PhysAddrWidth changes

PhysAddrWidth changes

// Copyright (c) 2014 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 GetPut::*;
import Connectable :: *;
import Clocks :: *;
import FIFO::*;
import Portal::*;
import HostInterface::*;
import CtrlMux::*;
import Leds::*;
import MemTypes::*;
import MemServer::*;
import MMU::*;
import PS7LIB::*;

// generated by tool
import FMComms1Request::*;
import FMComms1Indication::*;
import MemServerRequest::*;
import MMURequest::*;
import MemServerIndication::*;
import MMUIndication::*;

// defined by user
import XilinxCells::*;
import ConnectalXilinxCells::*;

import FMComms1ADC::*;
import FMComms1DAC::*;
import FMComms1::*;
import extraXilinxCells::*;

typedef enum { FMComms1Request, FMComms1Indication, HostMemServerIndication, HostMemServerRequest, HostMMURequest, HostMMUIndication} IfcNames deriving (Eq,Bits);

interface FMComms1Pins;
   interface FMComms1ADCPins adcpins;
   interface FMComms1DACPins dacpins;
   method Bit#(1) ad9548_ref_p();
   method Bit#(1) ad9548_ref_n();

//   (* prefix="" *)
endinterface

/* clk1 is the FCLKCLK1 controlled by software */

module mkConnectalTop#(HostType host)(ConnectalTop#(PhysAddrWidth,64,FMComms1Pins,1));

   Clock clk1 = host.fclkclk[1];
   C2B ref_clk_as_bit <- mkC2B(clk1);
   Wire#(Bit#(1)) ref_clk_wire <- mkDWire(0);

   rule senddown_clk;
      ref_clk_wire <= ref_clk_as_bit.o();
   endrule

   DiffOut ref_clk <- mkxOBUFDS(ref_clk_wire);

   FMComms1ADC adc <- mkFMComms1ADC();
   FMComms1DAC dac <- mkFMComms1DAC();

   FMComms1IndicationProxy fmcomms1IndicationProxy <- mkFMComms1IndicationProxy(FMComms1Indication);
   FMComms1 fmcomms1 <- mkFMComms1(fmcomms1IndicationProxy.ifc, dac.dac, adc.adc);
   FMComms1RequestWrapper fmcomms1RequestWrapper <- mkFMComms1RequestWrapper(FMComms1Request, fmcomms1.request);

   Vector#(1,  MemReadClient#(64))   readClients = cons(fmcomms1.readDmaClient, nil);
   Vector#(1, MemWriteClient#(64))  writeClients = cons(fmcomms1.writeDmaClient, nil);
   MMUIndicationProxy hostMMUIndicationProxy <- mkMMUIndicationProxy(HostMMUIndication);
   MMU#(PhysAddrWidth) hostMMU <- mkMMU(0, True, hostMMUIndicationProxy.ifc);
   MMURequestWrapper hostMMURequestWrapper <- mkMMURequestWrapper(HostMMURequest, hostMMU.request);

   MemServerIndicationProxy hostMemServerIndicationProxy <- mkMemServerIndicationProxy(HostMemServerIndication);
   MemServer#(PhysAddrWidth,64,1) dma <- mkMemServerRW(hostMemServerIndicationProxy.ifc, readClients, writeClients, cons(hostMMU,nil));
   MemServerRequestWrapper hostMemServerRequestWrapper <- mkMemServerRequestWrapper(HostMemServerRequest, dma.request);

   Vector#(6,StdPortal) portals;
   portals[0] = fmcomms1RequestWrapper.portalIfc;
   portals[1] = fmcomms1IndicationProxy.portalIfc;
   portals[2] = hostMemServerRequestWrapper.portalIfc;
   portals[3] = hostMemServerIndicationProxy.portalIfc;
   portals[4] = hostMMURequestWrapper.portalIfc;
   portals[5] = hostMMUIndicationProxy.portalIfc;
   let ctrl_mux <- mkSlaveMux(portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = dma.masters;
   interface leds = default_leds;
   interface FMComms1Pins pins;
      interface FMCOmms1ADCPins adcpins = adc.pins;
      interface FMCOmms1ADCPins dacpins = dac.pins;
      method Bit#(1) ad9548_ref_p();
	 return(ref_clk.read_p());
      endmethod

      method Bit#(1) ad9548_ref_n();
	 return(ref_clk.read_n());
      endmethod
   endinterface
endmodule : mkConnectalTop

// Copyright (c) 2014 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.

// bsv libraries
import Vector::*;
import GetPut::*;
import Connectable :: *;
import Clocks :: *;
import FIFO::*;
import DefaultValue::*;

// portz libraries
import Portal::*;
import CtrlMux::*;
import Leds::*;
import ConnectalMemory::*;
import MemTypes::*;
import MemServer::*;
import MMU::*;
import PS7LIB::*;
import HostInterface::*;

// generated by tool
import FMComms1Request::*;
import FMComms1Indication::*;
import MemServerRequest::*;
import MMURequest::*;
import MemServerIndication::*;
import MMUIndication::*;

// defined by user
import XilinxCells::*;
import ConnectalXilinxCells::*;

import FMComms1ADC::*;
import FMComms1DAC::*;
import FMComms1::*;
import extraXilinxCells::*;

typedef enum { FMComms1Request, FMComms1Indication, HostMemServerIndication, HostMemServerRequest, HostMMURequest, HostMMUIndication} IfcNames deriving (Eq,Bits);

interface FMComms1Pins;
   interface FMComms1ADCPins adcpins;
   interface FMComms1DACPins dacpins;
   method Bit#(1) ad9548_ref_p();
   method Bit#(1) ad9548_ref_n();

//   (* prefix="" *)
endinterface

/* clk1 is the FCLKCLK1 controlled by software */

module mkConnectalTop#(HostType host)(ConnectalTop#(PhysAddrWidth,64,FMComms1Pins,1));

   Clock clk1 = host.fclkclk[1];
   C2B ref_clk_as_bit <- mkC2B(clk1);
   Wire#(Bit#(1)) ref_clk_wire <- mkDWire(0);

   rule senddown_clk;
      ref_clk_wire <= ref_clk_as_bit.o();
   endrule

   DiffOut ref_clk <- mkxOBUFDS(ref_clk_wire);

   FMComms1ADC adc <- mkFMComms1ADC();
   FMComms1DAC dac <- mkFMComms1DAC();

   FMComms1IndicationProxy fmcomms1IndicationProxy <- mkFMComms1IndicationProxy(FMComms1Indication);
   FMComms1 fmcomms1 <- mkFMComms1(fmcomms1IndicationProxy.ifc, dac.dac, adc.adc);
   FMComms1RequestWrapper fmcomms1RequestWrapper <- mkFMComms1RequestWrapper(FMComms1Request, fmcomms1.request);

   Vector#(1,  MemReadClient#(64))   readClients = cons(fmcomms1.readDmaClient, nil);
   Vector#(1, MemWriteClient#(64))  writeClients = cons(fmcomms1.writeDmaClient, nil);
   MMUIndicationProxy hostMMUIndicationProxy <- mkMMUIndicationProxy(HostMMUIndication);
   MMU#(PhysAddrWidth) hostMMU <- mkMMU(0, True, hostMMUIndicationProxy.ifc);
   MMURequestWrapper hostMMURequestWrapper <- mkMMURequestWrapper(HostMMURequest, hostMMU.request);

   MemServerIndicationProxy hostMemServerIndicationProxy <- mkMemServerIndicationProxy(HostMemServerIndication);
   MemServer#(PhysAddrWidth,64,1) dma <- mkMemServerRW(hostMemServerIndicationProxy.ifc, readClients, writeClients, cons(hostMMU,nil));
   MemServerRequestWrapper hostMemServerRequestWrapper <- mkMemServerRequestWrapper(HostMemServerRequest, dma.request);

   Vector#(6,StdPortal) portals;
   portals[0] = fmcomms1RequestWrapper.portalIfc;
   portals[1] = fmcomms1IndicationProxy.portalIfc;
   portals[2] = hostMemServerRequestWrapper.portalIfc;
   portals[3] = hostMemServerIndicationProxy.portalIfc;
   portals[4] = hostMMURequestWrapper.portalIfc;
   portals[5] = hostMMUIndicationProxy.portalIfc;
   let ctrl_mux <- mkSlaveMux(portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = dma.masters;
   interface leds = default_leds;
   interface FMComms1Pins pins;
      interface FMCOmms1ADCPins adcpins = adc.pins;
      interface FMCOmms1ADCPins dacpins = dac.pins;
      method Bit#(1) ad9548_ref_p();
	 return(ref_clk.read_p());
      endmethod

      method Bit#(1) ad9548_ref_n();
	 return(ref_clk.read_n());
      endmethod
   endinterface
endmodule : mkConnectalTop


PhysAddrWidth changes

PhysAddrWidth changes

import Vector::*;
import FIFO::*;
import Connectable::*;
import CtrlMux::*;
import Portal::*;
import HostInterface::*;
import Leds::*;
import MemPortal::*;

import TinyTestTypes::*;

// generated by tool
import Tiny3Indication::*;
import Tiny3Request::*;

// defined by user
import TinyTest::*;

typedef enum {Tiny3Indication, Tiny3Request} IfcNames deriving (Eq,Bits);

module mkConnectalTop(StdConnectalTop#(PhysAddrWidth));

   // instantiate user portals
   Tiny3IndicationProxy tiny3IndicationProxy <- mkTiny3IndicationProxy(Tiny3Indication);
   Tiny3Request tiny3Request <- mkTiny3Request(tiny3IndicationProxy.ifc);
   Tiny3RequestWrapper tiny3RequestWrapper <- mkTiny3RequestWrapper(Tiny3Request,tiny3Request);

   Vector#(2,StdPortal) portals;
   portals[0] = tiny3RequestWrapper.portalIfc;
   portals[1] = tiny3IndicationProxy.portalIfc;
   let ctrl_mux <- mkSlaveMux(portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = nil;
   interface leds = default_leds;

endmodule : mkConnectalTop

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

// portz libraries
import CtrlMux::*;
import Portal::*;
import Leds::*;
import MemTypes::*;
import MemPortal::*;

import TinyTestTypes::*;

// generated by tool
import Tiny3Indication::*;
import Tiny3Request::*;

// defined by user
import TinyTest::*;

typedef enum {Tiny3Indication, Tiny3Request} IfcNames deriving (Eq,Bits);

module mkConnectalTop(StdConnectalTop#(PhysAddrWidth));

   // instantiate user portals
   Tiny3IndicationProxy tiny3IndicationProxy <- mkTiny3IndicationProxy(Tiny3Indication);
   Tiny3Request tiny3Request <- mkTiny3Request(tiny3IndicationProxy.ifc);
   Tiny3RequestWrapper tiny3RequestWrapper <- mkTiny3RequestWrapper(Tiny3Request,tiny3Request);

   Vector#(2,StdPortal) portals;
   portals[0] = tiny3RequestWrapper.portalIfc;
   portals[1] = tiny3IndicationProxy.portalIfc;
   let ctrl_mux <- mkSlaveMux(portals);

   interface interrupt = getInterruptVector(portals);
   interface slave = ctrl_mux;
   interface masters = nil;
   interface leds = default_leds;

endmodule : mkConnectalTop


use `MemServerTags if defined

use `MemServerTags if defined

// 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 FIFOF::*;
import Adapter::*;
import Vector::*;
import Connectable::*;
import BRAMFIFO::*;
import GetPut::*;
import ClientServer::*;

import ConnectalConfig::*;
import Pipe::*;
import ConnectalMemory::*;
import DefaultValue::*;
import AxiStream::*;

`include "ConnectalProjectConfig.bsv"

typedef Bit#(32) SGLId;
`ifndef ZYNQ
typedef 40 MemOffsetSize; // must be at least as large as PhysAddrSize
`else
`ifdef ZynqUltrascale
typedef 40 MemOffsetSize; // ZynqUltrascale PhysAddrWidth=40
`else
typedef 32 MemOffsetSize;
`endif
`endif
`ifdef MemTagSize
typedef `MemTagSize MemTagSize;
`else
typedef 6 MemTagSize;
`endif
typedef `BurstLenSize BurstLenSize;

`ifdef MemServerTags
    typedef `MemServerTags MemServerTags;
`else

    `ifndef USE_ACP
	`ifdef PCIE3
	// as configured, the Xilinx gen3 PCIe core supports 5 bit tags, and
	// we need to use unique tags for all transactions in flight. Since
	// MemServer uses the same tag numbers for reads and writes, we use
	// tag[4] to distinguish the two, leaving 4 bits for unique tags.
	// TODO: There is an option for longer tags in the gen3 core.
	typedef 16 MemServerTags;
	`else
	typedef 32 MemServerTags;
	`endif
    `else
	typedef 8 MemServerTags;
    `endif
`endif // MemServerTags

`ifdef DataBusWidth
typedef TDiv#(`DataBusWidth,8) ByteEnableSize;
`else
typedef TDiv#(64,8) ByteEnableSize;
`endif

// memory request with physical addresses.
// these can be transmitted directly to the bus master
typedef struct {
   Bit#(addrWidth) addr;
   Bit#(BurstLenSize) burstLen;
   Bit#(MemTagSize) tag;
`ifdef BYTE_ENABLES
   Bit#(TDiv#(dataBusWidth,8)) firstbe; // maybe we only need lastbe
   Bit#(TDiv#(dataBusWidth,8)) lastbe;
`endif
   } PhysMemRequest#(numeric type addrWidth, numeric type dataBusWidth) deriving (Bits, Eq, FShow);

instance DefaultValue#(PhysMemRequest#(addrWidth,dataBusWidth));
   defaultValue = PhysMemRequest { addr: 0, burstLen: 0, tag: 0
`ifdef BYTE_ENABLES
				  , firstbe: maxBound, lastbe: maxBound
`endif
      };
endinstance

// memory request with "virtual" addresses.
// these need to be translated before they can be send to the bus
typedef struct {
   SGLId sglId;
   Bit#(MemOffsetSize) offset;
   Bit#(BurstLenSize) burstLen;
   Bit#(MemTagSize)  tag;
`ifdef BYTE_ENABLES
   Bit#(ByteEnableSize) firstbe; // maybe we only need lastbe
   Bit#(ByteEnableSize) lastbe;
`endif
   } MemRequest deriving (Bits, FShow);

instance DefaultValue#(MemRequest);
   defaultValue = MemRequest {
      sglId: 0, offset: 0, burstLen: 0, tag: 0
`ifdef BYTE_ENABLES
      , firstbe: maxBound, lastbe: maxBound
`endif
      };
endinstance

// memory payload
typedef struct {
   Bit#(dsz) data;
   Bit#(MemTagSize) tag;
   Bool last;
   } MemData#(numeric type dsz) deriving (Bits, Eq, FShow);

function Bit#(dsz) memDataData(MemData#(dsz) md); return md.data; endfunction

typeclass ReqByteEnables#(type t, numeric type besz);
   function Bit#(besz) reqFirstByteEnable(t req);
   function Bit#(besz) reqLastByteEnable(t req);
endtypeclass
instance ReqByteEnables#(PhysMemRequest#(addrWidth,dataBusWidth),TDiv#(dataBusWidth,8));
`ifdef BYTE_ENABLES
   function Bit#(TDiv#(dataBusWidth,8)) reqFirstByteEnable(PhysMemRequest#(addrWidth,dataBusWidth) req); return req.firstbe; endfunction
   function Bit#(TDiv#(dataBusWidth,8)) reqLastByteEnable(PhysMemRequest#(addrWidth,dataBusWidth) req); return req.lastbe; endfunction
`else
   function Bit#(TDiv#(dataBusWidth,8)) reqFirstByteEnable(PhysMemRequest#(addrWidth,dataBusWidth) req); return maxBound; endfunction
   function Bit#(TDiv#(dataBusWidth,8)) reqLastByteEnable(PhysMemRequest#(addrWidth,dataBusWidth) req); return maxBound; endfunction
`endif
endinstance
instance ReqByteEnables#(MemRequest,ByteEnableSize);
`ifdef BYTE_ENABLES
   function Bit#(ByteEnableSize) reqFirstByteEnable(MemRequest req); return req.firstbe; endfunction
   function Bit#(ByteEnableSize) reqLastByteEnable(MemRequest req); return req.lastbe; endfunction
`else
   function Bit#(ByteEnableSize) reqFirstByteEnable(MemRequest req); return maxBound; endfunction
   function Bit#(ByteEnableSize) reqLastByteEnable(MemRequest req); return maxBound; endfunction
`endif
endinstance

///////////////////////////////////////////////////////////////////////////////////
//

typedef struct {SGLId sglId;
		Bit#(32) base;
		Bit#(BurstLenSize) burstLen;
		Bit#(32) len;
		Bit#(MemTagSize) tag;
		} MemengineCmd deriving (Eq,Bits);

interface MemWriteEngineServer#(numeric type userWidth);
   interface Put#(MemengineCmd)       request;
   interface Get#(Bool)               done;
   interface PipeIn#(Bit#(userWidth)) data;
   interface PipeOut#(MemRequestCycles)     requestCycles;
endinterface

interface MemWriteEngine#(numeric type busWidth, numeric type userWidth, numeric type cmdQDepth, numeric type numServers);
   interface MemWriteClient#(busWidth) dmaClient;
   interface Vector#(numServers, MemWriteEngineServer#(userWidth)) writeServers;
endinterface

typedef struct {
   Bit#(dsz) data;
   Bit#(MemTagSize) tag;
   Bool first;
   Bool last;
   } MemDataF#(numeric type dsz) deriving (Bits);

typedef struct {
   Bit#(MemTagSize) tag;
   Bit#(32)         cycles;
   } MemRequestCycles deriving (Bits);

interface MemReadEngineServer#(numeric type userWidth);
   interface Put#(MemengineCmd)             request;
   interface PipeOut#(MemDataF#(userWidth)) data;
   interface PipeOut#(MemRequestCycles)     requestCycles;
endinterface

interface MemReadEngine#(numeric type busWidth, numeric type userWidth, numeric type cmdQDepth, numeric type numServers);
   interface MemReadClient#(busWidth) dmaClient;
   interface Vector#(numServers, MemReadEngineServer#(userWidth)) readServers;
endinterface

//
///////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////
//

interface MemReadClient#(numeric type dsz);
   interface Get#(MemRequest)    readReq;
   interface Put#(MemData#(dsz)) readData;
endinterface

interface MemWriteClient#(numeric type dsz);
   interface Get#(MemRequest)    writeReq;
   interface Get#(MemData#(dsz)) writeData;
   interface Put#(Bit#(MemTagSize))       writeDone;
endinterface

interface MemClient#(numeric type dsz);
   interface MemReadClient#(dsz) readClient;
   interface MemWriteClient#(dsz) writeClient;
endinterface

interface MemReadServer#(numeric type dsz);
   interface Put#(MemRequest) readReq;
   interface Get#(MemData#(dsz))     readData;
endinterface

interface MemWriteServer#(numeric type dsz);
   interface Put#(MemRequest) writeReq;
   interface Put#(MemData#(dsz))     writeData;
   interface Get#(Bit#(MemTagSize))           writeDone;
endinterface

interface MemServer#(numeric type dataWidth);
   interface MemReadServer#(dataWidth) readServer;
   interface MemWriteServer#(dataWidth) writeServer;
endinterface

//
///////////////////////////////////////////////////////////////////////////////////
//

interface PhysMemSlave#(numeric type addrWidth, numeric type dataWidth);
   interface PhysMemReadServer#(addrWidth, dataWidth) read_server;
   interface PhysMemWriteServer#(addrWidth, dataWidth) write_server;
endinterface

interface PhysMemMaster#(numeric type addrWidth, numeric type dataWidth);
   interface PhysMemReadClient#(addrWidth, dataWidth) read_client;
   interface PhysMemWriteClient#(addrWidth, dataWidth) write_client;
endinterface

interface PhysMemReadClient#(numeric type asz, numeric type dsz);
   interface Get#(PhysMemRequest#(asz,dsz))    readReq;
   interface Put#(MemData#(dsz)) readData;
endinterface

interface PhysMemWriteClient#(numeric type asz, numeric type dsz);
   interface Get#(PhysMemRequest#(asz,dsz))    writeReq;
   interface Get#(MemData#(dsz)) writeData;
   interface Put#(Bit#(MemTagSize))       writeDone;
endinterface

interface PhysMemReadServer#(numeric type asz, numeric type dsz);
   interface Put#(PhysMemRequest#(asz,dsz)) readReq;
   interface Get#(MemData#(dsz))     readData;
endinterface

interface PhysMemWriteServer#(numeric type asz, numeric type dsz);
   interface Put#(PhysMemRequest#(asz,dsz)) writeReq;
   interface Put#(MemData#(dsz))     writeData;
   interface Get#(Bit#(MemTagSize))           writeDone;
endinterface

//
///////////////////////////////////////////////////////////////////////////////////

instance Connectable#(MemReadClient#(dsz), MemReadServer#(dsz));
   module mkConnection#(MemReadClient#(dsz) source, MemReadServer#(dsz) sink)(Empty);
      rule mr_request;
	 let req <- source.readReq.get();
	 sink.readReq.put(req);
      endrule
      rule mr_response;
	 let resp <- sink.readData.get();
	 source.readData.put(resp);
      endrule
   endmodule
endinstance

instance Connectable#(MemWriteClient#(dsz), MemWriteServer#(dsz));
   module mkConnection#(MemWriteClient#(dsz) source, MemWriteServer#(dsz) sink)(Empty);
      rule mw_request;
	 let req <- source.writeReq.get();
	 sink.writeReq.put(req);
      endrule
      rule mw_response;
	 let resp <- source.writeData.get();
	 sink.writeData.put(resp);
      endrule
      rule mw_done;
	 let resp <- sink.writeDone.get();
	 source.writeDone.put(resp);
      endrule
   endmodule
endinstance

instance Connectable#(MemClient#(dsz), MemServer#(dsz));
   module mkConnection#(MemClient#(dsz) source, MemServer#(dsz) sink)(Empty);
      mkConnection(source.readClient, sink.readServer);
      mkConnection(source.writeClient, sink.writeServer);
   endmodule
endinstance

instance Connectable#(PhysMemMaster#(addrWidth, busWidth), PhysMemSlave#(addrWidth, busWidth));
   module mkConnection#(PhysMemMaster#(addrWidth, busWidth) m, PhysMemSlave#(addrWidth, busWidth) s)(Empty);
      mkConnection(m.read_client.readReq, s.read_server.readReq);
      mkConnection(s.read_server.readData, m.read_client.readData);
      mkConnection(m.write_client.writeReq, s.write_server.writeReq);
      mkConnection(m.write_client.writeData, s.write_server.writeData);
      mkConnection(s.write_server.writeDone, m.write_client.writeDone);
   endmodule
endinstance

// this is used for debugging MemToPcie/PcieToMem in BsimTop.bsv
instance Connectable#(PhysMemMaster#(32, busWidth), PhysMemSlave#(40, busWidth));
   module mkConnection#(PhysMemMaster#(32, busWidth) m, PhysMemSlave#(40, busWidth) s)(Empty);
      //mkConnection(m.read_client.readReq, s.read_server.readReq);
      rule readreq;
	 let req <- m.read_client.readReq.get();
	 s.read_server.readReq.put(PhysMemRequest { addr: extend(req.addr), burstLen: req.burstLen, tag: req.tag
`ifdef BYTE_ENABLES
						   , firstbe: req.firstbe, lastbe: req.lastbe
`endif
	    });
      endrule

      mkConnection(s.read_server.readData, m.read_client.readData);
      //mkConnection(m.write_client.writeReq, s.write_server.writeReq);
      rule writereq;
	 let req <- m.write_client.writeReq.get();
	 s.write_server.writeReq.put(PhysMemRequest { addr: extend(req.addr), burstLen: req.burstLen, tag: req.tag
`ifdef BYTE_ENABLES
						     , firstbe: req.firstbe, lastbe: req.lastbe
`endif
 });
      endrule
      mkConnection(m.write_client.writeData, s.write_server.writeData);
      mkConnection(s.write_server.writeDone, m.write_client.writeDone);
   endmodule
endinstance

function Bool isQuadWordAligned(Bit#(7) lower_addr);
   return (lower_addr[2:0]==3'b0);
endfunction

function Put#(t) null_put();
   return (interface Put;
              method Action put(t x) if (False);
                 noAction;
              endmethod
           endinterface);
endfunction

function Get#(t) null_get();
   return (interface Get;
              method ActionValue#(t) get() if (False);
                 return ?;
              endmethod
           endinterface);
endfunction

function  PhysMemWriteClient#(addrWidth, busWidth) null_phys_mem_write_client();
   return (interface PhysMemWriteClient;
              interface Get writeReq = null_get;
              interface Get writeData = null_get;
              interface Put writeDone = null_put;
           endinterface);
endfunction

function  PhysMemReadClient#(addrWidth, busWidth) null_phys_mem_read_client();
   return (interface PhysMemReadClient;
              interface Get readReq = null_get;
              interface Put readData = null_put;
           endinterface);
endfunction

function  MemWriteClient#(busWidth) null_mem_write_client();
   return (interface MemWriteClient;
              interface Get writeReq = null_get;
              interface Get writeData = null_get;
              interface Put writeDone = null_put;
           endinterface);
endfunction

function  MemReadClient#(busWidth) null_mem_read_client();
   return (interface MemReadClient;
              interface Get readReq = null_get;
              interface Put readData = null_put;
           endinterface);
endfunction

instance MkAxiStream#(AxiStreamMaster#(dsize), FIFOF#(MemData#(dsize)));
   module mkAxiStream#(FIFOF#(MemData#(dsize)) f)(AxiStreamMaster#(dsize));
      Wire#(Bool) readyWire <- mkDWire(False);
      Wire#(MemData#(dsize)) dataWire <- mkDWire(unpack(0));
      rule rl_data if (f.notEmpty());
	 dataWire <= f.first();
      endrule
      rule rl_deq if (readyWire && f.notEmpty);
	 f.deq();
      endrule
     method Bit#(dsize)              tdata();
	return dataWire.data;
     endmethod
     method Bit#(TDiv#(dsize,8))     tkeep(); return maxBound; endmethod
     method Bit#(1)                tlast(); return pack(dataWire.last); endmethod
     method Action                 tready(Bit#(1) v);
	readyWire <= unpack(v);
     endmethod
     method Bit#(1)                tvalid(); return pack(f.notEmpty()); endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamSlave#(dsize), FIFOF#(MemData#(dsize)));
   module mkAxiStream#(FIFOF#(MemData#(dsize)) f)(AxiStreamSlave#(dsize));
      Wire#(Bit#(dsize)) dataWire <- mkDWire(unpack(0));
      Wire#(Bit#(1))     lastWire <- mkDWire(unpack(0));
      Wire#(Bool) validWire <- mkDWire(False);
      rule enq if (validWire && f.notFull());
	 f.enq(MemData { data: dataWire, last: unpack(lastWire), tag: 0 });
      endrule
      method Action      tdata(Bit#(dsize) v);
	 dataWire <= v;
      endmethod
      method Action      tkeep(Bit#(TDiv#(dsize,8)) v); endmethod
      method Action      tlast(Bit#(1) v); endmethod
      method Bit#(1)     tready(); return pack(f.notFull()); endmethod
      method Action      tvalid(Bit#(1) v);
	 validWire <= unpack(v);
      endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamMaster#(dsize), FIFOF#(MemDataF#(dsize)));
   module mkAxiStream#(FIFOF#(MemDataF#(dsize)) f)(AxiStreamMaster#(dsize));
      Wire#(Bool) readyWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      rule rl_deq if (readyWire && f.notEmpty);
	 f.deq();
	 lastWire <= f.first().last;
      endrule
     method Bit#(dsize)              tdata();
	if (f.notEmpty())
	  return f.first().data;
	else
	  return 0;
     endmethod
     method Bit#(TDiv#(dsize,8))     tkeep(); return maxBound; endmethod
     method Bit#(1)                tlast(); return pack(lastWire); endmethod
     method Action                 tready(Bit#(1) v);
	readyWire <= unpack(v);
     endmethod
     method Bit#(1)                tvalid(); return pack(f.notEmpty()); endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamSlave#(dsize), FIFOF#(MemDataF#(dsize)));
   module mkAxiStream#(FIFOF#(MemDataF#(dsize)) f)(AxiStreamSlave#(dsize));
      Reg#(Bool) first <- mkReg(True);
      Wire#(Bit#(dsize)) dataWire <- mkDWire(unpack(0));
      Wire#(Bool) validWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      rule enq if (validWire && f.notFull());
	 f.enq(MemDataF { data: dataWire, last: lastWire, first: first, tag: 0 });
	 first <= lastWire;
      endrule
      method Action      tdata(Bit#(dsize) v);
	 dataWire <= v;
      endmethod
      method Action      tkeep(Bit#(TDiv#(dsize,8)) v); endmethod
      method Action      tlast(Bit#(1) v); lastWire <= unpack(v); endmethod
      method Bit#(1)     tready(); return pack(f.notFull()); endmethod
      method Action      tvalid(Bit#(1) v);
	 validWire <= unpack(v);
      endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamMaster#(dsize), PipeOut#(MemDataF#(dsize)));
   module mkAxiStream#(PipeOut#(MemDataF#(dsize)) f)(AxiStreamMaster#(dsize));
      Wire#(Bool) readyWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      Wire#(Bit#(dsize)) dataWire <- mkDWire(0);
      rule rl_data if (f.notEmpty());
	 dataWire <= f.first().data;
	 lastWire <= f.first().last;
      endrule
      rule rl_deq if (readyWire && f.notEmpty);
	 f.deq();
      endrule
     method Bit#(dsize)              tdata();
	return dataWire;
     endmethod
     method Bit#(TDiv#(dsize,8))     tkeep(); return maxBound; endmethod
     method Bit#(1)                tlast(); return pack(lastWire); endmethod
     method Action                 tready(Bit#(1) v);
	readyWire <= unpack(v);
     endmethod
     method Bit#(1)                tvalid(); return pack(f.notEmpty()); endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamSlave#(dsize), PipeIn#(MemDataF#(dsize)));
   module mkAxiStream#(PipeIn#(MemDataF#(dsize)) f)(AxiStreamSlave#(dsize));
      Reg#(Bool) first <- mkReg(True);
      Wire#(Bit#(dsize)) dataWire <- mkDWire(unpack(0));
      Wire#(Bool) validWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      rule enq if (validWire && f.notFull());
	 f.enq(MemDataF { data: dataWire, last: lastWire, first: first, tag: 0 });
	 first <= lastWire;
      endrule
      method Action      tdata(Bit#(dsize) v);
	 dataWire <= v;
      endmethod
      method Action      tkeep(Bit#(TDiv#(dsize,8)) v); endmethod
      method Action      tlast(Bit#(1) v); lastWire <= unpack(v); endmethod
      method Bit#(1)     tready(); return pack(f.notFull()); endmethod
      method Action      tvalid(Bit#(1) v);
	 validWire <= unpack(v);
      endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamMaster#(dsize), PipeOut#(MemData#(dsize)));
   module mkAxiStream#(PipeOut#(MemData#(dsize)) f)(AxiStreamMaster#(dsize));
      Wire#(Bool) readyWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      Wire#(Bit#(dsize)) dataWire <- mkDWire(0);
      rule rl_data if (f.notEmpty());
	 dataWire <= f.first().data;
	 lastWire <= f.first().last;
      endrule
      rule rl_deq if (readyWire && f.notEmpty);
	 f.deq();
      endrule
     method Bit#(dsize)              tdata();
	return dataWire;
     endmethod
     method Bit#(TDiv#(dsize,8))     tkeep(); return maxBound; endmethod
     method Bit#(1)                tlast(); return pack(lastWire); endmethod
     method Action                 tready(Bit#(1) v);
	readyWire <= unpack(v);
     endmethod
     method Bit#(1)                tvalid(); return pack(f.notEmpty()); endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamSlave#(dsize), PipeIn#(MemData#(dsize)));
   module mkAxiStream#(PipeIn#(MemData#(dsize)) f)(AxiStreamSlave#(dsize));
      Wire#(Bit#(dsize)) dataWire <- mkDWire(unpack(0));
      Wire#(Bool) validWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      rule enq if (validWire && f.notFull());
	 f.enq(MemData { data: dataWire, last: lastWire, tag: 0 });
      endrule
      method Action      tdata(Bit#(dsize) v);
	 dataWire <= v;
      endmethod
      method Action      tkeep(Bit#(TDiv#(dsize,8)) v); endmethod
      method Action      tlast(Bit#(1) v); lastWire <= unpack(v); endmethod
      method Bit#(1)     tready(); return pack(f.notFull()); endmethod
      method Action      tvalid(Bit#(1) v);
	 validWire <= unpack(v);
      endmethod
   endmodule
endinstance

typeclass MkPhysMemSlave#(type srctype, numeric type addrWidth, numeric type dataWidth);
   module mkPhysMemSlave#(srctype axiSlave)(PhysMemSlave#(addrWidth,dataWidth));
endtypeclass
typeclass MkPhysMemMaster#(type srctype, numeric type addrWidth, numeric type dataWidth);
   module mkPhysMemMaster#(srctype axiSlave)(PhysMemMaster#(addrWidth,dataWidth));
endtypeclass

// 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 FIFOF::*;
import Adapter::*;
import Vector::*;
import Connectable::*;
import BRAMFIFO::*;
import GetPut::*;
import ClientServer::*;

import ConnectalConfig::*;
import Pipe::*;
import ConnectalMemory::*;
import DefaultValue::*;
import AxiStream::*;

`include "ConnectalProjectConfig.bsv"

typedef Bit#(32) SGLId;
`ifndef ZYNQ
typedef 40 MemOffsetSize; // must be at least as large as PhysAddrSize
`else
`ifdef ZynqUltrascale
typedef 40 MemOffsetSize; // ZynqUltrascale PhysAddrWidth=40
`else
typedef 32 MemOffsetSize;
`endif
`endif
`ifdef MemTagSize
typedef `MemTagSize MemTagSize;
`else
typedef 6 MemTagSize;
`endif
typedef `BurstLenSize BurstLenSize;

`ifndef USE_ACP
`ifdef PCIE3
// as configured, the Xilinx gen3 PCIe core supports 5 bit tags, and
// we need to use unique tags for all transactions in flight. Since
// MemServer uses the same tag numbers for reads and writes, we use
// tag[4] to distinguish the two, leaving 4 bits for unique tags.
// TODO: There is an option for longer tags in the gen3 core.
typedef 16 MemServerTags;
`else
typedef 32 MemServerTags;
`endif
`else
typedef 8 MemServerTags;
`endif
`ifdef DataBusWidth
typedef TDiv#(`DataBusWidth,8) ByteEnableSize;
`else
typedef TDiv#(64,8) ByteEnableSize;
`endif

// memory request with physical addresses.
// these can be transmitted directly to the bus master
typedef struct {
   Bit#(addrWidth) addr;
   Bit#(BurstLenSize) burstLen;
   Bit#(MemTagSize) tag;
`ifdef BYTE_ENABLES
   Bit#(TDiv#(dataBusWidth,8)) firstbe; // maybe we only need lastbe
   Bit#(TDiv#(dataBusWidth,8)) lastbe;
`endif
   } PhysMemRequest#(numeric type addrWidth, numeric type dataBusWidth) deriving (Bits, Eq, FShow);

instance DefaultValue#(PhysMemRequest#(addrWidth,dataBusWidth));
   defaultValue = PhysMemRequest { addr: 0, burstLen: 0, tag: 0
`ifdef BYTE_ENABLES
				  , firstbe: maxBound, lastbe: maxBound
`endif
      };
endinstance

// memory request with "virtual" addresses.
// these need to be translated before they can be send to the bus
typedef struct {
   SGLId sglId;
   Bit#(MemOffsetSize) offset;
   Bit#(BurstLenSize) burstLen;
   Bit#(MemTagSize)  tag;
`ifdef BYTE_ENABLES
   Bit#(ByteEnableSize) firstbe; // maybe we only need lastbe
   Bit#(ByteEnableSize) lastbe;
`endif
   } MemRequest deriving (Bits, FShow);

instance DefaultValue#(MemRequest);
   defaultValue = MemRequest {
      sglId: 0, offset: 0, burstLen: 0, tag: 0
`ifdef BYTE_ENABLES
      , firstbe: maxBound, lastbe: maxBound
`endif
      };
endinstance

// memory payload
typedef struct {
   Bit#(dsz) data;
   Bit#(MemTagSize) tag;
   Bool last;
   } MemData#(numeric type dsz) deriving (Bits, Eq, FShow);

function Bit#(dsz) memDataData(MemData#(dsz) md); return md.data; endfunction

typeclass ReqByteEnables#(type t, numeric type besz);
   function Bit#(besz) reqFirstByteEnable(t req);
   function Bit#(besz) reqLastByteEnable(t req);
endtypeclass
instance ReqByteEnables#(PhysMemRequest#(addrWidth,dataBusWidth),TDiv#(dataBusWidth,8));
`ifdef BYTE_ENABLES
   function Bit#(TDiv#(dataBusWidth,8)) reqFirstByteEnable(PhysMemRequest#(addrWidth,dataBusWidth) req); return req.firstbe; endfunction
   function Bit#(TDiv#(dataBusWidth,8)) reqLastByteEnable(PhysMemRequest#(addrWidth,dataBusWidth) req); return req.lastbe; endfunction
`else
   function Bit#(TDiv#(dataBusWidth,8)) reqFirstByteEnable(PhysMemRequest#(addrWidth,dataBusWidth) req); return maxBound; endfunction
   function Bit#(TDiv#(dataBusWidth,8)) reqLastByteEnable(PhysMemRequest#(addrWidth,dataBusWidth) req); return maxBound; endfunction
`endif
endinstance
instance ReqByteEnables#(MemRequest,ByteEnableSize);
`ifdef BYTE_ENABLES
   function Bit#(ByteEnableSize) reqFirstByteEnable(MemRequest req); return req.firstbe; endfunction
   function Bit#(ByteEnableSize) reqLastByteEnable(MemRequest req); return req.lastbe; endfunction
`else
   function Bit#(ByteEnableSize) reqFirstByteEnable(MemRequest req); return maxBound; endfunction
   function Bit#(ByteEnableSize) reqLastByteEnable(MemRequest req); return maxBound; endfunction
`endif
endinstance

///////////////////////////////////////////////////////////////////////////////////
//

typedef struct {SGLId sglId;
		Bit#(32) base;
		Bit#(BurstLenSize) burstLen;
		Bit#(32) len;
		Bit#(MemTagSize) tag;
		} MemengineCmd deriving (Eq,Bits);

interface MemWriteEngineServer#(numeric type userWidth);
   interface Put#(MemengineCmd)       request;
   interface Get#(Bool)               done;
   interface PipeIn#(Bit#(userWidth)) data;
   interface PipeOut#(MemRequestCycles)     requestCycles;
endinterface

interface MemWriteEngine#(numeric type busWidth, numeric type userWidth, numeric type cmdQDepth, numeric type numServers);
   interface MemWriteClient#(busWidth) dmaClient;
   interface Vector#(numServers, MemWriteEngineServer#(userWidth)) writeServers;
endinterface

typedef struct {
   Bit#(dsz) data;
   Bit#(MemTagSize) tag;
   Bool first;
   Bool last;
   } MemDataF#(numeric type dsz) deriving (Bits);

typedef struct {
   Bit#(MemTagSize) tag;
   Bit#(32)         cycles;
   } MemRequestCycles deriving (Bits);

interface MemReadEngineServer#(numeric type userWidth);
   interface Put#(MemengineCmd)             request;
   interface PipeOut#(MemDataF#(userWidth)) data;
   interface PipeOut#(MemRequestCycles)     requestCycles;
endinterface

interface MemReadEngine#(numeric type busWidth, numeric type userWidth, numeric type cmdQDepth, numeric type numServers);
   interface MemReadClient#(busWidth) dmaClient;
   interface Vector#(numServers, MemReadEngineServer#(userWidth)) readServers;
endinterface

//
///////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////
//

interface MemReadClient#(numeric type dsz);
   interface Get#(MemRequest)    readReq;
   interface Put#(MemData#(dsz)) readData;
endinterface

interface MemWriteClient#(numeric type dsz);
   interface Get#(MemRequest)    writeReq;
   interface Get#(MemData#(dsz)) writeData;
   interface Put#(Bit#(MemTagSize))       writeDone;
endinterface

interface MemClient#(numeric type dsz);
   interface MemReadClient#(dsz) readClient;
   interface MemWriteClient#(dsz) writeClient;
endinterface

interface MemReadServer#(numeric type dsz);
   interface Put#(MemRequest) readReq;
   interface Get#(MemData#(dsz))     readData;
endinterface

interface MemWriteServer#(numeric type dsz);
   interface Put#(MemRequest) writeReq;
   interface Put#(MemData#(dsz))     writeData;
   interface Get#(Bit#(MemTagSize))           writeDone;
endinterface

interface MemServer#(numeric type dataWidth);
   interface MemReadServer#(dataWidth) readServer;
   interface MemWriteServer#(dataWidth) writeServer;
endinterface

//
///////////////////////////////////////////////////////////////////////////////////
//

interface PhysMemSlave#(numeric type addrWidth, numeric type dataWidth);
   interface PhysMemReadServer#(addrWidth, dataWidth) read_server;
   interface PhysMemWriteServer#(addrWidth, dataWidth) write_server;
endinterface

interface PhysMemMaster#(numeric type addrWidth, numeric type dataWidth);
   interface PhysMemReadClient#(addrWidth, dataWidth) read_client;
   interface PhysMemWriteClient#(addrWidth, dataWidth) write_client;
endinterface

interface PhysMemReadClient#(numeric type asz, numeric type dsz);
   interface Get#(PhysMemRequest#(asz,dsz))    readReq;
   interface Put#(MemData#(dsz)) readData;
endinterface

interface PhysMemWriteClient#(numeric type asz, numeric type dsz);
   interface Get#(PhysMemRequest#(asz,dsz))    writeReq;
   interface Get#(MemData#(dsz)) writeData;
   interface Put#(Bit#(MemTagSize))       writeDone;
endinterface

interface PhysMemReadServer#(numeric type asz, numeric type dsz);
   interface Put#(PhysMemRequest#(asz,dsz)) readReq;
   interface Get#(MemData#(dsz))     readData;
endinterface

interface PhysMemWriteServer#(numeric type asz, numeric type dsz);
   interface Put#(PhysMemRequest#(asz,dsz)) writeReq;
   interface Put#(MemData#(dsz))     writeData;
   interface Get#(Bit#(MemTagSize))           writeDone;
endinterface

//
///////////////////////////////////////////////////////////////////////////////////

instance Connectable#(MemReadClient#(dsz), MemReadServer#(dsz));
   module mkConnection#(MemReadClient#(dsz) source, MemReadServer#(dsz) sink)(Empty);
      rule mr_request;
	 let req <- source.readReq.get();
	 sink.readReq.put(req);
      endrule
      rule mr_response;
	 let resp <- sink.readData.get();
	 source.readData.put(resp);
      endrule
   endmodule
endinstance

instance Connectable#(MemWriteClient#(dsz), MemWriteServer#(dsz));
   module mkConnection#(MemWriteClient#(dsz) source, MemWriteServer#(dsz) sink)(Empty);
      rule mw_request;
	 let req <- source.writeReq.get();
	 sink.writeReq.put(req);
      endrule
      rule mw_response;
	 let resp <- source.writeData.get();
	 sink.writeData.put(resp);
      endrule
      rule mw_done;
	 let resp <- sink.writeDone.get();
	 source.writeDone.put(resp);
      endrule
   endmodule
endinstance

instance Connectable#(MemClient#(dsz), MemServer#(dsz));
   module mkConnection#(MemClient#(dsz) source, MemServer#(dsz) sink)(Empty);
      mkConnection(source.readClient, sink.readServer);
      mkConnection(source.writeClient, sink.writeServer);
   endmodule
endinstance

instance Connectable#(PhysMemMaster#(addrWidth, busWidth), PhysMemSlave#(addrWidth, busWidth));
   module mkConnection#(PhysMemMaster#(addrWidth, busWidth) m, PhysMemSlave#(addrWidth, busWidth) s)(Empty);
      mkConnection(m.read_client.readReq, s.read_server.readReq);
      mkConnection(s.read_server.readData, m.read_client.readData);
      mkConnection(m.write_client.writeReq, s.write_server.writeReq);
      mkConnection(m.write_client.writeData, s.write_server.writeData);
      mkConnection(s.write_server.writeDone, m.write_client.writeDone);
   endmodule
endinstance

// this is used for debugging MemToPcie/PcieToMem in BsimTop.bsv
instance Connectable#(PhysMemMaster#(32, busWidth), PhysMemSlave#(40, busWidth));
   module mkConnection#(PhysMemMaster#(32, busWidth) m, PhysMemSlave#(40, busWidth) s)(Empty);
      //mkConnection(m.read_client.readReq, s.read_server.readReq);
      rule readreq;
	 let req <- m.read_client.readReq.get();
	 s.read_server.readReq.put(PhysMemRequest { addr: extend(req.addr), burstLen: req.burstLen, tag: req.tag
`ifdef BYTE_ENABLES
						   , firstbe: req.firstbe, lastbe: req.lastbe
`endif
	    });
      endrule

      mkConnection(s.read_server.readData, m.read_client.readData);
      //mkConnection(m.write_client.writeReq, s.write_server.writeReq);
      rule writereq;
	 let req <- m.write_client.writeReq.get();
	 s.write_server.writeReq.put(PhysMemRequest { addr: extend(req.addr), burstLen: req.burstLen, tag: req.tag
`ifdef BYTE_ENABLES
						     , firstbe: req.firstbe, lastbe: req.lastbe
`endif
 });
      endrule
      mkConnection(m.write_client.writeData, s.write_server.writeData);
      mkConnection(s.write_server.writeDone, m.write_client.writeDone);
   endmodule
endinstance

function Bool isQuadWordAligned(Bit#(7) lower_addr);
   return (lower_addr[2:0]==3'b0);
endfunction

function Put#(t) null_put();
   return (interface Put;
              method Action put(t x) if (False);
                 noAction;
              endmethod
           endinterface);
endfunction

function Get#(t) null_get();
   return (interface Get;
              method ActionValue#(t) get() if (False);
                 return ?;
              endmethod
           endinterface);
endfunction

function  PhysMemWriteClient#(addrWidth, busWidth) null_phys_mem_write_client();
   return (interface PhysMemWriteClient;
              interface Get writeReq = null_get;
              interface Get writeData = null_get;
              interface Put writeDone = null_put;
           endinterface);
endfunction

function  PhysMemReadClient#(addrWidth, busWidth) null_phys_mem_read_client();
   return (interface PhysMemReadClient;
              interface Get readReq = null_get;
              interface Put readData = null_put;
           endinterface);
endfunction

function  MemWriteClient#(busWidth) null_mem_write_client();
   return (interface MemWriteClient;
              interface Get writeReq = null_get;
              interface Get writeData = null_get;
              interface Put writeDone = null_put;
           endinterface);
endfunction

function  MemReadClient#(busWidth) null_mem_read_client();
   return (interface MemReadClient;
              interface Get readReq = null_get;
              interface Put readData = null_put;
           endinterface);
endfunction

instance MkAxiStream#(AxiStreamMaster#(dsize), FIFOF#(MemData#(dsize)));
   module mkAxiStream#(FIFOF#(MemData#(dsize)) f)(AxiStreamMaster#(dsize));
      Wire#(Bool) readyWire <- mkDWire(False);
      Wire#(MemData#(dsize)) dataWire <- mkDWire(unpack(0));
      rule rl_data if (f.notEmpty());
	 dataWire <= f.first();
      endrule
      rule rl_deq if (readyWire && f.notEmpty);
	 f.deq();
      endrule
     method Bit#(dsize)              tdata();
	return dataWire.data;
     endmethod
     method Bit#(TDiv#(dsize,8))     tkeep(); return maxBound; endmethod
     method Bit#(1)                tlast(); return pack(dataWire.last); endmethod
     method Action                 tready(Bit#(1) v);
	readyWire <= unpack(v);
     endmethod
     method Bit#(1)                tvalid(); return pack(f.notEmpty()); endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamSlave#(dsize), FIFOF#(MemData#(dsize)));
   module mkAxiStream#(FIFOF#(MemData#(dsize)) f)(AxiStreamSlave#(dsize));
      Wire#(Bit#(dsize)) dataWire <- mkDWire(unpack(0));
      Wire#(Bit#(1))     lastWire <- mkDWire(unpack(0));
      Wire#(Bool) validWire <- mkDWire(False);
      rule enq if (validWire && f.notFull());
	 f.enq(MemData { data: dataWire, last: unpack(lastWire), tag: 0 });
      endrule
      method Action      tdata(Bit#(dsize) v);
	 dataWire <= v;
      endmethod
      method Action      tkeep(Bit#(TDiv#(dsize,8)) v); endmethod
      method Action      tlast(Bit#(1) v); endmethod
      method Bit#(1)     tready(); return pack(f.notFull()); endmethod
      method Action      tvalid(Bit#(1) v);
	 validWire <= unpack(v);
      endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamMaster#(dsize), FIFOF#(MemDataF#(dsize)));
   module mkAxiStream#(FIFOF#(MemDataF#(dsize)) f)(AxiStreamMaster#(dsize));
      Wire#(Bool) readyWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      rule rl_deq if (readyWire && f.notEmpty);
	 f.deq();
	 lastWire <= f.first().last;
      endrule
     method Bit#(dsize)              tdata();
	if (f.notEmpty())
	  return f.first().data;
	else
	  return 0;
     endmethod
     method Bit#(TDiv#(dsize,8))     tkeep(); return maxBound; endmethod
     method Bit#(1)                tlast(); return pack(lastWire); endmethod
     method Action                 tready(Bit#(1) v);
	readyWire <= unpack(v);
     endmethod
     method Bit#(1)                tvalid(); return pack(f.notEmpty()); endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamSlave#(dsize), FIFOF#(MemDataF#(dsize)));
   module mkAxiStream#(FIFOF#(MemDataF#(dsize)) f)(AxiStreamSlave#(dsize));
      Reg#(Bool) first <- mkReg(True);
      Wire#(Bit#(dsize)) dataWire <- mkDWire(unpack(0));
      Wire#(Bool) validWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      rule enq if (validWire && f.notFull());
	 f.enq(MemDataF { data: dataWire, last: lastWire, first: first, tag: 0 });
	 first <= lastWire;
      endrule
      method Action      tdata(Bit#(dsize) v);
	 dataWire <= v;
      endmethod
      method Action      tkeep(Bit#(TDiv#(dsize,8)) v); endmethod
      method Action      tlast(Bit#(1) v); lastWire <= unpack(v); endmethod
      method Bit#(1)     tready(); return pack(f.notFull()); endmethod
      method Action      tvalid(Bit#(1) v);
	 validWire <= unpack(v);
      endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamMaster#(dsize), PipeOut#(MemDataF#(dsize)));
   module mkAxiStream#(PipeOut#(MemDataF#(dsize)) f)(AxiStreamMaster#(dsize));
      Wire#(Bool) readyWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      Wire#(Bit#(dsize)) dataWire <- mkDWire(0);
      rule rl_data if (f.notEmpty());
	 dataWire <= f.first().data;
	 lastWire <= f.first().last;
      endrule
      rule rl_deq if (readyWire && f.notEmpty);
	 f.deq();
      endrule
     method Bit#(dsize)              tdata();
	return dataWire;
     endmethod
     method Bit#(TDiv#(dsize,8))     tkeep(); return maxBound; endmethod
     method Bit#(1)                tlast(); return pack(lastWire); endmethod
     method Action                 tready(Bit#(1) v);
	readyWire <= unpack(v);
     endmethod
     method Bit#(1)                tvalid(); return pack(f.notEmpty()); endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamSlave#(dsize), PipeIn#(MemDataF#(dsize)));
   module mkAxiStream#(PipeIn#(MemDataF#(dsize)) f)(AxiStreamSlave#(dsize));
      Reg#(Bool) first <- mkReg(True);
      Wire#(Bit#(dsize)) dataWire <- mkDWire(unpack(0));
      Wire#(Bool) validWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      rule enq if (validWire && f.notFull());
	 f.enq(MemDataF { data: dataWire, last: lastWire, first: first, tag: 0 });
	 first <= lastWire;
      endrule
      method Action      tdata(Bit#(dsize) v);
	 dataWire <= v;
      endmethod
      method Action      tkeep(Bit#(TDiv#(dsize,8)) v); endmethod
      method Action      tlast(Bit#(1) v); lastWire <= unpack(v); endmethod
      method Bit#(1)     tready(); return pack(f.notFull()); endmethod
      method Action      tvalid(Bit#(1) v);
	 validWire <= unpack(v);
      endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamMaster#(dsize), PipeOut#(MemData#(dsize)));
   module mkAxiStream#(PipeOut#(MemData#(dsize)) f)(AxiStreamMaster#(dsize));
      Wire#(Bool) readyWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      Wire#(Bit#(dsize)) dataWire <- mkDWire(0);
      rule rl_data if (f.notEmpty());
	 dataWire <= f.first().data;
	 lastWire <= f.first().last;
      endrule
      rule rl_deq if (readyWire && f.notEmpty);
	 f.deq();
      endrule
     method Bit#(dsize)              tdata();
	return dataWire;
     endmethod
     method Bit#(TDiv#(dsize,8))     tkeep(); return maxBound; endmethod
     method Bit#(1)                tlast(); return pack(lastWire); endmethod
     method Action                 tready(Bit#(1) v);
	readyWire <= unpack(v);
     endmethod
     method Bit#(1)                tvalid(); return pack(f.notEmpty()); endmethod
   endmodule
endinstance

instance MkAxiStream#(AxiStreamSlave#(dsize), PipeIn#(MemData#(dsize)));
   module mkAxiStream#(PipeIn#(MemData#(dsize)) f)(AxiStreamSlave#(dsize));
      Wire#(Bit#(dsize)) dataWire <- mkDWire(unpack(0));
      Wire#(Bool) validWire <- mkDWire(False);
      Wire#(Bool) lastWire <- mkDWire(False);
      rule enq if (validWire && f.notFull());
	 f.enq(MemData { data: dataWire, last: lastWire, tag: 0 });
      endrule
      method Action      tdata(Bit#(dsize) v);
	 dataWire <= v;
      endmethod
      method Action      tkeep(Bit#(TDiv#(dsize,8)) v); endmethod
      method Action      tlast(Bit#(1) v); lastWire <= unpack(v); endmethod
      method Bit#(1)     tready(); return pack(f.notFull()); endmethod
      method Action      tvalid(Bit#(1) v);
	 validWire <= unpack(v);
      endmethod
   endmodule
endinstance

typeclass MkPhysMemSlave#(type srctype, numeric type addrWidth, numeric type dataWidth);
   module mkPhysMemSlave#(srctype axiSlave)(PhysMemSlave#(addrWidth,dataWidth));
endtypeclass
typeclass MkPhysMemMaster#(type srctype, numeric type addrWidth, numeric type dataWidth);
   module mkPhysMemMaster#(srctype axiSlave)(PhysMemMaster#(addrWidth,dataWidth));
endtypeclass


compiles,  I am skeptical about mkxOBUFDS

// Copyright (c) 2014 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 XilinxCells::*;
import XbsvXilinxCells::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;

interface DiffOut;
   method Bit#(1) read_p();
   method Bit#(1) read_n();
endinterface

import "BVI" OBUFDS =
module mkxOBUFDS#(Wire#(Bit#(1)) i)(DiffOut);
   default_clock no_clock;
   default_reset no_reset;

   port I = i;
   method O    read_p();
   method OB    read_n();

   path(I, O);
   path(I, OB);

  schedule (read_p, read_n) CF (read_p, read_n);

endmodule: mkxOBUFDS

(* always_enabled *)
interface FMComms1DACPins;
   method Bit#(14) io_dac_data_p();
   method Bit#(14) io_dac_data_n();
endinterface

typedef struct {
   Bit#(16) data_i;
   Bit#(16) data_q;
   } OIQ deriving (Bits);

interface FMComms1DAC;
   interface FMComms1DACPins pins;
   interface PipeIn#(Vector#(2, OIQ)) dac;
endinterface

/* This module drives an Analog Devices FMComms1
 * evaluation board Digital to Analog Converter, it accepts
 * the data as a PipeIn type on the default clock.
 * The FMComms1 supplies the DAC clock as a differential pair
 *
 * Output is double data rate, with clock supplied by the FMComms1
 * Output data is 14 bits twos-complement or offset binary
 *
 * Differential outputs are converted from single ended by using Xilinx OBUFDS
 * cells. The clock is converted to single ended by an IBUFGDS cell
 *
 * DDR data is convered from SDR using ODDR cells
 * At this point, the data is a 14 bit in-phase data signal,
 * plus a 14 bit quadrature signal, interleaved
 *
 * The SDR data is a 32-bit OIQ datatype
 *
 * The 32-bit data is converted from 64-bits by a Gearbox
 *
 * Clock conversion happens 64-bits wide using a SyncBRAMFIFO, which
 * presents a PipeIn channel to the rest of the logic.
 */

module mkFMComms1DAC#(Clock clk_p, Clock clk_n)(FMComms1DAC);

   Clock def_clock <- exposeCurrentClock;
   Reset def_reset <- exposeCurrentReset;

   Clock dac_dco <- mkClockIBUFGDS(clk_p, clk_n);
   Reset dac_reset <- mkAsyncReset(3, def_reset, dac_dco);

   SyncFIFOIfc#(Vector#(2, OIQ)) outfifo <- mkSyncBRAMFIFO(128, def_clock, def_reset, dac_dco, dac_reset);

   Gearbox#(2, 1, OIQ) gb <- mkNto1Gearbox(dac_dco, dac_reset, dac_dco, dac_reset);
   ODDRParams#(Bit#(14)) oddrparams = defaultValue;
   oddrparams.ddr_clk_edge = "SAME_EDGE_PIPELINED";

   ODDR#(Bit#(14)) dac_ddr <- mkODDR(oddrparams, clocked_by dac_dco);

   Vector#(14, Wire#(Bit#(1))) dac_ddr_data <- replicateM(mkDWire(0));

   Vector#(14, DiffOut) dac_out = newVector;

   for (Integer i = 0; i < 14; i = i + 1)
      dac_out[i] <- mkxOBUFDS(dac_ddr_data[i]);

   rule senddown_gb;
      outfifo.deq();
      gb.enq(outfifo.first());
   endrule

   rule senddown_oddr;
      let d = gb.first;
      gb.deq();
      dac_ddr.d1(d[0].data_i[15:2]);
      dac_ddr.d2(d[0].data_q[15:2]);
   endrule

   function Bit#(1) foo_p(DiffOut v);
      return (v.read_p());
   endfunction

   function Bit#(1) foo_n(DiffOut v);
      return (v.read_n());
   endfunction

   function Bit#(14) get_p(Vector#(14, DiffOut) v);
      return(pack(map(foo_p, v)));
   endfunction

   function Bit#(14) get_n(Vector#(14, DiffOut) v);
      return(pack(map(foo_n, v)));
   endfunction

   interface FMComms1DACPins pins;

      method Bit#(14) io_dac_data_p();
         return(get_p(dac_out));
      endmethod

      method Bit#(14) io_dac_data_n();
         return(get_n(dac_out));
      endmethod

   endinterface

   interface PipeIn dac;

      method Action enq(Vector#(2, OIQ) v);
	 outfifo.enq(v);
      endmethod

      method Bool notFull() = outfifo.notFull;

   endinterface

endmodule

// Copyright (c) 2014 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 XilinxCells::*;
import XbsvXilinxCells::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;

interface DiffOut;
   method Action _write(Bit#(1) v);
   method Bit#(1) read_p();
   method Bit#(1) read_n();
endinterface

import "BVI" OBUFDS =
module mkxOBUFDS#(Wire#(Bit#(1)) i)(DiffOut);
   default_clock no_clock;
   default_reset no_reset;

   port I = i;
   method O    read_p();
   method OB    read_n();

   path(I, O);
   path(I, OB);

  schedule _write  SB (read_p, read_n);
  schedule _write C _write;
  schedule (read_p, read_n) CF (read_p, read_n);

endmodule: mkxOBUFDS

(* always_enabled *)
interface FMComms1DACPins;
   method Bit#(14) io_dac_data_p();
   method Bit#(14) io_dac_data_n();
endinterface

typedef struct {
   Bit#(16) data_i;
   Bit#(16) data_q;
   } IQ deriving (Bits);

interface FMComms1DAC;
   interface FMComms1DACPins pins;
   interface PipeIn#(Vector#(2, IQ)) dac;
endinterface

/* This module drives an Analog Devices FMComms1
 * evaluation board Digital to Analog Converter, it accepts
 * the data as a PipeIn type on the default clock.
 * The FMComms1 supplies the DAC clock as a differential pair
 *
 * Output is double data rate, with clock supplied by the FMComms1
 * Output data is 14 bits twos-complement or offset binary
 *
 * Differential outputs are converted from single ended by using Xilinx OBUFDS
 * cells. The clock is converted to single ended by an IBUFGDS cell
 *
 * DDR data is convered from SDR using ODDR cells
 * At this point, the data is a 14 bit in-phase data signal,
 * plus a 14 bit quadrature signal, interleaved
 *
 * The SDR data is a 32-bit IQ datatype
 *
 * The 32-bit data is converted from 64-bits by a Gearbox
 *
 * Clock conversion happens 64-bits wide using a SyncBRAMFIFO, which
 * presents a PipeIn channel to the rest of the logic.
 */

module mkFMComms1DAC#(Clock clk_p, Clock clk_n)(FMComms1DAC);

   Clock def_clock <- exposeCurrentClock;
   Reset def_reset <- exposeCurrentReset;

   Clock dac_dco <- mkClockIBUFGDS(clk_p, clk_n);
   Reset dac_reset <- mkAsyncReset(3, def_reset, dac_dco);

   SyncFIFOIfc#(Vector#(2, IQ)) outfifo <- mkSyncBRAMFIFO(128, def_clock, def_reset, dac_dco, dac_reset);

   Gearbox#(2, 1, IQ) gb <- mkNto1Gearbox(dac_dco, dac_reset, dac_dco, dac_reset);
   ODDRParams#(Bit#(14)) oddrparams = defaultValue;
   oddrparams.ddr_clk_edge = "SAME_EDGE_PIPELINED";

   ODDR#(Bit#(14)) dac_ddr <- mkODDR(oddrparams, clocked_by dac_dco);

   Vector#(14, Wire#(Bit#(1))) dac_ddr_data <= replicateM(mkDWire(0));

   Vector#(14, DiffOut) dac_out = newVector;

   for (Integer i = 0; i < 14; i = i + 1)
      dac_out[i] <- mkxOBUFDS(dac_ddr_data[i]);

   rule senddown_gb;
      outfifo.deq();
      gb.enq(outfifo.first());
   endrule

   rule senddown_oddr;
      let d = gb.first;
      gb.deq();
      dac_ddr.d1(d[0]);
      dac_ddr.d2(d[1]);
   endrule

   function Bit#(1) foo_p(DiffPair v);
      return (v.read_p());
   endfunction

   function Bit#(1) foo_n(DiffPair v);
      return (v.read_n());
   endfunction

   function Bit#(14) get_p(Vector#(14, DiffPair) v);
      return(pack(map(foo_p, v)));
   endfunction

   function Bit#(14) get_n(Vector#(14, DiffPair) v);
      return(pack(map(foo_n, v)));
   endfunction

   interface FMComms1DACPins pins;

      method Bit#(14) io_dac_data_p();
         return(get_p(dac_out));
      endmethod

      method Bit#(14) io_dac_data_n();
         return(get_n(dac_out));
      endmethod

   endinterface

   interface PipeIn dac;

      method Action enq(Vector#(2, IQ) v);
	 outfifo.enq(v);
      endmethod

      method Bool notFull() = outfifo.notFull;

   endinterface

endmodule


fixed clock domain crossing in ImageCapture example

// 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 GetPut::*;
import Connectable :: *;
import PCIE :: *; // ConnectableWithClocks
import Clocks :: *;

import GetPutWithClocks :: *;
import Zynq::*;
import Imageon::*;
import HDMI::*;
import AxiDMA::*;
import BlueScope::*;
import SensorToVideo::*;

interface CoreIndication;
    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 triggen_control_value(Bit#(32) v);
    method Action spi_rxfifo_value(Bit#(32) v);
    method Action debugind(Bit#(32) v);
endinterface

interface CoreRequest;
    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_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_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_trigger_enable(Bit#(3) 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_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);
    method Action set_debugreq(Bit#(32) v);
    method Action get_debugind();
endinterface

interface ImageCaptureIndication;
    interface CoreIndication coreIndication;
    //interface BlueScopeIndication bsIndication;
endinterface

interface ImageCaptureRequest;
   interface CoreRequest coreRequest;
   //interface BlueScopeRequest bsRequest;
   interface ImageonVita imageon;
   interface HDMI hdmi;
endinterface

module mkImageCaptureRequest#(Clock hdmi_clock,
    ImageCaptureIndication indication)(ImageCaptureRequest) provisos (Bits#(XsviData,xsviDataWidth));

    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    Reset hdmi_reset <- mkSyncReset(2, defaultReset, hdmi_clock);

    ImageonVitaController imageonVita <- mkImageonVitaController();
    ImageonControl control = imageonVita.control;
    //jcaBlueScope#(64,64) spiBlueScope <- mkBlueScope(1024);

   AxiDMA dma <- mkAxiDMA;
   WriteChan dma_debug_write_chan = dma.write.writeChannels[1];
   //BlueScope#(64,64) spiBlueScope <- mkBlueScope(32, dma_debug_write_chan);
   //module mkSyncBlueScope#(Integer samples, WriteChan wchan, Clock sClk, Reset sRst, Clock dClk, Reset dRst)(BlueScope#(dataWidth, triggerWidth))
   //BlueScopeInternal bsi <- mkBlueScopeInternal(32, dma_debug_write_chan, indication.bsIndication);

    //BlueScope#(xsviDataWidth,xsviDataWidth) xsviBlueScope <- mkBlueScope(1024);
    SensorToVideo converter <- mkSensorToVideo;
    HdmiOut hdmiOut <- mkHdmiOut(clocked_by hdmi_clock, reset_by hdmi_reset);

    mkConnection(control.rxfifo_response.get, indication.coreIndication.spi_rxfifo_value);
    mkConnection(control.xsviData, converter.in.put);
    mkConnectionWithClocks(converter.out, hdmiOut.rgb, defaultClock, defaultReset, hdmi_clock, hdmi_reset); // second reset is not used

    interface CoreRequest coreRequest;
    method Action set_spi_control(Bit#(32) v);
        control.set_spi_control(v);
    endmethod
    method Action get_spi_control();
        indication.coreIndication.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();
        indication.coreIndication.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();
        indication.coreIndication.decoder_control_value(control.get_decoder_control());
    endmethod

    method Action set_triggen_control(Bit#(32) v);
        control.set_triggen_control(v);
    endmethod
    method Action get_triggen_control();
        indication.coreIndication.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();
        control.rxfifo_request.put(32'hABBAABBA);
    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_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_trigger_enable(Bit#(3) v);
        control.set_trigger_enable(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_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
    method Action set_debugreq(Bit#(32) v);
        control.set_debugreq(v);
    endmethod
    method Action get_debugind();
        indication.coreIndication.debugind(control.get_debugind());
    endmethod

    endinterface
   //interface BlueScopeRequest bsRequest = bsi.requestIfc;
   interface ImageonVita imageon = imageonVita.host;
   interface HDMI hdmi = hdmiOut.hdmi;

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 SPI::*;
import GetPut::*;

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

interface CoreIndication;
    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 triggen_control_value(Bit#(32) v);
    method Action spi_rxfifo_value(Bit#(32) v);
    method Action debugind(Bit#(32) v);
endinterface

interface CoreRequest;
    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_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_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_trigger_enable(Bit#(3) 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_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);
    method Action set_debugreq(Bit#(32) v);
    method Action get_debugind();
endinterface

interface ImageCaptureIndication;
    interface CoreIndication coreIndication;
    interface BlueScopeIndication bsIndication;
endinterface

interface ImageCaptureRequest;
   interface CoreRequest coreRequest;
   interface BlueScopeRequest bsRequest;
   interface ImageonVita imageon;
   interface HDMI hdmi;
endinterface

module mkImageCaptureRequest#(Clock hdmi_clock,
    ImageCaptureIndication indication)(ImageCaptureRequest) provisos (Bits#(XsviData,xsviDataWidth));
    ImageonVitaController imageonVita <- mkImageonVitaController();
    ImageonControl control = imageonVita.control;
    //jcaBlueScope#(64,64) spiBlueScope <- mkBlueScope(1024);

   AxiDMA dma <- mkAxiDMA;
   WriteChan dma_debug_write_chan = dma.write.writeChannels[1];
   //BlueScope#(64,64) spiBlueScope <- mkBlueScope(32, dma_debug_write_chan);
   //module mkSyncBlueScope#(Integer samples, WriteChan wchan, Clock sClk, Reset sRst, Clock dClk, Reset dRst)(BlueScope#(dataWidth, triggerWidth))
   BlueScopeInternal bsi <- mkBlueScopeInternal(32, dma_debug_write_chan, indication.bsIndication);

    //BlueScope#(xsviDataWidth,xsviDataWidth) xsviBlueScope <- mkBlueScope(1024);
    SensorToVideo converter <- mkSensorToVideo;
    HdmiOut hdmiOut <- mkHdmiOut;

    rule rxfifo_response;
        let v <- control.rxfifo_response.get();
        indication.coreIndication.spi_rxfifo_value(v);
    endrule

    // could use mkConnection here
    rule xsviData;
        let xsviData = control.xsviData();
	converter.in.put(xsviData);
	//xsviBlueScope.dataIn(pack(xsviData), pack(xsviData));
    endrule

    rule hdmiData;
        let rgb888VideoData <- converter.out.get();
        hdmiOut.rgb.put(rgb888VideoData);
    endrule

    interface CoreRequest coreRequest;
    method Action set_spi_control(Bit#(32) v);
        control.set_spi_control(v);
    endmethod
    method Action get_spi_control();
        indication.coreIndication.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();
        indication.coreIndication.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();
        indication.coreIndication.decoder_control_value(control.get_decoder_control());
    endmethod

    method Action set_triggen_control(Bit#(32) v);
        control.set_triggen_control(v);
    endmethod
    method Action get_triggen_control();
        indication.coreIndication.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();
        control.rxfifo_request.put(32'hABBAABBA);
    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_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_trigger_enable(Bit#(3) v);
        control.set_trigger_enable(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_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
    method Action set_debugreq(Bit#(32) v);
        control.set_debugreq(v);
    endmethod
    method Action get_debugind();
        indication.coreIndication.debugind(control.get_debugind());
    endmethod

    endinterface
   interface BlueScopeRequest bsRequest = bsi.requestIfc;
   interface ImageonVita imageon = imageonVita.host;
   interface HDMI hdmi = hdmiOut.hdmi;

endmodule