📄 anc_insert.vhd
字号:
--------------------------------------------------------------------------------
-- anc_insert.vhd
--
-- SDI ANC packet insertion module
--
--
--
-- Author: John F. Snow
-- Staff Applications Engineer
--
-- Video Applications
-- Advanced Products Group
-- Xilinx, Inc.
--
-- Copyright (c) 2002 Xilinx, Inc.
-- All rights reserved
--
-- Date: May 8, 2002
--
-- RESTRICTED RIGHTS LEGEND
--
-- This software has not been published by the author, and
-- has been disclosed to others for the purpose of enhancing
-- and promoting design productivity in Xilinx products.
--
-- Therefore use, duplication or disclosure, now and in the
-- future should give consideration to the productivity
-- enhancements afforded the user of this code by the author's
-- efforts. Thank you for using our products !
--
-- Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY
-- WHATSOEVER AND XILINX SPECIFICALLY DISCLAIMS ANY
-- IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
-- A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.
--
-- Revision:
-- May 8, 2002 Release
--
-- Other modules instanced in this design:
--
--------------------------------------------------------------------------------
--
-- This module is instanced by the anc_mux module. The anc_insert module
-- searches the video stream for an appropriate place to insert a new ANC
-- packet. The ANC space must be of the appropriate type (HANC or VANC) as
-- requested by the hanc_pkt and vanc_pkt inputs. The space must also be large
-- enough to accomodate a packet of the size indicated by the pkt_size value.
-- This module will overwrite end_marker packets but does not overwrite packets
-- that have been marked for deletion.
--
-- The new ANC packet data comes in on the anc_in port. When the pkt_rdy
-- input is asserted, the module begins looking for a free ANC space for the
-- packet. Note that when pkt_rdy is asserted, the module assumes that the first
-- word of the ADF is present on the anc_in port. The total number of words in
-- the new packet must also be present on the pkt_size port when pkt_rdy is
-- asserted.
--
-- The module will always assure that ANC packets are contiguous in the ANC
-- space. New packets will only be inserted immediately after the TRS symbols
-- at the beginning of the ANC space, after an existing EDH packet, or in place
-- of an end-marker ANC packet. The module respects the "keep-out" area around
-- the synchronous switching interval and also the spaces reserved for EDH
-- packets.
--
-- When the modules finds a candidate ANC space for the new packet, it asserts
-- the send_pkt output. At the next rising clock edge, the anc_in port must
-- change to the second word of the ADF. Each word of the new packet must be
-- placed on anc_in during each successive clock cycle. When the last word (CS)
-- of the ANC packet is on the anc_in port, the pkt_end signal must also be
-- asserted to let the module know that the end of the packet has been reached.
-- Note that send_pkt is asserted by the module for only a single clock cycle to
-- begin the process of sending the ANC packet.
--
-- In some cases, the module will attempt to insert the packet, only to find out
-- that the packet couldn't really be inserted. This is because either the ANC
-- space was part of the prohibited synchronous switching interval or because
-- another ANC packet already exists in the video stream and cannot be
-- overwritten. In this case, the module will assert the abort_pkt signal. The
-- module sending the packet to anc_insert must stop sending the packet and
-- resend the same packet when anc_insert next asserts the send_pkt signal. The
-- anc_insert module is designed in such a way that when a packet insertion is
-- aborted, the data in the video stream is not corrupted in any way.
--
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.anc_edh_pkg.all;
entity anc_insert is
port (
-- inputs
clk: in std_ulogic; -- clock input
ce: in std_ulogic; -- clock enable
rst: in std_ulogic; -- async reset input
pkt_rdy : in std_ulogic; -- indicates packet is ready to be sent
anc_in : in video_type; -- ANC packet data input
vid_in : in video_type; -- video data input
pkt_size : in pktsize_type;-- size of packet to be sent
pkt_end : in std_ulogic; -- indicates last word of packet being sent
anc_next : in std_ulogic; -- vid_in contains ANC packet starting at next word
eav_next : in std_ulogic; -- vid_in contains EAV starting at next word
sav_next : in std_ulogic; -- vid_in contains SAV starting at next word
hanc_pkt : in std_ulogic; -- ANC packet to be sent can be inserted into HANC space
vanc_pkt : in std_ulogic; -- ANC packet to be sent can be inserted into VANC space
std : in vidstd_type; -- current video standard
v_blank : in std_ulogic; -- vertical blanking indicator
field : in std_ulogic; -- field indicator
horz_count : in hpos_type; -- current horizontal position
vert_count : in vpos_type; -- current vertical position
switch_line : in std_ulogic; -- current line is a sync switching line
-- outputs
vid_out : out video_type; -- output video data
send_pkt : out std_ulogic; -- tells anc_pkt_gen to send packet
abort_pkt : out std_ulogic); -- tells anc_pkt_gen to abort packet
end;
architecture synth of anc_insert is
-- The padding subtype is used to pad the packet size vector to the lenth of
-- the horizontal position vector.
subtype padding is std_logic_vector(HCNT_WIDTH - 9 downto 0);
-------------------------------------------------------------------------------
-- Constant definitions
--
--
-- This group of constants defines the states of the EDH processor state
-- machine.
--
constant STATE_WIDTH : integer := 5;
subtype state_type is std_ulogic_vector(STATE_WIDTH - 1 downto 0);
constant S_WAIT : state_type := "00000";
constant S_EAV1 : state_type := "00001";
constant S_EAV2 : state_type := "00010";
constant S_EAV3 : state_type := "00011";
constant S_WHAT : state_type := "00100";
constant S_SAV1 : state_type := "00101";
constant S_SAV2 : state_type := "00110";
constant S_SAV3 : state_type := "00111";
constant S_SND1 : state_type := "01000";
constant S_SND2 : state_type := "01001";
constant S_ABRT : state_type := "01010";
constant S_ADF1 : state_type := "01011";
constant S_ADF2 : state_type := "01100";
constant S_ADF3 : state_type := "01101";
constant S_DID : state_type := "01110";
constant S_DBN : state_type := "01111";
constant S_DC : state_type := "10000";
constant S_UDW : state_type := "10001";
constant S_NC : state_type := "10010";
-------------------------------------------------------------------------------
-- Signal definitions
--
signal current_state: state_type; -- FSM current state
signal next_state: state_type; -- FSM next state
signal switching: std_ulogic; -- asserted if in switching keep-out area
signal done_switching: std_ulogic; -- used to generate the switching signal
signal space_avail: std_ulogic; -- asserted if space is available for packet
signal set_hanc: std_ulogic; -- sets the hanc signal
signal set_vanc: std_ulogic; -- clears the hanc signal (vanc = ~hanc)
signal hanc: std_ulogic; -- asserted during HANC space
signal ld_udw_cntr: std_ulogic; -- loads the UDW counter
signal udw_cntr_mux: ubyte_type; -- input MUX for the UDW counter
signal udw_cntr_eq_0: std_ulogic; -- asserted when udw_cntr_mux == 0
signal udw_cntr: ubyte_type; -- this is the UDW counter register
signal hanc_end: hpos_type; -- ending position of HANC space for current video std
signal vanc_end: hpos_type; -- ending position of VANC space for current video std
signal f1_edh_line: vpos_type; -- line in field 1 where EDH packet occurs
signal f2_edh_line: vpos_type; -- line in field 2 where EDH packet occurs
signal fx_edh_line: vpos_type; -- line in current field where EDH packet occurs
signal edh_line: std_ulogic; -- asserted when current line contains EDH packet
signal free_space: hpos_type; -- amount of free space remaining in ANC space
signal space_end: hpos_type; -- indicates the ending location of current ANC space
signal pkt_out: std_ulogic; -- asserted when ANC packet is being output
signal start_marker: std_ulogic; -- asserted when DID == 0x88
signal end_marker: std_ulogic; -- asserted when DID == 0x84
signal mod_pkt_size: pktsize_type; -- modified packet size value
signal pad_pkt_size: hpos_type; -- mod_pkt_size padded to HCNT width
signal mod_space_avail: std_ulogic; -- when asserted, reduces the pkt_size by 3 for overwrites
signal overwrite: std_ulogic; -- asserted when an end marker packet is overwritten
signal abort_pkt_int : std_ulogic; -- internal version of abort_pkt
signal send_pkt_int : std_ulogic; -- internal version of send_pkt
begin
--
-- FSM: current_state register
--
-- This code implements the current state register.
--
process(clk, rst)
begin
if (rst = '1') then
current_state <= S_WAIT;
elsif (clk'event and clk = '1') then
if (ce = '1') then
current_state <= next_state;
end if;
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, eav_next, sav_next, v_blank, switching, anc_next,
pkt_rdy, vanc_pkt, hanc_pkt, space_avail, pkt_end,
udw_cntr_eq_0, start_marker, overwrite)
begin
case current_state is
when S_WAIT =>
if (eav_next = '1') then
next_state <= S_EAV1;
elsif (sav_next = '1') then
next_state <= S_SAV1;
else
next_state <= S_WAIT;
end if;
when S_EAV1 =>
next_state <= S_EAV2;
when S_EAV2 =>
next_state <= S_EAV3;
when S_EAV3 =>
if (hanc_pkt = '0' or switching = '1') then
next_state <= S_WAIT;
elsif (pkt_rdy = '1') then
next_state <= S_WHAT;
else
next_state <= S_WAIT;
end if;
when S_WHAT =>
if (anc_next = '1') then
next_state <= S_ADF1;
elsif (space_avail = '1') then
next_state <= S_SND1;
else
next_state <= S_WAIT;
end if;
when S_SAV1 =>
next_state <= S_SAV2;
when S_SAV2 =>
next_state <= S_SAV3;
when S_SAV3 =>
if (v_blank = '0' or vanc_pkt = '0') then
next_state <= S_WAIT;
elsif (pkt_rdy = '1') then
next_state <= S_WHAT;
else
next_state <= S_WAIT;
end if;
when S_ADF1 =>
next_state <= S_ADF2;
when S_ADF2 =>
next_state <= S_ADF3;
when S_ADF3 =>
next_state <= S_DID;
when S_DID =>
if (start_marker = '1') then
next_state <= S_NC;
elsif (overwrite = '1') then
next_state <= S_SND2;
else
next_state <= S_DBN;
end if;
when S_DBN =>
next_state <= S_DC;
when S_DC =>
if (udw_cntr_eq_0 = '1' and pkt_rdy = '1') then
next_state <= S_WHAT;
elsif (udw_cntr_eq_0 = '1' and pkt_rdy = '0') then
next_state <= S_WAIT;
else
next_state <= S_UDW;
end if;
when S_UDW =>
if (udw_cntr_eq_0 = '1' and pkt_rdy = '1') then
next_state <= S_WHAT;
elsif (udw_cntr_eq_0 = '1' and pkt_rdy = '0') then
next_state <= S_WAIT;
else
next_state <= S_UDW;
end if;
when S_SND1 =>
if (switching = '1') then
next_state <= S_ABRT;
else
next_state <= S_SND2;
end if;
when S_SND2 =>
if (pkt_end = '1') then
next_state <= S_WAIT;
else
next_state <= S_SND2;
end if;
when S_ABRT =>
next_state <= S_WAIT;
when S_NC =>
if (anc_next = '1') then
next_state <= S_ADF1;
elsif (eav_next = '1') then
next_state <= S_EAV1;
elsif (sav_next = '1') then
next_state <= S_SAV1;
else
next_state <= S_NC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -