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: 17
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: 4,871
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: 17
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.