---
# System prepended metadata

title: 硬體描述語言
tags: [university note]

---

###### 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)
