library ieee; use work.ucore_package.all; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity ucore_decode is generic ( enable_udiv : std_logic := '1'; enable_exl2d : std_logic := '1' ); port ( -- global clk : in std_logic; reset : in std_logic; -- in stall : in std_logic; data_in : in std_logic_vector(15 downto 0); -- out decode_opcode : out opcode_t; decode_rc : out std_logic_vector(2 downto 0); decode_rb : out std_logic_vector(2 downto 0); decode_ra : out std_logic_vector(2 downto 0); decode_imm : out std_logic_vector(15 downto 0); decode_rc_we : out std_logic; decode_imm_a : out std_logic ); end entity; architecture rtl of ucore_decode is signal diextend_value : std_logic_vector(10 downto 0) := (others => '0'); begin -- decode opcode process(clk) begin if rising_edge(clk) then if reset = '1' then decode_opcode <= ope_nop; decode_rc <= (others => '0'); decode_rb <= (others => '0'); decode_ra <= (others => '0'); decode_imm <= (others => '0'); decode_rc_we <= '0'; decode_imm_a <= '0'; diextend_value <= (others => '0'); else if stall='0' then -- default decode_rc_we <= '0'; -- default decode_rc <= (others => '0'); decode_rb <= (others => '0'); decode_ra <= (others => '0'); decode_imm <= (others => '0'); decode_imm_a <= '0'; diextend_value <= (others => '0'); -- will be zero next cycle (only diextend decoder instruction can change) -- opcode if data_in(15) = '0' then -- reg im8 case data_in(14 downto 11) is when "0000" => decode_opcode <= ope_movei; decode_rc_we <= '1'; when "0001" => decode_opcode <= ope_moveih; decode_rc_we <= '1'; when "0010" => decode_opcode <= ope_addi; decode_rc_we <= '1'; when "0011" => decode_opcode <= ope_subi; decode_rc_we <= '1'; when "0100" => decode_opcode <= ope_lsri; decode_rc_we <= '1'; when "0101" => decode_opcode <= ope_asri; decode_rc_we <= '1'; when "0110" => decode_opcode <= ope_muli; decode_rc_we <= '1'; when "0111" => decode_opcode <= ope_cmpeqi; when "1000" => decode_opcode <= ope_cmploi; when "1001" => decode_opcode <= ope_cmplosi; when "1010" => decode_opcode <= ope_gpci; decode_rc_we <= '1'; when "1011" => decode_opcode <= ope_jmpi; when "1100" => decode_opcode <= ope_extri; when "1101" => decode_opcode <= ope_rqldi; when "1110" => decode_opcode <= ope_getsp; decode_rc_we <= '1'; when "1111" => decode_opcode <= ope_nop; -- dexti (decoder immediate hold for one cycle) -- will send nop to alu diextend_value <= data_in(10 downto 0); -- store this value when others => decode_opcode <= ope_illegal; -- modelsim end case; decode_rc <= data_in(10 downto 8); decode_rb <= data_in(10 downto 8); decode_ra <= (others => '0'); decode_imm <= diextend_value(7 downto 0) & data_in(7 downto 0); decode_imm_a <= '1'; else if data_in(14) = '0' then -- reg, reg, reg / reg, reg, imm3 if data_in(13) = '0' then -- reg, reg, reg case data_in(12 downto 9) is -- reg, reg, reg when "0000" => decode_opcode <= ope_add; decode_rc_we <= '1'; when "0001" => decode_opcode <= ope_sub; decode_rc_we <= '1'; when "0010" => decode_opcode <= ope_lsr; decode_rc_we <= '1'; when "0011" => decode_opcode <= ope_asr; decode_rc_we <= '1'; when "0100" => decode_opcode <= ope_mul; decode_rc_we <= '1'; when "0101" => decode_opcode <= ope_addt; decode_rc_we <= '1'; when "0110" => decode_opcode <= ope_subt; decode_rc_we <= '1'; when "0111" => decode_opcode <= ope_muls; decode_rc_we <= '1'; when "1000" => decode_opcode <= ope_movets; decode_rc_we <= '1'; when "1001" => decode_opcode <= ope_and; decode_rc_we <= '1'; when "1010" => decode_opcode <= ope_or; decode_rc_we <= '1'; when "1011" => decode_opcode <= ope_xor; decode_rc_we <= '1'; when "1100" => decode_opcode <= ope_bic; decode_rc_we <= '1'; when "1101" => decode_opcode <= ope_illegal; when "1110" => decode_opcode <= ope_illegal; when "1111" => decode_opcode <= ope_illegal; when others => decode_opcode <= ope_illegal; -- modelsim end case; decode_rc <= data_in(8 downto 6); decode_rb <= data_in(5 downto 3); decode_ra <= data_in(2 downto 0); decode_imm <= (others => '0'); decode_imm_a <= '0'; else -- data_in(13) = '1' if data_in(12) = '0' then case data_in(11 downto 9) is -- reg, reg, imm3 -- reg, reg, imm3 when "000" => decode_opcode <= ope_addqi; decode_rc_we <= '1'; when "001" => decode_opcode <= ope_subqi; decode_rc_we <= '1'; when "010" => decode_opcode <= ope_lsrqi; decode_rc_we <= '1'; when "011" => decode_opcode <= ope_asrqi; decode_rc_we <= '1'; when "100" => decode_opcode <= ope_mulqi; decode_rc_we <= '1'; when "101" => decode_opcode <= ope_addtqi; decode_rc_we <= '1'; when "110" => decode_opcode <= ope_subtqi; decode_rc_we <= '1'; when "111" => decode_opcode <= ope_illegal; when others => decode_opcode <= ope_illegal; -- modelsim end case; decode_rc <= data_in(8 downto 6); decode_rb <= data_in(5 downto 3); decode_ra <= (others => '0'); decode_imm <= "00" & diextend_value(10 downto 0) & data_in(2 downto 0); decode_imm_a <= '1'; else case data_in(11 downto 9) is -- reg, reg, special imm3 -- reg, reg, imm3 when "000" => decode_opcode <= ope_edrqldi; when "001" => decode_opcode <= ope_illegal; when "010" => decode_opcode <= ope_illegal; when "011" => decode_opcode <= ope_illegal; when "100" => decode_opcode <= ope_illegal; when "101" => decode_opcode <= ope_illegal; when "110" => decode_opcode <= ope_illegal; when "111" => decode_opcode <= ope_illegal; when others => decode_opcode <= ope_illegal; -- modelsim end case; decode_rc <= (others => '0'); decode_rb <= data_in(8 downto 6); decode_ra <= data_in(5 downto 3); decode_imm <= "00" & diextend_value(10 downto 0) & data_in(2 downto 0); decode_imm_a <= '0'; end if; end if; else -- data(14) = '1' if data_in(13 downto 12) = "11" then -- reg, reg / reg, imm3 / reg if data_in(11) = '0' then -- reg, reg / imm6 case data_in(10 downto 6) is -- reg, reg when "00000" => decode_opcode <= ope_cmpeq; when "00100" => decode_opcode <= ope_cmplo; when "01000" => decode_opcode <= ope_cmplos; when "01100" => decode_opcode <= ope_espage; when "10000" => decode_opcode <= ope_swp; decode_rc_we <= '1'; when "10100" => decode_opcode <= ope_swptc; decode_rc_we <= '1'; when "11000" => decode_opcode <= ope_st; when "11100" => decode_opcode <= ope_stinc; decode_rc_we <= '1'; when "00001" => decode_opcode <= ope_bffo; decode_rc_we <= '1'; when "00101" => decode_opcode <= ope_bset; decode_rc_we <= '1'; when "01001" => decode_opcode <= ope_bclr; decode_rc_we <= '1'; when "01101" => decode_opcode <= ope_cmple; when "10001" => decode_opcode <= ope_cmples; when "10101" => decode_opcode <= ope_rqld; when "11001" => decode_opcode <= ope_extb; decode_rc_we <= '1'; when "11101" => decode_opcode <= ope_stwo; when "00010" => decode_opcode <= ope_andts; decode_rc_we <= '1'; when "00110" => decode_opcode <= ope_orts; decode_rc_we <= '1'; when "01010" => decode_opcode <= ope_xorts; decode_rc_we <= '1'; when "01110" => decode_opcode <= ope_bicts; decode_rc_we <= '1'; when "10010" => decode_opcode <= ope_lsrts; decode_rc_we <= '1'; when "10110" => decode_opcode <= ope_asrts; decode_rc_we <= '1'; when "11010" => decode_opcode <= ope_mults; decode_rc_we <= '1'; when "11110" => decode_opcode <= ope_mulsts; decode_rc_we <= '1'; -- imm6 when "00011" => decode_opcode <= ope_erqldi; when "00111" => decode_opcode <= ope_ssto; when "01011" => if enable_udiv = '1' then decode_opcode <= ope_udivinit; else decode_opcode <= ope_illegal; end if; when "01111" => decode_opcode <= ope_illegal; when "10011" => decode_opcode <= ope_illegal; when "10111" => decode_opcode <= ope_illegal; when "11011" => decode_opcode <= ope_illegal; when "11111" => decode_opcode <= ope_illegal; when others => decode_opcode <= ope_illegal; end case; if data_in(7 downto 6) = "11" then -- imm6 decode_rc <= (others => '0'); decode_rb <= (others => '0'); decode_ra <= (others => '0'); decode_imm <= diextend_value(9 downto 0) & data_in(5 downto 0); decode_imm_a <= '1'; else -- reg, reg decode_rc <= data_in(5 downto 3); decode_rb <= data_in(5 downto 3); decode_ra <= data_in(2 downto 0); decode_imm <= (others => '0'); decode_imm_a <= '0'; end if; else -- data(11) = '1' if data_in(10 downto 4) = "1111111" then -- no param case data_in(3 downto 0) is when "0000" => decode_opcode <= ope_rqpop; when "0001" => decode_opcode <= ope_cli; when "0010" => decode_opcode <= ope_sei; when "0011" => decode_opcode <= ope_rti; when "0100" => decode_opcode <= ope_tnt; when "0101" => decode_opcode <= ope_vtt; when "0111" => decode_opcode <= ope_epushsadrl; when "1000" => decode_opcode <= ope_epushsadrh; when "1001" => decode_opcode <= ope_epopsadrl; when "1010" => decode_opcode <= ope_epopsadrh; when "1011" => decode_opcode <= ope_udivstep; when "1110" => decode_opcode <= ope_nop; -- nop for emulator dump when "1111" => decode_opcode <= ope_nop; when others => decode_opcode <= ope_illegal; end case; if enable_exl2d = '1' then if data_in(3 downto 0) = "0110" then decode_opcode <= ope_exl2derqld; elsif data_in(3 downto 0) = "1100" then decode_opcode <= ope_exl2den; elsif data_in(3 downto 0) = "1101" then decode_opcode <= ope_exl2denerqld; end if; end if; decode_rc <= (others => '0'); decode_rb <= (others => '0'); decode_ra <= (others => '0'); decode_imm <= (others => '0'); decode_imm_a <= '0'; else if data_in(10 downto 8) = "111" then -- reg case data_in(7 downto 3) is when "00000" => decode_opcode <= ope_eld; decode_rc_we <= '1'; when "00010" => decode_opcode <= ope_push; when "00100" => decode_opcode <= ope_gmulhi; decode_rc_we <= '1'; when "00110" => decode_opcode <= ope_ld_pop; decode_rc_we <= '1'; when "01000" => decode_opcode <= ope_poparqp; decode_rc_we <= '1'; when "01010" => decode_opcode <= ope_neg; decode_rc_we <= '1'; when "11100" => decode_opcode <= ope_erqld; when "00001" => decode_opcode <= ope_setsp; when "00011" => decode_opcode <= ope_erqldb; when "00101" => decode_opcode <= ope_jmpts; when "00111" => decode_opcode <= ope_jmptc; when "01001" => decode_opcode <= ope_negts; decode_rc_we <= '1'; when others => decode_opcode <= ope_illegal; end case; if enable_udiv = '1' then if data_in(7 downto 3) = "01100" then decode_opcode <= ope_udivgq; decode_rc_we <= '1'; elsif data_in(7 downto 3) = "01110" then decode_opcode <= ope_udivgr; decode_rc_we <= '1'; elsif data_in(7 downto 3) = "10000" then decode_opcode <= ope_udivgqh; decode_rc_we <= '1'; elsif data_in(7 downto 3) = "10010" then decode_opcode <= ope_udivgrh; decode_rc_we <= '1'; elsif data_in(7 downto 3) = "10100" then decode_opcode <= ope_udivsdd; elsif data_in(7 downto 3) = "10110" then decode_opcode <= ope_udivsdv; elsif data_in(7 downto 3) = "11000" then decode_opcode <= ope_udivsddh; elsif data_in(7 downto 3) = "11010" then decode_opcode <= ope_udivsdvh; end if; end if; decode_rc <= data_in(2 downto 0); decode_rb <= data_in(2 downto 0); decode_ra <= data_in(2 downto 0); decode_imm <= (others => '0'); decode_imm_a <= '0'; else -- reg, imm3 case data_in(10 downto 8) is when "000" => decode_opcode <= ope_illegal; when "001" => decode_opcode <= ope_illegal; when "010" => decode_opcode <= ope_illegal; when "011" => decode_opcode <= ope_est; when "100" => decode_opcode <= ope_estts; when "101" => decode_opcode <= ope_getssr; decode_rc_we <= '1'; when "110" => decode_opcode <= ope_setssr; when "111" => decode_opcode <= ope_illegal; -- can not occure when others => decode_opcode <= ope_illegal; end case; decode_rc <= data_in(5 downto 3); decode_rb <= data_in(5 downto 3); decode_ra <= (others => '0'); decode_imm <= "00" & diextend_value(10 downto 0) & data_in(2 downto 0); decode_imm_a <= '1'; end if; end if; end if; else -- imm12 case data_in(13 downto 12) is when "00" => decode_opcode <= ope_br; when "01" => decode_opcode <= ope_brts; when "10" => decode_opcode <= ope_brtc; when others => decode_opcode <= ope_illegal; end case; decode_rc <= (others => '0'); decode_rb <= (others => '0'); decode_ra <= (others => '0'); decode_imm <= "0000" & data_in(11 downto 0); -- no use of diextend_value decode_imm_a <= '1'; end if; end if; end if; end if; end if; end if; end process; end rtl;