data/full_repos/permissive/427281804/FPU/verilog/FPALU.v
1: b'%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:173: Operator COND expects 7 bits on the Conditional True, but Conditional True\'s SEL generates 6 bits.\n                                                                            : ... In instance FPALU\nwire [AL_EXPSIZE-1:0] s1_ea_sub_eb_abs = s1_ea_gte_eb ?  s1_ea_sub_eb[AL_EXPSIZE-1:0] : {~s1_ea_sub_eb+1\'b1};\n                                                      ^\n                ... Use "/* verilator lint_off WIDTH */" and lint_on around source to disable this message.\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:173: Operator ASSIGNW expects 6 bits on the Assign RHS, but Assign RHS\'s COND generates 7 bits.\n                                                                            : ... In instance FPALU\nwire [AL_EXPSIZE-1:0] s1_ea_sub_eb_abs = s1_ea_gte_eb ?  s1_ea_sub_eb[AL_EXPSIZE-1:0] : {~s1_ea_sub_eb+1\'b1};\n                                       ^\n%Error: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:180: Cannot find file containing module: \'xchg\'\nxchg #(.DWIDTH(AL_MANSIZE)) s1_u_manxchg(\n^~~~\n        ... Looked in:\n             data/full_repos/permissive/427281804/FPU/verilog,data/full_repos/permissive/427281804/xchg\n             data/full_repos/permissive/427281804/FPU/verilog,data/full_repos/permissive/427281804/xchg.v\n             data/full_repos/permissive/427281804/FPU/verilog,data/full_repos/permissive/427281804/xchg.sv\n             xchg\n             xchg.v\n             xchg.sv\n             obj_dir/xchg\n             obj_dir/xchg.v\n             obj_dir/xchg.sv\n%Error: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:197: Cannot find file containing module: \'booth_ppgen_r4\'\n  booth_ppgen_r4 s1_u_br4ppgen (\n  ^~~~~~~~~~~~~~\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:224: Operator ASSIGNDLY expects 6 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 7 bits.\n                                                                            : ... In instance FPALU\n  s2_ea_r   <= {{(AL_EXPSIZE-ML_EXPSIZE){1\'b0}},din_ML_expa};\n            ^~\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:225: Operator ASSIGNDLY expects 6 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 7 bits.\n                                                                            : ... In instance FPALU\n  s2_eb_r   <= {{(AL_EXPSIZE-ML_EXPSIZE){1\'b0}},din_ML_expb};\n            ^~\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:271: Operator COND expects 23 bits on the Conditional True, but Conditional True\'s VARREF \'s2_mmux2_rhs\' generates 22 bits.\n                                                                            : ... In instance FPALU\nwire [AL_MANSIZE:0]   s2_mmux3_rhs_addsub  = s2_addsubn_r ? s2_mmux2_rhs : ~s2_mmux2_rhs;\n                                                          ^\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:271: Operator NOT expects 23 bits on the LHS, but LHS\'s VARREF \'s2_mmux2_rhs\' generates 22 bits.\n                                                                            : ... In instance FPALU\nwire [AL_MANSIZE:0]   s2_mmux3_rhs_addsub  = s2_addsubn_r ? s2_mmux2_rhs : ~s2_mmux2_rhs;\n                                                                           ^\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:377: Operator ASSIGN expects 23 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 22 bits.\n                                                                            : ... In instance FPALU\n  s3_alumux_lhs = {3\'b0,s3_ps0_r}; \n                ^\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:378: Operator ASSIGN expects 23 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 22 bits.\n                                                                            : ... In instance FPALU\n  s3_alumux_rhs = {s3_ps1_r,1\'b0,s3_s2_r,4\'b0};\n                ^\n%Error: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:388: Cannot find file containing module: \'cla_adder\'\ncla_adder #(.DATA_WID(32)) s3_s4_u_cla(\n^~~~~~~~~\n%Error: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:451: Cannot find file containing module: \'cla_adder\'\ncla_adder #(.DATA_WID(AL_MANSIZE+1)) s4_u_compl2(\n^~~~~~~~~\n%Error: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:463: Cannot find file containing module: \'count_lead_zero\'\ncount_lead_zero #(.W_IN(32)) s4_u_lzd(.in(s4_lzdi), .out(s4_lzd));\n^~~~~~~~~~~~~~~\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:505: Operator ASSIGNDLY expects 22 bits on the Assign RHS, but Assign RHS\'s VARREF \'s4_many_r\' generates 23 bits.\n                                                                            : ... In instance FPALU\n  s5_many_skip_r <= s4_many_r;\n                 ^~\n%Error: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:506: Cannot find file containing module: \'bsl\'\nbsl #(.SWIDTH(5)) s5_u_bsl (\n^~~\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:542: Operator SUB expects 32 or 7 bits on the RHS, but RHS\'s VARREF \'s5_lzd_r\' generates 5 bits.\n                                                                            : ... In instance FPALU\n  s5_expadj_final = s5_expadj_add + 1 - s5_lzd_r;\n                                      ^\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:551: Operator SUB expects 32 or 7 bits on the RHS, but RHS\'s VARREF \'s5_lzd_r\' generates 5 bits.\n                                                                            : ... In instance FPALU\n   s5_expadj_final = s5_expadj_mul + 1 - s5_lzd_r;\n                                       ^\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:556: Operator ASSIGN expects 7 bits on the Assign RHS, but Assign RHS\'s REPLICATE generates 8 bits.\n                                                                            : ... In instance FPALU\n  s5_expadj_final = {1\'bx, s5_expadj_skip};\n                  ^\n%Warning-WIDTH: data/full_repos/permissive/427281804/FPU/verilog/FPALU.v:561: Operator SUB expects 32 or 7 bits on the RHS, but RHS\'s VARREF \'s5_lzd_r\' generates 5 bits.\n                                                                            : ... In instance FPALU\n  s5_expadj_final = s5_expadj_add + 1 - s5_lzd_r - AL_EXPBIAS + ML_EXPBIAS;\n                                      ^\n%Error: Exiting due to 6 error(s), 13 warning(s)\n'
module FPALU (

	input           clk,
	input [1:0]		opcode,

	input           din_uni_a_sgn,
	input [5:0]     din_uni_a_exp,
	input [21:0]    din_uni_a_man_dn,

	input           din_uni_b_sgn,
	input [5:0]     din_uni_b_exp,
	input [21:0]    din_uni_b_man_dn,


	output          dout_uni_y_sgn,
	output [5:0]    dout_uni_y_exp, 
	output [21:0]   dout_uni_y_man_dn
);





localparam ML_MANSIZE = 11;
localparam ML_EXPSIZE = 5;
localparam ML_EXPBIAS = 2**(ML_EXPSIZE-1)-1;
localparam ML_FPSIZE  = 1 + ML_EXPSIZE + ML_MANSIZE;
localparam AL_MANSIZE = 2 * ML_MANSIZE;
localparam AL_EXPSIZE = 1 + ML_EXPSIZE;
localparam AL_FPSIZE  = 1 + AL_EXPSIZE + AL_MANSIZE;
localparam AL_EXPBIAS = 2**(AL_EXPSIZE-1)-1;

localparam OPSIZE = 2;

localparam OPC_ADD29i  = 2'b11;
localparam OPC_MUL16i  = 2'b10;
localparam OPC_ADDSKIP = 2'b01;


localparam OPC_ADD29NORM = 2'b00;



wire [AL_EXPSIZE-1:0]   din_AL_expa = din_uni_a_exp;
wire [AL_EXPSIZE-1:0]   din_AL_expb = din_uni_b_exp;
wire [AL_MANSIZE-1:0]   din_AL_mana = din_uni_a_man_dn;
wire [AL_MANSIZE-1:0]   din_AL_manb = din_uni_b_man_dn;


wire [ML_EXPSIZE:0]     din_ML_expa = {1'b0,din_uni_a_exp[ML_EXPSIZE-1:0]};
wire [ML_EXPSIZE:0]     din_ML_expb = {1'b0,din_uni_b_exp[ML_EXPSIZE-1:0]};
reg [ML_MANSIZE-1:0]    din_ML_mana;
reg [ML_MANSIZE-1:0]    din_ML_manb;




wire s1_ml_ea_is_denorm = (|din_ML_expa) == 1'b0;
wire s1_ml_eb_is_denorm = (|din_ML_expb) == 1'b0;
always @* begin


	if(s1_ml_ea_is_denorm) din_ML_mana = {din_uni_a_man_dn[ML_MANSIZE-2:0],1'b0};
	else                   din_ML_mana = {1'b1, din_uni_a_man_dn[ML_MANSIZE-2:0]};
	
	if(s1_ml_eb_is_denorm) din_ML_manb = {din_uni_b_man_dn[ML_MANSIZE-2:0],1'b0};
	else                   din_ML_manb = {1'b1, din_uni_b_man_dn[ML_MANSIZE-2:0]};

end

`ifdef DEBUGINFO
	real a_real_FP16  [3:0];
	real a_real_FP29i [3:0];
	real b_real_FP16  [3:0];
	real b_real_FP29i [3:0];
	real a_real_FP16_s5;
	real a_real_FP29i_s5;
	real b_real_FP16_s5;
	real b_real_FP29i_s5;
	real y_real_FP29i;
	real y_real_FP29;
	real y_expected_ml;
	real y_expected_ad;
	integer many_expected_ml;	

	real tm;
	real ta;
	reg  mul_valid;
	reg  add_valid; 
	
	always @(*) begin
		a_real_FP16  [0] = (1.0-2.0*din_uni_a_sgn) * din_ML_mana * 2.0**(-10.0) * 2.0**(din_ML_expa-15.0);
		b_real_FP16  [0] = (1.0-2.0*din_uni_b_sgn) * din_ML_manb * 2.0**(-10.0) * 2.0**(din_ML_expb-15.0);


	
		a_real_FP29i [0] = (1.0-2.0*din_uni_a_sgn) * din_AL_mana * 2.0**(-21.0) * 2**(din_AL_expa-31.0);
		b_real_FP29i [0] = (1.0-2.0*din_uni_b_sgn) * din_AL_manb * 2.0**(-21.0) * 2**(din_AL_expb-31.0);
		y_real_FP29i     = (1.0-2.0*dout_uni_y_sgn) * dout_uni_y_man_dn * 2.0**(-21.0 + dout_uni_y_exp - 31.0);
		y_expected_ml = a_real_FP16_s5  * b_real_FP16_s5;
		y_expected_ad = a_real_FP29i_s5 + b_real_FP29i_s5;
		
		mul_valid = 0;
		if(y_real_FP29i == y_expected_ml) begin
			mul_valid = 1;
		end else begin
			if(y_expected_ml!=0.0)
				tm = (y_real_FP29i-y_expected_ml)/(y_expected_ml);
			else tm = y_real_FP29i; 
			if(tm>=0) mul_valid = ( tm)<0.0001;
			else      mul_valid = (-tm)<0.0001;
		end

		add_valid = 0;
		if(y_real_FP29i == y_expected_ad) begin
			add_valid = 1;
		end else begin
			if(y_expected_ad!=0.0)
				ta = (y_real_FP29i - y_expected_ad)/y_expected_ad;
			else ta = y_real_FP29i;	
			if(ta>=0) add_valid = ( ta)<0.0001;
			else      add_valid = (-ta)<0.0001; 
		end
	end

	integer i;
	always @(posedge clk) begin
		for(i=3;i>0;i=i-1) begin
			a_real_FP16 [i]  <= a_real_FP16 [i-1];
			a_real_FP29i [i] <= a_real_FP29i [i-1];
			b_real_FP16 [i]  <= b_real_FP16 [i-1];
			b_real_FP29i [i] <= b_real_FP29i [i-1];
		end
		if(s4_opcode_r==OPC_MUL16i) begin
			a_real_FP16_s5  <= a_real_FP16[3];
			b_real_FP16_s5  <= b_real_FP16[3];
		end else begin
			a_real_FP29i_s5 <= a_real_FP29i[3];
			b_real_FP29i_s5 <= b_real_FP29i[3];
		end
	end
`endif






reg [OPSIZE-1:0] s1_opcode;
always @* begin
	s1_opcode = opcode;
end







wire [AL_EXPSIZE:0]   s1_ea_sub_eb = {1'b0,din_uni_a_exp} - {1'b0,din_uni_b_exp};
wire                  s1_ea_lt_eb  = s1_ea_sub_eb[AL_EXPSIZE];
wire                  s1_ea_gte_eb  = ~s1_ea_lt_eb;
wire [AL_EXPSIZE-1:0] s1_ea_sub_eb_abs = s1_ea_gte_eb ?  s1_ea_sub_eb[AL_EXPSIZE-1:0] : {~s1_ea_sub_eb+1'b1};

wire       s1_addsubn = ~(din_uni_a_sgn ^ din_uni_b_sgn);


wire [AL_MANSIZE-1:0]	s1_mmux_lhs;
wire [AL_MANSIZE-1:0]	s1_mmux_rhs;
xchg #(.DWIDTH(AL_MANSIZE)) s1_u_manxchg(
	.ia(din_uni_a_man_dn),
	.ib(din_uni_b_man_dn),
	.xchg(s1_ea_lt_eb),
	.oa(s1_mmux_lhs),
	.ob(s1_mmux_rhs)
);


localparam  PPSIZE = ML_MANSIZE+1;
wire [ML_MANSIZE+2:0] s1_br4enc_input = {2'b00, din_ML_manb, 1'b0};
wire [(PPSIZE)*6-1:0]		    s1_br4_pp;
wire [5:0]                      s1_br4_s;
genvar gi;
generate
	for(gi=0;gi<6;gi=gi+1) begin : gen_br4enc

		booth_ppgen_r4 s1_u_br4ppgen (
			.a(din_ML_mana),
			.br4(s1_br4enc_input[2*(gi+1):2*gi]),
			.o(s1_br4_pp[PPSIZE*(gi+1)-1:PPSIZE*(gi)]),
			.s(s1_br4_s[gi])
		);
	end
endgenerate





reg [OPSIZE-1:0]     s2_opcode_r;
reg                  s2_sa_r;
reg                  s2_sb_r;
reg [AL_EXPSIZE-1:0]	s2_ea_r;
reg [AL_EXPSIZE-1:0]	s2_eb_r;

always @(posedge clk) begin
	s2_opcode_r <= s1_opcode;
	s2_sa_r     <= din_uni_a_sgn;
	s2_sb_r     <= din_uni_b_sgn;
	if(s1_opcode == OPC_ADD29i) begin
		s2_ea_r   <= din_uni_a_exp;
		s2_eb_r   <= din_uni_b_exp;
	end else if(s1_opcode == OPC_MUL16i) begin
		s2_ea_r   <= {{(AL_EXPSIZE-ML_EXPSIZE){1'b0}},din_ML_expa};
		s2_eb_r   <= {{(AL_EXPSIZE-ML_EXPSIZE){1'b0}},din_ML_expb};
	end
end


reg [AL_EXPSIZE-1:0] s2_ea_sub_eb_abs_r;
reg                  s2_ea_gte_eb_r;
wire                 s2_ea_lt_eb = ~s2_ea_gte_eb_r;
reg [AL_MANSIZE-1:0] s2_mmux_lhs_r;
reg [AL_MANSIZE-1:0] s2_mmux_rhs_r;
reg                  s2_addsubn_r;
always @(posedge clk) begin
	s2_ea_sub_eb_abs_r <= s1_ea_sub_eb_abs;
	s2_ea_gte_eb_r     <= s1_ea_gte_eb;
	s2_mmux_lhs_r      <= s1_mmux_lhs;
	s2_mmux_rhs_r      <= s1_mmux_rhs;
	s2_addsubn_r       <= s1_addsubn;
end





wire              s2_lhs_is_zero = ~(|s2_mmux_lhs_r);

wire [OPSIZE-1:0] s2_opcode_mod;
assign s2_opcode_mod = ((s2_opcode_r==OPC_ADD29i)&&s2_lhs_is_zero) ? OPC_ADDSKIP : s2_opcode_r;




wire [AL_MANSIZE-1:0] s2_bsr_out_gated = s2_mmux_rhs_r >> s2_ea_sub_eb_abs_r;



wire [AL_MANSIZE-1:0] s2_mmux2_lhs = s2_mmux_lhs_r;
wire [AL_MANSIZE-1:0] s2_mmux2_rhs = s2_bsr_out_gated;
wire [AL_MANSIZE:0]   s2_mmux3_rhs_addsub  = s2_addsubn_r ? s2_mmux2_rhs : ~s2_mmux2_rhs;



wire [AL_MANSIZE:0]   s2_mmux3_lhs_addsub;
assign s2_mmux3_lhs_addsub = (s2_lhs_is_zero) ? {1'b0,s2_mmux_rhs_r} : {1'b0, s2_mmux2_lhs};



reg [PPSIZE*6-1:0]		s2_br4_pp_r;
reg [5:0]               s2_br4_s_r;
always @(posedge clk) begin

	if(s1_opcode==OPC_MUL16i) begin
		s2_br4_pp_r  <= s1_br4_pp;
		s2_br4_s_r   <= s1_br4_s;
	end
end


wire [PPSIZE-1:0]  pp0 = s2_br4_pp_r[PPSIZE*1-1:PPSIZE*0];
wire [PPSIZE-1:0]  pp1 = s2_br4_pp_r[PPSIZE*2-1:PPSIZE*1];
wire [PPSIZE-1:0]  pp2 = s2_br4_pp_r[PPSIZE*3-1:PPSIZE*2];
wire [PPSIZE-1:0]  pp3 = s2_br4_pp_r[PPSIZE*4-1:PPSIZE*3];
wire [PPSIZE-1:0]  pp4 = s2_br4_pp_r[PPSIZE*5-1:PPSIZE*4];
wire [PPSIZE-1:0]  pp5 = s2_br4_pp_r[PPSIZE*6-1:PPSIZE*5];
reg [PPSIZE+7-1:0] s2_ps0;
reg [PPSIZE+4-1:0] s2_ps1;
wire               s2_s2 = s2_br4_s_r[2];


always @* begin
	s2_ps0 =          {4'b0,{!s2_br4_s_r[0]},{2{s2_br4_s_r[0]}},pp0};
	s2_ps0 = s2_ps0 + {4'b0001,{!s2_br4_s_r[1]},pp1,1'b0,s2_br4_s_r[0]};
	s2_ps0 = s2_ps0 + {2'b01,{!s2_br4_s_r[2]},pp2,1'b0,s2_br4_s_r[1],2'b0};
	s2_ps1 =          {3'b001,{!s2_br4_s_r[3]},pp3};
	s2_ps1 = s2_ps1 + {1'b1,{!s2_br4_s_r[4]},pp4,1'b0,s2_br4_s_r[3]};
	s2_ps1 = s2_ps1 + {pp5,1'b0,s2_br4_s_r[4],2'b0};
end







reg [OPSIZE-1:0]     s3_opcode_r;
reg                  s3_sa_r;
reg                  s3_sb_r;
reg [AL_EXPSIZE-1:0]	s3_ea_r;
reg [AL_EXPSIZE-1:0]	s3_eb_r;
always @(posedge clk) begin
	if(s2_lhs_is_zero&&(s2_opcode_r==OPC_ADD29i)) 
                       s3_opcode_r <= OPC_ADDSKIP;
	else               s3_opcode_r <= s2_opcode_r;
	s3_ea_r   <= s2_ea_r;
	s3_eb_r   <= s2_eb_r;
	s3_sa_r   <= s2_sa_r;
	s3_sb_r   <= s2_sb_r;
end


reg [AL_MANSIZE:0]  s3_lhs_r;
reg [AL_MANSIZE:0]  s3_rhs_r;
reg                 s3_addsubn_r;

always @(posedge clk) begin
	s3_lhs_r     <= s2_mmux3_lhs_addsub;
	s3_rhs_r     <= s2_mmux3_rhs_addsub;
	s3_addsubn_r <= s2_addsubn_r;
end


reg                     s3_ea_gte_eb_r;
always @(posedge clk) begin
	s3_ea_gte_eb_r <= s2_ea_gte_eb_r;
end


reg [21:0]                s3_mulout;
reg [PPSIZE+7-1:0]        s3_ps0_r;
reg [PPSIZE+4-1:0]        s3_ps1_r;
reg                       s3_s2_r;
always @(posedge clk) begin
	s3_ps0_r <= s2_ps0;
	s3_ps1_r <= s2_ps1;
	s3_s2_r  <= s2_s2;
end


reg [AL_MANSIZE:0]   s3_alumux_lhs;
reg [AL_MANSIZE:0]   s3_alumux_rhs;
reg                  s3_alumux_cin;
wire [31:0]  s3_alu_out;
reg [1:0] dbg_s3_alumux_state;
always @(*) begin
	if(s3_opcode_r==OPC_ADD29i) begin

		dbg_s3_alumux_state = 0;
		s3_alumux_lhs = s3_lhs_r;
		s3_alumux_rhs = s3_rhs_r;
		s3_alumux_cin = ~s3_addsubn_r;
	end else if (s3_opcode_r == OPC_MUL16i) begin


		dbg_s3_alumux_state = 1;
		s3_alumux_lhs = {3'b0,s3_ps0_r}; 
		s3_alumux_rhs = {s3_ps1_r,1'b0,s3_s2_r,4'b0};
		s3_alumux_cin = 1'b0;
	end else begin

		s3_alumux_lhs = {(AL_MANSIZE+1){1'bx}};
		s3_alumux_rhs = {(AL_MANSIZE+1){1'bx}};
		s3_alumux_cin = 1'bx;
	end
end

cla_adder #(.DATA_WID(32)) s3_s4_u_cla(
	.in1      ({{9{s3_alumux_lhs[AL_MANSIZE]}},s3_alumux_lhs}),
	.in2      ({{9{s3_alumux_rhs[AL_MANSIZE]}},s3_alumux_rhs}),
	.carry_in (s3_alumux_cin),
	.sum      (s3_alu_out   ),
	.carry_out(             )
);


reg [AL_MANSIZE:0] s3_mmux_y;
wire s3_alu_of = s3_alu_out[AL_MANSIZE+1];

always @* begin
	case(s3_opcode_r) 
	OPC_ADDSKIP:	s3_mmux_y = s3_lhs_r;
	OPC_ADD29i:		s3_mmux_y = s3_alu_out[AL_MANSIZE:0];
	OPC_MUL16i:		s3_mmux_y = {1'b0,s3_alu_out[AL_MANSIZE-1:0]};
	endcase
end














reg [OPSIZE-1:0]     s4_opcode_r;
reg [AL_MANSIZE:0]   s4_many_r;
reg [AL_MANSIZE:0]   s4_lzdi_r;
reg [AL_EXPSIZE-1:0] s4_ea_r;
reg [AL_EXPSIZE-1:0] s4_eb_r;
reg                  s4_ea_gte_eb_r;
reg                  s4_addsubn_r;
reg                  s4_sa_r;
reg                  s4_sb_r;
reg                  s4_flipsign_r;
always @(posedge clk) begin
	if((s3_opcode_r==OPC_ADD29i) && s3_alu_of)  begin
		s4_flipsign_r <= 1;
	end else begin
		s4_flipsign_r <= 0;
	end
	s4_many_r      <= s3_mmux_y;
	s4_opcode_r    <= s3_opcode_r;
	s4_ea_r        <= s3_ea_r;
	s4_eb_r        <= s3_eb_r;
	s4_ea_gte_eb_r <= s3_ea_gte_eb_r;
	s4_addsubn_r   <= s3_addsubn_r;
	s4_sa_r        <= s3_sa_r;
	s4_sb_r        <= s3_sb_r;
end

wire [AL_MANSIZE:0] s4_lzdi_fp;

wire s4_compl2_en = s4_flipsign_r & (s4_opcode_r!=OPC_ADDSKIP);

cla_adder #(.DATA_WID(AL_MANSIZE+1)) s4_u_compl2(
	.in1      (s4_flipsign_r ? ~ s4_many_r : s4_many_r),
	.in2      ({AL_MANSIZE+1{1'b0}}),
	.carry_in (s4_flipsign_r),
	.sum      (s4_lzdi_fp   ),
	.carry_out(             )
);


wire [4:0]  s4_lzd;
wire [31:0] s4_lzdi = {s4_lzdi_fp,9'b0};

count_lead_zero #(.W_IN(32)) s4_u_lzd(.in(s4_lzdi), .out(s4_lzd));







reg [OPSIZE-1:0]     s5_opcode_r;
reg                  s5_addsubn_r;
reg                  s5_sa_r;
reg                  s5_sb_r;
reg                  s5_flipsign_r;
always @(posedge clk) begin
	s5_opcode_r  <= s4_opcode_r;
	s5_addsubn_r <= s4_addsubn_r;
	s5_sa_r      <= s4_sa_r;
	s5_sb_r      <= s4_sb_r;
	s5_flipsign_r<= s4_flipsign_r;
end


reg [AL_MANSIZE:0] s5_many_r;
reg [4:0]          s5_lzd_r;
reg [4:0]          s5_shiftbias;
always @(posedge clk) begin
	s5_many_r    <= s4_lzdi_fp;
	s5_lzd_r     <= s4_lzd;
end

always @* s5_shiftbias = s5_lzd_r;
wire [31:0]          s5_bsl_out;
reg [AL_MANSIZE-1:0] s5_many_skip_r;
always @(posedge clk) 
	if(s4_opcode_r==OPC_ADDSKIP) 
		s5_many_skip_r <= s4_many_r;
bsl #(.SWIDTH(5)) s5_u_bsl (
	.din    ({s5_many_r,9'b0}),
	.s      (s5_shiftbias     ),
	.filler (1'b0             ),
	.dout   (s5_bsl_out       )
);



reg [AL_EXPSIZE-1:0] s5_ea_r;
reg [AL_EXPSIZE-1:0] s5_eb_r;
reg                  s5_ea_gte_eb_r;
wire                 s5_ea_lt_eb = ~s5_ea_gte_eb_r;
always @(posedge clk) begin
	s5_ea_r        <= s4_ea_r;
	s5_eb_r        <= s4_eb_r;
	s5_ea_gte_eb_r <= s4_ea_gte_eb_r;
end


wire [AL_EXPSIZE:0]   s5_expadj_skip;
wire [AL_EXPSIZE:0]   s5_expadj_mul;
wire [AL_EXPSIZE:0]   s5_expadj_add;
reg  [AL_EXPSIZE:0]   s5_expadj_final;
reg                   s5_sign_final;
reg [AL_MANSIZE-1:0]  s5_many_final;

assign s5_expadj_mul  = {1'b0,s5_ea_r} + {1'b0,s5_eb_r} - 2*ML_EXPBIAS + AL_EXPBIAS + 1;

assign s5_expadj_add  = s5_ea_gte_eb_r ?  {1'b0,s5_ea_r} : {1'b0,s5_eb_r};
assign s5_expadj_skip = s5_ea_gte_eb_r ?  {1'b0,s5_eb_r} : {1'b0,s5_ea_r};
wire   s5_sign_skip   = s5_ea_gte_eb_r ?  s5_sb_r : s5_sa_r;


always @* begin
	if(s5_opcode_r == OPC_ADD29i) begin
		s5_expadj_final = s5_expadj_add + 1 - s5_lzd_r;
		s5_sign_final   = ((s5_addsubn_r)? s5_sa_r : s5_ea_lt_eb ^ s5_sa_r) ^ s5_flipsign_r;
		s5_many_final   = s5_bsl_out[31:10];
	end else if (s5_opcode_r == OPC_MUL16i) begin
		s5_many_final   = s5_bsl_out[31:10];
		if((|s5_many_final)==0) begin
			s5_expadj_final = 0;
			s5_sign_final   = 0;
		end else begin
			s5_expadj_final = s5_expadj_mul + 1 - s5_lzd_r;
			s5_sign_final   = ~s5_addsubn_r;
		end
	end else if (s5_opcode_r == OPC_ADDSKIP) begin

		s5_expadj_final = {1'bx, s5_expadj_skip};
		s5_sign_final   = s5_sign_skip;
		s5_many_final   = s5_many_skip_r;

	end else begin
		s5_expadj_final = s5_expadj_add + 1 - s5_lzd_r - AL_EXPBIAS + ML_EXPBIAS;
		s5_sign_final   = s5_sign_skip;
		s5_many_final   = {12'b0,s5_bsl_out[32-1-1:32-10-1]};
	end	
end


assign dout_uni_y_exp    = s5_expadj_final[AL_EXPSIZE-1:0];
assign dout_uni_y_sgn    = s5_sign_final;
assign dout_uni_y_man_dn = s5_many_final;

endmodule
module FPALU (

	input           clk,
	input [1:0]		opcode,

	input           din_uni_a_sgn,
	input [5:0]     din_uni_a_exp,
	input [21:0]    din_uni_a_man_dn,

	input           din_uni_b_sgn,
	input [5:0]     din_uni_b_exp,
	input [21:0]    din_uni_b_man_dn,


	output          dout_uni_y_sgn,
	output [5:0]    dout_uni_y_exp, 
	output [21:0]   dout_uni_y_man_dn
);






localparam ML_MANSIZE = 11;
localparam ML_EXPSIZE = 5;
localparam ML_EXPBIAS = 2**(ML_EXPSIZE-1)-1;
localparam ML_FPSIZE  = 1 + ML_EXPSIZE + ML_MANSIZE;
localparam AL_MANSIZE = 2 * ML_MANSIZE;
localparam AL_EXPSIZE = 1 + ML_EXPSIZE;
localparam AL_FPSIZE  = 1 + AL_EXPSIZE + AL_MANSIZE;
localparam AL_EXPBIAS = 2**(AL_EXPSIZE-1)-1;

localparam OPSIZE = 2;

localparam OPC_ADD29i  = 2'b11;
localparam OPC_MUL16i  = 2'b10;
localparam OPC_ADDSKIP = 2'b01;


localparam OPC_ADD29NORM = 2'b00;



wire [AL_EXPSIZE-1:0]   din_AL_expa = din_uni_a_exp;
wire [AL_EXPSIZE-1:0]   din_AL_expb = din_uni_b_exp;
wire [AL_MANSIZE-1:0]   din_AL_mana = din_uni_a_man_dn;
wire [AL_MANSIZE-1:0]   din_AL_manb = din_uni_b_man_dn;


wire [ML_EXPSIZE:0]     din_ML_expa = {1'b0,din_uni_a_exp[ML_EXPSIZE-1:0]};
wire [ML_EXPSIZE:0]     din_ML_expb = {1'b0,din_uni_b_exp[ML_EXPSIZE-1:0]};
reg [ML_MANSIZE-1:0]    din_ML_mana;
reg [ML_MANSIZE-1:0]    din_ML_manb;




wire s1_ml_ea_is_denorm = (|din_ML_expa) == 1'b0;
wire s1_ml_eb_is_denorm = (|din_ML_expb) == 1'b0;
always @* begin


	if(s1_ml_ea_is_denorm) din_ML_mana = {din_uni_a_man_dn[ML_MANSIZE-2:0],1'b0};
	else                   din_ML_mana = {1'b1, din_uni_a_man_dn[ML_MANSIZE-2:0]};
	
	if(s1_ml_eb_is_denorm) din_ML_manb = {din_uni_b_man_dn[ML_MANSIZE-2:0],1'b0};
	else                   din_ML_manb = {1'b1, din_uni_b_man_dn[ML_MANSIZE-2:0]};

end

`ifdef DEBUGINFO
	real a_real_FP16  [3:0];
	real a_real_FP29i [3:0];
	real b_real_FP16  [3:0];
	real b_real_FP29i [3:0];
	real a_real_FP16_s5;
	real a_real_FP29i_s5;
	real b_real_FP16_s5;
	real b_real_FP29i_s5;
	real y_real_FP29i;
	real y_real_FP29;
	real y_expected_ml;
	real y_expected_ad;
	integer many_expected_ml;	

	real tm;
	real ta;
	reg  mul_valid;
	reg  add_valid; 
	
	always @(*) begin
		a_real_FP16  [0] = (1.0-2.0*din_uni_a_sgn) * din_ML_mana * 2.0**(-10.0) * 2.0**(din_ML_expa-15.0);
		b_real_FP16  [0] = (1.0-2.0*din_uni_b_sgn) * din_ML_manb * 2.0**(-10.0) * 2.0**(din_ML_expb-15.0);


	
		a_real_FP29i [0] = (1.0-2.0*din_uni_a_sgn) * din_AL_mana * 2.0**(-21.0) * 2**(din_AL_expa-31.0);
		b_real_FP29i [0] = (1.0-2.0*din_uni_b_sgn) * din_AL_manb * 2.0**(-21.0) * 2**(din_AL_expb-31.0);
		y_real_FP29i     = (1.0-2.0*dout_uni_y_sgn) * dout_uni_y_man_dn * 2.0**(-21.0 + dout_uni_y_exp - 31.0);
		y_expected_ml = a_real_FP16_s5  * b_real_FP16_s5;
		y_expected_ad = a_real_FP29i_s5 + b_real_FP29i_s5;
		
		mul_valid = 0;
		if(y_real_FP29i == y_expected_ml) begin
			mul_valid = 1;
		end else begin
			if(y_expected_ml!=0.0)
				tm = (y_real_FP29i-y_expected_ml)/(y_expected_ml);
			else tm = y_real_FP29i; 
			if(tm>=0) mul_valid = ( tm)<0.0001;
			else      mul_valid = (-tm)<0.0001;
		end

		add_valid = 0;
		if(y_real_FP29i == y_expected_ad) begin
			add_valid = 1;
		end else begin
			if(y_expected_ad!=0.0)
				ta = (y_real_FP29i - y_expected_ad)/y_expected_ad;
			else ta = y_real_FP29i;	
			if(ta>=0) add_valid = ( ta)<0.0001;
			else      add_valid = (-ta)<0.0001; 
		end
	end

	integer i;
	always @(posedge clk) begin
		for(i=3;i>0;i=i-1) begin
			a_real_FP16 [i]  <= a_real_FP16 [i-1];
			a_real_FP29i [i] <= a_real_FP29i [i-1];
			b_real_FP16 [i]  <= b_real_FP16 [i-1];
			b_real_FP29i [i] <= b_real_FP29i [i-1];
		end
		if(s4_opcode_r==OPC_MUL16i) begin
			a_real_FP16_s5  <= a_real_FP16[3];
			b_real_FP16_s5  <= b_real_FP16[3];
		end else begin
			a_real_FP29i_s5 <= a_real_FP29i[3];
			b_real_FP29i_s5 <= b_real_FP29i[3];
		end
	end
`endif






reg [OPSIZE-1:0] s1_opcode;
always @* begin
	s1_opcode = opcode;
end







wire [AL_EXPSIZE:0]   s1_ea_sub_eb = {1'b0,din_uni_a_exp} - {1'b0,din_uni_b_exp};
wire                  s1_ea_lt_eb  = s1_ea_sub_eb[AL_EXPSIZE];
wire                  s1_ea_gte_eb  = ~s1_ea_lt_eb;
wire [AL_EXPSIZE-1:0] s1_ea_sub_eb_abs = s1_ea_gte_eb ?  s1_ea_sub_eb[AL_EXPSIZE-1:0] : {~s1_ea_sub_eb+1'b1};

wire       s1_addsubn = ~(din_uni_a_sgn ^ din_uni_b_sgn);


wire [AL_MANSIZE-1:0]	s1_mmux_lhs;
wire [AL_MANSIZE-1:0]	s1_mmux_rhs;
xchg #(.DWIDTH(AL_MANSIZE)) s1_u_manxchg(
	.ia(din_uni_a_man_dn),
	.ib(din_uni_b_man_dn),
	.xchg(s1_ea_lt_eb),
	.oa(s1_mmux_lhs),
	.ob(s1_mmux_rhs)
);


localparam  PPSIZE = ML_MANSIZE+1;
wire [ML_MANSIZE+2:0] s1_br4enc_input = {2'b00, din_ML_manb, 1'b0};
wire [(PPSIZE)*6-1:0]		    s1_br4_pp;
wire [5:0]                      s1_br4_s;
genvar gi;
generate
	for(gi=0;gi<6;gi=gi+1) begin : gen_br4enc

		booth_ppgen_r4 s1_u_br4ppgen (
			.a(din_ML_mana),
			.br4(s1_br4enc_input[2*(gi+1):2*gi]),
			.o(s1_br4_pp[PPSIZE*(gi+1)-1:PPSIZE*(gi)]),
			.s(s1_br4_s[gi])
		);
	end
endgenerate





reg [OPSIZE-1:0]     s2_opcode_r;
reg                  s2_sa_r;
reg                  s2_sb_r;
reg [AL_EXPSIZE-1:0]	s2_ea_r;
reg [AL_EXPSIZE-1:0]	s2_eb_r;

always @(posedge clk) begin
	s2_opcode_r <= s1_opcode;
	s2_sa_r     <= din_uni_a_sgn;
	s2_sb_r     <= din_uni_b_sgn;
	if(s1_opcode == OPC_ADD29i) begin
		s2_ea_r   <= din_uni_a_exp;
		s2_eb_r   <= din_uni_b_exp;
	end else if(s1_opcode == OPC_MUL16i) begin
		s2_ea_r   <= {{(AL_EXPSIZE-ML_EXPSIZE){1'b0}},din_ML_expa};
		s2_eb_r   <= {{(AL_EXPSIZE-ML_EXPSIZE){1'b0}},din_ML_expb};
	end
end


reg [AL_EXPSIZE-1:0] s2_ea_sub_eb_abs_r;
reg                  s2_ea_gte_eb_r;
wire                 s2_ea_lt_eb = ~s2_ea_gte_eb_r;
reg [AL_MANSIZE-1:0] s2_mmux_lhs_r;
reg [AL_MANSIZE-1:0] s2_mmux_rhs_r;
reg                  s2_addsubn_r;
always @(posedge clk) begin
	s2_ea_sub_eb_abs_r <= s1_ea_sub_eb_abs;
	s2_ea_gte_eb_r     <= s1_ea_gte_eb;
	s2_mmux_lhs_r      <= s1_mmux_lhs;
	s2_mmux_rhs_r      <= s1_mmux_rhs;
	s2_addsubn_r       <= s1_addsubn;
end





wire              s2_lhs_is_zero = ~(|s2_mmux_lhs_r);

wire [OPSIZE-1:0] s2_opcode_mod;
assign s2_opcode_mod = ((s2_opcode_r==OPC_ADD29i)&&s2_lhs_is_zero) ? OPC_ADDSKIP : s2_opcode_r;




wire [AL_MANSIZE-1:0] s2_bsr_out_gated = s2_mmux_rhs_r >> s2_ea_sub_eb_abs_r;



wire [AL_MANSIZE-1:0] s2_mmux2_lhs = s2_mmux_lhs_r;
wire [AL_MANSIZE-1:0] s2_mmux2_rhs = s2_bsr_out_gated;
wire [AL_MANSIZE:0]   s2_mmux3_rhs_addsub  = s2_addsubn_r ? s2_mmux2_rhs : ~s2_mmux2_rhs;



wire [AL_MANSIZE:0]   s2_mmux3_lhs_addsub;
assign s2_mmux3_lhs_addsub = (s2_lhs_is_zero) ? {1'b0,s2_mmux_rhs_r} : {1'b0, s2_mmux2_lhs};



reg [PPSIZE*6-1:0]		s2_br4_pp_r;
reg [5:0]               s2_br4_s_r;
always @(posedge clk) begin

	if(s1_opcode==OPC_MUL16i) begin
		s2_br4_pp_r  <= s1_br4_pp;
		s2_br4_s_r   <= s1_br4_s;
	end
end


wire [PPSIZE-1:0]  pp0 = s2_br4_pp_r[PPSIZE*1-1:PPSIZE*0];
wire [PPSIZE-1:0]  pp1 = s2_br4_pp_r[PPSIZE*2-1:PPSIZE*1];
wire [PPSIZE-1:0]  pp2 = s2_br4_pp_r[PPSIZE*3-1:PPSIZE*2];
wire [PPSIZE-1:0]  pp3 = s2_br4_pp_r[PPSIZE*4-1:PPSIZE*3];
wire [PPSIZE-1:0]  pp4 = s2_br4_pp_r[PPSIZE*5-1:PPSIZE*4];
wire [PPSIZE-1:0]  pp5 = s2_br4_pp_r[PPSIZE*6-1:PPSIZE*5];
reg [PPSIZE+7-1:0] s2_ps0;
reg [PPSIZE+4-1:0] s2_ps1;
wire               s2_s2 = s2_br4_s_r[2];


always @* begin
	s2_ps0 =          {4'b0,{!s2_br4_s_r[0]},{2{s2_br4_s_r[0]}},pp0};
	s2_ps0 = s2_ps0 + {4'b0001,{!s2_br4_s_r[1]},pp1,1'b0,s2_br4_s_r[0]};
	s2_ps0 = s2_ps0 + {2'b01,{!s2_br4_s_r[2]},pp2,1'b0,s2_br4_s_r[1],2'b0};
	s2_ps1 =          {3'b001,{!s2_br4_s_r[3]},pp3};
	s2_ps1 = s2_ps1 + {1'b1,{!s2_br4_s_r[4]},pp4,1'b0,s2_br4_s_r[3]};
	s2_ps1 = s2_ps1 + {pp5,1'b0,s2_br4_s_r[4],2'b0};
end







reg [OPSIZE-1:0]     s3_opcode_r;
reg                  s3_sa_r;
reg                  s3_sb_r;
reg [AL_EXPSIZE-1:0]	s3_ea_r;
reg [AL_EXPSIZE-1:0]	s3_eb_r;
always @(posedge clk) begin
	if(s2_lhs_is_zero&&(s2_opcode_r==OPC_ADD29i)) 
                       s3_opcode_r <= OPC_ADDSKIP;
	else               s3_opcode_r <= s2_opcode_r;
	s3_ea_r   <= s2_ea_r;
	s3_eb_r   <= s2_eb_r;
	s3_sa_r   <= s2_sa_r;
	s3_sb_r   <= s2_sb_r;
end


reg [AL_MANSIZE:0]  s3_lhs_r;
reg [AL_MANSIZE:0]  s3_rhs_r;
reg                 s3_addsubn_r;

always @(posedge clk) begin
	s3_lhs_r     <= s2_mmux3_lhs_addsub;
	s3_rhs_r     <= s2_mmux3_rhs_addsub;
	s3_addsubn_r <= s2_addsubn_r;
end


reg                     s3_ea_gte_eb_r;
always @(posedge clk) begin
	s3_ea_gte_eb_r <= s2_ea_gte_eb_r;
end


reg [21:0]                s3_mulout;
reg [PPSIZE+7-1:0]        s3_ps0_r;
reg [PPSIZE+4-1:0]        s3_ps1_r;
reg                       s3_s2_r;
always @(posedge clk) begin
	s3_ps0_r <= s2_ps0;
	s3_ps1_r <= s2_ps1;
	s3_s2_r  <= s2_s2;
end


reg [AL_MANSIZE:0]   s3_alumux_lhs;
reg [AL_MANSIZE:0]   s3_alumux_rhs;
reg                  s3_alumux_cin;
wire [31:0]  s3_alu_out;
reg [1:0] dbg_s3_alumux_state;
always @(*) begin
	if(s3_opcode_r==OPC_ADD29i) begin

		dbg_s3_alumux_state = 0;
		s3_alumux_lhs = s3_lhs_r;
		s3_alumux_rhs = s3_rhs_r;
		s3_alumux_cin = ~s3_addsubn_r;
	end else if (s3_opcode_r == OPC_MUL16i) begin


		dbg_s3_alumux_state = 1;
		s3_alumux_lhs = {3'b0,s3_ps0_r}; 
		s3_alumux_rhs = {s3_ps1_r,1'b0,s3_s2_r,4'b0};
		s3_alumux_cin = 1'b0;
	end else begin

		s3_alumux_lhs = {(AL_MANSIZE+1){1'bx}};
		s3_alumux_rhs = {(AL_MANSIZE+1){1'bx}};
		s3_alumux_cin = 1'bx;
	end
end

cla_adder #(.DATA_WID(32)) s3_s4_u_cla(
	.in1      ({{9{s3_alumux_lhs[AL_MANSIZE]}},s3_alumux_lhs}),
	.in2      ({{9{s3_alumux_rhs[AL_MANSIZE]}},s3_alumux_rhs}),
	.carry_in (s3_alumux_cin),
	.sum      (s3_alu_out   ),
	.carry_out(             )
);


reg [AL_MANSIZE:0] s3_mmux_y;
wire s3_alu_of = s3_alu_out[AL_MANSIZE+1];

always @* begin
	case(s3_opcode_r) 
	OPC_ADDSKIP:	s3_mmux_y = s3_lhs_r;
	OPC_ADD29i:		s3_mmux_y = s3_alu_out[AL_MANSIZE:0];
	OPC_MUL16i:		s3_mmux_y = {1'b0,s3_alu_out[AL_MANSIZE-1:0]};
	endcase
end














reg [OPSIZE-1:0]     s4_opcode_r;
reg [AL_MANSIZE:0]   s4_many_r;
reg [AL_MANSIZE:0]   s4_lzdi_r;
reg [AL_EXPSIZE-1:0] s4_ea_r;
reg [AL_EXPSIZE-1:0] s4_eb_r;
reg                  s4_ea_gte_eb_r;
reg                  s4_addsubn_r;
reg                  s4_sa_r;
reg                  s4_sb_r;
reg                  s4_flipsign_r;
always @(posedge clk) begin
	if((s3_opcode_r==OPC_ADD29i) && s3_alu_of)  begin
		s4_flipsign_r <= 1;
	end else begin
		s4_flipsign_r <= 0;
	end
	s4_many_r      <= s3_mmux_y;
	s4_opcode_r    <= s3_opcode_r;
	s4_ea_r        <= s3_ea_r;
	s4_eb_r        <= s3_eb_r;
	s4_ea_gte_eb_r <= s3_ea_gte_eb_r;
	s4_addsubn_r   <= s3_addsubn_r;
	s4_sa_r        <= s3_sa_r;
	s4_sb_r        <= s3_sb_r;
end

wire [AL_MANSIZE:0] s4_lzdi_fp;

wire s4_compl2_en = s4_flipsign_r & (s4_opcode_r!=OPC_ADDSKIP);

cla_adder #(.DATA_WID(AL_MANSIZE+1)) s4_u_compl2(
	.in1      (s4_flipsign_r ? ~ s4_many_r : s4_many_r),
	.in2      ({AL_MANSIZE+1{1'b0}}),
	.carry_in (s4_flipsign_r),
	.sum      (s4_lzdi_fp   ),
	.carry_out(             )
);


wire [4:0]  s4_lzd;
wire [31:0] s4_lzdi = {s4_lzdi_fp,9'b0};

count_lead_zero #(.W_IN(32)) s4_u_lzd(.in(s4_lzdi), .out(s4_lzd));







reg [OPSIZE-1:0]     s5_opcode_r;
reg                  s5_addsubn_r;
reg                  s5_sa_r;
reg                  s5_sb_r;
reg                  s5_flipsign_r;
always @(posedge clk) begin
	s5_opcode_r  <= s4_opcode_r;
	s5_addsubn_r <= s4_addsubn_r;
	s5_sa_r      <= s4_sa_r;
	s5_sb_r      <= s4_sb_r;
	s5_flipsign_r<= s4_flipsign_r;
end


reg [AL_MANSIZE:0] s5_many_r;
reg [4:0]          s5_lzd_r;
reg [4:0]          s5_shiftbias;
always @(posedge clk) begin
	s5_many_r    <= s4_lzdi_fp;
	s5_lzd_r     <= s4_lzd;
end

always @* s5_shiftbias = s5_lzd_r;
wire [31:0]          s5_bsl_out;
reg [AL_MANSIZE-1:0] s5_many_skip_r;
always @(posedge clk) 
	if(s4_opcode_r==OPC_ADDSKIP) 
		s5_many_skip_r <= s4_many_r;
bsl #(.SWIDTH(5)) s5_u_bsl (
	.din    ({s5_many_r,9'b0}),
	.s      (s5_shiftbias     ),
	.filler (1'b0             ),
	.dout   (s5_bsl_out       )
);



reg [AL_EXPSIZE-1:0] s5_ea_r;
reg [AL_EXPSIZE-1:0] s5_eb_r;
reg                  s5_ea_gte_eb_r;
wire                 s5_ea_lt_eb = ~s5_ea_gte_eb_r;
always @(posedge clk) begin
	s5_ea_r        <= s4_ea_r;
	s5_eb_r        <= s4_eb_r;
	s5_ea_gte_eb_r <= s4_ea_gte_eb_r;
end


wire [AL_EXPSIZE:0]   s5_expadj_skip;
wire [AL_EXPSIZE:0]   s5_expadj_mul;
wire [AL_EXPSIZE:0]   s5_expadj_add;
reg  [AL_EXPSIZE:0]   s5_expadj_final;
reg                   s5_sign_final;
reg [AL_MANSIZE-1:0]  s5_many_final;

assign s5_expadj_mul  = {1'b0,s5_ea_r} + {1'b0,s5_eb_r} - 2*ML_EXPBIAS + AL_EXPBIAS + 1;

assign s5_expadj_add  = s5_ea_gte_eb_r ?  {1'b0,s5_ea_r} : {1'b0,s5_eb_r};
assign s5_expadj_skip = s5_ea_gte_eb_r ?  {1'b0,s5_eb_r} : {1'b0,s5_ea_r};
wire   s5_sign_skip   = s5_ea_gte_eb_r ?  s5_sb_r : s5_sa_r;


always @* begin
	if(s5_opcode_r == OPC_ADD29i) begin
		s5_expadj_final = s5_expadj_add + 1 - s5_lzd_r;
		s5_sign_final   = ((s5_addsubn_r)? s5_sa_r : s5_ea_lt_eb ^ s5_sa_r) ^ s5_flipsign_r;
		s5_many_final   = s5_bsl_out[31:10];
	end else if (s5_opcode_r == OPC_MUL16i) begin
		s5_many_final   = s5_bsl_out[31:10];
		if((|s5_many_final)==0) begin
			s5_expadj_final = 0;
			s5_sign_final   = 0;
		end else begin
			s5_expadj_final = s5_expadj_mul + 1 - s5_lzd_r;
			s5_sign_final   = ~s5_addsubn_r;
		end
	end else if (s5_opcode_r == OPC_ADDSKIP) begin

		s5_expadj_final = {1'bx, s5_expadj_skip};
		s5_sign_final   = s5_sign_skip;
		s5_many_final   = s5_many_skip_r;

	end else begin
		s5_expadj_final = s5_expadj_add + 1 - s5_lzd_r - AL_EXPBIAS + ML_EXPBIAS;
		s5_sign_final   = s5_sign_skip;
		s5_many_final   = {12'b0,s5_bsl_out[32-1-1:32-10-1]};
	end	
end


assign dout_uni_y_exp    = s5_expadj_final[AL_EXPSIZE-1:0];
assign dout_uni_y_sgn    = s5_sign_final;
assign dout_uni_y_man_dn = s5_many_final;

endmodule