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,然后再拉低