summaryrefslogtreecommitdiff
path: root/verilog/fpu/fpu_2.v
blob: b1930a5643e5395bb839c4934d531f59aa9265c6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
`include "exp_calc.v"
module fpu_2(
	input wire add_not,
	input wire[31:0] a_in, b_in,
	output wire[31:0] out
);

wire[23:0] a_sig, b_sig, b_shft_sig, a_shft_sig, a_sign_sig, b_sign_sig;
wire[24:0] sig_sum, sig_diff, sig_op, sig_final;
wire[7:0] exp;
wire[7:0] diff, neg_diff;
wire same_sign;

assign diff = a_in[30:23] - b_in[30:23];
assign neg_diff = b_in[30:23] - a_in[30:23];
assign exp = diff[7] ? b_in[30:23] : a_in[30:23];

assign same_sign = ~(a_in[31] ^ b_in[31]);

// Pull hidden bit into sig, if exp 0, no hidden bit
assign a_sig = (|a_in[30:23] ? {1'b1, a_in[22:0]} : {1'b0, a_in[22:0]});
assign b_sig = (|b_in[30:23] ? {1'b1, b_in[22:0]} : {1'b0, b_in[22:0]});

assign a_shft_sig = (diff[7] ? a_sig >> neg_diff : a_sig);
assign b_shft_sig = (diff[7] ? b_sig : b_sig >> diff);

//2C Invert if Negative and not same signs
assign a_sign_sig = same_sign ? a_shft_sig : (a_in[31] ? ~(a_shft_sig) + 24'b1 : a_shft_sig);
assign b_sign_sig = same_sign ? b_shft_sig : (b_in[31] ? ~(b_shft_sig) + 24'b1 : b_shft_sig);

//Adding
assign sig_sum = a_sign_sig + b_sign_sig;

//Subtraction
assign sig_diff = a_shft_sig + ~(b_shft_sig) + 25'b1;

assign sig_op = add_not ? sig_diff : sig_sum;
assign sig_final = sig_op[24] | same_sign ? sig_op : ~(sig_op) + 24'b1;

wire[24:0] sig_diff_final;
wire[7:0] exp_diff;
exp_calc exp_calc0(sig_final,exp,sig_diff_final,exp_diff);


// Assign exp and mantissa
assign out[31] = add_not & (a_in[31] | b_in[31]) ? (a_in[31] ^ b_in[31] ^ add_not ? (a_shft_sig > b_shft_sig ? 1 : 0) : a_in[31]) : (a_shft_sig > b_shft_sig ? a_in[31] : b_in[31]);
assign out[30:23] = add_not ? (same_sign ? exp_diff : (sig_diff_final[24] ? exp : exp)) : (sig_final[24] & same_sign ? exp + 8'b1 : (same_sign ? exp : exp_diff));
assign out[22:0] = add_not ? (same_sign ? sig_diff_final[22:0] : sig_diff_final[24] ? sig_diff_final[23:1] : sig_diff_final[22:0]) : sig_final[24] & same_sign ? sig_final[23:1] : (same_sign ? sig_final[22:0] : sig_diff_final[22:0]);

/* assign out = {exp_diff, 24'b0}; */
// assign out = {diff, neg_diff, 16'b0};
/* assign out = {sig_op, 7'b0}; */

endmodule