# Verilog Courses
###### tags: `verilog`
## Online Lecture 1
[Lecture : Verilog (Bar-Ilan University 83-612: Digital VLSI Design)](https://youtu.be/XfUOa2wudTs)
### Basic Constructs
1. Primitives
* not, and, or, buf, xor, nand, nor, xnor
* 不常用
```verilog=
or(out, in1, in2)
```
2. Signals
* 4 States: 0, 1, X, Z
* **Wires**: do not keep states
* **Registers**: keep states (i.e., outputs)
* Can represent **buses** or group of signals
```verilog=
wire in1, in2;
reg out;
wire [7:0] data; // one-dimentional
reg [32:0] mem [0:7] // width (bit) = 32, depth (word) = 8
```
3. Operators
* Similar to primitives
* &, |, ~, &&, ||, etc
```verilog=
out = in1 | in2;
```
4. Constants
* The format is W'Bval (width, apostrophe, type, value)
```verilog=
1'b0 // single bit binary 0 (or decimal 0)
4'b0011 // 4 bit binary 0011 (or decimal 3)
8'hff // 8 bit hexadecimal ff (or decimal 255)
8'd255 // 8 bit decimal 255
```
### Procedural Blocks
1. Initial block
* Will be executed only once, at first time the unit is called (Only in testbench)
```verilog=
intial begin
a = 1'b0;
b = 1'b0;
end
```
2. Always block
* Statements will be evaluate when **a change in sensitivity list** occurs
* sync reset, rising edge triggered flop
```verilog=
always @(posedge clock) // everytime we get a positive edge in the signal clock
if (!nreset)
q <= 1'b0;
else
q <= d;
```
* async reset, rising edge triggered, load enable flop
```verilog=
always @(posedge clock or negedge nreset)
if (!nreset)
q <= 1'b0;
else
q <= d;
```
3. There are 2 types of `always` blocks
* **Sequential**
* Asserted by a **clock** in the **sensitivity list**
* translates into **flip-flops** / latches
* 像是上面兩個例子
* **Combinational**
* Describes purely combinational logic
* The sensitivity list has (**non-clock**) signals
* Everything appears in the sensitivity list should appear on the RHS
* The verilog 2001 standard allows using * instead of a sensitivity list to reduce bugs
```verilog=
always @(a or b or c)
out = a & b &c;
```
```verilog=
always @(*)
out = a & b &c;
```
### Assignments
1. Continuous assignments
* outside of `always` blocks
* `assign` statement
```verilog=
assign muxout = (sel&in1) | (~sel&in0);
assign muxout = sel ? in1 : in0; // the same as the previous assignment
```
2. Blocking procedural assignment **"="**
* RHS is executed and **assignment is completed before the next statement** is executed
```verilog=
// assume initially a = 1
a = 2;
b = a;
// a = 2; b = 2
```
3. Non-blocking procedural assignment **"<="**
* RHS is executed and **assignment takes place at the end of the current time step** (not clock cycle)
* Quite confusing
```verilog=
// assume initially a = 1
a <= 2;
b <= a;
// a = 2; b = 1
```
4. To eliminate mistakes, follow these rules:
* Combinational `always` block: use **blocking** assignments (=)
* Sequential `always` block: use **non-blocking** assignments (<=)
* **Do not mix** blocking and non-blocking in the same `always` block
* **Do not assign to the same variable** from more than one `always` block
### Hierarchy
1. Modules: used to define a hardware block
* saved in `mux4.v`
![](https://hackmd.io/_uploads/SywcSqnZq.png =300x)
2. Instance: referencing a block at a different level
* dot notation
```verilog=
mux4 M0 (.out(outa), .in(a), .sel(sel)) // instantiate M0
mux4 M1 (.out(outb), .in(b), .sel(sel))
```
### System Tasks
1. System tasks are used to provide interface to simulate data
2. Identified by a `$name` syntax
3. Printing tasks:
* `$display`, `$strobe`: print once there is a change in one of the parameters
* `$moniter`: print every time there is a change in one of the parameters
* All take the "C" style `printf` format
```verilog=
$display("At %t Value of out is %b\n", $time, out)
```
### Arithmetic
Verilog supports standard arithmetic operators
* +, -, *, <<, >>, etc.
* Be careful about division (not synthesizable)
* Concatenate signals with the `{, }` operator
```verilog=
assign a = 4'b1100;
assign b = 4'b1010;
assign c = {a, b}; // c = 8'b11001010
```
* By default, verilog treats all vectors as **unsigned** binary numbers
* To do signed (two's complement) operations, declare the reg/wire as `signed`, for example, `wire signed [9:0] a, b;`
* To make constant signed, add an `s`, for example, `10'sh37C`
### reg vs. wire
1. A `reg` is not necessarily an actual register
2. Inside `always` blocks (both sequential and combinational) only `reg` can be used as LHS
3. For an `assign` statement, only `wire` can be used as LHS
4. Inside an initial block (Testbench) only `reg` can be used on the LHS
5. The output of an instantiated module can only connect to a `wire`
6. Inputs of a module cannot be a `reg`
![](https://hackmd.io/_uploads/HJ1_WhhZ5.png =300x)
### Testbench constructs
1. Create a clock
```verilog=
`define CLK_PERIOD 10
initial
begin // begins executing at time 0
clk = 0;
end
always // begins executing at time 0 and never stops
#(CLK_PERIOD/2) clk = ~clk;
// # means delay
```
---
## [雲科大] Verilog 硬體描述語言介紹
[Lecture : Verilog 硬體描述語言介紹](https://www.youtube.com/watch?v=nzq2g28-auY&list=PLI6pJZaOCtF3_-vE7VUn9RdhQ6KXpcFQD)
### Verilog 簡介
1. 一套硬體描述語言,輔助設計數位系統
* 用來描述電路的行為
2. 類似C語言的硬體描述語言
3. **切勿使用軟體思維 (循序) 撰寫**
* 在硬體上面有很多**並行**的執行
4. 支援**多種硬體層級**的描述方式
5. Verilog 的模型
* Switch Level Model / Transistor Model (一般不常用)
* Gate Level Model 邏輯閘層次模型
* 使用基本邏輯閘元件: AND, OR, NOT
* **邏輯電路圖**
* Data Flow Model 資料處理模型
* 描述電路中資料的處理方式
* 資料如何在電路中**運算及傳送**
* 輸出**持續驅動**輸入
* 運算式的方式呈現電路的行為,如 `out = a + b + c`
* Behavioral Model 行為模型
* Verilog 最高階的層次模型
* 不須考慮硬體元件的特性,只須放在模組的功能描述
* 需要**合成工具軟體**來呈現
* Structure Model
* 引用**硬體模組**的模式
![](https://hackmd.io/_uploads/HJ8DdQNVc.jpg =200x)
* 類似邏輯閘層次模型
* 支援階層式設計方法
6. 階層式設計: 將複雜電路分成一層疊一層的結構,架構上類似樹狀結構
* Bottom-up
![](https://hackmd.io/_uploads/H1hlFmV49.jpg =350x)
* Top-down
![](https://hackmd.io/_uploads/ry84K7EVc.jpg =350x)
* 混合式
![](https://hackmd.io/_uploads/S13LFXNNq.jpg =350x)
### Verilog 語法詞彙
#### 數值
1. Verilog 有兩種數值表示法
* 固定長度 (sized)
* 定義位元寬度
* format: `<size>'<base format><number>`
* 若要表示負數,可直接將負號放在`<size>`前面
* e.g., `18'h47CB` (其實用15bits就能表達,未給定的**高位元自動補0**)
* e.g., `13'h47CB` (要用15bits就能表達,實際只能表示7CB)
*
* 不定長度 (unsized)
* 未定義位元寬度
* format: `'<base format><number>`
2. 數值組 (Value Set)
Verilog 有四種 value level,表示實際邏輯電路中的狀態
![](https://hackmd.io/_uploads/HkUV6QE4c.jpg =400x)
### Verilog 資料物件與型態
1. Data objects
* 描述行為過程中所使用的**訊號載具**
* 一個物件**經過處理**再傳到另一個物件
2. Data type
* 定義 data object 的類型
* 接線(nets)、暫存器(registers)、參數等
3. Nets: 連接實體元件的**連接線**
* 要**被驅動**才能改變其內部的值
* `wire`
* 一個位元的純量 (scalar) 或多位元長度的向量 (vector)
* 內定值為 `z`
* 如何宣告?
```verilog=
wire w; // 內定預設值為 z
wire x = 1'b0;
wire a, b, c;
```
4. Registers
* **抽象**的資料儲存物件,有別於實體的暫存器 D flip-flop
* 保留一個數值直到下一次**指定新值為止**
* 像是C語言中的**變數**概念
* `reg`, `integer`, `real`, `time`
![](https://hackmd.io/_uploads/B1HgG4EV9.jpg =300x)
* 一個位元的純量 (scalar) 或多位元長度的向量 (vector)
* 內定值為 `x`
```verilog=
reg a; // 內定預設值為 z
reg x, y;
integer count; // 宣告一個 signed integer
real fraction; // 宣告一個 floating number
```
5. 純量與向量
* 純量 scalar: 一個位元的物件
* 向量 vector: 多個位元的物件
* `wire` and `reg`
* 預設為 scalar
* 若要定義為向量,使用 `[MSB:LSB]`, `[大數字:小數字]` 或 `[小數字:大數字]`
```verilog=
wire a; // 1 bit wire a
wire [4:0] x; // 5 bits wire x
reg b; // 1 bit reg b
reg [0:7] y; // 8 bit reg y
reg [31:0] z; // 32 bit reg z
```
6. Array
* 多個 `reg`, `wire` 所組成
* 透過 `index` 定義 element
* 支援多維度的陣列
* 用於 memory, register file
```verilog=
// memblock 是一個包含 128 個暫存器的陣列
// 每個暫存器是 32 bit
reg [31:0] memblock [127:0]
// mem_2D 是一個二維 4x64 的暫存器陣列
// 美個暫存器是 8 bit
reg [7:0] mem_2D [3:0][63:0]
```
7. Parameters 參數
* 定義編譯合成電路時的**常數**
* 每次編譯合成前更改,編譯合成器會根據參數值產生相對應的電路
* **重複使用**
* `parameter`
```verilog=
parameter width = 4;
wire [width-1:0] a, b;
```
### Module 模組概念
1. Module 模組
* 一個**電路區塊**
* 可以由其他模組組成
2. 連結模組時,只需考慮模組的**輸出與與輸入**介面,不須考慮模組內部的詳細電路
3. 電路設計時,只修改模組內的電路,不會改變模組對外及週邊的模組
4. 如何宣告?
* 關鍵字 `module`
* 模組名稱 `<module_name>`
* 輸入與輸出埠列 `(<module teminal list>)` 和埠列宣告
* 模組內部關於電路的描述
* 訊號資料型態宣告
* 引用其他模組、邏輯閘
* `assign` 資料處理模型之描述
* `always` 行為模型之描述
* function 與 task
* 除了訊號宣告需要先描述,其他部份的撰寫順序不會影響電路的行為
* 最後以關鍵字 `endmodule` 做為模組結尾
5. Module 基本型
![](https://hackmd.io/_uploads/B150vNEEq.jpg =300x)
6. 埠 (Port)
* 終端點 (terminal)
* module 與外界溝通的介面接點
* 一個模組通常是經由一串輸入輸出埠稱為**埠列 (terminal list)** 與外界溝通
* 若模組不須與外界溝通,則 terminal list 也不須存在 → 封閉系統
7. Port declaration
* `input`, `output`, `inout` (雙向埠)
* port 的 data type 預設為 `wire`,若要將訊號儲存起來則須宣告成 `reg`
* <font color="red">input 和 inout 只能是 `wire`</font>,因為輸入訊號只接受外來訊號 (被外部訊號所驅動)
* <font color="red">output 可宣告為 `wire` 或 `reg`</font>
```verilog=
module fulladder(a, b, c_in, sum); // terminal list
input [3:0] a, b;
input c_in;
output [4:0] sum;
reg [4:0] sum;
...
endmodule
```
### Gate Level Model 邏輯閘層次模型
1. 利用關鍵字即可引用基本的邏輯閘元件
* `and`, `nand`, `or`, `nor`, `not`, `xor`
2. 多個輸入邏輯閘
![](https://hackmd.io/_uploads/ryK5ur44c.jpg =350x)
![](https://hackmd.io/_uploads/SJYcdSN49.jpg =350x)
![](https://hackmd.io/_uploads/S1tcuH4Ec.jpg =350x)
3. 多個輸出邏輯閘
![](https://hackmd.io/_uploads/ByETuSE49.jpg =350x)
![](https://hackmd.io/_uploads/SJVpdHEN5.jpg =350x)
![](https://hackmd.io/_uploads/rkEaur4V9.jpg =350x)
4. 使用範例
![](https://hackmd.io/_uploads/Bk7ytrEVq.jpg =350x)
### Structural Model 結構式模型
1. 方塊架構圖,引用子模組完成上層模組
![](https://hackmd.io/_uploads/BJEBorEEc.jpg =150x)
* 不需要了解子模組的內部設計,重點放在模組的**介面與功能**
* 類似邏輯閘層次模型,基礎邏輯閘元件轉變成其他的子模組來替代
2. port 的連接規定
![](https://hackmd.io/_uploads/HJZfnr4V9.jpg =400x)
3. port 的對應方式
* **Position association** (in order) 位置對應
* **引用 module** 所使用的連接訊號與**被引用 module** 的埠列<font color="red">**順序一致**</font>
* ![](https://hackmd.io/_uploads/r16r6HEV9.jpg =400x)
* **Name Association** (by name) 名稱對應
* **引用 module** 所使用的連接訊號與**被引用 module** 的埠列<font color="red">**名稱相對應**</font>
* 比較推薦用這個方法
* ![](https://hackmd.io/_uploads/r1QSCrEV9.jpg =400x)
### Data Flow Model 資料處理模型
1. Usage
* 描述電路中資料的處理方式
* 資料如何在電路中**運算及傳送**
* 輸入與輸入經過運算,運算結果<font color="red">**持續驅動**</font>輸出
* 持續指定方式,`assign` 關鍵字
2. <font color="red">**Continuous Assignment 持續指定**</font>
* 資料處理模型的基本描述
* input **持續驅動** output ,input **經過邏輯閘**連接至 output
* 關鍵字是 `assign`
* `assign` 是利用<font color="red">**運算式**</font>表示 input 與 output 間的關係
* <font color="red">LHS 必須宣告為 `wire` (不能是 `reg`)</font>,因為 output 是被 input 持續驅動
* RHS 無規定
3. 隱藏式指定
* 也是持續指定
* **宣告**接線時,就指定與其他接線的關係
* 省略 `assign`
4. 持續指定是**永遠驅動的狀態**
* RHS 訊號 (input) 變動,LHS 指定的接線內容 (output) 就會跟著改變
* input 直接影響 output
* 持續指定主要是用來描述組合電路
```verilog=
// 正規式持續指定
wire wout1, a, b;
assign wout1 = a & b; // and 閘的運算式,a, b 為 input, wout_1 為 output
// 隱藏式持續指定, assign 可省略
wire wout2 = a & b;
```
```verilog=
// another example
module and_or_dataflow(in1, in2, in3, in4, out);
input in1, in2, in3, in4;
output out;
assign out = (in1 & in2) | (in3 & in4);
```
![](https://hackmd.io/_uploads/ry4p48VN9.jpg =150x)
### Expression 運算式表示
1. 用來描述訊號與其他訊號之間的關係
* 由 operand 和 operator 組成
* e.g., `X = A * (B + C)`
2. Operand 的資料型態
* 常數、整數、實數、`wire`、`reg`、陣列
* 函數的回傳值
* 向量 `wire`、`reg` 的一個、部分個位元或是全部位元
3. **算術運算子 Arithmetic Operator**
* 遇到輸入值不確定時,結果也為不確定值 (x)
![](https://hackmd.io/_uploads/B1BYD_NNc.jpg =350x)
4. **位元運算子 Bitwise Operator**
* 兩個運算元的**相對應位元**做邏輯運算
* 若兩運算元不等長,則較短者所缺之相對位則**補0**
![](https://hackmd.io/_uploads/ry5ouuE4q.jpg =350x)
5. **連結運算子 Concatenation Operator**
* 序連運算子 `{}`: 將不同的運算元做連結,連結之運算元其**位元數必須明確**
* 重複運算子 `{{}}`: 將一個運算元重複一個指定的次數
```verilog=
wire A = 1'b1;
wire [1:0] B = 2'b10;
wire [2:0] C = 3'b111;
// 記得定義 Y1 的時候要定義五個位元給他
assign Y1 = {B, C}; // Y1 = 5'b10_111
assign Y2 = {C, A, B[0]}; // Y2 = 5'b111_1_0
assign Y3 = { {3{C[2:1]}}, {2{B}}, A}; // Y3 = 11'11_11_11_10_10_1
```
6. **相等運算子 Equality Operator**
* 判斷兩運算元是否相等
* 屬於判斷運算式,回傳 0/1
* 邏輯上相等 (`==`, `!=`): 若運算元出現 `x` 或 `z` 皆回傳 `x` → 運用在電路設計上
* 事件上相等 (`===`, `!==`): 若運算元包含 `x` 或 `z` 皆做相等判斷 → 較為嚴謹,運用在模擬驗證比對上
![](https://hackmd.io/_uploads/rkUP7tVVc.jpg =350x)
7. **關係運算子 Relational Operator**
* 比較大小 (當成 <font color="red">**unsigned**</font> 做比較)
* 判斷運算式,回傳 0/1
* 若運算元為不確定值 `x`, `z` 時,結果也為不確定值 `x`
![](https://hackmd.io/_uploads/S1WzBFNN9.jpg =350x)
8. **邏輯運算子 Logical Operator**
* 將運算元先以真/偽判斷後,再進行邏輯運算
* 判斷運算式,回傳 0/1
* `x` 代表不確定值
![](https://hackmd.io/_uploads/rJ2y8FE4c.jpg =350x)
```verilog=
// X = 3'b110, Y = 3'b100
assign out = ( (X > 2) && (Y < 3) );
// && 視同 and 閘,但兩邊需要是 1-bit 的東西
```
9. Logical Operator vs. Bitwise Operator
![](https://hackmd.io/_uploads/SkIhIYNVq.jpg =350x)
10. **判斷運算子 Conditional Operator**
* 三元運算子
![](https://hackmd.io/_uploads/ryGtQ8H4q.jpg =350x)
```verilog=
wire select;
assign out = select ? a : b;
// select == 1'b1 則 out = a; else out = b
wire [3:0] X, Y, Z;
wire [3:0] out1, out2;
assign out1 = (X<Y) ? X : Y;
// 巢狀結構
assign out2 = Z ? Z : (X ? X : Y);
// assume X = 4'b1100, Y = 4'b1100, Z = 4'b0000
// out2 here = 4'b1100
```
11. **簡化運算子 Reduction Operator**
* 類似 bitwise operator,只需要一個運算元
* 將單一運算元的所有位元做邏輯上的運算,最後輸出一個位元的結果
* ![](https://hackmd.io/_uploads/BkOz88BVc.jpg =250x)
![](https://hackmd.io/_uploads/r1lDUIBNc.jpg =350x)
```verilog=
// X = 4'b1110
assign O1 = &X; // 1'b0
assign O2 = |X; // 1'b1
assign O3 = ^X; // 1'b1
```
12. **移位運算子 Shift Operator**
* 左移和右移
* 將向量運算元向左或向右移特定的位元數
* 移位所產生的空格自動補 0
![](https://hackmd.io/_uploads/BJMFOIBVc.jpg =350x)
```verilog=
wire [5:0] X = 6'b110111;
wire [5:0] O1, O2, O3;
assign O1 = X << 4; // 6'b110000
assign O2 = X >> 3; // 6'b000110
assign O3 = X << 2; // 6'b011100
```
13. **其他運算子**
![](https://hackmd.io/_uploads/ByjdtLHE9.jpg =350x)
14. Operator Precedence 運算子優先權
![](https://hackmd.io/_uploads/SyQ6K8HE5.jpg =350x)
### Behavioral Model 行為描述模型
1. Introduction
* Verilog 中**最高階**的層次模型
* 不須考慮硬體元件如何實現,只須放在模組的**功能描述**
* 使用<font color="red">**程序指定 Procedural assignment**</font> (有別於前面講到的 continuous assignment)
* 高階語法透過合成軟體工具轉換成邏輯閘
2. <font color="red">**程序指定 Procedural assignment**</font>
* Behavioral Model 的基本描述
* Combinational circuit 組合電路
* Sequential circuit 循序電路
* 關鍵字 `initial`, `always` 引導出的**區塊**描述行為
* **區塊內的 output 資料 (等號 LHS),用 `reg` 宣告**
* 用於測式波形的撰寫或電路驗證的描述
3. `initial` 關鍵字
* 區塊內的描述**只執行一次**
* 多行敘述須以 `begin...end` 包覆
* sequential block: 按順序執行
* 區塊內的 output 資料 (等號 LHS),用 `reg` 宣告
```verilog=
reg a;
initial
a = 1'b1;
reg a, b, c;
initial
begin
a = 1'b0;
b = 1'b1;
c = a & b;
end
```
4. **Blocking (Procedure) Assignment 限制指定 `=`**
* 在 **sequential blocks** (`begin...end`) 中的位置,**依序**執行
* 像C語言指令敘述是由上而下依序執行
* Blocking assignment 的符號是 `=`
```verilog=
// 順序影響結果
initial
begin
A = 3;
B = 2;
C = 1;
...
B = C; // B is 1
A = B; // A is 1
end
initial
begin
A = 3;
B = 2;
C = 1;
...
A = B; // A is 2
B = C; // B is 1
end
```
5. **Non-blocking (Procedure) Assignment 無限制指定`<=`**
* 在 **sequential blocks** (`begin...end`) 中的位置,**平行**處理
* 執行順序不受位置影響,每行敘述位置可以**任意調換**
* Non-blocking assignment 的符號是 `<=`
```verilog=
// 順序不影響結果
initial
begin
A = 3;
B = 2;
C = 1;
...
// 同時執行,可以先把 RHS 的值寫出來,再同一時間給到 LHS
B <= C; // B is 1
A <= B; // A is 2
C <= A; // C is 3
end
initial
begin
A = 3;
B = 2;
C = 1;
...
A <= B; // A is 2
C <= A; // C is 3
B <= C; // B is 1
end
```
6. `always` 關鍵字
* 區塊內的描述**永無止盡**
* 描述電路的行為
* **事件觸發** `@(事件表示式)`
* 多行敘述須以 `begin...end` 包覆
* **區塊內的 output 資料 (等號 LHS),用 `reg` 宣告**
7. 事件觸發
* **輸出改變**是因為**事件發生**
* 對於組合電路 (conbinational circuit) 來說,輸入有變化就是一個事件
* 對於循序電路 (sequential circuit) 來說,時脈 (clk) 變化就是一個事件
8. `always` 基本型
![](https://hackmd.io/_uploads/B1FhfvB4q.jpg =300x)
9. 事件表示式
* **組合電路 (combinational circuit)** → 直接放入訊號 (變數)
* 訊號 (變數) 發生變化時 → 0-to-1, 1-to-0
* 可以為純量或向量訊號 (變數)
* 可以有多個訊號 (變數),中間以 `or` 區隔
```verilog=
reg out;
always @(a or b)
begin
out = a & b; // LHS should be reg
end
```
* **循序電路 (sequential circuit)** → 放入**邊緣觸發**的**純量**訊號
* `posedge` 正緣觸發: 由 0 變化到 1 的瞬間
* `negedge` 負緣觸發: 由 1 變化到 0 的瞬間
* 訊號只能是純量
* 可以多個邊緣觸發訊號 (變數),中間以 `or` 區隔
```verilog=
// a, b 變化不會馬上影響 out
reg out;
always @(posedge clk)
begin
out <= a & b; // LHS should be reg
end
```
### Conditional Statement 條件敘述
1. `if...else if...else...`
* 若為多行執行敘述,須以`begin...end` 包覆
* 因為條件敘述是行為描述,所以要放在 `initial`, `always` 所引導的**行為區塊**內
```verilog=
reg [1:0] out; // 記得在 always 中的 LHS 一定要是 reg
always @(a or b)
begin
if (a == b)
out = 2'b10;
else
out = 2'b01;
end
```
### Multi-Way Branching 多路分支敘述
1. `case...endcase`
* 關鍵字以 `case` 開頭,`endcase` 結尾
* 剩餘未指定的條件,用關鍵字 `default` 一網打盡
* 要放在 `initial`, `always` 所引導的**行為區塊**內
```verilog=
// sel, a, b, c: 2 bits
// out: 2 bits
always @(*)
begin
case(sel)
2'b00: out = a;
2'b01: out = b;
2'b10: out = c;
default: out = 2'b00;
endcase // don't forget!
end
```
2. `casex` 和 `casez`
* `case` 敘述,不允許分支條件含有 "don't care"
* 會針對 `0, 1, x, z` 比對
* `casex` 和 `casez` 允許含有 "don't care"
* `casex` 使用 `x` 來代表 "don't care"
* `casez` 使用 `?` 或 `z` 來代表 "don't care"
```verilog=
// casex example
// sel, a, b, c: 2 bits
// out: 2 bits
always @(*)
begin
casex(sel)
2'b0x: out = a; // 當 sel[1] = 1'b0 時,out = a
2'b1x: out = b; // 當 sel[1] = 1'b1 時,out = b
default: out = c;
endcase // 勿忘
end
// casez example
// sel, a, b, c: 2 bits
// out: 2 bits
always @(*)
begin
casex(sel)
2'b?1: out = a; // 當 sel[0] = 1'b1 時,out = a
2'b?0: out = b; // 當 sel[0] = 1'b0 時,out = b
default: out = c;
endcase // 勿忘
end
```
### 迴圈敘述
1. 關鍵字
* `forever`
* `repeat`
* `while`
* `for`: 常用,其他的會用在模擬、驗證
2. 放在程序指定敘述內: `initial`, `always`
3. `forever` 敘述
* 持續執行某個敘述,**永無止盡**
* 通常搭配**時間延遲**產生週期性的訊號 → 波型模擬
```verilog=
reg clock
initial
begin
clock = 1'b0;
forever #5 clock = ~clock; // 延遲5個時間單位
end
```
4. `repeat` 敘述
* 持續執行某個敘述,**重複n次**
```verilog=
reg clear
initial
begin
clear = 1'b0;
repeat (3) #5 clear = ~clear; // 重複3次,延遲5個時間單位
end
```
5. `while` 敘述
* 迴圈一直執行,直到其條件運算式不成立
```verilog=
reg [2:0] count;
initial
begin
count = 3'd0;
while( count < 3'd4)
count = count + 1'd1;
end
```
6. `for` 敘述
* `for` 迴圈包含三部分
* 初始條件
* 判斷終止條件
* 改變控制變數的程序指定
* 精簡程式碼,不節省硬體
```verilog=
input [4:0] a, b;
output [4:0] out;
reg [4:0] out;
always @(*)
begin: bits_and_blk // begin...end 區塊標籤
integer i; // 區域變數
for (i = 0; i < 5; i = i + 1) // 不可以用 i++
out[i] = a[i] & b[i];
end
```
### 函數與任務
1. Function
* 關鍵字 `function` 開頭,`endfunction` 結尾
* 可使用**程序指定**
* 不能包含時間延遲控制的指令
* 至少有一個輸入且**回傳單一個值**
* 常用在電路設計 (可合成)
2. Function 基本型
* 函數的名稱就代表函數的回傳值,所以可以在定義函數時一併定義其位元數
* 函數的宣告須放在 module 中,也就是若這個 module 會用到這個 function,就要把該函數宣告在這個 module 中
![](https://hackmd.io/_uploads/HywiIsFEc.jpg =300x)
```verilog=
// example 1
module min(a, b, c, x, y);
input [3:0] a, b, c;
output [3:0] x, y;
reg [3:0] x, y;
always @(*)
begin
// call a function
x = min_fun(a, b); // 位置對應
y = min_fun(a, c);
end
// declare a function
function [3:0] min_fun;
input [3:0] in1, in2;
begin
if (in1 < in2)
min_fun = in1;
else
min_fun = in2;
end
endfunction
endmodule
// example 2
module min(a, b, c, x, y);
input [3:0] a, b, c;
output [3:0] x, y;
// 用 assign 的話,LHS 不可以是 reg,預設是 wire
assign x = min(a, b);
assign y = min(a, c);
// declare a function
function [3:0] min_fun;
input [3:0] in1, in2;
begin
if (in1 < in2)
min_fun = in1;
else
min_fun = in2;
end
endfunction
endmodule
```
3. Task
* 類似函數,重複使用程式碼
* 關鍵字 `task` 開頭,`endtask` 結尾
* 可使用**程序指定**
* 可以包含**時間延遲控制**的指令
* **輸入、輸出個數不定**
* 只用能**行為描述模型**來呼叫
* 常用在模擬與驗證 (不一定能合成)
4. Task 基本型
* 記得輸出入都要定義
![](https://hackmd.io/_uploads/BJr73sF4q.jpg =300x)
```verilog=
module min(a, b, c, x, y);
input [3:0] a, b, c;
output [3:0] x, y;
reg [3:0] x, y;
always @(*)
begin
min_task(a, b, x);
min_task(a, c, y);
end
task min_task;
input [3:0] in1, in2;
output [3:0] out;
begin
if (in1 < 2)
out = in1;
else
out = in2;
end
endmodule
```
5. 函數與任務的差別
![](https://hackmd.io/_uploads/H1UvaoYV9.jpg =400x)
---
## HDLBits — Verilog Practice
用來練上機的好網站,蠻循序漸進的,但是**建議先有一定 Verilog coding 基礎再來打**,不然他講解的其實沒有很詳細
* https://hdlbits.01xz.net/wiki/Main_Page
* My Stats: https://hdlbits.01xz.net/wiki/Special:VlgStats/F37895C8C792A327