Verilog 是 IC 設計中必備的工具或說是語言。認識 Verilog 之前,我們要先知道並非所有的語法都可以用來設計電路,部分的語法是用來「模擬」電路的。
舉例來說,#2 代表的是延遲2個時間單位,但是這在電路本身就非常奇怪,因為我們不可能去控制資料流動需要的時間,這其實是電路中包含電阻,才有延遲的效果。另外一個例子是 initial 這個關鍵字,initial 中的程式碼只會被執行一次,但是這有可能發生嗎?電路一旦通電,一定是不斷的運行,不會有這種可能發生。
因此設計電路時,要特別注意現在所撰寫的部分可否被「合成」。
Verilog 的變數大致分成 2 種:wire
, reg
,值得一提的是 reg
未必會被合成成「暫存器」。
以下舉幾個例子:
wire in_alu;
reg out_rom;
wire [N-1 : 0] in_opcode;
reg [N-1 : 0] out_rom;
reg [7 : 0] data_mem [N-1 : 0];
從上述例子可以發現,若寬度大於 1,則表示方式為 [MSB : LSB]
。
Verilog 中提供基本邏輯閘的模組,可以直接使用,不過每一個接口寬度都是 1 位元寬。
假設我們要實作一位元半加器,如下是電路圖 (圖片來源:維基百科)
// 假設 A, B 都已經處理完畢
wire S, C;
xor G0(S, A, B);
and G1(C, A, B);
在邏輯閘模組中,第一個接口代表的是邏輯閘輸出,後面兩個則為輸入。如果取得僅包含邏輯閘的電路圖,這將會是最直接的方式了!
在這種電路描述中,大致歸類為 2 個重點:
assign
wire
型態,右邊無特別限制假設我們有以下虛擬碼:
a = 5
b = 6
if (a < b)
c = a + b
else
c = a & b
若將它轉換成電路,則為下方結果:
wire [7 : 0] a, b, c;
assign a = 8'd5;
assign b = 8'd6;
assign c = (a < b) ? (a + b) : (a - b);
這段程式碼看似 C-Style 但是背後的原理卻完全不同。因為 C 程式執行方式為由上而下一行接著一行進行,但是 Verilog 描述的是電路,通電時,所有的電路同時運行。在最開始的時候,電路還不穩定, c
不會是理想中的 11
,因為此時 a
, b
也都是未知數。過了一段時間,a
, b
的數值都穩定了,c
才會是正確的數值。
在這種電路描述中,我們可以完成較複雜的描述。大致可以歸納成 2 個重點:
always
reg
型態,右邊無特別限制上述的虛擬碼,我們也可以用這種方式來描述電路:
wire [7 : 0] a, b;
assign a = 8'd5;
assign b = 8'd6;
always @(*) begin
if (a < b) c = a + b;
else c = a - b;
end
不論是 assign
還是 always
都代表的是獨立的電路,和軟體設計的思維截然不同!