--/********************************************************************************************* --*FCM Userlogic Interface VHDL --*Liu Hu --*UNC Charlotte RCS lab --*Email: lhu8@uncc.edu --*1/19/2009 --* --*Interface specification: --*four 32 bit registers as write registers --*slv_reg0 slv_reg1 slv_reg2 slv_reg3 --*two 32 bit registers as read registers --*slv_reg4 slv_reg5 --*fcmuserdata is data signal from this fcm interface to userlogic core 128bit --*userfcmdata is data signal from userlogic core to fcm interface regs 64bit --*use lqfcmx or ldfcmx intruction in your application program to load signals into write registers --*use stdfcmx intruction in your application program to store result signals back into memory --*************************************************************************************************/ library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity fcm is --generic --( --STATE_IDLE: integer := 0; --STATE_LOAD: integer := 1; --STATE_STORE: integer := 2 --); port ( --output of APU APUFCMINSTRUCTION : in std_logic_vector(0 to 31); APUFCMINSTRVALID : in std_logic; APUFCMRADATA : in std_logic_vector(0 to 31); APUFCMRBDATA : in std_logic_vector(0 to 31); APUFCMOPERANDVALID : in std_logic; APUFCMFLUSH : in std_logic; APUFCMWRITEBACKOK : in std_logic; APUFCMLOADDATA : in std_logic_vector(0 to 31); APUFCMLOADDVALID : in std_logic; APUFCMLOADBYTEEN : in std_logic_vector(0 to 3); APUFCMENDIAN : in std_logic; APUFCMXERCA : in std_logic; APUFCMDECODED : in std_logic; APUFCMDECUDI : in std_logic_vector(0 to 2); APUFCMDECUDIVALID : in std_logic; -- clock and reset clock : in std_logic; reset : in std_logic; --input to APU FCMAPUINSTRACK : out std_logic; FCMAPURESULT : out std_logic_vector(0 to 31); FCMAPUDONE : out std_logic; FCMAPUSLEEPNOTREADY : out std_logic; FCMAPUDECODEBUSY : out std_logic; FCMAPUDCDGPRWRITE : out std_logic; FCMAPUDCDRAEN : out std_logic; FCMAPUDCDRBEN : out std_logic; FCMAPUDCDPRIVOP : out std_logic; FCMAPUDCDFORCEALIGN : out std_logic; FCMAPUDCDXEROVEN : out std_logic; FCMAPUDCDXERCAEN : out std_logic; FCMAPUDCDCREN : out std_logic; FCMAPUEXECRFIELD : out std_logic_vector(0 to 2); FCMAPUDCDLOAD : out std_logic; FCMAPUDCDSTORE : out std_logic; FCMAPUDCDUPDATE : out std_logic; FCMAPUDCDLDSTBYTE : out std_logic; FCMAPUDCDLDSTHW : out std_logic; FCMAPUDCDLDSTWD : out std_logic; FCMAPUDCDLDSTDW : out std_logic; FCMAPUDCDLDSTQW : out std_logic; FCMAPUDCDTRAPLE : out std_logic; FCMAPUDCDTRAPBE : out std_logic; FCMAPUDCDFORCEBESTEERING : out std_logic; FCMAPUDCDFPUOP : out std_logic; FCMAPUEXEBLOCKINGMCO : out std_logic; FCMAPUEXENONBLOCKINGMCO : out std_logic; FCMAPULOADWAIT : out std_logic; FCMAPURESULTVALID : out std_logic; FCMAPUXEROV : out std_logic; FCMAPUXERCA : out std_logic; FCMAPUCR : out std_logic_vector(0 to 3); FCMAPUEXCEPTION : out std_logic ); end entity fcm; architecture IMP of fcm is -----------USER signal declarations added here, as needed for user logic----------- ----------Do not modify below this line---------------------------------------- component decode_ldst port ( --output signals update : out std_logic; --1=RA is loaded with effective address size : out std_logic_vector(0 to 1); --transaction size store_or_loadn : out std_logic; -- 1=store, 0=load valid_ldst : out std_logic; -- if this instruction is a valid FCM load/store -- input signals APUFCMINSTRUCTION : in std_logic_vector(0 to 31) ); end component decode_ldst; --internal signals --PPC instruction-related --signal reg_RT : std_logic_vector(0 to 5); --target register of PPC instruction signal reg_RT : std_logic_vector(0 to 4); --target register of PPC instruction --signal reg_RA : std_logic_vector(0 to 5); signal reg_RA : std_logic_vector(0 to 4); --base register of PPC instruction --signal reg_RA : std_logic_vector(0 to 5); signal reg_RB : std_logic_vector(0 to 4); --offset register of PPC instruction signal instrreg_we : std_logic; -- write enable --loads and stores signal store_or_loadn : std_logic; -- 1=store, 0=load signal store_or_loadn_reg : std_logic; -- stores the store_or_loadn signal signal ldst_update : std_logic; -- 1=update RA signal ldst_size : std_logic_vector(0 to 1); -- number of words to transfer signal ldst_size_reg : std_logic_vector(0 to 1); -- stores number of words to transfer signal ldst_size_counter : std_logic_vector(0 to 1); -- counter for number of words signal ldst_size_counter_we : std_logic; -- write enable signal ldst_valid : std_logic; -- 1=valid load/store instruction --register file for FCM loads signal slv_reg0 : std_logic_vector(0 to 31); -- 32-bit entry register file with 4 registers signal slv_reg1 : std_logic_vector(0 to 31); signal slv_reg2 : std_logic_vector(0 to 31); signal slv_reg3 : std_logic_vector(0 to 31); signal regfile_we : std_logic; -- write enable signal regfile_waddr : std_logic_vector(0 to 1); -- write address signal regfile_wdata : std_logic_vector(0 to 31); -- write data --signal regfile_raddr : std_logic_vector(0 to 1); -- register to store read address signal regfile_raddr : std_logic; -- register to store read address signal regfile_raddr_we : std_logic; -- write enable signal regfile_rdata : std_logic_vector(0 to 31); -- read data --internal variables --outputs to userlogic module signal fcmuserdata : std_logic_vector(0 to 127); --data to give to fpu signal fcmuserready : std_logic; --1 tells user ip core to accept input data --inputs from userlogic module signal userfcmdata : std_logic_vector(0 to 63);-- processed data from fpu signal userfcmready : std_logic; -- signal from user ip core indicate result is ready signal userfcminputready : std_logic; -- signal from user ip core indicate that ready for input --register file for FPU values and FCM stores -- store result 32-bit entry register file with 2 registers signal slv_reg4 : std_logic_vector(0 to 31); signal slv_reg5 : std_logic_vector(0 to 31); signal regfile_store_we : std_logic; -- result store regs write enable signal fcmapudone_reg : std_logic; -- state registers type state is (STATE_IDLE, STATE_LOAD, STATE_STORE, STATE_WAIT_USERCORE); signal curr_state, next_state : state; type userlogicstate is (USERLOGIC_STATE_IDLE, USERLOGIC_STATE_WAIT); signal user_curr_state, user_next_state : userlogicstate; begin --****************************** sequential blocks **************************-- -- PPC instruction-related registers instruction_write_proc: process (clock, reset) is begin if clock'event and clock = '1' then if reset = '1' then reg_RT <= (others => '0'); reg_RA <= (others => '0'); reg_RB <= (others => '0'); else if (instrreg_we = '1') then reg_RT <= APUFCMINSTRUCTION(6 to 10); reg_RA <= APUFCMINSTRUCTION(11 to 15); reg_RB <= APUFCMINSTRUCTION(16 to 20); store_or_loadn_reg <= store_or_loadn; ldst_size_reg <= ldst_size; end if; end if; end if; end process instruction_write_proc; -- read address of register file read_proc: process (clock, reset) is begin if clock'event and clock = '1' then if (reset = '1') then regfile_raddr <= '0'; else if (instrreg_we = '1') then regfile_raddr <= APUFCMINSTRUCTION(10); else if (regfile_raddr_we = '1') then regfile_raddr <= not regfile_raddr; end if; end if; end if; end if; end process read_proc; -- load / store counter for number of words ldst_counter_proc: process (clock, reset) is begin if clock'event and clock = '1' then if (reset = '1') then ldst_size_counter <= (others => '0'); else if (instrreg_we = '1') then ldst_size_counter <= (others => '0'); else if (ldst_size_counter_we = '1') then ldst_size_counter <= ldst_size_counter + 1; end if; end if; end if; end if; end process ldst_counter_proc; -- register write reg_write_proc: process (clock, reset) is begin if clock'event and clock = '1' then if (reset = '1') then -- set all register values to zero slv_reg0 <= (others => '0'); slv_reg1 <= (others => '0'); slv_reg2 <= (others => '0'); slv_reg3 <= (others => '0'); else if (regfile_we = '1') then-- write data to specified register when write enabled case regfile_waddr is when "00" => slv_reg0 <= regfile_wdata; when "01" => slv_reg1 <= regfile_wdata; when "10" => slv_reg2 <= regfile_wdata; when "11" => slv_reg3 <= regfile_wdata; when others => null; end case; end if; end if; end if; end process reg_write_proc; --state machine state_machine_proc: process (clock, reset) is begin if clock'event and clock = '1' then if (reset = '1') then curr_state <= STATE_IDLE; else curr_state <= next_state; end if; end if; end process state_machine_proc; --**************************** combinational blocks *************************/ --decoder decoder: decode_ldst port map ( -- outputs update => ldst_update, size => ldst_size, store_or_loadn => store_or_loadn, valid_ldst => ldst_valid, -- inputs APUFCMINSTRUCTION => APUFCMINSTRUCTION ); -- state machine logic state_machine_logic: process (curr_state, store_or_loadn, store_or_loadn_reg, ldst_size_counter, ldst_size_reg, user_curr_state, userfcmready, APUFCMINSTRVALID, APUFCMLOADDVALID, APUFCMDECODED) is begin case curr_state is -- wait for valid instruction when STATE_IDLE => if APUFCMINSTRVALID = '1' and APUFCMDECODED = '1' then -- valid instruction from APU if (store_or_loadn = '1') then -- store instruction if (user_curr_state = USERLOGIC_STATE_WAIT) then -- waiting for fpu next_state <= STATE_WAIT_USERCORE; else next_state <= STATE_STORE; end if; else -- load instruction if (APUFCMLOADDVALID = '1') then -- load data arrived at the same time if (ldst_size_counter < ldst_size_reg) then next_state <= STATE_LOAD; else next_state <= STATE_IDLE; end if; else next_state <= STATE_LOAD; end if; end if; else next_state <= STATE_IDLE; end if; -- seen a valid load instruction, wait for valid data when STATE_LOAD => -- keep track of how many words to access if (ldst_size_counter < ldst_size_reg) then next_state <= STATE_LOAD; else if (APUFCMLOADDVALID = '1') then next_state <= STATE_IDLE; else next_state <= STATE_LOAD; end if; end if; -- got a store instruction but FPU is not ready when STATE_WAIT_USERCORE => -- FPU result is valid if (userfcmready = '1') then next_state <= STATE_STORE; else next_state <= STATE_WAIT_USERCORE; end if; -- seen a valid store instruction, output data when STATE_STORE => -- keep track of how many words to access if (ldst_size_counter < ldst_size_reg) then next_state <= STATE_STORE; else next_state <= STATE_IDLE; end if; --when others: --next_state <= STATE_IDLE; end case; end process state_machine_logic; -- internal signal assignments instrreg_we <= '1' when (curr_state = STATE_IDLE) else '0'; -- data might arrive at the same time as the instruction regfile_we <= '1' when ( ( (curr_state = STATE_LOAD) and (APUFCMLOADDVALID = '1')) or ( (curr_state = STATE_IDLE) and (APUFCMLOADDVALID = '1')) ) else '0'; -- reg_RT is the target register value when data comes after the instruction regfile_waddr <= (reg_RT + ldst_size_counter); -- write data from memory to register file regfile_wdata <= APUFCMLOADDATA; -- address of register file to read data from for a store operation regfile_raddr_we <= '1' when ( ( (curr_state = STATE_LOAD) and (APUFCMLOADDVALID = '1')) or (curr_state = STATE_STORE) or ( (curr_state = STATE_IDLE) and (APUFCMLOADDVALID = '1')) ) else '0'; -- data read for a store operation read_data_proc: process (regfile_raddr, slv_reg4, slv_reg5) is begin case regfile_raddr is when '0' => regfile_rdata <= slv_reg4; when '1' => regfile_rdata <= slv_reg5; when others => regfile_rdata <= (others => '0'); end case; end process read_data_proc; -- update counter for number of data words transferred ldst_size_counter_we <= '1' when ( ( (curr_state = STATE_LOAD) and (APUFCMLOADDVALID = '1') ) or (curr_state = STATE_STORE) or ( (curr_state = STATE_IDLE) and (APUFCMLOADDVALID = '1') ) ) else '0'; -- output assignments fcmapudone_reg <= '1' when ( ( (curr_state = STATE_LOAD) and (APUFCMLOADDVALID = '1')and (ldst_size_counter = ldst_size_reg) ) or ( (curr_state = STATE_STORE) and (ldst_size_counter = ldst_size_reg) ) or ( (curr_state = STATE_IDLE) and (APUFCMLOADDVALID = '1') and (ldst_size_counter = ldst_size_reg) ) ) else '0'; FCMAPUDONE <= fcmapudone_reg; FCMAPUSLEEPNOTREADY <= '0'; FCMAPURESULT <= regfile_rdata; FCMAPURESULTVALID <= '1' when (curr_state = STATE_STORE) else '0'; -- ask APU to hold load data because FCM is not ready to process it FCMAPULOADWAIT <= '1' when ( (curr_state = STATE_IDLE) and (APUFCMLOADDVALID = '1') ) else '0'; -- unused output signals FCMAPUINSTRACK <= '0'; FCMAPUDECODEBUSY <= '0'; FCMAPUDCDGPRWRITE <= '0'; FCMAPUDCDRAEN <= '0'; FCMAPUDCDRBEN <= '0'; FCMAPUDCDPRIVOP <= '0'; FCMAPUDCDFORCEALIGN <= '0'; FCMAPUDCDXEROVEN <= '0'; FCMAPUDCDXERCAEN <= '0'; FCMAPUDCDCREN <= '0'; FCMAPUEXECRFIELD <= (others => '0'); --3 bits FCMAPUDCDLOAD <= '0'; FCMAPUDCDSTORE <= '0'; FCMAPUDCDUPDATE <= '0'; FCMAPUDCDLDSTBYTE <= '0'; FCMAPUDCDLDSTHW <= '0'; FCMAPUDCDLDSTWD <= '0'; FCMAPUDCDLDSTDW <= '0'; FCMAPUDCDLDSTQW <= '0'; FCMAPUDCDTRAPLE <= '0'; FCMAPUDCDTRAPBE <= '0'; FCMAPUDCDFORCEBESTEERING <= '0'; FCMAPUDCDFPUOP <= '0'; FCMAPUEXEBLOCKINGMCO <= '0'; FCMAPUEXENONBLOCKINGMCO <= '0'; FCMAPUXEROV <= '0'; FCMAPUXERCA <= '0'; FCMAPUCR <= (others => '0'); --4 bits FCMAPUEXCEPTION <= '0'; --************************************************************************ --************************** Userlogic-interface ************************* --************************************************************************ usercore_result_write: process (clock, reset) is begin if clock'event and clock = '1' then if ( reset = '1' ) then slv_reg4 <= (others => '0'); slv_reg5 <= (others => '0'); else if (regfile_store_we = '1') then slv_reg5 <= userfcmdata(32 to 63); slv_reg4 <= userfcmdata(0 to 31); end if; end if; end if; end process usercore_result_write; usercore_state_machine: process (clock, reset) is begin if clock'event and clock = '1' then if ( reset = '1') then user_curr_state <= USERLOGIC_STATE_IDLE; else user_curr_state <= user_next_state; end if; end if; end process usercore_state_machine; usercore_state_machine_proc: process (user_curr_state, fcmapudone_reg, store_or_loadn_reg, ldst_size_reg, userfcminputready, userfcmready) is begin case user_curr_state is -- wait for quad-word load to be done and fpu is ready for input when USERLOGIC_STATE_IDLE => if (store_or_loadn_reg = '0' and fcmapudone_reg = '1' and (ldst_size_reg = "11") and userfcminputready = '1') then user_next_state <= USERLOGIC_STATE_WAIT; else user_next_state <= USERLOGIC_STATE_IDLE; end if; -- wait for user core result when USERLOGIC_STATE_WAIT => if (userfcmready = '1') then-- result is available user_next_state <= USERLOGIC_STATE_IDLE; else user_next_state <= USERLOGIC_STATE_WAIT; end if; when others => user_next_state <= USERLOGIC_STATE_IDLE; end case; end process usercore_state_machine_proc; fcmuserready <= '1' when (user_curr_state = USERLOGIC_STATE_WAIT) else '0'; regfile_store_we <= userfcmready; -----------------put your user logic below this line ------------------------ fcmuserdata <= slv_reg0 & slv_reg1 & slv_reg2 & slv_reg3; ------------------put your user logic above this line --------------------------- end IMP; --------decoder do not modify------------------------------ library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity decode_ldst is port( --output signals update : out std_logic; --1=RA is loaded with effective address size : out std_logic_vector(0 to 1); --transaction size store_or_loadn : out std_logic; -- 1=store, 0=load valid_ldst : out std_logic; -- if this instruction is a valid FCM load/store -- input signals APUFCMINSTRUCTION : in std_logic_vector(0 to 31) ); end entity decode_ldst; architecture DEC of decode_ldst is begin update <= APUFCMINSTRUCTION(21); store_or_loadn <= APUFCMINSTRUCTION(23); valid_ldst <= '1' when ( (APUFCMINSTRUCTION(0 to 5) = "011111") and (APUFCMINSTRUCTION(26 to 31) = "001110") ) else '0'; st_ld_decode_process: process (APUFCMINSTRUCTION(22), APUFCMINSTRUCTION(24 to 25)) is begin case (APUFCMINSTRUCTION(22) & APUFCMINSTRUCTION(24 to 25)) is when "100" => size <= "01"; --double word when "011" => size <= "11"; --quad word when "111" => size <= "11"; --quad word when others => size <= "00"; end case; end process st_ld_decode_process; end DEC;