[米联客-XILINX-H3_CZ08_7100] FPGA程序设计基础实验连载-27浅谈XILINX BRAM的基本使用

news2024/11/25 2:45:35

软件版本:VIVADO2021.1

操作系统:WIN10 64bit

硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA

实验平台:米联客-MLK-H3-CZ08-7100开发板

板卡获取平台:https://milianke.tmall.com/

登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!

目录

1概述

2 BRAM RAM的应用形式

2.1单口ROM (Single-Port ROM)

2.2双口ROM(Dual-port ROM)

2.3单口RAM(Single-port RAM)

2.4简单双口RAM(Simple Dual-port RAM)

2.5真双口RAM(True Dual-port RAM)

3 BLOCK RAM的读写模式

3.1先写模式(Write First Mode)

3.2先读模式(Read First Mode)

3.3不变模式(No Change Mode)

4支持字节写入(BYTE Write)

5访问冲突 (Collision Behavior)

5.1异步时钟处理原则

5.2同步时钟处理原则

5.3简单的双端口RAM冲突

6输出寄存器

6.1通过无输出寄存器输出方式读取

6.2通过Primitives Output Register读取数据并实现rEad使能延迟

6.3使用两个流水线阶段读取数据的延迟

7添加BRAM IP

8读写BRAM代码

9仿真文件

10仿真结果


1概述

对于BRAM 详细的说明在XILINX 官方文档,pg058中有说明,我们这里仅对课程涉及的内容讲解。

Xlinx系列FPGA,包含两种RAM:Block RAM和分布式RAM(Distributed RAM),他们的区别在于,Block RAM是内嵌专用的RAM,而Distributed RAM需要消耗珍贵的逻辑资源组成。前者具有更高的时序性能,而后者由于分布在不通的位置,延迟较大。

2 BRAM RAM的应用形式

2.1单口ROM (Single-Port ROM)

单口ROM,就是数据只读的,需要在IP初始化的时候,对ROM进行初始化,而且只有一个读接口。

2.2双口ROM(Dual-port ROM)

端口A和端口B可以同时访问ROM

2.3单口RAM(Single-port RAM)

2.4简单双口RAM(Simple Dual-port RAM)

A端口写,B端口读

2.5真双口RAM(True Dual-port RAM)

A 端口和B端口都可以读或者写

3 BLOCK RAM的读写模式

支持3种模式,分别是Write First Mode, Read First Mode, No Change Mode

3.1先写模式(Write First Mode)

这种模式下:

1)写操作:设置WEA为1写入当前地址的数据,在下一个时钟DOUTA会输出这个地址新写入的数据

2)读操作:设置WEA为0读出当前地址的数据,在下一个时钟DOUTA会输出这个地址的数据

3.2先读模式(Read First Mode)

这种模式下:

1)写操作:设置WEA为1写入当前地址的数据,而且在下一个时钟DOUTA会输出这个地址的原先的数据

2)读操作:设置WEA为0读出当前地址的数据,在下一个时钟DOUTA会输出这个地址的数据

3.3不变模式(No Change Mode)

这种模式下:

1)写操作:设置WEA为1写入当前地址的数据,和前面两种方式不一样,DOUT保存不变

2)读操作:设置WEA为0读出当前地址的数据,在下一个时钟DOUTA会输出这个地址的数据

4支持字节写入(BYTE Write)

另外,BRAM还具备BYTE Write功能,这样可以只对某一个字节进行修改,从下图时序图可以看出,只要控制WEA就可以控制对具体哪一个BYTE进行写控制。

5访问冲突 (Collision Behavior)

BRAM 很好用,但是需要注意冲突的问题,就是对于同一个地址写或者读的时候需要注意。

5.1异步时钟处理原则

使用异步时钟,当一个端口将数据写入存储位置时,另一端口在指定的时间内不得读取或写入该位置。 器件数据手册中定义了该时钟到时钟的建立时间,以及其他Block RAM切换特性。这里说到的“ 时钟到时钟的建立时间”我还没注意到哪一个文档有说明。所以异步时钟可以通过长期的稳定性测试获取到这个时间间隔。

5.2同步时钟处理原则

同步写冲突:如果两个端口都试图写到内存中的同一位置,则会发生写写冲突。 内存位置的结果内容未知。 请注意,Write-Write冲突会影响内存内容,而Write-Read冲突只会影响数据输出

使用字节写入:使用字节写入时,在同一数据字中写入单独的字节时,存储器内容不会损坏。 仅当两个端口都试图写入同一字节时,RAM内容才会损坏。 下图说明了这种情况。 假设addra = addrb = 0

同步读写冲突:如果一个端口尝试写入内存位置而另一个端口读取相同的位置,则可能发生同步读写冲突。 虽然在写-读冲突中存储器的内容没有损坏,但是输出数据的有效性取决于写端口的工作模式。

a: 如果写入端口处于READ_FIRST模式,则另一个端口可以可靠地读取旧的存储器内容。

b: 如果写入端口处于WRITE_FIRST或NO_CHANGE模式,则读取端口的输出上的数据无效。

c: 如果是字节写入,则只有更新的字节在读取端口输出上无效,但是RAM中的内容是对的

下图说明了读写冲突和字节写入的影响。 当端口A处于WRITE_FIRST模式和READ_FIRST模式时,显示doutb。 假定addra = addrb = 0,端口B始终处于读取状态,并且所有内存位置均初始化为0。RAM的内容在读写冲突中不会被破坏。

5.3简单的双端口RAM冲突

对于简单双端口RAM,无论时钟如何,都可以使用READ_FIRST,WRITE_FIRST和NO_CHANGE工作模式。

简单双端口RAM就像真正的双端口RAM,其中仅连接了A端口的Write接口和B端口的Read接口。 工作模式定义了A或B端口的读写关系,并且仅在地址冲突期间影响A和B端口之间的关系。

对于同步时钟和冲突期间,可以配置端口A的写模式,以便对端口B的读操作可以产生数据(作用类似于READ_FIRST),也可以产生未定义的数据(Xs)。 因此,始终建议在配置为简单双端口RAM时使用READ_FIRST。 对于异步时钟,Xilinx建议将端口A的写入模式设置为WRITE_FIRST以确保碰撞安全。 有关此行为的详细信息,请参阅pg058第51页的冲突行为。

对于7系列设备,当RAM_MODE设置为ture dual port时,选定的操作模式将传递到Block RAM。 对于将RAM_MODE设置为simple dual port的原语,写模式为READ_FIRST用于同步时钟,而WRITE_FIRST用于异步时钟。

对于基于UltraScale架构的设备,没有限制,并且无论时钟如何,所选的操作模式总是传递给Block RAM原语。这一段说明,这种高级模式我们暂时不涉及。

其他内存冲突限制:地址空间重叠

7系列FPGA Block RAM存储器在以下配置中具有附加的冲突限制:

•当配置为真双端口(ture dual port)

•当CLKA(端口A)和CLKB(端口B)异步时

•在同时执行读写操作的应用程序中

•使用配置为READ_FIRST的写入模式配置端口A,端口B或两个端口时

上面文字描述中很多都在讲解冲突,其实对于我们的具体应用而言,更多时候我们BRAM是做乒乓使用的,也就是读地址和写地址,都是不会同时发生,而且时钟是同步的,这样就不容易发生冲突导致的数据破坏和不正确。

6输出寄存器

BRAM 可以设置有寄存器输出和无寄存器输出,下图是BRAM的框图结构

下图是有寄存器和无寄存器输出,可以达到的最高时钟频率的数据表,所以增加寄存器输出可以提高速度。我们例子中由于用到的演示时钟并没有很高所以不需要增加寄存器输出。

6.1通过无输出寄存器输出方式读取

6.2通过Primitives Output Register读取数据并实现rEad使能延迟

6.3使用两个流水线阶段读取数据的延迟

7添加BRAM IP

设置简单双口RAM

设置BRAM的端口A的宽度和深度

设置BRAM的端口B的宽度和深度,并且没有寄存器输出

这一页默认

单击OK

8读写BRAM代码

本代码的设计和FIFO使用非常类似

1)、写操作:写操作不断进行,每次写入1024个数据

2)、读操作:读操作是在每次写入达到512个数据开始的,当然实际上读操作完全可以和写操作同时进行,错开512个数据是为了方便观察现象。

/*************BRAM IP 测试********************************************
--BLOCK RAM 是FPGA内部自带的资源,BLOCK RAM分为硬核BLOCK RAM 和分布式BLOCK RAM(逻辑实现)
--BLCOK RAM 属于FPGA稀有资源,具有非常高效的访问速度和效率,比如FIFO实际也是用过BLOCK RAM实现
--本实验实现对 BLOCK RAM IP的仿真测试
*********************************************************************/
`timescale 1ns / 1ns //仿真时间刻度/精度

module bram_test(
input I_rstn, //系统复位输入
input I_sysclk_p,
input I_sysclk_n //系统时钟输入
);

wire I_clk;
IBUFGDS CLK_U(
.I(I_sysclk_p),
.IB(I_sysclk_n),
.O(I_clk)
);

reg [9:0]addra;    //通道A 地址
reg [7:0]wr_frame; //帧计数器
reg [1:0]WR_S;     //写状态机
reg ena;           //通道A使能
reg wea;           //通道A写使能

reg [9:0]addrb;   //读通道B地址
reg [1:0]RD_S;    //读状态机
reg enb;          //通道B使能

wire [31:0] dina;    //bram 数据输入
wire [31:0] doutb;   //bram 数据输出

assign dina = {wr_frame,wr_frame,addra[7:0],addra[7:0]};  //输入的数据包{帧信号,帧信号,通道A地址,通道A地址}

always @(posedge I_clk)begin
    if(!I_rstn)begin //复位重置相关寄存器
       wr_frame <= 8'd0;
       addra    <= 9'd0;
       ena      <= 1'b1;
       wea      <= 1'b0; 
       WR_S     <= 2'd0;
    end
    else begin
        case(WR_S)
        0:begin
             addra  <= 10'd0; //设置地址从0开始
             ena    <= 1'd1;  //设置通道A使能
             wea    <= 1'b1;  //设置写使能
             WR_S   <= 2'd1;  //下一个状态
        end
        1:begin
            if(addra != 10'd1023)begin //如果写地址不等于1023,
               wea   <= 1'b1; //设置写使能
               ena   <= 1'b1; //设置通道A使能
               addra <= addra + 1'b1;//那么通道A地址,每个时钟地址增加1
            end
            else begin //否则代表完成了1帧数据写入到BRAM
               wea   <= 1'b0; //设置写使能为0,停止写
               ena   <= 1'b0; //设置通道A使能为0
               wr_frame <= wr_frame +1'b1;//帧计数器
               WR_S   <= 2'd2;//下一个状态
            end
        end
        2:begin
            if(RD_S == 2'd2) //如果读操作完成
               WR_S   <= 2'd0; //回到状态0重新开始
        end
        default:WR_S   <= 2'd0;
        endcase
     end
end

always @(posedge I_clk)begin
    if(!I_rstn)begin //复位重置相关寄存器
       addrb    <= 9'd0;
       enb      <= 1'b0;
       RD_S     <= 2'd0;
    end
    else begin
        case(RD_S)
        0:begin
            enb     <= 1'b0; //设置读使能0
            addrb   <= 10'd0; //设置读地址从0开始
             if(addra == 10'd512)begin//读数据在写数据的第512个地址开始
                enb   <= 1'b1; //使能读通道
                RD_S  <= 2'd1; //下一状态
             end   
        end
        1:begin
            enb    <= 1'b1;//设置读使能1
            if(addrb != 10'd1023)如果读地址不等于1023,
               addrb  <= addrb + 1'b1;//那么通道B地址,每个时钟地址增加1
            else 
               RD_S   <= 2'd2;//下一状态
        end
        2:begin
            RD_S   <= 2'd0;//下一状态
        end
        default:RD_S   <= 2'd0;
        endcase
     end
end   
//例化BRAM IP,简单双口RAM
blk_mem_gen_0 bram_inst (
      .clka(I_clk),    //通道A时钟输入
      .ena(ena),          //通道A使能
      .wea(wea),          //写使能
      .addra(addra),      //通道A地址
      .dina(dina),        //通道A数据输入
      .clkb(I_clk),    //通道B时钟输入
      .enb(enb),          //通道B使能
      .addrb(addrb),      //通道B地址
      .doutb(doutb)       //通道B数据输出
    ); 
    
endmodule

9仿真文件

/*********************仿真文件****************************************
*********************************************************************/
`timescale 1ns / 1ns//仿真时间刻度/精度

module tb_bram_test;

localparam  SYS_TIME = 10 ;//定义时钟周期 单位ns

reg   I_sysclk_p;
reg   I_sysclk_n; //系统时钟
reg   I_rstn;   //系统复位

//例化bram_test 
bram_test bram_test_inst
(
.I_sysclk_p(I_sysclk_p),
.I_sysclk_n(I_sysclk_n),
.I_rstn(I_rstn)
);
   
//初始化
initial begin
    I_sysclk_p  = 1'b0;
    I_sysclk_n  = 1'b1;
    I_rstn = 1'b0;
    #100;//产生100ns的系统复位
    I_rstn = 1'b1;//复位完成
end

//产生仿真时钟
always #(SYS_TIME/2) I_sysclk_p= ~I_sysclk_p;
always #(SYS_TIME/2) I_sysclk_n= ~I_sysclk_n;                   
                           
endmodule

10仿真结果

箭头1 写开始

箭头2 写完1024个数据

箭头3 当写数据达到512个后开始读

箭头4 读完1024个数据

上图中,数据采用Primitives Output Register 方式数据延迟了3个时钟,这一点需要注意

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

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

相关文章

0826-0901 各种面试笔试题算法题整理

目录 1. 最长回文子串 2. 设计模式里和单一职责原则冲突的是&#xff1f; 3. int array[] {10,20,30} cout<<-2[array-1] 是多少 4. python 定义 class method 直接对类修改变量值和建立对象后通过对象修改变量值&#xff0c;最后的结果是多少 5. LRU缓存 6. 二叉…

Kafka【六】Linux下安装Kafka集群

Kafka从早期的消息传输系统转型为开源分布式事件流处理平台系统&#xff0c;所以很多核心组件&#xff0c;核心操作都是基于分布式多节点的。本文这里采用三台虚拟机模拟真实物理主机搭建Zookeeper集群和kafka集群。 VMware可以使用户在一台计算机上同时运行多个操作系统&…

继承(CPP)

引言 继承是CPP的一个重要语法。在现实生活中存在“子承父业”的说法&#xff0c;在CPP中同样存在这样的语法&#xff0c;而继承就是这种语法。 面向对象的三大特征&#xff1a;封装、继承、多态 本文将通过以下要素&#xff0c;进行继承的深入讲解 1.继承的概念及定义 2.基…

什么是网络准入控制系统?四款网络准入控制系统推荐 干货满满!

在当今的企业网络环境中&#xff0c;随着设备类型的多样化和远程办公的普及&#xff0c;网络安全面临的挑战愈加复杂。网络准入控制系统&#xff08;Network Access Control, NAC&#xff09;应运而生&#xff0c;成为企业保障网络安全的重要工具。本文就带你详细了解这一系统&…

4 款基于Python的鼠标键盘自动化工具,可解决Windows、macOS和Linux下的桌面自动化问题

在日常工作中&#xff0c;自动化工具可以极大地提升我们的工作效率&#xff0c;尤其是当面对重复性任务时。今天&#xff0c;我们将详细介绍四款基于Python的鼠标键盘自动化工具&#xff0c;帮助你在各种平台上轻松实现自动化操作。这些工具分别是 PyAutoGUI、KeymouseGo、Keyl…

《Nature》重磅发布:ChatGPT在学术研究和写作中的最佳应用指南

在论文写作过程中&#xff0c;ChatGPT 已成为许多研究人员的得力助手。知名生物医学教授 Milton Pividori 博士在《Nature》杂志上发表的文章《Chatbots in Science: What Can ChatGPT Do for You?》详细探讨了如何通过精心设计的提示词来有效利用 ChatGPT 提高学术写作的效率…

支付宝线上小程序打开异常

1. 其他手机都可以正常访问线上版本&#xff0c;只有一个安卓手机不行&#xff08;排除支付宝低版本以及手机系统问题&#xff09; 2. 出现访问异常的手机都可以正常访问体验版以及开发版本 3. 尝试去关闭该手机的联调设置以及清除开发版缓存&#xff0c;成功访问线上版本 需要…

如何彻底关闭Chrome浏览器自动更新

1.首先找到桌面 中Google Chrome浏览器的图片,鼠标右键打开文件所在的位置 2.选择Google 目录 选择 Update 目录 右键 选择属性 右键 选择属性 点击确定 修改成功 3.继续 第(2)步 选择 高级 4.点击禁用继承 !!!!!!! 测试 再次点击 Update 文件夹 弹出 你当前无权访问该文件夹…

一文1400字Jmeter实现mqtt协议压力测试

1. 下载jmeter&#xff0c;解压 https://jmeter.apache.org/download_jmeter.cgi 以 5.4.3 为例&#xff0c;下载地址&#xff1a; https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.4.3.zip linux下解压&#xff1a; unzip apache-jmeter-5.4.3.zip 2. 下载m…

如何在 Github 上找到心仪的开源项目?

Github&#xff0c;全球最大的开源社区&#xff0c;集中了目前最多、最优质的各种开源代码。 我们经常说不要重复造轮子&#xff0c;但如果不知道怎么找到已有的轮子&#xff0c;那就没有前提&#xff0c;对自己来说什么轮子都是新的。所以&#xff0c;搞开发&#xff0c;首先要…

Opencv中的直方图(5)计算EMD距离的函数EMD()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 计算两个加权点配置之间的“最小工作量”距离。 该函数计算地球搬运工距离&#xff08;Earth Mover’s Distance&#xff09;和/或两个加权点配…

微电网管理系统

微电网管理系统 1. 相关概念简介 基本概念及分析意义&#xff1a; 微电网基本概念&#xff1a;微电网&#xff08;MG&#xff09;由分布式电源、用电负荷、能量管理系统等组成&#xff0c;是一个能够基本实现内部电力电量平衡的供用电系统。 通过整合分布式电源、储能、负荷…

libusb在window下,使用vsstudio的初步安装与使用

下载&#xff1a; 首先&#xff0c;访问github官网 https://github.com/libusb/libusb/tree/master 然后&#xff0c;在版本选择里面&#xff0c;选择标签&#xff0c;点击最新的标签&#xff0c;&#xff08;这种一般稳定性最高&#xff09; 选择完后使用自己的方式下载下来…

双轨直销模式:团队互助与业绩倍增的商业策略

双轨直销模式因其操作简单、业绩压力较小、管理方便以及初期爆发力强等特点&#xff0c;受到许多直销公司的喜爱&#xff0c;并促进了多家大型企业的成长。 一、双轨直销模式简介 双轨直销是一种独特的组织架构&#xff0c;其核心在于每个销售代表仅需构建两个独立的销售线&a…

MiniMax 首个文生视频模型发布,可生成 6s,限时免费;阿里 Qwen2-VL 第二代视觉语言模型开源丨RTE 开发者日报

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、…

第七在线携手美国男士内衣品牌Tommy John,共启智能订货新篇章

【喜讯速递】在数字化转型的浪潮中&#xff0c;7thonline第七在线再次以卓越的技术实力和前瞻性的市场洞察&#xff0c;成功签约国际知名男士内衣品牌Tommy John&#xff0c;双方将携手推进智能订货会计划&#xff0c;共同开启零售供应链管理的新纪元。 男士内衣品牌Tommy John…

智慧水利解决方案应该部署哪些设备(近距离走进智慧水利解决方案)

作为一名水利工程技术人员&#xff0c;我深知智慧水利解决方案对于现代水资源管理的重要性。在我多年的工作经验中&#xff0c;我见证了传统水利系统向智能化转变的过程&#xff0c;也深刻理解了部署正确的设备对于实现智慧水利的关键作用。今天&#xff0c;我想分享一下在智慧…

android AccessibilityService合法合规增加小红书曝光阅读量(2024-09-02)

免责任声明: 任何可操作性的内容与本人无关,文章内容仅供参考学习&#xff0c;如有侵权损害贵公司利益&#xff0c;请联系作者&#xff0c;会立刻马上进行删除。 一、分析 目前可增加曝光阅读流量渠道入口&#xff08;完成&#xff09; 1. 发现页 打开小红书app选择顶部发现页&…

Python和MATLAB(Java)及Arduino和Raspberry Pi(树莓派)点扩展函数导图

&#x1f3af;要点 反卷积显微镜图像算法微珠图像获取显微镜分辨率基于像素、小形状、高斯混合等全视野建模基于探测器像素经验建模荧光成像算法模型傅里叶方法计算矢量点扩展函数模型天文空间成像重建二维高斯拟合天体图像伽马射线能量和视场中心偏移角标量矢量模型盲解卷积和…

三、数组————相关概念详解

数组 前言一、数据理论基础二、数组常用操作2.1 初始化数组2.2 访问数组中的元素2.3 插入元素2.4 删除元素 三、数组扩展3.1 遍历数组3.2 数组扩容 总结1、数组的优点2、数组的不足 前言 在数据结构中&#xff0c;数组可以算得上最基本的数据结构。数组可以用于实现栈、队列、…