ameer khan
ameer khan

Reputation: 33

VHDL up/down counter error counting

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

Answers (1)

JHBonarius
JHBonarius

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

Related Questions