在說明如何描述一個電路之前,先來提到電路主要可以分成2種電路
1. 組合邏輯電路
2. 循序邏輯電路
組合邏輯電路最大的一個特性就是,輸入到輸出的響應是沒有等待的,主要只有電路的延遲,最大的例子就是 各種邏輯的組合
如:
一個 and 閘,從左邊輸入直到右邊輸出,只會經過電路本身的延遲,這種就是組合邏輯電路
接著循序邏輯電路主要是有著clock訊號的,而且可儲存數值。
最簡單的例子就是 D Flip Flop
經過clock正緣觸發,才將資料輸出至輸出端。 這種電路就是循序電路
再來描述電路的方式主要可以分成3種
1. Gate Level
2. Data Flow
3. Behavior
1. Gate Level
首先 Gate Level的描述方式主要使用邏輯來描述 如 and or nor not
Ex:
(
);
and (o1 , a1, a2); // 內建語法 宣告一個and閘 a1, a2 為輸入 o1 為輸出
and(o2, a1, a2, a3); // 也不限於2輸入 也可以增加輸入訊號
不過這種方式幾乎沒在使用,最主要使用的都是後2種方式
2. Data flow
Data flow描述電路的方式主要是用資料的流向來設計電路,主要使用assign這個語法
EX:
假如要設計一個and閘用這種方式快速許多
(
);
assign o1 = a1 & a2; // 設定o1 為 a1 and a2
assign o2 = (a1 & a2) | a3; // 也可以使用不同的邏輯組合再一起
另外運算子也可以使用在data flow 的描述上
assign sum = A1 + A2 + C; // 描述一個加法器
assign
主要data flow使用在描述組合邏輯電路上
3. Behavior 描述方式
Behavior描述的方式更為高階,語法上類似於C語言
主要使用的是 always block來描述電路
首先介紹always block
always 宣告如下,事件觸發的地方填入要何時去觸發always block的內容
電路內容則是開始描述你的電路,另外再always block中要給予值的訊號都要宣告成reg
取值的訊號不用
always @( 事件觸發 )
begin
電路內容
end
Ex :
wire a , b; // 取值的訊號可以是 wire 也可以是 reg
reg c; // 給予值的才要宣告成 reg
begin
c = a | b; // 設定 c的數值 為 a | b
end
再來 Behavior描述電路則是兩種電路階可以描述,組合邏輯以及循序電路。
組合邏輯電路描述方式
在always 描述組合邏輯電路的方式主要使用blocking的描述 使用的是 " = "符號
那甚麼是blocking的描述呢 ? 那是不是還有non-blocking?
blocking的描述方式如名子所述 在執行這一行的時候會卡住就像一般的程式語言
像是 一開始 a = 1 b = 0
a = b; // 模擬時先執行這行 a = 0
b = a; // 再執行這行 最終 a = 0 ,b = 0
non-blocking的描述則是使用 " <= " 注意這不是小於等於
假設像上面 a = 1 b = 0
a <= b; //在模擬的時候則是 2行同時執行
b <= a; // 最終則是 a = 0, b = 1
好 再來回到描述組合邏輯的電路,那是不是很那笨上面2種的描述跟電路有啥關係?
上面提到的描述主要是會跟模擬時的優先順序有關,你只要記住組合邏輯使用 " = "
循序使用 " <= " 就可以了
Ex :
那我們現在來描述一個多工器使用always可以寫成
wire a1, a2 , sel; // 宣告訊號線
reg out; // 宣告多工器輸出
always @(a1, a2, sel) //事件觸發為 輸入訊號3個
begin
if(sel) //使用 if else 描述 多工器
out = a1; // sel == 1 輸出 = a1
else
out = a2; // sel == 0 輸出 = a2
end
如此一來便完成一個多工器了 另外組合邏輯如果訊號越來越多,事件觸發要寫的數量就會越來越多
為了節省手指的疲勞程度
通常會寫成 always @(*) 使用" * "來代表所有的訊號