← 回到課程目錄Back to course index
Verilog · FPGA · 高中生也看得懂for high-school readers

逐位元除法與開根號Bit-by-Bit Division and Square Root

FPGA 不一定要一瞬間算出答案。這篇用國小學過的直式除法,說明兩個「每個時脈算出答案一個位元」的硬體電路:div_seq 和 sqrt_seq。

An FPGA doesn't have to produce an answer all at once. Using the long division you learned in primary school, this page explains two circuits that compute one bit of the answer per clock cycle: div_seq and sqrt_seq.

每一步只問一件事:這一位填 1 會不會太大?Every step asks one question: is a 1 in this bit too big?

1核心想法:一位一位試The idea: try one bit at a time

回想十進位的直式除法,算 157 ÷ 12:

Recall decimal long division, for 157 ÷ 12:

  1. 看 15:12 放得進去 1 次,商寫 1,餘 3。Look at 15: 12 goes in once. Write 1, remainder 3.
  2. 把 7 拉下來,變成 37:12 放得進去 3 次,商寫 3,餘 1。Bring down 7 to make 37: 12 goes in 3 times. Write 3, remainder 1.
  3. 答案:商 13,餘 1。Answer: quotient 13, remainder 1.

每一步做的事都一樣:拉下一位 → 試試看放不放得進去 → 決定這一位答案 → 更新餘數。

Every step is the same: bring down a digit → see whether the divisor fits → decide this digit → update the remainder.

換成二進位更簡單,因為每一位答案只可能是 0 或 1。只要比大小,夠減就填 1 並減掉,不夠就填 0。硬體只需要一個比較器和一個減法器,每個時脈重複用一次。

Binary is even simpler, because each answer bit can only be 0 or 1. Just compare: if it fits, write 1 and subtract; if not, write 0. The hardware needs one comparator and one subtractor, reused once per clock.

好處Benefit

電路很小。88 位元的除法若一次算完,FPGA 工具甚至合成不出來(Quartus 的除法 IP 上限是 64 位元)。The circuit is small. An 88-bit divide done all at once can't even be synthesised (Quartus's divider IP stops at 64 bits).

代價Cost

比較慢。答案有幾個位元,就要幾個時脈。36 位元的商要 36 個時脈。It's slower. One clock per answer bit, so a 36-bit quotient takes 36 clocks.

2除法器 div_seqThe divider div_seq

算 quotient = dividend ÷ divisor。有三個參數:

It computes quotient = dividend ÷ divisor, with three parameters:

參數Parameter意思Meaning例子Example
WN被除數 dividend 有幾個位元Width of the dividend88
WD除數 divisor 有幾個位元Width of the divisor44
WQ商 quotient 有幾個位元,也是要算幾個時脈Width of the quotient, which is also the number of clocks36

暫存器各自的角色What each register does

名稱Name意思Meaning對應直式除法的In long division
d除數,算的過程中不變The divisor, fixed during the run除數The divisor
rem目前的餘數The current remainder每一步減完剩下的數What's left after each subtraction
lo被除數還沒拉下來的位元Dividend bits not yet brought down還沒用到的位數Digits not used yet
q目前算到一半的商The partial quotient商寫到一半The answer written so far
cnt還剩幾步Steps left—
busy / done正在算 / 算完了(只亮一個時脈)Working / finished (high for one clock)—

最關鍵的兩行The two key lines

wire [WD:0] rem_next = {rem[WD-1:0], lo[WQ-1]};  // rem × 2 + next bit  餘數 × 2 + 拉下的那一位
wire        fits     = (rem_next >= {1'b0, d});  // fits → this bit is 1  夠減 → 這位商是 1

{A, B} 是把位元接起來。把餘數左移一位再補上新的一位,等於「乘 2 再加上新位」,就像十進位的「3 拉下 7 變成 37」是 3 × 10 + 7。

{A, B} joins bits together. Shifting the remainder left by one and appending the new bit means "times 2, plus the new bit", just as bringing down 7 after 3 gives 37 = 3 × 10 + 7 in decimal.

為什麼 rem 要多一個位元?Why does rem have one extra bit?餘數本來小於 d,乘 2 再加 1 後最大是 2d − 1,可能比 d 多一位,所以 rem 是 [WD:0],比除數多留一格。The remainder is below d. Doubled plus one, it can reach 2d − 1, which may need one more bit than d. So rem is [WD:0], one bit wider than the divisor.

每個時脈做的事What happens each clock

lo  <= lo << 1;                                 // next bit to the front  下一位移到最前面
rem <= fits ? rem_next - {1'b0, d} : rem_next;  // subtract if it fits  夠減就減
q   <= {q[WQ-2:0], fits};                       // shift in the new bit  商左移,新位補在右邊
cnt <= cnt - 1'b1;

最後一步要寫 quotient <= {q[WQ-2:0], fits} 而不是 quotient <= q。因為 <= 是非阻塞賦值,同一個時脈裡 q 還是舊的值,要自己把最後一位接上。

On the last step the code writes quotient <= {q[WQ-2:0], fits}, not quotient <= q. <= is a non-blocking assignment, so within the same clock q still holds its old value, and the last bit has to be appended by hand.

走一遍:13 ÷ 3Walk-through: 13 ÷ 3

縮小成 WN = 5、WD = 2、WQ = 3。13 = 01101,上面 2 位 01 當初始餘數,下面 3 位 101 放進 lo。除數 3 = 11。

Scale down to WN = 5, WD = 2, WQ = 3. 13 = 01101: the top 2 bits 01 are the initial remainder and the low 3 bits 101 go into lo. The divisor 3 = 11.

步驟Step拉下Bit inrem_next≥ 3?≥ 3?新 remnew remq
111×2+1 = 3是 → 1yes → 101
200×2+0 = 0否 → 0no → 0010
310×2+1 = 1否 → 0no → 01100

商 = 100 = 4,餘 1。驗算:3 × 4 + 1 = 13。

Quotient = 100 = 4, remainder 1. Check: 3 × 4 + 1 = 13.

時序Timing

start : ‾\____________________________   ← one pulse  給一下 start
busy  : __/‾‾‾‾‾‾‾ WQ clocks ‾‾‾‾‾\_____
done  : _________________________/‾\___  ← one clock; quotient valid  只亮 1 個時脈

3什麼是「初始餘數」What the initial remainder is

開始計算時,電路把被除數切成兩段:

At the start, the circuit splits the dividend in two:

rem <= dividend[WN-1:WQ];   // upper part → starting remainder  上半部 → 一開始的餘數
lo  <= dividend[WQ-1:0];    // lower WQ bits → brought down one by one  下半部 → 一位一位拉下來

為什麼可以這樣?回到 157 ÷ 12。第一步看 1,12 放不進去,商是 0、餘數是 1,這步等於白做。所以可以直接把 1 當成起始餘數,從「拉下 5」開始,只要兩步就得到兩位數的商 13。

Why does that work? Back to 157 ÷ 12. The first step looks at 1: 12 doesn't fit, so the digit is 0 and the remainder is 1. That step does nothing useful. So we can start with 1 as the remainder, begin at "bring down 5", and get the two-digit quotient 13 in two steps.

只要上半部小於除數,那些位置的商一定全是 0,可以整段跳過。這讓 88 位元的被除數只需要 36 步,而不是 88 步。

As long as the upper part is smaller than the divisor, every quotient bit in that range is 0 and the whole range can be skipped. That is how an 88-bit dividend needs only 36 steps instead of 88.

使用條件Requirement上半部必須小於除數。例如 1257 ÷ 12,上半部 12 不小於 12,真正的商 104 有三位,但電路只算兩位,結果就會錯。而且電路不會報錯,只會默默給錯的數字。The upper part must be smaller than the divisor. In 1257 ÷ 12 the upper part 12 is not smaller than 12. The real quotient 104 has three digits but the circuit only produces two, so the result is wrong. The circuit does not report an error; it quietly outputs the wrong number.

4位元寬度怎麼事先決定Choosing bit widths in advance

WN、WD、WQ 都是 parameter,在合成時就固定了。Quartus 會照這個數字做出那麼多個正反器,電路做好之後就像蓋好的房子,房間數量不能再改。所以設計者必須在寫程式時就用紙筆分析好。

WN, WD and WQ are parameters, fixed at synthesis. Quartus builds exactly that many flip-flops. Once built, the circuit is like a finished house: you can't add rooms. So the designer has to work the widths out on paper before writing the code.

先懂定點數 Qm.fFixed-point numbers, Qm.f

FPGA 常用整數表示小數,約定「最後 f 個位元是小數」。例如 Q2.34 是 2 位整數加 34 位小數,共 36 位元,數值 = 整數值 ÷ 234。相除時:

FPGAs often store fractions as integers, agreeing that "the last f bits are the fraction". Q2.34 means 2 integer bits plus 34 fraction bits, 36 bits in all, with value = integer ÷ 234. When dividing:

小數位數規則Fraction-bit rule商的小數位數 = 被除數的小數位數 − 除數的小數位數。和 105 ÷ 102 = 103 指數相減是同一個道理。Quotient fraction bits = dividend fraction bits − divisor fraction bits. It's the same as subtracting exponents in 105 ÷ 102 = 103.

決定的步驟The steps

  1. WD:看除數訊號有幾個位元。WD: count the bits of the divisor signal.
  2. WN:看被除數訊號有幾個位元。小數位不夠的話,先左移補足。WN: count the bits of the dividend signal. If it lacks fraction bits, shift it left first.
  3. 估答案的最大值:分子取最大、分母取最小,算出最壞情況,決定整數部分要幾位。Bound the answer: take the largest numerator and smallest denominator to get the worst case, which sets the integer bits.
  4. WQ = 整數位 + 小數位。WQ = integer bits + fraction bits.

例子:光線打到地面的位置Example: where a light ray hits the ground

要算 z × |Tx| ÷ |Tz|:

We need z × |Tx| ÷ |Tz|:

項目Item格式Format位元Bits
zQ4.2428
|Tx|Q2.3032
被除數 z × |Tx|(相乘位數相加)Dividend z × |Tx| (widths add when multiplying)Q6.54WN = 60
除數 |Tz|Divisor |Tz|Q2.30WD = 32
商:小數 54 − 30 = 24 位,整數見下Quotient: 54 − 30 = 24 fraction bits; integer bits belowQ5.24WQ = 29

整數要幾位?這個題目裡 z 最大 6、|Tx| 最大 1、|Tz| 最小 1/3,所以答案最大 6 × 1 ÷ (1/3) = 18。18 < 25 = 32,整數 5 位就夠。

How many integer bits? Here z is at most 6, |Tx| at most 1 and |Tz| at least 1/3, so the answer is at most 6 × 1 ÷ (1/3) = 18. Since 18 < 25 = 32, 5 integer bits are enough.

估太小Too small

答案太大時最高位被丟掉,結果錯誤,而且沒有任何警告。這是最危險的情況。Large answers lose their top bits. The result is wrong with no warning. This is the dangerous case.

估太大Too large

結果一定正確,只是多用一點硬體、多花幾個時脈。所以實務上會留一點餘裕。Always correct, just a little more hardware and a few more clocks. In practice designers leave some margin.

紙筆推導可能漏掉情況,所以最後還要用模擬把所有可能的輸入跑一遍,和電腦的浮點數答案比對。誤差特別大的地方,通常就是某個寬度估錯、溢位了。

Paper analysis can miss cases, so the last step is to simulate every possible input and compare against a floating-point answer. Where the error is unusually large, some width was usually too small and overflowed.

5開根號器 sqrt_seqThe square-root unit sqrt_seq

算 root = ⌊√radicand⌋(無條件捨去)。輸入 W 位元,輸出 N = W/2 位元。

It computes root = ⌊√radicand⌋ (rounded down). The input has W bits and the output N = W/2 bits.

localparam N = W / 2;

N 同時代表三件事:答案有幾個位元、被開方數分成幾組(每組 2 位)、要算幾個時脈。例如 W = 88 時 N = 44。N 用 localparam 是因為它由 W 算出來,外面不能改,避免兩個數被設成互相矛盾。

N means three things at once: the number of answer bits, the number of 2-bit groups in the radicand, and the number of clocks. With W = 88, N = 44. N is a localparam because it is derived from W and can't be overridden, so the two can never disagree.

除法 div_seqDivide: div_seq

每步拉下 1 位,試減 除數 d(固定)Brings down 1 bit per step and tries to subtract the divisor d (fixed)

開根號 sqrt_seqSquare root: sqrt_seq

每步拉下 2 位,試減 4q + 1(隨答案變)Brings down 2 bits per step and tries to subtract 4q + 1 (changes with the answer)

為什麼一次拉 2 位?Why two bits at a time?

答案多一位,平方就多兩位。3² = 9(1 位)、30² = 900(3 位)、300² = 90000(5 位)。所以被開方數要兩位兩位一組,每組決定答案的一位。

One more digit in the answer means two more digits in its square: 3² = 9 (1 digit), 30² = 900 (3 digits), 300² = 90000 (5 digits). So the radicand is taken in pairs, and each pair decides one answer bit.

為什麼試減 4q + 1?Why subtract 4q + 1?

目前的答案是 q,下一位可以填 0 或 1:

The answer so far is q. The next bit can be 0 or 1:

兩者的平方差多少?用乘法公式 (a + b)² = a² + 2ab + b²:

How far apart are their squares? Using (a + b)² = a² + 2ab + b²:

(2q + 1)² − (2q)² = 4q² + 4q + 1 − 4q² = 4q + 1

所以「這一位能不能填 1」就是「剩下的餘數夠不夠再減掉 4q + 1」。而 4q + 1 在二進位裡就是 q 後面接上 01,不需要乘法器:

So "can this bit be 1?" is the same as "is the remainder at least 4q + 1?". In binary, 4q + 1 is just q followed by 01, so no multiplier is needed:

wire [N+1:0] rem_next = {rem[N-1:0], x[W-1:W-2]};  // rem × 4 + next two bits  餘數 × 4 + 拉下的兩位
wire [N+1:0] trial    = {q, 2'b01};                // 4q + 1
wire         fits     = (rem_next >= trial);

餘數為什麼乘 4?因為答案變成 2 倍,平方就變 4 倍,舊餘數也要跟著放大 4 倍。左移兩位就是乘 4。

Why multiply the remainder by 4? Doubling the answer quadruples its square, so the old remainder scales by 4 too. Shifting left by two is multiplying by 4.

走一遍:√45Walk-through: √45

W = 6、N = 3。45 = 101101,分成 10 | 11 | 01,餘數從 0 開始。

W = 6, N = 3. 45 = 101101, split into 10 | 11 | 01. The remainder starts at 0.

步驟Step拉下Bits inrem_next4q+1夠減?Fits?新 remnew remq
1100×4+2 = 21是 → 1yes → 111
2111×4+3 = 75是 → 1yes → 1211
3012×4+1 = 913否 → 0no → 09110

root = 110 = 6,餘 9。驗算:6² + 9 = 45。

root = 110 = 6, remainder 9. Check: 6² + 9 = 45.

兩個電路怎麼串在一起How the two circuits connect

在光線折射的計算裡,要把法向量變成長度為 1 的單位向量:

In the light-refraction calculation, the surface normal has to be scaled to a unit vector of length 1:

x² + y² + z²Q4.84 · 88 bits
→
sqrt_seq44 clocks
→
向量長度lengthQ2.42 · 44 bits
→
div_seq × 336 clocks
→
單位向量unit vectorQ2.34 · 36 bits

開根號時小數位數也減半:84 位小數 → 42 位小數。三個除法器同時把 x、y、z 分量除以長度。單位向量的分量一定在 −1 到 1 之間,所以 Q2.34 的 2 位整數就夠,初始餘數的條件也一定成立。

A square root also halves the fraction bits: 84 → 42. Three dividers divide the x, y and z components by the length at the same time. Unit-vector components always lie between −1 and 1, so the 2 integer bits of Q2.34 are enough and the initial-remainder condition always holds.

6自己動手算Try it yourself

輸入數字,看電路每一個時脈在做什麼。這裡用 JavaScript 照著 Verilog 的步驟模擬。

Enter numbers and watch what the circuit does on every clock. This is a JavaScript model that follows the Verilog step by step.