项目日志4——AD调试(Virtual JTAG)
0赞接着上一篇博文里提到了基于Quartus II的一 些在线调试方法,这一篇博文里将介绍基于Virtual JTAG的调试方法。对于Virtual JTAG,特权同学也很陌生,在这之前只记得riple兄的博客公告 里有一句“Virtual JTAG是一个非常实用的工具,希望更多的朋友把它用起来”。一直以来对tcl不是很熟悉(找了不少资料,但是一直没好好静下心来学习),对Virtual JTAG也不是很熟悉。不过借着这次机会,特权同学好好感受了回Virtual JTAG的很好很强大。
关于Virtual JTAG的资料,特权同学主要还是参考了官方的一些文档:
ug_virtualjtag.pdf【Virtual JTAG Megafunction User Guide】
AN 39_ IEEE 1149.1 (JTAG) Boundary-Scan Testing in Altera Devices (PDF) .pdf
当然,英文看得一头雾水找不到眉目的时候,google一下,最终 还是riple兄的数篇关于Virtual JTAG的 文章(http://blog.chinaaet.com/detail/3989.html)帮了我很大忙。这里要表示感谢,因为在网络上有很多很多像riple兄这样无私的人,才让我们的学习变得简单了。
这个Virtual JTAG确 实也不算什么新奇玩意,可以简单的理解,它和特权同学项目日志2里提到的利用串口来调试 的方法思路是一致的。只不过相对于使用Altera支持Virtual JTAG器 件的用户来说,如果掌握了这个调试方法,可以省却很多时间和精力(当然也包括额外调试用外设的考虑)。从硬件框图上来理解这个东西,可以如图1所示。和PC机连接只有使用现有的FPGA的JTAG端口,不需要任何额外的电路,这就是它最大的优势。另外,在我们原有的工程中例化一个Virtual JTAG的IP核,利用这个IP核给出的接口来传输数 据即可。用户要做的主要任务就是设计符合传输协议的逻辑,适时的将数据接收进来或者传输出去。这一点上和之前提到的串口方法类似。但是,在PC端,用户就可以利用Quartus II提供 的tcl支持来定制化自己需要的处理方式。
图1
看起来也是蛮简单的东西,不过由于对tcl不熟悉,特权同学 也是琢磨了两天才搞定一个基本的数据传输。下面将做一点简单的介绍,希望后来者能够少走弯路,快速上手。
1、 在MegaWizard中定义一个Virtual JTGA, 然后在工程中进行例化。
2、 在工程中设 计专门针对Virtual JTGA接口控制的逻辑,该实例中只是要输出一个8位的寄存器adc_din,只要上位机发送2’b11的地址,我们就 要把该数据逐位传送出去。其基本代码如下:
module debug_ctrl(
clk,rst_n,
adc_din//,source_sig
);
input clk; //25MHz
input rst_n; //低电平复位信号
input[7:0] adc_din;//模数转换数据寄存器0-256
reg tdo_r; //输出数据TDO
wire[1:0] ir_in; //输入IR数据
wire tck_in; //输入时钟TCK
wire tdi_in; //输入数据TDI
wire vs_cdr_in; //Virtual Capture DR
wire vs_cir_in; //Virtual Capture IR
wire vs_e1dr_in; //Virtual Exit1 DR
wire vs_e2dr_in; //Virtual Exit2 DR
wire vs_pdr_in; //Virtual Pause DR
wire vs_sdr_in; //Virtual Shift DR
wire vs_udr_in; //Virtual Update DR
wire vs_uir_in; //Virtual Update IR
vir_jtag vir_jtag_inst (
.ir_out ( ir_out_r ),
.tdo ( tdo_r ),
.ir_in ( ir_in ),
.tck ( tck_in ),
.tdi ( tdi_in ),
.virtual_state_cdr ( vs_cdr_in ),
.virtual_state_cir ( vs_cir_in ),
.virtual_state_e1dr ( vs_e1dr_in ),
.virtual_state_e2dr ( vs_e2dr_in ),
.virtual_state_pdr ( vs_pdr_in ),
.virtual_state_sdr ( vs_sdr_in ),
.virtual_state_udr ( vs_udr_in ),
.virtual_state_uir ( vs_uir_in )
);
wire cmd_dout = (ir_in[0] & ir_in[1]); //ir==2'b11
reg[7:0] tdo_db; //tdo输出缓存寄存器
reg bypass_reg; //旁路寄存器,没有针对这个virtual_jtag的 操作就旁路
always @(posedge tck_in)
if(vs_cdr_in && cmd_dout) tdo_db <= adc_din;
else if(vs_sdr_in && cmd_dout) tdo_db <= {tdi_in,tdo_db[7:1]}; //移位输出操作
always @ (posedge tck_in) begin
bypass_reg = tdi_in;
end
always @(vs_sdr_in or tdo_db or bypass_reg)//数据输出
if(vs_sdr_in) tdo_r <= tdo_db[0];
else tdo_r <= bypass_reg;
endmodule
对于上述代码,其实要使用的Virtual JTGA接 口并不多。尤其需要注意的是数据的输出tdo_r,特权同学在这上面吃了不少苦,参考了不少代码才发现其中的玄机。也就是说tdo_r在没有有效输出数据可传送的时候,需要回送打了一拍的由tdi发送过来的数据。
3、 编译工程, 下载代码。
4、 写一段tcl脚本,在Quartus II的tcl console上运行,主要是发一个获取FPGA中数据的命令。其 脚本如下:
# List all available programming hardwares, and select the USBBlaster.
# (Note: this example assumes only one USBBlaster connected.)
puts "Programming Hardwares:"
foreach hardware_name [get_hardware_names] {
puts $hardware_name
if { [string match "ByteBlasterII*" $hardware_name] } {
set ByteBlasterII_name $hardware_name
}
}
puts "\nSelect JTAG chain connected to $ByteBlasterII_name.\n";
# List all devices on the chain, and select the first device on the chain.
puts "\nDevices on the JTAG chain:"
foreach device_name [get_device_names -hardware_name $ByteBlasterII_name] {
puts $device_name
if { [string match "@1*" $device_name] } {
set test_device $device_name
}
}
puts "\nSelect device: $test_device.\n";
# Open device
open_device -hardware_name $ByteBlasterII_name -device_name $test_device
# The follow virtual JTAG IR and DR shift sequence engage with
# the example virtual JTAG instance.
#
# Two instructions: SAMPLE (1) FEED (2)
# SAMPLE instruction samples a 8-bit bus; the captured value shows the
# number of sample performed.
# FEED instruction supplies a 8-bit value to the logic connected to this
# instance.
# Both data registers corresponding to the IR are 8 bit wide.
# Send SAMPLE instruction to IR, read captured IR for the sampling
# number.
# Capture the DR register for the current sampled value.
device_lock -timeout 10000
puts "Current LED Value (sample #[device_virtual_ir_shift -instance_index \
0 -ir_value 3]): \
[device_virtual_dr_shift -instance_index 0 -length 8 -value_in_hex]"
device_unlock
# Send FEED instruction to IR, read a two-digit hex string from the
# console,
# then send the new value to the DR register.
# puts "\nType in 2 digits in hexadecimal to update the LED:"
# gets stdin update_value
# device_lock -timeout 10000
# device_virtual_ir_shift -instance_index 0 -ir_value 3 \
# -no_captured_ir_value
# device_virtual_dr_shift -instance_index 0 -length 8 -dr_value \
# $update_value -value_in_hex -no_captured_dr_value
# device_unlock
# Close device
close_device
这段代码也是根据官方的一个实例改写,详细的说明还请大家参考riple兄的文章。
5、 将该tcl脚本文件保存在工程目录下,然后在tcl console中 输入:
quartus_stp -t a.tcl
得到了 返回的数据:
Info: *******************************************************************
Info: Running Quartus II SignalTap II
Info: Version 9.1 Build 222 10/21/2009 SJ Web Edition
Info: Copyright (C) 1991-2009 Altera Corporation. All rights reserved.
Info: Your use of Altera Corporation's design tools, logic functions
Info: and other software and tools, and its AMPP partner logic
Info: functions, and any output files from any of the foregoing
Info: (including device programming or simulation files), and any
Info: associated documentation or information are expressly subject
Info: to the terms and conditions of the Altera Program License
Info: Subscription Agreement, Altera MegaCore Function License
Info: Agreement, or other applicable license agreement, including,
Info: without limitation, that your use is for the sole purpose of
Info: programming logic devices manufactured by Altera and sold by
Info: Altera or its authorized distributors. Please refer to the
Info: applicable agreement for further details.
Info: Processing started: Sun Feb 28 16:28:53 2010
Info: Command: quartus_stp -t a.tcl
Programming Hardwares:
ByteBlasterII [LPT1]
Select JTAG chain connected to ByteBlasterII [LPT1].
Devices on the JTAG chain:
@1: EP2C8 (0x020B20DD)
Select device: @1: EP2C8 (0x020B20DD).
Current LED Value (sample #0): 84
Info: Evaluation of Tcl script a.tcl was successful
Info: Quartus II SignalTap II was successful. 0 errors, 0 warnings
Info: Peak virtual memory: 75 megabytes
Info: Processing ended: Sun Feb 28 16:28:54 2010
Info: Elapsed time: 00:00:01
Info: Total CPU time (on all processors): 00:00:01
上面的 数据84H和实测结果一致,并且多次验证无误。
在初步掌握这项技巧后,如果再在tcl编程方面下点功 夫,使用Virtual JTGA带来的便利会更加明显。我想我有些迫不及待的希望尝试这个便利了。