📄 datapath.v
字号:
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 + -