使用Xilinx FPGA做板级验证的时候,如果要查看DUT的输出结果,除了UART这种接口之外,还可以通过JTAG读取数据
读取数据需要一个IP,JTAG to AXI4 Master。该IP通过AXI BRAM Controller连接到Block Memory Generator,如下图所示:
为了搭建成该图,Block Memory Generator需要设置为AXI BRAM Controller模式。
该模式下有一些注意事项:
- 该模式的寻址方式为按字节寻址,因为AXI协议就是按照字节寻址的。如果BRAM是32bit的,那么0地址对应第一个存储字,4地址对应第二个存储字,这一点与Native模式不同。
- 调整BRAM的深度只能通过Address Editor里的range来调整,调整好后,validate design,则controller和BMG也会自动调整。注意:Address Editor里的地址也是按字节寻址
搭建完上板后,连接JTAG,打开Vivado的Hardware Manager,读取BRAM的值需要tcl命令。
以下脚本为连续读取整个BRAM并写至txt的TCL代码:
set start_addr 0xC0000000
set end_addr 0xC0400000
set file [open "output.txt" a]
for {set addr $start_addr} {$addr < $end_addr} {set addr [expr $addr + 0x400]} {
puts "start fetch $addr"
create_hw_axi_txn rd_txn [get_hw_axis hw_axi_1] -address [format "%08X" $addr] -len 256 -type read -force -quiet
run_hw_axi rd_txn
set report [report_hw_axi_txn -w 4 rd_txn]
puts -nonewline $file $report
}
close $file
这里涉及到的命令有create_hw_axi_txn,run_hw_axi,report_hw_axi_txn。在TCL console输入-help参数即可查看对应的帮助。
关于代码的一些注意事项:
- address是字节编址,burst长度为256,转换成十六进制是0x100,因为每四个地址才是一个32bit存储字,所以addr递增0x400
- 如果需要自定义burst长度,一定要注意AXI协议规定的4k边界问题,即burst传输不能跨越以000结尾的地址(如0xC0001000)。从下图可以看到burst遇到4k边界时,会wrap回本4k段的起始,79这个值是地址0的值,而非真正的c0001000的值