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!


ZC706 PS-PL Block RAM sharing

Posts: 33
Registered: ‎12-25-2014

ZC706 PS-PL Block RAM sharing

I am using ZC706 evaluation kit. I have Vivado 2016.2.

My goal is to build a small project in which a Block RAM on the FPGA fabric can be accessed by both PS & PL. I am using a true dual port RAM such that through one port PS can read/write & through the other port PL can read/write. I took Zynq 7000 AP SOC Using BRAM for additional On Chip Memory as reference (although it is for earlier ISE version, I managed to build it for vivado 2016.2 & got same result). 


I modified my block design as shown below

Block Design.JPG

I wrote a small module which just reads data from BRAM PORTB. I give the same FCLK_CLK0 & increment the read address every clock cycle. I made BRAM_RST=0, BRAM_EN=1, BRAM_WE=0 & BRAM_DIN=0. I registered the BRAM_DOUT & added an ILA debug core on that. Below is the module which read data from PORT B

module system_top(PS_Clk, BRAM_Address, BRAM_DataIn, BRAM_DataOut, BRAM_Clk, BRAM_Rst, BRAM_Enable, BRAM_WE);
input PS_Clk;
input [31:0] BRAM_DataOut;
output [31:0] BRAM_Address;
output [31:0] BRAM_DataIn;
output BRAM_Clk;
output BRAM_Rst;
output BRAM_Enable;
output BRAM_WE;

(* mark_debug = "TRUE" *)reg [15:0] BRAM_Address16=0;
(* mark_debug = "TRUE" *)reg [31:0] Data_Read;

assign BRAM_Clk = PS_Clk;
assign BRAM_Address = {16'd0,BRAM_Address16};

always @(posedge PS_Clk)
		BRAM_Address16 <= BRAM_Address16 + 1;
		Data_Read <= BRAM_DataOut;
assign BRAM_WE = 4'd0;
assign BRAM_Rst = 0;
assign BRAM_Enable = 1;
assign BRAM_DataIn = 32'd0;


I generate the bit file & export & launch SDK. Through SDK I porgram the FPGA & run the GDB app that initializes the ZC706. The application project just writes continues int values from 0 to 65535 in the RAM. Below is that code too

#include <stdio.h>
#include "xparameters.h"
#define BRAM_SIZE 0x40000

int main()
	 unsigned int uiLoop;
	 unsigned int * uiDataArray = (unsigned int *)XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR;
	 unsigned int uiData;

	 printf("\n\r BRAM Data Initialization \n\r");
	 for(uiLoop =0 ; uiLoop < (BRAM_SIZE/4) ; uiLoop++)
		 *(unsigned int *)(uiDataArray + uiLoop) = uiLoop;
	 // BRAM Data Verification.
	 for(uiLoop =0 ; uiLoop < (BRAM_SIZE/4) ; uiLoop++)
		 uiData = *(unsigned int *)(uiDataArray + uiLoop);
		if(uiData != uiLoop)
			printf("BRAM verification failed \n\r");
			return -1;
	 printf("\n\r BRAM Verification Successful \n\r");
	 return 0;

It displays BRAM Verification Successful in the consol. Now, I close SDK & open Vivado Hardware Manager to see the ILA data. I am expecting data & address to be equal ie. in BRAM_Address=0, BRAM_DataOut=0, in BRAM_Address=1, BRAM_DataOut=1 & so on till in BRAM_Address=65536, BRAM_DataOut=65536. But what I observe doesn't make sense. I see address & data increment but not the above mentioned pattern. Below is what I see in the ILA


I am only reading data through PORT B so how is this possible. What mistake am I making?

Posts: 5,148
Registered: ‎03-31-2012

Re: ZC706 PS-PL Block RAM sharing

@kharobangd From PS side you are writing to word (32 bit) addresses so you  write 0 to address 0 and 1 to address 4 etc. In PL the increment is in byte addresses and somehow it looks like bottom 2 bits of the address is being ignored. You need to understand how many bits are being used for address on both sides.

- Please mark the Answer as "Accept as solution" if information provided is helpful.
Give Kudos to a post which you think is helpful and reply oriented.
Posts: 33
Registered: ‎12-25-2014

Re: ZC706 PS-PL Block RAM sharing

I am aware of that. The memory mapped address for the RAM is 0x4000_0000 to 0x4003_FFFF ie 262144 locations. Each 32 bit data(4 bytes) is stored in memory address offset of 4. The read & write from PS side is OK. I am trying to access this RAM from PL. There is no concept of memory-mapped address in PL(as far as I know, I am new to zynq), only relative address from 0 to 0xFFFF & each address stores the entire 32 bit data as far as PL is concerned. I am using 64 RAMB36 in 32x1024 combination. So when I access the address 0x0000 from PL side I should get 32'h0000, in address 0x0001 from PL side I should get 32'd0001.


Please somebody more experienced than me in Zynq programming just implement the code. I have already posted the block design & source code. I am getting frustrated getting this simple thing to work out.

Posts: 33
Registered: ‎12-25-2014

Re: ZC706 PS-PL Block RAM sharing

Nobody will help meaning how will beginners learn ah?

Posts: 29
Registered: ‎04-25-2017

Re: ZC706 PS-PL Block RAM sharing

Hi there,


There are several sources of information you can use for your project:


1. Xilinx coding templates which you can access from the Vivado editor when you have opened HDL file. Click on the "light bulb" icon and follow Synthesis Constructs ->Coding Examples -> RAM -> Block RAM -> True Dual Port , etc.

Templates are well commented and I believe even some testbenches are provided.

You will need to instantiate BRAM using parameters from the block diagram BRAM Generator.

You can have independent clocks in PL but you will need to pay attention to time constraints in this case.


2. Xilinx document pg058


Also you can create a custom IP module with your PL code and connect it to the second BRAM port. This way Vivado will take care of instantiation making your HDL coding much simpler.

Use web search and you will find how to do this.


Good luck!