diff options
author | James McKenzie <root@ka-ata-killa.panaceas.james.local> | 2025-10-05 17:17:44 +0100 |
---|---|---|
committer | James McKenzie <root@ka-ata-killa.panaceas.james.local> | 2025-10-05 17:17:44 +0100 |
commit | 8123e5531868f8db9787c81792286143a0f2868a (patch) | |
tree | b7ce93ef80af9b764f8c36ee7a3274c2682c2de2 /fpga/spartan6/example | |
parent | e26607065f26b6bc3705b4ab80c2bdf101f4f3b6 (diff) | |
download | hp_instrument_lcds-8123e5531868f8db9787c81792286143a0f2868a.tar.gz hp_instrument_lcds-8123e5531868f8db9787c81792286143a0f2868a.tar.bz2 hp_instrument_lcds-8123e5531868f8db9787c81792286143a0f2868a.zip |
syncing
Diffstat (limited to 'fpga/spartan6/example')
21 files changed, 4720 insertions, 0 deletions
diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/DRAM16XN.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/DRAM16XN.v new file mode 100644 index 0000000..656ec8f --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/DRAM16XN.v @@ -0,0 +1,51 @@ +// +// Module: DRAM16XN +// +// Description: Distributed SelectRAM example +// Dual Port 16 x N-bit +// +// Device: Spartan-3 Family +//--------------------------------------------------------------------------------------- + +module DRAM16XN #(parameter data_width = 20) + ( + DATA_IN, + ADDRESS, + ADDRESS_DP, + WRITE_EN, + CLK, + O_DATA_OUT, + O_DATA_OUT_DP); + +input [data_width-1:0]DATA_IN; +input [3:0] ADDRESS; +input [3:0] ADDRESS_DP; +input WRITE_EN; +input CLK; + +output [data_width-1:0]O_DATA_OUT_DP; +output [data_width-1:0]O_DATA_OUT; + +genvar i; +generate + for(i = 0 ; i < data_width ; i = i + 1) begin : dram16s + RAM16X1D i_RAM16X1D_U( + .D(DATA_IN[i]), //insert input signal + .WE(WRITE_EN), //insert Write Enable signal + .WCLK(CLK), //insert Write Clock signal + .A0(ADDRESS[0]), //insert Address 0 signal port SPO + .A1(ADDRESS[1]), //insert Address 1 signal port SPO + .A2(ADDRESS[2]), //insert Address 2 signal port SPO + .A3(ADDRESS[3]), //insert Address 3 signal port SPO + .DPRA0(ADDRESS_DP[0]), //insert Address 0 signal dual port DPO + .DPRA1(ADDRESS_DP[1]), //insert Address 1 signal dual port DPO + .DPRA2(ADDRESS_DP[2]), //insert Address 2 signal dual port DPO + .DPRA3(ADDRESS_DP[3]), //insert Address 3 signal dual port DPO + .SPO(O_DATA_OUT[i]), //insert output signal SPO + .DPO(O_DATA_OUT_DP[i]) //insert output signal DPO + ); + end +endgenerate + +endmodule + diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/dcmspi.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/dcmspi.v new file mode 100644 index 0000000..e549f69 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/dcmspi.v @@ -0,0 +1,142 @@ +///////////////////////////////////////////////////// +// DCM SPI Controller +///////////////////////////////////////////////////// +`timescale 1ns / 1ps + +module dcmspi ( + input RST, //Synchronous Reset + input PROGCLK, //SPI clock + input PROGDONE, //DCM is ready to take next command + input DFSLCKD, + input [7:0] M, //DCM M value + input [7:0] D, //DCM D value + input GO, //Go programme the M and D value into DCM(1 cycle pulse) + output reg BUSY, + output reg PROGEN, //SlaveSelect, + output reg PROGDATA //CommandData +); + +parameter TCQ = 1; + +wire [9:0] mval = {M, 1'b1, 1'b1}; //M command: 11,M0-M7 +wire [9:0] dval = {D, 1'b0, 1'b1}; //D command: 10,D0-D7 + +reg dfslckd_q; +reg dfslckd_rising; +always @ (posedge PROGCLK) +begin + dfslckd_q <=#TCQ DFSLCKD; + dfslckd_rising <=#TCQ !dfslckd_q & DFSLCKD; +end + +always @ (posedge PROGCLK) +begin + if(RST || (PROGDONE & dfslckd_rising)) + BUSY <=#TCQ 1'b0; + else if (GO) + BUSY <=#TCQ 1'b1; +end + +reg [9:0] sndval; +reg sndm = 1'b0; +reg sndd = 1'b0; + +wire ddone; +SRL16E VCNT ( + .Q(ddone), // SRL data output + .A0(1'b1), // Select[0] input + .A1(1'b0), // Select[1] input + .A2(1'b0), // Select[2] input + .A3(1'b1), // Select[3] input + .CE(1'b1), //clock enable + .CLK(PROGCLK), // Clock input + .D(GO) // SRL data input +); +// The following defparam declaration +defparam VCNT.INIT = 16'h0; + +always @ (posedge PROGCLK) +begin + if(RST || ddone) + sndd <=#TCQ 1'b0; + else if(GO) + sndd <=#TCQ 1'b1; +end + +//V has been sent now it is M's turn +wire ldm; +SRL16E DMGAP ( + .Q(ldm), // SRL data output + .A0(1'b0), // Select[0] input + .A1(1'b0), // Select[1] input + .A2(1'b1), // Select[2] input + .A3(1'b0), // Select[3] input + .CE(1'b1), //clock enable + .CLK(PROGCLK), // Clock input + .D(ddone) // SRL data input +); +// The following defparam declaration +defparam DMGAP.INIT = 16'h0; + +wire mdone; +SRL16E MCNT ( + .Q(mdone), // SRL data output + .A0(1'b1), // Select[0] input + .A1(1'b0), // Select[1] input + .A2(1'b0), // Select[2] input + .A3(1'b1), // Select[3] input + .CE(1'b1), //clock enable + .CLK(PROGCLK), // Clock input + .D(ldm) // SRL data input +); +// The following defparam declaration +defparam MCNT.INIT = 16'h0; + +always @ (posedge PROGCLK) +begin + if(RST || mdone) + sndm <=#TCQ 1'b0; + else if(ldm) + sndm <=#TCQ 1'b1; +end + +wire gocmd; +SRL16E GOGAP ( + .Q(gocmd), // SRL data output + .A0(1'b0), // Select[0] input + .A1(1'b0), // Select[1] input + .A2(1'b1), // Select[2] input + .A3(1'b0), // Select[3] input + .CE(1'b1), //clock enable + .CLK(PROGCLK), // Clock input + .D(mdone) // SRL data input +); +// The following defparam declaration +defparam GOGAP.INIT = 16'h0; + +always @ (posedge PROGCLK) +begin + if(RST) + sndval <=#TCQ 10'h0; + else if(GO) //send D first + sndval <=#TCQ dval; + else if(ldm) + sndval <=#TCQ mval; + else if(sndm || sndd) + sndval <=#TCQ sndval >> 1; +end + +always @ (posedge PROGCLK) +begin + PROGEN <=#TCQ sndd | sndm | gocmd; +end + +always @ (posedge PROGCLK) +begin + if(sndm || sndd) + PROGDATA <=#TCQ sndval[0]; + else + PROGDATA <=#TCQ 1'b0; +end + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/debnce.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/debnce.v new file mode 100644 index 0000000..4377b33 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/debnce.v @@ -0,0 +1,121 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2006 Xilinx, Inc. +// This design is confidential and proprietary of Xilinx, All Rights Reserved. +////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor: Xilinx +// \ \ \/ Version: 1.0.0 +// \ \ Filename: debnce.v +// / / Date Created: October 20, 2008 +// /___/ /\ Last Modified: October 20, 2008 +// \ \ / \ +// \___\/\___\ +// +// Devices: Spartan-3 Generation FPGA +// Purpose: Switch debouncer: Detecting signal transition and wait for 2^16 +// cycles +// Contact: bob.feng@xilinx.com +// Reference: None +// +// Revision History: +// Rev 1.0.0 - (Bob Feng) First created October 20, 2008. +// +////////////////////////////////////////////////////////////////////////////// +// +// LIMITED WARRANTY AND DISCLAIMER. These designs are provided to you "as is". +// Xilinx and its licensors make and you receive no warranties or conditions, +// express, implied, statutory or otherwise, and Xilinx specifically disclaims +// any implied warranties of merchantability, non-infringement, or fitness for +// a particular purpose. Xilinx does not warrant that the functions contained +// in these designs will meet your requirements, or that the operation of +// these designs will be uninterrupted or error free, or that defects in the +// designs will be corrected. Furthermore, Xilinx does not warrant or make any +// representations regarding use or the results of the use of the designs in +// terms of correctness, accuracy, reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its licensors be liable +// for any loss of data, lost profits, cost or procurement of substitute goods +// or services, or for any special, incidental, consequential, or indirect +// damages arising from the use or operation of the designs or accompanying +// documentation, however caused and on any theory of liability. This +// limitation will apply even if Xilinx has been advised of the possibility +// of such damage. This limitation shall apply not-withstanding the failure +// of the essential purpose of any limited remedies herein. +// +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2006 Xilinx, Inc. +// This design is confidential and proprietary of Xilinx, All Rights Reserved. +////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ns / 1 ps + +module debnce + ( + input wire sync, + input wire clk, + output reg debnced = 1'b0 + ); + + //******************************************************************// + // Implement debouncing. // + //******************************************************************// + + reg [15:0] ctr; + reg dly; + wire sat; + + reg sync_q; + reg transition; + + wire block_out; + SRL16E #(.INIT(16'h0)) blockout_0 ( + .Q(block_out), + .A0(1'b1), + .A1(1'b1), + .A2(1'b1), + .A3(1'b1), + .CE(1'b1), + .CLK(clk), + .D(1'b1) + ); + + always @ (posedge clk) begin + sync_q <= sync; + transition <= block_out & (sync_q ^ sync); + end + + reg cntr_en; + always @ (posedge clk) begin + if(transition) + cntr_en <= 1'b1; + else if(sat) + cntr_en <= 1'b0; + end + + +`ifdef SIMULATION + initial begin + ctr = 16'b0; + end + + parameter SATISFY = 16'hff; +`else + parameter SATISFY = 16'hffff; +`endif + + assign sat = (ctr == SATISFY); + + always @(posedge clk) + begin + if(transition) + ctr <= 1'b0; + else if(cntr_en) + ctr <= ctr + 1; + end + + always @ (posedge clk) begin + debnced <= sat; + end + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/hdclrbar.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/hdclrbar.v new file mode 100644 index 0000000..dffacec --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/hdclrbar.v @@ -0,0 +1,502 @@ +//------------------------------------------------------------------------------ +// Copyright (c) 2007 Xilinx, Inc. +// All Rights Reserved +//------------------------------------------------------------------------------ +// ____ ____ +// / /\/ / +// /___/ \ / Vendor: Xilinx +// \ \ \/ Author: Bob Feng, General Product Division, Xilinx, Inc. +// \ \ Filename: $RCSfile: hdclrbar.v,v $ +// / / Date Last Modified: $Date: 2010/08/25 00:37:39 $ +// /___/ /\ Date Created: July 26, 2007 +// \ \ / \ +// \___\/\___\ +// +//------------------------------------------------------------------------------ +/* +This video pattern generator will generate color bars for the 18 video standards +currently supported by the SMPTE 292M (HD-SDI) video standard. The color bars +comply with SMPTE RP-219 standard color bars, as shown below. This module can +also generate the SMPTE RP-198 HD-SDI checkfield test pattern and 75% color +bars. + +|<-------------------------------------- a ------------------------------------->| +| | +| |<----------------------------(3/4)a-------------------------->| | +| | | | +| d | c c c c c c c | d | ++--------+--------+--------+--------+--------+--------+--------+--------+--------+ - - - - - +| | | | | | | | | | ^ ^ +| | | | | | | | | | | | +| | | | | | | | | | | | +| | | | | | | | | | | | +| | | | | | | | | | (7/12)b | +| 40% | 75% | YELLOW | CYAN | GREEN | MAGENTA| RED | BLUE | 40% | | | +| GRAY | WHITE | | | | | | | GRAY | | | +| *1 | | | | | | | | *1 | | b +| | | | | | | | | | | | +| | | | | | | | | | | | +| | | | | | | | | | v | ++--------+--------+--------+--------+--------+--------+--------+--------+--------+ - - - | +|100%CYAN| *2 | 75% WHITE |100%BLUE| (1/12)b | ++--------+--------+-----------------------------------------------------+--------+ - - - | +|100%YELO| *3 | Y-RAMP |100% RED| (1/12)b | ++--------+--------+---+-----------------+-------+--+--+--+--+--+--------+--------+ - - - | +| | | | | | | | | | | | | +| 15% | 0% | 100% | 0% |BL|BL|BL|BL|BL| 0% | 15% | (3/12)b | +| GRAY | BLACK | WHITE | BLACK |K-|K |K+|K |K+| BLACK | GRAY | | +| *4 | | | |2%|0%|2%|0%|4%| | *4 | v ++--------+------------+-----------------+-------+--+--+--+--+--+--------+--------+ - - - - - + d (3/2)c 2c (5/6)c c c c c c c d + - - - - - + 3 3 3 3 3 + +*1: The block marked *1 is 40% Gray for a default value. This value may +optionally be set to any other value in accordance with the operational +requirements of the user. + +*2: In the block marked *2, the user may select 75% White, 100% White, +I, or +-I. + +*3: In the block marked *3, the user may select either 0% Black, or +Q. When the +-I value is selected for the block marked *2, then the +Q signal must be +selected for the *3 block. + +*4: The block marked *4 is 15% Gray for a default value. This value may +optionally be set to any other value in accordance with the operational +requirements of the user. + + + +*/ +module hdcolorbar( + input i_clk_74M, //74.25 MHZ pixel clock + input i_rst, + input baronly, //output only 75% color bar + input [1:0] i_format, + input [11:0] i_vcnt, //vertical counter from video timing generator + input [11:0] i_hcnt, //horizontal counter from video timing generator + + output reg[7:0] o_r, + output reg[7:0] o_g, + output reg[7:0] o_b +); + +parameter Lvl_100 = 8'd255; +parameter Lvl_75 = 8'd191; +parameter Lvl_40 = 8'd102; +parameter Lvl_15 = 8'd38; +parameter Lvl_4 = 8'd10; +parameter Lvl_2 = 8'd5; +parameter Lvl_0 = 8'd0; +parameter Lvl_2n = 8'd5; +parameter I_R = 8'd0; // -I signal +parameter Q_R = 8'd65;// +Q signal +parameter I_G = 8'd63; +parameter Q_G = 8'd0; +parameter I_B = 8'd105; +parameter Q_B = 8'd120; + +reg [1:0] i_format_sync, i_format_q; +always @ (posedge i_clk_74M) begin + i_format_sync <= i_format_q; + i_format_q <= i_format; +end + +wire interlace = i_format_sync[1]; //0-progressive 1-interlace +wire hdtype = i_format_sync[0]; //0-720 1-1080 + +/////////////////////////////////////////////////////////// +// There are total 4 vertical and 17 horizontal regions +/////////////////////////////////////////////////////////// + +reg [16:0] Hregion; +reg [3:0] Vregion; + +parameter VRGN1 = 4'd0; +parameter VRGN2 = 4'd1; +parameter VRGN3 = 4'd2; +parameter VRGN4 = 4'd3; + +parameter HRGN1 = 17'd0; +parameter HRGN2 = 17'd1; +parameter HRGN3 = 17'd2; +parameter HRGN4 = 17'd3; +parameter HRGN5 = 17'd4; +parameter HRGN6 = 17'd5; +parameter HRGN7 = 17'd6; +parameter HRGN8 = 17'd7; +parameter HRGN9 = 17'd8; +parameter HRGN10 = 17'd9; +parameter HRGN11 = 17'd10; +parameter HRGN12 = 17'd11; +parameter HRGN13 = 17'd12; +parameter HRGN14 = 17'd13; +parameter HRGN15 = 17'd14; +parameter HRGN16 = 17'd15; +parameter HRGN17 = 17'd16; + +/////////////////////////////////////////////////////////// +// Define Vertical and Horizontal regions +/////////////////////////////////////////////////////////// +wire [11:0] vbar1bgn, vbar1bgn2; +wire [11:0] vbar2bgn, vbar2bgn2; +wire [11:0] vbar3bgn, vbar3bgn2; +wire [11:0] vbar4bgn, vbar4bgn2; + +wire [11:0] hbar1bgn; +wire [11:0] hbar2bgn; +wire [11:0] hbar3bgn; +wire [11:0] hbar4bgn; +wire [11:0] hbar5bgn; +wire [11:0] hbar6bgn; +wire [11:0] hbar7bgn; +wire [11:0] hbar8bgn; +wire [11:0] hbar9bgn; +wire [11:0] hbar10bgn; +wire [11:0] hbar11bgn; +wire [11:0] hbar12bgn; +wire [11:0] hbar13bgn; +wire [11:0] hbar14bgn; +wire [11:0] hbar15bgn; +wire [11:0] hbar16bgn; +wire [11:0] hbar17bgn; + +/**************************************************************************************************** + 1080i Vertical Timing: + +|<-- 540 Active Lines --->|<-- 23 vblnks --->|<-- 540 Active Lines --->|<-- 22 vblnks -->| +|_________......__________| |_________......__________| |__...... +| | | | | +| |______......______| |______......_____| +^ ^ ^ ^ ^ +0 539 562 1102 1124 + +VSYNC: + _____ _____ + | | | | +_____________________________| |______________________________________| |___________ + +****************************************************************************************************/ + +/////////////////////////////////////////////////////////////////// +// Here we try to determine vertical ranges +/////////////////////////////////////////////////////////////////// +assign vbar1bgn = 12'd0; +assign vbar2bgn = (hdtype) ? ((interlace) ? 12'd315 : 12'd630) : 12'd420; +assign vbar3bgn = (hdtype) ? ((interlace) ? 12'd360 : 12'd720) : 12'd480; +assign vbar4bgn = (hdtype) ? ((interlace) ? 12'd405 : 12'd810) : 12'd540; + +//This is used only for interlaced second frame +assign vbar1bgn2 = 12'd563; +assign vbar2bgn2 = 12'd878; +assign vbar3bgn2 = 12'd923; +assign vbar4bgn2 = 12'd968; + +/////////////////////////////////////////////////////////////////// +// Here we try to determine horizontal ranges +/////////////////////////////////////////////////////////////////// +assign hbar1bgn = 12'd0; +assign hbar2bgn = (hdtype) ? 12'd 240 : 12'd160; +assign hbar3bgn = (hdtype) ? 12'd 445 : 12'd297; +assign hbar4bgn = (hdtype) ? 12'd 651 : 12'd434; +assign hbar5bgn = (hdtype) ? 12'd 857 : 12'd571; +assign hbar6bgn = (hdtype) ? 12'd 1063 : 12'd709; +assign hbar7bgn = (hdtype) ? 12'd 1269 : 12'd846; +assign hbar8bgn = (hdtype) ? 12'd 1475 : 12'd983; +assign hbar9bgn = (hdtype) ? 12'd 1680 : 12'd1120; +assign hbar10bgn = (hdtype) ? 12'd 240 : 12'd160; +assign hbar11bgn = (hdtype) ? 12'd 549 : 12'd366; +assign hbar12bgn = (hdtype) ? 12'd 960 : 12'd640; +assign hbar13bgn = (hdtype) ? 12'd 1131 : 12'd754; +assign hbar14bgn = (hdtype) ? 12'd 1200 : 12'd800; +assign hbar15bgn = (hdtype) ? 12'd 1268 : 12'd845; +assign hbar16bgn = (hdtype) ? 12'd 1337 : 12'd891; +assign hbar17bgn = (hdtype) ? 12'd 1405 : 12'd937; + +always @ (posedge i_clk_74M) +begin + if (i_rst) begin + Vregion <= 4'h0; + end else begin + if (baronly) + Vregion <= VRGN1; + else if(interlace) + if (((i_vcnt >= vbar1bgn) && (i_vcnt < vbar2bgn)) || + ((i_vcnt >= vbar1bgn2) && (i_vcnt < vbar2bgn2))) + Vregion <= VRGN1; + else if (((i_vcnt >= vbar2bgn) && (i_vcnt < vbar3bgn)) || + ((i_vcnt >= vbar2bgn2) && (i_vcnt < vbar3bgn2))) + Vregion <= VRGN2; + else if (((i_vcnt >= vbar3bgn) && (i_vcnt < vbar4bgn)) || + ((i_vcnt >= vbar3bgn2) && (i_vcnt < vbar4bgn2))) + Vregion <= VRGN3; + else + Vregion <= VRGN4; + else + if ((i_vcnt >= vbar1bgn) && (i_vcnt < vbar2bgn)) + Vregion <= VRGN1; + else if ((i_vcnt >= vbar2bgn) && (i_vcnt < vbar3bgn)) + Vregion <= VRGN2; + else if ((i_vcnt >= vbar3bgn) && (i_vcnt < vbar4bgn)) + Vregion <= VRGN3; + else + Vregion <= VRGN4; + end +end + +always @ (posedge i_clk_74M) +begin + if(i_rst) begin + Hregion <= 17'h0; + end else + case (Vregion) + VRGN4: begin + if((i_hcnt >= hbar1bgn) && (i_hcnt < hbar10bgn)) + Hregion <= HRGN1; + else if((i_hcnt >= hbar10bgn) && (i_hcnt < hbar11bgn)) + Hregion <= HRGN10; + else if((i_hcnt >= hbar11bgn) && (i_hcnt < hbar12bgn)) + Hregion <= HRGN11; + else if((i_hcnt >= hbar12bgn) && (i_hcnt < hbar13bgn)) + Hregion <= HRGN12; + else if((i_hcnt >= hbar13bgn) && (i_hcnt < hbar14bgn)) + Hregion <= HRGN13; + else if((i_hcnt >= hbar14bgn) && (i_hcnt < hbar15bgn)) + Hregion <= HRGN14; + else if((i_hcnt >= hbar15bgn) && (i_hcnt < hbar16bgn)) + Hregion <= HRGN15; + else if((i_hcnt >= hbar16bgn) && (i_hcnt < hbar17bgn)) + Hregion <= HRGN16; + else if((i_hcnt >= hbar17bgn) && (i_hcnt < hbar8bgn)) + Hregion <= HRGN17; + else if((i_hcnt >= hbar8bgn) && (i_hcnt < hbar9bgn)) + Hregion <= HRGN8; + else + Hregion <= HRGN9; + end + default: begin + if((i_hcnt >= hbar1bgn) && (i_hcnt < hbar2bgn)) + Hregion <= HRGN1; + else if((i_hcnt >= hbar2bgn) && (i_hcnt < hbar3bgn)) + Hregion <= HRGN2; + else if((i_hcnt >= hbar3bgn) && (i_hcnt < hbar4bgn)) + Hregion <= HRGN3; + else if((i_hcnt >= hbar4bgn) && (i_hcnt < hbar5bgn)) + Hregion <= HRGN4; + else if((i_hcnt >= hbar5bgn) && (i_hcnt < hbar6bgn)) + Hregion <= HRGN5; + else if((i_hcnt >= hbar6bgn) && (i_hcnt < hbar7bgn)) + Hregion <= HRGN6; + else if((i_hcnt >= hbar7bgn) && (i_hcnt < hbar8bgn)) + Hregion <= HRGN7; + else if((i_hcnt >= hbar8bgn) && (i_hcnt < hbar9bgn)) + Hregion <= HRGN8; + else + Hregion <= HRGN9; + end + endcase +end + +always @ (posedge i_clk_74M) +begin + if(i_rst) begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end else + case (Vregion) + VRGN1: begin + case (Hregion) + HRGN1: begin + o_r <= Lvl_40; + o_g <= Lvl_40; + o_b <= Lvl_40; + end + HRGN2: begin + o_r <= Lvl_75; + o_g <= Lvl_75; + o_b <= Lvl_75; + end + HRGN3: begin + o_r <= Lvl_75; + o_g <= Lvl_75; + o_b <= Lvl_0; + end + HRGN4: begin + o_r <= Lvl_0 ; + o_g <= Lvl_75; + o_b <= Lvl_75; + end + HRGN5: begin + o_r <= Lvl_0 ; + o_g <= Lvl_75; + o_b <= Lvl_0; + end + HRGN6: begin + o_r <= Lvl_75; + o_g <= Lvl_0; + o_b <= Lvl_75; + end + HRGN7: begin + o_r <= Lvl_75; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + HRGN8: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_75; + end + HRGN9: begin + o_r <= Lvl_40; + o_g <= Lvl_40; + o_b <= Lvl_40; + end + default: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + endcase + end + + VRGN2: begin + case (Hregion) + HRGN1: begin //100% Cyan + o_r <= Lvl_0; + o_g <= Lvl_100; + o_b <= Lvl_100; + end + HRGN2: begin //I + o_r <= I_R; + o_g <= I_G; + o_b <= I_B; + end + HRGN3, HRGN4, HRGN5, HRGN6, HRGN7, HRGN8: begin //75% White + o_r <= Lvl_75; + o_g <= Lvl_75; + o_b <= Lvl_75; + end + HRGN9: begin //100% Blue + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_100; + end + default: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + endcase + end + + VRGN3: begin + case (Hregion) + HRGN1: begin //100% Yellow + o_r <= Lvl_100; + o_g <= Lvl_100; + o_b <= Lvl_0; + end + HRGN2: begin //Q + o_r <= Q_R; + o_g <= Q_G; + o_b <= Q_B; + end + HRGN3, HRGN4, HRGN5: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + HRGN6, HRGN7, HRGN8: begin //white ramp + o_r <= (o_r == Lvl_100) ? Lvl_100 : o_r + 8'h1; + o_g <= (o_g == Lvl_100) ? Lvl_100 : o_g + 8'h1; + o_b <= (o_b == Lvl_100) ? Lvl_100 : o_b + 8'h1; + end + HRGN9: begin //100% RED + o_r <= Lvl_100; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + default: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + endcase + end + + VRGN4: begin + case (Hregion) + HRGN1: begin + o_r <= Lvl_15; + o_g <= Lvl_15; + o_b <= Lvl_15; + end + HRGN10: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + HRGN11: begin + o_r <= Lvl_100; + o_g <= Lvl_100; + o_b <= Lvl_100; + end + HRGN12: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + HRGN13: begin + o_r <= Lvl_2n; + o_g <= Lvl_2n; + o_b <= Lvl_2n; + end + HRGN14: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + HRGN15: begin + o_r <= Lvl_2; + o_g <= Lvl_2; + o_b <= Lvl_2; + end + HRGN16: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + HRGN17: begin + o_r <= Lvl_4; + o_g <= Lvl_4; + o_b <= Lvl_4; + end + HRGN8: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + HRGN9: begin + o_r <= Lvl_15; + o_g <= Lvl_15; + o_b <= Lvl_15; + end + default: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + endcase + end + + default: begin + o_r <= Lvl_0; + o_g <= Lvl_0; + o_b <= Lvl_0; + end + endcase +end + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/synchro.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/synchro.v new file mode 100644 index 0000000..e654b14 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/synchro.v @@ -0,0 +1,93 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2006 Xilinx, Inc. +// This design is confidential and proprietary of Xilinx, All Rights Reserved. +////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor: Xilinx +// \ \ \/ Version: 1.0.0 +// \ \ Filename: synchro.v +// / / Date Created: December 25, 2006 +// /___/ /\ Last Modified: December 25, 2006 +// \ \ / \ +// \___\/\___\ +// +// Devices: Spartan-3 Generation FPGA +// Purpose: Signal synchronizer, for async inputs +// Contact: crabill@xilinx.com +// Reference: None +// +// Revision History: +// Rev 1.0.0 - (crabill) First created December 25, 2006. +// +////////////////////////////////////////////////////////////////////////////// +// +// LIMITED WARRANTY AND DISCLAIMER. These designs are provided to you "as is". +// Xilinx and its licensors make and you receive no warranties or conditions, +// express, implied, statutory or otherwise, and Xilinx specifically disclaims +// any implied warranties of merchantability, non-infringement, or fitness for +// a particular purpose. Xilinx does not warrant that the functions contained +// in these designs will meet your requirements, or that the operation of +// these designs will be uninterrupted or error free, or that defects in the +// designs will be corrected. Furthermore, Xilinx does not warrant or make any +// representations regarding use or the results of the use of the designs in +// terms of correctness, accuracy, reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its licensors be liable +// for any loss of data, lost profits, cost or procurement of substitute goods +// or services, or for any special, incidental, consequential, or indirect +// damages arising from the use or operation of the designs or accompanying +// documentation, however caused and on any theory of liability. This +// limitation will apply even if Xilinx has been advised of the possibility +// of such damage. This limitation shall apply not-withstanding the failure +// of the essential purpose of any limited remedies herein. +// +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2006 Xilinx, Inc. +// This design is confidential and proprietary of Xilinx, All Rights Reserved. +////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ns / 1 ps + +module synchro + #( + parameter INITIALIZE = "LOGIC0" + ) + + ( + input wire async, + input wire clk, + output wire sync + ); + + //******************************************************************// + // Synchronizer. // + //******************************************************************// + + wire temp; + + generate + if (INITIALIZE == "LOGIC1") + begin : use_fdp + FDP fda (.Q(temp),.D(async),.C(clk),.PRE(1'b0)); + FDP fdb (.Q(sync),.D(temp),.C(clk),.PRE(1'b0)); + end + else + begin : use_fdc + FDC fda (.Q(temp),.D(async),.C(clk),.CLR(1'b0)); + FDC fdb (.Q(sync),.D(temp),.C(clk),.CLR(1'b0)); + end + endgenerate + + // synthesis attribute ASYNC_REG of fda is "TRUE"; + // synthesis attribute ASYNC_REG of fdb is "TRUE"; + // synthesis attribute HU_SET of fda is "SYNC"; + // synthesis attribute HU_SET of fdb is "SYNC"; + // synthesis attribute RLOC of fda is "X0Y0"; + // synthesis attribute RLOC of fdb is "X0Y0"; + + //******************************************************************// + // // + //******************************************************************// + +endmodule
\ No newline at end of file diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/timing.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/timing.v new file mode 100644 index 0000000..60a4f69 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/common/timing.v @@ -0,0 +1,167 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2006 Xilinx, Inc. +// This design is confidential and proprietary of Xilinx, All Rights Reserved. +////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor: Xilinx +// \ \ \/ Version: 1.0.0 +// \ \ Filename: timing.v +// / / Date Created: December 25, 2006 +// /___/ /\ Last Modified: December 25, 2006 +// \ \ / \ +// \___\/\___\ +// +// Devices: Spartan-3 Generation FPGA +// Purpose: Programmable video timing generation circuit +// Contact: crabill@xilinx.com +// Reference: None +// +// Revision History: +// Rev 1.0.0 - (crabill) First created December 25, 2006. +// +////////////////////////////////////////////////////////////////////////////// +// +// LIMITED WARRANTY AND DISCLAIMER. These designs are provided to you "as is". +// Xilinx and its licensors make and you receive no warranties or conditions, +// express, implied, statutory or otherwise, and Xilinx specifically disclaims +// any implied warranties of merchantability, non-infringement, or fitness for +// a particular purpose. Xilinx does not warrant that the functions contained +// in these designs will meet your requirements, or that the operation of +// these designs will be uninterrupted or error free, or that defects in the +// designs will be corrected. Furthermore, Xilinx does not warrant or make any +// representations regarding use or the results of the use of the designs in +// terms of correctness, accuracy, reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its licensors be liable +// for any loss of data, lost profits, cost or procurement of substitute goods +// or services, or for any special, incidental, consequential, or indirect +// damages arising from the use or operation of the designs or accompanying +// documentation, however caused and on any theory of liability. This +// limitation will apply even if Xilinx has been advised of the possibility +// of such damage. This limitation shall apply not-withstanding the failure +// of the essential purpose of any limited remedies herein. +// +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2006 Xilinx, Inc. +// This design is confidential and proprietary of Xilinx, All Rights Reserved. +////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ns / 1 ps + +module timing + ( + input wire [10:0] tc_hsblnk, + input wire [10:0] tc_hssync, + input wire [10:0] tc_hesync, + input wire [10:0] tc_heblnk, + + output wire [10:0] hcount, + output wire hsync, + output wire hblnk, + + input wire [10:0] tc_vsblnk, + input wire [10:0] tc_vssync, + input wire [10:0] tc_vesync, + input wire [10:0] tc_veblnk, + + output wire [10:0] vcount, + output wire vsync, + output wire vblnk, + + input wire restart, + input wire clk + ); + + //******************************************************************// + // This logic describes a 11-bit horizontal position counter. // + //******************************************************************// + + reg [10:0] hpos_cnt = 0; + wire hpos_clr; + wire hpos_ena; + + always @(posedge clk) + begin : hcounter + if (hpos_clr) hpos_cnt <= 11'b000_0000_0000; + else if (hpos_ena) hpos_cnt <= hpos_cnt + 11'b000_0000_0001; + end + + //******************************************************************// + // This logic describes a 11-bit vertical position counter. // + //******************************************************************// + + reg [10:0] vpos_cnt = 0; + wire vpos_clr; + wire vpos_ena; + + always @(posedge clk) + begin : vcounter + if (vpos_clr) vpos_cnt <= 11'b000_0000_0000; + else if (vpos_ena) vpos_cnt <= vpos_cnt + 11'b000_0000_0001; + end + + //******************************************************************// + // This logic describes the position counter control. Counters are // + // reset when they reach the total count and the counter is then // + // enabled to advance. Use of GTE operator ensures dynamic changes // + // to display timing parameters do not allow counters to run away. // + //******************************************************************// + + assign hpos_ena = 1'b1; + assign hpos_clr = ((hpos_cnt >= tc_heblnk) && hpos_ena ) || restart; + + assign vpos_ena = hpos_clr; + assign vpos_clr = ((vpos_cnt >= tc_veblnk) && vpos_ena ) || restart; + + //******************************************************************// + // This is the logic for the horizontal outputs. Active video is // + // always started when the horizontal count is zero. Example: // + // // + // tc_hsblnk = 03 // + // tc_hssync = 07 // + // tc_hesync = 11 // + // tc_heblnk = 15 (htotal) // + // // + // hcount 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 // + // hsync ________________________------------____________ // + // hblnk ____________------------------------------------ // + // // + // hsync time = (tc_hesync - tc_hssync) pixels // + // hblnk time = (tc_heblnk - tc_hsblnk) pixels // + // active time = (tc_hsblnk + 1) pixels // + // // + //******************************************************************// + + assign hcount = hpos_cnt; + assign hblnk = (hcount > tc_hsblnk); + assign hsync = (hcount > tc_hssync) && (hcount <= tc_hesync); + + //******************************************************************// + // This is the logic for the vertical outputs. Active video is // + // always started when the vertical count is zero. Example: // + // // + // tc_vsblnk = 03 // + // tc_vssync = 07 // + // tc_vesync = 11 // + // tc_veblnk = 15 (vtotal) // + // // + // vcount 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 // + // vsync ________________________------------____________ // + // vblnk ____________------------------------------------ // + // // + // vsync time = (tc_vesync - tc_vssync) lines // + // vblnk time = (tc_veblnk - tc_vsblnk) lines // + // active time = (tc_vsblnk + 1) lines // + // // + //******************************************************************// + + assign vcount = vpos_cnt; + assign vblnk = (vcount > tc_vsblnk); + assign vsync = (vcount > tc_vssync) && (vcount <= tc_vesync); + + //******************************************************************// + // // + //******************************************************************// + +endmodule
\ No newline at end of file diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/dvi_demo.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/dvi_demo.v new file mode 100644 index 0000000..5659c09 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/dvi_demo.v @@ -0,0 +1,511 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2010 Xilinx, Inc. +// This design is confidential and proprietary of Xilinx, All Rights Reserved. +////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor: Xilinx +// \ \ \/ Version: 1.0.0 +// \ \ Filename: dvi_demo.v +// / / Date Created: Feb. 2010 +// /___/ /\ Last Modified: Feb. 2010 +// \ \ / \ +// \___\/\___\ +// +// Devices: Spartan-6 FPGA +// Purpose: DVI Pass Through Top Module Based On XLAB Atlys Board +// Contact: +// Reference: None +// +// Revision History: +// Rev 1.0.0 - (Bob Feng) First created Feb. 2010 +// +////////////////////////////////////////////////////////////////////////////// +// +// LIMITED WARRANTY AND DISCLAIMER. These designs are provided to you "as is". +// Xilinx and its licensors make and you receive no warranties or conditions, +// express, implied, statutory or otherwise, and Xilinx specifically disclaims +// any implied warranties of merchantability, non-infringement, or fitness for +// a particular purpose. Xilinx does not warrant that the functions contained +// in these designs will meet your requirements, or that the operation of +// these designs will be uninterrupted or error free, or that defects in the +// designs will be corrected. Furthermore, Xilinx does not warrant or make any +// representations regarding use or the results of the use of the designs in +// terms of correctness, accuracy, reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its licensors be liable +// for any loss of data, lost profits, cost or procurement of substitute goods +// or services, or for any special, incidental, consequential, or indirect +// damages arising from the use or operation of the designs or accompanying +// documentation, however caused and on any theory of liability. This +// limitation will apply even if Xilinx has been advised of the possibility +// of such damage. This limitation shall apply not-withstanding the failure +// of the essential purpose of any limited remedies herein. +// +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2010 Xilinx, Inc. +// This design is confidential and proprietary of Xilinx, All Rights Reserved. +////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ns / 1 ps + +//`define DIRECTPASS + +module dvi_demo ( + input wire rstbtn_n, //The pink reset button + input wire clk100, //100 MHz osicallator + input wire [3:0] RX0_TMDS, + input wire [3:0] RX0_TMDSB, + input wire [3:0] RX1_TMDS, + input wire [3:0] RX1_TMDSB, + + output wire [3:0] TX0_TMDS, + output wire [3:0] TX0_TMDSB, + output wire [3:0] TX1_TMDS, + output wire [3:0] TX1_TMDSB, + + input wire [1:0] SW, + + output wire [7:0] LED +); + + //////////////////////////////////////////////////// + // 25 MHz and switch debouncers + //////////////////////////////////////////////////// + wire clk25, clk25m; + + BUFIO2 #(.DIVIDE_BYPASS("FALSE"), .DIVIDE(5)) + sysclk_div (.DIVCLK(clk25m), .IOCLK(), .SERDESSTROBE(), .I(clk100)); + + BUFG clk25_buf (.I(clk25m), .O(clk25)); + + wire [1:0] sws; + + synchro #(.INITIALIZE("LOGIC0")) + synchro_sws_0 (.async(SW[0]),.sync(sws[0]),.clk(clk25)); + + synchro #(.INITIALIZE("LOGIC0")) + synchro_sws_1 (.async(SW[1]),.sync(sws[1]),.clk(clk25)); + + wire [1:0] select = sws; + + reg [1:0] select_q = 2'b00; + reg [1:0] switch = 2'b00; + always @ (posedge clk25) begin + select_q <= select; + + switch[0] = select[0] ^ select_q[0]; + switch[1] = select[1] ^ select_q[1]; + end + + ///////////////////////// + // + // Input Port 0 + // + ///////////////////////// + wire rx0_pclk, rx0_pclkx2, rx0_pclkx10, rx0_pllclk0; + wire rx0_plllckd; + wire rx0_reset; + wire rx0_serdesstrobe; + wire rx0_hsync; // hsync data + wire rx0_vsync; // vsync data + wire rx0_de; // data enable + wire rx0_psalgnerr; // channel phase alignment error + wire [7:0] rx0_red; // pixel data out + wire [7:0] rx0_green; // pixel data out + wire [7:0] rx0_blue; // pixel data out + wire [29:0] rx0_sdata; + wire rx0_blue_vld; + wire rx0_green_vld; + wire rx0_red_vld; + wire rx0_blue_rdy; + wire rx0_green_rdy; + wire rx0_red_rdy; + + dvi_decoder dvi_rx0 ( + //These are input ports + .tmdsclk_p (RX0_TMDS[3]), + .tmdsclk_n (RX0_TMDSB[3]), + .blue_p (RX0_TMDS[0]), + .green_p (RX0_TMDS[1]), + .red_p (RX0_TMDS[2]), + .blue_n (RX0_TMDSB[0]), + .green_n (RX0_TMDSB[1]), + .red_n (RX0_TMDSB[2]), + .exrst (~rstbtn_n), + + //These are output ports + .reset (rx0_reset), + .pclk (rx0_pclk), + .pclkx2 (rx0_pclkx2), + .pclkx10 (rx0_pclkx10), + .pllclk0 (rx0_pllclk0), // PLL x10 output + .pllclk1 (rx0_pllclk1), // PLL x1 output + .pllclk2 (rx0_pllclk2), // PLL x2 output + .pll_lckd (rx0_plllckd), + .tmdsclk (rx0_tmdsclk), + .serdesstrobe(rx0_serdesstrobe), + .hsync (rx0_hsync), + .vsync (rx0_vsync), + .de (rx0_de), + + .blue_vld (rx0_blue_vld), + .green_vld (rx0_green_vld), + .red_vld (rx0_red_vld), + .blue_rdy (rx0_blue_rdy), + .green_rdy (rx0_green_rdy), + .red_rdy (rx0_red_rdy), + + .psalgnerr (rx0_psalgnerr), + + .sdout (rx0_sdata), + .red (rx0_red), + .green (rx0_green), + .blue (rx0_blue)); + + ///////////////////////// + // + // Input Port 1 + // + ///////////////////////// + wire rx1_pclk, rx1_pclkx2, rx1_pclkx10, rx1_pllclk0; + wire rx1_plllckd; + wire rx1_reset; + wire rx1_serdesstrobe; + wire rx1_hsync; // hsync data + wire rx1_vsync; // vsync data + wire rx1_de; // data enable + wire rx1_psalgnerr; // channel phase alignment error + wire [7:0] rx1_red; // pixel data out + wire [7:0] rx1_green; // pixel data out + wire [7:0] rx1_blue; // pixel data out + wire [29:0] rx1_sdata; + wire rx1_blue_vld; + wire rx1_green_vld; + wire rx1_red_vld; + wire rx1_blue_rdy; + wire rx1_green_rdy; + wire rx1_red_rdy; + + dvi_decoder dvi_rx1 ( + //These are input ports + .tmdsclk_p (RX1_TMDS[3]), + .tmdsclk_n (RX1_TMDSB[3]), + .blue_p (RX1_TMDS[0]), + .green_p (RX1_TMDS[1]), + .red_p (RX1_TMDS[2]), + .blue_n (RX1_TMDSB[0]), + .green_n (RX1_TMDSB[1]), + .red_n (RX1_TMDSB[2]), + .exrst (~rstbtn_n), + + //These are output ports + .reset (rx1_reset), + .pclk (rx1_pclk), + .pclkx2 (rx1_pclkx2), + .pclkx10 (rx1_pclkx10), + .pllclk0 (rx1_pllclk0), // PLL x10 outptu + .pllclk1 (rx1_pllclk1), // PLL x1 output + .pllclk2 (rx1_pllclk2), // PLL x2 output + .pll_lckd (rx1_plllckd), + .tmdsclk (rx1_tmdsclk), + .serdesstrobe(rx1_serdesstrobe), + .hsync (rx1_hsync), + .vsync (rx1_vsync), + .de (rx1_de), + + .blue_vld (rx1_blue_vld), + .green_vld (rx1_green_vld), + .red_vld (rx1_red_vld), + .blue_rdy (rx1_blue_rdy), + .green_rdy (rx1_green_rdy), + .red_rdy (rx1_red_rdy), + + .psalgnerr (rx1_psalgnerr), + + .sdout (rx1_sdata), + .red (rx1_red), + .green (rx1_green), + .blue (rx1_blue)); + + // TMDS output +`ifdef DIRECTPASS + wire rstin = rx0_reset; + wire pclk = rx0_pclk; + wire pclkx2 = rx0_pclkx2; + wire pclkx10 = rx0_pclkx10; + wire serdesstrobe = rx0_serdesstrobe; + wire [29:0] s_data = rx0_sdata; + + // + // Forward TMDS Clock Using OSERDES2 block + // + reg [4:0] tmdsclkint = 5'b00000; + reg toggle = 1'b0; + + always @ (posedge pclkx2 or posedge rstin) begin + if (rstin) + toggle <= 1'b0; + else + toggle <= ~toggle; + end + + always @ (posedge pclkx2) begin + if (toggle) + tmdsclkint <= 5'b11111; + else + tmdsclkint <= 5'b00000; + end + + wire tmdsclk; + + serdes_n_to_1 #( + .SF (5)) + clkout ( + .iob_data_out (tmdsclk), + .ioclk (pclkx10), + .serdesstrobe (serdesstrobe), + .gclk (pclkx2), + .reset (rstin), + .datain (tmdsclkint)); + + OBUFDS TMDS3 (.I(tmdsclk), .O(TX0_TMDS[3]), .OB(TX0_TMDSB[3])) ;// clock + + wire [4:0] tmds_data0, tmds_data1, tmds_data2; + wire [2:0] tmdsint; + + // + // Forward TMDS Data: 3 channels + // + serdes_n_to_1 #(.SF(5)) oserdes0 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(rstin), + .gclk(pclkx2), + .datain(tmds_data0), + .iob_data_out(tmdsint[0])) ; + + serdes_n_to_1 #(.SF(5)) oserdes1 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(rstin), + .gclk(pclkx2), + .datain(tmds_data1), + .iob_data_out(tmdsint[1])) ; + + serdes_n_to_1 #(.SF(5)) oserdes2 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(rstin), + .gclk(pclkx2), + .datain(tmds_data2), + .iob_data_out(tmdsint[2])) ; + + OBUFDS TMDS0 (.I(tmdsint[0]), .O(TX0_TMDS[0]), .OB(TX0_TMDSB[0])) ; + OBUFDS TMDS1 (.I(tmdsint[1]), .O(TX0_TMDS[1]), .OB(TX0_TMDSB[1])) ; + OBUFDS TMDS2 (.I(tmdsint[2]), .O(TX0_TMDS[2]), .OB(TX0_TMDSB[2])) ; + + convert_30to15_fifo pixel2x ( + .rst (rstin), + .clk (pclk), + .clkx2 (pclkx2), + .datain (s_data), + .dataout ({tmds_data2, tmds_data1, tmds_data0})); + +`else + ///////////////// + // + // Output Port 0 + // + ///////////////// + wire tx0_de; + wire tx0_pclk; + wire tx0_pclkx2; + wire tx0_pclkx10; + wire tx0_serdesstrobe; + wire tx0_reset; + wire [7:0] tx0_blue; + wire [7:0] tx0_green; + wire [7:0] tx0_red; + wire tx0_hsync; + wire tx0_vsync; + wire tx0_pll_reset; + + assign tx0_de = (select[0]) ? rx1_de : rx0_de; + assign tx0_blue = (select[0]) ? rx1_blue : rx0_blue; + assign tx0_green = (select[0]) ? rx1_green : rx0_green; + assign tx0_red = (select[0]) ? rx1_red : rx0_red; + assign tx0_hsync = (select[0]) ? rx1_hsync : rx0_hsync; + assign tx0_vsync = (select[0]) ? rx1_vsync : rx0_vsync; + assign tx0_pll_reset = switch[0] | ((select[0]) ? rx1_reset : rx0_reset); + + ////////////////////////////////////////////////////////////////// + // Instantiate a dedicate PLL for output port + ////////////////////////////////////////////////////////////////// + wire tx0_clkfbout, tx0_clkfbin, tx0_plllckd; + wire tx0_pllclk0, tx0_pllclk2; + + PLL_BASE # ( + .CLKIN_PERIOD(10), + .CLKFBOUT_MULT(10), //set VCO to 10x of CLKIN + .CLKOUT0_DIVIDE(1), + .CLKOUT1_DIVIDE(10), + .CLKOUT2_DIVIDE(5), + .COMPENSATION("SOURCE_SYNCHRONOUS") + ) PLL_OSERDES_0 ( + .CLKFBOUT(tx0_clkfbout), + .CLKOUT0(tx0_pllclk0), + .CLKOUT1(), + .CLKOUT2(tx0_pllclk2), + .CLKOUT3(), + .CLKOUT4(), + .CLKOUT5(), + .LOCKED(tx0_plllckd), + .CLKFBIN(tx0_clkfbin), + .CLKIN(tx0_pclk), + .RST(tx0_pll_reset) + ); + + // + // This BUFGMUX directly selects between two RX PLL pclk outputs + // This way we have a matched skew between the RX pclk clocks and the TX pclk + // + BUFGMUX tx0_bufg_pclk (.S(select[0]), .I1(rx1_pllclk1), .I0(rx0_pllclk1), .O(tx0_pclk)); + + // + // This BUFG is needed in order to deskew between PLL clkin and clkout + // So the tx0 pclkx2 and pclkx10 will have the same phase as the pclk input + // + BUFG tx0_clkfb_buf (.I(tx0_clkfbout), .O(tx0_clkfbin)); + + // + // regenerate pclkx2 for TX + // + BUFG tx0_pclkx2_buf (.I(tx0_pllclk2), .O(tx0_pclkx2)); + + // + // regenerate pclkx10 for TX + // + wire tx0_bufpll_lock; + BUFPLL #(.DIVIDE(5)) tx0_ioclk_buf (.PLLIN(tx0_pllclk0), .GCLK(tx0_pclkx2), .LOCKED(tx0_plllckd), + .IOCLK(tx0_pclkx10), .SERDESSTROBE(tx0_serdesstrobe), .LOCK(tx0_bufpll_lock)); + + assign tx0_reset = ~tx0_bufpll_lock; + + dvi_encoder_top dvi_tx0 ( + .pclk (tx0_pclk), + .pclkx2 (tx0_pclkx2), + .pclkx10 (tx0_pclkx10), + .serdesstrobe(tx0_serdesstrobe), + .rstin (tx0_reset), + .blue_din (tx0_blue), + .green_din (tx0_green), + .red_din (tx0_red), + .hsync (tx0_hsync), + .vsync (tx0_vsync), + .de (tx0_de), + .TMDS (TX0_TMDS), + .TMDSB (TX0_TMDSB)); + + ///////////////// + // + // Output Port 1 + // + ///////////////// + wire tx1_de; + wire tx1_pclk; + wire tx1_pclkx2; + wire tx1_pclkx10; + wire tx1_serdesstrobe; + wire tx1_reset; + wire [7:0] tx1_blue; + wire [7:0] tx1_green; + wire [7:0] tx1_red; + wire tx1_hsync; + wire tx1_vsync; + wire tx1_pll_reset; + + assign tx1_de = (select[1]) ? rx1_de : rx0_de; + assign tx1_blue = (select[1]) ? rx1_blue : rx0_blue; + assign tx1_green = (select[1]) ? rx1_green : rx0_green; + assign tx1_red = (select[1]) ? rx1_red : rx0_red; + assign tx1_hsync = (select[1]) ? rx1_hsync : rx0_hsync; + assign tx1_vsync = (select[1]) ? rx1_vsync : rx0_vsync; + assign tx1_pll_reset = switch[1] | ((select[1]) ? rx1_reset : rx0_reset); + + ////////////////////////////////////////////////////////////////// + // Instantiate a dedicate PLL for output port + ////////////////////////////////////////////////////////////////// + wire tx1_clkfbout, tx1_clkfbin, tx1_plllckd; + wire tx1_pllclk0, tx1_pllclk2; + + PLL_BASE # ( + .CLKIN_PERIOD(10), + .CLKFBOUT_MULT(10), //set VCO to 10x of CLKIN + .CLKOUT0_DIVIDE(1), + .CLKOUT1_DIVIDE(10), + .CLKOUT2_DIVIDE(5), + .COMPENSATION("SOURCE_SYNCHRONOUS") + ) PLL_OSERDES_1 ( + .CLKFBOUT(tx1_clkfbout), + .CLKOUT0(tx1_pllclk0), + .CLKOUT1(), + .CLKOUT2(tx1_pllclk2), + .CLKOUT3(), + .CLKOUT4(), + .CLKOUT5(), + .LOCKED(tx1_plllckd), + .CLKFBIN(tx1_clkfbin), + .CLKIN(tx1_pclk), + .RST(tx1_pll_reset) + ); + + // + // This BUFGMUX selects between two RX PLL pclk outputs + // This way we have a matched skew between the RX pclk clocks and the TX pclk + // + BUFGMUX tx1_bufg_pclk (.S(select[1]), .I1(rx1_pllclk1), .I0(rx0_pllclk1), .O(tx1_pclk)); + + // + // This BUFG is needed in order to deskew between PLL clkin and clkout + // So the tx1 pclkx2 and pclkx10 will have the same phase as the pclk input + // + BUFG tx1_clkfb_buf (.I(tx1_clkfbout), .O(tx1_clkfbin)); + + // + // regenerate pclkx2 for TX + // + BUFG tx1_pclkx2_buf (.I(tx1_pllclk2), .O(tx1_pclkx2)); + + // + // regenerate pclkx10 for TX + // + wire tx1_bufpll_lock; + BUFPLL #(.DIVIDE(5)) tx1_ioclk_buf (.PLLIN(tx1_pllclk0), .GCLK(tx1_pclkx2), .LOCKED(tx1_plllckd), + .IOCLK(tx1_pclkx10), .SERDESSTROBE(tx1_serdesstrobe), .LOCK(tx1_bufpll_lock)); + + assign tx1_reset = ~tx1_bufpll_lock; + + dvi_encoder_top dvi_tx1 ( + .pclk (tx1_pclk), + .pclkx2 (tx1_pclkx2), + .pclkx10 (tx1_pclkx10), + .serdesstrobe(tx1_serdesstrobe), + .rstin (tx1_reset), + .blue_din (tx1_blue), + .green_din (tx1_green), + .red_din (tx1_red), + .hsync (tx1_hsync), + .vsync (tx1_vsync), + .de (tx1_de), + .TMDS (TX1_TMDS), + .TMDSB (TX1_TMDSB)); +`endif + + ////////////////////////////////////// + // Status LED + ////////////////////////////////////// + assign LED = {rx0_red_rdy, rx0_green_rdy, rx0_blue_rdy, rx1_red_rdy, rx1_green_rdy, rx1_blue_rdy, + rx0_de, rx1_de}; + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/chnlbond.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/chnlbond.v new file mode 100644 index 0000000..c497d86 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/chnlbond.v @@ -0,0 +1,170 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Xilinx, Inc. 2007 www.xilinx.com +// +// XAPP xxx +// +////////////////////////////////////////////////////////////////////////////// +// +// File name : chnlbond.v +// +// Description : Channel Bonding Logic +// TMDS channel de-skew +// +// Author : Bob Feng +// +// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are +// provided to you "as is". Xilinx and its licensors makeand you +// receive no warranties or conditions, express, implied, +// statutory or otherwise, and Xilinx specificallydisclaims any +// implied warranties of merchantability, non-infringement,or +// fitness for a particular purpose. Xilinx does notwarrant that +// the functions contained in these designs will meet your +// requirements, or that the operation of these designswill be +// uninterrupted or error free, or that defects in theDesigns +// will be corrected. Furthermore, Xilinx does not warrantor +// make any representations regarding use or the results ofthe +// use of the designs in terms of correctness, accuracy, +// reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its +// licensors be liable for any loss of data, lost profits,cost +// or procurement of substitute goods or services, or forany +// special, incidental, consequential, or indirect damages +// arising from the use or operation of the designs or +// accompanying documentation, however caused and on anytheory +// of liability. This limitation will apply even if Xilinx +// has been advised of the possibility of such damage. This +// limitation shall apply not-withstanding the failure ofthe +// essential purpose of any limited remedies herein. +// +// Copyright © 2004 Xilinx, Inc. +// All rights reserved +// +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ns / 1ps + +module chnlbond ( + input wire clk, + input wire [9:0] rawdata, + input wire iamvld, + input wire other_ch0_vld, + input wire other_ch1_vld, + input wire other_ch0_rdy, + input wire other_ch1_rdy, + output reg iamrdy, + output reg [9:0] sdata +); + + parameter CTRLTOKEN0 = 10'b1101010100; + parameter CTRLTOKEN1 = 10'b0010101011; + parameter CTRLTOKEN2 = 10'b0101010100; + parameter CTRLTOKEN3 = 10'b1010101011; + + wire rawdata_vld; + assign rawdata_vld = other_ch0_vld & other_ch1_vld & iamvld; + + reg [3:0] wa, ra; + reg we; + + //////////////////////////////////////////////////////// + // FIFO Write Control Logic + //////////////////////////////////////////////////////// + always @ (posedge clk) begin + we <=#1 rawdata_vld; + end + + always @ (posedge clk) begin + if(rawdata_vld) + wa <=#1 wa + 1'b1; + else + wa <=#1 4'h0; + end + + wire [9:0] dpfo_dout; + DRAM16XN #(.data_width(10)) + cbfifo_i ( + .DATA_IN(rawdata), + .ADDRESS(wa), + .ADDRESS_DP(ra), + .WRITE_EN(we), + .CLK(clk), + .O_DATA_OUT(), + .O_DATA_OUT_DP(dpfo_dout)); + + always @ (posedge clk) begin + sdata <=#1 dpfo_dout; + end + + //////////////////////////////////////////////////////// + // FIFO read Control Logic + //////////////////////////////////////////////////////// + + //////////////////////////////// + // Use blank period beginning + // as a speical marker to + // align all channel together + //////////////////////////////// + reg rcvd_ctkn, rcvd_ctkn_q; //received control token + reg blnkbgn; //blank period begins + always @ (posedge clk) begin + rcvd_ctkn <=#1 ((sdata == CTRLTOKEN0) || (sdata == CTRLTOKEN1) || (sdata == CTRLTOKEN2) || (sdata == CTRLTOKEN3)); + rcvd_ctkn_q <=#1 rcvd_ctkn; + blnkbgn <=#1 !rcvd_ctkn_q & rcvd_ctkn; + end + + ///////////////////////////// + //skip the current line + ///////////////////////////// + wire next_blnkbgn; + reg skip_line; + always @ (posedge clk) begin + if(!rawdata_vld) + skip_line <=#1 1'b0; + else if(blnkbgn) + skip_line <=#1 1'b1; + end + + assign next_blnkbgn = skip_line & blnkbgn; + + ////////////////////////////// + //Declare my own readiness + ////////////////////////////// + always @ (posedge clk) begin + if(!rawdata_vld) + iamrdy <=#1 1'b0; + else if(next_blnkbgn) + iamrdy <=#1 1'b1; + end + + reg rawdata_vld_q; + reg rawdata_vld_rising; + always @ (posedge clk) begin + rawdata_vld_q <=#1 rawdata_vld; + rawdata_vld_rising <=#1 rawdata_vld & !rawdata_vld_q; + end + + ////////////////////////////////////////////////////////////////////////////////////////// + // 1. FIFO flow through first when all channels are found valid(phase aligned) + // 2. When the speical marker on my channel is found, the fifo read is hold + // 3. Until the same markers are found across all three channels, the fifo read resumes + ////////////////////////////////////////////////////////////////////////////////////////// + reg ra_en = 1'b0; + always @ (posedge clk) begin + if(rawdata_vld_rising || (other_ch0_rdy & other_ch1_rdy & iamrdy)) + ra_en <=#1 1'b1; + else if(next_blnkbgn && !(other_ch0_rdy & other_ch1_rdy & iamrdy)) + ra_en <=#1 1'b0; + end + + ///////////////////////////////////////// + //FIFO Read Address Counter + ///////////////////////////////////////// + always @ (posedge clk) begin + if(!rawdata_vld) + ra <=#1 4'h0; + else if(ra_en) + ra <=#1 ra + 1'b1; + end + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/decode.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/decode.v new file mode 100644 index 0000000..3b95485 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/decode.v @@ -0,0 +1,237 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Xilinx, Inc. 2010 www.xilinx.com +// +// XAPP xxx +// +////////////////////////////////////////////////////////////////////////////// +// +// File name : decoder.v +// +// Description : Spartan-6 dvi decoder +// +// +// Author : Bob Feng +// +// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are +// provided to you "as is". Xilinx and its licensors makeand you +// receive no warranties or conditions, express, implied, +// statutory or otherwise, and Xilinx specificallydisclaims any +// implied warranties of merchantability, non-infringement,or +// fitness for a particular purpose. Xilinx does notwarrant that +// the functions contained in these designs will meet your +// requirements, or that the operation of these designswill be +// uninterrupted or error free, or that defects in theDesigns +// will be corrected. Furthermore, Xilinx does not warrantor +// make any representations regarding use or the results ofthe +// use of the designs in terms of correctness, accuracy, +// reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its +// licensors be liable for any loss of data, lost profits,cost +// or procurement of substitute goods or services, or forany +// special, incidental, consequential, or indirect damages +// arising from the use or operation of the designs or +// accompanying documentation, however caused and on anytheory +// of liability. This limitation will apply even if Xilinx +// has been advised of the possibility of such damage. This +// limitation shall apply not-withstanding the failure ofthe +// essential purpose of any limited remedies herein. +// +// Copyright © 2004 Xilinx, Inc. +// All rights reserved +// +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ns / 1ps + +module decode ( + input wire reset, // + input wire pclk, // pixel clock + input wire pclkx2, // double pixel rate for gear box + input wire pclkx10, // IOCLK + input wire serdesstrobe, // serdesstrobe for iserdes2 + input wire din_p, // data from dvi cable + input wire din_n, // data from dvi cable + input wire other_ch0_vld, // other channel0 has valid data now + input wire other_ch1_vld, // other channel1 has valid data now + input wire other_ch0_rdy, // other channel0 has detected a valid starting pixel + input wire other_ch1_rdy, // other channel1 has detected a valid starting pixel + + output wire iamvld, // I have valid data now + output wire iamrdy, // I have detected a valid new pixel + output wire psalgnerr, // Phase alignment error + output reg c0, + output reg c1, + output reg de, + output reg [9:0] sdout, + output reg [7:0] dout); + + //////////////////////////////// + // + // 5-bit to 10-bit gear box + // + //////////////////////////////// + wire flipgear; + reg flipgearx2; + + always @ (posedge pclkx2) begin + flipgearx2 <=#1 flipgear; + end + + reg toggle = 1'b0; + + always @ (posedge pclkx2 or posedge reset) + if (reset == 1'b1) begin + toggle <= 1'b0 ; + end else begin + toggle <=#1 ~toggle; + end + + wire rx_toggle; + + assign rx_toggle = toggle ^ flipgearx2; //reverse hi-lo position + + wire [4:0] raw5bit; + reg [4:0] raw5bit_q; + reg [9:0] rawword; + + always @ (posedge pclkx2) begin + raw5bit_q <=#1 raw5bit; + + if(rx_toggle) //gear from 5 bit to 10 bit + rawword <=#1 {raw5bit, raw5bit_q}; + end + + //////////////////////////////// + // + // bitslip signal sync to pclkx2 + // + //////////////////////////////// + reg bitslipx2 = 1'b0; + reg bitslip_q = 1'b0; + wire bitslip; + + always @ (posedge pclkx2) begin + bitslip_q <=#1 bitslip; + bitslipx2 <=#1 bitslip & !bitslip_q; + end + + ///////////////////////////////////////////// + // + // 1:5 de-serializer working at x2 pclk rate + // + ///////////////////////////////////////////// + serdes_1_to_5_diff_data # ( + .DIFF_TERM("FALSE"), + .BITSLIP_ENABLE("TRUE") + ) des_0 ( + .use_phase_detector(1'b1), + .datain_p(din_p), + .datain_n(din_n), + .rxioclk(pclkx10), + .rxserdesstrobe(serdesstrobe), + .reset(reset), + .gclk(pclkx2), + .bitslip(bitslipx2), + .data_out(raw5bit) + ); + + ///////////////////////////////////////////////////// + // Doing word boundary detection here + ///////////////////////////////////////////////////// + wire [9:0] rawdata = rawword; + + /////////////////////////////////////// + // Phase Alignment Instance + /////////////////////////////////////// + phsaligner phsalgn_0 ( + .rst(reset), + .clk(pclk), + .sdata(rawdata), + .bitslip(bitslip), + .flipgear(flipgear), + .psaligned(iamvld) + ); + + assign psalgnerr = 1'b0; + + /////////////////////////////////////// + // Per Channel De-skew Instance + /////////////////////////////////////// + wire [9:0] sdata; + chnlbond cbnd ( + .clk(pclk), + .rawdata(rawdata), + .iamvld(iamvld), + .other_ch0_vld(other_ch0_vld), + .other_ch1_vld(other_ch1_vld), + .other_ch0_rdy(other_ch0_rdy), + .other_ch1_rdy(other_ch1_rdy), + .iamrdy(iamrdy), + .sdata(sdata) + ); + + ///////////////////////////////////////////////////////////////// + // Below performs the 10B-8B decoding function defined in DVI 1.0 + // Specification: Section 3.3.3, Figure 3-6, page 31. + ///////////////////////////////////////////////////////////////// + // Distinct Control Tokens + parameter CTRLTOKEN0 = 10'b1101010100; + parameter CTRLTOKEN1 = 10'b0010101011; + parameter CTRLTOKEN2 = 10'b0101010100; + parameter CTRLTOKEN3 = 10'b1010101011; + + wire [7:0] data; + assign data = (sdata[9]) ? ~sdata[7:0] : sdata[7:0]; + + always @ (posedge pclk) begin + if(iamrdy && other_ch0_rdy && other_ch1_rdy) begin + case (sdata) + CTRLTOKEN0: begin + c0 <=#1 1'b0; + c1 <=#1 1'b0; + de <=#1 1'b0; + end + + CTRLTOKEN1: begin + c0 <=#1 1'b1; + c1 <=#1 1'b0; + de <=#1 1'b0; + end + + CTRLTOKEN2: begin + c0 <=#1 1'b0; + c1 <=#1 1'b1; + de <=#1 1'b0; + end + + CTRLTOKEN3: begin + c0 <=#1 1'b1; + c1 <=#1 1'b1; + de <=#1 1'b0; + end + + default: begin + dout[0] <=#1 data[0]; + dout[1] <=#1 (sdata[8]) ? (data[1] ^ data[0]) : (data[1] ~^ data[0]); + dout[2] <=#1 (sdata[8]) ? (data[2] ^ data[1]) : (data[2] ~^ data[1]); + dout[3] <=#1 (sdata[8]) ? (data[3] ^ data[2]) : (data[3] ~^ data[2]); + dout[4] <=#1 (sdata[8]) ? (data[4] ^ data[3]) : (data[4] ~^ data[3]); + dout[5] <=#1 (sdata[8]) ? (data[5] ^ data[4]) : (data[5] ~^ data[4]); + dout[6] <=#1 (sdata[8]) ? (data[6] ^ data[5]) : (data[6] ~^ data[5]); + dout[7] <=#1 (sdata[8]) ? (data[7] ^ data[6]) : (data[7] ~^ data[6]); + + de <=#1 1'b1; + end + endcase + + sdout <=#1 sdata; + end else begin + c0 <= 1'b0; + c1 <= 1'b0; + de <= 1'b0; + dout <= 8'h0; + sdout <= 10'h0; + end + end +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/dvi_decoder.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/dvi_decoder.v new file mode 100644 index 0000000..038124d --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/dvi_decoder.v @@ -0,0 +1,242 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Xilinx, Inc. 2010 www.xilinx.com +// +// XAPPxxx +// +////////////////////////////////////////////////////////////////////////////// +// +// File name : dvi_decoder.v +// +// Description : Spartan-6 DVI decoder top module +// +// +// Author : Bob Feng +// +// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are +// provided to you "as is". Xilinx and its licensors makeand you +// receive no warranties or conditions, express, implied, +// statutory or otherwise, and Xilinx specificallydisclaims any +// implied warranties of merchantability, non-infringement,or +// fitness for a particular purpose. Xilinx does notwarrant that +// the functions contained in these designs will meet your +// requirements, or that the operation of these designswill be +// uninterrupted or error free, or that defects in theDesigns +// will be corrected. Furthermore, Xilinx does not warrantor +// make any representations regarding use or the results ofthe +// use of the designs in terms of correctness, accuracy, +// reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its +// licensors be liable for any loss of data, lost profits,cost +// or procurement of substitute goods or services, or forany +// special, incidental, consequential, or indirect damages +// arising from the use or operation of the designs or +// accompanying documentation, however caused and on anytheory +// of liability. This limitation will apply even if Xilinx +// has been advised of the possibility of such damage. This +// limitation shall apply not-withstanding the failure ofthe +// essential purpose of any limited remedies herein. +// +// Copyright © 2004 Xilinx, Inc. +// All rights reserved +// +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ns / 1ps + +module dvi_decoder ( + input wire tmdsclk_p, // tmds clock + input wire tmdsclk_n, // tmds clock + input wire blue_p, // Blue data in + input wire green_p, // Green data in + input wire red_p, // Red data in + input wire blue_n, // Blue data in + input wire green_n, // Green data in + input wire red_n, // Red data in + input wire exrst, // external reset input, e.g. reset button + + output wire reset, // rx reset + output wire pclk, // regenerated pixel clock + output wire pclkx2, // double rate pixel clock + output wire pclkx10, // 10x pixel as IOCLK + output wire pllclk0, // send pllclk0 out so it can be fed into a different BUFPLL + output wire pllclk1, // PLL x1 output + output wire pllclk2, // PLL x2 output + + output wire pll_lckd, // send pll_lckd out so it can be fed into a different BUFPLL + output wire serdesstrobe, // BUFPLL serdesstrobe output + output wire tmdsclk, // TMDS cable clock + + output wire hsync, // hsync data + output wire vsync, // vsync data + output wire de, // data enable + + output wire blue_vld, + output wire green_vld, + output wire red_vld, + output wire blue_rdy, + output wire green_rdy, + output wire red_rdy, + + output wire psalgnerr, + + output wire [29:0] sdout, + output wire [7:0] red, // pixel data out + output wire [7:0] green, // pixel data out + output wire [7:0] blue); // pixel data out + + + wire [9:0] sdout_blue, sdout_green, sdout_red; +/* + assign sdout = {sdout_red[9], sdout_green[9], sdout_blue[9], sdout_red[8], sdout_green[8], sdout_blue[8], + sdout_red[7], sdout_green[7], sdout_blue[7], sdout_red[6], sdout_green[6], sdout_blue[6], + sdout_red[5], sdout_green[5], sdout_blue[5], sdout_red[4], sdout_green[4], sdout_blue[4], + sdout_red[3], sdout_green[3], sdout_blue[3], sdout_red[2], sdout_green[2], sdout_blue[2], + sdout_red[1], sdout_green[1], sdout_blue[1], sdout_red[0], sdout_green[0], sdout_blue[0]} ; +*/ + assign sdout = {sdout_red[9:5], sdout_green[9:5], sdout_blue[9:5], + sdout_red[4:0], sdout_green[4:0], sdout_blue[4:0]}; + + wire de_b, de_g, de_r; + + assign de = de_b; + + //wire blue_vld, green_vld, red_vld; + //wire blue_rdy, green_rdy, red_rdy; + + wire blue_psalgnerr, green_psalgnerr, red_psalgnerr; + + // + // Send TMDS clock to a differential buffer and then a BUFIO2 + // This is a required path in Spartan-6 feed a PLL CLKIN + // + wire rxclkint; + IBUFDS #(.IOSTANDARD("TMDS_33"), .DIFF_TERM("FALSE") + ) ibuf_rxclk (.I(tmdsclk_p), .IB(tmdsclk_n), .O(rxclkint)); + + wire rxclk; + + BUFIO2 #(.DIVIDE_BYPASS("TRUE"), .DIVIDE(1)) + bufio_tmdsclk (.DIVCLK(rxclk), .IOCLK(), .SERDESSTROBE(), .I(rxclkint)); + + BUFG tmdsclk_bufg (.I(rxclk), .O(tmdsclk)); + + // + // PLL is used to generate three clocks: + // 1. pclk: same rate as TMDS clock + // 2. pclkx2: double rate of pclk used for 5:10 soft gear box and ISERDES DIVCLK + // 3. pclkx10: 10x rate of pclk used as IO clock + // + PLL_BASE # ( + .CLKIN_PERIOD(10), + .CLKFBOUT_MULT(10), //set VCO to 10x of CLKIN + .CLKOUT0_DIVIDE(1), + .CLKOUT1_DIVIDE(10), + .CLKOUT2_DIVIDE(5), + .COMPENSATION("INTERNAL") + ) PLL_ISERDES ( + .CLKFBOUT(clkfbout), + .CLKOUT0(pllclk0), + .CLKOUT1(pllclk1), + .CLKOUT2(pllclk2), + .CLKOUT3(), + .CLKOUT4(), + .CLKOUT5(), + .LOCKED(pll_lckd), + .CLKFBIN(clkfbout), + .CLKIN(rxclk), + .RST(exrst) + ); + + // + // Pixel Rate clock buffer + // + BUFG pclkbufg (.I(pllclk1), .O(pclk)); + + ////////////////////////////////////////////////////////////////// + // 2x pclk is going to be used to drive IOSERDES2 DIVCLK + ////////////////////////////////////////////////////////////////// + BUFG pclkx2bufg (.I(pllclk2), .O(pclkx2)); + + ////////////////////////////////////////////////////////////////// + // 10x pclk is used to drive IOCLK network so a bit rate reference + // can be used by IOSERDES2 + ////////////////////////////////////////////////////////////////// + + wire bufpll_lock; + BUFPLL #(.DIVIDE(5)) ioclk_buf (.PLLIN(pllclk0), .GCLK(pclkx2), .LOCKED(pll_lckd), + .IOCLK(pclkx10), .SERDESSTROBE(serdesstrobe), .LOCK(bufpll_lock)); + + assign reset = ~bufpll_lock; + + decode dec_b ( + .reset (reset), + .pclk (pclk), + .pclkx2 (pclkx2), + .pclkx10 (pclkx10), + .serdesstrobe (serdesstrobe), + .din_p (blue_p), + .din_n (blue_n), + .other_ch0_rdy(green_rdy), + .other_ch1_rdy(red_rdy), + .other_ch0_vld(green_vld), + .other_ch1_vld(red_vld), + + .iamvld (blue_vld), + .iamrdy (blue_rdy), + .psalgnerr (blue_psalgnerr), + .c0 (hsync), + .c1 (vsync), + .de (de_b), + .sdout (sdout_blue), + .dout (blue)) ; + + decode dec_g ( + .reset (reset), + .pclk (pclk), + .pclkx2 (pclkx2), + .pclkx10 (pclkx10), + .serdesstrobe (serdesstrobe), + .din_p (green_p), + .din_n (green_n), + .other_ch0_rdy(blue_rdy), + .other_ch1_rdy(red_rdy), + .other_ch0_vld(blue_vld), + .other_ch1_vld(red_vld), + + .iamvld (green_vld), + .iamrdy (green_rdy), + .psalgnerr (green_psalgnerr), + .c0 (), + .c1 (), + .de (de_g), + .sdout (sdout_green), + .dout (green)) ; + + decode dec_r ( + .reset (reset), + .pclk (pclk), + .pclkx2 (pclkx2), + .pclkx10 (pclkx10), + .serdesstrobe (serdesstrobe), + .din_p (red_p), + .din_n (red_n), + .other_ch0_rdy(blue_rdy), + .other_ch1_rdy(green_rdy), + .other_ch0_vld(blue_vld), + .other_ch1_vld(green_vld), + + .iamvld (red_vld), + .iamrdy (red_rdy), + .psalgnerr (red_psalgnerr), + .c0 (), + .c1 (), + .de (de_r), + .sdout (sdout_red), + .dout (red)) ; + + + + assign psalgnerr = red_psalgnerr | blue_psalgnerr | green_psalgnerr; + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/phsaligner.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/phsaligner.v new file mode 100644 index 0000000..ee582f6 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/phsaligner.v @@ -0,0 +1,265 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Xilinx, Inc. 2010 www.xilinx.com +// +// XAPP xxx - TMDS serial stream phase aligner +// +////////////////////////////////////////////////////////////////////////////// +// +// File name : phasealigner.v +// +// Description : This module determines whether the Spartan-6 IOSERDES +// has validate the incoming TMDS data stream +// +// +// Note: +// +// Author : Bob Feng +// +// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are +// provided to you "as is". Xilinx and its licensors make and you +// receive no warranties or conditions, express, implied, +// statutory or otherwise, and Xilinx specifically disclaims any +// implied warranties of merchantability, non-infringement,or +// fitness for a particular purpose. Xilinx does not warrant that +// the functions contained in these designs will meet your +// requirements, or that the operation of these designs will be +// uninterrupted or error free, or that defects in the Designs +// will be corrected. Furthermore, Xilinx does not warrantor +// make any representations regarding use or the results of the +// use of the designs in terms of correctness, accuracy, +// reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its +// licensors be liable for any loss of data, lost profits,cost +// or procurement of substitute goods or services, or for any +// special, incidental, consequential, or indirect damages +// arising from the use or operation of the designs or +// accompanying documentation, however caused and on any theory +// of liability. This limitation will apply even if Xilinx +// has been advised of the possibility of such damage. This +// limitation shall apply not-withstanding the failure of the +// essential purpose of any limited remedies herein. +// +// Copyright © 2006 Xilinx, Inc. +// All rights reserved +// +////////////////////////////////////////////////////////////////////////////// +// +`timescale 1 ns / 1ps + +module phsaligner # ( + parameter OPENEYE_CNT_WD = 3, // valid open eye counter width + parameter CTKNCNTWD = 7, // Control Token Counter Width + parameter SRCHTIMERWD = 12 // Idle Timer Width +) +( + input wire rst, + input wire clk, + input wire [9:0] sdata, // 10 bit serial stream sync. to clk + output reg flipgear, + output reg bitslip, + output reg psaligned // FSM output +); + + parameter CTRLTOKEN0 = 10'b1101010100; + parameter CTRLTOKEN1 = 10'b0010101011; + parameter CTRLTOKEN2 = 10'b0101010100; + parameter CTRLTOKEN3 = 10'b1010101011; + + /////////////////////////////////////////////////////// + // Control Token Detection + /////////////////////////////////////////////////////// + reg rcvd_ctkn, rcvd_ctkn_q; + reg blnkbgn; //blank period begins + + always @ (posedge clk) begin + rcvd_ctkn <=#1 ((sdata == CTRLTOKEN0) || (sdata == CTRLTOKEN1) || + (sdata == CTRLTOKEN2) || (sdata == CTRLTOKEN3)); + + rcvd_ctkn_q <=#1 rcvd_ctkn; + blnkbgn <=#1 !rcvd_ctkn_q & rcvd_ctkn; + end + + ///////////////////////////////////////////////////// + // Control Token Search Timer + // + // DVI 1.0 Spec. says periodic blanking should start + // no less than every 50ms or 20HZ + // 2^24 of 74.25MHZ cycles is about 200ms + ///////////////////////////////////////////////////// + reg [(SRCHTIMERWD-1):0] ctkn_srh_timer; + reg ctkn_srh_rst; //FSM output + + always @ (posedge clk) begin + if (ctkn_srh_rst) + ctkn_srh_timer <=#1 {SRCHTIMERWD{1'b0}}; + else + ctkn_srh_timer <=#1 ctkn_srh_timer + 1'b1; + end + + reg ctkn_srh_tout; + always @ (posedge clk) begin + ctkn_srh_tout <=#1 (ctkn_srh_timer == {SRCHTIMERWD{1'b1}}); + end + + ///////////////////////////////////////////////////// + // Contorl Token Event Counter + // + // DVI 1.0 Spec. says the minimal blanking period + // is at least 128 pixels long in order to achieve + // synchronization + // + // HDMI reduces this to as little as 8 + ///////////////////////////////////////////////////// + reg [(CTKNCNTWD-1):0] ctkn_counter; + reg ctkn_cnt_rst; //FSM output + + always @ (posedge clk) begin + if(ctkn_cnt_rst) + ctkn_counter <=#1 {CTKNCNTWD{1'b0}}; + else + ctkn_counter <=#1 ctkn_counter + 1'b1; + end + + reg ctkn_cnt_tout; + always @ (posedge clk) begin + ctkn_cnt_tout <=#1 (ctkn_counter == {CTKNCNTWD{1'b1}}); + end + + ////////////////////////////////////////////////////////// + // Below starts the phase alignment state machine + ////////////////////////////////////////////////////////// + parameter INIT = 6'b1 << 0; + parameter SEARCH = 6'b1 << 1; // Searching for control tokens + parameter BITSLIP = 6'b1 << 2; + parameter RCVDCTKN = 6'b1 << 3; // Received at one Control Token and check for more + parameter BLNKPRD = 6'b1 << 4; + parameter PSALGND = 6'b1 << 5; // Phase alignment achieved + parameter nSTATES = 6; + + reg [(nSTATES-1):0] cstate = {{(nSTATES-1){1'b0}}, 1'b1}; //current and next states + reg [(nSTATES-1):0] nstate; + +`ifdef SIMULATION + // synthesis translate_off + reg [8*20:1] state_ascii = "INIT "; + always @(cstate) begin + if (cstate == INIT ) state_ascii <= "INIT "; + else if (cstate == SEARCH ) state_ascii <= "SEARCH "; + else if (cstate == BITSLIP ) state_ascii <= "BITSLIP "; + else if (cstate == RCVDCTKN ) state_ascii <= "RCVDCTKN "; + else if (cstate == BLNKPRD ) state_ascii <= "BLNKPRD "; + else state_ascii <= "PSALGND "; + end + // synthesis translate_on +`endif + + always @ (posedge clk or posedge rst) begin + if (rst) + cstate <= INIT; + else + cstate <=#1 nstate; + end + + ////////////////////////////////////////////////////////// + // Counter counts number of blank period detected + // in order to qualify the bitslip position + ////////////////////////////////////////////////////////// + parameter BLNKPRD_CNT_WD = 1; + + reg [(BLNKPRD_CNT_WD-1):0] blnkprd_cnt = {BLNKPRD_CNT_WD{1'b0}}; + + always @ (*) begin + case (cstate) //synthesis parallel_case full_case + INIT: begin + nstate = (ctkn_srh_tout) ? SEARCH : INIT; + end + + SEARCH: begin + if(blnkbgn) + nstate = RCVDCTKN; + else + nstate = (ctkn_srh_tout) ? BITSLIP : SEARCH; + end + + BITSLIP: begin + nstate = SEARCH; + end + + RCVDCTKN: begin + if(rcvd_ctkn) + nstate = (ctkn_cnt_tout) ? BLNKPRD : RCVDCTKN; + else + nstate = SEARCH; + end + + BLNKPRD: begin + nstate = (blnkprd_cnt == {BLNKPRD_CNT_WD{1'b1}}) ? PSALGND : SEARCH; + end + + PSALGND: begin + nstate = PSALGND; // Phase aligned so hang around here + end + endcase + end + + reg [2:0] bitslip_cnt; + + always @ (posedge clk or posedge rst) begin + if(rst) begin + psaligned <=#1 1'b0; //phase alignment success flag + bitslip <=#1 1'b0; + ctkn_srh_rst <=#1 1'b1; //control token search timer reset + ctkn_cnt_rst <=#1 1'b1; //control token counter reset + + bitslip <=#1 1'b0; + bitslip_cnt <=#1 3'h0; + flipgear <=#1 1'b0; + blnkprd_cnt <=#1 {BLNKPRD_CNT_WD{1'b0}}; + end else begin + case (cstate) // synthesis parallel_case full_case + INIT: begin + ctkn_srh_rst <=#1 1'b0; + ctkn_cnt_rst <=#1 1'b1; + bitslip <=#1 1'b0; + psaligned <=#1 1'b0; + + bitslip <=#1 1'b0; + bitslip_cnt <=#1 3'h0; + flipgear <=#1 1'b0; + blnkprd_cnt <=#1 {BLNKPRD_CNT_WD{1'b0}}; + end + + SEARCH: begin + ctkn_srh_rst <=#1 1'b0; + ctkn_cnt_rst <=#1 1'b1; + bitslip <=#1 1'b0; + psaligned <=#1 1'b0; + end + + BITSLIP: begin + ctkn_srh_rst <=#1 1'b1; + + bitslip <=#1 1'b1; + bitslip_cnt <=#1 bitslip_cnt + 1'b1; + flipgear <=#1 bitslip_cnt[2]; //bitslip has toggled for 4 times + end + + RCVDCTKN: begin + ctkn_srh_rst <=#1 1'b0; + ctkn_cnt_rst <=#1 1'b0; + end + + BLNKPRD: begin + blnkprd_cnt <=#1 blnkprd_cnt + 1'b1; + end + + PSALGND: begin + psaligned <=#1 1'b1; + end + endcase + end + end + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/serdes_1_to_5_diff_data.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/serdes_1_to_5_diff_data.v new file mode 100644 index 0000000..dda62e3 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/rx/serdes_1_to_5_diff_data.v @@ -0,0 +1,403 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Xilinx, Inc. 2010 www.xilinx.com +// +// XAPP xxx - 1:5 Differential Data De-serializer +// +////////////////////////////////////////////////////////////////////////////// +// +// File name : serdes_1_to_5_diff_data.v +// +// Description : This module instantiates IODELAY2 and ISERDES2 primitives +// to receive TMDS differential data in 1:5 format +// +// Note: +// +// Author : Bob Feng +////////////////////////////////////////////////////////////////////////////// +// +// Disclaimer: +// +// This disclaimer is not a license and does not grant any rights to the materials +// distributed herewith. Except as otherwise provided in a valid license issued to you +// by Xilinx, and to the maximum extent permitted by applicable law: +// (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL FAULTS, +// AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, +// INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, OR +// FITNESS FOR ANY PARTICULAR PURPOSE; and (2) Xilinx shall not be liable (whether in contract +// or tort, including negligence, or under any other theory of liability) for any loss or damage +// of any kind or nature related to, arising under or in connection with these materials, +// including for any direct, or any indirect, special, incidental, or consequential loss +// or damage (including loss of data, profits, goodwill, or any type of loss or damage suffered +// as a result of any action brought by a third party) even if such damage or loss was +// reasonably foreseeable or Xilinx had been advised of the possibility of the same. +// +// Critical Applications: +// +// Xilinx products are not designed or intended to be fail-safe, or for use in any application +// requiring fail-safe performance, such as life-support or safety devices or systems, +// Class III medical devices, nuclear facilities, applications related to the deployment of airbags, +// or any other applications that could lead to death, personal injury, or severe property or +// environmental damage (individually and collectively, "Critical Applications"). Customer assumes +// the sole risk and liability of any use of Xilinx products in Critical Applications, subject only +// to applicable laws and regulations governing limitations on product liability. +// +// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE AT ALL TIMES. +// +////////////////////////////////////////////////////////////////////////////// + +`timescale 1ps/1ps + +module serdes_1_to_5_diff_data # ( + parameter DIFF_TERM = "TRUE", + parameter SIM_TAP_DELAY = 49, + parameter BITSLIP_ENABLE = "FALSE" +)( + input wire use_phase_detector, // '1' enables the phase detector logic + input wire datain_p, // Input from LVDS receiver pin + input wire datain_n, // Input from LVDS receiver pin + input wire rxioclk, // IO Clock network + input wire rxserdesstrobe, // Parallel data capture strobe + input wire reset, // Reset line + input wire gclk, // Global clock + input wire bitslip, // Bitslip control line + output wire [4:0] data_out // Output data +); + + wire ddly_m; + wire ddly_s; + wire busys; + wire rx_data_in; + wire cascade; + wire pd_edge; + reg [8:0] counter; + reg [3:0] state; + reg cal_data_sint; + wire busy_data; + reg busy_data_d; + wire cal_data_slave; + reg enable; + reg cal_data_master; + reg rst_data; + reg inc_data_int; + wire inc_data; + reg ce_data; + reg valid_data_d; + reg incdec_data_d; + reg [4:0] pdcounter; + wire valid_data; + wire incdec_data; + reg flag; + reg mux; + reg ce_data_inta ; + wire [1:0] incdec_data_or; + wire incdec_data_im; + wire [1:0] valid_data_or; + wire valid_data_im; + wire [1:0] busy_data_or; + wire all_ce; + + wire [1:0] debug_in = 2'b00; + + assign busy_data = busys ; + + assign cal_data_slave = cal_data_sint ; + + ///////////////////////////////////////////////// + // + // IDELAY Calibration FSM + // + ///////////////////////////////////////////////// + always @ (posedge gclk or posedge reset) + begin + if (reset == 1'b1) begin + state <= 0 ; + cal_data_master <= 1'b0 ; + cal_data_sint <= 1'b0 ; + counter <= 9'h000 ; + enable <= 1'b0 ; + mux <= 1'h1 ; + end + else begin + counter <= counter + 9'h001 ; + if (counter[8] == 1'b1) begin + counter <= 9'h000 ; + end + if (counter[5] == 1'b1) begin + enable <= 1'b1 ; + end + if (state == 0 && enable == 1'b1) begin // Wait for IODELAY to be available + cal_data_master <= 1'b0 ; + cal_data_sint <= 1'b0 ; + rst_data <= 1'b0 ; + if (busy_data_d == 1'b0) begin + state <= 1 ; + end + end + else if (state == 1) begin // Issue calibrate command to both master and slave, needed for simulation, not for the silicon + cal_data_master <= 1'b1 ; + cal_data_sint <= 1'b1 ; + if (busy_data_d == 1'b1) begin // and wait for command to be accepted + state <= 2 ; + end + end + else if (state == 2) begin // Now RST master and slave IODELAYs needed for simulation, not for the silicon + cal_data_master <= 1'b0 ; + cal_data_sint <= 1'b0 ; + if (busy_data_d == 1'b0) begin + rst_data <= 1'b1 ; + state <= 3 ; + end + end + else if (state == 3) begin // Wait for IODELAY to be available + rst_data <= 1'b0 ; + if (busy_data_d == 1'b0) begin + state <= 4 ; + end + end + else if (state == 4) begin // Wait for occasional enable + if (counter[8] == 1'b1) begin + state <= 5 ; + end + end + else if (state == 5) begin // Calibrate slave only + if (busy_data_d == 1'b0) begin + cal_data_sint <= 1'b1 ; + state <= 6 ; + end + end + else if (state == 6) begin // Wait for command to be accepted + cal_data_sint <= 1'b0 ; + if (busy_data_d == 1'b1) begin + state <= 7 ; + end + end + else if (state == 7) begin // Wait for all IODELAYs to be available, ie CAL command finished + cal_data_sint <= 1'b0 ; + if (busy_data_d == 1'b0) begin + state <= 4 ; + end + end + end + end + +always @ (posedge gclk or posedge reset) // Per-bit phase detection state machine +begin +if (reset == 1'b1) begin + pdcounter <= 5'b1000 ; + ce_data_inta <= 1'b0 ; + flag <= 1'b0 ; // flag is there to only allow one inc or dec per cal (test) +end +else begin + busy_data_d <= busy_data_or[1] ; + if (use_phase_detector == 1'b1) begin // decide whther pd is used + incdec_data_d <= incdec_data_or[1] ; + valid_data_d <= valid_data_or[1] ; + if (ce_data_inta == 1'b1) begin + ce_data = mux ; + end + else begin + ce_data = 64'h0000000000000000 ; + end + if (state == 7) begin + flag <= 1'b0 ; + end + else if (state != 4 || busy_data_d == 1'b1) begin // Reset filter if state machine issues a cal command or unit is busy + pdcounter <= 5'b10000 ; + ce_data_inta <= 1'b0 ; + end + else if (pdcounter == 5'b11111 && flag == 1'b0) begin // Filter has reached positive max - increment the tap count + ce_data_inta <= 1'b1 ; + inc_data_int <= 1'b1 ; + pdcounter <= 5'b10000 ; + flag <= 1'b1 ; + end + else if (pdcounter == 5'b00000 && flag == 1'b0) begin // Filter has reached negative max - decrement the tap count + ce_data_inta <= 1'b1 ; + inc_data_int <= 1'b0 ; + pdcounter <= 5'b10000 ; + flag <= 1'b1 ; + end + else if (valid_data_d == 1'b1) begin // increment filter + ce_data_inta <= 1'b0 ; + if (incdec_data_d == 1'b1 && pdcounter != 5'b11111) begin + pdcounter <= pdcounter + 5'b00001 ; + end + else if (incdec_data_d == 1'b0 && pdcounter != 5'b00000) begin // decrement filter + pdcounter <= pdcounter + 5'b11111 ; + end + end + else begin + ce_data_inta <= 1'b0 ; + end + end + else begin + ce_data = all_ce ; + inc_data_int = debug_in[1] ; + end +end +end + +assign inc_data = inc_data_int ; + +assign incdec_data_or[0] = 1'b0 ; // Input Mux - Initialise generate loop OR gates +assign valid_data_or[0] = 1'b0 ; +assign busy_data_or[0] = 1'b0 ; + +assign incdec_data_im = incdec_data & mux; // Input muxes +assign incdec_data_or[1] = incdec_data_im | incdec_data_or; // AND gates to allow just one signal through at a tome +assign valid_data_im = valid_data & mux; // followed by an OR +assign valid_data_or[1] = valid_data_im | valid_data_or; // for the three inputs from each PD +assign busy_data_or[1] = busy_data | busy_data_or; // The busy signals just need an OR gate + +assign all_ce = debug_in[0] ; + +IBUFDS #( + .DIFF_TERM (DIFF_TERM)) +data_in ( + .I (datain_p), + .IB (datain_n), + .O (rx_data_in) +); + +// +// Master IDELAY +// +IODELAY2 #( + .DATA_RATE ("SDR"), + .IDELAY_VALUE (0), + .IDELAY2_VALUE (0), + .IDELAY_MODE ("NORMAL" ), + .ODELAY_VALUE (0), + .IDELAY_TYPE ("DIFF_PHASE_DETECTOR"), + .COUNTER_WRAPAROUND ("STAY_AT_LIMIT"), //("WRAPAROUND"), + .DELAY_SRC ("IDATAIN"), + .SERDES_MODE ("MASTER"), + .SIM_TAPDELAY_VALUE (SIM_TAP_DELAY) +) iodelay_m ( + .IDATAIN (rx_data_in), // data from IBUFDS + .TOUT (), // tri-state signal to IOB + .DOUT (), // output data to IOB + .T (1'b1), // tri-state control from OLOGIC/OSERDES2 + .ODATAIN (1'b0), // data from OLOGIC/OSERDES2 + .DATAOUT (ddly_m), // Output data 1 to ILOGIC/ISERDES2 + .DATAOUT2 (), // Output data 2 to ILOGIC/ISERDES2 + .IOCLK0 (rxioclk), // High speed clock for calibration + .IOCLK1 (1'b0), // High speed clock for calibration + .CLK (gclk), // Fabric clock (GCLK) for control signals + .CAL (cal_data_master), // Calibrate control signal + .INC (inc_data), // Increment counter + .CE (ce_data), // Clock Enable + .RST (rst_data), // Reset delay line + .BUSY () // output signal indicating sync circuit has finished / calibration has finished +); + +// +// Slave IDELAY +// +IODELAY2 #( + .DATA_RATE ("SDR"), + .IDELAY_VALUE (0), + .IDELAY2_VALUE (0), + .IDELAY_MODE ("NORMAL" ), + .ODELAY_VALUE (0), + .IDELAY_TYPE ("DIFF_PHASE_DETECTOR"), + .COUNTER_WRAPAROUND ("WRAPAROUND"), + .DELAY_SRC ("IDATAIN"), + .SERDES_MODE ("SLAVE"), + .SIM_TAPDELAY_VALUE (SIM_TAP_DELAY) +) iodelay_s ( + .IDATAIN (rx_data_in), // data from IBUFDS + .TOUT (), // tri-state signal to IOB + .DOUT (), // output data to IOB + .T (1'b1), // tri-state control from OLOGIC/OSERDES2 + .ODATAIN (1'b0), // data from OLOGIC/OSERDES2 + .DATAOUT (ddly_s), // Slave output data to ILOGIC/ISERDES2 + .DATAOUT2 (), // + .IOCLK0 (rxioclk), // High speed IO clock for calibration + .IOCLK1 (1'b0), + .CLK (gclk), // Fabric clock (GCLK) for control signals + .CAL (cal_data_slave), // Calibrate control signal + .INC (inc_data), // Increment counter + .CE (ce_data), // Clock Enable + .RST (rst_data), // Reset delay line + .BUSY (busys) // output signal indicating sync circuit has finished / calibration has finished +); + +// +// Master ISERDES +// + +ISERDES2 #( + .DATA_WIDTH (5), + .DATA_RATE ("SDR"), + .BITSLIP_ENABLE (BITSLIP_ENABLE), + .SERDES_MODE ("MASTER"), + .INTERFACE_TYPE ("RETIMED")) +iserdes_m ( + .D (ddly_m), + .CE0 (1'b1), + .CLK0 (rxioclk), + .CLK1 (1'b0), + .IOCE (rxserdesstrobe), + .RST (reset), + .CLKDIV (gclk), + .SHIFTIN (pd_edge), + .BITSLIP (bitslip), + .FABRICOUT (), + .Q4 (data_out[4]), + .Q3 (data_out[3]), + .Q2 (data_out[2]), + .Q1 (data_out[1]), + .DFB (), + .CFB0 (), + .CFB1 (), + .VALID (valid_data), + .INCDEC (incdec_data), + .SHIFTOUT (cascade)); + +// +// Slave ISERDES +// + +ISERDES2 #( + .DATA_WIDTH (5), + .DATA_RATE ("SDR"), + .BITSLIP_ENABLE (BITSLIP_ENABLE), + .SERDES_MODE ("SLAVE"), + .INTERFACE_TYPE ("RETIMED") +) iserdes_s ( + .D (ddly_s), + .CE0 (1'b1), + .CLK0 (rxioclk), + .CLK1 (1'b0), + .IOCE (rxserdesstrobe), + .RST (reset), + .CLKDIV (gclk), + .SHIFTIN (cascade), + .BITSLIP (bitslip), + .FABRICOUT (), + .Q4 (data_out[0]), + .Q3 (), + .Q2 (), + .Q1 (), + .DFB (), + .CFB0 (), + .CFB1 (), + .VALID (), + .INCDEC (), + .SHIFTOUT (pd_edge)); + + +reg [7:0] rxpdcntr = 8'h7f; +always @ (posedge gclk or posedge reset) begin + if (reset) + rxpdcntr <= 8'h7f; + else if (ce_data) + if (inc_data) + rxpdcntr <= rxpdcntr + 1'b1; + else + rxpdcntr <= rxpdcntr - 1'b1; +end + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/convert_30to15_fifo.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/convert_30to15_fifo.v new file mode 100644 index 0000000..8ad8727 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/convert_30to15_fifo.v @@ -0,0 +1,168 @@ +module convert_30to15_fifo( + input wire rst, // reset + input wire clk, // clock input + input wire clkx2, // 2x clock input + input wire [29:0] datain, // input data for 2:1 serialisation + output wire [14:0] dataout); // 5-bit data out + + //////////////////////////////////////////////////// + // Here we instantiate a 16x10 Dual Port RAM + // and fill first it with data aligned to + // clk domain + //////////////////////////////////////////////////// + wire [3:0] wa; // RAM read address + reg [3:0] wa_d; // RAM read address + wire [3:0] ra; // RAM read address + reg [3:0] ra_d; // RAM read address + wire [29:0] dataint; // RAM output + + parameter ADDR0 = 4'b0000; + parameter ADDR1 = 4'b0001; + parameter ADDR2 = 4'b0010; + parameter ADDR3 = 4'b0011; + parameter ADDR4 = 4'b0100; + parameter ADDR5 = 4'b0101; + parameter ADDR6 = 4'b0110; + parameter ADDR7 = 4'b0111; + parameter ADDR8 = 4'b1000; + parameter ADDR9 = 4'b1001; + parameter ADDR10 = 4'b1010; + parameter ADDR11 = 4'b1011; + parameter ADDR12 = 4'b1100; + parameter ADDR13 = 4'b1101; + parameter ADDR14 = 4'b1110; + parameter ADDR15 = 4'b1111; + + always@(wa) begin + case (wa) + ADDR0 : wa_d = ADDR1 ; + ADDR1 : wa_d = ADDR2 ; + ADDR2 : wa_d = ADDR3 ; + ADDR3 : wa_d = ADDR4 ; + ADDR4 : wa_d = ADDR5 ; + ADDR5 : wa_d = ADDR6 ; + ADDR6 : wa_d = ADDR7 ; + ADDR7 : wa_d = ADDR8 ; + ADDR8 : wa_d = ADDR9 ; + ADDR9 : wa_d = ADDR10; + ADDR10 : wa_d = ADDR11; + ADDR11 : wa_d = ADDR12; + ADDR12 : wa_d = ADDR13; + ADDR13 : wa_d = ADDR14; + ADDR14 : wa_d = ADDR15; + default : wa_d = ADDR0; + endcase + end + + FDC fdc_wa0 (.C(clk), .D(wa_d[0]), .CLR(rst), .Q(wa[0])); + FDC fdc_wa1 (.C(clk), .D(wa_d[1]), .CLR(rst), .Q(wa[1])); + FDC fdc_wa2 (.C(clk), .D(wa_d[2]), .CLR(rst), .Q(wa[2])); + FDC fdc_wa3 (.C(clk), .D(wa_d[3]), .CLR(rst), .Q(wa[3])); + + //Dual Port fifo to bridge data from clk to clkx2 + DRAM16XN #(.data_width(30)) + fifo_u ( + .DATA_IN(datain), + .ADDRESS(wa), + .ADDRESS_DP(ra), + .WRITE_EN(1'b1), + .CLK(clk), + .O_DATA_OUT(), + .O_DATA_OUT_DP(dataint)); + + ///////////////////////////////////////////////////////////////// + // Here starts clk2x domain for fifo read out + // FIFO read is set to be once every 2 cycles of clk2x in order + // to keep up pace with the fifo write speed + // Also FIFO read reset is delayed a bit in order to avoid + // underflow. + ///////////////////////////////////////////////////////////////// + + always@(ra) begin + case (ra) + ADDR0 : ra_d = ADDR1 ; + ADDR1 : ra_d = ADDR2 ; + ADDR2 : ra_d = ADDR3 ; + ADDR3 : ra_d = ADDR4 ; + ADDR4 : ra_d = ADDR5 ; + ADDR5 : ra_d = ADDR6 ; + ADDR6 : ra_d = ADDR7 ; + ADDR7 : ra_d = ADDR8 ; + ADDR8 : ra_d = ADDR9 ; + ADDR9 : ra_d = ADDR10; + ADDR10 : ra_d = ADDR11; + ADDR11 : ra_d = ADDR12; + ADDR12 : ra_d = ADDR13; + ADDR13 : ra_d = ADDR14; + ADDR14 : ra_d = ADDR15; + default : ra_d = ADDR0; + endcase + end + + wire rstsync, rstsync_q, rstp; + (* ASYNC_REG = "TRUE" *) FDP fdp_rst (.C(clkx2), .D(rst), .PRE(rst), .Q(rstsync)); + + FD fd_rstsync (.C(clkx2), .D(rstsync), .Q(rstsync_q)); + FD fd_rstp (.C(clkx2), .D(rstsync_q), .Q(rstp)); + + wire sync; + FDR sync_gen (.Q (sync), .C (clkx2), .R(rstp), .D(~sync)); + + FDRE fdc_ra0 (.C(clkx2), .D(ra_d[0]), .R(rstp), .CE(sync), .Q(ra[0])); + FDRE fdc_ra1 (.C(clkx2), .D(ra_d[1]), .R(rstp), .CE(sync), .Q(ra[1])); + FDRE fdc_ra2 (.C(clkx2), .D(ra_d[2]), .R(rstp), .CE(sync), .Q(ra[2])); + FDRE fdc_ra3 (.C(clkx2), .D(ra_d[3]), .R(rstp), .CE(sync), .Q(ra[3])); + + wire [29:0] db; + + FDE fd_db0 (.C(clkx2), .D(dataint[0]), .CE(sync), .Q(db[0])); + FDE fd_db1 (.C(clkx2), .D(dataint[1]), .CE(sync), .Q(db[1])); + FDE fd_db2 (.C(clkx2), .D(dataint[2]), .CE(sync), .Q(db[2])); + FDE fd_db3 (.C(clkx2), .D(dataint[3]), .CE(sync), .Q(db[3])); + FDE fd_db4 (.C(clkx2), .D(dataint[4]), .CE(sync), .Q(db[4])); + FDE fd_db5 (.C(clkx2), .D(dataint[5]), .CE(sync), .Q(db[5])); + FDE fd_db6 (.C(clkx2), .D(dataint[6]), .CE(sync), .Q(db[6])); + FDE fd_db7 (.C(clkx2), .D(dataint[7]), .CE(sync), .Q(db[7])); + FDE fd_db8 (.C(clkx2), .D(dataint[8]), .CE(sync), .Q(db[8])); + FDE fd_db9 (.C(clkx2), .D(dataint[9]), .CE(sync), .Q(db[9])); + FDE fd_db10 (.C(clkx2), .D(dataint[10]), .CE(sync), .Q(db[10])); + FDE fd_db11 (.C(clkx2), .D(dataint[11]), .CE(sync), .Q(db[11])); + FDE fd_db12 (.C(clkx2), .D(dataint[12]), .CE(sync), .Q(db[12])); + FDE fd_db13 (.C(clkx2), .D(dataint[13]), .CE(sync), .Q(db[13])); + FDE fd_db14 (.C(clkx2), .D(dataint[14]), .CE(sync), .Q(db[14])); + FDE fd_db15 (.C(clkx2), .D(dataint[15]), .CE(sync), .Q(db[15])); + FDE fd_db16 (.C(clkx2), .D(dataint[16]), .CE(sync), .Q(db[16])); + FDE fd_db17 (.C(clkx2), .D(dataint[17]), .CE(sync), .Q(db[17])); + FDE fd_db18 (.C(clkx2), .D(dataint[18]), .CE(sync), .Q(db[18])); + FDE fd_db19 (.C(clkx2), .D(dataint[19]), .CE(sync), .Q(db[19])); + FDE fd_db20 (.C(clkx2), .D(dataint[20]), .CE(sync), .Q(db[20])); + FDE fd_db21 (.C(clkx2), .D(dataint[21]), .CE(sync), .Q(db[21])); + FDE fd_db22 (.C(clkx2), .D(dataint[22]), .CE(sync), .Q(db[22])); + FDE fd_db23 (.C(clkx2), .D(dataint[23]), .CE(sync), .Q(db[23])); + FDE fd_db24 (.C(clkx2), .D(dataint[24]), .CE(sync), .Q(db[24])); + FDE fd_db25 (.C(clkx2), .D(dataint[25]), .CE(sync), .Q(db[25])); + FDE fd_db26 (.C(clkx2), .D(dataint[26]), .CE(sync), .Q(db[26])); + FDE fd_db27 (.C(clkx2), .D(dataint[27]), .CE(sync), .Q(db[27])); + FDE fd_db28 (.C(clkx2), .D(dataint[28]), .CE(sync), .Q(db[28])); + FDE fd_db29 (.C(clkx2), .D(dataint[29]), .CE(sync), .Q(db[29])); + + wire [14:0] mux; + assign mux = (~sync) ? db[14:0] : db[29:15]; + + FD fd_out0 (.C(clkx2), .D(mux[0]), .Q(dataout[0])); + FD fd_out1 (.C(clkx2), .D(mux[1]), .Q(dataout[1])); + FD fd_out2 (.C(clkx2), .D(mux[2]), .Q(dataout[2])); + FD fd_out3 (.C(clkx2), .D(mux[3]), .Q(dataout[3])); + FD fd_out4 (.C(clkx2), .D(mux[4]), .Q(dataout[4])); + FD fd_out5 (.C(clkx2), .D(mux[5]), .Q(dataout[5])); + FD fd_out6 (.C(clkx2), .D(mux[6]), .Q(dataout[6])); + FD fd_out7 (.C(clkx2), .D(mux[7]), .Q(dataout[7])); + FD fd_out8 (.C(clkx2), .D(mux[8]), .Q(dataout[8])); + FD fd_out9 (.C(clkx2), .D(mux[9]), .Q(dataout[9])); + FD fd_out10 (.C(clkx2), .D(mux[10]), .Q(dataout[10])); + FD fd_out11 (.C(clkx2), .D(mux[11]), .Q(dataout[11])); + FD fd_out12 (.C(clkx2), .D(mux[12]), .Q(dataout[12])); + FD fd_out13 (.C(clkx2), .D(mux[13]), .Q(dataout[13])); + FD fd_out14 (.C(clkx2), .D(mux[14]), .Q(dataout[14])); + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/dvi_encoder.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/dvi_encoder.v new file mode 100644 index 0000000..963a96b --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/dvi_encoder.v @@ -0,0 +1,103 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Xilinx, Inc. 2009 www.xilinx.com +// +// XAPP xyz +// +////////////////////////////////////////////////////////////////////////////// +// +// File name : dvi_encoder.v +// +// Description : dvi_encoder +// +// Date - revision : April 2009 - 1.0.0 +// +// Author : Bob Feng +// +// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are +// provided to you "as is". Xilinx and its licensors makeand you +// receive no warranties or conditions, express, implied, +// statutory or otherwise, and Xilinx specificallydisclaims any +// implied warranties of merchantability, non-infringement,or +// fitness for a particular purpose. Xilinx does notwarrant that +// the functions contained in these designs will meet your +// requirements, or that the operation of these designswill be +// uninterrupted or error free, or that defects in theDesigns +// will be corrected. Furthermore, Xilinx does not warrantor +// make any representations regarding use or the results ofthe +// use of the designs in terms of correctness, accuracy, +// reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its +// licensors be liable for any loss of data, lost profits,cost +// or procurement of substitute goods or services, or forany +// special, incidental, consequential, or indirect damages +// arising from the use or operation of the designs or +// accompanying documentation, however caused and on anytheory +// of liability. This limitation will apply even if Xilinx +// has been advised of the possibility of such damage. This +// limitation shall apply not-withstanding the failure ofthe +// essential purpose of any limited remedies herein. +// +// Copyright © 2009 Xilinx, Inc. +// All rights reserved +// +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ns / 1ps + +module dvi_encoder ( +input wire clkin, // pixel clock +input wire clkx2in, // pixel clock x2 +input wire rstin, // reset +input wire [7:0] blue_din, // Blue data in +input wire [7:0] green_din, // Green data in +input wire [7:0] red_din, // Red data in +input wire hsync, // hsync data +input wire vsync, // vsync data +input wire de, // data enable +output wire [4:0] tmds_data0, +output wire [4:0] tmds_data1, +output wire [4:0] tmds_data2); // 5-bit busses converted from 10-bit + +wire [9:0] red ; +wire [9:0] green ; +wire [9:0] blue ; + +encode encb ( + .clkin (clkin), + .rstin (rstin), + .din (blue_din), + .c0 (hsync), + .c1 (vsync), + .de (de), + .dout (blue)) ; + +encode encg ( + .clkin (clkin), + .rstin (rstin), + .din (green_din), + .c0 (1'b0), + .c1 (1'b0), + .de (de), + .dout (green)) ; + +encode encr ( + .clkin (clkin), + .rstin (rstin), + .din (red_din), + .c0 (1'b0), + .c1 (1'b0), + .de (de), + .dout (red)) ; + +wire [29:0] s_data = {red[9:5], green[9:5], blue[9:5], + red[4:0], green[4:0], blue[4:0]}; + +convert_30to15_fifo pixel2x ( + .rst (rstin), + .clk (clkin), + .clkx2 (clkx2in), + .datain (s_data), + .dataout ({tmds_data2, tmds_data1, tmds_data0})); + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/dvi_encoder_top.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/dvi_encoder_top.v new file mode 100644 index 0000000..fcfefe0 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/dvi_encoder_top.v @@ -0,0 +1,172 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Xilinx, Inc. 2009 www.xilinx.com +// +// XAPP xyz +// +////////////////////////////////////////////////////////////////////////////// +// +// File name : dvi_encoder.v +// +// Description : dvi_encoder +// +// Date - revision : April 2009 - 1.0.0 +// +// Author : Bob Feng +// +// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are +// provided to you "as is". Xilinx and its licensors makeand you +// receive no warranties or conditions, express, implied, +// statutory or otherwise, and Xilinx specificallydisclaims any +// implied warranties of merchantability, non-infringement,or +// fitness for a particular purpose. Xilinx does notwarrant that +// the functions contained in these designs will meet your +// requirements, or that the operation of these designswill be +// uninterrupted or error free, or that defects in theDesigns +// will be corrected. Furthermore, Xilinx does not warrantor +// make any representations regarding use or the results ofthe +// use of the designs in terms of correctness, accuracy, +// reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its +// licensors be liable for any loss of data, lost profits,cost +// or procurement of substitute goods or services, or forany +// special, incidental, consequential, or indirect damages +// arising from the use or operation of the designs or +// accompanying documentation, however caused and on anytheory +// of liability. This limitation will apply even if Xilinx +// has been advised of the possibility of such damage. This +// limitation shall apply not-withstanding the failure ofthe +// essential purpose of any limited remedies herein. +// +// Copyright © 2009 Xilinx, Inc. +// All rights reserved +// +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ns / 1ps + +module dvi_encoder_top ( + input wire pclk, // pixel clock + input wire pclkx2, // pixel clock x2 + input wire pclkx10, // pixel clock x2 + input wire serdesstrobe, // OSERDES2 serdesstrobe + input wire rstin, // reset + input wire [7:0] blue_din, // Blue data in + input wire [7:0] green_din, // Green data in + input wire [7:0] red_din, // Red data in + input wire hsync, // hsync data + input wire vsync, // vsync data + input wire de, // data enable + output wire [3:0] TMDS, + output wire [3:0] TMDSB); + + wire [9:0] red ; + wire [9:0] green ; + wire [9:0] blue ; + + wire [4:0] tmds_data0, tmds_data1, tmds_data2; + wire [2:0] tmdsint; + + // + // Forward TMDS Clock Using OSERDES2 block + // + reg [4:0] tmdsclkint = 5'b00000; + reg toggle = 1'b0; + + always @ (posedge pclkx2 or posedge rstin) begin + if (rstin) + toggle <= 1'b0; + else + toggle <= ~toggle; + end + + always @ (posedge pclkx2) begin + if (toggle) + tmdsclkint <= 5'b11111; + else + tmdsclkint <= 5'b00000; + end + + wire tmdsclk; + + serdes_n_to_1 #( + .SF (5)) + clkout ( + .iob_data_out (tmdsclk), + .ioclk (pclkx10), + .serdesstrobe (serdesstrobe), + .gclk (pclkx2), + .reset (rstin), + .datain (tmdsclkint)); + + OBUFDS TMDS3 (.I(tmdsclk), .O(TMDS[3]), .OB(TMDSB[3])) ;// clock + + // + // Forward TMDS Data: 3 channels + // + serdes_n_to_1 #(.SF(5)) oserdes0 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(rstin), + .gclk(pclkx2), + .datain(tmds_data0), + .iob_data_out(tmdsint[0])) ; + + serdes_n_to_1 #(.SF(5)) oserdes1 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(rstin), + .gclk(pclkx2), + .datain(tmds_data1), + .iob_data_out(tmdsint[1])) ; + + serdes_n_to_1 #(.SF(5)) oserdes2 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(rstin), + .gclk(pclkx2), + .datain(tmds_data2), + .iob_data_out(tmdsint[2])) ; + + OBUFDS TMDS0 (.I(tmdsint[0]), .O(TMDS[0]), .OB(TMDSB[0])) ; + OBUFDS TMDS1 (.I(tmdsint[1]), .O(TMDS[1]), .OB(TMDSB[1])) ; + OBUFDS TMDS2 (.I(tmdsint[2]), .O(TMDS[2]), .OB(TMDSB[2])) ; + + encode encb ( + .clkin (pclk), + .rstin (rstin), + .din (blue_din), + .c0 (hsync), + .c1 (vsync), + .de (de), + .dout (blue)) ; + + encode encg ( + .clkin (pclk), + .rstin (rstin), + .din (green_din), + .c0 (1'b0), + .c1 (1'b0), + .de (de), + .dout (green)) ; + + encode encr ( + .clkin (pclk), + .rstin (rstin), + .din (red_din), + .c0 (1'b0), + .c1 (1'b0), + .de (de), + .dout (red)) ; + + wire [29:0] s_data = {red[9:5], green[9:5], blue[9:5], + red[4:0], green[4:0], blue[4:0]}; + + convert_30to15_fifo pixel2x ( + .rst (rstin), + .clk (pclk), + .clkx2 (pclkx2), + .datain (s_data), + .dataout ({tmds_data2, tmds_data1, tmds_data0})); + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/encode.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/encode.v new file mode 100644 index 0000000..0a7f13d --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/encode.v @@ -0,0 +1,191 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Xilinx, Inc. 2008 www.xilinx.com +// +////////////////////////////////////////////////////////////////////////////// +// +// File name : encode.v +// +// Description : TMDS encoder +// +// Date - revision : Jan. 2008 - v 1.0 +// +// Author : Bob Feng +// +// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are +// provided to you "as is". Xilinx and its licensors make and you +// receive no warranties or conditions, express, implied, +// statutory or otherwise, and Xilinx specifically disclaims any +// implied warranties of merchantability, non-infringement,or +// fitness for a particular purpose. Xilinx does not warrant that +// the functions contained in these designs will meet your +// requirements, or that the operation of these designs will be +// uninterrupted or error free, or that defects in the Designs +// will be corrected. Furthermore, Xilinx does not warrantor +// make any representations regarding use or the results of the +// use of the designs in terms of correctness, accuracy, +// reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its +// licensors be liable for any loss of data, lost profits,cost +// or procurement of substitute goods or services, or for any +// special, incidental, consequential, or indirect damages +// arising from the use or operation of the designs or +// accompanying documentation, however caused and on any theory +// of liability. This limitation will apply even if Xilinx +// has been advised of the possibility of such damage. This +// limitation shall apply not-withstanding the failure of the +// essential purpose of any limited remedies herein. +// +// Copyright © 2006 Xilinx, Inc. +// All rights reserved +// +////////////////////////////////////////////////////////////////////////////// +`timescale 1 ps / 1ps + +module encode ( + input clkin, // pixel clock input + input rstin, // async. reset input (active high) + input [7:0] din, // data inputs: expect registered + input c0, // c0 input + input c1, // c1 input + input de, // de input + output reg [9:0] dout // data outputs +); + + //////////////////////////////////////////////////////////// + // Counting number of 1s and 0s for each incoming pixel + // component. Pipe line the result. + // Register Data Input so it matches the pipe lined adder + // output + //////////////////////////////////////////////////////////// + reg [3:0] n1d; //number of 1s in din + reg [7:0] din_q; + + always @ (posedge clkin) begin + n1d <=#1 din[0] + din[1] + din[2] + din[3] + din[4] + din[5] + din[6] + din[7]; + + din_q <=#1 din; + end + + /////////////////////////////////////////////////////// + // Stage 1: 8 bit -> 9 bit + // Refer to DVI 1.0 Specification, page 29, Figure 3-5 + /////////////////////////////////////////////////////// + wire decision1; + + assign decision1 = (n1d > 4'h4) | ((n1d == 4'h4) & (din_q[0] == 1'b0)); +/* + reg [8:0] q_m; + always @ (posedge clkin) begin + q_m[0] <=#1 din_q[0]; + q_m[1] <=#1 (decision1) ? (q_m[0] ^~ din_q[1]) : (q_m[0] ^ din_q[1]); + q_m[2] <=#1 (decision1) ? (q_m[1] ^~ din_q[2]) : (q_m[1] ^ din_q[2]); + q_m[3] <=#1 (decision1) ? (q_m[2] ^~ din_q[3]) : (q_m[2] ^ din_q[3]); + q_m[4] <=#1 (decision1) ? (q_m[3] ^~ din_q[4]) : (q_m[3] ^ din_q[4]); + q_m[5] <=#1 (decision1) ? (q_m[4] ^~ din_q[5]) : (q_m[4] ^ din_q[5]); + q_m[6] <=#1 (decision1) ? (q_m[5] ^~ din_q[6]) : (q_m[5] ^ din_q[6]); + q_m[7] <=#1 (decision1) ? (q_m[6] ^~ din_q[7]) : (q_m[6] ^ din_q[7]); + q_m[8] <=#1 (decision1) ? 1'b0 : 1'b1; + end +*/ + wire [8:0] q_m; + assign q_m[0] = din_q[0]; + assign q_m[1] = (decision1) ? (q_m[0] ^~ din_q[1]) : (q_m[0] ^ din_q[1]); + assign q_m[2] = (decision1) ? (q_m[1] ^~ din_q[2]) : (q_m[1] ^ din_q[2]); + assign q_m[3] = (decision1) ? (q_m[2] ^~ din_q[3]) : (q_m[2] ^ din_q[3]); + assign q_m[4] = (decision1) ? (q_m[3] ^~ din_q[4]) : (q_m[3] ^ din_q[4]); + assign q_m[5] = (decision1) ? (q_m[4] ^~ din_q[5]) : (q_m[4] ^ din_q[5]); + assign q_m[6] = (decision1) ? (q_m[5] ^~ din_q[6]) : (q_m[5] ^ din_q[6]); + assign q_m[7] = (decision1) ? (q_m[6] ^~ din_q[7]) : (q_m[6] ^ din_q[7]); + assign q_m[8] = (decision1) ? 1'b0 : 1'b1; + + ///////////////////////////////////////////////////////// + // Stage 2: 9 bit -> 10 bit + // Refer to DVI 1.0 Specification, page 29, Figure 3-5 + ///////////////////////////////////////////////////////// + reg [3:0] n1q_m, n0q_m; // number of 1s and 0s for q_m + always @ (posedge clkin) begin + n1q_m <=#1 q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7]; + n0q_m <=#1 4'h8 - (q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7]); + end + + parameter CTRLTOKEN0 = 10'b1101010100; + parameter CTRLTOKEN1 = 10'b0010101011; + parameter CTRLTOKEN2 = 10'b0101010100; + parameter CTRLTOKEN3 = 10'b1010101011; + + reg [4:0] cnt; //disparity counter, MSB is the sign bit + wire decision2, decision3; + + assign decision2 = (cnt == 5'h0) | (n1q_m == n0q_m); + ///////////////////////////////////////////////////////////////////////// + // [(cnt > 0) and (N1q_m > N0q_m)] or [(cnt < 0) and (N0q_m > N1q_m)] + ///////////////////////////////////////////////////////////////////////// + assign decision3 = (~cnt[4] & (n1q_m > n0q_m)) | (cnt[4] & (n0q_m > n1q_m)); + + //////////////////////////////////// + // pipe line alignment + //////////////////////////////////// + reg de_q, de_reg; + reg c0_q, c1_q; + reg c0_reg, c1_reg; + reg [8:0] q_m_reg; + + always @ (posedge clkin) begin + de_q <=#1 de; + de_reg <=#1 de_q; + + c0_q <=#1 c0; + c0_reg <=#1 c0_q; + c1_q <=#1 c1; + c1_reg <=#1 c1_q; + + q_m_reg <=#1 q_m; + end + + /////////////////////////////// + // 10-bit out + // disparity counter + /////////////////////////////// + always @ (posedge clkin or posedge rstin) begin + if(rstin) begin + dout <= 10'h0; + cnt <= 5'h0; + end else begin + if (de_reg) begin + if(decision2) begin + dout[9] <=#1 ~q_m_reg[8]; + dout[8] <=#1 q_m_reg[8]; + dout[7:0] <=#1 (q_m_reg[8]) ? q_m_reg[7:0] : ~q_m_reg[7:0]; + + cnt <=#1 (~q_m_reg[8]) ? (cnt + n0q_m - n1q_m) : (cnt + n1q_m - n0q_m); + end else begin + if(decision3) begin + dout[9] <=#1 1'b1; + dout[8] <=#1 q_m_reg[8]; + dout[7:0] <=#1 ~q_m_reg[7:0]; + + cnt <=#1 cnt + {q_m_reg[8], 1'b0} + (n0q_m - n1q_m); + end else begin + dout[9] <=#1 1'b0; + dout[8] <=#1 q_m_reg[8]; + dout[7:0] <=#1 q_m_reg[7:0]; + + cnt <=#1 cnt - {~q_m_reg[8], 1'b0} + (n1q_m - n0q_m); + end + end + end else begin + case ({c1_reg, c0_reg}) + 2'b00: dout <=#1 CTRLTOKEN0; + 2'b01: dout <=#1 CTRLTOKEN1; + 2'b10: dout <=#1 CTRLTOKEN2; + default: dout <=#1 CTRLTOKEN3; + endcase + + cnt <=#1 5'h0; + end + end + end + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/serdes_n_to_1.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/serdes_n_to_1.v new file mode 100644 index 0000000..bc384b6 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/serdes_n_to_1.v @@ -0,0 +1,150 @@ +////////////////////////////////////////////////////////////////////////////// +// +// Xilinx, Inc. 2008 www.xilinx.com +// +////////////////////////////////////////////////////////////////////////////// +// +// File name : serdes_n_to_1.v +// +// Description : 1-bit generic n:1 transmitter module +// Takes in n bits of data and serialises this to 1 bit +// data is transmitted LSB first +// 0, 1, 2 ...... +// +// Date - revision : August 1st 2008 - v 1.0 +// +// Author : NJS +// +// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are +// provided to you "as is". Xilinx and its licensors make and you +// receive no warranties or conditions, express, implied, +// statutory or otherwise, and Xilinx specifically disclaims any +// implied warranties of merchantability, non-infringement,or +// fitness for a particular purpose. Xilinx does not warrant that +// the functions contained in these designs will meet your +// requirements, or that the operation of these designs will be +// uninterrupted or error free, or that defects in the Designs +// will be corrected. Furthermore, Xilinx does not warrantor +// make any representations regarding use or the results of the +// use of the designs in terms of correctness, accuracy, +// reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its +// licensors be liable for any loss of data, lost profits,cost +// or procurement of substitute goods or services, or for any +// special, incidental, consequential, or indirect damages +// arising from the use or operation of the designs or +// accompanying documentation, however caused and on any theory +// of liability. This limitation will apply even if Xilinx +// has been advised of the possibility of such damage. This +// limitation shall apply not-withstanding the failure of the +// essential purpose of any limited remedies herein. +// +// Copyright © 2008 Xilinx, Inc. +// All rights reserved +// +////////////////////////////////////////////////////////////////////////////// +// + +`timescale 1ps/1ps + +module serdes_n_to_1 (ioclk, serdesstrobe, reset, gclk, datain, iob_data_out) ; + +parameter integer SF = 8 ; // Parameter to set the serdes factor 1..8 + +input ioclk ; // IO Clock network +input serdesstrobe ; // Parallel data capture strobe +input reset ; // Reset +input gclk ; // Global clock +input [SF-1 : 0] datain ; // Data for output +output iob_data_out ; // output data + +wire cascade_di ; // +wire cascade_do ; // +wire cascade_ti ; // +wire cascade_to ; // +wire [8:0] mdatain ; // + +genvar i ; // Pad out the input data bus with 0's to 8 bits to avoid errors +generate +for (i = 0 ; i <= (SF - 1) ; i = i + 1) +begin : loop0 +assign mdatain[i] = datain[i] ; +end +endgenerate +generate +for (i = (SF) ; i <= 8 ; i = i + 1) +begin : loop1 +assign mdatain[i] = 1'b0 ; +end +endgenerate + +OSERDES2 #( + .DATA_WIDTH (SF), // SERDES word width. This should match the setting is BUFPLL + .DATA_RATE_OQ ("SDR"), // <SDR>, DDR + .DATA_RATE_OT ("SDR"), // <SDR>, DDR + .SERDES_MODE ("MASTER"), // <DEFAULT>, MASTER, SLAVE + .OUTPUT_MODE ("DIFFERENTIAL")) +oserdes_m ( + .OQ (iob_data_out), + .OCE (1'b1), + .CLK0 (ioclk), + .CLK1 (1'b0), + .IOCE (serdesstrobe), + .RST (reset), + .CLKDIV (gclk), + .D4 (mdatain[7]), + .D3 (mdatain[6]), + .D2 (mdatain[5]), + .D1 (mdatain[4]), + .TQ (), + .T1 (1'b0), + .T2 (1'b0), + .T3 (1'b0), + .T4 (1'b0), + .TRAIN (1'b0), + .TCE (1'b1), + .SHIFTIN1 (1'b1), // Dummy input in Master + .SHIFTIN2 (1'b1), // Dummy input in Master + .SHIFTIN3 (cascade_do), // Cascade output D data from slave + .SHIFTIN4 (cascade_to), // Cascade output T data from slave + .SHIFTOUT1 (cascade_di), // Cascade input D data to slave + .SHIFTOUT2 (cascade_ti), // Cascade input T data to slave + .SHIFTOUT3 (), // Dummy output in Master + .SHIFTOUT4 ()) ; // Dummy output in Master + +OSERDES2 #( + .DATA_WIDTH (SF), // SERDES word width. This should match the setting is BUFPLL + .DATA_RATE_OQ ("SDR"), // <SDR>, DDR + .DATA_RATE_OT ("SDR"), // <SDR>, DDR + .SERDES_MODE ("SLAVE"), // <DEFAULT>, MASTER, SLAVE + .OUTPUT_MODE ("DIFFERENTIAL")) +oserdes_s ( + .OQ (), + .OCE (1'b1), + .CLK0 (ioclk), + .CLK1 (1'b0), + .IOCE (serdesstrobe), + .RST (reset), + .CLKDIV (gclk), + .D4 (mdatain[3]), + .D3 (mdatain[2]), + .D2 (mdatain[1]), + .D1 (mdatain[0]), + .TQ (), + .T1 (1'b0), + .T2 (1'b0), + .T3 (1'b0), + .T4 (1'b0), + .TRAIN (1'b0), + .TCE (1'b1), + .SHIFTIN1 (cascade_di), // Cascade input D from Master + .SHIFTIN2 (cascade_ti), // Cascade input T from Master + .SHIFTIN3 (1'b1), // Dummy input in Slave + .SHIFTIN4 (1'b1), // Dummy input in Slave + .SHIFTOUT1 (), // Dummy output in Slave + .SHIFTOUT2 (), // Dummy output in Slave + .SHIFTOUT3 (cascade_do), // Cascade output D data to Master + .SHIFTOUT4 (cascade_to)) ; // Cascade output T data to Master + +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/vtc_demo.v b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/vtc_demo.v new file mode 100644 index 0000000..2194851 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/rtl/tx/vtc_demo.v @@ -0,0 +1,674 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2009 Xilinx, Inc. +// This design is confidential and proprietary of Xilinx, All Rights Reserved. +////////////////////////////////////////////////////////////////////////////// +// ____ ____ +// / /\/ / +// /___/ \ / Vendor: Xilinx +// \ \ \/ Version: 1.0.0 +// \ \ Filename: vtc_demo.v +// / / Date Created: April 8, 2009 +// /___/ /\ Author: Bob Feng +// \ \ / \ +// \___\/\___\ +// +// Devices: Spartan-6 Generation FPGA +// Purpose: SP601 board demo top level +// Contact: +// Reference: None +// +// Revision History: +// +// +////////////////////////////////////////////////////////////////////////////// +// +// LIMITED WARRANTY AND DISCLAIMER. These designs are provided to you "as is". +// Xilinx and its licensors make and you receive no warranties or conditions, +// express, implied, statutory or otherwise, and Xilinx specifically disclaims +// any implied warranties of merchantability, non-infringement, or fitness for +// a particular purpose. Xilinx does not warrant that the functions contained +// in these designs will meet your requirements, or that the operation of +// these designs will be uninterrupted or error free, or that defects in the +// designs will be corrected. Furthermore, Xilinx does not warrant or make any +// representations regarding use or the results of the use of the designs in +// terms of correctness, accuracy, reliability, or otherwise. +// +// LIMITATION OF LIABILITY. In no event will Xilinx or its licensors be liable +// for any loss of data, lost profits, cost or procurement of substitute goods +// or services, or for any special, incidental, consequential, or indirect +// damages arising from the use or operation of the designs or accompanying +// documentation, however caused and on any theory of liability. This +// limitation will apply even if Xilinx has been advised of the possibility +// of such damage. This limitation shall apply not-withstanding the failure +// of the essential purpose of any limited remedies herein. +// +////////////////////////////////////////////////////////////////////////////// +// Copyright (c) 2009 Xilinx, Inc. +// This design is confidential and proprietary of Xilinx, All Rights Reserved. +////////////////////////////////////////////////////////////////////////////// + +`timescale 1 ps / 1 ps + +module vtc_demo ( + input wire RSTBTN, + + input wire SYS_CLK, + + input wire [3:0] SW, + + output wire [3:0] TMDS, + output wire [3:0] TMDSB, + output wire [3:0] LED, + output wire [1:0] DEBUG +); + + //******************************************************************// + // Create global clock and synchronous system reset. // + //******************************************************************// + wire locked; + wire reset; + + wire clk50m, clk50m_bufg; + + wire pwrup; + + IBUF sysclk_buf (.I(SYS_CLK), .O(sysclk)); + + BUFIO2 #(.DIVIDE_BYPASS("FALSE"), .DIVIDE(2)) + sysclk_div (.DIVCLK(clk50m), .IOCLK(), .SERDESSTROBE(), .I(sysclk)); + + BUFG clk50m_bufgbufg (.I(clk50m), .O(clk50m_bufg)); + + wire pclk_lckd; + +//`ifdef SIMULATION +// assign pwrup = 1'b0; +//`else + SRL16E #(.INIT(16'h1)) pwrup_0 ( + .Q(pwrup), + .A0(1'b1), + .A1(1'b1), + .A2(1'b1), + .A3(1'b1), + .CE(pclk_lckd), + .CLK(clk50m_bufg), + .D(1'b0) + ); +//`endif + + ////////////////////////////////////// + /// Switching screen formats + ////////////////////////////////////// + wire busy; + wire [3:0] sws_sync; //synchronous output + + synchro #(.INITIALIZE("LOGIC0")) + synchro_sws_3 (.async(SW[3]),.sync(sws_sync[3]),.clk(clk50m_bufg)); + + synchro #(.INITIALIZE("LOGIC0")) + synchro_sws_2 (.async(SW[2]),.sync(sws_sync[2]),.clk(clk50m_bufg)); + + synchro #(.INITIALIZE("LOGIC0")) + synchro_sws_1 (.async(SW[1]),.sync(sws_sync[1]),.clk(clk50m_bufg)); + + synchro #(.INITIALIZE("LOGIC0")) + synchro_sws_0 (.async(SW[0]),.sync(sws_sync[0]),.clk(clk50m_bufg)); + + reg [3:0] sws_sync_q; + always @ (posedge clk50m_bufg) + begin + sws_sync_q <= sws_sync; + end + + wire sw0_rdy, sw1_rdy, sw2_rdy, sw3_rdy; + + debnce debsw0 ( + .sync(sws_sync_q[0]), + .debnced(sw0_rdy), + .clk(clk50m_bufg)); + + debnce debsw1 ( + .sync(sws_sync_q[1]), + .debnced(sw1_rdy), + .clk(clk50m_bufg)); + + debnce debsw2 ( + .sync(sws_sync_q[2]), + .debnced(sw2_rdy), + .clk(clk50m_bufg)); + + debnce debsw3 ( + .sync(sws_sync_q[3]), + .debnced(sw3_rdy), + .clk(clk50m_bufg)); + + reg switch = 1'b0; + always @ (posedge clk50m_bufg) + begin + switch <= pwrup | sw0_rdy | sw1_rdy | sw2_rdy | sw3_rdy; + end + + wire gopclk; + SRL16E SRL16E_0 ( + .Q(gopclk), + .A0(1'b1), + .A1(1'b1), + .A2(1'b1), + .A3(1'b1), + .CE(1'b1), + .CLK(clk50m_bufg), + .D(switch) + ); + // The following defparam declaration + defparam SRL16E_0.INIT = 16'h0; + + parameter SW_VGA = 4'b0000; + parameter SW_SVGA = 4'b0001; + parameter SW_XGA = 4'b0011; + parameter SW_HDTV720P = 4'b0010; + parameter SW_SXGA = 4'b1000; + + reg [7:0] pclk_M, pclk_D; + always @ (posedge clk50m_bufg) + begin + if(switch) begin + case (sws_sync_q) + SW_VGA: //25 MHz pixel clock + begin + pclk_M <= 8'd2 - 8'd1; + pclk_D <= 8'd4 - 8'd1; + end + + SW_SVGA: //40 MHz pixel clock + begin + pclk_M <= 8'd4 - 8'd1; + pclk_D <= 8'd5 - 8'd1; + end + + SW_XGA: //65 MHz pixel clock + begin + pclk_M <= 8'd13 - 8'd1; + pclk_D <= 8'd10 - 8'd1; + end + + SW_SXGA: //108 MHz pixel clock + begin + pclk_M <= 8'd54 - 8'd1; + pclk_D <= 8'd25 - 8'd1; + end + + default: //74.25 MHz pixel clock + begin + pclk_M <= 8'd37 - 8'd1; + pclk_D <= 8'd25 - 8'd1; + end + endcase + end + end + + // + // DCM_CLKGEN SPI controller + // + wire progdone, progen, progdata; + dcmspi dcmspi_0 ( + .RST(switch), //Synchronous Reset + .PROGCLK(clk50m_bufg), //SPI clock + .PROGDONE(progdone), //DCM is ready to take next command + .DFSLCKD(pclk_lckd), + .M(pclk_M), //DCM M value + .D(pclk_D), //DCM D value + .GO(gopclk), //Go programme the M and D value into DCM(1 cycle pulse) + .BUSY(busy), + .PROGEN(progen), //SlaveSelect, + .PROGDATA(progdata) //CommandData + ); + + // + // DCM_CLKGEN to generate a pixel clock with a variable frequency + // + wire clkfx, pclk; + DCM_CLKGEN #( + .CLKFX_DIVIDE (21), + .CLKFX_MULTIPLY (31), + .CLKIN_PERIOD(20.000) + ) + PCLK_GEN_INST ( + .CLKFX(clkfx), + .CLKFX180(), + .CLKFXDV(), + .LOCKED(pclk_lckd), + .PROGDONE(progdone), + .STATUS(), + .CLKIN(clk50m), + .FREEZEDCM(1'b0), + .PROGCLK(clk50m_bufg), + .PROGDATA(progdata), + .PROGEN(progen), + .RST(1'b0) + ); + + + wire pllclk0, pllclk1, pllclk2; + wire pclkx2, pclkx10, pll_lckd; + wire clkfbout; + + // + // Pixel Rate clock buffer + // + BUFG pclkbufg (.I(pllclk1), .O(pclk)); + + ////////////////////////////////////////////////////////////////// + // 2x pclk is going to be used to drive OSERDES2 + // on the GCLK side + ////////////////////////////////////////////////////////////////// + BUFG pclkx2bufg (.I(pllclk2), .O(pclkx2)); + + ////////////////////////////////////////////////////////////////// + // 10x pclk is used to drive IOCLK network so a bit rate reference + // can be used by OSERDES2 + ////////////////////////////////////////////////////////////////// + PLL_BASE # ( + .CLKIN_PERIOD(13), + .CLKFBOUT_MULT(10), //set VCO to 10x of CLKIN + .CLKOUT0_DIVIDE(1), + .CLKOUT1_DIVIDE(10), + .CLKOUT2_DIVIDE(5), + .COMPENSATION("INTERNAL") + ) PLL_OSERDES ( + .CLKFBOUT(clkfbout), + .CLKOUT0(pllclk0), + .CLKOUT1(pllclk1), + .CLKOUT2(pllclk2), + .CLKOUT3(), + .CLKOUT4(), + .CLKOUT5(), + .LOCKED(pll_lckd), + .CLKFBIN(clkfbout), + .CLKIN(clkfx), + .RST(~pclk_lckd) + ); + + wire serdesstrobe; + wire bufpll_lock; + BUFPLL #(.DIVIDE(5)) ioclk_buf (.PLLIN(pllclk0), .GCLK(pclkx2), .LOCKED(pll_lckd), + .IOCLK(pclkx10), .SERDESSTROBE(serdesstrobe), .LOCK(bufpll_lock)); + + synchro #(.INITIALIZE("LOGIC1")) + synchro_reset (.async(!pll_lckd),.sync(reset),.clk(pclk)); + +/////////////////////////////////////////////////////////////////////////// +// Video Timing Parameters +/////////////////////////////////////////////////////////////////////////// + //1280x1024@60HZ + parameter HPIXELS_SXGA = 11'd1280; //Horizontal Live Pixels + parameter VLINES_SXGA = 11'd1024; //Vertical Live ines + parameter HSYNCPW_SXGA = 11'd112; //HSYNC Pulse Width + parameter VSYNCPW_SXGA = 11'd3; //VSYNC Pulse Width + parameter HFNPRCH_SXGA = 11'd48; //Horizontal Front Portch + parameter VFNPRCH_SXGA = 11'd1; //Vertical Front Portch + parameter HBKPRCH_SXGA = 11'd248; //Horizontal Front Portch + parameter VBKPRCH_SXGA = 11'd38; //Vertical Front Portch + + //1280x720@60HZ + parameter HPIXELS_HDTV720P = 11'd1280; //Horizontal Live Pixels + parameter VLINES_HDTV720P = 11'd720; //Vertical Live ines + parameter HSYNCPW_HDTV720P = 11'd80; //HSYNC Pulse Width + parameter VSYNCPW_HDTV720P = 11'd5; //VSYNC Pulse Width + parameter HFNPRCH_HDTV720P = 11'd72; //Horizontal Front Portch + parameter VFNPRCH_HDTV720P = 11'd3; //Vertical Front Portch + parameter HBKPRCH_HDTV720P = 11'd216; //Horizontal Front Portch + parameter VBKPRCH_HDTV720P = 11'd22; //Vertical Front Portch + + //1024x768@60HZ + parameter HPIXELS_XGA = 11'd1024; //Horizontal Live Pixels + parameter VLINES_XGA = 11'd768; //Vertical Live ines + parameter HSYNCPW_XGA = 11'd136; //HSYNC Pulse Width + parameter VSYNCPW_XGA = 11'd6; //VSYNC Pulse Width + parameter HFNPRCH_XGA = 11'd24; //Horizontal Front Portch + parameter VFNPRCH_XGA = 11'd3; //Vertical Front Portch + parameter HBKPRCH_XGA = 11'd160; //Horizontal Front Portch + parameter VBKPRCH_XGA = 11'd29; //Vertical Front Portch + + //800x600@60HZ + parameter HPIXELS_SVGA = 11'd800; //Horizontal Live Pixels + parameter VLINES_SVGA = 11'd600; //Vertical Live ines + parameter HSYNCPW_SVGA = 11'd128; //HSYNC Pulse Width + parameter VSYNCPW_SVGA = 11'd4; //VSYNC Pulse Width + parameter HFNPRCH_SVGA = 11'd40; //Horizontal Front Portch + parameter VFNPRCH_SVGA = 11'd1; //Vertical Front Portch + parameter HBKPRCH_SVGA = 11'd88; //Horizontal Front Portch + parameter VBKPRCH_SVGA = 11'd23; //Vertical Front Portch + + //640x480@60HZ + parameter HPIXELS_VGA = 11'd640; //Horizontal Live Pixels + parameter VLINES_VGA = 11'd480; //Vertical Live ines + parameter HSYNCPW_VGA = 11'd96; //HSYNC Pulse Width + parameter VSYNCPW_VGA = 11'd2; //VSYNC Pulse Width + parameter HFNPRCH_VGA = 11'd16; //Horizontal Front Portch + parameter VFNPRCH_VGA = 11'd11; //Vertical Front Portch + parameter HBKPRCH_VGA = 11'd48; //Horizontal Front Portch + parameter VBKPRCH_VGA = 11'd31; //Vertical Front Portch + + reg [10:0] tc_hsblnk; + reg [10:0] tc_hssync; + reg [10:0] tc_hesync; + reg [10:0] tc_heblnk; + reg [10:0] tc_vsblnk; + reg [10:0] tc_vssync; + reg [10:0] tc_vesync; + reg [10:0] tc_veblnk; + + wire [3:0] sws_clk; //clk synchronous output + + synchro #(.INITIALIZE("LOGIC0")) + clk_sws_3 (.async(SW[3]),.sync(sws_clk[3]),.clk(pclk)); + + synchro #(.INITIALIZE("LOGIC0")) + clk_sws_2 (.async(SW[2]),.sync(sws_clk[2]),.clk(pclk)); + + synchro #(.INITIALIZE("LOGIC0")) + clk_sws_1 (.async(SW[1]),.sync(sws_clk[1]),.clk(pclk)); + + synchro #(.INITIALIZE("LOGIC0")) + clk_sws_0 (.async(SW[0]),.sync(sws_clk[0]),.clk(pclk)); + + reg [3:0] sws_clk_sync; //clk synchronous output + always @ (posedge pclk) + begin + sws_clk_sync <= sws_clk; + end + + reg hvsync_polarity; //1-Negative, 0-Positive + always @ (*) + begin + case (sws_clk_sync) + SW_VGA: + begin + hvsync_polarity = 1'b1; + + tc_hsblnk = HPIXELS_VGA - 11'd1; + tc_hssync = HPIXELS_VGA - 11'd1 + HFNPRCH_VGA; + tc_hesync = HPIXELS_VGA - 11'd1 + HFNPRCH_VGA + HSYNCPW_VGA; + tc_heblnk = HPIXELS_VGA - 11'd1 + HFNPRCH_VGA + HSYNCPW_VGA + HBKPRCH_VGA; + tc_vsblnk = VLINES_VGA - 11'd1; + tc_vssync = VLINES_VGA - 11'd1 + VFNPRCH_VGA; + tc_vesync = VLINES_VGA - 11'd1 + VFNPRCH_VGA + VSYNCPW_VGA; + tc_veblnk = VLINES_VGA - 11'd1 + VFNPRCH_VGA + VSYNCPW_VGA + VBKPRCH_VGA; + end + + SW_SVGA: + begin + hvsync_polarity = 1'b0; + + tc_hsblnk = HPIXELS_SVGA - 11'd1; + tc_hssync = HPIXELS_SVGA - 11'd1 + HFNPRCH_SVGA; + tc_hesync = HPIXELS_SVGA - 11'd1 + HFNPRCH_SVGA + HSYNCPW_SVGA; + tc_heblnk = HPIXELS_SVGA - 11'd1 + HFNPRCH_SVGA + HSYNCPW_SVGA + HBKPRCH_SVGA; + tc_vsblnk = VLINES_SVGA - 11'd1; + tc_vssync = VLINES_SVGA - 11'd1 + VFNPRCH_SVGA; + tc_vesync = VLINES_SVGA - 11'd1 + VFNPRCH_SVGA + VSYNCPW_SVGA; + tc_veblnk = VLINES_SVGA - 11'd1 + VFNPRCH_SVGA + VSYNCPW_SVGA + VBKPRCH_SVGA; + end + + SW_XGA: + begin + hvsync_polarity = 1'b1; + + tc_hsblnk = HPIXELS_XGA - 11'd1; + tc_hssync = HPIXELS_XGA - 11'd1 + HFNPRCH_XGA; + tc_hesync = HPIXELS_XGA - 11'd1 + HFNPRCH_XGA + HSYNCPW_XGA; + tc_heblnk = HPIXELS_XGA - 11'd1 + HFNPRCH_XGA + HSYNCPW_XGA + HBKPRCH_XGA; + tc_vsblnk = VLINES_XGA - 11'd1; + tc_vssync = VLINES_XGA - 11'd1 + VFNPRCH_XGA; + tc_vesync = VLINES_XGA - 11'd1 + VFNPRCH_XGA + VSYNCPW_XGA; + tc_veblnk = VLINES_XGA - 11'd1 + VFNPRCH_XGA + VSYNCPW_XGA + VBKPRCH_XGA; + end + + SW_SXGA: + begin + hvsync_polarity = 1'b0; // positive polarity + + tc_hsblnk = HPIXELS_SXGA - 11'd1; + tc_hssync = HPIXELS_SXGA - 11'd1 + HFNPRCH_SXGA; + tc_hesync = HPIXELS_SXGA - 11'd1 + HFNPRCH_SXGA + HSYNCPW_SXGA; + tc_heblnk = HPIXELS_SXGA - 11'd1 + HFNPRCH_SXGA + HSYNCPW_SXGA + HBKPRCH_SXGA; + tc_vsblnk = VLINES_SXGA - 11'd1; + tc_vssync = VLINES_SXGA - 11'd1 + VFNPRCH_SXGA; + tc_vesync = VLINES_SXGA - 11'd1 + VFNPRCH_SXGA + VSYNCPW_SXGA; + tc_veblnk = VLINES_SXGA - 11'd1 + VFNPRCH_SXGA + VSYNCPW_SXGA + VBKPRCH_SXGA; + end + + default: //SW_HDTV720P: + begin + hvsync_polarity = 1'b0; + + tc_hsblnk = HPIXELS_HDTV720P - 11'd1; + tc_hssync = HPIXELS_HDTV720P - 11'd1 + HFNPRCH_HDTV720P; + tc_hesync = HPIXELS_HDTV720P - 11'd1 + HFNPRCH_HDTV720P + HSYNCPW_HDTV720P; + tc_heblnk = HPIXELS_HDTV720P - 11'd1 + HFNPRCH_HDTV720P + HSYNCPW_HDTV720P + HBKPRCH_HDTV720P; + tc_vsblnk = VLINES_HDTV720P - 11'd1; + tc_vssync = VLINES_HDTV720P - 11'd1 + VFNPRCH_HDTV720P; + tc_vesync = VLINES_HDTV720P - 11'd1 + VFNPRCH_HDTV720P + VSYNCPW_HDTV720P; + tc_veblnk = VLINES_HDTV720P - 11'd1 + VFNPRCH_HDTV720P + VSYNCPW_HDTV720P + VBKPRCH_HDTV720P; + end + endcase + end + + wire VGA_HSYNC_INT, VGA_VSYNC_INT; + wire [10:0] bgnd_hcount; + wire bgnd_hsync; + wire bgnd_hblnk; + wire [10:0] bgnd_vcount; + wire bgnd_vsync; + wire bgnd_vblnk; + + timing timing_inst ( + .tc_hsblnk(tc_hsblnk), //input + .tc_hssync(tc_hssync), //input + .tc_hesync(tc_hesync), //input + .tc_heblnk(tc_heblnk), //input + .hcount(bgnd_hcount), //output + .hsync(VGA_HSYNC_INT), //output + .hblnk(bgnd_hblnk), //output + .tc_vsblnk(tc_vsblnk), //input + .tc_vssync(tc_vssync), //input + .tc_vesync(tc_vesync), //input + .tc_veblnk(tc_veblnk), //input + .vcount(bgnd_vcount), //output + .vsync(VGA_VSYNC_INT), //output + .vblnk(bgnd_vblnk), //output + .restart(reset), + .clk(pclk)); + + ///////////////////////////////////////// + // V/H SYNC and DE generator + ///////////////////////////////////////// + assign active = !bgnd_hblnk && !bgnd_vblnk; + + reg active_q; + reg vsync, hsync; + reg VGA_HSYNC, VGA_VSYNC; + reg de; + + always @ (posedge pclk) + begin + hsync <= VGA_HSYNC_INT ^ hvsync_polarity ; + vsync <= VGA_VSYNC_INT ^ hvsync_polarity ; + VGA_HSYNC <= hsync; + VGA_VSYNC <= vsync; + + active_q <= active; + de <= active_q; + end + + /////////////////////////////////// + // Video pattern generator: + // SMPTE HD Color Bar + /////////////////////////////////// + wire [7:0] red_data, green_data, blue_data; + +`ifdef SIMULATION + reg [23:0] pixel_buffer [1279:0]; + reg [23:0] active_pixel; + integer i; + initial begin + for (i = 0; i < 1280; i = i + 1) begin + pixel_buffer[i] = $random(dvi_tb.rx0_seed); + end + + i = 0; + end + + always @ (posedge pclk) begin + if(active_q) begin + active_pixel = pixel_buffer[i]; + i = i + 1; + end else begin + i = 0; + active_pixel = 24'hx; + end + end + + assign {red_data, green_data, blue_data} = active_pixel; +`else + hdcolorbar clrbar( + .i_clk_74M(pclk), + .i_rst(reset), + .i_hcnt(bgnd_hcount), + .i_vcnt(bgnd_vcount), + .baronly(1'b0), + .i_format(2'b00), + .o_r(red_data), + .o_g(green_data), + .o_b(blue_data) + ); +`endif + //////////////////////////////////////////////////////////////// + // DVI Encoder + //////////////////////////////////////////////////////////////// + wire [4:0] tmds_data0, tmds_data1, tmds_data2; + + dvi_encoder enc0 ( + .clkin (pclk), + .clkx2in (pclkx2), + .rstin (reset), + .blue_din (blue_data), + .green_din (green_data), + .red_din (red_data), + .hsync (VGA_HSYNC), + .vsync (VGA_VSYNC), + .de (de), + .tmds_data0 (tmds_data0), + .tmds_data1 (tmds_data1), + .tmds_data2 (tmds_data2)); + + + wire [2:0] tmdsint; + + wire serdes_rst = RSTBTN | ~bufpll_lock; + +//`define DEBUG + +`ifdef DEBUG + + wire [4:0] pattern = 5'b00011; + + serdes_n_to_1 #(.SF(5)) oserdes0 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(serdes_rst), + .gclk(pclkx2), + .datain(pattern), + .iob_data_out(tmdsint[0])) ; + + serdes_n_to_1 #(.SF(5)) oserdes1 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(serdes_rst), + .gclk(pclkx2), + .datain(pattern), + .iob_data_out(tmdsint[1])) ; + + serdes_n_to_1 #(.SF(5)) oserdes2 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(serdes_rst), + .gclk(pclkx2), + .datain(pattern), + .iob_data_out(tmdsint[2])) ; + + OBUFDS TMDS0 (.I(tmdsint[0]), .O(TMDS[0]), .OB(TMDSB[0])) ; + OBUFDS TMDS1 (.I(tmdsint[1]), .O(TMDS[1]), .OB(TMDSB[1])) ; + OBUFDS TMDS2 (.I(tmdsint[2]), .O(TMDS[2]), .OB(TMDSB[2])) ; + +`else + serdes_n_to_1 #(.SF(5)) oserdes0 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(serdes_rst), + .gclk(pclkx2), + .datain(tmds_data0), + .iob_data_out(tmdsint[0])) ; + + serdes_n_to_1 #(.SF(5)) oserdes1 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(serdes_rst), + .gclk(pclkx2), + .datain(tmds_data1), + .iob_data_out(tmdsint[1])) ; + + serdes_n_to_1 #(.SF(5)) oserdes2 ( + .ioclk(pclkx10), + .serdesstrobe(serdesstrobe), + .reset(serdes_rst), + .gclk(pclkx2), + .datain(tmds_data2), + .iob_data_out(tmdsint[2])) ; + + OBUFDS TMDS0 (.I(tmdsint[0]), .O(TMDS[0]), .OB(TMDSB[0])) ; + OBUFDS TMDS1 (.I(tmdsint[1]), .O(TMDS[1]), .OB(TMDSB[1])) ; + OBUFDS TMDS2 (.I(tmdsint[2]), .O(TMDS[2]), .OB(TMDSB[2])) ; +`endif + + reg [4:0] tmdsclkint = 5'b00000; + reg toggle = 1'b0; + + always @ (posedge pclkx2 or posedge serdes_rst) begin + if (serdes_rst) + toggle <= 1'b0; + else + toggle <= ~toggle; + end + + always @ (posedge pclkx2) begin + if (toggle) + tmdsclkint <= 5'b11111; + else + tmdsclkint <= 5'b00000; + end + + wire tmdsclk; + + serdes_n_to_1 #( + .SF (5)) + clkout ( + .iob_data_out (tmdsclk), + .ioclk (pclkx10), + .serdesstrobe (serdesstrobe), + .gclk (pclkx2), + .reset (serdes_rst), + .datain (tmdsclkint)); + + OBUFDS TMDS3 (.I(tmdsclk), .O(TMDS[3]), .OB(TMDSB[3])) ;// clock + + // + // Debug Ports + // + + assign DEBUG[0] = VGA_HSYNC; + assign DEBUG[1] = VGA_VSYNC; + + // LEDs + assign LED = {bufpll_lock, RSTBTN, VGA_HSYNC, VGA_VSYNC} ; +endmodule diff --git a/fpga/spartan6/example/xapp495/dvi_demo/ucf/dvi_demo.ucf b/fpga/spartan6/example/xapp495/dvi_demo/ucf/dvi_demo.ucf new file mode 100644 index 0000000..4a4bb95 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/ucf/dvi_demo.ucf @@ -0,0 +1,112 @@ +########################################### +# Setting VCCAUX for different SP601 board +########################################### +CONFIG VCCAUX = 3.3; + +# +# Constraint for RX0 +# +NET "dvi_rx0/rxclk" TNM_NET = DVI_CLOCK0; +TIMESPEC TS_DVI_CLOCK0 = PERIOD "DVI_CLOCK0" 100 MHz HIGH 50%; + +# +# Constraint for RX1 +# +NET "dvi_rx1/rxclk" TNM_NET = DVI_CLOCK1; +TIMESPEC TS_DVI_CLOCK1 = PERIOD "DVI_CLOCK1" 100 MHz HIGH 50%; + +# +# Multi-cycle paths for TX0 +# +TIMEGRP "bramgrp_0" = RAMS(dvi_tx0/pixel2x/dataint<*>); +TIMEGRP "fddbgrp_0" = FFS(dvi_tx0/pixel2x/db<*>); +TIMEGRP "bramra_0" = FFS(dvi_tx0/pixel2x/ra<*>); + +TIMESPEC "TS_ramdo_0" = FROM "bramgrp_0" TO "fddbgrp_0" TS_DVI_CLOCK0; +TIMESPEC "TS_ramra_0" = FROM "bramra_0" TO "fddbgrp_0" TS_DVI_CLOCK0; + +# +# Multi-cycle paths for TX1 +# +TIMEGRP "bramgrp_1" = RAMS(dvi_tx1/pixel2x/dataint<*>); +TIMEGRP "fddbgrp_1" = FFS(dvi_tx1/pixel2x/db<*>); +TIMEGRP "bramra_1" = FFS(dvi_tx1/pixel2x/ra<*>); + +TIMESPEC "TS_ramdo_1" = FROM "bramgrp_1" TO "fddbgrp_1" TS_DVI_CLOCK1; +TIMESPEC "TS_ramra_1" = FROM "bramra_1" TO "fddbgrp_1" TS_DVI_CLOCK1; + +############################################################################## +# SYSCLK Input +############################################################################## +NET "clk100" LOC = "L15" | IOSTANDARD = LVCMOS33 | PERIOD = 100 MHz; + +############################################################################## +# Mechanical Switches (SW) +############################################################################## +NET "SW<0>" LOC = "A10" | IOSTANDARD = LVCMOS33 ; +NET "SW<1>" LOC = "D14" | IOSTANDARD = LVCMOS33 ; +#NET "SW<2>" LOC = "C14" | IOSTANDARD = LVCMOS33 ; +#NET "SW<3>" LOC = "P15" | IOSTANDARD = LVCMOS33 ; + +############################################ +# TMDS pairs for Atlys top OUT: J2 - Bank 0 +############################################ +NET "TX0_TMDS(3)" LOC = "B6" |IOSTANDARD = TMDS_33 ; # Clock +NET "TX0_TMDSB(3)" LOC = "A6" |IOSTANDARD = TMDS_33 ; +NET "TX0_TMDS(2)" LOC = "B8" |IOSTANDARD = TMDS_33 ; # Red +NET "TX0_TMDSB(2)" LOC = "A8" |IOSTANDARD = TMDS_33 ; +NET "TX0_TMDS(1)" LOC = "C7" |IOSTANDARD = TMDS_33 ; # Green +NET "TX0_TMDSB(1)" LOC = "A7" |IOSTANDARD = TMDS_33 ; +NET "TX0_TMDS(0)" LOC = "D8" |IOSTANDARD = TMDS_33 ; # Blue +NET "TX0_TMDSB(0)" LOC = "C8" |IOSTANDARD = TMDS_33 ; + +############################################## +# TMDS pairs for Atlys top OUT: JA - Bank 2 +# Use TML_33 to add output series termination +############################################## +NET "TX1_TMDS(3)" LOC = "T9" |IOSTANDARD = TML_33; #TMDS_33 ; ## Clock +NET "TX1_TMDSB(3)" LOC = "V9" |IOSTANDARD = TML_33; #TMDS_33 ; # +NET "TX1_TMDS(2)" LOC = "N5" |IOSTANDARD = TML_33; #TMDS_33 ; ## Red +NET "TX1_TMDSB(2)" LOC = "P6" |IOSTANDARD = TML_33; #TMDS_33 ; # +NET "TX1_TMDS(1)" LOC = "T4" |IOSTANDARD = TML_33; #TMDS_33 ; ## Green +NET "TX1_TMDSB(1)" LOC = "V4" |IOSTANDARD = TML_33; #TMDS_33 ; # +NET "TX1_TMDS(0)" LOC = "R3" |IOSTANDARD = TML_33; #TMDS_33 ; ## Blue +NET "TX1_TMDSB(0)" LOC = "T3" |IOSTANDARD = TML_33; #TMDS_33 ; # + +################################################## +# TMDS pairs for Atlys IN (FPGA Bank 1): J3 +################################################## +NET "RX1_TMDS(3)" LOC = "H17" |IOSTANDARD = TMDS_33 ; # CLK +NET "RX1_TMDSB(3)" LOC = "H18" |IOSTANDARD = TMDS_33 ; +NET "RX1_TMDS(2)" LOC = "J16" |IOSTANDARD = TMDS_33 ; # Red +NET "RX1_TMDSB(2)" LOC = "J18" |IOSTANDARD = TMDS_33 ; +NET "RX1_TMDS(1)" LOC = "L17" |IOSTANDARD = TMDS_33 ; # Green +NET "RX1_TMDSB(1)" LOC = "L18" |IOSTANDARD = TMDS_33 ; +NET "RX1_TMDS(0)" LOC = "K17" |IOSTANDARD = TMDS_33 ; # Blue +NET "RX1_TMDSB(0)" LOC = "K18" |IOSTANDARD = TMDS_33 ; + +############################################## +# TMDS pairs for Atlys IN (FPGA Bank 0): J1 +############################################## +NET "RX0_TMDS(3)" LOC = "D11" |IOSTANDARD = TMDS_33 ; # CLK +NET "RX0_TMDSB(3)" LOC = "C11" |IOSTANDARD = TMDS_33 ; +NET "RX0_TMDS(2)" LOC = "B12" |IOSTANDARD = TMDS_33 ; # Red +NET "RX0_TMDSB(2)" LOC = "A12" |IOSTANDARD = TMDS_33 ; +NET "RX0_TMDS(1)" LOC = "B11" |IOSTANDARD = TMDS_33 ; # Green +NET "RX0_TMDSB(1)" LOC = "A11" |IOSTANDARD = TMDS_33 ; +NET "RX0_TMDS(0)" LOC = "G9" |IOSTANDARD = TMDS_33 ; # Blue +NET "RX0_TMDSB(0)" LOC = "F9" |IOSTANDARD = TMDS_33 ; + + +######################################## +# Reset button and LEDs and Mechanical Switches (SW) +######################################## +NET "rstbtn_n" LOC = "T15" | IOSTANDARD = LVCMOS33; +NET "LED<0>" LOC = "U18" | IOSTANDARD = LVCMOS33; +NET "LED<1>" LOC = "M14" | IOSTANDARD = LVCMOS33; +NET "LED<2>" LOC = "N14" | IOSTANDARD = LVCMOS33; +NET "LED<3>" LOC = "L14" | IOSTANDARD = LVCMOS33; +NET "LED<4>" LOC = "M13" | IOSTANDARD = LVCMOS33; +NET "LED<5>" LOC = "D4" | IOSTANDARD = LVCMOS33; +NET "LED<6>" LOC = "P16" | IOSTANDARD = LVCMOS33; +NET "LED<7>" LOC = "N12" | IOSTANDARD = LVCMOS33; diff --git a/fpga/spartan6/example/xapp495/dvi_demo/ucf/vtc_demo.ucf b/fpga/spartan6/example/xapp495/dvi_demo/ucf/vtc_demo.ucf new file mode 100644 index 0000000..c7a94d2 --- /dev/null +++ b/fpga/spartan6/example/xapp495/dvi_demo/ucf/vtc_demo.ucf @@ -0,0 +1,144 @@ +############################################################################## +## Copyright (c) 2009 Xilinx, Inc. +## This design is confidential and proprietary of Xilinx, All Rights Reserved. +############################################################################## +## ____ ____ +## / /\/ / +## /___/ \ / Vendor: Xilinx +## \ \ \/ Version: 1.0.0 +## \ \ Filename: vtc_demo.ucf +## / / Date Created: April, 2009 +## /___/ /\ +## \ \ / \ +## \___\/\___\ +## +## Devices: Spartan-36Generation FPGA +## Purpose: Constraint file for programmable video timing controller +## Contact: bob.feng@xilinx.com +## Reference: None +## +## Revision History: +## +## +############################################################################## +## +## LIMITED WARRANTY AND DISCLAIMER. These designs are provided to you "as is". +## Xilinx and its licensors make and you receive no warranties or conditions, +## express, implied, statutory or otherwise, and Xilinx specifically disclaims +## any implied warranties of merchantability, non-infringement, or fitness for +## a particular purpose. Xilinx does not warrant that the functions contained +## in these designs will meet your requirements, or that the operation of +## these designs will be uninterrupted or error free, or that defects in the +## designs will be corrected. Furthermore, Xilinx does not warrant or make any +## representations regarding use or the results of the use of the designs in +## terms of correctness, accuracy, reliability, or otherwise. +## +## LIMITATION OF LIABILITY. In no event will Xilinx or its licensors be liable +## for any loss of data, lost profits, cost or procurement of substitute goods +## or services, or for any special, incidental, consequential, or indirect +## damages arising from the use or operation of the designs or accompanying +## documentation, however caused and on any theory of liability. This +## limitation will apply even if Xilinx has been advised of the possibility +## of such damage. This limitation shall apply not-withstanding the failure +## of the essential purpose of any limited remedies herein. +## +############################################################################## +## Copyright (c) 2009 Xilinx, Inc. +## This design is confidential and proprietary of Xilinx, All Rights Reserved. +############################################################################## + +########################################### +# Setting VCCAUX for different SP601 board +########################################### +VCCAUX = 3.3; + +######################################## +# Reset button and LEDs +######################################## +NET "RSTBTN" LOC = "N4"; +NET "LED<0>" LOC = "H12"; +NET "LED<1>" LOC = "G13"; +NET "LED<2>" LOC = "E16"; +NET "LED<3>" LOC = "E18"; + +############################################################################## +# SYSCLK Input +############################################################################## + +NET "SYS_CLK" LOC = "L15"; + +############################################################################## +# Mechanical Switches (SW) +############################################################################## + +NET "SW<0>" LOC = "A10" | IOSTANDARD = LVCMOS33 ; +NET "SW<1>" LOC = "D14" | IOSTANDARD = LVCMOS33 ; +NET "SW<2>" LOC = "C14" | IOSTANDARD = LVCMOS33 ; +NET "SW<3>" LOC = "P15" | IOSTANDARD = LVCMOS33 ; + +############################################################################## +# Debug Port # JA1 +############################################################################## +NET "DEBUG[0]" LOC = "B12" | IOSTANDARD = LVCMOS33; +NET "DEBUG[1]" LOC = "B11" | IOSTANDARD = LVCMOS33; + +############################################################################## +# DCM/PLL/BUFPLL positions +############################################################################## +#INST "PCLK_GEN_INST" LOC = "DCM_X0Y3"; +#INST "PLL_OSERDES" LOC = "PLL_ADV_X0Y1"; +#INST "ioclk_buf" LOC = "BUFPLL_X1Y0"; + +########################################### +# Timing Constraints +########################################### +NET "clk50m_bufg" TNM_NET = "TNM_CLK50M"; +TIMESPEC "TS_CLK50M" = PERIOD "TNM_CLK50M" 50 MHz HIGH 50 % PRIORITY 0 ; + +NET "pclk" TNM_NET = "TNM_PCLK"; +TIMESPEC "TS_PCLK" = PERIOD "TNM_PCLK" 108 MHz HIGH 50 % PRIORITY 0 ; + +NET "pclkx2" TNM_NET = "TNM_PCLKX2"; +TIMESPEC "TS_PCLKX2" = PERIOD "TNM_PCLKX2" TS_PCLK * 2; + +NET "pclkx10" TNM_NET = "TNM_PCLKX10"; +TIMESPEC "TS_PCLKX10" = PERIOD "TNM_PCLKX10" TS_PCLK * 10; + +# +# Multi-cycle paths +# +TIMEGRP "bramgrp" = RAMS(enc0/pixel2x/dataint<*>); +TIMEGRP "fddbgrp" = FFS(enc0/pixel2x/db<*>); +TIMEGRP "bramra" = FFS(enc0/pixel2x/ra<*>); + +TIMESPEC "TS_ramdo" = FROM "bramgrp" TO "fddbgrp" TS_PCLK; +TIMESPEC "TS_ramra" = FROM "bramra" TO "fddbgrp" TS_PCLK; + +############################ +# TMDS pairs on the top +############################ +#NET "TMDS(0)" LOC = "C7" | IOSTANDARD = TMDS_33 ; # Blue +#NET "TMDSB(0)" LOC = "A7" | IOSTANDARD = TMDS_33 ; +#NET "TMDS(1)" LOC = "D8" | IOSTANDARD = TMDS_33 ; # Red +#NET "TMDSB(1)" LOC = "C8" | IOSTANDARD = TMDS_33 ; +#NET "TMDS(2)" LOC = "B6" | IOSTANDARD = TMDS_33 ; # Green +#NET "TMDSB(2)" LOC = "A6" | IOSTANDARD = TMDS_33 ; +#NET "TMDS(3)" LOC = "B8" | IOSTANDARD = TMDS_33 ; # Clock +#NET "TMDSB(3)" LOC = "A8" | IOSTANDARD = TMDS_33 ; + +NET "TMDS(0)" LOC = "D8" | IOSTANDARD = TMDS_33 ; # Blue +NET "TMDSB(0)" LOC = "C8" | IOSTANDARD = TMDS_33 ; +NET "TMDS(1)" LOC = "C7" | IOSTANDARD = TMDS_33 ; # Red +NET "TMDSB(1)" LOC = "A7" | IOSTANDARD = TMDS_33 ; +NET "TMDS(2)" LOC = "B8" | IOSTANDARD = TMDS_33 ; # Green +NET "TMDSB(2)" LOC = "A8" | IOSTANDARD = TMDS_33 ; +NET "TMDS(3)" LOC = "B6" | IOSTANDARD = TMDS_33 ; # Clock +NET "TMDSB(3)" LOC = "A6" | IOSTANDARD = TMDS_33 ; + + + + + + + +############################################################################## diff --git a/fpga/spartan6/example/xapp495/readme.txt b/fpga/spartan6/example/xapp495/readme.txt new file mode 100755 index 0000000..5cc5c43 --- /dev/null +++ b/fpga/spartan6/example/xapp495/readme.txt @@ -0,0 +1,102 @@ +*******************************************************************************
+** © Copyright 2010 Xilinx, Inc. All rights reserved.
+** This file contains confidential and proprietary information of Xilinx, Inc. and
+** is protected under U.S. and international copyright and other intellectual property laws.
+*******************************************************************************
+** ____ ____
+** / /\/ /
+** /___/ \ / Vendor: Xilinx
+** \ \ \/
+** \ \ readme.txt Version: 1.0
+** / / Date Last Modified: 11/17/2010
+** /___/ /\ Date Created:
+** \ \ / \ Associated Filename: xapp495.zip
+** \___\/\___\
+**
+** Device:
+** Purpose:
+** Reference: XAPP495.pdf
+** Revision History:
+** 1.0 - Initial Release
+**
+*******************************************************************************
+**
+** Disclaimer:
+**
+** This disclaimer is not a license and does not grant any rights to the materials
+** distributed herewith. Except as otherwise provided in a valid license issued to you
+** by Xilinx, and to the maximum extent permitted by applicable law:
+** (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL FAULTS,
+** AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY,
+** INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, OR
+** FITNESS FOR ANY PARTICULAR PURPOSE; and (2) Xilinx shall not be liable (whether in contract
+** or tort, including negligence, or under any other theory of liability) for any loss or damage
+** of any kind or nature related to, arising under or in connection with these materials,
+** including for any direct, or any indirect, special, incidental, or consequential loss
+** or damage (including loss of data, profits, goodwill, or any type of loss or damage suffered
+** as a result of any action brought by a third party) even if such damage or loss was
+** reasonably foreseeable or Xilinx had been advised of the possibility of the same.
+
+
+** Critical Applications:
+**
+** Xilinx products are not designed or intended to be fail-safe, or for use in any application
+** requiring fail-safe performance, such as life-support or safety devices or systems,
+** Class III medical devices, nuclear facilities, applications related to the deployment of airbags,
+** or any other applications that could lead to death, personal injury, or severe property or
+** environmental damage (individually and collectively, "Critical Applications"). Customer assumes
+** the sole risk and liability of any use of Xilinx products in Critical Applications, subject only
+** to applicable laws and regulations governing limitations on product liability.
+
+** THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE AT ALL TIMES.
+
+*******************************************************************************
+
+This readme describes how to use the files that come with XAPP495
+
+*******************************************************************************
+
+** IMPORTANT NOTES **
+
+1) The design files have been tested on Digilent Atlys Board
+
+2) The UCF files are targeted to the Atlys board
+
+*******************************************************************************
+
+Included files:
+
+DVI transmitter
+
+1. "dvi_demo/rtl/tx/dvi_encoder.v" --- DVI transmitter top module without instantiation of clocking resources
+2. "dvi_demo/rtl/tx/dvi_encoder_top.v" --- DVI transmitter wrapper with instantiation of clocking resources
+3. "dvi_demo/rtl/tx/encode.v" --- DVI encoder
+4. "dvi_demo/rtl/tx/serdes_n_to_1.v" --- configurable to 5:1 serializaer
+5. "dvi_demo/rtl/tx/convert_30to15_fifo.v" --- 30-bit 2:1 gear box
+6. "dvi_demo/rtl/tx/vtc_demo.v" --- Color bar generator with programmable timing controller
+
+DVI Receiver
+
+1. "dvi_demo/rtl/tx/dvi_decoder.v" --- DVI receiver top wrapper
+2. "dvi_demo/rtl/tx/decode.v" --- DVI decoder instantiating the CDR and channel de-skew circuits
+3. "dvi_demo/rtl/tx/chnlbond.v" --- Channel de-skew module
+4. "dvi_demo/rtl/tx/phsaligner.v" --- Bitslip and TMDS data validation state machine
+5. "dvi_demo/rtl/tx/serdes_1_to_5_diff_data.v" --- 1:5 de-serializer
+
+DVI Common Modules
+
+1. "dvi_demo/rtl/common/DRAM16XN.v" --- Width configurable distributed RAM
+2. "dvi_demo/rtl/common/timing.v" --- Video Timing Controller
+3. "dvi_demo/rtl/common/hdclrbar.v" --- SMPTE HD color bar generator
+4. "dvi_demo/rtl/common/debnce.v" --- DIP switch debouncer
+5. "dvi_demo/rtl/common/dcmspi.v" --- DCM_CLKGEN SPI controller
+6. "dvi_demo/rtl/common/synchro.v" --- Clock boundary synchronizer
+
+DVI Evaluation
+
+"dvi_demo/rtl/dvi_demo.v" --- 2x2 DVI Matrix design
+
+UCF
+
+"dvi_demo/ucf/vtc_demo.ucf" --- Transmitter only design with color bar generation and programmable timing controller
+"dvi_demo/ucf/dvi_demo.ucf" --- 2x2 DVI Matrix design
|