我看到未定义的输出序列在模拟中读取内存

I see undefined output sequences reading a memory in simulation

我有一个关于时钟 SRAM 内存实现的问题,它应该存储用户写入的数据,然后显示内存内容。此外,我创建了一个名为 display 的模块,它简化了读取过程,因此无需通过在每次读取后递增寄存器来提供应从中提取数据的内存地址。然而,当我模拟电路时,我看不到正确的输出;因此,当我读取内存时,我注意到一些未定义的输出序列。我把相应的代码贴在下面。

//stores output data
module sram_1port_data(
    input clk,//clocked memory
    input wr_en,//when high, data is written, otherwise is read
    input [15:0] address_in,//suppose timer cannout count more than 13ms
    input [3:0] wr_data,//memory does not sotre values greater than 13(ms)
    output reg [3:0] rd_data
);

reg [3:0] memory [2 ** 15 - 1 : 0];

always @(posedge clk) begin
    if(wr_en) memory[address_in] <= wr_data;
    else rd_data <= memory[address_in];
end

endmodule

//display interfacedesigned for the second memory
module display(
    input clk,
    input wr_en,
    input [15:0] address_in,
    input [3:0] wr_data,
    output [3:0] rd_data
);

reg [15:0] pointer,address;

initial pointer = 16'd0;

sram_1port_data i0(.clk(clk),.wr_en(wr_en),.address_in(address),.wr_data(wr_data),.rd_data(rd_data));

always @(posedge clk) begin
    if(!wr_en) begin
        address <= pointer;
        pointer <= pointer + 1;
    end 
    else address <= address_in;
end

endmodule

//tb for display
module display_tb(
    output reg clk,
    output reg wr_en,
    output reg [15:0] address_in,
    output reg [3:0] wr_data,
    output [3:0] rd_data
);

display i0(.clk(clk),.wr_en(wr_en),.address_in(address_in),.wr_data(wr_data),.rd_data(rd_data));

initial $dumpvars(0,display_tb);

initial begin
    clk = 1'd1;
    repeat (2000)
    #100 clk = ~clk;
end

initial begin
    wr_en = 1'd1;
    #100000 wr_en = 1'd0;
end

integer i;

initial begin
    wr_data = 3'd0;
    for(i = 1;i < 500;i = i + 1) begin
    #200 wr_data = i;
    end
end

initial begin
    address_in = 16'd0;
    for(i = 1;i < 500;i = i + 1) begin
    #200 address_in = i;
    end
end

endmodule

当我查看波形时,我发现 rd_data 在所有其他读数中都是未知的 (X)。查看内部地址信号,我发现未知数仅适用于偶数地址。在模拟的早期,您只写入偶数地址。

在您的测试台中,您在 2 个不同的 for 循环中使用相同的变量 (i)。在第二个 for 循环中,使用不同的变量名称(例如 j):

integer j;
initial begin
    address_in = 16'd0;
    for(j = 1;j < 500;j = j + 1) begin
    #200 address_in = j;
    end
end

现在,所有读取都具有已知值,因为它写入所有地址(偶数和奇数)。


您还可以将地址设置在与写入数据相同的 for 循环内。在这种情况下,这可能是更好的方法。

initial begin
    wr_data    =  3'd0;
    address_in = 16'd0;
    for(i = 1;i < 500;i = i + 1) begin
        #200;
        wr_data    = i;
        address_in = i;
    end
end