`line 1 "C:\AGX20\agx20_disp_dp2_vga\agx20_disp_dp2_vga_tb.v"

`define simulation
`define sim_fast
`define sim_no_phy

`include "dp_sink_aux_rx.v"
`include "dp_sink_aux_tx.v"

`include "agx20_disp_dp2_vga.v"
//`include "alt_clkbuf.v"
`include "alt_ddio_bidir.v"

`include "alt_pll_50x27x162.v"
`include "alt_alt2gxb_tx2.vo"

`include "sim/xil_8b10b_enc.v"
`include "sim/ENCODE_8B10B_V5_0.v"

`include "dp_main_linkup2.v"
`include "dp_aux_tx.v"
`include "dp_aux_rx.v"

`include "dispgen.v"

`include "dp_main_crtc2.v"
`include "dp_main_tbc2.v"
`include "dp_main_scramble.v"
`include "alt_ram_dp108x256.v"

`include "dp_main_linkup1.v"
`include "dp_main_linkup2.v"
`include "dp_main_crtc1.v"
`include "dp_main_crtc2.v"

`include "sim_altera/220model.v"
`include "sim_altera/altera_mf.v"
`include "sim_altera/arriagx_atoms.v"
`include "sim_altera/arriagx_hssi_atoms.v"
`include "sim_altera/sgate.v"

`timescale 1 ns / 1 ns

module tb(
);

	wire	CLK50;
	wire	CLK162;
	wire	CLK27;
	wire	RST_N;

	// ---- CLK50 (50MHz) ----

	reg		CLK50_r;

	initial
	begin
		forever
		begin
			CLK50_r <= 1'b0; #10;
			CLK50_r <= 1'b1; #10;
		end
	end

	assign CLK50=CLK50_r;

//	assign CLK50=1'b0;

	// ---- CLK27 (27MHz) ----

	reg		CLK27_r;

	initial
	begin
		forever
		begin
			CLK27_r <= 1'b0; #19;
			CLK27_r <= 1'b1; #18;
//			CLK27_r <= 1'b0; #1;
//			CLK27_r <= 1'b1; #1;
		end
	end

	assign CLK27=CLK27_r;

	// ---- CLK162 (162MHz) ----

	reg		CLK162_r;

	initial
	begin
		forever
		begin
			CLK162_r <= 1'b0; #3;
			CLK162_r <= 1'b1; #3;
		end
	end

	assign CLK162=CLK162_r;

	// ---- RESET async ----

	reg		RST_N_r;

	initial
	begin
		RST_N_r <= 'b1; #1;
		RST_N_r <= 'b0; #200;
		RST_N_r <= 'b1; #1;
	end

	assign RST_N=RST_N_r;

	// ---- ----

	wire	CLK_FB;

	// ---- sink device ----

	wire	aux_data_tx;
	wire	aux_data_oe;
	wire	aux_data_rx;

	wire	aux_sink_tx;
	wire	aux_sink_oe;
	wire	aux_sink_rx;

	localparam	i2cst00=4'b0000;	// idle
	localparam	i2cst01=4'b0001;	// req i2c-ao
	localparam	i2cst02=4'b0011;	// wait sink ack
	localparam	i2cst03=4'b0010;	// wait 2unit
	localparam	i2cst04=4'b0100;	// req i2c-read
	localparam	i2cst05=4'b0101;	// wait sink ack
	localparam	i2cst06=4'b0111;	// wait 2unit
	localparam	i2cst07=4'b0110;	// 

	wire	[31:0] ddc_addr;
	wire	[31:0] ddc_wdata;
	wire	[31:0] ddc_rdata;
	wire	[3:0] ddc_be;
	wire	ddc_rd;
	wire	ddc_req;
	wire	ddc_ack;

	wire	[11:0] ddc_waddr;
	wire	[8:0] ddc_data;
	wire	ddc_wreq;

	wire	i2c_txreq;
	wire	i2c_txack;
	wire	i2c_txdone;
	wire	[3:0] i2c_txcmd;
	wire	[19:0] i2c_txaddr;
	wire	[7:0] i2c_txlen;
	wire	[7:0] i2c_txdata;
	wire	i2c_txao;
	wire	i2c_txdreq;
	wire	[19:0] i2c_txsel;
	wire	[7:0] i2c_rxstat;
	wire	[7:0] i2c_rxdata;
	wire	i2c_rxcack;
	wire	i2c_rxdack;
	wire	i2c_rxsync;
	wire	i2c_rxstop;
	wire	i2c_rxdone;

	wire	[3:0] i2c_state_w;
	reg		[3:0] i2c_state_r;

	wire	[7:0] i2c_wait_w;
	wire	i2c_wait2unit_w;
	wire	i2c_rxreq_w;
	wire	[7:0] i2c_rxstat_w;
	wire	[7:0] i2c_rxlen_w;

	reg		[7:0] i2c_wait_r;
	reg		i2c_wait2unit_r;
	reg		i2c_rxreq_r;
	reg		[7:0] i2c_rxstat_r;
	reg		[7:0] i2c_rxlen_r;


	wire	aux_rxreq;
	wire	aux_rxack;
	wire	aux_rxdone;
	wire	[7:0] aux_rxcmd;
	wire	[7:0] aux_rxstat;
	wire	[7:0] aux_rxlen;
	wire	[7:0] aux_rxdata;
	wire	aux_rxdata_req;

	wire	[3:0] aux_txcmd;
	wire	[19:0] aux_txaddr;
	wire	[7:0] aux_txdata;
	wire	aux_txcmd_ack;
	wire	aux_txaddr_ack;
	wire	aux_txdata_ack;
	wire	aux_txsync;
	wire	aux_txstop;
	wire	aux_txdone;

	assign aux_rxreq=i2c_rxreq_r;
	assign aux_rxcmd[7:0]={aux_txcmd[3:0],4'b0};
	assign aux_rxstat[7:0]=i2c_rxstat_r[7:0];
	assign aux_rxlen[7:0]=i2c_rxlen_r[7:0];
//	assign aux_rxdata[7:0]=aux_txaddr[7:0];
//	assign aux_rxdata[7:0]=8'b00000001;	// tr1
	assign aux_rxdata[7:0]=8'b11111111;	// tr1,tr2

	always @(posedge CLK27 or negedge RST_N)
	begin
		if (RST_N==1'b0)
			begin
				i2c_state_r <= i2cst00;
				i2c_wait_r[7:0] <= 8'b0;
				i2c_wait2unit_r <= 1'b0;
				i2c_rxreq_r <= 1'b0;
				i2c_rxstat_r[7:0] <= 8'b0;
				i2c_rxlen_r[7:0] <= 8'b0;
			end
		else
			begin
				i2c_state_r <= i2c_state_w;
				i2c_wait_r[7:0] <= i2c_wait_w[7:0];
				i2c_wait2unit_r <= i2c_wait2unit_w;
				i2c_rxreq_r <= i2c_rxreq_w;
				i2c_rxstat_r[7:0] <= i2c_rxstat_w[7:0];
				i2c_rxlen_r[7:0] <= i2c_rxlen_w[7:0];
			end
	end

	reg		[3:0] sink_cmd_r;
	reg		[19:0] sink_addr_r;
	reg		[7:0] sink_len_r;
	reg		[7:0] sink_data_r;

	reg		[3:0] sink_data_count_r;

	always @(posedge CLK27 or negedge RST_N)
	begin
		if (RST_N==1'b0)
			begin
				sink_cmd_r[3:0] <= 4'b0;
				sink_addr_r[19:0] <= 20'b0;
				sink_len_r[7:0] <= 8'b0;
				sink_data_r[7:0] <= 8'b0;
				sink_data_count_r[3:0] <= 4'b0;
			end
		else
			begin
				sink_cmd_r[3:0] <= (aux_txcmd_ack==1'b1) ? aux_txcmd[3:0] : sink_cmd_r[3:0];
				sink_addr_r[19:0] <= (aux_txaddr_ack==1'b1) ? aux_txaddr[19:0] : sink_addr_r[19:0];
				sink_len_r[7:0] <= (aux_txdata_ack==1'b1) & (sink_data_count_r[3:0]==4'b0) ? aux_txdata[7:0] : sink_len_r[7:0];
				sink_data_r[7:0] <= (aux_txdata_ack==1'b1) & (sink_data_count_r[3:0]!=4'b0) ? aux_txdata[7:0] : sink_data_r[7:0];
				sink_data_count_r[3:0] <= 
					(aux_txcmd_ack==1'b1) ? 4'b0 :
					(aux_txcmd_ack==1'b0) & (aux_txdata_ack==1'b1) ? sink_data_count_r[3:0]+4'b01 :
					(aux_txcmd_ack==1'b0) & (aux_txdata_ack==1'b0) ? sink_data_count_r[3:0] :
					4'b0;
			end
	end

	assign i2c_state_w=
			(i2c_state_r==i2cst00) & (aux_txdone==1'b0) ? i2cst00 :
			(i2c_state_r==i2cst00) & (aux_txdone==1'b1) ? i2cst01 :
			(i2c_state_r==i2cst01) & (i2c_wait2unit_r==1'b0) ? i2cst01 :
			(i2c_state_r==i2cst01) & (i2c_wait2unit_r==1'b1) ? i2cst02 :
			(i2c_state_r==i2cst02) & (aux_rxdone==1'b0) ? i2cst02 :
			(i2c_state_r==i2cst02) & (aux_rxdone==1'b1) ? i2cst03 :
			(i2c_state_r==i2cst03) & (sink_cmd_r[3]==1'b1) ? i2cst00 :
			(i2c_state_r==i2cst03) & (sink_cmd_r[3]==1'b0) & (aux_txdone==1'b0) ? i2cst03 :
			(i2c_state_r==i2cst03) & (sink_cmd_r[3]==1'b0) & (aux_txdone==1'b1) ? i2cst04 :
			(i2c_state_r==i2cst04) & (i2c_wait2unit_r==1'b0) ? i2cst04 :
			(i2c_state_r==i2cst04) & (i2c_wait2unit_r==1'b1) ? i2cst05 :
			(i2c_state_r==i2cst05) & (aux_rxdone==1'b0) ? i2cst05 :
			(i2c_state_r==i2cst05) & (aux_rxdone==1'b1) ? i2cst06 :
			(i2c_state_r==i2cst06) ? i2cst00 :
			(i2c_state_r==i2cst07) ? i2cst00 :
			i2cst00;

	assign i2c_wait_w[7:0]=
			(i2c_state_r==i2cst00) ? 8'b0 :
			(i2c_state_r==i2cst01) ? i2c_wait_r[7:0]+8'b01 :
			(i2c_state_r==i2cst02) ? 8'b0 :
			(i2c_state_r==i2cst03) ? 8'b0 :
			(i2c_state_r==i2cst04) ? i2c_wait_r[7:0]+8'b01 :
			(i2c_state_r==i2cst05) ? 8'b0 :
			(i2c_state_r==i2cst06) ? 8'b0 :
			(i2c_state_r==i2cst07) ? 8'b0 :
			i2cst00;

	assign i2c_wait2unit_w=(i2c_wait_r[7:6]==2'b00) ? 1'b0 : 1'b1;

	assign i2c_rxreq_w=
			(i2c_state_r==i2cst00) ? 1'b0 :
			(i2c_state_r==i2cst01) & (i2c_wait2unit_r==1'b0) ? 1'b0 :
			(i2c_state_r==i2cst01) & (i2c_wait2unit_r==1'b1) ? 1'b1 :
			(i2c_state_r==i2cst02) & (aux_rxack==1'b0) ? i2c_rxreq_r :
			(i2c_state_r==i2cst02) & (aux_rxack==1'b0) ? 1'b0 :
			(i2c_state_r==i2cst03) ? 1'b0 :
			(i2c_state_r==i2cst04) & (i2c_wait2unit_r==1'b0) ? 1'b0 :
			(i2c_state_r==i2cst04) & (i2c_wait2unit_r==1'b1) ? 1'b1 :
			(i2c_state_r==i2cst05) & (aux_rxack==1'b0) ? i2c_rxreq_r :
			(i2c_state_r==i2cst05) & (aux_rxack==1'b0) ? 1'b0 :
			(i2c_state_r==i2cst06) ? 1'b0 :
			(i2c_state_r==i2cst07) ? 1'b0 :
			1'b0;

	assign i2c_rxstat_w[7:6]=2'b0;
//	assign i2c_rxstat_w[5]=(aux_txdone==1'b1) ? !i2c_rxstat_r[5] : i2c_rxstat_r[5];	// retry
	assign i2c_rxstat_w[5]=1'b0;
	assign i2c_rxstat_w[4:0]=5'b0;
/*
			(i2c_state_r==i2cst00) ? 8'b00000000 :
			(i2c_state_r==i2cst01) ? 8'b00000000 :
			(i2c_state_r==i2cst02) ? 8'b00000000 :
			(i2c_state_r==i2cst03) ? 8'b00000000 :
			(i2c_state_r==i2cst00) ? 8'b00000000 :
			(i2c_state_r==i2cst01) ? 8'b00000000 :
			(i2c_state_r==i2cst02) ? 8'b00000000 :
			(i2c_state_r==i2cst03) ? 8'b00000000 :
			8'b0;
*/

	assign i2c_rxlen_w[7:0]=
			(i2c_state_r==i2cst00) ? 8'h0 :
			(i2c_state_r==i2cst01) ? 8'h0 :
			(i2c_state_r==i2cst02) & (sink_cmd_r[3:0]==4'b1001) ? 8'h1 :
			(i2c_state_r==i2cst02) & (sink_cmd_r[3:0]!=4'b1001) ? 8'h0 :
			(i2c_state_r==i2cst03) ? 8'h0 :
			(i2c_state_r==i2cst04) ? 8'h1 :
			(i2c_state_r==i2cst05) ? 8'h1 :
			(i2c_state_r==i2cst06) ? 8'h1 :
			(i2c_state_r==i2cst07) ? 8'h1 :
			8'b0;

	// ---- ----

dp_sink_aux_tx sink_tx(
	.aux_tx(aux_sink_tx),			// out   [AUX] dp aux_tx
	.aux_oe(aux_sink_oe),			// out   [AUX] dp aux_tx oe
	.aux_req(aux_rxreq),			// in    [AUX] send request
	.aux_ack(aux_rxack),			// out   [AUX] send acknowredge
	.aux_done(aux_rxdone),			// out   [AUX] send done
	.aux_cmd(aux_rxcmd[7:0]),		// in    [AUX] send command
	.aux_stat(aux_rxstat[7:0]),		// in    [AUX] send status
	.aux_len(aux_rxlen[7:0]),		// in    [AUX] send data length
	.aux_data(aux_rxdata[7:0]),		// in    [AUX] send data
	.aux_data_req(aux_rxdata_req),	// out   [AUX] send data request
	.clk27(CLK27),					// in    [AUX] clk 27MHz
	.rst_n(RST_N)					// in    [AUX] #reset
);

dp_sink_aux_rx sink_rx(
	.aux_rx(aux_sink_rx),			// in    [AUX] dp aux_rx
	.aux_oe(!aux_data_oe),			// in    [AUX] dp aux send/#recieve
	.aux_cmd(aux_txcmd[3:0]),		// out   [AUX] recieve ack
	.aux_addr(aux_txaddr[19:0]),	// out   [AUX] recieve addr
	.aux_data(aux_txdata[7:0]),		// out   [AUX] recieve data
	.aux_cmd_ack(aux_txcmd_ack),	// out   [AUX] recieve cmd acknowredge
	.aux_addr_ack(aux_txaddr_ack),	// out   [AUX] recieve addr acknowredge
	.aux_data_ack(aux_txdata_ack),	// out   [AUX] recieve data acknowredge
	.aux_sync(aux_txsync),			// out   [AUX] recieve sync
	.aux_stop(aux_txstop),			// out   [AUX] recieve stop
	.aux_done(aux_txdone),			// out   [AUX] recieve done
	.clk27(CLK27),					// in    [AUX] clk 27MHz
	.rst_n(RST_N)					// in    [AUX] #reset
);


	// ---- source device ----

	wire	[3:0] TX_P;
	wire	[3:0] RX_P;

	assign aux_data_rx=aux_sink_tx | aux_data_tx;
	assign aux_sink_rx=aux_data_tx;

//	assign RX_P[3:0]={!CLK50,1'b0,CLK50,1'b1};
	assign RX_P[3:0]=4'b0;

agx20_disp_dp2_vga disp_vga(
`ifdef simulation
	.CLK27IN(CLK27),
	.CLK162IN(CLK50),
`else
`endif
	.EXA(),								// inout
	.EXB(),								// inout
	.KEY0(1'b1),						// in
	.KEY1(1'b0),						// in
	.KEY2(1'b0),						// in
	.KEY3(1'b0),						// in
	.DIPSW(4'b0),						// in
	.LEDG(),							// out
	.LED_X4(),							// out
	.LED_X1(),							// out
	.LED_LINK(),						// out

	.TX_P(TX_P[3:0]),					// out
	.RX_P(RX_P[3:0]),					// in
	.TX_SCL(aux_data_tx),				// inout
	.TX_SDA(aux_data_rx),				// inout
	.TX_HPD(1'b1),						// in
	.TX_DIR(aux_data_oe),				// inout
	.CLK1(CLK50),						// in
	.CLK2(CLK27),						// in
	.SYSRST_N(RST_N)					// in
);

`ifdef sim_no_phy
`else

	wire	  rx1_cal_blk_clk;
	wire	[0:0]  rx1_gxb_enable;
	wire	[0:0]  rx1_gxb_powerdown;
	wire	[0:0]  rx1_rx_analogreset;
	wire	[0:0]  rx1_rx_cruclk;
	wire	[0:0]  rx1_rx_datain;
	wire	[0:0]  rx1_rx_digitalreset;
	wire	[0:0]  rx1_rx_locktodata;
	wire	[0:0]  rx1_rx_clkout;
	wire	[1:0]  rx1_rx_ctrldetect;
	wire	[15:0]  rx1_rx_dataout;
	wire	[1:0]  rx1_rx_disperr;
	wire	[1:0]  rx1_rx_errdetect;
	wire	[0:0]  rx1_rx_freqlocked;
	wire	[1:0]  rx1_rx_patterndetect;
	wire	[1:0]  rx1_rx_syncstatus;

	reg		rx1_rx_locktodata_r;

	always @(posedge rx1_rx_clkout or negedge rx1_rx_freqlocked)
	begin
		if (rx1_rx_freqlocked==1'b0)
			begin
				rx1_rx_locktodata_r <= 1'b1;
			end
		else
			begin
				rx1_rx_locktodata_r <= (rx1_rx_patterndetect[0]!=1'b0) ? 1'b0 : rx1_rx_locktodata_r;
			end
	end

	assign rx1_cal_blk_clk=CLK50;
	assign rx1_gxb_enable=1'b1;
	assign rx1_gxb_powerdown=1'b0;
	assign rx1_rx_analogreset=!RST_N;
	assign rx1_rx_cruclk=CLK162;
	assign rx1_rx_datain=TX_P[0];
	assign rx1_rx_digitalreset=!RST_N;
	assign rx1_rx_locktodata=rx1_rx_locktodata_r;

alt_alt2gxb_rx1 alt2gxb_rx1 (
	.cal_blk_clk(rx1_cal_blk_clk),
	.gxb_enable(rx1_gxb_enable),
	.gxb_powerdown(rx1_gxb_powerdown),
	.rx_analogreset(rx1_rx_analogreset),
	.rx_cruclk(rx1_rx_cruclk),
	.rx_datain(rx1_rx_datain),
	.rx_digitalreset(rx1_rx_digitalreset),
//	.rx_locktodata(rx1_rx_locktodata),
	.rx_clkout(rx1_rx_clkout),						// out
	.rx_ctrldetect(rx1_rx_ctrldetect[0]),			// out
	.rx_dataout(rx1_rx_dataout[7:0]),			// out
	.rx_disperr(rx1_rx_disperr[0]),			// out
	.rx_errdetect(rx1_rx_errdetect[0]),			// out
	.rx_freqlocked(rx1_rx_freqlocked),			// out
	.rx_patterndetect(rx1_rx_patterndetect[0]),			// out
	.rx_syncstatus(rx1_rx_syncstatus[0])			// out
);
`endif

endmodule
