/*-----------------------------------------------------------------------------
 Title      : AHB Master Interface
-------------------------------------------------------------------------------
 File       : AHB_IF.v
 Author     : Corporate Applications Engineering
 Company    : Microsemi Corporation
 Device     : SmartFusion2
 Standard   : Verilog
-------------------------------------------------------------------------------
 Description: This code implements the AHB master logic to receive the write 
 address and data from CMD_Decoder and send via FIC_0 interface.
-------------------------------------------------------------------------------
 Copyright (c) 2014   Microsemi Corporation
                      All rights reserved.
-------------------------------------------------------------------------------
 Revisions  : V1.0
------------------------------------------------------------------------------- */

module AHB_IF( 

/* Generic Signals */
input      wire         HCLK,
input      wire         HRESETn,

/*AHB interface to Logic */
input      wire         READ,
input      wire         WRITE,
input      wire  [31:0] ADDR,
input      wire  [31:0] DATAIN,
output     reg   [31:0] DATAOUT,


/* AHB Side Interfacing with FIC */
output	   reg			HSEL,
output     reg   [31:0] HADDR,
output     reg   [1:0]  HTRANS,
output     reg          HWRITE,
output     wire  [2:0]  HSIZE,
output     wire  [2:0]  HBURST,
output     wire  [3:0]  HPROT,
output     reg   [31:0] HWDATA,
output	   wire		    HREADY_1,
input      wire  [31:0] HRDATA,
input      wire         HREADY,
input      wire  [1:0]  HRESP,
output           [1:0]  RESP_err,
output     reg          AHB_BUSY
);

/* AHB FSM States */
reg [2:0] ahb_fsm_current_state;
parameter [2:0] Idle_1 = 3'b000, Write_FIC_0 = 3'b001, Write_FIC_1 = 3'b010, Write_FIC_2 = 3'b011,
Read_FIC_0 = 3'b100, Read_FIC_1 = 3'b101, Read_FIC_2 = 3'b110;

reg   [31:0] HADDR_int;  /* temporary hold the address */
reg   [31:0] HWDATA_int; /* temporary hold the data */
wire  [2:0]  HSIZE_int;

assign RESP_err = HRESP;
assign HBURST = 3'b000;
assign HPROT  = 4'b0011;
assign HSIZE  = 3'b010; 

assign HREADY_1 = 1'b1;

parameter [4:0] Data_size	= 32;

/* FSM That Acts as Master on AHB Bus
/ Assuming only Non-Sequential & Idle */
always@(posedge HCLK, negedge HRESETn)
begin

	if(HRESETn  == 1'b0)
	    begin
	     HADDR               <=  32'h00000000;
	     HTRANS              <=  2'b00;  
	     HWRITE              <=  1'b0;
		 HSEL						<=  1'b0;
	     
	     HWDATA              <=  32'h00000000;
	     DATAOUT             <=  32'h00000000;
	     ahb_fsm_current_state   <=  Idle_1;
         AHB_BUSY                <=  1'b0;
	    end

	else
    	begin
	        case (ahb_fsm_current_state)
	      
	        Idle_1: 
	            begin
	                if ( WRITE  == 1'b1)
	                  begin
	                    ahb_fsm_current_state       <=  Write_FIC_0;
						HSEL						<=  1'b1;
                        HADDR                       <=  ADDR;
                        HADDR_int                   <=  ADDR;
                        HWDATA_int                  <=  DATAIN;
                        AHB_BUSY                    <=  1'b1;
	                  end
	                else if ( READ  == 1'b1)
	                  begin
						HSEL						<=  1'b1;
	                    ahb_fsm_current_state       <=  Read_FIC_0;
                        HADDR                       <=  ADDR;
                        HADDR_int                   <=  ADDR;
                        AHB_BUSY                    <=  1'b1;
	                  end
	                else
	                  begin
						HSEL						<=  1'b0;
	                    ahb_fsm_current_state       <=  Idle_1;
	                  end
	            end

	        Write_FIC_0: 
	            begin
    	            HTRANS                     <=  2'b10;
    	            
    	            HWRITE                     <=  1'b1;
    	            ahb_fsm_current_state      <=  Write_FIC_1;
                    AHB_BUSY                   <=  1'b1;
	             end
	        
            Write_FIC_1:  
                 begin
                  if ( HREADY  == 1'b0) 
                    begin
        	            HTRANS                 <=  2'b10;
    	                
    	                HWRITE                 <=  1'b1;
    	                HADDR                  <=  HADDR_int;
                        ahb_fsm_current_state  <=  Write_FIC_1;
                        AHB_BUSY               <=  1'b1;
    	            end
                  else  
                    begin
                        HWDATA                 <=  HWDATA_int;
                        HADDR                  <=  32'h00000000; 
                        HTRANS                 <=  2'b00;
    	                HWRITE                 <=  1'b0;
                        ahb_fsm_current_state  <=  Write_FIC_2;
                        AHB_BUSY               <=  1'b1;
                    end
                 end
             Write_FIC_2: 
    	         begin
                  if ( HREADY  == 1'b0) 
                    begin
        	            ahb_fsm_current_state  <=  Write_FIC_2;
                        AHB_BUSY               <=  1'b1;
    	            end
                  else     
    	            begin 
    	                ahb_fsm_current_state  <=  Idle_1;
                        AHB_BUSY               <=  1'b0;
    	            end
	              end
	           
	         Read_FIC_0: 
	              begin
	                    HTRANS                  <=  2'b10;
	                    
	                    HWRITE                  <=  1'b0;
	                    ahb_fsm_current_state   <=  Read_FIC_1;
                        AHB_BUSY                <=  1'b1;
	              end
	         Read_FIC_1: 
	              begin                   
	               if ( HREADY  == 1'b1) 
                     begin
	                    ahb_fsm_current_state    <=  Read_FIC_2;
                     end 
                   else   
                     begin   
                        HTRANS                   <=  2'b10;
	                    
	                    HWRITE                   <=  1'b0;
	                    HADDR                    <=  HADDR_int;
	                    ahb_fsm_current_state    <=  Read_FIC_1;
                        AHB_BUSY                 <=  1'b1;
                     end
                  end
             Read_FIC_2:                          
	              begin
                   if ( HREADY  == 1'b1)         
	                 begin
	                    DATAOUT                  <=  HRDATA;	                         
	                    ahb_fsm_current_state    <=  Idle_1;
                        AHB_BUSY                 <=  1'b0;
	                 end
	               else  
	                 begin
	                    ahb_fsm_current_state    <=  Read_FIC_2;
                        AHB_BUSY                 <=  1'b1;
	                  end
                         
                        HADDR                    <=  32'h00000000;  
                        HTRANS                   <=  2'b00;

	              end 	   
     endcase
	end     
end

endmodule