使用软件: Vivado
开发板: EGO1采用Xilinx Artix-7系列XC7A35T-1CSG324C FPGA
BRAM介绍
BRAM 即块 RAM, 是 FPGA 的固有硬件资源。 另一种形式的 RAM 是分布RAM(Distribution RAM), 是由 FPGA 逻辑资源查找表 LUT 拼起来的 。这两种 RAM 最本质的区别是块RAM 默认输入有寄存器,所以它在读、写使能信号后的下个时钟边沿返回数据,而分布式RAM就没有,就是个组合逻辑,读、写使能的同一时刻返回数据。从时序的角度上来说,块RAM更好,唯一不足的是,它是珍贵的硬件资源。一般来说,芯片越高级,块RAM资源越多。
Artix- - 7 FPGA 的最高型号具有可分配的 13Mbit双端口BRAM, 而实验电路板选型的XC7A35T具备 18Kbit 的BRAM100 个 ,36Kbit 的BRAM 50 个,共1800Kbit 。 Xilinx 7系列 FPGA 可将 BRAM 配置为同步双端口 RAM或单端口 RAM。
同步双端口BRAM
方便通过一个端口写的同时可以从另一个端口进行读取
每个真正的双端口的36Kbit BRAM 包含 36Kbit 个存储单元以及2个完全独立的访问接口A 和B 。每个 18Kbit BRAM 双端口内存包含18Kbit 个存储单元以及2个完全独立的访问接口A和B 。内存的结构完全对称, 双端口可互换。
BRAM读写操作
(1)读操作
读操作是在一个时钟边沿完成读取RAM指定单元(读地址)内容的操作。首先将读取地址寄存在读端口,并在RAM读取时间之后将存储的数据加载到输出锁存器中。当使用输出寄存器时,读操作需要一个额外的等待周期。
(2)写操作
写操作是一个时钟边沿写入RAM的操作。写地址寄存在写入端口,数据输入存储在内存中。
(3)写模式
写模式有三种,决定了写入时钟边沿后,有效数据出现在输出锁存器的时间。
三种模式是: 写优先模式WRITE_FIRST、读优先模式READ_FIRST和不变模式。每个端口的写模式可以通过配置过程单独配置。
默认模式是写优先模式,在这种模式总是将最新写入的数据送到输出总线上。
在读优先模式,当新的数据被写入时,仍然输出先前存储的数据。
在不变模式,输出总线上保持先前的输出。
写优先模式
在第一个时钟的上升沿,将地址aa的数据MEM(aa)读出放在数据总线DO上。在第二个时钟的上升沿,写有效,因此将DI上的1111写入地址bb。因为写优先,所以出现在数据总线上的是新写入的1111。
读优先模式
在第一个时钟的上升沿,将地址aa的数据MEM(aa)读出放在数据总线DO上。在第二
个时钟的上升沿,写有效,因此将DI上的1111写入地址bb。因为读优先,所以出现在数据总线上的不是新写入的1111,而是原来地址bb的内存的值old MEM(bb)。
不变模式
在第一个时钟的上升沿,将地址aa的数据MEM(aa)读出放在数据总线DO上。在第二个时钟的上升沿,写有效,因此将DI上的1111写入地址bb。因为不变模式,所以在写有效的时候出现在数据总线上的数据是不变的,仍然是MEM(aa),直到写无效后的第一个时钟上升沿才变为MEM(dd)。
双端口块内存接口
BRAM IP的使用及仿真验证
IP核使用
coe文件
使用matlab生成.coe文件:
l.coe文件内容如下,注意前两行要添加~
将IP核添加到工程
- 在工程管理栏下点击[IP Catalog],然后搜索RAM,找到块RAM生成器[Block Memory Generator],如下图所示:
- 将组件名称改为“ram”,其他设置如下图所示:
读写模式改为读优先“Read First”
取消勾选Primitives Output Register,不然输出会滞后一个时钟周期
文章来源:https://www.toymoban.com/news/detail-790899.html
- 在[Other Options]选项中勾选Load Init File,点击Browse添加前面用matlab生成的要存入RAM的初始数据。
代码
verilog代码
`timescale 1ns / 1ps
//
// Module Name: BRAM_test
// Revision 0.01 - File Created
// Additional Comments:
//
//
module BRAM_test(clk,ena,wea,addra,dina,douta);
input clk,ena,wea;
input[9:0] addra;
input[14:0] dina;
output[14:0] douta;
ram ram(clk,ena,wea,addra,dina,douta);
endmodule
仿真代码
`timescale 1ns / 1ps
//
// Create Date: 2022/10/20 10:59:14
// Design Name:
// Module Name: sim_bram
// Revision 0.01 - File Created
// Additional Comments:
//
//
module sim_bram();
reg clk;//时钟输入
reg wea;//写使能
reg[9:0] addra;//地址输入
reg[14:0] dina;//数据输入
wire[14:0] douta;//数据输出
reg[9:0] cnt1,cnt2;
initial begin
clk=0;
wea=0;
cnt1=0;
cnt2=0;
end
BRAM_test uut(//调用被仿真的模块完成内存读写
.clk(clk),
.ena(1),
.wea(wea),
.addra(addra),
.dina(dina),
.douta(douta)
);
always #10 clk=~clk;//周期20ns,模拟50M时钟
always@(posedge clk)
begin
if(cnt1==8)
begin
cnt1=0;
cnt2=cnt2+1;//cnt2低位每9个周期翻转一次
end
else
cnt1=cnt1+1;
end
//负边沿写地址,写数据输入,写使能信号,保证时钟上升沿时这些值是稳定的
always@(negedge clk)
begin
dina=cnt1;//数据输入总线是哪个的值是计数值cnt1
addra=cnt1;
if(cnt2[0]==0) wea=0;//每9个周期写使能翻转
else wea=1;
end
endmodule
仿真结果
仿真结果如下图所示:
初始时,在时钟上升沿读取RAM中addra地址(000 ~ 008)下存储的值(100 ~ 108)。
在写使能wea=1之后,因为是读优先,所以先读出该地址的值,再将dina内容写入,所以看到douta的值还是(100 ~ 108)。
写使能结束之后,再读取ram对应地址中的内容,可以看出douta结果为写入的数值(0 ~ 8)。文章来源地址https://www.toymoban.com/news/detail-790899.html
到了这里,关于FPGA — BRAM学习笔记—读写操作的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!