⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hdsdi_rx_autorate.vhd

📁 SDI接口的源程序,包括扰码编码,并串转换,用VHDL硬件描述语言编写
💻 VHD
字号:
-------------------------------------------------------------------------------- 
-- Copyright (c) 2004 Xilinx, Inc. 
-- All Rights Reserved 
-------------------------------------------------------------------------------- 
--   ____  ____ 
--  /   /\/   / 
-- /___/  \  /   Vendor: Xilinx 
-- \   \   \/    Author: John F. Snow, Advanced Product Division, Xilinx, Inc.
--  \   \        Filename: $RCSfile: hdsdi_rx_autorate.vhd,rcs $
--  /   /        Date Last Modified:  $Date: 2004-12-09 14:52:15-07 $
-- /___/   /\    Date Created: May 28, 2004 
-- \   \  /  \ 
--  \___\/\___\ 
-- 
--
-- Revision History: 
-- $Log: hdsdi_rx_autorate.vhd,rcs $
-- Revision 1.1  2004-12-09 14:52:15-07  jsnow
-- Cosmetic changes only.
--
-------------------------------------------------------------------------------- 
--   
--   XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" 
--   AS A COURTESY TO YOU, 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.
-- 
--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;

use work.hdsdi_pkg.all;

entity hdsdi_rx_autorate is
    port (
        clk:        in  std_logic;      -- rxusrclk input
        rst:        in  std_logic;      -- async reset
        sav:        in  std_logic;      -- must be asserted during XYZ of SAV symbols
        trs_err:    in  std_logic;      -- TRS error bit from framer
        y_crc_err:  in  std_logic;      -- Y channel CRC error
        c_crc_err:  in  std_logic;      -- C channel CRC error
        refclksel:  out std_logic);     -- output: 0 = 74.1758 MHz, 1 = 74.25 MHz
end hdsdi_rx_autorate;

architecture synth of hdsdi_rx_autorate is

--
-- Constant and type declarations
--
-- Changing the ERRCNT_WIDTH constant 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 constant, 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 constant 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.
--
constant ERRCNT_WIDTH :     integer := 2;
constant TRSCNT_WIDTH :     integer := 12;

subtype errcnt_type is std_logic_vector(ERRCNT_WIDTH - 1 downto 0);
subtype trscnt_type is std_logic_vector(TRSCNT_WIDTH - 1 downto 0);

constant MAX_ERRS :         errcnt_type := (others => '1');

--
-- This group of constants defines the states of the FSM.
--             
constant STATE_WIDTH :      integer := 3;

subtype state is std_logic_vector(STATE_WIDTH - 1 downto 0);

constant UNLOCK :           state := "000";
constant TOG :              state := "001";
constant LOCK1 :            state := "010";
constant LOCK2 :            state := "011";
constant ERR1 :             state := "100";
constant ERR2 :             state := "101";
                                  
         
--
-- Signal declarations
--
signal current_state :  state;          -- FSM current state
signal next_state :     state;          -- FSM next state
signal errcnt :         errcnt_type;    -- error counter
signal trscnt :         trscnt_type;    -- TRS timeout counter
signal trscnt_max :     trscnt_type;    -- MAX TRS count value
signal toggle :         std_logic;      -- FSM output that toggles refclksel
signal clr_errcnt :     std_logic;      -- FSM output that clears errcnt
signal inc_errcnt :     std_logic;      -- FSM output that increments errcnt
signal max_errcnt :     std_logic;      -- asserted when errcnt = MAX_ERRS
signal trs_tc :         std_logic;      -- terminal count output from trscnt
signal sel_int :        std_logic;      -- internal refclksel signal
signal sav_ok :         std_logic;      -- sav AND NOT trs_err
signal crc_err :        std_logic;      -- OR of CRC errors from Y and C channels


begin

    sav_ok <= sav and not trs_err;
    crc_err <= y_crc_err or 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.
    --
    process(clk, rst)
    begin
        if rst = '1' then
            trscnt <= (others => '0');
        elsif clk'event and clk = '1' then
            if sav_ok = '1' then
                trscnt <= (others => '0');
            else
                trscnt <= trscnt + 1;
            end if;
        end if;
    end process;

    trscnt_max <= (others => '1');
    trs_tc <= '1' when trscnt = trscnt_max else '0';

    --
    -- 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.
    --
    process(clk, rst)
    begin
        if rst = '1' then
            errcnt <= (others => '0');
        elsif clk'event and clk = '1' then
            if inc_errcnt = '1' then
                errcnt <= errcnt + 1;
            elsif clr_errcnt = '1' then
                errcnt <= (others => '0');
            end if;
        end if;
    end process;

    max_errcnt <= '1' when errcnt = MAX_ERRS else '0';

    --
    -- 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.
    --
    process(clk, rst)
    begin
        if rst = '1' then
            sel_int <= '0';
        elsif clk'event and clk = '1' then
            if toggle = '1' then
                sel_int <= not sel_int;
            end if;
        end if;
    end process;

    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.
    --
    process(clk, rst)
    begin
        if rst = '1' then
            current_state <= UNLOCK;
        elsif clk'event and clk = '1' then
            current_state <= next_state;
        end if;
    end process;

    --
    -- 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.
    --
    process(current_state, sav_ok, crc_err, max_errcnt, trs_tc)
    begin
        case current_state is
            --
            -- 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 TOG state to 
            -- toggle the refclksel signal.
            --
            when UNLOCK => 
                if sav_ok = '1' then
                    next_state <= LOCK1;
                elsif trs_tc = '1' then
                    next_state <= TOG;
                else
                    next_state <= UNLOCK;
                end if;

            --
            -- In the TOG state, the FSM toggles the refclksel signal and 
            -- returns to the UNLOCK state.
            --
            when TOG =>  
                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.
            --
            when LOCK1 => 
                if sav_ok = '1' and crc_err = '0' then
                    next_state <= LOCK2;
                elsif sav_ok = '1' and (crc_err = '1' or trs_tc = '1') then
                    next_state <= ERR1;
                else
                    next_state <= LOCK1;
                end if;

            --
            -- The FSM moves to LOCK2 from LOCK1 if a SAV is found. The error
            -- counter is reset in LOCK2.
            --
            when 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.
            --
            when 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 TOG state, otherwise the FSM
            -- returns to LOCK1.
            --
            when ERR2 => 
                if max_errcnt = '1' then
                    next_state <= TOG;
                else
                    next_state <= LOCK1;
                end if;

            when others => 
                next_state <= LOCK1;
        end case;
    end process;

            
    --
    -- FSM: outputs
    --
    -- This block decodes the current state to generate the various outputs of 
    -- the FSM.
    --
    process(current_state)
    begin
        toggle      <= '0';
        clr_errcnt  <= '0';
        inc_errcnt  <= '0';
        
        case current_state is
            when LOCK2 => 
                clr_errcnt <= '1';

            when TOG => 
                toggle <= '1';
                clr_errcnt <= '1';

            when ERR1 => 
                inc_errcnt <= '1';

            when others => 
                null;
        end case;   
    end process;

end synth;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -