jesd204_rx/jesd204_rx_ctrl: Fix de-glitch mechanism

The previous implementation of the de-glitch only delayed the assertion
of the SYNC phase by 64 clock cycles with the DEGLITCH state but if meanwhile
one of the lanes got into a bad state cgs_ready de-asserted the state machine
continued to go SYNCHRONIZED (DATA) state.
This change extends the required number of consecutive cycles while all lanes
must stay in data phase before moving the link to SYNCHRONIZED state from 8 to 256;
This increases the reliability of link bring-up without needing extra
link restarts from software side.
main
Laszlo Nagy 2020-09-03 15:21:47 +01:00 committed by Laszlo Nagy
parent 5edc798b6b
commit ee143d80d6
1 changed files with 20 additions and 39 deletions

View File

@ -68,19 +68,13 @@ module jesd204_rx_ctrl #(
output [NUM_LINKS-1:0] sync, output [NUM_LINKS-1:0] sync,
output reg latency_monitor_reset, output reg latency_monitor_reset,
output reg [1:0] status_state output [1:0] status_state
); );
localparam STATUS_STATE_RESET = 2'h1;
localparam STATUS_STATE_WAIT_FOR_PHY = 2'h1;
localparam STATUS_STATE_CGS = 2'h2;
localparam STATUS_STATE_SYNCHRONIZED = 2'h3;
localparam STATE_RESET = 0; localparam STATE_RESET = 0;
localparam STATE_WAIT_FOR_PHY = 1; localparam STATE_WAIT_FOR_PHY = 1;
localparam STATE_CGS = 2; localparam STATE_CGS = 2;
localparam STATE_DEGLITCH = 3; localparam STATE_SYNCHRONIZED = 3;
localparam STATE_SYNCHRONIZED = 4;
reg [2:0] state = STATE_RESET; reg [2:0] state = STATE_RESET;
reg [2:0] next_state = STATE_RESET; reg [2:0] next_state = STATE_RESET;
@ -91,24 +85,17 @@ reg [NUM_LINKS-1:0] sync_n = {NUM_LINKS{1'b1}};
reg en_align = 1'b0; reg en_align = 1'b0;
reg state_good = 1'b0; reg state_good = 1'b0;
reg [2:0] good_counter = 'h00; reg [7:0] good_counter = 'h00;
reg [9:0] deglitch_counter = 'h3ff;
wire [7:0] good_cnt_limit_s;
wire good_cnt_limit_reached_s;
assign cgs_reset = cgs_rst; assign cgs_reset = cgs_rst;
assign ifs_reset = ifs_rst; assign ifs_reset = ifs_rst;
assign sync = sync_n; assign sync = sync_n;
assign phy_en_char_align = en_align; assign phy_en_char_align = en_align;
always @(posedge clk) begin assign status_state = state;
case (state)
STATE_RESET: status_state <= STATUS_STATE_RESET;
STATE_WAIT_FOR_PHY: status_state <= STATUS_STATE_WAIT_FOR_PHY;
STATE_CGS: status_state <= STATUS_STATE_CGS;
STATE_DEGLITCH: status_state <= STATUS_STATE_CGS;
STATE_SYNCHRONIZED: status_state <= STATUS_STATE_SYNCHRONIZED;
default: status_state <= STATUS_STATE_RESET;
endcase
end
always @(posedge clk) begin always @(posedge clk) begin
case (state) case (state)
@ -132,33 +119,28 @@ always @(posedge clk) begin
endcase endcase
end end
always @(posedge clk) begin
case (state)
STATE_DEGLITCH: begin
if (deglitch_counter != 'h00) begin
deglitch_counter <= deglitch_counter - 1'b1;
end
end
default: begin
deglitch_counter <= 'h3f;
end
endcase
end
always @(*) begin always @(*) begin
case (state) case (state)
STATE_RESET: state_good <= 1'b1; STATE_RESET: state_good <= 1'b1;
STATE_WAIT_FOR_PHY: state_good <= phy_ready; STATE_WAIT_FOR_PHY: state_good <= phy_ready;
STATE_CGS: state_good <= &(cgs_ready | cfg_lanes_disable); STATE_CGS: state_good <= &(cgs_ready | cfg_lanes_disable);
STATE_DEGLITCH: state_good <= deglitch_counter == 'h00;
STATE_SYNCHRONIZED: state_good <= 1'b1; STATE_SYNCHRONIZED: state_good <= 1'b1;
default: state_good <= 1'b0; default: state_good <= 1'b0;
endcase endcase
end end
assign good_cnt_limit_s = (state == STATE_CGS) ? 'hff : 'h7;
assign good_cnt_limit_reached_s = good_counter == good_cnt_limit_s;
always @(posedge clk) begin always @(posedge clk) begin
if (state_good == 1'b1) begin if (reset) begin
good_counter <= 'h00;
end else if (state_good == 1'b1) begin
if (good_cnt_limit_reached_s) begin
good_counter <= 'h00;
end else begin
good_counter <= good_counter + 1'b1; good_counter <= good_counter + 1'b1;
end
end else begin end else begin
good_counter <= 'h00; good_counter <= 'h00;
end end
@ -175,8 +157,7 @@ always @(*) begin
case (state) case (state)
STATE_RESET: next_state <= STATE_WAIT_FOR_PHY; STATE_RESET: next_state <= STATE_WAIT_FOR_PHY;
STATE_WAIT_FOR_PHY: next_state <= STATE_CGS; STATE_WAIT_FOR_PHY: next_state <= STATE_CGS;
STATE_CGS: next_state <= STATE_DEGLITCH; STATE_CGS: next_state <= STATE_SYNCHRONIZED;
STATE_DEGLITCH: next_state <= STATE_SYNCHRONIZED;
default: next_state <= state_good ? state : STATE_RESET; default: next_state <= state_good ? state : STATE_RESET;
endcase endcase
end end
@ -185,7 +166,7 @@ always @(posedge clk) begin
if (reset == 1'b1) begin if (reset == 1'b1) begin
state <= STATE_RESET; state <= STATE_RESET;
end else begin end else begin
if (good_counter == 'h7) begin if (good_cnt_limit_reached_s) begin
state <= next_state; state <= next_state;
end end
end end