library ieee; use ieee.std_logic_1164.all; use work.alu_types.all; package decoder is type instruction_class_t is ( BIT_OP, BYTE_OP, LITERAL_OP, CONTROL_OP, UNKNOWN ); type instruction_t is record class : instruction_class_t; op : alu_op; f : std_logic_vector(6 downto 0); b : std_logic_vector(2 downto 0); d : std_logic; k : std_logic_vector(10 downto 0); end record; pure function instruction_get_class(opc : std_logic_vector(13 downto 0)) return instruction_class_t; pure function instruction_get_operation( opc : std_logic_vector(13 downto 0); instr_class : instruction_class_t) return alu_op; pure function instruction_decode(opc : std_logic_vector(13 downto 0)) return instruction_t; end package; package body decoder is pure function instruction_decode(opc : std_logic_vector(13 downto 0)) return instruction_t is variable instr : instruction_t; begin instr.class := instruction_get_class(opc); instr.op := instruction_get_operation(opc, instr.class); instr.f := (others => '0'); instr.b := (others => '0'); instr.d := '0'; instr.k := (others => '0'); case instr.class is when BIT_OP => instr.b := opc(9 downto 7); instr.f := opc(6 downto 0); when BYTE_OP => instr.f := opc(6 downto 0); instr.d := opc(7); when LITERAL_OP | CONTROL_OP => instr.k := opc(10 downto 0); when UNKNOWN => end case; return instr; end function; pure function instruction_get_class(opc : std_logic_vector(13 downto 0)) return instruction_class_t is begin -- RETURN (0x0008) has bits[13:12]="00" but must be treated as LITERAL_OP if opc = "00000000001000" then return LITERAL_OP; end if; case opc(13 downto 12) is -- byte-oriented file-register operations when "00" => return BYTE_OP; when "01" => return BIT_OP; when "10" => return CONTROL_OP; when "11" => return LITERAL_OP; when others => return UNKNOWN; end case; end function; pure function instruction_get_operation( opc : std_logic_vector(13 downto 0); instr_class : instruction_class_t) return alu_op is begin case instr_class is when BYTE_OP => case opc(11 downto 8) is when "0000" => if opc(7) = '1' then return MOVWF; else return NOP; end if; when "0001" => if opc(7) = '1' then return CLRF; else return CLRW; end if; when "0010" => return SUBWF; when "0011" => return DECF; when "0100" => return IORWF; when "0101" => return ANDWF; when "0110" => return XORWF; when "0111" => return ADDWF; when "1000" => return MOVF; when "1001" => return COMF; when "1010" => return INCF; when "1011" => return DECFSZ; when "1100" => return RRF; when "1101" => return RLF; when "1110" => return SWAPF; when "1111" => return INCFSZ; when others => return NOP; end case; when BIT_OP => case opc(11 downto 10) is when "00" => return BCF; when "01" => return BSF; when "10" => return BTFSC; when "11" => return BTFSS; when others => return NOP; end case; when CONTROL_OP => if opc(11) = '1' then return GOTO; else return CALL; end if; when LITERAL_OP => -- fixed full-word patterns first (fall inside 00xx space) -- if opc(11 downto 0) = "000000000001" then return RETFIE; if opc(11 downto 0) = "000000001000" then return RETUR; -- elsif opc(11 downto 0) = "000000000011" then return SLEEP; -- elsif opc(11 downto 0) = "000000000100" then return CLRWDT; else case? opc(11 downto 8) is when "00--" => return MOVLW; when "01--" => return RETLW; when "1000" => return IORLW; when "1001" => return ANDLW; when "1010" => return XORLW; when "110-" => return SUBLW; when "111-" => return ADDLW; when others => return NOP; end case?; end if; when others => return NOP; end case; end function; end decoder;