AURORA 仿真验证
定义:AURORA是一种高速串行通信协议,通常用于在数字信号处理系统和其他电子设备之间传输数据。它提供了一种高效的方式来传输大量数据,通常用于需要高带宽和低延迟的应用中。AURORA协议通常由Xilinx公司的FPGA器件支持,它使用了一种特殊的编码和时钟恢复机制来实现可靠的数据传输。
本实验仅仅演示了如何快速将AURORA使用起来,理论知识见以下参考文章:
Aurora IP简介-CSDN博客
Aurora 8B/10B IP核(2)----Aurora概述及数据接口(Framing接口、Streaming接口)_xinlinx中的aurora协议中端口解释-CSDN博客
IP 核设计
这里主要注意时钟的设计和线程的安排
Aurora的输入时钟:
GT Refclk:该时钟是收发器的参考时钟,由外部一对差分输入时钟输入进来,取125MHZ。
INT Clk:初始化时钟,作为复位信号的一个时钟,可以由锁相环直接得到,取50MHZ
例化IP核
module aurora_top(input [0:3] RXP,input [0:3] RXN,output [0:3] TXP,output [0:3] TXN,input gt_refclk_p,input gt_refclk_n,input init_clk,input reset,input power_down,input [2:0] loopback,output channel_up,output [0:3] lane_up,output gt_pll_lock,output user_clk_out,output tx_out_clk,//TX Interfaceinput [0:255] axi_tx_tdata,input axi_tx_tvalid,input [0:31] axi_tx_tkeep,input axi_tx_tlast,output axi_tx_tready,//RX Interfaceoutput [0:255] axi_rx_tdata,output axi_rx_tvalid,output [0:31] axi_rx_tkeep,output axi_rx_tlast);aurora_64b66b_0 u_aurora_64b66b_0 (.rxp (RXP), // input wire [0 : 3] rxp.rxn (RXN), // input wire [0 : 3] rxn.reset_pb (reset), // input wire reset_pb.power_down (power_down), // input wire power_down.pma_init (1'b0), // input wire pma_init.loopback (loopback), // input wire [2 : 0] loopback.txp (TXP), // output wire [0 : 3] txp.txn (TXN), // output wire [0 : 3] txn.hard_err (), // output wire hard_err.soft_err (), // output wire soft_err.channel_up (channel_up), // output wire channel_up.lane_up (lane_up), // output wire [0 : 3] lane_up.tx_out_clk (tx_out_clk), // output wire tx_out_clk.gt_pll_lock (gt_pll_lock), // output wire gt_pll_lock.s_axi_tx_tdata (axi_tx_tdata), // input wire [0 : 255] s_axi_tx_tdata.s_axi_tx_tkeep (axi_tx_tkeep), // input wire [0 : 31] s_axi_tx_tkeep.s_axi_tx_tlast (axi_tx_tlast), // input wire s_axi_tx_tlast.s_axi_tx_tvalid (axi_tx_tvalid), // input wire s_axi_tx_tvalid.s_axi_tx_tready (axi_tx_tready), // output wire s_axi_tx_tready.m_axi_rx_tdata (axi_rx_tdata), // output wire [0 : 255] m_axi_rx_tdata.m_axi_rx_tkeep (axi_rx_tkeep), // output wire [0 : 31] m_axi_rx_tkeep.m_axi_rx_tlast (axi_rx_tlast), // output wire m_axi_rx_tlast.m_axi_rx_tvalid (axi_rx_tvalid), // output wire m_axi_rx_tvalid.mmcm_not_locked_out (), // output wire mmcm_not_locked_out.gt0_drpaddr (10'd0), // input wire [9 : 0] gt0_drpaddr.gt1_drpaddr (10'd0), // input wire [9 : 0] gt1_drpaddr.gt2_drpaddr (10'd0), // input wire [9 : 0] gt2_drpaddr.gt3_drpaddr (10'd0), // input wire [9 : 0] gt3_drpaddr.gt0_drpdi (16'd0), // input wire [15 : 0] gt0_drpdi.gt1_drpdi (16'd0), // input wire [15 : 0] gt1_drpdi.gt2_drpdi (16'd0), // input wire [15 : 0] gt2_drpdi.gt3_drpdi (16'd0), // input wire [15 : 0] gt3_drpdi.gt0_drprdy (), // output wire gt0_drprdy.gt1_drprdy (), // output wire gt1_drprdy.gt2_drprdy (), // output wire gt2_drprdy.gt3_drprdy (), // output wire gt3_drprdy.gt0_drpwe (1'b0), // input wire gt0_drpwe.gt1_drpwe (1'b0), // input wire gt1_drpwe.gt2_drpwe (1'b0), // input wire gt2_drpwe.gt3_drpwe (1'b0), // input wire gt3_drpwe.gt0_drpen (1'b0), // input wire gt0_drpen.gt1_drpen (1'b0), // input wire gt1_drpen.gt2_drpen (1'b0), // input wire gt2_drpen.gt3_drpen (1'b0), // input wire gt3_drpen.gt0_drpdo (), // output wire [15 : 0] gt0_drpdo.gt1_drpdo (), // output wire [15 : 0] gt1_drpdo.gt2_drpdo (), // output wire [15 : 0] gt2_drpdo.gt3_drpdo (), // output wire [15 : 0] gt3_drpdo.init_clk (init_clk), // input wire init_clk.link_reset_out (), // output wire link_reset_out.gt_refclk1_p (gt_refclk_p), // input wire gt_refclk1_p.gt_refclk1_n (gt_refclk_n), // input wire gt_refclk1_n.user_clk_out (user_clk_out), // output wire user_clk_out.sync_clk_out (), // output wire sync_clk_out.gt_rxcdrovrden_in (1'b0), // input wire gt_rxcdrovrden_in.sys_reset_out (), // output wire sys_reset_out.gt_reset_out (), // output wire gt_reset_out.gt_refclk1_out (), // output wire gt_refclk1_out.gt_powergood () // output wire [3 : 0] gt_powergood
);endmodule
上面只是例化了这个IP核,把有用的信号引出来
TB仿真
module tb_aurora();wire [0:3]RXP;wire [0:3]RXN;wire [0:3]TXP;wire [0:3]TXN;reg locked;wire channel_up;wire [0:3]lane_up;wire axi_tx_tready;wire user_clk_out;wire channel_up1;wire [0:3]lane_up1;wire user_clk_out1;reg [0 : 255] axi_tx_tdata;reg axi_tx_tvalid;wire [0 : 255] axi_rx_tdata;wire axi_rx_tvalid;reg clk_125m;wire clk_125m_p;wire clk_125m_n;//125MHZ时钟initial clk_125m = 1;always #4 clk_125m = ~clk_125m;//产生差分时钟OBUFDS #(.IOSTANDARD("DEFAULT"), // Specify the output I/O standard.SLEW("SLOW") // Specify the output slew rate) OBUFDS_inst (.O(clk_125m_p), // Diff_p output (connect directly to top-level port).OB(clk_125m_n), // Diff_n output (connect directly to top-level port).I(clk_125m) // Buffer input);wire clk_50M;wire locked_0;//50M时钟clk_wiz_50M instance_name(// Clock out ports.clk_out50M(clk_50M), // output clk_out50M// Status and control signals.locked(locked_0), // output locked// Clock in ports.clk_in1_p(clk_125m_p), // input clk_in1_p.clk_in1_n(clk_125m_n) // input clk_in1_n ); //接收AURORAaurora_top u_aurora_64b66b_rev(.RXP (RXP), // input [0:3].RXN (RXN), // input [0:3].TXP (TXP), // output [0:3].TXN (TXN), // output [0:3].gt_refclk_p (clk_125m_p), // input.gt_refclk_n (clk_125m_n), // input.init_clk (clk_50M), // input.reset (~locked), // input.power_down (1'b0), // input //Drives the Aurora 64B/66B core to reset.loopback (3'b000), // input [2:0].channel_up (channel_up), // output.lane_up (lane_up), // output [0:3].gt_pll_lock (), // output.user_clk_out (user_clk_out), // output.tx_out_clk (), // output//TX Interface.axi_tx_tdata (), // input [0:255].axi_tx_tvalid (), // input.axi_tx_tkeep (), // input [0:31].axi_tx_tlast (), // input.axi_tx_tready (), // output//RX Interface.axi_rx_tdata (axi_rx_tdata), // output [0:255].axi_rx_tvalid (axi_rx_tvalid), // output.axi_rx_tkeep (axi_rx_tkeep), // output [0:31].axi_rx_tlast (axi_rx_tlast) // output);//发送AURORAaurora_top u_aurora_64b66b_set(.RXP (TXP), //input [0:3].RXN (TXN), //input [0:3].TXP (RXP), //output [0:3].TXN (RXN), //output [0:3].gt_refclk_p (clk_125m_p), //input.gt_refclk_n (clk_125m_n), //input.init_clk (clk_50M), //input.reset (~locked), //input.power_down (1'b0), //input //Drives the Aurora 64B/66B core to reset.loopback (3'b000), //input [2:0].channel_up (channel_up1), //output.lane_up (lane_up1), //output [0:3].gt_pll_lock (), //output.user_clk_out (user_clk_out1), //output.tx_out_clk (), //output//TX Interface.axi_tx_tdata (axi_tx_tdata ), // input [0:255].axi_tx_tvalid (axi_tx_tvalid ), // input.axi_tx_tkeep (32'hffff_ffff), // input [0:31].axi_tx_tlast (1'b0), // input.axi_tx_tready (axi_tx_tready), // output//RX Interface.axi_rx_tdata (), //output [0:255].axi_rx_tvalid (), //output.axi_rx_tkeep (), //output [0:31].axi_rx_tlast () //output);initial begin axi_tx_tdata = 256'h0;axi_tx_tvalid = 1'b0;locked = 1'b0;#5000;axi_tx_tdata = 256'h123456879abcdef;axi_tx_tvalid = 1'b1;locked = 1'b1;endendmodule
代码分析:
-
首先,产生一个125MHZ的时钟
clk_125m
-
然后生成差分时钟
clk_125m_p ,clk_125m_n
-
使用锁相环产生50MHZ时钟
clk_50M
-
接下来例化了两次AURORA,一个是接收,另一个是发送
上面的tb代码,仿真了两个AURORA传输数据的功能
备注:reset_pb拉高5us,然后再拉低