BRAM使用方法
在利用fpga进行数据处理的过程中,对高速数据采集或者传输的过程中,需要对数据尽心缓存,缓存一般有两种不同的方法,一种是FIFO,一种是RAM,FIFO在vivado中提供IP核,FIFO的缓存特性适用于先存先取得过程,没有寻址地址,数据只能按照次序读出,可以用于速率变换,位宽变换的应用中,数据的读写可以分开控制。RAM可以缓存数据,然后按照地址进行读出,这样不受顺序的限制,能够更加灵活的读取数据。在vivado中提供BRAM IP核,Block Memory Generator,使用该IP核可以实现该功能。
以下为使用BRMA的介绍 参考官方文档PG058 - Block Memory Generator v8.4 Product Guide(PG058) 。
直入主题,使用RAM,重点是实现写入和读取的过程,参照官方手册,查看操作模式。
操作模式
1.Write First Mode 写优先模式
在WRITE_FIRST模式下,输入数据同时写入内存,并驱动输出数据,如图3-9所示。这种透明模式提供了在同一端口上进行Write操作期间使用数据输出总线的灵活性。
这种模式适合用于先把数据都传入ram,传完之后再进行读取,在写使能信号有效时,输出的是当前写入地址的数据
测试过程
module test(
input clk,
input rst_n,
input [1:0] data_type,
input en,
input wr
);
wire [9:0] addra;
wire [7:0] dina;
wire [7:0] douta;
reg [9:0] addrw,addrr,addr;//读地址和写地址
reg [7:0] din;
reg [7:0] dout; //读出的有效数据
reg [1:0] mode_wr; //读写模式地址
parameter size = 10'd100;
//在单端口的控制模式下,只有一个地址,
//在写入使能的时候,从写模式的时序中可以看出想当与透传模式,
//先通过有效位进行读写模式判断
always@(posedge clk)begin
if(~rst_n)begin
mode_wr <= 2'b0;
end
else begin
if(en==1'b1 & wr==1'b0)begin
mode_wr <= 2'b01; //读模式;
end
if(en==1'b1 & wr==1'b1)begin
mode_wr <= 2'b10; //写模式
end
end
end
//分别读写地址
assign addra = (mode_wr == 2'b10) ? addrw : addrr;
//写控制 从0地址开始写,
always@(posedge clk)begin
if(~rst_n)begin
addrw <= 10'b0;
end
else begin
if(mode_wr == 2'b10)begin
if(addrw >= size)begin
addrw <= 10'b0;
end
else begin
addrw <= addrw + 10'b1;
end
end
else begin
addrw <= 10'b0;
end
end
end
//写数据
always@(posedge clk)begin
if(!rst_n)begin
din <= 8'b0;
end
else begin
if(mode_wr == 2'b10)begin
case(addrw)
10'h1: begin din <= 8'h1a;end
10'h2: begin din <= 8'hcf;end
10'h3: begin din <= 8'hfc;end
10'h4: begin din <= 8'hdc;end
10'h5: begin din <= 8'hb6;end
default: begin din <= 8'h11;end
endcase
end
end
end
assign dina = din;
//读控制
always@(posedge clk)begin
if(~rst_n)begin
addrr <= 10'b0;
end
else begin
if(mode_wr == 2'b01)begin
if(addrr >= size)begin
addrr <= 10'b0;
end
else begin
addrr <= addrr + 10'b1;
end
end
else begin
addrr <= 10'b0;
end
end
end
//读数据
always@(posedge clk)begin
if(!rst_n)begin
dout <= 8'b0;
end
else begin
if(mode_wr == 2'b01)begin
dout <= douta;
end
end
end
blk_mem u0 ( //2clk
.clka(clk), // input wire clka
.ena(en), // input wire ena 使能信号
.wea(wr), // input wire [0 : 0] wea
.addra(addra), // input wire [9 : 0] addra
.dina(dina), // input wire [7 : 0] dina
.douta(douta) // output wire [7 : 0] douta
);
endmodule
测试结果
2.Read First Mode 读优先模式
在READ_FIRST模式下,以前存储在Write地址的数据出现在数据输出中,而输入数据存储在内存中。这种先读后写的行为如图3-10所示
在这种模式下,写的地址在移动,但是不影响读数据,数据的内容是之前存储的。
3.No Change Mode 保持模式
在NO_CHANGE模式下,Write操作期间输出锁存保持不变。如图3-11所示,输出的数据仍然是原来的Read数据,不受同一个端口写操作的影响。
这种模式和读优先的模式相比,是在写的时候地址在动,但是输出不变,还是最开始的地址。