FPGA单端口RAM——IP核

news2024/10/5 16:20:49

文章目录

  • 前言
  • 一、RAM简介
    • 1、随机存储器IP核分类
      • 1、RAM IP核
      • 2、ROM IP核
    • 2、RAM IP核
  • 二、IP核配置步骤
  • 三、源码
    • 1、ram_rw驱动文件
    • 2、ip_1port_ram顶层文件
    • 3、仿真文件
    • 4、仿真波形
  • 四、SignalTap II在线调试
  • 五、总结
  • 六、参考资料


前言

环境:
1、Quartus18.1
2、vscode
3、板子型号:原子哥开拓者2(EP4CE10F17C8)
要求:
调用RAM IP核进行单端口RAM的读写数据。


一、RAM简介

RAM(Random Access Memory),即随机存储器。它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据,其读写速度是由时钟频率决定的。RAM 主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。

1、随机存储器IP核分类

在Cyclone IV 器件中,具有嵌入式存储器结构,嵌入式存储器结构由一系列M9K存储器模块进行配置,可以实现各种存储器功能,例如:RAM、移位寄存器、ROM以及FIFO缓冲器。

1、RAM IP核

RAM 是一种随机存取存储器,不仅仅可以存储数据,同时支持对存储的数据进行修改。

2、ROM IP核

是一种只读存储器,也就是说,在正常工作时只能读出数据,而不能写入数据。

  • 注意:

这两种存储器使用的资源都是 FPGA 的内部嵌入式 RAM 块,只不过 ROM IP 核只用到了嵌入式 RAM 块的读数据端口。

2、RAM IP核

Altera 推出的 RAM IP 核分为两种类型:单端口 RAM双端口 RAM。单端口 RAM 只有一组地址线,这组地址线控制着写数据端口和读数据端口,而双端口 RAM 具有两组地址线,这两组地址线分别控制着写数据端口和读数据端口。

在这里插入图片描述

  • 端口描述:

data:RAM 写数据端口;
address:RAM 读写地址端口,对于单口 RAM 来说,读地址和写地址共用同一组地址;
wren:写使能信号,高电平有效;
byteena:字节使能控制,该功能屏蔽了输入数据,这样仅写入数据中指定字节,未被写入的字节保留之前写入的值。当写入数据的位宽为 16 位、18 位、32 位和 36 位时,M9K 模块将支持字节使能,wren 信号以及字节 byteena 信号一起控制 RAM 模块的写操作。byteena 信号在 RAM IP 核创建过程中是可选的,可选择是否使用字节使能控制功能。
addressstall:地址时钟使能控制,当 addressstall 信号为高电平时,有效地址时钟使能就会保持之前的地址。addressstall 信号在 RAM IP 核创建过程中是可选的,可选择是否使用地址使能控制功能。
clockena:时钟使能控制,高电平有效;
rden:读使能信号,高电平有效;
aclr:异步复位信号,高电平有效;
q:从 RAM 中读出的数据;

输入与输出时钟模式下,输入时钟控制存储器模块的所有输入寄存器,输出时钟控制存储器模块的所有输出寄存器。只有一个时钟信号的情况下,一个时钟控制所有寄存器。

二、IP核配置步骤

  • 添加IP核:
    在这里插入图片描述
  • 双击后弹出:
    在这里插入图片描述

写入IP名、路径、语言等信息。

  • 参数配置:
    在这里插入图片描述

1、“How wide should the ‘q’ output bus be?”:用于指定输出数据端口的位宽,我们这里保持默认,选择 8bit;
2、“How many 8-bit words of memory?”:用于指定存储器的容量大小,我们这里选择存储容量为32words;
3、“What should the memory block type be?”:用于指定实现存储器使用的存储块类型,具体可选值与使用的 FPGA 芯片型号有关,一般选择默认 AUTO 就可以了;
4、“What clocking method would you like to use?”:用于指定使用的时钟模式,可选择单时钟和双时钟,一般对于单口 ram 选择单时钟就可以了。点击next。

  • next过后:
    在这里插入图片描述
  • next:
    在这里插入图片描述
  • next:
    在这里插入图片描述
  • next:
    在这里插入图片描述
  • next:
    在这里插入图片描述
  • 点击finish过后点击yes生成IP并加入到工程:

在这里插入图片描述

  • 效果:
    在这里插入图片描述

IP核简介及PLL_IP核的调用这是我的第一篇有关IP核的写的比较详细,还写了如何重新对IP核进行修改的操作。

三、源码

我们虽然配置了IP核但我们仍然需要写驱动文件、顶层文件对IP核进行调用。

1、ram_rw驱动文件

module ram_rw (
    input               clk,
    input               rst_n,
    input  [7:0]        ram_rd_data,//读数据

    output              ram_rw_en,//写使能
    output              ram_rd_en,//读使能
    output  reg [4:0]   ram_addr,//读写地址
    output  reg [7:0]   ram_wr_data//写数据
);
reg [5:0] rw_cnt;//读写控制器
//高电平操作
//rw_cnt 计数范围在 0~31,ram_wr_en 为高电平;32~63 时,ram_wr_en 为低电平
assign ram_rw_en = ((rw_cnt >= 6'd0) && (rw_cnt <= 6'd31) && rst_n) ? 1'b1 :1'b0;
//rw_cnt 计数范围在 32~63,ram_rd_en 为高电平;0~31 时,ram_rd_en 为低电平
assign ram_rd_en = ((rw_cnt >= 6'd32) && (rw_cnt <= 6'd63)) ? 1'b1 :1'b0;
//0~63的计数器
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        rw_cnt <= 6'd0;
    else if(rw_cnt == 6'd63)
        rw_cnt <= 6'd0;
    else 
        rw_cnt <= rw_cnt +1'b1;
end
//读写控制器计数范围:0~31 产生 ram 写使能信号和写数据信号,
//读使能信号也已产生,读数据信号由input信号引入
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        ram_wr_data <= 8'd0;
    else if(rw_cnt >= 6'd0 && rw_cnt <= 6'd31)
        ram_wr_data <= ram_wr_data +8'd1;
    else 
        ram_wr_data <= 8'd0;
end
//控制读写地址范围
always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        ram_addr <= 5'd0;
    else if(ram_addr == 5'd31)
        ram_addr <= 5'd0;
    else
        ram_addr <= ram_addr + 1'd1;
end
endmodule

2、ip_1port_ram顶层文件

module ip_1port_ram(
    input       sys_clk ,
    input       sys_rst_n

);
wire        ram_wr_en       ;//写使能
wire        ram_rd_en       ;//读使能
wire [4:0]  ram_addr        ;//读写地址
wire [7:0]  ram_wr_data     ;//ram写数据

wire [7:0]  ram_rd_data     ;//ram读数据
//ram读写控制模块
ram_rw ram_rw_inst(
    .clk            (sys_clk),
    .rst_n          (sys_rst_n),
    .ram_rd_data    (ram_rd_data),//读数据

    .ram_rw_en      (ram_wr_en  ),//写使能
    .ram_rd_en      (ram_rd_en  ),//读使能
    .ram_addr       (ram_addr   ),//读写地址
    .ram_wr_data    (ram_wr_data)//写数据
);   
ram ram_inst(
    .address    (ram_addr),
	.clock      (sys_clk),
	.data       (ram_wr_data),
	.rden       (ram_rd_en),
	.wren       (ram_wr_en),
	.q          (ram_rd_data)
);   
endmodule

3、仿真文件

`timescale 1ns/1ns
module ip_1port_ram_tb();

parameter T = 20;

reg   sys_clk;
reg   sys_rst_n;

initial begin
    sys_clk   = 1'b0;
    sys_rst_n = 1'b0;
    #(T+1)
    sys_rst_n = 1'b1;
    #(3000)
    $stop;
end

always #(T/2) sys_clk = ~sys_clk;

ip_1port_ram ip_1port_ram_tb_inst(
    .sys_clk        (sys_clk),
    .sys_rst_n      (sys_rst_n)
);

endmodule

4、仿真波形

  • 写状态的波形:
    在这里插入图片描述
  • 分析:

ram_wr_en 信号拉高,ram_rd_en 信号拉低,说明此时是对 ram 进行写操作。
ram_wr_en 信号拉高之后,地址和数据都是从 0 开始累加,也就说当 ram 地址为 0 >时,写入的数据也是 0;当 ram 地址为 1 时,写入的数据也是 1,我们总共向 ram >中写入 32 个数据。

  • 读状态波形:
    在这里插入图片描述
  • 分析:

ram_rd_en 信号拉高,ram_wr_en 信号拉低,说明此时是对 ram 进行读操作。
ram_rd_en(读使能)信号拉高之后,ram_addr 从 0 开始增加,也就是说从 ram的>地址 0 开始读数据;ram中读出的数据 ram_rd_data 在延时一个时钟周期之后,开始输出数据,输出的数据为 0,1,2……结果正确

四、SignalTap II在线调试

具体调试流程看:SignalTap II 软件使用步骤

  • 读状态:
    在这里插入图片描述

在读数据的状态下,读的数据都是延后一个时钟周期的数据,与仿真一致.

  • 写状态:
    在这里插入图片描述

写状态下,ram_wr_en 信号拉高之后,地址和数据都是从 0 开始累加,也就说当 ram 地址为 0 >时,写入的数据也是 0;当 ram 地址为 1 时,写入的数据也是 1.与仿真一致.实验结果正确.


五、总结

IP核的配置总体来说并不难,但需要我们一步步的细心配置,代码部分只需要对IP的操作为主。就是读数据哪里的波形,为什么我们的写数据没有时钟周期的延时,反而在读数据的时候会有一个时钟的延时。有没有懂佬解惑下?

六、参考资料

以上资料均来自正点原子的教学视频或开拓者2开发教程:
原子官方

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/768369.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leetcode-每日一题【1019.链表中的下一个更大结点】

题目 给定一个长度为 n 的链表 head 对于列表中的每个节点&#xff0c;查找下一个 更大节点 的值。也就是说&#xff0c;对于每个节点&#xff0c;找到它旁边的第一个节点的值&#xff0c;这个节点的值 严格大于 它的值。 返回一个整数数组 answer &#xff0c;其中 answer[…

Servlet的监听器

Servlet常用的监听器 ServletContextAttributeListener 用来感知ServlerContext对象属性变化&#xff0c;比如添加或删除属性变化 ServletContextListener 用来感知ServlerContext对象的创建和销毁的 ServletRequestListener 可以用来监听感知ServletRequest对象的创建和销毁的…

大语言模型(LLM)评估综述

论文地址&#xff1a;https://arxiv.org/abs/2307.03109 Github地址&#xff1a;https://github.com/MLGroupJLU/LLM-eval-survey 一 、背景 随着ChatGPT和GPT-4的推出&#xff0c;大型语言模型&#xff08;LLM&#xff09;在学术界和工业界的热度日益升高&#xff0c;这主要…

优雅的设计测试用例

⭐️前言⭐️ 入职以后接触到了公司的具体业务&#xff0c;提升了设计测试用例的能力&#xff0c;于是沉淀出这篇文档与大家分享。 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主将持续更新学习记录收获&…

Acwing.905 区间选点(贪心)

题目 给定N个闭区间[a,bi]&#xff0c;请你在数轴上选择尽量少的点&#xff0c;使得每个区间内至少包含一个选出的点。输出选择的点的最小数量。 位于区间端点上的点也算作区间内。 输入格式 第一行包含整数N&#xff0c;表示区间数。 接下来N行&#xff0c;每行包含两个整数…

Linux内核《CPU负载计算》

目录 前言一、什么是CPU负载&#xff1f;二、如何计算CPU负载三、计算CPU负载的一个脚本四、top命令详解 前言 在实际的产品开发中&#xff0c;我们往往需要关注CPU的负载&#xff0c;确保程序可以长久稳定的运行&#xff0c;并且能够重复发挥SOC的性能。Linux中提供了一些命令…

ArrayList和LinkedList

ArrayList的注意事项 1、在ArrayList中可以放任意元素&#xff0c;包括空值&#xff0c;任何元素&#xff0c;且可重复添加。 2、ArrayList底层是由数组来实现数据存储的 3、ArrayList基本等同于Vector&#xff0c;除了ArrayList是线程不安全(执行效率高),看源码 在多线程的…

【Linux系列P7】进度条小程序的深度解剖(细节满满)

​​​​​ ​ 前言 大家好吖&#xff0c;欢迎来到 YY 滴 Linux系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过Linux的老铁&#xff0c;主要内容含 欢迎订阅 YY滴Linux专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; 订阅专栏阅读&am…

SpringBoot项目中MVC使用--【SB系列之010】

SpringBoot系列文章目录 SpringBoot 的项目编译即报错处理–SB系列之001 —第一部的其它章节可以通过001链接 SpringBoot项目中WEB页面放哪里–【SB系列之008】 SpringBoot项目中WEB与Controller的联系–【SB系列之009】 ———————————————— 文章目录 SpringBoo…

线程池学习(五)线程工厂、线程池工厂

Executors 定义的Executor, ExecutorService, ScheduledExecutorService, ThreadFactory和Callable类的工厂和实用程序方法&#xff0c;我们称为线程池工厂。ThreadFactory 为定制化创建新线程的对象,我们称为线程工厂 前面几期的学习中&#xff0c;我已经初步会使用线程池了&…

用于公司文件防泄密用的保密软件(企业数据防泄密软件)

防止公司文件泄露是指采取各种措施和方法&#xff0c;以防止公司的敏感和机密文件被未经授权的人员获取、泄露或滥用的行为。 这些文件可能包含公司的商业机密、客户数据、财务信息、研发成果等重要资料&#xff0c;如果泄露给竞争对手、黑客或其他恶意人员&#xff0c;可能会对…

未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序。

offiice64位的按装名字短的&#xff0c;office32位的安装名字长的 安装32位的AccessDatabaseEngine.exe&#xff0c;如果使用64位office点击安装32位access时提示无法安装&#xff0c;此时需要&#xff1a; 1.WINR打开运行&#xff0c;输入CMD&#xff0c;进入安装包文件夹 …

AHD模拟高清方案汇总及国产替代方案

由于模拟高清方案对比LVDS数字高清方案在降本、远距离传输的优势明显&#xff0c;及实现方案相对简单&#xff0c;模拟相机一直在车载和安防监控产品上有着较重要的市场地位。伴随着ZM贸易战和境外疫情影响愈来愈趋于严重化&#xff0c;原有外来品牌公司模拟高清方案在产品交期…

LeetCode 75 第五题(345)反转字符串中的元音字母

题目: 示例: 分析: 给一个字符串,将里面的元音字母反转,并且保持非元音字母不变(包括顺序). 字符串反转类型的题,我们都可以使用双指针来解决:定义首尾指针,分别向中间靠拢,直到首尾指针都指向了元音字母,然后交换首尾指针所指的字母,如此不会影响到非元音字母,同时也将元音字…

【4】Vite+Vue3左右容器中相同属性的元素内容自动对齐

在当今前端开发的领域里&#xff0c;快速、高效的项目构建工具以及使用最新技术栈是非常关键的。ViteVue3 组合为一体的项目实战示例专栏将带领你深入了解和掌握这一最新的前端开发工具和框架。 作为下一代前端构建工具&#xff0c;Vite 在开发中的启动速度和热重载方面具有突…

【运维小知识】(四)——linux常用命令

运维专栏&#xff1a;运维小知识 目录 1.&#x1f341;&#x1f341;用mv命令修改文件名 2.&#x1f343;&#x1f343;创建及删除文件夹即文件夹下所有文件 3.&#x1f342;&#x1f342;移动文件夹并重命名 4.&#x1f33f;&#x1f33f;复制文件 5.&#x1f344;&#x…

Redis相关配置(3)

⭐ 作者简介&#xff1a;码上言 ⭐ 代表教程&#xff1a;Spring Boot vue-element 开发个人博客项目实战教程 ⭐专栏内容&#xff1a;个人博客系统 ⭐我的文档网站&#xff1a;http://xyhwh-nav.cn/ 文章目录 Redis相关配置1、units2、Include3、loadmodule 加载模块4、NET…

MySQL-多表设计-一对多

多表的设计-概述 项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在着各种联系&#xff0c;基本上分为三种&#xff1a; 一…

【PostgreSQL内核学习(二)—— 查询分析】

查询分析 查询处理查询分析查询处理与查询分析的关系查询分析执行流程Lex和YaccLex&#xff1a;Yacc&#xff1a;词法分析工具Lex语法分析工具Yacc使用Lex和Yacc的案例 词法和语法分析以SELECT语句为例讲解 PostgreSQL中查询语句如何被解析并生成分析树。 语义分析 声明&#x…

【Vue面试题系列】四

VNode有哪些属性&#xff1f; Vue内部定义的Vnode对象包含了以下属性&#xff1a; __v_isVNode: true&#xff0c;内部属性&#xff0c;有该属性表示为Vnode __v_skip: true&#xff0c;内部属性&#xff0c;表示跳过响应式转换&#xff0c;reactive转换时会根据此属性进行判断…