Reputation: 4363
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
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.
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.
Upvotes: 1
Views: 3059
Reputation: 4363
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
Upvotes: 2