# 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