  	//******************************************************************************************
    //*  COMPANY    :  TERASIC.  www.terasic.com  (c) 2005 all rights reserved.                *
    //*  NAME       :  ITU-R BT.656 YCrCb 4:2:2 DECODER                                                                *
    //*  Created    :  7/5/2005                                                                *
    //*  Author     :  Joe Yang                                                                *
    //******************************************************************************************

`define sync 8'd101
module itu_r656_decoder 
(
	CLOCK,   //system clock
	TD_D,    //4:2:2 video data stream
 	TD_HS,   //Decoder_hs 
	TD_VS,   //Decoder_vs
	
	Y,       //4:4:4 Y
	Cb,      //4:4:4 Cb
	Cr,      //4:4:4 Cr
	
	Ypix_clock, //Y pixel clock 
    HSx2,       
	VSx1,
	Y_check,
	START,
	COUNTER,
	R,G,B,
	h_tr,
	SW0,SW1,
	blank
);
	input CLOCK;
	input [7:0]TD_D;
 	input TD_HS;
	input TD_VS;
    input SW0;	
    input SW1;	
	
	output [7:0]Y;
	output [7:0]Cb;
	output [7:0]Cr;
	
    output HSx2;
	output VSx1;
	output Ypix_clock;
	
	
//test
	output Y_check;
	output START;
	output [1:0]COUNTER;
	
	
	output [9:0]R;
	output [9:0]G;
	output [9:0]B;
    output h_tr;
    output blank;
	
	reg [7:0]YY;
	reg [7:0]CCb,Cbb;
	reg [7:0]CCr,Crr;
	
    reg  HSx2 ;//TD_HS;
	wire VSx1=TD_VS;
	
	reg[7:0]R1,R2,R3;
	reg[7:0]RR1,RR2,RR3;
	
	wire [7:0]cr={2'b0,Cr[6:1]};
	wire [7:0]cb={3'b0,Cb[6:2]};	
	
 	wire [7:0]Rr=(Y-16)-{1'b0,Cr[7:0]};
 	wire [7:0]Gg=(Y-16)-cr -cb;
 	wire [7:0]Bb=(Y-16)-{1'b0,Cb[7:0]};
  
    wire [9:0]R={Rr,2'b00};
    wire [9:0]G={Gg,2'b00};
    wire [9:0]B={Bb,2'b00};
	
//   
	wire  Y_check=( (R3==8'hff) && (R2==8'h00) && (R1==8'h00) )?1:0;	
	always @(posedge CLOCK) begin
	   RR1=TD_D;
	   RR2=R1;
	   RR3=R2;
	end
	
	always @(negedge CLOCK) begin
	    R1=RR1;
	    R2=RR2;
	    R3=RR3;
	end
	
	reg START,Field;	
	always @(posedge CLOCK) begin
	if (Y_check==1)
	begin
	    START=~TD_D[4];
		Field= TD_D[6];
	end	
	end

	reg [1:0]COUNTER;	
	always @(posedge CLOCK) begin
		if (!START) 
		   COUNTER=0;
			else COUNTER=COUNTER+1;
    end			

    reg Ypix_clock;
	always @(posedge CLOCK) begin
		case (COUNTER)
			0:begin Cbb=TD_D;                  Ypix_clock =0;end
			1:begin YY  =TD_D;CCr=Crr;CCb=Cbb; Ypix_clock =1;end
			2:begin Crr=TD_D;                  Ypix_clock =0;end
			3:begin YY  =TD_D;CCr=Crr;CCb=Cbb; Ypix_clock =1;end			
        endcase 			
    end			



reg [10:0]H_COUNTER;
reg [10:0]RH_COUNTER;
	always @(posedge CLOCK) begin
		if (TD_HS) H_COUNTER=0;		  
			else H_COUNTER=H_COUNTER+1;
    end			

	always @(posedge TD_HS) begin
		RH_COUNTER=H_COUNTER;
    end			
	
    always @(posedge CLOCK) begin
		if (
			((H_COUNTER >= 0) && (H_COUNTER < `sync)) ||		
		    ((H_COUNTER >= RH_COUNTER[10:1]) && (H_COUNTER < (RH_COUNTER[10:1]+`sync+1)))
			)		
		HSx2=0;
		else
		HSx2=1;
    end			

	reg [10:0]h;
	reg h_tr;
	reg h_tr_h;
	
 always @(posedge CLOCK) begin
    if(!HSx2) h=0;
		else
		h=h+1;
    end

   always @(posedge CLOCK) begin
     if ((h< 51) || (h > 771)) 
		h_tr=0;
		else
		h_tr=1;
   end
   always @(posedge CLOCK) begin
     if ((h< 41) || (h > 781))  
		h_tr_h=0;
		else
		h_tr_h=1;
   end

	
wire  [7:0]Yw,YYw;
wire  [7:0]Cwr,CCwr;
wire  [7:0]Cwb,CCwb;

reg [10:0]pcounter_h;
reg [10:0]pcounter_v;

always @(posedge CLOCK) begin
if (!h_tr) pcounter_h=0;
else pcounter_h=pcounter_h+1;
end	

always @(posedge h_tr) begin
if (!TD_VS) pcounter_v=0;
else pcounter_v=pcounter_v+1;
end

wire t=(
//		((pcounter_h >=0) && (pcounter_h < 45)  && (pcounter_v[9:5]==5'b00000)) ||
		((pcounter_h >=0) && (pcounter_h < 90)  && (pcounter_v[9:5]==5'b00001)) ||
		((pcounter_h >=0) && (pcounter_h < 135) && (pcounter_v[9:5]==5'b00010)) ||
		((pcounter_h >=0) && (pcounter_h < 180) && (pcounter_v[9:5]==5'b00011)) ||
		((pcounter_h >=0) && (pcounter_h < 225) && (pcounter_v[9:5]==5'b00100)) ||
		((pcounter_h >=0) && (pcounter_h < 270) && (pcounter_v[9:5]==5'b00101)) ||
		((pcounter_h >=0) && (pcounter_h < 315) && (pcounter_v[9:5]==5'b00110)) ||
		//((pcounter_h >=0) && (pcounter_h < 360) && (pcounter_v[9:5]==5'b00111)) ||
		((pcounter_h >=0) && (pcounter_h < 405) && (pcounter_v[9:5]==5'b01000)) ||
		((pcounter_h >=0) && (pcounter_h < 450) && (pcounter_v[9:5]==5'b01001)) ||
		((pcounter_h >=0) && (pcounter_h < 495) && (pcounter_v[9:5]==5'b01010)) ||
		((pcounter_h >=0) && (pcounter_h < 540) && (pcounter_v[9:5]==5'b01011)) ||
		((pcounter_h >=0) && (pcounter_h < 585) && (pcounter_v[9:5]==5'b01100)) ||
//		((pcounter_h >=0) && (pcounter_h < 630) && (pcounter_v[9:5]==5'b01101)) ||
		((pcounter_h >=0) && (pcounter_h < 675) && (pcounter_v[9:5]==5'b01110)) ||
		((pcounter_h >=0) && (pcounter_h < 720) && (pcounter_v[9:5]==5'b01111)) 		
		)?1:0;
wire [7:0]ym= t? 8'hff:8'h80;
wire [7:0]crm=t? 8'h80:8'h80;
wire [7:0]cbm=t? 8'h80:8'h80;
		
assign	YYw  =((h_tr==1) && (VSx1==1))?Yw : 8'h10;//current set
assign	CCwr =((h_tr==1) && (VSx1==1))?Cwr: 8'h80;
assign	CCwb =((h_tr==1) && (VSx1==1))?Cwb: 8'h80;

wire  [7:0]Ymm  =SW1? ym :Yw ;
wire  [7:0]Crmm =SW1? crm:Cwr;
wire  [7:0]Cbmm =SW1? cbm:Cwb;

reg[10:0]Hde_counter;
reg[10:0]Vde_counter;

always @(posedge CLOCK)begin
	if(HSx2==0)
	  Hde_counter=0;
		else
	  Hde_counter=Hde_counter+1;
end	

always@(posedge  HSx2)begin
if (TD_VS==0)
	  Vde_counter=0;
		else
	  Vde_counter=Vde_counter+1;
end

wire hde=((Hde_counter > 51) && (Hde_counter < 691)) ? 1:0;//720
wire vde=((Vde_counter > 31) && (Vde_counter < 511)) ? 1:0;//480
wire blank_h  = h_tr   & vde;
wire blank  =   h_tr_h & vde;

wire  [7:0]Y  = (blank_h)?Ymm   :8'h10;
wire  [7:0]Cr = (blank_h)?Crmm  :8'h80;
wire  [7:0]Cb = (blank_h)?Cbmm  :8'h80;

dul_port_c1024 YYYR(
	.iDATA(YY[7:0]),
	.iHSYNC(TD_HS),
//	.iHSYNCx2(HSx2),
 	.iHSYNCx2(blank),
	.Y_CLOCK(Ypix_clock),
	.Y_CLOCKx2(CLOCK),
	.oDATA(Yw[7:0]),
	.field(Field),
	.VS(TD_VS)		
);


dul_port_c1024 CBB(
	.iDATA(CCb[7:0]),
	.iHSYNC(TD_HS),
//	.iHSYNCx2(HSx2),
 	.iHSYNCx2(blank),
	.Y_CLOCK(Ypix_clock),
	.Y_CLOCKx2(CLOCK),
	.oDATA(Cwb[7:0]),
	.field(Field),
	.VS(TD_VS)		
);

dul_port_c1024 CRR(
	.iDATA(CCr[7:0]),
	.iHSYNC(TD_HS),
//	.iHSYNCx2(HSx2),
 	.iHSYNCx2(blank),
	.Y_CLOCK(Ypix_clock),
	.Y_CLOCKx2(CLOCK),
	.oDATA(Cwr[7:0]),
	.field(Field),
	.VS(TD_VS)			
);

endmodule
