Jump to content

artvvb

Technical Forum Moderator
  • Posts

    1,056
  • Joined

  • Last visited

Everything posted by artvvb

  1. There are various potential things to troubleshoot for this: Does the power good indicator LED come on when it is powered up? Please try another USB cable in case your cable is not capable of transferring data. Please confirm whether USB drivers are installed on your system - there is a checkbox in the Vivado installer that can easily be missed. If you are using a Windows system, in the Device Manager, your board should show up as several USB serial converters and a COM port (see here: https://forum.digilent.com/topic/21713-brand-new-basys-3-user-cant-get-vivado-to-see-it/#comment-62685). You could also install Adept Runtime to quickly reinstall the drivers: https://digilent.com/reference/software/adept/start. Thanks, Arthur
  2. For some additional reading, UG480 (the XADC user guide) talks about the dedicated interface between PS and XADC: https://docs.amd.com/r/en-US/ug480_7Series_XADC/Zynq-7000-SoC-Processing-System-PS-to-XADC-Dedicated-Interface. As does the Zynq technical reference manual: https://docs.amd.com/r/en-US/ug585-zynq-7000-SoC-TRM/Control-Interfaces. The two control interfaces described here are the two pieces of hardware underlying the two drivers. XSysMon is used to control XADC when XADC is instantiated in PL. XAdcPs must be used when an XADC isn't instantiated and has a slightly different hardware interface, reflected by the difference in drivers. There are likely various tradeoffs for which interface to use - choosing whether to "waste" FPGA resources or to disallow hardware in PL from using alarm signals comes to mind - but they're likely all pretty irrelevant for just getting the thing working. This is all to say, if you have an XADC instantiated in the design, you should be able to run the code I posted previously as-is.
  3. In case I haven't mentioned, I'm working in Vitis 2023.1. XAdcPs_GetStatus does not exist in that API. XSysMon_GetStatus is defined in xsysmon.h and the mask macros are defined in xsysmon_hw.h. In general, if you have the code loaded into the IDE and the macro or function exists in scope, you can control-click on it to find declaration locations. I think this just prevents reading the same sample twice if the software is moving fast. Removing it works fine for me.
  4. I'll need to check out the XAdcPs API. If you have an XADC instantiated in your block design, you ought to be able to use the XSysMon drivers by directly copying over the posted code. Guessing, but I think that XAdcPs represents direct PS access to the XADC core, while XSysMon is only pulled in when an XADC is included in block design. I'm not sure what the differences between the APIs are, or if the PS gets a different level of access if the XADC isn't hung off of the AXI bus. Given the existence of the XAdcPs drivers, it seems that it should be possible to use XADC without instantiating the IP - which might make XSysMon completely redundant for Zynq parts - but I'll need to try it out.
  5. Please try switching the board into JTAG boot mode by moving jumper JP5 and power cycling it.
  6. I suspect that the transfer function defined by XSysMon_RawToVoltage is not accurate for differential aux channels. The following comes from UG480 (https://docs.amd.com/r/en-US/ug480_7Series_XADC/ADC-Transfer-Functions), when it describes the bipolar mode transfer function. Whereas the power supply transfer function is "ADC Code / 4096 * 3V". I think this means that the XSysMon_RawToVoltage macro ("((((float)(AdcData))* (3.0f))/65536.0f)") lines up with the supply conversion, not the aux input conversion, which doesn't seem to be defined in the drivers. The following is working cleanly for me: #include "xsysmon.h" #include "xparameters.h" #include "sleep.h" #include "stdio.h" #include "xil_types.h" #define XADC_DEVICE_ID XPAR_XADC_WIZ_0_DEVICE_ID typedef struct ChannelInfo { u8 Channel; u32 Mask; char *Name; u8 IsDiff; // 0 or 1 } ChannelInfo; #define NUMBER_OF_CHANNELS 4 ChannelInfo Channels[NUMBER_OF_CHANNELS] = { {XSM_SEQ_CH_AUX_SHIFT + 14, XSM_SEQ_CH_AUX14, "AUX14", 1}, {XSM_SEQ_CH_AUX_SHIFT + 7, XSM_SEQ_CH_AUX07, "AUX07", 1}, {XSM_SEQ_CH_AUX_SHIFT + 15, XSM_SEQ_CH_AUX15, "AUX15", 1}, {XSM_SEQ_CH_AUX_SHIFT + 6, XSM_SEQ_CH_AUX06, "AUX06", 1} }; void Xadc_Init(XSysMon *InstancePtr, u32 DeviceId) { XSysMon_Config *ConfigPtr; u32 DiffChannels, EnabledChannels; u8 Index; ConfigPtr = XSysMon_LookupConfig(DeviceId); XSysMon_CfgInitialize(InstancePtr, ConfigPtr, ConfigPtr->BaseAddress); DiffChannels = 0; EnabledChannels = 0; for (Index = 0; Index < NUMBER_OF_CHANNELS; Index++) { EnabledChannels |= Channels[Index].Mask; if (Channels[Index].IsDiff) { DiffChannels |= Channels[Index].Mask; } } // Disable the Channel Sequencer before configuring the Sequence registers. XSysMon_SetSequencerMode(InstancePtr, XSM_SEQ_MODE_SAFE); // Disable all alarms XSysMon_SetAlarmEnables(InstancePtr, 0x0); // Set averaging for all channels to 16 samples XSysMon_SetAvg(InstancePtr, XSM_AVG_16_SAMPLES); // Set differential input mode for appropriate channels XSysMon_SetSeqInputMode(InstancePtr, DiffChannels); // Set 6ADCCLK acquisition time in all channels XSysMon_SetSeqAcqTime(InstancePtr, EnabledChannels); // Disable averaging in all channels XSysMon_SetSeqAvgEnables(InstancePtr, EnabledChannels); // Enable all channels XSysMon_SetSeqChEnables(InstancePtr, EnabledChannels); // Set the ADCCLK frequency equal to 1/32 of System clock XSysMon_SetAdcClkDivisor(InstancePtr, 32); // Enable Calibration XSysMon_SetCalibEnables(InstancePtr, XSM_CFR1_CAL_PS_GAIN_OFFSET_MASK | XSM_CFR1_CAL_ADC_GAIN_OFFSET_MASK); // Enable the Channel Sequencer in continuous sequencer cycling mode XSysMon_SetSequencerMode(InstancePtr, XSM_SEQ_MODE_CONTINPASS); } void Xadc_ReadData (XSysMon *InstancePtr) { u8 Index; s16 RawData; float VoltageData; printf("Waiting for EOS...\r\n"); // Clear the Status XSysMon_GetStatus(InstancePtr); // Wait until the End of Sequence occurs while ((XSysMon_GetStatus(InstancePtr) & XSM_SR_EOS_MASK) != XSM_SR_EOS_MASK); printf("Capturing XADC Data...\r\n"); for (Index = 0; Index < NUMBER_OF_CHANNELS; Index++) { RawData = XSysMon_GetAdcData(InstancePtr, Channels[Index].Channel); VoltageData = ((float)(RawData) * (1.0f) / 65536.0f); printf("Capturing Data for Channel %s: ", Channels[Index].Name); printf("%04hx = ", RawData); printf("%.3fV\r\n", VoltageData); } } int main () { XSysMon Xadc; Xadc_Init(&Xadc, XADC_DEVICE_ID); printf("Zybo Z7 XADC Initialized!\r\n"); while(1) { Xadc_ReadData(&Xadc); sleep(1); } } Results, with VAUX14P at 25 mV, VAUX14N at 100 mV, and the rest grounded:
  7. Some progress, I can see changing values printed when running the attached code (a heavily modified version of the Cora XADC source), but am still figuring out how to interpret raw data readings and what the register configuration settings applied in the init function might need to be. (Edited to remove code after posting a followup)
  8. Hi @AaronNowack Apologies for the delay. We reached out to the engineer who designed the front-end circuitry on both Zmods about your question. Their response is below: Hope this helps, Arthur
  9. Hi DGISTKSJ, No, the MIG cannot be used to interface with DDR on the Eclypse, as the DDR is connected to the Zynq PS. However, you ought to be able to access DDR memory through the Zynq PS's AXI slave ports, which can be enabled in the PS configuration, as below. It isn't trivial to implement a custom full AXI master interface to control these ports, so we would normally recommend using IP like Xilinx's AXI DMA. Thanks, Arthur
  10. I have not. There are some AMD resources on simulating the Zynq PS, but I'm not sure if they cover external HW like Ethernet or if they're primarily for simulating software in conjunction with FPGA gateware. I'm sure "It works on my machine" isn't the most helpful, but I was able to download the 2022.1 Vitis archive for the Zybo Z7-20 variant of the DMA Audio demo, open it in 2023.1, and run it in hardware. Which download did you use?
  11. What raw data value does 0.790 V correspond to? If it's all zeros or some other notable bit pattern then something isn't being initialized. It's been quite a while since I worked on the Cora demo and I don't recall if the XADC device actually needs to be initialized in software, but that demo does it here: https://github.com/Digilent/Cora-Z7-SW/blob/d35d836848fed00dec917ff0784f6232862220f5/src/Cora-Z7-10-XADC_SW/src/main.c#L58. It also uses an "xsysmon" driver instead of xadcps, which might be a renamed version of the same drivers... Building out a project for Zybo to try it out.
  12. artvvb

    Zynq PWM output issue.

    Hey CEEJ38, This sounds like an electrical concern. The Zedboard's Pmod ports use 3.3V logic and the bank voltage cannot be changed (section 2.9.2 of the user guide covers it in brief, and DS187 covers it in extreme detail). You might look into using a level shifter circuit. Thanks, Arthur
  13. Hey, sorry for the delay. Unfortunately, whenever I've seen invalid xpfm files, I've needed to recreate a workspace... Speculating, but it's possible that copying or moving a workspace directory from one place on your system to another could cause it. It's great that the hardware project is working! Thanks, Arthur
  14. Another potential way to fix the issues would be to make sure that your source code uses the same instance of the XScuGic handler as the zmodlib sources. In zmodlib, this is declared in zmodlib/Zmod/zmod.cpp and is externed into other files where it's relevant. Options are to either modify the zmodlib sources so you can pass in a handler to an instance that you declare in code outside of zmodlib, or use the API defined in intc.h when setting up handlers for the ethernet and timer sources. I'm not sure of the details of either option. @Xband I realized you weren't necessarily just asking about the base addresses. Register offsets that specify where a particular register is located relative to a base address are commonly defined in both peripheral drivers and in IP documentation. The section of the AXI DMA user guide I linked in the previous comment is an example of the latter. As an example of where you might find register offsets in drivers, xaxidma_hw.h (found in BSP sources or by clicking through various other AXI DMA driver files) includes them for the DMA core. That receive status register offset is defined by the two following lines: #define XAXIDMA_RX_OFFSET 0x00000030 /**< RX channel registers base * offset */ #define XAXIDMA_SR_OFFSET 0x00000004 /**< Status */
  15. Regarding the approach of commenting out the interrupt functionality, as an experiment, I cloned a fresh instance of the Zmod Scope baremetal demo (here: https://digilent.com/reference/programmable-logic/eclypse-z7/demos/zmod-scope), and ran it in 2019.1 with and without the contents of the interrupt initialization functions. It worked fine with the interrupt functions, but when the sources were commented out, there was no response. Debugging the demo, it seems that the DMA API doesn't expose the polled version of the fnIsDMATransferComplete function, and the system stalls while waiting for data to be transferred from PL. To fix this, I added the second line below to zmodlib/Zmod/dma.h: uint8_t fnIsDMATransferComplete(uintptr_t addr); uint8_t fnIsDMATransferCompletePoll(uintptr_t addr); Modified the following line in zmodlib/ZmodADC1410/zmodadc1410.cpp's ZMODADC1410::acquirePolling function: // Wait for DMA to Complete transfer while(!isDMATransferCompletePoll()) {} And added the following function to zmodlib/Zmod/zmod.cpp and the corresponding header: /** * Check if the DMA transfer previously started has completed. * * @return true if the DMA transfer completed, false if it is still running */ bool ZMOD::isDMATransferCompletePoll() { return fnIsDMATransferCompletePoll(dmaAddr); } The zmodlib/Zmod/zmod.h header: bool isDMATransferComplete(); bool isDMATransferCompletePoll(); I also needed to adjust the fnIsDMATransferCompletePoll function in zmodlib/Zmod/baremetal/dma.c as follows, since the status register for PL->PS transfer is at address 0x34 instead of 4 (https://docs.amd.com/r/en-US/pg021_axi_dma/S2MM_DMASR-S2MM-DMA-Status-Register-Offset-34h): uint8_t fnIsDMATransferCompletePoll(uintptr_t addr) { DMAEnv *dmaEnv = (DMAEnv *)addr; if (!dmaEnv) return 0; uint32_t offset = (dmaEnv->direction == DMA_DIRECTION_RX) ? 0x34 : 0x04; uint8_t val = readDMAReg(dmaEnv->base_addr, offset); return (val & 2); }
  16. Hi SillyInventor, I've reached out internally about your request and will let you know when I hear back. Thanks, Arthur
  17. Mamatchai, I'll need a bit of time to reproduce and double-check whether there are other important interrupts. Addresses for PL IP are different per project, they're assigned in the address editor in Vivado. You can either let Vivado automatically assign them (the default behavior) or manually set them. Either way, the address map is exported with the XSA file after generating a bitstream, along with various additional information about the hardware design (this is also how IP configuration information makes its way into the files used by *_LookupConfig functions). Including the xparameters file in your code and using the macros it defines is recommended in case the peripheral addresses are changed in Vivado.
  18. I haven't benchmarked the TCP echo server example, but this sounds plausible to implement. Packets for the echo server unmodified might be 1 byte, or however large the software creating the packets makes them (a serial terminal you're typing into seems like it would likely send one byte at a time), but the raw ethernet packets max out only a little smaller than 1500 bytes. This blog post also extends the echo server example to send more than a byte at a time, using a python script on the PC side. Once data is received in the PS & DDR, you could use AXI DMA or a similar mechanism to move it to PL. Note that AXI DMA is an IP that is added to a block design, and not the hard DMAs built into the Zynq PS (which I believe are much less performant, could be wrong). There are various demo projects around, you could check out the Zybo's DMA Audio demo, which uses DMA to move audio data between DDR (where PS can access it) and an I2S interface. I've also written about DMA a fair amount on the forum, this thread being one example: There was another user building a similar system in this thread:
  19. AXI GPIO is intended for much slower software access to I/Os. You really do need a dedicated hardware design capable of initializing your ADC and properly handling the data coming in as defined by the ADC and FPGA datasheets.
  20. Yep, good catch. It's four differential inputs. From the feature list in the Zybo Z7 reference manual: From the Zybo Z7 XADC Demo description: Note that the channel names in the table above correspond to the actual XADC channel numbers you should be using in the XADC settings. Channels 6, 7, 14, and 15 correspond to the Zybo's Pmod inputs. This configuration should also be seen in the sequencer settings for the Zybo XADC demo. The Zybo schematics (screenshot from page 11) also show that the analog input circuitry is the same as the Cora's differential analog inputs: The Cora manual's description of diff. inputs:
  21. 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.
  22. 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.
  23. Are you looking for DIgSILENT rather than Digilent? We are not associated with them and don't provide support for PowerFactory, but it looks like their support channels are described here: https://www.digsilent.de/en/support.html. Thanks, Arthur
  24. I'm not familiar with pandapower, which looks to be what you're trying to use. Is there any particular Digilent product you're trying to use with it?
  25. 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
×
×
  • Create New...