2 use ieee.std_logic_1164.all;
3 use ieee.std_logic_unsigned.all;
4 use ieee.numeric_std.all;
5 use work.lx_fncapprox_pkg.all;
7 -- IRC bus interconnect
12 reset_i : in std_logic;
14 address_i : in std_logic_vector(4 downto 0);
15 next_ce_i : in std_logic;
16 data_i : in std_logic_vector(31 downto 0);
17 data_o : out std_logic_vector(31 downto 0);
19 bls_i : in std_logic_vector(3 downto 0)
23 -- reciproc ... a + (b + c * x) * x
24 -- sin ... a + (b + c * x) * x
27 architecture Behavioral of lx_fncapprox is
31 type state_fncapprox_t is (ST_IDLE, ST_RECI0, ST_RECI1,
32 ST_SIN0, ST_SIN1, ST_COS0, ST_COS1);
36 constant approx_top_bits : natural := 9;
37 constant reci_tab_bits : natural := 8;
38 constant sin_tab_bits : natural := 7;
39 constant approx_frac_bits : natural := 18;
40 constant approx_tab_b_shift : natural := 8;
41 constant approx_tab_c_shift : natural := 25;
43 constant approx_lo_used_bit : natural := 31 - approx_top_bits - approx_frac_bits + 1;
45 signal ce_s : std_logic;
46 signal address_s : std_logic_vector(4 downto 0);
48 signal argument_s : std_logic_vector(31 downto 0);
49 signal argument_r : std_logic_vector(31 downto 0);
51 signal dsp48_p_s : std_logic_vector(47 downto 0);
52 signal dsp48_a_s : std_logic_vector(17 downto 0);
53 signal dsp48_b_s : std_logic_vector(17 downto 0);
54 signal dsp48_c_s : std_logic_vector(47 downto 0);
55 signal dsp48_ce_s : std_logic;
57 signal state_tab_s : state_fncapprox_t;
58 signal state_tab_r : state_fncapprox_t;
59 signal state_dsp48_r : state_fncapprox_t;
60 signal state_regw_r : state_fncapprox_t;
62 signal reci_tab_idx_s : std_logic_vector(reci_tab_bits-1 downto 0);
63 signal approx_frac_s : std_logic_vector(approx_frac_bits-1 downto 0);
64 signal approx_frac_r : std_logic_vector(approx_frac_bits-1 downto 0);
65 signal reci_tab_a_data_s : std_logic_vector(35 downto 0);
66 signal reci_tab_a_data_r : std_logic_vector(35 downto 0);
67 signal reci_tab_bc_data_s : std_logic_vector(35 downto 0);
68 signal reci_tab_bc_data_r : std_logic_vector(35 downto 0);
70 signal sin_tab_idx_s : std_logic_vector(sin_tab_bits-1 downto 0);
71 signal sin_tab_a_data_s : std_logic_vector(35 downto 0);
72 signal sin_tab_bc_data_s : std_logic_vector(35 downto 0);
74 signal approx_tab_b_shifted_r : std_logic_vector(47 downto 0);
75 signal reci_tab_a_shifted_r : std_logic_vector(47 downto 0);
76 signal frac_c_mult_s : std_logic_vector(47 downto 0);
77 signal frac2_bc_mult_s : std_logic_vector(47 downto 0);
79 signal reci_result_s : std_logic_vector(31 downto 0);
80 signal reci_result_r : std_logic_vector(31 downto 0);
81 signal sin_result_s : std_logic_vector(31 downto 0);
82 signal sin_result_r : std_logic_vector(31 downto 0);
83 signal cos_result_s : std_logic_vector(31 downto 0);
84 signal cos_result_r : std_logic_vector(31 downto 0);
86 signal reci_tab_a_stb_s : std_logic;
87 signal reci_tab_bc_stb_s : std_logic;
88 signal sin_tab_a_stb_s : std_logic;
89 signal sin_tab_bc_stb_s : std_logic;
91 signal sin_cos_force_one_s : std_logic;
92 signal sin_cos_force_one_r : std_logic;
93 signal sin_cos_force_one_r2 : std_logic;
94 signal sin_cos_negate_out_s : std_logic;
95 signal sin_cos_negate_out_r : std_logic;
96 signal sin_cos_negate_out_r2: std_logic;
99 approx_dsp48: lx_fncapprox_dsp48
109 reci_tab_a : rom_table
112 addr_width => reci_tab_bits,
113 init_file => "reci_tab_a.lut"
118 stb_i => reci_tab_a_stb_s,
119 addr_i => reci_tab_idx_s,
120 data_o => reci_tab_a_data_s,
124 reci_tab_bc : rom_table
127 addr_width => reci_tab_bits,
128 init_file => "reci_tab_bc.lut"
133 stb_i => reci_tab_bc_stb_s,
134 addr_i => reci_tab_idx_s,
135 data_o => reci_tab_bc_data_s,
139 sin_tab_a : rom_table
142 addr_width => sin_tab_bits,
143 init_file => "sin_tab_a.lut"
148 stb_i => sin_tab_a_stb_s,
149 addr_i => sin_tab_idx_s,
150 data_o => sin_tab_a_data_s,
154 sin_tab_bc : rom_table
157 addr_width => sin_tab_bits,
158 init_file => "sin_tab_bc.lut"
163 stb_i => sin_tab_bc_stb_s,
164 addr_i => sin_tab_idx_s,
165 data_o => sin_tab_bc_data_s,
169 wire_in_and_next_state:
170 process(next_ce_i, ce_s, bls_i, address_i, data_i, state_tab_r, argument_r)
172 -- Incoming bus request
173 if (next_ce_i = '1') and (bls_i(0) = '1') then
174 argument_s <= data_i;
175 if address_i(4 downto 0) = "00001" then
176 state_tab_s <= ST_RECI0;
177 elsif address_i(4 downto 0) = "00010" then
178 state_tab_s <= ST_SIN0;
179 elsif address_i(4 downto 0) = "00011" then
180 state_tab_s <= ST_COS0;
182 state_tab_s <= ST_IDLE;
185 argument_s <= argument_r;
188 state_tab_s <= ST_IDLE;
190 state_tab_s <= ST_RECI1;
192 state_tab_s <= ST_IDLE;
194 state_tab_s <= ST_SIN1;
196 state_tab_s <= ST_COS0;
198 state_tab_s <= ST_COS1;
200 state_tab_s <= ST_IDLE;
205 function_tables_access:
206 process(state_tab_r, argument_r)
207 variable negate_arg_v : std_logic;
208 variable arg_frac_is_zeros_v : std_logic;
209 variable approx_frac_v : std_logic_vector(approx_frac_bits-1 downto 0);
212 reci_tab_idx_s <= (others => '-');
213 sin_tab_idx_s <= (others => '-');
214 approx_frac_s <= (others => '-');
215 sin_cos_force_one_s <= '-';
216 sin_cos_negate_out_s <= '-';
220 reci_tab_a_stb_s <= '0';
221 reci_tab_bc_stb_s <= '0';
222 sin_tab_a_stb_s <= '0';
223 sin_tab_bc_stb_s <= '0';
225 if argument_r(29 downto approx_lo_used_bit) = (28 - approx_lo_used_bit downto 0 => '0') then
226 arg_frac_is_zeros_v := '1';
228 arg_frac_is_zeros_v := '0';
236 reci_tab_idx_s <= argument_r(30 downto
237 30 - reci_tab_bits + 1);
238 reci_tab_bc_stb_s <= '1';
242 reci_tab_idx_s <= argument_r(30 downto
243 30 - reci_tab_bits + 1);
244 reci_tab_a_stb_s <= '1';
248 sin_tab_bc_stb_s <= '1';
249 sin_tab_a_stb_s <= '1';
250 negate_arg_v := argument_r(30);
253 if (arg_frac_is_zeros_v = '1') and (argument_r(30) = '1') then
254 sin_cos_force_one_s <= '1';
256 sin_cos_force_one_s <= '0';
259 if argument_r(31) = '1' then
260 sin_cos_negate_out_s <= '1';
262 sin_cos_negate_out_s <= '0';
265 sin_tab_bc_stb_s <= '1';
266 negate_arg_v := argument_r(30);
269 sin_tab_bc_stb_s <= '1';
270 sin_tab_a_stb_s <= '1';
271 negate_arg_v := not argument_r(30);
274 if (arg_frac_is_zeros_v = '1') and (argument_r(30) = '0') then
275 sin_cos_force_one_s <= '1';
277 sin_cos_force_one_s <= '0';
280 if argument_r(31) /= argument_r(30) then
281 sin_cos_negate_out_s <= '1';
283 sin_cos_negate_out_s <= '0';
286 sin_tab_bc_stb_s <= '1';
287 negate_arg_v := not argument_r(30);
290 approx_frac_v := argument_r(31 - approx_top_bits downto
291 31 - approx_top_bits - approx_frac_bits + 1);
292 approx_frac_v(approx_frac_bits - 1) := not approx_frac_v(approx_frac_bits - 1);
294 if negate_arg_v = '0' then
295 sin_tab_idx_s <= argument_r(29 downto
296 29 - sin_tab_bits + 1);
297 approx_frac_s <= approx_frac_v;
299 sin_tab_idx_s <= not argument_r(29 downto
300 29 - sin_tab_bits + 1);
301 approx_frac_s <= not approx_frac_v;
306 process(state_dsp48_r, approx_frac_r, dsp48_p_s,
307 reci_tab_a_data_s, reci_tab_bc_data_s,
308 sin_tab_a_data_s, sin_tab_bc_data_s)
310 dsp48_a_s <= (others => '-');
311 dsp48_b_s <= (others => '-');
312 dsp48_c_s <= (others => '-');
315 case state_dsp48_r is
320 -- yl = reci_tab_a[ti];
321 -- yl -= ((reci_tab_b[ti] - ((reci_tab_c[ti] * xd) >> approx_tab_c_shift)) * xd) >> approx_tab_b_shift;
323 dsp48_c_s(approx_tab_c_shift - 1 downto 0) <= (others => '0');
324 dsp48_c_s(approx_tab_c_shift + 17 downto approx_tab_c_shift) <= reci_tab_bc_data_s(35 downto 18);
325 dsp48_c_s(47 downto approx_tab_c_shift + 18) <= (others => reci_tab_bc_data_s(35));
327 dsp48_a_s <= reci_tab_bc_data_s(17 downto 0);
328 dsp48_b_s <= approx_frac_r;
332 dsp48_c_s(approx_tab_b_shift - 1 downto 0) <= (others => '0');
333 dsp48_c_s(approx_tab_b_shift + 35 downto approx_tab_b_shift) <= reci_tab_a_data_s;
334 dsp48_c_s(47 downto approx_tab_b_shift + 36) <= (others => '0');
336 dsp48_a_s <= dsp48_p_s(approx_tab_c_shift + 17 downto approx_tab_c_shift);
337 dsp48_b_s <= approx_frac_r;
340 when ST_SIN0 | ST_COS0 =>
341 dsp48_c_s(approx_tab_c_shift - 1 downto 0) <= (others => '0');
342 dsp48_c_s(approx_tab_c_shift + 17 downto approx_tab_c_shift) <= sin_tab_bc_data_s(35 downto 18);
343 dsp48_c_s(47 downto approx_tab_c_shift + 18) <= (others => sin_tab_bc_data_s(35));
345 dsp48_a_s <= sin_tab_bc_data_s(17 downto 0);
346 dsp48_b_s <= approx_frac_r;
349 when ST_SIN1 | ST_COS1 =>
350 dsp48_c_s(approx_tab_b_shift - 1 downto 0) <= (others => '0');
351 dsp48_c_s(approx_tab_b_shift + 35 downto approx_tab_b_shift) <= sin_tab_a_data_s;
352 dsp48_c_s(47 downto approx_tab_b_shift + 36) <= (others => '0');
354 dsp48_a_s <= dsp48_p_s(approx_tab_c_shift + 17 downto approx_tab_c_shift);
355 dsp48_b_s <= approx_frac_r;
361 result_registers_write:
362 process(state_regw_r, dsp48_p_s, sin_cos_negate_out_r2, sin_cos_force_one_r2,
363 reci_result_r, sin_result_r, cos_result_r)
364 variable sin_cos_res_v : std_logic_vector(31 downto 0);
365 variable sin_cos_res_short_v : std_logic_vector(17 downto 0);
367 reci_result_s <= reci_result_r;
368 sin_result_s <= sin_result_r;
369 cos_result_s <= cos_result_r;
371 if sin_cos_force_one_r2 = '1' then
372 sin_cos_res_v := (30 => '1', others => '0');
374 sin_cos_res_v := dsp48_p_s(approx_tab_b_shift + 35 -1 downto approx_tab_b_shift + 4 - 1);
377 -- Precise 2'nd complement
378 -- if sin_cos_negate_out_r2 = '1' then
379 -- sin_cos_res_v := std_logic_vector(-signed(sin_cos_res_v));
382 -- Fast imprecise first complement
383 if sin_cos_negate_out_r2 = '1' then
384 sin_cos_res_v := not sin_cos_res_v;
387 sin_cos_res_short_v := std_logic_vector(unsigned(sin_cos_res_v(31 downto 14)) +
388 unsigned(sin_cos_res_v(13 downto 13)));
398 reci_result_s <= dsp48_p_s(approx_tab_b_shift + 35 downto approx_tab_b_shift + 4);
404 sin_result_s(17 downto 0) <= sin_cos_res_short_v;
405 sin_result_s(31 downto 18) <= (others => sin_cos_res_short_v(17));
411 cos_result_s(17 downto 0) <= sin_cos_res_short_v;
412 cos_result_s(31 downto 18) <= (others => sin_cos_res_short_v(17));
418 process(ce_s, reci_result_r, sin_result_r, cos_result_r, address_s, argument_r)
420 data_o <= (others => '-');
423 if address_s(4 downto 0) = "00000" then
424 data_o <= x"FA00000E";
425 elsif address_s(4 downto 0) = "00001" then
426 data_o <= reci_result_r;
427 elsif address_s(4 downto 0) = "00010" then
428 data_o <= sin_result_r;
429 elsif address_s(4 downto 0) = "00011" then
430 data_o <= cos_result_r;
432 data_o <= (others => '0');
440 wait until clk_i'event and clk_i= '1';
442 address_s <= address_i;
444 approx_frac_r <= approx_frac_s;
446 state_tab_r <= state_tab_s;
447 state_dsp48_r <= state_tab_r;
448 state_regw_r <= state_dsp48_r;
450 argument_r <= argument_s;
451 sin_cos_force_one_r <= sin_cos_force_one_s;
452 sin_cos_force_one_r2 <= sin_cos_force_one_r;
453 sin_cos_negate_out_r <= sin_cos_negate_out_s;
454 sin_cos_negate_out_r2 <= sin_cos_negate_out_r;
456 reci_result_r <= reci_result_s;
457 sin_result_r <= sin_result_s;
458 cos_result_r <= cos_result_s;