THIS ARTICLE WAS UPDATED on 18-04-2024. OLD ARTICLE USED XILINX ISE INSTEAD OF VIVADO.
BRAM(Block Random access memory) is an advanced memory constructor that generates area and performance-optimized memories using embedded block RAM resources in Xilinx FPGAs. I hope you have already gone through the Core generator introductory tutorial before. If you haven't please read those articles here.
We will be using Xilinx Vivado 2023.2 version for this. The steps should be the same in any version of Vivado, I believe. Let me guide you through the process with a series of screenshots.
1. Create a new project in Xilinx Vivado.
2. Click on IP Catalog, under flow navigator on the left pane of the software. You will see something like this on screen:
2. Type "BRAM" in the search bar and you will get a list of matching results as shown below:
3. Double click on Block Memory Generator, which is highlighted in the previous screenshot. A new window opens up where you can set the properties of the BRAM. You can check out the data sheet of the BRAM by clicking on Documentation. This is helpful in case you dont understand what these settings are. The component name can be changed as well.
We have customized our BRAM with the following settings:
- It will be of 256 by 8 bits in size.
- Algorithm will be chosen for "Low Power".
- Read and write width will be of 8 bit.
- You can initialize the memory with a coe file, but I have chosen them to be initialized with zeros.
6. I have set the component name as "bram_test". Now click on the "OK" button at the bottom.
7. Click on "Generate".
8. The tool will generate the necessary files and will add bram_test as a new source to the project. You should be able to see the new component under "Design Sources".
9. Note that double clicking on the .xci file which is highlighted in the above image, will open the IP settings window once again. This means that anytime you can change the bram settings and regenerate the files if you want to.
10. To test the bram entity, we would need its port declaration. Meaning, we would need to know what are the input and output signals, their data type, size etc. To know this, we can click on the arrow, >, which shows the underlying vhdl file. This file contains the port definition which we can copy paste into our testbench code.
11. Next step would be to write a testbench code for testing the BRAM we just created. Create a new simulation source (tb_bram.vhd) and copy the following code into it:
library ieee; use ieee.std_logic_1164.all; --empty entity for testbench entity tb_bram is end tb_bram; architecture Behavioral of tb_bram is --copy paste the port declaration of the bram from the xilinx generated file. component bram_test is PORT ( clka : IN STD_LOGIC; ena : IN STD_LOGIC; wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0); addra : IN STD_LOGIC_VECTOR(7 DOWNTO 0); dina : IN STD_LOGIC_VECTOR(7 DOWNTO 0); douta : OUT STD_LOGIC_VECTOR(7 DOWNTO 0) ); end component; --port signals for connecting with the bram signal clka, ena : std_logic := '0'; signal wea : std_logic_vector(0 downto 0) := "0"; signal addra, dina, douta : std_logic_vector(7 downto 0) := (others => '0'); constant clk_period : time := 10 ns; --clock period. begin --componenent instantiation using named association. bram : bram_test port map( clka => clka, ena => ena, wea => wea, addra => addra, dina => dina, douta => douta); --generate the clock for bram clk_generation: process begin wait for clk_period/2; clka <= not clka; end process; --this is where we generate the inputs to apply to the bram stimulus: process begin wait for clk_period; ena <= '1'; wea <= "1"; addra <= x"00"; dina <= x"A5"; wait for clk_period; addra <= x"04"; dina <= x"B6"; wait for clk_period; addra <= x"05"; dina <= x"C7"; wait for clk_period; ena <= '0'; addra <= x"07"; dina <= x"D8"; wait for clk_period; wea <= "0"; ena <= '1'; addra <= x"00"; wait for clk_period; addra <= x"04"; wait for clk_period; addra <= x"05"; wait for clk_period; addra <= x"07"; wait for clk_period; wait; end process; end Behavioral;
12. Right click on "tb_bram.vhd" and click on "set as Top".
13. Run Behavioral Simulation. You should get the following waveform:
You can verify that, when the enable signal ena is low, BRAM doesnt respond to any read or write instruction. Also, there is a 2 clock cycle delay (or latency as they call it) for reading any address from bram. This is as expected as the summary page in the IP generate window says this: "Total port a read Latency: 2 clock cycles".
Note :- What we have tried out here is a very simple BRAM. But it demonstrates how we can work with Xilinx in built IPs. The design will get complicated when you go from single port to dual port RAM's. But the basic idea remains the same. By reading the documentation supplied by Xilinx you can explore more settings used in the GUI tool. For testing purpose I have used Xilinx Vivado 2023.2. The options in the IP tool may vary slightly depending on the version you are using.
You can verify that, when the enable signal ena is low, BRAM doesnt respond to any read or write instruction. Also, there is a 2 clock cycle delay (or latency as they call it) for reading any address from bram. This is as expected as the summary page in the IP generate window says this: "Total port a read Latency: 2 clock cycles".
Note :- What we have tried out here is a very simple BRAM. But it demonstrates how we can work with Xilinx in built IPs. The design will get complicated when you go from single port to dual port RAM's. But the basic idea remains the same. By reading the documentation supplied by Xilinx you can explore more settings used in the GUI tool. For testing purpose I have used Xilinx Vivado 2023.2. The options in the IP tool may vary slightly depending on the version you are using.
If you prefer to see this in action, watch this Youtube video I have created.
i have implemented ur design @ ise , i am getting following error -
ReplyDelete"Pack:198 - NCD was not produced. All logic was removed from the design.
This is usually due to having no input or output PAD connections in the
design and no nets or symbols marked as 'SAVE'. You can either add PADs or
'SAVE' attributes to the design, or run 'map -u' to disable logic trimming in
the mapper. For more information on trimming issues search the Xilinx
Answers database for "ERROR:Pack:198" and read the Master Answer Record for
MAP Trimming Issues."
I did exactly what you did, and now I have the following warnings:
ReplyDeleteWARNING:ProjectMgmt - Duplicate Design Unit 'BRAM_test' found in library 'work'
WARNING:ProjectMgmt - "C:/Users/tam/Desktop/BRAM/BRAM_test_synth.vhd" line 64 (active)
WARNING:ProjectMgmt - "C:/Users/tam/Desktop/BRAM/BRAM_test.vhd" line 43
And I also have the following errors:
Map:116 - The design is empty. No processing will be done.
Map:52 - Problem encountered processing RPMs.
Can you help me to fix this? thank you!
I did exactly what you did, and now I have the following warnings:
ReplyDeleteWARNING:ProjectMgmt - Duplicate Design Unit 'BRAM_test' found in library 'work'
WARNING:ProjectMgmt - "C:/Users/tam/Desktop/BRAM/BRAM_test_synth.vhd" line 64 (active)
WARNING:ProjectMgmt - "C:/Users/tam/Desktop/BRAM/BRAM_test.vhd" line 43
And I also have the following errors:
Map:116 - The design is empty. No processing will be done.
Map:52 - Problem encountered processing RPMs.
Can you help me to fix this? thank you!
HI guys u wanna implement 32x 32 matrix using 16x16 matrix pls help me
ReplyDelete