4. DRP 接口原理

DRP 接口,说白了就是 GTY 内部的配置通道。你想动态改那些高速参数,比如 CDR 频率、差分摆幅、均衡强度,都得通过它。我个人觉得理解 DRP,基本就拿到了动态重配置的钥匙。

好,我们正式开始。这节内容分四个部分:总线协议、地址映射、读写时序、跨时钟域处理。

4.1 DRP 总线协议

DRP 用的是简单的同步并行总线。说白了就三组信号是核心:地址总线、数据总线和控制信号。

信号分类 信号名 方向 描述
地址总线 DRPADDR[8:0] 输入 9位地址,可寻址 512 个寄存器
数据总线 DRPDI[15:0] 输入 写数据通道
数据总线 DRPDO[15:0] 输出 读数据通道
控制信号 DRPEN 输入 操作使能
控制信号 DRPWE 输入 写使能(1=写,0=读)
状态信号 DRPRDY 输出 操作完成标志
我的小经验: 这些信号在 GTY 的原语例化里都有。确保你把 DRPCLK 也连上,我见过有人忘连时钟,结果 DRP 怎么都不响应,查了半天才发现。

4.2 地址映射

GTY Quad 里的每个通道(CH0 ~ CH3)都有独立的 DRP 地址空间。记住一个关键点:地址的高位是通道选择位。

我个人习惯用这样的方式记忆:

  • A[8:7]:通道选择。00=CH0,01=CH1,10=CH2,11=CH3
  • A[6:0]:寄存器偏移地址。每个通道内部有 128 个寄存器

举个例子,CH1 的 TX 偏置控制寄存器,地址是 8'b01_0001010。这里的 01 就是 CH1,后面就是寄存器内部偏移。

坑!千万注意: 同一 Quad 内所有通道共享同一个 DRP 接口。你写地址时如果通道号写错了,就可能改了别的通道的配置。我曾经踩过这个坑,调试眼图时发现 CH0 的眼图变了,结果一查,是代码里把 CH0 和 CH1 的地址搞混了。

4.3 读写时序

DRP 的时序比较简单。但它对时钟频率有要求——DRPCLK 最高只能跑到 200MHz。如果你用 300MHz 去敲它,数据可能就错了。

读操作时序

// 读操作步骤
// 1. 拉高 DRPEN,拉低 DRPWE(读模式)
// 2. 给出 DRPADDR
// 3. 等待 DRPRDY 拉高
// 4. 从 DRPDO 上读取数据

always @(posedge drp_clk) begin
    if (drp_rd_start) begin
        drp_state  <= DRP_READ;
        DRPEN      <= 1'b1;
        DRPWE      <= 1'b0;
        DRPADDR    <= rd_addr;
    end
    
    if (drp_state == DRP_READ && DRPRDY) begin
        rd_data    <= DRPDO;
        DRPEN      <= 1'b0;
        drp_state  <= DRP_IDLE;
    end
end

写操作时序

// 写操作步骤
// 1. 拉高 DRPEN,拉高 DRPWE(写模式)
// 2. 给出 DRPADDR 和 DRPDI
// 3. 等待 DRPRDY 拉高
// 4. 写完成

always @(posedge drp_clk) begin
    if (drp_wr_start) begin
        drp_state  <= DRP_WRITE;
        DRPEN      <= 1'b1;
        DRPWE      <= 1'b1;
        DRPADDR    <= wr_addr;
        DRPDI      <= wr_data;
    end
    
    if (drp_state == DRP_WRITE && DRPRDY) begin
        DRPEN      <= 1'b0;
        drp_state  <= DRP_IDLE;
    end
end

你看,每次操作只需要一个上升沿来发起,然后等待 DRPRDY 拉高就行了。但要注意:DRPRDY 不会在一个周期内就变高,中间会有几个周期的延迟,具体看 DRPCLK 的频率。

关键时间参数: DRPRDY 通常在操作发起后 2~10 个 DRPCLK 周期内拉高。写操作一般比读操作快一点,因为写是纯内部配置,读则需要从寄存器里把数据搬出来。

4.4 跨时钟域处理

你的用户逻辑多半跑在 300MHz 以上,但 DRP 只能跑 200MHz。这就引出了跨时钟域问题。

我的做法是搞一个异步 FIFO,专门做跨时钟域同步。用户侧写请求写 FIFO,DRP 侧从 FIFO 读操作去执行。这样两边时钟域就隔离开了。

为什么一定要这么做?因为你不能直接把用户时钟域的使能信号打到 DRP 时钟域去。单拍的亚稳态风险很高,尤其是在温度或电压波动大的时候。

我个人习惯: 用两个同步器做地址和数据的跨时钟域传递。但更省心的方案是直接用 FIFO,集成现成的 IP,还能顺便做 buffer,防止用户突发写把 DRP 冲垮。

好了,这节的核心知识点差不多就是这些。下面这张图把整个 DRP 交互路径画出来了,你对着看会更清楚。

DRP 接口操作核心流程 用户逻辑 (fast clk) 异步 FIFO DRP 状态机 (slow clk) 触发读/写 等待 DRPRDY 操作完成 回写 FIFO 跨时钟域边界 Arbiter + Sync GTY Quad DRP 接口 选中的通道寄存器 关键:地址高位 A[8:7] 选通道,低位 A[6:0] 选寄存器;读写需等待 DRPRDY 才能发起下一操作

图里把整个流程串起来了。从用户逻辑写入异步 FIFO,再到 DRP 状态机以慢时钟从 FIFO 读出指令、执行读写、等待 DRPRDY,最后把结果回写。这个 FIFO 既是跨时钟域的桥梁,也是流量控制的关键。