Search code examples
vhdldiagramwaveform

VHDL. Why doesn't my "rdy" value change to 1? Still confused


In my waveform diagram, I am wondering why my "rdy" value does not change to 1 after 400ns. And why does my "d" value not output anything after the first two outputs? I've tried finding the error for hours but to no avail. Please help, thank you in advance.

Here is my waveform diagram:

waveform diagram

And here is my main code.

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

entity GCD is
port(st , clk: in std_logic;        --clk temporarily taken out
     d1, d2 : in std_logic_vector(7 downto 0);
     dout : out std_logic_vector(7 downto 0);
     rdy : out std_logic);
end GCD;

architecture behav of GCD is
type state is (S0, S1, S2, S3, S4, S5, S6, S7);

--temporary clk
--signal clk : std_logic;

signal new_state : state;
signal eq : boolean;
signal eq1 : boolean;
signal lt : boolean;

begin
    --State transition
    process is
    variable curr_state : state:= S0;
    begin
        if clk = '1' then
        case curr_state is
            when S0 => 
                if st = '1' then curr_state := S1;
                end if;
            when S1 =>
                curr_state := S2;
            when S2 =>
                if eq and not lt then curr_state := S7;
                elsif lt and not eq then curr_state := S4;
                elsif not eq and not lt then curr_state := S3;
                end if;
            when S3 => 
                curr_state := S4;
            when S4 =>
                curr_state := S5;
           when S5 =>
                if eq1 = true then curr_state := S7;
                else curr_state := S6;
                end if;
            when S6 =>
                curr_state := S1;
            when S7 =>
                if st = '0' then curr_state := S0;
                end if;
        end case;
        new_state <= curr_state;
        end if;
        wait on clk;
    end process;


--Asserted Output Process
process is
variable M, N, dout_val, tmp: std_logic_vector(7 downto 0);
variable rdy_val : std_logic;
variable lt_val, eq_val, eq1_val : boolean;
begin
    rdy_val := '0';
    case new_state is

        when S0 =>
            M :=  d1;
            N := d2;
        when S1 =>
            if (to_integer(M) = to_integer(N)) then eq_val := true;
            elsif (to_integer(M) < to_integer(N)) then lt_val := true;
            end if;

        when S2 =>
        when S3 =>
            M := N;
            N := M;         
        when S4 =>
            if (to_integer(M) = 1) then eq1_val := true;
            end if;
        when S5 =>
        when S6 =>
            N := (N - M);
        when S7 =>
            rdy_val := '1';
            dout_val := M; 
    end case;
    dout <= dout_val;   
    rdy <= rdy_val;
    lt <= lt_val;
    eq <= eq_val;
    eq1 <= eq1_val;
    wait on new_state;
end process;
end behav;

And here is my testbench:

library IEEE;

use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;

use work.all;

entity test_GCD is
end test_GCD;

architecture testbench of test_GCD is
signal m, n ,d: std_logic_vector(7 downto 0);
signal clk, st, rdy : std_logic;

begin

    --Component Instantiation
    device : GCD
    port map( clk => clk, st => st, d1 => m, 
              d2 => n, dout => d, rdy => rdy);


    --Process to Generate Test Data
    process is
    begin
        st <= '0';
        wait for 10ns;
        m <= "00001001";    --9 , 15    
        n <= "00001111";
        wait for 10ns;
        st <= '1';
        wait until rdy = '1';
        wait for 10ns;

        st <= '0';
        wait for 10ns;
        m <= "00001111";    --15, 9
        n <= "00001001";        
        wait for 10ns;
        st <= '1';
        wait until rdy = '1';
        wait for 10ns;

        st <= '0';
        wait for 10ns;      --15 , 14
        m <= "00001111";
        n <= "00001110";
        wait for 10ns;
        st <= '1';
        wait until rdy = '1';
        wait for 10ns;

        st <= '0';
        wait for 10ns;
        m <= "00010010";    --18 , 36
        n <= "00100100";
        wait for 30ns;
        st <= '1';
        wait until rdy = '1';
        wait for 10ns;

        st <= '0';
        wait for 10ns;
        m <= "01011011";    --91 = 01011011 , 39 = 00100111
        n <= "00100111";
        wait for 10ns;
        st <= '1';
        --wait for 10ns;
        wait until rdy = '1';
        wait for 10ns;

        st <= '0';
        wait for 10ns;
        m <= "01111111";    --127, 127
        n <= "01111111";
        wait for 10ns;
        st <= '1';
        wait until rdy = '1';
        wait for 10ns;

        wait;
    end process;

process is
begin
    clk <= '0', '1' after 15ns;
    wait for 30ns;
end process;

end testbench;

Solution

  • You're the second one to ask a question here today with the same assignment.

    In the third st/rdy set you've upset the timing relation:

        st <= '0';
        wait for 10ns;
        m <= "00010010";    --18 , 36
        n <= "00100100";
        wait for 30ns;
        st <= '1';
        wait until rdy = '1';
        wait for 10ns;
    

    The previous two sets have wait for 10 ns. This one has 30 ns. What does that do?

    You're state machine in the unlabelled state transition process is missing the st <= '1', because it's not looking for it when it occurs, add waveforms down in GCD, try new_state.

    There's a fine balance between helping someone and doing their assignment for them.


    addendum

    Can you elaborate what you mean by I am missing the st<='1' in my state transition? I've declared st as a std_logic so I can't use the "<=" assignment for it. Do you mean I am missing the st<='1' in my testbench?

    The idea was to get you to look at the operation of the state machine spread across two unlabelled processes.

    Your state machine is operating on the positive clock edge even though your code is not written to be synthesis eligible. The process is driven by only one event, clk and the expression clk = '1'is evaluated in the first if statement condition.

    if you add new_state to your waveform dump (show it in the waveform display):

    test_GCD_ghw.png (you can open the image in a separate tab or window, it's a link to itself)

    (And notice the first GCD 'answer' is all U's. The second 'answer' also doesn't appear to be the greatest common denominator between 15 and 9, either.)

    You'll see your state machine quits transitioning, remaining stuck in S2 which evaluates ltand eqbut doesn't modify them in the Asserted Output Process (and you could use labels instead of comments, any statement can be labelled in VHDL).

    We look to the previous state S1, where eq_val and lt_val are assigned. They are dependent on M and N, which are assigned from d1 and d2 in S0.

    Back in S2 notice:

            when S2 =>
                if eq and not lt then 
                    curr_state := S7;
                elsif lt and not eq then 
                    curr_state := S4;
                elsif not eq and not lt then 
                    curr_state := S3;
                end if;
    

    And if you look at eq and lt in the above waveform you see they are both true. How can that be? There is to transition condition for that, you stick in S2.

    So how can both conditions be true at the same time?

        when S1 =>
            if (to_integer(M) = to_integer(N)) then 
                eq_val := true;
            elsif (to_integer(M) < to_integer(N)) then 
                lt_val := true;
            end if;
    

    You are only assigning one of them.

    However, the other one remains in it's previous state, latched by new_state.

    As a short term demonstration I assigned eq_val and lt_val both false right before they are evaluated. That will leave at most only one true.

    Unfortunately that reveals another flaw in your design:

    test_GCD_ghw_only_one_lt_eq.png

    And that's not the subject of your question.

    You appear to use a Euclid (GCD) algorithm shown in the flow chart (figure 1) in the PDF found in the link. The Boolean types appears to be an assignment requirement (the other student used them as well). The resulting VHDL expresses this algorithm with at least one more error.

    You use N as an accumulator in finding the GCD, and you also change the contents of M. N has three sources, d2, the result of N-M in S6 and swappingMandNinS3(which has the effect of assigningNtoM, andN` to itself, variable assignment is immediate). M and N should be signals, or you need an intermediary value to swap through. (They should be signals).

    You can use your waveform display to troubleshoot your design. You should also be aware when you are inferring latches, which occur when you have conditional assignments without the equivalent of an 'else'.

    The open source tools I used looking at your design (ghdl and gtkwave) don't capture variables in waveform dumps. I'd suspect DesignWorks 5 doesn't either (and could be wrong). The impact of this is you can't see what the data is doing during the simulation. Your design is small enough you could have used signals throughout without impacting simulation time significantly. Assigning to eq and lt directly in S1 would require else assignments (false). If you're required to use variables for the assignment you can assign them to signals so they are visible, should DesignWorks 5 not display variables. Once you're done you can remove the signals.

    The answer to Why doesn't my “rdy” value change to 1? is that you have inferred latches creating a case you don't detect for branching out of S2.

    Once you straighten out the M and N swap in S3 it looks like it may have a good chance or working (there could be another gotcha or two in there).

    And when you use tmp to hold the value of M (not using signals):

            when S3 =>
                tmp := M;
                M := N;
                N := tmp;      
    

    You start getting the right answers:

    test_GCD_ghw_using_tmp.png

    Without seeing the handout you were given for your project I'd anticipate you worked from pseudo code like found in the linked PDF's figure 1. It may have been written in the anticipation of the use of signals.