clean up, moved hip_rs to PS5LIB.bsv

clean up, moved hip_rs to PS5LIB.bsv

// Copyright (c) 2014 Cornell University

// 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.

package PcieEndpointS5;

import Clocks            ::*;
import Vector            ::*;
import Connectable       ::*;
import GetPut            ::*;
import Reserved          ::*;
import TieOff            ::*;
import DefaultValue      ::*;
import DReg              ::*;
import Gearbox           ::*;
import FIFO              ::*;
import FIFOF             ::*;
import SpecialFIFOs      ::*;
import ClientServer      ::*;
import Real              ::*;

import PCIE              ::*;

`ifdef BOARD_de5
import PS5LIB            ::*;
//import PcieEndpointS5Test ::*;
`elsif BOARD_htg4
import PS4LIB            ::*;
`endif

(* always_ready, always_enabled *)
interface PciewrapPci_exp#(numeric type lanes);
(* prefix="", result="tx_p" *) method Bit#(lanes) tx_p();
(* prefix="", result="rx_p" *) method Action rx_p(Bit#(lanes) rx_p);
endinterface

(* always_ready, always_enabled *)
interface PciewrapUser#(numeric type lanes);
   interface Clock clk_out;
endinterface

(* always_ready, always_enabled *)
interface PciewrapCfg#(numeric type lanes);
   method Bit#(8) bus_number();
   method Bit#(5) device_number();
   method Bit#(3) function_number();
endinterface

////////////////////////////////////////////////////////////////////////////////
/// Interfaces
////////////////////////////////////////////////////////////////////////////////

interface PcieEndpointS5#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)   pcie;
   interface PciewrapUser#(lanes)      user;
   interface Server#(TLPData#(16), TLPData#(16)) tlp;
`ifdef VSIM
   interface PcieHipPipe pipe;
   interface PcieHipCtrl ctrl;
`endif
   interface Clock epClock125;
   interface Reset epReset125;
   interface Clock epClock250;
   interface Reset epReset250;
   interface Clock epDerivedClock;
   interface Reset epDerivedReset;
   method PciId device;
endinterface

typedef struct {
   Bit#(1)               sop;
   Bit#(1)               eop;
   Bit#(7)               hit;
   Bit#(bytes)           be;
   Bit#(TMul#(bytes, 8)) data;
} AvalonStRx#(type bytes) deriving (Bits, Eq);

typedef struct {
   Bit#(1)               sop;
   Bit#(1)               eop;
   Bit#(bytes)           be;
   Bit#(TMul#(bytes, 8)) data;
} AvalonStTx#(type bytes) deriving (Bits, Eq);

typedef 8 PcieLanes;
typedef 4 NumLeds;

//(* synthesize *)
module mkPcieEndpointS5#(Clock clk_100MHz, Clock clk_50MHz, Reset perst_n)(PcieEndpointS5#(PcieLanes));

   PCIEParams params = defaultValue;

   Clock default_clock <- exposeCurrentClock;
   Reset default_reset <- exposeCurrentReset;
   Reset reset_high <- invertCurrentReset;
   Reset npor = perst_n; //No soft reset signal from Application

`ifdef BOARD_de5
   PcieWrap#(12, 32, 128) pcie_ep <- mkPcieS5Wrap(clk_100MHz, clk_50MHz, npor, perst_n);
`elsif BOARD_htg4
   PcieWrap#(12, 32, 128) pcie_ep <- mkPcieS4Wrap(clk_100MHz, clk_50MHz, clk_100MHz, npor, perst_n);
`endif

   Clock core_clk = pcie_ep.coreclkout_hip;
   Reset core_reset = pcie_ep.core_reset;
   Reset core_resetn <- mkResetInverter(pcie_ep.core_reset, clocked_by core_clk);

   // Test Altera Application
//   PcieS5App pcie_app <- mkPcieS5App(core_clk, reset_high);
//   mkConnection(pcie_app, pcie_ep);

   Reg#(PciId) deviceReg <- mkReg(?, clocked_by core_clk, reset_by core_resetn);

   FIFOF#(AvalonStTx#(16)) fAvalonStTx <- mkBypassFIFOF(clocked_by core_clk, reset_by noReset);
   FIFOF#(AvalonStRx#(16)) fAvalonStRx <- mkBypassFIFOF(clocked_by core_clk, reset_by noReset);

   let txready = (pcie_ep.tx_st.ready != 0 && fAvalonStTx.notEmpty);

   function Bit#(2) getTxStEmpty (Bit#(16) be);
      if (be == 16'h000f || be == 16'h00ff) begin
         return 2'b1;
      end
      else begin
         return 2'b0;
      end
   endfunction

   rule drive_avalon_tx if (txready);
      let info = fAvalonStTx.first; fAvalonStTx.deq;
      pcie_ep.tx_st.valid(1);
      pcie_ep.tx_st.sop(info.sop);
      pcie_ep.tx_st.eop(info.eop);
      let txStEmpty = getTxStEmpty(info.be);
`ifdef BOARD_de5
      pcie_ep.tx_st.empty(txStEmpty);
`elsif BOARD_htg4
      pcie_ep.tx_st.empty(txStEmpty[0]);
`endif
      pcie_ep.tx_st.err(0);
      pcie_ep.tx_st.data(info.data);
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_avalon_tx2 if (!txready);
      pcie_ep.tx_st.valid(0);
      pcie_ep.tx_st.sop(0);
      pcie_ep.tx_st.eop(0);
      pcie_ep.tx_st.empty(0);
      pcie_ep.tx_st.err(0);
      pcie_ep.tx_st.data(0);
   endrule

   (* fire_when_enabled *)
   rule sink_avalon_rx if (pcie_ep.rx_st.valid != 0);
      AvalonStRx#(16) beat;
      beat.sop = pcie_ep.rx_st.sop;
      beat.eop = pcie_ep.rx_st.eop;
      beat.be  = pcie_ep.rx_st.be;
      // bar[7] is reserved for endpoints.
      beat.hit = pcie_ep.rx_st.bar[6:0];

      // 128-bit interface
      // when rx_st_empty==1, rx_st_data[63:0] are valid
      if (pcie_ep.rx_st.empty[0] == 1 && pcie_ep.rx_st.eop == 1) begin
         if (pcie_ep.rx_st.be == 16'h000f) begin
            beat.data = {96'h0, pcie_ep.rx_st.data[31:0]};
         end
         else if (pcie_ep.rx_st.be == 16'h00ff) begin
            beat.data = {64'h0, pcie_ep.rx_st.data[63:0]};
         end
         else begin
            beat.data = pcie_ep.rx_st.data;
         end
      end
      // else, rx_st_data[127:0] are valid
      else begin
         beat.data = pcie_ep.rx_st.data;
      end
      // 256-bit interface requires a more complex decoder.
      fAvalonStRx.enq(beat);
   endrule

   rule pertick1;
      pcie_ep.rx_st.ready(pack(fAvalonStRx.notFull));
      //pcie_ep.hip_rst.core_ready(pcie_ep.hip_rst.serdes_pll_locked);
   endrule

   rule capture_deviceid(pcie_ep.tl_cfg.add == 4'hF);
      deviceReg <= PciId {bus: pcie_ep.tl_cfg.ctl[12:5],
                          dev: pcie_ep.tl_cfg.ctl[4:0],
                          func: 0};
   endrule

   // The PCIE endpoint is processing TLPData#(16)s at 125MHz.  The
   // AXI bridge is accepting TLPData#(16)s at 125 MHz. For gen1 and
   // gen2, there is no need for gearbox conversion.
   // coreclkout_hip depends on link width, data rate and width of APP/TL interface
   // Link Width  |  Link Rate  |   Avalon Interface Width  |  coreclkout_hip
   //     x8            gen1                128 bit               125 Mhz
   //     x8            gen2                128 bit               250 Mhz
   //     x8            gen3                256 bit               250 Mhz
   Server#(TLPData#(16), TLPData#(16)) tlp16 = (interface Server;
      interface Put request;
         method Action put(TLPData#(16) data);
            fAvalonStTx.enq(AvalonStTx {
               eop: pack(data.eof),
               sop: pack(data.sof),
               be:  dwordSwap128BE(data.be),
               data: dwordSwap128(data.data)
            });
         endmethod
      endinterface
      interface Get response;
         method ActionValue#(TLPData#(16)) get();
            let info <- toGet(fAvalonStRx).get;
            TLPData#(16) retval = defaultValue;
            retval.sof = (info.sop == 1);
            retval.eof = (info.eop == 1);
            retval.be  = dwordSwap128BE(info.be);
            retval.hit = info.hit;
            retval.data = dwordSwap128(info.data);
            return retval;
         endmethod
      endinterface
   endinterface);

   method PciId device = deviceReg;

   interface PciewrapUser user;
      method Clock clk_out();
         return core_clk;
      endmethod
   endinterface

   interface PciewrapPci_exp pcie;
      Bit#(PcieLanes) vt = pack(pcie_ep.tx.out);
      method Bit#(PcieLanes) tx_p();
         return vt;
      endmethod
      method Action rx_p(Bit#(PcieLanes) v);
         action
            pcie_ep.rx.in(unpack(v));
         endaction
      endmethod
   endinterface

   interface tlp = tlp16;
   //FIXME: verify epClock250 is needed.
   interface Clock epClock250 = core_clk;
   interface Clock epReset250 = core_resetn;
   interface Clock epClock125 = core_clk;
   interface Clock epReset125 = core_resetn;

   //FIXME: verify derivedClock value
   interface Clock epDerivedClock = core_clk;
   interface Reset epDerivedReset = core_resetn;

`ifdef VSIM
   interface pipe = pcie_ep.hip_pipe;
   interface ctrl = pcie_ep.hip_ctrl;
`endif

endmodule: mkPcieEndpointS5

endpackage: PcieEndpointS5

// Copyright (c) 2014 Cornell University

// 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.

package PcieEndpointS5;

import Clocks            ::*;
import Vector            ::*;
import Connectable       ::*;
import GetPut            ::*;
import Reserved          ::*;
import TieOff            ::*;
import DefaultValue      ::*;
import DReg              ::*;
import Gearbox           ::*;
import FIFO              ::*;
import FIFOF             ::*;
import SpecialFIFOs      ::*;
import ClientServer      ::*;
import Real              ::*;

import PCIE              ::*;
import PS5LIB            ::*;
import PcieEndpointS5Test ::*;

(* always_ready, always_enabled *)
interface PciewrapPci_exp#(numeric type lanes);
(* prefix="", result="tx_p" *) method Bit#(lanes) tx_p();
(* prefix="", result="rx_p" *) method Action rx_p(Bit#(lanes) rx_p);
endinterface

(* always_ready, always_enabled *)
interface PciewrapUser#(numeric type lanes);
   interface Clock clk_out;
   interface Reset reset_out;
   method Bit#(1) lnk_up();
   method Bit#(1) app_rdy();
endinterface

(* always_ready, always_enabled *)
interface PciewrapCfg#(numeric type lanes);
   method Bit#(8) bus_number();
   method Bit#(5) device_number();
   method Bit#(3) function_number();
endinterface

////////////////////////////////////////////////////////////////////////////////
/// Interfaces
////////////////////////////////////////////////////////////////////////////////

interface PcieEndpointS5#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)   pcie;
   interface PciewrapUser#(lanes)      user;
   interface Server#(TLPData#(16), TLPData#(16)) tlp;
`ifdef VSIM
   interface PcieS5HipPipe pipe;
   interface PcieS5HipCtrl ctrl;
`endif
   interface Clock epClock125;
   interface Reset epReset125;
   interface Clock epClock250;
   interface Reset epReset250;
   interface Clock epDerivedClock;
   interface Reset epDerivedReset;
   method PciId device;
endinterface

typedef struct {
   Bit#(1)               sop;
   Bit#(1)               eop;
   Bit#(7)               hit;
   Bit#(bytes)           be;
   Bit#(TMul#(bytes, 8)) data;
} AvalonStRx#(type bytes) deriving (Bits, Eq);

typedef struct {
   Bit#(1)               sop;
   Bit#(1)               eop;
   Bit#(bytes)           be;
   Bit#(TMul#(bytes, 8)) data;
} AvalonStTx#(type bytes) deriving (Bits, Eq);

`ifdef BOARD_de5
typedef 8 PcieLanes;
typedef 4 NumLeds;
`elsif BOARD_vsim
typedef 8 PcieLanes;
typedef 4 NumLeds;
`endif

//(* synthesize *)
module mkPcieEndpointS5#(Clock clk_100MHz, Clock clk_50MHz, Reset perst_n)(PcieEndpointS5#(PcieLanes));

   PCIEParams params = defaultValue;

   Clock default_clock <- exposeCurrentClock;
   Reset default_reset <- exposeCurrentReset;
   Reset reset_high <- invertCurrentReset;
   Reset npor = perst_n; //No soft reset signal from Application

   PcieS5Wrap#(12, 32, 128) pcie_ep <- mkPcieS5Wrap(clk_100MHz, clk_50MHz, npor, perst_n);

   Clock core_clk = pcie_ep.coreclkout_hip;
   Reset core_reset = pcie_ep.core_reset;
   Reset core_resetn <- mkResetInverter(pcie_ep.core_reset, clocked_by core_clk);

   // Test Altera Application
//   PcieS5App pcie_app <- mkPcieS5App(core_clk, reset_high);
//   mkConnection(pcie_app, pcie_ep);

   AlteraPcieHipRs hip_rs <- mkAlteraPcieHipRs(core_clk, core_resetn);

   Reg#(PciId) deviceReg <- mkReg(?, clocked_by core_clk, reset_by core_resetn);

   FIFOF#(AvalonStTx#(16)) fAvalonStTx <- mkBypassFIFOF(clocked_by core_clk, reset_by noReset);
   FIFOF#(AvalonStRx#(16)) fAvalonStRx <- mkBypassFIFOF(clocked_by core_clk, reset_by noReset);

   let txready = (pcie_ep.tx_st.ready != 0 && fAvalonStTx.notEmpty);

   function Bit#(2) getTxStEmpty (Bit#(16) be);
      if (be == 16'h000f || be == 16'h00ff) begin
         return 2'b1;
      end
      else begin
         return 2'b0;
      end
   endfunction

   rule drive_avalon_tx if (txready);
      let info = fAvalonStTx.first; fAvalonStTx.deq;
      pcie_ep.tx_st.valid(1);
      pcie_ep.tx_st.sop(info.sop);
      pcie_ep.tx_st.eop(info.eop);
      let txStEmpty = getTxStEmpty(info.be);
      pcie_ep.tx_st.empty(txStEmpty);
      pcie_ep.tx_st.err(0);
      pcie_ep.tx_st.data(info.data);
   endrule

   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_avalon_tx2 if (!txready);
      pcie_ep.tx_st.valid(0);
      pcie_ep.tx_st.sop(0);
      pcie_ep.tx_st.eop(0);
      pcie_ep.tx_st.empty(0);
      pcie_ep.tx_st.err(0);
      pcie_ep.tx_st.data(0);
   endrule

   (* fire_when_enabled *)
   rule sink_avalon_rx if (pcie_ep.rx_st.valid != 0);
      AvalonStRx#(16) beat;
      beat.sop = pcie_ep.rx_st.sop;
      beat.eop = pcie_ep.rx_st.eop;
      beat.be  = pcie_ep.rx_specific.be;
      // bar[7] is reserved for endpoints.
      beat.hit = pcie_ep.rx_specific.bar[6:0];

      // 128-bit interface
      // when rx_st_empty==1, rx_st_data[63:0] are valid
      if (pcie_ep.rx_st.empty[0] == 1 && pcie_ep.rx_st.eop == 1) begin
         if (pcie_ep.rx_specific.be == 16'h000f) begin
            beat.data = {96'h0, pcie_ep.rx_st.data[31:0]};
         end
         else if (pcie_ep.rx_specific.be == 16'h00ff) begin
            beat.data = {64'h0, pcie_ep.rx_st.data[63:0]};
         end
         else begin
            beat.data = pcie_ep.rx_st.data;
         end
      end
      // else, rx_st_data[127:0] are valid
      else begin
         beat.data = pcie_ep.rx_st.data;
      end
      // 256-bit interface requires a more complex decoder.
      fAvalonStRx.enq(beat);
   endrule

   rule pertick1;
      pcie_ep.rx_st.ready(pack(fAvalonStRx.notFull));
      pcie_ep.hip_rst.core_ready(pcie_ep.hip_rst.serdes_pll_locked);
   endrule

   rule capture_deviceid(pcie_ep.tl.cfg_add == 4'hF);
      deviceReg <= PciId {bus: pcie_ep.tl.cfg_ctl[12:5],
                          dev: pcie_ep.tl.cfg_ctl[4:0],
                          func: 0};
   endrule

   rule pertick3;
      hip_rs.dlup_exit(pcie_ep.hip_status.dlup_exit);
      hip_rs.hotrst_exit(pcie_ep.hip_status.hotrst);
      hip_rs.l2_exit(pcie_ep.hip_status.l2_exit);
      hip_rs.ltssm(pcie_ep.hip_status.ltssmstate);
   endrule

   // The PCIE endpoint is processing TLPData#(16)s at 125MHz.  The
   // AXI bridge is accepting TLPData#(16)s at 125 MHz. For gen1 and
   // gen2, there is no need for gearbox conversion.
   // coreclkout_hip depends on link width, data rate and width of APP/TL interface
   // Link Width  |  Link Rate  |   Avalon Interface Width  |  coreclkout_hip
   //     x8            gen1                128 bit               125 Mhz
   //     x8            gen2                128 bit               250 Mhz
   //     x8            gen3                256 bit               250 Mhz
   Server#(TLPData#(16), TLPData#(16)) tlp16 = (interface Server;
      interface Put request;
         method Action put(TLPData#(16) data);
            fAvalonStTx.enq(AvalonStTx {
               eop: pack(data.eof),
               sop: pack(data.sof),
               be:  dwordSwap128BE(data.be),
               data: dwordSwap128(data.data)
            });
         endmethod
      endinterface
      interface Get response;
         method ActionValue#(TLPData#(16)) get();
            let info <- toGet(fAvalonStRx).get;
            TLPData#(16) retval = defaultValue;
            retval.sof = (info.sop == 1);
            retval.eof = (info.eop == 1);
            retval.be  = dwordSwap128BE(info.be);
            retval.hit = info.hit;
            retval.data = dwordSwap128(info.data);
            return retval;
         endmethod
      endinterface
   endinterface);

   method PciId device = deviceReg;

   interface PciewrapUser user;
      method Reset reset_out;
         return hip_rs.app_rstn;
      endmethod
      method Clock clk_out();
         return core_clk;
      endmethod
      method Bit#(1) lnk_up();
         return pcie_ep.hip_rst.serdes_pll_locked;
      endmethod
      method Bit#(1) app_rdy();
         return pcie_ep.hip_rst.pld_clk_inuse;
      endmethod
   endinterface

   interface PciewrapPci_exp pcie;
      Bit#(PcieLanes) vt = pack(pcie_ep.tx.out);
      method Bit#(PcieLanes) tx_p();
         return vt;
      endmethod
      method Action rx_p(Bit#(PcieLanes) v);
         action
            pcie_ep.rx.in(unpack(v));
         endaction
      endmethod
   endinterface

   interface tlp = tlp16;
   //FIXME: verify epClock250 is needed.
   interface Clock epClock250 = core_clk;
   interface Clock epReset250 = core_resetn;
   interface Clock epClock125 = core_clk;
   interface Clock epReset125 = core_resetn;

   //FIXME: verify derivedClock value
   interface Clock epDerivedClock = core_clk;
   interface Reset epDerivedReset = core_resetn;

`ifdef VSIM
   interface pipe = pcie_ep.hip_pipe;
   interface ctrl = pcie_ep.hip_ctrl;
`endif

endmodule: mkPcieEndpointS5

endpackage: PcieEndpointS5


the Zynq I2C controller needs the SCL input connected

Change-Id: I8b7493500525ad126c833b7896ae5d8045117c55

// 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 Clocks :: *;
import Vector            :: *;
import Connectable       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiMasterSlave    :: *;
import AxiDma            :: *;
import XilinxCells       :: *;
import XbsvXilinxCells   :: *;
import PS7LIB::*;
import PPS7LIB::*;
import XADC::*;
import FIFOF::*;
import HDMI::*;
import Imageon::*;
import ConnectableWithTrace::*;
import CtrlMux::*;
import TriState::*;

interface I2C_Pins;
   interface Inout#(Bit#(1)) scl;
   interface Inout#(Bit#(1)) sda;
endinterface

//`define TRACE_AXI
//`define AXI_READ_TIMING

(* always_ready, always_enabled *)
interface ZynqTop#(type pins);
   (* prefix="" *)
   interface ZynqPins zynq;
   (* prefix="GPIO" *)
   interface LEDS             leds;
   (* prefix="XADC" *)
   interface XADC             xadc;
   (* prefix="I2C" *)
   interface I2C_Pins         i2c;
   (* prefix="" *)
   interface pins             pins;
   interface Vector#(4, Clock) unused_clock;
   interface Vector#(4, Reset) unused_reset;
endinterface

typedef (function Module#(PortalTop#(32, 64, ipins)) mkpt(Clock clock200, Clock io_vita_clk)) MkPortalTop#(type ipins);

module [Module] mkZynqTopFromPortal#(Clock fmc_video_clk1, MkPortalTop#(ipins) constructor)(ZynqTop#(ipins));
   PS7 ps7 <- mkPS7();
   Clock mainclock = ps7.fclkclk[0];
   Reset mainreset = ps7.fclkreset[0];

   let tscl <- mkTriState(unpack(ps7.i2c[1].scltn), ps7.i2c[1].sclo, clocked_by mainclock, reset_by mainreset);
   let tsda <- mkTriState(unpack(ps7.i2c[1].sdatn), ps7.i2c[1].sdao, clocked_by mainclock, reset_by mainreset);
   rule sdai;
      ps7.i2c[1].sdai(tsda);
      ps7.i2c[1].scli(tscl);
   endrule

   Clock fmc_video_clk1_buf <- mkClockBUFG(clocked_by fmc_video_clk1);
   let top <- constructor(ps7.fclkclk[3], fmc_video_clk1_buf, clocked_by mainclock, reset_by mainreset);

   //mkConnection(ps7.m_axi_gp[0].client, top.ctrl);
   //mkConnectionWithTrace(top.m_axi, ps7.s_axi_hp[0].axi.server);
   Axi3Slave#(32,32,12) ctrl <- mkAxiDmaSlave(top.slave);
   mkConnection(ps7.m_axi_gp[0].client, ctrl, clocked_by mainclock, reset_by mainreset);
   Axi3Master#(32,64,6) m_axi <- mkAxiDmaMaster(top.master, clocked_by mainclock, reset_by mainreset);
   mkConnectionWithTrace(m_axi, ps7.s_axi_hp[0].axi.server, clocked_by mainclock, reset_by mainreset);

   let intr_mux <- mkInterruptMux(top.interrupt);
   rule send_int_rule;
      ps7.interrupt(pack(intr_mux));
   endrule

   interface zynq = ps7.pins;
   interface leds = top.leds;
   interface XADC xadc;
       method Bit#(4) gpio;
           return 0;
       endmethod
   endinterface

    interface I2C_Pins i2c;
       interface Inout scl = tscl.io;
       interface Inout sda = tsda.io;
    endinterface

   interface pins = top.pins;

   // these are exported to make bsc happy, and then the ports are disconnected after synthesis
   interface unused_clock = ps7.fclkclk;
   interface unused_reset = ps7.fclkreset;
endmodule

module mkImageonZynqTop#(Clock fmc_video_clk1)(ZynqTop#(ImageCapturePins));
   let top <- mkZynqTopFromPortal(fmc_video_clk1, mkPortalTop);
   return top;
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 Clocks :: *;
import Vector            :: *;
import Connectable       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import AxiMasterSlave    :: *;
import AxiDma            :: *;
import XilinxCells       :: *;
import XbsvXilinxCells   :: *;
import PS7LIB::*;
import PPS7LIB::*;
import XADC::*;
import FIFOF::*;
import HDMI::*;
import Imageon::*;
import ConnectableWithTrace::*;
import CtrlMux::*;
import TriState::*;

interface I2C_Pins;
   interface Inout#(Bit#(1)) scl;
   interface Inout#(Bit#(1)) sda;
endinterface

//`define TRACE_AXI
//`define AXI_READ_TIMING

(* always_ready, always_enabled *)
interface ZynqTop#(type pins);
   (* prefix="" *)
   interface ZynqPins zynq;
   (* prefix="GPIO" *)
   interface LEDS             leds;
   (* prefix="XADC" *)
   interface XADC             xadc;
   (* prefix="I2C" *)
   interface I2C_Pins         i2c;
   (* prefix="" *)
   interface pins             pins;
   interface Vector#(4, Clock) unused_clock;
   interface Vector#(4, Reset) unused_reset;
endinterface

typedef (function Module#(PortalTop#(32, 64, ipins)) mkpt(Clock clock200, Clock io_vita_clk)) MkPortalTop#(type ipins);

module [Module] mkZynqTopFromPortal#(Clock fmc_video_clk1, MkPortalTop#(ipins) constructor)(ZynqTop#(ipins));
   PS7 ps7 <- mkPS7();
   Clock mainclock = ps7.fclkclk[0];
   Reset mainreset = ps7.fclkreset[0];

   let tscl <- mkTriState(unpack(ps7.i2c[1].scltn), ps7.i2c[1].sclo, clocked_by mainclock, reset_by mainreset);
   let tsda <- mkTriState(unpack(ps7.i2c[1].sdatn), ps7.i2c[1].sdao, clocked_by mainclock, reset_by mainreset);
   rule sdai;
      ps7.i2c[1].sdai(tsda);
   endrule

   Clock fmc_video_clk1_buf <- mkClockBUFG(clocked_by fmc_video_clk1);
   let top <- constructor(ps7.fclkclk[3], fmc_video_clk1_buf, clocked_by mainclock, reset_by mainreset);

   //mkConnection(ps7.m_axi_gp[0].client, top.ctrl);
   //mkConnectionWithTrace(top.m_axi, ps7.s_axi_hp[0].axi.server);
   Axi3Slave#(32,32,12) ctrl <- mkAxiDmaSlave(top.slave);
   mkConnection(ps7.m_axi_gp[0].client, ctrl, clocked_by mainclock, reset_by mainreset);
   Axi3Master#(32,64,6) m_axi <- mkAxiDmaMaster(top.master, clocked_by mainclock, reset_by mainreset);
   mkConnectionWithTrace(m_axi, ps7.s_axi_hp[0].axi.server, clocked_by mainclock, reset_by mainreset);

   let intr_mux <- mkInterruptMux(top.interrupt);
   rule send_int_rule;
      ps7.interrupt(pack(intr_mux));
   endrule

   interface zynq = ps7.pins;
   interface leds = top.leds;
   interface XADC xadc;
       method Bit#(4) gpio;
           return 0;
       endmethod
   endinterface

    interface I2C_Pins i2c;
       interface Inout scl = tscl.io;
       interface Inout sda = tsda.io;
    endinterface

   interface pins = top.pins;

   // these are exported to make bsc happy, and then the ports are disconnected after synthesis
   interface unused_clock = ps7.fclkclk;
   interface unused_reset = ps7.fclkreset;
endmodule

module mkImageonZynqTop#(Clock fmc_video_clk1)(ZynqTop#(ImageCapturePins));
   let top <- mkZynqTopFromPortal(fmc_video_clk1, mkPortalTop);
   return top;
endmodule


update HdmiDisplay.bsv to match current DMA interfaces and portal structure

Change-Id: I009d39586230e5365cf97bfb0c785f0c9a532675

// Copyright (c) 2012 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 FIFOF::*;
import Clocks::*;
import GetPut::*;
import GetPutF::*;
import PCIE::*;
import GetPutWithClocks::*;
import Connectable::*;
import PortalMemory::*;
import Dma::*;
import DmaUtils::*;
import AxiMasterSlave::*;
import HDMI::*;
import XADC::*;
import YUV::*;

interface HdmiControlRequest;
    method Action startFrameBuffer0(Int#(32) base);
endinterface

interface HdmiDisplay;
    interface HdmiControlRequest controlRequest;
    interface HdmiInternalRequest internalRequest;
    interface DmaReadClient#(64) dmaClient;
    interface HDMI hdmi;
    interface XADC xadc;
endinterface

module mkHdmiDisplay#(Clock processing_system7_1_fclk_clk1,
		      HdmiInternalIndication hdmiInternalIndication)(HdmiDisplay);
    Clock defaultClock <- exposeCurrentClock;
    Reset defaultReset <- exposeCurrentReset;
    Clock hdmi_clock = processing_system7_1_fclk_clk1;
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);
    Reg#(Bool) sendVsyncIndication <- mkReg(False);
    SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, defaultClock);
    Reg#(Bit#(1)) bozobit <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
    Reg#(Bit#(8)) segmentIndexReg <- mkReg(0);
    Reg#(Bit#(24)) segmentOffsetReg <- mkReg(0);

    Reg#(DmaPointer) referenceReg <- mkReg(-1);
    Reg#(Bit#(40)) streamRdOff <- mkReg(0);

    HdmiGenerator hdmiGen <- mkHdmiGenerator(defaultClock, defaultReset,
					     vsyncPulse, hdmiInternalIndication, clocked_by hdmi_clock, reset_by hdmi_reset);

    DmaReadBuffer#(64, 1) dmaReadBuffer <- mkDmaReadBuffer();
    rule readReq if(referenceReg >= 0);
        streamRdOff <= streamRdOff + 16*8;
        dmaReadBuffer.dmaServer.readReq.put(DmaRequest {pointer: referenceReg, offset: streamRdOff, burstLen: 16, tag: 0});
    endrule
   PutF#(DmaData#(64)) sink = (interface PutF;
      method Action put(DmaData#(64) dmadata);
         hdmiGen.request.put(dmadata.data);
      endmethod
      endinterface);
    mkConnectionWithClocks(dmaReadBuffer.dmaServer.readData, sink, defaultClock, defaultReset, hdmi_clock, hdmi_reset);

    rule vsyncrule if (vsyncPulse.pulse() && referenceReg >= 0);
       streamRdOff <= 0;
    endrule

    rule bozobit_rule;
        bozobit <= ~bozobit;
    endrule

    interface HdmiControlRequest controlRequest;
	method Action startFrameBuffer0(Int#(32) base);
	    $display("startFrameBuffer %h", base);
            referenceReg <= truncate(pack(base));
	    hdmiGen.control.setTestPattern(0);
	endmethod
    endinterface: controlRequest

    interface DmaReadClient dmaClient = dmaReadBuffer.dmaClient;
    interface HDMI hdmi = hdmiGen.hdmi;
    interface HdmiInternalRequest internalRequest = hdmiGen.control;
    interface XADC xadc;
        method Bit#(4) gpio;
            return { bozobit, hdmiGen.hdmi.vsync,
                hdmiGen.hdmi.data[8], hdmiGen.hdmi.data[0]};
                //hdmiGen.hdmi.hsync, hdmi_de};
        endmethod
    endinterface: xadc
endmodule

// Copyright (c) 2012 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 FIFOF::*;
import Clocks::*;
import GetPut::*;
import PCIE::*;
import GetPutWithClocks::*;
import Connectable::*;
import PortalMemory::*;
import Dma::*;
import AxiDma::*;
import AxiMasterSlave::*;
import HDMI::*;
import XADC::*;
import YUV::*;

interface HdmiControlRequest;
    method Action startFrameBuffer0(Int#(32) base);
endinterface
interface HdmiControlIndication;
endinterface

interface HdmiDisplayRequest;
    interface HdmiControlRequest coreRequest;
    interface HdmiInternalRequest coRequest;
    interface DmaConfig dmaRequest;
    interface Axi3Master#(40,64,6) m_axi;
    interface HDMI hdmi;
    interface XADC xadc;
endinterface
interface HdmiDisplayIndication;
    interface HdmiControlIndication coreIndication;
    interface HdmiInternalIndication coIndication;
    interface DmaIndication dmaIndication;
endinterface

module mkHdmiDisplayRequest#(Clock processing_system7_1_fclk_clk1, HdmiDisplayIndication indication)(HdmiDisplayRequest);
    Clock defaultClock <- exposeCurrentClock;
    Reset defaultReset <- exposeCurrentReset;
    Clock hdmi_clock = processing_system7_1_fclk_clk1;
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);
    Reg#(Bool) sendVsyncIndication <- mkReg(False);
    SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, defaultClock);
    Reg#(Bit#(1)) bozobit <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
    Reg#(Bit#(8)) segmentIndexReg <- mkReg(0);
    Reg#(Bit#(24)) segmentOffsetReg <- mkReg(0);
`ifdef BSIM
    BsimDma#(Bit#(64))    dma <- mkBsimDma(indication.dmaIndication);
`else
    AxiDma#(Bit#(64))     dma <- mkAxiDma(indication.dmaIndication);
`endif
    ReadChan#(Bit#(64)) dma_stream_read_chan = dma.read.readChannels[0];
    Reg#(Int#(32)) referenceReg <- mkReg(-1);
    Reg#(Bit#(40)) streamRdOff <- mkReg(0);

    HdmiGenerator hdmiGen <- mkHdmiGenerator(defaultClock, defaultReset,
        vsyncPulse, indication.coIndication, clocked_by hdmi_clock, reset_by hdmi_reset);

    rule readReq if(referenceReg >= 0);
        streamRdOff <= streamRdOff + 1;
        dma_stream_read_chan.readReq.put(streamRdOff);
    endrule
    mkConnectionWithClocks(dma_stream_read_chan.readData, hdmiGen.request, defaultClock, defaultReset, hdmi_clock, hdmi_reset);

    rule vsyncrule if (vsyncPulse.pulse() && referenceReg >= 0);
        dma.request.configChan(Read, 0, pack(referenceReg), 16);
    endrule

    rule bozobit_rule;
        bozobit <= ~bozobit;
    endrule

    interface HdmiControlRequest coreRequest;
	method Action startFrameBuffer0(Int#(32) base);
	    $display("startFrameBuffer %h", base);
            referenceReg <= base;
	    hdmiGen.control.setTestPattern(0);
	endmethod
    endinterface: coreRequest

`ifndef BSIM
    interface Axi3Master m_axi = dma.m_axi;
`endif
    interface DmaConfig dmaRequest = dma.request;
    interface HDMI hdmi = hdmiGen.hdmi;
    interface HdmiInternalRequest coRequest = hdmiGen.control;
    interface XADC xadc;
        method Bit#(4) gpio;
            return { bozobit, hdmiGen.hdmi.vsync,
                hdmiGen.hdmi.data[8], hdmiGen.hdmi.data[0]};
                //hdmiGen.hdmi.hsync, hdmi_de};
        endmethod
    endinterface: xadc
endmodule


use a regular SizedFIFO for shorter critical path

// 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.

// BSV Libraries
import BRAMFIFO::*;
import FIFO::*;
import FIFOF::*;
import Vector::*;
import GetPut::*;
import ClientServer::*;
import Assert::*;
import BRAM::*;
import DefaultValue::*;

// CONNECTAL Libraries
import MemTypes::*;
import ConnectalMemory::*;
import ConnectalClocks::*;
import MMU::*;
import ConnectalCompletionBuffer::*;

typedef 32 BeatCountSize;

typedef 9 MMU_PIPELINE_DEPTH;

interface DmaDbg;
   method ActionValue#(Bit#(64)) getMemoryTraffic();
   method ActionValue#(DmaDbgRec) dbg();
endinterface

interface MemWriteInternal#(numeric type addrWidth, numeric type dataWidth, numeric type numTags, numeric type numServers);
   interface DmaDbg dbg;
   interface Put#(TileControl) tileControl;
   interface PhysMemWriteClient#(addrWidth,dataWidth) client;
   interface Vector#(numServers, MemWriteServer#(dataWidth)) servers;
endinterface

interface MemReadInternal#(numeric type addrWidth, numeric type dataWidth, numeric type numTags, numeric type numServers);
   interface DmaDbg dbg;
   interface Put#(TileControl) tileControl;
   interface PhysMemReadClient#(addrWidth,dataWidth) client;
   interface Vector#(numServers, MemReadServer#(dataWidth)) servers;
endinterface

function Bool sglid_outofrange(SGLId p);
   return ((p[15:0]) >= fromInteger(valueOf(MaxNumSGLists)));
endfunction

typedef struct {MemRequest req;
		Bit#(TLog#(TMax#(1,numClients))) client; } LRec#(numeric type numClients, numeric type addrWidth) deriving(Bits);

typedef struct {MemRequest req;
		Bit#(addrWidth) pa;
		Bit#(MemTagSize) rename_tag;
		Bit#(TLog#(TMax#(1,numClients))) client; } RRec#(numeric type numClients, numeric type addrWidth) deriving(Bits);

typedef struct {Bit#(MemTagSize) req_tag;
		Bit#(BurstLenSize) req_burstLen;
		Bit#(MemTagSize) rename_tag;
		Bit#(TLog#(TMax#(1,numClients))) client;
		Bool last;
   } DRec#(numeric type numClients, numeric type addrWidth) deriving(Bits);

typedef struct {Bit#(MemTagSize) orig_tag;
		Bit#(TLog#(TMax#(1,numClients))) client; } RResp#(numeric type numClients, numeric type addrWidth) deriving(Bits);

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

module mkMemReadInternal#(MemServerIndication ind,
			  Vector#(numMMUs,Server#(ReqTup,Bit#(addrWidth))) mmus)
   (MemReadInternal#(addrWidth, dataWidth, numTags, numServers))
   provisos(Log#(dataWidthBytes,beatShift)
	    ,Div#(dataWidth,8,dataWidthBytes)
	    ,Add#(beatShift, a__, 8)
	    ,Add#(b__, TLog#(numTags), 6)
	    );

   // stopping/killing infra
   Vector#(4,Reg#(Bool)) killv <- replicateM(mkReg(False));
   Vector#(4,Reg#(Bool)) stopv <- replicateM(mkReg(False));

   // stage 0: address translation (latency = MMU_PIPELINE_DEPTH)
   FIFO#(LRec#(numServers,addrWidth)) lreqFifo <- mkSizedFIFO(valueOf(MMU_PIPELINE_DEPTH));
   // stage 1: address validation (latency = 1)
   FIFO#(RRec#(numServers,addrWidth))  reqFifo <- mkFIFO;
   // stage 2: read commands
   BRAM_Configure bramConfig = defaultValue;
   if (mainClockPeriod < 8)
      bramConfig.latency = 2;
   BRAM2Port#(Bit#(TLog#(numTags)), DRec#(numServers,addrWidth)) dreqBram <- mkBRAM2Server(bramConfig);
   BRAM2Port#(Bit#(TAdd#(TLog#(numTags),TSub#(BurstLenSize,beatShift))), MemData#(dataWidth)) readBufferBram <- mkBRAM2Server(bramConfig);
   // stage 3: read data
   FIFO#(MemData#(dataWidth)) readDataPipelineFifo <- mkFIFO;

   let debug = False;

   Reg#(Bit#(BurstLenSize)) burstReg <- mkReg(0);
   Reg#(Bool)               firstReg <- mkReg(True);
   Reg#(Bool)                lastReg <- mkReg(False);

   Reg#(Bit#(32))  beatCount <- mkReg(0);
   let beat_shift = fromInteger(valueOf(beatShift));
   TagGen#(numTags) tag_gen <- mkTagGen;

   Reg#(Bit#(BurstLenSize))      compCountReg <- mkReg(0);
   Reg#(Bit#(TLog#(numTags)))    compTagReg <- mkReg(0);
   Reg#(Bit#(TLog#(TMax#(1,numServers)))) compClientReg <- mkReg(0);
   Reg#(Bit#(2))                 compTileReg <- mkReg(0);
   FIFO#(Bit#(TAdd#(1,TLog#(TMax#(1,numServers))))) compFifo0 <- mkFIFO;
   FIFO#(Bit#(TLog#(numTags)))   compFifo1 <- mkFIFO;

   // performance analytics
   Reg#(Bit#(64)) cycle_cnt <- mkReg(0);
   Reg#(Bit#(64)) last_loadClient <- mkReg(0);
   Reg#(Bit#(64)) last_mmuResp <- mkReg(0);
   Reg#(Bit#(64)) last_comp <- mkReg(0);
   Reg#(Bit#(64)) last_readReq <- mkReg(0);
   Reg#(Bit#(64)) last_readData <- mkReg(0);
   (* fire_when_enabled *)
   rule cycle;
      cycle_cnt <= cycle_cnt+1;
   endrule

   FIFO#(DmaError) dmaErrorFifo <- mkFIFO();
   rule dmaError;
      let error <- toGet(dmaErrorFifo).get();
      ind.error(extend(pack(error.errorType)), error.pref, 0, 0);
   endrule

   rule complete_burst0;
      let tag <- tag_gen.complete;
      dreqBram.portB.request.put(BRAMRequest{write:False, address:tag, datain: ?, responseOnWrite: ?});
      compFifo1.enq(tag);
      if(debug) $display("mkMemReadInternal::complete_burst0 %h", tag);
   endrule

   rule complete_burst1a if (compCountReg==0);
      let drq <- dreqBram.portB.response.get;
      let req_burstLen = drq.req_burstLen;
      let client = drq.client;
      let cnt = req_burstLen >> beat_shift;
      let tag <- toGet(compFifo1).get;
      if(killv[drq.req_tag[5:4]] == False) begin
	 compFifo0.enq(extend(client));
	 readBufferBram.portB.request.put(BRAMRequest{write:False, address:{tag,truncate(cnt)}, datain: ?, responseOnWrite: ?});
      end
      compCountReg <= cnt-1;
      compTagReg <= tag;
      compClientReg <= client;
      compTileReg <= drq.req_tag[5:4];
      if(debug) $display("mkMemReadInternal::complete_burst1a %h", client);
   endrule

   rule complete_burst1b if (compCountReg > 0);
      let cnt = compCountReg;
      let tag = compTagReg;
      let cli = compClientReg;
      if(killv[compTileReg] == False) begin
	 compFifo0.enq(extend(cli));
	 readBufferBram.portB.request.put(BRAMRequest{write:False, address:{tag,truncate(cnt)}, datain: ?, responseOnWrite: ?});
      end
      compCountReg <= cnt-1;
      if(debug) $display("mkMemReadInternal::complete_burst1b count %h", compCountReg);
   endrule

   rule checkMmuResp;
      let req = lreqFifo.first.req;
      let client = lreqFifo.first.client;
      let physAddr <- mmus[req.sglId[31:16]].response.get;
      let rename_tag <- tag_gen.getTag;
      lreqFifo.deq();
      reqFifo.enq(RRec{req:req, pa:physAddr, client:client, rename_tag:extend(rename_tag)});
      if (debug) $display("checkMmuResp: client=%d, rename_tag=%d", client,rename_tag);
      if (debug) $display("mkMemReadInternal::mmuResp %d %d", client, cycle_cnt-last_mmuResp);
      last_mmuResp <= cycle_cnt;
   endrule

   rule read_data;
      let response <- toGet(readDataPipelineFifo).get();
      Bit#(MemTagSize) response_tag = response.tag;
      let drq <- dreqBram.portA.response.get;
      let otag = drq.req_tag;
      let burstLen = burstReg;
      let first =    firstReg;
      let last  =    lastReg;
      if (first) begin
	 burstLen = drq.req_burstLen >> beat_shift;
	 last = drq.last;
	 dynamicAssert(last == (burstLen==1), "Last incorrect");
	 //$display("burstLen=%d dreqFifo.first.last=%d last=%d\n", burstLen, dreqFifo.first.last, last);
      end
      Bit#(TLog#(numTags)) tt = truncate(response_tag);
      readBufferBram.portA.request.put(BRAMRequest{write:True, responseOnWrite:False, datain:MemData{data: response.data, tag: otag, last: last}, address:{tt,truncate(burstLen)}});
      if (last) begin
	 tag_gen.returnTag(truncate(response_tag));
      end
      last_readData <= cycle_cnt;
      if (debug) $display("read_data %d", cycle_cnt-last_readData);
      burstReg <= burstLen-1;
      firstReg <= burstLen-1 == 0;
      lastReg  <= burstLen-1 == 1;
   endrule

   Vector#(numServers, MemReadServer#(dataWidth)) sv = newVector;
   for(Integer i = 0; i < valueOf(numServers); i=i+1)
      sv[i] = (interface MemReadServer;
		  interface Put readReq;
		     method Action put(MemRequest req);
			last_loadClient <= cycle_cnt;
			let mmusel = req.sglId[31:16];
      			if (debug) $display("mkMemReadInternal::loadClient %d %d %d", i, mmusel, cycle_cnt-last_loadClient);
			if (mmusel >= fromInteger(valueOf(numMMUs)))
			   dmaErrorFifo.enq(DmaError { errorType: DmaErrorMMUOutOfRange_r, pref: req.sglId });
   			else if (sglid_outofrange(req.sglId))
			   dmaErrorFifo.enq(DmaError { errorType: DmaErrorSGLIdOutOfRange_r, pref: req.sglId });
   			else if (stopv[req.tag[5:4]] == False) begin
   			   lreqFifo.enq(LRec{req:req, client:fromInteger(i)});
   			   mmus[mmusel].request.put(ReqTup{id:truncate(req.sglId),off:req.offset});
   			end
		     endmethod
		  endinterface
		  interface Get readData;
		     method ActionValue#(MemData#(dataWidth)) get if (compFifo0.first == fromInteger(i));
			compFifo0.deq;
			let data <- readBufferBram.portB.response.get;
			if (debug) $display("mkMemReadInternal::comp %d  %x %d", i, data.data, cycle_cnt-last_comp);
			last_comp <= cycle_cnt;
			return data;
		     endmethod
		  endinterface
	       endinterface);

   interface servers = sv;
   interface PhysMemReadClient client;
      interface Get readReq;
	 method ActionValue#(PhysMemRequest#(addrWidth)) get();
	    reqFifo.deq;
	    let req = reqFifo.first.req;
	    let physAddr = reqFifo.first.pa;
	    let client = reqFifo.first.client;
	    let rename_tag = reqFifo.first.rename_tag;
	    if (False && physAddr[31:24] != 0)
	       $display("req_ar: funny physAddr req.sglId=%d req.offset=%h physAddr=%h", req.sglId, req.offset, physAddr);
	    dreqBram.portB.request.put(BRAMRequest{write:True, responseOnWrite:False, address:truncate(rename_tag),
						   datain:DRec{req_tag:req.tag, req_burstLen: req.burstLen, client:client, rename_tag:rename_tag, last:(req.burstLen == fromInteger(valueOf(dataWidthBytes)))}});
	    //$display("readReq: client=%d, rename_tag=%d, physAddr=%h req.burstLen=%d beat_shift=%d last=%d", client,rename_tag,physAddr, req.burstLen, beat_shift, req.burstLen == beat_shift);
	    if (debug) $display("read_client.readReq %d", cycle_cnt-last_readReq);
	    last_readReq <= cycle_cnt;
	    return PhysMemRequest{addr:physAddr, burstLen:req.burstLen, tag:rename_tag};
	 endmethod
      endinterface
      interface Put readData;
	 method Action put(MemData#(dataWidth) response);
	    readDataPipelineFifo.enq(response);
	    dreqBram.portA.request.put(BRAMRequest{write:False, address:truncate(response.tag), datain: ?, responseOnWrite: ?});
	    beatCount <= beatCount+1;
	 endmethod
      endinterface
   endinterface
   interface Put tileControl;
      method Action put(TileControl tc);
	 let tile = tc.tile;
	 let kv = True;
	 let sv = True;
	 if (tc.state == Running || tc.state == Stopped)
	    kv = False;
	 if (tc.state == Running)
	    sv = False;
	 killv[tile] <= kv;
	 stopv[tile] <= sv;
      endmethod
   endinterface
   interface DmaDbg dbg;
      method ActionValue#(DmaDbgRec) dbg();
	 return DmaDbgRec{x:0, y:0, z:0, w:0};
      endmethod
      method ActionValue#(Bit#(64)) getMemoryTraffic();
	 return extend(beatCount);
      endmethod
   endinterface
endmodule

module mkMemWriteInternal#(MemServerIndication ind,
			   Vector#(numMMUs,Server#(ReqTup,Bit#(addrWidth))) mmus)
   (MemWriteInternal#(addrWidth, dataWidth, numTags, numServers))
   provisos(Log#(dataWidthBytes,beatShift)
	    ,Div#(dataWidth,8,dataWidthBytes)
	    ,Add#(beatShift, a__, 8)
	    ,Add#(b__, TLog#(numTags), 6)
	    );

   let debug = False;

   // stopping/killing infra
   Vector#(4,Reg#(Bool)) killv <- replicateM(mkReg(False));
   Vector#(4,Reg#(Bool)) stopv <- replicateM(mkReg(False));

   // stage 0: address translation (latency = MMU_PIPELINE_DEPTH)
   FIFO#(LRec#(numServers,addrWidth)) lreqFifo <- mkSizedFIFO(valueOf(MMU_PIPELINE_DEPTH));
   // stage 1: address validation (latency = 1)
   FIFO#(RRec#(numServers,addrWidth))  reqFifo <- mkFIFO;
   // stage 2: write commands
   FIFO#(DRec#(numServers, addrWidth)) dreqFifo <- mkSizedFIFO(valueOf(numTags));
   // stage 3: write data
   BRAM2Port#(Bit#(TLog#(numTags)), RResp#(numServers,addrWidth)) respFifos <- mkBRAM2Server(defaultValue);
   TagGen#(numTags) tag_gen <- mkTagGen;
   FIFO#(RResp#(numServers,addrWidth)) respFifos_buff <- mkFIFO;

   Reg#(Bit#(BurstLenSize)) burstReg <- mkReg(0);
   Reg#(Bool)               firstReg <- mkReg(True);
   Reg#(Bool)               lastReg <- mkReg(False);
   Reg#(Bit#(BeatCountSize)) beatCount <- mkReg(0);
   let beat_shift = fromInteger(valueOf(beatShift));

   Reg#(Bit#(64)) cycle_cnt <- mkReg(0);
   Reg#(Bit#(64)) last_loadClient <- mkReg(0);
   Reg#(Bit#(64)) last_mmuResp <- mkReg(0);

   (* fire_when_enabled *)
   rule cycle;
      cycle_cnt <= cycle_cnt+1;
   endrule

   FIFO#(DmaError) dmaErrorFifo <- mkFIFO();
   rule dmaError;
      let error <- toGet(dmaErrorFifo).get();
      ind.error(extend(pack(error.errorType)), error.pref, 0, 0);
   endrule

   rule checkMmuResp;
      let req = lreqFifo.first.req;
      let client = lreqFifo.first.client;
      let physAddr <- mmus[req.sglId[31:16]].response.get;
      let rename_tag <- tag_gen.getTag;
      lreqFifo.deq();
      reqFifo.enq(RRec{req:req, pa:physAddr, client:client, rename_tag:extend(rename_tag)});
      //if (debug) $display("checkMmuResp: client=%d, rename_tag=%d", client,rename_tag);
      if (debug) $display("mkMemWriteInternal::mmuResp %d %d", client, cycle_cnt-last_mmuResp);
      last_mmuResp <= cycle_cnt;
   endrule

   rule writeDoneComp0;
      let tag <- tag_gen.complete;
      respFifos.portB.request.put(BRAMRequest{write:False, address:tag, datain: ?, responseOnWrite: ?});
   endrule

   FIFO#(MemData#(dataWidth)) memDataFifo <- mkFIFO();
   Vector#(numServers, FIFO#(MemData#(dataWidth))) clientWriteData <- replicateM(mkFIFO);

   if(valueOf(numServers) > 0)
      rule memdata;
	 let drq = dreqFifo.first;
	 let req_tag = drq.req_tag;
	 let req_burstLen = drq.req_burstLen;
	 let rename_tag = drq.rename_tag;
	 let client = drq.client;
	 MemData#(dataWidth) tagdata = unpack(0);
	 if (killv[req_tag[5:4]] == False) begin
	    tagdata = clientWriteData[client].first;
	    clientWriteData[client].deq;
	 end
	 let burstLen = burstReg;
	 let first    = firstReg;
	 let last     = lastReg;
	 if (first) begin
	    burstLen = req_burstLen >> beat_shift;
	    last     = dreqFifo.first.last;
	    respFifos.portA.request.put(BRAMRequest{write:True,responseOnWrite:False, address:truncate(rename_tag), datain:RResp{orig_tag:req_tag, client:client}});
	 end
	 burstReg <= burstLen-1;
	 firstReg <= (burstLen-1 == 0);
	 lastReg  <= (burstLen-1 == 1);
	 beatCount <= beatCount+1;
	 if (last)
	    dreqFifo.deq();
	 //$display("writeData: client=%d, rename_tag=%d", client, rename_tag);
	 memDataFifo.enq(MemData { data: tagdata.data,  tag:extend(rename_tag), last: last });
      endrule

   rule fill_respFifos_buff;
      let rv <- respFifos.portB.response.get;
      respFifos_buff.enq(rv);
   endrule

   Vector#(numServers, MemWriteServer#(dataWidth)) sv = newVector;
   for(Integer i = 0; i < valueOf(numServers); i=i+1)
      sv[i] = (interface MemWriteServer;
		  interface Put writeReq;
		     method Action put(MemRequest req);
      			if (debug) $display("mkMemWriteInternal::loadClient %d %d", i, cycle_cnt-last_loadClient);
			last_loadClient <= cycle_cnt;
			let mmusel = req.sglId[31:16];
			if (mmusel >= fromInteger(valueOf(numMMUs)))
			   dmaErrorFifo.enq(DmaError { errorType: DmaErrorMMUOutOfRange_w, pref: req.sglId });
   			else if (sglid_outofrange(req.sglId))
			   dmaErrorFifo.enq(DmaError { errorType: DmaErrorSGLIdOutOfRange_w, pref: req.sglId });
   			else if (stopv[req.tag[5:4]] == False) begin
   			   lreqFifo.enq(LRec{req:req, client:fromInteger(i)});
   			   mmus[mmusel].request.put(ReqTup{id:truncate(req.sglId),off:req.offset});
   			end
		     endmethod
		  endinterface
		  interface Put writeData = toPut(clientWriteData[i]);
		  interface Get writeDone;
		     method ActionValue#(Bit#(MemTagSize)) get if (respFifos_buff.first.client == fromInteger(i));
			respFifos_buff.deq;
			return respFifos_buff.first.orig_tag;
		     endmethod
		  endinterface
	       endinterface);

   interface servers = sv;
   interface PhysMemWriteClient client;
      interface Get writeReq;
	 method ActionValue#(PhysMemRequest#(addrWidth)) get();
	    let req = reqFifo.first.req;
	    let physAddr = reqFifo.first.pa;
	    let client = reqFifo.first.client;
	    let rename_tag = reqFifo.first.rename_tag;
	    reqFifo.deq;
	    dreqFifo.enq(DRec{req_tag:req.tag, req_burstLen: req.burstLen, client:client, rename_tag:rename_tag, last: (req.burstLen == fromInteger(valueOf(dataWidthBytes))) });
	    //$display("writeReq: client=%d, rename_tag=%d", client,rename_tag);
	    return PhysMemRequest{addr:physAddr, burstLen:req.burstLen, tag:extend(rename_tag)};
	 endmethod
      endinterface
      interface Get writeData = toGet(memDataFifo);
      interface Put writeDone;
	 method Action put(Bit#(MemTagSize) resp);
	    tag_gen.returnTag(truncate(resp));
	    if (debug) $display("writeDone: resp=%d", resp);
	 endmethod
      endinterface
   endinterface
   interface Put tileControl;
      method Action put(TileControl tc);
	 let tile = tc.tile;
	 let kv = True;
	 let sv = True;
	 if (tc.state == Running || tc.state == Stopped)
	    kv = False;
	 if (tc.state == Running)
	    sv = False;
	 killv[tile] <= kv;
	 stopv[tile] <= sv;
      endmethod
   endinterface
   interface DmaDbg dbg;
      method ActionValue#(DmaDbgRec) dbg();
	 return DmaDbgRec{x:fromInteger(valueOf(numServers)), y:?, z:?, w:?};
      endmethod
      method ActionValue#(Bit#(64)) getMemoryTraffic();
	 return extend(beatCount);
      endmethod
   endinterface
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.

// BSV Libraries
import BRAMFIFO::*;
import FIFO::*;
import FIFOF::*;
import Vector::*;
import GetPut::*;
import ClientServer::*;
import Assert::*;
import BRAM::*;
import DefaultValue::*;

// CONNECTAL Libraries
import MemTypes::*;
import ConnectalMemory::*;
import ConnectalClocks::*;
import MMU::*;
import ConnectalCompletionBuffer::*;

typedef 32 BeatCountSize;

typedef 9 MMU_PIPELINE_DEPTH;

interface DmaDbg;
   method ActionValue#(Bit#(64)) getMemoryTraffic();
   method ActionValue#(DmaDbgRec) dbg();
endinterface

interface MemWriteInternal#(numeric type addrWidth, numeric type dataWidth, numeric type numTags, numeric type numServers);
   interface DmaDbg dbg;
   interface Put#(TileControl) tileControl;
   interface PhysMemWriteClient#(addrWidth,dataWidth) client;
   interface Vector#(numServers, MemWriteServer#(dataWidth)) servers;
endinterface

interface MemReadInternal#(numeric type addrWidth, numeric type dataWidth, numeric type numTags, numeric type numServers);
   interface DmaDbg dbg;
   interface Put#(TileControl) tileControl;
   interface PhysMemReadClient#(addrWidth,dataWidth) client;
   interface Vector#(numServers, MemReadServer#(dataWidth)) servers;
endinterface

function Bool sglid_outofrange(SGLId p);
   return ((p[15:0]) >= fromInteger(valueOf(MaxNumSGLists)));
endfunction

typedef struct {MemRequest req;
		Bit#(TLog#(TMax#(1,numClients))) client; } LRec#(numeric type numClients, numeric type addrWidth) deriving(Bits);

typedef struct {MemRequest req;
		Bit#(addrWidth) pa;
		Bit#(MemTagSize) rename_tag;
		Bit#(TLog#(TMax#(1,numClients))) client; } RRec#(numeric type numClients, numeric type addrWidth) deriving(Bits);

typedef struct {Bit#(MemTagSize) req_tag;
		Bit#(BurstLenSize) req_burstLen;
		Bit#(MemTagSize) rename_tag;
		Bit#(TLog#(TMax#(1,numClients))) client;
		Bool last;
   } DRec#(numeric type numClients, numeric type addrWidth) deriving(Bits);

typedef struct {Bit#(MemTagSize) orig_tag;
		Bit#(TLog#(TMax#(1,numClients))) client; } RResp#(numeric type numClients, numeric type addrWidth) deriving(Bits);

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

module mkMemReadInternal#(MemServerIndication ind,
			  Vector#(numMMUs,Server#(ReqTup,Bit#(addrWidth))) mmus)
   (MemReadInternal#(addrWidth, dataWidth, numTags, numServers))
   provisos(Log#(dataWidthBytes,beatShift)
	    ,Div#(dataWidth,8,dataWidthBytes)
	    ,Add#(beatShift, a__, 8)
	    ,Add#(b__, TLog#(numTags), 6)
	    );

   // stopping/killing infra
   Vector#(4,Reg#(Bool)) killv <- replicateM(mkReg(False));
   Vector#(4,Reg#(Bool)) stopv <- replicateM(mkReg(False));

   // stage 0: address translation (latency = MMU_PIPELINE_DEPTH)
   FIFO#(LRec#(numServers,addrWidth)) lreqFifo <- mkSizedFIFO(valueOf(MMU_PIPELINE_DEPTH));
   // stage 1: address validation (latency = 1)
   FIFO#(RRec#(numServers,addrWidth))  reqFifo <- mkFIFO;
   // stage 2: read commands
   BRAM_Configure bramConfig = defaultValue;
   if (mainClockPeriod < 8)
      bramConfig.latency = 2;
   BRAM2Port#(Bit#(TLog#(numTags)), DRec#(numServers,addrWidth)) dreqBram <- mkBRAM2Server(bramConfig);
   BRAM2Port#(Bit#(TAdd#(TLog#(numTags),TSub#(BurstLenSize,beatShift))), MemData#(dataWidth)) readBufferBram <- mkBRAM2Server(bramConfig);
   // stage 3: read data
   FIFO#(MemData#(dataWidth)) readDataPipelineFifo <- mkFIFO;

   let debug = False;

   Reg#(Bit#(BurstLenSize)) burstReg <- mkReg(0);
   Reg#(Bool)               firstReg <- mkReg(True);
   Reg#(Bool)                lastReg <- mkReg(False);

   Reg#(Bit#(32))  beatCount <- mkReg(0);
   let beat_shift = fromInteger(valueOf(beatShift));
   TagGen#(numTags) tag_gen <- mkTagGen;

   Reg#(Bit#(BurstLenSize))      compCountReg <- mkReg(0);
   Reg#(Bit#(TLog#(numTags)))    compTagReg <- mkReg(0);
   Reg#(Bit#(TLog#(TMax#(1,numServers)))) compClientReg <- mkReg(0);
   Reg#(Bit#(2))                 compTileReg <- mkReg(0);
   FIFO#(Bit#(TAdd#(1,TLog#(TMax#(1,numServers))))) compFifo0 <- mkFIFO;
   FIFO#(Bit#(TLog#(numTags)))   compFifo1 <- mkFIFO;

   // performance analytics
   Reg#(Bit#(64)) cycle_cnt <- mkReg(0);
   Reg#(Bit#(64)) last_loadClient <- mkReg(0);
   Reg#(Bit#(64)) last_mmuResp <- mkReg(0);
   Reg#(Bit#(64)) last_comp <- mkReg(0);
   Reg#(Bit#(64)) last_readReq <- mkReg(0);
   Reg#(Bit#(64)) last_readData <- mkReg(0);
   (* fire_when_enabled *)
   rule cycle;
      cycle_cnt <= cycle_cnt+1;
   endrule

   FIFO#(DmaError) dmaErrorFifo <- mkFIFO();
   rule dmaError;
      let error <- toGet(dmaErrorFifo).get();
      ind.error(extend(pack(error.errorType)), error.pref, 0, 0);
   endrule

   rule complete_burst0;
      let tag <- tag_gen.complete;
      dreqBram.portB.request.put(BRAMRequest{write:False, address:tag, datain: ?, responseOnWrite: ?});
      compFifo1.enq(tag);
      if(debug) $display("mkMemReadInternal::complete_burst0 %h", tag);
   endrule

   rule complete_burst1a if (compCountReg==0);
      let drq <- dreqBram.portB.response.get;
      let req_burstLen = drq.req_burstLen;
      let client = drq.client;
      let cnt = req_burstLen >> beat_shift;
      let tag <- toGet(compFifo1).get;
      if(killv[drq.req_tag[5:4]] == False) begin
	 compFifo0.enq(extend(client));
	 readBufferBram.portB.request.put(BRAMRequest{write:False, address:{tag,truncate(cnt)}, datain: ?, responseOnWrite: ?});
      end
      compCountReg <= cnt-1;
      compTagReg <= tag;
      compClientReg <= client;
      compTileReg <= drq.req_tag[5:4];
      if(debug) $display("mkMemReadInternal::complete_burst1a %h", client);
   endrule

   rule complete_burst1b if (compCountReg > 0);
      let cnt = compCountReg;
      let tag = compTagReg;
      let cli = compClientReg;
      if(killv[compTileReg] == False) begin
	 compFifo0.enq(extend(cli));
	 readBufferBram.portB.request.put(BRAMRequest{write:False, address:{tag,truncate(cnt)}, datain: ?, responseOnWrite: ?});
      end
      compCountReg <= cnt-1;
      if(debug) $display("mkMemReadInternal::complete_burst1b count %h", compCountReg);
   endrule

   rule checkMmuResp;
      let req = lreqFifo.first.req;
      let client = lreqFifo.first.client;
      let physAddr <- mmus[req.sglId[31:16]].response.get;
      let rename_tag <- tag_gen.getTag;
      lreqFifo.deq();
      reqFifo.enq(RRec{req:req, pa:physAddr, client:client, rename_tag:extend(rename_tag)});
      if (debug) $display("checkMmuResp: client=%d, rename_tag=%d", client,rename_tag);
      if (debug) $display("mkMemReadInternal::mmuResp %d %d", client, cycle_cnt-last_mmuResp);
      last_mmuResp <= cycle_cnt;
   endrule

   rule read_data;
      let response <- toGet(readDataPipelineFifo).get();
      Bit#(MemTagSize) response_tag = response.tag;
      let drq <- dreqBram.portA.response.get;
      let otag = drq.req_tag;
      let burstLen = burstReg;
      let first =    firstReg;
      let last  =    lastReg;
      if (first) begin
	 burstLen = drq.req_burstLen >> beat_shift;
	 last = drq.last;
	 dynamicAssert(last == (burstLen==1), "Last incorrect");
	 //$display("burstLen=%d dreqFifo.first.last=%d last=%d\n", burstLen, dreqFifo.first.last, last);
      end
      Bit#(TLog#(numTags)) tt = truncate(response_tag);
      readBufferBram.portA.request.put(BRAMRequest{write:True, responseOnWrite:False, datain:MemData{data: response.data, tag: otag, last: last}, address:{tt,truncate(burstLen)}});
      if (last) begin
	 tag_gen.returnTag(truncate(response_tag));
      end
      last_readData <= cycle_cnt;
      if (debug) $display("read_data %d", cycle_cnt-last_readData);
      burstReg <= burstLen-1;
      firstReg <= burstLen-1 == 0;
      lastReg  <= burstLen-1 == 1;
   endrule

   Vector#(numServers, MemReadServer#(dataWidth)) sv = newVector;
   for(Integer i = 0; i < valueOf(numServers); i=i+1)
      sv[i] = (interface MemReadServer;
		  interface Put readReq;
		     method Action put(MemRequest req);
			last_loadClient <= cycle_cnt;
			let mmusel = req.sglId[31:16];
      			if (debug) $display("mkMemReadInternal::loadClient %d %d %d", i, mmusel, cycle_cnt-last_loadClient);
			if (mmusel >= fromInteger(valueOf(numMMUs)))
			   dmaErrorFifo.enq(DmaError { errorType: DmaErrorMMUOutOfRange_r, pref: req.sglId });
   			else if (sglid_outofrange(req.sglId))
			   dmaErrorFifo.enq(DmaError { errorType: DmaErrorSGLIdOutOfRange_r, pref: req.sglId });
   			else if (stopv[req.tag[5:4]] == False) begin
   			   lreqFifo.enq(LRec{req:req, client:fromInteger(i)});
   			   mmus[mmusel].request.put(ReqTup{id:truncate(req.sglId),off:req.offset});
   			end
		     endmethod
		  endinterface
		  interface Get readData;
		     method ActionValue#(MemData#(dataWidth)) get if (compFifo0.first == fromInteger(i));
			compFifo0.deq;
			let data <- readBufferBram.portB.response.get;
			if (debug) $display("mkMemReadInternal::comp %d  %x %d", i, data.data, cycle_cnt-last_comp);
			last_comp <= cycle_cnt;
			return data;
		     endmethod
		  endinterface
	       endinterface);

   interface servers = sv;
   interface PhysMemReadClient client;
      interface Get readReq;
	 method ActionValue#(PhysMemRequest#(addrWidth)) get();
	    reqFifo.deq;
	    let req = reqFifo.first.req;
	    let physAddr = reqFifo.first.pa;
	    let client = reqFifo.first.client;
	    let rename_tag = reqFifo.first.rename_tag;
	    if (False && physAddr[31:24] != 0)
	       $display("req_ar: funny physAddr req.sglId=%d req.offset=%h physAddr=%h", req.sglId, req.offset, physAddr);
	    dreqBram.portB.request.put(BRAMRequest{write:True, responseOnWrite:False, address:truncate(rename_tag),
						   datain:DRec{req_tag:req.tag, req_burstLen: req.burstLen, client:client, rename_tag:rename_tag, last:(req.burstLen == fromInteger(valueOf(dataWidthBytes)))}});
	    //$display("readReq: client=%d, rename_tag=%d, physAddr=%h req.burstLen=%d beat_shift=%d last=%d", client,rename_tag,physAddr, req.burstLen, beat_shift, req.burstLen == beat_shift);
	    if (debug) $display("read_client.readReq %d", cycle_cnt-last_readReq);
	    last_readReq <= cycle_cnt;
	    return PhysMemRequest{addr:physAddr, burstLen:req.burstLen, tag:rename_tag};
	 endmethod
      endinterface
      interface Put readData;
	 method Action put(MemData#(dataWidth) response);
	    readDataPipelineFifo.enq(response);
	    dreqBram.portA.request.put(BRAMRequest{write:False, address:truncate(response.tag), datain: ?, responseOnWrite: ?});
	    beatCount <= beatCount+1;
	 endmethod
      endinterface
   endinterface
   interface Put tileControl;
      method Action put(TileControl tc);
	 let tile = tc.tile;
	 let kv = True;
	 let sv = True;
	 if (tc.state == Running || tc.state == Stopped)
	    kv = False;
	 if (tc.state == Running)
	    sv = False;
	 killv[tile] <= kv;
	 stopv[tile] <= sv;
      endmethod
   endinterface
   interface DmaDbg dbg;
      method ActionValue#(DmaDbgRec) dbg();
	 return DmaDbgRec{x:0, y:0, z:0, w:0};
      endmethod
      method ActionValue#(Bit#(64)) getMemoryTraffic();
	 return extend(beatCount);
      endmethod
   endinterface
endmodule

module mkMemWriteInternal#(MemServerIndication ind,
			   Vector#(numMMUs,Server#(ReqTup,Bit#(addrWidth))) mmus)
   (MemWriteInternal#(addrWidth, dataWidth, numTags, numServers))
   provisos(Log#(dataWidthBytes,beatShift)
	    ,Div#(dataWidth,8,dataWidthBytes)
	    ,Add#(beatShift, a__, 8)
	    ,Add#(b__, TLog#(numTags), 6)
	    );

   let debug = False;

   // stopping/killing infra
   Vector#(4,Reg#(Bool)) killv <- replicateM(mkReg(False));
   Vector#(4,Reg#(Bool)) stopv <- replicateM(mkReg(False));

   // stage 0: address translation (latency = MMU_PIPELINE_DEPTH)
   FIFO#(LRec#(numServers,addrWidth)) lreqFifo <- mkSizedFIFO(valueOf(MMU_PIPELINE_DEPTH));
   // stage 1: address validation (latency = 1)
   FIFO#(RRec#(numServers,addrWidth))  reqFifo <- mkFIFO;
   // stage 2: write commands
   FIFO#(DRec#(numServers, addrWidth)) dreqFifo <- mkSizedBRAMFIFO(valueOf(numTags));
   // stage 3: write data
   BRAM2Port#(Bit#(TLog#(numTags)), RResp#(numServers,addrWidth)) respFifos <- mkBRAM2Server(defaultValue);
   TagGen#(numTags) tag_gen <- mkTagGen;
   FIFO#(RResp#(numServers,addrWidth)) respFifos_buff <- mkFIFO;

   Reg#(Bit#(BurstLenSize)) burstReg <- mkReg(0);
   Reg#(Bool)               firstReg <- mkReg(True);
   Reg#(Bool)               lastReg <- mkReg(False);
   Reg#(Bit#(BeatCountSize)) beatCount <- mkReg(0);
   let beat_shift = fromInteger(valueOf(beatShift));

   Reg#(Bit#(64)) cycle_cnt <- mkReg(0);
   Reg#(Bit#(64)) last_loadClient <- mkReg(0);
   Reg#(Bit#(64)) last_mmuResp <- mkReg(0);

   (* fire_when_enabled *)
   rule cycle;
      cycle_cnt <= cycle_cnt+1;
   endrule

   FIFO#(DmaError) dmaErrorFifo <- mkFIFO();
   rule dmaError;
      let error <- toGet(dmaErrorFifo).get();
      ind.error(extend(pack(error.errorType)), error.pref, 0, 0);
   endrule

   rule checkMmuResp;
      let req = lreqFifo.first.req;
      let client = lreqFifo.first.client;
      let physAddr <- mmus[req.sglId[31:16]].response.get;
      let rename_tag <- tag_gen.getTag;
      lreqFifo.deq();
      reqFifo.enq(RRec{req:req, pa:physAddr, client:client, rename_tag:extend(rename_tag)});
      //if (debug) $display("checkMmuResp: client=%d, rename_tag=%d", client,rename_tag);
      if (debug) $display("mkMemWriteInternal::mmuResp %d %d", client, cycle_cnt-last_mmuResp);
      last_mmuResp <= cycle_cnt;
   endrule

   rule writeDoneComp0;
      let tag <- tag_gen.complete;
      respFifos.portB.request.put(BRAMRequest{write:False, address:tag, datain: ?, responseOnWrite: ?});
   endrule

   FIFO#(MemData#(dataWidth)) memDataFifo <- mkFIFO();
   Vector#(numServers, FIFO#(MemData#(dataWidth))) clientWriteData <- replicateM(mkFIFO);

   if(valueOf(numServers) > 0)
      rule memdata;
	 let drq = dreqFifo.first;
	 let req_tag = drq.req_tag;
	 let req_burstLen = drq.req_burstLen;
	 let rename_tag = drq.rename_tag;
	 let client = drq.client;
	 MemData#(dataWidth) tagdata = unpack(0);
	 if (killv[req_tag[5:4]] == False) begin
	    tagdata = clientWriteData[client].first;
	    clientWriteData[client].deq;
	 end
	 let burstLen = burstReg;
	 let first    = firstReg;
	 let last     = lastReg;
	 if (first) begin
	    burstLen = req_burstLen >> beat_shift;
	    last     = dreqFifo.first.last;
	    respFifos.portA.request.put(BRAMRequest{write:True,responseOnWrite:False, address:truncate(rename_tag), datain:RResp{orig_tag:req_tag, client:client}});
	 end
	 burstReg <= burstLen-1;
	 firstReg <= (burstLen-1 == 0);
	 lastReg  <= (burstLen-1 == 1);
	 beatCount <= beatCount+1;
	 if (last)
	    dreqFifo.deq();
	 //$display("writeData: client=%d, rename_tag=%d", client, rename_tag);
	 memDataFifo.enq(MemData { data: tagdata.data,  tag:extend(rename_tag), last: last });
      endrule

   rule fill_respFifos_buff;
      let rv <- respFifos.portB.response.get;
      respFifos_buff.enq(rv);
   endrule

   Vector#(numServers, MemWriteServer#(dataWidth)) sv = newVector;
   for(Integer i = 0; i < valueOf(numServers); i=i+1)
      sv[i] = (interface MemWriteServer;
		  interface Put writeReq;
		     method Action put(MemRequest req);
      			if (debug) $display("mkMemWriteInternal::loadClient %d %d", i, cycle_cnt-last_loadClient);
			last_loadClient <= cycle_cnt;
			let mmusel = req.sglId[31:16];
			if (mmusel >= fromInteger(valueOf(numMMUs)))
			   dmaErrorFifo.enq(DmaError { errorType: DmaErrorMMUOutOfRange_w, pref: req.sglId });
   			else if (sglid_outofrange(req.sglId))
			   dmaErrorFifo.enq(DmaError { errorType: DmaErrorSGLIdOutOfRange_w, pref: req.sglId });
   			else if (stopv[req.tag[5:4]] == False) begin
   			   lreqFifo.enq(LRec{req:req, client:fromInteger(i)});
   			   mmus[mmusel].request.put(ReqTup{id:truncate(req.sglId),off:req.offset});
   			end
		     endmethod
		  endinterface
		  interface Put writeData = toPut(clientWriteData[i]);
		  interface Get writeDone;
		     method ActionValue#(Bit#(MemTagSize)) get if (respFifos_buff.first.client == fromInteger(i));
			respFifos_buff.deq;
			return respFifos_buff.first.orig_tag;
		     endmethod
		  endinterface
	       endinterface);

   interface servers = sv;
   interface PhysMemWriteClient client;
      interface Get writeReq;
	 method ActionValue#(PhysMemRequest#(addrWidth)) get();
	    let req = reqFifo.first.req;
	    let physAddr = reqFifo.first.pa;
	    let client = reqFifo.first.client;
	    let rename_tag = reqFifo.first.rename_tag;
	    reqFifo.deq;
	    dreqFifo.enq(DRec{req_tag:req.tag, req_burstLen: req.burstLen, client:client, rename_tag:rename_tag, last: (req.burstLen == fromInteger(valueOf(dataWidthBytes))) });
	    //$display("writeReq: client=%d, rename_tag=%d", client,rename_tag);
	    return PhysMemRequest{addr:physAddr, burstLen:req.burstLen, tag:extend(rename_tag)};
	 endmethod
      endinterface
      interface Get writeData = toGet(memDataFifo);
      interface Put writeDone;
	 method Action put(Bit#(MemTagSize) resp);
	    tag_gen.returnTag(truncate(resp));
	    if (debug) $display("writeDone: resp=%d", resp);
	 endmethod
      endinterface
   endinterface
   interface Put tileControl;
      method Action put(TileControl tc);
	 let tile = tc.tile;
	 let kv = True;
	 let sv = True;
	 if (tc.state == Running || tc.state == Stopped)
	    kv = False;
	 if (tc.state == Running)
	    sv = False;
	 killv[tile] <= kv;
	 stopv[tile] <= sv;
      endmethod
   endinterface
   interface DmaDbg dbg;
      method ActionValue#(DmaDbgRec) dbg();
	 return DmaDbgRec{x:fromInteger(valueOf(numServers)), y:?, z:?, w:?};
      endmethod
      method ActionValue#(Bit#(64)) getMemoryTraffic();
	 return extend(beatCount);
      endmethod
   endinterface
endmodule


*port* cannot be empty

*port* cannot be empty

import Clocks::*;
import Vector::*;

import ConnectalClocks::*;
import LedController::*;
import PushButtonController::*;

import AlteraExtra::*;
import ALTERA_SI570_WRAPPER::*;

(* always_ready, always_enabled *)
interface DE5Pins;
`ifndef SIMULATION
   method Action osc_50(Bit#(1) b3d, Bit#(1) b4a, Bit#(1) b4d, Bit#(1) b7a, Bit#(1) b7d, Bit#(1) b8a, Bit#(1) b8d);
   method Action sfp(Bit#(1) refclk);
   method Vector#(4, Bit#(1)) serial_tx_data;
   method Action serial_rx(Vector#(4, Bit#(1)) data);
   method Bit#(4) led;
   method Bit#(4) led_bracket;
   method Action buttons(Vector#(4, Bit#(1)) v);
   interface Si570wrapI2c i2c;
   interface De5SfpCtrl#(4) sfpctrl;
   interface Clock deleteme_unused_clock;
   interface Clock deleteme_unused_clock2;
   interface Clock deleteme_unused_clock3;
   interface Reset deleteme_unused_reset;
`endif
endinterface

interface De5Clocks;
   interface Si570wrapI2c i2c;
   interface Clock clock_50;
   interface Reset reset_50_n;
   interface Clock clock_156_25;
   interface Reset reset_156_25_n;
   interface Clock clock_644_53;
endinterface

module mkDe5Clocks#(Bit#(1) clk_50, Bit#(1) clk_644)(De5Clocks);
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   B2C1 iclock_50 <- mkB2C1();
   B2C1 iclock_644 <- mkB2C1();

   //Reset reset_50 <- mkResetInverter(reset_n, clocked_by clk_50_b4a_buf.outclk);
   Reset rst_50_n <- mkAsyncReset(2, defaultReset, iclock_50.c);
   Reset reset_644 <- mkResetInverter(defaultReset, clocked_by iclock_644.c);
   //Reset reset_644_53_n <- mkAsyncReset(2, reset_n, sfp_refclk);

   // ===================================
   // PLL:
   // Input:   SFP REFCLK from SI570
   // Output:  156.25MHz
   // Reset: Active High, must invert default Reset
   PLL156 pll156 <- mkPLL156(iclock_644.c, reset_644, clocked_by iclock_644.c, reset_by reset_644);
   Clock clk_156_25 = pll156.outclk_0;
   Reset rst_156   <- mkResetInverter(defaultReset, clocked_by clk_156_25);
   Reset rst_156_n <- mkAsyncReset(2, defaultReset, clk_156_25, clocked_by clk_156_25);

   // ===================================
   // PLL: SI570 configurable clock
   // Input:
   // Output:
   // Reset: Active Low, use default Reset
   Si570Wrap si570 <- mkSi570Wrap(iclock_50.c, rst_50_n, clocked_by iclock_50.c, reset_by rst_50_n);

   rule si570_connections;
      let ifreq_mode = 3'b110;  //644.53125 MHZ
      si570.ifreq.mode(ifreq_mode);
      si570.istart.go(1'b0);
   endrule

   rule input_clock_50;
      iclock_50.inputclock(clk_50);
   endrule

   rule input_clock_644;
      iclock_644.inputclock(clk_644);
   endrule

   interface i2c = si570.i2c;
   interface clock_50 = iclock_50.c;
   interface reset_50_n = rst_50_n;
   interface clock_156_25 = clk_156_25;
   interface reset_156_25_n = rst_156_n;
   interface clock_644_53 = iclock_644.c;
endmodule

interface De5Leds;
   method Bit#(4) led_out;
endinterface

module mkDe5Leds#(Clock clk0, Clock clk1, Clock clk2, Clock clk3)(De5Leds);
   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;

   Reset reset0 <- mkSyncReset(2, defaultReset, clk0);
   Reset reset1 <- mkSyncReset(2, defaultReset, clk1);
   Reset reset2 <- mkSyncReset(2, defaultReset, clk2);
   Reset reset3 <- mkSyncReset(2, defaultReset, clk3);

   LedController led0 <- mkLedController(False, clocked_by clk0, reset_by reset0);
   LedController led1 <- mkLedController(False, clocked_by clk1, reset_by reset1);
   LedController led2 <- mkLedController(False, clocked_by clk2, reset_by reset2);
   LedController led3 <- mkLedController(False, clocked_by clk3, reset_by reset3);

   rule led0_run;
      led0.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led1_run;
      led1.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led2_run;
      led2.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led3_run;
      led3.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   method led_out = {led0.ifc.out,
                     led1.ifc.out,
                     led2.ifc.out,
                     led3.ifc.out
                     };
endmodule

interface De5SfpCtrl#(numeric type nPorts);
   method Action los (Vector#(nPorts, Bit#(1)) v);
   method Action mod0_presnt_n (Vector#(nPorts, Bit#(1)) v);
   method Action txfault (Vector#(nPorts, Bit#(1)) v);
// SCL/SDA not implemented
(* prefix="", result="ratesel0" *)   method Vector#(nPorts, Bit#(1)) ratesel0;
(* prefix="", result="ratesel1" *)   method Vector#(nPorts, Bit#(1)) ratesel1;
(* prefix="", result="txdisable" *)   method Vector#(nPorts, Bit#(1)) txdisable;
endinterface

module mkDe5SfpCtrl(De5SfpCtrl#(nPorts));
   Vector#(nPorts, Wire#(Bit#(1))) los_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) mod0_presnt_n_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) txfault_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) ratesel0_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) ratesel1_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) txdisable_wire <- replicateM(mkDWire(0));

   for (Integer i=0; i<valueOf(nPorts); i=i+1) begin
      rule set_output;
         ratesel0_wire[i] <= 1'b1;
         ratesel1_wire[i] <= 1'b1;
         txdisable_wire[i] <= 1'b0;
      endrule
   end

   method los = writeVReg(los_wire);
   method mod0_presnt_n = writeVReg(mod0_presnt_n_wire);
   method txfault = writeVReg(txfault_wire);
   method ratesel0 = readVReg(ratesel0_wire);
   method ratesel1 = readVReg(ratesel1_wire);
   method txdisable = readVReg(txdisable_wire);
endmodule

interface De5Buttons#(numeric type nButtons);
   method Action pins((* port="" *) Vector#(nButtons, Bit#(1)) v);
(* prefix="", result="pressed" *)   method Vector#(nButtons, Bool) pressed;
endinterface

module mkDe5Buttons(De5Buttons#(nButtons));
   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;
   Vector#(nButtons, Wire#(Bit#(1))) button_in <- replicateM(mkDWire(0));
   Vector#(nButtons, Wire#(Bool)) button_pressed <- replicateM(mkDWire(False));

   Vector#(4, PushButtonController) buttons <- replicateM(mkPushButtonController(defaultClock));
   for (Integer i=0; i<valueOf(nButtons); i=i+1) begin
      rule setPushButtonInput;
         buttons[i].ifc.button(button_in[i]);
      endrule

      rule setPushButtonParam;
         buttons[i].setRepeatParams(10, 10);
      endrule

      rule setPushButtonOutput;
         button_pressed[i] <= buttons[i].pressed;
      endrule
   end

   method pins = writeVReg(button_in);
   method pressed = readVReg(button_pressed);
endmodule

import Clocks::*;
import Vector::*;

import ConnectalClocks::*;
import LedController::*;
import PushButtonController::*;

import AlteraExtra::*;
import ALTERA_SI570_WRAPPER::*;

(* always_ready, always_enabled *)
interface DE5Pins;
`ifndef SIMULATION
   method Action osc_50(Bit#(1) b3d, Bit#(1) b4a, Bit#(1) b4d, Bit#(1) b7a, Bit#(1) b7d, Bit#(1) b8a, Bit#(1) b8d);
   method Action sfp(Bit#(1) refclk);
   method Vector#(4, Bit#(1)) serial_tx_data;
   method Action serial_rx(Vector#(4, Bit#(1)) data);
   method Bit#(4) led;
   method Bit#(4) led_bracket;
   method Action buttons(Vector#(4, Bit#(1)) v);
   interface Si570wrapI2c i2c;
   interface De5SfpCtrl#(4) sfpctrl;
   interface Clock deleteme_unused_clock;
   interface Clock deleteme_unused_clock2;
   interface Clock deleteme_unused_clock3;
   interface Reset deleteme_unused_reset;
`endif
endinterface

interface De5Clocks;
   interface Si570wrapI2c i2c;
   interface Clock clock_50;
   interface Reset reset_50_n;
   interface Clock clock_156_25;
   interface Reset reset_156_25_n;
   interface Clock clock_644_53;
endinterface

module mkDe5Clocks#(Bit#(1) clk_50, Bit#(1) clk_644)(De5Clocks);
   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   B2C1 iclock_50 <- mkB2C1();
   B2C1 iclock_644 <- mkB2C1();

   //Reset reset_50 <- mkResetInverter(reset_n, clocked_by clk_50_b4a_buf.outclk);
   Reset rst_50_n <- mkAsyncReset(2, defaultReset, iclock_50.c);
   Reset reset_644 <- mkResetInverter(defaultReset, clocked_by iclock_644.c);
   //Reset reset_644_53_n <- mkAsyncReset(2, reset_n, sfp_refclk);

   // ===================================
   // PLL:
   // Input:   SFP REFCLK from SI570
   // Output:  156.25MHz
   // Reset: Active High, must invert default Reset
   PLL156 pll156 <- mkPLL156(iclock_644.c, reset_644, clocked_by iclock_644.c, reset_by reset_644);
   Clock clk_156_25 = pll156.outclk_0;
   Reset rst_156   <- mkResetInverter(defaultReset, clocked_by clk_156_25);
   Reset rst_156_n <- mkAsyncReset(2, defaultReset, clk_156_25, clocked_by clk_156_25);

   // ===================================
   // PLL: SI570 configurable clock
   // Input:
   // Output:
   // Reset: Active Low, use default Reset
   Si570Wrap si570 <- mkSi570Wrap(iclock_50.c, rst_50_n, clocked_by iclock_50.c, reset_by rst_50_n);

   rule si570_connections;
      let ifreq_mode = 3'b110;  //644.53125 MHZ
      si570.ifreq.mode(ifreq_mode);
      si570.istart.go(1'b0);
   endrule

   rule input_clock_50;
      iclock_50.inputclock(clk_50);
   endrule

   rule input_clock_644;
      iclock_644.inputclock(clk_644);
   endrule

   interface i2c = si570.i2c;
   interface clock_50 = iclock_50.c;
   interface reset_50_n = rst_50_n;
   interface clock_156_25 = clk_156_25;
   interface reset_156_25_n = rst_156_n;
   interface clock_644_53 = iclock_644.c;
endmodule

interface De5Leds;
   method Bit#(4) led_out;
endinterface

module mkDe5Leds#(Clock clk0, Clock clk1, Clock clk2, Clock clk3)(De5Leds);
   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;

   Reset reset0 <- mkSyncReset(2, defaultReset, clk0);
   Reset reset1 <- mkSyncReset(2, defaultReset, clk1);
   Reset reset2 <- mkSyncReset(2, defaultReset, clk2);
   Reset reset3 <- mkSyncReset(2, defaultReset, clk3);

   LedController led0 <- mkLedController(False, clocked_by clk0, reset_by reset0);
   LedController led1 <- mkLedController(False, clocked_by clk1, reset_by reset1);
   LedController led2 <- mkLedController(False, clocked_by clk2, reset_by reset2);
   LedController led3 <- mkLedController(False, clocked_by clk3, reset_by reset3);

   rule led0_run;
      led0.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led1_run;
      led1.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led2_run;
      led2.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   rule led3_run;
      led3.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   method led_out = {led0.ifc.out,
                     led1.ifc.out,
                     led2.ifc.out,
                     led3.ifc.out
                     };
endmodule

interface De5SfpCtrl#(numeric type nPorts);
   method Action los ((* port="" *) Vector#(nPorts, Bit#(1)) v);
   method Action mod0_presnt_n ((* port="" *) Vector#(nPorts, Bit#(1)) v);
   method Action txfault ((* port="" *) Vector#(nPorts, Bit#(1)) v);
// SCL/SDA not implemented
(* prefix="", result="ratesel0" *)   method Vector#(nPorts, Bit#(1)) ratesel0;
(* prefix="", result="ratesel1" *)   method Vector#(nPorts, Bit#(1)) ratesel1;
(* prefix="", result="txdisable" *)   method Vector#(nPorts, Bit#(1)) txdisable;
endinterface

module mkDe5SfpCtrl(De5SfpCtrl#(nPorts));
   Vector#(nPorts, Wire#(Bit#(1))) los_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) mod0_presnt_n_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) txfault_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) ratesel0_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) ratesel1_wire <- replicateM(mkDWire(0));
   Vector#(nPorts, Wire#(Bit#(1))) txdisable_wire <- replicateM(mkDWire(0));

   for (Integer i=0; i<valueOf(nPorts); i=i+1) begin
      rule set_output;
         ratesel0_wire[i] <= 1'b1;
         ratesel1_wire[i] <= 1'b1;
         txdisable_wire[i] <= 1'b0;
      endrule
   end

   method los = writeVReg(los_wire);
   method mod0_presnt_n = writeVReg(mod0_presnt_n_wire);
   method txfault = writeVReg(txfault_wire);
   method ratesel0 = readVReg(ratesel0_wire);
   method ratesel1 = readVReg(ratesel1_wire);
   method txdisable = readVReg(txdisable_wire);
endmodule

interface De5Buttons#(numeric type nButtons);
   method Action pins((* port="" *) Vector#(nButtons, Bit#(1)) v);
(* prefix="", result="pressed" *)   method Vector#(nButtons, Bool) pressed;
endinterface

module mkDe5Buttons(De5Buttons#(nButtons));
   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;
   Vector#(nButtons, Wire#(Bit#(1))) button_in <- replicateM(mkDWire(0));
   Vector#(nButtons, Wire#(Bool)) button_pressed <- replicateM(mkDWire(False));

   Vector#(4, PushButtonController) buttons <- replicateM(mkPushButtonController(defaultClock));
   for (Integer i=0; i<valueOf(nButtons); i=i+1) begin
      rule setPushButtonInput;
         buttons[i].ifc.button(button_in[i]);
      endrule

      rule setPushButtonParam;
         buttons[i].setRepeatParams(10, 10);
      endrule

      rule setPushButtonOutput;
         button_pressed[i] <= buttons[i].pressed;
      endrule
   end

   method pins = writeVReg(button_in);
   method pressed = readVReg(button_pressed);
endmodule


the assert no longer seems to be true

the assert no longer seems to be true

// Copyright (c) 2013-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 FIFO::*;
import FIFOF::*;
import RegFile::*;
import SpecialFIFOs::*;
import GetPut::*;
import BRAM::*;
import Assert::*;

//portz libraries
import Portal::*;
import MemTypes::*;
import Ctrl2BRAM::*;

interface Directory#(numeric type _n,
		     numeric type _a,
		     numeric type _d);
   interface MemPortal#(_a,_d) portalIfc;
endinterface

typedef Directory#(16,16,32) StdDirectory;

typedef 6 StartDirectoryOffset;

module mkStdDirectoryPortalIfc#(BRAMServer#(Bit#(16), Bit#(32)) br)(StdPortal);
   MemSlave#(16,32) ctrl <- mkCtrl2BRAM(br);
   method Bit#(32) ifcId();
      return 0;
   endmethod
   method Bit#(32) ifcType();
      return 0;
   endmethod
   interface MemSlave slave = ctrl;
   interface ReadOnly interrupt;
      method Bool _read;
	 return False;
      endmethod
   endinterface
endmodule

module mkStdDirectory#(Vector#(n,StdPortal) portals) (StdDirectory);

   Reg#(Bit#(64)) cycle_count <- mkReg(0);
   Reg#(Bit#(32))    snapshot <- mkReg(0);
   FIFOF#(Bit#(16))  addrFifo <- mkSizedFIFOF(1);
   FIFO#(Bit#(32))   dataFifo <- mkSizedFIFO(1);
   let startDirectoryOffset=valueOf(StartDirectoryOffset);

   let base = 128;

   rule count;
      cycle_count <= cycle_count+1;
   endrule

   rule req1;
      let addr = addrFifo.first;
      addrFifo.deq;
      let idx = (addr-fromInteger(startDirectoryOffset)-base);
      if (idx[0] == 0)
	 dataFifo.enq(portals[idx>>1].ifcId);
      else
	 dataFifo.enq(portals[idx>>1].ifcType);
   endrule

   let br = (interface BRAMServer#(Bit#(16), Bit#(32));
		interface Put request;
		   method Action put(BRAMRequest#(Bit#(16),Bit#(32)) req) if (!addrFifo.notEmpty);
		      if (!req.write) begin
      			 if (req.address == 0+base)
			    dataFifo.enq(2); // directory version
			 else if (req.address == 1+base)
			    dataFifo.enq(`TimeStamp);
			 else if (req.address == 2+base)
			    dataFifo.enq(fromInteger(valueOf(n)));
			 else if (req.address == 3+base)
			    dataFifo.enq(16); // portal Addr bits
			 else if (req.address == 4+base) begin
			    snapshot <= truncate(cycle_count);
			    dataFifo.enq(cycle_count[63:32]);
			 end
			 else if (req.address == 5+base)
			    dataFifo.enq(snapshot);
			 else begin
			    addrFifo.enq(truncate(req.address));
			 end
		      end
		   endmethod
		endinterface
		interface Get response;
		   method ActionValue#(Bit#(32)) get;
		      dataFifo.deq;
		      return dataFifo.first;
      		   endmethod
		endinterface
      	     endinterface);
   let ifc <- mkStdDirectoryPortalIfc(br);
   interface StdPortal portalIfc = ifc;
endmodule

// Copyright (c) 2013-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 FIFO::*;
import FIFOF::*;
import RegFile::*;
import SpecialFIFOs::*;
import GetPut::*;
import BRAM::*;
import Assert::*;

//portz libraries
import Portal::*;
import MemTypes::*;
import Ctrl2BRAM::*;

interface Directory#(numeric type _n,
		     numeric type _a,
		     numeric type _d);
   interface MemPortal#(_a,_d) portalIfc;
endinterface

typedef Directory#(16,16,32) StdDirectory;

typedef 6 StartDirectoryOffset;

module mkStdDirectoryPortalIfc#(BRAMServer#(Bit#(16), Bit#(32)) br)(StdPortal);
   MemSlave#(16,32) ctrl <- mkCtrl2BRAM(br);
   method Bit#(32) ifcId();
      return 0;
   endmethod
   method Bit#(32) ifcType();
      return 0;
   endmethod
   interface MemSlave slave = ctrl;
   interface ReadOnly interrupt;
      method Bool _read;
	 return False;
      endmethod
   endinterface
endmodule

module mkStdDirectory#(Vector#(n,StdPortal) portals) (StdDirectory);

   Reg#(Bit#(64)) cycle_count <- mkReg(0);
   Reg#(Bit#(32))    snapshot <- mkReg(0);
   FIFOF#(Bit#(16))  addrFifo <- mkSizedFIFOF(1);
   FIFO#(Bit#(32))   dataFifo <- mkSizedFIFO(1);
   let startDirectoryOffset=valueOf(StartDirectoryOffset);

   let base = 128;

   rule count;
      cycle_count <= cycle_count+1;
   endrule

   rule req1;
      let addr = addrFifo.first;
      addrFifo.deq;
      let idx = (addr-fromInteger(startDirectoryOffset)-base);
      if (idx[0] == 0)
	 dataFifo.enq(portals[idx>>1].ifcId);
      else
	 dataFifo.enq(portals[idx>>1].ifcType);
   endrule

   let br = (interface BRAMServer#(Bit#(16), Bit#(32));
		interface Put request;
		   method Action put(BRAMRequest#(Bit#(16),Bit#(32)) req) if (!addrFifo.notEmpty);
		      if (!req.write) begin
      			 if (req.address == 0+base)
			    dataFifo.enq(2); // directory version
			 else if (req.address == 1+base)
			    dataFifo.enq(`TimeStamp);
			 else if (req.address == 2+base)
			    dataFifo.enq(fromInteger(valueOf(n)));
			 else if (req.address == 3+base)
			    dataFifo.enq(16); // portal Addr bits
			 else if (req.address == 4+base) begin
			    snapshot <= truncate(cycle_count);
			    dataFifo.enq(cycle_count[63:32]);
			 end
			 else if (req.address == 5+base)
			    dataFifo.enq(snapshot);
			 else begin
			    dynamicAssert((req.address > base), "mkStdDirectory: invalid address");
			    addrFifo.enq(truncate(req.address));
			 end
		      end
		   endmethod
		endinterface
		interface Get response;
		   method ActionValue#(Bit#(32)) get;
		      dataFifo.deq;
		      return dataFifo.first;
      		   endmethod
		endinterface
      	     endinterface);
   let ifc <- mkStdDirectoryPortalIfc(br);
   interface StdPortal portalIfc = ifc;
endmodule