OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7255|回复: 0
打印 上一主题 下一主题

[XILINX] 【正点原子FPGA连载】第十二章 IP核之RAM实验--摘自【正点原子】领航者ZYNQ之FPGA开发指南_V1.2

[复制链接]

1424

主题

1440

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
6075
金钱
6075
注册时间
2019-5-8
在线时间
1740 小时
跳转到指定楼层
楼主
发表于 2020-6-13 11:34:01 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 正点原子01 于 2020-6-13 11:33 编辑

1)实验平台:正点原子领航者ZYNQ开发板
2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-301505-1-1.html
4)本章实例源码下载: IP核之RAM实验.zip (2.68 MB, 下载次数: 2)
5)对正点原子FPGA感兴趣的同学可以加群讨论:712557122
6)关注正点原子公众号,获取最新资料更新


第十二章 IP核之RAM实验
    RAM的英文全称是RandomAccess Memory,即随机存取存储器,它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据,其读写速度是由时钟频率决定的。RAM主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。本章我们将对Vivado软件生成的RAM IP核进行读写测试,并向大家介绍Xilinx RAM IP核的使用方法。
本章包括以下几个部分:

1.1    RAM IP核简介
1.2    实验任务
1.3    硬件设计
1.4    程序设计
1.5    下载验证

1.1 RAM IP核简介
     Xilinx 7系列器件具有嵌入式存储器结构,满足了设计对片上存储器的需求。嵌入式存储器结构由一列列BRAM(块RAM)存储器模块组成,通过对这些BRAM存储器模块进行配置,可以实现各种存储器的功能,例如:RAM、移位寄存器、ROM以及FIFO缓冲器。
     Vivado软件自带了BMG IP核(BlockMemory Generator,块RAM生成器),可以配置成RAM或者ROM。这两者的区别是RAM是一种随机存取存储器,不仅仅可以存储数据,同时支持对存储的数据进行修改;而ROM是一种只读存储器,也就是说,在正常工作时只能读出数据,而不能写入数据。需要注意的是,配置成RAM或者ROM使用的资源都是FPGA内部的BRAM,只不过配置成ROM时只用到了嵌入式BRAM的读数据端口。本章我们主要介绍通过BRAM IP核配置成RAM的使用方法。
    Xilinx 7系列器件内部的BRAM全部是真双端口RAM(TrueDual-Port ram,TDP),这两个端口都可以独立地对BRAM进行读/写。但也可以被配置成伪双端口RAM(Simple Dual-Port ram,SDP)(有两个端口,但是其中一个只能读,另一个只能写)或单端口RAM(只有一      个端口,读/写只能通过这一个端口来进行)。单端口RAM只有一组数据总线、地址总线、时钟信号以及其他控制信号,而双端口RAM具有两组数据总线、地址总线、时钟信号以及其他控制信号。有关BRAM的更详细的介绍,请读者参阅Xilinx官方的手册文档“UG473,7 Series FPGAs Memory ResourcesUser Guide”。
    单端口RAM类型和双端口RAM类型在操作上都是一样的,我们只要学会了单端口RAM的使用,那么学习双端口RAM的读写操作也是非常容易的。本章我们以配置成单端口RAM为例进行讲解。
    BMG IP核配置成单端口RAM的框图如下图所示。

图12.1.1单端口RAM框图
    各个端口的功能描述如下:
    DINA:RAM端口A写数据信号。
    ADDRA:RAM端口A读写地址信号,对于单端口RAM来说,读地址和写地址共用同该地址线。
    WEA:RAM端口A写使能信号,高电平表示向RAM中写入数据,低电平表示从RAM中读出数据。
    ENA:端口A的使能信号,高电平表示使能端口A,低电平表示端口A被禁止,禁止后端口A上的读写操作都会变成无效。另外ENA信号是可选的,当取消该使能信号后,RAM会一直处于有效状态。
    RSTA:RAM端口A复位信号,可配置成高电平或者低电平复位,该复位信号是一个可选信号。
    REGCEA:RAM端口A输出寄存器使能信号,当REGCEA为高电平时,DOUTA保持最后一次输出的数据,REGCEA同样是一个可选信号。
    CLKA:RAM端口A的时钟信号。
    DOUTA:RAM端口A读出的数据。
1.2 实验任务
    本节实验任务是使用Xilinx BMGIP核,配置成一个单端口的RAM,然后对RAM进行读写操作,通过在Vivado自带的仿真器中观察波形是否正确,最后将设计下载到领航者Zynq开发板中,并使用ILA对其进行在线调试观察。
1.3硬件设计
    本章实验只用到了输入的时钟信号和按键复位信号,没有用到其它硬件外设,各端口信号的管脚分配如下表所示:
表12.3.1IP核之RAM实验管脚分配
对应的XDC约束语句如下所示:
  1. set_property -dict {PACKAGE_PIN U18 IOSTANDARDLVCMOS33} [get_ports sys_clk]
  2. set_property -dict {PACKAGE_PIN J15 IOSTANDARDLVCMOS33} [get_ports sys_rst_n]
复制代码
1.4 程序设计
    首先在Vivado软件中创建一个名为ip_ram的工程,工程创建完成后,在Vivado软件的左侧“FlowNavigator”栏中单击“IP Catalog”,如下图所示。

图12.4.1点击“IP Catalog”
    在“IP Catalog”窗口的搜索框中输入“BlockMemory”,出现唯一匹配的“Block Memory Generator”,如下图所示(图中出现的两个IP核为同一个BMG IP核)。

图12.4.2搜索框中输入“Block Memory”
    双击“Block MemoryGenerator”后弹出IP核的配置界面,接下来对BMG IP核进行配置,“Basic”选项页配置界面如下图所示。
图12.4.3“Basic”选项页配置
    Component Name:设置该IP核的名称,这里保持默认即可。
    Interface Type:RAM接口总线。这里保持默认,选择Native接口类型(标准RAM接口总线);
    Memory Type:存储器类型。可配置成SinglePort RAM(单端口RAM)、Simple Dual Port RAM(伪双端口RAM)、True Dual Port            RAM(真双端口RAM)、Single Port ROM(单端口ROM)和Dual Port ROM(双端口ROM),这里选择Single Port RAM,即配置成单端口RAM。
ECC Options:ErrorCorrection Capability,纠错能力选项,单端口RAM不支持ECC。
Write Enable:字节写使能选项,勾中后可以单独将数据的某个字节写入RAM中,这里不使能。
AlgorithmOptions:算法选项。可选择Minimum Area(最小面积)、Low Power(低功耗)和Fixed Primitives(固定的原语),这里选择默认的Minimum Area。
    接下来切换至“Port A”选项页,设置端口A的参数,该页面配置如下:

图12.4.4“Port A Options”选项页配置
    Write Width:端口A写数据位宽,单位Bit,这里设置成8。
    Read Width:端口A读数据位宽,一般和写数据位宽保持一致,设置成8。
    Write Depth:写深度,这里设置成32,即RAM所能访问的地址范围为0-31。
    Read Depth:读深度,默认和写深度保持一致。
    Operating Mode:RAM读写操作模式。共分为三种模式,分别是Write First(写优先模式)、Read First(读优先模式)和No Change(不变模式)。写优先模式指数据先写入RAM中,然后在下一个时钟输出该数据;读优先模式指数据先写入RAM中,同时输出RAM中同地址的上一次数据;不变模式指读写分开操作,不能同时进行读写,这里选择No Change模式。
    Enable Port Type:使能端口类型。UseENA pin(添加使能端口A信号);Always Enabled(取消使能信号,端口A一直处于使能状态),这里选择默认的Use ENA pin。
    Port A OptionalOutput Register:端口A输出寄存器选项。其中“Primitives Output Register”默认是选中状态,作用是打开BRAM内部位于输出数据总线之后的输出流水线寄存器,虽然在一般设计中为了改善时序性能会保持此选项的默认勾选状态,但是这会使得BRAM输出的数据延迟一拍,这不利于我们在Vivado的ILA调试窗口中直观清晰地观察信号;而且在本实验中我们仅仅是把BRAM的数据输出总线连接到了ILA的探针端口上来进行观察,除此之外数据输出总线没有别的负载,不会带来难以满足的时序路径,因此这里取消勾选。
Port A OutputReset Options:RAM复位信号选项,这里不添加复位信号,保持默认即可。
    另外,需要注意的是,下面的“PrimitivesOutput Register”默认是选中状态的,此选项的作用是打开块RAM内部的位于输出数据总线之后的输出流水线寄存器,虽然在一般设计中为了改善时序性能会保持此选项的默认勾选状态,但是这会使得块RAM输出的数据延迟一拍,这不利于我们在Vivado的ILA调试窗口中直观清晰地观察信号;而且在本实验中我们仅仅是把块RAM的数据输出总线连接到了ILA的探针端口上来进行观  察,除此之外数据输出总线没有别的负载,不会带来难以满足的时序路径。
    接下来的“Other Options”选项页用于设置RAM的初始值等,本次实验不需要设置,直接保持默认即可。
最后一个是“Summary”选项页,该页面显示了存储器的类型,消耗的BRAM资源等,我们直接点击“OK”按钮完成BMG IP核的配置,如下图所示:

图12.4.5“Summary”选项页
    接下来会弹出询问是否在工程目录下创建存放IP核的文件,我们点击“OK”按钮即可。
紧接着会弹出“GenarateOutput Products”窗口,我们直接点击“Generate”,如下图所示。

图12.4.6“Genarate Output Products”窗口
    之后我们就可以在“Design Run”窗口的“Out-of-ContextModule Runs”一栏中出现了该IP核对应的run“blk_mem_gen_0_synth_1”,其综合过程独立于顶层设计的综合,所以在我们可以看到其正在综合,如下图所示。

图12.4.10“blk_mem_gen_0_synth_1”run
    在其Out-of-Context综合的过程中,我们就可以进行RTL编码了。首先打开IP核的例化模板,在“Source”窗口中的“IP Sources”选项卡中,依次用鼠标单击展开“IP”-“blk_mem_gen_0”-“Instantitation Template”,我们可以看到“blk_mem_gen_0.veo”文件,它是由IP核自动生成的只读的verilog例化模板文件,双击就可以打开它,如下图所示。

图12.4.11“blk_mem_gen_0.veo”文件
接下来我们创建一个新的设计文件,命名为ram_rw.v,代码如下:
  1. module ram_rw(
  2. input               clk        ,//时钟信号
  3. input               rst_n      ,//复位信号,低电平有效

  4. output              ram_en     ,//ram使能信号
  5. output              ram_wea    ,//ram读写选择
  6. outputreg[4:0  ram_addr   ,//ram读写地址
  7. outputreg[7:0  ram_wr_data,//ram写数据
  8. input[7:0  ram_rd_data   //ram读数据      
  9. );

  10. //reg define
  11. reg[5:0  rw_cnt ;//读写控制计数器

  12. //*****************************************************
  13. //**                   main code
  14. //*****************************************************

  15. //控制RAM使能信号
  16. assign ram_en = rst_n;
  17. //rw_cnt计数范围在0~31,写入数据;32~63时,读出数据
  18. assign ram_wea =(rw_cnt <=6'd31&&ram_en ==1'b1)?1'b1:1'b0;

  19. //读写控制计数器,计数器范围0~63
  20. always@(posedge clk ornegedge rst_n)begin
  21. if(rst_n ==1'b0)
  22.          rw_cnt <=1'b0;
  23. elseif(rw_cnt ==6'd63)
  24.          rw_cnt <=1'b0;
  25. else
  26.          rw_cnt <=rw_cnt +1'b1;
  27. end

  28. //产生RAM写数据
  29. always@(posedge clk ornegedge rst_n)begin
  30. if(rst_n ==1'b0)
  31.          ram_wr_data <=1'b0;
  32. elseif(rw_cnt <=6'd31)//在计数器的0-31范围内,RAM写地址累加
  33.          ram_wr_data <= ram_wr_data +1'b1;
  34. else
  35.          ram_wr_data <=1'b0;
  36. end

  37. //读写地址信号 范围:0~31
  38. always@(posedge clk ornegedge rst_n)begin
  39. if(rst_n ==1'b0)
  40.          ram_addr <=1'b0;
  41. elseif(ram_addr ==5'd31)
  42.          ram_addr <=1'b0;
  43. else
  44.          ram_addr <=ram_addr +1'b1;
  45. end

  46. endmodule
复制代码
    模块中定义了一个读写控制计数器(rw_cnt),当计数范围在0~31之间时,向ram中写入数据;当计数范围在32~63之间时,从ram中读出数据。
    接下来我们设计一个verilog文件来实例化创建的RAMIP核以及ram_rw模块,文件名为ip_ram.v,编写的verilog代码如下。
  1. module ip_ram(
  2. input         sys_clk ,//系统时钟
  3. input         sys_rst_n  //系统复位,低电平有效
  4. );

  5. //wire define
  6. wire             ram_en      ;//RAM使能   
  7. wire             ram_wea     ;//ram读写使能信号,高电平写入,低电平读出
  8. wire[4:0    ram_addr    ;//ram读写地址
  9. wire[7:0    ram_wr_data ;//ram写数据
  10. wire[7:0    ram_rd_data ;//ram读数据

  11. //*****************************************************
  12. //**                   main code
  13. //*****************************************************

  14. //ram读写模块
  15. ram_rw  u_ram_rw(
  16. .clk            (sys_clk     ),
  17. .rst_n          (sys_rst_n   ),
  18. //RAM
  19. .ram_en         (ram_en      ),
  20. .ram_wea        (ram_wea     ),
  21. .ram_addr       (ram_addr    ),
  22. .ram_wr_data    (ram_wr_data),
  23. .ram_rd_data    (ram_rd_data)
  24. );

  25. //ram ip核
  26. blk_mem_gen_0  blk_mem_gen_0 (
  27. .clka  (sys_clk      ),// input wire clka
  28. .ena   (ram_en       ),// input wire ena  
  29. .wea   (ram_wea      ),// input wire [0 : 0] wea
  30. .addra (ram_addr    ),//input wire [4 : 0] addra
  31. .dina  (ram_wr_data  ),// input wire [7 : 0] dina
  32. .douta (ram_rd_data )//output wire [7 : 0] douta
  33. );

  34. endmodule
复制代码
    程序中例化了ram_rw模块和ram IP核blk_mem_gen_0,其中ram_rw模块负责产生对ram IP核读/写所需的所有数据、地址以和读写使能信号,同时从ram IP读出的数据也连接至ram_rw模块。
    接下来对RAM IP核进行仿真,来验证对RAM的读写操作是否正确。tb_ip_ram仿真文件源代码如下:
  1. `timescale1ns/1ps

  2. moduletb_ip_ram();

  3. reg     sys_clk;
  4. reg     sys_rst_n;

  5. always#10sys_clk =~sys_clk;

  6. initialbegin
  7.      sys_clk =1'b0;
  8.      sys_rst_n =1'b0;
  9. #200
  10.      sys_rst_n =1'b1;
  11. end

  12. ip_ram u_ip_ram(
  13. .sys_clk          (sys_clk        ),
  14. .sys_rst_n        (sys_rst_n      )
  15. );

  16. endmodule
复制代码
接下来就可以开始仿真了,仿真过程这里不再赘述,仿真波形图如下图所示。

图12.4.7 RAM写操作波形图
    图12.4.7为RAM的写操作仿真波形图,由上图可知,ram_wea信号拉高,说明此时是对ram进行写操作。ram_wea信号拉高之后,地址和数据都是从0开始累加,也就说当ram地址为0时,写入的数据也是0;当ram地址为1时,写入的数据也是1,我们总共向ram中写入32个数据。
RAM读操作仿真波形图如下图所示:

图12.4.8 RAM读操作波形图
    由上图可知,ram_wea信号拉低,说明此时是对ram进行读操作。ram_wea信号拉低之后,ram_addr从0开始增加,也就是说从ram的地址0开始读数据;ram中读出的数据ram_rd_data在延时一个时钟周期之后,开始输出数据,输出的数据为0,1,2……,和我们写入的值是相等的,也就是说,我们创建的RAM IP核从仿真结果上来看是正确的。
    接下来添加ILA IP核,将ram_en、ram_wea、ram_addr、ram_wr_data和ram_rd_data信号添加至观察列表中,添加ILAIP核的方法这里不再赘述。
最后为工程添加IO管脚约束,对应的XDC约束语句如下所示:
  1. set_property -dict {PACKAGE_PIN U18 IOSTANDARDLVCMOS33} [get_ports sys_clk]
  2. set_property -dict {PACKAGE_PIN J15 IOSTANDARDLVCMOS33} [get_ports sys_rst_n]
复制代码
1.5 下载验证
    编译工程并生成比特流.bit文件。将下载器一端连接电脑,另一端与开发板上的JTAG下载口连接,连接电源线,并打开开发板的电源开关。
    点击Vivado左侧“FlowNavigator”窗口最下面的“Open Hardware Manager”,此时Vivado软件识别到下载器,点击“Hardware”窗口中“Progam Device”下载程序,在弹出的界面中选择“Program”下载程序。
    RAM写操作在ILA中观察的波形如下图所示:

图12.5.1RAM写操作ILA波形图
    ram_wea信号拉高之后,地址和数据都是从0开始累加,也就说当ram地址为0时,写入的数据也是0;当ram地址为1时,写入的数据也是1。我们可以发现,上图中的数据变化和在Vivado仿真的波形是一致的。
    RAM读操作在ILA中观察的波形如下图所示:

图12.5.2 RAM读操作ILA波形图
    ram_wea(读使能)信号拉低之后,ram_addr从0开始增加,也就是说从ram的地址0开始读数据;ram中读出的数据ram_rd_data在延时一个时钟周期之后,开始输出数据,输出的数据为0,1,2……,和我们写入的值是相等的。我们可以发现,上图中的数据变化同样和Vivado仿真的波形是一致的。本次实验的IP核之RAM读写实验验证成功。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /1 下一条

正点原子公众号

如发现本坛存在违规或侵权内容, 请点击这里发送邮件举报 (或致电020-38271790)。请提供侵权说明和联系方式。我们将及时审核依法处理,感谢配合。

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2026-10-21 10:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表