百兆以太网FPGA实现,ARP+UDP功能,一个采集卡上的程序

因为很多功能揉在一起,没有分模块,比较杂乱,可以参考参考再自己修改!

	`timescale 1ns / 1ps
	
	
	module ETH_APP(		
	input    CLK50M,
	input    EXT_RST_N,
	//
	input		user1,
	//
	input 		mi, 
	output		sck, 
	output   	flash_cs, 
	output		flash_mo,
	//PHY PORT
	input     		RX_CLK, 
	input     		RX_DV,
	input  [3 : 0] RXD,
	input     		TX_CLK,
	output    		TX_EN,
	output [3 : 0] TXD,
	//AD PORT
	output          		ai_data_to_sample,
	input						ai_data_sample_done,
	output 	[7		:	0]	ai_data_chanel_sel,
	output 	[9		:	0] ai_data_addrb,
	input 	[23	:	0] ai_data,
	//DA PORT
	input					ao_data_done_ext,					
	output 				ao_data_valid_ext,
	output [31	:	0]	ao_data,
	//DIGITAL PORT
	output [7	:	0] do_data,
	input  [7	:	0] di_data
	);
	wire [47 : 0] daq_receiver_mac;
	wire [31 : 0] daq_receiver_ip;
	wire rx_wea;
	(*keep = "true"*)wire [7 : 0] rx_doutb;
	wire [31: 0] crc32_value_rx;
	wire [7 : 0] crc32_rxdata;
	wire [31: 0] rx_crc32_value_final;
	
	wire [47 : 0] ai_data_47_0;
	wire [7 	: 0]	crc32_txdata;
	wire [7 	: 0]	crc32_txdata_arp;
	wire [7  : 0] 	crc32_txdata_udp;
	wire [31 : 0] 	crc32_oldcrc_tx;
	wire 				crc32_enable_tx;
	wire [31 : 0] 	tx_crc32_value_final;
	wire [31 : 0]	crc32_value_tx;
	

	reg [5  : 0] 	rst_cnt = 6'b0;
	reg 				rst_n = 1'b0;
	reg 				mo = 1'b0;
	reg 				cs = 1'b0;
	reg				system_valid = 1'b0;
	
	reg [11 : 0] 	rx_addra = 12'b0;
	reg [1  : 0] 	rx_dv_s = 2'b0;
	reg [1  : 0] 	tx_done_s = 2'b0;
	reg 				rx_busy = 1'b0;
	reg [10 : 0] 	rx_addrb = 11'b0;
	reg [15 : 0] 	packet_type = 16'b0;
	reg [15 : 0] 	arp_op;
	reg [47 : 0] 	arp_sender_mac;
	reg [31 : 0] 	arp_sender_ip;
	reg [47 : 0] 	arp_receiver_mac;
	reg [31 : 0] 	arp_receiver_ip;
	reg [47 : 0]	udp_receiver_mac;
	reg [47 : 0]	udp_sender_mac;
	reg [7  : 0]	udp_tcp_type;
	reg [31 : 0]	udp_sender_ip;
	reg [31 : 0]	udp_receiver_ip;
	reg [15 : 0]   udp_sender_port_addr;
	reg [15 : 0]   udp_receiver_port_addr;
	reg [7  : 0]   app_cmd = 8'b0;
	reg [1  : 0]	udp_tx_s = 2'b0;
	reg [7  : 0] 	do_data_o = 8'b0;
	reg 				do_data_valid = 1'b0;
	reg [31 : 0] 	ao_data_o = 32'b0;
	reg [1  : 0]   ao_data_done_ext_s = 2'b0;
	reg 				ao_data_valid_o = 1'b0;
	reg [31 : 0]	udp_set_receiver_ip;
	reg				flash_wr_done = 1'b0;
	reg [1  : 0]	flash_wr_done_s = 2'b0;
	reg				flash_wr_cmd = 1'b0;
	reg [1  : 0]	flash_wr_cmd_s = 2'b0;
	reg [31 : 0]   test_data = 32'b0;
	reg				test_data_valid = 1'b0;
	reg				di_data_valid = 1'b0;
	reg [1  : 0]	ai_data_done_s = 2'b0;
	reg				ai_data_valid = 1'b0;
	reg [7 : 0]		ai_mode_select = 8'b0;
	reg [7 : 0]		ai_path_select = 8'b0;
	reg 				arp_tx = 1'b0;
	reg 				udp_tx = 1'b0;
	reg [31 : 0] 	crc32_oldcrc_rx = 32'hffff_ffff;
	reg 				crc32_enable_rx = 1'b0;
	reg [31 : 0] 	rx_crc32_value_ori = 32'h0000_0000;
	
	reg  [31 : 0] 	crc32_oldcrc_tx_arp;
	reg  [31 : 0] 	crc32_oldcrc_tx_udp;
	reg 				crc32_enable_tx_arp = 1'b0;
	reg 				crc32_enable_tx_udp = 1'b0;
	
	reg [1 : 0] do_data_valid_s = 2'b0;
	reg [1 : 0] ao_data_valid_s = 2'b0;
	reg [1 : 0] test_data_valid_s = 2'b0;
	reg [1 : 0] di_data_valid_s = 2'b0;
	reg [1 : 0] ai_data_valid_s = 2'b0;
	reg 			ao_data_valid_udp = 1'b0;
	reg			flash_wr_cmd_udp = 1'b0;
	reg [1 : 0]	ao_data_valid_udp_s = 2'b0;
	reg [1 : 0]	flash_wr_cmd_udp_s = 2'b0;
	reg [9 : 0] udp_checksum_cnt = 10'b0;
	reg [2 : 0] ai_data_cnt = 3'b0; 

	reg do_data_cs_done = 1'b0;
	reg ao_data_cs_done = 1'b0;
	reg flash_wr_cs_done = 1'b0;
	reg test_data_cs_done = 1'b0;
	reg di_data_cs_done = 1'b0;
	reg ai_cs1_done = 1'b0;
	reg ai_cs2_done = 1'b0;
	reg ai_cs3_done = 1'b0;
	
	reg 				tx_ram_wea_udp0 = 1'b0;
	reg 				tx_ram_wea_udp = 1'b0;
	reg [10 : 0]	tx_ram_addra_udp0 = 11'b0;
	reg [10 : 0]	tx_ram_addra_udp = 11'b0;
	
	reg	do_data_done = 1'b0;
	reg	ao_data_udp_done = 1'b0;
	reg	flash_wr_udp_done = 1'b0;
	reg	test_data_done = 1'b0;
	reg	di_data_done = 1'b0;
	reg	ai_packet_1_done = 1'b0;
	reg	ai_packet_2_done = 1'b0;
	reg   ai_packet_3_done = 1'b0; 
	reg	udp_ack_start	= 1'b0;
	
	wire 	[11	:	0] tx_ram_addrb;
	(*keep = "true"*)wire	[3		:	0]	tx_ram_doutb ;
	reg 	[11	:	0] tx_cnt_phy = 12'b0;
	reg					tx_en_o = 1'b0;
	reg					tx_done = 1'b0;
	
	reg ai_packet_phy1_done = 0;
	reg ai_packet_phy2_done = 0;
	
	parameter daq_cad_port_addr = 16'h1A28;
	//**************************************************************************
	//--------------------------------------------------------------------------
	//generate rst_n for phy control
	//--------------------------------------------------------------------------
	//**************************************************************************
	always @ (posedge CLK50M)
		begin
			if(~EXT_RST_N | (~user1)) rst_cnt <= 6'b0;
			else if(&rst_cnt) rst_cnt <= rst_cnt;
			else rst_cnt <= rst_cnt + 1;
		end
	//rst_n
	always @ (posedge CLK50M)
		begin
			if(~EXT_RST_N | (~user1)) rst_n <= 1'b0;
			else if(&rst_cnt) rst_n <= 1'b1;
			else rst_n <= 1'b0;
		end
	//**************************************************************************
	//--------------------------------------------------------------------------
	//93LC46A, store the new ip address
	//(1)according to the analyse of reading timing, the D[7] is valid when read 
	//counter is 12 at the posedge of spi clock
	//(2)when power up, procedure auto read address '0000001', if the value is 
	//'A5', replace the card ip address with the value of reading from address
	//'2-5', else using the default ip address.
	//(3)MAC address is {16'habcd, ipaddress};
	//--------------------------------------------------------------------------
	//**************************************************************************	
	//~~~~~~~~~~~~~~~~~~~~~~part1: generate spi clk1~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	parameter div = 50;
	reg [5:0] div_cnt = 6'b0;
	reg       spi_clk = 1'b0;
	always @ (posedge CLK50M)
		begin
			if(div_cnt == div) div_cnt <= 6'b0;
			else div_cnt <= div_cnt + 1;
		end
	always @ (posedge CLK50M)
		begin
			if(div_cnt == div/2) spi_clk <= !spi_clk;
			else if(div_cnt == div) spi_clk <= !spi_clk;
			else spi_clk <= spi_clk;
		end
	assign sck = !spi_clk;
	//~~~~~~~~~~~~~~~~~part2: generate read cmd when power up~~~~~~~~~~~~~~~~~~
	reg [1 : 0] rd_cmd_cnt = 2'b0;
	reg flash_rd_cmd = 1'b0;
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) rd_cmd_cnt <= 2'b0;
			else if(&rd_cmd_cnt) rd_cmd_cnt <= rd_cmd_cnt;
			else rd_cmd_cnt <= rd_cmd_cnt + 1;
		end
	//read command generate
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) flash_rd_cmd <= 1'b0;
			else 
				case(rd_cmd_cnt)
					2'b01: flash_rd_cmd <= 1'b1;
					2'b10: flash_rd_cmd <= 1'b0;
				endcase
		end
	//~~~~~~~~~~~~~~~~~~~part3: state machine and data control~~~~~~~~~~~~~~~~~
	//state
	parameter idle     = 2'b00,
	          s_write  = 2'b01,
				 s_read   = 2'b10,
				 s_eral	 = 2'b11;
	parameter rd_cmd_data = 10'b110_0000001;//rd cmd
	parameter ewen_data = 10'b100_1100000;
	parameter ewds_data = 10'b100_0000000;
	parameter eral_data = 10'b100_1000000;
	parameter default_receiver_ip = 32'hc0a80101;
	
	wire [17 : 0] flash_wr_data1,flash_wr_data2,flash_wr_data3,
					  flash_wr_data4,flash_wr_data5;
	wire flash_eral_cmd;
	reg [1  : 0] state = 2'b0;
	reg [39 : 0] read_data;
	reg [7  : 0] wr_state_cnt = 8'b0;
	reg [5  : 0] rd_state_cnt = 6'b0;
	reg [3  : 0] eral_state_cnt = 4'b0;
	//
	assign flash_wr_data1 = 18'b101_0000001_10100101;
	assign flash_wr_data2 = {10'b101_0000010, udp_set_receiver_ip[31:24]};
	assign flash_wr_data3 = {10'b101_0000011, udp_set_receiver_ip[23:16]};
	assign flash_wr_data4 = {10'b101_0000100, udp_set_receiver_ip[15:8]};
	assign flash_wr_data5 = {10'b101_0000101, udp_set_receiver_ip[7:0]};
	//state
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) state <= idle;
			else 
				case(state)
				idle:
					begin
					if(flash_rd_cmd) state <= s_read;
					else if(flash_wr_cmd_s == 2'b01) state <= s_write;
					else if(flash_eral_cmd) state <= s_eral;
					end
				s_read: state <= (rd_state_cnt == 6'd51) ? idle : s_read;
				s_write: state <= (wr_state_cnt == 8'd141) ? idle : s_write;
				s_eral: state <= (eral_state_cnt == 4'd11) ? idle : s_eral;
				endcase
		end
	//flash_wr_done
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) flash_wr_done <= 1'b0;
			else if(wr_state_cnt == 8'd141) flash_wr_done <= 1'b1;
			else flash_wr_done <= 1'b0;
		end
	//wr_state_cnt
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) wr_state_cnt <= 8'b0;
			else if(state == s_write) wr_state_cnt <= wr_state_cnt + 1;
			else wr_state_cnt <= 8'b0;
		end
	//rd_state_cnt
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) rd_state_cnt <= 6'b0;
			else if(state == s_read) rd_state_cnt <= rd_state_cnt + 1;
			else rd_state_cnt <= 6'b0;
		end
	//eral_state_cnt
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) eral_state_cnt <= 4'b0;
			else if(state == s_eral) eral_state_cnt <= eral_state_cnt + 1;
			else eral_state_cnt <= 4'b0;
		end
	//cs
	assign flash_cs = cs;
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) cs <= 1'b0;
			else if(state == s_write)
				case(wr_state_cnt)
					8'd1: cs <= 1'b1;
					8'd11: cs <= 1'b0;
					8'd16: cs <= 1'b1;
					8'd34: cs <= 1'b0;
					8'd39: cs <= 1'b1;
					8'd57: cs <= 1'b0;
					8'd62: cs <= 1'b1;
					8'd80: cs <= 1'b0;
					8'd85: cs <= 1'b1;
					8'd103: cs <= 1'b0;
					8'd108: cs <= 1'b1;
					8'd126: cs <= 1'b0;
					8'd131: cs <= 1'b1;
					8'd141: cs <= 1'b0;
				endcase
			//
			else if(state == s_read)
				begin
				case(rd_state_cnt)
					6'd1: cs <= 1'b1;
					6'd51: cs <= 1'b0;
				endcase
				end
			else if(state == s_eral)
				begin
				case(eral_state_cnt)
				4'd1 : cs <= 1'b1;
				4'd11 : cs <= 1'b0;
				endcase
				end
			else cs <= cs;
		end
	//mo
	assign flash_mo = mo;
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) mo <= 1'b0;
			else if(state == s_write) 
				begin
				case(wr_state_cnt)
				8'd1 : mo <= ewen_data[9];
				8'd2 : mo <= ewen_data[8];
				8'd3 : mo <= ewen_data[7];
				8'd4 : mo <= ewen_data[6];
				8'd5 : mo <= ewen_data[5];
				8'd6 : mo <= ewen_data[4];
				8'd7 : mo <= ewen_data[3];
				8'd8 : mo <= ewen_data[2];
				8'd9 : mo <= ewen_data[1];
				8'd10 : mo <= ewen_data[0];
				//flash_wr_data1
				8'd16 : mo <= flash_wr_data1[17];
				8'd17 : mo <= flash_wr_data1[16];
				8'd18 : mo <= flash_wr_data1[15];
				8'd19 : mo <= flash_wr_data1[14];
				8'd20 : mo <= flash_wr_data1[13];
				8'd21 : mo <= flash_wr_data1[12];
				8'd22 : mo <= flash_wr_data1[11];
				8'd23 : mo <= flash_wr_data1[10];
				8'd24 : mo <= flash_wr_data1[9];
				8'd25 : mo <= flash_wr_data1[8];
				8'd26 : mo <= flash_wr_data1[7];
				8'd27 : mo <= flash_wr_data1[6];
				8'd28 : mo <= flash_wr_data1[5];
				8'd29 : mo <= flash_wr_data1[4];
				8'd30 : mo <= flash_wr_data1[3];
				8'd31 : mo <= flash_wr_data1[2];
				8'd32 : mo <= flash_wr_data1[1];
				8'd33 : mo <= flash_wr_data1[0];
				//flash_wr_data2
				8'd39 : mo <= flash_wr_data2[17];
				8'd40 : mo <= flash_wr_data2[16];
				8'd41 : mo <= flash_wr_data2[15];
				8'd42 : mo <= flash_wr_data2[14];
				8'd43 : mo <= flash_wr_data2[13];
				8'd44 : mo <= flash_wr_data2[12];
				8'd45 : mo <= flash_wr_data2[11];
				8'd46 : mo <= flash_wr_data2[10];
				8'd47 : mo <= flash_wr_data2[9];
				8'd48 : mo <= flash_wr_data2[8];
				8'd49 : mo <= flash_wr_data2[7];
				8'd50 : mo <= flash_wr_data2[6];
				8'd51 : mo <= flash_wr_data2[5];
				8'd52 : mo <= flash_wr_data2[4];
				8'd53 : mo <= flash_wr_data2[3];
				8'd54 : mo <= flash_wr_data2[2];
				8'd55 : mo <= flash_wr_data2[1];
				8'd56 : mo <= flash_wr_data2[0];				
				//flash_wr_data3
				8'd62 : mo <= flash_wr_data3[17];
				8'd63 : mo <= flash_wr_data3[16];
				8'd64 : mo <= flash_wr_data3[15];
				8'd65 : mo <= flash_wr_data3[14];
				8'd66 : mo <= flash_wr_data3[13];
				8'd67 : mo <= flash_wr_data3[12];
				8'd68 : mo <= flash_wr_data3[11];
				8'd69 : mo <= flash_wr_data3[10];
				8'd70 : mo <= flash_wr_data3[9];
				8'd71 : mo <= flash_wr_data3[8];
				8'd72 : mo <= flash_wr_data3[7];
				8'd73 : mo <= flash_wr_data3[6];
				8'd74 : mo <= flash_wr_data3[5];
				8'd75 : mo <= flash_wr_data3[4];
				8'd76 : mo <= flash_wr_data3[3];
				8'd77 : mo <= flash_wr_data3[2];
				8'd78 : mo <= flash_wr_data3[1];
				8'd79 : mo <= flash_wr_data3[0];					
				//flash_wr_data4
				8'd85 : mo <= flash_wr_data4[17];
				8'd86 : mo <= flash_wr_data4[16];
				8'd87 : mo <= flash_wr_data4[15];
				8'd88 : mo <= flash_wr_data4[14];
				8'd89 : mo <= flash_wr_data4[13];
				8'd90 : mo <= flash_wr_data4[12];
				8'd91 : mo <= flash_wr_data4[11];
				8'd92 : mo <= flash_wr_data4[10];
				8'd93 : mo <= flash_wr_data4[9];
				8'd94 : mo <= flash_wr_data4[8];
				8'd95 : mo <= flash_wr_data4[7];
				8'd96 : mo <= flash_wr_data4[6];
				8'd97 : mo <= flash_wr_data4[5];
				8'd98 : mo <= flash_wr_data4[4];
				8'd99 : mo <= flash_wr_data4[3];
				8'd100 : mo <= flash_wr_data4[2];
				8'd101 : mo <= flash_wr_data4[1];
				8'd102 : mo <= flash_wr_data4[0];						
				//flash_wr_data5
				8'd108 : mo <= flash_wr_data5[17];
				8'd109 : mo <= flash_wr_data5[16];
				8'd110 : mo <= flash_wr_data5[15];
				8'd111 : mo <= flash_wr_data5[14];
				8'd112 : mo <= flash_wr_data5[13];
				8'd113 : mo <= flash_wr_data5[12];
				8'd114 : mo <= flash_wr_data5[11];
				8'd115 : mo <= flash_wr_data5[10];
				8'd116 : mo <= flash_wr_data5[9];
				8'd117 : mo <= flash_wr_data5[8];
				8'd118 : mo <= flash_wr_data5[7];
				8'd119 : mo <= flash_wr_data5[6];
				8'd120 : mo <= flash_wr_data5[5];
				8'd121 : mo <= flash_wr_data5[4];
				8'd122 : mo <= flash_wr_data5[3];
				8'd123 : mo <= flash_wr_data5[2];
				8'd124 : mo <= flash_wr_data5[1];
				8'd125 : mo <= flash_wr_data5[0];
				//
				8'd131 : mo <= ewds_data[9];
				8'd132 : mo <= ewds_data[8];
				8'd133 : mo <= ewds_data[7];
				8'd134 : mo <= ewds_data[6];
				8'd135 : mo <= ewds_data[5];
				8'd136 : mo <= ewds_data[4];
				8'd137 : mo <= ewds_data[3];
				8'd138 : mo <= ewds_data[2];
				8'd139 : mo <= ewds_data[1];
				8'd140 : mo <= ewds_data[0];
				//
				default: mo <= 1'b0;
				endcase
				end
			else if(state == s_read) 
				begin
				case(rd_state_cnt)
				6'd1 : mo <= rd_cmd_data[9];
				6'd2 : mo <= rd_cmd_data[8];
				6'd3 : mo <= rd_cmd_data[7];
				6'd4 : mo <= rd_cmd_data[6];
				6'd5 : mo <= rd_cmd_data[5];
				6'd6 : mo <= rd_cmd_data[4];
				6'd7 : mo <= rd_cmd_data[3];
				6'd8 : mo <= rd_cmd_data[2];
				6'd9 : mo <= rd_cmd_data[1];
				6'd10 : mo <= rd_cmd_data[0];
				endcase
				end
			else if(state == s_eral)
				begin
				case(eral_state_cnt)
				4'd1 : mo <= eral_data[9];
				4'd2 : mo <= eral_data[8];
				4'd3 : mo <= eral_data[7];
				4'd4 : mo <= eral_data[6];
				4'd5 : mo <= eral_data[5];
				4'd6 : mo <= eral_data[4];
				4'd7 : mo <= eral_data[3];
				4'd8 : mo <= eral_data[2];
				4'd9 : mo <= eral_data[1];
				4'd10 : mo <= eral_data[0];
				endcase
				end	
		end	
   //mi
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) read_data <= 8'b0;
			else if(state == s_read) 
				begin
				case(rd_state_cnt)
				//flag byte
				6'd12 : read_data[39] <= mi;
				6'd13 : read_data[38] <= mi;
				6'd14 : read_data[37] <= mi;
				6'd15 : read_data[36] <= mi;
				6'd16 : read_data[35] <= mi;
				6'd17 : read_data[34] <= mi;
				6'd18 : read_data[33] <= mi;
				6'd19 : read_data[32] <= mi;
				//ip address bytes
				6'd20 : read_data[31] <= mi;
				6'd21 : read_data[30] <= mi;
				6'd22 : read_data[29] <= mi;
				6'd23 : read_data[28] <= mi;
				6'd24 : read_data[27] <= mi;
				6'd25 : read_data[26] <= mi;
				6'd26 : read_data[25] <= mi;
				6'd27 : read_data[24] <= mi;
				//
				6'd28 : read_data[23] <= mi;
				6'd29 : read_data[22] <= mi;
				6'd30 : read_data[21] <= mi;
				6'd31 : read_data[20] <= mi;
				6'd32 : read_data[19] <= mi;
				6'd33 : read_data[18] <= mi;
				6'd34 : read_data[17] <= mi;
				6'd35 : read_data[16] <= mi;
				//
				6'd36 : read_data[15] <= mi;
				6'd37 : read_data[14] <= mi;
				6'd38 : read_data[13] <= mi;
				6'd39 : read_data[12] <= mi;
				6'd40 : read_data[11] <= mi;
				6'd41 : read_data[10] <= mi;
				6'd42 : read_data[9] <= mi;
				6'd43 : read_data[8] <= mi;
				//
				6'd44 : read_data[7] <= mi;
				6'd45 : read_data[6] <= mi;
				6'd46 : read_data[5] <= mi;
				6'd47 : read_data[4] <= mi;
				6'd48 : read_data[3] <= mi;
				6'd49 : read_data[2] <= mi;
				6'd50 : read_data[1] <= mi;
				6'd51 : read_data[0] <= mi;
				endcase
				end
		end
	//
	
	always @ (posedge spi_clk)
		begin 
			if(~rst_n) system_valid <= 1'b0;
			else if(rd_state_cnt == 6'd51)  system_valid <= 1'b1;
			else  system_valid <= system_valid;
		end
	assign daq_receiver_ip = (read_data[39:32] == 8'ha5) ? read_data[31:0] 
										: default_receiver_ip;
	assign daq_receiver_mac = {16'habcd, daq_receiver_ip};
	//**************************************************************************
	//--------------------------------------------------------------------------
	//ram for buffering data 
	//--------------------------------------------------------------------------
	//**************************************************************************
	//RX RAM
	ETH_RAM3200X4 ETH_RAM3200X4_RX(
	.clka (RX_CLK),    // input clka
	.wea (rx_wea),    // input [0 : 0] wea
	.addra(rx_addra),   // input [11 : 0] addra
	.dina (RXD),     // input [3 : 0] dina
	.clkb (CLK50M),    // input clkb
	.addrb(rx_addrb),   // input [10 : 0] addrb
	.doutb(rx_doutb)    // output [7 : 0] doutb
	);
	//rx_wea
	assign rx_wea = (~rx_busy)& RX_DV & system_valid;
	//rx_addra
	always @ (posedge RX_CLK)
		begin
			if(~rst_n) rx_addra <= 12'b0;
			else if(rx_busy) rx_addra <= 12'b0;
			else if(RX_DV) rx_addra <= rx_addra + 1;
			else rx_addra <= 12'b0;
		end
	//**************************************************************************
	//--------------------------------------------------------------------------
	//get ARP/IP key word, and do crc32 check.
	//(1)because the data from pc is few, the length of frame is fixed at 64.
	//(2)because ARP paclet and IP packet are different, the mac and ip infomation
	//   is stored separately.
	//--------------------------------------------------------------------------
	//************************************************************************** 
	//~~~~~~~~~~~~~~~~part1: rx control and get packet information~~~~~~~~~~~~~~
	//rx_dv_s
	always @ (posedge CLK50M)
		begin
			if(~rst_n) rx_dv_s <= 2'b0;
			else rx_dv_s <= {rx_dv_s,RX_DV};
		end
	//tx_done_s
	always @ (posedge CLK50M)
		begin
			if(~rst_n) tx_done_s <= 2'b0;
			else tx_done_s <= {tx_done_s,tx_done};
		end
	//rx_busy
	always @ (posedge CLK50M)
		begin
			if(~rst_n) rx_busy <= 1'b0;
			else if(tx_done_s == 2'b01) rx_busy <= 1'b0;	
			else if(rx_addrb == 11'd73)
				begin
					if(rx_crc32_value_final != rx_crc32_value_ori) rx_busy <= 1'b0;
					else 
							case(packet_type)
							16'h0806: if(arp_receiver_ip != daq_receiver_ip) rx_busy <= 1'b0;	
										 else if((~(&arp_receiver_mac))||(arp_op != 16'h0001))
										 rx_busy <= 1'b0;	
							16'h0800: if(udp_receiver_ip != daq_receiver_ip) rx_busy <= 1'b0;	
										 else if((udp_receiver_mac != daq_receiver_mac)||(udp_tcp_type != 8'h11)
										 ||(udp_receiver_port_addr != daq_cad_port_addr))
										 rx_busy <= 1'b0;
							endcase		
				end
			else if(~system_valid) rx_busy <= 1'b0;
			else if(rx_dv_s == 2'b10)  rx_busy <= 1'b1;
			else rx_busy <= rx_busy;
		end
	//rx_addrb
	always @ (posedge CLK50M)
		begin
			if(~rst_n) rx_addrb <= 11'b0;
			else if(rx_busy)
				begin
					if(rx_addrb == 11'd75) rx_addrb <= rx_addrb;
					else rx_addrb <= rx_addrb + 1;
				end
			else rx_addrb <= 11'b0;
		end
	//packet_type
	always @ (posedge CLK50M)
		begin
			if(~rst_n) packet_type <= 16'b0;
			else 
				case(rx_addrb)
				   11'd0 : packet_type <= 16'b0;
					11'd21: packet_type[15:8] <= rx_doutb;
					11'd22: packet_type[7:0] <= rx_doutb;
				  default: packet_type <= packet_type;
				endcase
		end
	//arp_receiver_mac
	always @ (posedge CLK50M)
		begin
			if(~rst_n) arp_receiver_mac <= 48'b0;
			else 
				case(rx_addrb)
				   11'd9:  arp_receiver_mac[47:40] <= rx_doutb;
					11'd10: arp_receiver_mac[39:32] <= rx_doutb;
					11'd11: arp_receiver_mac[31:24] <= rx_doutb;
					11'd12: arp_receiver_mac[23:16] <= rx_doutb;
               11'd13: arp_receiver_mac[15:8] <= rx_doutb;
					11'd14: arp_receiver_mac[7:0] <= rx_doutb;					
				  default: arp_receiver_mac <= arp_receiver_mac;
				endcase
		end	
	//arp_op
	always @ (posedge CLK50M)
		begin
			if(~rst_n) arp_op <= 16'b0;
			else 
				case(rx_addrb)
				   11'd29:  arp_op[15:8] <= rx_doutb;
					11'd30: arp_op[7:0] <= rx_doutb;					
				  default: arp_op <= arp_op;
				endcase
		end
	//arp_sender_mac
	always @ (posedge CLK50M)
		begin
			if(~rst_n) arp_sender_mac <= 48'b0;
			else 
				case(rx_addrb)
				   11'd31:  arp_sender_mac[47:40] <= rx_doutb;
					11'd32: arp_sender_mac[39:32] <= rx_doutb;
					11'd33: arp_sender_mac[31:24] <= rx_doutb;
					11'd34: arp_sender_mac[23:16] <= rx_doutb;
               11'd35: arp_sender_mac[15:8] <= rx_doutb;
					11'd36: arp_sender_mac[7:0] <= rx_doutb;					
				  default: arp_sender_mac <= arp_sender_mac;
				endcase
		end
	//arp_sender_ip
	always @ (posedge CLK50M)
		begin
			if(~rst_n) arp_sender_ip <= 48'b0;
			else 
				case(rx_addrb)
				   11'd37:  arp_sender_ip[31:24] <= rx_doutb;
					11'd38: arp_sender_ip[23:16] <= rx_doutb;
					11'd39: arp_sender_ip[15:8] <= rx_doutb;
					11'd40: arp_sender_ip[7:0] <= rx_doutb;
				  default: arp_sender_ip <= arp_sender_ip;
				endcase
		end
	//arp_receiver_ip
	always @ (posedge CLK50M)
		begin
			if(~rst_n) arp_receiver_ip <= 48'b0;
			else 
				case(rx_addrb)
				   11'd47:  arp_receiver_ip[31:24] <= rx_doutb;
					11'd48: arp_receiver_ip[23:16] <= rx_doutb;
					11'd49: arp_receiver_ip[15:8] <= rx_doutb;
					11'd50: arp_receiver_ip[7:0] <= rx_doutb;
				  default: arp_receiver_ip <= arp_receiver_ip;
				endcase
		end	
	//udp_receiver_mac
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_receiver_mac <= 48'b0;
			else 
				case(rx_addrb)
				   11'd9:  udp_receiver_mac[47:40] <= rx_doutb;
					11'd10: udp_receiver_mac[39:32] <= rx_doutb;
					11'd11: udp_receiver_mac[31:24] <= rx_doutb;
					11'd12: udp_receiver_mac[23:16] <= rx_doutb;
               11'd13: udp_receiver_mac[15:8] <= rx_doutb;
					11'd14: udp_receiver_mac[7:0] <= rx_doutb;					
				  default: udp_receiver_mac <= udp_receiver_mac;
				endcase
		end
	//udp_sender_mac
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_sender_mac <= 48'b0;
			else 
				case(rx_addrb)
				   11'd15:  udp_sender_mac[47:40] <= rx_doutb;
					11'd16: udp_sender_mac[39:32] <= rx_doutb;
					11'd17: udp_sender_mac[31:24] <= rx_doutb;
					11'd18: udp_sender_mac[23:16] <= rx_doutb;
               11'd19: udp_sender_mac[15:8] <= rx_doutb;
					11'd20: udp_sender_mac[7:0] <= rx_doutb;					
				  default: udp_sender_mac <= udp_sender_mac;
				endcase
		end
	//udp_tcp_type
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_tcp_type <= 8'b0;
			else 
				case(rx_addrb)
				   11'd32:  udp_tcp_type <= rx_doutb;				
				  default: udp_tcp_type <= udp_tcp_type;
				endcase
		end	
	//udp_sender_ip
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_sender_ip <= 48'b0;
			else 
				case(rx_addrb)
				   11'd35:  udp_sender_ip[31:24] <= rx_doutb;
					11'd36: udp_sender_ip[23:16] <= rx_doutb;
					11'd37: udp_sender_ip[15:8] <= rx_doutb;
					11'd38: udp_sender_ip[7:0] <= rx_doutb;
				  default: udp_sender_ip <= udp_sender_ip;
				endcase
		end	
	//udp_receiver_ip
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_receiver_ip <= 48'b0;
			else 
				case(rx_addrb)
				   11'd39:  udp_receiver_ip[31:24] <= rx_doutb;
					11'd40: udp_receiver_ip[23:16] <= rx_doutb;
					11'd41: udp_receiver_ip[15:8] <= rx_doutb;
					11'd42: udp_receiver_ip[7:0] <= rx_doutb;
				  default: udp_receiver_ip <= udp_receiver_ip;
				endcase
		end
	//udp_sender_port_addr
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_sender_port_addr <= 48'b0;
			else 
				case(rx_addrb)
				   11'd43: udp_sender_port_addr[15:8] <= rx_doutb;
					11'd44: udp_sender_port_addr[7:0] <= rx_doutb;
				  default: udp_sender_port_addr <= udp_sender_port_addr;
				endcase
		end
	//udp_receiver_port_addr
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_receiver_port_addr <= 48'b0;
			else 
				case(rx_addrb)
				   11'd45: udp_receiver_port_addr[15:8] <= rx_doutb;
					11'd46: udp_receiver_port_addr[7:0] <= rx_doutb;
				  default: udp_receiver_port_addr <= udp_receiver_port_addr;
				endcase
		end	
	//app_cmd 
	//udp mapping
	//01, AD data mode;02, DA data; 03, DI data;  
	//04, DO data; 05, ip reset; 06, test data;
	//11, AD ack mode;12, DA ack; 13, DI ack; 
	//14, DO ack; 15, ip reset ack; 16, test ack;
	always @ (posedge CLK50M)
		begin
			if(~rst_n) app_cmd <= 8'b0;
			else 
				case(rx_addrb)
					11'd51: app_cmd <= rx_doutb;
					default: app_cmd <= app_cmd;
				endcase
		end
	//DO data cmd,0,0,0,DO data,0,0,0;
	//DA data cmd,0,0,0,DA data1,DA data2,DA data3,DA data3;
	//ipset data cmd,0,0,0,ipset data1,ipset data2,ipset data3,ipset data4;
	//test data cmd,0,0,0,test data1,test data2,test data3,test data4;
	//DI data cmd,0,0,0,0,0,0,0;
	//AD data cmd,0,0,0,MODE SELCECT,PATH SELECT,0,0.
	//udp_tx_s
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_tx_s <= 2'b0;
			else udp_tx_s <= {udp_tx_s,udp_tx};
		end
	//do_data_o
	assign do_data = do_data_o;
	always @ (posedge CLK50M)
		begin
			if(~rst_n) do_data_o <= 8'b0;
			else 
				case(rx_addrb)
					11'd55: do_data_o <= rx_doutb;
					default: do_data_o <= do_data_o;
				endcase
		end
	//do_data_valid
	//do data only need to be updated by high speed clock, not by low speed.
	always @ (posedge CLK50M)
		begin
			if(~rst_n) do_data_valid <= 1'b0;
			else if(do_data_done) do_data_valid <= 1'b0;
			else if(udp_tx_s == 2'b01) do_data_valid <= (app_cmd == 8'd04) ? 1'b1 : 1'b0;
		end
	//ao_data
	assign ao_data = ao_data_o;
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ao_data_o <= 8'b0;
			else 
				case(rx_addrb)
					11'd55: ao_data_o[31:24] <= rx_doutb;
					11'd56: ao_data_o[23:16] <= rx_doutb;
					11'd57: ao_data_o[15:8] <= rx_doutb;
					11'd58: ao_data_o[7:0] <= rx_doutb;
					default: ao_data_o <= ao_data_o;
				endcase
		end
	//ao_data_done_s
	//ao data need to be updated by low speed clock.
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ao_data_done_ext_s <= 2'b0;
			else ao_data_done_ext_s <= {ao_data_done_ext_s,ao_data_done_ext};
		end
	//ao_data_valid_o
	assign ao_data_valid_ext = ao_data_valid_o;
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ao_data_valid_o <= 1'b0;
			else if(ao_data_done_ext_s == 2'b01) ao_data_valid_o <= 1'b0;
			else if(udp_tx_s == 2'b01) ao_data_valid_o <= (app_cmd == 8'd02) ? 1'b1 : 1'b0;
		end
	//ip reset, udp_set_receiver_ip
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_set_receiver_ip <= 8'b0;
			else 
				case(rx_addrb)
					11'd55: udp_set_receiver_ip[31:24] <= rx_doutb;
					11'd56: udp_set_receiver_ip[23:16] <= rx_doutb;
					11'd57: udp_set_receiver_ip[15:8] <= rx_doutb;
					11'd58: udp_set_receiver_ip[7:0] <= rx_doutb;
					default: udp_set_receiver_ip <= udp_set_receiver_ip;
				endcase
		end
	//flash_wr_done_s 
	always @ (posedge CLK50M)
		begin
			if(~rst_n) flash_wr_done_s <= 2'b0;
			else flash_wr_done_s <= {flash_wr_done_s,flash_wr_done};
		end
	//flash_wr_cmd
	always @ (posedge CLK50M)
		begin
			if(~rst_n) flash_wr_cmd <= 1'b0;
			else if(flash_wr_done_s == 2'b01) flash_wr_cmd <= 1'b0;
			else if(udp_tx_s == 2'b01) flash_wr_cmd <= (app_cmd == 8'd05) ? 1'b1 : 1'b0;
		end	
	//test data
	always @ (posedge CLK50M)
		begin
			if(~rst_n) test_data <= 8'b0;
			else 
				case(rx_addrb)
					11'd55: test_data[31:24] <= rx_doutb;
					11'd56: test_data[23:16] <= rx_doutb;
					11'd57: test_data[15:8] <= rx_doutb;
					11'd58: test_data[7:0] <= rx_doutb;
					default: test_data <= test_data;
				endcase
		end
	//test_data_valid
	always @ (posedge CLK50M)
		begin
			if(~rst_n) test_data_valid <= 1'b0;
			else if(test_data_done) test_data_valid <= 1'b0;
			else if(udp_tx_s == 2'b01) test_data_valid <= (app_cmd == 8'd06) ? 1'b1 : 1'b0;
		end
	//di_data_valid
	always @ (posedge CLK50M)
		begin
			if(~rst_n) di_data_valid <= 1'b0;
			else if(di_data_done) di_data_valid <= 1'b0;
			else if(udp_tx_s == 2'b01) di_data_valid <= (app_cmd == 8'd03) ? 1'b1 : 1'b0;
		end
	//ai_data_sample_done
	//tell fpga the data have been sampled 
	reg [1 : 0]ai_data_sample_done_s = 2'b0;
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ai_data_sample_done_s <= 2'b0;
			else ai_data_sample_done_s <= {ai_data_sample_done_s,ai_data_sample_done};
		end
	//ai_data_to_sample
	//the flag to tell the ADC to sample the data
	reg ai_data_to_sample_o = 1'b0;
	assign ai_data_to_sample = ai_data_to_sample_o;
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ai_data_to_sample_o <= 1'b0;
			else if(ai_data_sample_done_s == 2'b01) ai_data_to_sample_o <= 1'b0;
			else if((udp_tx_s == 2'b01) && (app_cmd == 8'd01) && (ai_mode_select == 8'h01)) 
				ai_data_to_sample_o <= 1'b1;
		end
	//ai_data_valid
	//tell fpga to generate ack packet
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ai_data_valid <= 1'b0;
			else if(ai_packet_3_done) ai_data_valid <= 1'b0;
			else if(ai_data_sample_done_s == 2'b01) ai_data_valid <= 1'b1;
		end
	//ai data mode, data path
	assign ai_data_chanel_sel = ai_path_select;
	always @ (posedge CLK50M)
		begin
			if(~rst_n) 
				begin
				ai_mode_select <= 8'b0;
				ai_path_select <= 8'b0;
				end
			else 
				case(rx_addrb)
					11'd55: ai_mode_select <= rx_doutb;
					11'd56: ai_path_select <= rx_doutb;
				endcase
		end
	//arp_tx,udp_tx
	always @ (posedge CLK50M)
		begin
			if(~rst_n) 
				begin
					arp_tx <= 1'b0;
					udp_tx <= 1'b0;
				end
			else if(tx_done_s == 2'b01)
				begin
					arp_tx <= 1'b0;
					udp_tx <= 1'b0;
				end
			else
				case(rx_addrb)
					11'd73: if(rx_crc32_value_final == rx_crc32_value_ori)
									begin
										case(packet_type)
											16'h0806: 
								arp_tx <= ((&arp_receiver_mac)&&(arp_op == 16'h0001)
												&&(arp_receiver_ip == daq_receiver_ip))
												? 1'b1 : 1'b0;
											16'h0800: 
								udp_tx <= ((udp_receiver_mac == daq_receiver_mac) 
												&& (udp_tcp_type == 8'h11)
												&&(udp_receiver_ip == daq_receiver_ip)
												&&(udp_receiver_port_addr == daq_cad_port_addr))
												? 1'b1 : 1'b0;
											default: ;
										endcase
									end
					default: ;
				endcase
		end
	//~~~~~~~~~~~~~~~~~~~~~~~~~~part2: CRC32 check~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	CRC32_D8_AAL5 CRC32_D8_AAL5_RX(
	.dataout	(crc32_value_rx),
	.datain	(crc32_rxdata),
	.oldcrc	(crc32_oldcrc_rx),
	.enable	(crc32_enable_rx),
	.clk		(CLK50M),
	.rst_n		(rst_n)
	); 
	assign crc32_rxdata[7:0] = {rx_doutb[0],rx_doutb[1],rx_doutb[2],rx_doutb[3],
										 rx_doutb[4],rx_doutb[5],rx_doutb[6],rx_doutb[7]};
	//crc32_oldcrc_rx
	always @ (posedge CLK50M)
		begin
			if(~rst_n) crc32_oldcrc_rx <= 32'hffff_ffff;
			else if(rx_addrb == 11'd8) crc32_oldcrc_rx <= 32'hffff_ffff;
			else crc32_oldcrc_rx <= crc32_value_rx;
		end
	//crc32_enable
	always @ (posedge CLK50M)
		begin
			if(~rst_n) crc32_enable_rx <= 1'b0;
			else if(rx_addrb == 11'd8) crc32_enable_rx <= 1'b1;
			else if(rx_addrb == 11'd68) crc32_enable_rx <= 1'b0;
			else crc32_enable_rx <= crc32_enable_rx;
		end
	//crc32_value_final
	assign rx_crc32_value_final[0] = ~crc32_value_rx[7];
	assign rx_crc32_value_final[1] = ~crc32_value_rx[6];
	assign rx_crc32_value_final[2] = ~crc32_value_rx[5];
	assign rx_crc32_value_final[3] = ~crc32_value_rx[4];
	assign rx_crc32_value_final[4] = ~crc32_value_rx[3];
	assign rx_crc32_value_final[5] = ~crc32_value_rx[2];
	assign rx_crc32_value_final[6] = ~crc32_value_rx[1];
	assign rx_crc32_value_final[7] = ~crc32_value_rx[0];
	assign rx_crc32_value_final[8] = ~crc32_value_rx[15];
	assign rx_crc32_value_final[9] = ~crc32_value_rx[14];
	assign rx_crc32_value_final[10] = ~crc32_value_rx[13];
	assign rx_crc32_value_final[11] = ~crc32_value_rx[12];
	assign rx_crc32_value_final[12] = ~crc32_value_rx[11];
	assign rx_crc32_value_final[13] = ~crc32_value_rx[10];
	assign rx_crc32_value_final[14] = ~crc32_value_rx[9];
	assign rx_crc32_value_final[15] = ~crc32_value_rx[8]; 
	assign rx_crc32_value_final[16] = ~crc32_value_rx[23];
	assign rx_crc32_value_final[17] = ~crc32_value_rx[22];
	assign rx_crc32_value_final[18] = ~crc32_value_rx[21];
	assign rx_crc32_value_final[19] = ~crc32_value_rx[20];
	assign rx_crc32_value_final[20] = ~crc32_value_rx[19];
	assign rx_crc32_value_final[21] = ~crc32_value_rx[18];
	assign rx_crc32_value_final[22] = ~crc32_value_rx[17];
	assign rx_crc32_value_final[23] = ~crc32_value_rx[16]; 
	assign rx_crc32_value_final[24] = ~crc32_value_rx[31];
	assign rx_crc32_value_final[25] = ~crc32_value_rx[30];
	assign rx_crc32_value_final[26] = ~crc32_value_rx[29];
	assign rx_crc32_value_final[27] = ~crc32_value_rx[28];
	assign rx_crc32_value_final[28] = ~crc32_value_rx[27];
	assign rx_crc32_value_final[29] = ~crc32_value_rx[26];
	assign rx_crc32_value_final[30] = ~crc32_value_rx[25];
	assign rx_crc32_value_final[31] = ~crc32_value_rx[24];
	//rx_crc32_value_ori
	always @ (posedge CLK50M)
		begin
			if(~rst_n) rx_crc32_value_ori <= 32'h0000_0000;
			else 
				case(rx_addrb)
				11'd0: rx_crc32_value_ori <= 32'h0000_0000;
				11'd69: rx_crc32_value_ori[31:24] <= rx_doutb;
				11'd70: rx_crc32_value_ori[23:16] <= rx_doutb;
				11'd71: rx_crc32_value_ori[15:8] <= rx_doutb;
				11'd72: rx_crc32_value_ori[7:0] <= rx_doutb;
				default: rx_crc32_value_ori <= rx_crc32_value_ori;
				endcase
		end
	//**************************************************************************
	//--------------------------------------------------------------------------
	//ARP ACK packet generatation
	//--------------------------------------------------------------------------
	//************************************************************************** 
	//~~~~~~~~~~~~~~~~~~~~~part1: ARP ACK sending control~~~~~~~~~~~~~~~~~~~~~~~
	wire 				tx_ram_wea;
	wire [7 	: 0]	tx_dina;
	wire [10 : 0]	tx_ram_addra;
	reg [6 : 0] 	arp_tx_cnt = 7'b0;
	reg [7 : 0] 	tx_dina_arp = 8'b0;
	reg [7 : 0]		tx_dina_udp = 8'b0;
	reg 				tx_ram_wea_arp = 1'b0;
	reg [10 : 0]	tx_ram_addra_arp = 11'b0;
	reg				arp_ack_start = 1'b0;      
	parameter arp_op_ack = 80'h0806_0001_0800_0604_0002;
	//arp_tx_cnt
	always @ (posedge CLK50M)
		begin
		if(~rst_n) arp_tx_cnt <= 7'b0;
		else if(arp_tx)
			 begin
			 if(&arp_tx_cnt) arp_tx_cnt <= arp_tx_cnt;
			 else arp_tx_cnt <= arp_tx_cnt + 1;
			 end
		else  arp_tx_cnt <= 7'b0;
		end
	//tx_dina_arp
	always @ (posedge CLK50M)
		begin
			if(~rst_n) tx_dina_arp <= 8'b0;
			else if(arp_tx)
				case(arp_tx_cnt)
					7'd1,7'd2,7'd3,7'd4,7'd5,7'd6,7'd7: tx_dina_arp <= 8'h55;
					7'd8:				tx_dina_arp <= 8'hd5;
					7'd9,7'd41:		tx_dina_arp <= arp_sender_mac[47:40];//distination mac
					7'd10,7'd42:	tx_dina_arp <=	arp_sender_mac[39:32];
					7'd11,7'd43:	tx_dina_arp <=	arp_sender_mac[31:24];
					7'd12,7'd44:	tx_dina_arp <=	arp_sender_mac[23:16];
					7'd13,7'd45:	tx_dina_arp <=	arp_sender_mac[15:8];
					7'd14,7'd46:	tx_dina_arp <=	arp_sender_mac[7:0];
					7'd15,7'd31:	tx_dina_arp <= daq_receiver_mac[47:40];//source mac
					7'd16,7'd32: 	tx_dina_arp <=	daq_receiver_mac[39:32];
					7'd17,7'd33:	tx_dina_arp <=	daq_receiver_mac[31:24];
					7'd18,7'd34:	tx_dina_arp <=	daq_receiver_mac[23:16];
					7'd19,7'd35:	tx_dina_arp <=	daq_receiver_mac[15:8];
					7'd20,7'd36:	tx_dina_arp <=	daq_receiver_mac[7:0];
					7'd21:   		tx_dina_arp <=	arp_op_ack[79:72];//op of ack
					7'd22:  			tx_dina_arp <=	arp_op_ack[71:64];
					7'd23:   		tx_dina_arp <=	arp_op_ack[63:56];	
					7'd24:   		tx_dina_arp <=	arp_op_ack[55:48];
					7'd25:   		tx_dina_arp <=	arp_op_ack[47:40];
					7'd26:   		tx_dina_arp <=	arp_op_ack[39:32];
					7'd27:   		tx_dina_arp <=	arp_op_ack[31:24];
					7'd28:  	 		tx_dina_arp <=	arp_op_ack[23:16];
					7'd29:   		tx_dina_arp <=	arp_op_ack[15:8];
					7'd30:   		tx_dina_arp <=	arp_op_ack[7:0];
					7'd37: 			tx_dina_arp <=	daq_receiver_ip[31:24];//source ip
					7'd38: 			tx_dina_arp <=	daq_receiver_ip[23:16];
					7'd39: 			tx_dina_arp <=	daq_receiver_ip[15:8];
					7'd40: 			tx_dina_arp <=	daq_receiver_ip[7:0];
					7'd47: 			tx_dina_arp <= arp_sender_ip[31:24];//distination ip
					7'd48: 			tx_dina_arp <= arp_sender_ip[23:16];
					7'd49: 			tx_dina_arp <= arp_sender_ip[15:8];
					7'd50: 			tx_dina_arp <= arp_sender_ip[7:0];
					7'd51 ,7'd52 ,7'd53 ,7'd54 ,7'd55 ,7'd56 ,
					7'd57 ,7'd58 ,7'd59 ,7'd60 ,7'd61 ,7'd62 ,
					7'd63 ,7'd64 ,7'd65 ,7'd66 ,7'd67 ,7'd68 :
								tx_dina_arp <= 8'h0;
					7'd69:	tx_dina_arp <= tx_crc32_value_final[31:24];
					7'd70:	tx_dina_arp <= tx_crc32_value_final[23:16];
					7'd71:	tx_dina_arp <= tx_crc32_value_final[15:8];
					7'd72:	tx_dina_arp <= tx_crc32_value_final[7:0];
				endcase
		end
	assign tx_dina = (arp_tx)	? tx_dina_arp	:	((udp_tx)	? 
									tx_dina_udp	:	8'h00);
	//tx_ram_wea_arp
	always @ (posedge CLK50M)
		begin
			if(~rst_n) tx_ram_wea_arp <= 1'b0;
			else if(arp_tx)
				case(arp_tx_cnt)
				7'd1: tx_ram_wea_arp <= 1'b1;
				7'd73: tx_ram_wea_arp <= 1'b0;
				endcase
		end
	assign tx_ram_wea = tx_ram_wea_arp | tx_ram_wea_udp;
	//tx_ram_addra_arp
	always @ (posedge CLK50M)
		begin
			if(~rst_n) tx_ram_addra_arp <= 7'b0;
			else if(arp_tx) tx_ram_addra_arp <= arp_tx_cnt - 1;
			else tx_ram_addra_arp <= 7'b0;
		end
	assign tx_ram_addra = (arp_tx)	? tx_ram_addra_arp	:	((udp_tx)	? 
									tx_ram_addra_udp	:	11'b0);
	//arp_ack_start
	always @ (posedge CLK50M)
		begin
			if(~rst_n) arp_ack_start <= 1'b0;
			else if(tx_done_s == 2'b01) arp_ack_start <= 1'b0;
			else if(arp_tx_cnt == 7'd73) arp_ack_start <= 1'b1;
		end							
	//~~~~~~~~~~~~~~~~~~~~~part2: sending CRC32 check~~~~~~~~~~~~~~~~~~~~~~~~~
	CRC32_D8_AAL5 CRC32_D8_AAL5_TX(
	.dataout	(crc32_value_tx),
	.datain	(crc32_txdata),
	.oldcrc	(crc32_oldcrc_tx),
	.enable	(crc32_enable_tx),
	.clk		(CLK50M),
	.rst_n	(rst_n)
	); 
	//crc32_txdata
	assign crc32_txdata_arp[7:0] = {tx_dina_arp[0],tx_dina_arp[1],tx_dina_arp[2],
											  tx_dina_arp[3],tx_dina_arp[4],tx_dina_arp[5],
											  tx_dina_arp[6],tx_dina_arp[7]};
	assign crc32_txdata_udp[7:0] = {tx_dina_udp[0],tx_dina_udp[1],tx_dina_udp[2],
											  tx_dina_udp[3],tx_dina_udp[4],tx_dina_udp[5],
											  tx_dina_udp[6],tx_dina_udp[7]};
	assign crc32_txdata = (arp_tx)	? crc32_txdata_arp	:	((udp_tx)	? 
									crc32_txdata_udp	:	8'hff);
	//crc32_oldcrc_tx
	always @ (posedge CLK50M)
		begin
			if(~rst_n) crc32_oldcrc_tx_arp <= 32'hffff_ffff;
			else if(arp_tx_cnt == 11'd9) crc32_oldcrc_tx_arp <= 32'hffff_ffff;
			else crc32_oldcrc_tx_arp <= crc32_value_tx;
		end
	assign crc32_oldcrc_tx = (arp_tx)	? crc32_oldcrc_tx_arp	:	((udp_tx)	? 
									crc32_oldcrc_tx_udp	:	32'hffffffff);
	//crc32_enable
	always @ (posedge CLK50M)
		begin
			if(~rst_n) crc32_enable_tx_arp <= 1'b0;
			else if(arp_tx_cnt == 11'd9)  crc32_enable_tx_arp <= 1'b1;
			else if(arp_tx_cnt == 11'd69) crc32_enable_tx_arp <= 1'b0;
			else crc32_enable_tx_arp <= crc32_enable_tx_arp;
		end
	assign crc32_enable_tx = crc32_enable_tx_arp|crc32_enable_tx_udp;
	//crc32_value_final
	assign tx_crc32_value_final[0] = ~crc32_value_tx[7];
	assign tx_crc32_value_final[1] = ~crc32_value_tx[6];
	assign tx_crc32_value_final[2] = ~crc32_value_tx[5];
	assign tx_crc32_value_final[3] = ~crc32_value_tx[4];
	assign tx_crc32_value_final[4] = ~crc32_value_tx[3];
	assign tx_crc32_value_final[5] = ~crc32_value_tx[2];
	assign tx_crc32_value_final[6] = ~crc32_value_tx[1];
	assign tx_crc32_value_final[7] = ~crc32_value_tx[0];
	assign tx_crc32_value_final[8] = ~crc32_value_tx[15];
	assign tx_crc32_value_final[9] = ~crc32_value_tx[14];
	assign tx_crc32_value_final[10] = ~crc32_value_tx[13];
	assign tx_crc32_value_final[11] = ~crc32_value_tx[12];
	assign tx_crc32_value_final[12] = ~crc32_value_tx[11];
	assign tx_crc32_value_final[13] = ~crc32_value_tx[10];
	assign tx_crc32_value_final[14] = ~crc32_value_tx[9];
	assign tx_crc32_value_final[15] = ~crc32_value_tx[8]; 
	assign tx_crc32_value_final[16] = ~crc32_value_tx[23];
	assign tx_crc32_value_final[17] = ~crc32_value_tx[22];
	assign tx_crc32_value_final[18] = ~crc32_value_tx[21];
	assign tx_crc32_value_final[19] = ~crc32_value_tx[20];
	assign tx_crc32_value_final[20] = ~crc32_value_tx[19];
	assign tx_crc32_value_final[21] = ~crc32_value_tx[18];
	assign tx_crc32_value_final[22] = ~crc32_value_tx[17];
	assign tx_crc32_value_final[23] = ~crc32_value_tx[16]; 
	assign tx_crc32_value_final[24] = ~crc32_value_tx[31];
	assign tx_crc32_value_final[25] = ~crc32_value_tx[30];
	assign tx_crc32_value_final[26] = ~crc32_value_tx[29];
	assign tx_crc32_value_final[27] = ~crc32_value_tx[28];
	assign tx_crc32_value_final[28] = ~crc32_value_tx[27];
	assign tx_crc32_value_final[29] = ~crc32_value_tx[26];
	assign tx_crc32_value_final[30] = ~crc32_value_tx[25];
	assign tx_crc32_value_final[31] = ~crc32_value_tx[24];
	//**************************************************************************
	//--------------------------------------------------------------------------
	//IP ACK packet generatation
	//The UDP ACK of AO, DO, and IP RESET : ack cmd,0,0,0,0,0,0,0;
	//The UDP ACK of DI:  ack cmd,0,0,0,di data,0,0,0;
	//The UDP ACK of test: ack cmd,0,0,0,td byte1, td byte2, td byte3, td byte4;
	//The UDP ACK of AI(AI mode1, AI mode2 are same): ack cmd, packet number,0,0,ai data...
	//************************************************************************** 	
	//ip header
	reg  [15 : 0] ip_identification = 16'h0;//Identification, add 1 when sending 1 ip packet
	reg  [2	: 0] ai_packet_num = 3'b001;
	wire [15 : 0] ip_header_1 = 16'h4500;//version, header length
	wire [15 : 0] ip_header_2_1 = 16'h0024;//length in all, filled byte '0' not included.
	wire [15 : 0] ip_header_2_2 = 16'h04d4;//length in all, only for ai data packet1 and 2.
	wire [15 : 0] ip_header_2_3 = 16'h027c;//length in all, only for ai data packet3.
	wire [15 : 0] ip_header_3; //Identification, add 1 when sending 1 ip packet
	wire [15 : 0] ip_header_4 = 16'h0;//offset
	wire [15 : 0] ip_header_5 = 16'h4011;//TTL,protocol
	wire [15 : 0] ip_header_6 = 16'b0;//ip check_sum, only header included
   wire [15 : 0] ip_header_7;//souce ip
	wire [15 : 0] ip_header_8;
	wire [15 : 0] ip_header_9;//distination ip
	wire [15 : 0] ip_header_10;
	//udp header, 1 to 6 are false header, not a part of frame
	wire [15 : 0] udp_header_1 = daq_receiver_ip[31:16];//source ip
	wire [15 : 0] udp_header_2 = daq_receiver_ip[15:0];
	wire [15 : 0] udp_header_3 = udp_sender_ip[31:16];//distination ip
	wire [15 : 0] udp_header_4 = udp_sender_ip[15:0];
	wire [15 : 0] udp_header_5 = 16'h0011;//protocol
	wire [15 : 0] udp_header_6_1 = 16'h0010;//udp length, 8 udp header,8 data bytes
	wire [15 : 0] udp_header_6_2 = 16'h04c0;//udp length, 8 udp header,1204 data bytes
	wire [15 : 0] udp_header_6_3 = 16'h0268;//udp length, 8 udp header,604 data bytes
	wire [15 : 0] udp_header_7 = daq_cad_port_addr;	  //source port
	wire [15 : 0] udp_header_8 = udp_sender_port_addr;//distination port
	wire [15 : 0] udp_header_9_1 = 16'h0010;//udp length
	wire [15 : 0] udp_header_9_2 = 16'h04c0;//udp length
	wire [15 : 0] udp_header_9_3 = 16'h0268;//udp length
	wire [15 : 0] udp_header_10 = 16'h0;//udp checksum, all udp packet and virtual header
	//CHECKSUM adder
	reg [15	: 0] ip_checksum_adder1;
	reg [15	: 0] ip_checksum_adder2;
	reg [15	: 0] udp_checksum_adder1;
	reg [15	: 0] udp_checksum_adder2;
	wire [16	: 0] ip_checksum_res;
	wire [16	: 0] udp_checksum_res;
	//
	CHECKSUM_ADDER CHECKSUM_ADDER_IP (
	.a		(ip_checksum_adder1), 	// input [15 : 0] a
	.b		(ip_checksum_adder2), 	// input [15 : 0] b
	.clk	(CLK50M), 	// input clk
	.ce	(udp_tx), 	// input ce
	.s		(ip_checksum_res) 		// output [16 : 0] s
	);
	//
	CHECKSUM_ADDER CHECKSUM_ADDER_UDP (
	.a		(udp_checksum_adder1), 	// input [15 : 0] a
	.b		(udp_checksum_adder2), 	// input [15 : 0] b
	.clk	(CLK50M), 	// input clk
	.ce	(udp_tx), 	// input ce
	.s		(udp_checksum_res) 		// output [16 : 0] s
	);
	//~~~~~~~~~~~~~~~~~~~~~part1: ip hearer checksum caculate~~~~~~~~~~~~~~~~~~~~~~~~~
	reg [3 : 0] ip_checksum_cnt = 4'b0;
	//ip_checksum_cnt
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ip_checksum_cnt <= 4'b0;
			else if(&ip_checksum_cnt) ip_checksum_cnt <= 4'b0;
			else if(ip_checksum_cnt != 4'b0) ip_checksum_cnt <= ip_checksum_cnt + 1;
			else if(udp_tx_s == 2'b01) ip_checksum_cnt <= ip_checksum_cnt + 1;
			else if(ai_packet_1_done) ip_checksum_cnt <= ip_checksum_cnt + 1;
			else if(ai_packet_2_done) ip_checksum_cnt <= ip_checksum_cnt + 1;
			else ip_checksum_cnt <= ip_checksum_cnt;
		end
	//ip_checksum_adder1,ip_checksum_adder2
	//use negedge of clock, to avoid the waste of time, about a half
	//when udp_tx_s == 2'b01, ip_checksum_cnt add 1, while valid of all data is active.
	always @ (negedge CLK50M)
		begin
			if(~rst_n) 
				begin 
				ip_checksum_adder1 <= 16'b0; 
				ip_checksum_adder2 <= 16'b0;
				end
			else 
				case(ip_checksum_cnt)
				4'd1:	begin 
						ip_checksum_adder1 <= ip_header_1;
						ip_checksum_adder2 <= (do_data_valid | ao_data_valid_udp | flash_wr_cmd_udp
							| test_data_valid | di_data_valid)  ? ip_header_2_1 : 
							((ai_data_valid&ai_packet_num[2])? ip_header_2_3 : ip_header_2_2);
						end
				4'd2:	begin 
						ip_checksum_adder1 <= ip_header_3;
						ip_checksum_adder2 <= ip_checksum_res[16] ? (ip_checksum_res[15:0] + 1)
							: ip_checksum_res[15:0];
						end
				
				4'd3:	begin 
						ip_checksum_adder1 <= ip_header_4;
						ip_checksum_adder2 <= ip_checksum_res[16] ? (ip_checksum_res[15:0] + 1)
							: ip_checksum_res[15:0];
						end
				4'd4:	begin 
						ip_checksum_adder1 <= ip_header_5;
						ip_checksum_adder2 <= ip_checksum_res[16] ? (ip_checksum_res[15:0] + 1)
							: ip_checksum_res[15:0];
						end
				
				4'd5:	begin 
						ip_checksum_adder1 <= ip_header_6;
						ip_checksum_adder2 <= ip_checksum_res[16] ? (ip_checksum_res[15:0] + 1)
							: ip_checksum_res[15:0];
						end
				4'd6:	begin 
						ip_checksum_adder1 <= ip_header_7;
						ip_checksum_adder2 <= ip_checksum_res[16] ? (ip_checksum_res[15:0] + 1)
							: ip_checksum_res[15:0];
						end
				4'd7:	begin 
						ip_checksum_adder1 <= ip_header_8;
						ip_checksum_adder2 <= ip_checksum_res[16] ? (ip_checksum_res[15:0] + 1)
							: ip_checksum_res[15:0];
						end
				4'd8:	begin 
						ip_checksum_adder1 <= ip_header_9;
						ip_checksum_adder2 <= ip_checksum_res[16] ? (ip_checksum_res[15:0] + 1)
							: ip_checksum_res[15:0];
						end
				4'd9:	begin 
						ip_checksum_adder1 <= ip_header_10;
						ip_checksum_adder2 <= ip_checksum_res[16] ? (ip_checksum_res[15:0] + 1)
							: ip_checksum_res[15:0];
						end
				default : begin
						ip_checksum_adder1 <= 16'b0;
						ip_checksum_adder2 <= ip_checksum_res[16] ? (ip_checksum_res[15:0] + 1)
							: ip_checksum_res[15:0];
							 end
				endcase
		end
	//~~~~~~~~~~~~~~~~~~~~~part2: udp hearer checksum caculate~~~~~~~~~~~~~~~~~~~~~~~~~
	//all valid flag shift
	always @ (posedge CLK50M)
		begin
			if(~rst_n) 
				begin
					do_data_valid_s <= 2'b0;
					ao_data_valid_s <= 2'b0;
					flash_wr_cmd_s <= 2'b0;
					test_data_valid_s <= 2'b0;
					di_data_valid_s <= 2'b0;
					ai_data_valid_s <= 2'b0;
					ao_data_valid_udp_s <= 2'b0;
					flash_wr_cmd_udp_s <= 2'b0;
				end
			else
				begin
					do_data_valid_s <= {do_data_valid_s,do_data_valid};
					ao_data_valid_s <= {ao_data_valid_s,ao_data_valid_o};
					flash_wr_cmd_s <= {flash_wr_cmd_s,flash_wr_cmd};
					test_data_valid_s <= {test_data_valid_s,test_data_valid};
					di_data_valid_s <= {di_data_valid_s,di_data_valid};
					ai_data_valid_s <= {ai_data_valid_s,ai_data_valid};
					ao_data_valid_udp_s <= {ao_data_valid_udp_s,ao_data_valid_udp};
					flash_wr_cmd_udp_s <= {flash_wr_cmd_udp_s,flash_wr_cmd_udp};
				end
		end
	//valid for udp, because the previous of valid, for example 'ao_data_valid', is 
	//used by external low speed clock
	always @ (posedge CLK50M)
		begin
			if(~rst_n)
				begin
	 			ao_data_valid_udp <= 1'b0;
				flash_wr_cmd_udp <= 1'b0;
				end
			else if(ao_data_udp_done) ao_data_valid_udp <= 1'b0;
			else if(flash_wr_udp_done) flash_wr_cmd_udp <= 1'b0;
			else	
				begin
				ao_data_valid_udp <= (ao_data_valid_s == 2'b01) ? 1'b1 : ao_data_valid_udp;
				flash_wr_cmd_udp <= (flash_wr_cmd_s == 2'b01) ? 1'b1 : flash_wr_cmd_udp;
				end
		end
	//udp_checksum_cnt
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_checksum_cnt <= 10'b0;
			//reset signals
			else if(do_data_cs_done| ao_data_cs_done | flash_wr_cs_done 
				| test_data_cs_done | di_data_cs_done | ai_cs1_done
				| ai_cs2_done | ai_cs3_done)
						udp_checksum_cnt <= 10'b0;
			else if(udp_checksum_cnt != 10'b0) udp_checksum_cnt <= udp_checksum_cnt + 1;
			//triger signals
			else if(do_data_valid_s == 2'b01) udp_checksum_cnt <= udp_checksum_cnt + 1;
			else if(ao_data_valid_udp_s ==  2'b01) udp_checksum_cnt <= udp_checksum_cnt + 1;
			else if(flash_wr_cmd_udp_s ==  2'b01) udp_checksum_cnt <= udp_checksum_cnt + 1;
			else if(test_data_valid_s ==  2'b01) udp_checksum_cnt <= udp_checksum_cnt + 1;
			else if(di_data_valid_s ==  2'b01) udp_checksum_cnt <= udp_checksum_cnt + 1;
			else if((ai_data_valid_s ==  2'b01) && (ai_mode_select == 8'h01))
														  udp_checksum_cnt <= udp_checksum_cnt + 1;
			else if(ai_data_valid && ai_packet_phy1_done)
															udp_checksum_cnt <= udp_checksum_cnt + 1;
			else if(ai_data_valid && ai_packet_phy2_done)
															udp_checksum_cnt <= udp_checksum_cnt + 1;	
		end
	//
	/*//udp header, 1 to 6 are false header, not a part of frame
	wire [15 : 0] udp_header_1 = daq_receiver_ip[31:16];//source ip
	wire [15 : 0] udp_header_2 = daq_r2qw21`	aa3c x  eceiver_ip[15:0];
	wire [15 : 0] udp_header_3 = udp_sender_ip[31:16];//distination ip
	wire [15 : 0] udp_header_4 = udp_sender_ip[15:0];
	wire [15 : 0] udp_header_5 = 16'h0011;//protocol
	wire [15 : 0] udp_header_6_1 = 16'h0010;//udp length, 8 udp header,8 data bytes
	wire [15 : 0] udp_header_6_2 = 16'h04bc;//udp length, 8 udp header,1204 data bytes
	wire [15 : 0] udp_header_6_3 = 16'h0264;//udp length, 8 udp header,604 data bytes
	wire [15 : 0] udp_header_7 = daq_cad_port_addr;	  //source port
	wire [15 : 0] udp_header_8 = udp_sender_port_addr;//distination port
	wire [15 : 0] udp_header_9_1 = 16'h0010;//udp lengthvbki97pol;m ,ljkxddbb
	wire [15 : 0] udp_header_9_2 = 16'h04bc;//udp length
	wire [15 : 0] udp_header_9_3 = 16'h0264;//udp length
	wire [15 : 0] udp_header_10 = 16'h0;//udp checksum, all udp packet and virtual header*/
	always @ (negedge CLK50M)
		begin
			if(~rst_n) 
				begin 
				udp_checksum_adder1 <= 16'b0; 
				udp_checksum_adder2 <= 16'b0;
				end
			else 
				case(udp_checksum_cnt)
				10'd1:	begin 
						udp_checksum_adder1 <= udp_header_1; 
						udp_checksum_adder2 <= udp_header_2;
						end
				10'd2:	begin 
						udp_checksum_adder1 <= udp_header_3; 
						udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
						end
				10'd3:	begin 
						udp_checksum_adder1 <= udp_header_4; 
						udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
						end
				10'd4:	begin 
						udp_checksum_adder1 <= udp_header_5; 
						udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
						end
				10'd5:	begin 
						begin
						if(do_data_valid | ao_data_valid_udp | flash_wr_cmd_udp | test_data_valid
								| di_data_valid)	udp_checksum_adder1 <= udp_header_6_1;
						else if(ai_data_valid &&(ai_packet_num[0]| ai_packet_num[1])) 
								udp_checksum_adder1 <= udp_header_6_2;
						else if(ai_data_valid && ai_packet_num[2]) 
								udp_checksum_adder1 <= udp_header_6_3;
						end
						udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
						end
				10'd6:	begin 
						udp_checksum_adder1 <= udp_header_7; 
						udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
						end
				10'd7:	begin 
						udp_checksum_adder1 <= udp_header_8; 
						udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
						end
				10'd8:	begin 
						begin
						if(do_data_valid | ao_data_valid_udp | flash_wr_cmd_udp | test_data_valid
								| di_data_valid)	udp_checksum_adder1 <= udp_header_9_1;
						else if(ai_data_valid &&(ai_packet_num[0]| ai_packet_num[1])) 
								udp_checksum_adder1 <= udp_header_9_2;
						else if(ai_data_valid && ai_packet_num[2]) 
								udp_checksum_adder1 <= udp_header_9_3;
						end
						udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
						end
				10'd9:	begin 
						udp_checksum_adder1 <= udp_header_10; 
						udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
						end
				//IP ACK packet generatation
				//The UDP ACK of AO, DO, and IP RESET : ack cmd,0,0,0,0,0,0,0;
				//The UDP ACK of DI:  ack cmd,0,0,0,di data,0,0,0;
				//The UDP ACK of test: ack cmd,0,0,0,td byte1, td byte2, td byte3, td byte4;
				//The UDP ACK of AI(AI mode1, AI mode2 are same): ack cmd, packet number,0,0,
				//0,0,0,0,ai data...		
				//01, AD data mode;02, DA data; 03, DI data;  
				//04, DO data; 05, ip reset; 06, test data;
				//11, AD ack mode;12, DA ack; 13, DI ack; 
				//14, DO ack; 15, ip reset ack; 16, test ack;
				10'd10:	begin 
							begin
							if(do_data_valid)	udp_checksum_adder1 <= {8'h14,8'h0};
							else if(ao_data_valid_udp)	udp_checksum_adder1 <= {8'h12,8'h0};
							else if(flash_wr_cmd_udp)	udp_checksum_adder1 <= {8'h15,8'h0};
							else if(test_data_valid)	udp_checksum_adder1 <= {8'h16,8'h0};
							else if(di_data_valid)	udp_checksum_adder1 <= {8'h13,8'h0};
							else if(ai_data_valid)	udp_checksum_adder1 <= {8'h11,5'h0,ai_packet_num[2:0]}; 
							end
							udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
							end
				10'd11:	begin 
							udp_checksum_adder1 <= 16'h0; 
							udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
							end
				10'd12:	begin 
							begin
							if(do_data_valid)	udp_checksum_adder1 <= 16'h0;
							else if(ao_data_valid_udp)	udp_checksum_adder1 <= 16'h0;
							else if(flash_wr_cmd_udp)	udp_checksum_adder1 <= 16'h0;
							else if(test_data_valid)	udp_checksum_adder1 <= test_data[31:16];
							else if(di_data_valid)	udp_checksum_adder1 <= {di_data[7:0],8'h0};
							else if(ai_data_valid)	udp_checksum_adder1 <= 16'h0; 
							end
							udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
							end
				10'd13:	begin 
							begin
							if(do_data_valid)	udp_checksum_adder1 <= 16'h0;
							else if(ao_data_valid_udp)	udp_checksum_adder1 <= 16'h0;
							else if(flash_wr_cmd_udp)	udp_checksum_adder1 <= 16'h0;
							else if(test_data_valid)	udp_checksum_adder1 <= test_data[15:0];
							else if(di_data_valid)	udp_checksum_adder1 <= 16'h0;
							else if(ai_data_valid)	udp_checksum_adder1 <= 16'h0; 
							end
							udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
														: udp_checksum_res[15:0];
							end
				default: 
							begin
							//when ai_data_cnt is 1 or 2, fetch 2 24bit ai data,
							//when 3, 4, 5, send the 2 24bit ai data
							begin
							if(ai_data_cnt[2:0] == 3'b011) udp_checksum_adder1 <= ai_data_47_0[47:32]; 
							else if(ai_data_cnt[2:0] == 3'b100) udp_checksum_adder1 <= ai_data_47_0[31:16]; 
							else if(ai_data_cnt[2:0] == 3'b101) udp_checksum_adder1 <= ai_data_47_0[15:0]; 
							end
							udp_checksum_adder2 <= udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
															: udp_checksum_res[15:0];
							end
				endcase
		end
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~part3: infomation control~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//ai_data_47_0
	assign ai_data_47_0[47:24] = (ai_data_cnt == 3'b011) ?  ai_data : ai_data_47_0[47:24];
	assign ai_data_47_0[23:0] = (ai_data_cnt == 3'b100) ?  ai_data : ai_data_47_0[23:0];
	//ai_data_addrb
	//read ai data from ram
	//when ai_data_cnt is 1, ai_data_addrb add 1, so when ai_data_cnt is 2, ai_data_addrb add 2,
	//and ai_data_cnt is 3, data is out.
	reg [9 : 0] ai_data_addrb_o = 10'b0;
	assign ai_data_addrb = ai_data_addrb_o;
	always @ (posedge CLK50M)
		begin
			if(~rst_n)  ai_data_addrb_o <= 10'b0;
			else if(ai_packet_3_done) ai_data_addrb_o <= 10'b0;
			else if((ai_data_cnt == 3'b001)||(ai_data_cnt == 3'b010)) 
				ai_data_addrb_o <= ai_data_addrb_o + 1;
		end
	//
	assign ip_header_7 = daq_receiver_ip[31:16];//souce ip
	assign ip_header_8 = daq_receiver_ip[15:0];
	assign ip_header_9 = udp_sender_ip[31:16];//distination ip
	assign ip_header_10 = udp_sender_ip[15:0];
	//ip ip_identification
	assign ip_header_3 = ip_identification;
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ip_identification <= 16'b0;
			else if(tx_done_s == 2'b01) ip_identification <= ip_identification + 1;
			else ip_identification <= ip_identification;
		end
	//ai_packet_num
	//ai packet 1 and 2 have 400 samples, that is 1200 bytes
	//ai packet 3 have 200 samples, that is 600 bytes
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ai_packet_num <= 3'b001;
			else if(ai_packet_1_done) ai_packet_num <= 3'b010;
			else if(ai_packet_2_done) ai_packet_num <= 3'b100;
			else if(ai_packet_3_done) ai_packet_num <= 3'b001;
			else ai_packet_num <= ai_packet_num;
		end
	//ai_data_cnt
	always @ (posedge CLK50M)
		begin
			if(~rst_n)  ai_data_cnt <= 3'b0;
			else if(udp_checksum_cnt > 10'd13) ai_data_cnt <= ai_data_cnt + 1;
		end	
	//checksum caculation done	
	//to reset the checksum counter, and triger  the CRC32 calculation of UDP
	always @ (posedge CLK50M)
		begin
			if(~rst_n) 
				begin
				do_data_cs_done <= 1'b0;
				ao_data_cs_done <= 1'b0;
				flash_wr_cs_done <= 1'b0;
				test_data_cs_done <= 1'b0;
				di_data_cs_done <= 1'b0;
				ai_cs1_done <= 1'b0;
				ai_cs2_done <= 1'b0;
				ai_cs3_done <= 1'b0;
				end
			else if(do_data_cs_done| ao_data_cs_done | flash_wr_cs_done 
				| test_data_cs_done | di_data_cs_done | ai_cs1_done
				| ai_cs2_done | ai_cs3_done)
				begin
				do_data_cs_done <= 1'b0;
				ao_data_cs_done <= 1'b0;
				flash_wr_cs_done <= 1'b0;
				test_data_cs_done <= 1'b0;
				di_data_cs_done <= 1'b0;
				ai_cs1_done <= 1'b0;
				ai_cs2_done <= 1'b0;
				ai_cs3_done <= 1'b0;
				end
			else if(udp_checksum_cnt == 10'd14)
				begin
				if(do_data_valid)	do_data_cs_done <= 1'b1;
				else if(ao_data_valid_udp) ao_data_cs_done <= 1'b1;
				else if(flash_wr_cmd_udp) flash_wr_cs_done <= 1'b1;
				else if(test_data_valid) test_data_cs_done <= 1'b1;
				else if(di_data_valid) di_data_cs_done <= 1'b1;
				end
			else if(udp_checksum_cnt == 10'd614)
				begin
				if(ai_data_valid && ai_packet_num[0])	ai_cs1_done <= 1'b1;	
				else if(ai_data_valid && ai_packet_num[1]) ai_cs2_done <= 1'b1;
				end
         else if(udp_checksum_cnt == 10'd314)
				begin
				if(ai_data_valid && ai_packet_num[2])	ai_cs3_done <= 1'b1;	
				end 
		end
	//~~~~~~~~~~~~~~~~~~~~part4: 16bit ack data storing~~~~~~~~~~~~~~~~~~~~~~~~~
	//
	wire [7 : 0] ip_doutb;
	wire [7 : 0] udp_doutb;
	reg ip_wea = 1'b0;
	reg [3 : 0] ip_addra = 4'b0;
	reg [15 : 0] ip_dina = 16'b0;
	reg [4  : 0] ip_addrb = 5'b0;
	reg [15 : 0] ip_checksum_adder1_s;
	reg [15 : 0] ip_checksum_adder2_s;
	reg udp_wea = 1'b0;
	reg [9 : 0] udp_addra = 10'b0;
	reg [15 : 0] udp_dina = 16'b0;
	reg [10 : 0] udp_addrb = 11'b0;
	reg [15 : 0] udp_checksum_adder1_s;
	reg [15 : 0] udp_checksum_adder2_s;

	IP_HEADER_10X16 IP_HEADER_10X16 (
	.clka		(CLK50M), 	// input clka
	.wea		(ip_wea), 		// input [0 : 0] wea
	.addra	(ip_addra), // input [3 : 0] addra
	.dina		(ip_dina), 	// input [15 : 0] dina
	.clkb		(CLK50M), 	// input clkb
	.addrb	(ip_addrb), // input [4 : 0] addrb
	.doutb	(ip_doutb) 	// output [7 : 0] doutb
	);
	//ip_addra
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ip_addra  <= 4'b0;
			else 
				case(ip_checksum_cnt)
				4'h1,4'h2,4'h3,4'h4,4'h5,4'h6,4'h7,4'h8,4'h9,4'ha:
									ip_addra  <= ip_checksum_cnt - 1;
				4'hb : ip_addra  <= 4'h5;
				default: ip_addra  <= 4'b0;
				endcase
		end
	//ip_wea
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ip_wea  <= 1'b0;
			else 
				case(ip_checksum_cnt)
				4'h1 : ip_wea <= 1'b1;
				4'hc : ip_wea <= 1'b0;
				default: ip_wea  <=ip_wea;
				endcase
		end
	//ip_checksum_adder1_s, ip_checksum_adder1_s
	always @ (negedge CLK50M)
		begin
			if(~rst_n) 
				begin 
				ip_checksum_adder1_s  <= 16'b0;
				ip_checksum_adder2_s  <= 16'b0;
				end
			else 
				begin
				ip_checksum_adder1_s  <= ip_checksum_adder1;
				ip_checksum_adder2_s  <= ip_checksum_adder2;
				end
		end
   //ip_dina
	wire [15 : 0] ip_checksum_res_final = ~ip_checksum_res;
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ip_dina <= 16'b0;
			else 
				case(ip_checksum_cnt)
				4'h1: ip_dina <= {ip_checksum_adder1[7:0],ip_checksum_adder1[15:8]};
				4'h2: ip_dina <= {ip_checksum_adder2_s[7:0],ip_checksum_adder2_s[15:8]};
				4'hb: ip_dina <= {ip_checksum_res_final[7:0],ip_checksum_res_final[15:8]};
				default:  ip_dina <= {ip_checksum_adder1_s[7:0],ip_checksum_adder1_s[15:8]};
				endcase
		end
	//ip_addrb
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ip_addrb <= 5'b0;
			else 
				case(tx_ram_addra_udp0)
				11'd21 ,11'd22 ,11'd23 ,11'd24 ,11'd25 ,11'd26 ,11'd27 ,11'd28 ,11'd29 ,11'd30 ,
				11'd31 ,11'd32 ,11'd33 ,11'd34 ,11'd35 ,11'd36 ,11'd37 ,11'd38 ,11'd39:
				ip_addrb <= ip_addrb  + 1;
				default:  ip_addrb <= 5'b0;
				endcase
		end
	//
	UDP_HEADER_DATA_606X16 UDP_HEADER_DATA_606X16 (
	.clka		(CLK50M), 	// input clka
	.wea		(udp_wea), 		// input [0 : 0] wea
	.addra	(udp_addra), // input [9 : 0] addra
	.dina		(udp_dina), 	// input [15 : 0] dina
	.clkb		(CLK50M), 	// input clkb
	.addrb	(udp_addrb), // input [10 : 0] addrb
	.doutb	(udp_doutb)  // output [7 : 0] doutb
	);
	//udp_wea
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_wea  <= 1'b0;
			else if(| ao_data_cs_done | flash_wr_cs_done 
				| test_data_cs_done | di_data_cs_done | ai_cs1_done
				| ai_cs2_done | ai_cs3_done)
						udp_wea <= 1'b0;
			else 
				case(udp_checksum_cnt)
				10'd6 : udp_wea <= 1'b1;
				default: udp_wea  <= udp_wea;
				endcase
		end
	//udp_addra
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_addra  <= 10'b0;
			else if(do_data_cs_done| ao_data_cs_done | flash_wr_cs_done 
				| test_data_cs_done | di_data_cs_done | ai_cs1_done
				| ai_cs2_done | ai_cs3_done)
						udp_addra  <= 10'b0;
			else if(udp_addra == 10'd7)
				begin
					if(do_data_valid | ao_data_valid_udp | flash_wr_cmd_udp | test_data_valid
						| di_data_valid) udp_addra  <= 10'd3;
					else  udp_addra  <= udp_addra + 1;
				end
			else if(udp_addra == 10'h25f) udp_addra  <= 10'd3;
			else if(udp_addra == 10'h133)
				begin 
					if(ai_packet_num[2]) udp_addra  <= 10'd3;
					else  udp_addra  <= udp_addra + 1;
				end
			else if(udp_wea) udp_addra  <= udp_addra + 1;
		end
	//udp_dina
	wire [15 : 0] udp_checksum_res0 =  udp_checksum_res[16] ? (udp_checksum_res[15:0] + 1) 
															: udp_checksum_res[15:0];
	wire [15 : 0] udp_checksum_res_final = ~ udp_checksum_res0;
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_dina <= 16'b0;
			else if(udp_checksum_cnt == 10'd14)
				begin 
					if(do_data_valid | ao_data_valid_udp | flash_wr_cmd_udp | test_data_valid
						| di_data_valid)
					udp_dina <= {udp_checksum_res_final[7:0],udp_checksum_res_final[15:8]};
					else udp_dina <= {udp_checksum_adder1[7:0],udp_checksum_adder1[15:8]};
				end
			else if(udp_addra == 10'h25f) 
				udp_dina <= {udp_checksum_res_final[7:0],udp_checksum_res_final[15:8]};
			else if(udp_addra == 10'h133)
				begin
				if(ai_packet_num[2])  
					udp_dina <= {udp_checksum_res_final[7:0],udp_checksum_res_final[15:8]};
				else udp_dina <= {udp_checksum_adder1[7:0],udp_checksum_adder1[15:8]};
				end
			else udp_dina <= {udp_checksum_adder1[7:0],udp_checksum_adder1[15:8]};
		end	
	//udp_addrb
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_addrb <= 11'b0;
			else if(~tx_ram_wea) udp_addrb <= 11'b0;
			else if(tx_ram_addra_udp0 >11'd40) udp_addrb <= udp_addrb + 1;
			else udp_addrb <= 11'b0;
		end
	//~~~~~~~~~~~~~~~~~~~~part5: crc32 caculation for udp~~~~~~~~~~~~~~~~~~~~~~~
	//
	always @ (posedge CLK50M)
		begin
			if(~rst_n) tx_ram_wea_udp0 <= 1'b0;
			else if(do_data_cs_done| ao_data_cs_done | flash_wr_cs_done 
				| test_data_cs_done | di_data_cs_done | ai_cs1_done
				| ai_cs2_done | ai_cs3_done)  tx_ram_wea_udp0 <= 1'b1;
			else if(do_data_done | ao_data_udp_done | flash_wr_udp_done
				| test_data_done | di_data_done | ai_packet_1_done 
				| ai_packet_2_done | ai_packet_3_done)  tx_ram_wea_udp0 <= 1'b0;
	   end
	//
	always @ (posedge CLK50M)
		begin
			if(~rst_n) tx_ram_wea_udp <= 1'b0;
			else tx_ram_wea_udp <= tx_ram_wea_udp0;
		end
	//
	always @ (posedge CLK50M)
		begin
			if(~rst_n) tx_ram_addra_udp0 <= 11'b0;
			else if(tx_done_s == 2'b01) tx_ram_addra_udp0 <= 11'b0;
			else if(ai_packet_phy1_done || ai_packet_phy2_done) tx_ram_addra_udp0 <= 11'b0;
			else if(tx_ram_wea_udp) tx_ram_addra_udp0 <= tx_ram_addra_udp0 + 1;
		end
	//
	always @ (posedge CLK50M)
		begin
			if(~rst_n) tx_ram_addra_udp <= 11'b0;
			else tx_ram_addra_udp <=  tx_ram_addra_udp0;
		end
	//
	always @ (posedge CLK50M)
		begin
			if(~rst_n) tx_dina_udp <= 8'b0;
			else if(tx_ram_wea_udp0)
				begin
				if(do_data_valid | ao_data_valid_udp | flash_wr_cmd_udp | 
					test_data_valid | di_data_valid)
					case(tx_ram_addra_udp0)
					11'd0,11'd1,11'd2,11'd3,11'd4,11'd5,11'd6 : tx_dina_udp <= 8'h55;
					11'd7 : tx_dina_udp <= 8'hd5;
					//next start crc32 calculation
					11'd8 : tx_dina_udp <= udp_sender_mac[47:40];
					11'd9 : tx_dina_udp <= udp_sender_mac[39:32];
					11'd10 : tx_dina_udp <= udp_sender_mac[31:24];
					11'd11 : tx_dina_udp <= udp_sender_mac[23:16];
               11'd12 : tx_dina_udp <= udp_sender_mac[15:8];
					11'd13 : tx_dina_udp <= udp_sender_mac[7:0];
						11'd14 : tx_dina_udp <= daq_receiver_mac[47:40];
						11'd15 : tx_dina_udp <= daq_receiver_mac[39:32];
						11'd16 : tx_dina_udp <= daq_receiver_mac[31:24];
						11'd17 : tx_dina_udp <= daq_receiver_mac[23:16];
						11'd18 : tx_dina_udp <= daq_receiver_mac[15:8];
						11'd19 : tx_dina_udp <= daq_receiver_mac[7:0];
					11'd20 : tx_dina_udp <= 8'h08;
					11'd21 : tx_dina_udp <= 8'h00;
						11'd22 ,11'd23 ,11'd24 ,11'd25 ,11'd26 ,11'd27 ,11'd28 ,11'd29 ,11'd30 ,11'd31 ,
						11'd32 ,11'd33 ,11'd34 ,11'd35 ,11'd36 ,11'd37 ,11'd38 ,11'd39 ,11'd40 ,11'd41 
						: tx_dina_udp <= ip_doutb;
					11'd42 ,11'd43 ,11'd44 ,11'd45 ,11'd46 ,11'd47 ,11'd48 ,11'd49,
					11'd50 ,11'd51 ,11'd52 ,11'd53 ,11'd54 ,11'd55 ,11'd56 ,11'd57
					: tx_dina_udp <= udp_doutb;
						11'd58 ,11'd59 ,11'd60 ,11'd61 ,11'd62 ,11'd63 ,11'd64 ,11'd65 ,11'd66 ,11'd67 
						: tx_dina_udp <= 8'h0;
					11'd68 : tx_dina_udp <= tx_crc32_value_final[31:24];
					11'd69 : tx_dina_udp <= tx_crc32_value_final[23:16];
					11'd70 : tx_dina_udp <= tx_crc32_value_final[15:8];
					11'd71 : tx_dina_udp <= tx_crc32_value_final[7:0];
					endcase
				else if(ai_data_valid & (ai_packet_num[0] |  ai_packet_num[1]))
					case(tx_ram_addra_udp0)
					11'd0,11'd1,11'd2,11'd3,11'd4,11'd5,11'd6 : tx_dina_udp <= 8'h55;
					11'd7 : tx_dina_udp <= 8'hd5;
					//next start crc32 calculation
					11'd8 : tx_dina_udp <= udp_sender_mac[47:40];
					11'd9 : tx_dina_udp <= udp_sender_mac[39:32];
					11'd10 : tx_dina_udp <= udp_sender_mac[31:24];
					11'd11 : tx_dina_udp <= udp_sender_mac[23:16];
               11'd12 : tx_dina_udp <= udp_sender_mac[15:8];
					11'd13 : tx_dina_udp <= udp_sender_mac[7:0];
						11'd14 : tx_dina_udp <= daq_receiver_mac[47:40];
						11'd15 : tx_dina_udp <= daq_receiver_mac[39:32];
						11'd16 : tx_dina_udp <= daq_receiver_mac[31:24];
						11'd17 : tx_dina_udp <= daq_receiver_mac[23:16];
						11'd18 : tx_dina_udp <= daq_receiver_mac[15:8];
						11'd19 : tx_dina_udp <= daq_receiver_mac[7:0];
					11'd20 : tx_dina_udp <= 8'h08;
					11'd21 : tx_dina_udp <= 8'h00;
						11'd22 ,11'd23 ,11'd24 ,11'd25 ,11'd26 ,11'd27 ,11'd28 ,11'd29 ,11'd30 ,11'd31 ,
						11'd32 ,11'd33 ,11'd34 ,11'd35 ,11'd36 ,11'd37 ,11'd38 ,11'd39 ,11'd40 ,11'd41 
						: tx_dina_udp <= ip_doutb;
					11'd1258 : tx_dina_udp <= tx_crc32_value_final[31:24];
					11'd1259 : tx_dina_udp <= tx_crc32_value_final[23:16];
					11'd1260 : tx_dina_udp <= tx_crc32_value_final[15:8];
					11'd1261 : tx_dina_udp <= tx_crc32_value_final[7:0];
					default: tx_dina_udp <= udp_doutb;
					endcase
				else if(ai_data_valid & ai_packet_num[2])
					case(tx_ram_addra_udp0)
					11'd0,11'd1,11'd2,11'd3,11'd4,11'd5,11'd6 : tx_dina_udp <= 8'h55;
					11'd7 : tx_dina_udp <= 8'hd5;
					//next start crc32 calculation
					11'd8 : tx_dina_udp <= udp_sender_mac[47:40];
					11'd9 : tx_dina_udp <= udp_sender_mac[39:32];
					11'd10 : tx_dina_udp <= udp_sender_mac[31:24];
					11'd11 : tx_dina_udp <= udp_sender_mac[23:16];
               11'd12 : tx_dina_udp <= udp_sender_mac[15:8];
					11'd13 : tx_dina_udp <= udp_sender_mac[7:0];
						11'd14 : tx_dina_udp <= daq_receiver_mac[47:40];
						11'd15 : tx_dina_udp <= daq_receiver_mac[39:32];
						11'd16 : tx_dina_udp <= daq_receiver_mac[31:24];
						11'd17 : tx_dina_udp <= daq_receiver_mac[23:16];
						11'd18 : tx_dina_udp <= daq_receiver_mac[15:8];
						11'd19 : tx_dina_udp <= daq_receiver_mac[7:0];
					11'd20 : tx_dina_udp <= 8'h08;
					11'd21 : tx_dina_udp <= 8'h00;
						11'd22 ,11'd23 ,11'd24 ,11'd25 ,11'd26 ,11'd27 ,11'd28 ,11'd29 ,11'd30 ,11'd31 ,
						11'd32 ,11'd33 ,11'd34 ,11'd35 ,11'd36 ,11'd37 ,11'd38 ,11'd39 ,11'd40 ,11'd41 
						: tx_dina_udp <= ip_doutb;
					11'd658 : tx_dina_udp <= tx_crc32_value_final[31:24];
					11'd659 : tx_dina_udp <= tx_crc32_value_final[23:16];
					11'd660 : tx_dina_udp <= tx_crc32_value_final[15:8];
					11'd661 : tx_dina_udp <= tx_crc32_value_final[7:0];
					default: tx_dina_udp <= udp_doutb;
					endcase
				end
		end
	//crc32_oldcrc_tx_udp
	always @ (posedge CLK50M)
		begin
			if(~rst_n) crc32_oldcrc_tx_udp <= 32'hffff_ffff;
			else if(tx_ram_addra_udp0 == 11'd8) crc32_oldcrc_tx_udp <= 32'hffff_ffff;
			else crc32_oldcrc_tx_udp <= crc32_value_tx;
		end	
	//crc32_enable_tx_udp
	always @ (posedge CLK50M)
		begin
			if(~rst_n) crc32_enable_tx_udp <= 1'b0;
			else if(do_data_valid | ao_data_valid_udp | flash_wr_cmd_udp | 
					test_data_valid | di_data_valid)
					begin
					if(tx_ram_addra_udp0 == 11'd8)  crc32_enable_tx_udp <= 1'b1;
					else if(tx_ram_addra_udp0 == 11'd68) crc32_enable_tx_udp <= 1'b0;
					end
			else if(ai_data_valid & (ai_packet_num[0] |  ai_packet_num[1]))
					begin
					if(tx_ram_addra_udp0 == 11'd8)  crc32_enable_tx_udp <= 1'b1;
					else if(tx_ram_addra_udp0 == 11'd1258) crc32_enable_tx_udp <= 1'b0;
					end
			else if(ai_data_valid & ai_packet_num[2])
					begin
					if(tx_ram_addra_udp0 == 11'd8)  crc32_enable_tx_udp <= 1'b1;
					else if(tx_ram_addra_udp0 == 11'd658) crc32_enable_tx_udp <= 1'b0;
					end
			else crc32_enable_tx_udp <= crc32_enable_tx_udp;
		end
	//do_data_done, ao_data_udp_done,flash_wr_udp_done,test_data_done
	//di_data_done, ai_packet_1_done, ai_packet_2_done, ai_packet_3_done
	always @ (posedge CLK50M)
		begin
			if(~rst_n) 
			begin
			do_data_done <= 1'b0;
			ao_data_udp_done <= 1'b0;
			flash_wr_udp_done <= 1'b0;
			test_data_done <= 1'b0;
			di_data_done <= 1'b0;
			ai_packet_1_done <= 1'b0;
			ai_packet_2_done <= 1'b0;
			ai_packet_3_done <= 1'b0; 
			end
			else 
			begin
			case(tx_ram_addra_udp0)
				11'd71: 	begin	
							do_data_done <= do_data_valid ? 1'b1 : 1'b0;
							ao_data_udp_done <= ao_data_valid_udp ? 1'b1 : 1'b0;
							flash_wr_udp_done <= flash_wr_cmd_udp ? 1'b1 : 1'b0;
							test_data_done <= test_data_valid ? 1'b1 : 1'b0;
							di_data_done <= di_data_valid ? 1'b1 : 1'b0;
							end
				11'd660:	ai_packet_3_done <= (ai_data_valid && ai_packet_num[2])  ? 1'b1 : 1'b0;
				11'd1260:	begin
								ai_packet_1_done <= (ai_data_valid && ai_packet_num[0])  ? 1'b1 : 1'b0;
								ai_packet_2_done <= (ai_data_valid && ai_packet_num[1])  ? 1'b1 : 1'b0;
								end
				default:	begin
							do_data_done <= 1'b0;
							ao_data_udp_done <= 1'b0;
							flash_wr_udp_done <= 1'b0;
							test_data_done <= 1'b0;
							di_data_done <= 1'b0;
							ai_packet_1_done <= 1'b0;
							ai_packet_2_done <= 1'b0;
							ai_packet_3_done <= 1'b0; 
							end
			endcase
			end
		end
	//udp_ack_start
	always @ (posedge CLK50M)
		begin
			if(~rst_n) udp_ack_start <= 1'b0;
			else if((tx_done_s == 2'b01) || ai_packet_phy1_done || ai_packet_phy2_done) 
				udp_ack_start <= 1'b0;
			else if(do_data_done | ao_data_udp_done | flash_wr_udp_done
				| test_data_done | di_data_done | ai_packet_1_done 
				| ai_packet_2_done | ai_packet_3_done) udp_ack_start <= 1'b1;
			else  udp_ack_start <=  udp_ack_start;
		end	
	//**************************************************************************
	//--------------------------------------------------------------------------
	//tx_ram data transmit
	//--------------------------------------------------------------------------
	//**************************************************************************
	assign tx_clk_phy = ~TX_CLK;
	//tx_cnt_phy
	always @ (posedge tx_clk_phy)
		begin
			if(~rst_n) tx_cnt_phy <= 12'b0;
			else if(arp_ack_start) tx_cnt_phy <= tx_cnt_phy + 1;
			else if(udp_ack_start) tx_cnt_phy <= tx_cnt_phy + 1;
			else tx_cnt_phy <= 12'b0;
		end
	//tx_ram_addrb
	assign tx_ram_addrb = tx_cnt_phy - 1;
	//tx_en_o
	assign TX_EN = tx_en_o;
	always @ (posedge tx_clk_phy)
		begin
			if(~rst_n) tx_en_o <= 1'b0;
			else if(arp_ack_start)
				begin
					case(tx_cnt_phy)
						12'd1: tx_en_o <= 1'b1;
						12'd145: tx_en_o <= 1'b0;
					endcase
				end
			else if(udp_ack_start)
				begin
					case(tx_cnt_phy)
						12'd1: tx_en_o <= 1'b1;
						12'd145: tx_en_o <= (tx_ram_addra_udp0 == 11'd74) ? 1'b0 : 1'b1;
						12'd1325:  tx_en_o <= (tx_ram_addra_udp0 == 11'd663) ? 1'b0 : 1'b1;
						12'd2525: tx_en_o <= 1'b0;
					endcase
				end
		end
	//TXD
	assign TXD = tx_ram_doutb;
	//tx_done, the flag of the third ai data packet have sent from the phy
	always @ (posedge tx_clk_phy)
		begin
			if(~rst_n) tx_done <= 1'b0;
			else if(tx_done)  tx_done <= 1'b0;
			else if(arp_ack_start)
				begin
					if(tx_cnt_phy == 12'd145) tx_done <= 1'b1;
				end
			else if(udp_ack_start)
			   begin
					if(tx_cnt_phy == {tx_ram_addra_udp0,1'b1} )
						begin
						if(tx_ram_addra_udp0 < 11'd100) tx_done <= 1'b1;
						else if(ai_packet_num[0])  tx_done <= 1'b1;
						end
						 
				end
		end
	//
	ETH_RAM1600X8 ETH_RAM1600X8_TX (
	.clka		(CLK50M), // input clka
	.wea		(tx_ram_wea), // input [0 : 0] wea
	.addra	(tx_ram_addra), // input [10 : 0] addra
	.dina		(tx_dina), // input [7 : 0] dina
	.clkb		(tx_clk_phy), // input clkb
	.addrb	(tx_ram_addrb), // input [11 : 0] addrb
	.doutb	(tx_ram_doutb) // output [3 : 0] doutb
	);
	
  //the flag of the first packet have sent from the phy
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ai_packet_phy1_done <= 1'b0;
			else if(ai_packet_phy1_done) ai_packet_phy1_done <= 1'b0;
			else if(ai_data_valid)
				begin
				if(udp_ack_start)
					begin
						if((tx_cnt_phy == {tx_ram_addra_udp0,1'b1} )&&(ai_packet_num[1])) 
							ai_packet_phy1_done <= 1'b1;
					end
				end
		end
	//the flag of the second packet have sent from the phy
	always @ (posedge CLK50M)
		begin
			if(~rst_n) ai_packet_phy2_done <= 1'b0;
			else if(ai_packet_phy2_done) ai_packet_phy2_done <= 1'b0;
			else if(ai_data_valid)
				begin
				if(udp_ack_start)
					begin
						if((tx_cnt_phy == {tx_ram_addra_udp0,1'b1} )&&(ai_packet_num[2])) 
							ai_packet_phy2_done <= 1'b1;
					end
				end
		end
		
	
	endmodule
	
	
	
	
	

 

 

 

 

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值