12
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

FPGAでI2C通信を試してみる

Last updated at Posted at 2017-12-28

I2C通信は、シリアル・データライン (SDA) とシリアル・ク ロックライン (SCL)の2本の線を使って、複数のデバイスが通信する仕組み。FPGAで直接I2C通信を試してみました。

オープンドレイン接続について

予備知識

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

(バス接続)
複数のデバイスが、共通の信号線(バスライン)を使って通信する接続方法。I2CのバスラインはSDAとSCLの2本。共通の信号線を使うため、電気回路や、送信するデバイスを選ぶための手順の規定が必要。

(ワイヤードアンド)
ワイヤードアンド接続は、1本の信号線(ワイヤー)に複数のデバイスの出力を並列に直接接続する回路の構成方法。デバイスの出力は、オープンドレインやオープンコレクタにするのがきまり。抵抗でプルアップした1つの信号線に、各デバイスの出力を直接繋ぐ。

オープンドレインやオープンコレクタ回路は、出力とGNDの間の抵抗値を増減する。信号線はプルアップされているため、この抵抗値が高い状態(ハイインピーダンス)では信号線の電圧は高い状態が維持されるのでプルアップされた信号線の論理値1となる。抵抗値が小さくなる(非ハイインピーダンス、論理0)と、信号線からオープンドレインやオープンコレクタの回路に電流が流れ込む。プルアップ抵抗の電圧降下により電圧が下がり、論理値0になる。

接続するデバイスのうち、1つでも0を出力するデバイスがあると信号が0になる。ワイヤーで接続するだけで、AND回路が構成できることからワイヤードANDと呼ばれる。負論理(低い電圧で1)の信号線でであればワイヤードOR。

FPGAとI2Cバスの接続

I2Cバスは、オープンドレイン接続かつ双方向接続であるため、トライステート制御する。
vivadoは、トライステート制御処理は自動的に追加される。SDAをinout port宣言して、SDAから入力したいときだけ、SDA<-'Z'とし、出力するときは'1'や'0'を書き込むようにソースをかけば、 vivadoがIOBUFを追加して制御回路を付加 する。 synthesized designをみるとIOBUFが入っていることが確認できます。(2019/9)

vivadoに頼る例
-- SDA inout
-- state st_readで読み出し
-- read_value 読み出しデータ
-- write_value 書き込みデータ
U_STATE:process(state,SDA,write_value) begin
  if state=st_read then
    SDA <='Z';
    read_value <- SDA;
  else
    SDA <= write_value;
  end if;    
end process

vivadoに頼らず、自分でトライステート制御する場合は、以下のように(出力をハイインピーダンスにできる)IOBUFを介して接続する。

IO回路
-- inSDA 信号線の状態
-- sda   出力したい信号(1でハイインピーダンス)
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)に、前項のようにotSDA_T,otSCL_Tでトライステート制御する例を示す。

パッチ
--  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バイト書き込みのシーケンス

横軸は時間、1行目はタイムスロット、2行目はMASTER装置の送信内容(空欄で受信)、3行目はSLAVE装置の送信内容(空欄で受信)

||S|SLAVE指定|R/W|Ack|DATA|Ack|P|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|MASTER|S|アドレス(7ビット)|0||書き込みデータ||P|
|SLAVE||||0||0||

1バイト読み出しのシーケンス

||S|SLAVE指定|R/W|Ack|DATA|ACK|P|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|MASTER|S|アドレス(7ビット)|1|||1|P|
|SLAVE||||0|読み出しデータ|||

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

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

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

2バイト以上の通信

2バイト以上のデータを連続書き込み/読み出しは、1バイトのシーケンスのデータ伝送とACK部分を繰り返す。

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

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

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

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

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

MASTER装置が、ROMや複数のレジスタをもつデバイスにアクセスするには、デバイスのアドレスを指定するだけでなく、レジスタやメモリのアドレス(1 or 2 byte)を指定する必要がある。このための代表的なプロトコルを示す。

書き込み

データの先頭にアドレスを追加する。

||S|SLAVE|W|A|DATA|A|DATA|A|DATA|A|DATA|A|P|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|MASTER|S|デバイス
アドレス|0||アドレス
上位バイト||アドレス
下位バイト||書き込み
データ1||書き込み
データ2||P|
|SLAVE||||0||0||0||0||0||

読み出し

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

||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|読み出し
データ||読み出し
データ|||
Sr:リピートスタートコンディション

12
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?