cleanup imageon

cleanup imageon

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

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

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

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import Vector::*;
import GetPut::*;
import Clocks :: *;
import BRAMFIFO::*;
import MemTypes::*;
import ClientServer::*;
import Pipe::*;
import MemwriteEngine::*;
import HostInterface::*;
import IserdesDatadeser::*;
import IserdesDatadeserIF::*;
import Connectable :: *;
import FIFO::*;
import MemServer::*;
import MMU::*;
import Portal::*;
import HostInterface::*;
import XilinxCells::*;
import ConnectalClocks::*;
import Gearbox::*;
import ConnectalSpi::*;
import ImageonVita::*;
import HDMI::*;
import YUV::*;
import ConnectalXilinxCells::*;

Bit#(10) imageDataTag = 10'h035;
Bit#(10) otherDataTag = 10'h015;

typedef struct {
    Bit#(2) monitor;
    Bit#(32) count;
} MonitorCount deriving (Bits, Eq);

interface ImageonCaptureIndication;
    method Action spi_response(Bit#(32) v);
endinterface

interface ImageonCaptureRequest;
    method Action set_trigger_cnt(Bit#(32) v);
    method Action startWrite(Bit#(32) pointer, Bit#(32) numBytes);
    method Action set_host_oe(Bit#(1) v);
    method Action put_spi_request(Bit#(32) v);
    method Action set_i2c_mux_reset_n(Bit#(1) v);
endinterface

interface ImageonCapturePins;
    method Bit#(1) io_vita_clk_pll();
    method Bit#(1) io_vita_reset_n();
    method Vector#(3, ReadOnly#(Bit#(1))) io_vita_trigger();
    method Action io_vita_monitor(Bit#(2) v);
    interface SpiMasterPins spi;
    method Bit#(1) i2c_mux_reset_n();
    interface Clock imageon_deleteme_unused_clock;
    interface Reset imageon_deleteme_unused_reset;
    interface ImageonSerdesPins serpins;
    (* prefix="" *)
    interface HDMI#(Bit#(HdmiBits)) hdmi;
    method Action fmc_video_clk1(Bit#(1) v);
endinterface

interface ImageonCapture;
   interface ImageonSerdesRequest            serdes_request;
   interface HdmiGeneratorRequest            hdmi_request;
   interface Vector#(1, MemWriteClient#(64)) dmaClient;
   interface ImageonCaptureRequest           capture_request;
   interface ImageonCapturePins              pins;
endinterface

module mkImageonCapture#(ImageonSerdesIndication serdes_indication, HdmiGeneratorIndication hdmi_ind, ImageonCaptureIndication cap_ind)(ImageonCapture);
`ifndef BSIM
    B2C1 iclock <- mkB2C1();
    Clock fmc_imageon_clk1 <- mkClockBUFG(clocked_by iclock.c);
`else
    Clock fmc_imageon_clk1 <- exposeCurrentClock();
`endif
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    ImageClocks clk <- mkImageClocks(fmc_imageon_clk1);
    Clock hdmi_clock = clk.hdmi;
    Clock imageon_clock = clk.imageon;
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);
    Reset imageon_reset <- mkAsyncReset(2, defaultReset, imageon_clock);
    SPI#(Bit#(26)) spiController <- mkSPI(1000, True);
    Reg#(Bit#(1)) i2c_mux_reset_n_reg <- mkReg(0);
    Reg#(Bool) dmaRun <- mkSyncReg(False, defaultClock, defaultReset, imageon_clock);
    Reg#(Bit#(32)) trigger_cnt_reg <- mkSyncReg(0, defaultClock, defaultReset, imageon_clock);
    Reg#(Bit#(1)) imageon_oe <- mkSyncReg(0, defaultClock, defaultReset, imageon_clock);
    Vector#(3, ReadOnly#(Bit#(1))) vita_trigger_wire;
    Reg#(Bool) remapKernel <- mkReg(False, clocked_by imageon_clock, reset_by imageon_reset);
    Gearbox#(4, 1, Bit#(10)) dataGearbox <- mkNto1Gearbox(imageon_clock, imageon_reset, hdmi_clock, hdmi_reset);

    function ReadOnly#(Bit#(1)) roval(Bit#(1) val);
        return (interface ReadOnly; method Bit#(1) _read(); return val; endmethod endinterface);
    endfunction

    // serdes: serial line protocol for wires from sensor (nothing sensor specific)
    ISerdes serdes <- mkISerdes(defaultClock, defaultReset, serdes_indication,
			clocked_by imageon_clock, reset_by imageon_reset);

    // mem capture
    MemwriteEngine#(64,1,1) we <- mkMemwriteEngine();
    SyncFIFOIfc#(Bit#(64)) synchronizer <- mkSyncBRAMFIFO(10, imageon_clock, imageon_reset, defaultClock, defaultReset);
    rule sync_data if (dmaRun);
        synchronizer.enq(serdes.data.capture);
    endrule
    rule send_data;
        we.dataPipes[0].enq(synchronizer.first);
        synchronizer.deq;
    endrule
    rule dma_response;
        let rv <- we.writeServers[0].response.get;
        serdes_indication.iserdes_dma('hffffffff); // request is all finished
    endrule

    SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, imageon_clock);
    Reg#(Bool)  triggerOutput <- mkReg(True, clocked_by imageon_clock, reset_by imageon_reset);
    Reg#(Bit#(32)) tcounter <- mkReg(0, clocked_by imageon_clock, reset_by imageon_reset);
    rule calcTrigger;
        if (triggerOutput && vsyncPulse.pulse())
            begin
            tcounter <= trigger_cnt_reg;
            triggerOutput <= False;
            end
        else
            tcounter <= tcounter - 1;
        if (!triggerOutput && tcounter == 0)
            triggerOutput <= True;
    endrule

    // fromSensor: sensor specific processing of serdes input, resulting in pixels
`ifndef BSIM
    ConnectalODDR#(Bit#(1)) pll_out <- mkConnectalODDR(ODDRParams{ddr_clk_edge:"SAME_EDGE", init:1, srtype:"ASYNC"}, clocked_by imageon_clock, reset_by imageon_reset);
    ConnectalODDR#(Bit#(1)) pll_t <- mkConnectalODDR(ODDRParams{ddr_clk_edge:"SAME_EDGE", init:1, srtype:"ASYNC"}, clocked_by imageon_clock, reset_by imageon_reset);
    ReadOnly#(Bit#(1)) vita_clk_pll <- mkOBUFT(roval(pll_out.q()), roval(pll_t.q()), clocked_by imageon_clock, reset_by imageon_reset);
    vita_trigger_wire[2] <- mkOBUFT(roval(0), regToReadOnly(imageon_oe), clocked_by imageon_clock, reset_by imageon_reset);
    vita_trigger_wire[1] <- mkOBUFT(roval(1), regToReadOnly(imageon_oe), clocked_by imageon_clock, reset_by imageon_reset);
    vita_trigger_wire[0] <- mkOBUFT(regToReadOnly(triggerOutput), regToReadOnly(imageon_oe), clocked_by imageon_clock, reset_by imageon_reset);
    ReadOnly#(Bit#(1)) vita_reset_n_wire <- mkOBUFT(regToReadOnly(serdes.data.reset), regToReadOnly(imageon_oe), clocked_by imageon_clock, reset_by imageon_reset);

    rule pll_rule;
        pll_t.s(False);
        pll_out.s(False);
        pll_out.d1(0);
        pll_out.d2(1);
        pll_out.ce(True);
        pll_t.d1(imageon_oe);
        pll_t.d2(imageon_oe);
        pll_t.ce(True);
    endrule
`else
    let vita_clk_pll = 0;
    let vita_reset_n_wire = 0;
    vita_trigger_wire = replicate(interface ReadOnly; method Bit#(1) _read(); return 0; endmethod endinterface);
`endif

    rule frameData;
        Vector#(5, Bit#(10)) v = serdes.data.raw_data();
        if (v[0] == imageDataTag || v[0] == otherDataTag)
            begin
            Vector#(4, Bit#(10)) dor;
            for (Integer i = 0; i < 4; i = i + 1)
                if (!remapKernel)
                    dor[i] = v[i+1];
                else
                    dor[i] = v[4-i];
            remapKernel <= !remapKernel;
            dataGearbox.enq(dor);
            end
        else
            remapKernel <= False;
    endrule

    rule spiResponse;
        Bit#(26) v <- spiController.response.get();
        cap_ind.spi_response(extend(v));
    endrule

    // hdmi: output to display
    HdmiGenerator#(Rgb888) lHdmiGenerator <- mkHdmiGenerator(defaultClock, defaultReset,
        vsyncPulse, hdmi_ind, clocked_by hdmi_clock, reset_by hdmi_reset);
    Rgb888ToYyuv converter <- mkRgb888ToYyuv(clocked_by hdmi_clock, reset_by hdmi_reset);
    mkConnection(lHdmiGenerator.rgb888, converter.rgb888);
    HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(converter.yyuv, clocked_by hdmi_clock, reset_by hdmi_reset);

    Reg#(Bool) frameStart <- mkReg(False, clocked_by imageon_clock, reset_by imageon_reset);
    Reg#(Bit#(32)) frameCount <- mkReg(0, clocked_by imageon_clock, reset_by imageon_reset);
    SyncFIFOIfc#(MonitorCount) frameStartSynchronizer <- mkSyncFIFO(2, imageon_clock, imageon_reset, defaultClock);
    Wire#(Bit#(2)) monitor_wires <- mkDWire(0, clocked_by imageon_clock, reset_by imageon_reset);

    rule frameStartRule;
        Bool fs = unpack(monitor_wires[0]);
        if (fs && !frameStart) begin
	   // start of frame?
	   // need to cross the clock domain
	   frameStartSynchronizer.enq(MonitorCount{monitor:monitor_wires, count:frameCount});
	   frameCount <= frameCount + 1;
        end
       frameStart <= fs;
    endrule
    rule frameStartIndication;
       let tpl = frameStartSynchronizer.first();
       frameStartSynchronizer.deq();
       //captureIndicationProxy.ifc.frameStart(tpl.monitor, tpl.count);
    endrule

    Reg#(Bit#(10)) xsvi <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
    rule xsviConnection;
        // copy data from sensor to hdmi output
        dataGearbox.deq;
        xsvi <= dataGearbox.first[0];
    endrule
    rule xsviput;
        Bit#(32) pixel = {8'b0, xsvi[9:2], xsvi[9:2], xsvi[9:2]};
        lHdmiGenerator.pdata.put(pixel);
    endrule

    interface serdes_request = serdes.request;
    interface hdmi_request = lHdmiGenerator.request;
    interface dmaClient = cons(we.dmaClient, nil);
    interface ImageonCaptureRequest capture_request;
        method Action set_trigger_cnt(Bit#(32) v);
            trigger_cnt_reg <= v;
            serdes.data.start_capture();
        endmethod
        method Action startWrite(Bit#(32) pointer, Bit#(32) numBytes);
            we.writeServers[0].request.put(MemengineCmd{sglId:pointer, base:0, len:truncate(numBytes), burstLen:8});
            dmaRun <= True;
        endmethod
	method Action set_host_oe(Bit#(1) v);
	    imageon_oe <= ~v;
	endmethod
        method Action put_spi_request(Bit#(32) v);
            spiController.request.put(truncate(v));
        endmethod
        method Action set_i2c_mux_reset_n(Bit#(1) v);
            i2c_mux_reset_n_reg <= v;
        endmethod
    endinterface
    interface ImageonCapturePins pins;
`ifndef BSIM
        method Action fmc_video_clk1(Bit#(1) v);
            iclock.inputclock(v);
        endmethod
`endif
        method Action io_vita_monitor(Bit#(2) v);
	    monitor_wires <= v;
        endmethod
        method Bit#(1) io_vita_clk_pll();
            return vita_clk_pll;
        endmethod
        method Bit#(1) io_vita_reset_n();
            return vita_reset_n_wire;
        endmethod
        method Vector#(3, ReadOnly#(Bit#(1))) io_vita_trigger();
            return vita_trigger_wire;
        endmethod
        method Bit#(1) i2c_mux_reset_n(); return i2c_mux_reset_n_reg; endmethod
        interface SpiMasterPins spi = spiController.pins;
        interface imageon_deleteme_unused_clock = imageon_clock;
        interface imageon_deleteme_unused_reset = imageon_reset;
        interface ImageonSerdesPins serpins = serdes.pins;
        interface HDMI hdmi = hdmisignals;
    endinterface
endmodule

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

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

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

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
import Vector::*;
import GetPut::*;
import Clocks :: *;
import BRAMFIFO::*;
import MemTypes::*;
import ClientServer::*;
import Pipe::*;
import MemwriteEngine::*;
import HostInterface::*;
import IserdesDatadeser::*;
import IserdesDatadeserIF::*;
import Connectable :: *;
import FIFO::*;
import MemServer::*;
import MMU::*;
import Portal::*;
import HostInterface::*;
import XilinxCells::*;
import ConnectalClocks::*;
import Gearbox::*;
import ConnectalSpi::*;
import ImageonVita::*;
import HDMI::*;
import YUV::*;
import ConnectalXilinxCells::*;

Bit#(10) imageDataTag = 10'h035;
Bit#(10) otherDataTag = 10'h015;

typedef struct {
    Bit#(2) monitor;
    Bit#(32) count;
} MonitorCount deriving (Bits, Eq);

interface ImageonCaptureIndication;
    method Action spi_response(Bit#(32) v);
endinterface

interface ImageonCaptureRequest;
    method Action set_trigger_cnt(Bit#(32) v);
    method Action startWrite(Bit#(32) pointer, Bit#(32) numBytes);
    method Action set_host_oe(Bit#(1) v);
    method Action put_spi_request(Bit#(32) v);
    method Action set_i2c_mux_reset_n(Bit#(1) v);
endinterface

interface ImageonCapturePins;
    method Bit#(1) io_vita_clk_pll();
    method Bit#(1) io_vita_reset_n();
    method Vector#(3, ReadOnly#(Bit#(1))) io_vita_trigger();
    method Action io_vita_monitor(Bit#(2) v);
    interface SpiMasterPins spi;
    method Bit#(1) i2c_mux_reset_n();
    interface Clock imageon_deleteme_unused_clock;
    interface Reset imageon_deleteme_unused_reset;
    interface ImageonSerdesPins serpins;
    (* prefix="" *)
    interface HDMI#(Bit#(HdmiBits)) hdmi;
    method Action fmc_video_clk1(Bit#(1) v);
endinterface

interface ImageonCapture;
   interface ImageonSerdesRequest            serdes_request;
   interface HdmiGeneratorRequest            hdmi_request;
   interface Vector#(1, MemWriteClient#(64)) dmaClient;
   interface ImageonCaptureRequest           capture_request;
   interface ImageonCapturePins              pins;
endinterface

module mkImageonCapture#(ImageonSerdesIndication serdes_indication, HdmiGeneratorIndication hdmi_ind, ImageonCaptureIndication cap_ind)(ImageonCapture);
`ifndef BSIM
    B2C1 iclock <- mkB2C1();
    Clock fmc_imageon_clk1 <- mkClockBUFG(clocked_by iclock.c);
`else
    Clock fmc_imageon_clk1 <- exposeCurrentClock();
`endif
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    ImageClocks clk <- mkImageClocks(fmc_imageon_clk1);
    Clock hdmi_clock = clk.hdmi;
    Clock imageon_clock = clk.imageon;
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);
    Reset imageon_reset <- mkAsyncReset(2, defaultReset, imageon_clock);
    SPI#(Bit#(26)) spiController <- mkSPI(1000, True);
    Reg#(Bit#(1)) i2c_mux_reset_n_reg <- mkReg(0);
    Reg#(Bool) dmaRun <- mkSyncReg(False, defaultClock, defaultReset, imageon_clock);
    Reg#(Bit#(32)) trigger_cnt_reg <- mkSyncReg(0, defaultClock, defaultReset, imageon_clock);
    Reg#(Bit#(1)) imageon_oe <- mkSyncReg(0, defaultClock, defaultReset, imageon_clock);
    Vector#(3, ReadOnly#(Bit#(1))) vita_trigger_wire;
    Reg#(Bool) remapKernel <- mkReg(False, clocked_by imageon_clock, reset_by imageon_reset);
    Gearbox#(4, 1, Bit#(10)) dataGearbox <- mkNto1Gearbox(imageon_clock, imageon_reset, hdmi_clock, hdmi_reset);

    function ReadOnly#(Bit#(1)) roval(Bit#(1) val);
        return (interface ReadOnly; method Bit#(1) _read(); return val; endmethod endinterface);
    endfunction

    // serdes: serial line protocol for wires from sensor (nothing sensor specific)
    ISerdes serdes <- mkISerdes(defaultClock, defaultReset, serdes_indication,
			clocked_by imageon_clock, reset_by imageon_reset);

    // mem capture
    MemwriteEngine#(64,1,1) we <- mkMemwriteEngine();
    SyncFIFOIfc#(Bit#(64)) synchronizer <- mkSyncBRAMFIFO(10, imageon_clock, imageon_reset, defaultClock, defaultReset);
    rule sync_data if (dmaRun);
        synchronizer.enq(serdes.data.capture);
    endrule
    rule send_data;
        we.dataPipes[0].enq(synchronizer.first);
        synchronizer.deq;
    endrule
    rule dma_response;
        let rv <- we.writeServers[0].response.get;
        serdes_indication.iserdes_dma('hffffffff); // request is all finished
    endrule

    SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, imageon_clock);
    Reg#(Bool)  trigger_active <- mkReg(True, clocked_by imageon_clock, reset_by imageon_reset);
    Reg#(Bit#(32)) tcounter <- mkReg(0, clocked_by imageon_clock, reset_by imageon_reset);
    rule calcTrigger;
        if (trigger_active && vsyncPulse.pulse())
            begin
            tcounter <= trigger_cnt_reg;
            trigger_active <= False;
            end
        else
            tcounter <= tcounter - 1;
        if (!trigger_active && tcounter == 0)
            trigger_active <= True;
    endrule

    // fromSensor: sensor specific processing of serdes input, resulting in pixels
`ifndef BSIM
    ConnectalODDR#(Bit#(1)) pll_out <- mkConnectalODDR(ODDRParams{ddr_clk_edge:"SAME_EDGE", init:1, srtype:"ASYNC"}, clocked_by imageon_clock, reset_by imageon_reset);
    ConnectalODDR#(Bit#(1)) pll_t <- mkConnectalODDR(ODDRParams{ddr_clk_edge:"SAME_EDGE", init:1, srtype:"ASYNC"}, clocked_by imageon_clock, reset_by imageon_reset);
    ReadOnly#(Bit#(1)) vita_clk_pll <- mkOBUFT(roval(pll_out.q()), roval(pll_t.q()), clocked_by imageon_clock, reset_by imageon_reset);
    vita_trigger_wire[2] <- mkOBUFT(roval(0), regToReadOnly(imageon_oe), clocked_by imageon_clock, reset_by imageon_reset);
    vita_trigger_wire[1] <- mkOBUFT(roval(1), regToReadOnly(imageon_oe), clocked_by imageon_clock, reset_by imageon_reset);
    vita_trigger_wire[0] <- mkOBUFT(regToReadOnly(trigger_active), regToReadOnly(imageon_oe), clocked_by imageon_clock, reset_by imageon_reset);
    ReadOnly#(Bit#(1)) vita_reset_n_wire <- mkOBUFT(regToReadOnly(serdes.data.reset), regToReadOnly(imageon_oe), clocked_by imageon_clock, reset_by imageon_reset);

    rule pll_rule;
        pll_t.s(False);
        pll_out.s(False);
        pll_out.d1(0);
        pll_out.d2(1);
        pll_out.ce(True);
        pll_t.d1(imageon_oe);
        pll_t.d2(imageon_oe);
        pll_t.ce(True);
    endrule
`else
    let vita_clk_pll = 0;
    let vita_reset_n_wire = 0;
    vita_trigger_wire = replicate(interface ReadOnly; method Bit#(1) _read(); return 0; endmethod endinterface);
`endif

    rule frameData;
        Vector#(5, Bit#(10)) v = serdes.data.raw_data();
        if (v[0] == imageDataTag || v[0] == otherDataTag)
            begin
            Vector#(4, Bit#(10)) dor;
            for (Integer i = 0; i < 4; i = i + 1)
                if (!remapKernel)
                    dor[i] = v[i+1];
                else
                    dor[i] = v[4-i];
            remapKernel <= !remapKernel;
            dataGearbox.enq(dor);
            end
        else
            remapKernel <= False;
    endrule

    rule spiResponse;
        Bit#(26) v <- spiController.response.get();
        cap_ind.spi_response(extend(v));
    endrule

    // hdmi: output to display
    HdmiGenerator#(Rgb888) lHdmiGenerator <- mkHdmiGenerator(defaultClock, defaultReset,
        vsyncPulse, hdmi_ind, clocked_by hdmi_clock, reset_by hdmi_reset);
    Rgb888ToYyuv converter <- mkRgb888ToYyuv(clocked_by hdmi_clock, reset_by hdmi_reset);
    mkConnection(lHdmiGenerator.rgb888, converter.rgb888);
    HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(converter.yyuv, clocked_by hdmi_clock, reset_by hdmi_reset);

    Reg#(Bool) frameStart <- mkReg(False, clocked_by imageon_clock, reset_by imageon_reset);
    Reg#(Bit#(32)) frameCount <- mkReg(0, clocked_by imageon_clock, reset_by imageon_reset);
    SyncFIFOIfc#(MonitorCount) frameStartSynchronizer <- mkSyncFIFO(2, imageon_clock, imageon_reset, defaultClock);
    Wire#(Bit#(2)) monitor_wires <- mkDWire(0, clocked_by imageon_clock, reset_by imageon_reset);

    rule frameStartRule;
        Bool fs = unpack(monitor_wires[0]);
        if (fs && !frameStart) begin
	   // start of frame?
	   // need to cross the clock domain
	   frameStartSynchronizer.enq(MonitorCount{monitor:monitor_wires, count:frameCount});
	   frameCount <= frameCount + 1;
        end
       frameStart <= fs;
    endrule
    rule frameStartIndication;
       let tpl = frameStartSynchronizer.first();
       frameStartSynchronizer.deq();
       //captureIndicationProxy.ifc.frameStart(tpl.monitor, tpl.count);
    endrule

    Reg#(Bit#(10)) xsvi <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
    rule xsviConnection;
        // copy data from sensor to hdmi output
        dataGearbox.deq;
        xsvi <= dataGearbox.first[0];
    endrule
    rule xsviput;
        Bit#(32) pixel = {8'b0, xsvi[9:2], xsvi[9:2], xsvi[9:2]};
        lHdmiGenerator.pdata.put(pixel);
    endrule

    interface serdes_request = serdes.request;
    interface hdmi_request = lHdmiGenerator.request;
    interface dmaClient = cons(we.dmaClient, nil);
    interface ImageonCaptureRequest capture_request;
        method Action set_trigger_cnt(Bit#(32) v);
            trigger_cnt_reg <= v;
            serdes.data.start_capture();
        endmethod
        method Action startWrite(Bit#(32) pointer, Bit#(32) numBytes);
            we.writeServers[0].request.put(MemengineCmd{sglId:pointer, base:0, len:truncate(numBytes), burstLen:8});
            dmaRun <= True;
        endmethod
	method Action set_host_oe(Bit#(1) v);
	    imageon_oe <= ~v;
	endmethod
        method Action put_spi_request(Bit#(32) v);
            spiController.request.put(truncate(v));
        endmethod
        method Action set_i2c_mux_reset_n(Bit#(1) v);
            i2c_mux_reset_n_reg <= v;
        endmethod
    endinterface
    interface ImageonCapturePins pins;
`ifndef BSIM
        method Action fmc_video_clk1(Bit#(1) v);
            iclock.inputclock(v);
        endmethod
`endif
        method Action io_vita_monitor(Bit#(2) v);
	    monitor_wires <= v;
        endmethod
        method Bit#(1) io_vita_clk_pll();
            return vita_clk_pll;
        endmethod
        method Bit#(1) io_vita_reset_n();
            return vita_reset_n_wire;
        endmethod
        method Vector#(3, ReadOnly#(Bit#(1))) io_vita_trigger();
            return vita_trigger_wire;
        endmethod
        method Bit#(1) i2c_mux_reset_n(); return i2c_mux_reset_n_reg; endmethod
        interface SpiMasterPins spi = spiController.pins;
        interface imageon_deleteme_unused_clock = imageon_clock;
        interface imageon_deleteme_unused_reset = imageon_reset;
        interface ImageonSerdesPins serpins = serdes.pins;
        interface HDMI hdmi = hdmisignals;
    endinterface
endmodule


moved I2C stuff from ZynqTop to here, using a different ifdef, in order to get visibility to input signals

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

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

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

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

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

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

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

/* Duplicate def here, this is also in ZynqTop */

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

`define BlueScopeEventPIOSampleLength 512

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

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

//   (* prefix="" *)
endinterface

/* clk1 is the FCLKCLK1 controlled by software */

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

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

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

   DiffOut ref_clk <- mkxOBUFDS(ref_clk_wire);

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

   BlueScopeEventPIOIndicationProxy blueScopeEventPIOIndicationProxy <- mkBlueScopeEventPIOIndicationProxy(BlueScopeEventPIOIndication);
   BlueScopeEventPIOControl#(32) bs <- mkBlueScopeEventPIO(`BlueScopeEventPIOSampleLength, blueScopeEventPIOIndicationProxy.ifc);
   BlueScopeEventPIORequestWrapper blueScopeEventPIORequestWrapper <- mkBlueScopeEventPIORequestWrapper(BlueScopeEventPIORequest,bs.requestIfc);

`ifdef USE_FMC_I2C1
   Clock mainclock = host.ps7.fclkclk[0];
   Reset mainreset = host.ps7.fclkreset[0];
   let tscl1 <- mkIOBUF(~host.ps7.i2c[1].scltn, host.ps7.i2c[1].sclo, clocked_by mainclock, reset_by mainreset);
   let tsda1 <- mkIOBUF(~host.ps7.i2c[1].sdatn, host.ps7.i2c[1].sdao, clocked_by mainclock, reset_by mainreset);
   rule sdai1;
      host.ps7.i2c[1].sdai(tsda1.o);
      host.ps7.i2c[1].scli(tscl1.o);
   endrule
   rule watchi2c;
      let a = host.ps7.i2c[1].sclo();
      let b = host.ps7.i2c[1].scltn();
      let c = host.ps7.i2c[1].sdao();
      let d = host.ps7.i2c[1].sdatn();
      bs.bse.dataIn({a, b, tscl1.o, c, d, tsda1.o, 0});
   endrule
`endif

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

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

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

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

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

   interface FMComms1Pins pins;
`ifdef USE_FMC_I2C1
   interface I2C_Pins i2c1;
      interface Inout scl = tscl1.io;
      interface Inout sda = tsda1.io;
   endinterface
`endif
      interface FMComms1ADCPins adcpins = adc.pins;
      interface FMComms1ADCPins dacpins = dac.pins;
      method Bit#(1) ad9548_ref_p();
	 return(ref_clk.read_p());
      endmethod

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

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

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

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

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

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

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

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

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

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

//   (* prefix="" *)
endinterface

/* clk1 is the FCLKCLK1 controlled by software */

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

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

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

   DiffOut ref_clk <- mkxOBUFDS(ref_clk_wire);

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

   BlueScopeEventPIOIndicationProxy blueScopeEventPIOIndicationProxy <- mkBlueScopeEventPIOIndicationProxy(BlueScopeEventPIOIndication);
   BlueScopeEventPIOControl#(32) bs <- mkBlueScopeEventPIO(`BlueScopeEventPIOSampleLength, blueScopeEventPIOIndicationProxy.ifc);
   BlueScopeEventPIORequestWrapper blueScopeEventPIORequestWrapper <- mkBlueScopeEventPIORequestWrapper(BlueScopeEventPIORequest,bs.requestIfc);

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

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

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

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

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

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


removed reference to MemMasterEngine and MemSlaveEngine

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

import Vector            :: *;
import Clocks            :: *;
import GetPut            :: *;
import FIFO              :: *;
import BRAMFIFO          :: *;
import Connectable       :: *;
import ClientServer      :: *;
import DefaultValue      :: *;
import PcieSplitter      :: *;
import Xilinx            :: *;
import Portal            :: *;
import Top               :: *;
import Leds              :: *;
import PcieCsr           :: *;
import MemTypes          :: *;
import Bscan             :: *;
import PcieEndpointS5    :: *;
import PcieHost           :: *;
import NetTop             :: *;
import HostInterface      :: *;
import ConnectalClocks    :: *;
import ALTERA_PLL_156     :: *;
import EthPorts           :: *;
import Ethernet           :: *;
import PinsTop            :: *;
import AlteraExtra        :: *;
import ConfigCounter      :: *;
import ALTERA_SI570_WRAPPER          ::*;
import ALTERA_EDGE_DETECTOR_WRAPPER  ::*;
import ALTERA_ETH_SONIC_PMA :: *;
import EthSonicPma :: *;
import DtpUser::*;
import Pipe::*;
import LedController::*;
import `PinTypeInclude::*;

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

//`ifndef PinType
//`define PinType Empty
//`endif

`define ENABLE_PCIE

typedef `PinType PinType;
typedef `ExportType ExportType;

(* synthesize, no_default_clock, no_default_reset *)
(* clock_prefix="", reset_prefix="" *)
module mkDtpTop #(Clock pcie_refclk_p,
                    Clock osc_50_b3b,
                    Clock osc_50_b3d,
                    Clock osc_50_b4a,
                    Clock osc_50_b4d,
                    Clock osc_50_b7a,
                    Clock osc_50_b7d,
                    Clock osc_50_b8a,
                    Clock osc_50_b8d,
                    Clock sfp_refclk,
                    Reset pcie_perst_n,
                    Reset user_reset_n) (PcieTop#(ExportType));

   // ===================================
   // PLL:
   // Input:    50MHz
   // Output0: 156.25MHz
   //
   // NOTE: input clock must be dedicated to PLL to avoid error:
   // Error (175020): Illegal constraint of fractional PLL to the region (x-coordinate, y- coordinate) to (x-coordinate, y-coordinate): no valid locations in region
   // ===================================
`ifdef ENABLE_PCIE
   PcieHostTop host <- mkPcieHostTop(pcie_refclk_p, osc_50_b3b, pcie_perst_n);

`ifdef IMPORT_HOSTIF
   ConnectalTop portalTop <- mkConnectalTop(host, clocked_by host.portalClock, reset_by host.portalReset);
`else
   ConnectalTop portalTop <- mkConnectalTop(clocked_by host.portalClock, reset_by host.portalReset);
`endif //IMPORT_HOSTIF
`endif //ENABLE_PCIE

   AltClkCtrl clk_50_b4a_buf <- mkAltClkCtrl(osc_50_b4a);
   Reset rst_50   <- mkResetInverter(user_reset_n, clocked_by clk_50_b4a_buf.outclk);
   Reset rst_50_n <- mkAsyncReset(2, user_reset_n, clk_50_b4a_buf.outclk);
   Reset rst_644   <- mkResetInverter(user_reset_n, clocked_by sfp_refclk);
   Reset rst_644_n <- mkAsyncReset(2, user_reset_n, sfp_refclk);

   // ==============
   // Button 0 is wired at top level to user_reset_n
   // Button 1 is used to reset si570.
   ButtonIfc   btns <- mkButton(clocked_by clk_50_b4a_buf.outclk, reset_by rst_50_n);

   // ===================================
   // PLL:
   // Input:   SFP REFCLK from SI570
   // Output:  156.25MHz
   // Reset: Active High, must invert default Reset
   PLL156 pll156 <- mkPLL156(sfp_refclk, rst_644, clocked_by sfp_refclk, reset_by rst_644);
   Clock clk_156_25 = pll156.outclk0;
   Reset rst_156   <- mkResetInverter(user_reset_n, clocked_by clk_156_25);
   Reset rst_156_n <- mkAsyncReset(1, user_reset_n, clk_156_25, clocked_by clk_156_25);

   // ===================================
   // PLL: SI570 configurable clock
   // Input:
   // Output:
   // Reset: Active Low, use default Reset
   Si570Wrap            si570 <- mkSi570Wrap(clk_50_b4a_buf.outclk, rst_50_n, clocked_by clk_50_b4a_buf.outclk, reset_by rst_50_n);
   EdgeDetectorWrap     edgedetect <- mkEdgeDetectorWrap(clk_50_b4a_buf.outclk, rst_50_n, clocked_by clk_50_b4a_buf.outclk, reset_by rst_50_n);

`ifdef ENABLE_PCIE
   // Reset from PCIe Command
   Reset rst_api <- mkSyncReset(0, portalTop.pins.rst, clk_156_25);
   Reset net_top_rst <- mkResetEither(rst_156_n, rst_api, clocked_by clk_156_25);
   NetTopIfc   eth <- mkNetTop(clk_50_b4a_buf.outclk, clk_156_25, sfp_refclk, clocked_by clk_156_25, reset_by net_top_rst); //rst_156_n);
`else
   NetTopIfc   eth <- mkNetTop(clk_50_b4a_buf.outclk, clk_156_25, sfp_refclk, clocked_by clk_156_25, reset_by rst_156_n);
`endif //ENABLE_PCIE

   rule si570_connections;
      //ifreq_mode = 3'b000;  //100.0 MHZ
      //ifreq_mode = 3'b001;  //125.0 MHZ
      //ifreq_mode = 3'b010;  //156.25.0 MHZ
      //ifreq_mode = 3'b011;  //250 MHZ
      //ifreq_mode = 3'b100;  //312.5 MHZ
      //ifreq_mode = 3'b101;  //322.26 MHZ
      let ifreq_mode = 3'b110;  //644.53125 MHZ
      si570.ifreq.mode(ifreq_mode);
      si570.istart.go(edgedetect.odebounce.out);
   endrule

   rule button_to_si570;
      edgedetect.itrigger.in(btns.out.getButton1());
   endrule

   Reset sfp_reset_n <- mkAsyncReset(2, user_reset_n, sfp_refclk);
   Reset xcvr_reset_n <- mkAsyncReset(2, user_reset_n, eth.ifcs.clk_xcvr[0]);

   LedController pci_led <- mkLedController(False, clocked_by pcie_refclk_p, reset_by pcie_perst_n);
   LedController eth_tx_led <- mkLedController(False, clocked_by clk_156_25, reset_by rst_156_n);
   LedController eth_rx_led <- mkLedController(False, clocked_by eth.ifcs.clk_xcvr[0], reset_by xcvr_reset_n);
   LedController sfp_led <- mkLedController(False, clocked_by sfp_refclk, reset_by sfp_reset_n);

   rule led_pcie;
      pci_led.setPeriod(led_off, 500, led_on_max, 500);
   endrule
   rule led_eth_tx;
      eth_tx_led.setPeriod(led_off, 500, led_on_max, 500);
   endrule
   rule led_eth_rx;
      eth_rx_led.setPeriod(led_off, 500, led_on_max, 500);
   endrule
   rule led_sfp;
      sfp_led.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   Vector#(4, LedController) led_xcvr_ <- replicateM(mkLedController(False, clocked_by clk_50_b4a_buf.outclk, reset_by rst_50_n));
   Led#(4) led_xcvr = combineLeds(led_xcvr_);

   rule led_xcvr_ready;
      for (Integer i = 0; i<4; i=i+1) begin
         led_xcvr_[i].setPeriod(led_off, 500, led_on_max, 500);
      end
   endrule

`ifdef ENABLE_PCIE
   mkConnection(host.tpciehost.master, portalTop.slave, clocked_by host.portalClock, reset_by host.portalReset);
   if (valueOf(NumberOfMasters) > 0) begin
      mapM(uncurry(mkConnection),zip(portalTop.masters, host.tpciehost.slave));
   end

   // mkConnection between net and portalTop
   SyncFIFOIfc#(Bit#(128)) tsFifo <- mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock);
   PipeOut#(Bit#(128)) txFifoPipeOut = toPipeOut(tsFifo);
   PipeIn#(Bit#(128)) txFifoPipeIn = toPipeIn(tsFifo);
   mkConnection(eth.api.timestamp, txFifoPipeIn);
   mkConnection(txFifoPipeOut, portalTop.pins.timestamp);

   // send log data from host to network
   Vector#(4, SyncFIFOIfc#(Bit#(53))) fromHostFifo <- replicateM(mkSyncFIFO(8, host.portalClock, host.portalReset, clk_156_25));
   Vector#(4, PipeOut#(Bit#(53))) fromHostPipeOut = map(toPipeOut,fromHostFifo);
   Vector#(4, PipeIn#(Bit#(53))) fromHostPipeIn = map(toPipeIn,fromHostFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(portalTop.pins.fromHost[i], fromHostPipeIn[i]);
      mkConnection(fromHostPipeOut[i], eth.api.phys[i].fromHost);
   end

   // send log data from network to host
   Vector#(4, SyncFIFOIfc#(Bit#(53))) toHostFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(53))) toHostPipeOut = map(toPipeOut, toHostFifo);
   Vector#(4, PipeIn#(Bit#(53))) toHostPipeIn = map(toPipeIn, toHostFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].toHost, toHostPipeIn[i]);
      mkConnection(toHostPipeOut[i], portalTop.pins.toHost[i]);
   end

   // send delay measurement to host
   Vector#(4, SyncFIFOIfc#(Bit#(32))) delayFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(32))) delayPipeOut = map(toPipeOut, delayFifo);
   Vector#(4, PipeIn#(Bit#(32))) delayPipeIn = map(toPipeIn, delayFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].delayOut, delayPipeIn[i]);
      mkConnection(delayPipeOut[i], portalTop.pins.delay[i]);
   end

   // send dtp state to host
   Vector#(4, SyncFIFOIfc#(Bit#(32))) stateFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(32))) statePipeOut = map(toPipeOut, stateFifo);
   Vector#(4, PipeIn#(Bit#(32))) statePipeIn = map(toPipeIn, stateFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].stateOut, statePipeIn[i]);
      mkConnection(statePipeOut[i], portalTop.pins.state[i]);
   end

   // send dtp error count to host
   Vector#(4, SyncFIFOIfc#(Bit#(64))) jumpCountFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(64))) jumpCountPipeOut = map(toPipeOut, jumpCountFifo);
   Vector#(4, PipeIn#(Bit#(64))) jumpCountPipeIn = map(toPipeIn, jumpCountFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].jumpCount, jumpCountPipeIn[i]);
      mkConnection(jumpCountPipeOut[i], portalTop.pins.jumpCount[i]);
   end

   // send dtp clocal to host
   Vector#(4, SyncFIFOIfc#(Bit#(53))) cLocalFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(53))) cLocalPipeOut = map(toPipeOut, cLocalFifo);
   Vector#(4, PipeIn#(Bit#(53))) cLocalPipeIn = map(toPipeIn, cLocalFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].cLocalOut, cLocalPipeIn[i]);
      mkConnection(cLocalPipeOut[i], portalTop.pins.cLocal[i]);
   end

   // send dtp cglobal to host
   SyncFIFOIfc#(Bit#(53)) cGlobalFifo <- mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock);
   PipeOut#(Bit#(53)) cGlobalPipeOut = toPipeOut(cGlobalFifo);
   PipeIn#(Bit#(53)) cGlobalPipeIn = toPipeIn(cGlobalFifo);
   mkConnection(eth.api.globalOut, cGlobalPipeIn);
   mkConnection(cGlobalPipeOut, portalTop.pins.globalOut);

   // set interval
   Vector#(4, SyncFIFOIfc#(Bit#(32))) intervalFifo <- replicateM(mkSyncFIFO(8, host.portalClock, host.portalReset, clk_156_25));
   Vector#(4, PipeOut#(Bit#(32))) intervalPipeOut = map(toPipeOut,intervalFifo);
   Vector#(4, PipeIn#(Bit#(32))) intervalPipeIn = map(toPipeIn,intervalFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(portalTop.pins.interval[i], intervalPipeIn[i]);
      mkConnection(intervalPipeOut[i], eth.api.phys[i].interval);
   end

   // send dtp rcvd err count
   Vector#(4, SyncFIFOIfc#(Bit#(32))) dtpErrCntFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(32))) dtpErrCntPipeOut = map(toPipeOut, dtpErrCntFifo);
   Vector#(4, PipeIn#(Bit#(32))) dtpErrCntPipeIn = map(toPipeIn, dtpErrCntFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].dtpErrCnt, dtpErrCntPipeIn[i]);
      mkConnection(dtpErrCntPipeOut[i], portalTop.pins.dtpErrCnt[i]);
   end

   // send switch mode
   SyncFIFOIfc#(Bit#(1)) switchModeFifo <- mkSyncFIFO(8, host.portalClock, host.portalReset, clk_156_25);
   PipeOut#(Bit#(1)) switchModePipeOut = toPipeOut(switchModeFifo);
   PipeIn#(Bit#(1)) switchModePipeIn = toPipeIn(switchModeFifo);
   mkConnection(portalTop.pins.switchMode, switchModePipeIn);
   mkConnection(switchModePipeOut, eth.api.switchMode);

   // going from level to edge-triggered interrupt
   Vector#(16, Reg#(Bool)) interruptRequested <- replicateM(mkReg(False, clocked_by host.portalClock, reset_by host.portalReset));
   rule interrupt_rule;
     Maybe#(Bit#(4)) intr = tagged Invalid;
     for (Integer i = 0; i < 16; i = i + 1) begin
	 if (portalTop.interrupt[i] && !interruptRequested[i])
             intr = tagged Valid fromInteger(i);
	 interruptRequested[i] <= portalTop.interrupt[i];
     end
     if (intr matches tagged Valid .intr_num) begin
        ReadOnly_MSIX_Entry msixEntry = host.tpciehost.msixEntry[intr_num];
        host.tpciehost.interruptRequest.put(tuple2({msixEntry.addr_hi, msixEntry.addr_lo}, msixEntry.msg_data));
     end
   endrule
`endif //ENABLE_PCIE

`ifndef BSIM
`ifdef ENABLE_PCIE
   interface pcie = host.tep7.pcie;
`endif
   interface pins = (interface PinsTopIfc;
      interface eth  = eth.ifcs;
      interface i2c  = si570.i2c;
      interface led0 = pci_led.ifc.out;
      interface led1 = eth_tx_led.ifc.out;
      interface led2 = eth_rx_led.ifc.out;
      interface led3 = sfp_led.ifc.out;
      interface led_bracket = led_xcvr.out;
      interface buttons  = btns.in;
      interface Clock clk_b4a = clk_50_b4a_buf.outclk;
   endinterface);
//`endif
endmodule

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

import Vector            :: *;
import Clocks            :: *;
import GetPut            :: *;
import FIFO              :: *;
import BRAMFIFO          :: *;
import Connectable       :: *;
import ClientServer      :: *;
import DefaultValue      :: *;
import PcieSplitter      :: *;
import Xilinx            :: *;
import Portal            :: *;
import Top               :: *;
import Leds              :: *;
import MemSlaveEngine    :: *;
import MemMasterEngine   :: *;
import PcieCsr           :: *;
import MemTypes          :: *;
import Bscan             :: *;
import PcieEndpointS5    :: *;
import PcieHost           :: *;
import NetTop             :: *;
import HostInterface      :: *;
import ConnectalClocks    :: *;
import ALTERA_PLL_156     :: *;
import EthPorts           :: *;
import Ethernet           :: *;
import PinsTop            :: *;
import AlteraExtra        :: *;
import ConfigCounter      :: *;
import ALTERA_SI570_WRAPPER          ::*;
import ALTERA_EDGE_DETECTOR_WRAPPER  ::*;
import ALTERA_ETH_SONIC_PMA :: *;
import EthSonicPma :: *;
import DtpUser::*;
import Pipe::*;
import LedController::*;
import `PinTypeInclude::*;

`ifndef DataBusWidth
`define DataBusWidth 64
`endif

//`ifndef PinType
//`define PinType Empty
//`endif

`define ENABLE_PCIE

typedef `PinType PinType;
typedef `ExportType ExportType;

(* synthesize, no_default_clock, no_default_reset *)
(* clock_prefix="", reset_prefix="" *)
module mkDtpTop #(Clock pcie_refclk_p,
                    Clock osc_50_b3b,
                    Clock osc_50_b3d,
                    Clock osc_50_b4a,
                    Clock osc_50_b4d,
                    Clock osc_50_b7a,
                    Clock osc_50_b7d,
                    Clock osc_50_b8a,
                    Clock osc_50_b8d,
                    Clock sfp_refclk,
                    Reset pcie_perst_n,
                    Reset user_reset_n) (PcieTop#(ExportType));

   // ===================================
   // PLL:
   // Input:    50MHz
   // Output0: 156.25MHz
   //
   // NOTE: input clock must be dedicated to PLL to avoid error:
   // Error (175020): Illegal constraint of fractional PLL to the region (x-coordinate, y- coordinate) to (x-coordinate, y-coordinate): no valid locations in region
   // ===================================
`ifdef ENABLE_PCIE
   PcieHostTop host <- mkPcieHostTop(pcie_refclk_p, osc_50_b3b, pcie_perst_n);

`ifdef IMPORT_HOSTIF
   ConnectalTop portalTop <- mkConnectalTop(host, clocked_by host.portalClock, reset_by host.portalReset);
`else
   ConnectalTop portalTop <- mkConnectalTop(clocked_by host.portalClock, reset_by host.portalReset);
`endif //IMPORT_HOSTIF
`endif //ENABLE_PCIE

   AltClkCtrl clk_50_b4a_buf <- mkAltClkCtrl(osc_50_b4a);
   Reset rst_50   <- mkResetInverter(user_reset_n, clocked_by clk_50_b4a_buf.outclk);
   Reset rst_50_n <- mkAsyncReset(2, user_reset_n, clk_50_b4a_buf.outclk);
   Reset rst_644   <- mkResetInverter(user_reset_n, clocked_by sfp_refclk);
   Reset rst_644_n <- mkAsyncReset(2, user_reset_n, sfp_refclk);

   // ==============
   // Button 0 is wired at top level to user_reset_n
   // Button 1 is used to reset si570.
   ButtonIfc   btns <- mkButton(clocked_by clk_50_b4a_buf.outclk, reset_by rst_50_n);

   // ===================================
   // PLL:
   // Input:   SFP REFCLK from SI570
   // Output:  156.25MHz
   // Reset: Active High, must invert default Reset
   PLL156 pll156 <- mkPLL156(sfp_refclk, rst_644, clocked_by sfp_refclk, reset_by rst_644);
   Clock clk_156_25 = pll156.outclk0;
   Reset rst_156   <- mkResetInverter(user_reset_n, clocked_by clk_156_25);
   Reset rst_156_n <- mkAsyncReset(1, user_reset_n, clk_156_25, clocked_by clk_156_25);

   // ===================================
   // PLL: SI570 configurable clock
   // Input:
   // Output:
   // Reset: Active Low, use default Reset
   Si570Wrap            si570 <- mkSi570Wrap(clk_50_b4a_buf.outclk, rst_50_n, clocked_by clk_50_b4a_buf.outclk, reset_by rst_50_n);
   EdgeDetectorWrap     edgedetect <- mkEdgeDetectorWrap(clk_50_b4a_buf.outclk, rst_50_n, clocked_by clk_50_b4a_buf.outclk, reset_by rst_50_n);

`ifdef ENABLE_PCIE
   // Reset from PCIe Command
   Reset rst_api <- mkSyncReset(0, portalTop.pins.rst, clk_156_25);
   Reset net_top_rst <- mkResetEither(rst_156_n, rst_api, clocked_by clk_156_25);
   NetTopIfc   eth <- mkNetTop(clk_50_b4a_buf.outclk, clk_156_25, sfp_refclk, clocked_by clk_156_25, reset_by net_top_rst); //rst_156_n);
`else
   NetTopIfc   eth <- mkNetTop(clk_50_b4a_buf.outclk, clk_156_25, sfp_refclk, clocked_by clk_156_25, reset_by rst_156_n);
`endif //ENABLE_PCIE

   rule si570_connections;
      //ifreq_mode = 3'b000;  //100.0 MHZ
      //ifreq_mode = 3'b001;  //125.0 MHZ
      //ifreq_mode = 3'b010;  //156.25.0 MHZ
      //ifreq_mode = 3'b011;  //250 MHZ
      //ifreq_mode = 3'b100;  //312.5 MHZ
      //ifreq_mode = 3'b101;  //322.26 MHZ
      let ifreq_mode = 3'b110;  //644.53125 MHZ
      si570.ifreq.mode(ifreq_mode);
      si570.istart.go(edgedetect.odebounce.out);
   endrule

   rule button_to_si570;
      edgedetect.itrigger.in(btns.out.getButton1());
   endrule

   Reset sfp_reset_n <- mkAsyncReset(2, user_reset_n, sfp_refclk);
   Reset xcvr_reset_n <- mkAsyncReset(2, user_reset_n, eth.ifcs.clk_xcvr[0]);

   LedController pci_led <- mkLedController(False, clocked_by pcie_refclk_p, reset_by pcie_perst_n);
   LedController eth_tx_led <- mkLedController(False, clocked_by clk_156_25, reset_by rst_156_n);
   LedController eth_rx_led <- mkLedController(False, clocked_by eth.ifcs.clk_xcvr[0], reset_by xcvr_reset_n);
   LedController sfp_led <- mkLedController(False, clocked_by sfp_refclk, reset_by sfp_reset_n);

   rule led_pcie;
      pci_led.setPeriod(led_off, 500, led_on_max, 500);
   endrule
   rule led_eth_tx;
      eth_tx_led.setPeriod(led_off, 500, led_on_max, 500);
   endrule
   rule led_eth_rx;
      eth_rx_led.setPeriod(led_off, 500, led_on_max, 500);
   endrule
   rule led_sfp;
      sfp_led.setPeriod(led_off, 500, led_on_max, 500);
   endrule

   Vector#(4, LedController) led_xcvr_ <- replicateM(mkLedController(False, clocked_by clk_50_b4a_buf.outclk, reset_by rst_50_n));
   Led#(4) led_xcvr = combineLeds(led_xcvr_);

   rule led_xcvr_ready;
      for (Integer i = 0; i<4; i=i+1) begin
         led_xcvr_[i].setPeriod(led_off, 500, led_on_max, 500);
      end
   endrule

`ifdef ENABLE_PCIE
   mkConnection(host.tpciehost.master, portalTop.slave, clocked_by host.portalClock, reset_by host.portalReset);
   if (valueOf(NumberOfMasters) > 0) begin
      mapM(uncurry(mkConnection),zip(portalTop.masters, host.tpciehost.slave));
   end

   // mkConnection between net and portalTop
   SyncFIFOIfc#(Bit#(128)) tsFifo <- mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock);
   PipeOut#(Bit#(128)) txFifoPipeOut = toPipeOut(tsFifo);
   PipeIn#(Bit#(128)) txFifoPipeIn = toPipeIn(tsFifo);
   mkConnection(eth.api.timestamp, txFifoPipeIn);
   mkConnection(txFifoPipeOut, portalTop.pins.timestamp);

   // send log data from host to network
   Vector#(4, SyncFIFOIfc#(Bit#(53))) fromHostFifo <- replicateM(mkSyncFIFO(8, host.portalClock, host.portalReset, clk_156_25));
   Vector#(4, PipeOut#(Bit#(53))) fromHostPipeOut = map(toPipeOut,fromHostFifo);
   Vector#(4, PipeIn#(Bit#(53))) fromHostPipeIn = map(toPipeIn,fromHostFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(portalTop.pins.fromHost[i], fromHostPipeIn[i]);
      mkConnection(fromHostPipeOut[i], eth.api.phys[i].fromHost);
   end

   // send log data from network to host
   Vector#(4, SyncFIFOIfc#(Bit#(53))) toHostFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(53))) toHostPipeOut = map(toPipeOut, toHostFifo);
   Vector#(4, PipeIn#(Bit#(53))) toHostPipeIn = map(toPipeIn, toHostFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].toHost, toHostPipeIn[i]);
      mkConnection(toHostPipeOut[i], portalTop.pins.toHost[i]);
   end

   // send delay measurement to host
   Vector#(4, SyncFIFOIfc#(Bit#(32))) delayFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(32))) delayPipeOut = map(toPipeOut, delayFifo);
   Vector#(4, PipeIn#(Bit#(32))) delayPipeIn = map(toPipeIn, delayFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].delayOut, delayPipeIn[i]);
      mkConnection(delayPipeOut[i], portalTop.pins.delay[i]);
   end

   // send dtp state to host
   Vector#(4, SyncFIFOIfc#(Bit#(32))) stateFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(32))) statePipeOut = map(toPipeOut, stateFifo);
   Vector#(4, PipeIn#(Bit#(32))) statePipeIn = map(toPipeIn, stateFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].stateOut, statePipeIn[i]);
      mkConnection(statePipeOut[i], portalTop.pins.state[i]);
   end

   // send dtp error count to host
   Vector#(4, SyncFIFOIfc#(Bit#(64))) jumpCountFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(64))) jumpCountPipeOut = map(toPipeOut, jumpCountFifo);
   Vector#(4, PipeIn#(Bit#(64))) jumpCountPipeIn = map(toPipeIn, jumpCountFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].jumpCount, jumpCountPipeIn[i]);
      mkConnection(jumpCountPipeOut[i], portalTop.pins.jumpCount[i]);
   end

   // send dtp clocal to host
   Vector#(4, SyncFIFOIfc#(Bit#(53))) cLocalFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(53))) cLocalPipeOut = map(toPipeOut, cLocalFifo);
   Vector#(4, PipeIn#(Bit#(53))) cLocalPipeIn = map(toPipeIn, cLocalFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].cLocalOut, cLocalPipeIn[i]);
      mkConnection(cLocalPipeOut[i], portalTop.pins.cLocal[i]);
   end

   // send dtp cglobal to host
   SyncFIFOIfc#(Bit#(53)) cGlobalFifo <- mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock);
   PipeOut#(Bit#(53)) cGlobalPipeOut = toPipeOut(cGlobalFifo);
   PipeIn#(Bit#(53)) cGlobalPipeIn = toPipeIn(cGlobalFifo);
   mkConnection(eth.api.globalOut, cGlobalPipeIn);
   mkConnection(cGlobalPipeOut, portalTop.pins.globalOut);

   // set interval
   Vector#(4, SyncFIFOIfc#(Bit#(32))) intervalFifo <- replicateM(mkSyncFIFO(8, host.portalClock, host.portalReset, clk_156_25));
   Vector#(4, PipeOut#(Bit#(32))) intervalPipeOut = map(toPipeOut,intervalFifo);
   Vector#(4, PipeIn#(Bit#(32))) intervalPipeIn = map(toPipeIn,intervalFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(portalTop.pins.interval[i], intervalPipeIn[i]);
      mkConnection(intervalPipeOut[i], eth.api.phys[i].interval);
   end

   // send dtp rcvd err count
   Vector#(4, SyncFIFOIfc#(Bit#(32))) dtpErrCntFifo <- replicateM(mkSyncFIFO(8, clk_156_25, rst_156_n, host.portalClock));
   Vector#(4, PipeOut#(Bit#(32))) dtpErrCntPipeOut = map(toPipeOut, dtpErrCntFifo);
   Vector#(4, PipeIn#(Bit#(32))) dtpErrCntPipeIn = map(toPipeIn, dtpErrCntFifo);
   for (Integer i=0; i<4; i=i+1) begin
      mkConnection(eth.api.phys[i].dtpErrCnt, dtpErrCntPipeIn[i]);
      mkConnection(dtpErrCntPipeOut[i], portalTop.pins.dtpErrCnt[i]);
   end

   // send switch mode
   SyncFIFOIfc#(Bit#(1)) switchModeFifo <- mkSyncFIFO(8, host.portalClock, host.portalReset, clk_156_25);
   PipeOut#(Bit#(1)) switchModePipeOut = toPipeOut(switchModeFifo);
   PipeIn#(Bit#(1)) switchModePipeIn = toPipeIn(switchModeFifo);
   mkConnection(portalTop.pins.switchMode, switchModePipeIn);
   mkConnection(switchModePipeOut, eth.api.switchMode);

   // going from level to edge-triggered interrupt
   Vector#(16, Reg#(Bool)) interruptRequested <- replicateM(mkReg(False, clocked_by host.portalClock, reset_by host.portalReset));
   rule interrupt_rule;
     Maybe#(Bit#(4)) intr = tagged Invalid;
     for (Integer i = 0; i < 16; i = i + 1) begin
	 if (portalTop.interrupt[i] && !interruptRequested[i])
             intr = tagged Valid fromInteger(i);
	 interruptRequested[i] <= portalTop.interrupt[i];
     end
     if (intr matches tagged Valid .intr_num) begin
        ReadOnly_MSIX_Entry msixEntry = host.tpciehost.msixEntry[intr_num];
        host.tpciehost.interruptRequest.put(tuple2({msixEntry.addr_hi, msixEntry.addr_lo}, msixEntry.msg_data));
     end
   endrule
`endif //ENABLE_PCIE

`ifndef BSIM
`ifdef ENABLE_PCIE
   interface pcie = host.tep7.pcie;
`endif
   interface pins = (interface PinsTopIfc;
      interface eth  = eth.ifcs;
      interface i2c  = si570.i2c;
      interface led0 = pci_led.ifc.out;
      interface led1 = eth_tx_led.ifc.out;
      interface led2 = eth_rx_led.ifc.out;
      interface led3 = sfp_led.ifc.out;
      interface led_bracket = led_xcvr.out;
      interface buttons  = btns.in;
      interface Clock clk_b4a = clk_50_b4a_buf.outclk;
   endinterface);
//`endif
endmodule


shorten type name, added necessary provisos

import List::*;
import Vector::*;
import BuildVector::*;
import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import DefaultValue::*;

import PriorityEncoder::*;

typedef 32 SIZE;

typedef struct {
    a v;
    b p;
} Node#(type a, type b) deriving(Bits, Eq);

instance DefaultValue#(Node#(a, b))
    provisos (Bits#(a, a__)
             ,Bits#(b, b__)
             ,Bounded#(a)
             ,Bounded#(b)
             ,Literal#(a));
    defaultValue = Node {
        v : minBound,
        p : maxBound
    };
endinstance

interface MinPriorityQueue#(type v, type p);
    interface Put#(Node#(v, p)) insert_req;
    interface Get#(void) insert_res;
    method ActionValue#(Node#(v, p)) first();
    method Action deq();
    method Action clear();
    method Action displayQueue();
endinterface

function Bit#(1) compare (Node#(v, p) x, Node#(v, p) y)
    provisos (Ord#(p));
    if (x.p > y.p)
        return 1;
    else
        return 0;
endfunction

module mkMinPriorityQueue(MinPriorityQueue#(v, p))
    provisos (Bits#(v, v__)
             ,Bits#(p, p__)
             ,Bounded#(v)
             ,Bounded#(p)
             ,Literal#(v)
             ,Ord#(p));

    PE#(SIZE) priority_encoder <- mkPEncoder;
    Vector#(SIZE, Reg#(Node#(v, p))) sorted_list <- replicateM(mkReg(defaultValue));
    Reg#(Node#(v, p)) node_to_insert <- mkReg(defaultValue);
    Reg#(Bit#(TLog#(SIZE))) curr_size <- mkReg(0);
    FIFO#(void) insert_res_fifo <- mkBypassFIFO;
    FIFOF#(Node#(v, p)) insert_req_fifo <- mkSizedBypassFIFOF(4);

    Bool deq_ok = (curr_size > 0);

    rule insert;
        let x <- toGet(priority_encoder.bin).get;
        case (x) matches
           tagged Valid .index : begin
              let v = readVReg(sorted_list);
              let shiftedV = shiftOutFromN(defaultValue, v, 1);
              /*TODO: implement with map(function, vec) */
              Vector#(SIZE, Node#(v, p)) outV = newVector;
              for (Integer i=0; i<valueOf(SIZE); i=i+1) begin
                  if (fromInteger(i) < index)
                     outV[i] = v[i];
                  else if (fromInteger(i) == index)
                     outV[i] = node_to_insert;
                  else
                     outV[i] = shiftedV[i];
              end
              writeVReg(sorted_list, outV);
              curr_size <= curr_size + 1;
              insert_res_fifo.enq(?);
           end
           tagged Invalid: $display("invalid output %h", x);
        endcase
    endrule

    rule handle_insert_req;
       let v <- toGet(insert_req_fifo).get;
       node_to_insert <= v;
       let r = map(uncurry(compare), zip(readVReg(sorted_list), replicate(v)));
       priority_encoder.oht.put(pack(r));
    endrule

    method ActionValue#(Node#(v, p)) first() if (curr_size > 0);
        return head(readVReg(sorted_list));
    endmethod

    method Action deq() if (deq_ok);
        let v = append(tail(readVReg(sorted_list)), vec(defaultValue));
        writeVReg(sorted_list, v);
        curr_size <= curr_size - 1;
    endmethod

    method Action clear();
        writeVReg(sorted_list, defaultValue);
        curr_size <= 0;
    endmethod

    method Action displayQueue();
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
            $display("(%d %d)", sorted_list[i].v, sorted_list[i].p);
    endmethod

    interface Put insert_req = toPut(insert_req_fifo);
    interface Get insert_res = toGet(insert_res_fifo);
endmodule

import List::*;
import Vector::*;
import BuildVector::*;
import FIFO::*;
import FIFOF::*;
import SpecialFIFOs::*;
import GetPut::*;
import DefaultValue::*;

import PriorityEncoder::*;

typedef 32 SIZE;

typedef struct {
    valueType v;
    priorityType p;
} Node#(type valueType, type priorityType) deriving(Bits, Eq);

instance DefaultValue#(Node#(Bit#(size_t), Bit#(size_t)));
    defaultValue = Node {
        v : 0,
        p : maxBound
    };
endinstance

interface MinPriorityQueue#(type valueType, type priorityType);
    interface Put#(Node#(valueType, priorityType)) insert_req;
    interface Get#(void) insert_res;
    method ActionValue#(Node#(valueType, priorityType)) first();
    method Action deq();
    method Action clear();
    method Action displayQueue();
endinterface

function Bit#(1) compare (Node#(Bit#(size_t), Bit#(size_t)) x,
                          Node#(Bit#(size_t), Bit#(size_t)) y);
    if (x.p > y.p)
        return 1;
    else
        return 0;
endfunction

module mkMinPriorityQueue(MinPriorityQueue#(Bit#(size_t), Bit#(size_t)));
    PE#(SIZE) priority_encoder <- mkPEncoder;
    Vector#(SIZE, Reg#(Node#(Bit#(size_t), Bit#(size_t))))
                   sorted_list <- replicateM(mkReg(defaultValue));
    Reg#(Node#(Bit#(size_t), Bit#(size_t))) node_to_insert <- mkReg(defaultValue);
    Reg#(Bit#(TLog#(SIZE))) curr_size <- mkReg(0);
    FIFO#(void) insert_res_fifo <- mkBypassFIFO;
    FIFOF#(Node#(Bit#(size_t), Bit#(size_t))) insert_req_fifo <- mkSizedBypassFIFOF(4);

    rule insert;
        let x <- toGet(priority_encoder.bin).get;
        $display("get from pe %h", x);
        case (x) matches
           tagged Valid .index : begin
              let v = readVReg(sorted_list);
              let shiftedV = shiftOutFromN(defaultValue, v, 1);
              /*TODO: implement with map(function, vec) */
              Vector#(SIZE, Node#(Bit#(size_t), Bit#(size_t))) outV = newVector;
              for (Integer i=0; i<valueOf(SIZE); i=i+1) begin
                  if (fromInteger(i) < index)
                     outV[i] = v[i];
                  else if (fromInteger(i) == index)
                     outV[i] = node_to_insert;
                  else
                     outV[i] = shiftedV[i];
              end
              writeVReg(sorted_list, outV);
              curr_size <= curr_size + 1;
              insert_res_fifo.enq(?);
           end
           tagged Invalid: $display("invalid output %h", x);
        endcase
    endrule

    rule handle_insert_req;
       let v <- toGet(insert_req_fifo).get;
       node_to_insert <= v;
       let r = map(uncurry(compare), zip(readVReg(sorted_list), replicate(v)));
       priority_encoder.oht.put(pack(r));
    endrule

    method ActionValue#(Node#(Bit#(size_t), Bit#(size_t))) first() if (curr_size > 0);
        return head(readVReg(sorted_list));
    endmethod

    method Action deq() if (curr_size > 0);
        let v = append(tail(readVReg(sorted_list)), vec(defaultValue));
        writeVReg(sorted_list, v);
        curr_size <= curr_size - 1;
    endmethod

    method Action clear() if (curr_size > 0);
        writeVReg(sorted_list, defaultValue);
        curr_size <= 0;
    endmethod

    method Action displayQueue();
        for (Integer i = 0; i < valueof(SIZE); i = i + 1)
            $display("(%d %d)", sorted_list[i].v, sorted_list[i].p);
    endmethod

    interface Put insert_req = toPut(insert_req_fifo);
    interface Get insert_res = toGet(insert_res_fifo);
endmodule


attempt to fix memread_4m, but number of arguments to startRead differs from examples/memread, so lib/cpp/testmemread.h gets compilation errors

// 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 SpecialFIFOs::*;
import Vector::*;
import StmtFSM::*;
import FIFO::*;

// portz libraries
import MemServer::*;
import SGList::*;
import Directory::*;
import CtrlMux::*;
import Portal::*;
import PortalMemory::*;
import MemTypes::*;
import Leds::*;

// generated by tool
import MemreadRequestWrapper::*;
import DmaDebugRequestWrapper::*;
import SGListConfigRequestWrapper::*;
import MemreadIndicationProxy::*;
import DmaDebugIndicationProxy::*;
import SGListConfigIndicationProxy::*;

// defined by user
import Memread::*;

typedef enum {MemreadIndication, MemreadRequest, HostmemDmaDebugIndication, HostmemDmaDebugRequest, HostmemSGListConfigRequest, HostmemSGListConfigIndication} IfcNames deriving (Eq,Bits);

typedef 4 NumMasters;
module mkPortalTop(PortalTop#(PhysAddrWidth,64,Empty,NumMasters));

   MemreadIndicationProxy memreadIndicationProxy <- mkMemreadIndicationProxy(MemreadIndication);
   Memread#(NumMasters) memread <- mkMemread(memreadIndicationProxy.ifc);
   MemreadRequestWrapper memreadRequestWrapper <- mkMemreadRequestWrapper(MemreadRequest,memread.request);

   SGListConfigIndicationProxy hostmemSGListConfigIndicationProxy <- mkSGListConfigIndicationProxy(HostmemSGListConfigIndication);
   SGListMMU#(PhysAddrWidth) hostmemSGList <- mkSGListMMU(0, True, hostmemSGListConfigIndicationProxy.ifc);
   SGListConfigRequestWrapper hostmemSGListConfigRequestWrapper <- mkSGListConfigRequestWrapper(HostmemSGListConfigRequest, hostmemSGList.request);

   DmaDebugIndicationProxy hostmemDmaDebugIndicationProxy <- mkDmaDebugIndicationProxy(HostmemDmaDebugIndication);
   MemServer#(PhysAddrWidth,64,NumMasters) dma <- mkMemServerR(hostmemDmaDebugIndicationProxy.ifc, memread.dmaClients, hostmemSGList);
   DmaDebugRequestWrapper hostmemDmaDebugRequestWrapper <- mkDmaDebugRequestWrapper(HostmemDmaDebugRequest, dma.request);

   Vector#(6,StdPortal) portals;
   portals[0] = memreadRequestWrapper.portalIfc;
   portals[1] = memreadIndicationProxy.portalIfc;
   portals[2] = hostmemDmaDebugRequestWrapper.portalIfc;
   portals[3] = hostmemDmaDebugIndicationProxy.portalIfc;
   portals[4] = hostmemSGListConfigRequestWrapper.portalIfc;
   portals[5] = hostmemSGListConfigIndicationProxy.portalIfc;

   StdDirectory dir <- mkStdDirectory(portals);
   let ctrl_mux <- mkSlaveMux(dir,portals);

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

endmodule : mkPortalTop

// 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 SpecialFIFOs::*;
import Vector::*;
import StmtFSM::*;
import FIFO::*;

// portz libraries
import MemServer::*;
import Directory::*;
import CtrlMux::*;
import Portal::*;
import PortalMemory::*;
import MemTypes::*;
import Leds::*;

// generated by tool
import MemreadRequestWrapper::*;
import DmaConfigWrapper::*;
import MemreadIndicationProxy::*;
import DmaIndicationProxy::*;

// defined by user
import Memread::*;

typedef enum {MemreadIndication, MemreadRequest, DmaIndication, DmaConfig} IfcNames deriving (Eq,Bits);

typedef 4 NumMasters;
module mkPortalTop(PortalTop#(PhysAddrWidth,64,Empty,NumMasters));

   MemreadIndicationProxy memreadIndicationProxy <- mkMemreadIndicationProxy(MemreadIndication);
   Memread#(NumMasters) memread <- mkMemread(memreadIndicationProxy.ifc);
   MemreadRequestWrapper memreadRequestWrapper <- mkMemreadRequestWrapper(MemreadRequest,memread.request);

   DmaIndicationProxy dmaIndicationProxy <- mkDmaIndicationProxy(DmaIndication);
   MemServer#(PhysAddrWidth,64,NumMasters) dma <- mkMemServerR(dmaIndicationProxy.ifc, memread.dmaClients);
   DmaConfigWrapper dmaRequestWrapper <- mkDmaConfigWrapper(DmaConfig,dma.request);

   Vector#(4,StdPortal) portals;
   portals[0] = memreadRequestWrapper.portalIfc;
   portals[1] = memreadIndicationProxy.portalIfc;
   portals[2] = dmaRequestWrapper.portalIfc;
   portals[3] = dmaIndicationProxy.portalIfc;

   StdDirectory dir <- mkStdDirectory(portals);
   let ctrl_mux <- mkSlaveMux(dir,portals);

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

endmodule : mkPortalTop


compilation

compilation

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

// types needed by both hardware and software
import GetPutF::*;

interface ServerF#(type intype, type outtype);
	  interface PutF#(intype) request;
	  interface GetF#(outtype) response;
endinterface

typedef 0 CmdNOP;
typedef 1 CmdCOPY;
typedef 2 CmdECHO;

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

// types needed by both hardware and software

interface ServerF#(type intype, type outtype);
	  interface PutF#(intype) request;
	  interface GetF#(outtype) response;
endinterface

typedef 0 CmdNOP;
typedef 1 CmdCOPY;
typedef 2 CmdECHO;