OpenCores
URL https://opencores.org/ocsvn/ae18/ae18/trunk

Subversion Repositories ae18

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /ae18/trunk/rtl/verilog
    from Rev 18 to Rev 20
    Reverse comparison

Rev 18 → Rev 20

/ae18_core.v
0,0 → 1,1632
/*
* $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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.