2
\$\begingroup\$

I am trying to simulate a D flip-flop using VHDL code which I compile and run using GHDL and later I ploting the waveform using GTKwave.

The problem is that my teacher told me that, when using D flip-flops, if the clock and data signal rises at the same time, the flip-flop state does not update till the next rising edge of the clock. But when I simulate that behavioral on a test bench, I get this:

enter image description here

Which seems to work perfect, except for the last D signal rising, where Q should update to HIGH after 10 nanoseconds. I don't know where the problem is, and it may be due to bad coding so I give you my code if it can help solve the problem.

D flip-flop module:

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity d_flip_flop is
    port (
        clk:    in  STD_LOGIC;
        d:      in  STD_LOGIC;
        reset:  in  STD_LOGIC;
        q:      out STD_LOGIC
    );
end entity;

architecture asynchronous of d_flip_flop is
begin
    process (clk, reset) begin
        if reset = '1' then
            q <= '0';
        elsif clk'event and clk = '1' then
            q <= d;
        end if;
    end process;
end architecture;

D flip-flop test bench:

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity d_flip_flop_tb is
end entity;

architecture testbench of d_flip_flop_tb is
    component d_flip_flop
        port (
            clk:    in  STD_LOGIC;
            d:      in  STD_LOGIC;
            reset:  in  STD_LOGIC;
            q:      out STD_LOGIC
        );
    end component;

    signal clk, d, reset, q: STD_LOGIC;
begin
    uut: d_flip_flop port map (clk, d, reset, q);

    process begin
        clk <= '0'; wait for 5 ns;
        clk <= '1'; wait for 5 ns;
    end process;

    process begin
        reset <= '1'; d <= '1'; wait for 12500 ps;
        reset <= '0';           wait for 10 ns;
        d <= '0';               wait for 12500 ps;
        d <= '1';               wait for 20 ns;
        assert false report "End of simulation" severity failure;
        wait;
    end process;
end architecture;
\$\endgroup\$
  • \$\begingroup\$ what exactly, that is EXACTLY, happens at 35nS? Do the clk and D rise at the same time? Does 5ns+5nS+5nS ... equal the same time as 12500pS+10nS+12500pS? Or are there rounding errors when the simulator turns those into IEE754 doubles internally and adds them? So question, does the d in fact rise first, by a tiny fraction? In real life, clk and data changing at the same time is undefined, could be 0, could be 1, could be metastable. \$\endgroup\$ – Neil_UK Aug 1 '17 at 18:24
  • \$\begingroup\$ Your teacher is oversimplifying, and nothing truly happens simultaneously in a simulator anyway. In reality, this is behavior that you should stay away from in your designs. In general, a string of flip-flops driven by a common clock will behave as a shift register in both real life and in simulation. \$\endgroup\$ – Dave Tweed Aug 1 '17 at 19:23
  • \$\begingroup\$ Learn the delta cycle model of VHDL and you'll see what's wrong. \$\endgroup\$ – Brian Drummond Aug 1 '17 at 21:37
3
\$\begingroup\$

The problem is that my teacher told me that, when using D flip-flops, if the clock and data signal rises at the same time, the flip-flop state does not update till the next rising edge of the clock.

This is a highly idealized description, and not even a very useful one.

A much better model for the behavior, which is still quite simple, is that

If the input is stable during the clock edge, for a "setup time" beforehand and a "hold time" after, that same stable level will emerge from the output after a "delay time".

And no guarantees are made if, as in your simulation, the input is changing within the setup-and-hold window.

In actual circuits, clock distribution is designed to be faster than signal distribution, so that changes happen after the clock edge. And the hold requirement in modern logic is very nearly zero. In such cases things work.

But if the delays in the logic producing the flip-flop's input add up to nearly a whole clock cycle, you can get into trouble with setup time violations.

And if you are doing your own PCB layout and not careful to make the clock the shortest trace, then signals synchronized to the clock in one part of the circuit can outrace it and be seen to transition in another part before the clock edge, which also violates the setup&hold requirement.

\$\endgroup\$
0
\$\begingroup\$

The problem is with how you're driving d in your testbench.

Although in hardware, the logic would execute simultaneously, the simulator has to execute one of the assignments before the other as a delta time step. Since the process in your testbench is not sensitive to clk, the simulation has trouble deciding if clk<='1' or d<='1' happens first.

My preferred solution would be to clock the process in the testbench rather than rely on wait for statements, but if you are looking for a one line solution, add wait until clk'event and clk='1'; between the d<='0' line and the d<='1' line. This will let the simulator know that the clock event comes before the transition d<='1'.

\$\endgroup\$
0
\$\begingroup\$

For this simulation you assign d to HIGH at the same time clock rises.

Simulation takes that value and assigns it to d. At the same time it goes into your elseif pathway because the clock is high and it assigns the value of D.

\$\endgroup\$
0
\$\begingroup\$

... and it may be due to bad coding so I give you my code if it can help solve the problem.

Yes, it is bad coding, bad testbench coding.

You are trying to set up edges to be simultaneous, which is a bad idea anyway. In real life, edges that are simulataneous (within the definition of setup and hold times) are dangerous. They could arrive in either order, or they could make the output metastable, which is even worse than not knowing whether the output is supposed to be 0 or 1.

So aside from the desirability of producing simultaneous changes, the way you have done it is not the way to do it. You have two different processes, one waiting multiples of 5nS, the other waiting 12.5nS, then 10nS, then 12.5nS, in the hope that they will line up at 35nS.

A well known way to get things wrong when computing is to assume that floating point numbers are exact. For instance, 1.0 + 0.1 - 1.1 is not 0.0, not in IEE754 doubles anyway. It's likely that your two different ways of getting to 35nS are different, at least at the few LSBs level.

If you still want to test simultaneous changes, check your VDHL simulator documentation to see whether if you generate them in the same process at the same time, it will implement them simultaneously, or whether they will still be ordered.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.