当前位置: 首页 > news >正文

FPGA开发——IP核RAM的调用(双端口)

一、简介

在上一篇文章中我们对于单端口的RAM调用进行了一个简单的介绍和相关应用,在这篇文章当中我们对于双端口的RAM进行介绍和调用,在调用程度上来说,双端口RAM是单端口RAM的一个进阶。

双端口RAM分类

        简单双口 RAM:一组读数据和读地址线,一组写数据和写地址线,能同时进行读和写操作, 但不能同时对同一地址进行读和写操作。

        真双口 RAM:有两组读数据线与读地址线,两组写数据线与写地址线;能同时进行两个端口 读,能同时进行两个端口写,也能一个端口读同时另一个端口写。

在文章中我们就以简单双口RAM进行一个介绍。

二、双端口RAM的配置

这里双端口的调用和单端口的基本上是一样的,只不过参数啥的有点不一样。

1、双端口RAM选择

        如图所示,在 IP Catalog 的搜索栏中搜索 RAM,然后选择 RAM:2-PORT。(这里工程的创建就不仔细讲了)

2、RAM存放位置的选择

选择自己需要存放的文件目录。

3、RAM类型和存储类型选择

如下图所示,该界面配置的参数有:

方框①:这里就是前面说的简单双口RAM真双口RAM的选择,因为我们使用的是简单双口RAM,所以选择上面一个选项的一个读和一个写端口就行。

②:这里是数据存放的尺度,分别为字节存放和bit存放,这里根据自身需要进行选择。

然后点击 Next 进入下一界面。

4、数据存放容量、输入输出数据位宽和资源类型的选择 

如图所示:

方框①:这里是对于RAM存放数据的深度进行一个选择,也就是存放容量。这里根据需要直接进行选择就行。

方框②:这里就是对于输入输出数据的位宽进行配置,如果想要输入输出数据的位宽不同,那么就可以在这里进行设置,首先就是在选项处进行勾画,然后对于输入输出数据位宽进行一个设置,如果不需要的话这里保持默认不选就行。

方框③:这里就是对于RAM的资源构成进行一个选择,这里默认选择Auto就行,如果有特别需要也可以进行选择。 点击“Next”进入下一界面。

 5、时钟数量、读使能信号、以及写入数据位宽控制位的选择

如图所示:

方框①:在这进行时钟数量进行一个选择,分别是单一时钟、读时钟,写始终、输入始终,输出时钟,这里如果没有特殊需求,我们可以直接选择单一时钟就行,如果需要在写和读添加时钟的话就选择第二个选项,输入输出就选择第三个选项。

方框②:这就是对于读数据使用信号的一个配置,如果不需要读数据使能信号的话这里就不选。

方框③:这里就是对于RAM写入数据的位宽进行选择,为高电平有效,如果这个byteena_a信号为高,不管写入数据位宽有多大,最终都只会把低8位读入RAM中。不要求的话也可以不选。 点击“Next”进入下一界面。

6、输出数据的时钟寄存配置

        这里和前面一步的时钟数量的选择相互关联,如果在前面时钟选择时只选择一个是话,这里选不选都不影响最后的结果,因为不管是写入还是读出都是在使用同一个系统时钟。

        但如果前面的时钟选择了写入和读出分别使用不同的时钟或者输入输出使用不同的时钟,那么这里一定要进行选择。在图中,这个选项的作用就是把rdclok也就是读数据时的时钟和输出数据进行一个连接,这样输出就会按照如数据时钟的变化实时进行数据读取。相反,如果没有进行勾选,读取数据时就会默认根据系统时钟进行一个变化。

        这里需要注意一下,如果不注意会极大的影响在仿真时我们对于结果的判断。

7、初始化文件的选择

如下图所示,这里是初始化文件的一个选择,我们有相应的.mif或者.hex等文件,救选择下面一个选项,进行文件的一个选择就行。点击“Next”进入下一界面。

8、仿真库文件的选择

如下图所示,显示的是仿真库文件 altera_mf。无需其它操作,点击“Next”进入下一界面。

9、生成文件的选择

如下图所示,该页面为需要配置生成的文件。勾选 ram_inst.v 即可。ram_bb.v 可勾可不勾选。然后点击 finish。

 10、将文件添加到工程中

如下图所示,配置完成,点击“Yes”即可。

三、双端口RAM的调用

1、设计文件的编写

在trl文件夹中新建ip_ram.v文件,如图:

因为我们在前面配置中选择了不同的时钟,所以我们在这里通过pll产生两个不同的时钟给写和读信号。(这里对于pll的调用就不做具体介绍了,不清楚的小伙伴可以参考前面pll调用的文章,这里我们只使用了两个输出时钟,所以在进行pll配置时需要注意一下)。

    
//---------<模块及端口声名>-------------------------------------------
module ip_ram( input				clk			,input				rst_n		,input				rden    	,input               wden		,input               byteena 	,input		[6:0]   raddress	,input       [6:0]   waddress 	,input		[15:0]	din 		,output		[7:0]	dout	
);								 
//---------<参数定义>------------------------------------------------//---------<内部信号定义>--------------------------------------------
wire clk_75m;
wire clk_100m;
pll_1	pll_1_inst (.areset ( ~rst_n ),.inclk0 ( clk ),.c0 ( clk_75m ),.c1 ( clk_100m ),.locked ( locked_sig )
);ram_1	ram_1_inst (.byteena_a ( byteena ),//读低八位数据.data ( din ),//写入的数据.rdaddress ( raddress ),//读数据的地址.rdclock ( clk_75m ),//读的时钟.rden ( rden ),//读信号使能.wraddress ( waddress ),//写数据的地址.wrclock ( clk_100m ),//写的时钟.wren ( wden ),//写信号使能.q ( dout )//输出数据
);
endmodule

 2、测试文件的编写

在tb文件夹中新建tb_ram.v文件,如图:

在代码中我们对于写入数据位宽控制信号进行了赋1操作,所以在后面的波形仿真中我们应该可以看到值写入低八位数据。

`timescale 1ns/1nsmodule tb_ram();//激励信号定义 reg				clk		 ;reg				rst_n	 ;reg				rden     ;reg		        wden	 ;reg		        byteena  ;reg		[6:0]   raddress ;reg     [6:0]   waddress ;reg     [15:0]	din 	 ;
//输出信号定义	 wire	[7:0]		dout    ;//时钟周期参数定义	parameter		CLOCK_CYCLE = 20;   //模块例化
ip_ram   ip_ram_inst( /*input		 */	.clk		(clk	),/*input		 */	.rst_n		(rst_n	),/*input		 */	.rden    	(rden    ),/*input      */ .wden		(wden	),/*input      */ .byteena 	(byteena ),/*input	[6:0]*/ .raddress	(raddress),/*input [6:0]*/ .waddress 	(waddress),/*input [7:0]*/	.din 		(din 	),/*output[7:0]*/	.dout	    (dout	 )
);				//产生时钟initial 		clk = 1'b0;always #(CLOCK_CYCLE/2) clk = ~clk;//产生激励integer i;initial  begin rst_n = 1'b0;wden = 1'b0;rden = 1'b0;#(CLOCK_CYCLE*20);rst_n = 1'b1;byteena =1;#(20*100);//写入50个16位数据,使用byteena写入低八位for (i = 0;i<50;i=i+1) beginwden = 1'b1;waddress = 7'(i);din = 16'($random);byteena =1;@(posedge clk);wden=1'b0;end//读50个数据for (i = 0;i<50;i=i+1) beginrden = 1'b1;raddress = 7'(i);@(posedge clk);wden=1'b0;end //同读同写for (i = 0;i<5;i=i+1) beginwden = 1'b1;waddress = 7'(i);din = 16'($random);@(posedge clk);wden=1'b0;rden = 1'b1;raddress = 7'(i);@(posedge clk);wden=1'b0;end$stop;end    endmodule 

3、波形图仿真

图中我们可以看到最后写入的数据确实是低八位的数据。而最后读取的信号和写入的第八位信号是完全一致的。到这里双端口RAM的调用就结束了。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 轻闪PDF v2.14.9 解锁版下载及安装教程 (一款全能PDF转换器,支持自动补全标签)
  • 某通电子文档安全管理系统 CDGAuthoriseTempletService1接口SQL注入漏洞复现 [附POC]
  • MySQL——索引(二)创建索引(1)创建表的时候创建索引
  • 大模型与数据分析的融合:创新与发展的新机遇
  • java 程序包org.junit.jupiter.api不存在
  • skynet 连接redis
  • 迷你厨房迷你玩具视频素材去哪里找?迷你游戏视频素材
  • 在同一个地方ip地址会一样吗?深入解析网络地址的奥秘
  • Selenium + Python 自动化测试07(滑块的操作方法)
  • 记一次Windows使用virtualbox作为容器作为开发环境运行idea,致每一位windows下的开发者
  • Android网络安全:如何防止中间人攻击
  • 微前端场景下如何做样式隔离?
  • IP地址封装类(InetAddress类)
  • 清华大学在感前光学计算方向获得进展
  • 疯狂Java讲义_08_泛型
  • android图片蒙层
  • Java 多线程编程之:notify 和 wait 用法
  • Java|序列化异常StreamCorruptedException的解决方法
  • Javascript 原型链
  • JavaScript实现分页效果
  • java多线程
  • JAVA之继承和多态
  • Js基础知识(一) - 变量
  • nginx 配置多 域名 + 多 https
  • Node 版本管理
  • PhantomJS 安装
  • swift基础之_对象 实例方法 对象方法。
  • Terraform入门 - 3. 变更基础设施
  • Webpack入门之遇到的那些坑,系列示例Demo
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 对象引论
  • 飞驰在Mesos的涡轮引擎上
  • 复杂数据处理
  • 聊聊flink的BlobWriter
  • 面试总结JavaScript篇
  • 如何抓住下一波零售风口?看RPA玩转零售自动化
  • 深入浅出Node.js
  • 思否第一天
  • 小李飞刀:SQL题目刷起来!
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 移动端高清、多屏适配方案
  • #define与typedef区别
  • #stm32整理(一)flash读写
  • #window11设置系统变量#
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (1)虚拟机的安装与使用,linux系统安装
  • (k8s中)docker netty OOM问题记录
  • (NO.00004)iOS实现打砖块游戏(十二):伸缩自如,我是如意金箍棒(上)!
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (含笔试题)深度解析数据在内存中的存储
  • (三十五)大数据实战——Superset可视化平台搭建
  • **CI中自动类加载的用法总结
  • .md即markdown文件的基本常用编写语法