如何魔改Xilinx Vivado 的MIG IP核

出于科研需求,需要修改DDR4控制器的物理层(PHY Layer)。DDR4控制器代码虽然好找,但是不一定能适配手上的ZCU104;从头开始写一个DDR4控制器工程量太大了,于是决定魔改一下Xilinx官方的MIG IP(v2.2 for Ultrascale+)核。

首先,官方的MIG并没有被lock,是可以看见源码的,也不构成侵权行为,官方论坛甚至也给出了一个修改的方法(https://forums.xilinx.com/t5/Memory-Interfaces-and-NoC/Editing-MIG-IP/td-p/902104)。但是这种修改方法不太适合大规模修改,尤其是在使用ZYNQ时,由于IP本身出于block diagram内,这方法不太适用,因此,需要寻找更彻底的修改方法,及完全重新封装这个IP的源码,毕竟它的源码是完全公开的。

既然源码是公开的,那岂不是先生成一个官方IP再把源码抠出来不就完事了?于是在做出一个官方可用版本后,我把所有源码(除了一些wrapper和simulation用的文件)全部加到了一个新工程里。它的文件结构大致可以用以下表格描述:

  • ddr4_0 //根目录
    • bd_0 // MicroBlaze的block design,主要目的可能是为了封装进elf
      • don't care files
      • bd_45eb.bd
      • bd_45eb_ooc.xdc
    • ip_0
      • don't care files
      • ddr4_microblaze_mcs.xci
    • ip_1
      • par //don't care
      • rtl
        • clocking //生成RXTX_BITSLICE的时钟(PLLE4)的模块
        • iob //生成io buffers的模块
        • ip_top //假顶层,是一个ip_wrapper,实际上没有用
        • map //逻辑向物理的映射文件和用于calibration地址映射文件
        • phy //真正的顶层文件和其下的一个小顶层,主要负责连接iob和RXTX_BITSLICE,并处理对上层的接口
        • xiphy_files //配置RXTX_BITSLICE的文件
      • don't care files
    • par
      • ddr4_0.xdc
    • rtl
      • axi //将AXI FULL向DDR4 PHY层输出的裸接口过渡
      • axi_ctrl //将AXI FULL向DDR4 PHY层输出的裸接口过渡;是一个选择关系,实际上这个文件夹中所有文件都没被用着,都是用的AXI FULL
      • cal //处理calibration以及控制权管理(是calibration控制接口还是用户读写)的一些模块
      • clocking //MMCM,生成DDR4主时钟,用户时钟,MicroBlaze (MB)时钟
      • controller //顾名思义,读写控制器
      • ip_top //顶层
      • ui //User Interface,连接并转化AXI和裸接口
    • sw
      • calibration_0
        • Debug
          • calibration_ddr.elf //装到MB里的calibration程序
    • tb //don't care
    • ddr4_0.xci
    • ddr4_0.xml
    • ddr4_0.xdc 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

其实到这里已经能发现问题了,这不是一个简单的代码,而是一个包含了子IP的复杂工程。其中甚至还有MicroBlaze这样的软核,必然需要一个在综合时关联elf文件(现在已经不允许将elf打包进ip了,只能通过打包block design的方法把elf一起封装进去,详见 https://www.xilinx.com/support/answers/67083.html)。所以这个方法可行性就比较低了,所以可能需要把MicroBlaze核心从代码中提取出来。首先来看看它的模块图(pg150, figure 3-5):

如何魔改Xilinx Vivado 的MIG IP核_第1张图片

基本就是上电后MB控制复位和校准,然后交给用户。所以只需要把图中 "cal_riu"模块拎出来就好。但是其中MicroBlaze mcs是一个block design,所以我们要重新封装一下。方法是创建一个新的工程,直接加入现在ddr4_0/bd_0/bd_45eb.bd。这时候就能打开block design了。但是由于这个IP被xilinx锁住了,所以无法编辑。为了确保elf能正确加入,直接在tcl窗口中运行:

write_bd_tcl /microblaze_mcs.tcl

之后删除刚才加入的bd_45eb.bd,再创建一个新的blcok design,之后在tcl窗口中运行:

source /microblaze_mcs.tcl

这时,xilinx会生成一个和之前一模一样的block design。之后,用上文提到过的方法(https://www.xilinx.com/support/answers/67083.html)将 ddr4_0/sw/calibration_0/Debug/calibrate_ddr.elf导入,并将当前block design封装成一个独立IP备用。阅读"cal_riu"的源码(ddr4_cal_riu.sv):

module design_1_ddr4_0_0_ddr4_cal_riu(
...

design_1_ddr4_0_0_microblaze_mcs  mcs0 (
      .Clk                (riu_clk),
      .Reset              (reset_ub_riuclk),
      .IO_addr_strobe     (io_addr_strobe_ub),
      .IO_read_strobe     (),
      .IO_write_strobe    (io_write_strobe_ub),
      .IO_address         (io_address_ub),
      .IO_byte_enable     (),
      .IO_write_data      (io_write_data_ub),
      .IO_read_data       (io_read_data_ub),
      .IO_ready           (io_ready_ub),
      .TRACE_pc           (Trace_PC)
    );
...
endmodule

所以其实没几根线需要引出来,但是需要从这一层一口气拉倒top。同时注意输入和输出,不能搞反。此时,ddr4_0/bd_0和ddr4_0/ip_0中的文件已经不用管了。接下来,只需要打包其他文件即可。创建一个新的工程,导入其余所有sv, vh 和 有内容的xdc 文件。注意虽然ip_1中也是一个ip文件,但是可以直接忽略,只把源文件加入,千万不能把.xci一并加入,否则会被识别成ip,就无法修改了。这时候,按照之前说的把例化的mb删除,连接到外面。打包IP,创建新工程,导入之前打包的mb IP 和刚打包的控制器IP,按照原方式连接好,理论上来说已经可以正常工作了。这时候整个IP核看起来像这样

如何魔改Xilinx Vivado 的MIG IP核_第2张图片

添加好zynq_mpsoc等等其他IP后,写好引脚约束文件,开始综合和实现(所有与ddr4相关的IO口的电平约束都在之前的文件中写好了,只需要约束位置即可)。

然后最骚的地方来了,貌似新版Vivado (我用的2019)的MIG IP核的配置页面里是不能指定引脚的约束的,也就是说当前MIG的代码其实并不能直接对应你的硬件。Vivado官方的指定做法是在配置好时钟之类的属性后,编辑引脚约束。然后,Vivado 会自动修改MIG中的一些文件从而使它适配你的硬件。由于Xilinx的代码是以HP IO上每个Byte为单位的(参见ug571),每个信号都和一个IO Byte绑定,在魔改后,Vivado不会修真代码,就会和约束产生冲突。举个例子,代码里可能默认ADDR[3]和ADDR[2]写在了一个IO Byte上,而在PCB上他们实际上在两个Byte上,冲突就产生了,导致我们无法通过implementation。那么想要解决这个问题,我们需要根据我们的硬件去修改MIG里面的某些代码,从而使代码与硬件不产生冲突。但是其实很好找,因为仔细想想既然都参数化了,一定是在一些头文件里,于是我找到了三个名字很显眼的文件:

  • design_1_ddr4_0_0_phy_ddrMapDDR4.vh
  • design_1_ddr4_0_0_phy_iobMapDDR4.vh
  • design_1_ddr4_0_0_phy_riuMap.vh

都叫Map了还不够明显吗。。。一个一个看,先看iobMap

其中是两组端口定义,分别是mcal_rd_vref_value和iob_pin

,.mcal_rd_vref_value (
{

    mcal_rd_vref_value[55:49],
    mcal_rd_vref_value[48:42],
    mcal_rd_vref_value[41:35],
    mcal_rd_vref_value[34:28],
    mcal_rd_vref_value[27:21],
    mcal_rd_vref_value[20:14],
    7'b0,
    7'b0,
    mcal_rd_vref_value[13:7],
    mcal_rd_vref_value[6:0]
}
)

其中很明显是一个7*8的v_ref向量,和两个组0。结合DDR的接口定义和ug571中HP IO的特性,我们可以猜到其中8组Vref显然对应了64位DDR上每8bit一组的DQ Bus;而0则是因为Command 总线只有输出,自然就不在乎输入的Vref了。那结合ZCU104的原理图我们用了3个Byte完成CMD的输出,数据的书序也不是顺序,所以我把他们对应改成了:

.mcal_rd_vref_value (
{
    mcal_rd_vref_value[34:28],
    mcal_rd_vref_value[41:35],
    mcal_rd_vref_value[48:42],
    mcal_rd_vref_value[55:49],
    mcal_rd_vref_value[13:7],
    mcal_rd_vref_value[6:0],
    mcal_rd_vref_value[20:14],
    mcal_rd_vref_value[27:21],
    7'b0,
    7'b0,
    7'b0
}

iob_pin 明显就是要根据原理图来重新填,在这里给出我的修改(只适用于ZCU104)

.iob_pin (
{
//byte 10, 15/14
ddr4_nc[24],//18/11
ddr4_dq[32],//17/10
ddr4_dq[33],//16/F
ddr4_dq[34],//15/E
ddr4_dq[35],//14/D
ddr4_dqs_c[4],//13/C
ddr4_dqs_t[4],//12/B
ddr4_dq[36],//17/10
ddr4_dq[37],//16/F
ddr4_dq[38],//15/E
ddr4_dq[39],//14/D
ddr4_nc[23],//13/C
ddr4_dm_dbi_n[4],//12/B
//byte 9, 13/12
ddr4_nc[22],//18/11
ddr4_dq[40],//17/10
ddr4_dq[41],//16/F
ddr4_dq[42],//15/E
ddr4_dq[43],//14/D
ddr4_dqs_c[5],//13/C
ddr4_dqs_t[5],//12/B
ddr4_dq[44],//17/10
ddr4_dq[45],//16/F
ddr4_dq[46],//15/E
ddr4_dq[47],//14/D
ddr4_nc[21],//13/C
ddr4_dm_dbi_n[5],//12/B
//byte 8, 11/10
ddr4_nc[20],//18/11
ddr4_dq[48],//17/10
ddr4_dq[49],//16/F
ddr4_dq[50],//15/E
ddr4_dq[51],//14/D
ddr4_dqs_c[6],//13/C
ddr4_dqs_t[6],//12/B
ddr4_dq[52],//17/10
ddr4_dq[53],//16/F
ddr4_dq[54],//15/E
ddr4_dq[55],//14/D
ddr4_nc[19],//13/C
ddr4_dm_dbi_n[6],//12/B
//byte 7, F/E
ddr4_nc[18],//18/11
ddr4_dq[56],//17/10
ddr4_dq[57],//16/F
ddr4_dq[58],//15/E
ddr4_dq[59],//14/D
ddr4_dqs_c[7],//13/C
ddr4_dqs_t[7],//12/B
ddr4_dq[60],//17/10
ddr4_dq[61],//16/F
ddr4_dq[62],//15/E
ddr4_dq[63],//14/D
ddr4_nc[17],//13/C
ddr4_dm_dbi_n[7],//12/B
//byte 6, D/C
ddr4_nc[16],//18/11
ddr4_dq[8],//17/10
ddr4_dq[9],//16/F
ddr4_dq[10],//15/E
ddr4_dq[11],//14/D
ddr4_dqs_c[1],//13/C
ddr4_dqs_t[1],//12/B
ddr4_dq[12],//17/10
ddr4_dq[13],//16/F
ddr4_dq[14],//15/E
ddr4_dq[15],//14/D
ddr4_nc[15],//13/C
ddr4_dm_dbi_n[1],//12/B
//byte 5, B/A
ddr4_nc[14],//18/11
ddr4_dq[0],//17/10
ddr4_dq[1],//16/F
ddr4_dq[2],//15/E
ddr4_dq[3],//14/D
ddr4_dqs_c[0],//13/C
ddr4_dqs_t[0],//12/B
ddr4_dq[4],//17/10
ddr4_dq[5],//16/F
ddr4_dq[6],//15/E
ddr4_dq[7],//14/D
ddr4_nc[13],//13/C
ddr4_dm_dbi_n[0],//12/B
//byte 4, 9/8
ddr4_nc[12],//18/11
ddr4_dq[16],//17/10
ddr4_dq[17],//16/F
ddr4_dq[18],//15/E
ddr4_dq[19],//14/D
ddr4_dqs_c[2],//13/C
ddr4_dqs_t[2],//12/B
ddr4_dq[20],//17/10
ddr4_dq[21],//16/F
ddr4_dq[22],//15/E
ddr4_dq[23],//14/D
ddr4_nc[11],//13/C
ddr4_dm_dbi_n[2],//12/B
//byte 3, 7/6
ddr4_nc[10],//18/11
ddr4_dq[24],//17/10
ddr4_dq[25],//16/F
ddr4_dq[26],//15/E
ddr4_dq[27],//14/D
ddr4_dqs_c[3],//13/C
ddr4_dqs_t[3],//12/B
ddr4_dq[28],//17/10
ddr4_dq[29],//16/F
ddr4_dq[30],//15/E
ddr4_dq[31],//14/D
ddr4_nc[9],//13/C
ddr4_dm_dbi_n[3],//12/B
//byte 2, 5/4
ddr4_nc[8],//18/11
ddr4_nc[7],//17/10
ddr4_cke[0],//16/F
ddr4_nc[28],//15/E
ddr4_adr[15],//14/D
ddr4_cs_n[0],//13/C
ddr4_adr[14],//12/B
ddr4_nc[27],//17/10
ddr4_nc[26],//16/F
ddr4_bg[0],//15/E
ddr4_act_n,//14/D
ddr4_odt[0],//13/C
ddr4_adr[16],//12/B
//byte 1, 3/2
ddr4_adr[0],//18/11
ddr4_adr[1],//17/10
ddr4_adr[2],//16/F
ddr4_adr[3],//15/E
ddr4_adr[4],//14/D
ddr4_adr[5],//13/C
ddr4_adr[6],//12/B
ddr4_adr[7],//17/10
ddr4_nc[25],//16/F
ddr4_ck_c[0],//15/E
ddr4_ck_t[0],//14/D
ddr4_nc[6],//13/C
not_used,//12/B
//byte 0, 1/0
ddr4_nc[4],		//18/11
ddr4_nc[3],		//17/10
ddr4_nc[2],		//16/F
ddr4_adr[8],	//15/E
ddr4_adr[9],	//14/D
ddr4_adr[10],	//13/C
ddr4_adr[11],	//12/B
ddr4_adr[12],	//17/10
ddr4_adr[13],	//16/F
ddr4_ba[0],		//15/E
ddr4_ba[1],		//14/D
ddr4_nc[1],		//13/C
ddr4_nc[0]		//12/B
}	
)

我们可以结合原理图看一下,这里就看CMD这一块如何魔改Xilinx Vivado 的MIG IP核_第3张图片

由于CKE1和ODT1没用到,所以直接写成ddr4_nc里的线。这个ddr4_nc就是专门定义出来丢垃圾的,后来没有被用到,只是用来对齐位。聪明的小伙伴应该一看就知道是咋对应的了。

改完这个,我们看看ddrMap,这里面是很多组端口映射。应该是将IO的线网名字对应到DDR4控制逻辑的线网。由于DDR4速度很高,所以Xilinx使用了每一个IO口都有的RXTX_Bitslice。其中包含了一个1-8串并转换器。换句话说,任何每一个IO口到这里对应的位宽都乘以了8。Xilinx的定义方式是按照每个IO Byte上的对应位来对齐。一个IO Byte上有13位,所以就有13组rd,wr,fifo_rden等等。这个时候填写的方式是按照之前我们iopin里Byte的顺序,找到每Byte中同一位,*8 后填入相应一组中,比如clb2phy_wr_dq11这一组,就是输出的每个Byte中的第11(或者12,从1数的话)位,*8后组合。那可以查一下iomap,从下往上一次是无输出,ADR[1],无输出,dq[24], dq[16],dq[0],dq[8],dq[56],dq[48],dq[40],dq[32],注意数据位要乘8作为起始位(串并转换导致),然后向上数八位,于是我们可以写出

.clb2phy_wr_dq11 (
    { 
        mcal_DQOut[263:256],
        mcal_DQOut[327:320],
        mcal_DQOut[391:384],
        mcal_DQOut[455:448],
        mcal_DQOut[71:64],
        mcal_DQOut[7:0],
        mcal_DQOut[135:128],
        mcal_DQOut[199:192],
        8'bx,
        mcal_ADR[15:8],
        8'bx
    } 

由于是修改,其实是重排序,不要修改变量名就不会出问题。在这里贴出完全修改玩的代码,同样只针对ZCU104


,.phy2clb_rd_dq0 (
    { 
        mcal_DMIn_n[39:32],
        mcal_DMIn_n[47:40],
        mcal_DMIn_n[55:48],
        mcal_DMIn_n[63:56],
        mcal_DMIn_n[15:8],
        mcal_DMIn_n[7:0],
        mcal_DMIn_n[23:16],
        mcal_DMIn_n[31:24],
        mcal_nc[0],
        mcal_nc[1],
        mcal_nc[2]
    } 
)
,.phy2clb_rd_dq1 (
    { 
        mcal_nc[3],
        mcal_nc[4],
        mcal_nc[5],
        mcal_nc[6],
        mcal_nc[7],
        mcal_nc[8],
        mcal_nc[9],
        mcal_nc[10],
        mcal_nc[11],
        mcal_nc[12],
        mcal_nc[13]
    } 
)
,.phy2clb_rd_dq3 (
    { 
        mcal_DQIn[311:304],
        mcal_DQIn[375:368],
        mcal_DQIn[439:432],
        mcal_DQIn[503:496],
        mcal_DQIn[119:112],
        mcal_DQIn[55:48],
        mcal_DQIn[183:176],
        mcal_DQIn[247:240],
        mcal_nc[14],
        mcal_nc[15],
        mcal_nc[16]
    } 
)
,.phy2clb_rd_dq2 (
    { 
        mcal_DQIn[319:312],
        mcal_DQIn[383:376],
        mcal_DQIn[447:440],
        mcal_DQIn[511:504],
        mcal_DQIn[127:120],
        mcal_DQIn[63:56],
        mcal_DQIn[191:184],
        mcal_DQIn[255:248],
        mcal_nc[17],
        act_n_phy,
        mcal_nc[19]
    } 
)
,.phy2clb_rd_dq12 (
    { 
        mcal_nc[20],
        mcal_nc[21],
        mcal_nc[22],
        mcal_nc[23],
        mcal_nc[24],
        mcal_nc[25],
        mcal_nc[26],
        mcal_nc[27],
        mcal_nc[28],
        mcal_nc[29],
        mcal_nc[30],
        mcal_nc[31],
        mcal_nc[32]
    } 
)
,.phy2clb_rd_dq11 (
    { 
        mcal_DQIn[263:256],
        mcal_DQIn[327:320],
        mcal_DQIn[391:384],
        mcal_DQIn[455:448],
        mcal_DQIn[71:64],
        mcal_DQIn[7:0],
        mcal_DQIn[135:128],
        mcal_DQIn[199:192],
        mcal_nc[33],
        mcal_nc[34],
        mcal_nc[35]
    } 
)
,.phy2clb_rd_dq10 (
    { 
        mcal_DQIn[271:264],
        mcal_DQIn[335:328],
        mcal_DQIn[399:392],
        mcal_DQIn[463:456],
        mcal_DQIn[79:72],
        mcal_DQIn[15:8],
        mcal_DQIn[143:136],
        mcal_DQIn[207:200],
        mcal_nc[36],
        mcal_nc[37],
        mcal_nc[38]
    } 
)
,.phy2clb_rd_dq9 (
    { 
        mcal_DQIn[279:272],
        mcal_DQIn[343:336],
        mcal_DQIn[407:400],
        mcal_DQIn[471:464],
        mcal_DQIn[87:80],
        mcal_DQIn[23:16],
        mcal_DQIn[151:144],
        mcal_DQIn[215:208],
        mcal_nc[39],
        mcal_nc[40],
        mcal_nc[41]
    } 
)
,.phy2clb_rd_dq8 (
    { 
        mcal_DQIn[287:280],
        mcal_DQIn[351:344],
        mcal_DQIn[415:408],
        mcal_DQIn[479:472],
        mcal_DQIn[95:88],
        mcal_DQIn[31:24],
        mcal_DQIn[159:152],
        mcal_DQIn[223:216],
        mcal_nc[42],
        mcal_nc[43],
        mcal_nc[44]
    } 
)
,.phy2clb_rd_dq6 (
    { 
        mcal_nc[45],
        mcal_nc[46],
        mcal_nc[47],
        mcal_nc[48],
        mcal_nc[49],
        mcal_nc[50],
        mcal_nc[51],
        mcal_nc[52],
        mcal_nc[53],
        mcal_nc[54],
        mcal_nc[55]
    } 
)
,.phy2clb_rd_dq7 (
    { 
        mcal_nc[60],
        mcal_nc[61],
        mcal_nc[62],
        mcal_nc[63],
        mcal_nc[64],
        mcal_nc[65],
        mcal_nc[66],
        mcal_nc[67],
        mcal_nc[68],
        mcal_nc[69],
        mcal_nc[70]
    } 
)
,.phy2clb_rd_dq5 (
    { 
        mcal_DQIn[295:288],
        mcal_DQIn[359:352],
        mcal_DQIn[423:416],
        mcal_DQIn[487:480],
        mcal_DQIn[103:96],
        mcal_DQIn[39:32],
        mcal_DQIn[167:160],
        mcal_DQIn[231:224],
        mcal_nc[71],
        mcal_nc[72],
        mcal_nc[73]
    } 
)
,.phy2clb_rd_dq4 (
    { 
        mcal_DQIn[303:296],
        mcal_DQIn[367:360],
        mcal_DQIn[431:424],
        mcal_DQIn[495:488],
        mcal_DQIn[111:104],
        mcal_DQIn[47:40],
        mcal_DQIn[175:168],
        mcal_DQIn[239:232],
        mcal_nc[74],
        mcal_nc[75],
        mcal_nc[76]
    } 
)
,.clb2phy_wr_dq0 (
    { 
        mcal_DMOut_n[39:32],
        mcal_DMOut_n[47:40],
        mcal_DMOut_n[55:48],
        mcal_DMOut_n[63:56],
        mcal_DMOut_n[15:8],
        mcal_DMOut_n[7:0],
        mcal_DMOut_n[23:16],
        mcal_DMOut_n[31:24],
        mcal_ADR[135:128],
        8'bx,
        8'bx
    } 
)
,.clb2phy_wr_dq1 (
    { 
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        mcal_ODT[7:0],
        8'bx,
        8'bx
    } 
)
,.clb2phy_wr_dq3 (
    { 
        mcal_DQOut[311:304],
        mcal_DQOut[375:368],
        mcal_DQOut[439:432],
        mcal_DQOut[503:496],
        mcal_DQOut[119:112],
        mcal_DQOut[55:48],
        mcal_DQOut[183:176],
        mcal_DQOut[247:240],
        mcal_BG[7:0],
        mcal_CK_c[7:0],
        mcal_BA[7:0]
        //mcal_CKE[7:0],
        //mcal_ADR[23:16],
    } 
)
,.clb2phy_wr_dq2 (
    { 
        mcal_DQOut[319:312],
        mcal_DQOut[383:376],
        mcal_DQOut[447:440],
        mcal_DQOut[511:504],
        mcal_DQOut[127:120],
        mcal_DQOut[63:56],
        mcal_DQOut[191:184],
        mcal_DQOut[255:248],
        mcal_ACT_n[7:0],
        mcal_CK_t[7:0],
        mcal_BA[15:8]
    } 
)
,.clb2phy_wr_dq12 (
    { 
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        mcal_ADR[7:0],
        8'bx
    } 
)
,.clb2phy_wr_dq11 (
    { 
        mcal_DQOut[263:256],
        mcal_DQOut[327:320],
        mcal_DQOut[391:384],
        mcal_DQOut[455:448],
        mcal_DQOut[71:64],
        mcal_DQOut[7:0],
        mcal_DQOut[135:128],
        mcal_DQOut[199:192],
        8'bx,
        mcal_ADR[15:8],
        8'bx
    } 
)
,.clb2phy_wr_dq10 (
    { 
        mcal_DQOut[271:264],
        mcal_DQOut[335:328],
        mcal_DQOut[399:392],
        mcal_DQOut[463:456],
        mcal_DQOut[79:72],
        mcal_DQOut[15:8],
        mcal_DQOut[143:136],
        mcal_DQOut[207:200],
        mcal_CKE[7:0],
        mcal_ADR[23:16],
        8'bx
    } 
)
,.clb2phy_wr_dq9 (
    { 
        mcal_DQOut[279:272],
        mcal_DQOut[343:336],
        mcal_DQOut[407:400],
        mcal_DQOut[471:464],
        mcal_DQOut[87:80],
        mcal_DQOut[23:16],
        mcal_DQOut[151:144],
        mcal_DQOut[215:208],
        8'bx,
        mcal_ADR[31:24],
        mcal_ADR[71:64]
    } 
)
,.clb2phy_wr_dq8 (
    { 
        mcal_DQOut[287:280],
        mcal_DQOut[351:344],
        mcal_DQOut[415:408],
        mcal_DQOut[479:472],
        mcal_DQOut[95:88],
        mcal_DQOut[31:24],
        mcal_DQOut[159:152],
        mcal_DQOut[223:216],
        mcal_ADR[127:120],
        mcal_ADR[39:32],
        mcal_ADR[79:72]
    } 
)
,.clb2phy_wr_dq6 (
    { 
        mcal_DQSOut,
        mcal_DQSOut,
        mcal_DQSOut,
        mcal_DQSOut,
        mcal_DQSOut,
        mcal_DQSOut,
        mcal_DQSOut,
        mcal_DQSOut,
        mcal_ADR[119:112],
        mcal_ADR[55:48],
        mcal_ADR[95:88]
    } 
)
,.clb2phy_wr_dq7 (
    { 
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        8'bx,
        mcal_CS_n[7:0],
        mcal_ADR[47:40],
        mcal_ADR[87:80]
    } 
)
,.clb2phy_wr_dq5 (
    { 
        mcal_DQOut[295:288],
        mcal_DQOut[359:352],
        mcal_DQOut[423:416],
        mcal_DQOut[487:480],
        mcal_DQOut[103:96],
        mcal_DQOut[39:32],
        mcal_DQOut[167:160],
        mcal_DQOut[231:224],
        8'bx,
        mcal_ADR[63:56],
        mcal_ADR[103:96]
    } 
)
,.clb2phy_wr_dq4 (
    { 
        mcal_DQOut[303:296],
        mcal_DQOut[367:360],
        mcal_DQOut[431:424],
        mcal_DQOut[495:488],
        mcal_DQOut[111:104],
        mcal_DQOut[47:40],
        mcal_DQOut[175:168],
        mcal_DQOut[239:232],
        8'bx,
        8'bx,
        mcal_ADR[111:104]
    } 
)
,.clb2phy_fifo_rden (
    { 
        mcal_clb2phy_fifo_rden[64:52],
        mcal_clb2phy_fifo_rden[77:65],
        mcal_clb2phy_fifo_rden[90:78],
        mcal_clb2phy_fifo_rden[103:91],
        mcal_clb2phy_fifo_rden[25:13],
        mcal_clb2phy_fifo_rden[12:0],
        mcal_clb2phy_fifo_rden[38:26],
        mcal_clb2phy_fifo_rden[51:39],
        13'bxxxxxxxxxxxxx,
        13'bxxxxxxxxxx1xx,
        13'bx
    } 
)
,.clb2phy_odt_low (
    { 
        mcal_clb2phy_odt_low[34:28],
        mcal_clb2phy_odt_low[41:35],
        mcal_clb2phy_odt_low[48:42],
        mcal_clb2phy_odt_low[55:49],
        mcal_clb2phy_odt_low[13:7],
        mcal_clb2phy_odt_low[6:0],
        mcal_clb2phy_odt_low[20:14],
        mcal_clb2phy_odt_low[27:21],
        7'bx,
        7'bx,
        7'bx
    } 
)
,.clb2phy_odt_upp (
    { 
        mcal_clb2phy_odt_upp[34:28],
        mcal_clb2phy_odt_upp[41:35],
        mcal_clb2phy_odt_upp[48:42],
        mcal_clb2phy_odt_upp[55:49],
        mcal_clb2phy_odt_upp[13:7],
        mcal_clb2phy_odt_upp[6:0],
        mcal_clb2phy_odt_upp[20:14],
        mcal_clb2phy_odt_upp[27:21],
        7'bx,
        7'bx,
        7'bx
    } 
)
,.clb2phy_rdcs0_low (
    { 
        mcal_clb2phy_rdcs0_low[19:16],
        mcal_clb2phy_rdcs0_low[23:20],
        mcal_clb2phy_rdcs0_low[27:24],
        mcal_clb2phy_rdcs0_low[31:28],
        mcal_clb2phy_rdcs0_low[7:4],
        mcal_clb2phy_rdcs0_low[3:0],
        mcal_clb2phy_rdcs0_low[11:8],
        mcal_clb2phy_rdcs0_low[15:12],
        4'b0000,
        4'b0000,
        4'b0000
    } 
)
,.clb2phy_rdcs0_upp (
    { 
        mcal_clb2phy_rdcs0_upp[19:16],
        mcal_clb2phy_rdcs0_upp[23:20],
        mcal_clb2phy_rdcs0_upp[27:24],
        mcal_clb2phy_rdcs0_upp[31:28],
        mcal_clb2phy_rdcs0_upp[7:4],
        mcal_clb2phy_rdcs0_upp[3:0],
        mcal_clb2phy_rdcs0_upp[11:8],
        mcal_clb2phy_rdcs0_upp[15:12],
        4'b0000,
        4'b0000,
        4'b0000
    } 
)
,.clb2phy_rdcs1_low (
    { 
        mcal_clb2phy_rdcs1_low[19:16],
        mcal_clb2phy_rdcs1_low[23:20],
        mcal_clb2phy_rdcs1_low[27:24],
        mcal_clb2phy_rdcs1_low[31:28],
        mcal_clb2phy_rdcs1_low[7:4],
        mcal_clb2phy_rdcs1_low[3:0],
        mcal_clb2phy_rdcs1_low[11:8],
        mcal_clb2phy_rdcs1_low[15:12],
        4'b0000,
        4'b0000,
        4'b0000
    } 
)
,.clb2phy_rdcs1_upp (
    { 
        mcal_clb2phy_rdcs1_upp[19:16],
        mcal_clb2phy_rdcs1_upp[23:20],
        mcal_clb2phy_rdcs1_upp[27:24],
        mcal_clb2phy_rdcs1_upp[31:28],
        mcal_clb2phy_rdcs1_upp[7:4],
        mcal_clb2phy_rdcs1_upp[3:0],
        mcal_clb2phy_rdcs1_upp[11:8],
        mcal_clb2phy_rdcs1_upp[15:12],
        4'b0000,
        4'b0000,
        4'b0000
    } 
)
,.clb2phy_rden_low (
    { 
        mcal_clb2phy_rden_low[19:16],
        mcal_clb2phy_rden_low[23:20],
        mcal_clb2phy_rden_low[27:24],
        mcal_clb2phy_rden_low[31:28],
        mcal_clb2phy_rden_low[7:4],
        mcal_clb2phy_rden_low[3:0],
        mcal_clb2phy_rden_low[11:8],
        mcal_clb2phy_rden_low[15:12],
        4'b1111,
        4'b1111,
        4'b0000
    } 
)
,.clb2phy_rden_upp (
    { 
        mcal_clb2phy_rden_upp[19:16],
        mcal_clb2phy_rden_upp[23:20],
        mcal_clb2phy_rden_upp[27:24],
        mcal_clb2phy_rden_upp[31:28],
        mcal_clb2phy_rden_upp[7:4],
        mcal_clb2phy_rden_upp[3:0],
        mcal_clb2phy_rden_upp[11:8],
        mcal_clb2phy_rden_upp[15:12],
        4'b1111,
        4'b1111,
        4'b0000
    } 
)
,.clb2phy_t_b_low (
    { 
        mcal_clb2phy_t_b_low[19:16],
        mcal_clb2phy_t_b_low[23:20],
        mcal_clb2phy_t_b_low[27:24],
        mcal_clb2phy_t_b_low[31:28],
        mcal_clb2phy_t_b_low[7:4],
        mcal_clb2phy_t_b_low[3:0],
        mcal_clb2phy_t_b_low[11:8],
        mcal_clb2phy_t_b_low[15:12],
        clb2phy_t_b_addr,
        clb2phy_t_b_addr,
        clb2phy_t_b_addr
    } 
)
,.clb2phy_t_b_upp (
    { 
        mcal_clb2phy_t_b_upp[19:16],
        mcal_clb2phy_t_b_upp[23:20],
        mcal_clb2phy_t_b_upp[27:24],
        mcal_clb2phy_t_b_upp[31:28],
        mcal_clb2phy_t_b_upp[7:4],
        mcal_clb2phy_t_b_upp[3:0],
        mcal_clb2phy_t_b_upp[11:8],
        mcal_clb2phy_t_b_upp[15:12],
        clb2phy_t_b_addr,
        clb2phy_t_b_addr,
        clb2phy_t_b_addr
    } 
)
,.clb2phy_wrcs0_low (
    { 
        mcal_clb2phy_wrcs0_low[19:16],
        mcal_clb2phy_wrcs0_low[23:20],
        mcal_clb2phy_wrcs0_low[27:24],
        mcal_clb2phy_wrcs0_low[31:28],
        mcal_clb2phy_wrcs0_low[7:4],
        mcal_clb2phy_wrcs0_low[3:0],
        mcal_clb2phy_wrcs0_low[11:8],
        mcal_clb2phy_wrcs0_low[15:12],
        4'b0000,
        4'b0000,
        4'b0000
    } 
)
,.clb2phy_wrcs0_upp (
    { 
        mcal_clb2phy_wrcs0_upp[19:16],
        mcal_clb2phy_wrcs0_upp[23:20],
        mcal_clb2phy_wrcs0_upp[27:24],
        mcal_clb2phy_wrcs0_upp[31:28],
        mcal_clb2phy_wrcs0_upp[7:4],
        mcal_clb2phy_wrcs0_upp[3:0],
        mcal_clb2phy_wrcs0_upp[11:8],
        mcal_clb2phy_wrcs0_upp[15:12],
        4'b0000,
        4'b0000,
        4'b0000
    } 
)
,.clb2phy_wrcs1_low (
    { 
        mcal_clb2phy_wrcs1_low[19:16],
        mcal_clb2phy_wrcs1_low[23:20],
        mcal_clb2phy_wrcs1_low[27:24],
        mcal_clb2phy_wrcs1_low[31:28],
        mcal_clb2phy_wrcs1_low[7:4],
        mcal_clb2phy_wrcs1_low[3:0],
        mcal_clb2phy_wrcs1_low[11:8],
        mcal_clb2phy_wrcs1_low[15:12],
        4'b0000,
        4'b0000,
        4'b0000
    } 
)
,.clb2phy_wrcs1_upp (
    { 
        mcal_clb2phy_wrcs1_upp[19:16],
        mcal_clb2phy_wrcs1_upp[23:20],
        mcal_clb2phy_wrcs1_upp[27:24],
        mcal_clb2phy_wrcs1_upp[31:28],
        mcal_clb2phy_wrcs1_upp[7:4],
        mcal_clb2phy_wrcs1_upp[3:0],
        mcal_clb2phy_wrcs1_upp[11:8],
        mcal_clb2phy_wrcs1_upp[15:12],
        4'b0000,
        4'b0000,
        4'b0000
    } 
)
,.phy2clb_fifo_empty (
    { 
        phy2clb_fifo_empty[64:52],
        phy2clb_fifo_empty[77:65],
        phy2clb_fifo_empty[90:78],
        phy2clb_fifo_empty[103:91],
        phy2clb_fifo_empty[25:13],
        phy2clb_fifo_empty[12:0],
        phy2clb_fifo_empty[38:26],
        phy2clb_fifo_empty[51:39],
        phy2clb_fifo_empty_nc[12:0],
        phy2clb_fifo_empty_nc[25:13],
        phy2clb_fifo_empty_nc[38:26]
    } 
)
,.pll_clk0 (
    { 
        pll_clk[2],
        pll_clk[2],
        pll_clk[2],
        pll_clk[2],
        pll_clk[1],
        pll_clk[1],
        pll_clk[1],
        pll_clk[1],
        pll_clk[0],
        pll_clk[0],
        pll_clk[0] 
    } 
)
,.pll_clk1 (
    { 
        pll_clk[2],
        pll_clk[2],
        pll_clk[2],
        pll_clk[2],
        pll_clk[1],
        pll_clk[1],
        pll_clk[1],
        pll_clk[1],
        pll_clk[0],
        pll_clk[0],
        pll_clk[0] 
    } 
)
,.clb2phy_t_txbit (
    { 
        13'b0111100111100,
        13'b0111100111100,
        13'b0111100111100,
        13'b0111100111100,
        13'b0111100111100,
        13'b0111100111100,
        13'b0111100111100,
        13'b0111100111100,
        13'b0000000000000,
        13'b0000000000000,
        13'b0000000000000
    } 
)

其中值得注意的是pll_clk,我们一共用了3个bank,每个bank独享一个时钟就行。接下来是riuMap。这应该是最复杂的需要修改的文件了。RIU是用来控制每个Byte的输入输出延时(IODELAY3)等等的。也就是说MicroBlaze会在calibration过程中调用这个接口,打开这个文件我们就能知道这里是将物理的RIU映射到了一个地址,这样MicroBlaze就能根据地址进行calibration了。查看代码,每个地址背后都跟了注释,说明了在MicroBlaze看来这个地址是在控制什么,那我们只需要找到这个pin对应的物理地址就搞定了。每个物理地址分为两部分,nibble和addr。nibble查看ug571知道其实是对每个IO Byte的进一步细分,每个IO Byte有上下两个nibble,所以根据iomap文件里的顺序,往上数其实就知道nibble的地址了。至于具体的ADDR则需要查看pg150,Table3-2。有用的部分这里也给出:如何魔改Xilinx Vivado 的MIG IP核_第4张图片

举个例子,adr[0]的Odelay, 首先adr[0]在IO Byte1的upper nibble,也就是从下往上数第四个nibble,所以nibble地址就是3,它是该Byte的第13pin,所以对应的odelay地址就是0x11。就这么填下去就行了。这里还是给出这个Map

 //DIRECT ACCESS to RIU (logical nibble order) 
 28'h???2???: begin 
   riu_addr_cal = io_address[5:0]; 
   riu_nibble = io_address[NIBBLE_CNT_WIDTH+6:6]; 
 end 
//========================================//
//===========Address ODELAYS=============//
//========================================//

28'h0010800: begin //c0_ddr4_odt[0] IO_L1N_T0L_N1_DBC_64
  riu_addr_cal = 6'hC;
  riu_nibble = 'h4;
end

28'h0010040: begin //c0_ddr4_act_n IO_L7N_T1L_N1_QBC_AD13N_64
  riu_addr_cal = 6'hD;
  riu_nibble = 'h4;
end

28'h0010010: begin //c0_ddr4_adr[0] IO_L14P_T2L_N2_GC_64
  riu_addr_cal = 6'h11;
  riu_nibble = 'h3;
end

28'h0010011: begin //c0_ddr4_adr[1] IO_L14N_T2L_N3_GC_64
  riu_addr_cal = 6'h10;
  riu_nibble = 'h3;
end

28'h0010012: begin //c0_ddr4_adr[2] IO_L15P_T2L_N4_AD11P_64
  riu_addr_cal = 6'hF;
  riu_nibble = 'h3;
end

28'h0010013: begin //c0_ddr4_adr[3] IO_L15N_T2L_N5_AD11N_64
  riu_addr_cal = 6'hE;
  riu_nibble = 'h3;
end

28'h0010014: begin //c0_ddr4_adr[4] IO_L17P_T2U_N8_AD10P_64
  riu_addr_cal = 6'hD;
  riu_nibble = 'h3;
end

28'h0010015: begin //c0_ddr4_adr[5] IO_L17N_T2U_N9_AD10N_64
  riu_addr_cal = 6'hC;
  riu_nibble = 'h3;
end

28'h0010016: begin //c0_ddr4_adr[6] IO_L18P_T2U_N10_AD2P_64
  riu_addr_cal = 6'hB;
  riu_nibble = 'h3;
end

28'h0010017: begin //c0_ddr4_adr[7] IO_L18N_T2U_N11_AD2N_64
  riu_addr_cal = 6'h10;
  riu_nibble = 'h2;
end

28'h0010018: begin //c0_ddr4_adr[8] IO_T2U_N12_64
  riu_addr_cal = 6'hE;
  riu_nibble = 'h1;
end

28'h0010019: begin //c0_ddr4_adr[9] IO_L19P_T3L_N0_DBC_AD9P_64
  riu_addr_cal = 6'hD;
  riu_nibble = 'h1;
end

28'h001001A: begin //c0_ddr4_adr[10] IO_L19N_T3L_N1_DBC_AD9N_64
  riu_addr_cal = 6'hC;
  riu_nibble = 'h1;
end

28'h001001B: begin //c0_ddr4_adr[11] IO_L20P_T3L_N2_AD1P_64
  riu_addr_cal = 6'hB;
  riu_nibble = 'h1;
end

28'h001001C: begin //c0_ddr4_adr[12] IO_L20N_T3L_N3_AD1N_64
  riu_addr_cal = 6'h10;
  riu_nibble = 'h0;
end

28'h001001D: begin //c0_ddr4_adr[13] IO_L21P_T3L_N4_AD8P_64
  riu_addr_cal = 6'hF;
  riu_nibble = 'h0;
end

28'h001001E: begin //c0_ddr4_adr[14] IO_L21N_T3L_N5_AD8N_64
  riu_addr_cal = 6'hB;
  riu_nibble = 'h5;
end

28'h001001F: begin //c0_ddr4_adr[15] IO_L22P_T3U_N6_DBC_AD0P_64
  riu_addr_cal = 6'hD;
  riu_nibble = 'h5;
end

28'h0010020: begin //c0_ddr4_adr[16] IO_L22N_T3U_N7_DBC_AD0N_64
  riu_addr_cal = 6'hB;
  riu_nibble = 'h4;
end

28'h0010080: begin //c0_ddr4_ba[0] IO_L23P_T3U_N8_64
  riu_addr_cal = 6'hE;
  riu_nibble = 'h0;
end

28'h0010081: begin //c0_ddr4_ba[1] IO_L23N_T3U_N9_64
  riu_addr_cal = 6'hD;
  riu_nibble = 'h0;
end

28'h0010100: begin //c0_ddr4_bg[0] IO_L24P_T3U_N10_64
  riu_addr_cal = 6'hE;
  riu_nibble = 'h4;
end

28'h0010400: begin //c0_ddr4_cs_n[0] IO_L24N_T3U_N11_64
  riu_addr_cal = 6'hC;
  riu_nibble = 'h5;
end

28'h0010200: begin //c0_ddr4_cke[0] IO_T3U_N12_64
  riu_addr_cal = 6'hF;
  riu_nibble = 'h5;
end

//========================================//
//===========Address IDELAYS=============//
//========================================//

//========================================//
//===========Clock ODELAYS=============//
//========================================//

28'h0006100: begin //c0_ddr4_ck_t[0] IO_L16P_T2U_N6_QBC_AD3P_64
  riu_addr_cal = 6'hD;
  riu_nibble = 'h2;
end

//========================================//
//===========Clock IDELAYS=============//
//========================================//

//========================================//
//===========Data ODELAYS=============//
//========================================//

28'h0004100: begin //c0_ddr4_dq[0] IO_L2P_T0L_N2_64
  riu_addr_cal = 6'h10;
  riu_nibble = 'hB;
end

28'h0004101: begin //c0_ddr4_dq[1] IO_L2N_T0L_N3_64
  riu_addr_cal = 6'hF;
  riu_nibble = 'hB;
end

28'h0004102: begin //c0_ddr4_dq[2] IO_L3P_T0L_N4_AD15P_64
  riu_addr_cal = 6'hE;
  riu_nibble = 'hB;
end

28'h0004103: begin //c0_ddr4_dq[3] IO_L3N_T0L_N5_AD15N_64
  riu_addr_cal = 6'hD;
  riu_nibble = 'hB;
end

28'h0004104: begin //c0_ddr4_dq[4] IO_L5P_T0U_N8_AD14P_64
  riu_addr_cal = 6'h10;
  riu_nibble = 'hA;
end

28'h0004105: begin //c0_ddr4_dq[5] IO_L5N_T0U_N9_AD14N_64
  riu_addr_cal = 6'hF;
  riu_nibble = 'hA;
end

28'h0004106: begin //c0_ddr4_dq[6] IO_L6P_T0U_N10_AD6P_64
  riu_addr_cal = 6'hE;
  riu_nibble = 'hA;
end

28'h0004107: begin //c0_ddr4_dq[7] IO_L6N_T0U_N11_AD6N_64
  riu_addr_cal = 6'hD;
  riu_nibble = 'hA;
end

28'h0004108: begin //c0_ddr4_dq[8] IO_L8P_T1L_N2_AD5P_64
  riu_addr_cal = 6'h10;
  riu_nibble = 'hD;
end

28'h0004109: begin //c0_ddr4_dq[9] IO_L8N_T1L_N3_AD5N_64
  riu_addr_cal = 6'hF;
  riu_nibble = 'hD;
end

28'h000410A: begin //c0_ddr4_dq[10] IO_L9P_T1L_N4_AD12P_64
  riu_addr_cal = 6'hE;
  riu_nibble = 'hD;
end

28'h000410B: begin //c0_ddr4_dq[11] IO_L9N_T1L_N5_AD12N_64
  riu_addr_cal = 6'hD;
  riu_nibble = 'hD;
end

28'h000410C: begin //c0_ddr4_dq[12] IO_L11P_T1U_N8_GC_64
  riu_addr_cal = 6'h10;
  riu_nibble = 'hC;
end

28'h000410D: begin //c0_ddr4_dq[13] IO_L11N_T1U_N9_GC_64
  riu_addr_cal = 6'hF;
  riu_nibble = 'hC;
end

28'h000410E: begin //c0_ddr4_dq[14] IO_L12P_T1U_N10_GC_64
  riu_addr_cal = 6'hE;
  riu_nibble = 'hC;
end

28'h000410F: begin //c0_ddr4_dq[15] IO_L12N_T1U_N11_GC_64
  riu_addr_cal = 6'hD;
  riu_nibble = 'hC;
end

28'h0004110: begin //c0_ddr4_dq[16] IO_L2P_T0L_N2_65
  riu_addr_cal = 6'h10;
  riu_nibble = 'h9;
end

28'h0004111: begin //c0_ddr4_dq[17] IO_L2N_T0L_N3_65
  riu_addr_cal = 6'hF;
  riu_nibble = 'h9;
end

28'h0004112: begin //c0_ddr4_dq[18] IO_L3P_T0L_N4_AD15P_65
  riu_addr_cal = 6'hE;
  riu_nibble = 'h9;
end

28'h0004113: begin //c0_ddr4_dq[19] IO_L3N_T0L_N5_AD15N_65
  riu_addr_cal = 6'hD;
  riu_nibble = 'h9;
end

28'h0004114: begin //c0_ddr4_dq[20] IO_L5P_T0U_N8_AD14P_65
  riu_addr_cal = 6'h10;
  riu_nibble = 'h8;
end

28'h0004115: begin //c0_ddr4_dq[21] IO_L5N_T0U_N9_AD14N_65
  riu_addr_cal = 6'hF;
  riu_nibble = 'h8;
end

28'h0004116: begin //c0_ddr4_dq[22] IO_L6P_T0U_N10_AD6P_65
  riu_addr_cal = 6'hE;
  riu_nibble = 'h8;
end

28'h0004117: begin //c0_ddr4_dq[23] IO_L6N_T0U_N11_AD6N_65
  riu_addr_cal = 6'hD;
  riu_nibble = 'h8;
end

28'h0004118: begin //c0_ddr4_dq[24] IO_L8P_T1L_N2_AD5P_65
  riu_addr_cal = 6'h10;
  riu_nibble = 'h7;
end

28'h0004119: begin //c0_ddr4_dq[25] IO_L8N_T1L_N3_AD5N_65
  riu_addr_cal = 6'hF;
  riu_nibble = 'h7;
end

28'h000411A: begin //c0_ddr4_dq[26] IO_L9P_T1L_N4_AD12P_65
  riu_addr_cal = 6'hE;
  riu_nibble = 'h7;
end

28'h000411B: begin //c0_ddr4_dq[27] IO_L9N_T1L_N5_AD12N_65
  riu_addr_cal = 6'hD;
  riu_nibble = 'h7;
end

28'h000411C: begin //c0_ddr4_dq[28] IO_L11P_T1U_N8_GC_65
  riu_addr_cal = 6'h10;
  riu_nibble = 'h6;
end

28'h000411D: begin //c0_ddr4_dq[29] IO_L11N_T1U_N9_GC_65
  riu_addr_cal = 6'hF;
  riu_nibble = 'h6;
end

28'h000411E: begin //c0_ddr4_dq[30] IO_L12P_T1U_N10_GC_65
  riu_addr_cal = 6'hE;
  riu_nibble = 'h6;
end

28'h000411F: begin //c0_ddr4_dq[31] IO_L12N_T1U_N11_GC_65
  riu_addr_cal = 6'hD;
  riu_nibble = 'h6;
end

28'h0004120: begin //c0_ddr4_dq[32] IO_L14P_T2L_N2_GC_65
  riu_addr_cal = 6'h10;
  riu_nibble = 'h15;
end

28'h0004121: begin //c0_ddr4_dq[33] IO_L14N_T2L_N3_GC_65
  riu_addr_cal = 6'hF;
  riu_nibble = 'h15;
end

28'h0004122: begin //c0_ddr4_dq[34] IO_L15P_T2L_N4_AD11P_65
  riu_addr_cal = 6'hE;
  riu_nibble = 'h15;
end

28'h0004123: begin //c0_ddr4_dq[35] IO_L15N_T2L_N5_AD11N_65
  riu_addr_cal = 6'hD;
  riu_nibble = 'h15;
end

28'h0004124: begin //c0_ddr4_dq[36] IO_L17P_T2U_N8_AD10P_65
  riu_addr_cal = 6'h10;
  riu_nibble = 'h14;
end

28'h0004125: begin //c0_ddr4_dq[37] IO_L17N_T2U_N9_AD10N_65
  riu_addr_cal = 6'hF;
  riu_nibble = 'h14;
end

28'h0004126: begin //c0_ddr4_dq[38] IO_L18P_T2U_N10_AD2P_65
  riu_addr_cal = 6'hE;
  riu_nibble = 'h14;
end

28'h0004127: begin //c0_ddr4_dq[39] IO_L18N_T2U_N11_AD2N_65
  riu_addr_cal = 6'hD;
  riu_nibble = 'h14;
end

28'h0004128: begin //c0_ddr4_dq[40] IO_L20P_T3L_N2_AD1P_65
  riu_addr_cal = 6'h10;
  riu_nibble = 'h13;
end

28'h0004129: begin //c0_ddr4_dq[41] IO_L20N_T3L_N3_AD1N_65
  riu_addr_cal = 6'hF;
  riu_nibble = 'h13;
end

28'h000412A: begin //c0_ddr4_dq[42] IO_L21P_T3L_N4_AD8P_65
  riu_addr_cal = 6'hE;
  riu_nibble = 'h13;
end

28'h000412B: begin //c0_ddr4_dq[43] IO_L21N_T3L_N5_AD8N_65
  riu_addr_cal = 6'hD;
  riu_nibble = 'h13;
end

28'h000412C: begin //c0_ddr4_dq[44] IO_L23P_T3U_N8_I2C_SCLK_65
  riu_addr_cal = 6'h10;
  riu_nibble = 'h12;
end

28'h000412D: begin //c0_ddr4_dq[45] IO_L23N_T3U_N9_65
  riu_addr_cal = 6'hF;
  riu_nibble = 'h12;
end

28'h000412E: begin //c0_ddr4_dq[46] IO_L24P_T3U_N10_PERSTN1_I2C_SDA_65
  riu_addr_cal = 6'hE;
  riu_nibble = 'h12;
end

28'h000412F: begin //c0_ddr4_dq[47] IO_L24N_T3U_N11_PERSTN0_65
  riu_addr_cal = 6'hD;
  riu_nibble = 'h12;
end

28'h0004130: begin //c0_ddr4_dq[48] IO_L2P_T0L_N2_66
  riu_addr_cal = 6'h10;
  riu_nibble = 'h11;
end

28'h0004131: begin //c0_ddr4_dq[49] IO_L2N_T0L_N3_66
  riu_addr_cal = 6'hF;
  riu_nibble = 'h11;
end

28'h0004132: begin //c0_ddr4_dq[50] IO_L3P_T0L_N4_AD15P_66
  riu_addr_cal = 6'hE;
  riu_nibble = 'h11;
end

28'h0004133: begin //c0_ddr4_dq[51] IO_L3N_T0L_N5_AD15N_66
  riu_addr_cal = 6'hD;
  riu_nibble = 'h11;
end

28'h0004134: begin //c0_ddr4_dq[52] IO_L5P_T0U_N8_AD14P_66
  riu_addr_cal = 6'h10;
  riu_nibble = 'h10;
end

28'h0004135: begin //c0_ddr4_dq[53] IO_L5N_T0U_N9_AD14N_66
  riu_addr_cal = 6'hF;
  riu_nibble = 'h10;
end

28'h0004136: begin //c0_ddr4_dq[54] IO_L6P_T0U_N10_AD6P_66
  riu_addr_cal = 6'hE;
  riu_nibble = 'h10;
end

28'h0004137: begin //c0_ddr4_dq[55] IO_L6N_T0U_N11_AD6N_66
  riu_addr_cal = 6'hD;
  riu_nibble = 'h10;
end

28'h0004138: begin //c0_ddr4_dq[56] IO_L8P_T1L_N2_AD5P_66
  riu_addr_cal = 6'h10;
  riu_nibble = 'hF;
end

28'h0004139: begin //c0_ddr4_dq[57] IO_L8N_T1L_N3_AD5N_66
  riu_addr_cal = 6'hF;
  riu_nibble = 'hF;
end

28'h000413A: begin //c0_ddr4_dq[58] IO_L9P_T1L_N4_AD12P_66
  riu_addr_cal = 6'hE;
  riu_nibble = 'hF;
end

28'h000413B: begin //c0_ddr4_dq[59] IO_L9N_T1L_N5_AD12N_66
  riu_addr_cal = 6'hD;
  riu_nibble = 'hF;
end

28'h000413C: begin //c0_ddr4_dq[60] IO_L11P_T1U_N8_GC_66
  riu_addr_cal = 6'h10;
  riu_nibble = 'hE;
end

28'h000413D: begin //c0_ddr4_dq[61] IO_L11N_T1U_N9_GC_66
  riu_addr_cal = 6'hF;
  riu_nibble = 'hE;
end

28'h000413E: begin //c0_ddr4_dq[62] IO_L12P_T1U_N10_GC_66
  riu_addr_cal = 6'hE;
  riu_nibble = 'hE;
end

28'h000413F: begin //c0_ddr4_dq[63] IO_L12N_T1U_N11_GC_66
  riu_addr_cal = 6'hD;
  riu_nibble = 'hE;
end

//========================================//
//===========Data IDELAYS=============//
//========================================//

28'h0004200: begin //c0_ddr4_dq[0] IO_L2P_T0L_N2_64
  riu_addr_cal  = 6'h17;
  riu_nibble = 'hB;
end

28'h0004201: begin //c0_ddr4_dq[1] IO_L2N_T0L_N3_64
  riu_addr_cal =  6'h16;
  riu_nibble = 'hB;
end

28'h0004202: begin //c0_ddr4_dq[2] IO_L3P_T0L_N4_AD15P_64
  riu_addr_cal =  6'h15;
  riu_nibble = 'hB;
end

28'h0004203: begin //c0_ddr4_dq[3] IO_L3N_T0L_N5_AD15N_64
  riu_addr_cal = 6'h14;
  riu_nibble = 'hB;
end

28'h0004204: begin //c0_ddr4_dq[4] IO_L5P_T0U_N8_AD14P_64
  riu_addr_cal  = 6'h17;
  riu_nibble = 'hA;
end

28'h0004205: begin //c0_ddr4_dq[5] IO_L5N_T0U_N9_AD14N_64
  riu_addr_cal =  6'h16;
  riu_nibble = 'hA;
end

28'h0004206: begin //c0_ddr4_dq[6] IO_L6P_T0U_N10_AD6P_64
  riu_addr_cal =  6'h15;
  riu_nibble = 'hA;
end

28'h0004207: begin //c0_ddr4_dq[7] IO_L6N_T0U_N11_AD6N_64
  riu_addr_cal = 6'h14;
  riu_nibble = 'hA;
end

28'h0004208: begin //c0_ddr4_dq[8] IO_L8P_T1L_N2_AD5P_64
  riu_addr_cal  = 6'h17;
  riu_nibble = 'hD;
end

28'h0004209: begin //c0_ddr4_dq[9] IO_L8N_T1L_N3_AD5N_64
  riu_addr_cal =  6'h16;
  riu_nibble = 'hD;
end

28'h000420A: begin //c0_ddr4_dq[10] IO_L9P_T1L_N4_AD12P_64
  riu_addr_cal =  6'h15;
  riu_nibble = 'hD;
end

28'h000420B: begin //c0_ddr4_dq[11] IO_L9N_T1L_N5_AD12N_64
  riu_addr_cal = 6'h14;
  riu_nibble = 'hD;
end

28'h000420C: begin //c0_ddr4_dq[12] IO_L11P_T1U_N8_GC_64
  riu_addr_cal  = 6'h17;
  riu_nibble = 'hC;
end

28'h000420D: begin //c0_ddr4_dq[13] IO_L11N_T1U_N9_GC_64
  riu_addr_cal =  6'h16;
  riu_nibble = 'hC;
end

28'h000420E: begin //c0_ddr4_dq[14] IO_L12P_T1U_N10_GC_64
  riu_addr_cal =  6'h15;
  riu_nibble = 'hC;
end

28'h000420F: begin //c0_ddr4_dq[15] IO_L12N_T1U_N11_GC_64
  riu_addr_cal = 6'h14;
  riu_nibble = 'hC;
end

28'h0004210: begin //c0_ddr4_dq[16] IO_L2P_T0L_N2_65
  riu_addr_cal  = 6'h17;
  riu_nibble = 'h9;
end

28'h0004211: begin //c0_ddr4_dq[17] IO_L2N_T0L_N3_65
  riu_addr_cal =  6'h16;
  riu_nibble = 'h9;
end

28'h0004212: begin //c0_ddr4_dq[18] IO_L3P_T0L_N4_AD15P_65
  riu_addr_cal =  6'h15;
  riu_nibble = 'h9;
end

28'h0004213: begin //c0_ddr4_dq[19] IO_L3N_T0L_N5_AD15N_65
  riu_addr_cal = 6'h14;
  riu_nibble = 'h9;
end

28'h0004214: begin //c0_ddr4_dq[20] IO_L5P_T0U_N8_AD14P_65
  riu_addr_cal  = 6'h17;
  riu_nibble = 'h8;
end

28'h0004215: begin //c0_ddr4_dq[21] IO_L5N_T0U_N9_AD14N_65
  riu_addr_cal =  6'h16;
  riu_nibble = 'h8;
end

28'h0004216: begin //c0_ddr4_dq[22] IO_L6P_T0U_N10_AD6P_65
  riu_addr_cal =  6'h15;
  riu_nibble = 'h8;
end

28'h0004217: begin //c0_ddr4_dq[23] IO_L6N_T0U_N11_AD6N_65
  riu_addr_cal = 6'h14;
  riu_nibble = 'h8;
end

28'h0004218: begin //c0_ddr4_dq[24] IO_L8P_T1L_N2_AD5P_65
  riu_addr_cal  = 6'h17;
  riu_nibble = 'h7;
end

28'h0004219: begin //c0_ddr4_dq[25] IO_L8N_T1L_N3_AD5N_65
  riu_addr_cal =  6'h16;
  riu_nibble = 'h7;
end

28'h000421A: begin //c0_ddr4_dq[26] IO_L9P_T1L_N4_AD12P_65
  riu_addr_cal =  6'h15;
  riu_nibble = 'h7;
end

28'h000421B: begin //c0_ddr4_dq[27] IO_L9N_T1L_N5_AD12N_65
  riu_addr_cal = 6'h14;
  riu_nibble = 'h7;
end

28'h000421C: begin //c0_ddr4_dq[28] IO_L11P_T1U_N8_GC_65
  riu_addr_cal  = 6'h17;
  riu_nibble = 'h6;
end

28'h000421D: begin //c0_ddr4_dq[29] IO_L11N_T1U_N9_GC_65
  riu_addr_cal =  6'h16;
  riu_nibble = 'h6;
end

28'h000421E: begin //c0_ddr4_dq[30] IO_L12P_T1U_N10_GC_65
  riu_addr_cal =  6'h15;
  riu_nibble = 'h6;
end

28'h000421F: begin //c0_ddr4_dq[31] IO_L12N_T1U_N11_GC_65
  riu_addr_cal = 6'h14;
  riu_nibble = 'h6;
end

28'h0004220: begin //c0_ddr4_dq[32] IO_L14P_T2L_N2_GC_65
  riu_addr_cal  = 6'h17;
  riu_nibble = 'h15;
end

28'h0004221: begin //c0_ddr4_dq[33] IO_L14N_T2L_N3_GC_65
  riu_addr_cal =  6'h16;
  riu_nibble = 'h15;
end

28'h0004222: begin //c0_ddr4_dq[34] IO_L15P_T2L_N4_AD11P_65
  riu_addr_cal =  6'h15;
  riu_nibble = 'h15;
end

28'h0004223: begin //c0_ddr4_dq[35] IO_L15N_T2L_N5_AD11N_65
  riu_addr_cal = 6'h14;
  riu_nibble = 'h15;
end

28'h0004224: begin //c0_ddr4_dq[36] IO_L17P_T2U_N8_AD10P_65
  riu_addr_cal  = 6'h17;
  riu_nibble = 'h14;
end

28'h0004225: begin //c0_ddr4_dq[37] IO_L17N_T2U_N9_AD10N_65
  riu_addr_cal =  6'h16;
  riu_nibble = 'h14;
end

28'h0004226: begin //c0_ddr4_dq[38] IO_L18P_T2U_N10_AD2P_65
  riu_addr_cal =  6'h15;
  riu_nibble = 'h14;
end

28'h0004227: begin //c0_ddr4_dq[39] IO_L18N_T2U_N11_AD2N_65
  riu_addr_cal = 6'h14;
  riu_nibble = 'h14;
end

28'h0004228: begin //c0_ddr4_dq[40] IO_L20P_T3L_N2_AD1P_65
  riu_addr_cal  = 6'h17;
  riu_nibble = 'h13;
end

28'h0004229: begin //c0_ddr4_dq[41] IO_L20N_T3L_N3_AD1N_65
  riu_addr_cal =  6'h16;
  riu_nibble = 'h13;
end

28'h000422A: begin //c0_ddr4_dq[42] IO_L21P_T3L_N4_AD8P_65
  riu_addr_cal =  6'h15;
  riu_nibble = 'h13;
end

28'h000422B: begin //c0_ddr4_dq[43] IO_L21N_T3L_N5_AD8N_65
  riu_addr_cal = 6'h14;
  riu_nibble = 'h13;
end

28'h000422C: begin //c0_ddr4_dq[44] IO_L23P_T3U_N8_I2C_SCLK_65
  riu_addr_cal  = 6'h17;
  riu_nibble = 'h12;
end

28'h000422D: begin //c0_ddr4_dq[45] IO_L23N_T3U_N9_65
  riu_addr_cal =  6'h16;
  riu_nibble = 'h12;
end

28'h000422E: begin //c0_ddr4_dq[46] IO_L24P_T3U_N10_PERSTN1_I2C_SDA_65
  riu_addr_cal =  6'h15;
  riu_nibble = 'h12;
end

28'h000422F: begin //c0_ddr4_dq[47] IO_L24N_T3U_N11_PERSTN0_65
  riu_addr_cal = 6'h14;
  riu_nibble = 'h12;
end

28'h0004230: begin //c0_ddr4_dq[48] IO_L2P_T0L_N2_66
  riu_addr_cal  = 6'h17;
  riu_nibble = 'h11;
end

28'h0004231: begin //c0_ddr4_dq[49] IO_L2N_T0L_N3_66
  riu_addr_cal =  6'h16;
  riu_nibble = 'h11;
end

28'h0004232: begin //c0_ddr4_dq[50] IO_L3P_T0L_N4_AD15P_66
  riu_addr_cal =  6'h15;
  riu_nibble = 'h11;
end

28'h0004233: begin //c0_ddr4_dq[51] IO_L3N_T0L_N5_AD15N_66
  riu_addr_cal = 6'h14;
  riu_nibble = 'h11;
end

28'h0004234: begin //c0_ddr4_dq[52] IO_L5P_T0U_N8_AD14P_66
  riu_addr_cal  = 6'h17;
  riu_nibble = 'h10;
end

28'h0004235: begin //c0_ddr4_dq[53] IO_L5N_T0U_N9_AD14N_66
  riu_addr_cal =  6'h16;
  riu_nibble = 'h10;
end

28'h0004236: begin //c0_ddr4_dq[54] IO_L6P_T0U_N10_AD6P_66
  riu_addr_cal =  6'h15;
  riu_nibble = 'h10;
end

28'h0004237: begin //c0_ddr4_dq[55] IO_L6N_T0U_N11_AD6N_66
  riu_addr_cal = 6'h14;
  riu_nibble = 'h10;
end

28'h0004238: begin //c0_ddr4_dq[56] IO_L8P_T1L_N2_AD5P_66
  riu_addr_cal  = 6'h17;
  riu_nibble = 'hF;
end

28'h0004239: begin //c0_ddr4_dq[57] IO_L8N_T1L_N3_AD5N_66
  riu_addr_cal =  6'h16;
  riu_nibble = 'hF;
end

28'h000423A: begin //c0_ddr4_dq[58] IO_L9P_T1L_N4_AD12P_66
  riu_addr_cal =  6'h15;
  riu_nibble = 'hF;
end

28'h000423B: begin //c0_ddr4_dq[59] IO_L9N_T1L_N5_AD12N_66
  riu_addr_cal = 6'h14;
  riu_nibble = 'hF;
end

28'h000423C: begin //c0_ddr4_dq[60] IO_L11P_T1U_N8_GC_66
  riu_addr_cal  = 6'h17;
  riu_nibble = 'hE;
end

28'h000423D: begin //c0_ddr4_dq[61] IO_L11N_T1U_N9_GC_66
  riu_addr_cal =  6'h16;
  riu_nibble = 'hE;
end

28'h000423E: begin //c0_ddr4_dq[62] IO_L12P_T1U_N10_GC_66
  riu_addr_cal =  6'h15;
  riu_nibble = 'hE;
end

28'h000423F: begin //c0_ddr4_dq[63] IO_L12N_T1U_N11_GC_66
  riu_addr_cal = 6'h14;
  riu_nibble = 'hE;
end

//========================================//
//===========Mask ODELAYS=============//
//========================================//

28'h0004400: begin //c0_ddr4_dm_dbi_n[0] IO_L1P_T0L_N0_DBC_64
  riu_addr_cal = 6'hB;
  riu_nibble = 'hA;
end

28'h0004401: begin //c0_ddr4_dm_dbi_n[1] IO_L7P_T1L_N0_QBC_AD13P_64
  riu_addr_cal = 6'hB;
  riu_nibble = 'hC;
end

28'h0004402: begin //c0_ddr4_dm_dbi_n[2] IO_L1P_T0L_N0_DBC_65
  riu_addr_cal = 6'hB;
  riu_nibble = 'h8;
end

28'h0004403: begin //c0_ddr4_dm_dbi_n[3] IO_L7P_T1L_N0_QBC_AD13P_65
  riu_addr_cal = 6'hB;
  riu_nibble = 'h6;
end

28'h0004404: begin //c0_ddr4_dm_dbi_n[4] IO_L13P_T2L_N0_GC_QBC_65
  riu_addr_cal = 6'hB;
  riu_nibble = 'h14;
end

28'h0004405: begin //c0_ddr4_dm_dbi_n[5] IO_L19P_T3L_N0_DBC_AD9P_65
  riu_addr_cal = 6'hB;
  riu_nibble = 'h12;
end

28'h0004406: begin //c0_ddr4_dm_dbi_n[6] IO_L1P_T0L_N0_DBC_66
  riu_addr_cal = 6'hB;
  riu_nibble = 'h10;
end

28'h0004407: begin //c0_ddr4_dm_dbi_n[7] IO_L7P_T1L_N0_QBC_AD13P_66
  riu_addr_cal = 6'hB;
  riu_nibble = 'hE;
end

//========================================//
//===========Mask IDELAYS=============//
//========================================//

28'h0004800: begin //c0_ddr4_dm_dbi_n[0] IO_L1P_T0L_N0_DBC_64
  riu_addr_cal = 6'h12;
  riu_nibble = 'hA;
end

28'h0004801: begin //c0_ddr4_dm_dbi_n[1] IO_L7P_T1L_N0_QBC_AD13P_64
  riu_addr_cal = 6'h12;
  riu_nibble = 'hC;
end

28'h0004802: begin //c0_ddr4_dm_dbi_n[2] IO_L1P_T0L_N0_DBC_65
  riu_addr_cal = 6'h12;
  riu_nibble = 'h8;
end

28'h0004803: begin //c0_ddr4_dm_dbi_n[3] IO_L7P_T1L_N0_QBC_AD13P_65
  riu_addr_cal = 6'h12;
  riu_nibble = 'h6;
end

28'h0004804: begin //c0_ddr4_dm_dbi_n[4] IO_L13P_T2L_N0_GC_QBC_65
  riu_addr_cal = 6'h14;
  riu_nibble = 'h14;
end

28'h0004805: begin //c0_ddr4_dm_dbi_n[5] IO_L19P_T3L_N0_DBC_AD9P_65
  riu_addr_cal = 6'h12;
  riu_nibble = 'h12;
end

28'h0004806: begin //c0_ddr4_dm_dbi_n[6] IO_L1P_T0L_N0_DBC_66
  riu_addr_cal = 6'h10;
  riu_nibble = 'h10;
end

28'h0004807: begin //c0_ddr4_dm_dbi_n[7] IO_L7P_T1L_N0_QBC_AD13P_66
  riu_addr_cal = 6'h12;
  riu_nibble = 'hE;
end

//========================================//
//===========Strobe ODELAYS=============//
//========================================//

28'h0008100: begin //c0_ddr4_dqs_t[0] IO_L4P_T0U_N6_DBC_AD7P_64
  riu_addr_cal = 6'hB;
  riu_nibble = 'hB;
end

28'h0008101: begin //c0_ddr4_dqs_t[1] IO_L10P_T1U_N6_QBC_AD4P_64
  riu_addr_cal = 6'hB;
  riu_nibble = 'hD;
end

28'h0008102: begin //c0_ddr4_dqs_t[2] IO_L4P_T0U_N6_DBC_AD7P_SMBALERT_65
  riu_addr_cal = 6'hB;
  riu_nibble = 'h9;
end

28'h0008103: begin //c0_ddr4_dqs_t[3] IO_L10P_T1U_N6_QBC_AD4P_65
  riu_addr_cal = 6'hB;
  riu_nibble = 'h7;
end

28'h0008104: begin //c0_ddr4_dqs_t[4] IO_L16P_T2U_N6_QBC_AD3P_65
  riu_addr_cal = 6'hB;
  riu_nibble = 'h15;
end

28'h0008105: begin //c0_ddr4_dqs_t[5] IO_L22P_T3U_N6_DBC_AD0P_65
  riu_addr_cal = 6'hB;
  riu_nibble = 'h13;
end

28'h0008106: begin //c0_ddr4_dqs_t[6] IO_L4P_T0U_N6_DBC_AD7P_66
  riu_addr_cal = 6'hB;
  riu_nibble = 'h11;
end

28'h0008107: begin //c0_ddr4_dqs_t[7] IO_L10P_T1U_N6_QBC_AD4P_66
  riu_addr_cal = 6'hB;
  riu_nibble = 'hF;
end

//========================================//
//===========Strobe IDELAYS=============//
//========================================//

28'h0008200: begin //c0_ddr4_dqs_t[0] IO_L4P_T0U_N6_DBC_AD7P_64
  riu_addr_cal = 6'h12;
  riu_nibble = 'hB;
end

28'h0008201: begin //c0_ddr4_dqs_t[1] IO_L10P_T1U_N6_QBC_AD4P_64
  riu_addr_cal = 6'h12;
  riu_nibble = 'hD;
end

28'h0008202: begin //c0_ddr4_dqs_t[2] IO_L4P_T0U_N6_DBC_AD7P_SMBALERT_65
  riu_addr_cal = 6'h12;
  riu_nibble = 'h9;
end

28'h0008203: begin //c0_ddr4_dqs_t[3] IO_L10P_T1U_N6_QBC_AD4P_65
  riu_addr_cal = 6'h12;
  riu_nibble = 'h7;
end

28'h0008204: begin //c0_ddr4_dqs_t[4] IO_L16P_T2U_N6_QBC_AD3P_65
  riu_addr_cal = 6'h12;
  riu_nibble = 'h15;
end

28'h0008205: begin //c0_ddr4_dqs_t[5] IO_L22P_T3U_N6_DBC_AD0P_65
  riu_addr_cal = 6'h12;
  riu_nibble = 'h13;
end

28'h0008206: begin //c0_ddr4_dqs_t[6] IO_L4P_T0U_N6_DBC_AD7P_66
  riu_addr_cal = 6'h12;
  riu_nibble = 'h11;
end

28'h0008207: begin //c0_ddr4_dqs_t[7] IO_L10P_T1U_N6_QBC_AD4P_66
  riu_addr_cal = 6'h12;
  riu_nibble = 'hF;
end

改完了这些本以为可以工作了,然后发现太天真了。在phy的top里其实还有一组参数宏观控制用了几个Byte,几个Bank等等。在这里,首先我们用了三个Bank,所以PLL_WIDTH要改成3;我们用了11个IO Byte,所以修改BYTES = 11。DBYTES就是数据用了几个BYTE,显然是8,没有变。然后是IOBTYPE。这个是一个3*13*BYTE数的向量。经过深度挖掘发现Xilinx用3个bit定义每个端口的输出类型,也就对应了要例化的IO Buffer。其中

  • 3'b001->obuf;
  • 3'b010->ibuf;
  • 3'b011->iobuf;
  • 3'b101->obufds;
  • 3'b110->ibufds;
  • 3'b111->iobufds;

很lucky,有3'b000和3'b100没被使用,这样我就可以用它来帮我修改了电路了。

然后是RX_DATA_TYPE, 正常情况下没啥要改的,如果有需要可以自己去挖,我这里修改了一位的属性,从而是的数据可以回环采样。

接下来很多

TX_OUTPUT_PHASE_90

RXTX_BITSLICE_EN

NATIVE_ODELAY_BYPASSEN_OTHER_PCLK      
EN_OTHER_NCLK      
RX_CLK_PHASE_P     
RX_CLK_PHASE_N     
TX_GATING          
RX_GATING          
EN_DYN_ODLY_MODE  

SELF_CALIBRATE

这些都需要相应根据你具体用了几个Byte,哪些是数据Byte哪些是CMD Byte来定义,但是基本不需要改什么。

 

OK!大功告成,生成比特流后就可以跑啦。之后,由于已经没有IP核的限制,想怎么改就怎么改了。唯一的缺点是不能使用debug core了。不过我自己写了个AXI 转RIU的IP,再用一个Swicth在calibration完成后将RIU总线控制权交给我的IP也就是ZYNQ中的ARM。这样,我就可以在calibration完成后始读取或者修改所有硬件参数啦!

做了这么多,成功在FCCM上发了一篇论文~名字是 “Runtime Detection of Probing/Tampering on Interconnecting Buses”,2021年刚中,大家有兴趣可以去看看。基本就是通过修改延时来实现对一些probe的侦测。

由于修改过程过于复杂,很可能有我漏掉的细节,如果真有人闲的蛋疼也要改DDR4的物理层的话遇到问题可以问我哦~

你可能感兴趣的:(fpga,ddr)