FPGA 版 FM 音源 (67) -- FPGA 版 EG (11)

16 ビット入力 1 次シグマ・デルタ型 1 ビット DA モジュール「sdm1_16()」の Verilog ソースを下に示します。
"sdm1_16.v"

// module sdm1_16() :
//
// 1st order Sigma-Delta 1-bit DAC
// for 16-bit / 2's complement input data
//
// 2017/01/23 modified for OPL3 EG
// 2010-Nov-26 Created by pcm1723

module sdm1_16(reset, m_clk, clk_ovs_en, fs_clk, din, daout);
// formal parameters
  input         reset; // async reset
  input         m_clk; // master clock
  input         clk_ovs_en; // oversampling clock enable
  input         fs_clk; // clock of fs rate
  input  [15:0] din;   // 16-bit 2's complement input data
  output        daout; // 1-bit DA out
// locals  
  reg    [15:0] sum;   // 16-bit accumulator
  reg           sum16; // carry bit of accum
  reg    [15:0] d_reg; // registered input
  reg    [1:0]  fs_clk_z; // delay sample of fs_clk
  wire          fs_edge; // positive edge df fs_clk
  
  
// fs_clk differentiation
  always @( posedge m_clk or posedge reset )  
    begin
      if (reset) // async reset
        begin
          fs_clk_z <= 2'b00;
        end
      else if (clk_ovs_en) 
        begin
          fs_clk_z <= {fs_clk_z[0], fs_clk};
        end // if (reset) ...
    end // always
  
  assign fs_edge = (fs_clk_z == 2'b01);
  
// data input register
  always @( posedge m_clk or posedge reset )  
    begin
      if (reset) // async reset
        begin
          d_reg <= 16'h0000;
        end
      else if (fs_edge)
        begin
// 2's complement input data converted to offset binary
          d_reg <= { (~din[15]), din[14:0] };
        end // if (reset) ...
    end // always
	
// registers
  always @( posedge m_clk or posedge reset )
    begin
      if (reset) // async reset
        begin
          {sum16, sum} <= 17'h0_0000;
        end
      else if (clk_ovs_en)
        begin
// update accumulator    
          { sum16, sum } <= ( sum + d_reg );
        end // if (reset) ...
    end // always
    
// wires   
  assign daout = sum16; // quantized 1-bit DA output
endmodule

このモジュールでは、

  • 非同期リセット (reset)
  • マスター・クロック (m_clk)
  • オーバーサンプリング・クロック・イネーブル信号 (clk_ovs_en)
  • fs レート・クロック信号 (fs_clk)
  • 16 ビット・パラレル、2 の補数のデータ入力 (da[15:0])

を入力とし、

  • 1 ビット DA 出力 (daout) (ovs_clk レート)

を出力します。
内部は m_clk と clk_ovs_en 信号とで構成されるオーバーサンプリング・クロック (ovs_clk) のレートで動作します。
内部レジスタに 16 ビット・パラレル・データ (din[15:0]) をラッチするトリガとして、fs レートのクロック信号 fs_clk の立ち上がりを ovs_clk で微分したものを使用しています。
この処理の都合上、fs_clk 信号は ovs_clk での再サンプリングでジッタが発生しないものとし、また、「H」レベルのパルス幅は ovs_clk の 1 周期分以上なければなりません。
通常、LR クロック (lrck) を供給してやれば条件を十分に満足します。
データ入力に対してオーバーサンプリングによる補間は行なわないので、DA 出力の周波数特性は fs レートでの 0 次ホールドの特性のままになります。
入力データの MSB (din[15]) は内部で反転されて、「2 の補数」表現から「オフセット・バイナリ」形式に変換され、符号なし数として扱われます。
シミュレーション結果を下に示します。 (図をクリックすると拡大します)

cic_modelsim.png

このシミュレーションでは、m_clk に 128 fs クロックを注入し、clk_ovs_en は「1」に吊ったままとして、128 倍オーバーサンプリングで動作させています。
実際には 1 ビット DA 出力に、アナログ LPF を作用させてアナログ値を得るのですが、ロジック・シミュレーション上で同様の効果を得るために、1 ビット DA 出力に 2 次 CIC (Cascaded Intergrator-Comb) フィルタを作用させて「ディジタル数値」として結果を得ています。
2 次 CIC フィルタにより、ビット幅は 1 ビットから 14 ビットに拡大しています。
DDA (Digital Differential Analyzer) アルゴリズムにより sin / cos 波形を発生させ、sin 波の方をデータ入力として使用しています。
上のグラフで中央付近、やや上にある赤いトレースが入力サイン波の「アナログ表示」で、中央付近、やや下にあるのが CIC フィルタ結果のディジタル数値のアナログ表示です。
上のグラフでほぼ中央にあるのが 1 ビット DA 出力の daout で、ほとんどの部分では塗り潰されたようになっていますが、サイン波形の正のピークおよび負のピーク付近では「疎密波」となっている様子が分かります。