//////////////////////////////////////////////////////////////////////////////// // // Create Date: 03/14/09 // Module Name: fpu_add.v // Description: Simple try of adding two floating point number together // // // // Revision: // Revision 0.01 - File Created // // File format: This file has been formated to use tabstop of 4 // // Development platform: Spartan-3 Nexys from Digilent // // Copyright (C) 2009, Rick Huang // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // //////////////////////////////////////////////////////////////////////////////// module fpu_add(mclk, ini, inj, out); // Setting of the width of the procesing unit parameter EXPONENT_BITS = 8; parameter MANTISSA_BITS = 23; parameter TOTAL_BITS = EXPONENT_BITS + MANTISSA_BITS + 1; parameter MSB = EXPONENT_BITS + MANTISSA_BITS; parameter BIT_COUNTER = 5; // Define the input and output port input mclk; input [MSB : 0] ini; input [MSB : 0] inj; output [MSB : 0] out; // Divide in input into it's sub component wire ini_sign; wire [EXPONENT_BITS - 1 : 0] ini_exp; wire [MANTISSA_BITS - 1 : 0] ini_man; wire inj_sign; wire [EXPONENT_BITS - 1: 0] inj_exp; wire [MANTISSA_BITS - 1: 0] inj_man; assign ini_sign = ini[MSB]; assign ini_exp = ini[MSB - 1 : MANTISSA_BITS]; assign ini_man = ini[MANTISSA_BITS - 1 : 0]; assign inj_sign = inj[MSB]; assign inj_exp = inj[MSB - 1 : MANTISSA_BITS]; assign inj_man = inj[MANTISSA_BITS - 1 : 0]; // Align the incoming data reg [EXPONENT_BITS - 1: 0] exp_aligned; reg [BIT_COUNTER : 0] exp_adj; // Fixed size for now, change it later reg exp_adj_on_j; // 1 for adjust on j, 0 for i; always @ * begin exp_aligned = (ini_exp >= inj_exp) ? ini_exp : inj_exp; exp_adj_on_j = ini_exp > inj_exp; if(exp_adj_on_j) exp_adj = exp_aligned - inj_exp; else exp_adj = exp_aligned - ini_exp; end // Assemble the mantissa bits into something that can be operated on reg signed [MANTISSA_BITS + 1 : 0] op_pre_i; reg signed [MANTISSA_BITS + 1 : 0] op_pre_j; always @ * begin op_pre_i[MANTISSA_BITS + 1] = ini_sign; op_pre_i[MANTISSA_BITS : 0] = ini_sign ? ~({1'b1, ini_man} - 1) : {1'b1, ini_man}; op_pre_j[MANTISSA_BITS + 1] = inj_sign; op_pre_j[MANTISSA_BITS : 0] = inj_sign ? ~({1'b1, inj_man} - 1) : {1'b1, inj_man}; end // Select which input is to be adjusted reg signed [MANTISSA_BITS + 1 : 0] op_pre_adj; reg signed [MANTISSA_BITS + 1 : 0] adjop; reg op_pre_adj_sign; always @ * begin op_pre_adj = exp_adj_on_j ? op_pre_j : op_pre_i; op_pre_adj_sign = exp_adj_on_j ? inj_sign : ini_sign; end // Adjust the mantissa bit with exponent shift - Sign extension is required always @ * begin case (exp_adj) 0: adjop = op_pre_adj; 1: adjop = {(op_pre_adj_sign ? (~ 1'h0): 1'h0), op_pre_adj[MANTISSA_BITS + 1: 1]}; 2: adjop = {(op_pre_adj_sign ? (~ 2'h0): 2'h0), op_pre_adj[MANTISSA_BITS + 1: 2]}; 3: adjop = {(op_pre_adj_sign ? (~ 3'h0): 3'h0), op_pre_adj[MANTISSA_BITS + 1: 3]}; 4: adjop = {(op_pre_adj_sign ? (~ 4'h0): 4'h0), op_pre_adj[MANTISSA_BITS + 1: 4]}; 5: adjop = {(op_pre_adj_sign ? (~ 5'h0): 5'h0), op_pre_adj[MANTISSA_BITS + 1: 5]}; 6: adjop = {(op_pre_adj_sign ? (~ 6'h0): 6'h0), op_pre_adj[MANTISSA_BITS + 1: 6]}; 7: adjop = {(op_pre_adj_sign ? (~ 7'h0): 7'h0), op_pre_adj[MANTISSA_BITS + 1: 7]}; 8: adjop = {(op_pre_adj_sign ? (~ 8'h0): 8'h0), op_pre_adj[MANTISSA_BITS + 1: 8]}; 9: adjop = {(op_pre_adj_sign ? (~ 9'h0): 9'h0), op_pre_adj[MANTISSA_BITS + 1: 9]}; 10: adjop = {(op_pre_adj_sign ? (~ 10'h0): 10'h0), op_pre_adj[MANTISSA_BITS + 1: 10]}; 11: adjop = {(op_pre_adj_sign ? (~ 11'h0): 11'h0), op_pre_adj[MANTISSA_BITS + 1: 11]}; 12: adjop = {(op_pre_adj_sign ? (~ 12'h0): 12'h0), op_pre_adj[MANTISSA_BITS + 1: 12]}; 13: adjop = {(op_pre_adj_sign ? (~ 13'h0): 13'h0), op_pre_adj[MANTISSA_BITS + 1: 13]}; 14: adjop = {(op_pre_adj_sign ? (~ 14'h0): 14'h0), op_pre_adj[MANTISSA_BITS + 1: 14]}; 15: adjop = {(op_pre_adj_sign ? (~ 15'h0): 15'h0), op_pre_adj[MANTISSA_BITS + 1: 15]}; 16: adjop = {(op_pre_adj_sign ? (~ 16'h0): 16'h0), op_pre_adj[MANTISSA_BITS + 1: 16]}; 17: adjop = {(op_pre_adj_sign ? (~ 17'h0): 17'h0), op_pre_adj[MANTISSA_BITS + 1: 17]}; 18: adjop = {(op_pre_adj_sign ? (~ 18'h0): 18'h0), op_pre_adj[MANTISSA_BITS + 1: 18]}; 19: adjop = {(op_pre_adj_sign ? (~ 19'h0): 19'h0), op_pre_adj[MANTISSA_BITS + 1: 19]}; 20: adjop = {(op_pre_adj_sign ? (~ 20'h0): 20'h0), op_pre_adj[MANTISSA_BITS + 1: 20]}; 21: adjop = {(op_pre_adj_sign ? (~ 21'h0): 21'h0), op_pre_adj[MANTISSA_BITS + 1: 21]}; 22: adjop = {(op_pre_adj_sign ? (~ 22'h0): 22'h0), op_pre_adj[MANTISSA_BITS + 1: 22]}; default: adjop = 0; endcase end // Put the data back into the operant reg signed [MANTISSA_BITS + 1 : 0] opi; reg signed [MANTISSA_BITS + 1 : 0] opj; always @ * begin if(exp_adj_on_j) begin opj = adjop; opi = op_pre_i; end else begin opi = adjop; opj = op_pre_j; end end // Do the addition reg signed [MANTISSA_BITS + 2 : 0] pre_out_man; always @ * begin pre_out_man = opi + opj; end // Define the output component reg out_sign; reg [EXPONENT_BITS - 1 : 0] out_exp; reg [MANTISSA_BITS - 1 : 0] out_man; // Extract the sign bit always @ * begin out_sign = pre_out_man[MANTISSA_BITS + 2]; end // Flip the output back to unsigned value reg [MANTISSA_BITS + 2 : 0] uns_out_man; always @ * begin uns_out_man = out_sign ? (~pre_out_man + 1) : pre_out_man; end // Find out how many shift is required - 0 = right shift by 1 reg [EXPONENT_BITS - 1 : 0] out_shift_req; always @ * begin out_shift_req = 0; if(uns_out_man[MANTISSA_BITS + 2] != 0) out_shift_req = 1; if(uns_out_man[MANTISSA_BITS + 2] == 0) out_shift_req = 2; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS + 1] == 0) out_shift_req = 3; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 0] == 0) out_shift_req = 4; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 1] == 0) out_shift_req = 5; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 2] == 0) out_shift_req = 6; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 3] == 0) out_shift_req = 7; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 4] == 0) out_shift_req = 8; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 5] == 0) out_shift_req = 9; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 6] == 0) out_shift_req = 10; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 7] == 0) out_shift_req = 11; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 8] == 0) out_shift_req = 12; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 9] == 0) out_shift_req = 13; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 10] == 0) out_shift_req = 14; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 11] == 0) out_shift_req = 15; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 12] == 0) out_shift_req = 16; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 13] == 0) out_shift_req = 17; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 14] == 0) out_shift_req = 18; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 15] == 0) out_shift_req = 19; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 16] == 0) out_shift_req = 20; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 17] == 0) out_shift_req = 21; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 18] == 0) out_shift_req = 22; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 19] == 0) out_shift_req = 23; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 20] == 0) out_shift_req = 24; if(uns_out_man[MANTISSA_BITS + 2 : MANTISSA_BITS - 21] == 0) out_shift_req = exp_aligned; end // Compute the final output exponent always @ * begin out_exp = exp_aligned - out_shift_req + 3; end // Shift the unsigned output to get the final Mantissa // uns_out_man is 3 bit larger than out_man, need to >> 3 by default // However, the first bit must be trimmed, so make it >> 2 by default always @ * begin out_man = uns_out_man; case (out_shift_req) 1: out_man = uns_out_man >> 2; // By default it should have been << 1 >> 2 2: out_man = uns_out_man >> 1; 3: out_man = uns_out_man ; 4: out_man = uns_out_man << 1; 5: out_man = uns_out_man << 2; 6: out_man = uns_out_man << 3; 7: out_man = uns_out_man << 4; 8: out_man = uns_out_man << 5; 9: out_man = uns_out_man << 6; 10: out_man = uns_out_man << 7; 11: out_man = uns_out_man << 8; 12: out_man = uns_out_man << 9; 13: out_man = uns_out_man << 10; 14: out_man = uns_out_man << 11; 15: out_man = uns_out_man << 12; 16: out_man = uns_out_man << 13; 17: out_man = uns_out_man << 14; 18: out_man = uns_out_man << 15; 19: out_man = uns_out_man << 16; 20: out_man = uns_out_man << 17; 21: out_man = uns_out_man << 18; 22: out_man = uns_out_man << 19; 23: out_man = uns_out_man << 20; 24: out_man = uns_out_man << 21; default: // output is 0 out_man = 0; endcase end // Form the output data assign out[MSB] = out_sign; assign out[MSB - 1 : MANTISSA_BITS] = out_exp; assign out[MANTISSA_BITS - 1 : 0] = out_man; endmodule