FPGA知识基础之--存储器知识点总结以及基于ip核的简单双端口RAM的实现和仿真(附RTL代码和Testbench代码)

news2024/9/22 21:23:24

目录

  • 前言
  • 一、存储器的分类
  • 二、实验任务
  • 三 、简单(伪)双端口
  • 四、程序设计
    • 4.1 模块
    • 4.2 时序分析
    • 4.3 RTL代码
      • ram_wr 写模块
      • 2.ram_rd 写模块
      • 3.top模块
  • 五、仿真


前言

笔者在最近的存储器学习时,遇到了一些问题,为此笔者用本篇博客来记录一下有关存储器的一些知识点


一、存储器的分类

在FPGA中,存储器主要分为两类。RAM和ROM,网上对其的分类有很多,比较杂乱,为此笔者做了一张mindmap,希望能使得知识框架更为清晰

在这里插入图片描述
笔者主要总结了关于一些主流存储器的功能以及基本功能介绍

二、实验任务

本次笔者将设计一个深度为64,宽度为6的伪双向端口RAM

三 、简单(伪)双端口

关于这方面的介绍,笔者必要参考了xlinx的官方文档pg058,在此笔者给出自己的一些学习经验

在这里插入图片描述
除去纠错端口后,其余的端口与单端口一样,为此读者不做过多阐述

重难点!
关于三种工作模式

1、Write First Mode

在这里插入图片描述
笔者将xlinx文档资料中关于写优先这一方面的时序找出来了,应该还是很好理解的
写优先即为写入的数据同时放入地址和输出,而原先地址的数据则被覆盖,例如 bb,cc,里面的内容被覆盖为了1111,2222

2、Read First Mode
在这里插入图片描述
读优先则会将地址上原先的数据给输出,然后将写入数据放到地址当中。

3、NO Change

在这里插入图片描述

这个模式则不管输入的数据,输出数据一直为写使能信号来之前的前一个信号对应的地址
希望读者能理解这三种模式,本次实验我们采取第三种No change模式

四、程序设计

4.1 模块

在这里插入图片描述
本次实验需要用到三个模块,读模块,写模块,以及xlinx自带的RAMip模块
三个模块之间的关系如图

4.2 时序分析

在这里插入图片描述

需要注意的是,笔者引入了一个flag变量,来消除读写冲突的问题

4.3 RTL代码

ram_wr 写模块

module ram_wr (
input                        clk,
input                        rst_n,


output       reg             ram_wr_en,
output                       ram_wr_we,
output       [7:0]           ram_wr_data, //ram深度8
output      reg [5:0]        ram_wr_addr,  //ram宽度6
output       reg       [5:0] flag
);



assign     ram_wr_we  =  ram_wr_en; //这是写模块,使能信号拉高之后,即进入写模式

assign ram_wr_data = {2'b0,ram_wr_addr} ;

always @(posedge clk or negedge rst_n) begin  //使能信号拉高
    if(!rst_n)
        ram_wr_en <= 1'b0;
    else
        ram_wr_en <= 1'b1;
end

always @(posedge clk or negedge rst_n) begin  //为ram_wr_addr写入数据
    if(!rst_n)
        ram_wr_addr <= 6'b0;
    else if(ram_wr_en && ram_wr_addr < 6'd63)
        ram_wr_addr <= ram_wr_addr + 1;
    else 
        ram_wr_addr <= 6'b0; 
end

always @(posedge clk or negedge rst_n) begin   //为了避免读写冲突,ram_wr_addr到31之后,进入读模式
    if(!rst_n)
        flag <= 6'd0;
    else if(ram_wr_addr == 6'd31)
        flag <=  6'd1;
    else 
        flag <=  flag;
    
end



    
endmodule

2.ram_rd 写模块

module ram_rd(
input                   clk,
input                   rst_n,
input    [7:0]          ram_rd_data,
input                   flag,


output                  ram_rd_en,
output    reg [5:0]     ram_rd_addr
);

assign ram_rd_en = flag;  //使能信号和flag信号同步

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        ram_rd_addr <= 6'd0;
    else if(ram_rd_en && ram_rd_addr <= 6'd63)
        ram_rd_addr <= ram_rd_addr + 1; // 地址赋值,在0~63之间循环
    else
        ram_rd_addr <= 0;

end

endmodule

3.top模块

module ip_2port_ram(
input       sys_clk,
input       sys_rst_n   
);

wire                        ram_wr_en;
wire                        ram_wr_we;
wire          [7:0]         ram_wr_data; 
wire          [5:0]         ram_wr_addr;


wire          [7:0]         ram_rd_data;
wire                        ram_rd_en;
wire          [5:0]         ram_rd_addr;
wire                        flag;

ram_wr  u_ram_wr(
   .clk                 (sys_clk),       
   .rst_n               (sys_rst_n),
   .ram_wr_en           (ram_wr_en),
   .ram_wr_we           (ram_wr_we),
   .ram_wr_data         (ram_wr_data),
   .ram_wr_addr         (ram_wr_addr),
   .flag                (flag)
);

ram_rd   u_ram_rd(
        .clk            (sys_clk),
        .rst_n          (sys_rst_n),
        .ram_rd_data    (ram_rd_data),
        .flag           (flag),
        .ram_rd_en      (ram_rd_en),
        .ram_rd_addr    (ram_rd_addr)
);



blk_mem_gen_0 u_blk_mem_gen_0 (
  .clka                 (sys_clk),    // input wire clka
  .ena                  (ram_wr_en),      // input wire ena
  .wea                  (ram_wr_we),      // input wire [0 : 0] wea
  .addra                (ram_wr_addr),  // input wire [5 : 0] addra
  .dina                 (ram_wr_data),    // input wire [7 : 0] dina
  .clkb                 (sys_clk),    // input wire clkb
  .enb                  (ram_rd_en),      // input wire enb
  .addrb                (ram_rd_addr),  // input wire [5 : 0] addrb
  .doutb                (ram_rd_data)  // output wire [7 : 0] doutb
);







endmodule

在此读者做一下说明,为了使用xlinx自带的RAMip核模块,我们需要提前做一点设置

在vivado的ip库中搜索ram,找到block memory generator,并进行如下设置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
其余保持默认
设置好ip核后,可找到xlinx提供的例化模板,根据自己的模块名代入即可
在这里插入图片描述

五、仿真

Testbench代码

`timescale	1ns/1ns //仿真的单位/仿真的精度s
module tb_ip_2port_ram();

parameter CLK_PERIOD = 20;

reg 		sys_clk;  //周期20ns
reg 		sys_rst_n; 


initial begin
	sys_clk <= 1'b0;
	sys_rst_n <=1'b0;
	#200 
	sys_rst_n <= 1'b1;
end

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


 
ip_2port_ram   u_ip_2port_ram (
    .sys_clk     (sys_clk),
	.sys_rst_n   (sys_rst_n) 
 );
 
 
 
 endmodule
 
 

模块仅有两个激励,所以仿真代码还是很好写的

vivado和modelsim联合仿真波形

在这里插入图片描述

在这里插入图片描述
代码与时序验证成功,结果正确


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

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

相关文章

ICM-20948芯片详解(9)

接前一篇文章&#xff1a;ICM-20948芯片详解&#xff08;8&#xff09; 六、寄存器详解 2. USER BANK 0寄存器详述 &#xff08;6&#xff09;INT_PIN_CFG 参考代码&#xff1a; #define ICM20948_INT_PIN_CFG 0x0F &#xff08;7&#xff09;INT_ENABLE 参考代码&#x…

我有10台120kw的直流充电桩,赢利了多少钱?我列出所有成本和多少利润,这里要算上政府补贴。【慧哥开源充电桩平台 HZCOS-chargeOS-cloud】

特别申明&#xff1a;仅仅代表个人观点&#xff0c;错的地方虚心请教学习&#xff0c;各位手下留情 拥有的10台120kW直流充电桩的盈利情况&#xff0c;并考虑到政府补贴&#xff0c;具体数字需要根据实际情况调整。 成本计算 初始投资成本 充电桩成本&#xff1a;每台120kW直…

利用Llama 3 API实现盈利:细节解析

随着人工智能技术的快速发展,基于大模型的服务成为了众多初创企业关注的焦点。Llama 3 API作为一种强大的语言模型接口,为小型公司提供了利用先进AI技术的机会。本文将探讨这些小公司如何通过Llama 3 API实现盈利,并分析其中的关键因素。 一、Llama 3 API性能概览 批处理输…

网络药理学:分子对接之一:macos上MOE和Autodock和PyMol和gromacs的下载、PDB数据库使用、gromacs能量最小化

MOE下载 别想了&#xff0c;要钱的。而且不算是主流软件&#xff0c;过。 Autodock和Autodock tools下载 下载地址&#xff1a;https://autodock.scripps.edu/download-autodock4/ 如果你的电脑满足以下配置&#xff0c;那么推荐下载autodock GPU 操作系统&#xff1a;mac…

重磅!观测云荣获SOC 2 Type II鉴证报告

近日&#xff0c;观测云在数据安全和内控管理领域再获殊荣&#xff0c;成功获得全球四大会计师事务所之一的安永会计师事务所签发的SOC 2 Type II 鉴证报告。这一荣誉不仅是对观测云在相关领域卓越表现的认可&#xff0c;更是对其对客户承诺坚定性和执行力的有力证明。 观测云 …

软件设计之JavaScript(1)

软件设计之JavaScript(1) 【狂神说Java】JavaScript最新教程通俗易懂 学习内容&#xff1a; 软件开发技能点参照&#xff1a;软件开发&#xff0c;小白变大佬&#xff0c;这套学习路线让你少走弯路是认真的&#xff0c;欢迎讨论 软件开发技能点顺序参照&#xff1a;Java学习…

“前缀和”专题篇一

目录 【模版】前缀和 【模版】二维前缀和 寻找数组的中心下标 除自身以外数组的乘积 【模版】前缀和 题目 思路 这道题如果使用暴力解法&#xff0c;即针对每次查询&#xff0c;先算出前r个数的总和&#xff0c;然后再算出前l-1个数的总和&#xff0c;然后相减就得出本次查…

2.类和对象(上)

1. 类的定义 1.1 类定义格式 • class为定义类的关键字&#xff0c;Stack为类的名字&#xff0c;{ }中为类的主体&#xff0c;注意类定义结束时后面分号不能省略。类体中内容称为类的成员&#xff1a;类中的变量称为类的属性或成员变量; &#xff08;类和结构体非常像&#…

12-利用Excel创建IC类元件库

1.新建excel文件 2.找到模型向导 3.修改属性

技术速递|.NET Aspire 8.1 中面向云原生开发人员的新增功能!

作者&#xff1a;Mitch Denny 排版&#xff1a;Alan Wang 5 月份&#xff0c;我们向全世界发布了 .NET Aspire 的第一个正式版本。.NET 社区的热烈响应令我们深受鼓舞&#xff0c;在大家首次试用时&#xff0c;我们一直在积极倾听并与开发人员互动。 今天&#xff0c;我们很高…

EF Core连接PostgreSQL数据库

PostgreSQL数据库介绍 PostgreSQL是一个功能强大的开源对象关系型数据库管理系统&#xff08;RDBMS&#xff09;。最初于1986年在加州大学伯克利分校的POSTGRES项目中诞生&#xff0c;PostgreSQL以其稳定性、灵活性和扩展性而著称。它支持丰富的数据类型、复杂的查询、事务完整…

C语言进阶(3)

1.数组传参 一维数组传参的时候使用数组名&#xff0c;代表数组首元素的地址&#xff1b;函数接受时形参可以是数组形式&#xff0c;也可能是指针形式&#xff0c;数组形式比较简单数组怎么写&#xff0c;函数接受是就怎么接受,使用指针就要将指针类型写清楚&#xff0c;如下 …

一文搞懂MES、ERP、SCM、WMS、APS、SCADA、PLM、QMS、CRM、EAM及其关系

MES、ERP、SCM、WMS、APS、SCADA、PLM、QMS、CRM、EAM各个系统到底是什么意思&#xff1f;今天一文就给大家分享&#xff01; 在企业管理中&#xff0c;各种信息系统扮演着至关重要的角色&#xff0c;它们如同企业的神经系统&#xff0c;确保各个部分高效协同运作。 MES&#…

微信小程序项目开发【从0到1~入门篇】

创建第一个小程序 1、小程序简介2、第一个小程序&#xff1a;注册小程序开发账号3、第一个小程序&#xff1a;安装开发者工具3.1 了解微信开发者工具3.2下载安装3.3 扫描登录 4、创建小程序项目5、小程序代码的构成5.1json配置文件5.2WXML模板5.3WXSS样式5.4JS 逻辑交互 6、宿主…

HDMI线连接显示器后色彩灰暗问题解析与解决方案

随着科技的快速发展&#xff0c;HDMI线已成为连接电脑与显示器的重要工具。然而&#xff0c;当HDMI线连接显示器后&#xff0c;有时会遇到显示器色彩灰暗的问题。本文将针对这一问题进行深入解析&#xff0c;并提供相应的解决方案。 一、HDMI线连接显示器后色彩灰暗的原因 1. …

C++ SQL ORM

测试代码 // // Created by www on 2024/8/7. // #include "sqlitepp/database.h" #include "sqlitepp/condition.h"#include <iostream> using namespace sqlitepp; using namespace sqlitepp::literals;enum class test_enum {hello };void test…

Matplotlib | 绘制折线图

目录 简介安装 Matplotlib开始绘制简单折线图改变线的样式改变节点的样式添加图表文字改变坐标轴标签改变坐标数值范围绘制多条折线实践&#xff1a;绘制温度变化图 简介 折线图&#xff08;Line Chart&#xff09;&#xff0c;是一种以折线来呈现数据随时间变化而变化的图表。…

上翘机头设计确保了机器人在与杆子正面碰撞后,平稳从水平飞行状态重新调整为垂直飞行状态,进而用翅膀紧紧抱住杆子,实现稳定的栖息

带翼无人驾驶飞行器&#xff08;UAV&#xff09;因其出色的单位质量续航能力&#xff0c;特别适用于远距离任务&#xff0c;如送货、测绘和搜索救援。然而&#xff0c;与有翼飞行动物相比&#xff0c;它们在复杂结构上的着陆或栖息能力受限&#xff0c;难以执行检查、操作、监控…

for循环中的setTimeout的几种情况

for循环中的setTimeout的几种情况 在做js相关的题目时&#xff0c;经常会遇到以下几种容易混淆的setTimeout相关的题目&#xff1a; 第一种 for(var i0;i<10;i){setTimeout(console.log(i),0); }在这个代码片段中&#xff0c;setTimeout 的第一个参数是 console.log(i)&…

Qt QTableWidget 去除序号列

ui->tableWidget->verticalHeader()->setHidden(true);//垂直序列号&#xff08;表左侧&#xff09;ui.tableWidget->horizontalHeader()->setHidden(true);//水平序列号&#xff08;表上方&#xff09;删除后效果图&#xff1a;