hamster

Members
  • Content Count

    500
  • Joined

  • Last visited

  • Days Won

    79

hamster last won the day on August 2

hamster had the most liked content!

About hamster

  • Rank
    Overly helpful
  • Birthday 08/23/1969

Contact Methods

  • Website URL
    http://hamsterworks.co.nz

Profile Information

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

Recent Profile Visitors

5960 profile views
  1. Maybe remove the 'reg' from the Verilog port definition?
  2. I've done it before without issue, and all I can suggest is that you look carefully at your component/module names and especially uppercase / lowercase. Maybe add some code snippets to the thread?
  3. The Vivado virtual logic analyser is very easy to set up and use, and will give you the most accurate result for minimal effort
  4. This little project might give you some ideas - it controls the speed of the dev board's fan based on the XADC reading. It also uses no IP blocks so everything is exposed. http://hamsterworks.co.nz/mediawiki/index.php/XADC_Fan_PWM
  5. As a gross oversimplification, FPGAs only have clocked flipflops that can store state information. You can use variables to store state rather than signals, but they have to be used in such a way that they can be mapped down to flipflops. Without using a clock edge in the HDL code this can't happen, and all sorts of weird stuff happens.
  6. Hi again, Changed the XDC file, and to run it on a board - it didn't work for me either. There are a few synthesis issues that need to be addressed (both of which were pointed out as warning in the logs, BTW): 1. input needs to be added on this process's sensitivity list: process(present_state,data,clk,rst,start, input) 2. The major problem - you are updating count and index_reg inside the async process: count:=count+1; and index:=index+1; You can't do this, as conceptually the process is "run" each time any of the input signals change state. If you want to work with the similar structure you need to assign count_next and index_next inside the async process, then assign them to count and index in the clocked one. Oh, and another tiny issue - if you want to do something every 10400 cycles, you need to count from 0 to 10399.
  7. Looking at the reference manual, if you intend to use the onboard USB to serial Bridge then your output pin should be A18 https://reference.digilentinc.com/basys3/refmanual
  8. I wrote a quick test bench. I couldn''t get it out of 'idle' state because of this code: if start='1' and rst='0' then count:=count+1; if count=clk_max then next_state<=start_state; count:=0; end if; end if; I asserted 'start' for only one cycle, and nothing happened. I see now that I need to assert it for up to 10,400 cycles before it will send data. Will let you know how testing progresses. Also, the async reset is a slightly unusual design pattern for FPGA designs. Synchronous resets (with a properly synchronised reset signal) work better. Here is the test bench so far. library IEEE; use IEEE.STD_LOGIC_1164.ALL; entity tb is end tb; architecture Behavioral of tb is component rs232_omo is generic(clk_max:integer:=10400); --for baudrate port( clk : in std_logic; rst : in std_logic; start : in std_logic; input : in std_logic_vector(7 downto 0); done : out std_logic; output : out std_logic; showstates : out std_logic_vector(3 downto 0) ); end component ; signal clk : std_logic; signal rst : std_logic := '0'; signal start : std_logic := '0'; signal input : std_logic_vector(7 downto 0) := x"55"; signal done : std_logic; signal output : std_logic; signal showstates : std_logic_vector(3 downto 0); begin process begin clk <= '0'; wait for 5ns; clk <= '1'; wait for 5ns; end process; process begin wait for 100ns; rst <= '1'; wait for 20ns; rst <= '0'; wait for 100ns; start <= '1'; wait for 10ns; start <= '0'; wait; end process; uut: rs232_omo generic map (clk_max => 10400) port map( clk => clk, rst => rst, start => start, input => input, done => done, output => output, showstates => showstates ); end Behavioral;
  9. I haven't looks at the code too much, but I did notice that you don't appear to have synchronizers on your external connections that control the state machine (start and reset). Although this is most likely not your problem it will cause inconsistent behaviour. Are you also sure you haven't got the Tx/Rx pins back to front, as naming depends on the designer perspective and whims on the day
  10. The error is because the magnitude as to be one bit longer than the inputs, (as the magnitude of (0xFFFFFF, 0xFFFFFF) is 0x16A09E4, which will overflow if you put it into a 25-bit signed value. It will however fit nicely into a 25-bit unsigned value, and as it is a magnitude it will be positive. So maybe snip off the top bit in the assignment, but remember it is unsigned!
  11. Using a tool for what it is meant to do is easy. Using a tool for something where it isn't suited, that is where the learning begins! (I now goes back to doing dental surgery with a steamroller, or maybe digging a tunnel with a teaspoon).
  12. Oh, a quick hack of a CORDIC magnitude library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity magnitude is Port ( clk : in std_logic; x_in : in std_logic_vector; y_in : in std_logic_vector; x_out : out std_logic_vector := (others => '0'); y_out : out std_logic_vector := (others => '0'); magnitude_out : out std_logic_vector := (others => '0') -- Accurate to 5 bits or so ); end magnitude; architecture Behavioral of magnitude is type a_x is array(0 to 5) of signed(x_in'high+1 downto 0); type a_y is array(0 to 5) of signed(y_in'high+1 downto 0); type a_x_delay is array(0 to 5) of std_logic_vector(x_in'high downto 0); type a_y_delay is array(0 to 5) of std_logic_vector(y_in'high downto 0); signal x : a_x := (others => (others => '0')); signal y : a_y := (others => (others => '0')); signal x_delay : a_x_delay := (others => (others => '0')); signal y_delay : a_y_delay := (others => (others => '0')); begin magnitude_out <= std_logic_vector(y(5)); x_out <= x_delay(x_delay'high); y_out <= y_delay(y_delay'high); process(clk) begin if rising_edge(clk) then if x(4) >= 0 then -- x(5) is not needed y(5) <= y(4) + x(4)(x(4)'high downto 4); else -- x(5) is not needed y(5) <= y(4) - x(4)(x(4)'high downto 4); end if; if x(3) >= 0 then x(4) <= x(3) - y(3)(y(3)'high downto 3); y(4) <= y(3) + x(3)(x(3)'high downto 3); else x(4) <= x(3) + y(3)(y(3)'high downto 3); y(4) <= y(3) - x(3)(x(3)'high downto 3); end if; if x(2) >= 0 then x(3) <= x(2) - y(2)(y(2)'high downto 2); y(3) <= y(2) + x(2)(x(2)'high downto 2); else x(3) <= x(2) + y(2)(y(2)'high downto 2); y(3) <= y(2) - x(2)(x(2)'high downto 2); end if; if x(1) >= 0 then x(2) <= x(1) - y(1)(y(1)'high downto 1); y(2) <= y(1) + x(1)(x(1)'high downto 1); else x(2) <= x(1) + y(1)(y(1)'high downto 1); y(2) <= y(1) - x(1)(x(1)'high downto 1); end if; if x(0) >= 0 then x(1) <= x(0) - y(0)(y(0)'high downto 0); y(1) <= y(0) + x(0)(x(0)'high downto 0); else x(1) <= x(0) + y(0)(y(0)'high downto 0); y(1) <= y(0) - x(0)(x(0)'high downto 0); end if; if y_in(y_in'high) = '1' then x(0) <= signed(x_in(x_in'high) & x_in); y(0) <= signed(to_signed(0,y_in'length+1)-signed(y_in)); else x(0) <= signed(x_in(x_in'high) & x_in); y(0) <= signed(y_in(y_in'high) & y_in); end if; -- Delay to output the inputs, so they are aligned with the magnitudes x_delay(1 to 5) <= x_delay(0 to 4); y_delay(1 to 5) <= y_delay(0 to 4); x_delay(0) <= x_in; y_delay(0) <= y_in; end if; end process; end Behavioral; Chaining the two together, and it seems to work. Top trace is the input, second trace is the delayed input, Third is the delayed output of the Hilbert filter, and the last is the scaled magnitude of the complex x+iy signal. NOTE: I know for sure that these are buggy, as they have range overflows), but they should give the idea of how @Ahmed Alfadhel could be implement it. magnitude.vhd hilbert_transformer.vhd tb_hilbert_transformer.vhd
  13. Going to Incorporate it into my (MCU based) guitar tuner... but it is a nice tool to have in the kit.
  14. I was intrigued enough by the Hilbert Transform to actually learn, experiment and implement it in VHDL. The math behind it is pretty nifty. Here's the very naively implemented example, using a short FIR filter. You can find this, a test bench and simulation output at http://hamsterworks.co.nz/mediawiki/index.php/Hilbert_Transform library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity hilbert_transformer is Port ( clk : in STD_LOGIC; real_in : in STD_LOGIC_VECTOR (9 downto 0); real_out : out STD_LOGIC_VECTOR (10 downto 0) := (others => '0'); imag_out : out STD_LOGIC_VECTOR (10 downto 0) := (others => '0')); end hilbert_transformer; architecture Behavioral of hilbert_transformer is -- Constants are 2/(n * pi) * 512, for n of -7,-5,-3,-1,1,3,5,7 constant kernel0 : signed(real_in'length-1 downto 0) := to_signed( -47, real_in'length); constant kernel2 : signed(real_in'length-1 downto 0) := to_signed( -66, real_in'length); constant kernel4 : signed(real_in'length-1 downto 0) := to_signed(-109, real_in'length); constant kernel6 : signed(real_in'length-1 downto 0) := to_signed(-326, real_in'length); constant kernel8 : signed(real_in'length-1 downto 0) := to_signed( 326, real_in'length); constant kernel10 : signed(real_in'length-1 downto 0) := to_signed( 109, real_in'length); constant kernel12 : signed(real_in'length-1 downto 0) := to_signed( 66, real_in'length); constant kernel14 : signed(real_in'length-1 downto 0) := to_signed( 47, real_in'length); type a_delay is array (0 to 14) of signed(real_in'high downto 0); signal delay : a_delay := (others => (others => '0')); signal tap0 : signed(real_in'length+kernel0'length-1 downto 0) := (others => '0'); signal tap2 : signed(real_in'length+kernel2'length-1 downto 0) := (others => '0'); signal tap4 : signed(real_in'length+kernel4'length-1 downto 0) := (others => '0'); signal tap6 : signed(real_in'length+kernel6'length-1 downto 0) := (others => '0'); signal tap8 : signed(real_in'length+kernel8'length-1 downto 0) := (others => '0'); signal tap10 : signed(real_in'length+kernel10'length-1 downto 0) := (others => '0'); signal tap12 : signed(real_in'length+kernel12'length-1 downto 0) := (others => '0'); signal tap14 : signed(real_in'length+kernel14'length-1 downto 0) := (others => '0'); begin process(clk) variable imag_tmp : signed(real_in'length*2-1 downto 0); begin if rising_edge(clk) then real_out <= std_logic_vector(resize(delay(8),real_out'length)); -- deliberatly advanced by one due to latency imag_tmp := tap0 + tap2 + tap4 + tap6 + tap8 + tap10 + tap12 + tap14; imag_out <= std_logic_vector(imag_tmp(imag_tmp'high downto imag_tmp'high-imag_out'high)); tap0 <= delay(0) * kernel0; tap2 <= delay(2) * kernel2; tap4 <= delay(4) * kernel4; tap6 <= delay(6) * kernel6; tap8 <= delay(8) * kernel8; tap10 <= delay(10) * kernel10; tap12 <= delay(12) * kernel12; tap14 <= delay(14) * kernel14; -- Update the delay line delay(1 to 14) <= delay(0 to 13) ; delay(0) <= signed(real_in); end if; end process; end Behavioral;
  15. Oh, for what it's worth I've been toying with the Hilbert Transform. Here is a example of it; #include <math.h> #include <stdio.h> #define SAMPLES 1000 #define HALF_WIDTH 11 /* e.g. 11 filters from -11 to 11 */ float x[SAMPLES]; int main(int argc, char *argv[]) { int i; /* Build some test data */ for(i = 0; i < SAMPLES; i++) { x[i] = cos(2*M_PI*i/10.3); } /* Now apply the Hilbert Transform and see what we get */ /* It should be close to sin(2*M_PI*i/10.3) */ for(i = HALF_WIDTH; i < SAMPLES-HALF_WIDTH-1; i++) { double h = 0; int j; /* Apply the kernel */ for(j = 1; j <= HALF_WIDTH; j+=2) h += (x[i-j]-x[i+j]) * 2.0/(j*M_PI); /* Print result */ printf("%8.5f, %8.5f\n", x[i], h); } }