Verilog 與 C:Verilog 描述硬體

Verilog 描述的是硬體。僅此而已。

如果你已經掌握了微控制器編程,那麼改掉這個習慣是最難的。雖然 Verilog 看起來像是時序程式碼,但它與 74 系列邏輯閘的相似之處遠多於 C 語言程式設計。

使用閘電路原語理解 Verilog 並行性

讓我們從數位邏輯課上的一個積之和範例開始(清單 1 和圖 1)。在這個例子中,我們使用 Verilog 閘電路原語來執行 𝑌 =∑𝑚(2,4,5)。

這些 Verilog 閘電路原語在風格上類似於 C 函數,由閘類型、布林輸出參數和輸入參數組成。例如,and (Out, in_1, in_2, in_3).。

它們看起來像函數,但實際上並非函數。它們永遠不會運作。硬體只是存在而已。

module sop3_prims (
    input  wire C,       // LSB
    input  wire B,
    input  wire A,
    output wire Y
);

    wire nA, nB, nC;     // inverter wires
    wire m2, m4, m5;     // minterm wires

    not (nA, A);
    not (nB, B);
    not (nC, C);

    and (m2, nA, B, nC); // minterm 2 (010)
    and (m4, A, nB, nC); // minterm 4 (100)
    and (m5, A, nB, C);  // minterm 5 (101)

    or  (Y, m2, m4, m5); // Sum-of-products

endmodule

列表 1:使用閘電路原語建構的 Verilog 積之和硬體。


圖 1:經典的 3-bit 積總和運算,對 2、4 和 5 敏感(https://circuitverse.org/)

技術提示:清單 1 和圖 1 僅用於說明。沒有人會這樣寫程式碼。它太耗時,而且容易出錯。請參閱清單 2 以獲得更好的解決方案。

這是一個純組合邏輯電路,用 Verilog 來描述。所有元件同時存在;沒有時脈,也沒有暫存器。這與使用 74HC04 六反相器、一個三輸入 74HC11 與閘和一個三輸入 74HC4075 或閘建構電路幾乎完全相同。

積之和硬體的標準 Verilog 描述

清單 2 展示了我們積和硬體的首選 Verilog 程式碼。它比清單 1 更簡潔,也更不容易出錯。然而,我們預期 FPGA 綜合工具會為給定的 FPGA 產生幾乎相同的網表。在所有情況下,綜合工具都會將邏輯提煉為結構高效且時序高效的 FPGA 配置位,以實現最小的佔用空間和最短的傳播延遲。

技術提示:如果您仍然以微控制器的角度來看待 FPGA,那麼 FPGA 的位元檔案實際上是一個用於配置周邊裝置的大型表格。

module sop3_standard (
    input  wire C, B, A,   // LSB to MSB
    output wire Y
);

    assign Y = (~A &  B & ~C) |  // minterm 2 (010)
               ( A & ~B & ~C) |  // minterm 4 (100)
               ( A & ~B &  C);   // minterm 5 (101)

endmodule

列表 2:積之和電路的建議程式碼。

FPGA LUT 的誤解及其對時序的影響

FPGA 並非邏輯閘的集合。相反,其核心建置區塊是查找表(LUT)。本文中描述的積之和電路對應到單一 LUT。實際上,由於現代 LUT 的位數超過 3 位,因此還有剩餘空間。例如,Terasic DE23-Lite 上的 Altera Agilex 3 A3CZ135BB18AE7S 就具有一個 8 輸入 LUT,如圖 2 所示。

回顧圖 1,我們可以看到,由於反相器具有較長的傳播延遲,因此會出現典型的毛邊風險。LUT 可以將所有乘積總和合併到一個 LUT 中,從而最大限度地減少這種風險。但這並不意味著時序毛邊完全消除,而是顯著減少。對於包含多個 LUT 的大型設計,使用暫存器可以更好地實現。

圖 2:Agilex 3 FPGA 自適應邏輯方塊圖

暫存器和時脈訊號控制 FPGA 硬體

到目前為止,我們一直假設 FPGA 中的所有操作都是同時進行的。現在,隨著時脈和觸發器(也稱為暫存器或同步記憶體)的引入,我們將從組合邏輯過渡到時序邏輯。

圖 2 清晰地展示了這種差異。舉個簡單的例子,我們可以看到最上面的輸出訊號直接取自查找表 (LUT),而下一個輸出訊號則取自最上面的觸發器 (Reg)。它們分別代表組合邏輯輸出和同步邏輯輸出。

  • 組合邏輯輸出持續更新。

  • 暫存器在時脈訊號的上升沿更新。

例如,Terasic 開發板使用可編程的 TI 的 LMK3C0105A05RERR 為 FPGA 提供三個時脈訊號。

清單 3 展示了同步 Verilog 程式碼。最顯著的變化是引入了非阻塞賦值運算子「<=」以及對時脈上升沿的敏感度。與圖 2 相比,查找表 (LUT) 仍然用於執行 SOP 操作,但現在我們新增了一個暫存器。此暫存器的值與時脈訊號同步。

module sop3_registered (
    input  wire clk, C, B, A,
    output reg Y
);

    always @(posedge clk) begin
        Y <= (~A &  B & ~C) | 
             ( A & ~B & ~C) | 
             ( A & ~B &  C);
    end

endmodule

清單 3:註冊積之和硬體描述。

模擬舒適圈謬誤:Verilog 何時不再是硬體

我們一直專注於綜合邏輯,它會被轉換為配置 FPGA 的位元檔。但這並非 Verilog 的唯一用途。很快,您將會接觸到基於 Verilog 的測試平台。測試平台並非駐留在 FPGA 上,而是駐留在您的 PC 上。因此,編譯後的 Verilog 測試平台可以執行 FPGA 無法實現的功能。主要區別在於時間控制和循環能力。例如,可以開發一個 Verilog 測試平台來產生 N 個時脈週期。

如果 Verilog 程式碼開始帶有程式設計的痕跡,它將無法被綜合。

區分硬體和測試平台

我們可以從清單 4 看到一些明顯的特徵。這包括模擬時間刻度、tb(測試平台)前置碼以及表示 5 個時間單位延遲的 #5。

THIS WILL NOT SYNTHESIZE INTO AN FPGA BITFILE.

`timescale 1ns/1ps

initial begin
    clk = 0;
    {A, B, C} = 3'b010; // Apply minterm 2

    for (i = 0; i < 10; i = i + 1) begin
        #5 clk = ~clk; // Rising edge - Y updates here!
        #5 clk = ~clk; // Falling edge
    end

    // Add code to test all minterms.

    $stop;
end

清單 4:Verilog 測試平台程式碼片段。此代碼無法綜合。

技術提示:我們改天再討論 Verilog 生成器。它們看起來像是程序,但實際上是迭代硬體產生器。它們提供了一種便捷的方式來實例化 N 個模組。

作者的相關文章

如果您喜歡這篇文章,您可能也會覺得以下相關文章很有幫助: