AIコーディングエージェント CursolにFPGAデザインを作らせます.アプリケーションはNight Riderです.流れるLEDの余韻もPWMで再現させます.

 FPGAボードとして,FPGAマガジン特別版No.3の付録基板(応募券方式)を使います.

 8連LEDとしてPmodのLEDモジュール(Sipeed)を使います.

付録 生基板(部品実装前)

● プロンプト

FPGAデザインを設計して,Quartus Primer Lite用のプロジェクトを作ってください

# アプリケーション
8個のLEDの点灯制御

## 点灯パターン
ナイトライダー

## LEDの駆動信号
FPGAのピンで直接駆動する
明るさはPWMで制御する

# HDL
SystemVerilog

# 合成系
Quartus Prime lite

# デバイス
## FPGAチップ
10M08SCE144C8G

## ベースボード
https://github.com/Lathe-Mariel/PCB_CQmax10

## System clock
50MHz

# 物理制約
信号は全て,3.3-V LVCMOS

信号名 | FPGA ピン | 内容
---|---|---
LED0 |  98 | led
LED1 | 101 | led
LED2 |  99 | led
LED3 | 100 | led
LED4 |  96 | led
LED5 | 105 | led
LED6 |  97 | led
LED7 | 106 | led
clk  | 88  | System clock(50MHz)
rst_n | 17 | system reset_n

● Cursol の応答

Night Rider LED — CQmax10 FPGA Project

8 LED ナイトライダー(KITT スキャナー)パターンを PWM 明るさ制御付きで駆動する SystemVerilog プロジェクトです。

ターゲット

項目
FPGAIntel MAX 10 10M08SCE144C8G
ボードCQmax10
ツールQuartus Prime Lite
システムクロック50 MHz

構成

night_rider_fpga/
├── night_rider.qpf          # Quartus プロジェクト
├── night_rider.qsf          # デバイス設定・ピン配置
├── rtl/
│   ├── night_rider_top.sv   # トップレベル
│   ├── night_rider.sv       # スキャナー位置・明るさ生成
│   └── pwm_controller.sv    # 8 bit PWM 出力
└── output_files/            # 合成・配置配線結果(生成物)

動作

  • スキャナーヘッドが LED0 → LED7 → LED0 … と往復移動(10 ステップ/秒)
  • ヘッド LED が最も明るく、離れるほど暗くなる尾光(4 段階の輝度)
  • PWM 周波数: 50 MHz / 256 ≈ 195 kHz(ちらつきなし)

ピン配置

信号FPGA ピンI/O 標準
clk883.3-V LVCMOS
rst_n173.3-V LVCMOS
led[0]983.3-V LVCMOS
led[1]1013.3-V LVCMOS
led[2]993.3-V LVCMOS
led[3]1003.3-V LVCMOS
led[4]963.3-V LVCMOS
led[5]1053.3-V LVCMOS
led[6]973.3-V LVCMOS
led[7]1063.3-V LVCMOS

ビルド手順

  1. Quartus Prime Lite を起動
  2. File → Open Projectnight_rider.qpf を開く
  3. Processing → Start Compilation(または Ctrl+L)
  4. 完了後、output_files/night_rider_top.sof を Program Device で書き込み

コマンドライン(任意)

Quartus が PATH にある場合:

cd C:\Users\nagai\night_rider_fpga
quartus_sh --flow compile night_rider
quartus_pgm -c USB-Blaster -m jtag -o "p;output_files/night_rider_top.sof"

パラメータ調整

rtl/night_rider.svSTEP_HZ(デフォルト 10)でスキャン速度を変更できます。
dist_brightness() 内の値で尾光の長さ・明るさを調整できます。

● 生成された RTL コード

・night_rider_top

// Top-level: 8-LED night rider with PWM brightness control
// Target: CQmax10 (10M08SCE144C8G), 50 MHz system clock

module night_rider_top (
    input  logic       clk,
    input  logic       rst_n,
    output logic [7:0] led
);

    logic [7:0] brightness [8];

    night_rider u_night_rider (
        .clk       (clk),
        .rst_n     (rst_n),
        .brightness(brightness)
    );

    pwm_controller u_pwm (
        .clk       (clk),
        .rst_n     (rst_n),
        .brightness(brightness),
        .led_pwm   (led)
    );

endmodule
広げる

・night_rider.sv

// Night rider (KITT scanner) brightness generator
// Head LED is brightest; trailing LEDs fade with distance

module night_rider #(
    parameter int NUM_LEDS  = 8,
    parameter int PWM_WIDTH = 8,
    parameter int CLK_HZ    = 50_000_000,
    parameter int STEP_HZ   = 10
) (
    input  logic                         clk,
    input  logic                         rst_n,
    output logic [PWM_WIDTH-1:0]         brightness [NUM_LEDS]
);

    localparam int STEP_CYCLES = CLK_HZ / STEP_HZ;
    localparam int POS_WIDTH   = $clog2(NUM_LEDS);

    logic [31:0]          step_cnt;
    logic [POS_WIDTH-1:0] position;
    logic                 direction; // 0: toward LED7, 1: toward LED0

    function automatic logic [PWM_WIDTH-1:0] dist_brightness(int unsigned distance);
        case (distance)
            0: dist_brightness = 8'hFF;
            1: dist_brightness = 8'hA0;
            2: dist_brightness = 8'h60;
            3: dist_brightness = 8'h20;
            default: dist_brightness = '0;
        endcase
    endfunction

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            step_cnt  <= '0;
            position  <= '0;
            direction <= 1'b0;
        end else if (step_cnt >= STEP_CYCLES - 1) begin
            step_cnt <= '0;

            if (!direction) begin
                if (position >= NUM_LEDS'(NUM_LEDS - 1))
                    direction <= 1'b1;
                else
                    position <= position + POS_WIDTH'(1);
            end else begin
                if (position == '0)
                    direction <= 1'b0;
                else
                    position <= position - POS_WIDTH'(1);
            end
        end else begin
            step_cnt <= step_cnt + 32'd1;
        end
    end

    always_comb begin
        for (int i = 0; i < NUM_LEDS; i++) begin
            int unsigned dist;

            dist = (i >= int'(position))
                 ? int'(i) - int'(position)
                 : int'(position) - int'(i);
            brightness[i] = dist_brightness(dist);
        end
    end

endmodule
広げる

・pwm_controller.sv

// PWM controller for direct LED drive
// Shared counter, per-LED duty cycle from brightness values

module pwm_controller #(
    parameter int PWM_WIDTH = 8,
    parameter int NUM_LEDS  = 8
) (
    input  logic                         clk,
    input  logic                         rst_n,
    input  logic [PWM_WIDTH-1:0]         brightness [NUM_LEDS],
    output logic [           NUM_LEDS-1:0] led_pwm
);

    logic [PWM_WIDTH-1:0] pwm_cnt;

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n)
            pwm_cnt <= '0;
        else
            pwm_cnt <= pwm_cnt + PWM_WIDTH'(1);
    end

    always_comb begin
        for (int i = 0; i < NUM_LEDS; i++)
            led_pwm[i] = (brightness[i] > pwm_cnt);
    end

endmodule
広げる

コメントを残す