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

Subversion Repositories Aquarius

[/] [Aquarius/] [trunk/] [verilog/] [datapath.v] - Rev 12

Compare with Previous | Blame | View Log

//======================================================
// Aquarius Project
//    SuperH-2 ISA Compatible RISC CPU
//------------------------------------------------------
// Module      : Data Path Unit
//------------------------------------------------------
// File        : datapath.v
// Library     : none
// Description : Data Path in CPU.
// Simulator   : Icarus Verilog (Cygwin)
// Synthesizer : Xilinx XST (Windows XP)
// Author      : Thorn Aitch
//------------------------------------------------------
// Revision Number : 1
// Date of Change  : 23rd April 2002
// Creator         : Thorn Aitch
// Description     : Initial Design				  
//------------------------------------------------------
// Revision Number : 2
// Date of Change  : 30th April 2003
// Modifier        : Thorn Aitch
// Description     : Release Version 1.0
//------------------------------------------------------
// Revision Number : 3
// Date of Change  : 10th December 2003
// Modifier        : Thorn Aitch
// Description     : Release Version 1.1
//                   Inhibit substitution of "x"
//                   except for defalut statement whose
//                   case describes all logic spaces. 
//======================================================
// Copyright (C) 2002-2003, Thorn Aitch
//
// Designs can be altered while keeping list of
// modifications "the same as in GNU" No money can
// be earned by selling the designs themselves, but
// anyone can get money by selling the implementation
// of the design, such as ICs based on some cores, 
// boards based on some schematics or Layouts, and
// even GUI interfaces to text mode drivers.
// "The same as GPL SW" Any update to the design
// should be documented and returned to the design. 
// Any derivative work based on the IP should be free
// under OpenIP License. Derivative work means any
// update, change or improvement on the design. 
// Any work based on the design can be either made
// free under OpenIP license or protected by any other
// license. Work based on the design means any work uses
// the OpenIP Licensed core as a building black without
// changing anything on it with any other blocks to
// produce larger design.  There is NO WARRANTY on the
// functionality or performance of the design on the
// real hardware implementation.
// On the other hand, the SuperH-2 ISA (Instruction Set
// Architecture) executed by Aquarius is rigidly
// the property of Renesas Corp. Then you have all 
// responsibility to judge if there are not any 
// infringements to Renesas's rights regarding your 
// Aquarius adoption into your design. 
// By adopting Aquarius, the user assumes all 
// responsibility for its use.
// This project may cause any damages around you, for 
// example, loss of properties, data, money, profits,
// life, or business etc. By adopting this source, 
// the user assumes all responsibility for its use.
//======================================================
 
`include "timescale.v"
`include "defines.v"
 
//*************************************************
// Module Definition
//*************************************************
module datapath(
    // system signal
    CLK, RST, SLOT,
    // general register strobe and the number
    RDREG_X,  RDREG_Y,  WRREG_Z,  WRREG_W,
    REGNUM_X, REGNUM_Y, REGNUM_Z, REGNUM_W,
    // ALU function
    ALUFUNC,
    // memory access
    MA_AD,    MA_DW,    MA_DR,
    WRMAAD_Z, WRMADW_X, WRMADW_Y, RDMADR_W,
    // multiplier
    MACIN1, MACIN2,
    MACSEL1, MACSEL2,
    MACH, MACL,
    RDMACH_X, RDMACL_X,
    RDMACH_Y, RDMACL_Y,
    // status register
    RDSR_X, RDSR_Y,
    WRSR_Z, WRSR_W,
    // S bit for MAC
    MAC_S, MAC_S_LATCH,
    // global base register
    RDGBR_X, RDGBR_Y,
    WRGBR_Z, WRGBR_W,
    // vector base register
    RDVBR_X, RDVBR_Y,
    WRVBR_Z, WRVBR_W,
    // procedure register
    RDPR_X, RDPR_Y,
    WRPR_Z, WRPR_W, WRPR_PC,
    // program counter
    RDPC_X, RDPC_Y, WRPC_Z,
    INCPC, IFADSEL, IF_AD,
    // make constant
    CONST_IFDR, 
    CONST_ZERO4, CONST_ZERO42, CONST_ZERO44,                         
    CONST_ZERO8, CONST_ZERO82, CONST_ZERO84,
    CONST_SIGN8, CONST_SIGN82, CONST_SIGN122,
    RDCONST_X, RDCONST_Y,
    // register forward
    REG_FWD_X, REG_FWD_Y,
    // commands for comparator and shifter
    CMPCOM, SFTFUNC,
    // read controls to Z-BUS
    RDSFT_Z, 
    // T value for Bcc judgement
    T_BCC,
    // SR control
    T_CMPSET, T_CRYSET, T_TSTSET, T_SFTSET,
    QT_DV1SET, MQT_DV0SET, T_CLR, T_SET, MQ_CLR,
    // Temporary Register
    RDTEMP_X,
    WRTEMP_Z, WRMAAD_TEMP,
    // I bit in Status Register
    RST_SR, IBIT, ILEVEL, WR_IBIT
    );
 
//-------------------
// Module I/O Signals
//-------------------
    input  CLK;            // clock
    input  RST;            // reset
    input  SLOT;           // cpu pipe slot
 
    input  RDREG_X;        // read Rn to X-bus
    input  RDREG_Y;        // read Rn to Y-bus
    input  WRREG_Z;        // write Rn from Z-bus
    input  WRREG_W;        // write Rn from W-bus
 
    input [3:0] REGNUM_X;  // register number to read to X-bus
    input [3:0] REGNUM_Y;  // register number to read to Y-bus
    input [3:0] REGNUM_Z;  // register number to write from Z-bus
    input [3:0] REGNUM_W;  // register number to write from W-bus
 
    input  [4:0]  ALUFUNC; // ALU function
 
    output [31:0] MA_AD;   // memory access address
    output [31:0] MA_DW;   // memory write data
    input  [31:0] MA_DR;   // memory read data
    input  WRMAAD_Z;       // output MA_AD from Z-bus
    input  WRMADW_X;       // output MA_DW from X-bus  
    input  WRMADW_Y;       // output MA_DW from Y-bus
    input  RDMADR_W;       // input MA_DR to W-bus
 
    output [31:0] MACIN1;  // data1 to mult.v
    output [31:0] MACIN2;  // data2 to mult.v
    input  [1:0] MACSEL1;  // select data of MACIN1 (00:from X, 01:from Z, 1?:from W) 
    input  [1:0] MACSEL2;  // select data of MACIN2 (00:from Y, 01:from Z, 1?:from W) 
    input  [31:0] MACH;    // physical data of MACH
    input  [31:0] MACL;    // physical data of MACL
    input  RDMACH_X;       // read MACH to X-bus
    input  RDMACL_X;       // read MACL to X-bus
    input  RDMACH_Y;       // read MACH to Y-bus
    input  RDMACL_Y;       // read MACL to Y-bus
 
    input  RDSR_X;         // read SR to X-bus
    input  RDSR_Y;         // read SR to Y-bus
    input  WRSR_Z;         // write SR from Z-bus
    input  WRSR_W;         // write SR from W-bus
    output MAC_S;          // latched S bit in SR (= SR[S])
    input  MAC_S_LATCH;    // latch command of S bit in SR
 
    input  RDGBR_X;        // read GBR to X-bus
    input  RDGBR_Y;        // read GBR to Y-bus
    input  WRGBR_Z;        // write GBR from Z-bus
    input  WRGBR_W;        // write GBR from W-bus
 
    input  RDVBR_X;        // read VBR to X-bus
    input  RDVBR_Y;        // read VBR to Y-bus
    input  WRVBR_Z;        // write VBR from Z-bus
    input  WRVBR_W;        // write VBR from W-bus
 
    input  RDPR_X;         // read PR to X-bus
    input  RDPR_Y;         // read PR to Y-bus
    input  WRPR_Z;         // write PR from Z-bus
    input  WRPR_W;         // write PR from W-bus
    input  WRPR_PC;        // write PR from PC
 
    input  RDPC_X;         // read PC to X-bus
    input  RDPC_Y;         // read PC to Y-bus
    inout  WRPC_Z;         // write PC from Z-bus
    input  INCPC;          // increment PC (PC+2->PC)
    input  IFADSEL;        // select IF_AD output from INC(0) or Z-bus(1)
    output [31:0] IF_AD;   // instruction fetch address
 
    input  [15:0] CONST_IFDR;   // instruction fetch data to make constant
    input  CONST_ZERO4;    // take constant from lower 4 bit as unsigned value 
    input  CONST_ZERO42;   // take constant from lower 4 bit as unsigned value * 2
    input  CONST_ZERO44;   // take constant from lower 4 bit as unsigned value * 4
    input  CONST_ZERO8;    // take constant from lower 8 bit as unsigned value
    input  CONST_ZERO82;   // take constant from lower 8 bit as unsigned value * 2
    input  CONST_ZERO84;   // take constant from lower 8 bit as unsigned value * 4
    input  CONST_SIGN8;    // take constant from lower 8 bit as signed value      
    input  CONST_SIGN82;   // take constant from lower 8 bit as signed value * 2
    input  CONST_SIGN122;  // take constant from lower 12 bit as signed value * 2
    input  RDCONST_X;      // read constant to X-bus
    input  RDCONST_Y;      // read constant to Y-bus
    input  REG_FWD_X;      // register forward from W-bus to X-bus
    input  REG_FWD_Y;      // register forward from W-bus to Y-bus
 
    input  [2:0] CMPCOM;   // define comparator operation (command)
    input  [4:0] SFTFUNC;  // Shifter Function
 
    input  RDSFT_Z;        // read SFTOUT to Z-BUS
 
    output T_BCC;          // T value for Bcc judgement
    input  T_CMPSET;       // reflect comparator result to T
    input  T_CRYSET;       // reflect carry/borrow out to T
    input  T_TSTSET;       // reflect tst result to T
    input  T_SFTSET;       // reflect shifted output to T
    input  QT_DV1SET;      // reflect DIV1 result to Q and T
    input  MQT_DV0SET;     // reflect DIV0S result to M, Q and T
    input  T_CLR;          // clear T
    input  T_SET;          // set T
    input  MQ_CLR;         // clear M and Q
 
    input  RDTEMP_X;       // read TEMP to X-bus
    input  WRTEMP_Z;       // write to TEMP from Z-bus
    input  WRMAAD_TEMP;    // output MAAD from TEMP
 
    input  RST_SR;         // reset SR
    output [3:0] IBIT;     // I bit in SR
    input  [3:0] ILEVEL;   // IRQ Level
    input  WR_IBIT;        // Write ILEVEL to I bit in SR 
 
//-----------------
// Internal Signals
//-----------------
    integer i;
 
    reg  [31:0] XBUS;     // internal X-bus
    reg  [31:0] YBUS;     // internal Y-bus
    reg  [31:0] ZBUS;     // internal Z-bus
    reg  [31:0] WBUS;     // internal W-bus
    reg  [31:0] VBUS;     // internal V-bus
 
    wire [31:0] REG_X;     // register out toward X
    wire [31:0] REG_Y;     // register out toward Y
    wire [31:0] REG_0;     // R0 value
 
    reg  [9:0]  SR;        // Status Register
    reg  MAC_S;            // latched S bit in SR
 
    reg  [31:0] GBR;       // Global Base Register
    reg  [31:0] VBR;       // Vector Base Register
    reg  [31:0] PR;        // Procedure Register
 
    reg  [31:0] ALUINX;    // ALU internal signal on X-side
    reg  [31:0] ALUINY;    // ALU internal signal on Y-side
    reg  ADDSUB;           // Specify ADD or SUB (ADD=0, SUB=1)
    reg  [32:0] ADDSUBXY;  // Carry :ADDSUBXY = ALUINX + ALUINY + Carry
                           // Borrow:ADDSUBXY = ALUINX - ALUINY - Borrow
    reg  [32:0] ALUINY_EOR;// = ADDSUB ^ ALUINY[]
    reg  [31:0] ALUOUT;    // ALU output
    reg  [31:0] MACIN1;    // data1 to mult.v
    reg  [31:0] MACIN2;    // data2 to mult.v
 
    reg  [31:0] MA_AD;     // Memory Access Address
    reg  [31:0] MA_DW;     // Memory Write Data
    reg  [31:0] IF_AD;     // Instruction Fetch Address
 
    reg  [31:0] PC;        // program counter
    reg  [31:0] PCADD2;    // =PC+2
 
    reg  [31:0] CONST;     // Constant Value generated from Instruction Field
 
    reg  EQMSB;                  // XBUS[31] == YBUS[31]
    reg  EQHH, EQHL, EQLH, EQLL; // XBUS[n+7:n] == YBUS[n+7:n], n=28,16,8,0
    reg  EQ;                     // XBUS[30:0] == YBUS[30:0]
    reg  HI;                     // XBUS[30:0] > YBUS[30:0]
    reg  CMPRESULT;              // result from comparator according to CMPCOM  
    reg  T_BCC;                  // T value for Bcc judgement
 
    reg  [31:0] SFTOUT;   // Shifter Output
    reg  SFTO;            // Shifted Output to be sent to T bit
 
    reg  SUBGT, ADDLT;    // Divider internal signal
    reg  Q_DIV1;          // Divider Result of Q by DIV1
    reg  T_DIV1;          // Divider Result of T by DIV1
    reg  T_DIV0S;         // Divider Result of T by DIV0S
 
    reg  CRYI;   // carry/borrow input to ALU operation
    reg  CRYO;   // carry/borrow output to T
    reg  TSTO;   // test resut to T
 
    reg  [31:0] R0;    // index register R0 to make MA address; @(R0,Rn)
    reg  [31:0] TEMP ; // Temorary Register
 
    wire [3:0] IBIT;   // I bit in SR
 
//----------
// X-BUS
//----------
    always @(WBUS  or REG_FWD_X
          or REG_X or RDREG_X 
          or MACH  or RDMACH_X
          or MACL  or RDMACL_X
          or PC    or RDPC_X
          or CONST or RDCONST_X
          or SR    or RDSR_X
          or GBR   or RDGBR_X
          or VBR   or RDVBR_X
          or PR    or RDPR_X
          or TEMP  or RDTEMP_X)
    begin
        casex ({REG_FWD_X,
                RDREG_X, RDMACH_X, RDMACL_X, RDPC_X, RDCONST_X, 
                RDSR_X, RDGBR_X, RDVBR_X, RDPR_X, RDTEMP_X})
            11'b1?????????? : XBUS <= WBUS;
            11'b01000000000 : XBUS <= REG_X;
            11'b00100000000 : XBUS <= MACH;
            11'b00010000000 : XBUS <= MACL;
            11'b00001000000 : XBUS <= PC;
            11'b00000100000 : XBUS <= CONST;
            11'b00000010000 : XBUS <= {22'h000000, SR};
            11'b00000001000 : XBUS <= GBR;
            11'b00000000100 : XBUS <= VBR;
            11'b00000000010 : XBUS <= PR; 
            11'b00000000001 : XBUS <= TEMP;
            default         : XBUS <= 32'h00000000;
        endcase
    end
 
//----------
// Y-BUS
//----------
    always @(WBUS  or REG_FWD_Y
          or REG_Y or RDREG_Y
          or MACH  or RDMACH_Y
          or MACL  or RDMACL_Y
          or PC    or RDPC_Y
          or CONST or RDCONST_Y
          or SR    or RDSR_Y 
          or GBR   or RDGBR_Y
          or VBR   or RDVBR_Y
          or PR    or RDPR_Y)
    begin
        casex ({REG_FWD_Y,
                RDREG_Y, RDMACH_Y, RDMACL_Y, RDPC_Y, RDCONST_Y, 
                RDSR_Y, RDGBR_Y, RDVBR_Y, RDPR_Y})
            10'b1????????? : YBUS <= WBUS;
            10'b0100000000 : YBUS <= REG_Y;
            10'b0010000000 : YBUS <= MACH;
            10'b0001000000 : YBUS <= MACL;
            10'b0000100000 : YBUS <= PC;
            10'b0000010000 : YBUS <= CONST;
            10'b0000001000 : YBUS <= {22'h000000, SR}; 
            10'b0000000100 : YBUS <= GBR;
            10'b0000000010 : YBUS <= VBR;
            10'b0000000001 : YBUS <= PR;
            default        : YBUS <= 32'h00000000;
        endcase
    end
 
//------
// Z-BUS
//------
    always @(ALUOUT
          or SFTOUT or RDSFT_Z)
    begin
        case (RDSFT_Z)
            1'b0    : ZBUS <= ALUOUT;
            1'b1    : ZBUS <= SFTOUT;
            default : ZBUS <= 32'hxxxxxxxx;
        endcase
    end
 
//------
// W-BUS
//------
    always @(MA_DR or RDMADR_W)
    begin
        if (RDMADR_W == 1'b1)
            WBUS <= MA_DR;
        else
            WBUS <= 32'h00000000;
    end
 
//-----------------
// General Register
//-----------------
   register REGISTER(
    // system signal
    .CLK(CLK), .SLOT(SLOT),
    // general register strobe and the number
    .WRREG_Z(WRREG_Z),  .WRREG_W(WRREG_W),
    .REGNUM_X(REGNUM_X), .REGNUM_Y(REGNUM_Y),
    .REGNUM_Z(REGNUM_Z), .REGNUM_W(REGNUM_W),
    // input & outout
    .REG_X(REG_X), .REG_Y(REG_Y), .REG_0(REG_0), 
    .ZBUS(ZBUS), .WBUS(WBUS)
    ); 
 
//-------------
// ALU Function
//-------------
    always @(WRREG_W or REGNUM_W or WBUS or REG_0)
    begin
        if ((WRREG_W) & (REGNUM_W == 4'h0))
            R0 <= WBUS;
        else
            R0 <= REG_0;
    end
 
    always @(ALUFUNC or XBUS or YBUS or R0 or CONST or SFTOUT)
    begin
        case(ALUFUNC)
            `ALU_ADDXFC  : begin
                               ALUINX <= {XBUS[31:2], 2'b0};
                               ALUINY <= YBUS;
                           end
            `ALU_INCX    : begin
                               ALUINX <= XBUS;
                               ALUINY <= 32'h00000001;
                           end
            `ALU_DECX    : begin
                               ALUINX <= XBUS;
                               ALUINY <= 32'h00000001;
                           end
            `ALU_INCX2   : begin
                               ALUINX <= XBUS;
                               ALUINY <= 32'h00000002;
                           end
            `ALU_DECX2   : begin
                               ALUINX <= XBUS;
                               ALUINY <= 32'h00000002;
                           end
            `ALU_INCX4   : begin
                               ALUINX <= XBUS;
                               ALUINY <= 32'h00000004;
                           end
            `ALU_DECX4   : begin
                               ALUINX <= XBUS;
                               ALUINY <= 32'h00000004;
                           end
            `ALU_ADDR0   : begin
                               ALUINX <= XBUS;
                               ALUINY <= R0;
                           end
            `ALU_ADDCN   : begin
                               ALUINX <= XBUS;
                               ALUINY <= CONST;
                           end
            `ALU_TAS     : begin
                               ALUINX <= XBUS;
                               ALUINY <= 32'h00000080;
                           end
            `ALU_DIV     : begin
                               ALUINX <= SFTOUT;
                               ALUINY <= YBUS;
                           end
            default      : begin
                               ALUINX <= XBUS;
                               ALUINY <= YBUS;
                           end
        endcase
    end
 
    always @(ALUFUNC or SR)
    begin
        case (ALUFUNC)
            `ALU_ADDC : CRYI <= SR[`T];
            `ALU_SUBC : CRYI <= SR[`T];
            default   : CRYI <= 1'b0;
        endcase
    end
 
    // Overflow and Underflow
    // [Addition] ADDV             [Subtruction] SUBV
    // X[31] Y[31] Z[31] OVF       X[31] Y[31] Z[31] UDF
    // 0     0     0     0         0     0     0     0
    // 0     0     1     1 <--     0     0     1     0
    // 0     1     0     0         0     1     0     0
    // 0     1     1     0         0     1     1     1 <--
    // 1     0     0     0         1     0     0     1 <--
    // 1     0     1     0         1     0     1     0
    // 1     1     0     1 <--     1     1     0     0
    // 1     1     1     0         1     1     1     0
    always @(ALUFUNC or ADDSUBXY or ALUINX or ALUINY)
    begin
        case (ALUFUNC)
            `ALU_ADDC : CRYO <= ADDSUBXY[32];
            `ALU_SUBC : CRYO <= ADDSUBXY[32];
            `ALU_ADDV : CRYO <= (~ALUINX[31]&~ALUINY[31]& ADDSUBXY[31])
                               |( ALUINX[31]& ALUINY[31]&~ADDSUBXY[31]);
            `ALU_SUBV : CRYO <= (~ALUINX[31]& ALUINY[31]& ADDSUBXY[31])
                               |( ALUINX[31]&~ALUINY[31]&~ADDSUBXY[31]);
            // default   : CRYO <= 1'bx; // Thorn Aitch 2003/12/10
		  default   : CRYO <= 1'b0;    // Thorn Aitch 2003/12/10
        endcase
    end
 
    // Adder / Subtractor
    //     add : ADDSUBXY = ALUINX + ALUINY + CRYI
    //     sub : ADDSUBXY = ALUINX - ALUINY - CRYI  
    // (Note)
    // A[] - B[]     =    A[] + /B[] + 1
    // A[] - B[]     = /(/A[] +  B[])
    // A[] - B[] - C =    A[] + /B[] + /C
    always  @(ALUFUNC or SR)
    begin
        casex ({ALUFUNC, SR[`Q], SR[`M]})   // (ALUFUNC, old_Q, M)
	       7'b00???_?? : ADDSUB <= 1'b0; //ADD
	       7'b010??_?? : ADDSUB <= 1'b0; //ADD			
	       7'b0110?_?? : ADDSUB <= 1'b0; //ADD
	       7'b01110_?? : ADDSUB <= 1'b0; //ADD
	       7'b01111_00 : ADDSUB <= 1'b1; //SUB(DIV)
	       7'b01111_01 : ADDSUB <= 1'b0; //ADD(DIV)
	       7'b01111_10 : ADDSUB <= 1'b0; //ADD(DIV)
	       7'b01111_11 : ADDSUB <= 1'b1; //SUB(DIV)
		  7'b1????_?? : ADDSUB <= 1'b1; //SUB
            default : ADDSUB <= 1'bx;
	   endcase
    end
    always @(ADDSUB or ALUINY)
    begin
        for (i=0;i<=31;i=i+1) ALUINY_EOR[i] <= ADDSUB ^ ALUINY[i];
        ALUINY_EOR[32] <= ADDSUB;
    end
    always @(ALUINX or ALUINY_EOR or ADDSUB or CRYI)
    begin //33bit operation
        ADDSUBXY <= {1'b0,ALUINX} + ALUINY_EOR + (ADDSUB ^ CRYI);
    end
 
    //Make ALU Output
    always @(ALUFUNC or ALUINX or ALUINY or WBUS or ADDSUBXY)
    begin
        case(ALUFUNC)
            `ALU_THRUX    : ALUOUT <= ALUINX;
            `ALU_THRUY    : ALUOUT <= ALUINY;
            `ALU_THRUW    : ALUOUT <= WBUS; 
            `ALU_ADDXFC   : ALUOUT <= ADDSUBXY[31:0];
            `ALU_ADD      : ALUOUT <= ADDSUBXY[31:0];
            `ALU_ADDC     : ALUOUT <= ADDSUBXY[31:0];
            `ALU_ADDV     : ALUOUT <= ADDSUBXY[31:0];
            `ALU_INCX     : ALUOUT <= ADDSUBXY[31:0];
            `ALU_INCX2    : ALUOUT <= ADDSUBXY[31:0];
            `ALU_INCX4    : ALUOUT <= ADDSUBXY[31:0];
            `ALU_SUB      : ALUOUT <= ADDSUBXY[31:0];
            `ALU_SUBC     : ALUOUT <= ADDSUBXY[31:0];
            `ALU_SUBV     : ALUOUT <= ADDSUBXY[31:0];
            `ALU_DECX     : ALUOUT <= ADDSUBXY[31:0];
            `ALU_DECX2    : ALUOUT <= ADDSUBXY[31:0];
            `ALU_DECX4    : ALUOUT <= ADDSUBXY[31:0];
            `ALU_NOT      : ALUOUT <= ~ALUINY;
            `ALU_AND      : ALUOUT <= ALUINX & ALUINY;
            `ALU_OR       : ALUOUT <= ALUINX | ALUINY;
            `ALU_XOR      : ALUOUT <= ALUINX ^ ALUINY;
            `ALU_SWAPB    : ALUOUT <= {ALUINY[31:16], ALUINY[ 7: 0], ALUINY[15:8]};
            `ALU_SWAPW    : ALUOUT <= {ALUINY[15: 0], ALUINY[31:16]};
            `ALU_EXTUB    : ALUOUT <= {24'h000000, ALUINY[ 7:0]};
            `ALU_EXTUW    : ALUOUT <= {16'h0000,   ALUINY[15:0]};
            `ALU_EXTSB    : begin
                                for (i= 8;i<=31;i=i+1) ALUOUT[i] <= ALUINY[ 7];
                                ALUOUT[ 7:0] <= ALUINY[ 7:0];
                            end
            `ALU_EXTSW    : begin
                                for (i=16;i<=31;i=i+1) ALUOUT[i] <= ALUINY[15];
                                ALUOUT[15:0] <= ALUINY[15:0];
                            end
            `ALU_XTRCT    : ALUOUT <= {ALUINY[15:0], ALUINX[31:16]};
            `ALU_ADDR0    : ALUOUT <= ADDSUBXY[31:0];                  
            `ALU_ADDCN    : ALUOUT <= ADDSUBXY[31:0];
            `ALU_TAS      : ALUOUT <= ALUINX | ALUINY;
            `ALU_DIV      : ALUOUT <= ADDSUBXY[31:0];
            default       : ALUOUT <= 32'h00000000; // ALU_NOP
        endcase
    end
 
    always @(ALUFUNC or ALUOUT or XBUS) 
    begin
        if (ALUFUNC == `ALU_TAS)
            TSTO <= (XBUS == 32'h00000000);
        else
            TSTO <= (ALUOUT == 32'h00000000);
    end
 
//-----------------
// Divider Function
//-----------------
    // old_Q : SR[`Q]
    // Q     : MSB of Rn (XBUS[31])
    // Rn = (Q <--[   Rn   ]<--T) (SFTOUT by ROTCL)
    // tmp0 = Rn (SFTOUT)
    // In ALU....
    // SR[`Q] SR[`M] ADDSUBXY(ALUOUT)
    // 0      0      SFTOUT - YBUS by ALU_DIV : Rn-=Rm
    // 0      1      SFTOUT + YBUS by ALU_DIV : Rn+=Rm
    // 1      0      SFTOUT + YBUS by ALU_DIV : Rn+=Rm
    // 1      1      SFTOUT - YBUS by ALU_DIV : Rn-=Rm
    always @(ADDSUBXY or SFTOUT)
    begin
        SUBGT <= (ADDSUBXY[31:0] > SFTOUT); // make SUBGT = (ADDSUBXY>tmp0)
        ADDLT <= (ADDSUBXY[31:0] < SFTOUT); // make ADDLT = (ADDSUBXY<tmp0)
    end
    always @(SR[`Q] or SR[`M] or XBUS or SUBGT or ADDLT)
    begin
        case ({SR[`Q], SR[`M], XBUS[31]}) // case (old_Q, M, Q)
            3'b000  : Q_DIV1 <=  SUBGT;
            3'b001  : Q_DIV1 <= ~SUBGT;
            3'b010  : Q_DIV1 <= ~ADDLT;
            3'b011  : Q_DIV1 <=  ADDLT;
            3'b100  : Q_DIV1 <=  ADDLT;
            3'b101  : Q_DIV1 <= ~ADDLT;
            3'b110  : Q_DIV1 <= ~SUBGT;
            3'b111  : Q_DIV1 <=  SUBGT;
            default : Q_DIV1 <=  1'bx;
        endcase
    end
    always @(Q_DIV1 or SR[`M]) T_DIV1  <= ~(Q_DIV1 ^ SR[`M]);
    always @(XBUS or YBUS)     T_DIV0S <=  (XBUS[31] ^ YBUS[31]);
 
//-----------
// Comparator
//-----------
//  CMPSIGN XBUS[31] YBUS[31] XBUS[30:0]-YBUS[30:0] : X=Y X>Y X<Y
//  0       0        0        ==                    :  1   0   0
//  0       0        0        >                     :  0   1   0
//  0       0        0        <                     :  0   0   1
//  0       0        1        don't care            :  0   0   1
//  0       1        0        don't care            :  0   1   0
//  0       1        1        ==                    :  1   0   0
//  0       1        1        >                     :  0   1   0
//  0       1        1        <                     :  0   0   1
//  1       0        0        ==                    :  1   0   0
//  1       0        0        >                     :  0   1   0
//  1       0        0        <                     :  0   0   1
//  1       0        1        don't care            :  0   1   0
//  1       1        0        don't care            :  0   0   1
//  1       1        1        ==                    :  1   0   0
//  1       1        1        >                     :  0   1   0
//  1       1        1        <                     :  0   0   1
//----------------------
// Comparator Commands
//     CMPEQ  : 000 equal
//     CMPHS  : 010 higher or same (unsigned)
//     CMPGE  : 011 grater or equal(signed)
//     CMPHI  : 110 higher than    (unsigned)
//     CMPGT  : 111 grater than    (signed)
//     CMPPL  : 101 plus (not 0)   (signed)
//     CMPPZ  : 001 plus or zero   (signed)
//     CMPSTR : 100 equal at least 1 byte
 
    always @(XBUS[31] or YBUS[31])
    begin
        EQMSB <= (XBUS[31] == YBUS[31]);
    end
 
    always @(XBUS[30:0] or YBUS[30:0])
    begin
        EQHH <= (XBUS[30:24] == YBUS[30:24]);
        EQHL <= (XBUS[23:16] == YBUS[23:16]);
        EQLH <= (XBUS[15: 8] == YBUS[15: 8]);
        EQLL <= (XBUS[ 7: 0] == YBUS[ 7: 0]);
    end
 
    always @(EQHH or EQHL or EQLH or EQLL)
    begin
        EQ <= EQHH & EQHL & EQLH & EQLL;
    end
 
    always @(XBUS or YBUS)
    begin
        if (XBUS[30:0] > YBUS[30:0])
            HI <= 1'b1;
        else
            HI <= 1'b0;
    end
 
    always @(CMPCOM or EQ or HI or XBUS or YBUS or EQMSB or EQHH or EQHL or EQLH or EQLL)
    begin
        case (CMPCOM)
            `CMPEQ : //000 equal
                     if (EQMSB & EQ)
                         CMPRESULT <= 1'b1;
                     else 
                         CMPRESULT <= 1'b0;
            `CMPHS : //010 higher or same (unsigned)
                     if ( (EQMSB & (HI | EQ))
                        | ((XBUS[31] == 1'b1) & (YBUS[31] == 1'b0)) )
                         CMPRESULT <= 1'b1;
                     else
                         CMPRESULT <= 1'b0;         
            `CMPGE : //011 grater or equal(signed)
                     if ( (EQMSB & (HI | EQ))
                        | ((XBUS[31] == 1'b0) & (YBUS[31] == 1'b1)) )
                         CMPRESULT <= 1'b1;
                     else
                         CMPRESULT <= 1'b0;
            `CMPHI : //110 higher than    (unsigned)
                     if ( (EQMSB & HI)
                        | ((XBUS[31] == 1'b1) & (YBUS[31] == 1'b0)) )
                         CMPRESULT <= 1'b1;
                     else
                         CMPRESULT <= 1'b0;  
            `CMPGT : //111 grater than    (signed) 
                     if ( (EQMSB & HI)
                        | ((XBUS[31] == 1'b0) & (YBUS[31] == 1'b1)) )
                         CMPRESULT <= 1'b1;
                     else
                         CMPRESULT <= 1'b0;
            `CMPPL : //101 plus (not 0)   (signed)
                     CMPRESULT <= ~XBUS[31] & ~(EQMSB & EQ);
            `CMPPZ : //001 plus or zero   (signed)
                     CMPRESULT <= ~XBUS[31] | (EQMSB & EQ);
            `CMPSTR: //100 equal at least 1 byte
                         CMPRESULT <= (EQMSB & EQHH) | EQHL | EQLH | EQLL;
            default : CMPRESULT <= 1'b0;
        endcase
    end
 
//-----------------
// Shifter Function
//-----------------
    always @(SFTFUNC or XBUS or SR)
    begin
        case (SFTFUNC)
            `SHLL   : SFTOUT <= {XBUS[30:0], 1'b0};
            `SHAL   : SFTOUT <= {XBUS[30:0], 1'b0};
            `SHLR   : SFTOUT <= {1'b0, XBUS[31:1]};
            `SHAR   : SFTOUT <= {XBUS[31], XBUS[31:1]};
            `ROTL   : SFTOUT <= {XBUS[30:0], XBUS[31]};
            `ROTCL  : SFTOUT <= {XBUS[30:0], SR[`T]};
            `ROTR   : SFTOUT <= {XBUS[0], XBUS[31:1]};
            `ROTCR  : SFTOUT <= {SR[`T], XBUS[31:1]};
            `SHLL2  : SFTOUT <= {XBUS[29:0], 2'b00};
            `SHLL8  : SFTOUT <= {XBUS[23:0], 8'h00};
            `SHLL16 : SFTOUT <= {XBUS[15:0], 16'h0000};
            `SHLR2  : SFTOUT <= {2'b00, XBUS[31:2]};
            `SHLR8  : SFTOUT <= {8'h00, XBUS[31:8]};
            `SHLR16 : SFTOUT <= {16'h0000, XBUS[31:16]};
            default: SFTOUT <= 32'hxxxxxxxx;
        endcase
        case (SFTFUNC)
            `SHLL   : SFTO <= XBUS[31];
            `SHAL   : SFTO <= XBUS[31];
            `SHLR   : SFTO <= XBUS[0];
            `SHAR   : SFTO <= XBUS[0];
            `ROTL   : SFTO <= XBUS[31];
            `ROTCL  : SFTO <= XBUS[31];
            `ROTR   : SFTO <= XBUS[0];
            `ROTCR  : SFTO <= XBUS[0];
            default: SFTO <= 1'bx;
        endcase
    end
 
//---------------
// Output to Mult
//---------------
    always @(MACSEL1 or XBUS or ZBUS or WBUS)
    begin
        casex (MACSEL1)
            2'b00   : MACIN1 <= XBUS;
            2'b01   : MACIN1 <= ZBUS;
            2'b1?   : MACIN1 <= WBUS;
            default : MACIN1 <= WBUS;
        endcase
    end
 
    always @(MACSEL2 or YBUS or ZBUS or WBUS)
    begin
        casex (MACSEL2)
            2'b00   : MACIN2 <= YBUS;
            2'b01   : MACIN2 <= ZBUS;
            2'b1?   : MACIN2 <= WBUS;
            default : MACIN2 <= WBUS;
        endcase
    end
 
//------------------------
// Memory Access Interface
//------------------------
    always @(WRMAAD_Z or ZBUS or WRMAAD_TEMP or TEMP or XBUS)
    begin
        if (WRMAAD_Z)
            MA_AD <= ZBUS;
        else if (WRMAAD_TEMP)
            MA_AD <= TEMP;
        else
            MA_AD <= XBUS; // default MA_AD is XBUS
    end
 
    always @(WRMADW_X or WRMADW_Y or XBUS or YBUS or ZBUS)
    begin
        if (WRMADW_X)
            MA_DW <= XBUS;
        else if (WRMADW_Y)
            MA_DW <= YBUS;
        else
            MA_DW <= ZBUS;
    end
 
//---------------------
// Program Counter : PC
//---------------------
    always @(posedge CLK)
    begin
        if (SLOT)
        begin
            if (WRPC_Z)
                PC <= ZBUS;
            else if (INCPC)
                PC <= PCADD2;
        end
    end
 
    always @(PC)
    begin
        PCADD2 <= PC + 2;
    end
 
    always @(IFADSEL or PCADD2 or ZBUS)
    begin
        if (IFADSEL == 1'b0)
            IF_AD <= PCADD2;
        else
            IF_AD <= ZBUS;
    end
 
//---------
// Constant
//---------
    always @(CONST_IFDR
          or CONST_ZERO4 or CONST_ZERO42 or CONST_ZERO44
          or CONST_ZERO8 or CONST_ZERO82 or CONST_ZERO84
          or CONST_SIGN8 or CONST_SIGN82
          or CONST_SIGN122)
    begin
        if (CONST_ZERO4)
            begin
                CONST[31:4] <= 28'h0000000;
                CONST[ 3:0] <= CONST_IFDR[3:0];
            end                          
        else if (CONST_ZERO42)
            begin
                CONST[31:5] <= 27'h0000000;
                CONST[ 4:1] <= CONST_IFDR[3:0];
                CONST[   0] <= 1'b0;    
            end                          
        else if (CONST_ZERO44)
            begin
                CONST[31:6] <= 26'h0000000;
                CONST[ 5:2] <= CONST_IFDR[3:0];
                CONST[ 1:0] <= 2'b00;    
            end
        else if (CONST_ZERO8)
            begin
                CONST[31:8] <= 24'h000000;
                CONST[ 7:0] <= CONST_IFDR[7:0];
            end                          
        else if (CONST_ZERO82)
            begin
                CONST[31:9] <= 23'h000000;
                CONST[ 8:1] <= CONST_IFDR[7:0];
                CONST[   0] <= 1'b0;    
            end                          
        else if (CONST_ZERO84)
            begin
                CONST[31:10] <= 22'h000000;
                CONST[ 9: 2] <= CONST_IFDR[7:0];
                CONST[ 1: 0] <= 2'b00;    
            end
        else if (CONST_SIGN8)
            begin
                for (i = 8 ; i <= 31 ; i = i + 1) CONST[i] <= CONST_IFDR[7];
                CONST[ 7:0] <= CONST_IFDR[7:0];
            end
        else if (CONST_SIGN82)
            begin
                for (i = 9 ; i <= 31 ; i = i + 1) CONST[i] <= CONST_IFDR[7];
                CONST[ 8:1] <= CONST_IFDR[7:0];
                CONST[   0] <= 1'b0;
            end
        else if (CONST_SIGN122)
            begin
                for (i = 13 ; i <= 31 ; i = i + 1) CONST[i] <= CONST_IFDR[11];
                CONST[12:1] <= CONST_IFDR[11:0];
                CONST[   0] <= 1'b0;
            end
        else
            CONST[31:0] <= 32'hxxxxxxxx;
    end
 
//--------------------------
// T value for Bcc judgement
//--------------------------
    always @(T_CMPSET   or CMPRESULT
          or T_CRYSET   or CRYO
          or T_TSTSET   or TSTO
          or T_SFTSET   or SFTO
          or QT_DV1SET  or T_DIV1
          or MQT_DV0SET or T_DIV0S
          or T_CLR
          or T_SET
          or WRSR_Z     or ZBUS
          or WRSR_W     or WBUS
          or SR[`T])
    begin
             if (T_CMPSET)   T_BCC <= CMPRESULT;
        else if (T_CRYSET)   T_BCC <= CRYO;
        else if (T_TSTSET)   T_BCC <= TSTO;
        else if (T_SFTSET)   T_BCC <= SFTO;
        else if (QT_DV1SET)  T_BCC <= T_DIV1;
        else if (MQT_DV0SET) T_BCC <= T_DIV0S;
        else if (T_CLR)      T_BCC <= 1'b0;
        else if (T_SET)      T_BCC <= 1'b1;
        else if (WRSR_W)     T_BCC <= WBUS[0];
        else if (WRSR_Z)     T_BCC <= ZBUS[0];
        else                 T_BCC <= SR[`T];
    end
 
//----------------
// Status Register
//----------------
    assign IBIT = SR[`I3:`I0];
 
    always @(posedge CLK)
    begin
        if (RST_SR)
            begin
              //SR[31:16] <= 16'h0000;
              //SR[15:10] <= 6'b000000;
                SR[`I3:`I0] <= 4'b1111;
                SR[3:2] <= 2'b00;
            end
        else if (SLOT)
        begin
            //---------------
            // T bit (bit 0)
            //---------------
            SR[`T] <= T_BCC;
            //--------------
            // Q bit (bit 8)
            //--------------
                 if (QT_DV1SET)  SR[`Q] <= Q_DIV1;
            else if (MQT_DV0SET) SR[`Q] <= XBUS[31];
            else if (MQ_CLR)     SR[`Q] <= 1'b0;
            else if (WRSR_W)     SR[`Q] <= WBUS[8];
            else if (WRSR_Z)     SR[`Q] <= ZBUS[8];
            //--------------
            // M bit (bit 9)
            //--------------
                 if (MQT_DV0SET) SR[`M] <= YBUS[31];
            else if (MQ_CLR)     SR[`M] <= 1'b0;
            else if (WRSR_W)     SR[`M] <= WBUS[9];
            else if (WRSR_Z)     SR[`M] <= ZBUS[9];
            //------
            // I bit
            //------
            if (WR_IBIT)
                SR[`I3:`I0] <= ILEVEL;    
            else if (WRSR_Z)     //ZBUS has the higher priority than WBUS.
                begin
                    SR[`I3:`I0] <= ZBUS[7:4];
                end
            else if (WRSR_W)
                begin
                    SR[`I3:`I0] <= WBUS[7:4];
                end
            //------
            // S bit
            //------
            if (WRSR_Z)     //ZBUS has the higher priority than WBUS.
                begin
                    SR[`S] <= ZBUS[1];
                end
            else if (WRSR_W)
                begin
                    SR[`S] <= WBUS[1];
                end
        end
    end
 
    always @(posedge CLK)
    begin
        if (MAC_S_LATCH)
            MAC_S <= SR[`S]; 
    end
 
//---------------------
// Global Base Register
//---------------------
    always @(posedge CLK)
    begin
        if (SLOT)
        begin
            if (WRGBR_Z)     //ZBUS has the higher priority than WBUS.
                GBR <= ZBUS;
            else if (WRGBR_W)
                GBR <= WBUS;
        end
    end
 
//---------------------
// Vector Base Register
//---------------------
    always @(posedge CLK)
    begin
        if (SLOT)
        begin
            if (WRVBR_Z)     //ZBUS has the higher priority than WBUS.
                VBR <= ZBUS;
            else if (WRVBR_W)
                VBR <= WBUS;
        end
    end
 
//-------------------
// Procedure Register
//-------------------
    always @(posedge CLK)
    begin
        if (SLOT)
        begin
            if (WRPR_PC)
                PR <= PC;
            else if (WRPR_Z)     //ZBUS has the higher priority than WBUS.
                PR <= ZBUS;
            else if (WRPR_W)
                PR <= WBUS;
        end
    end
 
//-------------------
// Temporary Register
//-------------------
    always @(posedge CLK)
    begin
        if (SLOT)
        begin
            if (WRTEMP_Z)
                TEMP <= ZBUS;
        end
    end
 
//======================================================
  endmodule
//======================================================

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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