DDS信号発生器の基本構造
DDS(直接デジタル周波数合成)は波形データを生成する技術です。以下に14ビット解像度のコアモジュールを示します。
module dds_generator(
input clk, // クロック入力
input rst_n, // リセット
input [31:0] freq_ctrl, // 周波数制御
input [1:0] wave_sel, // 波形選択
input [4:0] amp_scale, // 振幅係数
output reg [13:0] dac_out // DAC出力
);
localparam DATA_BITS = 14;
localparam ADDR_BITS = 12;
reg [ADDR_BITS-1:0] lut_addr;
wire [DATA_BITS-1:0] wave_data[0:3];
// 波形選択ロジック
always @(posedge clk or negedge rst_n) begin
if (!rst_n) dac_out <= 0;
else case(wave_sel)
2'b00: dac_out <= adjust_amp(wave_data[0], amp_scale);
2'b01: dac_out <= adjust_amp(wave_data[1], amp_scale);
2'b10: dac_out <= adjust_amp(wave_data[2], amp_scale);
2'b11: dac_out <= adjust_amp(wave_data[3], amp_scale);
endcase
end
// 位相累積器
reg [31:0] phase_acc;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) phase_acc <= 0;
else phase_acc <= phase_acc + freq_ctrl;
end
// LUTアドレス生成
always @(posedge clk or negedge rst_n) begin
if (!rst_n) lut_addr <= 0;
else lut_addr <= phase_acc[31:20];
end
// 波形ROMインスタンス化
sine_rom u_sine (.clk(clk), .addr(lut_addr), .dout(wave_data[0]));
triangular_rom u_tri (.clk(clk), .addr(lut_addr), .dout(wave_data[1]));
sawtooth_rom u_saw (.clk(clk), .addr(lut_addr), .dout(wave_data[2]));
square_rom u_sq (.clk(clk), .addr(lut_addr), .dout(wave_data[3]));
function [13:0] adjust_amp;
input [13:0] wave;
input [4:0] scale;
begin
adjust_amp = (wave > 14'd8192) ?
14'd8192 + ((wave - 14'd8192) / scale) :
14'd8192 - ((14'd8192 - wave) / scale);
end
endfunction
endmodule
波形選択モジュール
module wave_selector(
input clk,
input rst_n,
input key_in,
output reg [1:0] wave_sel
);
wire key_pressed;
// キー押下で波形切替
always @(posedge clk or negedge rst_n) begin
if (!rst_n) wave_sel <= 0;
else if (key_pressed) wave_sel <= wave_sel + 1;
end
debouncer #(.DELAY(24)) debounce_inst (
.clk(clk),
.rst_n(rst_n),
.key_in(key_in),
.key_flag(key_pressed)
);
endmodule
デバウンス回路
module debouncer #(
parameter MAX_COUNT = 999999
)(
input clk,
input rst_n,
input key_in,
output reg key_flag
);
reg [19:0] counter;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) counter <= 0;
else if (key_in) counter <= 0;
else if (counter == MAX_COUNT) counter <= counter;
else counter <= counter + 1;
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) key_flag <= 0;
else if (counter == MAX_COUNT - 1) key_flag <= 1;
else key_flag <= 0;
end
endmodule
周波数制御モジュール
module frequency_control(
input clk,
input rst_n,
input key_in,
output reg [31:0] freq_word
);
wire key_event;
reg [3:0] freq_index;
debouncer #(.DELAY(24)) deb_inst (
.clk(clk),
.rst_n(rst_n),
.key_in(key_in),
.key_flag(key_event)
);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) freq_index <= 0;
else if (key_event) freq_index <= (freq_index == 15) ? 0 : freq_index + 1;
end
// 200MHzクロック用設定値
always @(posedge clk or negedge rst_n) begin
if (!rst_n) freq_word <= 0;
else case(freq_index)
0: freq_word <= 32'd21; // 1Hz
1: freq_word <= 32'd215; // 10Hz
2: freq_word <= 32'd2147; // 100Hz
// その他周波数設定値
15: freq_word <= 32'd429496730; // 20MHz
endcase
end
endmodule
トップレベル設計
module dds_top(
input clk,
input rst_n,
input wave_select_key,
input freq_control_key,
output dac_clk,
output [13:0] dac_data
);
wire [1:0] wave_mode;
wire [31:0] freq_setting;
wire clk_200m;
dds_generator dds_core (
.clk(clk_200m),
.rst_n(rst_n),
.freq_ctrl(freq_setting),
.wave_sel(wave_mode),
.amp_scale(5'd1),
.dac_out(dac_data)
);
frequency_control freq_module (
.clk(clk_200m),
.rst_n(rst_n),
.key_in(freq_control_key),
.freq_word(freq_setting)
);
wave_selector wave_module (
.clk(clk),
.rst_n(rst_n),
.key_in(wave_select_key),
.wave_sel(wave_mode)
);
assign dac_clk = clk;
endmodule
実装検証
FPGAボード上で動作検証を実施。キー操作による波形切替と周波数変更を確認。ILAを使用した信号解析により10MHz正弦波出力を検証。