library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; -------------------------------------------------------------------------------------- entity special_bitswap_tab_accelerator is port( clk: in std_logic; nReset: in std_logic; -- Slave avs_Add: in std_logic_vector(1 downto 0); avs_CS: in std_logic; avs_Wr: in std_logic; avs_Rd: in std_logic; avs_WrData: in std_logic_vector(31 downto 0); avs_RdData: out std_logic_vector(31 downto 0); -- Master avm_Add: out std_logic_vector(31 downto 0); avm_BE: out std_logic_vector(3 downto 0); avm_Wr: out std_logic; avm_Rd: out std_logic; avm_WrData: out std_logic_vector(31 downto 0); avm_RdData: in std_logic_vector(31 downto 0); avm_WaitRequest: in std_logic -- Interrupt to signal end -- interrupt: out std_logic ); end entity special_bitswap_tab_accelerator; -------------------------------------------------------------------------------------- architecture behv of special_bitswap_tab_accelerator is -- Internal registers signal RegAddStart: std_logic_vector(31 downto 0); signal RegLgt: std_logic_vector(15 downto 0); -- Max 65535 data table length signal DataRd: std_logic_vector(31 downto 0); -- Data read from memory signal Start: std_logic; -- Command, Status bits -- starts accelerator signal Finished: std_logic; -- Command, Status bits -- signals end signal CntAdd: unsigned(31 downto 0); -- Address of the next element in table signal CntLgt: unsigned (15 downto 0); -- Remaining number of elements in table signal ValBitswap: std_logic_vector(31 downto 0); -- Result to write to memory -- Finite state machine for safe memory access type States is(Idle, LdParam, RdAcc, WaitRd, Calcul, WrBitswap, WrEnd); signal StateM: States; begin -- Slave Wr Access AvalonSlaveWr: process(clk, nReset) begin if nReset = '0' then RegAddStart <= (others => '0'); RegLgt <= (others => '0'); Start <= '0'; elsif rising_edge(clk) then Start <= '0'; -- immediate reset as soon as started AvalonMaster if avs_CS = '1' and avs_Wr = '1' then case avs_Add(1 downto 0) is when "00" => RegAddStart <= avs_WrData ; when "01" => RegLgt <= avs_WrData(15 downto 0); when "10" => Start <= avs_WrData(0); -- when "11" => interrupt <= avs_WrData(0); when others => null; end case; end if; end if; end process AvalonSlaveWr; -- Slave Rd Access, set 1 cycle wait in quartus for synchronous read AvalonSlaveRd: process(clk) begin if rising_edge(clk) then if avs_CS = '1' and avs_Rd = '1' then avs_RdData <= (others => '0'); -- default read case avs_Add(1 downto 0) is when "00" => avs_RdData <= RegAddStart; when "01" => avs_RdData(15 downto 0) <= RegLgt; when "10" => avs_RdData(0) <= Start; when "11" => avs_RdData(0) <= Finished; when others => null; end case; end if; end if; end process AvalonSlaveRd; -------------------------------------------------------------------------------------- -- Master bitswap table accelerator with memory access (definitely not optimized) AvalonMaster: process(clk, nReset) begin if nReset = '0' then Finished <= '0'; CntAdd <= (others => '0'); CntLgt <= (others => '0'); ValBitswap <= (others => '0'); StateM <= Idle; elsif rising_edge(clk) then case StateM is when Idle => -- Wait for Start command avm_Add <= (others => '0'); -- Init Avalon Master avm_BE <= "0000"; avm_Wr <= '0'; avm_Rd <= '0'; if Start = '1' then StateM <= LdParam; -- interrupt <= '0'; Finished <= '0'; end if; when LdParam => -- Define workload, unsigned to enable math operations CntAdd <= unsigned(RegAddStart); CntLgt <= unsigned(RegLgt); ValBitswap <= (others => '0'); StateM <= RdAcc; when RdAcc => -- Start read cycle avm_Add <= std_logic_vector(CntAdd); avm_BE <= "1111"; avm_Rd <= '1'; StateM <= WaitRd; when WaitRd => -- Wait for read to complete, store in DataRd if avm_WaitRequest = '0' then DataRd <= avm_RdData; avm_Rd <= '0'; StateM <= Calcul; end if; when Calcul => -- Perform operations on DataRd, save in ValBitswap ValBitswap(31 downto 24) <= DataRd( 7 downto 0); ValBitswap(23) <= DataRd( 8); ValBitswap(22) <= DataRd( 9); ValBitswap(21) <= DataRd(10); ValBitswap(20) <= DataRd(11); ValBitswap(19) <= DataRd(12); ValBitswap(18) <= DataRd(13); ValBitswap(17) <= DataRd(14); ValBitswap(16) <= DataRd(15); ValBitswap(15) <= DataRd(16); ValBitswap(14) <= DataRd(17); ValBitswap(13) <= DataRd(18); ValBitswap(12) <= DataRd(19); ValBitswap(11) <= DataRd(20); ValBitswap(10) <= DataRd(21); ValBitswap( 9) <= DataRd(22); ValBitswap( 8) <= DataRd(23); ValBitswap( 7 downto 0) <= DataRd(31 downto 24); StateM <= WrBitswap; when WrBitswap => -- Wait for write to complete, increment address -- if avm_WaitRequest = '0' then avm_Add <= std_logic_vector(CntAdd); avm_BE <= "1111"; avm_Wr <= '1'; avm_WrData <= ValBitswap; if CntLgt > 1 then CntAdd <= CntAdd + 4; CntLgt <= CntLgt - 1; StateM <= RdAcc; else StateM <= WrEnd; end if; -- end if; when WrEnd => -- Wait for last write to complete and signal end if avm_WaitRequest = '0' then avm_BE <= "0000"; avm_Wr <= '0'; -- interrupt <= '1'; Finished <= '1'; StateM <= Idle; end if; when others => null; end case; end if; end process AvalonMaster; end architecture behv;