IP核——RAM
一、Quartus
1.打开Quartus ii,点击Tools---MegaWizard Plug-In Manager
2.弹出创建页面,选择Creat a new custom megafunction variation,点Next
3.选择IP核,可以直接搜索ram,选择RAM:2-PORT,右上方选择器件型号,语言选成Verilog,再填写一下路径名字,点Next,后面就是参数设置了。
4.设置读写需要几个端口,深度计算按word还是bit。Next
5.设置深度,位宽,类型。Next
6.设置读写需要几个端口,深度计算按word还是bit,一般选word。Next
7.是否为输出添加一个寄存器(加了寄存器可以使RAM输出的数据更稳定)?本来ram的输出就是会慢1clk,勾选后又慢1clk,所以一般不勾选。Next
8.输出的是新数据还是老数据,一般是要新数据,所以I don't care就行。Next
9.是否添加初始化文件mif ? Next
10.告诉你此IP核的编译库是什么,Next
11.输出的文件列表,除了正常IP核,还可以选择例化文件,注意bb.v文件用不到,一般是不勾选的。之后点finish就生成IP核了。
二、ISE
1.创建ISE工程,IP核需要在ISE工程里面进行调用。点击Tools---Core Generator...
2.在新弹出来的界面中创建一个属于IP核的工程:file---new project,并填写文件存储位置和文件名称,一般为ipcore_dir文件夹,点击保存
3.弹出的Part处填写器件的系列、型号、封装以及速度等级,Generation处设置语言为Verilog,点击OK
4.点击文件夹,找到Memories & Storage Elements---RAMs & ROMs---Block Memory Generator,(也可以直接搜索)双击打开,进行参数设置
5.设置模块名称,Next
6.类型选择,一般选Single Dual RAM,该RAM为“a口负责写,b口负责读”,而对于真双口RAM来说,a和b都是可读可写。其他选项根据需要勾选。Next
7.RAM的位宽、深度、使能选择,Next
8.是否在B端添加一个寄存器(加了寄存器可以使RAM输出的数据更稳定)?本来ram的输出就慢1clk,勾选了又慢1clk,所以一般不勾选。是否需要初始化并加载初始化ceo文件,Next
9.是否对B口添加复位键,Next
10.总结页面,注意里面一句话:B口的读取有1clk的延迟,点击Generate即可生成RAM。大功告成!
三、单RAM读写操作(by威三学院FPGA教程)
本代码针对Quartus的RAM:2-PORT
- //==========================================================================
- // --- 名称 : ram_ctrl.v
- // --- 作者 : xianyu_FPGA
- // --- 日期 : 2019-06-23
- // --- 描述 : 单个ram读写操作
- //==========================================================================
- module ram_ctrl
- //---------------------<端口声明>-------------------------------------------
- (
- input wire clk , //时钟,50Mhz
- input wire rst_n , //复位,低电平有效
- input wire [:] din , //写入的数据
- output wire [:] dout //读出的数据
- );
- //---------------------<信号定义>-------------------------------------------
- reg wr_en ; //写使能
- reg [:] wr_addr ; //写地址
- reg [:] rd_addr ; //读地址
- //--------------------------------------------------------------------------
- //-- ram例化
- //--------------------------------------------------------------------------
- ram_256x8 u_ram_256x8
- (
- .clock (clk ),
- .wren (wr_en ),
- .wraddress (wr_addr ),
- .data (din ),
- .rdaddress (rd_addr ),
- .q (dout )
- );
- //--------------------------------------------------------------------------
- //-- 产生写使能
- //--------------------------------------------------------------------------
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n)
- wr_en <= 'b1;
- else if(wr_addr=='d255)
- wr_en <= 'b0;
- else if(rd_addr=='d255)
- wr_en <= 'b1;
- end
- //--------------------------------------------------------------------------
- //-- 产生写地址
- //--------------------------------------------------------------------------
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n)
- wr_addr <= 'd0;
- else if(wr_en==)
- wr_addr <= wr_addr+'d1;
- else
- wr_addr <= 'd0;
- end
- //--------------------------------------------------------------------------
- //-- 产生读地址
- //--------------------------------------------------------------------------
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n)
- rd_addr <= 'd0;
- else if(wr_en==)
- rd_addr <= rd_addr+'d1;
- else
- rd_addr <= 'd0;
- end
- endmodule
四、双RAM乒乓操作(by威三学院FPGA教程)
RAM的简单读写比较简单,平常也用不太到,比较重要的是异步双口RAM实现乒乓操作。
本代码针对ise的Simple Dual PORT RAM
- //==========================================================================
- // --- 名称 : ram_pp.v
- // --- 作者 : xianyu_FPGA
- // --- 日期 : 2019-06-23
- // --- 描述 : 异步双口ram乒乓操作
- //==========================================================================
- module ram_pp
- //---------------------<端口声明>-------------------------------------------
- (
- input wire clk , //时钟,50Mhz
- input wire rst_n , //复位,低电平有效
- input wire [:] din , //输入的数据
- output wire [:] dout //输出的数据
- );
- //---------------------<信号定义>-------------------------------------------
- //ram_a
- reg wr_en_a ;
- reg [:] wr_addr_a ;
- reg [:] rd_addr_a ;
- wire [:] dout_a ;
- //ram_b
- reg wr_en_b ;
- reg [:] wr_addr_b ;
- reg [:] rd_addr_b ;
- wire [:] dout_b ;
- //缓一拍
- reg wr_en_a_r0 ;
- //--------------------------------------------------------------------------
- //-- ip核例化
- //--------------------------------------------------------------------------
- //ram_a
- ram_1024x8 u_ram_1024x8_a
- (
- .clka (clk ), // input clka
- .wea (wr_en_a ), // input [0 : 0] wea
- .addra (wr_addr_a ), // input [9 : 0] addra
- .dina (din ), // input [7 : 0] dina
- .clkb (clk ), // input clkb
- .addrb (rd_addr_a ), // input [9 : 0] addrb
- .doutb (dout_a ) // output [7 : 0] doutb
- );
- //ram_b
- ram_1024x8 u_ram_1024x8_b
- (
- .clka (clk ), // input clka
- .wea (wr_en_b ), // input [0 : 0] wea
- .addra (wr_addr_b ), // input [9 : 0] addra
- .dina (din ), // input [7 : 0] dina
- .clkb (clk ), // input clkb
- .addrb (rd_addr_b ), // input [9 : 0] addrb
- .doutb (dout_b ) // output [7 : 0] doutb
- );
- //--------------------------------------------------------------------------
- //-- ram_a
- //--------------------------------------------------------------------------
- // 写使能
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n)
- wr_en_a <= 'b1;
- else if(rd_addr_a=='d1023)
- wr_en_a <= 'b1;
- else if(wr_addr_a=='d1023)
- wr_en_a <= 'b0;
- end
- // 写地址
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n)
- wr_addr_a <= 'd0;
- else if(wr_addr_a=='d1023)
- wr_addr_a <= 'd0;
- else if(wr_en_a=='b1)
- wr_addr_a <= wr_addr_a + 'b1;
- end
- // 读地址
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n)
- rd_addr_a <= 'd0;
- else if(rd_addr_a=='d1023)
- rd_addr_a <= 'd0;
- else if(wr_en_a=='b0)
- rd_addr_a <= rd_addr_a + 'b1;
- end
- //--------------------------------------------------------------------------
- //-- ram_b
- //--------------------------------------------------------------------------
- // 写使能
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n)
- wr_en_b <= 'b0;
- else if(wr_addr_a=='d1023) //关键之处!!!
- wr_en_b <= 'b1;
- else if(wr_addr_b=='d1023)
- wr_en_b <= 'b0;
- end
- // 写地址
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n)
- wr_addr_b <= 'd0;
- else if(wr_addr_b=='d1023)
- wr_addr_b <= 'd0;
- else if(wr_en_b=='b1)
- wr_addr_b <= wr_addr_b + 'b1;
- end
- // 读地址
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n)
- rd_addr_b <= 'd0;
- else if(rd_addr_b=='d1023)
- rd_addr_b <= 'd0;
- else if(wr_en_b=='b0)
- rd_addr_b <= rd_addr_b + 'b1;
- end
- //--------------------------------------------------------------------------
- //-- wr_en_a缓一拍时序才对齐
- //--------------------------------------------------------------------------
- always @(posedge clk or negedge rst_n) begin
- if(!rst_n)
- wr_en_a_r0 <= ;
- else
- wr_en_a_r0 <= wr_en_a;
- end
- //--------------------------------------------------------------------------
- //-- 数据输出
- //--------------------------------------------------------------------------
- assign dout = (wr_en_a_r0==) ? dout_a : dout_b;
- endmodule
五、单口,伪双口,真双口的区别
1.单口:只有一组数据线和地址线,只生成一个addr,因此不能同时进行读写。
2.双口:拥有两组数据线和地址线,可以生成wr_addr和rd_addr,因此可以同时进行读写。
①伪双口:一个端口读,一个端口写。
②真双口:两个端口都能读能写。
ps:
无论是单口、伪双口还是真双口,他们都只使用一块Memory,真双口其实是两组地址对同一块Memory进行读写,如果真双口的两端口同时对同一地址进行写入数据,那实际情况是未知(仿真也不可信)。
六、ROM、RAM和FIFO的区别
1.ROM有地址,只能读而不能写。用初始化文件mif/ceo将内容存进去,读取不会使得数据减少消失。
2.RAM有地址,可以进行寻址读写,数据写进去后,读取不会使得数据减少消失。
3.FIFO没有地址,只能是先进先出,数据写进去后,读取会使得数据减少消失,读一个少一个。
参考资料:
[1]威三学院FPGA教程
[2]小梅哥FPGA教程
IP核——RAM的更多相关文章
- 用嵌入式块RAM IP核配置一个双口RAM
本次设计源码地址:http://download.csdn.net/detail/noticeable/9914173 实验现象:通过串口将数据发送到FPGA 中,通过quartus II 提供的in ...
- 第7讲 SPI和RAM IP核
学习目的: (1) 熟悉SPI接口和它的读写时序: (2) 复习Verilog仿真语句中的$readmemb命令和$display命令: (3) 掌握SPI接口写时序操作的硬件语言描述流程(本例仅以写 ...
- SPI和RAM IP核
学习目的: (1) 熟悉SPI接口和它的读写时序: (2) 复习Verilog仿真语句中的$readmemb命令和$display命令: (3) 掌握SPI接口写时序操作的硬件语言描述流程(本例仅以写 ...
- 7系列高速收发器总结 GTP IP核使用篇
上一篇7系列收发器博文讲解了GTP IP核的基本配置,本文继续分析如何将它使用起来.生成IP核后打开example design,先看看工程中包含的文件结构. 顶层文件下包含了gtp ip核系统顶层文 ...
- Vivado中xilinx_BRAM IP核使用
Vivado2017.2 中BRAM版本为 Block Memory Generator Specific Features 8.3 BRAM IP核包括有5种类型: Single-port RA ...
- EMAC IP 核
在有线连接的世界里,以太网(Ethernet)无所不在.以太网具有各种速度模式.接口方式.以及灵活的配置方式.现在的以太网卡都是10/100/1000Mbps自适应网卡.以太网的物理层(PHY)通常使 ...
- IP核——FIFO
一.Quartus 1.打开Quartus ii,点击Tools---MegaWizard Plug-In Manager 2.弹出创建页面,选择Creat a new custom megafunc ...
- modelsim 独立仿真vivado的IP核及仿真脚本
Modelsim独立仿真vivado的IP 最近一直在做local dimming项目的FPGA硬件实现,算法的其中一步就是直方图统计,即数字图像的某一灰度级的像素数,这个直方图的源码找了半天才搞到, ...
- 调用altera IP核的仿真流程—下
调用altera IP核的仿真流程—下 编译 在 WorkSpace 窗口的 counter_tst.v上点击右键,如果选择Compile selected 则编译选中的文件,Compile All是 ...
随机推荐
- httpd.exe你的电脑中缺失msvcr110.dll怎么办(WIN2008服务器环境装WAMP2.5出现的问题)
httpd.exe你的电脑中缺失msvcr110.dll怎么办 去微软官方下载相应的文件 1 打开上面说的网址 Download and install, if you not have it alr ...
- 梯形法求解常微分方程(c++)
#include<iostream> #include<iomanip> using namespace std; int main() { double x,y,yn,h,t ...
- Ubuntu 16.04与Win10双系统双硬盘安装图解
一.先做准备工作.建议:在当前系统所在的硬盘上,留一片空的主分区安装Ubuntu系统. 2.划分多大的空间够?安装的过程中需要涉及到分区,为了以免日后重装,我的建议是如下分区:1).5G,主分区,空间 ...
- SQL多个逗号分开的字段值 取对应的数据名称信息
字段值 函数实现: )) ) as begin set @strs=','+@strs+',' ) ) set @str2='' declare SyncOrderCursor cursor for ...
- Spring cloud微服务安全实战-7-8ELK+SpringBoot环境搭建
采集不可聚合的离散的.日志信息的e ELK是三个系统的简称 LogStash:用来做日志的收集.过滤.格式转换 Kibana:和普罗米修斯的grafana一个意思.主要用来展示数据. 用docker来 ...
- iOS - 点击UIButton不变灰,button的image不变灰
要想让uibutton点击不变灰 初始化的时候就不能 UIButton *button = [[UIButton alloc]init]; 初始化的时候酱紫,可以保证button点击时不变灰 UIBu ...
- docker search mysql Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
1.docker search mysql 报错 [root@localhost usr]# docker search mysqlCannot connect to the Docker daemo ...
- Python - Django - AJAX 实现 POST 请求
index.html: <input type="text" id="i1">+ <input type="text" i ...
- 网页视频直播、微信视频直播技术解决方案:EasyNVR与EasyDSS流媒体服务器组合之区分不同场景下的直播接入需求
背景分析 熟悉EasyNVR产品的朋友们都知道,EasyNVR不仅可以独成体系,而且还可以跟其他系列产品相配合,形成各种不同类型的解决方案,满足各种不同应用场景的实际需求.针对很多设备现场没有固定公网 ...
- EasyNVR网页无插件播放摄像机RTSP流是如何调取接口在Web页实现多窗口同时直播的
背景需求 在互联网飞速发展的时代,开发者常会说的一个词就是"跨平台".自从移动端的用户需求越来越大,H5逐渐发展,跨平台似乎已经成为了软件开发不可或缺的技术.EasyNVR互联网直 ...