Outline — click to expand大綱 — 點擊展開アウトライン — クリックで展開
1. Design Flow1. 設計流程1. 設計フロー
2. Verilog Foundations2. Verilog 基礎2. Verilog の基礎
3. Simulation & Testbench3. 模擬與測試平台3. シミュレーションとテストベンチ
4. Data Types & Operators4. 資料型別與運算子4. データ型と演算子
5. User-Defined Primitives5. 使用者自定原件(UDP)5. ユーザー定義プリミティブ(UDP)
6. Propagation Delay6. 傳播延遲6. 伝搬遅延
7. Behavioral Descriptions7. 行為描述7. 動作記述
8. Tasks, Functions, Timing8. 任務、函式與時序8. タスク・関数・タイミング
9. Finite State Machines9. 有限狀態機9. 有限状態機械
10. Synthesis — Combinational10. 合成 — 組合邏輯10. 合成 — 組合せ論理
11. Synthesis — Sequential11. 合成 — 序向邏輯11. 合成 — 順序論理
12. Synthesis — Constructs12. 合成 — 語言結構12. 合成 — 言語構文
13. Design Examples13. 設計範例13. 設計例
14. Exam Essentials14. 考前重點14. 試験の要点
EE5733 · NSYSU EE · SNSD-IC LabEE5733 · 中山大學電機系 · SNSD-IC 實驗室EE5733 · 国立中山大学 電機工学系 · SNSD-IC ラボ

Digital Communication IC Design
Verilog HDL Self-Study Guide
數位通訊積體電路設計
Verilog HDL 自學指南
デジタル通信 IC 設計
Verilog HDL 自学ガイド

A consolidated study companion for Lectures 1–8 — design flow, Verilog syntax and semantics, simulation, delay modelling, behavioral description, synthesis rules, and the two capstone design examples.涵蓋第 1–8 講的整合式學習手冊 — 設計流程、Verilog 語法與語意、 模擬、延遲模型、行為描述、合成規則,以及兩個總結性的設計範例。第 1–8 講をまとめた学習ガイド — 設計フロー、Verilog の構文と意味、 シミュレーション、遅延モデル、動作記述、合成規則、そして 2 つの総仕上げの設計例。

Contents目次目次

  1. Digital IC Design Flow and Abstraction LEC 1-1數位 IC 設計流程與抽象層次 LEC 1-1デジタル IC 設計フローと抽象化 LEC 1-1
  2. Verilog Language Foundations LEC 1-2/1-3Verilog 語言基礎 LEC 1-2/1-3Verilog 言語の基礎 LEC 1-2/1-3
  3. Simulation and Testbenches LEC 2-1模擬與測試平台 LEC 2-1シミュレーションとテストベンチ LEC 2-1
  4. Data Types and Operators LEC 2-2資料型別與運算子 LEC 2-2データ型と演算子 LEC 2-2
  5. User-Defined Primitives LEC 3-1使用者自定原件 LEC 3-1ユーザー定義プリミティブ LEC 3-1
  6. Models of Propagation Delay LEC 3-2/3-3傳播延遲的模型 LEC 3-2/3-3伝搬遅延のモデル LEC 3-2/3-3
  7. Behavioral Descriptions LEC 4-1行為描述 LEC 4-1動作記述 LEC 4-1
  8. Tasks, Functions, and Timing Analysis LEC 4-2任務、函式與時序分析 LEC 4-2タスク・関数とタイミング解析 LEC 4-2
  9. Finite State Machines LEC 4-2/6有限狀態機 LEC 4-2/6有限状態機械 LEC 4-2/6
  10. Synthesis of Combinational Logic LEC 5組合邏輯的合成 LEC 5組合せ論理の合成 LEC 5
  11. Synthesis of Sequential Logic LEC 6序向邏輯的合成 LEC 6順序論理の合成 LEC 6
  12. Synthesis of Language Constructs LEC 7語言結構的合成 LEC 7言語構文の合成 LEC 7
  13. Design Examples LEC 8設計範例 LEC 8設計例 LEC 8
  14. Exam Essentials考前重點試験の要点
How to use this guide如何使用這份指南このガイドの使い方

Each section states the rule first, then shows the minimum code that demonstrates it, then flags the trap that the rule exists to prevent. Where the lecture slides asked a question ("what is the difference between always and forever?"), the answer is given in a collapsible box.每一節都先講規則,接著給出能說明該規則的最小程式碼,最後點出這條規則存在是為了避免哪個陷阱。凡是課堂投影片提出過的問題(例如「always 和 forever 有什麼不同?」),答案都放在可展開的方塊裡。各節はまず規則を述べ、次にそれを示す最小限のコードを挙げ、最後にその規則が防ごうとしている落とし穴を指摘します。講義スライドが問いかけていた点(たとえば「always と forever の違いは?」)については、答えを折りたたみボックスに収めてあります。

The single highest-yield idea in the whole course: Verilog is not a programming language, it is a notation for hardware. Every construct has three separate answers — what it simulates as, what it synthesizes to, and whether it synthesizes at all. Keep those three columns separate in your head and most of the exam becomes bookkeeping.整門課投報率最高的一個觀念:Verilog 不是程式語言,它是描述硬體的記法。每一個語法結構都有三個各自獨立的答案 — 它模擬出什麼行為、它合成成什麼電路,以及它到底能不能合成。把這三欄在腦中分清楚,大部分考題就只剩查表的功夫。この科目で最も費用対効果の高い一点:Verilog はプログラミング言語ではなく、ハードウェアを表す記法である。どの構文にも独立した 3 つの答えがあります — シミュレーションではどう振る舞うか、合成すると何になるか、そもそも合成できるのか。この 3 つの列を頭の中で分けておけば、試験の大半は表を引く作業になります。

1. Digital IC Design Flow and Abstraction1. 數位 IC 設計流程與抽象層次1. デジタル IC 設計フローと抽象化

1.1 The cell-based design flow1.1 Cell-based 設計流程1.1 セルベース設計フロー

The course places Verilog inside a larger industrial flow. Knowing where each tool sits is worth easy exam marks.本課程把 Verilog 放在一條更大的產業流程裡。知道每個工具落在哪個位置,是很好拿的考試分數。この講義は Verilog をより大きな産業フローの中に位置づけます。どのツールがどこに入るかを知っておくと、試験で確実に点が取れます。

FRONT END前段設計フロントエンド BACK END後段設計バックエンド Design Specification設計規格設計仕様 Design Partition設計分割設計分割 Design Entry設計輸入設計入力 Verilog behavioralVerilog 行為描述Verilog 動作記述 Simulation /模擬/シミュレーション/ Functional verify功能驗證機能検証 Integration &整合與統合と Verification驗證検証 Pre-Synth Sign-Off合成前簽核合成前サインオフ Synthesize & Map合成與映射合成とマッピング gate-level netlist閘級網表ゲートレベル・ネットリスト Post-Synth Validation合成後驗證合成後の検証 Post-Synth Timing合成後時序合成後タイミング Verification驗證検証 Test Gen (ATPG) &測試圖樣產生(ATPG)與テストパターン生成(ATPG)と Fault Simulation故障模擬故障シミュレーション Placement, Scan Chain,佈局、掃描鏈、配置・スキャンチェーン・ Clock Tree, Routing時脈樹、繞線クロックツリー・配線 Verify Physical &檢查實體與物理規則と Electrical Rules電性規則電気的規則の検証 Extract Parasitics萃取寄生參數寄生成分の抽出 Post-Layout Timing佈局後時序レイアウト後タイミング Design Sign-Off設計簽核設計サインオフ Production-Ready可量產的量産可能な Masks (Tape-Out)光罩(下線)マスク(テープアウト)
Cell-based design flow. The course lives in the front end (Verilog → synthesis → DFT/ATPG); APR, sign-off, and tape-out are the back end.Cell-based 設計流程。本課程活動在前段(Verilog → 合成 → DFT/ATPG); APR、簽核與下線屬於後段。セルベース設計フロー。この講義が扱うのはフロントエンド(Verilog → 合成 → DFT/ATPG)で、 APR・サインオフ・テープアウトはバックエンドです。
Flow vocabulary you must be able to expand必須能展開的流程術語展開できるようにしておくフロー用語
  • HDL — Hardware Description LanguageHDL — 硬體描述語言(Hardware Description Language)HDL — ハードウェア記述言語(Hardware Description Language)
  • DFT — Design for Testability (scan chain insertion)DFT — 可測試性設計(Design for Testability,插入掃描鏈)DFT — テスト容易化設計(Design for Testability、スキャンチェーン挿入)
  • ATPG — Automatic Test Pattern Generation (Synopsys TetraMAX)ATPG — 自動測試圖樣產生(Synopsys TetraMAX)ATPG — 自動テストパターン生成(Synopsys TetraMAX)
  • APR — Automatic Place and RouteAPR — 自動佈局繞線(Automatic Place and Route)APR — 自動配置配線(Automatic Place and Route)
  • TO — Tape-OutTO — 下線(Tape-Out)TO — テープアウト(Tape-Out)
  • PG / LA — Pattern Generator / Logic Analyzer, used for chip measurement after packagingPG / LA — 圖樣產生器/邏輯分析儀,用於封裝後的晶片量測PG / LA — パターンジェネレータ/ロジックアナライザ。パッケージ後のチップ測定に使用
  • DC / DV / RC — Synopsys Design Compiler / Design Vision, Cadence Encounter RTL Compiler — the synthesis toolsDC / DV / RC — Synopsys Design Compiler/Design Vision、Cadence Encounter RTL Compiler — 也就是合成工具DC / DV / RC — Synopsys Design Compiler/Design Vision、Cadence Encounter RTL Compiler — つまり合成ツール

The research-level loop the lecture draws is: choose a direction → pick a topic → simulate the algorithm (MATLAB/C) → write Verilog → verify the IC design → layout → fabrication → board assembly → chip measurement → compare against reference ICs. Verilog sits in the middle, and the algorithm simulation before it produces the golden pattern the testbench will later compare against.投影片畫出的研究層級循環是:選定方向 → 決定題目 → 模擬演算法(MATLAB/C)→ 撰寫 Verilog → 驗證 IC 設計 → 佈局 → 下線製造 → 電路板組裝 → 晶片量測 → 與參考 IC 比較。Verilog 位在中間,而在它之前的演算法模擬會產生測試平台日後要拿來比對的 golden pattern。講義が描く研究レベルのループは、方向を選ぶ → テーマを決める → アルゴリズムを(MATLAB/C で)シミュレーションする → Verilog を書く → IC 設計を検証する → レイアウト → 製造 → ボード実装 → チップ測定 → 参照 IC と比較、という流れです。Verilog はその中間にあり、その手前のアルゴリズムシミュレーションが、後でテストベンチが比較に使う golden pattern を生み出します。

1.2 Levels of abstraction1.2 抽象層次1.2 抽象化のレベル

System concept系統概念システム構想 Algorithm演算法アルゴリズム Architecture架構アーキテクチャ RTLRTLRTL Gate閘級ゲート Transistor電晶體トランジスタ increasing行為抽象動作の抽象度が behavioral程度上がる abstraction越高方向 increasing detail細節與複雜度細部と複雑さが & complexity越高増える方向
The behavioral model hierarchy. RTL (highlighted) is the level at which you hand a design to a synthesis tool.行為模型的層次。RTL(標示處)就是把設計交給合成工具的那一層。動作モデルの階層。RTL(強調部分)が、設計を合成ツールに渡すレベルです。
Level層次レベルWhat the model describes模型描述的內容モデルが記述するものTypical artefact典型產出典型的な成果物
Architectural / Algorithmic架構級/演算法級アーキテクチャ級/アルゴリズム級the algorithm, in high-level language constructs以高階語言結構表達的演算法高水準言語の構文で表したアルゴリズムC / MATLAB, behavioral VerilogC/MATLAB、行為級 VerilogC/MATLAB、動作レベルの Verilog
RTLRTLRTLflow of data between registers and how the design processes it資料在暫存器之間的流動,以及設計如何處理它レジスタ間のデータの流れと、その処理のしかたsynthesizable Verilog可合成的 Verilog合成可能な Verilog
Gate閘級ゲート級logic gates and their interconnections邏輯閘與它們之間的連接論理ゲートとその相互接続netlist from synthesis合成產生的網表合成が出力するネットリスト
Transistor電晶體級トランジスタ級transistors and their interconnections電晶體與它們之間的連接トランジスタとその相互接続SPICE, standard-cell layoutSPICE、標準單元佈局SPICE、スタンダードセル・レイアウト

1.3 Design model domains1.3 設計模型的三個領域1.3 設計モデルの 3 つの領域

The same design can be viewed in three domains at each level: abstract (behavior), structural (connectivity), and physical (geometry). Moving down the abstract column is design; moving rightwards from abstract to structural is synthesis; comparing the two is verification.同一份設計在每一層都可以從三個領域來看:抽象(行為)、結構(連接關係)與實體(幾何形狀)。沿著抽象那一欄往下走是設計;從抽象往右走到結構是合成;把兩者互相比對則是驗證。同じ設計は、どのレベルでも 3 つの領域から眺められます:抽象(動作)、構造(接続関係)、物理(幾何形状)。抽象の列を下に降りるのが設計、抽象から構造へ右に移るのが合成、両者を突き合わせるのが検証です。

Naming the synthesis steps為各個合成步驟命名合成の各ステップの呼び名
  • System → Architecture: architecture synthesis系統 → 架構:架構合成システム → アーキテクチャ:アーキテクチャ合成
  • Algorithm → RTL: RTL-level synthesis (high-level synthesis)演算法 → RTL:RTL 級合成(高階合成)アルゴリズム → RTL:RTL レベル合成(高位合成)
  • RTL → Gate: logic-level synthesis — this is what Design Compiler doesRTL → 閘級:邏輯級合成 — 這就是 Design Compiler 做的事RTL → ゲート:論理レベル合成 — Design Compiler が行うのはこれです
  • Gate → Transistor/geometry: layout design (APR)閘級 → 電晶體/幾何:佈局設計(APR)ゲート → トランジスタ/幾何:レイアウト設計(APR)

2. Verilog Language Foundations2. Verilog 語言基礎2. Verilog 言語の基礎

2.1 Modules and ports2.1 模組與埠2.1 モジュールとポート

The module is the basic building block — Verilog's design entity. Three facts about modules carry most of the exam weight:module 是最基本的組成單位 — Verilog 的設計實體。關於模組有三件事佔了大部分的考試分數:module は最も基本的な構成単位、すなわち Verilog の設計エンティティです。モジュールについて試験の配点の大半を占めるのは次の 3 点です。

module test (a, b, c, d);
  input  a, b;          // default net type: wire
  output c, d;
  wire   c, d;          // explicit, but redundant here

  assign c = a | b;     // continuous assignment, drives a net
  assign d = a & b;
endmodule

2.2 Nets versus registers — the central distinction2.2 net 與 register — 最核心的區別2.2 net と register — 中心となる区別

Verilog splits every signal into one of two families. Almost every "why does this not compile?" question in the course reduces to putting a signal in the wrong family.Verilog 把每個訊號分成兩大家族。這門課裡幾乎所有「為什麼這段編不過?」的問題,追根究柢都是把訊號放錯了家族。Verilog はすべての信号をこの 2 つの系統のいずれかに分類します。この講義で出てくる「なぜコンパイルが通らないのか」という疑問は、ほぼすべて信号を誤った系統に置いたことに帰着します。

NetNetNetRegisterRegisterRegister
Keywords關鍵字キーワード wire, wand, wor, tri, triand, trior, supply0, supply1wire、wand、wor、tri、triand、 trior、supply0、supply1wire、wand、wor、tri、triand、 trior、supply0、supply1 reg, integer, time, real, realtimereg、integer、time、real、realtimereg、integer、time、real、realtime
Meaning意義意味structural connectivity — a wire, stores nothing結構上的連接 — 一條線,本身不儲存任何東西構造的な接続 — ただの配線であり、何も保持しない abstraction of storage — holds a value between events儲存的抽象 — 在事件之間保住一個值記憶の抽象 — イベントとイベントの間、値を保持する
Assigned by由什麼賦值何によって代入されるかassign (continuous), or by being driven by a primitive or module outputassign(連續賦值),或被原件、模組輸出所驅動assign(連続代入)、またはプリミティブやモジュール出力に駆動されること procedural statement inside always/initial, a task, a function, or a sequential UDPalways/initial、task、function 或序向 UDP 內的程序式敘述always/initial、task、function、順序回路 UDP の中の手続き文
May NOT be不可以是次にはできないthe target of a procedural assignment inside alwaysalways 內程序式賦值的目標always 内の手続き型代入の左辺 the output of a primitive gate; the target of a continuous assign原件閘的輸出;連續 assign 的目標プリミティブゲートの出力、および連続 assign の左辺
Initial value at time 0時間 0 的初始值時刻 0 での初期値x if driven, z if undriven被驅動時為 x,未被驅動時為 z駆動されていれば x、駆動されていなければ z x
The single most common misconception最常見的一個誤解最もよくある誤解

Declaring a signal reg does not mean a flip-flop will be synthesized. reg is only a simulation-time storage abstraction: it says "this variable must hold its value between procedural assignments". Whether real hardware storage appears depends entirely on the sensitivity list and whether the value is fully assigned in every branch.把訊號宣告成 reg 並不代表就會合成出正反器。reg 只是模擬時的儲存抽象:它表示「這個變數必須在兩次程序式賦值之間保住自己的值」。真正的硬體儲存元件會不會出現,完全取決於敏感度列表,以及這個值是否在每個分支中都被賦值。信号を reg と宣言しても、フリップフロップが合成されるという意味ではありません。reg はシミュレーション上の記憶の抽象にすぎず、「この変数は手続き型代入と代入の間で値を保持しなければならない」ことを表すだけです。実際のハードウェア記憶素子ができるかどうかは、センシティビティリストと、すべての分岐で値が代入されているかどうかで決まります。

module test (a, b, c, d);
  input  a, b;
  output c, d;
  reg    c, d;          // required because they are assigned procedurally

  always @ (a or b) begin   // sensitivity list
    c = a | b;
    d = a & b;
  end
endmodule

This synthesizes to exactly the same two gates as the assign version above — no latches, no flip-flops — because the sensitivity list is complete and both targets are assigned unconditionally.這段合成出來的結果,和上面用 assign 的版本完全相同 — 就是那兩個閘,沒有鎖存器、也沒有正反器 — 因為敏感度列表是完整的,而且兩個目標都被無條件賦值。これは上の assign 版とまったく同じ 2 つのゲートに合成されます — ラッチもフリップフロップも生じません — センシティビティリストが完全で、両方の対象が無条件に代入されているからです。

Scope作用範圍スコープ

The scope of a variable is the module, task, function, or named begin…end block in which it is declared. To reach inside an instantiated module from a testbench, use a hierarchical path name: X.w, or X.Y.Z.w. This is legal in testbenches and is how force reaches internal nodes; it is not synthesizable.一個變數的作用範圍是宣告它的那個 module、task、function,或具名的 begin…end 區塊。若要從測試平台伸進被實體化的模組內部,要用階層路徑名稱:X.w 或 X.Y.Z.w。這在測試平台中是合法的,也是 force 能碰到內部節點的方式;但它不可合成。変数のスコープは、それを宣言した module・task・function、または名前付きの begin…end ブロックです。テストベンチからインスタンス化したモジュールの内部に手を伸ばすには、階層パス名(X.w や X.Y.Z.w)を使います。テストベンチでは合法で、force が内部ノードに届くのもこの仕組みですが、合成はできません。

2.3 The four-value logic system2.3 四值邏輯系統2.3 4 値論理システム

Value值値Meaning意義意味
0logic zero / FALSE邏輯零/FALSE論理ゼロ/FALSE
1logic one / TRUE邏輯一/TRUE論理イチ/TRUE
x or Xx 或 Xx または Xunknown, ambiguous — the simulator cannot decide未知、無法判定 — 模擬器決定不了不定・あいまい — シミュレータが決められない
z or Zz 或 Zz または Zhigh impedance, open circuit, undriven高阻抗、開路、無人驅動ハイインピーダンス、開放、無駆動

Logic values are not case-sensitive (x and X are the same); identifiers and keywords are.邏輯值不分大小寫(x 和 X 相同);識別字與關鍵字則會分。論理値は大文字・小文字を区別しません(x と X は同じ)。一方、識別子とキーワードは区別します。

The AND truth table over four values is the one to memorise, because it shows the asymmetry that makes x propagation tolerable:四值下的 AND 真值表最該背起來,因為它呈現出讓 x 的傳播不至於失控的那種不對稱性:4 値の AND 真理値表は覚えておくべきものです。x の伝播が許容できるものになる非対称性が、そこに現れているからです。

&01xz
00000
101xx
x0xxx
z0xxx
Why row and column 0 are all zeros為什麼第 0 列與第 0 行全都是零0 の行と列がすべてゼロになる理由

A controlling value dominates. 0 & anything = 0 even if the other input is unknown, because no value of the unknown input can change the answer. Likewise 1 | x = 1. Everywhere else the unknown leaks through and the output becomes x. Note that z on the input of a logic gate behaves like x, never like a third logic level.控制值會壓過一切。即使另一個輸入是未知的,0 & anything = 0 仍然成立,因為未知輸入不論取什麼值都改變不了答案。同理 1 | x = 1。其他地方未知就會滲出來,輸出變成 x。注意邏輯閘輸入端的 z 行為等同於 x,絕不是第三種邏輯準位。支配値がすべてに優先します。もう一方の入力が不定でも 0 & anything = 0 は成り立ちます。不定の入力がどんな値であっても答えは変わらないからです。同様に 1 | x = 1 です。それ以外の場所では不定が漏れ出て、出力は x になります。論理ゲートの入力の z は x と同じ扱いであり、第 3 の論理レベルではない点に注意してください。

2.4 Number literals2.4 數值常量2.4 数値リテラル

Literal syntax常量語法リテラルの構文

<[size]> <'base_format> <number><[位元數]> <'底數格式> <數值><[サイズ]> <'基数> <数値>

Two rules govern what happens when size and value disagree:位元數與數值不吻合時,由兩條規則決定結果:サイズと値が食い違うときは、次の 2 つの規則が結果を決めます。

Literal常量リテラルExpands to展開成展開結果Note說明備考
8'b10100000_1010decimal 10十進位 10十進の 10
6'b01011101_0111exact fit剛好放得下ちょうど収まる
8'b01100000_0110zero-padded左邊補零ゼロ埋め
4'bx014'bx014'bx01xx01xx01xx01leading x extends開頭的 x 會延伸先頭の x が拡張される
16'H3AB16'H3AB16'H3AB0000_0011_1010_1011
12'd240000_0001_1000
5'O3611110octal 36 is 6 bits, truncated to 5八進位 36 佔 6 位元,被截成 5 位元八進の 36 は 6 ビットなので 5 ビットに切り詰められる
16'Hx16'Hx16'Hxxxxx_xxxx_xxxx_xxxxxxxx_xxxx_xxxx_xxxxxxxx_xxxx_xxxx_xxxxx extends across all 16 bitsx 延伸填滿全部 16 個位元x が 16 ビット全体に拡張される
8'hz8'hz8'hzzzzz_zzzzzzzz_zzzzzzzz_zzzzz extends tooz 也會延伸z も拡張される
3'b5illegal — digit 5 is not valid in base 2不合法 — 數字 5 在二進位裡不成立不正 — 数字の 5 は 2 進では使えない

2.5 The three descriptive styles2.5 三種描述風格2.5 3 つの記述スタイル

Verilog lets you mix all three freely inside one module. The exam habitually asks you to write the same circuit in all three.Verilog 允許在同一個模組裡自由混用這三種風格。考試很習慣要你把同一個電路用三種風格各寫一次。Verilog では 1 つのモジュール内で 3 つのスタイルを自由に混ぜられます。試験では同じ回路を 3 つのスタイルすべてで書かせるのが定番です。

Style風格スタイルMechanism機制仕組みAbstraction抽象程度抽象度
1. Behavioral1. 行為描述1. 動作記述procedural assignments in always/initial, with if, case, loops, timing control在 always/initial 裡的程序式賦值,搭配 if、case、迴圈與時序控制always/initial の中の手続き型代入。if、case、ループ、タイミング制御を伴うhighest最高最も高い
2. RTL / dataflow2. RTL/資料流2. RTL/データフローcontinuous assign statements; combinational logic plus registers連續 assign 敘述;組合邏輯加上暫存器連続 assign 文。組合せ論理とレジスタmiddle中間中間
3. Structural3. 結構描述3. 構造記述instantiation of primitives, UDPs, and modules實體化原件、UDP 與模組プリミティブ・UDP・モジュールのインスタンス化lowest (gate and transistor)最低(閘級與電晶體級)最も低い(ゲート級・トランジスタ級)
Practice 1 — One full adder, three styles練習 1 — 一個全加器,三種風格演習 1 — 全加算器を 3 つのスタイルで

Problem: Write a 1-bit full adder (S, CO, A, B, CI) in behavioral, RTL, and structural style. For the structural version, build it from two half adders and an OR gate.題目:用行為、RTL 與結構三種風格各寫一次 1 位元全加器 (S, CO, A, B, CI)。結構版請用兩個半加器加一個 OR 閘組成。問題:1 ビット全加算器 (S, CO, A, B, CI) を、動作記述・RTL・構造記述の 3 つのスタイルで書きなさい。構造記述版は半加算器 2 個と OR ゲート 1 個で構成すること。

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

Style 1 — Behavioral風格 1 — 行為描述スタイル 1 — 動作記述

module fa_bhv (S, CO, A, B, CI);
  output S, CO;
  input  A, B, CI;
  reg    S, CO;         // required to hold values between events

  always @ (A or B or CI) begin
    S  = A ^ B ^ CI;                    // procedural assignment
    CO = A & B | A & CI | B & CI;
  end
endmodule

Style 2 — RTL / dataflow風格 2 — RTL/資料流スタイル 2 — RTL/データフロー

module fa_rtl (S, CO, A, B, CI);
  output S, CO;
  input  A, B, CI;

  assign S  = A ^ B ^ CI;               // continuous assignment
  assign CO = A & B | A & CI | B & CI;
endmodule

Style 3 — Structural風格 3 — 結構描述スタイル 3 — 構造記述

module half_add (S, C, X, Y);
  output S, C;
  input  X, Y;
  xor (S, X, Y);        // primitive: output first, then inputs
  and (C, X, Y);
endmodule

module full_add (S, CO, A, B, CI);
  output S, CO;
  input  A, B, CI;
  wire   N1, N2, N3;

  or       P1  (CO, N3, N2);            // primitive with instance name P1
  half_add HA1 (N1, N2, A,  B),         // module instances
           HA2 (S,  N3, N1, CI);
endmodule

Points to note. In fa_bhv, S and CO must be reg; in fa_rtl they stay nets. All three synthesize to the same logic. In the structural version the primitive port order is outputs first, then inputs — always. The instance name on a primitive (P1) is optional; on a module instance it is mandatory.要注意的地方。在 fa_bhv 裡,S 與 CO 必須是 reg;在 fa_rtl 裡它們仍是 net。三者合成出來的邏輯完全相同。結構版中原件的埠順序永遠是輸出在前、輸入在後。原件實體的名稱(P1)可以省略;模組實體的名稱則是必要的。注意点。fa_bhv では S と CO を reg にしなければなりませんが、fa_rtl ではネットのままです。3 つとも同じ論理に合成されます。構造記述版では、プリミティブのポート順序は必ず出力が先、入力が後です。プリミティブのインスタンス名(P1)は省略できますが、モジュールのインスタンス名は必須です。

2.6 Instantiation and hierarchy2.6 實體化與階層2.6 インスタンス化と階層

Hierarchy is created by module instantiation. Rules:階層是由模組實體化建立的。規則如下:階層はモジュールのインスタンス化によって作られます。規則は次のとおりです。

// by position — order must match the declaration exactly
full_add FA0 (sum[0], c1, a[0], b[0], cin);

// by name — order is irrelevant, far safer for wide port lists
full_add FA0 (.S(sum[0]), .CO(c1), .A(a[0]), .B(b[0]), .CI(cin));

// empty port — leave an output unconnected
full_add FA0 (.S(sum[0]), .CO(), .A(a[0]), .B(b[0]), .CI(cin));

Array of instances實體陣列インスタンス配列

When the same bit-wise operation repeats across a vector, an array of instances is more compact than writing each one out:當同一個位元運算要在整個向量上重複時,用實體陣列會比一個一個寫出來簡潔得多:同じビット単位の演算がベクタ全体で繰り返されるときは、1 つずつ書き下すよりインスタンス配列のほうがはるかに簡潔です。

wire [3:0] a, b, y;
and A[3:0] (y, a, b);      // four AND gates: y[i] = a[i] & b[i]

A 16-bit ripple-carry adder built this way chains the carry through a wire vector:用這種寫法做出的 16 位元漣波進位加法器,會透過一條線向量把進位串起來:この書き方で作る 16 ビットのリップルキャリー加算器は、配線ベクタを通してキャリーを連結します。

module rca16 (sum, cout, a, b, cin);
  output [15:0] sum;  output cout;
  input  [15:0] a, b; input  cin;
  wire   [16:0] c;

  assign c[0] = cin;
  assign cout = c[16];

  full_add FA [15:0] (sum, c[16:1], a, b, c[15:0]);
endmodule

2.7 Language conventions2.7 語言慣例2.7 言語の約束事

Practice 2 — Number literals and part-selects練習 2 — 數值常量與部分選取演習 2 — 数値リテラルと部分選択

Problem: Given word = 8'b1100_0100, evaluate (a) word[3:0], (b) word[5:1], (c) word[7:5], (d) word[9:4]. Then state the bit pattern of (e) 4'bx01 and (f) 5'O36.題目:已知 word = 8'b1100_0100,求 (a) word[3:0]、(b) word[5:1]、(c) word[7:5]、(d) word[9:4]。 再寫出 (e) 4'bx01 與 (f) 5'O36 的位元樣式。問題:word = 8'b1100_0100 のとき、 (a) word[3:0]、(b) word[5:1]、(c) word[7:5]、(d) word[9:4] を求めなさい。 さらに (e) 4'bx01 と (f) 5'O36 のビットパターンを答えなさい。

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

Index the vector using the declared range. With [7:0], bit 7 is the leftmost bit of 1100_0100.用宣告時的範圍去索引向量。宣告為 [7:0] 時,第 7 位元是 1100_0100 最左邊那一位。宣言した範囲に従ってベクタを添字付けします。[7:0] と宣言した場合、ビット 7 は 1100_0100 の左端のビットです。

  • (a) word[3:0] = 4'b0100(a) word[3:0] = 4'b0100(a) word[3:0] = 4'b0100
  • (b) word[5:1] = 5'b00010 — bits 5,4,3,2,1 are 0,0,0,1,0(b) word[5:1] = 5'b00010 — 第 5,4,3,2,1 位元依序是 0,0,0,1,0(b) word[5:1] = 5'b00010 — ビット 5,4,3,2,1 は順に 0,0,0,1,0
  • (c) word[7:5] = 3'b110(c) word[7:5] = 3'b110(c) word[7:5] = 3'b110
  • (d) word[9:4] is an illegal select — index out of bounds. Verilog returns x rather than erroring, which is exactly why you should never write it: the bug is silent.(d) word[9:4] 是不合法的選取 — 索引超出範圍。Verilog 會回傳 x 而不是報錯,這正是絕對不該這樣寫的理由:錯誤是無聲的。(d) word[9:4] は不正な選択です — 添字が範囲外だからです。Verilog はエラーを出さずに x を返します。これこそ、こう書いてはいけない理由です。バグが表に出ません。
  • (e) 4'bx01 = xx01 — the leading x extends to fill.(e) 4'bx01 = xx01 — 開頭的 x 會延伸填滿。(e) 4'bx01 = xx01 — 先頭の x が拡張して埋めます。
  • (f) 5'O36: octal 3 is 011, octal 6 is 110, giving 011110, truncated from the left to 5 bits, so 11110.(f) 5'O36:八進位的 3 是 011、6 是 110,合起來是 011110,從左截成 5 位元後得到 11110。(f) 5'O36:八進の 3 は 011、6 は 110 なので 011110 となり、左から切り詰めて 5 ビットにすると 11110 です。

Rule to remember: the MSB of a part-select is the leftmost index, the LSB is the rightmost. Out of bounds returns x — avoid.要記住的規則:部分選取的 MSB 是最左邊的索引、LSB 是最右邊的。超出範圍會回傳 x — 避免這樣寫。覚えておく規則:部分選択の MSB は左端の添字、LSB は右端の添字です。範囲外は x を返すので、書かないこと。

3. Simulation and Testbenches3. 模擬與測試平台3. シミュレーションとテストベンチ

3.1 Event-driven simulation3.1 事件驅動模擬3.1 イベント駆動シミュレーション

Definition定義定義

A change in the value of a signal during simulation is an event. Simulation is event-driven if new values are computed only for signals affected by events that have already occurred, and only at those times when a change can occur.模擬過程中訊號值的一次改變稱為一個事件。若新值只為那些受已發生事件影響的訊號計算,而且只在可能發生變化的那些時刻計算,這樣的模擬就是事件驅動的。シミュレーション中に信号の値が変化することをイベントといいます。すでに発生したイベントの影響を受ける信号だけについて、しかも変化が起こりうる時刻だけで新しい値を計算するとき、そのシミュレーションはイベント駆動であるといいます。

The simulator maintains a time-ordered event list. Initial events are the input changes in the testbench; executing them schedules further events at later times. Simulation stops when the event list becomes empty — or when $finish is executed, whichever comes first.模擬器維護一份依時間排序的事件清單。最初的事件是測試平台中的輸入變化;執行它們會排程更晚時刻的後續事件。當事件清單變空時模擬就停止 — 或是執行到 $finish,以先發生者為準。シミュレータは時刻順のイベントリストを保持します。最初のイベントはテストベンチでの入力変化であり、それを実行するとより後の時刻に新たなイベントが登録されます。イベントリストが空になるとシミュレーションは停止します — あるいは $finish が実行されたときで、どちらか早いほうです。

3.2 Delay in simulation, and the inertial rule3.2 模擬中的延遲與慣性規則3.2 シミュレーションにおける遅延と慣性の規則

With no delay specified, a gate produces its result immediately (zero response time). With a gate delay, the output is scheduled delay time units later. But Verilog gate delay is inertial, not transport, and that has a consequence that is a perennial exam question.沒有指定延遲時,閘會立即產生結果(反應時間為零)。有閘延遲時,輸出會被排程在延遲個時間單位之後。但 Verilog 的閘延遲是慣性延遲而非傳輸延遲,這件事帶來的後果是歷年必考題。遅延を指定しなければ、ゲートは即座に結果を出します(応答時間ゼロ)。ゲート遅延がある場合、出力は遅延時間単位だけ後に登録されます。ただし Verilog のゲート遅延は伝送遅延ではなく慣性遅延であり、その帰結は毎年のように試験に出ます。

Inertial delay — the pulse-swallowing rule慣性延遲 — 脈衝被吞掉的規則慣性遅延 — パルスが飲み込まれる規則

Inertial delay is the amount of time an input pulse must endure for the output to respond. Verilog uses the propagation delay as the inertial delay. Consequently, multiple events cannot occur on the output in a time period shorter than the inertial delay — an input pulse narrower than the gate delay is swallowed entirely and never appears at the output.慣性延遲是輸入脈衝必須持續多久,輸出才會有反應。Verilog 直接把傳播延遲當成慣性延遲。因此,輸出上不可能在短於慣性延遲的時間內發生兩個以上的事件 — 比閘延遲還窄的輸入脈衝會被整個吞掉,根本不會出現在輸出端。慣性遅延とは、出力が反応するために入力パルスが持続していなければならない時間のことです。Verilog は伝搬遅延をそのまま慣性遅延として使います。したがって、慣性遅延より短い間隔で出力に複数のイベントが起こることはありません — ゲート遅延より狭い入力パルスは丸ごと飲み込まれ、出力には現れません。

A B O = A&B 3 ns overlap — passes重疊 3 ns — 通過3 ns 重なる — 通過 1 ns overlap重疊 1 ns1 ns しか重ならない 2 ns2 ns2 ns swallowed — no output event被吞掉 — 輸出無事件飲み込まれる — 出力イベントなし time (1 division = 1 ns)時間(1 格 = 1 ns)時間(1 目盛 = 1 ns)
AND gate with 2 ns inertial delay. The first coincidence of A and B lasts 3 ns, which exceeds the inertial delay, so O pulses 2 ns later. The second coincidence lasts only 1 ns and produces no output event at all — the pulse is swallowed.慣性延遲為 2 ns 的 AND 閘。A 與 B 第一次重合持續 3 ns,超過慣性延遲,所以 O 在 2 ns 後跟著出現脈衝。第二次重合只有 1 ns,完全不產生輸出事件 — 脈衝被吞掉了。慣性遅延 2 ns の AND ゲート。A と B の最初の重なりは 3 ns 続き、慣性遅延を超えるので、O は 2 ns 後にパルスを出します。2 回目の重なりは 1 ns しかなく、出力イベントはまったく生じません — パルスが飲み込まれたのです。
Practice 3 — Delay through a small network練習 3 — 通過小型網路的延遲演習 3 — 小さな回路網を通る遅延

Problem: An AND gate has 3 ns delay and an inverter has 2 ns delay. Signal a rises at $t=0$. It feeds both an inverter and, together with the inverter's output, an AND gate, so y = a & ~a. (a) What does the simulator produce? (b) What would the same circuit produce with zero delay? (c) What real phenomenon does this model?題目:AND 閘延遲 3 ns,反相器延遲 2 ns。訊號 a 在 $t=0$ 上升,它同時接到反相器,並與反相器輸出一起接到 AND 閘,因此 y = a & ~a。(a) 模擬器會得到什麼?(b) 若延遲全為零,同一電路會得到什麼?(c) 這個模型對應到現實中的什麼現象?問題:AND ゲートの遅延は 3 ns、インバータの遅延は 2 ns とします。信号 a は $t=0$ で立ち上がり、インバータに入るとともに、インバータ出力と一緒に AND ゲートへ入ります。つまり y = a & ~a です。(a) シミュレータは何を出力しますか。(b) 遅延がすべてゼロなら同じ回路は何を出しますか。(c) これは現実のどんな現象のモデルですか。

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

(a) At $t=0$, a goes 0→1. The AND gate sees a=1 immediately, but ~a is still 1 until $t=2$ ns. So the AND input pair is (1,1) during $0 \le t \lt 2$ ns — a 2 ns wide glitch at the AND's input. The AND has 3 ns of inertial delay. Since $2 \lt 3$, the glitch is swallowed and y stays 0.(a) 在 $t=0$,a 由 0→1。AND 閘立刻看到 a=1,但 ~a 要到 $t=2$ ns 才變,在那之前仍是 1。所以在 $0 \le t \lt 2$ ns 期間 AND 的兩個輸入是 (1,1) — 也就是 AND 輸入端一個 2 ns 寬的突波。AND 的慣性延遲是 3 ns,因為 $2 \lt 3$,這個突波被吞掉,y 維持 0。(a) $t=0$ で a が 0→1 に変わります。AND ゲートは即座に a=1 を見ますが、~a は $t=2$ ns までまだ 1 のままです。したがって $0 \le t \lt 2$ ns の間、AND の入力対は (1,1) — AND の入力に幅 2 ns のグリッチが立ちます。AND の慣性遅延は 3 ns で $2 \lt 3$ なので、グリッチは飲み込まれ、y は 0 のままです。

(b) With zero delay, ~a updates in the same time step, the AND never sees (1,1), and y is identically 0. Same final answer, different reason.(b) 延遲為零時,~a 在同一個時間步就更新,AND 從來不會看到 (1,1),y 恆為 0。答案相同,理由不同。(b) 遅延がゼロなら ~a は同じ時間ステップで更新されるので、AND が (1,1) を見ることはなく、y は恒等的に 0 です。答えは同じでも理由が違います。

(c) This models a static hazard (glitch) caused by unequal path delays. The inertial-delay rule decides whether a real gate is fast enough to pass the glitch on. If the inverter delay had been 4 ns instead of 2 ns, the glitch would be 4 ns wide, exceed the AND's 3 ns inertia, and a spurious pulse would appear on y from $t=4$ to $t=7$ ns.(c) 這是路徑延遲不相等所造成的靜態危障(突波)模型。慣性延遲規則決定了真實的閘是否快到足以把這個突波傳下去。如果反相器延遲是 4 ns 而不是 2 ns,突波就會有 4 ns 寬,超過 AND 的 3 ns 慣性,於是 y 上真的會在 $t=4$ 到 $t=7$ ns 之間出現一個假脈衝。(c) これは経路遅延の不一致による静的ハザード(グリッチ)のモデルです。慣性遅延の規則が、実際のゲートがそのグリッチを通すほど速いかどうかを決めます。インバータの遅延が 2 ns ではなく 4 ns なら、グリッチ幅は 4 ns となって AND の 3 ns の慣性を超え、y には $t=4$ から $t=7$ ns にかけて偽のパルスが実際に現れます。

3.3 Testbench anatomy3.3 測試平台的結構3.3 テストベンチの構成

TESTBENCH (not synthesizable)測試平台(不可合成)テストベンチ(合成不可) Input輸入入力 pattern圖樣パターン Golden標準答案ゴールデン pattern圖樣パターン Design Under待測被試験 Test (DUT)設計(DUT)回路(DUT) Compare比較比較 (equal?)(相等?)(一致?) Check檢查出力結果を output result輸出結果確認
Testbench structure. The golden pattern is produced by independent software (C/C++, MATLAB) so that the comparison is a genuine check rather than a restatement of the design.測試平台的結構。golden pattern 由獨立的軟體(C/C++、MATLAB)產生,這樣比較才是真正的檢查,而不是把設計再講一遍。テストベンチの構成。ゴールデンパターンは独立したソフトウェア(C/C++、MATLAB)で生成します。そうしてはじめて比較が本当の検査になり、設計の言い換えに終わりません。
What a testbench is and is not測試平台是什麼、不是什麼テストベンチとは何で、何ではないか
  • It cannot be synthesized — it is behavioral modelling only.它不能被合成 — 純粹是行為建模。合成できません — 動作モデリングにすぎません。
  • It detects syntax violations, simulates circuit behavior, and monitors output results.它可以找出語法違規、模擬電路行為,並監看輸出結果。構文違反の検出、回路動作のシミュレーション、出力結果の監視を行います。
  • It is not real hardware; write it like C/C++.它不是真的硬體;把它當成 C/C++ 來寫。本物のハードウェアではありません。C/C++ を書くつもりで書きます。
  • There is no firm rule for how to write one. Be systematic anyway.怎麼寫沒有硬性規則。但還是要有系統地寫。書き方に決まった規則はありません。それでも体系立てて書くべきです。

The system tasks every testbench uses每個測試平台都會用到的系統任務どのテストベンチでも使うシステムタスク

Construct語法結構構文Purpose用途用途
initialinitialinitialdeclares a one-shot behavior — runs once, starting at time 0宣告一次性的 behavior — 從時間 0 開始,只跑一次一度だけ実行される behavior を宣言する — 時刻 0 から 1 回だけ動く
$monitor$monitor$monitorcontinuously watches its arguments; prints whenever any of them changes持續監看其引數;只要其中任何一個改變就印出引数を監視し続け、そのうちいずれかが変化するたびに出力する
$display$display$displayprints once, immediately, when encountered被執行到時立刻印一次実行された時点で直ちに 1 回出力する
$time$time$timecurrent simulation time as a 64-bit integer ($realtime for floating point)以 64 位元整數表示的目前模擬時間(浮點版為 $realtime)現在のシミュレーション時刻を 64 ビット整数で返す(浮動小数点版は $realtime)
$stop$stop$stophalts the simulator into interactive mode — you can still resume讓模擬器停進互動模式 — 仍可繼續執行シミュレータを対話モードで停止させる — 再開できる
$finish$finish$finishends the simulation and returns control to the operating system結束模擬並把控制權交還作業系統シミュレーションを終了し、制御をオペレーティングシステムに返す
`timescale 1ns/10ps

module tb_fa;
  reg  A, B, CI;
  wire S, CO;

  fa_rtl DUT (.S(S), .CO(CO), .A(A), .B(B), .CI(CI));   // connect by name

  initial
    $monitor("t=%0d A=%b B=%b CI=%b -> CO=%b S=%b", $time, A, B, CI, CO, S);

  initial begin
    {A,B,CI} = 3'b000;
    repeat (7) #10 {A,B,CI} = {A,B,CI} + 1'b1;          // sweep all 8 cases
    #10 $finish;
  end
endmodule
$display versus $monitor (click to expand)$display 與 $monitor 的差別(點擊展開)$display と $monitor の違い(クリックで展開)

$display prints once, at the moment it is executed, and then forgets about it. $monitor needs to be called only once; after that it prints automatically whenever any signal in its argument list changes, until it is switched off or the simulation ends.$display 在被執行到的當下印一次,之後不再管。$monitor 只需要 呼叫一次,之後只要參數清單中任何一個訊號改變就自動印出,直到被關閉或模擬結束。$display は実行された瞬間に 1 回だけ出力し、その後は何もしません。$monitor は一度呼び出せば十分で、以後は引数リストのいずれかの信号が変化するたびに自動的に出力し、それが解除されるかシミュレーションが終わるまで続きます。

One subtlety of scheduling is worth remembering: within the same time step, $display executes before the non-blocking assignments complete, whereas $monitor executes at the end of that time step. The two can therefore print different values from the same piece of code — a favourite exam trap.排程上的細微差異值得記住:在同一個時間步內,$display 會在 non-blocking assignment 完成之前執行,而 $monitor 在該時間步的 最後才執行。因此同一段程式裡兩者印出的值可能不同 — 這是常考的陷阱。スケジューリング上の細かな違いを覚えておく価値があります。同じ時間ステップ内で、$display はノンブロッキング代入が完了する前に実行されるのに対し、$monitor はその時間ステップの最後に実行されます。そのため同じコードでも両者が異なる値を表示することがあり、試験で好んで問われる落とし穴です。

File I/O and memory loading檔案 I/O 與記憶體載入ファイル I/O とメモリのロード

Compiler directives編譯器指令コンパイラディレクティブ

Directive指令ディレクティブExample範例例Effect作用効果
`timescale`timescale`timescale`timescale 1ns/10ps`timescale 1ns/10ps`timescale 1ns/10pstime unit / precision時間單位/精度時間単位/精度
`include`include`include`include "testbench.v"`include "testbench.v"`include "testbench.v"textual inclusion文字層級的檔案引入テキストとしての取り込み
`default_nettype`default_nettype`default_nettype`default_nettype wor`default_nettype wor`default_nettype worchange the implicit net type改變隱含的 net 型別暗黙のネット型を変更する
`define / `undef`define/`undef`define/`undef`define wait_state 3'b010`define wait_state 3'b010`define wait_state 3'b010macro definition, referenced as `wait_state巨集定義,引用時寫成 `wait_stateマクロ定義。参照するときは `wait_state と書く
Design side, testbench side設計端與測試平台端設計側とテストベンチ側

Design: real hardware; every module instance exists all the time; every module has an architecture figure — draw the figure before writing the code.
Testbench: not hardware; behavioral level; feeds input patterns and compares outputs versus time.
設計端:真實硬體;每個模組實體隨時都存在;每個模組都有一張架構圖 — 先畫圖,再寫程式。
測試平台端:不是硬體;屬於行為層級;負責餵入輸入圖樣,並隨時間比對輸出。
設計側:本物のハードウェア。モジュールのインスタンスは常に存在し、どのモジュールにもアーキテクチャ図がある — コードを書く前に図を描くこと。
テストベンチ側:ハードウェアではなく動作レベル。入力パターンを与え、時間に沿って出力を比較します。

4. Data Types and Operators4. 資料型別與運算子4. データ型と演算子

4.1 Net types in detail4.1 net 型別詳解4.1 net 型の詳細

Keyword關鍵字キーワードMeaning意義意味
wirewirewirethe default; establishes connectivity預設型別;建立連接關係既定の型。接続関係を作る
tritritriidentical to wire, but explicitly states the net is tri-stated與 wire 完全相同,只是明確表示這條 net 會進入三態wire と同一だが、そのネットがトライステートであることを明示する
wand / worwand/worwand/worwired-AND / wired-OR resolution when a net has multiple drivers當一條 net 有多個驅動源時,以 wired-AND/wired-OR 決議ネットに複数のドライバがあるとき、ワイヤード AND/ワイヤード OR で解決する
triand / triortriand/triortriand/triortri-stated wired-AND / wired-OR with multiple drivers多驅動源下可進入三態的 wired-AND/wired-OR複数ドライバをもつトライステートのワイヤード AND/ワイヤード OR
supply0 / supply1supply0/supply1supply0/supply1permanently connected to GND / VDD永久接到 GND/VDDGND/VDD に恒久的に接続される

A classic tri use: O = A when E = 1, otherwise O = z. That is exactly what the built-in primitive bufif1 does.tri 的經典用法:E = 1 時 O = A,否則 O = z。這正是內建原件 bufif1 在做的事。tri の典型的な使い方:E = 1 のとき O = A、そうでなければ O = z。これは組み込みプリミティブ bufif1 がまさに行うことです。

Declaration forms宣告的寫法宣言の書き方

wire       x;                    // scalar
wand       y;                    // wired-AND resolution
wire [15:0] data;                // vector; data[5] bit-select, data[5:3] part-select
wire [0:7]  array_a;             // little-endian declaration; array_a[0:3] is the left half
wire [7:0]  array_2d_p [0:31];   // 32 entries of 8 bits; array_2d_p[2] is an 8-bit vector
wire        a = b + c;           // declaration with an implicit continuous assignment
How a net gets its valuenet 的值從哪裡來ネットが値を得る経路

Explicitly by a continuous assignment (assign). Implicitly by being connected to the output terminal of a primitive, or to the output port of a module. At time 0, a driven net takes the value its drivers give it (defaulting to x); an undriven net is z. An undeclared net defaults to type wire.顯式:由連續賦值(assign)給值。隱式:被接到某個原件的輸出端,或某個模組的輸出埠。在時間 0,有被驅動的 net 取得驅動源給的值(預設為 x);未被驅動的 net 則是 z。未宣告的 net 預設型別為 wire。明示的には連続代入(assign)によって、暗黙的にはプリミティブの出力端子やモジュールの出力ポートに接続されることによって値を得ます。時刻 0 では、駆動されているネットはドライバが与える値(既定では x)を取り、駆動されていないネットは z です。宣言されていないネットは既定で wire 型になります。

4.2 Register types and memory4.2 register 型別與記憶體4.2 register 型とメモリ

Keyword關鍵字キーワードStores儲存的內容保持するもの
regregrega logic value (4-state)一個邏輯值(四值)論理値(4 値)
integerintegerintegersigned integers in two's complement — 32 bits by default二補數表示的有號整數 — 預設 32 位元2 の補数表現の符号付き整数 — 既定で 32 ビット
realrealrealdouble-precision floating point倍精度浮點數倍精度浮動小数点数
timetimetime64-bit unsigned time value64 位元無號時間值64 ビット符号なしの時刻値
realtimerealtimerealtimetime stored as a real number以實數儲存的時間実数として保持される時刻
reg        a, b;
reg [15:0] counter;
reg [7:0]  shift_reg [0:15];     // 16-deep memory of 8-bit words
integer    c;

Memory記憶體メモリ

A memory is a collection of registers — a 2-D array. Individual bits cannot be addressed directly: you must read a whole word out first.記憶體就是一群暫存器 — 一個二維陣列。不能直接定址到單一位元:必須先把整個字讀出來。メモリはレジスタの集まり、すなわち 2 次元配列です。個々のビットを直接アドレス指定することはできません。まずワード全体を読み出す必要があります。

reg [31:0] cache [0:1023];       // 1K x 32-bit memory
reg [31:0] one_word;
reg        one_bit;

one_word = cache[1022];          // legal: word select
one_bit  = one_word[31];         // legal: bit select on a plain reg
// one_bit = cache[1022][31];    // NOT legal in Verilog-1995/2001 memories
Register assignment restrictionsregister 賦值的限制register への代入の制限
  • In simulation a register variable starts at x.在模擬中,register 變數的初值是 x。シミュレーションでは、レジスタ変数の初期値は x です。
  • An undeclared identifier is assumed to be a net (wire), which is illegal inside a behavior — a frequent cause of "cannot assign to wire" errors.未宣告的識別字會被當成 net(wire),而這在 behavior 內是不合法的 — 這是「cannot assign to wire」錯誤的常見原因。宣言されていない識別子はネット(wire)とみなされますが、それは behavior の中では不正です — 「cannot assign to wire」エラーのよくある原因です。
  • A register may only be assigned within a procedural statement, a user-defined sequential primitive, a task, or a function.register 只能在程序式敘述、使用者自定序向原件、task 或 function 之中被賦值。レジスタに代入できるのは、手続き文・ユーザー定義順序回路プリミティブ・task・function の中だけです。
  • A reg object may never be the output of a primitive gate, nor the target of a continuous assignment.reg 物件絕對不可以是原件閘的輸出,也不可以是連續賦值的目標。reg オブジェクトは決してプリミティブゲートの出力にも、連続代入の左辺にもできません。

4.3 Addressing rules4.3 定址規則4.3 アドレッシングの規則

4.4 Parameters (constants)4.4 參數(常數)4.4 パラメータ(定数)

parameter size      = 16;
reg [size-1:0] a;                          // parameterised width
parameter num_b     = 2'b01;
parameter av_delay  = (min_delay + max_delay) / 2;   // expression of other parameters

A parameter's value cannot change during simulation, but it can be changed at compile time by substitution:參數的值在模擬期間不能改變,但可以在編譯期以替換的方式改掉:パラメータの値はシミュレーション中に変えられませんが、コンパイル時に置き換えることはできます。

Direct substitution — defparam直接替換 — defparam直接の置き換え — defparam

module top;
  adder #(.WIDTH(8)) A1 (...);
  // or, the older form:
  defparam A2.WIDTH = 12;
  adder A2 (...);
endmodule

Indirect substitution — at instantiation間接替換 — 在實體化時指定間接的な置き換え — インスタンス化のとき

module adder (sum, a, b);
  parameter WIDTH = 4;
  output [WIDTH-1:0] sum;
  input  [WIDTH-1:0] a, b;
  assign sum = a + b;
endmodule

adder #(16) A3 (s, x, y);   // WIDTH = 16
Why parameters matter參數為什麼重要パラメータが重要な理由

They make hardware flexible (design once, reuse at many widths), make the code easier to maintain, and make it readable. In a communication IC, where the same FIR or interleaver is instantiated at several word widths, this is not a stylistic nicety — it is the difference between one module and six.參數讓硬體有彈性(設計一次,就能在多種位元寬度下重用)、讓程式好維護,也讓它易讀。在通訊 IC 裡,同一個 FIR 或交錯器常常要以好幾種字寬實體化,這時參數就不只是寫法好看的問題 — 它決定你是寫一個模組還是六個。パラメータはハードウェアに柔軟性を与え(一度設計すれば複数のビット幅で再利用できる)、コードを保守しやすく、読みやすくします。同じ FIR やインタリーバを複数のワード幅でインスタンス化する通信 IC では、これは書き方の good taste の問題ではありません — モジュールが 1 つで済むか 6 つ必要かの違いです。

4.5 Operator catalogue4.5 運算子總表4.5 演算子一覧

Arithmetic算術算術

Binary + - * / %; unary + -.二元 + - * / %;一元 + -。2 項 + - * / %、単項 + -。

Bitwise位元ビット単位

~ & | ^ ~^ ^~. The shorter operand is zero-extended to the width of the longer.~ & | ^ ~^ ^~。較短的運算元會被補零延伸到較長者的寬度。~ & | ^ ~^ ^~。短いほうのオペランドは長いほうの幅までゼロ拡張されます。

Expression運算式式Result結果結果
~(1010)0101
(01) & (11)01
(01) | (11)11
(01) ^ (11)10
(01) ~^ (11)01

Reduction縮減リダクション

Unary operators & ~& | ~| ^ ~^ ^~ that collapse a vector to a single bit.一元運算子 & ~& | ~| ^ ~^ ^~,把一個向量收縮成單一位元。単項演算子 & ~& | ~| ^ ~^ ^~ は、ベクタを1 ビットに畳み込みます。

Expression運算式式Result結果結果Why原因理由
&(0101)0not all bits are 1並非所有位元都是 1すべてのビットが 1 ではない
|(0101)1at least one bit is 1至少有一個位元是 1少なくとも 1 ビットが 1 である
&(01xx)&(01xx)&(01xx)0a 0 is present — controlling value settles it出現了 0 — 控制值直接定案0 があるので — 支配値で決着する
|(01xx)|(01xx)|(01xx)1a 1 is present — controlling value settles it出現了 1 — 控制值直接定案1 があるので — 支配値で決着する
Bitwise versus reduction — tell them apart by arity位元運算與縮減運算 — 靠運算元個數分辨ビット演算とリダクション演算 — オペランドの数で見分ける

& with two operands is bitwise and returns a vector. & with one operand is reduction and returns one bit. Same symbol, completely different operation. &(01xx) is 0 while (01xx) & (1111) is 01xx.& 帶兩個運算元是位元運算,回傳一個向量。& 帶一個運算元是縮減運算,回傳一個位元。同一個符號,完全不同的運算。&(01xx) 是 0,而 (01xx) & (1111) 是 01xx。& はオペランドが2 つならビット演算でベクタを返し、1 つならリダクションで 1 ビットを返します。同じ記号でまったく別の演算です。&(01xx) は 0 ですが、(01xx) & (1111) は 01xx です。

Logical邏輯論理

! && || == != === !==. These return a single-bit truth value.! && || == != === !==。這些回傳單一位元的真假值。! && || == != === !==。いずれも 1 ビットの真偽値を返します。

Operator運算子演算子Behaviour with x / z遇到 x/z 時的行為x/z があるときの振る舞い
== / !=logical equality — result is x if either operand contains x or z邏輯相等 — 只要有一邊含 x 或 z,結果就是 x論理等価 — どちらかのオペランドに x や z が含まれると結果は x
=== / !==case equality — compares x and z literally; always returns 0 or 1, never xcase 相等 — 把 x 與 z 照字面比較;一律回傳 0 或 1,絕不會是 xケース等価 — x と z を文字どおり比較する。常に 0 か 1 を返し、x にはならない

Only === and !== can ask "is this signal exactly x?" — and neither is synthesizable, because real hardware has no x.只有 === 與 !== 能問「這個訊號是不是剛好等於 x?」— 而且兩者都不可合成,因為真實硬體沒有 x。「この信号はちょうど x か」と問えるのは === と !== だけです — そしてどちらも合成できません。実際のハードウェアに x は存在しないからです。

Other operators其他運算子その他の演算子

Class類別分類Operators運算子演算子Example範例例
Relational關係関係< <= > >=if ((a < size-1) || (b >= 3))if ((a < size-1) || (b >= 3))if ((a < size-1) || (b >= 3))
Shift位移シフト<< >>result = (a << 3);result = (a << 3);result = (a << 3);
Conditional條件条件? :y = (a == b) ? a : b;
Concatenation串接連結{ , }{a,b}
Replication複製繰り返し{n{ }}{4{a}} gives {a,a,a,a}{4{a}} 得到 {a,a,a,a}{4{a}} は {a,a,a,a} になる
{3{a}, 2{b}, 4{c}}   // -> {a,a,a, b,b, c,c,c,c}
Conditional operator with an ambiguous condition條件式的條件無法判定時条件があいまいな場合の条件演算子

signal = (cond) ? true_expr : false_expr;
z is not allowed in the conditional expression. If the condition is ambiguous (evaluates to x), the simulator evaluates both branches and combines them bitwise: a bit position where both branches agree keeps that value; a position where they disagree becomes x. It does not simply return all-x.
signal = (cond) ? true_expr : false_expr;
條件運算式中不允許出現 z。若條件無法判定(求值為 x),模擬器會把兩個分支都算出來,再逐位元合併:兩個分支一致的位元保留該值,不一致的位元變成 x。它並不是直接回傳全 x。
signal = (cond) ? true_expr : false_expr;
条件式に z を書くことはできません。条件があいまい(評価結果が x)の場合、シミュレータは両方の分岐を評価し、ビットごとに合成します。両分岐が一致するビットはその値を保ち、食い違うビットは x になります。単純に全ビット x を返すわけではありません。

4.6 Operator precedence4.6 運算子優先順序4.6 演算子の優先順位

Precedence優先順序優先順位Operators運算子演算子
Highest最高最高unary ! ~ + - and reduction一元 ! ~ + - 與縮減運算単項 ! ~ + - とリダクション
* / %
+ - (binary)+ -(二元)+ -(2 項)
<< >>
< <= > >=
== != === !==
&, then ^ ~^, then |先 &,再 ^ ~^,最後 |まず &、次に ^ ~^、最後に |
&&, then ||先 &&,再 ||まず &&、次に ||
Lowest最低最低? :
The lecture's own advice投影片自己給的建議講義スライド自身の助言

"If unsure, use parentheses." This is not laziness — parenthesised RTL also reads better in code review and produces identical synthesis results.「不確定就加括號。」這不是偷懶 — 加了括號的 RTL 在程式審查時也更好讀,而且合成結果完全相同。「迷ったら括弧を付けよ。」これは手抜きではありません — 括弧を付けた RTL はコードレビューでも読みやすく、合成結果はまったく同じです。

Practice 4 — Operator evaluation練習 4 — 運算子求值演習 4 — 演算子の評価

Problem: Let a = 4'b1010, b = 4'b0110, c = 4'b01x0. Evaluate: (a) a & b, (b) &a, (c) |c, (d) a == c, (e) a === a, (f) {2{b[1:0]}}, (g) a >> 2, (h) (a > b) ? a : b.題目:設 a = 4'b1010、b = 4'b0110、c = 4'b01x0。求: (a) a & b、(b) &a、(c) |c、(d) a == c、 (e) a === a、(f) {2{b[1:0]}}、(g) a >> 2、 (h) (a > b) ? a : b。問題:a = 4'b1010、b = 4'b0110、c = 4'b01x0 とします。次を評価しなさい。 (a) a & b、(b) &a、(c) |c、(d) a == c、 (e) a === a、(f) {2{b[1:0]}}、(g) a >> 2、 (h) (a > b) ? a : b。

Click to reveal solution點擊看解答クリックで解答を表示
  • (a) bitwise AND: 1010 & 0110 = 4'b0010(a) 位元 AND:1010 & 0110 = 4'b0010(a) ビット単位 AND:1010 & 0110 = 4'b0010
  • (b) reduction AND of 1010: a 0 is present, so 1'b0(b) 1010 的縮減 AND:存在 0,所以是 1'b0(b) 1010 のリダクション AND:0 があるので 1'b0
  • (c) reduction OR of 01x0: a 1 is present, so 1'b1 — the x is irrelevant because 1 is the controlling value for OR(c) 01x0 的縮減 OR:存在 1,所以是 1'b1 — x 無關緊要,因為 1 是 OR 的控制值(c) 01x0 のリダクション OR:1 があるので 1'b1 — 1 は OR の支配値なので x は影響しません
  • (d) == is logical equality and c contains an x, so the result is 1'bx — not 0(d) == 是邏輯相等,而 c 含有 x,所以結果是 1'bx — 不是 0(d) == は論理等価で、c に x が含まれるため結果は 1'bx です — 0 ではありません
  • (e) === is case equality: 1'b1(e) === 是 case 相等:1'b1(e) === はケース等価なので 1'b1
  • (f) b[1:0] = 2'b10, replicated twice: 4'b1010(f) b[1:0] = 2'b10,複製兩次:4'b1010(f) b[1:0] = 2'b10 を 2 回繰り返して 4'b1010
  • (g) logical right shift, zero fill: 4'b0010(g) 邏輯右移,左邊補零:4'b0010(g) 論理右シフトでゼロ埋め:4'b0010
  • (h) a = 10, b = 6, so the condition is true and the result is a = 4'b1010(h) a = 10、b = 6,條件成立,結果為 a = 4'b1010(h) a = 10、b = 6 なので条件は真となり、結果は a = 4'b1010

The trap is (d). Comparing against a vector containing x with == gives x, and if (x) takes the false branch. Every if whose condition can go unknown silently falls through — this is why reset must be applied before any comparison-driven logic runs.陷阱在 (d)。用 == 去和含 x 的向量比較會得到 x,而 if (x) 走的是假分支。任何條件可能變成未知的 if 都會無聲地掉進 else — 這正是為什麼任何由比較驅動的邏輯開始運作之前,必須先做好重置。落とし穴は (d) です。x を含むベクタと == で比較すると結果は x になり、if (x) は偽の分岐を通ります。条件が不定になりうる if はすべて黙って else に落ちます — 比較で駆動される論理が動き出す前に必ずリセットをかけなければならない理由がこれです。

5. User-Defined Primitives (UDPs)5. 使用者自定原件(UDP)5. ユーザー定義プリミティブ(UDP)

5.1 Primitives and the rules that govern them5.1 原件與規範它們的規則5.1 プリミティブとそれを律する規則

A primitive is a built-in logic model: and, or, nand, nor, buf, not, xor, xnor, and the tri-state buffers bufif0/1, notif0/1. Because the predefined set is limited, Verilog lets you define your own with primitive … endprimitive.原件是內建的邏輯模型:and、or、nand、nor、buf、not、xor、xnor,以及三態緩衝器 bufif0/1、notif0/1。由於預先定義的種類有限,Verilog 讓你用 primitive … endprimitive 自己定義。プリミティブは組み込みの論理モデルで、and、or、nand、nor、buf、not、xor、xnor、およびトライステートバッファ bufif0/1、notif0/1 があります。定義済みの種類は限られているため、Verilog では primitive … endprimitive で自分のプリミティブを定義できます。

Rules for primitives and UDPs alike原件與 UDP 共通的規則プリミティブと UDP に共通の規則
  • Exactly one output port, and it is always first in the port list.只有一個輸出埠,而且永遠排在埠列表的第一個。出力ポートはちょうど 1 つで、常にポートリストの先頭に置きます。
  • Multiple inputs are allowed (2, 3, 4, …); no inout.可以有多個輸入(2、3、4、…);不可以有 inout。入力は複数(2、3、4、…)でもかまいませんが、inout は使えません。
  • Never used stand-alone — must be instantiated inside a module.不能單獨使用 — 必須在模組內實體化。単独では使えません — 必ずモジュール内でインスタンス化します。
  • The instance name is optional for both predefined and user-defined primitives.不論預先定義或使用者自定的原件,實體名稱都是可省略的。定義済み・ユーザー定義のいずれのプリミティブでも、インスタンス名は省略できます。
  • Default delay is 0.預設延遲為 0。既定の遅延は 0 です。
  • Port elements of an instance must be outputs followed by inputs.實體的埠元素順序必須是先輸出、後輸入。インスタンスのポートは出力が先、入力が後の順に並べます。
  • The output port must be a net in a combinational UDP, a reg in a sequential UDP.組合邏輯 UDP 的輸出埠必須是 net,序向 UDP 的輸出埠則必須是 reg。出力ポートは、組合せ論理 UDP では net、順序回路 UDP では reg でなければなりません。
  • Anything unspecified in the table is treated as x.表格中沒有指定到的組合一律視為 x。テーブルで指定されていない組合せはすべて x として扱われます。
and (d, a, b, c);          // no instance name — legal
and M1 (z2, x2, y2);       // with instance name — also legal
my_udp   (c2, a2, b2);
my_udp N1 (c1, a1, b1);

5.2 Table symbols5.2 表格符號5.2 テーブル記号

Symbol符號記号Means意義意味
0 1 xthe literal logic values (note: z is not a table value)字面上的邏輯值(注意:z 不是表格值)そのままの論理値(注意:z はテーブル値ではありません)
?any of {0, 1, x} — a don't-care input{0, 1, x} 中的任何一個 — 代表輸入的 don't-care{0, 1, x} のいずれか — 入力のドントケア
beither of {0, 1}{0, 1} 中的任一個{0, 1} のいずれか
(vw)(vw)(vw)an input transition from v to w輸入由 v 變成 w 的轉態入力が v から w へ遷移すること
-no change (used in the output column of a sequential UDP)不改變(用在序向 UDP 的輸出欄)変化なし(順序回路 UDP の出力欄で使う)
*shorthand for (??) — any transition on that input(??) 的簡寫 — 該輸入的任意轉態(??) の略記 — その入力の任意の遷移
rshorthand for (01) — rising edge(01) 的簡寫 — 上升邊緣(01) の略記 — 立ち上がりエッジ
fshorthand for (10) — falling edge(10) 的簡寫 — 下降邊緣(10) の略記 — 立ち下がりエッジ

5.3 Combinational UDPs5.3 組合邏輯 UDP5.3 組合せ論理 UDP

Structure: $n$ inputs, 1 output, and therefore $n+1$ columns in the table — the first $n$ are inputs, the last is the output.結構:$n$ 個輸入、1 個輸出,因此表格有 $n+1$ 欄 — 前 $n$ 欄是輸入,最後一欄是輸出。構成:入力 $n$ 個と出力 1 個なので、テーブルは $n+1$ 列になります — 先頭の $n$ 列が入力、最後の 1 列が出力です。

Boolean function out = ab + ac + bc (majority of three)布林函數 out = ab + ac + bc(三者多數決)ブール関数 out = ab + ac + bc(3 入力の多数決)

primitive boolean_func (out, a, b, c);
  output out;
  input  a, b, c;

  table
    // a  b  c  :  out
       0  0  ?  :  0;
       0  ?  0  :  0;
       ?  0  0  :  0;
       1  1  ?  :  1;
       1  ?  1  :  1;
       ?  1  1  :  1;
  endtable
endprimitive
Why "?" earns its keep「?」為什麼值得用「?」が役に立つ理由

A full 3-input table over {0,1,x} would need 27 rows. Using ? covers the majority function in 6. The remaining combinations — those with a genuine x that actually matters, such as (1, 0, x) — are unspecified and therefore evaluate to x, which is the correct answer.在 {0,1,x} 上寫完整的三輸入表格需要 27 列。用 ? 只要 6 列就能涵蓋多數決函數。剩下的組合 — 那些真的有 x 且會影響結果的,例如 (1, 0, x) — 因為未指定而求值為 x,而那正是正確答案。{0,1,x} 上で 3 入力の完全なテーブルを書くと 27 行になります。? を使えば多数決関数は 6 行で表せます。残りの組合せ — (1, 0, x) のように x が実際に効いてくるもの — は未指定なので x と評価され、それがまさに正しい答えです。

5.4 Sequential UDPs5.4 序向 UDP5.4 順序回路 UDP

Structure: $n$ inputs, plus a state and an output — so $n+2$ columns: <n inputs> : <state> : <output = next state>. The output port must be declared reg, and an initial statement inside the primitive may set its power-up value.結構:$n$ 個輸入,再加上一個狀態與一個輸出 — 所以有 $n+2$ 欄:<n 個輸入> : <狀態> : <輸出=次態>。輸出埠必須宣告為 reg,而原件內部的 initial 敘述可以設定它的上電初值。構成:入力 $n$ 個に状態と出力が加わるので $n+2$ 列になります:<n 個の入力> : <状態> : <出力=次状態>。出力ポートは reg と宣言する必要があり、プリミティブ内の initial 文で電源投入時の値を設定できます。

Two flavours:有兩種:2 つの種類があります。

Level-sensitive — transparent latch準位敏感 — 透通鎖存器レベルセンシティブ — 透過ラッチ

primitive latch (q, clk, d);
  output q;  reg q;
  input  clk, d;

  table
   // clk  d  : state : q(next)
        0   1  :   ?   :   1;
        0   0  :   ?   :   0;
        1   ?  :   ?   :   -;  // hold
  endtable
endprimitive

Edge-sensitive — rising-edge D flip-flop邊緣敏感 — 上升邊緣觸發的 D 正反器エッジセンシティブ — 立ち上がりエッジ D フリップフロップ

primitive dff (q, clk, d);
  output q;  reg q;
  input  clk, d;

  table
   // clk    d  : state : q(next)
      (01)   0  :   ?   :   0;
      (01)   1  :   ?   :   1;
      (0x)   1  :   1   :   1;
      (0x)   0  :   0   :   0;
      (?0)   ?  :   ?   :   -;  // ignore falling
       ?    (??):   ?   :   -;  // ignore data change
  endtable
endprimitive
Sequential UDPs do not synthesize序向 UDP 不可合成順序回路 UDP は合成できない

Combinational UDPs are synthesizable. Sequential UDPs are not — they appear in the lecture's explicit list of unsupported constructs. Use them for modelling library cells and for teaching, never in RTL you intend to hand to Design Compiler.組合邏輯 UDP 是可以合成的。序向 UDP 則不行 — 它明確列在投影片的不支援結構清單裡。序向 UDP 適合用來建立函式庫單元模型和教學,絕不要寫進打算交給 Design Compiler 的 RTL。組合せ論理 UDP は合成できます。順序回路 UDP はできません — 講義がサポート対象外として明示的に挙げている構文です。ライブラリセルのモデリングや教育目的には使えますが、Design Compiler に渡すつもりの RTL に書いてはいけません。

Practice 5 — Write a 2-to-1 multiplexer as a UDP練習 5 — 用 UDP 寫一個 2 對 1 多工器演習 5 — 2 対 1 マルチプレクサを UDP で書く

Problem: Write primitive mux2 (out, sel, a, b) where out = a when sel = 0 and out = b when sel = 1. Make it handle the case where sel is x but both data inputs agree.題目:寫出 primitive mux2 (out, sel, a, b),使 sel = 0 時 out = a、sel = 1 時 out = b。並讓它能處理 sel 為 x 但兩個資料輸入相同的情況。問題:primitive mux2 (out, sel, a, b) を書きなさい。sel = 0 のとき out = a、sel = 1 のとき out = b とします。さらに sel が x でも 2 つのデータ入力が一致する場合を扱えるようにしなさい。

Click to reveal solution點擊看解答クリックで解答を表示
primitive mux2 (out, sel, a, b);
  output out;
  input  sel, a, b;

  table
   // sel  a  b  :  out
       0   1  ?  :   1;
       0   0  ?  :   0;
       1   ?  1  :   1;
       1   ?  0  :   0;
       x   0  0  :   0;    // both agree — selector does not matter
       x   1  1  :   1;
  endtable
endprimitive

Why the last two rows matter. Without them, sel = x falls through to "unspecified", and the output becomes x even though both data inputs are 1. Real hardware would output 1 regardless of the selector. Adding those rows makes the model less pessimistic and prevents spurious x propagation through a long datapath — the practical reason UDPs exist in cell libraries.最後兩列為什麼重要。少了它們,sel = x 就會掉進「未指定」,即使兩個資料輸入都是 1,輸出仍會變成 x。真實硬體不管選擇訊號如何都會輸出 1。加上那兩列可以讓模型不那麼悲觀,避免 x 沿著長長的資料路徑虛假地傳播 — 這正是函式庫單元裡會有 UDP 的實務理由。最後の 2 行が重要な理由。これがないと sel = x は「未指定」に落ち、両方のデータ入力が 1 でも出力は x になります。実際のハードウェアはセレクタがどうであれ 1 を出します。この 2 行を加えるとモデルは過度に悲観的でなくなり、長いデータパスを通じた偽の x 伝播を防げます — セルライブラリに UDP が存在する実務上の理由です。

Note the column count: 3 inputs + 1 output = 4 columns, consistent with the $n+1$ rule for a combinational UDP. The output is a net (no reg), as required.注意欄數:3 個輸入 + 1 個輸出 = 4 欄,符合組合邏輯 UDP 的 $n+1$ 規則。輸出依規定是 net(不是 reg)。列数に注目:入力 3 + 出力 1 = 4 列で、組合せ論理 UDP の $n+1$ の規則どおりです。出力は規定どおりネット(reg ではない)です。

6. Models of Propagation Delay6. 傳播延遲的模型6. 伝搬遅延のモデル

Three delay types三種延遲3 種類の遅延
  • Gate delay — inertial. Attached to a primitive instance.閘延遲 — 屬於慣性延遲。附加在原件實體上。ゲート遅延 — 慣性遅延。プリミティブのインスタンスに付けます。
  • Net delay — transport. Attached to a net declaration. Passes every pulse, however narrow.net 延遲 — 屬於傳輸延遲。附加在 net 宣告上。不論多窄的脈衝都會通過。ネット遅延 — 伝送遅延。ネットの宣言に付けます。どんなに狭いパルスでも通します。
  • Module path delay — declared in a specify block; describes input-to-output paths without reference to internal structure.模組路徑延遲 — 宣告在 specify 區塊裡;描述輸入到輸出的路徑,不牽涉內部結構。モジュールパス遅延 — specify ブロックで宣言します。内部構造に触れずに入力から出力への経路を記述します。

6.1 Gate propagation delay6.1 閘的傳播延遲6.1 ゲートの伝搬遅延

Signal transition definitions訊號轉態的定義信号遷移の定義

Delay延遲遅延Applies to transitions適用的轉態対象となる遷移
Rising上升立ち上がりanything except 1 → 1, i.e. 0->1, x->1, z->1除了 1 → 1 以外的任何轉態,也就是 0->1、x->1、z->11 → 1 以外のすべて、すなわち 0->1、x->1、z->1
Falling下降立ち下がりanything except 0 → 0, i.e. 1->0, x->0, z->0除了 0 → 0 以外的任何轉態,也就是 1->0、x->0、z->00 → 0 以外のすべて、すなわち 1->0、x->0、z->0
Turn-off關斷ターンオフanything except z → z, i.e. 0->z, 1->z, x->z除了 z → z 以外的任何轉態,也就是 0->z、1->z、x->zz → z 以外のすべて、すなわち 0->z、1->z、x->z

Delay specification forms延遲的指定方式遅延の指定形式

and (y, x1, x2);                 // no delay — zero
and #2 (y, x1, x2);              // all transitions: 2
and #1.45 (y, x1, x2);           // fractional, scaled by `timescale
and #(2,3) (y, x1, x2);          // rise = 2, fall = 3

bufif1 #(3,4,1) (out, in, ctrl); // rise = 3, fall = 4, turn-off = 1
bufif1 #(3:4:5, 6:7:8, 5:8:9) (out, in, ctrl);  // min:typ:max for each
Number of delays given給定的延遲個數指定した遅延の個数Rise上升立ち上がりFall下降立ち下がりTurn-off關斷ターンオフ
#dddd
#(d1,d2)d1d2min(d1,d2)min(d1,d2)min(d1,d2)
#(d1,d2,d3)d1d2d3

The bufif1 truth table — worth knowing because it is the basis of every tri-state bus:bufif1 的真值表 — 值得記住,因為每一條三態匯流排都建立在它之上:bufif1 の真理値表 — あらゆるトライステートバスの土台なので覚えておく価値があります。

bufif1bufif1bufif1ctrl=0ctrl=0ctrl=0ctrl=1ctrl=1ctrl=1ctrl=xctrl=xctrl=xctrl=zctrl=zctrl=z
in=0in=0in=0z0LL
in=1in=1in=1z1HH
in=xin=xin=xzxxx
in=zin=zin=zzxxx

L means "0 or z", H means "1 or z" — the simulator's way of saying the output is either driven or floating but definitely not the opposite polarity.L 代表「0 或 z」,H 代表「1 或 z」— 這是模擬器在說:輸出不是被驅動就是浮接,但絕不會是相反的極性。L は「0 または z」、H は「1 または z」を表します — 出力は駆動されているかフローティングかのどちらかであって、逆の極性には決してならない、というシミュレータの言い方です。

6.2 Net delay6.2 net 延遲6.2 ネット遅延

Delay may be attached to a net, and it adds to the gate delay of whatever drives it.延遲可以掛在 net 上,而且它會疊加到驅動它的那個閘的延遲之上。遅延はネットにも付けられ、それを駆動するもののゲート遅延に加算されます。

Gate delay only — total 5只有閘延遲 — 合計 5ゲート遅延のみ — 合計 5

module my_xor1 (y_out, a, b);
  output y_out;
  input  a, b;
  xor #5 (y_out, a, b);
endmodule

Gate + net delay — total 8閘延遲+net 延遲 — 合計 8ゲート遅延+ネット遅延 — 合計 8

module my_xor2 (y_out, a, b);
  output y_out;
  input  a, b;
  wire #3 y_int;          // net delay = 3
  xor #5 (y_int, a, b);   // gate delay = 5
  assign y_out = y_int;
endmodule

6.3 Module path delay and specify blocks6.3 模組路徑延遲與 specify 區塊6.3 モジュールパス遅延と specify ブロック

In a structural description, the module delay can be traced through gate and net delays. In a behavioral description there are no gates to trace, so paths are described separately inside specify … endspecify.在結構描述中,模組延遲可以沿著閘延遲與 net 延遲一路追蹤。但行為描述裡沒有閘可以追,所以路徑要另外寫在 specify … endspecify 之中。構造記述では、モジュールの遅延をゲート遅延とネット遅延をたどって求められます。しかし動作記述にはたどるべきゲートがないため、経路は specify … endspecify の中に別途記述します。

Path kind路徑種類パスの種類Meaning意義意味Models對應的模型モデル対象
Simple簡單路徑単純パスunconditional direct input-to-output path無條件的輸入到輸出直達路徑条件なしで入力から出力へ直結する経路combinational blocks組合邏輯區塊組合せ論理ブロック
State-dependent狀態相依路徑状態依存パスpath exists only when a condition holds只有在某個條件成立時才存在的路徑ある条件が成り立つときだけ存在する経路transparent latches透通鎖存器透過ラッチ
Edge-dependent邊緣相依路徑エッジ依存パスsource is an edge transition of a synchronising signal起點是某個同步訊號的邊緣轉態起点が同期信号のエッジ遷移である経路edge-triggered flip-flops邊緣觸發正反器エッジトリガ・フリップフロップ
specify
  // simple path, parallel connection (bit i to bit i)
  (a => y) = (3, 4);                  // rise = 3, fall = 4

  // full connection: every bit of a to every bit of y
  (a *> y) = (3, 4);

  // named delay values
  specparam t_rise = 3, t_fall = 4;
  (b => y) = (t_rise, t_fall);

  // state-dependent: only while enable is high (a latch)
  if (enable) (data *> q) = (3, 4);

  // edge-sensitive: clock edge to register output
  (posedge clock => (q +: data)) = (5, 6);
endspecify
=> versus *>, and path polarity=> 與 *>,以及路徑極性=> と *>、そしてパスの極性

=> is a parallel connection: source bit $i$ to destination bit $i$; the two must be the same width. *> is a full connection: every source bit to every destination bit; widths may differ.=> 是平行連接:來源的第 $i$ 位元對應目的的第 $i$ 位元,兩者寬度必須相同。*> 是全連接:來源每一個位元都連到目的的每一個位元,寬度可以不同。=> は並列接続で、ソースのビット $i$ をデスティネーションのビット $i$ に対応させます。両者の幅は同じでなければなりません。*> は全結合で、ソースの全ビットをデスティネーションの全ビットに結びます。幅は異なっていてもかまいません。

Polarity operators +: and -: tell the timing engine whether the path is non-inverting or inverting, so that a rising input maps to the correct rise/fall delay at the output.極性運算子 +: 與 -: 告訴時序引擎這條路徑是同相還是反相,這樣輸入上升時才會對應到輸出端正確的上升/下降延遲。極性演算子 +: と -: は、その経路が非反転か反転かをタイミングエンジンに伝えます。これにより入力の立ち上がりが出力側の正しい立ち上がり/立ち下がり遅延に対応づけられます。

Pulse rejection脈衝排除パルスの除去

Module paths obey inertial-delay rules too. A pulse narrower than the path delay is rejected. The PATHPULSE$ specparam lets you separate two thresholds:模組路徑同樣遵守慣性延遲規則。比路徑延遲窄的脈衝會被排除。PATHPULSE$ 這個 specparam 讓你把兩個門檻分開:モジュールパスも慣性遅延の規則に従います。パス遅延より狭いパルスは除去されます。specparam の PATHPULSE$ を使うと、2 つのしきい値を分けて指定できます。

6.4 Time units and `timescale6.4 時間單位與 `timescale6.4 時間単位と `timescale

Directive指令ディレクティブ

`timescale <time_unit> / <precision>`timescale <時間單位> / <精度>`timescale <時間単位> / <精度>

With `timescale 10ps/1ps: one time unit is 10 ps, and all times are rounded to 1 ps precision. So nor #3.57 (z, x1, x2) gives a delay of $3.57 \times 10\,\text{ps} = 35.7\,\text{ps}$, rounded to 36 ps.用 `timescale 10ps/1ps 時:一個時間單位是 10 ps,所有時間都四捨五入到 1 ps 的精度。因此 nor #3.57 (z, x1, x2) 的延遲是 $3.57 \times 10\,\text{ps} = 35.7\,\text{ps}$,取整為 36 ps。`timescale 10ps/1ps の場合、1 時間単位は 10 ps で、すべての時刻は 1 ps の精度に丸められます。したがって nor #3.57 (z, x1, x2) の遅延は $3.57 \times 10\,\text{ps} = 35.7\,\text{ps}$ となり、丸めて 36 ps です。

Precision is global, not local精度是全域的,不是區域的精度はローカルではなくグローバル

The simulator's actual time resolution is the smallest precision declared anywhere in the design. A single file with `timescale 1ns/1fs forces femtosecond resolution on the whole simulation and can slow it down by orders of magnitude. Keep the timescale consistent across files.模擬器實際的時間解析度,是整個設計中任何一處宣告過的最小精度。只要有一個檔案寫了 `timescale 1ns/1fs,整個模擬就被迫用飛秒解析度,速度可能慢上好幾個數量級。請讓各檔案的 timescale 保持一致。シミュレータの実際の時間分解能は、設計中のどこかで宣言された最小の精度になります。1 つのファイルに `timescale 1ns/1fs と書いてあるだけで、シミュレーション全体がフェムト秒分解能を強いられ、速度が桁違いに落ちることがあります。ファイル間でタイムスケールをそろえてください。

Practice 6 — Delay arithmetic練習 6 — 延遲計算演習 6 — 遅延の計算

Problem: Under `timescale 10ns/1ns, consider題目:在 `timescale 10ns/1ns 之下,考慮問題:`timescale 10ns/1ns のもとで次を考えます。

wire #2.5 w;
and #(1.24, 3.66) G1 (w, a, b);
assign y = w;

(a) What rise and fall delays does G1 use, in ns? (b) What is the net delay in ns? (c) What is the total a-to-y rise delay? (d) If a 30 ns pulse appears at the AND inputs, does it reach y?(a) G1 使用的上升與下降延遲各是多少 ns?(b) net 延遲是多少 ns?(c) 從 a 到 y 的總上升延遲是多少?(d) 若 AND 輸入端出現一個 30 ns 的脈衝,它會傳到 y 嗎?(a) G1 の立ち上がり遅延と立ち下がり遅延はそれぞれ何 ns ですか。(b) ネット遅延は何 ns ですか。(c) a から y までの立ち上がり遅延の合計は何 ns ですか。(d) AND の入力に 30 ns のパルスが現れたとき、それは y に届きますか。

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

(a) One time unit = 10 ns, precision 1 ns.
Rise: $1.24 \times 10 = 12.4$ ns, rounded to precision → 12 ns.
Fall: $3.66 \times 10 = 36.6$ ns → 37 ns.
(a) 一個時間單位 = 10 ns,精度 1 ns。
上升:$1.24 \times 10 = 12.4$ ns,依精度取整 → 12 ns。
下降:$3.66 \times 10 = 36.6$ ns → 37 ns。
(a) 1 時間単位 = 10 ns、精度は 1 ns です。
立ち上がり:$1.24 \times 10 = 12.4$ ns を精度に丸めて → 12 ns。
立ち下がり:$3.66 \times 10 = 36.6$ ns → 37 ns。

(b) $2.5 \times 10 = 25$ ns exactly → 25 ns.(b) $2.5 \times 10 = 25$ ns 剛好整除 → 25 ns。(b) $2.5 \times 10 = 25$ ns でちょうど割り切れます → 25 ns。

(c) Net delay adds to gate delay: $12 + 25 = $ 37 ns total rise delay from a to y.(c) net 延遲與閘延遲相加:$12 + 25 = $ 37 ns,即 a 到 y 的總上升延遲。(c) ネット遅延はゲート遅延に加算されます:$12 + 25 = $ 37 ns が a から y までの立ち上がり遅延の合計です。

(d) Yes, but think about which delay gates it. The gate's inertial delay for a pulse is governed by the transitions involved: the pulse must survive the rise delay of 12 ns to start, and the output pulse then has to last long enough to fall. A 30 ns input pulse exceeds the 12 ns rise delay, so the output begins to rise. The subsequent falling edge is scheduled 37 ns after the input falls. Since the gate is inertial, the key comparison is pulse width (30 ns) against the delay that would suppress it — here 30 > 12, so the pulse is not swallowed and does appear at w, then at y 25 ns later (net delay is transport, so it never rejects anything).(d) 會,但要想清楚是哪一個延遲在把關。閘對脈衝的慣性延遲由所涉及的轉態決定:脈衝必須撐過 12 ns 的上升延遲才開始,接著輸出脈衝還要持續夠久才能落下。30 ns 的輸入脈衝超過 12 ns 的上升延遲,所以輸出開始上升。後續的下降邊緣則排程在輸入下降後的 37 ns。既然閘是慣性的,關鍵比較就是脈衝寬度(30 ns)對上會抑制它的那個延遲 — 這裡 30 > 12,所以脈衝不會被吞掉,會出現在 w,再過 25 ns 出現在 y(net 延遲是傳輸型的,永遠不排除任何東西)。(d) 届きます。ただし、どの遅延が関門になるかを考えてください。パルスに対するゲートの慣性遅延は、関係する遷移で決まります。パルスはまず 12 ns の立ち上がり遅延を生き延びる必要があり、その後、出力パルスは立ち下がれるだけの長さを保たなければなりません。30 ns の入力パルスは 12 ns の立ち上がり遅延を超えるので、出力は立ち上がり始めます。続く立ち下がりエッジは入力が立ち下がってから 37 ns 後に登録されます。ゲートは慣性的なので、鍵となる比較はパルス幅(30 ns)と、それを抑制しうる遅延との比較です — ここでは 30 > 12 なのでパルスは飲み込まれず、w に現れ、その 25 ns 後に y にも現れます(ネット遅延は伝送型なので何も除去しません)。

The point of (d): gate delay can swallow pulses; net delay never can. That is the practical difference between inertial and transport delay.(d) 的重點:閘延遲會吞掉脈衝,net 延遲永遠不會。這就是慣性延遲與傳輸延遲在實務上的差別。(d) の要点:ゲート遅延はパルスを飲み込みますが、ネット遅延は決して飲み込みません。これが慣性遅延と伝送遅延の実務上の違いです。

BNF notation, brieflyBNF 記法簡介BNF 記法について簡単に

The IEEE Verilog standard describes syntax in Backus-Naur Form. You need to read it, not write it:IEEE Verilog 標準用 Backus-Naur Form 描述語法。你需要會讀它,不需要會寫它:IEEE Verilog 規格は構文を Backus-Naur Form で記述しています。読めれば十分で、書けるようになる必要はありません。

Symbol符號記号Means意義意味
::=is defined as定義為~と定義される
|alternative擇一選択肢
[ ... ]appears once or not at all出現一次或完全不出現1 回現れるか、まったく現れない
{ ... }appears any number of times, or not at all出現任意次,或完全不出現任意の回数現れるか、まったく現れない

For example conditional_expression ::= expression1 ? expression2 : expression3.例如 conditional_expression ::= expression1 ? expression2 : expression3。たとえば conditional_expression ::= expression1 ? expression2 : expression3 です。

7. Behavioral Descriptions7. 行為描述7. 動作記述

Everything from the preceding sections can coexist in one module:前面各節提到的一切,都可以共存在同一個模組裡:ここまでの節で扱ったものは、すべて 1 つのモジュールの中に共存できます。

module my_module (...);
  assign ...;                  // continuous assignment
  and (...);                   // instantiation of a primitive
  my_udp (...);                // instantiation of a UDP
  adder_16bits M1 (...);       // instantiation of a module
  always @ (...) begin         // behavior
    ...
  end
endmodule

7.1 initial and always7.1 initial 與 always7.1 initial と always

initialinitialinitialalwaysalwaysalways
Activity活動方式動作one-shot — runs once from time 0一次性 — 從時間 0 開始跑一次1 回限り — 時刻 0 から 1 度だけ実行するcyclic — an infinite loop until simulation stops週期性 — 無窮迴圈,直到模擬結束繰り返し — シミュレーションが終わるまでの無限ループ
Triggered by觸發來源起動のきっかけsimulation start模擬開始シミュレーションの開始its event control (sensitivity list)它的事件控制(敏感度列表)そのイベント制御(センシティビティリスト)
Synthesizable可否合成合成可否No — testbench only不可以 — 只用於測試平台不可 — テストベンチ専用Yes可以可

The body may be a single statement or a block statement delimited by begin … end. Procedural statements assign values to register variables — the one exception being force…release, which can also target nets.本體可以是單一敘述,也可以是以 begin … end 括起來的區塊敘述。程序式敘述賦值給的是register 變數 — 唯一的例外是 force…release,它也可以作用在 net 上。本体は単一の文でも、begin … end で囲んだブロック文でもかまいません。手続き文が値を代入する相手はレジスタ変数です — 唯一の例外が force…release で、これはネットも対象にできます。

initialinitialinitial

initial begin
  sig_a = 0;     // procedural assignments
  sig_b = 1;     // execute sequentially
  sig_c = 0;
end

alwaysalwaysalways

always @ (b or c or d) begin
  if (b == 1'b1)
    a = c;
  else
    a = d;
end

7.2 Blocking versus non-blocking assignment7.2 阻擋式與非阻擋式賦值7.2 ブロッキング代入とノンブロッキング代入

The rule in one line一句話的規則一行で言うと

Blocking =: an assignment completes before the next one starts.
Non-blocking <=: all right-hand sides are evaluated first, then all assignments happen together.
阻擋式 =:一個賦值完成之後,下一個才開始。
非阻擋式 <=:先把所有右式算完,然後所有賦值一起發生。
ブロッキング =:1 つの代入が完了してから次が始まります。
ノンブロッキング <=:まずすべての右辺を評価し、その後すべての代入が同時に起こります。

Blocking阻擋式ブロッキング

a = 0;
a = 1;
c = a;     // c = 1

Non-blocking非阻擋式ノンブロッキング

a = 0;
a <= 1;
c = a;     // c = 0

In the non-blocking case, a <= 1 schedules the update for the end of the time step, so c = a still reads the old value 0.在非阻擋式的情況下,a <= 1 把更新排到時間步的最後,所以 c = a 讀到的仍是舊值 0。ノンブロッキングの場合、a <= 1 は更新を時間ステップの最後に登録するため、c = a が読むのは古い値 0 のままです。

Two non-blocking assignments to the same target in one step同一個時間步內對同一目標做兩次非阻擋式賦值同じ時間ステップで同じ対象に 2 回ノンブロッキング代入する

d <= 0; d <= 1; — is d 0 or 1? The result is ambiguous, and therefore illegal as a modelling practice. Never assign the same variable twice non-blockingly in one time step, and never mix = and <= on the same variable inside the same behavior.d <= 0; d <= 1; — d 到底是 0 還是 1?結果無法確定,因此在建模實務上是不合法的。絕對不要在一個時間步內對同一個變數做兩次非阻擋式賦值,也絕對不要在同一個 behavior 裡對同一個變數混用 = 與 <=。d <= 0; d <= 1; — d は 0 でしょうか 1 でしょうか。結果はあいまいであり、モデリングの作法として不正です。1 つの時間ステップで同じ変数に 2 度ノンブロッキング代入してはいけませんし、同じ behavior の中で同じ変数に = と <= を混ぜてもいけません。

The rule you actually code by實際寫程式時依循的規則実際にコードを書くときの規則

Use <= for sequential logic序向邏輯用 <=順序論理には <= を使う

Anything inside always @ (posedge clk). Non-blocking assignments are order-independent, which is exactly the semantics of a bank of flip-flops all clocked together.凡是寫在 always @ (posedge clk) 裡的東西都用它。非阻擋式賦值與順序無關,而這正是一整排同時被時脈打到的正反器的語意。always @ (posedge clk) の中身はすべてこれです。ノンブロッキング代入は順序に依存しないので、同じクロックで一斉に叩かれるフリップフロップ群の意味そのものになります。

Use = for combinational logic組合邏輯用 =組合せ論理には = を使う

Anything inside always @(*). Blocking assignments let you build up an intermediate result across several lines, which is how combinational logic reads.凡是寫在 always @(*) 裡的東西都用它。阻擋式賦值讓你可以分好幾行逐步堆出中間結果,而組合邏輯本來就該這樣讀。always @(*) の中身はすべてこれです。ブロッキング代入なら数行かけて中間結果を積み上げられ、それが組合せ論理の読み方に合っています。

7.3 Intra-assignment delay7.3 賦值內延遲7.3 代入内遅延

Postpone the assignment, not the evaluation延後的是賦值,不是求值遅らせるのは代入であって評価ではない

A delay before the statement (#5 a = b;) suspends the activity flow, then evaluates and assigns. A delay inside the statement (a = #5 b;) evaluates the right-hand side now and assigns the captured value 5 units later.寫在敘述之前的延遲(#5 a = b;)會先暫停活動流程,然後才求值與賦值。寫在敘述裡面的延遲(a = #5 b;)則是現在就把右式算好,5 個單位之後才把擷取到的值寫進去。文の前に置いた遅延(#5 a = b;)は実行フローを一旦止め、それから評価して代入します。文の中に置いた遅延(a = #5 b;)は右辺を今評価し、取り込んだ値を 5 単位後に書き込みます。

Blocking, intra-assignment阻擋式、賦值內延遲ブロッキング・代入内遅延

a = #5 b;     // b captured now, written at t+5;
              //   flow resumes at t+5
c = d;        // executes at t+5

Event-controlled intra-assignment以事件控制的賦值內延遲イベント制御による代入内遅延

e = @(bus) f;  // f captured now, written when
               //   bus next changes
g = h;         // executes after that event

With non-blocking assignment the difference becomes dramatic, because the activity flow is not suspended at all:改用非阻擋式賦值後差別更明顯,因為活動流程完全不會被暫停:ノンブロッキング代入にすると違いは劇的になります。実行フローがまったく止まらないからです。

initial begin
  d <= #10 0;     // evaluated at t=0, scheduled for t=10
  d <= #11 1;     // evaluated at t=0, scheduled for t=11
  d <= #12 0;     // evaluated at t=0, scheduled for t=12
  d <= #13 1;     // evaluated at t=0, scheduled for t=13
end                // all four lines execute at t=0

Repeated intra-assignment delay重複型的賦值內延遲繰り返しを伴う代入内遅延

repeat may appear in the intra-assignment position to wait for $n$ occurrences of an event — the idiomatic way to say "capture this now, deliver it three clocks later":repeat 可以出現在賦值內的位置,用來等待某事件發生 $n$ 次 — 這是「現在就把值抓起來,三個時脈之後再送出去」的慣用寫法:repeat は代入内の位置に書いて、あるイベントが $n$ 回起こるのを待てます — 「今の値を取り込んで、3 クロック後に出す」という定型表現です。

a = repeat (3) @(posedge clk) b;   // b captured now, written on the 3rd rising edge

Not synthesizable; useful in testbenches.不可合成;在測試平台裡很好用。合成はできませんが、テストベンチでは便利です。

7.4 Procedural continuous assignment (PCA)7.4 程序式連續賦值(PCA)7.4 手続き型連続代入(PCA)

Two mechanisms that override normal assignment. Both are dynamic bindings, both are testbench and debugging tools, and synthesis tools might not support either.有兩種機制可以覆蓋一般的賦值。兩者都是動態繫結,都是測試平台與除錯用的工具,而且合成工具可能兩者都不支援。通常の代入を上書きする仕組みが 2 つあります。どちらも動的な束縛であり、テストベンチとデバッグのための道具で、合成ツールはどちらもサポートしない可能性があります。

assign … deassignassign … deassignassign … deassignforce … releaseforce … releaseforce … release
Target作用對象対象register variables only只能是 register 變數レジスタ変数のみnets or registersnet 或 registerネットまたはレジスタ
Overrides覆蓋什麼何を上書きするかall procedural assignments to that register對該 register 的所有程序式賦值そのレジスタへのすべての手続き型代入primitives and continuous assignments on a net; procedural assignments on a registernet 上的原件與連續賦值;register 上的程序式賦值ネット上のプリミティブと連続代入、レジスタ上の手続き型代入
Released by如何解除解除の方法deassign, or a new PCA (deassign is optional)deassign,或另一個 PCA(deassign 可省略)deassign、または別の PCA(deassign は省略可)release — and only releaserelease — 而且只能用 releaserelease — そして release のみ
Typical use典型用途典型的な用途level-sensitive combinational behavior, transparent latches, asynchronous control of sequential logic準位敏感的組合行為、透通鎖存器、序向邏輯的非同步控制レベルセンシティブな組合せ動作、透過ラッチ、順序論理の非同期制御code debugging in the testbench; works with hierarchical de-referencing測試平台中的程式除錯;可搭配階層路徑取用テストベンチでのコードデバッグ。階層パスによる参照と組み合わせられる
Do not confuse the two assigns不要把兩種 assign 搞混2 つの assign を混同しないこと

A continuous assignment assign y = a & b; at module level drives a net and is core synthesizable RTL. A procedural continuous assignment assign inside an always block targets a register and is a simulation override. Same keyword, different construct, opposite synthesizability.模組層級的連續賦值 assign y = a & b; 驅動的是一條 net,是核心的可合成 RTL。而 always 區塊內的程序式連續賦值 assign 作用在 register 上,是模擬時的覆蓋手段。同一個關鍵字,不同的語法結構,可合成性完全相反。モジュールレベルの連続代入 assign y = a & b; は ネットを駆動する、合成可能な RTL の中核です。一方 always ブロック内の手続き型連続代入 assign は レジスタを対象とするシミュレーション上の上書きです。同じキーワードでも別の構文であり、合成可否は正反対です。

// force/release reaching into the DUT from a testbench
initial begin
  #100 force DUT.sig_a = 1'b1;     // hierarchical de-reference to an internal node
  #50  force DUT.sig_b = 1'b0;
  #50  release DUT.sig_a;
       release DUT.sig_b;
end                                 // non-synthesizable

Net and register assignment modes — the summary tablenet 與 register 的賦值方式 — 總表ネットとレジスタへの代入方式 — まとめの表

Target對象対象Continuous assign連續 assign連続 assignProcedural (always/initial)程序式(always/initial)手続き型(always/initial)PCA assignPCA assignPCA assignPCA forcePCA forcePCA force
NetNetネットyes可以可no不可以不可no不可以不可yes可以可
RegisterRegisterレジスタno不可以不可yes可以可yes可以可yes可以可

7.5 Procedural timing controls7.5 程序式時序控制7.5 手続き型のタイミング制御

Mechanism機制仕組みSyntax語法構文Synthesizable?可合成?合成可能か
Delay control延遲控制遅延制御#10 a = b;no不可以不可
Event control事件控制イベント制御@(posedge clk) a = b;@(posedge clk) a = b;@(posedge clk) a = b;yes (as a clocked behavior)可以(作為時脈驅動的 behavior)可(クロック同期の behavior として)
Event or事件 orイベントの or@(posedge clk or negedge rst)@(posedge clk or negedge rst)@(posedge clk or negedge rst)yes可以可
Named event具名事件名前付きイベントevent e; -> e; @(e) ...event e; -> e; @(e) ...event e; -> e; @(e) ...no不可以不可
waitwaitwaitwait (enable) data_out = data_in;wait (enable) data_out = data_in;wait (enable) data_out = data_in;no不可以不可

posedge and negedge — exact definitionsposedge 與 negedge — 精確定義posedge と negedge — 正確な定義

Edge definitions邊緣的定義エッジの定義

posedge: 0->1, 0->x, x->1
negedge: 1->0, 1->x, x->0
posedge:0->1、0->x、x->1
negedge:1->0、1->x、x->0
posedge:0->1、0->x、x->1
negedge:1->0、1->x、x->0

The transitions through x are the reason a simulation can appear to clock itself during the unknown-value startup phase before reset is applied.會經過 x 的那些轉態,正是為什麼在重置生效之前那段值都未知的啟動階段,模擬看起來像是會自己打時脈。x を経由する遷移があるからこそ、リセットがかかる前の値が不定な起動段階では、シミュレーションが勝手にクロックを刻んでいるように見えるのです。

Event or — a D flip-flop with asynchronous active-low set and reset事件 or — 帶非同步低態有效 set 與 reset 的 D 正反器イベントの or — 非同期・負論理のセットとリセットを持つ D フリップフロップ

always @ (posedge clk or negedge set or negedge rst) begin
  if (rst == 0)
    q = 1'b0;                // asynchronous reset — highest priority
  else if (set == 0)
    q = 1'b1;                // asynchronous set
  else if (clk == 1)
    q = data_in;             // synchronous branch — must be last
  else
    q = q;
end
Why the synchronous branch must be last為什麼同步分支必須放在最後同期の分岐を最後に置かなければならない理由

When the event control is sensitive to the edge of more than one signal, an if statement must be the first statement in the behavior, and the synchronizing signal is not tested explicitly — by default the last branch describes the synchronous activity. This ordering is how the synthesis tool knows which signals are asynchronous controls (which map to the flip-flop's set/reset pins) and which is the clock. Get the order wrong and you get either a synthesis error or an unintended priority structure.當事件控制對一個以上訊號的邊緣敏感時,if 敘述必須是 behavior 的第一個敘述,而且不能顯式地測試同步訊號 — 依慣例由最後一個分支來描述同步行為。這個順序正是合成工具用來判斷哪些訊號是非同步控制(對應到正反器的 set/reset 接腳)、哪一個才是時脈的依據。順序寫錯,得到的不是合成錯誤,就是一個你沒打算要的優先權結構。イベント制御が複数の信号のエッジに反応する場合、if 文は behavior の最初の文でなければならず、同期信号を明示的に判定してはいけません — 既定では最後の分岐が同期動作を表します。この順序こそ、合成ツールがどの信号を非同期制御(フリップフロップの set/reset ピンに対応)とみなし、どれをクロックとみなすかの手がかりです。順序を間違えると、合成エラーになるか、意図しない優先順位構造ができます。

waitwaitwait

data_out = 0;
wait (enable) data_out = data_in;   // suspend until enable is true

wait is level-sensitive (unlike @, which is edge/change sensitive) and is not synthesizable.wait 是準位敏感的(不像 @ 是邊緣/變化敏感),而且不可合成。wait はレベルセンシティブで(エッジ・変化に反応する @ とは異なります)、合成できません。

Named events具名事件名前付きイベント

event  trigger;           // declared only within a module
always @ (posedge clk) -> trigger;          // event-trigger operator
always @ (trigger) $display("fired at %0d", $time);

Named events synchronize activity within and between modules; they can be referenced from other modules by hierarchical de-referencing. Not synthesizable.具名事件用來在模組內部與模組之間同步活動;可以由其他模組透過階層路徑引用。不可合成。名前付きイベントは、モジュール内およびモジュール間で動作を同期させるために使い、他のモジュールから階層パスで参照できます。合成はできません。

7.6 Activity flow control7.6 活動流程控制7.6 実行フローの制御

Available constructs: the conditional operator ?:; case, casex, casez; if…else; loops repeat, for, while, forever; disable; and fork…join.可用的語法結構:條件運算子 ?:;case、casex、casez;if…else;迴圈 repeat、for、while、forever;disable;以及 fork…join。使える構文:条件演算子 ?:、case・casex・casez、if…else、ループの repeat・for・while・forever、disable、そして fork…join。

case and its variantscase 及其變體case とその派生

Statement敘述文Matching behavior比對行為照合の振る舞い
casecasecaserequires a complete bitwise match; expression and case item must have the same bit length; x and z must match literally要求逐位元完全相符;運算式與 case 項目的位元長度必須相同;x 與 z 必須照字面相符ビットごとの完全一致を要求する。式と case 項のビット長は同じでなければならず、x と z は文字どおり一致する必要がある
casezcasezcasezignores bit positions that contain z; ? may be used as a don't-care忽略含 z 的位元位置;可以用 ? 當作 don't-carez を含むビット位置を無視する。? をドントケアとして使える
casexcasexcasexignores bit positions that contain x or z; ? may also be used忽略含 x 或 z 的位元位置;同樣可以用 ?x または z を含むビット位置を無視する。? も使える
The incomplete-case trapcase 不完整的陷阱case が不完全なときの落とし穴

If the case list is incomplete, synthesis infers a latch to hold the unassigned value — an uncontrollable element that breaks static timing analysis and scan test. Always finish with default. Section 10.3 shows the synthesized result.如果 case 清單不完整,合成會推論出一個鎖存器來保住沒被賦值的那個值 — 那是個無法控制的元件,會破壞靜態時序分析與掃描測試。一律用 default 收尾。10.3 節會給出合成結果。case のリストが不完全だと、合成は代入されなかった値を保持するためにラッチを推論します — 制御できない素子であり、静的タイミング解析とスキャンテストを壊します。必ず default で締めてください。合成結果は 10.3 節に示します。

if…elseif…elseif…else

Loops迴圈ループ

repeat — fixed countrepeat — 固定次數repeat — 回数固定

parameter memory_size = 1024;
integer i;

initial begin
  i = 0;
  repeat (memory_size) begin
    mem[i] = 0;
    i = i + 1;
  end
end

for — the synthesizable workhorsefor — 可合成的主力for — 合成できる主力

integer k;
always @ (a or b) begin
  for (k = 0; k < 8; k = k + 1)
    y[k] = a[k] & b[k];
end
// unrolls into 8 AND gates

whilewhilewhile

while (count < limit) begin
  ...
  count = count + 1;
end

forever — clock generatorforever — 時脈產生器forever — クロック発生器

initial begin
  clk = 0;
  forever #5 clk = ~clk;   // 10-unit period
end
From the slides: how does always differ from forever? (click to expand)投影片提問:always 與 forever 有何不同?(點擊展開)スライドの問い:always と forever の違いは?(クリックで展開)
  • always is a module-level behavior. It runs in parallel with the other always/initial blocks as a thread of its own, and it is synthesizable.always 是模組層級的 behavior,和其他 always/initial 平行執行,自己就是一個執行緒;可以合成。always はモジュールレベルの behavior で、他の always/initial と並行に動く独立したスレッドです。合成できます。
  • forever is a statement-level loop. It must sit inside an initial or always block and cannot stand alone, and it is not synthesizable.forever 是敘述層級的迴圈,必須寫在 initial 或 always 裡面,不能單獨存在;不可合成。forever は文レベルのループで、initial か always の中に書く必要があり、単独では存在できません。合成はできません。
  • The key trap: if a forever contains no timing control (# or @), the simulation loops forever at the same instant and hangs. The same is true of always — always a = ~a; locks the simulator up.關鍵陷阱:forever 內若沒有任何時間控制(# 或 @),模擬會在同一個時間點 無限迴圈而卡死。always 也一樣 — always a = ~a; 會鎖死模擬器。重要な落とし穴:forever の中にタイミング制御(# や @)がないと、シミュレーションは同じ時刻で無限にループしてハングします。always も同様で、always a = ~a; はシミュレータを固めます。
From the slides: how does disable differ from $finish? (click to expand)投影片提問:disable 與 $finish 有何不同?(點擊展開)スライドの問い:disable と $finish の違いは?(クリックで展開)

disable terminates only the named block or task you point it at. The rest of the behavior keeps running and simulation time keeps advancing — the equivalent of C's break or an early return. $finish ends the whole simulation and returns control to the operating system. $stop merely pauses into interactive mode, and you can resume afterwards.disable 只終止指定的具名區塊或 task,其餘的 behavior 繼續跑,模擬時間繼續前進 — 相當於 C 的 break/提早 return。 $finish 結束整個模擬並把控制權交回作業系統。 $stop 則是暫停進入互動模式,之後還能繼續。disable は指定した名前付きブロックまたは task だけを終了させます。behavior の残りは動き続け、シミュレーション時間も進みます — C の break や早期 return に相当します。$finish はシミュレーション全体を終了し、制御をオペレーティングシステムに返します。$stop は対話モードで一時停止するだけで、後から再開できます。

begin : search_block          // named block
  for (i = 0; i < 16; i = i + 1)
    if (mem[i] == target) begin
      found = 1;
      disable search_block;   // break out early
    end
end

7.7 fork…join and race conditions7.7 fork…join 與競爭條件7.7 fork…join と競合状態

begin…endbegin…endbegin…endfork…joinfork…joinfork…join
statements execute sequentially敘述依序執行文は順番に実行されるstatements execute in parallel, as independent threads敘述平行執行,各自是獨立的執行緒文は独立したスレッドとして並行に実行される
finishes when the last statement finishes最後一個敘述結束時就結束最後の文が終わった時点で終了するfinishes when all threads have completed所有執行緒都完成時才結束すべてのスレッドが完了した時点で終了する
synthesizable可合成合成可能not supported by synthesis tools合成工具不支援合成ツールは非対応

There is no ordering among the threads, so interaction between them can create ambiguity.執行緒之間沒有先後順序,所以它們一旦互動就可能產生無法確定的結果。スレッド間に順序関係がないため、互いに影響し合うとあいまいさが生じ得ます。

Race condition有競爭條件競合状態あり

fork
  a = 1;
  b = a;      // is b 1 or the old a?
join

No race condition沒有競爭條件競合状態なし

fork
  a = 1;
  #1 b = a;   // ordering is now explicit
join
Definition of a race condition競爭條件的定義競合状態の定義

The target signal becomes ambiguous when different assignment statements occur simultaneously and the language does not define their order. The two classic cures: impose a delay, or use non-blocking assignments so that all reads happen before all writes.當不同的賦值敘述同時發生,而語言又沒有定義它們的先後順序時,目標訊號就變得無法確定。兩種經典解法:加上延遲,或改用非阻擋式賦值,讓所有讀取都發生在所有寫入之前。異なる代入文が同時に起こり、言語がその順序を定義していないとき、対象の信号はあいまいになります。古典的な対処は 2 つ:遅延を入れるか、ノンブロッキング代入を使ってすべての読み出しをすべての書き込みより先に済ませるかです。

7.8 Simulation of procedural assignments — the time-step algorithm7.8 程序式賦值的模擬 — 時間步演算法7.8 手続き型代入のシミュレーション — 時間ステップのアルゴリズム

Within one simulation time step, the simulator performs these steps in this order:在一個模擬時間步之內,模擬器依照這個順序執行下列步驟:1 つのシミュレーション時間ステップの中で、シミュレータはこの順序で次の処理を行います。

  1. Evaluate all expressions on the right-hand sides.計算所有右式的運算式。すべての右辺の式を評価する。
  2. Execute blocking assignments.執行阻擋式賦值。ブロッキング代入を実行する。
  3. Execute non-blocking assignments that have no intra-assignment timing control.執行沒有賦值內時序控制的非阻擋式賦值。代入内タイミング制御を持たないノンブロッキング代入を実行する。
  4. Execute past assignments that had been scheduled to land in the current time step.執行先前排程、要落在目前這個時間步的賦值。以前に登録され、現在の時間ステップに着地する予定の代入を実行する。
  5. Execute $monitor. ($display executes when it is encountered — that is, before the non-blocking assignments.)執行 $monitor。($display 是在被執行到的當下就跑 — 也就是在非阻擋式賦值之前。)$monitor を実行する。($display は出会った時点で実行される — つまりノンブロッキング代入より前です。)
  6. Advance simulation time.推進模擬時間。シミュレーション時刻を進める。
This list is the answer to most waveform questions這份清單就是大部分波形題的答案この一覧が波形問題のほとんどの答えになる

When an exam asks "what does $display print, and what does $monitor print, at time 10?", the answer is always read off this ordering: $display sees the pre-non-blocking values, $monitor sees the settled end-of-step values.當考題問「在時間 10 時 $display 印什麼、$monitor 又印什麼?」,答案永遠是照這個順序讀出來的:$display 看到的是非阻擋式賦值之前的值,$monitor 看到的是時間步結束後穩定下來的值。試験で「時刻 10 で $display は何を表示し、$monitor は何を表示するか」と問われたら、答えは常にこの順序から読み取れます。$display が見るのはノンブロッキング代入前の値、$monitor が見るのはステップ終了時の確定値です。

Practice 7 — The merged blocking / non-blocking example練習 7 — 阻擋式/非阻擋式的合併範例演習 7 — ブロッキングとノンブロッキングをまとめた例題

Problem: Work out the $monitor output of this module.題目:推導出這個模組的 $monitor 輸出。問題:このモジュールの $monitor の出力を求めなさい。

module blocking_nonblocking ();
  reg a, b, c, d;

  initial begin            initial begin
    #10  a = 0;              c = #10 0;
    #11  a = 1;              c = #11 1;
    #12  a = 0;              c = #12 0;
    #13  a = 1;              c = #13 1;
  end                      end

  initial begin            initial begin
    #10  b <= 0;             d <= #10 0;
    #11  b <= 1;             d <= #11 1;
    #12  b <= 0;             d <= #12 0;
    #13  b <= 1;             d <= #13 1;
  end                      end

  initial begin
    $monitor("TIME = %d A = %b B = %b C = %b D = %b", $time, a, b, c, d);
    #50 $finish;
  end
endmodule
Click to reveal solution點擊看解答クリックで解答を表示

Analyse each block separately.逐個區塊分析。ブロックごとに分析します。

a — delay control before a blocking assignment. Each #n suspends the flow, so the delays accumulate: assignments land at $t = 10,\; 21,\; 33,\; 46$.a — 阻擋式賦值前的延遲控制。每個 #n 都會暫停流程,所以延遲會累加:賦值分別落在 $t = 10,\; 21,\; 33,\; 46$。a — ブロッキング代入の前の遅延制御。それぞれの #n が実行フローを止めるので、遅延は累積します。代入は $t = 10,\; 21,\; 33,\; 46$ に着地します。

b — delay control before a non-blocking assignment. The #n is still a delay control on the activity flow, so the flow is suspended exactly as for a. Once the flow resumes, the non-blocking assignment lands at the end of that same time step. Times are therefore identical to a: $10, 21, 33, 46$.b — 非阻擋式賦值前的延遲控制。#n 仍然是作用在活動流程上的延遲控制,所以流程暫停的方式和 a 完全一樣。流程恢復後,非阻擋式賦值落在同一個時間步的末尾。因此時間點與 a 完全相同:$10, 21, 33, 46$。b — ノンブロッキング代入の前の遅延制御。#n は依然として実行フローに対する遅延制御なので、フローの停止のしかたは a とまったく同じです。フローが再開すると、ノンブロッキング代入はその同じ時間ステップの終わりに着地します。したがって時刻は a と同一で $10, 21, 33, 46$ です。

c — intra-assignment delay with blocking assignment. The RHS is evaluated immediately, but the statement still blocks for n units before assigning and before the next statement starts. So the delays accumulate again: $10, 21, 33, 46$. Same as a and b.c — 阻擋式賦值搭配賦值內延遲。右式立刻求值,但敘述仍會阻擋 n 個單位之後才賦值,也才輪到下一個敘述。所以延遲又累加起來:$10, 21, 33, 46$。與 a、b 相同。c — ブロッキング代入と代入内遅延。右辺は直ちに評価されますが、文は依然として n 単位だけブロックしてから代入し、その後に次の文へ進みます。よって遅延はまた累積し、$10, 21, 33, 46$ です。a・b と同じになります。

d — intra-assignment delay with non-blocking assignment. Non-blocking does not suspend the activity flow. All four statements execute at $t = 0$, each capturing its RHS immediately and scheduling the write independently. Assignments therefore land at $t = 10,\; 11,\; 12,\; 13$ — not accumulated.d — 非阻擋式賦值搭配賦值內延遲。非阻擋式不會暫停活動流程。四個敘述全都在 $t = 0$ 執行,各自立刻擷取自己的右式,並各自獨立地排程寫入。因此賦值落在 $t = 10,\; 11,\; 12,\; 13$ — 不會累加。d — ノンブロッキング代入と代入内遅延。ノンブロッキングは実行フローを止めません。4 つの文はすべて $t = 0$ で実行され、それぞれ直ちに右辺を取り込み、独立に書き込みを登録します。したがって代入は $t = 10,\; 11,\; 12,\; 13$ に着地し、累積しません。

Time時間時刻ABCDWhat happened發生了什麼起きたこと
0xxxxregisters power up unknown暫存器上電時為未知レジスタは電源投入時に不定
100000all four first assignments coincide四個區塊的第一次賦值同時發生4 ブロックの最初の代入が同時に起こる
110001only d's second assignment只有 d 的第二次賦值d の 2 回目の代入だけ
120000only d只有 dd だけ
130001only d — d is now finished只有 d — d 到此結束d だけ — d はこれで終わり
211111a, b, c second assignments (10+11)a、b、c 的第二次賦值(10+11)a・b・c の 2 回目の代入(10+11)
330001third assignments (21+12)第三次賦值(21+12)3 回目の代入(21+12)
461111fourth assignments (33+13)第四次賦值(33+13)4 回目の代入(33+13)

The lesson. Three of the four blocks behave identically. Only the combination of non-blocking assignment and intra-assignment delay decouples the schedule from the activity flow — because that is the only case where the statement does not suspend the thread. This is why d <= #5 x; is the correct idiom for modelling clock-to-Q delay in a flip-flop, and #5 d <= x; is not.教訓。四個區塊裡有三個行為完全相同。唯有非阻擋式賦值加上賦值內延遲的組合,才能把排程與活動流程脫鉤 — 因為那是唯一一種敘述不會暫停執行緒的情況。這正是為什麼模擬正反器的 clock-to-Q 延遲時,d <= #5 x; 才是正確的寫法,#5 d <= x; 不是。教訓。4 つのブロックのうち 3 つはまったく同じ振る舞いをします。スケジュールを実行フローから切り離せるのは、ノンブロッキング代入と代入内遅延の組合せだけです — 文がスレッドを止めない唯一の場合だからです。フリップフロップのクロック-Q 遅延をモデル化するとき d <= #5 x; が正しい書き方で、#5 d <= x; がそうでない理由がこれです。

Practice 8 — Swapping two registers練習 8 — 交換兩個暫存器演習 8 — 2 つのレジスタを入れ替える

Problem: You want to swap a and b on every rising clock edge. Consider three attempts. Which work, and what does each synthesize to?題目:你想在每個時脈上升邊緣交換 a 與 b。考慮以下三種寫法。哪些行得通?各自又會合成出什麼?問題:クロックの立ち上がりごとに a と b を入れ替えたいとします。3 つの書き方を考えます。どれが正しく、それぞれ何に合成されますか。

// Attempt 1                  // Attempt 2                 // Attempt 3
always @(posedge clk) begin   always @(posedge clk) begin  always @(posedge clk)
  a = b;                        a <= b;                      a <= b;
  b = a;                        b <= a;                    always @(posedge clk)
end                           end                            b <= a;
Click to reveal solution點擊看解答クリックで解答を表示

Attempt 1 — broken. Blocking assignments complete in order. After a = b, a already holds b's value, so b = a writes b's own value back. Both registers end up holding the old b. Synthesis produces two flip-flops both fed from b — a copy, not a swap.寫法 1 — 錯誤。阻擋式賦值會依序完成。a = b 之後 a 已經是 b 的值,所以 b = a 只是把 b 自己的值寫回去。兩個暫存器最後都拿到舊的 b。合成出來是兩個都由 b 餵入的正反器 — 這是複製,不是交換。書き方 1 — 誤り。ブロッキング代入は順番に完了します。a = b の後 a はすでに b の値なので、b = a は b 自身の値を書き戻すだけです。両方のレジスタが古い b を保持して終わります。合成すると、どちらも b から入力される 2 つのフリップフロップになります — 入れ替えではなく複製です。

Attempt 2 — correct. Both right-hand sides are evaluated first (capturing the old a and old b), then both assignments occur. This is exactly the behavior of two flip-flops whose D inputs are cross-connected to each other's Q. The swap works.寫法 2 — 正確。兩個右式先被求值(擷取舊的 a 與舊的 b),然後兩個賦值一起發生。這正是兩個 D 輸入互相交叉接到對方 Q 的正反器的行為。交換成功。書き方 2 — 正しい。まず両方の右辺が評価され(古い a と古い b を取り込み)、その後で両方の代入が起こります。これは D 入力を互いの Q に交差接続した 2 つのフリップフロップの動作そのものです。入れ替えは成功します。

Attempt 3 — also correct. Two separate behaviors, each non-blocking. Because non-blocking assignments are order-independent, it does not matter which always block the simulator happens to evaluate first. This is precisely why the lecture recommends non-blocking assignments for FSM and sequential code: it removes the dependence on evaluation order between behaviors.寫法 3 — 同樣正確。兩個獨立的 behavior,各自用非阻擋式。因為非阻擋式賦值與順序無關,模擬器先算哪一個 always 區塊都無所謂。這正是投影片建議 FSM 與序向程式碼一律使用非阻擋式賦值的理由:它消除了 behavior 之間對求值順序的依賴。書き方 3 — これも正しい。独立した 2 つの behavior が、それぞれノンブロッキング代入を使っています。ノンブロッキング代入は順序に依存しないので、シミュレータがどちらの always を先に評価しても関係ありません。FSM や順序回路のコードにノンブロッキング代入が推奨される理由はまさにこれで、behavior 間の評価順序への依存がなくなるからです。

The general rule. If two registers are updated in the same clock domain and either depends on the other, blocking assignment makes the result depend on textual order — a race. Non-blocking assignment makes the result match the hardware.通則。如果兩個暫存器在同一個時脈域內更新,而且其中一個依賴另一個,那麼阻擋式賦值會讓結果取決於文字順序 — 這就是競爭。非阻擋式賦值則讓結果與硬體一致。一般則。同じクロックドメインで更新される 2 つのレジスタが互いに依存している場合、ブロッキング代入では結果が記述順に左右されます — それが競合です。ノンブロッキング代入なら結果はハードウェアと一致します。

8. Tasks, Functions, and Timing Analysis8. 任務、函式與時序分析8. タスク・関数とタイミング解析

8.1 Task versus function8.1 task 與 function8.1 task と function

Both let you call a common procedure from several places and both improve readability. The differences are mechanical and heavily examined:兩者都讓你從多個地方呼叫同一段共用流程,也都能改善可讀性。差別是機械式的,而且是考試重點:どちらも共通の処理を複数の場所から呼び出せるようにし、可読性も高めます。違いは形式的なものですが、試験で頻出です。

task … endtasktask … endtasktask … endtaskfunction … endfunctionfunction … endfunctionfunction … endfunction
Arguments引數引数zero or more, of type input, output, or inout零個或多個,型別可為 input、output 或 inout0 個以上。型は input、output、inout のいずれかat least one input; no output or inout至少一個 input;不可以有 output 或 inoutinput が少なくとも 1 つ必要。output と inout は不可
Returns回傳值戻り値nothing — passes values back through output/inout沒有 — 透過 output/inout 把值帶回去なし — output/inout を通して値を返すalways a single value, through its own name永遠是單一個值,透過自己的名稱回傳常に 1 つの値を、自分自身の名前を通して返す
Timing control時序控制タイミング制御may contain # and @可以包含 # 與 @# と @ を含められるmust not contain any一律不可包含一切含めてはならない
Simulation time模擬時間シミュレーション時間may consume non-zero time可以耗掉非零的時間ゼロでない時間を消費してよいalways executes in zero time永遠在零時間內執行完常にゼロ時間で実行される
Called from從哪裡呼叫呼び出し元a procedural statement程序式敘述手続き文an expression — e.g. the RHS of a continuous assignment運算式 — 例如連續賦值的右式式 — たとえば連続代入の右辺
Models可建模的對象モデル化できるものanything任何東西何でもcombinational behavior only只有組合行為組合せ動作のみ
Shared characteristics共通的特性共通の性質
  • Both are declared within a module and must be named.兩者都宣告在模組之內,而且必須命名。どちらもモジュールの中で宣言し、名前を付けなければなりません。
  • Local variables may be declared inside either.兩者內部都可以宣告區域變數。どちらの中でもローカル変数を宣言できます。
  • Arguments are passed by value, and are associated with the formal arguments in declaration order.引數是以值傳遞,並且依宣告順序與形式引數對應。引数は値渡しで、宣言順に仮引数と対応づけられます。
  • A function implicitly declares a register variable with the same name, range, and type as the function itself; the function body must assign to that variable — that is how it returns.function 會隱含地宣告一個與函式同名、同範圍、同型別的 register 變數;函式本體必須賦值給這個變數 — 它就是這樣回傳的。function は、関数自身と同じ名前・範囲・型のレジスタ変数を暗黙に宣言します。関数の本体はその変数に代入しなければなりません — それが戻り値の返し方です。

Task — can have multiple outputstask — 可以有多個輸出task — 出力を複数持てる

task full_adder;
  input  a, b, cin;
  output sum, cout;
  begin
    sum  = a ^ b ^ cin;
    cout = (a & b) | (a & cin) | (b & cin);
  end
endtask

always @ (a or b or cin)
  full_adder (a, b, cin, s, co);

Function — returns one valuefunction — 回傳一個值function — 値を 1 つ返す

function [3:0] add4;
  input [3:0] x, y;
  begin
    add4 = x + y;      // assign to the function name
  end
endfunction

assign sum = add4(a, b);   // called in an expression

Worked example — LFSR as a function實例演練 — 用 function 寫 LFSR実例 — LFSR を function で書く

A Linear Feedback Shift Register is the standard binary pattern generator for self-testing circuits, and in a communication IC it is also the scrambler and the PRBS source. The lecture's structure:線性回授移位暫存器是自我測試電路的標準二元圖樣產生器,在通訊 IC 裡它同時也是擾碼器與 PRBS 源。投影片給的結構是:線形帰還シフトレジスタは自己テスト回路の標準的な 2 値パターン発生器であり、通信 IC ではスクランブラや PRBS 源でもあります。講義が示す構成は次のとおりです。

module lfsr (Y, clk, rst);
  parameter N    = 8;
  parameter TAPS = 8'b1000_1110;    // C[N-1:0], the characteristic polynomial
  output [N-1:0] Y;
  input          clk, rst;
  reg    [N-1:0] Y;

  function [N-1:0] next_state;
    input [N-1:0] y;
    integer j;
    begin
      next_state[N-1] = y[0];                        // C_N = 1 always
      for (j = 1; j <= N-1; j = j + 1)
        next_state[j-1] = TAPS[j] ? (y[j] ^ y[0]) : y[j];
    end
  endfunction

  always @ (posedge clk or posedge rst)
    if (rst) Y <= {N{1'b1}};        // must never be all-zero
    else     Y <= next_state(Y);
endmodule
Why a function and not a task here這裡為什麼用 function 而不是 taskここで task ではなく function を使う理由

The next-state computation is pure combinational logic returning one value, evaluated in zero time, and it is used on the right-hand side of an assignment. That is the exact profile of a function. Writing it as a task would force it into a procedural statement and lose the ability to write Y <= next_state(Y); in one line.次態的計算是純組合邏輯,回傳單一個值,在零時間內完成,而且用在賦值的右式。這完全符合 function 的輪廓。如果寫成 task,就會被迫變成程序式敘述,也就寫不出 Y <= next_state(Y); 這樣的一行了。次状態の計算は純粋な組合せ論理で、値を 1 つ返し、ゼロ時間で評価され、代入の右辺で使われます。これはまさに function の輪郭です。task として書くと手続き文に押し込められ、Y <= next_state(Y); と 1 行で書けなくなります。

8.2 Static versus dynamic timing analysis8.2 靜態時序分析與動態時序分析8.2 静的タイミング解析と動的タイミング解析

Static timing analysis (STA)靜態時序分析(STA)静的タイミング解析(STA)Dynamic timing analysis動態時序分析動的タイミング解析
Method方法手法no simulation — analyses the netlist graph不做模擬 — 直接分析網表構成的圖シミュレーションせず、ネットリストのグラフを解析するsimulation-based以模擬為基礎シミュレーションに基づく
Coverage涵蓋範圍カバレッジconsiders all paths, including false paths that can never be exercised考慮所有路徑,包括永遠不可能被觸發的偽路徑すべての経路を考慮する。決して活性化されない false path も含むonly paths the input stimulus actually exercises只有輸入激勵實際走到的路徑入力刺激が実際に通した経路だけ
Risk風險リスクpessimistic — reports violations on paths that do not matter偏悲觀 — 會在無關緊要的路徑上報違規悲観的 — 問題にならない経路でも違反を報告するoptimistic — can miss violations if the stimulus is incomplete偏樂觀 — 激勵不完整時可能漏掉違規楽観的 — 刺激が不十分だと違反を見逃しうる
False paths偽路徑false pathreported; must be excluded manually會被報出來;必須手動排除報告される。手動で除外する必要があるnot reported不會被報出來報告されない
Slack $$\text{slack} = \text{required arrival time} - \text{arrival time}$$Slack $$\text{slack} = \text{required arrival time} - \text{arrival time}$$スラック $$\text{slack} = \text{required arrival time} - \text{arrival time}$$
Reading slack如何讀 slackスラックの読み方

Slack $\ge 0$: the path meets its timing budget — good.
Slack $< 0$: the path violates the budget — bad. This is the single number synthesis is optimising, and the reason the tool restructures your logic.
Slack $\ge 0$:這條路徑符合時序預算 — 好。
Slack $< 0$:這條路徑違反預算 — 不好。這就是合成在最佳化的那一個數字,也是工具會去重構你的邏輯的原因。
スラック $\ge 0$:その経路はタイミング予算を満たしています — 良好。
スラック $< 0$:予算を超過しています — 不良。合成が最適化しているのはこの 1 つの数字であり、ツールがあなたの論理を作り替える理由でもあります。

Practice 9 — Slack and the critical path練習 9 — Slack 與關鍵路徑演習 9 — スラックとクリティカルパス

Problem: A combinational path runs from a launching flip-flop through three gates with delays 1.2 ns, 0.8 ns, and 1.5 ns to a capturing flip-flop. Clock-to-Q of the launching FF is 0.4 ns; the setup time of the capturing FF is 0.3 ns. The clock period is 4 ns with zero skew. (a) Compute the arrival time, required arrival time, and slack. (b) What is the maximum clock frequency? (c) If synthesis reports slack of $-0.6$ ns, name two things you could change in the RTL.題目:有一條組合路徑,從發射端正反器出發,經過延遲 1.2 ns、0.8 ns、1.5 ns 的三個閘,到達接收端正反器。發射端正反器的 clock-to-Q 為 0.4 ns;接收端正反器的 setup 時間為 0.3 ns。時脈週期 4 ns,skew 為零。 (a) 求 arrival time、required arrival time 與 slack。(b) 最高時脈頻率是多少?(c) 若合成回報 slack 為 $-0.6$ ns,請舉出兩個你可以在 RTL 層改動的地方。問題:ある組合せ経路が、送出側フリップフロップから遅延 1.2 ns・0.8 ns・1.5 ns の 3 つのゲートを通って受け側フリップフロップに至ります。送出側のクロック-Q は 0.4 ns、受け側のセットアップ時間は 0.3 ns、クロック周期は 4 ns でスキューはゼロです。 (a) 到達時刻・要求到達時刻・スラックを求めなさい。(b) 最大クロック周波数はいくらですか。(c) 合成がスラック $-0.6$ ns を報告した場合、RTL で変えられることを 2 つ挙げなさい。

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

(a) Arrival time at the D pin of the capturing flip-flop:(a) 資料抵達接收端正反器 D 腳的時刻:(a) 受け側フリップフロップの D ピンへの到達時刻:

$$t_{\text{arrival}} = t_{\text{CQ}} + \sum t_{\text{gate}} = 0.4 + (1.2 + 0.8 + 1.5) = 3.9\ \text{ns}$$$$t_{\text{arrival}} = t_{\text{CQ}} + \sum t_{\text{gate}} = 0.4 + (1.2 + 0.8 + 1.5) = 3.9\ \text{ns}$$$$t_{\text{arrival}} = t_{\text{CQ}} + \sum t_{\text{gate}} = 0.4 + (1.2 + 0.8 + 1.5) = 3.9\ \text{ns}$$

Required arrival time, i.e. the latest the data may arrive and still be captured:required arrival time,也就是資料最晚可以在什麼時候抵達而仍能被擷取:要求到達時刻、すなわちデータが到着してもまだ取り込める最も遅い時刻:

$$t_{\text{required}} = T_{\text{clk}} - t_{\text{setup}} = 4.0 - 0.3 = 3.7\ \text{ns}$$ $$\text{slack} = 3.7 - 3.9 = -0.2\ \text{ns} \quad \Rightarrow \quad \textbf{violation}$$$$t_{\text{required}} = T_{\text{clk}} - t_{\text{setup}} = 4.0 - 0.3 = 3.7\ \text{ns}$$ $$\text{slack} = 3.7 - 3.9 = -0.2\ \text{ns} \quad \Rightarrow \quad \textbf{violation}$$$$t_{\text{required}} = T_{\text{clk}} - t_{\text{setup}} = 4.0 - 0.3 = 3.7\ \text{ns}$$ $$\text{slack} = 3.7 - 3.9 = -0.2\ \text{ns} \quad \Rightarrow \quad \textbf{violation}$$

(b) The minimum feasible period is $t_{\text{CQ}} + t_{\text{logic}} + t_{\text{setup}} = 0.4 + 3.5 + 0.3 = 4.2$ ns, so(b) 可行的最小週期是 $t_{\text{CQ}} + t_{\text{logic}} + t_{\text{setup}} = 0.4 + 3.5 + 0.3 = 4.2$ ns,所以(b) 実現できる最小周期は $t_{\text{CQ}} + t_{\text{logic}} + t_{\text{setup}} = 0.4 + 3.5 + 0.3 = 4.2$ ns なので、

$$f_{\max} = \frac{1}{4.2\ \text{ns}} \approx 238\ \text{MHz}$$$$f_{\max} = \frac{1}{4.2\ \text{ns}} \approx 238\ \text{MHz}$$$$f_{\max} = \frac{1}{4.2\ \text{ns}} \approx 238\ \text{MHz}$$

(c) Two RTL-level fixes, both taught in this course:(c) 兩個 RTL 層級的解法,都是本課程教過的:(c) RTL レベルの対策を 2 つ。どちらもこの講義で扱ったものです。

  • Pipelining — insert a register in the middle of the combinational chain, splitting 3.5 ns of logic into two stages of roughly 1.75 ns each. Throughput is preserved; latency grows by one cycle. This is exactly the 16-bit adder example in Section 11.4.管線化 — 在組合鏈中間插入一級暫存器,把 3.5 ns 的邏輯切成兩段、各約 1.75 ns。吞吐量不變,延遲多一個週期。這正是 11.4 節那個 16 位元加法器的例子。パイプライン化 — 組合せチェーンの途中にレジスタを 1 段入れ、3.5 ns の論理をおよそ 1.75 ns の 2 段に分けます。スループットは保たれ、レイテンシが 1 サイクル増えます。これは 11.4 節の 16 ビット加算器の例そのものです。
  • Restructure the logic — replace a ripple-carry adder with a carry-look-ahead adder, or rewrite a long priority if…else if chain as a case with mutually exclusive items so that it synthesizes to a balanced mux instead of a serial priority structure (Section 10.5).重構邏輯 — 把漣波進位加法器換成超前進位加法器,或把一長串優先權式的 if…else if 改寫成項目互斥的 case,讓它合成出平衡的多工器而不是串列的優先權結構(10.5 節)。論理の作り替え — リップルキャリー加算器をキャリー先見加算器に置き換える、あるいは長い優先順位付きの if…else if 連鎖を、項目が互いに排他的な case に書き換えて、直列の優先順位構造ではなくバランスの取れたマルチプレクサに合成させます(10.5 節)。

A third, non-RTL option is to let the synthesis tool retime or upsize cells — but 0.2 ns on a 4 ns period is usually recoverable by constraint tuning alone.第三個非 RTL 的選項,是讓合成工具做 retiming 或把單元加大 — 不過 4 ns 週期上差 0.2 ns,通常光靠調整約束就能救回來。RTL 以外の第 3 の選択肢として、合成ツールにリタイミングやセルのサイズアップをさせる手もあります — ただし 4 ns 周期で 0.2 ns の不足なら、たいていは制約の調整だけで取り戻せます。

8.3 Timing-check system tasks8.3 時序檢查系統任務8.3 タイミングチェック・システムタスク

These may be invoked inside a testbench behavior or inside a module's specify block.這些可以在測試平台的 behavior 內呼叫,也可以寫在模組的 specify 區塊裡。これらはテストベンチの behavior の中でも、モジュールの specify ブロックの中でも呼び出せます。

Task任務タスクViolation is reported when…在什麼情況下回報違規…違反が報告される条件…Example範例例
$setup(data_event, ref_event, limit)$setup(data_event, ref_event, limit)$setup(data_event, ref_event, limit)the time from data_event to ref_event is less than limit從 data_event 到 ref_event 的時間小於 limitdata_event から ref_event までの時間が limit 未満のとき$setup(data, posedge clk, 5);$setup(data, posedge clk, 5);$setup(data, posedge clk, 5);
$hold(ref_event, data_event, limit)$hold(ref_event, data_event, limit)$hold(ref_event, data_event, limit)data is stable for less than limit after ref_eventref_event 之後資料維持穩定的時間小於 limitref_event の後にデータが安定している時間が limit 未満のとき$hold(posedge clk, data, 2);$hold(posedge clk, data, 2);$hold(posedge clk, data, 2);
$setuphold(data, ref, s_limit, h_limit)$setuphold(data, ref, s_limit, h_limit)$setuphold(data, ref, s_limit, h_limit)combination of both上述兩者的組合上記 2 つの組合せ$setuphold(data, posedge clk, 5, 2);$setuphold(data, posedge clk, 5, 2);$setuphold(data, posedge clk, 5, 2);
$period(ref_event, limit)$period(ref_event, limit)$period(ref_event, limit)two consecutive ref_events are closer than limit連續兩個 ref_event 的間隔比 limit 還短連続する 2 つの ref_event の間隔が limit より短いとき$period(posedge clk, 16);$period(posedge clk, 16);$period(posedge clk, 16);
$width(ref_event, limit)$width(ref_event, limit)$width(ref_event, limit)the interval from ref_event to the next opposite transition is less than limit從 ref_event 到下一次反向轉態的間隔小於 limitref_event から次の逆向きの遷移までの間隔が limit より短いとき$width(posedge clk, 8);$width(posedge clk, 8);$width(posedge clk, 8);
$skew(event_1, event_2, limit)$skew(event_1, event_2, limit)$skew(event_1, event_2, limit)the time between the two events exceeds limit兩個事件之間的時間超過 limit2 つのイベント間の時間が limit を超えるとき$skew(posedge clk1, posedge clk2, 3);$skew(posedge clk1, posedge clk2, 3);$skew(posedge clk1, posedge clk2, 3);
$nochange(ref, data, start, end)$nochange(ref, data, start, end)$nochange(ref, data, start, end)data changes inside the window relative to ref_event資料在相對於 ref_event 的視窗內發生變化ref_event を基準とする窓の中でデータが変化したとき$nochange(posedge clk, data, -1, 2);$nochange(posedge clk, data, -1, 2);$nochange(posedge clk, data, -1, 2);
Argument order is not arbitrary引數順序不是隨便排的引数の順序は恣意的ではない

Note that $setup takes (data, reference) while $hold takes (reference, data). The order mirrors the physical ordering in time: setup measures data before the clock, hold measures data after the clock. Getting this backwards is a guaranteed lost mark.注意 $setup 收的是 (data, reference),而 $hold 收的是 (reference, data)。這個順序對應著時間上的物理順序:setup 量的是時脈之前的資料,hold 量的是時脈之後的資料。寫反必定丟分。$setup は (data, reference) を取り、$hold は (reference, data) を取ることに注意してください。この順序は時間軸上の物理的な順序を映しています。セットアップはクロックの前のデータを、ホールドはクロックの後のデータを測ります。逆にすれば確実に失点します。

The edge specifieredge 指定子edge 指定子

The transitions {01, 10, 0x, x1, 1x, x0} can be named explicitly:轉態 {01, 10, 0x, x1, 1x, x0} 可以被明確指名:遷移 {01, 10, 0x, x1, 1x, x0} は明示的に名指しできます。

$setuphold (data, edge 01 clk, 5, 2);

NotifiersNotifierノーティファイア

When a timing check is violated, Verilog reports the violation but the output still takes its new value — which hides the fact that real silicon might have gone metastable. A notifier fixes this: an extra port on a sequential UDP that forces the output to x whenever the notifier register toggles.時序檢查被違反時,Verilog 會回報違規,但輸出仍然會取得新值 — 這就掩蓋了真實矽晶片可能已經進入介穩態的事實。notifier 解決了這件事:在序向 UDP 上多加一個埠,只要 notifier 暫存器翻轉就把輸出強制成 x。タイミングチェックに違反すると、Verilog は違反を報告しますが出力は新しい値を取ってしまいます — 実際のシリコンならメタステーブルになっていたかもしれない事実が隠れてしまうのです。ノーティファイアがこれを解決します。順序回路 UDP に追加のポートを設け、ノーティファイア・レジスタがトグルするたびに出力を x に強制します。

reg notifier;
specify
  $setuphold (posedge clk, data, 5, 2, notifier);
endspecify
// the UDP has an extra input port bound to `notifier`;
//   toggling it drives q to x, propagating the uncertainty

9. Finite State Machines9. 有限狀態機9. 有限状態機械

9.1 Mealy versus Moore9.1 Mealy 與 Moore9.1 Mealy と Moore

MEALY — output depends on state AND inputMEALY — 輸出取決於狀態「與」輸入MEALY — 出力は状態と入力の両方で決まる Next-state次態次状態 logic邏輯論理 State狀態状態 register暫存器レジスタ Output輸出出力 logic邏輯論理 in輸入入力 out輸出出力 current state現態現在の状態 the input reaches the output logic directly輸入直接抵達輸出邏輯入力が出力論理に直接届く MOORE — output depends on state ONLYMOORE — 輸出「只」取決於狀態MOORE — 出力は状態だけで決まる Next-state次態次状態 logic邏輯論理 State狀態状態 register暫存器レジスタ Output輸出出力 logic邏輯論理 in輸入入力 out輸出出力 current state現態現在の状態 no path from the input to the output logic — glitch-free, registered沒有從輸入到輸出邏輯的路徑 — 無突波,已被暫存入力から出力論理への経路がない — グリッチなし、レジスタ出力
Mealy and Moore machines. The only structural difference is the red path: in Mealy the input feeds the output logic directly, so the output can change mid-cycle. The lecture marks Moore as the better choice.Mealy 與 Moore 機器。結構上唯一的差別就是那條紅色路徑:Mealy 的輸入直接餵進輸出邏輯,所以輸出可能在週期中途就改變。投影片把 Moore 標為較好的選擇。Mealy 機械と Moore 機械。構造上の唯一の違いは赤い経路です。Mealy では入力が出力論理に直接入るため、出力がサイクルの途中で変わり得ます。講義は Moore をより良い選択としています。
MealyMealyMealyMooreMooreMoore
Output depends on輸出取決於出力が依存するものcurrent state and inputs現態與輸入現在の状態と入力current state only只有現態現在の状態のみ
Labelled on the state graph在狀態圖上標在状態遷移図での表示位置each arc (transition)每一條弧(轉移)上各アーク(遷移)each node (state)每一個節點(狀態)上各ノード(状態)
States needed需要的狀態數必要な状態数generally fewer通常較少一般に少ないgenerally more通常較多一般に多い
Output timing輸出時序出力のタイミングresponds in the same cycle as the input; can glitch與輸入同一個週期就反應;可能出現突波入力と同じサイクルで応答する。グリッチが出うるchanges only after a clock edge; glitch-free只在時脈邊緣之後才改變;無突波クロックエッジの後にのみ変化する。グリッチなし
Lecture's verdict投影片的結論講義の結論Better較佳こちらが良い
Why Moore is "better" here為什麼這裡說 Moore「較好」ここで Moore が「良い」とされる理由

Because the output is a pure function of registered state, it is stable for the whole cycle and cannot pass an input glitch straight through to the output. That matters enormously when the FSM output drives another clock domain or an off-chip pin. The cost is an extra state and one cycle of latency.因為輸出是已暫存狀態的純函數,它整個週期都穩定,也不可能把輸入的突波直接傳到輸出。當 FSM 的輸出要驅動另一個時脈域或晶片外的接腳時,這件事非常重要。代價是多一個狀態和一個週期的延遲。出力がレジスタに取り込まれた状態の純粋な関数なので、1 サイクルを通じて安定し、入力のグリッチをそのまま出力へ通すことがありません。FSM の出力が別のクロックドメインやチップ外のピンを駆動する場合、この点は決定的に重要です。代償は状態が 1 つ増えることと 1 サイクルのレイテンシです。

9.2 Explicit versus implicit style9.2 顯式風格與隱式風格9.2 明示的スタイルと暗黙的スタイル

Explicit style — better顯式風格 — 較佳明示的スタイル — こちらが良いImplicit style隱式風格暗黙的スタイル
Mechanism機制仕組みdeclare a state register that encodes the state宣告一個把狀態編碼起來的狀態暫存器状態を符号化する状態レジスタを宣言するuse multiple event controls to describe an evolution of states用多個事件控制描述狀態的演進複数のイベント制御で状態の推移を記述する
Code volume程式量コード量more較多多いless, more abstract較少,較抽象少なく、より抽象的
Reset重置リセットstraightforward直截了當素直に書けるcan be considerably more complicated可能複雜得多かなり複雑になりうる
Applicability適用範圍適用範囲any FSM任何 FSMあらゆる FSMonly when a given state can be reached from exactly one other state只有當某個狀態恰好只能由另一個狀態抵達時ある状態にちょうど 1 つの状態からしか到達しない場合のみ
Synthesis合成合成reliable可靠確実frequently un-synthesizable經常無法合成しばしば合成できない

Implicit style — avoid隱式風格 — 避免使用暗黙的スタイル — 避けること

always begin
  @(posedge clk) y = 0;
  @(posedge clk) y = 1;
  @(posedge clk) y = 1;
end
// no state register; reset is awkward;
//   only works for a simple ring

Explicit style — use顯式風格 — 建議使用明示的スタイル — こちらを使う

always @(posedge clk or posedge rst)
  if (rst) state <= S0;
  else     state <= next_state;

always @(*)
  case (state)
    S0: next_state = S1;
    S1: next_state = S2;
    S2: next_state = S0;
    default: next_state = S0;
  endcase

9.3 The recommended coding template9.3 建議的撰寫樣板9.3 推奨される記述テンプレート

The lecture's recommendations, verbatim投影片的建議,原文照錄講義の推奨事項(原文どおり)
  • Make sure the description is complete.確認描述是完整的。記述が完全であることを確認する。
  • Use separate behaviors to describe the state transitions and the next-state logic.用分開的 behavior 來描述狀態轉移與次態邏輯。状態遷移と次状態論理は別々の behavior で記述する。
  • Use non-blocking assignments, because they are order-independent.使用非阻擋式賦值,因為它與順序無關。順序に依存しないのでノンブロッキング代入を使う。
  • Never mix blocking and non-blocking assignments to the same variable within the same behavior.在同一個 behavior 內,對同一個變數絕不混用阻擋式與非阻擋式賦值。同じ behavior の中で同じ変数にブロッキングとノンブロッキングを混ぜない。

The resulting three-block template is the one to reproduce under exam conditions:由此得到的三區塊樣板,就是考試時要能默寫出來的那一個:こうして得られる 3 ブロックのテンプレートが、試験で再現できるようにしておくべきものです。

module seq_detect (out, in_bit, clk, rst);
  output out;
  input  in_bit, clk, rst;

  parameter S0 = 2'b00,   // no history
            S1 = 2'b01,   // last bit was 0
            S2 = 2'b10,   // last bit was 1
            S3 = 2'b11;   // two successive equal bits seen

  reg [1:0] state, next_state;

  // ---- Block 1: state register (sequential) ----
  always @ (posedge clk or posedge rst)
    if (rst) state <= S0;
    else     state <= next_state;

  // ---- Block 2: next-state logic (combinational) ----
  always @ (state or in_bit)
    case (state)
      S0:      next_state = in_bit ? S2 : S1;
      S1:      next_state = in_bit ? S2 : S3;
      S2:      next_state = in_bit ? S3 : S1;
      S3:      next_state = in_bit ? S3 : S1;
      default: next_state = S0;          // completes the case — no latch
    endcase

  // ---- Block 3: output logic (Moore: state only) ----
  assign out = (state == S3);
endmodule
Three things that must be present必須具備的三件事必ず備えるべき 3 点
  1. A default (or a fully-enumerated case) in block 2 — otherwise an unwanted latch.第 2 個區塊要有 default(或把 case 完全列舉)— 否則會生出非預期的鎖存器。ブロック 2 に default(または完全に列挙した case)を置く — さもないと意図しないラッチができます。
  2. Non-blocking <= in block 1, blocking = in block 2.第 1 個區塊用非阻擋式 <=,第 2 個區塊用阻擋式 =。ブロック 1 ではノンブロッキング <=、ブロック 2 ではブロッキング = を使う。
  3. A reset that puts the machine in a known state — otherwise the FSM starts at x and never recovers, because case (2'bxx) matches no item.要有把機器帶到已知狀態的重置 — 否則 FSM 會從 x 起步而且永遠回不來,因為 case (2'bxx) 比對不到任何項目。機械を既知の状態に置くリセットを用意する — さもないと FSM は x から始まり、case (2'bxx) はどの項目にも一致しないため二度と復帰できません。

9.4 State encoding9.4 狀態編碼9.4 状態エンコーディング

Encoding編碼方式エンコーディング4 states as4 個狀態編成4 状態の表し方FF count正反器數FF の数Next-state logic次態邏輯次状態論理Best for最適合適した用途
Binary二進位バイナリ00, 01, 10, 11$\lceil \log_2 N \rceil$ — minimum$\lceil \log_2 N \rceil$ — 最少$\lceil \log_2 N \rceil$ — 最小widest / deepest最寬/最深最も広く・深いarea-critical, many states面積吃緊、狀態很多的情況面積が厳しく状態数が多い場合
Gray格雷碼グレイ00, 01, 11, 10$\lceil \log_2 N \rceil$$\lceil \log_2 N \rceil$$\lceil \log_2 N \rceil$moderate中等中程度counters, async FIFO pointers — only one bit changes per step計數器、非同步 FIFO 指標 — 每步只變一個位元カウンタ、非同期 FIFO のポインタ — 1 ステップで 1 ビットしか変わらない
One-hotOne-hotワンホット0001, 0010, 0100, 1000$N$ — maximum$N$ — 最多$N$ — 最大shallowest, often a single AND-OR level最淺,往往只需一層 AND-OR最も浅く、多くの場合 AND-OR 1 段で済むspeed-critical FSMs, FPGAs (flip-flops are free)速度吃緊的 FSM、FPGA(正反器不用錢)速度が厳しい FSM、FPGA(フリップフロップはただ同然)
JohnsonJohnsonジョンソン000, 001, 011, 111, 110, 100$N/2$simple簡單単純ring-type sequencers, glitch-free decode環狀定序器、無突波解碼リング型シーケンサ、グリッチのないデコード
One-hot and the default branchOne-hot 與 default 分支ワンホットと default 分岐

With one-hot encoding, the vast majority of the $2^N$ codes are illegal states. A default branch that returns to the reset state is therefore not just a latch-prevention measure — it is the FSM's recovery path after a single-event upset. In a communication IC that matters.採用 one-hot 編碼時,$2^N$ 個碼中絕大多數都是不合法狀態。因此一個會回到重置狀態的 default 分支,就不只是防鎖存器的措施 — 它是 FSM 在單一事件翻轉之後的復原路徑。在通訊 IC 裡,這件事很重要。ワンホット符号化では、$2^N$ 個の符号のほとんどが不正な状態です。したがってリセット状態に戻る default 分岐は、単なるラッチ防止策ではありません — シングルイベント・アップセット後の FSM の復帰経路です。通信 IC ではこれが効いてきます。

Practice 10 — Sequence detector, Mealy and Moore練習 10 — 序列偵測器,Mealy 與 Moore演習 10 — シーケンス検出器、Mealy と Moore

Problem: Design an FSM that synchronously reads a serial bit stream and asserts its output after two successive equal bits (two 0s or two 1s) are detected. It is active on the rising clock edge. (a) Draw the Moore state graph. (b) For the input stream 0 0 1 1 1 0 0 0 1, give the output sequence. (c) How would a Mealy version differ?題目:設計一個 FSM,同步讀取序列位元流,在偵測到連續兩個相同的位元(兩個 0 或兩個 1)之後令輸出成立。它在時脈上升邊緣作用。 (a) 畫出 Moore 狀態圖。(b) 對輸入串 0 0 1 1 1 0 0 0 1,寫出輸出序列。(c) Mealy 版本會有什麼不同?問題:シリアルビット列を同期的に読み取り、連続する 2 つの等しいビット(0 が 2 つ、または 1 が 2 つ)を検出したら出力をアサートする FSM を設計しなさい。クロックの立ち上がりで動作します。 (a) Moore 型の状態遷移図を描きなさい。(b) 入力列 0 0 1 1 1 0 0 0 1 に対する出力列を示しなさい。(c) Mealy 版はどう違いますか。

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

(a) Four states suffice. Let $S_1$ = "last bit was 0, no pair yet", $S_2$ = "last bit was 1, no pair yet", $S_3$ = "a pair has just been completed". Because the output must be a function of state alone, the pair detection has to be captured in the state.(a) 四個狀態就夠了。令 $S_1$ =「上一個位元是 0,尚未成對」、$S_2$ =「上一個位元是 1,尚未成對」、$S_3$ =「剛剛湊成一對」。由於輸出必須只是狀態的函數,成對這件事就必須被記進狀態裡。(a) 状態は 4 つで足ります。$S_1$ =「直前のビットは 0、まだ対になっていない」、$S_2$ =「直前のビットは 1、まだ対になっていない」、$S_3$ =「たった今対が成立した」とします。出力は状態だけの関数でなければならないので、対の検出そのものを状態の中に取り込む必要があります。

State狀態状態Meaning意義意味Output輸出出力on in=0in=0 時in=0 のときon in=1in=1 時in=1 のとき
S0reset, no history重置,沒有歷史リセット、履歴なし0S1S2
S1last bit 0上一個位元為 0直前のビットが 00S3S2
S2last bit 1上一個位元為 1直前のビットが 10S1S3
S3pair detected偵測到一對対を検出1S1 or S3S1 或 S3S1 または S3S2 or S3S2 或 S3S2 または S3

From S3 the machine must remember which bit ended the pair. Using the template in 9.3, S3 goes to S1 on a 0 and S3 on a 1 if the pair was of 1s — which is why a strict Moore version usually splits S3 into S3a ("pair of 0s") and S3b ("pair of 1s"), giving five states. This is the standard Moore penalty: more states, cleaner output.從 S3 出發時,機器必須記得是哪個位元結束了這一對。依照 9.3 的樣板,若這對是兩個 1,S3 遇 0 走到 S1、遇 1 留在 S3 — 這正是為什麼嚴格的 Moore 版本通常會把 S3 拆成 S3a(「一對 0」)與 S3b(「一對 1」),變成五個狀態。這就是 Moore 一貫的代價:狀態較多,輸出較乾淨。S3 からは、どちらのビットで対が成立したのかを機械が覚えていなければなりません。9.3 のテンプレートに従うと、対が 1 のペアだった場合、S3 は 0 で S1 へ、1 で S3 に留まります — 厳密な Moore 版では S3 を S3a(「0 の対」)と S3b(「1 の対」)に分け、5 状態にするのが普通である理由がこれです。これが Moore の定番の代償、状態は増えるが出力はきれいです。

(b) Tracing 0 0 1 1 1 0 0 0 1 with the 5-state Moore machine, where the output is asserted in the cycle after the pair completes:(b) 用 5 狀態的 Moore 機器追蹤 0 0 1 1 1 0 0 0 1,輸出在成對之後的那個週期成立:(b) 5 状態の Moore 機械で 0 0 1 1 1 0 0 0 1 を追います。出力は対が成立した次のサイクルでアサートされます。

bit位元ビット001110001
pair?成對?対?–yes是はいno否いいえyes是はいyes是はいno否いいえyes是はいyes是はいno否いいえ
Moore outMoore 輸出Moore の出力001011011

The Moore output is the "pair?" row delayed by one clock cycle, because the output is decoded from the registered state.Moore 的輸出就是「成對?」那一列延後一個時脈週期,因為輸出是從已暫存的狀態解碼出來的。Moore の出力は「対?」の行を1 クロック遅らせたものです。出力がレジスタに取り込まれた状態からデコードされるからです。

(c) A Mealy version needs only the two states S1 and S2 (last bit 0 / last bit 1) and asserts the output combinationally whenever the incoming bit equals the remembered one: out = (state == S1 && in == 0) || (state == S2 && in == 1). Fewer states, and the output appears one cycle earlier — but it follows in asynchronously within the cycle and will show every glitch on in.(c) Mealy 版本只需要 S1 與 S2 兩個狀態(上一個位元是 0/是 1),並在進來的位元與記住的那個相同時以組合邏輯令輸出成立:out = (state == S1 && in == 0) || (state == S2 && in == 1)。狀態較少,輸出也早一個週期出現 — 但它在週期之內非同步地跟隨 in,in 上的每一個突波都會照單全收。(c) Mealy 版に必要な状態は S1 と S2(直前のビットが 0 か 1 か)の 2 つだけで、入ってきたビットが記憶しているビットと等しいときに組合せ論理で出力をアサートします:out = (state == S1 && in == 0) || (state == S2 && in == 1)。状態は少なく、出力も 1 サイクル早く出ます — ただしサイクル内で in に非同期に追従するため、in のグリッチをすべて拾います。

Testbench note from the lecture: drive the input data stream on the falling edge of the clock. That guarantees the data is stable well before the rising edge the FSM samples on, so the simulation never races.投影片的測試平台提醒:輸入資料流請在時脈的下降邊緣驅動。這樣可以保證資料在 FSM 取樣的上升邊緣之前就已經穩定很久,模擬永遠不會發生競爭。講義のテストベンチに関する注意:入力データ列はクロックの立ち下がりエッジで与えてください。そうすれば FSM がサンプルする立ち上がりエッジのはるか前にデータが安定し、シミュレーションで競合が起きません。

10. Synthesis of Combinational Logic10. 組合邏輯的合成10. 組合せ論理の合成

10.1 What is synthesizable10.1 什麼可以合成10.1 合成できるもの

Synthesizable可合成合成可能
  • Netlist of Verilog primitives由 Verilog 原件構成的網表Verilog プリミティブのネットリスト
  • Combinational UDP組合邏輯 UDP組合せ論理の UDP
  • Continuous assignment連續賦值連続代入
  • Behavioral statement (always block)行為敘述(always 區塊)動作記述文(always ブロック)
  • Functionfunctionfunction
  • Task without delay or event control沒有延遲或事件控制的 task遅延やイベント制御を含まない task
  • Interconnected modules of any of the above以上任何項目互相連接而成的模組上記のいずれかを相互接続したモジュール
Not synthesizable — avoid不可合成 — 避免使用合成不可 — 使わないこと
  • Multiple event controls in one procedural block同一個程序區塊內有多個事件控制1 つの手続きブロック内に複数のイベント制御
  • Named event with edge-sensitive event control搭配邊緣敏感事件控制的具名事件エッジセンシティブなイベント制御を伴う名前付きイベント
  • Feedback loops (combinational loops)回授迴路(組合迴路)フィードバックループ(組合せループ)
  • PCA containing event or delay control含事件或延遲控制的 PCAイベント制御や遅延制御を含む PCA
  • fork…joinfork…joinfork…join
  • waitwaitwait
  • External disable statement外部的 disable 敘述外部からの disable 文
  • Procedural loops with timing controls含時序控制的程序式迴圈タイミング制御を含む手続き型ループ
  • Data-dependent loops與資料相依的迴圈データ依存のループ
  • Tasks with timing controls含時序控制的 taskタイミング制御を含む task
  • Sequential UDPs序向 UDP順序回路 UDP
  • initial, $system tasks, specify blocksinitial、$ 系統任務、specify 區塊initial、$ システムタスク、specify ブロック

10.2 Logic minimization10.2 邏輯最小化10.2 論理の最小化

The synthesis target is to minimize area, delay, or power. Two families of technique:合成的目標是把面積、延遲或功耗最小化。技術分成兩大家族:合成の目標は面積・遅延・消費電力のいずれかを最小化することです。手法は大きく 2 系統あります。

Two-level minimization兩層最小化2 レベル最小化

Sum-of-products (SOP) form — Karnaugh maps and Quine-McCluskey. Fast, but the resulting AND-OR network can be very wide.積項和(SOP)形式 — 卡諾圖與 Quine-McCluskey。速度快,但得到的 AND-OR 網路可能非常寬。積和(SOP)形式 — カルノー図と Quine-McCluskey 法。高速ですが、得られる AND-OR 網は非常に広くなりがちです。

Multi-level minimization — the five operations多層最小化 — 五種操作多レベル最小化 — 5 つの操作

Operation操作操作Before之前変換前After之後変換後
Decomposition分解分解 $F = abc + abd + a'c'd' + b'c'd'$$F = abc + abd + a'c'd' + b'c'd'$$F = abc + abd + a'c'd' + b'c'd'$ with $X = ab$, $Y = c+d$:  $F = XY + X'Y'$取 $X = ab$、$Y = c+d$:  $F = XY + X'Y'$$X = ab$、$Y = c+d$ とおくと:  $F = XY + X'Y'$
Extraction提取共用項抽出 $F = (a{+}b)cd + e$, $G = (a{+}b)e'$, $H = cde$$F = (a{+}b)cd + e$、$G = (a{+}b)e'$、$H = cde$$F = (a{+}b)cd + e$、$G = (a{+}b)e'$、$H = cde$ with $X = a+b$, $Y = cd$:  $F = XY + e$, $G = Xe'$, $H = Ye$取 $X = a+b$、$Y = cd$:  $F = XY + e$、$G = Xe'$、$H = Ye$$X = a+b$、$Y = cd$ とおくと:  $F = XY + e$、$G = Xe'$、$H = Ye$
Factoring因式分解因数分解 $F = ac + ad + bc + bd + e$$F = ac + ad + bc + bd + e$$F = ac + ad + bc + bd + e$ $F = (a+b)(c+d) + e$
Substitution代入代入 $F = a + b + c$, $G = a + b$ $F = G + c$
Elimination展開(反代入)消去(逆代入) $F = Ga + G'b$, $G = c + d$$F = Ga + G'b$、$G = c + d$$F = Ga + G'b$、$G = c + d$ $F = ac + ad + bc'd'$$F = ac + ad + bc'd'$$F = ac + ad + bc'd'$
Decomposition versus extraction分解與提取的差別分解と抽出の違い

Decomposition introduces new intermediate variables inside one function. Extraction finds a sub-expression shared by several functions and factors it out once. Elimination is the inverse of substitution — you would apply it to flatten logic when the extra level costs more delay than the shared gate saves area.分解是在一個函數內部引入新的中間變數。提取則是找出多個函數共用的子運算式,一次把它提出來。展開是代入的反操作 — 當多出來的那一層造成的延遲,比共用閘省下的面積還貴時,你就會用它來攤平邏輯。分解は1 つの関数の内部に新しい中間変数を導入します。抽出は複数の関数が共有する部分式を見つけ、一度だけ括り出します。消去は代入の逆操作で、余分な段が増やす遅延のほうが共有ゲートで節約できる面積より高くつくときに、論理を平坦化するために使います。

10.3 Unwanted latches — the number-one synthesis bug10.3 非預期的鎖存器 — 頭號合成 bug10.3 意図しないラッチ — 合成バグの第 1 位

The rule規則規則

All inputs to a behavior that implements combinational logic must be included in the event control expression — where "inputs" means operands on the RHS of assignments plus all control signals whose transitions affect the assignment. Failure to do so produces unwanted latches. Equally, a case or if that does not cover all possibilities is incompletely specified and also produces latches.凡是實作組合邏輯的 behavior,其所有輸入都必須列在事件控制運算式裡 — 這裡的「輸入」指的是賦值右式的運算元,加上所有轉態會影響該賦值的控制訊號。沒做到就會產生非預期的鎖存器。同樣地,沒有涵蓋所有可能性的 case 或 if 屬於規格不完整,一樣會產生鎖存器。組合せ論理を実装する behavior では、その入力をすべてイベント制御式に含めなければなりません — ここでいう「入力」とは、代入の右辺のオペランドと、その遷移が代入に影響するすべての制御信号のことです。これを怠ると意図しないラッチが生じます。同様に、すべての可能性を網羅していない case や if は記述が不完全であり、やはりラッチを生みます。

Bad — incomplete case list不好 — case 清單不完整悪い例 — case のリストが不完全

always @ (sel or a or b or c)
  case (sel)
    2'b00: y = a;
    2'b01: y = b;
    2'b10: y = c;
  endcase
// sel = 2'b11 not covered
//   -> y must hold -> LATCH

Good — completed with default好 — 用 default 補完良い例 — default で補完

always @ (sel or a or b or c)
  case (sel)
    2'b00:   y = a;
    2'b01:   y = b;
    2'b10:   y = c;
    default: y = 1'b0;
  endcase
// pure 4-to-1 mux, no storage

Bad — if-chain with no final else不好 — if 串沒有最後的 else悪い例 — if 連鎖に最後の else がない

always @ (a or b or sel)
  if (sel == 2'b00)      y = a;
  else if (sel == 2'b01) y = b;
  else if (sel == 2'b10) y = a & b;
// the last statement should be "else"

Good好良い例

always @ (a or b or sel)
  if (sel == 2'b00)      y = a;
  else if (sel == 2'b01) y = b;
  else                   y = a & b;
D-LATCHD 鎖存器D ラッチ (inferred!)(被推論出來的!)(推論された!) D G Q next value新的值次の値 "case matched"「有分支符合」「どれかの分岐が一致」 y feedback path holds the old value when no branch matches沒有分支符合時,回授路徑保住舊值どの分岐も一致しないとき、帰還路が古い値を保持する
Generic synthesis result of an incompletely-specified conditional: a transparent latch whose gate is "some branch matched". The feedback path is the storage — and it is uncontrollable by scan test.規格不完整的條件式,其通用的合成結果:一個閘控訊號為「有某個分支符合」的透通鎖存器。回授路徑就是儲存元件 — 而它無法被掃描測試控制。記述が不完全な条件文の一般的な合成結果:ゲートが「いずれかの分岐が一致」である透過ラッチです。帰還路そのものが記憶素子であり、スキャンテストでは制御できません。

10.4 Combinational loops10.4 組合迴路10.4 組合せループ

A case or if that is complete but assigns the variable to itself in a level-sensitive behavior synthesizes to a mux with feedback. Unlike the latch above, this one cannot be synthesized to gates at all.一個確實完整、但在準位敏感的 behavior 裡把變數指派給它自己的 case 或 if,會合成出帶回授的多工器。與上面的鎖存器不同,這一個根本無法合成成閘。記述としては完全でも、レベルセンシティブな behavior の中で変数を自分自身に代入する case や if は、帰還付きのマルチプレクサに合成されます。上のラッチと違い、こちらはそもそもゲートに合成できません。

always @ (sel or a or b or c)
  case (sel)
    2'b00:   y = a;
    2'b01:   y = b;
    2'b10:   y = c;
    default: y = y;    // explicit self-assignment -> combinational loop
  endcase
The related rule相關的規則関連する規則

The target of an assignment must not be an operand on the RHS of any assignment in the same combinational behavior — that produces an infinite loop in simulation and an unsynthesizable structure in hardware. Continuous assignments carry the same restriction: no structural feedback.賦值的目標,不可以同時是同一個組合 behavior 中任何賦值右式的運算元 — 那會在模擬中造成無窮迴圈,在硬體上則是無法合成的結構。連續賦值也受同樣的限制:不可以有結構性回授。代入の対象を、同じ組合せ behavior 内のどの代入の右辺のオペランドにもしてはいけません — シミュレーションでは無限ループになり、ハードウェアでは合成不能な構造になります。連続代入にも同じ制限があります:構造的な帰還は不可です。

10.5 Priority structure versus multiplexer10.5 優先權結構與多工器10.5 優先順位構造とマルチプレクサ

The determining question決定性的一問決め手となる問い

Are the branch conditions mutually exclusive?
Yes → the tool synthesizes a multiplexer (all branches equal priority, balanced delay).
No → the tool synthesizes a priority structure (a chain, delay grows with depth).
各分支的條件是否互斥?
是 → 工具合成出多工器(所有分支優先權相同,延遲平衡)。
否 → 工具合成出優先權結構(一條鏈,延遲隨深度增加)。
分岐の条件は互いに排他的ですか。
はい → ツールはマルチプレクサを合成します(全分岐が同じ優先度、遅延は均等)。
いいえ → ツールは優先順位構造を合成します(直列の連鎖で、深さとともに遅延が増えます)。

This holds for both case and if. It is not about which keyword you use — a common misconception. An if…else if chain with mutually exclusive conditions synthesizes to a mux; a case whose items overlap (possible with casex/casez) synthesizes to a priority structure.這對 case 與 if 都成立。重點不在你用了哪個關鍵字 — 這是常見的誤解。條件互斥的 if…else if 串會合成出多工器;項目重疊的 case(用 casex/casez 時有可能)則會合成出優先權結構。これは case にも if にも当てはまります。どちらのキーワードを使ったかは関係ありません — よくある誤解です。条件が互いに排他的な if…else if 連鎖はマルチプレクサに合成され、項目が重なる case(casex/casez ではあり得ます)は優先順位構造に合成されます。

8-to-3 encoder — no priority8 對 3 編碼器 — 無優先權8 対 3 エンコーダ — 優先順位なし

always @ (d)
  case (d)
    8'b0000_0001: code = 3'd0;
    8'b0000_0010: code = 3'd1;
    8'b0000_0100: code = 3'd2;
    8'b0000_1000: code = 3'd3;
    8'b0001_0000: code = 3'd4;
    8'b0010_0000: code = 3'd5;
    8'b0100_0000: code = 3'd6;
    8'b1000_0000: code = 3'd7;
    default:      code = 3'bx;
  endcase
// items mutually exclusive -> MUX

8-to-3 priority encoder8 對 3 優先權編碼器8 対 3 プライオリティエンコーダ

always @ (d)
  casex (d)
    8'b1xxx_xxxx: code = 3'd7;
    8'b01xx_xxxx: code = 3'd6;
    8'b001x_xxxx: code = 3'd5;
    8'b0001_xxxx: code = 3'd4;
    8'b0000_1xxx: code = 3'd3;
    8'b0000_01xx: code = 3'd2;
    8'b0000_001x: code = 3'd1;
    8'b0000_0001: code = 3'd0;
    default:      code = 3'bx;
  endcase
// items overlap -> PRIORITY chain

The equivalent if forms produce identical hardware:等價的 if 寫法會產生完全相同的硬體:等価な if の書き方でも、まったく同じハードウェアになります。

if      (d[7]) code = 3'd7;
else if (d[6]) code = 3'd6;
else if (d[5]) code = 3'd5;
// ... a priority chain, same as the casex above
Timing consequence時序上的後果タイミングへの影響

A priority chain of $N$ conditions has delay $O(N)$; a mux tree has delay $O(\log N)$. When STA reports a critical path through a long else if chain and the conditions are in fact mutually exclusive, rewriting as a case is a free timing win.$N$ 個條件的優先權鏈延遲為 $O(N)$;多工器樹的延遲則是 $O(\log N)$。當 STA 回報關鍵路徑穿過一長串 else if,而那些條件其實是互斥的,把它改寫成 case 就是白撿的時序改善。$N$ 個の条件からなる優先順位チェーンの遅延は $O(N)$、マルチプレクサツリーの遅延は $O(\log N)$ です。STA が長い else if 連鎖を通るクリティカルパスを報告し、しかも条件が実は互いに排他的なら、case に書き換えるだけでタイミングがただで改善します。

10.6 Buses, buffers, and tri-state logic10.6 匯流排、緩衝器與三態邏輯10.6 バス・バッファ・トライステート論理

Four implementation concerns from the lecture: tri-state buffers, bidirectional buses, bus loading, and tri-state outputs with don't-cares.投影片提出四個實作上的考量:三態緩衝器、雙向匯流排、匯流排負載,以及帶 don't-care 的三態輸出。講義が挙げる実装上の論点は 4 つ:トライステートバッファ、双方向バス、バスの負荷、そしてドントケアを伴うトライステート出力です。

Tri-state buffer onto a shared bus接到共用匯流排上的三態緩衝器共有バスに接続するトライステートバッファ

assign bus = en_a ? data_a : 8'bz;
assign bus = en_b ? data_b : 8'bz;
// bus must be a net (wire/tri);
//   en_a and en_b must never be 1 together

Bidirectional bus (inout)雙向匯流排(inout)双方向バス(inout)

inout [7:0] dbus;
assign dbus     = wr_en ? data_out : 8'bz;
assign data_in  = dbus;
// one net, two directions, one enable
Don't-care versus high impedance in a conditional條件式中的 don't-care 與高阻抗条件文におけるドントケアとハイインピーダンス

Assigning x in a default branch means "I don't care" — the tool is free to pick whatever minimizes logic. Assigning z means "drive nothing" — the tool must build a tri-state device. The two produce entirely different hardware from nearly identical source, which is why the lecture contrasts alu_with_z1 and alu_with_z2.在 default 分支賦值 x 表示「我不在乎」— 工具可以自由挑選最能簡化邏輯的值。賦值 z 則表示「什麼都不要驅動」— 工具必須做出一個三態元件。兩者的原始碼幾乎相同,硬體卻完全不同,這正是投影片要拿 alu_with_z1 和 alu_with_z2 對照的原因。default 分岐で x を代入するのは「どちらでもよい」という意味で、ツールは論理が最小になる値を自由に選べます。z を代入するのは「何も駆動しない」という意味で、ツールはトライステート素子を作らなければなりません。ソースはほとんど同じなのにハードウェアはまったく別物になります。講義が alu_with_z1 と alu_with_z2 を対比する理由がこれです。

10.7 Resource sharing10.7 資源共用10.7 リソース共有

Resource sharing should be done before RTL coding — it is an architectural decision, not something to hope the tool finds.資源共用應該在寫 RTL 之前就決定 — 這是架構決策,不是指望工具自己找出來的事。リソース共有は RTL を書く前に決めるべきです — アーキテクチャ上の判断であり、ツールが見つけてくれるのを期待するものではありません。

Two adders — costly兩個加法器 — 昂貴加算器 2 個 — 高価

always @ (*)
  if (sel) y_out = accum + data_a;
  else     y_out = data_b + data_a;
// the tool may infer TWO adders

One adder — shared一個加法器 — 共用加算器 1 個 — 共有

wire [N-1:0] mux_out = sel ? accum : data_b;
assign y_out = mux_out + data_a;
// mux first, then ONE adder
MUX多工器MUX selselsel Adder加法器加算器 accumaccumaccum 1 data_bdata_bdata_b 0 data_adata_adata_a y_outy_outy_out One adder instead of two — a mux is far cheaper than an adder用一個加法器取代兩個 — 多工器比加法器便宜太多了加算器を 2 個から 1 個へ — マルチプレクサは加算器よりはるかに安い
Resource sharing: move the selection before the expensive operator.資源共用:把選擇動作移到昂貴的運算子之前。リソース共有:選択を高価な演算子の前に移す。
Practice 11 — Latch hunting練習 11 — 找出鎖存器演習 11 — ラッチ探し

Problem: For each fragment, state whether synthesis infers a latch, a flip-flop, or pure combinational logic, and why.題目:對每一段程式碼,判斷合成會推論出鎖存器、正反器,還是純組合邏輯,並說明理由。問題:各コード片について、合成がラッチ・フリップフロップ・純粋な組合せ論理のどれを推論するかを、理由とともに答えなさい。

// (a)                         // (b)
always @ (a or b)              always @ (a)
  begin                          begin
    y = a & b;                     y = a & b;
    z = a | b;                     z = a | b;
  end                            end

// (c)                         // (d)
always @ (posedge clk)         always @ (sel or a or b)
  q <= d;                        if (sel) y = a;
                                 else     y = b;

// (e)                         // (f)
always @ (en or d)             always @ (*)
  if (en) q = d;                 case (op)
                                   2'b00: y = a + b;
                                   2'b01: y = a - b;
                                   2'b10: y = a & b;
                                 endcase
Click to reveal solution點擊看解答クリックで解答を表示
  • (a) Combinational. Sensitivity list complete, both targets assigned unconditionally. Two gates.(a) 組合邏輯。敏感度列表完整,兩個目標都被無條件賦值。就是兩個閘。(a) 組合せ論理。センシティビティリストは完全で、両方の対象が無条件に代入されています。ゲート 2 個です。
  • (b) Latch — but a subtle one. b is missing from the sensitivity list. In simulation, y and z fail to update when b changes, so the behavior looks like storage. Most modern synthesis tools ignore an incomplete sensitivity list and synthesize pure combinational logic anyway — which means simulation and synthesis disagree. That mismatch is worse than either outcome alone. Use always @(*).(b) 鎖存器 — 但很微妙。b 沒有列在敏感度列表裡。在模擬中,b 改變時 y 與 z 不會更新,所以這個 behavior 看起來像是有儲存。但大多數現代合成工具會忽略不完整的敏感度列表,照樣合成出純組合邏輯 — 也就是模擬與合成互相矛盾。這種不一致比其中任何一種結果單獨出現都更糟。請用 always @(*)。(b) ラッチ — ただし微妙な例。b がセンシティビティリストにありません。シミュレーションでは b が変化しても y と z が更新されないため、記憶があるように見えます。しかし現代の合成ツールの多くは不完全なセンシティビティリストを無視して純粋な組合せ論理を合成します — つまりシミュレーションと合成が食い違うのです。この不一致はどちらか一方の結果よりたちが悪いものです。always @(*) を使いましょう。
  • (c) Flip-flop. Edge-sensitive event control plus non-blocking assignment — the canonical D flip-flop.(c) 正反器。邊緣敏感的事件控制加上非阻擋式賦值 — 標準的 D 正反器。(c) フリップフロップ。エッジセンシティブなイベント制御とノンブロッキング代入 — 定番の D フリップフロップです。
  • (d) Combinational. The if has a matching else, so y is assigned on every path. A 2-to-1 mux.(d) 組合邏輯。這個 if 有配對的 else,所以 y 在每條路徑上都被賦值。一個 2 對 1 多工器。(d) 組合せ論理。この if には対応する else があるので、y はどの経路でも代入されます。2 対 1 マルチプレクサです。
  • (e) Latch — intentionally. No else, so when en is 0, q must hold. This is the correct way to describe a transparent latch. It is only a bug when you did not mean it.(e) 鎖存器 — 而且是刻意的。沒有 else,所以 en 為 0 時 q 必須保住。這正是描述透通鎖存器的正確方式。只有在你並非有意如此時,它才是 bug。(e) ラッチ — ただし意図的なもの。else がないので en が 0 のとき q は保持されます。透過ラッチを記述する正しい方法です。意図していなかった場合にだけバグになります。
  • (f) Latch. op = 2'b11 is uncovered, so y holds. Add default: y = 'bx; (don't-care, cheapest) or default: y = 0; (defined, safer).(f) 鎖存器。op = 2'b11 沒有被涵蓋,所以 y 會保住。加上 default: y = 'bx;(don't-care,最省)或 default: y = 0;(有明確值,較安全)。(f) ラッチ。op = 2'b11 が網羅されていないので y は保持されます。default: y = 'bx;(ドントケア、最も安価)か default: y = 0;(値が定まり安全)を加えてください。

The diagnostic question: "Is there any reachable input combination for which this variable is not assigned?" If yes, you get a latch. That single question resolves every case above.診斷用的一問:「有沒有任何可達的輸入組合,會讓這個變數沒被賦值?」如果有,你就會得到鎖存器。這一個問題就能解決上面全部的情況。診断のための問い:「この変数が代入されない到達可能な入力の組合せはあるか?」あるならラッチができます。この 1 つの問いで上のすべての場合が判定できます。

11. Synthesis of Sequential Logic11. 序向邏輯的合成11. 順序論理の合成

11.1 When a flip-flop is inferred11.1 何時會推論出正反器11.1 フリップフロップが推論される条件

The inference rule推論規則推論の規則

A register variable in a behavior is synthesized as a flip-flop if it is (1) aligned with clock behavior — i.e. the behavior is edge-sensitive to a clock — and (2) assigned a value by some assignment in that behavior.一個 behavior 內的 register 變數,若同時滿足 (1)與時脈行為對齊 — 也就是該 behavior 對某個時脈是邊緣敏感的 — 以及 (2) 在該 behavior 內被某個賦值指派了值,就會被合成成正反器。behavior 内のレジスタ変数は、(1)クロック動作と整合していること — すなわちその behavior があるクロックにエッジセンシティブであること — と、(2) その behavior 内のいずれかの代入で値を与えられていることの両方を満たすとき、フリップフロップとして合成されます。

always @ (posedge clk)
  case ({set1, set2})
    2'b00:   data_a <= 1'b0;
    2'b01:   data_a <= 1'b1;
    2'b10:   data_a <= 1'b1;
    default: data_a <= 1'b1;
  endcase
// synthesizes to: combinational decode -> D input of ONE flip-flop

The hardware is a mux (or decode logic) feeding a D flip-flop. Note that the mux collapses: since three of the four cases give 1, the tool reduces the decode to a single gate.硬體是一個多工器(或解碼邏輯)餵進一個 D 正反器。注意這個多工器會塌縮:因為四種情況中有三種都給 1,工具會把解碼縮成單一個閘。ハードウェアはマルチプレクサ(あるいはデコード論理)が D フリップフロップに入る形です。ただしこのマルチプレクサは潰れます。4 つのケースのうち 3 つが 1 を与えるため、ツールはデコードを 1 つのゲートにまとめます。

11.2 Synchronous versus asynchronous reset11.2 同步重置與非同步重置11.2 同期リセットと非同期リセット

Asynchronous reset (active high)非同步重置(高態有效)非同期リセット(正論理)

always @ (posedge clk or posedge reset)
  if (reset) data_out <= 4'd0;   // first stmt
  else       data_out <= data_in; // last = sync

Reset appears in the sensitivity list. Reset pulse width may be arbitrary — it takes effect immediately.重置訊號出現在敏感度列表裡。重置脈衝的寬度可以任意 — 它會立刻生效。リセットがセンシティビティリストに入ります。リセットパルスの幅は任意でかまいません — 直ちに効きます。

Synchronous reset (active high)同步重置(高態有效)同期リセット(正論理)

always @ (posedge clk)
  if (reset) data_out <= 4'd0;
  else       data_out <= data_in;

Reset is not in the sensitivity list. Caution: the reset pulse must be wider than one clock period, or it may be missed entirely.重置訊號不在敏感度列表裡。注意:重置脈衝必須比一個時脈週期還寬,否則可能整個被漏掉。リセットはセンシティビティリストに入りません。注意:リセットパルスは1 クロック周期より広くなければならず、さもないと丸ごと見逃されることがあります。

ASYNCHRONOUS RESET非同步重置非同期リセット SYNCHRONOUS RESET同步重置同期リセット clock時脈クロックreset重置リセット data_indata_indata_indata_outdata_outdata_out clock時脈クロックreset重置リセット data_indata_indata_indata_outdata_outdata_out 4'd8 4'd8 4'dx4'dx4'dx 4'd0 4'd8 4'dx4'dx4'dx 4'd0 4'd8 narrow pulse,窄脈衝,狭いパルス、 no clock edge inside內部沒有時脈邊緣中にクロックエッジがない must span a clock edge必須跨過一個時脈邊緣クロックエッジをまたぐ必要がある data_out drops the instant reset asserts重置一成立,data_out 立刻掉下來リセットが立った瞬間に data_out が落ちる data_out waits for the next rising edgedata_out 要等到下一個上升邊緣data_out は次の立ち上がりエッジまで待つ
Asynchronous reset drives the output low the instant it asserts; synchronous reset waits for the next rising edge, so a reset pulse narrower than one period can be missed entirely.非同步重置一成立就把輸出拉低;同步重置要等下一個上升邊緣,所以比一個週期還窄的重置脈衝可能整個被漏掉。非同期リセットはアサートされた瞬間に出力を下げます。同期リセットは次の立ち上がりエッジを待つため、1 周期より狭いリセットパルスは丸ごと見逃されることがあります。
Structural requirement for asynchronous control非同步控制的結構性要求非同期制御に対する構造上の要求

When the event control expression is sensitive to the edge of more than one signal: an if statement must be the first statement in the behavior; the synchronizing signal (the clock) is not tested explicitly; and the last branch must describe the synchronous activity. Asynchronous control signals therefore automatically have priority over the clock — which is what the flip-flop's physical set/reset pins do. Also: no signal may be qualified by both posedge and negedge, and there may be only one clock edge in the list.當事件控制運算式對一個以上訊號的邊緣敏感時:if 敘述必須是 behavior 的第一個敘述;同步訊號(時脈)不可被顯式測試;而且最後一個分支必須描述同步行為。因此非同步控制訊號會自動取得高於時脈的優先權 — 這正是正反器實體 set/reset 接腳的作用。此外:任何訊號都不可以同時被 posedge 與 negedge 修飾,而且列表中只能有一個時脈邊緣。イベント制御式が複数の信号のエッジに反応する場合:if 文は behavior の最初の文でなければならず、同期信号(クロック)を明示的に判定してはならず、最後の分岐が同期動作を記述しなければなりません。その結果、非同期制御信号は自動的にクロックより高い優先度を持ちます — フリップフロップの物理的な set/reset ピンの働きそのものです。さらに、同じ信号を posedge と negedge の両方で修飾することはできず、リストに入れられるクロックエッジは1 つだけです。

11.3 Shift registers, counters, and loadable registers11.3 移位暫存器、計數器與可載入暫存器11.3 シフトレジスタ・カウンタ・ロード可能なレジスタ

Plain shift register單純的移位暫存器単純なシフトレジスタ

always @ (posedge clk)
  data_out <= {data_out[6:0], serial_in};
// always catches the input data

Shift register with judgement (enable)帶判斷(enable)的移位暫存器判定(イネーブル)付きのシフトレジスタ

always @ (posedge clk)
  if (shift_en)
    data_out <= {data_out[6:0], serial_in};
// no else -> holds; this is a FF with
//   enable, NOT a latch (it is clocked)
Why a missing else is safe here but not in Section 10.3為什麼這裡少了 else 沒問題,10.3 節卻不行ここでは else がなくても安全で、10.3 節ではそうでない理由

Inside always @(posedge clk), a missing else means "keep the current value", which a flip-flop does natively — the tool implements it with a clock-enable pin or a feedback mux. Inside a level-sensitive combinational behavior, the same omission has nowhere to store the value, so a latch must be created. Same code, opposite verdict, because of the sensitivity list.在 always @(posedge clk) 裡少了 else 代表「保持目前的值」,而正反器本來就會這麼做 — 工具會用 clock-enable 接腳或一個回授多工器實作它。但在準位敏感的組合 behavior 裡,同樣的省略沒有任何地方能存這個值,所以必須造出一個鎖存器。同樣的程式碼,相反的判決,差別只在敏感度列表。always @(posedge clk) の中で else が欠けているのは「現在の値を保つ」という意味であり、フリップフロップは本来それをする素子です — ツールはクロックイネーブル端子か帰還マルチプレクサで実装します。ところがレベルセンシティブな組合せ behavior では、同じ省略でも値を置く場所がないため、ラッチを作らざるを得ません。同じコードでも判定が逆になるのは、センシティビティリストのせいです。

Barrel shifter with load可載入的桶形移位器ロード機能付きバレルシフタ

always @ (posedge clk)
  if (load)      q <= data_in;
  else if (sl)   q <= {q[6:0], q[7]};   // rotate left
  else if (sr)   q <= {q[0], q[7:1]};   // rotate right

Ring counter環形計數器リングカウンタ

always @ (posedge clk or posedge rst)
  if (rst) q <= 4'b0001;
  else     q <= {q[2:0], q[3]};
// one-hot sequencer; 4 states
Ripple counter versus synchronous counter漣波計數器與同步計數器リプルカウンタと同期カウンタ

A ripple counter clocks each stage from the previous stage's output. It is small, but the stages do not change together, the tool cannot analyse it with STA (each stage is its own clock domain), and it cannot be scan-tested normally. Prefer a synchronous counter — all flip-flops on the same clock, with combinational increment logic — in anything you intend to tape out.漣波計數器是拿前一級的輸出去打下一級的時脈。它很小,但各級不會同時改變,工具也無法用 STA 分析它(每一級自成一個時脈域),而且沒辦法正常做掃描測試。任何你打算下線的設計,都該優先選同步計數器 — 所有正反器接同一個時脈,再配上組合的遞增邏輯。リプルカウンタは前段の出力で次段のクロックを叩きます。小さくはありますが、各段が同時に変化せず、ツールは STA で解析できず(各段が独自のクロックドメインになるため)、通常のスキャンテストもできません。テープアウトするつもりの設計では同期カウンタ — すべてのフリップフロップを同じクロックにつなぎ、組合せのインクリメント論理を添えたもの — を選んでください。

11.4 Pipelining11.4 管線化11.4 パイプライン化

A 16-bit adder built as two 8-bit adders in series has a critical path through both. Splitting it with a register stage halves the path.把 16 位元加法器做成兩個 8 位元加法器串接,關鍵路徑就會穿過兩者。插入一級暫存器把它切開,路徑長度就少一半。16 ビット加算器を 8 ビット加算器 2 段の直列で作ると、クリティカルパスは両方を貫きます。レジスタ段を挟んで分割すれば、経路長は半分になります。

Before: one long combinational path之前:一條長長的組合路徑変更前:1 本の長い組合せ経路 Adder LSB低位元加法器下位加算器 Adder MSB高位元加法器上位加算器 carry進位キャリー critical path = 2 x T(add8)關鍵路徑 = 2 x T(add8)クリティカルパス = 2 x T(add8) After: pipelined — registers split the path之後:管線化 — 暫存器把路徑切開変更後:パイプライン化 — レジスタが経路を分割 Adder LSB低位元加法器下位加算器 FFFFFF Adder MSB高位元加法器上位加算器 FFFFFF T(add8)T(add8)T(add8) T(add8)T(add8)T(add8) ~2x clock rate,時脈率約兩倍,クロック速度は約 2 倍、 +1 cycle latency延遲多一個週期レイテンシは 1 サイクル増
Pipelining the 16-bit adder. Throughput roughly doubles; latency grows by one clock cycle. The LSB operands must also be delayed by one stage so that both halves meet correctly — the "hardware reuse" the slide refers to.把 16 位元加法器管線化。吞吐量大約加倍;延遲多一個時脈週期。低位元的運算元也必須延後一級,兩半才會正確會合 — 這就是投影片說的「硬體重用」。16 ビット加算器のパイプライン化。スループットはおよそ 2 倍になり、レイテンシは 1 クロック増えます。下位側のオペランドも 1 段遅らせないと両半分が正しく合流しません — スライドのいう「ハードウェアの再利用」がこれです。
module add16_pipe (sum, cout, a, b, cin, clk);
  output [15:0] sum;  output cout;
  input  [15:0] a, b; input cin, clk;

  wire [7:0]  sum_lo;  wire c_mid;
  reg  [7:0]  sum_lo_r, a_hi_r, b_hi_r;
  reg         c_mid_r;
  wire [7:0]  sum_hi;

  add8 U_LO (.s(sum_lo), .co(c_mid), .a(a[7:0]), .b(b[7:0]), .ci(cin));

  always @ (posedge clk) begin           // pipeline registers
    sum_lo_r <= sum_lo;
    c_mid_r  <= c_mid;
    a_hi_r   <= a[15:8];                 // MSB operands must be delayed too
    b_hi_r   <= b[15:8];
  end

  add8 U_HI (.s(sum_hi), .co(cout), .a(a_hi_r), .b(b_hi_r), .ci(c_mid_r));

  assign sum = {sum_hi, sum_lo_r};
endmodule
The mistake everyone makes once每個人都會犯一次的錯誰もが一度はやる間違い

Forgetting to register a[15:8] and b[15:8]. The MSB adder would then see cycle-$n$ operands with a cycle-$(n{-}1)$ carry, and the result is wrong for every input change. Every pipeline stage must delay all signals that cross it, not just the ones on the critical path.忘了把 a[15:8] 與 b[15:8] 也暫存起來。這樣高位元加法器看到的是第 $n$ 週期的運算元配上第 $(n{-}1)$ 週期的進位,只要輸入一變結果就錯。每一級管線都必須把所有穿越它的訊號延後,不能只顧關鍵路徑上的那些。a[15:8] と b[15:8] をレジスタに通し忘れることです。そうすると上位側の加算器はサイクル $n$ のオペランドにサイクル $(n{-}1)$ のキャリーを組み合わせて見ることになり、入力が変わるたびに結果が誤ります。パイプラインの各段は、クリティカルパス上の信号だけでなく、そこを横切るすべての信号を遅らせなければなりません。

Practice 12 — Reset styles and their consequences練習 12 — 重置風格及其後果演習 12 — リセットのスタイルとその帰結

Problem: (a) Rewrite the asynchronous-reset flip-flop so the reset is active low. (b) Why can a synchronous reset pulse be missed but an asynchronous one cannot? (c) Give one advantage of each style. (d) What is wrong with always @ (posedge clk or reset)?題目:(a) 把非同步重置的正反器改寫成低態有效重置。(b) 為什麼同步重置脈衝可能被漏掉,非同步的卻不會?(c) 各舉出一項兩種風格的優點。(d) always @ (posedge clk or reset) 有什麼問題?問題:(a) 非同期リセットのフリップフロップを、リセットが負論理になるよう書き直しなさい。(b) 同期リセットのパルスは見逃されうるのに、非同期リセットではそうならないのはなぜですか。(c) それぞれのスタイルの利点を 1 つずつ挙げなさい。(d) always @ (posedge clk or reset) の何が問題ですか。

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

(a) Active-low reset means the reset action happens at value 0, so the sensitivity list must watch the falling edge:(a) 低態有效代表重置動作發生在值為 0 的時候,所以敏感度列表要盯的是下降邊緣:(a) 負論理とはリセット動作が値 0 のときに起こるという意味なので、センシティビティリストは立ち下がりエッジを見る必要があります。

always @ (posedge clk or negedge rst_n)
  if (!rst_n) q <= 1'b0;
  else        q <= d;

The edge qualifier and the polarity of the test must agree: negedge rst_n pairs with if (!rst_n). Mismatching them is a synthesis error, not just a style problem.邊緣修飾子與測試的極性必須一致:negedge rst_n 要配 if (!rst_n)。兩者不搭是合成錯誤,不只是寫法風格的問題。エッジ修飾子と判定の極性は一致していなければなりません:negedge rst_n には if (!rst_n) が対応します。食い違えば合成エラーであり、単なるスタイルの問題ではありません。

(b) A synchronous reset is only sampled at the clock edge, so a pulse that rises and falls entirely between two edges is never seen. An asynchronous reset is in the sensitivity list, so its own edge wakes the behavior immediately — independent of the clock. Hence the lecture's caution that a synchronous reset pulse must be wider than one clock period.(b) 同步重置只在時脈邊緣被取樣,所以一個完全落在兩個邊緣之間、起了又落的脈衝根本不會被看到。非同步重置在敏感度列表裡,它自己的邊緣會立刻喚醒該 behavior — 與時脈無關。這就是投影片提醒「同步重置脈衝必須比一個時脈週期還寬」的原因。(b) 同期リセットはクロックエッジでのみサンプルされるため、2 つのエッジのあいだで立って落ちてしまうパルスはまったく見えません。非同期リセットはセンシティビティリストにあるので、自身のエッジが即座に behavior を起動します — クロックとは無関係です。講義が「同期リセットのパルスは 1 クロック周期より広くすること」と注意する理由がこれです。

(c) Asynchronous: works even when the clock is not running (essential at power-up, and for low-power modes where the clock is gated off); uses the flip-flop's dedicated reset pin, so it costs no extra logic in the datapath.
Synchronous: every path is a normal clocked path, so STA covers it and there is no reset-recovery/removal timing to close; it is also immune to glitches on the reset line, which an asynchronous reset would propagate straight into the register.
(c) 非同步:即使時脈沒在跑也有效(上電時必要,時脈被閘控關掉的低功耗模式也是);它用的是正反器專屬的重置接腳,所以不會在資料路徑上多花任何邏輯。
同步:每條路徑都是一般的時脈路徑,STA 涵蓋得到,也不必去收斂 reset recovery/removal 的時序;而且它對重置線上的突波免疫,那種突波在非同步重置下會直接打進暫存器。
(c) 非同期:クロックが動いていなくても効きます(電源投入時に必須で、クロックをゲーティングする低消費電力モードでも同様)。フリップフロップ専用のリセットピンを使うので、データパスに余分な論理を足しません。
同期:どの経路も普通のクロック同期経路なので STA でカバーでき、リセットのリカバリ/リムーバル・タイミングを閉じる必要もありません。さらにリセット線上のグリッチに強く、非同期リセットならそのままレジスタに伝わってしまうものを遮断できます。

(d) reset appears without an edge qualifier while clk has one. Mixing edge-qualified and non-qualified signals in the same event control is illegal for synthesis: the tool cannot tell whether you mean an asynchronous reset or a level-sensitive dependency. Every asynchronous control in the list must carry its own posedge/negedge, and there must be exactly one clock edge.(d) reset 沒有邊緣修飾子,clk 卻有。在同一個事件控制裡混用有邊緣修飾與沒有的訊號,對合成而言是不合法的:工具無法判斷你指的是非同步重置,還是準位相依。列表中每一個非同步控制都必須帶自己的 posedge/negedge,而且只能有恰好一個時脈邊緣。(d) clk にはエッジ修飾子があるのに reset にはありません。同じイベント制御の中でエッジ修飾のある信号とない信号を混ぜるのは合成上不正です。非同期リセットのつもりなのか、レベル依存のつもりなのかをツールが判断できないからです。リスト中の非同期制御にはそれぞれ posedge/negedge を付け、クロックエッジはちょうど 1 つにしてください。

12. Synthesis of Language Constructs12. 語言結構的合成12. 言語構文の合成

12.1 Nets and register variables12.1 net 與 register 變數12.1 ネットとレジスタ変数

Construct語法結構構文Synthesis behavior合成行為合成時の扱い
Nets declared as input/output ports宣告為 input/output 埠的 netinput/output ポートとして宣言されたネットretained會保留保持される
Internal nets內部 net内部ネットmay be eliminated by logic optimization; the tool offers directives to force one to survive可能被邏輯最佳化消掉;工具提供指令可以強制保留某一條論理最適化で消されることがある。特定のネットを残すよう強制するディレクティブがツールにある
wand, worwand、worwand、worimplemented as logic gates會實作成邏輯閘論理ゲートとして実装される
integerintegerinteger32-bit register by default; the size may be reduced during optimization. Declare constants with a fixed size to keep the hardware small.預設是 32 位元的 register;最佳化過程中位元數可能被縮小。請用固定位元數宣告常數,讓硬體維持精簡。既定では 32 ビットのレジスタ。最適化の過程でビット幅が縮められることがある。ハードウェアを小さく保つため、定数はサイズを明示して宣言すること。
real, time, realtimereal、time、realtimereal、time、realtimenot supported不支援非対応

Where x and z are permittedx 與 z 允許出現在哪裡x と z が許される場所

Value值値Allowable uses in synthesizable code可合成程式碼中允許的用法合成可能なコードでの許容される用法
xcasex; casez; the default of a conditional (if, case, ?:) — where it means "don't care"; assigned to a wire or reg by a UDPcasex;casez;條件式(if、case、?:)的 default — 此時代表「don't care」;由 UDP 指派給 wire 或 regcasex、casez、条件文(if、case、?:)の default(この場合は「ドントケア」の意味)、UDP が wire や reg に与える値
zonly in constructs implying a tri-state output — as the default outcome of a conditional statement只能出現在隱含三態輸出的結構中 — 作為條件敘述的預設結果トライステート出力を含意する構文でのみ — 条件文の既定の結果として

12.2 Operators12.2 運算子12.2 演算子

Operator class運算子類別演算子の分類Implementation實作方式実装のされ方
Adder / subtractor加法器/減法器加算器/減算器ripple-carry or carry-look-ahead, chosen by the tool from the timing constraint漣波進位或超前進位,由工具依時序約束自行選擇リップルキャリーかキャリー先見か、タイミング制約に応じてツールが選ぶ
* and /* 與 /* と /may not be implemented efficiently as combinational logic. Special cases: use shift when one operand is a power of 2; use a part-select for % when the divisor is a power of 2當成組合邏輯實作時未必有效率。特例:其中一個運算元是 2 的冪次時改用位移;除數是 2 的冪次時,% 可用部分選取取代組合せ論理として効率よく実装できるとは限らない。特例:一方のオペランドが 2 のべき乗ならシフトを使い、除数が 2 のべき乗なら % は部分選択で置き換える
Shift << >>位移 << >>シフト << >>the shift amount, or the number of bits storing it, must be a constant. Inside a behavior they become shift registers and muxes built from low-level gates — not necessarily mapped to a shift-register library cell位移量,或存放位移量的位元數,必須是常數。寫在 behavior 內時會變成由低階閘組成的移位暫存器與多工器 — 未必會映射到函式庫裡的移位暫存器單元シフト量、またはそれを保持するビット数は定数でなければならない。behavior の中では低レベルのゲートから作られたシフトレジスタとマルチプレクサになり、ライブラリのシフトレジスタセルに割り当てられるとは限らない
Relational < > <= >=關係 < > <= >=関係 < > <= >=combinational logic, often an adder/subtractor: $A \ge B$ iff the sign bit of $A-B$ is 0組合邏輯,通常是一個加法器/減法器:$A \ge B$ 的充要條件是 $A-B$ 的符號位元為 0組合せ論理。多くは加算器/減算器:$A \ge B$ であることと $A-B$ の符号ビットが 0 であることは同値
Identity == != === !==相等 == != === !==等価 == != === !==simple combinational comparators. ===/!== are not synthesizable — silicon has no x簡單的組合比較器。===/!== 不可合成 — 矽晶片上沒有 x単純な組合せ比較器。===/!== は合成できない — シリコンに x は存在しない
Reduction, bitwise, logical縮減、位元、邏輯リダクション・ビット単位・論理translated to Boolean equations, then mapped to physical gates先翻成布林方程式,再映射到實體閘まずブール式に変換され、その後に実ゲートへ割り当てられる
Conditional ?:條件 ?:条件 ?:muxes, or gates that implement muxes多工器,或實作多工器功能的閘マルチプレクサ、またはそれを実現するゲート
Concatenation {}串接 {}連結 {}generally supported; equivalent to a logical bus with no functionality of its own — zero gates一般都支援;等同於一條本身沒有功能的邏輯匯流排 — 零個閘通常サポートされる。それ自体は機能を持たない論理バスと等価 — ゲート数はゼロ
The multiply-by-constant trick乘以常數的技巧定数倍のテクニック

Because * is expensive and shifts are free, any multiplication by a constant should be hand-decomposed into shifts and adds. This is exactly what Lecture 8's temperature converter does — see Practice 14.因為 * 很貴而位移不用錢,任何乘以常數的運算都該手動拆成位移與加法。第 8 講的溫度轉換器做的正是這件事 — 見練習 14。* は高価でシフトはただ同然なので、定数倍はすべて手作業でシフトと加算に分解すべきです。第 8 講の温度変換器がまさにこれを行っています — 演習 14 を参照。

Other construct behaviors其他結構的合成行為その他の構文の扱い

12.3 Loops — the four types12.3 迴圈 — 四種類型12.3 ループ — 4 つの型

Classification分類方式分類

A loop is static (data-independent) if the compiler can determine the number of iterations. Cross that with "contains internal timing control or not" and you get four cases.如果編譯器能判定迭代次數,這個迴圈就是靜態的(與資料無關)。再與「有沒有內部時序控制」交叉,就得到四種情形。コンパイラが繰り返し回数を決定できるとき、そのループは静的(データ非依存)です。これに「内部にタイミング制御があるか」を掛け合わせると 4 通りになります。

Type類型型Static?靜態?静的かInternal timing control?有內部時序控制?内部タイミング制御があるかSynthesizes to合成結果合成結果
Iyes是はいno否いいえcombinational logic by loop unrolling — recommended以迴圈展開得到組合邏輯 — 建議使用ループ展開により組合せ論理になる — 推奨
IIIIIIyes是はいyes是はいsequential logic; activity distributed over one or more clock cycles — not recommended序向邏輯;活動分散在一個或多個時脈週期 — 不建議順序論理。動作が 1 つ以上のクロックサイクルに分散する — 非推奨
IIIIIIIIIno否いいえno否いいえnot synthesizable — it would be an iterative circuit of data-dependent size不可合成 — 那會是一個大小取決於資料的迭代電路合成不可 — 規模がデータに依存する反復回路になってしまう
IVIVIVno否いいえyes是はいsequential logic, cycle count determined at run time — not recommended序向邏輯,週期數在執行時才決定 — 不建議順序論理。サイクル数は実行時に決まる — 非推奨

Type I — the one to use類型 I — 該用的那一種型 I — 使うべきもの

always @ (a or b) begin
  for (k = 0; k < 8; k = k + 1)
    y[k] = a[k] & b[k];
end
// unrolls to 8 independent AND gates

// change the event control to
//   @(posedge clk) and the same loop
//   produces 8 registered outputs

Type III — simulates, will not synthesize類型 III — 模擬得動,但合成不了型 III — シミュレーションは通るが合成できない

always @ (data) begin
  count = 0;
  tmp   = data;
  while (tmp) begin       // bound depends on data
    count = count + tmp[0];
    tmp   = tmp >> 1;
  end
end

The "counting ones" problem is the lecture's running example across all four types. The synthesizable version is Type I — a fixed-bound for loop:「數 1 的個數」是投影片貫穿四種類型的例子。可合成的版本是類型 I — 上界固定的 for 迴圈:「1 の個数を数える」問題は、講義が 4 つの型すべてで使い回す例です。合成可能な版は型 I — 上限が固定された for ループです。

always @ (data) begin
  count = 0;
  for (k = 0; k < 8; k = k + 1)      // bound is a constant -> static
    count = count + data[k];
end
// unrolls into an adder tree: 8 one-bit addends -> 4-bit result

12.4 Tasks and functions in synthesis12.4 合成中的 task 與 function12.4 合成における task と function

TaskTasktaskFunctionFunctionfunction
How the tool handles it工具怎麼處理ツールの扱いexpanded inline就地展開インライン展開されるexpanded at the site of its call在被呼叫的位置展開呼び出し箇所で展開される
Restriction限制制限may not contain inout ports; no timing controls不可含 inout 埠;不可有時序控制inout ポートを含めない。タイミング制御も不可no incompletely specified case or if不可有規格不完整的 case 或 if記述が不完全な case や if は不可
Result結果結果combinational logic (when free of timing control)組合邏輯(在沒有時序控制的前提下)組合せ論理(タイミング制御がない場合)always combinational logic一律是組合邏輯常に組合せ論理

A task used as a full adder and a function used as an arithmetic unit both synthesize to the plain gate networks you would write by hand — the abstraction is free.拿 task 當全加器、拿 function 當算術單元,合成出來的都是你手寫也會得到的那種單純閘網路 — 這層抽象是免費的。task を全加算器として、function を演算ユニットとして使っても、合成されるのは手で書いた場合と同じ素朴なゲート網です — この抽象化はただで手に入ります。

Practice 13 — Classify these loops練習 13 — 把這些迴圈分類演習 13 — これらのループを分類する

Problem: Classify each loop by type (I–IV) and state whether it synthesizes.題目:把每個迴圈依類型(I–IV)分類,並說明它能不能合成。問題:各ループを型(I–IV)で分類し、合成できるかどうかを答えなさい。

// (a)                              // (b)
for (i = 0; i < N; i = i + 1)       for (i = 0; i < N; i = i + 1)
  @(posedge clk) sum = sum + a[i];    sum = sum + a[i];
                                     // N is a parameter

// (c)                              // (d)
i = 0;                              i = 0;
while (a[i] == 0) i = i + 1;        while (a[i] == 0)
                                      @(posedge clk) i = i + 1;
Click to reveal solution點擊看解答クリックで解答を表示
  • (a) Type II — static bound (N is known), but contains an internal edge- sensitive event control. It does synthesize, into sequential logic spread over N clock cycles, but the lecture marks this type not recommended: the resulting state machine is implicit and hard to constrain.(a) 類型 II — 上界是靜態的(N 已知),但內部含有邊緣敏感的事件控制。它確實能合成,變成分散在 N 個時脈週期上的序向邏輯,但投影片把這一類標為不建議:得到的狀態機是隱式的,很難下約束。(a) 型 II — 上限は静的(N は既知)ですが、内部にエッジセンシティブなイベント制御があります。合成はできて、N クロックに分散する順序論理になりますが、講義はこの型を非推奨としています。できあがる状態機械が暗黙的で、制約をかけにくいからです。
  • (b) Type I — static bound, no timing control. Unrolls into a combinational adder tree. Recommended. This is the correct way to write an accumulate-over-a-vector.(b) 類型 I — 上界靜態,沒有時序控制。展開成一棵組合加法樹。建議使用。這正是「把一個向量累加起來」的正確寫法。(b) 型 I — 上限が静的でタイミング制御もありません。展開されて組合せの加算ツリーになります。推奨。ベクタを累算する正しい書き方です。
  • (c) Type III — the bound depends on the data in a. Not synthesizable. It simulates fine, which is what makes it dangerous: it passes verification and fails at synthesis. To make it synthesizable, convert to a fixed-bound for with a "found" flag, or build an explicit FSM.(c) 類型 III — 上界取決於 a 裡的資料。不可合成。它模擬起來好好的,這正是它危險的地方:它通過了驗證,卻在合成時掛掉。要讓它可合成,就改寫成上界固定的 for 加一個「找到了」旗標,或是建一個顯式的 FSM。(c) 型 III — 上限が a の中身に依存します。合成不可。シミュレーションは問題なく通ってしまうのが厄介で、検証を通過してから合成で落ちます。合成できるようにするには、上限を固定した for と「見つかった」フラグに書き換えるか、明示的な FSM を作ります。
  • (d) Type IV — non-static bound plus internal timing control. Synthesizes to sequential logic whose cycle count is determined at run time. Not recommended; write the FSM explicitly instead so that the state encoding and the exit conditions are visible and constrainable.(d) 類型 IV — 上界非靜態,又有內部時序控制。會合成出週期數在執行時才決定的序向邏輯。不建議;請改成顯式地寫出 FSM,這樣狀態編碼與離開條件才看得見、也才下得了約束。(d) 型 IV — 上限が静的でなく、内部にタイミング制御もあります。サイクル数が実行時に決まる順序論理に合成されます。非推奨。FSM を明示的に書き、状態符号化と終了条件が見えて制約をかけられる形にしてください。

The practical takeaway: only Type I belongs in RTL. If you need a data-dependent number of iterations, that is a state machine, and you should write it as one (Section 9.3) rather than hoping the tool infers a good one.實務結論:RTL 裡只應該出現類型 I。如果你需要與資料相依的迭代次數,那就是一台狀態機,你應該把它當成狀態機來寫(9.3 節),而不是指望工具幫你推論出一台好的。実務上の結論:RTL に置いてよいのは型 I だけです。データ依存の繰り返し回数が必要なら、それは状態機械なので、ツールが良いものを推論してくれるのを期待せず、状態機械として書いてください(9.3 節)。

13. Design Examples13. 設計範例13. 設計例

13.1 FIFO13.1 FIFO13.1 FIFO

A First-In First-Out buffer is the standard elastic store between two blocks running at different rates — the single most reused block in a communication IC. Internally it is a memory array plus a read pointer, a write pointer, and status flags.先進先出緩衝器是兩個速率不同的區塊之間標準的彈性儲存 — 通訊 IC 裡被重用最多次的一個區塊。內部就是一個記憶體陣列,加上讀指標、寫指標與狀態旗標。先入れ先出しバッファは、速度の異なる 2 つのブロックのあいだに置く標準的な弾性記憶であり、通信 IC で最も再利用されるブロックです。中身はメモリ配列に読み出しポインタ・書き込みポインタ・ステータスフラグを添えたものです。

module fifo (data_out, full, empty, data_in, wr, rd, clk, rst);
  parameter WIDTH = 8, DEPTH = 16, AWID = 4;   // AWID = log2(DEPTH)

  output [WIDTH-1:0] data_out;
  output             full, empty;
  input  [WIDTH-1:0] data_in;
  input              wr, rd, clk, rst;

  reg [WIDTH-1:0] mem [0:DEPTH-1];             // the storage array
  reg [AWID-1:0]  wr_ptr, rd_ptr;
  reg [AWID:0]    count;                       // one extra bit: 0 .. DEPTH
  reg [WIDTH-1:0] data_out;

  assign full  = (count == DEPTH);
  assign empty = (count == 0);

  always @ (posedge clk or posedge rst) begin
    if (rst) begin
      wr_ptr <= 0;  rd_ptr <= 0;  count <= 0;
    end
    else begin
      if (wr && !full) begin
        mem[wr_ptr] <= data_in;
        wr_ptr      <= wr_ptr + 1'b1;          // wraps naturally at 2^AWID
      end
      if (rd && !empty) begin
        data_out <= mem[rd_ptr];
        rd_ptr   <= rd_ptr + 1'b1;
      end
      case ({wr && !full, rd && !empty})
        2'b10:   count <= count + 1'b1;        // write only
        2'b01:   count <= count - 1'b1;        // read only
        default: count <= count;               // idle, or simultaneous r+w
      endcase
    end
  end
endmodule
Three details that make this FIFO correct讓這個 FIFO 正確的三個細節この FIFO を正しくしている 3 つの細部
  1. count is one bit wider than the pointers. With 4-bit pointers, full and empty both give wr_ptr == rd_ptr and cannot be distinguished. A separate counter that can reach DEPTH resolves the ambiguity.count 比指標多一個位元。用 4 位元指標時,滿與空都會給出 wr_ptr == rd_ptr,分不出來。用一個能數到 DEPTH 的獨立計數器就解決了這個歧義。count はポインタより 1 ビット広い。4 ビットのポインタでは、満杯のときも空のときも wr_ptr == rd_ptr となって区別できません。DEPTH まで数えられる別のカウンタを置けば、このあいまいさは解消します。
  2. The pointers wrap automatically. A 4-bit counter incremented past 15 returns to 0 — no explicit modulo needed, which is why DEPTH is chosen as a power of two.指標會自動繞回。4 位元計數器數過 15 就回到 0 — 不需要顯式取模,這也是把 DEPTH 選成 2 的冪次的原因。ポインタは自動的に折り返します。4 ビットカウンタは 15 を超えると 0 に戻ります — 明示的な剰余演算は不要で、DEPTH を 2 のべき乗に選ぶ理由もそこにあります。
  3. Simultaneous read and write leaves count unchanged — handled by the default branch, which also completes the case and so prevents a latch.同時讀寫時 count 不變 — 由 default 分支處理,它同時也把 case 補完,因而防止了鎖存器。読み書きが同時に起きたとき count は変わりません — default 分岐が処理します。この分岐は case を完結させる役目も果たし、ラッチを防ぎます。

13.2 Design Example I — Temperature monitor system13.2 設計範例 I — 溫度監測系統13.2 設計例 I — 温度モニタシステム

The FIFO application in Lecture 8. Five circuits in a chain:第 8 講中 FIFO 的應用。串成一列的五個電路:第 8 講における FIFO の応用です。5 つの回路が直列につながります。

(1) Data(1) 資料(1) データ Register暫存器レジスタ (2) Data(2) 資料(2) データ Converter轉換器変換器 (3) Data(3) 資料(3) データ Filter濾波器フィルタ (5) FIFO(5) FIFO(5) FIFO (memory)(記憶體)(メモリ) (4) FIFO Ctrl(4) FIFO 控制器(4) FIFO 制御 T_sensorT_sensorT_sensor TcTcTc TfTfTf avgavgavg read out讀出読み出し latch input鎖存輸入入力をラッチ C to F攝氏轉華氏摂氏から華氏へ avg of 4四點平均4 点平均
Temperature monitor system. Blocks 1–3 are the datapath, block 4 is the controller, block 5 is the FIFO storage.溫度監測系統。區塊 1–3 是資料路徑,區塊 4 是控制器,區塊 5 是 FIFO 儲存。温度モニタシステム。ブロック 1–3 がデータパス、ブロック 4 が制御部、ブロック 5 が FIFO の記憶部です。

Circuit 1 — Data register電路 1 — 資料暫存器回路 1 — データレジスタ

always @ (posedge clk or posedge rst)
  if (rst) temp_reg <= 0;
  else if (sample) temp_reg <= temp_sensor;   // store/latch the input data

Circuit 2 — Data converter: the interesting one電路 2 — 資料轉換器:有意思的那一個回路 2 — データ変換器:面白いのはこれ

Celsius to Fahrenheit $$T_f = \frac{9}{5}\,T_c + 32 = 1.8\,T_c + 32$$攝氏轉華氏 $$T_f = \frac{9}{5}\,T_c + 32 = 1.8\,T_c + 32$$摂氏から華氏へ $$T_f = \frac{9}{5}\,T_c + 32 = 1.8\,T_c + 32$$

Both obvious codings are wrong for hardware:兩種直覺寫法在硬體上都是錯的:素直に思いつく 2 つの書き方は、どちらもハードウェアとしては誤りです。

assign temp_out = temp_in * 9 / 5 + 32;      // non-synthesizable division
assign temp_out = (9 * temp_in) / 5 + 32;    // same problem

The standard IC-design move is to approximate 1.8 by a sum of powers of two. The lecture uses $1.75 = 1 + \tfrac{1}{2} + \tfrac{1}{4}$.IC 設計的標準做法是用 2 的冪次之和去逼近 1.8。投影片取 $1.75 = 1 + \tfrac{1}{2} + \tfrac{1}{4}$。IC 設計の定石は、1.8 を 2 のべき乗の和で近似することです。講義では $1.75 = 1 + \tfrac{1}{2} + \tfrac{1}{4}$ を使います。

Alternative 1 — 1 + 0.5 + 0.25替代方案 1 — 1 + 0.5 + 0.25代替案 1 — 1 + 0.5 + 0.25

parameter k32 = 6'b100000;    // 32
assign temp_out = temp_in
                + (temp_in >> 1)
                + (temp_in >> 2) + k32;

Alternative 2 — 2 − 0.25替代方案 2 — 2 − 0.25代替案 2 — 2 − 0.25

assign temp_out = ((temp_in << 1)
                -  (temp_in >> 2)) + k32;
Why the slide calls the first version "synthesizable but incorrect"投影片為什麼說第一個版本「可合成但不正確」スライドが最初の版を「合成できるが正しくない」と呼ぶ理由

Writing it as temp_in/k1 + temp_in/k2 with parameter k1 = 2'b10, k2 = 3'b100 is synthesizable, because the divisors are constant powers of two and the tool turns them into shifts. But the result is not $1.8\,T_c$, it is $1.75\,T_c$ — an approximation error of $-0.05\,T_c$, which at $T_c = 100$ °C is a 5 °C error. Whether that is acceptable is a specification question, not a coding question. Alternative 2 gives the same value with one adder instead of two.配上 parameter k1 = 2'b10, k2 = 3'b100 寫成 temp_in/k1 + temp_in/k2 確實可以合成,因為除數是常數且是 2 的冪次,工具會把它們變成位移。但算出來的不是 $1.8\,T_c$ 而是 $1.75\,T_c$ — 逼近誤差為 $-0.05\,T_c$,在 $T_c = 100$ °C 時就是 5 °C 的誤差。這能不能接受是規格問題,不是寫法問題。替代方案 2 用一個加法器就能得到同樣的值,而不是兩個。parameter k1 = 2'b10, k2 = 3'b100 を添えて temp_in/k1 + temp_in/k2 と書けば、除数が定数かつ 2 のべき乗なのでツールがシフトに変換し、確かに合成できます。しかし得られるのは $1.8\,T_c$ ではなく $1.75\,T_c$ で、近似誤差は $-0.05\,T_c$、$T_c = 100$ °C なら 5 °C の誤差です。それが許容できるかは仕様の問題であって、コーディングの問題ではありません。代替案 2 なら加算器 2 個ではなく 1 個で同じ値が得られます。

Circuit 3 — Data filter (moving average of 4)電路 3 — 資料濾波器(四點移動平均)回路 3 — データフィルタ(4 点移動平均)

reg [WIDTH-1:0] d0, d1, d2, d3;

always @ (posedge clk) begin                 // 4-deep shift register
  d0 <= temp_f;  d1 <= d0;  d2 <= d1;  d3 <= d2;
end

assign avg = (d0 + d1 + d2 + d3) >> 2;       // divide by 4 = shift right 2

Note the same trick again: averaging four samples is a division by a power of two, so it costs a wire re-indexing, not a divider.注意同樣的技巧又出現了:對四個取樣取平均就是除以 2 的冪次,代價只是重新編排線的索引,不是一個除法器。同じ技がまた使われている点に注目してください。4 サンプルの平均は 2 のべき乗による除算なので、コストは配線の添字の付け替えだけで、除算器は不要です。

13.3 Design Example II — AMD 2901 4-bit microcontroller13.3 設計範例 II — AMD 2901 四位元微控制器13.3 設計例 II — AMD 2901 4 ビットマイクロコントローラ

A bit-slice ALU from the classic era, used here because it exercises every construct in the course: a register file, muxes, an ALU, a shift register, and an output selector, all driven by one instruction word.一顆經典年代的位元切片 ALU。這裡拿它當例子,是因為它把整門課的語法結構都操練了一遍:暫存器檔案、多工器、ALU、移位暫存器與輸出選擇器,全都由一個指令字驅動。古典的な時代のビットスライス ALU です。ここで取り上げるのは、レジスタファイル・マルチプレクサ・ALU・シフトレジスタ・出力セレクタという、この講義のすべての構文を 1 つの命令語で動かして見せてくれるからです。

(1) Register File(1) 暫存器檔案(1) レジスタファイル 16 words, dual address16 個字,雙位址16 ワード、アドレス 2 系統 (2) Operand(2) 運算元(2) オペランド Selector選擇器セレクタ (3) ALU(3) ALU(3) ALU (4) Q Register(4) Q 暫存器(4) Q レジスタ with L/R shifters含左右移位器左右シフタ付き (5) Output(5) 輸出(5) 出力 Selector選擇器セレクタ ad, bdad, bdad, bd F write-back寫回ライトバック y
AMD 2901 block diagram. The ALU output fans out to three destinations — the output selector, the register file, and the Q register — and the 9-bit instruction word decides which.AMD 2901 方塊圖。ALU 的輸出分岔到三個去處 — 輸出選擇器、暫存器檔案與 Q 暫存器 — 由 9 位元的指令字決定走哪一條。AMD 2901 のブロック図。ALU の出力は 3 つの行き先 — 出力セレクタ、レジスタファイル、Q レジスタ — に分岐し、どれを使うかは 9 ビットの命令語が決めます。
Instruction word partitioning — the key idea指令字的欄位切割 — 關鍵想法命令語のフィールド分割 — 核心となる考え方

The 9-bit instruction is split into three independent 3-bit fields:9 位元的指令被切成三個互相獨立的 3 位元欄位:9 ビットの命令は、互いに独立した 3 ビットのフィールド 3 つに分かれます。

Field欄位フィールドControls控制什麼制御する対象
i[2:0]the operands for the ALU (operand selector)ALU 的運算元(運算元選擇器)ALU のオペランド(オペランドセレクタ)
i[5:3]the operation of the ALUALU 的運算ALU の演算
i[8:6]the destination of the ALU output (output selector)ALU 輸出的去處(輸出選擇器)ALU 出力の行き先(出力セレクタ)
// Mnemonics via compiler directives — readability with zero hardware cost
`define ADD  3'b000
`define SUBR 3'b001
`define SUBS 3'b010
`define OR   3'b011
`define AND  3'b100

// (1) Register file: 16 words, dual read address
reg [3:0] ram [0:15];
assign ad = ram[a_addr];
assign bd = ram[b_addr];

// (3) ALU: a complete case -> a mux, not a priority chain
always @ (*)
  case (i[5:3])
    `ADD:    {co, F} = r + s + cin;
    `SUBR:   {co, F} = s - r - cin;
    `SUBS:   {co, F} = r - s - cin;
    `OR:     {co, F} = {1'b0, r | s};
    `AND:    {co, F} = {1'b0, r & s};
    default: {co, F} = 5'b0;                // completes the case
  endcase
What to take from this example這個範例該帶走什麼この例から持ち帰るもの

It is a compendium of the course's rules applied together: `define mnemonics instead of magic numbers; a register file as a 2-D reg array; every case terminated with default; mutually exclusive case items so the ALU becomes a balanced mux rather than a priority chain; non-blocking assignment in the clocked blocks and blocking in the combinational ones. Nothing new — just everything at once.它是整門課規則同時上場的一本合集:用 `define 助記符取代魔術數字;把暫存器檔案寫成二維 reg 陣列;每個 case 都以 default 收尾;case 項目互斥,讓 ALU 變成平衡的多工器而不是優先權鏈;時脈區塊用非阻擋式賦值、組合區塊用阻擋式。沒有新東西 — 只是全部一次到齊。この講義の規則がいっぺんに使われている見本市です。マジックナンバーの代わりに `define のニーモニックを使い、レジスタファイルを 2 次元の reg 配列で表し、すべての case を default で締め、case 項目を互いに排他的にして ALU を優先順位チェーンではなくバランスの取れたマルチプレクサにし、クロック同期ブロックではノンブロッキング、組合せブロックではブロッキング代入を使う。新しいものは何もありません — ただすべてが一度に出てくるだけです。

Practice 14 — Multiplying by a constant without a multiplier練習 14 — 不用乘法器做常數乘法演習 14 — 乗算器を使わずに定数倍する

Problem: (a) Implement $y = 1.8x$ using only shifts and adds, with error smaller than the lecture's 1.75 approximation. (b) How many adders does your version need? (c) For an 8-bit unsigned temp_in, how wide must temp_out be for $T_f = 1.75\,T_c + 32$ not to overflow?題目:(a) 只用位移與加法實作 $y = 1.8x$,誤差要比投影片的 1.75 逼近更小。(b) 你的版本需要幾個加法器?(c) 若 temp_in 是 8 位元無號數,temp_out 要多寬,$T_f = 1.75\,T_c + 32$ 才不會溢位?問題:(a) シフトと加算だけで $y = 1.8x$ を実装し、講義の 1.75 近似より誤差を小さくしなさい。(b) その版には加算器がいくつ必要ですか。(c) temp_in が 8 ビット符号なしのとき、$T_f = 1.75\,T_c + 32$ がオーバーフローしないためには temp_out は何ビット必要ですか。

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

(a) Expand 1.8 in binary: $1.8_{10} = 1.11001100\overline{1100}_2$. Truncating after four fractional bits gives(a) 把 1.8 展開成二進位:$1.8_{10} = 1.11001100\overline{1100}_2$。取到小數點後四位後截斷,得到(a) 1.8 を 2 進展開すると $1.8_{10} = 1.11001100\overline{1100}_2$ です。小数第 4 位で打ち切ると、

$$1 + \tfrac{1}{2} + \tfrac{1}{4} + \tfrac{1}{32} = 1.78125$$$$1 + \tfrac{1}{2} + \tfrac{1}{4} + \tfrac{1}{32} = 1.78125$$$$1 + \tfrac{1}{2} + \tfrac{1}{4} + \tfrac{1}{32} = 1.78125$$
assign y = x + (x >> 1) + (x >> 2) + (x >> 5);

Error is $1.8 - 1.78125 = 0.01875$, versus $1.8 - 1.75 = 0.05$ for the lecture's version — about 2.7 times better. Adding the next term $\tfrac{1}{64}$ gives 1.796875, error 0.003125.誤差是 $1.8 - 1.78125 = 0.01875$,對比投影片版本的 $1.8 - 1.75 = 0.05$ — 大約好 2.7 倍。再加上一項 $\tfrac{1}{64}$ 得到 1.796875,誤差 0.003125。誤差は $1.8 - 1.78125 = 0.01875$ で、講義版の $1.8 - 1.75 = 0.05$ に対しておよそ 2.7 倍良くなります。さらに $\tfrac{1}{64}$ を足すと 1.796875、誤差は 0.003125 です。

(b) Four terms require three adders (plus one more for the +32). The lecture's 1.75 needs two adders for the multiply. So the improved accuracy costs one adder — a genuine area-versus-accuracy trade, and exactly the kind of decision the course means by "do resource sharing before RTL coding".(b) 四項需要三個加法器(再加一個做 +32)。投影片的 1.75 在乘法部分只要兩個加法器。所以更高的精度代價是多一個加法器 — 這是不折不扣的面積對精度取捨,也正是本課程說「資源共用要在寫 RTL 之前做」的那種決策。(b) 4 項には加算器 3 個が必要です(+32 用にもう 1 個)。講義の 1.75 は乗算部分に加算器 2 個で済みます。つまり精度を上げる代償は加算器 1 個 — 面積と精度の正真正銘のトレードオフであり、この講義が「リソース共有は RTL を書く前に」というときに念頭に置いている判断そのものです。

A cheaper route to similar accuracy: $1.8 \approx 2 - \tfrac{1}{4} + \tfrac{1}{16} - \ldots$ Using $2 - \tfrac{1}{4} = 1.75$ takes one adder/subtractor, matching Alternative 2 in the lecture; adding $+\tfrac{1}{32}$ gives 1.78125 with two.要達到相近精度還有更便宜的路:$1.8 \approx 2 - \tfrac{1}{4} + \tfrac{1}{16} - \ldots$ 只取 $2 - \tfrac{1}{4} = 1.75$ 需要一個加減器,等同投影片的替代方案 2;再加上 $+\tfrac{1}{32}$ 得到 1.78125,需要兩個。同程度の精度に達するより安い道もあります:$1.8 \approx 2 - \tfrac{1}{4} + \tfrac{1}{16} - \ldots$。$2 - \tfrac{1}{4} = 1.75$ なら加減算器 1 個で、講義の代替案 2 と同じです。$+\tfrac{1}{32}$ を足して 1.78125 にするなら 2 個必要です。

(c) Worst case is $x = 255$:(c) 最壞情況是 $x = 255$:(c) 最悪の場合は $x = 255$ です。

$$y_{\max} = 1.75 \times 255 + 32 = 446.25 + 32 = 478.25$$$$y_{\max} = 1.75 \times 255 + 32 = 446.25 + 32 = 478.25$$$$y_{\max} = 1.75 \times 255 + 32 = 446.25 + 32 = 478.25$$

$\lceil \log_2 479 \rceil = 9$, so 9 bits suffice for the integer part. If you keep the two fractional bits produced by the shifts rather than truncating them, the result needs 11 bits total in a $9.2$ fixed- point format.$\lceil \log_2 479 \rceil = 9$,所以整數部分 9 個位元就夠。如果你把位移產生的兩個小數位保留下來而不截掉,結果需要總共 11 個位元,格式為 $9.2$ 定點數。$\lceil \log_2 479 \rceil = 9$ なので、整数部は 9 ビットで足ります。シフトで生じる小数 2 ビットを切り捨てずに残すなら、$9.2$ の固定小数点形式で合計 11 ビット必要です。

The general habit: after any constant-multiply decomposition, recompute the worst-case output range and size the target accordingly. Silent truncation in a temperature path is a wrong reading; in a communication receiver it is a raised bit-error rate.通用的習慣:做完任何常數乘法分解之後,重新算一次最壞情況的輸出範圍,再據此決定目標的位元寬度。溫度路徑上的無聲截斷只是讀數錯了;在通訊接收機裡,那就是位元錯誤率上升。身につけるべき習慣:定数乗算を分解したら、必ず最悪ケースの出力範囲を計算し直し、それに合わせて格納先の幅を決めること。温度計測経路での黙った切り捨ては読み値の誤りで済みますが、通信受信機ではビット誤り率の悪化になります。

14. Exam Essentials14. 考前重點14. 試験の要点

14.1 Rule cheat-sheet14.1 規則速查表14.1 ルール早見表

Nets and registersnet 與 registerネットとレジスタ
  • Net: driven by assign or a primitive/module outputNet:由 assign 或原件/模組輸出驅動ネット:assign か、プリミティブ/モジュールの出力に駆動される
  • Register: assigned only in a procedural block, task, function, or sequential UDPRegister:只能在程序區塊、task、function 或序向 UDP 中被賦值レジスタ:手続きブロック・task・function・順序回路 UDP の中でのみ代入される
  • Undriven net = z; uninitialised register = x未被驅動的 net = z;未初始化的 register = x駆動されていないネット = z、初期化されていないレジスタ = x
  • Undeclared identifier defaults to wire未宣告的識別字預設為 wire宣言されていない識別子は既定で wire
Assignment operators賦值運算子代入演算子
  • = blocking → combinational always @(*)= 阻擋式 → 組合的 always @(*)= ブロッキング → 組合せの always @(*)
  • <= non-blocking → sequential always @(posedge clk)<= 非阻擋式 → 序向的 always @(posedge clk)<= ノンブロッキング → 順序回路の always @(posedge clk)
  • Never mix both on one variable in one behavior同一個 behavior 內,絕不對同一個變數混用兩者同じ behavior 内で同じ変数に両方を混ぜない
  • Non-blocking is order-independent — that is why FSMs use it非阻擋式與順序無關 — 這就是 FSM 用它的理由ノンブロッキングは順序に依存しない — FSM が使う理由がこれ
Delay延遲遅延
  • Gate delay = inertial → swallows narrow pulses閘延遲 = 慣性 → 會吞掉窄脈衝ゲート遅延 = 慣性 → 狭いパルスを飲み込む
  • Net delay = transport → passes everythingnet 延遲 = 傳輸 → 什麼都放行ネット遅延 = 伝送 → 何でも通す
  • #5 a = b; suspends the flow#5 a = b; 會暫停流程#5 a = b; はフローを止める
  • a = #5 b; evaluates now, assigns later, still suspendsa = #5 b; 現在求值、稍後賦值,一樣會暫停a = #5 b; は今評価して後で代入し、やはりフローを止める
  • a <= #5 b; evaluates now, assigns later, does not suspenda <= #5 b; 現在求值、稍後賦值,不會暫停a <= #5 b; は今評価して後で代入し、フローを止めない
Latch prevention避免鎖存器ラッチを防ぐ
  • Complete sensitivity list (or always @(*))敏感度列表要完整(或用 always @(*))センシティビティリストを完全にする(または always @(*) を使う)
  • default on every case每個 case 都要有 defaultすべての case に default を置く
  • else on every combinational if chain每個組合的 if 串都要有 else組合せの if 連鎖にはすべて else を置く
  • No self-assignment (that is a combinational loop, which is worse)不要自我賦值(那是組合迴路,更糟)自分自身への代入をしない(それは組合せループで、もっと悪い)
Flip-flop inference正反器的推論フリップフロップの推論
  • Edge-sensitive event control + an assignment邊緣敏感的事件控制 + 一個賦值エッジセンシティブなイベント制御 + 代入
  • Asynchronous controls need their own edge qualifier非同步控制訊號要有自己的邊緣修飾子非同期制御には自前のエッジ修飾子が要る
  • Exactly one clock edge in the list列表中恰好只能有一個時脈邊緣リスト中のクロックエッジはちょうど 1 つ
  • The last branch is the synchronous one最後一個分支才是同步分支最後の分岐が同期の分岐
Never synthesizable永遠不可合成決して合成できないもの
  • initial, fork/join, wait, named eventsinitial、fork/join、wait、具名事件initial、fork/join、wait、名前付きイベント
  • Delay controls, force/release, $tasks延遲控制、force/release、$ 系統任務遅延制御、force/release、$ システムタスク
  • Sequential UDPs, specify blocks序向 UDP、specify 區塊順序回路 UDP、specify ブロック
  • === / !==, real/time===/!==、real/time===/!==、real/time
  • Data-dependent loops without timing control沒有時序控制、且與資料相依的迴圈タイミング制御のないデータ依存ループ

14.2 Classic traps14.2 經典陷阱14.2 典型的な落とし穴

Trap陷阱思い込みWhat actually happens實際上會怎樣実際に起きること
reg means a flip-flopreg 就代表正反器reg はフリップフロップを意味するNo. It means "holds a value between procedural assignments". Only a clock edge creates a flip-flop.不對。它的意思是「在兩次程序式賦值之間保住一個值」。只有時脈邊緣才會造出正反器。違います。「手続き型代入と代入の間で値を保持する」という意味です。フリップフロップを生むのはクロックエッジだけです。
case is faster than ifcase 比 if 快case は if より速いNo. What matters is whether the conditions are mutually exclusive → mux, or overlapping → priority chain.不對。重點在於條件是否互斥 → 多工器,還是重疊 → 優先權鏈。違います。効くのは条件が互いに排他的か(→ マルチプレクサ)、重なっているか(→ 優先順位チェーン)です。
a == b is always 0 or 1a == b 一定是 0 或 1a == b は必ず 0 か 1 になるNo. It is x if either operand contains x/z. Only === is guaranteed 0 or 1.不對。只要有一邊含 x/z,結果就是 x。只有 === 才保證是 0 或 1。違います。どちらかに x/z があれば結果は x です。0 か 1 が保証されるのは === だけです。
if (x) takes the true branchif (x) 會走真分支if (x) は真の分岐を通るNo. True is only the value 1; {0, x, z} are all false.不對。真只有值 1;{0, x, z} 全都是假。違います。真は値 1 だけで、{0, x, z} はすべて偽です。
Missing else always makes a latch少了 else 一定會生鎖存器else がなければ必ずラッチができるOnly in a level-sensitive behavior. In always @(posedge clk) it makes a clock-enabled flip-flop, which is fine.只有在準位敏感的 behavior 裡才是。在 always @(posedge clk) 裡它做出的是帶 clock enable 的正反器,這沒有問題。レベルセンシティブな behavior の場合だけです。always @(posedge clk) の中ではクロックイネーブル付きフリップフロップになり、問題ありません。
Non-blocking delays the assignment by one cycle非阻擋式會把賦值延後一個週期ノンブロッキングは代入を 1 サイクル遅らせるNo. It delays the assignment to the end of the current time step. The one-cycle behavior comes from the clock edge, not the operator.不對。它把賦值延到目前這個時間步的末尾。一個週期的行為來自時脈邊緣,不是來自這個運算子。違います。代入を現在の時間ステップの終わりまで遅らせるだけです。1 サイクル分の振る舞いはクロックエッジによるもので、この演算子によるものではありません。
&(01xx) is x&(01xx) 是 x&(01xx) は x になるNo, it is 0. A controlling value settles a reduction regardless of unknowns.不對,是 0。不管有沒有未知值,控制值都能定下縮減運算的結果。違います、0 です。不定値があっても支配値がリダクションの結果を決めます。
A narrow glitch always shows up at the gate output窄突波一定會出現在閘的輸出狭いグリッチは必ずゲート出力に現れるNo. Inertial delay swallows any pulse shorter than the gate delay.不對。慣性延遲會吞掉任何比閘延遲還短的脈衝。違います。慣性遅延はゲート遅延より短いパルスをすべて飲み込みます。
Primitive instances must be named原件實體必須命名プリミティブのインスタンスには名前が必要No — optional for primitives and UDPs, mandatory for module instances.不對 — 原件與 UDP 可以省略,模組實體則是必要的。違います — プリミティブと UDP では省略でき、モジュールのインスタンスでは必須です。
An incomplete sensitivity list is only a simulation issue敏感度列表不完整只是模擬的問題センシティビティリストの不備はシミュレーションだけの問題Worse: simulation and synthesis disagree, so the bug survives verification.更糟:模擬與合成會互相矛盾,所以這個 bug 會活著通過驗證。もっと悪いです。シミュレーションと合成が食い違うため、バグが検証を生き延びます。

14.3 Mixed quiz14.3 綜合小測14.3 総合クイズ

Final Review — ten short questions總複習 — 十道簡答題総復習 — 10 の短答問題

Problem:題目:問題:

  1. Why must the output of a combinational UDP be a net, but the output of a sequential UDP a reg?為什麼組合邏輯 UDP 的輸出必須是 net,而序向 UDP 的輸出必須是 reg?組合せ論理 UDP の出力はネットでなければならず、順序回路 UDP の出力は reg でなければならないのはなぜですか。
  2. Under `timescale 10ps/1ps, what delay does nor #3.57 (z, x1, x2) produce?在 `timescale 10ps/1ps 之下,nor #3.57 (z, x1, x2) 產生多少延遲?`timescale 10ps/1ps のもとで、nor #3.57 (z, x1, x2) の遅延はいくらですか。
  3. What does {3{a}, 2{b}} expand to?{3{a}, 2{b}} 會展開成什麼?{3{a}, 2{b}} は何に展開されますか。
  4. Give the three transitions that count as posedge.寫出算作 posedge 的三種轉態。posedge とみなされる 3 つの遷移を挙げなさい。
  5. An always block contains only a = ~a; with no timing control. What happens?某個 always 區塊裡只有 a = ~a;,沒有任何時序控制。會發生什麼事?ある always ブロックに a = ~a; だけがあり、タイミング制御が一切ありません。何が起こりますか。
  6. Distinguish $stop, $finish, and disable.區分 $stop、$finish 與 disable。$stop、$finish、disable の違いを述べなさい。
  7. Why does the lecture prefer Moore machines?投影片為什麼偏好 Moore 機器?講義が Moore 型を好むのはなぜですか。
  8. Name the four loop types and say which one belongs in RTL.說出四種迴圈類型,並指出哪一種才該出現在 RTL 裡。ループの 4 つの型を挙げ、RTL に置いてよいのはどれかを答えなさい。
  9. What is the slack of a path with arrival time 3.9 ns and required arrival time 3.7 ns, and is it a violation?某條路徑的 arrival time 為 3.9 ns、required arrival time 為 3.7 ns,slack 是多少?這算違規嗎?到達時刻 3.9 ns、要求到達時刻 3.7 ns の経路のスラックはいくらですか。また、それは違反ですか。
  10. In a FIFO, why must the occupancy counter be one bit wider than the address pointers?在 FIFO 中,為什麼存量計數器必須比位址指標多一個位元?FIFO において、占有数カウンタがアドレスポインタより 1 ビット広くなければならないのはなぜですか。
Click to reveal solution點擊看解答クリックで解答を表示
  1. A combinational UDP's output is a pure function of its current inputs, so it needs no storage — a net carries it. A sequential UDP has a state that must persist between evaluations, and only a reg can hold a value between events.組合邏輯 UDP 的輸出是目前輸入的純函數,不需要儲存 — 一條 net 就承載得了。序向 UDP 有狀態,必須在兩次求值之間保住,而只有 reg 能在事件之間保住一個值。組合せ論理 UDP の出力は現在の入力の純粋な関数なので記憶は不要で、ネットで運べます。順序回路 UDP には評価と評価のあいだ保持しなければならない状態があり、イベント間で値を保てるのは reg だけです。
  2. One time unit is 10 ps, so $3.57 \times 10 = 35.7$ ps, rounded to the 1 ps precision → 36 ps.一個時間單位是 10 ps,所以 $3.57 \times 10 = 35.7$ ps,依 1 ps 的精度取整 → 36 ps。1 時間単位は 10 ps なので $3.57 \times 10 = 35.7$ ps、1 ps の精度に丸めて → 36 ps。
  3. {a, a, a, b, b} — a 5-bit vector.{a, a, a, b, b} — 一個 5 位元的向量。{a, a, a, b, b} — 5 ビットのベクタです。
  4. 0->1, 0->x, x->1. (Symmetrically, negedge is 1->0, 1->x, x->0.)0->1、0->x、x->1。(對稱地,negedge 是 1->0、1->x、x->0。)0->1、0->x、x->1。(対称的に negedge は 1->0、1->x、x->0 です。)
  5. The simulator hangs. The block re-triggers itself within the same time step, simulation time never advances, and the event list never empties. Every always that is to run forever needs a # or @ somewhere in its body.模擬器會卡死。這個區塊在同一個時間步內不斷觸發自己,模擬時間永遠推不動,事件清單也永遠清不空。任何要永遠跑下去的 always,本體裡都必須有個 # 或 @。シミュレータがハングします。そのブロックが同じ時間ステップ内で自分自身を再起動し続け、シミュレーション時刻は進まず、イベントリストも空になりません。永久に回る always には、本体のどこかに # か @ が必要です。
  6. $stop halts the simulator into interactive mode — you can resume. $finish ends the whole simulation and returns to the OS. disable terminates only a named block or task; simulation continues.$stop 讓模擬器停進互動模式 — 還能繼續。$finish 結束整個模擬並回到作業系統。disable 只終止某個具名區塊或 task;模擬會繼續下去。$stop はシミュレータを対話モードで停止させます — 再開できます。$finish はシミュレーション全体を終了して OS に戻ります。disable は名前付きブロックか task だけを終了させ、シミュレーションは続きます。
  7. Because a Moore output is decoded from registered state alone, it is stable for a full clock cycle and cannot pass an input glitch through to the output. The cost is generally one more state and one cycle of latency.因為 Moore 的輸出是單獨從已暫存的狀態解碼出來的,它整個時脈週期都穩定,不可能把輸入的突波傳到輸出。代價通常是多一個狀態和一個週期的延遲。Moore の出力はレジスタに取り込まれた状態だけからデコードされるため、1 クロック周期を通じて安定し、入力のグリッチを出力へ通すことがありません。代償はふつう状態 1 つとレイテンシ 1 サイクルです。
  8. Type I: static, no internal timing control → combinational logic by unrolling — this is the one for RTL. Type II: static with timing control → sequential, not recommended. Type III: non-static, no timing control → not synthesizable. Type IV: non-static with timing control → sequential, not recommended.類型 I:靜態、無內部時序控制 → 展開成組合邏輯 — 這一種才該用在 RTL。類型 II:靜態但有時序控制 → 序向,不建議。類型 III:非靜態、無時序控制 → 不可合成。類型 IV:非靜態且有時序控制 → 序向,不建議。型 I:静的でタイミング制御なし → 展開して組合せ論理 — RTL に置くべきはこれ。型 II:静的だがタイミング制御あり → 順序論理、非推奨。型 III:非静的でタイミング制御なし → 合成不可。型 IV:非静的でタイミング制御あり → 順序論理、非推奨。
  9. $\text{slack} = 3.7 - 3.9 = -0.2$ ns. Negative, so yes, it is a violation — the data arrives 0.2 ns later than the capturing flip-flop's setup requirement allows.$\text{slack} = 3.7 - 3.9 = -0.2$ ns。是負的,所以確實是違規 — 資料比接收端正反器 setup 所允許的時間晚到了 0.2 ns。$\text{slack} = 3.7 - 3.9 = -0.2$ ns。負なので違反です — データが受け側フリップフロップのセットアップが許す時刻より 0.2 ns 遅れて到着しています。
  10. With $n$-bit pointers, the full and empty conditions both give wr_ptr == rd_ptr and are indistinguishable. A counter that can represent 0 through DEPTH inclusive needs $n+1$ bits and separates the two cases unambiguously.用 $n$ 位元指標時,滿與空兩種情況都給出 wr_ptr == rd_ptr,無法區分。而一個能表示 0 到 DEPTH(含)的計數器需要 $n+1$ 個位元,這樣就能毫不含糊地把兩者分開。$n$ ビットのポインタでは、満杯と空のどちらでも wr_ptr == rd_ptr となり区別できません。0 から DEPTH まで(両端を含む)を表せるカウンタには $n+1$ ビットが必要で、これなら 2 つの状態を明確に分けられます。
Closing advice from the lecture投影片的結語建議講義の結びの助言

Verilog is a platform. It supports hardware design (the design module) and also C/C++-like coding (the testbench, non-synthesized). How do you write Verilog well?Verilog 是一個平台。它既支援硬體設計(設計模組),也支援類似 C/C++ 的寫程式方式(測試平台,不合成)。那要怎麼把 Verilog 寫好?Verilog はプラットフォームです。ハードウェア設計(設計モジュール)も、C/C++ に近いコーディング(合成しないテストベンチ)も支えます。では、どうすれば Verilog をうまく書けるでしょうか。

  • Know the basic concepts and syntax.把基本概念與語法弄懂。基本概念と構文を身につけること。
  • Get a good reference — a person, or some code files worth imitating.找一個好的參考對象 — 一個人,或幾份值得模仿的程式碼。良い手本を得ること — 人でもよいし、真似する価値のあるコードでもよい。
  • Form good coding habits: naming rules, comments, and a consistent partition between assign blocks and always blocks.養成好的撰寫習慣:命名規則、註解,以及 assign 區塊與 always 區塊之間一致的分工。良い書き方の習慣をつけること:命名規則、コメント、そして assign ブロックと always ブロックの一貫した使い分け。

Hardware divides into two parts — combinational circuits and sequential circuits. Draw the picture (the architecture) first, then make the connections (the coding).硬體分成兩部分 — 組合電路與序向電路。先畫圖(架構),再接線(寫程式)。ハードウェアは 2 つに分かれます — 組合せ回路と順序回路です。まず絵(アーキテクチャ)を描き、それから配線(コーディング)をすること。