I have this code which is a bidirectional counter that loops around.
I now want to add an input (maybe from switches or something), which controls the maximum value of the counter, for example if the max value from the input is "0111" the counter will count up to 0111 and then loop back around to 0000, and if the counter is counting down to 0000 it will loop back to 0111. I'm getting a bit confused on how/where I should do this because I've used nested ifs to implement an enable and reset input.
Here is the code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity UPDOWN_COUNTER is
Port ( clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down
enable: in std_logic; -- enable
max: in std_logic_vector(3 downto 0); -- max value counter
counter: out std_logic_vector(3 downto 0) -- output 4-bit counter
);
end UPDOWN_COUNTER;
architecture Behavioral of UPDOWN_COUNTER is
signal counter_updown: std_logic_vector(3 downto 0);
begin
process(clk,reset,enable,max)
begin
if(enable ='1') then
if(rising_edge(clk)) then
if(reset='1') then
counter_updown <= x"0";
elsif(up_down='1') then
counter_updown <= counter_updown - x"1"; -- count down
else
counter_updown <= counter_updown + x"1"; -- count up
end if;
end if;
end if;
end process;
counter <= counter_updown;
end Behavioral;
Here is the test bench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity tb_counters is
end tb_counters;
architecture Behavioral of tb_counters is
component UPDOWN_COUNTER
Port ( clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down input
enable: in std_logic; -- enable input
max: in std_logic_vector(3 downto 0); -- max value counter
counter: out std_logic_vector(3 downto 0) -- output 4-bit counter
);
end component;
signal reset,clk,enable,up_down: std_logic;
signal max,counter:std_logic_vector(3 downto 0);
begin
dut: UPDOWN_COUNTER port map (clk => clk, reset=>reset,enable => enable, up_down => up_down, max => max,counter => counter);
-- Clock
clock_process :process
begin
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 10 ns;
end process;
stim_proc: process
begin
max <= "1000"; -- Test value for Counter max value
enable <= '1';
reset <= '1';
up_down <= '0';
wait for 20 ns;
reset <= '0';
wait for 300 ns;
up_down <= '1';
--
wait for 50 ns;
enable <= '0';
wait for 50 ns;
enable <= '1';
wait;
end process;
end Behavioral;
You've specified a synchronous reset. There's at least one synthesis issue, where enable is inferred to gate the clock. The numeric package has been switched to ieee.numeric_std in the following (the example can be modified for the non-standard Synopsys numeric package):
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity updown_counter is
port (
clk: in std_logic;
reset: in std_logic;
up_down: in std_logic;
enable: in std_logic;
max: in std_logic_vector(3 downto 0);
counter: out std_logic_vector(3 downto 0)
);
end entity updown_counter;
architecture behavioral of updown_counter is
signal counter_updown: unsigned(3 downto 0);
begin
process (clk) -- other signals evaluated inside clock edge
begin
if rising_edge(clk) then
if enable = '1' then -- don't gate the clock
if reset = '1' then
counter_updown <= (others => '0');
elsif up_down = '1' then -- down
if counter_updown = 0 then
counter_updown <= unsigned(max);
else
counter_updown <= counter_updown - 1;
end if;
else -- count up
if counter_updown = unsigned(max) then
counter_updown <= (others => '0');
else
counter_updown <= counter_updown + 1;
end if;
end if;
end if;
end if;
end process;
counter <= std_logic_vector(counter_updown);
end architecture behavioral;
And that gives:
with your testbench.
This is the similar to @user1155120's answer (which I recommend you accept as the answer), but I've used an asynchronous reset instead. Also added a generic to specify the number bits in the counter.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity UpdownCounter is
generic
(
COUNTER_BITS: natural := 4
);
port
(
clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down input
enable: in std_logic; -- enable input
max: in std_logic_vector(COUNTER_BITS - 1 downto 0); -- max value counter
counter: out std_logic_vector(COUNTER_BITS - 1 downto 0) -- output N-bit counter
);
end UpdownCounter;
architecture V1 of UpdownCounter is
signal counter_updown: unsigned(COUNTER_BITS - 1 downto 0);
begin
process(clk, reset)
begin
if reset then
-- Do asynchronous reset.
counter_updown <= (others => '0');
elsif rising_edge(clk) then
-- Do synchronous stuff.
if enable then
if up_down then
-- Count down to zero cyclically.
if counter_updown = 0 then
counter_updown <= unsigned(max);
else
counter_updown <= counter_updown - 1;
end if;
else
-- Count up to max cyclically.
if counter_updown = unsigned(max) then
counter_updown <= (others => '0');
else
counter_updown <= counter_updown + 1;
end if;
end if;
end if;
end if;
end process;
counter <= std_logic_vector(counter_updown);
end V1;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity UpdownCounter_TB is
end UpdownCounter_TB;
architecture V1 of UpdownCounter_TB is
component UpdownCounter
generic
(
COUNTER_BITS: natural := 4
);
port
(
clk: in std_logic; -- clock input
reset: in std_logic; -- reset input
up_down: in std_logic; -- up or down input
enable: in std_logic; -- enable input
max: in std_logic_vector(COUNTER_BITS - 1 downto 0); -- max value counter
counter: out std_logic_vector(COUNTER_BITS - 1 downto 0) -- output 4-bit counter
);
end component;
signal reset, clk, enable, up_down: std_logic;
signal max, counter: std_logic_vector(3 downto 0);
signal halt_clk: boolean := false;
begin
DUT: UpdownCounter
generic map
(
COUNTER_BITS => 4
)
port map
(
clk => clk,
reset => reset,
enable => enable,
up_down => up_down,
max => max,
counter => counter
);
-- Clock
ClockProocess :process
begin
while not halt_clk loop
clk <= '0';
wait for 10 ns;
clk <= '1';
wait for 10 ns;
end loop;
wait;
end process;
StimulusProcess: process
begin
max <= "1000"; -- Test value for Counter max value
enable <= '1';
reset <= '1';
up_down <= '0';
wait for 20 ns;
reset <= '0';
wait for 300 ns;
up_down <= '1';
--
wait for 50 ns;
enable <= '0';
wait for 50 ns;
enable <= '1';
wait for 1000 ns;
halt_clk <= true;
wait;
end process;
end V1;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.