一、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的更多相关文章

  1. 用嵌入式块RAM IP核配置一个双口RAM

    本次设计源码地址:http://download.csdn.net/detail/noticeable/9914173 实验现象:通过串口将数据发送到FPGA 中,通过quartus II 提供的in ...

  2. 第7讲 SPI和RAM IP核

    学习目的: (1) 熟悉SPI接口和它的读写时序: (2) 复习Verilog仿真语句中的$readmemb命令和$display命令: (3) 掌握SPI接口写时序操作的硬件语言描述流程(本例仅以写 ...

  3. SPI和RAM IP核

    学习目的: (1) 熟悉SPI接口和它的读写时序: (2) 复习Verilog仿真语句中的$readmemb命令和$display命令: (3) 掌握SPI接口写时序操作的硬件语言描述流程(本例仅以写 ...

  4. 7系列高速收发器总结 GTP IP核使用篇

    上一篇7系列收发器博文讲解了GTP IP核的基本配置,本文继续分析如何将它使用起来.生成IP核后打开example design,先看看工程中包含的文件结构. 顶层文件下包含了gtp ip核系统顶层文 ...

  5. Vivado中xilinx_BRAM IP核使用

     Vivado2017.2 中BRAM版本为 Block Memory Generator Specific Features  8.3 BRAM IP核包括有5种类型: Single-port RA ...

  6. EMAC IP 核

    在有线连接的世界里,以太网(Ethernet)无所不在.以太网具有各种速度模式.接口方式.以及灵活的配置方式.现在的以太网卡都是10/100/1000Mbps自适应网卡.以太网的物理层(PHY)通常使 ...

  7. IP核——FIFO

    一.Quartus 1.打开Quartus ii,点击Tools---MegaWizard Plug-In Manager 2.弹出创建页面,选择Creat a new custom megafunc ...

  8. modelsim 独立仿真vivado的IP核及仿真脚本

    Modelsim独立仿真vivado的IP 最近一直在做local dimming项目的FPGA硬件实现,算法的其中一步就是直方图统计,即数字图像的某一灰度级的像素数,这个直方图的源码找了半天才搞到, ...

  9. 调用altera IP核的仿真流程—下

    调用altera IP核的仿真流程—下 编译 在 WorkSpace 窗口的 counter_tst.v上点击右键,如果选择Compile selected 则编译选中的文件,Compile All是 ...

随机推荐

  1. 使用terraform 生成自签名证书

    terraform 是一个很不错的基础设施工具,我们可以用来做关于基础设施部署的事情,可以实现基础设施即代码 以下演示一个简单的自签名证书的生成(使用tls provider) main.tf 文件 ...

  2. HTML相对路径和绝对路径

     一.相对路径 相对路径不带有盘符,通常是以HTML网页文件为起点,通过层级关系描述目标图像的位置. 相对于文件自身出发,就是相对路径. 主要有以下几种情况:   ①文件和图片(html文档)在同一个 ...

  3. Cogs 739. [网络流24题] 运输问题(费用流)

    [网络流24题] 运输问题 ★★ 输入文件:tran.in 输出文件:tran.out 简单对比 时间限制:1 s 内存限制:128 MB «问题描述: «编程任务: 对于给定的m 个仓库和n 个零售 ...

  4. 洛谷P4047 [JSOI2010]部落划分题解

    洛谷P4047 [JSOI2010]部落划分题解 题目描述 聪聪研究发现,荒岛野人总是过着群居的生活,但是,并不是整个荒岛上的所有野人都属于同一个部落,野人们总是拉帮结派形成属于自己的部落,不同的部落 ...

  5. 忽略 IDEA 文件

    IntelliJ IDEA .idea *.iml /WebRoot/WEB-INF/classes

  6. 【大数据】分布式文件系统HDFS 练习

    作业要求来自于https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3292 利用Shell命令与HDFS进行交互 以”./bin/dfs d ...

  7. 【CS224n】Lecture8 Notes

    注:这是2017年课程的lecture8.一直都在用RNN,但是对它内部的构造不甚了解,所以这次花了一个下午加一个晚上看了CS224n中关于RNN的推导,不敢说融会贯通,算是比以前清楚多了.做个笔记, ...

  8. 【Qt开发】vs2017+qt5.x编译32位应用

    概述 最近有同学私信我,问如何使用vs2017+qt5.10编译出32位的应用,需要使用msvc2017_x86的插件,然而qt官网并没有提供,只能使用源码编译生成msvc2017_x86插件,使用n ...

  9. em,rem,px的区别,以及实现原理?

    px像素(Pixel).相对长度单位.像素px是相对于显示器屏幕分辨率而言的.em是相对长度单位.相对于当前对象内文本的字体尺寸举个例子:比如说当前容器`font-size:16px;`则`1em`就 ...

  10. qtcreator 添加 cppreference 离线文档

    https://en.cppreference.com/w/File:qch_book_20190607.zip 下载后放到 D:\Qt\Qt5.10.0\Docs\Qt-5.10.0目录下, 并在q ...