Gowin Vol.3 第1部第3章 リスト9

module decimal_counter #(
parameter CLK_FREQ = 27_000_000 // 入力クロックの周波数を指定
) (
input wire clk, // 27MHzクロック入力
output wire [3:0] counter_output[6] // 6桁の10進数カウンタの値
);

// 前章で作成したタイマーモジュール
// 1ミリ秒に1回count_enableがHiになる
wire count_enable;
timer #(
.COUNT_LIMIT (CLK_FREQ / 1000)
) timer_i (
.count_max (count_enable),
.*
);

// 6桁の10進数カウントアップロジック
// 1ミリ秒に一度カウントアップする
logic [3:0] counter_reg[6];
logic [3:0] counter_next_value[6];
logic [6:0] carry;
assign carry[0] = count_enable; // 1ミリ秒に一度最下位のキャリーを1としてカウントアップ
// 6桁分の10進数カウンタをインスタンシエート
for (genvar i = 0; i < 6; i++) begin
// カウンタの次の値を計算する組み合わせ回路
always_comb begin
if (carry[i] == 1'b1) begin // 下の桁からのキャリーが1場合は,次の値が変わる
if (counter_reg[i] == 4'd9) begin // 現在の値が9のときは,
counter_next_value[i] = 4'd0; // - 次の値は0
carry[i + 1] = 1'b1; // - 上の桁へのキャリーは1
end else begin // 現在の値が9以外のときは,
counter_next_value[i] = counter_reg[i] + 4'd1; // - 次の値は現在の値+1
carry[i + 1] = 1'b0; // - 上の桁へのキャリーは0
end
end else begin // 下の桁からキャリーがない場合は次の値は現在の値と同じ
counter_next_value[i] = counter_reg[i];
carry[i + 1] = 1'b0;
end
end
// カウンタ値を保持するレジスタ
always_ff @ (posedge clk) begin
counter_reg[i] <= counter_next_value[i];
end
end