前言:
明确设计思路,精准定位问题,对于我们后期理解迭代工程有很大的帮助。
这就是我们常说的40%设计,20%编写和剩下的40%时间进行调试优化。
今天为大家带来的是通过理解手册和GT核复位状态机源码,解决GT核接收端复位完成标识位一直为低的原因。
问题:
由于CMOS经过配置后的数据输出只能观察到VS和HS,而四路视频流则通过GTP接口传输至FPGA,无法直接进行ILA抓取;
目前的设计是通过配置GT核后生成官方demo,进行更改从而接收数据流,通过观察rx_data来反映CMOS传输像素;
通过问题定位,发现本应该自动复位的GT核出现了RX_RESETDONE信号一直为低,即RX复位未完成。
AMD问题贴
UG482 GTP Transceivers:
Reset and Initialization:
GTP收发器必须在FPGA器件上电和配置后进行初始化,然后才能使用。GTP收发器的发射器(TX)和接收器(RX)可以独立并行初始化,如图2-11所示。GTP 收发器的 TX 和 RX 初始化包括两个步骤:
- 初始化关联的PLL驱动TX/RX
- 初始化 TX 和 RX 数据路径 (PMA + PCS)
GTP 收发器的 TX 和 RX 可以接收来自 PLL0 或 PLL1 的时钟。TX 和 RX 使用的关联 PLL (PLL0 /PLL1) 必须先初始化,然后再初始化 TX 和 RX。TX和RX使用的任何PLL都是单独复位的,其复位操作完全独立于所有TX和RX复位。TX 和 RX 数据路径只有在关联的 PLL 锁定后才能初始化。
通过官方手册可以发现只有当FPGA上电后,先进行锁相环复位,后对RX/TX进行复位,RX/TX RESETDONE复位完成标识位才会拉高。
PLL Reset:
PLL(PLL0 和 PLL1)必须使用 PLL0PD 和 PLL1PD 端口关断,直到在逻辑中检测到参考时钟边沿。取消 PLL0PD/PLL1PD 后,必须复位PLL0 和 PLL1 才能使用。每个GTPE2_COMMON有六个专用端口用于PLL复位。如图2-12所示,PLL0RESET是复位PLL0的输入,PLL1RESET是复位PLL1的输入。PLL0LOCK 和 PLL1LOCK 是指示重置过程已完成的输出。这种异步PLL0RESET和PLL1RESET脉冲宽度的准则是参考时钟的一个周期。由内部 GTP 生成的实际 PLL0 和 PLL1 复位。
收发器电路比PLL0RESET长得多,PLL1RESET 高脉冲持续时间。PLL锁定所需的时间受几个因素的影响,例如带宽设置和时钟频率。
仿真模拟:
大家可以配置GT核,然后右键Open IP Example Design生成官方demo,通过观察仿真理解GT核自动复位的时序。
- 通过观察可以发现仿真一段时间后,gt0_pll0reset_out拉高,同时可以看到gt0_pll0reflost_in由1变为0(该信号存在问题,大家都知道产生复位后频率丢失reflost应该拉高,等待频率稳定后该信号再拉低,后续通过上板也会纠正该信号的仿真)。
- 等待复位一段时间后,gt0_pll0lock_in拉高,表示锁相环频率信号稳定,此时已经完成锁相环复位工作。
- 等待一段时间后,首先gt0_rx_mmcm_reset_out信号拉低,然后gt0_rx_mmcm_lock_in拉高,从而影响slvsec_gtp_GT_USRCLK_SOURCE模块产生gt_rxusrclk和gt_rxusrclk2时钟信号。
- 由用户控制gt0_data_valid_in数据有效标识信号,最终通过观察gt0_rxdata_out可以发现高速数据流。
源码分析:
大家看完复位相关的手册和仿真模拟可能觉得太难了,毕竟手册上还提到了顺序和单一两种复位方式,好在官方IP核支持通过软复位进行自动复位,实现一条龙服务,快速上手该IP核。
首先我们通过波形图状态机帮助大家理解GT核自动复位的过程,避免来自源码的恐惧。
TIME(ns)是状态机执行的时间点,目前该GT核仅使用RX端,所以RX_PLL0_USED为TRUE,TX_PLL0_USED为FALSE。
- SOFT_RESET拉低后,状态机开始运转,起始为INIT state,然后需要计数600ns后拉高init_wait_done信号。
- 检测到init_wait_done信号拉高后,复位状态机跳转至ASSERT_ALL_RESETS state。
- 在ASSERT state下,初始时refclk_lost为0,标识参考时钟未丢失,于是产生核内部产生PLL0_RESET,并将pll_reset_assert信号拉高。
- PLL0_RESET拉高的同时,关于锁相环复位的pll0_lock_sync拉低,refclk_lost信号拉高。
- 检测到pll0_lock_sync拉低,复位状态机跳转至WAIT_FOR_PLL_LOCK state。
- 从时序图也可以看出,等待了大约10_000ns后,复位状态机跳转至RELEASE_PLL_RESET state。
- 在改状态下,检测到pll0_lock_sync拉高,即锁相环复位完成,频率稳定,复位状态机跳转至VERIFY_RECCLK_STABLE state。
- 该状态下,gtrxreset_i信号由高变低,即复位和初始化的第二步,RX PMA和RX PCS复位将完成。
- 由时序图可知,等待21_000ns后,复位状态机跳转至RELEASE_MMCM_RESET state。
- 在MMCM状态下,当检测到rxpmaresetdone_sync信号拉高后,mmcm_reset_i信号拉低,至此将产生gt_rxusrclk/2时钟信号。
以下便是GT核内部关于复位状态机的源码,我们所绘制的时序图也是通过分析源码帮助大家理解,大家可以通过查看源码逻辑加深印象。
always @(posedge STABLE_CLOCK)
begin
if (SOFT_RESET == 1'b1)
//if (SOFT_RESET == 1'b1 || (rx_state != INIT && rx_state != ASSERT_ALL_RESETS && refclk_lost == 1'b1))
begin
rx_state <= `DLY INIT;
RXUSERRDY <= `DLY 1'b0;
gtrxreset_i <= `DLY 1'b0;
mmcm_reset_i <= `DLY 1'b0;
rx_fsm_reset_done_int <= `DLY 1'b0;
PLL0_RESET <= `DLY 1'b0;
PLL1_RESET <= `DLY 1'b0;
pll_reset_asserted <= `DLY 1'b0;
reset_time_out <= `DLY 1'b1;
retry_counter_int <= `DLY 0;
run_phase_alignment_int <= `DLY 1'b0;
check_tlock_max <= `DLY 1'b0;
RESET_PHALIGNMENT <= `DLY 1'b1;
recclk_mon_count_reset <= `DLY 1'b1;
end
else
begin
case (rx_state)
INIT :
begin
//Initial state after configuration. This state will be left after
//approx. 500 ns and not be re-entered.
if (init_wait_done == 1'b1)
rx_state <= `DLY ASSERT_ALL_RESETS;
end
ASSERT_ALL_RESETS :
begin
//This is the state into which the FSM will always jump back if any
//time-outs will occur.
//The number of retries is reported on the output RETRY_COUNTER. In
//case the transceiver never comes up for some reason, this machine
//will still continue its best and rerun until the FPGA is turned off
//or the transceivers come up correctly.
if (RX_PLL0_USED == "TRUE" )
begin
if ((pll_reset_asserted == 1'b0 && refclk_lost == 1'b0))
begin
PLL0_RESET <= `DLY 1'b1;
pll_reset_asserted <= `DLY 1'b1;
end
else
PLL0_RESET <= `DLY 1'b0;
end
else
begin
if ((pll_reset_asserted == 1'b0 && refclk_lost == 1'b0))
begin
PLL1_RESET <= `DLY 1'b1;
pll_reset_asserted <= `DLY 1'b1;
end
else
PLL1_RESET <= `DLY 1'b0;
end
RXUSERRDY <= `DLY 1'b0;
gtrxreset_i <= `DLY 1'b1;
mmcm_reset_i <= `DLY 1'b1;
run_phase_alignment_int <= `DLY 1'b0;
RESET_PHALIGNMENT <= `DLY 1'b1;
check_tlock_max <= `DLY 1'b0;
recclk_mon_count_reset <= `DLY 1'b1;
if ((RX_PLL0_USED == "TRUE" && pll0lock_sync == 1'b0 && pll_reset_asserted) ||
(RX_PLL0_USED == "FALSE" && pll1lock_sync == 1'b0 && pll_reset_asserted ))
begin
rx_state <= `DLY WAIT_FOR_PLL_LOCK;
reset_time_out <= `DLY 1'b1;
end
end
WAIT_FOR_PLL_LOCK :
begin
if(wait_time_done)
rx_state <= `DLY RELEASE_PLL_RESET;
end
RELEASE_PLL_RESET :
begin
//PLL-Reset of the GTX gets released and the time-out counter
//starts running.
pll_reset_asserted <= `DLY 1'b0;
reset_time_out <= `DLY 1'b0;
if ((RX_PLL0_USED == "TRUE" && TX_PLL0_USED == "FALSE" && pll0lock_sync == 1'b1) ||
(RX_PLL0_USED == "FALSE" && TX_PLL0_USED == "TRUE" && pll1lock_sync == 1'b1))
begin
rx_state <= `DLY VERIFY_RECCLK_STABLE;
reset_time_out <= `DLY 1'b1;
recclk_mon_count_reset <= `DLY 1'b0;
end
else if ((RX_PLL0_USED == "TRUE" && pll0lock_sync == 1'b1) ||
(RX_PLL0_USED == "FALSE" && pll1lock_sync == 1'b1))
begin
rx_state <= `DLY VERIFY_RECCLK_STABLE;
reset_time_out <= `DLY 1'b1;
recclk_mon_count_reset <= `DLY 1'b0;
end
if (time_out_2ms == 1'b1)
begin
if (retry_counter_int == MAX_RETRIES)
// If too many retries are performed compared to what is specified in
// the generic, the counter simply wraps around.
retry_counter_int <= `DLY 0;
else
begin
retry_counter_int <= `DLY retry_counter_int + 1;
end
rx_state <= `DLY ASSERT_ALL_RESETS;
end
end
VERIFY_RECCLK_STABLE :
begin
//reset_time_out <= `DLY '0';
//Time-out counter is not released in this state as here the FSM
//does not wait for a certain period of time but checks on the number
//of retries in the CDR PPM detector.
gtrxreset_i <= `DLY 1'b0;
if (RECCLK_STABLE == 1'b1)
begin
rx_state <= `DLY RELEASE_MMCM_RESET;
reset_time_out <= `DLY 1'b1;
end
if (recclk_mon_restart_count == 2)
begin
//If two retries are performed in the CDR "Lock" (=CDR PPM-detector)
//the whole initialisation-sequence gets restarted.
if (retry_counter_int == MAX_RETRIES)
// If too many retries are performed compared to what is specified in
// the generic, the counter simply wraps around.
retry_counter_int <= `DLY 0;
else
begin
retry_counter_int <= `DLY retry_counter_int + 1;
end
rx_state <= `DLY ASSERT_ALL_RESETS;
end
end
RELEASE_MMCM_RESET :
begin
//Release of the MMCM-reset. Waiting for the MMCM to lock.
check_tlock_max <= `DLY 1'b1;
if (rxpmaresetdone_sync == 1'b1 )
begin
mmcm_reset_i <= `DLY 1'b0;
reset_time_out <= `DLY 1'b0;
end
if (mmcm_lock_reclocked == 1'b1)
begin
rx_state <= `DLY WAIT_FOR_RXUSRCLK;
reset_time_out <= `DLY 1'b1;
end
if (time_tlock_max == 1'b1 && reset_time_out == 1'b0 )
begin
if (retry_counter_int == MAX_RETRIES)
// If too many retries are performed compared to what is specified in
// the generic, the counter simply wraps around.
retry_counter_int <= `DLY 0;
else
begin
retry_counter_int <= `DLY retry_counter_int + 1;
end
rx_state <= `DLY ASSERT_ALL_RESETS;
end
end
WAIT_FOR_RXUSRCLK :
begin
if(wait_time_done)
rx_state <= `DLY WAIT_RESET_DONE;
end
WAIT_RESET_DONE :
......//后续还有几个状态,大家感兴趣可以查看核内部源码slvsec_gtp_TX_STARTUP_FSM
endcase
end
end
结果展示:
通过上板波形图大家可以发现,gt_reset拉低后,等待了大概630ns(ILA频率为100MHz,时钟周期10ns),产生了锁相环复位信号,和我们通过观察源码绘制的时序图一致。
【gt0_pll0reset_out】:
该复位信号拉高的同时,lock拉低,lost拉高,而不是仿真的那种时序。
至此GT核自动复位已经结束,可以通过各个通道的rxdata捕获到数据了。文章来源:https://www.toymoban.com/news/detail-844553.html
文章来源地址https://www.toymoban.com/news/detail-844553.html
到了这里,关于GT核内部自动复位状态机的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!