一. 简介
在上篇文章中,主要结合IP配置界面介绍了一下Aurora8B10B,这篇文章将结合文档来学习一下Aurora8B10B内部的一些细节 和 相关的时序吧。文档主要是参考的是这个 pg046-aurora-8b10b-en-us-11.1
二. Aurora8B10B内部细节
在手册上,对Aurora8B10B的内部并没有做非常信息的说明,所以我们也不用纠结的特别深入,大概的了解一下有效带宽和延时大概是多少就可以了,重点还是放在如何使用上。
- 数据: 在用户发送每一帧数据的时候,Aurora8B10都会在数据的开始位置增加2byte的SCP和末尾增加2btye的EOF来表示数据帧的开始和结束标志(如果用户的数据btye数为奇数的话,会为其增加额外的一个PAD byte来使数据为偶数)。所以为了最大传输带宽,用户每次传输的数据byte数最好为偶数。
- 时钟补偿: 传输通道每10000 bytes需要进行一次时钟补偿,每次时钟补偿需要发送12 bytes的数据,需要消耗6个或者3个时钟周期,在这期间用户是不能进行数据传输的,有效带宽又进一步减少了。
- 传输延时:从发送端发送第一个数据开始,到接收端接收到第一个数据结束所消耗的时间,最小的延时为41个用户时钟周期,对时延有要求的话,这里需要着重注意。
需要注意的点,就以上三点,其它更细节的地方可以去研究官方文档。
微信公众号 : FPGA之旅 出品
三. Aurora8B10B 模块信号
这部分才是学习的重点,同样对于一些不重要的信号,或者这个信号很重要,但是在我使用的过程中,这个重要的信号我不care的,在下面的介绍中就一笔带过了,有对应需求的可以在官方文档里快速查找对应信号的功能(这样介绍起来,毕竟太费键盘了O(∩_∩)O)。
本次设计的IP配置如下(上篇文章中 已经对IP的配置进行了详细的讲解):
- 数据位宽4Btyes,线速率6.25,GT Refclk 125M,INT(DRP) CLk 50,数据模式双向,接口是Framing,其它都没有选
- GT 收发器选择一个Lane,Shared Logic选择 in core,其它的都不勾选。
最后得到的端口信号如下,接口信号挺多的,但是设计上使用到的却只有那么几个而已,和DDR MIG IP差不多,下面就按类别进行介绍。
- IO信号: 连接到对应bank的IO Pin上
// GT Serial I/O
.rxp ( aurora_rxp_pin_i ),
.rxn ( aurora_rxn_pin_i ),
.txp ( aurora_txp_pin_o ),
.txn ( aurora_txn_pin_o ),
-
GT的参考时钟: 由外部差分时钟输入,引脚相对固定
// GT Reference Clock Interface .gt_refclk1_p ( gt_refclk1_p_i ), .gt_refclk1_n ( gt_refclk1_n_i ), .gt_refclk1_out ( gt_refclk1_out ),
-
错误标识信号: 当出现错误时,对应信号会拉高
// Error Detection Interface
.frame_err ( aurora_error[0] ),
.hard_err ( aurora_error[1] ),
.soft_err ( aurora_error[2] ),
- IP初始化成功信号: 当IP初始化成功,并且接收方与发送方握手成功后拉高,只需要对channel_up信号进行判断即可
// Status
.lane_up ( ),
.channel_up ( channel_up ),
- 系统接口: 只需要操作gt复位和系统复位两个信号即可,初始化时钟自行输入即可,可以是单端信号(IP配置时勾选即可)。这个两个复位信号是在初始化时钟域下进行的。
loopback用来设置回环模式的,power_down设置0即可正常工作
复位说明:
// System Interface
.sync_clk_out ( ),
.gt_reset ( gt_reset ),
.reset ( reset ),
.sys_reset_out ( ),
.gt_reset_out ( ),
.power_down ( 'd0 ),
.loopback ( 'd0 ),
.tx_lock ( ),
.init_clk_p ( init_clk_p_i ),
.init_clk_n ( init_clk_n_i ),
.init_clk_out ( init_clk_out ),
.tx_resetdone_out ( ),
.rx_resetdone_out ( ),
.link_reset_out ( ),
- 动态配置信号,在IP运行过程中,可以对其进行动态配置,一般来说,用不到,可以不用管
//DRP Ports
.drpclk_in ( init_clk_out ),
.drpaddr_in ( 'd0 ),
.drpen_in ( 'd0 ),
.drpdi_in ( 'd0 ),
.drprdy_out ( ),
.drpdo_out ( ),
.drpwe_in ( 1'b0 ),
- GT COMMON信号输出: 由于我们选择的是in core,所以在IP里面包含了这个模块,输出的信号可以给其他收发器使用。
//____________________________COMMON PORTS_______________________________{
.gt0_pll0refclklost_out ( ),
.quad1_common_lock_out ( ),
//----------------------- Channel - Ref Clock Ports ------------------------
.gt0_pll0outclk_out ( ),
.gt0_pll1outclk_out ( ),
.gt0_pll0outrefclk_out ( ),
.gt0_pll1outrefclk_out ( ),
//____________________________COMMON PORTS_______________________________}
.pll_not_locked_out ( )
- 用户接口: 最后就是我们的用户接口了,是一个非常简单的AXI stream接口 ,直接看时序图吧
.user_clk_out ( user_clk_out ),
// AXI TX Interface
.s_axi_tx_tdata ( s_axi_tx_tdata ),
.s_axi_tx_tkeep ( s_axi_tx_tkeep ),
.s_axi_tx_tvalid ( s_axi_tx_tvalid ),
.s_axi_tx_tlast ( s_axi_tx_tlast ),
.s_axi_tx_tready ( s_axi_tx_tready ),
// AXI RX Interface
.m_axi_rx_tdata ( m_axi_rx_tdata ),
.m_axi_rx_tkeep ( m_axi_rx_tkeep ),
.m_axi_rx_tvalid ( m_axi_rx_tvalid ),
.m_axi_rx_tlast ( m_axi_rx_tlast ),
其中tlast和tkeep两个信号需要注意一下,在发送接收一帧数据时,在最后一个数据需要tlast会拉高,同时tkeep会指示最后一个数据中有效的byte数是多少。
四. 仿真
仿真的时候,我们只需要给时钟和复位信号就可以了,主要观察到channel_up信号拉高了,就说名IP可以正常使用了, tb如下:
reg gt_reset;
reg reset;
reg aurora_rst_n_i;
reg gt_refclk1_p ;
reg gt_refclk1_n ;
reg init_clk_p ;
reg init_clk_n ;
wire aurora_rxp_pin ;
wire aurora_rxn_pin ;
wire aurora_txp_pin ;
wire aurora_txn_pin ;
assign aurora_rxp_pin = aurora_txp_pin;
assign aurora_rxn_pin = aurora_txn_pin;
always@(*) #2.5 gt_refclk1_p <= ~gt_refclk1_p;
always@(*) gt_refclk1_n <= ~gt_refclk1_p;
always@(*) #10 init_clk_p <= ~init_clk_p;
always@(*) init_clk_n <= ~init_clk_p;
initial begin
gt_refclk1_p = 1'b1;
gt_refclk1_n = 1'b0;
init_clk_p = 1'b1;
init_clk_n = 1'b0;
aurora_rst_n_i = 1'b1;
gt_reset = 1'b0;
reset = 1'b0;
#10
reset = 1'b1;
#100
gt_reset = 1'b1;
#1000
gt_reset = 1'b0;
#200
reset = 1'b0;
end
仿真到360us的时候,channel_up拉高了。就可以根据时序图正常进行读写操作了。到这里就结束了,可以根据自己需要进行读写设计了。