Jump to content

artvvb

Technical Forum Moderator
  • Posts

    1,063
  • Joined

  • Last visited

Posts posted by artvvb

  1. The Zybo's demo is HDL-only, so it's correct that you aren't seeing a block design. The Cora Z7's XADC demo (another Digilent Zynq board) involves setting up an XADC IP with an AXI interface to the processor in a block design: https://digilent.com/reference/programmable-logic/cora-z7/demos/xadc. Screenshots are attached. Specifics of the XADC configuration will differ, but it hopefully could help show you how to connect and constrain things. I'm not positive but suspect that you should connect the Vaux0 and Vaux1 interfaces externally, rather than the individual pins, and constrain both the _p and _n pins regardless of whether the input is single-ended or not. The warnings imply that the tool is trying to use an IBUF primitive, input buffer for a digital pin, rather than actually use the dedicated XADC input routing.

    UG480 also states that location constraints do not need to be specified (quote below), so it could be unnecessary to include them (although the same lines are where the required IOSTANDARD is set): https://docs.amd.com/r/en-US/ug480_7Series_XADC/Analog-Inputs.

    Quote

    The auxiliary analog inputs do not require any user-specified constraints or pin locations. They do not require an I/O standard setting to be added to the UCF or in the PlanAhead pinout tool. In the Vivado design tools, an IOSTANDARD must be selected that is compatible for the bank even though the IOSTANDARD does not affect the input programming. All configuration is automatic when the analog inputs are connected to the top level of the design.

    image.png

    image.png

     

  2. Unless you have a particularly power-hungry demo, you can power the board over USB from your laptop - that said, this supply is compatible: https://digilent.com/shop/5v-2-5a-switching-power-supply/. You can also program it directly over USB via J12. Installing Vivado should install the drivers that are needed to talk to it. I'd recommend you run through the reference manual and some of the tutorials listed on the board's resource center: https://digilent.com/reference/programmable-logic/zybo-z7/start.

  3. Hi @oldViking

    You can compare where the input port for your reset has been placed in the synthesized or implemented design to the FPGA pin associated with the CK_RST schematic net. For example, the screenshots below show that the leaf cell "led_4bits_tri_o_OBUF[0]_inst" in a design for the Arty A7 maps to the site H5, which corresponds to the LED4 net of that board.

    Synthesized design:

    image.png

     

    Schematic:

    image.png

     

    Thanks,

    Arthur

  4. The quoted text is intended to mean that the guide is unlikely to work as written with 2023.2. 2023.1 should work fine as it's what it was written for. We've updated the text in the infobox to be more clear.

  5. Hi T106A81,

    This is a big project. If you just need a 125 MS/s ADC, you could take a look at the Zmod Scope & Zmod Digitizer variants that support that rate, along with an Eclypse. Note that Digilent's example code generally doesn't run at 125 MS/s out of the box either, so there are additional steps that would need to be taken to modify existing demo material. IP designed for those products is at least somewhat similar to what you would need to create for AD9255/65, but I don't have all of the details. The ADC vendor likely also provides some sample code.

    Thanks,

    Arthur

  6. Hey Jey,

    Increasing the clock speed of the DMA and potentially increasing the width of the DMA master interface to 64 bits from 32 bits can help, but I'm not sure how much of an improvement you will see, as each AXI transaction the processor or DMA performs (register read, register write, DMA write, etc) blocks the loop for a period of time. Single-sample reads like it looks like you are doing also require many more transactions than bursts do (several registers are read and written to every time a DMA transfer is performed).

    Scatter gather DMA can be used to queue up DMA transactions, which is used in this demo to stream data into DDR from an ADC at full rate: https://digilent.com/reference/programmable-logic/eclypse-z7/demos/ddr-streaming. It also makes use of both of the previously mentioned techniques (higher clock frequency for the DMA, increased interface data width) to improve throughput. It's built for 2021.1 rather than 2019.1 unfortunately.

    Thanks,

    Arthur

  7. Hi Oscar,

    Please review this guide, "Getting Started with Zynq Servers", which runs through setting up one of AMD's TCP echo server example: https://digilent.com/reference/programmable-logic/guides/zynq-servers. This will get data into and out of the PS, after which PS-PL communication can be implemented using EMIO peripherals, AXI IP such as GPIOs or custom modules, or DMA. Digilent doesn't currently provide a demo for the Zybo Z7 that integrates every part of this communication chain.

    Thanks,

    Arthur

  8. Running through the debugging process:

    Using a 20-word (80-byte) transfer for the sake of being able to see things on screen. Below is the input stream going into the DMA. You can see that it counts from 0 to 19, and on that 19 (the 20th word), tlast is asserted. If an issue with the counter module was causing the first two words to be corrupted, I'd expect to see it here, but everything looks as expected. - If the DMA worked perfectly, but the counter provided data to it that didn't match what I expected, then the data seen in software would also be wrong, not the case here, since we see the expected 0, 1, 2, 3, ...

    image.png

    Below is the output of the DMA, the AXI master interface that writes to DDR. The DMA takes the input stream, breaks it up into bursts, and sends data to DDR by first writing an address and then the data - here you can see the first ten bytes are transferred in one burst, starting with address 0x2062d8. After the DMA transfer is complete, the processor will be able to access that memory and see the new data. Again, if there was an issue with the DMA or the counter, I'd expect to see it here, potentially by seeing a value other than 0 or 1 on the WDATA bus at the start of the transfer.

    image.png

    Now in the Vitis debugger, this is where we can actually see the bug. I can look at the data in DDR after the transfer by setting a breakpoint after the Xil_DCacheInvalidateRange call, and using the "Memory" view to monitor the address that the buffer is pointing at. In this case, I have two breakpoints set. One at the start of the do_transfer function, so that I can check the buffer address in the "Variables" view. I take that buffer address and add it to the memory view, which shows me that the data is set up as expected - in the code pictured, I'm zeroing everything other than the first word to make sure that the expected value after DMA is different from the known value before the transfer.

    image.png

    Hitting continue to go to the next breakpoint, we can see that everything except for the first two words is updated correctly - the red delta indicates that there's a difference in the value at that memory address since the last time the processor was halted:

    image.png

    This is then checked by the program and the pass/fail is printed to console, in this case a fail since the first two words don't match the expectation.

    image.png

    So, the issue doesn't seem to be with the hardware, at least up to the DMA output. Either the first two words aren't being written by the DMA transfer at all, or they are overwritten behind the scenes after the transfer is completed (overwritten specifically back to the original state).

    Moving the buffer declaration out of the do_transfer function so that it's a global variable seems to consistently fix it (it puts the buffer at a different place in memory). That said, I'm still not sure what exactly is going on. I tried increasing both the stack and heap sizes in lscript.ld to 0x200000, which didn't help. I also tried checking the "allow unaligned transfers" box in the DMA settings, since alignment can also matter, which also didn't help.

    image.png

    Hopefully my thought process is relatively clear.

  9. Ugh, I'm really sorry, there's a bug I didn't catch... The hardware design seems to be fine but the second word in the buffer is getting overwritten at some point, possibly due to insufficient memory in the stack/heap, memory alignment, or some pointer issue. Taking a look.

    I also likely should have started a new thread when posting the example code, rather than replying into this one.

  10. Hi @Bach

    Local memory size is set when you run Block Automation to build out the system around the Microblaze processor in Vivado - you can't change local memory size from Vitis as the amount of BRAM dedicated to it is part of the hardware design. The easiest way to increase it is often to go back to Vivado, strip out Microblaze and many of the core blocks that come with it, add a Microblaze IP back into the design, and rerun Block Automation picking the largest local memory available (likely 64k). If you need more than 64k of memory and your board has DDR, you should use it (again, by modifying the hardware design).

    Alternatively, reduce the amount of memory used by your software app - common libraries for C/C++, even stdio, can be too large for a system with very little memory.

    Thanks,

    Arthur

  11. If you believe you have been mistakenly flagged by AMD's US export control / trade compliance policies, please reach out to their support.

  12. Hi @M.Saad Ikram

    This link is still active but requires logging in and filling out a design license agreement to access the files. The license agreement restricts the sharing of files, which means we are unable to help.

    Thanks,

    Arthur

  13. 46 minutes ago, Xband said:

    my serial terminal output is a few "test done" printf statements. 

    This is a good thing - it means that the data returned into the buffer matches the expected incrementing values and no mismatch was printed. To confirm, you could modify the section and add a pass/fail message after it checks the buffer contents as below:

    	// verify the transferred data is as expected
    	u8 test_good = 1;
    	for (u32 i = 0; i < transfer_length; i++) {
    		if (i != buffer[i]) {
    			xil_printf("buffer[%d]: %d != %d\r\n", i, buffer[i], i);
    			test_good = 0;
    		}
    	}
    
    	if (test_good == 1) {
    		xil_printf("test passed\r\n");
    	} else {
    		xil_printf("test failed\r\n");
    	}
    	xil_printf("test done\r\n");
    50 minutes ago, Xband said:

    When the ILA is launched it is "waiting for trigger" 0 of 1024 samples. 

    For the ILA, I'm not certain what you mean. To verify that data is flowing:

    1. Launch the Vitis debugger (right-click on system project in Vitis, select Debug -> Launch Hardware). After some time putting the bitstream and application onto the board, the trace will be planted at the top of main - you should see one of the lines of code turn green to indicate that this is where the program is currently. If you want, set a breakpoint at the end of the do_transfer function by right-clicking to the left of the line number and selecting "Toggle Breakpoint".

    2. Open Vivado Hardware Manager and Open Target -> Auto Connect to the hardware server. You should see the ILA interface appear. You may need to add signals to the Waveform view, if so, click the plus button in the top left, select all, and hit OK.

    3. Configure a trigger in the ILA. Trigger Setup pane, click the plus button, search for and select both axis_counter_0_count : TREADY and axis_counter_0_count : TVALID. Set the Value dropdown for both to "1 (logical one)". Operator should stay "==". Make sure the gate button at the top of the Trigger Setup pane is set to 'Global AND'. This will make it so that the logic analyzer will trigger the first time that ready and valid are simultaneously asserted at the counter module's output, which is when data starts moving.

    4. Click the Run button in the ILA Status pane to start it. Click the Resume button in Vitis (or F8 hotkey) to launch the program. The ILA should fill with data. You should expand the interface and channel groups of interest to see individual signals. Should look something like this:

    image.png

  14. For interrupts, there might be a way to work around it by making sure that zmodlib and the constructors for its classes either don't reinitialize the xscugic driver, or to make sure the constructors get called before the ethernet code initializes the driver. A quick way to check it would be to comment out or remove code from the functions in Zmod/baremetal/intc.c (assuming you're using baremetal).

    XStatus fnInitInterruptController(XScuGic *psIntc)
    {
    	return XST_SUCCESS;
    }
    
    void fnEnableInterrupts(XScuGic *psIntc, const ivt_t *prgsIvt, unsigned int csIVectors)
    {
    	return;
    }

    This would prevent zmodlib from reinitializing the interrupt controller and from registering any interrupts - which also means no interrupts that zmodlib uses would work anymore and you'd have to rely on the Polling acquisition functions. I'm not 100% sure whether there are other interrupts in zmodlib that are still used when using Polling functions, but I don't think so.

    That said, either a substantial rewrite of the ethernet code (so that it uses zmodlib's intc API) or a rewrite of the zmodlib source so that it can be told to not reinitialize the interrupt controller would probably be the better long-term solution.

    Hope this helps,

    Arthur

  15. ZMODADC1410_REG_ADDR_TRIG is an offset - there should be a corresponding BASEADDR (base address) macro in the "xparameters.h" file, add the offset to the base address, rather than just using the offset. In the screenshot in my previous comment, you can see the addresses are coming from "XPAR_AXI_DMA_0_BASEADDR + * + XAXIDMA_*_OFFSET". Ignore the middle value, it's specific to the DMA IP and doesn't apply to the Zmod ADC controller. You should have something like "XPAR_(Zmod ADC controller name)_BASEADDR + ZMODADC1410_REG_ADDR_TRIG".

    I apologize if that's not super clear - if you have the Vivado project, you can also see where base addresses are assigned for different peripherals in the Address Editor, something like this is usually in the 0x40000000+ range (that DMA core in the screenshot is at address 0x40400000). You can also get this info in the hardware platform SPR file, though the xparameters.h header is where to get it for the code itself.

    image.png

  16. I've attached an archive of the project. As mentioned before, it targets Eclypse Z7 and is for 2023.1: basic_dma_pl_to_ps.xpr.zip

    It's minorly different from the block design screenshot in the original comment but I think the only change is the addition of an ILA for debugging some of the AXI interfaces.

  17. All of the code is running in the processor unless explicitly specified. There are two approaches to HLS - one is to create a separate project in Vitis HLS that is compiled into an IP that you then include in your Vivado project. The other way requires a platform created in Vivado, which is then rebuilt under the hood in Vitis while stitching in IP written with HLS, likely running a Linux image - Digilent generally doesn't provide these platforms, at least currently. In either case, it has to be intentionally set up.

×
×
  • Create New...