2012年8月5日日曜日

FPGA FMトランスミッタ: 32倍オーバーサンプリングFIRフィルタ

これまでの処理では、152kHzのサンプルレートで信号処理を行ってきました。
後段のFM変調器は512倍の77.824MHzで動作しているため、サンプルレートの変換が必要です。とはいえ、いきなり512倍のサンプルレート変換は難しいため32倍と16倍の2回に分けることにします。
今回は、この32倍オーバーサンプリングFIRフィルタについて書きます。
基本的なところは、15kHzローパスフィルタと同じで係数データを含めJA2SVZ様の指導を得ています。どうもありがとうございました。

入力データと係数の組み合わせ
FIRデジタルフィルタのアドレッシングはまるでパズルのようです。まずは入出力のサンプルレートが同じ場合を図にしてみます。
下の図は、512タップのFIRフィルタの入力データ(リングバッファ)のアドレスと係数ROMのアドレスの組み合わせを示しています。1回目、2回目と処理を追うごとに入力データのアドレスがずれていきますが、リングバッファのデータは常に更新されるので、左端のデータが最も新しく右側に行くほど古くなっています。
入出力のサンプルレートが同じ場合、512個の入力データと係数の掛け算の総和がデジタルフィルタの出力となります。

入出力サンプルレートが同じ

次は32倍オーバーサンプリングです。
出力のサンプルレートが入力の32倍なので、出力32サンプルにつき入力は1サンプルしかないので残り31サンプルは "0" で補完します。(ゼロパディング; zero padding)
この "0" と係数の掛け算の結果は "0" なので、"0" で補完されたデータの計算はしなくてすみます。結果的に、512タップと言いながら、16回の掛け算の総和でデジタルフィルタの処理ができることになります。

32倍オーバーサンプリング


タイミング関係
ROM、リングバッファの読み出し、乗算器処理のレイテンシを考慮したタイミング関係図です。デジタルフィルタ1サンプル分の16回の乗算に着目しています。

データ処理の時間関係


インパルス応答の確認
コードのデバッグでは、係数アドレスと係数値が比例(単調に増加)するテスト用 coeファイルで妥当なインパルス応答が出るまでシミュレーションと修正を繰り返します。

ISimのシミュレーション画面

テスト用 coeファイルのインパルス応答。

time, l55k_i, l55k_o
104986,020000, 0
105178,020000, 1
105370,020000, 2
105562,020000, 3
105754,020000, 4
105946,020000, 5
106138,020000, 6
106330,020000, 7

202522,000000, 508
202714,000000, 509
202906,000000, 510
203098,000000, 511
203290,000000, 0


最後に、本番用のcoeファイルに差し替えて、インパルス応答を確認します。

インパルス応答(シミュレーション結果)


特性の測定
このフィルタの入力にaf_oscモジュールから10kHz信号を接続。出力を14ビットD/A(サンプルレート77.824MHz)にそのまま接続して、出力のスペクトラムを観測しました。D/Aコンバータの出力にはトランスが入っているので低域まで特性が伸びていませんが傾向を掴めるかと思います。
図で緑色がフィルタなし、黄色がフィルタありです。低域からフィルタの出力サンプルレート4.864kHzまでフィルタの効果があることがわかります。ただ、期待値(70dB以上)ほど効果が見えません。4.864MHz付近に1本のスペクトルが見えますが、拡大すると10kHz信号の折り返しで2本あることがわかります。

出力スペクトラム(DC-10MHz)

出力スペクトラム(4.864MHz付近)

出力スペクトラム(DC-500kHz)

lpf55k.v

module lpf55k(
  l55k_i, l55k_o, clk, reset, l55k_thru
  );

  input clk;
  input reset;
  input l55k_thru;
  input [23:0] l55k_i;
  output [23:0] l55k_o;

  reg [12:0] state512x16;
  reg init_cycle;
  wire [3:0] ring16;
  wire [3:0] state16;
  wire acc_init;
  wire acc_out;

  wire [8:0] COEF_ADDR;
  wire [17:0] COEF_DATA;
  wire [3:0] RING_RADDR;
  wire [17:0] RING_RDATA;
  wire [3:0] RING_WADDR;
  wire [17:0] RING_WDATA;
  wire [0:0] RING_WEN;
  wire [17:0] mul_in1;
  wire [17:0] mul_in2;
  wire [35:0] mul_out;
  wire [27:0] acc_in;  // 24bit + 4bit
  reg [27:0] acc;    // 24bit + 4bit
  reg [23:0] l55k_o;

  ////   state counters and control signals   ////
  always @(posedge clk or posedge reset) begin
    if (reset)
      begin
        state512x16 <= 0;
        init_cycle <= 1;
      end
    else if (state512x16 == 8191)
      begin
        state512x16 <= 0;
        if (init_cycle == 1)
          init_cycle <= 0;
      end
    else
      state512x16 <= state512x16 + 1;
  end

  assign ring16 = state512x16[12:9];
  assign state16 = state512x16[3:0];
  assign acc_init = (state16 == 5);
  assign acc_out = (state16 == 5) && (~init_cycle);
  assign RING_WEN = (state512x16[8:0] == 0);

  ////   ring-buffer RAM and coefficient ROM address generation   ////
  assign COEF_ADDR = {state16, state512x16[8:4]};
  assign RING_WADDR = - ring16;
  assign RING_RADDR = - ring16 + state16;
  
  ////   input data acquisition to ring-buffer RAM   ////
  assign RING_WDATA = l55k_i[23:6];

  ////   ring-buffer RAM and coefficient ROM read, input MUX and multiplier   ////
  assign mul_in1 = COEF_DATA;
  assign mul_in2 = RING_RDATA;
  assign acc_in = {{4{mul_out[34]}}, mul_out[34:11]};

  ////   accumulator   ////
  always @(posedge clk or posedge reset) begin
    if (reset)
      acc <= 0;
    else
      acc <= (acc_init)? acc_in : acc + acc_in;
  end

  ////   output data register   ////
  always @(posedge clk or posedge reset) begin
    if (reset) 
      l55k_o <= 0;
    else if (l55k_thru) 
      l55k_o <= l55k_i;
    else
      if (acc_out)
        begin
          if (~acc[27] && !(acc[26:23] == 4'b0000))
            l55k_o <= 8388607;    // 24-bit positive max
          else if (acc[27] && !(acc[26:23] == 4'b1111))
            l55k_o <= -8388608;    // 24-bit negative max
          else
            l55k_o <= acc[23:0];
        end
  end

  ////   memory and multiplier instantiation (Xilinx)   //// 
  lpf55k_coef U1 (
    .clka(clk),
    .rsta(reset),
    .addra(COEF_ADDR),
    .douta(COEF_DATA)
    );

  lpf55k_rbuf U2 (
    .clka(clk),
    .wea(RING_WEN),
    .addra(RING_WADDR),
    .dina(RING_WDATA),
    .clkb(clk),
    .rstb(reset),
    .addrb(RING_RADDR),
    .doutb(RING_RDATA)
    );

   mul_p U3 (
    .clk(clk),
    .sclr(reset),
    .a(mul_in1),
    .b(mul_in2),
    .p(mul_out)
    );

endmodule


Block Memory Generator(ring-buffer RAM)の設定
リングバッファ用デュアルポートRAMです。読み出しのレイテンシは2クロックです。
Total Port B Read Latency (From Rising Edge of Read Clock): 2 Clock Cycles









Block Memory Generator(coefficient ROM)の設定
係数用ROMです。読み出しのレイテンシは2クロックです。
Total Port A Read Latency (From Rising Edge of Read Clock): 2 Clock Cycles









Multiplierの設定
乗算器です。演算のレイテンシは3クロックです。
ここは、15kHz ローパスフィルタの記事と同一なので割愛します。

フィルタ係数COEファイル
・タップ数: 512
・入力サンプルレート: 152kHz
・出力サンプルレート: 4,864kHz (152kHz×32)
・通過域: 0~55kHz
・阻止域: 97kHz~

MEMORY_INITIALIZATION_RADIX=2;
MEMORY_INITIALIZATION_VECTOR=
000000000011100000,
111111111110101010,
111111111110110010,
111111111110110101,
111111111110110101,
111111111110110001,
111111111110101100,

111111111110100101,
111111111110011101,
111111111110010100,
111111111110001100,
111111111110000011,
111111111101111011,
111111111101110011,
111111111101101100,
111111111101100110,
111111111101100001,
111111111101011101,
111111111101011100,
111111111101011100,
111111111101011111,
111111111101100011,
111111111101101010,
111111111101110011,
111111111101111111,
111111111110001110,
111111111110011111,
111111111110110011,
111111111111001010,
111111111111100011,
111111111111111111,
000000000000011101,
000000000000111110,
000000000001100000,
000000000010000100,
000000000010101001,
000000000011010000,
000000000011110111,
000000000100011110,
000000000101000101,
000000000101101011,
000000000110010000,
000000000110110011,
000000000111010100,
000000000111110001,
000000001000001100,
000000001000100010,
000000001000110100,
000000001001000000,
000000001001001000,
000000001001001001,
000000001001000011,
000000001000110111,
000000001000100100,
000000001000001001,
000000000111100111,
000000000110111101,
000000000110001011,
000000000101010010,
000000000100010001,
000000000011001010,
000000000001111011,
000000000000100111,
111111111111001100,
111111111101101101,
111111111100001001,
111111111010100010,
111111111000111001,
111111110111001110,
111111110101100010,
111111110011111000,
111111110010010000,
111111110000101011,
111111101111001011,
111111101101110001,
111111101100011110,
111111101011010100,
111111101010010100,
111111101001011111,
111111101000110111,
111111101000011100,
111111101000010000,
111111101000010011,
111111101000100110,
111111101001001011,
111111101010000001,
111111101011001000,
111111101100100010,
111111101110001101,
111111110000001010,
111111110010011000,
111111110100110111,
111111110111100101,
111111111010100010,
111111111101101100,
000000000001000010,
000000000100100010,
000000001000001010,
000000001011111000,
000000001111101010,
000000010011011101,
000000010111010000,
000000011010111110,
000000011110100110,
000000100010000101,
000000100101011000,
000000101000011011,
000000101011001110,
000000101101101100,
000000101111110011,
000000110001100000,
000000110010110010,
000000110011100111,
000000110011111011,
000000110011101110,
000000110010111110,
000000110001101010,
000000101111110010,
000000101101010100,
000000101010010010,
000000100110101011,
000000100010100000,
000000011101110011,
000000011000100101,
000000010010111000,
000000001100101111,
000000000110001100,
111111111111010010,
111111111000000110,
111111110000101100,
111111101001000110,
111111100001011100,
111111011001110000,
111111010010001000,
111111001010101001,
111111000011011001,
111110111100011110,
111110110101111011,
111110101111111000,
111110101010011000,
111110100101100010,
111110100001011010,
111110011110000100,
111110011011100110,
111110011010000010,
111110011001011101,
111110011001111001,
111110011011011001,
111110011101111110,
111110100001101010,
111110100110011101,
111110101100010110,
111110110011010110,
111110111011011010,
111111000100011111,
111111001110100010,
111111011001100000,
111111100101010100,
111111110001110111,
111111111111000101,
000000001100110101,
000000011011000001,
000000101001100000,
000000111000001010,
000001000110110110,
000001010101011010,
000001100011101100,
000001110001100011,
000001111110110101,
000010001011011000,
000010010111000001,
000010100001100110,
000010101010111111,
000010110011000010,
000010111001100110,
000010111110100100,
000011000001110011,
000011000011001110,
000011000010101110,
000011000000001111,
000010111011101110,
000010110101000111,
000010101100011001,
000010100001100100,
000010010100101001,
000010000101101011,
000001110100101110,
000001100001110111,
000001001101001100,
000000110110110110,
000000011110111110,
000000000101101111,
111111101011010100,
111111001111111100,
111110110011110100,
111110010111001011,
111101111010010011,
111101011101011101,
111101000000111001,
111100100100111100,
111100001001111000,
111011110000000000,
111011010111101000,
111011000001000100,
111010101100100111,
111010011010100100,
111010001011001110,
111001111110110111,
111001110101110000,
111001110000001001,
111001101110010011,
111001110000011001,
111001110110101011,
111010000001010001,
111010010000010101,
111010100100000000,
111010111100010101,
111011011001011010,
111011111011010000,
111100100001110110,
111101001101001001,
111101111101000100,
111110110001100001,
111111101010010111,
000000100111011000,
000001101000011001,
000010101101001001,
000011110101010111,
000101000000101111,
000110001110111011,
000111011111100110,
001000110010010101,
001010000110110000,
001011011100011011,
001100110010111001,
001110001001101111,
001111100000011101,
010000110110100111,
010010001011101110,
010011011111010010,
010100110000110111,
010101111111111111,
010111001100001011,
011000010101000000,
011001011010000011,
011010011010111010,
011011010111001011,
011100001110100001,
011101000000100101,
011101101101000100,
011110010011101110,
011110110100010010,
011111001110100110,
011111100010011101,
011111101111110001,
011111110110011101,
011111110110011101,
011111101111110001,
011111100010011101,
011111001110100110,
011110110100010010,
011110010011101110,
011101101101000100,
011101000000100101,
011100001110100001,
011011010111001011,
011010011010111010,
011001011010000011,
011000010101000000,
010111001100001011,
010101111111111111,
010100110000110111,
010011011111010010,
010010001011101110,
010000110110100111,
001111100000011101,
001110001001101111,
001100110010111001,
001011011100011011,
001010000110110000,
001000110010010101,
000111011111100110,
000110001110111011,
000101000000101111,
000011110101010111,
000010101101001001,
000001101000011001,
000000100111011000,
111111101010010111,
111110110001100001,
111101111101000100,
111101001101001001,
111100100001110110,
111011111011010000,
111011011001011010,
111010111100010101,
111010100100000000,
111010010000010101,
111010000001010001,
111001110110101011,
111001110000011001,
111001101110010011,
111001110000001001,
111001110101110000,
111001111110110111,
111010001011001110,
111010011010100100,
111010101100100111,
111011000001000100,
111011010111101000,
111011110000000000,
111100001001111000,
111100100100111100,
111101000000111001,
111101011101011101,
111101111010010011,
111110010111001011,
111110110011110100,
111111001111111100,
111111101011010100,
000000000101101111,
000000011110111110,
000000110110110110,
000001001101001100,
000001100001110111,
000001110100101110,
000010000101101011,
000010010100101001,
000010100001100100,
000010101100011001,
000010110101000111,
000010111011101110,
000011000000001111,
000011000010101110,
000011000011001110,
000011000001110011,
000010111110100100,
000010111001100110,
000010110011000010,
000010101010111111,
000010100001100110,
000010010111000001,
000010001011011000,
000001111110110101,
000001110001100011,
000001100011101100,
000001010101011010,
000001000110110110,
000000111000001010,
000000101001100000,
000000011011000001,
000000001100110101,
111111111111000101,
111111110001110111,
111111100101010100,
111111011001100000,
111111001110100010,
111111000100011111,
111110111011011010,
111110110011010110,
111110101100010110,
111110100110011101,
111110100001101010,
111110011101111110,
111110011011011001,
111110011001111001,
111110011001011101,
111110011010000010,
111110011011100110,
111110011110000100,
111110100001011010,
111110100101100010,
111110101010011000,
111110101111111000,
111110110101111011,
111110111100011110,
111111000011011001,
111111001010101001,
111111010010001000,
111111011001110000,
111111100001011100,
111111101001000110,
111111110000101100,
111111111000000110,
111111111111010010,
000000000110001100,
000000001100101111,
000000010010111000,
000000011000100101,
000000011101110011,
000000100010100000,
000000100110101011,
000000101010010010,
000000101101010100,
000000101111110010,
000000110001101010,
000000110010111110,
000000110011101110,
000000110011111011,
000000110011100111,
000000110010110010,
000000110001100000,
000000101111110011,
000000101101101100,
000000101011001110,
000000101000011011,
000000100101011000,
000000100010000101,
000000011110100110,
000000011010111110,
000000010111010000,
000000010011011101,
000000001111101010,
000000001011111000,
000000001000001010,
000000000100100010,
000000000001000010,
111111111101101100,
111111111010100010,
111111110111100101,
111111110100110111,
111111110010011000,
111111110000001010,
111111101110001101,
111111101100100010,
111111101011001000,
111111101010000001,
111111101001001011,
111111101000100110,
111111101000010011,
111111101000010000,
111111101000011100,
111111101000110111,
111111101001011111,
111111101010010100,
111111101011010100,
111111101100011110,
111111101101110001,
111111101111001011,
111111110000101011,
111111110010010000,
111111110011111000,
111111110101100010,
111111110111001110,
111111111000111001,
111111111010100010,
111111111100001001,
111111111101101101,
111111111111001100,
000000000000100111,
000000000001111011,
000000000011001010,
000000000100010001,
000000000101010010,
000000000110001011,
000000000110111101,
000000000111100111,
000000001000001001,
000000001000100100,
000000001000110111,
000000001001000011,
000000001001001001,
000000001001001000,
000000001001000000,
000000001000110100,
000000001000100010,
000000001000001100,
000000000111110001,
000000000111010100,
000000000110110011,
000000000110010000,
000000000101101011,
000000000101000101,
000000000100011110,
000000000011110111,
000000000011010000,
000000000010101001,
000000000010000100,
000000000001100000,
000000000000111110,
000000000000011101,
111111111111111111,
111111111111100011,
111111111111001010,
111111111110110011,
111111111110011111,
111111111110001110,
111111111101111111,
111111111101110011,
111111111101101010,
111111111101100011,
111111111101011111,
111111111101011100,
111111111101011100,
111111111101011101,
111111111101100001,
111111111101100110,
111111111101101100,
111111111101110011,
111111111101111011,
111111111110000011,
111111111110001100,
111111111110010100,
111111111110011101,
111111111110100101,
111111111110101100,
111111111110110001,
111111111110110101,
111111111110110101,
111111111110110010,
111111111110101010,
000000000011100000;


0 件のコメント:

コメントを投稿