我想写verilog
中的寄存器文件,即写入和读取数据寄存器。
这是我的代码:
module registerfile(writeaddr1,writedata1,readaddr2,readdata2,readaddr3,readdata3,write,clock);
input [4:0] writeaddr1, readaddr2, readaddr3;
input [31:0] writedata1;
output[31:0]readdata2,readdata3;
reg [31:0]readdata2,readdata3;
input write,clock;
reg [31:0] cells [0:31];
always @(posedge clock)
begin
if (write == 1) cells[writeaddr1] =writedata1;
readdata2 = cells[readaddr2];
readdata3 = cells[readaddr3];
end
endmodule
这是我的测试台。
module testreg;
reg [3:0]addr1,addr2,addr3;
reg [31:0]data1;
reg write;
wire [31:0]data2,data3;
reg clock ; //Rising edge every 10 timesteps
registerfile regf(addr1,data1,addr2,data2,addr3,data3,write,clock);
initial begin
addr1=1;
addr2=2;
addr3=3;
write=0;
data1=32'bx;
clock=0;
#10
addr1=1;
addr2=1;
addr3=3;
write=1;
data1=30;
clock=1;
#10
$finish;
end
endmodule
但我不知道为什么10到20之间的data2
是xxx?我在那个地方写了30 :(
答案 0 :(得分:3)
如果clk的周期为20ns,则在0ns和20ns之间应用第一次写入,但data2
不是data1
,因为读取和写入是同时的,并且当您在内存上写入值时,在下一个clk上升沿,您可以从内存中读取相同的值。然后介于20ns和40ns之间(在clk上升沿上)data2
等于data1
。
testreg
模块中addr1
的大小应为[4:0]
:
reg [4:0] addr1,addr2,addr3;
正如Greg在模块registerfile
中所说,最好使用非阻塞分配(<=
),例如以下代码:
always @(posedge clock)
if (write) begin
cells[writeaddr1] <= writedata1;
readdata2 <= cells[readaddr2];
readdata3 <= cells[readaddr3];
end
只需使用以下代码并继续运行模拟直到40ns:
initial begin
addr1=1;
data1=30;
addr2=1;
write=1;
end
initial begin
clock = 0;
forever #10 clock = ~clock;
end
我使用上述更改模拟了您的代码,可以得到正确的结果。