Up-down counter

This up-down counter includes the following control inputs:

en: enable counting

sclr: synchronous clear

load: load counter with data present at data_in

up_ndown: if the counter is enabled, it will count up if this input is asserted or down if it is de-asserted.

  1. library ieee;
  2. use ieee.std_logic_1164.all;
  3. use ieee.numeric_std.all;
  4.  
  5. entity counter_ud is
  6. generic (
  7. DATA_W : natural := 32
  8. );
  9. port (
  10. clk : in std_logic;
  11. rst : in std_logic;
  12.  
  13. -- inputs
  14. data_in : in std_logic_vector (DATA_W - 1 downto 0);
  15. load : in std_logic;
  16. sclr : in std_logic;
  17. en : in std_logic;
  18. up_ndown : in std_logic;
  19.  
  20. -- outputs
  21. data_out : out std_logic_vector (DATA_W - 1 downto 0)
  22. );
  23. end counter_ud;
  24. architecture rtl of counter_ud is
  25. signal counter_reg : unsigned (DATA_W - 1 downto 0);
  26.  
  27. begin
  28. counter_pr : process (clk, rst)
  29. begin
  30. if (rst = '1') then
  31. counter_reg <= (others => '0');
  32. elsif (rising_edge(clk)) then
  33. if (sclr = '1') then -- synchronous clear
  34. counter_reg <= (others => '0');
  35. elsif (load = '1') then -- load counter
  36. counter_reg <= unsigned(data_in);
  37. elsif (en = '1') then -- is counting enabled?
  38. if (up_ndown = '1') then -- count up
  39. counter_reg <= counter_reg + 1;
  40. else -- count down
  41. counter_reg <= counter_reg - 1;
  42. end if;
  43. end if;
  44. end if;
  45. end process;
  46.  
  47. data_out <= std_logic_vector(counter_reg);
  48.  
  49. end rtl;

In the following figure, the counter is loaded (cursor 1),  counts up and wraps-around (cursor 2), counting is disabled for one clock (cursor 3), then it is cleared synchronously (cursor 4).

Cursor 5 marks the moment where the counter starts counting down, and it wraps around at cursor 6.

The waveforms are repeated below without cursors for clarity. Note the usage of ‘analog’ display of Modelsim which helps visualizing the counter values (last data_out signal on waveform).

wfm1

wfm2

The source files for the up-down counter and its testbench are available at Gihtub.


Proposed exercises:

  1. Add a ‘zero’ output. Each time the counter has a zero value, this line is asserted. Hint: The logic for this output can be combinatorial (asynchronous).
  2. Same as 1, but this time the ‘zero’ output must be synchronous. Hint: You will have to check the value one clock before the clock reaches zero, taking also into account wether the counter is counting up or down.
  3. Add a ‘in range’ output. The output will be set if the counter value is ‘min’. Min and max can be constants or generic parameters.