FPGA 版 FM 音源 (68) -- FPGA 版 EG (12)
ステレオ 16 ビット・シリアル入力 DA 用送信モジュール「i2s_tx()」の Verilog ソースを下に示します。
"i2s_tx.v"
// // i2s_tx.v : I2S Transmitter module // only support 16-bit data word // / 32 clock per frame format (std. format) // ( I2S format not supported ) // // 2017/01/19 Created by pcm1723 // module i2s_tx( // Input reset, // async reset m_clk, // master clock clk_128fs_en, // 128fs clock enable lrck, // LR clock input da, // 16-bit parallel audio data // Output sclk, // serial clock sdat, // serial data lrck_out, // LR clock output da_out // latched data out for monitor ); // Input port input reset; input m_clk; input clk_128fs_en; input lrck; input [15:0] da; // Output port output sclk; output sdat; output lrck_out; output [15:0] da_out; // reg [15:0] da_out; // wires wire sclk_en; wire load; // regs reg [15:0] sr; // shift regeiser reg [1:0] cnt; // 1/4 clock divider / bit counter reg lrck_z1; // 1 clock delay of lrck assign sclk_en = ( clk_128fs_en & (cnt == 2'b11) ); assign sclk = cnt[1]; assign load = ( lrck ^ lrck_z1 ); // parallel data load timing assign sdat = sr[15]; assign lrck_out = lrck_z1; // SCLK generator always @(posedge m_clk or posedge reset) begin if (reset) // async reset begin cnt <= 2'b00; lrck_z1 <= 1'b0; end else if (clk_128fs_en) // 128fs clock timing begin cnt <= (cnt + 1'b1); // count up if ( sclk_en ) // SCLK timing begin lrck_z1 <= lrck; // 1 clock delay end // if (cnt4 == ... end // if (reset) ... end // always @() ... // serializer always @(posedge m_clk or posedge reset) begin if (reset) // async reset begin sr <= 16'h0000; da_out <= 16'h0000; end else if ( sclk_en ) begin if ( load ) // parallel load timing begin sr <= da; // parallel load da_out <= da; end else // shift begin sr <= { sr[14:0], 1'b0 }; da_out <= da_out; // hold end // if (load) ... end // if (reset) ... end // always @() ... endmodule
ここで、I2S は「シリアル・データ入力を持つオーディオ用 DAC」とのインターフェースを行なう回路の「総称名」として使っており、データ・フォーマット自体は、いわゆる「標準フォーマット」のみをサポートしており、「I2S フォーマット」はサポートしていません。
このモジュールでは、
- 非同期リセット (reset)
- マスター・クロック (m_clk)
- 128 fs クロック・イネーブル信号 (clk_128fs_en)
- デューティー 50 %、fs レートの方形波クロック (lrck)
- 16 ビット・パラレル、2 の補数のデータ入力 (da[15:0])
を入力とし、
- DA 用シリアル・クロック (sclk)
- DA 用シリアル・データ (sdat)
- DA 用 LR クロック (lrck_out)
- パラレル・ロードされた DA データのモニタ出力 (da_out[15:0])
を出力します。
モジュール内部で 128 fs クロックを 4 分周し、32 fs クロックを得て sclk として出力します。
内部にはビット・カウンタを持たず、(128 fs クロックで再サンプリングした) lrck が「H」側、「L」側ともに正確に 128 fs クロック 64 周期分、(sclk 16 周期分) であることを前提にしています。
シリアライズの動作としては、いわゆる「左詰め」、つまり 16 ビット・データの MSB (da[15]) が LRCK のエッジと接するような配置になりますが、L/R の期間がそれぞれ SCLK 16 周期分なので、16 ビット・データの LSB (da[0]) が LRCK のエッジと接する、つまり「右詰め」の状態でもあります。
da_out[15:0] は、内部のシフトレジスタにロードされた値を外部からモニタするための出力で、シフトレジスタへのデータ・ロードと同じタイミングで同じ値が da_out[15:0] レジスタにもロードされ、それ以降は次のロード・タイミングまで (シフトせず) 単にその値を保持し続けます。
シミュレーション結果を下に示します。 (図をクリックすると拡大します)