Verilog:如何将输入信号延迟一个时钟周期?
Verilog: How to delay an input signal by one clock cycle?
我想将输入信号延迟一个完整的时钟周期。
我有下面的代码,它基本上试图在时钟的位置改变信号。
但是,测试台显示它并不总是延迟1个周期。
在某些情况下,它会在输入信号变化的同时发生变化。
有什么办法可以解决这种问题吗?
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
波形如下:
波形显示,例如,当输入信号在时钟边沿变为 1010 时,输出也同时发生变化。
delayed_signal实际上并没有延迟到下一个周期!
所以当在clk
的上升沿发生的同时改变original_signal
时,original_signal
会根据clk
获取更新前的新值,并且结果是您没有获得所需的延迟。
在 always
个块中使用非阻塞分配 (<=
) 而不是阻塞分配 (=
)。
如@e19293001 指出的那样,还使用 clk
通过 repeat (5) @(posedge clk);
控制刺激数据的变化,以便为顺序设计获得稳健的测试平台。
中阅读有关该问题的更多信息
这个问题和你的问题很相似Why is my D Flip Flop not waiting for the positive edge of the clock?
您可能想尝试这个约定来避免竞争条件:
@(posedge clk);
尽量避免将输入信号设置为具有阻塞分配的 RTL 代码。按照@Morten Zilmer 的建议使用非阻塞赋值。
您的测试台应该看起来像这样:
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
希望对您有所帮助。
这可能是因为当您更改输入数据时,输出值也会发生变化,但是根据您的测试台,例如,将值更改为 4'd11 是在时钟的边缘发生的。所以原来模块中的always块直到时钟的posedge才进入。
我想将输入信号延迟一个完整的时钟周期。
我有下面的代码,它基本上试图在时钟的位置改变信号。
但是,测试台显示它并不总是延迟1个周期。
在某些情况下,它会在输入信号变化的同时发生变化。
有什么办法可以解决这种问题吗?
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
波形如下:
delayed_signal实际上并没有延迟到下一个周期!
所以当在clk
的上升沿发生的同时改变original_signal
时,original_signal
会根据clk
获取更新前的新值,并且结果是您没有获得所需的延迟。
在 always
个块中使用非阻塞分配 (<=
) 而不是阻塞分配 (=
)。
如@e19293001 指出的那样,还使用 clk
通过 repeat (5) @(posedge clk);
控制刺激数据的变化,以便为顺序设计获得稳健的测试平台。
这个问题和你的问题很相似Why is my D Flip Flop not waiting for the positive edge of the clock?
您可能想尝试这个约定来避免竞争条件:
@(posedge clk);
尽量避免将输入信号设置为具有阻塞分配的 RTL 代码。按照@Morten Zilmer 的建议使用非阻塞赋值。
您的测试台应该看起来像这样:
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
希望对您有所帮助。
这可能是因为当您更改输入数据时,输出值也会发生变化,但是根据您的测试台,例如,将值更改为 4'd11 是在时钟的边缘发生的。所以原来模块中的always块直到时钟的posedge才进入。