module eth_img_pkt(
    input                 rst_n          ,   //¸´Î»ÐÅºÅ£¬µÍµçÆ½ÓÐÐ§
    //Í¼ÏñÏà¹ØÐÅºÅ
    input                 cam_pclk       ,   //ÏñËØÊ±ÖÓ
    input                 img_vsync      ,   //Ö¡Í¬²½ÐÅºÅ
    input                 img_data_en    ,   //Êý¾ÝÓÐÐ§Ê¹ÄÜÐÅºÅ
    input        [15:0]   img_data       ,   //ÓÐÐ§Êý¾Ý 
    
    input                 transfer_flag  ,   //Í¼Ïñ¿ªÊ¼´«Êä±êÖ¾,1:¿ªÊ¼´«Êä 0:Í£Ö¹´«Êä
    //ÒÔÌ«ÍøÏà¹ØÐÅºÅ 
    input                 eth_tx_clk     ,   //ÒÔÌ«Íø·¢ËÍÊ±ÖÓ
    input                 udp_tx_req     ,   //udp·¢ËÍÊý¾ÝÇëÇóÐÅºÅ
    input                 udp_tx_done    /* synthesis PAP_MARK_DEBUG="1" */,   //udp·¢ËÍÊý¾ÝÍê³ÉÐÅºÅ                               
    output  reg           udp_tx_start_en,   //udp¿ªÊ¼·¢ËÍÐÅºÅ
    output       [31:0]   udp_tx_data    /* synthesis PAP_MARK_DEBUG="1" */,   //udp·¢ËÍµÄÊý¾Ý
    output  reg  [15:0]   udp_tx_byte_num    //udpµ¥°ü·¢ËÍµÄÓÐÐ§×Ö½ÚÊý
    );    
    
//parameter define
parameter  CMOS_H_PIXEL = 16'd960;  //Í¼ÏñË®Æ½·½Ïò·Ö±æÂÊ
parameter  CMOS_V_PIXEL = 16'd540;  //Í¼Ïñ´¹Ö±·½Ïò·Ö±æÂÊ
parameter  UDP_DATA_SIZE = 16'd960; //UDPÊý¾Ý³¤¶È£¨²»°üº¬Ê×²¿£©
parameter  ETH_TRAN_DELAY = 11'd800; //Ö¡¼ä¸ôÑÓ³Ù
//Í¼ÏñÖ¡Í·,ÓÃÓÚ±êÖ¾Ò»Ö¡Êý¾ÝµÄ¿ªÊ¼
parameter  IMG_FRAME_HEAD = {32'hf0_5a_a5_0f};

reg             img_vsync_d0    ;  //Ö¡ÓÐÐ§ÐÅºÅ´òÅÄ
reg             img_vsync_d1    ;  //Ö¡ÓÐÐ§ÐÅºÅ´òÅÄ
reg             neg_vsync_d0    ;  //Ö¡ÓÐÐ§ÐÅºÅÏÂ½µÑØ´òÅÄ
reg             neg_vsync_d1    ;
reg             img_de_d0       ;  //DE±êÖ¾Î»´òÅÄ
reg             img_de_d1       ;  //DE±êÖ¾Î» ´òÅÄ     
reg             eth_delay_d0    ;
reg             eth_delay_d1    ;                          


reg             wr_sw           ;  //ÓÃÓÚÎ»Æ´½ÓµÄ±êÖ¾
reg    [15:0]   img_data_d0     ;  //ÓÐÐ§Í¼ÏñÊý¾Ý´òÅÄ
reg             wr_fifo_en      /* synthesis PAP_MARK_DEBUG="1" */;  //Ð´fifoÊ¹ÄÜ
reg    [31:0]   wr_fifo_data    /* synthesis PAP_MARK_DEBUG="1" */;  //Ð´fifoÊý¾Ý

reg             img_vsync_txc_d0;  //ÒÔÌ«Íø·¢ËÍÊ±ÖÓÓòÏÂ,Ö¡ÓÐÐ§ÐÅºÅ´òÅÄ
reg             img_vsync_txc_d1;  //ÒÔÌ«Íø·¢ËÍÊ±ÖÓÓòÏÂ,Ö¡ÓÐÐ§ÐÅºÅ´òÅÄ
reg             tx_busy_flag    ;  //·¢ËÍÃ¦ÐÅºÅ±êÖ¾
reg    [15 : 0] img_de_cnt      /* synthesis PAP_MARK_DEBUG="1" */;//deÏÂ½µÑØ¼ÆÊý
reg    [31 : 0] img_pkt_cnt    /* synthesis PAP_MARK_DEBUG="1" */;
reg    [15 : 0]       eth_delay_cnt  /* synthesis PAP_MARK_DEBUG="1" */;    //delay¼ÆÊýÆ÷  
reg                  eth_delay_start/* synthesis PAP_MARK_DEBUG="1" */;
reg                  eth_delay_done /* synthesis PAP_MARK_DEBUG="1" */;                           
//wire define                   
wire            pos_vsync       ;  //Ö¡ÓÐÐ§ÐÅºÅÉÏÉýÑØ
wire            neg_vsync       ;  //Ö¡ÓÐÐ§ÐÅºÅÏÂ½µÑØ
wire            neg_vsynt_txc   ;  //ÒÔÌ«Íø·¢ËÍÊ±ÖÓÓòÏÂ,Ö¡ÓÐÐ§ÐÅºÅÏÂ½µÑØ
wire            pos_de          ;  //Êý¾ÝÓÐÐ§ÐÅºÅÉÏÉýÑØ
wire            pos_eth_delay   ;  //udp
wire   [10:0]    fifo_rdusedw    /* synthesis PAP_MARK_DEBUG="1" */;  //µ±Ç°FIFO»º´æµÄ¸öÊý


//*****************************************************
//**                    main code
//*****************************************************

//ÐÅºÅ²ÉÑØ
assign neg_vsync = img_vsync_d1 & (~img_vsync_d0);
assign pos_vsync = ~img_vsync_d1 & img_vsync_d0;
assign neg_vsynt_txc = ~img_vsync_txc_d1 & img_vsync_txc_d0;
assign neg_de    = (~img_de_d0) & img_de_d1;
assign pos_eth_delay = eth_delay_d0 & (~eth_delay_d1);
//¶Ôimg_vsyncÐÅºÅÑÓÊ±Á½¸öÊ±ÖÓÖÜÆÚ,ÓÃÓÚ²ÉÑØ
always @(posedge cam_pclk or negedge rst_n) begin
    if(!rst_n) begin
        img_vsync_d0 <= 1'b0;
        img_vsync_d1 <= 1'b0;
        img_de_d0    <= 1'b0;
        img_de_d1    <= 1'b0;
        eth_delay_d0 <=  'd0;//ÔÚÊäÈëÊ±ÖÓÓòÏÂ¶Ôudp·¢ËÍÍê³ÉÐÅºÅ²ÉÑù
        eth_delay_d1 <=  'd0;
    end
    else begin
        img_vsync_d0 <= img_vsync;
        img_vsync_d1 <= img_vsync_d0;
        img_de_d0 <= img_data_en;
        img_de_d1 <= img_de_d0;
        eth_delay_d0 <= eth_delay_start;//ÔÚÊäÈëÊ±ÖÓÓòÏÂ¶Ôudp·¢ËÍÍê³ÉÐÅºÅ²ÉÑù
        eth_delay_d1 <= eth_delay_d0;
    end
end

//¼Ä´æneg_vsyncÐÅºÅ
always @(posedge cam_pclk or negedge rst_n) begin
    if(!rst_n) begin
        neg_vsync_d0 <= 1'b0;
        neg_vsync_d1 <= 1'b0;
    end    
    else begin 
        neg_vsync_d0 <= neg_vsync;
        neg_vsync_d1 <= neg_vsync_d0;
    end
end    

//¶Ôwr_swºÍimg_data_d0ÐÅºÅ¸³Öµ,ÓÃÓÚÎ»Æ´½Ó
always @(posedge cam_pclk or negedge rst_n) begin
    if(!rst_n) begin
        wr_sw <= 1'b0;
        img_data_d0 <= 1'b0;
    end
     else if(neg_vsync)
        wr_sw <= 1'b0;
    else if(img_data_en) begin
        wr_sw <= ~wr_sw;
        img_data_d0 <= img_data;
    end    
end 

//½«Ö¡Í·ºÍÍ¼ÏñÊý¾ÝÐ´ÈëFIFO
always @(posedge cam_pclk or negedge rst_n) begin
    if(!rst_n || pos_vsync) begin
        wr_fifo_en <= 1'b0;
        wr_fifo_data <= 32'b0;
        img_de_cnt <= 32'd0;
        img_pkt_cnt <= 'd1;
    end
    else begin
        if(neg_vsync) begin
            wr_fifo_en <= 1'b1;
            wr_fifo_data <= img_pkt_cnt;                  //UDP°ü±êÖ¾Î»
            img_pkt_cnt <= img_pkt_cnt + 'd1;
        end
        else if(neg_vsync_d0) begin
            wr_fifo_en <= 1'b1;
            wr_fifo_data <= IMG_FRAME_HEAD;               //Ö¡Í·
        end
        else if(neg_vsync_d1) begin
            wr_fifo_en <= 1'b1;
            wr_fifo_data <= {CMOS_H_PIXEL,CMOS_V_PIXEL};  //Ë®Æ½ºÍ´¹Ö±·½Ïò·Ö±æÂÊ
        end
        else if(img_data_en && wr_sw) begin
            wr_fifo_en <= 1'b1;
            img_de_cnt <= img_de_cnt + 'd1;
            wr_fifo_data <= {img_data_d0,img_data};       //Í¼ÏñÊý¾ÝÎ»Æ´½Ó,16Î»×ª32Î»
        end
        else if(img_de_cnt == 240) begin
            wr_fifo_en <= 1'b1;
            wr_fifo_data <= img_pkt_cnt;
            img_pkt_cnt <= img_pkt_cnt + 'd1;
            
        end
        else if(neg_de) begin  
            wr_fifo_en <= 1'b1;
            wr_fifo_data <= img_pkt_cnt;           //de½áÊøºóÐ´Èë¼ÆÊý
            img_pkt_cnt <= img_pkt_cnt + 'd1;
            img_de_cnt <= 'd0;
        end
        else begin
            wr_fifo_en <= 1'b0;
            wr_fifo_data <= 32'b0;        
        end
    end
end

//ÒÔÌ«Íø·¢ËÍÊ±ÖÓÓòÏÂ,¶Ôimg_vsyncÐÅºÅÑÓÊ±Á½¸öÊ±ÖÓÖÜÆÚ,ÓÃÓÚ²ÉÑØ
always @(posedge eth_tx_clk or negedge rst_n) begin
    if(!rst_n) begin
        img_vsync_txc_d0 <= 1'b0;
        img_vsync_txc_d1 <= 1'b0;
    end
    else begin
        img_vsync_txc_d0 <= img_vsync;
        img_vsync_txc_d1 <= img_vsync_txc_d0;
    end
end

//¿ØÖÆÒÔÌ«Íø·¢ËÍµÄ×Ö½ÚÊý
always @(posedge eth_tx_clk or negedge rst_n) begin
    if(!rst_n)
        udp_tx_byte_num <= 1'b0;
    else if(neg_vsynt_txc)//vsºóµÚÒ»¸öÊý¾Ý°ü·¢ËÍÍ¼ÏñÊý¾Ý³¤¶È+ÆðÊ¼±êÖ¾Î»³¤¶È8Byte
        //udp_tx_byte_num <= {CMOS_H_PIXEL,1'b0} + 16'd8;
        udp_tx_byte_num <= UDP_DATA_SIZE + 16'd12;//16'd960 + 16'd8;
    else if(udp_tx_done)//ºóÐøÕý³£°ü³¤    
        //udp_tx_byte_num <= {CMOS_H_PIXEL,1'b0};
        udp_tx_byte_num <= UDP_DATA_SIZE + 16'd4;//16'd960;
end

//¿ØÖÆÒÔÌ«Íø·¢ËÍ¿ªÊ¼ÐÅºÅ
always @(posedge eth_tx_clk or negedge rst_n) begin
    if(!rst_n) begin
        udp_tx_start_en <= 1'b0;
        tx_busy_flag <= 1'b0;
    end
    //ÉÏÎ»»úÎ´·¢ËÍ"¿ªÊ¼"ÃüÁîÊ±,ÒÔÌ«Íø²»·¢ËÍÍ¼ÏñÊý¾Ý
    else if(transfer_flag == 1'b0) begin
        udp_tx_start_en <= 1'b0;
        tx_busy_flag <= 1'b0;        
    end
    else begin
        udp_tx_start_en <= 1'b0;
        //µ±FIFOÖÐµÄ¸öÊýÂú×ãÐèÒª·¢ËÍµÄ×Ö½ÚÊýÊ± Ë®Î»/4(32bit->8bit)
        if(tx_busy_flag == 1'b0 && fifo_rdusedw >= udp_tx_byte_num[15:2]) begin
            udp_tx_start_en <= 1'b1;                     //¿ªÊ¼¿ØÖÆ·¢ËÍÒ»°üÊý¾Ý
            tx_busy_flag <= 1'b1;
        end
        else if(eth_delay_done|| neg_vsynt_txc) 
            tx_busy_flag <= 1'b0;
    end
end
//×îÐ¡Ö¡¼ä¸ô£¬ÖÁÉÙÓÐ96bitsµÄ¼ä¸ô,Ç§Õ×ÒÔÌ«ÍøÒªÇó96ns£¬125Mhz->8ns£¬¼´12¸öÊ±ÖÓÖÜÆÚ£¬ÕâÀï¸ø500+°É
always @(posedge eth_tx_clk or negedge rst_n) begin
    if(!rst_n) begin
        eth_delay_cnt <= 'd0;
        eth_delay_start <= 'd0;
        eth_delay_done <= 'd0;
    end
    else begin
        eth_delay_done <= 'd0;
        if(udp_tx_done) begin
            eth_delay_start <= 'd1;
        end 
        if(eth_delay_start) begin
            eth_delay_cnt <= eth_delay_cnt + 'd1;
        end
        if(eth_delay_cnt >= ETH_TRAN_DELAY) begin
            eth_delay_done  <= 'd1;
            eth_delay_start <= 'd0;
            eth_delay_cnt   <= 'd0;
        end
    end
end
reg    [10:0]   udp_pkt_cnt     /* synthesis PAP_MARK_DEBUG="1" */;  //udp°ü¼ÆÊý
always @(posedge eth_tx_clk or negedge rst_n) begin
    if(!rst_n || neg_vsynt_txc) begin
        udp_pkt_cnt <= 'd0;
    end    
    else if(udp_tx_done)begin
        udp_pkt_cnt <= udp_pkt_cnt + 'd1;
    end
    else begin
        udp_pkt_cnt <= udp_pkt_cnt;
    end
end
//Òì²½FIFO
  
eth_pkt_fifo u_eth_pkt_fifo (
  .wr_clk           (cam_pclk                    ) ,    // input
  .wr_rst           (pos_vsync | (~transfer_flag)) ,    // input
  .wr_en            (wr_fifo_en                  ) ,    // input
  .wr_data          (wr_fifo_data                ) ,    // input [31:0]
  .wr_full          (                            ) ,    // output
  .wr_water_level   (                            ) ,    // output [10:0]
  .almost_full      (                            ) ,    // output
  .rd_clk           (eth_tx_clk                  ) ,    // input
  .rd_rst           (pos_vsync | (~transfer_flag)) ,    // input
  .rd_en            (udp_tx_req                  ) ,    // input
  .rd_data          (udp_tx_data                 ) ,    // output [31:0]
  .rd_empty         (                            ) ,    // output
  .rd_water_level   (fifo_rdusedw                ) ,    // output [10:0]
  .almost_empty     (                            )      // output
);
//eth_pkt_fifo u_eth_pkt_fifo (
//  .wr_clk(wr_clk),                    // input
//  .wr_rst(wr_rst),                    // input
//  .wr_en(wr_en),                      // input
//  .wr_data(wr_data),                  // input [31:0]
//  .wr_full(wr_full),                  // output
//  .wr_water_level(wr_water_level),    // output [9:0]
//  .almost_full(almost_full),          // output
//  .rd_clk(rd_clk),                    // input
//  .rd_rst(rd_rst),                    // input
//  .rd_en(rd_en),                      // input
//  .rd_data(rd_data),                  // output [31:0]
//  .rd_empty(rd_empty),                // output
//  .rd_water_level(rd_water_level),    // output [9:0]
//  .almost_empty(almost_empty)         // output
//);

endmodule