From 8bd8dd6ce07fb8e247f651b3c61c94bb1f00895a Mon Sep 17 00:00:00 2001 From: Väinö Kauppila Date: Sun, 19 Apr 2026 00:33:08 +0300 Subject: starting files and example programs --- PIC/decoder.vhd | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 PIC/decoder.vhd (limited to 'PIC/decoder.vhd') diff --git a/PIC/decoder.vhd b/PIC/decoder.vhd new file mode 100644 index 0000000..5a1eb2c --- /dev/null +++ b/PIC/decoder.vhd @@ -0,0 +1,155 @@ +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; -- cgit v1.3