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: 
Explorer
Explorer
9,207 Views
Registered: ‎02-05-2015

Ap_memory tutorial & ILA tutorial

Jump to solution

I really really need some help, I've been around at this for too long an nothing.

 

I have a block from Vivado HLS which receives an array. That array is automatically converted into ap_memory interface and I was trying to connect them to the PS via  GPIO (proper initializing them in SDK) but I failed miserably.

 

What I need is just a tutorial in Vivado that shows you how to deal with ap_memory interfaces (and preferably on how to initialize them after in SDK)

 

Thank you very much

0 Kudos
1 Solution

Accepted Solutions
Scholar jprice
Scholar
10,211 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

There's no reason you have to express indicies or addresses in hex its often easier to look at if they are expressed that way. For this sort of thing I prefer hex so I use it. There is no signifance to either quantity being represented in decimal vs. hex. 

 

 

So, keep in mind that in your HLS top level function parameters are representing physical interfaces which is very much not like normal C. You use the interface directive to indicate what kind of interface they are, keep that in mind as you develop your designs. So a pointer which we have set to be a master AXI port represents a physical AXI interface. You may want to study some of the AXI signal descriptions at some point since it may communicate more clearly how some of this works. Accesing that pointer translates to accesses on the AXI bus. However accessing that pointer has no implict base address and how could it. It's possible for there to be a variety of memory mapped devices that it could communicate with. There has to be a way to distinguish one from the other which is done by address space mapping. That said I believe it is possible to explicitly set a base address on an instantiation by instantiation basis. The VHDL created supports a "Target Address" generic which is added to all the transaction addresses. It may be possible to configure this in IPI as well. This would work for this application but when you have multiple memories you would have to rethink the scheme. Finally there is an offset for the m_axi directive which may do the same thing, but then you're back to your code needing to know the address. It also means the Zynq Software and your HLS design have slightly different memory maps which I would find undesirable but really is very application specific.  

 

 

I think your point of confusion may be due to the way the simple example I created works. It relies on a shared memry space between the Zynq PS and your HLS design. The memory is accessed by both using the same AXI interface on the AXI interconnect. Going through this thread again I might pick a slightly different example to communicate my point more clearly. For example you could have two different AXI BRAM Controllers connected to the same BRAM. The Zynq PS would talk to one through the interconnect and the HLS design would talk to another one directly. In this case the HLS design would only be accessing the BRAM's memory space and nothing more. As a result it would behave in a way closer to your thought process. Note the reason I'm using Master AXI and not say an ap_memory port is that memcpy requires a master AXI interface to work. 

 

Now your last point, you can't just specify an address because that's not specifying an interface. In normal SW that would work since the CPU only has access to one memory space. However in this case no such limitation exists. You have to explicitly use the pointer. Naturally my previous example code was a lie since it also doesn't specify an interface. It was to try to explain to you what's going on but it wouldn't work since it doesn't specify an interface.

 

 

Note: Learning VHDL is defintely helpful. I don't believe you can do everything in HLS without understanding some of the FPGA side as well. I've found HLS pretty simple to pick up but I have a lot of experience with the hardware side. From a HDL designer pointer of view HLS makes a lot of really annoying tasks substantially easier (far less work to develop/implement). I'm not sure the same is true if one is approaching from a software perspective. That said if you understand a handful of basic concepts you can probably go pretty far.

121 Replies
Explorer
Explorer
9,162 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

Guys, please help me. I searched all around and literally found 0 examples or tutorials on how to deal with an ap_memory interface from Vivado HLS.

 

Come on Xilinx guys, wtf! Can't you take 1 min of your time to answer a question?

 

I also tried to make sense of this alone but couldn't by any way. With an array of length 4 only I havethese parameteres in the IP block:

In:

-..._q0[31:0] 

-..._q1[31:0]

 

Out

-..._ce_0

-..._we0

-..._ce1

-..._we1

-...._address0[1:0]

-...._d0[31_0]

-...._address1[1:0]

-...._d1[31_0]

0 Kudos
Scholar jprice
Scholar
9,150 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

jmales,

 

You're going to need to take a step back. There's a certain amount of assumed experience in the HLS user guide that you don't have yet (which is fine). However it's not a simple "one minute answer" like you'd expect since you're interfacing to the Zynq PS. The way you address this problem has broad implications in your design that you need to understand before you proceed. Now those in/out ports are for the HDL implementation and should be self explainatory. Jjust think of a generic dual port memory; it's two addresses, two write data's, two write enables, two clock enables and two read datas. If you don't understand what those ports mean I'll be happy to explain but that means you probably don't have enough background knowledge to do what you want just yet.

 

Now since you're trying to connect this to the Zynq PS I would reccomend taking a step back. There are a few ways to do this and while GPIO would theoretically work this probably isn't what you would want. Presumably some sort of software/driver would be communicating with your HLS design and maybe other designs on your PL. This is best handled using a memory mapped protocol like AXI (I strongly reccomend you read up on this protocol, it will come up again and again). Once you understand how AXI works you should look at the HP and GP AXI ports available on the zynq and figure out how you want to map PS to PL memory spaces. You can set a pointer from your top level function to be an axi interface. I recognize this is not just a "how do you do it answer" but in these sorts of scenarios that just isn't possible.

 

0 Kudos
Explorer
Explorer
9,137 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

@jprice Ty for answering one of my questions once again.

 

 Now those in/out ports are for the HDL implementation and should be self explainatory. 

But isn't Vivado HLS intendend to not be necessary that you write and manage HDL code? From what I can understand, Vivado HLS is a tool to transform "automatically" C code into IP blocks. However they have 0 tutorials or examples on how to deal with various interfaces, e.g. ap_memory...

 

This is best handled using a memory mapped protocol like AXI (I strongly reccomend you read up on this protocol, it will come up again and again). Once you understand how AXI works you should look at the HP and GP AXI ports available on the zynq and figure out how you want to map PS to PL memory spaces. You can set a pointer from your top level function to be an axi interface. I recognize this is not just a "how do you do it answer" but in these sorts of scenarios that just isn't possible.

I know about AXI protocol, HP and GP already, and I've used them in some examples that I made. The problem is that I can't convert the array into s_axilite since it is automatically converted into ap_memory... That's why I'm having this problem.

 

Note: See this post to see how the structure of the parameter of entrance that I'm talking about is: http://forums.xilinx.com/t5/Embedded-Development-Tools/S-Axilite-from-Vivado-HLS/td-p/593566

0 Kudos
Scholar jprice
Scholar
9,122 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

jmales,

 

    HLS will greatly help to reduce the amount of HDL you have to write yourself, however the nature/maturity of the tool and the C language is that it will not completely eliminate it (although in my experience it reduces a ton of work, very much still worth while).  Now, if you're willing to use AXI I can take a guess as to why it's using an ap_memory port instead. AXI itself is just a bus and your enterance structure doesn't directly map to that. Instead have a pointer (say a uint32 *mem) and specify that as a master AXI port (or a slave AXI lite). You should be able to read/write to it and grab the values you desire so long as you know where the data is in memory. This can work (this is exactly what I'm doing in my current design) assuming it meets your needs. I'm reasonably certain there is a way with IPI to use AP_Memory port as well but it would likely involve chaining a few cores together to make it work (and I have not yet had the occassion to do it myself).

 

Hope that helps!

 

 

0 Kudos
Explorer
Explorer
9,112 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

I'm sorrry, I haven't understood your solution. Making it a pointer doesn't solve it... The array is still declared as ap_memory

 

I tried to find a workaround. Can you check the picture in attachement to see if everything is correct?

 

What I did was separate the array parameters from the structure, and then I tried to connect it to DDR via an AXI DMA.

Everything seems well connected but when I export from SDK to the Zedboard, the result is not correct, which brings me to ask you if the following procedure is correct:

 

1-With one GPIO I set ap_start to 1 (question here is on whether I should set ap_start to 1 here or after MM2S has passed the values to the block)

 

2-With interrupts and AXI DMA initialized I pass the array to the IP block - MM2S transfer (my main doubt is here. As a stream, where is it being keep within the block? I mean, if I pass 10 values from the DDR to an IP block, where are they being kept before using in the IP block? Or are they used as they are received? )

 

3-I try reading the ap_done and ap_ready ports though the GPIO 1 (which I have set for "all inputs" ) but their values is always 0 -_-

 

Please, please help me understand what I'm doing worng.This is critical and I can't find information on how to deal with this anywhere.

Screenshot from 2015-04-28 17:03:10.png
0 Kudos
Scholar jprice
Scholar
9,083 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

No problem, I wasn't very explicit so I'll try again. Your GPIO example I don't believe will work although could be made to eventually work. However it would be very difficult to follow and hard to maintain. Below is a snippet of code that more clearly shows what I mean with regards to the AXI interface.

 

void axiTest(uint32 *DDR)
{
   //DDR should be a m_axi port that you would probably
   //connect to one of the Zynq's HP_AXI ports or an
   //interconnect that does.
   #pragma HLS INTERFACE m_axi port=DDR
   MembershipFunction input;
   memcpy(&input,&DDR[physical_address],sizeof(MembershipFunction));
}

The only unknown is how you would acquire the physical address.

 

 

However I looked at the user guide regarding the AXI Lite Slave Interface option and I suspuect this is what you really want. You can read up at it here: 2014.1 Vivado HLS User Guide.The section in question starts on page 170. The part you'll be most interested in is that it claims to automatically generate some driver code for you (I have not tested this). There is some setup invovled but it appears to go into detail on how to do so.

 

float axiTest(MembershipFunction *input)
{
   #pragma HLS INTERFACE s_axilite port=input bundle=BUS_A
   //do stuff
   return input.bound_Min;
}

This seems to compile and generates an axi lite interface for me.

 

 

 

 

Explorer
Explorer
9,069 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution
There is some setup invovled but it appears to go into detail on how to do so.

 

float axiTest(MembershipFunction *input)
{
   #pragma HLS INTERFACE s_axilite port=input bundle=BUS_A
   //do stuff
   return input.bound_Min;
}

This seems to compile and generates an axi lite interface for me.

With Membership function having the array parameters??

Which version of Vivado HLS are you using? I'm using 2014.2 and doind that generates an axi lite interface and also ap_memory interface for mf_parameters...

 

The manual you sent said in page 153 that for structures I can use the DATA_PACK directive. However I don't have it available in Vivado HLS 2014.2 don't know why.

0 Kudos
Scholar jprice
Scholar
9,061 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

Good point, for the record I'm using 2014.4. I know changing versions mid-project might be unpleasant but you may want to try to see if that AXI issue goes away. But for me it worked even with the array called parameters in the structure, I simply had to apply the correct directive. One thing you could try is to put an array_partition directive on it and see if your version is able to handle it better with that guidance.

 

 

Scholar jprice
Scholar
9,058 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

To be clear, I do not get an ap_memory interface at all, just the AXI lite interface.

Explorer
Explorer
8,566 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

Ty for the answers @jprice

 

Well, unfortunately my Vivado HLS 2014.4 license is finished and I can't even synthesize...

 

So, I'm left with 2014.2 version and I guess I'll try to get it working by setting the parameters to port axis with the use of an AXI DMA block.

 

Tell me something though:

-When I send a stream through an AXI DMA to a custom IP block, what happens to that stream? I mean, I defined the entrance as:

float parameters[4];

and then I use them within the function. So, when I send the stream of 4*4=16 bytes to the IP block what happens? Where is it being kept? I think the reason my previous block wasn't working is due to me not understanding this properly.

0 Kudos
Scholar jprice
Scholar
8,561 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

If possible try to get 2014.4 working would be my reccomendation. To answer your question, I'm not clear on how stream interfaces work with HLS. My guess is that HLS takes the incoming stream and interprets the bytes based on your inputs. In your example the first 4 bytes would be the first float, the second 4 bytes would be the second and so forth.The parameters are likely being kept in an internal memory (internal to your HLS design).  The AXI DMA core to a streaming interface in HLS should work just fine for this application.

Explorer
Explorer
8,555 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

Yes, you are correct, it should work easily. However the results being given are not correct.

 

Can I ask for one last thing that is for you to check the printscreens (and SDK code if necessary) to see what I'm doing wrong? I won't ask for anything more and I'm even willing to pay you something if you want.

 

I guess the problem is in the MM2S transfer. I managed to do a S2MM transfer already but not a MM2S.

 

Note: The files dma.c and isr.c you probably won't need to check, they are adapted from other example code

0 Kudos
Observer gorker
Observer
8,541 Views
Registered: ‎07-17-2014

Re: Ap_memory tutorial

Jump to solution

just out of curiosity, is it possible to bundle the control signals as another axi. presumably, it is easier??

0 Kudos
Scholar jprice
Scholar
8,534 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

To help you more in depth will require more context. I haven't directly worked with the SW side of Xilinx generated code. What I've done in the past was more custom (I wrote some HDL to interface to the SW side). For example I configured a memory region on the GP0 axi port and setup a small dual port memory that the PS could write directly into. I worked with a SW engineer who wrote the Linux driver that handled the SW side so I'm not familiar with how that worked. The HDL would poll certain addresses for control and then stream the necessary data out to the appropiate logic. It's certainly not necessary but I'm not familiar with the IPI flow you're using (which I agree should be possible to make work) so I'm not able to pin-point the likely small detail you've gotten wrong.  

 

What I would do is try something simpler to gain more familiarity (you likely have more experience with this flow than I do). For now take out everything and setup an AXI interconnect (two ports), then connect aa master AXI GP port to the inteconnect. I would connect a BRAM with to the interconnect along with a modified version of your design. Your design should contain a master AXI port. You need to know where in BRAM your SW writes your structure but thats a detail I believe you can figure out. If you can make this work (I think this is simpler than the method you're using) I believe that would be an excellent start (and might even get you fully there). Hopefully my thoughts here make sense. 

 

 

0 Kudos
Explorer
Explorer
8,531 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

The thing is..I really need to learn this MM2S transfer because I will need it in the future to read maps from the DDR memories.

 

But about what you said: yes it makes sense. Let's just discuss the flow oof this please:

-So, I make a BRAM block (which has just a Slave AXI port) and connect it via an interconnect to a port of the kind Master AXI that I'll make in my custom IP block. That's it? If so, problem is (again) that I can't establish the mf struct with m_axi interface. It doesn't let me and says that for example mf.bound_Min is a calara and m_axi can't be specified for scalars.

 

I can't thank you enough for the knowledge and tips you've been giving me. THANK YOU mate!

0 Kudos
Scholar jprice
Scholar
8,523 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

I don't have your version of the tool and don't have the time to directly figure this out myself. I'd certainly like to know how to use the MM2S and S2MM but I'm starting with something more familiar and hopefully we can work towards what you need.

 

To continue, don't use your structure as a parameter in your top level function. Instead create a pointer, say of an unsigned integer. Set that to a m_axi interface and and read (using memcpy) from the memory space. An example is given below. The key thing is you don't use your Membership function as an input. Instead you create an instance of it inside your design and copy from memory to it. Let me know what your version of the tool does with this but this should work. What this doesn't help you with is how to start your particular IP but I think you already have a method in place to do this.

 

void axiTest(uint32 *mem)
{
    #pragma HLS INTERFACE m_axi port=mem
    Membership_Function input;
    memcpy(&input, mem, sizeof(Membership_Function));
    process(input); 
}

 

0 Kudos
Explorer
Explorer
8,516 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

Ok, let's forget about the MM2S for now then.

 

Help me understand this well and I'll be on my way. I understand what you are saying and there's also a small example here  on page 178/179. However I'm missing something to fully understand the flow of this. Here's 2 ways of how my noob experience can understand this:

 

1-So, I connect the M_Axi output port via an interconnect to the Slave AXI port of a BRAM controller, the S_AXI of this block to a GP port from Zynq PS and then within this function (axiTest) I define the MembershipFunction? If so, then in SDK I just need to initialize the BRAM controller, start the axiTest block and we're ok to go?

 

My question at this point is: what if I want to use mf->parameters[0] inside that axiTest function, how will that work if I'm only defining it now? Or is this just an example on how to pass a MembershipFunction to RAM memory and then I need to use another (or maybe the same) BRAM controller to use that RAM memory in other IP blocks?

 

OR

 

2- I connect the M_Axi output port via an interconnect to the Slave AXI port of a BRAM controller which gives the address of RAM memory in which MembershipFunction bytes are defined (if so, how do I define them in the 1st place to the RAM memory?) and the S_AXI of this block to a GP port from Zynq PS.

 

Which option is coorect when we are doing a m_axi transfer to BRAM?

 

Sorry if the post is confusing. I'm confused as hell myself, and because of that I couldn't make it clearer than this.

 

I have no more time today, but I'll try this tomorrow first thing in the morning and I'll give you some feeedback.

0 Kudos
Highlighted
Scholar jprice
Scholar
8,514 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

No problem, it's confusing especially at first. One thing that has worked to my advantage is working at an HDL level instrinically means that you have to work at a lower level and understand low level details (which Xilinx is trying to abstract away from you with the IPI flow). It might benefit you to do some experiments in HDL if you're able. Understanding the signals might go a long way towards helping you develop a deeper understanding.

 

Now to clarify. You have the Zynq PS, which we desire to be a master, and we have your design which we also desire to be a master. We'll have a BRAM controller which we desire to be a slave. The AXI Interconnect will have two slave interfaces which you connect to masters (The Zynq PS, presumably on M_GP0 and your block). The master port of the AXI interconnect should connect to the BRAM controller. This allows the Zynq PS and your logic to both directly read/write to the BRAM controller. Now what would be desirable is if you could map a memory space from the M_GP0 port to the BRAM controller. I can not find any documentation in the BRAM controller regarding how you would do it. See if IPI gives you any options here. I just wrote custom HDL to filter the address space in the past but there must be an option to do this in IPI. For now, if yuo make a 32 by 1k deep memory it would be sufficent to keep the 15 LSBs of the address space mapped to the M_AXI_GP0 to 0. For example could map the  address space of the Zynq PS M_AXI_GP0 port to to 0xC000_0000 to 0xC000_FFFF. Writing to this address in SW will result in transactions taking place in the PL. The BRAM controller will see them and should handle them accordingly. Your software should write to the BRAM controller the necessary values in the correct byte order. Now your HLS code will know that your SW will write values starting at say BRAM Address 0 (arbitary). This should happen before your block is "called". Then your block may be called (one method is using the GPIO method you've connected to the ap_start port). When your block is called it copies data (raw bytes) into an instance of the membership function using the memcpy call. Since your block is a master like the Zynq PS, it can initiate requests. The block RAM is a slave to both the Zynq PS and your block in this example configuration.

0 Kudos
Explorer
Explorer
8,496 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

I think I finally understood the AXI BRAM flow, all thanks to you :D

 

Here's the simple function that I made to try this and in attachment the printscreen of the block design.

 

void bram_func(float    *mem, float *result_out){
#pragma HLS INTERFACE m_axi port=mem
#pragma HLS INTERFACE s_axilite port=result_out bundle=BUS_A

    float parameters[4];

    memcpy(&parameters,mem, sizeof(parameters));

    *result_out=parameters[2]+parameters[3];

} 

 

After the bitstream is ready I'll try to proper initialize the BRAM and GPIO in the SDK and I'll post the results

Screenshot from 2015-04-30 12:35:53.png
0 Kudos
Scholar jprice
Scholar
7,972 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

jmales,

 

Your connections look good! I'm glad it's finally starting to make sense. Let us know what your results are. As a heads up you can actually specify the return port to be s_axilite. This would allow you to command your block through AXI (instead of using the GPIO tied to your start). You're not doing anything wrong but that might be cleaner and more consistent if you desire. Good luck, I hope it works!

0 Kudos
Explorer
Explorer
7,964 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution
As a heads up you can actually specify the return port to be s_axilite. This would allow you to command your block through AXI (instead of using the GPIO tied to your start). 

Yes, I know. But as this is just an example to get BRAM working I didn't bother with that.

 

Well man, unfortunately I couldn't get it to work -_-

 

Here's the code:

 

int main()
{
int Status; u32 *BufferPtr,*mm2s_bufferPtr; union float32 thisone; init_platform();
//Enable the PL ps7_post_config(); /* ***** Initialize drivers BRAM and GPIO******/ Status = init_drivers(); if (Status != XST_SUCCESS) { xil_printf("Driver initialization failed!\n\r"); return XST_FAILURE; } /*Initialize IP block*/ Status = bramfunc_init(&BRAM_func); /*Write to ap_start*/ XGpio_WriteReg(XPAR_AXI_GPIO_0_BASEADDR,0x0,1); /*Set the Parameters*/ initialize_parameters(XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR); thisone.u32=XBram_func_Get_result_out(&BRAM_func); printf("Result: %f\n\r",thisone.f32); cleanup_platform(); return 0; }


static void initialize_parameters(u32 SrcAddress){
    u32 *BufferPtr;
    union float32 thisfloat;

    BufferPtr=(u32*)(SrcAddress);
    thisfloat.f32=10.0;
    BufferPtr[0]=thisfloat.u32;

    thisfloat.f32=10.0;
    BufferPtr[1]=thisfloat.u32;

    thisfloat.f32=1.0;
    BufferPtr[2]=thisfloat.u32;

    thisfloat.f32=20.0;
    BufferPtr[3]=thisfloat.u32;
}

 It's a very simple code and I feel that it should work but the printed result is 0.00

 

I tried looking into  AXI BRAM logicore IP to check the Address for which I should write but I got confused so I tried a lot of them, all with the same bad result. What am I doing wrong mate?

 

Note: here are the parameters for the BRAM block in xparameters.h

/* Definitions for peripheral AXI_BRAM_CTRL_0 */
#define XPAR_AXI_BRAM_CTRL_0_DEVICE_ID 0
#define XPAR_AXI_BRAM_CTRL_0_DATA_WIDTH 32
#define XPAR_AXI_BRAM_CTRL_0_ECC 0
#define XPAR_AXI_BRAM_CTRL_0_FAULT_INJECT 0
#define XPAR_AXI_BRAM_CTRL_0_CE_FAILING_REGISTERS 0
#define XPAR_AXI_BRAM_CTRL_0_UE_FAILING_REGISTERS 0
#define XPAR_AXI_BRAM_CTRL_0_ECC_STATUS_REGISTERS 0
#define XPAR_AXI_BRAM_CTRL_0_CE_COUNTER_WIDTH 0
#define XPAR_AXI_BRAM_CTRL_0_ECC_ONOFF_REGISTER 0
#define XPAR_AXI_BRAM_CTRL_0_ECC_ONOFF_RESET_VALUE 0
#define XPAR_AXI_BRAM_CTRL_0_WRITE_ACCESS 0
#define XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR 0x40000000
#define XPAR_AXI_BRAM_CTRL_0_BASEADDR 0x00000000
#define XPAR_AXI_BRAM_CTRL_0_S_AXI_HIGHADDR 0x40001FFF
#define XPAR_AXI_BRAM_CTRL_0_HIGHADDR 0x00000000
#define XPAR_AXI_BRAM_CTRL_0_S_AXI_CTRL_BASEADDR 0xFFFFFFFF 
#define XPAR_AXI_BRAM_CTRL_0_S_AXI_CTRL_HIGHADDR 0xFFFFFFFF 
0 Kudos
Scholar jprice
Scholar
7,959 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

There are probably a few issues. However the one that jumps at me immediately is the fact you start your block before you initialize its parameters. What happened is that you started your block and it didnt have any values yet so it probably used zeros. Swap those around and try again.

Explorer
Explorer
7,953 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

I had already tried that. the result is the same: 0.000 instead of the correct 21.000

0 Kudos
Scholar jprice
Scholar
7,948 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

The next step is to set up some debugging tools to see what is happening. Are you familiar with using integrated logic analyzer or chipscope? We'd want to verify everything, from the memory writes to the BRAM, the GPIO Start, the memory reads from BRAM and the axi_lite interface writes from your logic. Once we know where its failing we can proceed more easily.

Explorer
Explorer
7,946 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

I was actually seeing some tutorials on the integrated logic analyzer. But since I'm still a noob and while I'm not good enough to figure the problem through that tool, do you have any other suggestion looking at the code?

I can't thank you enough for all the help man ;)

0 Kudos
Scholar jprice
Scholar
7,932 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

No problem, glad I can be of some assistance! Learning to use that tool will help you tremendously so I strongly reccomend it. You will probably spend several days understanding the ins/outs of looking at signals in hardware. The rewards are well worth it if you plan to do more work with devices like the Zynq or FPGAs in general. Unfortunately without a tool like the integrated logic analyzer we don't know exactly what is going on so all I can do is take guesses. One thing you should check is to make sure the M_AXI_GP0 maps to the address range you see in your parameters. Your GPIO Base Address should also fall into that range (out of curiousity what is that value?). Keep in mind when you configure the Zynq PS you do provide it a range of addresses on those General Purpose AXI ports.

 

 

 

 

 

 

0 Kudos
Explorer
Explorer
7,929 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

Yes, I feel that way too. Learning about that tool will help my in the future when a problem like this appears.

 

If you remember a good tutorial that you used in your noob time please don't hesitate in giving it to me :D

About the M_AXI_GPO, here they are in attachment.

 

In the xparameters.h file they are:

#define XPAR_AXI_GPIO_0_BASEADDR 0x41200000
#define XPAR_AXI_GPIO_0_HIGHADDR 0x4120FFFF

 

They appear to be ok, right?

 

 

 

 

 

 

Screenshot from 2015-04-30 15:59:41.png
0 Kudos
Scholar jprice
Scholar
7,916 Views
Registered: ‎01-28-2014

Re: Ap_memory tutorial

Jump to solution

Everything looks good, so the next step is to learn to use the ILA tool. I don;t know how to use it from IPI (once again I do this sort of thing in HDL) so I can't directly give you advice on how to set it up.You'll want to look at the M_AXI_GP0 port. Signals like read/write addresses, their valids, read data/read valid, readies, etc. You'll want to reference the ARM AXI guide for definitions of these signals. This will allow us to look at the actual AXI Bus from the Zynq PS which will be very helpful.

0 Kudos
Explorer
Explorer
7,901 Views
Registered: ‎02-05-2015

Re: Ap_memory tutorial

Jump to solution

I'm actually confused about the ILA tool now. I thought it was the Chipscope tool but I realzied that within Vivado there's a tool for logic analyzer also. It this the one you're talking about?

-Video 1

 

-Video 2

 

I'm going to try and learn the tool over the long weekend, just need to first know exactly which tool it is xD

 

0 Kudos