[FPGA] Block memory module Setup and Usage guide

When FPGA synthesis is performed, memory is also created as block memory in vivado, similar to clock wiz (DCM), and bits are generated.

How to create block memory

First, select IP Catalog from the Project manager on the far left of the Vivado window.

vivado 메뉴에서 IP Catalog 선택
Select IP Catalog from the vivado menu

When you select IP Catalog, a window like the following will appear. Search for memory and select Block Memory Generator.

IP Catalog 선택 시 나오는 창
Window that appears when selecting IP Catalog
Block Memory Generator 선택
Select module

This will bring up a window like this, where you can set memory options.

Block Memory 옵션 창
Options

So, how do we modify which values? To figure that out, we first need to understand how memory instances are structured in typical ASIC architecture designs.

input  wire        clk        ;
input  wire        data0_cs   ;
input  wire [10:0] data0_addr ;
input  wire [ 3:0] data0_we   ;
input  wire [31:0] data0_wdata;
output wire [31:0] data0_rdata;

spsram_2048x32 u_mem0 (
     .CLK     (clk         )
    ,.CEN     (~data0_cs   )
    ,.WEN     (~(|data0_we))
    ,.BWEN    (~data0_we   )
    ,.A       ( data0_addr )
    ,.D       ( data0_wdata)
    ,.Q       ( data0_rdata)
);
  • CLK: memory input clock
  • CEN: chip enable signal (active low)
  • WEN: write enable signal (active low)
  • BWEN: byte write enable signal (active low)
  • A: address signal
  • D: memory write(input) data
  • Q: memory read(output) data

What we need to pay close attention to here are the memory type, we, and width/depth. Let's take a look at them one by one.

Memory type

Most memory instance names are listed here. Here, it's called spsram, which stands for single-port RAM. So, what other types are there?

  • single port ram (sp ram)
  • simple dual port ram (tp ram)
  • true dual port ram (dp ram)

Let's understand the characteristics of each memory by looking at the block diagram.

Single port ram(sp ram)

SP RAM is literally a memory with only one memory port (A).

Single port ram block diagram
Single Port ram block diagram

Simple dual port ram (tp ram)

TP RAM has two memory ports (A, B), but the chip enable signal (ena) and the write enable signal (wea) are shared between the two ports. So, one port is used for writing, and the other port is used for reading.

Simple Dual Port RAM block diagram
Simple Dual Port RAM block diagram

True dual port ram (dp ram)

DP RAM is a memory in which both memory ports (A, B) have their own ena signals (ena, enb) and wen signals (wea, web), so all memory ports can be read and written. Therefore, unlike TP RAM, it has dina, dinb, douta, and doutb signals.

True Dual Port RAM block diagram

Write enable(we)

To understand we, let's check the memory port.

Memory u_mem0 (
     .clka       ()
    ,.ena        ()
    ,.wea        ()
    ,.addra      ()
    ,.dina       ()
    ,.douta      ()
);
  • addra: address signal
  • dina: memory write(input) data
  • douta: memory read(output) data

Of course, there is clk, and then there is en, we, addr, data_in, and data_out. en is enable and we is write enable. en is a 1-bit signal, but we may or may not be 1-bit. This is because we can decide whether to write a byte or write the data width at once. If data_width is 32 bits, when byte write enable is enabled, we will be a 4-bit signal, and when byte write enable is not enabled, we will be a 1-bit signal.

1-byte can be set to 8-bit or 9-bit (but most people would probably set it to 8-bit, right?) and if byte write enable is set, the data width that follows can only be entered as 8(or 9) x n. (ex. if set to 8-bit, data_width can only be set to 8, 16, 24, 32…)

Shall we set it up to here?

옵션 설정
Set options

Width / Depth

The width and depth are also specified in the instance name. It is spsram_2048x32, where 2048 is the depth and 32 is the width. When you set the depth and width, the memory's addra, dina, and douta are automatically changed.

옵션 설정 후
After setting the options

Then, you can modify it as follows.

input  wire        clk        ;
input  wire        data0_cs   ;
input  wire [10:0] data0_addr ;
input  wire [ 3:0] data0_we   ;
input  wire [31:0] data0_wdata;
output wire [31:0] data0_rdata;

`ifdef FPGA
spsram_2048x32_FPGA u_mem0_FPGA (
     .clka       (clk        )
    ,.ena        (data0_cs   )
    ,.wea        (data0_we   )
    ,.addra      (data0_addr )
    ,.dina       (data0_wdata)
    ,.douta      (data0_rdata)
);
`else
spsram_2048x32 u_mem0 (
     .CLK     (clk         )
    ,.CEN     (~data0_cs   )
    ,.WEN     (~(|data0_we))
    ,.BWEN    (~data0_we   )
    ,.A       ( data0_addr )
    ,.D       ( data0_wdata)
    ,.Q       ( data0_rdata)
);
`endif

I don't remember exactly the polarity of ena and wea;;;;

ROM code(boot loader) setting

Computers and SoCs have ROM (Read-Only Memory), so when booting, they need to load and execute a boot loader embedded in the ROM. So, how do we embed this boot loader into a memory block when synthesizing a bit file for board testing?

You can do this in the Memory Generator settings. You can specify the boot loader to run in the "Other options" section, as shown below. Load the corresponding bootloader file from the block to be used as ROM and synthesize the bits. Once the bits are downloaded to the board, the specified program will be executed.

Boot loader 설정
Boot loader Setting

참조: Xilinx Memory Generator Data sheet

Similar Posts