An up-down counter counts numbers up or down based on a control signal. It helps track quantities that can increase or decrease.
Up-down counter with control in VHDL
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity up_down_counter is port( clk : in std_logic; reset : in std_logic; up_down : in std_logic; -- '1' for up, '0' for down count : out unsigned(3 downto 0) ); end up_down_counter; architecture Behavioral of up_down_counter is signal counter : unsigned(3 downto 0) := (others => '0'); begin process(clk, reset) begin if reset = '1' then counter <= (others => '0'); elsif rising_edge(clk) then if up_down = '1' then counter <= counter + 1; else counter <= counter - 1; end if; end if; end process; count <= counter; end Behavioral;
The up_down input controls counting direction: '1' means count up, '0' means count down.
Reset sets the counter back to zero immediately.
up_down <= '1'; -- counter will increase by 1 on each clock
up_down <= '0'; -- counter will decrease by 1 on each clock
reset <= '1'; -- counter resets to zero immediatelyThis program defines an up-down counter and a testbench that first resets the counter, then counts up 5 times, then counts down 3 times. The count value is reported on each clock.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity up_down_counter is port( clk : in std_logic; reset : in std_logic; up_down : in std_logic; count : out unsigned(3 downto 0) ); end up_down_counter; architecture Behavioral of up_down_counter is signal counter : unsigned(3 downto 0) := (others => '0'); begin process(clk, reset) begin if reset = '1' then counter <= (others => '0'); elsif rising_edge(clk) then if up_down = '1' then counter <= counter + 1; else counter <= counter - 1; end if; end if; end process; count <= counter; end Behavioral; -- Testbench to simulate counting up then down library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity tb_up_down_counter is end tb_up_down_counter; architecture test of tb_up_down_counter is signal clk : std_logic := '0'; signal reset : std_logic := '1'; signal up_down : std_logic := '1'; signal count : unsigned(3 downto 0); constant clk_period : time := 10 ns; begin uut: entity work.up_down_counter port map(clk => clk, reset => reset, up_down => up_down, count => count); clk_process : process begin while true loop clk <= '0'; wait for clk_period / 2; clk <= '1'; wait for clk_period / 2; end loop; end process; stim_proc: process begin wait for 20 ns; reset <= '0'; -- release reset -- count up for 5 clock cycles up_down <= '1'; wait for clk_period * 5; -- count down for 3 clock cycles up_down <= '0'; wait for clk_period * 3; wait; end process; -- Monitor output monitor_proc: process(clk) begin if rising_edge(clk) then report "Count = " & integer'image(to_integer(count)); end if; end process; end test;
Make sure the counter does not underflow below zero or overflow beyond its max value.
Use unsigned type for natural counting numbers.
Reset is asynchronous here, so it works immediately when set.
An up-down counter changes its count based on a control signal.
Use 'up_down' input to decide counting direction.
Reset clears the count to zero quickly.
Practice
Solution
Step 1: Understand the control signal meaning
In an up-down counter, the control signal '1' usually means count up.Step 2: Identify the counting behavior
When control is '1', the counter increments its value on each clock pulse.Final Answer:
It counts up by increasing the value on each clock pulse. -> Option DQuick Check:
Control '1' means count up [OK]
- Confusing control '1' with reset signal
- Thinking control '1' holds the value
- Mixing up count up and count down signals
count?Solution
Step 1: Identify correct type and range for 4-bit vector
std_logic_vector(3 downto 0) is the standard way to declare a 4-bit vector from bit 3 down to 0.Step 2: Check other options for errors
signal count : integer range 0 to 15; uses integer, not vector; signal count : bit_vector(4 downto 1); uses bit_vector with wrong range; signal count : std_logic_vector(0 to 3); uses ascending range which is less common and may cause confusion.Final Answer:
signal count : std_logic_vector(3 downto 0); -> Option BQuick Check:
4-bit vector uses std_logic_vector(3 downto 0) [OK]
- Using integer instead of vector for bit signals
- Incorrect range direction (0 to 3 instead of 3 downto 0)
- Using bit_vector instead of std_logic_vector
up_down and synchronous reset rst, what is the value of count after 3 clock cycles if rst = '0' and up_down = '0' initially?process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
count <= "000";
else
if up_down = '1' then
count <= count + 1;
else
count <= count - 1;
end if;
end if;
end if;
end process;Solution
Step 1: Understand initial conditions and counting direction
Reset is '0', so no reset occurs. up_down = '0' means count down. Initial count is unknown but assumed 0 at start.Step 2: Calculate count after each clock cycle
Cycle 1: count = 0 - 1 = 7 (since 3-bit unsigned wraps around)
Cycle 2: count = 7 - 1 = 6
Cycle 3: count = 6 - 1 = 5 (binary "101")Final Answer:
"101" -> Option CQuick Check:
Counting down 3 times from 0 wraps to 5 [OK]
- Assuming count starts at zero without reset
- Ignoring wrap-around behavior in unsigned counters
- Mixing up count up and count down logic
process(clk)
begin
if clk'event and clk = '1' then
if rst = '1' then
count <= (others => '0');
elsif up_down = '1' then
count <= count + 1;
else
count <= count - 1;
end if;
end if;
end process;Solution
Step 1: Check clock edge detection method
Using clk'event and clk = '1' is legal but less safe and less recommended than rising_edge(clk) in modern VHDL.Step 2: Identify best practice for clock edge
rising_edge(clk) is preferred for clarity and synthesis compatibility.Final Answer:
Using clk'event and clk = '1' instead of rising_edge(clk) -> Option AQuick Check:
Use rising_edge(clk) for clock detection [OK]
- Using clk'event instead of rising_edge(clk)
- Confusing synchronous and asynchronous reset
- Incorrect reset assignment syntax
dir where dir = '1' counts up and dir = '0' counts down. The counter should reset to "1000" on reset. Which code snippet correctly implements this behavior inside a synchronous process?process(clk)
begin
if rising_edge(clk) then
if rst = '1' then
count <= "1000";
else
if dir = '1' then
count <= count + 1;
else
count <= count - 1;
end if;
end if;
end if;
end process;Solution
Step 1: Check reset behavior
Reset sets count to "1000" as required, synchronously on rising clock edge.Step 2: Verify counting direction logic
dir='1' triggers count increment, dir='0' triggers decrement, matching the requirement.Step 3: Confirm synchronous reset usage
Reset is synchronous, which is acceptable and matches the problem statement.Final Answer:
Correct implementation for the described behavior. -> Option AQuick Check:
Synchronous reset and correct dir logic [OK]
- Using wrong reset value
- Reversing count up/down logic
- Confusing synchronous and asynchronous reset
Ready to prove it?
Pass the test and this pattern moves unknown
