我想通过将值保存在LUT中获得Tanh函数的近似值(通过这种方式,我正在进行量化)。我想选择LUT中的条目数。
作为一个不正确的例子,我想象一个像 这样的代码library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use ieee.fixed_pkg.all;
entity tanh_lut is
generic (
MIN_RANGE: real := 0.0; -- Minimum value of x
MAX_RANGE: real := 5.0; -- Maximum value of x
DATA_RANGE_int: positive:= 8;
DATA_RANGE_frac: positive:= 8;
);
Port ( DIN : in sfixed(DATA_RANGE_int-1 downto -(DATA_RANGE_frac-1));
DOUT : out sfixed(DATA_RANGE_int-1 downto -(DATA_RANGE_frac-1))
end tanh_lut;
architecture Behavioral of tanh_lut is
begin
lut_gen: for i in 0 to LUT_SIZE-1 generate
constant x_val : real := MIN_RANGE + (MAX_RANGE - MIN_RANGE) * i / (LUT_SIZE-1);
constant x_val_next : real := MIN_RANGE + (MAX_RANGE - MIN_RANGE) * (i+1) / (LUT_SIZE-1);
constant y_val : real := tanh(x_val);
if DIN>=x_val_previous AND DIN<x_val then
DOUT <= to_sfixed(tanh(y_val),DOUT ) ;
END IF
end generate;
end Behavioral;
例如,如果我想在0到3的范围内有4个条目,我希望它合成如下代码:
if DIN>0 AND DIN<=1 then
DOUT <= to_sfixed(0, DOUT);
else DIN>1 AND DIN<=2 then
DOUT <= to_sfixed(0.76159415595, DOUT);
else DIN>2 AND DIN<=3 then
DOUT <= to_sfixed(0.96402758007, DOUT);
else DIN>3 AND DIN<=4 then
DOUT <= to_sfixed(0.99505475368, DOUT);
End if
这样的代码或实现其背后思想的代码是否有可能实现?
带地址的简单LUT是不可能的,因为地址总是整数,DIN是定点,例如1.5
另一种可能是两个LUT,一个用于将Input映射到地址,另一个用于将地址映射到LUT项,例如,LUT1: 1.5=>地址5,LUT2:地址5 =>0.90. 但是这样的话,我就会把我不想要的资源翻倍
我的要求:像tanh(x)这样的东西不应该被合成,只有tanh(x)的最终值。它还应该是硬件高效的
无论您是使用嵌套的" if-elsif "结构还是为每个检查使用新的" if "结构都没有关系。所以你可以创建一个这样的循环:
for i in 0 to c_number_of_checks-1 loop
if c_boundaries(i)<DIN and DIN<=c_boundaries(i+1) then
DOUT <= c_output_values(i);
end if;
end loop;
当然你必须提供常量c_number_of_checks和c_boundaries, c_output_values。可以这样做:
constant c_number_of_checks : natural := 4;
type array_of_your_data_type is array (natural range <>) of your_data_type;
constant c_boundaries : array_of_your_data_type(c_number_of_checks downto 0) := init_c_boundaries(c_number_of_checks);
constant c_output_values : array_of_your_data_type(c_number_of_checks-1 downto 0) := init_c_output_values(c_number_of_checks);
这意味着您将需要init_c_boundaries, init_c_output_values函数,它们创建值数组,可以初始化常量c_boundaries和c_output_values。但这并不复杂(您可以使用ieee。math_real(函数TANH),因为函数不需要是可合成的,因为它们只在编译时被调用。
如你所见,你将有一些努力。因此,也许遵循其他建议更容易。如果您这样做(值作为LUT的地址),您应该考虑自动ROM推断,这是由几个工具链提供的,并将为您提供非常高效(小型)的硬件。