Hey folks,

ZynqHW_2017_4_lab_6_v12.pdf

 

So let's continue our arduous journey through the lab manuals. Boy, aren't things spicing up a bit?

So the first part of lab 6 shows us to import our SDK files done from Lab 3. The main aim was just to show us how to import lab files. So in all fairness, we won't be needing those lab files.

The next part talks about importing a pre-made C file which executes the following steps :

  • Number of words the user wants to transfer
  • The manner in which these would get transferred
  • And a small report talking about the number of clock cycles used by a BRAM transfer and the number of clock cycles used by a DMA transfer.
{gallery} Outputs from Lab 6

Build output of the C file

Build Output : .elf file loaded onto the Cortex

Output from the board

Output from the board:Note the menu options

Output from the board

Output from the board: What an ambiguous output indeed!

Hmmm sounds fishy that last part...Looks like we will have to see under hood on what's going on :

So looks to me like a pretty straight forward code : I have added a few helpful comments here and there My dma_test.c . To be honest, I got stuck at a few parts in the code and had to continuously refer to the documentation given for each peripheral. A brief outline of what the code does is given below:

  • Initializes the following in order : A UART connection for user interrupt, Setting up the GIC along with the Interrupt Service Routine, a PS_Timer and finally the PS_DMA definitions.
  • The Scu Private Timer had started just before printing out the message "-----Simple DMA Design-----" after which the counted timer value was printed out.
  • A while loop is initialized taking a number of words as input. Here the size of a word would be size of a single entry in the Memory unit of the ARM (PS side) [So 32 bits I presume]
  • The timer is reset and then starts off again for each of the testcases (here BRAM and DMA)
  • For a BRAM transfer, no fancy function (from bram_cntrl_0 documentation) was used as the ECC (Error Correction Capabilities) was not enabled. Thus we could directly write in and out of the memory ranges of the BRAM unit (which is what the program does)
  • The next part uses passes data through the DMA instead of the BRAM. All functions and structures used to start the DMA are given in this file - have a look : xdmaps.h
  • Finally the results are printed out.

A short notes on what I observed : No DMA was initialized on the PL side. Instead it was setup by the PS. For better visualization isn't it better to setup a block diagram in the PL? Probably the lab was getting complex as it is and they thought of this shorter way. Also from what I've read soft DMA in fabric is way faster than the PS DMA controller thanks to HP ports. So implementing it in the PL would have been a better choice, no?

So that about covers lab 6.

 

Tomfoolery

 

The GIC or Generic Interrupt Controller is used to manage different interrupts between PL and PS side. It is required to setup the DMA in poll-mode. The counter is initialized when data is about to be sent to the DMA from let's say here the DDR . An interrupt is also sent to stand by all other low priority interrupts. After which the DMA sends data (here the DDR) and the counter is reset. This gives us the number of clock cycles. What happens if we remove the interrupt altogether? I mean, there can't be any other higher priority process running in the background right? So the DMA should respond naturally to the data sent by the DDR.

Turns out  I was wrong.

The DMA needs an interrupt and a handler to start off, irrespective of any other process being run at the background.

 

Easter egg ! - Inheritance level 99

Inheritance lvl 99

 

ZynqHW_2017_4_lab_7_v13.pdf

 

This lab talks about packaging a new IP with an AXI-4 connection. It also talks about setting up a debug ILA too.

So, having a glance at the source code Avnet has given is (a) it is in VHDL and (b) some constructs, I think are poorly written. For example in PWM_Controller_Int.v:

Looks funny doesn't it? We can simply write this procedural block as :

always @ (posedge Clk)

    if(DutyCycle > 990000)

        Interrupt <= 1;

    else

        Interrupt<=0;

Well , according to me, it's not too major a error so we can ignore this for now. Also the IP src files are written in VHDL. For the Verilog guys, I have written the IP as a Verilog design and is on  My repo  . Feel free to use it. Other than that the lab drags out with the steps to setup a new PWM output IP. The final IP properties block should look something like this :

Also a quicker way to setup the ILA is - right click on the wires you want to debug and select Debug.

After which just run the Connection Automation green dialog which appears. The final block diagram looks like this :

After which we have to add to JTAG-AXI core IP. So basically this is a TCL console controlled Ip where we generate AXI transactions through JTAG to the block design. Another IP could be used instead is the AXI Traffic Generator. Infact, there would be no TCL console required here! And instead of generating a separate PWM module for generating PWM, One could also use the AXI timer in PWM mode. However, the period and the duty cycles have to be setup in the PS side ( C file SDK).

Final Block Diagram

That was some food for thought,  until next time e14!