// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// This file is part of the M32632 project
|
// This file is part of the M32632 project
|
// http://opencores.org/project,m32632
|
// http://opencores.org/project,m32632
|
//
|
//
|
// Filename: DP_FPU.v
|
// Filename: DP_FPU.v
|
// Version: 1.0
|
// Version: 2.0
|
// Date: 30 May 2015
|
// History: 1.0 first release of 30 Mai 2015
|
|
// Date: 14 August 2016
|
//
|
//
|
// Copyright (C) 2015 Udo Moeller
|
// Copyright (C) 2016 Udo Moeller
|
//
|
//
|
// This source file may be used and distributed without
|
// This source file may be used and distributed without
|
// restriction provided that this copyright statement is not
|
// restriction provided that this copyright statement is not
|
// removed from the file and that any derivative work contains
|
// removed from the file and that any derivative work contains
|
// the original copyright notice and the associated disclaimer.
|
// the original copyright notice and the associated disclaimer.
|
//
|
//
|
// This source file is free software; you can redistribute it
|
// This source file is free software; you can redistribute it
|
// and/or modify it under the terms of the GNU Lesser General
|
// and/or modify it under the terms of the GNU Lesser General
|
// Public License as published by the Free Software Foundation;
|
// Public License as published by the Free Software Foundation;
|
// either version 2.1 of the License, or (at your option) any
|
// either version 2.1 of the License, or (at your option) any
|
// later version.
|
// later version.
|
//
|
//
|
// This source is distributed in the hope that it will be
|
// This source is distributed in the hope that it will be
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
// useful, but WITHOUT ANY WARRANTY; without even the implied
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
// PURPOSE. See the GNU Lesser General Public License for more
|
// PURPOSE. See the GNU Lesser General Public License for more
|
// details.
|
// details.
|
//
|
//
|
// You should have received a copy of the GNU Lesser General
|
// You should have received a copy of the GNU Lesser General
|
// Public License along with this source; if not, download it
|
// Public License along with this source; if not, download it
|
// from http://www.opencores.org/lgpl.shtml
|
// from http://www.opencores.org/lgpl.shtml
|
//
|
//
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// Modules contained in this file:
|
// Modules contained in this file:
|
// 1. PREPDATA Prepare data for the big multiplier
|
// 1. PREPDATA Prepare data for the big multiplier
|
// 2. BCDADDER 4 bit BCD adder
|
// 2. BCDADDER 4 bit BCD adder
|
// 3. DFPU_BCD Binary coded decimal (BCD) adder and subtractor
|
// 3. DFPU_BCD Binary coded decimal (BCD) adder and subtractor
|
// 4. DFPU_ADDSUB Double precision floating point adder and subtractor
|
// 4. DFPU_ADDSUB Double precision floating point adder and subtractor
|
// 5. DFPU_MISC Double precision floating point miscellaneous operations
|
// 5. DFPU_MISC Double precision floating point miscellaneous operations
|
// 6. DFPU_MUL Double precision floating point multiplier
|
// 6. DFPU_MUL Double precision floating point multiplier
|
// 7. DIVI_PREP Prepare data for the divider
|
// 7. SCANDIG Scan digit for leading one
|
// 8. DFPU_DIV The divider for all divide opcodes : double, single and integer
|
// 8. DIVI_PREP Prepare data for the divider
|
// 9. DP_LOGIK Control logic and result path for different functions
|
// 9. DFPU_DIV The divider for all divide opcodes : double, single and integer
|
// 10. DP_FPU Top level of long operations datapath
|
// 10. DP_LOGIK Control logic and result path for different functions
|
|
// 11. DP_FPU Top level of long operations datapath
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 1. PREPDATA Prepare data for the big multiplier
|
// 1. PREPDATA Prepare data for the big multiplier
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module PREPDATA ( START, MEI, DFLOAT, BWD, SRC1, SRC2,
|
module PREPDATA ( START, MEI, DFLOAT, BWD, SRC1, SRC2,
|
MSD_1, MSD_2, LSD_1, LSD_2, LOAD_MSD, LOAD_LSD1, LOAD_LSD2 );
|
MSD_1, MSD_2, LSD_1, LSD_2, LOAD_MSD, LOAD_LSD1, LOAD_LSD2 );
|
|
|
input [1:0] START;
|
input [1:0] START;
|
input MEI,DFLOAT;
|
input MEI,DFLOAT;
|
input [1:0] BWD;
|
input [1:0] BWD;
|
input [31:0] SRC1,SRC2;
|
input [31:0] SRC1,SRC2;
|
|
|
output [52:32] MSD_1,MSD_2;
|
output [52:32] MSD_1,MSD_2;
|
output [31:0] LSD_1,LSD_2;
|
output [31:0] LSD_1,LSD_2;
|
output LOAD_MSD,LOAD_LSD1,LOAD_LSD2;
|
output LOAD_MSD,LOAD_LSD1,LOAD_LSD2;
|
|
|
reg [31:0] LSD_1,LSD_2;
|
reg [31:0] LSD_1,LSD_2;
|
|
|
assign MSD_1 = MEI ? 21'h0 : {1'b1,SRC1[19:0]};
|
assign MSD_1 = MEI ? 21'h0 : {1'b1,SRC1[19:0]};
|
assign MSD_2 = MEI ? 21'h0 : {1'b1,SRC2[19:0]};
|
assign MSD_2 = MEI ? 21'h0 : {1'b1,SRC2[19:0]};
|
|
|
always @(MEI or BWD or SRC1)
|
always @(MEI or BWD or SRC1)
|
casex ({MEI,BWD})
|
casex ({MEI,BWD})
|
3'b100 : LSD_1 = {24'h000000,SRC1[7:0]};
|
3'b100 : LSD_1 = {24'h000000,SRC1[7:0]};
|
3'b101 : LSD_1 = {16'h0000,SRC1[15:0]};
|
3'b101 : LSD_1 = {16'h0000,SRC1[15:0]};
|
default : LSD_1 = SRC1;
|
default : LSD_1 = SRC1;
|
endcase
|
endcase
|
|
|
always @(MEI or BWD or SRC2)
|
always @(MEI or BWD or SRC2)
|
casex ({MEI,BWD})
|
casex ({MEI,BWD})
|
3'b100 : LSD_2 = {24'h000000,SRC2[7:0]};
|
3'b100 : LSD_2 = {24'h000000,SRC2[7:0]};
|
3'b101 : LSD_2 = {16'h0000,SRC2[15:0]};
|
3'b101 : LSD_2 = {16'h0000,SRC2[15:0]};
|
default : LSD_2 = SRC2;
|
default : LSD_2 = SRC2;
|
endcase
|
endcase
|
|
|
assign LOAD_MSD = (START[0] & MEI) | (START[0] & DFLOAT); // 1. step data load at DFLOAT
|
assign LOAD_MSD = (START[0] & MEI) | (START[0] & DFLOAT); // 1. step data load at DFLOAT
|
assign LOAD_LSD1 = (START[0] & MEI) | (START[1] & DFLOAT); // 2. step execute at DFLOAT
|
assign LOAD_LSD1 = (START[0] & MEI) | (START[1] & DFLOAT); // 2. step execute at DFLOAT
|
assign LOAD_LSD2 = (START[1] & MEI) | (START[1] & DFLOAT); // 2. step execute at DFLOAT
|
assign LOAD_LSD2 = (START[1] & MEI) | (START[1] & DFLOAT); // 2. step execute at DFLOAT
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 2. BCDADDER 4 bit BCD adder
|
// 2. BCDADDER 4 bit BCD adder
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module BCDADDER ( A_IN, B_IN, CY_IN, SUBP, OUT, CY_OUT );
|
module BCDADDER ( A_IN, B_IN, CY_IN, SUBP, OUT, CY_OUT );
|
|
|
input [3:0] A_IN,B_IN;
|
input [3:0] A_IN,B_IN;
|
input CY_IN;
|
input CY_IN;
|
input SUBP;
|
input SUBP;
|
|
|
output [3:0] OUT;
|
output [3:0] OUT;
|
output CY_OUT;
|
output CY_OUT;
|
|
|
|
reg [4:0] data;
|
wire [4:0] result;
|
wire [4:0] result;
|
wire over;
|
wire over;
|
|
|
assign result = SUBP ? ({1'b0,A_IN} - {1'b0,B_IN} - {4'b0,CY_IN})
|
always @(B_IN)
|
: ({1'b0,A_IN} + {1'b0,B_IN} + {4'b0,CY_IN});
|
case (B_IN)
|
|
4'h0 : data = 5'h00;
|
|
4'h1 : data = 5'h1F;
|
|
4'h2 : data = 5'h1E;
|
|
4'h3 : data = 5'h1D;
|
|
4'h4 : data = 5'h1C;
|
|
4'h5 : data = 5'h1B;
|
|
4'h6 : data = 5'h1A;
|
|
4'h7 : data = 5'h19;
|
|
4'h8 : data = 5'h18;
|
|
4'h9 : data = 5'h17;
|
|
default : data = 5'hxx;
|
|
endcase
|
|
|
|
assign result = {1'b0,A_IN} + (SUBP ? data : {1'b0,B_IN}) + {{4{SUBP & CY_IN}},CY_IN};
|
|
|
assign over = result[4] | (result[3] & (result[2] | result[1]));
|
assign over = result[4] | (result[3] & (result[2] | result[1]));
|
|
|
// if result<0 : -6 if result>9 : -10
|
// if result<0 : -6 if result>9 : -10
|
assign OUT = result[3:0] - (SUBP ? {1'b0,result[4],result[4],1'b0} : {over,1'b0,over,1'b0});
|
assign OUT = result[3:0] - (SUBP ? {1'b0,result[4],result[4],1'b0} : {over,1'b0,over,1'b0});
|
|
|
assign CY_OUT = SUBP ? result[4] : over;
|
assign CY_OUT = SUBP ? result[4] : over;
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 3. DFPU_BCD Binary coded decimal (BCD) adder and subtractor
|
// 3. DFPU_BCD Binary coded decimal (BCD) adder and subtractor
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DFPU_BCD ( BCLK, BRESET, START, DO_BCD, BWD, SRC1, SRC2, CY_IN, SUBP, BCD_Q, CY_OUT, BCD_DONE );
|
module DFPU_BCD ( BCLK, BRESET, START, DO_BCD, BWD, SRC1, SRC2, CY_IN, SUBP, BCD_Q, CY_OUT, BCD_DONE );
|
|
|
// Byte : 3 cycles in shortest case REG-REG, Word : 4 cycles and Double : 6 cycles
|
// Byte : 3 cycles in shortest case REG-REG, Word : 4 cycles and Double : 6 cycles
|
input BCLK;
|
input BCLK;
|
input BRESET;
|
input BRESET;
|
input START; // START[1]
|
input START; // START[1]
|
input DO_BCD; // BCD Opcode is valid
|
input DO_BCD; // BCD Opcode is valid
|
input [1:0] BWD;
|
input [1:0] BWD;
|
input [31:0] SRC1,SRC2; // Source , Destination, data is stable during operation
|
input [31:0] SRC1,SRC2; // Source , Destination, data is stable during operation
|
input CY_IN; // comes from PSR
|
input CY_IN; // comes from PSR
|
input SUBP; // SUBP = 1 : SUBP , 0 : ADDP
|
input SUBP; // SUBP = 1 : SUBP , 0 : ADDP
|
|
|
output reg [31:0] BCD_Q;
|
output reg [31:0] BCD_Q;
|
output reg CY_OUT; // went to PSR if DONE is valid
|
output reg CY_OUT; // went to PSR if DONE is valid
|
output BCD_DONE;
|
output BCD_DONE;
|
|
|
reg run_bcd;
|
reg run_bcd;
|
reg [1:0] byte_cou;
|
reg [1:0] byte_cou;
|
reg [15:0] datain;
|
reg [15:0] datain;
|
|
|
wire [7:0] result;
|
wire [7:0] result;
|
wire carry,carry_lsd,carry_msd;
|
wire carry,carry_lsd,carry_msd;
|
|
|
// START : _/---\________________
|
// START : _/---\________________
|
// byte_cou : xxxxxx 0 x 1 x 2 x 3 x
|
// byte_cou : xxxxxx 0 x 1 x 2 x 3 x
|
// BCD_DONE : _____/---\____________ if BWD = Byte
|
// BCD_DONE : _____/---\____________ if BWD = Byte
|
|
|
always @(posedge BCLK or negedge BRESET)
|
always @(posedge BCLK or negedge BRESET)
|
if (!BRESET) run_bcd <= 1'b0;
|
if (!BRESET) run_bcd <= 1'b0;
|
else
|
else
|
run_bcd <= (START & DO_BCD) | (run_bcd & (BWD != byte_cou));
|
run_bcd <= (START & DO_BCD & (BWD != 2'd0)) | (run_bcd & (BWD != byte_cou));
|
|
|
always @(posedge BCLK) byte_cou <= START ? 2'd0 : byte_cou + {1'b0,run_bcd};
|
always @(posedge BCLK) byte_cou <= START ? 2'd1 : byte_cou + {1'b0,run_bcd};
|
|
|
always @(*)
|
always @(*)
|
casex ({START,byte_cou})
|
casex ({START,byte_cou})
|
3'b1_xx : datain = {SRC1[7:0], SRC2[7:0]};
|
3'b1_xx : datain = {SRC1[7:0], SRC2[7:0]};
|
3'b0_00 : datain = {SRC1[15:8], SRC2[15:8]};
|
3'b0_0x : datain = {SRC1[15:8], SRC2[15:8]};
|
3'b0_01 : datain = {SRC1[23:16],SRC2[23:16]};
|
3'b0_10 : datain = {SRC1[23:16],SRC2[23:16]};
|
3'b0_1x : datain = {SRC1[31:24],SRC2[31:24]};
|
3'b0_11 : datain = {SRC1[31:24],SRC2[31:24]};
|
endcase
|
endcase
|
|
|
assign carry = START ? CY_IN : CY_OUT;
|
assign carry = START ? CY_IN : CY_OUT;
|
|
|
BCDADDER lsd_inst ( .A_IN(datain[3:0]), .B_IN(datain[11:8]), .CY_IN(carry), .SUBP(SUBP),
|
BCDADDER lsd_inst ( .A_IN(datain[3:0]), .B_IN(datain[11:8]), .CY_IN(carry), .SUBP(SUBP),
|
.OUT(result[3:0]), .CY_OUT(carry_lsd) );
|
.OUT(result[3:0]), .CY_OUT(carry_lsd) );
|
|
|
BCDADDER msd_inst ( .A_IN(datain[7:4]), .B_IN(datain[15:12]), .CY_IN(carry_lsd), .SUBP(SUBP),
|
BCDADDER msd_inst ( .A_IN(datain[7:4]), .B_IN(datain[15:12]), .CY_IN(carry_lsd), .SUBP(SUBP),
|
.OUT(result[7:4]), .CY_OUT(carry_msd) );
|
.OUT(result[7:4]), .CY_OUT(carry_msd) );
|
|
|
always @(posedge BCLK) CY_OUT <= carry_msd;
|
always @(posedge BCLK) CY_OUT <= carry_msd;
|
|
|
always @(posedge BCLK) if (START) BCD_Q[7:0] <= result;
|
always @(posedge BCLK) if (START) BCD_Q[7:0] <= result;
|
always @(posedge BCLK) if (byte_cou == 2'd0) BCD_Q[15:8] <= result;
|
always @(posedge BCLK) if (~byte_cou[1]) BCD_Q[15:8] <= result;
|
always @(posedge BCLK) if (byte_cou == 2'd1) BCD_Q[23:16] <= result;
|
always @(posedge BCLK) if (byte_cou == 2'd2) BCD_Q[23:16] <= result;
|
always @(posedge BCLK) if (byte_cou[1]) BCD_Q[31:24] <= result;
|
always @(posedge BCLK) if (byte_cou == 2'd3) BCD_Q[31:24] <= result;
|
|
|
assign BCD_DONE = run_bcd & (BWD == byte_cou);
|
assign BCD_DONE = (START & DO_BCD & (BWD == 2'd0)) | (run_bcd & (BWD == byte_cou));
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 4. DFPU_ADDSUB Double precision floating point adder and subtractor
|
// 4. DFPU_ADDSUB Double precision floating point adder and subtractor
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DFPU_ADDSUB ( BCLK, START, SRC1, SRC2, MAN1, MAN2, SRCFLAGS, BWD, SELECT, OUT, IOUT, CMPRES );
|
module DFPU_ADDSUB ( BCLK, START, SRC1, SRC2, MAN1, MAN2, SRCFLAGS, BWD, SELECT, OUT, IOUT, CMPRES );
|
|
|
input BCLK;
|
input BCLK;
|
input [1:0] START;
|
input [1:0] START;
|
input [31:0] SRC1,SRC2; // The input data
|
input [31:0] SRC1,SRC2; // The input data
|
input [20:0] MAN1,MAN2;
|
input [20:0] MAN1,MAN2;
|
input [5:0] SRCFLAGS; // NAN, ZERO and SIGN of operands
|
input [5:0] SRCFLAGS; // NAN, ZERO and SIGN of operands
|
input [1:0] BWD; // size of integer
|
input [1:0] BWD; // size of integer
|
input [3:0] SELECT; // upper 2 bits : R.T.F. code
|
input [3:0] SELECT; // upper 2 bits : R.T.F. code
|
|
|
output [69:0] OUT;
|
output [69:0] OUT;
|
output [31:0] IOUT; // result of ROUNDLi/TRUNCLi/FLOORLi = R.T.F.
|
output [31:0] IOUT; // result of ROUNDLi/TRUNCLi/FLOORLi = R.T.F.
|
output [1:0] CMPRES;
|
output [1:0] CMPRES;
|
|
|
reg [69:0] outreg;
|
reg [69:0] outreg;
|
reg [31:0] IOUT;
|
reg [31:0] IOUT;
|
|
|
// MOViL : 2 cycles
|
// MOViL : 2 cycles
|
// ROUNDLi : 3 cycles (+TRUNC & FLOOR)
|
// ROUNDLi : 3 cycles (+TRUNC & FLOOR)
|
// ADD/SUB : 4 cycles
|
// ADD/SUB : 4 cycles
|
// CMP : 2 cycles
|
// CMP : 2 cycles
|
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
// MOViL : 1. Pipeline stage : needs 3 cycles
|
// MOViL : 1. Pipeline stage : needs 3 cycles
|
|
|
reg [31:8] movdat;
|
reg [31:0] movdat;
|
reg [31:0] movif;
|
reg [31:0] movif;
|
reg sign_movif;
|
reg sign_movif;
|
|
|
always @(BWD or SRC1)
|
always @(BWD or SRC1)
|
casex({BWD,SRC1[15],SRC1[7]})
|
casex(BWD)
|
4'b00x0 : movdat = 24'h0000_00; // Byte
|
2'b00 : movdat = {{24{SRC1[7]}}, SRC1[7:0]}; // Byte
|
4'b00x1 : movdat = 24'hFFFF_FF;
|
2'b01 : movdat = {{16{SRC1[15]}},SRC1[15:0]}; // Word
|
4'b010x : movdat = {16'h0000,SRC1[15:8]}; // Word
|
default : movdat = SRC1[31:0]; // Double
|
4'b011x : movdat = {16'hFFFF,SRC1[15:8]};
|
|
default : movdat = SRC1[31:8]; // Double
|
|
endcase
|
endcase
|
|
|
// This pipeline stage for better timing
|
// This pipeline stage for better timing
|
always @(posedge BCLK) movif <= movdat[31] ? (32'h0 - {movdat,SRC1[7:0]}) : {movdat,SRC1[7:0]}; // -2^31 is kept !
|
always @(posedge BCLK) movif <= ({32{movdat[31]}} ^ movdat) + {31'h0,movdat[31]}; // -2^31 is kept !
|
|
|
always @(posedge BCLK) sign_movif <= movdat[31];
|
always @(posedge BCLK) sign_movif <= movdat[31];
|
|
|
// ROUNDLi/TRUNCLi/FLOORLi : 1. pipeline stage : can Opcode-Decoder deliver direct the 64 bit operand ? From register "yes"
|
// ROUNDLi/TRUNCLi/FLOORLi : 1. pipeline stage : can Opcode-Decoder deliver direct the 64 bit operand ? From register "yes"
|
|
|
reg ovflag,ovflag2;
|
reg ovflag,ovflag2;
|
reg rovfl;
|
reg rovfl;
|
reg minint;
|
reg minint;
|
wire [11:0] rexdiff,rexo;
|
wire [11:0] rexdiff,rexo;
|
wire ganzklein; // Flag for 0
|
wire ganzklein; // Flag for 0
|
|
|
assign rexdiff = 12'h41D - {1'b0,SRC1[30:20]}; // 4..0 is the right shift value : like Single FP same value space
|
assign rexdiff = 12'h41D - {1'b0,SRC1[30:20]}; // 4..0 is the right shift value : like Single FP same value space
|
|
|
// ovflag2 at the end of rounding : Check for Overflow
|
// ovflag2 at the end of rounding : Check for Overflow
|
always @(posedge BCLK) rovfl <= (ovflag | ovflag2) & (SELECT[1:0] == 2'b11) & ~minint;
|
always @(posedge BCLK) rovfl <= (ovflag | ovflag2) & (SELECT[1:0] == 2'b11) & ~minint;
|
|
|
// a large positiv difference is a very small number :
|
// a large positiv difference is a very small number :
|
assign ganzklein = (~rexdiff[11] & (rexdiff[10:5] != 6'b0)); // 0 is implicit via SRC1[30:20]=0
|
assign ganzklein = (~rexdiff[11] & (rexdiff[10:5] != 6'b0)); // 0 is implicit via SRC1[30:20]=0
|
|
|
// Detection of Overflow
|
// Detection of Overflow
|
assign rexo = ({1'b0,SRC1[30:20]} - {11'h1FF,~BWD[1]}); // subtract B/W = 3FF , D = 3FE
|
assign rexo = ({1'b0,SRC1[30:20]} - {11'h1FF,~BWD[1]}); // subtract B/W = 3FF , D = 3FE
|
|
|
always @(BWD or rexo) // 0 ist in implicitly
|
always @(BWD or rexo) // 0 ist in implicitly
|
casex (BWD)
|
casex (BWD)
|
2'b00 : ovflag = (~rexo[11] & (rexo[10:3] != 8'h0)); // Exponent 0..7 because -128.4 => -128
|
2'b00 : ovflag = (~rexo[11] & (rexo[10:3] != 8'h0)); // Exponent 0..7 because -128.4 => -128
|
2'b01 : ovflag = (~rexo[11] & (rexo[10:4] != 7'h0)); // Exponent 0..15 look above
|
2'b01 : ovflag = (~rexo[11] & (rexo[10:4] != 7'h0)); // Exponent 0..15 look above
|
default : ovflag = (~rexo[11] & (rexo[10:5] != 6'h0)); // but Exponent only 0..30
|
default : ovflag = (~rexo[11] & (rexo[10:5] != 6'h0)); // but Exponent only 0..30
|
endcase
|
endcase
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (START[1]) minint <= (SRC1 == 32'hC1E0_0000) & (SRC2 == 32'h0) & BWD[1]; // detection of -2^31
|
if (START[1]) minint <= (SRC1 == 32'hC1E0_0000) & (SRC2 == 32'h0) & BWD[1]; // detection of -2^31
|
|
|
// ++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++
|
// ADD/SUB : 1. Pipeline Stage : which operand ist bigger ? Exchange if neccessary
|
// ADD/SUB : 1. Pipeline Stage : which operand ist bigger ? Exchange if neccessary
|
// SUB/CMP : SRC2 - SRC1
|
// SUB/CMP : SRC2 - SRC1
|
|
|
reg ex_null,ma_null,ex_msb,ma_msb;
|
reg ex_null,ma_null,ex_msb,ma_msb;
|
reg [10:0] expo1,expo2;
|
reg [10:0] expo1,expo2;
|
wire [11:0] exdiff,exdiff12;
|
wire [11:0] exdiff,exdiff12;
|
wire [20:0] madiff;
|
wire [20:0] madiff;
|
wire switch,nan,sign,sign1,sign2;
|
wire switch,nan,sign,sign1,sign2;
|
reg [5:0] shift1,shift2;
|
reg [5:0] shift1,shift2;
|
|
|
// Pipeline register :
|
// Pipeline register :
|
reg [63:0] muxsrc2;
|
reg [63:0] muxsrc2;
|
reg [55:3] pipe1; // Nummbers for right shifter
|
wire [55:3] pipe1; // Nummbers for right shifter
|
reg [5:0] shift;
|
wire [5:0] shift;
|
|
reg [2:0] pshift;
|
reg vorz,addflag;
|
reg vorz,addflag;
|
|
|
wire [52:0] muxsrc1;
|
wire [52:0] muxsrc1;
|
wire [32:0] lowdiff;
|
wire [32:0] lowdiff;
|
|
|
assign nan = (SELECT[1:0] == 2'b11) ? SRCFLAGS[1] : (~SELECT[1] & (SRCFLAGS[3] | SRCFLAGS[1])); // used at the end
|
assign nan = (SELECT[1:0] == 2'b11) ? SRCFLAGS[1] : (~SELECT[1] & (SRCFLAGS[3] | SRCFLAGS[1])); // used at the end
|
|
|
assign exdiff = {1'b0,SRC2[30:20]} - {1'b0,SRC1[30:20]}; // Difference of Exponents
|
assign exdiff = {1'b0,SRC2[30:20]} - {1'b0,SRC1[30:20]}; // Difference of Exponents
|
assign madiff = {1'b0,SRC2[19:0]} - {1'b0,SRC1[19:0]}; // Difference of Mantissa
|
assign madiff = {1'b0,SRC2[19:0]} - {1'b0,SRC1[19:0]}; // Difference of Mantissa
|
assign exdiff12 = {1'b0,SRC1[30:20]} - {1'b0,SRC2[30:20]}; // Diff. Exponents exchanged
|
assign exdiff12 = {1'b0,SRC1[30:20]} - {1'b0,SRC2[30:20]}; // Diff. Exponents exchanged
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (START[0])
|
if (START[0])
|
begin
|
begin
|
ex_null <= (exdiff[10:0] == 11'h0);
|
ex_null <= (exdiff[10:0] == 11'h0);
|
ma_null <= (madiff[19:0] == 20'h0);
|
ma_null <= (madiff[19:0] == 20'h0);
|
ex_msb <= exdiff[11];
|
ex_msb <= exdiff[11];
|
ma_msb <= madiff[20];
|
ma_msb <= madiff[20];
|
shift1 <= (exdiff[10:6] != 5'h0) ? 6'h3F : exdiff[5:0];
|
shift1 <= (exdiff[10:6] != 5'h0) ? 6'h3F : exdiff[5:0];
|
shift2 <= (exdiff12[10:6] != 5'h0) ? 6'h3F : exdiff12[5:0];
|
shift2 <= (exdiff12[10:6] != 5'h0) ? 6'h3F : exdiff12[5:0];
|
expo1 <= SRC1[30:20];
|
expo1 <= SRC1[30:20];
|
expo2 <= SRC2[30:20];
|
expo2 <= SRC2[30:20];
|
end
|
end
|
|
|
assign lowdiff = {1'b0,SRC2} - {1'b0,SRC1}; // LSD compare
|
assign lowdiff = {1'b0,SRC2} - {1'b0,SRC1}; // LSD compare
|
|
|
assign switch = ex_msb | (ex_null & (ma_msb | (ma_null & lowdiff[32]))); // exchange ?
|
assign switch = ex_msb | (ex_null & (ma_msb | (ma_null & lowdiff[32]))); // exchange ?
|
|
|
assign muxsrc1 = switch ? {MAN2,SRC2} : {MAN1,SRC1};
|
assign muxsrc1 = switch ? {MAN2,SRC2} : {MAN1,SRC1};
|
|
|
|
assign pipe1 = SELECT[1] ? (ganzklein ? 53'd0 : {1'b1,SRC1[19:0],SRC2}) : muxsrc1; // feeding of R.T.F.
|
|
assign shift = SELECT[1] ? {1'b0,rexdiff[4:0]} : (switch ? shift2 : shift1);
|
|
|
always @(posedge BCLK) // Pipeline Reg
|
always @(posedge BCLK) // Pipeline Reg
|
begin
|
begin
|
muxsrc2 <= switch ? {expo1,MAN1,SRC1} : {expo2,MAN2,SRC2}; // Incl. Exponent & "1" of mantissa
|
muxsrc2 <= switch ? {expo1,MAN1,SRC1} : {expo2,MAN2,SRC2}; // Incl. Exponent & "1" of mantisse
|
pipe1 <= SELECT[1] ? (ganzklein ? 53'd0 : {1'b1,SRC1[19:0],SRC2}) : muxsrc1; // Feeding of R.T.F.
|
pshift <= shift[2:0];
|
shift <= SELECT[1] ? {1'b0,rexdiff[4:0]} : (switch ? shift2 : shift1);
|
|
end
|
end
|
|
|
// SRC2 SRC1 : switch = 0 SRC2 SRC1 : switch = 1
|
// SRC2 SRC1 : switch = 0 SRC2 SRC1 : switch = 1
|
// 5 + 3 : +(5 + 3) = 8 3 + 5 : +(5 + 3) = 8 SELECT[0] = 0
|
// 5 + 3 : +(5 + 3) = 8 3 + 5 : +(5 + 3) = 8 SELECT[0] = 0
|
// 5 + (-3) : +(5 - 3) = 2 3 + (-5) : -(5 - 3) = -2
|
// 5 + (-3) : +(5 - 3) = 2 3 + (-5) : -(5 - 3) = -2
|
// (-5) + 3 : -(5 - 3) = -2 (-3) + 5 : +(5 - 3) = 2
|
// (-5) + 3 : -(5 - 3) = -2 (-3) + 5 : +(5 - 3) = 2
|
// (-5) + (-3) : -(5 + 3) = -8 (-3) + (-5) : -(5 + 3) = -8
|
// (-5) + (-3) : -(5 + 3) = -8 (-3) + (-5) : -(5 + 3) = -8
|
// 5 - 3 : +(5 - 3) = 2 3 - 5 : -(5 - 3) = -2 SELECT[0] = 1
|
// 5 - 3 : +(5 - 3) = 2 3 - 5 : -(5 - 3) = -2 SELECT[0] = 1
|
// 5 - (-3) : +(5 + 3) = 8 3 - (-5) : +(5 + 3) = 8
|
// 5 - (-3) : +(5 + 3) = 8 3 - (-5) : +(5 + 3) = 8
|
// (-5) - 3 : -(5 + 3) = -8 (-3) - 5 : -(5 + 3) = -8
|
// (-5) - 3 : -(5 + 3) = -8 (-3) - 5 : -(5 + 3) = -8
|
// (-5) - (-3) : -(5 - 3) = -2 (-3) - (-5) : +(5 - 3) = 2
|
// (-5) - (-3) : -(5 - 3) = -2 (-3) - (-5) : +(5 - 3) = 2
|
|
|
assign sign1 = SRCFLAGS[4];
|
assign sign1 = SRCFLAGS[4];
|
assign sign2 = SRCFLAGS[5];
|
assign sign2 = SRCFLAGS[5];
|
|
|
always @(posedge BCLK) // Pipeline Reg
|
always @(posedge BCLK) // Pipeline Reg
|
begin
|
begin
|
vorz <= switch ? (SELECT[0] ^ sign1) : sign2;
|
vorz <= switch ? (SELECT[0] ^ sign1) : sign2;
|
addflag <= ~(SELECT[0] ^ (sign1 ^ sign2));
|
addflag <= ~(SELECT[0] ^ (sign1 ^ sign2));
|
end
|
end
|
|
|
// CMPF : 1. Pipeline Stage : first result : is stored one level higer in Reg
|
// CMPF : 1. Pipeline Stage : first result : is stored one level higer in Reg
|
|
|
assign CMPRES[1] = ~CMPRES[0] & (switch ? ~sign1 : sign2); // look table above
|
assign CMPRES[1] = ~CMPRES[0] & (switch ? ~sign1 : sign2); // look table above
|
assign CMPRES[0] = (ex_null & ma_null & (sign1 == sign2) & (lowdiff == 33'h0)) | (SRCFLAGS[2] & SRCFLAGS[0]);
|
assign CMPRES[0] = (ex_null & ma_null & (sign1 == sign2) & (lowdiff == 33'h0)) | (SRCFLAGS[2] & SRCFLAGS[0]);
|
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
// ADD/SUB + ROUND/TRUNC : 2. Step : Barrelshifter to the right -->
|
// ADD/SUB + ROUND/TRUNC : 2. Step : Barrelshifter to the right -->
|
|
|
wire [55:0] brshifta,brshiftb,brshiftc,brshiftd,brshifte,brshiftf;
|
wire [55:0] brshifta,brshiftb,brshiftd,brshifte,brshiftf;
|
|
reg [55:0] brshiftc;
|
|
|
// 5..33322222222221111111111 is this picture still correct ? Took over from Single FP
|
// 5..33322222222221111111111 is this picture still correct ? Took over from Single FP
|
// 5..2109876543210987654321098765432-10
|
// 5..2109876543210987654321098765432-10
|
// 1..VVVVVVVVVVVVVVVVVVVVVVVV0000000-00 // last 2 bit for rounding
|
// 1..VVVVVVVVVVVVVVVVVVVVVVVV0000000-00 // last 2 bit for rounding
|
|
|
assign brshifta = shift[5] ? {32'h0, pipe1[55:33], (pipe1[32:3] != 30'h0)} : {pipe1,3'h0};
|
assign brshifta = shift[5] ? {32'h0, pipe1[55:33], (pipe1[32:3] != 30'h0)} : {pipe1,3'h0};
|
assign brshiftb = shift[4] ? {16'h0,brshifta[55:17],(brshifta[16:0] != 17'h0)} : brshifta;
|
assign brshiftb = shift[4] ? {16'h0,brshifta[55:17],(brshifta[16:0] != 17'h0)} : brshifta;
|
assign brshiftc = shift[3] ? { 8'h0, brshiftb[55:9], (brshiftb[8:0] != 9'h0)} : brshiftb;
|
always @(posedge BCLK)
|
assign brshiftd = shift[2] ? { 4'h0, brshiftc[55:5], (brshiftc[4:0] != 5'h0)} : brshiftc;
|
brshiftc <= shift[3] ? { 8'h0, brshiftb[55:9], (brshiftb[8:0] != 9'h0)} : brshiftb;
|
assign brshifte = shift[1] ? { 2'h0, brshiftd[55:3], (brshiftd[2:0] != 3'h0)} : brshiftd;
|
assign brshiftd = pshift[2] ? { 4'h0, brshiftc[55:5], (brshiftc[4:0] != 5'h0)} : brshiftc;
|
assign brshiftf = shift[0] ? { 1'b0, brshifte[55:2], (brshifte[1:0] != 2'h0)} : brshifte;
|
assign brshifte = pshift[1] ? { 2'h0, brshiftd[55:3], (brshiftd[2:0] != 3'h0)} : brshiftd;
|
|
assign brshiftf = pshift[0] ? { 1'b0, brshifte[55:2], (brshifte[1:0] != 2'h0)} : brshifte;
|
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
// ROUNDLi/TRUNCLi/FLOORLi : 3. Step : round to Integer
|
// ROUNDLi/TRUNCLi/FLOORLi : 3. Step : round to Integer
|
|
|
reg car_ry;
|
reg car_ry;
|
wire [1:0] inex;
|
wire [1:0] inex;
|
wire [30:0] compl;
|
wire [32:0] iadder;
|
wire [31:0] iadder;
|
|
wire restbits;
|
wire restbits;
|
|
|
assign restbits = (brshiftf[23:0] != 24'h0);
|
assign restbits = (brshiftf[23:0] != 24'h0);
|
assign inex = {brshiftf[24],restbits}; // Inexact-Flag-Data transfered to multiplexer at the end
|
assign inex = {brshiftf[24],restbits}; // Inexact-Flag-Data transfered to multiplexer at the end
|
|
|
always @(SELECT or sign1 or brshiftf or restbits or inex or ganzklein)
|
always @(SELECT or sign1 or brshiftf or restbits or inex or ganzklein)
|
casex (SELECT[3:2])
|
casex (SELECT[3:2])
|
2'b00 : car_ry = sign1 ^ (((brshiftf[25:24] == 2'b11) & ~restbits) | (inex == 2'b11)); // ROUNDLi
|
2'b00 : car_ry = sign1 ^ (((brshiftf[25:24] == 2'b11) & ~restbits) | (inex == 2'b11)); // ROUNDLi
|
2'b1x : car_ry = sign1 ? (~ganzklein & (inex == 2'b00)) : 1'b0; // +numbers like TRUNCLi, -numbers to "-infinity" round
|
2'b1x : car_ry = sign1 ? (~ganzklein & (inex == 2'b00)) : 1'b0; // +numbers like TRUNCLi, -numbers to "-infinity" round
|
default : car_ry = sign1; // TRUNCLi , simple cut off
|
default : car_ry = sign1; // TRUNCLi , simple cut off
|
endcase
|
endcase
|
|
|
assign compl = sign1 ? ~brshiftf[55:25] : brshiftf[55:25];
|
assign iadder = (sign1 ? {2'b11,~brshiftf[55:25]} : {2'b0,brshiftf[55:25]}) + {32'h0,car_ry};
|
|
|
assign iadder = {sign1,compl} + {31'h0,car_ry};
|
|
|
|
always @(posedge BCLK) IOUT <= minint ? 32'h8000_0000 : iadder;
|
always @(posedge BCLK) IOUT <= minint ? 32'h8000_0000 : iadder[31:0];
|
|
|
always @(iadder or BWD or sign1) // special overflow detection i.e. -129 to -255 at Byte
|
always @(iadder or BWD or sign1) // special overflow detection i.e. -129 to -255 at Byte
|
casex (BWD) // or 127.9 -> 128 = error !
|
casex (BWD) // or 127.9 -> 128 = error !
|
2'b00 : ovflag2 = (iadder[8] != iadder[7]); // Byte
|
2'b00 : ovflag2 = (iadder[8] != iadder[7]); // Byte
|
2'b01 : ovflag2 = (iadder[16] != iadder[15]); // Word
|
2'b01 : ovflag2 = (iadder[16] != iadder[15]); // Word
|
default : ovflag2 = 1'b0;
|
default : ovflag2 = (iadder[32] != iadder[31]); // Double
|
endcase
|
endcase
|
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
// ADD/SUB : 3. Step : Addition or Subtraction
|
// ADD/SUB : 3. Step : Addition or Subtraction
|
|
|
wire [67:0] result;
|
wire [67:0] result;
|
wire [55:0] blshifti;
|
wire [55:0] blshifti;
|
wire [12:0] shiftl;
|
wire [12:0] shiftl;
|
wire shift_32;
|
wire shift_32;
|
wire [65:0] add_q;
|
wire [65:0] add_q;
|
|
|
// The central adder : the subtraction needs 3 Guard-Bits after LSB for correct rounding
|
// The central adder : the subtraction needs 3 Guard-Bits after LSB for correct rounding
|
assign result = {1'b0,muxsrc2,3'b000} + (addflag ? {12'h0,brshiftf} : {12'hFFF,~brshiftf}) + {67'd0,~addflag};
|
assign result = {1'b0,muxsrc2,3'b000} + (addflag ? {12'h0,brshiftf} : {12'hFFF,~brshiftf}) + {67'd0,~addflag};
|
|
|
assign blshifti = SELECT[1] ? {movif,24'h0} : result[55:0]; // Feeding of MOViL, comes from Register
|
assign blshifti = SELECT[1] ? {movif,24'h0} : result[55:0]; // Feeding of MOViL, comes from Register
|
|
|
assign shiftl = SELECT[1] ? 13'h041E : {1'b0,result[67:56]}; // MOViL
|
assign shiftl = SELECT[1] ? 13'h041E : {1'b0,result[67:56]}; // MOViL
|
|
|
assign shift_32 = (blshifti[55:24] == 32'h0);
|
assign shift_32 = (blshifti[55:24] == 32'h0);
|
|
|
// In case of ADD the result bypasses the barrelshifter : LSB of exponent has changed
|
// In case of ADD the result bypasses the barrelshifter : LSB of exponent has changed
|
assign add_q = (muxsrc2[53] != result[56]) ? {result[67:3],(result[2:0] != 3'b000)}
|
assign add_q = (muxsrc2[53] != result[56]) ? {result[67:3],(result[2:0] != 3'b000)}
|
: {result[67:56],result[54:2],(result[1:0] != 2'b00)} ;
|
: {result[67:56],result[54:2],(result[1:0] != 2'b00)} ;
|
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
// ADD/SUB : 4. Step : Barrelshifter left for SUB and MOViF :
|
// ADD/SUB : 4. Step : Barrelshifter left for SUB and MOViF :
|
|
|
wire shift_16,shift_8,shift_4,shift_2,shift_1,zero;
|
wire shift_16,shift_8,shift_4,shift_2,shift_1,zero;
|
wire [1:0] lsb_bl;
|
wire [1:0] lsb_bl;
|
wire [55:0] blshifta,blshiftb,blshiftc,blshiftd,blshifte,blshiftf;
|
wire [55:0] blshifta,blshiftb,blshiftc,blshiftd,blshifte,blshiftf;
|
wire [12:0] expol;
|
wire [12:0] expol;
|
|
|
assign blshifta = shift_32 ? {blshifti[23:0],32'h0} : blshifti;
|
assign blshifta = shift_32 ? {blshifti[23:0],32'h0} : blshifti;
|
assign shift_16 = (blshifta[55:40] == 16'h0);
|
assign shift_16 = (blshifta[55:40] == 16'h0);
|
assign blshiftb = shift_16 ? {blshifta[39:0],16'h0} : blshifta;
|
assign blshiftb = shift_16 ? {blshifta[39:0],16'h0} : blshifta;
|
assign shift_8 = (blshiftb[55:48] == 8'h00);
|
assign shift_8 = (blshiftb[55:48] == 8'h00);
|
assign blshiftc = shift_8 ? {blshiftb[47:0],8'h0} : blshiftb;
|
assign blshiftc = shift_8 ? {blshiftb[47:0],8'h0} : blshiftb;
|
assign shift_4 = (blshiftc[55:52] == 4'h0);
|
assign shift_4 = (blshiftc[55:52] == 4'h0);
|
assign blshiftd = shift_4 ? {blshiftc[51:0],4'h0} : blshiftc;
|
assign blshiftd = shift_4 ? {blshiftc[51:0],4'h0} : blshiftc;
|
assign shift_2 = (blshiftd[55:54] == 2'b00);
|
assign shift_2 = (blshiftd[55:54] == 2'b00);
|
assign blshifte = shift_2 ? {blshiftd[53:0],2'b0} : blshiftd;
|
assign blshifte = shift_2 ? {blshiftd[53:0],2'b0} : blshiftd;
|
assign shift_1 = ~blshifte[55];
|
assign shift_1 = ~blshifte[55];
|
assign blshiftf = shift_1 ? {blshifte[54:0],1'b0} : blshifte;
|
assign blshiftf = shift_1 ? {blshifte[54:0],1'b0} : blshifte;
|
|
|
// Overflow at ROUNDLi/TRUNCLi/FLOORLi is shown in overflow of exponent , SELECT[1] is then 1
|
// Overflow at ROUNDLi/TRUNCLi/FLOORLi is shown in overflow of exponent , SELECT[1] is then 1
|
assign expol = shiftl - {7'h00,shift_32,shift_16,shift_8,shift_4,shift_2,shift_1};
|
assign expol = shiftl - {7'h00,shift_32,shift_16,shift_8,shift_4,shift_2,shift_1};
|
|
|
// Inexact at ROUNDLi/TRUNCLi/FLOORLi : evaluation for all one level higher
|
// Inexact at ROUNDLi/TRUNCLi/FLOORLi : evaluation for all one level higher
|
assign lsb_bl = (SELECT == 2'b11) ? inex : {blshiftf[2],(blshiftf[1:0] != 2'b0)};
|
assign lsb_bl = (SELECT == 2'b11) ? inex : {blshiftf[2],(blshiftf[1:0] != 2'b0)};
|
|
|
assign zero = (~SELECT[1] & SRCFLAGS[2] & SRCFLAGS[0])
|
assign zero = (~SELECT[1] & SRCFLAGS[2] & SRCFLAGS[0])
|
| ((blshifti == 56'h0) & ((~addflag & ~SELECT[1]) | (SELECT[1:0] == 2'b10)));
|
| ((blshifti == 56'h0) & ((~addflag & ~SELECT[1]) | (SELECT[1:0] == 2'b10)));
|
|
|
assign sign = SELECT[1] ? sign_movif : (vorz & ~zero); // sign for MOViL
|
assign sign = SELECT[1] ? sign_movif : (vorz & ~zero); // sign for MOViL
|
|
|
// 2. Pipeline register for ADD , SUB and MOViL
|
// 2. Pipeline register for ADD , SUB and MOViL
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
outreg <= (addflag & ~SELECT[1]) ? {nan,zero,sign,1'b0,add_q}
|
outreg <= (addflag & ~SELECT[1]) ? {nan,zero,sign,1'b0,add_q}
|
: {nan,zero,sign,expol,blshiftf[54:3],lsb_bl};
|
: {nan,zero,sign,expol,blshiftf[54:3],lsb_bl};
|
|
|
// ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++
|
|
|
assign OUT = {outreg[69:67],(rovfl ? 2'b01 : outreg[66:65]),outreg[64:0]};
|
assign OUT = {outreg[69:67],(rovfl ? 2'b01 : outreg[66:65]),outreg[64:0]};
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 5. DFPU_MISC Double precision floating point miscellaneous operations
|
// 5. DFPU_MISC Double precision floating point miscellaneous operations
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DFPU_MISC ( BCLK, START, SRC1, SRC2, SRCFLAG, MIMUX, MODE, OUT );
|
module DFPU_MISC ( BCLK, START, SRC1, SRC2, MAN2, SRCFLAGS, MODE, OUT );
|
|
|
input BCLK;
|
input BCLK;
|
input START;
|
input [1:0] START;
|
input [31:0] SRC1,SRC2;
|
input [31:0] SRC1,SRC2;
|
input SRCFLAG;
|
input [19:0] MAN2;
|
input MIMUX;
|
input [5:0] SRCFLAGS;
|
input [3:0] MODE;
|
input [3:0] MODE;
|
output [69:0] OUT;
|
output [69:0] OUT;
|
|
|
reg [69:0] OUT;
|
reg [69:0] OUT;
|
reg [63:0] daten;
|
reg [63:0] daten;
|
|
|
wire [10:0] scalb_l;
|
wire sign;
|
wire nan,zero,sign;
|
|
wire [12:0] lexpo,sexpo;
|
wire [12:0] lexpo,sexpo;
|
wire [69:0] scalb_res,logb_res,fl_lf;
|
wire [69:0] scalb_res,logb_res,fl_lf;
|
|
|
always @(posedge BCLK) if (START) daten <= {(MIMUX ? {daten[31],scalb_l,daten[19:0]}: SRC1),SRC2};
|
always @(posedge BCLK) if (START[1]) daten <= {SRC1,SRC2};
|
|
assign sign = daten[63];
|
|
|
assign nan = MODE[0] ? (daten[62:55] == 8'hFF) : (daten[62:52] == 11'h7FF);
|
// +++++++++++++++++++++++++++ MOVFL and MOVLF +++++++++++++++++++++++++++++++++++
|
assign zero = MODE[0] ? (daten[62:55] == 8'h00) : (daten[62:52] == 11'h000);
|
|
assign sign = daten[63] & ~zero;
|
|
|
|
assign lexpo = {5'b0,daten[62:55]} + 13'h0380; // -7F + 3FF
|
assign lexpo = {5'b0,daten[62:55]} + 13'h0380; // -7F + 3FF
|
|
|
assign sexpo = (daten[62:52] > 11'h47E) ? 13'h0FFF
|
assign sexpo = (daten[62:52] > 11'h47E) ? 13'h0FFF
|
: ((daten[62:52] < 11'h381) ? 13'h0 : {2'b0,{4{daten[62]}},daten[58:52]});
|
: ((daten[62:52] < 11'h381) ? 13'h0 : {2'b0,{4{daten[62]}},daten[58:52]});
|
|
|
assign fl_lf = MODE[0] ? {nan,zero,sign,lexpo,daten[54:32],31'h0} // MOVFL
|
assign fl_lf = MODE[0] ? {SRCFLAGS[1:0],sign,lexpo,daten[54:32],31'h0} // MOVFL
|
: {nan,zero,sign,sexpo,daten[51:29],28'h0,daten[29:28],(daten[27:0] != 28'h0)}; // MOVLF
|
: {SRCFLAGS[1:0],sign,sexpo,daten[51:29],28'h0,daten[29:28],(daten[27:0] != 28'h0)}; // MOVLF
|
|
|
// +++++++++++++++++++++++++++ LOGBf +++++++++++++++++++++++++++++++++++
|
// +++++++++++++++++++++++++++ LOGBf +++++++++++++++++++++++++++++++++++
|
|
|
wire logb_null;
|
|
wire [9:0] sel_data,unbiased,shift_l8,shift_l4,shift_l2;
|
wire [9:0] sel_data,unbiased,shift_l8,shift_l4,shift_l2;
|
wire [8:0] shift_l;
|
wire [8:0] shift_l;
|
wire posi_8,posi_4,posi_2,posi_1;
|
wire posi_8,posi_4,posi_2,posi_1;
|
wire [4:0] calc_exp;
|
wire [4:0] calc_exp;
|
wire [6:0] logb_exp;
|
wire [6:0] logb_exp;
|
|
|
assign logb_null = MODE[1] ? (daten[62:55] == 8'h7F) : (daten[62:52] == 11'h3FF);
|
|
|
|
assign sel_data = MODE[1] ? {{3{~daten[62]}},daten[61:55]} : daten[61:52];
|
assign sel_data = MODE[1] ? {{3{~daten[62]}},daten[61:55]} : daten[61:52];
|
assign unbiased = daten[62] ? (sel_data + 10'h001) : ~sel_data;
|
assign unbiased = daten[62] ? (sel_data + 10'h001) : ~sel_data;
|
|
|
// detection of leading "1"
|
// detection of leading "1"
|
assign posi_8 = (unbiased[9:2] == 8'h00);
|
assign posi_8 = (unbiased[9:2] == 8'h00);
|
assign shift_l8 = posi_8 ? {unbiased[1:0],8'h00} : unbiased;
|
assign shift_l8 = posi_8 ? {unbiased[1:0],8'h00} : unbiased;
|
assign posi_4 = (shift_l8[9:6] == 4'h0);
|
assign posi_4 = (shift_l8[9:6] == 4'h0);
|
assign shift_l4 = posi_4 ? {shift_l8[5:0],4'h0} : shift_l8;
|
assign shift_l4 = posi_4 ? {shift_l8[5:0],4'h0} : shift_l8;
|
assign posi_2 = (shift_l4[9:8] == 2'b00);
|
assign posi_2 = (shift_l4[9:8] == 2'b00);
|
assign shift_l2 = posi_2 ? {shift_l4[7:0],2'b0} : shift_l4;
|
assign shift_l2 = posi_2 ? {shift_l4[7:0],2'b0} : shift_l4;
|
assign posi_1 = ~shift_l2[9];
|
assign posi_1 = ~shift_l2[9];
|
assign shift_l = posi_1 ? {shift_l2[7:0],1'b0} : shift_l2[8:0]; // top bit is hidden "1"
|
assign shift_l = posi_1 ? {shift_l2[7:0],1'b0} : shift_l2[8:0]; // top bit is hidden "1"
|
|
|
assign calc_exp = 5'h08 - {1'b0,posi_8,posi_4,posi_2,posi_1}; // Minimum is "F" = for exponent +/-1 <=> 2^0
|
assign calc_exp = 5'h08 - {1'b0,posi_8,posi_4,posi_2,posi_1}; // Minimum is "F" = for exponent +/-1 <=> 2^0
|
|
|
// exponent is set one level higher for F and L
|
// exponent is set one level higher for F and L
|
assign logb_exp = MODE[1] ? {{4{~calc_exp[4]}},{3{calc_exp[4]}}} : {~calc_exp[4],{6{calc_exp[4]}}};
|
assign logb_exp = MODE[1] ? {{4{~calc_exp[4]}},{3{calc_exp[4]}}} : {~calc_exp[4],{6{calc_exp[4]}}};
|
|
|
assign logb_res = logb_null ? {70'h10_0000_0000_0000_0000} : {2'b00,~daten[62],2'b00,logb_exp,calc_exp[3:0],shift_l,45'h0};
|
assign logb_res = {SRCFLAGS[1],1'b0,~daten[62],2'b00,logb_exp,calc_exp[3:0],shift_l,45'h0};
|
|
|
// ++++++++++++++++++++++++ SCALBf ++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++ SCALBf ++++++++++++++++++++++++++++++++++
|
|
|
wire [7:0] scalb_f;
|
reg [3:0] rshift;
|
|
reg [10:0] shf_r0,dexpo; // dexpo = Exponent Destination
|
|
reg huge;
|
|
reg svorz,dvorz;
|
|
|
|
wire [10:0] shf_r1,shf_r2,shf_r4,shf_r8;
|
|
wire [12:0] addexp,newexp,finexp;
|
|
wire nan;
|
|
|
assign scalb_f = SRCFLAG ? 8'h00 : (daten[39:32] + daten[30:23]);
|
always @(posedge BCLK) // 2**0,9.. is transformed to 2**0 = 1 -> no change at SRC2
|
assign scalb_l = SRCFLAG ? 11'h000 : (daten[42:32] + daten[30:20]);
|
if (START[0])
|
|
begin
|
|
shf_r0 <= ( SRC1[30] | ((SRC1[29:23] == 7'h7F) & (MODE[1] | (SRC1[22:20] == 3'd7))) ) ?
|
|
(MODE[1] ? {4'd1,SRC1[22:16]} : {1'b1,SRC1[19:10]}) : 11'd0;
|
|
rshift <= MODE[1] ? 4'd6 - SRC1[26:23] : 4'd9 - SRC1[23:20];
|
|
huge <= MODE[1] ? ( SRC1[30] & ((SRC1[29:26] != 4'd0) | (SRC1[25:23] == 3'h7)) ) // >406 in Double Style
|
|
: ( SRC1[30] & ((SRC1[29:24] != 6'd0) | (SRC1[23] & (SRC1[22] | SRC1[21]))) ); // >409
|
|
svorz <= SRC1[31];
|
|
dvorz <= SRC2[31];
|
|
dexpo <= MODE[1] ? {3'd0,SRC2[30:23]} : SRC2[30:20];
|
|
end
|
|
|
|
assign shf_r1 = rshift[0] ? {1'b0,shf_r0[10:1]} : shf_r0; // a mini-TRUNC of 11 Bits
|
|
assign shf_r2 = rshift[1] ? {2'd0,shf_r1[10:2]} : shf_r1;
|
|
assign shf_r4 = rshift[2] ? {4'd0,shf_r2[10:4]} : shf_r2;
|
|
assign shf_r8 = rshift[3] ? {8'd0,shf_r4[10:8]} : shf_r4;
|
|
|
|
assign addexp = svorz ? {2'd0,dexpo} - {2'd0,shf_r8} : {2'd0,dexpo} + {2'd0,shf_r8};
|
|
|
assign scalb_res = MODE[1] ? // no rounding of Single Data
|
assign newexp = MODE[1] ? {addexp[9:8],{3{addexp[7]}},addexp[7:0]} : addexp[12:0];
|
{2'b00,daten[31],5'b0,scalb_f,daten[22:0],daten[28:1],3'b000}
|
|
: {2'b00,daten[63],2'b0,daten[62:0],2'b00};
|
assign finexp = SRCFLAGS[2] ? {3'd0,newexp[9:0]} // never an Overflow if SRC2 = 0.0 !
|
|
: {(huge ? {svorz,1'b1} : newexp[12:11]),newexp[10:0]}; // Overflow or Underflow
|
|
|
|
assign nan = SRCFLAGS[3] | SRCFLAGS[1];
|
|
|
|
assign scalb_res = MODE[1] ? // Mantisse doesn't change !
|
|
{nan,SRCFLAGS[2],daten[31],finexp,daten[22:0],daten[28:0],2'b00}
|
|
: {nan,SRCFLAGS[2],dvorz,finexp,MAN2,daten[31:0],2'b00};
|
|
|
// ++++++++++++++++++++++++ Output ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++ Output ++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
always @(posedge BCLK) OUT <= MODE[3] ? (MODE[2] ? logb_res : scalb_res) : fl_lf ; // LOGB/SCALB : MOVLF/MOVFL
|
always @(posedge BCLK) OUT <= MODE[3] ? (MODE[2] ? logb_res : scalb_res) : fl_lf ; // LOGB/SCALB : MOVLF/MOVFL
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 6. DFPU_MUL Double precision floating point multiplier
|
// 6. DFPU_MUL Double precision floating point multiplier
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DFPU_MUL ( BCLK, SRC1, SRC2, START, MRESULT, SRCFLAGS, OUT );
|
module DFPU_MUL ( BCLK, SRC1, SRC2, START, MRESULT, SRCFLAGS, OUT );
|
|
|
input BCLK;
|
input BCLK;
|
input [31:0] SRC1,SRC2;
|
input [31:0] SRC1,SRC2;
|
input START; // that is START[0]
|
input START; // that is START[0]
|
input [105:0] MRESULT;
|
input [105:0] MRESULT;
|
input [5:0] SRCFLAGS; // NAN and ZERO flags
|
input [5:0] SRCFLAGS; // NAN and ZERO flags
|
output [69:0] OUT; // The result
|
output [69:0] OUT; // The result
|
|
|
reg [69:0] OUT;
|
reg [69:0] OUT;
|
reg [12:0] exponent;
|
reg [12:0] exponent;
|
wire orlow;
|
wire orlow;
|
wire [12:0] expoh,expol;
|
wire [12:0] expoh,expol;
|
wire [1:0] restlow,resthigh;
|
wire [1:0] restlow,resthigh;
|
wire zero,nan,sign;
|
wire zero,nan,sign;
|
|
|
assign zero = SRCFLAGS[2] | SRCFLAGS[0]; // one is NULL -> NULL is the result
|
assign zero = SRCFLAGS[2] | SRCFLAGS[0]; // one is NULL -> NULL is the result
|
assign nan = SRCFLAGS[3] | SRCFLAGS[1]; // one is NAN -> error
|
assign nan = SRCFLAGS[3] | SRCFLAGS[1]; // one is NAN -> error
|
assign sign = (SRCFLAGS[5] ^ SRCFLAGS[4]) & ~zero;
|
assign sign = (SRCFLAGS[5] ^ SRCFLAGS[4]) & ~zero;
|
|
|
assign orlow = (MRESULT[50:0] != 51'b0);
|
assign orlow = (MRESULT[50:0] != 51'b0);
|
|
|
assign restlow = {MRESULT[51],orlow};
|
assign restlow = {MRESULT[51],orlow};
|
assign resthigh = {MRESULT[52],(MRESULT[51] | orlow)};
|
assign resthigh = {MRESULT[52],(MRESULT[51] | orlow)};
|
|
|
always @(posedge BCLK) if (START) exponent <= {2'b00,SRC1[30:20]} + {2'b00,SRC2[30:20]};
|
always @(posedge BCLK) if (START) exponent <= {2'b00,SRC1[30:20]} + {2'b00,SRC2[30:20]};
|
|
|
assign expoh = exponent - 13'h03FE;
|
assign expoh = exponent - 13'h03FE;
|
assign expol = exponent - 13'h03FF; // for MSB if MRESULT=0
|
assign expol = exponent - 13'h03FF; // for MSB if MRESULT=0
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
OUT <= MRESULT[105] ? {nan,zero,sign,expoh,MRESULT[104:53],resthigh} // 52 Bit Mantissa
|
OUT <= MRESULT[105] ? {nan,zero,sign,expoh,MRESULT[104:53],resthigh} // 52 Bit Mantissa
|
: {nan,zero,sign,expol,MRESULT[103:52],restlow};
|
: {nan,zero,sign,expol,MRESULT[103:52],restlow};
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 7. DIVI_PREP Prepare data for the divider
|
// 7. SCANDIG Scan digit for leading one
|
|
//
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
module SCANDIG (DIN, MBIT, LBIT, NONZ);
|
|
|
|
input [3:0] DIN;
|
|
output MBIT,LBIT,NONZ;
|
|
|
|
assign MBIT = DIN[3] | DIN[2]; // 1xxx = 11
|
|
assign LBIT = DIN[3] | (DIN[3:1] == 3'b001); // 01xx = 10
|
|
assign NONZ = (DIN != 4'd0); // 001x = 01
|
|
|
|
endmodule
|
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//
|
|
// 8. DIVI_PREP Prepare data for the divider
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DIVI_PREP (SRC, BWD, NOT_DEI, EXTDATA, DOUT, MSB, NULL, MINUS);
|
module DIVI_PREP (SRC, BWD, NOT_DEI, EXTDATA, DOUT, MSB, NULL, MINUS);
|
|
|
input [31:0] SRC;
|
input [31:0] SRC;
|
input [1:0] BWD;
|
input [1:0] BWD;
|
input NOT_DEI;
|
input NOT_DEI;
|
input EXTDATA;
|
input EXTDATA;
|
|
|
output [31:0] DOUT;
|
output [31:0] DOUT;
|
output [4:0] MSB;
|
output [4:0] MSB;
|
output NULL;
|
output NULL;
|
output MINUS;
|
output MINUS;
|
|
|
reg [31:0] double;
|
reg [31:0] double;
|
|
reg [2:0] select;
|
|
|
wire [15:0] test_16;
|
|
wire [7:0] test_8;
|
|
wire [3:0] test_4;
|
|
wire [1:0] test_2;
|
|
wire bit_4,bit_3,bit_2,bit_1,bit_0;
|
|
wire [1:0] modus;
|
wire [1:0] modus;
|
|
wire [7:0] mbits,lbits,dnonz;
|
|
|
assign modus = (NOT_DEI | EXTDATA) ? BWD : {(BWD[1] | BWD[0]),1'b1};
|
assign modus = (NOT_DEI | EXTDATA) ? BWD : {(BWD[1] | BWD[0]),1'b1};
|
|
|
always @(modus or SRC or NOT_DEI)
|
always @(modus or SRC or NOT_DEI)
|
casex (modus)
|
casex (modus)
|
2'b00 : double = {{24{SRC[7] & NOT_DEI}},SRC[7:0]};
|
2'b00 : double = {{24{SRC[7] & NOT_DEI}},SRC[7:0]};
|
2'b01 : double = {{16{SRC[15] & NOT_DEI}},SRC[15:0]};
|
2'b01 : double = {{16{SRC[15] & NOT_DEI}},SRC[15:0]};
|
2'b1x : double = SRC;
|
2'b1x : double = SRC;
|
endcase
|
endcase
|
|
|
assign MINUS = double[31] & NOT_DEI;
|
assign MINUS = double[31] & NOT_DEI;
|
|
|
assign DOUT = ({32{MINUS}} ^ double) + {31'h0,MINUS}; // assign DOUT = MINUS ? (32'd0 - double) : double;
|
assign DOUT = ({32{MINUS}} ^ double) + {31'h0,MINUS}; // assign DOUT = MINUS ? (32'd0 - double) : double;
|
|
|
// now find most significant set bit : FFS
|
// now find most significant set bit : FFS
|
|
|
assign bit_4 = (DOUT[31:16] != 16'h0);
|
SCANDIG digit_0 (.DIN(DOUT[3:0]), .MBIT(mbits[0]), .LBIT(lbits[0]), .NONZ(dnonz[0]) );
|
assign test_16 = bit_4 ? DOUT[31:16] : DOUT[15:0];
|
SCANDIG digit_1 (.DIN(DOUT[7:4]), .MBIT(mbits[1]), .LBIT(lbits[1]), .NONZ(dnonz[1]) );
|
assign bit_3 = (test_16[15:8] != 8'h0);
|
SCANDIG digit_2 (.DIN(DOUT[11:8]), .MBIT(mbits[2]), .LBIT(lbits[2]), .NONZ(dnonz[2]) );
|
assign test_8 = bit_3 ? test_16[15:8] : test_16[7:0];
|
SCANDIG digit_3 (.DIN(DOUT[15:12]), .MBIT(mbits[3]), .LBIT(lbits[3]), .NONZ(dnonz[3]) );
|
assign bit_2 = (test_8[7:4] != 4'h0);
|
SCANDIG digit_4 (.DIN(DOUT[19:16]), .MBIT(mbits[4]), .LBIT(lbits[4]), .NONZ(dnonz[4]) );
|
assign test_4 = bit_2 ? test_8[7:4] : test_8[3:0];
|
SCANDIG digit_5 (.DIN(DOUT[23:20]), .MBIT(mbits[5]), .LBIT(lbits[5]), .NONZ(dnonz[5]) );
|
assign bit_1 = (test_4[3:2] != 2'b0);
|
SCANDIG digit_6 (.DIN(DOUT[27:24]), .MBIT(mbits[6]), .LBIT(lbits[6]), .NONZ(dnonz[6]) );
|
assign test_2 = bit_1 ? test_4[3:2] : test_4[1:0];
|
SCANDIG digit_7 (.DIN(DOUT[31:28]), .MBIT(mbits[7]), .LBIT(lbits[7]), .NONZ(dnonz[7]) );
|
assign bit_0 = test_2[1];
|
|
assign NULL = (test_2 == 2'b00);
|
always @(dnonz)
|
|
casex (dnonz[7:1])
|
|
7'b1xxx_xxx : select = 3'b111;
|
|
7'b01xx_xxx : select = 3'b110;
|
|
7'b001x_xxx : select = 3'b101;
|
|
7'b0001_xxx : select = 3'b100;
|
|
7'b0000_1xx : select = 3'b011;
|
|
7'b0000_01x : select = 3'b010;
|
|
7'b0000_001 : select = 3'b001;
|
|
default : select = 3'b000;
|
|
endcase
|
|
|
|
assign NULL = (dnonz == 8'd0);
|
|
|
assign MSB = {bit_4,bit_3,bit_2,bit_1,bit_0};
|
assign MSB = {select,mbits[select],lbits[select]};
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 8. DFPU_DIV The divider for all divide opcodes : double, single and integer
|
// 9. DFPU_DIV The divider for all divide opcodes : double, single and integer
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DFPU_DIV ( BCLK, BRST, START, SRC1, SRC2, MAN1, MAN2, SRCFLAGS, FL, BWD, OPCODE, OUT, DONE, DIVI_OUT, DVZ_TRAP, DEI_OVF );
|
module DFPU_DIV ( BCLK, BRST, START, SRC1, SRC2, MAN1, MAN2, SRCFLAGS, FL, BWD, OPCODE, OUT, DONE, DIVI_OUT, DVZ_TRAP, DEI_OVF );
|
|
|
// This version needs for Double 28+1 cycles if MAN1<MAN2 otherwise 28+2.
|
// This version needs for Double 28+1 cycles if MAN1<MAN2 otherwise 28+2.
|
// For Single it needs 13+1 cyckes or 13+2.
|
// For Single it needs 13+1 cyckes or 13+2.
|
|
|
input BCLK,BRST;
|
input BCLK,BRST;
|
input [3:0] START; // START & recognized Divider Operation
|
input [3:0] START; // START & recognized Divider Operation
|
input [31:0] SRC1,SRC2; // input data
|
input [31:0] SRC1,SRC2; // input data
|
input [20:0] MAN1,MAN2;
|
input [20:0] MAN1,MAN2;
|
input [5:0] SRCFLAGS; // NAN and ZERO
|
input [5:0] SRCFLAGS; // NAN and ZERO
|
input FL;
|
input FL;
|
input [1:0] BWD;
|
input [1:0] BWD;
|
input [2:0] OPCODE; // for all DIVi variants
|
input [2:0] OPCODE; // for all DIVi variants
|
|
|
output [69:0] OUT; // the result
|
output [69:0] OUT; // the result
|
output reg DONE; // Pipeline-Flag
|
output reg DONE; // Pipeline-Flag
|
output [63:0] DIVI_OUT; // for Integer Division
|
output [63:0] DIVI_OUT; // for Integer Division
|
output DVZ_TRAP; // Divide by Zero Trap
|
output DVZ_TRAP; // Divide by Zero Trap
|
output [1:0] DEI_OVF; // DEI Overflow
|
output [1:0] DEI_OVF; // DEI Overflow
|
|
|
// ++++++++++++++ for Integer Division ++++++++++++++
|
// ++++++++++++++ for Integer Division ++++++++++++++
|
reg run_divi;
|
reg run_divi;
|
reg divi_pipe1,divi_pipe2,divi_pipe3,divi_pipe4;
|
reg divi_pipe1,divi_pipe2,divi_pipe3,divi_pipe4;
|
reg neg_src1,neg_src2,nul_src2;
|
reg neg_src1,neg_src2,nul_src2;
|
reg [4:0] msb_src1;
|
reg [4:0] msb_src1;
|
reg [5:0] msb_src2;
|
reg [5:0] msb_src2;
|
reg [31:0] ivalue,src2_reg,pipe_reg;
|
reg [31:0] ivalue,src2_reg,pipe_reg;
|
reg [4:0] divi_counter;
|
reg [4:0] divi_counter;
|
reg sub_case;
|
reg sub_case;
|
reg negativ;
|
reg negativ;
|
reg [32:0] divi_result;
|
reg [32:0] divi_result;
|
reg [63:0] DIVI_OUT;
|
reg [63:0] DIVI_OUT;
|
reg DVZ_TRAP,dvz_pipe;
|
reg DVZ_TRAP,dvz_pipe;
|
reg sel_in;
|
reg sel_in;
|
reg [62:0] din_mux;
|
reg [62:0] din_mux;
|
reg dei_pipe;
|
reg dei_pipe;
|
reg extdata; // extended data : 2 data packets, only apply to DEI
|
reg extdata; // extended data : 2 data packets, only apply to DEI
|
reg [2:0] addoff;
|
reg [2:0] addoff;
|
reg next_msb2;
|
reg next_msb2;
|
reg [31:0] dei_result;
|
reg [31:0] dei_result;
|
reg [1:0] DEI_OVF;
|
reg [1:0] DEI_OVF;
|
|
|
wire [31:0] i_in;
|
wire [31:0] i_in;
|
wire [37:0] i_out;
|
wire [37:0] i_out;
|
wire [6:0] diff_msb;
|
wire [6:0] diff_msb;
|
wire [5:1] shift_r;
|
wire [5:1] shift_r;
|
wire [62:0] shift_2;
|
wire [62:0] shift_2;
|
wire [62:0] shift_4;
|
wire [62:0] shift_4;
|
wire [62:0] shift_8;
|
wire [62:0] shift_8;
|
wire [62:0] shift_16;
|
wire [62:0] shift_16;
|
wire [64:0] shift_32;
|
wire [64:0] shift_32;
|
wire stop_divi,neg_flag;
|
wire stop_divi,neg_flag;
|
wire rest_null,plus_1,ist_null;
|
wire rest_null,plus_1,ist_null;
|
wire not_dei;
|
wire not_dei;
|
wire valdata; // Data <> 0 at DEI
|
wire valdata; // Data <> 0 at DEI
|
|
|
// ++++++++++++++ Floating Point & calculation path ++++++++
|
// ++++++++++++++ Floating Point & calculation path ++++++++
|
reg [69:0] OUT;
|
reg [69:0] OUT;
|
reg [32:0] save1;
|
reg [32:0] save1;
|
reg runflag;
|
reg runflag;
|
reg [55:0] dreimal;
|
reg [55:0] dreimal;
|
reg [56:0] divreg,divsr;
|
reg [56:0] divreg,divsr;
|
reg [31:0] divreg_ext;
|
reg [31:0] divreg_ext;
|
reg [12:0] exponent;
|
reg [12:0] exponent;
|
|
|
wire load_src1,load_src2;
|
wire load_src1,load_src2;
|
wire [56:0] sub1,sub2,sub3;
|
wire [56:0] sub1,sub2,sub3;
|
wire [32:0] src_1;
|
wire [32:0] src_1;
|
wire [20:0] man_1;
|
wire [20:0] man_1;
|
wire [12:0] expoh,expol,offset;
|
wire [12:0] expoh,expol,offset;
|
wire restlsb,restlow,resthigh;
|
wire restlsb,restlow,resthigh;
|
wire zero,nan,sign,ende;
|
wire zero,nan,sign,ende;
|
wire orlow_s,orlow_d;
|
wire orlow_s,orlow_d;
|
wire short;
|
wire short;
|
|
|
// +++++++++++++++++++++++++++ Integer Division, DEI +++++++++++++++++++++++++++
|
// +++++++++++++++++++++++++++ Integer Division, DEI +++++++++++++++++++++++++++
|
|
|
assign not_dei = OPCODE[2]; // 0 = DEI
|
assign not_dei = OPCODE[2]; // 0 = DEI
|
always @(posedge BCLK) if (START[3]) extdata <= ~START[1]; // during START[0] for SRC1 not valid
|
always @(posedge BCLK) if (START[3]) extdata <= ~START[1]; // during START[0] for SRC1 not valid
|
|
|
always @(posedge BCLK or negedge BRST)
|
always @(posedge BCLK or negedge BRST)
|
if (!BRST) run_divi <= 1'b0;
|
if (!BRST) run_divi <= 1'b0;
|
else
|
else
|
run_divi <= (START[3] & ~ist_null) | (~divi_pipe4 & run_divi); // Abort at DVZ Trap
|
run_divi <= (START[3] & ~ist_null) | (~divi_pipe4 & run_divi); // Abort at DVZ Trap
|
|
|
always @(posedge BCLK) divi_pipe1 <= START[3] & ~ist_null; // no start if SRC1 = 0 : DVZ Trap
|
always @(posedge BCLK) divi_pipe1 <= START[3] & ~ist_null; // no start if SRC1 = 0 : DVZ Trap
|
always @(posedge BCLK) dei_pipe <= divi_pipe1 & extdata;
|
always @(posedge BCLK) dei_pipe <= divi_pipe1 & extdata;
|
always @(posedge BCLK) divi_pipe2 <= extdata ? dei_pipe : divi_pipe1;
|
always @(posedge BCLK) divi_pipe2 <= extdata ? dei_pipe : divi_pipe1;
|
|
|
always @(posedge BCLK) src2_reg <= SRC2;
|
always @(posedge BCLK) src2_reg <= SRC2;
|
|
|
always @(posedge BCLK) sel_in <= START[3] | divi_pipe1; // two times data for DEI
|
always @(posedge BCLK) sel_in <= START[3] | divi_pipe1; // two times data for DEI
|
assign i_in = sel_in ? src2_reg : SRC1;
|
assign i_in = sel_in ? src2_reg : SRC1;
|
|
|
DIVI_PREP prep_inst ( .SRC(i_in), .BWD(BWD), .NOT_DEI(not_dei), .EXTDATA(extdata | START[0]),
|
DIVI_PREP prep_inst ( .SRC(i_in), .BWD(BWD), .NOT_DEI(not_dei), .EXTDATA(extdata | START[0]),
|
.DOUT(i_out[31:0]), .MSB(i_out[36:32]), .NULL(ist_null), .MINUS(i_out[37]) );
|
.DOUT(i_out[31:0]), .MSB(i_out[36:32]), .NULL(ist_null), .MINUS(i_out[37]) );
|
|
|
always @(posedge BCLK) dvz_pipe <= START[3] & ist_null; // Pulse 1 cycle long
|
always @(posedge BCLK) dvz_pipe <= START[3] & ist_null; // Pulse 1 cycle long
|
always @(posedge BCLK) DVZ_TRAP <= dvz_pipe; // one cycle later if DEI with extdata
|
always @(posedge BCLK) DVZ_TRAP <= dvz_pipe; // one cycle later if DEI with extdata
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (START[3])
|
if (START[3])
|
begin
|
begin
|
neg_src1 <= i_out[37];
|
neg_src1 <= i_out[37];
|
msb_src1 <= i_out[36:32];
|
msb_src1 <= i_out[36:32];
|
end
|
end
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (divi_pipe1)
|
if (divi_pipe1)
|
begin
|
begin
|
nul_src2 <= ist_null;
|
nul_src2 <= ist_null;
|
neg_src2 <= i_out[37];
|
neg_src2 <= i_out[37];
|
end
|
end
|
|
|
always @(posedge BCLK) ivalue <= i_out[31:0];
|
always @(posedge BCLK) ivalue <= i_out[31:0];
|
|
|
// The following is only for DEI :
|
// The following is only for DEI :
|
always @(posedge BCLK) pipe_reg <= {32{extdata}} & ivalue; // Register must be 0 if not used
|
always @(posedge BCLK) pipe_reg <= {32{extdata}} & ivalue; // Register must be 0 if not used
|
|
|
assign valdata = extdata & ~ist_null;
|
assign valdata = extdata & ~ist_null;
|
always @(BWD or valdata)
|
always @(BWD or valdata)
|
casex (BWD)
|
casex (BWD)
|
2'b00 : addoff = { 1'b0, 1'b0,valdata};
|
2'b00 : addoff = { 1'b0, 1'b0,valdata};
|
2'b01 : addoff = { 1'b0,valdata, 1'b0};
|
2'b01 : addoff = { 1'b0,valdata, 1'b0};
|
default : addoff = {valdata, 1'b0, 1'b0};
|
default : addoff = {valdata, 1'b0, 1'b0};
|
endcase
|
endcase
|
|
|
always @(posedge BCLK) next_msb2 <= extdata & ist_null & divi_pipe1; // Special case at DEI : MSD = 0
|
always @(posedge BCLK) next_msb2 <= extdata & ist_null & divi_pipe1; // Special case at DEI : MSD = 0
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (divi_pipe1) msb_src2 <= {addoff[2],(addoff[1:0] | i_out[36:35]),i_out[34:32]};
|
if (divi_pipe1) msb_src2 <= {addoff[2],(addoff[1:0] | i_out[36:35]),i_out[34:32]};
|
else
|
else
|
if (next_msb2) msb_src2 <= {1'b0,i_out[36:32]};
|
if (next_msb2) msb_src2 <= {1'b0,i_out[36:32]};
|
|
|
// Shifter for Source2
|
// Shifter for Source2
|
|
|
assign diff_msb = {1'b0,msb_src2} - {2'b0,msb_src1};
|
assign diff_msb = {1'b0,msb_src2} - {2'b0,msb_src1};
|
|
|
// negativ shift limited to 0 : Source2=0 calculated without special handling, result always 0
|
// negativ shift limited to 0 : Source2=0 calculated without special handling, result always 0
|
assign shift_r = diff_msb[6] ? 5'd0 : diff_msb[5:1]; // LSB does not count
|
assign shift_r = diff_msb[6] ? 5'd0 : diff_msb[5:1]; // LSB does not count
|
|
|
always @(BWD or extdata or ivalue or pipe_reg)
|
always @(BWD or extdata or ivalue or pipe_reg)
|
casex ({BWD,extdata})
|
casex ({BWD,extdata})
|
3'b0x0 : din_mux = {31'b0,ivalue}; // the normal case for all except DEI
|
3'b0x0 : din_mux = {31'b0,ivalue}; // the normal case for all except DEI
|
3'b001 : din_mux = {23'b0,pipe_reg,ivalue[7:0]};
|
3'b001 : din_mux = {23'b0,pipe_reg,ivalue[7:0]};
|
3'b011 : din_mux = {15'b0,pipe_reg,ivalue[15:0]};
|
3'b011 : din_mux = {15'b0,pipe_reg,ivalue[15:0]};
|
default : din_mux = {pipe_reg[30:0],ivalue}; // 63 Bit wide
|
default : din_mux = {pipe_reg[30:0],ivalue}; // 63 Bit wide
|
endcase
|
endcase
|
|
|
assign shift_2 = shift_r[1] ? din_mux : {din_mux[60:0], 2'b0};
|
assign shift_2 = shift_r[1] ? din_mux : {din_mux[60:0], 2'b0};
|
assign shift_4 = shift_r[2] ? shift_2 : {shift_2[58:0], 4'b0};
|
assign shift_4 = shift_r[2] ? shift_2 : {shift_2[58:0], 4'b0};
|
assign shift_8 = shift_r[3] ? shift_4 : {shift_4[54:0], 8'b0};
|
assign shift_8 = shift_r[3] ? shift_4 : {shift_4[54:0], 8'b0};
|
assign shift_16 = shift_r[4] ? shift_8 : {shift_8[46:0],16'b0}; // Result is 63 Bit wide
|
assign shift_16 = shift_r[4] ? shift_8 : {shift_8[46:0],16'b0}; // Result is 63 Bit wide
|
|
|
// 65 Bit result because of DEI
|
// 65 Bit result because of DEI
|
assign shift_32 = shift_r[5] ? {1'b0,pipe_reg,ivalue} : {shift_16,2'b00}; // special case DEI : 32 times shift
|
assign shift_32 = shift_r[5] ? {1'b0,pipe_reg,ivalue} : {shift_16,2'b00}; // special case DEI : 32 times shift
|
|
|
always @(posedge BCLK or negedge BRST) // Flag for rounding, only if DEST <>0
|
always @(posedge BCLK or negedge BRST) // Flag for rounding, only if DEST <>0
|
if (!BRST) divi_pipe3 <= 1'b0;
|
if (!BRST) divi_pipe3 <= 1'b0;
|
else
|
else
|
divi_pipe3 <= divi_pipe2 | (divi_pipe3 & ~stop_divi);
|
divi_pipe3 <= divi_pipe2 | (divi_pipe3 & ~stop_divi);
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (divi_pipe2) divi_counter <= shift_r;
|
if (divi_pipe2) divi_counter <= shift_r;
|
else divi_counter <= divi_counter - {4'b000,~stop_divi}; // should stop at 0
|
else divi_counter <= divi_counter - {4'b000,~stop_divi}; // should stop at 0
|
|
|
assign stop_divi = (divi_counter == 5'h0); // caclulation ready
|
assign stop_divi = (divi_counter == 5'h0); // caclulation ready
|
|
|
always @(posedge BCLK) divi_pipe4 <= divi_pipe3 & stop_divi;
|
always @(posedge BCLK) divi_pipe4 <= divi_pipe3 & stop_divi;
|
|
|
assign neg_flag = neg_src1 ^ neg_src2;
|
assign neg_flag = neg_src1 ^ neg_src2;
|
assign rest_null = (divreg[33:2] == 32'h0);
|
assign rest_null = (divreg[33:2] == 32'h0);
|
|
|
always @(posedge BCLK) sub_case <= neg_flag & ~nul_src2; // little help for MODi opcode
|
always @(posedge BCLK) sub_case <= neg_flag & ~nul_src2; // little help for MODi opcode
|
|
|
// Result preparation :
|
// Result preparation :
|
// DEST SRC QUO REM / DIV MOD
|
// DEST SRC QUO REM / DIV MOD
|
// +33 +13 : 2 7 / 2 7
|
// +33 +13 : 2 7 / 2 7
|
// +33 -13 : -2 7 / -3 -6
|
// +33 -13 : -2 7 / -3 -6
|
// -33 +13 : -2 -7 / -3 6
|
// -33 +13 : -2 -7 / -3 6
|
// -33 -13 : 2 -7 / 2 -7
|
// -33 -13 : 2 -7 / 2 -7
|
always @(*)
|
always @(*)
|
case (OPCODE[1:0])
|
case (OPCODE[1:0])
|
2'b00 : divi_result = {neg_flag,divsr[31:0]}; // QUO
|
2'b00 : divi_result = {neg_flag,divsr[31:0]}; // QUO
|
2'b01 : divi_result = {neg_src2,divreg[33:2]}; // REM
|
2'b01 : divi_result = {neg_src2,divreg[33:2]}; // REM
|
2'b10 : divi_result = {neg_src1,((sub_case & ~rest_null) ? (save1[31:0] - divreg[33:2]) : divreg[33:2])}; // MOD
|
2'b10 : divi_result = {neg_src1,((sub_case & ~rest_null) ? (save1[31:0] - divreg[33:2]) : divreg[33:2])}; // MOD
|
2'b11 : divi_result = {neg_flag,divsr[31:0]}; // DIV
|
2'b11 : divi_result = {neg_flag,divsr[31:0]}; // DIV
|
endcase
|
endcase
|
|
|
always @(posedge BCLK) negativ <= divi_result[32];
|
always @(posedge BCLK) negativ <= divi_result[32];
|
|
|
assign plus_1 = (OPCODE[1:0] == 2'b11) ? (negativ & rest_null) : negativ; // Special case Rest=0 at DIV
|
assign plus_1 = (OPCODE[1:0] == 2'b11) ? (negativ & rest_null) : negativ; // Special case Rest=0 at DIV
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (divi_pipe4) DIVI_OUT[63:32] <= not_dei ? (({32{negativ}} ^ divi_result[31:0]) + {31'd0,plus_1}) : dei_result;
|
if (divi_pipe4) DIVI_OUT[63:32] <= not_dei ? (({32{negativ}} ^ divi_result[31:0]) + {31'd0,plus_1}) : dei_result;
|
|
|
always @(posedge BCLK) if (divi_pipe4) DIVI_OUT[31:0] <= divreg[33:2];
|
always @(posedge BCLK) if (divi_pipe4) DIVI_OUT[31:0] <= divreg[33:2];
|
|
|
always @(extdata or BWD or divsr or divreg)
|
always @(extdata or BWD or divsr or divreg)
|
casex ({extdata,BWD})
|
casex ({extdata,BWD})
|
3'b000 : dei_result = {16'hxxxx,divsr[7:0],divreg[9:2]};
|
3'b000 : dei_result = {16'hxxxx,divsr[7:0],divreg[9:2]};
|
3'b001 : dei_result = {divsr[15:0],divreg[17:2]};
|
3'b001 : dei_result = {divsr[15:0],divreg[17:2]};
|
default : dei_result = divsr[31:0];
|
default : dei_result = divsr[31:0];
|
endcase
|
endcase
|
|
|
// +++++++++++++++++++++++++++ Calculation path for Division ++++++++++++++++++++++++++++
|
// +++++++++++++++++++++++++++ Calculation path for Division ++++++++++++++++++++++++++++
|
|
|
always @(posedge BCLK or negedge BRST)
|
always @(posedge BCLK or negedge BRST)
|
if (!BRST) runflag <= 1'b0;
|
if (!BRST) runflag <= 1'b0;
|
else
|
else
|
runflag <= START[2] | (~ende & runflag);
|
runflag <= START[2] | (~ende & runflag);
|
|
|
always @(posedge BCLK) DONE <= (ende & runflag) | divi_pipe4;
|
always @(posedge BCLK) DONE <= (ende & runflag) | divi_pipe4;
|
|
|
assign man_1 = (FL | run_divi) ? 21'h0 : MAN1;
|
assign man_1 = (FL | run_divi) ? 21'h0 : MAN1;
|
assign src_1 = run_divi ? {1'b0,ivalue} : ( FL ? {10'h001,SRC1[22:0]} : {SRC1,1'b0});
|
assign src_1 = run_divi ? {1'b0,ivalue} : ( FL ? {10'h001,SRC1[22:0]} : {SRC1,1'b0});
|
|
|
assign load_src1 = START[2] | divi_pipe1;
|
assign load_src1 = START[2] | divi_pipe1;
|
|
|
// *2 + *1
|
// *2 + *1
|
always @(posedge BCLK) if (load_src1) dreimal <= {1'b0,man_1,src_1,1'b0} + {2'b00,man_1,src_1}; // 54 Bit Reg
|
always @(posedge BCLK) if (load_src1) dreimal <= {1'b0,man_1,src_1,1'b0} + {2'b00,man_1,src_1}; // 54 Bit Reg
|
|
|
always @(posedge BCLK) if (load_src1) save1 <= src_1;
|
always @(posedge BCLK) if (load_src1) save1 <= src_1;
|
|
|
assign sub1 = divreg - {3'b000, man_1,save1 };
|
assign sub1 = divreg - {3'b000, man_1,save1 };
|
assign sub2 = divreg - {2'b00 ,man_1,save1,1'b0};
|
assign sub2 = divreg - {2'b00 ,man_1,save1,1'b0};
|
assign sub3 = divreg - {1'b0, dreimal };
|
assign sub3 = divreg - {1'b0, dreimal };
|
|
|
assign load_src2 = START[2] | divi_pipe2;
|
assign load_src2 = START[2] | divi_pipe2;
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (load_src2) divreg <= divi_pipe2 ? {23'h0,shift_32[64:32]} : ( FL ? {34'h0_0000_0001,SRC2[22:0]} : {3'b0,MAN2,SRC2,1'b0});
|
if (load_src2) divreg <= divi_pipe2 ? {23'h0,shift_32[64:32]} : ( FL ? {34'h0_0000_0001,SRC2[22:0]} : {3'b0,MAN2,SRC2,1'b0});
|
else
|
else
|
begin
|
begin
|
casex ({sub3[56],sub2[56],sub1[56]})
|
casex ({sub3[56],sub2[56],sub1[56]})
|
3'b0xx : divreg <= {sub3[54:0],divreg_ext[31:30]};
|
3'b0xx : divreg <= {sub3[54:0],divreg_ext[31:30]};
|
3'b10x : divreg <= {sub2[54:0],divreg_ext[31:30]};
|
3'b10x : divreg <= {sub2[54:0],divreg_ext[31:30]};
|
3'b110 : divreg <= {sub1[54:0],divreg_ext[31:30]};
|
3'b110 : divreg <= {sub1[54:0],divreg_ext[31:30]};
|
default : divreg <= {divreg[54:0],divreg_ext[31:30]};
|
default : divreg <= {divreg[54:0],divreg_ext[31:30]};
|
endcase
|
endcase
|
end
|
end
|
|
|
always @(posedge BCLK) // Extension Register for Integer Division
|
always @(posedge BCLK) // Extension Register for Integer Division
|
if (load_src2) divreg_ext <= divi_pipe2 ? shift_32[31:0] : 32'd0;
|
if (load_src2) divreg_ext <= divi_pipe2 ? shift_32[31:0] : 32'd0;
|
else
|
else
|
divreg_ext <= {divreg_ext[29:0],2'b0};
|
divreg_ext <= {divreg_ext[29:0],2'b0};
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (load_src2) divsr <= 57'h0;
|
if (load_src2) divsr <= 57'h0;
|
else
|
else
|
begin
|
begin
|
casex ({sub3[56],sub2[56],sub1[56]})
|
casex ({sub3[56],sub2[56],sub1[56]})
|
3'b0xx : divsr <= {divsr[54:0],2'b11};
|
3'b0xx : divsr <= {divsr[54:0],2'b11};
|
3'b10x : divsr <= {divsr[54:0],2'b10};
|
3'b10x : divsr <= {divsr[54:0],2'b10};
|
3'b110 : divsr <= {divsr[54:0],2'b01};
|
3'b110 : divsr <= {divsr[54:0],2'b01};
|
default : divsr <= {divsr[54:0],2'b00};
|
default : divsr <= {divsr[54:0],2'b00};
|
endcase
|
endcase
|
end
|
end
|
|
|
// Overflow Detection for DEI : serial calculation
|
// Overflow Detection for DEI : serial calculation
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (load_src2) DEI_OVF[0] <= 1'b0;
|
if (load_src2) DEI_OVF[0] <= 1'b0;
|
else DEI_OVF[0] <= DEI_OVF[0] | (BWD[1] ? |divsr[33:32] : (BWD[0] ? |divsr[17:16] : |divsr[9:8]));
|
else DEI_OVF[0] <= DEI_OVF[0] | (BWD[1] ? |divsr[33:32] : (BWD[0] ? |divsr[17:16] : |divsr[9:8]));
|
|
|
always @(posedge BCLK) DEI_OVF[1] <= divi_pipe4; // Timing pulse for OVF inclusiv for DIV and QUO
|
always @(posedge BCLK) DEI_OVF[1] <= divi_pipe4; // Timing pulse for OVF inclusiv for DIV and QUO
|
|
|
assign short = (SRCFLAGS[3:0] != 4'h0) & runflag;
|
assign short = (SRCFLAGS[3:0] != 4'h0) & runflag;
|
|
|
assign ende = ((FL ? (divsr[26] | divsr[25]) : (divsr[56] | divsr[55])) & runflag) | short;
|
assign ende = ((FL ? (divsr[26] | divsr[25]) : (divsr[56] | divsr[55])) & runflag) | short;
|
|
|
assign sign = (SRCFLAGS[4] ^ SRCFLAGS[5]) & ~zero;
|
assign sign = (SRCFLAGS[4] ^ SRCFLAGS[5]) & ~zero;
|
assign zero = SRCFLAGS[2] & ~SRCFLAGS[0]; // SRC2 = NULL -> NULL as result
|
assign zero = SRCFLAGS[2] & ~SRCFLAGS[0]; // SRC2 = NULL -> NULL as result
|
assign nan = SRCFLAGS[3] | SRCFLAGS[1] | (SRCFLAGS[2] & SRCFLAGS[0]);
|
assign nan = SRCFLAGS[3] | SRCFLAGS[1] | (SRCFLAGS[2] & SRCFLAGS[0]);
|
// one of both NAN or both 0 -> invalid Operation
|
// one of both NAN or both 0 -> invalid Operation
|
|
|
assign orlow_d = (divreg[56:27] != 29'b0) & ~zero & ~FL; // is there Rest ? [1:0] are always 0.
|
assign orlow_d = (divreg[56:27] != 29'b0) & ~zero & ~FL; // is there Rest ? [1:0] are always 0.
|
assign orlow_s = (divreg[26:2] != 25'b0) & ~zero;
|
assign orlow_s = (divreg[26:2] != 25'b0) & ~zero;
|
|
|
assign restlsb = divsr[0] | orlow_s;
|
assign restlsb = divsr[0] | orlow_s;
|
assign restlow = (divsr[1:0] != 2'b00) | orlow_s | orlow_d;
|
assign restlow = (divsr[1:0] != 2'b00) | orlow_s | orlow_d;
|
assign resthigh = divsr[2] | restlow;
|
assign resthigh = divsr[2] | restlow;
|
|
|
always @(posedge BCLK) if (START[0]) exponent <= FL ? ({5'b00,SRC2[30:23]} - {5'b00,SRC1[30:23]})
|
always @(posedge BCLK) if (START[0]) exponent <= FL ? ({5'b00,SRC2[30:23]} - {5'b00,SRC1[30:23]})
|
: ({2'b00,SRC2[30:20]} - {2'b00,SRC1[30:20]});
|
: ({2'b00,SRC2[30:20]} - {2'b00,SRC1[30:20]});
|
assign offset = FL ? 13'h007E : 13'h03FE;
|
assign offset = FL ? 13'h007E : 13'h03FE;
|
assign expoh = exponent + {offset[12:1],1'b1}; // Double = 3FF/3FE Single = 7F/7E
|
assign expoh = exponent + {offset[12:1],1'b1}; // Double = 3FF/3FE Single = 7F/7E
|
assign expol = exponent + offset; // in case of normalizing
|
assign expol = exponent + offset; // in case of normalizing
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (ende && runflag)
|
if (ende && runflag)
|
casex ({FL,divsr[26],divsr[56]})
|
casex ({FL,divsr[26],divsr[56]})
|
3'b11x : OUT <= {nan,zero,sign,expoh[9:8],expoh[7],expoh[7],expoh[7],expoh[7:0],divsr[25:3],28'b0,divsr[3:2],restlow};
|
3'b11x : OUT <= {nan,zero,sign,expoh[9:8],expoh[7],expoh[7],expoh[7],expoh[7:0],divsr[25:3],28'b0,divsr[3:2],restlow};
|
3'b10x : OUT <= {nan,zero,sign,expol[9:8],expol[7],expol[7],expol[7],expol[7:0],divsr[24:2],28'b0,divsr[2:1],restlsb};
|
3'b10x : OUT <= {nan,zero,sign,expol[9:8],expol[7],expol[7],expol[7],expol[7:0],divsr[24:2],28'b0,divsr[2:1],restlsb};
|
3'b0x1 : OUT <= {nan,zero,sign,expoh,divsr[55:3],resthigh};
|
3'b0x1 : OUT <= {nan,zero,sign,expoh,divsr[55:3],resthigh};
|
3'b0x0 : OUT <= {nan,zero,sign,expol,divsr[54:2],restlow};
|
3'b0x0 : OUT <= {nan,zero,sign,expol,divsr[54:2],restlow};
|
endcase
|
endcase
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 9. DP_LOGIK Control logic and result path for different functions
|
// 10. DP_LOGIK Control logic and result path for different functions
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DP_LOGIK ( BCLK, BRESET, OPCODE, SRC1, SRC2, FSR, START, MRESULT, BWD, FL, MAN1, MAN2, WR_REG, CY_IN,
|
module DP_LOGIK ( BCLK, BRESET, OPCODE, SRC1, SRC2, FSR, START, MRESULT, BWD, FL, MAN1, MAN2, WR_REG, CY_IN,
|
COP_DONE, COP_OP, COP_IN,
|
COP_DONE, COP_OP, COP_IN,
|
DOUT, TT_DP, DP_CMP, OVF_BCD, MEI, DFLOAT, DONE, UP_DP, CLR_LSB, WREN_L, LD_OUT_L, DVZ_TRAP, COP_GO );
|
DOUT, TT_DP, DP_CMP, OVF_BCD, MEI, DFLOAT, DONE, UP_DP, CLR_LSB, WREN_L, DVZ_TRAP, COP_GO );
|
|
|
// Definition of output word OUT of sub-moduls : the hidden-bit of the mantissa is already gone
|
// Definition of output word OUT of sub-moduls : the hidden-bit of the mantissa is already gone
|
//
|
//
|
// N Z S Exponent Mantissa Round
|
// N Z S Exponent Mantissa Round
|
// A E I Double : 13 Bit 52 Bit 2 Bit
|
// A E I Double : 13 Bit 52 Bit 2 Bit
|
// N R G Single : 10 Bit 23 Bit 2 Bit
|
// N R G Single : 10 Bit 23 Bit 2 Bit
|
// O N -mmmm.mmmm.mmmm.mmmm.mmmm.mmm-.-- -m.
|
// O N -mmmm.mmmm.mmmm.mmmm.mmmm.mmm-.-- -m.
|
// -F-F-F-E.EEEE.EEEE.EEEE-MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.RR
|
// -F-F-F-E.EEEE.EEEE.EEEE-MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.MMMM.RR
|
//
|
//
|
// 6 6 6 6 6666 6655 5555 5555 4444 4444 4433 3333 3333 2222 2222 2211 1111 1111 0000 0000 00
|
// 6 6 6 6 6666 6655 5555 5555 4444 4444 4433 3333 3333 2222 2222 2211 1111 1111 0000 0000 00
|
// 9 8 7 6 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 10
|
// 9 8 7 6 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 1098 7654 3210 9876 5432 10
|
//
|
//
|
// Single FP delivers the exponent in a way, that it is identical for rounding :
|
// Single FP delivers the exponent in a way, that it is identical for rounding :
|
//
|
//
|
// Exponent 61 - 54 => kept
|
// Exponent 61 - 54 => kept
|
// Bits 64 - 62 are filled with bit 61 , carry should come through
|
// Bits 64 - 62 are filled with bit 61 , carry should come through
|
// Exponent 62 => Bit 65 , Overflow
|
// Exponent 62 => Bit 65 , Overflow
|
// Exponent 63 => Bit 66 , Underflow
|
// Exponent 63 => Bit 66 , Underflow
|
|
|
input BCLK,BRESET;
|
input BCLK,BRESET;
|
input [7:0] OPCODE;
|
input [7:0] OPCODE;
|
input [31:0] SRC1,SRC2; // the input data
|
input [31:0] SRC1,SRC2; // the input data
|
input [20:0] MAN1,MAN2; // the MSB of mantissa
|
input [20:0] MAN1,MAN2; // the MSB of mantissa
|
input [8:3] FSR; // Floating Point Status Register
|
input [8:3] FSR; // Floating Point Status Register
|
input [1:0] START;
|
input [1:0] START;
|
input [105:0] MRESULT; // Result of multiplier
|
input [105:0] MRESULT; // Result of multiplier
|
input [1:0] BWD; // Size of integer
|
input [1:0] BWD; // Size of integer
|
input FL;
|
input FL;
|
input WR_REG; // from DECODER
|
input WR_REG; // from DECODER
|
input CY_IN;
|
input CY_IN;
|
input COP_DONE; // Coprozessor Interface
|
input COP_DONE; // Coprozessor Interface
|
input [23:0] COP_OP;
|
input [23:0] COP_OP;
|
input [63:0] COP_IN;
|
input [63:0] COP_IN;
|
|
|
output [63:0] DOUT;
|
output [63:0] DOUT;
|
output [4:0] TT_DP; // Trap-Info to FSR
|
output [4:0] TT_DP; // Trap-Info to FSR
|
output [2:0] DP_CMP; // CMPL result
|
output [2:0] DP_CMP; // CMPL result
|
output [3:0] OVF_BCD; // Integer Division Overflow + BCD Carry update
|
output [3:0] OVF_BCD; // Integer Division Overflow + BCD Carry update
|
output MEI,DFLOAT;
|
output MEI,DFLOAT;
|
output DONE,UP_DP;
|
output DONE,UP_DP,WREN_L;
|
output CLR_LSB,WREN_L,LD_OUT_L;
|
output reg CLR_LSB;
|
output DVZ_TRAP;
|
output DVZ_TRAP;
|
output reg COP_GO;
|
output reg COP_GO;
|
|
|
reg [63:0] DOUT;
|
reg [63:0] DOUT;
|
reg CLR_LSB;
|
|
reg [2:0] DP_CMP;
|
reg [2:0] DP_CMP;
|
reg [5:0] preflags;
|
reg [5:0] preflags;
|
reg [5:0] srcflags;
|
reg [5:0] srcflags;
|
reg [69:0] fpout;
|
reg [69:0] fpout;
|
reg [2:0] tt;
|
reg [2:0] tt;
|
reg [6:0] select;
|
reg [7:0] select;
|
reg [4:0] wctrl;
|
reg [5:0] wctrl;
|
reg [2:1] sequ;
|
reg [2:1] sequ;
|
reg misc_op;
|
reg misc_op;
|
reg misc_mux;
|
|
reg car_ry;
|
reg car_ry;
|
reg wr_part2;
|
reg wr_part2;
|
reg up_flag;
|
reg up_flag;
|
reg ovf_div;
|
reg ovf_div;
|
|
reg late_bcd_done;
|
|
|
wire zexp2,zman2,zexp1,zman1,znan1;
|
wire zexp2,zman2,zexp1,zman1,znan1;
|
wire make_i;
|
wire make_i;
|
wire scalbl,go_misc;
|
|
wire op_cmp;
|
wire op_cmp;
|
wire [69:0] mulout,addout,divout,miscout;
|
wire [69:0] mulout,addout,divout,miscout;
|
wire go_divf,go_divi,divi_ops,div_done;
|
wire go_divf,go_divi,divi_ops,div_done;
|
wire bcd_ops,man_ops;
|
wire bcd_ops,man_ops;
|
wire [31:0] i_out;
|
wire [31:0] i_out;
|
wire [63:0] divi_out;
|
wire [63:0] divi_out;
|
wire [66:2] rund,cy_val; // Indexnumber like in xxxout
|
wire [66:2] rund,cy_val; // Indexnumber like in xxxout
|
wire div_zero,overflow,underflow,inexact;
|
wire div_zero,overflow,underflow,inexact;
|
wire [1:0] cmpres;
|
wire [1:0] cmpres;
|
wire [63:0] fp_out,fp_res;
|
wire [63:0] fp_out,fp_res;
|
wire wr_part1;
|
wire wr_part1;
|
wire done_i;
|
wire done_i;
|
|
wire later;
|
wire [31:0] bcd_q;
|
wire [31:0] bcd_q;
|
wire bcd_done;
|
wire bcd_done;
|
wire bcd_carry;
|
wire bcd_carry;
|
wire [1:0] dei_ovf;
|
wire [1:0] dei_ovf;
|
wire quo_div;
|
wire quo_div;
|
wire copop;
|
wire copop;
|
wire copwr;
|
wire copwr;
|
|
|
// Control of datapath : together with START the Double Unit becomes activ
|
// Control of datapath : together with START the Double Unit becomes activ
|
|
|
always @(OPCODE or FL)
|
always @(OPCODE or FL)
|
casex (OPCODE)
|
casex (OPCODE)
|
8'b1001_000x : select = 7'b00_01010; // 0 1 0 : MOViL
|
8'b1001_000x : select = {5'b0000_0, ~FL ,2'b10}; // 0 1 0 : MOViL
|
8'b1001_010x : select = 7'b10_11000; // MOVLF
|
8'b1001_010x : select = {5'b0001_1, 1'b1,2'b00}; // MOVLF
|
8'b1001_011x : select = 7'b01_11000; // MOVFL
|
8'b1001_011x : select = {5'b0011_1, 1'b1,2'b00}; // MOVFL
|
8'b1001_100x : select = 7'b10_01011; // 0 1 1 : ROUNDLi
|
8'b1001_100x : select = {5'b0001_0, ~FL ,2'b11}; // 0 1 1 : ROUNDLi
|
8'b1001_101x : select = 7'b10_01011; // 0 1 1 : TRUNCLi
|
8'b1001_101x : select = {5'b0001_0, ~FL ,2'b11}; // 0 1 1 : TRUNCLi
|
8'b1001_111x : select = 7'b10_01011; // 0 1 1 : FLOORLi
|
8'b1001_111x : select = {5'b0001_0, ~FL ,2'b11}; // 0 1 1 : FLOORLi
|
8'b1011_0000 : select = 7'bxx_01000; // 0 0 0 : ADDL
|
8'b1011_0000 : select = {5'b1010_0, ~FL ,2'b00}; // 0 0 0 : ADDL Es werden Shifter wiederverwendet...
|
8'b1011_0010 : select = 7'bxx_01001; // 0 0 1 : CMPL
|
8'b1011_0010 : select = {5'b1010_0, ~FL ,2'b01}; // 0 0 1 : CMPL
|
8'b1011_0100 : select = 7'bxx_01001; // 0 0 1 : SUBL
|
8'b1011_0100 : select = {5'b1010_0, ~FL ,2'b01}; // 0 0 1 : SUBL
|
8'b1011_1000 : select = 7'b11_01100; // 1 0 1 : DIVf , Default Float for srcflags
|
8'b1011_1000 : select = {1'b1,FL,1'b1,FL,1'b0,1'b1,2'b00}; // 1 0 1 : DIVf , Default Float fuer srcflags
|
8'b1011_1100 : select = 7'bxx_01100; // 1 0 0 : MULL
|
8'b1011_1100 : select = {5'b1010_0, ~FL ,2'b00}; // 1 0 0 : MULL
|
8'b1011_0110 : select = 7'b11_11000; // SCALBf , Default Float for srcflags
|
8'b1011_0110 : select = {1'b1,FL,1'b1,FL,1'b1,1'b1,2'b00}; // SCALBf
|
8'b1011_0111 : select = {~FL,FL,5'b11000}; // LOGBf
|
8'b1011_0111 : select = {2'b00,FL,2'b1_1, 1'b1,2'b00}; // LOGBf
|
default : select = 7'b0;
|
default : select = 8'b0;
|
endcase
|
endcase
|
|
|
assign MEI = (OPCODE == 8'h79);
|
assign MEI = (OPCODE == 8'h79);
|
assign divi_ops = (OPCODE[7:2] == 6'b0111_11) | (OPCODE == 8'h7B); // QUO/REM/MOD/DIV & DEI
|
assign divi_ops = (OPCODE[7:2] == 6'b0111_11) | (OPCODE == 8'h7B); // QUO/REM/MOD/DIV & DEI
|
assign go_divf = (OPCODE == 8'hB8) & START[1]; // because of runflag in DIV Unit
|
assign go_divf = (OPCODE == 8'hB8) & START[1]; // because of runflag in DIV Unit
|
assign go_divi = divi_ops & (OPCODE[2] ? START[1] : START[0]); // DEI starts with START[0]
|
assign go_divi = divi_ops & (OPCODE[2] ? START[1] : START[0]); // DEI starts with START[0]
|
assign bcd_ops = (OPCODE == 8'h6F) | (OPCODE == 8'h6B); // ADDP , SUBP
|
assign bcd_ops = (OPCODE == 8'h71) | (OPCODE == 8'h70); // ADDP , SUBP
|
|
|
assign man_ops = (OPCODE == 8'hB1) | (OPCODE == 8'hB5) | (OPCODE == 8'hB9) | (OPCODE == 8'hBD); // MOVf,NEGf,XXXf,ABSf
|
assign man_ops = (OPCODE == 8'hB1) | (OPCODE == 8'hB5) | (OPCODE == 8'hB9) | (OPCODE == 8'hBD); // MOVf,NEGf,XXXf,ABSf
|
|
|
assign DFLOAT = (select[3] | copop) & ~FL; // all Double Floating Point Operations for PREPDATA
|
assign DFLOAT = (select[2] | copop) & ~FL; // all Double Floating Point Operations for PREPDATA
|
assign make_i = (select[2:0] == 3'b011) | divi_ops | bcd_ops; // ROUND/TRUNC/FLOOR for output multiplexer
|
assign make_i = (select[1:0] == 2'b11) | divi_ops | bcd_ops; // ROUND/TRUNC/FLOOR for output multiplexer
|
assign op_cmp = (OPCODE == 8'hB2) & ~FL;
|
assign op_cmp = (OPCODE == 8'hB2) & ~FL;
|
always @(posedge BCLK) misc_op <= select[4]; // for OUT-Multiplexer
|
always @(posedge BCLK) misc_op <= select[3]; // for OUT-Multiplexer
|
|
|
assign copop = (OPCODE == 8'hDD);
|
assign copop = (OPCODE == 8'hDD);
|
assign copwr = (COP_OP[18:17] == 2'd0) & (COP_OP[13:11] == 3'b111) & (COP_OP[7:5] == 3'b001); // Custom Convert
|
assign copwr = (COP_OP[18:17] == 2'd0) & (COP_OP[13:11] == 3'b111) & (COP_OP[7:5] == 3'b001); // Custom Convert
|
|
|
// very special solution for SCALBL
|
|
assign scalbl = START[0] & ~FL & (OPCODE == 8'hB6);
|
|
assign go_misc = START[1] | scalbl;
|
|
always @(posedge BCLK) misc_mux <= scalbl; // switches at START[1] the input multiplexer
|
|
|
|
// SRCFLAGS : special handling for operands is done locally
|
// SRCFLAGS : special handling for operands is done locally
|
|
|
assign zexp2 = (SRC2[30:20] == 11'd0);
|
assign zexp2 = (SRC2[30:20] == 11'd0);
|
assign zman2 = (SRC2[19:0] == 20'd0);
|
assign zman2 = (SRC2[19:0] == 20'd0);
|
assign zexp1 = (SRC1[30:20] == 11'd0);
|
assign zexp1 = (SRC1[30:20] == 11'd0);
|
assign zman1 = (SRC1[19:0] == 20'd0);
|
assign zman1 = (SRC1[19:0] == 20'd0);
|
assign znan1 = (SRC1[30:20] == 11'h7FF);
|
assign znan1 = (SRC1[30:20] == 11'h7FF);
|
|
|
always @(posedge BCLK)
|
always @(posedge BCLK)
|
if (START[0])
|
if (START[0])
|
begin
|
begin
|
srcflags[5] <= SRC2[31];
|
srcflags[5] <= SRC2[31];
|
srcflags[4] <= SRC1[31];
|
srcflags[4] <= SRC1[31];
|
preflags <= {(SRC2[30:20] == 11'h7FF),zexp2,zman2,znan1,zexp1,zman1};
|
preflags <= {(SRC2[30:20] == 11'h7FF),zexp2,zman2,znan1,zexp1,zman1};
|
end
|
end
|
|
|
// case Definition : 00 : 0 , if START[i]=0 then there are always 2 long operands
|
// case Definition : 00 : 0 , if START[i]=0 then there are always 2 long operands
|
// 01 : 1 Float Operand SCR1
|
// 01 : 1 Float Operand SCR1
|
// 10 : 1 Long Operand SRC1+SRC2
|
// 10 : 1 Long Operand SRC1+SRC2
|
// 11 : 2 Float Operands SRC1 , SRC2
|
// 11 : 2 Float Operands SRC1 , SRC2
|
|
|
always @(posedge BCLK) // NaN
|
always @(posedge BCLK) // NaN
|
if (START[1])
|
if (START[1])
|
casex ({START[0],select[6:5]})
|
case (select[7:6])
|
3'b0xx : srcflags[3] <= preflags[5] | (preflags[4] & (~preflags[3] | SRC2[31] | ~zexp2 | ~zman2));
|
2'b10 : srcflags[3] <= preflags[5] | (preflags[4] & (~preflags[3] | SRC2[31] | ~zexp2 | ~zman2));
|
3'b111 : srcflags[3] <= (SRC2[30:23] == 8'hFF) | ((SRC2[30:23] == 8'd0) & ((SRC2[22:20] != 3'd0) | ~zman2)); // F:SRC2 = NaN
|
2'b11 : srcflags[3] <= (SRC2[30:23] == 8'hFF) | ((SRC2[30:23] == 8'd0) & ((SRC2[22:20] != 3'd0) | ~zman2)); // F:SRC2 = NaN
|
default : srcflags[3] <= 1'b0;
|
default : srcflags[3] <= 1'b0;
|
endcase
|
endcase
|
|
|
always @(posedge BCLK) // Zero : only exponent ! If denormalized => NaN !
|
always @(posedge BCLK) // Zero : only exponent ! If denormalized => NaN !
|
if (START[0])
|
if (START[1])
|
casex ({START[1],select[6:5]})
|
case (select[7:6])
|
3'b0xx : srcflags[2] <= zexp2; // L:(SRC1,SRC2) = Zero , SRC1 = MSB
|
2'b10 : srcflags[2] <= preflags[4]; // L:SRC2 = Zero , 2*SRC2
|
3'b111 : srcflags[2] <= (SRC2[30:23] == 8'd0); // F:SRC2 = Zero
|
2'b11 : srcflags[2] <= (SRC2[30:23] == 8'd0); // F:SRC2 = Zero
|
default : srcflags[2] <= 1'b0;
|
default : srcflags[2] <= 1'b0;
|
endcase
|
endcase
|
|
|
always @(posedge BCLK) // NaN
|
always @(posedge BCLK) // NaN
|
if (START[1])
|
if (START[1])
|
casex ({START[0],select[6:5]})
|
case (select[5:4])
|
3'b0xx : srcflags[1] <= preflags[2] | (preflags[1] & (~preflags[0] | SRC1[31] | ~zexp1 | ~zman1));
|
2'b01 : srcflags[1] <= znan1 | (zexp1 & (~zman1 | SRC2[31] | ~zexp2 | ~zman2)); // L:(SRC1,SRC2) = NaN , SRC1 = MSB
|
3'b1x1 : srcflags[1] <= (SRC1[30:23] == 8'hFF) | ((SRC1[30:23] == 8'd0) & ((SRC1[22:20] != 3'd0) | ~zman1)); // F:SRC1 = NaN
|
2'b10 : srcflags[1] <= preflags[2] | (preflags[1] & (~preflags[0] | SRC1[31] | ~zexp1 | ~zman1));
|
3'b110 : srcflags[1] <= znan1 | (zexp1 & (~zman1 | SRC2[31] | ~zexp2 | ~zman2)); // L:(SRC1,SRC2) = NaN , SRC1 = MSB
|
2'b11 : srcflags[1] <= (SRC1[30:23] == 8'hFF) | ((SRC1[30:23] == 8'd0) & ((SRC1[22:20] != 3'd0) | ~zman1)); // F:SRC1 = NaN
|
default : srcflags[1] <= 1'b0;
|
default : srcflags[1] <= 1'b0;
|
endcase
|
endcase
|
|
|
always @(posedge BCLK) // Zero : only exponent ! If denormalized => NaN !
|
always @(posedge BCLK) // Zero : only exponent ! If denormalized => NaN !
|
if (START[0])
|
if (START[1])
|
casex ({START[1],select[6:5]})
|
case (select[5:4])
|
3'b0xx : srcflags[0] <= zexp1; // L:(SRC1,SRC2) = Zero , SRC1 = MSB
|
2'b01 : srcflags[0] <= zexp1; // L:(SRC1,SRC2) = Zero , SRC1 = MSB, Special Case ROUNDL,etc.
|
3'b1x1 : srcflags[0] <= (SRC1[30:23] == 8'd0); // F:SRC1 = Zero
|
2'b10 : srcflags[0] <= preflags[1]; // L:SRC1 = Zero , 2*SRC1
|
3'b110 : srcflags[0] <= zexp1; // L:(SRC1,SRC2) = Zero , SRC1 = MSB
|
2'b11 : srcflags[0] <= (SRC1[30:23] == 8'd0); // F:SRC1 = Zero
|
default : srcflags[0] <= 1'b0;
|
default : srcflags[0] <= 1'b0;
|
endcase
|
endcase
|
|
|
// The Sub-moduls :
|
// The Sub-moduls :
|
|
|
DFPU_ADDSUB as_inst ( .BCLK(BCLK), .START(START), .SRC1(SRC1), .SRC2(SRC2),
|
DFPU_ADDSUB as_inst ( .BCLK(BCLK), .START(START), .SRC1(SRC1), .SRC2(SRC2),
|
.MAN1({~srcflags[0],MAN1[19:0]}), .MAN2({~srcflags[2],MAN2[19:0]}),
|
.MAN1({~preflags[1],MAN1[19:0]}), .MAN2({~preflags[4],MAN2[19:0]}),
|
.SRCFLAGS(srcflags), .BWD(BWD), .SELECT({OPCODE[2:1],select[1:0]}),
|
.SRCFLAGS(srcflags), .BWD(BWD), .SELECT({OPCODE[2:1],select[1:0]}),
|
.OUT(addout), .IOUT(i_out), .CMPRES(cmpres) );
|
.OUT(addout), .IOUT(i_out), .CMPRES(cmpres) );
|
|
|
DFPU_MUL mul_inst ( .BCLK(BCLK), .SRC1(SRC1), .SRC2(SRC2), .START(START[0]), .MRESULT(MRESULT),
|
DFPU_MUL mul_inst ( .BCLK(BCLK), .SRC1(SRC1), .SRC2(SRC2), .START(START[0]), .MRESULT(MRESULT),
|
.OUT(mulout), .SRCFLAGS(srcflags) );
|
.OUT(mulout), .SRCFLAGS(srcflags) );
|
|
|
DFPU_DIV div_inst ( .BCLK(BCLK), .BRST(BRESET), .START({go_divi,go_divf,START}), .SRC1(SRC1), .SRC2(SRC2),
|
DFPU_DIV div_inst ( .BCLK(BCLK), .BRST(BRESET), .START({go_divi,go_divf,START}), .SRC1(SRC1), .SRC2(SRC2),
|
.MAN1(MAN1), .MAN2(MAN2), .SRCFLAGS(srcflags), .FL(FL), .OUT(divout), .DONE(div_done),
|
.MAN1(MAN1), .MAN2(MAN2), .SRCFLAGS(srcflags), .FL(FL), .OUT(divout), .DONE(div_done),
|
.BWD(BWD), .OPCODE(OPCODE[2:0]), .DIVI_OUT(divi_out), .DVZ_TRAP(DVZ_TRAP), .DEI_OVF(dei_ovf) );
|
.BWD(BWD), .OPCODE(OPCODE[2:0]), .DIVI_OUT(divi_out), .DVZ_TRAP(DVZ_TRAP), .DEI_OVF(dei_ovf) );
|
|
|
DFPU_MISC misc_inst ( .BCLK(BCLK), .START(go_misc), .SRC1(SRC1), .SRC2(SRC2), .SRCFLAG(srcflags[2]),
|
DFPU_MISC misc_inst ( .BCLK(BCLK), .START(START), .SRC1(SRC1), .SRC2(SRC2), .MAN2(MAN2[19:0]), .SRCFLAGS(srcflags),
|
.MIMUX(misc_mux), .MODE({OPCODE[5],OPCODE[0],FL,OPCODE[1]}), .OUT(miscout) );
|
.MODE({OPCODE[5],OPCODE[0],FL,OPCODE[1]}), .OUT(miscout) );
|
|
|
DFPU_BCD bcd_inst ( .BCLK(BCLK), .BRESET(BRESET), .START(START[1]), .DO_BCD(bcd_ops), .BWD(BWD), .SRC1(SRC1), .SRC2(SRC2),
|
DFPU_BCD bcd_inst ( .BCLK(BCLK), .BRESET(BRESET), .START(START[1]), .DO_BCD(bcd_ops), .BWD(BWD), .SRC1(SRC1), .SRC2(SRC2),
|
.CY_IN(CY_IN), .SUBP(~OPCODE[2]), .BCD_Q(bcd_q), .CY_OUT(bcd_carry), .BCD_DONE(bcd_done) );
|
.CY_IN(CY_IN), .SUBP(~OPCODE[0]), .BCD_Q(bcd_q), .CY_OUT(bcd_carry), .BCD_DONE(bcd_done) );
|
|
|
// FP - path : selection of result and rounding :
|
// FP - path : selection of result and rounding :
|
|
|
always @(misc_op or OPCODE or mulout or addout or divout or miscout)
|
always @(misc_op or OPCODE or mulout or addout or divout or miscout)
|
casex ({misc_op,OPCODE[5],OPCODE[3:2]}) //OPCODE[5] only for Flags i.e. NAN
|
casex ({misc_op,OPCODE[5],OPCODE[3:2]}) //OPCODE[5] only for Flags i.e. NAN
|
4'b1xxx : fpout = miscout; // for MOVLF,MOVFL,SCALB & LOGB
|
4'b1xxx : fpout = miscout; // for MOVLF,MOVFL,SCALB & LOGB
|
4'b0110 : fpout = divout;
|
4'b0110 : fpout = divout;
|
4'b0111 : fpout = mulout;
|
4'b0111 : fpout = mulout;
|
default : fpout = addout;
|
default : fpout = addout;
|
endcase
|
endcase
|
|
|
always @(FSR or fpout) // Calculation of Carry according to rounding mode, fpout[67] = sign bit
|
always @(FSR or fpout) // Calculation of Carry according to rounding mode, fpout[67] = sign bit
|
casex (FSR[8:7])
|
casex (FSR[8:7])
|
2'b00 : car_ry = ((fpout[1:0] == 2'b10) & fpout[2]) | (fpout[1:0] == 2'b11); // round to nearest
|
2'b00 : car_ry = ((fpout[1:0] == 2'b10) & fpout[2]) | (fpout[1:0] == 2'b11); // round to nearest
|
2'b10 : car_ry = ~fpout[67] & (fpout[1:0] != 2'b00); // round to positiv infinity
|
2'b10 : car_ry = ~fpout[67] & (fpout[1:0] != 2'b00); // round to positiv infinity
|
2'b11 : car_ry = fpout[67] & (fpout[1:0] != 2'b00); // round to negativ infinity
|
2'b11 : car_ry = fpout[67] & (fpout[1:0] != 2'b00); // round to negativ infinity
|
default : car_ry = 1'b0; // round to zero
|
default : car_ry = 1'b0; // round to zero
|
endcase
|
endcase
|
|
|
assign cy_val = {35'h0,(FL & car_ry),28'h0,(~FL & car_ry)};
|
assign cy_val = {35'h0,(FL & car_ry),28'h0,(~FL & car_ry)};
|
|
|
assign rund = {fpout[66:2]} + cy_val;
|
assign rund = {fpout[66:2]} + cy_val;
|
|
|
// Detection of Div-by-0, Overflow, Underflow and Inexact : Epxonent from [66:54] = 13 Bits
|
// Detection of Div-by-0, Overflow, Underflow and Inexact : Epxonent from [66:54] = 13 Bits
|
assign div_zero = (srcflags[3:0] == 4'h1) & (OPCODE == 8'hB8); // true FPU Divide by Zero
|
assign div_zero = (srcflags[3:0] == 4'h1) & ((OPCODE == 8'hB8) | (OPCODE == 8'hB7)); // true FPU Divide by Zero also for LOGBf
|
assign overflow = ~rund[66] & (rund[65] | (rund[64:54] == 11'h7FF));
|
assign overflow = ~rund[66] & (rund[65] | (rund[64:54] == 11'h7FF));
|
assign underflow = (rund[66] | (rund[65:54] == 12'h0)) & ~fpout[68]; // Zero-Flag
|
assign underflow = (rund[66] | (rund[65:54] == 12'h0)) & ~fpout[68]; // Zero-Flag
|
assign inexact = (fpout[1:0] != 2'b00);
|
assign inexact = (fpout[1:0] != 2'b00);
|
|
|
always @(fpout or op_cmp or div_zero or overflow or underflow or inexact or FSR)
|
always @(fpout or op_cmp or div_zero or overflow or underflow or inexact or FSR)
|
casex ({fpout[69],op_cmp,div_zero,overflow,FSR[3],underflow,FSR[5],inexact}) // [69] = NAN
|
casex ({fpout[69],op_cmp,div_zero,overflow,FSR[3],underflow,FSR[5],inexact}) // [69] = NAN
|
8'b1xxxxxxx : tt = 3'b101; // Invalid operation
|
8'b1xxxxxxx : tt = 3'b101; // Invalid operation
|
8'b001xxxxx : tt = 3'b011; // Divide by Zero
|
8'b001xxxxx : tt = 3'b011; // Divide by Zero
|
8'b0001xxxx : tt = 3'b010; // Overflow
|
8'b0001xxxx : tt = 3'b010; // Overflow
|
8'b000011xx : tt = 3'b001; // Underflow
|
8'b000011xx : tt = 3'b001; // Underflow
|
8'b00000011 : tt = 3'b110; // Inexact Result
|
8'b00000011 : tt = 3'b110; // Inexact Result
|
default : tt = 3'b000; // no error
|
default : tt = 3'b000; // no error
|
endcase
|
endcase
|
|
|
assign TT_DP = man_ops ? 5'd0 : {(inexact & ~op_cmp),(underflow & ~op_cmp),tt}; // at ABSf/NEGf no error : different to NS32381 !
|
assign TT_DP = man_ops ? 5'd0 : {(inexact & ~op_cmp),(underflow & ~op_cmp),tt}; // at ABSf/NEGf no error : different to NS32381 !
|
|
|
assign fp_res = FL ? {fpout[67],rund[61:31],rund[33:2]}
|
assign fp_res = FL ? {fpout[67],rund[61:31],rund[33:2]}
|
: {fpout[67],rund[64:2]}; // lower 32 bits identical
|
: {fpout[67],rund[64:2]}; // lower 32 bits identical
|
|
|
// Underflow special case and get ZERO
|
// Underflow special case and get ZERO
|
assign fp_out = (underflow | fpout[68]) ? 64'h0 : fp_res;
|
assign fp_out = (underflow | fpout[68]) ? 64'h0 : fp_res;
|
|
|
// 63..32 goes to memory if Word or Byte ! Also in ODD Register , 31..0 goes in EVEN Register
|
// 63..32 goes to memory if Word or Byte ! Also in ODD Register , 31..0 goes in EVEN Register
|
// DEI comes without WR_REG information
|
// DEI comes without WR_REG information
|
always @(make_i or copop or MEI or BWD or WR_REG or MRESULT or COP_IN or i_out or fp_out or divi_ops or divi_out or bcd_ops or bcd_q)
|
always @(make_i or copop or MEI or BWD or WR_REG or MRESULT or COP_IN or i_out or fp_out or divi_ops or divi_out or bcd_ops or bcd_q)
|
casex ({make_i,copop,MEI,BWD})
|
casex ({make_i,copop,MEI,BWD})
|
5'b00100 : DOUT = {MRESULT[31:8], (WR_REG ? MRESULT[15:8] : MRESULT[7:0]), MRESULT[31:0]}; // LSD always the same
|
5'b00100 : DOUT = {MRESULT[31:8], (WR_REG ? MRESULT[15:8] : MRESULT[7:0]), MRESULT[31:0]}; // LSD always the same
|
5'b00101 : DOUT = {MRESULT[31:16],(WR_REG ? MRESULT[31:16] : MRESULT[15:0]),MRESULT[31:0]};
|
5'b00101 : DOUT = {MRESULT[31:16],(WR_REG ? MRESULT[31:16] : MRESULT[15:0]),MRESULT[31:0]};
|
5'b0011x : DOUT = MRESULT[63:0];
|
5'b0011x : DOUT = MRESULT[63:0];
|
5'b01xxx : DOUT = COP_IN; // true alignment in Coprocessor
|
5'b01xxx : DOUT = COP_IN; // true alignment in Coprocessor
|
5'b1xxxx : DOUT = divi_ops ? divi_out : {(bcd_ops ? bcd_q : i_out),fp_out[31:0]}; // MSD is written first
|
5'b1xxxx : DOUT = divi_ops ? divi_out : {(bcd_ops ? bcd_q : i_out),fp_out[31:0]}; // MSD is written first
|
default : DOUT = fp_out;
|
default : DOUT = fp_out;
|
endcase
|
endcase
|
|
|
always @(posedge BCLK) DP_CMP <= {(srcflags[3] | srcflags[1]),cmpres}; // Only valid if not NaN
|
always @(posedge BCLK) DP_CMP <= {(srcflags[3] | srcflags[1]),cmpres}; // Only valid if not NaN
|
|
|
// Pipeline Control + Registerfile write control
|
// Pipeline Control + Registerfile write control
|
|
|
always @(posedge BCLK or negedge BRESET)
|
always @(posedge BCLK or negedge BRESET)
|
if (!BRESET) sequ <= 2'b00;
|
if (!BRESET) sequ <= 2'b00;
|
else
|
else
|
sequ <= {(sequ[1] & ~DONE),START[1]};
|
sequ <= {(sequ[1] & ~DONE),(START[1] & ~wctrl[5])};
|
|
|
always @(FL or OPCODE or copwr)
|
always @(FL or OPCODE or copwr)
|
casex ({FL,OPCODE}) // WRITE Control : [2] = clr_lsb, [1] = wr_part2, [0] = wr_part1
|
casex ({FL,OPCODE}) // WRITE Control : [2] = clr_lsb, [1] = wr_part2, [0] = wr_part1
|
9'bx_1001_000x : wctrl = 5'b01_111; // MOViL
|
9'b0_1001_000x : wctrl = 6'b001_111; // MOViL
|
9'bx_1001_010x : wctrl = 5'b00_010; // MOVLF
|
9'b1_1001_000x : wctrl = 6'b100_010; // MOViF <= SFPU
|
9'bx_1001_011x : wctrl = 5'b01_111; // MOVFL
|
9'bx_1001_010x : wctrl = 6'b000_010; // MOVLF
|
9'bx_1001_100x : wctrl = 5'b00_010; // ROUNDLi - DONE is one cycle earlier for this opcodes
|
9'bx_1001_011x : wctrl = 6'b001_111; // MOVFL
|
9'bx_1001_101x : wctrl = 5'b00_010; // TRUNCLi
|
9'b0_1001_100x : wctrl = 6'b000_010; // ROUNDLi
|
9'bx_1001_111x : wctrl = 5'b00_010; // FLOORLi
|
9'b0_1001_101x : wctrl = 6'b000_010; // TRUNCLi
|
9'bx_1011_0000 : wctrl = 5'b01_111; // ADDL
|
9'b0_1001_111x : wctrl = 6'b000_010; // FLOORLi
|
9'bx_1011_0010 : wctrl = 5'b00_000; // CMPL - via LD one cycle later in PSR
|
9'b1_1001_100x : wctrl = 6'b100_010; // ROUNDFi
|
9'bx_1011_0100 : wctrl = 5'b01_111; // SUBL
|
9'b1_1001_101x : wctrl = 6'b100_010; // TRUNCFi
|
9'b1_1011_1000 : wctrl = 5'b10_001; // DIVF - measured 18 cycles Reg-Reg
|
9'b1_1001_111x : wctrl = 6'b100_010; // FLOORFi
|
9'b0_1011_1000 : wctrl = 5'b10_111; // DIVL - measured 34 cycles Reg-Reg
|
9'b0_1011_0000 : wctrl = 6'b001_111; // ADDL
|
9'bx_1011_1100 : wctrl = 5'b01_111; // MULL
|
9'b1_1011_0000 : wctrl = 6'b100_010; // ADDF <= SFPU
|
9'bx_0110_1x11 : wctrl = 5'b10_001; // ADDP,SUBP
|
9'b0_1011_0010 : wctrl = 6'b000_000; // CMPL
|
9'bx_0111_1001 : wctrl = 5'b00_111; // MEIi
|
9'b1_1011_0010 : wctrl = 6'b100_000; // CMPF
|
9'bx_0111_1011 : wctrl = 5'b10_111; // DEIi
|
9'b0_1011_0100 : wctrl = 6'b001_111; // SUBL
|
9'bx_0111_11xx : wctrl = 5'b10_001; // QUOi,REMi,MODi,DIVi
|
9'b1_1011_0100 : wctrl = 6'b100_010; // SUBF <= SFPU
|
9'b1_1011_011x : wctrl = 5'b00_010; // SCALBF/LOGBF
|
9'b1_1011_1000 : wctrl = 6'b010_001; // DIVF - measured 18 clocks Reg-Reg
|
9'b0_1011_011x : wctrl = 5'b01_111; // SCALBL/LOGBL
|
9'b0_1011_1000 : wctrl = 6'b010_111; // DIVL - measured 34 clocks Reg-Reg
|
9'bx_1101_1101 : wctrl = {4'b10_00,copwr}; // execute coprocessor opcode
|
9'b0_1011_1100 : wctrl = 6'b001_111; // MULL
|
default : wctrl = 5'b0;
|
9'b1_1011_1100 : wctrl = 6'b100_010; // MULF <= SFPU
|
endcase
|
9'bx_0111_000x : wctrl = 6'b100_010; // ADDP,SUBP
|
|
9'bx_0111_1001 : wctrl = 6'b000_111; // MEIi
|
assign done_i = wctrl[4] ? (div_done | bcd_done | COP_DONE) : ( (wctrl[3] | ~WR_REG) ? sequ[2] : sequ[1] );
|
9'bx_0111_1011 : wctrl = 6'b010_111; // DEIi
|
assign DONE = ~START[1] & done_i; // DONE is valid for all opcodes
|
9'bx_0111_11xx : wctrl = 6'b010_001; // QUOi,REMi,MODi,DIVi
|
|
9'b1_1011_011x : wctrl = 6'b000_010; // SCALBF/LOGBF
|
|
9'b0_1011_011x : wctrl = 6'b001_111; // SCALBL/LOGBL
|
|
9'bx_1101_1101 : wctrl = {5'b010_00,copwr}; // Coprocessor opcode
|
|
default : wctrl = 6'b00;
|
|
endcase
|
|
|
|
assign later = wctrl[3] & WR_REG; // if DEST = Reg and 64 bit of data then DONE comes 1 clock later
|
|
assign done_i = wctrl[4] ? (div_done | COP_DONE) : ( later ? sequ[2] : sequ[1] );
|
|
assign DONE = wctrl[5] ? (bcd_ops ? bcd_done : START[1]) : ~START[1] & done_i; // DONE is valid for all opcodes
|
|
|
assign wr_part1 = DONE & WR_REG & wctrl[0];
|
assign wr_part1 = DONE & WR_REG & wctrl[0];
|
|
|
always @(posedge BCLK) CLR_LSB <= DONE & WR_REG & wctrl[2];
|
always @(posedge BCLK) CLR_LSB <= DONE & WR_REG & wctrl[2];
|
always @(posedge BCLK) wr_part2 <= DONE & WR_REG & wctrl[1];
|
always @(posedge BCLK) wr_part2 <= DONE & WR_REG & wctrl[1];
|
|
|
assign WREN_L = wr_part1 | wr_part2;
|
assign WREN_L = wr_part1 | wr_part2;
|
assign LD_OUT_L = DONE & ~WR_REG; // meaning is "Load Out-Reg from Long-Path"
|
|
|
|
always @(posedge BCLK) up_flag <= DONE & ~wctrl[0]; // DONE one cycle later
|
always @(posedge BCLK) up_flag <= DONE & ~later; // DONE one cycle later
|
assign UP_DP = (select[3] & (wctrl[0] ? DONE : up_flag)) | man_ops; // Update FSR Trap etc. : all FPU opcodes of DP_FPU
|
assign UP_DP = (select[2] & (later ? DONE : up_flag)) | man_ops; // Update FSR Trap etc. : all FPU opcodes of DP_FPU
|
|
|
// Overflow Trap for Division : DEI, QUO, DIV
|
// Overflow Trap for Division : DEI, QUO, DIV
|
assign quo_div = (OPCODE == 8'h7C) | (OPCODE == 8'h7F);
|
assign quo_div = (OPCODE == 8'h7C) | (OPCODE == 8'h7F);
|
always @(*)
|
always @(*)
|
casex ({OPCODE[2],BWD})
|
casex ({OPCODE[2],BWD})
|
3'b100 : ovf_div = (divi_out[39] & SRC1[7] & SRC2[7] ) & quo_div;
|
3'b100 : ovf_div = (divi_out[39] & SRC1[7] & SRC2[7] ) & quo_div;
|
3'b101 : ovf_div = (divi_out[47] & SRC1[15] & SRC2[15]) & quo_div;
|
3'b101 : ovf_div = (divi_out[47] & SRC1[15] & SRC2[15]) & quo_div;
|
3'b11x : ovf_div = (divi_out[63] & SRC1[31] & SRC2[31]) & quo_div;
|
3'b11x : ovf_div = (divi_out[63] & SRC1[31] & SRC2[31]) & quo_div;
|
default : ovf_div = dei_ovf[0] & (OPCODE == 8'h7B); // DEI
|
default : ovf_div = dei_ovf[0] & (OPCODE == 8'h7B); // DEI
|
endcase
|
endcase
|
|
|
assign OVF_BCD = {dei_ovf[1],ovf_div,bcd_done,bcd_carry}; // to I_PFAD
|
always @(posedge BCLK) late_bcd_done <= bcd_done; // parallel to data write
|
|
|
|
assign OVF_BCD = {dei_ovf[1],ovf_div,late_bcd_done,bcd_carry}; // to I_PFAD
|
|
|
always @(posedge BCLK) COP_GO <= START[1] & copop;
|
always @(posedge BCLK) COP_GO <= START[1] & copop;
|
|
|
endmodule
|
endmodule
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 10. DP_FPU Top level of long operations datapath
|
// 11. DP_FPU Top level of long operations datapath
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
module DP_FPU( BCLK, FL, BRESET, LD_LDQ, WR_REG, BWD, FSR, OPCODE, SRC1, SRC2, START, DONE, UP_DP, WREN_L,
|
module DP_FPU( BCLK, FL, BRESET, LD_OUT, WR_REG, BWD, FSR, OPCODE, SRC1, SRC2, START, CY_IN, COP_DONE, COP_OP, COP_IN,
|
CLR_LSB, LD_OUT_L, DVZ_TRAP, DP_CMP, DP_OUT, DP_Q, TT_DP, CY_IN, OVF_BCD, COP_GO, COP_OP,
|
DONE, UP_DP, WREN_L, CLR_LSB, DVZ_TRAP, DP_CMP, DP_OUT, DP_Q, TT_DP, OVF_BCD, COP_GO, COP_OUT );
|
COP_IN, COP_DONE, COP_OUT );
|
|
|
|
input BCLK;
|
input BCLK;
|
input FL;
|
input FL;
|
input BRESET;
|
input BRESET;
|
input LD_LDQ;
|
input [1:0] LD_OUT;
|
input WR_REG;
|
input WR_REG;
|
input [1:0] BWD;
|
input [1:0] BWD;
|
input [8:3] FSR;
|
input [8:3] FSR;
|
input [7:0] OPCODE;
|
input [7:0] OPCODE;
|
input [31:0] SRC1;
|
input [31:0] SRC1;
|
input [31:0] SRC2;
|
input [31:0] SRC2;
|
input [1:0] START;
|
input [1:0] START;
|
input CY_IN;
|
input CY_IN;
|
input COP_DONE;
|
input COP_DONE;
|
input [23:0] COP_OP;
|
input [23:0] COP_OP;
|
input [63:0] COP_IN;
|
input [63:0] COP_IN;
|
|
|
output DONE;
|
output DONE;
|
output UP_DP;
|
output UP_DP;
|
output WREN_L;
|
output WREN_L;
|
output CLR_LSB;
|
output CLR_LSB;
|
output LD_OUT_L;
|
|
output DVZ_TRAP;
|
output DVZ_TRAP;
|
output [2:0] DP_CMP;
|
output [2:0] DP_CMP;
|
output [31:0] DP_OUT;
|
output [31:0] DP_OUT;
|
output [31:0] DP_Q;
|
output [31:0] DP_Q;
|
output [4:0] TT_DP;
|
output [4:0] TT_DP;
|
output [3:0] OVF_BCD;
|
output [3:0] OVF_BCD;
|
output COP_GO;
|
output COP_GO;
|
output [127:0] COP_OUT;
|
output [127:0] COP_OUT;
|
|
|
reg [52:0] MDA;
|
reg [52:0] MDA;
|
reg [52:0] MDB;
|
reg [52:0] MDB;
|
reg [31:0] DP_Q;
|
reg [31:0] DP_Q;
|
reg [31:20] RCOPA,RCOPB;
|
reg [31:20] RCOPA,RCOPB;
|
|
|
wire [63:0] DOUT;
|
wire [63:0] DOUT;
|
wire [105:0] MRESULT;
|
wire [105:0] MRESULT;
|
wire MEI;
|
wire MEI;
|
wire DFLOAT;
|
wire DFLOAT;
|
wire LOAD_MSD;
|
wire LOAD_MSD;
|
wire LOAD_LSD1;
|
wire LOAD_LSD1;
|
wire LOAD_LSD2;
|
wire LOAD_LSD2;
|
wire [31:0] LSD_1;
|
wire [31:0] LSD_1;
|
wire [31:0] LSD_2;
|
wire [31:0] LSD_2;
|
wire [52:32] MSD_1;
|
wire [52:32] MSD_1;
|
wire [52:32] MSD_2;
|
wire [52:32] MSD_2;
|
|
|
|
|
DP_LOGIK DOUBLE_U(
|
DP_LOGIK DOUBLE_U(
|
.FL(FL),
|
.FL(FL),
|
.BRESET(BRESET),
|
.BRESET(BRESET),
|
.BCLK(BCLK),
|
.BCLK(BCLK),
|
.WR_REG(WR_REG),
|
.WR_REG(WR_REG),
|
.BWD(BWD),
|
.BWD(BWD),
|
.FSR(FSR),
|
.FSR(FSR),
|
.MAN1(MDA[52:32]),
|
.MAN1(MDA[52:32]),
|
.MAN2(MDB[52:32]),
|
.MAN2(MDB[52:32]),
|
.MRESULT(MRESULT),
|
.MRESULT(MRESULT),
|
.OPCODE(OPCODE),
|
.OPCODE(OPCODE),
|
.SRC1(SRC1),
|
.SRC1(SRC1),
|
.SRC2(SRC2),
|
.SRC2(SRC2),
|
.START(START),
|
.START(START),
|
.MEI(MEI),
|
.MEI(MEI),
|
.DFLOAT(DFLOAT),
|
.DFLOAT(DFLOAT),
|
.DONE(DONE),
|
.DONE(DONE),
|
.UP_DP(UP_DP),
|
.UP_DP(UP_DP),
|
.CLR_LSB(CLR_LSB),
|
.CLR_LSB(CLR_LSB),
|
.WREN_L(WREN_L),
|
.WREN_L(WREN_L),
|
.LD_OUT_L(LD_OUT_L),
|
|
.DVZ_TRAP(DVZ_TRAP),
|
.DVZ_TRAP(DVZ_TRAP),
|
.DOUT(DOUT),
|
.DOUT(DOUT),
|
.DP_CMP(DP_CMP),
|
.DP_CMP(DP_CMP),
|
.TT_DP(TT_DP),
|
.TT_DP(TT_DP),
|
.CY_IN(CY_IN),
|
.CY_IN(CY_IN),
|
.OVF_BCD(OVF_BCD),
|
.OVF_BCD(OVF_BCD),
|
.COP_DONE(COP_DONE),
|
.COP_DONE(COP_DONE),
|
.COP_OP(COP_OP),
|
.COP_OP(COP_OP),
|
.COP_IN(COP_IN),
|
.COP_IN(COP_IN),
|
.COP_GO(COP_GO));
|
.COP_GO(COP_GO));
|
|
|
PREPDATA DP_PREP(
|
PREPDATA DP_PREP(
|
.MEI(MEI),
|
.MEI(MEI),
|
.DFLOAT(DFLOAT),
|
.DFLOAT(DFLOAT),
|
.BWD(BWD),
|
.BWD(BWD),
|
.SRC1(SRC1),
|
.SRC1(SRC1),
|
.SRC2(SRC2),
|
.SRC2(SRC2),
|
.START(START),
|
.START(START),
|
.LOAD_LSD1(LOAD_LSD1),
|
.LOAD_LSD1(LOAD_LSD1),
|
.LOAD_LSD2(LOAD_LSD2),
|
.LOAD_LSD2(LOAD_LSD2),
|
.LOAD_MSD(LOAD_MSD),
|
.LOAD_MSD(LOAD_MSD),
|
.LSD_1(LSD_1),
|
.LSD_1(LSD_1),
|
.LSD_2(LSD_2),
|
.LSD_2(LSD_2),
|
.MSD_1(MSD_1),
|
.MSD_1(MSD_1),
|
.MSD_2(MSD_2));
|
.MSD_2(MSD_2));
|
|
|
assign MRESULT = MDA * MDB; // unsigned multiplier 53 * 53 bits = 106 bits
|
assign MRESULT = MDA * MDB; // unsigned multiplier 53 * 53 bits = 106 bits
|
|
|
assign DP_OUT = CLR_LSB ? DP_Q : DOUT[63:32];
|
assign DP_OUT = CLR_LSB ? DP_Q : DOUT[63:32];
|
|
|
always@(posedge BCLK) if (LD_OUT_L || LD_LDQ || WREN_L) DP_Q <= LD_LDQ ? SRC2 : DOUT[31:0];
|
always@(posedge BCLK) if (LD_OUT[1] || LD_OUT[0] || WREN_L) DP_Q <= LD_OUT[0] ? SRC2 : DOUT[31:0];
|
|
|
always@(posedge BCLK) if (LOAD_LSD1) MDA[31:0] <= LSD_1;
|
always@(posedge BCLK) if (LOAD_LSD1) MDA[31:0] <= LSD_1;
|
|
|
always@(posedge BCLK) if (LOAD_LSD2) MDB[31:0] <= LSD_2;
|
always@(posedge BCLK) if (LOAD_LSD2) MDB[31:0] <= LSD_2;
|
|
|
always@(posedge BCLK)
|
always@(posedge BCLK)
|
if (LOAD_MSD)
|
if (LOAD_MSD)
|
begin
|
begin
|
MDA[52:32] <= MSD_1;
|
MDA[52:32] <= MSD_1;
|
MDB[52:32] <= MSD_2;
|
MDB[52:32] <= MSD_2;
|
RCOPA <= SRC1[31:20];
|
RCOPA <= SRC1[31:20];
|
RCOPB <= SRC2[31:20];
|
RCOPB <= SRC2[31:20];
|
end
|
end
|
|
|
assign COP_OUT = {RCOPA,MDA[51:32],SRC1,RCOPB,MDB[51:32],SRC2};
|
assign COP_OUT = {RCOPA,MDA[51:32],SRC1,RCOPB,MDB[51:32],SRC2};
|
|
|
endmodule
|
endmodule
|
|
|