有关寄存器行为的问题

问题描述 投票:0回答:1

我是一名刚接触 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

以下为模块波形

waveform of the module

该模块的主要目的是,如果 write_flag 上升,则将 d_in 中的值放入寄存器 d_out_r 中。我以前知道对寄存器的任何更改都会在下一个周期更新。然而,在仿真结果中,我们可以看到,对于uut_1,d_out_r与write_flag同时上升。我对这种行为感到非常困惑,无法用我目前的知识来解释它。我尝试在网上搜索,但发现很难找到正确的关键字和针对这个特定问题的答案。奇怪的是,当我使用寄存器来延迟 uut_2 测试台中的 write_flag_b 时,模块 2 的行为正是我所期望的。 d_out_r 将在下一个时钟周期更新其值。如果有人能帮助我解决这个问题,那将非常有帮助。如果有人需要有关该问题的更多信息,我将很乐意提供其他必要的信息!非常感谢!

我尝试开发一个在 verilog 中显示寄存器行为的模块。我预计寄存器将在下一个周期更新其值。但是,它会在触发后立即更新值。

verilog cpu-architecture system-verilog
1个回答
0
投票

考虑到您刚刚开始,您的编码非常好。现在关于这个问题,您必须在我们的测试台中的初始块中使用非阻塞语句

<=
<=
测试台中的非阻塞语句用于将逻辑与相应的时钟沿同步。

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

或者,您可以在开始时提供

clk = 1;
来抵消您的刺激。

大多数人都知道 Verilog 模块中非阻塞和阻塞语句的用法,即分别用于顺序逻辑和组合逻辑。但在测试台中这些语句的使用常常被忽视。

您可以查看这里了解更多详情。

© www.soinside.com 2019 - 2024. All rights reserved.