53 / 63 · 概念
定點數、捨入與飽和
以 W,F 格式定義數值範圍,設計 guard、sticky 的捨入至偶數,以及捨入後飽和。
單元可免費閱讀,註冊課程即可儲存學習進度。
先備知識:signed 加法與乘法的寬度、算術右移與 overflow。
以契約定義位元序列的小數點位置
定點數定點數預先固定小數點位置,對整數位元序列套用固定倍率來表示數值。必須一併指定位寬、是否帶符號與小數位元數。將整數 X 解讀為 ,硬體並沒有儲存小數點位元。本課定義 signed 總寬度 W 包含符號位,F 為小數位元數。不同文獻的 Q 記法對整數部分是否含符號位有差異,因此介面同時標 W,F 較清楚。
W=8,F=4 時,間隔 1/16,範圍 −8~7.9375。此契約的 0x18 是 1.5,不是整數 24;同樣 0x18 若 F=3 就是 3。接好導線不代表數值意義也吻合,應記錄各連接埠的 scale。
加法前先對齊小數點。F 不同時,可把較小 F 的一方充分擴展再左移,或依指定捨入規則縮減較大 F。W、F 相同的兩數精確相加需要 W+1 位元,F 不變。乘法則相乘 raw 整數,小數位數相加。
兩個 8 位元 F=4 的完整乘積是 signed 16 位元 F=8。要輸出 8 位元 F=4,須先減少四個小數位,再檢查 signed 8 位元範圍。若先把乘積截成 8 位元,後續飽和電路便無法知道原始大小。
截除與捨入的差別
丟棄 d 位的算術右移為 ,負數也向下。例如 ,精確商 −1.5,但 q=−2,與向零截斷不同。不能假設正數適用的「直接取高位」,對負數也有相同誤差性質。
設計 round-to-nearest, ties-to-even:取最近值,恰在中間時取偶數整數。被丟棄區的最高位為 guard g,其餘位元 OR 為 sticky t,保留 q 的最低位為 l。
g=0 表示小於一半,保持;g=1,t=1 表示大於一半,向上加 1;g=1,t=0 正好一半,只有 q 為奇數時加 1。負數也同規則,因採 floor 商 q 與餘數 時,永遠 。
例如 −24/16=−1.5,q=−2 是偶數,結果 −2;−40/16=−2.5,q=−3 是奇數,結果仍 −2。「負數一律減 1」的額外規則反而錯誤。未飽和時,最終數值誤差不超過輸出 LSBLSB是位權最低的位元。須同時確認表示方向與索引規則。 詳細內容 的一半。Ties-to-even 不保證所有輸入分布的平均誤差必為 0,但可減少中點總向同側偏移的偏差。
將 16 位元 F=8 的 raw P=2040 轉成 8 位元 F=4:127.5 先捨入為偶數 128,再限為 signed 8 位元最大值 127。直到最後儲存前都要保留寬度。
- 輸入 P=2040: 16 位元 · F=8
- 縮小尺度: 2040 / 16 = 127.5
- 中間值取偶數: 捨入後 raw = 128
- 飽和後儲存: raw 127 → 7.9375
完成捨入後才做飽和
飽和將超過最大值者限為最大值,低於最小值者限為最小值。與 wrap 不同,大正數不會翻成負數。但已縮窄並回捲的值,無法再正確飽和。
以下完整組合模組將 signed 16 位元 F=8 轉成 signed 8 位元 F=4。d 固定為 4,guard=p[3]、sticky=p[2:0]。捨入遞增與範圍比較在 17 位元 signed 空間完成,最後才取 8 位元。
module requantize (
input logic signed [15:0] p,
output logic signed [7:0] y,
output logic saturated
);
logic signed [16:0] wide, q, rounded;
logic inc;
always_comb begin
wide = {p[15], p};
q = wide >>> 4;
inc = p[3] & ((|p[2:0]) | q[0]);
rounded = q + (inc ? 17'sd1 : 17'sd0);
saturated = 1'b0;
if (rounded > 17'sd127) begin
y = 8'sh7f;
saturated = 1'b1;
end else if (rounded < -17'sd128) begin
y = 8'sh80;
saturated = 1'b1;
end else begin
y = rounded[7:0];
end
end
endmoduleP=2040 時,P/16=127.5 先捨入到偶數 128,再飽和為 127,最終值為 7.9375。只檢查捨入前的 q=127,會漏掉這次超出範圍的情況。Saturated 表示數值超出範圍而被限制,不只是丟失低小數位。
泛化模組時,d=0 沒有待丟位元,d=1 沒有 sticky 區域,需分開處理。把越界 part-select 藏在條件式中,不一定能消除 elaboration 錯誤。
捨入與飽和增加加法器、比較器、MUX多工器是依選擇訊號,將多個輸入之一連至輸出的組合電路。必須明確定義選擇位元與輸入編號的對應關係。 詳細內容 的成本及延遲,需作為獨立政策選擇。AMD 定點數格式文件也有此區分。累加多項時,先決定是否保留中間寬度、最後只轉換一次。每級飽和可能破壞加法結合律,每級捨入則可能反覆累積小誤差。
自己試試看
將 signed 16 位元 F=8 的 P 轉成 signed 8 位元 F=4。P=24,40,−24,−40,2040 時,求 floor 商 q、guard/sticky、捨入整數、最終 raw 輸出與實際值。2040 若先做飽和檢查,有何問題?
查看解說
所有輸入低四位都是 1000,故 guard=1、sticky=0。P=24:q=1(奇數)→2,raw=2,實際值 0.125。P=40:q=2(偶數)→2,raw=2,0.125。P=−24:q=−2(偶數)→−2,raw=−2,−0.125。P=−40:q=−3(奇數)→−2,raw=−2,−0.125。P=2040:q=127(奇數)→128,超過 signed 8 位元最大值,故 raw=127、實際值 7.9375、saturated=1。若先只檢查 q=127,再在 8 位元加 1,可能回捲成 0x80 而輸出 −8;須在寬 signed 值完成遞增與比較。