From 5d0a940aea129ba32db5c38cb42975fc6a5dff8d Mon Sep 17 00:00:00 2001 From: Josh Gao Date: Fri, 28 Jun 2024 10:39:55 +0800 Subject: [PATCH] finish post, zynq dynamic ddr configuration --- _config.next.yml | 4 +- .../_posts/2024-06-27-zynq-mpsoc-ddr-spd.md | 126 +++++++++++++----- ...-zynq-mpsoc-ddr-spd-060-DDR4SPDAddress.png | Bin 0 -> 345709 bytes ...-27-zynq-mpsoc-ddr-spd-070-DebugConfig.png | Bin 0 -> 144238 bytes ...6-27-zynq-mpsoc-ddr-spd-080-Breakpoint.png | Bin 0 -> 480605 bytes ...6-27-zynq-mpsoc-ddr-spd-090-IICMuxRead.png | Bin 0 -> 502283 bytes ...7-zynq-mpsoc-ddr-spd-100-IICEEPROMRead.png | Bin 0 -> 507434 bytes 7 files changed, 91 insertions(+), 39 deletions(-) create mode 100644 source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-060-DDR4SPDAddress.png create mode 100644 source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-070-DebugConfig.png create mode 100644 source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-080-Breakpoint.png create mode 100644 source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-090-IICMuxRead.png create mode 100644 source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-100-IICEEPROMRead.png diff --git a/_config.next.yml b/_config.next.yml index f566c7d..14006e9 100644 --- a/_config.next.yml +++ b/_config.next.yml @@ -367,8 +367,8 @@ codeblock: # Code Highlight theme # All available themes: https://theme-next.js.org/highlight/ theme: - light: default - dark: github-dark + light: vs + dark: github-dark-dimmed prism: light: prism dark: prism-dark diff --git a/source/_posts/2024-06-27-zynq-mpsoc-ddr-spd.md b/source/_posts/2024-06-27-zynq-mpsoc-ddr-spd.md index b82f0e3..715af9b 100644 --- a/source/_posts/2024-06-27-zynq-mpsoc-ddr-spd.md +++ b/source/_posts/2024-06-27-zynq-mpsoc-ddr-spd.md @@ -1,5 +1,5 @@ --- -title: Zynq MPSoC/RFSoC 动态配置 DIMM DDR +title: Zynq MPSoC / RFSoC 动态配置 DIMM DDR mathjax: true comments: true copyright: true @@ -22,7 +22,7 @@ abbrlink: 11cd1dc date: 2024-06-27 20:06:13 --- -对于 DIMM 拓扑的 DDR,通常可以使用 I2C 对搭载在 DIMM 上的 SDP EEPROM 进行读取后获得配置参数,然后对 DDR 控制器进行配置。 +对于 DIMM 拓扑的 DDR,通常可以使用 I2C 对搭载在 DIMM 上的 SPD EEPROM 进行读取后获得配置参数,然后对 DDR 控制器进行配置。 AMD Xilinx UG1085 的 [Dynamic DDR Configuration](https://docs.amd.com/r/en-US/ug1085-zynq-ultrascale-trm/Dynamic-DDR-Configuration) 一节指出,当 DDR 控制器处于复位状态时,可以在运行时通过 FSBL 获取 DDR 参数并对 DDR 控制器进行初始化。 @@ -51,9 +51,9 @@ AMD Xilinx UG1085 的 [Dynamic DDR Configuration](https://docs.amd.com/r/en-US/u | Vivado | 2024.1 | | Vitis Classic | 2024.1 | -# Zynq MPSoC/RFSoC 动态 DDR 配置简介 +# Zynq MPSoC / RFSoC 动态 DDR 配置简介 -Zynq MPSoC/RFSoC 动态 DDR 配置具有如下特性: +Zynq MPSoC / RFSoC 动态 DDR 配置具有如下特性: - 无需在 Vivado 中进行改动即可更换 DIMM,并使用动态 DDR 配置初始化 DDR; - 支持 DDR3 和 DDR4 DIMM; @@ -61,7 +61,7 @@ Zynq MPSoC/RFSoC 动态 DDR 配置具有如下特性: {% note warning %} -**注**:动态 DDR 配置功能仅可用于 PS DIMM DDR,不支持颗粒 DDR。 +动态 DDR 配置功能仅可用于 PS DIMM DDR,不支持颗粒 DDR。 {% endnote %} @@ -71,19 +71,19 @@ Zynq MPSoC/RFSoC 动态 DDR 配置具有如下特性: 在使用动态 DDR 配置之前,需要在如[图 1](#图1) 的 Vivado 的 PCW GUI 中启用 DDR 控制器,且将“DDR Controller Options”部分设置为: -- Memory Type - DDR4 or DDR3 -- Components - UDIMM or RDIMM -- ECC - Enabled or Disabled -- Effective DRAM Bus Width - 64 Bit +- Memory Type:DDR4 或 DDR3 +- Components:UDIMM 或 RDIMM +- ECC:Enabled 或 Disabled +- Effective DRAM Bus Width:64 Bit ![图 1. Zynq UltraScale+ MPSoC 配置 GUI](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-010-ZynqGui.png) -动态 DDR 配置将自动设置“DDR Memory Option”部分的所有参数,如下表。 +动态 DDR 配置将自动读取 SPD 表,并设置“DDR Memory Option”部分的所有参数,如下表。 -| **Option** | **Value** | **Option** | **Value** | -| ------------------------------- | --------- | ------------------------------- | --------- | +| Option | Value Example | Option | Value Example | +| -------------- | --------- | -------------- | --------- | | Speed Bin (Use Tooltip) | DDR42133P | DRAM IC Bus Width (per die) | 8 Bits | | Cas Latency | 15 | DRAM Device Capacity(per die) | 4096 MBits | | RAS to CAS Delay (Cycles) | 15 | Bank Group Address Count (Bits) | 2 | @@ -94,10 +94,10 @@ Zynq MPSoC/RFSoC 动态 DDR 配置具有如下特性: | tFAW (ns) | 21 | DDR Size (in hexa) | 0XFFFFFFFF (4GB) | | Additive Latency (Cycles) | 0 | | | -而中“Other Options”部分的所有值都需要用户根据需要设置,无法从 SPD 表中获得,如下表。 +而“Other Options”部分的所有值都需要用户根据需要设置,无法从 SPD 表中获得,如下表。 -| **Option** | **Value** | **Option** | **Value** | -| ------------------------ | ------------ | ----------------------------- | ----------------- | +| Option | Value Example | Option | Value Example | +| -------------- | --------- | -------------- | --------- | | Memory Address Map | ROW BANK COL | Power Mode Settings | Power Down Enable | | Data Mask and DBI | DM NO DBI | Clock Stop | | Address Mirroring | | **Refresh Mode Settings** | @@ -109,7 +109,7 @@ Zynq MPSoC/RFSoC 动态 DDR 配置具有如下特性: ## 启用动态 DDR 配置功能 -要动态 DDR 配置功能,需要在 Vivado 中使用 Tcl 命令将参数 `CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN` 置为 1: +要启用动态 DDR 配置功能,需要在 Vivado 中使用 TCL 命令将参数 `CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN` 置为 1: ``` tcl set_property CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN 1 [get_bd_cells /zynq_ultra_ps_e] @@ -121,11 +121,11 @@ set_property CONFIG.PSU_DYNAMIC_DDR_CONFIG_EN 1 [get_bd_cells /zynq_ultra_ps_e] ![图 2. Block Design 整体](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-020-BlockDesign.png) -然后生成 output products 即可(若除 PS 处理器外还有其他逻辑,则需要重新生成比特流)。FSBL 将会在启动过程中使用该参数,并执行动态 DDR 配置。 +然后重新生成 Output Products 即可(若除 PS 处理器外还有其他逻辑,则需要重新生成比特流)。FSBL 将会在启动过程中使用该参数,并执行动态 DDR 配置。 {% note info %} -**注**:如果设置了上述参数却出现了如下警告,是因为 GUI 中 DDR 类型必须为 UDIMM 或 RDIMM,不能为 Component。 +如果设置了上述参数却出现了如下警告,是因为 GUI 中 DDR 类型必须为 UDIMM 或 RDIMM,不能为 Component。 ``` plain WARNING: [BD 41-721] Attempt to set value '1' on disabled parameter 'PSU_DYNAMIC_DDR_CONFIG_EN' of cell '/zynq_ultra_ps_e_0' is ignored @@ -135,17 +135,17 @@ WARNING: [BD 41-721] Attempt to set value '1' on disabled parameter 'PSU_DYNAMIC ## I2C 硬件要求 -由于动态 DDR 配置需要在 FSBL 中使用 I2C 读取 DDR SPD EEPROM 中的数据,而在 Xilinx 自动生成 FSBL 中,I2C 读取 DDR SPD EEPROM 的方式不变的,因此**若不想对生成的 FSBL 进行修改,则需要在硬件上适配 FSBL**。 +由于动态 DDR 配置需要在 FSBL 中使用 I2C 读取 DDR SPD EEPROM 中的数据,而在 Xilinx 自动生成 FSBL 中,I2C 读取 DDR SPD EEPROM 的方式是固定的,因此**若不想对生成的 FSBL 进行修改,则需要在硬件上适配 FSBL**。 Xilinx FSBL 使用 I2C1(1 号 I2C 控制器),借助一个 I2C Mux 与 SPD EEPROM 进行通信,使用的地址为: -- I2C Mux 地址 = 0x75 -- I2C Slave 地址 = 0b1010001 (0x51) -- SODIMM SA[2:0] = 0b001 +- I2C Mux 地址: 0x75 +- I2C Slave 地址: 0b1010001 (0x51) +- SODIMM SA[2:0]: 0b001 {% note info %} -**注**:从 Vivado 2019.1 开始,动态 DDR 配置对于所有使用 DIMM DDR 的 Zynq MPSoC 评估板均启用,在使用预置硬件配置时无需额外用户操作。 +从 Vivado 2019.1 开始,动态 DDR 配置对于所有使用 DIMM DDR 的 Zynq MPSoC / RFSoC 评估板均启用,在使用预置硬件配置时无需额外用户操作。 {% endnote %} @@ -153,27 +153,25 @@ Xilinx FSBL 使用 I2C1(1 号 I2C 控制器),借助一个 I2C Mux 与 SPD 若 I2C 硬件连接不满足上述要求,还可以按照实际连接关系修改 FSBL。FSBL 中使用 I2C 读取 DDR SPD EEPROM 的函数为 `u32 XFsbl_IicReadSpdEeprom(u8 *SpdData)`。 -``` C +``` c xfsbl_ddr_init.c u32 XFsbl_DdrInit(void) { // ... - /* Get the Model Part Number from the SPD stored in EEPROM */ Status = XFsbl_IicReadSpdEeprom(SpdData); if (Status != XFSBL_SUCCESS) { Status = XFSBL_FAILURE; goto END; } - // ... } ``` -下面对函数进行拆解,其是注释已经能够很清楚了。 +下面对函数进行拆解,结合注释可以更好理解操作的过程。 ### 初始化 I2C 控制器 -首先对 I2C 控制器 I2C1 进行初始化。注意从 Vivado/Vitis 2023.2 版本开始,不再依赖于设备的 Device ID 来寻找设备了,而是只是用基地址 Base Address,少了从 Device ID 到 Base Address 这一步操作,从开发的角度来看更为合理了。 +首先对 I2C 控制器 I2C1 进行初始化。值得一提的是,从 Vivado / Vitis 2023.2 版本开始,对设备进行寻址时,不再依赖于设备的 Device ID,而是直接使用基地址 Base Address,少了从 Device ID 到 Base Address 这一步操作,从开发的角度来看更为合理了。 {% note info %} @@ -181,7 +179,7 @@ u32 XFsbl_DdrInit(void) {% endnote %} -``` C +``` c xfsbl_ddr_init.c static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData) { // ... @@ -216,9 +214,9 @@ static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData) ### 选择 I2C Mux 的 Slave -由于开发板会有较多的 I2C 外设,而 Zynq MPSoC/RFSoC 搭载的 I2C 控制器数量有限,因此需要通过 I2C Mux 来扩展所连 I2C Slave 的数量。 +由于开发板搭载了较多 I2C 外设,而 Zynq MPSoC / RFSoC 的 I2C 控制器数量有限,因此需要通过 I2C Mux 来扩展所连 I2C Slave 的数量。 -本板卡 I2C1 原理图如[图 3](#图3),所用 I2C Mux 的型号为 TCA9548A,其地址选择方式如[图 4](#图4),Slave 选择方式如[图 5](#图5),和评估板保持一致,因此可以与自动生成的 FSBL 兼容。 +本板卡 I2C1 原理图如[图 3](#图3),所用 I2C Mux 的型号为 TCA9548A,其地址配置方式如[图 4](#图4),Slave 选择方式如[图 5](#图5),这里均和评估板保持一致,因此可以与自动生成的 FSBL 兼容。 结合[图 3](#图3) 和[图 4](#图4) 可知 I2C Mux 的地址为 `0x75`,从[图 3](#图3) 中可知 PS DDR4 SODIMM 的 I2C 连接在了第 3 号 Slave 的位置,因此按照[图 5](#图5) 需要将 B3 置 1,也即需要向地址为 `0x75` 的 I2C Mux TCA9548A 的控制寄存器中写入 `0x08`。 @@ -228,23 +226,23 @@ static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData) -![图 4. TCA9548A 地址选择](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-040-tca9548aAddress.png){width=600px} +![图 4. TCA9548A 地址配置](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-040-tca9548aAddress.png){width=600px} ![图 5. TCA9548A Slave选择](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-050-tca9548aConfig.png){width=1000px} -按照上述分析,下面的代码就不难理解了,首先向地址为 `XFSBL_MUX_ADDR` 的 I2C Mux 写入选通配置 `0x08`,然后从同样地地址回读,验证配置是否正确。 +按照上述分析,下面的代码就不难理解了,首先向地址为 `XFSBL_MUX_ADDR`(默认为 `0x75`)的 I2C Mux 写入选通配置 `0x08`,然后从同样的地址回读,验证配置是否正确。 {% note info %} - 若设计中没有使用到 I2C Mux,而是直接将 I2C 控制器连接到了 DIMM,则可以删去这部分代码; - 若设计中 I2C Mux 地址不同,则可以修改 `XFSBL_MUX_ADDR` 的宏定义; -- 若设计中 I2C Mux 连接的 Slave 不同,可以修改 `TxArray`。 +- 若设计中 I2C Mux 连接的 Slave 不同,可以修改 I2C 发送的 `TxArray`。 {% endnote %} -``` C +``` c xfsbl_ddr_init.c static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData) { // ... @@ -290,7 +288,21 @@ static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData) ### 读取 EEPROM 的第一页 -``` C +配置完 I2C Mux 后,即可开始读取 SPD EEPROM 中的内容了。[图 6](#图6) 给出了 EEPROM 支持的指令表,由于 EEPROM 一次读的最大长度为一页,也即一个 Page,因此需要分两次对其中的两个 Page 进行读取。 + + + +![图 6. DDR4 SPD EEPROM 指令表](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-060-DDR4SPDAddress.png){width=800px} + +首先设置 Page Address 为 0,也即向地址 `0x36` 中写入 `0x00`,表示从 Page 0 中进行读取,一次读取 256 Byte。 + +{% note info %} + +通常 SPD EEPROM 的 Page 选择地址是固定的,如果 Page Address 0 的地址有变更,修改 `XFSBL_SODIMM_CONTROL_ADDR_LOW` 的宏定义即可。 + +{% endnote %} + +``` c xfsbl_ddr_init.c static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData) { // ... @@ -357,7 +369,15 @@ static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData) ### 读取 EEPROM 的第二页 -``` C +然后设置 Page Address 为 1,也即向地址 `0x37` 中写入 `0x00`,表示从 Page 0 中进行读取,一次读取 256 Byte。 + +{% note info %} + +通常 SPD EEPROM 的 Page 选择地址是固定的,如果 Page Address 1 的地址有变更,修改 `XFSBL_SODIMM_CONTROL_ADDR_HIGH` 的宏定义即可。 + +{% endnote %} + +``` c xfsbl_ddr_init.c static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData) { // ... @@ -422,6 +442,38 @@ static u32 XFsbl_IicReadSpdEeprom(u8 *SpdData) } ``` +# 调试 + +配置完成后可以实测了,这里对 FSBL 进行 Debug,观察整个读写的过程。在单独调试 FSBL 的时候,可以不勾选“Program FPGA”和“Initialize using FSBL”,如[图 7](#图7)。 + + + +![图 7. Debug 配置](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-070-DebugConfig.png) + +将断点设置在函数 `XFsbl_IicReadSpdEeprom()` 被调用的地方。 + + + +![图 8. `XFsbl_IicReadSpdEeprom()` 函数断点](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-080-Breakpoint.png) + +观察 I2C Mux 回读的数据。回读的数据存储在 `SpdData` 数组中,可以观察到数组的第 0 个字节为 `0x08`,与写入的数据一致。 + + + +![图 9. I2C Mux 回读](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-090-IICMuxRead.png) + +然后观察 I2C EEPROM 回读的数据,并与 Micron 给出的 [MTA4ATF51264HZ-2G6E1 的 SPD 数据][]进行对比,可以观察到数据是一致的。 + + + +![图 10. I2C EEPROM 回读](../images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-100-IICEEPROMRead.png) + +最后,`XFsbl_DdrInit()` 函数的剩余部分会完成 DDR 参数的解析与 DDR 控制器的初始化。 + # 参考文档 [75768 - Zynq MPSoC Dynamic DDR Configuration Support for DIMM Devices](https://support.xilinx.com/s/article/75768) + +[SPD I2c Address for DDR4 SODIMM](https://electronics.stackexchange.com/questions/554703/spd-i2c-address-for-ddr4-sodimm) + +[MTA4ATF51264HZ-2G6E1 的 SPD 数据]: https://www.micron.com/products/memory/dram-modules/sodimm/part-catalog/part-detail/spd-data/mta4atf51264hz-2g6e1 diff --git a/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-060-DDR4SPDAddress.png b/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-060-DDR4SPDAddress.png new file mode 100644 index 0000000000000000000000000000000000000000..0a143842b77e902fc7e1bccfdd698d7516e5f0f7 GIT binary patch literal 345709 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