Line 2... |
Line 2... |
//
|
//
|
// 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.
|
Line 37... |
Line 38... |
// 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
|
//
|
//
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
Line 100... |
Line 102... |
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
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
Line 149... |
Line 167... |
// 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),
|
Line 172... |
Line 190... |
.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
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
Line 210... |
Line 228... |
// 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"
|
|
|
Line 270... |
Line 286... |
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;
|
|
|
Line 302... |
Line 319... |
|
|
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
|
Line 336... |
Line 355... |
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
|
|
|
Line 368... |
Line 388... |
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
|
|
|
Line 450... |
Line 468... |
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//
|
//
|
// 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);
|
Line 511... |
Line 524... |
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
|
|
|
Line 573... |
Line 617... |
|
|
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;
|
Line 589... |
Line 649... |
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)
|
Line 612... |
Line 669... |
|
|
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.
|
Line 933... |
Line 1002... |
|
|
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
|
Line 978... |
Line 1047... |
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;
|
Line 1015... |
Line 1082... |
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;
|
Line 1027... |
Line 1095... |
|
|
// 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);
|
Line 1087... |
Line 1150... |
// 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
|
Line 1162... |
Line 1225... |
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)
|
Line 1204... |
Line 1267... |
// 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})
|
Line 1254... |
Line 1325... |
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;
|
Line 1289... |
Line 1361... |
|
|
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;
|
Line 1337... |
Line 1408... |
.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),
|
Line 1368... |
Line 1438... |
|
|
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;
|
|
|