1. ICL 和 PDL的作用
2. ICL语法
2.1 模块定义语法 (Module Definition)
模块是 ICL 的基本单元,使用 Module 关键字定义,内部逻辑和端口声明包裹在大括号 {} 中。
Module <模块名称> {
// 端口声明、寄存器定义、实例化等
}
2.2 端口声明语法 (Port Declarations)
端口决定了模块如何与外部通信。ICL 提供了丰富的端口类型关键字,部分端口需要通过 {} 指定其内部信号源(Source)。
(1)扫描端口:
ScanInPort <名称>; (数据流入)
ScanOutPort <名称> { Source <内部信号> }; // 数据流出,必须指定 Source
(2)Host端口:
ToShiftEnPort <名称>; // 声明一个主机移位使能端口,用于使能下游模块中 ScanRegister 元素的移位操作。
ToUpdateEnPort <名称>; // 声明一个主机更新使能端口,用于控制下游模块 ScanRegister 的更新操作。
ToCaptureEnPort <名称>; // 声明一个主机捕获使能端口,用于触发下游模块的数据捕获。
ToSelectPort <名称>; // 声明一个主机选择使能端口,用于向下游仪器发送选择信号(例如 SIB 模块通常会使用此端口来控制其下游分支是否接入扫描链)。
(3)控制端口:
ShiftEnPort <名称>; // client端口,它需要接收来自外部的移位使能信号
UpdateEnPort <名称>; // client端口,它需要接收来自外部的更新使能信号
CaptureEnPort <名称>; // client端口,它需要接收来自外部的捕获使能信号
TCKPort <名称>;
TMSPort <名称>;
ResetPort <名称>;
(4)数据端口:
DataInPort <名称>[位宽];
DataOutPort <名称> { Source <内部信号> };
2.3 扫描寄存器与多路选择器语法 (Registers & Mux)
这是 ICL 中描述扫描链内部结构的核心语法。
(1)ScanRegister (扫描寄存器):
ScanRegister <寄存器名>[位宽] {
ScanInSource <输入信号>; // 移位时的数据来源
CaptureSource <捕获信号>; // 捕获阶段的数据来源
ResetValue <复位值>; // 可选,复位时的默认值
}
(2)ScanMux (扫描多路选择器):
通常与 SIB (Segment Insertion Bit) 配合使用,用于动态切换扫描链路径。
ScanMux <多路器名称> SelectedBy <控制寄存器> {
<选择值1> : <输入端口1>;
<选择值2> : <输入端口2>;
}
2.4 实例化与连接语法 (Instantiation & Connections)
在顶层模块(如 chip)中,通过 Instance 关键字调用底层模块,并使用 InputPort 完成信号绑定。
Instance <实例名称> of <模块名称> {
InputPort <目标端口> = <源信号或上级端口>;
InputPort <目标端口> = <源信号或上级端口>;
}
2.5 常量与位宽表示法
- 位宽定义:使用方括号表示,如 [3:0] 表示 4 位宽。
- 常量表示:采用 <位宽>'<进制><值> 的格式,例如 1'b0(1位二进制0),1'b1(1位二进制1)。
2.6 语法规范与注意事项
- 大小写敏感:ICL 是严格区分大小写的语言。例如,关键字必须大写(如 ScanInPort),而用户自定义的名称(如 tdi, Sensor_1)通常遵循小写或驼峰命名法。
- 分号结尾:每一条端口声明、寄存器定义和实例化连接语句都必须以分号 ; 结尾。
- 注释:支持使用 // 进行单行注释,这在编写复杂的顶层连接时非常有助于提高代码可读性。
掌握上述语法结构后,您就可以像搭积木一样,通过组合 Module、ScanRegister、ScanMux 和 Instance,构建出任意复杂的 IJTAG 测试网络拓扑。
3. PDL语法
4. 举例
注:本例转自8. IJTAG:芯片测试的超级英雄 半导体领域的小伙伴们,今天我们来聊聊一个可能并不广为人知,但绝对是幕后英雄的技术——IJTAG。别担心,虽然这听起来有点... - 雪球
4.1 电路结构
实例讲解:温度传感器的ICL和PDL描述
让我们通过一个温度传感器的实例,来看看ICL和PDL的实际应用。

图1 温度传感器的电路结构
4.2 ICL
对应的ICL如下:
// 基础仪器定义 (Sensor)
Module Sensor {
DataInPort En;
DataOutPort Temp[3:0];
}
// 定义了一个名为 Sensor 的普通功能模块(非测试模块)。
// 它有两个接口:一个输入使能信号 En,和一个4位的温度数据输出 Temp。
// 测试数据寄存器 (TDR)
Module TDR {
ScanInPort si;
ScanOutPort so { Source EN_reg };
ShiftEnPort se;
UpdateEnPort ue;
DataInPort Temp[3:0];
DataOutPort En { Source EN_Reg };
ScanRegister SR[3:0] {
ScanInSource si;
CaptureSource Temp;
}
ScanRegister EN_reg {
ScanInSource SR[0];
}
}
// 这是用于控制 Sensor 的测试逻辑封装。
// SR[3:0]:一个4位的扫描寄存器。
// 在 Shift 阶段,数据从 si 移入;
// 在 Capture 阶段,它会捕获外部传感器传来的 Temp 数据。
// EN_reg:一个1位的扫描寄存器,用于控制传感器的使能。
// 它的移位输入来源于 SR 的最低位 SR[0]。
// 数据流向:扫描链的输出 so 取自 EN_reg;
// 同时,EN_reg 的值通过 DataOutPort En 输出给外部的 Sensor 模块作为使能信号。
// 段互连位 / 扫描链开关 (SIB)
Module SIB {
ScanInPort si;
ScanInPort fso;
ScanOutPort so { Source sib };
ScanOutPort tsi { Source si };
ShiftEnPort se;
UpdateEnPort ue;
ScanRegister sib {
ScanInSource mux;
CaptureSource 1'b0;
ResetValue 1'b0;
}
ScanMux mux SelectedBy sib {
1'b0 : si;
1'b1 : fso;
}
}
// SIB 相当于测试网络中的“可编程交换机”,用于动态决定测试数据的路径。
// sib 寄存器:控制位,复位默认为0。
// ScanMux (多路选择器):由 sib 寄存器控制。
// 当 sib = 0 时,选择 si(输入端口),此时 SIB 处于旁路状态,数据直接穿透。
// 当 sib = 1 时,选择 fso(来自下游仪器的反馈扫描输出),此时 SIB 将下游的测试仪器接入扫描链。
// tsi:提供了一个直通的扫描输出端口,始终输出 si 的值,通常用于级联其他不需要被 SIB 旁路的设备。
// 测试访问端口 (TAP)
Module TAP {
TCKPort tck;
TMSPort tms;
ScanInport tdi;
ScanOutPort tdo;
ToShiftEnPort shift_en;
ToUpdateEnPort update_en;
ToCaptureEnPort capture_en;
}
// 符合 JTAG 标准的 TAP 控制器。
// 除了基本的 tck, tms, tdi, tdo 外,它还向外提供全局的测试控制信号(移位、更新、捕获使能),用于驱动整个 IJTAG 网络。
// 顶层网络拓扑 (chip)
Module chip {
TCKPort TCK;
TMSPort TMS;
ScanInPort TDI;
ScanOutPort TDO;
Instance TAP_inst of TAP {
InputPort tck = TCK;
InputPort tms = TMS;
InputPort tdi = TDI;
InputPort sib_tdo = SIB_2.so;
}
Instance SIB_1 of SIB {
InputPort si = TAP_inst.to_si;
InputPort fso = TDR_1.so;
}
Instance SIB_2 of SIB {
InputPort si = SIB_1.so;
InputPort fso = TDR_2.so;
}
Instance TDR_1 of TDR {
InputPort si = SIB_1.tsi;
InputPort Temp = Sensor_1.Temp;
}
Instance TDR_2 of TDR {
InputPort si = SIB_2.tsi;
InputPort Temp = Sensor_2.Temp;
}
Instance Sensor_1 of Sensor {
InputPort En = TDR_1.En;
}
Instance Sensor_2 of Sensor {
InputPort En = TDR_2.En;
}
}
// 这部分定义了芯片内部测试仪器的物理连接关系:
// 主干扫描链:TAP_inst -> SIB_1 -> SIB_2 -> 回到 TAP_inst.sib_tdo。
// 分支 1:SIB_1 的直通端口 tsi 连接到 TDR_1 的 si。当 SIB_1 被激活(置1)时,TDR_1 及其控制的 Sensor_1 被接入扫描链。
// 分支 2:SIB_2 的直通端口 tsi 连接到 TDR_2 的 si。当 SIB_2 被激活(置1)时,TDR_2 及其控制的 Sensor_2 被接入扫描链。