module recv_credit_flow_ctrl
  (
   input 	CLK,
   input 	RST,
   input [2:0] 	CONFIG_MAX_READ_REQUEST_SIZE, // Maximum read payload: 000=128B, 001=256B, 010=512B, 011=1024B, 100=2048B, 101=4096B
   input [11:0] CONFIG_MAX_CPL_DATA, // Receive credit limit for data
   input [7:0] 	CONFIG_MAX_CPL_HDR, // Receive credit limit for headers
   input 	CONFIG_CPL_BOUNDARY_SEL, // Read completion boundary (0=64 bytes, 1=128 bytes)w
   input 	RX_ENG_RD_DONE, // Read completed
   input 	TX_ENG_RD_REQ_SENT, // Read completion request issued
   output 	RXBUF_SPACE_AVAIL // High if enough read completion credits exist to make a read completion request
   );

   reg 		rCreditAvail=0;
   reg 		rCplDAvail=0;
   reg 		rCplHAvail=0;
   reg [12:0] 	rMaxRecv=0;
   reg [11:0] 	rCplDAmt=0;
   reg [7:0] 	rCplHAmt=0;
   reg [11:0] 	rCplD=0;
   reg [7:0] 	rCplH=0;

   assign RXBUF_SPACE_AVAIL = rCreditAvail;

   // Determine the completions required for a max read completion request.
   always @(posedge CLK) begin
      rMaxRecv <= #1 (13'd128<<CONFIG_MAX_READ_REQUEST_SIZE);
      rCplHAmt <= #1 (rMaxRecv>>({2'b11, CONFIG_CPL_BOUNDARY_SEL}));
      rCplDAmt <= #1 (rMaxRecv>>4);
      rCplHAvail <= #1 (rCplH <= CONFIG_MAX_CPL_HDR);
      rCplDAvail <= #1 (rCplD <= CONFIG_MAX_CPL_DATA);
      rCreditAvail <= #1 (rCplHAvail & rCplDAvail);
   end

   // Count the number of outstanding read completion requests.
   always @ (posedge CLK) begin
      if (RST) begin
	 rCplH <= #1 0;
	 rCplD <= #1 0;
      end
      else if (RX_ENG_RD_DONE & TX_ENG_RD_REQ_SENT) begin
	 rCplH <= #1 rCplH;
	 rCplD <= #1 rCplD;
      end
      else if (TX_ENG_RD_REQ_SENT) begin
	 rCplH <= #1 rCplH + rCplHAmt;
	 rCplD <= #1 rCplD + rCplDAmt;
      end
      else if (RX_ENG_RD_DONE) begin
	 rCplH <= #1 rCplH - rCplHAmt;
	 rCplD <= #1 rCplD - rCplDAmt;
      end
   end

endmodule