我有一个与时钟 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 个不同的
i
循环中使用相同的变量 (for
)。 在第二个 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