/*-------------------------------------------------------------------------------
 Title      : COM Interface
-------------------------------------------------------------------------------
 File       : Control_Logic.v
 Author     : Corporate Applications Engineering
 Company    : Microsemi Corporation
 Device     : IGLOO2
 Standard   : Verilog
-------------------------------------------------------------------------------
 Description: It receives the COMMAND from PC GUI and send to COMMAND Decoder.
              Once AXI master completes the data transfer, it read the throughput
              from LSRAM and send to PC. It also send MDDR Configuration register
              values to PC.
-------------------------------------------------------------------------------
 Copyright (c) 2014   Microsemi Corporation
                      All rights reserved.
-------------------------------------------------------------------------------
 Revisions  : V1.0
-------------------------------------------------------------------------------*/

module Control_Logic( 
	input wire		 CLK,
	input wire		 RESET_N,
	input wire		 TX_RDY,
	input wire		 RX_RDY,
	input wire		 AXI_BUSY,
	input wire [7:0] DATA_IN,
	input wire [7:0] RAM_RD,
	input wire	     AHB_BUSY,
	input wire [31:0]AHB_DATA,

	output reg		  RAM_REN,
	output reg		  WEN,
	output reg		  OEN,
	output reg  [7:0] DATA_OUT,
	output wire [7:0] COMMAND,
	output reg  [3:0] RAM_RADDR
);

reg [3:0]  fsm;
reg [7:0]  CMD;
reg [31:0] DATA_OUT_tmp;
reg [1:0]  cnt4;
reg sel;

wire [3:0] PDM;

assign COMMAND  = CMD;
assign PDM    = {CMD[5],CMD[4],CMD[3],CMD[2]};

always @(posedge CLK or negedge RESET_N)
if(!RESET_N)
 begin
    DATA_OUT_tmp <= 32'h00000000;
    DATA_OUT     <= 8'b00000000;
	CMD          <= 8'b00000000;
    RAM_RADDR    <= 4'b1111;
	WEN          <= 1'b1;
	OEN          <= 1'b1;
	RAM_REN      <= 1'b0;
    sel          <= 1'b0;
	cnt4         <= 2'b00;
	fsm          <= 4'b0000; 
 end
else
 begin
   case (fsm)
    4'b0000 :  
      begin
        DATA_OUT_tmp <= 32'h00000000;
		DATA_OUT     <= 8'b00000000;
		RAM_RADDR    <= 4'b1111;
		WEN          <= 1'b1;
		OEN          <= 1'b1;
		RAM_REN      <= 1'b0;
		sel          <= 1'b0;
		cnt4         <= 2'b00;
        if(RX_RDY == 1'b1) 
		  begin
            if(DATA_IN == 8'b01111000) /* 'x' */
              begin
                OEN  <= 1'b0;
                fsm  <= 4'b0001;                   
              end
            else
              begin
                OEN     <= 1'b0;
			    CMD     <= DATA_IN;
                fsm     <= 4'b0100; 
              end
		  end
        else
		  begin
            OEN <= 1'b1;
		    fsm <= 4'b0000;
			CMD <= 8'b00000000;
		  end		
	  end  
	4'b0001 :      /* Acknowledge 'a' */ 
      begin
	    OEN <= 1'b1;
        if(TX_RDY == 1'b1)
          begin
            DATA_OUT <= 8'b01100001; /* 'a' */
            WEN      <= 1'b0;
			fsm      <= 4'b0010;
          end
        else
          begin
            WEN <= 1'b1;
            fsm <= 4'b0001;
          end	  
	  end
	4'b0010 :      
      begin
	    WEN  <= 1'b1;
		fsm  <= 4'b0000;  //fsm  <= 4'b0011; 
	  end
	4'b0011 :  /* Reading the Command */
      begin
        if(RX_RDY == 1'b1) 
		  begin
            OEN     <= 1'b0;
			CMD     <= DATA_IN;
            fsm     <= 4'b0100;                  
		  end
        else
		  begin
            OEN     <= 1'b1;
			CMD     <= 8'b00000000;
            fsm     <= 4'b0011; 
		  end
	  end
    4'b0100 :  
      begin
	  	OEN     <= 1'b1;
		if ( (PDM == 4'b1001) || (PDM == 4'b1010) || (PDM == 4'b1011) || (PDM == 4'b1100) ||(PDM == 4'b1101) )
		  begin
		    fsm     <= 4'b1100;       /* Reading Configuration Register  */
		  end
		else if( PDM == 4'b1110 )
		  begin
		    fsm     <= 4'b1000;       /* Reading Throughput values  */
		  end
        else
          begin
		    fsm     <= 4'b0000;
          end
	  end
    4'b1100 :
      begin
		    fsm     <= 4'b1101;
      end
    4'b1101 :
      begin
		    fsm     <= 4'b0101;
      end
    4'b0101 :  
      begin
		if( AHB_BUSY == 1'b1 )
		  begin
		    fsm     <= 4'b0101;
		  end
		else 
		  begin
		    DATA_OUT_tmp <= AHB_DATA;
			cnt4         <= 2'b00;
		    fsm          <= 4'b0110; 
		  end
	  end
	4'b0110 :      /* Sending Register values to CoreUART  */ 
      begin
        if(TX_RDY == 1'b1)
          begin
            WEN                 <= 1'b0;
			fsm                 <= 4'b0111;
			DATA_OUT            <= DATA_OUT_tmp[31:24];
			DATA_OUT_tmp[31:24] <= DATA_OUT_tmp[23:16];
			DATA_OUT_tmp[23:16] <= DATA_OUT_tmp[15:8];
			DATA_OUT_tmp[15:8]  <= DATA_OUT_tmp[7:0];
			cnt4                <= cnt4 + 1'b1;
			if(cnt4 == 2'b11)
			  begin
				sel <= 1'b1;
			  end
			else
			  begin
				sel <= 1'b0;			  
			  end
          end
        else
          begin
            WEN <= 1'b1;
            fsm <= 4'b0110; 
          end	  
	  end
	4'b0111 :      
      begin
	  	WEN  <= 1'b1;
	    if (TX_RDY == 1'b0)
		  begin
            if(sel == 1'b1)
                fsm  <= 4'b0000;
			else
		        fsm  <= 4'b0110;  
		  end
	  end
    4'b1000 :  /* Sending the throughput values to CoreUART  */ 
      begin
			RAM_RADDR <= RAM_RADDR + 1;
            fsm       <= 4'b1001;    
	  end 
	4'b1001 :  
      begin
			RAM_REN   <= 1'b1;
            fsm       <= 4'b1010; 
	  end
    4'b1010 :  
      begin
		if(TX_RDY == 1'b1)
		  begin
            DATA_OUT <= RAM_RD;  
            WEN      <= 1'b0;	
            fsm      <= 4'b1011;	
			RAM_REN  <= 1'b0;	
		  end
		else
		  begin
            fsm      <= 4'b1010; 
		  end
	  end
    4'b1011 :  
      begin
        WEN     <= 1'b1; 
        if(TX_RDY == 1'b0)
		  begin
			if(RAM_RADDR == 4'b1111)
			  begin
                fsm     <= 4'b0000; 
			  end
			else
			  begin
               fsm   <= 4'b1000;  
			  end
		  end
		else
		  begin
            fsm      <= 4'b1011;	
		  end
	  end 
    default : fsm <= 4'b0000;    
  endcase
end
endmodule


