From: Vladimir Burian Date: Mon, 14 Mar 2011 14:07:36 +0000 (+0100) Subject: Added wave look-up-table module. X-Git-Url: https://rtime.felk.cvut.cz/gitweb/fpga/pwm.git/commitdiff_plain/7f84dd5f3b2c1765a966d2856193e2898425c876 Added wave look-up-table module. Verified with testbench. --- diff --git a/gen_sin_lut.m b/gen_sin_lut.m new file mode 100644 index 0000000..b0c9fb1 --- /dev/null +++ b/gen_sin_lut.m @@ -0,0 +1,28 @@ +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 + diff --git a/sin.lut b/sin.lut new file mode 100644 index 0000000..894f92a --- /dev/null +++ b/sin.lut @@ -0,0 +1,512 @@ +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 diff --git a/tb/tb_wave_table.sav b/tb/tb_wave_table.sav new file mode 100644 index 0000000..67fcf71 --- /dev/null +++ b/tb/tb_wave_table.sav @@ -0,0 +1,27 @@ +[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 diff --git a/tb/tb_wave_table.vhd b/tb/tb_wave_table.vhd new file mode 100644 index 0000000..d0a8e29 --- /dev/null +++ b/tb/tb_wave_table.vhd @@ -0,0 +1,115 @@ +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; + diff --git a/wave_table.vhd b/wave_table.vhd new file mode 100644 index 0000000..8bd9f03 --- /dev/null +++ b/wave_table.vhd @@ -0,0 +1,90 @@ +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; +