Vivado版本:2019.2 Modelsim版本:Modelsim SE-64 10.7
说到 FPGA ,不得不提的是存储器,当我们做相关项目时,经常会遇到存储数据的问题,数据量过大时,我们可以将其存储在 FPGA 芯片的外设存储器上,比如 sdram、ddr sdram、ddr3 sdram等,然而访问外设存储器相对比较麻烦,因此当数据量较小时,我们可以直接使用 FPGA 芯片内部自带的 ram 的 IP 核。
Ram是random access memory的简称,即随机存储器的意思,Ram可以按照所需进行随机读/写。我们可以通过调用FPGA内部的IP核生成一个ram,并通过编写Verilog HDL代码控制该ram。
打开vivado软件,新建一个工程,配置芯片为xc7a75tfgg484-2:
进入工程,选择IP Catalog:
在IP Catalog界面搜索框中输入RAM,在Memories & storage Elements选项下有两种IP,一种是DRAM(Distributed Memory Generator),一种是BRAM(Block Memory Generator):
这里的DRAM并不是动态存储器,而是分布式存储器,与BRAM区别在于,DRAM通过FPGA中的查找表拼凑形成,而BRAM是FPGA中整块双口RAM资源。
这里学习BRAM的使用,双击Block Memory Generator。学习一个IP核,先看IP的官方手册,点击Documentation,在选项中选择Product Guide:
注意IP核的版本为8.4,按照IP核的设置找每个配置的含义:
IP名字保持默认;
Interface Type:支持AXI4 和AXI4Lite,默认为Native。
Memory Type:IP核支持生成5种类型的存储:
Single-port RAM
Simple Dual-port RAM
Ture Dual-port RAM
Single-port ROM
Dual-port ROM
Single-port RAM(单口RAM),通过单组接口读写一块存储空间,接口如下:
Simple Dual-port RAM(简单双口RAM),有A和B两组接口,其中A接口用来写RAM,B接口用来读RAM,接口如下:
Ture Dual-port RAM(真双口RAM),有A和B两组接口,每一组接口都可以完成读和写操作,接口如下:
Single-port ROM(单口ROM),有单个接口读取存储空间,接口如下:
Dual-port ROM(双口ROM),有两组读取接口,接口如下:
ECC Options:只有Simple Dual-port RAM时,该选项才可用,IP核支持内置的汉明纠错功能(Built-in Hamming Error Correction Capability(BuiltIn ECC)),且支持数据位宽小于64位的软汉明纠错(soft ECC)。
Write Enable:设置是否启用字节写入,启用时,字节位宽可选为8位(无奇偶校验位)和9位(有奇偶校验位),此时数据位宽应是字节位宽的倍数,默认情况下不启用。
Algorithm Options:选择实现的内存算法。
Minimum Area Algorithm:使用最少数量的原语生成IP核;
Low Power Algorithm:低功耗算法,在读或写操作期间启用最小数量的块RAM原语;
Fixed Primitive Algorithm:固定单元算法,连接一个基本内存单元来生成IP核,在下拉列表中选择要使用的单元类型。
各芯片片内RAM资源如下:
这里选用Single-port RAM,其余保持默认。
配置端口A:
Write Width:写入位宽
Read Width:读出位宽,读写位宽可以不一致,IP核支持的读写位宽比例有:1:32、1:16、1:8、1:4、1:2、1:1、2:1、4:1、8:1、16:1、32:1。
Write Depth:写入深度
Read Depth:读出深度
Operating Mode:选项有Write First、Read First和No Change三种模式。
Enable Port Type:端口使能控制,可以使用ENA引脚控制,也可以选择always Enabled
Port A Optional Output Rregisters:选择是否在输出端添加寄存器
Port A Output Reset Options:配置复位信号
READ Address Change A:这个功能只在UltraScale设备上使用。
RAM写优先(Write First)时序如下,在ENA信号拉高后,在时钟上升沿检测ADDRA地址为aa,而WEA写使能为低,DOUTA就输出地址aa对应的数据;在第二个时钟上升沿,ENA为高,WEA信号为高,执行写操作,地址为bb,就将fdzxc上的数据1111写入存储中,并把fdzxc上的数据送到DOUTA上进行输出;在第三个时钟上升沿依然如此,将fdzxc数据写入存储同时将数据送到DOUTA上进行输出;第四个上升沿,ENA为高,WEA为低,执行读操作,地址为dd,就读取存储器地址dd中的数据送到DOUTA上进行输出。
RAM读优先时序如下:在ENA和WEA同时为高时,输出的数据是存储器存储的数据,同时,也会把新写入的数据替换掉存储器中的对应地址的数据。
RAM No Change模式:在ENA和WEA同时为高时,只进行写操作,不进行读操作,也就是说DOUTA保持前一拍数据,直到WEA为低。
Pipeline Stages within Mux:输出端Mux流水线级数
Memory Initialization:选择是否使用本地初始化.coe文件初始化存储空间。以及是否使用默认值初始化内存。
Structural/UNISIM Simulation Model Options:选择发生碰撞时由结构仿真模型生成的警告消息和输出的类型。
点击OK生成IP核。
根据读写时序,编写tb测试激励文件来仿真这几种模式。
(1) 首先将RAM中的内存赋初值,为0到255循环递增数据。
(2) 然后在将地址设置为0,并修改之后的10个数据,观察时序,是否为写优先。
初始化内存 初始化为递增数据
将地址0到9的数据替换为随机数,与手册中写优先时序一致
(3) 在生成一个RAM,同样的位宽与深度,配置为读优先模式:
同样的数据下,读优先模式,数据输出内存中的旧数据,同时把新数据写入相应地址中,与读优先时序一致。
(4) No Change模式不再展示
(5) 双RAM读写冲突,如果一个端口写入数据,另一个端口读取相同地址,此时内
存中的数据可以被写入,但读出的数据取决于写入端口的操作模式,如果是读优先,则可以正常输出旧的数据,如果是写优先或不改变模式,则输出数据无效。
再生成一个RAM,Memory Type选择True Dual-port Ram
两个端口都选用读优先模式,然后通过A口写入数据,同时通过B口读取数据,查看读取内容。
可以看到同步时钟下,通过A口写入的数据,在A口读出旧的数据,通过B口读出,则为新写入的数据。
(6) 使用异步时钟时,在一个端口往某个地址写数据时,另一个端口在指定时间内不能读或写该地址,在器件手册中定义了此置位时间。
(7) 数据位宽问题
读写位宽可以不一致,IP核支持的比例有1:32、1:16、1:8、1:4、1:2、1:1、2:1、4:1、8:1、16:1、32:1。当数据位宽不一致时,地址每次偏移值需要注意。
例如:写入位宽16位,读出位宽8位,此时写入地址每次递增为2,读出地址每次递增为1,这样才能将数据完全读出。
附:tb测试激励代码
www.makerw.com
www.v3edu.org
威三学院长期开FPGA人工智能就业班,FPGA软件无线电、通信IC就业班
欢迎咨询 15921999232 同微信 尤老师