/* * idecode.v - instruction decoder for a PIC-family microprocessor. * specificly 16C62X, but similar to (and maybe same as) other 16C6x, 16C7x * * Copyright 1999 Steve Tell. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * **************************************************************************** * * * Editing this requires a rather wide window. * */ `include "funcs.v" module idecode(Clk, Q, null, inst, Aop, Afn, Sw, Sf, Lw, Sflg, PCf, SNf, i_sleep, i_clrwdt); input Clk; input [3:0] Q; input null; input [13:0] inst; output [3:0] Aop; // ALU operation output [2:0] Afn; // ALU A mux function output Sw; // store ALU output to W output Sf; // store ALU output to register file output Lw; // select literal (1) or register (0) for ALU B value output [2:0] Sflg; // store enables for flag bits: Z, DC, C output [2:0] PCf; // PC/stack functions: where next PC comes from, when to push output [2:0] SNf; // when to skip next instruction output i_sleep, i_clrwdt; reg [3:0] Aop; reg [2:0] Afn; reg Sw, Sf, Lw; reg [2:0] Sflg; reg [2:0] PCf; reg [2:0] SNf; reg In; // instruction with no address, like SLEEP or CLRWDT // result-store modes used in the table `define SD ~d,d `define SW 2'b10 `define SF 2'b01 `define SN 2'b00 wire d = inst[7]; // 0=result to W, 1=result to reg always @(posedge Clk) if(Q[0] == 1'b1) begin casez({null, inst[13:0]}) //LZDC_i 15'b0_000111_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_ADD, 1'b0,`AFW, `SD, 5'b0111_0, `PCN,`NN}; // ADDWF 15'b0_11111?_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_ADD, 1'b0,`AFW, `SW, 5'b1111_0, `PCN,`NN}; // ADDLW 15'b0_000101_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_AND, 1'b0,`AFW, `SD, 5'b0100_0, `PCN,`NN}; // ANDWF 15'b0_111001_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_AND, 1'b0,`AFW, `SW, 5'b1100_0, `PCN,`NN}; // ANDLW 15'b0_000001_1???_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_A, 1'b0,`AF0, `SF, 5'b0100_0, `PCN,`NN}; // CLRF 15'b0_000001_0???_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_A, 1'b0,`AF0, `SW, 5'b0100_0, `PCN,`NN}; // CLRW 15'b0_001001_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_XOR, 1'b1,`AF0, `SD, 5'b0100_0, `PCN,`NN}; // COMF 15'b0_000011_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_ADD, 1'b1,`AF0, `SD, 5'b0100_0, `PCN,`NN}; // DECF 15'b0_001011_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_ADD, 1'b1,`AF0, `SD, 5'b0000_0, `PCN,`N0}; // DECFSZ 15'b0_001010_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_ADD, 1'b0,`AF1, `SD, 5'b0100_0, `PCN,`NN}; // INCF 15'b0_001111_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_ADD, 1'b0,`AF1, `SD, 5'b0000_0, `PCN,`N0}; // INCFSZ * 15'b0_000100_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_OR, 1'b0,`AFW, `SD, 5'b0100_0, `PCN,`NN}; // IORWF 15'b0_111000_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_OR, 1'b0,`AFW, `SW, 5'b1100_0, `PCN,`NN}; // IORLW 15'b0_001000_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_B, 1'b0,`AF0, `SD, 5'b0100_0, `PCN,`NN}; // MOVF 15'b0_000000_1???_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_A, 1'b0,`AFW, `SF, 5'b0000_0, `PCN,`NN}; // MOVWF 15'b0_000000_0??0_0000: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_A, 1'b0,`AF0, `SN, 5'b0000_0, `PCN,`NN}; // NOP 15'b1_??????_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_A, 1'b0,`AF0, `SN, 5'b0000_0, `PCN,`NN}; // null (NOP) 15'b0_001101_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_RLB, 1'b0,`AF0, `SD, 5'b0000_0, `PCN,`NN}; // RLF 15'b0_001100_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_RRB, 1'b0,`AF0, `SD, 5'b0000_0, `PCN,`NN}; // RRF 15'b0_0100??_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_AND, 1'b1,`AFB, `SF, 5'b0000_0, `PCN,`NN}; // BCF 15'b0_0101??_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_OR, 1'b0,`AFB, `SF, 5'b0000_0, `PCN,`NN}; // BSF 15'b0_0110??_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_AND, 1'b0,`AFB, `SN, 5'b0000_0, `PCN,`N0}; // BITSC * 15'b0_0111??_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_AND, 1'b0,`AFB, `SN, 5'b0000_0, `PCN,`N1}; // BITSS * 15'b0_000010_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_ADD1, 1'b1,`AFW, `SD, 5'b0111_0, `PCN,`NN}; // SUBWF 15'b0_11110?_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_ADD1, 1'b1,`AFW, `SW, 5'b1111_0, `PCN,`NN}; // SUBLW 15'b0_001110_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_SWAPB,1'b0,`AF0, `SD, 5'b0000_0, `PCN,`NN}; // SWAPF 15'b0_000110_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_XOR, 1'b0,`AFW, `SD, 5'b0100_0, `PCN,`NN}; // XORWF 15'b0_111010_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_XOR, 1'b0,`AFW, `SW, 5'b1100_0, `PCN,`NN}; // XORLW 15'b0_100???_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_A, 1'b0,`AF0, `SN, 5'b0000_0, `PGS,`NA}; // CALL 15'b0_101???_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_A, 1'b0,`AF0, `SN, 5'b0000_0, `PGO,`NA}; // GOTO 15'b0_1100??_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_B, 1'b0,`AFW, `SW, 5'b1000_0, `PCN,`NN}; // MOVLW 15'b0_1101??_????_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_B, 1'b0,`AFW, `SW, 5'b1000_0, `POP,`NA}; // RETLW 15'b0_000000_0000_1000: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_A, 1'b0,`AF0, `SN, 5'b0000_0, `POP,`NA}; // RETURN 15'b0_000000_0000_1001: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_A, 1'b0,`AF0, `SN, 5'b0000_0, `POP,`NA}; // RETIE * // no-address instructions that do no ALU operation, but have some other side effect 15'b0_000000_0110_????: {Aop,Afn,Sw,Sf,Lw,Sflg,In,PCf,SNf}<={`ALU_A, 1'b0,`AF0, `SN, 5'b0000_1, `PCN,`NN}; // SLEEP, etc. endcase // casez(inst) end // if (Q0 == 1'b1) reg i_sleep; reg i_clrwdt; // subdecode for instruction format 14'b000000_0110_???? always @(posedge Clk) begin i_sleep = 0; i_clrwdt = 0; if(In == 1'b1) begin if(inst[3:0] == 4'b0100) i_clrwdt = 1; else if(inst[3:0] == 4'b0011) i_sleep = 1; end // if (In == 1'b1) end // always @ (posedge Clk) endmodule // idecode