FPGA设计中BRAM(Block RAMs)资源的使用
RAM分为BRAM(Block RAMs)和DRAM(Distributed RAM),即块RAM与分布式RAM,这两个差别在于BRAM是FPGA上固有的一些存储资源(针对不同型号的FPGA,其存储资源大小会有差别),而DRAM则是由LUT组合而成的。所以在数据量较大的情况下,一般使用BRAM,尽量避免使用DRAM,导致LUT资源的浪费。
以Vivado平台为例,如果不指定综合为BRAM还是DRAM,则Vivado会根据RAM的大小自动判断综合为BRAM还是DRAM。
参考博客《单端口RAM设计》中的单端口RAM代码,如下。
`timescale 1ns / 1psmodule single_port_ram (
clk , // Clock Input
address , // Address Input
data , // Data bi-directional
cs , // Chip Select
we , // Write Enable/Read Enable
oe // Output Enable
); parameter DATA_WIDTH = 8 ;
parameter ADDR_WIDTH = 4 ;
parameter RAM_DEPTH = 1 << ADDR_WIDTH;//--------------Input Ports-----------------------
input clk ;
input [ADDR_WIDTH-1:0] address ;
input cs ;
input we ;
input oe ; //--------------Inout Ports-----------------------
inout [DATA_WIDTH-1:0] data ;//--------------Internal variables----------------
reg [DATA_WIDTH-1:0] data_out ;
//(*ram_style = "block"*) reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1];
reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1];
reg oe_r;//initialization// synopsys_translate_off
integer i;
initial begin//$readmemb("F:/IP_core/Single Port RAM/SIM/single_port_rom_init.txt", mem);for(i=0; i < RAM_DEPTH; i = i + 1) beginmem[i] = 8'h00;end
end
// synopsys_translate_on//--------------Code Starts Here------------------ // Tri-State Buffer control
// output : When we = 0, oe = 1, cs = 1
assign data = (cs && oe && !we) ? data_out : 8'bz; // Memory Write Block
// Write Operation : When we = 1, cs = 1
always @ (posedge clk)
begin : MEM_WRITEif ( cs && we ) beginmem[address] <= data;end
end// Memory Read Block
// Read Operation : When we = 0, oe = 1, cs = 1
always @ (posedge clk)
begin : MEM_READif (cs && !we && oe) begindata_out <= mem[address];
/* oe_r <= 1;end else beginoe_r <= 0; */end
endendmodule // End of Module ram_sp_sr_sw
对该代码进行综合,可以看到资源使用报告如下。可以看到这里根据RAM的大小自动综合成DRAM(LUTRAM)。
于是,参考Xilinx Template给出模板(或者在Xilinx官方文档UG901中也可查看),指定将RAM综合为BRAM,如下图所示。
在寄存器前面加上语句: (*ram_style=“block”*),即
reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; //修改前(*ram_style = "block"*) reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1]; //修改后
再进行综合,查看资源使用报告,可见此时我们编写的单端口RAM已经被综合成了BRAM。
注意:这里由于所设计的RAM不大,所以在不指定RAM的类型时会自动综合成了DRAM,但是在RAM的存储空间较大时,会自动综合成BRAM,可以通过在前面加入语句 (*ram_style=“distributed”*)指定综合为DRAM。
参考资料
1、FPGA单端口RAM的设计(同步读、同步写)
2、UG901(Xilinx官方设计文档)