//------------------------------------------------------------------------------
//
//  dp_main_crtc2.v : displaport main-link display timinig generate module
//
//  LICENSE : "as-is"
//  TakeshiNagashima(T.NG) caramelgete@gmail.com
//------------------------------------------------------------------------------
//  2009/dec/15 release 0.0  
//  2010/jan/28 release 0.1  display timinig generate test
//
//------------------------------------------------------------------------------

module dp_main_crtc2(
	output	[7:0]	TX_RED,			// out   [CRTC] red[7:0]
	output	[7:0]	TX_GRN,			// out   [CRTC] grn[7:0]
	output	[7:0]	TX_BLU,			// out   [CRTC] blu[7:0]
	output			TX_HS,			// out   [CRTC] hsync
	output			TX_VS,			// out   [CRTC] vsync
	output			TX_DE,			// out   [CRTC] de/#blank
	output			TX_CLK,			// out   [CRTC] pixel clock

	input	[23:0]	dp_mvid,		// in    [CRTC] mvid[23:0]
	input	[23:0]	dp_nvid,		// in    [CRTC] nvid[23:0]
	input	[7:0]	dp_maud,		// in    [CRTC] maud[7:0]
	input	[15:0]	dp_htotal,		// in    [CRTC] htotal[15:0]
	input	[15:0]	dp_vtotal,		// in    [CRTC] vtotal[15:0]
	input	[15:0]	dp_hstart,		// in    [CRTC] hstart[15:0]
	input	[15:0]	dp_vstart,		// in    [CRTC] vstart[15:0]
	input	[15:0]	dp_hwidth,		// in    [CRTC] hwidth[15:0]
	input	[15:0]	dp_vheight,		// in    [CRTC] vheight[15:0]
	input	[15:0]	dp_hsync,		// in    [CRTC] hsync[15:0] ({hs_pol,hs_wid[14:0]})
	input	[15:0]	dp_vsync,		// in    [CRTC] vsync[15:0] ({vs_pol,vs_wid[14:0]})
	input	[7:0]	dp_misc0,		// in    [CRTC] misc0[7:0]
	input	[7:0]	dp_misc1,		// in    [CRTC] misc1[7:0]

	output	[8:0]	tbc_data0,		// out   [TBC] data0[8:0]
	output	[8:0]	tbc_data1,		// out   [TBC] data1[8:0]
	output	[8:0]	tbc_data2,		// out   [TBC] data2[8:0]
	output	[8:0]	tbc_data3,		// out   [TBC] data3[8:0]

	input			CLK,			// in    [MAIN] system clock
	input			SYSRST_N		// in    [MAIN] #reset
);


//--------------------------------------------------------------
//  override parameter

	parameter	dp_vbid_vs  =8'b00_0_1_0_0_0_1;	// !de,sync (wo HDCP)
	parameter	dp_vbid_hs  =8'b00_0_1_0_0_0_0;	// de,sync  (wo HDCP)
	parameter	dp_vbid_idle=8'b00_0_1_0_0_0_0;	// blank    (wo HDCP)

	parameter	K237=9'b1_111_10111;
	parameter	K277=9'b1_111_11011;
	parameter	K280=9'b1_000_11100;
	parameter	K281=9'b1_001_11100;
	parameter	K282=9'b1_010_11100;
	parameter	K283=9'b1_011_11100;
	parameter	K284=9'b1_100_11100;
	parameter	K285=9'b1_101_11100;
	parameter	K286=9'b1_110_11100;
	parameter	K287=9'b1_111_11100;
	parameter	K297=9'b1_111_11101;
	parameter	K307=9'b1_111_11110;
	parameter	D102=9'b0_010_01010;
	parameter	D116=9'b0_110_01011;

	localparam	code_bs  =K285;	// defalut symbol blank start
	localparam	code_be  =K277;	// defalut symbol blank end
	localparam	code_ss  =K282;	// defalut symbol secondary start
	localparam	code_se  =K297;	// defalut symbol secondary end
	localparam	code_fs  =K307;	// defalut symbol fill start
	localparam	code_fe  =K237;	// defalut symbol fill end
	localparam	code_sr  =K280;	// defalut symbol scramble reset
	localparam	code_cpbs=K281;	// defalut symbol content protection bs
	localparam	code_cpsr=K283;	// defalut symbol content protection sr

	localparam	code_ebs =K285;	// enhanced symbol blank start
	localparam	code_ebe =K277;	// enhanced symbol blank end
	localparam	code_ess =K282;	// enhanced symbol secondary start
	localparam	code_ese =K297;	// enhanced symbol secondary end
	localparam	code_efs =K307;	// enhanced symbol fill start
	localparam	code_efe =K237;	// enhanced symbol fill end
	localparam	code_esr =K280;	// enhanced symbol scramble reset
	localparam	code_ecp =K281;	// enhanced symbol content protection
	localparam	code_ebf =K283;	// enhanced symbol 

//--------------------------------------------------------------
//  local parameter

//--------------------------------------------------------------
//  signal

//--------------------------------------------------------------
//  design

//	wire	[9:0] TX_RED;
//	wire	[9:0] TX_GRN;
//	wire	[9:0] TX_BLU;
//	wire	TX_HS;
//	wire	TX_VS;
//	wire	TX_DE;
//	wire	TX_CLK;

	wire	[31:0] disp_data_out;
	wire	disp_hsync_out_n;
	wire	disp_vsync_out_n;
	wire	disp_blank_out_n;
	wire	disp_dclk_out;

	wire	[31:0] disp_data_out_w;
	reg		[31:0] disp_data_out_r;
	wire	[7:0] disp_hsync_out_n_w;
	reg		[7:0] disp_hsync_out_n_r;
	wire	[7:0] disp_vsync_out_n_w;
	reg		[7:0] disp_vsync_out_n_r;
	wire	[7:0] disp_blank_out_n_w;
	reg		[7:0] disp_blank_out_n_r;

	wire	[11:0] disp_hcount_w;
	reg		[11:0] disp_hcount_r;
	wire	[11:0] disp_vcount_w;
	reg		[11:0] disp_vcount_r;
	wire	[11:0] disp_hcount_inc;
	wire	[11:0] disp_vcount_inc;
	wire	disp_hcount_end;
	wire	[7:0] disp_htiming_w;
	reg		[7:0] disp_htiming_r;
	wire	disp_vcount_end;
	wire	[7:0] disp_vtiming_w;
	reg		[7:0] disp_vtiming_r;

	wire	disp_hsync_n_w;
	reg		disp_hsync_n_r;
	wire	disp_vsync_n_w;
	reg		disp_vsync_n_r;
	wire	disp_hblank_n_w;
	reg		disp_hblank_n_r;
	wire	disp_vblank_n_w;
	reg		disp_vblank_n_r;
	wire	disp_vnext_w;
	reg		disp_vnext_r;
	wire	disp_blank_n_w;
	reg		disp_blank_n_r;

	// ---- display timing output ----

	assign TX_RED[7:0]=disp_data_out[23:16];
	assign TX_GRN[7:0]=disp_data_out[15:8];
	assign TX_BLU[7:0]=disp_data_out[7:0];

	assign TX_HS=disp_hsync_out_n;
	assign TX_VS=disp_vsync_out_n;
	assign TX_DE=disp_blank_out_n;
	assign TX_CLK=disp_dclk_out;

	// ---- dipslay timing generate ----

	wire	disp_dclk_sync;

	wire	[23:0] disp_dclk_w;
	wire	disp_dclk_sync_w;
	wire	[23:0] disp_reg_dclk_w;
	reg		[23:0] disp_dclk_r;
	reg		disp_dclk_sync_r;
	reg		[23:0] disp_reg_dclk_r;

	reg		[15:0] disp_reg_hcount_sbp_r;
	reg		[15:0] disp_reg_hcount_sav_r;
	reg		[15:0] disp_reg_hcount_eav_r;
	reg		[15:0] disp_reg_hcount_end_r;
	reg		[15:0] disp_reg_vcount_sbp_r;
	reg		[15:0] disp_reg_vcount_sav_r;
	reg		[15:0] disp_reg_vcount_eav_r;
	reg		[15:0] disp_reg_vcount_end_r;
	reg		[15:0] disp_reg_hsize_r;
	reg		[15:0] disp_reg_vsize_r;

	wire	disp_hcount_sbp;
	wire	disp_hcount_sav;
	wire	disp_hcount_de1;
	wire	disp_hcount_eav;
	wire	disp_vcount_sbp;
	wire	disp_vcount_sav;
	wire	disp_vcount_eav;

	assign disp_dclk_out=disp_dclk_sync_r;
	assign disp_dclk_sync=disp_dclk_sync_r;

	assign disp_hcount_sbp=disp_htiming_r[1];
	assign disp_hcount_sav=disp_htiming_r[3];
	assign disp_hcount_de1=disp_htiming_r[2];
	assign disp_hcount_eav=disp_htiming_r[4];
	assign disp_vcount_sbp=disp_vtiming_r[1];
	assign disp_vcount_sav=disp_vtiming_r[3];
	assign disp_vcount_eav=disp_vtiming_r[4];

	assign disp_data_out[31:0]=32'b0;
	assign disp_hsync_out_n=disp_hsync_n_r;
	assign disp_vsync_out_n=disp_vsync_n_r;
	assign disp_blank_out_n=disp_blank_n_r;

	always @(posedge CLK or negedge SYSRST_N)
	begin
		if (SYSRST_N==1'b0)
			begin
				disp_dclk_r[23:0] <= 24'b0;
				disp_dclk_sync_r <= 1'b0;
				disp_reg_dclk_r[23:0] <= 24'b0;
				disp_reg_hcount_sbp_r[15:0] <= 12'b0;
				disp_reg_hcount_sav_r[15:0] <= 12'b0;
				disp_reg_hcount_eav_r[15:0] <= 12'b0;
				disp_reg_hcount_end_r[15:0] <= 12'b0;
				disp_reg_vcount_sbp_r[15:0] <= 12'b0;
				disp_reg_vcount_sav_r[15:0] <= 12'b0;
				disp_reg_vcount_eav_r[15:0] <= 12'b0;
				disp_reg_vcount_end_r[15:0] <= 12'b0;
				disp_reg_hsize_r[15:0] <= 12'b0;
				disp_reg_vsize_r[15:0] <= 12'b0;
			end
		else
			begin
				disp_dclk_r[23:0] <= disp_dclk_w[23:0];
				disp_dclk_sync_r <= disp_dclk_sync_w;
				disp_reg_dclk_r[23:0] <= dp_mvid[23:0];
				disp_reg_hcount_sbp_r[15:0] <= dp_hsync[15:0]-16'h001;
				disp_reg_hcount_sav_r[15:0] <= dp_hstart[15:0]-16'h001;
				disp_reg_hcount_eav_r[15:0] <= dp_hstart[15:0]+dp_hwidth[15:0]-16'h001;
				disp_reg_hcount_end_r[15:0] <= dp_htotal[15:0]-16'h001;
				disp_reg_vcount_sbp_r[15:0] <= dp_vsync[15:0]-16'h001;
				disp_reg_vcount_sav_r[15:0] <= dp_vstart[15:0]-16'h001;
				disp_reg_vcount_eav_r[15:0] <= dp_vstart[15:0]+dp_vheight[15:0]-16'h001;
				disp_reg_vcount_end_r[15:0] <= dp_vtotal[15:0]-16'h001;
				disp_reg_hsize_r[15:0] <= dp_hwidth[15:0];
				disp_reg_vsize_r[15:0] <= dp_vheight[15:0];
			end
	end

	wire	[24:0] disp_dclk_add;

	assign disp_dclk_add[24:0]={1'b0,disp_dclk_r[23:0]}+{1'b0,disp_reg_dclk_r[23:0]};

	assign disp_dclk_w[23:0]={9'b0,disp_dclk_add[14:0]};
	assign disp_dclk_sync_w=(disp_dclk_add[15]==2'b0) ? 1'b0 : 1'b1;

	always @(posedge CLK or negedge SYSRST_N)
	begin
		if (SYSRST_N==1'b0)
			begin
				disp_hcount_r[11:0] <= 12'h001;
				disp_htiming_r[7:0] <= 8'h00;
				disp_vcount_r[11:0] <= 12'h000;
				disp_vtiming_r[7:0] <= 8'h00;
				disp_hsync_n_r <= 1'b0;
				disp_vsync_n_r <= 1'b0;
				disp_hblank_n_r <= 1'b0;
				disp_vblank_n_r <= 1'b0;
				disp_vnext_r <= 1'b0;
				disp_blank_n_r <= 1'b0;
			end
		else
			begin
				disp_hcount_r[11:0] <= disp_hcount_w[11:0];
				disp_htiming_r[7:0] <= disp_htiming_w[7:0];
				disp_vcount_r[11:0] <= disp_vcount_w[11:0];
				disp_vtiming_r[7:0] <= disp_vtiming_w[7:0];
				disp_hsync_n_r <= disp_hsync_n_w;
				disp_vsync_n_r <= disp_vsync_n_w;
				disp_hblank_n_r <= disp_hblank_n_w;
				disp_vblank_n_r <= disp_vblank_n_w;
				disp_vnext_r <= disp_vnext_w;
				disp_blank_n_r <= disp_blank_n_w;
			end
	end

	assign disp_hcount_inc[11:0]=(disp_dclk_sync==1'b1) ? disp_hcount_r[11:0]+12'h001 : disp_hcount_r[11:0];
	assign disp_vcount_inc[11:0]=(disp_dclk_sync==1'b1) ? disp_vcount_r[11:0]+12'h001 : disp_vcount_r[11:0];

	assign disp_hcount_end=(disp_dclk_sync==1'b1) & (disp_htiming_r[7]==1'b1) ? 1'b1 : 1'b0;
	assign disp_vcount_end=(disp_dclk_sync==1'b1) & (disp_vtiming_r[7]==1'b1) ? 1'b1 : 1'b0;

	assign disp_hcount_w[11:0]=
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) ? 12'h001 :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b0) ? disp_hcount_inc[11:0] :
			(disp_dclk_sync==1'b0) ? disp_hcount_r[11:0] :
			12'h001;

	assign disp_vcount_w[11:0]=
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) & (disp_vcount_end==1'b1) ? 12'h000 :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) & (disp_vcount_end==1'b0) ? disp_vcount_inc[11:0] :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b0) ? disp_vcount_r[11:0] :
			(disp_dclk_sync==1'b0) ? disp_vcount_r[11:0] :
			12'h000;

	assign disp_htiming_w[0]=1'b0;
	assign disp_htiming_w[1]=
			(disp_dclk_sync==1'b1) & (disp_hcount_r[11:0]==disp_reg_hcount_sbp_r[11:0]) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_hcount_r[11:0]!=disp_reg_hcount_sbp_r[11:0]) ? 1'b0 :
			(disp_dclk_sync==1'b0) ? disp_htiming_r[1] :
			1'b0;
	assign disp_htiming_w[2]=(disp_dclk_sync==1'b1) ? disp_htiming_r[3] : disp_htiming_r[2];
	assign disp_htiming_w[3]=
			(disp_dclk_sync==1'b1) & (disp_hcount_r[11:0]==disp_reg_hcount_sav_r[11:0]) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_hcount_r[11:0]!=disp_reg_hcount_sav_r[11:0]) ? 1'b0 :
			(disp_dclk_sync==1'b0) ? disp_htiming_r[3] :
			1'b0;
	assign disp_htiming_w[4]=
			(disp_dclk_sync==1'b1) & (disp_hcount_r[11:0]==disp_reg_hcount_eav_r[11:0]) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_hcount_r[11:0]!=disp_reg_hcount_eav_r[11:0]) ? 1'b0 :
			(disp_dclk_sync==1'b0) ? disp_htiming_r[4] :
			1'b0;
	assign disp_htiming_w[5]=1'b0;
	assign disp_htiming_w[6]=1'b0;
	assign disp_htiming_w[7]=
			(disp_dclk_sync==1'b1) & (disp_hcount_r[11:0]==disp_reg_hcount_end_r[11:0]) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_hcount_r[11:0]!=disp_reg_hcount_end_r[11:0]) ? 1'b0 :
			(disp_dclk_sync==1'b0) ? disp_htiming_r[7] :
			1'b0;

	assign disp_vtiming_w[0]=1'b0;
	assign disp_vtiming_w[1]=
			(disp_dclk_sync==1'b1) & (disp_vcount_r[11:0]==disp_reg_vcount_sbp_r[11:0]) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_vcount_r[11:0]!=disp_reg_vcount_sbp_r[11:0]) ? 1'b0 :
			(disp_dclk_sync==1'b0) ? disp_vtiming_r[1] :
			1'b0;
	assign disp_vtiming_w[2]=1'b0;
	assign disp_vtiming_w[3]=
			(disp_dclk_sync==1'b1) & (disp_vcount_r[11:0]==disp_reg_vcount_sav_r[11:0]) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_vcount_r[11:0]!=disp_reg_vcount_sav_r[11:0]) ? 1'b0 :
			(disp_dclk_sync==1'b0) ? disp_vtiming_r[3] :
			1'b0;
	assign disp_vtiming_w[4]=
			(disp_dclk_sync==1'b1) & (disp_vcount_r[11:0]==disp_reg_vcount_eav_r[11:0]) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_vcount_r[11:0]!=disp_reg_vcount_eav_r[11:0]) ? 1'b0 :
			(disp_dclk_sync==1'b0) ? disp_vtiming_r[4] :
			1'b0;
	assign disp_vtiming_w[5]=1'b0;
	assign disp_vtiming_w[6]=1'b0;
	assign disp_vtiming_w[7]=
			(disp_dclk_sync==1'b1) & (disp_vcount_r[11:0]==disp_reg_vcount_end_r[11:0]) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_vcount_r[11:0]!=disp_reg_vcount_end_r[11:0]) ? 1'b0 :
			(disp_dclk_sync==1'b0) ? disp_vtiming_r[7] :
			1'b0;

	assign disp_hsync_n_w=
			(disp_dclk_sync==1'b1) & (disp_htiming_r[7]==1'b1) ? 1'b0 :
			(disp_dclk_sync==1'b1) & (disp_htiming_r[7]==1'b0) & (disp_htiming_r[1]==1'b1) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_htiming_r[7]==1'b0) & (disp_htiming_r[1]==1'b0) ? disp_hsync_n_r :
			(disp_dclk_sync==1'b0) ? disp_hsync_n_r :
			1'b0;

	assign disp_vsync_n_w=
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) & (disp_vtiming_r[7]==1'b1) ? 1'b0 :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) & (disp_vtiming_r[7]==1'b0) & (disp_vtiming_r[1]==1'b1) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) & (disp_vtiming_r[7]==1'b0) & (disp_vtiming_r[1]==1'b0) ? disp_vsync_n_r :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b0) ? disp_vsync_n_r :
			(disp_dclk_sync==1'b0) ? disp_vsync_n_r :
			1'b0;

	assign disp_hblank_n_w=
			(disp_dclk_sync==1'b1) & (disp_htiming_r[4]==1'b1) ? 1'b0 :
			(disp_dclk_sync==1'b1) & (disp_htiming_r[4]==1'b0) & (disp_htiming_r[3]==1'b1) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_htiming_r[4]==1'b0) & (disp_htiming_r[3]==1'b0) ? disp_hblank_n_r :
			(disp_dclk_sync==1'b0) ? disp_hblank_n_r :
			1'b0;

	assign disp_vblank_n_w=
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) & (disp_vtiming_r[4]==1'b1) ? 1'b0 :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) & (disp_vtiming_r[4]==1'b0) & (disp_vtiming_r[3]==1'b1) ? 1'b1 :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) & (disp_vtiming_r[4]==1'b0) & (disp_vtiming_r[3]==1'b0) ? disp_vblank_n_r :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b0) ? disp_vblank_n_r :
			(disp_dclk_sync==1'b0) ? disp_vblank_n_r :
			1'b0;

	assign disp_vnext_w=
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) & (disp_vblank_n_r==1'b0) ? 1'b0 :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b1) & (disp_vblank_n_r==1'b1) ? !disp_vnext_r :
			(disp_dclk_sync==1'b1) & (disp_hcount_end==1'b0) ? disp_vnext_r :
			(disp_dclk_sync==1'b0) ? disp_vnext_r :
			1'b0;

	assign disp_blank_n_w=
			(disp_dclk_sync==1'b1) &  ((disp_hblank_n_w==1'b0) | (disp_vblank_n_w==1'b0)) ? 1'b0 :
			(disp_dclk_sync==1'b1) & !((disp_hblank_n_w==1'b0) | (disp_vblank_n_w==1'b0)) ? 1'b1 :
			(disp_dclk_sync==1'b0) ? disp_blank_n_r :
			1'b1;

	// ---- ----

	// ---- ----

	wire	[287:0] tbc_disp_de24_32;
	wire	[287:0] tbc_disp24_32;

	wire	[287:0] tbc_disp_de;
	wire	[287:0] tbc_disp;
	wire	[287:0] tbc_disp_hs;
	wire	[287:0] tbc_disp_vs;
	wire	[287:0] tbc_sync_vs;
	wire	[287:0] tbc_disp_hs_bs1;
	wire	[287:0] tbc_disp_vs_bs1;
	wire	[287:0] tbc_sync_vs_bs1;
	wire	[287:0] tbc_sync_ss0;
	wire	[287:0] tbc_sync_ss1;

	assign tbc_disp_de[287:0]=tbc_disp_de24_32[287:0];
	assign tbc_disp[287:0]=tbc_disp24_32[287:0];
	assign tbc_disp_hs[287:0]=tbc_disp_hs_bs1[287:0];
	assign tbc_disp_vs[287:0]=tbc_disp_vs_bs1[287:0];
	assign tbc_sync_vs[287:0]=tbc_sync_vs_bs1[287:0];


	assign tbc_disp_de24_32[287:0]={
			9'b0,9'b0,9'b0,9'b0,			// 28
			9'b0,9'b0,9'b0,9'b0,			// 24
			9'b0,9'b0,9'b0,9'b0,			// 20
			9'b0,9'b0,9'b0,9'b0,			// 16
			9'b0,9'b0,9'b0,					// 13
			code_fs[8:0],					// 12
			9'h0ff,9'h0ff,					// 10
			9'h0ff,9'h0ff,					// 8
			9'h0ff,9'h0ff,					// 6
			9'h0ff,9'h0ff,					// 4
			code_be[8:0],					// 3
			9'h0,							// 2
			9'h0,							// 1
			9'b0};							// 0
	assign tbc_disp24_32[287:0]={
			9'b0,9'b0,9'b0,9'b0,			// 28
			9'b0,9'b0,9'b0,9'b0,			// 24
			9'b0,9'b0,9'b0,9'b0,			// 20
			9'b0,9'b0,9'b0,9'b0,			// 16
			9'b0,9'b0,9'b0,					// 13
			code_fs[8:0],					// 12
			9'h0ff,9'h0ff,					// 10
			9'h0ff,9'h0ff,					// 8
			9'h0ff,9'h0ff,					// 6
			9'h0ff,9'h0ff,					// 4
			code_fe[8:0],					// 3
			9'h0,							// 2
			9'h0,							// 1
			9'b0};							// 0

	assign tbc_disp_hs_bs1[287:0]={
			9'b0,9'b0,9'b0,9'b0,			// 28
			9'b0,9'b0,9'b0,9'b0,			// 24
			9'b0,9'b0,9'b0,9'b0,			// 20
			9'b0,9'b0,9'b0,9'b0,			// 16
			1'b0,dp_maud[7:0],				// 15
			1'b0,dp_mvid[7:0],				// 14
			1'b0,dp_vbid_hs[7:0],			// 13
			code_bs[8:0],					// 12
			9'h0ff,9'h0ff,					// 10
			9'h0ff,9'h0ff,					// 8
			9'h0ff,9'h0ff,					// 6
			9'h0ff,9'h0ff,					// 4
			code_fe[8:0],					// 3
			9'h0,							// 2
			9'h0,							// 1
			9'b0};							// 0
	assign tbc_disp_vs_bs1[287:0]={
			9'b0,9'b0,9'b0,9'b0,			// 28
			9'b0,9'b0,9'b0,9'b0,			// 24
			9'b0,9'b0,9'b0,9'b0,			// 20
			9'b0,9'b0,9'b0,9'b0,			// 16
			1'b0,dp_maud[7:0],				// 15
			1'b0,dp_mvid[7:0],				// 14
			1'b0,dp_vbid_vs[7:0],			// 13
			code_bs[8:0],					// 12
			9'h0ff,9'h0ff,					// 10
			9'h0ff,9'h0ff,					// 8
			9'h0ff,9'h0ff,					// 6
			9'h0ff,9'h0ff,					// 4
			code_fe[8:0],					// 3
			9'h0,							// 2
			9'h0,							// 1
			9'b0};							// 0
	assign tbc_sync_vs_bs1[287:0]={
			9'b0,9'b0,9'b0,9'b0,			// 28
			9'b0,9'b0,9'b0,9'b0,			// 24
			9'b0,9'b0,9'b0,9'b0,			// 20
			9'b0,9'b0,9'b0,9'b0,			// 16
			1'b0,dp_maud[7:0],				// 15
			1'b0,dp_mvid[7:0],				// 14
			1'b0,dp_vbid_vs[7:0],			// 13
			code_bs[8:0],					// 12
			9'h0,9'h0,						// 10
			9'h0,9'h0,						// 8
			9'h0,9'h0,						// 6
			9'h0,9'h0,						// 4
			9'h0,							// 3
			9'h0,							// 2
			9'h0,							// 1
			9'b0};							// 0

	assign tbc_sync_ss0[287:0]={
			9'b0,9'b0,9'b0,9'b0,			// 28
			9'b0,9'b0,9'b0,9'b0,			// 24
			9'b0,9'b0,						// 22
			code_se[8:0],					// 21
			9'b0,							// 20
			9'b0,							// 19
			1'b0,dp_vheight[7:0],			// 18
			1'b0,dp_vheight[15:8],			// 17
			1'b0,dp_hwidth[7:0],			// 16
			1'b0,dp_hwidth[15:8],			// 15
			1'b0,dp_mvid[7:0],				// 14
			1'b0,dp_mvid[15:8],				// 13
			1'b0,dp_mvid[23:16],			// 12
			1'b0,dp_hsync[7:0],				// 11
			1'b0,dp_hsync[15:8],			// 10
			1'b0,dp_vtotal[7:0],			// 9
			1'b0,dp_vtotal[15:8],			// 8
			1'b0,dp_htotal[7:0],			// 7
			1'b0,dp_htotal[15:8],			// 6
			1'b0,dp_mvid[7:0],				// 5
			1'b0,dp_mvid[15:8],				// 4
			1'b0,dp_mvid[23:16],			// 3
			code_ss[8:0],					// 2
			code_ss[8:0],					// 1
			9'b0};							// 0

	assign tbc_sync_ss1[287:0]={
			9'b0,9'b0,9'b0,9'b0,			// 28
			9'b0,9'b0,9'b0,9'b0,			// 24
			9'b0,9'b0,						// 22
			code_se[8:0],					// 21
			9'b0,							// 20
			1'b0,dp_misc1[7:0],				// 19
			1'b0,dp_misc0[7:0],				// 18
			1'b0,dp_nvid[7:0],				// 17
			1'b0,dp_nvid[15:8],				// 16
			1'b0,dp_nvid[23:16],			// 15
			1'b0,dp_mvid[7:0],				// 14
			1'b0,dp_mvid[15:8],				// 13
			1'b0,dp_mvid[23:16],			// 12
			1'b0,dp_vsync[7:0],				// 11
			1'b0,dp_vsync[15:8],			// 10
			1'b0,dp_vstart[7:0],			// 9
			1'b0,dp_vstart[15:8],			// 8
			1'b0,dp_hstart[7:0],			// 7
			1'b0,dp_hstart[15:8],			// 6
			1'b0,dp_mvid[7:0],				// 5
			1'b0,dp_mvid[15:8],				// 4
			1'b0,dp_mvid[23:16],			// 3
			code_ss[8:0],					// 2
			code_ss[8:0],					// 1
			9'b0};							// 0

	wire	[3:0] tbc_sync_w;
	wire	tbc_clr_w;
	wire	tbc_sync_ss_w;
	wire	[7:0] tbc_count_w;
	wire	tbc_count_sync_w;
	wire	tbc_de1_w;
	wire	[7:0] tbc_dcount_w;
	wire	[15:0] tbc_xcount_w;
	wire	[15:0] tbc_vcount_w;
	wire	tbc_dcount_sync_w;
	wire	[287:0] tbc_data0_out_w;
	wire	[287:0] tbc_data1_out_w;
	wire	[287:0] tbc_data2_out_w;
	wire	[287:0] tbc_data3_out_w;
	reg		[3:0] tbc_sync_r;
	reg		tbc_clr_r;
	reg		tbc_sync_ss_r;
	reg		[7:0] tbc_count_r;
	reg		tbc_count_sync_r;
	reg		tbc_de1_r;
	reg		[7:0] tbc_dcount_r;
	reg		[15:0] tbc_xcount_r;
	reg		[15:0] tbc_vcount_r;
	reg		tbc_dcount_sync_r;
	reg		[287:0] tbc_data0_out_r;
	reg		[287:0] tbc_data1_out_r;
	reg		[287:0] tbc_data2_out_r;
	reg		[287:0] tbc_data3_out_r;

	assign tbc_data0[8:0]=tbc_data0_out_r[8:0];
	assign tbc_data1[8:0]=tbc_data1_out_r[8:0];
	assign tbc_data2[8:0]=tbc_data2_out_r[8:0];
	assign tbc_data3[8:0]=tbc_data3_out_r[8:0];

	always @(posedge CLK or negedge SYSRST_N)
	begin
		if (SYSRST_N==1'b0)
			begin
				tbc_sync_r[3:0] <= 4'b0;
				tbc_clr_r <= 1'b0;
				tbc_sync_ss_r <= 1'b0;
				tbc_count_r[7:0] <= 8'b0;
				tbc_count_sync_r <= 1'b0;
				tbc_de1_r <= 1'b0;
				tbc_dcount_r[7:0] <= 8'b0;
				tbc_xcount_r[15:0] <= 16'b0;
				tbc_vcount_r[15:0] <= 16'b0;
				tbc_dcount_sync_r <= 1'b0;
				tbc_data0_out_r[287:0] <= 288'b0;
				tbc_data1_out_r[287:0] <= 288'b0;
				tbc_data2_out_r[287:0] <= 288'b0;
				tbc_data3_out_r[287:0] <= 288'b0;
			end
		else
			begin
				tbc_sync_r[3:0] <= tbc_sync_w[3:0];
				tbc_clr_r <= tbc_clr_w;
				tbc_sync_ss_r <= tbc_sync_ss_w;
				tbc_count_r[7:0] <= tbc_count_w[7:0];
				tbc_count_sync_r <= tbc_count_sync_w;
				tbc_de1_r <= tbc_de1_w;
				tbc_dcount_r[7:0] <= tbc_dcount_w[7:0];
				tbc_xcount_r[15:0] <= tbc_xcount_w[15:0];
				tbc_vcount_r[15:0] <= tbc_vcount_w[15:0];
				tbc_dcount_sync_r <= tbc_dcount_sync_w;
				tbc_data0_out_r[287:0] <= tbc_data0_out_w[287:0];
				tbc_data1_out_r[287:0] <= tbc_data1_out_w[287:0];
				tbc_data2_out_r[287:0] <= tbc_data2_out_w[287:0];
				tbc_data3_out_r[287:0] <= tbc_data3_out_w[287:0];
			end
	end

	wire	tbc_de;
	wire	tbc_vs;
	wire	tbc_eav;
	wire	tbc_sav;
	wire	tbc_de1;
	wire	tbc_unit;

	assign tbc_de=disp_blank_n_r;
	assign tbc_vs=disp_vblank_n_r;
	assign tbc_eav=disp_hcount_eav;
	assign tbc_sav=disp_hcount_sav;
	assign tbc_de1=disp_hcount_de1;
	assign tbc_vend=disp_vcount_eav;
	assign tbc_unit=tbc_count_sync_r;
	assign tbc_dclk=disp_dclk_sync;

	assign tbc_sync_w[3:0]=
			(tbc_de==1'b1) & (tbc_de1_r==1'b0) & (tbc_unit==1'b1) ? 4'b0001 :	// transfer unit + be
			(tbc_de==1'b1) & (tbc_de1_r==1'b0) & (tbc_unit==1'b0) ? 4'b0001 :	// transfer unit + be
			(tbc_de==1'b1) & (tbc_de1_r==1'b1) & (tbc_eav==1'b0) & (tbc_unit==1'b1) ? 4'b0010 :	// transfer unit
			(tbc_de==1'b1) & (tbc_de1_r==1'b1) & (tbc_eav==1'b0) & (tbc_unit==1'b0) ? tbc_sync_r[3:0] :	// none
			(tbc_de==1'b1) & (tbc_de1_r==1'b1) & (tbc_eav==1'b1) & (tbc_dclk==1'b1) & (tbc_vend==1'b0) ? 4'b0011 :	// bs(hs)
			(tbc_de==1'b1) & (tbc_de1_r==1'b1) & (tbc_eav==1'b1) & (tbc_dclk==1'b1) & (tbc_vend==1'b1) ? 4'b0100 :	// bs(vs) disp end
			(tbc_de==1'b1) & (tbc_de1_r==1'b1) & (tbc_eav==1'b1) & (tbc_dclk==1'b0) ? tbc_sync_r[3:0] :	// none
			(tbc_de==1'b0) & (tbc_dclk==1'b1) & (tbc_eav==1'b1) ? 4'b0101 :	// bs(vs)
			(tbc_de==1'b0) & (tbc_dclk==1'b1) & (tbc_eav==1'b0) & (tbc_vs==1'b0) & (tbc_sav==1'b1) & (tbc_sync_ss_r==1'b0) ? 4'b0110 :	// ss(vs)
			(tbc_de==1'b0) & (tbc_dclk==1'b1) & (tbc_eav==1'b0) & (tbc_vs==1'b0) & (tbc_sav==1'b1) & (tbc_sync_ss_r==1'b1) ? tbc_sync_r[3:0] :	// none
			(tbc_de==1'b0) & (tbc_dclk==1'b1) & (tbc_eav==1'b0) & (tbc_vs==1'b0) & (tbc_sav==1'b0) ? tbc_sync_r[3:0] :	// none
			(tbc_de==1'b0) & (tbc_dclk==1'b1) & (tbc_eav==1'b0) & (tbc_vs==1'b1) ? tbc_sync_r[3:0] :	// none
			(tbc_de==1'b0) & (tbc_dclk==1'b0) ? tbc_sync_r[3:0] :
			4'b0;

	assign tbc_clr_w=
			(tbc_de==1'b1) & (tbc_de1_r==1'b0) & (tbc_unit==1'b1) ? 1'b1 :	// transfer unit + be
			(tbc_de==1'b1) & (tbc_de1_r==1'b0) & (tbc_unit==1'b0) ? 1'b0 :	// none
			(tbc_de==1'b1) & (tbc_de1_r==1'b1) & (tbc_eav==1'b0) & (tbc_unit==1'b1) ? 1'b1 :	// transfer unit
			(tbc_de==1'b1) & (tbc_de1_r==1'b1) & (tbc_eav==1'b0) & (tbc_unit==1'b0) ? 1'b0 :	// none
			(tbc_de==1'b1) & (tbc_de1_r==1'b1) & (tbc_eav==1'b1) & (tbc_dclk==1'b1) & (tbc_vend==1'b0) ? 1'b1 :	// bs(hs)
			(tbc_de==1'b1) & (tbc_de1_r==1'b1) & (tbc_eav==1'b1) & (tbc_dclk==1'b1) & (tbc_vend==1'b1) ? 1'b1 :	// bs(vs) disp end
			(tbc_de==1'b1) & (tbc_de1_r==1'b1) & (tbc_eav==1'b1) & (tbc_dclk==1'b0) ? 1'b0 :	// none
			(tbc_de==1'b0) & (tbc_dclk==1'b1) & (tbc_eav==1'b1) ? 1'b1 :	// bs(vs)
			(tbc_de==1'b0) & (tbc_dclk==1'b1) & (tbc_eav==1'b0) & (tbc_vs==1'b0) & (tbc_sav==1'b1) & (tbc_sync_ss_r==1'b0) ? 1'b1 :	// ss(vs)
			(tbc_de==1'b0) & (tbc_dclk==1'b1) & (tbc_eav==1'b0) & (tbc_vs==1'b0) & (tbc_sav==1'b1) & (tbc_sync_ss_r==1'b1) ? 1'b0 :	// none
			(tbc_de==1'b0) & (tbc_dclk==1'b1) & (tbc_eav==1'b0) & (tbc_vs==1'b0) & (tbc_sav==1'b0) ? 1'b0 :	// none
			(tbc_de==1'b0) & (tbc_dclk==1'b1) & (tbc_eav==1'b0) & (tbc_vs==1'b1) ? 1'b0 :	// none
			(tbc_de==1'b0) & (tbc_dclk==1'b0) ? 1'b0 :
			1'b0;

	assign tbc_sync_ss_w=
			(tbc_dclk==1'b1) & (tbc_de==1'b1) ? 1'b0 :
			(tbc_dclk==1'b1) & (tbc_de==1'b0) &  ((tbc_eav==1'b0) & (tbc_vs==1'b0) & (tbc_sav==1'b1)) ? 1'b1 :
			(tbc_dclk==1'b1) & (tbc_de==1'b0) & !((tbc_eav==1'b0) & (tbc_vs==1'b0) & (tbc_sav==1'b1)) ? tbc_sync_ss_r :
			(tbc_dclk==1'b0) ? tbc_sync_ss_r :
			1'b0;

	assign tbc_count_w[7:0]=
			(tbc_sav==1'b1) ? 8'b0 : 
			(tbc_sav==1'b0) ? tbc_count_r[7:0]+8'b01 :
			8'b0;

	assign tbc_count_sync_w=
			(tbc_de==1'b0) ? 1'b0 : 
			(tbc_de==1'b1) & (tbc_count_r[4:0]==5'b11110) ? 1'b1 :	// 32
			(tbc_de==1'b1) & (tbc_count_r[4:0]!=5'b11110) ? 1'b0 :
		//	(tbc_de==1'b1) & (tbc_count_r[5:0]==6'b111110) ? 1'b1 :	// 64
		//	(tbc_de==1'b1) & (tbc_count_r[5:0]!=6'b111110) ? 1'b0 :
			1'b0;

	assign tbc_de1_w=
			(tbc_de==1'b0) ? 1'b0 : 
			(tbc_de==1'b1) & (tbc_count_r[4:0]==5'b11111) ? 1'b1 :	// 32
			(tbc_de==1'b1) & (tbc_count_r[4:0]!=5'b11111) ? tbc_de1_r :
		//	(tbc_de==1'b1) & (tbc_count_r[5:0]==6'b111111) ? 1'b1 :	// 64
		//	(tbc_de==1'b1) & (tbc_count_r[5:0]!=6'b111111) ? tbc_de1_r :
			1'b0;

	assign tbc_dcount_w[7:0]=
			(tbc_clr_r==1'b1) ? 8'b0 :
			(tbc_clr_r==1'b0) & (tbc_dcount_r[4:0]==5'h1f) ? 8'h1f :
			(tbc_clr_r==1'b0) & (tbc_dcount_r[4:0]!=5'h1f) ? tbc_dcount_r[7:0]+8'b01 :
			8'b0;

	assign tbc_xcount_w[15:0]=
			(tbc_de==1'b0) ? 16'b0 :
			(tbc_de==1'b1) ? tbc_xcount_r[15:0]+16'b01 :
			8'b0;

	assign tbc_vcount_w[15:0]=
			(tbc_de==1'b0) ? 16'b0 :
			(tbc_de==1'b1) & (tbc_dclk==1'b1) ? tbc_vcount_r[15:0]+16'b01 :
			(tbc_de==1'b1) & (tbc_dclk==1'b0) ? tbc_vcount_r[15:0] :
			8'b0;

	assign tbc_dcount_sync_w=
			(tbc_clr_r==1'b1) ? 1'b0 :
			(tbc_clr_r==1'b0) & (tbc_dcount_r[4:0]==5'h1e) ? 1'b1 :
			(tbc_clr_r==1'b0) & (tbc_dcount_r[4:0]!=5'h1e) ? 1'b0 :
			1'b0;

	assign tbc_data0_out_w[287:0]=
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0000) ? 288'b0 :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0001) ? tbc_disp_de[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0010) ? tbc_disp[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0011) ? tbc_disp_hs[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0100) ? tbc_disp_vs[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0101) ? tbc_sync_vs[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0110) ? tbc_sync_ss0[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0111) ? 288'b0 :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3]==1'b1) ? 288'b0 :
			!((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) ? {9'b0,tbc_data0_out_r[287:9]} :
			288'b0;

	assign tbc_data1_out_w[287:0]=
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0000) ? 288'b0 :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0001) ? tbc_disp_de[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0010) ? tbc_disp[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0011) ? tbc_disp_hs[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0100) ? tbc_disp_vs[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0101) ? tbc_sync_vs[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0110) ? tbc_sync_ss1[287:0] :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3:0]==4'b0111) ? 288'b0 :
			 ((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) & (tbc_sync_r[3]==1'b1) ? 288'b0 :
			!((tbc_clr_r==1'b1) | (tbc_count_sync_r==1'b1)) ? {9'b0,tbc_data1_out_r[287:9]} :
			288'b0;

	assign tbc_data2_out_w[287:0]=288'b0;

	assign tbc_data3_out_w[287:0]=288'b0;

endmodule
