
/*////////////////////////////////////////////////////////////////////////////////
 command of uart: "R F" ASCII code denotes read the color, type and number R:0x52 F:0x46
 of fruit. "C A" ASCII code denotes read one frame of data  C:0x43 A:0x41 sp:0x20
 mainly for receiving command from computer and processing color, number, feature information
 from ISP module. Color determination is primarily based on the presence or absence of a 
 continuous color enable signal being recorded.  The number of continuous color enable signals 
 is defined by the parameter color_thred.
//*******************************************************************************/

module uart_ctrl(
input                           sys_clk    ,
input                           rst_n      ,
input                           frame_vaild,
input       [ 2:0]              s_frame_cnt,
//color enable signal
input                           red_en     ,
//input                           blue_en    ,
input                           green_en   ,
input                           yellow_en  ,
input                           purple_en  ,
input                           brown_en   ,
input                           pyellow_en ,
input                           orange_en  ,
input                           pink_en    ,
//fruit type enable signal
input                           apple_type_en ,
input                           pear_type_en  ,
input                           banan_type_en ,
input                           mango_type_en ,
input                           orang_type_en ,
input                           grape_type_en ,
input                           pitay_type_en ,
input                           kiwi_type_en  ,    
input      [3:0]                fruit_num     ,
input                           uart_rx       ,
output                          uart_tx   
);


//parameter                        CLK_FRE = 50;//Mhz
parameter                        CLK_FRE = 62;

localparam                       RIDLE   =   9'b000000001   ;
localparam                       RR      =   9'b000000010   ;
localparam                       R_      =   9'b000000100   ;
localparam                       RF      =   9'b000001000   ;
localparam                       RC      =   9'b000010000   ;
localparam                       RA      =   9'b000100000   ;
localparam                       R_RF    =   9'b001000000   ;
localparam                       R_CA    =   9'b010000000   ;
localparam                       RSTOP   =   9'b100000000   ;


reg       [ 8:0]                 RSTATE; //The state machine is used to determine whether a valid command is received
reg       [ 8:0]                 RSTATE_NEXT;
reg                              frame_vaild_d1;
reg                              frame_vaild_d2;
reg       [ 2:0]                 r_s_frame_cnt ;
wire                             neg_frame_vaild; //denote one frame end
wire                             pos_frame_vaild; //denote one frame start


reg       [7:0]                  tx_str/*synthesis syn_keep=1*/;
reg                              tx_data_valid;
wire                             tx_data_ready;
reg       [7:0]                  tx_cnt;
wire      [7:0]                  rx_data;
wire                             rx_data_valid;
wire                             rx_data_ready;
wire     [7:0]                   tx_data;
//reg      [3:0]                   state;

assign rx_data_ready = 1'b1;//always can receive data,
			
assign neg_frame_vaild = (!frame_vaild_d1) & frame_vaild_d2 ; //negedge of frame_vaild denote one frame end
assign pos_frame_vaild = (frame_vaild_d1) & (!frame_vaild_d2);

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n) begin
        frame_vaild_d1    <=    1'b0             ;
        frame_vaild_d2    <=    1'b0             ;
    end
    else begin
        frame_vaild_d1    <=    frame_vaild      ;
        frame_vaild_d2    <=    frame_vaild_d1   ;    
    end
end

always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n) 
	   RSTATE  <=  9'd0        ;
	else
	   RSTATE  <=  RSTATE_NEXT ;
end

always @(RSTATE_NEXT or rx_data_valid or rx_data or pos_frame_vaild or neg_frame_vaild) begin
	case (RSTATE)
	     RIDLE : begin
			 if ((rx_data_valid == 1'b1)&&(rx_data == "R"))
			    RSTATE_NEXT <= RR ;
			 else if ((rx_data_valid == 1'b1)&&(rx_data == "C"))
			    RSTATE_NEXT <= RC ;
			 else 
			    RSTATE_NEXT <= RIDLE ;
		 end
		 RR   :  begin
			 if ((rx_data_valid == 1'b1)&&(rx_data == 8'h20))
			    RSTATE_NEXT <= R_ ;
			 else
			    RSTATE_NEXT <= RR ;
		 end
		 R_   : begin
			 if ((rx_data_valid == 1'b1)&&(rx_data == "F"))
			    RSTATE_NEXT <= RF ;
			 else if ((rx_data_valid == 1'b1)&&(rx_data == "A"))
			    RSTATE_NEXT <= RA ;
			 else  
			    RSTATE_NEXT <= R_ ;
		 end
		 RF   : begin
		     if (pos_frame_vaild == 1'b1 && r_s_frame_cnt == 3'd1)
			    RSTATE_NEXT <= R_RF;  // represent start of one frame signal
			 else                     // frame start change to R_RF state and read color 
			    RSTATE_NEXT <= RF  ;
		 end
		 R_RF : begin
		     if (neg_frame_vaild == 1'b1)
			    RSTATE_NEXT <= RIDLE ;
			 else
			    RSTATE_NEXT <= R_RF  ;
		 end
		 RC   : begin
		     if ((rx_data_valid == 1'b1)&&(rx_data == 8'h20))
			    RSTATE_NEXT <= R_    ;                             
			 else                          
			    RSTATE_NEXT <= RC    ;
		 end
		 RA   : begin
			 if (pos_frame_vaild == 1'b1)
			    RSTATE_NEXT <= R_CA  ;   // represent start of one frame signal
			 else                        // frame start change to R_RF state and read one farme data
			    RSTATE_NEXT <= RA    ;
		 end
		 R_CA : begin
			 if (neg_frame_vaild == 1'b1)
			    RSTATE_NEXT <= RIDLE ;
			 else
			    RSTATE_NEXT <= R_CA  ;
		 end	
		 default : RSTATE_NEXT <= RIDLE ;			 	
	endcase
end

/*******************************************************************************************
     count different color number enable signal ; 
	 receive the number and type of fruit       ;
*******************************************************************************************/
localparam                   color_thred = 8'd100;

reg         [7:0]            red_cnt            ;
//reg         [7:0]            blue_cnt           ;
reg         [7:0]            green_cnt          ;
reg         [7:0]            yellow_cnt         ;
reg         [7:0]            purple_cnt         ;
reg         [7:0]            brown_cnt          ;
reg         [7:0]            pyellow_cnt        ;
reg         [7:0]            orange_cnt         ;
reg         [7:0]            pink_cnt           ;
//reg                          detect_red         ;
//reg                          detect_blue        ;
//reg                          detect_green       ;
//reg                          detect_yellow      ;
//reg                          detect_purple      ;
//reg                          detect_brown       ;

always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n) begin
		red_cnt    <=       8'd0        ;
		green_cnt  <=       8'd0        ;
		yellow_cnt <=       8'd0        ;
		purple_cnt <=       8'd0        ;
		brown_cnt  <=       8'd0        ;
        pyellow_cnt<=       8'd0        ;
        orange_cnt <=       8'd0        ;
		pink_cnt   <=       8'd0        ;
	end
	else if ((red_en == 1'b1)&&(RSTATE == R_RF)) begin
		if (red_cnt == color_thred) 
		   red_cnt <= 8'd0 ;
		else
		   red_cnt <= red_cnt + 8'd1 ;
	end
//	else if ((blue_en == 1'b1)&&(RSTATE == R_RF)) begin
//		if (blue_cnt == color_thred) 
//		   blue_cnt <= 8'd0 ;
//		else
//		   blue_cnt <= blue_cnt + 8'd1 ;
//	end
	else if ((green_en == 1'b1)&&(RSTATE == R_RF)) begin
		if (green_cnt == color_thred) 
		   green_cnt <= 8'd0 ;
		else
		   green_cnt <= green_cnt + 8'd1 ;
	end
	else if ((yellow_en == 1'b1)&&(RSTATE == R_RF)) begin
		if (yellow_cnt == color_thred) 
		   yellow_cnt <= 8'd0 ;
		else
		   yellow_cnt <= yellow_cnt + 8'd1 ;
	end
	else if ((purple_en == 1'b1)&&(RSTATE == R_RF)) begin
		if (purple_cnt == color_thred) 
		   purple_cnt <= 8'd0 ;
		else
		   purple_cnt <= purple_cnt + 8'd1 ;
	end
	else if ((brown_en == 1'b1)&&(RSTATE == R_RF)) begin
		if (brown_cnt == color_thred) 
		   brown_cnt <= 8'd0 ;
		else
		   brown_cnt <= brown_cnt + 8'd1 ;
	end
	else if ((pyellow_en == 1'b1)&&(RSTATE == R_RF)) begin
		if (pyellow_cnt == color_thred) 
		   pyellow_cnt <= 8'd0 ;
		else
		   pyellow_cnt <= pyellow_cnt + 8'd1 ;
	end	
	else if ((orange_en == 1'b1)&&(RSTATE == R_RF)) begin
		if (orange_cnt == color_thred) 
		   orange_cnt <= 8'd0 ;
		else
		   orange_cnt <= orange_cnt + 8'd1 ;
	end
	else if ((pink_en == 1'b1)&&(RSTATE == R_RF)) begin
		if (pink_cnt == color_thred) 
		   pink_cnt <= 8'd0 ;
		else
		   pink_cnt <= pink_cnt + 8'd1 ;
	end	
	else begin
		red_cnt    <=       8'd0        ;
		green_cnt  <=       8'd0        ;
		yellow_cnt <=       8'd0        ;
		purple_cnt <=       8'd0        ;
		brown_cnt  <=       8'd0        ;
        pyellow_cnt<=       8'd0        ;
        orange_cnt <=       8'd0        ;
		pink_cnt   <=       8'd0        ;
	end
end

//always @(posedge sys_clk or negedge rst_n) begin
//	if (!rst_n)
//	   detect_red <= 1'b0  ;
//	else if (red_cnt == color_thred)
//	   detect_red <= 1'b1  ;
//	else if ((neg_frame_vaild == 1'b1)&&((RSTATE == R_RF)))
//	   detect_red <= 1'b0  ;
//	else
//	   detect_red <= detect_red ;
//end
//
//always @(posedge sys_clk or negedge rst_n) begin
//	if (!rst_n)
//	   detect_blue <= 1'b0  ;
//	else if (blue_cnt == color_thred)
//	   detect_blue <= 1'b1  ;
//	else if ((neg_frame_vaild == 1'b1)&&(RSTATE == R_RF))
//	   detect_blue <= 1'b0  ;
//	else
//	   detect_blue <= detect_blue ;
//end
//
//always @(posedge sys_clk or negedge rst_n) begin
//	if (!rst_n)
//	   detect_green <= 1'b0  ;
//	else if (green_cnt == color_thred)
//	   detect_green <= 1'b1  ;
//	else if ((neg_frame_vaild == 1'b1)&&(RSTATE == R_RF))
//	   detect_green <= 1'b0  ;
//	else
//	   detect_green <= detect_green ;
//end
//
//always @(posedge sys_clk or negedge rst_n) begin
//	if (!rst_n)
//	   detect_yellow <= 1'b0  ;
//	else if (yellow_cnt == color_thred)
//	   detect_yellow <= 1'b1  ;
//	else if ((neg_frame_vaild == 1'b1)&&(RSTATE == R_RF))
//	   detect_yellow <= 1'b0  ;
//	else
//	   detect_yellow <= detect_yellow ;
//end
//
//always @(posedge sys_clk or negedge rst_n) begin
//	if (!rst_n)
//	   detect_purple <= 1'b0  ;
//	else if (purple_cnt == color_thred)
//	   detect_purple <= 1'b1  ;
//	else if ((neg_frame_vaild == 1'b1)&&(RSTATE == R_RF))
//	   detect_purple <= 1'b0  ;
//	else
//	   detect_purple <= detect_purple ;
//end
//
//always @(posedge sys_clk or negedge rst_n) begin
//	if (!rst_n)
//	   detect_brown <= 1'b0  ;
//	else if (brown_cnt == color_thred)
//	   detect_brown <= 1'b1  ;
//	else if ((neg_frame_vaild == 1'b1)&&(RSTATE == R_RF))
//	   detect_brown <= 1'b0  ;
//	else
//	   detect_brown <= detect_brown ;
//end
localparam         save_num =  5'd17  ;

reg    [55:0]         red     ;   //ASCII code "red "
reg    [55:0]         blue    ;   //ASCII code "blue "
reg    [55:0]         green   ;   //ASCII code "green "
reg    [55:0]         yellow  ;   //ASCII code "yellow "
reg    [55:0]         purple  ;   //ASCII code "purple "
reg    [55:0]         brown   ;   //ASCII code "brown "
reg    [55:0]         orange  ;   //ASCII code "orange "
reg    [55:0]         pink    ;   //ASCII code "pink "
reg    [4:0]          save_cnt;

reg    [55:0]     r_fruit_num /* synthesis syn_preserve = 1 */;   //the detection number of fruit


//wire     [5:0]     detect_sum      ;
//
//assign  detect_sum = {detect_red,detect_blue,detect_green,detect_yellow,detect_purple,detect_brown};

/*******************************************************************************************
     when the color enable signal reach the threshold latch the color information ; 
	 ASCII        hex
	 ONE          56'h4F4E4520202020
	 TWO          56'h54574F20202020
	 THREE        56'h54485245452020
	 FOUR         56'h464F5552202020
	 FIVE         56'h46495645202020
	 SIX          56'h53495820202020
	 SEVEN        56'h534556454E2020
	 EIGHT        56'h45494748542020
	 NINE         56'h4E494E45202020
	 TEN          56'h54454E20202020
*******************************************************************************************/
always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n)
	   r_fruit_num <= 56'd0       ;
	else if (fruit_num == 4'd1)
                 r_fruit_num <= 56'h4F4E4520202020;
              else if (fruit_num == 4'd2)
	   r_fruit_num <= 56'h54574F20202020;
              else if (fruit_num == 4'd3)          
	    r_fruit_num <= 56'h54485245452020;
              else if (fruit_num == 4'd4)                        
	    r_fruit_num <= 56'h464F5552202020;
              else if (fruit_num == 4'd5)                        
	    r_fruit_num <= 56'h46495645202020;
              else if (fruit_num == 4'd6)                        
	    r_fruit_num <= 56'h53495820202020;
              else if (fruit_num == 4'd7)                        
	    r_fruit_num <= 56'h534556454E2020;
              else if (fruit_num == 4'd8)                        
	    r_fruit_num <= 56'h45494748542020;
              else if (fruit_num == 4'd9)                        
	    r_fruit_num <= 56'h4E494E45202020;
              else if (fruit_num == 4'd10)                        
	   r_fruit_num <= 56'h54454E20202020;
end

always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n)
	   red <= 56'd0  ;
	else if (red_cnt == color_thred)
	   red <= {56'h52454420202020}  ;
	else if (save_cnt == save_num)
	   red <= 56'd0  ; //after save done clear
end


always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n)
	   green <= 56'd0  ;
	else if (green_cnt == color_thred)
	   green <= {56'h475245454E2020}  ;
	else if (save_cnt == save_num)
	   green <= 56'd0  ; //after save done clear
end

always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n)
	   yellow <= 56'd0  ;
	else if (yellow_cnt == color_thred || pyellow_cnt == color_thred)
	   yellow <= {56'h594549494F5720}  ;
	else if (save_cnt == save_num)
	   yellow <= 56'd0  ; //after save done clear
end

always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n)
	   purple <= 56'd0  ;
	else if (purple_cnt == color_thred)
	   purple <= {56'h505552504C4520}  ;
	else if (save_cnt == save_num)
	   purple <= 56'd0  ; //after save done clear
end

always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n)
	   brown <= 56'd0  ;
	else if (brown_cnt == color_thred)
	   brown <= {56'h42524F574E2020}  ;
	else if (save_cnt == save_num)
	   brown <= 56'd0  ; //after save done clear
end

always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n)
	   orange <= 56'd0  ;
	else if (orange_cnt == color_thred)
	   orange <= {56'h4F52414E474520}  ;
	else if (save_cnt == save_num)
	   orange <= 56'd0  ; //after save done clear
end

always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n)
	   pink <= 56'd0  ;
	else if (pink_cnt == color_thred)
	   pink <= {56'h50494E4B202020}  ;
	else if (save_cnt == save_num)
	   pink <= 56'd0  ; //after save done clear
end

/*******************************************************************************************
     save the number, color and type information in FIFO ; 
*******************************************************************************************/

reg      [55:0]       r_wr_data       ;
//reg                   r_wr_en         ;
reg                   r_rd_en         ;
reg                   r_r_rd_en       ;
reg                   save_flag       ;
reg      [55:0]       send_data       ;
reg      [3:0]        send_cnt        ;
reg      [4:0]        read_cnt        ;
reg                   tx_data_ready_d1;
reg                   tx_data_ready_d2;

wire                  pos_tx_ready    ;
wire     [55:0]       wr_data         ;
wire     [55:0]       rd_data         ;
wire                  full            ;
wire                  almost_full     ;
wire                  empty           ;
wire                  almost_empty    ;
wire                  wr_en           ;
wire                  rd_en           ;

reg      [55:0]       type1  = 56'd0;           
reg      [55:0]       type2  = 56'd0; 
reg      [55:0]       type3  = 56'd0; 
reg      [55:0]       type4  = 56'd0; 
reg      [55:0]       type5  = 56'd0; 
reg      [55:0]       type6  = 56'd0; 
reg      [55:0]       type7  = 56'd0; 
reg      [55:0]       type8  = 56'd0; 
reg      [55:0]       type9  = 56'd0; 
reg      [55:0]       type10 = 56'd0;

assign    wr_data = r_wr_data         ;
assign    wr_en   = save_flag         ;
assign    rd_en   = r_rd_en           ;
assign    pos_tx_ready = tx_data_ready_d1 & (!tx_data_ready_d2) ;

always @(posedge sys_clk or negedge rst_n) begin
	if (!rst_n)
	   save_flag <= 1'b0  ;
	else if ((neg_frame_vaild == 1'b1)&&(RSTATE == R_RF))
	   save_flag <= 1'b1  ;
	else if (save_cnt == save_num)
	   save_flag <= 1'b0  ;
	else
	   save_flag <= save_flag ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
	   save_cnt <= 5'd0  ;
	else if (save_flag == 1'b1) begin
	   if (save_cnt == save_num)
	     save_cnt <= 5'd0  ;
	   else
	     save_cnt <= save_cnt + 5'd1 ;
	end
	else
	   save_cnt <= 5'd0  ;
end
/*----------------------------------------------------------------
Latch the input signal
----------------------------------------------------------------*/

reg                           r_apple_type_en  ;
reg                           r_pear_type_en   ;
reg                           r_banan_type_en  ;
reg                           r_mango_type_en  ;
reg                           r_orang_type_en  ;
reg                           r_grape_type_en  ;
reg                           r_pitay_type_en  ;
reg                           r_kiwi_type_en   ;

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n) begin
        r_s_frame_cnt     <=    3'd0           ;
        r_apple_type_en   <=    1'b0           ;   
        r_pear_type_en    <=    1'b0           ;    
        r_banan_type_en   <=    1'b0           ;    
        r_mango_type_en   <=    1'b0           ;    
        r_orang_type_en   <=    1'b0           ;    
        r_grape_type_en   <=    1'b0           ;   
        r_pitay_type_en   <=    1'b0           ;   
        r_kiwi_type_en    <=    1'b0           ;   

    end
    else begin
        r_s_frame_cnt     <=    s_frame_cnt    ;
        r_apple_type_en   <=    apple_type_en  ;   
        r_pear_type_en    <=    pear_type_en   ;    
        r_banan_type_en   <=    banan_type_en  ;    
        r_mango_type_en   <=    mango_type_en  ;    
        r_orang_type_en   <=    orang_type_en  ;    
        r_grape_type_en   <=    grape_type_en  ;   
        r_pitay_type_en   <=    pitay_type_en  ;   
        r_kiwi_type_en    <=    kiwi_type_en   ;    
    end
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
	   type1 <= 56'd0  ;
	else if (RSTATE == R_RF && r_s_frame_cnt == 3'd1 && red_cnt == color_thred && r_apple_type_en == 1'b1)
       type1 <= 56'h4150504C452020  ; //APPLE ASCII code 4150504C45  space ASCII code 20 
	else if (save_cnt == save_num)
	   type1 <= 56'd0  ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
	   type2 <= 56'd0  ;
	else if (RSTATE == R_RF && r_s_frame_cnt == 3'd1 && green_cnt == color_thred && r_pear_type_en == 1'b1)
       type2 <= 56'h50454152202020  ;
	else if (save_cnt == save_num)
	   type2 <= 56'd0  ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
	   type3 <= 56'd0  ;
	else if (RSTATE == R_RF && r_s_frame_cnt == 3'd1 && yellow_cnt == color_thred && r_banan_type_en == 1'b1)
       type3 <= 56'h42414E414E4120  ;
	else if (save_cnt == save_num)
	   type3 <= 56'd0  ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
	   type4 <= 56'd0  ;
	else if (RSTATE == R_RF && r_s_frame_cnt == 3'd1 && pyellow_cnt == color_thred && r_mango_type_en == 1'b1)
       type4 <= 56'h4D414E474D2020  ;
	else if (save_cnt == save_num)
	   type4 <= 56'd0  ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
	   type5 <= 56'd0  ;
	else if (RSTATE == R_RF && r_s_frame_cnt == 3'd1 && purple_cnt == color_thred && r_grape_type_en == 1'b1)
       type5 <= 56'h47524150452020  ;
	else if (save_cnt == save_num)
	   type5 <= 56'd0  ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
	   type6 <= 56'd0  ;
	else if (RSTATE == R_RF && r_s_frame_cnt == 3'd1 && brown_cnt == color_thred && r_kiwi_type_en == 1'b1)
       type6 <= 56'h4B495749202020  ;
	else if (save_cnt == save_num)
	   type6 <= 56'd0  ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
	   type7 <= 56'd0  ;
	else if (RSTATE == R_RF && r_s_frame_cnt == 3'd1 && orange_cnt == color_thred && r_orang_type_en == 1'b1)
       type7 <= 56'h4F52414E474520  ;
	else if (save_cnt == save_num)
	   type7 <= 56'd0  ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
	   type8 <= 56'd0  ;
//	else if (RSTATE == R_RF && r_s_frame_cnt == 3'd1 && pink_cnt == color_thred && green_cnt == color_thred && r_pitay_type_en == 1'b1)
	else if (RSTATE == R_RF && r_s_frame_cnt == 3'd1 && pink_cnt == color_thred && r_pitay_type_en == 1'b1)
       type8 <= 56'h50495441594120  ;
	else if (save_cnt == save_num)
	   type8 <= 56'd0  ;
end
/////////////////Store in FIFO/////////////////////////////////
//always @(posedge sys_clk or negedge rst_n) begin
//    if (!rst_n) 
//       r_wr_data  <=  56'd0   ;
//    else if (save_flag == 1'b1)  begin 
//       case(save_cnt) //
//           5'd0 : r_wr_data <= red               ;
//           5'd1 : r_wr_data <= green             ;
//           5'd2 : r_wr_data <= yellow            ;
//           5'd3 : r_wr_data <= purple            ;
//           5'd4 : r_wr_data <= brown             ;
//           5'd5 : r_wr_data <= orange            ;
//           5'd6 : r_wr_data <= pink              ;
//           5'd7 : r_wr_data <= r_fruit_num       ;
//           5'd8 : r_wr_data <= type1             ;
//           5'd9 : r_wr_data <= type2             ;
//           5'd10: r_wr_data <= type3             ;
//           5'd11: r_wr_data <= type4             ;
//           5'd12: r_wr_data <= type5             ;
//           5'd13: r_wr_data <= type6             ;
//           5'd14: r_wr_data <= type7             ;
//           5'd15: r_wr_data <= type8             ;
//           5'd16: r_wr_data <= type9             ;
//           5'd17: r_wr_data <= type10            ;
//           default : r_wr_data <= 56'd0           ;
//	endcase
//    end
//end
always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n) 
       r_wr_data  <=  56'd0   ;
    else if (save_flag == 1'b1 && type1 == 56'h4150504C452020)  begin 
       case(save_cnt) //
           5'd0 : r_wr_data <= red               ;
           5'd1 : r_wr_data <= 56'd0             ;
           5'd2 : r_wr_data <= 56'd0             ;
           5'd3 : r_wr_data <= 56'd0             ;
           5'd4 : r_wr_data <= 56'd0             ;
           5'd5 : r_wr_data <= 56'd0             ;
           5'd6 : r_wr_data <= 56'd0             ;
           5'd7 : r_wr_data <= r_fruit_num       ;
           5'd8 : r_wr_data <= type1             ;
           5'd9 : r_wr_data <= type2             ;
           5'd10: r_wr_data <= type3             ;
           5'd11: r_wr_data <= type4             ;
           5'd12: r_wr_data <= type5             ;
           5'd13: r_wr_data <= type6             ;
           5'd14: r_wr_data <= type7             ;
           5'd15: r_wr_data <= type8             ;
           5'd16: r_wr_data <= type9             ;
           5'd17: r_wr_data <= type10            ;
           default : r_wr_data <= 56'd0          ;
	endcase
    end
    else if (save_flag == 1'b1 && type2 == 56'h50454152202020)  begin 
       case(save_cnt) //
           5'd0 : r_wr_data <= 56'd0             ;
           5'd1 : r_wr_data <= green             ;
           5'd2 : r_wr_data <= 56'd0             ;
           5'd3 : r_wr_data <= 56'd0             ;
           5'd4 : r_wr_data <= 56'd0             ;
           5'd5 : r_wr_data <= 56'd0             ;
           5'd6 : r_wr_data <= 56'd0             ;
           5'd7 : r_wr_data <= r_fruit_num       ;
           5'd8 : r_wr_data <= type1             ;
           5'd9 : r_wr_data <= type2             ;
           5'd10: r_wr_data <= type3             ;
           5'd11: r_wr_data <= type4             ;
           5'd12: r_wr_data <= type5             ;
           5'd13: r_wr_data <= type6             ;
           5'd14: r_wr_data <= type7             ;
           5'd15: r_wr_data <= type8             ;
           5'd16: r_wr_data <= type9             ;
           5'd17: r_wr_data <= type10            ;
           default : r_wr_data <= 56'd0          ;
	endcase
    end	
    else if (save_flag == 1'b1 && (type3 == 56'h42414E414E4120 || type4 == 56'h4D414E474D2020))  begin 
       case(save_cnt) //
           5'd0 : r_wr_data <= 56'd0             ;
           5'd1 : r_wr_data <= 56'd0             ;
           5'd2 : r_wr_data <= yellow            ;
           5'd3 : r_wr_data <= 56'd0             ;
           5'd4 : r_wr_data <= 56'd0             ;
           5'd5 : r_wr_data <= 56'd0             ;
           5'd6 : r_wr_data <= 56'd0             ;
           5'd7 : r_wr_data <= r_fruit_num       ;
           5'd8 : r_wr_data <= type1             ;
           5'd9 : r_wr_data <= type2             ;
           5'd10: r_wr_data <= type3             ;
           5'd11: r_wr_data <= type4             ;
           5'd12: r_wr_data <= type5             ;
           5'd13: r_wr_data <= type6             ;
           5'd14: r_wr_data <= type7             ;
           5'd15: r_wr_data <= type8             ;
           5'd16: r_wr_data <= type9             ;
           5'd17: r_wr_data <= type10            ;
           default : r_wr_data <= 56'd0          ;
	endcase
    end	
    else if (save_flag == 1'b1 && type5 == 56'h47524150452020)  begin 
       case(save_cnt) //
           5'd0 : r_wr_data <= 56'd0             ;
           5'd1 : r_wr_data <= 56'd0             ;
           5'd2 : r_wr_data <= 56'd0             ;
           5'd3 : r_wr_data <= purple            ;
           5'd4 : r_wr_data <= 56'd0             ;
           5'd5 : r_wr_data <= 56'd0             ;
           5'd6 : r_wr_data <= 56'd0             ;
           5'd7 : r_wr_data <= r_fruit_num       ;
           5'd8 : r_wr_data <= type1             ;
           5'd9 : r_wr_data <= type2             ;
           5'd10: r_wr_data <= type3             ;
           5'd11: r_wr_data <= type4             ;
           5'd12: r_wr_data <= type5             ;
           5'd13: r_wr_data <= type6             ;
           5'd14: r_wr_data <= type7             ;
           5'd15: r_wr_data <= type8             ;
           5'd16: r_wr_data <= type9             ;
           5'd17: r_wr_data <= type10            ;
           default : r_wr_data <= 56'd0          ;
	endcase
    end	
    else if (save_flag == 1'b1 && type6 == 56'h4B495749202020)  begin 
       case(save_cnt) //
           5'd0 : r_wr_data <= 56'd0             ;
           5'd1 : r_wr_data <= 56'd0             ;
           5'd2 : r_wr_data <= 56'd0             ;
           5'd3 : r_wr_data <= 56'd0             ;
           5'd4 : r_wr_data <= brown             ;
           5'd5 : r_wr_data <= 56'd0             ;
           5'd6 : r_wr_data <= 56'd0             ;
           5'd7 : r_wr_data <= r_fruit_num       ;
           5'd8 : r_wr_data <= type1             ;
           5'd9 : r_wr_data <= type2             ;
           5'd10: r_wr_data <= type3             ;
           5'd11: r_wr_data <= type4             ;
           5'd12: r_wr_data <= type5             ;
           5'd13: r_wr_data <= type6             ;
           5'd14: r_wr_data <= type7             ;
           5'd15: r_wr_data <= type8             ;
           5'd16: r_wr_data <= type9             ;
           5'd17: r_wr_data <= type10            ;
           default : r_wr_data <= 56'd0          ;
	endcase
    end	
    else if (save_flag == 1'b1 && type7 == 56'h4F52414E474520)  begin 
       case(save_cnt) //
           5'd0 : r_wr_data <= 56'd0             ;
           5'd1 : r_wr_data <= 56'd0             ;
           5'd2 : r_wr_data <= 56'd0             ;
           5'd3 : r_wr_data <= 56'd0             ;
           5'd4 : r_wr_data <= 56'd0             ;
           5'd5 : r_wr_data <= orange            ;
           5'd6 : r_wr_data <= 56'd0             ;
           5'd7 : r_wr_data <= r_fruit_num       ;
           5'd8 : r_wr_data <= type1             ;
           5'd9 : r_wr_data <= type2             ;
           5'd10: r_wr_data <= type3             ;
           5'd11: r_wr_data <= type4             ;
           5'd12: r_wr_data <= type5             ;
           5'd13: r_wr_data <= type6             ;
           5'd14: r_wr_data <= type7             ;
           5'd15: r_wr_data <= type8             ;
           5'd16: r_wr_data <= type9             ;
           5'd17: r_wr_data <= type10            ;
           default : r_wr_data <= 56'd0          ;
	endcase
    end	
    else if (save_flag == 1'b1 && type8 == 56'h50495441594120)  begin 
       case(save_cnt) //
           5'd0 : r_wr_data <= 56'd0             ;
           5'd1 : r_wr_data <= 56'd0             ;
           5'd2 : r_wr_data <= 56'd0             ;
           5'd3 : r_wr_data <= 56'd0             ;
           5'd4 : r_wr_data <= 56'd0             ;
           5'd5 : r_wr_data <= 56'd0             ;
           5'd6 : r_wr_data <= pink              ;
           5'd7 : r_wr_data <= r_fruit_num       ;
           5'd8 : r_wr_data <= type1             ;
           5'd9 : r_wr_data <= type2             ;
           5'd10: r_wr_data <= type3             ;
           5'd11: r_wr_data <= type4             ;
           5'd12: r_wr_data <= type5             ;
           5'd13: r_wr_data <= type6             ;
           5'd14: r_wr_data <= type7             ;
           5'd15: r_wr_data <= type8             ;
           5'd16: r_wr_data <= type9             ;
           5'd17: r_wr_data <= type10            ;
           default : r_wr_data <= 56'd0          ;
	endcase
    end
end



FIFO56x32 save_fruit (
  .wr_data        (wr_data        ),      // input [55:0]
  .wr_en          (wr_en          ),      // input
  .full           (full           ),      // output
  .almost_full    (almost_full    ),      // output
  .rd_data        (rd_data        ),      // output [55:0]
  .rd_en          (rd_en          ),      // input
  .empty          (empty          ),      // output
  .almost_empty   (almost_empty   ),      // output
  .clk            (sys_clk        ),      // input
  .rst            (!rst_n         )       // input
);


/*--------------------------------------------------------------------------------
The read bit width is inconsistent with the serial port send bit width, 
so the corresponding read enable processing is required.
---------------------------------------------------------------------------------*/
always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
      r_rd_en   <=    1'b0    ;
    else if (save_cnt == save_num)    //
      r_rd_en   <=    1'b1    ;
    else if ((send_cnt == 4'd6)&&(empty != 1'b1)&&(read_cnt < (save_num + 5'd1))&&(pos_tx_ready == 1'b1)) //not read empty
      r_rd_en   <=    1'b1    ;
    else 
      r_rd_en   <=    1'b0    ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
      r_r_rd_en   <=    1'b0    ;
    else 
      r_r_rd_en   <= r_rd_en    ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
      read_cnt   <=    5'd0        ;
    else if (r_r_rd_en == 1'b1)
      read_cnt   <= read_cnt + 5'd1;
    else if (empty == 1'b1)
      read_cnt   <=    5'd0        ; 
    else if (read_cnt == (save_num + 5'd1))
      read_cnt   <=    5'd0        ; 
    else 
      read_cnt   <=    read_cnt    ;  
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n)
      tx_data_valid <= 1'b0   ;
    else if (r_r_rd_en == 1'b1) 
      tx_data_valid <= 1'b1   ;
    else if ((pos_tx_ready == 1'b1)&&(read_cnt > 5'd0)&&(send_cnt != 4'd6))
      tx_data_valid <= 1'b1   ;
    else 
      tx_data_valid <= 1'b0   ;
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n) begin
      tx_data_ready_d1 <= 1'b0   ;
      tx_data_ready_d2 <= 1'b0   ;
    end
    else begin
      tx_data_ready_d1 <= tx_data_ready   ;
      tx_data_ready_d2 <= tx_data_ready_d1 ;
    end
end

always @(posedge sys_clk or negedge rst_n) begin
    if (!rst_n) begin
      send_data     <=  56'd0 ;
      send_cnt      <=  4'd0  ;
    end
    else if (r_r_rd_en == 1'b1) begin
      send_data     <=  rd_data;
      send_cnt      <=  4'd0   ;
    end
    else if ((pos_tx_ready == 1'b1)&&(read_cnt > 5'd0)) begin
      send_data     <=  {send_data[47:0],{8{1'b0}}};
      if (send_cnt == 4'd6)
        send_cnt <= 4'd0 ;
      else
        send_cnt <= send_cnt + 4'd1;
    end
end

assign tx_data = send_data[55:48] ;

uart_rx#
(
	.CLK_FRE(CLK_FRE),
	.BAUD_RATE(115200)
) uart_rx_inst
(
	.clk                        (sys_clk                  ),
	.rst_n                      (rst_n                    ),
	.rx_data                    (rx_data                  ),
	.rx_data_valid              (rx_data_valid            ),
	.rx_data_ready              (rx_data_ready            ),
	.rx_pin                     (uart_rx                  )
);

uart_tx#
(
	.CLK_FRE(CLK_FRE),
	.BAUD_RATE(115200)
) uart_tx_inst
(
	.clk                        (sys_clk                  ),
	.rst_n                      (rst_n                    ),
	.tx_data                    (tx_data                  ),
	.tx_data_valid              (tx_data_valid            ),
	.tx_data_ready              (tx_data_ready            ),
	.tx_pin                     (uart_tx                  )
);
endmodule