How nets, registers, x/z, every operator, assignments, delay and event controls, the four loop types, tasks and functions map to hardware — a trilingual self-study guidenet、register、x/z、各種運算子、指定敘述、延遲與事件控制、四種迴圈型態、task 與 function 如何對應到硬體 — 語言結構合成自學指南ネット、レジスタ、x/z、各種演算子、代入、遅延制御とイベント制御、四つのループ型、タスクと関数がどのようにハードウェアへ対応するか — 言語構造の合成 学習ガイド
input or output ports are retained.宣告為 input 或 output 埠的 net 會被保留。input または output ポートとして宣言されたネットは保持される。wand and wor are implemented as AND / OR gates.wand 與 wor 會實作成 AND / OR 閘。wand と wor は AND / OR ゲートとして実装される。integer: 32-bit register by default; the size may be reduced during optimization.integer:預設是 32 位元的 register;最佳化時位元寬可能被縮減。integer:既定では 32 ビットのレジスタ。最適化でビット幅が削られることがある。4'd9, not 9, which is a 32-bit number).常數應該宣告固定位元寬,硬體才不會變大(寫 4'd9,不要寫 9,後者是 32 位元的數)。定数はビット幅を固定して宣言し、ハードウェアを小さく保つ(9 は 32 ビット値なので 4'd9 と書く)。real, time and realtime are not supported.real、time 與 realtime 不支援合成。real、time、realtime はサポートされない。reg becomes a flip-flop only if it must hold a value across clock edges; otherwise it is just a wire (Lecture 6).reg 只有在必須跨時脈邊緣保存數值時才會變成正反器;否則它只是一條線(第 6 講)。reg がフリップフロップになるのは、クロックエッジをまたいで値を保持する必要があるときだけで、そうでなければ単なる配線である(第 6 講)。| Value數值値 | Allowed uses in synthesizable code在可合成程式中允許的用法合成可能なコードで許される使い方 | Meaning to the tool對工具的意義ツールにとっての意味 |
|---|---|---|
x | casex, casez items; the default of a conditional (if, case, ?:); x assigned to a wire / reg by a UDPcasex、casez 的項目;條件敘述(if、case、?:)的 default;由 UDP 指定給 wire / reg 的 xcasex、casez の項目、条件分岐(if、case、?:)の default、UDP が wire / reg に代入する x | Don't care — the optimizer may pick 0 or 1Don't care — 最佳化器可以自行選 0 或 1ドントケア — 最適化器が 0 か 1 を自由に選べる |
z | Constructs implying a tri-state output: z as the default outcome of a conditional會推出三態輸出的寫法:以 z 當作條件敘述的預設結果トライステート出力を示唆する記述。条件分岐の既定の結果として z を与える | Tri-state device三態元件トライステート素子 |
Comparing against x or z (if (a === 1'bx)) has no hardware meaning.拿 x 或 z 來比較(if (a === 1'bx))在硬體上沒有意義。x や z との比較(if (a === 1'bx))にハードウェア上の意味はない。
Problem: Which lines are acceptable for synthesis and what do they become?題目:哪幾行可以合成?它們又會變成什麼硬體?問題:どの行が合成可能か。またそれぞれ何になるか。
(a) assign y = en ? d : 8'bz; (b) if (sel == 2'bx1) y = a; (c) case (op) 2'b00: y = a; 2'b01: y = b; default: y = 4'bx; endcase (d) reg [7:0] r = 8'bx; // as reset value (e) casez (req) 4'b1???: g = 0; ... endcase
(a) OK — tri-state buffer. (b) Not meaningful: == with an x operand is never true in simulation; synthesis treats it as don't care or rejects it — use casez. (c) OK — don't care in the default; lets the optimizer simplify. (d) Not a default of a conditional; initial values are ignored or rejected. Use a reset. (e) OK — ? bits are don't cares, giving a priority encoder.(a) 可以 — 三態緩衝器。(b) 沒有意義:運算元含 x 時 == 在模擬中永遠不會成立,合成工具會當成 don't care 或直接拒絕 — 請改用 casez。(c) 可以 — default 裡的 don't care 讓最佳化器得以化簡。(d) 這不是條件敘述的 default;初始值會被忽略或拒絕,請改用重置。(e) 可以 — ? 位元是 don't care,合成出優先編碼器。(a) 可 — トライステートバッファ。(b) 意味を持たない。オペランドに x があると == はシミュレーションで決して真にならず、合成ではドントケア扱いか拒否される。casez を使う。(c) 可 — default のドントケアが最適化器に簡単化を許す。(d) 条件分岐の default ではない。初期値は無視されるか拒否されるので、リセットを使う。(e) 可 — ? のビットはドントケアであり、プライオリティエンコーダになる。
* and / may not be implemented efficiently as combinational logic.* 與 / 做成組合邏輯不一定有效率。* と / は組合せ論理として効率よく実装されるとは限らない。% by a power of 2 → part select of the low bits.對 2 的冪次取 % → 低位元的 part select。2 のべき乗での % → 下位ビットの部分選択。| Control控制制御 | Action動作動作 |
|---|---|
reset = 0 | Clear (asynchronous, active low)清除(非同步,低準位有效)クリア(非同期、負論理) |
data_load = 1 | Load data_in載入 data_indata_in をロード |
SL = 1 | Shift left by 1 bit左移 1 位元1 ビット左シフト |
SR = 1 | Shift right by 1 bit右移 1 位元1 ビット右シフト |
module data_shift (data_out, data_in, clk, reset, data_load, SL, SR);
input [3:0] data_in;
input clk, reset, data_load, SL, SR;
output [3:0] data_out;
reg [3:0] data_out;
always @ (posedge clk or negedge reset)
if (reset == 0) data_out = 0; else
if (data_load) data_out = data_in; else
if (SL) data_out = data_out << 1; else
if (SR) data_out = data_out >> 1;
endmodule
The synthesized netlist realizes this per bit as AND-OR-INVERT gates in front of four DFFs with asynchronous reset.合成出來的 netlist 在每一個位元上都用一組 AND-OR-INVERT 閘實現這個結構,接在四個具非同步重置的 DFF 前面。合成されたネットリストでは、各ビットが AND-OR-INVERT ゲート群として実現され、非同期リセット付きの DFF 4 個の前段に置かれる。
< > >= <=: combinational logic, or an adder/subtractor — $A \ge B$ when the sign bit of $A - B$ is 0, $A < B$ otherwise.關係運算子 < > >= <=:組合邏輯,或是一個加法器/減法器 — 當 $A - B$ 的符號位元為 0 時 $A \ge B$,否則 $A < B$。関係演算子 < > >= <=:組合せ論理、あるいは加減算器になる。$A - B$ の符号ビットが 0 なら $A \ge B$、そうでなければ $A < B$ である。== != === !==: simple combinational logic (XOR per bit + OR). ===/!== synthesize like ==/!= because hardware has no x.相等運算子 == != === !==:簡單的組合邏輯(每位元 XOR 之後再 OR)。因為硬體裡沒有 x,===/!== 的合成結果與 ==/!= 相同。等価演算子 == != === !==:単純な組合せ論理(ビットごとの XOR と OR)。ハードウェアに x は存在しないので、===/!== は ==/!= と同じように合成される。module identity_4bit (A_eq_B, A_noteq_B, A, B); output A_eq_B, A_noteq_B; input [3:0] A, B; assign A_eq_B = (A == B); assign A_noteq_B = (A != B); endmodule
Four XORs feed a 4-input OR = A_noteq_B; one inverter gives A_eq_B.四個 XOR 餵進一個 4 輸入 OR 就得到 A_noteq_B,再加一個反相器得到 A_eq_B。4 個の XOR が 4 入力 OR に入って A_noteq_B となり、インバータ 1 個で A_eq_B が得られる。
module identity_if_4bit (data_out, data_a,
data_b, data_c, data_d, sel);
input [3:0] data_a, data_b, data_c, data_d;
input [1:0] sel;
output [3:0] data_out;
reg [3:0] data_out;
always @ (data_a or data_b or data_c
or data_d or sel)
begin
if (sel == 2'b00) data_out = data_a;
else if (sel == 2'b01) data_out = data_b;
else if (sel == 2'b10) data_out = data_c;
else data_out = data_d;
end
endmoduleThe equality tests are mutually exclusive, so the result is a single 4:1 mux (mux4_a per bit). Another tool run produced plain AND-OR gates with sel[1], sel[0] and their inverses — same function, different mapping.這些相等判斷互斥,所以結果只是一個 4:1 多工器(每位元一顆 mux4_a)。另一次工具執行則產生以 sel[1]、sel[0] 及其反相訊號組成的 AND-OR 閘 — 功能相同,只是對應到的元件不同。等価判定は互いに排他的なので、結果は 4:1 マルチプレクサ 1 個(ビットごとに mux4_a)になる。別のツール実行では sel[1]、sel[0] とその反転信号による単純な AND-OR ゲートが得られた。機能は同じでマッピングが異なる。
Translated to Boolean equations and mapped to gates.會被翻譯成布林方程式,再對應到邏輯閘。ブール式に変換され、ゲートへマッピングされる。
module reduction (data_word, y_red_and, y_red_or, y_red_nand,
y_red_nor, y_red_xor, y_red_xnor);
input [1:0] data_word;
output y_red_and, y_red_or, y_red_nand, y_red_nor, y_red_xor, y_red_xnor;
reg y_red_and, y_red_or, y_red_nand, y_red_nor, y_red_xor, y_red_xnor;
always @ (data_word) begin
y_red_and <= &data_word;
y_red_or <= |data_word;
y_red_nand <= ~&data_word;
y_red_nor <= ~|data_word;
y_red_xor <= ^data_word;
y_red_xnor <= ~^data_word;
end
endmodule
Six 2-input gates (AND, OR, XOR and their inverted versions) on data_word[1:0]. Non-blocking in a combinational block works here but = is the usual style.對 data_word[1:0] 產生六個 2 輸入閘(AND、OR、XOR 以及它們的反相版本)。在組合邏輯區塊中使用非阻斷式指定在這裡可以運作,但慣用寫法仍是 =。data_word[1:0] に対して 2 入力ゲートが 6 個(AND、OR、XOR とそれぞれの反転版)生成される。組合せ論理ブロックで非ブロッキング代入を使っても動作はするが、通常は = を使う。
module mux_conditional (data_out, data_a, data_b, data_c, data_d, sel);
input [3:0] data_a, data_b, data_c, data_d;
input [1:0] sel;
output [3:0] data_out;
assign data_out = (sel == 2'b00) ? data_a :
(sel == 2'b01) ? data_b :
(sel == 2'b10) ? data_c : data_d;
endmodule
?: synthesizes into muxes or gates that implement muxes.?: 會合成成多工器,或是實作多工器功能的邏輯閘。?: はマルチプレクサ、またはマルチプレクサを実現するゲートに合成される。{ } is supported in general and is just a logical bus — wiring with no function of its own.串接 { } 一般都支援,它只是一條邏輯匯流排 — 純粹是接線,本身沒有任何功能。連結 { } は一般にサポートされ、論理的なバスにすぎない。すなわち配線だけで、それ自体に機能はない。module operator_group (sum1, sum2, a, b, c, d); input [3:0] a, b, c, d; output [4:0] sum1, sum2; assign sum1 = a + b + c + d; assign sum2 = (a + b) + (c + d); endmodule
Verilog evaluates a + b + c + d left to right as ((a + b) + c) + d: a chain of three adders. Parentheses turn it into a balanced tree — still three adders, but only two adder delays on the critical path.Verilog 由左而右把 a + b + c + d 解讀成 ((a + b) + c) + d:三個加法器串成一條鏈。加上括號就變成平衡樹 — 一樣是三個加法器,但關鍵路徑上只剩兩個加法器延遲。Verilog は a + b + c + d を左から右へ ((a + b) + c) + d と評価する。すなわち加算器 3 個の直列である。括弧を付けると平衡木になり、加算器は 3 個のままだがクリティカルパス上の加算器遅延は 2 段だけになる。
Problem: a is [7:0]. Rewrite without *, /, %: (a) a * 8 (b) a / 4 (c) a % 16 (d) a * 10. (e) For four 8-bit operands summed as a+b+c+d, how many adder delays are on the critical path, and with parentheses?題目:a 是 [7:0]。請在不使用 *、/、% 的情況下改寫:(a) a * 8 (b) a / 4 (c) a % 16 (d) a * 10。(e) 四個 8 位元運算元以 a+b+c+d 相加時,關鍵路徑上有幾個加法器延遲?加上括號之後又是幾個?問題:a は [7:0] である。*、/、% を使わずに書き換えよ。(a) a * 8 (b) a / 4 (c) a % 16 (d) a * 10。(e) 8 ビットのオペランド 4 個を a+b+c+d と加算するとき、クリティカルパス上の加算器遅延は何段か。括弧を付けた場合は何段か。
(a) {a, 3'b000} (= a << 3, 11 bits). (b) a[7:2] (= a >> 2). (c) a[3:0]. (d) (a << 3) + (a << 1) — one adder instead of a multiplier.(a) {a, 3'b000}(即 a << 3,11 位元)。(b) a[7:2](即 a >> 2)。(c) a[3:0]。(d) (a << 3) + (a << 1) — 用一個加法器取代乘法器。(a) {a, 3'b000}(= a << 3、11 ビット)。(b) a[7:2](= a >> 2)。(c) a[3:0]。(d) (a << 3) + (a << 1) — 乗算器の代わりに加算器 1 個で済む。
(e) Chain: 3 adder delays; (a+b)+(c+d): 2.(e) 串接寫法:3 個加法器延遲;(a+b)+(c+d):2 個。(e) 直列なら加算器遅延 3 段、(a+b)+(c+d) なら 2 段。
module alu_reg_with_z1 (alu_out, en, a, b, s0, s1, s2, clk, reset);
output [1:0] alu_out;
input [1:0] a, b;
input en, s0, s1, s2, clk, reset;
reg [1:0] out_int;
assign alu_out = (en == 1) ? out_int : 2'bz;
always @ (posedge clk)
if (reset) out_int = 2'b0;
else
case ({s0, s1, s2})
3'b111: out_int = a & b;
3'b011: out_int = a | b;
3'b001: out_int = a ^ b;
default: out_int = 2'bx;
endcase
endmodule
All three listed cases have s2 = 1, and every other code is a don't care. The optimizer can therefore choose outputs that ignore s2 entirely — the logic is driven only by s0 and s1. The unused input s2 is still retained as a port (ports are never removed). Result: two DFFs with synchronous reset, a gate-level ALU in front and two tri-state output buffers.列出的三個 case 都滿足 s2 = 1,其餘編碼全是 don't care。因此最佳化器可以挑出完全不理會 s2 的輸出 — 邏輯只由 s0 與 s1 驅動。沒用到的輸入 s2 仍然保留為埠(埠永遠不會被刪掉)。結果是:兩個具同步重置的 DFF,前面接閘級 ALU,後面接兩個三態輸出緩衝器。挙げられた 3 つの case はいずれも s2 = 1 であり、それ以外のコードはすべてドントケアである。したがって最適化器は s2 を完全に無視する出力を選べる。論理は s0 と s1 だけで駆動される。使われない入力 s2 もポートとしては残る(ポートが削除されることはない)。結果は、同期リセット付き DFF 2 個、その前段のゲートレベル ALU、そして 2 個のトライステート出力バッファである。
module pipe1 (data, rega, regb, regc, clk, reset);
input [1:0] data;
input clk, reset;
output [1:0] rega, regb, regc;
reg [1:0] rega, regb, regc;
always @ (posedge clk or posedge reset)
if (reset)
begin
rega = 2'b0;
regb <= 2'b0;
regc <= 2'b0;
end
else
begin
rega = data;
regb <= rega + 1; // new rega!
regc <= regb + 1; // old regb
end
endmodulemodule pipe1_alt (data, rega, regb, regc, clk, reset);
...
always @ (posedge clk or posedge reset)
if (reset) rega = 2'b0; else rega = data;
always @ (posedge clk or posedge reset)
if (reset)
begin
regb <= 2'b0;
regc <= 2'b0;
end
else
begin
regb <= rega + 1; // rega of the previous cycle
regc <= regb + 1;
end
endmodulemodule pipe2 (data, rega, regb, regc, clk, reset);
...
always @ (posedge clk or posedge reset)
if (reset)
begin
rega = 2'b0;
regb = 2'b0;
regc = 2'b0;
end
else
begin
rega = data;
regb = rega + 1;
regc = regb + 1;
end
endmodulerega = data;
regb = data + 1;
regc = data + 1 + 1;
// equivalent to
rega <= data;
regb <= data + 1;
regc <= data + 1 + 1;| Module模組モジュール | rega | regb | regc | Structure結構構造 |
|---|---|---|---|---|
| pipe1 | data | data + 1 | old regb + 1舊的 regb + 1前回の regb + 1 | rega, regb parallel; regc one stage laterrega、regb 平行;regc 晚一級rega と regb は並列、regc は 1 段遅れ |
| pipe1_alt | data | old rega + 1舊的 rega + 1前回の rega + 1 | old regb + 1舊的 regb + 1前回の regb + 1 | True 3-stage pipeline真正的三級管線本物の 3 段パイプライン |
| pipe2 | data | data + 1 | data + 2 | Three parallel registers, two adders in series三個平行的暫存器,兩個加法器串接並列な 3 個のレジスタと直列 2 個の加算器 |
The rega read by regb in pipe1_alt is from the previous cycle, not the current one, because it lives in a different always block. Same text, different hardware — the reason for the rule "clocked logic uses <= only". Strictly, pipe1_alt is also a simulation race: rega is written with = in one block and read in another at the same edge, so the simulator may show either value. Synthesis builds the flip-flop (previous-cycle) behavior; writing rega <= data removes the race.在 pipe1_alt 中 regb 讀到的 rega 是上一拍的值,不是這一拍的,因為它寫在另一個 always 區塊裡。程式碼看起來一樣,硬體卻不同 — 這正是「時脈邏輯一律只用 <=」這條規則的由來。嚴格來說,pipe1_alt 在模擬上還是一個競爭(race):rega 在一個區塊中用 = 寫入,又在同一個邊緣於另一個區塊被讀取,模擬器給出哪一個值都算合法。合成會做出正反器(上一拍)的行為;把它改寫成 rega <= data 就能消除這個競爭。pipe1_alt で regb が読む rega は、今回のサイクルではなく前回のサイクルの値である。別の always ブロックにあるからだ。記述は同じでもハードウェアは異なる。これが「クロック同期論理では <= だけを使う」という規則の理由である。厳密には pipe1_alt はシミュレーション上のレースでもある。rega は一方のブロックで = により書かれ、同じエッジで他方のブロックから読まれるため、シミュレータはどちらの値を示してもよい。合成はフリップフロップ(前回サイクル)の動作を作る。rega <= data と書けばレースはなくなる。
Problem: After reset all registers are 0. data = 1, 2, 3 at clock edges 1, 2, 3. Give (rega, regb, regc) after each edge for pipe1, pipe1_alt and pipe2 (2-bit arithmetic wraps mod 4).題目:重置之後所有暫存器都是 0。data 在時脈邊緣 1、2、3 依序為 1、2、3。請寫出 pipe1、pipe1_alt 與 pipe2 在每個邊緣之後的 (rega, regb, regc)(2 位元運算以 mod 4 環繞)。問題:リセット後、すべてのレジスタは 0 である。クロックエッジ 1、2、3 で data はそれぞれ 1、2、3 となる。pipe1、pipe1_alt、pipe2 について各エッジ後の (rega, regb, regc) を示せ(2 ビット演算は mod 4 で巡回する)。
| Edge邊緣エッジ | pipe1 | pipe1_alt | pipe2 |
|---|---|---|---|
| 1 | (1, 2, 1) | (1, 1, 1) | (1, 2, 3) |
| 2 | (2, 3, 3) | (2, 2, 2) | (2, 3, 0) |
| 3 | (3, 0, 0) | (3, 3, 3) | (3, 0, 1) |
pipe1, edge 1: regb = new rega + 1 = 2, regc = old regb (0) + 1 = 1. pipe1_alt, edge 1: regb = old rega (0) + 1 = 1, regc = 0 + 1 = 1. pipe2 computes everything from the current data.pipe1 的第 1 個邊緣:regb = 新的 rega + 1 = 2,regc = 舊的 regb(0)+ 1 = 1。pipe1_alt 的第 1 個邊緣:regb = 舊的 rega(0)+ 1 = 1,regc = 0 + 1 = 1。pipe2 則全部用當下的 data 計算。pipe1 のエッジ 1:regb = 新しい rega + 1 = 2、regc = 前回の regb(0)+ 1 = 1。pipe1_alt のエッジ 1:regb = 前回の rega(0)+ 1 = 1、regc = 0 + 1 = 1。pipe2 はすべて現在の data から計算する。
if or ?:).接在事件控制後面的敘述應該是條件分支(if 或 ?:)。イベント制御に続く文は条件分岐(if または ?:)であるべきである。posedge and negedge.同一個訊號不可以同時被 posedge 與 negedge 修飾。同一の信号を posedge と negedge の両方で修飾してはならない。always @ (posedge x or posedge y or posedge z)
begin
if (x)
a <= 0; // asynchronous clear
else if (y)
a <= 1; // asynchronous set
// z is not mentioned here, and is assumed synchronous
else a <= b & c; // z acts as the clock
end
Problem: Which are acceptable for synthesis? Identify the clock.題目:哪幾個可以合成?並指出時脈是哪一個訊號。問題:どれが合成可能か。またクロックはどれか答えよ。
// (a) always @ (posedge clk or negedge rst_n) if (!rst_n) q <= 0; else q <= d; // (b) always @ (posedge clk or negedge rst_n) if (en) q <= d; else if (!rst_n) q <= 0; // (c) always @ (posedge clk or negedge clk) q <= d; // (d) always @ (posedge clk or posedge set or posedge clr) if (clr) q <= 0; else if (set) q <= 1; else q <= d;
(a) OK — clock clk, async active-low reset.(a) 可以 — 時脈是 clk,非同步低準位有效重置。(a) 可 — クロックは clk、非同期の負論理リセット。
(b) Not OK — the asynchronous branch (!rst_n) is not first and the synchronous branch is not last.(b) 不行 — 非同步分支(!rst_n)不在最前面,同步分支也不在最後面。(b) 不可 — 非同期分岐(!rst_n)が先頭になく、同期分岐も最後にない。
(c) Not OK — clk qualified by both edges (a dual-edge FF is not in normal libraries).(c) 不行 — clk 同時被兩種邊緣修飾(一般元件庫沒有雙邊緣正反器)。(c) 不可 — clk が両エッジで修飾されている(両エッジ動作の FF は通常のライブラリにない)。
(d) OK — clock clk, async clear has priority over async set.(d) 可以 — 時脈是 clk,非同步清除的優先權高於非同步設定。(d) 可 — クロックは clk、非同期クリアが非同期セットより優先される。
A loop is static (data-independent) if the compiler can determine the number of iterations.如果編譯器能決定迴圈的執行次數,這個迴圈就是靜態的(與資料無關)。コンパイラが反復回数を決定できるとき、そのループは静的(データ非依存)である。
| Type型態型 | Static?靜態?静的か | Internal timing control?有內部時序控制?内部タイミング制御 | Result結果結果 |
|---|---|---|---|
| I | Yes是はい | No否いいえ | Combinational logic (loop unrolling) — recommended組合邏輯(迴圈展開)— 建議採用組合せ論理(ループ展開)— 推奨 |
| II | Yes是はい | Yes是はい | Sequential logic, fixed number of cycles — not recommended循序邏輯,週期數固定 — 不建議順序論理、サイクル数は固定 — 非推奨 |
| III | No否いいえ | No否いいえ | Not synthesizable (simulates fine)不可合成(模擬沒問題)合成不可(シミュレーションは可能) |
| IV | No否いいえ | Yes是はい | Sequential logic, data-dependent number of cycles — not recommended循序邏輯,週期數取決於資料 — 不建議順序論理、サイクル数がデータ依存 — 非推奨 |
module for_and_loop_comb (out, a, b);
input [3:0] a, b;
output [3:0] out;
reg [2:0] i;
reg [3:0] out;
always @ (a or b)
begin
for (i = 0; i < 4; i = i + 1)
out[i] = a[i] & b[i];
end
endmodule
Unrolled into four AND gates. Replacing @(a or b) with @(posedge clk) gives for_and_loop_reg: the same ANDs feeding four flip-flops.展開成四個 AND 閘。把 @(a or b) 換成 @(posedge clk) 就成為 for_and_loop_reg:同樣的 AND 閘接到四個正反器。AND ゲート 4 個に展開される。@(a or b) を @(posedge clk) に替えると for_and_loop_reg になり、同じ AND ゲートが 4 個のフリップフロップを駆動する。
The loop exits when i reaches 4, so i must hold 4. A reg [1:0] i would wrap 3 → 0 and loop forever in simulation.迴圈要等 i 到 4 才結束,所以 i 必須存得下 4。若宣告成 reg [1:0] i,3 會環繞回 0,模擬時就會無限迴圈。ループは i が 4 になったときに終わるので、i は 4 を保持できなければならない。reg [1:0] i では 3 から 0 へ巡回し、シミュレーションで無限ループになる。
module count_ones_a (bit_count, data, clk, reset);
parameter data_width = 4;
parameter count_width = 3;
output [count_width-1:0] bit_count;
input [data_width-1:0] data;
input clk, reset;
reg [count_width-1:0] count, bit_count, index;
reg [data_width-1:0] temp;
always @ (posedge clk)
if (reset) begin count = 0; bit_count = 0; end
else begin
count = 0;
bit_count = 0;
temp = data;
for (index = 0; index < data_width; index = index + 1) begin
count = count + temp[0];
temp = temp >> 1;
end
bit_count = count;
end
endmodule
The loop unrolls into a small adder tree that counts the ones of data in one clock; only bit_count (3 FFs) is registered — count, temp, index are written before they are read, so they are wires.迴圈展開成一棵小的加法器樹,在一個時脈內數完 data 裡的 1;只有 bit_count(3 個正反器)會被暫存 — count、temp、index 都是先寫後讀,所以只是線。ループは小さな加算器ツリーに展開され、data 中の 1 を 1 クロックで数える。レジスタになるのは bit_count(FF 3 個)だけで、count、temp、index は読まれる前に書かれるため単なる配線になる。
If a static loop contains an edge-sensitive event control, its work is synchronized and distributed over one or more clock cycles.靜態迴圈若含有邊緣觸發的事件控制,它的工作會被同步化,並分散到一個或多個時脈週期。静的ループがエッジセンシティブなイベント制御を含む場合、その処理は同期化され、1 つ以上のクロック周期に分散される。
module count_ones_b (bit_count, data, clk, reset);
... // same declarations
always @ (posedge clk)
if (reset) begin count = 0; bit_count = 0; end
else begin
count = 0;
temp = data;
for (index = 0; index < data_width; index = index + 1)
@ (posedge clk)
begin
if (temp[0]) count = count + 1;
temp = temp >> 1;
end
@ (posedge clk)
bit_count = count;
end
endmodule
One bit is examined per clock; bit_count updates after data_width + 1 extra clocks. This is an implicit state machine — supported only by some tools. Not recommended.每個時脈檢查一個位元;bit_count 要再過 data_width + 1 個時脈才更新。這是一個隱含的狀態機 — 只有部分工具支援。不建議使用。1 クロックにつき 1 ビットを調べ、bit_count は追加の data_width + 1 クロック後に更新される。これは暗黙の状態機械であり、一部のツールしか対応しない。推奨しない。
module count_ones_c (bit_count, data, clk, reset);
...
always @ (posedge clk)
if (reset) begin count = 0; bit_count = 0; end
else begin
count = 0;
temp = data;
for (index = 0; | temp; index = index + 1) begin // stops when temp == 0
if (temp[0]) count = count + 1;
temp = temp >> 1;
end
bit_count = count;
end
endmodule
The timing control distributes the loop over multiple cycles; the number of cycles is set by a variable modified within the loop.時序控制把迴圈分散到多個週期;週期數由迴圈內部被修改的變數決定。タイミング制御がループを複数サイクルに分散させ、そのサイクル数はループ内で変更される変数によって決まる。
module count_ones_d (bit_count, data, clk, reset);
...
always @ (posedge clk)
if (reset) begin count = 0; bit_count = 0; end
else begin: bit_counter
count = 0;
temp = data;
while (temp)
@ (posedge clk)
if (reset) begin
count = 2'b0;
disable bit_counter; end
else begin
count = count + temp[0]; // notice: no if needed
temp = temp >> 1;
end
@ (posedge clk);
if (reset) begin
count = 0;
disable bit_counter; end
else bit_count = count;
end
endmodule
Reset must be re-checked at every internal @(posedge clk), and disable jumps back to the top. Not recommended.每一個內部的 @(posedge clk) 都必須重新檢查 reset,而 disable 會跳回最上面。不建議使用。内部の @(posedge clk) ごとにリセットを再確認する必要があり、disable は先頭へ戻る。推奨しない。
Problem: Give the type (I–IV) and whether it is synthesizable.題目:寫出型態(I–IV),並說明是否可以合成。問題:型(I–IV)と、合成可能かどうかを答えよ。
(a) for (k = 0; k < 8; k = k + 1) y[k] = x[7-k]; (b) while (q != 0) begin q = q - 1; n = n + 1; end (c) repeat (4) @(posedge clk) acc = acc + in; (d) while (busy) @(posedge clk) busy = check(status);
(a) Type I — bit reversal, pure wiring. (b) Type III — not synthesizable. (c) Type II — static (4) with timing; synthesizable by some tools only. (d) Type IV — data-dependent cycles; avoid.(a) 型 I — 位元反轉,純接線。(b) 型 III — 不可合成。(c) 型 II — 靜態(4 次)且含時序控制,只有部分工具能合成。(d) 型 IV — 週期數取決於資料,請避免。(a) タイプ I — ビット反転、配線のみ。(b) タイプ III — 合成不可。(c) タイプ II — 静的(4 回)でタイミング制御あり。一部のツールのみ合成できる。(d) タイプ IV — サイクル数がデータ依存。避けること。
Problem: For data = 4'b1010 and data = 4'b0100, how many clock edges after the starting edge does bit_count update in count_ones_a, _b and _d? What value?題目:對 data = 4'b1010 與 data = 4'b0100,在 count_ones_a、_b 與 _d 中,bit_count 會在起始邊緣之後第幾個時脈邊緣更新?更新成什麼值?問題:data = 4'b1010 と data = 4'b0100 について、count_ones_a、_b、_d では開始エッジから何クロックエッジ後に bit_count が更新されるか。またその値は何か。
Both inputs contain ones: 1010 → 2, 0100 → 1.兩組輸入各自含有的 1 的個數:1010 → 2,0100 → 1。各入力に含まれる 1 の個数:1010 → 2、0100 → 1。
_a: at the starting edge itself (0 extra) for both._a:兩者都在起始邊緣當下就更新(額外 0 個邊緣)。_a: どちらも開始エッジそのもので更新される(追加 0 エッジ)。
_b: 4 loop edges + 1 = 5 extra edges for both (static)._b:兩者都是 4 個迴圈邊緣 + 1 = 額外 5 個邊緣(靜態)。_b: どちらもループ 4 エッジ + 1 = 追加 5 エッジ(静的)。
_d: the while loop runs until temp becomes 0: 1010 → 0101 → 0010 → 0001 → 0000 is 4 iterations, 0100 → 0010 → 0001 → 0000 is 3 iterations; plus 1 final edge → 5 and 4 extra edges. The latency depends on the data._d:while 迴圈一直跑到 temp 變成 0 為止:1010 → 0101 → 0010 → 0001 → 0000 共 4 次,0100 → 0010 → 0001 → 0000 共 3 次;再加最後 1 個邊緣 → 額外 5 個與 4 個邊緣。延遲取決於資料。_d: while ループは temp が 0 になるまで回る。1010 → 0101 → 0010 → 0001 → 0000 で 4 回、0100 → 0010 → 0001 → 0000 で 3 回。最後の 1 エッジを加えて、追加 5 エッジと 4 エッジになる。レイテンシはデータに依存する。
inout ports.要拿去合成的 task 不可以有 inout 埠。合成対象のタスクに inout ポートを含めてはならない。module adder_task (c_out, sum, clk, reset, c_in, data_a, data_b);
input [3:0] data_a, data_b;
input clk, reset, c_in;
output [3:0] sum;
output c_out;
reg [3:0] sum;
reg c_out;
always @ (posedge clk or posedge reset)
if (reset) {c_out, sum} = 0; else
add_values (sum, c_out, data_a, data_b, c_in);
task add_values;
output [3:0] sum;
output c_out;
input [3:0] data_a, data_b;
input c_in;
begin
{c_out, sum} = data_a + (data_b + c_in);
end
endtask
endmodule
Result: two 5-bit adders (data_b + c_in, then + data_a) feeding five DFFs with asynchronous reset.結果:兩個 5 位元加法器(先 data_b + c_in,再 + data_a)接到五個具非同步重置的 DFF。結果:5 ビット加算器 2 個(まず data_b + c_in、次に + data_a)が、非同期リセット付き DFF 5 個を駆動する。
case and if statements are not allowed inside a function.function 裡不允許出現不完整的 case 與 if 敘述。関数の中では、不完全に記述された case 文や if 文は許されない。module arithmetic_unit (operand_1, operand_2, result_1, result_2);
input [3:0] operand_1, operand_2;
output [4:0] result_1;
output [3:0] result_2;
assign result_1 = sum_of_operands (operand_1, operand_2);
assign result_2 = largest_operand (operand_1, operand_2);
function [4:0] sum_of_operands;
input [3:0] operand_1, operand_2;
sum_of_operands = operand_1 + operand_2;
endfunction
function [3:0] largest_operand;
input [3:0] operand_1, operand_2;
largest_operand = (operand_1 >= operand_2) ? operand_1 : operand_2;
endfunction
endmodule
Result: one 4-bit adder for result_1, and a comparator (gates) driving four 2:1 muxes for result_2.結果:result_1 用一個 4 位元加法器;result_2 則是一個比較器(邏輯閘)驅動四個 2:1 多工器。結果:result_1 には 4 ビット加算器 1 個、result_2 には比較器(ゲート)が 2:1 マルチプレクサ 4 個を駆動する構成になる。
| Construct語法結構構文 | Synthesis合成結果合成結果 |
|---|---|
specify ... endspecify | Ignored (timing comes from the cell library)忽略(時序資訊來自元件庫)無視される(タイミングはセルライブラリから得る) |
`define, `include, other compiler directives`define、`include 等編譯指令`define、`include などのコンパイラ指令 | Honored — they change the source text the tool reads有效 — 它們會改變工具讀到的原始碼有効 — ツールが読むソーステキストを変える |
= and read again inside the same always block and you see the new value; read it from a different always block and you see the previous cycle's value.同一個 always 內先用 = 寫再讀,讀到的是「新值」;不同 always 之間讀到的是「上一拍」的值。同じ always ブロック内で = により書いてから読むと新しい値が見え、別の always ブロックから読むと前回サイクルの値になる。Problem: You need a reusable block that (a) returns the parity of a 16-bit word, (b) produces both quotient and remainder of a division by 8, (c) waits 3 clock edges before writing a register. Choose task or function (or neither) and justify.題目:你需要一個可重複使用的區塊:(a) 回傳 16 位元字組的奇偶性,(b) 同時產生除以 8 的商與餘數,(c) 等 3 個時脈邊緣之後才寫入暫存器。請選擇 task 或 function(或兩者皆不可),並說明理由。問題:再利用できるブロックが必要である。(a) 16 ビットワードのパリティを返す、(b) 8 による除算の商と剰余の両方を出す、(c) 3 クロックエッジ待ってからレジスタに書く。タスクか関数か(あるいはどちらでもないか)を選び、理由を述べよ。
(a) Function — one return value, pure combinational: parity = ^word;(a) 用 function — 只有一個回傳值,純組合邏輯:parity = ^word;(a) 関数 — 戻り値は 1 つで純粋な組合せ論理:parity = ^word;
(b) Task with two outputs (or two functions): quotient x >> 3, remainder x[2:0]; no timing, so it is combinational.(b) 用有兩個輸出的 task(或兩個 function):商是 x >> 3,餘數是 x[2:0];沒有時序控制,所以是組合邏輯。(b) 出力を 2 つ持つタスク(または関数 2 つ)。商は x >> 3、剰余は x[2:0]。タイミング制御がないので組合せ論理になる。
(c) Neither for synthesis — a task with timing controls is not synthesizable. Use a counter or a 3-stage shift register in the clocked logic instead.(c) 兩者都不行 — 含時序控制的 task 不可合成。請改用計數器,或在時脈邏輯中放一個 3 級移位暫存器。(c) 合成の観点ではどちらも不可 — タイミング制御を持つタスクは合成できない。代わりにカウンタか、クロック同期論理の中の 3 段シフトレジスタを使う。
integer = 32 bits; size constants.integer = 32 位元;常數要指定位元寬。integer は 32 ビット。定数はビット幅を明示する。real, time, realtime.不支援 real、time、realtime。real、time、realtime は使えない。>= via sign of A − B.>= 看 A − B 的符號位元。>= は A − B の符号で判定。* / % are free.對 2 的冪次做 * / % 不花硬體。2 のべき乗の * / % はコストゼロ。= then read in same block → new value.同一區塊內先 = 再讀 → 新值。同じブロックで = の後に読む → 新しい値。specify ignored.specify 會被忽略。specify は無視される。