import MemwriteEngine

import MemwriteEngine

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

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

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

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

import FIFO::*;
import FIFOF::*;
import Vector::*;
import ClientServer::*;
import GetPut::*;

import MemTypes::*;
import MemreadEngine::*;
import MemwriteEngine::*;
import Pipe::*;

interface FMComms1Request;
   method Action startRead(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) run);
   method Action startWrite(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) run);
   method Action getReadStatus();
   method Action getWriteStatus();
endinterface

interface FMComms1;
   interface FMComms1Request request;
   interface ObjectReadClient#(64) readDmaClient;
   interface ObjectWriteClient#(64) writeDmaClient;
endinterface

interface FMComms1Indication;
   method Action readStatus(Bit#(32) numIter, Bit#(32) running);
   method Action writeStatus(Bit#(32) numIter, Bit#(32) running);
endinterface

/* This is like a combined memread and memwrite.
 * The read side is set to repetitively read a buffer, until
 * another portal call is made to startRead with the run bit off.
 *
 * Writes are the same
 */
module mkFMComms1#(FMComms1Indication indication, PipeIn#(Bit#(64)) dac, PipeOut#(Bit#(64)) adc) (FMComms1);

   Reg#(ObjectPointer)     readPointer <- mkReg(0);
   Reg#(Bit#(32))         readNumWords <- mkReg(0);
   Reg#(Bit#(32))         readIterCount <- mkReg(0);
   Reg#(Bit#(8))          readBurstLen <- mkReg(0);
   Reg#(Bit#(1))          readRun <- mkReg(0);

   MemreadEngine#(64,1)         re <- mkMemreadEngineBuff(64*16);

   Reg#(ObjectPointer)     writePointer <- mkReg(0);
   Reg#(Bit#(32))         writeNnumWords <- mkReg(0);
   Reg#(Bit#(8))          writeBurstLen <- mkReg(0);
   Reg#(Bit#(1))          writeRun <- mkReg(0);

   MemwriteEngine#(64,1)        we <- mkMemwriteEngineBuff(64*16);

   mkConnection(adc, wr.dataPipe[0]);
   mkConnection(re.dataPipe[0], dac);

   rule readStart (readRun == 1);
      readIterCount <= readIterCount + 1;
      re.readServers[0].request.put(MemengineCmd{pointer:readPointer, base:0, len:readNumWords*4, burstLen:readBurstLen*4});
   endrule

   rule readFinish;
      let rv <- re.readServers[0].response.get;
      if (readRun == 0)
	 indication.readStatus(readIterCount, readRun);
   endrule

   rule writeStart (writeRun == 1);
      writeIterCount <= writeIterCount + 1;
      re.writeServers[0].request.put(MemengineCmd{pointer:writePointer, base:0, len:writeNumWords*4, burstLen:writeBurstLen*4});
   endrule

   rule writeFinish;
      let rv <- re.writeServers[0].response.get;
      if (writeRun == 0)
	 indication.writeStatus(writeIterCount, writeRun);
   endrule

   interface ObjectReadClient readDmaClient = re.dmaClient;
   interface ObjectWeadClient writeDmaClient = we.dmaClient;
   interface FMComms1Request request;
      method Action startRead(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) run);
	 $display("startRead rdPointer=%d numWords=%h burstLen=%d run=%d",
	    pointer, numWords, burstLen, run);
	 if (run == 1) indication.readStarted(readInterCount, run);
	 readPointer <= pointer;
	 readNumWords  <= numWords;
	 readBurstLen  <= truncate(burstLen);
	 readRun <= truncate(run);
      endmethod
      method Action startWrite(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) run);
	 $display("startWrite rdPointer=%d numWords=%h burstLen=%d run=%d",
	    pointer, numWords, burstLen, run);
	 if (run == 1) indication.writeStarted(writeInterCount, run);
	 writePointer <= pointer;
	 writeNumWords  <= numWords;
	 writeBurstLen  <= truncate(burstLen);
	 writeRun <= truncate(run);
      endmethod
      method Action getReadStatus();
	 indication.readStatus(readIterCount, readRun);
      endmethod
      method Action getWriteStatus();
	 indication.writeStatus(writeIterCount, writeRun);
      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.

import FIFO::*;
import FIFOF::*;
import Vector::*;
import ClientServer::*;
import GetPut::*;

import MemTypes::*;
import MemreadEngine::*;
import Pipe::*;

interface FMComms1Request;
   method Action startRead(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) run);
   method Action startWrite(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) run);
   method Action getReadStatus();
   method Action getWriteStatus();
endinterface

interface FMComms1;
   interface FMComms1Request request;
   interface ObjectReadClient#(64) readDmaClient;
   interface ObjectWriteClient#(64) writeDmaClient;
endinterface

interface FMComms1Indication;
   method Action readStatus(Bit#(32) numIter, Bit#(32) running);
   method Action writeStatus(Bit#(32) numIter, Bit#(32) running);
endinterface

/* This is like a combined memread and memwrite.
 * The read side is set to repetitively read a buffer, until
 * another portal call is made to startRead with the run bit off.
 *
 * Writes are the same
 */
module mkFMComms1#(FMComms1Indication indication, PipeIn#(Bit#(64)) dac, PipeOut#(Bit#(64)) adc) (FMComms1);

   Reg#(ObjectPointer)     readPointer <- mkReg(0);
   Reg#(Bit#(32))         readNumWords <- mkReg(0);
   Reg#(Bit#(32))         readIterCount <- mkReg(0);
   Reg#(Bit#(8))          readBurstLen <- mkReg(0);
   Reg#(Bit#(1))          readRun <- mkReg(0);

   MemreadEngine#(64,1)         re <- mkMemreadEngineBuff(64*16);

   Reg#(ObjectPointer)     writePointer <- mkReg(0);
   Reg#(Bit#(32))         writeNnumWords <- mkReg(0);
   Reg#(Bit#(8))          writeBurstLen <- mkReg(0);
   Reg#(Bit#(1))          writeRun <- mkReg(0);

   MemwriteEngine#(64,1)        we <- mkMemwriteEngineBuff(64*16);

   mkConnection(adc, wr.dataPipe[0]);
   mkConnection(re.dataPipe[0], dac);

   rule readStart (readRun == 1);
      readIterCount <= readIterCount + 1;
      re.readServers[0].request.put(MemengineCmd{pointer:readPointer, base:0, len:readNumWords*4, burstLen:readBurstLen*4});
   endrule

   rule readFinish;
      let rv <- re.readServers[0].response.get;
      if (readRun == 0)
	 indication.readStatus(readIterCount, readRun);
   endrule

   rule writeStart (writeRun == 1);
      writeIterCount <= writeIterCount + 1;
      re.writeServers[0].request.put(MemengineCmd{pointer:writePointer, base:0, len:writeNumWords*4, burstLen:writeBurstLen*4});
   endrule

   rule writeFinish;
      let rv <- re.writeServers[0].response.get;
      if (writeRun == 0)
	 indication.writeStatus(writeIterCount, writeRun);
   endrule

   interface ObjectReadClient readDmaClient = re.dmaClient;
   interface ObjectWeadClient writeDmaClient = we.dmaClient;
   interface FMComms1Request request;
      method Action startRead(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) run);
	 $display("startRead rdPointer=%d numWords=%h burstLen=%d run=%d",
	    pointer, numWords, burstLen, run);
	 if (run == 1) indication.readStarted(readInterCount, run);
	 readPointer <= pointer;
	 readNumWords  <= numWords;
	 readBurstLen  <= truncate(burstLen);
	 readRun <= truncate(run);
      endmethod
      method Action startWrite(Bit#(32) pointer, Bit#(32) numWords, Bit#(32) burstLen, Bit#(32) run);
	 $display("startWrite rdPointer=%d numWords=%h burstLen=%d run=%d",
	    pointer, numWords, burstLen, run);
	 if (run == 1) indication.writeStarted(writeInterCount, run);
	 writePointer <= pointer;
	 writeNumWords  <= numWords;
	 writeBurstLen  <= truncate(burstLen);
	 writeRun <= truncate(run);
      endmethod
      method Action getReadStatus();
	 indication.readStatus(readIterCount, readRun);
      endmethod
      method Action getWriteStatus();
	 indication.writeStatus(writeIterCount, writeRun);
      endmethod
   endinterface
endmodule


first attempt at hsync/vsync FSM

first attempt at hsync/vsync FSM

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

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

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

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

import Vector::*;
import FIFO::*;
import GetPut::*;
import Gearbox::*;

interface ImageonSpi;
    method Bit#(1) reset();
    method Bit#(16) timing();
    method Action status_busy(Bit#(1) busy);
    method Action status_error(Bit#(1) error);
    method Bit#(1) txfifo_wen();
    method Bit#(32) txfifo_din();
    method Action txfifo_full(Bit#(1) full);
    method Bit#(1) rxfifo_ren();
    method Action rxfifo_dout(Bit#(32) dout);
    method Action rxfifo_empty(Bit#(1) empty);
endinterface

interface ImageonSerdes;
    method Bit#(1) reset();
    method Bit#(1) auto_align();
    method Bit#(1) align_start();
    method Bit#(1) fifo_enable();
    method Bit#(10) manual_tap();
    method Bit#(10) training();
    method Action iserdes_clk_ready(Bit#(1) ready);
    method Action iserdes_clk_status(Bit#(16) status);
    method Action iserdes_align_busy(Bit#(1) busy);
    method Action iserdes_aligned(Bit#(1) aligned);
endinterface

interface ImageonDecoder;
    method Bit#(1) reset();
    method Bit#(1) enable();
    method Bit#(10) code_ls();
    method Bit#(10) code_le();
    method Bit#(10) code_fs();
    method Bit#(10) code_fe();
    method Bit#(10) code_bl();
    method Bit#(10) code_img();
    method Action frame_start(Bit#(1) start);
endinterface

interface ImageonTrigger;
    method Bit#(3) enable();
    method Bit#(32) default_freq();
    method Bit#(32) cnt_trigger0high();
    method Bit#(32) cnt_trigger0low();
endinterface

interface ImageonSyncGen;
    method Bit#(16) delay();
    method Bit#(16) hactive();
    method Bit#(16) hfporch();
    method Bit#(16) hsync();
    method Bit#(16) hbporch();
    method Bit#(16) vactive();
    method Bit#(16) vfporch();
    method Bit#(16) vsync();
    method Bit#(16) vbporch();
endinterface

typedef struct {
    Bit#(1) fsync;
    Bit#(1) vsync;
    Bit#(1) hsync;
    Bit#(1) active_video;
    Bit#(10) video_data;
} XsviData deriving (Bits);

interface ImageonSensorData;
    method Action fsync(Bit#(1) v);
    method Action hsync(Bit#(1) v);
    method Action vsync(Bit#(1) v);
    method Action active_video(Bit#(1) v);
    method Action video_data_old(Bit#(10) v);
    method Action framestart(Bit#(1) v);
    method Action video_data(Bit#(40) v);
endinterface

(* always_enabled *)
interface ImageonVita;
    method Bit#(1) host_vita_reset();
    method Bit#(1) host_oe();
    interface ImageonSpi spi;
    interface ImageonSerdes serdes;
    interface ImageonDecoder decoder;
    interface ImageonTrigger trigger;
    interface ImageonSyncGen syncgen;
    method Bit#(32) get_debugreq();
    method Action set_debugind(Bit#(32) v);
endinterface

interface ImageonControl;
    method Action set_spi_control(Bit#(32) v);
    method Bit#(32) get_spi_control();
    method Action set_iserdes_control(Bit#(32) v);
    method Bit#(32) get_iserdes_control();
    method Action set_decoder_control(Bit#(32) v);
    method Bit#(32) get_decoder_control();
    method Action set_triggen_control(Bit#(32) v);
    method Bit#(32) get_triggen_control();

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

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

    interface Put#(Bit#(32)) txfifo;
    interface Put#(Bit#(32)) rxfifo_request;
    interface Get#(Bit#(32)) rxfifo_response;

    method Action set_serdes_reset(Bit#(1) v);
    method Action set_serdes_auto_align(Bit#(1) v);
    method Action set_serdes_align_start(Bit#(1) v);
    method Action set_serdes_fifo_enable(Bit#(1) v);
    method Action set_serdes_manual_tap(Bit#(10) v);
    method Action set_serdes_training(Bit#(10) v);
    method Action set_decoder_reset(Bit#(1) v);
    method Action set_decoder_enable(Bit#(1) v);
    method Action set_decoder_code_ls(Bit#(10) v);
    method Action set_decoder_code_le(Bit#(10) v);
    method Action set_decoder_code_fs(Bit#(10) v);
    method Action set_decoder_code_fe(Bit#(10) v);
    method Action set_decoder_code_bl(Bit#(10) v);
    method Action set_decoder_code_img(Bit#(10) v);
    method Action set_trigger_enable(Bit#(3) v);
    method Action set_trigger_default_freq(Bit#(32) v);
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
    method Action set_syncgen_delay(Bit#(16) v);
    method Action set_syncgen_hactive(Bit#(16) v);
    method Action set_syncgen_hfporch(Bit#(16) v);
    method Action set_syncgen_hsync(Bit#(16) v);
    method Action set_syncgen_hbporch(Bit#(16) v);
    method Action set_syncgen_vactive(Bit#(16) v);
    method Action set_syncgen_vfporch(Bit#(16) v);
    method Action set_syncgen_vsync(Bit#(16) v);
    method Action set_syncgen_vbporch(Bit#(16) v);
    method Action set_debugreq(Bit#(32) v);
    method Bit#(32) get_debugind();
endinterface

interface ImageonVitaController;
    interface ImageonVita host;
    interface ImageonControl control;
endinterface

module mkImageonVitaController(ImageonVitaController);

    Reg#(Bit#(1)) host_vita_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) host_oe_reg <- mkReg(0);
    Wire#(Bit#(1)) host_clock_gen_locked_wire <- mkDWire(0);
    Reg#(Bit#(1)) spi_reset_reg <- mkReg(0);
    Reg#(Bit#(16)) spi_timing_reg <- mkReg(0);

    Wire#(Bit#(1)) spi_status_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_status_error_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_full_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_wen_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_txfifo_din_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_ren_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_rxfifo_dout_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_empty_wire <- mkDWire(0);
    Reg#(Bool) spi_rxfifo_requested_reg <- mkReg(False);

    Reg#(Bit#(1)) serdes_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_auto_align_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_align_start_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_fifo_enable_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_manual_tap_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_training_reg <- mkReg(0);
    Wire#(Bit#(1)) serdes_clk_ready_wire <- mkDWire(0);
    Wire#(Bit#(16)) serdes_clk_status_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_align_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_aligned_wire <- mkDWire(0);

    Reg#(Bit#(1)) decoder_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) decoder_enable_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_ls_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_le_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fs_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fe_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_bl_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_img_reg <- mkReg(0);
    Wire#(Bit#(1)) decoder_frame_start_wire <- mkDWire(0);
    Wire#(Bit#(10)) decoder_video_data_wire <- mkDWire(0);

    Reg#(Bit#(3)) trigger_enable_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_default_freq_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0high_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0low_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_delay_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hbporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vbporch_reg <- mkReg(0);
    Reg#(Bit#(32)) debugreq_value <- mkReg(0);
    Reg#(Bit#(32)) debugind_value <- mkReg(0);

    interface ImageonVita host;
	method Bit#(1) host_vita_reset();
	    return host_vita_reset_reg;
	endmethod
	method Bit#(1) host_oe();
	    return host_oe_reg;
	endmethod
	interface ImageonSpi spi;
	    method Bit#(1) reset();
		return spi_reset_reg;
	    endmethod
	    method Bit#(16) timing();
		return spi_timing_reg;
	    endmethod
	    method Action status_busy(Bit#(1) busy);
	        spi_status_busy_wire <= busy;
	    endmethod
	    method Action status_error(Bit#(1) error);
	        spi_status_error_wire <= error;
	    endmethod
	    method Bit#(1) txfifo_wen();
		return spi_txfifo_wen_wire;
	    endmethod
	    method Bit#(32) txfifo_din();
		return spi_txfifo_din_wire;
	    endmethod
	    method Action txfifo_full(Bit#(1) full);
	        spi_txfifo_full_wire <= full;
	    endmethod
	    method Bit#(1) rxfifo_ren();
		return spi_rxfifo_ren_wire;
	    endmethod
	    method Action rxfifo_dout(Bit#(32) dout);
	        spi_rxfifo_dout_wire <= dout;
	    endmethod
	    method Action rxfifo_empty(Bit#(1) empty);
	        spi_rxfifo_empty_wire <= empty;
	    endmethod
	endinterface
	interface ImageonSerdes serdes;
	    method Bit#(1) reset();
		return serdes_reset_reg;
	    endmethod
	    method Bit#(1) auto_align();
		return serdes_auto_align_reg;
	    endmethod
	    method Bit#(1) align_start();
		return serdes_align_start_reg;
	    endmethod
	    method Bit#(1) fifo_enable();
		return serdes_fifo_enable_reg;
	    endmethod
	    method Bit#(10) manual_tap();
		return serdes_manual_tap_reg;
	    endmethod
	    method Bit#(10) training();
		return serdes_training_reg;
	    endmethod
	    method Action iserdes_clk_ready(Bit#(1) ready);
	        serdes_clk_ready_wire <= ready;
	    endmethod
	    method Action iserdes_clk_status(Bit#(16) status);
	        serdes_clk_status_wire <= status;
	    endmethod
	    method Action iserdes_align_busy(Bit#(1) busy);
	        serdes_align_busy_wire <= busy;
	    endmethod
	    method Action iserdes_aligned(Bit#(1) aligned);
	        serdes_aligned_wire <= aligned;
	    endmethod
	endinterface
	interface ImageonDecoder decoder;
	    method Bit#(1) reset();
		return decoder_reset_reg;
	    endmethod
	    method Bit#(1) enable();
		return decoder_enable_reg;
	    endmethod
	    method Bit#(10) code_ls();
		return decoder_code_ls_reg;
	    endmethod
	    method Bit#(10) code_le();
		return decoder_code_le_reg;
	    endmethod
	    method Bit#(10) code_fs();
		return decoder_code_fs_reg;
	    endmethod
	    method Bit#(10) code_fe();
		return decoder_code_fe_reg;
	    endmethod
	    method Bit#(10) code_bl();
		return decoder_code_bl_reg;
	    endmethod
	    method Bit#(10) code_img();
		return decoder_code_img_reg;
	    endmethod
	    method Action frame_start(Bit#(1) start);
	        decoder_frame_start_wire <= start;
	    endmethod
	endinterface
	interface ImageonTrigger trigger;
	    method Bit#(3) enable();
		return trigger_enable_reg;
	    endmethod
	    method Bit#(32) default_freq();
		return trigger_default_freq_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0high();
		return trigger_cnt_trigger0high_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0low();
		return trigger_cnt_trigger0low_reg;
	    endmethod
	endinterface
	interface ImageonSyncGen syncgen;
	    method Bit#(16) delay();
		return syncgen_delay_reg;
	    endmethod
	    method Bit#(16) hactive();
		return syncgen_hactive_reg;
	    endmethod
	    method Bit#(16) hfporch();
		return syncgen_hfporch_reg;
	    endmethod
	    method Bit#(16) hsync();
		return syncgen_hsync_reg;
	    endmethod
	    method Bit#(16) hbporch();
		return syncgen_hbporch_reg;
	    endmethod
	    method Bit#(16) vactive();
		return syncgen_vactive_reg;
	    endmethod
	    method Bit#(16) vfporch();
		return syncgen_vfporch_reg;
	    endmethod
	    method Bit#(16) vsync();
		return syncgen_vsync_reg;
	    endmethod
	    method Bit#(16) vbporch();
		return syncgen_vbporch_reg;
	    endmethod
	endinterface
        method Bit#(32) get_debugreq();
            return debugreq_value;
	endmethod
        method Action set_debugind(Bit#(32) v);
            debugind_value <= v;
	endmethod
    endinterface
    interface ImageonControl control;
// SPI_CONTROL
//    [ 0] VITA_RESET
//    [ 1] SPI_RESET
//    [ 8] SPI_STATUS_BUSY
//    [ 9] SPI_STATUS_ERROR
//    [16] SPI_TXFIFO_FULL
//    [24] SPI_RXFIFO_EMPTY
	method Action set_spi_control(Bit#(32) v);
            host_vita_reset_reg <= v[0];
            spi_reset_reg <= v[1];
	endmethod
	method Bit#(32) get_spi_control();
	    let v = 0;
            v[0] = host_vita_reset_reg;
	    v[1] = spi_reset_reg;
	    v[8] = spi_status_busy_wire;
	    v[9] = spi_status_error_wire;
	    v[16] = spi_txfifo_full_wire;
	    v[24] = spi_rxfifo_empty_wire;
	    return v;
	endmethod

// ISERDES_CONTROL
//    [ 0] ISERDES_RESET
//    [ 1] ISERDES_AUTO_ALIGN
//    [ 2] ISERDES_ALIGN_START
//    [ 3] ISERDES_FIFO_ENABLE
//    [ 8] ISERDES_CLK_READY
//    [ 9] ISERDES_ALIGN_BUSY
//    [10] ISERDES_ALIGNED
// [23:16] ISERDES_TXCLK_STATUS
// [31:24] ISERDES_RXCLK_STATUS
	method Action set_iserdes_control(Bit#(32) v);
	    serdes_reset_reg <= v[0];
	    serdes_auto_align_reg <= v[1];
	    serdes_align_start_reg <= v[2];
	    serdes_fifo_enable_reg <= v[3];
	endmethod
	method Bit#(32) get_iserdes_control();
	    let v = 0;
	    v[0] = serdes_reset_reg;
	    v[1] = serdes_auto_align_reg;
	    v[2] = serdes_align_start_reg;
	    v[3] = serdes_fifo_enable_reg;
	    v[8] = serdes_clk_ready_wire;
	    v[9] = serdes_align_busy_wire;
	    v[10] = serdes_aligned_wire;
	    v[31:16] = serdes_clk_status_wire;
	    return v;
	endmethod
// DECODER_CONTROL[7:0]
//    [0] DECODER_RESET
//    [1] DECODER_ENABLE
	method Action set_decoder_control(Bit#(32) v);
	    decoder_reset_reg <= v[0];
	    decoder_enable_reg <= v[1];
	endmethod
	method Bit#(32) get_decoder_control();
	    let v = 0;
	    v[0] = decoder_reset_reg;
	    v[1] = decoder_enable_reg;
	    return v;
	endmethod
// TRIGGEN_CONTROL
// [ 2: 0] TRIGGEN_ENABLE
// [ 6: 4] TRIGGEN_SYNC2READOUT
// [    8] TRIGGEN_READOUTTRIGGER
// [   16] TRIGGEN_EXT_POLARITY
// [   24] TRIGGEN_CNT_UPDATE
// [30:28] TRIGGEN_GEN_POLARITY
	method Action set_triggen_control(Bit#(32) v);
	    trigger_enable_reg <= v[2:0];
	endmethod
	method Bit#(32) get_triggen_control();
	    let v = 0;
	    v[2:0] = trigger_enable_reg;
	    return v;
	endmethod

	method Action set_host_vita_reset(Bit#(1) v);
	    host_vita_reset_reg <= v;
	endmethod
	method Action set_host_oe(Bit#(1) v);
	    host_oe_reg <= v;
	endmethod

	method Action set_spi_reset(Bit#(1) v);
	    spi_reset_reg <= v;
	endmethod
	method Action set_spi_timing(Bit#(16) v);
	    spi_timing_reg <= v;
	endmethod
	interface Put txfifo;
	    method Action put(Bit#(32) v) if (spi_txfifo_full_wire == 0);
	        spi_txfifo_wen_wire <= 1;
		spi_txfifo_din_wire <= v;
	    endmethod
	endinterface
        interface Put rxfifo_request;
	    method Action put(Bit#(32) v) if (!spi_rxfifo_requested_reg && (spi_rxfifo_empty_wire == 0));
	        spi_rxfifo_requested_reg <= True;
		spi_rxfifo_ren_wire <= 1;
	    endmethod
	endinterface
	interface Get rxfifo_response;
	    method ActionValue#(Bit#(32)) get() if (spi_rxfifo_requested_reg);
	        spi_rxfifo_requested_reg <= False;
		return spi_rxfifo_dout_wire;
	    endmethod
	endinterface
	method Action set_serdes_reset(Bit#(1) v);
	    serdes_reset_reg <= v;
	endmethod
	method Action set_serdes_auto_align(Bit#(1) v);
	    serdes_auto_align_reg <= v;
	endmethod
	method Action set_serdes_align_start(Bit#(1) v);
	    serdes_align_start_reg <= v;
	endmethod
	method Action set_serdes_fifo_enable(Bit#(1) v);
	    serdes_fifo_enable_reg <= v;
	endmethod
	method Action set_serdes_manual_tap(Bit#(10) v);
	    serdes_manual_tap_reg <= v;
	endmethod
	method Action set_serdes_training(Bit#(10) v);
	    serdes_training_reg <= v;
	endmethod
	method Action set_decoder_reset(Bit#(1) v);
	    decoder_reset_reg <= v;
	endmethod
	method Action set_decoder_enable(Bit#(1) v);
	    decoder_enable_reg <= v;
	endmethod
	method Action set_decoder_code_ls(Bit#(10) v);
	    decoder_code_ls_reg <= v;
	endmethod
	method Action set_decoder_code_le(Bit#(10) v);
	    decoder_code_le_reg <= v;
	endmethod
	method Action set_decoder_code_fs(Bit#(10) v);
	    decoder_code_fs_reg <= v;
	endmethod
	method Action set_decoder_code_fe(Bit#(10) v);
	    decoder_code_fe_reg <= v;
	endmethod
	method Action set_decoder_code_bl(Bit#(10) v);
	    decoder_code_bl_reg <= v;
	endmethod
	method Action set_decoder_code_img(Bit#(10) v);
	    decoder_code_img_reg <= v;
	endmethod
	method Action set_trigger_enable(Bit#(3) v);
	    trigger_enable_reg <= v;
	endmethod
	method Action set_trigger_default_freq(Bit#(32) v);
	    trigger_default_freq_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0high(Bit#(32) v);
	    trigger_cnt_trigger0high_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0low(Bit#(32) v);
	    trigger_cnt_trigger0low_reg <= v;
	endmethod
	method Action set_syncgen_delay(Bit#(16) v);
	    syncgen_delay_reg <= v;
	endmethod
	method Action set_syncgen_hactive(Bit#(16) v);
	    syncgen_hactive_reg <= v;
	endmethod
	method Action set_syncgen_hfporch(Bit#(16) v);
	    syncgen_hfporch_reg <= v;
	endmethod
	method Action set_syncgen_hsync(Bit#(16) v);
	    syncgen_hsync_reg <= v;
	endmethod
	method Action set_syncgen_hbporch(Bit#(16) v);
	    syncgen_hbporch_reg <= v;
	endmethod
	method Action set_syncgen_vactive(Bit#(16) v);
	    syncgen_vactive_reg <= v;
	endmethod
	method Action set_syncgen_vfporch(Bit#(16) v);
	    syncgen_vfporch_reg <= v;
	endmethod
	method Action set_syncgen_vsync(Bit#(16) v);
	    syncgen_vsync_reg <= v;
	endmethod
	method Action set_syncgen_vbporch(Bit#(16) v);
	    syncgen_vbporch_reg <= v;
	endmethod
        method Action set_debugreq(Bit#(32) v);
            debugreq_value <= v;
	endmethod
        method Bit#(32) get_debugind();
            return debugind_value;
	endmethod
    endinterface
endmodule

interface ImageonXsviFromSensor;
    interface ImageonSensorData in;
    interface Get#(XsviData) out;
endinterface

typedef enum { Idle, Active, FrontP, Sync, BackP} State deriving (Bits,Eq);

module mkImageonXsviFromSensor#(Clock slow_clock, Reset slow_reset)(ImageonXsviFromSensor);
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    Gearbox#(4, 1, Bit#(10)) dataGearbox <- mkNto1Gearbox(slow_clock, slow_reset, defaultClock, defaultReset);
    Gearbox#(4, 1, Bit#(1))  syncGearbox <- mkNto1Gearbox(slow_clock, slow_reset, defaultClock, defaultReset);

    Reg#(Bit#(1)) vsync_reg <- mkReg(0);
    Reg#(Bit#(1)) hsync_reg <- mkReg(0);
    Reg#(Bit#(1)) active_video_reg <- mkReg(0);
    Wire#(Bit#(1))  xsvi_framestart_old_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_hsync_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_vsync_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_active_video_wire <- mkDWire(0);
    Wire#(Bit#(10)) xsvi_video_data_wire <- mkDWire(0);

    Reg#(Bit#(1))     framestart <- mkReg(0);
    Reg#(State)       hstate <- mkReg(Idle);
    Reg#(State)       vstate <- mkReg(Idle);
    Reg#(Bit#(16))    vsync_count <- mkReg(0);
    Reg#(Bit#(16))    hsync_count <- mkReg(0);
    Reg#(Bit#(16))    host_syncgen_hactive <- mkReg(0);
    Reg#(Bit#(16))    host_syncgen_hfporch <- mkReg(0);
    Reg#(Bit#(16))    host_syncgen_hbporch <- mkReg(0);
    Reg#(Bit#(16))    host_syncgen_hsync <- mkReg(0);
    Reg#(Bit#(16))    host_syncgen_vactive <- mkReg(0);
    Reg#(Bit#(16))    host_syncgen_vfporch <- mkReg(0);
    Reg#(Bit#(16))    host_syncgen_vsync <- mkReg(0);

    rule start_fsm if (framestart == 1);
        vsync_count <= 0;
        hsync_count <= 0;
        hstate <= Active;
        vstate <= Active;
    endrule

    rule sync_fsm if (framestart != 1);
        let hs = hstate;
        let vs = vstate;
        let hc = hsync_count;
        let vc = vsync_count;

        hc = hc + 1;
        if (hstate == FrontP && hsync_count >= host_syncgen_hfporch - 1)
            begin
            hc = 0;
            hs = Sync;
            vc = vc + 1;
            if (vstate == Active && vsync_count >= host_syncgen_vactive - 1)
                begin
                vc = 0;
                vs = FrontP;
                end
            if (vstate == FrontP && vsync_count >= host_syncgen_vfporch - 1)
                begin
                vc = 0;
                vs = Sync;
                end
            if (vstate == Sync && vsync_count >= host_syncgen_vsync - 1)
                begin
                vc = 0;
                vs = BackP;
                end
            end
        if (hstate == Sync && hsync_count >= host_syncgen_hsync - 1)
            begin
            hc = 0;
            hs = BackP;
            end
        if (hstate == BackP && hsync_count >= host_syncgen_hbporch - 1)
            begin
            hc = 0;
            hs = Active;
            end
        if (hstate == Active && hsync_count >= host_syncgen_hactive - 1)
            begin
            hc = 0;
            hs = FrontP;
            end

        hstate <= hs;
        vstate <= vs;
        hsync_count <= hc;
        vsync_count <= vc;
    endrule

    interface ImageonSensorData in;
        method Action fsync(Bit#(1) v);
	    xsvi_framestart_old_wire <= v;
	endmethod
        method Action hsync(Bit#(1) v);
	    xsvi_hsync_wire <= v;
	endmethod
        method Action vsync(Bit#(1) v);
	    xsvi_vsync_wire <= v;
	endmethod
        method Action active_video(Bit#(1) v);
            xsvi_active_video_wire <= v;
        endmethod
	method Action video_data_old(Bit#(10) v);
            xsvi_video_data_wire <= v;
	endmethod
	method Action framestart(Bit#(1) v);
	    Vector#(4, Bit#(1)) in = replicate(0);
	    // zero'th element shifted out first
	    in[0] = v;
	    syncGearbox.enq(in);
	endmethod
	method Action video_data(Bit#(40) v);
	    // least signifcant 10 bits shifted out first
	    Vector#(4, Bit#(10)) in = unpack(v);
	    dataGearbox.enq(in);
	endmethod
    endinterface
    interface Get out;
	method ActionValue#(XsviData) get();
	    //dataGearbox.deq;
	    //syncGearbox.deq;
	    return XsviData {
		fsync: xsvi_framestart_old_wire, //syncGearbox.first[0],
		vsync: xsvi_vsync_wire,
		hsync: xsvi_hsync_wire,
		active_video: xsvi_active_video_wire,
		video_data: xsvi_video_data_wire //dataGearbox.first[0]
	    };
	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.

import Vector::*;
import FIFO::*;
import GetPut::*;
import Gearbox::*;

interface ImageonSpi;
    method Bit#(1) reset();
    method Bit#(16) timing();
    method Action status_busy(Bit#(1) busy);
    method Action status_error(Bit#(1) error);
    method Bit#(1) txfifo_wen();
    method Bit#(32) txfifo_din();
    method Action txfifo_full(Bit#(1) full);
    method Bit#(1) rxfifo_ren();
    method Action rxfifo_dout(Bit#(32) dout);
    method Action rxfifo_empty(Bit#(1) empty);
endinterface

interface ImageonSerdes;
    method Bit#(1) reset();
    method Bit#(1) auto_align();
    method Bit#(1) align_start();
    method Bit#(1) fifo_enable();
    method Bit#(10) manual_tap();
    method Bit#(10) training();
    method Action iserdes_clk_ready(Bit#(1) ready);
    method Action iserdes_clk_status(Bit#(16) status);
    method Action iserdes_align_busy(Bit#(1) busy);
    method Action iserdes_aligned(Bit#(1) aligned);
endinterface

interface ImageonDecoder;
    method Bit#(1) reset();
    method Bit#(1) enable();
    method Bit#(10) code_ls();
    method Bit#(10) code_le();
    method Bit#(10) code_fs();
    method Bit#(10) code_fe();
    method Bit#(10) code_bl();
    method Bit#(10) code_img();
    method Action frame_start(Bit#(1) start);
endinterface

interface ImageonTrigger;
    method Bit#(3) enable();
    method Bit#(32) default_freq();
    method Bit#(32) cnt_trigger0high();
    method Bit#(32) cnt_trigger0low();
endinterface

interface ImageonSyncGen;
    method Bit#(16) delay();
    method Bit#(16) hactive();
    method Bit#(16) hfporch();
    method Bit#(16) hsync();
    method Bit#(16) hbporch();
    method Bit#(16) vactive();
    method Bit#(16) vfporch();
    method Bit#(16) vsync();
    method Bit#(16) vbporch();
endinterface

typedef struct {
    Bit#(1) fsync;
    Bit#(1) vsync;
    Bit#(1) hsync;
    Bit#(1) active_video;
    Bit#(10) video_data;
} XsviData deriving (Bits);

interface ImageonSensorData;
    method Action fsync(Bit#(1) v);
    method Action hsync(Bit#(1) v);
    method Action vsync(Bit#(1) v);
    method Action active_video(Bit#(1) v);
    method Action video_data_old(Bit#(10) v);
    method Action framestart(Bit#(1) v);
    method Action video_data(Bit#(40) v);
endinterface

(* always_enabled *)
interface ImageonVita;
    method Bit#(1) host_vita_reset();
    method Bit#(1) host_oe();
    interface ImageonSpi spi;
    interface ImageonSerdes serdes;
    interface ImageonDecoder decoder;
    interface ImageonTrigger trigger;
    interface ImageonSyncGen syncgen;
    method Bit#(32) get_debugreq();
    method Action set_debugind(Bit#(32) v);
endinterface

interface ImageonControl;
    method Action set_spi_control(Bit#(32) v);
    method Bit#(32) get_spi_control();
    method Action set_iserdes_control(Bit#(32) v);
    method Bit#(32) get_iserdes_control();
    method Action set_decoder_control(Bit#(32) v);
    method Bit#(32) get_decoder_control();
    method Action set_triggen_control(Bit#(32) v);
    method Bit#(32) get_triggen_control();

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

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

    interface Put#(Bit#(32)) txfifo;
    interface Put#(Bit#(32)) rxfifo_request;
    interface Get#(Bit#(32)) rxfifo_response;

    method Action set_serdes_reset(Bit#(1) v);
    method Action set_serdes_auto_align(Bit#(1) v);
    method Action set_serdes_align_start(Bit#(1) v);
    method Action set_serdes_fifo_enable(Bit#(1) v);
    method Action set_serdes_manual_tap(Bit#(10) v);
    method Action set_serdes_training(Bit#(10) v);
    method Action set_decoder_reset(Bit#(1) v);
    method Action set_decoder_enable(Bit#(1) v);
    method Action set_decoder_code_ls(Bit#(10) v);
    method Action set_decoder_code_le(Bit#(10) v);
    method Action set_decoder_code_fs(Bit#(10) v);
    method Action set_decoder_code_fe(Bit#(10) v);
    method Action set_decoder_code_bl(Bit#(10) v);
    method Action set_decoder_code_img(Bit#(10) v);
    method Action set_trigger_enable(Bit#(3) v);
    method Action set_trigger_default_freq(Bit#(32) v);
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
    method Action set_syncgen_delay(Bit#(16) v);
    method Action set_syncgen_hactive(Bit#(16) v);
    method Action set_syncgen_hfporch(Bit#(16) v);
    method Action set_syncgen_hsync(Bit#(16) v);
    method Action set_syncgen_hbporch(Bit#(16) v);
    method Action set_syncgen_vactive(Bit#(16) v);
    method Action set_syncgen_vfporch(Bit#(16) v);
    method Action set_syncgen_vsync(Bit#(16) v);
    method Action set_syncgen_vbporch(Bit#(16) v);
    method Action set_debugreq(Bit#(32) v);
    method Bit#(32) get_debugind();
endinterface

interface ImageonVitaController;
    interface ImageonVita host;
    interface ImageonControl control;
endinterface

module mkImageonVitaController(ImageonVitaController);

    Reg#(Bit#(1)) host_vita_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) host_oe_reg <- mkReg(0);
    Wire#(Bit#(1)) host_clock_gen_locked_wire <- mkDWire(0);
    Reg#(Bit#(1)) spi_reset_reg <- mkReg(0);
    Reg#(Bit#(16)) spi_timing_reg <- mkReg(0);

    Wire#(Bit#(1)) spi_status_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_status_error_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_full_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_txfifo_wen_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_txfifo_din_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_ren_wire <- mkDWire(0);
    Wire#(Bit#(32)) spi_rxfifo_dout_wire <- mkDWire(0);
    Wire#(Bit#(1)) spi_rxfifo_empty_wire <- mkDWire(0);
    Reg#(Bool) spi_rxfifo_requested_reg <- mkReg(False);

    Reg#(Bit#(1)) serdes_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_auto_align_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_align_start_reg <- mkReg(0);
    Reg#(Bit#(1)) serdes_fifo_enable_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_manual_tap_reg <- mkReg(0);
    Reg#(Bit#(10)) serdes_training_reg <- mkReg(0);
    Wire#(Bit#(1)) serdes_clk_ready_wire <- mkDWire(0);
    Wire#(Bit#(16)) serdes_clk_status_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_align_busy_wire <- mkDWire(0);
    Wire#(Bit#(1)) serdes_aligned_wire <- mkDWire(0);

    Reg#(Bit#(1)) decoder_reset_reg <- mkReg(0);
    Reg#(Bit#(1)) decoder_enable_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_ls_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_le_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fs_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_fe_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_bl_reg <- mkReg(0);
    Reg#(Bit#(10)) decoder_code_img_reg <- mkReg(0);
    Wire#(Bit#(1)) decoder_frame_start_wire <- mkDWire(0);
    Wire#(Bit#(10)) decoder_video_data_wire <- mkDWire(0);

    Reg#(Bit#(3)) trigger_enable_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_default_freq_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0high_reg <- mkReg(0);
    Reg#(Bit#(32)) trigger_cnt_trigger0low_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_delay_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_hbporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vactive_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vfporch_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vsync_reg <- mkReg(0);
    Reg#(Bit#(16)) syncgen_vbporch_reg <- mkReg(0);
    Reg#(Bit#(32)) debugreq_value <- mkReg(0);
    Reg#(Bit#(32)) debugind_value <- mkReg(0);

    interface ImageonVita host;
	method Bit#(1) host_vita_reset();
	    return host_vita_reset_reg;
	endmethod
	method Bit#(1) host_oe();
	    return host_oe_reg;
	endmethod
	interface ImageonSpi spi;
	    method Bit#(1) reset();
		return spi_reset_reg;
	    endmethod
	    method Bit#(16) timing();
		return spi_timing_reg;
	    endmethod
	    method Action status_busy(Bit#(1) busy);
	        spi_status_busy_wire <= busy;
	    endmethod
	    method Action status_error(Bit#(1) error);
	        spi_status_error_wire <= error;
	    endmethod
	    method Bit#(1) txfifo_wen();
		return spi_txfifo_wen_wire;
	    endmethod
	    method Bit#(32) txfifo_din();
		return spi_txfifo_din_wire;
	    endmethod
	    method Action txfifo_full(Bit#(1) full);
	        spi_txfifo_full_wire <= full;
	    endmethod
	    method Bit#(1) rxfifo_ren();
		return spi_rxfifo_ren_wire;
	    endmethod
	    method Action rxfifo_dout(Bit#(32) dout);
	        spi_rxfifo_dout_wire <= dout;
	    endmethod
	    method Action rxfifo_empty(Bit#(1) empty);
	        spi_rxfifo_empty_wire <= empty;
	    endmethod
	endinterface
	interface ImageonSerdes serdes;
	    method Bit#(1) reset();
		return serdes_reset_reg;
	    endmethod
	    method Bit#(1) auto_align();
		return serdes_auto_align_reg;
	    endmethod
	    method Bit#(1) align_start();
		return serdes_align_start_reg;
	    endmethod
	    method Bit#(1) fifo_enable();
		return serdes_fifo_enable_reg;
	    endmethod
	    method Bit#(10) manual_tap();
		return serdes_manual_tap_reg;
	    endmethod
	    method Bit#(10) training();
		return serdes_training_reg;
	    endmethod
	    method Action iserdes_clk_ready(Bit#(1) ready);
	        serdes_clk_ready_wire <= ready;
	    endmethod
	    method Action iserdes_clk_status(Bit#(16) status);
	        serdes_clk_status_wire <= status;
	    endmethod
	    method Action iserdes_align_busy(Bit#(1) busy);
	        serdes_align_busy_wire <= busy;
	    endmethod
	    method Action iserdes_aligned(Bit#(1) aligned);
	        serdes_aligned_wire <= aligned;
	    endmethod
	endinterface
	interface ImageonDecoder decoder;
	    method Bit#(1) reset();
		return decoder_reset_reg;
	    endmethod
	    method Bit#(1) enable();
		return decoder_enable_reg;
	    endmethod
	    method Bit#(10) code_ls();
		return decoder_code_ls_reg;
	    endmethod
	    method Bit#(10) code_le();
		return decoder_code_le_reg;
	    endmethod
	    method Bit#(10) code_fs();
		return decoder_code_fs_reg;
	    endmethod
	    method Bit#(10) code_fe();
		return decoder_code_fe_reg;
	    endmethod
	    method Bit#(10) code_bl();
		return decoder_code_bl_reg;
	    endmethod
	    method Bit#(10) code_img();
		return decoder_code_img_reg;
	    endmethod
	    method Action frame_start(Bit#(1) start);
	        decoder_frame_start_wire <= start;
	    endmethod
	endinterface
	interface ImageonTrigger trigger;
	    method Bit#(3) enable();
		return trigger_enable_reg;
	    endmethod
	    method Bit#(32) default_freq();
		return trigger_default_freq_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0high();
		return trigger_cnt_trigger0high_reg;
	    endmethod
	    method Bit#(32) cnt_trigger0low();
		return trigger_cnt_trigger0low_reg;
	    endmethod
	endinterface
	interface ImageonSyncGen syncgen;
	    method Bit#(16) delay();
		return syncgen_delay_reg;
	    endmethod
	    method Bit#(16) hactive();
		return syncgen_hactive_reg;
	    endmethod
	    method Bit#(16) hfporch();
		return syncgen_hfporch_reg;
	    endmethod
	    method Bit#(16) hsync();
		return syncgen_hsync_reg;
	    endmethod
	    method Bit#(16) hbporch();
		return syncgen_hbporch_reg;
	    endmethod
	    method Bit#(16) vactive();
		return syncgen_vactive_reg;
	    endmethod
	    method Bit#(16) vfporch();
		return syncgen_vfporch_reg;
	    endmethod
	    method Bit#(16) vsync();
		return syncgen_vsync_reg;
	    endmethod
	    method Bit#(16) vbporch();
		return syncgen_vbporch_reg;
	    endmethod
	endinterface
        method Bit#(32) get_debugreq();
            return debugreq_value;
	endmethod
        method Action set_debugind(Bit#(32) v);
            debugind_value <= v;
	endmethod
    endinterface
    interface ImageonControl control;
// SPI_CONTROL
//    [ 0] VITA_RESET
//    [ 1] SPI_RESET
//    [ 8] SPI_STATUS_BUSY
//    [ 9] SPI_STATUS_ERROR
//    [16] SPI_TXFIFO_FULL
//    [24] SPI_RXFIFO_EMPTY
	method Action set_spi_control(Bit#(32) v);
            host_vita_reset_reg <= v[0];
            spi_reset_reg <= v[1];
	endmethod
	method Bit#(32) get_spi_control();
	    let v = 0;
            v[0] = host_vita_reset_reg;
	    v[1] = spi_reset_reg;
	    v[8] = spi_status_busy_wire;
	    v[9] = spi_status_error_wire;
	    v[16] = spi_txfifo_full_wire;
	    v[24] = spi_rxfifo_empty_wire;
	    return v;
	endmethod

// ISERDES_CONTROL
//    [ 0] ISERDES_RESET
//    [ 1] ISERDES_AUTO_ALIGN
//    [ 2] ISERDES_ALIGN_START
//    [ 3] ISERDES_FIFO_ENABLE
//    [ 8] ISERDES_CLK_READY
//    [ 9] ISERDES_ALIGN_BUSY
//    [10] ISERDES_ALIGNED
// [23:16] ISERDES_TXCLK_STATUS
// [31:24] ISERDES_RXCLK_STATUS
	method Action set_iserdes_control(Bit#(32) v);
	    serdes_reset_reg <= v[0];
	    serdes_auto_align_reg <= v[1];
	    serdes_align_start_reg <= v[2];
	    serdes_fifo_enable_reg <= v[3];
	endmethod
	method Bit#(32) get_iserdes_control();
	    let v = 0;
	    v[0] = serdes_reset_reg;
	    v[1] = serdes_auto_align_reg;
	    v[2] = serdes_align_start_reg;
	    v[3] = serdes_fifo_enable_reg;
	    v[8] = serdes_clk_ready_wire;
	    v[9] = serdes_align_busy_wire;
	    v[10] = serdes_aligned_wire;
	    v[31:16] = serdes_clk_status_wire;
	    return v;
	endmethod
// DECODER_CONTROL[7:0]
//    [0] DECODER_RESET
//    [1] DECODER_ENABLE
	method Action set_decoder_control(Bit#(32) v);
	    decoder_reset_reg <= v[0];
	    decoder_enable_reg <= v[1];
	endmethod
	method Bit#(32) get_decoder_control();
	    let v = 0;
	    v[0] = decoder_reset_reg;
	    v[1] = decoder_enable_reg;
	    return v;
	endmethod
// TRIGGEN_CONTROL
// [ 2: 0] TRIGGEN_ENABLE
// [ 6: 4] TRIGGEN_SYNC2READOUT
// [    8] TRIGGEN_READOUTTRIGGER
// [   16] TRIGGEN_EXT_POLARITY
// [   24] TRIGGEN_CNT_UPDATE
// [30:28] TRIGGEN_GEN_POLARITY
	method Action set_triggen_control(Bit#(32) v);
	    trigger_enable_reg <= v[2:0];
	endmethod
	method Bit#(32) get_triggen_control();
	    let v = 0;
	    v[2:0] = trigger_enable_reg;
	    return v;
	endmethod

	method Action set_host_vita_reset(Bit#(1) v);
	    host_vita_reset_reg <= v;
	endmethod
	method Action set_host_oe(Bit#(1) v);
	    host_oe_reg <= v;
	endmethod

	method Action set_spi_reset(Bit#(1) v);
	    spi_reset_reg <= v;
	endmethod
	method Action set_spi_timing(Bit#(16) v);
	    spi_timing_reg <= v;
	endmethod
	interface Put txfifo;
	    method Action put(Bit#(32) v) if (spi_txfifo_full_wire == 0);
	        spi_txfifo_wen_wire <= 1;
		spi_txfifo_din_wire <= v;
	    endmethod
	endinterface
        interface Put rxfifo_request;
	    method Action put(Bit#(32) v) if (!spi_rxfifo_requested_reg && (spi_rxfifo_empty_wire == 0));
	        spi_rxfifo_requested_reg <= True;
		spi_rxfifo_ren_wire <= 1;
	    endmethod
	endinterface
	interface Get rxfifo_response;
	    method ActionValue#(Bit#(32)) get() if (spi_rxfifo_requested_reg);
	        spi_rxfifo_requested_reg <= False;
		return spi_rxfifo_dout_wire;
	    endmethod
	endinterface
	method Action set_serdes_reset(Bit#(1) v);
	    serdes_reset_reg <= v;
	endmethod
	method Action set_serdes_auto_align(Bit#(1) v);
	    serdes_auto_align_reg <= v;
	endmethod
	method Action set_serdes_align_start(Bit#(1) v);
	    serdes_align_start_reg <= v;
	endmethod
	method Action set_serdes_fifo_enable(Bit#(1) v);
	    serdes_fifo_enable_reg <= v;
	endmethod
	method Action set_serdes_manual_tap(Bit#(10) v);
	    serdes_manual_tap_reg <= v;
	endmethod
	method Action set_serdes_training(Bit#(10) v);
	    serdes_training_reg <= v;
	endmethod
	method Action set_decoder_reset(Bit#(1) v);
	    decoder_reset_reg <= v;
	endmethod
	method Action set_decoder_enable(Bit#(1) v);
	    decoder_enable_reg <= v;
	endmethod
	method Action set_decoder_code_ls(Bit#(10) v);
	    decoder_code_ls_reg <= v;
	endmethod
	method Action set_decoder_code_le(Bit#(10) v);
	    decoder_code_le_reg <= v;
	endmethod
	method Action set_decoder_code_fs(Bit#(10) v);
	    decoder_code_fs_reg <= v;
	endmethod
	method Action set_decoder_code_fe(Bit#(10) v);
	    decoder_code_fe_reg <= v;
	endmethod
	method Action set_decoder_code_bl(Bit#(10) v);
	    decoder_code_bl_reg <= v;
	endmethod
	method Action set_decoder_code_img(Bit#(10) v);
	    decoder_code_img_reg <= v;
	endmethod
	method Action set_trigger_enable(Bit#(3) v);
	    trigger_enable_reg <= v;
	endmethod
	method Action set_trigger_default_freq(Bit#(32) v);
	    trigger_default_freq_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0high(Bit#(32) v);
	    trigger_cnt_trigger0high_reg <= v;
	endmethod
	method Action set_trigger_cnt_trigger0low(Bit#(32) v);
	    trigger_cnt_trigger0low_reg <= v;
	endmethod
	method Action set_syncgen_delay(Bit#(16) v);
	    syncgen_delay_reg <= v;
	endmethod
	method Action set_syncgen_hactive(Bit#(16) v);
	    syncgen_hactive_reg <= v;
	endmethod
	method Action set_syncgen_hfporch(Bit#(16) v);
	    syncgen_hfporch_reg <= v;
	endmethod
	method Action set_syncgen_hsync(Bit#(16) v);
	    syncgen_hsync_reg <= v;
	endmethod
	method Action set_syncgen_hbporch(Bit#(16) v);
	    syncgen_hbporch_reg <= v;
	endmethod
	method Action set_syncgen_vactive(Bit#(16) v);
	    syncgen_vactive_reg <= v;
	endmethod
	method Action set_syncgen_vfporch(Bit#(16) v);
	    syncgen_vfporch_reg <= v;
	endmethod
	method Action set_syncgen_vsync(Bit#(16) v);
	    syncgen_vsync_reg <= v;
	endmethod
	method Action set_syncgen_vbporch(Bit#(16) v);
	    syncgen_vbporch_reg <= v;
	endmethod
        method Action set_debugreq(Bit#(32) v);
            debugreq_value <= v;
	endmethod
        method Bit#(32) get_debugind();
            return debugind_value;
	endmethod
    endinterface
endmodule

interface ImageonXsviFromSensor;
    interface ImageonSensorData in;
    interface Get#(XsviData) out;
endinterface

module mkImageonXsviFromSensor#(Clock slow_clock, Reset slow_reset)(ImageonXsviFromSensor);
    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    Gearbox#(4, 1, Bit#(10)) dataGearbox <- mkNto1Gearbox(slow_clock, slow_reset, defaultClock, defaultReset);
    Gearbox#(4, 1, Bit#(1))  syncGearbox <- mkNto1Gearbox(slow_clock, slow_reset, defaultClock, defaultReset);

    Reg#(Bit#(1)) vsync_reg <- mkReg(0);
    Reg#(Bit#(1)) hsync_reg <- mkReg(0);
    Reg#(Bit#(1)) active_video_reg <- mkReg(0);
    Wire#(Bit#(1))  xsvi_framestart_old_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_hsync_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_vsync_wire <- mkDWire(0);
    Wire#(Bit#(1))  xsvi_active_video_wire <- mkDWire(0);
    Wire#(Bit#(10)) xsvi_video_data_wire <- mkDWire(0);

    interface ImageonSensorData in;
        method Action fsync(Bit#(1) v);
	    xsvi_framestart_old_wire <= v;
	endmethod
        method Action hsync(Bit#(1) v);
	    xsvi_hsync_wire <= v;
	endmethod
        method Action vsync(Bit#(1) v);
	    xsvi_vsync_wire <= v;
	endmethod
        method Action active_video(Bit#(1) v);
            xsvi_active_video_wire <= v;
        endmethod
	method Action video_data_old(Bit#(10) v);
            xsvi_video_data_wire <= v;
	endmethod
	method Action framestart(Bit#(1) v);
	    Vector#(4, Bit#(1)) in = replicate(0);
	    // zero'th element shifted out first
	    in[0] = v;
	    syncGearbox.enq(in);
	endmethod
	method Action video_data(Bit#(40) v);
	    // least signifcant 10 bits shifted out first
	    Vector#(4, Bit#(10)) in = unpack(v);
	    dataGearbox.enq(in);
	endmethod
    endinterface
    interface Get out;
	method ActionValue#(XsviData) get();
	    //dataGearbox.deq;
	    //syncGearbox.deq;
	    return XsviData {
		fsync: xsvi_framestart_old_wire, //syncGearbox.first[0],
		vsync: xsvi_vsync_wire,
		hsync: xsvi_hsync_wire,
		active_video: xsvi_active_video_wire,
		video_data: xsvi_video_data_wire //dataGearbox.first[0]
	    };
	endmethod
    endinterface
endmodule


MemSlave.bsv is no longer used

MemSlave.bsv is no longer used

// 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 Clocks            :: *;
import GetPut            :: *;
import FIFO              :: *;
import Connectable       :: *;
import ClientServer      :: *;
import DefaultValue      :: *;
import PcieSplitter      :: *;
import PcieTracer        :: *;
import Xilinx            :: *;
import PCIEWRAPPER       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import MemSlaveEngine    :: *;
import MemMasterEngine   :: *;
import PcieCsr           :: *;
import MemTypes          :: *;
import Bscan             :: *;
`ifndef BSIM
import PcieEndpointX7    :: *;
`endif
import HostInterface    :: *;

`ifndef DataBusWidth
`define DataBusWidth 64
`endif
`ifndef PinType
`define PinType Empty
`endif

`ifdef USES_BSCAN
`define BSCAN_ARG  local_bscan
`else
`define BSCAN_ARG
`endif
typedef `PinType PinType;

// implemented in TlpReplay.cxx
import "BDPI" function Action put_tlp(TLPData#(16) d);
import "BDPI" function ActionValue#(TLPData#(16)) get_tlp();
import "BDPI" function Bool can_put_tlp();
import "BDPI" function Bool can_get_tlp();

(* synthesize *)
module  mkPcieHost#(PciId my_pciId)(PcieHost#(DataBusWidth, NumberOfMasters));
   Clock epClock125 <- exposeCurrentClock();
   Reset epReset125 <- exposeCurrentReset();
   let dispatcher <- mkTLPDispatcher;
   let arbiter    <- mkTLPArbiter;
   Vector#(NumberOfMasters,MemSlaveEngine#(DataBusWidth)) sEngine <- replicateM(mkMemSlaveEngine(my_pciId));
   Vector#(NumberOfMasters,MemSlave#(40,DataBusWidth)) slavearr;
   MemInterrupt intr <- mkMemInterrupt(my_pciId);
   BscanTop bscan <- mkBscanTop(3); // Use USER3  (JTAG IDCODE address 0x22)
   BscanLocal lbscan <- mkBscanLocal(bscan, clocked_by bscan.tck, reset_by bscan.rst);

   Vector#(PortMax, MemMasterEngine) mvec;
   for (Integer i = 0; i < valueOf(PortMax) - 1 + valueOf(NumberOfMasters); i=i+1) begin
       let tlp;
       if (i == portInterrupt)
           tlp = intr.tlp;
       else if (i >= portAxi) begin
           tlp = sEngine[i - portAxi].tlp;
           slavearr[i - portAxi] = sEngine[i - portAxi].slave;
       end
       else begin
           mvec[i] <- mkMemMasterEngine(my_pciId);
           tlp = mvec[i].tlp;
       end
       mkConnection((interface Server;
                        interface response = dispatcher.out[i];
                        interface request = arbiter.in[i];
                     endinterface), tlp);
   end

   PcieTracer  traceif <- mkPcieTracer();
   mkConnection(traceif.bus, (interface Client;
                                 interface request = arbiter.outToBus;
                                 interface response = dispatcher.inFromBus;
                              endinterface));
`ifndef BSIM
   Reg#(Bit#(TAdd#(TlpTraceAddrSize,1))) bscanPcieTraceBramWrAddrReg <- mkReg(0);
   BscanBram#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) pcieBscanBram <- mkBscanBram(127, bscanPcieTraceBramWrAddrReg, lbscan.loc[1]);
   mkConnection(pcieBscanBram.bramClient, traceif.tlpdata.bscanBramServer);
   rule tdorule;
      lbscan.loc[1].tdo(pcieBscanBram.data_out());
   endrule
`endif

   PcieControlAndStatusRegs csr <- mkPcieControlAndStatusRegs(traceif.tlpdata);
   mkConnection(mvec[portConfig].master, csr.memSlave);

   interface msixEntry = csr.msixEntry;
   interface master = mvec[portPortal].master;
   interface slave = slavearr;
   interface interruptRequest = intr.interruptRequest;
   interface pci = traceif.pci;
   interface BscanTop bscanif = lbscan.loc[0];
endmodule: mkPcieHost

interface PcieTop#(type ipins);
`ifndef BSIM
   (* prefix="PCIE" *)
   interface PciewrapPci_exp#(PcieLanes) pcie;
   (* always_ready *)
   method Bit#(NumLeds) leds();
   (* prefix="" *)
   interface ipins       pins;
`endif
endinterface

`ifdef BSIM
module mkPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);
   let dc <- exposeCurrentClock;
   let dr <- exposeCurrentReset;
   Clock epClock125 = dc;
   Reset epReset125 = dr;
   PcieHost#(DataBusWidth, NumberOfMasters) pciehost <- mkPcieHost(PciId{ bus:0, dev:0, func:0});
   // connect pciehost.pci to bdip functions here
   rule from_bdpi if (can_get_tlp);
      TLPData#(16) foo <- get_tlp;
      pciehost.pci.response.put(foo);
      //$display("from_bdpi: %h %d", foo, valueOf(SizeOf#(TLPData#(16))));
   endrule
   rule to_bdpi if (can_put_tlp);
      TLPData#(16) foo <- pciehost.pci.request.get;
      put_tlp(foo);
      //$display("to_bdpi");
   endrule
   interface Clock tepClock125 = epClock125;
   interface Reset tepReset125 = epReset125;
   interface PcieHost tpciehost = pciehost;
endmodule
`else // not BSIM
//(* synthesize, no_default_clock, no_default_reset *)
(* no_default_clock, no_default_reset *)
module mkPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);
   Clock sys_clk_200mhz <- mkClockIBUFDS(sys_clk_p, sys_clk_n);
   Clock sys_clk_200mhz_buf <- mkClockBUFG(clocked_by sys_clk_200mhz);
   Clock pci_clk_100mhz_buf <- mkClockIBUFDS_GTE2(True, pci_sys_clk_p, pci_sys_clk_n);
   // Instantiate the PCIE endpoint
   PcieEndpointX7#(PcieLanes) ep7 <- mkPcieEndpointX7( clocked_by pci_clk_100mhz_buf
						      , reset_by pci_sys_reset_n
						       );

   Clock epClock125 = ep7.epClock125;
   Reset epReset125 = ep7.epReset125;
   PcieHost#(DataBusWidth, NumberOfMasters) pciehost <- mkPcieHost(
         PciId{ bus:  ep7.cfg.bus_number(), dev: ep7.cfg.device_number(), func: ep7.cfg.function_number()},
         clocked_by epClock125, reset_by epReset125);
   mkConnection(ep7.tlp, pciehost.pci, clocked_by epClock125, reset_by epReset125);
   interface Clock tsys_clk_200mhz = sys_clk_200mhz;
   interface Clock tsys_clk_200mhz_buf = sys_clk_200mhz_buf;
   interface Clock tpci_clk_100mhz_buf = pci_clk_100mhz_buf;
   interface PcieEndpointX7 tep7 = ep7;
   interface Clock tepClock125 = epClock125;
   interface Reset tepReset125 = epReset125;
   interface PcieHost tpciehost = pciehost;

   //once the dot product server makes timing, replace epClock125 with ep7.epclock250
   interface doubleClock = epClock125;
   interface doubleReset = epReset125;

endmodule
`endif

`ifndef BSIM
(* no_default_clock, no_default_reset *)
`endif
module mkPcieTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)
   (PcieTop#(PinType));

   PcieHostTop host <- mkPcieHostTop(pci_sys_clk_p, pci_sys_clk_n, sys_clk_p, sys_clk_n, pci_sys_reset_n);

`ifdef IMPORT_HOSTIF
   PortalTop#(40, DataBusWidth, PinType, NumberOfMasters) portalTop <- mkPortalTop(host, clocked_by host.tepClock125, reset_by host.tepReset125);
`else
   PortalTop#(40, DataBusWidth, PinType, NumberOfMasters) portalTop <- mkPortalTop(clocked_by host.tepClock125, reset_by host.tepReset125);
`endif
   mkConnection(host.tpciehost.master, portalTop.slave, clocked_by host.tepClock125, reset_by host.tepReset125);
   if (valueOf(NumberOfMasters) > 0) begin
      mapM(uncurry(mkConnection),zip(portalTop.masters, host.tpciehost.slave));
   end

   // going from level to edge-triggered interrupt
   Vector#(15, Reg#(Bool)) interruptRequested <- replicateM(mkReg(False, clocked_by host.tepClock125, reset_by host.tepReset125));
   rule interrupt_rule;
     Integer intr_num = 0;
     for (Integer i = 0; i < 15; i = i + 1) begin
	 if (intr_num == 0 && portalTop.interrupt[i] && !interruptRequested[i])
             intr_num = i+1;
	 interruptRequested[i] <= portalTop.interrupt[i];
     end
     if (intr_num != 0) begin // i= 0 for the directory
        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

`ifndef BSIM
   interface pcie = host.tep7.pcie;
   method Bit#(NumLeds) leds();
      return extend({host.tep7.user.lnk_up(),3'd2});
   endmethod
   interface pins = portalTop.pins;
`endif
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 Clocks            :: *;
import GetPut            :: *;
import FIFO              :: *;
import Connectable       :: *;
import ClientServer      :: *;
import DefaultValue      :: *;
import PcieSplitter      :: *;
import PcieTracer        :: *;
import Xilinx            :: *;
import PCIEWRAPPER       :: *;
import Portal            :: *;
import Leds              :: *;
import Top               :: *;
import MemSlaveEngine    :: *;
import MemMasterEngine   :: *;
import PcieCsr           :: *;
import MemSlave          :: *;
import MemTypes          :: *;
import Bscan             :: *;
`ifndef BSIM
import PcieEndpointX7    :: *;
`endif
import HostInterface    :: *;

`ifndef DataBusWidth
`define DataBusWidth 64
`endif
`ifndef PinType
`define PinType Empty
`endif

`ifdef USES_BSCAN
`define BSCAN_ARG  local_bscan
`else
`define BSCAN_ARG
`endif
typedef `PinType PinType;

// implemented in TlpReplay.cxx
import "BDPI" function Action put_tlp(TLPData#(16) d);
import "BDPI" function ActionValue#(TLPData#(16)) get_tlp();
import "BDPI" function Bool can_put_tlp();
import "BDPI" function Bool can_get_tlp();

(* synthesize *)
module  mkPcieHost#(PciId my_pciId)(PcieHost#(DataBusWidth, NumberOfMasters));
   Clock epClock125 <- exposeCurrentClock();
   Reset epReset125 <- exposeCurrentReset();
   let dispatcher <- mkTLPDispatcher;
   let arbiter    <- mkTLPArbiter;
   Vector#(NumberOfMasters,MemSlaveEngine#(DataBusWidth)) sEngine <- replicateM(mkMemSlaveEngine(my_pciId));
   Vector#(NumberOfMasters,MemSlave#(40,DataBusWidth)) slavearr;
   MemInterrupt intr <- mkMemInterrupt(my_pciId);
   BscanTop bscan <- mkBscanTop(3); // Use USER3  (JTAG IDCODE address 0x22)
   BscanLocal lbscan <- mkBscanLocal(bscan, clocked_by bscan.tck, reset_by bscan.rst);

   Vector#(PortMax, MemMasterEngine) mvec;
   for (Integer i = 0; i < valueOf(PortMax) - 1 + valueOf(NumberOfMasters); i=i+1) begin
       let tlp;
       if (i == portInterrupt)
           tlp = intr.tlp;
       else if (i >= portAxi) begin
           tlp = sEngine[i - portAxi].tlp;
           slavearr[i - portAxi] = sEngine[i - portAxi].slave;
       end
       else begin
           mvec[i] <- mkMemMasterEngine(my_pciId);
           tlp = mvec[i].tlp;
       end
       mkConnection((interface Server;
                        interface response = dispatcher.out[i];
                        interface request = arbiter.in[i];
                     endinterface), tlp);
   end

   PcieTracer  traceif <- mkPcieTracer();
   mkConnection(traceif.bus, (interface Client;
                                 interface request = arbiter.outToBus;
                                 interface response = dispatcher.inFromBus;
                              endinterface));
`ifndef BSIM
   Reg#(Bit#(TAdd#(TlpTraceAddrSize,1))) bscanPcieTraceBramWrAddrReg <- mkReg(0);
   BscanBram#(Bit#(TAdd#(TlpTraceAddrSize,1)), TimestampedTlpData) pcieBscanBram <- mkBscanBram(127, bscanPcieTraceBramWrAddrReg, lbscan.loc[1]);
   mkConnection(pcieBscanBram.bramClient, traceif.tlpdata.bscanBramServer);
   rule tdorule;
      lbscan.loc[1].tdo(pcieBscanBram.data_out());
   endrule
`endif

   PcieControlAndStatusRegs csr <- mkPcieControlAndStatusRegs(traceif.tlpdata);
   mkConnection(mvec[portConfig].master, csr.memSlave);

   interface msixEntry = csr.msixEntry;
   interface master = mvec[portPortal].master;
   interface slave = slavearr;
   interface interruptRequest = intr.interruptRequest;
   interface pci = traceif.pci;
   interface BscanTop bscanif = lbscan.loc[0];
endmodule: mkPcieHost

interface PcieTop#(type ipins);
`ifndef BSIM
   (* prefix="PCIE" *)
   interface PciewrapPci_exp#(PcieLanes) pcie;
   (* always_ready *)
   method Bit#(NumLeds) leds();
   (* prefix="" *)
   interface ipins       pins;
`endif
endinterface

`ifdef BSIM
module mkPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);
   let dc <- exposeCurrentClock;
   let dr <- exposeCurrentReset;
   Clock epClock125 = dc;
   Reset epReset125 = dr;
   PcieHost#(DataBusWidth, NumberOfMasters) pciehost <- mkPcieHost(PciId{ bus:0, dev:0, func:0});
   // connect pciehost.pci to bdip functions here
   rule from_bdpi if (can_get_tlp);
      TLPData#(16) foo <- get_tlp;
      pciehost.pci.response.put(foo);
      //$display("from_bdpi: %h %d", foo, valueOf(SizeOf#(TLPData#(16))));
   endrule
   rule to_bdpi if (can_put_tlp);
      TLPData#(16) foo <- pciehost.pci.request.get;
      put_tlp(foo);
      //$display("to_bdpi");
   endrule
   interface Clock tepClock125 = epClock125;
   interface Reset tepReset125 = epReset125;
   interface PcieHost tpciehost = pciehost;
endmodule
`else // not BSIM
//(* synthesize, no_default_clock, no_default_reset *)
(* no_default_clock, no_default_reset *)
module mkPcieHostTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)(PcieHostTop);
   Clock sys_clk_200mhz <- mkClockIBUFDS(sys_clk_p, sys_clk_n);
   Clock sys_clk_200mhz_buf <- mkClockBUFG(clocked_by sys_clk_200mhz);
   Clock pci_clk_100mhz_buf <- mkClockIBUFDS_GTE2(True, pci_sys_clk_p, pci_sys_clk_n);
   // Instantiate the PCIE endpoint
   PcieEndpointX7#(PcieLanes) ep7 <- mkPcieEndpointX7( clocked_by pci_clk_100mhz_buf
						      , reset_by pci_sys_reset_n
						       );

   Clock epClock125 = ep7.epClock125;
   Reset epReset125 = ep7.epReset125;
   PcieHost#(DataBusWidth, NumberOfMasters) pciehost <- mkPcieHost(
         PciId{ bus:  ep7.cfg.bus_number(), dev: ep7.cfg.device_number(), func: ep7.cfg.function_number()},
         clocked_by epClock125, reset_by epReset125);
   mkConnection(ep7.tlp, pciehost.pci, clocked_by epClock125, reset_by epReset125);
   interface Clock tsys_clk_200mhz = sys_clk_200mhz;
   interface Clock tsys_clk_200mhz_buf = sys_clk_200mhz_buf;
   interface Clock tpci_clk_100mhz_buf = pci_clk_100mhz_buf;
   interface PcieEndpointX7 tep7 = ep7;
   interface Clock tepClock125 = epClock125;
   interface Reset tepReset125 = epReset125;
   interface PcieHost tpciehost = pciehost;

   //once the dot product server makes timing, replace epClock125 with ep7.epclock250
   interface doubleClock = epClock125;
   interface doubleReset = epReset125;

endmodule
`endif

`ifndef BSIM
(* no_default_clock, no_default_reset *)
`endif
module mkPcieTop #(Clock pci_sys_clk_p, Clock pci_sys_clk_n, Clock sys_clk_p, Clock sys_clk_n, Reset pci_sys_reset_n)
   (PcieTop#(PinType));

   PcieHostTop host <- mkPcieHostTop(pci_sys_clk_p, pci_sys_clk_n, sys_clk_p, sys_clk_n, pci_sys_reset_n);

`ifdef IMPORT_HOSTIF
   PortalTop#(40, DataBusWidth, PinType, NumberOfMasters) portalTop <- mkPortalTop(host, clocked_by host.tepClock125, reset_by host.tepReset125);
`else
   PortalTop#(40, DataBusWidth, PinType, NumberOfMasters) portalTop <- mkPortalTop(clocked_by host.tepClock125, reset_by host.tepReset125);
`endif
   mkConnection(host.tpciehost.master, portalTop.slave, clocked_by host.tepClock125, reset_by host.tepReset125);
   if (valueOf(NumberOfMasters) > 0) begin
      mapM(uncurry(mkConnection),zip(portalTop.masters, host.tpciehost.slave));
   end

   // going from level to edge-triggered interrupt
   Vector#(15, Reg#(Bool)) interruptRequested <- replicateM(mkReg(False, clocked_by host.tepClock125, reset_by host.tepReset125));
   rule interrupt_rule;
     Integer intr_num = 0;
     for (Integer i = 0; i < 15; i = i + 1) begin
	 if (intr_num == 0 && portalTop.interrupt[i] && !interruptRequested[i])
             intr_num = i+1;
	 interruptRequested[i] <= portalTop.interrupt[i];
     end
     if (intr_num != 0) begin // i= 0 for the directory
        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

`ifndef BSIM
   interface pcie = host.tep7.pcie;
   method Bit#(NumLeds) leds();
      return extend({host.tep7.user.lnk_up(),3'd2});
   endmethod
   interface pins = portalTop.pins;
`endif
endmodule


use a SizedBRAMFIFOF when TOP_SOURCES_PORTAL_CLOCK is defined

// Copyright (c) 2016 Connectal Project

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

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

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

import Clocks::*;
import Connectable::*;
import FIFOF::*;
import GetPut::*;
import Vector::*;

import ConnectalClocks::*;
import DefaultValue::*;
import HostInterface::*;
import XilinxCells::*;
import MemTypes::*;
import AxiBits::*;

import AxiPcieRootPort::*;
import RootPortIfc::*;
import RootPortPins::*;

`ifndef TOP_SOURCES_PORTAL_CLOCK
import ConnectalBramFifo::*;
`else
import BRAMFIFO::*;
module mkDualClockBramFIFOF#(Clock clock1, Reset reset1, Clock clock2, Reset reset2)(FIFOF#(a))
   provisos (Bits#(a, asz), Add#(1, a__, asz));
   FIFOF#(a) fifo <- mkSizedBRAMFIFOF(512, clocked_by clock1, reset_by reset1);
   return fifo;
endmodule
`endif

interface RootPort;
   interface RootPortRequest request;
   interface RootPortPins pins;
`ifdef TOP_SOURCES_PORTAL_CLOCK
   interface Clock portalClockSource;
`endif
endinterface

module mkRootPort#(HostInterface host, RootPortIndication ind)(RootPort);
   let clock <- exposeCurrentClock;
   let reset <- exposeCurrentReset;
   let refclk_p <- mkB2C1();
   let refclk_n <- mkB2C1();
   let pcie_clk_100mhz_buf <- mkClockIBUFDS_GTE2(
`ifdef ClockDefaultParam
       defaultValue,
`endif
      True, refclk_p.c, refclk_n.c);
`ifndef TOP_SOURCES_PORTAL_CLOCK
   let axiClockB2C    <- mkB2C1();
   let axiCtlClockB2C <- mkB2C1();
   let axiClock = axiClockB2C.c;
   let axiCtlClock = axiCtlClockB2C.c;
   let axiReset <- mkSyncReset(10, reset, axiClock);
   let axiCtlReset <- mkSyncReset(10, reset, axiCtlClock);
`else
   let axiClock = clock;
   let axiCtlClock = clock;
   let axiReset = reset;
   let axiCtlReset = reset;
`endif

   let axiRootPort <- mkAPRP(pcie_clk_100mhz_buf, reset, axiClock, axiReset, axiCtlClock, axiCtlReset);
`ifndef TOP_SOURCES_PORTAL_CLOCK
   let axiClockC2B <- mkC2B(axiRootPort.axi.aclk_out);
   let axiCtlClockC2B <- mkC2B(axiRootPort.axi.ctl_aclk_out);
   rule rl_connect_clocks;
      axiClockB2C.inputclock(axiClockC2B.o);
      axiCtlClockB2C.inputclock(axiClockC2B.o);
   endrule
`endif

   FIFOF#(Bit#(32)) dfifoCtl <- mkFIFOF();
   Axi4SlaveBits#(32,64,4,Empty) axiRootPortSlave    = toAxi4SlaveBits(axiRootPort.s_axi);
   Axi4SlaveLiteBits#(32,32)     axiRootPortSlaveCtl = toAxi4SlaveBits(axiRootPort.s_axi_ctl);
   PhysMemSlave#(32,64)          axiRootPortMemSlave    <- mkPhysMemSlave(axiRootPortSlave, clocked_by axiClock, reset_by axiReset);
   PhysMemSlave#(32,32)          axiRootPortMemSlaveCtl <- mkPhysMemSlave(axiRootPortSlaveCtl, clocked_by axiCtlClock, reset_by axiCtlReset);

   FIFOF#(PhysMemRequest#(32,64)) araddrFifo <- mkDualClockBramFIFOF(clock, reset, axiClock, axiReset);
   FIFOF#(PhysMemRequest#(32,64)) awaddrFifo <- mkDualClockBramFIFOF(clock, reset, axiClock, axiReset);
   FIFOF#(MemData#(64))           rdataFifo <- mkDualClockBramFIFOF(axiClock, axiReset, clock, reset);
   FIFOF#(MemData#(64))           wdataFifo <- mkDualClockBramFIFOF(clock, reset, axiClock, axiReset);
   FIFOF#(Bit#(6))                doneFifo <- mkDualClockBramFIFOF(axiClock, axiReset, clock, reset);

   let araddrCnx <- mkConnection(toGet(araddrFifo), axiRootPortMemSlave.read_server.readReq);
   let awaddrCnx <- mkConnection(toGet(awaddrFifo), axiRootPortMemSlave.write_server.writeReq);
   let rdataCnx  <- mkConnection(axiRootPortMemSlave.read_server.readData, toPut(rdataFifo));
   let wdataCnx  <- mkConnection(toGet(wdataFifo), axiRootPortMemSlave.write_server.writeData);
   let doneCnx   <- mkConnection(axiRootPortMemSlave.write_server.writeDone, toPut(doneFifo));

   rule rl_rdata;
      let rdata <- toGet(rdataFifo).get();
      ind.readDone(rdata.data);
   endrule

   rule rl_writeDone;
      let tag <- toGet(doneFifo).get();
      ind.writeDone();
   endrule

   FIFOF#(PhysMemRequest#(32,32)) araddrFifoCtl <- mkDualClockBramFIFOF(clock, reset, axiCtlClock, axiCtlReset);
   FIFOF#(PhysMemRequest#(32,32)) awaddrFifoCtl <- mkDualClockBramFIFOF(clock, reset, axiCtlClock, axiCtlReset);
   FIFOF#(MemData#(32))           rdataFifoCtl <- mkDualClockBramFIFOF(axiCtlClock, axiCtlReset, clock, reset);
   FIFOF#(MemData#(32))           wdataFifoCtl <- mkDualClockBramFIFOF(clock, reset, axiCtlClock, axiCtlReset);
   FIFOF#(Bit#(6))                doneFifoCtl <- mkDualClockBramFIFOF(axiCtlClock, axiCtlReset, clock, reset);

   let araddrCtlCnx <- mkConnection(toGet(araddrFifoCtl), axiRootPortMemSlaveCtl.read_server.readReq);
   let awaddrCtlCnx <- mkConnection(toGet(awaddrFifoCtl), axiRootPortMemSlaveCtl.write_server.writeReq);
   let rdataCtlCnx  <- mkConnection(axiRootPortMemSlaveCtl.read_server.readData, toPut(rdataFifoCtl));
   let wdataCtlCnx  <- mkConnection(toGet(wdataFifoCtl), axiRootPortMemSlaveCtl.write_server.writeData);
   let doneCtlCnx   <- mkConnection(axiRootPortMemSlaveCtl.write_server.writeDone, toPut(doneFifoCtl));

   rule rl_rdata_ctl;
      let rdata <- toGet(rdataFifoCtl).get();
      ind.readDone(extend(rdata.data));
   endrule

   rule rl_writeDone_ctl;
      let tag <- toGet(doneFifoCtl).get();
      ind.writeDone();
   endrule

   interface RootPortRequest request;
      method Action status();
        ind.status(axiRootPort.mmcm.lock());
      endmethod

      method Action read(Bit#(32) addr);
	 araddrFifo.enq(PhysMemRequest { addr: addr, burstLen: 4, tag: 0 });
      endmethod
      method Action write(Bit#(32) addr, Bit#(64) value);
	 awaddrFifo.enq(PhysMemRequest { addr: addr, burstLen: 4, tag: 0 });
	 wdataFifo.enq(MemData {data: value, tag: 0, last: True});
      endmethod

      method Action readCtl(Bit#(32) addr);
	 araddrFifoCtl.enq(PhysMemRequest { addr: addr, burstLen: 4, tag: 0 });
      endmethod
      method Action writeCtl(Bit#(32) addr, Bit#(64) value);
	 awaddrFifoCtl.enq(PhysMemRequest { addr: addr, burstLen: 4, tag: 0 });
	 wdataFifoCtl.enq(MemData {data: truncate(value), tag: 0, last: True});
      endmethod
   endinterface
   interface Clock portalClockSource = axiRootPort.axi.aclk_out;
   interface RootPortPins pins;
      interface deleteme_unused_clock = clock;
      interface pcie_sys_reset_n = reset;
      interface pcie = axiRootPort.pci;
      method Action pcie_refclk(Bit#(1) p, Bit#(1) n);
         refclk_p.inputclock(p);
         refclk_n.inputclock(n);
      endmethod
   endinterface

endmodule

instance ToAxi4SlaveBits#(Axi4SlaveBits#(32,64,4,Empty), AprpS_axi);
   function Axi4SlaveBits#(32,64,4,Empty) toAxi4SlaveBits(AprpS_axi s);
      return (interface Axi4SlaveBits#(32,64,4,Empty);
	 method araddr = compose(s.araddr, extend);
	 method arburst = s.arburst;
	 //method arcache = s.arcache;
	 method arid = s.arid;
	 method arlen = s.arlen;
	 //method arlock = s.arlock;
	 //method arprot = s.arprot;
	 //method arqos = s.arqos;
	 method arready = s.arready;
	 method arsize = s.arsize;
	 method arvalid = s.arvalid;

	 method awaddr = compose(s.awaddr, extend);
	 method awburst = s.awburst;
	 //method awcache = s.awcache;
	 method awid = s.awid;
	 method awlen = s.awlen;
	 //method awlock = s.awlock;
	 //method awprot = s.awprot;
	 //method awqos = s.awqos;
	 method awready = s.awready;
	 method awsize = s.awsize;
	 method awvalid = s.awvalid;

	 method bid = s.bid;
	 method bready = s.bready;
	 method bresp = s.bresp;
	 method bvalid = s.bvalid;
	 method rdata = s.rdata;
	 method rid = s.rid;
	 method rlast = s.rlast;
	 method rready = s.rready;
	 method rresp = s.rresp;
	 method rvalid = s.rvalid;
	 method wdata = s.wdata;
	 method wlast = s.wlast;
	 method wready = s.wready;
	 method Action      wvalid(Bit#(1) v);
	    s.wvalid(v);
	    s.wstrb(pack(replicate(v)));
	 endmethod
	 endinterface);
   endfunction
endinstance

instance ToAxi4SlaveBits#(Axi4SlaveLiteBits#(32,32), AprpS_axi_ctl);
   function Axi4SlaveLiteBits#(32,32) toAxi4SlaveBits(AprpS_axi_ctl s);
      return (interface Axi4SlaveLiteBits#(32,32);
	 method araddr = compose(s.araddr, extend);
	 method arready = s.arready;
	 method arvalid = s.arvalid;

	 method awaddr = compose(s.awaddr, extend);
	 method awready = s.awready;
	 method awvalid = s.awvalid;

	 method bready = s.bready;
	 method bresp = s.bresp;
	 method bvalid = s.bvalid;
	 method rdata = s.rdata;
	 method rready = s.rready;
	 method rresp = s.rresp;
	 method rvalid = s.rvalid;
	 method wdata = s.wdata;
	 method wready = s.wready;
	 method Action      wvalid(Bit#(1) v);
	    s.wvalid(v);
	    s.wstrb(pack(replicate(v)));
	 endmethod
	 endinterface);
   endfunction
endinstance

// Copyright (c) 2016 Connectal Project

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

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

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

import Clocks::*;
import Connectable::*;
import FIFOF::*;
import GetPut::*;
import Vector::*;

import ConnectalClocks::*;
import ConnectalBramFifo::*;
import DefaultValue::*;
import HostInterface::*;
import XilinxCells::*;
import MemTypes::*;
import AxiBits::*;

import AxiPcieRootPort::*;
import RootPortIfc::*;
import RootPortPins::*;

interface RootPort;
   interface RootPortRequest request;
   interface RootPortPins pins;
`ifdef TOP_SOURCES_PORTAL_CLOCK
   interface Clock portalClockSource;
`endif
endinterface

module mkRootPort#(HostInterface host, RootPortIndication ind)(RootPort);
   let clock <- exposeCurrentClock;
   let reset <- exposeCurrentReset;
   let refclk_p <- mkB2C1();
   let refclk_n <- mkB2C1();
   let pcie_clk_100mhz_buf <- mkClockIBUFDS_GTE2(
`ifdef ClockDefaultParam
       defaultValue,
`endif
      True, refclk_p.c, refclk_n.c);
   let axiClockB2C    <- mkB2C1();
   let axiCtlClockB2C <- mkB2C1();
   let axiClock = axiClockB2C.c;
   let axiCtlClock = axiCtlClockB2C.c;
   let axiReset <- mkSyncReset(10, reset, axiClock);
   let axiCtlReset <- mkSyncReset(10, reset, axiCtlClock);

   let axiRootPort <- mkAPRP(pcie_clk_100mhz_buf, reset, axiClock, axiReset, axiCtlClock, axiCtlReset);
   let axiClockC2B <- mkC2B(axiRootPort.axi.aclk_out);
   let axiCtlClockC2B <- mkC2B(axiRootPort.axi.ctl_aclk_out);
   rule rl_connect_clocks;
      axiClockB2C.inputclock(axiClockC2B.o);
      axiCtlClockB2C.inputclock(axiClockC2B.o);
   endrule

   FIFOF#(Bit#(32)) dfifoCtl <- mkFIFOF();
   Axi4SlaveBits#(32,64,4,Empty) axiRootPortSlave    = toAxi4SlaveBits(axiRootPort.s_axi);
   Axi4SlaveLiteBits#(32,32)     axiRootPortSlaveCtl = toAxi4SlaveBits(axiRootPort.s_axi_ctl);
   PhysMemSlave#(32,64)          axiRootPortMemSlave    <- mkPhysMemSlave(axiRootPortSlave, clocked_by axiClock, reset_by axiReset);
   PhysMemSlave#(32,32)          axiRootPortMemSlaveCtl <- mkPhysMemSlave(axiRootPortSlaveCtl, clocked_by axiCtlClock, reset_by axiCtlReset);

   FIFOF#(PhysMemRequest#(32,64)) araddrFifo <- mkDualClockBramFIFOF(clock, reset, axiClock, axiReset);
   FIFOF#(PhysMemRequest#(32,64)) awaddrFifo <- mkDualClockBramFIFOF(clock, reset, axiClock, axiReset);
   FIFOF#(MemData#(64))           rdataFifo <- mkDualClockBramFIFOF(axiClock, axiReset, clock, reset);
   FIFOF#(MemData#(64))           wdataFifo <- mkDualClockBramFIFOF(clock, reset, axiClock, axiReset);
   FIFOF#(Bit#(6))                doneFifo <- mkDualClockBramFIFOF(axiClock, axiReset, clock, reset);

   let araddrCnx <- mkConnection(toGet(araddrFifo), axiRootPortMemSlave.read_server.readReq);
   let awaddrCnx <- mkConnection(toGet(awaddrFifo), axiRootPortMemSlave.write_server.writeReq);
   let rdataCnx  <- mkConnection(axiRootPortMemSlave.read_server.readData, toPut(rdataFifo));
   let wdataCnx  <- mkConnection(toGet(wdataFifo), axiRootPortMemSlave.write_server.writeData);
   let doneCnx   <- mkConnection(axiRootPortMemSlave.write_server.writeDone, toPut(doneFifo));

   rule rl_rdata;
      let rdata <- toGet(rdataFifo).get();
      ind.readDone(rdata.data);
   endrule

   rule rl_writeDone;
      let tag <- toGet(doneFifo).get();
      ind.writeDone();
   endrule

   FIFOF#(PhysMemRequest#(32,32)) araddrFifoCtl <- mkDualClockBramFIFOF(clock, reset, axiCtlClock, axiCtlReset);
   FIFOF#(PhysMemRequest#(32,32)) awaddrFifoCtl <- mkDualClockBramFIFOF(clock, reset, axiCtlClock, axiCtlReset);
   FIFOF#(MemData#(32))           rdataFifoCtl <- mkDualClockBramFIFOF(axiCtlClock, axiCtlReset, clock, reset);
   FIFOF#(MemData#(32))           wdataFifoCtl <- mkDualClockBramFIFOF(clock, reset, axiCtlClock, axiCtlReset);
   FIFOF#(Bit#(6))                doneFifoCtl <- mkDualClockBramFIFOF(axiCtlClock, axiCtlReset, clock, reset);

   let araddrCtlCnx <- mkConnection(toGet(araddrFifoCtl), axiRootPortMemSlaveCtl.read_server.readReq);
   let awaddrCtlCnx <- mkConnection(toGet(awaddrFifoCtl), axiRootPortMemSlaveCtl.write_server.writeReq);
   let rdataCtlCnx  <- mkConnection(axiRootPortMemSlaveCtl.read_server.readData, toPut(rdataFifoCtl));
   let wdataCtlCnx  <- mkConnection(toGet(wdataFifoCtl), axiRootPortMemSlaveCtl.write_server.writeData);
   let doneCtlCnx   <- mkConnection(axiRootPortMemSlaveCtl.write_server.writeDone, toPut(doneFifoCtl));

   rule rl_rdata_ctl;
      let rdata <- toGet(rdataFifoCtl).get();
      ind.readDone(extend(rdata.data));
   endrule

   rule rl_writeDone_ctl;
      let tag <- toGet(doneFifoCtl).get();
      ind.writeDone();
   endrule

   interface RootPortRequest request;
      method Action status();
        ind.status(axiRootPort.mmcm.lock());
      endmethod

      method Action read(Bit#(32) addr);
	 araddrFifo.enq(PhysMemRequest { addr: addr, burstLen: 4, tag: 0 });
      endmethod
      method Action write(Bit#(32) addr, Bit#(64) value);
	 awaddrFifo.enq(PhysMemRequest { addr: addr, burstLen: 4, tag: 0 });
	 wdataFifo.enq(MemData {data: value, tag: 0, last: True});
      endmethod

      method Action readCtl(Bit#(32) addr);
	 araddrFifoCtl.enq(PhysMemRequest { addr: addr, burstLen: 4, tag: 0 });
      endmethod
      method Action writeCtl(Bit#(32) addr, Bit#(64) value);
	 awaddrFifoCtl.enq(PhysMemRequest { addr: addr, burstLen: 4, tag: 0 });
	 wdataFifoCtl.enq(MemData {data: truncate(value), tag: 0, last: True});
      endmethod
   endinterface
   interface Clock portalClockSource = axiRootPort.axi.aclk_out;
   interface RootPortPins pins;
      interface deleteme_unused_clock = clock;
      interface pcie_sys_reset_n = reset;
      interface pcie = axiRootPort.pci;
      method Action pcie_refclk(Bit#(1) p, Bit#(1) n);
         refclk_p.inputclock(p);
         refclk_n.inputclock(n);
      endmethod
   endinterface

endmodule

instance ToAxi4SlaveBits#(Axi4SlaveBits#(32,64,4,Empty), AprpS_axi);
   function Axi4SlaveBits#(32,64,4,Empty) toAxi4SlaveBits(AprpS_axi s);
      return (interface Axi4SlaveBits#(32,64,4,Empty);
	 method araddr = compose(s.araddr, extend);
	 method arburst = s.arburst;
	 //method arcache = s.arcache;
	 method arid = s.arid;
	 method arlen = s.arlen;
	 //method arlock = s.arlock;
	 //method arprot = s.arprot;
	 //method arqos = s.arqos;
	 method arready = s.arready;
	 method arsize = s.arsize;
	 method arvalid = s.arvalid;

	 method awaddr = compose(s.awaddr, extend);
	 method awburst = s.awburst;
	 //method awcache = s.awcache;
	 method awid = s.awid;
	 method awlen = s.awlen;
	 //method awlock = s.awlock;
	 //method awprot = s.awprot;
	 //method awqos = s.awqos;
	 method awready = s.awready;
	 method awsize = s.awsize;
	 method awvalid = s.awvalid;

	 method bid = s.bid;
	 method bready = s.bready;
	 method bresp = s.bresp;
	 method bvalid = s.bvalid;
	 method rdata = s.rdata;
	 method rid = s.rid;
	 method rlast = s.rlast;
	 method rready = s.rready;
	 method rresp = s.rresp;
	 method rvalid = s.rvalid;
	 method wdata = s.wdata;
	 method wlast = s.wlast;
	 method wready = s.wready;
	 method Action      wvalid(Bit#(1) v);
	    s.wvalid(v);
	    s.wstrb(pack(replicate(v)));
	 endmethod
	 endinterface);
   endfunction
endinstance

instance ToAxi4SlaveBits#(Axi4SlaveLiteBits#(32,32), AprpS_axi_ctl);
   function Axi4SlaveLiteBits#(32,32) toAxi4SlaveBits(AprpS_axi_ctl s);
      return (interface Axi4SlaveLiteBits#(32,32);
	 method araddr = compose(s.araddr, extend);
	 method arready = s.arready;
	 method arvalid = s.arvalid;

	 method awaddr = compose(s.awaddr, extend);
	 method awready = s.awready;
	 method awvalid = s.awvalid;

	 method bready = s.bready;
	 method bresp = s.bresp;
	 method bvalid = s.bvalid;
	 method rdata = s.rdata;
	 method rready = s.rready;
	 method rresp = s.rresp;
	 method rvalid = s.rvalid;
	 method wdata = s.wdata;
	 method wready = s.wready;
	 method Action      wvalid(Bit#(1) v);
	    s.wvalid(v);
	    s.wstrb(pack(replicate(v)));
	 endmethod
	 endinterface);
   endfunction
endinstance