Jump to content

artvvb

Technical Forum Moderator
  • Posts

    1,057
  • Joined

  • Last visited

Everything posted by artvvb

  1. 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: Schematic: Thanks, Arthur
  2. I believe that to get the updated bitstream into BOOT.bin, you need to clone the petalinux project, use petalinux-config to swap out the HDF file with a new export from your project, then rebuild and repackage the project. https://github.com/Digilent/Eclypse-Z7-OS/tree/zmod_adc_dac/master
  3. 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.
  4. 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
  5. 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
  6. 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
  7. Hi Leuven, This demo supports the Zmod ADC (renamed to the Zmod Scope) 1410-105 in 2019.1: https://digilent.com/reference/programmable-logic/eclypse-z7/demos/zmod-scope. Have you tried it, and if so, could you describe issues you run into with the checkout process? Thanks, Arthur
  8. Recreating the Vivado project for this demo requires Vivado 2019.1 and the process is documented here: https://digilent.com/reference/programmable-logic/eclypse-z7/git. What version are you using?
  9. 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, ... 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. 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. 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: 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. 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. Hopefully my thought process is relatively clear.
  10. 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.
  11. Hi @amna Could you provide the settings of your DDS compiler? The more IP settings provided the better, to make it easier to reproduce your results. I'm also assuming your results are in simulation? Thanks, Arthur
  12. 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
  13. artvvb

    XAPP 495

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

    XAPP 495

    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
  15. 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"); 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:
  16. Hi @Vincent Bartolomei The Pmod RS485 is listed on our store here: https://digilent.com/shop/pmod-rs485-high-speed-isolated-communication/. You can find distributor stock at the bottom of the page. Thanks, Arthur
  17. 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
  18. 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.
  19. 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.
  20. Sure. The GPIOs are both configured for a single output-only channel and are being used to drive the counter's control/configuration inputs.
  21. 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.
  22. Hey @CEEJ38 Apologies for the delay. There are various ways forward depending on the architecture you're going for and the systems/subsystems you want to learn about - if you want to do something only in Vivado with Verilog, that's possible. If you want to use software with the existing peripherals or custom peripherals, either is possible. The block design as presented ought to work - the Zynq PS runs software that controls both peripherals and would repeatedly poll the Pmod controller and update the PWM controller in a loop. The main thing to pay attention to would be translating from the PmodAD1's ADC codes to PWM duty cycles - the software would likely do some extra math to scale or offset these values however you want. If you want to learn to design your own peripheral, you would be looking into how to design an AXI peripheral (or other form of PS-PL communication). Funcdamentally, the goal would be to expose the pulseLength value to software. You could potentially do something like convert the pulseLength value into an input to your main_file module, instantiate the main_file module in your block design, and connect the pulseLength input to something controlled by software. As an easy first step, you could control the new pulseLength input with an AXI GPIO. I recently wrote about some related info on using AXI GPIOs for this kind of purpose here: Third option, you could implement everything in the programmable logic (FPGA fabric). I wouldn't recommend using the PmodAD1 IP core for this, as you would then need to write a custom AXI4-lite master (probably overly complex and a large topic), however, you could pull the SPI controller out of it (https://github.com/Digilent/vivado-library/blob/master/ip/Pmods/PmodAD1_v1_0/src/ad1_spi.v) and put together a relatively simple FPGA-only design in Vivado. You'd be designing a bridge component that can pull data out of the AD1 controller whenever it's ready and send it to a custom PWM component. Thanks, Arthur
  23. Simulating your code has a much faster turnaround time when tweaking IP settings and checking results than repeatedly building bitstreams and programming them into the FPGA. As previously mentioned, please check the radix you're using while viewing your data. Your results look like you're using signed magnitude instead of signed decimal.
  24. Hi @Mamatchai Edit: There's no specific zmodlib API function for reading back the trigger value after it's written, you'd need to store data in the application calling setTrigger or one of the acquire functions. The rest of this comment is about how to work around this. So these tips are mainly for baremetal. Linux user space virtual addresses probably complicate things, and could require modifications to zmodlib sources. A screenshot showing each is attached. You can view values stored in memory-mapped registers in the debugger - though this feature has had a bug in some versions of Vitis where only the lowest byte of each word can be viewed (this can be seen in the screenshot). You can also use a debugger expression to determine the value of the register at a particular point in the code, by dereferencing its address. Note that the debugger may not have access to macros coming in from headers like xparameters for this, so you may need to declare the pointer in the code. If you're trying to modify the code to read the register value and then use it for something, you can use the above method of dereferencing a pointer that has been set to the register address. Hope this helps, Arthur
  25. Hi @jarvis Please refer to Viktor Nikolov's tutorial for using the MIG here: Thanks, Arthur
×
×
  • Create New...