Jump to content

Viktor Nikolov

Members
  • Posts

    32
  • Joined

  • Last visited

Everything posted by Viktor Nikolov

  1. You can try a sample project for Zybo Z7-20, which I published here. This project is a demonstration of my port of ILI9488 TFT SPI display library to Xilinx SoC. Nevertheless, for the purpose of your test, you can run it without the display attached just to see if you can start debugging the code.
  2. I wouldn't do it differently. Just to make sure: You have selected the jumper JP5 for the JTAG boot, right? I have the Zybo Z7020 board and Vivado & Vitis 2023.2 installed. If you share here your Vivado and Vitis projects, I will try to run them on my board.
  3. I can offer a test project I recently created to test single-ended XADC with DMA. See the attached Vivado 2023.1 HW project and export of the Vitis 2023.1 workspace. The project is for Cora Z7-7S, but it can be easily re-generated for Arty-Z7 (the constraints file may need a modification, though). I first created the HW design following the Vivado design part of this tutorial: Signal Processing with XADC and PYNQ - Hackster.io However, this tutorial covers only differential XADC input, so it took some trial and error to get it to work with single-ended input. If I remember well, I did the following steps: In the XADC Wizard IP configuration, I set Startup Channel Selection to Single Channel. On the Single Channel tab, I then selected "VAUXP1 VPAUXN1". And I unchecked the "Bipolar" check box to set unipolar (single-ended) mode. Signal Vaux1 appeared on the XADC Wizard. I right-clicked it and selected Make External. This created the input signal Vaux1_0 in the diagram, connected to Vaux1 on the XADC Wizard. I then uncommented the following lines in the Cora-Z7-7S-Master.xdc: set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { Vaux1_0_v_p }]; #IO_L3P_T0_DQS_AD1P_35 Sch=ck_an_p[0] set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { Vaux1_0_v_n }]; #IO_L3N_T0_DQS_AD1N_35 Sch=ck_an_n[0] With that, I got no errors for the Incompatible Pair of IO Standards. Edit: The constraints look like they define a differential signal; however, on Cora Z7, VAUX1_N is connected to GND, and VAUX1_P is connected to the board pin labeled A0, as explained in the reference manual. XDAC_DMA_test_hw.zip vitis_export_archive.ide.zip
  4. If anybody is interested: When the width of the AXI Stream going into AXI DMA IP is reduced to 16-bit, the AXI DMA handles up to 33,554,431 data samples in a single call to XAxiDma_SimpleTransfer(). I tested this using the attached Vivado 2023.1 HW project and the Vitis 2023.1 workplace exported as an attachment as well. The HW project is for Cora Z7-7S. I implemented a very simple 16-bit AXI Stream generator in Verilog (see stream_generator.v). In my test, it generated an AXI Stream at the data rate of 10 Msps, which means the whole DMA transfer takes 3.36 seconds. Generator_DMA_test_hw.zip vitis_export_archive.ide.zip main.cpp
  5. It was all about Data Cache invalidation calls! In the main.c attached, I demonstrate the successful transfer of 16,777,215 32bit words (==64 MB) as a single packet, which is the largest possible DMA transfer by the AXI DMA IP (because the max. width of Buffer Length Register is 26bit). This main.c is intended for the Vitis 2023.1 workspace @artvvb shared in the previous post. First, I fixed in the code the bug Arthur mentioned on 24 April 2024: Data Cache invalidation calls have to be made with length RECV_BUFFER_SIZE * sizeof(u32). After this fix, I saw the same behavior as Arthur. The last 5 values in the received buffer were zeroes. Edit: This happens for DMA transfers of all lengths (I tested it down to 1,000) when RECV_BUFFER_SIZE==words_per_packet. The Xil_DCacheFlushRange() and Xil_DCacheInvalidateRange() apparently "forget" to work on the last 5 words of the memory range. Then I added an additional 16 bytes to the data length passed to the Data Cache functions in the function ReceiveData(): Xil_DCacheFlushRange( buf_addr, RECV_BUFFER_SIZE * sizeof(u32) + 16 ); ... Xil_DCacheInvalidateRange( buf_addr, RECV_BUFFER_SIZE * sizeof(u32) + 16 ); That did the trick. With the cache invalidated with an extra 16 bytes, the DMA transfer works as documented. Edit: This seems to be an undocumented feature of Xil_DCacheFlushRange() and Xil_DCacheInvalidateRange(). When I read comments in the source code xil_cache.c, I get impression that the problem is caused by end of the buffer not being aligned with cache line. This forum post from @asmi confirms it. main.c
  6. Do you mean that you didn't see any output on a terminal connected to the appropriate COM port? Have you tried debugging the program? If you are able to step over commands in the program, then the PS works, and the board is not kaput. Occasionally, I have problems seeing UART output from PS programs on my Windows 11. It's usually an intermittent problem and I wasn't able to pinpoint the root cause. Try PuTTY. For me, it's usually the most reliable terminal app.
  7. I did the test with recv_buffer able to hold up to 4M words (still way below the theoretical limit of the DMA 26-bit max.). When I tried a single packet of words_per_packet==2,000,000 , only the first 1,805,843 words were transferred correctly. Then 16,248 zeroes followed, and then the correct values continued (although I did not check the very end of the 2M buffer; it's possible it was corrupted the way you experienced). I was surprised to see the very same behavior with packets==2, words_per_packet==1,000,000 , and with packets==4, words_per_packet==500,000. With packets==1, words_per_packet==1,805,843 , everything was transferred correctly. I did this test as part of my research for a project in which I want to try sampling a long series of data from Zynq 1 Msps XDAC. It seems, 1.8 seconds is the limit when using Xilinx AXI DMA IP.
  8. You can use the output of XADC Wizard IP in the PL when you enable the "Enable AXI4Stream" option. Recently, I created HW design following this tutorial: Signal Processing with XADC and PYNQ - Hackster.io (I used only the HW design from that tutorial.) The XADC Wizard IP can output measurement data as an AXI Stream, which is a pretty simple protocol. In the HW design I mention here, the AXI stream is fed into the AXI-Stream Subset Converter IP (to divide the stream into chunks of 128 records by setting the tlast signal) and then into AXI DMA IP to load it into memory accessible by Zynq ARM core. Nevertheless, you can process the AXI Stream coming from the XADC Wizard IP using any PL logic you want. I have attached the PS code I used in my experiment. It doesn't communicate with the XADC Wizard IP in any way. It only calls routines working with the AXI DMA IP. The "magic" of getting data into AXI DMA IP happens solely on the PL level. main.c
  9. My understanding is that you need to use the XADC Wizard IP to access the ADC of the Zynq. Digilent provides Cora Z7 XADC Demo project. I used it recently, and it worked pretty well. I opened the 2021.1 version available for download in Vivado 2023.1 and was able to upgrade it and generate outputs without issues.
  10. I tried HW design and SW code from @artvvb (big thanks, Arthur, for both!) in Vivado and Vitis 2023.1 I was able to successfully transfer by the DMA exactly 1,805,843 words (i.e., 6.89 MB of data). After the 1,805,843rd word follows 16,248 zeroes, and then the correct values continue. The strange thing is that I observed the same behavior even when trying to split data transfer to multiple calls of XAxiDma_SimpleTransfer(). E.g., setting in the main() variable words_per_packet=500000 and packets=4. Calling XAxiDma_SimpleTransfer() once or multiple times always correctly transfers only 1,805,843 words. I can only speculate that this is a bug in AXI DMA IP.
  11. I'm not sure I understand. When I download the https://github.com/Digilent/digilent-xdc/archive/master.zip and uncompressed it to a folder on my computer, it does contain the file Nexys-A7-100T-Master.xdc . You need to add this single file as constraints file to you HW project in Vitis.
  12. I'm afraid you missed a step in the tutorial to rename CLK100MHZ to sys_clk_i in the constraints file (as shown on this picture from the tutorial). Names of ports in the constraints file and in the diagram must match. The error about conflicting voltages is probably caused by an issue I described in an article here. Add BUFG buffer between sys_clk_i and MIG.sys_clk_i, that should solve the problem (you can find the guidance in the article). Using DDR memory (i.e., the MIG) with MicroBlaze is an advanced HW design. For the first proof of concept I suggest that you use the MicroBlaze only with the block memory within the FPGA itself. It makes the HW design much more simple. You can add the DDR at later stage of HW design evolution.
  13. Good start for beginners is this guide provided by Digilent. It explains, among other things, how to create constraints file and how to get constraints file template for the board you are using.
  14. I suggest you share the content of your Nexys-A7-100-Master.xdc file and a screenshot of your diagram. That would help the audience of this forum to understand possible sources of critical warnings and errors.
  15. My first guess is that you don't have a constraints file (.xdc) defined in your HW design. Or you do, but you do not set IOSTANDARD attribute for the ports.
  16. The Arty A7 board file comes with the configuration for MIG. For instructions on setting up the MIG on Arty A7, you can refer to the first chapter of this tutorial. The tutorial is focused on MicroBlaze; nevertheless, setting up the MIG is the same for both MicroBlaze and PL logic.
  17. Just to add for clarity: You configured UART 1 to use MIO pins 8 and 9. However, almost all MIO pins are connected to some peripherals on the Arty Z7 board itself (e.g., flash, Ethernet). See the table in this chapter of the Reference Manual and check what MIO pins 8 and 9 are connected to. According to that table, UART 0 has to be configured on MIO pins 14 and 15! If you want to use UART 1, you need to set it to use EMIO. Then, it would appear as a signal on the Zynq IP and could be routed to I/O ports
  18. What is your motivation for enabling UART1? The Arty Z7 reference manual says that USB-UART bridge is to be used with UART 0. It is wired to UART 0 Zynq IC pins. How do your Board Support Package (BSP) settings look like in Vitis? I attached a screenshot of the BSP settings of a functional Zynq project. stdin and stdout need to be configured to UART 0 because your HW design doesn't expose UART 1 pins to PL and output ports, and thus, you can't access UART 1 in any way. Viktor
  19. I think you need to wait one cycle between the busy signal going down and you setting ready_2 high. I see in the source code of uart_tx that it reacts to i_Tx_DV (i.e., ready_2) going high only when uart_tx is in the state s_IDLE. However, after setting o_Tx_Active low, uart_tx waits one cycle before going to state s_IDLE. This is to keep o_Tx_Done high exactly for one cycle. However, during this one cycle, you advance to the next state and set ready_2 to low. So, the uart_tx doesn't catch it. I would introduce an intermediate state between the bytes, waiting for o_Tx_Done to go high. Viktor
  20. If this is of any help: On my Windows 11 I can normally use Cora Z7-07S in both Vivado and Vitis 2023.1. Windows shows that a driver from FTDI is being used. Have you tried to install a driver published here?: https://ftdichip.com/drivers/vcp-drivers/ Viktor
  21. Hi! In a project of mine, I want to use this 3.5″ 480x320 TFT SPI display based on the ILI9488 display controller. I, therefore, ported the ILI9488 Arduino library for use on AMD Xilinx SoC and FPGA. The integral part was porting of the Adafruit_GFX library because the ILI9488 library is based on it. I removed all Arduino-specific code, optimized SPI writes for the capabilities of Xilinx SPI libraries, and made other modifications. I published the library and sample projects on the GitHub repository. You can see the capabilities of the library in this video. I tested the library on AMD Xilinx Zynq-7000 SoC and Artix-7 FPGA (running on MicroBlaze soft CPU). The repository contains sample projects that run on Digilent boards Zybo Z7, Arty A7 and Cmod A7. I also provided a detailed step-by-step tutorial on how to use the display on the Zynq board Cora Z7. The library supports both Zynq Processing System SPI and AXI Quad SPI IP. The library also supports both Zynq Processing System EMIO GPIO and AXI GPIO IP. Different kinds of SPI and GPIO can be combined (e.g., you can use AXI SPI with PS GPIO and vice versa). All four combinations are supported by the library. Three out of four combinations are showcased by the sample projects in the repository. I tested the ILI9488 library with a standalone application running on ARM core or MicroBlaze. I believe it should also work on a PetaLinux app. Viktor
  22. Sorry, my bad. I thought that you were using PS SPI, but you are using an AXI Quad SPI from PS. 🙂 @artvvb is of course right. The ratio is for the ext_spi_clk. In the ILI9488 AXI SPI sample project, I needed to have a 20 MHz SPI clock for the display. Therefore, I feed AXI SPI IP ext_spi_clk input by 40 MHz from the clocking wizard. The Frequency Ratio on the AXI SPI IP is set to 2. Rest is clocked by 100 MHz from the FCLK_CLK0 output of Zynq. Viktor
  23. I can offer you two sample projects of mine for inspiration. The first one is a demo of using 3.5″ TFT SPI Module ILI9488 with Zybo Z7. The display is connected to PS via PS SPI. I guess the PS SPI initialization sequence may be interesting for you; see here. The second one showcases the same display, but this time, it's controlled via AXI SPI by a code running in PS. Both sample projects include a HW design in Vivado 2023.1 and a workspace for Vitis 2023.1 The projects are part of the repository where I publish my port of Arduino ILI9488 library to Xilinx SoC and FPGA. I need to finish some readme files, but the library and examples are ready and functional. Viktor
  24. I do not think so. FCLK_CLKx are the output clocks from Zynq for use in PL. The SPI frequency in your case is set to default 166.67 MHz, as seen in IO Peripheral Clocks. If you set in your app the ratio by this call: XSpiPs_SetClkPrescaler(&SpiInstance, XSPIPS_CLK_PRESCALE_16); The SPI CLK frequency will be 166.67 / 16 = 10.42 MHz. Viktor
  25. Hi! I don't have Nexys Video board, but let me guide you through the documentation and Nexys Video .xdc. 100 MHz clock We need a pin with 100 MHz input system clock. Nexys Video Reference Manual tells us that "the board includes a single 100 MHz crystal oscillator connected to pin R4". The .xdc contains this definition at the very top (I uncommented the relevant lines): ## Clock Signal set_property -dict { PACKAGE_PIN R4 IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L13P_T2_MRCC_34 Sch=sysclk create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk] So the "clk" is your 100 MHz input clock pin. You can rename "clk" to "CLK100MHZ" in the .xdc. Or rename "CLK100MHZ" to "clk" in the block diagram. Do it per your taste. Just make sure that the name of the pin in .xdc and in the diagram are the same. Reset pin Information about a reset button is a bit hidden in the Basic I/O section of the reference manual. It is the button BTN6 connected to FPGA pin G4. It provides high signal when not pressed. So we must look into Buttons section of the .xdc (I uncommented the relevant line): ## Buttons #set_property -dict { PACKAGE_PIN B22 IOSTANDARD LVCMOS12 } [get_ports { btnc }]; #IO_L20N_T3_16 Sch=btnc #set_property -dict { PACKAGE_PIN D22 IOSTANDARD LVCMOS12 } [get_ports { btnd }]; #IO_L22N_T3_16 Sch=btnd #set_property -dict { PACKAGE_PIN C22 IOSTANDARD LVCMOS12 } [get_ports { btnl }]; #IO_L20P_T3_16 Sch=btnl #set_property -dict { PACKAGE_PIN D14 IOSTANDARD LVCMOS12 } [get_ports { btnr }]; #IO_L6P_T0_16 Sch=btnr #set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS12 } [get_ports { btnu }]; #IO_0_16 Sch=btnu set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS15 } [get_ports { cpu_resetn }]; #IO_L12N_T1_MRCC_35 Sch=cpu_resetn I suggest that you rename "ck_rst" in the block diagram to "cpu_resetn". The pin name used in Nexys Video .xdc is more explanatory than the one from Arty A7 .xdc used in the tutorial. The output GPIO pin In my tutorial I use a single GPIO pin ck_a0 (i.e., the pin named A0 on the Arty A7) for the purpose of measuring memory read performance in the app provided in the tutorial's repository. An oscilloscope is supposed to be connected to this pin, see detailed explanation here. I guess you are creating your design for something more interesting than just a single GPIO pin. 🙂 Nevertheless, if you want to replicate my design, you can select just any available output pin on the Nexys Video. I would select pin 1 on the PMOD JA. This is because PMOD JA is protected with 200 Ohm resistors against "human interaction". See details here. You enable PMOD JA pin 1 by uncommenting the following line in the .xdc (and have the same pin name in the block diagram): ## Pmod header JA set_property -dict { PACKAGE_PIN AB22 IOSTANDARD LVCMOS33 } [get_ports { ja[0] }]; #IO_L10N_T1_D15_14 Sch=ja[1] Since you probably want to use the pin as scalar, I would change "ja[0]" to "ja_1" as follows: set_property -dict { PACKAGE_PIN AB22 IOSTANDARD LVCMOS33 } [get_ports { ja_1 }]; #IO_L10N_T1_D15_14 Sch=ja[1] Viktor
×
×
  • Create New...