📄 anc_pkt_gen.vhd
字号:
--------------------------------------------------------------------------------
-- anc_pkt_gen.vhd
--
-- SDI ANC packet generator
--
--
--
-- 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
--
-- Other modules instanced in this design:
-- none
--
--------------------------------------------------------------------------------
--
-- This module formats an ANC packet from raw data written into the module. Once
-- all the raw data has been written, as indicated by the pkt_rdy_in input being
-- asserted, the module will assert the pkt_rdy_out signal to the anc_insert
-- module and place the first word of the ADF on the anc_out port.
--
-- When the anc_insert module is ready to insert the packet, it will assert the
-- send_pkt signal. The anc_pkt_gen module responds by sequentially placing each
-- word of the ANC packet on the anc_out port for one clock cycle. It also
-- asserts the pkt_end signal when the last word of the packet (CS) is on the
-- anc_out port.
--
-- The anc_insert module sometimes needs to abort the insertion of a packet
-- after it has asserted the send_pkt signal. This is indicated by the abort_pkt
-- input. This signal may be asserted up through the DBN/SDID word of the
-- packet, but not later.
--
-- The following signals are used to write the ANC data to the module. The CS
-- and ADF words are generated automatically and do not need to be written to
-- the module.
--
-- pkt_in_empty: This output must be asserted high before any ANC data may be
-- written to the module. It remains high until pkt_rdy_in is asserted, at which
-- point it goes low and remains low until the ANC packet has been inserted into
-- the video stream.
--
-- data_in: This 10-bit port is the input data port for the raw ANC data. When
-- 8-bit values (DID, SDID, DBN, and DC) are written, they must be placed on the
-- least significant 8-bits of the data_in port.
--
-- ld_did: When this signal is asserted, the module accepts the 8-bit DID value
-- from the data_in port.
--
-- ld_dbn: When this signal is asserted, the module accepts the 8-bit DBN or
-- SDID value from the data_in port.
--
-- ld_dc: When this signal is asserted, the module accepts the 8-bit DC value
-- from the data_in port.
--
-- ld_udw: When this signal is asserted, a 10-bit user data word value is
-- accepted from the data_in port. The udw_wr_adr value must indicate which word
-- of the UDW payload is currently being written whenever ld_udw is asserted.
--
-- udw_wr_adr: This 8-bit input port must be set to indicate which word of the
-- UDW words is currently being written whenever ld_udw is asserted. When the
-- first word of the payload is written, udw_wr_adr must be 0. It must be 1 for
-- the second word, and so on.
--
-- calc_udw_parity: If the UDW words are formatted such that they have data in
-- the LS eight bits, and even parity bit in bit 8, and the complement of bit 8
-- in bit 9, then the module can automatically calculate the parity bits (8 and
-- 9). When the calc_udw_parity signal is asserted at the same time as ld_udw,
-- the two MS bits of data_in are ignored and the module calculates bits 8 and 9
-- of the UDW word as parity bits.
--
-- pkt_rdy_in: Once all the words of the ANC packet have been written to the
-- module, the pkt_rdy_in signal must be asserted. This signal only needs to be
-- asserted for one clock cycle. The pkt_rdy_in signal must be negated before
-- the pkt_empty_in signal will be reasserted by the module.
--
-- It should be noted that it is not possible to simply insert another copy of a
-- packet by reasserting pkt_rdy_in. This is because the DC word of the packet
-- is destroyed in the process of transmitting the packet to the anc_insert
-- module. At the very least, the DC word must be re-written to the anc_pkt_gen
-- module before pkt_rdy_in is reasserted.
--
-- This module calculates the size of the current packet by adding the number of
-- overhead words to the size of the payload. The total size of the packet is
-- sent out through the pkt_size port. This information is used by the
-- anc_insert module.
--
-- The UDW words of the new packet are written into a 2560-bit (256 words x
-- 10-bits) RAM and stored until they are sent to the anc_insert module. This
-- RAM may be implemented in the FPGA as either distributed RAM or as block RAM.
-- The module contains code that will allows XST to infer either a single-port
-- distributed RAM or a dual-port block RAM. A `define statement defines a
-- variable called UDW_BLOCK_RAM. If this variable is defined, then block RAM
-- will be inferred (if the FPGA has block RAM). If this variable is not
-- defined, distributed RAM is inferred. If the variable is defined, but the
-- FPGA does not have block RAM, a dual-port distributed RAM will be inferred.
-- This dual-port RAM will consume twice as many LUTs as the single-port RAM and
-- is therefore rather wasteful.
--
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_pkt_gen 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: in std_ulogic; -- indicates packet has been loaded into registers
calc_udw_parity:in std_ulogic; -- indicates that module should calculate parity on UDW
send_pkt: in std_ulogic; -- causes module to send packet
abort_pkt: in std_ulogic; -- will abort the sending of a packet
-- input packet RAM/register write controls and data
data_in: in video_type; -- input data bus
ld_did: in std_ulogic; -- loads DID register
ld_dbn: in std_ulogic; -- loads SDID/DBN register
ld_dc: in std_ulogic; -- loads DC register
ld_udw: in std_ulogic; -- loads the UDW RAM
udw_wr_adr: in udwadr_type; -- UDW RAM write address
-- outputs
anc_out: out video_type; -- ANC packet data output
pkt_size: out pktsize_type;-- total number of words in packet
pkt_in_empty: out std_ulogic; -- module is ready for input packet to be loaded
pkt_end: out std_ulogic; -- output indicating last word of packet is being sent
pkt_rdy_out: out std_ulogic); -- output indicating module is ready to send packet
end;
architecture synth of anc_pkt_gen is
--
-- Define a datatype for the UDW memory array
--
type udw_ram_type is array (UDW_MEM_SIZE - 1 downto 0) of video_type;
--
-- This group of constants defines the states of the EDH processor state
-- machine.
--
constant STATE_WIDTH : integer := 4;
subtype state_type is std_ulogic_vector(STATE_WIDTH - 1 downto 0);
constant S_WAIT : state_type := "0000";
constant S_ADF1 : state_type := "0001";
constant S_ADF2 : state_type := "0010";
constant S_DID : state_type := "0011";
constant S_DBN : state_type := "0100";
constant S_DC : state_type := "0101";
constant S_UDW : state_type := "0110";
constant S_CHK : state_type := "0111";
constant S_END : state_type := "1000";
constant S_DONE : state_type := "1001";
constant S_ABRT : state_type := "1010";
--
-- This group of constants specifies the select values for the various MUXes
-- in the module.
--
constant PMUXSEL_WIDTH : integer := 2;
subtype pmuxsel_type is std_ulogic_vector(PMUXSEL_WIDTH - 1 downto 0);
constant PMUXSEL_DID : pmuxsel_type := "00";
constant PMUXSEL_DBN : pmuxsel_type := "01";
constant PMUXSEL_DC : pmuxsel_type := "10";
constant PMUXSEL_UDW : pmuxsel_type := "11";
constant OMUXSEL_WIDTH : integer := 2;
subtype omuxsel_type is std_ulogic_vector(OMUXSEL_WIDTH - 1 downto 0);
constant OMUXSEL_ADF0 : omuxsel_type := "00";
constant OMUXSEL_ADF1 : omuxsel_type := "01";
constant OMUXSEL_DATA : omuxsel_type := "10";
constant OMUXSEL_CHK : omuxsel_type := "11";
constant DMUXSEL_PGEN : std_ulogic := '0';
constant DMUXSEL_UDW : std_ulogic := '1';
--
-- These constants define the Ancillary Data Flag word values
--
constant ANC_ADF0 : video_type := (others => '0');
constant ANC_ADF1 : video_type := (others => '1');
-------------------------------------------------------------------------------
-- Signal definitions
--
signal current_state : state_type; -- FSM current state
signal next_state : state_type; -- FSM next state
signal parity : std_ulogic; -- used to generate parity_err signal
signal pword : video_type; -- data word with parity calculated
signal checksum : cksum_type; -- checksum generator for ANC packet
signal clr_checksum : std_ulogic; -- asserted to clear the checksum
signal udw_rd_cntr : udwadr_type; -- UDW read counter
signal clr_udw_rd_cntr: std_ulogic; -- clears the UDW read address
signal inc_udw_rd_cntr: std_ulogic; -- increments the UDW read address
signal dc_eq_0 : std_ulogic; -- asserted when DC register equals 0
signal dec_dc : std_ulogic; -- causes DC register to decrement
signal pmux : ubyte_type; -- output of the parity gen input MUX
signal dmux : video_type; -- selects between parity gen out or UDW RAM out
signal omux : video_type; -- output data MUX
signal pmux_sel : pmuxsel_type; -- parity MUX select
signal dmux_sel : std_ulogic; -- data MUX select
signal omux_sel : omuxsel_type; -- output MUX select
signal did : ubyte_type; -- DID register
signal dbn : ubyte_type; -- DBN/SDID register
signal dc : ubyte_type; -- DC register/counter
signal udw_ram : udw_ram_type; -- UDW RAM
signal udw_wr_en : std_ulogic; -- write enable signal for UDW RAM
signal ld_out_reg : std_ulogic; -- loads the anc_out reg when asserted
signal pkt_in_empty_x : std_ulogic; -- internal version of pkt_in_empty output
signal udw : video_type; -- UDW RAM output
--------------------------------------------------------------------------------
-- If using block RAM, use this signal definition.
--
-- signal udw_rd_adr : udwadr_type; -- RAM read address reg for block RAM
--------------------------------------------------------------------------------
-- If using distributed RAM, use this signal definition.
--
signal udw_adr : udwadr_type; -- MUXed address into single port RAM
--
-- XST 4.1 was trying to use one-hot encoding for pmux_sel and omux_sel. These
-- statements force XST to use the constant values as given.
--
attribute fsm_encoding : string;
attribute fsm_encoding of pmux_sel : signal is "user";
attribute fsm_encoding of omux_sel : signal is "user";
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, pkt_rdy_in, send_pkt, dc_eq_0, abort_pkt)
begin
case current_state is
when S_WAIT =>
if (pkt_rdy_in = '1') then
next_state <= S_ADF1;
else
next_state <= S_WAIT;
end if;
when S_ADF1 =>
if (send_pkt = '1') then
next_state <= S_ADF2;
else
next_state <= S_ADF1;
end if;
when S_ADF2 =>
if (abort_pkt = '1') then
next_state <= S_ABRT;
else
next_state <= S_DID;
end if;
when S_DID =>
if (abort_pkt = '1') then
next_state <= S_ABRT;
else
next_state <= S_DBN;
end if;
when S_DBN =>
if (abort_pkt = '1') then
next_state <= S_ABRT;
else
next_state <= S_DC;
end if;
when S_DC =>
if (dc_eq_0 = '1') then
next_state <= S_CHK;
else
next_state <= S_UDW;
end if;
when S_UDW =>
if (dc_eq_0 = '1') then
next_state <= S_CHK;
else
next_state <= S_UDW;
end if;
when S_CHK =>
next_state <= S_END;
when S_END =>
next_state <= S_DONE;
when S_DONE =>
if (pkt_rdy_in = '1') then
next_state <= S_DONE;
else
next_state <= S_WAIT;
end if;
when S_ABRT =>
next_state <= S_ADF1;
when others =>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -