[IP][Avalon] I2C master controller wrapper
はじめに
自作部分はAvalon SlaveにWISHBONEモジュールをぶら下げるためのBridgeのみなので、ほかのモジュールにも転用できるかと思います。
【注意】本記事は、16ヶ月ほど前のコードと資料を元に作成しており、i2c_masterもversionがあがっております.WISHBONEおよびI2Cインタフェース部分にも修正が入っているようなので、最新版での動作保障はありません.現状、環境がないので確認できません…
自製部分のみ、_IP_I2C_v000.zipとして置いておきます。tclも入れておきますが、FatFSのときのように動作確認をしていませんので、ご了承いただきたく。実際に使ったサンプルコードも置いておきます(avalon_i2c.zip)。\いまさらですが、writeしか使ってない模様…。WM8731へは書きっぱなしでよかったのかな... 記憶があいまいデスすみません.
概要
I2C MasterとなるIPです.\本IPは,opencores.orgで開示されている,以下のものをベースとしました.
http://www.opencores.org/ "I2C controller core" Category :: Communication controller Name: i2c Created: 25-Sep-2001 10:15:03 Updated: 03-Nov-2008 14:55:35 Category :: Communication controller Language :: Verilog Language :: VHDL Phaze :: ASIC proven Phaze :: Design done Phaze :: FPGA proven Standard :: Wishbone compliant core Development status :: Production/Stable Rev. 0.9 Release data: 03/07/03 i2c_specs.pdf
収録ファイルと個々の概要説明
- avalonif_i2c.txt
このファイル.IPの簡単な説明等を記載する
- avalonif_i2c_hw.tcl
SOPC builderが食うファイル. Avalon-MM I/Fの仕様や追加すべきファイル,パラメータ初期値などの情報が入っている.
- avalonif_i2c.v
Avalon I/Fを含む本モジュールのtopレベルモジュールを記述したファイル. "i2c_master_top.v"と同等の機能を有す.(moduleとSystem BUSの仲介だけ)
以下、i2cオリジナルに含まれるものです。
- timescale.v
- i2c_master_defines.v
- i2c_master_byte_ctrl.v
- i2c_master_bit_ctrl.v
- i2c_master_top.v
実装時の注意事項
I2Cバスの信号である,SDA/SCKは外部Pull Upになり,master/slaveはopen drainで駆動します.本IPも,各信号をLowに落とすときだけ,Padのenable信号を出すように作られています.tope level moduleには,以下の信号が出ています.
sda_padoen_o sda_pad_o sda_pad_i scl_padoen_o scl_pad_o scl_pad_i
PADの出力値は,sda_pad_o(scl_pad_o)に出てきます.ただし常にLowでGND接続になります.\PADからの入力は,sda_pad_i(scl_pad_i)を通して行います.\最後に,PADの出力制御は,sda_padoen_o(scl_padoen_o)を用い,active lowです.\highのときは,PADはドライブせず,Hi-Z状態としてください.\※詳細はオリジナルのドキュメントを参照していただきたく.
Verilog-HDLでの記述例を示します.\NEEKなど,シングルマスタを想定してプルアップしていない回路では,コメントアウトしたほうを用いてください.ただしデータに関しては双方向と成るため,Pull Upは必須と成ります.\# I2Cとした時点で,CLK/DAT双方ともPullUpすべきだと思うのですが...
module xxx ( inout HC_I2C_SDAT, HC_I2C_SCLK, ... ) ; assign sda_pad_i = HC_I2C_SDAT ; assign HC_I2C_SDAT = (sda_padoen_o==1'b0 ? sda_pad_o : 1'bz) ; assign scl_pad_i = HC_I2C_SCLK ; assign HC_I2C_SCLK = (scl_padoen_o==1'b0 ? scl_pad_o : 1'bz) ; // assign HC_I2C_SCLK = scl_padoen_o ; // if Single Master and No-Pull Up(for NEEK) slave address = 7'b0011010 @ CSB = Low at NEEK
ハードウェア仕様
モジュールのアドレス空間
offset | symbol | description |
---|---|---|
0 | Status / RxData | |
1 | Command Register | |
2 | Control / TxData | |
3 | pre | I2C clock prescaler |
"Command"
7 | STA | START condition |
6 | STO | STOP condition |
5 | RD | Read Data |
4 | WR | Write Data |
3 | ACK | when receiver(1:ACK/0:NACK) |
2 | - | |
1 | - | |
0 | IACK | 1書き込みで要因クリア |
"Control / TxData"
31 | EN | Enable I2C core |
30 | IEN | interrupt enable |
29-24 | - | reserved |
23-8 | - | reserved |
7-0 | txdata | Transmit data. slaveアドレス送信時はLSBがdirection(1:R/0:W)を示す |
"Status"
31-16 | - | reserved |
15 | RxACK | スレーブからのACK受領ステータス.0で受信,1で未受信 |
14 | Busy | 1:STArt detected, 0:STOp detected |
13 | AL | Arbitration Lost |
12-10 | reserved | |
9 | TIP | 1: 転送中, 0:転送完了 |
8 | IF | 割込みフラグ.転送完了もしくはArbitration Lostでたつ |
7-0 | rxdata |
プリスケーラの値は,下記の算出式により得ることができます.
(document 3.2.1参照) IPの動作クロックを f_clk[Hz],SCLKの周波数を f_sclk[Hz]とします value of pre-scaler = f_clk / (5 * f_sclk) - 1 ex.) f_clk = 18.432MHz f_sclk = 500kHz value of pre-scaler = 18432 / (5 * 500) - 1 = 6.3728 => 7