一、Xilinx官方文档 pg046 复位时序

按照官方文件显示,时序顺序:
① RESET和GT_RESET为0;
②拉高RESET;
③最少128use_clk(程序设为1000个clk)后拉高GT_RESET;
④1s(程序设为49999999个clk)后拉低GT_RESET;
⑤最少128use_clk后拉低RESET(程序设为1000个use_clk)。
初始设计代码:设计思路,上电后重复上述复位时序一次,时钟使用的不是use_clk,使用的init_clk,50MHz。
module aurora_rst(
input wire clk ,
input wire rstn ,
output reg reset ,
output reg gtreset
);
localparam IDEL = 0 ,
SYS_RESET = 1 ,
GT_RESET = 2 ,
GT_ASSERT = 3 ,
SYS_ASSERT = 4 ,
OVER = 5 ;
reg [31:0] cnt = 0 ;
reg [4 :0] cur_state ;
always @(posedge clk or negedge rstn) begin
if(!rstn)
begin
cnt <= 32'd0 ;
cur_state <= IDEL ;
reset <= 0 ;
gtreset <= 0 ;
end
else
begin
case (cur_state)
IDEL :
begin
reset <= 1 ;
gtreset <= 0 ;
cur_state <= SYS_RESET ;
end
SYS_RESET :
begin
if(cnt == 1000)
begin
cnt <= 0 ;
cur_state <= GT_RESET ;
end
else
begin
cnt <= cnt + 1 ;
cur_state <= SYS_RESET ;
end
end
GT_RESET :
begin
gtreset <= 1 ;
cur_state <= GT_ASSERT ;
end
GT_ASSERT :
begin
if(cnt == 32'd49999999)
begin
cnt <= 0 ;
cur_state <= SYS_ASSERT ;
gtreset <= 0 ;
end
else
begin
cnt <= cnt + 1 ;
cur_state <= GT_ASSERT ;
gtreset <= 1 ;
end
end
SYS_ASSERT :
begin
if(cnt == 1000)
begin
cnt <= 0 ;
reset <= 0 ;
cur_state <= OVER ;
end
else
begin
cnt <= cnt + 1 ;
reset <= 1 ;
cur_state <= SYS_ASSERT ;
end
end
OVER :
begin
reset <= reset ;
gtreset <= gtreset ;
cur_state <= OVER ;
end
default
begin
reset <= reset ;
gtreset <= gtreset ;
cur_state <= OVER ;
end
endcase
end
end
endmodule
二:上述程序问题:
一对一通信,或者五个模块通信,则没问题,但是因为只复位一次,如果级数过多,上电时间不一致,则会出现CHANNEL_UP,LANE_UP不稳现象。
三:解决问题:
如果LANE_UP上升沿重新启动复位逻辑,能保证再上电稳定后,多个板子的IP同时启动复位时序,同时在GT_RESET拉低后延时3S后再拉低RESET,给系统足够多的恢复时间。
module aurora_reset_with_laneup (
input clk , // 50MHz
input ext_reset_n , // 外部复位(低有效)
input lane_up , // Aurora IP的lane_up信号
output reg reset , // Aurora RESET(高有效)
output reg gt_reset // Aurora GT_RESET(高有效)
);
// 时序参数(50MHz时钟)
localparam RESET_HOLD_1 = 1000 ; // RESET拉高后保持1000个clk
localparam GT_RESET_HOLD = 49_999_999 ; // GT_RESET保持49,999,999个clk(约1秒)
localparam RESET_HOLD_2 = 1000 ; // GT_RESET拉低后RESET再保持1000个clk
localparam LANEUP_WAIT = 1_000_000 ; // lane_up稳定等待20ms
localparam TIMEOUT_MAX = 150_000_000 ; // 3秒超时
// 状态编码
localparam ST_IDLE = 4'd0 ;
localparam ST_RESET_HIGH_1 = 4'd1 ; // RESET拉高阶段1
localparam ST_GT_RESET_HIGH = 4'd2 ; // GT_RESET拉高阶段
localparam ST_GT_RESET_LOW = 4'd3 ; // 等待GT_RESET拉低后的延时
localparam ST_RESET_HIGH_2 = 4'd4 ; // RESET拉高阶段2
localparam ST_WAIT_LANEUP = 4'd5 ; // 等待lane_up稳定
localparam ST_RELEASE_RESET = 4'd6 ; // 释放RESET
localparam ST_RUNNING = 4'd7 ; // 正常运行
reg [3:0] state ;
reg [31:0] timer ; // 足够大的计数器
reg [19:0] laneup_cnt ;
reg [2:0] retry_cnt ;
// 状态机时序逻辑
always @(posedge clk or negedge ext_reset_n) begin
if (!ext_reset_n) begin
// 外部复位有效(低电平),进入复位状态
state <= ST_RESET_HIGH_1 ;
reset <= 1'b1 ; // RESET拉高
gt_reset <= 1'b0 ; // GT_RESET初始为低
timer <= 0 ;
laneup_cnt <= 0 ;
retry_cnt <= 0 ;
end else begin
case (state)
ST_RESET_HIGH_1: begin
// 阶段1:RESET拉高,保持1000个clk
reset <= 1'b1 ;
gt_reset <= 1'b0 ;
if (timer >= RESET_HOLD_1 - 1) begin
timer <= 0 ;
state <= ST_GT_RESET_HIGH ;
end else begin
timer <= timer + 1 ;
end
end
ST_GT_RESET_HIGH: begin
// 阶段2:拉高GT_RESET,保持49,999,999个clk
reset <= 1'b1 ;
gt_reset <= 1'b1 ;
if (timer >= GT_RESET_HOLD) begin
timer <= 0 ;
state <= ST_GT_RESET_LOW ;
end else begin
timer <= timer + 1 ;
end
end
ST_GT_RESET_LOW: begin
// 阶段3:拉低GT_RESET,等待一段时间(可选)
reset <= 1'b1 ;
gt_reset <= 1'b0 ;
if (timer >= 1000) begin // 额外等待1000个clk
timer <= 0 ;
state <= ST_RESET_HIGH_2 ;
end else begin
timer <= timer + 1 ;
end
end
ST_RESET_HIGH_2: begin
// 阶段4:RESET保持高,再等1000个clk
reset <= 1'b1 ;
gt_reset <= 1'b0 ;
if (timer >= RESET_HOLD_2 - 1) begin
timer <= 0 ;
state <= ST_WAIT_LANEUP ;
laneup_cnt <= 0 ;
end else begin
timer <= timer + 1 ;
end
end
ST_WAIT_LANEUP: begin
// 阶段5:等待lane_up稳定(此时RESET仍为高)
reset <= 1'b1;
gt_reset <= 1'b0;
if (lane_up) begin
if (laneup_cnt < LANEUP_WAIT) begin
laneup_cnt <= laneup_cnt + 1;
end else begin
// lane_up稳定,可以释放RESET
state <= ST_RELEASE_RESET;
end
end else begin
laneup_cnt <= 0;
// 超时重试机制
if (timer >= TIMEOUT_MAX) begin
if (retry_cnt < 3) begin
retry_cnt <= retry_cnt + 1;
state <= ST_RESET_HIGH_1; // 重新开始
timer <= 0;
end
// 超过重试次数,保持等待
end else begin
timer <= timer + 1;
end
end
end
ST_RELEASE_RESET: begin
// 阶段6:释放RESET
reset <= 1'b0;
gt_reset <= 1'b0;
state <= ST_RUNNING;
end
ST_RUNNING: begin
// 正常运行,监控链路状态
reset <= 1'b0;
gt_reset <= 1'b0;
if (!lane_up) begin
// 链路意外断开,重新进入复位流程
state <= ST_RESET_HIGH_1;
timer <= 0;
retry_cnt <= 0;
end
end
default: begin
state <= ST_RESET_HIGH_1;
reset <= 1'b1;
gt_reset <= 1'b0;
timer <= 0;
end
endcase
end
end
endmodule
四:结语:
此操作可以使多板子串行通信,在上电时间不一致,以及中途断电再上电后,可以比上电只复位一次程序,恢复更快。但是时间也不确定,有时候十几秒,有时候一分多钟有时候两分多钟,似乎问题还没解决,但是比只复位一次好一些。