4、Aurora核的生成与例化:生成IP核输出产物、在顶层模块中例化Aurora核、连接时钟与复位信号

好,咱们接着往下走。上一节我们把Vivado工程搭好了,也把Aurora IP核的配置界面过了一遍。这一节,我带你亲手把它“生”出来,然后正确地例化到你的顶层模块里。

说白了,IP核就是个黑盒子。你给它配好参数,Vivado会帮你生成一堆文件。你得知道哪些文件有用,哪些是干啥的。不然工程一复杂,你连找啥都找不到。

4.1 生成IP核后的输出产物

点击“Generate”之后,Vivado会跑一会儿。我习惯泡杯咖啡等着。生成完毕后,你会在IP Sources面板里看到一堆东西。别慌,我帮你捋一捋。

核心产物就这几样:

  • 例化模板(.veo):这是最直接的。Vivado会给你生成一个Verilog例化模板,你直接复制粘贴到顶层模块里就行。省时省力。
  • 网表文件(.ngc / .dcp):这是IP核的物理实现。说白了就是布局布线后的“黑盒”。你不能改它,只能用它。
  • 仿真模型(.v / .vhd):用于仿真。我建议你仿真时用这个模型,别用综合后的网表,不然仿真慢得你想哭。
  • XDC约束文件(.xdc):里面包含了IP核的时钟、复位、以及一些时序例外约束。这个文件会自动被Vivado识别,你一般不用手动改。
  • 文档(.pdf):嗯,这个我建议你至少翻一翻。尤其是“Clocking”和“Resets”章节,我踩过坑。

我个人习惯:生成IP后,第一件事就是打开.veo文件,把例化模板复制出来。然后看一眼XDC文件,确认时钟频率和复位极性对不对。这一步能避免很多低级错误。

4.2 在顶层模块中例化Aurora核

好,现在我们来写顶层模块。你打开.veo文件,会看到类似下面的代码。我稍微整理了一下,加上了我自己的注释。

// aurora_64b66b_0 是IP核的名字,你生成时可能不一样
aurora_64b66b_0 u_aurora_64b66b_0 (
    // 用户时钟与复位
    .user_clk_out        (user_clk),          // 输出:用户逻辑时钟
    .reset_pb            (reset_pb),          // 输入:按键复位(低有效)
    .gt_reset            (gt_reset),          // 输入:GT复位
    .pll_not_locked      (pll_not_locked),    // 输入:PLL失锁指示

    // GT接口
    .gt_rxp_in           (gt_rxp_in),         // 输入:GT RX正极
    .gt_rxn_in           (gt_rxn_in),         // 输入:GT RX负极
    .gt_txp_out          (gt_txp_out),        // 输出:GT TX正极
    .gt_txn_out          (gt_txn_out),        // 输出:GT TX负极

    // 用户接口
    .s_axi_tx_tdata      (s_axi_tx_tdata),    // 输入:发送数据
    .s_axi_tx_tkeep      (s_axi_tx_tkeep),    // 输入:发送数据使能
    .s_axi_tx_tlast      (s_axi_tx_tlast),    // 输入:发送数据结束
    .s_axi_tx_tready     (s_axi_tx_tready),   // 输出:发送就绪
    .s_axi_tx_tvalid     (s_axi_tx_tvalid),   // 输入:发送数据有效

    .m_axi_rx_tdata      (m_axi_rx_tdata),    // 输出:接收数据
    .m_axi_rx_tkeep      (m_axi_rx_tkeep),    // 输出:接收数据使能
    .m_axi_rx_tlast      (m_axi_rx_tlast),    // 输出:接收数据结束
    .m_axi_rx_tvalid     (m_axi_rx_tvalid),   // 输出:接收数据有效

    // 状态与控制
    .channel_up          (channel_up),        // 输出:通道建立
    .lane_up             (lane_up),           // 输出:Lane建立
    .hard_err            (hard_err),          // 输出:硬错误
    .soft_err            (soft_err),          // 输出:软错误
    .tx_out_clk          (tx_out_clk)         // 输出:发送时钟
);

你可能会问:“这么多信号,我都要连吗?” 嗯,其实不是。有些信号是必须的,有些是可选的。我建议你一开始把所有的都连上,调试时方便观察。等稳定了再精简。

一个小技巧:我在项目中遇到过,有些工程师为了省事,把不用的信号直接悬空了。结果调试时发现通道死活起不来。后来一查,是复位信号没处理好。所以,所有输入信号都必须有驱动,所有输出信号都必须有接收。哪怕你暂时不用,也要接个寄存器或者拉高拉低。

4.3 连接时钟与复位信号

时钟和复位,是Aurora核的命脉。连错了,整个系统都跑不起来。我见过太多人在这上面栽跟头了。

时钟连接

  • user_clk_out:这是Aurora核输出给你的用户逻辑时钟。频率等于线速率除以40(对于64b66b编码)。比如线速率是10.3125 Gbps,那么user_clk就是257.8125 MHz。你所有的用户逻辑(发送/接收FIFO、状态机等)都应该用这个时钟。
  • tx_out_clk:这是GT的发送时钟。一般不用,除非你要做特殊的时钟域处理。
  • gt_refclk:这是GT的参考时钟。在IP核配置时指定,一般来自板上的差分晶振。你需要在顶层模块里把这个时钟连到IP核的对应引脚上。

复位连接

  • reset_pb:这是按键复位,低有效。我建议你用一个外部按键或者上电复位芯片来驱动它。不要直接用逻辑里的复位信号,因为Aurora核初始化时需要一段稳定的复位时间。
  • gt_reset:这是GT复位。一般和reset_pb连在一起,或者用一个更长的复位脉冲。我曾经遇到过,gt_reset脉冲太短,导致GT PLL锁不住。后来我改成至少100us的复位脉冲,问题就解决了。
  • pll_not_locked:这是PLL失锁指示。如果这个信号为高,说明GT PLL没锁住,通道肯定起不来。我习惯把这个信号接到一个LED上,方便调试时观察。

注意:复位信号的处理,一定要看你的板卡手册。有些板卡的复位是低有效,有些是高有效。极性搞反了,IP核永远无法初始化。我刚开始做Aurora时,就因为这个折腾了两天。

4.4 核心逻辑流程图

下面这张图,是我自己总结的Aurora核例化与时钟复位连接的核心流程。你照着这个做,基本不会出错。

Aurora核例化与时钟复位连接流程 步骤1:生成IP核 步骤2:打开.veo文件,复制例化模板 步骤3:在顶层模块中例化,连接所有信号 步骤4:连接时钟(user_clk_out驱动用户逻辑,gt_refclk来自晶振) 步骤5:连接复位(reset_pb低有效,gt_reset脉冲≥100us) 完成

嗯,这张图把整个流程串起来了。你照着做,基本不会漏掉什么。记住,时钟和复位是Aurora核的“心脏”和“大脑”,一定要认真对待。

最后再啰嗦一句:我建议你在顶层模块里,把所有的用户接口信号(s_axi_tx_* 和 m_axi_rx_*)都先拉到模块端口上。这样调试时,你可以直接用ILA抓波形,不用再改代码。省心省力。


公众号:蓝海资料掘金营,微信deep3321