module axi_descriptor #
   (
      parameter integer DESCRIPTOR_WIDTH	= 128,
      parameter integer DESCRIPTOR_LENGTH	= 1
   )
	(
      axi4l_intf.slave axi,
      input [DESCRIPTOR_WIDTH-1:0] descriptor_list[DESCRIPTOR_LENGTH]
   );
   
   // incoming pipeline of write address
   reg awaddr_valid;
   reg [axi.AXI_ADDR_WIDTH-1:0] awaddr;

   // incoming pipeline of write data
   reg wdata_valid;
   reg [((axi.AXI_DATA_WIDTH/8)-1):0] wstrb;
   reg [axi.AXI_DATA_WIDTH-1:0] wdata;
   
   // incoming pipeline of read address
   reg araddr_valid;
   reg [axi.AXI_ADDR_WIDTH:0] araddr;
   
   // outgoing pipeline of read data
   reg rvalid;
   reg [axi.AXI_DATA_WIDTH-1:0] rdata;
      
   integer descriptor_index1, descriptor_index2;      
  
   // ready while data hasn't been latched and still waiting
   // for acknowledgement to our response
   assign axi.awready = !awaddr_valid && !axi.bvalid;
   assign axi.wready = !wdata_valid && !axi.bvalid;
   
	always @( posedge axi.clk )
   begin
      if ( axi.resetn == 1'b0 ) begin
         awaddr_valid <= 1'b0; 
         awaddr <= 'b0; 
         wdata_valid <= 1'b0;
         wstrb <= 'b0;
         wdata <= 'b0;    
         axi.bvalid <= 1'b0;
         axi.bresp  <= 2'b0;                       
	   end
	   else begin   
         // latch awaddr and valid signal
         if (axi.awready && axi.awvalid) begin 
            awaddr_valid <= 1'b1;   
            awaddr <= axi.awaddr; 
         end
         
         // latch wirte data and valid signal
         if (axi.wready && axi.wvalid) begin 
            wdata_valid <= 1'b1;   
            wstrb <= axi.wstrb;
            wdata <= axi.wdata;    
         end    
         
         // clear valids when both high;
         // data needs to be consumed on this same condition
         if (awaddr_valid && wdata_valid && !axi.bvalid) begin
             awaddr_valid <= 1'b0; 
             wdata_valid <= 1'b0;
             
             axi.bvalid <= 1'b1;
             axi.bresp  <= 2'b0; // 'OKAY' response          
         end  
         
         // clear bvalid when it has been acknowledged
         if (axi.bvalid && axi.bready) begin
            axi.bvalid <= 1'b0;
         end
      end
	end
	
	// ready while data hasn't been latched and still waiting
   // for acknowledgement to our response
	assign axi.arready = !araddr_valid && !axi.rvalid;
	   
	always @( posedge axi.clk )
   begin
      if ( axi.resetn == 1'b0 ) begin
         araddr_valid <= 1'b0; 
         araddr <= 'b0; 
         axi.rvalid <= 1'b0;
         axi.rresp  <= 2'b0;                       
         axi.rdata <= 'b0;    
	   end
	   else begin   
         // latch araddr and valid signal	   
         if (axi.arready && axi.arvalid) begin 
            araddr_valid <= 1'b1;   
            araddr <= axi.araddr; 
         end
                  
         // if address is valid and rdata has been latched;
         // set axi bus rdata and valid signal
         if (araddr_valid && rvalid && !axi.rvalid) begin
             araddr_valid <= 1'b0; 
             
             axi.rvalid <= 1'b1;
             axi.rresp  <= 2'b0; // 'OKAY' response     
             axi.rdata <= rdata;     
         end  
         
         // clear rvalid when it has been acknowledged
         if (axi.rvalid && axi.rready) begin
            axi.rvalid <= 1'b0;
         end
      end
	end
	
	always @( posedge axi.clk )
   begin
      if ( axi.resetn == 1'b0 ) begin
         rvalid <= 1'b0;                      
         rdata <= 'b0; 
	   end
	   else begin   

         // by default rvalid is low; unless read address is valid;
         // latch appropriate data and set valid signal
         rvalid <= 1'b0;
         rdata <= 'b0; 
         if (araddr_valid) begin
            for ( descriptor_index2 = 0; descriptor_index2 < DESCRIPTOR_LENGTH; descriptor_index2 = descriptor_index2+1 ) begin
               for ( descriptor_index1 = 0; descriptor_index1 < (DESCRIPTOR_WIDTH/32); descriptor_index1 = descriptor_index1+1 ) begin
                  if ( araddr[7:0] == (((descriptor_index2 * (DESCRIPTOR_WIDTH/32)) + descriptor_index1) * 4) ) begin
                     rdata <= descriptor_list[descriptor_index2][descriptor_index1*32 +: 32];
                  end
               end
            end      
            rvalid <= 1'b1;
         end               
      end
             
   end	
	


endmodule
