2023年12月14日 星期四

第一支 Verilog 程式

上星期四就已經將交接事項全部完成,但臨時被交辦要拿一塊真實板子將某個專案流程實際跑過一遍,板子配 DRAM 問題總是千奇百怪,這也是我最擔心的部分,故押了一個兩個星期後的完成日期。

因為 A chip 板子不能開機,趁著同事如火如荼 debug 時,改拿 B chip 板子來跑,雖然收集資料階段可以跑完,但也是死當在我的最後一個 UEFI script 開機途中,本想忽略這個狀況繼續往下走,沒想到連開機值的 MT86 測試都過不了,害我浪費了不少時間。

昨天晚上拿到同事處理好的 A chip 板子,但因為是 debug 版 BIOS,開機需花不少時間,終於在今天中午時順利地進到我們專案的最主要測試流程。

上星期四到今早都只能斷斷續續的學語法,還要分心注意板子,進度幾乎為 0!下午總算可以好好學 Verilog 了。

花點時間思考一下,參考網友文章,選擇使用 Icarus Verilog 來 compile 並用 GTKWave 來看波形,雖然功能不多,但目前夠我用了。

iverilog - compile verilog code.
vvp - simulation engine.
gtkwave - wave viewr.

編譯方式

@echo off

REM compile code.
iverilog -o wave led_demo.v led_demo_tb.v

IF NOT "%ERRORLEVEL%" == "0" (
    echo.
    pause
    goto END
)

REM convert wave to wave.vcd
vvp -n wave -lxt2

REM run gtkwave to check signals.
gtkwave wave.vcd


:END
echo.

Testbench

`timescale 1ns/100ps

module led_demo_tb;

parameter SYSCLK_PERIOD = 10;

reg SYSCLK;
reg NSYSRESET;

initial
begin
    SYSCLK = 1'b0;
    NSYSRESET = 1'b0;
end

// For Iverilog
initial
begin
    $dumpfile("wave.vcd");
    $dumpvars(0, led_demo_tb);
end

initial
begin
    #(SYSCLK_PERIOD * 10)
        NSYSRESET = 1'b1;
    #1000
        $stop;
end

always @ (SYSCLK)
    #(SYSCLK_PERIOD / 2.0) SYSCLK <= !SYSCLK;

led_demo led_demo_ut0 (
    // Inputs
    .rst_n(NSYSRESET),
    .clk(SYSCLK),

    // Outputs
    .led(led)
);

endmodule

LED Module

module led_demo(
    input clk,
    input rst_n,

    output reg led
);

reg [4:0] cnt;

always @ (posedge clk)
begin
    if (!rst_n)
        cnt <= 0;
    else if (cnt >= 10)
        cnt <= 0;
    else
        cnt <= cnt + 1;
end

always @ (posedge clk)
begin
    if (!rst_n)
        led <= 0;
    else if (cnt == 10)
        led <= !led;
end

endmodule

GTKWave 畫面


該網友的範例是個很不錯的 Hello World,包含很多基礎語法。

如果只是要學 Verilog 語法,也可以單寫 Testbench 就好。 

總之,Verilog 一定要配合波形看(simulation),學習才能事半功倍。

沒有留言:

張貼留言