📄 hdsdi_rx_autorate.v
字号:
//------------------------------------------------------------------------------
// Copyright (c) 2005 Xilinx, Inc.
// All Rights Reserved
//------------------------------------------------------------------------------
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Author: John F. Snow, Advanced Product Division, Xilinx, Inc.
// \ \ Filename: $RCSfile: hdsdi_rx_autorate.v,rcs $
// / / Date Last Modified: $Date: 2005-01-14 10:50:49-07 $
// /___/ /\ Date Created: Jan 5, 2005
// \ \ / \
// \___\/\___\
//
//
// Revision History:
// $Log: hdsdi_rx_autorate.v,rcs $
// Revision 1.1 2005-01-14 10:50:49-07 jsnow
// Header update.
//
//------------------------------------------------------------------------------
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
// SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
// XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION
// AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION
// OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS
// IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
// AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
// FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
// WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
// IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
// REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
// INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE.
//
//------------------------------------------------------------------------------
/*
This module will automatically toggle the reference clock to the RocketIO
transceiver until the data being received is error free. The reference clock
will then stay at this clock frequency too many errors are detected.
The user needs to balance error tolerance against reaction speed in this design.
Occasional errors, or even a burst of errors, should not cause the circuit to
toggle reference clock frequencies prematurely. On the other hand, in some
cases it is necessary to reacquire lock with the bitstream as quickly as
possible after the incoming bitstream changes frequencies.
When running with the wrong reference clock, the RocketIO receiver actually will
receive much of the data correctly. Most of the TRS symbols will be correctly
received. So, simply looking for missing or bad TRS symbols usually isn't
sufficient. A better indication is CRC errors. A CRC error will be detected on
virtually every video line when the wrong reference clock is selected. However,
simply looking for CRC errors may be insufficient, too, since CRC errors
aren't found when there are no TRS symbols being received.
This module uses both missing TRS symbols and CRC errors as the detection
mechanism for determining when to toggle the reference clock frequency. A
missing SAV, an SAV with protection bit errors, or a CRC error will cause
the finite state machine to flag the error as containing an error. Each line
that contains an error causes the error counter to increment. If a line is
found that is error free, the error counter is cleared back to zero. When
MAX_ERRS consecutive lines occur with errors, the state machine will toggle the
refclksel signal.
The width of the error counter and the MAX_ERRS value are both specified as
parameters and can modified by changing the parameter value. Also, the width of
the counter that determines if a SAV is missing is also programmable. This
counter times out when it reaches a count of all ones, signalling that an SAV
missing error has occurred.
--------------------------------------------------------------------------------
*/
module hdsdi_rx_autorate (
clk, // rxusrclk input
rst, // async reset input
sav, // asserted during SAV symbols
trs_err, // TRS error bit from framer
y_crc_err, // Y channel CRC error
c_crc_err, // C channel CRC error
refclksel // output: 0 = 74.1758 MHz, 1 = 74.25 MHz
);
//-----------------------------------------------------------------------------
// Parameter definitions
//
// Changing the ERRCNT_WIDTH parameter changes the width of the counter that is
// used to keep track of the number of consecutive lines that contained errors.
// By changing the counter width and changing the MAX_ERRS parameter, the
// latency for refclksel switching can be changed. Making the MAX_ERRS value
// smaller will reduce the switching latency, but will also reduce the tolerance
// to errors and cause unintentional refclksel switching.
//
// The TRSCNT_WIDTH parameter determines the width of the missing SAV timeout
// counter. Increasing this counter's width causes the state machine to wait
// longer before determining that a SAV was missing.
//
parameter ERRCNT_WIDTH = 2;
parameter TRSCNT_WIDTH = 12;
parameter ERRCNT_MSB = ERRCNT_WIDTH - 1;
parameter TRSCNT_MSB = TRSCNT_WIDTH - 1;
parameter MAX_ERRS = 3; // Max number of consecutive errored lines before switching
//
// This group of parameters defines the states of the FSM.
//
parameter STATE_WIDTH = 3;
parameter STATE_MSB = STATE_WIDTH - 1;
parameter [STATE_WIDTH-1:0]
UNLOCK = 0,
TOGGLE = 1,
LOCK1 = 2,
LOCK2 = 3,
ERR1 = 4,
ERR2 = 5;
//-----------------------------------------------------------------------------
// Signal definitions
//
// IO definitions
input clk;
input rst;
input sav;
input trs_err;
input y_crc_err;
input c_crc_err;
output refclksel;
// internal signals
reg [STATE_MSB:0] current_state; // FSM current state
reg [STATE_MSB:0] next_state; // FSM next state
reg [ERRCNT_MSB:0] errcnt; // error counter
reg [TRSCNT_MSB:0] trscnt; // TRS timeout counter
reg toggle; // FSM output that toggles the refclksel
reg clr_errcnt; // FSM output that clears errcnt
reg inc_errcnt; // FSM output that increments errcnt
wire max_errcnt; // asserted when errcnt = MAX_ERRS
wire trs_tc; // terminal count output from trscnt
reg sel_int; // internal refclksel signal
wire sav_ok; // sav AND ~trs_err
wire crc_err; // OR of two crc_err inputs
assign sav_ok = sav & ~trs_err;
assign crc_err = y_crc_err | c_crc_err;
//
// TRS timeout counter
//
// This counter is reset whenever a SAV signal is received, otherwise it
// increments. When it reaches its terminal count, the trs_tc signal is
// asserted and the the counter will roll over to zero on the next clock cycle.
//
always @ (posedge clk or posedge rst)
if (rst)
trscnt <= 0;
else if (sav_ok)
trscnt <= 0;
else
trscnt <= trscnt + 1;
assign trs_tc = trscnt == {TRSCNT_WIDTH{1'b1}};
//
// Error counter
//
// The error counter increments each time the inc_errcnt output from the FSM
// is asserted. It clears to zero when clr_errcnt is asserted. The max_errcnt
// output is asserted if the error counter equals MAX_ERRS.
//
always @ (posedge clk or posedge rst)
if (rst)
errcnt <= 0;
else if (inc_errcnt)
errcnt <= errcnt + 1;
else if (clr_errcnt)
errcnt <= 0;
assign max_errcnt = errcnt == MAX_ERRS;
//
// refclksel control signal
//
// This is the hd_sd mode control output signal. hd_sd_int is the actual
// flip-flop for internal use in this module and hd_sd is the output from the
// module.
//
always @ (posedge clk or posedge rst)
if (rst)
sel_int <= 1'b0;
else if (toggle)
sel_int <= ~sel_int;
assign refclksel = sel_int;
// FSM
//
// The finite state machine is implemented in three processes, one for the
// current_state register, one to generate the next_state value, and the
// third to decode the current_state to generate the outputs.
//
// FSM: current_state register
//
// This code implements the current state register. It loads with the HSYNC1
// state on reset and the next_state value with each rising clock edge.
//
always @ (posedge clk or posedge rst)
if (rst)
current_state <= UNLOCK;
else
current_state <= next_state;
//
// FSM: next_state logic
//
// This case statement generates the next_state value for the FSM based on
// the current_state and the various FSM inputs.
//
always @ (current_state or sav_ok or crc_err or max_errcnt or trs_tc)
case(current_state)
//
// The FSM begins in the UNLOCK state and stays there until a SAV
// symbol is found. In this state, if the TRS timeout counter reaches
// its terminal count, the FSM moves to the TOGGLE state to toggle the
// refclksel signal.
//
UNLOCK: if (sav_ok)
next_state = LOCK1;
else if (trs_tc)
next_state = TOGGLE;
else
next_state = UNLOCK;
//
// In the TOGGLE state, the FSM toggles the refclksel signal and returns
// to the UNLOCK state.
//
TOGGLE: next_state = UNLOCK;
//
// This is the main locked state LOCK1. Once a SAV has been found, the
// FSM stays here until either another SAV is found or the TRS counter
// times out.
//
LOCK1: if (sav_ok & ~crc_err)
next_state = LOCK2;
else if (sav_ok & crc_err | trs_tc)
next_state = ERR1;
else
next_state = LOCK1;
//
// The FSM moves to LOCK2 from LOCK1 if a SAV is found. The error
// counter is reset in LOCK2.
//
LOCK2: next_state = LOCK1;
//
// The FSM moves to ERR1 from LOCK 1 if the TRS timeout counter reaches
// its terminal count before a SAV is found. In this state, the error
// counter is incremented and the FSM moves to ERR2.
//
ERR1: next_state = ERR2;
//
// The FSM enters ERR2 from ERR1 where the error counter was
// incremented. In this state the max_errcnt signal is tested. If it
// is asserted, the FSM moves to the TOGGLE state, otherwise the FSM
// returns to LOCK1.
//
ERR2: if (max_errcnt)
next_state = TOGGLE;
else
next_state = LOCK1;
default: next_state = LOCK1;
endcase
//
// FSM: outputs
//
// This block decodes the current state to generate the various outputs of the
// FSM.
//
always @ (current_state)
begin
// Unless specifically assigned in the case statement, all FSM outputs
// are low.
toggle = 1'b0;
clr_errcnt = 1'b0;
inc_errcnt = 1'b0;
case(current_state)
LOCK2: clr_errcnt = 1'b1;
TOGGLE: begin
toggle = 1'b1;
clr_errcnt = 1'b1;
end
ERR1: inc_errcnt = 1'b1;
endcase
end
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -