first cut of attaching to ps7 (not compiled)

// bsv libraries
//import SpecialFIFOs::*;
//import Vector::*;
//import StmtFSM::*;
//import FIFO::*;
//import Connectable::*;

// portz libraries
//import AxiMasterSlave::*;
//import Directory::*;
//import CtrlMux::*;
//import Portal::*;
//import Leds::*;
import Top::*;
import PS7::*;

module mkZynqTop(AxiTop);
    let axiTop <- mkAxiTop();
    PS7#(4, 32, 4, 32, 64/*gpio_width*/, 12, 54) ps7 <- mkPS7(4, 32, 4, 32, 64/*gpio_width*/, 12, 54);
        //.M_AXI_GP0_ACLK(processing_system7_1_fclk_clk0),
        //.S_AXI_HP0_ACLK(processing_system7_1_fclk_clk0),

    rule m_ar_rule; //.M_AXI_GP0_ARREADY(ctrl_arready), .M_AXI_GP0_ARVALID(ctrl_arvalid),
        let m_ar = ps7.m_axi_gp[0].req_ar.get();
            //req_ar lock; //req_ar qos;
        //.M_AXI_GP0_ARLOCK(ctrl_arlock),
        ctrl.read.readAddr(m_ar.addr, m_ar.len, m_ar.size, m_ar.burst, m_ar.prot, m_ar.cache, m_ar.id);
    endrule

    rule m_aw_rule; //.M_AXI_GP0_AWREADY(ctrl_awready), .M_AXI_GP0_AWVALID(ctrl_awvalid),
        let m_aw = ps7.m_axi_gp[0].req_aw.get();
            //req_aw lock; //req_aw qos;
            //.M_AXI_GP0_AWLOCK(ctrl_awlock),
        ctrl.write.writeAddr(m_aw.addr, m_aw.len, m_aw.size, m_aw.burst, m_aw.prot, m_aw.cache, m_aw.id);
    endrule

    rule m_arespb_rule; //.M_AXI_GP0_BREADY(ctrl_bready), .M_AXI_GP0_BVALID(ctrl_bvalid),
        AxiResp#(12) m_arespb;
        m_arespb.id = ctrl.write.bid();
        m_arespb.resp = ctrl.write.writeResponse();
        ps7.m_axi_gp[0].resp_b.put(m_arespb);
    endrule

    rule m_arespr_rule; //.M_AXI_GP0_RREADY(ctrl_rready), .M_AXI_GP0_RVALID(ctrl_rvalid),
        AxiRead#(32, 12) m_arespr;
        m_arespr.r.id = ctrl.read.rid();
        m_arespr.r.resp = ??; //.M_AXI_GP0_RRESP(ctrl_rresp),
        m_arespr.rd.data = ctrl.read.readData();
        m_arespr.rd.last = ctrl.read.last();
        ps7.m_axi_gp[0].resp_read.put(m_arespr);
    endrule

    rule m_arespw_rule; //.M_AXI_GP0_WREADY(ctrl_wready), .M_AXI_GP0_WVALID(ctrl_wvalid),
        let m_arespw = ps7.m_axi_gp[0].resp_write.get();
        ctrl.write.writeData(m_arespw.wd.data, m_arespw.wstrb, m_arespw.wd.last, m_aresp.wid);
    endrule

    rule s_areqr_rule; //.S_AXI_HP0_ARREADY(m_axi_arready), .S_AXI_HP0_ARVALID(m_axi_arvalid),
        AxiREQ#(12) s_areqr;
        //.S_AXI_HP0_ARLOCK .S_AXI_HP0_ARQOS .S_AXI_HP0_AWLOCK .S_AXI_HP0_AWQOS
        s_areqr.addr = m_axi.read.readAddr();
        s_areqr.burst = m_axi.read.readBurstType();
        s_areqr.cache = m_axi.read.readBurstCache();
        s_areqr.id = m_axi.read.readId();
        s_areqr.len = m_axi.read.readBurstLen();
        s_areqr.prot = m_axi.read.readBurstProt();
        s_areqr.size = m_axi.read.readBurstWidth();
        ps7.s_axi_hp[0].req_ar(s_areqr);
    endrule

    rule s_areqw_rule; //.S_AXI_HP0_AWREADY(m_axi_awready), .S_AXI_HP0_AWVALID(m_axi_awvalid),
        AxiREQ#(12) s_areqw;
        s_areqw.addr = m_axi.write.writeAddr();
        s_areqw.burst = m_axi.write.writeBurstType();
        s_areqw.cache = m_axi.write.writeBurstCache();
        s_areqw.id = m_axi.write.writeId();
        s_areqw.len = m_axi.write.writeBurstLen();
        s_areqw.prot = m_axi.write.writeBurstProt();
        s_areqw.size = m_axi.write.writeBurstWidth();
        ps7.s_axi_hp[0].req_ar(s_areqr);
    endrule

    rule s_arespb_rule; //.S_AXI_HP0_BREADY(m_axi_bready), .S_AXI_HP0_BVALID(m_axi_bvalid),
        let s_arespb = ps7.s_axi_hp[0].resp_b.get();
        m_axi.write.writeResponse(s_arespb.resp, s_arespb.id);
    endrule

    rule s_arespr_rule; //.S_AXI_HP0_RREADY(m_axi_rready), .S_AXI_HP0_RVALID(m_axi_rvalid),
        let s_arespr = ps7.s_axi_hp[0].resp_read.get();
        m_axi.read.readData(s_arespr.rd.data, s_arespr.r.resp, s_arespr.rd.last, s_arespr.r.id);
    endrule

    rule s_arespw_rule; //.S_AXI_HP0_WREADY(m_axi_wready), .S_AXI_HP0_WVALID(m_axi_wvalid),
        s_arespw.wid = m_axi.write.writeWid();
        //??s_arespw.wd.data = m_axi.write.writeWid(); //.m_axi_write_writeData(m_axi_wdata_wire),
        //.S_AXI_HP0_WDATA(m_axi_wdata),
        s_arespw.wd.last = m_axi.write.writeLastDataBeat();
        s_arespw.wstrb = m_axi.write.writeDataByteEnable();
        ps7.s_axi_hp[0].resp_write(s_arespw);
    endrule

        //.DDR_Addr(DDR_Addr[14:0]), .DDR_BankAddr(DDR_BankAddr[2:0]),
        //.DDR_CAS_n(DDR_CAS_n), .DDR_CKE(DDR_CKE), .DDR_CS_n(DDR_CS_n), .DDR_Clk(DDR_Clk_p),
        //.DDR_Clk_n(DDR_Clk_n), .DDR_DM(DDR_DM[3:0]), .DDR_DQ(DDR_DQ[31:0]),
        //.DDR_DQS(DDR_DQS_p[3:0]), .DDR_DQS_n(DDR_DQS_n[3:0]), .DDR_DRSTB(DDR_DRSTB),
        //.DDR_ODT(DDR_ODT), .DDR_RAS_n(DDR_RAS_n),
        //.DDR_VRN(FIXED_IO_ddr_vrn), .DDR_VRP(FIXED_IO_ddr_vrp), .DDR_WEB(DDR_WEB),
        //.FCLK_CLK0(processing_system7_1_fclk_clk0),
        //.FCLK_CLK1(processing_system7_1_fclk_clk1),
        //.FCLK_CLK2(processing_system7_1_fclk_clk2),
        //.FCLK_CLK3(processing_system7_1_fclk_clk3),
        //.FCLK_RESET0_N(processing_system7_1_fclk_reset0_n),
        //.IRQ_F2P(irq_f2p),
        //.MIO(FIXED_IO_mio[53:0]),
        //.PS_PORB(FIXED_IO_ps_porb),
        //.PS_SRSTB(FIXED_IO_ps_srstb),
        //.PS_CLK(FIXED_IO_ps_clk));
   return axiTop;
endmodule : mkZynqTop

// bsv libraries
//import SpecialFIFOs::*;
//import Vector::*;
//import StmtFSM::*;
//import FIFO::*;
//import Connectable::*;

// portz libraries
//import AxiMasterSlave::*;
//import Directory::*;
//import CtrlMux::*;
//import Portal::*;
//import Leds::*;
import Top::*;
import PS7::*;

module mkZynqTop(AxiTop);
   let axiTop <- mkAxiTop();
//PS7#(4, 32, 4, 32, 64/*gpio_width*/, 12, 54) ps7 <- mkPS7(4, 32, 4, 32, 64/*gpio_width*/, 12, 54);
   return axiTop;
endmodule : mkZynqTop


forgot to include the call to selectMMUPort

// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import FIFO::*;
import Vector::*;
import List::*;
import GetPut::*;
import ClientServer::*;
import Assert::*;
import StmtFSM::*;
import SpecialFIFOs::*;
import Connectable::*;
import HostInterface::*;
import MemTypes::*;
import ConnectalMemory::*;
import MMU::*;
import MemServerInternal::*;

interface MemServer#(numeric type addrWidth, numeric type busWidth, numeric type nMasters);
   interface MemServerRequest request;
   interface Vector#(nMasters,PhysMemMaster#(addrWidth, busWidth)) masters;
endinterface

interface MemServerWithMMU#(numeric type addrWidth, numeric type busWidth, numeric type nMasters);
   interface MemServerRequest memServerRequest;
   interface Vector#(nMasters,PhysMemMaster#(addrWidth, busWidth)) masters;
   interface MMURequest mmuRequest;
endinterface

interface MemServerRead#(numeric type addrWidth, numeric type busWidth, numeric type numClients, numeric type numServers);
   interface MemServerRequest request;
   interface Vector#(numClients, PhysMemReadClient#(addrWidth,busWidth)) clients;
   interface Vector#(numServers, MemReadServer#(busWidth)) servers;
endinterface

interface MemServerWrite#(numeric type addrWidth, numeric type busWidth, numeric type numClients, numeric type numServers);
   interface MemServerRequest request;
   interface Vector#(numClients, PhysMemWriteClient#(addrWidth,busWidth)) clients;
   interface Vector#(numServers, MemWriteServer#(busWidth)) servers;
endinterface

typedef struct {
   DmaErrorType errorType;
   Bit#(32) pref;
   } DmaError deriving (Bits);

module mkMemServer#(Vector#(numReadClients, MemReadClient#(busWidth)) readClients,
		    Vector#(numWriteClients, MemWriteClient#(busWidth)) writeClients,
		    Vector#(numMMUs,MMU#(addrWidth)) mmus,
		    MemServerIndication indication)
   (MemServer#(addrWidth, busWidth, nMasters))
   provisos(Mul#(TDiv#(numWriteClients, nMasters),nMasters,nws)
	    ,Mul#(TDiv#(numReadClients, nMasters),nMasters,nrs)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), d__, 8)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), e__, BurstLenSize)
	    ,Add#(c__, addrWidth, 64)
	    ,Add#(numWriteClients, a__, nws)
	    ,Add#(numReadClients, b__, nrs)
	    );

   MemServerRead#(addrWidth,busWidth,nMasters,nrs)  reader <- mkMemServerRead(indication, mmus);
   MemServerWrite#(addrWidth,busWidth,nMasters,nws) writer <- mkMemServerWrite(indication, mmus);

   zipWithM(mkConnection,readClients,take(reader.servers));
   zipWithM(mkConnection,writeClients,take(writer.servers));

   function PhysMemMaster#(addrWidth,busWidth) mkm(Integer i) = (interface PhysMemMaster#(addrWidth,busWidth);
		     interface PhysMemReadClient read_client = reader.clients[i];
		     interface PhysMemWriteClient write_client = writer.clients[i];
		  endinterface);

   interface MemServerRequest request;
      method Action setTileState(TileControl tc);
	 reader.request.setTileState(tc);
	 writer.request.setTileState(tc);
      endmethod
      method Action stateDbg(ChannelType rc);
	 if (rc == ChannelType_Read)
	    reader.request.stateDbg(rc);
	 else
	    writer.request.stateDbg(rc);
      endmethod
      method Action memoryTraffic(ChannelType rc);
	 if (rc == ChannelType_Read)
	    reader.request.memoryTraffic(rc);
	 else
	    writer.request.memoryTraffic(rc);
      endmethod
      method Action addrTrans(Bit#(32) pointer, Bit#(32) offset);
	 writer.request.addrTrans(pointer,offset);
      endmethod
   endinterface
   interface masters = map(mkm,genVector);
endmodule

module mkMemServerRead#(MemServerIndication indication,
			Vector#(numMMUs,MMU#(addrWidth)) mmus)
   (MemServerRead#(addrWidth, busWidth, numClients, numServers))
   provisos(Mul#(nrc, numClients, numServers)
	    ,Add#(a__, addrWidth, 64)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), b__, 8)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), c__, BurstLenSize)
	    );

   FIFO#(Bit#(32))   addrReqFifo <- mkFIFO;
   Reg#(Bit#(8)) dbgPtr <- mkReg(0);
   Reg#(Bit#(8)) trafficPtr <- mkReg(0);
   Reg#(Bit#(64)) trafficAccum <- mkReg(0);

   function Server#(AddrTransRequest,Bit#(addrWidth)) selectMMUPort(Integer i);
      return mmus[i].addr[0];
   endfunction
   Vector#(numMMUs,ArbitratedMMU#(addrWidth,numClients)) mmu_servers <- mapM(mkArbitratedMMU,map(selectMMUPort,genVector));
   Vector#(numClients,MemReadInternal#(addrWidth,busWidth,MemServerTags,nrc)) readers;
   Vector#(numClients, PhysMemReadClient#(addrWidth,busWidth)) read_clients;
   Vector#(numServers, MemReadServer#(busWidth)) read_servers;

   for(Integer i = 0; i < valueOf(numClients); i = i+1) begin
      Vector#(numMMUs,Server#(AddrTransRequest,Bit#(addrWidth))) ss;
      for(Integer j = 0; j < valueOf(numMMUs); j=j+1)
	 ss[j] = mmu_servers[j].servers[i];
      readers[i] <- mkMemReadInternal(indication,ss);
      read_clients[i] = readers[i].client;
      for(Integer j = 0; j < valueOf(nrc); j=j+1)
	 read_servers[i*valueOf(nrc)+j] = readers[i].servers[j];
   end

   rule mmuEntry;
      addrReqFifo.deq;
      let physAddr <- mmus[addrReqFifo.first[31:16]].addr[0].response.get;
      indication.addrResponse(zeroExtend(physAddr));
   endrule

   Stmt dbgStmt =
   seq
      for(dbgPtr <= 0; dbgPtr < fromInteger(valueOf(numClients)); dbgPtr <= dbgPtr+1)
	 (action
	     let rv <- readers[dbgPtr].dbg.dbg;
	     indication.reportStateDbg(rv);
	  endaction);
   endseq;
   FSM dbgFSM <- mkFSM(dbgStmt);

   Stmt trafficStmt =
   seq
      trafficAccum <= 0;
      for(trafficPtr <= 0; trafficPtr < fromInteger(valueOf(numClients)); trafficPtr <= trafficPtr+1)
	 (action
	     let rv <- readers[trafficPtr].dbg.getMemoryTraffic();
	     trafficAccum <= trafficAccum + rv;
	  endaction);
      indication.reportMemoryTraffic(trafficAccum);
   endseq;
   FSM trafficFSM <- mkFSM(trafficStmt);

   interface servers = read_servers;
   interface clients = read_clients;
   interface MemServerRequest request;
      method Action setTileState(TileControl tc);
	 for(Integer i = 0; i < valueOf(numClients); i=i+1)
	    readers[i].tileControl.put(tc);
      endmethod
      method Action stateDbg(ChannelType rc);
	 if (rc == ChannelType_Read)
	    dbgFSM.start;
      endmethod
      method Action memoryTraffic(ChannelType rc);
	 if (rc == ChannelType_Read)
	    trafficFSM.start;
      endmethod
      method Action addrTrans(Bit#(32) pointer, Bit#(32) offset);
	 addrReqFifo.enq(pointer);
	 mmus[pointer[31:16]].addr[0].request.put(AddrTransRequest{id:truncate(pointer), off:extend(offset)});
      endmethod
   endinterface
endmodule

module mkMemServerWrite#(MemServerIndication indication,
		     Vector#(numMMUs,MMU#(addrWidth)) mmus)
   (MemServerWrite#(addrWidth, busWidth, numClients, numServers))
   provisos(Mul#(nwc, numClients, numServers)
	    ,Add#(a__, addrWidth, 64)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), b__, 8)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), c__, BurstLenSize)
	    );

   FIFO#(Bit#(32))   addrReqFifo <- mkFIFO;
   Reg#(Bit#(8)) dbgPtr <- mkReg(0);
   Reg#(Bit#(8)) trafficPtr <- mkReg(0);
   Reg#(Bit#(64)) trafficAccum <- mkReg(0);

   function Server#(AddrTransRequest,Bit#(addrWidth)) selectMMUPort(Integer i);
      return mmus[i].addr[1];
   endfunction
   Vector#(numMMUs,ArbitratedMMU#(addrWidth,numClients)) mmu_servers <- mapM(mkArbitratedMMU,map(selectMMUPort,genVector));
   Vector#(numClients,MemWriteInternal#(addrWidth,busWidth,MemServerTags,nwc)) writers;
   Vector#(numClients, PhysMemWriteClient#(addrWidth,busWidth)) write_clients;
   Vector#(numServers, MemWriteServer#(busWidth)) write_servers;

   for(Integer i = 0; i < valueOf(numClients); i = i+1) begin
      Vector#(numMMUs,Server#(AddrTransRequest,Bit#(addrWidth))) ss;
      for(Integer j = 0; j < valueOf(numMMUs); j=j+1)
	 ss[j] = mmu_servers[j].servers[i];
      writers[i] <- mkMemWriteInternal(indication, ss);
      write_clients[i] = writers[i].client;
      for(Integer j = 0; j < valueOf(nwc); j=j+1)
	 write_servers[i*valueOf(nwc)+j] = writers[i].servers[j];
   end

   rule mmuEntry;
      addrReqFifo.deq;
      let physAddr <- mmus[addrReqFifo.first[31:16]].addr[1].response.get;
      indication.addrResponse(zeroExtend(physAddr));
   endrule

   Stmt dbgStmt =
   seq
      for(dbgPtr <= 0; dbgPtr < fromInteger(valueOf(numClients)); dbgPtr <= dbgPtr+1)
	 (action
	     let rv <- writers[dbgPtr].dbg.dbg;
	     indication.reportStateDbg(rv);
	  endaction);
   endseq;
   FSM dbgFSM <- mkFSM(dbgStmt);

   Stmt trafficStmt =
   seq
      trafficAccum <= 0;
      for(trafficPtr <= 0; trafficPtr < fromInteger(valueOf(numClients)); trafficPtr <= trafficPtr+1)
	 (action
	     let rv <- writers[trafficPtr].dbg.getMemoryTraffic();
	     trafficAccum <= trafficAccum + rv;
	  endaction);
      indication.reportMemoryTraffic(trafficAccum);
   endseq;
   FSM trafficFSM <- mkFSM(trafficStmt);

   interface servers = write_servers;
   interface clients = write_clients;
   interface MemServerRequest request;
      method Action setTileState(TileControl tc);
	 for(Integer i = 0; i < valueOf(numClients); i=i+1)
	    writers[i].tileControl.put(tc);
      endmethod
      method Action stateDbg(ChannelType rc);
	 if (rc == ChannelType_Write)
	    dbgFSM.start;
      endmethod
      method Action memoryTraffic(ChannelType rc);
	 if (rc == ChannelType_Write)
	    trafficFSM.start;
      endmethod
      method Action addrTrans(Bit#(32) pointer, Bit#(32) offset);
	 addrReqFifo.enq(pointer);
	 mmus[pointer[31:16]].addr[1].request.put(AddrTransRequest{id:truncate(pointer), off:extend(offset)});
      endmethod
   endinterface
endmodule

module mkMemServerWithMMU#(Vector#(numReadClients, MemReadClient#(busWidth)) readClients,
			  Vector#(numWriteClients, MemWriteClient#(busWidth)) writeClients,
			  MemServerIndication indication,
			  MMUIndication mmuIndication)(MemServerWithMMU#(addrWidth, busWidth,nMasters))

   provisos(Add#(TLog#(TDiv#(busWidth, 8)), e__, 8)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), f__, BurstLenSize)
	    ,Add#(c__, addrWidth, 64)
	    ,Add#(d__, addrWidth, MemOffsetSize)
	    ,Add#(numWriteClients, a__, TMul#(TDiv#(numWriteClients, nMasters),nMasters))
	    ,Add#(numReadClients, b__, TMul#(TDiv#(numReadClients, nMasters),nMasters))
	    );

   MMU#(addrWidth) hostMMU <- mkMMU(0, True, mmuIndication);
   MemServer#(addrWidth,busWidth,nMasters) dma <- mkMemServer(readClients, writeClients, cons(hostMMU,nil), indication);

   interface MemServerRequest memServerRequest = dma.request;
   interface MMURequest mmuRequest = hostMMU.request;
   interface Vector masters = dma.masters;
endmodule

// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import FIFO::*;
import Vector::*;
import List::*;
import GetPut::*;
import ClientServer::*;
import Assert::*;
import StmtFSM::*;
import SpecialFIFOs::*;
import Connectable::*;
import HostInterface::*;
import MemTypes::*;
import ConnectalMemory::*;
import MMU::*;
import MemServerInternal::*;

interface MemServer#(numeric type addrWidth, numeric type busWidth, numeric type nMasters);
   interface MemServerRequest request;
   interface Vector#(nMasters,PhysMemMaster#(addrWidth, busWidth)) masters;
endinterface

interface MemServerWithMMU#(numeric type addrWidth, numeric type busWidth, numeric type nMasters);
   interface MemServerRequest memServerRequest;
   interface Vector#(nMasters,PhysMemMaster#(addrWidth, busWidth)) masters;
   interface MMURequest mmuRequest;
endinterface

interface MemServerRead#(numeric type addrWidth, numeric type busWidth, numeric type numClients, numeric type numServers);
   interface MemServerRequest request;
   interface Vector#(numClients, PhysMemReadClient#(addrWidth,busWidth)) clients;
   interface Vector#(numServers, MemReadServer#(busWidth)) servers;
endinterface

interface MemServerWrite#(numeric type addrWidth, numeric type busWidth, numeric type numClients, numeric type numServers);
   interface MemServerRequest request;
   interface Vector#(numClients, PhysMemWriteClient#(addrWidth,busWidth)) clients;
   interface Vector#(numServers, MemWriteServer#(busWidth)) servers;
endinterface

typedef struct {
   DmaErrorType errorType;
   Bit#(32) pref;
   } DmaError deriving (Bits);

module mkMemServer#(Vector#(numReadClients, MemReadClient#(busWidth)) readClients,
		    Vector#(numWriteClients, MemWriteClient#(busWidth)) writeClients,
		    Vector#(numMMUs,MMU#(addrWidth)) mmus,
		    MemServerIndication indication)
   (MemServer#(addrWidth, busWidth, nMasters))
   provisos(Mul#(TDiv#(numWriteClients, nMasters),nMasters,nws)
	    ,Mul#(TDiv#(numReadClients, nMasters),nMasters,nrs)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), d__, 8)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), e__, BurstLenSize)
	    ,Add#(c__, addrWidth, 64)
	    ,Add#(numWriteClients, a__, nws)
	    ,Add#(numReadClients, b__, nrs)
	    );

   MemServerRead#(addrWidth,busWidth,nMasters,nrs)  reader <- mkMemServerRead(indication, mmus);
   MemServerWrite#(addrWidth,busWidth,nMasters,nws) writer <- mkMemServerWrite(indication, mmus);

   zipWithM(mkConnection,readClients,take(reader.servers));
   zipWithM(mkConnection,writeClients,take(writer.servers));

   function PhysMemMaster#(addrWidth,busWidth) mkm(Integer i) = (interface PhysMemMaster#(addrWidth,busWidth);
		     interface PhysMemReadClient read_client = reader.clients[i];
		     interface PhysMemWriteClient write_client = writer.clients[i];
		  endinterface);

   interface MemServerRequest request;
      method Action setTileState(TileControl tc);
	 reader.request.setTileState(tc);
	 writer.request.setTileState(tc);
      endmethod
      method Action stateDbg(ChannelType rc);
	 if (rc == ChannelType_Read)
	    reader.request.stateDbg(rc);
	 else
	    writer.request.stateDbg(rc);
      endmethod
      method Action memoryTraffic(ChannelType rc);
	 if (rc == ChannelType_Read)
	    reader.request.memoryTraffic(rc);
	 else
	    writer.request.memoryTraffic(rc);
      endmethod
      method Action addrTrans(Bit#(32) pointer, Bit#(32) offset);
	 writer.request.addrTrans(pointer,offset);
      endmethod
   endinterface
   interface masters = map(mkm,genVector);
endmodule

module mkMemServerRead#(MemServerIndication indication,
			Vector#(numMMUs,MMU#(addrWidth)) mmus)
   (MemServerRead#(addrWidth, busWidth, numClients, numServers))
   provisos(Mul#(nrc, numClients, numServers)
	    ,Add#(a__, addrWidth, 64)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), b__, 8)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), c__, BurstLenSize)
	    );

   FIFO#(Bit#(32))   addrReqFifo <- mkFIFO;
   Reg#(Bit#(8)) dbgPtr <- mkReg(0);
   Reg#(Bit#(8)) trafficPtr <- mkReg(0);
   Reg#(Bit#(64)) trafficAccum <- mkReg(0);

   function Server#(AddrTransRequest,Bit#(addrWidth)) selectMMUPort(Integer i);
      return mmus[i].addr[0];
   endfunction
   Vector#(numMMUs,ArbitratedMMU#(addrWidth,numClients)) mmu_servers <- mapM(mkArbitratedMMU,map(genVector));
   Vector#(numClients,MemReadInternal#(addrWidth,busWidth,MemServerTags,nrc)) readers;
   Vector#(numClients, PhysMemReadClient#(addrWidth,busWidth)) read_clients;
   Vector#(numServers, MemReadServer#(busWidth)) read_servers;

   for(Integer i = 0; i < valueOf(numClients); i = i+1) begin
      Vector#(numMMUs,Server#(AddrTransRequest,Bit#(addrWidth))) ss;
      for(Integer j = 0; j < valueOf(numMMUs); j=j+1)
	 ss[j] = mmu_servers[j].servers[i];
      readers[i] <- mkMemReadInternal(indication,ss);
      read_clients[i] = readers[i].client;
      for(Integer j = 0; j < valueOf(nrc); j=j+1)
	 read_servers[i*valueOf(nrc)+j] = readers[i].servers[j];
   end

   rule mmuEntry;
      addrReqFifo.deq;
      let physAddr <- mmus[addrReqFifo.first[31:16]].addr[0].response.get;
      indication.addrResponse(zeroExtend(physAddr));
   endrule

   Stmt dbgStmt =
   seq
      for(dbgPtr <= 0; dbgPtr < fromInteger(valueOf(numClients)); dbgPtr <= dbgPtr+1)
	 (action
	     let rv <- readers[dbgPtr].dbg.dbg;
	     indication.reportStateDbg(rv);
	  endaction);
   endseq;
   FSM dbgFSM <- mkFSM(dbgStmt);

   Stmt trafficStmt =
   seq
      trafficAccum <= 0;
      for(trafficPtr <= 0; trafficPtr < fromInteger(valueOf(numClients)); trafficPtr <= trafficPtr+1)
	 (action
	     let rv <- readers[trafficPtr].dbg.getMemoryTraffic();
	     trafficAccum <= trafficAccum + rv;
	  endaction);
      indication.reportMemoryTraffic(trafficAccum);
   endseq;
   FSM trafficFSM <- mkFSM(trafficStmt);

   interface servers = read_servers;
   interface clients = read_clients;
   interface MemServerRequest request;
      method Action setTileState(TileControl tc);
	 for(Integer i = 0; i < valueOf(numClients); i=i+1)
	    readers[i].tileControl.put(tc);
      endmethod
      method Action stateDbg(ChannelType rc);
	 if (rc == ChannelType_Read)
	    dbgFSM.start;
      endmethod
      method Action memoryTraffic(ChannelType rc);
	 if (rc == ChannelType_Read)
	    trafficFSM.start;
      endmethod
      method Action addrTrans(Bit#(32) pointer, Bit#(32) offset);
	 addrReqFifo.enq(pointer);
	 mmus[pointer[31:16]].addr[0].request.put(AddrTransRequest{id:truncate(pointer), off:extend(offset)});
      endmethod
   endinterface
endmodule

module mkMemServerWrite#(MemServerIndication indication,
		     Vector#(numMMUs,MMU#(addrWidth)) mmus)
   (MemServerWrite#(addrWidth, busWidth, numClients, numServers))
   provisos(Mul#(nwc, numClients, numServers)
	    ,Add#(a__, addrWidth, 64)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), b__, 8)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), c__, BurstLenSize)
	    );

   FIFO#(Bit#(32))   addrReqFifo <- mkFIFO;
   Reg#(Bit#(8)) dbgPtr <- mkReg(0);
   Reg#(Bit#(8)) trafficPtr <- mkReg(0);
   Reg#(Bit#(64)) trafficAccum <- mkReg(0);

   function Server#(AddrTransRequest,Bit#(addrWidth)) selectMMUPort(Integer i);
      return mmus[i].addr[1];
   endfunction
   Vector#(numMMUs,ArbitratedMMU#(addrWidth,numClients)) mmu_servers <- mapM(mkArbitratedMMU,map(genVector));
   Vector#(numClients,MemWriteInternal#(addrWidth,busWidth,MemServerTags,nwc)) writers;
   Vector#(numClients, PhysMemWriteClient#(addrWidth,busWidth)) write_clients;
   Vector#(numServers, MemWriteServer#(busWidth)) write_servers;

   for(Integer i = 0; i < valueOf(numClients); i = i+1) begin
      Vector#(numMMUs,Server#(AddrTransRequest,Bit#(addrWidth))) ss;
      for(Integer j = 0; j < valueOf(numMMUs); j=j+1)
	 ss[j] = mmu_servers[j].servers[i];
      writers[i] <- mkMemWriteInternal(indication, ss);
      write_clients[i] = writers[i].client;
      for(Integer j = 0; j < valueOf(nwc); j=j+1)
	 write_servers[i*valueOf(nwc)+j] = writers[i].servers[j];
   end

   rule mmuEntry;
      addrReqFifo.deq;
      let physAddr <- mmus[addrReqFifo.first[31:16]].addr[1].response.get;
      indication.addrResponse(zeroExtend(physAddr));
   endrule

   Stmt dbgStmt =
   seq
      for(dbgPtr <= 0; dbgPtr < fromInteger(valueOf(numClients)); dbgPtr <= dbgPtr+1)
	 (action
	     let rv <- writers[dbgPtr].dbg.dbg;
	     indication.reportStateDbg(rv);
	  endaction);
   endseq;
   FSM dbgFSM <- mkFSM(dbgStmt);

   Stmt trafficStmt =
   seq
      trafficAccum <= 0;
      for(trafficPtr <= 0; trafficPtr < fromInteger(valueOf(numClients)); trafficPtr <= trafficPtr+1)
	 (action
	     let rv <- writers[trafficPtr].dbg.getMemoryTraffic();
	     trafficAccum <= trafficAccum + rv;
	  endaction);
      indication.reportMemoryTraffic(trafficAccum);
   endseq;
   FSM trafficFSM <- mkFSM(trafficStmt);

   interface servers = write_servers;
   interface clients = write_clients;
   interface MemServerRequest request;
      method Action setTileState(TileControl tc);
	 for(Integer i = 0; i < valueOf(numClients); i=i+1)
	    writers[i].tileControl.put(tc);
      endmethod
      method Action stateDbg(ChannelType rc);
	 if (rc == ChannelType_Write)
	    dbgFSM.start;
      endmethod
      method Action memoryTraffic(ChannelType rc);
	 if (rc == ChannelType_Write)
	    trafficFSM.start;
      endmethod
      method Action addrTrans(Bit#(32) pointer, Bit#(32) offset);
	 addrReqFifo.enq(pointer);
	 mmus[pointer[31:16]].addr[1].request.put(AddrTransRequest{id:truncate(pointer), off:extend(offset)});
      endmethod
   endinterface
endmodule

module mkMemServerWithMMU#(Vector#(numReadClients, MemReadClient#(busWidth)) readClients,
			  Vector#(numWriteClients, MemWriteClient#(busWidth)) writeClients,
			  MemServerIndication indication,
			  MMUIndication mmuIndication)(MemServerWithMMU#(addrWidth, busWidth,nMasters))

   provisos(Add#(TLog#(TDiv#(busWidth, 8)), e__, 8)
	    ,Add#(TLog#(TDiv#(busWidth, 8)), f__, BurstLenSize)
	    ,Add#(c__, addrWidth, 64)
	    ,Add#(d__, addrWidth, MemOffsetSize)
	    ,Add#(numWriteClients, a__, TMul#(TDiv#(numWriteClients, nMasters),nMasters))
	    ,Add#(numReadClients, b__, TMul#(TDiv#(numReadClients, nMasters),nMasters))
	    );

   MMU#(addrWidth) hostMMU <- mkMMU(0, True, mmuIndication);
   MemServer#(addrWidth,busWidth,nMasters) dma <- mkMemServer(readClients, writeClients, cons(hostMMU,nil), indication);

   interface MemServerRequest memServerRequest = dma.request;
   interface MMURequest mmuRequest = hostMMU.request;
   interface Vector masters = dma.masters;
endmodule


spi_rxfifo_get -> get_spi_rxfifo

spi_rxfifo_get -> get_spi_rxfifo

// Copyright (c) 2013 Nokia, Inc.
// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import FIFO::*;
import SPI::*;
import GetPut::*;

import Zynq::*;
import Imageon::*;
import HDMI::*;
import BlueScope::*;

interface ImageCaptureIndications;
    method Action spi_control_value(Bit#(32) v);
    method Action iserdes_control_value(Bit#(32) v);
    method Action decoder_control_value(Bit#(32) v);
    method Action crc_control_value(Bit#(32) v);
    method Action crc_status_value(Bit#(32) v);
    method Action remapper_control_value(Bit#(32) v);
    method Action triggen_control_value(Bit#(32) v);

    method Action rxfifo_value(Bit#(32) v);
endinterface

interface ImageCapture;
    method Action set_spi_control(Bit#(32) v);
    method Action get_spi_control();
    method Action set_iserdes_control(Bit#(32) v);
    method Action get_iserdes_control();
    method Action set_decoder_control(Bit#(32) v);
    method Action get_decoder_control();
    method Action set_crc_control(Bit#(32) v);
    method Action get_crc_control();
    method Action get_crc_status();
    method Action set_remapper_control(Bit#(32) v);
    method Action get_remapper_control();
    method Action set_triggen_control(Bit#(32) v);
    method Action get_triggen_control();

    method Action set_host_vita_reset(Bit#(1) v);
    method Action set_host_oe(Bit#(1) v);

    method Action set_spi_reset(Bit#(1) v);
    method Action set_spi_timing(Bit#(16) v);
    method Action put_spi_txfifo(Bit#(32) v);
    method Action get_spi_rxfifo();

    method Action set_serdes_reset(Bit#(1) v);
    method Action set_serdes_auto_align(Bit#(1) v);
    method Action set_serdes_align_start(Bit#(1) v);
    method Action set_serdes_fifo_enable(Bit#(1) v);
    method Action set_serdes_manual_tap(Bit#(10) v);
    method Action set_serdes_training(Bit#(10) v);
    method Action set_decoder_reset(Bit#(1) v);
    method Action set_decoder_enable(Bit#(1) v);
    method Action set_decoder_startoddeven(Bit#(32) v);
    method Action set_decoder_code_ls(Bit#(10) v);
    method Action set_decoder_code_le(Bit#(10) v);
    method Action set_decoder_code_fs(Bit#(10) v);
    method Action set_decoder_code_fe(Bit#(10) v);
    method Action set_decoder_code_bl(Bit#(10) v);
    method Action set_decoder_code_img(Bit#(10) v);
    method Action set_decoder_code_tr(Bit#(10) v);
    method Action set_decoder_code_crc(Bit#(10) v);
    method Action set_crc_reset(Bit#(1) v);
    method Action set_crc_initvalue(Bit#(1) v);
    method Action set_remapper_write_cfg(Bit#(3) v);
    method Action set_remapper_mode(Bit#(3) v);
    method Action set_trigger_enable(Bit#(3) v);
    method Action set_trigger_sync2readout(Bit#(3) v);
    method Action set_trigger_readouttrigger(Bit#(1) v);
    method Action set_trigger_default_freq(Bit#(32) v);
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
    method Action set_trigger_cnt_trigger1high(Bit#(32) v);
    method Action set_trigger_cnt_trigger1low(Bit#(32) v);
    method Action set_trigger_cnt_trigger2high(Bit#(32) v);
    method Action set_trigger_cnt_trigger2low(Bit#(32) v);
    method Action set_trigger_ext_debounce(Bit#(32) v);
    method Action set_trigger_ext_polarity(Bit#(1) v);
    method Action set_trigger_gen_polarity(Bit#(3) v);
    method Action set_prnu_values(Bit#(64) v0, Bit#(64) v1, Bit#(64) v2, Bit#(64) v3);
    method Action set_syncgen_delay(Bit#(16) v);
    method Action set_syncgen_hactive(Bit#(16) v);
    method Action set_syncgen_hfporch(Bit#(16) v);
    method Action set_syncgen_hsync(Bit#(16) v);
    method Action set_syncgen_hbporch(Bit#(16) v);
    method Action set_syncgen_vactive(Bit#(16) v);
    method Action set_syncgen_vfporch(Bit#(16) v);
    method Action set_syncgen_vsync(Bit#(16) v);
    method Action set_syncgen_vbporch(Bit#(16) v);

    interface ImageonVita imageon;
//    interface HDMI hdmi;
endinterface

module mkImageCapture#(//Clock hdmi_clock,
       ImageCaptureIndications indications)(ImageCapture);
    ImageonVitaController imageonVita <- mkImageonVitaController();
    ImageonControl control = imageonVita.control;
    //BlueScope#(96,96) spiBlueScope <- mkBlueScope(1024);

    method Action set_spi_control(Bit#(32) v);
        control.set_spi_control(v);
    endmethod
    method Action get_spi_control();
        indications.spi_control_value(control.get_spi_control());
    endmethod

    method Action set_iserdes_control(Bit#(32) v);
        control.set_iserdes_control(v);
    endmethod
    method Action get_iserdes_control();
        indications.iserdes_control_value(control.get_iserdes_control());
    endmethod

    method Action set_decoder_control(Bit#(32) v);
        control.set_decoder_control(v);
    endmethod
    method Action get_decoder_control();
        indications.decoder_control_value(control.get_decoder_control());
    endmethod

    method Action set_crc_control(Bit#(32) v);
        control.set_crc_control(v);
    endmethod
    method Action get_crc_control();
        indications.crc_control_value(control.get_crc_control());
    endmethod

    method Action get_crc_status();
        indications.crc_status_value(control.get_crc_status());
    endmethod

    method Action set_remapper_control(Bit#(32) v);
        control.set_remapper_control(v);
    endmethod
    method Action get_remapper_control();
        indications.remapper_control_value(control.get_remapper_control());
    endmethod

    method Action set_triggen_control(Bit#(32) v);
        control.set_triggen_control(v);
    endmethod
    method Action get_triggen_control();
        indications.triggen_control_value(control.get_triggen_control());
    endmethod

    method Action set_host_vita_reset(Bit#(1) v);
        control.set_host_vita_reset(v);
    endmethod
    method Action set_host_oe(Bit#(1) v);
        control.set_host_oe(v);
    endmethod
    method Action set_spi_reset(Bit#(1) v);
        control.set_spi_reset(v);
    endmethod
    method Action set_spi_timing(Bit#(16) v);
        control.set_spi_timing(v);
    endmethod
    method Action put_spi_txfifo(Bit#(32) v);
        control.txfifo.put(v);
    endmethod
    method Action get_spi_rxfifo();
        Bit#(32) v <- control.rxfifo.get();
        indications.rxfifo_value(v);
    endmethod
    method Action set_serdes_reset(Bit#(1) v);
        control.set_serdes_reset(v);
    endmethod
    method Action set_serdes_auto_align(Bit#(1) v);
        control.set_serdes_auto_align(v);
    endmethod
    method Action set_serdes_align_start(Bit#(1) v);
        control.set_serdes_align_start(v);
    endmethod
    method Action set_serdes_fifo_enable(Bit#(1) v);
        control.set_serdes_fifo_enable(v);
    endmethod
    method Action set_serdes_manual_tap(Bit#(10) v);
        control.set_serdes_manual_tap(v);
    endmethod
    method Action set_serdes_training(Bit#(10) v);
        control.set_serdes_training(v);
    endmethod
    method Action set_decoder_reset(Bit#(1) v);
        control.set_decoder_reset(v);
    endmethod
    method Action set_decoder_enable(Bit#(1) v);
        control.set_decoder_enable(v);
    endmethod
    method Action set_decoder_startoddeven(Bit#(32) v);
        control.set_decoder_startoddeven(v);
    endmethod
    method Action set_decoder_code_ls(Bit#(10) v);
        control.set_decoder_code_ls(v);
    endmethod
    method Action set_decoder_code_le(Bit#(10) v);
        control.set_decoder_code_le(v);
    endmethod
    method Action set_decoder_code_fs(Bit#(10) v);
        control.set_decoder_code_fs(v);
    endmethod
    method Action set_decoder_code_fe(Bit#(10) v);
        control.set_decoder_code_fe(v);
    endmethod
    method Action set_decoder_code_bl(Bit#(10) v);
        control.set_decoder_code_bl(v);
    endmethod
    method Action set_decoder_code_img(Bit#(10) v);
        control.set_decoder_code_img(v);
    endmethod
    method Action set_decoder_code_tr(Bit#(10) v);
        control.set_decoder_code_tr(v);
    endmethod
    method Action set_decoder_code_crc(Bit#(10) v);
        control.set_decoder_code_crc(v);
    endmethod
    method Action set_crc_reset(Bit#(1) v);
        control.set_crc_reset(v);
    endmethod
    method Action set_crc_initvalue(Bit#(1) v);
        control.set_crc_initvalue(v);
    endmethod
    method Action set_remapper_write_cfg(Bit#(3) v);
        control.set_remapper_write_cfg(v);
    endmethod
    method Action set_remapper_mode(Bit#(3) v);
        control.set_remapper_mode(v);
    endmethod
    method Action set_trigger_enable(Bit#(3) v);
        control.set_trigger_enable(v);
    endmethod
    method Action set_trigger_sync2readout(Bit#(3) v);
        control.set_trigger_sync2readout(v);
    endmethod
    method Action set_trigger_readouttrigger(Bit#(1) v);
        control.set_trigger_readouttrigger(v);
    endmethod
    method Action set_trigger_default_freq(Bit#(32) v);
        control.set_trigger_default_freq(v);
    endmethod
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
        control.set_trigger_cnt_trigger0high(v);
    endmethod
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
        control.set_trigger_cnt_trigger0low(v);
    endmethod
    method Action set_trigger_cnt_trigger1high(Bit#(32) v);
        control.set_trigger_cnt_trigger1high(v);
    endmethod
    method Action set_trigger_cnt_trigger1low(Bit#(32) v);
        control.set_trigger_cnt_trigger1low(v);
    endmethod
    method Action set_trigger_cnt_trigger2high(Bit#(32) v);
        control.set_trigger_cnt_trigger2high(v);
    endmethod
    method Action set_trigger_cnt_trigger2low(Bit#(32) v);
        control.set_trigger_cnt_trigger2low(v);
    endmethod
    method Action set_trigger_ext_debounce(Bit#(32) v);
        control.set_trigger_ext_debounce(v);
    endmethod
    method Action set_trigger_ext_polarity(Bit#(1) v);
        control.set_trigger_ext_polarity(v);
    endmethod
    method Action set_trigger_gen_polarity(Bit#(3) v);
        control.set_trigger_gen_polarity(v);
    endmethod
    method Action set_prnu_values(Bit#(64) v0, Bit#(64) v1, Bit#(64) v2, Bit#(64) v3);
        Bit#(256) bitvec;
	bitvec[63:0] = v0;
	bitvec[127:64] = v1;
	bitvec[191:128] = v2;
	bitvec[255:192] = v3;
        control.set_prnu_values(bitvec);
    endmethod
    method Action set_syncgen_delay(Bit#(16) v);
        control.set_syncgen_delay(v);
    endmethod
    method Action set_syncgen_hactive(Bit#(16) v);
        control.set_syncgen_hactive(v);
    endmethod
    method Action set_syncgen_hfporch(Bit#(16) v);
        control.set_syncgen_hfporch(v);
    endmethod
    method Action set_syncgen_hsync(Bit#(16) v);
        control.set_syncgen_hsync(v);
    endmethod
    method Action set_syncgen_hbporch(Bit#(16) v);
        control.set_syncgen_hbporch(v);
    endmethod
    method Action set_syncgen_vactive(Bit#(16) v);
        control.set_syncgen_vactive(v);
    endmethod
    method Action set_syncgen_vfporch(Bit#(16) v);
        control.set_syncgen_vfporch(v);
    endmethod
    method Action set_syncgen_vsync(Bit#(16) v);
        control.set_syncgen_vsync(v);
    endmethod
    method Action set_syncgen_vbporch(Bit#(16) v);
        control.set_syncgen_vbporch(v);
    endmethod

    interface ImageonVita imageon = imageonVita.host;
endmodule

// Copyright (c) 2013 Nokia, Inc.
// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import FIFO::*;
import SPI::*;
import GetPut::*;

import Zynq::*;
import Imageon::*;
import HDMI::*;
import BlueScope::*;

interface ImageCaptureIndications;
    method Action spi_control_value(Bit#(32) v);
    method Action iserdes_control_value(Bit#(32) v);
    method Action decoder_control_value(Bit#(32) v);
    method Action crc_control_value(Bit#(32) v);
    method Action crc_status_value(Bit#(32) v);
    method Action remapper_control_value(Bit#(32) v);
    method Action triggen_control_value(Bit#(32) v);

    method Action rxfifo_value(Bit#(32) v);
endinterface

interface ImageCapture;
    method Action set_spi_control(Bit#(32) v);
    method Action get_spi_control();
    method Action set_iserdes_control(Bit#(32) v);
    method Action get_iserdes_control();
    method Action set_decoder_control(Bit#(32) v);
    method Action get_decoder_control();
    method Action set_crc_control(Bit#(32) v);
    method Action get_crc_control();
    method Action get_crc_status();
    method Action set_remapper_control(Bit#(32) v);
    method Action get_remapper_control();
    method Action set_triggen_control(Bit#(32) v);
    method Action get_triggen_control();

    method Action set_host_vita_reset(Bit#(1) v);
    method Action set_host_oe(Bit#(1) v);

    method Action set_spi_reset(Bit#(1) v);
    method Action set_spi_timing(Bit#(16) v);
    method Action spi_txfifo_put(Bit#(32) v);
    method Action spi_rxfifo_get();

    method Action set_serdes_reset(Bit#(1) v);
    method Action set_serdes_auto_align(Bit#(1) v);
    method Action set_serdes_align_start(Bit#(1) v);
    method Action set_serdes_fifo_enable(Bit#(1) v);
    method Action set_serdes_manual_tap(Bit#(10) v);
    method Action set_serdes_training(Bit#(10) v);
    method Action set_decoder_reset(Bit#(1) v);
    method Action set_decoder_enable(Bit#(1) v);
    method Action set_decoder_startoddeven(Bit#(32) v);
    method Action set_decoder_code_ls(Bit#(10) v);
    method Action set_decoder_code_le(Bit#(10) v);
    method Action set_decoder_code_fs(Bit#(10) v);
    method Action set_decoder_code_fe(Bit#(10) v);
    method Action set_decoder_code_bl(Bit#(10) v);
    method Action set_decoder_code_img(Bit#(10) v);
    method Action set_decoder_code_tr(Bit#(10) v);
    method Action set_decoder_code_crc(Bit#(10) v);
    method Action set_crc_reset(Bit#(1) v);
    method Action set_crc_initvalue(Bit#(1) v);
    method Action set_remapper_write_cfg(Bit#(3) v);
    method Action set_remapper_mode(Bit#(3) v);
    method Action set_trigger_enable(Bit#(3) v);
    method Action set_trigger_sync2readout(Bit#(3) v);
    method Action set_trigger_readouttrigger(Bit#(1) v);
    method Action set_trigger_default_freq(Bit#(32) v);
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
    method Action set_trigger_cnt_trigger1high(Bit#(32) v);
    method Action set_trigger_cnt_trigger1low(Bit#(32) v);
    method Action set_trigger_cnt_trigger2high(Bit#(32) v);
    method Action set_trigger_cnt_trigger2low(Bit#(32) v);
    method Action set_trigger_ext_debounce(Bit#(32) v);
    method Action set_trigger_ext_polarity(Bit#(1) v);
    method Action set_trigger_gen_polarity(Bit#(3) v);
    method Action set_prnu_values(Bit#(64) v0, Bit#(64) v1, Bit#(64) v2, Bit#(64) v3);
    method Action set_syncgen_delay(Bit#(16) v);
    method Action set_syncgen_hactive(Bit#(16) v);
    method Action set_syncgen_hfporch(Bit#(16) v);
    method Action set_syncgen_hsync(Bit#(16) v);
    method Action set_syncgen_hbporch(Bit#(16) v);
    method Action set_syncgen_vactive(Bit#(16) v);
    method Action set_syncgen_vfporch(Bit#(16) v);
    method Action set_syncgen_vsync(Bit#(16) v);
    method Action set_syncgen_vbporch(Bit#(16) v);

    interface ImageonVita imageon;
//    interface HDMI hdmi;
endinterface

module mkImageCapture#(//Clock hdmi_clock,
       ImageCaptureIndications indications)(ImageCapture);
    ImageonVitaController imageonVita <- mkImageonVitaController();
    ImageonControl control = imageonVita.control;
    //BlueScope#(96,96) spiBlueScope <- mkBlueScope(1024);

    method Action set_spi_control(Bit#(32) v);
        control.set_spi_control(v);
    endmethod
    method Action get_spi_control();
        indications.spi_control_value(control.get_spi_control());
    endmethod

    method Action set_iserdes_control(Bit#(32) v);
        control.set_iserdes_control(v);
    endmethod
    method Action get_iserdes_control();
        indications.iserdes_control_value(control.get_iserdes_control());
    endmethod

    method Action set_decoder_control(Bit#(32) v);
        control.set_decoder_control(v);
    endmethod
    method Action get_decoder_control();
        indications.decoder_control_value(control.get_decoder_control());
    endmethod

    method Action set_crc_control(Bit#(32) v);
        control.set_crc_control(v);
    endmethod
    method Action get_crc_control();
        indications.crc_control_value(control.get_crc_control());
    endmethod

    method Action get_crc_status();
        indications.crc_status_value(control.get_crc_status());
    endmethod

    method Action set_remapper_control(Bit#(32) v);
        control.set_remapper_control(v);
    endmethod
    method Action get_remapper_control();
        indications.remapper_control_value(control.get_remapper_control());
    endmethod

    method Action set_triggen_control(Bit#(32) v);
        control.set_triggen_control(v);
    endmethod
    method Action get_triggen_control();
        indications.triggen_control_value(control.get_triggen_control());
    endmethod

    method Action set_host_vita_reset(Bit#(1) v);
        control.set_host_vita_reset(v);
    endmethod
    method Action set_host_oe(Bit#(1) v);
        control.set_host_oe(v);
    endmethod
    method Action set_spi_reset(Bit#(1) v);
        control.set_spi_reset(v);
    endmethod
    method Action set_spi_timing(Bit#(16) v);
        control.set_spi_timing(v);
    endmethod
    method Action spi_txfifo_put(Bit#(32) v);
        control.txfifo.put(v);
    endmethod
    method Action spi_rxfifo_get();
        Bit#(32) v <- control.rxfifo.get();
        indications.rxfifo_value(v);
    endmethod
    method Action set_serdes_reset(Bit#(1) v);
        control.set_serdes_reset(v);
    endmethod
    method Action set_serdes_auto_align(Bit#(1) v);
        control.set_serdes_auto_align(v);
    endmethod
    method Action set_serdes_align_start(Bit#(1) v);
        control.set_serdes_align_start(v);
    endmethod
    method Action set_serdes_fifo_enable(Bit#(1) v);
        control.set_serdes_fifo_enable(v);
    endmethod
    method Action set_serdes_manual_tap(Bit#(10) v);
        control.set_serdes_manual_tap(v);
    endmethod
    method Action set_serdes_training(Bit#(10) v);
        control.set_serdes_training(v);
    endmethod
    method Action set_decoder_reset(Bit#(1) v);
        control.set_decoder_reset(v);
    endmethod
    method Action set_decoder_enable(Bit#(1) v);
        control.set_decoder_enable(v);
    endmethod
    method Action set_decoder_startoddeven(Bit#(32) v);
        control.set_decoder_startoddeven(v);
    endmethod
    method Action set_decoder_code_ls(Bit#(10) v);
        control.set_decoder_code_ls(v);
    endmethod
    method Action set_decoder_code_le(Bit#(10) v);
        control.set_decoder_code_le(v);
    endmethod
    method Action set_decoder_code_fs(Bit#(10) v);
        control.set_decoder_code_fs(v);
    endmethod
    method Action set_decoder_code_fe(Bit#(10) v);
        control.set_decoder_code_fe(v);
    endmethod
    method Action set_decoder_code_bl(Bit#(10) v);
        control.set_decoder_code_bl(v);
    endmethod
    method Action set_decoder_code_img(Bit#(10) v);
        control.set_decoder_code_img(v);
    endmethod
    method Action set_decoder_code_tr(Bit#(10) v);
        control.set_decoder_code_tr(v);
    endmethod
    method Action set_decoder_code_crc(Bit#(10) v);
        control.set_decoder_code_crc(v);
    endmethod
    method Action set_crc_reset(Bit#(1) v);
        control.set_crc_reset(v);
    endmethod
    method Action set_crc_initvalue(Bit#(1) v);
        control.set_crc_initvalue(v);
    endmethod
    method Action set_remapper_write_cfg(Bit#(3) v);
        control.set_remapper_write_cfg(v);
    endmethod
    method Action set_remapper_mode(Bit#(3) v);
        control.set_remapper_mode(v);
    endmethod
    method Action set_trigger_enable(Bit#(3) v);
        control.set_trigger_enable(v);
    endmethod
    method Action set_trigger_sync2readout(Bit#(3) v);
        control.set_trigger_sync2readout(v);
    endmethod
    method Action set_trigger_readouttrigger(Bit#(1) v);
        control.set_trigger_readouttrigger(v);
    endmethod
    method Action set_trigger_default_freq(Bit#(32) v);
        control.set_trigger_default_freq(v);
    endmethod
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
        control.set_trigger_cnt_trigger0high(v);
    endmethod
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
        control.set_trigger_cnt_trigger0low(v);
    endmethod
    method Action set_trigger_cnt_trigger1high(Bit#(32) v);
        control.set_trigger_cnt_trigger1high(v);
    endmethod
    method Action set_trigger_cnt_trigger1low(Bit#(32) v);
        control.set_trigger_cnt_trigger1low(v);
    endmethod
    method Action set_trigger_cnt_trigger2high(Bit#(32) v);
        control.set_trigger_cnt_trigger2high(v);
    endmethod
    method Action set_trigger_cnt_trigger2low(Bit#(32) v);
        control.set_trigger_cnt_trigger2low(v);
    endmethod
    method Action set_trigger_ext_debounce(Bit#(32) v);
        control.set_trigger_ext_debounce(v);
    endmethod
    method Action set_trigger_ext_polarity(Bit#(1) v);
        control.set_trigger_ext_polarity(v);
    endmethod
    method Action set_trigger_gen_polarity(Bit#(3) v);
        control.set_trigger_gen_polarity(v);
    endmethod
    method Action set_prnu_values(Bit#(64) v0, Bit#(64) v1, Bit#(64) v2, Bit#(64) v3);
        Bit#(256) bitvec;
	bitvec[63:0] = v0;
	bitvec[127:64] = v1;
	bitvec[191:128] = v2;
	bitvec[255:192] = v3;
        control.set_prnu_values(bitvec);
    endmethod
    method Action set_syncgen_delay(Bit#(16) v);
        control.set_syncgen_delay(v);
    endmethod
    method Action set_syncgen_hactive(Bit#(16) v);
        control.set_syncgen_hactive(v);
    endmethod
    method Action set_syncgen_hfporch(Bit#(16) v);
        control.set_syncgen_hfporch(v);
    endmethod
    method Action set_syncgen_hsync(Bit#(16) v);
        control.set_syncgen_hsync(v);
    endmethod
    method Action set_syncgen_hbporch(Bit#(16) v);
        control.set_syncgen_hbporch(v);
    endmethod
    method Action set_syncgen_vactive(Bit#(16) v);
        control.set_syncgen_vactive(v);
    endmethod
    method Action set_syncgen_vfporch(Bit#(16) v);
        control.set_syncgen_vfporch(v);
    endmethod
    method Action set_syncgen_vsync(Bit#(16) v);
        control.set_syncgen_vsync(v);
    endmethod
    method Action set_syncgen_vbporch(Bit#(16) v);
        control.set_syncgen_vbporch(v);
    endmethod

    interface ImageonVita imageon = imageonVita.host;
endmodule


added license to ConneclBram.bsv

added license to ConneclBram.bsv

// Copyright (c) 2015 Connectal Project

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import FIFO::*;
import FIFOF::*;
import Vector::*;
import BRAM::*;
import BRAMCore::*;
import GetPut::*;
import ClientServer::*;
import EHR::*;
import ConfigCounter::*;

interface BRAMServers#(numeric type numServers, type addr, type data);
   interface Vector#(numServers, BRAM1Port#(addr,data)) ports;
endinterface

module mkBRAMServers#(BRAM_Configure bramConfig)(BRAMServers#(numServers, addr, data))
   provisos (Bits#(addr,asz),
	     Bits#(data,dsz));
   BRAM_DUAL_PORT#(addr,data) bram <- mkBRAMCore2(bramConfig.memorySize, True); // latency 2
   Vector#(2, FIFOF#(data)) responseFifo <- replicateM(mkSizedFIFOF(2));
   // EHR did not work here, CReg doesn't seem to go into a vector, so using Wire. -Jamey
   Vector#(2, Wire#(Maybe#(Tuple2#(Bool,data)))) data0 <- replicateM(mkDWire(tagged Invalid));
   Vector#(2, Reg#(Maybe#(Tuple2#(Bool,data)))) data1 <- replicateM(mkReg(tagged Invalid));
   Vector#(2, Reg#(Maybe#(Tuple2#(Bool,data)))) data2 <- replicateM(mkReg(tagged Invalid));
   Vector#(2, ConfigCounter#(2)) counter <- replicateM(mkConfigCounter(2));

   function BRAM_PORT#(addr, data) portsel(Integer port);
      return (port == 0) ? bram.a : bram.b;
   endfunction

   for (Integer i = 0; i < 2; i = i + 1) begin
      rule bramRule;
	 // zeroth stage
	 let d0 = data0[i];
	 data1[i] <= d0;

	 // first stage // address register
	 let d1 = data1[i];
	 data2[i] <= d1;

	 // second stage
	 let d2 = data2[i];
	 if (d2 matches tagged Valid .tpl) begin
	    match { .write, .data } = tpl;
	    if (!write)
	       data = portsel(i).read();
	    if (responseFifo[i].notFull())
	       responseFifo[i].enq(data);
	    else
	       $display("Error: responseFifo is unexpectedly full");
	 end
      endrule
   end

   function BRAM1Port#(addr,data) server(Integer i);
      return (interface BRAM1Port#(addr,data);
	 interface BRAMServer portA;
	 interface Put request;
	    method Action put(BRAMRequest#(addr,data) req) if (counter[i].positive());
	      portsel(i).put(req.write, req.address, req.datain);
	      if (!req.write || req.responseOnWrite) begin
		 counter[i].decrement(1);
		 data0[i] <= tagged Valid tuple2(req.write, req.datain);
	      end
	    endmethod
	 endinterface
	 interface Get response;
	    method ActionValue#(data) get();
	      let v <- toGet(responseFifo[i]).get();
	      counter[i].increment(1);
	      return v;
	    endmethod
	 endinterface: response
	 endinterface: portA
	      method Action portAClear();
		 //FIXME
	      endmethod
	 endinterface);
   endfunction

   interface ports = genWith(server);
endmodule

module mkBRAM2Server#(BRAM_Configure bramConfig)(BRAM2Port#(addr, data))
   provisos (Bits#(addr, a__),
	     Bits#(data, b__));
   BRAMServers#(2,addr,data) bram <- mkBRAMServers(bramConfig);

   interface portA = bram.ports[0].portA;
   interface portB = bram.ports[1].portA;
   method portAClear = bram.ports[0].portAClear;
   method portBClear = bram.ports[1].portAClear;
endmodule

module mkBRAM1Server#(BRAM_Configure bramConfig)(BRAM1Port#(addr, data))
   provisos (Bits#(addr, a__),
	     Bits#(data, b__));
   BRAMServers#(1,addr,data) bram <- mkBRAMServers(bramConfig);

   interface portA = bram.ports[0].portA;
   method portAClear = bram.ports[0].portAClear;
endmodule

export mkBRAM1Server;
export mkBRAM2Server;


use a vector of registers for the MemengineCmd

// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Vector::*;
import FIFOF::*;
import FIFO::*;
import GetPut::*;
import Assert::*;
import ClientServer::*;
import BRAM::*;
import BRAMFIFO::*;
import ConfigCounter::*;
import Connectable::*;

import ConnectalMemory::*;
import MemTypes::*;
import Pipe::*;
import MemUtils::*;

module mkMemreadEngine(MemreadEngine#(dataWidth, cmdQDepth, numServers))
   provisos( Mul#(TDiv#(dataWidth, 8), 8, dataWidth)
	    ,Add#(1, a__, numServers)
	    ,Add#(b__, TLog#(numServers), TAdd#(1, TLog#(TMul#(cmdQDepth,numServers))))
	    ,Add#(c__, TLog#(numServers), TLog#(TMul#(cmdQDepth, numServers)))
	    ,Add#(d__, TLog#(numServers), 6)
	    );
   let rv <- mkMemreadEngineBuff(valueOf(TExp#(BurstLenSize)));
   return rv;
endmodule

module mkMemreadEngineBuff#(Integer bufferSizeBytes) (MemreadEngine#(dataWidth, cmdQDepth, numServers))
   provisos (Div#(dataWidth,8,dataWidthBytes),
	     Mul#(dataWidthBytes,8,dataWidth),
	     Log#(dataWidthBytes,beatShift),
	     Log#(cmdQDepth,logCmdQDepth),
	     Mul#(cmdQDepth,numServers,cmdBuffSz),
	     Log#(cmdBuffSz, cmdBuffAddrSz),
	     Log#(numServers, serverIdxSz),
	     Add#(1,logCmdQDepth, outCntSz),
	     Add#(1, c__, numServers),
	     Add#(b__, TLog#(numServers), cmdBuffAddrSz),
	     Add#(e__, TLog#(numServers), TAdd#(1, cmdBuffAddrSz)),
	     Add#(a__, serverIdxSz, cmdBuffAddrSz),
	     Min#(2,TLog#(numServers),bpc),
	     Add#(d__, TLog#(numServers), TAdd#(1, serverIdxSz)),
	     Add#(f__, serverIdxSz, 6));

   let verbose = False;

   Integer bufferSizeBeats = bufferSizeBytes/valueOf(dataWidthBytes);
   Vector#(numServers, Reg#(Bool))               outs1 <- replicateM(mkReg(False));
   Vector#(numServers, Reg#(Bit#(outCntSz)))     outs0 <- replicateM(mkReg(0));
   Vector#(numServers, ConfigCounter#(16))     buffCap <- replicateM(mkConfigCounter(fromInteger(bufferSizeBeats)));
   FIFO#(Bool)                                 cmdFifo <- mkFIFO1();
   Vector#(numServers, Reg#(MemengineCmd))     cmdRegs <- replicateM(mkReg(unpack(0)));

   Reg#(Bool) load_in_progress <- mkReg(False);
   FIFO#(Tuple3#(MemengineCmd,Bool,Bool))         loadf_b <- mkSizedFIFO(1);
   FIFO#(Tuple2#(Bit#(serverIdxSz),MemengineCmd)) loadf_c <- mkSizedFIFO(1);
   FIFO#(Tuple3#(Bit#(8),Bit#(serverIdxSz),Bool))   workf <- mkSizedBRAMFIFO(32); // isthis the right size?

   Vector#(numServers, FIFO#(void))              outfs <- replicateM(mkSizedFIFO(valueOf(cmdQDepth)));
   Vector#(numServers, FIFOF#(MemengineCmd))   cmds_in <- replicateM(mkSizedFIFOF(valueOf(cmdQDepth)));

   FIFOF#(MemData#(dataWidth))                             read_data <- mkFIFOF;
   Vector#(numServers, FIFOF#(MemData#(dataWidth)))  read_data_buffs <- replicateM(mkSizedBRAMFIFOF(bufferSizeBeats));
   function PipeOut#(Bit#(dataWidth)) check_out(PipeOut#(MemData#(dataWidth)) inpipe, Integer i) =
      (interface PipeOut;
	  method Bit#(dataWidth) first;
	     return inpipe.first.data;
	  endmethod
	  method Action deq;
	     inpipe.deq;
	     buffCap[i].increment(1);
	     if (inpipe.first.last)
		outfs[i].enq(?);
	  endmethod
	  method Bool notEmpty = inpipe.notEmpty;
       endinterface);
   Vector#(numServers, PipeOut#(Bit#(dataWidth))) read_data_pipes = zipWith(check_out, map(toPipeOut,read_data_buffs), genVector);

   Reg#(Bit#(8))                    respCnt <- mkReg(0);
   Reg#(Bit#(TAdd#(1,serverIdxSz))) loadIdx <- mkReg(0);
   let beat_shift = fromInteger(valueOf(beatShift));
   let cmd_q_depth = fromInteger(valueOf(cmdQDepth));

   function Action incr_loadIdx =
      (action
       if(loadIdx+1 >= fromInteger(valueOf(numServers)))
	  loadIdx <= 0;
       else
	  loadIdx <= loadIdx+1;
       endaction);

   for (Integer idx = 0; idx < valueOf(numServers); idx = idx + 1)
      rule store_cmd if (!outs1[idx]);
	 let cmd <- toGet(cmds_in[idx]).get();
	 outs1[idx] <= True;
	 cmdRegs[idx] <= cmd;
	 if (verbose) $display("mkMemreadEngineBuff::store_cmd %d %d", idx, buffCap[idx].read);
      endrule

   rule load_ctxt_a (!load_in_progress);
      if (outs1[loadIdx]) begin
	 load_in_progress <= True;
	 cmdFifo.enq(True);
	 if (verbose) $display("mkMemreadEngineBuff::load_ctxt_a %d", loadIdx);
      end
      else begin
	 incr_loadIdx;
      end
   endrule

   rule load_ctxt_b if (load_in_progress);
      let unused <- toGet(cmdFifo).get();
      let cmd = cmdRegs[loadIdx];
      let cond0 <- buffCap[loadIdx].maybeDecrement(unpack(extend(cmd.burstLen>>beat_shift)));
      let cond1 = cmd.len <= extend(cmd.burstLen);
      loadf_b.enq(tuple3(cmd,cond0,cond1));
      if (verbose) $display("mkMemreadEngineBuff::load_ctxt_b %d %d", buffCap[loadIdx].read(), cmd.burstLen>>beat_shift);
   endrule

   rule load_ctxt_c if (load_in_progress);
      load_in_progress <= False;
      incr_loadIdx;
      match {.cmd,.cond0,.cond1} <- toGet(loadf_b).get;
      if  (cond0) begin
	 if (verbose) $display("mkMemreadEngineBuff::load_ctxt_c %d %d", cmd.len, loadIdx);
	 let x = cmd.burstLen;
	 if (cmd.len < extend(cmd.burstLen))
	    x = truncate(cmd.len);
	 loadf_c.enq(tuple2(truncate(loadIdx),cmd));
	 if (cond1) begin
	    //$display("load_ctxt_b cond1");
	    outs1[loadIdx] <= False;
	 end
	 else begin
	    let new_cmd = MemengineCmd{sglId:cmd.sglId, base:cmd.base+extend(cmd.burstLen),
				       burstLen:cmd.burstLen, len:cmd.len-extend(cmd.burstLen), tag:cmd.tag};
	    cmdRegs[loadIdx] <= new_cmd;
	 end
      end
   endrule

   rule read_data_rule;
      let d <- toGet(read_data).get();
      match {.rc, .idx, .last} = workf.first;
      let new_respCnt = respCnt+1;
      let l = False;
      //$display("%h %d", d.data, idx);
      if (new_respCnt == rc) begin
	 respCnt <= 0;
	 workf.deq;
	 //$display("eob %d", idx);
	 l = last;
      end
      else begin
	 respCnt <= new_respCnt;
      end
      read_data_buffs[idx].enq(d);
   endrule

   function MemreadServer#(dataWidth) toMemreadServer(Server#(MemengineCmd,Bool) cs, PipeOut#(Bit#(dataWidth)) p) =
      (interface MemreadServer;
	  interface cmdServer = cs;
	  interface dataPipe  = p;
       endinterface);

   Vector#(numServers, Server#(MemengineCmd,Bool)) rs;
   for(Integer i = 0; i < valueOf(numServers); i=i+1)
      rs[i] = (interface Server#(MemengineCmd,Bool);
		  interface Put request;
		     method Action put(MemengineCmd cmd) if (outs0[i] < cmd_q_depth);
			Bit#(32) bsb = fromInteger(bufferSizeBytes);
`ifdef BSIM
			Bit#(32) dw = fromInteger(valueOf(dataWidthBytes));
			let mdw = ((cmd.len)/dw)*dw != cmd.len;
			let bbl = extend(cmd.burstLen) > bsb;
			if(bbl || mdw) begin
			   if (bbl)
			      $display("XXXXXXXXXX mkMemreadEngineBuff::unsupported burstLen %d %d", bsb, cmd.burstLen);
			   if (mdw)
			      $display("XXXXXXXXXX mkMemreadEngineBuff::unsupported len %d", cmd.len);
			end
			else begin
`endif
	 		   outs0[i] <= outs0[i]+1;
			   cmds_in[i].enq(cmd);
`ifdef BSIM
			end
`endif
 		     endmethod
		  endinterface
		  interface Get response;
		     method ActionValue#(Bool) get;
			outfs[i].deq;
	 		outs0[i] <= outs0[i]-1;
			return True;
		     endmethod
		  endinterface
	       endinterface);
   interface readServers = rs;
   interface MemReadClient dmaClient;
      interface Get readReq;
	 method ActionValue#(MemRequest) get();
	    match {.idx, .cmd} <- toGet(loadf_c).get;
	    Bit#(BurstLenSize) bl = cmd.burstLen;
	    let last = False;
	    if (cmd.len <= extend(bl)) begin
	       last = True;
	       bl = truncate(cmd.len);
	    end
	    workf.enq(tuple3(truncate(bl>>beat_shift), idx, last));
	    //$display("readReq %d, %h %h %h", idx, cmd.base, bl, last);
	    return MemRequest { sglId: cmd.sglId, offset: cmd.base, burstLen:bl, tag: (cmd.tag << valueOf(serverIdxSz)) | extend(idx)};
	 endmethod
      endinterface
      interface Put readData = toPut(read_data);
   endinterface
   interface dataPipes = read_data_pipes;
   interface read_servers = zipWith(toMemreadServer, rs, read_data_pipes);
endmodule

// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy,
// modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import Vector::*;
import FIFOF::*;
import FIFO::*;
import GetPut::*;
import Assert::*;
import ClientServer::*;
import BRAM::*;
import BRAMFIFO::*;
import ConfigCounter::*;
import Connectable::*;

import ConnectalMemory::*;
import MemTypes::*;
import Pipe::*;
import MemUtils::*;

module mkMemreadEngine(MemreadEngine#(dataWidth, cmdQDepth, numServers))
   provisos( Mul#(TDiv#(dataWidth, 8), 8, dataWidth)
	    ,Add#(1, a__, numServers)
	    ,Add#(b__, TLog#(numServers), TAdd#(1, TLog#(TMul#(cmdQDepth,numServers))))
	    ,Add#(c__, TLog#(numServers), TLog#(TMul#(cmdQDepth, numServers)))
	    ,Add#(d__, TLog#(numServers), 6)
	    );
   let rv <- mkMemreadEngineBuff(valueOf(TExp#(BurstLenSize)));
   return rv;
endmodule

module mkMemreadEngineBuff#(Integer bufferSizeBytes) (MemreadEngine#(dataWidth, cmdQDepth, numServers))
   provisos (Div#(dataWidth,8,dataWidthBytes),
	     Mul#(dataWidthBytes,8,dataWidth),
	     Log#(dataWidthBytes,beatShift),
	     Log#(cmdQDepth,logCmdQDepth),
	     Mul#(cmdQDepth,numServers,cmdBuffSz),
	     Log#(cmdBuffSz, cmdBuffAddrSz),
	     Log#(numServers, serverIdxSz),
	     Add#(1,logCmdQDepth, outCntSz),
	     Add#(1, c__, numServers),
	     Add#(b__, TLog#(numServers), cmdBuffAddrSz),
	     Add#(e__, TLog#(numServers), TAdd#(1, cmdBuffAddrSz)),
	     Add#(a__, serverIdxSz, cmdBuffAddrSz),
	     Min#(2,TLog#(numServers),bpc),
	     Add#(d__, TLog#(numServers), TAdd#(1, serverIdxSz)),
	     Add#(f__, serverIdxSz, 6));

   let verbose = False;

   Integer bufferSizeBeats = bufferSizeBytes/valueOf(dataWidthBytes);
   Vector#(numServers, Reg#(Bool))               outs1 <- replicateM(mkReg(False));
   Vector#(numServers, Reg#(Bit#(outCntSz)))     outs0 <- replicateM(mkReg(0));
   Vector#(numServers, ConfigCounter#(16))     buffCap <- replicateM(mkConfigCounter(fromInteger(bufferSizeBeats)));
   UGBramFifos#(numServers,cmdQDepth,MemengineCmd) cmdBuf <- mkUGBramFifos;

   Reg#(Bool) load_in_progress <- mkReg(False);
   FIFO#(Tuple3#(MemengineCmd,Bool,Bool))         loadf_b <- mkSizedFIFO(1);
   FIFO#(Tuple2#(Bit#(serverIdxSz),MemengineCmd)) loadf_c <- mkSizedFIFO(1);
   FIFO#(Tuple3#(Bit#(8),Bit#(serverIdxSz),Bool))   workf <- mkSizedBRAMFIFO(32); // isthis the right size?

   Vector#(numServers, FIFO#(void))              outfs <- replicateM(mkSizedFIFO(valueOf(cmdQDepth)));
   Vector#(numServers, FIFOF#(MemengineCmd))   cmds_in <- replicateM(mkSizedFIFOF(valueOf(cmdQDepth)));

   FIFOF#(MemData#(dataWidth))                             read_data <- mkFIFOF;
   Vector#(numServers, FIFOF#(MemData#(dataWidth)))  read_data_buffs <- replicateM(mkSizedBRAMFIFOF(bufferSizeBeats));
   function PipeOut#(Bit#(dataWidth)) check_out(PipeOut#(MemData#(dataWidth)) inpipe, Integer i) =
      (interface PipeOut;
	  method Bit#(dataWidth) first;
	     return inpipe.first.data;
	  endmethod
	  method Action deq;
	     inpipe.deq;
	     buffCap[i].increment(1);
	     if (inpipe.first.last)
		outfs[i].enq(?);
	  endmethod
	  method Bool notEmpty = inpipe.notEmpty;
       endinterface);
   Vector#(numServers, PipeOut#(Bit#(dataWidth))) read_data_pipes = zipWith(check_out, map(toPipeOut,read_data_buffs), genVector);

   Reg#(Bit#(8))                    respCnt <- mkReg(0);
   Reg#(Bit#(TAdd#(1,serverIdxSz))) loadIdx <- mkReg(0);
   let beat_shift = fromInteger(valueOf(beatShift));
   let cmd_q_depth = fromInteger(valueOf(cmdQDepth));

   function Action incr_loadIdx =
      (action
       if(loadIdx+1 >= fromInteger(valueOf(numServers)))
	  loadIdx <= 0;
       else
	  loadIdx <= loadIdx+1;
       endaction);

   for (Integer idx = 0; idx < valueOf(numServers); idx = idx + 1)
      rule store_cmd if (!outs1[idx]);
	 let cmd <- toGet(cmds_in[idx]).get();
	 outs1[idx] <= True;
	 cmdBuf.enq(fromInteger(idx),cmd);
	 if (verbose) $display("mkMemreadEngineBuff::store_cmd %d %d", idx, buffCap[idx].read);
      endrule

   rule load_ctxt_a (!load_in_progress);
      if (outs1[loadIdx]) begin
	 load_in_progress <= True;
	 cmdBuf.first_req(truncate(loadIdx));
	 if (verbose) $display("mkMemreadEngineBuff::load_ctxt_a %d", loadIdx);
      end
      else begin
	 incr_loadIdx;
      end
   endrule

   rule load_ctxt_b if (load_in_progress);
      let cmd <- cmdBuf.first_resp;
      let cond0 <- buffCap[loadIdx].maybeDecrement(unpack(extend(cmd.burstLen>>beat_shift)));
      let cond1 = cmd.len <= extend(cmd.burstLen);
      loadf_b.enq(tuple3(cmd,cond0,cond1));
      if (verbose) $display("mkMemreadEngineBuff::load_ctxt_b %d %d", buffCap[loadIdx].read(), cmd.burstLen>>beat_shift);
   endrule

   rule load_ctxt_c if (load_in_progress);
      load_in_progress <= False;
      incr_loadIdx;
      match {.cmd,.cond0,.cond1} <- toGet(loadf_b).get;
      if  (cond0) begin
	 if (verbose) $display("mkMemreadEngineBuff::load_ctxt_c %d %d", cmd.len, loadIdx);
	 let x = cmd.burstLen;
	 if (cmd.len < extend(cmd.burstLen))
	    x = truncate(cmd.len);
	 loadf_c.enq(tuple2(truncate(loadIdx),cmd));
	 if (cond1) begin
	    //$display("load_ctxt_b cond1");
	    outs1[loadIdx] <= False;
	    cmdBuf.deq(truncate(loadIdx));
	 end
	 else begin
	    let new_cmd = MemengineCmd{sglId:cmd.sglId, base:cmd.base+extend(cmd.burstLen),
				       burstLen:cmd.burstLen, len:cmd.len-extend(cmd.burstLen), tag:cmd.tag};
	    cmdBuf.upd_head(truncate(loadIdx),new_cmd);
	 end
      end
   endrule

   rule read_data_rule;
      let d <- toGet(read_data).get();
      match {.rc, .idx, .last} = workf.first;
      let new_respCnt = respCnt+1;
      let l = False;
      //$display("%h %d", d.data, idx);
      if (new_respCnt == rc) begin
	 respCnt <= 0;
	 workf.deq;
	 //$display("eob %d", idx);
	 l = last;
      end
      else begin
	 respCnt <= new_respCnt;
      end
      read_data_buffs[idx].enq(d);
   endrule

   function MemreadServer#(dataWidth) toMemreadServer(Server#(MemengineCmd,Bool) cs, PipeOut#(Bit#(dataWidth)) p) =
      (interface MemreadServer;
	  interface cmdServer = cs;
	  interface dataPipe  = p;
       endinterface);

   Vector#(numServers, Server#(MemengineCmd,Bool)) rs;
   for(Integer i = 0; i < valueOf(numServers); i=i+1)
      rs[i] = (interface Server#(MemengineCmd,Bool);
		  interface Put request;
		     method Action put(MemengineCmd cmd) if (outs0[i] < cmd_q_depth);
			Bit#(32) bsb = fromInteger(bufferSizeBytes);
`ifdef BSIM
			Bit#(32) dw = fromInteger(valueOf(dataWidthBytes));
			let mdw = ((cmd.len)/dw)*dw != cmd.len;
			let bbl = extend(cmd.burstLen) > bsb;
			if(bbl || mdw) begin
			   if (bbl)
			      $display("XXXXXXXXXX mkMemreadEngineBuff::unsupported burstLen %d %d", bsb, cmd.burstLen);
			   if (mdw)
			      $display("XXXXXXXXXX mkMemreadEngineBuff::unsupported len %d", cmd.len);
			end
			else begin
`endif
	 		   outs0[i] <= outs0[i]+1;
			   cmds_in[i].enq(cmd);
`ifdef BSIM
			end
`endif
 		     endmethod
		  endinterface
		  interface Get response;
		     method ActionValue#(Bool) get;
			outfs[i].deq;
	 		outs0[i] <= outs0[i]-1;
			return True;
		     endmethod
		  endinterface
	       endinterface);
   interface readServers = rs;
   interface MemReadClient dmaClient;
      interface Get readReq;
	 method ActionValue#(MemRequest) get();
	    match {.idx, .cmd} <- toGet(loadf_c).get;
	    Bit#(BurstLenSize) bl = cmd.burstLen;
	    let last = False;
	    if (cmd.len <= extend(bl)) begin
	       last = True;
	       bl = truncate(cmd.len);
	    end
	    workf.enq(tuple3(truncate(bl>>beat_shift), idx, last));
	    //$display("readReq %d, %h %h %h", idx, cmd.base, bl, last);
	    return MemRequest { sglId: cmd.sglId, offset: cmd.base, burstLen:bl, tag: (cmd.tag << valueOf(serverIdxSz)) | extend(idx)};
	 endmethod
      endinterface
      interface Put readData = toPut(read_data);
   endinterface
   interface dataPipes = read_data_pipes;
   interface read_servers = zipWith(toMemreadServer, rs, read_data_pipes);
endmodule