ボード:Tang Primer 25K
サウンドモジュール:PMOD-AUDIO V1.2(muse lab)
サウンドモジュールのスピーカを使ったモノラル出力としたので,FPGAからPMODモジュールへの信号は1本のみを利用
単純なPWMで音階を表現しただけのメロディプレーヤを作成する.
Claudeの生成したメロディは,よく分からないものだったので,手動で修正した.
●プロンプト
FPGAデザインを作る
# Application
インテル入っているCMの効果音を鳴らす
# Hardware
## FPGA Board
Tang Primer 25K
### System Clock
50MHz
## Speaker
PMOD-AUDIO-v1.2
(https://github.com/wuxx/icesugar/blob/master/schematic/pmod-audio-v1.2.pdf)
(https://github.com/wuxx/icesugar/blob/master/src/basic/verilog/music4/music.v)
# HDL
SystemVerilog
# Physical constraint file
Port1 | G11 | Input_L // スピーカ側はG10だったので生成コードを手動で修正
Port2 | D11 | none
Port3 | B11 | none
Port4 | C11 | none
Port5 | G10 | none
Port6 | D10 | none
Port7 | B10 | none
Port8 | C10 | noneExpand
●生成コード
・トップモジュール
module top (
input logic clk, // 50 MHz system clock (core-board oscillator, pin E2)
output logic pmod_audio // PMOD-AUDIO "IL" input (Port1 / G11)
);
logic rst;
// Power-on reset generator (synchronous, self-clearing)
por_reset u_por (
.clk (clk),
.rst (rst)
);
// Note sequencer + square-wave tone generator
jingle_player u_jingle (
.clk (clk),
.rst (rst),
.audio (pmod_audio)
);
endmodule広げる
・音源・シーケンサモジュール
// 省略
module jingle_player #(
parameter int CLK_HZ = 50_000_000
) (
input logic clk,
input logic rst,
output logic audio
);
// ------------
// Step table (5 tones + trailing rest/gap before the loop repeats)
//
// step | note | freq (Hz) | half-period (cyc @50MHz) | dur (ms)
// 0 | F# | 739.989 | 33784 | 600
// 1 | C# | 554.365 | 45096 | 200
// 2 | F# | 739.989 | 33784 | 200
// 3 | C# | 554.365 | 45096 | 200
// 4 | G# | 830.609 | 30098 | 200
// 5 | (rest / gap) | -- | 0 | 2000
// ------------
localparam int NUM_STEPS = 7;
logic [2:0] step;
logic [17:0] half_period;
logic [26:0] duration_cyc;
always_comb begin
unique case (step)
3'd0: begin half_period = 18'd67568; duration_cyc = 27'd10_000_000; end // 600ms
3'd1: begin half_period = 18'd0; duration_cyc = 27'd20_000_000; end //
3'd2: begin half_period = 18'd90193; duration_cyc = 27'd10_000_000; end // 200ms
3'd3: begin half_period = 18'd67568; duration_cyc = 27'd10_000_000; end // 200ms
3'd4: begin half_period = 18'd90193; duration_cyc = 27'd10_000_000; end // 200ms
3'd5: begin half_period = 18'd60196; duration_cyc = 27'd15_000_000; end //
default: begin half_period = 18'd0; duration_cyc = 27'd200_000_000; end // 3000ms rest
endcase
end
// -----------------------
// Step/duration sequencer
// -----------------------
logic [26:0] dur_cnt;
logic step_done;
assign step_done = (dur_cnt == duration_cyc - 27'd1);
always_ff @(posedge clk) begin
if (rst) begin
dur_cnt <= '0;
step <= '0;
end else if (step_done) begin
dur_cnt <= '0;
step <= (step == NUM_STEPS - 1) ? 3'd0 : step + 3'd1;
end else begin
dur_cnt <= dur_cnt + 27'd1;
end
end
// --------------------------
// Square-wave tone generator
// --------------------------
logic [17:0] tone_cnt;
logic tone_bit;
logic note_active;
assign note_active = (half_period != 18'd0);
always_ff @(posedge clk) begin
if (rst) begin
tone_cnt <= '0;
tone_bit <= 1'b0;
end else if (!note_active) begin
tone_cnt <= '0;
tone_bit <= 1'b0; // silence during the rest step
end else if (tone_cnt == half_period - 18'd1) begin
tone_cnt <= '0;
tone_bit <= ~tone_bit;
end else begin
tone_cnt <= tone_cnt + 18'd1;
end
end
assign audio = tone_bit;
endmodule広げる
・リセット
module por_reset #(
parameter int WIDTH = 6 // 64 clk cycles of reset after config
) (
input logic clk,
output logic rst
);
logic [WIDTH-1:0] cnt = '0;
always_ff @(posedge clk) begin
if (!(&cnt))
cnt <= cnt + 1'b1;
end
assign rst = ~(&cnt);
endmodule広げる