///////////////////////////////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------------------
//-- Title      : AXI Master Interface
//-------------------------------------------------------------------------------
//-- File       : AXI_IF.v
//-- Author     : Corporate Applications Engineering
//-- Company    : Microsemi Corporation
//-- Device     : IGLOO2
//-- Standard   : Verilog
//-------------------------------------------------------------------------------
//-- Description: This code implementes the AXI master logic to write the data to  
//--              MDDR through DDR_FIC and does 64bit burst transactions.
//-------------------------------------------------------------------------------
//-- Copyright (c) 2013   Microsemi Corporation
//--                      All rights reserved.
//-------------------------------------------------------------------------------
//-- Revisions  : V1.0
//-------------------------------------------------------------------------------
/////////////////////////////////////////////////////////////////////////////////////////////////// 

module AXI_IF(
	//input DRAM_Ready,
	input 				CLK,
	input 				RESETn,

	input 				write_start,
	input 				read_start,
    input    wire[3:0]  WLEN,
    input    wire[3:0]  RLEN,
    input    wire[63:0] WDATA_int_input,
    input    wire[31:0] AWADDR_int,
    input    wire[31:0] ARADDR_int,
	output	 reg		AXI_WBUSY,
    output   reg        AXI_RBUSY,  
  	// Write Address Channel (WAC)
	output		[3:0]   AWID, 
	output	reg [31:0]  AWADDR, 
  	output  reg	[3:0]   AWLEN, 
  	output reg 	[2:0]   AWSIZE, 
  	output  	[1:0]   AWLOCK,  
  	output reg 	[1:0]   AWBURST, 
  	output reg          AWVALID,  
  	input               AWREADY,  
  	// Write Data Channel (RDC)
  	output  [3:0]       WID, 
  	output reg [7:0]    WSTRB,
  	output reg          WLAST,
  	output reg          WVALID,
  	output reg [63:0]   WDATA, 
  	input               WREADY, 	
  	// Write Response Channel (WRC)
 	input [3:0]         BID,
	input [1:0]         BRESP,  
	input               BVALID,	
	output   reg        BREADY,
  // Read Address Channel (RAC)
	output [3:0]        ARID, 
	output reg [31:0]   ARADDR, 
	output reg [3:0]    ARLEN, 
    output reg [1:0]      ARSIZE, 
    output  [1:0]         ARLOCK, 
    output reg [1:0]      ARBURST, 
    output reg            ARVALID, 
    input                 ARREADY, 
  // Read Data Channel (RDC)
    input [3:0]           RID,
    input [63:0]          RDATA, 
    input [1:0]           RRESP,
    input                 RLAST,
    input                 RVALID,
    output reg            RREADY);

// AXI FSM States
reg [2:0] axi_fsm_current_state;
reg [2:0] axi_fsm_read_state;

parameter [2:0] Idle_0 = 3'b000, Idle_1 = 3'b001, Write_0 = 3'b010, Write_1 = 3'b011, Read_0 = 3'b010, Read_1 = 3'b011, Read_2 = 3'b100, Bresp_0 = 3'b100, Write_2 = 3'b101;


reg   [63:0] WDATA_int;
reg   [3:0] burst_cnt;

//////////////////////////////

assign AWLOCK = 2'b00;
assign ARLOCK = 2'b00;
assign AWID  = 4'b0000;
assign WID = 4'b0000;
assign ARID = 4'b0000;


//Write address, Write data and Write response channels
always@(posedge CLK, negedge RESETn)
begin	
	if(RESETn == 1'b0 )
		begin
		 WDATA_int		<= 64'h0000000000000000; 
         WDATA          <= 64'h0000000000000000;
		 AWSIZE 		<= 3'b000;		 
		 AWBURST 		<= 2'b00;		
		 WSTRB  		<= 8'h00;		 
		 AXI_WBUSY		<= 1'b0;
		 AWVALID 		<= 1'b0;
		 WVALID 		<= 1'b0;
		 WLAST  		<= 1'b0;
		 burst_cnt 		<= 4'b0000;
		 axi_fsm_current_state   <=  Idle_1;
         BREADY         <= 1'b0;
		end
	else
		begin
			case (axi_fsm_current_state)
			Idle_1:
			begin
                BREADY            <= 1'b0; 
				if ( write_start == 1'b1 )
				begin
				AWSIZE 					<= 3'b011;
				AWBURST 				<= 2'b01;// incremental burst
				AWADDR 					<= AWADDR_int ;
                WDATA_int               <= WDATA_int_input;
				AWVALID 				<= 1'b1;
				burst_cnt 				<= 4'b0000;  
				AXI_WBUSY				<= 1'b1;
				axi_fsm_current_state   <= Write_0;
                AWLEN                   <= WLEN;                
				end
				else
				begin
				axi_fsm_current_state   <= Idle_1;
				end
			end
			Write_0:
			begin
				if (AWREADY == 1'b1)
				begin
				AWVALID 				<= 1'b0;
				WSTRB  					<= 8'hFF;
				WVALID 					<= 1'b1;
				WDATA                   <= WDATA_int;
                WDATA_int               <= WDATA_int+1;
				axi_fsm_current_state   <= Write_1;
                    if(AWLEN == 4'b0000)
                        begin
                            WLAST  		<= 1'b1;
                        end
                    else
                        begin
                            WLAST  		<= 1'b0;
                        end

				end
				else
				begin
				axi_fsm_current_state   <= Write_0;
				end
			end
			Write_1:
			begin
				if (WREADY == 1'b1)
				begin	
				WDATA <= WDATA_int;			
				WDATA_int <= WDATA_int+1;
				burst_cnt <= burst_cnt+1;
                    if(AWLEN == 4'b0000)                      
                    begin
                        WLAST  					<= 1'b0;
                        WVALID 					<= 1'b0;
                        axi_fsm_current_state   <= Bresp_0;
                    end
                    else
                    begin
                        WVALID 					<= 1'b1;
                        if(burst_cnt == AWLEN-1'b1)  
                        begin
                        WLAST  					<= 1'b1;
                        axi_fsm_current_state   <= Write_2;					
                        end
                        else
                        begin
                        axi_fsm_current_state   <= Write_1;	
                        end
                    end
				end
				else
				begin
				axi_fsm_current_state   <= Write_1;
				end
			end
			Write_2:
			begin
				if (WREADY == 1'b1)
				begin	
				WVALID 					<= 1'b0;
				WLAST  					<= 1'b0;
				axi_fsm_current_state   <= Bresp_0;
				end
				
			end		
			Bresp_0:
			begin
				if (BVALID == 1'b1)
				begin			
                BREADY                <= 1'b1;
				AXI_WBUSY			  <= 1'b0;		 		
				axi_fsm_current_state <= Idle_1;
				end
				else
				begin
				axi_fsm_current_state <=  Bresp_0;
                BREADY   <= 1'b0;
				end
			end	
			
			endcase
	end
end

//Read address and Read data channels
always@(posedge CLK, negedge RESETn)
begin	
	if(RESETn == 1'b0 )
		begin
		 ARADDR 	 		<= 32'h00000000;		 
		 ARSIZE 		    <= 3'b000;		 
		 ARBURST 	    	<= 2'b00;	
		 RREADY				<= 1'b0;
		 ARVALID 			<= 1'b0;	
         AXI_RBUSY          <= 1'b0;	 		 
		 axi_fsm_read_state <=  Idle_1;
		end
	else
		begin 
			case (axi_fsm_read_state)
			Idle_1:
			begin
                RREADY					<= 1'b0;
 
				if ( read_start == 1'b1 )
				begin						

				ARSIZE 					<= 3'b011;
				ARBURST 				<= 2'b01;
				ARADDR 					<= ARADDR_int;
				ARVALID 				<= 1'b1;
				axi_fsm_read_state      <= Read_0;
                ARLEN                   <= RLEN;
                AXI_RBUSY               <= 1'b1;
				end
				else
				begin

				axi_fsm_read_state   <= Idle_1;
				end
			end
			Read_0:
			begin
				if (ARREADY == 1'b1)
				begin
				ARVALID 				<= 1'b0;
				axi_fsm_read_state      <= Read_2;
				end
				else
				begin
				axi_fsm_read_state      <= Read_0;
				end
			end
			Read_2:
			begin
				if (RVALID == 1'b1)
				begin
                    RREADY					<= 1'b1;

                    if (RLAST == 1'b1)
                        begin					
                        AXI_RBUSY           <= 1'b0;			
                        axi_fsm_read_state  <= Idle_1;
                        end
                end
				else
				begin
				axi_fsm_read_state   <= Read_2;
				end
			end			
			
			endcase
	end
end


endmodule

