11module int18_to_bf16_lzd #(
2- parameter FRAC_BITS = 8 // Number of fractional bits in Q10.8
2+ parameter FRAC_BITS = 8
33)(
44 input wire signed [17 :0 ] acc,
55 output reg [15 :0 ] bf16
@@ -13,54 +13,37 @@ module int18_to_bf16_lzd #(
1313 reg [7 :0 ] exp;
1414 reg [6 :0 ] mant;
1515 reg [17 :0 ] normalized;
16-
17- // Leading zero detector
18- function [4 :0 ] lzd;
19- input [17 :0 ] x ;
20- reg [17 :0 ] scan;
21- begin
22- // Priority encode from MSB to LSB
23- scan = x ;
24-
25- casez (scan)
26- 18'b1 ?????????????????: lzd = 5'd0 ;
27- 18'b01 ????????????????: lzd = 5'd1 ;
28- 18'b001 ???????????????: lzd = 5'd2 ;
29- 18'b0001 ??????????????: lzd = 5'd3 ;
30- 18'b00001 ?????????????: lzd = 5'd4 ;
31- 18'b000001 ????????????: lzd = 5'd5 ;
32- 18'b0000001 ???????????: lzd = 5'd6 ;
33- 18'b00000001 ??????????: lzd = 5'd7 ;
34- 18'b000000001 ?????????: lzd = 5'd8 ;
35- 18'b0000000001 ????????: lzd = 5'd9 ;
36- 18'b00000000001 ???????: lzd = 5'd10 ;
37- 18'b000000000001 ??????: lzd = 5'd11 ;
38- 18'b0000000000001 ?????: lzd = 5'd12 ;
39- 18'b00000000000001 ????: lzd = 5'd13 ;
40- 18'b000000000000001 ???: lzd = 5'd14 ;
41- 18'b0000000000000001 ??: lzd = 5'd15 ;
42- 18'b00000000000000001 ?: lzd = 5'd16 ;
43- 18'b000000000000000001 : lzd = 5'd17 ;
44- default : lzd = 5'd18 ; // All zeros
45- endcase
46- end
47- endfunction
48-
16+
17+ // ===================== HIERARCHICAL LEADING ZERO DETECTOR =====================
18+ wire [2 :0 ] lz_hi, lz_mid, lz_lo;
19+ wire nz_hi, nz_mid, nz_lo;
20+
21+ lzd6 lzd_hi (.x (mag[17 :12 ]), .lz(lz_hi), .nz(nz_hi));
22+ lzd6 lzd_mid (.x (mag[11 :6 ]), .lz(lz_mid), .nz(nz_mid));
23+ lzd6 lzd_lo (.x (mag[5 :0 ]), .lz(lz_lo), .nz(nz_lo));
24+
4925 always @(* ) begin
5026 // Default assignments (prevent latches)
5127 sign = acc[17 ];
5228 mag = sign ? - acc : acc;
5329 bf16 = 16'h0 ;
54-
5530 lz = 5'd0 ;
5631 exp_unbiased= 9 'sd0;
5732 exp = 8'd0 ;
5833 mant = 7'd0 ;
5934 normalized = 18'd0 ;
60-
35+
6136 if (mag != 0 ) begin
62- lz = lzd(mag);
63-
37+ // Combine hierarchical LZD results with proper offsets
38+ if (nz_hi)
39+ lz = {2'b00 , lz_hi}; // bits [17:12]: offset 0
40+ else if (nz_mid)
41+ lz = 5'd6 + {2'b00 , lz_mid}; // bits [11:6]: offset 6
42+ else if (nz_lo)
43+ lz = 5'd12 + {2'b00 , lz_lo}; // bits [5:0]: offset 12
44+ else
45+ lz = 5'd18 ;
46+
6447 // MSB position is (17 - lz), binary point at FRAC_BITS
6548 exp_unbiased = 9 '(17 ) - 9 '(lz) - 9 '(FRAC_BITS);
6649
@@ -70,12 +53,32 @@ module int18_to_bf16_lzd #(
7053 bf16 = {sign, 8'hFF , 7'd0 }; // overflow
7154 end else begin
7255 exp = exp_unbiased + BF16_BIAS;
73-
7456 // normalize so MSB ends up at bit 17
7557 normalized = mag << lz;
7658 mant = normalized[16 :10 ];
7759 bf16 = {sign, exp, mant};
7860 end
7961 end
8062 end
63+ endmodule
64+
65+ // ===================== 6-BIT LEADING ZERO DETECTOR =====================
66+ module lzd6 (
67+ input wire [5 :0 ] x ,
68+ output reg [2 :0 ] lz,
69+ output wire nz // Non-zero flag
70+ );
71+ assign nz = | x ;
72+
73+ always @(* ) begin
74+ casez (x )
75+ 6'b1 ?????: lz = 3'd0 ;
76+ 6'b01 ????: lz = 3'd1 ;
77+ 6'b001 ???: lz = 3'd2 ;
78+ 6'b0001 ??: lz = 3'd3 ;
79+ 6'b00001 ?: lz = 3'd4 ;
80+ 6'b000001 : lz = 3'd5 ;
81+ default : lz = 3'd6 ;
82+ endcase
83+ end
8184endmodule
0 commit comments