FPGA
HDL
I2C

I2C通信を試してみる

FPGAで直接I2C通信を行ってみました。

予備知識

仕様書はこちらI2Cバス仕様およびユーザーマニュアル(NXP Semiconductors)

(ワイヤードアンド)
I2C通信では、ワイヤードアンドの手法を用いることで、複数のデバイスを2本の線に芋づる式に接続している。

ワイヤードアンド接続は、1本の信号線(ワイヤー)に複数のデバイスの出力を並列に直接接続するのが特長であり、接続するデバイスのうち、1つでも0を出力するデバイスがあると信号が0になる。ワイヤーで接続するだけで、AND回路が構成できることからワイヤードアンドと呼ばれる。

具体的には、デバイスの出力回路をオープンドレイン(オープンコレクタ)で構成し、信号線は抵抗(プルアップ抵抗)を介してVDDに接続する。オープンドレイン回路は、OFF状態ではハイインピーダンス状態となり信号線に電流が流れない。このため、全てのデバイスの出力がOFFであれば、信号線の電位はプルアップ抵抗によりVDDとなる。逆に、オープンドレイン回路の出力がON状態では、信号線がGNDの間のインピーダンスが小さくなり、電流が流れる。電圧降下により信号線の電位がGNDに近づく。

FPGAとI2Cバスの接続

I2Cバスは、オープンドレイン接続かつ双方向接続であるため、トライステート制御可能であるIOBUFを介して接続する。

IO回路
U_SDA:IOBUF Port(
  O=>inSDA,    -- 入力バッファ出力を入力信号に
  IO=>IIC_SDA, -- PIN 
  I=>otSDA,    -- 出力バッファ入力に出力信号に
  T=>otSDA_T   -- トライステート制御
);
U_SDAOUT:process(sda) begin
    if   sda = '0' then
        otSDA <='0';otSDA_T<='0';
    else
        otSDA <='1';otSDA_T<='1';--'1'でハイインピーダンスにする
    end if;
end process;

マスターコントローラ

Scott Larson,I2C Master(VHDL)

パッチ
--  scl <= '0' WHEN (scl_ena = '1' AND scl_clk = '0') ELSE 'Z';
U8100_SCLOUT:process(scl_ena,scl_clk) begin
    if  (scl_ena = '1' AND scl_clk = '0') then
        otSCL <='0';otSCL_T<='0';
    else
        otSCL <='1';otSCL_T<='1';
    end if;
end process;
--  sda <= '0' WHEN sda_ena_n = '0' ELSE 'Z';
U8200_SDAOUT:process(sda_ena_n) begin
    if   sda_ena_n = '0' then
        otSDA <='0';otSDA_T<='0';
    else
        otSDA <='1';otSDA_T<='1';
    end if;
end process;

基本プロトコル

I2Cのプロトコルには、複数のMASTERを接続するための機能や、SLAVEが応答を引き延ばす機能、SLAVEアドレスの拡張機能など、いろいろ素晴らしい機能があるのですが、スター型に接続するだけなら基本のプロトコルだけ覚えればそれなりに使えるかと。

ポイント1)連続書き込みはストップコンディションで終了を伝え、連続読み込みはNACKで終了を伝える。
ポイント2)アドレスを指定した読み出しや、引数を指定た関数の呼び出し(Remote Procedure Call)では、リピートスタートコンディションを使う。
ポイント3)I2C通信では上位プロトコルは規定せず。アドレス長や通信シーケンスなどは、アプリケーションやデバイス仕様で規定。

1バイト書き込み

S SLAVE R/W Ack DATA Ack P
MASTER S アドレス指定 0 書き込みデータ P
SLAVE 0 0

1バイト読み出し

S SLAVE R/W Ack DATA ACK P
MASTER S アドレス指定 1 1 P
SLAVE 0 読み出しデータ

読み出しデータに対するMASTERの確認応答(ACKフィールド)の意味については、上位のプロトコルの設計次第かと。仕様書によれば、NACKを発生させる条件は以下のとおり。

  1. 転送されたアドレスのレシーバがバスに存在しない.つまりアクノリッジで応答する デバイスがない場合。
  2. レシーバが何らかのリアルタイム機能を実行中でマスタとの通信を行える状態ではなく、送信も受信もできない場合。
  3. 転送の間、 受信したデータやコマンドをレシーバが理解できない場合。
  4. 転送の間、 レシーバがそれ以上データバイトを受信できない場合。
  5. マスタレシーバがスレーブトランスミッタに対し転送の終了を伝える場合。

マスターが、1バイトで転送の終了を明確に伝えるなら(5)の意味でNACKを返す。スレーブが1バイトしか伝送しないことがあらかじめ決まっているならばACKを返す。

2バイト以上の通信

2バイト以上のデータを連続書き込み、読み出しする場合。

S SLAVE R/W Ack DATA Ack DATA Ack P
MASTER S アドレス指定 0 書き込みデータ 書き込みデータ P
SLAVE 0 0 0

書き込みでは、書き込むバイト数だけDATAを繰り返したのち、STOPコンディションを発行する。

S SLAVE R/W Ack DATA ACK DATA ACK P
MASTER S アドレス指定 1 0 1 P
SLAVE 0 読み出しデータ 読み出しデータ

読み出しでは、読み出したいバイト数だけDATAを受信すると、ACKの代わりにNACKをSLAVEに送る。

レジスタアクセスプロトコルの例

デバイスに複数のレジスタがある場合やROMは、デバイス指定だけでなく、レジスタやメモリのアドレス(1 or 2 byte)を指定する。

書き込みの場合は、データの先頭にアドレスを追加する。

S SLAVE W A DATA A DATA A DATA A DATA A P
MASTER S デバイス
アドレス
0 アドレス アドレス 書き込みデータ 書き込みデータ P
SLAVE 0 0 0 0 0

読み出しの場合は、アドレスを書き込んだのち、停止させずにリピートスタートコンディションを発行し、読み出しを開始する。

S SLAVE W A DATA A DATA A Sr SLAVE R A DATA A DATA A P
MASTER S デバイス
アドレス
0 アドレス アドレス Sr デバイス
アドレス
1 0 1 P
SLAVE 0 0 0 0 読み出し
データ
読み出し
データ