mahmood
mahmood

Reputation: 24705

Implementing a counter in VHDL

The following code implements a two digit counter and displays the output on seven segments. As can be seen, in each clock cycle, the value has to be changed but the simulation results doesn't show such thing. To reduce the code size, I only put 0 and 1 in the seven segment driver.

library ieee;
use ieee.std_logic_1164.all;

entity two_digit_counter is
    port( clk: in std_logic;
          x, y: out std_logic_vector( 6 downto 0 ));
end;

architecture x of two_digit_counter is
begin
    process( clk )
        variable d1 : integer range 0 to 9 := 0;
        variable d2 : integer range 0 to 9 := 0;
    begin
        if (clk'event and clk = '1') then
            if d1 = 9 then
                d1 := 0;
                d2 := d2 + 1;
            elsif d2 = 9 then
                d2 := 0;
                d1 := 0;
            else
                d1 := d1 + 1;
            end if;
        end if;

        case d1 is
            when 0   =>    x <= "1111110";  -- 7E
            when 1   =>    x <= "0110000";  -- 30
        end case;
        case d2 is
            when 0   =>    x <= "1111110";
            when 1   =>    x <= "0110000";
        end case;
    end process;
end;

enter image description here

Upvotes: 0

Views: 6916

Answers (3)

user1155120
user1155120

Reputation:

Unfortunately your d2 counter doesn't work properly besides the missing assignments to y:

d2_bottom_trace.png

d2 the bottom trace should hold each value for 10 counts of d1 (here shown as ten seconds. The if statements aren't comprehensive and should be changed. d1 is showing up incorrectly as well.

Fix that by nesting the two counter if statements:

    process (clk)
        variable d1 : integer range 0 to 9 := 0;
        variable d2 : integer range 0 to 9 := 0;
    begin
        if rising_edge(clk) then
            -- if d1 = 9 then
            --     d1 := 0;
            --     d2 := d2 + 1;
            -- elsif d2 = 9 then
            --     d2 := 0;
            --     d1 := 0;
            -- else
            --     d1 := d1 + 1;
            -- end if;
            if d1 = 9 then       -- nested if statements
                d1 := 0;
                if d2 = 9 then
                    d2 := 0;
                else
                    d2 := d2 + 1;
                end if;
            else
                d1 := d1 + 1;
            end if;
        end if; 
        case d1 is
            when 0   =>    x <= "1111110";  -- 7E
            when 1   =>    x <= "0110000";  -- 30
            when 2   =>    x <= "1101101";  -- 6D
            when 3   =>    x <= "1111001";  -- 79
            when 4   =>    x <= "0110011";  -- 33
            when 5   =>    x <= "1011011";  -- 5B
            when 6   =>    x <= "1011111";  -- 5F
            when 7   =>    x <= "1110000";  -- 70
            when 8   =>    x <= "1111111";  -- 7F
            when 9   =>    x <= "1111011";  -- 7B
        end case;
        case d2 is
            when 0   =>    y <= "1111110";   -- WAS assignment to x
            when 1   =>    y <= "0110000";   -- ""
            when 2   =>    y <= "1101101";
            when 3   =>    y <= "1111001";
            when 4   =>    y <= "0110011";
            when 5   =>    y <= "1011011";
            when 6   =>    y <= "1011111";
            when 7   =>    y <= "1110000";
            when 8   =>    y <= "1111111";
            when 9   =>    y <= "1111011";
        end case;
    end process;

And that produces:

two_digit_counter_tb_fixed.png

Your question's other answers could have pointed this out if your question had provided a Minimal, Complete and Verifiable example.

Upvotes: 1

travelboy
travelboy

Reputation: 2697

Did you really mean for case d2 to overwrite the value assigned to x by the case d1 statement? Or did you mean y?

If the logic that derives x and y from d1 and d2 is purely combinatorial, you can move it out of the process.

Upvotes: 0

Matthew
Matthew

Reputation: 13967

Don't you mean:

    case d2 is
        when 0   =>    y <= "1111110";
        when 1   =>    y <= "0110000";
    end case;
    --                 ^
    --                 |
    --        shouldn't this be y ?

Upvotes: 0

Related Questions