前導
Verilog 是一種 硬體描述語言(HDL, Hardware Description Language)。
HDL 類似於一般的電腦程式語言,例如 C 語言,但它專門用於描述硬體結構和邏輯電路的行為。這使得 HDL 與其他用於數值計算的語言有所不同。
- HDL 模型還可以將大型電路劃分為多個相互連接的小功能單元。
- 透過電腦模擬來顯示數位系統的行為,這可以幫助檢測設計中的功能錯誤,而無需實際製造電路。
- 如果在模擬過程中發現錯誤,設計人員可以透過修改 HDL 語句來修正這些錯誤。
Verilog 基本架構
- Verilog 主要的架構就是模組(module)。
- 每一個 Verilog 檔案,必須包含一個 Module。
- 每個模組代表一個硬體單元。模組包含輸入、輸出、內部信號和邏輯行為的描述。
- Module 就像是積木,而一個大型的數位系統就是由一些特定功能的積木組成。
module 模組名稱( 輸出入埠名稱 );
......
endmodule
資料類型
Verilog 中有兩種主要的資料類型:
- 用於連接硬體元件,例如
wire
。本質上是一條導線的意思(電路中的連接線),它不儲存任何數據,只是將一個訊號從一個地方傳遞到另一個地方。 - 用於暫存資料,例如
reg
。
識別字與關鍵字
- 識別字(Identifier): 用來命名變數、模組等,例如
my_signal
- 關鍵字(Keyword): Verilog 保留的特殊詞,例如
module
,input
,output
,wire
等
註解與空白
- 單行註解:
// 這是單行註解
- 多行註解:
/* 這是多行註解 */
設計模式
我們要描述模組的電路架構與功能,主要有四種層次的描述:
- 電晶體層次(Switch Level)
- 邏輯閘層次(Gate Level)
- 資料流層次(Dataflow Level)
- 行為層次(Behavior Level)
行為層次與資料流層次合稱"暫存器轉換層次 RTL(Register Transfer Level )。
另外,在大學中,通常只會接觸到 邏輯閘層次(Gate Level)、資料流層次(Dataflow Level)、行為層次(Behavior Level)。
簡單範例:
假設我今天要描述 全加器(FA) 電路,如下圖:

使用 邏輯閘層次(Gate Level)描述電路
以下示範:
module full_adder(x, y, c_in, s, c_out);
input x, y, c_in; // 宣告輸入埠:x、y 為兩個加數,c_in 為來自前一位的進位輸入。
output s, c_out; // 宣告輸出埠:s 為本位的和,c_out 為向高位的進位訊號。
wire s1, c1, c2, c3;
// XOR gate for sum calculation
xor G1 (s1, x, y);
xor G2 (s, s1, c_in);
// AND gates for carry calculation
and G3 (c1, x, y);
and G4 (c2, x, c_in);
and G5 (c3, y, c_in);
// OR gate to get the final carry-out
or G6 (c_out, c1, c2, c3);
endmodule
使用 資料流層次(Dataflow Level)描述電路
指以邏輯運算式的方式來表達輸入與輸出之間的關係,而不涉及閘級或行為描述。在這層次,我們會根據布林代數推導出輸出位元的邏輯關係。
也就是說,我們只需要知道:
- s(和):

- c_out(進位):

最後透過assign
來建立輸出與輸入的持續性對應關係。也就是說,只要運算元變化,輸出就會立即更新。
assign
並不是「賦值」的概念,而是建立一條「訊號關係」。
以下示範:
module full_adder (x, y, c_in, s, c_out);
input x,
input y,
input c_in,
output s,
output c_out
assign s = x ^ y ^ c_in;
assign c_out = (x & y) | (x & c_in) | (y & c_in);
endmodule
使用 行為層次(Behavior Level)描述電路
使用 always
區塊,區塊內可以放入複雜的控制結構描述方式來描述電路。
另外,有幾個需要注意的點:
- 寫在always裡面的被賦值變數必須是宣告成
reg
的形式。 assign
不能出現在always
區塊內。
以下示範:
module full_adder(x, y, c_in, s, c_out);
input x, y, c_in;
output reg s, c_out;
// always 區塊:描述當任何一個輸入變化時,輸出應如何改變。"*" 代表所有輸入。
// always @(*) 用於組合邏輯
always @(*) begin
{c_out, s} = x + y + c_in;
end
endmodule
其中:
{c_out, s} = x + y + c_in;
{}
為串接運算子,用於將多個信號或數值按指定順序合併成一個更寬的總資料體。- 所以這行程次碼表示將
x
、y
、c_in
三個 1-bit 值相加。 - 其結果為一個 2-bit 的總和:高位指派給
c_out
(進位),低位指派給s
(和)。