当我尝试在两个不同的测试平台中测试我的定制 Vivado block ram IP 时,我得到了矛盾的结果。
生成的RAM是一块具有本机接口的16x255 True Dual Port Ram(端口A和端口B)。原语输出寄存器和 RST 信号可用于两个端口。此外,操作模式也没有变化。图 1 和图 2 分别提供了端口配置和 IP 摘要。
图 1. 端口配置:
图2.IP摘要:
Testbench A 是一个简单直观的测试平台,其中所有内容(控制信号、输入数据和 I/O 地址)都是手动提供的。
module tb_blk_mem_1();
reg rst, clk, clkb;
reg blk_mem_wen, blk_mem_ren;
wire wrst_busy, rrst_busy;
reg [7:0] waddr_0, raddr_0;
reg [15:0] din_0;
wire [15:0] dout_0;
reg ena;
always begin
#10 clk = ~clk;
end
always begin
#10 clkb = ~clkb;
end
initial begin
clk = 1; rst = 1; blk_mem_wen = 0; blk_mem_ren = 0; waddr_0 = 255; raddr_0 = 3; din_0 = 65535;clkb = 1; ena = 1;
#40 rst = 0;
#180 blk_mem_wen = 1;
#20 din_0 = 1; waddr_0 = 0;
#20 blk_mem_wen = 1; waddr_0 = 1; din_0 = 2;
#20 blk_mem_wen = 1; waddr_0 = 2; din_0 = 3;
#20 blk_mem_wen = 1; waddr_0 = 3; din_0 = 4;
#20 blk_mem_wen = 0;ena = 0;
#200 blk_mem_ren = 1; raddr_0 = 0;
#20 blk_mem_ren = 1; raddr_0 = 1;
#20 blk_mem_ren = 1; raddr_0 = 2;
#20 blk_mem_ren = 1; raddr_0 = 3;
#20 raddr_0 = 0;
#20 raddr_0 = 1;
end
blk_mem_gen_1 blk_mem_gen_1(
.clka(clk),
.wea(blk_mem_wen),
.addra(waddr_0),
.dina(din_0),
.douta(),
.ena(ena),
.addrb(raddr_0),
.dinb(),
.rsta(rst),
.doutb(dout_0),
.rstb(rst),
.enb(blk_mem_ren),
.web(1'b0),
.clkb(clkb),
.rsta_busy(wrst_busy),
.rstb_busy(rrst_busy)
);
endmodule
图 3. 测试平台 A 结果:
根据图3可以看出,在提供地址时,Block ram第一次返回数据失败。而且,进一步返回的数据仅延迟 1 个时钟周期而不是 2 个时钟周期。
Testbench B 是一个惰性测试程序,地址和数据都会自动提供给块 RAM。地址和数据以累加的方式生成。
module tb_blk_mem();
wire [15:0] douta, doutb;
reg clka, clkb;
reg ena, enb;
reg wea;
reg rst;
wire rsta_busy, rstb_busy;
wire [15:0] dina;
wire [7:0] addra, addrb;
blk_mem_wr blk_mem_wr(
.wr_clk(clka),
.rst_busy(rsta_busy),
.wr_data(dina),
.wr_addr(addra),
.wen(wea)
);
blk_mem_rd blk_mem_rd(
.rd_clk(clkb),
.ren(enb),
.rst_busy(rstb_busy),
.rd_addr(addrb)
);
blk_mem_gen_1 blk_mem_gen_1(
.addra(addra),
.addrb(addrb),
.dina(dina),
.dinb(),
.clka(clka),
.clkb(clkb),
.ena(ena),
.enb(enb),
.wea(wea),
.web(),
.rsta(rst),
.rstb(rst),
.douta(),
.doutb(doutb),
.rsta_busy(rsta_busy),
.rstb_busy(rstb_busy)
);
always begin
#10 clka = !clka;
end
always begin
#10 clkb = !clkb;
end
initial begin
clka = 1; clkb = 1;rst = 1;ena = 1; enb = 0; wea = 0;
#10 rst = 0;
#300 ena = 1'b1; wea = 1'b1;
#400 wea = 1'b0;ena = 1'b0;
#50 enb = 1;
#400 $finish;
end
endmodule
图 4. 测试平台 B 结果:
根据图 4,块公羊工作得非常好。由于 255 显然大于 150,因此是合法的“X”。
总而言之,我有两个测试平台,A)IP ram 工作不正常,测试结果与 IP 信息不符,而 B)IP ram 工作良好。
我尝试使用不同的块内存,但问题仍然存在。另外,通过比较两个波形图(图3和图4),控制逻辑几乎相同。因此,我预计我的测试平台中存在一些我显然没有意识到的错误。
我能够重现您的问题。该问题是由测试台提供的输入引起的,因此在时钟的上升沿您会切换所有信号,从而产生竞争条件。简而言之,由于测试平台中的输入是异步驱动的,因此正在创建竞争条件。要详细了解为什么会出现这种竞争情况,您可以查看此答案。在您的测试台上将
clk = 1;
的值更改为clk = 0;
,将clkb = 1;
更改为clkb = 0;
,这样可以防止出现竞争情况。换句话说,从数据输入的转换中稍微移动时钟沿。
由于同样的原因,您的测试平台 B 正在生成正确的结果,因为在测试平台 B 中,您没有驱动来自测试平台的输入。相反,在测试平台 B 中,您从其他两个模块获取输入,并且它们同步向 Block Ram 提供输入。