PSoC5LP Prototyping Kit (32) --- UDB routed clock (1)

実は、spdif_dma プロジェクトで使っている I2S フォーマットの WS 信号を標準フォーマット LRCK 信号に変換する回路は「論理的」には正しくありません。
一方、論理的に正しい回路にすると、期待しているような動作になりません。
これは、変換回路のクロックが純粋な (1 次) クロックではなく、2 次的な、加工されたクロックとして扱われるためです。
PSoC では、これを「routed clock」と呼んでいるようです。
まずは、I2S の WS と標準フォーマットの LRCK のタイミング・チャートを下に示します。

I2S/標準フォーマットのいずれも、シリアル・データおよび WS/LRCK はシリアル・クロック (SCK, BCLK) の立ち下がりで変化し、データのラッチはシリアル・クロックの立ち上がりで行なうようになっています。
I2S では、WS = "0" で L チャネル、WS = "1" で R チャネルのデータ転送であることを示しています。
標準フォーマットでは、その逆に、LRCK = "1" で L チャネル、LRCK = "0" で R チャネルを示します。
さらに、WS のエッジ位置と比べて SCK (BCLK) 1 クロック分遅れて LRCK が変化しています。

この変換は、左の図のように、シリアル・クロックの立ち下がりで動作する D-FF に WS を反転したものを入力することで実現できます。
D-FF にポジティブ・エッジ・トリガのものを使っているので、SCK を反転したものをクロック入力に加えています。

一方、spdif_dma プロジェクトで使っている回路を下に示します。

参考のために、下側に、きわめてオーソドックスな方法で「LRCK2」を作り出している回路を示しています。
I2S コンポーネントの SCK 出力は、クロック入力を 2 分周したものとなっているので、I2S コンポーネントのクロックと同じもので 2 クロック分遅延させてやれば SCK 1 クロック分の遅延となります。
もちろん、この回路は何の問題もなく、期待通りの動作をします。
一方、上側の「LRCK」の回路では、先に示した回路とは違って、D-FF のクロック入力にインバータがなく、SCK の立ち上がりエッジで動作する回路に見えます。
しかし、実際には LRCK 出力は SCK の立ち下がりの位置で変化し、出力波形としては正しいものになります。
逆に、先に示した「正しい」はずの回路では、出力波形としては正しくなりません。
これが腑に落ちずにいたのですが、「noritan」さんのブログ

リップルカウンタを作ってみたはずなのに:新適当マイコン電子工作研究所:So-net blog

にヒントがありました。
上記のプログの内容をまとまると、(無理やり) リップル・カウンタを実装すると、一応それらしい動作はするが、正確な実現ではなく、擬似的な実現になっているという話です。
その記事の中でリポート・ファイル (.rpt) 内の該当するマクロセルに関する記述を調べています。
同様にして、リポート・ファイル中の LRCK と LRCK2 を作り出している部分を調べて見た結果を下に示します。

<CYPRESSTAG name="Macrocell listing" icon="FILE_RPT_EQUATION">

    . . . . . < 中略 > . . . . .

    MacroCell: Name=cydff_2, Mode=(D-Register)
        Total # of inputs        : 1
        Total # of product terms : 1
        List of special equations: 
            Clock  = (ClockBlock_fs_x64) => Global
            Clock Enable: True
        Main Equation            : 1 pterm
        (
              !i2s0_ws
        );
        Output = cydff_2 (fanout=1)

    . . . . . < 中略 > . . . . .

    MacroCell: Name=cydff_1, Mode=(D-Register)
        Total # of inputs        : 1
        Total # of product terms : 1
        List of special equations: 
            Clock  = (ClockBlock_fs_x64) => Global
            Clock Enable: PosEdge(i2s0_sck)
        Main Equation            : 1 pterm
        (
              !i2s0_ws
        );
        Output = cydff_1 (fanout=1)
</CYPRESSTAG>

前半の、マクロセル名 Cydff_2 がオーソドックスな方法による LRCK2 発生の 1 段目の D-FF です。
クロックとして指定通りのグローバル・クロック「fs_x64」が使われており、「Clock Enable」は (後で説明するように) True でクロック「素通し」の状態です。
後半の、マクロセル名 Cydff_1 が「謎」の LRCK 回路で、指定した覚えのないグローバル・クロック「fs_x64」がクロックとして使われており、クロックとして指定した「i2s0_sck」は「Clock Enable」の項に「PosEdge(i2s0_sck)」として登場しています。
これで、「i2s0_sck」信号がシステムにより何か特別な扱いを受けていることが判明しました。
実はこれが「routed clock」なのですが、その話は次回に回します・