// ****************************************************************************/
// Actel Corporation Proprietary and Confidential
// Copyright 2010 Actel Corporation.  All rights reserved.
//
// ANY USE OR REDISTRIBUTION IN PART OR IN WHOLE MUST BE HANDLED IN
// ACCORDANCE WITH THE ACTEL LICENSE AGREEMENT AND MUST BE APPROVED
// IN ADVANCE IN WRITING.
//
// Description: master_stage - Module defines interface with Master 
//
// Revision Information:
// Date            Description
// ----            -----------------------------------------
// 02Feb11         Inital. Ports and Parameters declaration
//
// SVN Revision Information:
// SVN $Revision: 11146 $
// SVN $Date: 2009-11-21 11:44:53 -0800 (Sat, 21 Nov 2009) $
//
// Resolved SARs
// SAR      Date     Who   Description
//
// Notes:
// 1. 
//
// ****************************************************************************/
`timescale 1ns/1ps
module master_stage (
    // Global signals
    ACLK,
    ARESETN,

    // MASTER 0
    // AXI MASTER 0 write address channel signals
    AWID_M0,
    AWADDR_M0,
    AWLEN_M0,
    AWSIZE_M0,
    AWBURST_M0,
    AWLOCK_M0,
    AWCACHE_M0,
    AWPROT_M0,
    AWVALID_M0,
    AWREADY_M0,
    // AXI MASTER 0 write data channel signals
    WID_M0,
    WDATA_M0,
    WSTRB_M0,
    WLAST_M0,
    WVALID_M0,
    WREADY_M0,
    // AXI MASTER 0 write response channel signals
    BID_M0,
    BRESP_M0,
    BVALID_M0,
    BREADY_M0,
    // AXI MASTER 0 read address channel signals
    ARID_M0,
    ARADDR_M0,
    ARLEN_M0,
    ARSIZE_M0,
    ARBURST_M0,
    ARLOCK_M0,
    ARCACHE_M0,
    ARPROT_M0,
    ARVALID_M0,
    ARREADY_M0,
    // AXI MASTER 0 read response channel signals
    RID_M0,
    RDATA_M0,
    RRESP_M0,
    RLAST_M0,
    RVALID_M0,
    RREADY_M0,

    // SLAVE 0
    // AXI SLAVE 0 write address channel signals
    AWID_MI,
    AWADDR_MI,
    AWLEN_MI,
    AWSIZE_MI,
    AWBURST_MI,
    AWLOCK_MI,
    AWCACHE_MI,
    AWPROT_MI,
    AWVALID_MI,
    AWREADY_IM,
    // AXI SLAVE 0 write data channel signals
    WID_MI,
    WDATA_MI,
    WSTRB_MI,
    WLAST_MI,
    WVALID_MI,
    WREADY_IM,
    // AXI SLAVE 0 write response channel signals
    BID_IM,
    BRESP_IM,
    BVALID_IM,
    BREADY_MI,
    // AXI SLAVE 0 read address channel signals
    ARID_MI,
    ARADDR_MI,
    ARLEN_MI,
    ARSIZE_MI,
    ARBURST_MI,
    ARLOCK_MI,
    ARCACHE_MI,
    ARPROT_MI,
    ARVALID_MI,
    ARREADY_IM,
    // AXI SLAVE 0 read response channel signals
    RID_IM,
    RDATA_IM,
    RRESP_IM,
    RLAST_IM,
    RVALID_IM,
    RREADY_MI,
    awaddr_buf,
    araddr_buf
);

    parameter AXI_AWIDTH           = 32;
    parameter AXI_DWIDTH           = 64;
    parameter AXI_STRBWIDTH        = AXI_DWIDTH/8;
    parameter NUM_SLAVE_SLOT       = 1;
    parameter ID_WIDTH             = 4;
    parameter BASE_ID_WIDTH        = 0;

    localparam UNIQUE_MASTER_ID    = 0;  // ID appended unique to Master by the core

   // Global signals
   input      ACLK;
   input      ARESETN;

   // MASTER 0
   // AXI MASTER 0 write address channel signals
   input [ID_WIDTH-1:0]          AWID_M0;
   input [AXI_AWIDTH-1:0]        AWADDR_M0;
   input [3:0]                   AWLEN_M0;
   input [2:0]                   AWSIZE_M0;
   input [1:0]                   AWBURST_M0;
   input [1:0]                   AWLOCK_M0;
   input [3:0]                   AWCACHE_M0;
   input [2:0]                   AWPROT_M0;
   input                         AWVALID_M0;
   output                        AWREADY_M0;
   // AXI MASTER 0 write data channel signals
   input [ID_WIDTH-1:0]          WID_M0;
   input [AXI_DWIDTH-1:0]        WDATA_M0;
   input [AXI_STRBWIDTH-1:0]     WSTRB_M0;
   input                         WLAST_M0;
   input                         WVALID_M0;
   output                        WREADY_M0;
   // AXI MASTER 0 write response channel signals
   output [ID_WIDTH-1:0]         BID_M0;
   output [1:0]                  BRESP_M0;
   output                        BVALID_M0;
   input                         BREADY_M0;
   // AXI MASTER 0 read address channel signals
   input [ID_WIDTH-1:0]          ARID_M0;
   input [AXI_AWIDTH-1:0]        ARADDR_M0;
   input [3:0]                   ARLEN_M0;
   input [2:0]                   ARSIZE_M0;
   input [1:0]                   ARBURST_M0;
   input [1:0]                   ARLOCK_M0;
   input [3:0]                   ARCACHE_M0;
   input [2:0]                   ARPROT_M0;
   input                         ARVALID_M0;
   output                        ARREADY_M0;
   // AXI MASTER 0 read response channel signals
   output [ID_WIDTH-1:0]         RID_M0;
   output [AXI_DWIDTH-1:0]       RDATA_M0;
   output [1:0]                  RRESP_M0;
   output                        RLAST_M0;
   output                        RVALID_M0;
   input                         RREADY_M0;

   // SLAVE 0
   // AXI SLAVE 0 write address channel signals
   output [BASE_ID_WIDTH+ID_WIDTH - 1:0] AWID_MI;
   output [AXI_AWIDTH-1:0]      AWADDR_MI;
   output [3:0]                 AWLEN_MI;
   output [2:0]                 AWSIZE_MI;
   output [1:0]                 AWBURST_MI;
   output [1:0]                 AWLOCK_MI;
   output [3:0]                 AWCACHE_MI;
   output [2:0]                 AWPROT_MI;
   output                       AWVALID_MI;
   input                        AWREADY_IM;
   // AXI SLAVE 0 write data channel signals
   output [BASE_ID_WIDTH + ID_WIDTH - 1:0] WID_MI;
   output [AXI_DWIDTH-1:0]      WDATA_MI;
   output [AXI_STRBWIDTH-1:0]   WSTRB_MI;
   output                       WLAST_MI;
   output                       WVALID_MI;
   input                        WREADY_IM;
   // AXI SLAVE 0 write response channel signals
   input [BASE_ID_WIDTH + ID_WIDTH - 1:0] BID_IM;
   input  [1:0]                 BRESP_IM;
   input                        BVALID_IM;
   output                       BREADY_MI;
   // AXI SLAVE 0 read address channel signals
   output [(BASE_ID_WIDTH+ID_WIDTH)-1:0] ARID_MI;
   output [AXI_AWIDTH-1:0]      ARADDR_MI;
   output [3:0]                 ARLEN_MI;
   output [2:0]                 ARSIZE_MI;
   output [1:0]                 ARBURST_MI;
   output [1:0]                 ARLOCK_MI;
   output [3:0]                 ARCACHE_MI;
   output [2:0]                 ARPROT_MI;
   output                       ARVALID_MI;
   input                        ARREADY_IM;
   // AXI SLAVE 0 read response channel signals
   input [(BASE_ID_WIDTH+ID_WIDTH)-1:0] RID_IM;
   input  [AXI_DWIDTH-1:0]      RDATA_IM;
   input  [1:0]                 RRESP_IM;
   input                        RLAST_IM;
   input                        RVALID_IM;
   output                       RREADY_MI;

   output [AXI_AWIDTH - 1:0]    awaddr_buf;
   output [AXI_AWIDTH - 1:0]    araddr_buf;


   // --------------------------------------------------------------------------
   // Internal signals
   // --------------------------------------------------------------------------
   reg [BASE_ID_WIDTH+ID_WIDTH - 1:0] AWID_MI;
   reg [AXI_AWIDTH-1:0]      AWADDR_MI;
   reg [3:0]                 AWLEN_MI;
   reg [2:0]                 AWSIZE_MI;
   reg [1:0]                 AWBURST_MI;
   reg [1:0]                 AWLOCK_MI;
   reg [3:0]                 AWCACHE_MI;
   reg [2:0]                 AWPROT_MI;
   reg                       AWVALID_MI;

   reg [BASE_ID_WIDTH+ID_WIDTH - 1:0] ARID_MI;
   reg [AXI_AWIDTH-1:0]      ARADDR_MI;
   reg [3:0]                 ARLEN_MI;
   reg [2:0]                 ARSIZE_MI;
   reg [1:0]                 ARBURST_MI;
   reg [1:0]                 ARLOCK_MI;
   reg [3:0]                 ARCACHE_MI;
   reg [2:0]                 ARPROT_MI;
   reg                       ARVALID_MI;
   reg                       RREADY_MI;
   reg                       BREADY_MI;

   reg [BASE_ID_WIDTH+ID_WIDTH - 1:0] WID_MI;
   reg [AXI_DWIDTH-1:0]      WDATA_MI;
   reg                       WVALID_MI;
   reg                       WLAST_MI;
   reg [AXI_STRBWIDTH-1:0]   WSTRB_MI;

   reg [AXI_AWIDTH - 1:0]  awaddr_bf0;
   reg [AXI_AWIDTH - 1:0]  araddr_bf0;
   reg [AXI_AWIDTH - 1:0]  awaddr_bf1;
   reg [AXI_AWIDTH - 1:0]  araddr_bf1;
   reg [AXI_AWIDTH - 1:0]  awaddr_bf2;
   reg [AXI_AWIDTH - 1:0]  araddr_bf2;
   reg [AXI_AWIDTH - 1:0]  awaddr_bf3;
   reg [AXI_AWIDTH - 1:0]  araddr_bf3;
   reg [AXI_AWIDTH - 1:0]  awaddr_buf;
   reg [AXI_AWIDTH - 1:0]  araddr_buf;
   wire [(BASE_ID_WIDTH+ID_WIDTH)-1:0] AWID_int;
   wire [(BASE_ID_WIDTH+ID_WIDTH)-1:0] WID_int;
   wire [(BASE_ID_WIDTH+ID_WIDTH)-1:0] ARID_int;
   wire                                              waddr_buf_full;
   wire                                              raddr_buf_full;
   reg [AXI_AWIDTH - 1 : 0]                          awaddr_buf_r;
   reg [AXI_AWIDTH - 1 : 0]                          araddr_buf_r;

   wire [3:0]                                         pending_wr_req;
   reg [3:0]                                         pending_wr_req_r;
   wire [3:0]                                         pending_rd_req;
   reg [3:0]                                         pending_rd_req_r;
   integer k;
   integer p;
   reg [3:0]                                         wreq_set;
   reg [3:0]                                         wreq_reset;
   reg [3:0]                                         rreq_set;
   reg [3:0]                                         rreq_reset;
   reg [AXI_AWIDTH - 1:0]  awaddr_bf0_d1;
   reg [AXI_AWIDTH - 1:0]  araddr_bf0_d1;
   reg [AXI_AWIDTH - 1:0]  awaddr_bf1_d1;
   reg [AXI_AWIDTH - 1:0]  araddr_bf1_d1;
   reg [AXI_AWIDTH - 1:0]  awaddr_bf2_d1;
   reg [AXI_AWIDTH - 1:0]  araddr_bf2_d1;
   reg [AXI_AWIDTH - 1:0]  awaddr_bf3_d1;
   reg [AXI_AWIDTH - 1:0]  araddr_bf3_d1;


   /////////////////////////////////////////////////////////////////////////////
   //                               Start - of - Code                         //
   /////////////////////////////////////////////////////////////////////////////

   always @(*) begin
      // Latched Write data channel signals
      WID_MI      = WID_int;
      WDATA_MI    = WDATA_M0;
      WSTRB_MI    = WSTRB_M0;
      WLAST_MI    = WLAST_M0;
      WVALID_MI   = WVALID_M0;
   end

   //---------------------------------------------------------------------------
   // Write address signals to the Interconnect
   //---------------------------------------------------------------------------
   always @(*) begin  
      // Latched Write Address signals 
      AWVALID_MI  <= AWVALID_M0;
      AWLEN_MI    <= AWLEN_M0;
      AWSIZE_MI   <= AWSIZE_M0;
      AWBURST_MI  <= AWBURST_M0;
      AWLOCK_MI   <= AWLOCK_M0;
      AWCACHE_MI  <= AWCACHE_M0;
      AWPROT_MI   <= AWPROT_M0;
      AWADDR_MI   <= AWADDR_M0;
      AWID_MI     <= AWID_int;
      // Latched Read Address signals 
      ARVALID_MI  <= ARVALID_M0;
      ARSIZE_MI   <= ARSIZE_M0;
      ARBURST_MI  <= ARBURST_M0;
      ARLOCK_MI   <= ARLOCK_M0;
      ARCACHE_MI  <= ARCACHE_M0;
      ARPROT_MI   <= ARPROT_M0;
      ARLEN_MI    <= ARLEN_M0;
      ARID_MI     <= ARID_int;
      ARADDR_MI   <= ARADDR_M0;

   end

   always @(*) begin
      // latched Write Response signals
      BREADY_MI   = BREADY_M0;

      // Latched Read Response signals
      RREADY_MI   = RREADY_M0;
   end

   // Pass AW/AR/WREADY signal from Interconnect to master top
   assign AWREADY_M0 = AWREADY_IM;
   assign ARREADY_M0 = ARREADY_IM;
   assign WREADY_M0  = WREADY_IM;

   // Pass Write response signals back to the master top
   assign BID_M0    = BID_IM;
   assign BVALID_M0 = BVALID_IM;
   assign BRESP_M0  = BRESP_IM;

   // Pass Read response signals back to the master top
   assign RID_M0    = RID_IM;
   assign RVALID_M0 = RVALID_IM;
   assign RDATA_M0  = RDATA_IM;
   assign RRESP_M0  = RRESP_IM;
   assign RLAST_M0  = RLAST_IM;

   //---------------------------------------------------------------------------
   // ID Calculations
   //---------------------------------------------------------------------------
   // Write address channel ID assignment towards the Interconnect
   assign AWID_int = {UNIQUE_MASTER_ID,AWID_M0};
   
   // Read address channel ID assignment towards the Interconnect
   assign ARID_int = {UNIQUE_MASTER_ID,ARID_M0};

   // Write data channel ID assignment towards the Interconnect
   assign WID_int  = {UNIQUE_MASTER_ID,WID_M0};

   //---------------------------------------------------------------------------
   // Write transaction logic                                                 //
   //---------------------------------------------------------------------------
   //---------------------------------------------------------------------------
   // Latch the Write address for multiple outstanding transactions
   //---------------------------------------------------------------------------
   //---------------------------------------------------------------------------
   // Write address buffer register - 4-bit register
   // This register is used to maintain the outstanding transactions to be
   // performed.
   // When there is an outstanding transaction on the write address channel, a
   // bit in the register is set.
   // The bit is reset only on receiving the response for the corresponding write
   // i.e. when the write has been serviced by the slave
   // The core supports upto 4 outstanding multiple transactions
   //---------------------------------------------------------------------------


   always @(posedge ACLK or negedge ARESETN) begin
      if(!ARESETN) begin
         awaddr_bf0_d1 <= {AXI_AWIDTH{1'b0}};
         awaddr_bf1_d1 <= {AXI_AWIDTH{1'b0}};
         awaddr_bf2_d1 <= {AXI_AWIDTH{1'b0}};
         awaddr_bf3_d1 <= {AXI_AWIDTH{1'b0}};
         araddr_bf0_d1 <= {AXI_AWIDTH{1'b0}};
         araddr_bf1_d1 <= {AXI_AWIDTH{1'b0}};
         araddr_bf2_d1 <= {AXI_AWIDTH{1'b0}};
         araddr_bf3_d1 <= {AXI_AWIDTH{1'b0}};
      end
      else begin
         awaddr_bf0_d1 <= awaddr_bf0;
         awaddr_bf1_d1 <= awaddr_bf1;
         awaddr_bf2_d1 <= awaddr_bf2;
         awaddr_bf3_d1 <= awaddr_bf3;
         araddr_bf0_d1 <= araddr_bf0;
         araddr_bf1_d1 <= araddr_bf1;
         araddr_bf2_d1 <= araddr_bf2;
         araddr_bf3_d1 <= araddr_bf3;
      end
   end

   //---------------------------------------------------------------------------
   // Register to keep track of the number of write transactions in queue
   //---------------------------------------------------------------------------
    always @(posedge ACLK or negedge ARESETN) begin
      if(!ARESETN) begin
         wreq_set <= 4'b0001;
      end
      else begin
        if(AWVALID_M0 == 1'b1 && AWREADY_IM == 1'b1 && pending_wr_req == 4'b1111) begin
           wreq_set <= wreq_set;
        end
        else if(AWVALID_M0 == 1'b1 && AWREADY_IM == 1'b1 && wreq_set[3] == 1'b1) begin
           wreq_set <= {wreq_set[2:0],1'b0};
        end
        else if(AWVALID_M0 == 1'b1 && AWREADY_IM == 1'b1 && wreq_set != 4'b1111) begin
           wreq_set <= {wreq_set[2:0],1'b1};
        end
      end
    end

   //---------------------------------------------------------------------------
   // Register to keep track of the number of write transactions complete
   //---------------------------------------------------------------------------
   always @(posedge ACLK or negedge ARESETN) begin
      if(!ARESETN) begin
         wreq_reset <= 4'b0001;
     end
      else begin
        if(BVALID_IM == 1'b1 && BREADY_MI == 1'b1 && wreq_reset[3] == 1'b1) begin
           wreq_reset <= {wreq_reset[2:0],1'b0};
        end
        else if(BVALID_IM == 1'b1 && BREADY_MI == 1'b1 && wreq_reset != 4'b1111) begin
           wreq_reset <= {wreq_reset[2:0],1'b1};
        end
      end
    end

   //---------------------------------------------------------------------------
   // Register to keep track of the number of write transactions yet to be
   // serviced
   //---------------------------------------------------------------------------
    assign pending_wr_req = wreq_set ^ wreq_reset;
 
   // Check whether there is any pending write request
   assign waddr_buf_full = (& pending_wr_req);   

   //---------------------------------------------------------------------------
   // Pass the address which is being serviced correctly (to the
   // interconnect) based on the pending write register
   // Each bit in the pending register represents the write to be serviced.
   // The logic services the current one and then moves to service the next
   // address indicated by the subsequent register bit.
   //---------------------------------------------------------------------------

   always @(*) begin
		awaddr_bf0 = awaddr_bf0_d1;
		awaddr_bf1 = awaddr_bf1_d1;
		awaddr_bf2 = awaddr_bf2_d1;
		awaddr_bf3 = awaddr_bf3_d1;
      case(pending_wr_req)
          4'b0000, 4'b0001:
          begin
              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf0 = AWADDR_M0;
              end else   begin
                awaddr_bf0 = awaddr_bf0_d1;
              end
          end
        4'b0010:    
          begin
              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf1 = AWADDR_M0;
              end else   begin
                awaddr_bf1 = awaddr_bf1_d1;
              end
          end
        4'b0011:    
          begin
              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf1 = AWADDR_M0;
              end else   begin
                awaddr_bf1 = awaddr_bf1_d1;
              end
          end
        4'b0100:
          begin

              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf2 = AWADDR_M0;
              end else   begin
                awaddr_bf2 = awaddr_bf2_d1;
              end
          end
        4'b0110:
          begin

              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf2 = AWADDR_M0;
              end else   begin
                awaddr_bf2 = awaddr_bf2_d1;
              end
          end
        4'b0111:
          begin

              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf2 = AWADDR_M0;
              end else   begin
                awaddr_bf2 = awaddr_bf2_d1;
              end
          end
        4'b1000:
          begin

              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf3 = AWADDR_M0;
              end else   begin
                awaddr_bf3 = awaddr_bf3_d1;
              end
          end
        4'b1001:
          begin

              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf0 = AWADDR_M0;
              end else   begin
                awaddr_bf0 = awaddr_bf0_d1;
              end
          end
        4'b1011:
          begin

              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf1 = AWADDR_M0;
              end else   begin
                awaddr_bf1 = awaddr_bf1_d1;
              end
          end
        4'b1100:
          begin

              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf3 = AWADDR_M0;
              end else   begin
                awaddr_bf3 = awaddr_bf3_d1;
              end
          end
        4'b1101:
          begin

              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf0 = AWADDR_M0;
              end else   begin
                awaddr_bf0 = awaddr_bf0_d1;
              end
          end
        4'b1110:
          begin

              if(AWVALID_M0 == 1'b1) begin
                awaddr_bf3 = AWADDR_M0;
              end else   begin
                awaddr_bf3 = awaddr_bf3_d1;
              end
          end
        4'b1111:  begin
           if(pending_wr_req == 4'b1111 && pending_wr_req_r == 4'b1110) begin
               awaddr_bf0 = AWADDR_M0;
           end
           else if(pending_wr_req == 4'b1111 && pending_wr_req_r == 4'b1101) begin
               awaddr_bf1 = AWADDR_M0;
           end
           else if(pending_wr_req == 4'b1111 && pending_wr_req_r == 4'b1011) begin
               awaddr_bf2 = AWADDR_M0;
           end
           else if(pending_wr_req == 4'b1111 && pending_wr_req_r == 4'b1111) begin
               awaddr_bf3 = AWADDR_M0;
           end
           else begin
		awaddr_bf0 = awaddr_bf0_d1;
		awaddr_bf1 = awaddr_bf1_d1;
		awaddr_bf2 = awaddr_bf2_d1;
		awaddr_bf3 = awaddr_bf3_d1;
           end
          
        end
       default:        begin
		awaddr_bf0 = awaddr_bf0_d1;
		awaddr_bf1 = awaddr_bf1_d1;
		awaddr_bf2 = awaddr_bf2_d1;
		awaddr_bf3 = awaddr_bf3_d1;
       end
      endcase
   end

   always @(*) begin
      awaddr_buf = awaddr_buf_r;
      case(pending_wr_req)
          4'b0000, 4'b0001:
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf0;
          end
        4'b0010:    
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf1;
          end
        4'b0011:    
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf0;
          end
        4'b0100:
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf2;
          end
        4'b0110:
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf1;
          end
        4'b0111:
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf0;
          end
        4'b1000:
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf3;
          end
        4'b1001:
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf3; //last change
                //awaddr_buf = awaddr_bf2;
          end
        4'b1011:
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf3;
          end
        4'b1100:
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf2;
          end
        4'b1101:
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf3; //last change
                //awaddr_buf = awaddr_bf1;
          end
        4'b1110:
          begin
              if(AWVALID_M0 == 1'b1)
                awaddr_buf = awaddr_bf1;
          end
        4'b1111:  begin
           if(pending_wr_req == 4'b1111 && pending_wr_req_r == 4'b1110) begin
               awaddr_buf = awaddr_bf1;
           end
           else if(pending_wr_req == 4'b1111 && pending_wr_req_r == 4'b1101) begin
               awaddr_buf = awaddr_bf2;
           end
           else if(pending_wr_req == 4'b1111 && pending_wr_req_r == 4'b1011) begin
               awaddr_buf = awaddr_bf3;
           end
           else if(pending_wr_req == 4'b1111 && pending_wr_req_r == 4'b1111) begin
               awaddr_buf = awaddr_buf_r;
           end
           else begin
               awaddr_buf = awaddr_bf0;
           end
        end
       default:        begin
           awaddr_buf = awaddr_buf_r;
       end
      endcase
   end

   //---------------------------------------------------------------------------
   // Pass the address which is being serviced correctly (to the
   // interconnect) based on the pending read register
   // Each bit in the pending register represents the read to be serviced.
   // The logic services the current one and then moves to service the next
   // address indicated by the subsequent register bit.
   //---------------------------------------------------------------------------

   always @(*) begin
      araddr_bf0 = araddr_bf0_d1;
      araddr_bf1 = araddr_bf1_d1;
      araddr_bf2 = araddr_bf2_d1;
      araddr_bf3 = araddr_bf3_d1;
      case(pending_rd_req)
          4'b0000, 4'b0001:
          begin
              if(ARVALID_M0 == 1'b1) begin
                araddr_bf0 = ARADDR_M0;
              end else   begin
                araddr_bf0 = araddr_bf0_d1;
              end
          end
        4'b0010:    
          begin
              if(ARVALID_M0 == 1'b1) begin
                araddr_bf1 = ARADDR_M0;
              end else   begin
                araddr_bf1 = araddr_bf1_d1;
              end
          end
        4'b0011:    
          begin
              if(ARVALID_M0 == 1'b1) begin
                araddr_bf1 = ARADDR_M0;
              end else   begin
                araddr_bf1 = araddr_bf1_d1;
              end
          end
        4'b0100:
          begin

              if(ARVALID_M0 == 1'b1) begin
                araddr_bf2 = ARADDR_M0;
              end else   begin
                araddr_bf2 = araddr_bf2_d1;
              end
          end
        4'b0110:
          begin

              if(ARVALID_M0 == 1'b1) begin
                araddr_bf2 = ARADDR_M0;
              end else   begin
                araddr_bf2 = araddr_bf2_d1;
              end
          end
        4'b0111:
          begin

              if(ARVALID_M0 == 1'b1) begin
                araddr_bf2 = ARADDR_M0;
              end else   begin
                araddr_bf2 = araddr_bf2_d1;
              end
          end
        4'b1000:
          begin

              if(ARVALID_M0 == 1'b1) begin
                araddr_bf3 = ARADDR_M0;
              end else   begin
                araddr_bf3 = araddr_bf3_d1;
              end
          end
        4'b1001:
          begin

              if(ARVALID_M0 == 1'b1) begin
                araddr_bf0 = ARADDR_M0;
              end else   begin
                araddr_bf0 = araddr_bf0_d1;
              end
          end
        4'b1011:
          begin

              if(ARVALID_M0 == 1'b1) begin
                araddr_bf1 = ARADDR_M0;
              end else   begin
                araddr_bf1 = araddr_bf1_d1;
              end
          end
        4'b1100:
          begin

              if(ARVALID_M0 == 1'b1) begin
                araddr_bf3 = ARADDR_M0;
              end else   begin
                araddr_bf3 = araddr_bf3_d1;
              end
          end
        4'b1101:
          begin

              if(ARVALID_M0 == 1'b1) begin
                araddr_bf0 = ARADDR_M0;
              end else   begin
                araddr_bf0 = araddr_bf0_d1;
              end
          end
        4'b1110:
          begin

              if(ARVALID_M0 == 1'b1) begin
                araddr_bf3 = ARADDR_M0;
              end else   begin
                araddr_bf3 = araddr_bf3_d1;
              end
          end
        4'b1111:  begin
           if(pending_rd_req == 4'b1111 && pending_rd_req_r == 4'b1110) begin
               araddr_bf0 = ARADDR_M0;
           end
           else if(pending_rd_req == 4'b1111 && pending_rd_req_r == 4'b1101) begin
               araddr_bf1 = ARADDR_M0;
           end
           else if(pending_rd_req == 4'b1111 && pending_rd_req_r == 4'b1011) begin
               araddr_bf2 = ARADDR_M0;
           end
           else if(pending_rd_req == 4'b1111 && pending_rd_req_r == 4'b1111) begin
               araddr_bf3 = ARADDR_M0;
           end
           else begin
		araddr_bf0 = araddr_bf0_d1;
		araddr_bf1 = araddr_bf1_d1;
		araddr_bf2 = araddr_bf2_d1;
		araddr_bf3 = araddr_bf3_d1;
           end
          
        end
       default:        begin
		araddr_bf0 = araddr_bf0_d1;
		araddr_bf1 = araddr_bf1_d1;
		araddr_bf2 = araddr_bf2_d1;
		araddr_bf3 = araddr_bf3_d1;
       end
      endcase
   end

   always @(*) begin
                araddr_buf = araddr_buf_r;
      case(pending_rd_req)
          4'b0000, 4'b0001:
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf0;
          end
        4'b0010:    
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf1;
          end
        4'b0011:    
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf0;
          end
        4'b0100:
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf2;
          end
        4'b0110:
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf1;
          end
        4'b0111:
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf0;
          end
        4'b1000:
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf3;
          end
        4'b1001:
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf3;  // last change
               // araddr_buf = araddr_bf2;
          end
        4'b1011:
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf3;
          end
        4'b1100:
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf2;
          end
        4'b1101:
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf3;  // last change
               // araddr_buf = araddr_bf1;
          end
        4'b1110:
          begin
              if(ARVALID_M0 == 1'b1)
                araddr_buf = araddr_bf1;
          end
        4'b1111:  begin
           if(pending_rd_req == 4'b1111 && pending_rd_req_r == 4'b1110) begin
               araddr_buf = araddr_bf1;
           end
           else if(pending_rd_req == 4'b1111 && pending_rd_req_r == 4'b1101) begin
               araddr_buf = araddr_bf2;
           end
           else if(pending_rd_req == 4'b1111 && pending_rd_req_r == 4'b1011) begin
               araddr_buf = araddr_bf3;
           end
           else if(pending_rd_req == 4'b1111 && pending_rd_req_r == 4'b1111) begin
               araddr_buf = araddr_buf_r;
           end
           else begin
               araddr_buf = araddr_bf0;
           end
        end
       default:        begin
           araddr_buf = araddr_buf_r;
       end
      endcase
   end
 
   //---------------------------------------------------------------------------
   // Register the signals
   //---------------------------------------------------------------------------
    always @(posedge ACLK or negedge ARESETN) begin
      if(!ARESETN) begin
         awaddr_buf_r <= {AXI_AWIDTH{1'b0}};
         araddr_buf_r <= {AXI_AWIDTH{1'b0}};
         pending_wr_req_r  <= 4'b0000;
         pending_rd_req_r  <= 4'b0000;
      end
      else begin
         awaddr_buf_r <= awaddr_buf;
         araddr_buf_r <= araddr_buf;
         pending_wr_req_r  <= pending_wr_req;
         pending_rd_req_r  <= pending_rd_req;
      end
   end

   //---------------------------------------------------------------------------
   // Latch the Read address for multiple outstanding transactions
   //---------------------------------------------------------------------------

 
   //---------------------------------------------------------------------------
   // Register to keep track of the number of read transactions queued
   //---------------------------------------------------------------------------

   always @(posedge ACLK or negedge ARESETN) begin
      if(!ARESETN) begin
         rreq_set <= 4'b0001;
      end
      else begin
       if(ARVALID_M0 == 1'b1 && ARREADY_IM == 1'b1 && pending_rd_req == 4'b1111) begin
           rreq_set <= rreq_set;
       end
       else if(ARVALID_M0 == 1'b1 && ARREADY_IM == 1'b1 && rreq_set[3] == 1'b1) begin
           rreq_set <= {rreq_set[2:0],1'b0};
       end
       else if(ARVALID_M0 == 1'b1 && ARREADY_IM == 1'b1 && rreq_set != 4'b1111) begin
           rreq_set <= {rreq_set[2:0],1'b1};
        end
      end
    end


   //---------------------------------------------------------------------------
   // Register to keep track of the number of read transactions complete
   //---------------------------------------------------------------------------
   always @(posedge ACLK or negedge ARESETN) begin
      if(!ARESETN) begin
         rreq_reset <= 4'b0001;
      end
      else begin
        if(RVALID_IM == 1'b1 && RREADY_MI == 1'b1 && RLAST_IM == 1'b1 && 
            rreq_reset[3] == 1'b1) begin
           rreq_reset <= {rreq_reset[2:0],1'b0};
        end
        else if(RVALID_IM == 1'b1 && RREADY_MI == 1'b1 && RLAST_IM == 1'b1 && 
            rreq_reset != 4'b1111) begin
           rreq_reset <= {rreq_reset[2:0],1'b1};
        end
      end
    end

   //---------------------------------------------------------------------------
   // Register to keep track of the number of read transactions yet to be
   // serviced
   //---------------------------------------------------------------------------
    assign pending_rd_req = rreq_set ^ rreq_reset;

   // Check whether there is any pending read request
   assign raddr_buf_full = (& pending_rd_req);   

   
endmodule // master_stage

   /////////////////////////////////////////////////////////////////////////////
   //                               End - of - Code                           //
   /////////////////////////////////////////////////////////////////////////////
