cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
anon12850
Visitor
Visitor
1,260 Views
Registered: ‎06-30-2021

PS-PL DRAM discrepancy

Jump to solution

Hi.

I am currently facing a problem whilst attempting to exchange data between the PL and PS of a Trenz Electronic TE0808-04-BBE21-AS MPSoC module. The following test fails my expectations:

  1. I have a AXI master PL design which fills up the 0x0-0xFFC adress range with 0xFFFFFFFF through an AXI burst write upon receiving a start signal. It is a state machine, first performing a burst read (doing nothing with the data), and then performing a burst write in the mentioned address range. See axi_test_top.zip.
  2. The start signal is connected to the PS through an AXI GPIO. See platform.pdf.
  3. I have a short piece of C code which pulses the PL start signal. See main.c.
  4. I program the PL and run the code on core #0 of the PS.
  5. Once finished, I take a look at the DRAM in the XSCT console from the perspective of core #0. What I notice is that some sub-ranges of the 0x0-0xFFC address range are not filled up with 0xFFFFFFFF, but most are. I cannot explain why so. See mrd_core0.txt.
  6. I now switch targets to another PS core and I read the 0x0-0xFFC DRAM address range. I notice that everything looks as intended, the full address range is filled with 0xFFFFFFFF. See mrd_core1.txt.
I initially ran this test on a ZedBoard Rev E, obtaining similar results. In addition, the ZedBoard would not allow the PS to read DRAM values in its code after it triggered the start signal of the PL. I could only read the DRAM from the XSCT console.
 
The Vivado AXI peripheral example design with one master interface apears to behave correctly. It successfully fills up a range of DRAM addresses with an incrementing value. This convinces me that I am making a mistake in my design. But where?
Tags (3)
0 Kudos
1 Solution

Accepted Solutions
vanmierlo
Mentor
Mentor
923 Views
Registered: ‎06-10-2008

This is caching. Before you read the memory that was written by the PL you must invalidate that region in the cache of the CPU.

View solution in original post

11 Replies
anon12850
Visitor
Visitor
1,119 Views
Registered: ‎06-30-2021

The slightest clue, anyone?

0 Kudos
anon12850
Visitor
Visitor
1,111 Views
Registered: ‎06-30-2021

I guess the question boils down to: how is it possible for two PS cores to read different values at the same DRAM addresses?

0 Kudos
vanmierlo
Mentor
Mentor
924 Views
Registered: ‎06-10-2008

This is caching. Before you read the memory that was written by the PL you must invalidate that region in the cache of the CPU.

View solution in original post

dgisselq
Scholar
Scholar
906 Views
Registered: ‎05-21-2015

@anon12850 ,

I just took a quick read of your VHDL design looking for common errors.  I found two.

  • WLAST is set independent of WREADY.  This is an error.  If WVALID is true (as it would be for any sufficiently long burst), then you can't set WLAST until both WVALID && WREADY are true.  In general, however, the criteria for changing *ANYTHING* should be if (!WVALID or WLAST).
  • If WREADY is true on the clock cycle before WLAST, so that you don't have a problem, then you enter the write response state machine with WVALID and WLAST set.  This state no longer checks that WVALID && WREADY before adjusting anything, so there's your second error.

While not technically a bug, let me note that you've set the respective xVALID lines to 0 on every clock cycle, only to be overridden by the logic following.  A better choice might be to set them to zero if xREADY is true.

Dan

anon12850
Visitor
Visitor
872 Views
Registered: ‎06-30-2021

@vanmierlo 

That makes a lot of sense, thank you very much for your reply. I will let you know of the results once I look into it.

0 Kudos
anon12850
Visitor
Visitor
816 Views
Registered: ‎06-30-2021

@dgisselq 

 I see what you mean, thank you very much for your input. The attached code should be correct.

0 Kudos
dgisselq
Scholar
Scholar
784 Views
Registered: ‎05-21-2015

@anon12850 ,

No, you're not there yet.  Here are the first two bugs I found:

The first bug is that you can't test for RLAST without also testing for RVALID && RREADY.  Unless RVALID && RREADY are both true, RLAST is meaningless.  In this case, because you don't check for RVALID && RREADY, your design moves on to the write stage of the design and lowers RREADY.  The read channel of the bus will then hang.  In the best of cases, you might come back and get the burst on the next time around--but then you'd be way out of synch.

20210723-read-trace.png

Will RLAST always be high when RVALID is low?  No.  But if RVALID is low then you can't depend upon its value.

The second problem I found was in the write channel.  In this case, your first beat of a 64-beat packet starts with WLAST set.

20210723-write-trace.png

When setting up this test case, I was surprised that your design doesn't have an AXI reset input, ARESETN.  This will also lead to a protocol error.  Your state machine and your AWVALID, WVALID, and ARVALID signals all need to be reset if ARESETN is ever low.

FYI: The trace above came from a 2 second formal verification run.  It took me longer to set it up, snap pictures of the trace, annotate them, and write back than it did to find the bugs themselves.

Dan

anon12850
Visitor
Visitor
757 Views
Registered: ‎06-30-2021

@dgisselq 

I was acting under the impression that the protocol only allows for an xLAST signal to be asserted during xVALID. I see now that, to quote the AXI specifications: "The master must assert the WLAST signal while it is driving the final write transfer in the burst", does not imply it cannot be asserted otherwise.

As for the WLAST starting out asserted, I have no idea why. Maybe you modified the code? It should start out undefined:

waves.png

When it comes to the reset signal, I plan to test the design on a reconfigurable partition, and as far as I understand, all registers are cleared upon writing the bitstream. Therefore I thought I had no need for a reset. Would you have it there in any case?

On a different note, mind telling me what HDL simulator you use?

Thanks again, Dan.

0 Kudos
dgisselq
Scholar
Scholar
741 Views
Registered: ‎05-21-2015

@anon12850 ,

The reset signal is a required AXI signal, perhaps all the more so if you are trying to work within a reconfigurable partition.

I generated the traces using SymbiYosys, and plotted them using GTKWave.  The formal properties I used were my own.  SymbiYosys also selects values, 1'b0 or 1'b1 to any disadvantage it may cause, for values that would otherwise be 'x.  That's why WLAST wasn't 'x, but rather a value chosen by the solver to your disadvantage.

When I need to do simulation, I tend to chose Verilator.  Verilator works by converting Verilog (not VHDL) source to C++, and then running the C++ as the simulation.  It does not implement 'x values, since 'x isn't supported in C++.  Verilator doesn't necessarily play well with Xilinx's IPs, but then I'm not known for using Xilinx IPs.  When Verilator doesn't work for me, then I've been known to use Icarus Verilog or (on one project) XCellium.  (I'm not much of a VHDL type.)

Dan

anon12850
Visitor
Visitor
737 Views
Registered: ‎06-30-2021

@dgisselq 

Very interesting, thank you.

0 Kudos
anon12850
Visitor
Visitor
573 Views
Registered: ‎06-30-2021

@vanmierlo 

You're right of course, I marked your reply as the solution. Thank you again.

I get the expected results doing one of the following before reading the DRAM:

  • Disabling the data cache using Xil_DCacheDisable().
  • Invalidating the whole data cache using Xil_DCacheInvalidate().
  • Invalidating just the required range using Xil_DCacheInvalidateRange(INTPTR adr, INTPTR len).

The functions are declared in xil_cache.h.

0 Kudos