Reputation: 33
Im trying to make a counter which counts up to 3 then counts down to 0 etc.. example: 0 1 2 3 2 1 0 1 2 3 2 1 0...
What I did:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Counter is
port(
Clock: in std_logic;
Reset: in std_logic;
Output: out std_logic_vector(0 to 1 ));
end Counter;
architecture Behavioral of Counter is
signal temp: std_logic_vector(0 to 1);
signal down: std_logic := '0';
begin process(Clock,Reset)
begin
if Reset='0' then
temp <= "00";
down<= '0';
elsif(rising_edge(Clock)) then
if temp="11" then
down<= '1';
elsif temp="00" then
down<='0';
end if;
if down='0' then
temp <= temp +1;
else
temp <= temp-1;
end if;
end if;
end process;
Output <= temp;
end Behavioral;
Somehow the output is going from 3 to 0 without showing the middle numbers.. What is wrong?
Upvotes: 3
Views: 634
Reputation: 11291
You are not looking at all the signals: look at down
to see what happens. Because you are using clocked/synchronous logic, down
is changed in the clock cycle where temp
is detected 3, so it will have effect one clock cycle later. I.e. when temp
is 3, down
will still be 0, thus (3+1) mod 4 = 0.
One possible solution is to be one step ahead of this: Change down
one clock cycle earlier... when temp
=2.
One other problem is that you are combining the non-standardized packages STD_LOGIC_ARITH
and STD_LOGIC_UNSIGNED
with logic arrays in reverse direction. That can give unpredictable results. Please use standardized packages. Example:
library ieee;
use ieee.STD_LOGIC_1164.ALL;
entity counter is
port(
clk : in std_logic;
rst_n : in std_logic;
output : out std_logic_vector(1 downto 0)
);
end entity;
architecture behavioral of counter is
use ieee.numeric_std.ALL;
signal temp : unsigned(output'range) := (others => '0');
signal down : std_logic := '0';
begin
process(clk, rst_n)
begin
if rst_n = '0' then -- why asynchronous reset??
temp <= (others => '0');
down <= '0';
elsif(rising_edge(clk)) then
if temp = 2 then
down <= '1';
elsif temp = 1 then
down <= '0';
end if;
if down = '0' then
temp <= temp + 1;
else
temp <= temp - 1;
end if;
end if;
end process;
output <= std_logic_vector(temp);
end architecture;
-
entity counter_tb is end entity;
library ieee;
use IEEE.STD_LOGIC_1164.ALL;
architecture behavioral of counter_tb is
signal clk : std_logic;
signal rst_n : std_logic;
signal output : std_logic_vector(1 downto 0);
begin
DUT: entity work.Counter
port map(
clk => clk,
rst_n => rst_n,
output => output
);
rst_n <= '1';
process
begin
clk <= '0', '1' after 1 ns;
wait for 2 ns;
end process;
end architecture;
Next time please add your test bench to form a complete set... and please don't use 3-space indentation :( use 4, like everybody does)
Upvotes: 3