[[FpgaI2c]]

* 概要 [#se990e91]
- Nexys 4 付属のI2C温度計の SDA, SCL 信号線を直接スイッチで ON/OFFしながら、温度計を操作してみます。チャタリング防止や LED 表示などのため、ちょっと verilog で回路を作ります。
-- 参考: Nesys4 のマニュアル
--- https://reference.digilentinc.com/_media/nexys:nexys4:nexys4_rm.pdf
-- このマニュアルを確認しながら設定を行うと良いと思います。
- Nexys 4 付属の温度計,  Analog Devices の ADT7420
-- 詳しい情報は以下の pdf に載っています。
--- http://www.analog.com/media/jp/technical-documentation/data-sheets/ADT7420_jp.pdf
-- ADT7420 をNexys 4 で使うとき、
--- Vivadoのxdcファイルの場合は、sclの PACKAGE_PIN は "F16", sdaの PACKAGE_PINは "G16" を指定します。 (Nexys4のマニュアルのpage 22, 12 Temperature Sensor で確認してください)
 ##Temperature Sensor
 ##Bank = 15, Pin name = IO_L14N_T2_SRCC_15,					Sch name = TMP_SCL
 set_property PACKAGE_PIN F16 [get_ports scl]					
 	set_property IOSTANDARD LVCMOS33 [get_ports scl]
 ##Bank = 15, Pin name = IO_L13N_T2_MRCC_15,					Sch name = TMP_SDA
 set_property PACKAGE_PIN G16 [get_ports sda]					
 	set_property IOSTANDARD LVCMOS33 [get_ports sda]

--- ISEのUCFの場合は、sclの LOCは "F16", sdaの LOCは "G16" を指定します。 (Nexys4のマニュアルのpage 22, 12 Temperature Sensor で確認してください)
 NET "scl"			LOC = "F16"	| IOSTANDARD = "LVCMOS33";		#Bank = 15, Pin name = IO_L14N_T2_SRCC_15,					Sch name = TMP_SCL
 NET "sda"			LOC = "G16"	| IOSTANDARD = "LVCMOS33";		#Bank = 15, Pin name = IO_L13N_T2_MRCC_15,					Sch name = TMP_SDA
-- ADT7420 の(slave)device addressは、0x4b (=1001011) です。
-- 温度データを取り出すには、以下の手順を実行します。
--- Master がStart 信号を送信。... scl=1, sda=1の状態から、scl=1, sda=0 の状態にして、その後、scl=0, sda=0 とする。
--- これ以降、通信を終了するまで、Master またはdeviceが sda に high(=Z=1)または low(=0)を設定し、その状態で、Master が sclを 0->1->0 に変化することを繰り返す。
--- Master がdevice(ADT7420)のアドレス(0x4b)と、Masterからデータが送信されることを表す 0 (レジスタ番号書き込み)を送信。
--- device が ack 信号(成功していれば、0)を出力。 Master側ではこのとき、 sda 端子をZ状態(=1)として、入力を待つ。
--- Master がレジスタを表す 8bitのデータ(0000 0000)を出力。
--- device が ack 信号 0 を出力
--- Master がrestart 信号を送信(start と同じ)
--- Master が device address (0x4b)と、入力を表す 1を出力。
--- device が ack 信号 0 を出力
--- device が 最初の 8 bit を出力... この時のbit 列を Master 側で入力。
--- Master が ack 0 を出力。
--- device が次の8 bit を出力 ... この時の bit 列を Master 側で入力。
--- Master が nack 1 を出力。
--- 通信終了手順を行う。 ... sclを 1 にして、その間に sdaを 0から 1 にする。

* 回路の概要 [#j9728216]
- sw[7:0]と up button, left button, center button, right button をチャタリング防止回路に通し、その出力をswx[7:0], BUx, BLx, BCx, BRx とします。
- sw[0]をチャタリング防止回路を通して(swx[o]), sda に接続します。
- center button をチャタリング防止回路を通して(BCx),  sclに接続します。
- down button をリセット信号とします。
- sda を led[8] に接続します。scl が 0->1 に変化するたびに、これをシフトして、過去8回のsda の High/Low の遷移を led[15:8] に表示します。 これを実現するために、レジスタ data[7:0] を使っています。
- 1つのポートで入出力を行う為、scl, sda は verilog の inout 型を使います。
- data[7:0]の値を16進法4桁でLEDマトリックスの左側4個に出力する回路に接続します。
- sw[7:0]をled[7:0]に接続します。
- sw[7:0]を16進法4桁でLEDマトリックスの右側4個に出力する回路に接続します。
- 回路図
-- &ref(I2Cデバイスを手で動かしてみる/i2c-1-circuit.jpg,75%);
* Verilog と xdc または ucf [#c4fc3ca8]
- ソース: [[i2c-thermo-verilog-xdc]]
- Vivadoの画面の例 (ISEの場合は[[isc-thermo-ise]])
-- 入力終了後の状態(上のverilog のコピペで良いです)
--- &ref(I2Cデバイスを手で動かしてみる/i2c_thermo-1.png,50%);
* verilog のコンパイルと bit ファイルの作成 [#kdebad86]
- Run systhesis をクリック
--- &ref(I2Cデバイスを手で動かしてみる/i2c-thermo-run-synthesis.png,50%);
- Run Implementation  ... ポップアップウィンドウで指定, 左側のメニュー一覧から選んでもよい.
--- &ref(I2Cデバイスを手で動かしてみる/i2c-therm-synthesis-2.png,50%);
- bitファイルの生成,Generate bit stream
--- &ref(I2Cデバイスを手で動かしてみる/i2c_thermo-generate-bitstream-1.png,50%);
* Nexys4とパソコンの接続, bit ファイルのダウンロード [#m25f789a]
- bitファイル生成後, ポップアップウィンドウが開きます. ここでは OKはクリックしません.
- bitファイル生成後, ポップアップウィンドウが開きます. Open Hardware Manager を選びます。ここでは OKはクリックしません.
--&ref(I2Cデバイスを手で動かしてみる/i2c-thermo-open-hw-manager-2.png,50%);
- パソコンとNexys4を接続します.
--- &ref(I2Cデバイスを手で動かしてみる/i2c-1-7-s.jpg,30%);
- ポップアップウィンドウのOKをクリックします.
-- Hardware Managerの Open Tagert が click 可能になります。
--- &ref(I2Cデバイスを手で動かしてみる/i2c-thermo-open-manager-0.png,50%);
- Open Taget を click し, auto connect をクリックします。 
--- &ref(I2Cデバイスを手で動かしてみる/i2c-therm-hw-manager-auto-connect.png,50%);
- Program Device をクリックします。
--- &ref(I2Cデバイスを手で動かしてみる/i2c-thermo-hw-manager-program-device.png,50%);
- プログラム可能なデバイス名(xc7a100t)が表示されます。これをクリックします。
--- &ref(I2Cデバイスを手で動かしてみる/i2c-thermo-hw-manager-program-device-2.png,50%);
- プログラム(download)するbitファイルの候補が表示されるので、確認して、programボタンをクリックします。
--- &ref(I2Cデバイスを手で動かしてみる/i2c-thermo-hw-manager-program-device-3.png,50%);

-- ダウンロードが終了すると、ボードの7セグメントLEDに"0000 0000"が表示される(スライドスイッチがすべてOffの場合)。
--- &ref(I2Cデバイスを手で動かしてみる/i2c-1-19-s.jpg,50%); &br; (スライドスイッチ 0 がONになっているので、左端が1になっています。)
* 実行 [#m6897115]
- 手順詳細
-- bitファイルのダウンロード終了時点で、自動的に回路に電源が供給されて、回路が動き始めます。
-- sw[0](sda) を1にします。center button (scl)は、押していない時に0, 押したときに 1 になります。
-- sclを1 にして、sda を 1->0にします。(center button を1にして、その状態のまま, sw[0]を1から0にする)
-- sclを0にします。(center buttonを離す)
-- sdaを1にして、sclを 0->1->0にします。(sw[0]を1にして、center button を押して離す)... これで device の7bit のアドレスのMSBの1bit がデバイス側に送られます。
-- sdaを0にして、sclを 0->1->0にします。
-- sdaを0のまま、sclを 0->1->0にします。
-- sdaを1にして、sclを 0->1->0にします。
-- sdaを0にして、sclを 0->1->0にします。
-- sdaを1にして、sclを 0->1->0にします。
-- sdaを1のまま、sclを 0->1->0にします。ここまでが、ADT7420のアドレス, 0x4bの出力です。
-- sdaを0にして、sclを 0->1->0にします。write (=0)の出力です。
-- sdaを1(Z)にして、sclを0->1->0にします。ADT7420から ack(=0)が出力され、led[8]に表示されるはずです。
-- sdaを0にして、sclを8回、0->1->0にします。 ... register 0の指定です。
-- sdaを1(Z)にして、sclを0->1->0にし、ADT7420から ackを入力します。
-- sdaを1のまま、sclを1にします。
-- sclを1のまま、sdaを0にして、restart します。そのあと、sclを0にします。
-- sdaを1にして、sclを 0->1->0にします。
-- sdaを0にして、sclを 0->1->0にします。
-- sdaを0のまま、sclを 0->1->0にします。
-- sdaを1にして、sclを 0->1->0にします。
-- sdaを0にして、sclを 0->1->0にします。
-- sdaを1にして、sclを 0->1->0にします。
-- sdaを1のまま、sclを 0->1->0にします。ADT7420のアドレス, 0x4bの再出力です。
-- sdaを1にして、sclを 0->1->0にします。read (=1)の出力です。
-- sdaを1のまま、sclを 0->1->0にし、ADT7420からackを入力します。
-- sdaを1のまま、sclを8回 0->1->0します。このとき、ADT7420から温度データが送られてきて、それが、led[8]から入力され、右にシフトされます。最初の bit は、符号を表します。符号を含む最初の8bitは、全16bitのMSB側の8bitです。
-- sdaを0にして、sclを 0->1->0にして、Master から ADT7420へ ack (0)を送ります。
-- sdaを1にして、そのまま、sclを8回 0->1->0します。このとき、ADT7420から温度データの下位8bitが送られてきて、それが、led[8]から入力され、右にシフトされます。入力された全16bitのうち、符号を除く上位8bit、(つまり、最初の1byte(8bit)のうち、2番目以降の7bit と、次に入力された1byte の最初の1bit )が、摂氏で表した温度の整数部分を表します。
-- 最後に、sdaを0, sclを1, そのまま sdaを1, にすることによって、通信終了信号がMaster からADT7420へ送られます。これで一通りのサイクルが終了します。
----
- 実際に操作しているところの動画です。
-- http://youtu.be/mjl-93KeypM
- 説明
-- 最初のスイッチの操作 ... I2C通信開始信号送信
--- center button を押して sclを 1にして、押したままにしておく。&br; &ref(I2Cデバイスを手で動かしてみる/i2c-1-23.jpg,50%); 
---スライドスイッチをOffからONにして, sdaを1にする。&br;  &ref(I2Cデバイスを手で動かしてみる/i2c-1-24.jpg,50%); 
--- スライドスイッチをONからOFFにする。&br; &ref(I2Cデバイスを手で動かしてみる/i2c-1-25.jpg,50%);
-- アドレスの送信の最初の部分
---  sclを0にしたあと, sdaを1にして、sclを 0->1->0 &br;
&ref(I2Cデバイスを手で動かしてみる/i2c-1-26.jpg,50%); 
--- led[8]が点灯(1がsdaに流れたことを示す)。&br;
&ref(I2Cデバイスを手で動かしてみる/i2c-1-27.jpg,50%); 
-- 再スタート, アドレス指定, 読み込みbit (1)送信, ack受信(0)受信の後, 最初に読み込んだ8bitのデータが 00010000
--- &ref(I2Cデバイスを手で動かしてみる/i2c-1-r-data-2.jpg,50%); 
-- 次の8bit が, 11010000 
---  &ref(I2Cデバイスを手で動かしてみる/i2c-1-r-data-3.jpg,50%); 
-- この2つの01の列を接続した16bitの値が計測された温度です。最初の1bitは符号で、そのあとの8bit が摂氏で表した温度の小数点より大きいあたい、残りが、小数点より小さい値です。
-- 従って、0010 0001 が摂氏の小数点より大きい値となり、摂氏33度であることがわかります(ボードの熱で、ちょっと高い温度になるようです)。小数点以下の部分は、101なので 1/2 + 1/8=0.5+0.125=0.625となり、整数部分に加えると、33.625度、ということになります。
--- 実際に赤外線温度計で計測すると、摂氏33.6度となっており、かなり近い値が計測されていることが確認できます。&br;
---  &ref(I2Cデバイスを手で動かしてみる/i2c-1-28.jpg,50%); 
* 考察 [#x8893931]
- 手でI2Cデバイスを制御するのは大変。ちょっと間違えたら1からやり直し。
- tinyCPUを作ったのだから、それを使って、プログラムで制御したらいいじゃん。

----
#counter

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS