`timescale 1ns/ 1ps

module Vertical_Projection_sum#(
       parameter IMG_WIDTH_LINE = 1024  ,
       parameter DIV_REVERSE = 0  ,
       parameter THRED_BINARY = 24'h333333  
	   )(
                 input                          pixelclk,
	   input                          reset_n , 
                 input                          en  ,   
	   input  [23:0]                  i_binary,
	   input                          i_hs    ,
	   input                          i_vs    ,
	   input                          i_de    ,       

	   input [11:0]                   i_hcount,
	   input [11:0]                   i_vcount,

   //    output    [23:0]    O_binary,	   
	   output            [11:0]       hcount_l,
                 output            [11:0]       hcount_r,
                 output            [11:0]       vcount_l,
                 output            [11:0]       vcount_r,
       
	   output            [2:0]        s_frame_cnt,
                 output            [17:0]       scircul , //Circularity integer
	   output                         sc_done ,
	   output            [3:0]        total_num ,
     output                         no_use 

		 );


 
parameter IDLE =   5'b00001;
parameter FRAME1 = 5'b00010;
parameter FRAME2 = 5'b00100;
parameter FRAME3 = 5'b01000;
parameter FRAME4 = 5'b10000;

wire                 TFT_VS_fall;
wire                 th_flag;
wire [11:0]          hcount;
wire [11:0]          vcount;
reg  [2:0]           frame_cnt;

assign   s_frame_cnt  = frame_cnt ;


reg          hs_r;
reg          vs_r;
reg          de_r;


//assign    O_binary=i_binary;

assign o_hs = hs_r;
assign o_vs = vs_r;
assign o_de = de_r;

assign TFT_VS_fall = (!i_vs & (vs_r))?1'b1:1'b0; //posedge of vs

assign th_flag = (i_binary == THRED_BINARY)?1'b0:1'b1;

assign hcount = i_hcount;
assign vcount = i_vcount;

reg [4:0] c_state;
reg [4:0] n_state;

//reg [1:0] frame_cnt;
reg [11:0] i;

reg  [11:0] hcount_l1_r;
reg  [11:0] hcount_r1_r;
reg  [11:0] vcount_l1_r;
reg  [11:0] vcount_r1_r;
  
reg h_we;
reg [11:0] h_waddr;
reg [11:0] h_raddr;
reg  h_di;
wire h_dout;
reg  h_dout_r;
reg  v_we;
reg [11:0] v_waddr;
reg [11:0] v_raddr;
reg  v_di;
wire v_dout;
reg  v_dout_r;
 
wire h_pedge = (h_dout & (!h_dout_r));
wire h_nedge = ((!h_dout) & h_dout_r);
wire v_pedge = (v_dout & (!v_dout_r));
wire v_nedge = ((!v_dout) & v_dout_r);
reg h_pedge_r;
reg h_nedge_r;
reg v_pedge_r;
reg v_nedge_r;

reg h_pedge_r0;
reg h_nedge_r0;
reg v_pedge_r0;
reg v_nedge_r0;


reg  [3:0] h_pedge_cnt;
reg  [3:0] h_nedge_cnt;
reg  [3:0] v_pedge_cnt;
reg  [3:0] v_nedge_cnt;

assign       hcount_l  = hcount_l1_r;
assign       hcount_r  = hcount_r1_r;
assign       vcount_l  = vcount_l1_r;
assign       vcount_r  = vcount_r1_r;

/*-------------------------------------------------------------------------
 number state design,count the number of fruit
-------------------------------------------------------------------------*/
reg    [2:0]      HSTATE ;
reg    [2:0]      VSTATE ;
reg    [9:0]      H_thrd_cnt  ;
reg    [9:0]      V_thrd_cnt  ;
reg    [3:0]      H_num_cnt   /* synthesis syn_preserve = 1 */; //H direction fruit number
reg    [3:0]      V_num_cnt   /* synthesis syn_preserve = 1 */; //V direction fruit number
reg    [3:0]      r_TOTAL_NUM /* synthesis syn_preserve = 1 */;

localparam        HIDLE = 3'b001;
localparam        HPOSE = 3'b010;
localparam        HNEGE = 3'b100;
localparam        VIDLE = 3'b001;
localparam        VPOSE = 3'b010;
localparam        VNEGE = 3'b100;

assign total_num = r_TOTAL_NUM ;

always @(posedge pixelclk or negedge reset_n) begin
    if (!reset_n)
	   HSTATE  <=  HIDLE   ;
	else begin
       case (HSTATE)
	       HIDLE: begin
			   if (h_pedge == 1'b1)
			      HSTATE <= HPOSE ;
			   else 
			      HSTATE <= HIDLE ;
		   end
		   HPOSE: begin
			   if ((H_thrd_cnt>10'd100) && (h_nedge == 1'b1))
			      HSTATE  <= HNEGE ;
			   else if (H_thrd_cnt == 10'd1023)
			      HSTATE <= HIDLE ;
			   else 
			      HSTATE <= HPOSE ;
		   end
		   HNEGE: begin
                  HSTATE <= HIDLE ;
		   end
		   default : HSTATE <= HIDLE ;
	endcase 
	end
end

always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
    H_thrd_cnt <= 10'd0;
  else if(HSTATE == HPOSE) begin
    if(H_thrd_cnt == 10'd1023)
       H_thrd_cnt <= 10'd0;
	else 
	   H_thrd_cnt <= H_thrd_cnt + 10'd1;
  end  
  else
    H_thrd_cnt <= 10'd0;
end 

always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
    H_num_cnt <= 4'd0;
  else if((HSTATE == HNEGE)&&(c_state == FRAME2)&&(h_raddr < (IMG_WIDTH_LINE-1)))
    H_num_cnt <= H_num_cnt + 4'd1 ; 
  else if (c_state == FRAME2)
    H_num_cnt <= H_num_cnt ;
  else
    H_num_cnt <= 4'd0;
end

always @(posedge pixelclk or negedge reset_n) begin
    if (!reset_n)
	   VSTATE  <=  VIDLE   ;
    else begin
       case (VSTATE)
	VIDLE: begin
	  if (v_pedge == 1'b1)
	    VSTATE <= VPOSE ;
	  else 
	    VSTATE <= VIDLE ;
	end
	VPOSE: begin
	  if ((V_thrd_cnt>10'd100) && (v_nedge == 1'b1))
                  VSTATE  <= VNEGE ;
	  else if (V_thrd_cnt == 10'd1023)
	    VSTATE <= VIDLE ;
	  else 
	    VSTATE <= VPOSE ;
	 end
	VNEGE: begin
                  VSTATE <= VIDLE ;
	end
	default : VSTATE <= VIDLE ;
       endcase 
    end
end

always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
    V_thrd_cnt <= 10'd0;
  else if(VSTATE == VPOSE) begin
    if(V_thrd_cnt == 10'd1023)
       V_thrd_cnt <= 10'd0;
    else 
       V_thrd_cnt <= V_thrd_cnt + 10'd1;
  end  
  else
    V_thrd_cnt <= 10'd0;
end 

always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
    V_num_cnt <= 4'd0;
  else if((VSTATE == VNEGE)&&(c_state == FRAME2)&&(h_raddr < (IMG_WIDTH_LINE-1)))
    V_num_cnt <= V_num_cnt + 4'd1 ; 
  else if (c_state == FRAME2)
    V_num_cnt <= V_num_cnt;
  else
    V_num_cnt <= 4'd0;
end

always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
    r_TOTAL_NUM <= 4'd0;
  else if((c_state == FRAME2)&&(h_raddr == (IMG_WIDTH_LINE-1))) 
    r_TOTAL_NUM <= V_num_cnt * H_num_cnt ; 
  else if (c_state == FRAME4)
    r_TOTAL_NUM <= 4'd0;
  else
    r_TOTAL_NUM <= r_TOTAL_NUM;
end
//////////////////////////////////////////////////////////////////////////
always @(posedge pixelclk )
    if(en) begin
  hs_r     <= i_hs;
  vs_r     <= i_vs;
  de_r     <= i_de;
  
  h_dout_r <= h_dout;
  v_dout_r <= v_dout;
  
  h_pedge_r <= h_pedge;
  h_nedge_r <= h_nedge;
  v_pedge_r <= v_pedge;
  v_nedge_r <= v_nedge;
  
  h_pedge_r0 <= h_pedge_r;
  h_nedge_r0 <= h_nedge_r;
  v_pedge_r0 <= v_pedge_r;
  v_nedge_r0 <= v_nedge_r;
end

//-------------------------------------------------------------
//frame counter 0 1 2 3 4   0 1 2 3 4 ...
//-------------------------------------------------------------
always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
    frame_cnt <=3'd0;
  else if(en)
    if(frame_cnt == 3'd4)
    frame_cnt <=3'd0;
  else if(TFT_VS_fall== 1'b1) //falling edge
    frame_cnt <= frame_cnt + 3'd1;
  else
    frame_cnt <= frame_cnt; 
end 


//FSM1
always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
    c_state <= IDLE;
  else if(en)
    c_state <= n_state;
    else
        c_state <= IDLE;
end


//FSM2
always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
     n_state <= IDLE;
  else case(c_state)
    IDLE:begin
	   if(i > (IMG_WIDTH_LINE-1))      // initial ram
		  n_state <= FRAME1;
		else 
		  n_state <= IDLE;
	 end
	 FRAME1:begin
	   if(frame_cnt == 3'd1)
		  n_state <= FRAME2;
		else
		  n_state <= FRAME1;
	 end
	 FRAME2:begin
	   if(frame_cnt == 3'd2)
		  n_state <= FRAME3;
		else
		  n_state <= FRAME2;
	 end
	 FRAME3:begin
	   if(frame_cnt == 3'd3)
		  n_state <= FRAME4;
		else
		  n_state <= FRAME3;
	 end
	 FRAME4:begin
	   if(frame_cnt == 3'd0)
		  n_state <= FRAME1;
		else
		  n_state <= FRAME4;
	 end
  endcase      
end

//FMS3
always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) begin 
     h_we <= 1'b0;
	 h_waddr <= 12'b0;
	 h_raddr <= 12'b0;
	 h_di <= 0;
	 v_we <= 1'b0;
	 v_waddr <= 12'b0;
	 v_raddr <= 12'b0;
	 v_di <= 0;
	 i <= 12'd0;
	 hcount_l1_r<= 12'b0;
     hcount_r1_r<= 12'b0;
     vcount_l1_r<= 12'b0;
     vcount_r1_r<= 12'b0;

     h_pedge_cnt<=4'b0;
     h_nedge_cnt<=4'b0;
     v_pedge_cnt<=4'b0;
     v_nedge_cnt<=4'b0;
  end	 
  else case(c_state)
    IDLE: begin
	   if(i > (IMG_WIDTH_LINE-1)) begin
		  i<=i;
		  h_we <= 0;
		  h_waddr <= 0;
		  h_di <= 0;
		  v_we <= 0;
		  v_waddr <= 0;
		  v_di <= 0;
		end  
		else begin
		  i <= i +1;
		  h_we <= 1;
		  h_waddr <= h_waddr +1;
		  h_di <= 0;
		  v_we <= 1;
		  v_waddr <= v_waddr +1;
		  v_di <= 0;
		end
	 end
    FRAME1:begin
	   if((hcount > 12)&& (vcount > 12)&& (!th_flag)) begin //finish projection process,save all h and v position of characteristic point
		  h_we <= 1;
		  h_waddr <= hcount;
		  h_di <= 1;
		  v_we <= 1;
		  v_waddr <= vcount;
		  v_di <= 1;
		end
		else begin
		  h_we <= 0;
		  h_waddr <= 0;
		  h_di <= 0;
		  v_we <= 0;
		  v_waddr <= 0;
		  v_di <= 0;
		end
	 end
	 FRAME2:begin
	  if(h_raddr < (IMG_WIDTH_LINE-1)) begin 
	     i <= 0;
	     h_raddr <= h_raddr + 1;
		 v_raddr <= v_raddr + 1;
		  
	    if(h_pedge) h_pedge_cnt <= h_pedge_cnt +1;
	    if(h_pedge_r0 && h_pedge_cnt == 1) hcount_l1_r <= (h_raddr+25);//包围盒内扩？
	  
	    if(h_nedge) h_nedge_cnt <= h_nedge_cnt +1;
	    if(h_nedge_r0 && h_nedge_cnt == 1) hcount_r1_r <= (h_raddr-22);
		 
		if(v_pedge) v_pedge_cnt <= v_pedge_cnt +1;
	    if(v_pedge_r0 && v_pedge_cnt == 1) vcount_l1_r <= (v_raddr +30);
	  
	    if(v_nedge) v_nedge_cnt <= v_nedge_cnt +1;
	    if(v_nedge_r0 && v_nedge_cnt == 1) vcount_r1_r <= (v_raddr-32);
	  end
	  else begin
	     h_pedge_cnt <= h_pedge_cnt;
		 h_nedge_cnt <= h_nedge_cnt;
		  
		 v_pedge_cnt <= v_pedge_cnt;
		 v_nedge_cnt <= v_nedge_cnt;
		  
		 h_raddr <= h_raddr;
	     v_raddr <= v_raddr;
	    if(i < (IMG_WIDTH_LINE-1)) begin //clear h_ram and v_ram
		  i <= i + 1;
		  h_we <= 1;
		  h_waddr <= h_waddr +1;
		  h_di <= 0;
		  v_we <= 1;
		  v_waddr <= v_waddr +1;
		  v_di <= 0;
		 end	
		 else begin
		  i<=i;
		  h_we <= 0;
		  h_waddr <= 0;
		  h_di <= 0;
		  v_we <= 0;
		  v_waddr <= 0;
		  v_di <= 0;
		 end
	  end
	 end
	 FRAME3:begin
	   h_raddr <= 0;
	   v_raddr <= 0;
		h_pedge_cnt <= 4'b0;
		h_nedge_cnt <= 4'b0;
		v_pedge_cnt <= 4'b0;
		v_nedge_cnt <= 4'b0;
	 end
  endcase
end
/*-------------------------------------------------------------------------
 calculate the circularity,represent by the h direction projection value 
 and v direction projection value. use color process binarization,projection
 picture has only one fruit
-------------------------------------------------------------------------*/
parameter              count_thred = 10'd100;

reg        [9:0]       h_cnt      ;
reg        [9:0]       v_cnt      ;
reg                    h_valid    ;
reg                    v_valid    ;
reg                    h_nedge_flag;
reg                    v_nedge_flag;
//the first fruit projection h value and v value
reg        [9:0]       h_1        ;   
reg        [9:0]       v_1        ;
wire                    enable_1   ;

wire       [17:0]      yshang_1   ;
wire                   done_1     ;

always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
     h_nedge_flag   <=   1'b0     ;
  else if (h_nedge == 1'b1)
     h_nedge_flag   <=   1'b1     ;
  else if (h_pedge == 1'b1)
     h_nedge_flag   <=   1'b0     ;  //avoid discontinue
  else if (h_nedge_flag == 1'b1 && v_nedge_flag == 1'b1)
     h_nedge_flag   <=   1'b0     ;
  else 
     h_nedge_flag   <=h_nedge_flag;   
end

always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
     v_nedge_flag   <=   1'b0     ;
  else if (v_nedge == 1'b1)
     v_nedge_flag   <=   1'b1     ;
  else if (v_pedge == 1'b1)
     v_nedge_flag   <=   1'b0     ;
  else if (h_nedge_flag == 1'b1 && v_nedge_flag == 1'b1)
     v_nedge_flag   <=   1'b0     ;
  else 
     v_nedge_flag   <=v_nedge_flag;   
end

always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) begin 
      h_valid   <=   1'b0         ;
      v_valid   <=   1'b0         ;
  end
  else if (h_pedge == 1'b1)
      h_valid   <=   1'b1         ;
  else if (h_nedge == 1'b1)
      h_valid   <=   1'b0         ;
  else if (v_pedge == 1'b1) 
      v_valid   <=   1'b1         ;
  else if (v_nedge == 1'b1)
      v_valid   <=   1'b0         ;
  else begin
      h_valid   <=   h_valid      ;
      v_valid   <=   v_valid      ;	  
  end
end
always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) begin 
      h_cnt   <=   10'd0         ;
  end
  else if (h_valid == 1'b1 && h_nedge == 1'b1) begin    
      h_cnt   <=   10'd0         ;
  end
  else if (h_valid == 1'b1) begin
      h_cnt   <=   h_cnt + 10'd1 ;
  end
  else begin
      h_cnt   <=   h_cnt         ;	  
  end
end
always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) begin 
      v_cnt   <=   10'd0         ;
  end
  else if (v_valid == 1'b1 && v_nedge == 1'b1) begin
      v_cnt   <=   10'd0         ;
  end
  else if (v_valid == 1'b1) begin
      v_cnt   <=   v_cnt + 10'd1 ;
  end
  else begin
      v_cnt   <=   v_cnt         ;	  
  end
end
always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
       h_1      <=     10'd0   ;        	  
  else if (c_state == FRAME2 && h_valid == 1'b1 && h_nedge == 1'b1 && h_cnt >= count_thred) 
       h_1      <=     h_cnt   ;		  
  else 
       h_1      <=     h_1   ;        
end

always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
       v_1      <=     10'd0   ;        	  
  else if (c_state == FRAME2 && v_valid == 1'b1 && v_nedge == 1'b1 && v_cnt >= count_thred) 
       v_1      <=     v_cnt   ;		  
  else 
       v_1      <=     v_1   ;        
end

//add no use signal//
reg            r_no_use       ;
wire           v_out          ;
wire           h_out          ;

assign         v_out  = (c_state == FRAME2 && v_1 > 10'd0)?1'b1:1'b0;
assign         h_out  = (c_state == FRAME2 && h_1 > 10'd0)?1'b1:1'b0;
assign         no_use = r_no_use ;

always @(posedge pixelclk or negedge reset_n) begin
  if(!reset_n) 
       r_no_use    <=    1'b0    ;        	  
  else if (v_out == 1'b1 || h_out == 1'b1) 
       r_no_use    <=    1'b1    ; 
  else if (c_state == FRAME4)		 
       r_no_use    <=    1'b0    ; 
  else 
       r_no_use    <=    r_no_use;      
end

wire           rst            ;
wire  [17:0]   a              ;
wire  [17:0]   b              ;

assign   a = (DIV_REVERSE == 1)?((h_1<v_1)?{h_1,{8{1'b0}}}:{v_1,{8{1'b0}}}):((h_1>v_1)?{h_1,{8{1'b0}}}:{v_1,{8{1'b0}}}) ;
assign   b = (DIV_REVERSE == 1)?((h_1<v_1)?{{8{1'b0}},v_1}:{{8{1'b0}},h_1}):((h_1>v_1)?{{8{1'b0}},v_1}:{{8{1'b0}},h_1}) ;
assign   rst = !reset_n  ;
assign   enable_1 = h_nedge_flag & v_nedge_flag  ;
assign   scircul = yshang_1 ; //Circularity
assign   sc_done = done_1 ;

div_rill2 #( 
   .N(18)
)divede1(
.clk      (pixelclk             ) ,
.rst      (rst                  ) , 
.enable   (enable_1             ) ,
.a        (a                    ) ,  //expand 2^8
.b        (b                    ) , 
.yshang   (yshang_1             ) ,
.yyushu   (                     ) , 
.done     (done_1               )
);

ram #(
       .IMG_WIDTH_LINE(IMG_WIDTH_LINE)
      )h_ram_inst(
     .clk(pixelclk),
     .rst_n(reset_n),	
     .we(h_we),
     .waddr(h_waddr),
     .raddr(h_raddr),
     .di(h_di),
     .dout(h_dout)
);
	
ram #(
      .IMG_WIDTH_LINE(IMG_WIDTH_LINE)
      )v_ram_inst(
    .clk(pixelclk),
    .rst_n(reset_n),	
    .we(v_we),
    .waddr(v_waddr),
    .raddr(v_raddr),
    .di(v_di),
    .dout(v_dout)
); 


endmodule