UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

AR# 63041

Vivado IP Integrator - How to populate the BRAM in processorless IP Integrator systems

Description

Processor-less block RAM (BRAM) systems are a popular use-case in FPGA solutions. However, currently the Vivado tool will not allow the user to associate ELF to processor-less Block Memory Generators (BMG).

This answer record contains work-arounds which might be useful depending on the user's needs.

 

Note:The work-arounds and scripts provided offer a best effort solution and although every effort is made to try to achieve a solution, they might not work for some use-cases.

The scripts are not supported by Xilinx.

Solution

There are two flows to populate the BRAM in a Block Design; the MEMDATA flow and the Updatemem flow.

The MEMDATA flow is used when the user associates the ELF to a MicroBlaze processor. This is the flow that the Vivado tool uses. If an ELF is not associated, then the bootloop ELF is used.

However, if for example a user wants to update the BRAM post implementation, where the application is built in SDK and they want to test it, then the Updatemem flow is used.

Updatemem uses a Memory Map Info (MMI) file to describe the BRAM layout. The MMI file is similar to the BMM file used in previous releases. The MMI file is built in Vivado and exported to SDK in the HDF.

The MMI file is only built for processor systems.

For this reason processorless systems cause an issue in the current tool. 

The following work-arounds are offered in this Answer Record.

  1. Work-around 1 - Use the attached script to build the MMI
    • Cons: Only Supports BD designs, and BRAM connected to an AXI/LMB Memory Controller
  2. Work-around 2 - Manually create the MMI file
    • Pros: Works on all BRAM. Cons: open to error
  3. Work-around 3 - Use the XPM (Xilinx Parameterized Module) Memory
    • Cons: Currently does not support updatemem

Work-around 1 - Use the attached script to build the MMI

To work around this issue, download the attached write_mmi.tcl Tcl file into the Vivado project directory, and follow the steps below:

Step 1: Generate the bitstream (write_bitstream), and open the implemented design:

Source the attached script from the Tcl command line:

source -quiet write_mmi.tcl

Step 2: Run the script to generate MMI file:

To implement the script run the command below:

write_mmi <BRAM Name>

Note: the BRAM name can be obtained from the implemented design. Open the implemented design, and press Ctrl+F to search for all BRAM:

 

This will list all of the BRAM in a design. The script uses a similar method to list all of the available BRAM. However, the user needs to provide a filter to narrow results to just the BRAM that the MMI is to be created for. 

For example, below is a list of all of the BRAM in a design:

 

So, here you would use the command:

  • write_mmi axi_bram_ctrl_0

This will filter all of the BRAM containing the string axi_bram_ctrl_0.

Step 3: Run updatemem to initialize the BRAM with MEM data:

The script run in Step 2 will create a template updatemem command line which should be used.

Step 4: Test on Hardware:

Caveats and Limitations of the script:

  • The script only supports BRAM connected to a BRAM controller. i.e. not in standalone.

  • Only 32-bit data width is supported.

Demo:

To better demonstrate this, a simple demo has been created.

The Block Diagram for this can be seen below:

 

This was implemented, and the implemented design was opened.

The commands seen in Step 1 and Step 2 were run:

source -quiet write_mmi.tcl
write_mmi axi_bram_ctrl_0

This produces the result below on the console:

Warning: No Processor found
MMI file (C:/cases/non_processor_mmi/project_1.runs/impl_1/design_1_wrapper.mmi) created successfully

To run updatemem, use the command line below after write_bitstream:

updatemem -force --meminfo C:/cases/non_processor_mmi/project_1.runs/impl_1/design_1_wrapper.mmi --data <path to data file>.elf/mem --bit <path to input bit> --proc dummy --out <output bit file>.bit

Next, generate a MEM file to be placed into the BRAM:

@00000000
12345678

Then run updatemem using the template given in Step 2:

cd {C:\cases\non_processor_mmi\project_1.runs\impl_1}
updatemem -debug -force --meminfo design_1_wrapper.mmi --data test.mem --bit design_1_wrapper.bit --proc dummy --out download.bit > debug.txt

Note: I have added the debug switch here, this will dump the BRAM insit strings content into a debug.txt file for debugging purposes.

Test on hardware, using the AXI JTAG commands.

Open the Hardware Manager, connect, and program the FPGA using the BIT file output from updatemem:

 

Once this is done, you can use the AXI JTAG Tcl commands to read the block RAM:

create_hw_axi_txn rd_txn [get_hw_axis hw_axi_1] -address 00000000 -len 8 -size 32 -type read
run_hw_axi rd_txn

This returns the following:

INFO: [Labtoolstcl 44-481] READ DATA is: 0000000000000000000000000000000000000000000000000000000078563412

Note: the data is swapped.

This is done in the updatemem, so you will need to be aware of this.

Work-around 2 - Manually Create the MMI

The Vivado tools will only create the work-around provided in Work-around 1, and will only work for Block Designs (BD), that contain a memory controller, and a BRAM.

However, in some use-cases, you might want to populate the BRAM that is instantiated in your RTL, or added via the BMG in the IP catalog outside a BD. 

If you want the flexibility to update this BRAM post implementation, you will need to use updatemem. Because updatemem requires a MMI file, this will need to be manually created.

The MMI file is discussed in Chapter 6 in (UG898). In the example shown here, I have used the single port BRAM VHDL instantiation template seen under Tools > Language Templates > Verilog/VHDL.

I add this to my top level module, as shown below:

 

I have configured the BRAM instance as shown below:

 

Note: this file is attached to this Answer Record for reference

Next, I packaged this HDL file using the IP packager tool in Vivado and added this to my BD.

Note: These steps are only used for testing purposes. You can add the BRAM to the project however you choose.

 

Here, I connected the BRAM to an AXI BRAM controller, and an AXI to JTAG Master. Generate the Output Products, the HDL wrapper, and write_bitstream.

Open the implemented design, and search for the BRAMs used in the design. (Ctrl + f):

 

This will result in a list of all the BRAMs found in the implemented design. 

For example, my results are shown below:


Highlight our RTL BRAM (the bottom one), and view the cell properties. We need to find the following information:

  • bitlane
  • placement

 

Here, we can read the placement info as X2Y17 from the LOC property, and the READ/WRITE is set to 36. We can now create the MMI file:



So, Here I used the data obtained from the cell property of the BRAM to create the MMI file. 

The address space can be calculated as follows:

1 x RAMB32 (I am not using the parity) = 32 x 1024 = 32768 bits, or 4096 Bytes. Since the whole memory region is made up of one BRAM, then we can use the same for the Address Range. 

The Data width MSB to LSB can be obtained from the cell property too. 

Note: I am not using the parity bits. So, i just have 0 to 31.

In the InstPath, I have set this to "dummy".

Next, generate a MEM file to be placed into the BRAM:
@00000000
12345678


The updatemem command line command is as follows:

updatemem -debug -force --meminfo test.mmi --data test.mem --bit design_1_wrapper.bit  --proc dummy --out download.bit > debug.txt 
Note: I have added the debug switch here, this will dump the BRAM insit strings content into a debug.txt file for debugging purposes.


To test, we can use the Hardware Manager. Open Hardware Manager, and program the FPGA with the bit output from Updatemem.

Once this is done, you can use the AXI JTAG Tcl commands to read the block RAM:

create_hw_axi_txn rd_txn [get_hw_axis hw_axi_1] -address 00000000 -len 8 -size 32 -type read
run_hw_axi rd_txn
This returns the following:
INFO: [Labtoolstcl 44-481] READ DATA is: 0000000000000000000000000000000000000000000000000000000078563412



Work-around 3 - Use the XPM (Xilinx Parameterized Module) Memory

The XPM can be added in Vivado2016.1, under Tools > Language Templates > Verilog/VHDL > Xilinx Parameterized Macros (XPM) > Memory using the command below:

set_property XPM_LIBRARIES XPM_MEMORY [current_project]

Here you can select either RAM or ROM. Distributed RAM/ROM should be selected as this is not synthesized in BRAM.

For example below is a single port RAM:



Next, Create the Memory File (MEM file). You can add this as a design source file in Vivado. Below, I have created a simple MEM file (test.mem).

This is added as the MEMORY_INIT_FILE in the XPM instance:




Note: To package this, do not use the IP Packager. Instead, use the steps below:

Right click on the IPI canvas, and select Add Module:

 

Select the top Module where the XPM resides:



The BRAM will not be populated with the contents of the MEM file post synthesis.


Note: Updatemem does not currently support XPM.

Attachments

Associated Attachments

Name File Size File Type
write_mmi.tcl 5 KB TCL
spram.vhd 16 KB VHD
AR# 63041
Date Created 12/04/2014
Last Updated 04/28/2016
Status Active
Type General Article
Devices
  • Kintex-7
  • Artix-7
  • Virtex-7
Tools
  • Vivado Design Suite - 2014.4
  • Vivado Design Suite - 2014.3
  • Vivado Design Suite - 2014.2
  • More
  • Vivado Design Suite - 2015.3
  • Vivado Design Suite - 2015.2
  • Vivado Design Suite - 2015.1
  • Vivado Design Suite - 2016.1
  • Vivado Design Suite - 2015.4.2
  • Less