我是一名刚接触 verilog 和系统 verilog 的工程师。这是我第一次在这个网站上提问。我试图制作一个倾向于实现内存的模块。然而,该模块的行为并不是我所期望的。经过调试,我发现verilog和系统verilog中寄存器的行为并不完全是我想象的那样。然后我编写了一个测试模块来测试寄存器的行为。以下是该模块的代码。
`timescale 1ns/1ps
module reg_behve(
input clk,
input rst_n,
input write_flag,
input d_in,
output d_out
);
reg d_out_r;
always @(posedge clk or negedge rst_n) begin
if(~rst_n)begin
d_out_r <= 0;
end
else if(write_flag)begin
d_out_r <= d_in;
end
end
assign d_out = d_out_r;
endmodule
以下是模块的测试台
`timescale 1ns/1ps
module reg_behve_tb();
reg clk;
reg rst_n;
reg write_flag_a;
reg write_flag_b;
reg d_in;
wire d_out_a;
wire d_out_b;
reg_behve uut_1(
.clk (clk),
.rst_n (rst_n),
.write_flag (write_flag_a),
.d_in (d_in),
.d_out (d_out_a)
);
reg_behve uut_2(
.clk (clk),
.rst_n (rst_n),
.write_flag (write_flag_b),
.d_in (d_in),
.d_out (d_out_b)
);
integer i;
initial begin
clk = 0;
rst_n = 1;
@(posedge clk)
rst_n = 0;
write_flag_a = 0;
write_flag_b = 0;
d_in = 0;
@(posedge clk)
rst_n = 1;
@(posedge clk)
d_in = 1;
write_flag_a = 1;
@(posedge clk)
write_flag_a = 0;
for(i = 0; i < 5; i = i + 1)begin
@(posedge clk);
end
$finish;
end
always @(posedge clk) begin
write_flag_b <= write_flag_a;
end
initial begin
$recordfile("sim/result.trn", "compress");
$recordvars();
end
always #1 clk = ~clk;
endmodule
该模块的主要目的是,如果 write_flag 上升,则将 d_in 中的值放入寄存器 d_out_r 中。我以前知道对寄存器的任何更改都会在下一个周期更新。然而,在仿真结果中,我们可以看到,对于uut_1,d_out_r与write_flag同时上升。我对这种行为感到非常困惑,无法用我目前的知识来解释它。我尝试在网上搜索,但发现很难找到正确的关键字和针对这个特定问题的答案。奇怪的是,当我使用寄存器来延迟 uut_2 测试台中的 write_flag_b 时,模块 2 的行为正是我所期望的。 d_out_r 将在下一个时钟周期更新其值。如果有人能帮助我解决这个问题,那将非常有帮助。如果有人需要有关该问题的更多信息,我将很乐意提供其他必要的信息!非常感谢!
我尝试开发一个模块来显示 verilog/system verilog 中寄存器的行为。我预计寄存器将在下一个周期更新其值。但是,它会在触发后立即更新值。
您必须在我们的测试台的初始块中使用非阻塞语句
<=
。
initial begin
clk = 0;
rst_n <= 1;
@(posedge clk)
rst_n <= 0;
write_flag_a <= 0;
write_flag_b <= 0;
d_in <= 0;
@(posedge clk)
rst_n <= 1;
@(posedge clk)
d_in <= 1;
write_flag_a <= 1;
@(posedge clk)
write_flag_a <= 0;
for(i = 0; i < 5; i = i + 1)begin
@(posedge clk);
end
$finish;
end