Verilog if語句完整教學:FPGA設計中的條件判斷與應用技巧

1. 前言

Verilog HDL(硬體描述語言,Hardware Description Language)廣泛應用於數位電路的設計與模擬。其中的「if語句」是撰寫條件分支時不可或缺的要素。本文將聚焦於 Verilog 的 if 語句,從基礎語法到進階應用進行解說,同時也會介紹常見錯誤與注意事項,幫助讀者更高效地撰寫程式碼。

2. if 語句的基本語法

Verilog 的 if 語句用於根據條件來控制程式的執行。首先來看看基本語法。

if 語句的基本格式

if (條件式) begin
    // 當條件為真時執行的處理
end

if-else 語句的語法

在 if 語句中,可以針對條件為真或為假的情況撰寫不同的處理。

if (條件式) begin
    // 當條件為真時的處理
end else begin
    // 當條件為假時的處理
end

使用範例: 簡單的條件分支

以下範例展示當輸入訊號 a 為 1 時,將輸出訊號 b 設定為 1 的程式。

module simple_if_example(input a, output reg b);
    always @ (a) begin
        if (a == 1) begin
            b = 1;
        end else begin
            b = 0;
        end
    end
endmodule

3. if 語句與 case 語句的差異

在 Verilog 中,條件分支可以透過「if 語句」或「case 語句」來撰寫。理解它們的特點與適用情境,能讓程式更有效率。

適用情境的差異

  • if 語句: 適合用於條件較複雜、需要更靈活比較的情況。
  • case 語句: 適合用於多個固定值的條件判斷。

程式碼比較

以下展示同樣條件下,分別使用 if 語句與 case 語句的寫法。

if 語句的例子:

if (a == 1) begin
    b = 1;
end else if (a == 2) begin
    b = 2;
end else begin
    b = 0;
end

case 語句的例子:

case (a)
    1: b = 1;
    2: b = 2;
    default: b = 0;
endcase

當條件明確時,case 語句能讓程式碼更簡潔;但若條件較複雜,if 語句更具彈性。

4. 常見錯誤與注意事項

在使用 Verilog 的 if 語句時,經常會出現以下錯誤或需要注意的地方。

未定義值(x, z)的處理

當條件式中包含未定義值時,判斷結果可能會與預期不同。以下為範例:

if (a == 1) begin
    b = 1;
end

axz,此條件會被判斷為假。為了確保正確行為,建議考慮使用 === 運算子。

阻塞式賦值與非阻塞式賦值

在 if 語句中,賦值可以使用 =(阻塞式)或 <=(非阻塞式)。必須依情境選擇正確的方式。

// 阻塞式賦值
always @ (posedge clk) begin
    a = b;
end

// 非阻塞式賦值
always @ (posedge clk) begin
    a <= b;
end

非阻塞式賦值更適合用於時脈同步的處理。

5. if 語句的實務應用

在 Verilog 中,if 語句的用途不僅限於基礎條件分支。在實際的電路設計中,它廣泛應用於狀態機以及複雜控制邏輯的建構。本章將透過範例介紹實務中的用法。

在狀態機中的應用

狀態機是電路設計中最常見的模式之一。在依據條件進行狀態轉換時,常會用到 if 語句。

範例: 三狀態的簡單狀態機

module state_machine(
    input clk,
    input reset,
    input start,
    output reg done
);
    reg [1:0] state;
    parameter IDLE = 2'b00, RUNNING = 2'b01, COMPLETE = 2'b10;

    always @(posedge clk or posedge reset) begin
        if (reset) begin
            state <= IDLE;
            done <= 0;
        end else begin
            case (state)
                IDLE: begin
                    if (start) state <= RUNNING;
                end
                RUNNING: begin
                    // 根據條件進行轉換
                    state <= COMPLETE;
                end
                COMPLETE: begin
                    done <= 1;
                    state <= IDLE; // 回到初始狀態
                end
                default: state <= IDLE;
            endcase
        end
    end
endmodule

在這個範例中,狀態從 IDLE 轉換到 RUNNINGCOMPLETE,過程中透過 if 語句控制邏輯。

處理複雜條件分支

當多個條件同時相關時,if 語句能有效簡化程式。以下範例展示如何在所有條件成立時控制輸出。

範例: 特定條件的判斷

always @(posedge clk) begin
    if (enable && (data_in > threshold) && !error) begin
        data_out <= data_in;
    end else begin
        data_out <= 0;
    end
end

此處僅在以下條件同時成立時,data_out 才會被更新:

  1. enable 啟用。
  2. data_in 大於 threshold
  3. error 未發生。

模擬與實體電路的差異

在 Verilog 中,模擬環境與實體硬體的行為可能不同。特別是在 if 語句中,需注意以下要點:

  1. 初始值設定
    在硬體中,所有訊號必須被明確初始化;但模擬中,初始值常為 x,容易造成預期外的行為。
  2. 轉換時機差異
    在硬體中,因存在時脈延遲,分支條件的判斷時機可能與模擬不同。

範例: 初始值設定的建議方法

initial begin
    data_out = 0;
end

透過此方式,可提升 if 語句在實務中的穩定性。