• Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by hamster

  1. Hi, Once you get the feel for how FPGAs work, have a good look at the Vivado Synthesis Guide ( https://www.xilinx.com/support/documentation/sw_manuals/xilinx2017_1/ug901-vivado-synthesis.pdf ). It has lots of design patterns for how to describe the sorts of structures you might want to use -without reaching for the library of primitives. It covers things like memories, DSP blocks, shift registers, fifos and so on - without using the IP generator. It can be a great technique to use, as: - it does not tie your logic designs to a vendor's IP libraries & licensing - it allowing others to use your designs on different FPGA tools - is more flexible than using IP blocks - you don't need to regenerate IP blocks to make small changes - Easier to integrate into source control systems like Git, compared with IP blocks You might need to flick between other user guides (such as https://www.xilinx.com/support/documentation/user_guides/ug473_7Series_Memory_Resources.pdf for memories), but I am ure you will find it interesting.
  2. The is from memory, and I am on a phone, so don't be surprised if it is wrong... The PLL and the MMCM blocks have different max/min clock frequencies. I am pretty sure you will need to use the MMCM. CAn you check the datasheet and add an update to this post? "Artix 7 switching characteristics" should find it the correct PDF file quickly.
  3. Hi, A bit of background.... The transmitter uses the EDID ROM in the receiver (eg monitor or FPGA board) to see what formats the device can receive. If it identifies as DVI-D, then the source can only support picture data. IIfit identifies as HDMI then it can support pictures and audio. Here is what I think is going on. If you plug in the audio extractor by itself (or without the design running in the FPGA, the audio extractor says it supports HDMI, so audio is sent. When the FPGA design is loaded the splitter passes through the capabilities of the FPGA design in gn, which only supports DVI. So you get picture but no audio. The solution would be to have a full HDMI receiver in the FPGA (and then you might not require the audio splitter anyway.
  4. Last night I measured the speed of RF waves in a generic 10m TV coax using the AD2, a socket and two resistors Why?: I'm trying to build a cheap colinear antenna for receiving 1090MHz plane broadcasts. To do this I need to know the "velocity factor" of a cable. The setup: Connect the AD2 wave output and the input of the first scope channel (the reference channel) to one end of a 330 ohm resistor, Connect the other end of the 330 Ohm resistor, the second scope channel, and one end of the 100 Ohm resistor to the center pin on the socket. Connect the other end of the 100 Ohm resistor plus the AD2's ground connection to the shell/ground connection of the socket. Running the test: Without the cable plugged into the connector, run the Network Analyzer, from 1 MHz to 10 Mhz - it should be a pretty much flat line. Then connect the cable and test again. There will be a 'dip' somewhere 5 or 6 MHz. What is going on: The 330Ohm+100Ohm resistor acts as a signal divider, and has an AC impedance of about 75 ohm, matching that of the Coax cable. Because the cable has an open end, it is acting as an 'open stub' and any signal that is injected into the cable reaches the end of the cable and is reflected. The source and reflected signal interfere with each other, and where the signal is destructively interferes with the source signal the "dip" is seen. The bottom of this dip is when the cable is 1/4th the wavelength of the RF signal - so if the driving signal is at 90 degrees, the reflection is at 270 degrees, making the measured signal much weaker. Results: For a 10m (30 ft?) cable the dip was at 5.634MHz. That makes a full wavelength 40m long. That gives a speed of propagation of 5.634MHz * 40m = 225,360,000 m/second - about 75% the speed of light in a vacuum.
  5. The "sensitivity list" is the list of signals that will cause the body of the process to be evaluated when their values change. It can be also thought of the list of all asynchronous inputs and any clock signals used in the process. For hardware, usually the synthesis tool will generate the correct hardware anyway, regardless of any errors or omissions. For simulation they need to have all the required signals, as otherwise they body of the process won't be evaluated when it should be. For clocked processes, it should usually just be the clock signal and any async reset signal (which shouldn't really be used in FPGAs anyway!) For unclocked processes (asynchronous logic), it should be any signal that is used within the process. A template for a clocked process is this: process_name: process(clk, async_reset) begin if async_reset = '1' then x <= whatever_the_reset_state_is; elsif rising_edge(clk) then -- all your usual stuff if a = '1' then x <= b AND c; end if; end if; end process; In this case, if a = '1', b ='1' and then c changes the output x doesn't change - it only changes when the clk rises or if reset is asserted, which is why a,b and c are not needed on the sensitivity list. A template for an unclocked ("async") process is this: process_name: process(a,b,c) begin if a = '1' then x <= b AND c; end if; end process; if a = '1' and b = 'a' the process needs to be evaluated every time 'c' changes, so 'c' has to be on the sensitivity list. Likewise the output might change if a or b changes value, depending on the values of the other inputs, so they have to be there too. Having additional signals that aren't needed to the sensitivity list doesn't break anything, but it can waste time in simulation as the process triggers but nothing changes. You can do other things like "wait until rising_edge(clk);", which avoids the "if rising_edge() then" and nesting, but that is not "the done thing", and considered being a bit of a smarty-pants.
  6. I know I am completely off topic, and being no help at all, but.... IMO an FSM is the wrong tool for the job, and that why it seems odd. This is a pretty standard "build an FSM" assignment, but it involves creating a state machine where none is really needed. All you need to know is the state of the input during the previous clock cycle. if rising_edge(clk) then if my_signal_last = '0' and my_signal = '1' then my_signal_rising_edge <= '1'; else my_signal_rising_edge <= '0'; end if; my_signal_last <= my_signal; end if; or -- concurrently detect the rising edge of my_signal. -- It will be asserted when my_signal transitions from -- zero to one. -- -- You better make sure that my_signal is synchronised -- to the clock for this to work correctly! -- my_signal_rising_edge <= my_signal and not my_signal_last; process(clk) begin if rising_edge(clk) then my_signal_last <= my_signal; end if; end if; And as for "dividing the clock a few times", I shudder a little. Far better to keep everything in one clock domain, signal clock_enable_shift_register := std_logic_vector(7 downto 0) := "10000000"; generate_clock_enable_process: process(clk) begin if rising_edge(clk) then clock_enable <= clock_enable_shift_register(0); clock_enable_shift_register <=clock_enable_shift_register(0) & clock_enable_shift_register(clock_enable_shift_register'high downto 1); end if; end process; do_stuff_slowly_process: process(clk) begin if rising_edge(clk) then if clock_enable = '1' then ... do stuff once in a while end if end if; end process;
  7. Most of the FPGA pins can be used for multiple things - inputs, outputs, global clocks, configuration, XADC, DDR memory.... as long as the pin can do what you want it to do you can the you are OK to ignore the other features (as long as you don't need to use the other feature!) This is one of the differences between Xilinx and Altera FPGAs - Altera FPGAs usually have input-only pins, and high speed/low speed banks, making pin planning much more important for Altera.
  8. Hey there! For the standard I/O pins on 7-series FPGA are only rated to 1250 Mb/s or 950Gb/s depending on speed grade, so pixel clocks > 125MHz are very much out of spec. Also the ability to tune the capture phase (using IDELAY2 primitive) does not have enough resolution align clock edges at 148.6MHz pixel clocks, so it is somewhat hit and miss. However, If you use the high speed transceivers for HDMI, anything is possible :-)
  9. This might be of interest to you https://www.xilinx.com/video/hardware/using-the-non-project-batch-flow.html (regarding none-GUI builds) XDC files are a mystery, but here goes. - Both lines are comments - they begin with hashs - The second line is the true 'human readable' comment - the "Sch=" is the net naming in the schematic. . The IO_L8N... is the pin name on the FPGA package, It is in IO bank 35, it is the negative connection for LVDS pair 8 ("L8N"), and looks to also be the Negative input for XADC pair 14 ("AD14N"). Given the context it is pin M3 on the package being used. So if you removed the first '#' on the first line, this is what is going on. It applies the following settings: PACKAGE_PIN attribute is set to M3 IOSTANDARD attribute is set to LVCMOS33 to the list of external connection that match those found by "get_ports" looking for things that match "pio[01]".
  10. It is a Micro-B socket based on this picture - https://en.wikipedia.org/wiki/USB#/media/File:USB_konektory.png
  11. Hi, I haven't looked at the board's specs, but you can find examples at https://github.com/hamsternz/ArtyEtherentTX (100BaseT on the Arty board) https://github.com/hamsternz/FPGA_GigabitTx (1000BaseT on the Nexys Video board). They should be helpful to you.
  12. Sort of pen-and-papered it. 0xCCCCCCCD is 0.8*2^32, so it is d = i * (4/5*2^32) / 2^32 which reduces to d = i/10 expecting that I would have to do a fixup to pick up rounding errors, but then found it wasn't needed. It turns out that GCC does this optimization by default, but uses a 32-bit multiply that splits the result across two registers (EDX:EAX), but the above method doesn't touch EDX so leaves a register free, and can be a tad quicker.
  13. Tonight I discovered that this is a fast way to divide by 10 unsigned div10(unsigned x) { #ifdef REF /* Implement 32-bit division using divide */ return x/10; #else return (x * 0xCCCCCCCDLLU)>>35; #endif } Just wanted to post it here in case it becomes of use to somebody. A variant It could most likely be used with a DSP48 block to divide shorter (20 or 23 bit) binary numbers with much less resources and latency than a 10-bit binary divider.
  14. hamster

    Change ROM COE

    For the definitive word on how to infer memory blocks, including code examples, have a look at https://www.xilinx.com/support/documentation/sw_manuals/xilinx2014_1/ug901-vivado-synthesis.pdf from page 95. It covers everything from the simplest single port RAMs/ROMs to dual port RAMs with different data widths, with byte enables. For the large part, the same patterns also work in ISE. page 148 & 149 might be of special interest. It has "Initializing Block RAM From an External Data File VHDL Coding Example" and "Initializing Block RAM From an External Data File Verilog Coding Example"
  15. hamster

    Change ROM COE

    Hi! I too share your pain :-) I now infer all my ROMs - using code like this: library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity beacon is Port ( clk : in STD_LOGIC; leds : out STD_LOGIC_VECTOR (7 downto 0)); end beacon; architecture Behavioral of beacon is type a_data is array(0 to 31) of std_logic_vector(7 downto 0); signal data : a_data := ( x"01",x"02",x"04",x"08",x"10",x"20",x"40",x"80", x"01",x"02",x"04",x"08",x"10",x"20",x"40",x"80", x"01",x"01",x"02",x"02",x"04",x"04",x"08",x"08", x"10",x"10",x"20",x"20",x"40",x"40",x"80",x"80"); signal counter : unsigned(26 downto 0) := (others => '0'); begin process(clk) begin if rising_edge(clk) then leds <= data(to_integer(counter(counter'high downto counter'high-4))); counter <= counter+1; end if; end process; end Behavioral; This is something I had open right now - the counter is longer than it would need to be for a ROM address, passed in as a parameter for the module. It isn't very much work to make a script that converts your source data (in whatever format) into the entire Verilog/VHDL module, and it means that your code will work with other FPGA vendors tooling. If you track down some Arcade Game implementations for an FPGA they usually have a script to do exactly this - it is against the rules to include the ROM dumps in the code base. For example - https://github.com/bhamadicharef/bombjack-papilioplus-fpga/tree/master/romgen_source
  16. HI, This is a case when using shift registers can make your life so much easier in the constants - you can almost draw what you want to see library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity dac is Port ( clk : in STD_LOGIC; dac_clk : out STD_LOGIC; dac_cs : out STD_LOGIC; dac_ld : out STD_LOGIC; dac_data : out STD_LOGIC); end dac; architecture Behavioral of dac is signal clk_sr : std_logic_vector(3 downto 0) := "0011"; signal cs_sr : std_logic_vector(19 downto 0) := x"C0003"; signal data_sr : std_logic_vector(19 downto 0) := x"00000"; signal ld_sr : std_logic_vector(19 downto 0) := x"FFFFE"; signal counter : unsigned(2 downto 0) := "000"; type t_table is array(0 to 7) of std_logic_vector(15 downto 0); signal table : t_table := ( x"8000",x"E000",x"FFFF",x"E000", x"8000",x"2000",x"0000",x"2000"); begin process(clk) begin if rising_edge(clk) then -- Set the outputs dac_clk <= clk_sr(clk_sr'high); dac_cs <= cs_sr(cs_sr'high); dac_data <= data_sr(data_sr'high); dac_ld <= ld_sr(ld_sr'high); -- shift the data shift registers if clk_sr = "1001" then cs_sr <= cs_sr(cs_sr'high-1 downto 0) & cs_sr(cs_sr'high); data_sr <= data_sr(data_sr'high-1 downto 0) & data_sr(data_sr'high); ld_sr <= ld_sr(ld_sr'high-1 downto 0) & ld_sr(ld_sr'high); -- put a new data value in the data shift register, when needed needed if cs_sr(15) = '1' and cs_sr(14) = '0' then data_sr(15 downto 0) <= table(to_integer(counter)); counter <= counter + 1; end if; end if; -- Shift the clock shift registers clk_sr <= clk_sr(clk_sr'high-1 downto 0) & clk_sr(clk_sr'high); end if; end process; end Behavioral; I've attached the simulation image
  17. Hi! I've hooked up a CMOD-A7 to an audio codec board designed for the Raspberry Pi, getting ready to play with some audio. You can find the VHDL source at http://hamsterworks.co.nz/mediawiki/index.php/STGL5000#sgtl5000_interface.vhd It is still rough and ready, but it works
  18. hamster

    SERDES: A first project

    The SERDES isn't super tricky to use once working (esp for outputs), but getting it to work the first time is quite hard. Make sure that you follow the clocking design in the user guide exactly. You don't have the flexibility to use just any clocking resource to drive them - you must use the correct MMCM connections and the correct buffers The bit ordering can be a confusing, when thinking about the order of the bits on the wire. In the user guide there is a picture that is helpful, showing the order the bits leave the SERDES block and then arrive at the receiver. The spec sheet limits performance to about 1Gb/s or 1.25Gb/s (for a 500 or 600 MHz toggle rate). They can work a little bit faster than this, but of course that is out of spec.
  19. Hi! Is the USB stick formatted with FAT32? I have had no problem with loading a bit file from a USB stick on my Basys3... except when it was formatted with NTFS ;-)
  20. Hi deltaepsilon3, You can talk directly to the Ethernet interfaces - here is something for the Arty Board, showing the level of complexity needed http://hamsterworks.co.nz/mediawiki/index.php/ArtyEthernet For Gigabit Ethernet it is much the same http://hamsterworks.co.nz/mediawiki/index.php/GigabitTX With a bit of experimentation you can replace the data payload with your samples, and implement some form of flow control (so you only send packets when you have data to send. Mike
  21. hamster

    inquiry on Artix7 board

    At a glance, from the last screen shot it seems you are sampling 10 channels, so that look to be about 100k samples per channel per second... I haven't used the XADC that much at all. You would really need to have a a quick read of the user guide to find the bits of interest, then read them closely to find out exactly what you want to do. Mike
  22. This little module might be of use to somebody - it sends 16-bit values to an external serial device, as four ascii hexidecimal digits (eg "12AB"), with new lines and carriage returns. http://hamsterworks.info/index.php/Hw_tx_binary_as_ascii The sample design send the settings of the 16 slide switches every time the center button is pressed.
  23. hamster

    inquiry on Artix7 board

    The XADC is a Dual 12-bit ADC. 1MS/s ADC. You are you getting the data off of the ARTY for analysis? Or are you using a Microblaze CPU? Are you getting 1,000,000 reading per second? The ADCs are shared between multiple channels, so if you have 5 channels enabled you will at best only get 200k samples per channel. It can also be set up as bipolar or unipolar mode - are you sure you have it configured right? can you show any of your configuration? For unipolar signals the XADC's range is only from 0.0V to 1.0V - are you sure you are not driving it out of this range?
  24. 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.
  25. I know this sounds wrong, but.... A good way to convert 8-bit binary into Decimal Digits is most likely a 256 entry lookup table, giving an two 4-bit results. Yes, it will seem a lot of code, but it will implement very efficient, is fast, and will use very little power. You can also replace a lot of logic, if your conversion would otherwise involve constants (e.g. if you also need to calculate "out_val = k * in_val + c", like you would to convert degrees C into degrees F)