Xilinx FPGA RAM存储资源verilog可综合描述方法

1 概述

       在FPGA设计中经常要使用片内RAM资源来缓存数据。对于Xilinx FPGA器件,片内存储资源分为块存储Block RAM和分布式存储Distributed RAM。Block RAM为硬核,不会占用触发器FF和查找表LUT这类逻辑资源。而Distributed RAM是通过LUT和FF搭建而成,会占用逻辑资源。因此,在进行程序设计时会优先考虑使用Block RAM资源。

       一般情况下,要使用Xilinx FPGA内的RAM资源,可通过vivado软件IP Catalog中的Block Memory Generator和Distributed Memory Generator配置参数例化生成1个RAM的IP核。


       对于一些复杂的设计,需要使用很多位宽不同,深度不同的RAM时,通过例化IP核的方式便会带来一些问题:

  • 增加工作量,每使用或更改1个RAM都需要进行1次IP核参数配置和例化。
  • 缺乏灵活性,如果需要对IP核重命名,只能删除重建IP。
  • 增加工程冗余度,每个RAM IP单独生成1组IP文件,占用空间,不利于维护。

       因此,本文介绍通过verilog描述RAM的方法,使其综合、布局布线后的结果与使用IP核例化RAM的效果相同。

       本文内容参考自AMD Xilinx官方文档UG901。

2 Single Port RAM

module bram_sp #
(
    parameter 	DATA_WIDTH = 8,
    parameter 	ADDR_WIDTH = 11,
	parameter 	OP_MODE = "NO_CHANGE"  //WRITE_FIRST, READ_FIRST or NO_CHANGE
)
(
	input wire							clk,
	input wire							we, 
	input wire							en,
	input wire [ADDR_WIDTH - 1:0] 		addr, 
	input wire [DATA_WIDTH - 1:0] 		din, 
	output reg [DATA_WIDTH - 1:0] 		dout
);

// Shared memory
localparam RAM_DEPTH = 2 ** ADDR_WIDTH;
(* ram_style = "block" *) reg [DATA_WIDTH-1:0] ram [RAM_DEPTH-1:0];


integer i;
initial 
begin
for(i=0; i

3 Simple Dual Port RAM

module bram_sdp #
(
    parameter DATA_WIDTH = 8,
    parameter ADDR_WIDTH = 11
) 
(
   // Port A
    input   wire                      clka,
    input   wire                      ena,
	input	wire					  wea,
    input   wire    [ADDR_WIDTH-1:0]  addra,
    input   wire    [DATA_WIDTH-1:0]  dina,

    // Port B
    input   wire                      clkb,
    input   wire                      enb,
    input   wire    [ADDR_WIDTH-1:0]  addrb,
    output  reg     [DATA_WIDTH-1:0]  doutb = 0
);

// Shared memory
localparam RAM_DEPTH = 2 ** ADDR_WIDTH;
(* ram_style = "block" *) reg [DATA_WIDTH-1:0] ram [RAM_DEPTH-1:0];

integer i;
initial 
begin
for(i=0; i

4 True Dual Port RAM

module bram_tdp #
(
    parameter DATA_WIDTH = 8,
    parameter ADDR_WIDTH = 11,
	parameter PORTA_MODE = "NO_CHANGE",  //WRITE_FIRST, READ_FIRST or NO_CHANGE
	parameter PORTB_MODE = "NO_CHANGE"  //WRITE_FIRST, READ_FIRST or NO_CHANGE
) 
(
   // Port A
    input   wire                      clka,
    input   wire                      ena,
	input	wire					  wea,
    input   wire    [ADDR_WIDTH-1:0]  addra,
    input   wire    [DATA_WIDTH-1:0]  dina,
	output  reg     [DATA_WIDTH-1:0]  douta,

    // Port B
    input   wire                      clkb,
    input   wire                      enb,
	input   wire					  web,
    input   wire    [ADDR_WIDTH-1:0]  addrb,
	input   wire    [DATA_WIDTH-1:0]  dinb,
    output  reg     [DATA_WIDTH-1:0]  doutb
);
// Shared memory
localparam RAM_DEPTH = 2 ** ADDR_WIDTH;
(* ram_style = "block" *) reg [DATA_WIDTH-1:0] ram [RAM_DEPTH-1:0];


integer i;
initial 
begin
for(i=0; i

你可能感兴趣的:(#,verilog,fpga开发,verilog,fpga,xilinx)