In my previous blog. IEEE 1687 (IJTAG): ICL and PDL Explained, I provided a laymanโs introduction to the Instrument Connectivity Language (ICL) and Procedural Description Language (PDL). As you may have gleaned from this article, ICL in particular is a complex language; its basic function is to describe the access network between embedded instruments and device interfaces. In this article, Iโll describe how an ICL network and instrumentation is created and inserted within a test FPGA, thereby giving more insight into the languageโs constructs and the principles of IJTAG.
With our ScanWorks product, we demonstrate the use of IJTAG with a simple Project that we described in the previous article, using the Opal Kelly board. This ScanWorks Project stores (1) the board topology (that is, understands the layout of the Scan Path and the boundary scan attributes of the Xilinx Spartan-6 FPGA), (2) the SVF that programs and initializes the IJTAG network and the simple register/instrument that controls an LED, and (3) the ScanWorks Actions (vectors) used to run the PDL against the specific instrument.
The three ScanWorks Actions associated with our demonstration Project can be seen below:
Action #1 above shows the Scan Path Verify (SPV). This Action is typically included in all Projects, as itโs the first action to run to verify scan chain integrity.
Action #2 above is used to insert the IJTAG network into the Spartan-6 FPGA.
And Action #3 above uses ICL and PDL to generate test actions using specific IJTAG iProcs against the instrumentโs fully qualified network path. This is sometimes called retargeting, whereby a sequence of operations written in PDL are applied at the instrument boundary and mapped through the instrument access network to a higher level of hierarchy (and ultimately to the ports of the top-level module that connects to the Spartan-6โs pins).
What does the overall flow of creating these Actions and using them within ScanWorks look like? Hereโs a visual of the flow, and Iโll describe the necessary steps:
The first two steps, reading the Spartan-6 FPGAโs BSDL into ScanWorks and describing the board scan path, are standard steps that are done for all JTAG and boundary scan related projects.
Note the third step, โRun ETG to generate Verilog and ICLโ. ETG is short for Embedded Tester Generator, an application within ScanWorks that is used to create and install embedded instruments and provide access to them via an on-chip IJTAG network. For this example single-instrument Project, we are using a very simple instrument that is manifested by a single boundary scan cell. We need to do only two things: (1) configure the instrument based upon its defined attributes, and (2) associate the instrument with a pin map on the board. In terms of configuring the instrument, we are just defining an OUTPUT2 boundary scan cell โ that is, the simplest 2-state output cell, since we will just be using it to turn the associated LED on and off:
And regarding the pin, we know from the schematics of the Opal Kelly board that pin K2 is the one weโll be using to light up its associated LED, so we set that up as well, calling its port LD0 (for later use in the ICL and PDL), and its I/O Type is known to be LVCMOS33:
Once this is done, we run ETG, that outputs the associated ICL and Verilog for the network and instrument. The Verilog RTL is below:
module LD_1Bit_Instr_1__Wrapper #( ย parameterย ย ย ย ย ย ย ย ย ย ย OUTPUT2 = 0 )( ย inputย wireย ย ย ย ย ย ย ย ย ckDR, ย inputย wireย ย ย ย ย ย ย ย ย ON, ย inputย wireย ย ย ย ย ย ย ย ย shDR, ย inputย wireย ย ย ย ย ย ย ย ย TCK, ย inputย wireย ย ย ย ย ย ย ย ย TCK_B, ย inputย wireย ย ย ย ย ย ย ย ย TDI, ย inputย wireย ย ย ย ย ย ย ย ย TRST_B, ย inputย wireย ย ย ย ย ย ย ย ย upDR, ย output wireย ย ย ย ย ย ย ย ย LD0, ย output wireย ย ย ย ย ย ย ย ย TDO ); ย // Wrap Input Wires ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย xi_LD0; ย // Instrument Type Specific Wires ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย TDO_ctrl; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย TDO_read; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย TDO_RW_mux; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย TDO_sib; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย TDO_write; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย WS_SEL; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย WS_SEL_ON; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย WSIo; ย my_and2 WS_SEL_enable ( .I0(ON), .I1(WS_SEL), .O(WS_SEL_ON) ); ย sync_TypeSIB_1bit SIB ย ( ย ย ย .ckDR(ckDR), ย ย ย .ON(ON), ย ย ย .shDR(shDR), ย ย ย .TCK(TCK), ย ย ย .TCK_B(TCK_B), ย ย ย .TDI(TDI), ย ย ย .TDO(TDO_sib), ย ย ย .TRST_B(TRST_B), ย ย ย .upDR(upDR), ย ย ย .WSIo(WSIo), ย ย ย .WSOi(TDO_write), ย ย ย .WS_SEL(WS_SEL) ย ); // SIB ย sync_TypeW_1bit Write_Data ย ( ย ย ย .ckDR(ckDR), ย ย ย .NDO(xi_LD0), ย ย ย .ON(WS_SEL_ON), ย ย ย .shDR(shDR), ย ย ย .TCK(TCK), ย ย ย .TCK_B(TCK_B), ย ย ย .TDI(WSIo), ย ย ย .TDO(TDO_write), ย ย ย .TRST_B(TRST_B), ย ย ย .upDR(upDR) ย ); // Write_Data ย my_buf TDO_buf ( .I(TDO_sib), .O(TDO) ); ย BST_IO_LD_1Bit_Instr_1 ย #( ย ย ย .OUTPUT2(OUTPUT2) ย ) ย LD_1Bit_Instr_1 ย ( ย ย ย .LD0(LD0), ย ย ย .xi_LD0(xi_LD0) ย ); // LD_1Bit_Instr_1 endmodule // LD_1Bit_Instr_1__Wrapper module sync_TypeSIB_1bit ( ย // An IJTAG Segment Insertion Bit test data register that responds to the Synchronous JTAG signals ย inputย wireย ย ย ย ย ย ย ย ON, ย inputย wireย ย ย ย ย ย ย ย TDI, ย inputย wire ย ย ย ย ย ย ย ย WSOi, ย inputย wireย ย ย ย ย ย ย ย TCK, ย inputย wireย ย ย ย ย ย ย ย TCK_B, ย inputย wireย ย ย ย ย ย ย ย TRST_B, ย inputย wireย ย ย ย ย ย ย ย shDR, ย inputย wireย ย ย ย ย ย ย ย ckDR, ย inputย wireย ย ย ย ย ย ย ย upDR, ย output wireย ย ย ย ย ย ย ย TDO, ย output wireย ย ย ย ย ย ย ย WS_SEL, ย output wireย ย ย ย ย ย ย ย WSIo ); ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย i_shDR; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย i_ckDR; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย i_upDR; ย my_and2 shDR_enable ( .I0(ON), .I1(shDR), .O(i_shDR) ); ย my_and2 ckDR_enable ( .I0(ON), .I1(ckDR), .O(i_ckDR) ); ย my_and2 upDR_enable ( .I0(ON), .I1(upDR), .O(i_upDR) ); ย sib_cell bit_0 ( .WS_SEL(WS_SEL), .WSIo(WSIo), .WSOi(WSOi), .TDO(TDO), .TDI(TDI), .TCK(TCK), .TCK_B(TCK_B), .TRST_B(TRST_B), .shDR(i_shDR), .ckDR(i_ckDR), .upDR(i_upDR) ); endmodule // sync_TypeSIB_1bit module sync_TypeW_1bit ( ย // An IJTAG Shift-Update test data register that responds to the Synchronous JTAG signals ย inputย wireย ย ย ย ย ย ย ย ON, ย inputย wireย ย ย ย ย ย ย ย TDI, ย inputย wireย ย ย ย ย ย ย ย TCK, ย inputย wireย ย ย ย ย ย ย ย TCK_B, ย inputย wireย ย ย ย ย ย ย ย TRST_B, ย inputย wireย ย ย ย ย ย ย ย shDR, ย inputย wireย ย ย ย ย ย ย ย ckDR, ย inputย wireย ย ย ย ย ย ย ย upDR, ย output wireย ย ย ย ย ย ย ย TDO, ย output wireย ย ย ย ย ย ย ย NDO ); ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย i_shDR; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย i_ckDR; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย i_upDR; ย my_and2 shDR_enable ( .I0(ON), .I1(shDR), .O(i_shDR) ); ย my_and2 ckDR_enable ( .I0(ON), .I1(ckDR), .O(i_ckDR) ); ย my_and2 upDR_enable ( .I0(ON), .I1(upDR), .O(i_upDR) ); ย sub_cell bit_0 (.TCK(TCK), .TCK_B(TCK_B), .TRST_B(TRST_B), .shDR(i_shDR), .ckDR(i_ckDR), .upDR(i_upDR), .NDO(NDO), .TDI(TDI), .TDO(TDO) ); endmodule // sync_TypeW_1bit module IJTAG_Network ( ย inputย wireย ย ย ย ย ย ย ย ย ckDR, ย inputย wireย ย ย ย ย ย ย ย ย ON, ย inputย wireย ย ย ย ย ย ย ย ย shDR, ย inputย wireย ย ย ย ย ย ย ย ย TCK, ย inputย wireย ย ย ย ย ย ย ย ย TCK_B, ย inputย wireย ย ย ย ย ย ย ย ย TDI, ย inputย wireย ย ย ย ย ย ย ย ย TRST_B, ย inputย wireย ย ย ย ย ย ย ย ย upDR, ย output wireย ย ย ย ย ย ย ย ย LD_1Bit_Instr_1___LD0, ย output wireย ย ย ย ย ย ย ย ย TDO ); ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย WSIo; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย WSOi; ย wireย ย ย ย ย ย ย ย ย ย ย ย ย ย ย ย WS_SEL; ย LD_1Bit_Instr_1__Wrapper ย #( ย ย ย .OUTPUT2("LD0") ย ) ย LD_1Bit_Instr_1__W1 ย ( ย ย ย .LD0(LD_1Bit_Instr_1___LD0), ย ย ย .ON(WS_SEL), ย ย ย .ckDR(ckDR), ย ย ย .shDR(shDR), ย ย ย .TCK(TCK), ย ย ย .TCK_B(TCK_B), ย ย ย .TDI(WSIo), ย ย ย .TDO(WSOi), ย ย ย .TRST_B(TRST_B), ย ย ย .upDR(upDR) ย ); // LD_1Bit_Instr_1__W1 ย sync_TypeSIB_1bit SIB ย ( ย ย ย .ckDR(ckDR), ย ย ย .ON(ON), ย ย ย .shDR(shDR), ย ย ย .TCK(TCK), ย ย ย .TCK_B(TCK_B), ย ย ย .TDI(TDI), ย ย ย .TDO(TDO), ย ย ย .TRST_B(TRST_B), ย ย ย .upDR(upDR), ย ย ย .WSIo(WSIo), ย ย ย .WSOi(WSOi), ย ย ย .WS_SEL(WS_SEL) ย ); // SIB endmodule // IJTAG_Network module ET_IJTAG_Demo_1Bit_ET_0 ( ย output wireย ย ย ย ย ย ย ย ย LD_1Bit_Instr_1___LD0 ); ย wireย ย ย ย ย ย ย ย tdi; ย wireย ย ย ย ย ย ย ย tdo; ย wireย ย ย ย ย ย ย ย cdr; ย wireย ย ย ย ย ย ย ย sdr; ย wireย ย ย ย ย ย ย ย udr; ย wireย ย ย ย ย ย ย ย tlr; ย wireย ย ย ย ย ย ย ย ckDR = (cdr || sdr); ย wireย ย ย ย ย ย ย ย shDR = sdr; ย wireย ย ย ย ย ย ย ย upDR = udr; ย // Xilinx BSCAN Interface specific wire declarations and signal assignments. ย wireย ย ย ย ย ย ย ย tck; ย wireย ย ย ย ย ย ย ย tck_b; ย wireย ย ย ย ย ย ย ย tms; ย wireย ย ย ย ย ย ย ย rti; ย wireย ย ย ย ย ย ย ย user_1_sel; ย wireย ย ย ย ย ย ย ย BSCAN_tck; ย BUFG BUFG_tckย ย (.O(tck),ย ย .I(BSCAN_tck)); ย BUFG BUFG_tck_b (.O(tck_b), .I(~BSCAN_tck)); ย // Xilinx BSCAN Interface instance. ย //ย ย Instantiate a "BSCAN_SPARTAN6" type JTAG interface ย BSCAN_SPARTAN6 #(.JTAG_CHAIN(1)) BSCAN_SPARTAN6_i ( ย ย ย ย ย .CAPTURE(cdr), ย ย ย ย ย .RESET(tlr), ย ย ย ย ย .RUNTEST(rti), ย ย ย ย ย .SEL(user_1_sel), ย ย ย ย ย .SHIFT(sdr), ย ย ย ย ย .TCK(BSCAN_tck), ย ย ย ย ย .TDI(tdi), ย ย ย ย ย .TMS(tms), ย ย ย ย ย .UPDATE(udr), ย ย ย ย ย .TDO(tdo) ย ); // BSCAN_SPARTAN6_i ย IJTAG_Network IJTAG_Network_1 ย ( ย ย ย .ckDR(ckDR), ย ย ย .ON(user_1_sel), ย ย ย .shDR(shDR), ย ย ย .TCK(tck), ย ย ย .TCK_B(tck_b), ย ย ย .TDI(tdi), ย ย ย .TRST_B(tlr), ย ย ย .upDR(upDR), ย ย ย .LD_1Bit_Instr_1___LD0(LD_1Bit_Instr_1___LD0), ย ย ย .TDO(tdo) ย ); // IJTAG_Network_1 endmodule // ET_IJTAG_Demo_1Bit_ET_0 module IJTAG_Demo_1Bit_ET_0 ( ย output wireย ย ย ย ย ย ย ย ย ย K2 ); ย wireย ย ย ย ย ย ย ย LD_1Bit_Instr_1___LD0; ย assign K2ย ย ย ย ย ย = ~LD_1Bit_Instr_1___LD0; ย ET_IJTAG_Demo_1Bit_ET_0 ET_IJTAG_Demo_1Bit_ET_0_i ย ( ย ย ย .LD_1Bit_Instr_1___LD0(LD_1Bit_Instr_1___LD0) ย ); // ET_IJTAG_Demo_1Bit_ET_0_i endmodule // IJTAG_Demo_1Bit_ET_0
Itโs an exercise for the student to read this Verilog and piece it together. Have fun!
The ICL is also output by ETG. The contents are displayed in the previous article as well, but Iโll list it here for completeness. Here it is:
// The Instrument to be Tested Module BST_IO_LD_1Bit_Instr_1__LD_1Bit_Instr_1 { ย ย ย DataInPort xi_LD0; ย ย ย DataOutPort LD0; } // SIB/TDR Unit: Contains an instance of the Instrument to be Tested, //ย ย the Test Data Register (TDR) associated with the Instrument, and //ย ย the SIB used to insert the TDR data into the Scan Chain. Module LD_1Bit_Instr_1__Wrapper { ย ย ย // Scan Chain associated ports ย ย ย ScanInPort TDI; ย ย ย ScanOutPort TDO { Source SIB_mux; } ย ย ย // Instrument associated port ย ย ย DataOutPort LD0 { Source LD_1Bit_Instr_1.LD0; } ย ย ย // Instance of the Instrument to be Tested ย ย ย Instance LD_1Bit_Instr_1 Of BST_IO_LD_1Bit_Instr_1__LD_1Bit_Instr_1 { ย ย ย ย ย ย ย InputPort xi_LD0 = Write_TDR[0]; ย ย ย } ย ย ย // The Test Data Register (TDR) associated with the Instrument ย ย ย ScanRegister Write_TDR[0] { ย ย ย ย ย ย ย ResetValue 1'b0; ย ย ย ย ย ย ย ScanInSource SIB; ย ย ย ย ย ย ย CaptureSource LD_1Bit_Instr_1.LD0[0]; ย ย ย } ย ย ย // The ScanRegister and ScanMux, collectively, comprise the SIB ย ย ย ย ย ย // (Segment Insertion Bit).ย When the value of SIB is '0', the ย ย ย ย ย ย // SIB is considered "closed" and the TDR data cannot be accessed. ย ย ย ย ย ย // When the SIB is '1', the SIB is considered "open" and the TDR ย ย ย ย ย ย // data is inserted into the Scan Chain. ย ย ย ย ย ย // -- The SIB bit ย ย ย ScanRegister SIB { ย ย ย ย ย ย ย ResetValue 1'b0; ย ย ย ย ย ย ย ScanInSource TDI; ย ย ย ย ย ย ย CaptureSource SIB; ย ย ย } ย ย ย // -- The SIB MUX ย ย ย ScanMux SIB_Mux SelectedBy SIB { ย ย ย ย ย ย ย 1'b0 : SIB; ย ย ย ย ย ย ย 1'b1 : Write_TDR; ย ย ย } } // This Module defines the Scan Chain which includes any module // instances that consist of Instrument TDRs and SIBs for accessing // thsoe TDRs. Module IJTAG_Network { ย ย ย // Scan Chain associated ports ย ย ย ScanInPort TDI; ย ย ย ScanOutPort TDO { Source SIB_Mux; }ย ย ย ย ย // Instrument associated port ย ย ย DataOutPort LD_1Bit_Instr_1___LD0ย ย ย ย ย { Source LD_1Bit_Instr_1__W1.LD0; } ย ย ย // The short Scan Chain network includes this instance of the module ย ย ย ย ย ย // LD_1Bit_Instr_1__Wrapper/ ย ย ย Instance LD_1Bit_Instr_1__W1 Of LD_1Bit_Instr_1__Wrapper { ย ย ย ย ย ย ย InputPort TDI = SIB; ย ย ย } ย ย ย // The ScanRegister and ScanMux, collectively, represent a top-level ย ย ย ย ย ย // SIB which, when closed ('0') hides any SIBs that come after it, ย ย ย ย ย ย // such as the one associated with LD_1Bit_Instr_1__Wrapper. ย ย ย ย ย ย // -- The SIB bit ย ย ย ScanRegister SIB { ย ย ย ย ย ย ย ResetValue 1'b0; ย ย ย ย ย ย ย ScanInSource TDI; ย ย ย ย ย ย ย CaptureSource SIB; ย ย ย } ย ย ย // -- The SIB MUX ย ย ย ScanMux SIB_Mux SelectedBy SIB { ย ย ย ย ย ย ย 1'b0 : SIB; ย ย ย ย ย ย ย 1'b1 : LD_1Bit_Instr_1__W1.TDO; ย ย ย } } Module IJTAG_Demo_1Bit_ET_0 { ย ย ย // Scan Chain associated ports ย ย ย ScanInPort BSCAN_SPARTAN6_tdi; ย ย ย ScanOutPort BSCAN_SPARTAN6_tdo { Source IJTAG_Network_1.TDO; } ย ย ย // Instrument associated port ย ย ย DataOutPort K2 { Source IJTAG_Network_1.LD_1Bit_Instr_1___LD0; } ย ย ย ย ย ย // Instance of the module IJTAG_Network which defines the ย ย ย ย ย ย // Scan Chain ย ย ย Instance IJTAG_Network_1 Of IJTAG_Network { ย ย ย ย ย ย ย InputPort TDI = BSCAN_SPARTAN6_tdi; ย ย ย } ย ย ย ย ย ย // The Scan Interface Declaration: this defines the Scan In ย ย ย ย ย ย // and Scan Out ports for accessing the Scan Chain. ย ย ย ScanInterface BSCAN_SPARTAN6_Gateway { Port BSCAN_SPARTAN6_tdi; Port BSCAN_SPARTAN6_tdo; } ย ย ย ย ย ย // The Access Link Declaration: this provides the conduit between ย ย ย ย ย ย // the Test Access Point (TAP) and the Scan Interface and ย ย ย ย ย ย // includes the Instrument Register command taken from the BSDL ย ย ย ย ย ย // file for opening the Scan Chain (in this case, "USER1" with ย ย ย ย ย ย // a value of 0b000010). ย ย ย AccessLink Tap_1149_dot_1 Of STD_1149_1_2001 { ย ย ย ย ย ย ย BSDLEntity XC6SLX9_FTG256; ย ย ย ย ย ย ย USER1 { ย ย ย ย ย ย ย ย ย ย ย ScanInterface { IJTAG_Demo_1Bit_ET_0.BSCAN_SPARTAN6_Gateway; } ย ย ย ย ย ย ย } ย ย ย } }
And now the real magic begins. We have outputted the Verilog (which is used to program the FPGA with the network and associated instrument) and the ICL (that describes the network for tools such as ScanWorks that speak ICL and PDL). We now have to use the Xilinx tool to synthesize the Verilog and output a .bit programming file, and then (optionally) do a โGenerate SVFโ to program the FPGA. In this instance, weโll take the extra step to generate the SVF, as the ScanWorks tooling can quickly program the device using this format and fast programming hardware, for an end-to-end ScanWorks flow.
ETG invokes the Xilinx ISE (as opposed to the newer Vivado or Vitis environment) tool for the Spartan-6 to do the synthesis and SVF generation, as it is an older FPGA. The beginning of the output SVF looks like this:
TRST OFF; ENDIR IDLE; ENDDR IDLE; STATE RESET; STATE IDLE; FREQUENCY 1E6 HZ; //Operation: Program -p 0 TIR 0 ; HIR 0 ; TDR 0 ; HDR 0 ; TIR 0 ; HIR 0 ; HDR 0 ; TDR 0 ; //Loading device with 'idcode' instruction. SIR 6 TDI (09) SMASK (3f) ; SDR 32 TDI (00000000) SMASK (ffffffff) TDO (f4001093) MASK (0fffffff) ; //Boundary Scan Chain Contents //Position 1: xc6slx9 TIR 0 ; HIR 0 ; TDR 0 ; HDR 0 ; TIR 0 ; HIR 0 ; TDR 0 ; HDR 0 ; TIR 0 ; HIR 0 ; HDR 0 ; TDR 0 ; //Loading device with 'idcode' instruction. SIR 6 TDI (09) ; SDR 32 TDI (00000000) TDO (f4001093) ; //Loading device with 'bypass' instruction. SIR 6 TDI (3f) ; // Loading device with a `jprogram` instruction. SIR 6 TDI (0b) ; // Loading device with a `cfg_in` instruction. SIR 6 TDI (05) ; RUNTEST 10000 TCK; STATE RESET; // Loading device with a `cfg_in` instruction. SIR 6 TDI (05) ; SDR 32 TDI (00000000) SMASK (ffffffff) ; SIR 6 TDI (05) TDO (00) MASK (00) ; SDR 2724896 TDI (00040004000400040004000400040004000400040004โฆโฆโฆโฆโฆ.
The remainder of the SVF is just a long continuation of the ScanDR (SDR) instruction scan bytes. This part is truly โmagicโ; I will describe its intrinsics in a future blog post, when I learn a little more about how we go from Verilog to .bit to SVF. Truly, though, Iโve been told that few humans can read the SVF that provisions an FPGA.
So, now we have it all! The SVF is used to program the device, and the ICL can be parsed by ScanWorks so that the internal IJTAG network/instrument connectivity structure is known. From the previous article, we just manually created a simple PDL with write and read functions to the register that turns the LED on and off and reads the value of the register. For the sake of completeness again, below is the PDL:
iProcsForModule BST_IO_LD_1Bit_Instr_1__LD_1Bit_Instr_1 iProc write_input { DATA } { ย ย ย iWrite xi_LD0 $DATA ; ย ย ย iApply; ย ย ย ย ย ย iRunLoop -time 2000; } iProc read_output { EXP } { ย ย ย iRead LD0 $EXP ; ย ย ย iApply; ย ย ย puts $EXP } iProc puts_read_output { EXP } { ย ย ย iRead LD0 $EXP ; ย ย ย iApply; ย ย ย set output [iGetReadValue LD0] ; ย ย ย set expected 0b$EXP ; ย ย ย if { $output != $expected } { ย ย ย ย ย ย ย iSetFail "iSetFail: Failing action since actual does not match expected" ; ย ย ย ย ย ย ย iNote -comment "*** LD0: Expected = $expected, Actual = $output ***" ; ย ย ย } }
And thatโs it. I hope that this has been a helpful primer on how to create and insert a simple IJTAG network and instrument within an FPGA. The steps to do so with an ASIC are of course much more complex, and the tooling much more expensive. But, with the above, and my previous blog,ย you should get a basic understanding of the fundamentals of IEEE 1687 and its use.
If youโd like to know more, the third edition of our IJTAG Tutorial has a much broader coverage of IEEE 1687 and its applications. Feel free to click on this tutorial and register for the eBook download.