External Memory Interfaces Agilex™ 7 F-Series and I-Series FPGA IP User Guide

ID 683216
Date 9/19/2024
Public
Document Table of Contents

11.10.5. Example: Reading Calibration Results and Margins with the On-Chip Debug Port

This example provides instructions for reading calibration results and margins using the on-chip debug port.

The values in the example below are for illustrative purposes and are obtained from an EMIF example design using DDR4 RDIMM x72, implemented on the Intel® Agilex™ 7 F-Series FPGA Development Kit.

  1. Assume that you obtain the following data from the Global Parameter Table (GPT):
    Address Field Name Value
    0x500_0000 gpt_GLOBAL_PAR_VER 0x00000002
    0x500_0004 gpt_NIOS_C_VER 0x00000001
    0x500_0008 gpt_COLUMN_ID 0x00000001
    0x500_000c gpt_NUM_IOPACKS 0x00000010
    0x500_0010 gpt_NIOS_CLK_FREQ_KHZ 0x0003D090
    0x500_0014 gpt_PARAM_TABLE_SIZE 0x000001A0
    0x500_0018 gpt_RESERVED 0x00000008
    0x500_001c gpt_GLOBAL_CAL_CONFIG 0x00000505
    0x500_0020 gpt_SLAVE_CLK_DIVIDER 0x0000001C
    0x500_0024 gpt_INTERFACE_PAR_PTRS_0 0x00000064
    0x500_0028 gpt_INTERFACE_PAR_PTRS_1 0x00000000
    0x500_002c gpt_INTERFACE_PAR_PTRS_2 0x00000000
    0x500_0030 gpt_INTERFACE_PAR_PTRS_3 0x00000000
    0x500_0034 gpt_INTERFACE_PAR_PTRS_4 0x00000000
    0x500_0038 gpt_INTERFACE_PAR_PTRS_5 0x00000000
    0x500_003c gpt_INTERFACE_PAR_PTRS_6 0x00000000
    0x500_0040 gpt_INTERFACE_PAR_PTRS_7 0x00000000
    0x500_0044 gpt_INTERFACE_PAR_PTRS_8 0x00000000
    0x500_0048 gpt_INTERFACE_PAR_PTRS_9 0x00000000
    0x500_004c gpt_INTERFACE_PAR_PTRS_10 0x00000000
    0x500_0050 gpt_INTERFACE_PAR_PTRS_11 0x00000000
    0x500_0054 gpt_INTERFACE_PAR_PTRS_12 0x00000000
    0x500_0058 gpt_INTERFACE_PAR_PTRS_13 0x00000000
    0x500_005c gpt_INTERFACE_PAR_PTRS_14 0x00000000
    0x500_0060 gpt_INTERFACE_PAR_PTRS_15 0x00000000
  2. Determine the base address for the per-interface parameter table. There is only one EMIF interface in the I/O row, because only one gpt_INTERFACE_PAR_PTRS has a non-zero value.

    The base address for the per-interface parameter table = 0x500_0000 + 0x64 = 0x500_0064.

  3. Read the per-interface parameter table starting from its base address of 0x500_0064. The content of the per-interface parameter table is shown below.
    Address Field Name Value
    Bit [31:24] Bit [23:16] Bit [15:8] Bit [7:0]
    0x500_0064 pt_INTERFACE_PAR_VER pt_IP_VER 0x00024C40
    0x500_0068 pt_UNUSED pt_DEBUG_DATA_PTR 0x000001A0
    0x500_006C pt_RESERVED pt_ CONTROLLER_ TYPE pt_ DIMM_ TYPE pt_ MEMORY_ TYPE 0x00000201
    0x500_0070 pt_AFI_CLK_FREQ_KHZ 0x000411AC
    0x500_0074 pt_ NUM_ RANKS pt_ WRITE_ LATENCY pt_ READ_ LATENCY pt_ BURST_ LEN 0x01121708
    0x500_0078 pt_ NUM_ DQ pt_ NUM_ DQS_RD pt_ NUM_ DQS_WR pt_ NUM_ DIMMS 0x48090901
    0x500_007C pt_CS_WIDTH pt_BANK_ WIDTH pt_ADDR_ WIDTH pt_NUM_DM 0x01021109
    0x500_0080 pt_BANK_ GROUP_ WIDTH pt_C_WIDTH pt_ODT_ WIDTH pt_CKE_ WIDTH 0x02000101
    0x500_0084 pt_NUM_ LRDIMM_CFG pt_CAL_ DATA_SIZE pt_CK_WIDTH pt_ADDR_ MIRROR 0x05140100
    0x500_0088 pt_NUM_ DATA_LANES pt_NUM_ CA_LANES pt_NUM_ CENTERS pt_NUM_AC_ ROM_ENUMS 0x09040434
    0x500_008C pt_ODT_TABLE_LO 0x00000004
    0x500_0090 pt_ODT_TABLE_HI 0x00000000
    0x500_0094 pt_RESERVED 0x0D00C081
    0x500_0098 pt_CAL_DATA_PTR pt_RESERVED 0x00B00000
    0x500_009C pt_DBG_SKIP_RANKS 0x00000000
    0x500_00A0 pt_DBG_SKIP_GROUPS 0x00000000
    0x500_00A4 pt_DBG_SKIP_STEPS 0x00670000
    0x500_00A8 pt_TILE_ID_PTR pt_NUM_DIMM pt_NUM_MR 0x00C4070C
    0x500_00AC pt_MR_PTR pt_PIN_ADDR_PTR 0x017000D8
  4. Determine the base address for debug_data_structure.
    Base address for debug_data_struct = 0x500_0000 + pt_DEBUG_DATA_PTR
                                       = 0x500_0000 + 0x1A0
                                       = 0x500_01A0
  5. Read the debug_data_struct starting from its base address of 0x500_01A0. Below is the content for the debug_data_struct:
    Address Parameter Value
    0x500_01A0 data_size 0x00000000
    0x500_01A4 status 0x00000006
    0x500_01A8 requested_command 0x000003E8
    0x500_01AC command_status 0x00000000
    0x500_01B0 command_parameters[0] 0x00000000
    0x500_01B4 command_parameters[1] 0x00000000
    0x500_01B8 command_parameters[2] 0x00000000
    0x500_01BC command_parameters[3] 0x00000000
    0x500_01C0 mem_summary_report_pointer 0x05000354
    0x500_01C4 mem_cal_report_pointer 0x050003A0
  6. Read the memory_summary_report from the address starting at 0x500_0354.
    • Read from report_flags (address = 0x500_0358). Ensure the LSB of the readdata is 1’b1 (indicating that the calibration report is ready), before reading the other members in the memory_summary_report structure or the mem_cal_report structure.
    • In this example, error_stage, error_group and error_code are all 0, because the calibration is successful.
    Address Parameter Value
    0x5000354 data_size 0x00000013
    0x5000358 report_flags 0x01000001
    0x5000360 error_stage 0x00000000
    0x5000364 error_group 0x00000000
    0x5000368 error_code 0x00000000
    0x500039C in_out_rate 0x00000014
  7. Read the mem_cal_report from the address beginning at 0x500_03A0.
    Address Parameter Value
    0x500_03A0 data_size 0x00000021
    0x500_03A4 debug_cal_data_struct_pointer__cal_data_dq_in 0x05000424
    0x500_03A8 debug_cal_data_struct_pointer__cal_data_dq_out 0x05000544
    0x500_03AC debug_cal_data_struct_pointer__cal_data_dm_dbi_in 0x05000664
    0x500_03B0 debug_cal_data_struct_pointer__cal_data_dm_dbi_out 0x05000688
    0x500_03B4 debug_cal_data_struct_pointer__cal_data_dqs_in 0x050006AC
    0x500_03B8 debug_cal_data_struct_pointer__cal_data_dqs_en 0x050006D0
    0x500_03BC debug_cal_data_struct_pointer__cal_data_dqs_en_b 0x050006F4
    0x500_03C0 debug_cal_data_struct_pointer__cal_data_dqs_out 0x05000718
    0x500_03C4 debug_cal_data_struct_pointer__vrefin 0x0500073C
    0x500_03C8 debug_cal_data_struct_pointer__vrefout 0x05000760
    0x500_03CC debug_cal_data_struct_pointer__cal_data_ca 0x05000784
    0x500_03D4 debug_cal_data_struct_pointer__vfifo* 0x05000878
    0x500_03D8 debug_cal_data_struct_pointer__lfifo* 0x05000884
    0x500_03DC debug_cal_data_struct_pointer__dcc_dq_in* 0x05000890
    0x500_03E0 debug_cal_data_struct_pointer__dcc_dq_out* 0x050008D8
    0x500_03E4 debug_cal_data_struct_pointer__dcc_dm_dbi_in* 0x05000920
    0x500_03E8 debug_cal_data_struct_pointer__dcc_dm_dbi_out* 0x0500092C
    0x500_03EC debug_cal_data_struct_pointer__dcc_dqs_in* 0x05000938
    0x500_03F0 debug_cal_data_struct_pointer__dcc_dqs_out* 0x05000944
    0x500_03F4 debug_cal_data_struct_pointer__dcc_ca* 0x05000950
    0x500_03F8 debug_cal_data_struct_pointer__vrefout_all_ranks* 0x05000984
    0x500_03FC debug_cal_data_struct_pointer__ctle_out* 0x05000990
    0x500_0400 debug_cal_data_struct_pointer__ctle_in_dq* 0x0500099C
    0x500_0404 debug_cal_data_struct_pointer__ctle_in_dqs* 0x050009E4
    0x500_040C write_lat 0x00000005
    0x500_0410 read_lat 0x0000000D
    0x500_0414 rank_skew_data_out 0x00000000
    0x500_0418 rank_skew_dqsen 0x00000000
    0x500_041C extra_rank_delay_any_to_read 0x00000000
    0x500_0420 extra_rank_delay_any_to_write 0x00000000
    Note: * Each address stores the setting for 4 pins or 4 groups.
  8. Read the calibration result for DQ input setting (read path) starting from address 0x0500_0424.
    • The data at address 0x0500_0424 has the calibration result for DQ[0].
    • The data at address 0x0500_0428 has the calibration result for DQ[1].
    • The data at address 0x0500_042C has the calibration result for DQ[2], and so forth.

    For data at each address:

    • Bit[15:0] corresponds to the calibrated setting.
    • Bit[23:16] corresponds to the left edge margin.
    • Bit[31:24] corresponds to the right edge margin.
  9. Repeat step 8 for other pins.
  10. Read the Vrefin setting starting from address 0x0500_073C.
    • The data at address 0x0500_073C has the calibration result for group 0.
    • The data at address 0x0500_0740 has the calibration result for group 1, and so forth.

    For Vrefin/Vrefout calibration setting:

    • Bit[15:8] corresponds to Vref_range:
      • Vref_range =0 means range of 60-92.5% of VCCIO/VREFDQ.
      • Vref_range =1 means range of 45-77.5% of VCCIO/VREFDQ.
    • Bit[7:0] corresponds to Vref_setting where each step is 0.65%.
    For example, in DDR4, VCCIO/VREFDQ is 1.2V. Assuming you obtain 0x122:
    • Vref_range = 0x1
    • Vref_setting =0x22 = 34 (decimal)

    The Vref value in volts = ((34*0.0065) + 0.45) x 1.2V = 0.805V.

  11. Read the mem_summary_report starting from address 0x05000354.
    • The data at 0x5000360 indicates the stage at which calibration first failed. (ENUM_CAL_STAGE).
    • The data at 0x5000364 contains per-group status. Each bit corresponds to a dqs group. If a bit is set 1, then the corresponding group failed in the stage indicated by error_stage.
    • The data at 0x5000368 contains detailed calibration status (ENUM_CAL_ERROR).
  12. For a calibration setting that is stored as 8-bit data (for example, vfifo, lfifo, dcc*, ctle*), each address stores the setting for 4 pins or 4 groups. If you want to read the vfifo setting for this interface implemented in 9 DQS groups, reading the data from address 0x500_0878, 0x500_087C and 0x500_0880 is adequate.
    • Bit [ 7:0] @ address 0x500_0878 = vfifo setting for group 0
    • Bit [15:8] @ address 0x500_0878 = vfifo setting for group 1
    • Bit [23:16] @ address 0x500_0878 = vfifo setting for group 2
    • Bit [31:24] @ address 0x500_0878 = vfifo setting for group 3
    • Bit [ 7:0] @ address 0x500_087C = vfifo setting for group 4
    • Bit [15:8] @ address 0x500_087C = vfifo setting for group 5
    • Bit [23:16] @ address 0x500_087C = vfifo setting for group 6
    • Bit [31:24] @ address 0x500_087C = vfifo setting for group 7
    • Bit [ 7:0] @ address 0x500_0880 = vfifo setting for group 9
  13. All the debug_cal_data is initialized with an all-1 value. Getting an all-1 value for given calibration data (such as dcc-related calibration) means that the value is not overwritten after calibration and you can ignore it.