###### tags: `university note` [TOC] # 硬體描述語言 ## CH1 ___ ```verilog= module add_half_struct (a, b, sum, c_out); input a, b; output sum, c_out; wire c_out_bar; xor G1//取名(sum, a, b); nand G2(c_out_bar, a, b); not G3(c_out, c_out_bar); xor #1(sum, a, b); //延遲1ms #表延遲 endmodule ``` ___ ### 0-1,1-0 delay轉換延遲 ```verilog= module nanf201 (A1, B1, O); input A1, B1; output O; nand (O, A1, B1); specify specparam Tpd_0_1 = 1.13:3.09:7.75, // rising delay (min-typical-max) Tpd_1_0 = 0.93:2.50:7.34; // falling delay (min-typical-max) (A1 => O) = (Tpd_0_1, Tpd_1_0); (B1 => O) = (Tpd_0_1, Tpd_1_0); endspecify endmodul ``` ![](https://hackmd.io/_uploads/HyQ9Ttflp.png) ___ ### 一些基礎電路語法 `assign sum = a+b; //assign宣告讓sum在a,b之後改變時會同時改變` #### MUX ```verilog= input [1:0]select; output y_out; assign y_out = (a && !select[1] && !select[0]) ||(b && select[1] && !select[0])||.... ``` ![](https://hackmd.io/_uploads/H1owzqGgT.png) ___ ### Module Function 要用幾次就寫幾次(電路角度思考) ![](https://hackmd.io/_uploads/r1XpynMx6.png) ```verilog= module main_MOD(); MOD_A(); endmodule module MOD_A(); .... endmodule ``` **Full adder with module** Add_half是我們寫的一個module ![](https://hackmd.io/_uploads/SyiBH5Mxa.png) ___ ### 宣告單變數多個值(類array) `[x:y]variable;` ```verilog= module bitArray(y, a, b); input [7:0]a, b; //類似陣列宣告 output [7:0]y; assign y = a|b; ``` ![](https://hackmd.io/_uploads/rkofnqzla.png) ___ ### Port connection by name `module(.modvariable(variable)...)` ```verilog= module main; wire [3:0] g; mod(.a(g[0]), .b(g[1]), .c(g[2]), .c(g[3])); endmodule module mod(a,b,c,d); output a,b; input c,d; endmodule ``` ___ ### bitArray自己操作 可讓bitArray內的值自行互相操作 ```verilog= //一般寫法 module and4_assign_1 (x_in1, x_in2, x_in3, x_in4, y_out); input x_in1, x_in2, x_in3, x_in4; output y_out; assign y_out = x_in1 & x_in2 & x_in3 & x_in4; endmodule //更好的寫法 module and4_assign_2 (x_in, y_out); input [3:0] x_in; output y_out; assign y_out = & x_in; endmodule ``` ___ ### always語法 反覆執行always內的code ```verilog= always begin ... end always@(a or b) //a或b滿足觸發 always@(posedge clk) //上緣觸發 always@(negedge clk) //下緣觸發 ``` :::danger `always`宣告內的輸出要多加reg ```verilog= output out; reg out; always@(a or b); begin out = ....; end ``` ::: ##### Always + bitArray ```verilog= module and4_alg (y_out, x_in); input [3:0] x_in; output y_out; reg y_out; integer k; always @ (x_in) // x_in[3] or x_in[2] or x_in[1] or x_in[0] begin: and_loop y_out = 1; for (k=0; k <= 3; k = k+1) if (x_in[k] == 0) begin y_out = 0; disable and_loop; end end endmodule ``` ___ ### bitArray減少code行數 ![](https://hackmd.io/_uploads/ry4qW3GeT.png) :::danger **必須要有一定規則** EX:[24:0]output, 每小段都切5bit ::: ![](https://hackmd.io/_uploads/Bkle8-HZT.png) [bit數]'[base][val] ___ ## CH2 ### Inertial Delay Due to propagation delay, the input signal pulse duration need to longer than **inertial delay time** ![](https://hackmd.io/_uploads/rJiLh-Sbp.png) ___ ### Unit Test 思考需要甚麼輸入->設計code->設計輸出monitor->對拍測試 設計state diagram ![](https://hackmd.io/_uploads/r1T_dzS-T.png) EX: NAND-Latch test ``` ``` ___ ### Variable x: unknown z: high impedence **$\neg x$ is not exists** ___ #### Data types * Structural Connectivity: **net**(wire, wand...) * Data Storage: reg * Procedural Computation: integer, real, time, realtime :::info reg(register)都是static nets主要是線路設計出來連接(實際電路會做出來) ::: ___ #### Nets 主要是不同電路設計模組與閘之間的連接 ##### wire 連接電路與訊號,不像邏輯閘本身有邏輯運算行為 * tri same as wire, but with tri-stted(類似多工器控制是否input signal) ![](https://hackmd.io/_uploads/HkdKvQBZT.png) * supply0 gnd接地 * supply1 接電源 ![](https://hackmd.io/_uploads/rkregIAWT.png) ___ #### Regs * use in flip-flop or latch stored * stored in memory(不輸出電路) * always use in prcedural statement * initial value: "x" :::danger unsigned value(注意取補數時) ::: ___ #### module間net和reg限制 ![](https://hackmd.io/_uploads/rJzyX8RZ6.png) ___ #### 2D-Array 電路中沒有真正的2d-array 對一個bitarray去開n個重複個bitarray `reg [31:0] array[0:1023] -> array[1024][32] `![](https://hackmd.io/_uploads/Sy_pV8AZa.png) ___ #### Module Hierarchical(模組間階層) Reference 父模組可透過identifier取子模組值 ![](https://hackmd.io/_uploads/B1Kan8CWT.png) ___ ### Parameter(Const) :::info Verilog特殊用法 ![](https://hackmd.io/_uploads/B1QmaLC-T.png) #**(4,5)代表size=4,delay=5**變成有點類似function的預設parameter值 ::: ___ ### 數學運算 ![](https://hackmd.io/_uploads/rJaXZDAZa.png) sum,diff,neg由於上面是開5bit,所以會有5個bit :::danger **注意reg是unsigned value** ::: #### Reduction 簡稱自己內部做bitwise ![](https://hackmd.io/_uploads/SyogMDCbp.png) ___ ### Operators * !num: 判斷是否為正數 * ===: 完全相等於(包括x,z都要依樣) * 其餘大致跟C++差不多 設計輸入電路時,可以寫緩衝避免奇怪沒用到的資料混進去 ![](https://hackmd.io/_uploads/ByeA5_wM6.png) ![](https://hackmd.io/_uploads/BJoE2uDM6.png) ___ #### 信號組合合成 使用`{}` EX: `{10,01}=1001` ___ ## CH3 電路行為描述 * 注重function化(注重function功能較不注重內部電路設計) * 合成到ASIC, FPGAs * 非所有電路都可組合輸出,也非所有組合輸出都合乎預期 ### Behaviors 自己去查怎麼用 * initial * initialize a simulation and create stimulus waveforms * always ![](https://hackmd.io/_uploads/HygjeFDG6.png) 每一個behavior都是各自獨立同時執行的 ![](https://hackmd.io/_uploads/HyqvttPM6.png) ___ ### Procedural assignment * Continuous Assigment:(static) * 連續賦值語句總是處於激活狀態。只要任意一個操作數發生變化,表達式就會被立即重新計算。 * assign * 只能用在NET * Procedural Assigment: * 阻塞賦值Blocking(=): 等這段跑完才跑後面 * 非阻塞賦值Non-blocking(<=): 併發執行,語句順序不影響 * 在always/initial內使用 * 只能用在reg * Procedural Continuous Assigment: * 在always/initial內使用 ___ #### assign/deassign(PCA) 可用於reg的變數 * assign * assign的优先级高于普通过程赋值语句 * 後一條assign賦值會覆蓋前一句 * 類似把變數進入static狀態 * deassign * deassign後變數保持上一次賦值的內容 * 解除連續賦值狀態 EX: * MUX: 若無使用assign則a,b,c,d更改時y_out不會更改可能不會是我們想要的 ![](https://hackmd.io/_uploads/HJXGTFwf6.png) * SR latch: 注意紅框兩部分當有clear/preset指令時assign q 到指定值會覆蓋前段`q = data`的部分,而若要讓`q = data`則先deassign q ![](https://hackmd.io/_uploads/BJ1G-5PGp.png) ___ #### force/release(PCA) 可用於reg/wire變數,測試電路時感覺很實用(debug) EX: debug時不想管in1/2/3那邊直接測試可用force/release ![](https://hackmd.io/_uploads/SkaUI5Pf6.png) ___ **各種狀態適用Net,Reg表** ![](https://hackmd.io/_uploads/rkFoU5wf6.png) ___ ### Time Control 不同#的位置會在不同地方產生延遲 ![](https://hackmd.io/_uploads/H1DjKqwfa.png) ___ #### Event Control Operator(@) `@(event)`當event產生變化,則進行下面的操作(常搭配always使用) 若@內還有其他@則有可能會依據目前狀態進行到哪邊而有無視事件 ![](https://hackmd.io/_uploads/SJ7U5cDf6.png) ![image.png](https://hackmd.io/_uploads/SyILHaemp.png) 注意sig_B和sig_A變化的時間 EX: * Flip-flop :::danger flip-flop值的更改需依照clk不可依set/reset...會造成值更改錯誤,跟預想不一樣 ::: #### Intra assignment delay `a = @(enable) b+c //intra assigment delay` `@(enable) a = b+c //inter assigment delay` 兩者是不同的,同理`#` ___ ### Event `event (variable_name)`宣告一個事件變數 ```verilog= event up_edge always@(posedge clock) ->up_edge; always@(up_edge) begin q = data; end ``` clock觸發->up_edge->後續判斷到up_edge改變去對flip-flop做改變 EX: ![image.png](https://hackmd.io/_uploads/Sy_hY2eX6.png) event可以跨模組使用,方便! ___ #### Wait [wait和@的差別](https://blog.csdn.net/qq_41894346/article/details/104964478) `wait(enable) ` wait中的值為TRUE時,觸發wait後的描述 EX: latch ![image.png](https://hackmd.io/_uploads/S1VH23eXp.png) ![image.png](https://hackmd.io/_uploads/HkzSgTeXp.png) 有多種寫法,此為用wait之寫法 ___ #### Event with non-blocking ![image.png](https://hackmd.io/_uploads/ryeN9l0emT.png) :::danger ![image.png](https://hackmd.io/_uploads/Sywc8Cl7a.png) ![image.png](https://hackmd.io/_uploads/BJkjLReXp.png) ::: ___ #### Non-blocking運作 :::info 1. The non-blocking statements are encountered first in the sequential activity flow, and sample the values of c and d (x). 2. The blocking assignments at the same time step then execute in order, setting c to 0 and d to 1. 3. Then the non-blocking assignments execute, setting c to x and d to x. 4. Thus, the non-blocking assignments overwrite the blocked assignments at the same time step. 取樣RHS->執行同時間的blocking->執行non-blocking ::: ___ #### display&monitor ![image.png](https://hackmd.io/_uploads/Hyh7-lcXp.png) * **Montitor和display同時出現時,display會優先執行** * display遇到non-blocking會印non-blocking前的值 * monitor會印non-blocking後的值 ___ ### LFSR 產生一長周期的數字排列(偽隨機數) ![image.png](https://hackmd.io/_uploads/H1cE1-qmp.png) ![image.png](https://hackmd.io/_uploads/HkMSk-9X6.png) ___ ### Repeat Intra-assignment Delay `repeat(count)`:條件重複5次後才執行 * if count it x/z -> 0 * use`disable` to stop count repeat ![image.png](https://hackmd.io/_uploads/BySfzbcQp.png) reg_b會在經過5次正緣後=10時間單位時reg_a的值 ___ ### 模糊賦值(同時間對值有不同賦值) 可能會造成不確定賦值 ___ ### Activity Flow Control * 三元運算子 * case * if/else * repeat * Loop * fork...join #### case * case * 嚴格比較 * casex * x,z可為任何可能 * casez * z可為任何可能 ![image.png](https://hackmd.io/_uploads/r1RGN-cma.png) ___ #### Loop * for * 需要注意條件判斷bits數 * while * forever * 無限執行 皆可透過`disable`強制中斷 :::danger **always v.s. foerever** * always * concurrent behavior * can't be nested * forever * computational activty flow * can be nested ::: ##### disable ![image.png](https://hackmd.io/_uploads/ryxMkzc7T.png) ___ #### fork/join Create parallel threads of activity 常用於信號分配 ```verilog= fork statement1 statement2 join ``` ![image.png](https://hackmd.io/_uploads/Byz8eMcXp.png) ___ ##### Race 同時賦值和被賦值->模糊賦值 ![image.png](https://hackmd.io/_uploads/ryqDgfc76.png) ___ ### Task and Function ![image](https://hackmd.io/_uploads/SyS4FD2E6.png) Function need LHS `() = func()`,預設返回為RHS之type ___ Task EX: ![image](https://hackmd.io/_uploads/BJoQqw2Ea.png) ___ Function EX: ![image](https://hackmd.io/_uploads/SkYPFwnNT.png) ___ ### State Chart 有state的電路可分為兩部分 1. state 2. combinational outputs 根據不同狀態和我們所期望的output訊號可以畫出狀態機 狀態機設計可主要分成三步驟: 1. clk觸發傳遞狀態(non-blocking) 2. 根據目前狀態和輸入確定下一狀態(blockin) 3. 根據目前狀態和輸入確定輸出(non-blocking) ![image](https://hackmd.io/_uploads/By27fuhEp.png) 有$n$個狀態時需要$ln(n)$個bits去儲存狀態 ___ #### Mealy machine with registered outputs 目的在於同步state和output不要在非需要時輸出output訊號(change output when clk edge) ![image](https://hackmd.io/_uploads/B1gBtdnE6.png) ___ ## CH4 ### Synthesis of Combinational Logic(組合電路合成) * 移除多餘電路 * 自動調整成多層組合電路 * 整合成黏在一起(?(找適合的電路組合) ___ ### Cyclic Behavior(always) Synthesis * 所有output都必須在行為中被賦值,否則可能會自動生成latch * 要有狀態控制訊號/事件 ![image](https://hackmd.io/_uploads/B1P4N4_Ua.png) ![image](https://hackmd.io/_uploads/S1xrV4d86.png) ___ ### Function/Task Synthesis ![image](https://hackmd.io/_uploads/HJ9j4EdUT.png) 電路基本上長一樣(? ___ #### Simulation Efficiency ![image](https://hackmd.io/_uploads/HkcKSEOL6.png) ![image](https://hackmd.io/_uploads/SkJfUE_Ip.png) ___ ### Unexpected Latches 不完全敘述的if/case(缺少else敘述、case缺default或沒寫所有可能case),此時組合電路可能會自動**添加latch表示使訊號保持訊號不變** ![image](https://hackmd.io/_uploads/BkggGX_8p.png) ![image](https://hackmd.io/_uploads/rknWfXOIa.png) ___ ### Priortiy Structure case/if在較前的敘述對電路來說優先級會更高 ![image](https://hackmd.io/_uploads/ByCLUXO8T.png) if(a)->直接跑完 if(c)->if(b)->if(a)->done EX: ![image](https://hackmd.io/_uploads/H1xDF8XdLp.png) ___ ### 7-Segment Display ![image](https://hackmd.io/_uploads/S1hB_m_U6.png) ![image](https://hackmd.io/_uploads/HyFqFXO8p.png) ___ ### Some Technology #### Mapping 可以把相關電路但不同訊號整合在一起,之後使用做mapping即可 EX: Adder的Carry和out ![image](https://hackmd.io/_uploads/r1Ze5mdIp.png) ___ #### Use Special Synthesis or Technology 用各種方法減少電路數量(省成本) ![image](https://hackmd.io/_uploads/ry18q7OI6.png) ![image](https://hackmd.io/_uploads/By98cQOU6.png) 下面的寫法只會有一次算data_a+其中一個 而原寫法會把data_a+accum和data_a+data_b都算過之後丟mux看選哪個信號 ___ #### 3-State Buffer 控制多個信號的傳輸 EX: bus ![image](https://hackmd.io/_uploads/SkYp5md86.png) ___ ___ ## CH5(序向電路-儲存元件) https://blog.csdn.net/weixin_37728585/article/details/120185758 ### Synthesis of Latch latch在enable時值會持續改變(level-sensitive) 1. 可能多次改變,或no debounce增加下一層級電路不正確性 2. 不完全的電路設計造成電路增加latch複雜化(i.e. self-feedback) ___ #### Self-Feedback :::info 示意圖 ![image](https://hackmd.io/_uploads/H18Tprbwp.png) ::: 此種電路非組合電路,且會**自動加上mux**(根據模擬軟體決定) ![image](https://hackmd.io/_uploads/Bkvb0H-vT.png) ___ #### if/case寫不完全造成的預設latch/flip-flop [verilog避免latch](https://www.runoob.com/w3cnote/verilog-latch.html) **if** * else不寫明 * 不同值賦值未寫明 ![image](https://hackmd.io/_uploads/rkguIGu86.png) 避免方式 1. 補上else敘述 2. 對信號賦予初值 ![image](https://hackmd.io/_uploads/SkuaLGdUT.png) ___ **case** ![image](https://hackmd.io/_uploads/HJ8GEzuU6.png) ![image](https://hackmd.io/_uploads/rks3GLbD6.png) 沒有列出所有Case又沒寫default,則某些合成軟體會預設default為原本值而自動添加latch ___ #### always內判斷信號不完整 always內的敏感信號有寫錯或不符合預期,该触发的时候没有触发,那么相关寄存器还是会保存之前的输出结果,因而会生成锁存器。 ![image](https://hackmd.io/_uploads/SkmqdM_Lp.png) 缺少`x_in[0]`判斷 ![image](https://hackmd.io/_uploads/Sy3gkX_LT.png) ___ ### JK-FlipFlop 直接上扣 ![image](https://hackmd.io/_uploads/HkqMCP-wp.png) case.ver ![image](https://hackmd.io/_uploads/S16mCPWDp.png) #### JK-FlipFlop內部電路 ![image](https://hackmd.io/_uploads/HyfZyd-P6.png) :::info 由j,k決定q值 j,k值不同->q必定同為j,k值 j,k值相同->根據q決定next_q之值 ::: ___ ### Clk時間 * Clk開關時間必須確保能夠讓input訊號能送進來 * 資料必須在Clk正/負緣觸發前穩定 ___ ### 各種Register #### Shift Register 多register ![image](https://hackmd.io/_uploads/BJtHCK9wT.png) 單register,因為blocking賦予 ![image](https://hackmd.io/_uploads/ryqw0K9D6.png) 等於`Data_reg[0]=Data_in` ___ #### Parallel Load Register ![image](https://hackmd.io/_uploads/SJes455vT.png) code: ![image](https://hackmd.io/_uploads/S1g245qw6.png) ___ #### Barrel Shifter ![image](https://hackmd.io/_uploads/S1X1qc9Pa.png) ![image](https://hackmd.io/_uploads/SkATtqqvp.png) MSB回到LSB ```verilog= Data_out <= {Data_out[6:0], Data_out[7]}; ``` ___ #### Ripple Counter 前項從1變成0時,此項下一clk會變成1 ![image](https://hackmd.io/_uploads/HkP-pqqP6.png) ![image](https://hackmd.io/_uploads/SkaHa95Pa.png) ```verilog= always @(negedge c0 or posedge reset) if(reset == 1'b1) count[1] <= 1'b0; else if(toggle == 1'b1) count[1] <= ~count[1]; ... ``` **並非只有clk訊號可以當作觸發clk** ___ #### Shift Register+Combinational Logic 在begin end內的組合電路敘述會被自動加上flip-flop,因此要善用assign ![image](https://hackmd.io/_uploads/S1qbrsqPT.png) ![image](https://hackmd.io/_uploads/r1lzSo9PT.png) new_signal使用到flip-flop中的sig_a/sig_b ___ #### Accumulator 累加器,可以使用`{}`把sum加上一個overflow來判斷說是否有溢位 ![image](https://hackmd.io/_uploads/SJR01Amup.png) ___ ### Data Flow Graph(重要) 資料間運算關係的圖 ![image](https://hackmd.io/_uploads/SJ5gW0Xd6.png) ___ #### Synthesis of Non-blocking ```verilog= //dataB會為上一周期的dataA always@(posedge clk) dataA = data_in; always@(posedge clk) dataB <= dataA; _____________________________________________ //dataB會和dataA一樣是正緣時的data_in always@(posedge clk) dataA = data_in; dataB <= dataA; ``` ![image](https://hackmd.io/_uploads/rJpVQC7da.png) ___ ### Synthesis of Multi-Cycle ![image](https://hackmd.io/_uploads/HJRomCm_p.png) 兩個clk,裡面的clk等收到一次外面的clk ___ ### Flip-Flop Timing(超重要) $t_{cd}$: $t_{pd}$: $t_{setup}$: $t_{hold}$: ___ ### More about Synthesis 目的要讓最後output一定要是Wire(善用assign) #### Memory Synthesis ![image](https://hackmd.io/_uploads/HJXdlyVup.png) ___ #### Synthesis of Equality Operation ![image](https://hackmd.io/_uploads/SkmZQkN_a.png) 當我們寫判斷兩signal是否相同時,合成軟體可能會合成以下電路 ![image](https://hackmd.io/_uploads/S1NN7kVd6.png) ___ #### Synthesis of Reduction Operator(自己對自己做bit operation) ![image](https://hackmd.io/_uploads/S1on7yVdp.png) 會生成以下電路 ![image](https://hackmd.io/_uploads/ByS6mk4dT.png) ___ ___ ## ModelSim 電路模擬 module+testbench(測試檔) ![](https://hackmd.io/_uploads/rknHZSA-a.png)