Flip-flop inference, synchronous and asynchronous reset, shift registers, counters, pipelining and Mealy / Moore finite state machines正反器推論、同步與非同步重置、移位暫存器、計數器、管線化,以及 Mealy / Moore 有限狀態機 — 序向邏輯合成自學指南フリップフロップの推論、同期・非同期リセット、シフトレジスタ、カウンタ、パイプライン化、Mealy / Moore 有限状態機械 — 順序回路合成の学習ガイド
A register variable in a behavior is synthesized as an edge-triggered flip-flop when行為描述中的暫存變數(reg)在下列情況下會被合成成邊緣觸發正反器:ビヘイビア記述中のレジスタ変数は、次の条件を満たすときエッジトリガ・フリップフロップとして合成される。
always @(posedge clk) or negedge), and它與時脈行為對齊(在 always @(posedge clk) 或 negedge 中被指定),且クロック動作に同期していること(always @(posedge clk) または negedge の中で代入されること)、かつ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} | 00 | 01 | 10 | 11 |
|---|---|---|---|---|
D of data_adata_a 的 Ddata_a の D | data_b | 0 | 1 | 1 |
D of data_bdata_b 的 Ddata_b の D | data_a | 1 | 0 | 0 |
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)にまとめられる。
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
(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 つの名前すべてを駆動する。シフトレジスタのつもりで書いたときの典型的なバグである。
If the event control expression is sensitive to the edge of more than one signal:若事件控制運算式對一個以上訊號的邊緣敏感:イベント制御式が複数の信号のエッジに感応する場合:
if statement must be the first statement in the behavior;行為中的第一個敘述必須是 if 敘述;ビヘイビアの最初の文は if 文でなければならない。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
endmodulemodule 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 reset | posedge 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 クロック周期より長いこと |
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 のクリア端子に接続され、即座に作用し、パルス幅は任意でよい。if, and the final else branch is the synchronous (clocked) action — never test if (clock) yourself.多個邊緣敏感時,第一個敘述必須是 if,最後的 else 分支就是同步(時脈)動作,不要再寫 if (clock)。複数のエッジに感応する場合、最初の文は if でなければならず、最後の else 分岐が同期(クロック)動作になる。if (clock) を自分で書いてはいけない。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 を示せ。
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 クロック周期より長くなければならない。
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 端子を駆動する。
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
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)。
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 個が直列に並ぶ。
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 個)である。
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位元ビット | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|
| Before之前変化前 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 |
| After 1 clock1 個時脈後1 クロック後 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
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])を持つ。
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 が無いが、クロック同期ブロックではこれで問題ない。値を保持することはフリップフロップ本来の動作だからである。ツールはフィードバック・マルチプレクサを追加する(またはイネーブル付きフリップフロップを使う)のであって、ラッチを作らない。
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 を書き忘れると、意図しないラッチができる。しかしエッジトリガのブロックでは単に「値を保持する」という意味にすぎず、これは正当でよく使われる書き方である(ロードイネーブル付きレジスタ)。
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 クロック後の値は何か。
| Clock時脈クロック | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| Data_reg | 1000 | 1100 | 0110 | 1011 | 0101 | 0010 |
| Data_out | 0 | 0 | 0 | 1 | 1 | 0 |
(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)。
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] で駆動される。
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 と書くこと。
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 なので、クリアではなくプリセットされるフリップフロップが必要になる。
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 になった場合、リングカウンタはどうなるか。
(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 でしか復帰できない。
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 ビット加算器になる。キャリーが両方を伝播するためクリティカルパスが長すぎる → パイプライン構成にする。
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
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 ビットの代入先が加算の幅を広げる。
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)。
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 段)と最大クロック周波数を比較せよ。
(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 倍速くなる。
default).確保描述是完整的(每個狀態、每個輸入,再加上 default)。記述が完全であることを確かめる(すべての状態、すべての入力、そして default)。| Type類型種類 | Output depends on輸出取決於出力が依存するもの | Diagram labels狀態圖的標示状態図のラベル |
|---|---|---|
| Mealy | current 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_state | 3'b000 | After reset, nothing read重置後,尚未讀入任何位元リセット直後、まだ何も読んでいない |
read_1_zero | 3'b001 | Last bit 0 (first 0)最後一個位元是 0(第一個 0)直前のビットが 0(最初の 0) |
read_1_one | 3'b010 | Last bit 1 (first 1)最後一個位元是 1(第一個 1)直前のビットが 1(最初の 1) |
read_2_zero | 3'b011 | Last two bits 00最後兩個位元是 00直前の 2 ビットが 00 |
read_2_one | 3'b100 | Last two bits 11最後兩個位元是 11直前の 2 ビットが 11 |
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 のときだけである。
| Rising edge上升緣立ち上がりエッジ | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|---|---|---|---|---|---|---|---|---|---|
| in_bit sampled取樣到的 in_bitサンプルされた in_bit | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |
| state_reg after之後的 state_regその後の state_reg | 1 | 3 | 2 | 4 | 4 | 1 | 3 | 3 | 2 |
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 番目…と続く等しいビットが入力に現れているビット期間であり、それを読み込むクロックエッジより前である。
next_state depends on {input, current_state} (transition logic T).next_state 取決於 {input, current_state}(轉移邏輯 T)。next_state は {input, current_state} に依存する(遷移論理 T)。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 となる。
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 は一致する入力が現れた時点で立ち上がる(このテストベンチでは半周期早い)。
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 サイクル早く応答するが、入力のグリッチをそのまま通してしまう。
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
@ vs the @ inside forever), plus the stored bits and flag (set after the second sampled bit).狀態隱含在程式停在哪裡等待(第一個 @ 還是 forever 裡的 @),再加上存起來的位元與 flag(在取樣到第二個位元之後被設起來)。状態は、コードがどこで待っているか(最初の @ か、forever の中の @ か)と、保持されたビットおよび flag(2 ビット目をサンプルした後に立つ)に暗黙的に含まれる。forever — constructs listed as "to be avoided" in Lecture 4 (Part 2). Only tools that support implicit state machines accept it (the slide's netlist uses scan-mux flip-flops dffrmqb for last_bit, this_bit, flag).它在同一個行為中使用多個事件控制,還用了 forever — 這些都是第 4 講(下)列為「應避免」的語法結構。只有支援隱含式狀態機的工具才接受(投影片的 netlist 以掃描多工正反器 dffrmqb 實作 last_bit、this_bit、flag)。1 つのビヘイビアの中で複数のイベント制御を使い、さらに forever も用いている。いずれも第 4 講(後半)で「避けるべき」と挙げられた構文である。暗黙的状態機械に対応したツールだけがこれを受け付ける(スライドのネットリストでは last_bit、this_bit、flag にスキャンマルチプレクサ付きフリップフロップ dffrmqb が使われている)。posedge reset is commented out.這裡的 reset 是同步的:posedge reset 被註解掉了。ここでのリセットは同期式である。posedge reset はコメントアウトされている。| # | Binary二進位バイナリ | One-hotOne-hotワンホット | Gray格雷碼グレイ | JohnsonJohnsonジョンソン |
|---|---|---|---|---|
| 0 | 0000 | 0000000000000001 | 0000 | 00000000 |
| 1 | 0001 | 0000000000000010 | 0001 | 00000001 |
| 2 | 0010 | 0000000000000100 | 0011 | 00000011 |
| 3 | 0011 | 0000000000001000 | 0010 | 00000111 |
| 4 | 0100 | 0000000000010000 | 0110 | 00001111 |
| 5 | 0101 | 0000000000100000 | 0111 | 00011111 |
| 6 | 0110 | 0000000001000000 | 0101 | 00111111 |
| 7 | 0111 | 0000000010000000 | 0100 | 01111111 |
| 8 | 1000 | 0000000100000000 | 1100 | 11111111 |
| 9 | 1001 | 0000001000000000 | 1101 | 11111110 |
| 10 | 1010 | 0000010000000000 | 1111 | 11111100 |
| 11 | 1011 | 0000100000000000 | 1110 | 11111000 |
| 12 | 1100 | 0001000000000000 | 1010 | 11110000 |
| 13 | 1101 | 0010000000000000 | 1011 | 11100000 |
| 14 | 1110 | 0100000000000000 | 1001 | 11000000 |
| 15 | 1111 | 1000000000000000 | 1000 | 10000000 |
| 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 入力でグリッチ無くデコードできる |
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 がハイになるのはどのエッジの後か。
| Edge邊緣エッジ | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| in_bit | 1 | 0 | 1 | 1 | 0 | 0 |
| state after之後的狀態遷移後の状態 | read_1_one | read_1_zero | read_1_one | read_2_one | read_1_zero | read_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 サイクルずつハイになる。検出する事象は同じで、どちらもクロックエッジまで遅れるだけである。
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 宣言を書け。
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] だけで済む。
<=.時序邏輯請用 <=。クロック同期論理には <= を使う。if first; last branch = clocked action.if 要在最前面;最後一個分支 = 同步動作。if を最初に置く。最後の分岐 = クロック動作。{in, r[n-1:1]}.移位:{in, r[n-1:1]}。シフト:{in, r[n-1:1]}。{r[6:0], r[7]}.旋轉:{r[6:0], r[7]}。ローテート:{r[6:0], r[7]}。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