1. 介紹:「display」在 Verilog 中的重要性與目的 「display」在 Verilog 中是什麼意思? 在 Verilog 中,$display 是一個系統任務,用來在模擬過程中「顯示」設計的內部狀態。它類似於 C 語言的 printf,可以將訊號、變數值與字串輸出到終端機或主控台——在除錯與功能驗證中扮演核心。為什麼 $display 對 Verilog 開發至關重要? 提升除錯效率 :在複雜的電路設計中,能即時觀察內部訊號是否正常運作相當關鍵。使用 $display ,即可在模擬時立即檢查感興趣的訊號值。模擬可視化 :當僅靠波形圖追蹤特定時間點的值變化可能不足時,顯示日誌提供了可靠的方式標示那些精確時刻。同時有助於文件編寫 :在向其他工程師說明設計意圖或操作規則時,加入註解式的顯示日誌可以增進程式碼的可讀性。本文的目的與結構 在本文中,我們將系統性說明以下內容:基本語法與使用方式 :細緻介紹 $display 的基本語法與使用方法。與其他系統任務的比較 :整理 $write、$strobe、$monitor 等與顯示相關任務的差異。格式化字元與進階使用技巧 :說明 %d、%b、%h、%s 等格式化字元的使用,以及特殊的顯示技巧。實務使用範例 :提供測試平台與程式碼範例,讓讀者能立即上手。顯示控制的應用 :舉例說明硬體輸出(如 LCD、螢幕)與文字/影像顯示的情境。 透過上述結構,無論是初學者或中階使用者,都能正確理解 Verilog 中的 $display,並在實務上加以運用。接下來的每個章節,我們都會盡量以範例與圖示說明,讓概念更清晰。
2. $display 基礎:語法、使用情境與注意事項 $display 的基本語法 在 Verilog 中使用 $display 時,其基本語法如下。$display("string or format specifiers", signal1, signal2, ...);
字串部分 :寫入欲顯示的文字或格式化字元(例如: %d、%b、%h)。參數 :列出要依照對應格式輸出的訊號名稱或變數。 範例:顯示時脈計數與訊號值$display("Time=%0t : clk=%b, reset=%b", $time, clk, reset);
在此範例中,會輸出模擬時間以及時脈/重置信號的值。$display 的使用情境掌握模擬進度 :在設計的特定位置插入 $display ,即可驗證程式碼已執行到哪一段。訊號值驗證 :即使波形觀測器難以直觀了解條件分支或狀態轉移,文字輸出也能讓理解變得更容易。**條件訊息顯示 :結合 if 敘述,只在特定條件成立時記錄訊息。 if (reset) $display("Reset asserted at %0t", $time); $display 與 $write 的差異 $display 會自動在輸出末尾加上換行;相對地,$write 會持續輸出而不換行。
範例:$display("Hello");
$display("World");
輸出:Hello
World
$write("Hello");
$write("World");
輸出:HelloWorld
如果需要更清晰的逐行日誌,請使用 $display;若想在同一行上格式化多項輸出,則使用 $write。注意事項 避免過度輸出 :如果在每個時鐘週期都使用 $display,日誌會變得龐大且可讀性下降。→ 使用條件化來減少輸出。利用時間顯示 :輸出 $time 或 $realtime 可讓您精確捕捉操作的時序。僅供模擬使用的任務 :$display 不能用於綜合(FPGA/ASIC 實作)。它嚴格是僅供模擬的除錯工具。
3. 比較日誌輸出系統任務:$display、$write、$strobe、$monitor Verilog 提供了除 $display 之外的系統任務來輸出訊息。它們的使用情境與時機不同,了解如何分別使用它們相當有效率。$display:標準顯示任務特性 會自動加入換行,每次呼叫記錄一行。使用情境 最常用作為基本除錯方法;可在任何時候呼叫一次性輸出。$write:不換行的顯示特性 不會附加換行,因而在同一行持續輸出。使用情境 當您想要將多個值並排顯示時很有用。範例 $write("A=%d, ", a); $write("B=%d\n", b); → 輸出: A=5, B=10 。$strobe:在模擬週期結束時輸出特性 在當前步驟的所有模擬評估完成後才列印值。使用情境 用於避免競爭條件(多個訊號同時變化時)。範例 $strobe("Time=%0t, signal=%b", $time, sig); → 雖然 $display 可能顯示中間值,$strobe 會顯示穩定值。$monitor:自動蹤輸出特性 當任何被監控的訊號變化時自動輸出。使用情境 想要持續監控一組訊號時相當方便。範例 $monitor("At %0t a=%b, b=%b", $time, a, b); → 當 a 或 b 任一變化時記錄。總結表格 任務 換行 輸出時機 主要使用情境 $display是 呼叫時 基本日誌輸出 $write否 呼叫時 並排格式化 $strobe是 模擬週期結束後 檢查穩定值 $monitor是 訊號變化時自動 持續監控
有效使用技巧 預設使用 $display :可讀性佳,對初學者友好。需要單行合併輸出時使用 $write 。在變化後需要穩定值時使用 $strobe 。需要持續訊號監控時使用 $monitor 。
4. 格式說明子與進階顯示技巧 使用 $display 或 $write 等任務時,您可以在字串中加入「格式說明子」以所需的格式輸出訊號或變數。因為它類似 C 語言的 printf,依需求正確使用可大幅提升除錯效率。基本格式說明子 說明子 說明 輸出範例 %bbinary 1010%ddecimal 10%hhexadecimal A%ooctal 12%cASCII character A%sstring Hello%tsimulation time #100 等%mhierarchy name top.u1.u2
實用範例 以多種格式顯示訊號 reg [7:0] data = 8'b10101010; $display("data = %b (bin), %d (dec), %h (hex)", data, data, data); → 範例輸出: data = 10101010 (bin), 170 (dec), AA (hex)檢查模組層級 $display("Current module hierarchy is %m"); → 範例輸出: Current module hierarchy is top.u1.counter顯示模擬時間 $display("Time=%0t: clk=%b", $time, clk); → 範例輸出: Time=100: clk=1進階顯示技巧 Zero‑padding 與欄位寬度 您可以使用 %0d 之類的格式指定零填充或欄位寬度。範例: $display("Count=%04d", count); → 輸出: Count=0012有號與無號的差別 %d 以有號解讀數值, %u 以無號方式解讀。若負數未如預期顯示,請檢查並調整格式說明子。多行訊息格式化 使用 \n 斷行以提升可讀性。範例: $display("Start of test\nSignal A=%b\nSignal B=%b", A, B);注意事項 留意位元寬度 :Verilog 訊號的寬度可能不同,使用 %d 可能導致截斷或符號延伸的問題。處理未定義值 (X, Z) :若包含未定義位元,使用 %b 會直接顯示 x 或 z 。
5. 實作範例:在 Test Bench 與 Module 中使用 $display 以下將透過真實的 Verilog 程式碼範例,說明 $display 的有效用法,涵蓋測試平台的基本應用到條件式除錯訊息。基本範例:在 Test Bench 中輸出 在測試平台中插入 $display,即可在模擬期間觀察行為。module tb_counter;
reg clk;
reg reset;
wire [3:0] count;
// DUT (Device Under Test)
counter uut (
.clk(clk),
.reset(reset),
.count(count)
);
// Clock generation
initial begin
clk = 0;
forever #5 clk = ~clk; // invert every 5 units
end
// Test scenario
initial begin
reset = 1;
#10 reset = 0;
#50 $finish;
end
// Display state
always @(posedge clk) begin
$display("Time=%0t | reset=%b | count=%d", $time, reset, count);
end
endmodule
在此範例中,每個上升時都會輸出 reset 與 count。過文字日誌與波形同時檢視,可更容易追蹤行為。條件式顯示範例 結合 if 敘述,只在特定條件成立時記錄訊息。always @(posedge clk) begin
if (count == 4'd10) begin
$display("Count has reached 10 (Time=%0t)", $time);
end
end
→ 這樣可以避免過多的日誌,同時精確定位您關心的事件。除錯訊息範例 在設計除錯時,捕捉訊號進入「非預期狀態」非常有效。always @(posedge clk) begin
if (count > 4'd12) begin
$display("WARNING: count overflow detected! Time=%0t, value=%d", $time, count);
end
end
→ 您可以快速發現設計缺陷或模擬行為異常。同時監控多個訊號 當需要同時輸出多個訊號時,使用 $display 將它們合併成一行,可提升日誌的可讀性。$display("Time=%0t | clk=%b | reset=%b | A=%h | B=%h | SUM=%h",
$time, clk, reset, A, B, SUM);
實用技巧小結 將 $display 放在測試平台中以視覺化進度 使用條件分支精緻化日誌 產生警告訊息以偵測異常 將多個訊號合併同一行以提升可讀性
6. 顯示控制應用(像素/文字/影像顯示) 到目前為止,我們已介紹 $display 用於模擬日誌。另一方面,Verilog 也廣泛應用於硬體層面的「顯示控制」(LCD、VGA、HDMI 輸出)。本節將簡要說明硬體層面實作螢幕顯示。顯示控制的基本概念 要在螢幕上顯示文字或影像,必須產生視訊訊號,而非僅使用 $display。
常見的控制訊號包括:HSYNC(水平同步) :表示每一行結束的訊號VSYNC(垂直同步) :表示每一影格結束的訊號RGB 資料 :代表每個像素顏色的訊號(例如 8 位元 × 3 = 24 位元顏色) 在 Verilog 中,您會透過計數器與來控制這些訊號,並依時序輸出,以實現「螢幕顯示」。範例 1:顯示彩條 … 最基本的範例是水平輸彩條於顯示器上。always @(posedge clk) begin
if (h_counter < 100) rgb <= 24'hFF0000; // red
else if (h_counter < 200) rgb <= 24'h00FF00; // green
else if (h_counter < 300) rgb <= 24'h0000FF; // blue
else rgb <= 24'h000000; // black
end
會在螢幕上水平排列出紅、綠、藍三色彩條。範例 2:文字顯示 要顯示文字,您需要準備 字型 ROM ,並將每個字元的點陣圖樣轉換成像素。// Referencing the pattern of 'A' from the font ROM and displaying
if (font_rom[char_code][y][x] == 1'b1)
rgb <= 24'hFFFFFF; // white for display
else
rgb <= 24'h000000; // black background
→ 這會在螢幕上繪製特定字元例如「A」)。範例 3:影像顯示 要顯示影像,您需要讀取預先儲存的 點陣資料(ROM 或外部記憶體) ,並將其轉換為像素輸出。rgb <= image_rom[addr]; // Retrieve color data from ROM
在使用 FPGA 的嵌入式系統中,此方法可讓您顯示簡單的圖示或標誌。與除錯 $display 的差異 $display 為 文字輸出(僅限模擬) 顯示控制則是 視訊訊號產生(可硬體實作) 雖然兩者的目的不同,Verilog 學習者常常會混淆。「我想在模擬期間驗證行為」→ 使用 $display 「我想在 FPGA 上輸出到實際螢幕」→ 設計視訊訊號邏輯 應用擴展 在學習 FPGA 開發板時,Verilog 常用於 七段 LED 顯示 或 小型 LCD 顯示 。 進一步發展,您可以構建支援 VGA/HDMI 輸出 的系統,用於遊戲開發或 GUI 顯示。 結合 $display 與顯示控制邏輯的知識,您即可在模擬與實體硬體中同時處理「顯示」功能。
7. 依據應用情境的適當使用與技巧 當我們談到 Verilog 中的「顯示」時,分為兩個層面:僅限模擬的 $display 任務 與 硬體實作的顯示控制 。適當使用兩者可提升開發與除錯效率。模擬中的使用 $display 作為除錯日誌使用 $display 輸出關鍵變數或訊號,以檢查設計是否如預期運作。 透過日誌驗證「特定條件下的值」或「計數器達到某點」相當有效率。 避免過度輸出 每個時脈週期都輸出會淹沒日誌並降低可讀性。請縮小條件範圍。 範例: if (state == ERROR) $display("Error occured at %0t", $time); 區分不同任務 $monitor → 用於持監看訊號$strobe → 當需要輸出穩定值時 * $write → 用於格式化的水平輸出硬體顯示控制的使用 學習用的七段顯示 在 FPGA 初學者專案中,將計數器值顯示於七段 LED 是常見做法。 結合 $display 的模擬輸出,可加深對顯示與模擬差異的理解。 LCD 或 VGA 顯示器控制 使用字型 ROM 或影像 ROM 來顯示文字或圖像。 同時在模擬中使用 $display,可雙重驗證視訊訊號產生是否正確。 硬體除錯覆疊 您可以在實際的視訊輸出上覆疊「計數器值」、「座標」或「除錯訊息」。在 FPGA 開發中,常會將「螢幕本身」作為除錯工具。 實用技巧 先模擬 → 硬體流程 先使用 $display 於模擬中驗證行為,之後再移至硬體實作的顯示控制邏輯。同時使用日誌與波形 來自 $display 的文字日誌會指出「事件發生時間」,而波形則顯示「詳細轉換」。兩者結合可提升除錯精度。統一團隊開發的訊息格式 標準化 $display 訊息格式(前綴、時間顯示等)可讓多人協作時的日誌分析更為容易。摘要 $display 類型的任務是僅供模擬使用的「觀測工具」顯示控制則是硬體實作的「顯示方法」 依需求適當使用並結合兩者,可提升開發效率
8. 常見問題 (FAQ) Q1. $display 與 $monitor 有何差異? A. $display 於被呼叫的那一刻輸出一次;相較之下,$monitor 會在註冊的訊號變化時自動輸出。單次除錯 → $display 持續監控 → $monitor Q2. 何時該使用 $strobe? A. $strobe 會在模擬週期結束時輸出穩定值。例如在同一個時脈上升沿同時改變多個訊號時,$display 可能會顯示中間值;此時 $strobe 可方便地顯示最終值。Q3. 格式指定子 %m 有什麼用途? A. %m 會輸出目前的模組階層名稱。在大型設計中,記錄「訊息來源的階層」能大幅簡化分析。$display("Current module: %m");
範例輸出:Current module: top.u1.counter
Q4. 我的日誌因使用大量 $display 而變得龐大,該怎麼辦? A. 以下措施相當有效:使用 if 敘述過濾輸出 僅輸出錯誤偵測或特定事件 使用 $monitor 只監看最少必要的訊號 輸出至日誌檔,於分析時再套用過濾工具 Q5. $display 可以用於綜合 (FPGA/ASIC) 嗎? A. 不能。$display 嚴格是 僅供模擬的任務 ,綜合工具會忽略它,實際硬體中不會出現。如果想在實體硬體上顯示輸出,必須以 Verilog 設計「七段 LED」、「LCD」或「VGA 控制邏輯」等方式。Q6. 如何在實體硬體上顯示文字或影像? A. 不是透過 $display,而是產生視訊訊號。七段顯示器 → 用於簡單的數字或字元顯示 VGA / LCD → 產生 HSYNC、VSYNC、RGB 訊號並加以控制 文字 → 使用字型 ROM 輸出點陣圖案 影像 → 將點陣圖存於 ROM 或外部記憶體,依序輸出像素
9. 結論與後續步驟 本文摘要 本文從基礎到應用,全面說明 Verilog 中的「display」相關概念,重點包括:$display 基礎一個模擬使用的任務,可類比 C 語言 printf 來顯示訊號或變數。 與相關任務的差異 $write → 顯示但不換行$strobe → 在模擬週期結束時輸出穩定值$monitor → 自動監看訊號變化並輸出使用格式指定子 透過 %b、%d、%h、%m、%t 等,可產生更清晰、實用的日誌。 實作範例 在測試平台中插入 $display 以監控執行進度。 使用條件訊息提升除錯效率。 顯示控制的應用 $display 僅限模擬;硬體實作則以 HSYNC、VSYNC、RGB 輸出文字/影像。從學習七段顯示器到進階 VGA/HDMI 控制,皆有延伸可能。 後續步驟 進階至 SystemVerilog → 在繼任語言 SystemVerilog 中,你可以使用更進階的除錯功能(斷言、增強的 $display 等)。結合波形檢視器 → 結合 $display 日誌與波形資料,你可以同時分析數值與變化,提升除錯精度。學習輸出 → 在小型 FPGA 開發板專案中嘗試將資訊輸出至 7 段顯示器或 LCD,體驗「模擬顯示」與「硬體顯示控制」之間的差異。 應用於團隊開發 * → 透過統一 $display 訊息格式,可提升多人開發時的日誌分析效率。結語 $display 不只是單純的「文字輸出」。它是模擬除錯的強大工具。當你踏入顯示控制的領域時,亦能體驗在 FPGA 上於真實螢幕顯示圖形的樂趣。
希望本篇文章能協助 Verilog 學習者清楚了解「模擬除錯」與「硬體顯示輸出」兩者的差異。