🎤

Zybo Z7 オーディオコーデック送受信

2022/07/04に公開

実施内容

PC等から出力した音声を、Zybo Z7 ボードの LINE入力端子からオーディオコーデックチップ SSM2603 の ADコンバータに入力します。得られたPCM信号を、再び SSM2603 のDAコンバータに入力し、Zybo Z7 ボードのヘッドフォン出力端子から音声を出力します。
PCM信号をDAコンバータに入力する前に、ディレイエコーのエフェクトをかけることができます。ディレイエコーは、こだまが遅延・減衰して返ってくるカラオケマイクのような効果です。

SSM2603の設定

SSM2603に設定した制御レジスタの値を以下の表に示します。

  • R7,Digital audio I/F について
    参考文献はSSM2603をSlaveモード、Left justfied フォーマットに設定して使用していたのでそれに倣いました。

SSM2603制御のタイミングチャート

SSM2603の制御モジュールを実装するにあたって作成したタイミングチャートです。

RECDAT読み取りについて

RECDAT信号を読むことで、AD変換結果をMSBから1ビットずつ取得できます。divider256 の値と、読み込むデータは以下の関係にあります。
Leftチャネル読取り

  • divider256 が "h02" に変化する時に データ[15] を読む
  • divider256 が "h06" に変化する時に データ[14] を読む
    (中略)
  • divider256 が "h3E" に変化する時に データ[0] を読む, Leftチャネル読取り終了

Rightチャネル読取り

  • divider256 が "h82" に変化する時に データ[15] を読む (Rightチャネル)
  • divider256 が "h86" に変化する時に データ[14] を読む
    (中略)
  • divider256 が "hBE" に変化する時に データ[0] を読む, Right チャネル読取り終了

上記のタイミングは16bitでサンプリングする場合です。もしも24bitや32bitでサンプリングする場合は読取り終了のタイミングが後ろに変化します。

クロック生成

SSM2603で使用する周波数のクロックがClocking wizardで生成できるか確認して以下の表を作成しました。50MHz, 100MHz クロックはzynqのPS部から、また125MHzクロックはPL部で容易に確保できます。

50MHzのクロックをClocking wizardに入力し、11.2896MHzのクロックを生成させることにしました。

ソースコード

ファイル7個を含むzipファイルです。
https://github.com/cipressino/244_adcechodac/archive/refs/heads/main.zip

Vivadoのプロジェクト

Vivadoのプロジェクトを作成して、Vitis に渡すための Hardware Platform File 出力まで進めてください。以下はおおよその手順です。

BRAM

ディレイエコーエフェクトに使用するBRAMを定義。
IPカタログから

Block Memory Generator を選択

以下のパラメータを指定。

  • Component Name = blk_mem_sig_buffer (Basicタブ)
  • Memory Type = Single Port Ram (Basicタブ)
  • Write Depth = 32768 (Port A Options タブ)

プロジェクトにファイルを追加

Design Sources に以下のファイルを追加。
dlyecho.sv
prj_top.v
prj.sv
ssm2603.sv
syncfifo.sv

Constraints に以下のファイルを追加。
zybo-z7-20.xdc

ブロックダイアグラム

本件で使用したIPは以下です。

  • ZYNQ7 Processing System
  • AXI IIC
  • Clocking Wizard
  • Constant (Highを発生)

また、ブロックダイアグラムの上を右クリックし、Add Module メニューから prj_top ブロックを発生させてください。

これらのブロックを上図のように結線してください。

Clocking Wizrd

入力クロックは50MHz

出力クロックは 11.2896MHz (== 44.1kHz の 256倍)

Bitstream 作成

Run Synthesis, Run Implementation, Generate Bitstream を進める。

タイミング違反が出た場合は以下手順で回避する。
Project Summary から、 Implemented Timing Report を開く。

Inter-Clock Paths のリストのアイテムを右クリック、Set Clock Groups を選択
現れた画面で適当なグループ名を記入して保存、再度Implementation以降を実行する

Hardware Platform File 出力

File -> Export -> Export Hardware メニューを選択。
.xsaファイルを出力。

Vitis のプロジェクト

Platform project

Vivado から出力した .xsa ファイルを参照して Platform project を作成してください。

Application project

Application project を新規作成してください。
本件の main.c を追加してください。

実行

Application project を実行してください。PCでUART端末を起動しておくと、以下のような文字列をボードから受信します。以降は1秒おきに経過時間を受信します。

Zybo Z7ボードの ライン入力端子に任意の音源を接続、ヘッドフォン端子に任意のスピーカーを接続すれば音が鳴ります。

Zybo Z7 ボード上の SW1 で、ディレイエコーエフェクト有無を切り替えることができます。

実装について

ディレイエコー

最新時刻の信号サンプルに、以下の3つのサンプルを加えることでディレイエコーの効果を与えました。(参考[1])

  • 1/8秒前のサンプルを 0.8倍に減衰して加える
  • 2/8秒前のサンプルを 0.7倍に減衰して加える
  • 3/8秒前のサンプルを 0.6倍に減衰して加える

本件で扱ったPCM信号は 符号付き16bit整数ですが、エフェクトの計算は 32bit 符号付き整数にキャストして実行しました。

減衰の計算について

  • 0.8 の乗算
    13倍して16で割る、としました。(13/16 = 0.8125)
    13倍を実行する回路については特にDSPの利用を意識せずVivadoにお任せしました。16で割るのは4ビット算術シフト。
  • 0.7 の乗算
    11倍して16で割る、としました。(11/16=0.6875)
  • 0.6 の乗算
    9倍して16で割る、としました。(9/16=0.5625)

過去のサンプルの取得について
サンプリングレートは 44.1kHz なので、1/8秒前のサンプルとして5512個過去にさかのぼったサンプルを参照しました。2/8秒前のサンプル = 11025個、3/8秒前のサンプル = 16537個、それぞれ過去にさかのぼったサンプルを参照しました。

PS部 メインプログラム

AXI IIC のドライバを利用してSSM2603の制御レジスタに設定を書き込みました。本家Digilent社のデモを参考にしました。(参考[2])

SSM2603のデータシート

SSM2603のデータシートから関連箇所を引用します。


LLINEIN と RLINEIN -34.5dB~+33dB の音量調整可能。制御レジスタR0 と R1,ビット[5:0]
LHPOUT と RHPOUT -73dB~+6dB の音量調整可能。制御レジスタR2 と R3,ビット[6:0]
SIDETONE経路 -8dB~-15dB の音量調整可能。制御レジスタR4,ビット[7:6]
MICIN の音量を 0dB または 20dB で選択可能。制御レジスタR4,ビット[0]


OSC ブロック:
MCLKを外部から与えるならばOSCブロックの電源を落としてもよい。制御レジスタR6,ビット[5] (1でパワーオフ)

CLKGENブロック:
18.5MHzを超えるような周波数のMCLKを与えて、SSM2603内部ではそれを遅く(2分周)して使いたいケースがあるかもしれない。制御レジスタR8,ビット[6] (1を設定すると分周が有効)。 分周後のクロックをCLKOUTから出力できる。 これらの機能が不要ならCLKGENブロックの電源を落としてよい。制御レジスタR6,ビット[6] (1でパワーオフ)

OUTブロック:
SSM2603の制御レジスタ群設定時には、OUTブロックの電源を落としておく。制御レジスタR6,ビット[4] (1でパワーオフ) 設定が終わってから電源を入れる。制御レジスタR6,ビット[4] (0でパワーオン)


Table.2 より抜粋
MCLK は 8MHz ~ 18.5MHz で与えること。


Slaveモードでのタイミング制約。
PBLRC と RECLRC のsetupタイミング制約。BCLK の rise edge よりも tLRSU だけ早く遷移させること。 (tLRSU >= 10ns)
PBDAT のsetupタイミング制約。BCLK の rise edge よりも tDS だけ早く遷移させること。 (tDS >= 10ns)
RECDAT が有効な期間。 BCLK の fall edge から最大 tDD ns (tDD <= 30ns) (それ以上経つと次のデータが来る)


SSM2603 のMUTEピンにより、ミュートするかどうか、ハードウェアで制御する。 0 に設定するとミュート。


Left-Justified モードのタイミングチャート。


(以下、MCLK=18.432MHzの場合と MCLK=16.9344MHzの場合は省略)
本件では MCLK 11.2896MHz, サンプリングレート 44.1kHz, 16bit量子化, で使用することにしました。

参考文献

  • 参考[3] ボードは異なるが同じ SSM2603 が使用されていました。制御モジュールの実装を参考にしました。
  • 参考[4] SSM2603のデータシート
脚注
  1. プログラム101付き 音声信号処理, https://shop.cqpub.co.jp/hanbai/books/31/31471.html ↩︎

  2. Zybo Z7 DMA Audio Demo, https://digilent.com/reference/programmable-logic/zybo-z7/demos/dma-audio ↩︎

  3. Exploring the Arrow SoCKit Part VIII - The Audio Codec, https://zhehaomao.com/blog/fpga/2014/01/15/sockit-8.html ↩︎

  4. SSM2603 データシートおよび製品情報 | アナログ・デバイセズ (analog.com), https://www.analog.com/jp/products/ssm2603.html ↩︎

Discussion