Jump to content

hamster

Members
  • Posts

    548
  • Joined

  • Last visited

Posts posted by hamster

  1. 26 minutes ago, zygot said:

    Mull over your sine LUT. BTW, why did you replicate 2 cycles instead of just using 1 in your LUT?

     

    Because I am quite happy to use a whole block of RAM rather than debugging indexing and sign-flipping code... :D It's actually one full cycle (half positive, half negative). It is jsut a column from a Google docs spreadsheet https://docs.google.com/spreadsheets/d/13srKHRNCD2dfbMglMvvCUESHR23kHWlzAJ24MJ_erzc/edit?usp=sharing

    I could have also got away with just one quadrant, but then it would be more 'active' code on what I'm not interested in playing with

  2. 7 hours ago, zygot said:

    I glanced at your code.

    The lines like this one bother me: new_val := dac1_accum + sample - 2048;

    I wonder how Vivado implemented this. Usually, in my experience a better way to do this is to pipeline so that each '+' operation is performed on a separate pipeline version of the signal. From a coding viewpoint it appears to be straightforward. From an implementation viewpoint it looks like you have in implied latch, at least. Regardless, you are trying to perform 2 add or one add and 1 subtract in a clock cycle. Even for a quick prototype exercise this isn't a good idea. Sometimes our HDL code gets written by the parts of our brain wired for C. It's dangerous.

    I can't see the latching issues, but agree that if the +/-2048 was a separate signal, then the code could be simplified quite a bit... however, the optimizer should be doing that at the moment. "Premature optimization is the root of all evil" and so on.

    One other finer point. As currently written +full scale value will generate a stream of all ones output but a -full scale won't generate all zero outputs, but a zero value gives a perfect 50:50 mix of ones and zeros.

    Others might need it that -full scale gives all zeros, and +full scale gives all ones, but a zero value will give slightly more zeros than ones.

     

  3. BASYS3 + PMOD Breadboard + Analog Discovery 2.

    It was just a hack, so the table was a quick formula in a spreadsheet, yes, I assume the + and - sides are both rounding towards zero causing some asymmetry, but with 11 significant bits that should be somewherere about -60dB at a guess.

    Most of the noise is just the shoddy physical implementation. Flying wires on a breadboard, on PMODs, just the shielded wires on the AD2 and so on.  If I leave a wire hanging around  it will pick up most the noise too, maybe 6dB lower than on the channel that is under measurement.

    This was just a quick experiment, just using the 100MHz clock rate. If I use a slower clock (e.g. update only every 8 cycles so 12.5MHz) the noise floor actually drops a lot..

    Also using the AD2 on a different laptop to the one programming/powering the FPGA removes a lot of noise too. I assume that this is due to voltage drops and noise on the USB cables.

    Plenty of room for experimentation and improvement.

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

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

  6. 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;
    

     

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

  8. If I get a chance I'll simulate it this weekend.... but chances are that it is the mismatch of the DAC output impedance and the speaker impedance. The speaker is 4 ohm, and the DAC is for driving 10k ohm loads. Have you got some powered speakers you can test with?

    For an un-amplifed speaker you might want to use PMOD-AMP3 ( http://store.digilentinc.com/pmodamp3-stereo-power-amplifier ) which is also I2S. As it is a bridged class-D amplifier you can't connect a PMOD-AMP3 to an external power amp but it is ideally suited to to the 4 ohm speaker.

    Also, sending the clock directly to a pin isn't best practices (but should work for this application). Have a look for "clock forwarding" in http://www.xilinx.com/support/documentation/user_guides/ug471_7Series_SelectIO.pdf at around page 128.

  9. 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?

     

×
×
  • Create New...