fix i/o ness of misc signals

fix i/o ness of misc signals

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

// This file is a hand-generated file that we hope will someday be
// generated automatically by connectal/generated/scripts/importbvi.py
//
// Created by copying the style of connectal/generated/xilinx/PPS7LIB.bsv

import Clocks::*;
import DefaultValue::*;
import XilinxCells::*;
import GetPut::*;
import AxiBits::*;

// The name of this interface is a prefix "Par_" plus the common prefix of the signals "txo"
// Hopefully this is what importbvi.py would do
(* always_ready, always_enabled *)
interface Par_txo;
   method Action data_p(Bit#(8) v);
   method Action data_n(Bit#(8) v);
   method Action frame_p(Bit#(1) v);
   method Action frame_n(Bit#(1) v);
   method Action lclk_p(Bit#(1) v);
   method Action lclk_n(Bit#(1) v);
endinterface

(* always_ready, always_enabled *)
interface Par_txi;
   method Bit#(1) wr_wait_p();
   method Bit#(1) wr_wait_n();
   method Bit#(1) rd_wait_p();
   method Bit#(1) rd_wait_n();
endinterface

(* always_ready, always_enabled *)
interface Par_rxi;
   method Bit#(8) data_p();
   method Bit#(8) data_n();
   method Bit#(1) frame_p();
   method Bit#(1) frame_n();
   method Bit#(1) lclk_p();
   method Bit#(1) lclk_n();
   method Action cclk_p(Bit#(1) v);
   method Action cclk_n(Bit#(1) v);
endinterface

(* always_ready, always_enabled *)
interface Par_rxo;
   method Action wr_wait_p(Bit#(1) v);
   method Action wr_wait_n(Bit#(1) v);
   method Action rd_wait_p(Bit#(1) v);
   method Action rd_wait_n(Bit#(1) v);
endinterface

(* always_ready, always_enabled *)
interface Par_misc;
   method Bit#(1) csysack();
   method Bit#(1) cactive();
   method Action csysreq(Bit#(1) v);
   method Bit#(1) reset_chip();
   method Bit#(1) reset_fpga();
endinterface

(* always_ready, always_enabled *)
interface PParallellaLib;
   interface Par_txo txo;
   interface Par_txi txi;
   interface Par_rxo rxo;
   interface Par_rxi rxi;
   interface AxiSlaveBits#(32,32,12,Empty) maxi;   // this will connect to a master
   interface AxiMasterBits#(32,64,6,Empty) saxi;  // this will connect to a slave
   interface Par_misc misc;
endinterface

import "BVI" PParallellaZZZ =
module mkPParallellaLIB#(Clock maxiclk, Clock saxiclk,
   Reset maxiclk_reset, Reset saxiclk_reset,
   Reset maxireset, Reset saxireset,
   Reset reset_chip, Reset reset_fpga)(PParallellaLib);
   // default_clock clk();
   // default_reset rst();
   input_clock maxiclk(emaxi_aclk) = maxiclk;  // assigns the verilog emaxi_aclk
   input_clock saxiclk(esaxi_aclk) = saxiclk;  // assigns the verilog esaxi_aclk
   input_reset maxiclk_reset() = maxiclk_reset; /* from clock*/
   input_reset saxiclk_reset() = saxiclk_reset; /* from clock*/
   input_reset maxireset() = maxireset;
   input_reset saxireset() = saxireset;

   interface Par_misc misc;
      method csysack csysack();
      method cactive cactive();
      method reset_chip reset_chip();
      method reset_fpga reset_fpga();
      method csysreq(csysreq) enable((*inhigh*) EN_csysreq);
   endinterface

   interface Par_txo txo;
      method data_p(txo_data_p) enable((*inhigh*) EN_txo_data_p);
      method data_n(txo_data_n) enable((*inhigh*) EN_txo_data_n);
      method frame_p(txo_frame_p) enable((*inhigh*) EN_txo_frame_p);
      method frame_n(txo_frame_n) enable((*inhigh*) EN_txo_frame_n);
      method lclk_p(txo_lclk_p) enable((*inhigh*) EN_txo_lclk_p);
      method lclk_n(txo_lclk_n) enable((*inhigh*) EN_txo_lclk_n);
   endinterface

   interface Par_txi txi;
      method txo_wr_wait_p wr_wait_p();
      method txo_wr_wait_n wr_wait_n();
      method txo_rd_wait_p rd_wait_p();
      method txo_rd_wait_n rd_wait_n();
   endinterface

   interface Par_rxi rxi;
      method rxi_data_p data_p();
      method rxi_data_n data_n();
      method rxi_frame_p frame_p();
      method rxi_frame_n frame_n();
      method rxi_lclk_p lclk_p();
      method rxi_lclk_n lclk_n();
      method cclk_p(rxi_cclk_p) enable((*inhigh*) EN_rxi_cclk_p);
      method cclk_n(rxi_cclk_n) enable((*inhigh*) EN_rxi_cclk_n);
   endinterface

   interface Par_rxo rxo;
      method wr_wait_p(rxo_wr_wait_p) enable((*inhigh*) EN_rxo_wr_wait_p);
      method wr_wait_n(rxo_wr_wait_n) enable((*inhigh*) EN_rxo_wr_wait_n);
      method rd_wait_p(rxo_rd_wait_p) enable((*inhigh*) EN_rxo_rd_wait_p);
      method rd_wait_n(rxo_rd_wait_n) enable((*inhigh*) EN_rxo_rd_wait_n);
   endinterface

   interface AxiSlaveBits maxi;
      method emaxi_araddr araddr() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arburst arburst() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arcache arcache() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_aresetn aresetn() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arid arid() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arlen arlen() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arlock arlock() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arprot arprot() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arqos arqos() clocked_by (maxiclk) reset_by(maxireset);
      method arready(emaxi_arready)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_arready);
      method emaxi_arsize arsize() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arvalid arvalid() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awaddr awaddr() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awburst awburst() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awcache awcache() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awid awid() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awlen awlen() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awlock awlock() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awprot awprot() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awqos awqos() clocked_by (maxiclk) reset_by(maxireset);
      method awready(emaxi_awready)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_awready);
      method emaxi_awsize awsize() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awvalid awvalid() clocked_by (maxiclk) reset_by(maxireset);
      method bid(emaxi_bid) enable((*inhigh*) EN_emaxi_bid);
      method emaxi_bready bready() clocked_by (maxiclk) reset_by(maxireset);
      method bresp(emaxi_bresp)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_bresp);
      method bvalid(emaxi_bvalid)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_bvalid);
      method rdata(emaxi_rdata)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_rdata);
      method rid(emaxi_rid)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_rid);
      method rlast(emaxi_rlast)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_rlast);
      method emaxi_rready rready() clocked_by (maxiclk) reset_by(maxireset);
      method rresp(emaxi_rresp)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_rresp);
      method rvalid(emaxi_rvalid)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_rvalid);
      method emaxi_wdata wdata() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_wid wid() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_wlast wlast() clocked_by (maxiclk) reset_by(maxireset);
      method wready(emaxi_wready)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_wready);
      method emaxi_wstrb wstrb() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_wvalid wvalid() clocked_by (maxiclk) reset_by(maxireset);
   endinterface

   interface AxiMasterBits saxi;
      method araddr(esaxi_araddr) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_araddr);
      method arburst(esaxi_arburst) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arburst);
      method arcache(esaxi_arcache) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arcache);
      method esaxi_aresetn aresetn() clocked_by(saxiclk) reset_by(saxireset);
      method arid(esaxi_arid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arid);
      method arlen(esaxi_arlen) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arlen);
      method arlock(esaxi_arlock) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arlock);
      method arprot(esaxi_arprot) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arprot);
      method arqos(esaxi_arqos) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arqos);
      method esaxi_arready arready() clocked_by(saxiclk) reset_by(saxireset);
      method arsize(esaxi_arsize) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arsize);
      method arvalid(esaxi_arvalid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arvalid);
      method awaddr(esaxi_awaddr) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awaddr);
      method awburst(esaxi_awburst) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awburst);
      method awcache(esaxi_awcache) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awcache);
      method awid(esaxi_awid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awid);
      method awlen(esaxi_awlen) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awlen);
      method awlock(esaxi_awlock) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awlock);
      method awprot(esaxi_awprot) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awprot);
      method awqos(esaxi_awqos) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awqos);
      method esaxi_awready awready() clocked_by(saxiclk) reset_by(saxireset);
      method awsize(esaxi_awsize) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awsize);
      method awvalid(esaxi_awvalid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awvalid);
      method esaxi_bid bid() clocked_by(saxiclk) reset_by(saxireset);
      method bready(esaxi_bready) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_bready);
      method esaxi_bresp bresp() clocked_by(saxiclk) reset_by(saxireset);
      method esaxi_bvalid bvalid() clocked_by(saxiclk) reset_by(saxireset);
      method esaxi_rdata rdata() clocked_by(saxiclk) reset_by(saxireset);
      method esaxi_rlast rlast() clocked_by(saxiclk) reset_by(saxireset);
      method rready(esaxi_rready) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_rready);
      method esaxi_rresp rresp() clocked_by(saxiclk) reset_by(saxireset);
      method esaxi_rvalid rvalid() clocked_by(saxiclk) reset_by(saxireset);
      method wdata(esaxi_wdata) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_wdata);
      method wid(esaxi_wid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_wid);
      method wlast(esaxi_wlast) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_wlast);
      method esaxi_wready wready() clocked_by(saxiclk) reset_by(saxireset);
      method wstrb(esaxi_wstrb) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_wstrb);
      method wvalid(esaxi_wvalid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_wvalid);
      method esaxi_rid rid() clocked_by(saxiclk) reset_by(saxireset);
      //interface extraType   extra;

   endinterface

schedule (
   misc.csysack, misc.cactive, misc.reset_chip, misc.reset_fpga, txo.data_p, txo.data_n,
   txo.frame_p, txo.frame_n, txo.lclk_p, txo.lclk_n, rxo.wr_wait_p,
   rxo.wr_wait_n, rxo.rd_wait_p, rxo.rd_wait_n, rxi.cclk_p,
   rxi.cclk_n, maxi.awid, maxi.awaddr, maxi.awlen, maxi.awsize,
   maxi.awburst, maxi.awlock, maxi.awcache, maxi.awprot,
   maxi.awvalid, saxi.awready, maxi.wid, maxi.wdata, maxi.wstrb,
   maxi.wlast, maxi.wvalid, saxi.wready, maxi.bready, saxi.bid,
   saxi.bresp, saxi.bvalid, maxi.arid, maxi.araddr, maxi.arlen,
   maxi.arsize, maxi.arburst, maxi.arlock, maxi.arcache,
   maxi.arprot, maxi.arvalid, saxi.arready, maxi.rready,
   saxi.rid, saxi.rdata, saxi.rresp, saxi.rlast, saxi.rvalid,
   maxi.awqos, maxi.arqos,
   // Inputs
   // clkin_100, saxi.aclk, maxi.aclk, reset,
   saxi.aresetn,
   maxi.aresetn, misc.csysreq, rxi.data_p, rxi.data_n, rxi.frame_p,
   rxi.frame_n, rxi.lclk_p, rxi.lclk_n, txi.wr_wait_p, txi.wr_wait_n,
   txi.rd_wait_p, txi.rd_wait_n, maxi.awready, saxi.awid,
   saxi.awaddr, saxi.awlen, saxi.awsize, saxi.awburst,
   saxi.awlock, saxi.awcache, saxi.awprot, saxi.awvalid,
   maxi.wready, saxi.wid, saxi.wdata, saxi.wstrb, saxi.wlast,
   saxi.wvalid, maxi.bid, maxi.bresp, maxi.bvalid, saxi.bready,
   maxi.arready, saxi.arid, saxi.araddr, saxi.arlen, saxi.arsize,
   saxi.arburst, saxi.arlock, saxi.arcache, saxi.arprot,
   saxi.arvalid, maxi.rid, maxi.rdata, maxi.rresp, maxi.rlast,
   maxi.rvalid, saxi.rready, saxi.awqos, saxi.arqos
) CF (
   misc.csysack, misc.cactive, misc.reset_chip, misc.reset_fpga, txo.data_p, txo.data_n,
   txo.frame_p, txo.frame_n, txo.lclk_p, txo.lclk_n, rxo.wr_wait_p,
   rxo.wr_wait_n, rxo.rd_wait_p, rxo.rd_wait_n, rxi.cclk_p,
   rxi.cclk_n, maxi.awid, maxi.awaddr, maxi.awlen, maxi.awsize,
   maxi.awburst, maxi.awlock, maxi.awcache, maxi.awprot,
   maxi.awvalid, saxi.awready, maxi.wid, maxi.wdata, maxi.wstrb,
   maxi.wlast, maxi.wvalid, saxi.wready, maxi.bready, saxi.bid,
   saxi.bresp, saxi.bvalid, maxi.arid, maxi.araddr, maxi.arlen,
   maxi.arsize, maxi.arburst, maxi.arlock, maxi.arcache,
   maxi.arprot, maxi.arvalid, saxi.arready, maxi.rready,
   saxi.rid, saxi.rdata, saxi.rresp, saxi.rlast, saxi.rvalid,
   maxi.awqos, maxi.arqos,
   // Inputs
   // clkin_100, saxi.aclk, maxi.aclk, reset,
   saxi.aresetn,
   maxi.aresetn, misc.csysreq, rxi.data_p, rxi.data_n, rxi.frame_p,
   rxi.frame_n, rxi.lclk_p, rxi.lclk_n, txi.wr_wait_p, txi.wr_wait_n,
   txi.rd_wait_p, txi.rd_wait_n, maxi.awready, saxi.awid,
   saxi.awaddr, saxi.awlen, saxi.awsize, saxi.awburst,
   saxi.awlock, saxi.awcache, saxi.awprot, saxi.awvalid,
   maxi.wready, saxi.wid, saxi.wdata, saxi.wstrb, saxi.wlast,
   saxi.wvalid, maxi.bid, maxi.bresp, maxi.bvalid, saxi.bready,
   maxi.arready, saxi.arid, saxi.araddr, saxi.arlen, saxi.arsize,
   saxi.arburst, saxi.arlock, saxi.arcache, saxi.arprot,
   saxi.arvalid, maxi.rid, maxi.rdata, maxi.rresp, maxi.rlast,
   maxi.rvalid, saxi.rready, saxi.awqos, saxi.arqos

   );

endmodule

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

// This file is a hand-generated file that we hope will someday be
// generated automatically by connectal/generated/scripts/importbvi.py
//
// Created by copying the style of connectal/generated/xilinx/PPS7LIB.bsv

import Clocks::*;
import DefaultValue::*;
import XilinxCells::*;
import GetPut::*;
import AxiBits::*;

// The name of this interface is a prefix "Par_" plus the common prefix of the signals "txo"
// Hopefully this is what importbvi.py would do
(* always_ready, always_enabled *)
interface Par_txo;
   method Action data_p(Bit#(8) v);
   method Action data_n(Bit#(8) v);
   method Action frame_p(Bit#(1) v);
   method Action frame_n(Bit#(1) v);
   method Action lclk_p(Bit#(1) v);
   method Action lclk_n(Bit#(1) v);
endinterface

(* always_ready, always_enabled *)
interface Par_txi;
   method Bit#(1) wr_wait_p();
   method Bit#(1) wr_wait_n();
   method Bit#(1) rd_wait_p();
   method Bit#(1) rd_wait_n();
endinterface

(* always_ready, always_enabled *)
interface Par_rxi;
   method Bit#(8) data_p();
   method Bit#(8) data_n();
   method Bit#(1) frame_p();
   method Bit#(1) frame_n();
   method Bit#(1) lclk_p();
   method Bit#(1) lclk_n();
   method Action cclk_p(Bit#(1) v);
   method Action cclk_n(Bit#(1) v);
endinterface

(* always_ready, always_enabled *)
interface Par_rxo;
   method Action wr_wait_p(Bit#(1) v);
   method Action wr_wait_n(Bit#(1) v);
   method Action rd_wait_p(Bit#(1) v);
   method Action rd_wait_n(Bit#(1) v);
endinterface

(* always_ready, always_enabled *)
interface Par_misc;
   method Bit#(1) csysack();
   method Bit#(1) cactive();
   method Action csysreq();
   method Action reset_chip();
   method Action reset_fpga();
endinterface

(* always_ready, always_enabled *)
interface PParallellaLib;
   interface Par_txo txo;
   interface Par_txi txi;
   interface Par_rxo rxo;
   interface Par_rxi rxi;
   interface AxiSlaveBits#(32,32,12,Empty) maxi;   // this will connect to a master
   interface AxiMasterBits#(32,64,6,Empty) saxi;  // this will connect to a slave
   interface Par_misc misc;
endinterface

import "BVI" PParallellaZZZ =
module mkPParallellaLIB#(Clock maxiclk, Clock saxiclk,
   Reset maxiclk_reset, Reset saxiclk_reset,
   Reset maxireset, Reset saxireset,
   Reset reset_chip, Reset reset_fpga)(PParallellaLib);
   // default_clock clk();
   // default_reset rst();
   input_clock maxiclk(emaxi_aclk) = maxiclk;  // assigns the verilog emaxi_aclk
   input_clock saxiclk(esaxi_aclk) = saxiclk;  // assigns the verilog esaxi_aclk
   input_reset maxiclk_reset() = maxiclk_reset; /* from clock*/
   input_reset saxiclk_reset() = saxiclk_reset; /* from clock*/
   input_reset maxireset() = maxireset;
   input_reset saxireset() = saxireset;

   interface Par_misc misc;
      method csysack csysack();
      method cactive cactive();
      method csysreq(csysreq) enable((*inhigh*) EN_csysreq);
      method reset_chip(reset_chip) enable((*inhigh*) EN_reset_chip);
      method reset_fpga(reset_fpga) enable((*inhigh*) EN_reset_fpga);
   endinterface

   interface Par_txo txo;
      method data_p(txo_data_p) enable((*inhigh*) EN_txo_data_p);
      method data_n(txo_data_n) enable((*inhigh*) EN_txo_data_n);
      method frame_p(txo_frame_p) enable((*inhigh*) EN_txo_frame_p);
      method frame_n(txo_frame_n) enable((*inhigh*) EN_txo_frame_n);
      method lclk_p(txo_lclk_p) enable((*inhigh*) EN_txo_lclk_p);
      method lclk_n(txo_lclk_n) enable((*inhigh*) EN_txo_lclk_n);
   endinterface

   interface Par_txi txi;
      method txo_wr_wait_p wr_wait_p();
      method txo_wr_wait_n wr_wait_n();
      method txo_rd_wait_p rd_wait_p();
      method txo_rd_wait_n rd_wait_n();
   endinterface

   interface Par_rxi rxi;
      method rxi_data_p data_p();
      method rxi_data_n data_n();
      method rxi_frame_p frame_p();
      method rxi_frame_n frame_n();
      method rxi_lclk_p lclk_p();
      method rxi_lclk_n lclk_n();
      method cclk_p(rxi_cclk_p) enable((*inhigh*) EN_rxi_cclk_p);
      method cclk_n(rxi_cclk_n) enable((*inhigh*) EN_rxi_cclk_n);
   endinterface

   interface Par_rxo rxo;
      method wr_wait_p(rxo_wr_wait_p) enable((*inhigh*) EN_rxo_wr_wait_p);
      method wr_wait_n(rxo_wr_wait_n) enable((*inhigh*) EN_rxo_wr_wait_n);
      method rd_wait_p(rxo_rd_wait_p) enable((*inhigh*) EN_rxo_rd_wait_p);
      method rd_wait_n(rxo_rd_wait_n) enable((*inhigh*) EN_rxo_rd_wait_n);
   endinterface

   interface AxiSlaveBits maxi;
      method emaxi_araddr araddr() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arburst arburst() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arcache arcache() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_aresetn aresetn() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arid arid() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arlen arlen() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arlock arlock() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arprot arprot() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arqos arqos() clocked_by (maxiclk) reset_by(maxireset);
      method arready(emaxi_arready)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_arready);
      method emaxi_arsize arsize() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_arvalid arvalid() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awaddr awaddr() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awburst awburst() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awcache awcache() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awid awid() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awlen awlen() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awlock awlock() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awprot awprot() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awqos awqos() clocked_by (maxiclk) reset_by(maxireset);
      method awready(emaxi_awready)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_awready);
      method emaxi_awsize awsize() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_awvalid awvalid() clocked_by (maxiclk) reset_by(maxireset);
      method bid(emaxi_bid) enable((*inhigh*) EN_emaxi_bid);
      method emaxi_bready bready() clocked_by (maxiclk) reset_by(maxireset);
      method bresp(emaxi_bresp)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_bresp);
      method bvalid(emaxi_bvalid)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_bvalid);
      method rdata(emaxi_rdata)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_rdata);
      method rid(emaxi_rid)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_rid);
      method rlast(emaxi_rlast)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_rlast);
      method emaxi_rready rready() clocked_by (maxiclk) reset_by(maxireset);
      method rresp(emaxi_rresp)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_rresp);
      method rvalid(emaxi_rvalid)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_rvalid);
      method emaxi_wdata wdata() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_wid wid() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_wlast wlast() clocked_by (maxiclk) reset_by(maxireset);
      method wready(emaxi_wready)  clocked_by (maxiclk) reset_by(maxireset) enable((*inhigh*) EN_emaxi_wready);
      method emaxi_wstrb wstrb() clocked_by (maxiclk) reset_by(maxireset);
      method emaxi_wvalid wvalid() clocked_by (maxiclk) reset_by(maxireset);
   endinterface

   interface AxiMasterBits saxi;
      method araddr(esaxi_araddr) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_araddr);
      method arburst(esaxi_arburst) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arburst);
      method arcache(esaxi_arcache) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arcache);
      method esaxi_aresetn aresetn() clocked_by(saxiclk) reset_by(saxireset);
      method arid(esaxi_arid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arid);
      method arlen(esaxi_arlen) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arlen);
      method arlock(esaxi_arlock) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arlock);
      method arprot(esaxi_arprot) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arprot);
      method arqos(esaxi_arqos) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arqos);
      method esaxi_arready arready() clocked_by(saxiclk) reset_by(saxireset);
      method arsize(esaxi_arsize) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arsize);
      method arvalid(esaxi_arvalid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_arvalid);
      method awaddr(esaxi_awaddr) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awaddr);
      method awburst(esaxi_awburst) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awburst);
      method awcache(esaxi_awcache) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awcache);
      method awid(esaxi_awid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awid);
      method awlen(esaxi_awlen) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awlen);
      method awlock(esaxi_awlock) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awlock);
      method awprot(esaxi_awprot) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awprot);
      method awqos(esaxi_awqos) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awqos);
      method esaxi_awready awready() clocked_by(saxiclk) reset_by(saxireset);
      method awsize(esaxi_awsize) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awsize);
      method awvalid(esaxi_awvalid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_awvalid);
      method esaxi_bid bid() clocked_by(saxiclk) reset_by(saxireset);
      method bready(esaxi_bready) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_bready);
      method esaxi_bresp bresp() clocked_by(saxiclk) reset_by(saxireset);
      method esaxi_bvalid bvalid() clocked_by(saxiclk) reset_by(saxireset);
      method esaxi_rdata rdata() clocked_by(saxiclk) reset_by(saxireset);
      method esaxi_rlast rlast() clocked_by(saxiclk) reset_by(saxireset);
      method rready(esaxi_rready) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_rready);
      method esaxi_rresp rresp() clocked_by(saxiclk) reset_by(saxireset);
      method esaxi_rvalid rvalid() clocked_by(saxiclk) reset_by(saxireset);
      method wdata(esaxi_wdata) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_wdata);
      method wid(esaxi_wid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_wid);
      method wlast(esaxi_wlast) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_wlast);
      method esaxi_wready wready() clocked_by(saxiclk) reset_by(saxireset);
      method wstrb(esaxi_wstrb) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_wstrb);
      method wvalid(esaxi_wvalid) clocked_by(saxiclk) reset_by(saxireset) enable((*inhigh*) EN_esaxi_wvalid);
      method esaxi_rid rid() clocked_by(saxiclk) reset_by(saxireset);
      //interface extraType   extra;

   endinterface

schedule (
   misc.csysack, misc.cactive, misc.reset_chip, misc.reset_fpga, txo.data_p, txo.data_n,
   txo.frame_p, txo.frame_n, txo.lclk_p, txo.lclk_n, rxo.wr_wait_p,
   rxo.wr_wait_n, rxo.rd_wait_p, rxo.rd_wait_n, rxi.cclk_p,
   rxi.cclk_n, maxi.awid, maxi.awaddr, maxi.awlen, maxi.awsize,
   maxi.awburst, maxi.awlock, maxi.awcache, maxi.awprot,
   maxi.awvalid, saxi.awready, maxi.wid, maxi.wdata, maxi.wstrb,
   maxi.wlast, maxi.wvalid, saxi.wready, maxi.bready, saxi.bid,
   saxi.bresp, saxi.bvalid, maxi.arid, maxi.araddr, maxi.arlen,
   maxi.arsize, maxi.arburst, maxi.arlock, maxi.arcache,
   maxi.arprot, maxi.arvalid, saxi.arready, maxi.rready,
   saxi.rid, saxi.rdata, saxi.rresp, saxi.rlast, saxi.rvalid,
   maxi.awqos, maxi.arqos,
   // Inputs
   // clkin_100, saxi.aclk, maxi.aclk, reset,
   saxi.aresetn,
   maxi.aresetn, misc.csysreq, rxi.data_p, rxi.data_n, rxi.frame_p,
   rxi.frame_n, rxi.lclk_p, rxi.lclk_n, txi.wr_wait_p, txi.wr_wait_n,
   txi.rd_wait_p, txi.rd_wait_n, maxi.awready, saxi.awid,
   saxi.awaddr, saxi.awlen, saxi.awsize, saxi.awburst,
   saxi.awlock, saxi.awcache, saxi.awprot, saxi.awvalid,
   maxi.wready, saxi.wid, saxi.wdata, saxi.wstrb, saxi.wlast,
   saxi.wvalid, maxi.bid, maxi.bresp, maxi.bvalid, saxi.bready,
   maxi.arready, saxi.arid, saxi.araddr, saxi.arlen, saxi.arsize,
   saxi.arburst, saxi.arlock, saxi.arcache, saxi.arprot,
   saxi.arvalid, maxi.rid, maxi.rdata, maxi.rresp, maxi.rlast,
   maxi.rvalid, saxi.rready, saxi.awqos, saxi.arqos
) CF (
   misc.csysack, misc.cactive, misc.reset_chip, misc.reset_fpga, txo.data_p, txo.data_n,
   txo.frame_p, txo.frame_n, txo.lclk_p, txo.lclk_n, rxo.wr_wait_p,
   rxo.wr_wait_n, rxo.rd_wait_p, rxo.rd_wait_n, rxi.cclk_p,
   rxi.cclk_n, maxi.awid, maxi.awaddr, maxi.awlen, maxi.awsize,
   maxi.awburst, maxi.awlock, maxi.awcache, maxi.awprot,
   maxi.awvalid, saxi.awready, maxi.wid, maxi.wdata, maxi.wstrb,
   maxi.wlast, maxi.wvalid, saxi.wready, maxi.bready, saxi.bid,
   saxi.bresp, saxi.bvalid, maxi.arid, maxi.araddr, maxi.arlen,
   maxi.arsize, maxi.arburst, maxi.arlock, maxi.arcache,
   maxi.arprot, maxi.arvalid, saxi.arready, maxi.rready,
   saxi.rid, saxi.rdata, saxi.rresp, saxi.rlast, saxi.rvalid,
   maxi.awqos, maxi.arqos,
   // Inputs
   // clkin_100, saxi.aclk, maxi.aclk, reset,
   saxi.aresetn,
   maxi.aresetn, misc.csysreq, rxi.data_p, rxi.data_n, rxi.frame_p,
   rxi.frame_n, rxi.lclk_p, rxi.lclk_n, txi.wr_wait_p, txi.wr_wait_n,
   txi.rd_wait_p, txi.rd_wait_n, maxi.awready, saxi.awid,
   saxi.awaddr, saxi.awlen, saxi.awsize, saxi.awburst,
   saxi.awlock, saxi.awcache, saxi.awprot, saxi.awvalid,
   maxi.wready, saxi.wid, saxi.wdata, saxi.wstrb, saxi.wlast,
   saxi.wvalid, maxi.bid, maxi.bresp, maxi.bvalid, saxi.bready,
   maxi.arready, saxi.arid, saxi.araddr, saxi.arlen, saxi.arsize,
   saxi.arburst, saxi.arlock, saxi.arcache, saxi.arprot,
   saxi.arvalid, maxi.rid, maxi.rdata, maxi.rresp, maxi.rlast,
   maxi.rvalid, saxi.rready, saxi.awqos, saxi.arqos

   );

endmodule


fixed mkSpiTestBench

fixed mkSpiTestBench

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

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

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

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

import Clocks      :: *;
import GetPut      :: *;
import FIFOF       :: *;
import Probe       :: *;
import Connectable :: *;
import SpecialFIFOs:: *;
import SyncBits    :: *;
import StmtFSM     :: *;
import Assert      :: *;

(* always_enabled *)
interface SpiPins;
    method Bit#(1) mosi();
    method Bit#(1) sel_n();
    method Action miso(Bit#(1) v);
    interface Clock clock;
    interface Clock deleteme_unused_clock;
    interface Reset deleteme_unused_reset;
endinterface: SpiPins

interface SPI#(type a);
   interface Put#(a) request;
   interface Get#(a) response;
   interface SpiPins pins;
endinterface

module mkSpiShifter#(Bool invert_clk) (SPI#(a)) provisos(Bits#(a,awidth),Add#(1,awidth1,awidth),Log#(awidth,logawidth));

   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;
   ClockDividerIfc clockInverter <- mkClockInverter;
   Clock spiClock = clockInverter.slowClock;
   Reset spiReset <-  mkAsyncResetFromCR(2, clockInverter.slowClock);
   Reg#(Bit#(awidth)) shiftreg <- mkReg(unpack(0));
   Reg#(Bit#(1)) selreg <- mkReg(1);
   Reg#(Bit#(TAdd#(logawidth,1))) countreg <- mkReg(0);
   FIFOF#(a) resultFifo <- mkFIFOF;

   Clock outputClock = invert_clk ? clockInverter.slowClock : defaultClock;
   Reset outputReset = defaultReset;
   ReadOnly#(Bit#(awidth)) sync_shiftreg <- mkNullCrossingWire(outputClock, shiftreg);

   Wire#(Bit#(1)) misoWire <- mkDWire(0);
   let verbose = False;

   rule running if (countreg > 0);
      countreg <= countreg - 1;
      Bit#(awidth) newshiftreg = { shiftreg[valueOf(awidth)-2:0], misoWire };
      if(verbose) $display("newshiftreg = %08h", newshiftreg);
      shiftreg <= newshiftreg;
      if (countreg == 1 && resultFifo.notFull) begin
	 resultFifo.enq(unpack(newshiftreg));
	 selreg <= 1;
      end
   endrule

   interface Put request;
      method Action put(a v) if (countreg == 0);
	 selreg <= 0;
	 shiftreg <= pack(v);
	 countreg <= fromInteger(valueOf(awidth));
      endmethod
   endinterface: request

   interface Get response;
      method ActionValue#(a) get();
	 resultFifo.deq;
	 return resultFifo.first;
      endmethod
   endinterface: response

   interface SpiPins pins;
      method Bit#(1) mosi();
         return sync_shiftreg[valueOf(awidth)-1];
      endmethod
      method Bit#(1) sel_n();
	 return selreg;
      endmethod
      method Action miso(Bit#(1) v);
         misoWire <= v;
      endmethod
      interface Clock clock = outputClock;
      interface Clock deleteme_unused_clock = invert_clk ? defaultClock : clockInverter.slowClock;
      interface Reset deleteme_unused_reset = defaultReset;
   endinterface: pins
endmodule: mkSpiShifter

module mkSPI#(Integer divisor, Bool invert_clk)(SPI#(a)) provisos(Bits#(a,awidth),Add#(1,awidth1,awidth),Log#(awidth,logawidth));
   ClockDividerIfc clockDivider <- mkClockDivider(divisor);
   Reset slowReset <- mkAsyncResetFromCR(2, clockDivider.slowClock);
   SPI#(a) spi <- mkSpiShifter(invert_clk, clocked_by clockDivider.slowClock, reset_by slowReset);

   SyncFIFOIfc#(a) requestFifo <- mkSyncFIFOFromCC(1, clockDivider.slowClock);
   SyncFIFOIfc#(a) responseFifo <- mkSyncFIFOToCC(1, clockDivider.slowClock, slowReset);

   mkConnection(toGet(requestFifo), spi.request);
   mkConnection(spi.response, toPut(responseFifo));

   //interface spiClock = spi.spiClock;
   interface request = toPut(requestFifo);
   interface response = toGet(responseFifo);
   interface pins = spi.pins;
endmodule: mkSPI

module mkSPI20(SPI#(Bit#(20)));
   SPI#(Bit#(20)) spi <- mkSPI(200, True);
   return spi;
endmodule

module mkSpiTestBench(Empty);
   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;

   Bit#(20) slaveV = 20'h96ed5;
   Bit#(20) masterV = 20'h8baeb;
   let verbose = False;

   SPI#(Bit#(20)) spi <- mkSPI(4, False);
   Reg#(Bit#(20)) slaveCount <- mkReg(20, clocked_by spi.pins.clock, reset_by spi.pins.deleteme_unused_reset);
   Reg#(Bit#(20)) slaveValue <- mkReg(slaveV, clocked_by spi.pins.clock, reset_by spi.pins.deleteme_unused_reset);
   Reg#(Bit#(20)) responseValue <- mkReg(0, clocked_by spi.pins.clock, reset_by spi.pins.deleteme_unused_reset);
   SyncBitIfc#(Bit#(1)) sync_sel_n <- mkSyncBits(0, defaultClock, defaultReset, spi.pins.clock, spi.pins.deleteme_unused_reset);

   Probe#(Bit#(1)) probeSelN <- mkProbe(clocked_by spi.pins.clock, reset_by spi.pins.deleteme_unused_reset);
   Probe#(Bit#(1)) probeMiso <- mkProbe(clocked_by spi.pins.clock, reset_by spi.pins.deleteme_unused_reset);
   Probe#(Bit#(1)) probeMosi <- mkProbe(clocked_by spi.pins.clock, reset_by spi.pins.deleteme_unused_reset);

   rule probePins;
      probeSelN <= spi.pins.sel_n;
      probeMosi <= spi.pins.mosi;
   endrule

   rule slaveIn if (spi.pins.sel_n == 0);
      slaveCount <= slaveCount - 1;
      slaveValue <= (slaveValue << 1);
   endrule

   rule miso if (spi.pins.sel_n == 0);
      probeMiso <= slaveValue[19];
      spi.pins.miso(slaveValue[19]);
   endrule

   rule spipins if (spi.pins.sel_n == 0);
      if(verbose) $display("miso=%d mosi=%d sel=%d", slaveValue[19], spi.pins.mosi, sync_sel_n.read());
      responseValue <= { responseValue[18:0], spi.pins.mosi };
   endrule

   rule displaySlaveValue if (slaveCount == 0);
      if(verbose) $display("slave received %h", responseValue);
      dynamicAssert(responseValue == masterV, "wrong value received by slave");
   endrule

   rule finished;
      let result <- spi.response.get();
      if(verbose) $display("master received %h", result);
      dynamicAssert(result == slaveV, "wrong value received by master");
      $finish(0);
   endrule

   let once <- mkOnce(action
      if(verbose) $display("master sending %h; slave sending %h", masterV, slaveV);
      $dumpvars();
      spi.request.put(masterV);
      endaction);
   rule foobar;
      once.start();
   endrule

endmodule

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

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

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

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

import Clocks      :: *;
import GetPut      :: *;
import FIFOF       :: *;
import Connectable :: *;
import SpecialFIFOs:: *;
import StmtFSM     :: *;
import Assert      :: *;

(* always_enabled *)
interface SpiPins;
    method Bit#(1) mosi();
    method Bit#(1) sel_n();
    method Action miso(Bit#(1) v);
    interface Clock clock;
    interface Clock deleteme_unused_clock;
    interface Reset deleteme_unused_reset;
endinterface: SpiPins

interface SPI#(type a);
   interface Put#(a) request;
   interface Get#(a) response;
   interface SpiPins pins;
endinterface

module mkSpiShifter#(Bool invert_clk) (SPI#(a)) provisos(Bits#(a,awidth),Add#(1,awidth1,awidth),Log#(awidth,logawidth));

   Clock defaultClock <- exposeCurrentClock;
   Reset defaultReset <- exposeCurrentReset;
   ClockDividerIfc clockInverter <- mkClockInverter;
   Clock spiClock = clockInverter.slowClock;
   Reset spiReset <-  mkAsyncResetFromCR(2, clockInverter.slowClock);
   Reg#(Bit#(awidth)) shiftreg <- mkReg(unpack(0));
   Reg#(Bit#(1)) selreg <- mkReg(1);
   Reg#(Bit#(TAdd#(logawidth,1))) countreg <- mkReg(0);
   FIFOF#(a) resultFifo <- mkFIFOF;

   Wire#(Bit#(1)) misoWire <- mkDWire(0);
   let verbose = False;

   rule running if (countreg > 0);
      countreg <= countreg - 1;
      Bit#(awidth) newshiftreg = { shiftreg[valueOf(awidth)-2:0], misoWire };
      if(verbose) $display("newshiftreg = %08h", newshiftreg);
      shiftreg <= newshiftreg;
      if (countreg == 1 && resultFifo.notFull) begin
	 resultFifo.enq(unpack(newshiftreg));
	 selreg <= 1;
      end
   endrule

   interface Put request;
      method Action put(a v) if (countreg == 0);
	 selreg <= 0;
	 shiftreg <= pack(v);
	 countreg <= fromInteger(valueOf(awidth));
      endmethod
   endinterface: request

   interface Get response;
      method ActionValue#(a) get();
	 resultFifo.deq;
	 return resultFifo.first;
      endmethod
   endinterface: response

   interface SpiPins pins;
      method Bit#(1) mosi();
         return shiftreg[valueOf(awidth)-1];
      endmethod
      method Bit#(1) sel_n();
	 return selreg;
      endmethod
      method Action miso(Bit#(1) v);
         misoWire <= v;
      endmethod
      interface Clock clock = invert_clk ? clockInverter.slowClock : defaultClock;
      interface Clock deleteme_unused_clock = invert_clk ? defaultClock : clockInverter.slowClock;
      interface Reset deleteme_unused_reset = defaultReset;
   endinterface: pins
endmodule: mkSpiShifter

module mkSPI#(Integer divisor, Bool invert_clk)(SPI#(a)) provisos(Bits#(a,awidth),Add#(1,awidth1,awidth),Log#(awidth,logawidth));
   ClockDividerIfc clockDivider <- mkClockDivider(divisor);
   Reset slowReset <- mkAsyncResetFromCR(2, clockDivider.slowClock);
   SPI#(a) spi <- mkSpiShifter(invert_clk, clocked_by clockDivider.slowClock, reset_by slowReset);

   SyncFIFOIfc#(a) requestFifo <- mkSyncFIFOFromCC(1, clockDivider.slowClock);
   SyncFIFOIfc#(a) responseFifo <- mkSyncFIFOToCC(1, clockDivider.slowClock, slowReset);

   mkConnection(toGet(requestFifo), spi.request);
   mkConnection(spi.response, toPut(responseFifo));

   //interface spiClock = spi.spiClock;
   interface request = toPut(requestFifo);
   interface response = toGet(responseFifo);
   interface pins = spi.pins;
endmodule: mkSPI

module mkSPI20(SPI#(Bit#(20)));
   SPI#(Bit#(20)) spi <- mkSPI(200, True);
   return spi;
endmodule

module mkSpiTestBench(Empty);
   Bit#(20) slaveV = 20'h96ed5;
   Bit#(20) masterV = 20'h8baeb;
   let verbose = False;

   SPI#(Bit#(20)) spi <- mkSPI(4, True);
   Reg#(Bit#(20)) slaveCount <- mkReg(20, clocked_by spi.pins.clock, reset_by spi.pins.deleteme_unused_reset);
   Reg#(Bit#(20)) slaveValue <- mkReg(slaveV, clocked_by spi.pins.clock, reset_by spi.pins.deleteme_unused_reset);
   Reg#(Bit#(20)) responseValue <- mkReg(0, clocked_by spi.pins.clock, reset_by spi.pins.deleteme_unused_reset);

   rule slaveIn if (spi.pins.sel_n == 0);
      slaveCount <= slaveCount - 1;
      slaveValue <= (slaveValue << 1);
   endrule

   rule miso if (spi.pins.sel_n == 0);
      spi.pins.miso(slaveValue[19]);
   endrule

   rule spipins if (spi.pins.sel_n == 0);
      if(verbose) $display("miso=%d mosi=%d sel=%d", slaveValue[19], spi.pins.mosi, spi.pins.sel_n);
      responseValue <= { responseValue[18:0], spi.pins.mosi };
   endrule

   rule displaySlaveValue if (slaveCount == 0);
      if(verbose) $display("slave received %h", responseValue);
      dynamicAssert(responseValue == masterV, "wrong value received by slave");
   endrule

   rule finished;
      let result <- spi.response.get();
      if(verbose) $display("master received %h", result);
      dynamicAssert(result == slaveV, "wrong value received by master");
      $finish(0);
   endrule

   let once <- mkOnce(action
      if(verbose) $display("master sending %h; slave sending %h", masterV, slaveV);
      spi.request.put(masterV);
      endaction);
   rule foobar;
      once.start();
   endrule

endmodule


add delete_me clock and reset

add delete_me clock and reset

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

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

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

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

import XilinxCells::*;
import XbsvXilinxCells::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;

(* always_enabled *)
interface FMComms1ADCPins;
   method Action io_adc_data_p(Bit#(14) v);
   method Action io_adc_data_n(Bit#(14) v);
   method Action io_adc_or_p(Bit#(1) v);
   method Action io_adc_or_n(Bit#(1) v);
   method Action io_adc_dco_p(Bit#(1) v);
   method Action io_adc_dco_n(Bit#(1) v);
   interface Clock deleteme_unused_clock;
   interface Reset deleteme_unused_reset;
endinterface

typedef struct {
   Bit#(14) data_i;
   Bit#(1) z_i;
   Bit#(1) or_i;
   Bit#(14) data_q;
   Bit#(1) z_q;
   Bit#(1) or_q;
   } IQ deriving (Bits);

interface FMComms1ADC;
   interface FMComms1ADCPins pins;
   interface PipeOut#(Bit#(64)) adc;
endinterface

/* This module accepts inputs from an Analog Devices FMComms1
 * evaluation board Analog to Digital Converter, and delivers
 * the data as a PipeOut type on the default clock.
 *
 * Input is double data rate, with clock supplied by the FMComms1
 * Input data is 14 bits twos-complement or offset binary, plus
 * an overrange signa=
 *
 * Differential inputs are converted to single ended by using Xilinx IBUFDS
 * cells. The clock is converted to single ended by an IBUFGDS cell
 *
 * DDR data is convered to SDR using IDDR cells
 * At this point, the data is a 14 bit in-phase data signal, plus in-phase
 * overrange, but a 14 bit quadrature signal, plus overrange.
 *
 * The data is packed into a 64-bit IQ datatype, with overrange as the LSB
 *
 * The 32-bit data is converted to 64-bits by a Gearbox
 *
 * Clock conversion happens 64-bits wide using a SyncBRAMFIFO, which
 * presents a PipeOut channel to the rest of the logic.
 */

module mkFMComms1ADC(FMComms1ADC);

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

   function Bit#(1) foo(ReadOnly#(Bit#(1)) v);
      return (v._read());
   endfunction

   function ReadOnly#(Bit#(14)) rofromrov(Vector#(14, ReadOnly#(Bit#(1))) v);
      return(interface ReadOnly;
	     method Bit#(14) _read;
		return ( pack(map(foo, v)));
	     endmethod
	     endinterface
	     );
   endfunction

   Clock adc_dco;     /* DDR clock */
   Wire#(Bit#(1)) adc_dco_p <- mkDWire(0);
   Wire#(Bit#(1)) adc_dco_n <- mkDWire(0);
   adc_dco <- mkClockIBUFDS(adc_dco_p, adc_dco_n);

   Vector#(14, Wire#(Bit#(1))) adc_data_p = newVector;
   for (Integer i = 0; i < 14; i = i + 1)
      adc_data_p[i] <- mkDWire(0, clocked_by adc_dco);

   Vector#(14, Wire#(Bit#(1))) adc_data_n = newVector;
   for (Integer i = 0; i < 14; i = i + 1)
      adc_data_n[i] <- mkDWire(0, clocked_by adc_dco);

   Wire#(Bit#(1)) adc_or_p <- mkDWire(0, clocked_by adc_dco);
   Wire#(Bit#(1)) adc_or_n <- mkDWire(0, clocked_by adc_dco);

   Vector#(14, ReadOnly#(Bit#(1))) v_adc_data;   /* data */
   ReadOnly#(Bit#(14)) adc_data;

   ReadOnly#(Bit#(1)) adc_or;      /* overrange */

   Reset adc_reset <- mkAsyncReset(3, def_reset, adc_dco);
   for(Integer i = 0; i < 14; i = i + 1)
      v_adc_data[i] <- mkIBUFDS(adc_data_p[i], adc_data_n[i], clocked_by adc_dco);
   adc_data = rofromrov(v_adc_data);

   adc_or <- mkIBUFDS(adc_or_p, adc_or_n, clocked_by adc_dco);

   IDDRParams#(Bit#(14)) iddrparams_data = defaultValue;
//   iddrparams_data.ddr_clk_edge = "SAME_EDGE_PIPELINED";
      iddrparams_data.ddr_clk_edge = "SAME_EDGE";
   IDDR#(Bit#(14)) adc_sdr_data <- mkIDDR(iddrparams_data, clocked_by adc_dco);

   IDDRParams#(Bit#(1)) iddrparams_or = defaultValue;
//   iddrparams_or.ddr_clk_edge = "SAME_EDGE_PIPELINED";
   iddrparams_or.ddr_clk_edge = "SAME_EDGE";
   IDDR#(Bit#(1)) adc_sdr_or <- mkIDDR(iddrparams_or, clocked_by adc_dco);

   rule sendup_adc_data;
      adc_sdr_data.d(pack(adc_data));
   endrule

   rule sendup_adc_or;
      adc_sdr_or.d(adc_or);
   endrule

   Gearbox#(1, 2, IQ) gb <- mk1toNGearbox(adc_dco, adc_reset, adc_dco, adc_reset);
   SyncFIFOIfc#(Vector#(2, IQ)) infifo <- mkSyncBRAMFIFO(128, adc_dco, adc_reset, def_clock, def_reset);

   rule sendup_gb_data;
      gb.enq(unpack(pack(IQ{data_i: adc_sdr_data.q1, z_i: 0, or_i: adc_sdr_or.q1,
	 data_q: adc_sdr_data.q2, z_q: 0, or_q: adc_sdr_or.q2})));
   endrule

   rule sendup_adc_fifo_data;
      gb.deq();
      infifo.enq(gb.first());
   endrule

   interface FMComms1ADCPins pins;

      method Action io_adc_data_p(Bit#(14) v);
         for (Integer i = 0; i < 14; i = i + 1)
	    adc_data_p[i] <= v[i];
      endmethod

      method Action io_adc_data_n(Bit#(14) v);
         for (Integer i = 0; i < 14; i = i + 1)
	    adc_data_n[i] <= v[i];
      endmethod

      method Action io_adc_or_p(Bit#(1) v);
	 adc_or_p <= v;
      endmethod

      method Action io_adc_or_n(Bit#(1) v);
	 adc_or_n <= v;
      endmethod
      method Action io_adc_dco_p(Bit#(1) v);
	 adc_dco_p <= v;
      endmethod

      method Action io_adc_dco_n(Bit#(1) v);
	 adc_dco_n <= v;
      endmethod
      interface deleteme_unused_clock = defaultClock;
      interface deleteme_unused_reset = defaultReset;

   endinterface

   interface PipeOut adc;

      method Bit#(64) first();
	 return(unpack(pack(infifo.first)));
      endmethod

      method Action deq() = infifo.deq;

      method Bool notEmpty() = infifo.notEmpty;

   endinterface

endmodule

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

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

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

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

import XilinxCells::*;
import XbsvXilinxCells::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;

(* always_enabled *)
interface FMComms1ADCPins;
   method Action io_adc_data_p(Bit#(14) v);
   method Action io_adc_data_n(Bit#(14) v);
   method Action io_adc_or_p(Bit#(1) v);
   method Action io_adc_or_n(Bit#(1) v);
   method Action io_adc_dco_p(Bit#(1) v);
   method Action io_adc_dco_n(Bit#(1) v);
endinterface

typedef struct {
   Bit#(14) data_i;
   Bit#(1) z_i;
   Bit#(1) or_i;
   Bit#(14) data_q;
   Bit#(1) z_q;
   Bit#(1) or_q;
   } IQ deriving (Bits);

interface FMComms1ADC;
   interface FMComms1ADCPins pins;
   interface PipeOut#(Bit#(64)) adc;
endinterface

/* This module accepts inputs from an Analog Devices FMComms1
 * evaluation board Analog to Digital Converter, and delivers
 * the data as a PipeOut type on the default clock.
 *
 * Input is double data rate, with clock supplied by the FMComms1
 * Input data is 14 bits twos-complement or offset binary, plus
 * an overrange signa=
 *
 * Differential inputs are converted to single ended by using Xilinx IBUFDS
 * cells. The clock is converted to single ended by an IBUFGDS cell
 *
 * DDR data is convered to SDR using IDDR cells
 * At this point, the data is a 14 bit in-phase data signal, plus in-phase
 * overrange, but a 14 bit quadrature signal, plus overrange.
 *
 * The data is packed into a 64-bit IQ datatype, with overrange as the LSB
 *
 * The 32-bit data is converted to 64-bits by a Gearbox
 *
 * Clock conversion happens 64-bits wide using a SyncBRAMFIFO, which
 * presents a PipeOut channel to the rest of the logic.
 */

module mkFMComms1ADC(FMComms1ADC);

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

   function Bit#(1) foo(ReadOnly#(Bit#(1)) v);
      return (v._read());
   endfunction

   function ReadOnly#(Bit#(14)) rofromrov(Vector#(14, ReadOnly#(Bit#(1))) v);
      return(interface ReadOnly;
	     method Bit#(14) _read;
		return ( pack(map(foo, v)));
	     endmethod
	     endinterface
	     );
   endfunction

   Vector#(14, Wire#(Bit#(1))) adc_data_p = newVector;

   for (Integer i = 0; i < 14; i = i + 1)
      adc_data_p[i] <- mkDWire(0);
   Vector#(14, Wire#(Bit#(1))) adc_data_n = newVector;
   for (Integer i = 0; i < 14; i = i + 1)
      adc_data_n[i] <- mkDWire(0);

   Wire#(Bit#(1)) adc_or_p <- mkDWire(0);
   Wire#(Bit#(1)) adc_or_n <- mkDWire(0);
   Wire#(Bit#(1)) adc_dco_p <- mkDWire(0);
   Wire#(Bit#(1)) adc_dco_n <- mkDWire(0);

   Vector#(14, ReadOnly#(Bit#(1))) v_adc_data;   /* data */
   ReadOnly#(Bit#(14)) adc_data;

   ReadOnly#(Bit#(1)) adc_or;      /* overrange */
   Clock adc_dco;     /* DDR clock */

   adc_dco <- mkClockIBUFDS(adc_dco_p, adc_dco_n);

   Reset adc_reset <- mkAsyncReset(3, def_reset, adc_dco);
   for(Integer i = 0; i < 14; i = i + 1)
      v_adc_data[i] <- mkIBUFDS(adc_data_p[i], adc_data_n[i], clocked_by adc_dco);
   adc_data = rofromrov(v_adc_data);

   adc_or <- mkIBUFDS(adc_or_p, adc_or_n, clocked_by adc_dco);

   IDDRParams#(Bit#(14)) iddrparams_data = defaultValue;
   iddrparams_data.ddr_clk_edge = "SAME_EDGE_PIPELINED";
   IDDR#(Bit#(14)) adc_sdr_data <- mkIDDR(iddrparams_data, clocked_by adc_dco);

   IDDRParams#(Bit#(1)) iddrparams_or = defaultValue;
   iddrparams_or.ddr_clk_edge = "SAME_EDGE_PIPELINED";
   IDDR#(Bit#(1)) adc_sdr_or <- mkIDDR(iddrparams_or, clocked_by adc_dco);

   rule sendup_adc_data;
      adc_sdr_data.d(pack(adc_data));
   endrule

   rule sendup_adc_or;
      adc_sdr_or.d(adc_or);
   endrule

   Gearbox#(1, 2, IQ) gb <- mk1toNGearbox(adc_dco, adc_reset, adc_dco, adc_reset);
   SyncFIFOIfc#(Vector#(2, IQ)) infifo <- mkSyncBRAMFIFO(128, adc_dco, adc_reset, def_clock, def_reset);

   rule sendup_gb_data;
      gb.enq(unpack(pack(IQ{data_i: adc_sdr_data.q1, z_i: 0, or_i: adc_sdr_or.q1,
	 data_q: adc_sdr_data.q2, z_q: 0, or_q: adc_sdr_or.q2})));
   endrule

   rule sendup_adc_fifo_data;
      gb.deq();
      infifo.enq(gb.first());
   endrule

   interface FMComms1ADCPins pins;

      method Action io_adc_data_p(Bit#(14) v);
         for (Integer i = 0; i < 14; i = i + 1)
	    adc_data_p[i] <= v[i];
      endmethod

      method Action io_adc_data_n(Bit#(14) v);
         for (Integer i = 0; i < 14; i = i + 1)
	    adc_data_n[i] <= v[i];
      endmethod

      method Action io_adc_or_p(Bit#(1) v);
	 adc_or_p <= v;
      endmethod

      method Action io_adc_or_n(Bit#(1) v);
	 adc_or_n <= v;
      endmethod
      method Action io_adc_dco_p(Bit#(1) v);
	 adc_dco_p <= v;
      endmethod

      method Action io_adc_dco_n(Bit#(1) v);
	 adc_dco_n <= v;
      endmethod

   endinterface

   interface PipeOut adc;

      method Bit#(64) first();
	 return(unpack(pack(infifo.first)));
      endmethod

      method Action deq() = infifo.deq;

      method Bool notEmpty() = infifo.notEmpty;

   endinterface

endmodule


add dci logic

add dci logic

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

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

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

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

import XilinxCells::*;
import XbsvXilinxCells::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;

import extraXilinxCells::*;

(* always_enabled *)
interface FMComms1DACPins;
   method Bit#(14) io_dac_data_p();
   method Bit#(14) io_dac_data_n();
   method Action io_dac_dco_p(Bit#(1) v);
   method Action io_dac_dco_n(Bit#(1) v);
   interface Bit#(1) io_dac_dci_p();
   interface Bit#(2) io_dac_dci_n();
   interface Clock deleteme_unused_clock;
   interface Reset deleteme_unused_reset;
endinterface

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

interface FMComms1DAC;
   interface FMComms1DACPins pins;
   interface PipeIn#(Bit#(64)) dac;
endinterface

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

module mkFMComms1DAC(FMComms1DAC);

   Clock def_clock <- exposeCurrentClock;
   Reset def_reset <- exposeCurrentReset;
   Clock dac_dco;
   Wire#(Bit#(1)) dac_dco_p <- mkDWire(0);
   Wire#(Bit#(1)) dac_dco_n <- mkDWire(0);

   dac_dco <- mkClockIBUFDS(dac_dco_p, dac_dco_n);
   Reset dac_reset <- mkAsyncReset(3, def_reset, dac_dco);

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

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

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

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

   Vector#(14, DiffOut) dac_out = newVector;

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

   Bit#(1) dac_dci_bit <- mkC2B(dac_dco);
   Wire#(Bit#(1)) dac_dci_wire <- mkDWire(0);

   rule senddown_clk;
      dac_dci_wire <- dac_dci_bit;
   endrule

   DiffOut dac_dci <- mkxOBUFDS(dac_dci_wire);

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

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

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

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

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

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

   interface FMComms1DACPins pins;

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

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

      method Bit#(1) io_dac_dci_p();
         return(dac_dci.read_p());
      endmethod

      method Bit#(1) io_dac_dci_n();
         return(dac_dci.read_n());
      endmethod

      method Action io_dac_dco_p(Bit#(1) v);
	 dac_dco_p <= v;
      endmethod

      method Action io_dac_dco_n(Bit#(1) v);
	 dac_dco_n <= v;
      endmethod
      interface deleteme_unused_clock = dac_dco;
      interface deleteme_unused_reset = dac_reset;

   endinterface

   interface PipeIn dac;

      method Action enq(Bit#(64) v);
	 outfifo.enq(unpack(pack(v)));
      endmethod

      method Bool notFull() = outfifo.notFull;

   endinterface

endmodule

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

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

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

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

import XilinxCells::*;
import XbsvXilinxCells::*;
import Gearbox::*;
import Pipe::*;
import FIFO::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import DefaultValue::*;

import extraXilinxCells::*;

(* always_enabled *)
interface FMComms1DACPins;
   method Bit#(14) io_dac_data_p();
   method Bit#(14) io_dac_data_n();
   method Action io_dac_dco_p(Bit#(1) v);
   method Action io_dac_dco_n(Bit#(1) v);
   interface Clock deleteme_unused_clock;
   interface Reset deleteme_unused_reset;
endinterface

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

interface FMComms1DAC;
   interface FMComms1DACPins pins;
   interface PipeIn#(Bit#(64)) dac;
endinterface

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

module mkFMComms1DAC(FMComms1DAC);

   Clock def_clock <- exposeCurrentClock;
   Reset def_reset <- exposeCurrentReset;
   Clock dac_dco;
   Wire#(Bit#(1)) dac_dco_p <- mkDWire(0);
   Wire#(Bit#(1)) dac_dco_n <- mkDWire(0);

   dac_dco <- mkClockIBUFDS(dac_dco_p, dac_dco_n);
   Reset dac_reset <- mkAsyncReset(3, def_reset, dac_dco);

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

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

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

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

   Vector#(14, DiffOut) dac_out = newVector;

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

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

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

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

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

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

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

   interface FMComms1DACPins pins;

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

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

      method Action io_dac_dco_p(Bit#(1) v);
	 dac_dco_p <= v;
      endmethod

      method Action io_dac_dco_n(Bit#(1) v);
	 dac_dco_n <= v;
      endmethod
      interface deleteme_unused_clock = dac_dco;
      interface deleteme_unused_reset = dac_reset;

   endinterface

   interface PipeIn dac;

      method Action enq(Bit#(64) v);
	 outfifo.enq(unpack(pack(v)));
      endmethod

      method Bool notFull() = outfifo.notFull;

   endinterface

endmodule


manually pad SPI request/response from 26 to 32 bits

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

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

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

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

import FIFO::*;
import GetPut::*;
import Connectable :: *;
import PCIE :: *; // ConnectableWithClocks
import Clocks :: *;
import XbsvSpi :: *;

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

interface CoreIndication;
    method Action spi_control_value(Bit#(32) v);
    method Action iserdes_control_value(Bit#(32) v);
    method Action decoder_control_value(Bit#(32) v);
    method Action triggen_control_value(Bit#(32) v);
    method Action spi_rxfifo_value(Bit#(32) v);
    method Action debugind(Bit#(32) v);
    method Action spi_response(Bit#(32) v);
endinterface

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

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

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

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

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

interface ImageCaptureRequest;
   interface CoreRequest coreRequest;
   interface BlueScopeRequest bsRequest;
   interface ImageonVita imageon;
   interface ImageonSensorData sensor_data;
   interface HDMI hdmi;
   interface SpiPins spi;
endinterface

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

    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    Reset imageon_reset <- mkAsyncReset(2, defaultReset, imageon_clock);
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);

    ImageonVitaController imageonVita <- mkImageonVitaController();
    ImageonControl control = imageonVita.control;
    ImageonXsviFromSensor xsviFromSensor <- mkImageonXsviFromSensor(imageon_clock, imageon_reset, clocked_by hdmi_clock, reset_by hdmi_reset);

    Reg#(Bit#(32)) debugind_value <- mkSyncReg(0, hdmi_clock, hdmi_reset, defaultClock);
    rule copydebugval;
        debugind_value <= xsviFromSensor.in.get_debugind();
    endrule

    AxiDMA dma <- mkAxiDMA;
    WriteChan dma_debug_write_chan = dma.write.writeChannels[1];
    BlueScopeInternal bsi <- mkSyncBlueScopeInternal(32, dma_debug_write_chan, indication.bsIndication,
					             hdmi_clock, hdmi_reset, defaultClock, defaultReset);

    SPI#(Bit#(26)) spiController <- mkSPI(1000);

    SensorToVideo converter <- mkSensorToVideo(clocked_by hdmi_clock, reset_by hdmi_reset);
    HdmiOut hdmiOut <- mkHdmiOut(clocked_by hdmi_clock, reset_by hdmi_reset);

    mkConnection(control.rxfifo_response.get, indication.coreIndication.spi_rxfifo_value);
    // hdmi clock domain
    //mkConnection(xsviFromSensor.out, converter.in);
    rule xsviConnection;
        let xsvi <- xsviFromSensor.out.get();
        //bsi.dataIn(extend(pack(xsvi)), extend(pack(xsvi)));
        converter.in.put(xsvi);
    endrule
    // hdmi clock domain
    mkConnection(converter.out, hdmiOut.rgb);

    rule spiControllerResponse;
       Bit#(26) v <- spiController.response.get();
       indication.coreIndication.spi_response(extend(v));
    endrule

    interface CoreRequest coreRequest;
    method Action set_spi_control(Bit#(32) v);
        control.set_spi_control(v);
    endmethod
    method Action get_spi_control();
        indication.coreIndication.spi_control_value(control.get_spi_control());
    endmethod

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

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

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

    method Action set_host_vita_reset(Bit#(1) v);
        control.set_host_vita_reset(v);
    endmethod
    method Action set_host_oe(Bit#(1) v);
        control.set_host_oe(v);
    endmethod

    method Action set_spi_reset(Bit#(1) v);
        control.set_spi_reset(v);
    endmethod
    method Action set_spi_timing(Bit#(16) v);
        control.set_spi_timing(v);
    endmethod
    method Action put_spi_txfifo(Bit#(32) v);
        control.txfifo.put(v);
    endmethod
    method Action get_spi_rxfifo();
        control.rxfifo_request.put(32'hABBAABBA);
    endmethod

    method Action set_serdes_reset(Bit#(1) v);
        control.set_serdes_reset(v);
    endmethod
    method Action set_serdes_auto_align(Bit#(1) v);
        control.set_serdes_auto_align(v);
    endmethod
    method Action set_serdes_align_start(Bit#(1) v);
        control.set_serdes_align_start(v);
    endmethod
    method Action set_serdes_fifo_enable(Bit#(1) v);
        control.set_serdes_fifo_enable(v);
    endmethod
    method Action set_serdes_manual_tap(Bit#(10) v);
        control.set_serdes_manual_tap(v);
    endmethod
    method Action set_serdes_training(Bit#(10) v);
        control.set_serdes_training(v);
    endmethod
    method Action set_decoder_reset(Bit#(1) v);
        control.set_decoder_reset(v);
    endmethod
    method Action set_decoder_enable(Bit#(1) v);
        control.set_decoder_enable(v);
    endmethod
    method Action set_decoder_code_ls(Bit#(10) v);
        control.set_decoder_code_ls(v);
    endmethod
    method Action set_decoder_code_le(Bit#(10) v);
        control.set_decoder_code_le(v);
    endmethod
    method Action set_decoder_code_fs(Bit#(10) v);
        control.set_decoder_code_fs(v);
    endmethod
    method Action set_decoder_code_fe(Bit#(10) v);
        control.set_decoder_code_fe(v);
    endmethod
    method Action set_decoder_code_bl(Bit#(10) v);
        control.set_decoder_code_bl(v);
    endmethod
    method Action set_decoder_code_img(Bit#(10) v);
        control.set_decoder_code_img(v);
    endmethod
    method Action set_trigger_enable(Bit#(3) v);
        control.set_trigger_enable(v);
    endmethod
    method Action set_trigger_default_freq(Bit#(32) v);
        control.set_trigger_default_freq(v);
    endmethod
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
        control.set_trigger_cnt_trigger0high(v);
    endmethod
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
        control.set_trigger_cnt_trigger0low(v);
    endmethod
    method Action set_syncgen_delay(Bit#(16) v);
        control.set_syncgen_delay(v);
    endmethod
    method Action set_syncgen_hactive(Bit#(16) v);
        control.set_syncgen_hactive(v);
    endmethod
    method Action set_syncgen_hfporch(Bit#(16) v);
        control.set_syncgen_hfporch(v);
    endmethod
    method Action set_syncgen_hsync(Bit#(16) v);
        control.set_syncgen_hsync(v);
    endmethod
    method Action set_syncgen_hbporch(Bit#(16) v);
        control.set_syncgen_hbporch(v);
    endmethod
    method Action set_syncgen_vactive(Bit#(16) v);
        control.set_syncgen_vactive(v);
    endmethod
    method Action set_syncgen_vfporch(Bit#(16) v);
        control.set_syncgen_vfporch(v);
    endmethod
    method Action set_syncgen_vsync(Bit#(16) v);
        control.set_syncgen_vsync(v);
    endmethod
    method Action set_syncgen_vbporch(Bit#(16) v);
        control.set_syncgen_vbporch(v);
    endmethod
    method Action set_debugreq(Bit#(32) v);
        control.set_debugreq(v);
    endmethod
    method Action get_debugind();
        //indication.coreIndication.debugind(control.get_debugind());
        indication.coreIndication.debugind(debugind_value);
    endmethod
    method Action put_spi_request(Bit#(32) v);
        spiController.request.put(truncate(v));
    endmethod

    endinterface
   interface BlueScopeRequest bsRequest = bsi.requestIfc;
   interface ImageonVita imageon = imageonVita.host;
   interface ImageonSensorData sensor_data = xsviFromSensor.in;
   interface HDMI hdmi = hdmiOut.hdmi;
   interface SpiPins spi = spiController.pins;
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 GetPut::*;
import Connectable :: *;
import PCIE :: *; // ConnectableWithClocks
import Clocks :: *;
import XbsvSpi :: *;

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

interface CoreIndication;
    method Action spi_control_value(Bit#(32) v);
    method Action iserdes_control_value(Bit#(32) v);
    method Action decoder_control_value(Bit#(32) v);
    method Action triggen_control_value(Bit#(32) v);
    method Action spi_rxfifo_value(Bit#(32) v);
    method Action debugind(Bit#(32) v);
    method Action spi_response(Bit#(26) v);
endinterface

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

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

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

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

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

interface ImageCaptureRequest;
   interface CoreRequest coreRequest;
   interface BlueScopeRequest bsRequest;
   interface ImageonVita imageon;
   interface ImageonSensorData sensor_data;
   interface HDMI hdmi;
   interface SpiPins spi;
endinterface

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

    Clock defaultClock <- exposeCurrentClock();
    Reset defaultReset <- exposeCurrentReset();
    Reset imageon_reset <- mkAsyncReset(2, defaultReset, imageon_clock);
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);

    ImageonVitaController imageonVita <- mkImageonVitaController();
    ImageonControl control = imageonVita.control;
    ImageonXsviFromSensor xsviFromSensor <- mkImageonXsviFromSensor(imageon_clock, imageon_reset, clocked_by hdmi_clock, reset_by hdmi_reset);

    Reg#(Bit#(32)) debugind_value <- mkSyncReg(0, hdmi_clock, hdmi_reset, defaultClock);
    rule copydebugval;
        debugind_value <= xsviFromSensor.in.get_debugind();
    endrule

    AxiDMA dma <- mkAxiDMA;
    WriteChan dma_debug_write_chan = dma.write.writeChannels[1];
    BlueScopeInternal bsi <- mkSyncBlueScopeInternal(32, dma_debug_write_chan, indication.bsIndication,
					             hdmi_clock, hdmi_reset, defaultClock, defaultReset);

    SPI#(Bit#(26)) spiController <- mkSPI(1000);

    SensorToVideo converter <- mkSensorToVideo(clocked_by hdmi_clock, reset_by hdmi_reset);
    HdmiOut hdmiOut <- mkHdmiOut(clocked_by hdmi_clock, reset_by hdmi_reset);

    mkConnection(control.rxfifo_response.get, indication.coreIndication.spi_rxfifo_value);
    // hdmi clock domain
    //mkConnection(xsviFromSensor.out, converter.in);
    rule xsviConnection;
        let xsvi <- xsviFromSensor.out.get();
        //bsi.dataIn(extend(pack(xsvi)), extend(pack(xsvi)));
        converter.in.put(xsvi);
    endrule
    // hdmi clock domain
    mkConnection(converter.out, hdmiOut.rgb);

    mkConnection(spiController.response.get(), indication.coreIndication.spi_response);

    interface CoreRequest coreRequest;
    method Action set_spi_control(Bit#(32) v);
        control.set_spi_control(v);
    endmethod
    method Action get_spi_control();
        indication.coreIndication.spi_control_value(control.get_spi_control());
    endmethod

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

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

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

    method Action set_host_vita_reset(Bit#(1) v);
        control.set_host_vita_reset(v);
    endmethod
    method Action set_host_oe(Bit#(1) v);
        control.set_host_oe(v);
    endmethod

    method Action set_spi_reset(Bit#(1) v);
        control.set_spi_reset(v);
    endmethod
    method Action set_spi_timing(Bit#(16) v);
        control.set_spi_timing(v);
    endmethod
    method Action put_spi_txfifo(Bit#(32) v);
        control.txfifo.put(v);
    endmethod
    method Action get_spi_rxfifo();
        control.rxfifo_request.put(32'hABBAABBA);
    endmethod

    method Action set_serdes_reset(Bit#(1) v);
        control.set_serdes_reset(v);
    endmethod
    method Action set_serdes_auto_align(Bit#(1) v);
        control.set_serdes_auto_align(v);
    endmethod
    method Action set_serdes_align_start(Bit#(1) v);
        control.set_serdes_align_start(v);
    endmethod
    method Action set_serdes_fifo_enable(Bit#(1) v);
        control.set_serdes_fifo_enable(v);
    endmethod
    method Action set_serdes_manual_tap(Bit#(10) v);
        control.set_serdes_manual_tap(v);
    endmethod
    method Action set_serdes_training(Bit#(10) v);
        control.set_serdes_training(v);
    endmethod
    method Action set_decoder_reset(Bit#(1) v);
        control.set_decoder_reset(v);
    endmethod
    method Action set_decoder_enable(Bit#(1) v);
        control.set_decoder_enable(v);
    endmethod
    method Action set_decoder_code_ls(Bit#(10) v);
        control.set_decoder_code_ls(v);
    endmethod
    method Action set_decoder_code_le(Bit#(10) v);
        control.set_decoder_code_le(v);
    endmethod
    method Action set_decoder_code_fs(Bit#(10) v);
        control.set_decoder_code_fs(v);
    endmethod
    method Action set_decoder_code_fe(Bit#(10) v);
        control.set_decoder_code_fe(v);
    endmethod
    method Action set_decoder_code_bl(Bit#(10) v);
        control.set_decoder_code_bl(v);
    endmethod
    method Action set_decoder_code_img(Bit#(10) v);
        control.set_decoder_code_img(v);
    endmethod
    method Action set_trigger_enable(Bit#(3) v);
        control.set_trigger_enable(v);
    endmethod
    method Action set_trigger_default_freq(Bit#(32) v);
        control.set_trigger_default_freq(v);
    endmethod
    method Action set_trigger_cnt_trigger0high(Bit#(32) v);
        control.set_trigger_cnt_trigger0high(v);
    endmethod
    method Action set_trigger_cnt_trigger0low(Bit#(32) v);
        control.set_trigger_cnt_trigger0low(v);
    endmethod
    method Action set_syncgen_delay(Bit#(16) v);
        control.set_syncgen_delay(v);
    endmethod
    method Action set_syncgen_hactive(Bit#(16) v);
        control.set_syncgen_hactive(v);
    endmethod
    method Action set_syncgen_hfporch(Bit#(16) v);
        control.set_syncgen_hfporch(v);
    endmethod
    method Action set_syncgen_hsync(Bit#(16) v);
        control.set_syncgen_hsync(v);
    endmethod
    method Action set_syncgen_hbporch(Bit#(16) v);
        control.set_syncgen_hbporch(v);
    endmethod
    method Action set_syncgen_vactive(Bit#(16) v);
        control.set_syncgen_vactive(v);
    endmethod
    method Action set_syncgen_vfporch(Bit#(16) v);
        control.set_syncgen_vfporch(v);
    endmethod
    method Action set_syncgen_vsync(Bit#(16) v);
        control.set_syncgen_vsync(v);
    endmethod
    method Action set_syncgen_vbporch(Bit#(16) v);
        control.set_syncgen_vbporch(v);
    endmethod
    method Action set_debugreq(Bit#(32) v);
        control.set_debugreq(v);
    endmethod
    method Action get_debugind();
        //indication.coreIndication.debugind(control.get_debugind());
        indication.coreIndication.debugind(debugind_value);
    endmethod
    method Action put_spi_request(Bit#(26) v);
        spiController.request.put(v);
    endmethod

    endinterface
   interface BlueScopeRequest bsRequest = bsi.requestIfc;
   interface ImageonVita imageon = imageonVita.host;
   interface ImageonSensorData sensor_data = xsviFromSensor.in;
   interface HDMI hdmi = hdmiOut.hdmi;
   interface SpiPins spi = spiController.pins;
endmodule