JEDEC DDR5 SPD Hub Devices例程
DDR5生态系统的核心是SidebandBus Protocol
参考下图,可以将SV4E-I3C的端口1声明为主服务器(模拟主机控制器),并且它可以属于SV4E-I3C上的一个总线。端口2可以作为SPD Hub DUT的Local Bus侧的从站连接。这个从站可以被编程来模拟,端口2属于SV4E-I3C上的第二个总线,并且独立于端口1进行编程。SV4E-I3C的端口3和4也可以连接到SPD集线器的本地总线侧,它们可以用来模拟PMIC和/或RCD设备。这些端口属于SV4E-I3C上的同一第二条总线。这些端口的可用性为SPD Hub执行地址修改等功能提供了完整的覆盖范围。
图片来源《EN-W002E-E-21090-Component-Validation-of-JEDEC-DDR5-SPD-Hub-Devices》
以下所有例程,SV4E-I3C设备连接器件均为SPD5芯片,Reg表示MR寄存器,Mem表示NVM存储器
1、I2C模式读Reg
SV4E-I3C设备在i2c模式下读SPD5的Reg(MR寄存器),Python代码如下:
i3cDataCapture.start()
sidebandBusController.setup()
regAddr = 0x00
byte_num = 64
sidebandBusController.enableLowBitRateMode()
bytesFromTarget = sidebandBusController.spdLegacyReadReg('DIMM0-SPD', regAddr, numBytes = byte_num, twoByteAddressing=False)
for value in range(int(regAddr),int(byte_num+regAddr)):print("regAddr: 0x%02X mrbyte: 0x%02X" % (value, bytesFromTarget[(value-(int(regAddr)))]))
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图,LOG区域已经打印运行结果:
打开生成的波形结果,如图:
2、I3C模式读Reg
SV4E-I3C设备在i3c模式下读SPD5的Reg(MR寄存器),Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
regAddr = 0x00
byte_num = 64
sidebandBusController.enableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
bytesFromTarget = sidebandBusController.spdReadReg('DIMM0-SPD', regAddr, numBytes = byte_num)
for value in range(int(regAddr),int(byte_num+regAddr)):print("regAddr: 0x%02X mrbyte: 0x%02X" % (value, bytesFromTarget[(value-(int(regAddr)))]))
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,LOG区域已经打印运行结果,如图所示:
打开生成的波形结果,如图:
3、使能ENEC+获取器件状态
3、4、5部分的工作主要是测试SV4E-I3C设备的PEC注错功能,PEC注错方式有多种,这里仅对sidebandBusController.startPecErrorInjection()进行测试,首先使能ENEC,但是pecEnable为False(如图sidebandBusController部分的参数设置),Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.initializeBus()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('ENEC', cccDefiningBytes = [0x01])
if status == True:svt.printMsg('ENEC CCC PASS', 'green')
else:svt.printMsg('ENEC CCC FAIL', 'red')
targetAddr = 'DIMM0-SPD'
regAddr = 0x0C
dataByte = 0x01 # one byte
status = sidebandBusController.spdWriteReg(targetAddr, regAddr, dataByte)
if status == True:svt.printMsg('spdWriteReg PASS', 'green')
else:svt.printMsg('spdWriteReg FAIL', 'red')
statusTuple = sidebandBusController.getTargetStatus('DIMM0-SPD')
if statusTuple is not None:(pecErr, protocolErr, pendingInterrupt) = statusTupleprint("pecErr: 0x%02X protocolErr: 0x%02X pendingInterrupt: 0x%02X" % (pecErr, protocolErr, pendingInterrupt))
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图:
打开生成的波形结果,如图:
4、使能ENEC+使能PEC+获取器件状态
接下来,pecEnable为True(如图sidebandBusController部分的参数设置),Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.initializeBus()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('ENEC', cccDefiningBytes = [0x01])
if status == True:svt.printMsg('ENEC CCC PASS', 'green')
else:svt.printMsg('ENEC CCC FAIL', 'red')
targetAddr = 'DIMM0-SPD'
regAddr = 0x0C
dataByte = 0x01 # one byte
status = sidebandBusController.spdWriteReg(targetAddr, regAddr, dataByte)
if status == True:svt.printMsg('spdWriteReg PASS', 'green')
else:svt.printMsg('spdWriteReg FAIL', 'red')
statusTuple = sidebandBusController.getTargetStatus('DIMM0-SPD')
if statusTuple is not None:(pecErr, protocolErr, pendingInterrupt) = statusTupleprint("pecErr: 0x%02X protocolErr: 0x%02X pendingInterrupt: 0x%02X" % (pecErr, protocolErr, pendingInterrupt))
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
代码没有改变,点击Run运行,如图:
打开生成的波形结果,对比与刚刚生成的结果,由于使能PEC,故结果中包含pec byte:
5、使能ENEC+使能PEC+注入PEC错误+获取器件状态
然后开始注入PEC error,Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.initializeBus()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('ENEC', cccDefiningBytes = [0x01])
if status == True:svt.printMsg('ENEC CCC PASS', 'green')
else:svt.printMsg('ENEC CCC FAIL', 'red')
sidebandBusController.startPecErrorInjection()
targetAddr = 'DIMM0-SPD'
regAddr = 0x0C
dataByte = 0x01 # one byte
status = sidebandBusController.spdWriteReg(targetAddr, regAddr, dataByte)
if status == True:svt.printMsg('spdWriteReg PASS', 'green')
else:svt.printMsg('spdWriteReg FAIL', 'red')
sidebandBusController.stopPecErrorInjection()
statusTuple = sidebandBusController.getTargetStatus('DIMM0-SPD')
if statusTuple is not None:(pecErr, protocolErr, pendingInterrupt) = statusTupleprint("pecErr: 0x%02X protocolErr: 0x%02X pendingInterrupt: 0x%02X" % (pecErr, protocolErr, pendingInterrupt))
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图,LOG区域已经打印运行结果:
打开生成的波形结果,如图,在写Reg时注入错误的PEC byte:
ibi payload自动完成,如图所示:
6、使能ENEC+未注入parity错误+获取器件状态
6、7部分的工作主要是测试SV4E-I3C设备的parity注错功能,这里对sidebandBusController.startErrorInjection(errorSpecs)进行测试,首先是未进行parity注错,Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.enableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('ENEC', cccDefiningBytes = [0x01])
if status == True:svt.printMsg('ENEC CCC PASS', 'green')
else:svt.printMsg('ENEC CCC FAIL', 'red')
bytesFromTarget = sidebandBusController.spdWriteReg('DIMM0-SPD', 0x00,0x00)
statusTuple = sidebandBusController.getTargetStatus('DIMM0-SPD')
if statusTuple is not None:(pecErr, protocolErr, pendingInterrupt) = statusTupleprint("pecErr: 0x%02X protocolErr: 0x%02X pendingInterrupt: 0x%02X" % (pecErr, protocolErr, pendingInterrupt))
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图,LOG区域已经打印运行结果:
打开生成的波形结果,如图:
7、使能ENEC+注入parity错误+获取器件状态
注入parity错误,Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.enableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('ENEC', cccDefiningBytes = [0x01])
if status == True:svt.printMsg('ENEC CCC PASS', 'green')
else:svt.printMsg('ENEC CCC FAIL', 'red')
errorSpecs = [ (2, 3) ]
sidebandBusController.startErrorInjection(errorSpecs)
bytesFromTarget = sidebandBusController.spdWriteReg('DIMM0-SPD', 0x00,0x00)
sidebandBusController.stopErrorInjection()
statusTuple = sidebandBusController.getTargetStatus('DIMM0-SPD')
if statusTuple is not None:(pecErr, protocolErr, pendingInterrupt) = statusTupleprint("pecErr: 0x%02X protocolErr: 0x%02X pendingInterrupt: 0x%02X" % (pecErr, protocolErr, pendingInterrupt))
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图:
打开生成的波形结果,如图,写Reg注入parity error,ibi payload自动完成:
8、使能ENEC+注入parity错误+读Reg+ibiResponse(ackAndDisable)+获取器件状态
8、9部分的工作主要是测试SV4E-I3C设备的ibiResponse设置,首先controllerParams部分ibiResponse设置为ackAndDisable,Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.enableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('ENEC', cccDefiningBytes = [0x01])
if status == True:svt.printMsg('ENEC CCC PASS', 'green')
else:svt.printMsg('ENEC CCC FAIL', 'red')
errorSpecs = [ (2, 3) ]
sidebandBusController.startErrorInjection(errorSpecs)
bytesFromTarget = sidebandBusController.spdWriteReg('DIMM0-SPD', 0x00,0x00)
sidebandBusController.stopErrorInjection()
bytesFromTarget = sidebandBusController.spdReadReg('DIMM0-SPD', 0x30, numBytes = 5)
for value in range(int(0x30),int(5+0x30)):print("regAddr: 0x%02X mrbyte: 0x%02X" % (value, bytesFromTarget[(value-(int(0x30)))]))
statusTuple = sidebandBusController.getTargetStatus('DIMM0-SPD')
if statusTuple is not None:(pecErr, protocolErr, pendingInterrupt) = statusTupleprint("pecErr: 0x%02X protocolErr: 0x%02X pendingInterrupt: 0x%02X" % (pecErr, protocolErr, pendingInterrupt))
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图,LOG区域已经打印运行结果:
打开生成的波形结果,如图,注意与下个波形结果进行对比:
9、使能ENEC+注入parity错误+读Reg+ibiResponse(ackAndProceed)+获取器件状态
controllerParams部分ibiResponse设置为ackAndProceed,Python代码未改变,如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.enableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('ENEC', cccDefiningBytes = [0x01])
if status == True:svt.printMsg('ENEC CCC PASS', 'green')
else:svt.printMsg('ENEC CCC FAIL', 'red')
errorSpecs = [ (2, 3) ]
sidebandBusController.startErrorInjection(errorSpecs)
bytesFromTarget = sidebandBusController.spdWriteReg('DIMM0-SPD', 0x00,0x00)
sidebandBusController.stopErrorInjection()
bytesFromTarget = sidebandBusController.spdReadReg('DIMM0-SPD', 0x30, numBytes = 5)
for value in range(int(0x30),int(5+0x30)):print("regAddr: 0x%02X mrbyte: 0x%02X" % (value, bytesFromTarget[(value-(int(0x30)))]))
statusTuple = sidebandBusController.getTargetStatus('DIMM0-SPD')
if statusTuple is not None:(pecErr, protocolErr, pendingInterrupt) = statusTupleprint("pecErr: 0x%02X protocolErr: 0x%02X pendingInterrupt: 0x%02X" % (pecErr, protocolErr, pendingInterrupt))
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
点击Run运行,如图:
打开生成的波形结果,如图:
10、I2C模式写Reg
SV4E-I3C设备在i2c模式下写SPD5的Reg(MR寄存器),Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
regAddr = 0x00
dataByte = 0x00
sidebandBusController.enableLowBitRateMode()
status = sidebandBusController.spdLegacyWriteReg('DIMM0-SPD', regAddr, dataByte, twoByteAddressing=False)
if status == True:svt.printMsg('spdLegacyWriteReg PASS', 'green')
else:svt.printMsg('spdLegacyWriteReg FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图:
打开生成的波形结果,如图:
11、I2C模式写Mem
SV4E-I3C设备在i2c模式下写SPD5的Mem(NVM寄存器),Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.enableLowBitRateMode()
memBlock = 0x00
data16Bytes = []
for datanum in range(16):data16Bytes.append(0xFF)
for block in range(16):for addr in range(4):status = sidebandBusController.spdLegacyWriteMem('DIMM0-SPD', memBlock, 0x00, data16Bytes)if status == True:print("memBlock: %d write 0x%02X PASS" % (block,data16Bytes[0]))else:print("memBlock: %d write 0x%02X FAIL" % (block,data16Bytes[0]))
memBlock = memBlock + 1
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图,LOG区域已经打印运行结果:
打开生成的波形结果,如图:
12、I2C模式读Mem
SV4E-I3C设备在i2c模式下读SPD5的Mem(NVM寄存器),Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.enableLowBitRateMode()
memBlock = 0x00
for block in range(16):
bytesFromTarget = sidebandBusController.spdLegacyReadMem('DIMM0-SPD', memBlock, 0x00, numBytes = 64, twoByteAddressing=False)for value in range(64):print("memBlock: %d memAddr: 0x%02X mrbyte: 0x%02X" % (block, value, bytesFromTarget[value]))
memBlock = memBlock + 1
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图,LOG区域已经打印运行结果:
打开生成的波形结果,如图:
13、I3C模式读Reg
SV4E-I3C设备在i3c模式下读SPD5的Reg(MR寄存器),Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
regAddr = 0x00
byte_num = 64
sidebandBusController.enableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
bytesFromTarget = sidebandBusController.spdReadReg('DIMM0-SPD', regAddr, numBytes = byte_num)
for value in range(int(regAddr),int(byte_num+regAddr)):print("regAddr: 0x%02X mrbyte: 0x%02X" % (value, bytesFromTarget[(value-(int(regAddr)))]))
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图,LOG区域已经打印运行结果:
打开生成的波形结果,如图:
14、I3C模式写Reg
SV4E-I3C设备在i3c模式下写SPD5的Reg(MR寄存器),Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.enableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
regAddr = 0x00
dataByte = 0x00
status = sidebandBusController.spdWriteReg('DIMM0-SPD', regAddr, dataByte)
if status == True:svt.printMsg('spdWriteReg PASS', 'green')
else:svt.printMsg('spdWriteReg FAIL', 'red')
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图,LOG区域已经打印运行结果:
打开生成的波形结果,如图:
15、I3C模式写Mem
SV4E-I3C设备在i3c模式下写SPD5的Mem(NVM寄存器),Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.enableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:svt.printMsg('SETAASA CCC PASS', 'green')
else:svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
memBlock = 0x00
data16Bytes = []
for datanum in range(16):data16Bytes.append(0xFF)
for block in range(16):for addr in range(4):status = sidebandBusController.spdWriteMem('DIMM0-SPD', memBlock, 0x00, data16Bytes)if status == True:print("memBlock: %d write 0x%02X PASS" % (block,data16Bytes[0]))else:print("memBlock: %d write 0x%02X FAIL" % (block,data16Bytes[0]))
memBlock = memBlock + 1
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:svt.printMsg('RSTDAA CCC PASS', 'green')
else:svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图,LOG区域已经打印运行结果:
打开生成的波形结果,如图:
16、I3C模式读Mem
SV4E-I3C设备在i3c模式下读SPD5的Mem(NVM寄存器),Python代码如下:
import dftm.svt as svt
i3cDataCapture.start()
sidebandBusController.setup()
sidebandBusController.enableLowBitRateMode()
status = sidebandBusController.doBroadcastWrite('SETAASA')
if status == True:
svt.printMsg('SETAASA CCC PASS', 'green')
else:
svt.printMsg('SETAASA CCC FAIL', 'red')
sidebandBusController.disableLowBitRateMode()
memBlock = 0x00
for block in range(16):
bytesFromTarget = sidebandBusController.spdReadMem('DIMM0-SPD', memBlock, 0x00, numBytes = 64)for value in range(64):
print("memBlock: %d memAddr: 0x%02X mrbyte: 0x%02X" % (block, value, bytesFromTarget[value]))
memBlock = memBlock + 1
status = sidebandBusController.doBroadcastWrite('RSTDAA')
if status == True:
svt.printMsg('RSTDAA CCC PASS', 'green')
else:
svt.printMsg('RSTDAA CCC FAIL', 'red')
i3cDataCapture.stop()
Procedure区域编辑代码,点击Run运行,如图,LOG区域已经打印运行结果:
打开生成的波形结果,如图:
上述程序可能存在少量错误和可优化的地方,后续博文将进行修改和优化
希望本文对大家有帮助,上文若有不妥之处,欢迎指正
分享决定高度,学习拉开差距