Reputation: 2901
As I have known, D flipflop samples its input value at every positive edge of the clock.
Thus, it will produce a 1 cycle delay. Right?
But why does my D flip flop does not produce a 1 cycle delay?
module flipflop(
input clk,
input rstn,
input [7:0] i_data,
output reg [7:0] o_data
);
always @(posedge clk) begin
if (~rstn) begin
o_data <= 0;
end
else begin
o_data <= i_data;
end
end
endmodule
module test;
reg clk;
reg [7:0] i_data;
reg rstn;
wire [7:0] o_data;
initial begin
clk = 0;
rstn = 1;
i_data = 0;
#20;
rstn = 0;
#30;
rstn = 1;
#20;
i_data = 8'hFA;
#20;
i_data = 8'hF0;
#20
i_data = 8'hF1;
#20
#10 $finish;
end
always #10 clk = !clk;
flipflop flipflop(
.clk (clk),
.rstn(rstn),
.i_data(i_data),
.o_data(o_data)
);
initial begin
$dumpfile("flipflop.vcd");
$dumpvars();
end
endmodule
My D flip flop functions like a combinational circuit here.
Upvotes: 8
Views: 4512
Reputation: 6644
You've run up against Verilog simulator event scheduling subtleties! Changing the data assignments to use nonblocking assignments is probably the easiest fix.
#20;
i_data <= 8'hFA;
#20;
i_data <= 8'hF0;
#20
i_data <= 8'hF1;
#20
What was happening in your original version is that the clock and the input data were scheduled to happen at the same time. Since the simulator can only do one thing at a time, it has to decide if it will change the clock or the data first. It changed the data first, so when the clock edge comes along, the input data has already changed to the next value so it looks like the data is slipping through the FF.
Nonblocking assignments (<=
) are scheduled to happen after all the blocking assignments (=
) have been done. So making the data assignments nonblocking ensures that they happen after the blocking-assigned clock edges.
Another way to rewrite things to work would be:
initial begin
@(posedge clk) i_data = 8'hFA;
@(posedge clk) i_data = 8'hF0;
@(posedge clk) i_data = 8'hF1;
end
Upvotes: 10
Reputation:
The simulator is probably doing something like this:
initial begin
clk = 0;
rstn = 1;
i_data = 0;
#10;
clk = !clk;
#10;
rstn = 0;
clk = !clk;
#10;
clk = !clk;
#10;
clk = !clk;
#10;
rstn = 1;
clk = !clk;
#10;
clk = !clk;
#10
i_data = 8'hFA; //Input updated
clk = !clk; //Clock event
//o_data assigned here
#10;
clk = !clk;
#10;
i_data = 8'hF0;
clk = !clk;
#20
i_data = 8'hF1;
#20
#10 $finish;
end
Since the clock event is occurring last in each time step from your testbench, it looks like the flop is being assigned immediately. You likely want your testbench to be entirely slaved off the clock so Marty's suggestion of using @(posedge...) will achieve this. You could also simply delay your assignments once at the very beginning:
initial begin
clk = 0;
#1;
rstn = 1;
i_data = 0;
#20;
rstn = 0;
#30;
rstn = 1;
#20;
i_data = 8'hFA;
#20;
i_data = 8'hF0;
#20
i_data = 8'hF1;
#20
#10 $finish;
end
Upvotes: 6