bram设置为简单双口
建议取消勾选这个,这样读出来的数据是差一个时钟周期的
vivado中的bram,写的时候,写使能,写地址,写数据一起赋值
读的时候,读使能,读地址可以一起赋值,数据为下一时钟周期才会来
逻辑为在地址1写入了数据2。
读的逻辑,地址1的数据2在一个时钟周期之后
代码:
`timescale 1ns / 1psmodule test_bram(input wire clk,input wire restn);wire ena, enb, wea;
wire [9 : 0] addra, addrb;
wire [15 : 0] dina, doutb;
reg ena_r, enb_r, wea_r;
reg [9 : 0] addra_r, addrb_r;
reg [15 : 0] dina_r;
assign ena = ena_r;
assign enb = enb_r;
assign wea = wea_r;
assign addra = addra_r;
assign addrb = addrb_r;
assign dina = dina_r;
reg [9:0] cnt;
reg enb_r_1;
blk_mem_gen_0 bram (.clka(clk), // input wire clka.ena(ena), // input wire ena.wea(wea), // input wire [0 : 0] wea.addra(addra), // input wire [9 : 0] addra.dina(dina), // input wire [15 : 0] dina.clkb(clk), // input wire clkb.enb(enb), // input wire enb.addrb(addrb), // input wire [9 : 0] addrb.doutb(doutb) // output wire [15 : 0] doutb
);
// bram先写后读验证
reg [9:0] cnt_a;
always @(posedge clk or negedge restn) beginif(!restn) beginena_r <= 0;wea_r <= 0;dina_r <= 1;//数据为地址加一addra_r <= 0;cnt_a <= 0;endelse if (cnt_a < 10'd639)beginena_r <= 1;wea_r <= 1;dina_r <= dina_r + 1;addra_r <= addra_r + 1;cnt_a <= cnt_a + 1;endelse beginena_r <= 0;wea_r <= 0;dina_r <= 0;addra_r <= 0;end
endalways @(posedge clk or negedge restn) beginif(!restn) beginenb_r <= 0;addrb_r <= 0;endelse if (cnt_a == 10'd639)beginenb_r <= 1;addrb_r <= (addrb_r>=10'd639) ? 10'd639 : (addrb_r + 1);end
endendmodule
testbench:
//~ `New testbench
`timescale 1ns / 1psmodule tb_test_bram;// test_bram Parameters
parameter PERIOD = 10;// test_bram Inputs
reg clk = 0 ;
reg restn = 0 ;// test_bram Outputsinitial
beginforever #(PERIOD/2) clk=~clk;
endinitial
begin#(PERIOD*2) restn = 1;
endtest_bram u_test_bram (.clk ( clk ),.restn ( restn )
);initial
begin$finish;
endendmodule