---
# System prepended metadata

title: 1. 程式風格
tags: [設計觀念, Verilog]

---

# 程式風格

###### 參考資料：[Coding Style](https://hackmd.io/@derek8955/BJB9M33yo)
> [!Tip] **目的**
> - **可讀性 ==(Readable)==**  
> - **可合成的代碼 ==(Synthesizable Code)==**  
> - **減少 ==電路面積==**  
> - **縮短 ==電路時間==**

## 1. 可讀性 (Readable)

### (1) 一些好的習慣
- **`always block` 中 ==邊緣觸發==、==準位觸發== 不要混用**
```verilog=
always@(posedge clk or a) begin /* ... */end
```
- **設計==組合邏輯==時，`always block` 使用 ==`*`(全域觸發)==**
```verilog=
always@(*) begin /* ... */ end
```
- **==組合邏輯==電路使用 ==`blocking assignment (=)`==**
```verilog=
always@(*) begin
    out = (out == 1'd0)? in1:in2;
end
```
- **==循序邏輯==電路使用 ==`non-blocking assignment (<=)`==**
```verilog=
always@(posedge clk) begin
    out <= (out == 1'd0)? in1:in2;
end
```
- **電路的 ==input==、==output== 先用 ==FF== 存起來，避免取出訊號為 ==`X`==、==`Z`== 的狀態**
```verilog=
input a;
reg a_buffer;
always@(posedge clk) begin
    if (a) b <= a;
    else b <= 1'b0;
end
```
- **多使用 ==FSM (Finite State Machine)==**
### (2) 明確區塊分工

> [!Note] **說明**
> - **在設計電路時，==不要==把所有變數==寫入同一個程式區塊中==**  
> - **建議==分散==成不同的電路區塊，每個區塊有==不同==的主要==功能==**  
>   - **ex： ==FSM== 中，把 ==CS==、==NS==、==OL==分開撰寫**
>     ```verilog=
>     always@(posedge clk) begin
>         if (reset) CS <= S0;
>         else CS <= NS;
>     end
>     always@(*) begin
>         case(CS)
>             S0: NS <= /*...*/
>             S1: NS <= /*...*/
>             default: NS <= /*...*/
>         endcase
>     end
>     always@(*) begin
>         case(CS)
>             S0: OL <= /*...*/
>             S1: OL <= /*...*/
>             default: OL <= /*...*/
>         endcase
>     end
>     ```

> [!Tip] **優點**
> - **==邏輯分清楚==，debug 比較輕鬆**  
> - **==電路合成==會比較接近預期結果**

## 2. 避免在組合邏輯中產生 ==Latch==

### (1) 不要沒寫完組合邏輯的 ==條件表達式== 

> [!Caution] **注意：**  
> - **ex1：`CASE` ==狀態沒列完==**  
>   ```verilog=
>   always@(*) begin
>       case(sel)
>           2'd0: out = in1;
>           2'd1: out = in2;
>       endcase
>   end
>   ```
> - **ex2：`IF` ==沒有接`ELSE`==**  
>   ```verilog
>   always@(*) begin
>       if(en) out = in;
>   end
>   ```

> [!Tip] **原因**
> - **組合邏輯的 ==訊號== 在電路中只是 ==一條帶有標籤的線路(`wire`)==**  
> - **所以 ==`wire` 不會儲存訊號狀態==**  
> - **因此當條件表達式遇到 ==未定義的條件==時，需要先將 ==原本的訊號保存==下來**  
> **直到遇到 ==已定義的條件==**

### (2) 不要在組合邏輯電路中產生 ==回授電路==

> [!Caution] **注意：**
> - **ex：`a = ~c;` `b = ~a;` `c = ~b;`**  
> ![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjpV_qZVsuHEK6KROI-5qCAg3ojgnxnPCh8F_kcn_T8NZKTF0KrRPh_MGj_QImDM1v33_pwZgcDNohpUWL-x4u9_hE-uAI5F5Z6zRjVdkRlrW4S_Gw6ctNSIAZXQ2Rhj5jmOE0yoyQM90M/s1600/Ring_Osc.bmp)  
> - **ex：把輸出透過==組合邏輯電路==、==直接連線==送到輸入**
>   ```verilog=
>   wire sel;
>   wire [3:0] a;
>   assign a = b ? a : a + 1;
>   ```

> [!Tip] **原因**
> - **一樣是 ==`wire` 不會儲存訊號狀態== 的問題**  
> - **要把==原始的訊號==送回輸入端，產出==新的訊號==，**  
> **需要先把==原始的訊號==保存起來，才能送回輸入端**

### (3) 循序邏輯電路不會產生 ==Latch==

> [!Tip] **原因**
> - **循序邏輯的 ==訊號== 在電路中是==DFF 的輸出(`reg`)==**  
> - **所以 ==`reg`== 本身具有 ==栓鎖功能==**
> - **且 ==觸發源== 來自程式中的 ==`always@()` block==**
> - **==Latch== 沒有跟著 ==`always@()` block== 的觸發源**
> - **ex：以下電路==不會產生 Latch==**
>   ```verilog=
>   reg [3:0] a;
>   always@(posege clk) begin
>       if(flag) a <= 3;
>   end
>   ```



---