FPGAによる14ビットDDS信号発生器のVerilog実装とDAC波形出力

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正弦波出力を検証。

タグ: FPGA Verilog DDS DAC 信号発生器

5月31日 19:43 投稿