2012年7月23日月曜日

FPGA FMトランスミッタ: オーディオ信号発生器

内部変調用のオーディオ信号発生器は、DDSで作ります。このDDSは、オプション指定で所要リソースがかわります。24ビット出力にして、余った乗算器を無駄遣いさせる事にしました。

2012.7.23補足
DDSのクロックは152kHzで動作させるべきでしょうが、何も考えずに9.728MHzで動作させていたことに気がつきました。結果的には、サンプルレート変換を行っている形ですが、ナイキスト周波数未満で使う分には問題ないように思っています。


オーディオ信号発生器の仕様
チューナなどのセパレーション調整に使えそうな信号を想定しています。

内部変調の動作モード

内部変調レベル

内部変調周波数

実測値
コーデックのアナログ出力で測定してみました。

0dBFS 100Hz

0dBFS 1kHz

af_osc.v

module af_osc(
  af_l_o, af_r_o, clk, reset, af_set
  );

  output [23:0] af_l_o;
  output [23:0] af_r_o;
  input clk;  // 64fs
  input reset;
  input [6:0] af_set;

  reg [23:0] af_l_o;
  reg [23:0] af_r_o;
  reg [5:0] state64;
  wire [23:0] sine;
  wire [23:0] pinc_in;
  wire [23:0] afosc_out;
  wire [1:0] OSC_MODE;
  wire [1:0] LEVEL_SETTING;
  wire [2:0] FREQ_SETTING;
  wire latch_out;

  // State counter
  always @(posedge clk or posedge reset)
    begin
      if (reset)
        state64 <= 0;
      else if (state64 == 63)
        state64 <= 0;
      else
        state64 <= state64 + 1;
    end

  assign latch_out = (state64 == 0);
  assign OSC_MODE = af_set[6:5];
  assign LEVEL_SETTING = af_set[4:3];
  assign FREQ_SETTING = af_set[2:0];
  assign pinc_in = dds_setting(FREQ_SETTING);
  assign afosc_out = level_set(sine, LEVEL_SETTING);

  // output level setting
  function [23:0] level_set;
    input [23:0] audio_input;
    input [1:0] setting;
    case (setting)
      0: level_set = 0;
      1: level_set = {{4{audio_input[23]}}, audio_input[23:4]};
      2: level_set = {audio_input[23], audio_input[23:1]};
      3: level_set = audio_input;
      default: level_set = 0;
    endcase
  endfunction

  // dds_setting
  function [23:0] dds_setting;
    input [2:0] addr;
    case (addr)
      0: dds_setting = 24'h000056;
      1: dds_setting = 24'h0000AC;
      2: dds_setting = 24'h0002B2;
      3: dds_setting = 24'h0006BD;
      4: dds_setting = 24'h0021AF;
      5: dds_setting = 24'h003287;
      6: dds_setting = 24'h00435E;
      7: dds_setting = 24'h00650D;
      default: dds_setting = 24'h0006BD;
    endcase
  endfunction

  //  output data register
  always @(posedge clk or posedge reset)
    begin
      if (reset)
        begin
          af_l_o <= 0;
          af_r_o <= 0;
        end
      else if (latch_out)
        begin
          case (OSC_MODE)
            0:  begin 
                af_l_o <= afosc_out;
                af_r_o <= afosc_out;
              end

            1:  begin 
                af_l_o <= afosc_out;
                af_r_o <= 0;
              end

            2:  begin 
                af_l_o <= 0;
                af_r_o <= afosc_out;
              end
  
            3:  begin 
                af_l_o <= afosc_out;
                af_r_o <= ~afosc_out + 1;
              end
  
            default:  begin
                af_l_o <= afosc_out;
                af_r_o <= afosc_out;
              end
          endcase
        end
    end

  // dds
  af_osc_dds af_osc_dds (
    .clk(clk),
    .pinc_in(pinc_in), // input [23 : 0] pinc_in
    .sine(sine)); // output [23 : 0] sine

endmodule

DDS Compiler設定画面1

DDS Compiler設定画面2

DDS Compiler設定画面3

DDS Compiler設定画面4

DDS Compiler IP Symbol

0 件のコメント:

コメントを投稿