如何在 verilog 中使用显示或监视器来检查寄存器

How can I use display or monitor in verilog to check a register

我有 2 个模块。一个是 Register_File_Rf,它是我创建的 32 个寄存器的文件。我希望能够看到每个寄存器存储的内容。

我可以用 $display$monitor 以某种方式做到这一点吗? 这些应该在哪里?在实际代码中或在Testbench中,当存储的Data既不是输入也不是输出时,如何获取testbench中的值?

module Register(
input Clk,
input [31:0] Data,
input WE,
output reg[31:0] Dout
);
reg [31:0] stored;

// With every Positive Edge of the Clock
always @(posedge Clk)begin
    // If Write is Enabled we store the new Data
    if (WE)begin
        stored <= Data;
        Dout <= stored;
    end else
        Dout <= stored;
end

module Register_File_RF(
input [4:0] Adr1,
input [4:0] Adr2,
input [4:0] Awr,
output reg[31:0] Dout1,
output reg[31:0] Dout2,
input [31:0] Din,
input WrEn,
input Clk
);

integer j;
genvar i;
wire [31:0]Temp_Dout[31:0];
reg W_E [31:0];

// Writing only in the first time R0 Register with 0
initial begin
W_E[0] = 1;
end
// Creating the R0 Register
Register register (.Clk(Clk),.WE(W_E[0]),.Data(0),.Dout(Temp_Dout[0]));


// Creating 30 Registers
for(i = 1; i < 32; i = i + 1)begin:loop
    Register register (.Clk(Clk),.WE(W_E[i]),.Data(Din),.Dout(Temp_Dout[i]));
end:loop

// Assigning to Dout1 and Dout2 the Data from a spesific register
always @(Adr1, Adr2) begin
    Dout1 = Temp_Dout[Adr1];
    Dout2 = Temp_Dout[Adr2];
end

// Wrting Data to a specific register
always @(posedge Clk)begin
    //Reseting Write Enable of the register to 0
    for (j = 0; j < 32; j = j + 1)begin:loop2
            W_E[j] = 0;
    end:loop2
    
    if(WrEn)begin
        W_E[Awr] = WrEn;
    end
end
endmodule

是的,您可以使用 $display$monitor

通常,$monitor 会在 initial 块内调用,因为它只能在您的模拟中调用一次。只要其参数信号之一更改值,它就会自动显示值。

$monitor不同,$display只在调用时显示值;每当您想显示信号值时都必须调用它。它可以在initial块中调用,但通常在always块中调用。

关于何时使用其中任何一个,由您决定需要什么。

如果您不打算综合您的模块,您可以将 monitor/display 直接放在您的设计模块中。但是,如果您打算综合,将它们放在测试台中可能会更好。

您可以使用分层范围来查看来自测试台模块的内部信号。例如,假设您将测试平台中 Register_File_RF 模块的实例命名为 dut:

Register_File_RF dut (
   // ports
);

always @(posedge Clk) begin
    $display($time, " dout='h%x", dut.register.Dout);
end

initial begin
    $monitor($time, " dout='h%x", dut.register.Dout);
end

$monitor 每次 Dout 更改值时都会显示一个值,而 $display 会在时钟的位置显示值。

如果您的模拟器支持 SystemVerilog 功能,您还可以使用 bind 神奇地将代码添加到您的设计模块中。