📄 hdsdi_framer_mult.v
字号:
//------------------------------------------------------------------------------
// Copyright (c) 2005 Xilinx, Inc.
// All Rights Reserved
//------------------------------------------------------------------------------
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Author: John F. Snow, Advanced Product Division, Xilinx, Inc.
// \ \ Filename: $RCSfile: hdsdi_framer_mult.v,rcs $
// / / Date Last Modified: $Date: 2006-01-04 10:36:34-07 $
// /___/ /\ Date Created: Jan 5, 2005
// \ \ / \
// \___\/\___\
//
//
// Revision History:
// $Log: hdsdi_framer_mult.v,rcs $
// Revision 1.2 2006-01-04 10:36:34-07 jsnow
// Modifications to prevent false detection of TRS sequences.
//
// Revision 1.1 2005-01-14 10:45:02-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.
//
//------------------------------------------------------------------------------
/*
NOTE: THIS VERSION OF THE FRAMER HAS BEEN REPLACED WITH THE FULL 60-BIT DECODE
VERSION BECAUSE THIS VERSION WILL, VERY OCCASIONALLY, FALSELY DETECT A TRS WHEN
AUDIO IS EMBEDDED IN THE HD-SDI BITSTREAM.
Description of module:
SMPTE 292M-1998 HD-SDI is a standard for transmitting high-definition digital
video over a serial link. This module is exactly the same as the normal
hdsdi_framer module except that the barrel shifter is made from six MULT18X18
blocks plus a little bit of decoding logic. This can reduce the amount of fabric
used by the framer if the multiplier blocks are available. This framer uses 94
fewer 4-input LUTs than the standard framer, at the cost of 6 MULT18X18 blocks.
This module accepts 20-bit parallel "unframed" data words from the HD-SDI
descrambler module and examines the bit stream for the 30-bit TRS pramble. Once
a TRS is found, the framer then knows the bit boundary of all subsequent 10-bit
characters in the bit stream and uses this offset to generate two 10-bit
parallel data words on its output every clock cycle.
The module has the following control inputs:
ce: The clock enable input controls loading of all registers in the module. It
must be asserted whenever a new 10-bit word is to be loaded into the module. By
providing a clock enable, this module can use a clock that is running at the
bit rate of the SDI bit stream if ce is asserted once every ten clock cycles.
frame_en: This input controls whether the framer rsynchronize to new character
offsets when out-of-phase TRS symbols are detected. When this input is high,
out-of-phase TRS symbols will cause the framer to resynchronize.
The module generates the following outputs:
q: This 20-bit output port contains the properly framed data word.
trs: (timing reference signal) This output is asserted when the y and c outputs
have any of the four words of a TRS.
xyz: This output is asserted when the XYZ word of a TRS is output.
eav: This output is asserted when the XYZ word of a EAV is output.
sav: This output is asserted when the XYZ word of a SAV is output.
trs_err: This output is asserted during the XYZ word if an error is detected
by examining the protection bits.
nsp: (new start position) If frame_en is low and a TRS is detected that does not
match the current character offset, this signal will be asserted high. The nsp
signal will remain asserted until the offset error has been corrected..
There are normally three ways to use the frame_en input:
frame_en tied high: When frame_en is tied high, the framer will resynchronize
on every TRS detected.
frame_en tied to nsp: When in this mode, the framer implements TRS filtering.
If a TRS is detected that is out of phase with the existing character offset,
nsp will be asserted, but the framer will not resynchronize. If the next TRS
received is in phase with the current character offset, nsp will go low and the
will not resynchronize. If the next TRS arrives out of phase with the current
character offset, then the new character offset will be loaded and nsp will be
deasserted. Single erroneous TRS are ignored in this mode, but if they persist,
the decoder will adjust.
frame_en tied low: The automatic framing function is disabled when frame_en is
tied low. If data is being sent across the interface that does not comply with
the SDI standard and may contain data that looks like TRS symbols, the framing
function can be disabled in this manner.
--------------------------------------------------------------------------------
*/
`timescale 1ns / 1ns
module hdsdi_framer_mult (
input wire clk, // input clock
input wire rst, // reset signal
input wire ce, // clock enable
input wire [19:0] d, // input data
input wire frame_en, // enables resynchronization when high
output wire [9:0] c, // chroma channel output data
output wire [9:0] y, // luma channel output data
output reg trs, // asserted when out reg contains a TRS symbol
output wire xyz, // asserted during XYZ word of TRS symbol
output wire eav, // asserted during XYZ word of EAV symbol
output wire sav, // asserted during XYZ word of SAV symbol
output wire trs_err, // asserted if error detected in XYZ word
output reg nsp // new start position detected
);
//------------------------------------------------------------------------------
// Internal signals
//
reg [19:0] in_reg; // input register
reg [19:0] dly_reg; // pipeline delay register
reg [19:0] dly_reg2; // pipeline dealy register
reg [4:0] offset_reg; // offset register
reg [3:0] trs_out; // used to generate the trs output signal
wire [38:0] in_0; // input vector for zeros detector
wire [38:0] in_1; // input vector for ones detector
reg [19:0] ones_in; // ones detector result vector
reg [19:0] zeros_in; // zeros detector result vector
reg [19:0] zeros_dly; // zeros detector result vector delayed
wire [19:0] trs_match; // TRS detector result vector
wire trs_detected; // asserted when TRS symbol is detected
wire [4:0] offset_val; // calculated offset value to load into offset_reg
reg [38:0] barrel_in; // barrel shifter input register
wire [19:0] barrel_out; // output of barrel shifter
wire new_offset; // mismatch between offset_val and offset_reg
reg [53:0] bs_in; // input vector to barrel shifter first level
reg sc_top; // shift code for top level barrel shifter MUX
reg [11:0] sc_bot; // shift code for bottom level barrel shifter MUX
wire [35:0] bstop_a; // output of barrel shifter top level MULT18X18 A
wire [35:0] bstop_b; // output of barrel shifter top level MULT18X18 B
wire [35:0] bstop_c; // output of barrel shifter top level MULT18X18 C
reg [26:0] bstop; // output of the barrel shifter's top level MUX section
wire [35:0] bsbot_a; // output of barrel shifter bottom level MULT18X18 A
wire [35:0] bsbot_b; // output of barrel shifter bottom level MULT18X18 B
wire [35:0] bsbot_c; // output of barrel shifter bottom level MULT18X18 C
reg [9:0] c_int; // internal version of c output
reg [9:0] y_int; // internal version of y output
reg xyz_int;
integer i,j; // barrel shifter loop variables
integer l,m; // TRS detect for loop variables
//------------------------------------------------------------------------------
// Input and pipeline delay registers
//
//
// input register
//
always @ (posedge clk or posedge rst)
if (rst)
in_reg <= 0;
else if (ce)
in_reg <= d;
//
// delay register
//
always @ (posedge clk or posedge rst)
if (rst)
dly_reg <= 0;
else if (ce)
dly_reg <= in_reg;
//
// delay register 2
//
always @ (posedge clk or posedge rst)
if (rst)
dly_reg2 <= 0;
else if (ce)
dly_reg2 <= dly_reg;
//------------------------------------------------------------------------------
// TRS detector and offset encoder
//
// The TRS detector identifies the 60-bit TRS sequence consisting of 20 '1'
// bits followed by 40 '0' bits. The first level of the TRS detector consists
// of a ones detector and a zeros detector. The ones detector looks for a run
// of 20 consecutive ones in the in_1 vector. The in_1 vector is a 39-bit
// vector made up of the contents of dly_reg2 and the 19 LSBs of dly_reg. The
// zeros detector looks for a run of 20 consecutive '0' bits in the in_0 vector.
// The in_0 vector is 39-bits wide and is made up of the contents of in_reg and
// the 19 LSBs of the d input port. The output of the zeros detector is stored
// in the zeros_dly register so that the zeros detector can be used twice to
// find two consecutive runs of 20 zeros. The output of the zeros detector
// (both zeros_in and zeros_dly) and the ones detector (ones_in) are 20-bit
// vectors with a bit for each possible starting position of the 20-bit run.
//
// A vector called trs_match is created by ORing the ones_in, zeros_in, and
// zeros_dly values together. The 20-bit trs_match vector will have a single
// bit set indicating the starting position of a TRS if one is present in the
// input vector. The trs_detected signal, asserted when a TRS is detected, can
// then be created by ORing all of the bits of trs_match together. And the
// offset_val, which is a 4-bit binary value indicating the starting position
// of the TRS to the barrel shifter, can be generated from the trs_match vector.
//
//
// TRS detector and offset encoder
//
assign in_0 = {d[18:0], in_reg};
assign in_1 = {dly_reg[18:0], dly_reg2};
//
// zeros and ones detectors
//
always @ (in_0)
for (l = 0; l < 20; l = l + 1)
zeros_in[l] <= ~(in_0[l+19] | in_0[l+18] | in_0[l+17] | in_0[l+16] |
in_0[l+15] | in_0[l+14] | in_0[l+13] | in_0[l+12] |
in_0[l+11] | in_0[l+10] | in_0[l+ 9] | in_0[l+ 8] |
in_0[l+ 7] | in_0[l+ 6] | in_0[l+ 5] | in_0[l+ 4] |
in_0[l+ 3] | in_0[l+ 2] | in_0[l+ 1] | in_0[l+ 0]);
always @ (in_1)
for (m = 0; m < 20; m = m + 1)
ones_in[m] <= in_1[m+19] & in_1[m+18] & in_1[m+17] & in_1[m+16] &
in_1[m+15] & in_1[m+14] & in_1[m+13] & in_1[m+12] &
in_1[m+11] & in_1[m+10] & in_1[m+ 9] & in_1[m+ 8] &
in_1[m+ 7] & in_1[m+ 6] & in_1[m+ 5] & in_1[m+ 4] &
in_1[m+ 3] & in_1[m+ 2] & in_1[m+ 1] & in_1[m+ 0];
// delay reg for zeros_in
always @ (posedge clk or posedge rst)
if (rst)
zeros_dly <= 0;
else if (ce)
zeros_dly <= zeros_in;
// second level of gates
assign trs_match = zeros_in & zeros_dly & ones_in;
// trs_detected signal
assign trs_detected = |trs_match;
//
// The following assignments encode the trs_match vector into a binary
// offset code.
//
assign offset_val[0] = trs_match[1] | trs_match[3] | trs_match[5] |
trs_match[7] | trs_match[9] | trs_match[11] |
trs_match[13] | trs_match[15] | trs_match[17] |
trs_match[19];
assign offset_val[1] = trs_match[2] | trs_match[3] | trs_match[6] |
trs_match[7] | trs_match[10] | trs_match[11] |
trs_match[14] | trs_match[15] | trs_match[18] |
trs_match[19];
assign offset_val[2] = trs_match[4] | trs_match[5] | trs_match[6] |
trs_match[7] | trs_match[12] | trs_match[13] |
trs_match[14] | trs_match[15];
assign offset_val[3] = trs_match[8] | trs_match[9] | trs_match[10] |
trs_match[11] | trs_match[12] | trs_match[13] |
trs_match[14] | trs_match[15];
assign offset_val[4] = trs_match[16] | trs_match[17] | trs_match[18] |
trs_match[19];
//
// offset_reg: barrel shifter offset register
//
// The offset_reg loads the offset_val whenever trs_detected is
// asserted and frame_en is asserted.
//
always @ (posedge clk or posedge rst)
if (rst)
offset_reg <= 0;
else if (ce)
if (trs_detected & frame_en)
offset_reg <= offset_val;
//
// New start position detector
//
// A comparison between offset_val and offset_reg determines if
// the new offset is different than the current one. If there is
// a mismatch and frame_en is not asserted, then the nsp output
// will be asserted.
//
assign new_offset = offset_val != offset_reg;
always @ (posedge clk or posedge rst)
if (rst)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -