FPGA基础知识(十九):Xilinx Block Memory IP核(4)--True Dual Port RAM 详解

《FPGA基础知识》系列导航  

        本专栏专为FPGA新手打造的Xilinx平台入门指南。旨在手把手带你走通从代码、仿真、约束到生成比特流并烧录的全过程。

       本篇是该系列的第十九篇内容

       上一篇:FPGA基础知识(十八):Xilinx Block Memory IP核(3)--Single Dual Port RAM 详解-优快云博客

       下一篇:关注我,第一时间获取更新!!


1 引言

        如果说Simple Dual Port RAM是“读写分离的单向车道”,那么True Dual Port RAM就是完全双向的双车道高速公路。两个端口(Port A和Port B)都完全独立,且都可以执行读或写操作。

2 配置

外部接口,如下图,每个端口都有其独立的en信号和 we信号

        与Single Dual Port RAM类似,它也是有两个端口PortA 和 PortB

        不同的是 True Dual Port RAM的两个端口都是可以独立配置其位宽和工作模式的

        关于三种模式的时序我们在单端口模式的分享的时候做了详细的说明,这里就不再赘述了

FPGA基础知识(十七):Xilinx Block Memory IP核(2)--单端口 RAM 的三种操作模式详解-优快云博客

3 仿真 

         我们看一下仿真,这是将PortA 和Port B都配置为no change模式的仿真情况,可以看到

        两个端口目前设定的是分时工作:

        Port A写-->port A读--->port B写--->port B读 这样的情况下,目前这样的设定看似没有相互影响的

但其实这里有一个关键点:
        不管我们操作的是PortA 还是 PortB   我们操作的都是同一块BRAM区域,只是按照地址进行了划分,那就会有几种情况

        第一种:双端口同时读同一地址,如下图,Port A“提前”向地址1和2写入数据D0和D1,port A和portB同时读地址1和2的数据,这种情况,不会相互影响。

        第二种:一端写,另一端读同一地址,这种情况就一定要注意三种模式的配置 和 与应用之间的协调。

        第三种:两个端口同时写同一地址,这就很危险,结果也会不确定,因为你很难预判最终写成功的数据到底是A的还是B的,所以必须要避免这种情况

        第四种:读写同时,但是地址不同,这种情况也是没有影响的哈


        True Dual Port RAM是Xilinx Block Memory Generator IP核中功能最全面的存储解决方案。它提供了最大的设计灵活性,但同时也带来了更高的设计复杂性;

module softmax_data_memory ( input wire clk, input wire rst_n, // PORTA input wire [11:0]BRAM_PORTA_1_addr, input wire [31:0]BRAM_PORTA_1_din, output wire [31:0]BRAM_PORTA_1_dout, input wire BRAM_PORTA_1_en, input wire BRAM_PORTA_1_rst, input wire [3:0]BRAM_PORTA_1_we, // PORTB input wire [31:0] mem_addr, input wire read_req, output reg read_ack, output wire [31:0] read_data, input wire write_req, input wire write_we, input wire [31:0] write_data, output reg write_ack ); // 参数定义 parameter DATA_WIDTH = 32; parameter MEMORY_SIZE = 2**11; // 内存大小(以32位为单位) parameter ADDR_WIDTH = 11; // 地址位宽 (2^32 ) parameter MEM_PRIMITIVE = "auto" ; //自动选择 Block/Distributed RAM parameter MEM_INIT_FILE = "none" ; parameter READ_LATENCY_A = 1 ; parameter READ_LATENCY_B = 1 ; // 地址转换(字节地址转换为字地址) wire [ADDR_WIDTH-1:0] word_addrb = mem_addr[ADDR_WIDTH+1:2]; // 原语控制信号 wire [DATA_WIDTH-1:0] doutb; wire ena = BRAM_PORTA_1_en; wire enb = write_req || read_req; wire [0:0] wea = |BRAM_PORTA_1_we; //单bit 写使能 wire [0:0] web = write_we; //单bit 写使能 // 应答逻辑(独立于原语) always@(posedge clk or negedge rst_n) begin if(!rst_n) begin read_ack <= 1'b0; write_ack <= 1'b0; end else begin read_ack <= read_req; //读延迟1周期 write_ack <= write_req & write_we; //写延迟1周期 end end // xpm_memory_tdpram: True Dual Port RAM // Xilinx Parameterized Macro, version 2021.2 //PORTA-CPU; PORTB-SOFTMAX xpm_memory_tdpram #( .ADDR_WIDTH_A(ADDR_WIDTH), // DECIMAL .ADDR_WIDTH_B(ADDR_WIDTH), // DECIMAL .AUTO_SLEEP_TIME(0), // DECIMAL .BYTE_WRITE_WIDTH_A(DATA_WIDTH), // DECIMAL .BYTE_WRITE_WIDTH_B(DATA_WIDTH), // DECIMAL .CASCADE_HEIGHT(0), // DECIMAL .CLOCKING_MODE("common_clock"), // String .ECC_MODE("no_ecc"), // String .MEMORY_INIT_FILE(MEM_INIT_FILE), // String .MEMORY_INIT_PARAM("0"), // String .MEMORY_OPTIMIZATION("true"), // String .MEMORY_PRIMITIVE(MEM_PRIMITIVE), // String .MEMORY_SIZE(MEMORY_SIZE*DATA_WIDTH), // DECIMAL .MESSAGE_CONTROL(0), // DECIMAL .READ_DATA_WIDTH_A(DATA_WIDTH), // DECIMAL .READ_DATA_WIDTH_B(DATA_WIDTH), // DECIMAL .READ_LATENCY_A(READ_LATENCY_A), // DECIMAL .READ_LATENCY_B(READ_LATENCY_B), // DECIMAL .READ_RESET_VALUE_A("0"), // String .READ_RESET_VALUE_B("0"), // String .RST_MODE_A("SYNC"), // String .RST_MODE_B("SYNC"), // String .SIM_ASSERT_CHK(1), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages .USE_EMBEDDED_CONSTRAINT(0), // DECIMAL .USE_MEM_INIT(1), // DECIMAL .USE_MEM_INIT_MMI(0), // DECIMAL .WAKEUP_TIME("disable_sleep"), // String .WRITE_DATA_WIDTH_A(DATA_WIDTH), // DECIMAL .WRITE_DATA_WIDTH_B(DATA_WIDTH), // DECIMAL .WRITE_MODE_A("no_change"), // String .WRITE_MODE_B("no_change"), // String .WRITE_PROTECT(1) // DECIMAL ) xpm_memory_tdpram_inst ( .dbiterra(), // 1-bit output: Status signal to indicate double bit error occurrence // on the data output of port A. .dbiterrb(), // 1-bit output: Status signal to indicate double bit error occurrence // on the data output of port A. .douta(BRAM_PORTA_1_dout), // READ_DATA_WIDTH_A-bit output: Data output for port A read operations. .doutb(read_data), // READ_DATA_WIDTH_B-bit output: Data output for port B read operations. .sbiterra(), // 1-bit output: Status signal to indicate single bit error occurrence // on the data output of port A. .sbiterrb(), // 1-bit output: Status signal to indicate single bit error occurrence // on the data output of port B. .addra(BRAM_PORTA_1_addr), // ADDR_WIDTH_A-bit input: Address for port A write and read operations. .addrb(word_addrb), // ADDR_WIDTH_B-bit input: Address for port B write and read operations. .clka(clk), // 1-bit input: Clock signal for port A. Also clocks port B when // parameter CLOCKING_MODE is "common_clock". .clkb(clk), // 1-bit input: Clock signal for port B when parameter CLOCKING_MODE is // "independent_clock". Unused when parameter CLOCKING_MODE is // "common_clock". .dina(BRAM_PORTA_1_din), // WRITE_DATA_WIDTH_A-bit input: Data input for port A write operations. .dinb(write_data), // WRITE_DATA_WIDTH_B-bit input: Data input for port B write operations. .ena(ena), // 1-bit input: Memory enable signal for port A. Must be high on clock // cycles when read or write operations are initiated. Pipelined // internally. .enb(enb), // 1-bit input: Memory enable signal for port B. Must be high on clock // cycles when read or write operations are initiated. Pipelined // internally. .injectdbiterra(1'b0), // 1-bit input: Controls double bit error injection on input data when // ECC enabled (Error injection capability is not available in // "decode_only" mode). .injectdbiterrb(1'b0), // 1-bit input: Controls double bit error injection on input data when // ECC enabled (Error injection capability is not available in // "decode_only" mode). .injectsbiterra(1'b0), // 1-bit input: Controls single bit error injection on input data when // ECC enabled (Error injection capability is not available in // "decode_only" mode). .injectsbiterrb(1'b0), // 1-bit input: Controls single bit error injection on input data when // ECC enabled (Error injection capability is not available in // "decode_only" mode). .regcea(1'b1), // 1-bit input: Clock Enable for the last register stage on the output // data path. .regceb(1'b1), // 1-bit input: Clock Enable for the last register stage on the output // data path. .rsta(~rst_n), // 1-bit input: Reset signal for the final port A output register stage. // Synchronously resets output port douta to the value specified by // parameter READ_RESET_VALUE_A. .rstb(~rst_n), // 1-bit input: Reset signal for the final port B output register stage. // Synchronously resets output port doutb to the value specified by // parameter READ_RESET_VALUE_B. .sleep(1'b0), // 1-bit input: sleep signal to enable the dynamic power saving feature. .wea(wea), // WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A-bit input: Write enable vector // for port A input data port dina. 1 bit wide when word-wide writes are // used. In byte-wide write configurations, each bit controls the // writing one byte of dina to address addra. For example, to // synchronously write only bits [15-8] of dina when WRITE_DATA_WIDTH_A // is 32, wea would be 4'b0010. .web(web) // WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B-bit input: Write enable vector // for port B input data port dinb. 1 bit wide when word-wide writes are // used. In byte-wide write configurations, each bit controls the // writing one byte of dinb to address addrb. For example, to // synchronously write only bits [15-8] of dinb when WRITE_DATA_WIDTH_B // is 32, web would be 4'b0010. ); // End of xpm_memory_tdpram_inst instantiation endmodule 这是同一块RAM,分地址双端口独立访问吗,一共定义了几块ram
07-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FPGA_小田老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值