XAPP1249,用来介绍UHD_SDI的实现。
XAPP1290,用来介绍3G_SDI的实现。
XAPP592,用来介绍SDI常规设计。
++++++++++++++++++++++++++++++++++++++++++
以xapp592为例,分析之。
kc705_sdi_demo,是总的wrapper。
IBUFDS_GTE2原语,用来接收晶振的1485差分时钟并驱动,并分频出7425时钟。
7425时钟,用一个BUFG来驱动。
第二个IBUFDS_GTE2原语,用来接收晶振的14835差分时钟并驱动。
k7gtx_sdi_wrapper,是GTX的quad的wrapper,里面例化了4个k7gtx_sdi_wrapper_GT,这是4个transceiver,还有一个GTXE2_COMMON原语,这个QPLL。
k7gtx_sdi_wrapper_GT则例化了一个GTXE2_CHANNEL原语。
k7gtx_sdi_wrapper,例化了整个QUAD,如果只用到了其中的两个,例如GT1和GT2,那么,注释掉其他两个的相关PORT即可。
GTX的主要控制信号,来自于k7_sdi_rxtx。这个wrapper实现整个SDI接口的协议和物理层控制。
回到kc705_sdi_demo,
GT会输出RXOUTCLK和TXOUTCLK,他们经过BUFG后,成为RXUSRCLK和TXUSRCLK。
所以,共用了8个BUFG来驱动8个USRCLK。
每个GTREFCLK0_IN,连接14835时钟,作为CPLL的参考时钟,而
1485时钟,则作为QPLL的参考时钟,所以连接到GT0_GTREFCLK0_COMMON_IN。
GT0_QPLLLOCKDETCLK_IN,则连接到7425时钟。
每个CPLLLOCKDETCLK_IN,也都连接到7425时钟,
每个DRPCLK_IN,也都连接到7425时钟。
GTXRXP_IN和GTXRXN_IN,是连接到外部的差分串行线,接收的数据,被转换成为rxdata,20bits,被同步到rxusrclk。
类似的,
GTXTXP_OUT和GTXTXN_OUT,是连接到外部的差分串行线,发送的数据,是txdata,20bits,同步到txusrclk。
再来看k7_sdi_rxtx,这是SDI协议和物理控制的high level wrapper。
其中使用的multigenHD,vidgen_ntsc,vidgen_pal,都是用来生成合适的视频格式的时序控制模块。他们使用的是tx_usrclk。从而和GT的TX保持同步。
其中用到的x7gtx_sdi_rxtx_wrapper,是SDI协议和物理控制的mid level wrapper。
来分析这个模块。
其中的smpte_sdi模块,是VIVADO生成的XCI,这是生成的SDI的IP。
其中的x7gtx_sdi_control模块,是用来控制GTX的模块。
这里面用到了4个时钟,
clk,是模块的工作时钟,这里,我们使用的是7425时钟,
txusrclk,是GTX的TX相关时钟,这里,我们使用的是txusrclk,
rxusrclk,是GTX的RX相关时钟,这里,我们使用的是rxusrclk,
drpclk,是GTX的DRP的工作时钟。这里,我们使用的是7425时钟。
其中用到dru模块,需要在工程中包含dru.v和dru.ngc两个文件,因为dru.ngc是一个预编译的模块。
来分析smpte_sdi。
这是一个在vivado中生成的IP,我们在代码中例化时,要把模块名字改为我们自己生成的IP的名字。
回到x7gtx_sdi_rxtx_wrapper,
其中关键的信号如下:
input wire [19:0] gtx_rxdata, // connect to RXDATA port of GTX
output wire [19:0] gtx_txdata, // connect to TXDATA port of GTX
将GTX收到的rxdata送入该模块,
该模块将待发送的txdata送入GTX。
output wire [9:0] rx_ds1a, // data stream 1A: SD=Y/C, HD=Y, 3GA=ds1, 3GB=Y link A
output wire [9:0] rx_ds2a, // data stream 2A: HD=C, 3GA=ds2, 3GB=C link A
output wire [9:0] rx_ds1b, // data stream 1B: 3G level B only = Y link B
output wire [9:0] rx_ds2b, // data stream 2B: 3G level B only = C link B
output wire [10:0] rx_line_a, // line number for HD & 3G (link A for level B)
output wire [10:0] rx_line_b, // line number of 3G level B link B
将rxdata转换成ds1和ds2输出,这是经过协议解析之后的视频流数据。
input wire [9:0] tx_video_a_y_in, // Data stream Y link A input: SD Y/C, HD & 3GA Y in, 3GB A Y in
input wire [9:0] tx_video_a_c_in, // Data stream C link A input: HD & 3GA C in, 3GB A C in
input wire [9:0] tx_video_b_y_in, // 3G level B only: Data stream Y link B input
input wire [9:0] tx_video_b_c_in, // 3G level B only: Data stream C link B input
input wire [10:0] tx_line_a, // current line number for link A
input wire [10:0] tx_line_b, // current line number for link B
input wire tx_use_dsin, // 0=use the internal data streams, 1=use the tx_dsxx_in data streams
input wire [9:0] tx_ds1a_in, // data stream 1 link A in: SD Y/C, HD Y, 3G Y, dual-link A Y
input wire [9:0] tx_ds2a_in, // data stream 2 link A in: HD C, 3G C, dual-link A C
input wire [9:0] tx_ds1b_in, // data stream 1 link B in: dual-link B Y
input wire [9:0] tx_ds2b_in, // data stream 2 link B in: dual-link B C
将video_yc视频流或者ds视频流按照协议转换成txdata输出,选择哪个视频流,取决于tx_use_dsin这个控制信号。
来看看它的上层,即k7_sdi_rxtx,
这里面如何例化x7gtx_sdi_rxtx_wrapper,又是如何使用它的。
对于tx而言,使用的是video_yc视频流,只使用了linka,不使用linkb,所以只连接了tx_y和tx_c,两个10bits的信号。
tx_line_a和tx_line_b使用的是multigenHD输出的tx_line信号。
注意,tx_y和ty_c都是内部生成的信号,用来生成测试视频流。
对于rx而言,使用的是ds视频流,在用户逻辑模块中,可以进一步处理ds视频流,得到需要的格式的数据。
++++++++++++++++++++++++++++++++++++++++++++++++++++++
demo中,sdi的发送,使用的是内部生成的测试视频流,且受到的视频流数据,也没有经过格式转换从而被其他模块使用,下面来看看,实际使用中,如何配置SDI的RX和TX。
对于TX_wrapper,
添加
input wire [9:0] tx_hd_y,
input wire [9:0] tx_hd_c,
input wire [10:0] tx_line
从外部引入要发送的数据流,然后在k7_sdi_rxrtx中引入相应的数据流,
k7_sdi_rxtx SDI3 (
.clk (clk_74_25),
.sdi_c_in (tx_hd_c),
.sdi_y_in (tx_hd_y),
.sdi_ln_in (tx_line),
在k7_sdi_rxtx模块内部,
assign tx_line = sdi_ln_in;
assign tx_c = sdi_c_in;
assign tx_y = tx_mode == 2'b01 ? tx_sd : sdi_y_in;
然后将数据流引入x7gtx_sdi_rxtx_wrapper模块,
x7gtx_sdi_rxtx_wrapper #(
.FXDCLK_FREQ (74250000))
SDI (
.clk (clk),
.tx_rst (tx_fabric_reset),
.tx_usrclk (tx_usrclk),
.tx_insert_crc (1'b1),
.tx_insert_ln (1'b1),
.tx_insert_edh (1'b1),
.tx_insert_vpid (tx_mode == 2'b10),
.tx_overwrite_vpid (1'b1),
.tx_video_a_y_in (tx_y),
.tx_video_a_c_in (tx_c),
.tx_video_b_y_in (10'b0),
.tx_video_b_c_in (10'b0),
.tx_line_a (tx_line),
.tx_line_b (tx_line),