1 ------------------------------------------------------------------------------- 2 -- Filename: inc_dec_addn_cntr.vhd 3 -- 4 -- Description: This counter can increment, decrement or skip ahead 5 -- by an arbitrary amount. 6 -- 7 -- If Reset is active, the value Cnt synchronously resets 8 -- to all ones. (This reset value, different than the 9 -- customary reset value of zero, caters to the original 10 -- application of inc_dec_addn_cntr as the address 11 -- counter for fifo_rbu) 12 -- 13 -- Otherwise, on each Clk, one is added to Cnt if Incr is 14 -- asserted and one is subtracted if Decr is asserted. 15 -- (If both are asserted, then there is no change to Cnt.) 16 -- 17 -- If Decr is not asserted, then the input value, 18 -- Nm_to_add, is added. (Simultaneous assertion of Incr 19 -- would add one more.) If Decr is asserted, then 20 -- N_to_add, is ignored, i.e., it is possible to decrement 21 -- by one or add N, but not both, and Decr overrides. 22 -- 23 -- The value that Cnt will take on at the next clock 24 -- is available as Cnt_p1. 25 -- 26 -- 27 -- VHDL-Standard: VHDL'93 28 ------------------------------------------------------------------------------- 29 library IEEE; 30 use IEEE.STD_LOGIC_1164.all; 31 32 -- Uncomment the following library declaration if using 33 -- arithmetic functions with Signed or Unsigned values 34 use IEEE.NUMERIC_STD.all; 35 36 -- Uncomment the following library declaration if instantiating 37 -- any Xilinx primitives in this code. 38 --library UNISIM; 39 --use UNISIM.VComponents.all; 40 41 entity inc_dec_addn_cntr is 42 generic ( 43 C_SIZE : natural := 8); 44 port ( 45 Clk : in std_logic; 46 Reset : in std_logic; -- Note: the counter resets to all ones! 47 Incr : in std_logic; 48 Decr : in std_logic; 49 N_to_add : in std_logic_vector(C_SIZE-1 downto 0); 50 Cnt : out std_logic_vector(C_SIZE-1 downto 0); 51 Cnt_p1 : out std_logic_vector(C_SIZE-1 downto 0) 52 ); 53 end inc_dec_addn_cntr; 54 55 architecture Behavioral of inc_dec_addn_cntr is 56 signal cnt_r : std_logic_vector(Cnt'range); 57 signal cnt_p1_r : std_logic_vector(Cnt'range); 58 59 begin 60 Cnt <= cnt_r; 61 Cnt_p1 <= cnt_p1_r; 62 63 CNT_I_P1_PROC : process( cnt_r, N_to_add, Decr, Incr) is 64 65 function qual_n_to_add(N_to_add : std_logic_vector; Decr : std_logic) return UNSIGNED is 66 variable r : UNSIGNED(N_to_add'range); 67 begin 68 for i in r'range loop 69 r(i) := N_to_add(i) or Decr; -- "1111...111" when Decr = '1' 70 end loop; 71 return r; 72 end; 73 74 function to_singleton_unsigned(s : std_logic) return unsigned is 75 variable r : unsigned(0 to 0) := (others => s); 76 begin 77 return r; 78 end; 79 80 begin 81 cnt_p1_r <= std_logic_vector( UNSIGNED(cnt_r) + qual_n_to_add(N_to_add, Decr) + to_singleton_unsigned(Incr) ); 82 end process; 83 84 CNT_I_PROC : process(Clk) is 85 begin 86 if Clk'event and Clk = '1' then 87 if Reset = '1' then 88 cnt_r <= (others => '1'); -- "11111...111" --> "00000...000" when Incr='1' 89 else 90 cnt_r <= cnt_p1_r; 91 end if; 92 end if; 93 end process; 94 95 96 end Behavioral;