]> rtime.felk.cvut.cz Git - fpga/pwm.git/commitdiff
Added wave look-up-table module.
authorVladimir Burian <buriavl2@fel.cvut.cz>
Mon, 14 Mar 2011 14:07:36 +0000 (15:07 +0100)
committerVladimir Burian <buriavl2@fel.cvut.cz>
Mon, 14 Mar 2011 14:07:36 +0000 (15:07 +0100)
Verified with testbench.

gen_sin_lut.m [new file with mode: 0644]
sin.lut [new file with mode: 0644]
tb/tb_wave_table.sav [new file with mode: 0644]
tb/tb_wave_table.vhd [new file with mode: 0644]
wave_table.vhd [new file with mode: 0644]

diff --git a/gen_sin_lut.m b/gen_sin_lut.m
new file mode 100644 (file)
index 0000000..b0c9fb1
--- /dev/null
@@ -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 (file)
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 (file)
index 0000000..67fcf71
--- /dev/null
@@ -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 (file)
index 0000000..d0a8e29
--- /dev/null
@@ -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 (file)
index 0000000..8bd9f03
--- /dev/null
@@ -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;
+