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!

cancel
Showing results for 
Search instead for 
Did you mean: 
Adventurer
Adventurer
7,732 Views
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)
	begin
		BRAM_Address16 <= BRAM_Address16 + 1;
		Data_Read <= BRAM_DataOut;
	end
	
assign BRAM_WE = 4'd0;
assign BRAM_Rst = 0;
assign BRAM_Enable = 1;
assign BRAM_DataIn = 32'd0;

endmodule

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

ILA.JPG

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

Tags (4)
0 Kudos
8 Replies
Teacher muzaffer
Teacher
7,695 Views
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.
0 Kudos
Adventurer
Adventurer
7,642 Views
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.

0 Kudos
Adventurer
Adventurer
7,492 Views
Registered: ‎12-25-2014

Re: ZC706 PS-PL Block RAM sharing

Nobody will help meaning how will beginners learn ah?

0 Kudos
Observer novec_16
Observer
7,390 Views
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!

0 Kudos
Observer deepika07
Observer
3,012 Views
Registered: ‎05-15-2018

Re: ZC706 PS-PL Block RAM sharing

Hi @novec_16

I have a question regarding what you suggested.

How are we supposed to use the language templates when working with IP integrator? Or do they just help in understanding the BRAM better? My issue is in this question:

https://forums.xilinx.com/t5/AXI-Infrastructure/Accessing-BRAM-through-PS-and-PL/m-p/894449 

Can you please have a look and suggest something.

 

Thanks!

0 Kudos
Observer novec_16
Observer
2,982 Views
Registered: ‎04-25-2017

Re: ZC706 PS-PL Block RAM sharing

Here are some clues. First of all make block connection similar to shown below. In this case PL is only writing to BRAM. You can add read to it also. In the RTL block you don't need any definitions of BRAM, you just operate with interface signals. Having blocks and connections in the diagram provides sufficient information for Vivado to understand your circuit. SDK should get BRAM address from the file xparameters.h. Add a line to your C code: #define BRAM_MEMORY XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR After that you can read and write BRAM using pointers or whatever you prefer. Be careful defining block parameters and BRAM width. Good understang can be gained from BRAM simulation. Cheers!

Capture.JPG
Observer jg_spitfire
Observer
455 Views
Registered: ‎12-10-2019

Re: ZC706 PS-PL Block RAM sharing

Hi, do you know why the bram clk and enables are not connected when vivado does the auto-connect?, is very strange (for me) that those pins are not connected

thanks

0 Kudos
Observer jg_spitfire
Observer
205 Views
Registered: ‎12-10-2019

Re: ZC706 PS-PL Block RAM sharing

@novec_16Hi, please, could you help me with this questions?:

 

1.- you said:

"Add a line to your C code: #define BRAM_MEMORY XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR After that you can read and write BRAM using pointers or whatever you prefer"

why?, if I am including the xparameters.h file I don't know why I need to declare that constant

 

2.- why do you create an output clock in your RTL block?, why not to use the clock from the zynq processing system?, my RTL block has an input clock (from PS zynq block) and I connected that clock to the port b ram input clock to operate all the system with the same clock source

I have problems reading my ram from ps, if I always write the same values I read them ok, but If I write different values I got random values in the output, I will attach some captures, basically, I write the ram three times, always in the same addresses but with values from 0 to 9, 10 to 19, 20 to 29, and in the PS side I wait 5 seconds to detect the ram full signal, I know 5 seconds is too much time but at that time the ram should be written and I should get the latest values, I mean, 20 to 29 in addresses 0 to 9, but I got random values.

(in putty I have three reads because I push the reset button three times)

thanks 

 

0 Kudos