Altifigence Academy

52 / 63 · 概念

桶式移位器與分級 MUX

以 1、2、4、8 位 MUX 級實作可變移位,處理方向共用、符號填補與超範圍移位。

先備知識:MUX多工器是依選擇訊號,將多個輸入之一連至輸出的組合電路。必須明確定義選擇位元與輸入編號的對應關係。 詳細內容、邏輯與算術移位,以及組合電路的傳播延遲傳播延遲是輸入改變後,輸出穩定至正確值所需的時間。邏輯式是否等價與時間特性是兩個不同問題。 詳細內容。

把可變移位化成固定配線選擇

每次移一位的移位暫存器暫存器儲存多個位元的狀態。本課程中的同步暫存器會在時脈邊緣儲存指定的輸入。 詳細內容需要與移動次數相同的時脈數。Barrel shifter 接收移位量,在一條組合路徑產生結果。不是位元在時間上反覆移動,而是選擇將所需輸入位元接到輸出的配線路徑。

16 位元值移動 0~15 位,移位量為 s=s0+2s1+4s2+8s3s=s_0+2s_1+4s_2+8s_3。因此串接移 1、2、4、8 位的四級,每級 MUX 選擇「原樣通過」或「移動固定距離」。

X0=X,Xk+1={shift⁡(Xk,2k),sk=1Xk,sk=0X_0=X,\qquad X_{k+1}= \begin{cases} \operatorname{shift}(X_k,2^k),&s_k=1\\ X_k,&s_k=0 \end{cases}

例如 11 的二進位為 1011,選擇 1、2、8 位級,4 位級直通。X=0xD2A5X=0xD2A5 邏輯右移時,依序得到 0x6952、0x1A54、0x1A54、0x001A。這些是四個組合級的值,不是四個時脈的值。

每級 16 個 MUX、共四組,即 64 個 1 位元 2:1 選擇點;這是配線與常數傳播最佳化前的結構數。一般 W=2KW=2^K 時,資料選擇結構與 Wlog⁡2WW\log_2W 成正比,深度與 log⁡2W\log_2W 成正比。即使每個輸出單獨畫 W:1 MUX,合成後也可能變成樹,因此不能用 RTL 行數斷言面積或頻率。

下圖將 0xD2A5 邏輯右移 11 位,標出移位量 1011 各位選擇的四個組合級,不表示跨四個時脈執行。

將移動 11 位分解為 1+2+8
  1. 移 1 位階段 · s0=1: D2A5 → 6952
  2. 移 2 位階段 · s1=1: 6952 → 1A54
  3. 移 4 位階段 · s2=0: 1A54 原樣通過
  4. 移 8 位階段 · s3=1: 1A54 → 001A

用右移電路建立左移

先反轉位元順序,邏輯右移 s 位,再反轉回來,就得到邏輯左移。利用此對稱性可共用四級,但輸入、輸出還需方向選擇 MUX,總成本不只 64 個。沒有方向選擇的固定位元反序本身只是配線。

算術右移將空出的高位填入原始輸入的符號位元。左移即使在算術模式也補 0。二補數二補數以固定寬度的位元序列表示帶符號整數。n 位元範圍為 −2^(n−1) 至 2^(n−1)−1。 詳細內容的算術左移與邏輯左移位元操作相同,不會自動檢查 signed overflow。

移位量範圍也是契約。以下範例以 5 位元 shamt 接受 0~31。≥16 時,邏輯移位與左移輸出 0,算術右移則輸出十六個符號位元。只用低四位會把移 16 位誤判成移 0 位,需另外處理。

SystemVerilog
module barrel16 (
  input  wire [15:0] x,
  input  wire [4:0] shamt,
  input  wire left,
  input  wire arithmetic,
  output wire [15:0] y
);
  wire fill;
  wire [15:0] stage [0:4];
  assign fill = (!left) && arithmetic && x[15];

  for (genvar i = 0; i < 16; i++) begin : direction
    assign stage[0][i] = left ? x[15-i] : x[i];
    assign y[i] = shamt[4] ? fill :
                  (left ? stage[4][15-i] : stage[4][i]);
  end

  for (genvar k = 0; k < 4; k++) begin : shift_stage
    localparam int D = 1 << k;
    assign stage[k+1] = shamt[k]
      ? {{D{fill}}, stage[k][15:D]}
      : stage[k];
  end
endmodule

Generate 的 k 是建立電路時決定的常數;這裡的迴圈不代表執行期重複四次的動作。各級 part-select 與重複串接長度固定,因此表達為四種固定配線與 MUX。Fill 不隨級數改變,即使選取多級,也以相同符號擴展。

此 RTL 明確指定符號填補,因此可用 unsigned無符號(unsigned)將位元序列解讀為非負整數。n 位元範圍為 0 至 2^n−1;相同位元序列的帶符號解讀可能得到不同數值。 詳細內容 向量實作算術移位。若改用運算子簡寫,算術右移需 signed 運算元與 >>>。不能只加 >>>,或只讓 part-select 的原變數為 signed 就認為安全;串接與部分選取可能失去 signed 解讀,應先轉成預期寬度的 signed 值。工具支援的運算子可見 AMD Verilog 表達式文件。

分開處理延遲與資訊損失

四個組合級還要加上方向、範圍選擇與配線延遲。時序不足時可插入暫存器,但剩餘移位量與方向控制也須隨資料延後相同時脈數。此時輸出 latency延遲(latency)是接受輸入至產生對應輸出之間的時間或週期數。它與表示單位時間處理量的吞吐量不同。 詳細內容 改變,介面不能再當作純組合模組。

移位無法還原被截掉的資訊。Unsigned 左移若推出的高位有任何 1,就是範圍超出;signed 則還需考慮原符號與被截位元。本模組不輸出這些旗標。負數算術右移把除以 2s2^s 的值向下取整,因此 −3-3 右移一位為 −2-2,不同於朝零整數除法的 −1-1。

自己試試看

16 位元 x=0x8123,求 (1) 邏輯右移 3 位、(2) 算術右移 3 位、(3) 邏輯左移 16 位、(4) 算術右移 20 位。說明 (2) 選中的級,以及 (3) 漏掉 shamt[4] 處理的錯誤。

查看解說

(1) 0x1024、(2) 0xF024、(3) 0x0000、(4) 0xFFFF。3=1+2,因此選 1 位與 2 位級。算術移位中間值為 0xC091→0xF024,原符號為 1,所以高位補 1。16 的 shamt=10000,若只用低四位就全部直通,錯誤輸出原值 0x8123,因此須另判斷 ≥16。即使開啟算術模式,左移空出的低位仍補 0。

此選擇適用於本瀏覽器,隨時可從頁尾變更。