///////////////////////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------
//-- Title      : APB slave wrapper
//-------------------------------------------------------------------------------
//-- File       : DATAHANDLE_FSM.v
//-- Author     : Corporate Applications Engineering
//-- Company    : Microsemi Corporation
//-- Device     : SmartFusion2
//-- Standard   : Verilog
//-------------------------------------------------------------------------------
//-- Description: It is a APB wrapper recieves the data from the MSS through FIC_0 interface and sends the data to UART_IF_FSM 
//-------------------------------------------------------------------------------
//-- Copyright (c) 2013   Microsemi Corporation
//--                      All rights reserved.
//-------------------------------------------------------------------------------
//-- Revisions  : V1.0
//-------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////////////////////


`timescale 1 ns/100 ps
module DATAHANDLE_FSM(
  PCLK,
  PENABLE,
  PSEL,
  PRESETN,
  PWRITE,
  PREADY,
  PSLVERR,
  PADDR,
  PWDATA,
  PRDATA,

  ram_ren, 
  ram_rdata,
  ram_raddr,
  user_option,
  user_address,
  user_data1,
  user_data2,
  start_axi

  );

parameter DATA_WIDTH = 32;                 // data width 
parameter ADDR_WIDTH = 32;                 // address width 
  
input  PCLK,PENABLE, PSEL, PRESETN, PWRITE;
input  [ADDR_WIDTH-1:0] PADDR;
input  [DATA_WIDTH-1:0] PWDATA;
input  [DATA_WIDTH-1:0] ram_rdata;
output reg [DATA_WIDTH-1:0] PRDATA;
output PREADY, PSLVERR;
output ram_ren;

output [8:0] ram_raddr;
output reg [7:0] user_option;
output reg [31:0] user_address;
output reg [31:0] user_data1;
output reg [31:0] user_data2;
output reg start_axi;

reg SEL; 
reg [8:0] ram_raddr;
reg ram_ren;
reg PREADY;
reg  [1:0]   fsm;                       //state machine register


wire [DATA_WIDTH-1:0] ram_rdata;

assign PSLVERR = 1'b0;

always@(PADDR)
begin 
                                    if (PADDR[12:2] == 11'b0000000000)   
                                     begin
                                        PRDATA <= user_option;               
                                        ram_ren <= 1'b0;
                                        ram_raddr <= 9'b000000000;
                                      end
                                    else if (PADDR[12:2] == 11'b0000000001) 
                                      begin
                                        PRDATA <= user_address;
                                        ram_ren <= 1'b0;
                                        ram_raddr <= 9'b000000000;
                                       end
                                    else if (PADDR[12:2] == 11'b0000000010) 
                                      begin
                                        PRDATA <= user_data1;
                                        ram_ren <= 1'b0;
                                        ram_raddr <= 9'b000000000;
                                       end
                                     else if(PADDR[12:2] == 11'b0000000011) 
                                      begin                                  
                                        PRDATA <= user_data2;
                                        ram_ren <= 1'b0;
                                        ram_raddr <= 9'b000000000;
                                       end
                                      else
                                        begin
                                        ram_ren <= 1'b1;
                                        ram_raddr <= PADDR[12:2] - 3'b100;
                                        PRDATA <= ram_rdata;
                                        end
end



always@(posedge PCLK or negedge PRESETN)
begin
if(~PRESETN)
  begin
      fsm <= 2'b00;
      PREADY <= 1'b1;
      start_axi   <= 1'b0;
      user_option <= 8'b0000000;
      user_address <= 32'h0000000;
      user_data1 <= 32'h00000000;
      user_data2 <= 32'h00000000;
  end
else
  begin
  
  case (fsm)
     2'b00 :  begin
                                 
                  if (~PSEL)
                        begin
                         fsm <= 2'b00;   
						 start_axi   <= 1'b0;   
                         PREADY <= 1'b0;      
             
                        end
                  else        
                        begin
                          fsm <= 2'b01;
                          if (PWRITE)
                                begin
                                   PREADY <= 1'b1;
                                    if (PADDR[3:2] == 2'b00) 
                                     begin
                                        user_option <= PWDATA[7:0];
										start_axi   <= 1'b0;                                    
                                      end
                                    else if (PADDR[3:2] == 2'b01) 
                                      begin
                                   	   user_address <= PWDATA;
										start_axi   <= 1'b0;                                       
                                       end
                                    else if (PADDR[3:2] == 2'b10) 
                                      begin
                                       user_data1 <= PWDATA;
										start_axi   <= 1'b0;
                                       end
                                     else if(PADDR[3:2] == 2'b11) 
                                      begin                                    
 									    user_data2 <= PWDATA;             
										start_axi   <= 1'b1;                                        
                                      end

                                end
                        end
               end

     2'b01 :  begin    
                          start_axi   <= 1'b0;
                          if (PWRITE)
                            begin 
                                fsm <= 2'b00;
                                PREADY <= 1'b1;
                              
                             end
                          else
                             begin   
                                PREADY <= 1'b1;
                                fsm <= 2'b10;
                                
                              end

              end

     2'b10 :  begin                            
                          PREADY <= 1'b0;
						  start_axi   <= 1'b0;        
                          fsm <= 2'b11;                               
              end

     2'b11 :  begin     
                          PREADY <= 1'b0;
                          fsm <= 2'b00;
  

              end


    default : fsm <= 2'b00;
  endcase
end
end
   
endmodule
