Outline — click to expand大綱 — 點擊展開アウトライン — クリックで展開
1. Data Types1. 資料型別1. データ型
2. Operators2. 運算子2. 演算子
3. Assignments and Statements3. 指定與敘述3. 代入と文
4. Timing and Event Controls4. 時序與事件控制4. タイミングとイベント制御
5. Loops5. 迴圈5. ループ
6. Tasks, Functions, Directives6. task、function 與編譯指令6. タスク・関数・指令
7. Summary7. 總結7. まとめ
← DCIC Study Guides← DCIC 自學指南← DCIC 学習ガイド
EE5733 Digital Communication IC Design · Lecture 6EE5733 數位通訊積體電路設計 · 第 6 講EE5733 デジタル通信 IC 設計 · 第 6 講

Synthesis of Language Constructs語言結構的合成言語構造の合成

How nets, registers, x/z, every operator, assignments, delay and event controls, the four loop types, tasks and functions map to hardware — a trilingual self-study guidenet、register、x/z、各種運算子、指定敘述、延遲與事件控制、四種迴圈型態、task 與 function 如何對應到硬體 — 語言結構合成自學指南ネット、レジスタ、x/z、各種演算子、代入、遅延制御とイベント制御、四つのループ型、タスクと関数がどのようにハードウェアへ対応するか — 言語構造の合成 学習ガイド

Contents目錄目次

  1. Data Types: Nets, Registers, x and z資料型別:net、register、x 與 zデータ型:ネット、レジスタ、x と z
  2. Operators運算子演算子
  3. Assignments, case / if and Blocking vs Non-Blocking指定敘述、case / if 與阻斷式對非阻斷式代入、case / if、ブロッキングと非ブロッキング
  4. Delay Controls, Event Controls and Resets延遲控制、事件控制與重置遅延制御、イベント制御、リセット
  5. Loops迴圈ループ
  6. Tasks, Functions, specify and Compiler Directivestask、function、specify 與編譯指令タスク、関数、specify、コンパイラ指令
  7. Summary and Exam Checklist總結與考試檢查表まとめと試験チェックリスト

1. Data Types: Nets, Registers, x and z1. 資料型別:net、register、x 與 z1. データ型:ネット、レジスタ、x と z

1.1 Synthesis of net variables1.1 net 變數的合成1.1 ネット変数の合成

1.2 Synthesis of register variables1.2 register 變數的合成1.2 レジスタ変数の合成

1.3 Four-value logic: x and z1.3 四值邏輯:x 與 z1.3 4 値論理:x と z

Value數值値Allowed uses in synthesizable code在可合成程式中允許的用法合成可能なコードで許される使い方Meaning to the tool對工具的意義ツールにとっての意味
xcasex, casez items; the default of a conditional (if, case, ?:); x assigned to a wire / reg by a UDPcasex、casez 的項目;條件敘述(if、case、?:)的 default;由 UDP 指定給 wire / reg 的 xcasex、casez の項目、条件分岐(if、case、?:)の default、UDP が wire / reg に代入する xDon't care — the optimizer may pick 0 or 1Don't care — 最佳化器可以自行選 0 或 1ドントケア — 最適化器が 0 か 1 を自由に選べる
zConstructs implying a tri-state output: z as the default outcome of a conditional會推出三態輸出的寫法:以 z 當作條件敘述的預設結果トライステート出力を示唆する記述。条件分岐の既定の結果として z を与えるTri-state device三態元件トライステート素子

Comparing against x or z (if (a === 1'bx)) has no hardware meaning.拿 x 或 z 來比較(if (a === 1'bx))在硬體上沒有意義。x や z との比較(if (a === 1'bx))にハードウェア上の意味はない。

Practice 1 — Legal x / z?練習 1 — x / z 合法嗎?演習 1 — x / z は合法か

Problem: Which lines are acceptable for synthesis and what do they become?題目:哪幾行可以合成?它們又會變成什麼硬體?問題:どの行が合成可能か。またそれぞれ何になるか。

(a) assign y = en ? d : 8'bz;
(b) if (sel == 2'bx1) y = a;
(c) case (op) 2'b00: y = a; 2'b01: y = b; default: y = 4'bx; endcase
(d) reg [7:0] r = 8'bx;            // as reset value
(e) casez (req) 4'b1???: g = 0; ... endcase
Click to reveal solution點擊展開解答クリックで解答を表示

(a) OK — tri-state buffer. (b) Not meaningful: == with an x operand is never true in simulation; synthesis treats it as don't care or rejects it — use casez. (c) OK — don't care in the default; lets the optimizer simplify. (d) Not a default of a conditional; initial values are ignored or rejected. Use a reset. (e) OK — ? bits are don't cares, giving a priority encoder.(a) 可以 — 三態緩衝器。(b) 沒有意義:運算元含 x 時 == 在模擬中永遠不會成立,合成工具會當成 don't care 或直接拒絕 — 請改用 casez。(c) 可以 — default 裡的 don't care 讓最佳化器得以化簡。(d) 這不是條件敘述的 default;初始值會被忽略或拒絕,請改用重置。(e) 可以 — ? 位元是 don't care,合成出優先編碼器。(a) 可 — トライステートバッファ。(b) 意味を持たない。オペランドに x があると == はシミュレーションで決して真にならず、合成ではドントケア扱いか拒否される。casez を使う。(c) 可 — default のドントケアが最適化器に簡単化を許す。(d) 条件分岐の default ではない。初期値は無視されるか拒否されるので、リセットを使う。(e) 可 — ? のビットはドントケアであり、プライオリティエンコーダになる。

2. Operators2. 運算子2. 演算子

2.1 Arithmetic operators2.1 算術運算子2.1 算術演算子

Free arithmetic免費的算術コストゼロの算術 $$a \times 2^k = a \ll k,\qquad a \div 2^k = a \gg k,\qquad a \bmod 2^k = a[k-1:0]$$

2.2 Shift operators2.2 移位運算子2.2 シフト演算子

Example: shift right / left unit範例:右移 / 左移單元例:右シフト/左シフトユニット

Control控制制御Action動作動作
reset = 0Clear (asynchronous, active low)清除(非同步,低準位有效)クリア(非同期、負論理)
data_load = 1Load data_in載入 data_indata_in をロード
SL = 1Shift left by 1 bit左移 1 位元1 ビット左シフト
SR = 1Shift right by 1 bit右移 1 位元1 ビット右シフト
module data_shift (data_out, data_in, clk, reset, data_load, SL, SR);
  input  [3:0] data_in;
  input        clk, reset, data_load, SL, SR;
  output [3:0] data_out;
  reg    [3:0] data_out;

  always @ (posedge clk or negedge reset)
    if (reset == 0)  data_out = 0;              else
    if (data_load)   data_out = data_in;        else
    if (SL)          data_out = data_out << 1;  else
    if (SR)          data_out = data_out >> 1;
endmodule
d_out[1]hold保持保持0data_in[0] 10 01 01 SRSLdata_load DFFdata_out[0]clk / reset
Basic structure for the LSB: three 2:1 muxes in priority order (data_load nearest the flip-flop, highest priority). Shift left brings 0 into bit 0; shift right brings data_out[1].最低位元的基本結構:三個 2:1 多工器依優先順序串接(data_load 最靠近正反器,優先權最高)。左移時第 0 位補 0,右移時第 0 位取得 data_out[1]。最下位ビットの基本構造:3 個の 2:1 マルチプレクサを優先順位順に並べる(data_load がフリップフロップに最も近く、優先度が最も高い)。左シフトではビット 0 に 0 が入り、右シフトでは data_out[1] が入る。

The synthesized netlist realizes this per bit as AND-OR-INVERT gates in front of four DFFs with asynchronous reset.合成出來的 netlist 在每一個位元上都用一組 AND-OR-INVERT 閘實現這個結構,接在四個具非同步重置的 DFF 前面。合成されたネットリストでは、各ビットが AND-OR-INVERT ゲート群として実現され、非同期リセット付きの DFF 4 個の前段に置かれる。

2.3 Relational and identity operators2.3 關係運算子與相等運算子2.3 関係演算子と等価演算子

Example 1 — equality範例 1 — 相等比較例 1 — 等価比較
module identity_4bit (A_eq_B, A_noteq_B, A, B);
  output       A_eq_B, A_noteq_B;
  input  [3:0] A, B;

  assign A_eq_B    = (A == B);
  assign A_noteq_B = (A != B);
endmodule

Four XORs feed a 4-input OR = A_noteq_B; one inverter gives A_eq_B.四個 XOR 餵進一個 4 輸入 OR 就得到 A_noteq_B,再加一個反相器得到 A_eq_B。4 個の XOR が 4 入力 OR に入って A_noteq_B となり、インバータ 1 個で A_eq_B が得られる。

Example 2 — if chain on sel範例 2 — 以 sel 串接的 if例 2 — sel による if の連鎖
module identity_if_4bit (data_out, data_a,
          data_b, data_c, data_d, sel);
  input  [3:0] data_a, data_b, data_c, data_d;
  input  [1:0] sel;
  output [3:0] data_out;
  reg    [3:0] data_out;

  always @ (data_a or data_b or data_c
            or data_d or sel)
    begin
      if      (sel == 2'b00) data_out = data_a;
      else if (sel == 2'b01) data_out = data_b;
      else if (sel == 2'b10) data_out = data_c;
      else                   data_out = data_d;
    end
endmodule

The equality tests are mutually exclusive, so the result is a single 4:1 mux (mux4_a per bit). Another tool run produced plain AND-OR gates with sel[1], sel[0] and their inverses — same function, different mapping.這些相等判斷互斥,所以結果只是一個 4:1 多工器(每位元一顆 mux4_a)。另一次工具執行則產生以 sel[1]、sel[0] 及其反相訊號組成的 AND-OR 閘 — 功能相同,只是對應到的元件不同。等価判定は互いに排他的なので、結果は 4:1 マルチプレクサ 1 個(ビットごとに mux4_a)になる。別のツール実行では sel[1]、sel[0] とその反転信号による単純な AND-OR ゲートが得られた。機能は同じでマッピングが異なる。

2.4 Reduction, bitwise and logical operators2.4 縮減、位元與邏輯運算子2.4 リダクション・ビット単位・論理演算子

Translated to Boolean equations and mapped to gates.會被翻譯成布林方程式,再對應到邏輯閘。ブール式に変換され、ゲートへマッピングされる。

module reduction (data_word, y_red_and, y_red_or, y_red_nand,
                  y_red_nor, y_red_xor, y_red_xnor);
  input  [1:0] data_word;
  output       y_red_and, y_red_or, y_red_nand, y_red_nor, y_red_xor, y_red_xnor;
  reg          y_red_and, y_red_or, y_red_nand, y_red_nor, y_red_xor, y_red_xnor;

  always @ (data_word) begin
    y_red_and  <=  &data_word;
    y_red_or   <=  |data_word;
    y_red_nand <= ~&data_word;
    y_red_nor  <= ~|data_word;
    y_red_xor  <=  ^data_word;
    y_red_xnor <= ~^data_word;
  end
endmodule

Six 2-input gates (AND, OR, XOR and their inverted versions) on data_word[1:0]. Non-blocking in a combinational block works here but = is the usual style.對 data_word[1:0] 產生六個 2 輸入閘(AND、OR、XOR 以及它們的反相版本)。在組合邏輯區塊中使用非阻斷式指定在這裡可以運作,但慣用寫法仍是 =。data_word[1:0] に対して 2 入力ゲートが 6 個(AND、OR、XOR とそれぞれの反転版)生成される。組合せ論理ブロックで非ブロッキング代入を使っても動作はするが、通常は = を使う。

2.5 Conditional and concatenation operators2.5 條件運算子與串接運算子2.5 条件演算子と連結演算子

module mux_conditional (data_out, data_a, data_b, data_c, data_d, sel);
  input  [3:0] data_a, data_b, data_c, data_d;
  input  [1:0] sel;
  output [3:0] data_out;

  assign data_out = (sel == 2'b00) ? data_a :
                    (sel == 2'b01) ? data_b :
                    (sel == 2'b10) ? data_c : data_d;
endmodule

2.6 Grouping of operators2.6 運算子的分組2.6 演算子のグループ化

module operator_group (sum1, sum2, a, b, c, d);
  input  [3:0] a, b, c, d;
  output [4:0] sum1, sum2;

  assign sum1 = a + b + c + d;
  assign sum2 = (a + b) + (c + d);
endmodule
++++++ sum1: 3 levelssum1:3 層sum1:3 段sum2: 2 levelssum2:2 層sum2:2 段

Verilog evaluates a + b + c + d left to right as ((a + b) + c) + d: a chain of three adders. Parentheses turn it into a balanced tree — still three adders, but only two adder delays on the critical path.Verilog 由左而右把 a + b + c + d 解讀成 ((a + b) + c) + d:三個加法器串成一條鏈。加上括號就變成平衡樹 — 一樣是三個加法器,但關鍵路徑上只剩兩個加法器延遲。Verilog は a + b + c + d を左から右へ ((a + b) + c) + d と評価する。すなわち加算器 3 個の直列である。括弧を付けると平衡木になり、加算器は 3 個のままだがクリティカルパス上の加算器遅延は 2 段だけになる。

Practice 2 — Cheap arithmetic練習 2 — 便宜的算術演習 2 — 安価な算術

Problem: a is [7:0]. Rewrite without *, /, %: (a) a * 8 (b) a / 4 (c) a % 16 (d) a * 10. (e) For four 8-bit operands summed as a+b+c+d, how many adder delays are on the critical path, and with parentheses?題目:a 是 [7:0]。請在不使用 *、/、% 的情況下改寫:(a) a * 8 (b) a / 4 (c) a % 16 (d) a * 10。(e) 四個 8 位元運算元以 a+b+c+d 相加時,關鍵路徑上有幾個加法器延遲?加上括號之後又是幾個?問題:a は [7:0] である。*、/、% を使わずに書き換えよ。(a) a * 8 (b) a / 4 (c) a % 16 (d) a * 10。(e) 8 ビットのオペランド 4 個を a+b+c+d と加算するとき、クリティカルパス上の加算器遅延は何段か。括弧を付けた場合は何段か。

Click to reveal solution點擊展開解答クリックで解答を表示

(a) {a, 3'b000} (= a << 3, 11 bits). (b) a[7:2] (= a >> 2). (c) a[3:0]. (d) (a << 3) + (a << 1) — one adder instead of a multiplier.(a) {a, 3'b000}(即 a << 3,11 位元)。(b) a[7:2](即 a >> 2)。(c) a[3:0]。(d) (a << 3) + (a << 1) — 用一個加法器取代乘法器。(a) {a, 3'b000}(= a << 3、11 ビット)。(b) a[7:2](= a >> 2)。(c) a[3:0]。(d) (a << 3) + (a << 1) — 乗算器の代わりに加算器 1 個で済む。

(e) Chain: 3 adder delays; (a+b)+(c+d): 2.(e) 串接寫法:3 個加法器延遲;(a+b)+(c+d):2 個。(e) 直列なら加算器遅延 3 段、(a+b)+(c+d) なら 2 段。

3. Assignments, case / if and Blocking vs Non-Blocking3. 指定敘述、case / if 與阻斷式對非阻斷式3. 代入、case / if、ブロッキングと非ブロッキング

3.1 Continuous assignments3.1 連續指定3.1 連続代入

3.2 case and if statements3.2 case 與 if 敘述3.2 case 文と if 文

module alu_reg_with_z1 (alu_out, en, a, b, s0, s1, s2, clk, reset);
  output [1:0] alu_out;
  input  [1:0] a, b;
  input        en, s0, s1, s2, clk, reset;
  reg    [1:0] out_int;

  assign alu_out = (en == 1) ? out_int : 2'bz;

  always @ (posedge clk)
    if (reset) out_int = 2'b0;
    else
      case ({s0, s1, s2})
        3'b111:  out_int = a & b;
        3'b011:  out_int = a | b;
        3'b001:  out_int = a ^ b;
        default: out_int = 2'bx;
      endcase
endmodule

All three listed cases have s2 = 1, and every other code is a don't care. The optimizer can therefore choose outputs that ignore s2 entirely — the logic is driven only by s0 and s1. The unused input s2 is still retained as a port (ports are never removed). Result: two DFFs with synchronous reset, a gate-level ALU in front and two tri-state output buffers.列出的三個 case 都滿足 s2 = 1,其餘編碼全是 don't care。因此最佳化器可以挑出完全不理會 s2 的輸出 — 邏輯只由 s0 與 s1 驅動。沒用到的輸入 s2 仍然保留為埠(埠永遠不會被刪掉)。結果是:兩個具同步重置的 DFF,前面接閘級 ALU,後面接兩個三態輸出緩衝器。挙げられた 3 つの case はいずれも s2 = 1 であり、それ以外のコードはすべてドントケアである。したがって最適化器は s2 を完全に無視する出力を選べる。論理は s0 と s1 だけで駆動される。使われない入力 s2 もポートとしては残る(ポートが削除されることはない)。結果は、同期リセット付き DFF 2 個、その前段のゲートレベル ALU、そして 2 個のトライステート出力バッファである。

3.3 Blocking vs non-blocking in clocked blocks3.3 時脈區塊中的阻斷式與非阻斷式指定3.3 クロック同期ブロックにおけるブロッキングと非ブロッキング

Example 1 — pipe1範例 1 — pipe1例 1 — pipe1
module pipe1 (data, rega, regb, regc, clk, reset);
  input  [1:0] data;
  input        clk, reset;
  output [1:0] rega, regb, regc;
  reg    [1:0] rega, regb, regc;

  always @ (posedge clk or posedge reset)
    if (reset)
      begin
        rega  = 2'b0;
        regb <= 2'b0;
        regc <= 2'b0;
      end
    else
      begin
        rega  = data;
        regb <= rega + 1;     // new rega!
        regc <= regb + 1;     // old regb
      end
endmodule
Example 2 — pipe1_alt範例 2 — pipe1_alt例 2 — pipe1_alt
module pipe1_alt (data, rega, regb, regc, clk, reset);
  ...
  always @ (posedge clk or posedge reset)
    if (reset) rega = 2'b0; else rega = data;

  always @ (posedge clk or posedge reset)
    if (reset)
      begin
        regb <= 2'b0;
        regc <= 2'b0;
      end
    else
      begin
        regb <= rega + 1;     // rega of the previous cycle
        regc <= regb + 1;
      end
endmodule
Example 3 — pipe2 (all blocking)範例 3 — pipe2(全部用阻斷式)例 3 — pipe2(すべてブロッキング)
module pipe2 (data, rega, regb, regc, clk, reset);
  ...
  always @ (posedge clk or posedge reset)
    if (reset)
      begin
        rega = 2'b0;
        regb = 2'b0;
        regc = 2'b0;
      end
    else
      begin
        rega = data;
        regb = rega + 1;
        regc = regb + 1;
      end
endmodule
Expression substitution運算式代換式の置き換え
rega = data;
regb = data + 1;
regc = data + 1 + 1;

// equivalent to
rega <= data;
regb <= data + 1;
regc <= data + 1 + 1;
Module模組モジュールregaregbregcStructure結構構造
pipe1datadata + 1old regb + 1舊的 regb + 1前回の regb + 1rega, regb parallel; regc one stage laterrega、regb 平行;regc 晚一級rega と regb は並列、regc は 1 段遅れ
pipe1_altdataold rega + 1舊的 rega + 1前回の rega + 1old regb + 1舊的 regb + 1前回の regb + 1True 3-stage pipeline真正的三級管線本物の 3 段パイプライン
pipe2datadata + 1data + 2Three parallel registers, two adders in series三個平行的暫存器,兩個加法器串接並列な 3 個のレジスタと直列 2 個の加算器
Note注意注意

The rega read by regb in pipe1_alt is from the previous cycle, not the current one, because it lives in a different always block. Same text, different hardware — the reason for the rule "clocked logic uses <= only". Strictly, pipe1_alt is also a simulation race: rega is written with = in one block and read in another at the same edge, so the simulator may show either value. Synthesis builds the flip-flop (previous-cycle) behavior; writing rega <= data removes the race.在 pipe1_alt 中 regb 讀到的 rega 是上一拍的值,不是這一拍的,因為它寫在另一個 always 區塊裡。程式碼看起來一樣,硬體卻不同 — 這正是「時脈邏輯一律只用 <=」這條規則的由來。嚴格來說,pipe1_alt 在模擬上還是一個競爭(race):rega 在一個區塊中用 = 寫入,又在同一個邊緣於另一個區塊被讀取,模擬器給出哪一個值都算合法。合成會做出正反器(上一拍)的行為;把它改寫成 rega <= data 就能消除這個競爭。pipe1_alt で regb が読む rega は、今回のサイクルではなく前回のサイクルの値である。別の always ブロックにあるからだ。記述は同じでもハードウェアは異なる。これが「クロック同期論理では <= だけを使う」という規則の理由である。厳密には pipe1_alt はシミュレーション上のレースでもある。rega は一方のブロックで = により書かれ、同じエッジで他方のブロックから読まれるため、シミュレータはどちらの値を示してもよい。合成はフリップフロップ(前回サイクル)の動作を作る。rega <= data と書けばレースはなくなる。

Practice 3 — Three pipes練習 3 — 三種管線演習 3 — 三つのパイプ

Problem: After reset all registers are 0. data = 1, 2, 3 at clock edges 1, 2, 3. Give (rega, regb, regc) after each edge for pipe1, pipe1_alt and pipe2 (2-bit arithmetic wraps mod 4).題目:重置之後所有暫存器都是 0。data 在時脈邊緣 1、2、3 依序為 1、2、3。請寫出 pipe1、pipe1_alt 與 pipe2 在每個邊緣之後的 (rega, regb, regc)(2 位元運算以 mod 4 環繞)。問題:リセット後、すべてのレジスタは 0 である。クロックエッジ 1、2、3 で data はそれぞれ 1、2、3 となる。pipe1、pipe1_alt、pipe2 について各エッジ後の (rega, regb, regc) を示せ(2 ビット演算は mod 4 で巡回する)。

Click to reveal solution點擊展開解答クリックで解答を表示
Edge邊緣エッジpipe1pipe1_altpipe2
1(1, 2, 1)(1, 1, 1)(1, 2, 3)
2(2, 3, 3)(2, 2, 2)(2, 3, 0)
3(3, 0, 0)(3, 3, 3)(3, 0, 1)

pipe1, edge 1: regb = new rega + 1 = 2, regc = old regb (0) + 1 = 1. pipe1_alt, edge 1: regb = old rega (0) + 1 = 1, regc = 0 + 1 = 1. pipe2 computes everything from the current data.pipe1 的第 1 個邊緣:regb = 新的 rega + 1 = 2,regc = 舊的 regb(0)+ 1 = 1。pipe1_alt 的第 1 個邊緣:regb = 舊的 rega(0)+ 1 = 1,regc = 0 + 1 = 1。pipe2 則全部用當下的 data 計算。pipe1 のエッジ 1:regb = 新しい rega + 1 = 2、regc = 前回の regb(0)+ 1 = 1。pipe1_alt のエッジ 1:regb = 前回の rega(0)+ 1 = 1、regc = 0 + 1 = 1。pipe2 はすべて現在の data から計算する。

4. Delay Controls, Event Controls and Resets4. 延遲控制、事件控制與重置4. 遅延制御、イベント制御、リセット

4.1 Delay controls4.1 延遲控制4.1 遅延制御

4.2 Event controls4.2 事件控制4.2 イベント制御

Rules for an edge-sensitive behavior邊緣觸發行為描述的規則エッジセンシティブな振る舞い記述の規則
  1. The statement attached to the event control should be a conditional branch (if or ?:).接在事件控制後面的敘述應該是條件分支(if 或 ?:)。イベント制御に続く文は条件分岐(if または ?:)であるべきである。
  2. Its branches split into asynchronous parts and exactly one synchronous branch.它的分支分成非同步的部分,以及恰好一個同步分支。その分岐は非同期の部分と、ちょうど 1 つの同期分岐に分かれる。
  3. A branch that does not depend on a signal of the event control expression is assumed synchronous.不依賴事件控制運算式中任何訊號的分支,會被視為同步分支。イベント制御式のどの信号にも依存しない分岐は、同期分岐とみなされる。
  4. The synchronous branch must be the last branch — asynchronous controls have priority.同步分支必須是最後一個分支 — 非同步控制有優先權。同期分岐は最後の分岐でなければならない。非同期制御が優先される。
  5. With posedge/negedge resets there is only one clock edge; any number of other asynchronous control signals may be listed, each with its own edge qualifier.使用 posedge/negedge 重置時只能有一個時脈邊緣;其他非同步控制訊號可以列任意多個,各自帶自己的邊緣修飾字。posedge/negedge のリセットを用いる場合、クロックエッジは 1 つだけである。その他の非同期制御信号は、それぞれ独自のエッジ修飾子を付けていくつ並べてもよい。
  6. No signal may be qualified by both posedge and negedge.同一個訊號不可以同時被 posedge 與 negedge 修飾。同一の信号を posedge と negedge の両方で修飾してはならない。
always @ (posedge x or posedge y or posedge z)
  begin
    if (x)
      a <= 0;          // asynchronous clear
    else if (y)
      a <= 1;          // asynchronous set
    // z is not mentioned here, and is assumed synchronous
    else a <= b & c;   // z acts as the clock
  end

4.3 Resets4.3 重置4.3 リセット

Practice 4 — Legal event control?練習 4 — 事件控制合法嗎?演習 4 — イベント制御は合法か

Problem: Which are acceptable for synthesis? Identify the clock.題目:哪幾個可以合成?並指出時脈是哪一個訊號。問題:どれが合成可能か。またクロックはどれか答えよ。

// (a)
always @ (posedge clk or negedge rst_n)
  if (!rst_n) q <= 0; else q <= d;
// (b)
always @ (posedge clk or negedge rst_n)
  if (en) q <= d; else if (!rst_n) q <= 0;
// (c)
always @ (posedge clk or negedge clk) q <= d;
// (d)
always @ (posedge clk or posedge set or posedge clr)
  if (clr) q <= 0; else if (set) q <= 1; else q <= d;
Click to reveal solution點擊展開解答クリックで解答を表示

(a) OK — clock clk, async active-low reset.(a) 可以 — 時脈是 clk,非同步低準位有效重置。(a) 可 — クロックは clk、非同期の負論理リセット。

(b) Not OK — the asynchronous branch (!rst_n) is not first and the synchronous branch is not last.(b) 不行 — 非同步分支(!rst_n)不在最前面,同步分支也不在最後面。(b) 不可 — 非同期分岐(!rst_n)が先頭になく、同期分岐も最後にない。

(c) Not OK — clk qualified by both edges (a dual-edge FF is not in normal libraries).(c) 不行 — clk 同時被兩種邊緣修飾(一般元件庫沒有雙邊緣正反器)。(c) 不可 — clk が両エッジで修飾されている(両エッジ動作の FF は通常のライブラリにない)。

(d) OK — clock clk, async clear has priority over async set.(d) 可以 — 時脈是 clk,非同步清除的優先權高於非同步設定。(d) 可 — クロックは clk、非同期クリアが非同期セットより優先される。

5. Loops5. 迴圈5. ループ

5.1 Four loop types5.1 四種迴圈型態5.1 四つのループ型

A loop is static (data-independent) if the compiler can determine the number of iterations.如果編譯器能決定迴圈的執行次數,這個迴圈就是靜態的(與資料無關)。コンパイラが反復回数を決定できるとき、そのループは静的(データ非依存)である。

Type型態型Static?靜態?静的かInternal timing control?有內部時序控制?内部タイミング制御Result結果結果
IYes是はいNo否いいえCombinational logic (loop unrolling) — recommended組合邏輯(迴圈展開)— 建議採用組合せ論理(ループ展開)— 推奨
IIYes是はいYes是はいSequential logic, fixed number of cycles — not recommended循序邏輯,週期數固定 — 不建議順序論理、サイクル数は固定 — 非推奨
IIINo否いいえNo否いいえNot synthesizable (simulates fine)不可合成(模擬沒問題)合成不可(シミュレーションは可能)
IVNo否いいえYes是はいSequential logic, data-dependent number of cycles — not recommended循序邏輯,週期數取決於資料 — 不建議順序論理、サイクル数がデータ依存 — 非推奨

5.2 Type I — static loop without internal timing controls5.2 型 I — 無內部時序控制的靜態迴圈5.2 タイプ I — 内部タイミング制御のない静的ループ

module for_and_loop_comb (out, a, b);
  input  [3:0] a, b;
  output [3:0] out;
  reg    [2:0] i;
  reg    [3:0] out;

  always @ (a or b)
    begin
      for (i = 0; i < 4; i = i + 1)
        out[i] = a[i] & b[i];
    end
endmodule

Unrolled into four AND gates. Replacing @(a or b) with @(posedge clk) gives for_and_loop_reg: the same ANDs feeding four flip-flops.展開成四個 AND 閘。把 @(a or b) 換成 @(posedge clk) 就成為 for_and_loop_reg:同樣的 AND 閘接到四個正反器。AND ゲート 4 個に展開される。@(a or b) を @(posedge clk) に替えると for_and_loop_reg になり、同じ AND ゲートが 4 個のフリップフロップを駆動する。

Why i is 3 bits為什麼 i 要 3 位元なぜ i は 3 ビットなのか

The loop exits when i reaches 4, so i must hold 4. A reg [1:0] i would wrap 3 → 0 and loop forever in simulation.迴圈要等 i 到 4 才結束,所以 i 必須存得下 4。若宣告成 reg [1:0] i,3 會環繞回 0,模擬時就會無限迴圈。ループは i が 4 になったときに終わるので、i は 4 を保持できなければならない。reg [1:0] i では 3 から 0 へ巡回し、シミュレーションで無限ループになる。

Counting ones (Type I)數 1 的個數(型 I)1 の個数を数える(タイプ I)

module count_ones_a (bit_count, data, clk, reset);
  parameter data_width  = 4;
  parameter count_width = 3;
  output [count_width-1:0] bit_count;
  input  [data_width-1:0]  data;
  input                    clk, reset;
  reg    [count_width-1:0] count, bit_count, index;
  reg    [data_width-1:0]  temp;

  always @ (posedge clk)
    if (reset) begin count = 0; bit_count = 0; end
    else begin
      count = 0;
      bit_count = 0;
      temp = data;
      for (index = 0; index < data_width; index = index + 1) begin
        count = count + temp[0];
        temp  = temp >> 1;
      end
      bit_count = count;
    end
endmodule

The loop unrolls into a small adder tree that counts the ones of data in one clock; only bit_count (3 FFs) is registered — count, temp, index are written before they are read, so they are wires.迴圈展開成一棵小的加法器樹,在一個時脈內數完 data 裡的 1;只有 bit_count(3 個正反器)會被暫存 — count、temp、index 都是先寫後讀,所以只是線。ループは小さな加算器ツリーに展開され、data 中の 1 を 1 クロックで数える。レジスタになるのは bit_count(FF 3 個)だけで、count、temp、index は読まれる前に書かれるため単なる配線になる。

5.3 Type II — static loop with internal timing controls5.3 型 II — 含內部時序控制的靜態迴圈5.3 タイプ II — 内部タイミング制御のある静的ループ

If a static loop contains an edge-sensitive event control, its work is synchronized and distributed over one or more clock cycles.靜態迴圈若含有邊緣觸發的事件控制,它的工作會被同步化,並分散到一個或多個時脈週期。静的ループがエッジセンシティブなイベント制御を含む場合、その処理は同期化され、1 つ以上のクロック周期に分散される。

module count_ones_b (bit_count, data, clk, reset);
  ... // same declarations
  always @ (posedge clk)
    if (reset) begin count = 0; bit_count = 0; end
    else begin
      count = 0;
      temp  = data;
      for (index = 0; index < data_width; index = index + 1)
        @ (posedge clk)
          begin
            if (temp[0]) count = count + 1;
            temp = temp >> 1;
          end
      @ (posedge clk)
        bit_count = count;
    end
endmodule

One bit is examined per clock; bit_count updates after data_width + 1 extra clocks. This is an implicit state machine — supported only by some tools. Not recommended.每個時脈檢查一個位元;bit_count 要再過 data_width + 1 個時脈才更新。這是一個隱含的狀態機 — 只有部分工具支援。不建議使用。1 クロックにつき 1 ビットを調べ、bit_count は追加の data_width + 1 クロック後に更新される。これは暗黙の状態機械であり、一部のツールしか対応しない。推奨しない。

5.4 Type III — non-static loop without internal timing controls 5.4 型 III — 無內部時序控制的非靜態迴圈 5.4 タイプ III — 内部タイミング制御のない非静的ループ Not synthesizable不可合成合成不可

module count_ones_c (bit_count, data, clk, reset);
  ...
  always @ (posedge clk)
    if (reset) begin count = 0; bit_count = 0; end
    else begin
      count = 0;
      temp  = data;
      for (index = 0; | temp; index = index + 1) begin   // stops when temp == 0
        if (temp[0]) count = count + 1;
        temp = temp >> 1;
      end
      bit_count = count;
    end
endmodule

5.5 Type IV — non-static loop with internal timing controls5.5 型 IV — 含內部時序控制的非靜態迴圈5.5 タイプ IV — 内部タイミング制御のある非静的ループ

The timing control distributes the loop over multiple cycles; the number of cycles is set by a variable modified within the loop.時序控制把迴圈分散到多個週期;週期數由迴圈內部被修改的變數決定。タイミング制御がループを複数サイクルに分散させ、そのサイクル数はループ内で変更される変数によって決まる。

module count_ones_d (bit_count, data, clk, reset);
  ...
  always @ (posedge clk)
    if (reset) begin count = 0; bit_count = 0; end
    else begin: bit_counter
      count = 0;
      temp  = data;
      while (temp)
        @ (posedge clk)
          if (reset) begin
            count = 2'b0;
            disable bit_counter; end
          else begin
            count = count + temp[0];   // notice: no if needed
            temp  = temp >> 1;
          end
      @ (posedge clk);
        if (reset) begin
          count = 0;
          disable bit_counter; end
        else bit_count = count;
    end
endmodule

Reset must be re-checked at every internal @(posedge clk), and disable jumps back to the top. Not recommended.每一個內部的 @(posedge clk) 都必須重新檢查 reset,而 disable 會跳回最上面。不建議使用。内部の @(posedge clk) ごとにリセットを再確認する必要があり、disable は先頭へ戻る。推奨しない。

Practice 5 — Classify the loop練習 5 — 判別迴圈型態演習 5 — ループを分類する

Problem: Give the type (I–IV) and whether it is synthesizable.題目:寫出型態(I–IV),並說明是否可以合成。問題:型(I–IV)と、合成可能かどうかを答えよ。

(a) for (k = 0; k < 8; k = k + 1) y[k] = x[7-k];
(b) while (q != 0) begin q = q - 1; n = n + 1; end
(c) repeat (4) @(posedge clk) acc = acc + in;
(d) while (busy) @(posedge clk) busy = check(status);
Click to reveal solution點擊展開解答クリックで解答を表示

(a) Type I — bit reversal, pure wiring. (b) Type III — not synthesizable. (c) Type II — static (4) with timing; synthesizable by some tools only. (d) Type IV — data-dependent cycles; avoid.(a) 型 I — 位元反轉,純接線。(b) 型 III — 不可合成。(c) 型 II — 靜態(4 次)且含時序控制,只有部分工具能合成。(d) 型 IV — 週期數取決於資料,請避免。(a) タイプ I — ビット反転、配線のみ。(b) タイプ III — 合成不可。(c) タイプ II — 静的(4 回)でタイミング制御あり。一部のツールのみ合成できる。(d) タイプ IV — サイクル数がデータ依存。避けること。

Practice 6 — Counting-ones latency練習 6 — 數 1 的延遲演習 6 — 1 の個数を数える遅延

Problem: For data = 4'b1010 and data = 4'b0100, how many clock edges after the starting edge does bit_count update in count_ones_a, _b and _d? What value?題目:對 data = 4'b1010 與 data = 4'b0100,在 count_ones_a、_b 與 _d 中,bit_count 會在起始邊緣之後第幾個時脈邊緣更新?更新成什麼值?問題:data = 4'b1010 と data = 4'b0100 について、count_ones_a、_b、_d では開始エッジから何クロックエッジ後に bit_count が更新されるか。またその値は何か。

Click to reveal solution點擊展開解答クリックで解答を表示

Both inputs contain ones: 1010 → 2, 0100 → 1.兩組輸入各自含有的 1 的個數:1010 → 2,0100 → 1。各入力に含まれる 1 の個数:1010 → 2、0100 → 1。

_a: at the starting edge itself (0 extra) for both._a:兩者都在起始邊緣當下就更新(額外 0 個邊緣)。_a: どちらも開始エッジそのもので更新される(追加 0 エッジ)。

_b: 4 loop edges + 1 = 5 extra edges for both (static)._b:兩者都是 4 個迴圈邊緣 + 1 = 額外 5 個邊緣(靜態)。_b: どちらもループ 4 エッジ + 1 = 追加 5 エッジ(静的)。

_d: the while loop runs until temp becomes 0: 1010 → 0101 → 0010 → 0001 → 0000 is 4 iterations, 0100 → 0010 → 0001 → 0000 is 3 iterations; plus 1 final edge → 5 and 4 extra edges. The latency depends on the data._d:while 迴圈一直跑到 temp 變成 0 為止:1010 → 0101 → 0010 → 0001 → 0000 共 4 次,0100 → 0010 → 0001 → 0000 共 3 次;再加最後 1 個邊緣 → 額外 5 個與 4 個邊緣。延遲取決於資料。_d: while ループは temp が 0 になるまで回る。1010 → 0101 → 0010 → 0001 → 0000 で 4 回、0100 → 0010 → 0001 → 0000 で 3 回。最後の 1 エッジを加えて、追加 5 エッジと 4 エッジになる。レイテンシはデータに依存する。

6. Tasks, Functions, specify and Compiler Directives6. task、function、specify 與編譯指令6. タスク、関数、specify、コンパイラ指令

6.1 Tasks6.1 task6.1 タスク

module adder_task (c_out, sum, clk, reset, c_in, data_a, data_b);
  input  [3:0] data_a, data_b;
  input        clk, reset, c_in;
  output [3:0] sum;
  output       c_out;
  reg    [3:0] sum;
  reg          c_out;

  always @ (posedge clk or posedge reset)
    if (reset) {c_out, sum} = 0; else
    add_values (sum, c_out, data_a, data_b, c_in);

  task add_values;
    output [3:0] sum;
    output       c_out;
    input  [3:0] data_a, data_b;
    input        c_in;
    begin
      {c_out, sum} = data_a + (data_b + c_in);
    end
  endtask
endmodule

Result: two 5-bit adders (data_b + c_in, then + data_a) feeding five DFFs with asynchronous reset.結果:兩個 5 位元加法器(先 data_b + c_in,再 + data_a)接到五個具非同步重置的 DFF。結果:5 ビット加算器 2 個(まず data_b + c_in、次に + data_a)が、非同期リセット付き DFF 5 個を駆動する。

6.2 Functions6.2 function6.2 関数

module arithmetic_unit (operand_1, operand_2, result_1, result_2);
  input  [3:0] operand_1, operand_2;
  output [4:0] result_1;
  output [3:0] result_2;

  assign result_1 = sum_of_operands (operand_1, operand_2);
  assign result_2 = largest_operand (operand_1, operand_2);

  function [4:0] sum_of_operands;
    input [3:0] operand_1, operand_2;
    sum_of_operands = operand_1 + operand_2;
  endfunction

  function [3:0] largest_operand;
    input [3:0] operand_1, operand_2;
    largest_operand = (operand_1 >= operand_2) ? operand_1 : operand_2;
  endfunction
endmodule

Result: one 4-bit adder for result_1, and a comparator (gates) driving four 2:1 muxes for result_2.結果:result_1 用一個 4 位元加法器;result_2 則是一個比較器(邏輯閘)驅動四個 2:1 多工器。結果:result_1 には 4 ビット加算器 1 個、result_2 には比較器(ゲート)が 2:1 マルチプレクサ 4 個を駆動する構成になる。

6.3 specify blocks and compiler directives6.3 specify 區塊與編譯指令6.3 specify ブロックとコンパイラ指令

Construct語法結構構文Synthesis合成結果合成結果
specify ... endspecifyIgnored (timing comes from the cell library)忽略(時序資訊來自元件庫)無視される(タイミングはセルライブラリから得る)
`define, `include, other compiler directives`define、`include 等編譯指令`define、`include などのコンパイラ指令Honored — they change the source text the tool reads有效 — 它們會改變工具讀到的原始碼有効 — ツールが読むソーステキストを変える
Key points (click to expand)重點整理(點擊展開)要点まとめ(クリックで展開)
  • x may only serve as a don't care (casex/casez, the default of a conditional); z is only there to imply a tri-state output.x 只能當 don't care(casex/casez、條件敘述的 default);z 只能用來推出三態輸出。x はドントケアとしてのみ使える(casex/casez、条件分岐の default)。z はトライステート出力を示すためだけに使う。
  • Multiply or divide by a power of 2 with a shift and take the remainder with a part select; grouping with parentheses shortens the critical path of an adder chain.乘除以 2 的冪次用移位,取餘用 part select;括號分組可縮短加法器串的關鍵路徑。2 のべき乗の乗除算はシフトで、剰余は部分選択で行う。括弧でグループ化すると加算器直列のクリティカルパスが短くなる。
  • Write with = and read again inside the same always block and you see the new value; read it from a different always block and you see the previous cycle's value.同一個 always 內先用 = 寫再讀,讀到的是「新值」;不同 always 之間讀到的是「上一拍」的值。同じ always ブロック内で = により書いてから読むと新しい値が見え、別の always ブロックから読むと前回サイクルの値になる。
  • In an edge-sensitive always block the asynchronous branches come first in the if and the final else is the one synchronous branch; no signal may carry both posedge and negedge.邊緣觸發 always:if 最前面是非同步分支,最後一個 else 是唯一的同步分支;同一訊號不可同時 posedge 與 negedge。エッジセンシティブな always では、if の先頭に非同期分岐を置き、最後の else が唯一の同期分岐となる。同じ信号に posedge と negedge の両方を付けてはならない。
  • Loops: static with no timing control (Type I) is the recommended form; non-static with no timing control (Type III) cannot be synthesized.迴圈:靜態且無時序控制(Type I)最推薦;非靜態且無時序控制(Type III)不可合成。ループ:静的でタイミング制御のないタイプ I が最も推奨され、非静的でタイミング制御のないタイプ III は合成できない。
  • A task is expanded inline and may not have inout ports; a function is always combinational and may not contain an incomplete case or if.task 會被展開,不可有 inout;function 必定是組合邏輯,不能有不完整的 case/if。タスクはインライン展開され、inout を持てない。関数は必ず組合せ論理であり、不完全な case や if を含められない。
Practice 7 — Task or function?練習 7 — 用 task 還是 function?演習 7 — タスクか関数か

Problem: You need a reusable block that (a) returns the parity of a 16-bit word, (b) produces both quotient and remainder of a division by 8, (c) waits 3 clock edges before writing a register. Choose task or function (or neither) and justify.題目:你需要一個可重複使用的區塊:(a) 回傳 16 位元字組的奇偶性,(b) 同時產生除以 8 的商與餘數,(c) 等 3 個時脈邊緣之後才寫入暫存器。請選擇 task 或 function(或兩者皆不可),並說明理由。問題:再利用できるブロックが必要である。(a) 16 ビットワードのパリティを返す、(b) 8 による除算の商と剰余の両方を出す、(c) 3 クロックエッジ待ってからレジスタに書く。タスクか関数か(あるいはどちらでもないか)を選び、理由を述べよ。

Click to reveal solution點擊展開解答クリックで解答を表示

(a) Function — one return value, pure combinational: parity = ^word;(a) 用 function — 只有一個回傳值,純組合邏輯:parity = ^word;(a) 関数 — 戻り値は 1 つで純粋な組合せ論理:parity = ^word;

(b) Task with two outputs (or two functions): quotient x >> 3, remainder x[2:0]; no timing, so it is combinational.(b) 用有兩個輸出的 task(或兩個 function):商是 x >> 3,餘數是 x[2:0];沒有時序控制,所以是組合邏輯。(b) 出力を 2 つ持つタスク(または関数 2 つ)。商は x >> 3、剰余は x[2:0]。タイミング制御がないので組合せ論理になる。

(c) Neither for synthesis — a task with timing controls is not synthesizable. Use a counter or a 3-stage shift register in the clocked logic instead.(c) 兩者都不行 — 含時序控制的 task 不可合成。請改用計數器,或在時脈邏輯中放一個 3 級移位暫存器。(c) 合成の観点ではどちらも不可 — タイミング制御を持つタスクは合成できない。代わりにカウンタか、クロック同期論理の中の 3 段シフトレジスタを使う。

7. Summary and Exam Checklist7. 總結與考試檢查表7. まとめと試験チェックリスト

Data types資料型別データ型
  • Port nets kept; internal nets may vanish.埠上的 net 會保留,內部 net 可能消失。ポートのネットは残り、内部ネットは消えることがある。
  • integer = 32 bits; size constants.integer = 32 位元;常數要指定位元寬。integer は 32 ビット。定数はビット幅を明示する。
  • No real, time, realtime.不支援 real、time、realtime。real、time、realtime は使えない。
x and zx 與 zx と z
  • x → don't care (casex/casez, defaults).x → don't care(casex/casez、default)。x → ドントケア(casex/casez、default)。
  • z → tri-state.z → 三態。z → トライステート。
Operators運算子演算子
  • Shift amount constant.移位量必須是常數。シフト量は定数。
  • >= via sign of A − B.>= 看 A − B 的符號位元。>= は A − B の符号で判定。
  • Power-of-2 * / % are free.對 2 的冪次做 * / % 不花硬體。2 のべき乗の * / % はコストゼロ。
  • Parentheses shape the adder tree.括號決定加法器樹的形狀。括弧が加算器ツリーの形を決める。
Assignments指定敘述代入
  • = then read in same block → new value.同一區塊內先 = 再讀 → 新值。同じブロックで = の後に読む → 新しい値。
  • Other block → previous cycle.不同區塊 → 上一拍的值。別のブロック → 前回サイクルの値。
  • Ports kept even if logic ignores them.即使邏輯沒用到,埠仍然保留。論理が使わなくてもポートは残る。
Event controls事件控制イベント制御
  • if first; async branches first.先寫 if;非同步分支擺最前面。まず if。非同期分岐を先頭に置く。
  • One synchronous branch, last.只有一個同步分支,擺最後面。同期分岐は 1 つだけで、最後に置く。
  • Delays ignored or harmful.延遲會被忽略,甚至有害。遅延は無視されるか有害である。
Loops, tasks, functions迴圈、task、functionループ、タスク、関数
  • Type I best; Type III not synthesizable.型 I 最好;型 III 不可合成。タイプ I が最良。タイプ III は合成不可。
  • Tasks inline, no inout.task 就地展開,不可有 inout。タスクはインライン展開、inout は不可。
  • Functions combinational, complete.function 是組合邏輯,條件必須完整。関数は組合せ論理で、条件は完全に記述する。
  • specify ignored.specify 會被忽略。specify は無視される。