Jump to content

artvvb

Technical Forum Moderator
  • Posts

    1,067
  • Joined

  • Last visited

Everything posted by artvvb

  1. artvvb

    PS GPIO - baremetal

    Sounds like the interrupts are triggering on active-high level sensitive. You should be able to change the interrupt type to edge sensitive: /****************************************************************************/ /** * * This function is used for setting the Interrupt Type, Interrupt Polarity and * Interrupt On Any for the specified GPIO Bank pins. * * @param InstancePtr is a pointer to an XGpioPs instance. * @param Bank is the bank number of the GPIO to operate on. * Valid values are 0-3 in Zynq and 0-5 in Zynq Ultrascale+ MP. * @param IntrType is the 32 bit mask of the interrupt type. * 0 means Level Sensitive and 1 means Edge Sensitive. * @param IntrPolarity is the 32 bit mask of the interrupt polarity. * 0 means Active Low or Falling Edge and 1 means Active High or * Rising Edge. * @param IntrOnAny is the 32 bit mask of the interrupt trigger for * edge triggered interrupts. 0 means trigger on single edge using * the configured interrupt polarity and 1 means trigger on both * edges. * * @return None. * * @note This function is used for setting the interrupt related * properties of all the pins in the specified bank. The previous * state of the pins is not maintained. * To change the Interrupt properties of a single GPIO pin, use the * function XGpioPs_SetPinIntrType(). * *****************************************************************************/ void XGpioPs_SetIntrType(const XGpioPs *InstancePtr, u8 Bank, u32 IntrType, u32 IntrPolarity, u32 IntrOnAny) Cheers, Arthur
  2. See attached. The software app should just be a default empty C application with the three source files added in. Reviewing the traffic_generator.v file may be of particular interest. project_10.xpr.zip gpio.c gpio.h
  3. artvvb

    PS GPIO - baremetal

    That may constitute a bug in the board files' Zynq preset. Will look into getting it fixed. Thank you for writing out your debugging process as you went, reproducing and fixing it should be pretty straightforward, given the information you've presented. -Arthur
  4. Digging some more, the MIG configuration also allows the input clock buffer to be removed, so this might actually be doable:
  5. It seems that both the MIG and clocking wizard try to instantiate the input buffer (IBUFG) that the clock must pass through on its way from the pin. If these buffers were removed from generated HDL sources and placed in an RTL module feeding into both the MIG and clocking wizard, perhaps this could work, however, that could be a painful process in the tools, especially managing when those generated sources might be updated and overwritten. The "No Buffer" on input clock option in the clocking wizard would be helpful. Some related info: https://support.xilinx.com/s/question/0D52E00006hpsa9SAA/using-a-global-clock-buffer-at-a-clock-capable-pin?language=en_US And a relevant critical warning: Thanks, Arthur
  6. Working on it, will reply here when we have the document. Thanks, Arthur
  7. If you haven't manually installed the board files per the guides JColvin linked, this behavior can show up. Click the download button in the "Status" column for your board to install the version of the board files present in Xilinx's system. See below: Thanks, Arthur
  8. artvvb

    Cannot export hardware

    Exporting a hardware platform assumes that you have created a block design that includes a processor, and an address map that informs how the processor will communicate with various peripherals in your design. The step is not needed if you aren't going to bring your design up into Vitis to write software. If you have a bitstream without a processor that you want to run on your board, you may want to refer to a guide like this instead: Getting Started with Vivado for Hardware-Only Designs.
  9. artvvb

    Cannot export hardware

    Have you created a block design and generated a bitstream for your project? This error looks like what would happen if you tried exporting a hardware design from an empty project. Thanks, Arthur
  10. Great post! It's always shocking just how simple a straightforward tcl build script is. It's subjectively so much easier to "just get in and start designing" when you don't need to fire up multiple heavy applications just to use a text editor, or go ten levels of UI deep to change some IP setting in a wizard. Worth noting here that the write_bd_tcl command that is often used to automatically generate scripts to recreate block designs has some optional flags that allows you to ignore the version numbers of IP being included into a project. That doesn't get around the fact that IP changing versions between Vivado versions comes with the possibility that the ports and parameters don't match up, but at least the script can try to add it. Also with regards to the IP integrator, the following shows up in every block design TCL script, and really underscores how valuable just going in and seeing what you can make happen in text editors, without the Vivado GUI, really is. There are several similar posts that have been floating around, hwjedi and starware design's come to mind.
  11. artvvb

    PS GPIO - baremetal

    In the xgpiops drivers, I'd also refer to lines 154:159 of xgpiops.h: And to the XGpioPs_GetBankPin implementation in xgpiops.c, relevant part around line 763. The function is able to return which pin index within which bank a given MIO# is connected to. Thanks, Arthur
  12. Typically, Digilent's product roadmap is planned years in advance. So when I say "any time in the near future", I'm inferring that there is currently no plan on our roadmap to end of life the 3000-series devices. Of course, these things can change due to unforeseen circumstances, but that's above my pay grade.
  13. On it. No promises on an update, but we'll take a look at it. There are a couple other of these ethernet echo server guides for various boards that could also use some TLC. Thanks, Arthur
  14. Yes, but 32-bit int should be aligned by default, the suggestion was made assuming that you might be using a u16 declaration. After increasing receive buffer size and validating data a bit more, two successive transfers of both 1,000 four-byte samples each is now working. Also worked with 10,000-sample SimpleTransfers. main.c Here are my DMA settings:
  15. This ought to generate XST_INVALID_PARAM errors, but you should also make sure that adcDMAArray is aligned to a 4-byte address boundary. I'm looking more into this and managed to reproduce the issue: Using a project I had sitting around for 2021.1, main.c below, I seem to also be running into the same issue when trying to use larger requested numbers of bytes, the buffer length and buffer address registers are getting masked to 8 bits. Requesting 4000 (0x7A0) bytes to a buffer address at 0x10c794, and the DMA buffer address register (0x48) updates to 0x94 and buffer length register (0x58) updates to 0xA0. I haven't checked the block design and IP settings for my project again yet, but the width of buffer length is 26 and it has some custom counter hardware to generate test traffic sitting in front of the DMA - still clearly having some issues with the CR run bit being high while idle. Data isn't transferred past 0x102, meaning 1k bytes are transferred before halting. It almost seems like only the bottom 8 bits of each of these registers are wired up in hardware. Will look into this more tomorrow. Also, another approach to tackling issues with the DMA simpletransfer function (just doing the register accesses yourself) is detailed here: #include "xparameters.h" #include "xaxidma.h" #include "xil_printf.h" #include "gpio.h" XAxiDma axi_dma; const int axi_dma_id = XPAR_AXI_DMA_0_DEVICE_ID; #define num_gpio XPAR_XGPIO_NUM_INSTANCES const reg reset_bit = {XPAR_AXIS_TRAFFIC_GENERATOR_AXI_GPIO0_DEVICE_ID, 1, 0, 1}; const reg start_bit = {XPAR_AXIS_TRAFFIC_GENERATOR_AXI_GPIO0_DEVICE_ID, 1, 1, 1}; const reg busy_bit = {XPAR_AXIS_TRAFFIC_GENERATOR_AXI_GPIO0_DEVICE_ID, 1, 2, 1}; const reg high_count = {XPAR_AXIS_TRAFFIC_GENERATOR_AXI_GPIO0_DEVICE_ID, 2, 0, 32}; const reg packet_high_count = {XPAR_AXIS_TRAFFIC_GENERATOR_AXI_GPIO1_DEVICE_ID, 1, 0, 32}; #define RECV_BUFFER_SIZE 1024 u32 recv_buffer[RECV_BUFFER_SIZE]; void DmaInitialize () { XAxiDma_Config *cfgptr; cfgptr = XAxiDma_LookupConfig(axi_dma_id); XAxiDma_CfgInitialize(&axi_dma, cfgptr); XAxiDma_Reset(&axi_dma); XAxiDma_IntrDisable(&axi_dma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DEVICE_TO_DMA); XAxiDma_IntrDisable(&axi_dma, XAXIDMA_IRQ_ALL_MASK, XAXIDMA_DMA_TO_DEVICE); } void TrafficGenInitialize () { GpioInitialize(); RegWrite(reset_bit, 1); RegWrite(reset_bit, 0); // RegWrite(start_bit, 1); // RegWrite(start_bit, 0); // RegRead(busy_bit, 1); } u32 TransferDone () { return !XAxiDma_Busy(&axi_dma, XAXIDMA_DEVICE_TO_DMA); } void ReceiveData (u32 words_per_packet, u32 packets) { UINTPTR buf_addr = (UINTPTR)recv_buffer; RegWrite(high_count, words_per_packet - 1); RegWrite(packet_high_count, packets - 1); Xil_DCacheFlushRange(buf_addr, RECV_BUFFER_SIZE); XAxiDma_SimpleTransfer(&axi_dma, buf_addr, words_per_packet * sizeof(u32), XAXIDMA_DEVICE_TO_DMA); RegWrite(start_bit, 1); RegWrite(start_bit, 0); while (!TransferDone()); for (int i = 1; i < packets; i++) { u32 offset = i * words_per_packet * sizeof(u32); XStatus status = XAxiDma_SimpleTransfer(&axi_dma, buf_addr + offset, words_per_packet * sizeof(u32), XAXIDMA_DEVICE_TO_DMA); if (status != XST_SUCCESS) { xil_printf("simple transfer error\r\n"); } while (!TransferDone()); } Xil_DCacheInvalidateRange(buf_addr, RECV_BUFFER_SIZE); } void ValidateBuffer () { for (u32 i = 0; i < RECV_BUFFER_SIZE; i++) { u32 d = recv_buffer[i]; xil_printf("%08x\r\n", d); } } int main() { DmaInitialize(); TrafficGenInitialize(); ReceiveData(1000, 2); ValidateBuffer(); xil_printf("hello world\r\n"); }
  16. Hey @zzzhhh, sorry for the delayed response. I'm the one who wrote the guide in its current form a while back, and honestly, I'm not sure. I've been digging around in some Xilinx docs (links below), and haven't been able to come up with anything definitive so far. Perhaps using the clock would impose an otherwise unnecessary clock domain crossing on the AXI data bus connection to the MIG. Perhaps the high fanout of using the clock in many places across the design would make it more difficult to meet timing once the FPGA is more full than it is with the simple setup created in the guide. Perhaps using the clock for logic would pull it off of the CMT backbone that it needs to be on for the MIG (I don't think this one is the case, since the clock on the backbone seems like it could drive both a BUFG and a CMT/PLL?). Maybe someone with deeper experience will be able to jump in. If you build a system with Microblaze being clocked from the system clock input and don't run into any related warnings, are able to meet timing, and the clock interactions look okay, you should be good. Docs in question: https://support.xilinx.com/s/article/40603?language=en_US https://docs.xilinx.com/v/u/1.4-English/ug586_7Series_MIS, particularly "Clocking Architecture" p69 https://support.xilinx.com/s/question/0D52E00007G0d8DSAR/whats-the-meaning-of-backbone?language=en_US https://docs.xilinx.com/v/u/en-US/ug472_7Series_Clocking Hope this helped, Arthur
  17. Hey @connoisseur_de_mimi, There are a couple of different versions of the IP floating around. Any of the low-level controllers should be able to be used in any version 2019.1 or newer, given you're implementing your own block design. Version support gets hairy when IP include drivers or you're trying to start from an existing project that relies on specific built-in IP versions. Vitis now automatically creates an FSBL for you when you check a box in the new application project wizard. It looks like you did this since the zynq_fsbl BSP exists in your project. Xilinx SDK didn't do this, which is probably why the threads you saw recommended creating one. This means you probably already have the correct boot.bin file being generated whenever you build your system project. This guide details how to create a boot image for Zynq boards: https://digilent.com/reference/programmable-logic/guides/zynq-baremetal-boot Thanks, Arthur
  18. Hi @connoisseur_de_mimi, Yes, going over the DMA buffer length register's size is a problem when doing SimpleTransfers. You can increase the max transfer length by adjusting the setting in the IP configuration (see screenshot below). It can be increased up to 26 bits. Transfer length is specified in bytes, not words. 2^26 bytes (~67 MB) should barely fit the needed 64 MB. The default 14 bits can only handle a 1024-sample frame. Even if you need more data than fits in one frame, you can get away with repeated SimpleTransfers, given sufficient buffering in FIFOs. I've only worked with polled mode DMA, but you should be able to wait until XAxiDma_Busy stops returning a busy status. As noted, probably not if 64 MB is your max, but you would if you wanted to go much larger. A couple of extra notes: Make sure tlast is only generated once per SimpleTransfer, on the right beat, sending one beforehand should stop the transfer partway through. Given this, make sure that the PS and PL are on the same page for the length of any particular transfer. A counter with a rollover value specified by the PS via AXI4-Lite that asserts tlast on rollover is one way to accomplish this. Always using the same frame length is another way. This shouldn't be relevant at 1 MS/s, but more for anyone else reading who is using a faster input stream: Having a FIFO in front of the DMA is good. You should still make sure that the DMA has enough data bandwidth on both the AXI4-stream and AXI4-full master interfaces to sink your incoming stream, including the AXI protocol overhead. Increasing its clock frequencies above the base sample rate is a good idea. So is using a 64-bit wide memory map data width (to match the width of the Zynq PS's HP slave interfaces). There's an under-construction demo for the Eclypse on the Reference site that uses scatter-gather to perform arbitrary-length transfers that might be useful to you. Apologies that the code is still pretty messy, I haven't made the time to clean it up and finish it. There might also still be a bug in one of the trigger detectors in the prerelease Vivado project archive. https://digilent.com/reference/programmable-logic/eclypse-z7/demos/ddr-streaming Thanks, Arthur
  19. Hi @Stanislav, welcome to the forum! ASCII character 13 in this case refers to the carriage return character '\r', rather than the string "13". The most significant digit should be transmitted first so that a straightforward UART passthrough to a serial console prints the data in human-readable form. Thanks, Arthur
  20. The red question mark means that Vivado can't locate the modules in the project's source files. If files containing a module can be found, the filename is typically listed in parentheses next to the module name, if they can't, they get this icon. You may need to add the source files containing the modules to your IP packager project, both in the sources -> design sources view, and to the component XML file's file groups page. The missing modules could also be placed in the same source file as your AXI peripheral, though this isn't usually recommended (one module per file is a common style). IPs' generated files are split out into their own source sets in the base Vivado project, so you shouldn't need to worry about duplicate names for files or modules. Thanks, Arthur
  21. Passing on this feedback to hopefully start another internal conversation on the topic. Thanks.
  22. artvvb

    Zybo Z7-20

    Hi @chiron40k There are a fair number of materials around on how to select the resistors. This post looks at the specific circuit on the Pmod VGA: https://electronics.stackexchange.com/questions/473370/is-this-how-a-r-2r-dac-for-vga-should-work. This project also looks comprehensive for a 4-bit DAC: https://svenssonjoel.github.io/pages/zynqberry-vga/index.html I'm not certain, but suspect that the buffer is there to isolate the DAC circuitry from any resistors that might be in series with the Pmod outputs. The Zybo's "High Speed" Pmod ports don't have these resistors. Thanks, Arthur
  23. Hi @JacksonR, The low level filter example for the Eclypse provides location constraints that should work for your purposes, in addition to implementing necessary controllers that set up the Zmods. https://digilent.com/reference/programmable-logic/eclypse-z7/demos/low-level-low-pass-filter Thanks, Arthur
  24. The JTAG interface is used to debug Microblaze systems with a Miicroblaze Debug Module (MDM) connected to the JTAG pins, however this capability is somewhat cooked into the tools. It might be possible to adapt the MDM debug interface to access your RISC-V processor if you can get it into a block design environment. Might also be possible to directly connect the JTAG interface, if the processor supports that, Digilent doesn't include the JTAG pins in master XDC files, but the locations may be fixed and BSCAN primitives might be usable to access them (I only have a cursory knowledge of this area). This is complicated by the fact that Digilent has made the business decision not to share the JTAG circuitry portion of our designs, and this is one of the areas affected by that. The same software used for debugging via the Olimex debugger or HS3 also doesn't necessarily support the on-board programming circuitry. Various other JTAG programmers that can be connected to Pmod ports could also work. Digilent also manufactures and sells some JTAG programmer components (like the JTAG HS3, which one of my colleagues indicated is also compatible with OpenOCD) that might fit the bill. Apologies, Arthur
  25. Hi, @zzzhhh, Unfortunately, that's the only Risc-V tutorial we've run through and tested internally. There are some other projects out there using the Arty A7, but from what I can see, most still require some form of additional kit to program the CPU once its loaded onto the board, similar to that Olimex programmer. Thanks, Arthur
×
×
  • Create New...