平台:vivado2017.4
芯片:xc7k325tfbg676-2 (active)
关于Aurora的开发学习。使用xilinx官方提供的IP核。
官方资料,pg046-aurora-8b10b.pdf和pg074-aurora-64b66b-en-us-12.0.pdf。
IP核的生成步骤
首先在IP Catalog中搜索Aurora IP核关于此IP有两种不同的IP,分别对应两种不同的编码方式和两份文档(PG046和PG074)。
这里先选择Aurora 8B/10B。
Component name | IP默认的名字 |
Lane width | 选择在IP中使用的收发器字节宽度,以及TX和RX位宽。 |
Lane rate | 范围0.5-6.6Gb/s。(64B/66B模式下支持10.3.125)。核心的总数据速率为(0.8*lane rate) |
GT Refclk(MHZ) | 参考时钟频率,取决于所选择的lane rate。 |
INIT clk(MHZ) | 输入一个有效的INIT时钟速率。 |
DRP clk(MHZ) | 输入一个有效的DRP时钟频率。(INIT clk和DRP clk相同) |
Dataflow Mode | 通信模式。仅TX和仅RX已经全双工。 |
Interface | 接口模式,可以选择Framing和Streaming两种模式。 |
Flow Control | 流控。 UFC允许用户应用程序发送一个简短的、高优先级的消息。 NFC允许全双工接收器调节发送给他们的数据速率。 Immediate允许在数据帧中插入空闲代码。 Completion 只在完整的数据帧之间插入空闲代码。 |
Back Channel | 默认。 |
Use Scrambler/Descrambler | 使用加扰器和解扰器,为了确保在长时间内不出现重复的数据。默认不使用。 |
Little Endian Support | 小端模式,数据传输时先传输高位为大端模式,先传输低位为小端模式。 |
Vivado Lab Tools | 此选项将为example project创建ila在线逻辑分析仪。 |
Use CRC | 用以检测一个数据包是否在传输中发生错误。 |
第二页设置
GT选择
在学习GTX的时候知道,一个Quad里面有四组GTXE2_CHANNEL,一个QPLL和一对差分输入。每个GTXE2_CHANNEL包含一组TX和RX,以及一个CPLL。
这里lane可以选择为1到16个。默认选择一个。
第三页
共享逻辑选择
默认将共享逻辑放入example design
IP核的接口和含义
下面我们看一下IP核的整体接口。分别介绍IP的各个接口的意义。
用户测端口介绍。
名字 | 方向 | 时钟域 | 描述 |
USER_DATA_S_AXI_TX | |||
s_axi_tx_tdata | 输入 | user_clk | 正在输出的数据 |
s_axi_tx_tready | 输出 | user_clk | 核已经准备好发送数据 |
s_axi_tx_tlast | 输入 | user_clk | 当前发送的最后一个数据 |
s_axi_tx_tkeep | 输入 | user_clk | 指定最后一个数据中的有效字节。 |
s_axi_tx_tvalid | 输入 | user_clk | 用户发送数据有效。 |
USER_DATA_S_AXI_TX | |||
m_axi_rx_tdata | 输出 | user_clk | 接收的数据 |
m_axi_rx_tlast | 输出 | user_clk | 最后一个数据 |
m_axi_rx_tkeep | 输出 | user_clk | 最后一个数据中的有效字节。 |
m_axi_rx_tvalid | 输出 | user_clk | 接收的数据有效 |
状态和控制端口
名字 | 方向 | 时钟域 | 描述 |
Channel up | 输出 | user_clk | 当Aurora 8B/10B通道初始化完成且该通道已准备好进行数据传输时有效。 |
lane_up | 输出 | user_clk | 在成功初始化时为每个lane断言,每个位代表一个lane。 |
frame_err | 输出 | user_clk | 检测到信道帧/协议错误 |
hard_err | 输出 | user_clk | 检测到硬错误(在Aurora 8B/10B核心复位之前确认) |
soft_err | 输出 | user_clk | 在传入的串行流中检测到软错误 |
reset | 输入 | async | 重置Aurora 8B/10B核心(活动-高)。该信号必须断言至少6个user_clk周期。 |
gt_reset | 输入 | async | 收发器的复位信号通过解冻器连接到顶层。在硬件中首次启动模块时,应断言gt_reset端口。这将系统地重置收发器的所有物理编码子层(PCS)和物理介质附件(PMA)子组件。信号使用init_clk_in,必须断言6个init_clk_in周期。 |
link_reset_out | 输出 | init_clk | 热插拔计数过期驱动高 |
init_clk_in | 输入 | NA | init_clk_in端口是必需的,因为user_clk会在断言gt_reset时停止。建议为init_clk_in选择的频率应低于GT参考时钟输入频率。 |
时钟接口
名字 | 方向 | 描述 |
pll_not_locked | 输入 | 如果使用PLL作为Aurora核心生成时钟,则pll_not_locked信号应该连接到PLL锁定信号的倒数。如果PLL不用于Aurora8B/10B核心生成时钟信号。则将pll_not_locked接地。 |
user_clk | 输入 | 核和用户应用程序共享的并行时钟。 |
sync_clk | 输入 | 由收发器内部同步逻辑所使用的并行时钟。 |
用户侧数据接口时序。
Framing Interface
Streaming Interface
接口的数据传输都是在AXI总线下完成的,
Framing模式下:发送tvalid和tready同时有效时数据有效,同时需要tlast指示当前最后一个数据。接收时tvalid有效时数据有效,tlast指示最后一个数据。
Streaming模式下:发送tvalid和tready同时有效时数据有效。接收时tvalid有效时数据有效。感兴趣可以去看一下AXI总线协议。在来理解这个就很简单了。
(161条消息) AXI总线,AXI_BRAM读写仿真测试_爱漂流的易子的博客-CSDN博客
Aurora 8B/10B模式下的工程仿真
现在打开example project
打开设计示例,可以看到该示例
示例的工程结构和GTX的例子工程结构一致的。
模块 | 作用 |
aurora_8b10b_0_support | 例化Aurora,例化时钟,复位,原语等。 |
aurora_8b10b_0_CLOCK_MODULE | 产生user_clk和sync_clk等时钟 |
aurora_8b10b_0_SUPPORT_RESET_LOGIC | 产生系统复位和GT复位 |
aurora_8b10b_0_gt_common_wrapper | 例化GTX原语 |
aurora_8b10b_0_LL_TO_AXI_EXDES | 将FRAME_GEN产生的数据信号转化为AXI信号。 |
aurora_8b10b_0_FRAME_GEN | 重要模块,TX数据产生模块。 |
aurora_8b10b_0_AXI_TO_LL_EXDES | 将核接收到的数据转换为RX数据 |
aurora_8b10b_0_FRAME_CHECK | 检查接收到的数据,是否正常。 |
为了方便测试,我们先看一下xilinx提供的TB的结构。
模块之间RX和TX互连。
下面分析一下aurora_8b10b_0_FRAME_GEN模块。让数据动起来。从模块的代码中可以看到,FRAMEE_GEN模块发送提供的代码为生成Generate random data using XNOR feedback LFSR。
//______________________________ Transmit Data __________________________________
//Generate random data using XNOR feedback LFSR
always @(posedge USER_CLK)
if(reset_c)
begin
data_lfsr_r <= `DLY 16'hABCD; //random seed value
end
else if(!TX_DST_RDY_N && !idle_r)
begin
data_lfsr_r <= `DLY {!{data_lfsr_r[3]^data_lfsr_r[12]^data_lfsr_r[14]^data_lfsr_r[15]},data_lfsr_r[0:14]};
end
产生随机数。在这之前需要了解一下LocalLink和AXI4-Stream总线之间的转换,xilinx提供的example模板是使用的LocalLink总线数据收发,后来改成了AXI4-Stream,我们需要先了解一下各个信号的对应关系。当然也可以不使用xilinx提供的example project工程思路,直接使用AXI总线向Aurora IP核内发数据,结果也是一致的。
先看一下两者的转换代码。
///
// (c) Copyright 2010 Xilinx, Inc. All rights reserved.
//
// This file contains confidential and proprietary information
// of Xilinx, Inc. and is protected under U.S. and
// international copyright and other intellectual property
// laws.
//
// DISCLAIMER
// This disclaimer is not a license and does not grant any
// rights to the materials distributed herewith. Except as
// otherwise provided in a valid license issued to you by
// Xilinx, and to the maximum extent permitted by applicable
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
// (2) Xilinx shall not be liable (whether in contract or tort,
// including negligence, or under any other theory of
// liability) for any loss or damage of any kind or nature
// related to, arising under or in connection with these
// materials, including for any direct, or any indirect,
// special, incidental, or consequential loss or damage
// (including loss of data, profits, goodwill, or any type of
// loss or damage suffered as a result of any action brought
// by a third party) even if such damage or loss was
// reasonably foreseeable or Xilinx had been advised of the
// possibility of the same.
//
// CRITICAL APPLICATIONS
// Xilinx products are not designed or intended to be fail-
// safe, or for use in any application requiring fail-safe
// performance, such as life-support or safety devices or
// systems, Class III medical devices, nuclear facilities,
// applications related to the deployment of airbags, or any
// other applications that could lead to death, personal
// injury, or severe property or environmental damage
// (individually and collectively, "Critical
// Applications"). Customer assumes the sole risk and
// liability of any use of Xilinx products in Critical
// Applications, subject only to applicable laws and
// regulations governing limitations on product liability.
//
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
// PART OF THIS FILE AT ALL TIMES.
//
//
///
//
// LL_TO_AXI
//
//
// Description: This light wrapper/shim convertes Legacy LocalLink interface
// signals to AXI-4 Stream protocol signals
//
//
///
`timescale 1 ns/1 ps
(* core_generation_info = "aurora_8b10b_0,aurora_8b10b_v11_1_3,{user_interface=AXI_4_Streaming,backchannel_mode=Sidebands,c_aurora_lanes=1,c_column_used=left,c_gt_clock_1=GTXQ0,c_gt_clock_2=None,c_gt_loc_1=1,c_gt_loc_10=X,c_gt_loc_11=X,c_gt_loc_12=X,c_gt_loc_13=X,c_gt_loc_14=X,c_gt_loc_15=X,c_gt_loc_16=X,c_gt_loc_17=X,c_gt_loc_18=X,c_gt_loc_19=X,c_gt_loc_2=X,c_gt_loc_20=X,c_gt_loc_21=X,c_gt_loc_22=X,c_gt_loc_23=X,c_gt_loc_24=X,c_gt_loc_25=X,c_gt_loc_26=X,c_gt_loc_27=X,c_gt_loc_28=X,c_gt_loc_29=X,c_gt_loc_3=X,c_gt_loc_30=X,c_gt_loc_31=X,c_gt_loc_32=X,c_gt_loc_33=X,c_gt_loc_34=X,c_gt_loc_35=X,c_gt_loc_36=X,c_gt_loc_37=X,c_gt_loc_38=X,c_gt_loc_39=X,c_gt_loc_4=X,c_gt_loc_40=X,c_gt_loc_41=X,c_gt_loc_42=X,c_gt_loc_43=X,c_gt_loc_44=X,c_gt_loc_45=X,c_gt_loc_46=X,c_gt_loc_47=X,c_gt_loc_48=X,c_gt_loc_5=X,c_gt_loc_6=X,c_gt_loc_7=X,c_gt_loc_8=X,c_gt_loc_9=X,c_lane_width=2,c_line_rate=31250,c_nfc=false,c_nfc_mode=IMM,c_refclk_frequency=125000,c_simplex=false,c_simplex_mode=TX,c_stream=false,c_ufc=false,flow_mode=None,interface_mode=Framing,dataflow_config=Duplex}" *)
module aurora_8b10b_0_LL_TO_AXI_EXDES #
(
parameter DATA_WIDTH = 16, // DATA bus width
parameter STRB_WIDTH = 2, // STROBE bus width
parameter USE_UFC_REM = 0, // UFC REM bus width identifier
parameter USE_4_NFC = 0, // 0 => PDU, 1 => NFC, 2 => UFC
parameter BC = DATA_WIDTH/8, //Byte count
parameter REM_WIDTH = 1 // REM bus width
)
(
// LocalLink input Interface
LL_IP_DATA,
LL_IP_SOF_N,
LL_IP_EOF_N,
LL_IP_REM,
LL_IP_SRC_RDY_N,
LL_OP_DST_RDY_N,
// AXI4-S output signals
AXI4_S_OP_TVALID,
AXI4_S_OP_TDATA,
AXI4_S_OP_TKEEP,
AXI4_S_OP_TLAST,
AXI4_S_IP_TREADY
);
`define DLY #1
//***********************************Port Declarations*******************************
// AXI4-Stream TX Interface
output [(DATA_WIDTH-1):0] AXI4_S_OP_TDATA;
output [(STRB_WIDTH-1):0] AXI4_S_OP_TKEEP;
output AXI4_S_OP_TVALID;
output AXI4_S_OP_TLAST;
input AXI4_S_IP_TREADY;
// LocalLink TX Interface
input [0:(DATA_WIDTH-1)] LL_IP_DATA;
input [0:(REM_WIDTH-1)] LL_IP_REM;
input LL_IP_SOF_N;
input LL_IP_EOF_N;
input LL_IP_SRC_RDY_N;
output LL_OP_DST_RDY_N;
wire [0:(STRB_WIDTH-1)] AXI4_S_OP_TKEEP_i;
//*********************************Main Body of Code**********************************
generate
if(USE_4_NFC==0)
begin
genvar i;
for (i=0; i<BC; i=i+1) begin: pdu
assign AXI4_S_OP_TDATA[((BC-1-i)*8)+7:((BC-1-i)*8)] = LL_IP_DATA[((BC-1-i)*8):((BC-1-i)*8)+7];
end
end
endgenerate
generate
genvar j;
for (j=0; j<STRB_WIDTH; j=j+1) begin: strb
assign AXI4_S_OP_TKEEP[j] = AXI4_S_OP_TKEEP_i[j];
end
endgenerate
assign AXI4_S_OP_TVALID = !LL_IP_SRC_RDY_N;
assign AXI4_S_OP_TLAST = !LL_IP_EOF_N;
assign AXI4_S_OP_TKEEP_i = (LL_IP_REM == 1'b1)? 2'b11:2'b10;
assign LL_OP_DST_RDY_N = !AXI4_S_IP_TREADY;
endmodule
可以看到:
AXI_DATA等于LL_DATA交换数据位值。
AXI_VALID等于LL_SRC_RDY的非。
AXI_LAST等于LL_EOF的非。
AXI_KEEP与LL_REM参数有关。
LL_DST_RDY等于AXI_READY有关。
从仿真图中也可以看出来。
所以我们在FRAMEE_GEN模块中修改数据发送代码如下。
//______________________________ Transmit Data __________________________________
//Generate random data using XNOR feedback LFSR
always @(posedge USER_CLK)
if(reset_c)
begin
data_lfsr_r <= `DLY 16'hABCD; //random seed value
end
else if(!TX_DST_RDY_N && !idle_r)
begin
if(data_lfsr_r == 16'hABCD)
data_lfsr_r <= `DLY 16'h0000;
else
data_lfsr_r <= `DLY data_lfsr_r + 16'h1;
end
//Connect TX_D to the DATA LFSR
assign TX_D = {1{data_lfsr_r}};
//Tie DATA LFSR to REM to generate random words
// assign TX_REM = data_lfsr_r[0:0];
assign TX_REM = 1'b1;
发送从0递增的有效数据。这里也可以设置为从FIFO中读出数据(好应用)。我们这里直接将发送的第一个数据设置为0,在后续的情况下,数据值累加。并设置TX_REM为一,保证最后一个传输的数据位全部有效。
同时在接收模块,设置接收的验证数据也是从0递增的。判断是否出现错误数据。
//generate expected RX_D using LFSR
always @(posedge USER_CLK)
if(reset_c)
begin
// data_lfsr_r <= `DLY 16'hD5E6; //random seed value
data_lfsr_r <= `DLY 16'h0000; //random seed value
end
else if(CHANNEL_UP)
begin
if(data_valid_c)
// data_lfsr_r <= `DLY {!{data_lfsr_r[3]^data_lfsr_r[12]^data_lfsr_r[14]^data_lfsr_r[15]},data_lfsr_r[0:14]};
begin
if(data_lfsr_r == 16'hABCD)
data_lfsr_r <= `DLY 16'h0000;
else
data_lfsr_r <= `DLY data_lfsr_r + 16'h1;
end
end
else
begin
// data_lfsr_r <= `DLY 16'hD5E6; //random seed value
data_lfsr_r <= `DLY 16'h0000; //random seed value
end
assign data_lfsr_concat_w = {1{data_lfsr_r}};
发送模块的仿真。可以看到发送的数据为0,1,2,3,4。
接收模块的仿真。可以看到接收的数据为0,1,2,3,4。