Vivado - JTAG to AXI Master (DDR4)

news2024/10/6 17:38:02

目录

1. 简介

2. JTAG 直接操作 DDR4

2.1 Block Design

2.2 AXI SmartConnect

2.3 DDR4 MIG

2.3.1 时钟和复位

2.3.2 AXI Slave 接口

2.4 XDC 约束

2.5 TCL 代码

2.5.1 写入 DDR4

2.5.2 读取 DDR4

3. HLS IP 操作 DDR4

3.1 Block Design

3.2 HLS IP

3.2.1 HLS 代码

3.2.2 HLS Report

3.3 TCL 代码

3.3.1 基本 proc

3.3.2 验证写入和读取

3.3.3 执行 HLS IP

4. 格式化显示报告

4.1 report_hw_axi_txn

4.2 保存到本地

4.2.1 带记录功能的读过程

4.2.2 带记录功能的写过程

4.2.3 将记录存储到本地

4.2.4 加载文件到控制台

5. 总结


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
  • 格式化显示传输事务
  • 保存传输事务记录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2192490.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TypeScript面向对象 01

使用class关键字来定义一个类。对象中主要包含了两个部分&#xff1a;属性和方法。 class Person {// 定义实例属性name:string glm;age:number 1234; } const a new Person(); console.log(a.name);在属性前使用static关键字可以定义类属性&#xff08;静态属性&#xff0…

Sebastian Raschka 最新博客:从头开始用 Llama 2 构建 Llama 3.2

最近已有不少大厂都在秋招宣讲了&#xff0c;也有一些在 Offer 发放阶段。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行了…

自动驾驶-问题笔记-待解决

参考线的平滑方法 参考线平滑算法主要有三种&#xff1a; 离散点平滑&#xff1b;螺旋曲线平滑&#xff1b;多项式平滑&#xff1b; 参考链接&#xff1a;参考线平滑 对于平滑方法&#xff0c;一直不太理解平滑、拟合以及滤波三者的作用与区别&#xff1b; 规划的起点&#x…

代码随想录一刷完结

非常偶然的机会让我看到这个算法训练营的存在&#xff0c;虽然我也没有多大的动力&#xff0c;但当时就觉得没什么事情&#xff0c;想着刷刷题&#xff0c;为以后找工作打打基础。 收获 提示&#xff1a;在刷题过程中的收获 第一次使用CSDN记录&#xff0c;每次有别人点赞和收…

【React】事件机制

事件机制 react 基于浏览器的事件机制自身实现了一套事件机制&#xff0c;称为合成事件。比如&#xff1a;onclick -> onClick 获取原生事件&#xff1a;e.nativeEvent onClick 并不会将事件代理函数绑定到真实的 DOM节点上&#xff0c;而是将所有的事件绑定到结构的最外层…

【LeetCode: 134. 加油站 | 贪心算法】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

AI模型部署初认识

AI部署这个词儿大家肯定不陌生&#xff0c;可能有些小伙伴还不是很清楚这个是干嘛的&#xff0c;但总归是耳熟能详了。 近些年来&#xff0c;在深度学习算法已经足够卷卷卷之后&#xff0c;深度学习的另一个偏向于工程的方向–部署工业落地&#xff0c;才开始被谈论的多了起来…

C语言 | Leetcode C语言题解之第456题132模式

题目&#xff1a; 题解&#xff1a; int upper_bound(int* vec, int vecSize, int target) {int low 0, high vecSize - 1;if (vec[high] > target) {return -1;}while (low < high) {int mid (high - low) / 2 low;int num vec[mid];if (num > target) {low m…

IDEA基础开发配置以及和git的联动

1.1方向一&#xff1a;工具介绍 我今天要介绍的就是学习Java大部分情况下都会选择的一款工具-----IDEA&#xff0c;这个和我们熟悉的这个pycharm一样&#xff0c;都是属于这个Jetbrains公司的&#xff0c;虽然我对于这个并不是很了解&#xff0c;但是确实知道一点&#xff0c;…

静止坐标系和旋转坐标系变换的线性化,锁相环线性化通用推导

将笛卡尔坐标系的电压 [ U x , U y ] [U_x, U_y] [Ux​,Uy​] 通过旋转变换(由锁相环角度 θ P L L \theta_{PLL} θPLL​ 控制)转换为 dq 坐标系下的电压 [ U d , U q ] [U_d, U_q] [Ud​,Uq​]。这个公式是非线性的,因为它涉及到正弦和余弦函数。 图片中的推导过程主要…

一款基于 Java 的可视化 HTTP API 接口快速开发框架,干掉 CRUD,效率爆炸(带私活源码)

平常我们经常需要编写 API&#xff0c;但其实常常只是一些简单的增删改查&#xff0c;写这些代码非常枯燥无趣。 今天给大家带来的是一款基于 Java 的可视化 HTTP API 接口快速开发框架&#xff0c;通过 UI 界面编写接口&#xff0c;无需定义 Controller、Service、Dao 等 Jav…

使用 Python 进行大规模数据处理

在 Python 中&#xff0c;处理大量数据时&#xff0c;效率是非常重要的。当你有一个包含 100 万个元素的列表&#xff0c;每个元素都是一个字典&#xff0c;并且需要将它们转换为 DataFrame 时&#xff0c;Pandas 是一个很好的工具。Pandas 是 Python 数据处理和分析的强大库&a…

一键生成PPT的AI工具-Kimi!

一键生成PPT的AI工具-Kimi&#xff01; 前言介绍Kimi为什么选择Kimi如何使用Kimi在线编辑PPT下载生成的PPT自己编辑 结语 &#x1f600;大家好&#xff01;我是向阳&#x1f31e;&#xff0c;一个想成为优秀全栈开发工程师的有志青年&#xff01; &#x1f4d4;今天不来讨论前后…

yolov5-7.0模型DNN加载函数及参数详解(重要)

yolov5-7.0模型DNN加载函数及参数详解&#xff08;重要&#xff09; 引言yolov5&#xff08;v7.0&#xff09;1&#xff0c;yolov5.h(加载对应模型里面的相关参数要更改)2&#xff0c;main主程序&#xff08;1&#xff09;加载网络&#xff08;2&#xff09;检测推理&#xff0…

超酷!任务栏美化 给任务栏添加一个好看的时钟

如何给任务栏美化&#xff1f;今天我们这个主题就是帮大家美化任务栏&#xff0c;估计很多伙伴都用过任务栏美化工具。任务栏美化是非常有个性化的功能&#xff0c;不但可以让你的任务栏变得漂亮&#xff0c;还可以增加一些非常有创意的功能&#xff0c;比如今天小编要给大家带…

文件共享软件推荐,哪些工具最实用?

预计到2025年文档共享市场将增长至近100亿美金。文件共享软件助力跨区域协作&#xff0c;推荐ZohoWorkDrive、GoogleDrive、DropboxBusiness。软件设计直观&#xff0c;上手易&#xff0c;可保障数据安全&#xff0c;选择时需考虑企业规模、需求及预算。 一、什么是文件共享软件…

linux部署NFS和autofs自动挂载

目录 &#xff08;一&#xff09;NFS&#xff1a; 1. 什么是NFS 2. NFS守护进程 3. RPC服务 4. 原理 5. 部署 5.1 安装NFS服务 5.2 配置防火墙 5.3 创建服务端共享目录 5.4 修改服务端配置文件 (1). /etc/exports (2). nfs.conf 5.5 启动nfs并加入自启 5.6 客户端…

陀螺仪LSM6DSV16X与AI集成(14)----上报匿名上位机

陀螺仪LSM6DSV16X与AI集成.14--上报匿名上位机 概述视频教学样品申请源码下载硬件准备上位机通讯陀螺仪工作方式欧拉角数据的转换数据帧填充校验和计算数据发送演示开启INT中断中断读取传感器数据主程序演示 概述 本文介绍了如何将 LSM6DSV16X 传感器的姿态数据通过匿名通信协…

【Android】Handler消息机制

文章目录 前言概述核心组件概述Android消息机制概述 Android消息机制分析ThreadLocal的工作原理ThreadLocal基础ThreadLocal实现原理 MessageQueueLooperHandler的工作原理总结 前言 本文用于记录Android的消息机制&#xff0c;主要是指Handler的运行机制。部分内容参考自《An…

产品经理都会的ComfyUI搭建指南

最近准备参加一个ComfyUI的活动&#xff0c;发现还没有上手过ComfyUI&#xff0c;于是先部署起来。ComfyUI是一个基于Stable Diffusion开发的UI。比起WebUI表单式交互的简单&#xff0c;ComfyUI主打灵活&#xff0c;Diffusion Model管线中的各个模块如&#xff1a;VAE、Control…