Gowin_Vol3 1部1章リスト2

 

// Verilog は言語仕様で、宣言されていない信号線を幅1 のwire として解釈する
// Typo 等で意図しない回路が生成されないよう、定義しない信号をエラーに設定する
`default_nettype none

// clk 入力ごとにカウントアップするタイマー
// - 内部のカウンタがCOUNT_LIMIT に達したときのみcount_max が1 を出力
// - それ以外の場合は0 を出力
module timer #(
parameter COUNT_LIMIT = 27_000_000
) (
input wire clk,
output wire count_max
);
// カウンタ本体を定義
// - COUNT_LIMIT の値に応じて必要な幅を確保
// - 初期値はゼロに設定
logic [$clog2(COUNT_LIMIT+1)-1:0] counter = 'd0;

// count_max の出力を組み合わせ回路で記載
// - counter がCOUNT_LIMIT と一致したときに1 を出力
// - それ以外の場合は0 を出力
assign count_max = (counter == COUNT_LIMIT)? 1'b1: 1'b0;

// counter の値を順序回路で記載
// - counter がCOUNT_LIMIT と一致したら値を0 に戻す
// - それ以外の場合はclk 入力ごとにカウントアップ
always_ff @ (posedge clk) begin
if (counter == COUNT_LIMIT) begin
counter <= 'd0;
end else begin
counter <= counter + 'd1;
end
end

endmodule

// 最上位モジュール
// - ボード上のLED を点滅させるモジュール
// - 点滅間隔はモジュール内部のパラメータで設定
module led_blinking (
input wire clk,
output wire [5:0] led_output
);
// 入力されるクロック周波数
localparam CLK_FREQ = 27_000_000;

// 点滅間隔をms 単位で設定
localparam BLINKING_MS = 500;

// 実装したタイマーのインスタンス
// - COUNT_LIMIT の値をクロック周波数と点滅間隔から計算
// - .* と記述することで同名のwire, logic が自動的に接続される
wire count_max;
timer #(
.COUNT_LIMIT ((CLK_FREQ / 1000) * BLINKING_MS)
) timer_i (
.*
);

// LED を点滅させるロジックを順序回路で記載
// - count_max が入力されたタイミングでled の値を反転
logic [5:0] led = 6'b101010;
always_ff @ (posedge clk) begin
if (count_max) led <= ~led;
end

// led ロジックをled_output に接続
assign led_output = led;

endmodule

// 他のモジュールに影響を与えないよう、もとの設定に戻す
`default_nettype wire