CPLD或者FPGA开发工具会生成SVF文件用以通过JTAG口配置CPLD或者FPGA。这里有些基本控制JTAG状态机的指令,其实就是主要两条SIR和SDR分别实现对IR寄存器和DR寄存器的写。
这样我们的这个下载器的基本工作变成了解析SVF文件之后对JTAG的TAP状态机进行操作实现对IR和DR的读写(其中IR仅写)。
关于JTAG的TAP状态机,在【注释1】这里有详细的介绍,我就是通过这个网站入门JTAG并在2010年做出了龙芯仿真用的EJTAG。
这里JTAG就是通过TMS控制各种状态的转换,通过TDI传递数据给IR或者DR,通过TDO收取到DR的数据。
上面这个状态机注意从SHIFT_IR到EXIT1_IR时候给出的TMS=1是跟随这TDI的最后一个BIT一起给出的。同样从SHIFT_DR到EXIT1_DR也是如此。
有了上面状态机我们就是实现用四根信号线TDI TDO TMS TCK来实现TAP状态机的转换。这四根线我们暂且不考虑速度,可以是四根并口线,其中TDI,TMS,TCK是控制器输出给CPLD或者FPGA的JTAG接口线,TDO是CPLD或者FPGA输出给控制器的数据线。
在上述的网站里面用了并口实现这四根信号线,我们电脑没有并口了,可以考虑用USB转串口之后用一个单片机或者可编程逻辑转成并口。手里现成的硬件就是ZC706,ZC706上有USB转串口,也有多个PMOD可以接出来四根信号线接JTAG。如下图:
ZC706的逻辑根串口的上位机简单做个通讯协议就可以实现并口输出的效果。这样我们剩下的问题就是解析SVF文件以及实现JTAG状态机转换的问题。
解析SVF文件比较简单,就是对字符的处理。下图就是部分SVF文件截图
我们看到SIR 10 TDI (203)的意思就是通过TDI写10BIT的数据0X203到IR寄存器。
SDR 32 TDI (E7FFFFFF)的意思就是通过TDI写32BIT的数据0XE7FFFFFF到DR寄存器。
RUNTEST 3200 TCK 是说等待3200个TCK时钟的时间。其中指令的周期由文件开头的FREQUENCY指定,一般为10M的样子。当然我们实际TCK没有那么快,执行RUNTEST时候只需要等待对应的时间(而不是TCK的数量)就可以。
实现JTAG转换也是比较简单,可以直接使用【注释1】网站的部分转换代码,我在接下来的步骤中详细分解。
注释
1:fpga4fun.com - JTAG 2 - How JTAG works