本文转载自:FPGA入门到精通微信公众号
FPGA开发中使用频率非常高的两个IP就是FIFO和BRAM,上一篇文章中已经详细介绍了Vivado FIFO IP,今天我们来聊一聊BRAM IP。
本文将详细介绍Vivado中BRAM IP的配置方式和使用技巧。
一、BRAM IP核的配置
1、打开BRAM IP核
在Vivado的IP Catalog中找到Block Memory Generator IP核,双击打开参数配置界面。
2、配置BRAM IP基本参数
(1)IP名
定制的IP的名字只能在定制时设定好,后续不能修改。
IP名设定,简单易懂即可,按照功能或数据宽度和深度来设定即可,例如BRAM_8x256,即表示数据宽度为8bit,数据深度为256bit。
(2)接口类型(Interface Type)
Native:最基本的接口,包括数据写入、数据读取等信号。
AXI4:AXI4总线通信协议接口
(3)存储类型(Memory Type)
Single Port RAM:单端口RAM
Simple Dual Port RAM:简单双端口RAM,可选同步时钟和异步时钟,A端口只支持写数据,B端口只支持读数据。
True Dual Port RAM:真双端口RAM,可选同步时钟和异步时钟,A端口和B端口都支持写数据和读数据。
Single Port ROM:单端口ROM
Dual Port ROM:双端口ROM,A端口和B端口都可以读取数据
3、配置A端口或B端口参数
A端口和B端口参数配置界面基本一致,这里只介绍A端口的参数配置。
(1)存储大小设置(Memory Size)
设置读数据或写数据端的数据位宽和深度,数据位宽范围为1~4608bit,数存储深度为2~1048576。
operating mode:读写同一个地址时,操作模式设定:写优先、读优先、不变,建议在实际应用时不出现这种情况。
Enable Port Type:设定是否开放端口使能控制信号。
(2)输出数据寄存设置
Primitives Output Register:输出数据是否插入一个寄存器,如果不选中这个,则读数据延时只有1个周期,否则读数据延时有2个周期。
建议选中这个输出寄存器,可以改善时序。
(3)复位参数设置
RSTA Pin (setreset pin):复位端口选择,如果选中,则开放复位端口。
Output Reset Value (Hex):设定复位生效后,输出数据值,默认为0
4、Other Options
这部分初始化值,对于RAM来说可能用处不大,但对于ROM来说很重要。
选中这个Load Init File,再点击“Browse”选中“coe或mif”格式文件,最后点击“Edit”,在打开的界面选择“Valide”校验一下,如果有问题,这部分会提示红色文字,否则继续下一步即可。
5、IP设置参数总览
IP设置参数总览,可看到资源消耗、宽度、深度、读延迟等信息。
6、点击OK生成IP核。
在IP核生成完成后,点击source窗口下的“IP source”,鼠标左键单击这个IP,在“Instantiation Template”下,双击“veo”后缀文件,即可看到例化模板。
二、BRAM IP核的接口
1、时钟信号和复位信号
复位信号 rsta/rstb
时钟 clka(A端口时钟) clkb(b端口时钟),复位信号 rsta(A端口复位),rstb(B端口复位)
2、端口信号
A和B端口信号基本一样,这里以A端口为例。
ena A端口使能信号
wea A端口写使能信号
addra A端口读写地址
dina A端口的写入数据
douta A端口的读取数据
三、BRAM IP核的调用
BRAM IP核的调用很简单,这里以同步时钟下的简单双端口RAM为例:
module top (
input clk,
input [7:0] data_in,
input wr_en,
input [7:0] wr_addr,
input [7:0] rd_addr,
output [7:0] data_out
);
BRAM_8x256 u_BRAM_8x256 (
.clka(clk), // input wire clka
.ena(1'b1), // input wire ena
.wea(wr_en), // input wire [0 : 0] wea
.addra(wr_addr), // input wire [7 : 0] addra
.dina(data_in), // input wire [7 : 0] dina
.clkb(clk), // input wire clkb
.enb(1'b1), // input wire enb
.addrb(rd_addr), // input wire [7 : 0] addrb
.doutb(data_out) // output wire [7 : 0] doutb
);
endmodule
下面是BRAM IP核的一个简单的testbench:
module test;
reg clk;
reg [7:0] din;
reg wen;
reg [7:0] waddr;
reg [7:0] raddr;
wire [7:0] dout;
top u_top(
.clk(clk),
.data_in(din),
.wr_en(wen),
.wr_addr(waddr),
.rd_addr(raddr),
.data_out(dout)
);
initial begin
clk = 0;
wen = 0; waddr = 0; raddr = 0;
#10 wen = 1; waddr = 1; din = 5;
#10 wen = 1; waddr = 2; din = 6;
#10 wen = 1; waddr = 3; din = 7;
#10 wen = 1; waddr = 4; din = 8;
#10 wen = 1; waddr = 5; din = 9;
#10 wen = 0; raddr = 1;
#10 wen = 0; raddr = 2;
#10 wen = 0; raddr = 3;
#10 wen = 0; raddr = 4;
#10 wen = 0; raddr = 5;
#30 $finish;
end
always #5 clk = ~clk;
endmodule
仿真测试图:
参考文献: