URL
https://opencores.org/ocsvn/ae18/ae18/trunk
Subversion Repositories ae18
[/] [ae18/] [trunk/] [rtl/] [verilog/] [ae18_core.v] - Rev 20
Compare with Previous | Blame | View Log
/* * $Id: ae18_core.v,v 1.8 2007-10-11 18:51:49 sybreon Exp $ * * AE18 8-bit Microprocessor Core * Copyright (C) 2006 Shawn Tan Ser Ngiap <shawn.tan@aeste.net> * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, * or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * * DESCRIPTION * This core provides a PIC18 software compatible core. It does not provide * any of the additional functionality needed to form a full PIC18 micro- * controller system. Additional functionality such as I/O devices would * need to be integrated with the core. This core provides the necessary * signals to wire up WISHBONE compatible devices to it. * * HISTORY * $Log: not supported by cvs2svn $ * Revision 1.7 2007/04/13 22:18:51 sybreon * Moved testbench into sim/verilog/testbench.v * Minor cleanup. * * Revision 1.6 2007/04/03 22:13:25 sybreon * Fixed various bugs: * - STATUS,C not correct for subtraction instructions * - Data memory indirect addressing mode bugs * - Other minor fixes * * Revision 1.5 2007/03/04 23:26:37 sybreon * Rearranged code to make it synthesisable. * * Revision 1.4 2006/12/29 18:08:56 sybreon * Minor code clean up * */ module ae18_core (/*AUTOARG*/ // Outputs wb_clk_o, wb_rst_o, iwb_adr_o, iwb_dat_o, iwb_stb_o, iwb_we_o, iwb_sel_o, dwb_adr_o, dwb_dat_o, dwb_stb_o, dwb_we_o, // Inputs iwb_dat_i, iwb_ack_i, dwb_dat_i, dwb_ack_i, int_i, inte_i, clk_i, rst_i ) ; // Instruction address bit length parameter ISIZ = 20; // Data address bit length parameter DSIZ = 12; // WDT length parameter WSIZ = 16; // System WB output wb_clk_o, wb_rst_o; // Instruction WB Bus output [ISIZ-1:0] iwb_adr_o; output [15:0] iwb_dat_o; output iwb_stb_o, iwb_we_o; output [1:0] iwb_sel_o; input [15:0] iwb_dat_i; input iwb_ack_i; // Data WB Bus output [DSIZ-1:0] dwb_adr_o; output [7:0] dwb_dat_o; output dwb_stb_o, dwb_we_o; input [7:0] dwb_dat_i; input dwb_ack_i; // System input [1:0] int_i; input [7:6] inte_i; input clk_i, rst_i; /* * Parameters */ // State Registers parameter [2:0] FSM_RUN = 4'h0, FSM_ISRL = 4'h1, FSM_ISRH = 4'h2, FSM_SLEEP = 4'h3; parameter [1:0] FSM_Q0 = 2'h0, FSM_Q1 = 2'h1, FSM_Q2 = 2'h2, FSM_Q3 = 2'h3; // MX_SRC parameter [1:0] MXSRC_MASK = 2'h2, MXSRC_LIT = 2'h3, MXSRC_WREG = 2'h0, MXSRC_FILE = 2'h1; // MX_TGT parameter [1:0] MXTGT_MASK = 2'h2, MXTGT_LIT = 2'h3, MXTGT_WREG = 2'h0, MXTGT_FILE = 2'h1; // MX_DST parameter [1:0] MXDST_NULL = 2'h0, MXDST_EXT = 2'h1, MXDST_WREG = 2'h2, MXDST_FILE = 2'h3; // MX_ALU parameter [3:0] MXALU_XOR = 4'h0, MXALU_IOR = 4'h1, MXALU_AND = 4'h2, MXALU_SWAP = 4'h3, MXALU_ADD = 4'h4, MXALU_ADDC = 4'h5, MXALU_SUB = 4'h6, MXALU_SUBC = 4'h7, MXALU_RLNC = 4'h8, MXALU_RLC = 4'h9, MXALU_RRNC = 4'hA, MXALU_RRC = 4'hB, MXALU_NEG = 4'hC, // EXTRA MXALU_MOVLB = 4'hC, MXALU_DAW = 4'hD, MXALU_LFSR = 4'hE, MXALU_MUL = 4'hF; // MX_BSR parameter [1:0] MXBSR_BSR = 2'o3, MXBSR_BSA = 2'o2, MXBSR_LIT = 2'o1, MXBSR_NUL = 2'o0; // MX_SKP parameter [2:0] MXSKP_SZ = 3'o1, MXSKP_SNZ = 3'o2, MXSKP_SNC = 3'o3, MXSKP_SU = 3'o4, MXSKP_SCC = 3'o7, MXSKP_NON = 3'o0; // NPC_MX parameter [2:0] MXNPC_FAR = 3'o3, MXNPC_NEAR = 3'o2, MXNPC_BCC = 3'o7, MXNPC_RET = 3'o1, MXNPC_RESET = 3'o4, MXNPC_ISRH = 3'o5, MXNPC_ISRL = 3'o6, MXNPC_INC = 3'o0; // MX_STA parameter [2:0] MXSTA_ALL = 3'o7, MXSTA_CZN = 3'o1, MXSTA_ZN = 3'o2, MXSTA_Z = 3'o3, MXSTA_C = 3'o4, MXSTA_NONE = 3'o0; // BCC_MX parameter [2:0] MXBCC_BZ = 3'o0, MXBCC_BNZ = 3'o1, MXBCC_BC = 3'o2, MXBCC_BNC = 3'o3, MXBCC_BOV = 3'o4, MXBCC_BNOV = 3'o5, MXBCC_BN = 3'o6, MXBCC_BNN = 3'o7; // STK_MX parameter [1:0] MXSTK_PUSH = 2'o2, MXSTK_POP = 2'o1, MXSTK_NONE = 2'o0; // SHADOW MX parameter [1:0] MXSHA_CALL = 2'o2, MXSHA_RET = 2'o1, MXSHA_NONE = 2'o0; // TBLRD/TBLWT MX parameter [3:0] MXTBL_RD = 4'h8, MXTBL_RDINC = 4'h9, MXTBL_RDDEC = 4'hA, MXTBL_RDPRE = 4'hB, MXTBL_WT = 4'hC, MXTBL_WTINC = 4'hD, MXTBL_WTDEC = 4'hE, MXTBL_WTPRE = 4'hF, MXTBL_NOP = 4'h0; // Machine Status //output [3:0] qena_o; //output [1:0] qfsm_o; //output [1:0] qmod_o; // Special Function Registers reg [4:0] rPCU; reg [7:0] rPCH,rPCL, rTOSU, rTOSH, rTOSL, rPCLATU, rPCLATH, rTBLPTRU, rTBLPTRH, rTBLPTRL, rTABLAT, rPRODH, rPRODL, rFSR0H, rFSR0L, rFSR1H, rFSR1L, rFSR2H, rFSR2L; reg rSWDTEN, rSTKFUL, rSTKUNF; reg rZ,rOV,rDC,rN,rC; reg [5:0] rSTKPTR, rSTKPTR_; reg [7:0] rWREG, rWREG_; reg [7:0] rBSR, rBSR_; reg [4:0] rSTATUS_; // Control Word Registers reg [1:0] rMXSRC, rMXTGT, rMXDST, rMXBSR, rMXSTK, rMXSHA; reg [2:0] rMXSKP, rMXSTA, rMXNPC, rMXBCC; reg [3:0] rMXALU, rMXFSR, rMXTBL; reg [15:0] rEAPTR; // Control Path Registers reg rCLRWDT, rRESET, rSLEEP; reg rNSKP, rBCC, rSFRSTB; reg [7:0] rSFRDAT; // Control flags /* * DESCRIPTION * AE18 PLL generator. * Clock and reset generation using on chip DCM/PLL. */ wire clk = clk_i; wire xrst = rst_i; wire qrst = rRESET; assign wb_clk_o = clk_i; assign wb_rst_o = ~rRESET; // WDT reg [WSIZ:0] rWDT; always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rWDT <= {(1+(WSIZ)){1'b0}}; // End of automatics end else if (rCLRWDT|rSLEEP) begin $display("\tWDT cleared."); /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rWDT <= {(1+(WSIZ)){1'b0}}; // End of automatics end else if (rSWDTEN) rWDT <= #1 rWDT + 1; // RAND reg [7:0] rPRNG; always @(negedge clk or negedge xrst) if (!xrst) /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rPRNG <= 8'h0; // End of automatics else rPRNG <= #1 {rPRNG[6:0], ^{rPRNG[7],rPRNG[5:3]}}; /* * DESCRIPTION * AE18 MCU conductor. * Determines and generates the control signal for machine states. */ reg [3:0] rQCLK; reg [1:0] rQCNT; reg [1:0] rFSM, rNXT; //assign qena_o = rQCLK; //assign qfsm_o = rQCNT; //assign qmod_o = rFSM; wire xrun = !((iwb_stb_o ^ iwb_ack_i) | (dwb_stb_o ^ dwb_ack_i)); wire qrun = (rFSM != FSM_SLEEP); wire [3:0] qena = rQCLK; wire [1:0] qfsm = rQCNT; // Interrupt Debounce reg [2:0] rINTH,rINTL; wire fINTH = (rINTH == 3'o3); wire fINTL = (rINTL == 3'o3); always @(negedge clk or negedge xrst) if (!xrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rINTH <= 3'h0; rINTL <= 3'h0; // End of automatics end else begin rINTH <= #1 {rINTH[1:0],int_i[1]}; rINTL <= #1 {rINTL[1:0],int_i[0]}; end // Control Wires wire inth = fINTH; wire isrh = inte_i[7] & fINTH; wire intl = ~isrh & fINTL; wire isrl = intl & inte_i[6]; // QCLK and QCNT sync always @(negedge clk or negedge qrst) if (!qrst) begin rQCLK <= 4'h8; rQCNT <= 2'h3; end else if (xrun & qrun) begin rQCLK <= #1 {rQCLK[2:0],rQCLK[3]}; rQCNT <= #1 rQCNT + 2'd1; end // rINTF Latch reg [1:0] rINTF; always @(negedge clk or negedge xrst) if (!xrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rINTF <= 2'h0; // End of automatics end else begin rINTF <= #1 (^rFSM) ? rFSM : (qena[3]) ? 2'b00 : rINTF; end // FSM Sync always @(negedge clk or negedge qrst) if (!qrst) /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rFSM <= 2'h0; // End of automatics else// if (qena[3]) rFSM <= #1 rNXT; // FSM Logic always @(/*AUTOSENSE*/inth or intl or isrh or isrl or rFSM or rSLEEP) case (rFSM) //FSM_RESET: rNXT <= FSM_RUN; FSM_ISRH: rNXT <= FSM_RUN; FSM_ISRL: rNXT <= FSM_RUN; FSM_SLEEP: begin if (inth) rNXT <= FSM_ISRH; else if (intl) rNXT <= FSM_ISRL; //else if (rWDT[WSIZ]) rNXT <= FSM_RUN; else rNXT <= FSM_SLEEP; end default: begin if (isrh) rNXT <= FSM_ISRH; else if (isrl) rNXT <= FSM_ISRL; else if (rSLEEP) rNXT <= FSM_SLEEP; else rNXT <= FSM_RUN; end endcase // case(rFSM) /* * DESCRIPTION * Instruction WB logic */ // WB Registers reg [23:0] rIWBADR; reg rIWBSTB, rIWBWE; reg [1:0] rIWBSEL; //reg [15:0] rIDAT; assign iwb_adr_o = {rIWBADR,1'b0}; assign iwb_stb_o = rIWBSTB; assign iwb_we_o = rIWBWE; assign iwb_dat_o = {rTABLAT,rTABLAT}; assign iwb_sel_o = rIWBSEL; reg [15:0] rIREG, rROMLAT; reg [7:0] rILAT; reg [ISIZ-2:0] rPCNXT; wire [ISIZ-2:0] wPCLAT = {rPCU,rPCH,rPCL[7:1]}; // FIXME: PCL writes do not affect PC // IWB ADDR signal always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rIWBADR <= 24'h0; // End of automatics end else if (qrun) case (qfsm) FSM_Q3: begin case (rINTF) FSM_ISRH: rIWBADR <= #1 23'h000004; FSM_ISRL: rIWBADR <= #1 23'h00000C; default: rIWBADR <= #1 rPCNXT; endcase // case(rINTF) end FSM_Q1: begin rIWBADR <= #1 (rMXTBL == MXTBL_NOP) ? rIWBADR : {rTBLPTRU,rTBLPTRH,rTBLPTRL[7:1]}; end endcase // case(qfsm) // PC next calculation wire [ISIZ-2:0] wPCINC = rIWBADR + 1; wire [ISIZ-2:0] wPCBCC = (!rNSKP) ? wPCINC : (rBCC) ? rIWBADR + {{(ISIZ-8){rIREG[7]}},rIREG[7:0]} : wPCINC; wire [ISIZ-2:0] wPCNEAR = (!rNSKP) ? wPCINC : rIWBADR + {{(ISIZ-11){rIREG[10]}},rIREG[10:0]}; wire [ISIZ-2:0] wPCFAR = (!rNSKP) ? wPCINC : {rROMLAT[11:0],rIREG[7:0]}; wire [ISIZ-2:0] wPCSTK = (!rNSKP) ? wPCINC : {rTOSU, rTOSH, rTOSL[7:1]}; always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rPCNXT <= {(1+(ISIZ-2)){1'b0}}; // End of automatics end else if (qena[1]) begin case (rMXNPC) MXNPC_RET: rPCNXT <= #1 wPCSTK; //MXNPC_RESET: rPCNXT <= #1 24'h00; //MXNPC_PCL: rPCNXT <= #1 wPCLAT; MXNPC_ISRH: rPCNXT <= #1 24'h08; MXNPC_ISRL: rPCNXT <= #1 24'h18; MXNPC_NEAR: rPCNXT <= #1 wPCNEAR; MXNPC_FAR: rPCNXT <= #1 wPCFAR; MXNPC_BCC: rPCNXT <= #1 wPCBCC; default: rPCNXT <= #1 wPCINC; endcase // case(rMXNPC) end // if (qena[1]) // ROMLAT + IREG always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rILAT <= 8'h0; rIREG <= 16'h0; rROMLAT <= 16'h0; // End of automatics end else if (qrun) begin case (qfsm) FSM_Q0: rROMLAT <= #1 iwb_dat_i; FSM_Q3: rIREG <= #1 rROMLAT; FSM_Q2: rILAT <= (rTBLPTRL[0]) ? iwb_dat_i[7:0] : iwb_dat_i[15:8]; endcase // case(qfsm) end // IWB STB signal wire wISTB = (rMXTBL != MXTBL_NOP); always @(negedge clk or negedge qrst) if (!qrst) /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rIWBSTB <= 1'h0; // End of automatics else if (qrun) case (qfsm) FSM_Q3: rIWBSTB <= #1 1'b1; FSM_Q1: rIWBSTB <= #1 wISTB & rNSKP; default: rIWBSTB <= #1 1'b0; endcase // case(qfsm) // IWB WE signal wire wIWE = (rMXTBL == MXTBL_WT) | (rMXTBL == MXTBL_WTINC) | (rMXTBL == MXTBL_WTDEC) | (rMXTBL == MXTBL_WTPRE); always @(negedge clk or negedge qrst) if (!qrst) /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rIWBWE <= 1'h0; // End of automatics else if (qrun) case (qfsm) FSM_Q1: rIWBWE <= #1 wIWE & rNSKP; default: rIWBWE <= #1 1'b0; endcase // case(qfsm) // IWB SEL signal always @(negedge clk or negedge qrst) if (!qrst) /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rIWBSEL <= 2'h0; // End of automatics else if (qrun) case (qfsm) FSM_Q3: rIWBSEL <= #1 2'h3; FSM_Q1: rIWBSEL <= {rTBLPTRL[0],~rTBLPTRL[0]}; default: rIWBSEL <= #1 2'd0; endcase // case(qfsm) /* * DESCRIPTION * Instruction decode logic */ wire [3:0] fOPCH = rROMLAT[15:12]; wire [3:0] fOPCL = rROMLAT[11:8]; wire [7:0] fOPCK = rROMLAT[7:0]; // NIBBLE DECODER wire fOPC0 = (fOPCH == 4'h0); wire fOPC1 = (fOPCH == 4'h1); wire fOPC2 = (fOPCH == 4'h2); wire fOPC3 = (fOPCH == 4'h3); wire fOPC4 = (fOPCH == 4'h4); wire fOPC5 = (fOPCH == 4'h5); wire fOPC6 = (fOPCH == 4'h6); wire fOPC7 = (fOPCH == 4'h7); wire fOPC8 = (fOPCH == 4'h8); wire fOPC9 = (fOPCH == 4'h9); wire fOPCA = (fOPCH == 4'hA); wire fOPCB = (fOPCH == 4'hB); wire fOPCC = (fOPCH == 4'hC); wire fOPCD = (fOPCH == 4'hD); wire fOPCE = (fOPCH == 4'hE); wire fOPCF = (fOPCH == 4'hF); wire fOP4G0 = (fOPCL == 4'h0); wire fOP4G1 = (fOPCL == 4'h1); wire fOP4G2 = (fOPCL == 4'h2); wire fOP4G3 = (fOPCL == 4'h3); wire fOP4G4 = (fOPCL == 4'h4); wire fOP4G5 = (fOPCL == 4'h5); wire fOP4G6 = (fOPCL == 4'h6); wire fOP4G7 = (fOPCL == 4'h7); wire fOP4G8 = (fOPCL == 4'h8); wire fOP4G9 = (fOPCL == 4'h9); wire fOP4GA = (fOPCL == 4'hA); wire fOP4GB = (fOPCL == 4'hB); wire fOP4GC = (fOPCL == 4'hC); wire fOP4GD = (fOPCL == 4'hD); wire fOP4GE = (fOPCL == 4'hE); wire fOP4GF = (fOPCL == 4'hF); wire fOP3G0 = (fOPCL[3:1] == 3'h0); wire fOP3G1 = (fOPCL[3:1] == 3'h1); wire fOP3G2 = (fOPCL[3:1] == 3'h2); wire fOP3G3 = (fOPCL[3:1] == 3'h3); wire fOP3G4 = (fOPCL[3:1] == 3'h4); wire fOP3G5 = (fOPCL[3:1] == 3'h5); wire fOP3G6 = (fOPCL[3:1] == 3'h6); wire fOP3G7 = (fOPCL[3:1] == 3'h7); wire fOP2G0 = (fOPCL[3:2] == 2'h0); wire fOP2G1 = (fOPCL[3:2] == 2'h1); wire fOP2G2 = (fOPCL[3:2] == 2'h2); wire fOP2G3 = (fOPCL[3:2] == 2'h3); wire fOP1G0 = (fOPCL[3] == 1'b0); wire fOP1G1 = (fOPCL[3] == 1'b1); // GROUP F wire fNOPF = fOPCF; // GROUP E wire fBZ = fOPCE & fOP4G0; wire fBNZ = fOPCE & fOP4G1; wire fBC = fOPCE & fOP4G2; wire fBNC = fOPCE & fOP4G3; wire fBOV = fOPCE & fOP4G4; wire fBNOV = fOPCE & fOP4G5; wire fBN = fOPCE & fOP4G6; wire fBNN = fOPCE & fOP4G7; wire fCALL = fOPCE & fOP3G6; wire fLFSR = fOPCE & fOP4GE; wire fGOTO = fOPCE & fOP4GF; // GROUP D wire fBRA = fOPCD & fOP1G0; wire fRCALL = fOPCD & fOP1G1; // GROUP C wire fMOVFF = fOPCC; // GROUP B/A/9/8/7 wire fBTFSC = fOPCB; wire fBTFSS = fOPCA; wire fBCF = fOPC9; wire fBSF = fOPC8; wire fBTG = fOPC7; // GROUP 6 wire fCPFSLT = fOPC6 & fOP3G0; wire fCPFSEQ = fOPC6 & fOP3G1; wire fCPFSGT = fOPC6 & fOP3G2; wire fTSTFSZ = fOPC6 & fOP3G3; wire fSETF = fOPC6 & fOP3G4; wire fCLRF = fOPC6 & fOP3G5; wire fNEGF = fOPC6 & fOP3G6; wire fMOVWF = fOPC6 & fOP3G7; // GROUP 5 wire fMOVF = fOPC5 & fOP2G0; wire fSUBFWB = fOPC5 & fOP2G1; wire fSUBWFB = fOPC5 & fOP2G2; wire fSUBWF = fOPC5 & fOP2G3; // GROUP 4 wire fRRNCF = fOPC4 & fOP2G0; wire fRLNCF = fOPC4 & fOP2G1; wire fINFSNZ = fOPC4 & fOP2G2; wire fDCFSNZ = fOPC4 & fOP2G3; // GROUP 3 wire fRRCF = fOPC3 & fOP2G0; wire fRLCF = fOPC3 & fOP2G1; wire fSWAPF = fOPC3 & fOP2G2; wire fINCFSZ = fOPC3 & fOP2G3; // GROUP 2 wire fADDWFC = fOPC2 & fOP2G0; wire fADDWF = fOPC2 & fOP2G1; wire fINCF = fOPC2 & fOP2G2; wire fDECFSZ = fOPC2 & fOP2G3; // GROUP 1 wire fIORWF = fOPC1 & fOP2G0; wire fANDWF = fOPC1 & fOP2G1; wire fXORWF = fOPC1 & fOP2G2; wire fCOMF = fOPC1 & fOP2G3; // GROUP 0 wire fMISC = fOPC0 & fOP4G0; wire fMOVLB = fOPC0 & fOP4G1; wire fMULWF = fOPC0 & fOP3G1; wire fDECF = fOPC0 & fOP2G1; wire fSUBLW = fOPC0 & fOP4G8; wire fIORLW = fOPC0 & fOP4G9; wire fXORLW = fOPC0 & fOP4GA; wire fANDLW = fOPC0 & fOP4GB; wire fRETLW = fOPC0 & fOP4GC; wire fMULLW = fOPC0 & fOP4GD; wire fMOVLW = fOPC0 & fOP4GE; wire fADDLW = fOPC0 & fOP4GF; // GROUP MISC wire fNOP0 = fMISC & (fOPCK == 8'h00); wire fRESET = fMISC & (fOPCK == 8'hFF); wire fSLEEP = fMISC & (fOPCK == 8'h03); wire fCLRWDT = fMISC & (fOPCK == 8'h04); wire fPUSH = fMISC & (fOPCK == 8'h05); wire fPOP = fMISC & (fOPCK == 8'h06); wire fDAW = fMISC & (fOPCK == 8'h07); wire fRETFIE = fMISC & (fOPCK == 8'h10 | fOPCK == 8'h11); wire fRETURN = fMISC & (fOPCK == 8'h12 | fOPCK == 8'h13); wire fNOP = fNOP0 | fNOPF; wire fTBLRDWT = fMISC & (fOPCK[7:3] == 5'h01); // MX INT wire fINT = ^rINTF; // MX_SRC wire [1:0] wMXSRC = (fMOVLW|fRETLW|fCOMF| fDECF|fDECFSZ|fDCFSNZ| fINCF|fINCFSZ|fINFSNZ| fMOVF|fMOVFF|fMOVWF| fSETF|fTSTFSZ) ? MXSRC_LIT : (fBSF|fBTG|fBTFSC|fBTFSS) ? MXSRC_MASK : (fBCF|fCPFSLT|fSUBFWB) ? MXSRC_FILE : MXSRC_WREG; // MX_TGT wire [1:0] wMXTGT = (fBCF) ? MXTGT_MASK : (fRETLW|fMOVLW| fMULLW| fADDLW|fSUBLW| fANDLW|fXORLW|fIORLW) ? MXTGT_LIT : (fBSF|fBTFSC|fBTFSS|fBTG| fADDWF|fADDWFC|fSUBWF|fSUBWFB|fMULWF| fMULWF|fSWAPF| fANDWF|fIORWF|fXORWF| fCOMF|fMOVF|fMOVFF| fCPFSEQ|fCPFSGT|fNEGF| fDECF|fDECFSZ|fDCFSNZ| fINCF|fINCFSZ|fINFSNZ| fRLCF|fRLNCF|fRRCF|fRRNCF| fTSTFSZ) ? MXTGT_FILE : MXTGT_WREG; // MX_DST wire [1:0] wMXDST = (fMULWF|fMULLW|fMOVLB|fLFSR|fDAW) ? MXDST_EXT : (fBCF|fBSF|fBTG| fCLRF| fMOVFF|fMOVWF| fNEGF|fSETF) ? MXDST_FILE : (fADDLW|fSUBLW| fANDLW|fIORLW|fXORLW| fMOVLW|fRETLW) ? MXDST_WREG : (fADDWF|fADDWFC| fANDWF|fIORWF|fXORWF| fMOVF|fSWAPF|fCOMF| fSUBFWB|fSUBWF|fSUBWFB| fDECF|fDECFSZ|fDCFSNZ| fINCF|fINCFSZ|fINFSNZ| fRLCF|fRLNCF|fRRCF|fRRNCF) ? {1'b1,fOPCL[1]} : MXDST_NULL; // MX_ALU wire [3:0] wMXALU = (fDAW) ? MXALU_DAW : (fMOVLB) ? MXALU_MOVLB : (fLFSR) ? MXALU_LFSR : (fMULLW|fMULWF) ? MXALU_MUL : (fNEGF) ? MXALU_NEG : (fADDLW|fADDWF| fDECF|fDECFSZ|fDCFSNZ) ? MXALU_ADD : (fSUBLW|fSUBWF| fCPFSEQ|fCPFSGT|fCPFSLT| fINCF|fINCFSZ|fINFSNZ) ? MXALU_SUB : (fSUBWFB|fSUBFWB) ? MXALU_SUBC : (fADDWFC) ? MXALU_ADDC : (fRRCF) ? MXALU_RRC : (fRRNCF) ? MXALU_RRNC : (fRLCF) ? MXALU_RLC : (fRLNCF) ? MXALU_RLNC : (fSWAPF) ? MXALU_SWAP : (fSETF|fIORWF|fIORLW|fBSF) ? MXALU_IOR : (fBCF|fANDWF|fANDLW| fRETLW|fBTFSS|fBTFSC|fTSTFSZ| fMOVF|fMOVFF|fMOVWF|fMOVLW) ? MXALU_AND : MXALU_XOR; // MX_BSR wire [1:0] wMXBSR = (fMOVFF) ? MXBSR_LIT : (fBCF|fBSF|fBTG|fBTFSS|fBTFSC| fANDWF|fIORWF|fXORWF|fCOMF| fADDWF|fADDWFC|fSUBWF|fSUBWFB|fSUBFWB|fMULWF| fCLRF|fMOVF|fMOVWF|fSETF|fSWAPF| fCPFSEQ|fCPFSGT|fCPFSLT|fTSTFSZ| fINCF|fINCFSZ|fINFSNZ|fDECF|fDECFSZ|fDCFSNZ| fRLCF|fRLNCF|fRRCF|fRRNCF) ? {1'b1, fOPCL[0]} : MXBSR_NUL; // MX_SKP wire [2:0] wMXSKP = (fTSTFSZ|fINCFSZ|fDECFSZ|fCPFSEQ|fBTFSC) ? MXSKP_SZ : (fINFSNZ|fDCFSNZ|fBTFSS) ? MXSKP_SNZ : (fCPFSGT|fCPFSLT) ? MXSKP_SNC : (fBC|fBNC|fBZ|fBNZ|fBN|fBNN|fBOV|fBNOV) ? MXSKP_SCC : (fBRA|fCALL|fRCALL|fGOTO|fRETFIE|fRETURN|fRETLW) ? MXSKP_SU : MXSKP_NON; // NPC_MX wire [2:0] wMXNPC = (fBC|fBNC|fBN|fBNN|fBOV|fBNOV|fBZ|fBNZ) ? MXNPC_BCC : (fBRA|fRCALL) ? MXNPC_NEAR : (fCALL|fGOTO) ? MXNPC_FAR : (fRETFIE|fRETURN|fRETLW) ? MXNPC_RET : MXNPC_INC; // MX_STA wire [2:0] wMXSTA = (fADDLW|fADDWF|fADDWFC| fSUBLW|fSUBWF|fSUBWFB|fSUBFWB| fDECF|fINCF|fNEGF) ? MXSTA_ALL : (fRRCF|fRLCF) ? MXSTA_CZN : (fRRNCF|fRLNCF| fMOVF|fCOMF| fIORWF|fANDWF|fXORWF|fIORLW|fANDLW|fXORLW) ? MXSTA_ZN : (fDAW) ? MXSTA_C : (fCLRF) ? MXSTA_Z : MXSTA_NONE; // BCC_MX wire [2:0] wMXBCC = fOPCL[2:0]; // STK_MX wire [1:0] wMXSTK = (fRETFIE|fRETLW|fRETURN|fPOP) ? MXSTK_POP : (fCALL|fRCALL|fPUSH|fINT) ? MXSTK_PUSH : MXSTK_NONE; // SHADOW MX wire [1:0] wMXSHA = (fCALL) ? {fOPCL[0] ,1'b0} : (fINT) ? {MXSHA_CALL} : (fRETURN|fRETFIE) ? {1'b0,fOPCK[0]} : 1'b0; // TBLRD/TBLWT MX wire [3:0] wMXTBL = (fTBLRDWT) ? fOPCK[3:0] : MXTBL_NOP; // FSR DECODER parameter [15:0] aPLUSW2 = 16'hFFDB, aPREINC2 = 16'hFFDC, aPOSTDEC2 = 16'hFFDD, aPOSTINC2 = 16'hFFDE, aINDF2 = 16'hFFDF, aPLUSW1 = 16'hFFE3, aPREINC1 = 16'hFFE4, aPOSTDEC1 = 16'hFFE5, aPOSTINC1 = 16'hFFE6, aINDF1 = 16'hFFE7, aPLUSW0 = 16'hFFEB, aPREINC0 = 16'hFFEC, aPOSTDEC0 = 16'hFFED, aPOSTINC0 = 16'hFFEE, aINDF0 = 16'hFFEF; wire fGFF = (rEAPTR[15:6] == 10'h03F) | (rEAPTR[15:6] == 10'h3FF); wire fGFSR0 = (rEAPTR[5:3] == 3'o5); wire fGFSR1 = (rEAPTR[5:3] == 3'o4); wire fGFSR2 = (rEAPTR[5:3] == 3'o3); wire fGPLUSW = (rEAPTR[2:0] == 3'o3); wire fGPREINC = (rEAPTR[2:0] == 3'o4); wire fGPOSTDEC = (rEAPTR[2:0] == 3'o5); wire fGPOSTINC = (rEAPTR[2:0] == 3'o6); wire fGINDF = (rEAPTR[2:0] == 3'o7); wire fPLUSW2 = fGFF & fGFSR2 & fGPLUSW; wire fPREINC2 = fGFF & fGFSR2 & fGPREINC; wire fPOSTDEC2 = fGFF & fGFSR2 & fGPOSTDEC; wire fPOSTINC2 = fGFF & fGFSR2 & fGPOSTINC; wire fINDF2 = fGFF & fGFSR2 & fGINDF; wire fPLUSW1 = fGFF & fGFSR1 & fGPLUSW; wire fPREINC1 = fGFF & fGFSR1 & fGPREINC; wire fPOSTDEC1 = fGFF & fGFSR1 & fGPOSTDEC; wire fPOSTINC1 = fGFF & fGFSR1 & fGPOSTINC; wire fINDF1 = fGFF & fGFSR1 & fGINDF; wire fPLUSW0 = fGFF & fGFSR0 & fGPLUSW; wire fPREINC0 = fGFF & fGFSR0 & fGPREINC; wire fPOSTDEC0 = fGFF & fGFSR0 & fGPOSTDEC; wire fPOSTINC0 = fGFF & fGFSR0 & fGPOSTINC; wire fINDF0 = fGFF & fGFSR0 & fGINDF; parameter [3:0] MXFSR_INDF2 = 4'hF, MXFSR_POSTINC2 = 4'hE, MXFSR_POSTDEC2 = 4'hD, MXFSR_PREINC2 = 4'hC, MXFSR_PLUSW2 = 4'hB, MXFSR_INDF1 = 4'hA, MXFSR_POSTINC1 = 4'h9, MXFSR_POSTDEC1 = 4'h8, MXFSR_PREINC1 = 4'h7, MXFSR_PLUSW1 = 4'h6, MXFSR_INDF0 = 4'h5, MXFSR_POSTINC0 = 4'h4, MXFSR_POSTDEC0 = 4'h3, MXFSR_PREINC0 = 4'h2, MXFSR_PLUSW0 = 4'h1, MXFSR_NORM = 4'h0; wire [3:0] wMXFSR = (fINDF0) ? MXFSR_INDF0 : (fPLUSW0) ? MXFSR_PLUSW0 : (fPREINC0) ? MXFSR_PREINC0 : (fPOSTINC0) ? MXFSR_POSTINC0 : (fPOSTDEC0) ? MXFSR_POSTDEC0 : (fINDF1) ? MXFSR_INDF1 : (fPLUSW1) ? MXFSR_PLUSW1 : (fPREINC1) ? MXFSR_PREINC1 : (fPOSTINC1) ? MXFSR_POSTINC1 : (fPOSTDEC1) ? MXFSR_POSTDEC1 : (fINDF2) ? MXFSR_INDF2 : (fPLUSW2) ? MXFSR_PLUSW2 : (fPREINC2) ? MXFSR_PREINC2 : (fPOSTINC2) ? MXFSR_POSTINC2 : (fPOSTDEC2) ? MXFSR_POSTDEC2 : MXFSR_NORM; always @(negedge clk or negedge qrst) if (!qrst) /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rMXBSR <= 2'h0; // End of automatics else if (qena[1]) rMXBSR <= #1 wMXBSR; // Control Word always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rMXALU <= 4'h0; rMXBCC <= 3'h0; rMXDST <= 2'h0; rMXFSR <= 4'h0; rMXNPC <= 3'h0; rMXSHA <= 2'h0; rMXSKP <= 3'h0; rMXSRC <= 2'h0; rMXSTA <= 3'h0; rMXSTK <= 2'h0; rMXTBL <= 4'h0; rMXTGT <= 2'h0; // End of automatics end else if (qena[3]) begin // if (!qrst) rMXTGT <= #1 wMXTGT; rMXSRC <= #1 wMXSRC; rMXALU <= #1 wMXALU; rMXNPC <= #1 wMXNPC; rMXDST <= #1 wMXDST; rMXSTA <= #1 wMXSTA; rMXSKP <= #1 wMXSKP; rMXBCC <= #1 wMXBCC; rMXSTK <= #1 wMXSTK; rMXFSR <= #1 wMXFSR; rMXSHA <= #1 wMXSHA; rMXTBL <= #1 wMXTBL; end // if (qena[3]) /* * DESCRIPTION * EA pre calculation */ wire [15:0] wFILEBSR = {rBSR, rROMLAT[7:0]}; wire [15:0] wFILEBSA = { {(8){rROMLAT[7]}}, rROMLAT[7:0]}; wire [15:0] wFILELIT = {rBSR[7:4],rROMLAT[11:0]}; //wire [DSIZ-1:0] wFILEBSR = {rBSR, rROMLAT[7:0]}; //wire [DSIZ-1:0] wFILEBSA = { {(8){rROMLAT[7]}}, rROMLAT[7:0]}; //wire [DSIZ-1:0] wFILELIT = {rROMLAT[11:0]}; always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rEAPTR <= 16'h0; // End of automatics end else if (qena[2]) begin case (rMXBSR) MXBSR_BSR: rEAPTR <= #1 wFILEBSR; MXBSR_BSA: rEAPTR <= #1 wFILEBSA; MXBSR_LIT: rEAPTR <= #1 wFILELIT; default: rEAPTR <= #1 rEAPTR; endcase // case(rMXBSR) end /* * DESCRIPTION * Arithmetic Shift Logic Unit */ // BITMASK reg [7:0] rMASK; wire [7:0] wMASK = (fOP3G0) ? 8'h01 : (fOP3G1) ? 8'h02 : (fOP3G2) ? 8'h04 : (fOP3G3) ? 8'h08 : (fOP3G4) ? 8'h10 : (fOP3G5) ? 8'h20 : (fOP3G6) ? 8'h40 : 8'h80; always @(negedge clk or negedge qrst) if (!qrst) /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rMASK <= 8'h0; // End of automatics else if (qena[2] & rNSKP) rMASK <= #1 wMASK; // SRC and TGT reg [7:0] rSRC, rTGT; always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rSRC <= 8'h0; rTGT <= 8'h0; // End of automatics end else if (qena[1] & rNSKP) begin case (rMXSRC) MXSRC_FILE: rSRC <= #1 (rSFRSTB) ? rSFRDAT : dwb_dat_i; //MXSRC_FILE: rSRC <= #1 dwb_dat_i; MXSRC_MASK: rSRC <= #1 rMASK; MXSRC_LIT: rSRC <= #1 8'hFF; default: rSRC <= #1 rWREG; endcase // case(rMXSRC) case (rMXTGT) MXTGT_MASK: rTGT <= #1 ~rMASK; MXTGT_FILE: rTGT <= #1 (rSFRSTB) ? rSFRDAT : dwb_dat_i; //MXTGT_FILE: rTGT <= #1 dwb_dat_i; MXTGT_LIT: rTGT <= #1 rIREG[7:0]; default: rTGT <= #1 rWREG; endcase // case(rMXTGT) end // if (qena[1] & rNSKP) // ALU Operations wire [8:0] wADD = (rSRC + rTGT); wire [8:0] wADDC = wADD + rC; wire [8:0] wSUB = (rTGT - rSRC); wire [8:0] wSUBC = wSUB - ~rC; wire [8:0] wNEG = (0 - rTGT); wire [8:0] wRRC = {rTGT[0],rC,rTGT[7:1]}; wire [8:0] wRLC = {rTGT[7:0],rC}; wire [8:0] wRRNC = {1'b0,rTGT[0],rTGT[7:1]}; wire [8:0] wRLNC = {1'b0,rTGT[6:0],rTGT[7]}; wire [8:0] wAND = {1'b0, rSRC & rTGT}; wire [8:0] wIOR = {1'b0, rSRC | rTGT}; wire [8:0] wXOR = {1'b0, rSRC ^ rTGT}; wire [8:0] wSWAP = {1'b0, rTGT[3:0], rTGT[7:4]}; // RESULT register reg [7:0] rRESULT; always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rRESULT <= 8'h0; // End of automatics end else if (qena[2] & rNSKP) begin case (rMXALU) default: rRESULT <= #1 wXOR; MXALU_AND: rRESULT <= #1 wAND; MXALU_IOR: rRESULT <= #1 wIOR; MXALU_SWAP: rRESULT <= #1 wSWAP; MXALU_RRC: rRESULT <= #1 wRRC; MXALU_RLC: rRESULT <= #1 wRLC; MXALU_RRNC: rRESULT <= #1 wRRNC; MXALU_RLNC: rRESULT <= #1 wRLNC; MXALU_ADD: rRESULT <= #1 wADD; MXALU_ADDC: rRESULT <= #1 wADDC; MXALU_SUB: rRESULT <= #1 wSUB; MXALU_SUBC: rRESULT <= #1 wSUBC; MXALU_NEG: rRESULT <= #1 wNEG; endcase // case(rMXALU) end // if (qena[2] & rNSKP) // C register reg rC_; always @(negedge clk or negedge qrst) if (!qrst) /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rC_ <= 1'h0; // End of automatics else if (qena[2] & rNSKP) case (rMXALU) MXALU_ADD: rC_ <= #1 wADD[8]; MXALU_ADDC: rC_ <= #1 wADDC[8]; MXALU_SUB: rC_ <= #1 ~wSUB[8]; MXALU_SUBC: rC_ <= #1 ~wSUBC[8]; MXALU_RRC: rC_ <= #1 wRRC[8]; MXALU_RLC: rC_ <= #1 wRLC[8]; MXALU_NEG: rC_ <= #1 wNEG[8]; default: rC_ <= #1 rC; endcase // case(rMXALU) wire wC, wZ, wN, wOV, wDC; assign wN = rRESULT[7]; assign wOV = ~(rSRC[7] ^ rTGT[7]) & (rRESULT[7] ^ rSRC[7]); assign wZ = (rRESULT[7:0] == 8'h00); assign wDC = rRESULT[4]; assign wC = rC_; /* * DESCRIPTION * Other Execution Units */ // SPECIAL OPERATION reg rCLRWDT_, rSLEEP_; always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rCLRWDT <= 1'h0; rCLRWDT_ <= 1'h0; rSLEEP <= 1'h0; rSLEEP_ <= 1'h0; // End of automatics end else begin //rCLRWDT <= #1 (rCLRWDT_ & rNSKP); //rSLEEP <= #1 (rSLEEP_ & rNSKP); rCLRWDT <= #1 (rCLRWDT_ & rNSKP & qena[3]); rSLEEP <= #1 (rSLEEP_ & rNSKP & qena[3]); rCLRWDT_ <= #1 (qena[3]) ? fCLRWDT : rCLRWDT_; rSLEEP_ <= #1 (qena[3]) ? fSLEEP : rSLEEP_; end reg rRESET_; always @(negedge clk or negedge xrst) if (!xrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rRESET <= 1'h0; rRESET_ <= 1'h0; // End of automatics end else begin rRESET_ <= #1 ~(fRESET | rWDT[WSIZ]); rRESET <= #1 rRESET_; end // BCC Checker always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rBCC <= 1'h0; // End of automatics end else if (qena[0]) begin case (rMXBCC) MXBCC_BZ: rBCC <= #1 rZ; MXBCC_BNZ: rBCC <= #1 ~rZ; MXBCC_BC: rBCC <= #1 rC; MXBCC_BNC: rBCC <= #1 ~rC; MXBCC_BOV: rBCC <= #1 rOV; MXBCC_BNOV: rBCC <= #1 ~rOV; MXBCC_BN: rBCC <= #1 rN; MXBCC_BNN: rBCC <= #1 ~rN; endcase // case(rMXBCC) end /* * DESCRIPTION * Data WB logic */ reg [15:0] rDWBADR; reg rDWBSTB, rDWBWE; assign dwb_adr_o = rDWBADR; assign dwb_stb_o = rDWBSTB; assign dwb_we_o = rDWBWE; assign dwb_dat_o = rRESULT; // DWB ADR signal wire [DSIZ-1:0] wFSRINC0 = {rFSR0H,rFSR0L} + 1; wire [DSIZ-1:0] wFSRINC1 = {rFSR1H,rFSR1L} + 1; wire [DSIZ-1:0] wFSRINC2 = {rFSR2H,rFSR2L} + 1; wire [DSIZ-1:0] wFSRPLUSW0 = {rFSR0H,rFSR0L} + rWREG; wire [DSIZ-1:0] wFSRPLUSW1 = {rFSR1H,rFSR1L} + rWREG; wire [DSIZ-1:0] wFSRPLUSW2 = {rFSR2H,rFSR2L} + rWREG; always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rDWBADR <= 16'h0; // End of automatics end else if (qrun & rNSKP) case (qfsm) FSM_Q0: case (rMXFSR) MXFSR_INDF0,MXFSR_POSTINC0,MXFSR_POSTDEC0: rDWBADR <= #1 {rFSR0H,rFSR0L}; MXFSR_INDF1,MXFSR_POSTINC1,MXFSR_POSTDEC1: rDWBADR <= #1 {rFSR1H,rFSR1L}; MXFSR_INDF2,MXFSR_POSTINC2,MXFSR_POSTDEC2: rDWBADR <= #1 {rFSR2H,rFSR2L}; MXFSR_PREINC0: rDWBADR <= #1 wFSRINC0; MXFSR_PREINC1: rDWBADR <= #1 wFSRINC1; MXFSR_PREINC2: rDWBADR <= #1 wFSRINC2; MXFSR_PLUSW2: rDWBADR <= #1 wFSRPLUSW2; MXFSR_PLUSW1: rDWBADR <= #1 wFSRPLUSW1; MXFSR_PLUSW0: rDWBADR <= #1 wFSRPLUSW0; default: rDWBADR <= #1 rEAPTR; endcase // case(rMXFSR) FSM_Q1: rDWBADR <= #1 (rMXBSR == MXBSR_LIT) ? {rROMLAT[11:0]} : rDWBADR; default: rDWBADR <= #1 rDWBADR; endcase // case(qfsm) // DWB WE signal always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rDWBWE <= 1'h0; // End of automatics end else if (qrun & rNSKP) case (qfsm) FSM_Q2: rDWBWE <= #1 (rMXDST == MXDST_FILE); default: rDWBWE <= #1 1'b0; endcase // case(qfsm) // DWB STB signal always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rDWBSTB <= 1'h0; // End of automatics end else if (qrun & rNSKP) case (qfsm) FSM_Q2: rDWBSTB <= #1 (rMXDST == MXDST_FILE); FSM_Q0: rDWBSTB <= #1 ((rMXSRC == MXSRC_FILE) | (rMXTGT == MXTGT_FILE)); default: rDWBSTB <= #1 1'b0; endcase // case(qfsm) // STACK wire [ISIZ-1:0] wSTKW = {rTOSU,rTOSH,rTOSL}; wire [ISIZ-1:0] wSTKR; wire wSTKE = (qena[1]); reg [ISIZ-1:0] rSTKRAM [0:31]; assign wSTKR = rSTKRAM[rSTKPTR[4:0]]; always @(posedge clk) if (wSTKE) rSTKRAM[rSTKPTR_[4:0]] <= wSTKW; /* * SFR Bank */ parameter [15:0] //aRCON = 16'hFFD0, aWDTCON = 16'hFFD1, aSTATUS = 16'hFFD8,// aFSR2L = 16'hFFD9,// aFSR2H = 16'hFFDA,// aBSR = 16'hFFE0,// aFSR1L = 16'hFFE1,// aFSR1H = 16'hFFE2,// aWREG = 16'hFFE8,// aFSR0L = 16'hFFE9,// aFSR0H = 16'hFFEA,// aPRODL = 16'hFFF3,// aPRODH = 16'hFFF4,// aPRNG = 16'hFFD4,// aTABLAT = 16'hFFF5,// aTBLPTRL = 16'hFFF6,// aTBLPTRH = 16'hFFF7,// aTBLPTRU = 16'hFFF8,// aPCL = 16'hFFF9,// aPCLATH = 16'hFFFA,// aPCLATU = 16'hFFFB,// aSTKPTR = 16'hFFFC,// aTOSL = 16'hFFFD,// aTOSH = 16'hFFFE,// aTOSU = 16'hFFFF;// // Read SFR always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rSFRDAT <= 8'h0; // End of automatics end else if (rDWBSTB & rNSKP) begin case (rDWBADR[5:0]) aWDTCON[5:0]: rSFRDAT <= #1 {7'd0,rSWDTEN}; aSTATUS[5:0]: rSFRDAT <= #1 {3'd0,rN,rOV,rZ,rDC,rC}; aFSR2L[5:0]: rSFRDAT <= #1 rFSR2L; aFSR2H[5:0]: rSFRDAT <= #1 rFSR2H; aBSR[5:0]: rSFRDAT <= #1 rBSR; aFSR1L[5:0]: rSFRDAT <= #1 rFSR1L; aFSR1H[5:0]: rSFRDAT <= #1 rFSR1H; aWREG[5:0]: rSFRDAT <= #1 rWREG; aFSR0L[5:0]: rSFRDAT <= #1 rFSR0L; aFSR0H[5:0]: rSFRDAT <= #1 rFSR0H; aPRODL[5:0]: rSFRDAT <= #1 rPRODL; aPRODH[5:0]: rSFRDAT <= #1 rPRODH; aPRNG[5:0]: rSFRDAT <= #1 rPRNG; aTABLAT[5:0]: rSFRDAT <= #1 rTABLAT; aTBLPTRL[5:0]: rSFRDAT <= #1 rTBLPTRL; aTBLPTRH[5:0]: rSFRDAT <= #1 rTBLPTRH; aTBLPTRU[5:0]: rSFRDAT <= #1 rTBLPTRU; aPCL[5:0]: rSFRDAT <= #1 rPCL; aPCLATH[5:0]: rSFRDAT <= #1 rPCLATH; aPCLATU[5:0]: rSFRDAT <= #1 rPCLATU; aSTKPTR[5:0]: rSFRDAT <= #1 {rSTKFUL,rSTKUNF,1'b0,rSTKPTR[4:0]}; aTOSU[5:0]: rSFRDAT <= #1 rTOSU; aTOSH[5:0]: rSFRDAT <= #1 rTOSH; aTOSL[5:0]: rSFRDAT <= #1 rTOSL; default rSFRDAT <= #1 rSFRDAT; endcase // case(rDWBADR) end wire wSFRSTB = (rDWBADR[15:6] == 10'h3FF); always @(posedge clk or negedge qrst) if (!qrst) begin // Beginning of autoreset for uninitialized flops rSFRSTB <= 1'h0; // End of automatics end else if (rDWBSTB & rNSKP) begin case (rDWBADR[5:0]) aFSR2L[5:0],aFSR2H[5:0],aFSR1L[5:0],aFSR1H[5:0],aFSR0H[5:0],aFSR0L[5:0], aWDTCON[5:0],aBSR[5:0],aWREG[5:0],aSTATUS[5:0], aPRODL[5:0],aPRODH[5:0],aPRNG[5:0], aTABLAT[5:0],aTBLPTRH[5:0],aTBLPTRU[5:0],aTBLPTRL[5:0], aPCL[5:0],aPCLATH[5:0],aPCLATU[5:0], aSTKPTR[5:0],aTOSU[5:0],aTOSH[5:0],aTOSL[5:0]: rSFRSTB <= #1 wSFRSTB; default rSFRSTB <= #1 1'b0; endcase // case(rDWBADR) end // WDTCON always @(posedge clk or negedge qrst) if (!qrst) rSWDTEN <= 1; else if (qena[3] & rNSKP) rSWDTEN <= #1 ((rDWBADR == aWDTCON) & rDWBWE) ? rRESULT[0] : rSWDTEN; // TOSH, TOSU, TOSL, STKPTR wire [5:0] wSTKINC = rSTKPTR + 1; wire [5:0] wSTKDEC = rSTKPTR - 1; always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rSTKPTR_ <= 6'h0; // End of automatics end else if (qena[0]) begin rSTKPTR_ <= #1 wSTKINC; end always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rSTKFUL <= 1'h0; rSTKPTR <= 6'h0; rSTKUNF <= 1'h0; // End of automatics end else if (qrun & rNSKP) begin rSTKFUL <= #1 (wSTKINC == 6'h20); rSTKUNF <= #1 (wSTKDEC == 6'h3F); case (qfsm) FSM_Q3: begin rSTKPTR <= #1 ((rDWBADR == aSTKPTR) & rDWBWE) ? rRESULT : rSTKPTR; end FSM_Q2: begin case (rMXSTK) MXSTK_PUSH: begin rSTKPTR <= #1 (rSTKFUL) ? rSTKPTR : wSTKINC; end MXSTK_POP: begin rSTKPTR <= #1 (rSTKUNF) ? rSTKPTR : wSTKDEC; end default: begin rSTKPTR <= #1 rSTKPTR; end endcase // case(rMXSTK) end // case: FSM_Q2 default: begin rSTKPTR <= #1 rSTKPTR; end endcase // case(qfsm) end // if (qrun & rNSKP) always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rTOSH <= 8'h0; rTOSL <= 8'h0; rTOSU <= 8'h0; // End of automatics end else if (qrun & rNSKP) case (qfsm) FSM_Q3: begin rTOSU <= #1 ((rDWBADR == aTOSU) & rDWBWE) ? rRESULT : rTOSU; rTOSH <= #1 ((rDWBADR == aTOSH) & rDWBWE) ? rRESULT : rTOSH; rTOSL <= #1 ((rDWBADR == aTOSL) & rDWBWE) ? rRESULT : rTOSL; end FSM_Q2: begin case (rMXSTK) MXSTK_PUSH: begin {rTOSU,rTOSH,rTOSL} <= #1 {wPCLAT,1'b0}; end MXSTK_POP: begin {rTOSU,rTOSH,rTOSL} <= #1 wSTKR; end default: begin rTOSU <= #1 rTOSU; rTOSH <= #1 rTOSH; rTOSL <= #1 rTOSL; end endcase // case(rMXSTK) end // case: FSM_Q2 default: begin rTOSU <= #1 rTOSU; rTOSH <= #1 rTOSH; rTOSL <= #1 rTOSL; end endcase // case(qfsm) // SHADOW REGISTERS always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rBSR_ <= 8'h0; rSTATUS_ <= 5'h0; rWREG_ <= 8'h0; // End of automatics end else if (qena[3] & rNSKP) begin rWREG_ <= #1 (rMXSHA == MXSHA_CALL) ? rWREG : rWREG_; rBSR_ <= #1 (rMXSHA == MXSHA_CALL) ? rBSR : rBSR_; rSTATUS_ <= #1 (rMXSHA == MXSHA_CALL) ? {rN,rOV,rZ,rDC,rC} : rSTATUS_; end // STATUS reg [2:0] rMXSTAL; always @(negedge clk or negedge qrst) if (!qrst) /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rMXSTAL <= 3'h0; // End of automatics else if (qena[3]) rMXSTAL <= #1 rMXSTA; always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rC <= 1'h0; rDC <= 1'h0; rN <= 1'h0; rOV <= 1'h0; rZ <= 1'h0; // End of automatics end else if (qrun & rNSKP) begin case (qfsm) default: {rN,rOV,rZ,rDC,rC} <= #1 ((rDWBADR == aSTATUS) & rDWBWE) ? rRESULT : {rN,rOV,rZ,rDC,rC}; FSM_Q2: {rN,rOV,rZ,rDC,rC} <= #1 (rMXSHA == MXSHA_RET) ? rSTATUS_ : {rN,rOV,rZ,rDC,rC}; FSM_Q0: case (rMXSTAL) MXSTA_ALL: {rN,rOV,rZ,rDC,rC} <= #1 {wN,wOV,wZ,wDC,wC}; MXSTA_CZN: {rN,rOV,rZ,rDC,rC} <= #1 {wN,rOV,wZ,rDC,wC}; MXSTA_ZN: {rN,rOV,rZ,rDC,rC} <= #1 {wN,rOV,wZ,rDC,rC}; MXSTA_Z: {rN,rOV,rZ,rDC,rC} <= #1 {rN,rOV,wZ,rDC,rC}; MXSTA_C: {rN,rOV,rZ,rDC,rC} <= #1 {rN,rOV,rZ,rDC,wC}; default: {rN,rOV,rZ,rDC,rC} <= #1 {rN,rOV,rZ,rDC,rC}; endcase // case(rMXSTA) endcase // case(qfsm) end // if (qena[3] & rNSKP) // WREG // TODO: DAW wire [7:0] wDAW = ((rMXALU == MXALU_DAW) & (rMXDST == MXDST_EXT)) ? 8'h00 : rWREG; always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rWREG <= 8'h0; // End of automatics end else if (qena[3] & rNSKP) begin rWREG <= #1 (((rDWBADR == aWREG) & rDWBWE) | (rMXDST == MXDST_WREG)) ? rRESULT : (rMXSHA == MXSHA_RET) ? rWREG_ : rWREG; end // BSR always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rBSR <= 8'h0; // End of automatics end else if (qrun & rNSKP) case (qfsm) FSM_Q3: rBSR <= #1 (((rDWBADR == aBSR) & rDWBWE)) ? rRESULT : (rMXSHA == MXSHA_RET) ? rBSR_ : rBSR; default: rBSR <= #1 ((rMXALU == MXALU_MOVLB) & (rMXDST == MXDST_EXT)) ? rIREG[7:0] : rBSR; endcase // case(qfsm) // FSRXH/FSRXL wire [DSIZ-1:0] wFSRDEC0 = {rFSR0H,rFSR0L} - 1; wire [DSIZ-1:0] wFSRDEC1 = {rFSR1H,rFSR1L} - 1; wire [DSIZ-1:0] wFSRDEC2 = {rFSR2H,rFSR2L} - 1; always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rFSR0H <= 8'h0; rFSR0L <= 8'h0; rFSR1H <= 8'h0; rFSR1L <= 8'h0; rFSR2H <= 8'h0; rFSR2L <= 8'h0; // End of automatics end else if (qrun & rNSKP) // if (!qrst) case (qfsm) FSM_Q3: begin rFSR0H <= #1 (((rDWBADR == aFSR0H) & rDWBWE)) ? rRESULT : rFSR0H; rFSR0L <= #1 (((rDWBADR == aFSR0L) & rDWBWE)) ? rRESULT : rFSR0L; rFSR1H <= #1 (((rDWBADR == aFSR1H) & rDWBWE)) ? rRESULT : rFSR1H; rFSR1L <= #1 (((rDWBADR == aFSR1L) & rDWBWE)) ? rRESULT : rFSR1L; rFSR2H <= #1 (((rDWBADR == aFSR2H) & rDWBWE)) ? rRESULT : rFSR2H; rFSR2L <= #1 (((rDWBADR == aFSR2L) & rDWBWE)) ? rRESULT : rFSR2L; end FSM_Q2: begin // Post Inc/Dec case (rMXFSR) MXFSR_POSTINC0: {rFSR0H,rFSR0L} <= #1 wFSRINC0; MXFSR_POSTINC1: {rFSR1H,rFSR1L} <= #1 wFSRINC1; MXFSR_POSTINC2: {rFSR2H,rFSR2L} <= #1 wFSRINC2; MXFSR_POSTDEC0: {rFSR0H,rFSR0L} <= #1 wFSRDEC0; MXFSR_POSTDEC1: {rFSR1H,rFSR1L} <= #1 wFSRDEC1; MXFSR_POSTDEC2: {rFSR2H,rFSR2L} <= #1 wFSRDEC2; endcase // case(rMXFSR) end // case: FSM_Q2 FSM_Q1: begin // Load Literals if ((rMXALU == MXALU_LFSR) & (rMXDST == MXDST_EXT)) case (rIREG[5:4]) 2'o0: {rFSR0H,rFSR0L} <= #1 {rIREG[3:0],rROMLAT[7:0]}; 2'o1: {rFSR1H,rFSR1L} <= #1 {rIREG[3:0],rROMLAT[7:0]}; 2'o2: {rFSR2H,rFSR2L} <= #1 {rIREG[3:0],rROMLAT[7:0]}; endcase // case(rIREG[5:4]) end // case: FSM_Q1 FSM_Q0: begin // Pre inc case (rMXFSR) MXFSR_PREINC0: {rFSR0H,rFSR0L} <= #1 wFSRINC0; MXFSR_PREINC1: {rFSR1H,rFSR1L} <= #1 wFSRINC1; MXFSR_PREINC2: {rFSR2H,rFSR2L} <= #1 wFSRINC2; endcase // case(rMXFSR) end endcase // case(qfsm) // PRODH/PRODL wire [15:0] wPRODUCT = ((rMXALU == MXALU_MUL) & (rMXDST == MXDST_EXT)) ? (rSRC * rTGT) : {rPRODH,rPRODL}; always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rPRODH <= 8'h0; rPRODL <= 8'h0; // End of automatics end else if (qena[3] & rNSKP) begin rPRODH <= #1 (((rDWBADR == aPRODH) & rDWBWE)) ? rRESULT : wPRODUCT[15:8]; rPRODL <= #1 (((rDWBADR == aPRODL) & rDWBWE)) ? rRESULT : wPRODUCT[7:0]; end // TBLATU/TBLATH/TBLATL wire [ISIZ-1:0] wTBLINC = {rTBLPTRU,rTBLPTRH,rTBLPTRL} + 1; wire [ISIZ-1:0] wTBLAT = {rTBLPTRU,rTBLPTRH,rTBLPTRL}; wire [ISIZ-1:0] wTBLDEC = {rTBLPTRU,rTBLPTRH,rTBLPTRL} - 1; always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rTBLPTRH <= 8'h0; rTBLPTRL <= 8'h0; rTBLPTRU <= 8'h0; // End of automatics end else if (qrun & rNSKP) case (qfsm) FSM_Q0: {rTBLPTRU,rTBLPTRH,rTBLPTRL} <= #1 ((rMXTBL == MXTBL_WTPRE) | (rMXTBL == MXTBL_RDPRE)) ? wTBLINC : wTBLAT; FSM_Q2: {rTBLPTRU,rTBLPTRH,rTBLPTRL} <= #1 ((rMXTBL == MXTBL_WTINC) | (rMXTBL == MXTBL_RDINC)) ? wTBLINC : ((rMXTBL == MXTBL_WTDEC) | (rMXTBL == MXTBL_RDDEC)) ? wTBLDEC : wTBLAT; default: begin rTBLPTRU <= #1 ((rDWBADR == aTBLPTRU) & rDWBWE) ? rRESULT : rTBLPTRU; rTBLPTRH <= #1 ((rDWBADR == aTBLPTRH) & rDWBWE) ? rRESULT : rTBLPTRH; rTBLPTRL <= #1 ((rDWBADR == aTBLPTRL) & rDWBWE) ? rRESULT : rTBLPTRL; end endcase // case(qfsm) // TABLAT always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rTABLAT <= 8'h0; // End of automatics end else if (qena[3] & rNSKP) case (rMXTBL) MXTBL_RD,MXTBL_RDINC,MXTBL_RDDEC,MXTBL_RDPRE: rTABLAT <= #1 rILAT; default: rTABLAT <= #1 (rDWBWE & (rDWBADR == aTABLAT)) ? rRESULT : rTABLAT; endcase // case(rMXTBL) // PCLATU/PCLATH always @(posedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rPCLATH <= 8'h0; rPCLATU <= 8'h0; // End of automatics end else if (qena[3] & rNSKP) begin rPCLATU <= #1 ((rDWBADR == aPCLATU) & rDWBWE) ? rRESULT : ((rDWBADR == aPCL) & ~rDWBWE) ? rPCU : rPCLATU; rPCLATH <= #1 ((rDWBADR == aPCLATH) & rDWBWE) ? rRESULT : ((rDWBADR == aPCL) & ~rDWBWE) ? rPCH : rPCLATH; end // PCU/PCH/PCL always @(negedge clk or negedge qrst) if (!qrst) begin /*AUTORESET*/ // Beginning of autoreset for uninitialized flops rPCH <= 8'h0; rPCL <= 8'h0; rPCU <= 5'h0; // End of automatics end else if (qena[3]) begin {rPCU,rPCH,rPCL} <= #1 ((rDWBADR == aPCL) & rDWBWE) ? {rPCLATU,rPCLATH,rRESULT} : {rPCNXT,1'b0}; end // SKIP register wire wSKP = (rMXSKP == MXSKP_SZ) ? wZ : (rMXSKP == MXSKP_SNZ) ? ~wZ : (rMXSKP == MXSKP_SNC) ? wC : (rMXSKP == MXSKP_SCC) ? rBCC : (rMXSKP == MXSKP_SU) ? (1'b1) : 1'b0; always @(negedge clk or negedge qrst) if (!qrst) rNSKP <= 1'h1; else if (qena[3]) rNSKP <= #1 ((rDWBADR == aPCL) & rDWBWE) ? 1'b0 : ~(wSKP & rNSKP); endmodule // ae18_core