]> rtime.felk.cvut.cz Git - fpga/lx-cpu1/lx-rocon.git/commitdiff
Reciprocal computation implemented in function approximation block.
authorPavel Pisa <ppisa@pikron.com>
Sun, 30 Nov 2014 19:03:25 +0000 (20:03 +0100)
committerPavel Pisa <ppisa@pikron.com>
Sun, 30 Nov 2014 19:03:25 +0000 (20:03 +0100)
The function approximation block is placed
on address 0x80023000 .

Signed-off-by: Pavel Pisa <ppisa@pikron.com>
hw/lx-fncapprox/lx_fncapprox.vhd
hw/lx_rocon_top.vhd

index d8ed833c912c9e18b36876a3450358e3b6537ccc..a5653b3b6ea346970292eac5aafa7f22379ed1a1 100644 (file)
@@ -40,57 +40,99 @@ architecture Behavioral of lx_fncapprox is
        );
        end component;
 
+       constant approx_tab_bits    : natural := 8;
+       constant approx_frac_bits   : natural := 18;
+
+       constant reci_tab_b_shift   : natural := 9;
+       constant reci_tab_c_shift   : natural := 26;
+
        signal ce_s                 : std_logic;
 
-       signal reci_tab_idx_s       : std_logic_vector(7 downto 0);
-       signal reci_tab_idx_r       : std_logic_vector(7 downto 0);
+       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 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);
        signal reci_tab_a_data_r    : std_logic_vector(35 downto 0);
+       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 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_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;
 begin
 
 reci_tab_a : rom_table
        generic map (
                data_width => 36,
-               addr_width => 8,
+               addr_width => approx_tab_bits,
                init_file  => "reci_tab_a.lut"
        )
        port map
        (
                clk_i  => clk_i,
                stb_i  => reci_tab_a_stb_s,
-               addr_i => reci_tab_idx_s,
+               addr_i => approx_tab_idx_s,
                data_o => reci_tab_a_data_s,
                ack_o  => reci_tab_a_ack_s
        );
 
+reci_tab_bc : rom_table
+       generic map (
+               data_width => 36,
+               addr_width => approx_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
+       );
 
 wire_in:
-       process(next_ce_i, ce_s, bls_i, address_i, data_i, reci_tab_idx_r)
+       process(next_ce_i, ce_s, bls_i, address_i, data_i, approx_tab_idx_r, approx_frac_r)
        begin
                -- init values
                reci_tab_a_stb_s     <= '0';
-               reci_tab_idx_s <= reci_tab_idx_r;
+               reci_tab_bc_stb_s     <= '0';
+               approx_tab_idx_s <= approx_tab_idx_r;
+               approx_frac_s <= approx_frac_r;
 
                -- Incoming bus request
                if next_ce_i = '1' then
                        if bls_i(0) = '1' then
                                reci_tab_a_stb_s <= '1';
-                               reci_tab_idx_s <= data_i(7 downto 0);
+                               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;
                end if;
        end process;
 
 wire_out:
-       process(ce_s, reci_tab_a_data_r)
+       process(ce_s, approx_result_s)
        begin
 
                data_o <= (others => '0');
 
                if ce_s = '1' then
-                       data_o <= reci_tab_a_data_r(35 downto 4);
+                       data_o <= approx_result_s;
                end if;
        end process;
 
@@ -102,8 +144,34 @@ update:
                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)));
+
+               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');
+
+               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));
+
+               approx_result_s <= frac2_bc_mult_s(reci_tab_b_shift + 35 downto reci_tab_b_shift + 4);
 
-               reci_tab_idx_r <= reci_tab_idx_s;
+               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;
        end process;
 
 end Behavioral;
index 48ebe35f4fb3b8484097a0a9c2b4d5a647c9f0b8..25cf26bf396a736ef7fe4c2d3d3ad922b8fa9273 100644 (file)
@@ -572,10 +572,11 @@ tumbl_bus_o:
 
                if sel_v = '1' then
                        -- IRC:       0x0800 - 0x081F (32-bit address)
+                       -- LX FNC AP: 0x0C00 - 0x0C1F (32-bit address)
                        -- LX MASTER: 0x1000 - 0x17FF (32-bit address)
                        if addr_v(14 downto 5) = "0001000000" then
                                irc_proc_next_ce_s     <= '1';
-                       elsif addr_v(14 downto 5) = "0001000001" then
+                       elsif addr_v(14 downto 5) = "0001100000" then
                                lxfncapprox_next_ce_s  <= '1';
                        elsif addr_v(14 downto 11) = "0010" then
                                lxmaster_next_ce_s     <= '1';