Leaderboard


Popular Content

Showing content with the highest reputation since 09/29/16 in all areas

  1. 3 points
    An FPGA can be a useful "swiss army knife", but all the nice features aren't easily accessible. Enter "LabToy": A batteries-included collection of utilities, just double-click and go. As the name implies, this isn't meant to compete against "real" test equipment. The main selling point is like a pocket knife - this fits into a shirt pocket and the power tools don't. And speaking of "selling points", it's free to use. So what do we have here: - Digital data: Shows the input state of all pins - Analog data: Readings from the two ADCs, up to about 700 ksps sustained (XADC "simultaneous sampling" mode, phase-accurate between channels) - Streaming data logger: Both analog and digital data can be written to a .vcd file, to be shown in gtkwave. There is no limit to the capture length. - Analog signal generator: 8 fully independent channels, sine, square wave, the usual suspects. Well, the DACs won't win any audiophile awards, but they are usable. - "Programmable" digital LED mode: Configurable pulse width to suppress short glitches, or edge detect with a built-in pulse generator to highlight them. - Analog LED mode: Shows the input value of the ADC in real time Some screenshots: 1k sine / cosine from DAC jumpered to ADC (in gtkwave) The digital signal is the generator's sync output that can be recorded as a digital input. Realtime display of the inputs. With pocket knives in mind ("this button will unlock the large blade, allowing it to be manually returned to its folded position") I decided to keep the screen uncluttered and put descriptions into tooltips. The large displays are the average voltage readings from the ADC. The smaller ones show the digital inputs in groups of four. Generator controls (frequency, minimum voltage, maximum voltage, phase). The voltage scaling is a bit unusual (typically there is "AC magnitude" and "DC offset") but I chose this approach because it shows clearly the limitations of the 0..3.3V output range. Most people will probably leave all this at the default values for a full-scale signal. Data capture Example: The output in gtkwave after I touched a jumper cable to the digital inputs on the DIL connector. +++ DO NOT USE THE +5V OUTPUT P24 FOR THIS KIND OF TEST +++ (3.3 V is available on the PMOD connector, bottom row) The red "undefined" marks flag the first input in an 8-bit group. In this example, they aren't too meaningful, but they can alert me to the fact that no data events have been observed yet. LED control The two numbers give the number of consecutive 1 or 0 samples (at 125 MHz) before a signal change is propagated to the LED. E.g. put 125 million there and it'll take one second after changing the input state for the LED to light / go dark. Those can be used interactively to study an unknown signal. "Level": no further processing ("level" mode and 1 / 1 sample counts is equivalent to directly connecting the LED to the physical input) "Edge" mode generates a brief pulse on signal changes, the LED is dark otherwise. "Invert" flips the input right next to the pin (0 becomes 1, black becomes white and man gets himself killed on the next zebra crossing -DA). How to get it: The file is attached: labToy0v1_beta.exe The installer unpacks a single .exe. Happy hacking! Requirements: Windows 64 bit (!) .NET 4.5 FTDI libraries CMOD A7 35 T (not 15 T). Warnings: Direct access to digital IO pins is an inherently dangerous activity. "PROVIDED WITHOUT WARRANTY OF ANY KIND" means Just That. And beware of the +5V pin. PS: If you try it, kindly let me know whether it works, or what goes wrong.
  2. 3 points
    A few reasons are... a - The introduction of logic hazards can cause glitches : https://en.wikipedia.org/wiki/Hazard_(logic) b - Routing of clocks is very complex - It is hard to ensure that the same clock edge appears all over the FPGA at almost exactly the same time. Sometimes this is achieved with 'slight of hand' (e.g. using a on-chip PLL to advance phase of the clock, so that by the time it reaches the edge of the chip is in back phase with the original signal). Low-skew paths also exist, but are restricted to small areas of the FPGA, and the clock has to be connected to the correct pin to be placed and routed correctly. c - FPGAs and their tools are designed to behave predictably under the "synchronous digital design" paradigm (something like https://hps.hs-regensburg.de/scm39115/homepage/education/courses/red/2_SynchronousDigitalCircuitDesignRules.pdf). If you work outside the paradigm you will be fighting against the tools and their assumptions. d - There is almost nothing that you are unable to code in an FPGA friendly way, but there are infinitely many ways to write FPGA-hostile code. If you want your FPGA to place nice with you, you have to play nice with it. So you can either add an RC filter to debounce you switch, or you can sample it using a reliable clock.
  3. 3 points
    D@n

    Just for fun: Frequency Resolution challenge

    Hello everybody! Since I was sharing this image with others, I thought I'd share it here at Digilent as well. The attached image shows the frequency response of several FFT windows, including the well-known rectangle and Hanning windows. The blue window is one I've put together, but haven't shared the FPGA source code used to implement it. I challenge anyone to do better. Oh, and one other comment ... all but the Hanning window can be used in an invertible FFT process. Dan
  4. 2 points
    Hi @Blake, I was struggling with the same problem. In Adam's project is mistake which result is an FMC-HDMI module is not recognizable by other devices. The reason for that is not sending EDID at all. The cause of this situation is wrong initialized EDID map. In Adams example EDID is initialized by: but the correct way is: the body of iic_write2 is from LK example: By the way, in LucasKandle example initialization is done in same way as in Adam's example so is the reason why it not worked in your case. I hope it will helps. If you want I will post my working code for a ZedBoard with FMC-HDMI when I clean it because at the moment is kind of messy.
  5. 2 points
    kwilber

    Pmod DA3 clocking

    It seems to me the AXI Quad SPI block is sending address + data. Looking at the .xci file again, I see C_SPI_MEM_ADDR_BITS set to 24 bits. So 24 bits of address and 16 bits of data would yield 40 bits.
  6. 2 points
    The warning you pasted is benign and simply means there are no ILAs present in your design. The real issue could be your clock. You should review the datasheet for the dvi2rgb.Table 1 in section 5 specifies RefClk is supposed to be 200Mhz. Also, your constraint should follow the recommendation in section 6.1 for a 720p design. Finally, @elodg gives some great troubleshooting information in this thread.
  7. 2 points
    Hi @akhilahmed, In the mentioned video tutorial, the leds are controlled using "xgpio.h" library but the application is standalone. If you want to use a linux based application you have to use linux drivers for controlling. In the current Petalinux build, which is used in SDSoC platform, UIO driver is the best approach. Steps: 1. Vivado project generation: - Extract .dsa archive from /path_to_sdsoc_platform/zybo_z7_20/hw/zybo_z7_20.dsa - Launch Vivado - In Tcl Console: cd /path_to_extracted_dsa/prj - In Tcl Console: source rebuild.tcl - In this point you should have the vivado project which is the hardware component of SDSoC platform. Open Block Design. Change to Address Editor Tab. Here you will find the address for axi_gpio_led IP: 0x4122_0000 2. Petalinux UIO driver: - Launch SDx - Import zybo-z7-20 SDSoC platform - Create a new SDx linux based project using a sample application (e.g. array_zero_copy) - Build the project - Copy the files from /Dubug/sd_card to SD card - Plug the SD card in Zybo Z7. Make sure that the JP5 is set in SD position. Turn on the baord - Use your favorite serial terminal to interact with the board (115200, 8 data bits, 2 stop bits, none parity) - cd to /sys/class/uio - if you run ls you will get something like: uio0 uio1 uio2 uio3 uio4 uio5 - Now you have to iterate through all these directories and to search for the above mentioned axi_gpio_led address: 0x4122_0000 - For example: cat uio0/maps/map0/addr will output: 0x41220000, which means that the axi_gpio_led can be accessed using linux uio driver through uio0 device. - Code: #include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <stdint.h> #include <unistd.h> #include <fcntl.h> #define UIO_MEM_SIZE 65536 #define UIO_LED_PATH "/dev/uio0" void UioWrite32(uint8_t *uioMem, unsigned int offset, uint32_t data) { *((uint32_t*) (uioMem+offset)) = data; } uint32_t UioRead32(uint8_t *uioMem, unsigned int offset) { return *((uint32_t*) (uioMem+offset)); } void led_count_down(uint8_t *ledMem) { uint8_t count = 0xF; uint8_t index = 0; for (index = 0; index < 5; index++) { UioWrite32(ledMem, 0, count); count = count >> 1; sleep(1); } } int main() { // Set Leds as output int led_fd = open(UIO_LED_PATH, O_RDWR); uint8_t *ledMem = (uint8_t *) mmap( 0, UIO_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, led_fd, (off_t)0); UioWrite32(ledMem, 4, 0x0); // Set all leds as output while(1) { // Start led count-down led_count_down(ledMem); } return 0; } - Build the project and copy the content of Debug/sd_card on SD sd_card - Power on the board and connect to it using a serial terminal - run the following commands: mount mmcblk0p1 /mnt cd /mnt ./project_name.elf - Result: A countdown should be displayed on leds.
  8. 2 points
    JColvin

    Arty A7 flash chip

    Hi @D@n, I believe the new part that is used in the Arty A7 boards (and other A7 boards) is now a Spansion S25FL128SAGMF100; based on old schematics, I believe this was added in Rev D of the Arty A7 (dated August 2017), though I do not know when that particular Rev was then released (or if it even was released) to the public. I confirmed that the Arty S7 also uses this part and I wouldn't be surprised if most of our other Artix 7 based boards use it now as well. I've requested that the chip name and images are updated in any appropriate tutorials and requested that the pdf version of the reference manual (updated wiki) is updated as well. Thanks, JColvin
  9. 2 points
    attila

    Math on FFT traces

    Hi @lab!fyi In the Network Analyzer extended option lets you use Wavegen channels at up to 20MHz and with external up to 50MHz. In the Spectrum Analyzer you can select frequency range up to 10MHz but with auto option lets you set Stop frequency up to 50MHz. Selecting the dB unit will let you specify custom reference, for dBm I think it should be 0.316V
  10. 2 points
    @hamster I was able to run your AXI Slave interface. It works great! It is now very easy to exchange information between PS and PL, and it even supports execute-in-place (e.g. I can put ARM instructions to register file and run PS CPU directly from it). I have some questions about your AXI Slave design: 1) AXI_a*size has no effect on INCR type of burst transactions, but according to AXI protocol: the increment value depends on the size of the transfer. You set it only for WRAP type, is it correct? Thus, burst size is always 0 for INCR type? 2) Do you know how PS initiates INCR burst type? A kind of memset/memcpy need to be used for that or an incrementing pointer will also work? 3) Where WRAP type is necessary? How to use PS to work in WRAP mode? You may also update your wiki page with following: 0) Create provided VHDL files 1) Create a block-diagram and add PS IP core to it 2) Apply configuration provided by your board's pre-settings; this will set all necessary initialization settings for PS (e.g. clock frequencies, DDR bindings, etc.) 3) Press auto-configure (or how it's called) ==> this will connect PS IP to DDR and to fixed IO 4) Add "External ports" to the diagram (create new AXI_CLK and AXI external ports) and connect them to PS ports 5) Generate VHDL wrapping code for this block diagram 6) Put generated system under axi_test_top by renaming it to axi_test_wrapper (default name is design_#_wrapper in my Vivado version) 7) This will auto-connect block-diagram external ports with axi_test_top 8 ) Add constrains file and rename/uncomment external ports where necessary 9) Generate bitstream 10) File->Export->Hardware and create .hwf file which contains PS configuration 11) Open Xilinx SDK and create a new project: select .hwf file as Hardware BSP for this project 12) Now, Xilinx SDK will auto-generate few .c and .h files which contain necessary PS initialization ==> clocks, IRQs, DDR, etc. 13) Add hello_world.c application to the project @hamster Thank you very much. I've learned a bunch of new things thanks to your help!
  11. 2 points
    mohammadhgh

    Zybo z7-20 Zynq Presets

    Hi @Mahesh, As @jpeyron said in the post marked as accepted solution, the Zynq processing system will be configured with the board presets when you first add the Zynq processing system IP core to the block design and run the block automation task from the green message that appears! Just remember to keep the Apply Board Preset option checked as shown in he picture. So this means if you are using the pre-built block design from the example project, a possible solution can be to remove the existing Zynq processing system block and adding a new one!
  12. 2 points
    xc6lx45

    Cmod A7 oscillator question

    PS: Reading the above post: I suggest you DO use the IP wizard, not calculate it manually. Pain does not equal gain.
  13. 2 points
    xc6lx45

    Vivado slowness reality check

    For comparison: My labToy project on CMOD A7 35 builds in 3:40 min (excluding clock IP, measured on my wristwatch by resetting synthesis, then "generate bitstream"). It's not a large project - about 20 % of DSP used and slices touched - but not trivial either. A hello-world project compiles in maybe 1 min, give or take some. But my desktop was built for the job (water-cooled i7 4930 @ 4.5G, 32G quad-channel RAM, M2 SSD). Most of this doesn't help with a one-LED design, but there are a number of things that will slow down the run considerably: - Use correct timing constraints: For example, a LED driven from logic clocked at 200 MHz can be very difficult to route (but at the 12 MHz crystal frequency it shouldn't matter much). A simple set_false_path -to [get_ports LED] makes it "don't-care". - Throw in extra registers where appropriate, especially between blocks (which tend to be physically separate). Most of the time, it does not matter whether the signal arrives one or two clock cycles late, and some spare registers will simplify implementation. This is especially useful for register rebalancing. - For the extra registers, it may make sense to use a "don't touch" attribute. E.g. in Verilog: (* DONT_TOUCH = "TRUE" *)reg [5:0] wa [1:NWRDELAY]; (* DONT_TOUCH = "TRUE" *)reg [17:0] wd [1:NWRDELAY]; (* DONT_TOUCH = "TRUE" *)reg we [1:NWRDELAY]; When I have multiple, parallel instances of a timing-critical block, the input registers are logically equivalent, get optimized away, and then P&R takes ages because timing is so difficult. The "don't touch" attribute" keeps them separate, possibly using a couple of FFs more than strictly necessary. - Removal of redundant logic can take a long time. For example, when I simulate pipelined DSP like the "labToy" generators I simply carry all data all the way through the pipeline, even though most of it isn't needed. Optimization will eventually remove it, but the cost is runtime. The LabToy example includes 8 instances each with a 6-lane 14-cycle 18-bit wide pipeline, and it adds minutes to the synthesis time if I don't remove the unused ends of delay chains in the source code. - Read and understand every warning, and read the timing report. "The compiler is my friend" For example, with PLL blocks it is easy to create duplicate clocks with the same frequency (one from the constraints file, one from the IP block). Timing analysis tries to (and will eventually) sort out all possible interactions, but it takes a lot of time and can create meaningless but difficult routing constraints. - Fix "critical warnings" related to timing. Even if common sense tells the design will work e.g. classroom demo with buttons, Vivado will waste a lot of time trying the impossible.
  14. 2 points
    I solved my ethernet problem and the specific connections to make it work. I didn't have I2C enabled on the Zynq7 customisation. so I also enabled I2C over EMIO. I think this hampered it's ability to communicate with the address chip I changed in the Zynq 7 processor MIO configuration - the ENET0 MDIO device is now MDIO pins MIO 52-53.
  15. 2 points
    @Shuvo Sarkar What exactly needs to be done depends on what you mean by "region of interest" and "binary mask". I will assume that you are trying to replace some area of what is being displayed on the screen with a rectangular image. A good starting point would be to take the input stream and output it with modifications. The DemoScaleFrame function in video_demo.c does this. The resolution scaling being done by this function also may or may not be desirable for your project. The Bilinear interpolation function implemented on line 473 of the original source is the primary point of interest here. The three variables required to tell what is being written to in the destination frame are the index, i, which can be used to determine the color channel being written to, and the destination coordinate variables xcoDest and ycoDest. A good starting point to be able to see changes being made would be to add extra code to black out a rectangular area of the screen. This can be accomplished by wrapping the destFrame[iDest] statement within an if statement, that either writes a zero to destFrame[iDest] or runs the bilinear interpolation of the source frame, depending on the coordinates of the target pixel in the destination frame. How you store, access, and process the binary mask (overlay image?) is a large topic that I would need more details to provide information on. Let us know if you have more questions. -Arthur
  16. 2 points
    attila

    Analog Discovery 2 vs Raspberry Pi 3

    FTDI USBs like AD, AD2, DD are not working with RPI model B (1,2,3) data packets/bytes are randomly lost. The EExplorer with different USB controller is working fine on these. All devices are working with other embeddeds: Zed, Zybo, BeagleBone… According reports AD is working with the original RPI model A and probably Zero because it has similar chipset/USB. The problem seems to be with FTDI or RPI B USB, library or hardware. You can find such comments regarding RPI problems with other devices too. Unfortunately we couldn't remediate this problem.
  17. 2 points
    @Sam_a Should be fixed this time. Thanks for your patience, Arthur
  18. 2 points
    Notarobot

    Zynq PL-PS Interrupt issue

    @artvvb The issue seems to solved after I've added the statement: XScuGic_SetPriorityTriggerType(IntcInstancePtr, INTC_INTERRUPT_ID,0x00, 0x3); Now the applications responds and counts interrupt sisgnals coming fro PL. Regards, N
  19. 2 points
    @dcc, If you actually want to set/read memory, you'll need to learn how to interact with a bus. I like to use a B4 pipelined wishbone bus. I find it very simple and easy to use. For example, you can find a very simple block RAM device here that interacts with a wishbone bus. (It would be even simpler if I wasn't keeping my high speed and low speed code in the same file ...) Xilinx has committed themselves to the AXI bus--a bus that requires the management of five separate data paths just to get right. If you want access to DDR3 SDRAM, you'll need to use Xilinx's memory interface generator (MIG) to build an interface for you. (I tried without MIG, made lots of progress, but ... after two months of full time work on it hadn't finished the task. It's a shame. The memory access delay would've been about half of what Xilinx's delay is.) Xilinx's MIG generates a DDR3 interface to a memory using an AXI controller. You can see how I interact with that AXI controller in my own Arty design here. Within that file, take a look at the mig_axis component and then roll your eyes with me at the quantity of wires and communications paths you need to handle just to read or write from memory. Yuck. That's why, in the same file, you'll find a wishbone to axi bridge, one I call wbm2axisp, or wishbone master to AXI slave pipelined. As a result, I can interact with that core using wishbone signals, such as i_wb_cyc to indicate that I am accessing the bus (needs to be high throughout the transaction), i_wb_stb to request a memory interaction (only needs to be high for one clock while o_wb_stall is low per request), i_wb_addr (specifying the address of my request, must be valid any time i_wb_stb is high), i_wb_we (specifies if I am reading or writing), i_wb_data (data to write, must be valid anytime i_wb_stb and i_wb_we are high), o_wb_ack (true any time a memory access completes), o_wb_stall (true if the memory isn't ready to accept a transaction), and o_wb_data (the data result of any read transaction). The number of wishbone signals are truly ... much less than that giant AXI bus. (10 signals, of which 4 have multiple bits associated with them.) Looking at the AXI bus, to interact with it you will need 35 signals, of which 23 have multiple bits. Take your pick. (By the way, going from an 8-bit data width to the 128 bit data width used by the DDR3 SDRAM is not nearly as hard as it sounds, if that's something you would be struggling with.) If you are trying to read/write from memory to support both an ADC and a DAC, you'll need a couple of things. One of them is a FIFO. You can see an example of a FIFO supporting a UART here. DDR3 memory speed can be unpredictable, and it can drop out suddenly for a refresh cycle while you are trying to interact with it. Worse, that MIG interface takes upwards of 24 clocks to complete a transaction. (If you pipeline your requests, only the first will take 24 clocks, the rest can take one clock. See the wishbone B4 spec for a discussion of this.) However, with a FIFO you can weather some of these problems without dropping samples, and even get on and off the memory bus faster. Second, you'll need an arbiter--something that decides of the two transactions you'd like to make, which of them actually gets access to the bus. You can find my own wishbone arbiter here. If you are wondering just how to get a wishbone transaction working, I have examples ranging from simple to complex. For example, here is a simple prefetch example that just reads a single value from memory (i.e., the next instruction for a CPU). Here's another, similar example, which reads two values from memory at a time. (When working with that SDRAM, the first can take 24 cycles per read, the second can do two reads in 25 clock cycles.) And, while we are at it, here's an example which reads 2^N values at once--but since it's got a cache within it, it ... tends to be more complicated. Another example would be the code I've used for building my own DMA. Take your pick. How deep would you like to dive into this? I could go on and on for a while with more examples ... Is this the sort of thing you are looking for? Let me know, and I can offer more, explain any of the above, or ... you tell me. Yours, Dan
  20. 2 points
    The trick is your code does not need to infer a block memory generator. It will actually need to explicitly implement the block memory generator INTERFACE. This is because the block memory generator is already being instantiated in the block diagram. You will need to design a state machine in VHDL that properly implements the interface. For a description of the signals (en, we, addr, etc.) you should refer to the block memory generator Product Guide. You can find the guide by double clicking the block memory generator IP and selecting Documentation in the upper left corner. The end goal will be to create a custom IP core that contains this custom VHDL. Since you do not have an AXI interface on your core, this should be pretty easy. I believe you can just create a new project that targets the ZYBO and has its top level ports be the desired ports on the IP block. Then I think you can run the Create and Package IP wizard from the tools menu to convert the project to an IP core so it can be inserted into you block diagram (which will be in a different vivado project). I'd recommend simulating your project before you convert it to an IP core to help make sure it is functioning as expected. BTW, you can just expand the BRAM_PORTB interface on the block memory generator IP core and manually connect each of the signals to your IP core if you have difficulty making you custom IP implement the BRAM interface. See the picture below for an example of what your end goal will be:
  21. 2 points
    @silverwolfman, I don't have my S6 on my desk to tell you how much time it took me to load the flash, but I do know I didn't use iMPACT. You can find my work here. In particular, the flash loader is called zipload, and depends upon the using the Digilent Adept utilities to load an initial configuration (generated from this toplevel file) into the flash. Dan P.S. I'll be redoing my work again soon, to prove that the updated ZipCPU can still fit (and work) on the device. You can see some of my update works in the 8-bit branch of the s6soc project, but ... although it builds, it hasn't been tested yet so ... it's still a work in progress.
  22. 2 points
    @Hassan Iqbal, Can I try to answer? Your solution will have two parts. The first part will feed the camera image constantly into memory. When you get the vertical sync to start again at the top of the page, you just reset your write memory pointer. The second part of your solution will read the image out of memory on your other clock. This will read out with the synchronization parameters you are trying to achieve. This way, if you write faster than you read, you'll quietly and slowly drop a frame, and if you read faster than you write, you'll eventually get a full frame stuffed into your stream--but either way things will work. This approach will use a "nearest-neighbor" interpolator, and will handle over and underruns by frame dropping or stuffing respectively. The trick you will have is that you only have one interface to memory. For that reason, both video streams will need to buffer their work into a FIFO. When the writer's FIFO is roughly half full, then it will need to write to memory until it's FIFO is empty. Likewise, when the reader's FIFO is half full, it'll want to initiate a read until its FIFO is full. This way, if both the writer and the reader want to access memory at the same time, they'll both be able to wait until the other completes it's memory access request/requirement. I haven't checked on your memory timing requirements at all. That could make things difficult. If it makes things impossible, then drop color bits and you should be able to get back into the realm of possible again. As for how to handle the multiple clocks, you will have three clocks you will need to deal with and work from. Two of these are your pixel clocks. The third is your memory clock. You can synchronize from the pixel to the memory clock and back again using the single "FIFO is half-full" wire. Dan
  23. 2 points
    WereCatf

    Stretch Goals?

    I ain't got anything specific in mind. For now, I'm just throwing spaghetti at the fridge and seeing if any of it sticks!
  24. 2 points
    D@n

    XADC demo

    @Manas, Sam is trying to turn voltage = (12-bit-code)/4096 into microvolts = (1000)*(1000)*(12-bit-code)/4096, and he's trying to avoid division. Rearranging: 1000*1000/4096 = 500*500/1024 (just by dropping common factors of two from both numerator and denominator) Shifting right by ten is equivalent to dividing by 1024, and then he multiplies by 500*500. Looks like it works alright. I might be concerned personally about losing any precision in the divide by 1024 (i.e. shift right by 10), especially since it is being done before the multiply if I understand correctly--leaving you with only 2-bits of precision (did I read that right?). Looking at the above, you might simplify it further into a shift right by 6, followed by a multiply of 15625. To get here, all I did was cancel out any factors of two that were in both the numerator and denominator. Then --- rearrange your order of operations, so the multiply is done first. What makes this choice special is that 15625 can fit within an 18-bit multiplier. Hence you can do: A = 15625*(12-bit-voltage-code) inside a DSP multiplier, and hence inside one clock. The result of this multiply will be a 30-bit number. If you ignore the bottom six bits, the 24-bit number that remains will be the number of microvolts that you are looking for. Converting this to a decimal display might take some more work though. Dan
  25. 1 point
    Hi @ahmedengr.bilal, Like I mentioned in the previous post there is no HDMI output from the Linux side, neither the embedded rootFS provided by petalinux nor the kernel configuration we give out is set to accommodate this feature. Regarding the missing media-ctl and v4l2-ctl, you have not activated the v4l-utils in the rootfs configuration of the petalinux. to do this you need to navigate to your petalinux project folder and run: petalinux-config -c rootfs Once the menu appears you need to go to Filesystem Packages->misc->v4l-utils and activate: v4l-utils, libv4l, media-ctl. Rebuild the whole project and it should be working now. -Ciprian
  26. 1 point
    HI xc6lx45: Well, to my surprise, when I got home and loaded the .BIT file onto the board...it works perfectly. [1:0]sw is changing the frequency the the led is blinking at properly. So this tells me that I don't quite have my testbed code done properly. I tried to attach it into this text but it kept getting reformatted so I've simply attached the actual file. If somebody could look at it and tell me what (if anything) I've done wrong I'd greatly appreciate it. THANKS! NOTE: In the actual module code, above, I had changed the CASE choices to the 0, 1st, 2nd and 3rd flip-flops in order to better see the led changing value on the wave panel. However I've changed the code back to the actual flip-flops I wanted; the 26th, 25th, 24th and 23rd flip-flops. As I said...the board is working perfectly now and the switch setting are appropriately changing the led blinking frequency. It HAS to be something wrong with the TestBench code...or me not using the simulator properly. THANKS MUCH! clock_divider.tb
  27. 1 point
    D@n

    Conflicting Voltages in Bank Arty-A7

    @zygot, @Ahmed Alfadhel is not using a Basys3 board, and so this is really a bad example of attaching one question to another post. @Ahmed Alfadhel appears to be using an Artix-A7 board. In that case, the sys_clk is properly constrained, but he may well have some of the DDR3 I/O pins improperly constrained. These are the pins located on Bank 35. I think the problem in this case is that @Ahmed Alfadhel has improperly constrained in DDR DQS pins. For example, ddr3_dqs_[0] should be set to pin N2, not to A6. Compounding the problem is the way these pins are hidden in a "board definition file" rather than in the XDC file, making it likely to have conflicting pin definitions. @Ahmed Alfadhel, If you are following Digilent's instructions, you might want to double check that you have the appropriate board definition file. If you are trying this on your own, using only an XDC file, then you might find these instructions valuable. Also, I would recommend you not attach unrelated issues to old posts. Perhaps the Digilent staff might be kind enough to separate these two issues into separate forum posts--since they really are quite different. For example, the Basys3 board doesn't have the DDR3 memory which is the source of your pin-connection troubles. Dan
  28. 1 point
    Well that's a pretty horrible looking 5 MHz signal coming directly out of an MMCM. It does remind me of the characteristic response of a particular passive component to a pulse, from decades ago when I took my intro electronics course. What do you think? Remind you of anything? I didn't mention the idea of scope probe compensation. It sure doesn't look like something that even a cheapo compensated probe would present for a low frequency signal out of a functioning FPGA pin into a high impedance load. Past that there are a number of usual suspects... but something is fundamentally wrong with your test setup.
  29. 1 point
    jpeyron

    Vivado and SDSoC with purchase

    Hi @Sduru, Welcome to the Digilent Forums. The list that comes with Vivado currently does not come with Digilent's board files included. You will need to install the board files as @kwilber describes above. thank you, Jon
  30. 1 point
    jpeyron

    Custom Image Processing on Zybo-Z7 20

    Hi @Amin, I have not made a project like this. To get a Zybo-Z7-20 project working with the SD card: Make sure you are using the Digilent board files.Here is the installation tutorial for the board files. Your block design should be the just the Zynq processor with FCLK_CLK0 connected to the M_AXI GP0_ACLK as shown with the attached screen shot. Run block automation as default(board files) when the Digilent board files are being used. Then create a wrapper and generate a bitstream. Next export the hardware including the bitstream and launch SDK. In SDK you should be able to alter the main.c file attache above to work for your needs. If your goal is to use a standalone project i can assist with using the ZYNQ processor with the SD card. I would have to reach out to more experience engineers for assistance using HLS or non-prebuilt SDSoC project. If your project does not need to be standalone then I would suggest using either an embedded linux project like petalinux , a pre-built SDSoC project or the SDSoC reVISION platform. 1) Here is the Petalinux Support for Digilent Boards which has two version releases and a very detailed readme which should help you get the project going. 2) Here is the SDSoC Platforms which has a project completed for the Zybo-Z7-20. 3) Here is the SDSoC reVISION project for the Zybo-Z7-20. thank you, Jon
  31. 1 point
    Hi @remalytics, I have moved you forum thread to a section where more experienced WaveForms/AD2 engineers look. thank you, Jon
  32. 1 point
    xc6lx45

    PmodHB5

    I'm sure it's possible to "drive" it at any rate. What I don't know is the amount and color of the magic smoke coming out :-) This is a fairly basic power electronics question: Each switching event dissipates energy because there is voltage across the transistor while current is nonzero. The question is, how much energy dissipation can you tolerate. With a 2A transistor you can probably feel with your finger whether or not it runs hot. In similar applications, PWM frequencies of 15 kHz or more are possible (search for "brushless ESC") but I doubt the motor will run any smoother.
  33. 1 point
    edu5163

    FMC-HDMI

    Hi mohammad, FMC-HDMI Diligent can work with this resolutions, it support formats up to UXGA(1600x1200) 60MHz at 8 bit at 161MHz. I attached a link to a tutorial where the resolution used is 1080p@60fps/16bit YUV 4:2:2 (150-148.5 MHz), in the tutorial I explain how to make a motion estimation application. https://arcoresearchgroup.wordpress.com/2018/03/23/realizing-the-lucas-kanade-motion-estimation-algorithm-on-xilinx-zc702-board-for-full-hd-real-time-video-analysis/ I hope it helps.
  34. 1 point
    Hi @BYTEMAN, These warnings are because when you installed the Vivado software, the support materials for the Spartan 7 chips (not available for Vivado 2016.X) nor the Kintex 7-series chips were installed alongside the Artix-7 series FPGA chips. As you are not creating a project for either of those chip series, you can safely ignore them. Let me know if you have any other questions. Thanks, JColvin
  35. 1 point
    attila

    I2C ACK before STOP bit

    Hi @kdumont According the I2C specs the address and written bytes are acknowledged by slave. The read bytes are acknowledged by the master except the last byte before stop. A master-receiver is done reading data and indicates this to the slave through a NACK.
  36. 1 point
    xc6lx45

    FPGA audio - ADC and DAC

    If I take it to extremes, the answer is surprisingly complex (this is how it's done inside the clock management tiles or a cellphone, for example). For household use, take (e.g.) a 32 bit counter and add "delta" at a high frequency, e.g. 100 MHz. Don't check for overflow, it will wrap around cyclically (which is the "correct" way to behave in this application. E.g. 0xFFFFFFFF + 3 becomes 0x00000002) For example, at 100 MHz clock, a delta of 1 gives a cycle time of 42.9 seconds (2^32 / 100e6). A delta of 43 gives a cycle time of one second. A delta of 42950 gives a cycle time of exactly 1 ms => 1 kHz. Now we've got a 32 bit number. Take the highest bits (as many as the DAC needs), voilà, a sawtooth generator. Plug that into your wavetable (you'll have to recalculate for a 0..31 range if using five ramp bits). Simple lookup from a block RAM (aka "nearest-neighbor / zero-order interpolation") will give abysmal audio quality, or the wavetable grows so large that it doesn't fit into the FPGA. So I need higher-order interpolation or a different algorithm (e.g. CORDIC for sine), and things get messy. PS: When working with signed numbers, check Verilog's "signed" keyword. It's not mandatory, but makes life easier.
  37. 1 point
    zygot

    Feedback on a register file design?

    You are wise and entering this with "eyes wide open"; I am confident that you will be successful and be rewarded for your efforts. As to textbooks, all of mine are currently boxed up as I am about to relocate.... Ashenden's VHDL textbook is a standard reference, though my copy is a bit dated. Sorry, the titles or authors of other books don't come to mind. Altera's Quartus reference manual has some excellent guidance on how to write text syntax that their synthesis tool understand. They also have an excellent "cookbook" of coding syntax for various structures like registers, counters, state machines, etc. Of course imitating good coding styles is not the same as understanding why they are good. Both Altera and Xilinx offer application notes as well example designs with source code. The material can be daunting, even for seasoned professionals, so don't get discouraged by the learning curve. Of course, sometimes you run into a problem that just doesn't get solved after hours of effort and this forum might help with that. The tools are not perfect and can be an impediment on their own.
  38. 1 point
    D@n

    cmods6 pinS

    @jvalls, You picked a good platform. I love my CMod-S6. It has taught me to appreciate every logic unit on the board. You can see what I did with mine here: a home-made CPU running a fully multi-tasking O/S! I personally never used the I/O planner. I instead found the master UCF file and edited it for my own purposes. (I must be crusty--I trust text files that I can edit over anything I can point-and-click with a mouse). For the most part, all I ever did was to change the names of the pins I wanted to use and commented pins I wasn't using. You may need to use the schematic to trace the pins from their I/O connections all the way to the FPGA names used in the UCF file. It can be annoying, but it's quite doable. Hope this helps, Dan
  39. 1 point
    Lao.Alex.512

    Heat Sink for Zybo

    Auto thermal shutdown can be enabled in the bitstream settings but I highly doubt you are going to run into thermal issues. The chip is rated for 85C so until you can burn yourself on the chip you should be OK. You could buy some heatsinks meant for GPU RAM in many places and attach it with thermal tape if you desire.
  40. 1 point
    JColvin

    Save an acquisition

    Hi @jpnbino, I don't necessarily have the answer to your question, but just as a clarification question so that we ensure we understand what you are looking for, you want to be able to: - capture data with logic analyzer - save the data - reopen the data from inside the logic analyzer tool itself so you can scroll and zoom and use the cursors as you please Is that accurate? Thank you, JColvin
  41. 1 point
    Hi @Happybacon, The 12 bits represent a single sample. Each sample that you take from the MIC3 represents (in a sense) both the amplitude and the frequency of the measured signal. The ADC takes the resulting voltage coming from the microphone (after it goes through some filters) and digitizes the signal. Because the incoming signal from the microphone will be sinusoidal since it is measuring sound waves and the ADC takes up to 1 MSPS, you can get a nice collection of data points where you can view how quickly the data oscillates between the top and bottom peaks (the frequency) and how high and low those peaks get (the amplitude). The circuitry for the Pmod MIC3 is set up so that it oscillates around the voltage midpoint (Vcc/2). You can then put the data through an FFT if you wish. There is a demo of running audio data from a microphone through an FFT on a Nexys 4 DDR here: https://reference.digilentinc.com/learn/programmable-logic/tutorials/nexys-4-ddr-spectral-sources-demo/start. Let me know if you have any questions. Thanks, JColvin
  42. 1 point
    No problem. Here is the design in action - it's a kayaking trainer. I wanted to count flywheel revolutions so that I can calculate power output and log training sessions. I guess it's a standard data logging application. It was fun. I'm now considering a super accurate version that times the periods between each sensor event - but this will do the job well enough.
  43. 1 point
    Hi @dummyC, I have reached out to my co-workers to get some input into your issue. cheers, Jon
  44. 1 point
    hamster

    MMCM dynamic clocking

    I feel a bit bad about posting a minor novel here, but here is an example of going from "5 cycles on, 5 off" (i.e. divide by 10) to "10 on, 10 off" (device by 20). The VCO is initially to 800 MHz with CLK0 being VCO divide by 8.... so after config you get 100MHz. Push the button and you get 800/20 = 40MHz, release the button and you get 80MHz. It is all really hairy in practice! EDIT: Through experimentation I just found that you don't need to reset the MMCM if you are not changing the VCO frequency. So the 'rst' signal in the code below isn't needed (and LOCKED will stay asserted). -------------------------------------------------------------------------------------------------------- -- Playing with the MMCM DRP ports. -- see https://www.xilinx.com/support/documentation/application_notes/xapp888_7Series_DynamicRecon.pdf -- for the Dynamic Reconviguration Port addresses -------------------------------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; library UNISIM; use UNISIM.VComponents.all; entity mmcm_reset is Port ( clk_100 : in STD_LOGIC; btn_raw : in STD_LOGIC; led : out STD_LOGIC_VECTOR (15 downto 0)); end mmcm_reset; architecture Behavioral of mmcm_reset is signal btn_meta : std_logic := '0'; signal btn : std_logic := '0'; signal speed_select : std_logic := '0'; signal counter : unsigned(26 downto 0) := (others => '0'); signal debounce : unsigned(15 downto 0) := (others => '0'); signal clk_switched : std_logic := '0'; signal clk_fb : std_logic := '0'; type t_state is (state_idle_fast, state_go_slow_1, state_go_slow_2, state_go_slow_3, state_idle_slow, state_go_fast_1, state_go_fast_2, state_go_fast_3); signal state : t_state := state_idle_fast; ----------------------------------------------------------------------------- --- This is the CLKOUT0 ClkReg1 address - the only register to be played with ----------------------------------------------------------------------------- signal daddr : std_logic_vector(6 downto 0) := "0001000"; signal do : std_logic_vector(15 downto 0) := (others => '0'); signal drdy : std_logic := '0'; signal den : std_logic := '0'; signal di : std_logic_vector(15 downto 0) := (others => '0'); signal dwe : std_logic := '0'; signal rst : std_logic := '0'; begin MMCME2_ADV_inst : MMCME2_ADV generic map ( BANDWIDTH => "OPTIMIZED", -- Jitter programming (OPTIMIZED, HIGH, LOW) CLKFBOUT_MULT_F => 8.0, -- Multiply value for all CLKOUT (2.000-64.000). CLKFBOUT_PHASE => 0.0, -- Phase offset in degrees of CLKFB (-360.000-360.000). -- CLKIN_PERIOD: Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz). CLKIN1_PERIOD => 10.0, CLKIN2_PERIOD => 0.0, -- CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for CLKOUT (1-128) CLKOUT1_DIVIDE => 1, CLKOUT2_DIVIDE => 1, CLKOUT3_DIVIDE => 1, CLKOUT4_DIVIDE => 1, CLKOUT5_DIVIDE => 1, CLKOUT6_DIVIDE => 1, CLKOUT0_DIVIDE_F => 8.0, -- Divide amount for CLKOUT0 (1.000-128.000). -- CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for CLKOUT outputs (0.01-0.99). CLKOUT0_DUTY_CYCLE => 0.5, CLKOUT1_DUTY_CYCLE => 0.5, CLKOUT2_DUTY_CYCLE => 0.5, CLKOUT3_DUTY_CYCLE => 0.5, CLKOUT4_DUTY_CYCLE => 0.5, CLKOUT5_DUTY_CYCLE => 0.5, CLKOUT6_DUTY_CYCLE => 0.5, -- CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for CLKOUT outputs (-360.000-360.000). CLKOUT0_PHASE => 0.0, CLKOUT1_PHASE => 0.0, CLKOUT2_PHASE => 0.0, CLKOUT3_PHASE => 0.0, CLKOUT4_PHASE => 0.0, CLKOUT5_PHASE => 0.0, CLKOUT6_PHASE => 0.0, CLKOUT4_CASCADE => FALSE, -- Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE) COMPENSATION => "ZHOLD", -- ZHOLD, BUF_IN, EXTERNAL, INTERNAL DIVCLK_DIVIDE => 1, -- Master division value (1-106) -- REF_JITTER: Reference input jitter in UI (0.000-0.999). REF_JITTER1 => 0.0, REF_JITTER2 => 0.0, STARTUP_WAIT => FALSE, -- Delays DONE until MMCM is locked (FALSE, TRUE) -- Spread Spectrum: Spread Spectrum Attributes SS_EN => "FALSE", -- Enables spread spectrum (FALSE, TRUE) SS_MODE => "CENTER_HIGH", -- CENTER_HIGH, CENTER_LOW, DOWN_HIGH, DOWN_LOW SS_MOD_PERIOD => 10000, -- Spread spectrum modulation period (ns) (VALUES) -- USE_FINE_PS: Fine phase shift enable (TRUE/FALSE) CLKFBOUT_USE_FINE_PS => FALSE, CLKOUT0_USE_FINE_PS => FALSE, CLKOUT1_USE_FINE_PS => FALSE, CLKOUT2_USE_FINE_PS => FALSE, CLKOUT3_USE_FINE_PS => FALSE, CLKOUT4_USE_FINE_PS => FALSE, CLKOUT5_USE_FINE_PS => FALSE, CLKOUT6_USE_FINE_PS => FALSE ) port map ( -- Clock Outputs: 1-bit (each) output: User configurable clock outputs CLKOUT0 => clk_switched, CLKOUT0B => open, CLKOUT1 => open, CLKOUT1B => open, CLKOUT2 => open, CLKOUT2B => open, CLKOUT3 => open, CLKOUT3B => open, CLKOUT4 => open, CLKOUT5 => open, CLKOUT6 => open, -- Dynamic Phase Shift Ports: 1-bit (each) output: Ports used for dynamic phase shifting of the outputs PSDONE => open, -- Feedback Clocks: 1-bit (each) output: Clock feedback ports CLKFBOUT => clk_fb, CLKFBOUTB => open, -- Status Ports: 1-bit (each) output: MMCM status ports CLKFBSTOPPED => open, CLKINSTOPPED => open, LOCKED => open, -- Clock Inputs: 1-bit (each) input: Clock inputs CLKIN1 => clk_100, CLKIN2 => '0', -- Control Ports: 1-bit (each) input: MMCM control ports CLKINSEL => '1', PWRDWN => '0', -- 1-bit input: Power-down RST => rst, -- 1-bit input: Reset -- DRP Ports: 16-bit (each) output: Dynamic reconfiguration ports DCLK => clk_100, -- 1-bit input: DRP clock DO => DO, -- 16-bit output: DRP data DRDY => DRDY, -- 1-bit output: DRP ready -- DRP Ports: 7-bit (each) input: Dynamic reconfiguration ports DADDR => DADDR, -- 7-bit input: DRP address DEN => DEN, -- 1-bit input: DRP enable DI => DI, -- 16-bit input: DRP data DWE => DWE, -- 1-bit input: DRP write enable -- Dynamic Phase Shift Ports: 1-bit (each) input: Ports used for dynamic phase shifting of the outputs PSCLK => '0', PSEN => '0', PSINCDEC => '0', -- Feedback Clocks: 1-bit (each) input: Clock feedback ports CLKFBIN => clk_fb ); speed_change_fsm: process(clk_100) begin if rising_edge(clk_100) then di <= (others => '0'); dwe <= '0'; den <= '0'; case state is when state_idle_fast => if speed_select = '1'then state <= state_go_slow_1; -- High 10 Low 10 di <= "0001" & "001010" & "001010"; dwe <= '1'; den <= '1'; end if; when state_go_slow_1 => if drdy = '1' then state <= state_go_slow_2; end if; when state_go_slow_2 => rst <= '1'; state <= state_go_slow_3; when state_go_slow_3 => rst <= '0'; state <= state_idle_slow; when state_idle_slow => di <= (others => '0'); if speed_select = '0' and drdy = '0' then state <= state_go_fast_1; -- High 5 Low 5 di <= "0001" & "000101" & "000101"; dwe <= '1'; den <= '1'; end if; when state_go_fast_1 => if drdy = '1' then state <= state_go_fast_2; end if; when state_go_fast_2 => rst <= '1'; state <= state_go_fast_3; when state_go_fast_3 => rst <= '0'; state <= state_idle_fast; end case; end if; end process; dbounce_proc: process(clk_100) begin if rising_edge(clk_100) then if speed_select = btn then debounce <= (others => '0'); elsif debounce(debounce'high) = '1' then speed_select <= not speed_select; else debounce <= debounce + 1; end if; -- Syncronise the button btn <= btn_meta; btn_meta <= btn_raw; end if; end process; show_speed_proc: process(clk_switched) begin if rising_edge(clk_switched) then counter <= counter + 1; led(7 downto 0) <= std_logic_vector(counter(counter'high downto counter'high-7)); end if; end process; led(15) <= speed_select; end Behavioral;
  45. 1 point
    D@n

    Guidance

    @C_R, Welcome to the forum, and welcome to the wonderful world of FPGA design! Let me see if I can answer some of your questions: Regarding your question of textbook, I've never used one so ... I may not be the best person to ask. However, an individual on the #yosys freenode IRC channel just recently read through FPGAs: Instant Access, and found that it helped to answer many of his questions. As for installing Vivado, ahm ... I just followed the instructions that came with the package? There were a couple of gotcha's that I had to deal with though, but these may be because I use Linux. 1) I needed to make certain I installed the board drivers as I went through the design flow--this required admin access, 2) I needed to make sure I ran a setup script before running Vivado in every window I ran it in, and 3) the interface between Vivado and my web browser was broken, so getting the license took a bit more work. To start with Vivado, you will first want to create a new project. You will initialize this new project with the FPGA you are programming for. You can find that in the schematic, and sometimes in the web page for your board. Then you'll want to add files to your project. If you are just starting from scratch, you can come back and add those later. Vivado has it's own file structure for things. I don't care for it. It feels like something that I can't control, so I impose my own. Really, the structure you choose is in many ways up to you. I tend to use the coding guidelines I found on Open Cores, with one exception: I create a "xilinx" directory to tell Vivado about, and to have Vivado dump all of its info into. The easiest way to download a file onto your board is using the hardware manager within Vivado. So, the flow works as 1) create/edit your design, 2) synthesize your design, 3) implement your design, 4) generate a bit stream, and 5) download that bitstream onto your board. With any new board, there are two basic designs you will find valuable. The first is the demo design offered by the manufacturer. This often gives you a quick "proof" that all the hardware on your board works, but ... not everybody finds that a useful starting point. My personal approach to a new board starts with first verifying that I can load a design into the board to turn an LED on, then again to turn it off, and finally to get it to blink. These three designs will make sure you are up and running with the tool set, that you really are up and running with the tool set, and last that you have a valid clock on your board. From this point, I can usually build everything else. (I'll come back to this in a moment.) I'm afraid, though, that my instructions will only get you so far. So ... can you write back regarding any steps you get confused or stuck on, and we can work through them? Dan
  46. 1 point
    D@n

    ETHERNET SHIELD

    @SUSHMA MANTAGANI, I think what you are wondering is what is wrong with your design. To answer that question, you really need to use wireshark for debugging it. That will allow you to look at and inspect the packets that are crossing the wire, so that you can see if they are properly formed or not. Indeed, that will also allow you to figure out whether or not it is the fault of the computer you are transmitting from, or the fault of the one you are transmitting to, and what part of the packet(s) are actually at fault. Dan
  47. 1 point
    jpeyron

    Arty COM Port issue

    Hi @spfoster, I think i see the issue. Please connect the resetn on the clock wizard to the reset line as in my screen shot. cheers, Jon
  48. 1 point
    The device is equipped with USB 2 controller, connecting it to USB 3 port it will still work at USB 2 speed.
  49. 1 point
    sLowe

    XADC demo

    Yea I think there may have been a more clear way to do that math. Maybe I'll add a comment above that line. In the project I do the multiply before shifting right which avoids the two bit precision which would be a big problem. Also in the project is the gross /10, &10 chain that calculates the decimal values but that will throw timing errors. I think what needs to be done is some sort of BCD conversion to evaluate those digits faster. Or spread the process over multiple clock cycles since the display doesn't need to be updated as fast as values are coming in. -Sam
  50. 1 point
    lukeswr

    Adept library to use in visual .net c#

    I have an excellent example of interfacing with non-managed libraries using an internal sealed class. I have attached the file. I copied this foot print from another interface class regarding a USB interface. This example is nowhere near complete, but it provides the building block. using System; using System.IO; using System.Runtime.InteropServices; namespace Linear.common.lap.Digilent.Adept2 { /// <summary> /// This class library provides the 64-bit interface to the Digilent Inc. Adept2 dmgr library. /// </summary> internal sealed class StaticDmgr : IDisposable { // ReSharper disable InconsistentNaming /// <summary> /// The following value is passed to DmgrGetTransResult to specify /// wait until the transfer completes. /// </summary> public const UInt32 tmsWaitInfinite = 0xFFFFFFFF; // Handle to our DLL - used with GetProcAddress to load all of our functions private IntPtr hDMGR = IntPtr.Zero; // Declare pointers to each of the functions we are going to use in DMGR.DLL // These are assigned in our constructor and freed in our destructor. private readonly IntPtr pDmgrGetVersion = IntPtr.Zero; private readonly IntPtr pDmgrEnumDevices = IntPtr.Zero; private readonly IntPtr pDmgrGetDvc = IntPtr.Zero; private readonly IntPtr pDmgrIsEnumFinished = IntPtr.Zero; private readonly IntPtr pDmgrStopEnum = IntPtr.Zero; private readonly IntPtr pDmgrFreeDvcEnum = IntPtr.Zero; internal StaticDmgr() { // If DMGR.DLL is NOT loaded already, load it if (hDMGR == IntPtr.Zero) { // Load our DEPP.DLL library hDMGR = LoadLibrary(@"DMGR.DLL"); if (hDMGR == IntPtr.Zero) { // Failed to load our DEPP.DLL library from System32 or the application directory // Try the same directory that this Adept2 DLL is in hDMGR = LoadLibrary(@Path.GetDirectoryName(GetType().Assembly.Location) + "\\DMGR.DLL"); } } if (hDMGR == IntPtr.Zero) throw new ApplicationException("Cannot locate the driver's DMGR.DLL interface library."); // If we have succesfully loaded the library, get the function pointers set up // Set up our function pointers for use through our exported methods pDmgrGetVersion = GetProcAddress(hDMGR, "DmgrGetVersion"); pDmgrEnumDevices = GetProcAddress(hDMGR, "DmgrEnumDevices"); pDmgrGetDvc = GetProcAddress(hDMGR, "DmgrGetDvc"); pDmgrIsEnumFinished = GetProcAddress(hDMGR, "DmgrIsEnumFinished"); pDmgrStopEnum = GetProcAddress(hDMGR, "DmgrStopEnum"); pDmgrFreeDvcEnum = GetProcAddress(hDMGR, "DmgrFreeDvcEnum"); InitializeDelegates(); } private void InitializeDelegates() { if (pDmgrGetVersion == IntPtr.Zero) throw new ApplicationException("Failed to load function DmgrGetVersion."); if (pDmgrEnumDevices == IntPtr.Zero) throw new ApplicationException("Failed to load function DmgrEnumDevices."); if (pDmgrIsEnumFinished == IntPtr.Zero) throw new ApplicationException("Failed to load function DmgrIsEnumFinished."); if (pDmgrStopEnum == IntPtr.Zero) throw new ApplicationException("Failed to load function DmgrStopEnum."); if (pDmgrFreeDvcEnum == IntPtr.Zero) throw new ApplicationException("Failed to load function DmgrFreeDvcEnum."); DmgrGetVersion = (tDmgrGetVersion)Marshal.GetDelegateForFunctionPointer(pDmgrGetVersion, typeof(tDmgrGetVersion)); DmgrEnumDevices = (tDmgrEnumDevices)Marshal.GetDelegateForFunctionPointer(pDmgrEnumDevices, typeof(tDmgrEnumDevices)); DmgrGetDvc = (tDmgrGetDvc)Marshal.GetDelegateForFunctionPointer(pDmgrGetDvc, typeof(tDmgrGetDvc)); DmgrIsEnumFinished = (tDmgrIsEnumFinished)Marshal.GetDelegateForFunctionPointer(pDmgrIsEnumFinished, typeof(tDmgrIsEnumFinished)); DmgrStopEnum = (tDmgrStopEnum)Marshal.GetDelegateForFunctionPointer(pDmgrStopEnum, typeof(tDmgrStopEnum)); DmgrFreeDvcEnum = (tDmgrFreeDvcEnum)Marshal.GetDelegateForFunctionPointer(pDmgrFreeDvcEnum, typeof(tDmgrFreeDvcEnum)); } #region Instantiated Function Delegates internal tDmgrGetVersion DmgrGetVersion; internal tDmgrEnumDevices DmgrEnumDevices; internal tDmgrGetDvc DmgrGetDvc; internal tDmgrIsEnumFinished DmgrIsEnumFinished; internal tDmgrStopEnum DmgrStopEnum; internal tDmgrFreeDvcEnum DmgrFreeDvcEnum; #endregion #region IDisposable Methods /// <summary> /// Destructor for the D2XX class. /// </summary> ~StaticDmgr() { if (hDMGR != IntPtr.Zero) { // FreeLibrary here - we should only do this if we are completely finished FreeLibrary(hDMGR); hDMGR = IntPtr.Zero; } } public void Dispose() { if (hDMGR != IntPtr.Zero) { // FreeLibrary here - we should only do this if we are completely finished FreeLibrary(hDMGR); hDMGR = IntPtr.Zero; } } #endregion #region Marshalling Methods to Unmanaged DMGR /// <summary> /// Built-in Windows API functions to allow us to dynamically load our own DLL. /// Will allow us to use old versions of the DLL that do not have all of these functions available. /// </summary> [DllImport("kernel32.dll")] private static extern IntPtr LoadLibrary(string dllToLoad); [DllImport("kernel32.dll")] private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); [DllImport("kernel32.dll")] private static extern bool FreeLibrary(IntPtr hModule); // Definitions for DMGR functions [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate int tDmgrGetVersion(byte[] szVersion); //OPEN & CLOSE functions internal delegate int tDmgrOpen(ref int phif, byte[] szSel); internal delegate int tDmgrOpenEx(ref int phif, byte[] szSel, int dtpTable, int dtpDisc); internal delegate int tDmgrClose(int hif); //ENUMERATION functions internal delegate int tDmgrEnumDevices(ref int pcdvc); //internal delegate int tDmgrEnumDevicesEx(ref int pcdvc, int dtpTable, int dtpDisc, int dinfoSel); //internal delegate int tDmgrStartEnum(ref int pcdvc); internal delegate int tDmgrIsEnumFinished(); internal delegate int tDmgrStopEnum(); //internal delegate int tDmgrGetEnumCount(ref int pcdvc); internal delegate int tDmgrGetDvc(int pcdvc, byte [] dvc); internal delegate int tDmgrFreeDvcEnum(); #endregion } }