Verified with testbench.
--- /dev/null
+function [ y ] = gen_sin_lut( file, length, bits )
+%gen_sin_lut Generate sinus look-up-table
+% Generates sinus look-up-table for use in 'wave_table.vhd' entity. One period
+% is generated. Wave values are in range 0 .. (2^bits - 1).
+%
+% Length - length of the table
+% Bits - bit length of each value
+% File - if not empty waveform is saved in this file for direct use in VHDL
+%
+
+fd = fopen(file,'w');
+
+x = (0:length-1);
+
+y = sin(2*pi*x/length);
+y = (y + 1) * (2^(bits-1) - 0.5);
+y = round(y);
+
+if (file ~= '')
+ for i=y
+ fprintf(fd,'%s\n',dec2bin(i,bits));
+ end
+
+ fclose(fd);
+end
+
+end
+
--- /dev/null
+1000000000
+1000000110
+1000001100
+1000010010
+1000011001
+1000011111
+1000100101
+1000101011
+1000110010
+1000111000
+1000111110
+1001000100
+1001001011
+1001010001
+1001010111
+1001011101
+1001100011
+1001101001
+1001110000
+1001110110
+1001111100
+1010000010
+1010001000
+1010001110
+1010010100
+1010011010
+1010100000
+1010100110
+1010101100
+1010110010
+1010111000
+1010111101
+1011000011
+1011001001
+1011001111
+1011010101
+1011011010
+1011100000
+1011100101
+1011101011
+1011110001
+1011110110
+1011111100
+1100000001
+1100000110
+1100001100
+1100010001
+1100010110
+1100011100
+1100100001
+1100100110
+1100101011
+1100110000
+1100110101
+1100111010
+1100111111
+1101000100
+1101001001
+1101001110
+1101010010
+1101010111
+1101011100
+1101100000
+1101100101
+1101101001
+1101101110
+1101110010
+1101110110
+1101111010
+1101111111
+1110000011
+1110000111
+1110001011
+1110001111
+1110010011
+1110010111
+1110011010
+1110011110
+1110100010
+1110100101
+1110101001
+1110101100
+1110110000
+1110110011
+1110110110
+1110111001
+1110111101
+1111000000
+1111000011
+1111000110
+1111001000
+1111001011
+1111001110
+1111010001
+1111010011
+1111010110
+1111011000
+1111011010
+1111011101
+1111011111
+1111100001
+1111100011
+1111100101
+1111100111
+1111101001
+1111101011
+1111101100
+1111101110
+1111110000
+1111110001
+1111110011
+1111110100
+1111110101
+1111110110
+1111110111
+1111111001
+1111111001
+1111111010
+1111111011
+1111111100
+1111111101
+1111111101
+1111111110
+1111111110
+1111111110
+1111111111
+1111111111
+1111111111
+1111111111
+1111111111
+1111111111
+1111111111
+1111111110
+1111111110
+1111111110
+1111111101
+1111111101
+1111111100
+1111111011
+1111111010
+1111111001
+1111111001
+1111110111
+1111110110
+1111110101
+1111110100
+1111110011
+1111110001
+1111110000
+1111101110
+1111101100
+1111101011
+1111101001
+1111100111
+1111100101
+1111100011
+1111100001
+1111011111
+1111011101
+1111011010
+1111011000
+1111010110
+1111010011
+1111010001
+1111001110
+1111001011
+1111001000
+1111000110
+1111000011
+1111000000
+1110111101
+1110111001
+1110110110
+1110110011
+1110110000
+1110101100
+1110101001
+1110100101
+1110100010
+1110011110
+1110011010
+1110010111
+1110010011
+1110001111
+1110001011
+1110000111
+1110000011
+1101111111
+1101111010
+1101110110
+1101110010
+1101101110
+1101101001
+1101100101
+1101100000
+1101011100
+1101010111
+1101010010
+1101001110
+1101001001
+1101000100
+1100111111
+1100111010
+1100110101
+1100110000
+1100101011
+1100100110
+1100100001
+1100011100
+1100010110
+1100010001
+1100001100
+1100000110
+1100000001
+1011111100
+1011110110
+1011110001
+1011101011
+1011100101
+1011100000
+1011011010
+1011010101
+1011001111
+1011001001
+1011000011
+1010111101
+1010111000
+1010110010
+1010101100
+1010100110
+1010100000
+1010011010
+1010010100
+1010001110
+1010001000
+1010000010
+1001111100
+1001110110
+1001110000
+1001101001
+1001100011
+1001011101
+1001010111
+1001010001
+1001001011
+1001000100
+1000111110
+1000111000
+1000110010
+1000101011
+1000100101
+1000011111
+1000011001
+1000010010
+1000001100
+1000000110
+1000000000
+0111111001
+0111110011
+0111101101
+0111100110
+0111100000
+0111011010
+0111010100
+0111001101
+0111000111
+0111000001
+0110111011
+0110110100
+0110101110
+0110101000
+0110100010
+0110011100
+0110010110
+0110001111
+0110001001
+0110000011
+0101111101
+0101110111
+0101110001
+0101101011
+0101100101
+0101011111
+0101011001
+0101010011
+0101001101
+0101000111
+0101000010
+0100111100
+0100110110
+0100110000
+0100101010
+0100100101
+0100011111
+0100011010
+0100010100
+0100001110
+0100001001
+0100000011
+0011111110
+0011111001
+0011110011
+0011101110
+0011101001
+0011100011
+0011011110
+0011011001
+0011010100
+0011001111
+0011001010
+0011000101
+0011000000
+0010111011
+0010110110
+0010110001
+0010101101
+0010101000
+0010100011
+0010011111
+0010011010
+0010010110
+0010010001
+0010001101
+0010001001
+0010000101
+0010000000
+0001111100
+0001111000
+0001110100
+0001110000
+0001101100
+0001101000
+0001100101
+0001100001
+0001011101
+0001011010
+0001010110
+0001010011
+0001001111
+0001001100
+0001001001
+0001000110
+0001000010
+0000111111
+0000111100
+0000111001
+0000110111
+0000110100
+0000110001
+0000101110
+0000101100
+0000101001
+0000100111
+0000100101
+0000100010
+0000100000
+0000011110
+0000011100
+0000011010
+0000011000
+0000010110
+0000010100
+0000010011
+0000010001
+0000001111
+0000001110
+0000001100
+0000001011
+0000001010
+0000001001
+0000001000
+0000000110
+0000000110
+0000000101
+0000000100
+0000000011
+0000000010
+0000000010
+0000000001
+0000000001
+0000000001
+0000000000
+0000000000
+0000000000
+0000000000
+0000000000
+0000000000
+0000000000
+0000000001
+0000000001
+0000000001
+0000000010
+0000000010
+0000000011
+0000000100
+0000000101
+0000000110
+0000000110
+0000001000
+0000001001
+0000001010
+0000001011
+0000001100
+0000001110
+0000001111
+0000010001
+0000010011
+0000010100
+0000010110
+0000011000
+0000011010
+0000011100
+0000011110
+0000100000
+0000100010
+0000100101
+0000100111
+0000101001
+0000101100
+0000101110
+0000110001
+0000110100
+0000110111
+0000111001
+0000111100
+0000111111
+0001000010
+0001000110
+0001001001
+0001001100
+0001001111
+0001010011
+0001010110
+0001011010
+0001011101
+0001100001
+0001100101
+0001101000
+0001101100
+0001110000
+0001110100
+0001111000
+0001111100
+0010000000
+0010000101
+0010001001
+0010001101
+0010010001
+0010010110
+0010011010
+0010011111
+0010100011
+0010101000
+0010101101
+0010110001
+0010110110
+0010111011
+0011000000
+0011000101
+0011001010
+0011001111
+0011010100
+0011011001
+0011011110
+0011100011
+0011101001
+0011101110
+0011110011
+0011111001
+0011111110
+0100000011
+0100001001
+0100001110
+0100010100
+0100011010
+0100011111
+0100100101
+0100101010
+0100110000
+0100110110
+0100111100
+0101000010
+0101000111
+0101001101
+0101010011
+0101011001
+0101011111
+0101100101
+0101101011
+0101110001
+0101110111
+0101111101
+0110000011
+0110001001
+0110001111
+0110010110
+0110011100
+0110100010
+0110101000
+0110101110
+0110110100
+0110111011
+0111000001
+0111000111
+0111001101
+0111010100
+0111011010
+0111100000
+0111100110
+0111101101
+0111110011
+0111111001
--- /dev/null
+[timestart] 0
+[size] 1280 746
+[pos] -1 -1
+*-33.377708 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+@28
+clk_i
+@22
+dat_o[9:0]
+@8022
+dat_o[9:0]
+@20000
+-
+-
+-
+-
+@22
+adr_i[8:0]
+@8022
+adr_i[8:0]
+@20000
+-
+-
+-
+@20001
+-
+[pattern_trace] 1
+[pattern_trace] 0
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+entity tb_wave_table is
+end tb_wave_table;
+
+--------------------------------------------------------------------------------
+
+architecture testbench of tb_wave_table is
+
+ constant period : time := 37.5 ns;
+ constant offset : time := 0 us;
+
+ constant DAT_W : integer := 10;
+ constant ADR_W : integer := 9;
+ constant INIT_FILE : string := "../sin.lut";
+
+ constant WAVE_SIZE : integer := 2**ADR_W;
+
+
+ signal ACK_O : std_logic;
+ signal ADR_I : std_logic_vector (ADR_W-1 downto 0);
+ signal CLK_I : std_logic;
+ signal DAT_I : std_logic_vector (DAT_W-1 downto 0);
+ signal DAT_O : std_logic_vector (DAT_W-1 downto 0);
+ signal STB_I : std_logic;
+ signal WE_I : std_logic;
+ signal RST_I : std_logic;
+
+--------------------------------------------------------------------------------
+
+ component wave_table is
+ generic (
+ DAT_W : integer;
+ ADR_W : integer;
+ INIT_FILE : string);
+ port (
+ ACK_O : out std_logic;
+ ADR_I : in std_logic_vector (ADR_W-1 downto 0);
+ CLK_I : in std_logic;
+ DAT_I : in std_logic_vector (DAT_W-1 downto 0);
+ DAT_O : out std_logic_vector (DAT_W-1 downto 0);
+ STB_I : in std_logic;
+ WE_I : in std_logic);
+ end component wave_table;
+
+--------------------------------------------------------------------------------
+
+begin
+
+ uut : wave_table
+ generic map (
+ DAT_W => DAT_W,
+ ADR_W => ADR_W,
+ INIT_FILE => INIT_FILE)
+ port map (
+ ACK_O => ACK_O,
+ ADR_I => ADR_I,
+ CLK_I => CLK_I,
+ DAT_I => DAT_I,
+ DAT_O => DAT_O,
+ STB_I => STB_I,
+ WE_I => WE_I);
+
+ SYSCON_CLK : process
+ begin
+ CLK_I <= '0';
+ wait for offset;
+ loop
+ CLK_I <= '1';
+ wait for period/2;
+ CLK_I <= '0';
+ wait for period/2;
+ end loop;
+ end process;
+
+ SYSCON_RST : process
+ begin
+ RST_I <= '0';
+ wait for offset;
+ wait for 0.75*period;
+ RST_I <= '1';
+ wait for 2*period;
+ RST_I <= '0';
+ wait;
+ end process;
+
+--------------------------------------------------------------------------------
+
+ UUT_FEED : process
+ begin
+ DAT_I <= (others => '0');
+ ADR_I <= (others => '0');
+ STB_I <= '0';
+ WE_I <= '0';
+
+ wait for offset;
+ wait for 4*period;
+
+ for i in 0 to 2*(WAVE_SIZE-1) loop
+ ADR_I <= conv_std_logic_vector(i, ADR_W);
+ STB_I <= '1';
+ wait until ACK_O = '1';
+ wait for period;
+ STB_I <= '0';
+ wait for period;
+ end loop;
+
+ wait;
+ end process;
+
+end testbench;
+
--- /dev/null
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+
+library std;
+use std.textio.all;
+
+--------------------------------------------------------------------------------
+-- Waveform Look Up Table
+--
+-- It's based on behavioral description of full synchronous RAM, so it should be
+-- mapped into FPGA BRAM. Interface is Wishbone like. Data and address bus width
+-- is configurable.
+--
+-- Table is initialized from file specified by 'INIT_FILE' parameter. This is a
+-- text file which contains one value per line. Values are typed in binary
+-- format. Sample file 'sin.lut' together with Matlab generation function
+-- 'gen_lut_sin.m' is enclosed.
+--------------------------------------------------------------------------------
+
+entity wave_table is
+ generic (
+ DAT_W : integer := 10;
+ ADR_W : integer := 9;
+ INIT_FILE : string := "sin.lut");
+ port (
+ ACK_O : out std_logic;
+ ADR_I : in std_logic_vector (ADR_W-1 downto 0);
+ CLK_I : in std_logic;
+ DAT_I : in std_logic_vector (DAT_W-1 downto 0);
+ DAT_O : out std_logic_vector (DAT_W-1 downto 0);
+ STB_I : in std_logic;
+ WE_I : in std_logic);
+end entity wave_table;
+
+--------------------------------------------------------------------------------
+
+architecture behavioral of wave_table is
+
+ constant SIZE : integer := 2**ADR_W;
+
+ type wave_table_t is array (0 to SIZE-1) of bit_vector (DAT_W-1 downto 0);
+
+
+ function init_table_from_file (file_name : string) return wave_table_t is
+ file table_file : text open read_mode is file_name;
+ variable file_line : line;
+ variable table : wave_table_t;
+ begin
+ for i in wave_table_t'range loop
+ readline(table_file, file_line);
+ read(file_line, table(i));
+ end loop;
+
+ return table;
+ end function init_table_from_file;
+
+
+ signal ram : wave_table_t := init_table_from_file(INIT_FILE);
+
+ signal stb_delayed : std_logic;
+
+--------------------------------------------------------------------------------
+
+begin
+
+ MEM : process (CLK_I) is
+ variable address : integer;
+ begin
+ address := conv_integer(ADR_I);
+
+ if rising_edge(CLK_I) then
+ stb_delayed <= STB_I;
+
+ if STB_I = '1' then
+ if WE_I = '0' then
+ DAT_O <= to_stdLogicVector(ram(address));
+ else
+ ram(address) <= to_bitvector(DAT_I);
+ end if;
+ end if;
+ end if;
+ end process;
+
+
+ ACK_O <= STB_I and (stb_delayed or WE_I);
+
+end architecture behavioral;
+