阅读量:2
AURORA 仿真验证
定义:AURORA是一种高速串行通信协议,通常用于在数字信号处理系统和其他电子设备之间传输数据。它提供了一种高效的方式来传输大量数据,通常用于需要高带宽和低延迟的应用中。AURORA协议通常由Xilinx公司的FPGA器件支持,它使用了一种特殊的编码和时钟恢复机制来实现可靠的数据传输。
本实验仅仅演示了如何快速将AURORA使用起来,理论知识见以下参考文章:
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 Interface input [0:255] axi_tx_tdata, input axi_tx_tvalid, input [0:31] axi_tx_tkeep, input axi_tx_tlast, output axi_tx_tready, //RX Interface output [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 ); //接收AURORA aurora_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 ); //发送AURORA aurora_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; end endmodule
代码分析:
首先,产生一个125MHZ的时钟
clk_125m
然后生成差分时钟
clk_125m_p ,clk_125m_n
使用锁相环产生50MHZ时钟
clk_50M
接下来例化了两次AURORA,一个是接收,另一个是发送
上面的tb代码,仿真了两个AURORA传输数据的功能
备注:reset_pb拉高5us,然后再拉低