RAM IP核
RAM: Random Access Memory, 随机存取存储器。
可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据,将地址作为索引
读写速度是由时钟频率决定的。
作用: 主要用来存放程序以及程序执行过程中产生的中间数据、结果等
RAM IP核简介
通过对BRAM( 块RAM )存储器模块进行配置,可以实现各种存储器功能( RAM, 移位寄存器,ROM以及FIFO缓冲器 )
Block RAM资源, 一片是36K
每一片RAM有完全独立的读写端口
每一个端口都可以配置为32Kx1, 16Kx2, 8Kx4, 4Kx9(or8), 1Kx36(or 32), 512x72(or 64), 常用位宽为8,16,32
36K 资源不一定能够完全使用, 只有在特定的位宽才可以使用36K
每一块Block RAM可以被分割成独立的两块18K块RAM使用
所有的Block RAM的读写位宽都可以改变
两个邻近的36KBlock RAM,可以被配置成为一个64Kx1的双端口RAM
Vivado的BMG IP核( Block Memory Generator , 块RAM生成器),可以配置成RAM或者ROM。
- RAM,随机存取存储器,可读可写
- ROM, 只读存储器,正常工作时只读
两者使用资源都是FPGA内部的BRAM, 不过ROM只用到了BRAM的读数据端口。
RAM分类: 真双端口RAM, 伪双端口RAM,单端口RAM
- 真双端口RAM( True Dual-Port RAM, TDP), 两个端口都可以独立的对BRAM进行读写
- 伪双端口RAM( Simple Dual-Port RAM, SDP), 有两个端口,其中一个只能读,另一个只能写
- 单端口RAM, 只有一个RAM, 读写通过这一个端口来进行
单端口RAM只有一组数据线、地址线、时钟信号以及控制信号,双端口RAM具有两组数据线、地址线、时钟信号以及控制信号。
Xilinx 7系列的内部BRAM全部是真双端口RAM,两个端口可以独立的进行读写,可以被配置成不同的RAM形式。
端口描述
- DINA: 端口A写数据信号
- ADDRA: 端口A,读写地址信号,对于单端口RAM来说,读地址和写地址共用该地址线
- WEA: 端口A写使能信号,1->写有效,0->读有效
- ENA: 端口A写使能信号,高有效。禁止后端口A上的读写无效。ENA信号可选,取消该信号后,RAM一直处于有效状态。
- RSTA:端口A复位信号,可配置为高有效或者低有效,可选信号
- REGCEA: 端口A输出寄存器使能信号,为1时,DOUTA保持最后一次输出的数据,可选信号
- CLKA: 端口A的时钟信号
- DOUTA: 端口A读出的数据。
RAM IP核配置
- Basic
- 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 : Error Correction Capability 纠错能力选项 ( 单端口RAM不支持ECC )
- Write Enable: 字节写使能选项,勾选后可以单独将数据的某个字节写入RAM中
- Algorithm Options: 算法选项
- Minimum Area 最小面积
- Low Power 低功耗
- Fixed Primitives 固定原语
- Port A 选项,设置端口A的参数
- Write Width 写数据位宽( Bit )
- Read Width
- Write Depth 写深度,例如设置为32,RAM所能访问的地址范围为0-31
- Read Depth
- Operating Mode: RAM 读写操作模式,共三种模式
- Write First 写优先, 数据先写入RAM,然后在下一个时钟输出该数据
- Read First 读优先, 数据先写入RAM中,同时输出RAM中同地址的上一次数据
- No Change 不变模式,读写分开操作,不能同时进行
- Enable Port Type: 使能端口类型
- Use ENA Pin 添加使能端口A信号
- Always Enabled 取消使能信号,端口一直处于使能状态
- Port A Optional Output Register : 端口A输出寄存器选项
- Primitives Output Register ,打开BRAM内部位于输出数据总线之后的输出流水线寄存器。
一般设计中为了改善时序性能会勾选此选项,但是会使得BRAM输出的数据延迟一拍。
数据输出总线负载多,可能带来难以满足的时序路径
- Port A Output Reset Options : RAM 复位信号选项。
- Other Options 设置RAM的初始值
RAM IP核仿真
.veo 文件是IP核自动生成的只读verilog例化模板文件。
文件1 ram_wr.v
产生读写RAM的信号, 写入32个数,再读出32个数
`timescale 1ns / 1ns // // Engineer: wkk // // Create Date: 2023/03/20 16:18:49 // Design Name: // Module Name: ram_wr // module ram_wr( input i_clk , input i_rst_n , input i_en , output o_wr_mode , output [4:0] o_wr_addr , output [7:0] o_w_data ); reg [5:0] cnt ; reg [5:0] cnt_reg ; reg wr_mode_reg ; //reg [7:0] o_w_data_reg ; assign o_w_data = {2'b0,cnt} ; assign o_wr_addr = cnt_reg[4:0] ; always @(posedge i_clk or negedge i_rst_n ) begin if( !i_rst_n )begin cnt_reg <= 6'b0; end else cnt_reg <= cnt; end always @(posedge i_clk or negedge i_rst_n ) begin if( !i_rst_n )begin cnt <= 6'b0; end else if(i_en) begin if( cnt == 6'd63 ) cnt <= 6'b0; else cnt <= cnt + 1'b1; end else begin cnt <= 6'b0 ; end end assign o_wr_mode = wr_mode_reg; always @(posedge i_clk or negedge i_rst_n ) begin if( !i_rst_n ) wr_mode_reg <= 1'b0; // default read mode else if(i_en && cnt <= 6'd30 ) wr_mode_reg <= 1'b1; else wr_mode_reg <= 1'b0; end endmodule
文件2 ram_test_top.v
进行ram读写
`timescale 1ns / 1ns // // Engineer: wkk // // Create Date: 2023/03/20 16:55:18 // Design Name: // Module Name: ram_test_top // module ram_test_top( input i_clk , input i_rst_n , output [7:0] o_r_data ); //reg i_en ; wire o_wr_mode ; wire [4:0] o_wr_addr ; wire [7:0] o_w_data ; ram_wr ram_wr_inst( .i_clk ( i_clk ), .i_rst_n ( i_rst_n ), .i_en ( 1'b1 ), .o_wr_mode ( o_wr_mode ), .o_wr_addr ( o_wr_addr ), .o_w_data ( o_w_data ) ); singleport_ram_8x32 singleport_ram_8x32_inst ( .clka (i_clk ), // input wire clka .wea (o_wr_mode ), // input wire [0 : 0] wea .addra (o_wr_addr ), // input wire [4 : 0] addra .dina (o_w_data ), // input wire [7 : 0] dina .douta (o_r_data ) // output wire [7 : 0] douta ); endmodule
文件3 ram_test_top_tb.v
`timescale 1ns / 1ns // // Engineer: wkk // // Create Date: 2023/03/22 23:00:02 // Design Name: // Module Name: ram_test_top_tb // module ram_test_top_tb(); reg i_clk ; reg i_rst_n ; wire [7:0] o_r_data ; ram_test_top ram_test_top_inst( .i_clk (i_clk ) , .i_rst_n (i_rst_n ) , .o_r_data (o_r_data) ); initial begin i_clk = 1'b0; i_rst_n = 1'b0; forever #5 i_clk = ~i_clk; end initial begin #10 i_rst_n = 1'b1; #1000 $stop; end endmodule
仿真结果
- 写数据,写入1-31
- 读数据,读出1-31
RAM 中读出的数据在延时一个时钟周期之后,开始输出数据