128-bit pcie_7x core uses tuser[12] to endicate tlp.eof instead of tlast

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2012  Bluespec, Inc.  ALL RIGHTS RESERVED.
////////////////////////////////////////////////////////////////////////////////
//  Filename      : ConnectalXilinx7PCIE.bsv
//  Description   :
////////////////////////////////////////////////////////////////////////////////
package PcieEndpointX7Gen2;

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

import ConnectalClocks   ::*;
import ConnectalXilinxCells   ::*;
import XilinxCells       ::*;
import PCIE              ::*;
import PCIEWRAPPER2      ::*;
import Bufgctrl           ::*;

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

interface PcieEndpointX7#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)   pcie;
   interface PciewrapUser#(lanes)      user;
   interface PciewrapCfg#(lanes)       cfg;
   interface Server#(TLPData#(16), TLPData#(16)) tlp;
   interface Clock epPcieClock;
   interface Reset epPcieReset;
   interface Clock epPortalClock;
   interface Reset epPortalReset;
   interface Clock epDerivedClock;
   interface Reset epDerivedReset;
endinterface

typedef struct {
   Bit#(22)      user;
   Bit#(1)       last;
   Bit#(16)      keep;
   Bit#(128)     data;
} AxiRx deriving (Bits, Eq);

typedef struct {
   Bit#(1)       last;
   Bit#(16)      keep;
   Bit#(128)     data;
} AxiTx deriving (Bits, Eq);

`ifdef Artix7
typedef 4 PcieLanes;
`endif
`ifdef BOARD_zc706
typedef 4 PcieLanes;
`endif
`ifdef BOARD_vc707
typedef 8 PcieLanes;
`endif
`ifdef BOARD_kc705
typedef 8 PcieLanes;
`endif
`ifdef BOARD_vc707g2
typedef 8 PcieLanes;
`endif
`ifdef BOARD_kc705g2
typedef 8 PcieLanes;
`endif
`ifdef BOARD_netfpgasume
typedef 8 PcieLanes;
`endif

(* synthesize *)
module mkPcieEndpointX7(PcieEndpointX7#(PcieLanes));

   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   PcieWrap#(PcieLanes) pcie_ep <- mkPcieWrap(defaultClock, defaultReset);

   Clock user_clk = pcie_ep.user_clk_out;
   Reset user_reset_n <- mkResetInverter(pcie_ep.user_reset_out, clocked_by user_clk);

   FIFOF#(AxiTx)             fAxiTx              <- mkFIFOF(clocked_by user_clk, reset_by user_reset_n);
   FIFOF#(AxiRx)             fAxiRx              <- mkFIFOF(clocked_by user_clk, reset_by user_reset_n);

   (* fire_when_enabled, no_implicit_conditions *)
   rule every1;
      pcie_ep.fc.sel(0 /*RECEIVE_BUFFER_AVAILABLE_SPACE*/);
      pcie_ep.cfg_dsn({ 32'h0000_0001, {{ 8'h1 } , 24'h000A35 }});
      pcie_ep.rx.np_ok(1);
      pcie_ep.rx.np_req(1);
      pcie_ep.tx.cfg_gnt(1);
      pcie_ep.s_axis_tx.tuser(4'b0);
      pcie_ep.m_axis_rx.tready(pack(fAxiRx.notFull));
   endrule
   rule every_cfg_err;
      pcie_ep.cfg_err.acs(0);
      pcie_ep.cfg_err.aer_headerlog(0);
      pcie_ep.cfg_err.atomic_egress_blocked(0);
      pcie_ep.cfg_err.cor(0);
      pcie_ep.cfg_err.cpl_abort(0);
      pcie_ep.cfg_err.cpl_timeout(0);
      pcie_ep.cfg_err.cpl_unexpect(0);
      pcie_ep.cfg_err.ecrc(0);
      pcie_ep.cfg_err.internal_cor(0);
      pcie_ep.cfg_err.internal_uncor(0);
      pcie_ep.cfg_err.locked(0);
      pcie_ep.cfg_err.malformed(0);
      pcie_ep.cfg_err.mc_blocked(0);
      pcie_ep.cfg_err.norecovery(0);
      pcie_ep.cfg_err.poisoned(0);
      pcie_ep.cfg_err.posted(0);
      pcie_ep.cfg_err.tlp_cpl_header(0);
      pcie_ep.cfg_err.ur(0);
   endrule
   rule every_interrupt;
      pcie_ep.cfg_interrupt.zzassert(0);
      pcie_ep.cfg_interrupt.di(0);
      pcie_ep.cfg_interrupt.stat(0);
   endrule
   rule every_mgmt;
      pcie_ep.cfg_mgmt.byte_en(0);
      pcie_ep.cfg_mgmt.di(0);
      pcie_ep.cfg_mgmt.dwaddr(0);
      pcie_ep.cfg_mgmt.rd_en(0);
      pcie_ep.cfg_mgmt.wr_en(0);
      pcie_ep.cfg_mgmt.wr_readonly(0);
   endrule
   rule every_pm;
      pcie_ep.cfg_pm.force_state(0);
      pcie_ep.cfg_pm.force_state_en(0);
      pcie_ep.cfg_pm.halt_aspm_l0s(0);
      pcie_ep.cfg_pm.halt_aspm_l1(0);
      pcie_ep.cfg_pm.send_pme_to(0);
      pcie_ep.cfg_pm.wake(0);
   endrule
   rule every_pl;
      pcie_ep.pl.directed_link_auton(0);
      pcie_ep.pl.directed_link_change(0);
      pcie_ep.pl.directed_link_speed(0);
      pcie_ep.pl.directed_link_width(0);
      pcie_ep.pl.downstream_deemph_source(0);
      pcie_ep.pl.transmit_hot_rst(0);
      pcie_ep.pl.upstream_prefer_deemph(1);
   endrule

   let txready = (pcie_ep.s_axis_tx.tready == 1 && fAxiTx.notEmpty);

   (* fire_when_enabled *)
   rule drive_axi_tx if (txready);
      let info = unpack(0);
      if (fAxiTx.notEmpty) begin
	 info <- toGet(fAxiTx).get();
      end
      pcie_ep.s_axis_tx.tlast(info.last);
      pcie_ep.s_axis_tx.tdata(info.data);
      pcie_ep.s_axis_tx.tkeep(info.keep);
   endrule
   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_txvalid if (fAxiTx.notEmpty);
      pcie_ep.s_axis_tx.tvalid(1);
   endrule
   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_tx2 if (!fAxiTx.notEmpty);
      pcie_ep.s_axis_tx.tvalid(0);
      pcie_ep.s_axis_tx.tlast(0);
      pcie_ep.s_axis_tx.tdata(0);
      pcie_ep.s_axis_tx.tkeep(0);
   endrule

   (* fire_when_enabled *)
   rule sink_axi_rx if (pcie_ep.m_axis_rx.tvalid == 1);
      fAxiRx.enq(AxiRx {user: pcie_ep.m_axis_rx.tuser,
                        last: pcie_ep.m_axis_rx.tlast,
                        keep: pcie_ep.m_axis_rx.tkeep,
                        data: pcie_ep.m_axis_rx.tdata });
   endrule

   Reset user_reset <- mkAsyncReset(4, user_reset_n, user_clk);

   ClockGenerator7Params     clkgenParams = defaultValue;
   clkgenParams.clkin1_period    = 4.000; //  250MHz
   clkgenParams.clkin_buffer     = False;
   clkgenParams.clkfbout_mult_f  = 4.000; // 1000MHz
   clkgenParams.clkout0_divide_f = 4.000; //  250MHz
   clkgenParams.clkout1_divide     = round(mainClockPeriod);
   clkgenParams.clkout1_duty_cycle = 0.5;
   clkgenParams.clkout1_phase      = 0.0000;
   clkgenParams.clkout2_divide     = round(derivedClockPeriod);
   clkgenParams.clkout2_duty_cycle = 0.5;
   clkgenParams.clkout2_phase      = 0.0000;
   ClockGenerator7           clkgen <- mkClockGenerator7(clkgenParams, clocked_by user_clk, reset_by user_reset_n);
   Clock portalClock;
   Reset portalReset;
   if (mainClockPeriod == 4) begin
      portalClock = user_clk;
      portalReset = user_reset_n;
   end
   else begin
      portalClock = clkgen.clkout1;
      portalReset <- mkAsyncReset(4, user_reset_n, portalClock);
   end
   Clock derivedClock = clkgen.clkout2;
   Reset derivedReset <- mkAsyncReset(4, user_reset_n, derivedClock);

   Server#(TLPData#(16), TLPData#(16)) tlp16 = (interface Server;
						interface Put request;
						   method Action put(TLPData#(16) data);
						      fAxiTx.enq(AxiTx {last: pack(data.eof),
									keep: dwordSwap128BE(data.be), data: dwordSwap128(data.data) });
						   endmethod
						endinterface
						interface Get response;
						   method ActionValue#(TLPData#(16)) get();
						      let info <- toGet(fAxiRx).get;
						      TLPData#(16) retval = defaultValue;
						      retval.sof  = (info.user[14] == 1);
						      retval.eof  = (info.user[21] == 1); // 128-bit interface uses tuser bits instead of tlast to indicate EOF
						      retval.hit  = info.user[8:2];
						      retval.be= dwordSwap128BE(info.keep);
						      retval.data = dwordSwap128(info.data);
						      return retval;
						   endmethod
						endinterface
					     endinterface);

   interface tlp = tlp16;
   interface pcie    = pcie_ep.pci_exp;
   interface PciewrapUser user = pcie_ep.user;
   interface PciewrapCfg cfg = pcie_ep.cfg;
   interface Clock epPcieClock = user_clk;
   interface Reset epPcieReset = user_reset_n;
   interface Clock epPortalClock = portalClock;
   interface Reset epPortalReset = portalReset;
   interface Clock epDerivedClock = derivedClock;
   interface Reset epDerivedReset = derivedReset;
endmodule: mkPcieEndpointX7

endpackage: PcieEndpointX7Gen2

////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2012  Bluespec, Inc.  ALL RIGHTS RESERVED.
////////////////////////////////////////////////////////////////////////////////
//  Filename      : ConnectalXilinx7PCIE.bsv
//  Description   :
////////////////////////////////////////////////////////////////////////////////
package PcieEndpointX7Gen2;

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

import ConnectalClocks   ::*;
import ConnectalXilinxCells   ::*;
import XilinxCells       ::*;
import PCIE              ::*;
import PCIEWRAPPER2      ::*;
import Bufgctrl           ::*;

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

interface PcieEndpointX7#(numeric type lanes);
   interface PciewrapPci_exp#(lanes)   pcie;
   interface PciewrapUser#(lanes)      user;
   interface PciewrapCfg#(lanes)       cfg;
   interface Server#(TLPData#(16), TLPData#(16)) tlp;
   interface Clock epPcieClock;
   interface Reset epPcieReset;
   interface Clock epPortalClock;
   interface Reset epPortalReset;
   interface Clock epDerivedClock;
   interface Reset epDerivedReset;
endinterface

typedef struct {
   Bit#(22)      user;
   Bit#(1)       last;
   Bit#(16)      keep;
   Bit#(128)     data;
} AxiRx deriving (Bits, Eq);

typedef struct {
   Bit#(1)       last;
   Bit#(16)      keep;
   Bit#(128)     data;
} AxiTx deriving (Bits, Eq);

`ifdef Artix7
typedef 4 PcieLanes;
`endif
`ifdef BOARD_zc706
typedef 4 PcieLanes;
`endif
`ifdef BOARD_vc707
typedef 8 PcieLanes;
`endif
`ifdef BOARD_kc705
typedef 8 PcieLanes;
`endif
`ifdef BOARD_vc707g2
typedef 8 PcieLanes;
`endif
`ifdef BOARD_kc705g2
typedef 8 PcieLanes;
`endif
`ifdef BOARD_netfpgasume
typedef 8 PcieLanes;
`endif

(* synthesize *)
module mkPcieEndpointX7(PcieEndpointX7#(PcieLanes));

   Clock defaultClock <- exposeCurrentClock();
   Reset defaultReset <- exposeCurrentReset();

   PcieWrap#(PcieLanes) pcie_ep <- mkPcieWrap(defaultClock, defaultReset);

   Clock user_clk = pcie_ep.user_clk_out;
   Reset user_reset_n <- mkResetInverter(pcie_ep.user_reset_out, clocked_by user_clk);

   FIFOF#(AxiTx)             fAxiTx              <- mkFIFOF(clocked_by user_clk, reset_by user_reset_n);
   FIFOF#(AxiRx)             fAxiRx              <- mkFIFOF(clocked_by user_clk, reset_by user_reset_n);

   (* fire_when_enabled, no_implicit_conditions *)
   rule every1;
      pcie_ep.fc.sel(0 /*RECEIVE_BUFFER_AVAILABLE_SPACE*/);
      pcie_ep.cfg_dsn({ 32'h0000_0001, {{ 8'h1 } , 24'h000A35 }});
      pcie_ep.rx.np_ok(1);
      pcie_ep.rx.np_req(1);
      pcie_ep.tx.cfg_gnt(1);
      pcie_ep.s_axis_tx.tuser(4'b0);
      pcie_ep.m_axis_rx.tready(pack(fAxiRx.notFull));
   endrule
   rule every_cfg_err;
      pcie_ep.cfg_err.acs(0);
      pcie_ep.cfg_err.aer_headerlog(0);
      pcie_ep.cfg_err.atomic_egress_blocked(0);
      pcie_ep.cfg_err.cor(0);
      pcie_ep.cfg_err.cpl_abort(0);
      pcie_ep.cfg_err.cpl_timeout(0);
      pcie_ep.cfg_err.cpl_unexpect(0);
      pcie_ep.cfg_err.ecrc(0);
      pcie_ep.cfg_err.internal_cor(0);
      pcie_ep.cfg_err.internal_uncor(0);
      pcie_ep.cfg_err.locked(0);
      pcie_ep.cfg_err.malformed(0);
      pcie_ep.cfg_err.mc_blocked(0);
      pcie_ep.cfg_err.norecovery(0);
      pcie_ep.cfg_err.poisoned(0);
      pcie_ep.cfg_err.posted(0);
      pcie_ep.cfg_err.tlp_cpl_header(0);
      pcie_ep.cfg_err.ur(0);
   endrule
   rule every_interrupt;
      pcie_ep.cfg_interrupt.zzassert(0);
      pcie_ep.cfg_interrupt.di(0);
      pcie_ep.cfg_interrupt.stat(0);
   endrule
   rule every_mgmt;
      pcie_ep.cfg_mgmt.byte_en(0);
      pcie_ep.cfg_mgmt.di(0);
      pcie_ep.cfg_mgmt.dwaddr(0);
      pcie_ep.cfg_mgmt.rd_en(0);
      pcie_ep.cfg_mgmt.wr_en(0);
      pcie_ep.cfg_mgmt.wr_readonly(0);
   endrule
   rule every_pm;
      pcie_ep.cfg_pm.force_state(0);
      pcie_ep.cfg_pm.force_state_en(0);
      pcie_ep.cfg_pm.halt_aspm_l0s(0);
      pcie_ep.cfg_pm.halt_aspm_l1(0);
      pcie_ep.cfg_pm.send_pme_to(0);
      pcie_ep.cfg_pm.wake(0);
   endrule
   rule every_pl;
      pcie_ep.pl.directed_link_auton(0);
      pcie_ep.pl.directed_link_change(0);
      pcie_ep.pl.directed_link_speed(0);
      pcie_ep.pl.directed_link_width(0);
      pcie_ep.pl.downstream_deemph_source(0);
      pcie_ep.pl.transmit_hot_rst(0);
      pcie_ep.pl.upstream_prefer_deemph(1);
   endrule

   let txready = (pcie_ep.s_axis_tx.tready == 1 && fAxiTx.notEmpty);

   (* fire_when_enabled *)
   rule drive_axi_tx if (txready);
      let info = unpack(0);
      if (fAxiTx.notEmpty) begin
	 info <- toGet(fAxiTx).get();
      end
      pcie_ep.s_axis_tx.tlast(info.last);
      pcie_ep.s_axis_tx.tdata(info.data);
      pcie_ep.s_axis_tx.tkeep(info.keep);
   endrule
   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_txvalid if (fAxiTx.notEmpty);
      pcie_ep.s_axis_tx.tvalid(1);
   endrule
   (* fire_when_enabled, no_implicit_conditions *)
   rule drive_axi_tx2 if (!fAxiTx.notEmpty);
      pcie_ep.s_axis_tx.tvalid(0);
      pcie_ep.s_axis_tx.tlast(0);
      pcie_ep.s_axis_tx.tdata(0);
      pcie_ep.s_axis_tx.tkeep(0);
   endrule

   (* fire_when_enabled *)
   rule sink_axi_rx if (pcie_ep.m_axis_rx.tvalid == 1);
      fAxiRx.enq(AxiRx {user: pcie_ep.m_axis_rx.tuser,
                        last: pcie_ep.m_axis_rx.tlast,
                        keep: pcie_ep.m_axis_rx.tkeep,
                        data: pcie_ep.m_axis_rx.tdata });
   endrule

   Reset user_reset <- mkAsyncReset(4, user_reset_n, user_clk);

   ClockGenerator7Params     clkgenParams = defaultValue;
   clkgenParams.clkin1_period    = 4.000; //  250MHz
   clkgenParams.clkin_buffer     = False;
   clkgenParams.clkfbout_mult_f  = 4.000; // 1000MHz
   clkgenParams.clkout0_divide_f = 4.000; //  250MHz
   clkgenParams.clkout1_divide     = round(mainClockPeriod);
   clkgenParams.clkout1_duty_cycle = 0.5;
   clkgenParams.clkout1_phase      = 0.0000;
   clkgenParams.clkout2_divide     = round(derivedClockPeriod);
   clkgenParams.clkout2_duty_cycle = 0.5;
   clkgenParams.clkout2_phase      = 0.0000;
   ClockGenerator7           clkgen <- mkClockGenerator7(clkgenParams, clocked_by user_clk, reset_by user_reset_n);
   Clock portalClock;
   Reset portalReset;
   if (mainClockPeriod == 4) begin
      portalClock = user_clk;
      portalReset = user_reset_n;
   end
   else begin
      portalClock = clkgen.clkout1;
      portalReset <- mkAsyncReset(4, user_reset_n, portalClock);
   end
   Clock derivedClock = clkgen.clkout2;
   Reset derivedReset <- mkAsyncReset(4, user_reset_n, derivedClock);

   Server#(TLPData#(16), TLPData#(16)) tlp16 = (interface Server;
						interface Put request;
						   method Action put(TLPData#(16) data);
						      fAxiTx.enq(AxiTx {last: pack(data.eof),
									keep: dwordSwap128BE(data.be), data: dwordSwap128(data.data) });
						   endmethod
						endinterface
						interface Get response;
						   method ActionValue#(TLPData#(16)) get();
						      let info <- toGet(fAxiRx).get;
						      TLPData#(16) retval = defaultValue;
						      retval.sof  = (info.user[14] == 1);
						      retval.eof  = info.last != 0;
						      retval.hit  = info.user[8:2];
						      retval.be= dwordSwap128BE(info.keep);
						      retval.data = dwordSwap128(info.data);
						      return retval;
						   endmethod
						endinterface
					     endinterface);

   interface tlp = tlp16;
   interface pcie    = pcie_ep.pci_exp;
   interface PciewrapUser user = pcie_ep.user;
   interface PciewrapCfg cfg = pcie_ep.cfg;
   interface Clock epPcieClock = user_clk;
   interface Reset epPcieReset = user_reset_n;
   interface Clock epPortalClock = portalClock;
   interface Reset epPortalReset = portalReset;
   interface Clock epDerivedClock = derivedClock;
   interface Reset epDerivedReset = derivedReset;
endmodule: mkPcieEndpointX7

endpackage: PcieEndpointX7Gen2


[RISCV] Cleanup MemInit*

[RISCV] Cleanup MemInit*

import GetPut::*;

import Types::*;

typedef Data MemResp;

typedef enum{Ld, St} MemOp deriving(Eq, Bits, FShow);
typedef struct{
    MemOp op;
    Addr  addr;
    Data  data;
} MemReq deriving(Eq, Bits, FShow);

typedef 16 NumTokens;
typedef Bit#(TLog#(NumTokens)) Token;

typedef 16 LoadBufferSz;
typedef Bit#(TLog#(LoadBufferSz)) LoadBufferIndex;

typedef struct {
    Addr addr;
    Data data;
} MemInitLoad deriving(Eq, Bits, FShow);

typedef union tagged {
    MemInitLoad InitLoad;
    void InitDone;
} MemInit deriving(Eq, Bits, FShow);

interface MemInitIfc;
    interface Put#(MemInit) request;
    method Bool done();
endinterface


further simplification of mkTLPDispatcher

// Copyright (c) 2008- 2009 Bluespec, Inc.  All rights reserved.
// $Revision$
// $Date$
// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// PCI-Express for Xilinx 7
// FPGAs.

package PcieSplitter;

// This is a package which acts as a bridge between a TLP-based PCIe
// interface on one side and an AXI slave (portal) and AXI Master on
// the other.

import GetPut       :: *;
import Connectable  :: *;
import Vector       :: *;
import FIFO         :: *;
import FIFOF        :: *;
import Counter      :: *;
import PCIE         :: *;
import Clocks       :: *;
import ClientServer :: *;

Integer portConfig = 0;
Integer portPortal = 1;
Integer portAxi    = 2;
typedef 3 PortMax;

// When TLP packets come in from the PCIe bus, they are dispatched to
// either the configuration register block, the portal (AXI slave) or
// the AXI master.
interface TLPDispatcher;
   // TLPs in from PCIe
   interface Put#(TLPData#(16)) inFromBus;
   // TLPs out to the bridge implementation
   interface Vector#(PortMax, Get#(TLPData#(16))) out;
endinterface: TLPDispatcher

typedef function Bool tlpMatchFunction(TLPData#(16) tlp) TlpMatchFunction;

(* synthesize *)
module mkTLPDispatcher(TLPDispatcher);
   FIFO#(TLPData#(16))  tlp_in_fifo     <- mkFIFO();
   Vector#(PortMax, FIFOF#(TLPData#(16))) tlp_out_fifo <- replicateM(mkGFIFOF(True,False)); // unguarded enq
   Reg#(Maybe#(Bit#(TLog#(PortMax)))) routeToPort <- mkReg(tagged Invalid);

   PulseWire is_read       <- mkPulseWire();
   PulseWire is_write      <- mkPulseWire();
   PulseWire is_completion <- mkPulseWire();

   function Bool configMatch(TLPData#(16) tlp);
      TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);
      Bool is_config_read    =  tlp.sof
                             && (tlp.hit == 7'h01)
                             && (hdr_3dw.format == MEM_READ_3DW_NO_DATA)
                             ;
      Bool is_config_write   =  tlp.sof
                             && (tlp.hit == 7'h01)
                             && (hdr_3dw.format == MEM_WRITE_3DW_DATA)
                             && (hdr_3dw.pkttype != COMPLETION)
                             ;
      return is_config_read || is_config_write;
   endfunction

   function Bool axiMatch(TLPData#(16) tlp);
      TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);
      Bool is_axi_read       =  tlp.sof
                             && (tlp.hit == 7'h04)
                             && (hdr_3dw.format == MEM_READ_3DW_NO_DATA)
                             ;
      Bool is_axi_write      =  tlp.sof
                             && (tlp.hit == 7'h04)
                             && (hdr_3dw.format == MEM_WRITE_3DW_DATA)
                             && (hdr_3dw.pkttype != COMPLETION)
                             ;
      return is_axi_read || is_axi_write;
   endfunction

   function Bool axiCompletionMatch(TLPData#(16) tlp);
      TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);
      Bool is_axi_completion =  tlp.sof
                             && (hdr_3dw.format == MEM_WRITE_3DW_DATA)
                             && (hdr_3dw.pkttype == COMPLETION)
                             ;
      return is_axi_completion;
   endfunction

   Vector#(PortMax, TlpMatchFunction) matchFunctions = newVector;
   matchFunctions[portConfig] = configMatch;
   matchFunctions[portPortal] = axiMatch;
   matchFunctions[portAxi]    = axiCompletionMatch;

   (* fire_when_enabled *)
   rule dispatch_incoming_TLP;
      TLPData#(16) tlp = tlp_in_fifo.first();
      TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);

      if (tlp.sof) begin
	 Bool matched = False;
         // route the packet based on this header
	 for (Integer port = 0; port < valueOf(PortMax); port = port+1)
            if (!matched && matchFunctions[port](tlp)) begin
	       matched = True;
               if (tlp_out_fifo[port].notFull()) begin
		  tlp_in_fifo.deq();
		  tlp_out_fifo[port].enq(tlp);
		  if (!tlp.eof)
                     routeToPort <= tagged Valid fromInteger(port);
               end
            end
         if (!matched) begin
            // unknown packet type -- just discard it
            tlp_in_fifo.deq();
         end
         // indicate activity type
         //if (is_config_read)                     is_read.send();
         //if (is_config_write)                    is_write.send();
      end
      else begin
	 if (routeToPort matches tagged Valid .port) begin
            if (tlp_out_fifo[port].notFull()) begin
               tlp_in_fifo.deq();
               tlp_out_fifo[port].enq(tlp);
               if (tlp.eof)
                  routeToPort <= tagged Invalid;
            end
         end
         else begin
            // unknown packet type -- just discard it
            tlp_in_fifo.deq();
         end
      end
   endrule: dispatch_incoming_TLP

   Vector#(PortMax, Get#(TLPData#(16))) outtemp;
   for (Integer i = 0; i < valueOf(PortMax); i=i+1)
       outtemp[i] = toGet(tlp_out_fifo[i]);
   interface out = outtemp;
   interface Put inFromBus    = toPut(tlp_in_fifo);
endmodule: mkTLPDispatcher

// Multiple sources of TLP packets must all share the PCIe bus. There
// is an arbiter which controls which source gets access to the PCIe
// endpoint.

interface TLPArbiter;
   // TLPs out to PCIe
   interface Get#(TLPData#(16)) outToBus;
   // TLPs in from the bridge implementation
   interface Vector#(PortMax, Put#(TLPData#(16))) in;
endinterface: TLPArbiter

(* synthesize *)
module mkTLPArbiter(TLPArbiter);
   FIFO#(TLPData#(16))  tlp_out_fifo     <- mkFIFO();
   Vector#(PortMax, FIFOF#(TLPData#(16))) tlp_in_fifo <- replicateM(mkGFIFOF(False,True)); // unguarded deq
   Vector#(PortMax, Reg#(Bool)) route_from <- replicateM(mkReg(False));

   PulseWire is_read       <- mkPulseWire();
   PulseWire is_write      <- mkPulseWire();
   PulseWire is_completion <- mkPulseWire();

   (* fire_when_enabled *)
   rule arbitrate_outgoing_TLP;
      if (route_from[portConfig]) begin
         // continue taking from the config FIFO until end-of-frame
         if (tlp_in_fifo[portConfig].notEmpty()) begin
            TLPData#(16) tlp = tlp_in_fifo[portConfig].first();
            tlp_in_fifo[portConfig].deq();
            tlp_out_fifo.enq(tlp);
            if (tlp.eof)
               route_from[portConfig] <= False;
         end
      end
      else if (route_from[portPortal]) begin
         // continue taking from the portal FIFO until end-of-frame
         if (tlp_in_fifo[portPortal].notEmpty()) begin
            TLPData#(16) tlp = tlp_in_fifo[portPortal].first();
            tlp_in_fifo[portPortal].deq();
            tlp_out_fifo.enq(tlp);
            if (tlp.eof)
               route_from[portPortal] <= False;
         end
      end
      else if (route_from[portAxi]) begin
         // continue taking from the axi FIFO until end-of-frame
         if (tlp_in_fifo[portAxi].notEmpty()) begin
            TLPData#(16) tlp = tlp_in_fifo[portAxi].first();
            tlp_in_fifo[portAxi].deq();
            tlp_out_fifo.enq(tlp);
            if (tlp.eof)
               route_from[portAxi] <= False;
         end
      end
      else if (tlp_in_fifo[portConfig].notEmpty()) begin
         // prioritize config read completions over portal traffic
         TLPData#(16) tlp = tlp_in_fifo[portConfig].first();
         tlp_in_fifo[portConfig].deq();
         if (tlp.sof) begin
            tlp_out_fifo.enq(tlp);
            if (!tlp.eof)
               route_from[portConfig] <= True;
            is_completion.send();
         end
      end
      else if (tlp_in_fifo[portPortal].notEmpty()) begin
         // prioritize portal read completions over AXI master traffic
         TLPData#(16) tlp = tlp_in_fifo[portPortal].first();
         tlp_in_fifo[portPortal].deq();
         if (tlp.sof) begin
            tlp_out_fifo.enq(tlp);
            if (!tlp.eof)
               route_from[portPortal] <= True;
            is_completion.send();
         end
      end
      else if (tlp_in_fifo[portAxi].notEmpty()) begin
         TLPData#(16) tlp = tlp_in_fifo[portAxi].first();
         tlp_in_fifo[portAxi].deq();
         if (tlp.sof) begin
            tlp_out_fifo.enq(tlp);
            if (!tlp.eof)
               route_from[portAxi] <= True;
            is_completion.send();
         end
      end
   endrule: arbitrate_outgoing_TLP

   Vector#(PortMax, Put#(TLPData#(16))) intemp;
   for (Integer i = 0; i < valueOf(PortMax); i=i+1)
       intemp[i] = toPut(tlp_in_fifo[i]);
   interface in = intemp;
   interface Get outToBus     = toGet(tlp_out_fifo);
endmodule
endpackage: PcieSplitter

// Copyright (c) 2008- 2009 Bluespec, Inc.  All rights reserved.
// $Revision$
// $Date$
// Copyright (c) 2013 Quanta Research Cambridge, Inc.

// PCI-Express for Xilinx 7
// FPGAs.

package PcieSplitter;

// This is a package which acts as a bridge between a TLP-based PCIe
// interface on one side and an AXI slave (portal) and AXI Master on
// the other.

import GetPut       :: *;
import Connectable  :: *;
import Vector       :: *;
import FIFO         :: *;
import FIFOF        :: *;
import Counter      :: *;
import PCIE         :: *;
import Clocks       :: *;
import ClientServer :: *;

Integer portConfig = 0;
Integer portPortal = 1;
Integer portAxi    = 2;
typedef 3 PortMax;

// When TLP packets come in from the PCIe bus, they are dispatched to
// either the configuration register block, the portal (AXI slave) or
// the AXI master.
interface TLPDispatcher;
   // TLPs in from PCIe
   interface Put#(TLPData#(16)) inFromBus;
   // TLPs out to the bridge implementation
   interface Vector#(PortMax, Get#(TLPData#(16))) out;
endinterface: TLPDispatcher

(* synthesize *)
module mkTLPDispatcher(TLPDispatcher);
   FIFO#(TLPData#(16))  tlp_in_fifo     <- mkFIFO();
   Vector#(PortMax, FIFOF#(TLPData#(16))) tlp_out_fifo <- replicateM(mkGFIFOF(True,False)); // unguarded enq
   Vector#(PortMax, Reg#(Bool)) route_to <- replicateM(mkReg(False));

   PulseWire is_read       <- mkPulseWire();
   PulseWire is_write      <- mkPulseWire();
   PulseWire is_completion <- mkPulseWire();

   (* fire_when_enabled *)
   rule dispatch_incoming_TLP;
      TLPData#(16) tlp = tlp_in_fifo.first();
      TLPMemoryIO3DWHeader hdr_3dw = unpack(tlp.data);
      Bool is_config_read    =  tlp.sof
                             && (tlp.hit == 7'h01)
                             && (hdr_3dw.format == MEM_READ_3DW_NO_DATA)
                             ;
      Bool is_config_write   =  tlp.sof
                             && (tlp.hit == 7'h01)
                             && (hdr_3dw.format == MEM_WRITE_3DW_DATA)
                             && (hdr_3dw.pkttype != COMPLETION)
                             ;
      Bool is_axi_read       =  tlp.sof
                             && (tlp.hit == 7'h04)
                             && (hdr_3dw.format == MEM_READ_3DW_NO_DATA)
                             ;
      Bool is_axi_write      =  tlp.sof
                             && (tlp.hit == 7'h04)
                             && (hdr_3dw.format == MEM_WRITE_3DW_DATA)
                             && (hdr_3dw.pkttype != COMPLETION)
                             ;
      Bool is_axi_completion =  tlp.sof
                             && (hdr_3dw.format == MEM_WRITE_3DW_DATA)
                             && (hdr_3dw.pkttype == COMPLETION)
                             ;
      if (tlp.sof) begin
         // route the packet based on this header
         if (is_config_read || is_config_write) begin
            // send to config interface if it will accept
            if (tlp_out_fifo[portConfig].notFull()) begin
               tlp_in_fifo.deq();
               tlp_out_fifo[portConfig].enq(tlp);
               if (!tlp.eof)
                  route_to[portConfig] <= True;
            end
         end
         else if (is_axi_read || is_axi_write) begin
            // send to portal interface if it will accept
            if (tlp_out_fifo[portPortal].notFull()) begin
               tlp_in_fifo.deq();
               tlp_out_fifo[portPortal].enq(tlp);
               if (!tlp.eof)
                  route_to[portPortal] <= True;
            end
         end
	 else if (is_axi_completion) begin
            // send to AXI interface if it will accept
            if (tlp_out_fifo[portAxi].notFull()) begin
               tlp_in_fifo.deq();
               tlp_out_fifo[portAxi].enq(tlp);
               if (!tlp.eof)
                  route_to[portAxi] <= True;
            end
	 end
         else begin
            // unknown packet type -- just discard it
            tlp_in_fifo.deq();
         end
         // indicate activity type
         if (is_config_read)                     is_read.send();
         if (is_config_write)                    is_write.send();
      end
      else begin
         // this is a continuation of a previous TLP packet, so route
         // based on the last header
         if (route_to[portConfig]) begin
            // send to config interface if it will accept
            if (tlp_out_fifo[portConfig].notFull()) begin
               tlp_in_fifo.deq();
               tlp_out_fifo[portConfig].enq(tlp);
               if (tlp.eof)
                  route_to[portConfig] <= False;
            end
         end
         else if (route_to[portPortal]) begin
            // send to portal interface if it will accept
            if (tlp_out_fifo[portPortal].notFull()) begin
               tlp_in_fifo.deq();
               tlp_out_fifo[portPortal].enq(tlp);
               if (tlp.eof)
                  route_to[portPortal] <= False;
            end
         end
         else if (route_to[portAxi]) begin
            // send to AXI interface if it will accept
            if (tlp_out_fifo[portAxi].notFull()) begin
               tlp_in_fifo.deq();
               tlp_out_fifo[portAxi].enq(tlp);
               if (tlp.eof)
                  route_to[portAxi] <= False;
            end
         end
         else begin
            // unknown packet type -- just discard it
            tlp_in_fifo.deq();
         end
      end
   endrule: dispatch_incoming_TLP

   Vector#(PortMax, Get#(TLPData#(16))) outtemp;
   for (Integer i = 0; i < valueOf(PortMax); i=i+1)
       outtemp[i] = toGet(tlp_out_fifo[i]);
   interface out = outtemp;
   interface Put inFromBus    = toPut(tlp_in_fifo);
endmodule: mkTLPDispatcher

// Multiple sources of TLP packets must all share the PCIe bus. There
// is an arbiter which controls which source gets access to the PCIe
// endpoint.

interface TLPArbiter;
   // TLPs out to PCIe
   interface Get#(TLPData#(16)) outToBus;
   // TLPs in from the bridge implementation
   interface Vector#(PortMax, Put#(TLPData#(16))) in;
endinterface: TLPArbiter

(* synthesize *)
module mkTLPArbiter(TLPArbiter);
   FIFO#(TLPData#(16))  tlp_out_fifo     <- mkFIFO();
   Vector#(PortMax, FIFOF#(TLPData#(16))) tlp_in_fifo <- replicateM(mkGFIFOF(False,True)); // unguarded deq
   Vector#(PortMax, Reg#(Bool)) route_from <- replicateM(mkReg(False));

   PulseWire is_read       <- mkPulseWire();
   PulseWire is_write      <- mkPulseWire();
   PulseWire is_completion <- mkPulseWire();

   (* fire_when_enabled *)
   rule arbitrate_outgoing_TLP;
      if (route_from[portConfig]) begin
         // continue taking from the config FIFO until end-of-frame
         if (tlp_in_fifo[portConfig].notEmpty()) begin
            TLPData#(16) tlp = tlp_in_fifo[portConfig].first();
            tlp_in_fifo[portConfig].deq();
            tlp_out_fifo.enq(tlp);
            if (tlp.eof)
               route_from[portConfig] <= False;
         end
      end
      else if (route_from[portPortal]) begin
         // continue taking from the portal FIFO until end-of-frame
         if (tlp_in_fifo[portPortal].notEmpty()) begin
            TLPData#(16) tlp = tlp_in_fifo[portPortal].first();
            tlp_in_fifo[portPortal].deq();
            tlp_out_fifo.enq(tlp);
            if (tlp.eof)
               route_from[portPortal] <= False;
         end
      end
      else if (route_from[portAxi]) begin
         // continue taking from the axi FIFO until end-of-frame
         if (tlp_in_fifo[portAxi].notEmpty()) begin
            TLPData#(16) tlp = tlp_in_fifo[portAxi].first();
            tlp_in_fifo[portAxi].deq();
            tlp_out_fifo.enq(tlp);
            if (tlp.eof)
               route_from[portAxi] <= False;
         end
      end
      else if (tlp_in_fifo[portConfig].notEmpty()) begin
         // prioritize config read completions over portal traffic
         TLPData#(16) tlp = tlp_in_fifo[portConfig].first();
         tlp_in_fifo[portConfig].deq();
         if (tlp.sof) begin
            tlp_out_fifo.enq(tlp);
            if (!tlp.eof)
               route_from[portConfig] <= True;
            is_completion.send();
         end
      end
      else if (tlp_in_fifo[portPortal].notEmpty()) begin
         // prioritize portal read completions over AXI master traffic
         TLPData#(16) tlp = tlp_in_fifo[portPortal].first();
         tlp_in_fifo[portPortal].deq();
         if (tlp.sof) begin
            tlp_out_fifo.enq(tlp);
            if (!tlp.eof)
               route_from[portPortal] <= True;
            is_completion.send();
         end
      end
      else if (tlp_in_fifo[portAxi].notEmpty()) begin
         TLPData#(16) tlp = tlp_in_fifo[portAxi].first();
         tlp_in_fifo[portAxi].deq();
         if (tlp.sof) begin
            tlp_out_fifo.enq(tlp);
            if (!tlp.eof)
               route_from[portAxi] <= True;
            is_completion.send();
         end
      end
   endrule: arbitrate_outgoing_TLP

   Vector#(PortMax, Put#(TLPData#(16))) intemp;
   for (Integer i = 0; i < valueOf(PortMax); i=i+1)
       intemp[i] = toPut(tlp_in_fifo[i]);
   interface in = intemp;
   interface Get outToBus     = toGet(tlp_out_fifo);
endmodule
endpackage: PcieSplitter


add newline at the end of the file

add newline at the end of the file

// 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 Complex::*;
import FixedPoint::*;
import Pipe::*;

typedef FixedPoint#(2,16) Signal;
typedef FixedPoint#(2,23) Coeff;
typedef FixedPoint#(4,39) Product;

typedef struct {
		Complex#(Coeff) a;
		Bit#(1) filterPhase;
		} CoeffData;

typedef struct {
		Complex#(Product) y;
		Bit#(1) filterPhase;
		} ProductData;

interface FPCMult;
   interface PipeIn#(Complex#(Signal)) x;
   interface PipeIn#(CoeffData) a;
   interface PipeOut#(ProductData) y;
endinterface

module mkFPCMult(FPCMult);
   /* input registers */
   Reg#(Complex#(Signal)) xin <- mkReg(?);
   Reg#(CoeffData) ain <- mkReg(?);
   /* pipeline registers at output of multipliers */
   Reg#(Product) arxr <- mkReg(?);
   Reg#(Product) aixi <- mkReg(?);
   Reg#(Product) arxi <- mkReg(?);
   Reg#(Product) aixr <- mkReg(?);
   Reg#(Bit#(1)) multstage <- mkReg(?);
   /* result registers */
   Reg#(ProductData) yout <- mkReg(?);

   rule work;
      /* compute multiplies */
      arxr <= fxptMult(ain.a.r, xin.r);
      aixi <= fxptMult(ain.a.i, xin.i);
      arxi <= fxptMult(ain.a.r, xin.i);
      aixr <= fxptMult(ain.a.i, xin.r);
      multFilterPhase <= ain.filterPhase;
      /* combine into outputs */
      yout <= ProductData{y: Complex{r: arxr - aixi, i: arxi + aixr}, filterPhase: multstage};
   endrule

   interface PipeOut y = toPipeOut(yout);
   interface PipeIn x;
      method Action enq(Complex#(Signal) v);
         xin <= v;
      endmethod
      method Bool notFull();
         return (True);
      endmethod
   endinterface
   interface PipeIn a;
      method Action enq(CoeffData v);
         ain <= v;
      endmethod
      method Bool notFull();
         return (True);
      endmethod
   endinterface

endmodule;


fix field names of complex

fix field names of complex

// 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 DDS::*;
import FixedPoint::*;
import Complex::*;
import Pipe::*;
import DDSTestInterfaces::*;

module mkDDSTestRequest#(DDSTestIndication indication) (DDSTestRequest);
   DDS dds <- mkDDS();

   method Action setPhaseAdvance(Bit#(32) i, Bit#(32) f);
    dds.setPhaseAdvance(PhaseType{i: truncate(i), f: truncate(f)});
      indication.setConfigResp();
   endmethod

   method Action getData();
      PhaseType p = dds.getPhase();
      DDSOutType d = dds.osc.first();
      indication.ddsData(zeroExtend(p.i), zeroExtend(pack(d.rel)), zeroExtend(pack(d.img)));
   endmethod
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 DDS::*;
import FixedPoint::*;
import Complex::*;
import Pipe::*;
import DDSTestInterfaces::*;

module mkDDSTestRequest#(DDSTestIndication indication) (DDSTestRequest);
   DDS dds <- mkDDS();

   method Action setPhaseAdvance(Bit#(32) i, Bit#(32) f);
    dds.setPhaseAdvance(PhaseType{i: truncate(i), f: truncate(f)});
      indication.setConfigResp();
   endmethod

   method Action getData();
      PhaseType p = dds.getPhase();
      DDSOutType d = dds.osc.first();
      indication.ddsData(zeroExtend(p.i), zeroExtend(pack(d.re)), zeroExtend(pack(d.im)));
   endmethod
endmodule


Use empty and full from all subfifos in mkDualClockBramFIFOF

This fixes a clock domain crossing bug when mkDualClockBramFIFOF is
wider than 36 bits wide.

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

import Clocks::*;
import Vector::*;
import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import CBus::*; // extendNP and truncateNP

`include "ConnectalProjectConfig.bsv"
import Arith::*;
import ConnectalClocks::*;

`ifdef SIMULATION
`ifdef BOARD_xsim
`define USE_XILINX_MACRO
`endif // xsim
`else // not SIMULATION
`ifdef XILINX
`define USE_XILINX_MACRO
`endif // XILINX
`endif // not SIMULATION

`ifdef USE_XILINX_MACRO
(* always_ready, always_enabled *)
interface X7FifoSyncMacro#(numeric type data_width);
   method Bit#(1) empty();
   method Bit#(1) full();
   method Action din(Bit#(data_width) v);
   method Action wren(Bit#(1) wren);
   method Bit#(data_width) dout();
   method Action rden(Bit#(1) rden);
   method Bit#(9) wrcount();
   method Bit#(9) rdcount();
endinterface

import "BVI" FIFO_DUALCLOCK_MACRO =
module  vmkBramFifo#(String fifo_size, Clock wrClock, Reset wrReset, Clock rdClock, Reset rdReset)(X7FifoSyncMacro#(data_width));
`ifndef BSV_POSITIVE_RESET
   let rdReset1 <- mkSyncReset(10, rdReset, wrClock);
   let eitherReset <- mkResetEither(wrReset, rdReset1, clocked_by wrClock);
   let positiveReset <- mkPositiveReset(10, eitherReset, wrClock);
   let fifoReset = positiveReset.positiveReset;
`else
   let fifoReset = wrReset;
`endif
`ifdef XilinxUltrascale
   parameter DEVICE = "ULTRASCALE";
`else
   parameter DEVICE = "7SERIES";
`endif
   parameter DATA_WIDTH = valueOf(data_width);
   parameter FIFO_SIZE = fifo_size;
`ifndef SIMULATION
   parameter FIRST_WORD_FALL_THROUGH = "TRUE"; // not supported by xsim
`else
   parameter FIRST_WORD_FALL_THROUGH = True;
`endif
   default_clock wrClock(WRCLK) = wrClock;
   no_reset;
   input_reset wrReset(RST) = fifoReset;
   input_clock rdClock(RDCLK) = rdClock;
   method EMPTY empty() clocked_by (rdClock) reset_by (wrReset);
   method FULL full() clocked_by (wrClock) reset_by (wrReset);
   method din(DI) enable ((*inhigh*)EN_di) clocked_by (wrClock) reset_by (wrReset);
   method wren(WREN) enable ((*inhigh*)EN_wren) clocked_by (wrClock) reset_by (wrReset);
   method DO dout() clocked_by (rdClock) reset_by (wrReset);
   method rden(RDEN) enable ((*inhigh*)EN_rden) clocked_by (rdClock) reset_by (wrReset);
   // wrcount and rdcount ports are needed for xsim
   method WRCOUNT wrcount() clocked_by (wrClock) reset_by (wrReset);
   method RDCOUNT rdcount() clocked_by (rdClock) reset_by (wrReset);
   schedule (empty, full, dout, din, wren, rden, wrcount, rdcount) CF (empty, full, dout, din, wren, rden, wrcount, rdcount);
endmodule

module mkDualClockBramFIFOF#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   String fifo_size = "18Kb";
   Vector#(TDiv#(sizet,36),X7FifoSyncMacro#(36)) fifos <- replicateM(vmkBramFifo(fifo_size, srcClock, srcReset, dstClock, dstReset));
   Wire#(Bit#(1)) rdenWire <- mkDWire(0, clocked_by dstClock, reset_by dstReset);
   Wire#(Bit#(1)) wrenWire <- mkDWire(0, clocked_by srcClock, reset_by srcReset);
   Vector#(TDiv#(sizet,36),Wire#(Bit#(36))) dinWires <- replicateM(mkDWire(0, clocked_by srcClock, reset_by srcReset));

   for (Integer i = 0; i < valueOf(TDiv#(sizet,36)); i = i+1) begin
      Reg#(Bit#(9)) rdcount <- mkReg(0, clocked_by dstClock, reset_by dstReset);
      Reg#(Bit#(9)) wrcount <- mkReg(0, clocked_by srcClock, reset_by srcReset);
      rule rdenRule;
	 fifos[i].rden(rdenWire);
      endrule
      rule wrenRule;
	 fifos[i].wren(wrenWire);
      endrule
      rule inputs;
	 fifos[i].din(dinWires[i]);
      endrule
      rule countrds;
	 rdcount <= fifos[i].rdcount();
      endrule
      rule countwrs;
	 wrcount <= fifos[i].wrcount();
      endrule
   end

   function Bool fifoNotEmpty(X7FifoSyncMacro#(36) f); return f.empty == 0; endfunction
   function Bool fifoNotFull(X7FifoSyncMacro#(36) f); return f.full == 0; endfunction

   method t first() if (all(fifoNotEmpty, fifos));
      function Bit#(36) fifoFirst(Integer i); return fifos[i].dout(); endfunction
      Vector#(TDiv#(sizet,36), Bit#(36)) v = genWith(fifoFirst);
      return unpack(truncateNP(pack(v)));
   endmethod
   method Action deq() if (all(fifoNotEmpty, fifos));
      rdenWire <= 1;
   endmethod
   method notEmpty = all(fifoNotEmpty, fifos);
   method Action enq(t v) if (all(fifoNotFull, fifos));
      Vector#(TDiv#(sizet,36), Bit#(36)) vs = unpack(extendNP(pack(v)));
      Vector#(TDiv#(sizet,36), Integer) indices = genVector();
      function Action fifoEnq(Integer i); action dinWires[i] <= vs[i]; endaction endfunction
      mapM_(fifoEnq, indices);
      wrenWire <= 1;
   endmethod
   method notFull = all(fifoNotEmpty, fifos);
endmodule

module mkDualClockBramFIFO#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFO#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));

   let syncFifo <- mkDualClockBramFIFOF(srcClock, srcReset, dstClock, dstReset);
   method enq = syncFifo.enq;
   method deq = syncFifo.deq;
   method first = syncFifo.first;
endmodule

`else // compatibility mode
module mkDualClockBramFIFOF#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let syncFifo <- mkSyncFIFO(512, srcClock, srcReset, dstClock);
   method enq = syncFifo.enq;
   method deq = syncFifo.deq;
   method first = syncFifo.first;
   method notFull = syncFifo.notFull;
   method notEmpty = syncFifo.notEmpty;
endmodule
module mkDualClockBramFIFO#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFO#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));

   let syncFifo <- mkSyncFIFO(512, srcClock, srcReset, dstClock);
   method enq = syncFifo.enq;
   method deq = syncFifo.deq;
   method first = syncFifo.first;
endmodule
`endif

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

import Clocks::*;
import Vector::*;
import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import CBus::*; // extendNP and truncateNP

`include "ConnectalProjectConfig.bsv"
import Arith::*;
import ConnectalClocks::*;

`ifdef SIMULATION
`ifdef BOARD_xsim
`define USE_XILINX_MACRO
`endif // xsim
`else // not SIMULATION
`ifdef XILINX
`define USE_XILINX_MACRO
`endif // XILINX
`endif // not SIMULATION

`ifdef USE_XILINX_MACRO
(* always_ready, always_enabled *)
interface X7FifoSyncMacro#(numeric type data_width);
   method Bit#(1) empty();
   method Bit#(1) full();
   method Action din(Bit#(data_width) v);
   method Action wren(Bit#(1) wren);
   method Bit#(data_width) dout();
   method Action rden(Bit#(1) rden);
   method Bit#(9) wrcount();
   method Bit#(9) rdcount();
endinterface

import "BVI" FIFO_DUALCLOCK_MACRO =
module  vmkBramFifo#(String fifo_size, Clock wrClock, Reset wrReset, Clock rdClock, Reset rdReset)(X7FifoSyncMacro#(data_width));
`ifndef BSV_POSITIVE_RESET
   let rdReset1 <- mkSyncReset(10, rdReset, wrClock);
   let eitherReset <- mkResetEither(wrReset, rdReset1, clocked_by wrClock);
   let positiveReset <- mkPositiveReset(10, eitherReset, wrClock);
   let fifoReset = positiveReset.positiveReset;
`else
   let fifoReset = wrReset;
`endif
`ifdef XilinxUltrascale
   parameter DEVICE = "ULTRASCALE";
`else
   parameter DEVICE = "7SERIES";
`endif
   parameter DATA_WIDTH = valueOf(data_width);
   parameter FIFO_SIZE = fifo_size;
`ifndef SIMULATION
   parameter FIRST_WORD_FALL_THROUGH = "TRUE"; // not supported by xsim
`else
   parameter FIRST_WORD_FALL_THROUGH = True;
`endif
   default_clock wrClock(WRCLK) = wrClock;
   no_reset;
   input_reset wrReset(RST) = fifoReset;
   input_clock rdClock(RDCLK) = rdClock;
   method EMPTY empty() clocked_by (rdClock) reset_by (wrReset);
   method FULL full() clocked_by (wrClock) reset_by (wrReset);
   method din(DI) enable ((*inhigh*)EN_di) clocked_by (wrClock) reset_by (wrReset);
   method wren(WREN) enable ((*inhigh*)EN_wren) clocked_by (wrClock) reset_by (wrReset);
   method DO dout() clocked_by (rdClock) reset_by (wrReset);
   method rden(RDEN) enable ((*inhigh*)EN_rden) clocked_by (rdClock) reset_by (wrReset);
   // wrcount and rdcount ports are needed for xsim
   method WRCOUNT wrcount() clocked_by (wrClock) reset_by (wrReset);
   method RDCOUNT rdcount() clocked_by (rdClock) reset_by (wrReset);
   schedule (empty, full, dout, din, wren, rden, wrcount, rdcount) CF (empty, full, dout, din, wren, rden, wrcount, rdcount);
endmodule

module mkDualClockBramFIFOF#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   String fifo_size = "18Kb";
   Vector#(TDiv#(sizet,36),X7FifoSyncMacro#(36)) fifos <- replicateM(vmkBramFifo(fifo_size, srcClock, srcReset, dstClock, dstReset));
   Wire#(Bit#(1)) rdenWire <- mkDWire(0, clocked_by dstClock, reset_by dstReset);
   Wire#(Bit#(1)) wrenWire <- mkDWire(0, clocked_by srcClock, reset_by srcReset);
   Vector#(TDiv#(sizet,36),Wire#(Bit#(36))) dinWires <- replicateM(mkDWire(0, clocked_by srcClock, reset_by srcReset));

   for (Integer i = 0; i < valueOf(TDiv#(sizet,36)); i = i+1) begin
      Reg#(Bit#(9)) rdcount <- mkReg(0, clocked_by dstClock, reset_by dstReset);
      Reg#(Bit#(9)) wrcount <- mkReg(0, clocked_by srcClock, reset_by srcReset);
      rule rdenRule;
	 fifos[i].rden(rdenWire);
      endrule
      rule wrenRule;
	 fifos[i].wren(wrenWire);
      endrule
      rule inputs;
	 fifos[i].din(dinWires[i]);
      endrule
      rule countrds;
	 rdcount <= fifos[i].rdcount();
      endrule
      rule countwrs;
	 wrcount <= fifos[i].wrcount();
      endrule
   end

   method t first() if (fifos[0].empty == 0);
      function Bit#(36) fifoFirst(Integer i); return fifos[i].dout(); endfunction
      Vector#(TDiv#(sizet,36), Bit#(36)) v = genWith(fifoFirst);
      return unpack(truncateNP(pack(v)));
   endmethod
   method Action deq() if (fifos[0].empty == 0);
      rdenWire <= 1;
   endmethod
   method notEmpty = (fifos[0].empty == 0);
   method Action enq(t v) if (fifos[0].full == 0);
      Vector#(TDiv#(sizet,36), Bit#(36)) vs = unpack(extendNP(pack(v)));
      Vector#(TDiv#(sizet,36), Integer) indices = genVector();
      function Action fifoEnq(Integer i); action dinWires[i] <= vs[i]; endaction endfunction
      mapM_(fifoEnq, indices);
      wrenWire <= 1;
   endmethod
   method notFull = (fifos[0].full == 0);
endmodule

module mkDualClockBramFIFO#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFO#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));

   let syncFifo <- mkDualClockBramFIFOF(srcClock, srcReset, dstClock, dstReset);
   method enq = syncFifo.enq;
   method deq = syncFifo.deq;
   method first = syncFifo.first;
endmodule

`else // compatibility mode
module mkDualClockBramFIFOF#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFOF#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));
   let syncFifo <- mkSyncFIFO(512, srcClock, srcReset, dstClock);
   method enq = syncFifo.enq;
   method deq = syncFifo.deq;
   method first = syncFifo.first;
   method notFull = syncFifo.notFull;
   method notEmpty = syncFifo.notEmpty;
endmodule
module mkDualClockBramFIFO#(Clock srcClock, Reset srcReset, Clock dstClock, Reset dstReset)(FIFO#(t))
   provisos (Bits#(t,sizet),
	     Add#(1,a__,sizet));

   let syncFifo <- mkSyncFIFO(512, srcClock, srcReset, dstClock);
   method enq = syncFifo.enq;
   method deq = syncFifo.deq;
   method first = syncFifo.first;
endmodule
`endif


eliminated debug freq counter

eliminated debug freq counter

Change-Id: I5ad71594d2921725b36cb078d6e2808d11a885d9

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

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

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

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

import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import GetPut::*;
import ClientServer::*;
import PCIE::*;
import GetPutWithClocks::*;
import Connectable::*;
import PortalMemory::*;
import MemTypes::*;
import DmaUtils::*;
import ClientServer::*;
import AxiMasterSlave::*;
import MemreadEngine::*;
import HDMI::*;
import XADC::*;
import YUV::*;
import Gearbox::*;
import MIMO::*;
import BlueScope::*;

interface HdmiDisplayRequest;
   method Action startFrameBuffer(Int#(32) base, UInt#(32) rows, UInt#(32) cols, UInt#(32) pixels);
   method Action stopFrameBuffer();
   method Action getTransferStats();
   method Action setTraceTransfers(Bit#(1) trace);
endinterface
interface HdmiDisplayIndication;
   method Action transferStarted(Bit#(32) count);
   method Action transferFinished(Bit#(32) count);
   method Action transferStats(Bit#(32) count, Bit#(32) transferCycles, Bit#(64) sumOfCycles);
endinterface

interface HdmiDisplay;
   interface BlueScopeRequest  bluescopeRequest;
    interface HdmiDisplayRequest displayRequest;
    interface HdmiInternalRequest internalRequest;
    interface ObjectReadClient#(64) dmaClient;
   interface ObjectWriteClient#(64) bluescopeWriteClient;
    interface HDMI#(Bit#(HdmiBits)) hdmi;
    interface XADC xadc;
endinterface

module mkHdmiDisplay#(Clock hdmi_clock,
		      HdmiDisplayIndication hdmiDisplayIndication,
		      HdmiInternalIndication hdmiInternalIndication,
		      BlueScopeIndication bluescopeIndication)(HdmiDisplay);
    Clock defaultClock <- exposeCurrentClock;
    Reset defaultReset <- exposeCurrentReset;
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);

   Reg#(UInt#(16)) rowsReg <- mkReg(1080);
   Reg#(UInt#(16)) colsReg <- mkReg(1920);
   Reg#(UInt#(24)) pixelCountReg <- mkReg(1080*1920);

    Reg#(Bool) sendVsyncIndication <- mkReg(False);
    SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, defaultClock);
    Reg#(Bit#(1)) bozobit <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);

    Reg#(Maybe#(Bit#(32))) referenceReg <- mkReg(tagged Invalid);
    FIFO#(Bit#(64)) mrFifo <- mkSizedBRAMFIFO(1024);
    MemreadEngine#(64,16) memreadEngine <- mkMemreadEngine;

    HdmiGenerator#(Rgb888) hdmiGen <- mkHdmiGenerator(defaultClock, defaultReset,
							vsyncPulse, hdmiInternalIndication, clocked_by hdmi_clock, reset_by hdmi_reset);
`ifndef ZC706
   Rgb888ToYyuv converter <- mkRgb888ToYyuv(clocked_by hdmi_clock, reset_by hdmi_reset);
   mkConnection(hdmiGen.rgb888, converter.rgb888);
   HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(converter.yyuv, clocked_by hdmi_clock, reset_by hdmi_reset);
`else
   HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(hdmiGen.rgb888, clocked_by hdmi_clock, reset_by hdmi_reset);
`endif
   let bluescope <- mkSyncBlueScope(65536, bluescopeIndication, hdmi_clock, hdmi_reset, defaultClock, defaultReset);
   //Gearbox#(1, 16, Bit#(4)) gearbox <- mk1toNGearbox(hdmi_clock, hdmi_reset, hdmi_clock, hdmi_reset);
   MIMO#(1, 16, 64, Bit#(4)) mimo <- mkMIMO(MIMOConfiguration { unguarded: False, bram_based: False }, clocked_by hdmi_clock, reset_by hdmi_reset);
   Reg#(Bool) triggered <- mkReg(False, clocked_by hdmi_clock, reset_by hdmi_reset);
   rule toGearbox if ((hdmisignals.hdmi_vsync == 1) || triggered);
      Bit#(4) v = 0;
      v[0] = hdmisignals.hdmi_vsync;
      v[1] = hdmisignals.hdmi_de;
      v[2] = hdmisignals.hdmi_hsync;
      v[3] = hdmisignals.hdmi_vsync;
      triggered <= True;
      if (mimo.enqReadyN(1))
	 mimo.enq(1, cons(v,nil));
      else
	 $display("mimo.stalled mimo.count=%d", mimo.count);
   endrule
   rule gearboxToBlueScope if (mimo.deqReadyN(16));
      Bit#(64) v = pack(mimo.first());
      mimo.deq(16);
      bluescope.dataIn(v, v);
   endrule

   SyncFIFOIfc#(Bit#(64)) synchronizer <- mkSyncFIFO(32, defaultClock, defaultReset, hdmi_clock);
   rule fromMemread;
      let v <- toGet(memreadEngine.dataPipes[0]).get;
      mrFifo.enq(v);
   endrule
   rule toSynch;
      let v <- toGet(mrFifo).get();
      synchronizer.enq(v);
   endrule
   Reg#(Bit#(1)) evenOdd <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
   Reg#(Vector#(2,Bit#(32))) doublePixelReg <- mkReg(unpack(0), clocked_by hdmi_clock, reset_by hdmi_reset);
   rule doPut;
      Vector#(2,Bit#(32)) doublePixel = doublePixelReg;
      let pixel = doublePixel[evenOdd];
      if (evenOdd == 0) begin
	 doublePixel = unpack(synchronizer.first);
	 synchronizer.deq;
	 pixel = doublePixel[0];
      end
      doublePixelReg <= doublePixel;
      evenOdd <= evenOdd + 1;
      hdmiGen.request.put(pixel);
   endrule

   Reg#(Bit#(32)) transferCount <- mkReg(0);
   Reg#(Bit#(32)) transferCyclesSnapshot <- mkReg(0);
   Reg#(Bit#(32)) transferCycles <- mkReg(0);
   Reg#(Bit#(48)) transferSumOfCycles<- mkReg(0);
   Reg#(Bit#(32)) vsyncCount <- mkReg(0);

   FIFOF#(Bool) vsyncFifo <- mkFIFOF();
   rule vsyncrule if (vsyncPulse.pulse());
      vsyncCount <= vsyncCount + 1;
      if (vsyncFifo.notFull())
	 vsyncFifo.enq(True);
   endrule

   Reg#(Bool) traceTransfers <- mkReg(False);
   rule notransfer if (referenceReg matches tagged Invalid);
      vsyncFifo.deq();
   endrule
   rule startTransfer if (referenceReg matches tagged Valid .reference);
      memreadEngine.readServers[0].request.put(MemengineCmd{pointer:reference, base:0, len:pack(extend(pixelCountReg))*4, burstLen:64});
      if (traceTransfers)
	 hdmiDisplayIndication.transferStarted(transferCount);
      transferCyclesSnapshot <= transferCycles;
      vsyncFifo.deq();
   endrule
   rule countCycles;
      transferCycles <= transferCycles + 1;
   endrule
   rule finishTransferRule;
      let b <- memreadEngine.readServers[0].response.get;
      transferCount <= transferCount + 1;
      let tc = transferCycles - transferCyclesSnapshot;
      transferSumOfCycles <= transferSumOfCycles + extend(tc);
      if (traceTransfers)
	 hdmiDisplayIndication.transferFinished(transferCount);
   endrule

    rule bozobit_rule;
        bozobit <= ~bozobit;
    endrule

    interface HdmiDisplayRequest displayRequest;
	method Action startFrameBuffer(Int#(32) base, UInt#(32) rows, UInt#(32) cols, UInt#(32) pixels);
	   rowsReg <= truncate(rows);
	   colsReg <= truncate(cols);
	   pixelCountReg <= truncate(pixels);
	   $display("startFrameBuffer %h", base);
           referenceReg <= tagged Valid truncate(pack(base));
	   hdmiGen.control.setTestPattern(0);
	endmethod
       method Action stopFrameBuffer();
	  referenceReg <= tagged Invalid;
	  hdmiGen.control.setTestPattern(1);
       endmethod
       method Action getTransferStats();
          hdmiDisplayIndication.transferStats(transferCount, transferCycles-transferCyclesSnapshot, extend(transferSumOfCycles));
       endmethod
       method Action setTraceTransfers(Bit#(1) trace);
	  traceTransfers <= unpack(trace);
       endmethod
    endinterface: displayRequest

    interface ObjectReadClient dmaClient = memreadEngine.dmaClient;
    interface HDMI hdmi = hdmisignals;
    interface HdmiInternalRequest internalRequest = hdmiGen.control;
    interface BlueScopeRequest bluescopeRequest = bluescope.requestIfc;
    interface ObjectWriteClient bluescopeWriteClient = bluescope.writeClient;
    interface XADC xadc;
        method Bit#(4) gpio;
            return { bozobit, hdmisignals.hdmi_vsync,
                hdmisignals.hdmi_data[8], hdmisignals.hdmi_data[0]};
                //hdmiGen.hdmi.hsync, hdmi_de};
        endmethod
    endinterface: xadc
endmodule

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

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

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

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

import FIFO::*;
import FIFOF::*;
import BRAMFIFO::*;
import Vector::*;
import Clocks::*;
import GetPut::*;
import ClientServer::*;
import PCIE::*;
import GetPutWithClocks::*;
import Connectable::*;
import PortalMemory::*;
import MemTypes::*;
import DmaUtils::*;
import ClientServer::*;
import AxiMasterSlave::*;
import MemreadEngine::*;
import HDMI::*;
import XADC::*;
import YUV::*;
import FrequencyCounter::*;
import Gearbox::*;
import MIMO::*;
import BlueScope::*;

interface HdmiDisplayRequest;
   method Action startFrameBuffer(Int#(32) base, UInt#(32) rows, UInt#(32) cols, UInt#(32) pixels);
   method Action stopFrameBuffer();
   method Action getTransferStats();
   method Action setTraceTransfers(Bit#(1) trace);
   method Action fcStart(Bit#(32) fclk0_cycles);
endinterface
interface HdmiDisplayIndication;
   method Action transferStarted(Bit#(32) count);
   method Action transferFinished(Bit#(32) count);
   method Action transferStats(Bit#(32) count, Bit#(32) transferCycles, Bit#(64) sumOfCycles);
   method Action fcElapsedCycles(Bit#(32) elapsedCycles);
endinterface

interface HdmiDisplay;
   interface BlueScopeRequest  bluescopeRequest;
    interface HdmiDisplayRequest displayRequest;
    interface HdmiInternalRequest internalRequest;
    interface ObjectReadClient#(64) dmaClient;
   interface ObjectWriteClient#(64) bluescopeWriteClient;
    interface HDMI#(Bit#(HdmiBits)) hdmi;
    interface XADC xadc;
endinterface

module mkHdmiDisplay#(Clock hdmi_clock,
		      HdmiDisplayIndication hdmiDisplayIndication,
		      HdmiInternalIndication hdmiInternalIndication,
		      BlueScopeIndication bluescopeIndication)(HdmiDisplay);
    Clock defaultClock <- exposeCurrentClock;
    Reset defaultReset <- exposeCurrentReset;
    Reset hdmi_reset <- mkAsyncReset(2, defaultReset, hdmi_clock);

   Reg#(UInt#(16)) rowsReg <- mkReg(1080);
   Reg#(UInt#(16)) colsReg <- mkReg(1920);
   Reg#(UInt#(24)) pixelCountReg <- mkReg(1080*1920);

    Reg#(Bool) sendVsyncIndication <- mkReg(False);
    SyncPulseIfc vsyncPulse <- mkSyncHandshake(hdmi_clock, hdmi_reset, defaultClock);
    Reg#(Bit#(1)) bozobit <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);

    Reg#(Maybe#(Bit#(32))) referenceReg <- mkReg(tagged Invalid);
    FIFO#(Bit#(64)) mrFifo <- mkSizedBRAMFIFO(1024);
    MemreadEngine#(64,16) memreadEngine <- mkMemreadEngine;

    HdmiGenerator#(Rgb888) hdmiGen <- mkHdmiGenerator(defaultClock, defaultReset,
							vsyncPulse, hdmiInternalIndication, clocked_by hdmi_clock, reset_by hdmi_reset);
`ifndef ZC706
   Rgb888ToYyuv converter <- mkRgb888ToYyuv(clocked_by hdmi_clock, reset_by hdmi_reset);
   mkConnection(hdmiGen.rgb888, converter.rgb888);
   HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(converter.yyuv, clocked_by hdmi_clock, reset_by hdmi_reset);
`else
   HDMI#(Bit#(HdmiBits)) hdmisignals <- mkHDMI(hdmiGen.rgb888, clocked_by hdmi_clock, reset_by hdmi_reset);
`endif
   let freqCounter <- mkFrequencyCounter(hdmi_clock, hdmi_reset);
   let bluescope <- mkSyncBlueScope(65536, bluescopeIndication, hdmi_clock, hdmi_reset, defaultClock, defaultReset);
   //Gearbox#(1, 16, Bit#(4)) gearbox <- mk1toNGearbox(hdmi_clock, hdmi_reset, hdmi_clock, hdmi_reset);
   MIMO#(1, 16, 64, Bit#(4)) mimo <- mkMIMO(MIMOConfiguration { unguarded: False, bram_based: False }, clocked_by hdmi_clock, reset_by hdmi_reset);
   Reg#(Bool) triggered <- mkReg(False, clocked_by hdmi_clock, reset_by hdmi_reset);
   rule toGearbox if ((hdmisignals.hdmi_vsync == 1) || triggered);
      Bit#(4) v = 0;
      v[0] = hdmisignals.hdmi_vsync;
      v[1] = hdmisignals.hdmi_de;
      v[2] = hdmisignals.hdmi_hsync;
      v[3] = hdmisignals.hdmi_vsync;
      triggered <= True;
      if (mimo.enqReadyN(1))
	 mimo.enq(1, cons(v,nil));
      else
	 $display("mimo.stalled mimo.count=%d", mimo.count);
   endrule
   rule gearboxToBlueScope if (mimo.deqReadyN(16));
      Bit#(64) v = pack(mimo.first());
      mimo.deq(16);
      bluescope.dataIn(v, v);
   endrule

   SyncFIFOIfc#(Bit#(64)) synchronizer <- mkSyncFIFO(32, defaultClock, defaultReset, hdmi_clock);
   rule fromMemread;
      let v <- toGet(memreadEngine.dataPipes[0]).get;
      mrFifo.enq(v);
   endrule
   rule toSynch;
      let v <- toGet(mrFifo).get();
      synchronizer.enq(v);
   endrule
   Reg#(Bit#(1)) evenOdd <- mkReg(0, clocked_by hdmi_clock, reset_by hdmi_reset);
   Reg#(Vector#(2,Bit#(32))) doublePixelReg <- mkReg(unpack(0), clocked_by hdmi_clock, reset_by hdmi_reset);
   rule doPut;
      Vector#(2,Bit#(32)) doublePixel = doublePixelReg;
      let pixel = doublePixel[evenOdd];
      if (evenOdd == 0) begin
	 doublePixel = unpack(synchronizer.first);
	 synchronizer.deq;
	 pixel = doublePixel[0];
      end
      doublePixelReg <= doublePixel;
      evenOdd <= evenOdd + 1;
      hdmiGen.request.put(pixel);
   endrule

   Reg#(Bit#(32)) transferCount <- mkReg(0);
   Reg#(Bit#(32)) transferCyclesSnapshot <- mkReg(0);
   Reg#(Bit#(32)) transferCycles <- mkReg(0);
   Reg#(Bit#(48)) transferSumOfCycles<- mkReg(0);
   Reg#(Bit#(32)) vsyncCount <- mkReg(0);

   FIFOF#(Bool) vsyncFifo <- mkFIFOF();
   rule vsyncrule if (vsyncPulse.pulse());
      vsyncCount <= vsyncCount + 1;
      if (vsyncFifo.notFull())
	 vsyncFifo.enq(True);
   endrule

   Reg#(Bool) traceTransfers <- mkReg(False);
   rule notransfer if (referenceReg matches tagged Invalid);
      vsyncFifo.deq();
   endrule
   rule startTransfer if (referenceReg matches tagged Valid .reference);
      memreadEngine.readServers[0].request.put(MemengineCmd{pointer:reference, base:0, len:pack(extend(pixelCountReg))*4, burstLen:64});
      if (traceTransfers)
	 hdmiDisplayIndication.transferStarted(transferCount);
      transferCyclesSnapshot <= transferCycles;
      vsyncFifo.deq();
   endrule
   rule countCycles;
      transferCycles <= transferCycles + 1;
   endrule
   rule finishTransferRule;
      let b <- memreadEngine.readServers[0].response.get;
      transferCount <= transferCount + 1;
      let tc = transferCycles - transferCyclesSnapshot;
      transferSumOfCycles <= transferSumOfCycles + extend(tc);
      if (traceTransfers)
	 hdmiDisplayIndication.transferFinished(transferCount);
   endrule

    rule bozobit_rule;
        bozobit <= ~bozobit;
    endrule
   rule fc;
      let ec <- freqCounter.elapsedCycles();
      hdmiDisplayIndication.fcElapsedCycles(ec);
   endrule

    interface HdmiDisplayRequest displayRequest;
	method Action startFrameBuffer(Int#(32) base, UInt#(32) rows, UInt#(32) cols, UInt#(32) pixels);
	   rowsReg <= truncate(rows);
	   colsReg <= truncate(cols);
	   pixelCountReg <= truncate(pixels);
	   $display("startFrameBuffer %h", base);
           referenceReg <= tagged Valid truncate(pack(base));
	   hdmiGen.control.setTestPattern(0);
	endmethod
       method Action stopFrameBuffer();
	  referenceReg <= tagged Invalid;
	  hdmiGen.control.setTestPattern(1);
       endmethod
       method Action getTransferStats();
          hdmiDisplayIndication.transferStats(transferCount, transferCycles-transferCyclesSnapshot, extend(transferSumOfCycles));
       endmethod
       method Action setTraceTransfers(Bit#(1) trace);
	  traceTransfers <= unpack(trace);
       endmethod
       method Action fcStart(Bit#(32) fclk0_cycles);
	  freqCounter.start(fclk0_cycles);
       endmethod
    endinterface: displayRequest

    interface ObjectReadClient dmaClient = memreadEngine.dmaClient;
    interface HDMI hdmi = hdmisignals;
    interface HdmiInternalRequest internalRequest = hdmiGen.control;
    interface BlueScopeRequest bluescopeRequest = bluescope.requestIfc;
    interface ObjectWriteClient bluescopeWriteClient = bluescope.writeClient;
    interface XADC xadc;
        method Bit#(4) gpio;
            return { bozobit, hdmisignals.hdmi_vsync,
                hdmisignals.hdmi_data[8], hdmisignals.hdmi_data[0]};
                //hdmiGen.hdmi.hsync, hdmi_de};
        endmethod
    endinterface: xadc
endmodule