• Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by hamster

  1. Oh, here's a few comments on the O.P's code. Most of the problems is that the adder's clock isn't an actual clock signal - it is the two buttons ORed together. To make this sort of design work you want an adder that has a "Clock Enable" ("CE") signal. That way the clock can tick every cycle, and the 'trigger' signal can drive the "Clock Enable" input. The more subtle issue is that their is something close to a race condition - the pressing of the buttons changes the input to the adder, but the pressing of the button also triggers the adder. Which will happen first? Who knows? An experiment in bad form could be to have trigger be "trigger <= NOT(btnU or btnD);" - that way the adder would be clocked by the falling edge of the button signal (i.e. on the downpress the input is set to either 'minus' or 'plus', and on the lift the adder is clocked. However, you still have a race condition - will add_sub be reset to 'zero' before or after the adder actually responds to the clock input? if btnD = '1' then add_sub <= minus; elsif btnU = '1' then add_sub <= plus; else add_sub <= zero; -- (sub zero lol) end if; If you change that bit of code to this, as well as the change to trigger to clock on button lift: if btnD = '1' then add_sub <= minus; elsif btnU = '1' then add_sub <= plus; end if; It will most likely give warnings about inferred latches, but it might work as expected. It is still not good synchronous design though, but still might be interesting. PS. Good choice of board to learn on too :-)
  2. Worse than metastability is just simple timing issues - a signal takes a short period of time to get along the wires in the FPGA - just using indicative numbers, maybe a nanosecond or so. If the signal for a button is being used in the top left and bottom right of the chip the downstream logic see a skewed value on the wire. If a design is running at 100MHz (10ns cycle) there is a 1 in 10 chance of failure (a metastability error is much less likely 1 in 1 million chance) The solution is the same though - for any asynchronous signal latch it in a flip-flop before you use it.
  3. I Hadn't picked up a board in a while (we are trying to get our house ready for sale, so I've been picking up paint brushes!) So here is a quick design I knocked out to achieve your aim, with all the tricks I think need to be added. I've found my Basys3 and it works for me - it might work for you too. The big difference is "use IEEE.NUMERIC_STD.ALL;" and, it allowing the use of "unsigned" data type, to which you can add and subtract. Feel free to ask questions - most of the design decisions are quite arbitrary and you might have better ideas! library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity up_down is Port ( clk : in STD_LOGIC; btn1_raw : in STD_LOGIC; btn2_raw : in STD_LOGIC; leds : out STD_LOGIC_VECTOR (3 downto 0)); end up_down; architecture Behavioral of up_down is -- For synchronizing into the clock domain signal btn1_meta : std_logic := '0'; signal btn2_meta : std_logic := '0'; signal btn1 : std_logic := '0'; signal btn2 : std_logic := '0'; -- Fro debouncing the synchronised signals -- Length defines the 'hold time' for the debouncing - 2^19 cycles signal debounce1 : unsigned(19 downto 0) := (others => '0'); signal debounce2 : unsigned(19 downto 0) := (others => '0'); signal debounced1 : std_logic := '0'; signal debounced2 : std_logic := '0'; -- For detecting the rising edges of the debounced signals signal debounced1_last : std_logic := '0'; signal debounced2_last : std_logic := '0'; signal count : unsigned(3 downto 0) := (others => '0'); begin leds <= std_logic_vector(count); -------------------------------------------- -- Process to synchronise the button signals -------------------------------------------- sync_proc: process(clk) begin if rising_edge(clk) then btn1 <= btn1_meta; btn2 <= btn2_meta; btn1_meta <= btn1_raw; btn2_meta <= btn2_raw; end if; end process; ---------------------------------------------- -- Process to debounce the buttons, to generate -- 'debouncedX' that is stable for 2^19 cycles ----------------------------------------------- debounce_proc: process(clk) begin if rising_edge(clk) then if btn1 = '0' then if debounce1(debounce1'high) = '1' then -- Count down if the button is lifted debounce1 <= debounce1 - 1; else -- snap down to zero once the MSB clears debounce1 <= (others => '0'); end if; else if debounce1(debounce1'high) = '0' then -- Count up if the button is pressed debounce1 <= debounce1 + 1; else -- snap down to zero once the MSB is set debounce1 <= (others => '1'); end if; end if; debounced1 <= std_logic(debounce1(debounce1'high)); if btn2 = '0' then if debounce2(debounce2'high) = '1' then -- Count down if the button is lifted debounce2 <= debounce2 - 1; else -- snap down to zero once the MSB clears debounce2 <= (others => '0'); end if; else if debounce2(debounce2'high) = '0' then -- Count up if the button is pressed debounce2 <= debounce2 + 1; else -- snap down to zero once the MSB is set debounce2 <= (others => '1'); end if; end if; debounced2 <= std_logic(debounce1(debounce1'high)); end if; end process; ---------------------------------------------- -- A process to detect the rising edges in the -- debounced signals and then update the counter ----------------------------------------------- count_proc: process(clk) begin if rising_edge(clk) then if debounced1 = '1' and debounced1_last = '0' and debounced2 = '1' and debounced2_last = '0' then -- both buttons pressed at the same time. NULL; elsif debounced1 = '1' and debounced1_last = '0' then -- Count up count <= count + 1; elsif debounced2 = '1' and debounced2_last = '0' then -- Count down count <= count - 1; end if; -- Remember button states for next cycle debounced1_last <= debounced1; debounced2_last <= debounced2; end if; end process; end Behavioral;
  4. Oh, I've just used Vivado on a freshly re-installed Win10 laptop and had to use this fix again. Just remember to either reboot once the drivers have correctly installed, or kill off the "hw_server" process.
  5. Hi You want to map the values of [-128 to +127] to [0 to 255]. So either just add 128, or XOR with binary 10000000
  6. Your code looks fine, so as far as I can guess you have two possible problems. 1) Your I/O pins are not connected as expected (e.g. you constraints are set wrong) 2) Your clock is not ticking Humm... Maybe I have found it. Have a look at page 21 of https://www.xilinx.com/support/documentation/university/XUP Boards/XUPZYBO/documentation/ZYBO_RM_B_V6.pdf "Keep in mind that CLK125 will be disabled when the Ethernet PHY (IC1) is held in hardware reset by driving the PHYRSTB signal low." You may also need to add the PHYRSTB signal to your design and drive it high, to bring the Ethernet PHY out of reset and start your 125MHz clock ticking. Ouch - that is a trap for beginers
  7. Hi! Can you also post the active lines of the XDC file you are using? Don't bother posting the comments :-) It should be something like... set_property -dict { PACKAGE_PIN L16 IOSTANDARD LVCMOS33 } [get_ports { clk }]; create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 4} [get_ports { clk }]; set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { btn[0] }]; set_property -dict { PACKAGE_PIN P16 IOSTANDARD LVCMOS33 } [get_ports { btn[1] }]; set_property -dict { PACKAGE_PIN V16 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; set_property -dict { PACKAGE_PIN Y16 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 } [get_ports { led[0] }]; set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports { led[1] }]; set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { led[2] }]; set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { led[3] }]; based on https://github.com/Digilent/ZYBO/blob/master/Resources/XDC/ZYBO_Master.xdc
  8. Hi Greg765, +1 for synchronizing the RX signal. I'm a bit confused by having multiple processes in the same clock domain, The interactions take a while to understand... I'ld have to simulate it, but I think your problem is that your tick counters are getting out of alignment with the data. I would try this for an idea.... Have a counter that just counts through the entire 9 and half bit times, but only starts counting when RxD_sync is zero. (It will need to be 18 bits long if you use UNSIGNED types): constant half_bit : natural := 5902; -- This is clock speed / baud_rate / 2; if counter == 0 then if RxD_sync = '0' then counter <= counter+1; end if; else if counter = half_bit*19 then -- 19/2 bit counts = middle of stop bit count <= 0; else counter <= counter+1; end if; end if And then sample the bits when the counter is in the center of the bits, which might look something like this: case counter is when half_bit*3 => data_out(0) <= RxD_sync; when half_bit*5 => data_out(1) <= RxD_sync; when half_bit*7 => data_out(2) <= RxD_sync; when half_bit*9 => data_out(3) <= RxD_sync; when half_bit*11 => data_out(4) <= RxD_sync; when half_bit*13 => data_out(5) <= RxD_sync; when half_bit*15 => data_out(6) <= RxD_sync; when half_bit*17 => data_out(7) <= RxD_sync; end case; (of course you will need to wrap it up in a nice clocked process and all that, but 80% of the code is there). It might not be the most efficient of implementation in terms of logic resources, and it is super-sensitive to noise on the RX signal causing a false start bit, but it is pretty simple to debug as an initial test and should work second time. Designing for ease of debug / least complexity / least chance of needing debug is a good habit...
  9. The SD card is connected to the Zynq's MIO pins so you do not need to constrain anything. The MIO pins are defined in the Zynq Processing System's configuration - in the IP block you define of the pins are used for for what function (e.g. Serial, Ethernet, SPI...) The MIO pins have fixed pin assignments on the Chip's package, so no XDC entries are needed - you just need to define the MIO settings to match the board's layout. Here is the screen you want to look for (although this is NOT correctly configured for the Zybo!):
  10. hamster

    4 tap FIR filter

    @Dan - You will give away all the secrets! - Yes the to_signed(255,8) was one of a few talking points. I find modeling it in a spreadsheet is the best way to play with filter values to ensure you use the best precision and avoid overflows. and to play with different scaling values - have the "ideal" filter in floating point, and then try different scaling and roundings. To handle rounding I sometimes to subtract 2^(n-1) from negative total values before truncating to n bits in length...
  11. hamster

    4 tap FIR filter

    1) See http://hamsterworks.co.nz/mediawiki/index.php/Minimal_XADC_design for a very minimal XADC using primatives (if that is your thing!) 2) Here is a really simple framework for your filter. Although it looks straightforward you will have to look at everything very closely. Issues and subtleties lurk in almost every line - type conversions, overflow errors, timing errors. very poor use of resources, implicit assumptions about intermediate type, rounding, precision errors - it has the general form of the answer you are looking for, but will not work without you working hard to see what is going on. I recommend you set up a project in Vivado, and then have a close look at the RTL schematic to see what it actually describes, then try and design and pass pathological data through it in the simulator to show up the errors (such as overflows and underflows). However, the line you are looking for in the 20-bit to 12-bit conversion is the one after the "begin" statement. library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity filter is Port ( clk : in STD_LOGIC; in_sample : in STD_LOGIC_VECTOR(11 downto 0); in_data_enable : in STD_LOGIC; out_sample : out STD_LOGIC_VECTOR(11 downto 0); out_data_enable : out STD_LOGIC); end filter; architecture Behavioral of filter is type t_data is array(0 to 4) of signed(11 downto 0); type t_kernel is array(0 to 4) of signed(7 downto 0); signal data : t_data := (others => (others => '0')); signal kernel : t_kernel := (to_signed( 10,8), to_signed( -10,8), to_signed( 255,8), to_signed( -10,8), to_signed( 10,8)); signal updated_data : std_logic := '0'; signal total : signed(19 downto 0) := (others => '0'); begin -------------------------------------------------- -- Type conversion and scaling -------------------------------------------------- out_sample <= std_logic_vector(total(19 downto 8)); process(clk) begin if rising_edge(clk) then --------------------------------------- -- Process any data received last cycle --------------------------------------- if updated_data = '1' then total <= (data(0) * kernel(0)) + (data(1) * kernel(1)) + (data(2) * kernel(2)) + (data(3) * kernel(3)) + (data(4) * kernel(4)); out_data_enable <= '1'; end if; -------------------------------------------- -- Receive any new data presented this cycle -------------------------------------------- if in_data_enable = '1' then data(1 to 4) <= data(0 to 3); data(0) <= signed(in_sample); updated_data <= '1'; end if; end if; end process; end Behavioral;
  12. If you haven't already done an RMA, now that the cable drivers are installed can you remove the mouse device while the CMOD ins't plugged in, then plug it in so it can detect it again? To do this Start a CMD prompt as administrator, run: SET DEVMGR_SHOW_NONPRESENT_DEVICES=1 DEVMGMT.MSC Then in device manager select the "View/Show hidden devices" menu item. You should then be able to remove the mouse device. Then plug the CMOD in and see what happens. This will allow the driver autodetect to run while the new cable drivers are installed. (see http://www.thewindowsclub.com/show-non-present-devices-windows for a better walkthrough of the process) It is also a way you can get rid of all the old USB COM ports that are left behind by DevBoards past... and disk devices from old USB drivers.
  13. Something like this maybe? (I don't use Verilog)... if(clk_cnt[ divider_i] == 1'b1) clk_o_s <= 1'b1; else clk_o_s <= 1'b0; ;
  14. I had the same problem. You should find the answer here:
  15. You can use any signal you like as a clock, so make a counter/divider to divide down a faster clock, and then use that a clock signal The other option is to have a faster clock, but use a "clock enable" to one do work one cycle in every 'n'.cycles e.g. if rising_edge(clk) and clock_enable = '1' then
  16. A lot of the unanswered questions are around what you are trying to do. Glancing through the datasheet (http://www.mouser.com/ds/2/256/MAX11300-335894.pdf), the ADC is fairly complex, and could require quite a bit of setup to get it configured and delivering sample data. There looks to be more than a handful of registers that need to be set. This makes me think that a micro-controller with a SPI peripheral or a soft CPU will be a good idea to use. The device also has a lot of channels, how many will you be using? What do you want to do with the samples once you get the data?
  17. Hi! I am not familiar with your ADC, but this is using SPI to read a different ADC: http://hamsterworks.co.nz/mediawiki/index.php/SPI_ADC
  18. There are a few issues with Vivado on Ubuntu - for example: https://forums.xilinx.com/t5/Embedded-Development-Tools/Vivado-2016-1-SDK-launch-problem/td-p/693615 I've also heard that it is sensitive to library versions - something to do with the tools calling "setenv(NULL);" (which should not be done), and is handled differently in different versions.
  19. I've had some trouble with Vivado Cable drivers under Windows 10 - Hardware Manager fails to detect hardware and the log says "warning: cannot find symbol ftdimgr_lock in library dpcomm.dll, frequently used Digilent JTAG cables cannot be supported" To fix this open a windows command problem, but use "Run as Administrator". Then reinstall the cable drivers with the following commands. cd \Xilinx\Vivado\2016.4\data\xicom\cable_drivers\nt64 install_drivers_wrapper.bat \Xilinx\Vivado\2016.4\data\xicom\cable_drivers\nt64 c:\Xilinx\Vivado\2016.4\install.log c:\Xilinx\Vivado\2016.4\ this error is also referenced in
  20. It's pretty simple, When adding 3 to a 3-bit counter, it will 'roll over' 3 times every 8 (or 2^3) cycles. And 40 MHz * 3/8 = 15 MHz If it was a 5=bit counter it would roll over 3 times every 32 (2^5) cycles, so it would give 40MHz * 3/32 = 3.75 MHz
  21. @zygot... I got a little bit of code working last night... - Test pattern generator, which counts 0 to 2^n-1, and then sends a few sync patterns - 4-bit to 5-bit symbol conversion, that also looks up a symbol's parity count. This only generates symbols with positive disparity - Disparity balancing - if the running disparity is negative it inverts the symbol and subtracts the current symbol's disparity, otherwise it it just added the current symbol's disparity to the running total - A 5:1 serializer to output the bits towards the PMOD connector I've also got a plan together for the RX side of the link... especially about recovering framing and how to detect the sync pattern. It is coming together quite nicely! Using three data pairs and sending 20-bit values is just awkward. If not, I might send 21-bit values (about 5% less efficient) but I can then send one number using 7 data bits on each of three pairs... is that still valid for the challenge? Mike
  22. @zygot, you have a strange turn of phrase... passively aggressive and paternal at the same time, and with all the taste and nutrition of a fine Belgian chocolate. Thinking/design is important than code, as the HDL is the expression of your thoughts and ideas - without good ideas you end up with hollow and unimaginative code. Not having a clock input isn't a grand problem, you can always hook things though a BUFG and onto the clocking networks, and deskew in a PLL by creeping the phase if you really have to because you can't get it to lock. I have to get a grips on how to do this for my HDMI input project, because the current way I do it by looking for symbol errors sucks big-time. For my testing I was going to do it for real - between two different 7-series boards (e.g. from an Arty to a Basys3 or similar). Looping back to the same chip (sharing references and so on) is a bit of a cheat. Also place and route times are much quicker on the smaller chips. You can hold your breath if you like, but it might take me a while - most likely after Christmas. Work is busy before a the change freeze, I have an existing software project I'm working on and then I'm away camping for two weeks holiday. But you can be assured that I will be doing some more thinking.
  23. I've been thinking, and I'm going to try this coding.... Bit 0 - Invert / non-invert Bit 1 - Data bit 0 Bit 2 - Data bit 1 Bit 3 - Data bit 2 Bit 4 - Data bit 3 Symbols are inverted to preserve DC balance & minimize running disparity. This coding will also still work if the + and - signals get swapped.So the next issue is how to synchronize the symbols. We have a problem though ...00000111110000011111... is ambiguous 0 0 0 0 0 - 1 1 1 1 1 - 0 0 0 0 0 - 1 1 1 1 1 is a stream of zeros. 0 0 0 0 1 - 1 1 1 1 0 - 0 0 0 0 1 - 1 1 1 1 0 is a stream of ones. 0 0 0 1 1 - 1 1 1 0 0 - 0 0 0 1 1 - 1 1 1 0 0 is a stream of threes. 0 0 1 1 1 - 1 1 0 0 0 - 0 0 1 1 1 - 1 1 0 0 0 is a stream of seven. 0 1 1 1 1 - 1 0 0 0 0 - 0 1 1 1 1 - 1 0 0 0 0 is a stream of hexadecimal Fs. It needs some way to recover the synchronization. Within a data sequences "00000000001111111111" or "11111111110000000000" should never be seen within a data sequence as it takes the running disparity to far out of wack. I can then use the center transition to recover the framing. This has a crufty feel to it, but should work. Good points: - Coding overhead is 25% vs 100% for something like Differential Manchester encoding or Biphase Mark Code. - DC neutral. - run length limited to 15 bits, Bad points: - Framing isn't too efficient or effective - No effective way to detect errors (e.g all codes are valid), other than running disparity goes out of wack - RF/EMI is most likely very poor - sending repeating patterns is very easy to do - could be improved by scrambling data before sending. The need for the RX to oversample the input to recover the clock can be removed if one pair sends the clock, leaving three pairs to take data. At 100MB/s over the remaining three pairs the clock rate needs to be 33.3 MHz, and a bit rate of 333Mb/s per pair. Using only DDR registers the RX and TX can run at 166 MHz, which is pretty achievable.Using SERDES at 5:1 it only needs to run at 66MHz. How does that sound as a plan? Sounds reasonably workable...
  24. Dan meant a 'three bit' counter (that counts from zero to seven). when you adding 3 each cycle the counter will run as follows: 0, 3, 6, 1, 4, 7, 2, 5, 0, 3, 6, 1, 4, 7, 2, 5... And the most significant bit of the counter will be: 0, 0, 1, 0, 1, 1, 0 ,1, 0, 0, 1, 0, 1, 1, 0 ,1... That gives three 0-to-1 transitions every eight clock ticks, for a total of 15,000,000 every second if you are using a 40MHz clock. You can do the same thing with a shift register, avoiding addition completely: shift_reg : std_logic_vector(7 downto 0) := "00001111"; if rising_edge(clk) then output_signal <= shift_reg(7); shift_reg <= shift_reg(4 downto 0) & shift_reg(7 downto 5); end if; You can do a little bit better than this using a DDR register to halve the phase noise on the output, but it is still very poor compared with using a PLL or MMCM.