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); impure 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); if endfile(table_file) then file_close(table_file); file_open(table_file, file_name, read_mode); readline(table_file, file_line); end if; 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;