---
# System prepended metadata

title: Verilog Courses
tags: [verilog]

---

# 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