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核的“心脏”和“大脑”,一定要认真对待。
最后再啰嗦一句:我建议你在顶层模块里,把所有的用户接口信号(s_axi_tx_* 和 m_axi_rx_*)都先拉到模块端口上。这样调试时,你可以直接用ILA抓波形,不用再改代码。省心省力。
公众号:蓝海资料掘金营,微信deep3321