在上篇文章中,主要结合IP配置界面介绍了一下Aurora8B10B,这篇文章将结合文档来学习一下Aurora8B10B内部的一些细节 和 相关的时序吧。文档主要是参考的是这个 pg046-aurora-8b10b-en-us-11.1
在手册上,对Aurora8B10B的内部并没有做非常信息的说明,所以我们也不用纠结的特别深入,大概的了解一下有效带宽和延时大概是多少就可以了,重点还是放在如何使用上。
需要注意的点,就以上三点,其它更细节的地方可以去研究官方文档。
微信公众号 : FPGA之旅 出品
这部分才是学习的重点,同样对于一些不重要的信号,或者这个信号很重要,但是在我使用的过程中,这个重要的信号我不care的,在下面的介绍中就一笔带过了,有对应需求的可以在官方文档里快速查找对应信号的功能(这样介绍起来,毕竟太费键盘了O(∩_∩)O)。
本次设计的IP配置如下(上篇文章中 已经对IP的配置进行了详细的讲解):
最后得到的端口信号如下,接口信号挺多的,但是设计上使用到的却只有那么几个而已,和DDR MIG IP差不多,下面就按类别进行介绍。
// 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] ),
// Status
.lane_up ( ),
.channel_up ( channel_up ),
? 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 ( ),
//DRP Ports
.drpclk_in ( init_clk_out ),
.drpaddr_in ( 'd0 ),
.drpen_in ( 'd0 ),
.drpdi_in ( 'd0 ),
.drprdy_out ( ),
.drpdo_out ( ),
.drpwe_in ( 1'b0 ),
//____________________________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 ( )
.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拉高了。就可以根据时序图正常进行读写操作了。到这里就结束了,可以根据自己需要进行读写设计了。