Digital Sine

From Hamsterworks Wiki!

Jump to: navigation, search

This FPGA Project was completed in May 2015.

I'm oorking on a relatively big project (for me) and one one of the components needed is a high resolution DAC. I've been experimenting with a Digilent PMOD DA3, which is a 16-bit DAC that runs at up to 3M samples per second.

I've set the project up to output a new sample every 76 cycles of the 100MHz clock (1,315,789 HZ) and using a 18-bit phase accumulator it allows me to generate sine waves from 5.019 Hz to 328.942 kHz in 5.019 Hz steps. The high 10 bits of an 18 bit phase accumulator indexes to look into a 4096 entry 18-bit wide lookup table, and then samples are interpolated with the remaining 8 bits of the phase accumulator.

The results look pretty good.

Digit sine slow.jpg

The DAC doesn't have an reconstruction filter on it, so at higher frequencies the 0.760us between different samples can be clearly seen.

Digit sine fast.jpg

Rather than building a filter, turning on the DSP filter on my oscilloscope and tuning down to 750MHz (approx half the sample rate) tidies things up, showing what is possible:

Digit sine fast filtered.jpg

Contents

Source files

pmod_da3_test.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net/nz>
-- 
-- File Name : pmod_da3_test.vhd
--
-- Description: Generate Sine Waves between 5.014Hz and 328,621 Hz in 5.014Hz 
--              steps.
-- 
-- Exact Output Freqency = is DAC output rate / 262,144 * value on switches.
--
-- In this case DAC output rate is every 76 clocks, or 1.315,789 MHz.
--
----------------------------------------------------------------------------------


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity pmod_da3_test is
    Port ( clk      : in STD_LOGIC;
           CSn      : out STD_LOGIC;
           LDACn    : out STD_LOGIC;
           SCLK     : out STD_LOGIC;
           SDAT     : out STD_LOGIC;
           sw       : in  std_logic_vector(15 downto 0));
end pmod_da3_test;

architecture Behavioral of pmod_da3_test is
    component pmod_da3 is
    Port ( clk        : in STD_LOGIC;
           CSn        : out STD_LOGIC;
           LDACn      : out STD_LOGIC;
           SCLK       : out STD_LOGIC;
           SDAT       : out STD_LOGIC;
           data_taken : out STD_LOGIC;
           level      : in STD_LOGIC_VECTOR (15 downto 0));
    end component;

    component sine_table is
        Port ( clk : in STD_LOGIC;
               phase : in STD_LOGIC_VECTOR (17 downto 0);
               sine : out STD_LOGIC_VECTOR (19 downto 0));
    end component;
    
    signal counter    : unsigned(17 downto 0) := (others => '0');
    signal level      : STD_LOGIC_VECTOR (19 downto 0);
    signal phase      : STD_LOGIC_VECTOR (17 downto 0);
    signal sw_synced  : unsigned(15 downto 0) := (others => '0');
    signal data_taken : std_logic;
begin
    phase <= std_logic_vector(counter);

clk_proc: process(clk)
    begin
        if rising_edge(clk) then
            if data_taken = '1' then
                counter   <= counter + sw_synced;
                sw_synced <= unsigned(sw);
            end if;
        end if;
    end process;

i_sine_table : sine_table port map (
        clk   => clk,
        phase => phase,
        sine  => level);

i_pmod_da3: pmod_da3 port map (
           clk   => clk,
           CSn   => CSn,
           LDACn => LDACn,
           SCLK  => SCLK,
           SDAT  => SDAT,
           data_taken => data_taken, 
           level => level(level'high downto level'high-15));


end Behavioral;

pmod_da3.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz> 
-- 
-- A simple inteface for the PMOD DA3, a 16 bit DAC.
-- 
-- SCLK runs at 1/4th the rate of 'clk'.
--
-- Strobes 'data_taken' and then sends the value to the serial DAC, taking 19
-- Cycles of SCLK (or 76 cycles of 'clk').
--
-- Running at 100MHz it updates the output at 1,315,789 Hz
-- If you change 'len' to 20, it will update at 1.25 MHz.
--
-- This odd speed is important for this project, as 1,315,789 / (2^18) is 
-- 5.019Hz (within 0.4% of 1.25Hz)
--
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity pmod_da3 is
    Port ( clk        : in STD_LOGIC;
           CSn        : out STD_LOGIC;
           LDACn      : out STD_LOGIC;
           SCLK       : out STD_LOGIC;
           SDAT       : out STD_LOGIC;
           data_taken : out STD_LOGIC := '0';
           level      : in STD_LOGIC_VECTOR (15 downto 0));
end pmod_da3;

architecture Behavioral of pmod_da3 is
    constant len           : integer := 19;
    signal CSn_shift_reg   : std_logic_vector(len-1 downto 0) := (len-17 downto 0 => '1', others => '0');
    signal LDACn_shift_reg : std_logic_vector(len-1 downto 0) := (1 => '0', others => '1');
    signal SDAT_shift_reg  : std_logic_vector(len-1 downto 0) := (others => '0');
    signal sclk_state      : std_logic_vector(1 downto 0)  := "00";
begin
    SCLK  <= sclk_state(1);
    LDACn <= LDACn_shift_reg(0);
    CSn   <= CSn_shift_reg(0);

clk_proc: process(clk)
    begin
        if rising_edge(clk) then
            data_taken <= '0';
            case sclk_state is 
                when "00" =>   sclk_state <= "01";
                                -- Mpve the shift regeister along
                               SDAT  <= SDAT_shift_reg(SDAT_shift_reg'high);
                               SDAT_shift_reg  <= SDAT_shift_reg(len-2 downto 0)  & 'X';
                               LDACn_shift_reg <= LDACn_shift_reg(len-2 downto 0) & LDACn_shift_reg(len-1);
                               if LDACn_shift_reg(1) = '0' then
                                  SDAT_shift_reg(SDAT_shift_reg'high downto SDAT_shift_reg'high-level'high) <= level;
                                  data_taken <= '1';
                               end if;
                when "01" =>   sclk_state <= "10";
                when "10" =>   sclk_state <= "11";
                               CSn_shift_reg   <= CSn_shift_reg(len-2 downto 0)   & CSn_shift_reg(len-1);
                when others => sclk_state <= "00";
            end case;
        end if;
    end process;
end Behavioral;

sine_table.vhd

----------------------------------------------------------------------------------
-- Engineer: Mike Field <hamster@snap.net.nz>
-- 
-- Module Name: sine_table - Behavioral
-- Description: A lookup table with interpolation for sin(x) function
-- 
-- To help with the coding, this actually returns sin(x+2*pi/8192)
-- subtract 0x70 from 'pahse' to keep the zero crossing at zero.  
----------------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity sine_table is
    Port ( clk : in STD_LOGIC;
           phase : in STD_LOGIC_VECTOR (17 downto 0);
           sine : out STD_LOGIC_VECTOR (19 downto 0));
end sine_table;

architecture Behavioral of sine_table is
    signal sine_sum    : unsigned(9+phase'high downto 0) := (others => '0');
    
    signal sine_mult_1 : unsigned(9+phase'high downto 0)  := (others => '0');
    signal frac_1      : unsigned(phase'high-11 downto 0) := (others => '0');
    signal sine_1      : unsigned(19 downto 0)            := (others => '0');
    signal index_1     : unsigned(11 downto 0)            := (others => '0');
    signal quad_1      : unsigned( 1 downto 0)            := (others => '0');
    signal entry_1     : unsigned( 9 downto 0)            := (others => '0');

    signal sine_mult_2 : unsigned(9+phase'high downto 0) := (others => '0');
    signal frac_2      : unsigned(phase'high-11 downto 0) := (others => '0');
    signal sine_2      : unsigned(19 downto 0)            := (others => '0');
    signal quad_2      : unsigned(1 downto 0)             := (others => '0');
    signal entry_2     : unsigned(9 downto 0)             := (others => '0');
    signal index_2     : unsigned(11 downto 0)            := (others => '0');

    signal frac        : unsigned(phase'high-12 downto 0);

    constant frac_max  : unsigned(phase'high-11 downto 0) := (phase'high-11 => '1', others => '0');
    constant table_max : unsigned(9 downto 0)  := (others => '1');
    constant midrange  : unsigned(19 downto 0) := x"80000";

    type a_mem is array (0 to 1023) of unsigned (19 downto 0);
    signal mem : a_mem := (
        x"000C9", x"0025B", x"003ED", x"0057F", x"00711", x"008A3", x"00A35", x"00BC7",
        x"00D59", x"00EEC", x"0107E", x"01210", x"013A2", x"01534", x"016C6", x"01858",
        x"019EA", x"01B7C", x"01D0E", x"01EA0", x"02032", x"021C4", x"02355", x"024E7",
        x"02679", x"0280B", x"0299D", x"02B2F", x"02CC0", x"02E52", x"02FE4", x"03175",
        x"03307", x"03499", x"0362A", x"037BC", x"0394D", x"03ADF", x"03C70", x"03E02",
        x"03F93", x"04124", x"042B6", x"04447", x"045D8", x"04769", x"048FA", x"04A8B",
        x"04C1C", x"04DAD", x"04F3E", x"050CF", x"05260", x"053F1", x"05582", x"05712",
        x"058A3", x"05A34", x"05BC4", x"05D55", x"05EE5", x"06075", x"06206", x"06396",
        x"06526", x"066B6", x"06846", x"069D6", x"06B66", x"06CF6", x"06E86", x"07016",
        x"071A5", x"07335", x"074C5", x"07654", x"077E3", x"07973", x"07B02", x"07C91",
        x"07E20", x"07FAF", x"0813E", x"082CD", x"0845C", x"085EB", x"08779", x"08908",
        x"08A96", x"08C25", x"08DB3", x"08F41", x"090CF", x"0925D", x"093EB", x"09579",
        x"09707", x"09894", x"09A22", x"09BB0", x"09D3D", x"09ECA", x"0A057", x"0A1E5",
        x"0A372", x"0A4FF", x"0A68B", x"0A818", x"0A9A5", x"0AB31", x"0ACBE", x"0AE4A",
        x"0AFD6", x"0B162", x"0B2EE", x"0B47A", x"0B606", x"0B792", x"0B91D", x"0BAA9",
        x"0BC34", x"0BDBF", x"0BF4A", x"0C0D5", x"0C260", x"0C3EB", x"0C575", x"0C700",
        x"0C88A", x"0CA15", x"0CB9F", x"0CD29", x"0CEB3", x"0D03C", x"0D1C6", x"0D350",
        x"0D4D9", x"0D662", x"0D7EC", x"0D975", x"0DAFD", x"0DC86", x"0DE0F", x"0DF97",
        x"0E120", x"0E2A8", x"0E430", x"0E5B8", x"0E740", x"0E8C7", x"0EA4F", x"0EBD6",
        x"0ED5D", x"0EEE5", x"0F06C", x"0F1F2", x"0F379", x"0F500", x"0F686", x"0F80C",
        x"0F992", x"0FB18", x"0FC9E", x"0FE24", x"0FFA9", x"1012E", x"102B3", x"10438",
        x"105BD", x"10742", x"108C6", x"10A4B", x"10BCF", x"10D53", x"10ED7", x"1105B",
        x"111DE", x"11362", x"114E5", x"11668", x"117EB", x"1196E", x"11AF0", x"11C73",
        x"11DF5", x"11F77", x"120F9", x"1227A", x"123FC", x"1257D", x"126FE", x"1287F",
        x"12A00", x"12B81", x"12D01", x"12E81", x"13002", x"13181", x"13301", x"13481",
        x"13600", x"1377F", x"138FE", x"13A7D", x"13BFC", x"13D7A", x"13EF8", x"14076",
        x"141F4", x"14372", x"144EF", x"1466C", x"147E9", x"14966", x"14AE3", x"14C5F",
        x"14DDC", x"14F58", x"150D3", x"1524F", x"153CB", x"15546", x"156C1", x"1583C",
        x"159B6", x"15B31", x"15CAB", x"15E25", x"15F9F", x"16118", x"16292", x"1640B",
        x"16584", x"166FC", x"16875", x"169ED", x"16B65", x"16CDD", x"16E55", x"16FCC",
        x"17143", x"172BA", x"17431", x"175A7", x"1771E", x"17894", x"17A0A", x"17B7F",
        x"17CF5", x"17E6A", x"17FDF", x"18153", x"182C8", x"1843C", x"185B0", x"18724",
        x"18897", x"18A0A", x"18B7E", x"18CF0", x"18E63", x"18FD5", x"19147", x"192B9",
        x"1942B", x"1959C", x"1970D", x"1987E", x"199EF", x"19B5F", x"19CCF", x"19E3F",
        x"19FAF", x"1A11E", x"1A28D", x"1A3FC", x"1A56B", x"1A6D9", x"1A847", x"1A9B5",
        x"1AB23", x"1AC90", x"1ADFD", x"1AF6A", x"1B0D6", x"1B243", x"1B3AF", x"1B51B",
        x"1B686", x"1B7F1", x"1B95C", x"1BAC7", x"1BC31", x"1BD9C", x"1BF06", x"1C06F",
        x"1C1D9", x"1C342", x"1C4AA", x"1C613", x"1C77B", x"1C8E3", x"1CA4B", x"1CBB3",
        x"1CD1A", x"1CE81", x"1CFE7", x"1D14E", x"1D2B4", x"1D419", x"1D57F", x"1D6E4",
        x"1D849", x"1D9AE", x"1DB12", x"1DC76", x"1DDDA", x"1DF3E", x"1E0A1", x"1E204",
        x"1E366", x"1E4C9", x"1E62B", x"1E78D", x"1E8EE", x"1EA4F", x"1EBB0", x"1ED11",
        x"1EE71", x"1EFD1", x"1F131", x"1F290", x"1F3EF", x"1F54E", x"1F6AC", x"1F80B",
        x"1F968", x"1FAC6", x"1FC23", x"1FD80", x"1FEDD", x"20039", x"20195", x"202F1",
        x"2044C", x"205A8", x"20702", x"2085D", x"209B7", x"20B11", x"20C6A", x"20DC4",
        x"20F1D", x"21075", x"211CD", x"21325", x"2147D", x"215D4", x"2172B", x"21882",
        x"219D8", x"21B2E", x"21C84", x"21DDA", x"21F2F", x"22083", x"221D8", x"2232C",
        x"2247F", x"225D3", x"22726", x"22879", x"229CB", x"22B1D", x"22C6F", x"22DC0",
        x"22F11", x"23062", x"231B3", x"23303", x"23452", x"235A2", x"236F1", x"2383F",
        x"2398E", x"23ADC", x"23C29", x"23D77", x"23EC4", x"24010", x"2415D", x"242A9",
        x"243F4", x"2453F", x"2468A", x"247D5", x"2491F", x"24A69", x"24BB2", x"24CFB",
        x"24E44", x"24F8D", x"250D5", x"2521C", x"25364", x"254AB", x"255F1", x"25738",
        x"2587E", x"259C3", x"25B08", x"25C4D", x"25D92", x"25ED6", x"26019", x"2615D",
        x"262A0", x"263E2", x"26525", x"26666", x"267A8", x"268E9", x"26A2A", x"26B6A",
        x"26CAA", x"26DEA", x"26F29", x"27068", x"271A7", x"272E5", x"27423", x"27560",
        x"2769D", x"277DA", x"27916", x"27A52", x"27B8D", x"27CC8", x"27E03", x"27F3D",
        x"28077", x"281B1", x"282EA", x"28423", x"2855B", x"28693", x"287CB", x"28902",
        x"28A39", x"28B6F", x"28CA5", x"28DDB", x"28F10", x"29045", x"2917A", x"292AE",
        x"293E2", x"29515", x"29648", x"2977A", x"298AC", x"299DE", x"29B0F", x"29C40",
        x"29D71", x"29EA1", x"29FD0", x"2A100", x"2A22F", x"2A35D", x"2A48B", x"2A5B9",
        x"2A6E6", x"2A813", x"2A93F", x"2AA6B", x"2AB97", x"2ACC2", x"2ADED", x"2AF17",
        x"2B041", x"2B16B", x"2B294", x"2B3BD", x"2B4E5", x"2B60D", x"2B734", x"2B85B",
        x"2B982", x"2BAA8", x"2BBCE", x"2BCF3", x"2BE18", x"2BF3D", x"2C061", x"2C184",
        x"2C2A8", x"2C3CA", x"2C4ED", x"2C60F", x"2C730", x"2C851", x"2C972", x"2CA92",
        x"2CBB2", x"2CCD2", x"2CDF0", x"2CF0F", x"2D02D", x"2D14B", x"2D268", x"2D385",
        x"2D4A1", x"2D5BD", x"2D6D8", x"2D7F3", x"2D90E", x"2DA28", x"2DB42", x"2DC5B",
        x"2DD74", x"2DE8C", x"2DFA4", x"2E0BC", x"2E1D3", x"2E2EA", x"2E400", x"2E515",
        x"2E62B", x"2E740", x"2E854", x"2E968", x"2EA7B", x"2EB8E", x"2ECA1", x"2EDB3",
        x"2EEC5", x"2EFD6", x"2F0E7", x"2F1F7", x"2F307", x"2F416", x"2F525", x"2F634",
        x"2F742", x"2F850", x"2F95D", x"2FA69", x"2FB76", x"2FC81", x"2FD8D", x"2FE97",
        x"2FFA2", x"300AC", x"301B5", x"302BE", x"303C7", x"304CF", x"305D6", x"306DD",
        x"307E4", x"308EA", x"309F0", x"30AF5", x"30BFA", x"30CFE", x"30E02", x"30F06",
        x"31009", x"3110B", x"3120D", x"3130E", x"3140F", x"31510", x"31610", x"31710",
        x"3180F", x"3190D", x"31A0B", x"31B09", x"31C06", x"31D03", x"31DFF", x"31EFB",
        x"31FF6", x"320F1", x"321EB", x"322E5", x"323DF", x"324D7", x"325D0", x"326C8",
        x"327BF", x"328B6", x"329AC", x"32AA2", x"32B98", x"32C8D", x"32D81", x"32E75",
        x"32F69", x"3305C", x"3314E", x"33240", x"33332", x"33423", x"33513", x"33603",
        x"336F3", x"337E2", x"338D0", x"339BF", x"33AAC", x"33B99", x"33C86", x"33D72",
        x"33E5D", x"33F48", x"34033", x"3411D", x"34207", x"342F0", x"343D8", x"344C0",
        x"345A8", x"3468F", x"34775", x"3485B", x"34941", x"34A26", x"34B0A", x"34BEE",
        x"34CD2", x"34DB5", x"34E97", x"34F79", x"3505B", x"3513C", x"3521C", x"352FC",
        x"353DC", x"354BA", x"35599", x"35677", x"35754", x"35831", x"3590D", x"359E9",
        x"35AC4", x"35B9F", x"35C79", x"35D53", x"35E2C", x"35F05", x"35FDD", x"360B5",
        x"3618C", x"36262", x"36339", x"3640E", x"364E3", x"365B8", x"3668C", x"3675F",
        x"36832", x"36905", x"369D6", x"36AA8", x"36B79", x"36C49", x"36D19", x"36DE8",
        x"36EB7", x"36F85", x"37053", x"37120", x"371EC", x"372B8", x"37384", x"3744F",
        x"3751A", x"375E4", x"376AD", x"37776", x"3783E", x"37906", x"379CD", x"37A94",
        x"37B5A", x"37C20", x"37CE5", x"37DAA", x"37E6E", x"37F31", x"37FF4", x"380B7",
        x"38178", x"3823A", x"382FB", x"383BB", x"3847B", x"3853A", x"385F8", x"386B7",
        x"38774", x"38831", x"388EE", x"389AA", x"38A65", x"38B20", x"38BDA", x"38C94",
        x"38D4D", x"38E06", x"38EBE", x"38F75", x"3902C", x"390E3", x"39199", x"3924E",
        x"39303", x"393B7", x"3946B", x"3951E", x"395D0", x"39683", x"39734", x"397E5",
        x"39895", x"39945", x"399F4", x"39AA3", x"39B51", x"39BFF", x"39CAC", x"39D58",
        x"39E04", x"39EB0", x"39F5B", x"3A005", x"3A0AE", x"3A158", x"3A200", x"3A2A8",
        x"3A350", x"3A3F7", x"3A49D", x"3A543", x"3A5E8", x"3A68C", x"3A731", x"3A7D4",
        x"3A877", x"3A919", x"3A9BB", x"3AA5D", x"3AAFD", x"3AB9D", x"3AC3D", x"3ACDC",
        x"3AD7A", x"3AE18", x"3AEB6", x"3AF52", x"3AFEE", x"3B08A", x"3B125", x"3B1C0",
        x"3B259", x"3B2F3", x"3B38B", x"3B424", x"3B4BB", x"3B552", x"3B5E9", x"3B67F",
        x"3B714", x"3B7A9", x"3B83D", x"3B8D0", x"3B963", x"3B9F6", x"3BA88", x"3BB19",
        x"3BBAA", x"3BC3A", x"3BCCA", x"3BD59", x"3BDE7", x"3BE75", x"3BF02", x"3BF8F",
        x"3C01B", x"3C0A6", x"3C131", x"3C1BC", x"3C245", x"3C2CF", x"3C357", x"3C3DF",
        x"3C467", x"3C4EE", x"3C574", x"3C5FA", x"3C67F", x"3C703", x"3C787", x"3C80B",
        x"3C88E", x"3C910", x"3C992", x"3CA13", x"3CA93", x"3CB13", x"3CB92", x"3CC11",
        x"3CC8F", x"3CD0D", x"3CD8A", x"3CE06", x"3CE82", x"3CEFD", x"3CF78", x"3CFF2",
        x"3D06B", x"3D0E4", x"3D15C", x"3D1D4", x"3D24B", x"3D2C2", x"3D337", x"3D3AD",
        x"3D421", x"3D496", x"3D509", x"3D57C", x"3D5EE", x"3D660", x"3D6D1", x"3D742",
        x"3D7B2", x"3D821", x"3D890", x"3D8FE", x"3D96C", x"3D9D9", x"3DA46", x"3DAB1",
        x"3DB1D", x"3DB87", x"3DBF1", x"3DC5B", x"3DCC4", x"3DD2C", x"3DD94", x"3DDFB",
        x"3DE61", x"3DEC7", x"3DF2C", x"3DF91", x"3DFF5", x"3E059", x"3E0BC", x"3E11E",
        x"3E180", x"3E1E1", x"3E241", x"3E2A1", x"3E301", x"3E35F", x"3E3BD", x"3E41B",
        x"3E478", x"3E4D4", x"3E530", x"3E58B", x"3E5E5", x"3E63F", x"3E699", x"3E6F1",
        x"3E749", x"3E7A1", x"3E7F8", x"3E84E", x"3E8A4", x"3E8F9", x"3E94D", x"3E9A1",
        x"3E9F5", x"3EA47", x"3EA99", x"3EAEB", x"3EB3C", x"3EB8C", x"3EBDC", x"3EC2B",
        x"3EC79", x"3ECC7", x"3ED14", x"3ED61", x"3EDAD", x"3EDF8", x"3EE43", x"3EE8D",
        x"3EED7", x"3EF20", x"3EF68", x"3EFB0", x"3EFF7", x"3F03E", x"3F084", x"3F0C9",
        x"3F10E", x"3F152", x"3F196", x"3F1D9", x"3F21B", x"3F25D", x"3F29E", x"3F2DE",
        x"3F31E", x"3F35D", x"3F39C", x"3F3DA", x"3F417", x"3F454", x"3F491", x"3F4CC",
        x"3F507", x"3F542", x"3F57B", x"3F5B4", x"3F5ED", x"3F625", x"3F65C", x"3F693",
        x"3F6C9", x"3F6FF", x"3F734", x"3F768", x"3F79C", x"3F7CF", x"3F801", x"3F833",
        x"3F864", x"3F895", x"3F8C5", x"3F8F4", x"3F923", x"3F951", x"3F97F", x"3F9AC",
        x"3F9D8", x"3FA04", x"3FA2F", x"3FA59", x"3FA83", x"3FAAC", x"3FAD5", x"3FAFD",
        x"3FB24", x"3FB4B", x"3FB71", x"3FB97", x"3FBBC", x"3FBE0", x"3FC04", x"3FC27",
        x"3FC4A", x"3FC6B", x"3FC8D", x"3FCAD", x"3FCCD", x"3FCED", x"3FD0C", x"3FD2A",
        x"3FD47", x"3FD64", x"3FD81", x"3FD9C", x"3FDB8", x"3FDD2", x"3FDEC", x"3FE05",
        x"3FE1E", x"3FE36", x"3FE4D", x"3FE64", x"3FE7A", x"3FE90", x"3FEA5", x"3FEB9",
        x"3FECD", x"3FEE0", x"3FEF3", x"3FF05", x"3FF16", x"3FF26", x"3FF36", x"3FF46",
        x"3FF55", x"3FF63", x"3FF70", x"3FF7D", x"3FF8A", x"3FF95", x"3FFA1", x"3FFAB",
        x"3FFB5", x"3FFBE", x"3FFC7", x"3FFCF", x"3FFD6", x"3FFDD", x"3FFE3", x"3FFE9",
        x"3FFEE", x"3FFF2", x"3FFF6", x"3FFF9", x"3FFFB", x"3FFFD", x"3FFFE", x"3FFFF"
    );
begin
    sine <= std_logic_vector(sine_sum(sine_sum'high-1 downto sine_sum'high-sine'high-1));
    index_1 <= UNSIGNED(phase(phase'high downto phase'high-11));
    index_2 <= UNSIGNED(phase(phase'high downto phase'high-11))+1;
             
clk_proc: process(clk)
    begin
        if rising_edge(clk) then
            -- Sage 4 - 
            sine_sum  <= sine_mult_1 + sine_mult_2;
            
            -- Pipeline stage 3 - generate the final value
            sine_mult_1 <= sine_1 * frac_1;
            sine_mult_2 <= sine_2 * frac_2;
            
            -- Pipeline state 2 - look up the values in the table
            case quad_1 is
                when "00"   => sine_1 <= midrange+mem(to_integer(entry_1));
                when "01"   => sine_1 <= midrange+mem(to_integer(entry_1));
                when "10"   => sine_1 <= midrange-mem(to_integer(entry_1));
                when others => sine_1 <= midrange-mem(to_integer(entry_1));
            end case;

            case quad_2 is
                when "00"   => sine_2 <= midrange+mem(to_integer(entry_2));
                when "01"   => sine_2 <= midrange+mem(to_integer(entry_2));
                when "10"   => sine_2 <= midrange-mem(to_integer(entry_2));
                when others => sine_2 <= midrange-mem(to_integer(entry_2));
            end case;
            frac_1 <= frac_max - frac;
            frac_2 <= "0" & frac;

            -- Pipeline state 1 - break out the phase components into table indexes
             quad_1  <= index_1(11 downto 10);
             if index_1(10) = '0' then
                entry_1 <= index_1(9 downto 0);
             else 
                entry_1 <= table_max - index_1(9 downto 0);
             end if;

             quad_2  <= index_2(11 downto 10);
             if index_2(10) = '0' then
                entry_2 <= index_2(9 downto 0);
             else 
                entry_2 <= table_max - index_2(9 downto 0);
             end if;

             frac <= unsigned(phase(phase'high-12 downto 0));
        end if;
    end process;
end Behavioral;

basys3.xdc

####################################################
# Constraints file for the Digilent Basys3 board,
# with the PMOD-DA3 attached on the top pins of JA 
####################################################

set_property PACKAGE_PIN W5 [get_ports clk]							
	set_property IOSTANDARD LVCMOS33 [get_ports clk]
	create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]

## Switches
set_property PACKAGE_PIN V17 [get_ports {sw[0]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[0]}]
set_property PACKAGE_PIN V16 [get_ports {sw[1]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[1]}]
set_property PACKAGE_PIN W16 [get_ports {sw[2]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[2]}]
set_property PACKAGE_PIN W17 [get_ports {sw[3]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[3]}]
set_property PACKAGE_PIN W15 [get_ports {sw[4]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[4]}]
set_property PACKAGE_PIN V15 [get_ports {sw[5]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[5]}]
set_property PACKAGE_PIN W14 [get_ports {sw[6]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[6]}]
set_property PACKAGE_PIN W13 [get_ports {sw[7]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[7]}]
set_property PACKAGE_PIN V2 [get_ports {sw[8]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[8]}]
set_property PACKAGE_PIN T3 [get_ports {sw[9]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[9]}]
set_property PACKAGE_PIN T2 [get_ports {sw[10]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[10]}]
set_property PACKAGE_PIN R3 [get_ports {sw[11]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[11]}]
set_property PACKAGE_PIN W2 [get_ports {sw[12]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[12]}]
set_property PACKAGE_PIN U1 [get_ports {sw[13]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[13]}]
set_property PACKAGE_PIN T1 [get_ports {sw[14]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[14]}]
set_property PACKAGE_PIN R2 [get_ports {sw[15]}]					
	set_property IOSTANDARD LVCMOS33 [get_ports {sw[15]}]
	
##Sch name = JA1
set_property PACKAGE_PIN J1 [get_ports {CSn}]                    
    set_property IOSTANDARD LVCMOS33 [get_ports {CSn}]
##Sch name = JA2
set_property PACKAGE_PIN L2 [get_ports {SDAT}]                    
    set_property IOSTANDARD LVCMOS33 [get_ports {SDAT}]
##Sch name = JA3
set_property PACKAGE_PIN J2 [get_ports {LDACn}]                    
    set_property IOSTANDARD LVCMOS33 [get_ports {LDACn}]
##Sch name = JA4
set_property PACKAGE_PIN G2 [get_ports {SCLK}]                    
    set_property IOSTANDARD LVCMOS33 [get_ports {SCLK}]

Personal tools