anchor.diff:     provisos( Mul#(TDiv#(busWidth, 8), 8, busWidth)
   	    ,Add#(1, a__, numServers)
   	    ,Add#(busWidth, 0, userWidth)
  -	    ,Add#(b__, TLog#(numServers), TAdd#(1, TLog#(TMul#(cmdQDepth,numServers))))
  -	    ,Add#(c__, TLog#(numServers), TLog#(TMul#(cmdQDepth, numServers)))
  -	    ,Add#(d__, TLog#(numServers), MemTagSize)
  -	    );
  +	    ,FunnelPipesPipelined#(1, numServers, MemTypes::MemData#(userWidth), 2)
  +	    ,Pipe::FunnelPipesPipelined#(1, numServers, MemTypes::MemRequest, 2)
  +	    ,Add#(b__, TLog#(numServers), 6)
  +      	    );
      let rv <- mkMemReadEngineBuff(valueOf(cmdQDepth) * valueOf(TExp#(BurstLenSize)));
      return rv;
   endmodule
  
positive.code:    let reset <- exposeCurrentReset();
  
     Integer bufferSizeBeats = bufferSizeBytes/valueOf(busWidthBytes);
     Vector#(numServers, Reg#(Bool))          clientInFlight <- replicateM(mkReg(False));
     Vector#(numServers, ConfigCounter#(16))  clientAvail <- replicateM(mkConfigCounter(fromInteger(bufferSizeBeats)));
     Vector#(numServers, Reg#(MemengineCmd))  clientCommand <- replicateM(mkReg(unpack(0)));
  `ifdef USE_DUAL_CLOCK_FIFOF
     Vector#(numServers, FIFOF#(MemDataF#(userWidth))) clientDataFifo <- replicateM(mkDualClockBramFIFOF(clock, reset, clock, reset));
  `else
     Vector#(numServers, FIFOF#(MemDataF#(userWidth))) clientDataFifo <- replicateM(mkSizedBRAMFIFOF(bufferSizeBeats));
  `endif
     Vector#(numServers, FIFO#(MemengineCmd)) clientRequest <- replicateM(mkFIFO());
     Vector#(numServers, Reg#(Bit#(32)))      clientLen <- replicateM(mkReg(unpack(0)));
     Vector#(numServers, Reg#(Bit#(32)))      clientBase <- replicateM(mkReg(unpack(0)));
     Vector#(numServers, Reg#(NextReq))       clientNext <- replicateM(mkReg(unpack(0)));
     Vector#(numServers, Count#(Bit#(32)))    clientCycles <- replicateM(mkCount(0));
     Vector#(numServers, FIFOF#(MemRequestCycles)) clientCyclesFifo <- replicateM(mkFIFOF());
     Vector#(numServers, FIFOF#(ServerRequest#(serverIdxSz))) clientSReq <- replicateM(mkSizedFIFOF(1));
     
     Vector#(numServers, FIFO#(Tuple3#(Bool,Bool,Bit#(BurstLenSize)))) serverCheckAvail <- replicateM(mkSizedFIFO(1));
     FIFO#(ServerRequest#(serverIdxSz))       serverRequest <- mkSizedFIFO(valueOf(cmdQDepth));
     FIFO#(Tuple3#(Bit#(8),Bit#(serverIdxSz),Bool)) serverProcessing <- mkSizedFIFO(valueOf(cmdQDepth));
     FIFOF#(MemData#(busWidth))                       serverDataFifo <- mkFIFOF;
  
     Reg#(Bit#(8))                    respCnt <- mkReg(0);
     Reg#(Bit#(32)) counter <- mkReg(0);
  
     mkFunnelNodeRR(map(toPipeOut, clientSReq), valueOf(numServers), toPut(serverRequest));
  
     rule incCounter;
        counter <= counter + 1;
     endrule
           
     for (Integer idx = 0; idx < valueOf(numServers); idx = idx + 1) begin
        rule rule_startNew if (!clientInFlight[idx]);
  	 let cmd <- toGet(clientRequest[idx]).get();
  	 clientInFlight[idx] <= True;
  	 clientCommand[idx] <= cmd;
           clientLen[idx] <= cmd.len - extend(cmd.burstLen);
           clientBase[idx] <= cmd.base;
           clientNext[idx] <= getNext(cmd.len, cmd.burstLen);
  	 clientCycles[idx] <= 0;
  	 if (verbose) $display("mkMemReadEngineBuff::%d rule_startNew %d %d", counter, idx, clientAvail[idx].read);
        endrule
        rule rule_cycles;
  	 clientCycles[idx].incr(1);
        endrule
        rule rule_checkAvail if (clientInFlight[idx]);
           let cmd_len = clientNext[idx].len;
           let last_burst = clientNext[idx].last;
           let cond0 <- clientAvail[idx].maybeDecrement(unpack(extend(cmd_len>>beatShift)));
           serverCheckAvail[idx].enq(tuple3(cond0,last_burst,cmd_len));
           if (verbose) $display("mkMemReadEngineBuff::%d rule_checkAvail avail[%d] %d burstLen %d cond0 %d last_burst %d", counter, idx, clientAvail[idx].read(), cmd_len>>beatShift, cond0, last_burst);
        endrule
  
        rule rule_requestServer if (clientInFlight[idx]);
           match {.cond0,.last_burst,.cmd_len} <- toGet(serverCheckAvail[idx]).get;
           if  (cond0) begin
  	    if (verbose) $display("mkMemReadEngineBuff::%d rule_requestServer clientLen %d idx %d cond0 %d last_burst %d", counter, clientLen[idx], idx, cond0, last_burst);
  	    clientSReq[idx].enq(ServerRequest{
                   idx:fromInteger(idx),sglId:clientCommand[idx].sglId,base:clientBase[idx],
                   tag:clientCommand[idx].tag,last:last_burst,burstLen:cmd_len});
              clientBase[idx] <= clientBase[idx] + extend(cmd_len);
              clientLen[idx] <= clientLen[idx] - extend(cmd_len);
              clientNext[idx] <= getNext(clientLen[idx], clientCommand[idx].burstLen);
  	    if (last_burst) begin
  	       if (verbose) $display("mkMemReadEngineBuff::%d rule_requestServer last_burst %d", counter, last_burst);
  	       clientInFlight[idx] <= False;
  `ifdef MEMENGINE_REQUEST_CYCLES
  	       $display("clientCycles[%d] = %d", idx, clientCycles[idx]);
  	       clientCyclesFifo[idx].enq(MemRequestCycles { tag:clientCommand[idx].tag, cycles: clientCycles[idx] });
  `endif
  	    end
           end
        endrule
     end
     
     rule read_data_rule;
        let d <- toGet(serverDataFifo).get();
        match {.rc, .idx, .last_burst} = serverProcessing.first;
        let new_respCnt = respCnt+1;
        let l = False;
        if (verbose) $display("mkMemReadEngineBuff::%d data %h new_respCnt %d rc %d last_burst %d idx %d clientInFlight %d eob %d", counter, d.data, new_respCnt, rc, last_burst, idx, clientInFlight[idx], d.last);
        if (new_respCnt == rc) begin
  	 respCnt <= 0;
  	 serverProcessing.deq;
  
negative.code:    Bit#(BurstLenSize) burstLen;
  } ServerRequest#(numeric type indexSize) deriving (Bits, Eq);
  
  interface MemReadChannel#(numeric type busWidth, numeric type userWidth, numeric type cmdQDepth);
     interface PipeOut#(MemRequest)        readReq;
     interface PipeIn#(MemData#(busWidth)) readData;
     interface MemReadEngineServer#(userWidth) readServer;
  endinterface
  
  module mkMemReadChannel#(Integer bufferSizeBytes, Integer channelNumber) (MemReadChannel#(busWidth, userWidth, cmdQDepth))
     provisos (Div#(busWidth,8,busWidthBytes),
  	     Mul#(busWidthBytes,8,busWidth),
  	     Log#(busWidthBytes,beatShift),
  	     Log#(cmdQDepth,logCmdQDepth),
  	     Log#(cmdQDepth, cmdBuffAddrSz),
  	     Log#(1, serverIdxSz),
  	     Add#(busWidth, 0, userWidth),
  	     Add#(1,logCmdQDepth, outCntSz),
  	     Add#(1, c__, 1),
  	     Add#(b__, TLog#(1), cmdBuffAddrSz),
  	     Add#(e__, TLog#(1), TAdd#(1, cmdBuffAddrSz)),
  	     Add#(a__, serverIdxSz, cmdBuffAddrSz),
  	     Min#(2,TLog#(1),bpc),
  	     Add#(d__, TLog#(1), TAdd#(1, serverIdxSz)),
  	     Add#(f__, serverIdxSz, MemTagSize));
     let verbose = False;
     let beatShift = fromInteger(valueOf(beatShift));
  