如何在Vivado中同周期写入12个地址且被识别为BRAM
问题:实现12×14结构RAM的单周期整列写入并映射为BRAM
以下是原本可被综合为BRAM的RAM代码:
module RAM_IMAGINARY (clk, we, en, addr, di, dout); input clk; input we; input en; input [7:0] addr; input [15:0] di; output [15:0] dout; logic [15:0] RAM_IMAGINARY [167:0]; logic [15:0] dout; always @(posedge clk) begin if (en)begin if (we) begin RAM_IMAGINARY[addr] <= di; dout <= di; end else dout <= RAM_IMAGINARY[addr]; end end endmodule
需求是将RAM视为12×14的二维结构,实现单周期写入整列数据。曾尝试例化12个小容量RAM并行写入,但因每个RAM的深度(14)和宽度(16bit)过小,未被工具识别为BRAM,相关代码如下:
小容量RAM模块
module RAM_IMAGINARY (clk, we, en, addr, di, dout); input clk; input we; input en; input [7:0] addr; input [15:0] di; output [15:0] dout; logic [15:0] RAM_IMAGINARY [13:0]; logic [15:0] dout; always @(posedge clk) begin if (en)begin if (we) begin RAM_IMAGINARY[addr] <= di; dout <= di; end else dout <= RAM_IMAGINARY[addr]; end end endmodule
顶层例化模块
module Top(clk, we, en, addr, di, dout0,dout1,dout2,dout3,dout4,dout5,dout6,dout7,dout8,dout9,dout10,dout11); input clk; input we; input en; input [7:0] addr; input [15:0] di; output [15:0] dout0,dout1,dout2,dout3,dout4,dout5,dout6,dout7,dout8,dout9,dout10,dout11; RAM_IMAGINARY RAM0 (clk, we, en, addr, di, dout0) ; RAM_IMAGINARY RAM1 (clk, we, en, addr, di, dout1) ; RAM_IMAGINARY RAM2 (clk, we, en, addr, di, dout2) ; RAM_IMAGINARY RAM3 (clk, we, en, addr, di, dout3) ; RAM_IMAGINARY RAM4 (clk, we, en, addr, di, dout4) ; RAM_IMAGINARY RAM5 (clk, we, en, addr, di, dout5) ; RAM_IMAGINARY RAM6 (clk, we, en, addr, di, dout6) ; RAM_IMAGINARY RAM7 (clk, we, en, addr, di, dout7) ; RAM_IMAGINARY RAM8 (clk, we, en, addr, di, dout8) ; RAM_IMAGINARY RAM9 (clk, we, en, addr, di, dout9) ; RAM_IMAGINARY RAM10 (clk, we, en, addr, di, dout10) ; RAM_IMAGINARY RAM11 (clk, we, en, addr, di, dout11) ; endmodule
解决方案
方案1:合并为大容量RAM(推荐)
将12×14的二维结构转换为**深度14、位宽192bit(12×16bit)**的单块RAM,单周期写入一个地址即可完成整列12个数据的写入,总容量为14×192=2688bit,完全符合BRAM的资源阈值,会被工具自动识别为BRAM。
代码示例:
module RAM_COLUMN_WRITE ( clk, we, en, addr, di, dout ); input clk; input we; input en; input [3:0] addr; // 14列对应地址0-13,4bit足够 input [191:0] di; // 12个16bit数据拼接:di[191:176]为第11个,di[15:0]为第0个 output [191:0] dout; logic [191:0] RAM [13:0]; // 深度14,位宽192bit logic [191:0] dout; always @(posedge clk) begin if (en) begin if (we) begin RAM[addr] <= di; dout <= di; end else begin dout <= RAM[addr]; end end end endmodule
若需要单独访问单个16bit数据,可直接拆分dout信号,例如assign dout0 = dout[15:0];、assign dout1 = dout[31:16];等。
方案2:强制小RAM映射为BRAM
若必须保留12个独立RAM的结构,可通过添加Synopsys属性(* ram_style = "block" *)强制工具将小RAM映射为BRAM,忽略容量阈值限制。
修改后的小RAM模块代码:
module RAM_IMAGINARY (clk, we, en, addr, di, dout); input clk; input we; input en; input [3:0] addr; // 优化地址位宽,深度14仅需4bit input [15:0] di; output [15:0] dout; (* ram_style = "block" *) logic [15:0] RAM_IMAGINARY [13:0]; // 强制映射为BRAM logic [15:0] dout; always @(posedge clk) begin if (en)begin if (we) begin RAM_IMAGINARY[addr] <= di; dout <= di; end else dout <= RAM_IMAGINARY[addr]; end end endmodule
注意:此方案会浪费BRAM资源(单个BRAM可容纳多个小RAM),仅在必须保留独立RAM结构时使用。
方案3:使用FPGA厂商IP核
直接调用Vivado的Block Memory Generator IP核,配置为深度14、位宽192bit的单端口RAM,可确保100%映射为BRAM,同时支持输出寄存器、写保护等定制化功能,适合复杂场景。
内容的提问来源于stack exchange,提问作者WithaSpirit1234
相关产品推荐
相关产品推荐

