目录:

  • 1.IP核 RAM简介
  • 2.实验1: 配置单端口 RAM
    • 1)实验任务
    • 2)创建工程并添加ram ip
    • 3)编写ram_rw.v
    • 4)编写顶层文件
    • 5)编写激励文件
    • 6)仿真测试
    • 7)ILA测试
  • 3.实验2: 配置伪双端口 RAM
    • 1)创建工程并添加ram ip
    • 2)伪双端口RAM的端口定义和时序
    • 3)编写测试程序
    • 4)编写激励文件
    • 5)仿真测试
    • 6)ILA测试

1.IP核 RAM简介

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

Xilinx 7 系列器件具有嵌入式存储器结构,它由一列列 BRAM(块 RAM)存储器模块组成,通过对这些 BRAM 存储器模块进行配置,可以实现各种存储器的功能,例如:RAM、移位寄存器、ROM 以及 FIFO 缓冲器。

Vivado 软件自带了 BMG IP 核(Block Memory Generator,块 RAM 生成器),可以配置成 RAM 或者ROM。这两者的区别是 RAM 是一种随机存取存储器,不仅仅可以存储数据,同时支持对存储的数据进行修改;而 ROM 是一种只读存储器,也就是说,在正常工作时只能读出数据,而不能写入数据。

BRAM 全部是真双端口 RAM(True Dual-Port ram,TDP),这两个端口都可以独立地对 BRAM 进行读/写。但也可以被配置成伪双端口 RAM(Simple Dual-Port ram,SDP)(有两个端口,但是其中一个只能读,另一个只能写)或单端口 RAM(只有一个端口,读/写只能通过这一个端口来进行)。单端口 RAM 只有一组数据总线、地址总线、时钟信号以及其他控制信号,而双端口 RAM 具有两 组数据总线、地址总线、时钟信号以及其他控制信号。

2.实验1: 配置单端口 RAM

1)实验任务

配置一个单端口的 RAM,然后对 RAM 进行读写操作,通过在 Vivado 自带的仿真器中观察波形是否正确,最后将设计下载到 Zynq 开发板中,并使用 ILA 对其进行在线调试观察。

2)创建工程并添加ram ip

图1 PICTURE ONE 图2 PICTURE TWO 图3 PICTURE TWO

3)编写ram_rw.v

/** 当计数范围在 0~31 之间时,向 ram 中写入数据;* 当计数范围在 32~63 之间时,从 ram 中读出数据。*/
module ram_rw(input                 clk,input               rst_n,output                ram_wea,output              ram_en, output  reg [4:0]   ram_addr,output reg [7:0]   ram_wr_data,input       [7:0]   ram_rd_data);reg [5:0]  cnt;//计数器 范围(0~63)
always @(posedge clk or negedge rst_n) beginif(!rst_n)cnt <= 6'd0;else if(cnt == 6'd63)cnt <= 6'd0;elsecnt <= cnt + 1'b1;
end//使能信号
assign ram_en = rst_n;//读写信号
assign ram_wea = (cnt < 6'd32 && ram_en) ? 1'b1:1'b0;//地址信号
always @(posedge clk or negedge rst_n) beginif(!rst_n)ram_addr <= 5'd0;else if(ram_addr == 5'd31)ram_addr <= 5'd0;elseram_addr <= ram_addr + 1'b1;
end//写信号的数据
always @(posedge clk or negedge rst_n) beginif(!rst_n)ram_wr_data <= 8'd0;else if(ram_addr == 6'd31)ram_wr_data <= 8'd0;elseram_wr_data <= ram_wr_data + 1'b1;
endendmodule

4)编写顶层文件

module top_singlep_ram_test(input clk,input rst_n);
wire        ram_wea;
wire        ram_en;
wire [4:0]  ram_addr;
wire [7:0]  ram_wr_data;
wire [7:0]  ram_rd_data;  // ram_rw 读写模块
ram_rw u_ram_rw(.clk             (clk),.rst_n           (rst_n),.ram_wea         (ram_wea),.ram_en          (ram_en),.ram_addr        (ram_addr),.ram_wr_data     (ram_wr_data),.ram_rd_data     (ram_rd_data)
);// ip_ram 核
blk_mem_gen_0 u_blk_mem_gen_0 (.clka        (clk),    // input wire clka.ena        (ram_en),      // input wire ena.wea        (ram_wea),      // input wire [0 : 0] wea.addra     (ram_addr),  // input wire [4 : 0] addra.dina       (ram_wr_data),    // input wire [7 : 0] dina.douta      (ram_rd_data)  // output wire [7 : 0] douta
);endmodule

5)编写激励文件

`timescale 1ns / 1psmodule tb_ip_ram();reg      clk;
reg     rst_n;initial beginclk = 1'b0;rst_n = 1'b0;#200rst_n = 1'b1;
endalways #10 clk = ~clk;top_singlep_ram_test u_top_singlep_ram_test(.clk    (clk),.rst_n  (rst_n)
);
endmodule

6)仿真测试


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

由上图可知,ram_wea 信号拉低,说明此时是对 ram 进行读操作。ram_wea 信号拉低之后,ram_addr从 0 开始增加,也就是说从 ram 的地址 0 开始读数据;ram 中读出的数据 ram_rd_data 在延时一个时钟周期之后,开始输出数据,输出的数据为 0,1,2……,和我们写入的值是相等的。

7)ILA测试

添加 ILA IP 核,将 ram_en、ram_wea、ram_addr、ram_wr_data 和 ram_rd_data 信号添加至观察列表中。

图1 PICTURE ONE 图2 PICTURE TWO

ILA 的时钟和探针信号连接到顶层设计中,例化 ILA IP 核的代码如下:

ila_0 your_instance_name (.clk(clk), // input wire clk.probe0(ram_en), // input wire [0:0]  probe0  .probe1(ram_wea), // input wire [0:0]  probe1 .probe2(ram_addr), // input wire [4:0]  probe2 .probe3(ram_wr_data), // input wire [7:0]  probe3 .probe4(ram_rd_data) // input wire [7:0]  probe4
);

最后为工程添加 IO 管脚约束,对应的 XDC 约束语句如下所示:

set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports clk]
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports rst_n]

生成比特流之后,直接点击“Program”,此时 Vivado 会自动打开 ILA 的调试窗口,如下图所示:

3.实验2: 配置伪双端口 RAM

1)创建工程并添加ram ip

图1 PICTURE ONE 图2 PICTURE TWO
图3 PICTURE ONE 图4 PICTURE TWO

注意:在Port B Options 栏目下,Primitives Output Register 取消勾选,其功能是在输出数据加上寄存器,可以有效改善时序,但读出的数据会落后地址两个周期。很多情况下,不使能这项功能,保持数据落后地址一个周期。

完成配置后,点击“Generate”生成 RAM IP。

2)伪双端口RAM的端口定义和时序

Simple Dual Port RAM 模块端口的说明如下:

信号名称 方向 说明
clka in 端口A时钟输入
wea in 端口A使能
addra in 端口A地址输入
dina in 端口A数据输入
clkb in 端口B时钟输入
addrb in 端口B地址输入
doutb in 端口B数据输出
图1 写时序 图2 读时序

RAM 的数据写入和读出都是按时钟的上升沿操作的,端口 A 数据写入的时候需要置高wea 信号,同时提供地址和要写入的数据。

而端口 B 是不能写入数据的,只能从 RAM 中读出数据,只要提供地址就可以了,一般情况下可以在下一个周期采集到有效的数据。

3)编写测试程序

/** 当计数范围在 0~511 之间时,向 ram 中写入数据;* 当计数范围在 512~1023 之间时,从 ram 中读出数据。*/module ip_simple_port_ram_test(input   clk,input   rst_n);wire ram_wea;
reg     [8:0]   ram_wr_addr;
reg     [15:0]  ram_wr_data;
reg     [8:0]   ram_rd_addr;
wire    [15:0]  ram_rd_data;reg [9:0] cnt; //读写使能信号
assign ram_wea = (cnt < 10'd512) ? 1'b1:1'b0; //计数器 范围(0~1023)
always @(posedge clk or negedge rst_n) beginif(!rst_n)cnt <= 1'b0;else if(cnt == 10'd1023)cnt <= 1'b0;elsecnt <= cnt + 1'b1;
end//写信号地址及数据
always @(posedge clk or negedge rst_n) beginif(!rst_n) beginram_wr_addr <= 1'b0;ram_wr_data <= 1'b0;endelse if(ram_wr_addr == 9'd511 && ram_wr_data == 16'd511) beginram_wr_addr <= 1'b0;ram_wr_data <= 1'b0;    endelse beginram_wr_addr <= ram_wr_addr + 1'b1;ram_wr_data <= ram_wr_data + 1'b1;end
end//读信号地址
always @(posedge clk or negedge rst_n) beginif(!rst_n) ram_rd_addr <= 1'b0;else if (ram_rd_addr == 9'd511)ram_rd_addr <= 1'b0;elseram_rd_addr <= ram_rd_addr + 1'b1;
end//例化 ip ram核
ip_simple_ram u_ip_simple_ram (.clka(clk),    // input wire clka.wea(ram_wea),      // input wire [0 : 0] wea.addra(ram_wr_addr),  // input wire [8 : 0] addra.dina(ram_wr_data),    // input wire [15 : 0] dina.clkb(clk),    // input wire clkb.addrb(ram_rd_addr),  // input wire [8 : 0] addrb.doutb(ram_rd_data)  // output wire [15 : 0] doutb
);endmodule

4)编写激励文件

`timescale 1ns / 1psmodule tb_ip_simport_ram();reg      clk;
reg     rst_n;initial beginclk = 1'b0;rst_n = 1'b0;#200rst_n = 1'b1;
endalways #10 clk = ~clk;ip_simple_port_ram_test u_ip_simple_port_ram_test(.clk    (clk),.rst_n  (rst_n)
);endmodule

5)仿真测试

6)ILA测试

添加 ILA IP 核,将 ram_wea、ram_wr_addr、ram_wr_data 、ram_rd_addr和ram_rd_data 信号添加至观察列表中。

图1 PICTURE ONE 图2 PICTURE TWO

ILA 的时钟和探针信号连接到顶层设计中,例化 ILA IP 核的代码如下:

//例化 ILA IP核
ila_0 your_instance_name (.clk(clk), // input wire clk.probe0(ram_wea), // input wire [0:0]  probe0  .probe1(ram_wr_addr), // input wire [8:0]  probe1 .probe2(ram_wr_data), // input wire [15:0]  probe2 .probe3(ram_rd_addr), // input wire [8:0]  probe3 .probe4(ram_rd_data) // input wire [15:0]  probe4
);

最后为工程添加 IO 管脚约束,对应的 XDC 约束语句如下所示:

set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports sys_clk]
set_property -dict {PACKAGE_PIN J15 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]

生成比特流之后,直接点击“Program”,此时 Vivado 会自动打开 ILA 的调试窗口,如下图所示:


IP 核之RAM实验相关推荐

  1. 【正点原子MP157连载】 第十四章 IP核之RAM实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  2. 【正点原子FPGA连载】第十四章 IP核之RAM实验 -摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  3. 异步fifo_正点原子开拓者FPGA开发板资料连载第十五章 IP核之FIFO实验

    1)实验平台:正点原子开拓者FPGA 开发板 2)摘自<开拓者FPGA开发指南>关注官方微信号公众号,获取更多资料:正点原子 3)全套实验源码+手册+视频下载地址:http://www.o ...

  4. 【正点原子FPGA连载】第十五章 IP核之FIFO实验 -摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  5. 如何测试IP核(RAM为例)

    如何测试IP核(RAM为例) (读出数据有两个时钟的延时) 了解RAM IP 核的几种工作方式. Simple Dual port RAM (简化双口RAM):A端只能写入,B端只能读出. Singl ...

  6. qq自定义diy名片代码复制_「正点原子FPGA连载」第六章自定义IP核-呼吸灯实验

    1)摘自[正点原子]领航者 ZYNQ 之嵌入式开发指南 2)实验平台:正点原子领航者ZYNQ开发板 3)平台购买地址:https://item.taobao.com/item.htm?&id= ...

  7. 【ZYNQ】从入门到秃头06 Vivado下的IP核MMC/PLL实验

    文章目录 实验原理 创建Vivado工程 仿真 板上验证 生成其他PLL信号 很多初学者看到板上只有一个50Mhz 时钟输入的时候都产生疑惑,时钟怎么才 50Mhz ?如果要工作在 100Mhz . ...

  8. Altera FPGA 储存单元IP核之RAM、FIFO

    一.储存单元简介 1.ROM 只读存储器,系统上电后数据就被写入ROM,运行过程中只能从ROM中读取数据,而不能改变ROM中的数值. 2.RAM 随机存取储存器,可以随时把数据写入任一指定地址的储存单 ...

  9. FPGA IP核之RAM

    1.RAM简介 RAM 是随机存取存储器(Random Access Memory)的简称,是一个易失性存储器.RAM 工作时可以随时从任何一个指定的地址写入或读出数据,同时我们还能修改其存储的数据, ...

最新文章

  1. logo qt添加_linux下如何给qt程序添加图标?
  2. IdentityHashMap
  3. GitHub初次使用记录(一)
  4. mysql保存plc数据_MySQL空间数据的保存
  5. sqlserver函数 1209
  6. clonecd中文破解版|clonecdv光盘复制工具5.5.1.4绿色免费版下载
  7. 关于Java中TCP/IPMonitor监听器无响应的心得
  8. 常用Gis通用符号库大全
  9. OpenCV老版本下载方法
  10. 富士施乐m115b怎么连接电脑_富士施乐m115b驱动下载
  11. crmeb 多商户小程序配置
  12. winows+Eclipse下Mahout配置
  13. 如何将win7电脑变身WIFI热点,让手机、笔记本共享上网?
  14. 教育教培行业年终工作总结ppt制作幻灯片模板设计.pptx
  15. Gym 100015H Hidden Code
  16. python错误:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb5 in position 0: invalid start byte
  17. Linux lolcat输出彩色格言
  18. SAP 上传图片至系统
  19. pdf的下载和在线预览
  20. xmr monero miner

热门文章

  1. iOS系统中导航栏的转场解决方案与最佳实践
  2. N012_根据明细表自动统计,然后将标题拉平 二维列标题变成一维
  3. ROS安装 rosdep init 或者rosdep update 出错(很有用)
  4. 京东java多级缓存_多级缓存设计详解 | 给数据库减负,刻不容缓!
  5. 前端表白纪念日用js+html+css实现的页面代码复制粘贴就能用
  6. 计算机ip地址和用户名和密码是什么,华为路由器登录入口用户名和密码是多少...
  7. Finalize、Dispose、Close 的区别与使用[C#基础]
  8. VR全景技术炙手可热,VR全景教育将颠覆传统教育模式?道可云
  9. 卡巴斯基推出自己的香水产品
  10. java发微信_java访问微信接口发送消息