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 / 1ps
module 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) begin
mem[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_WRITE
if ( cs && we ) begin
mem[address] <= data;
end
end
// Memory Read Block
// Read Operation : When we = 0, oe = 1, cs = 1
always @ (posedge clk)
begin : MEM_READ
if (cs && !we && oe) begin
data_out <= mem[address];
/* oe_r <= 1;
end else begin
oe_r <= 0; */
end
end
endmodule // 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官方设计文档)