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
このモジュールでは、
を入力とし、
- 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 の補数」表現から「オフセット・バイナリ」形式に変換され、符号なし数として扱われます。
シミュレーション結果を下に示します。 (図をクリックすると拡大します)
このシミュレーションでは、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 で、ほとんどの部分では塗り潰されたようになっていますが、サイン波形の正のピークおよび負のピーク付近では「疎密波」となっている様子が分かります。