Xilinx-IP核 Distributed Memory Generator
一、功能简介
1. 存储器类型生成
- ROM生成:可创建只读存储器,用于存储固定的数据或程序代码,如查找表、字符编码表等,在系统运行时提供稳定的只读数据。
- 单端口RAM生成:能生成单端口随机存取存储器,通过单一的端口进行数据的读写操作,适用于同一时刻只需要进行读或写操作的场景,如简单的数据缓存。
- 双端口RAM生成:包括简单双端口和真双端口RAM。简单双端口RAM通常一个端口用于写操作,另一个端口用于读操作,常用于跨时钟域数据传输、数据缓存等。真双端口RAM的两个端口都可独立进行读写操作,适用于需要同时在两个不同的时钟域或逻辑模块中对同一存储区域进行读写的复杂场景。
- 基于SRL16的RAM生成:可生成基于SRL16的RAM,用于一些对存储深度要求不高,但需要特定移位寄存器功能的应用,如实现数据的串行移位、延迟等操作。
2. 数据宽度与深度配置
- 数据宽度灵活:支持1到1024位之间的数据宽度选择,可满足不同数据类型和应用的需求,比如存储单个字节数据、多字节整数、浮点数或自定义的数据结构等。
- 数据深度可选:数据深度范围为16到65536,以16为步长进行配置,能适应不同存储容量需求,从小规模的缓存到较大规模的数据存储都能实现。
3. 输入输出选项配置
- 输入寄存器可选:可选择是否在地址输入、数据输入和写使能等信号上添加寄存器,对输入信号进行寄存,以提高信号的稳定性和同步性,便于与其他模块进行接口。
- 输出寄存器可选:能选择是否在输出端口添加寄存器,对输出数据进行寄存,使输出数据在时钟的控制下更加稳定,减少输出毛刺和延迟。
- 时钟使能功能:提供输入时钟使能和输出时钟使能信号,可灵活控制输入输出数据的有效时间,便于在多时钟域或复杂的逻辑控制中进行数据的同步和管理。
- 流水线选项:当选择寄存器模式的单端口RAM、简单双端口RAM和双端口RAM时,可在输出路径中放置可选的流水线寄存器,提高系统的运行速度和数据处理效率。
4. 复位与初始化功能
- 复位选项:支持异步复位和同步复位两种方式,可分别对单端口输出和双端口输出进行复位操作,确保在系统启动或出现异常情况时,存储器能够恢复到初始状态。
- 初始化功能:可通过加载COE文件来设置存储元件的初始值,也能设置默认数据,在未加载COE文件或COE文件中未初始化的内存位置,使用默认数据进行初始化。
二、与BMG对比
二、设置界面
`timescale 1ns / 1ns module blk_mem_gen_tb(); reg clka ='d0; reg ena ='d1; reg [0 : 0] wea ='d1; reg [5 : 0] addra ='d0; reg [15 : 0] dina ='d0; reg clkb ='d1; reg enb ='d1; reg [5 : 0] addrb ='d0; wire [15 : 0] doutb ; wire [7 : 0] bhigh; wire [7 : 0] blow; reg [2 : 0] s_addr_a_flag = 'd0; reg s_a_flag = 'd0; reg [2 : 0] s_a_flag_2_b = 'd0; reg s_b_flag = 'd0; reg [2 : 0] s_clk_cnt8 = 'd0; always#1 clka=~clka; always#1 clkb=~clkb; assign blow = doutb[7:0]; assign bhigh = doutb[15:8]; always @(posedge clka) if (ena && wea) begin addra <= addra + 1'b1; dina <= dina + 1'b1; end always @(posedge clka) s_addr_a_flag[0] <= (addra == 4'd15); always @(posedge clka) s_addr_a_flag[2:1] <= s_addr_a_flag[1:0]; always @(posedge clka) s_a_flag <= |s_addr_a_flag; always @(posedge clkb) s_a_flag_2_b <= {s_a_flag_2_b[1:0],s_a_flag}; always @(posedge clkb) s_b_flag <= (~s_a_flag_2_b[2] && s_a_flag_2_b[1]); always @(posedge clkb) if((s_clk_cnt8 > 3'd2)&& s_b_flag) s_clk_cnt8 <= 3'd2; else s_clk_cnt8 <= s_clk_cnt8 + 1'b1; always @(posedge clkb) if(s_clk_cnt8 == 3'd3) addrb <= 'd0; else addrb <= addrb + 1'b1; dist_mem_gen_0 your_instance_name ( .a(addra), // input wire [5 : 0] a .d(dina), // input wire [15 : 0] d .dpra(addrb), // input wire [5 : 0] dpra .clk(clka), // input wire clk .we(wea), // input wire we .qdpo_clk(clkb), // input wire qdpo_clk .qdpo(doutb) // output wire [15 : 0] qdpo ); endmodule
真双端口模式下:
qspo-遵循clka,且在addra走完一个循环后开始输出
qdpo-遵循clkb,在addrb第一次出现0时开始输出