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;