Vivado - JTAG to AXI Master (DDR4)
目录
1. 简介
本文分享了使用 JTAG to AXI Master 调试 DDR4 IP 的全过程。
- 在 Block Design 中通过 AXI SmartConnect 和 DDR4 MIG 进行地址分配和时钟管理。
- 对于 AXI SmartConnect 的时钟域管理,分享了同步和异步转换的优缺点,提供了在设计中优化时钟域交叉的方法,以减少延迟和资源消耗。
- 在 DDR4 MIG 的配置中,本文列出了时钟和复位信号的功能。
- 分享了 XDC 约束文件。
- 使用 TCL 脚本实现了对 DDR4 的读写操作,展示了如何通过创建 AXI 事务来进行数据传输。
- 通过封装 TCL 过程,使得写入和读取操作更加简洁和高效。
- 使用 HLS IP 初始化,分享内存访问的基本操作方法。
- 介绍了如何格式化 AXI 事务报告,以及如何将操作记录保存到本地文件中,便于后续的分析和调试。
2. JTAG 直接操作 DDR4
2.1 Block Design
地址分配:
2.2 AXI SmartConnect
- 默认情况下,SmartConnect 上的所有接口都在相同的时钟域中运行,通过 aclk 引脚接收。
- 支持多个时钟域(aclk1…aclkn),工具会自动识别并连接到对应的时钟域。
- 当沿任何 AXI 通道在属于不同时钟域的接口之间交换信息时,时钟转换逻辑会自动插入路径中。
- 当工具确定时钟域之间的关系是整数比,范围在1:16到16:1之间,并且时钟来自同一时钟源时,工具会自动配置时钟转换器以执行同步转换;否则,时钟转换器配置为异步模式。
- 当时钟转换器配置为异步模式时,所有时钟域交叉都在 FIFO 生成器核心的底层实例中执行,该核心设计用于在其写入和读取时钟域内部重新同步,无论相位或频率关系如何。在异步模式下,核心会生成适当的仅数据路径的时序约束,以覆盖所有重新同步路径。
- 时钟转换器会引入延迟。与同步转换相比,异步转换会产生更多延迟并使用更多的逻辑资源。
- 为了减少系统中的时钟转换器数量,可以级联 AXI SmartConnect 核心实例,将时钟相似的设备组合在一起。例如,将一组低频 AXI4-Lite 从设备连接到低频时钟的单独 AXI SmartConnect 核心,可以将时钟域交叉合并到级联的 AXI SmartConnect 核心实例之间的单个转换器路径中。
2.3 DDR4 MIG
2.3.1 时钟和复位
| 信号 | 方向 | 功能
|-------------------------|------- |--------------------------------------------------------
| C0_SYS_CLK | input | DRAM IP Core 时钟
| c0_ddr4_aresetn | input | AXI 复位输入,应该与 FPGA 逻辑时钟同步。
| sys_rst | input | 系统复位,高电平有效,重置整个内存模块
| c0_ddr4_ui_clk | output | 用户接口时钟,AXI 接口同步时钟取自 ui_clk。(Table 4-39)
| c0_ddr4_ui_clk_sync_rst | output | 用户接口复位,高电平有效
sys_rst 信号重置整个内存设计,包括由 MMCM 时钟(clkout0)驱动的通用互连(fabric)逻辑和 RIU 逻辑。MicroBlaze™ 和校准逻辑由 MMCM 时钟(clkout6)驱动。sys_rst 输入信号在内部同步,以创建 ui_clk_sync_rst 信号。ui_clk_sync_rst 重置信号同步地被断言和同步地被解除断言。
图3-14显示,在断言 sys_rst 后几个时钟延迟,ui_clk_sync_rst(fabric 重置)会同步断言。当 ui_clk_sync_rst 被断言时,在关闭时钟之前还有几个时钟周期。
2.3.2 AXI Slave 接口
- AXI4 从接口是可选的。
- AXI4 从接口块将 AXI4 事务映射到 UI(User Interface)。
- UI 在表 4-14 中描述(PG150),并连接到 FPGA 用户逻辑,以访问外部存储设备。
- UI 构建在早先在控制器描述中提到的本地接口之上。
- 两种工具之间的RTL是一致的。
2.4 XDC 约束
############# DDR4 Memory Controller ################################
set_property PACKAGE_PIN K22 [get_ports C0_SYS_CLK_0_clk_p]
set_property PACKAGE_PIN L22 [get_ports {c0_alert_n[0]}]
set_property IOSTANDARD SSTL12 [get_ports {c0_alert_n[0]}]
############# External Memory Interface - Clock #####################
set_property PACKAGE_PIN G24 [get_ports {ddr4_rtl_0_ck_t[0]}]
############# External Memory Interface - ADDR & CMD ################
set_property PACKAGE_PIN D26 [get_ports {ddr4_rtl_0_adr[0]}]
set_property PACKAGE_PIN D25 [get_ports {ddr4_rtl_0_adr[1]}]
set_property PACKAGE_PIN E26 [get_ports {ddr4_rtl_0_adr[2]}]
set_property PACKAGE_PIN C24 [get_ports {ddr4_rtl_0_adr[3]}]
set_property PACKAGE_PIN C26 [get_ports {ddr4_rtl_0_adr[4]}]
set_property PACKAGE_PIN F24 [get_ports {ddr4_rtl_0_adr[5]}]
set_property PACKAGE_PIN M26 [get_ports {ddr4_rtl_0_adr[6]}]
set_property PACKAGE_PIN B25 [get_ports {ddr4_rtl_0_adr[7]}]
set_property PACKAGE_PIN G26 [get_ports {ddr4_rtl_0_adr[8]}]
set_property PACKAGE_PIN B26 [get_ports {ddr4_rtl_0_adr[9]}]
set_property PACKAGE_PIN E25 [get_ports {ddr4_rtl_0_adr[10]}]
set_property PACKAGE_PIN H26 [get_ports {ddr4_rtl_0_adr[11]}]
set_property PACKAGE_PIN D23 [get_ports {ddr4_rtl_0_adr[12]}]
set_property PACKAGE_PIN F25 [get_ports {ddr4_rtl_0_adr[13]}]
set_property PACKAGE_PIN K25 [get_ports {ddr4_rtl_0_adr[14]}]
set_property PACKAGE_PIN E23 [get_ports {ddr4_rtl_0_adr[15]}]
set_property PACKAGE_PIN F22 [get_ports {ddr4_rtl_0_adr[16]}]
set_property PACKAGE_PIN K26 [get_ports {ddr4_rtl_0_bg[0]}]
set_property PACKAGE_PIN M25 [get_ports {ddr4_rtl_0_ba[0]}]
set_property PACKAGE_PIN F23 [get_ports {ddr4_rtl_0_ba[1]}]
set_property PACKAGE_PIN J26 [get_ports ddr4_rtl_0_act_n]
set_property IOSTANDARD SSTL12_DCI [get_ports ddr4_rtl_0_act_n]
############# External Memory Interface - Data ######################
set_property PACKAGE_PIN E16 [get_ports {ddr4_rtl_0_dqs_t[0]}]
set_property PACKAGE_PIN E17 [get_ports {ddr4_rtl_0_dqs_c[0]}]
set_property PACKAGE_PIN A17 [get_ports {ddr4_rtl_0_dqs_t[1]}]
set_property PACKAGE_PIN A18 [get_ports {ddr4_rtl_0_dqs_c[1]}]
set_property PACKAGE_PIN F20 [get_ports {ddr4_rtl_0_dqs_t[2]}]
set_property PACKAGE_PIN E20 [get_ports {ddr4_rtl_0_dqs_c[2]}]
set_property PACKAGE_PIN C21 [get_ports {ddr4_rtl_0_dqs_t[3]}]
set_property PACKAGE_PIN B21 [get_ports {ddr4_rtl_0_dqs_c[3]}]
set_property PACKAGE_PIN G15 [get_ports {ddr4_rtl_0_dm_n[0]}]
set_property PACKAGE_PIN C18 [get_ports {ddr4_rtl_0_dm_n[1]}]
set_property PACKAGE_PIN H18 [get_ports {ddr4_rtl_0_dm_n[2]}]
set_property PACKAGE_PIN A22 [get_ports {ddr4_rtl_0_dm_n[3]}]
set_property PACKAGE_PIN C16 [get_ports {ddr4_rtl_0_dq[0]}]
set_property PACKAGE_PIN G16 [get_ports {ddr4_rtl_0_dq[1]}]
set_property PACKAGE_PIN D15 [get_ports {ddr4_rtl_0_dq[2]}]
set_property PACKAGE_PIN G17 [get_ports {ddr4_rtl_0_dq[3]}]
set_property PACKAGE_PIN H17 [get_ports {ddr4_rtl_0_dq[4]}]
set_property PACKAGE_PIN H16 [get_ports {ddr4_rtl_0_dq[5]}]
set_property PACKAGE_PIN D16 [get_ports {ddr4_rtl_0_dq[6]}]
set_property PACKAGE_PIN E15 [get_ports {ddr4_rtl_0_dq[7]}]
set_property PACKAGE_PIN B19 [get_ports {ddr4_rtl_0_dq[8]}]
set_property PACKAGE_PIN C17 [get_ports {ddr4_rtl_0_dq[9]}]
set_property PACKAGE_PIN B20 [get_ports {ddr4_rtl_0_dq[10]}]
set_property PACKAGE_PIN B15 [get_ports {ddr4_rtl_0_dq[11]}]
set_property PACKAGE_PIN A19 [get_ports {ddr4_rtl_0_dq[12]}]
set_property PACKAGE_PIN A15 [get_ports {ddr4_rtl_0_dq[13]}]
set_property PACKAGE_PIN A20 [get_ports {ddr4_rtl_0_dq[14]}]
set_property PACKAGE_PIN B17 [get_ports {ddr4_rtl_0_dq[15]}]
set_property PACKAGE_PIN G20 [get_ports {ddr4_rtl_0_dq[16]}]
set_property PACKAGE_PIN D19 [get_ports {ddr4_rtl_0_dq[17]}]
set_property PACKAGE_PIN D20 [get_ports {ddr4_rtl_0_dq[18]}]
set_property PACKAGE_PIN F19 [get_ports {ddr4_rtl_0_dq[19]}]
set_property PACKAGE_PIN G21 [get_ports {ddr4_rtl_0_dq[20]}]
set_property PACKAGE_PIN E18 [get_ports {ddr4_rtl_0_dq[21]}]
set_property PACKAGE_PIN D18 [get_ports {ddr4_rtl_0_dq[22]}]
set_property PACKAGE_PIN F18 [get_ports {ddr4_rtl_0_dq[23]}]
set_property PACKAGE_PIN C23 [get_ports {ddr4_rtl_0_dq[24]}]
set_property PACKAGE_PIN C22 [get_ports {ddr4_rtl_0_dq[25]}]
set_property PACKAGE_PIN A24 [get_ports {ddr4_rtl_0_dq[26]}]
set_property PACKAGE_PIN B22 [get_ports {ddr4_rtl_0_dq[27]}]
set_property PACKAGE_PIN A25 [get_ports {ddr4_rtl_0_dq[28]}]
set_property PACKAGE_PIN D21 [get_ports {ddr4_rtl_0_dq[29]}]
set_property PACKAGE_PIN B24 [get_ports {ddr4_rtl_0_dq[30]}]
set_property PACKAGE_PIN E21 [get_ports {ddr4_rtl_0_dq[31]}]
############# External Memory Interface - Control ###################
set_property PACKAGE_PIN L24 [get_ports {ddr4_rtl_0_cke[0]}]
set_property PACKAGE_PIN D24 [get_ports {ddr4_rtl_0_cs_n[0]}]
set_property PACKAGE_PIN H24 [get_ports {ddr4_rtl_0_odt[0]}]
set_property PACKAGE_PIN L25 [get_ports ddr4_rtl_0_reset_n]
############################ Others #################################
set_property PACKAGE_PIN H13 [get_ports ext_reset_in_0]
set_property IOSTANDARD LVCMOS33 [get_ports ext_reset_in_0]
set_property PACKAGE_PIN H12 [get_ports led_0]
set_property IOSTANDARD LVCMOS33 [get_ports led_0]
########################## Debug Hub ################################
set_property C_CLK_INPUT_FREQ_HZ 300000000 [get_debug_cores dbg_hub]
set_property C_ENABLE_CLK_DIVIDER false [get_debug_cores dbg_hub]
set_property C_USER_SCAN_CHAIN 1 [get_debug_cores dbg_hub]
connect_debug_port dbg_hub/clk [get_nets clk]
即使没有手动添加,Vivado 可能会在某些情况下自动插入 ILA 以便于调试。
Debug core 包括以下几种常见类型:
- ILA(Integrated Logic Analyzer):用于捕获和分析设计中的信号波形。
- VIO(Virtual Input/Output):用于监控和驱动信号,主要用于模拟外部输入输出。
- JTAG-to-AXI Master:用于通过 JTAG 接口驱动 AXI 总线,发送和接收数据包。
这些调试核心通过 Debug Hub 模块连接到 JTAG 接口,从而允许 Vivado Hardware Manager 通过 JTAG 控制和监控这些核心。
2.5 TCL 代码
2.5.1 写入 DDR4
1)将 32bit*4 作为整体直接发送:
create_hw_axi_txn \
write_txn [get_hw_axis hw_axi_1] \
-type WRITE \
-address 4000_0000 \
-len 4 \
-data {11112222_33334444_55556666_77778888} \
-force
run_hw_axi [get_hw_axi_txns write_txn]
“-data” 方向为左侧 MSB(即,地址 3)和右侧 LSB(即,地址 0)。
读取4个数据进行验证:
run_hw_axi [get_hw_axi_txns read_txn]
report_hw_axi_txn read_txn -w 4
---
4000 77778888
4004 55556666
4008 33334444
400c 11112222
2)将 32bit*4 分为四个数据发送:
create_hw_axi_txn \
write_txn [get_hw_axis hw_axi_1] \
-type WRITE \
-address 4000_0000 \
-len 4 \
-data {11112222 33334444 55556666 77778888} \
-force
run_hw_axi [get_hw_axi_txns write_txn]
“-data” 方向与情况一相反,为左侧 LSB(即,地址 0)和右侧 MSB(即,地址 3)
读取4个数据进行验证:
run_hw_axi [get_hw_axi_txns read_txn]
report_hw_axi_txn read_txn -w 4
---
4000 11112222
4004 33334444
4008 55556666
400c 77778888
3)封装写入过程的 TCL 代码:
proc write {address dataList} {
# 移除地址中的 "0x" 前缀(如果存在)和任何下划线
set address [string map {"0x" "" "_" ""} $address]
# 创建写事务
create_hw_axi_txn wr_txn [get_hw_axis hw_axi_1] -address $address -data $dataList -len [llength $dataList] -type write -force
# 执行事务
run_hw_axi wr_txn
}
write 0x4000_0000 {0x11111111 0x22222222 0x33333333 0x44444444}
2.5.2 读取 DDR4
proc read {address len} {
# 移除地址中的 "0x" 前缀(如果存在)和任何下划线
set address [string map {"0x" "" "_" ""} $address]
# 创建读事务
create_hw_axi_txn rd_txn [get_hw_axis hw_axi_1] -address $address -len $len -type read -force
# 执行事务
run_hw_axi rd_txn
}
read 0x4000_0000 4
3. HLS IP 操作 DDR4
3.1 Block Design
- 红色:166.625 MHz 时钟域
- 蓝色:333.250 MHz 时钟域
为什么这么安排时钟?
JTAG to AXI Master 的最高设计时钟是 200MHz,DDR4 IP 输出的用户时钟为 333.25MHz,通过BUFGCE_DIV 二分频为 166.625 MHz,此时钟给所有模块进行驱动。而 333.25MHz 仅给 AXI Interconnet 上与 DDR4 IP 的 AXI Slave 接口使用。
3.2 HLS IP
3.2.1 HLS 代码
一个简单的内存初始化函数:将一个整型数组初始化,数组的每个元素的值等于其索引。
void init_memory(int *mem)
{
#pragma HLS INTERFACE mode=s_axilite port=return
#pragma HLS INTERFACE mode=m_axi port=mem depth=128
int i;
for (i = 0; i < 128; i++) {
mem[i] = i; // 初始化内存,值为 0 到 127
}
}
代码分析
- 函数 init_memory 接受一个指向整数的指针 mem 作为参数。这个指针指向的是需要被初始化的内存区域。
- HLS INTERFACE mode=s_axilite port=return:块级控制接口为 s_axilite。
- HLS INTERFACE mode=m_axi port=mem depth=128:指定 mem 参数应该通过一个 AXI Master 接口来访问,存储深度是 128。表示这个内存区域可以存储128个整数。
- 循环迭代:用于初始化内存区域。
地址递增分析
mem 是一个指向整数数组的起始地址。每次循环迭代,`i` 的值增加1,因此访问的内存地址也相应地递增。mem 是整数指针,占用4个字节。因此,每次数组索引递增时,内存地址递增的4个字节。
3.2.2 HLS Report
1)地址位宽
* M_AXI
+------------+------------+---------------+---------+--------+----------+-----------+--------------+--------------+-------------+-------------+
| Interface | Data Width | Address Width | Latency | Offset | Register | Max Widen | Max Read | Max Write | Num Read | Num Write |
| | (SW->HW) | | | | | Bitwidth | Burst Length | Burst Length | Outstanding | Outstanding |
+------------+------------+---------------+---------+--------+----------+-----------+--------------+--------------+-------------+-------------+
| m_axi_gmem | 32 -> 32 | 32 | 0 | slave | 0 | 0 | 16 | 16 | 16 | 16 |
+------------+------------+---------------+---------+--------+----------+-----------+--------------+--------------+-------------+-------------+
Vitis HLS 工具默认生成的位宽是 64bit,通过取消勾选 m_axi_addr64,可以启用 32bit 位宽。
3.3 TCL 代码
3.3.1 基本 proc
proc write {address dataList} {
set address [string map {"0x" "" "_" ""} $address]
create_hw_axi_txn wr_txn [get_hw_axis hw_axi_1] -address $address -data $dataList -len [llength $dataList] -type write -force
run_hw_axi wr_txn
}
proc read {address len} {
set address [string map {"0x" "" "_" ""} $address]
create_hw_axi_txn rd_txn [get_hw_axis hw_axi_1] -address $address -len $len -type read -force
run_hw_axi rd_txn
}
3.3.2 验证写入和读取
首先写入特定的数据:
write 0x0000_0000 {0x12345678 0x22345678 0x32345678 0x42345678}
---
INFO: [Labtoolstcl 44-481] WRITE DATA is: 0x12345678 0x22345678 0x32345678 0x42345678
读取,以验证高低位:
report_hw_axi_txn read_txn -w 4
---
0000 12345678
0004 22345678
0008 32345678
000c 42345678
3.3.3 执行 HLS IP
寄存器描述:
// ==============================================================
// control
// 0x0 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read/COR)
// bit 7 - auto_restart (Read/Write)
// bit 9 - interrupt (Read)
// others - reserved
// 0x4 : Global Interrupt Enable Register
// bit 0 - Global Interrupt Enable (Read/Write)
// others - reserved
// 0x8 : IP Interrupt Enable Register (Read/Write)
// bit 0 - enable ap_done interrupt (Read/Write)
// bit 1 - enable ap_ready interrupt (Read/Write)
// others - reserved
// 0xc : IP Interrupt Status Register (Read/COR)
// bit 0 - ap_done (Read/COR)
// bit 1 - ap_ready (Read/COR)
// others - reserved
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)
向 bit 0 - ap_start 写入 '1',启动一次 HLS IP。
write 0x8000_0000 0x0000_0001
此时,内存中的数据已被 HLS IP 初始化。读取 0x0000_0000 地址的数据以验证:
read 0x0000_0000 4
INFO: [Labtoolstcl 44-481] READ DATA is: 00000003000000020000000100000000
report_hw_axi_txn read_txn -w 4
---
0000 00000000
0004 00000001
0008 00000002
000c 00000003
4. 格式化显示报告
4.1 report_hw_axi_txn
描述
报告格式化的硬件 AXI 事务数据(读取事务和写入事务均可)。
语法
report_hw_axi_txn [-w <arg>] [-t <arg>] [-quiet] [-verbose] <hw_axi_txns>...
用法:
Name Description
--------------------------
[-w] 每行输出的数据字节数(默认值:8)
[-t] d[SIZE] 有符号十进制,每个整数SIZE字节
b[SIZE] 二进制,每个整数SIZE字节
o[SIZE] 八进制,每个整数SIZE字节
u[SIZE] 无符号十进制,每个整数SIZE字节
x[SIZE] 十六进制,每个整数SIZE字节,默认值:x4(4字节十六进制)
[-quiet] 忽略命令错误
[-verbose] 在命令执行期间暂停消息限制
<hw_axi_txns> 要报告的硬件AXI事务对象
示例(以默认的十六进制数显示):
创建传输事务(先写,后读):
create_hw_axi_txn \
write_txn [get_hw_axis hw_axi_1] \
-type WRITE \
-address 4000_0000 \
-len 4 \
-data {11111111_22222222_33333333_44444444} \
-force
run_hw_axi [get_hw_axi_txns write_txn]
create_hw_axi_txn \
read_txn [get_hw_axis hw_axi_1] \
-type READ \
-address 4000_0000 \
-len 4 \
-force
run_hw_axi [get_hw_axi_txns read_txn]
每行显示4个字节 :
report_hw_axi_txn read_txn -w 4
---
4000 44444444
4004 33333333
4008 22222222
400c 11111111
每行显示8个字节:
report_hw_axi_txn write_txn -w 8
---
4000 44444444 33333333
4008 22222222 11111111
每行显示16个字节:
report_hw_axi_txn write_txn -w 16
---
4000 44444444 33333333 22222222 11111111
4.2 保存到本地
4.2.1 带记录功能的读过程
proc read { address } {
# 定义全局变量data_list和num
global data_list
global num
# 创建一个AXI读事务命令。指定硬件接口为hw_axi_1,地址为传入的address,操作类型为读取。
create_hw_axi_txn read_txn [get_hw_axis hw_axi_1] -address $address -type read
# 执行创建的AXI读事务
run_hw_axi read_txn
# 从事务报告中获取读取的值,该值位于返回列表的第二个位置(索引为1)
set read_value [lindex [report_hw_axi_txn read_txn] 1];
# 将读取的事务信息格式化后追加到data_list列表中。包括事务编号、操作类型(读取)、地址和读取的值。
# 这里分别格式化事务编号、操作类型、地址和读取的值,并追加到data_list字符串中。
append data_list [format %3i $num]
append data_list [format %4s r]
append data_list [format %10s $address]
append data_list [format "%10s\n" $read_value]
# 删除已完成的读事务
delete_hw_axi_txn read_txn
# 递增事务编号
incr num
}
4.2.2 带记录功能的写过程
proc WriteReg { address data } {
# 定义全局变量data_list和num
global data_list
global num
# 创建一个AXI写事务命令。指定硬件接口为hw_axi_1,地址为传入的address,数据为传入的data,操作类型为写入。
create_hw_axi_txn write_txn [get_hw_axis hw_axi_1] -address $address -data $data -type write
# 执行创建的AXI写事务
run_hw_axi write_txn
# 从事务报告中获取写入的值,该值位于返回列表的第二个位置(索引为1)
set write_value [lindex [report_hw_axi_txn write_txn] 1];
# 将写入的事务信息格式化后追加到data_list列表中。包括事务编号、操作类型(写入)、地址和写入的值。
# 这里分别格式化事务编号、操作类型、地址和写入的值,并追加到data_list字符串中。
append data_list [format %3i $num]
append data_list [format %4s w]
append data_list [format %10s $address]
append data_list [format "%10s\n" $write_value]
# 删除已完成的写事务
delete_hw_axi_txn write_txn
# 递增事务编号
incr num
}
4.2.3 将记录存储到本地
#-----------------------------------
# 时间戳
#-----------------------------------
# 获取当前时间的秒数
set currentTime [clock seconds]
# 格式化当前时间,包括日期和时间,并存储在变量ctime中
set ctime "The time is: \
[clock format $currentTime -format %D] \
[clock format $currentTime -format %H:%M:%S] \n"
#-----------------------------------
# 文件保存:设置您自己的文件路径
#-----------------------------------
# 将命令数据保存到本地
# 设置文件路径,这里需要用户根据实际情况设置路径
set file_path "xx/log.txt"
# 以追加模式打开文件,如果文件不存在则创建文件
set fp [open $file_path a+]
# 将当前时间写入文件
puts $fp $ctime
# 将数据列表写入文件
puts $fp $data_list
# 关闭文件
close $fp
4.2.4 加载文件到控制台
# 从本地数据文件加载数据
# 以只读模式打开文件
set fp [open $file_path r]
# 读取文件的全部内容
set file_data [read $fp]
# 输出读取的数据到控制台,用于验证内容
puts $file_data
# 关闭文件
close $fp
5. 总结
本文分享了使用 JTAG to AXI Master 调试 DDR4 IP 的过程。
要点:
- 使用 JTAG to AXI Master 直连 DDR4 IP
- 添加 HLS IP 初始化 DDR4 IP
- 格式化显示传输事务
- 保存传输事务记录
原文地址:https://blog.csdn.net/DongDong314/article/details/142644755
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!