library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_signed.all; -------------------------------------------------------------------------------- entity vector_scale is generic ( IRF_ADR_W : integer := 5; BASE : integer := 0; SCALE_OFF : integer := 5; PHASE_BASE : integer := 16; VECTOR_OFF : integer := 0; SCALED_OFF : integer := 1; VECTOR_W : integer := 10); port ( -- Primary slave intefrace ACK_O : out std_logic; CLK_I : in std_logic; RST_I : in std_logic; STB_I : in std_logic; -- Multiplier interface MUL_A : out std_logic_vector (15 downto 0); MUL_B : out std_logic_vector (15 downto 0); MUL_PROD : in std_logic_vector (31 downto 0); -- Shared dual-port memory IRF_ACK_I : in std_logic; IRF_ADR_O : out std_logic_vector (IRF_ADR_W-1 downto 0); IRF_DAT_I : in std_logic_vector (15 downto 0); IRF_DAT_O : out std_logic_vector (15 downto 0); IRF_STB_O : out std_logic := '0'; IRF_WE_O : out std_logic := '0'); end entity vector_scale; -------------------------------------------------------------------------------- architecture behavioral of vector_scale is constant SCALE_SUBDIV : integer := 10; type state_t is (ready, load_scale, load_vector, save_scaled, done); subtype irf_adr_t is std_logic_vector (IRF_ADR_W-1 downto 0); constant SCALE_ADR : irf_adr_t := conv_std_logic_vector(BASE + SCALE_OFF, IRF_ADR_W); constant VECTOR_ADR : irf_adr_t := conv_std_logic_vector(PHASE_BASE + VECTOR_OFF, IRF_ADR_W); constant SCALED_ADR : irf_adr_t := conv_std_logic_vector(PHASE_BASE + SCALED_OFF, IRF_ADR_W); signal state : state_t := ready; signal INNER_ACK : std_logic := '0'; function twos_to_biased (twos : std_logic_vector) return std_logic_vector is variable result : std_logic_vector (twos'RANGE); begin result := twos; result(result'HIGH) := not twos(twos'HIGH); return result; end; function biased_to_twos (biased : std_logic_vector) return std_logic_vector is variable result : std_logic_vector (biased'range); begin result := biased; result(result'HIGH) := not biased(biased'HIGH); return result; end; -------------------------------------------------------------------------------- begin ACK_O <= STB_I and INNER_ACK; IRF_DAT_O <= "000000" & twos_to_biased(conv_std_logic_vector(signed(MUL_PROD(15+SCALE_SUBDIV downto SCALE_SUBDIV)), 10)); FSM : process (CLK_I, RST_I) is begin if rising_edge(CLK_I) then if RST_I = '1' then state <= ready; INNER_ACK <= '0'; IRF_STB_O <= '0'; IRF_WE_O <= '0'; else case state is when ready => if STB_I = '1' then state <= load_scale; IRF_ADR_O <= SCALE_ADR; IRF_STB_O <= '1'; end if; when load_scale => state <= load_vector; IRF_ADR_O <= VECTOR_ADR; when load_vector => state <= save_scaled; IRF_ADR_O <= SCALED_ADR; MUL_A <= IRF_DAT_I; when save_scaled => state <= done; INNER_ACK <= '1'; IRF_WE_O <= '1'; MUL_B <= conv_std_logic_vector(signed(biased_to_twos(IRF_DAT_I(VECTOR_W-1 downto 0))), 16); when done => IRF_STB_O <= '0'; IRF_WE_O <= '0'; if STB_I = '0' then state <= ready; INNER_ACK <= '0'; end if; end case; end if; end if; end process; end architecture behavioral;