• Content count

  • Joined

  • Last visited

  • Days Won


hamster last won the day on September 25

hamster had the most liked content!

About hamster

  • Rank
    Overly helpful
  • Birthday 08/23/69

Contact Methods

  • Website URL

Profile Information

  • Gender
  • Location
    New Zealand
  • Interests
    Electronics, FPGAs, MtBiking, Road Cycling, Linux....

Recent Profile Visitors

3573 profile views
  1. 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.
  2. One-hot encoding mystery

    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.
  3. One-hot encoding mystery

    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;
  4. Artix-A7 non-GUI development

    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.
  5. DVI to RGB IP Core - problems with resolutions above 720p

    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 :-)
  6. Artix-A7 non-GUI development

    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]".
  7. CMOD A7 Type of USB Micro Connector

    It is a Micro-B socket based on this picture - https://en.wikipedia.org/wiki/USB#/media/File:USB_konektory.png
  8. Using the Rj45 and Ethernet controller

    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.
  9. Dividing by 10....

    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.
  10. Dividing by 10....

    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.
  11. 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"
  12. 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
  13. create sine wave on dac using vhdl

    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
  14. SGTL5000 + PMOD CMOD-A7

    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
  15. 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.