⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 datapath.v

📁 日立SH-2 CPU核的VERLOG源码
💻 V
📖 第 1 页 / 共 3 页
字号:
        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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -