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 0000000..0a14384 Binary files /dev/null and b/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-060-DDR4SPDAddress.png differ diff --git a/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-070-DebugConfig.png b/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-070-DebugConfig.png new file mode 100644 index 0000000..3ae3a46 Binary files /dev/null and b/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-070-DebugConfig.png differ diff --git a/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-080-Breakpoint.png b/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-080-Breakpoint.png new file mode 100644 index 0000000..a7ecc56 Binary files /dev/null and b/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-080-Breakpoint.png differ diff --git a/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-090-IICMuxRead.png b/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-090-IICMuxRead.png new file mode 100644 index 0000000..d0d721c Binary files /dev/null and b/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-090-IICMuxRead.png differ diff --git a/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-100-IICEEPROMRead.png b/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-100-IICEEPROMRead.png new file mode 100644 index 0000000..d6a0d8f Binary files /dev/null and b/source/images/post/2024-06-27-zynq-mpsoc-ddr-spd/2024-06-27-zynq-mpsoc-ddr-spd-100-IICEEPROMRead.png differ