• Content Count

  • Joined

  • Last visited

  • Days Won


Everything posted by hamster

  1. Hi Jaiko07 What is specification for your output that you are aiming for? It is is a 50% duty cycle, 200Hz signal then this might be a better pattern to follow for your process: countClock: process(clock,clear) begin if (clear = '1') then adjfreq <= "000000000000000000"; elsif(clock'event and clock = '1') then -- Flip a the output once every 125,000 cycles (400Hz) -- to give a 200Hz output with 50% duty cycle if (adjfreq = "011110100001001000") then adjfreq <= "000000000000000000"; adjclock <= not adjclock; else adjfreq <= adjfreq+1; end if; end if; end process; I haven't compiled it or tested it, but the intent should be clear - you are counting the cycles between the transitions, then flipping the output.
  2. Hi Shruthi, 1) check http://www.xilinx.com/support/documentation/user_guides/ug480_7Series_XADC.pdf page 60 - table 4-4. The channel numbering is a little bit odd. 2) Not sure, as XADC is only available on 7-Series FPGAs. I guess it is for future chips, and I guess it only matters for simulation. 3) If you want to only read channel 6, yes. See figure 3-1 on page 36. Mike
  3. hamster

    basys 3 FPGA

    Hi Marco you can find a very basic example of the logic for PWM control here: http://hamsterworks.co.nz/mediawiki/index.php/XADC_Fan_PWM - it controls the speed of the fan on the Genesys2 board.
  4. Oh, and just to rant on a little more. It seems to be nicer as a single "read or write" process, than two separate processes. read_and_write: process (Clock) begin if rising_edge(Clock) then if Reset = '1' then -- Synchronous reset to clear memory Memory <= (others => (others => '0')); DataOut <= (others => '0'); elsif Enable = '1' then if WriteEn = '1' then -- Write Memory Memory(to_integer(unsigned(Address))) <= DataIn; else -- Read Memory DataOut <= Memory(to_integer(unsigned(Address))); end if; end if; end if; end process;
  5. Fixups were.... Only one process should write to 'memory' (that was what was most likely breaking it - I was scratching my head as to why it was broken). In the testbench, the 'generics' were not being used correctly. Also, the middle processes (stim_main) was not needed, and was upsetting the simulation. Oh, I would tend to write the test process as: -- Stimulate Write process stim_write_read : process begin wait until rising_edge(clock); wait until rising_edge(clock); wait until rising_edge(clock); -- write Address <= "00000"; Reset <= '0'; for i in 0 to 2 loop WriteEn <= '1'; Enable <= '1'; wait until rising_edge(clock); Address <= Address + 4; DataIn <= DataIn + 3; end loop; -- read Address <= "00000"; for k in 0 to 2 loop WriteEn <= '0'; Enable <= '1'; wait until rising_edge(clock); Address <= Address + 4; end loop; Enable <= '1'; wait; end process; end; I find waiting for the clock edge makes more sense than waiting for the clock period.
  6. Contrast with this: LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; entity RAM is Generic ( DATA_WIDTH : integer := 8; ADDRESS_WIDTH : integer := 8 ); Port ( Clock : in STD_LOGIC; Reset : in STD_LOGIC; DataIn : in STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0); Address : in STD_LOGIC_VECTOR (ADDRESS_WIDTH - 1 downto 0); WriteEn : in STD_LOGIC; Enable : in STD_LOGIC; DataOut : out STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0) ); end RAM; architecture Behavioral of RAM is type Memory_Array is array (0 to (2 ** ADDRESS_WIDTH) - 1) of STD_LOGIC_VECTOR (DATA_WIDTH - 1 downto 0); signal Memory : Memory_Array; begin -- Read process process (Clock) begin if rising_edge(Clock) then if Enable = '1' then if WriteEn = '0' then -- Read Memory DataOut <= Memory(to_integer(unsigned(Address))); end if; end if; end if; end process; -- Write process process (Clock) begin if rising_edge(Clock) then if Reset = '1' then -- Clear Memory on Reset Memory <= (others => (others => '0')); elsif Enable = '1' then if WriteEn = '1' then -- Store DataIn to Current Memory Address Memory(to_integer(unsigned(Address))) <= DataIn; end if; end if; end if; end process; end Behavioral; and LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY TB_RAM IS END TB_RAM; ARCHITECTURE behavior OF TB_RAM IS COMPONENT RAM Generic ( DATA_WIDTH : integer := 8; ADDRESS_WIDTH : integer := 5 ); PORT( Clock : IN std_logic; Reset : IN std_logic; DataIn : IN std_logic_vector(DATA_WIDTH-1 downto 0); Address : IN std_logic_vector(ADDRESS_WIDTH-1 downto 0); WriteEn : IN std_logic; Enable : IN std_logic; DataOut : OUT std_logic_vector(DATA_WIDTH-1 downto 0) ); END COMPONENT; --Inputs signal Clock : std_logic := '0'; signal Reset : std_logic := '1'; signal DataIn : std_logic_vector(7 downto 0) := (others => '0'); signal Address : std_logic_vector(4 downto 0) := (others => '0'); signal WriteEn : std_logic := '0'; signal Enable : std_logic := '0'; --Outputs signal DataOut : std_logic_vector(7 downto 0); -- Clock period definitions constant CLK_period : time := 10 ns; BEGIN -- Instantiate the Unit Under Test (UUT) uut : RAM Generic map ( DATA_WIDTH => datain'length, ADDRESS_WIDTH => address'length ) PORT MAP ( Clock => Clock, Reset => Reset, DataIn => DataIn, Address => Address, WriteEn => WriteEn, Enable => Enable, DataOut => DataOut ); -- Clock process definitions CLK_process : process begin Clock <= '0'; wait for CLK_period/2; Clock <= '1'; wait for CLK_period/2; end process; -- Stimulate Write process stim_write_read : process begin -- write wait for CLK_period * 1; Address <= "00000"; Reset <= '0'; for i in 0 to 2 loop WriteEn <= '1'; Enable <= '1'; wait for CLK_period * 1; Address <= Address + 4; DataIn <= DataIn + 3; end loop; -- read Address <= "00000"; for k in 0 to 2 loop WriteEn <= '0'; Enable <= '1'; wait for CLK_period * 1; Address <= Address + 4; end loop; Enable <= '1'; wait; end process; end;
  7. hamster

    how to define constraint

    Yep - like Alex says - you just need to add the index to the name of the signal: set_property -dict { PACKAGE_PIN V12 IOSTANDARD LVCMOS33 } [get_ports { gpio2_io_o[0] }]; set_property -dict { PACKAGE_PIN some_other_pin IOSTANDARD LVCMOS33 } [get_ports { gpio2_io_o[1] }]; ... set_property -dict { PACKAGE_PIN some_other_pin IOSTANDARD LVCMOS33 } [get_ports { gpio2_io_o[7] }];
  8. Hi. I've replaced my Cubieboard with a Raspberry Pi 3, and it runs the ARM version of Waveforms really well. With an Electronics Explorer everything works sweet. With the AD2, it complains about supply and/or AUX voltage, even with a 5V 3A power pack attached (The power supply panel indicates that the AUX supply is present so I know it is working well). The USB voltage usually shows as 4.92V at a few 10s of mAs I've tried with 2.5A USB PSU => Pi3 => Powered Hub => AD2, as well as 2.5A USB PSU => Pi3 => AD2. I also get a "unsufficent power". I've tried a few different USB cables too. The USB 2.0 spec, according to Wikipedia is 5V +/- 0.25V, so anything above 4.75V should be possible. Is there any hints? If I wanted to make a USB dummy load and test the voltage drop, what specs should I be checking for?
  9. If you suggest one, and we'll make it better together? there is actually quiet a bit that could be tested. Writing & reading the same address at the same time, or reading the address the cycle after it is written,, with/without write enable set, does read enable work correctly... Do you have any sort of a test plan drawn up, detailing what you want to test?
  10. Duty cycle isn't that important (it has to be between 45% and 55%) , but it has to be perfect integer ratio between MCLK and the other signals. You might be able to run the PMOD with internal clocking mode - SCLK isn't actively driven, just tie it high. That might allow you to use a perfect integer MCLK. Have a look at 4.2.2 in the datasheet. If you don't make any headway, I could try configuring my design for an internal serial clock.
  11. I'll get you a trace tonight if I can. The master clock isn't too important. It can be anything from 0.5 MHz to 50 MHz, but of course most of these will not give "industry standard" sample rates. I've been using it on a few different boards, including the Basys3. Also, be careful to check your pin assignments. For a while the schematic and PMOD reference manual didn't agree on pin ordering (the schematic was correct). All of the signals must be an integer ratio of mclk - i.e. you can't have 256.001 mclk ticks per frame. So if you see the phase of the LR or SDIN changing with respect to the MCLK then it won't work.
  12. Hi TJ Your code is 99% of the way there. Here's the last 1% that I can see. - I am not sure that you need "we" and "re" on your sensitivity list. I would reformat the code with nested 'if's. e.g.: mem_read : process (clk_out) begin if clk_out'event and clk_out = '1' then if re = '1' then data_out <= mem( conv_integer( addr_out)) ; end if ; end if ; end process read; - There is a more subtle problem. As the read and write is split over two different processes, there is a bit of flexibility in which occurs first and which occurs second. I don't know the full semantics of this (do both processes get run, then the updates occur? or do they individually run and update, with flexibility as to who gets to run first). Seems to be a perfect place for some undefined behavior to occur, causing a simulation / synthesis miss-match. I would recommend that you fix this by putting everything in one process. - You really want to initialize the contents of your memory array, otherwise simulation will not match what occurs in the FPGA. signal mem : mem_type := (others => (others => '0'));
  13. I have sound out of my PMOD I2S, but on an FPGA. Is there anything I can give you to help you with your design (scope traces, timing info...)? What tools to you have at hand to help debug? If you are really stuck, a $10 logic analyser (e.g. http://www.dx.com/p/logic-analyzer-w-dupont-lines-and-usb-cable-for-scm-black-148945 ) will solve this for you. But if you can at all afford it, get yourself a true Saleae from https://www.saleae.com/ - they rock. Mike
  14. Hi TJ, You have at least two ways you can do this. 1) If the count is zero, then set the "underflow" flag. This is pretty obvious, but not very efficient. if rising_edge(clk) then if counter = 0 then underflow <= '1'; else underflow <= '0'; end if; counter <= counter - 1; end if; 2) Make the counter one bit longer than needed, use the top-most bit as an underflow, and don't feed the top bit into the decrement operation. Option 2 requires a bit more explanation. For a four-bit counter you will need five bits of state. 00010 - 1 = 00001 (No underflow, and a count of 0001) 00001 - 1 = 00000 (No underflow, and a count of 0000) 00000 - 1 = 11111 (underflow, and a count of 1111) 01111 - 1 = 01110 (no underflow, and a count of 1110) Note how on the last one, the MSB is forced to zero. In VHDL this is how I would do it: if rising_edge(clk) then -- Drop the high bit of the counter - it is used to detect underflow counter <= ('0' & counter(counter'high-1 downto 0)) - 1; end if; This is much more efficient as the logic in the FPGA has been optimized for implementing addition and subtraction, Does that make sense?
  15. hamster

    8 bit even parity check

    It looks fine - however a few questions 1) Did you mean to spell "parity" as "pairity"? 2) Why do you have the three 'use' statements - only one is really needed? 3) Only the upper bit of 'b' needs to be assigned in the process. If you assign "b(n-1 downto 0) <= a;" you can remove the 'temp2' variable. Mike
  16. It could, but it might be a bit of an overkill. If you have the option, maybe use something like the the Arduino ESP8266 to reprogram the ESP8266 module to handle the bulk of the communication protocol for you (e.g connecting to the WiFi network, opening the socket and error recovery)
  17. hamster

    VHDL RAM example

    Oh, if you want to get swamped with info, have a look at http://www.xilinx.com/support/documentation/sw_manuals/xilinx2014_1/ug901-vivado-synthesis.pdf from about page 97. It has examples on how to infer everything from single port ROMs to True Dual-Port Asymmetric Ram Write First RAMs in VHDL....
  18. hamster

    VHDL RAM example

    Have a look at http://hamsterworks.co.nz/mediawiki/index.php/MIC_and_AMP#delay_buffer.vhd Maybe it will help...
  19. hamster

    7 segment display

    The reference manual / wiki pages for the board has this detail. However you could map the switches through to the segments and have a play... That should only take a few minutes to map them all out
  20. hamster

    7 segment display

    Hi You should be able to find this elsewhere, but here is the simple overview. You need the following constraints: NET "sevenseg<0>" LOC = "L14"; NET "sevenseg<1>" LOC = "H12"; NET "sevenseg<2>" LOC = "N14"; NET "sevenseg<3>" LOC = "N11"; NET "sevenseg<4>" LOC = "P12"; NET "sevenseg<5>" LOC = "L13"; NET "sevenseg<6>" LOC = "M12"; NET "dp" LOC = "N13"; NET "anodes<3>" LOC = "K14"; NET "anodes<2>" LOC = "M13"; NET "anodes<1>" LOC = "J12"; NET "anodes<0>" LOC = "F12"; And then you need the appropriate top-level ports in your design: anodes : out std_logic_vector(3 downto 0); sevenseg : out std_logic_vector(6 downto 0); dp : out std_logic; So to select a digit you need to drive one bit of anodes low, and leave the rest high, e.g. anodes <= "1110"; or anodes <= "1101"; That 'enables' the corrosponding digit of the display. You then need to set sevenseg and dp (the decimal point) to light the segments you want to see. eg sevenseg <= "1111111"; ... will light all segments (display the number 8) and maybe "1111101" might display zero (if bit 2 is the center segment). sevenseg <= "0000000" Will turn off all segments on the active display. If you want to display more than one digit on the display, you need to use clocked logic that enables one digit at a time and sets 'segment' to display the correct set of LEDs. For it to work nicely each digit needs to be shown for about 1/400th of a second.
  21. Hi, This might be a long answer...... The main clock 'clk' ticks at 100MHz - a period of 10ns, with 5.000 ns high, 5.000 ns low The MMCM's VCO ticks at 7x this = 700MHz, a period of 1.4ns, with 0.715ns high and 0.715ns low. The derived clock 'mclk' runs at 700MHz / 57 = 12.281 MHz, a period of 81.43 ns, with 40.715ns high and 40.715ns low The code as you have it needs timing of 0.715ns (the time difference between the 40.715ns changes in mclk and four ticks of the 10ns main clock. To do this requires logic that runs at at least 1.4GHz to work properly, so it fails timing. So how to make it work... You shouldn't be using "mclk" as though it it is a logical signal - it's a clock. What you want to do is toggle a single bit in the mclk domain, and then sample that into the clk domain: // flip mclk_toggle every cycle always@(posedge(mclk)) begin mclk_toggle <= !mclk_toggle; end // sample mclk_toggle and add a two-stage synchronizer, followed with an edge detector.. always@(posedge(clk)) begin if(toggle_safe_last & !toggle_safe_last) mclk_count <= mclk_count + 1; toggle_safe_last <= toggle_safe toggle_safe <= toggle_almost_safe; toggle_almost_safe <= toggle_unsafe; toggle_unsafe <= mclk_toggle; end So now you face three issues: Issue 1) the incrementing of mclk_count lags a few cycles (5 or 6? - calculating this makes my head hurt!) cycles from when the edge of mclk actually occurs. This might not be a problem for you. However, if you add a few more cycles of delay you can delay it 9 cycles (or 90 to 100ns) - into the next tick of mclk, but as mclk_toggle is ticking like clockwork this looks as though mclk_count increments sometime between 90ns - 81.43ns = 8.5ns and 100ns - 81.43ns = 18.5ns or after mclk changes. This might be of help. Issue 2) You still have a timing failure between 'toggle_unsafe' and 'mclk_toggle', as it is still required to meet the 1.43 ns timing caused by running Vco at 700MHz. Because this is by design a safe clock domain crossing you might need to add a "timing ignore" constraint. See page 93 of http://www.xilinx.com/support/documentation/sw_manuals/xilinx2014_1/ug903-vivado-using-constraints.pdf for how to do this. Issue 3) You need to set "async_reg" attribute for toggle_unsafe and toggle_almost_safe to ensure that the tools implement it properly - see page 37 of http://www.xilinx.com/support/documentation/sw_manuals/xilinx2013_2/ug901-vivado-synthesis.pdf An easier solution One simpler way might be to run 'clk' at a frequency that is more compatible with that of mclk. Consider if you generate a new clock of 700MHz/9 = 77.77MHz, then one clock would be 700/9, and the other is 700/57, The timing window is the VCO frequency divided by greatest common factor for the two numerators - GCD(9, 57) = 3. This gives a timing constraint of about 1000/700*3 = 4.28ns, and the timing requirement would be 6 times longer than what it is now. That should easily make timing without any special effort. The correct solution? What is going on here feels wrong. The better solution might be to put a small dual-clock FIFO between the two domains, and have the slower domain read or write data every cycle (depending on if the slower domain is the producer or consumer) and have the faster domain only read or write to/from the FIFO when it needs to .(e.g when 'full' is not asserted).
  22. Looking at http://www.xilinx.com/products/design-tools/vivado/vivado-webpack.html it seems the recently released HL Webpack includes all the features of the Design Edition, and the whole Artix-7 is supported by Vivado Webpack, You should be good to go!
  23. I'm also running Vivado 2015.4 a ) For board files, have a look at https://reference.digilentinc.com/vivado:boardfiles2015 b ) I don't use a board file - I just use xc7a35tcpq236-1 for the "project part". It works for me. If you don't have that part number in the database you might have not installed support for the Artix-7 devices.
  24. hamster

    Microblaze frequency

    It looks like the complexity of the design is such that it won't run at 200 MHz on the class of FPGA you are using. If you implement it at 100 MHz look at how much positive slack you have, you should be able to reduce the clock period by at least that much and try again. e.g. if you have 2ns of slack when targeting a 100 MHz (10ns period) clock, you should be able to make it work at 125MHz (10ns - 2ns = 8ns period). You can do this a few times, until you only just meet timing. The only downside is that you can find yourself balanced on a knife-edge - a small change in the design might cause it to fail timing and error out again.
  25. I got a bit bored yesterday, and hooked the PMODmic3 up to my PMODamp3 design, and put a small delay (of 32768 samples). The VHDL module for the microphone interface is actually surprisingly small : ---------------------------------------------------------------------------------- -- Engineer: Mike Field <hamster@snap.net.nz> -- -- Module Name: pmod_mic3 - Behavioral -- -- Description: Sample input form a PMOD_MIC3, once every 256 ticks of the -- master clock (mclk). ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity pmod_mic3 is Port ( mclk : in STD_LOGIC; sclk : out STD_LOGIC; cs : out STD_LOGIC; sdat : in STD_LOGIC; de : out STD_LOGIC; sample : out STD_LOGIC_VECTOR (15 downto 0) := (others => '0')); end pmod_mic3; architecture Behavioral of pmod_mic3 is signal counter : unsigned(7 downto 0) := (others => '0'); signal data_sr : std_logic_vector(11 downto 0) := (others => '0'); begin process(mclk) begin if rising_edge(mclk) then de <= '0'; if counter > 5 and counter < 6 + 16*8 then cs <= '0'; else cs <= '1'; end if; if counter(2 downto 0) = 0 then data_sr <= data_sr(10 downto 0) & sdat; end if; if counter = 17 * 8 then --------------------------------------------- -- convert the 12-bit unsigned sample to the -- lowest 12 bits of a 16-bit signed sample -- by adding it to -2048 --------------------------------------------- de <= '1'; sample <= std_logic_vector(to_unsigned(63488,16) + unsigned(data_sr)); end if; sclk <= std_logic(counter(2)); counter <= counter + 1; end if; end process; end Behavioral; If interested, the rest of the code is at http://hamsterworks.co.nz/mediawiki/index.php/MIC_and_AMP