在 verilog 上模拟数据时遇到问题
Having trouble in simulating data on verilog
我提出了新问题 sheet 以获取更多详细信息。
我正在使用理想的 SRAM 和 CPU 设计一些数据总线系统的代码。我想写内存mem[0] -> IR,读内存IR -> mem[1],最后写内存mem[1] -> DR.
我认为现在在 mem
上转储数据是不正常的,因为内存和 dout
值一直在 ZZZZ。 SRAM 上的数据移动不畅。我怎样才能解决这个问题?
module sram(addr,clk,din,dout,we);
parameter addr_width = 12, word_depth = 4096, word_width = 16;
input clk,we;
input [addr_width-1:0] addr;
input [word_width-1:0] din;
output [word_width-1:0] dout;
reg [word_width-1:0]mem[0:word_depth-1];
reg [word_width-1:0] dout;
always @(posedge clk) begin
if(!we)
mem[addr] <= din[word_width-1:0];
end
always @(posedge clk) begin
dout[word_width-1:0] <= mem[addr];
end
endmodule
module cpu(clk,load,reset,select,ir,dr,ac,ar,pc,addr,we);
input clk,reset;
input [1:0]select;
input [1:0]load;
output reg[15:0] ir,dr,ac;
output reg[11:0] ar,pc;
input we;
input [11:0] addr;
reg[15:0] din;
wire[15:0] dout;
sram sram(addr,clk,din,dout,we);
always @ (posedge clk or negedge reset) begin
if(!reset) begin
ar <= 12'b0; ir <= 16'b0; pc <= 12'b0; dr <= 16'b0; ac <= 16'b0;
end
if(select==2'b01 && load==2'b01 && we==1) //read
ir[15:0] <= dout[15:0];
else if(select==2'b11 && load==2'b10 && we==0) //write
din[15:0] <= ir[15:0];
else if(select==2'b10 && load==2'b11 && we==1) //read
dr[15:0] <= dout[15:0];
end
endmodule
module tb_cpu();
parameter addr_width = 12, word_depth = 4096, word_width = 16;
reg clk,reset,we;
reg [1:0]select;
reg [1:0]load;
reg [addr_width-1:0] addr;
wire [word_width-1:0] ir,dr,ac;
wire [word_width-5:0] ar,pc;
integer file_pointer;
integer file_pointer2;
wire [word_width-1:0]mem[0:word_depth-1];
wire [word_width-1:0] dout;
cpu cpu(clk,load,reset,select,ir,dr,ac,ar,pc,addr,we);
always #5 clk = ~clk;
initial begin
clk = 0; we = 0; reset = 1;
#2 reset = 0;
#2 reset = 1;
file_pointer = $fopen("reg.dat");
file_pointer2 = $fopen("memory.dat");
$readmemb("sram.dat", tb_cpu.cpu.sram.mem);
#10 select = 2'b01; load = 2'b01; we = 1; addr = 12'b000000000000; //cycle 1
#10 select = 2'b11; load = 2'b10; we = 0; addr = 12'b000000000001; //cycle 2
#10 select = 2'b10; load = 2'b11; we = 1; addr = 12'b000000000001; //cycle 3
$fdisplay(file_pointer, "AR = %b", tb_cpu.cpu.ar);
$fdisplay(file_pointer, "IR = %b", tb_cpu.cpu.ir);
$fdisplay(file_pointer, "PC = %b", tb_cpu.cpu.pc);
$fdisplay(file_pointer, "DR = %b", tb_cpu.cpu.dr);
$fdisplay(file_pointer, "AC = %b", tb_cpu.cpu.ac);
$fdisplay(file_pointer2, "mem[0000 0000 0000] = %b",tb_cpu.cpu.sram.mem[000000000000]);
$fdisplay(file_pointer2, "mem[0000 0000 0001] = %b",tb_cpu.cpu.sram.mem[000000000001]);
$fdisplay(file_pointer2, "mem[0000 0000 0010] = %b",tb_cpu.cpu.sram.mem[000000000010]);
$fclose(file_pointer);
$fclose(file_pointer2);
#10 $finish;
end
endmodule
我认为原因是你需要 2 个时钟周期来传播 mem->dout->ir
。
在你的情况下,sram 在 posedge clk 读取 dout
。在同一位置,您将其值推入 ir
。但是硬件和模拟推动了 dout
的旧值,即 xxx...
。你需要给它更多的时间来安定下来。因此,如果您在测试台中使用 #20
而不是 #10
,您应该会看到不同的结果。
我提出了新问题 sheet 以获取更多详细信息。 我正在使用理想的 SRAM 和 CPU 设计一些数据总线系统的代码。我想写内存mem[0] -> IR,读内存IR -> mem[1],最后写内存mem[1] -> DR.
我认为现在在 mem
上转储数据是不正常的,因为内存和 dout
值一直在 ZZZZ。 SRAM 上的数据移动不畅。我怎样才能解决这个问题?
module sram(addr,clk,din,dout,we);
parameter addr_width = 12, word_depth = 4096, word_width = 16;
input clk,we;
input [addr_width-1:0] addr;
input [word_width-1:0] din;
output [word_width-1:0] dout;
reg [word_width-1:0]mem[0:word_depth-1];
reg [word_width-1:0] dout;
always @(posedge clk) begin
if(!we)
mem[addr] <= din[word_width-1:0];
end
always @(posedge clk) begin
dout[word_width-1:0] <= mem[addr];
end
endmodule
module cpu(clk,load,reset,select,ir,dr,ac,ar,pc,addr,we);
input clk,reset;
input [1:0]select;
input [1:0]load;
output reg[15:0] ir,dr,ac;
output reg[11:0] ar,pc;
input we;
input [11:0] addr;
reg[15:0] din;
wire[15:0] dout;
sram sram(addr,clk,din,dout,we);
always @ (posedge clk or negedge reset) begin
if(!reset) begin
ar <= 12'b0; ir <= 16'b0; pc <= 12'b0; dr <= 16'b0; ac <= 16'b0;
end
if(select==2'b01 && load==2'b01 && we==1) //read
ir[15:0] <= dout[15:0];
else if(select==2'b11 && load==2'b10 && we==0) //write
din[15:0] <= ir[15:0];
else if(select==2'b10 && load==2'b11 && we==1) //read
dr[15:0] <= dout[15:0];
end
endmodule
module tb_cpu();
parameter addr_width = 12, word_depth = 4096, word_width = 16;
reg clk,reset,we;
reg [1:0]select;
reg [1:0]load;
reg [addr_width-1:0] addr;
wire [word_width-1:0] ir,dr,ac;
wire [word_width-5:0] ar,pc;
integer file_pointer;
integer file_pointer2;
wire [word_width-1:0]mem[0:word_depth-1];
wire [word_width-1:0] dout;
cpu cpu(clk,load,reset,select,ir,dr,ac,ar,pc,addr,we);
always #5 clk = ~clk;
initial begin
clk = 0; we = 0; reset = 1;
#2 reset = 0;
#2 reset = 1;
file_pointer = $fopen("reg.dat");
file_pointer2 = $fopen("memory.dat");
$readmemb("sram.dat", tb_cpu.cpu.sram.mem);
#10 select = 2'b01; load = 2'b01; we = 1; addr = 12'b000000000000; //cycle 1
#10 select = 2'b11; load = 2'b10; we = 0; addr = 12'b000000000001; //cycle 2
#10 select = 2'b10; load = 2'b11; we = 1; addr = 12'b000000000001; //cycle 3
$fdisplay(file_pointer, "AR = %b", tb_cpu.cpu.ar);
$fdisplay(file_pointer, "IR = %b", tb_cpu.cpu.ir);
$fdisplay(file_pointer, "PC = %b", tb_cpu.cpu.pc);
$fdisplay(file_pointer, "DR = %b", tb_cpu.cpu.dr);
$fdisplay(file_pointer, "AC = %b", tb_cpu.cpu.ac);
$fdisplay(file_pointer2, "mem[0000 0000 0000] = %b",tb_cpu.cpu.sram.mem[000000000000]);
$fdisplay(file_pointer2, "mem[0000 0000 0001] = %b",tb_cpu.cpu.sram.mem[000000000001]);
$fdisplay(file_pointer2, "mem[0000 0000 0010] = %b",tb_cpu.cpu.sram.mem[000000000010]);
$fclose(file_pointer);
$fclose(file_pointer2);
#10 $finish;
end
endmodule
我认为原因是你需要 2 个时钟周期来传播 mem->dout->ir
。
在你的情况下,sram 在 posedge clk 读取 dout
。在同一位置,您将其值推入 ir
。但是硬件和模拟推动了 dout
的旧值,即 xxx...
。你需要给它更多的时间来安定下来。因此,如果您在测试台中使用 #20
而不是 #10
,您应该会看到不同的结果。