MxTNIのJTAGライブラリとSVFファイルを使用してXilinx社製PROMデバイスをプログラムする

要約

このアプリケーションノートでは、MxTNI™のJTAGライブラリとSVF (シリアルベクトルフォーマット)ファイルを使用して、Xilinx®社製PROMデバイスをプログラムする方法について説明します。読者は、JTAGおよびプログラマブルロジックについてある程度の知識があることを前提にしています。

はじめに

Maxim Tiny Network Interface (MxTNI)は、マキシム・インテグレーテッド・プロダクツの完全子会社であるダラスセミコンダクタが開発したプラットフォームです。TINIは、小型ながらも強力なチップセットとJava®プログラマブルランタイム環境とを組み合わせたものです。チップセットには、処理、制御、デバイスレベルの通信、およびネットワーキング機能が搭載されています。いずれのJTAGデバイスとも通信できるようにするため、TINIs400ソケットボードは、J21端子に4ピンのJTAG出力が設けられています。これらのピンは、JTAGデバイスの標準JTAGピンであるTDI、TDO、TMS、およびTCKに直接結線します。

インシステムプログラム(ISP)可能なPROMは、個別にプログラムすることもチェーン式にプログラムすることも可能です。チェーン内のすべてのデバイスは、TCKとTMS信号を共有します。MxTNIのTDI信号は、バウンダリスキャンチェーン内の最初のデバイスのTDI入力に接続します。この最初のデバイスのTDO信号は、チェーン内の2番目のデバイスのTDI入力に接続され、以降同様に接続されます。チェーン内の最後のデバイスのTDO出力は、図1に示すように、MxTNIのTDOピンに接続されます。

図1. すべてのJTAG動作は、デバイスのテストアクセスポートを通じて制御されます。
図1. すべてのJTAG動作は、デバイスのテストアクセスポートを通じて制御されます。

すべてのJTAG動作は、デバイスのテストアクセスポート(TAP)を通じて制御されます。TAPは、TMS、TDI、TDO、およびTCKの4つの信号で構成されます。これらの信号は、TAPコントローラ、すなわち16ステートの有限ステートマシンを通してデバイスと対話します。JTAGのTMS信号は、ステート間の遷移を制御します。命令やデータは、TDIピンからデバイスにシフト入力され、TDOピンからシフト出力されます。TDI信号やTDO信号上でのすべてのステート遷移や状況は、TCK信号に同期しています。図2を参照してください。

図2.
図2.

すべてのJTAG動作は、JTAGの命令レジスタとデータレジスタとの間でデータをシフト入力/出力します。TAPコントローラは、これらすべてのレジスタに直接アクセスすることができます。JTAGレジスタには、IR (命令レジスタ)とDR (データレジスタ)の2つのクラスがあります。IRには、Shift-IRステートを通じてアクセスし、DRには、Shift-DRステートを通じてアクセスします。通常、IRの長さは2ビット以上の任意のサイズです。IEEE®標準1149.1で「すべて1」と定義されているBYPASS命令を除いて、製造業者は他のすべての命令ビットコードを定義します。

このアプリケーションノートでは、JAVAのサンプルコードは、プログラミングを実行するためにシリアルベクトルフォーマット(SVF)ファイルを解釈します。ここで使用するSVFは、ハイレベルのIEEE 1149.1 (JTAG)バス動作を記述するための構文仕様です。SVFは、データ交換の規格として、JTAG機器やソフトウェアの製造業者によって採用されてきました。SVFは、簡潔で移植可能な形式のJTAGチェーン動作を記述することに使用されます。SVFファイルは、デバイスチェーンにシフト入力することが必要な情報を記述することで、JTAG動作を記録します。JTAG動作は、Xilinx社製iMPACT (詳細は後述)ソフトウェアによって、SVFファイルに記録されます。SVFファイルは、ASCIIテキストで書かれているため、任意のテキストエディタにて、手動で読み取り、修正、書き込みが可能です。「多くのサードパーティ製プログラミングユーティリティは、SVFファイルを入力として使用し、そのSVFファイルに含まれる情報を用いて、JTAGチェーン内のXilinx社製デバイスをプログラムすることができます。」

JTAGライブラリの概要

JTAGクラスライブラリは、MxTNIを使用してJTAGデバイスと通信を行うユーザを支援するために開発されたものです。遠隔地からプログラマブルロジックを動的にインシステムで更新することも、1つの応用例です。ユーザは、TAPコントローラを初期ステートへ初期化して、16ステートの確認、TAPステートの取得または設定、クロック信号の生成、およびコマンドやデータの送信を行うことができます。以下に、JTAGクラスメソッドの概要を示します。

  • public jtag():jtagライブラリをロードします。
  • public String getVersion():jtagクラスのバージョンを返します。
  • public int runClock(int numticks):numticksで指定した数値のクロックで実行します。
  • public byte initialize():TCKの5パルス間、TMSをハイに駆動し、さらに1クロックの間TMSをローにして、デフォルトのRun-Test-Idleステートに移行します。
  • public byte setState(byte aState):オブジェクトステートを、aStateで指定されたステートに設定します。
  • public byte getState():オブジェクトステートを返します。
  • public byte scanState(byte state):TAPコントローラのステートマシンをパラメータstateで示すステートに遷移させます。
  • public String displayState(byte state):TAPコントローラのステートを表示します。
  • public byte waitState(int msecs):ミリ秒単位で指定した値だけ処理を遅らせます。
  • public byte getTDO():TDOピンの現在のステートを取得します。
  • public void setTDI(byte logic):指定したロジックにTDIピンを設定します。
  • public byte getTDI():TDIピンの現在のステートを取得します。
  • public void setTMS(byte logic):指定したロジックにTMSピンを設定します。
  • public byte getTMS():TMSピンの現在のステートを取得します。
  • public void setTCK(byte logic):指定したロジックにTCKピンを設定します。
  • public byte getTCK():TCKピンの現在のステートを取得します。
  • public byte sendNrcv(byte[] data, int offset, int size, byte numberOfBits, boolean state, boolean update, byte extraHeaderClock, byte HeaderBitVal, byte extraTrailerClock, byte TrailerBitVal):データをバイト配列で送信し、バイト配列で受信します。
  • public byte sendNrcv(int[] data, int offset, int size, byte numberOfBits, boolean state, boolean update, byte extraHeaderClock, byte HeaderBitVal, byte extraTrailerClock, byte TrailerBitVal):データを整数配列で送信し、整数配列で受信します。

ハードウェアとソフトウェア要件

以下のハードウェアとソフトウェアが必要です。

プログラミング手順

手順1:MxTNIボードの4本のJTAGピンと、JTAGデバイスの4本のJTAGピンとを結線します。
手順2:SVFファイルのコマンドに従い、JTAGライブラリを使用してJAVAアプリケーションを記述し、JTAGデバイスのプログラム、コンパイル、およびMxTNIへのロードを行います。
(付録A:スタンドアロンのXilinx社製XC18V02デバイスからIDCODEを読み取るためのサンプルファイルIdcode.svf)
(付録B:サンプルプログラムAppJtag.javaが、SVFファイルを入力として処理し、IDCODEを読み取るためのJTAG信号を生成します。このサンプルプログラムは、スタンドアロンのデバイスを処理するために記述されたものです(チェーン接続のデバイスの場合の詳細については、付録Cを参照してください))
(付録C:既存のSVFファイルからチェーン接続のデバイスをプログラムするための手順の説明)
手順3:JAVAプログラムを実行します。実行可能なAppJtag.tiniは、MxTNIボードにロードされます。MxTNIプロンプトに「java AppJtag.tini Idcode.svf」と入力して、プログラムを実行します)。プログラムは、JTAGデバイスと通信するためのJTAG信号を生成します。
注:

  1. プログラムされたJTAGデバイスのSVFファイルは、デバイスチェーン内で設計したモデルとまったく同じモデルで生成する必要があります。
  2. プログラムされたJTAGデバイスのすべてのオペコード(READ、WRITE、ERASEその他)は製造業者によって定義されます。SVFファイルは、ユーザが必要とするすべてのオペコードを含んでいなければなりません。

事例

以下の事例は、JTAGライブラリを使用してXilinx社のJTAGデバイスXC18V02からIDCODEを読み取る方法を示しています。完全なサンプルコードについては、付録Bを確認してください。

  1. デバイスモデルのSVFファイルを生成します。
    Xilinx社のWEB STARTを使用して、SVFファイルを生成します。
    • iMPACTを実行し、ラジオボタンの[Prepare Configuration Files (構成ファイルの準備)]オプションを選択して、[Next (次へ)]をクリックします。ラジオボタン[Boundary Scan file (バウンダリスキャンファイル)」を選択し、[Next (次へ)]をクリックします。[SVF File (SVFファイル)]を選択して、[Finish (終了)]をクリックします。
    • ダイアログ内の例のようにSVFファイルの名前を入力し、[OK]をクリックします。
    • name_of_mcs_file.mcsファイルを選択し、ロードして、リストからPROMデバイスを選択します(XC18V02_vq44)。
    • XC18V02がモデルに追加されます。
    • モデルをクリックして、プログラムするデバイスXC18V02を選択します。デバイスが強調表示されます。
    • マウスを右クリックして、プログラムオプションを選択します。[Get Idcode (Idcodeの取得)]のチェックボックスをオンにします。
    • モデルの外側でマウスをクリックしてデバイスの強調表示を解除し、右クリックしてSVFを終了するオプションを選択します。この時点で、モデルのSVFファイルが生成されます。
  2. SVFファイルを読み取り、JTAGライブラリを使用して、XC18V02デバイスをプログラムします。
    • 以下は、SVFファイルのサンプルの一部です。
    // Created using Xilinx iMPACT Software [ISE WebPACK - 5.1i]
    TRST OFF;
    ENDIR IDLE;
    ENDDR IDLE;
    STATE RESET IDLE;
    TIR 0 ;
    HIR 0 ;
    TDR 0 ;
    HDR 0 ;
    // Validating chain...
    TIR 0 ;
    HIR 0 ;
    TDR 0 ;
    HDR 0 ;
    SIR 8 TDI (ff) SMASK (ff) ;
    TIR 0 ;
    HIR 5 TDI (1f) SMASK (1f) ;
    HDR 1 TDI (00) SMASK (01) ;
    TDR 0 ;
    //Loading device with 'idcode' instruction.
    SIR 8 TDI (fe) SMASK (ff) ;
    SDR 32 TDI (00000000) SMASK (ffffffff) TDO (05025093) MASK (ffffffff) ;
    //Loading device with 'conld' instruction.
    SIR 8 TDI (f0) ;
    RUNTEST 110000 TCK;
    
    • SVFコマンドに従い、ライブラリを使用して、XC18V02にコマンドを送信します。
    • SVFの仕様には、ヘッダ命令レジスタ(HIR)、トレーラ命令レジスタ(TIR)、ヘッダデータレジスタ(HDR)、およびトレーラデータレジスタ(TDR)の4つのグローバルパディング命令があります。これらのグローバルコマンドは、シフト操作の先頭や末尾にパディングするビット数を指定することで、バイパスされるデバイスを説明し、SVFファイルの圧縮方法を簡素化しています。一度指定されると、これらのビットは、SIRまたはSDRコマンド用にシフトされるあらゆるビットセットの前または後に付加されます。
    • 以下は、SVFコマンドを解釈してJTAGライブラリコマンドに変換する方法の2つの事例です。

事例1:グローバルパディング命令を用いたSVF構文

a/ SVF file commands:
STATE RESET IDLE;
TIR 0 ;
HIR 5 TDI (1f) SMASK (1f) ;
HDR 1 TDI (00) SMASK (01) ;
TDR 0 ;
//Loading device with 'idcode' instruction.
SIR 8 TDI (fe) SMASK (ff) ;
SDR 32 TDI (00000000) SMASK (ffffffff) TDO (05025093) MASK (ffffffff) ;
//Loading device with 'conld' instruction.
SIR 8 TDI (f0) ;
RUNTEST 110000 TCK;
//Check for Read/Write Protect.
SIR 8 TDI (ff) TDO (01) MASK (ff) ;
//Loading device with 'idcode' instruction.
SIR 8 TDI (fe) ;
SDR 32 TDI (00000000) TDO (05025093) ;
//Loading device with 'conld' instruction.
SIR 8 TDI (f0) ;
RUNTEST 110000 TCK;
//Check for Read/Write Protect.
SIR 8 TDI (ff) TDO (01) ;
TIR 0 ;
HIR 0 ;
TDR 0 ;
HDR 0 ;
b/ Sample JAVA program using JTAG library:
import java.io.*;
import javax.comm.*;
import com.dalsemi.comm.*
public static void main(String[] args)
{
myJtag = new jtag();
int SIZE = 0x1000;
byte[] byteArray = new byte[SIZE];
byte HeaderInstBitVal = (byte)0x00;
byte TrailerInstBitVal = (byte)0x00;
byte HeaderDataBitVal= (byte)0x00;
byte TrailerDataBitVal= (byte)0x00;  
// STATE RESET IDLE;
myJtag.initialize();//This JTAG library method will initialize 
		  // XC18V02 TAP controller and stay at 
		  // Run-Test/Idle 
// TIR 0 ;
byte TIR = (byte)0x00; 
// HIR 5 TDI (1f) SMASK (1f) ;
byte HIR = (byte)0x05;
HeaderInstBitVal = (byte)0x01;
// HDR 1 TDI (00) SMASK (01) ; 
byte HDR = (byte)0x01; 
HeaderDataBitVal = (byte)0x00;
// TDR 0 
byte TDR = (byte)0x00;
// SIR 8 TDI (fe) SMASK (ff) ; 
byteArray[0] = (byte)0xfe;
myJtag.sendNrcv(byteArray,0,1,(byte)8,true,false,(byte)HIR,
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
// SDR 32 TDI (00000000) SMASK (ffffffff) TDO (05025093) MASK
// (ffffffff) ;
byteArray[0] = (byte)0x00;
byteArray[1] = (byte)0x00;
byteArray[2] = (byte)0x00;
byteArray[3] = (byte)0x00;
myJtag.sendNrcv(byteArray,0,4,(byte)8,false,false,(byte)HDR,
(byte)HeaderDataBitVal,(byte)TDR,(byte)TrailerDataBitVal);
// SIR 8 TDI (f0) ;
byteArray[0] = (byte)0xf0;
myJtag.sendNrcv(byteArray,0,1,(byte)8,true,false,(byte)HIR,
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
// RUNTEST 110000 TCK;
myJtag.waitState(100); // Depend on operation frequency, user can
			 // calculate how many miliseconds to wait.     
}

事例2:グローバルパディング命令を用いないSVF構文

a/ SVF file commands:
STATE RESET IDLE;
TIR 0 ;
HIR 0 ;
TDR 0 ;
HDR 0 ;
SIR 13 TDI (1fff) SMASK (1fff) ;
SDR 2 TDI (00) SMASK (03) ;
SIR 13 TDI (1fff) TDO (0021) MASK (1c63) ;
// Loading devices with 'ispen' or 'bypass'  instruction.
SIR 13 TDI (1d1f) ;
SDR 7 TDI (68) SMASK (7f) ;
// Loading device with 'faddr' instruction.
SIR 13 TDI (1d7f) ;
SDR 17 TDI (000002) SMASK (01ffff) ;
RUNTEST 1 TCK;
// Loading device with 'ferase' instruction.
SIR 13 TDI (1d9f) ;
RUNTEST 100000 TCK;
// Loading device with a 'faddr' instruction.
SIR 13 TDI (1d7f) ;
SDR 17 TDI (000002) ;
RUNTEST 1 TCK;
// Loading device with 'serase' instruction.
SIR 13 TDI (015f) ;
RUNTEST 37000 TCK;
// Loading devices with 'conld' or 'bypass' instruction.
SIR 13 TDI (1e1f) ;
RUNTEST 110000 TCK;
// Loading devices with 'ispen' or 'bypass'  instruction.
SIR 13 TDI (1d1f) ;
SDR 7 TDI (68) SMASK (7f) ;
// Loading device with a 'fdata0' instruction.
SIR 13 TDI (1dbf) ;
b/ Sample JAVA program using JTAG library:
import java.io.*;
import javax.comm.*;
import com.dalsemi.comm.*
public static void main(String[] args)
{
myJtag = new jtag();
int SIZE = 0x1000;
int[] intArray = new int[SIZE];
byte HeaderInstBitVal = (byte)0x00;
byte TrailerInstBitVal = (byte)0x00;
byte HeaderDataBitVal= (byte)0x00;
byte TrailerDataBitVal= (byte)0x00;  
// STATE RESET IDLE;
myJtag.initialize();//This JTAG library method will initialize 
	  // XC18V02 TAP controller and stay at 
	  // Run-Test/Idle 
// TIR 0 ;
byte TIR = (byte)0x00; 
// HIR 0 ;
byte HIR = (byte)0x00; 
// HDR 0 ; 
byte HDR = (byte)0x00; 
// TDR 0 
byte TDR = (byte)0x00;
// SIR 13 TDI (1fff) SMASK (1fff) ; 
intArray[0] = (int)(0x1fff&0x1fff);
myJtag.sendNrcv(intArray,0,1,(byte)13,true,false,(byte)HIR, 
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
// SDR 2 TDI (00) SMASK (03) ;
intArray[0] = (int)(0x00&0x03);
myJtag.sendNrcv(intArray,0,1,(byte)2,false,false,(byte)HDR, 
(byte)HeaderDataBitVal,(byte)TDR,(byte)TrailerDataBitVal);
// SIR 13 TDI (1fff) TDO (0021) MASK (1c63) ;
intArray[0] = (byte)0x1fff;
myJtag.sendNrcv(intArray,0,1,(byte)13,true,false,(byte)HIR,
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
// SIR 13 TDI (1d1f) ;
intArray[0] = (byte)0x1d1f;
myJtag.sendNrcv(intArray,0,1,(byte)13,true,false,(byte)HIR, 
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
// SDR 7 TDI (68) SMASK (7f) ;
intArray[0] = (int)(0x68&0x7f);
myJtag.sendNrcv(intArray,0,1,(byte)7,false,false,(byte)HDR, 
(byte)HeaderDataBitVal,(byte)TDR,(byte)TrailerDataBitVal);
// SIR 13 TDI (1d7f) ;
intArray[0] = (byte)0x1d7f;
myJtag.sendNrcv(intArray,0,1,(byte)13,true,false,(byte)HIR, 
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
// SDR 17 TDI (000002) SMASK (01ffff) ;
intArray[0] = (int)(0x0002 & 0xffff);
TDR = (byte)0x01;
myJtag.sendNrcv(intArray,0,1,(byte)16,false,false,(byte)HDR, 
(byte)HeaderDataBitVal,(byte)TDR,(byte)TrailerDataBitVal);
// RUNTEST 1 TCK;
myJtag.waitState(1);
// SIR 13 TDI (1d9f) ;
intArray[0] = (byte)0x1d9f;
myJtag.sendNrcv(intArray,0,1,(byte)13,true,false,(byte)HIR, 
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
// RUNTEST 100000 TCK;
myJtag.waitState(1000);
// SIR 13 TDI (1d7f) ;
intArray[0] = (byte)0x1d7f;
myJtag.sendNrcv(intArray,0,1,(byte)13,true,false,(byte)HIR, 
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
// SDR 17 TDI (000002) ;
intArray[0] = (int)(0x0002 & 0xffff);
TDR = (byte)0x01;
myJtag.sendNrcv(intArray,0,1,(byte)16,false,false,(byte)HDR, 
(byte)HeaderDataBitVal,(byte)TDR,(byte)TrailerDataBitVal);
// RUNTEST 1 TCK;
myJtag.waitState(1);
// SIR 13 TDI (015f) ;
intArray[0] = (byte)0x015f;
myJtag.sendNrcv(intArray,0,1,(byte)13,true,false,(byte)HIR, 
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);  
// RUNTEST 37000 TCK;
myJtag.waitState(100);
// SIR 13 TDI (1e1f) ;
intArray[0] = (byte)0x1e1f;
myJtag.sendNrcv(intArray,0,1,(byte)13,true,false,(byte)HIR, 
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
// RUNTEST 110000 TCK;
myJtag.waitState(110);
// SIR 13 TDI (1d1f) ;
intArray[0] = (byte)0x1d1f;
myJtag.sendNrcv(intArray,0,1,(byte)13,true,false,(byte)HIR, 
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
// SDR 7 TDI (68) SMASK (7f) ;
intArray[0] = (int)(0x68 & 0x7f);
TDR = (byte)0x00;
myJtag.sendNrcv(intArray,0,1,(byte)7,false,false,(byte)HDR, 
(byte)HeaderDataBitVal,(byte)TDR,(byte)TrailerDataBitVal);
// SIR 13 TDI (1dbf) ;
intArray[0] = (byte)0x1dbf;
myJtag.sendNrcv(intArray,0,1,(byte)13,true,false,(byte)HIR, 
(byte)HeaderInstBitVal,(byte)TIR,(byte)TrailerInstBitVal);
}

結論

Xilinx社製PROMデバイスは、提供されたSVFを用いて非常に簡単にプログラムすることができます。しかし、そうであっても、ユーザがSVFファイルを分析できて、どのようにデバイスチェーン内のデバイスがプログラムされるのかを理解することは、より望ましいことです。この情報がわかれば、プログラマはより効率的にJTAGライブラリを活用することができます。このライブラリには、Xilinx社製JTAGデバイスのプログラミングを遠隔地に配信したいと考えるソフトウェアチームにとって実用的なアプリケーションが用意されています。これは、パッケージに組み込まれたJTAGプログラミングソフトウェアと入力ファイルとしてmcsファイルを使用することにより、簡単に実行できます。

付録A
デバイスのIDCODEを取得するためのIDCODE.SVFファイルの完全なサンプル

// Created using Xilinx iMPACT Software [ISE WebPACK - 5.1i]
TRST OFF;
ENDIR IDLE;
ENDDR IDLE;
STATE RESET IDLE;
TIR 0 ;
HIR 0 ;
TDR 0 ;
HDR 0 ;
// Validating chain...
TIR 0 ;
HIR 0 ;
TDR 0 ;
HDR 0 ;
SIR 13 TDI (1fff) SMASK (1fff) TDO (0021) MASK (1c63) ;
TIR 0 ;
HIR 5 TDI (1f) SMASK (1f) ;
HDR 1 TDI (00) SMASK (01) ;
TDR 0 ;
//Loading device with 'idcode' instruction.
SIR 8 TDI (fe) SMASK (ff) ;
SDR 32 TDI (00000000) SMASK (ffffffff) TDO (05025093) MASK (ffffffff) ;
//Loading device with 'conld' instruction.
SIR 8 TDI (f0) ;
RUNTEST 110000 TCK;
//Check for Read/Write Protect.
SIR 8 TDI (ff) TDO (01) MASK (ff) ;
//Loading device with 'idcode' instruction.
SIR 8 TDI (fe) ;
SDR 32 TDI (00000000) TDO (05025093) ;
//Loading device with 'bypass' instruction.
SIR 8 TDI (ff) ;
TIR 0 ;
HIR 0 ;
TDR 0 ;
HDR 0 ;
SIR 13 TDI (1fff) SMASK (1fff) ;
SDR 2 TDI (00) SMASK (03) ;

付録B
スタンドアロンのデバイスとしてXilinx社製XC18V02デバイスのIDCODEを読み取るための例

NOTES: This sample program will process SVF file with global padding instructions only. 
Users need to modify to work with SVF file without global padding.
import java.io.*;
import java.lang.*;
import javax.comm.*;
import com.dalsemi.comm.*;
public final class AppJtag
{
private static jtag myJtag; 
// Starting index of data array 
static int Offset = 0;  
// Number of byte to send within the data array             
static   int Size = 0;  
// Number of bits/byte or bits/integer               
static   byte NumberOfBits = 8;
// State = true (Instruction); State = false (Data)        
static   boolean State = true; 
// For Xilinc device this variable always false        
static   boolean Update = false; 
// For Instruction header and trailer      
static   byte HIR = 0 , TIR = 0 ;  
// For Data header and trailer    
static   byte HDR = 0 , TDR = 0;
// For Instruction header and trailer bit value
static   byte HeaderBitInstVal = 1, TrailerBitInstVal = 1;  
// For Data header and trailer bit value
static   byte HeaderBitDatVal = 0, TrailerBitDatVal = 0; 
static   int Key;
static   byte[] myData = new byte[4096]; 
static   String line;
static   RandomAccessFile SVFFile;
static   File mySVF ;
public static int ProcessSVFLine()
{
int  loop;
int OBracket = 0, CBracket = 0 ;
int myKey = 0x0;
StringBuffer buffer;
byte myAdd = (byte)0x0;
// Check the size in bits
myKey = Integer.parseInt(line.substring(line.indexOf(' ')+1,line.indexOf(' ',line.indexOf(' ')+1)));
if (myKey != 0)  // myKey != 0
{
// Find value of data in byte format
OBracket = line.indexOf('(');
if ( myKey/8 > line.length()) 
{
// Copy data string to buffer starting from open bracket to
// end of data line
buffer = new StringBuffer(line.substring(OBracket+1,line.length()));
// Get another line of data and append to buffer
try
{ 
line = SVFFile.readLine();
while(line != null)
{
	 // Find close bracket
	 CBracket = line.indexOf(')',0);
	 if ( CBracket < 0) //Can not find close bracket
	 {
		buffer.append(line.substring(0,line.length()));  
		line = SVFFile.readLine();
	 }     
	 else // Find close bracket
	 {
		 buffer.append(line.substring(0,CBracket));
		 line = null;
	 }
}
loop = 0;
// Store data into array to send
for (int x = buffer.length(); x > 0; x--)
{
myData[loop] =(byte) Integer.parseInt((buffer.toString()).substring(x-2,x),16);
loop++; x--; } } catch(IOException a) { System.out.println("Cannot read data "+ a); } } else { // Line of data is within one line."); CBracket = line.indexOf(')',OBracket+1); if (Key <= 3 || Key == 6) // Process header & trailer { if (Key != 6) { // determine value of header and trailer if(Integer.parseInt(line.substring(OBracket+1,CBracket).substring(0,2),16)>0) myAdd = (byte)0x01; else myAdd = (byte)0x00; } } else // Process SIR & SDR { loop = 0; for (int s = CBracket - (OBracket+1); s >0 ; s--) { myData[loop] =(byte) Integer.parseInt((line.substring(OBracket+1,CBracket)).substring(s-2,s),16);
loop++; s--; } } } } switch(Key) { case 0: //System.out.println("TIR & TrailerBitInstVal "); TIR = (byte)myKey; TrailerBitInstVal = myAdd; break; case 1: //System.out.println("HIR & HeaderBitInstVal "); HIR = (byte)myKey; HeaderBitInstVal = myAdd; break; case 2: //System.out.println("TDR & TrailerBitDatVal "); TDR = (byte)myKey; TrailerBitDatVal = myAdd; break; case 3: //System.out.println("HDR & HeaderBitDatVal "); HDR = (byte)myKey; HeaderBitDatVal = myAdd; break; case 4: case 5: Size = myKey; break; default: System.out.println("Invalid opcode."); return 0; } return 1; } public static void main(String[] args) { // The key words of the SVF file include: // TRST OFF: Ignore // ENDIR IDLE: Ignore // ENDDR IDLE: Ignore // STATE RESET IDLE: Ignore // TIR 5 TDI (1f): Key word = 0, length, pin, value(Instruction // trailer) // HIR 5 TDI (1f): Key word = 1, length, pin, value(Instruction // header) // TDR 5 TDI (00): Key word = 2, length, pin, value(Data trailer) // HDR 5 TDI (00): Key word = 3, length, pin, value(Data header) // SIR 13 TDI (1fff)): Key word = 4, length, pin, // value(Instruction) // SDR 32 TDI (00000000)): Key word = 5, length, pin, value(Data) // RUNTEST 110000 TCK: Key word = 0, clock pulse, pin (Run clock) /* // Command send format for Instruction. myJtag.sendNrcv(Data,Offset,Size,(byte)NumberOfBits,State,Update, (byte)HIR,(byte)HeaderBitInstVal,(byte)TIR,(byte)TrailerBitInstVal); // Command send format for Data myJtag.sendNrcv(Data,Offset,Size,(byte)NumberOfBits,State,Update, (byte)HDR,(byte)HeaderBitDatVal,(byte)TDR,(byte)TrailerBitDatVal); */ myJtag = new jtag(); if(args.length != 0) { for (int x = 0; x < args.length ; x++) { mySVF = new File(args[x]); if (mySVF.exists()) { if (mySVF.canRead()) { try { SVFFile= new RandomAccessFile(mySVF.getName(), "r"); // Process one line at a time and set all variables while((line = SVFFile.readLine()) != null) { System.out.println(line); if(line.regionMatches(false,0,"TIR",0,3)) Key = 0; else if(line.regionMatches(false,0,"HIR",0,3)) Key = 1; else if(line.regionMatches(false,0,"TDR",0,3)) Key = 2; else if(line.regionMatches(false,0,"HDR",0,3)) Key = 3; else if(line.regionMatches(false,0,"SIR",0,3)) Key = 4; else if(line.regionMatches(false,0,"SDR",0,3)) Key = 5; else if(line.regionMatches(false,0,"RUNTEST",0,7)) Key = 6; else if(line.regionMatches(false,0,"STATE",0,5)) Key = 7; else { Key = 8; //System.out.println(line); } switch(Key) { case 0: // TIR if (ProcessSVFLine()==0) System.out.println("Fail to fetch TIR and TrailerBitInstVal."); break; case 1: // HIR if (ProcessSVFLine()==0) System.out.println("Fail to fetch HIR and HeaderBitInstVal."); break; case 2: // TDR if (ProcessSVFLine()==0) System.out.println("Fail to fetch TDR and TrailerBitDatVal."); break; case 3: // HDR if (ProcessSVFLine()==0) System.out.println("Fail to fetch THR and HeaderBitDatVal."); break; case 4: // SIR State = true; if (ProcessSVFLine()==1) myJtag.sendNrcv(myData,Offset,Size,(byte)NumberOfBits,State,Update, (byte)HIR,(byte)HeaderBitInstVal,(byte)TIR,(byte)TrailerBitInstVal); else System.out.println("Fail to process ProcessSVFLine."); break; case 5: // SDR State = false; if (ProcessSVFLine()==1) { // Users need to retrieve read data from byte array if needed. myJtag.sendNrcv(myData,Offset,Size,(byte)NumberOfBits,State,Update, (byte)HDR,(byte)HeaderBitDatVal,(byte)TDR,(byte)TrailerBitDatVal); } else System.out.println("Fail to process ProcessSVFLine."); break; case 6: System.out.println("Run clock"); Size = Integer.parseInt(line.substring
(line.indexOf(' ')+1,line.indexOf(' ',line.indexOf(' ')+1))) ; myJtag.waitState((Size/1000)+1); break; case 7: System.out.println("Initialize TAP controller."); myJtag.initialize(); myJtag.initialize(); myJtag.initialize(); break; default:System.out.println("Ignore key word."); break; } } } catch(IOException a) { System.out.println("Cannot create random file "+ a); } } else System.out.println(args[x]+" file cannot be read"); } else System.out.println(args[x]+" file does not exist"); } // Process SVF file } else System.out.println("SVF file is not specified in parameter"); } }

付録C
SVFサンプルファイルを拡張して、チェーン接続のデバイスを取り扱う方法

付録AとBは、スタンドアロンまたは単一デバイスを取り扱う方法を示したものです。実際の現場では、チェーン接続した多くのXilinx社製デバイスを取り扱う必要があります。例えば、以下に示すような直列に接続されたXilinx社製デバイスのチェーンがあります。

図3.
図3.

チェーン内のデバイスBを取り扱うには、以下の手順に従ってください。
手順1:前述のとおり、単一デバイスBのSVFファイルを生成します。
手順2:チェーン内の他のすべてのデバイスのためのBSDLファイルから、Instruction Length AttributeやInstruction Opcode AttributeなどのXilinx社製デバイスのためのデータを収集します。詳細については、ウェブサイトhttps://www.xilinx.com/support/documentation/application_notes/xapp503.pdfを参照してください。
手順3:TIR、HIR、TDR、およびHDRの値を適宜修正するためにSVFファイルを編集します。ここでは、デバイスAのIR長は5ビット、デバイスBのIR長は6ビット、およびデバイスCのIR長は7ビットと仮定しています。デバイスBを取り扱う場合は、SVFファイルのTIR、HIR、TDR、およびHDRの値を以下に示すように置き換える必要があります。

TIR 5 TDI (1f) SMASK (1f) ;
HIR 7 TDI (7f) SMASK (7f) ;
HDR 1 TDI (00) SMASK (01) ;
TDR 1 TDI (00) SMASK (01) ;
The same procedures to work with device A with step 3:
TIR 0 ;
HIR 13 TDI (1fff) SMASK (1fff) ;
HDR 2 TDI (00) SMASK (02) ;
TDR 0 ; 
The same procedures to work with device C with step 3:
TIR 11 TDI (7ff) SMASK (7ff) ;
HIR 0 ;
HDR 0 ;
TDR 2 TDI (00) SMASK (02) ;