1

I'm trying to implement the nand2tetris project in verilog and am hitting a wall using icarus verilog. In the book they implement the DFF as so, q(t) = d(t-1). The output at the current time is the input at the previous posedge clk. Here is the DFF I realized.

module Dff (
    output reg q,
    input data, clk
);

    reg p;
    reg o;

    always @(posedge clk) begin
        o <= data;
        q <= p;
    end

    always @(negedge clk) begin
        p <= o;
    end

endmodule

This DFF seems to work just fine when I test it directly. But when I reused it to create a Bit (a memory cell), it gets crazy. Interestingly, the craziness is different using Icarus Verilog or EDAPlayground (which uses VCS).

module Mux (out, a, b, sel);
    input a, b;
    input sel;
    output reg out;

    assign out = ~sel ? a : b;
endmodule

module Bit (
    output out,
    input data, load, clk
);

    Mux m0(in, out, data, load);
    Dff d0(out, in, clk);
endmodule

Icarus Verilog output

 data | load | clk | out
------+------+-----+-----
    0 |    1 |   1 |   x
    0 |    1 |   0 |   x
    1 |    1 |   1 |   x
    1 |    1 |   0 |   x
    0 |    1 |   1 |   1
    0 |    1 |   0 |   1
    0 |    0 |   1 |   0
    0 |    0 |   0 |   0
    1 |    1 |   1 |   0
    1 |    1 |   0 |   0
    0 |    0 |   1 |   0   # !?!?!
    0 |    0 |   0 |   0   # it should be 1 here.

EDAPlayground output

 data | load | clk | out
------+------+-----+-----
    0 |    1 |   1 |   x
    0 |    1 |   0 |   x
    1 |    1 |   1 |   x
    1 |    1 |   0 |   x
    0 |    1 |   1 |   1
    0 |    1 |   0 |   1
    0 |    0 |   1 |   0
    0 |    0 |   0 |   0
    1 |    1 |   1 |   1  # !?!?!
    1 |    1 |   0 |   1  # it should be 0 here.
    0 |    0 |   1 |   1
    0 |    0 |   0 |   1

The code is testable on EDAPlayground.

5
  • I'd say your DFF is not working correctly, as it uses three D flip-flops when synthesised. Commented Aug 17, 2015 at 15:16
  • 2
    I dont know if I can properly explain exactly what is happening in both cases but Ill boil it down here: because you are not using non-blocking assignment for your initial block (ie load <= 0, not load = 0, treat it like its coming out of another register somewhere), simulation order of the various blocks in your design (the always in the DFF, the assign in the Mux and the always clocking block and initial stimulus block) matters. Ie, when the updates from the initial block happen are not happening when you want them to due to the blocking assignment. Commented Aug 17, 2015 at 16:20
  • DFF is usually sensitive to one edge of the clock, either posedge or negedge. Why are you using both? Commented Aug 17, 2015 at 18:31
  • 1
    Your DFF almost looks like a latches. "q(t) = d(t-1)" is simply always @(posedge clk) begin q <= data; end. As Unn pointed out, your data and load stimuli should be non-blocking so it doesn't cause a race condition with the clock. Alternatively, add a little delay so the simultaneous. Point being the new values for the stimuli must be updated after the clock. Commented Aug 17, 2015 at 18:37
  • To summarize: my test cases are badly designed hence the code is crap and the behavior hardly predictable. Big TA! Commented Aug 17, 2015 at 19:25

1 Answer 1

2

Thanks to Uun and Greg, here is how I fixed the issue. The code is on EDA playground

A DFF can be simpler.

module Dff (
    output reg q,
    input data, clk
);
    always @(posedge clk) begin
        q <= data;
    end
endmodule

Then the tests are the culprits. Blocking assignments are causing confusion. A simple way to fix that is to change all the = by <= like that:

module Bit_tb;
    reg clk = 0;
    reg data = 0;
    reg load = 1;
    wire out;

    initial begin
        #2
        data <= 1;

        #2
        load <= 0;  // load = 0; /!\ would be blocking before
        data <= 0;  // data = 0; doing this line. /!\

        #2
        $finish;
    end
endmodule
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.