当前位置: 首页 > article >正文

ZYNQ-PL学习实践(四)IP核之读写RAM

ZYNQ-PL学习实践(四)IP核之读写RAM)

  • 1 概述
  • 2 硬件管脚约束
  • 3 搭建IP核
  • 4 创建新的verilog文件
  • 5 创建另一个实例化
  • 6 仿真文件
  • 7 编译、下载
  • 总结

1 概述

RAM(随机存取存储器), 它用来随时把数据写入或者读取任一指定地址的存储单元。RAM 主要用来存放程序及程序执行过程中产生的中间数据、 运算结果等。
XILINX 7系列BRAM IP核可配置成单端口RAM、也可以配置成双端口RAM。本文介绍配置成单端口 RAM 。
本文介绍xilinx RAM IP 核。
单端口RAM框图如下,
在这里插入图片描述
单端口RAM端口介绍,

DINA	: RAM 端口A写数据信号。
ADDRA	: RAM 端口A读写地址信号,读地址、写地址共用同该地址线。
WEA		: RAM 端口A写使能信号, 高电平表示向 RAM 中写入数据,低电平表示从 RAM 中读出数据。
ENA		: 端口A的使能信号, 高电平表示使能端口A, 低电平表示端口 A 被禁止。
RSTA	: RAM 端口A复位信号,可配置成高电平或者低电平复位。
REGCEA	: RAM 端口A输出寄存器使能信号, 当 REGCEA 为高电平时, DOUTA 保持最后一次输出的数据。
CLKA	: RAM 端口A的时钟信号。
DOUTA	: RAM 端口A读出的数据。

接下来介绍 Vivado 软件携带了 BMG IP 核(块 RAM 生成器),配置成单端口RAM,进行读写操作。

2 硬件管脚约束

关于时钟、复位如下,

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]

3 搭建IP核

选择Block Memory Generator,
在这里插入图片描述

在这里插入图片描述

Interface Type:

选择 Native 接口类型(标准 RAM 接口总线)。

Memory Type选项如下,

Memory Type(存储器类型):
可配置成 Single Port RAM(单端口 RAM)

Simple Dual Port RAM	(伪双端口 RAM)
True Dual Port RAM		(真双端口 RAM)
Single Port ROM			(单端口 ROM)
Dual Port ROM			(双端口 ROM)

ECC Options(纠错能力选项):

单端口 RAM 不支持 ECC。

Write Enable(字节写使能选项):

勾中后可以单独将数据的某个字节写入 RAM 中,这里不使能。

Algorithm Options(算法选项):

 Minimum Area 		(最小面积)
 Low Power 			(低功耗)
 Fixed Primitives	(固定的原语)

点击Port A Option,
在这里插入图片描述

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(不变模式)。

使能端口类型

Enable Port Type(使能端口类型): Use ENA pin(添加使能端口 A 信号); Always Enabled(取消使能信号)

Port A Optional Output Register(端口 A 输出寄存器选项)

Port A Output Reset Options(RAM 复位信号选项):这里不添加复位信号,保持默认即可。
.

在这里插入图片描述
点击OK,
在这里插入图片描述
在“Design Run”窗口的“Out-of-Context Module Runs”一栏中出现了该 IP 核对应的run“blk_mem_gen_0_synth_1”,正在综合如下图,
在这里插入图片描述

4 创建新的verilog文件

verilog文件包含如下:

tb_ip_ram.v
ip_ram.v
ram_rw.v

创建一个新的设计文件 ram_rw.v,

module ram_rw(
    input               clk        ,  //时钟信号
    input               rst_n      ,  //复位信号,低电平有效
    
    output              ram_en     ,  //ram使能信号
    output              ram_wea    ,  //ram读写选择
    output  reg  [4:0]  ram_addr   ,  //ram读写地址
    output  reg  [7:0]  ram_wr_data,  //ram写数据
    input        [7:0]  ram_rd_data   //ram读数据        
    );

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

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

//读写控制计数器,计数器范围0~63
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        rw_cnt <= 1'b0;    
    else if(rw_cnt == 6'd63)
        rw_cnt <= 1'b0;
    else
        rw_cnt <= rw_cnt + 1'b1;    
end  

//产生RAM写数据
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        ram_wr_data <= 1'b0;  
    else if(rw_cnt <= 6'd31)  //在计数器的0-31范围内,RAM写地址累加
        ram_wr_data <= ram_wr_data + 1'b1;
    else
        ram_wr_data <= 1'b0 ;   
end  

//读写地址信号 范围:0~31
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)
        ram_addr <= 1'b0;
    else if(ram_addr == 5'd31)
        ram_addr <= 1'b0;
    else    
        ram_addr <= ram_addr + 1'b1;
end

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 [0:0]  probe2 
    .probe3(ram_wr_data),// input wire [4:0]  probe3 
    .probe4(ram_rd_data) // input wire [7:0]  probe4 
);

endmodule

5 创建另一个实例化

实例化创建的 RAM IP 核以及 ram_rw 模块文件名 ip_ram.v,

module ip_ram(
    input         sys_clk ,  //系统时钟
    input         sys_rst_n  //系统复位,低电平有效
    );

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

//ram读写模块
ram_rw  u_ram_rw(
    .clk            (sys_clk     ),
    .rst_n          (sys_rst_n   ),
	//RAM
	.ram_en         (ram_en      ),
    .ram_wea        (ram_wea     ),
    .ram_addr       (ram_addr    ),
    .ram_wr_data    (ram_wr_data ),
    .ram_rd_data    (ram_rd_data )
    );

//ram ip核
blk_mem_gen_0  blk_mem_gen_0 (
	.clka  (sys_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

6 仿真文件

对 RAM IP 核进行 仿真,文件tb_ip_ram,

`timescale 1ns / 1ps

module tb_ip_ram();

reg     sys_clk;
reg     sys_rst_n;      

always #10 sys_clk = ~sys_clk;

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

ip_ram u_ip_ram(
    .sys_clk          (sys_clk        ),
    .sys_rst_n        (sys_rst_n      )
    );

endmodule

7 编译、下载

略。。。

总结

待定。。。

感谢阅读,祝君成功!
-by aiziyou


http://www.kler.cn/a/572920.html

相关文章:

  • 使用vivado2023.2新版Vitis创建hello world项目以及新版vitis的一些说明
  • 前端基础之组件自定义事件
  • 项目工坊 | Python驱动淘宝信息爬虫
  • CSS设置文字渐变色样式(附带动画效果)
  • 鸿蒙5.0实战案例:基于OpenGL渲染视频画面帧
  • 网络编程之TCP协议
  • 数据结构:八大排序(冒泡,堆,插入,选择,希尔,快排,归并,计数)详解
  • CHAPTER 5 Data Class Builders
  • MWC 2025 | 移远通信大模型解决方案加速落地,引领服务机器人创新变革
  • Tripo3D使用体验
  • C语言_图书管理系统_借阅系统管理
  • E22-xxxT22D lora模块配置
  • OpenFeign 学习笔记
  • 并查集—数组实现
  • 【Linux】进程间通信 续
  • 美颜SDK架构揭秘:人脸美型API的底层实现与优化策略
  • 立体仓WMS同MES制造的协同
  • upload-labs Pass5-18 文件上传
  • 观察者模式的C++实现示例
  • 从零开始的kafka学习 (一)| 概念,Java API