]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/commitdiff
Approximated function block computes reciprocal, sine and cosine functions.
authorPavel Pisa <ppisa@pikron.com>
Sat, 6 Dec 2014 11:58:46 +0000 (12:58 +0100)
committerPavel Pisa <ppisa@pikron.com>
Sat, 6 Dec 2014 11:58:46 +0000 (12:58 +0100)
Signed-off-by: Pavel Pisa <ppisa@pikron.com>
hw/lx-fncapprox/lx_fncapprox.vhd
hw/lx-fncapprox/lx_fncapprox_dsp48.vhd [new file with mode: 0644]
hw/lx-fncapprox/lx_fncapprox_pkg.vhd [new file with mode: 0644]
hw/lx-fncapprox/rom_table.vhd
hw/lx-fncapprox/sin_tab_a.lut [new file with mode: 0644]
hw/lx-fncapprox/sin_tab_bc.lut [new file with mode: 0644]
hw/lx_rocon_top.prj

index 07793a759639abf91d709d562832f099d33889c0..b7d21281b79108b8f2757a6724e8cbe3e0a2076c 100644 (file)
@@ -2,8 +2,7 @@ library ieee;
 use ieee.std_logic_1164.all;
 use ieee.std_logic_unsigned.all;
 use ieee.numeric_std.all;
-use work.mbl_pkg.all;
-use work.lx_rocon_pkg.all;
+use work.lx_fncapprox_pkg.all;
 
 -- IRC bus interconnect
 entity lx_fncapprox is
@@ -21,35 +20,47 @@ entity lx_fncapprox is
        );
 end lx_fncapprox;
 
+-- reciproc ...  a - (b - c * x) * x
+-- sin      ...  a + (b - c * x) * x
+
+
 architecture Behavioral of lx_fncapprox is
 
-       component rom_table
-       generic
-       (
-               data_width : integer;
-               addr_width : integer;
-               init_file  : string
-       );
-       port
-       (
-               ack_o  : out std_logic;
-               addr_i : in  std_logic_vector (addr_width-1 downto 0);
-               clk_i  : in  std_logic;
-               data_o : out std_logic_vector (data_width-1 downto 0);
-               stb_i  : in  std_logic
-       );
-       end component;
+       -- Types
+
+       type state_fncapprox_t is (ST_IDLE, ST_RECI0, ST_RECI1,
+                        ST_SIN0, ST_SIN1, ST_COS0, ST_COS1);
+
+       -- Signals
 
-       constant approx_tab_bits    : natural := 8;
+       constant approx_top_bits    : natural := 9;
+       constant reci_tab_bits      : natural := 8;
+       constant sin_tab_bits       : natural := 7;
        constant approx_frac_bits   : natural := 18;
+       constant approx_tab_b_shift : natural := 9;
+       constant approx_tab_c_shift : natural := 25;
 
-       constant reci_tab_b_shift   : natural := 9;
-       constant reci_tab_c_shift   : natural := 25;
+       constant approx_lo_used_bit : natural := 31 - approx_top_bits - approx_frac_bits + 1;
 
        signal ce_s                 : std_logic;
+       signal address_s            : std_logic_vector(4 downto 0);
+
+       signal argument_s           : std_logic_vector(31 downto 0);
+       signal argument_r           : std_logic_vector(31 downto 0);
+
+       signal dsp48_p_s            : std_logic_vector(47 downto 0);
+       signal dsp48_a_s            : std_logic_vector(17 downto 0);
+       signal dsp48_b_s            : std_logic_vector(17 downto 0);
+       signal dsp48_c_s            : std_logic_vector(47 downto 0);
+       signal dsp48_add_sub_x_s    : std_logic;
+       signal dsp48_ce_s           : std_logic;
+
+       signal state_tab_s          : state_fncapprox_t;
+       signal state_tab_r          : state_fncapprox_t;
+       signal state_dsp48_r        : state_fncapprox_t;
+       signal state_regw_r         : state_fncapprox_t;
 
-       signal approx_tab_idx_s     : std_logic_vector(approx_tab_bits-1 downto 0);
-       signal approx_tab_idx_r     : std_logic_vector(approx_tab_bits-1 downto 0);
+       signal reci_tab_idx_s       : std_logic_vector(reci_tab_bits-1 downto 0);
        signal approx_frac_s        : std_logic_vector(approx_frac_bits-1 downto 0);
        signal approx_frac_r        : std_logic_vector(approx_frac_bits-1 downto 0);
        signal reci_tab_a_data_s    : std_logic_vector(35 downto 0);
@@ -57,82 +68,367 @@ architecture Behavioral of lx_fncapprox is
        signal reci_tab_bc_data_s   : std_logic_vector(35 downto 0);
        signal reci_tab_bc_data_r   : std_logic_vector(35 downto 0);
 
-       signal reci_tab_b_shifted_r : std_logic_vector(47 downto 0);
+       signal sin_tab_idx_s        : std_logic_vector(sin_tab_bits-1 downto 0);
+       signal sin_tab_a_data_s     : std_logic_vector(35 downto 0);
+       signal sin_tab_bc_data_s    : std_logic_vector(35 downto 0);
+
+       signal approx_tab_b_shifted_r : std_logic_vector(47 downto 0);
        signal reci_tab_a_shifted_r : std_logic_vector(47 downto 0);
        signal frac_c_mult_s        : std_logic_vector(47 downto 0);
        signal frac2_bc_mult_s      : std_logic_vector(47 downto 0);
 
-       signal approx_result_s      : std_logic_vector(31 downto 0);
+       signal reci_result_s        : std_logic_vector(31 downto 0);
+       signal reci_result_r        : std_logic_vector(31 downto 0);
+       signal sin_result_s         : std_logic_vector(31 downto 0);
+       signal sin_result_r         : std_logic_vector(31 downto 0);
+       signal cos_result_s         : std_logic_vector(31 downto 0);
+       signal cos_result_r         : std_logic_vector(31 downto 0);
 
-       signal reci_tab_a_ack_s     : std_logic;
-       signal reci_tab_a_ack_r     : std_logic;
        signal reci_tab_a_stb_s     : std_logic;
-
-       signal reci_tab_bc_ack_s    : std_logic;
-       signal reci_tab_bc_ack_r    : std_logic;
        signal reci_tab_bc_stb_s    : std_logic;
+       signal sin_tab_a_stb_s      : std_logic;
+       signal sin_tab_bc_stb_s     : std_logic;
+
+       signal sin_cos_force_one_s  : std_logic;
+       signal sin_cos_force_one_r  : std_logic;
+       signal sin_cos_force_one_r2 : std_logic;
+       signal sin_cos_negate_out_s : std_logic;
+       signal sin_cos_negate_out_r : std_logic;
+       signal sin_cos_negate_out_r2: std_logic;
 begin
 
+approx_dsp48: lx_fncapprox_dsp48
+       port map (
+               P         => dsp48_p_s,
+               A         => dsp48_a_s,
+               B         => dsp48_b_s,
+               C         => dsp48_c_s,
+               ADD_SUB_X => dsp48_add_sub_x_s,
+               CLK       => clk_i,
+               CE        => dsp48_ce_s
+       );
+
 reci_tab_a : rom_table
        generic map (
                data_width => 36,
-               addr_width => approx_tab_bits,
+               addr_width => reci_tab_bits,
                init_file  => "reci_tab_a.lut"
        )
        port map
        (
                clk_i  => clk_i,
                stb_i  => reci_tab_a_stb_s,
-               addr_i => approx_tab_idx_s,
-               data_o => reci_tab_a_data_s,
-               ack_o  => reci_tab_a_ack_s
+               addr_i => reci_tab_idx_s,
+               data_o => reci_tab_a_data_s
        );
 
 reci_tab_bc : rom_table
        generic map (
                data_width => 36,
-               addr_width => approx_tab_bits,
+               addr_width => reci_tab_bits,
                init_file  => "reci_tab_bc.lut"
        )
        port map
        (
                clk_i  => clk_i,
                stb_i  => reci_tab_bc_stb_s,
-               addr_i => approx_tab_idx_s,
-               data_o => reci_tab_bc_data_s,
-               ack_o  => reci_tab_bc_ack_s
+               addr_i => reci_tab_idx_s,
+               data_o => reci_tab_bc_data_s
        );
 
-wire_in:
-       process(next_ce_i, ce_s, bls_i, address_i, data_i, approx_tab_idx_r, approx_frac_r)
+sin_tab_a : rom_table
+       generic map (
+               data_width => 36,
+               addr_width => sin_tab_bits,
+               init_file  => "sin_tab_a.lut"
+       )
+       port map
+       (
+               clk_i  => clk_i,
+               stb_i  => sin_tab_a_stb_s,
+               addr_i => sin_tab_idx_s,
+               data_o => sin_tab_a_data_s
+       );
+
+sin_tab_bc : rom_table
+       generic map (
+               data_width => 36,
+               addr_width => sin_tab_bits,
+               init_file  => "sin_tab_bc.lut"
+       )
+       port map
+       (
+               clk_i  => clk_i,
+               stb_i  => sin_tab_bc_stb_s,
+               addr_i => sin_tab_idx_s,
+               data_o => sin_tab_bc_data_s
+       );
+
+wire_in_and_next_state:
+       process(next_ce_i, ce_s, bls_i, address_i, data_i, state_tab_r, argument_r)
+       begin
+               -- Incoming bus request
+               if (next_ce_i = '1') and (bls_i(0) = '1') then
+                       argument_s <= data_i;
+                       if address_i(4 downto 0) = "00001" then
+                               state_tab_s <= ST_RECI0;
+                       elsif address_i(4 downto 0) = "00010" then
+                               state_tab_s <= ST_SIN0;
+                       elsif address_i(4 downto 0) = "00011" then
+                               state_tab_s <= ST_COS0;
+                       else
+                               state_tab_s <= ST_IDLE;
+                       end if;
+               else
+                       argument_s <= argument_r;
+                       case state_tab_r is
+                               when ST_IDLE =>
+                                       state_tab_s <= ST_IDLE;
+                               when ST_RECI0 =>
+                                       state_tab_s <= ST_RECI1;
+                               when ST_RECI1 =>
+                                       state_tab_s <= ST_IDLE;
+                               when ST_SIN0 =>
+                                       state_tab_s <= ST_SIN1;
+                               when ST_SIN1 =>
+                                       state_tab_s <= ST_COS0;
+                               when ST_COS0 =>
+                                       state_tab_s <= ST_COS1;
+                               when ST_COS1 =>
+                                       state_tab_s <= ST_IDLE;
+                       end case;
+               end if;
+       end process;
+
+function_tables_access:
+       process(state_tab_r, argument_r)
+               variable negate_arg_v : std_logic;
+               variable arg_frac_is_zeros_v : std_logic;
        begin
                -- init values
-               reci_tab_a_stb_s     <= '0';
-               reci_tab_bc_stb_s     <= '0';
-               approx_tab_idx_s <= approx_tab_idx_r;
-               approx_frac_s <= approx_frac_r;
+               reci_tab_idx_s <= (others => '-');
+               sin_tab_idx_s <= (others => '-');
+               approx_frac_s <= (others => '-');
+               sin_cos_force_one_s <= '-';
+               sin_cos_negate_out_s <= '-';
 
-               -- Incoming bus request
-               if next_ce_i = '1' then
-                       if bls_i(0) = '1' then
-                               reci_tab_a_stb_s <= '1';
+               negate_arg_v := '-';
+
+               reci_tab_a_stb_s   <= '0';
+               reci_tab_bc_stb_s  <= '0';
+               sin_tab_a_stb_s    <= '0';
+               sin_tab_bc_stb_s   <= '0';
+
+               if argument_r(29 downto approx_lo_used_bit) = (28 - approx_lo_used_bit downto 0 => '0') then
+                       arg_frac_is_zeros_v := '1';
+               else
+                       arg_frac_is_zeros_v := '0';
+               end if;
+
+               case state_tab_r is
+                       when ST_IDLE =>
+                               null;
+
+                       when ST_RECI0 =>
+                               reci_tab_idx_s <= argument_r(30 downto
+                                       30 - reci_tab_bits + 1);
                                reci_tab_bc_stb_s <= '1';
-                               approx_tab_idx_s <= data_i(30 downto
-                                          30 - approx_tab_bits + 1);
-                               approx_frac_s <= data_i(30 - approx_tab_bits downto
-                                          30 - approx_tab_bits - approx_frac_bits + 1);
-                       end if;
+                               negate_arg_v := '0';
+
+                       when ST_RECI1 =>
+                               reci_tab_idx_s <= argument_r(30 downto
+                                       30 - reci_tab_bits + 1);
+                               reci_tab_a_stb_s <= '1';
+                               negate_arg_v := '0';
+
+                       when ST_SIN0 =>
+                               sin_tab_bc_stb_s <= '1';
+                               sin_tab_a_stb_s <= '1';
+                               negate_arg_v := argument_r(30);
+
+                       when ST_SIN1 =>
+                               if (arg_frac_is_zeros_v = '1') and (argument_r(30) = '1') then
+                                       sin_cos_force_one_s <= '1';
+                               else
+                                       sin_cos_force_one_s <= '0';
+                               end if;
+
+                               if argument_r(31) = '1' then
+                                       sin_cos_negate_out_s <= '1';
+                               else
+                                       sin_cos_negate_out_s <= '0';
+                               end if;
+
+                               sin_tab_bc_stb_s <= '1';
+                               negate_arg_v := argument_r(30);
+
+                       when ST_COS0 =>
+                               sin_tab_bc_stb_s <= '1';
+                               sin_tab_a_stb_s <= '1';
+                               negate_arg_v := not argument_r(30);
+
+                       when ST_COS1 =>
+                               if (arg_frac_is_zeros_v = '1') and (argument_r(30) = '0') then
+                                       sin_cos_force_one_s <= '1';
+                               else
+                                       sin_cos_force_one_s <= '0';
+                               end if;
+
+                               if argument_r(31) /= argument_r(30) then
+                                       sin_cos_negate_out_s <= '1';
+                               else
+                                       sin_cos_negate_out_s <= '0';
+                               end if;
+
+                               sin_tab_bc_stb_s <= '1';
+                               negate_arg_v := not argument_r(30);
+               end case;
+
+               if negate_arg_v = '0' then
+                       sin_tab_idx_s <= argument_r(29 downto
+                               29 - sin_tab_bits + 1);
+                       approx_frac_s <= argument_r(31 - approx_top_bits downto
+                               31 - approx_top_bits - approx_frac_bits + 1);
+               else
+                       sin_tab_idx_s <= not argument_r(29 downto
+                               29 - sin_tab_bits + 1);
+                       approx_frac_s <= not argument_r(31 - approx_top_bits downto
+                               31 - approx_top_bits - approx_frac_bits + 1);
                end if;
        end process;
 
-wire_out:
-       process(ce_s, approx_result_s)
+dsp48_computation:
+       process(state_dsp48_r, approx_frac_r, dsp48_p_s,
+               reci_tab_a_data_s, reci_tab_bc_data_s,
+               sin_tab_a_data_s, sin_tab_bc_data_s)
+       begin
+               dsp48_a_s <= (others => '-');
+               dsp48_b_s <= (others => '-');
+               dsp48_c_s <= (others => '-');
+               dsp48_add_sub_x_s <= '-';
+               dsp48_ce_s <= '0';
+
+               case state_dsp48_r is
+                       when ST_IDLE =>
+                               null;
+
+                       when ST_RECI0 =>
+                               -- yl = reci_tab_a[ti];
+                               -- yl -= ((reci_tab_b[ti] - ((reci_tab_c[ti] * xd) >> approx_tab_c_shift)) * xd) >> approx_tab_b_shift;
+
+                               dsp48_c_s(approx_tab_c_shift - 1 downto 0) <= (others => '0');
+                               dsp48_c_s(approx_tab_c_shift + 17 downto approx_tab_c_shift) <= reci_tab_bc_data_s(35 downto 18);
+                               dsp48_c_s(47 downto approx_tab_c_shift + 18) <= (others => '0');
+
+                               dsp48_a_s <= reci_tab_bc_data_s(17 downto 0);
+                               dsp48_b_s <= approx_frac_r;
+                               dsp48_add_sub_x_s <= '1';
+                               dsp48_ce_s <= '1';
+
+                       when ST_RECI1 =>
+                               dsp48_c_s(approx_tab_b_shift - 1 downto 0) <= (others => '0');
+                               dsp48_c_s(approx_tab_b_shift + 35 downto approx_tab_b_shift) <= reci_tab_a_data_s;
+                               dsp48_c_s(47 downto approx_tab_b_shift + 36) <= (others => '0');
+
+                               dsp48_a_s <= dsp48_p_s(approx_tab_c_shift + 17 downto approx_tab_c_shift);
+                               dsp48_b_s <= approx_frac_r;
+                               dsp48_add_sub_x_s <= '1';
+                               dsp48_ce_s <= '1';
+
+                       when ST_SIN0 | ST_COS0 =>
+                               dsp48_c_s(approx_tab_c_shift - 1 downto 0) <= (others => '0');
+                               dsp48_c_s(approx_tab_c_shift + 17 downto approx_tab_c_shift) <= sin_tab_bc_data_s(35 downto 18);
+                               dsp48_c_s(47 downto approx_tab_c_shift + 18) <= (others => '0');
+
+                               dsp48_a_s <= sin_tab_bc_data_s(17 downto 0);
+                               dsp48_b_s <= approx_frac_r;
+                               dsp48_add_sub_x_s <= '1';
+                               dsp48_ce_s <= '1';
+
+                       when ST_SIN1 | ST_COS1 =>
+                               dsp48_c_s(approx_tab_b_shift - 1 downto 0) <= (others => '0');
+                               dsp48_c_s(approx_tab_b_shift + 35 downto approx_tab_b_shift) <= sin_tab_a_data_s;
+                               dsp48_c_s(47 downto approx_tab_b_shift + 36) <= (others => '0');
+
+                               dsp48_a_s <= dsp48_p_s(approx_tab_c_shift + 17 downto approx_tab_c_shift);
+                               dsp48_b_s <= approx_frac_r;
+                               dsp48_add_sub_x_s <= '0';
+                               dsp48_ce_s <= '1';
+
+               end case;
+       end process;
+
+result_registers_write:
+       process(state_regw_r, dsp48_p_s, sin_cos_negate_out_r2, sin_cos_force_one_r2,
+               reci_result_r, sin_result_r, cos_result_r)
+               variable sin_cos_res_v  : std_logic_vector(31 downto 0);
        begin
+               reci_result_s <= reci_result_r;
+               sin_result_s <= sin_result_r;
+               cos_result_s <= cos_result_r;
+
+               if sin_cos_force_one_r2 = '1' then
+                       sin_cos_res_v := (30 => '1', others => '0');
+               else
+                       sin_cos_res_v := dsp48_p_s(approx_tab_b_shift + 35 -1 downto approx_tab_b_shift + 4 - 1);
+               end if;
+
+               if sin_cos_negate_out_r2 = '1' then
+                       sin_cos_res_v := std_logic_vector(-signed(sin_cos_res_v));
+                end if;
+
+               case state_regw_r is
+                       when ST_IDLE =>
+                               null;
+
+                       when ST_RECI0 =>
+                               null;
+
+                       when ST_RECI1 =>
+                               reci_result_s <= dsp48_p_s(approx_tab_b_shift + 35 downto approx_tab_b_shift + 4);
+
+                       when ST_SIN0 =>
+                               null;
+
+                       when ST_SIN1 =>
+                               sin_result_s <= sin_cos_res_v;
+
+                       when ST_COS0 =>
+                               null;
 
-               data_o <= (others => '0');
+                       when ST_COS1 =>
+                               cos_result_s <= sin_cos_res_v;
+
+               end case;
+       end process;
+
+wire_out:
+       process(ce_s, reci_result_r, sin_result_r, cos_result_r, address_s, argument_r)
+       begin
+               data_o <= (others => '-');
 
                if ce_s = '1' then
-                       data_o <= approx_result_s;
+                       if address_s(4 downto 0) = "00000" then
+                               data_o <= x"12345678";
+                       elsif address_s(4 downto 0) = "00001" then
+                               data_o <= reci_result_r;
+                       elsif address_s(4 downto 0) = "00010" then
+                               data_o <= sin_result_r;
+                       elsif address_s(4 downto 0) = "00011" then
+                               data_o <= cos_result_r;
+                       elsif address_s(4 downto 0) = "00100" then
+                               data_o(17 downto 0) <= sin_result_r(31 downto 14);
+                               data_o(31 downto 18) <= (others => sin_result_r(31));
+                       elsif address_s(4 downto 0) = "00101" then
+                               data_o(17 downto 0) <= cos_result_r(31 downto 14);
+                               data_o(31 downto 18) <= (others => cos_result_r(31));
+                       elsif address_s(4 downto 0) = "00110" then
+                               data_o <= x"ABCDEF01";
+                       elsif address_s(4 downto 0) = "00111" then
+                               data_o <= argument_r;
+                       else
+                               data_o <= (others => '0');
+                       end if;
                end if;
        end process;
 
@@ -141,37 +437,23 @@ update:
        begin
                wait until clk_i'event and clk_i= '1';
                ce_s      <= next_ce_i;
-               if reci_tab_a_ack_s = '1' then
-                       reci_tab_a_data_r <= reci_tab_a_data_s;
-               end if;
-               if reci_tab_bc_ack_s = '1' then
-                       reci_tab_bc_data_r <= reci_tab_bc_data_s;
-               end if;
-
-               -- yl = reci_tab_a[ti];
-               -- yl -= ((reci_tab_b[ti] - ((reci_tab_c[ti] * xd) >> RECI_TAB_C_SHIFT)) * xd) >> RECI_TAB_B_SHIFT;
-
-               reci_tab_b_shifted_r(reci_tab_c_shift - 1 downto 0) <= (others => '0');
-               reci_tab_b_shifted_r(reci_tab_c_shift + 17 downto reci_tab_c_shift) <= reci_tab_bc_data_r(35 downto 18);
-               reci_tab_b_shifted_r(47 downto reci_tab_c_shift + 18) <= (others => '0');
-
-               frac_c_mult_s <= std_logic_vector(unsigned(reci_tab_b_shifted_r) -
-                       (unsigned(reci_tab_bc_data_r(17 downto 0)) * unsigned(approx_frac_r)));
+               address_s <= address_i;
 
-               reci_tab_a_shifted_r(reci_tab_b_shift - 1 downto 0) <= (others => '0');
-               reci_tab_a_shifted_r(reci_tab_b_shift + 35 downto reci_tab_b_shift) <= reci_tab_a_data_r;
-               reci_tab_a_shifted_r(47 downto reci_tab_b_shift + 36) <= (others => '0');
+               approx_frac_r <= approx_frac_s;
 
-               frac2_bc_mult_s <= std_logic_vector(unsigned(reci_tab_a_shifted_r) -
-                       unsigned(frac_c_mult_s(reci_tab_c_shift + 17 downto reci_tab_c_shift)) *
-                       unsigned(approx_frac_r));
+               state_tab_r <= state_tab_s;
+               state_dsp48_r <= state_tab_r;
+               state_regw_r <= state_dsp48_r;
 
-               approx_result_s <= frac2_bc_mult_s(reci_tab_b_shift + 35 downto reci_tab_b_shift + 4);
+               argument_r <= argument_s;
+               sin_cos_force_one_r <= sin_cos_force_one_s;
+               sin_cos_force_one_r2 <= sin_cos_force_one_r;
+               sin_cos_negate_out_r <= sin_cos_negate_out_s;
+               sin_cos_negate_out_r2 <= sin_cos_negate_out_r;
 
-               reci_tab_a_ack_r <= reci_tab_a_ack_s;
-               reci_tab_bc_ack_r <= reci_tab_bc_ack_s;
-               approx_tab_idx_r <= approx_tab_idx_s;
-               approx_frac_r <= approx_frac_s;
+               reci_result_r <= reci_result_s;
+               sin_result_r <= sin_result_s;
+               cos_result_r <= cos_result_s;
        end process;
 
 end Behavioral;
diff --git a/hw/lx-fncapprox/lx_fncapprox_dsp48.vhd b/hw/lx-fncapprox/lx_fncapprox_dsp48.vhd
new file mode 100644 (file)
index 0000000..230199c
--- /dev/null
@@ -0,0 +1,38 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+use work.lx_fncapprox_pkg.all;
+
+-- IRC bus interconnect
+entity lx_fncapprox_dsp48 is
+       port (
+               P         : out std_logic_vector(47 downto 0);
+               A         : in  std_logic_vector(17 downto 0) := (others => '0');
+               B         : in  std_logic_vector(17 downto 0) := (others => '0');
+               C         : in  std_logic_vector(47 downto 0) := (others => '0');
+               ADD_SUB_X : in  std_logic;
+               CLK       : in  std_logic;
+               CE        : in  std_logic
+       );
+end lx_fncapprox_dsp48;
+
+architecture Behavioral of lx_fncapprox_dsp48 is
+       signal P_s        : std_logic_vector(47 downto 0);
+
+begin
+
+       P <= P_s;
+
+update:
+       process
+       begin
+               wait until CLK'event and CLK= '1' and CE = '1';
+               if ADD_SUB_X = '1' then
+                       P_s <= std_logic_vector(unsigned(C) - unsigned(A) * unsigned(B));
+               else
+                       P_s <= std_logic_vector(unsigned(C) + unsigned(A) * unsigned(B));
+               end if;
+       end process;
+end Behavioral;
+
diff --git a/hw/lx-fncapprox/lx_fncapprox_pkg.vhd b/hw/lx-fncapprox/lx_fncapprox_pkg.vhd
new file mode 100644 (file)
index 0000000..b081da5
--- /dev/null
@@ -0,0 +1,44 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_arith.all;
+use ieee.std_logic_unsigned.all;
+use ieee.numeric_std.all;
+
+-- Entities within lx_fncapprox_pkg
+
+package lx_fncapprox_pkg is
+
+       component rom_table
+       generic
+       (
+               data_width : integer;
+               addr_width : integer;
+               init_file  : string
+       );
+       port
+       (
+               ack_o  : out std_logic;
+               addr_i : in  std_logic_vector (addr_width-1 downto 0);
+               clk_i  : in  std_logic;
+               data_o : out std_logic_vector (data_width-1 downto 0);
+               stb_i  : in  std_logic
+       );
+       end component;
+
+       component lx_fncapprox_dsp48
+       port (
+               P         : out std_logic_vector(47 downto 0);
+               A         : in  std_logic_vector(17 downto 0) := (others => '0');
+               B         : in  std_logic_vector(17 downto 0) := (others => '0');
+               C         : in  std_logic_vector(47 downto 0) := (others => '0');
+               ADD_SUB_X : in  std_logic;
+               CLK       : in  std_logic;
+               CE        : in  std_logic
+       );
+       end component;
+
+end lx_fncapprox_pkg;
+
+package body lx_fncapprox_pkg is
+
+end lx_fncapprox_pkg;
index 02c6f7c78099ea03a7c8928c136e3cdaffb82ed9..1072ec069c54ef28b057c611b9a107c7f9a8015f 100644 (file)
@@ -64,7 +64,7 @@ architecture behavioral of rom_table is
                return table;
        end function init_table_from_file;
 
-       signal ram : rom_table_t := init_table_from_file(init_file);
+       constant ram : rom_table_t := init_table_from_file(init_file);
 
        signal stb_delayed : std_logic;
 
diff --git a/hw/lx-fncapprox/sin_tab_a.lut b/hw/lx-fncapprox/sin_tab_a.lut
new file mode 100644 (file)
index 0000000..db767ee
--- /dev/null
@@ -0,0 +1,128 @@
+000000000000000000000000000000000000
+000000000110010010000111010001111111
+000000001100100100001010101011111100
+000000010010110110000110010101110110
+000000011001000111110110010111110001
+000000011111011001010110111001111010
+000000100101101010100100000100100110
+000000101011111011011010000000010101
+000000110010001011110100110101111000
+000000111000011011110000101110001111
+000000111110101011001001110010101101
+000001000100111001111100001100111011
+000001001011001000000100000110111010
+000001010001010101011101101011000101
+000001010111100010000101000100010010
+000001011101101101110110011101111001
+000001100011111000101110000011110010
+000001101010000010101000000010010111
+000001110000001011100000100110101010
+000001110110010011010011111110010101
+000001111100011001111110010111101101
+000010000010011111011100000001110010
+000010001000100011101001001100010110
+000010001110100110100010000111111010
+000010010100101000000011000101110111
+000010011010101000001000011000010111
+000010100000100110101110010010100001
+000010100110100011110001001000010100
+000010101100011111001101001110101101
+000010110010011000111110111011101010
+000010111000010001000010100110001000
+000010111110000111010100100110001001
+000011000011111011110001010100110101
+000011001001101110010101001100011110
+000011001111011110111100101000011101
+000011010101001101100100000101011011
+000011011010111010001000000001001111
+000011100000100100100100111011000000
+000011100110001100110111010011001010
+000011101011110010111011101011011100
+000011110001010110101110100111000000
+000011110110111000001100101010010111
+000011111100010111010010011011100000
+000100000001110011111100100001110101
+000100000111001110000111100110010010
+000100001100100101110000010011010110
+000100010001111010110011010101000010
+000100010111001101001101011000111110
+000100011100011100111011001110011011
+000100100001101001111001100110010011
+000100100110110100000101010011001110
+000100101011111011011011001001100000
+000100110000111111110111111111001110
+000100110110000001011000101100010000
+000100111010111111111010001010010010
+000100111111111011011001010100110100
+000101000100110011110011001001010001
+000101001001101001000100100110111010
+000101001110011011001010101110111110
+000101010011001010000010100100101010
+000101010111110101101001001101001001
+000101011100011101111011101111100110
+000101100001000010110111010101010010
+000101100101100100011001001001011111
+000101101010000010011110011001101000
+000101101110011101000100010101001111
+000101110010110100001000001101111111
+000101110111000111100111010111110000
+000101111011010111011111001000100111
+000101111111100011101100111000110101
+000110000011101100001110000011000000
+000110000111110001000000000011111100
+000110001011110010000000011010110001
+000110001111101111001100101000111111
+000110010011101000100010010010011001
+000110010111011101111110111101001100
+000110011011001111100000010001111111
+000110011110111101000011111011110011
+000110100010100110100111101000000100
+000110100110001100001001000110110000
+000110101001101101100110001010010001
+000110101101001010111100100111100010
+000110110000100100001010010110000001
+000110110011111001001101001111101111
+000110110111001010000011010001010010
+000110111010010110101010011001110011
+000110111101011111000000101011000111
+000111000000100011000100001001100111
+000111000011100010110010111100011000
+000111000110011110001011001101001001
+000111001001010101001011001000010011
+000111001100000111110000111101000000
+000111001110110101111010111101000100
+000111010001011111100111011101000100
+000111010100000100110100110100010101
+000111010110100101100001011100111101
+000111011001000001101011110011110011
+000111011011011001010010011000100100
+000111011101101100010011101101101101
+000111011111111010101110011000100011
+000111100010000100100001000001001111
+000111100100001001101010010010110011
+000111100110001010001000111011000101
+000111101000000101111011101010110101
+000111101001111101000001010101101100
+000111101011101111011000110010001110
+000111101101011101000000111001110111
+000111101111000101111000101000111110
+000111110000101001111110111110111001
+000111110010001001010010111101110111
+000111110011100011110011101011000110
+000111110100111001100000001110110001
+000111110110001010010111110011111111
+000111110111010110011001101000111010
+000111111000011101100100111110100111
+000111111001011111111001001001001101
+000111111010011101010101011111110001
+000111111011010101111001011100011001
+000111111100001001100100011100001110
+000111111100111000010101111111010111
+000111111101100010001101101000111101
+000111111110000111001010111111001100
+000111111110100111001101101011010000
+000111111111000010010101011001011001
+000111111111011000100001111000111000
+000111111111101001110010111100000000
+000111111111110110001000011000001000
+000111111111111101100010000101101010
diff --git a/hw/lx-fncapprox/sin_tab_bc.lut b/hw/lx-fncapprox/sin_tab_bc.lut
new file mode 100644 (file)
index 0000000..339ef78
--- /dev/null
@@ -0,0 +1,128 @@
+110010010001000001000000001111100000
+110010010000110010000000101110100000
+110010010000000011000001001101100000
+110010001110110110000001101100011111
+110010001101001001000010001011011101
+110010001010111110000010101010011010
+110010001000010011000011001001010101
+110010000101001011000011101000001110
+110010000001100010000100000111000101
+110001111101011011000100100101111001
+110001111000110101000101000100101011
+110001110011110000000101100011011001
+110001101110001110000110000010000100
+110001101000001011000110100000101011
+110001100001101010000110111111001110
+110001011010101011000111011101101101
+110001010011001110000111111100000111
+110001001011010010001000011010011101
+110001000010110111001000111000101101
+110000111001111110001001010110110111
+110000110000100111001001110100111100
+110000100110110010001010010010111011
+110000011100011111001010110000110100
+110000010001101111001011001110100110
+110000000110100000001011101100010001
+101111111010110011001100001001110100
+101111101110101010001100100111010000
+101111100010000011001101000100100101
+101111010100111110001101100001110001
+101111000111011100001101111110110101
+101110111001011101001110011011110001
+101110101011000010001110111000100011
+101110011100001001001111010101001101
+101110001100110011001111110001101100
+101101111101000011010000001110000011
+101101101100110100010000101010001111
+101101011100001010010001000110010001
+101101001011000100010001100010001000
+101100111001100001010001111101110100
+101100100111100011010010011001010110
+101100010101001010010010110100101100
+101100000010010101010011001111110110
+101011101111000110010011101010110101
+101011011011011011010100000101100111
+101011000111010110010100100000001101
+101010110010110101010100111010100111
+101010011101111010010101010100110011
+101010001000100110010101101110110011
+101001110010110111010110001000100101
+101001011100101111010110100010001001
+101001000110001100010110111011011111
+101000101111010001010111010100101000
+101000010111111100010111101101100010
+101000000000001111011000000110001101
+100111101000001000011000011110101001
+100111001111101010011000110110110110
+100110110110110011011001001110110100
+100110011101100100011001100110100011
+100110000011111110011001111110000001
+100101101001111111011010010101010000
+100101001111101010011010101100001110
+100100110100111110011011000010111100
+100100011001111011011011011001011001
+100011111110100001011011101111100110
+100011100010110001011100000101100001
+100011000110101100011100011011001011
+100010101010010001011100110000100011
+100010001101100000011101000101101010
+100001110000011011011101011010011110
+100001010011000000011101101111000001
+100000110101010001011110000011010001
+100000010111001110011110010111001110
+011111111000110111011110101010111001
+011111011010001100011110111110010001
+011110111011001101011111010001010110
+011110011011111101011111100100001000
+011101111100011000011111110110100110
+011101011100100010100000001000110000
+011100111100011001100000011010100111
+011100011011111110100000101100001001
+011011111011010010100000111101011000
+011011011010010101100001001110010010
+011010111001000110100001011110111000
+011010010111100111100001101111001001
+011001110101111000100001111111000101
+011001010011111001100010001110101100
+011000110001101010100010011101111110
+011000001111001100100010101100111011
+010111101100011111100010111011100010
+010111001001100011100011001001110100
+010110100110011010100011010111110001
+010110000011000010100011100101010111
+010101011111011101100011110010100111
+010100111011101010100011111111100010
+010100010111101011100100001100000110
+010011110011011111100100011000010100
+010011001111000111100100100100001011
+010010101010100010100100101111101100
+010010000101110010100100111010110110
+010001100000110111100101000101101001
+010000111011110010100101010000000110
+010000010110100010100101011010001100
+001111110001000111100101100011111010
+001111001011100011100101101101010001
+001110100101110111100101110110010001
+001110000000000000100101111110111010
+001101011010000001100110000111001011
+001100110011111010100110001111000101
+001100001101101011100110010110100111
+001011100111010100100110011101110010
+001011000000110110100110100100100100
+001010011010010010100110101010111111
+001001110011100111100110110001000011
+001001001100110110100110110110101110
+001000100101111111100110111100000001
+000111111111000011100111000000111100
+000111011000000010100111000101011111
+000110110000111100100111001001101011
+000110001001110010100111001101011101
+000101100010100101100111010000111000
+000100111011010100100111010011111011
+000100010100000001100111010110100101
+000011101100101010100111011000110111
+000011000101010001100111011010110001
+000010011101110110100111011100010010
+000001110110011010100111011101011011
+000001001110111101100111011110001100
+000000100111011110100111011110100100
index 503996e73bbcafc7dc1ec9a1a6810bceb199751a..2a3f8cce55c9185f07c7659de2f824ac19e068dd 100644 (file)
@@ -8,6 +8,8 @@ vhdl work "tumbl/fetch.vhd"
 vhdl work "tumbl/exeq.vhd"
 vhdl work "tumbl/decode.vhd"
 vhdl work "tumbl/core_ctrl.vhd"
+vhdl work "lx-fncapprox/lx_fncapprox_pkg.vhd"
+vhdl work "lx-fncapprox/lx_fncapprox_dsp48.vhd"
 vhdl work "lx-fncapprox/lx_fncapprox.vhd"
 vhdl work "lx-fncapprox/rom_table.vhd"
 vhdl work "qcounter.vhd"