I would like to delay an input signal by one complete clock cycle.
I have the code below which basically tries to change the signal at posedge of the clock.
However, the test bench shows that it doesn't always delay by 1 cycle.
In some cases, it changes at the same time the input signal changes.
Is there any way to solve this kind of problem?
module delay_one_cycle(
input clk,
input[3:0] original_signal,
output reg[3:0] delayed_signal
);
always @(posedge clk) begin
delayed_signal <= original_signal;
end
endmodule
module delay_one_cycle_tb();
reg clk;
reg[3:0] original_signal;
wire[3:0] delayed_signal;
delay_one_cycle doc_inst (clk, original_signal, delayed_signal);
// Initial setup
initial begin
clk = 0;
original_signal = 4'd9;
#5 original_signal = 4'd10;
#5 original_signal = 4'd11;
#4 original_signal = 4'd12;
#3 original_signal = 4'd13;
// finish the simulation
#5 $finish;
end
// clock
always begin
#1 clk = !clk;
end
endmodule
Here is the waveform: The waveform shows, for example, when input signal changes on the clock edge to 1010, output also changes at the same time.
the delayed_signal is not actually delayed to next cycle!
This question is quite similar to your question Why is my D Flip Flop not waiting for the positive edge of the clock?
You might want to try this convention to avoid race condition:
@(posedge clk);
Try to avoid setting input signals to your RTL code with blocking assignments. Use non-blocking assignment instead as what @Morten Zilmer suggests.
Your test bench should somehow look something like this:
module delay_one_cycle(
input clk,
input[3:0] original_signal,
output reg[3:0] delayed_signal
);
always @(posedge clk) begin
delayed_signal <= original_signal;
end
endmodule
module delay_one_cycle_tb();
reg clk;
reg[3:0] original_signal;
wire[3:0] delayed_signal;
delay_one_cycle doc_inst (clk, original_signal, delayed_signal);
// Initial setup
initial begin
original_signal <= 4'd9;
repeat (5) @(posedge clk);
original_signal <= 4'd10;
repeat (5) @(posedge clk);
original_signal <= 4'd11;
repeat (4) @(posedge clk);
original_signal <= 4'd12;
repeat (3) @(posedge clk);
original_signal <= 4'd13;
// finish the simulation
repeat (5) @(posedge clk);
$finish;
end
initial begin
clk = 0;
forever begin
#1 clk = !clk;
end
end
endmodule
Hope that helps.
Problem is a Verilog race condition .
So when changing original_signal
at the same time where a rising edge of clk
occurs, then original_signal
gets the new value before update based on clk
, and the result is that you don't get the desired delay.
Use non-blocking assign ( <=
) instead of blocking assign ( =
) in the always
blocks.
Also use the clk
to control change of stimuli data with repeat (5) @(posedge clk);
as @e19293001 points out, in order to get a robust test bench for a sequential design.
Read more about the issue in the above search, and in this Nonblocking Assignments in Verilog Synthesis .
This could be because the instant you change the input data, the output value changes, but according to your test bench, for example, changing the value to 4'd11 is happening at the negedge of the clock. So the always block in the original module is not entered till the posedge of the clock.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.