Outline — click to expand大綱 — 點擊展開アウトライン — クリックで展開
1. Sequential Synthesis1. 序向邏輯合成1. 順序回路の合成
2. Reset2. 重置 Reset2. リセット
3. Registered Logic3. 暫存化的邏輯3. レジスタ付き論理
4. Registers and Shifters4. 暫存器與移位器4. レジスタとシフタ
5. Counters5. 計數器5. カウンタ
6. Pipelining6. 管線化6. パイプライン化
7. Finite State Machines7. 有限狀態機7. 有限状態機械
8. Summary8. 總結8. まとめ
← DCIC Study Guides← DCIC 自學指南← DCIC 学習ガイド
EE5733 Digital Communication IC Design · Lecture 5EE5733 數位通訊積體電路設計 · 第 5 講EE5733 デジタル通信 IC 設計 · 第 5 講

Synthesis of Sequential Logic序向邏輯合成順序回路の合成

Flip-flop inference, synchronous and asynchronous reset, shift registers, counters, pipelining and Mealy / Moore finite state machines正反器推論、同步與非同步重置、移位暫存器、計數器、管線化,以及 Mealy / Moore 有限狀態機 — 序向邏輯合成自學指南フリップフロップの推論、同期・非同期リセット、シフトレジスタ、カウンタ、パイプライン化、Mealy / Moore 有限状態機械 — 順序回路合成の学習ガイド

Contents目錄目次

  1. Synthesizing Sequential Logic序向邏輯的合成順序回路の合成
  2. Reset: Event Control, Synchronous and Asynchronous重置:事件控制、同步與非同步リセット:イベント制御、同期と非同期
  3. Registered Combinational Logic暫存化的組合邏輯レジスタ付き組合せ論理
  4. Shift Registers, Barrel Shifter and Load Registers移位暫存器、桶形移位器與載入暫存器シフトレジスタ、バレルシフタ、ロードレジスタ
  5. Ripple and Ring Counters漣波計數器與環形計數器リプルカウンタとリングカウンタ
  6. Pipelined 16-bit Adder管線化的 16 位元加法器パイプライン化 16 ビット加算器
  7. Finite State Machines有限狀態機有限状態機械
  8. Summary and Exam Checklist總結與考前檢查表まとめと試験前チェックリスト

1. Synthesizing Sequential Logic1. 序向邏輯的合成1. 順序回路の合成

1.1 Commonly synthesized sequential logic1.1 常見被合成的序向邏輯1.1 よく合成される順序回路

Storage and datapath儲存與資料路徑記憶とデータパス
  • Data register, transparent latch資料暫存器、透明閂鎖データレジスタ、トランスペアレント・ラッチ
  • Shift register, accumulator移位暫存器、累加器シフトレジスタ、アキュムレータ
  • Parallel/serial converter並列/串列轉換器パラレル・シリアル変換器
  • Synchronizer, edge detector同步器、邊緣偵測器同期化回路、エッジ検出器
Counters計數器カウンタ
  • Binary, Johnson, BCD, Gray counter二進位、Johnson、BCD、格雷碼計數器バイナリ、ジョンソン、BCD、グレイコード・カウンタ
  • Event counter事件計數器イベントカウンタ
  • Memory address counter, FIFO pointer記憶體位址計數器、FIFO 指標メモリアドレスカウンタ、FIFO ポインタ
Generators產生器ジェネレータ
  • Gate, pulse, timing generator閘控、脈衝、時序產生器ゲート、パルス、タイミング生成器
  • Clock generator時脈產生器クロック生成器
Control控制制御
  • Finite state machine有限狀態機有限状態機械
  • Sequencer, controller序列器、控制器シーケンサ、コントローラ

1.2 When a register variable becomes a flip-flop1.2 暫存變數何時會變成正反器1.2 レジスタ変数がフリップフロップになるとき

A register variable in a behavior is synthesized as an edge-triggered flip-flop when行為描述中的暫存變數(reg)在下列情況下會被合成成邊緣觸發正反器:ビヘイビア記述中のレジスタ変数は、次の条件を満たすときエッジトリガ・フリップフロップとして合成される。

module swap_synch (set1, set2, clk, data_a, data_b);
  output data_a, data_b;
  input  clk, set1, set2;
  reg    data_a, data_b;

  always @ (posedge clk)
    begin
      if (set1)      begin data_a <= 1; data_b <= 0; end
      else if (set2) begin data_a <= 0; data_b <= 1; end
      else
        begin
          data_b <= data_a;      // non-blocking: true swap
          data_a <= data_b;
        end
    end
endmodule

Each of data_a and data_b becomes one DFF fed by a 4:1 mux selected by {set1, set2}:data_a 與 data_b 各變成一個 DFF,前面接一個由 {set1, set2} 選擇的 4:1 多工器:data_a と data_b はそれぞれ 1 個の DFF になり、その前段に {set1, set2} で選択される 4:1 マルチプレクサが入る。

{set1, set2}00011011
D of data_adata_a 的 Ddata_a の Ddata_b011
D of data_bdata_b 的 Ddata_b の Ddata_a100

The synthesized netlist folds each mux into a few gates (inverter, AND, NOR) in front of the DFF.合成後的 netlist 會把每個多工器摺成 DFF 前面的幾個閘(反相器、AND、NOR)。合成後のネットリストでは、各マルチプレクサは DFF の前段にある数個のゲート(インバータ、AND、NOR)にまとめられる。

Practice 1 — Flip-flop or wire?練習 1 — 正反器還是連線?練習 1 — フリップフロップか配線か?

Problem: How many flip-flops does each block infer?題目:每個區塊各會推論出幾個正反器?問題:それぞれのブロックは何個のフリップフロップを推論するか。

// (a)
always @ (posedge clk) begin t = a & b; y <= t | c; end
// (b)
always @ (posedge clk) begin y <= t | c; t = a & b; end
// (c)
always @ (posedge clk) begin q1 <= d; q2 <= q1; q3 <= q2; end
// (d)
always @ (posedge clk) begin q1 = d; q2 = q1; q3 = q2; end
Click to reveal solution點擊展開解答クリックで解答を表示

(a) 1 (y). t is written before it is read in the same clock, so it is just a wire.(a) 1 個(y)。t 在同一個時脈內先寫後讀,所以只是一條連線。(a) 1 個(y)。t は同じクロック内で書き込まれてから読まれるので、単なる配線になる。

(b) 2. t is read before it is written, so y sees last cycle's t — t must be stored.(b) 2 個。t 先讀後寫,所以 y 看到的是上一個週期的 t,t 必須被儲存起來。(b) 2 個。t は書き込まれる前に読まれるため、y は前サイクルの t を見る。したがって t は保持されなければならない。

(c) 3 — a 3-stage shift register.(c) 3 個 — 一個三級的移位暫存器。(c) 3 個 — 3 段のシフトレジスタ。

(d) 1. With blocking assignments q1, q2, q3 all get d in the same clock: one FF whose output drives all three names. A classic bug when a shift register was intended.(d) 1 個。使用阻擋式指定時,q1、q2、q3 在同一個時脈都拿到 d:只有一個正反器,其輸出驅動全部三個名稱。想做移位暫存器時,這是經典的錯誤。(d) 1 個。ブロッキング代入では q1、q2、q3 が同一クロックですべて d を受け取る。つまりフリップフロップは 1 個で、その出力が 3 つの名前すべてを駆動する。シフトレジスタのつもりで書いたときの典型的なバグである。

2. Reset: Event Control, Synchronous and Asynchronous2. 重置:事件控制、同步與非同步2. リセット:イベント制御、同期と非同期

2.1 Event control with reset2.1 含 reset 的事件控制2.1 リセットを含むイベント制御

If the event control expression is sensitive to the edge of more than one signal:若事件控制運算式對一個以上訊號的邊緣敏感:イベント制御式が複数の信号のエッジに感応する場合:

2.2 Asynchronous vs synchronous reset2.2 非同步 reset 與同步 reset2.2 非同期リセットと同期リセット

Asynchronous reset非同步 reset非同期リセット
module reg_4_a (Data_in, clock, reset, Data_out);
  input  [3:0] Data_in;
  input        clock, reset;
  output [3:0] Data_out;
  reg    [3:0] Data_out;

  always @ (posedge clock or posedge reset)
    begin
      if (reset == 1'b1) Data_out <= 4'b0;
      else               Data_out <= Data_in;
    end
endmodule
Synchronous reset同步 reset同期リセット
module reg_4_b (Data_in, clock, reset, Data_out);
  input  [3:0] Data_in;
  input        clock, reset;
  output [3:0] Data_out;
  reg    [3:0] Data_out;

  always @ (posedge clock)
    begin
      if (reset == 1'b1) Data_out <= 4'b0;
      else               Data_out <= Data_in;
    end
endmodule
Asynchronous reset非同步 reset非同期リセットSynchronous reset同步 reset同期リセット
Event list事件列表イベントリストposedge clock or posedge resetposedge clock only只有 posedge clockposedge clock のみ
Hardware硬體ハードウェアReset wired to the R (clear) pin of each DFFreset 接到每個 DFF 的 R(清除)腳リセットは各 DFF の R(クリア)端子に配線されるReset is ordinary data logic in front of D (AND / mux)reset 只是 D 端前面的一般資料邏輯(AND/多工器)リセットは D の前段にある通常のデータ論理(AND/マルチプレクサ)にすぎない
Timing時序タイミングNot synchronized with the clock; acts immediately不與時脈同步;立即生效クロックと同期せず、即座に作用するSynchronized with the clock; acts at the next edge與時脈同步;在下一個邊緣才生效クロックに同期し、次のエッジで作用する
Reset pulse重置脈衝リセットパルスAny width寬度不限幅は任意Must cover a rising clock edge — wider than one clock period必須涵蓋一個時脈上升緣 — 寬度要大於一個時脈週期クロックの立ち上がりエッジを含む必要がある — 1 クロック周期より長いこと

2.3 Waveform comparison (active-high reset)2.3 波形比較(高準位有效的 reset)2.3 波形の比較(アクティブハイのリセット)

clockresetData_inData_out clockresetData_inData_out 4'd84'd8 4'dx4'd04'd8 4'dx4'd04'd8 async: clears at reset edge非同步:在 reset 邊緣立即清除非同期:リセットのエッジで即クリアsync: clears at next clock edge同步:在下一個時脈邊緣才清除同期:次のクロックエッジでクリア
Left: asynchronous reset clears Data_out immediately, even for a narrow pulse. Right: synchronous reset clears only at a rising clock edge while reset is high; Data_out then loads 4'd8 at the next edge after reset falls.左:非同步 reset 立即清除 Data_out,即使脈衝很窄也一樣。右:同步 reset 只有在 reset 為高時遇到時脈上升緣才清除;reset 落下之後的下一個邊緣,Data_out 才載入 4'd8。左:非同期リセットは、パルスが狭くても Data_out を即座にクリアする。右:同期リセットは、リセットがハイの間にクロックの立ち上がりエッジが来たときだけクリアする。その後、リセットが下がった次のエッジで Data_out は 4'd8 を取り込む。
Key points — click to expand重點整理(點擊展開)要点(クリックで展開)
  • Asynchronous reset: put posedge reset in the sensitivity list. It is wired to the clear pin of the DFF, takes effect immediately, and the pulse may be any width.非同步 reset:敏感列表放 posedge reset,接到 DFF 的清除腳,立即生效,脈衝寬度不限。非同期リセット:センシティビティリストに posedge reset を置く。DFF のクリア端子に接続され、即座に作用し、パルス幅は任意でよい。
  • Synchronous reset: sensitive to the clock only. Reset is just combinational logic at the D pin, so it takes effect only if it is still high at a rising clock edge — the pulse must be wider than one clock period.同步 reset:只對時脈敏感,reset 只是 D 端的組合邏輯,必須持續到時脈上升緣才會生效,因此脈衝寬度要大於一個時脈週期。同期リセット:クロックにのみ感応する。リセットは D 端子の組合せ論理にすぎず、クロックの立ち上がりエッジまでハイを保って初めて有効になる。したがってパルス幅は 1 クロック周期より長くする。
  • When several edges are in the event list, the first statement must be an if, and the final else branch is the synchronous (clocked) action — never test if (clock) yourself.多個邊緣敏感時,第一個敘述必須是 if,最後的 else 分支就是同步(時脈)動作,不要再寫 if (clock)。複数のエッジに感応する場合、最初の文は if でなければならず、最後の else 分岐が同期(クロック)動作になる。if (clock) を自分で書いてはいけない。
Practice 2 — A short reset pulse練習 2 — 很窄的重置脈衝練習 2 — 短いリセットパルス

Problem: Clock period 10 with rising edges at 5, 15, 25, ... reset is high only during [7, 12]. Data_in = 4'd8 throughout, Data_out = 4'd3 before t = 7. Give Data_out for reg_4_a and reg_4_b over [0, 30].題目:時脈週期為 10,上升緣在 5、15、25、…。reset 只在 [7, 12] 期間為高。全程 Data_in = 4'd8,而 t = 7 之前 Data_out = 4'd3。請寫出 reg_4_a 與 reg_4_b 在 [0, 30] 之間的 Data_out。問題:クロック周期は 10、立ち上がりエッジは 5、15、25、…。reset は [7, 12] の間だけハイである。全期間で Data_in = 4'd8、t = 7 より前は Data_out = 4'd3 とする。reg_4_a と reg_4_b の [0, 30] における Data_out を示せ。

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

reg_4_a (async): 3 until t = 5, 8 at the edge at t = 5, cleared to 0 at t = 7 by the reset edge, then 8 again at t = 15 (first clock edge with reset low).reg_4_a(非同步):t = 5 之前為 3,t = 5 的邊緣變成 8,t = 7 被 reset 邊緣清為 0,之後在 t = 15 再度變成 8(reset 已為低的第一個時脈邊緣)。reg_4_a(非同期):t = 5 までは 3、t = 5 のエッジで 8、t = 7 でリセットのエッジにより 0 へクリアされ、t = 15 で再び 8 になる(リセットがローになってから最初のクロックエッジ)。

reg_4_b (sync): no rising clock edge falls inside [7, 12], so the reset is missed: 3 until 5, then 8 at t = 5 and stays 8. This is exactly the slide's caution — the pulse must be longer than one clock period.reg_4_b(同步):[7, 12] 之間沒有任何時脈上升緣,所以這次 reset 被漏掉了:t = 5 之前為 3,t = 5 變成 8 之後一直維持 8。這正是投影片提醒的重點 — 脈衝必須長於一個時脈週期。reg_4_b(同期):[7, 12] の間にクロックの立ち上がりエッジが無いため、このリセットは取りこぼされる。t = 5 までは 3、t = 5 で 8 になり、その後も 8 のままである。これがスライドの注意点そのもので、パルスは 1 クロック周期より長くなければならない。

3. Registered Combinational Logic3. 暫存化的組合邏輯3. レジスタ付き組合せ論理

3.1 Example 1 — registered AND3.1 範例 1 — 暫存化的 AND3.1 例 1 — レジスタ付き AND

module reg_and (a, b, c, clk, y);
  input  a, b, c, clk;
  output y;
  reg    y;

  always @ (posedge clk)
    begin
      y <= a & b & c;
    end
endmodule

The expression becomes a 3-input AND driving the D pin of one DFF.這個運算式變成一個 3 輸入 AND 閘,驅動一個 DFF 的 D 腳。この式は 3 入力 AND となり、1 個の DFF の D 端子を駆動する。

3.2 Example 2 — registered mux3.2 範例 2 — 暫存化的多工器3.2 例 2 — レジスタ付きマルチプレクサ

module mux_reg (a, b, c, d, y, select, clock);
  input  [7:0] a, b, c, d;
  output [7:0] y;
  input  [1:0] select;
  reg    [7:0] y;

  always @ (posedge clock)
    case (select)
      0: y <= a;          // non-blocking
      1: y <= b;          // same result with =
      2: y <= c;
      3: y <= d;
      default y <= 8'bx;
    endcase
endmodule
abcd 0123 selectclock data_inqy 8
Behavior: an 8-bit 4:1 mux in front of 8 DFFs. The synthesized netlist has one mux cell per bit and a shared select decoder.行為:8 個 DFF 前面接一個 8 位元寬的 4:1 多工器。合成後的 netlist 每個位元各有一顆多工器單元,並共用一個 select 解碼器。動作:8 個の DFF の前段に 8 ビット幅の 4:1 マルチプレクサが入る。合成後のネットリストでは 1 ビットあたり 1 個のマルチプレクサ・セルと、共有された select デコーダを持つ。
Why "same result with ="為什麼「用 = 結果相同」なぜ「= でも同じ結果」なのか

There is only one assignment per clock and nobody else in the block reads y, so blocking and non-blocking give the same hardware here. Use <= anyway for clocked logic — it stays correct when more registers are added (Practice 1d).每個時脈只有一次指定,而且區塊內沒有其他地方讀取 y,所以這裡阻擋式與非阻擋式合成出相同的硬體。但時序邏輯仍請一律使用 <= — 日後再加暫存器時才不會出錯(見練習 1d)。クロックごとの代入は 1 回だけで、ブロック内の他の場所で y を読んでいないため、ここではブロッキングでも非ブロッキングでも同じハードウェアになる。それでもクロック同期論理には <= を使うこと。レジスタを追加しても正しいままだからである(練習 1d)。

4. Shift Registers, Barrel Shifter and Load Registers4. 移位暫存器、桶形移位器與載入暫存器4. シフトレジスタ、バレルシフタ、ロードレジスタ

4.1 Shift register4.1 移位暫存器4.1 シフトレジスタ

On every triggering clock edge the register catches the input data.每個觸發的時脈邊緣,暫存器都會擷取輸入資料。トリガとなるクロックエッジごとに、レジスタは入力データを取り込む。

module Shift_reg4 (Data_in, Data_out, clock, reset);
  input       Data_in, clock, reset;
  output      Data_out;
  reg   [3:0] Data_reg;

  assign Data_out = Data_reg[0];

  always @ (negedge reset or posedge clock)
    begin
      if (reset == 1'b0) Data_reg <= 4'b0;            // async, active low
      else               Data_reg <= {Data_in, Data_reg[3:1]};
    end
endmodule

Data enters at bit 3 and shifts right; Data_out is the input delayed by 4 clocks. Four DFFs in a chain, all with asynchronous clear.資料從位元 3 進入並向右移;Data_out 就是延遲 4 個時脈的輸入。四個 DFF 串成一條鏈,全部帶非同步清除。データはビット 3 から入って右へシフトする。Data_out は入力を 4 クロック遅らせたものである。非同期クリア付きの DFF 4 個が直列に並ぶ。

4.2 Shift register with judgement4.2 帶判斷的移位暫存器4.2 判定付きシフトレジスタ

module shifter_1 (Data_in, clock, reset, sig_d, new_signal);
  input  Data_in, clock, reset;
  output sig_d, new_signal;
  reg    sig_a, sig_b, sig_c, sig_d, new_signal;

  always @ (posedge reset or posedge clock)
    begin
      if (reset == 1'b1)
        begin
          sig_a <= 0; sig_b <= 0; sig_c <= 0; sig_d <= 0;
          new_signal <= 0;
        end
      else
        begin
          sig_a <= Data_in;
          sig_b <= sig_a;
          sig_c <= sig_b;
          sig_d <= sig_c;
          new_signal <= (~sig_a) & sig_b;
        end
    end
endmodule

sig_b is the previous value of sig_a, so (~sig_a) & sig_b is 1 when the stream just went 1 → 0: a registered falling-edge detector (inverter + AND + one extra DFF).sig_b 是 sig_a 的前一個值,所以當位元流剛從 1 變 0 時 (~sig_a) & sig_b 為 1:這是一個暫存化的下降緣偵測器(反相器 + AND + 一顆額外的 DFF)。sig_b は sig_a の 1 つ前の値なので、ビット列が 1 → 0 と変化した直後に (~sig_a) & sig_b が 1 になる。すなわちレジスタ付きの立ち下がりエッジ検出器(インバータ + AND + DFF 1 個)である。

4.3 Barrel shifter with loading data4.3 可載入資料的桶形移位器4.3 データロード付きバレルシフタ

module barrel_shifter (Data_out, Data_in, load, clock, reset);
  output [7:0] Data_out;
  input  [7:0] Data_in;
  input        load, clock, reset;
  reg    [7:0] Data_out;

  always @ (posedge reset or posedge clock)
    begin
      if      (reset == 1'b1) Data_out <= 8'b0;
      else if (load  == 1'b1) Data_out <= Data_in;
      else                    Data_out <= {Data_out[6:0], Data_out[7]};  // rotate left
    end
endmodule
Bit位元ビット76543210
Before之前変化前11000110
After 1 clock1 個時脈後1 クロック後10001101

Each bit has a 2:1 mux (load ? Data_in[i] : Data_out[i-1]) in front of a DFF with asynchronous reset.每個位元在帶非同步重置的 DFF 前面都有一個 2:1 多工器(load ? Data_in[i] : Data_out[i-1])。各ビットは、非同期リセット付き DFF の前段に 2:1 マルチプレクサ(load ? Data_in[i] : Data_out[i-1])を持つ。

4.4 Stored register with loading data4.4 可載入資料的儲存暫存器4.4 データロード付き保持レジスタ

module Par_load_reg4 (Data_out, Data_in, load, clock, reset);
  input  [3:0] Data_in;
  input        load, clock, reset;
  output [3:0] Data_out;
  reg    [3:0] Data_out;

  always @ (posedge reset or posedge clock)
    begin
      if      (reset == 1'b1) Data_out <= 4'b0;
      else if (load  == 1'b1) Data_out <= Data_in;
    end
endmodule

No final else — but in a clocked block that is fine: holding the value is what a flip-flop does. The tool adds a feedback mux (or uses an enable flip-flop), not a latch.沒有最後的 else — 但在時序區塊中這沒問題:保持原值本來就是正反器的行為。工具會加上一個回授多工器(或改用帶 enable 的正反器),不會產生閂鎖。最後の else が無いが、クロック同期ブロックではこれで問題ない。値を保持することはフリップフロップ本来の動作だからである。ツールはフィードバック・マルチプレクサを追加する(またはイネーブル付きフリップフロップを使う)のであって、ラッチを作らない。

Contrast with Lecture 4 (Part 2)與第 4 講(下)的對比第 4 講(後半)との対比

A missing else in a combinational block creates an unwanted latch. In an edge-triggered block it simply means "keep the value", which is legal and common (load-enable registers).在組合邏輯區塊中少了 else 會產生不想要的閂鎖;但在邊緣觸發的區塊中,它只是表示「保持原值」,這是合法而且常見的寫法(帶 load enable 的暫存器)。組合せブロックで else を書き忘れると、意図しないラッチができる。しかしエッジトリガのブロックでは単に「値を保持する」という意味にすぎず、これは正当でよく使われる書き方である(ロードイネーブル付きレジスタ)。

Practice 3 — Trace the shifters練習 3 — 追蹤移位器練習 3 — シフタの動作を追う

Problem: (a) Shift_reg4 starts at 0000 after reset; Data_in = 1, 1, 0, 1, 0, 0 on six successive clocks. List Data_reg and Data_out after each clock. (b) For shifter_1 with the same input stream, at which clock does new_signal first become 1? (c) The barrel shifter holds 8'b1100_0110; what does it hold after 3 more clocks with load = 0?題目:(a) Shift_reg4 重置後從 0000 開始;連續六個時脈的 Data_in = 1, 1, 0, 1, 0, 0。請列出每個時脈後的 Data_reg 與 Data_out。(b) 在同樣的輸入序列下,shifter_1 的 new_signal 在第幾個時脈首次變成 1?(c) 桶形移位器目前存著 8'b1100_0110;在 load = 0 之下再經過 3 個時脈後,它存的是什麼?問題:(a) Shift_reg4 はリセット後 0000 から始まる。連続する 6 クロックの Data_in = 1, 1, 0, 1, 0, 0 とする。各クロック後の Data_reg と Data_out を示せ。(b) 同じ入力列に対し、shifter_1 の new_signal が最初に 1 になるのは何クロック目か。(c) バレルシフタが 8'b1100_0110 を保持しているとき、load = 0 のままさらに 3 クロック後の値は何か。

Click to reveal solution點擊展開解答クリックで解答を表示
Clock時脈クロック123456
Data_reg100011000110101101010010
Data_out000110

(b) After clock k, sig_a = input k and sig_b = input k−1, and new_signal is computed from the old sig_a/sig_b. sig_a/sig_b after clocks 1–5: (1,0), (1,1), (0,1), (1,0), (0,1). The first (0,1) is after clock 3, so new_signal = 1 after clock 4 — one clock after the edge is visible in sig_a/sig_b.(b) 第 k 個時脈後,sig_a = 第 k 個輸入、sig_b = 第 k−1 個輸入,而 new_signal 是用舊的 sig_a/sig_b 算出來的。第 1–5 個時脈後的 sig_a/sig_b 為:(1,0)、(1,1)、(0,1)、(1,0)、(0,1)。第一次出現 (0,1) 是在第 3 個時脈之後,所以 new_signal = 1 出現在第 4 個時脈之後 — 比邊緣在 sig_a/sig_b 中顯現晚一個時脈。(b) k クロック目の後、sig_a = k 番目の入力、sig_b = k−1 番目の入力であり、new_signal は更新前の sig_a/sig_b から計算される。クロック 1–5 後の sig_a/sig_b は (1,0)、(1,1)、(0,1)、(1,0)、(0,1) となる。最初の (0,1) はクロック 3 の後なので、new_signal = 1 となるのはクロック 4 の後である。エッジが sig_a/sig_b に現れてから 1 クロック遅れる。

(c) Rotate left 3 = 8'b0011_0110 (1100_0110 → 1000_1101 → 0001_1011 → 0011_0110).(c) 左旋 3 次 = 8'b0011_0110(1100_0110 → 1000_1101 → 0001_1011 → 0011_0110)。(c) 左へ 3 回ローテート = 8'b0011_0110(1100_0110 → 1000_1101 → 0001_1011 → 0011_0110)。

5. Ripple and Ring Counters5. 漣波計數器與環形計數器5. リプルカウンタとリングカウンタ

5.1 Ripple counter5.1 漣波計數器5.1 リプルカウンタ

module ripple_counter (clock, toggle, reset, count);
  input        clock, toggle, reset;
  output [3:0] count;
  reg    [3:0] count;
  wire         c0, c1, c2;

  assign c0 = count[0];
  assign c1 = count[1];
  assign c2 = count[2];

  always @ (posedge reset or posedge clock)
    if (reset == 1'b1) count[0] <= 1'b0; else
    if (toggle == 1'b1) count[0] <= ~count[0];

  always @ (posedge reset or negedge c0)
    if (reset == 1'b1) count[1] <= 1'b0; else
    if (toggle == 1'b1) count[1] <= ~count[1];

  always @ (posedge reset or negedge c1)
    if (reset == 1'b1) count[2] <= 1'b0; else
    if (toggle == 1'b1) count[2] <= ~count[2];

  always @ (posedge reset or negedge c2)
    if (reset == 1'b1) count[3] <= 1'b0; else
    if (toggle == 1'b1) count[3] <= ~count[3];
endmodule

Each stage is a toggle flip-flop clocked by the falling edge of the previous bit, so the count goes up 0, 1, 2, ... 15. The synthesized netlist realizes each T-FF as a DFF with an XOR (toggle ^ Q) at D, and the clock pin of stage i is driven by an inverted count[i-1].每一級都是一個由前一位元下降緣觸發的 toggle 正反器,所以計數值依 0, 1, 2, … 15 遞增。合成後的 netlist 把每個 T-FF 實作成 D 端接 XOR(toggle ^ Q)的 DFF,而第 i 級的時脈腳由反相後的 count[i-1] 驅動。各段は前のビットの立ち下がりエッジでクロックされるトグル・フリップフロップであり、計数値は 0, 1, 2, … 15 と増える。合成後のネットリストでは、各 T-FF は D に XOR(toggle ^ Q)を付けた DFF として実現され、第 i 段のクロック端子は反転した count[i-1] で駆動される。

Design caution設計注意事項設計上の注意

A ripple counter is small, but its bits do not change together (each stage adds a clock-to-Q delay), it creates derived clocks that complicate static timing analysis, and decoding its outputs produces glitches. In synchronous designs use count <= count + 1 on one clock instead.漣波計數器面積小,但各位元不會同時改變(每一級多一段 clock-to-Q 延遲),它會產生衍生時脈而讓靜態時序分析變複雜,而且解碼它的輸出會出現突波。同步設計請改用單一時脈的 count <= count + 1。リプルカウンタは小さいが、各ビットが同時に変化せず(段ごとに clock-to-Q 遅延が加わる)、派生クロックを生むため静的タイミング解析が複雑になり、出力をデコードするとグリッチが出る。同期設計では、単一クロックで count <= count + 1 と書くこと。

5.2 Ring counter5.2 環形計數器5.2 リングカウンタ

module ring_counter (count, enable, clock, reset);
  output [7:0] count;
  input        enable, reset, clock;
  reg    [7:0] count;

  always @ (posedge reset or posedge clock)
    if (reset == 1'b1) count <= 8'b0000_0001; else
    if (enable == 1'b1) count <= {count[6:0], count[7]};   // concatenation operator
endmodule

A single 1 circulates: 0000_0001 → 0000_0010 → ... → 1000_0000 → 0000_0001. Eight states from eight DFFs, each output already one-hot decoded (no decoding glitches). Bit 0 resets to 1, so it needs a flip-flop that is preset rather than cleared.只有一個 1 在循環:0000_0001 → 0000_0010 → … → 1000_0000 → 0000_0001。八個 DFF 給出八個狀態,每個輸出本身就是 one-hot 解碼的結果(沒有解碼突波)。位元 0 重置後為 1,所以它需要的是預設(preset)而不是清除的正反器。1 個の 1 が巡回する:0000_0001 → 0000_0010 → … → 1000_0000 → 0000_0001。8 個の DFF で 8 状態を表し、各出力はそのままワンホットのデコード結果になる(デコードによるグリッチが無い)。ビット 0 はリセット後に 1 なので、クリアではなくプリセットされるフリップフロップが必要になる。

Practice 4 — Counter sequences練習 4 — 計數器的計數序列練習 4 — カウンタの計数列

Problem: (a) In the ripple counter at count = 0111, the next clock edge arrives. List every intermediate value count passes through before it settles. (b) A ring counter and a binary counter both need 8 states; compare FF count and decode logic. (c) What happens to the ring counter if a glitch makes count = 8'b0000_0011?題目:(a) 漣波計數器目前為 count = 0111,下一個時脈邊緣到來。請列出 count 穩定之前經過的每一個中間值。(b) 環形計數器與二進位計數器都需要 8 個狀態;請比較兩者的正反器數量與解碼邏輯。(c) 若一個突波使 count = 8'b0000_0011,環形計數器會變成怎樣?問題:(a) リプルカウンタが count = 0111 のとき、次のクロックエッジが来る。count が安定するまでに通過するすべての中間値を挙げよ。(b) リングカウンタとバイナリカウンタがともに 8 状態を必要とするとき、フリップフロップ数とデコード論理を比較せよ。(c) グリッチによって count = 8'b0000_0011 になった場合、リングカウンタはどうなるか。

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

(a) 0111 → 0110 (bit 0 falls) → 0100 (bit 1 falls) → 0000 (bit 2 falls) → 1000 (bit 3 rises). Three wrong values appear briefly — glitches for any logic decoding count.(a) 0111 → 0110(位元 0 下降)→ 0100(位元 1 下降)→ 0000(位元 2 下降)→ 1000(位元 3 上升)。中間會短暫出現三個錯誤值 — 對任何解碼 count 的邏輯而言就是突波。(a) 0111 → 0110(ビット 0 が下がる)→ 0100(ビット 1 が下がる)→ 0000(ビット 2 が下がる)→ 1000(ビット 3 が上がる)。誤った値が 3 つ、ごく短時間現れる。count をデコードする論理にとってはグリッチである。

(b) Ring: 8 FFs, no decoder. Binary: 3 FFs plus an incrementer and a 3:8 decoder if one-hot outputs are needed.(b) 環形:8 個正反器,不需要解碼器。二進位:3 個正反器再加一個遞增器;若需要 one-hot 輸出,還要一個 3:8 解碼器。(b) リング:フリップフロップ 8 個、デコーダ不要。バイナリ:フリップフロップ 3 個に加えてインクリメンタが必要で、ワンホット出力が要るなら 3:8 デコーダも要る。

(c) The pattern with two 1s just rotates forever; a plain ring counter is not self-correcting. Only reset recovers it.(c) 有兩個 1 的樣式會一直旋轉下去;單純的環形計數器沒有自我修正能力,只有 reset 才能救回來。(c) 1 が 2 個あるパターンはそのまま回り続ける。素のリングカウンタは自己修正しないので、reset でしか復帰できない。

6. Pipelined 16-bit Adder6. 管線化的 16 位元加法器6. パイプライン化 16 ビット加算器

6.1 Serial connection of two 8-bit adders6.1 兩個 8 位元加法器的串接6.1 8 ビット加算器 2 個の直列接続

Two 8-bit adders chained through the carry form a 16-bit adder. The carry ripples through both, so the critical path is too long → use a pipelined design.兩個 8 位元加法器透過進位串接就構成一個 16 位元加法器。進位要漣波通過兩級,關鍵路徑太長 → 改用管線化設計。8 ビット加算器 2 個をキャリーで連結すると 16 ビット加算器になる。キャリーが両方を伝播するためクリティカルパスが長すぎる → パイプライン構成にする。

6.2 Pipelined design6.2 管線化設計6.2 パイプライン構成

b[15:8]a[15:8]b[7:0]a[7:0]c_in Input register IR[32:0]輸入暫存器 IR[32:0]入力レジスタ IR[32:0] b[15:8]a[15:8]PR[8] carryPR[8] 進位PR[8] キャリーPR[7:0] = sum[7:0] Pipeline reg PR[24:0]管線暫存器 PR[24:0]パイプライン・レジスタ PR[24:0] OR[16] = c_out, OR[15:0] = sum Output reg OR[16:0]輸出暫存器 OR[16:0]出力レジスタ OR[16:0] 8-bit add (low)8 位元加法(低位)8 ビット加算(下位) 8-bit add (high)8 位元加法(高位)8 ビット加算(上位) {c_out, sum[15:0]}
Stage 1 adds the low bytes with c_in while the high bytes wait in PR; stage 2 adds the high bytes with the stored carry PR[8]. Each stage contains only one 8-bit adder.第一級把低位元組和 c_in 相加,同時高位元組在 PR 中等待;第二級把高位元組與存下來的進位 PR[8] 相加。每一級只含一個 8 位元加法器。第 1 段は下位バイトと c_in を加算し、その間に上位バイトは PR で待機する。第 2 段は上位バイトと保存されたキャリー PR[8] を加算する。各段には 8 ビット加算器が 1 個しか含まれない。
module add_16_pipe (c_out, sum, a, b, c_in, clock);
  parameter size   = 16;
  parameter half   = size / 2;      // 8
  parameter double = 2 * size;      // 32
  parameter triple = 3 * half;      // 24
  parameter size1  = half - 1;      // 7
  parameter size2  = size - 1;      // 15
  parameter size3  = half + 1;      // 9
  parameter R1 = 1;                 // 1
  parameter L1 = half;              // 8
  parameter R2 = size3;             // 9
  parameter L2 = size;              // 16
  parameter R3 = size + 1;          // 17
  parameter L3 = size + half;       // 24
  parameter R4 = double - half + 1; // 25
  parameter L4 = double;            // 32

  input  [size2:0]  a, b;
  input             c_in, clock;
  output [size2:0]  sum;
  output            c_out;
  reg    [double:0] IR;
  reg    [triple:0] PR;
  reg    [size:0]   OR;

  assign {c_out, sum} = OR;

  always @ (posedge clock) begin
    // Load input register
    IR[0]     <= c_in;
    IR[L1:R1] <= a[size1:0];
    IR[L2:R2] <= b[size1:0];
    IR[L3:R3] <= a[size2:half];
    IR[L4:R4] <= b[size2:half];

    // Load pipeline register
    PR[L3:R3]  <= IR[L4:R4];
    PR[L2:R2]  <= IR[L3:R3];
    PR[half:0] <= IR[L2:R2] + IR[L1:R1] + IR[0];

    // Load output register
    OR <= {{1'b0, PR[L3:R3]} + {1'b0, PR[L2:R2]} + PR[half], PR[size1:0]};
  end
endmodule
About the two 1'b0關於那兩個 1'b02 つの 1'b0 について

The slide says "both 1'b0 should be removed". Be careful: operands inside a concatenation { ... } are self-determined in Verilog, so without the zero extension the upper sum is only 8 bits wide and the carry into OR[16] (c_out) is lost. Either keep {1'b0, ...} as above, or compute the 9-bit upper sum in its own assignment, e.g. OR[size:half] <= PR[L3:R3] + PR[L2:R2] + PR[half]; where the 9-bit target widens the addition.投影片寫著「兩個 1'b0 都應該拿掉」。但請小心:在 Verilog 中,串接 { ... } 裡的運算元是自定寬度(self-determined)的,所以少了零擴展,高位的和只有 8 位元寬,進到 OR[16](c_out)的進位就不見了。要嘛保留上面的 {1'b0, ...},要嘛把 9 位元的高位加法寫成獨立的指定,例如 OR[size:half] <= PR[L3:R3] + PR[L2:R2] + PR[half];,由 9 位元的目標來放寬加法的寬度。スライドには「2 つの 1'b0 は削除すべき」とある。しかし注意が必要である。Verilog では連接 { ... } の中のオペランドは自己決定(self-determined)幅になるため、ゼロ拡張を外すと上位の和は 8 ビット幅しかなく、OR[16](c_out)へのキャリーが失われる。上のように {1'b0, ...} を残すか、9 ビットの上位加算を独立した代入として書く。たとえば OR[size:half] <= PR[L3:R3] + PR[L2:R2] + PR[half]; とすれば、9 ビットの代入先が加算の幅を広げる。

Hardware reuse and throughput硬體重複使用與吞吐量ハードウェアの再利用とスループット

The clock period is set by one 8-bit adder instead of the full 16-bit carry chain. A new pair of operands enters every clock (throughput 1 per cycle) and each result leaves 3 clocks after its inputs are presented (IR → PR → OR).時脈週期由單一個 8 位元加法器決定,而不是完整的 16 位元進位鏈。每個時脈都可以送入一對新的運算元(吞吐量為每週期 1 筆),而每筆結果在輸入進來之後 3 個時脈才輸出(IR → PR → OR)。クロック周期を決めるのは 16 ビット全体のキャリーチェーンではなく、8 ビット加算器 1 個である。オペランドの組は毎クロック投入でき(スループットは 1 サイクルあたり 1 組)、各結果は入力が与えられてから 3 クロック後に出てくる(IR → PR → OR)。

Practice 5 — Pipeline timing練習 5 — 管線的時序練習 5 — パイプラインのタイミング

Problem: Inputs (a, b, c_in) = (16'h00FF, 16'h0001, 0) at clock edge 1 and (16'hFFFF, 16'h0001, 0) at edge 2. (a) Give PR after edge 2 and OR after edge 3. (b) When does the second result appear and what is it? (c) If an 8-bit adder takes 4 ns and a register adds 1 ns, compare the max clock frequency with the non-pipelined 16-bit adder (two chained 8-bit adders, one register stage).題目:在第 1 個時脈邊緣輸入 (a, b, c_in) = (16'h00FF, 16'h0001, 0),第 2 個邊緣輸入 (16'hFFFF, 16'h0001, 0)。(a) 寫出第 2 個邊緣後的 PR 與第 3 個邊緣後的 OR。(b) 第二筆結果何時出現?值是多少?(c) 若一個 8 位元加法器需要 4 ns、一級暫存器再加 1 ns,請與未管線化的 16 位元加法器(兩個串接的 8 位元加法器、一級暫存器)比較最高時脈頻率。問題:クロックエッジ 1 で (a, b, c_in) = (16'h00FF, 16'h0001, 0)、エッジ 2 で (16'hFFFF, 16'h0001, 0) を入力する。(a) エッジ 2 後の PR とエッジ 3 後の OR を示せ。(b) 2 番目の結果はいつ現れ、値はいくつか。(c) 8 ビット加算器が 4 ns、レジスタが 1 ns を加えるとして、パイプライン化していない 16 ビット加算器(8 ビット加算器 2 個を直列、レジスタ 1 段)と最大クロック周波数を比較せよ。

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

(a) After edge 2: low sum FF + 01 + 0 = 1_00 → PR[8] = 1, PR[7:0] = 8'h00; PR[24:17] = 8'h00 (b high), PR[16:9] = 8'h00 (a high). After edge 3: upper = 00 + 00 + 1 = 9'h001 → {c_out, sum} = 17'h0_0100, i.e. 0x00FF + 0x0001 = 0x0100. ✔(a) 第 2 個邊緣後:低位和 FF + 01 + 0 = 1_00 → PR[8] = 1、PR[7:0] = 8'h00;PR[24:17] = 8'h00(b 的高位元組)、PR[16:9] = 8'h00(a 的高位元組)。第 3 個邊緣後:高位 = 00 + 00 + 1 = 9'h001 → {c_out, sum} = 17'h0_0100,即 0x00FF + 0x0001 = 0x0100。✔(a) エッジ 2 の後:下位の和は FF + 01 + 0 = 1_00 → PR[8] = 1、PR[7:0] = 8'h00。PR[24:17] = 8'h00(b の上位)、PR[16:9] = 8'h00(a の上位)。エッジ 3 の後:上位 = 00 + 00 + 1 = 9'h001 → {c_out, sum} = 17'h0_0100、すなわち 0x00FF + 0x0001 = 0x0100。✔

(b) After edge 4: FFFF + 0001 = {c_out, sum} = {1, 16'h0000}.(b) 在第 4 個邊緣後:FFFF + 0001 = {c_out, sum} = {1, 16'h0000}。(b) エッジ 4 の後:FFFF + 0001 = {c_out, sum} = {1, 16'h0000}。

(c) Pipelined: 4 + 1 = 5 ns → 200 MHz. Non-pipelined: 8 + 1 = 9 ns → ≈111 MHz. Each result now takes more clock cycles to come out (latency), but a new result still leaves every cycle and the clock is almost twice as fast.(c) 管線化:4 + 1 = 5 ns → 200 MHz。未管線化:8 + 1 = 9 ns → 約 111 MHz。現在每筆結果要多等幾個時脈週期才出來(延遲變大),但每個週期仍然輸出一筆結果,而且時脈快了將近一倍。(c) パイプライン化:4 + 1 = 5 ns → 200 MHz。非パイプライン:8 + 1 = 9 ns → 約 111 MHz。1 つの結果が出るまでのクロック数(レイテンシ)は増えるが、結果は毎サイクル出続け、クロックは約 2 倍速くなる。

7. Finite State Machines7. 有限狀態機7. 有限状態機械

7.1 Developing the logic of an FSM7.1 發展 FSM 的邏輯7.1 FSM の論理を組み立てる

Recommendations建議做法推奨される書き方
  • Use separate behaviors for the state register (clocked) and the next-state logic (combinational).狀態暫存器(時序)與次態邏輯(組合)請用分開的行為區塊撰寫。状態レジスタ(クロック同期)と次状態論理(組合せ)は別々のビヘイビアで書く。
  • Use non-blocking assignments for the state register — they are order-independent.狀態暫存器請使用非阻擋式指定 — 它與敘述的順序無關。状態レジスタには非ブロッキング代入を使う。記述順序に依存しないからである。
  • Never mix blocking and non-blocking assignments to the same variable in the same behavior.絕對不要在同一個行為區塊中,對同一個變數混用阻擋式與非阻擋式指定。同一のビヘイビア内で、同じ変数にブロッキング代入と非ブロッキング代入を混在させてはならない。

7.2 Example: sequence detector7.2 範例:序列偵測器7.2 例:系列検出器

Type類型種類Output depends on輸出取決於出力が依存するものDiagram labels狀態圖的標示状態図のラベル
Mealycurrent state and input目前狀態與輸入現在の状態と入力Each arc: input/output每條弧:input/output各遷移:input/output
Moore (better)Moore(較佳)Moore(こちらが良い)current state only只有目前狀態現在の状態のみEach node: state / output每個節點:state / output各ノード:state / output
State狀態状態Code編碼コードMeaning意義意味
start_state3'b000After reset, nothing read重置後,尚未讀入任何位元リセット直後、まだ何も読んでいない
read_1_zero3'b001Last bit 0 (first 0)最後一個位元是 0(第一個 0)直前のビットが 0(最初の 0)
read_1_one3'b010Last bit 1 (first 1)最後一個位元是 1(第一個 1)直前のビットが 1(最初の 1)
read_2_zero3'b011Last two bits 00最後兩個位元是 00直前の 2 ビットが 00
read_2_one3'b100Last two bits 11最後兩個位元是 11直前の 2 ビットが 11

7.3 FSM type 1: Mealy machine7.3 FSM 型式一:Mealy 機7.3 FSM その 1:Mealy 機械

start_stateread_1_zeroread_1_oneread_2_zeroread_2_one 0/01/0 1/00/0 0/11/1 1/00/0 0/11/1 reset
Mealy state diagram: each arc is labeled input/output. The output is 1 only on an arc that completes a pair of equal bits.Mealy 狀態圖:每條弧都標示 input/output。只有在完成一對相同位元的弧上,輸出才是 1。Mealy の状態図:各遷移に input/output が付く。出力が 1 になるのは、等しいビットの対を完成させる遷移だけである。
module seq_det_mealy_1exp (clock, reset, in_bit, out_bit);
  input       clock, reset, in_bit;
  output      out_bit;
  reg   [2:0] state_reg, next_state;
  parameter start_state = 3'b000;
  parameter read_1_zero = 3'b001;
  parameter read_1_one  = 3'b010;
  parameter read_2_zero = 3'b011;
  parameter read_2_one  = 3'b100;

  always @ (posedge clock or posedge reset)
    if (reset == 1) state_reg <= start_state; else state_reg <= next_state;

  always @ (state_reg or in_bit)
    case (state_reg)
      start_state: if (in_bit == 0) next_state = read_1_zero; else
                   if (in_bit == 1) next_state = read_1_one;  else
                                    next_state = start_state;
      read_1_zero: if (in_bit == 0) next_state = read_2_zero; else
                   if (in_bit == 1) next_state = read_1_one;  else
                                    next_state = start_state;
      read_2_zero: if (in_bit == 0) next_state = read_2_zero; else
                   if (in_bit == 1) next_state = read_1_one;  else
                                    next_state = start_state;
      read_1_one:  if (in_bit == 0) next_state = read_1_zero; else
                   if (in_bit == 1) next_state = read_2_one;  else
                                    next_state = start_state;
      read_2_one:  if (in_bit == 0) next_state = read_1_zero; else
                   if (in_bit == 1) next_state = read_2_one;  else
                                    next_state = start_state;
      default:                      next_state = start_state;
    endcase

  assign out_bit = (((state_reg == read_1_zero) || (state_reg == read_2_zero)) && (in_bit == 0)) ||
                   (((state_reg == read_1_one)  || (state_reg == read_2_one))  && (in_bit == 1))
                   ? 1 : 0;
endmodule

Separate clocked state register and combinational next-state block, a complete case with default, and the output computed from state and in_bit. The final else branches only matter when in_bit is x/z in simulation.時序的狀態暫存器與組合的次態區塊分開寫、case 完整並附 default,而輸出由狀態與 in_bit 共同決定。最後那些 else 分支只有在模擬中 in_bit 為 x/z 時才會用到。クロック同期の状態レジスタと組合せの次状態ブロックを分け、case は default 付きで完全にし、出力は状態と in_bit から計算する。最後の else 分岐が意味を持つのは、シミュレーションで in_bit が x/z のときだけである。

Simulation: in_bit = 0011_1000_1 (left first)模擬:in_bit = 0011_1000_1(最左邊先進入)シミュレーション:in_bit = 0011_1000_1(左から順に入力)

Rising edge上升緣立ち上がりエッジ123456789
in_bit sampled取樣到的 in_bitサンプルされた in_bit001110001
state_reg after之後的 state_regその後の state_reg132441332

out_bit is high while the state is 1 or 3 and the input is 0, or while the state is 2 or 4 and the input is 1 — i.e. during the bit periods where the second, third, ... equal bit is present at the input, before the clock edge that reads it.當狀態為 1 或 3 且輸入為 0,或狀態為 2 或 4 且輸入為 1 時,out_bit 為高 — 也就是在第二個、第三個……相同位元出現在輸入端的那段位元期間,早於讀取它的那個時脈邊緣。状態が 1 または 3 で入力が 0 のとき、あるいは状態が 2 または 4 で入力が 1 のとき、out_bit はハイになる。つまり 2 番目、3 番目…と続く等しいビットが入力に現れているビット期間であり、それを読み込むクロックエッジより前である。

7.4 FSM type 2: Moore machine7.4 FSM 型式二:Moore 機7.4 FSM その 2:Moore 機械

TSG input輸入入力output輸出出力 next_statestate transition logic轉移邏輯遷移論理state memory狀態記憶状態メモリoutput logic輸出邏輯出力論理 clockreset current_state
Moore structure: the input never reaches the output directly, so the output changes only after a clock edge.Moore 結構:輸入不會直接到達輸出,所以輸出只在時脈邊緣之後才改變。Moore の構成:入力が直接出力に届かないため、出力はクロックエッジの後にしか変化しない。

State diagram: the same five states and transitions, with node outputs start_state/0, read_1_zero/0, read_1_one/0, read_2_zero/1, read_2_one/1.狀態圖:五個狀態與轉移都相同,節點輸出為 start_state/0、read_1_zero/0、read_1_one/0、read_2_zero/1、read_2_one/1。状態図:5 つの状態と遷移は同じで、ノードの出力は start_state/0、read_1_zero/0、read_1_one/0、read_2_zero/1、read_2_one/1 となる。

Approach I — explicit FSM方法一 — 明確式 FSM方法 I — 明示的 FSM

module seq_det_moore_1exp (clock, reset, in_bit, out_bit);
  ... // declarations identical to seq_det_mealy_1exp

  always @ (posedge clock or posedge reset)
    if (reset == 1) state_reg <= start_state; else state_reg <= next_state;

  always @ (state_reg or in_bit)
    case (state_reg)
      ... // next-state logic identical to the Mealy machine
    endcase

  assign out_bit = ((state_reg == read_2_zero) || (state_reg == read_2_one)) ? 1 : 0;
endmodule

The state sequence is identical to the Mealy machine; only the output differs. out_bit_moore rises after the clock edge that enters read_2_zero/read_2_one and lasts whole clock periods, whereas out_bit_mealy rises as soon as the matching input appears (half a cycle earlier with this test bench).狀態序列與 Mealy 機完全相同,只有輸出不同。out_bit_moore 在進入 read_2_zero/read_2_one 的那個時脈邊緣之後才拉高,並維持整個時脈週期;而 out_bit_mealy 在相符的輸入一出現就拉高(在這個測試平台中早了半個週期)。状態の並びは Mealy 機械と同一で、異なるのは出力だけである。out_bit_moore は read_2_zero/read_2_one に入るクロックエッジの後に立ち上がり、クロック周期ぶんだけ持続する。一方 out_bit_mealy は一致する入力が現れた時点で立ち上がる(このテストベンチでは半周期早い)。

Why Moore is "better" here為什麼這裡 Moore「比較好」ここで Moore が「良い」理由

The Moore output is a function of flip-flops only: glitch-free, aligned to the clock, and it does not create a combinational path from input to output. The Mealy output reacts one cycle earlier but carries any input glitch straight through.Moore 的輸出只是正反器的函數:沒有突波、與時脈對齊,也不會產生從輸入到輸出的組合路徑。Mealy 的輸出早一個週期反應,但輸入端的任何突波都會直接傳到輸出。Moore の出力はフリップフロップだけの関数である。グリッチが無く、クロックに揃い、入力から出力への組合せパスも作らない。Mealy の出力は 1 サイクル早く応答するが、入力のグリッチをそのまま通してしまう。

7.5 Approach II — implicit state machine7.5 方法二 — 隱含式狀態機7.5 方法 II — 暗黙的状態機械 Un-synthesized無法合成合成不可

module seq_det_mealy_1imp (clock, reset, in_bit, out_bit);
  input  clock, reset, in_bit;
  output out_bit;
  reg    last_bit, this_bit, flag;
  wire   out_bit;

  always begin: wrapper_for_synthesis
    @ (posedge clock /* or posedge reset */) begin: machine
      if (reset == 1) begin
        last_bit = 0;
        this_bit = 0;
        flag     = 0;
        disable machine; end
      else begin                                            // 1
        last_bit = this_bit;
        this_bit = in_bit;
        forever
          @ (posedge clock /* or posedge reset */) begin   // 2
            if (reset == 1) begin
              last_bit = 0;
              this_bit = 0;
              flag     = 0;
              disable machine; end
            else begin
              last_bit = this_bit;
              this_bit = in_bit;
              flag     = 1; end
          end                                               // 2
      end                                                   // 1
    end    // machine
  end      // wrapper_for_synthesis

  assign out_bit = (flag && (this_bit == last_bit) && (this_bit == in_bit));
endmodule

7.6 Various-way state encoding7.6 各種狀態編碼方式7.6 さまざまな状態符号化

#Binary二進位バイナリOne-hotOne-hotワンホットGray格雷碼グレイJohnsonJohnsonジョンソン
000000000000000000001000000000000
100010000000000000010000100000001
200100000000000000100001100000011
300110000000000001000001000000111
401000000000000010000011000001111
501010000000000100000011100011111
601100000000001000000010100111111
701110000000010000000010001111111
810000000000100000000110011111111
910010000001000000000110111111110
1010100000010000000000111111111100
1110110000100000000000111011111000
1211000001000000000000101011110000
1311010010000000000000101111100000
1411100100000000000000100111000000
1511111000000000000000100010000000
Encoding編碼方式符号化方式FFs for N statesN 個狀態所需的 FF 數N 状態に必要な FF 数Property特性特徴
Binary二進位バイナリ$\lceil \log_2 N \rceil$Fewest FFs; more next-state and decode logicFF 數最少;次態與解碼邏輯較多FF 数は最少。次状態論理とデコード論理は増える
One-hotOne-hotワンホット$N$Simplest, fastest logic (one bit per state); common in FPGAs邏輯最簡單、最快(一個狀態一個位元);在 FPGA 中很常用論理が最も単純で高速(1 状態 1 ビット)。FPGA でよく使われる
Gray格雷碼グレイ$\lceil \log_2 N \rceil$One bit changes per step: low power, safe for sequential transitions and clock-domain crossing每一步只變一個位元:低功耗,適合連續的狀態轉移與跨時脈域1 ステップで 1 ビットしか変化しない。低消費電力で、順次遷移やクロックドメイン間の受け渡しに安全
JohnsonJohnsonジョンソン$\lceil N/2 \rceil$Twisted ring; one bit changes per step, glitch-free 2-input decode扭環式;每一步只變一個位元,用 2 個輸入即可無突波解碼ツイストリング。1 ステップで 1 ビットのみ変化し、2 入力でグリッチ無くデコードできる
Key points — click to expand重點整理(點擊展開)要点(クリックで展開)
  • Mealy: output = f(state, input), labeled on the arcs. It reacts one cycle earlier, but noise on the input passes straight through to the output.Mealy:輸出 = f(狀態, 輸入),標在箭頭上,反應快一個週期,但輸入的雜訊會直接傳到輸出。Mealy:出力 = f(状態, 入力) で、遷移の矢印に記す。応答は 1 サイクル早いが、入力のノイズがそのまま出力に伝わる。
  • Moore: output = f(state), labeled on the nodes. The output changes only after a clock edge, which is cleaner and easier to analyze for timing.Moore:輸出 = f(狀態),標在節點上,輸出只在時脈後改變,較乾淨、易於時序分析。Moore:出力 = f(状態) で、ノードに記す。出力はクロックの後にしか変化しないため、波形がきれいでタイミング解析も容易である。
  • Recommended FSM style: write the state register (clocked, non-blocking) and the next-state logic (combinational, a complete case plus default) as separate blocks.FSM 建議寫法:狀態暫存器(時序、非阻擋)與次態邏輯(組合、完整 case + default)分開寫。FSM の推奨スタイル:状態レジスタ(クロック同期・非ブロッキング)と次状態論理(組合せ・default を含む完全な case)を別々のブロックに書く。
  • State encoding: binary uses the fewest FFs; one-hot gives the simplest and fastest logic; Gray and Johnson change only one bit per step.狀態編碼:Binary 最省 FF;One-hot 邏輯最簡單最快;Gray / Johnson 每次只變一個位元。状態符号化:バイナリは FF が最少、ワンホットは論理が最も単純で高速、グレイとジョンソンは 1 ステップで 1 ビットしか変化しない。
Practice 6 — Mealy vs Moore trace練習 6 — Mealy 與 Moore 的追蹤練習 6 — Mealy と Moore の追跡

Problem: After reset, in_bit = 1, 0, 1, 1, 0, 0 is sampled at rising edges 1–6 (each value is applied half a cycle before its edge). (a) Give state_reg after each edge. (b) In which bit periods is out_bit_mealy high? (c) After which edges is out_bit_moore high?題目:重置之後,in_bit = 1, 0, 1, 1, 0, 0 於第 1–6 個上升緣被取樣(每個值都在它的邊緣前半個週期施加)。(a) 寫出每個邊緣後的 state_reg。(b) out_bit_mealy 在哪些位元期間為高?(c) out_bit_moore 在哪些邊緣之後為高?問題:リセット後、in_bit = 1, 0, 1, 1, 0, 0 を立ち上がりエッジ 1–6 でサンプルする(各値はそのエッジの半周期前に与えられる)。(a) 各エッジ後の state_reg を示せ。(b) out_bit_mealy がハイになるビット期間はどれか。(c) out_bit_moore がハイになるのはどのエッジの後か。

Click to reveal solution點擊展開解答クリックで解答を表示
Edge邊緣エッジ123456
in_bit101100
state after之後的狀態遷移後の状態read_1_oneread_1_zeroread_1_oneread_2_oneread_1_zeroread_2_zero

(b) Mealy is high while the presented bit equals the stored previous bit: during the periods of input 4 (state read_1_one, in = 1) and input 6 (state read_1_zero, in = 0).(b) 當送入的位元與已儲存的前一個位元相同時 Mealy 為高:也就是第 4 個輸入(狀態 read_1_one,in = 1)與第 6 個輸入(狀態 read_1_zero,in = 0)的位元期間。(b) 提示されたビットが保持している直前のビットと等しい間、Mealy はハイになる。すなわち 4 番目の入力(状態 read_1_one、in = 1)と 6 番目の入力(状態 read_1_zero、in = 0)の期間である。

(c) Moore is high for one cycle after edge 4 (read_2_one) and after edge 6 (read_2_zero). Same detections, each delayed to the clock edge.(c) Moore 在第 4 個邊緣(read_2_one)之後與第 6 個邊緣(read_2_zero)之後各維持一個週期為高。偵測到的事件相同,只是都被延到時脈邊緣。(c) Moore はエッジ 4(read_2_one)の後とエッジ 6(read_2_zero)の後に 1 サイクルずつハイになる。検出する事象は同じで、どちらもクロックエッジまで遅れるだけである。

Practice 7 — Encoding cost練習 7 — 編碼的成本練習 7 — 符号化のコスト

Problem: The sequence detector has 5 states. How many flip-flops does each encoding need? Write the one-hot parameter list.題目:這個序列偵測器有 5 個狀態。每一種編碼各需要幾個正反器?並寫出 one-hot 的 parameter 宣告。問題:この系列検出器は 5 状態である。各符号化に必要なフリップフロップ数はいくつか。またワンホットの parameter 宣言を書け。

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

Binary 3, Gray 3, Johnson 3 (3 FFs give 6 Johnson states), one-hot 5.二進位 3 個、格雷碼 3 個、Johnson 3 個(3 個 FF 可得 6 個 Johnson 狀態)、one-hot 5 個。バイナリ 3 個、グレイ 3 個、ジョンソン 3 個(FF 3 個でジョンソン状態は 6 個得られる)、ワンホット 5 個。

parameter start_state = 5'b00001;
parameter read_1_zero = 5'b00010;
parameter read_1_one  = 5'b00100;
parameter read_2_zero = 5'b01000;
parameter read_2_one  = 5'b10000;

With one-hot the Moore output is just state_reg[3] | state_reg[4].採用 one-hot 時,Moore 的輸出就只是 state_reg[3] | state_reg[4]。ワンホットなら、Moore の出力は state_reg[3] | state_reg[4] だけで済む。

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

FF inference正反器推論FF の推論
  • Assigned in an edge-triggered block → DFF.在邊緣觸發的區塊中被指定 → DFF。エッジトリガのブロック内で代入される → DFF。
  • Written-then-read temp → wire.先寫後讀的暫時變數 → 連線。先に書いてから読む一時変数 → 配線。
  • Clocked logic: <=.時序邏輯請用 <=。クロック同期論理には <= を使う。
Reset重置リセット
  • Async: edge in event list, any pulse width.非同步:邊緣寫進事件列表,脈衝寬度不限。非同期:イベントリストにエッジを書く。パルス幅は任意。
  • Sync: clock only, pulse > 1 period.同步:事件列表只有時脈,脈衝要 > 1 個週期。同期:クロックのみ。パルスは 1 周期より長く。
  • if first; last branch = clocked action.if 要在最前面;最後一個分支 = 同步動作。if を最初に置く。最後の分岐 = クロック動作。
Registers暫存器レジスタ
  • Shift: {in, r[n-1:1]}.移位:{in, r[n-1:1]}。シフト:{in, r[n-1:1]}。
  • Rotate: {r[6:0], r[7]}.旋轉:{r[6:0], r[7]}。ローテート:{r[6:0], r[7]}。
  • Missing else in clocked block = hold, not latch.時序區塊缺少 else = 保持原值,不是閂鎖。クロック同期ブロックで else が無い = 保持であり、ラッチではない。
Counters計數器カウンタ
  • Ripple: derived clocks, glitches — avoid.漣波:衍生時脈、突波 — 應避免。リプル:派生クロックとグリッチ — 避ける。
  • Ring: one-hot, N FFs, not self-correcting.環形:one-hot、N 個 FF,不會自我修正。リング:ワンホット、FF は N 個、自己修正しない。
Pipelining管線化パイプライン化
  • Split the carry chain with registers.用暫存器把進位鏈切開。レジスタでキャリーチェーンを分割する。
  • Shorter period, higher throughput, more latency.週期更短、吞吐量更高、延遲更長。周期は短く、スループットは高く、レイテンシは増える。
  • Concatenation operands are self-determined.串接中的運算元是自定寬度的。連接のオペランドは自己決定幅になる。
FSM
  • Mealy: f(state, input). Moore: f(state).Mealy:f(狀態, 輸入)。Moore:f(狀態)。Mealy:f(状態, 入力)。Moore:f(状態)。
  • Separate state register and next-state logic.狀態暫存器與次態邏輯要分開寫。状態レジスタと次状態論理を分けて書く。
  • Binary / one-hot / Gray / Johnson trade-offs.Binary/one-hot/Gray/Johnson 之間的取捨。バイナリ/ワンホット/グレイ/ジョンソンのトレードオフ。
FSM templateFSM 範本FSM のテンプレート
always @ (posedge clock or posedge reset)      // state register
  if (reset) state_reg <= S0;
  else       state_reg <= next_state;

always @*                                     // next-state logic
  begin
    next_state = state_reg;                   // default: stay
    case (state_reg)
      ...
      default: next_state = S0;
    endcase
  end

assign out = (state_reg == S_DETECT);         // Moore output