pub const FP16_MUL_V: &str = r#"module fp16_mul(input [15:0] a, input [15:0] b, output reg [15:0] y);
localparam [15:0] QNAN = 16'h7E00;
reg sa, sb, rs;
reg [4:0] ea, eb;
reg [9:0] ma, mb;
reg azero,bzero,ainf,binf,anan,bnan,ha,hb;
reg [10:0] siga, sigb, sa_sh, sb_sh, fsig;
reg [4:0] lza, lzb;
reg [21:0] prod, norm;
reg signed [11:0] exp_sum, e, fe, bexp;
reg [13:0] mant;
reg g, r, s, l, up;
reg [11:0] rnd, rr, rsh;
reg [63:0] wide;
reg g2, r2, s2, l2, up2;
function [4:0] clz11(input [10:0] v);
integer j; reg dn;
begin clz11 = 5'd11; dn = 1'b0;
for (j = 10; j >= 0; j = j - 1) if (v[j] && !dn) begin clz11 = 5'd10 - j[4:0]; dn = 1'b1; end
end
endfunction
always @(*) begin
sa = a[15]; sb = b[15]; rs = sa ^ sb;
ea = a[14:10]; eb = b[14:10];
ma = a[9:0]; mb = b[9:0];
azero=(ea==5'd0)&&(ma==10'd0); bzero=(eb==5'd0)&&(mb==10'd0);
ainf =(ea==5'h1F)&&(ma==10'd0); binf =(eb==5'h1F)&&(mb==10'd0);
anan =(ea==5'h1F)&&(ma!=10'd0); bnan =(eb==5'h1F)&&(mb!=10'd0);
ha=(ea!=5'd0); hb=(eb!=5'd0);
siga={ha,ma}; sigb={hb,mb};
y=16'd0;
lza=5'd0; lzb=5'd0; sa_sh=11'd0; sb_sh=11'd0; prod=22'd0; norm=22'd0;
exp_sum=12'sd0; e=12'sd0; fe=12'sd0; bexp=12'sd0; mant=14'd0; rnd=12'd0; rr=12'd0;
fsig=11'd0; rsh=12'd0; wide=64'd0; g=0;r=0;s=0;l=0;up=0;g2=0;r2=0;s2=0;l2=0;up2=0;
if (anan || bnan) y = QNAN;
else if ((ainf && bzero) || (binf && azero)) y = QNAN;
else if (ainf || binf) y = {rs, 5'h1F, 10'd0};
else if (azero || bzero) y = {rs, 15'd0};
else begin
lza = clz11(siga); lzb = clz11(sigb);
exp_sum = (ea!=5'd0 ? $signed({7'd0,ea})-12'sd15 : -12'sd14)
+ (eb!=5'd0 ? $signed({7'd0,eb})-12'sd15 : -12'sd14)
- $signed({7'd0,lza}) - $signed({7'd0,lzb});
sa_sh = (siga << lza); sb_sh = (sigb << lzb);
prod = sa_sh * sb_sh;
if (prod[21]) begin norm = prod; e = exp_sum + 12'sd1; end
else begin norm = prod << 1; e = exp_sum; end
if (e < -12'sd14) begin
wide = ({42'd0, norm}) >> 12'd8;
if (|(({42'd0, norm}) & ((64'd1 << 12'd8) - 64'd1))) wide[0] = 1'b1;
rsh = (-12'sd14) - e;
if (rsh >= 12'd64) begin s2 = |wide; wide = 64'd0; wide[0] = s2; end
else if (rsh != 12'd0) begin
if (|(wide & ((64'd1 << rsh) - 64'd1))) begin wide = wide >> rsh; wide[0] = 1'b1; end
else wide = wide >> rsh;
end
g2=wide[2]; r2=wide[1]; s2=wide[0]; l2=wide[3];
up2 = g2 & (r2 | s2 | l2);
rr = {1'b0, wide[13:3]} + (up2 ? 12'd1 : 12'd0);
if (rr[10]) y = {rs, 5'd1, rr[9:0]};
else y = {rs, 5'd0, rr[9:0]};
end else begin
mant = {norm[21:11], norm[10], norm[9], (|norm[8:0])};
g=mant[2]; r=mant[1]; s=mant[0]; l=mant[3];
up = g & (r | s | l);
rnd = {1'b0, mant[13:3]} + (up ? 12'd1 : 12'd0);
if (rnd[11]) begin fsig = rnd[11:1]; fe = e + 12'sd1; end
else begin fsig = rnd[10:0]; fe = e; end
if (fe > 12'sd15) y = {rs, 5'h1F, 10'd0};
else if (fe < -12'sd14) y = {rs, 5'd1, fsig[9:0]};
else begin bexp = fe + 12'sd15; y = {rs, bexp[4:0], fsig[9:0]}; end
end
end
end
endmodule
"#;Expand description
The synthesizable combinational IEEE-754 f16 multiplier — the f32 multiplier narrowed to binary16
(11-bit significand product = 22 bits, leading at 20/21). Proven bit-exact to f16_mul under iverilog.