incremental step to moving mkClockGenerator7Adv to XbsvXilinx7Pcie.bsv


syntax error in GenB2C

syntax error in GenB2C

// 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 Clocks       :: *;
import DefaultValue :: *;
import XilinxCells  :: *;
import Vector       :: *;

import "BVI" IBUFDS =
module mkIBUFDS#(Wire#(one_bit) i, Wire#(one_bit) ib)(ReadOnly#(one_bit)) provisos(Bits#(one_bit,1));
   default_clock clk();
   default_reset rstn();

   parameter CAPACITANCE = "DONT_CARE";
   parameter DIFF_TERM = 1;
   parameter IBUF_DELAY_VALUE = 0;
   parameter IFD_DELAY_VALUE = "AUTO";
   parameter IOSTANDARD = "DEFAULT";

   port I = i;
   port IB = ib;
   method O    _read;

   path(I, O);
   path(IB, O);

   schedule _read  CF _read;

endmodule: mkIBUFDS

import "BVI" IBUFDS =
module vMkClockIBUFDS#(Wire#(one_bit) i, Wire#(one_bit) ib)(ClockGenIfc) provisos(Bits#(one_bit,1));
   default_clock clk();
   default_reset rstn();
   parameter CAPACITANCE = "DONT_CARE";
   parameter DIFF_TERM = 1;
   parameter IBUF_DELAY_VALUE = 0;
   parameter IFD_DELAY_VALUE = "AUTO";
   parameter IOSTANDARD = "DEFAULT";
   port I = i;
   port IB = ib;
   //method O    _read;
   output_clock gen_clk(O);
   path(I, O);
   path(IB, O);
   //schedule _read  CF _read;
endmodule: vMkClockIBUFDS

module mkClockIBUFDS#(Wire#(one_bit) i, Wire#(one_bit) ib)(Clock) provisos(Bits#(one_bit,1));
   let _m <- vMkClockIBUFDS(i, ib);
   return _m.gen_clk;
endmodule: mkClockIBUFDS

import "BVI" OBUFT =
module mkOBUFT#(Wire#(one_bit) i, Wire#(one_bit) t)(ReadOnly#(one_bit)) provisos(Bits#(one_bit,1));
   default_clock clk();
   default_reset rstn();

   port I = i;
   port T = t;
   method O    _read;

   path(I, O);
   path(T, O);

   schedule _read  CF _read;

endmodule: mkOBUFT

typedef struct {
   String cinvctrl_sel;           // "TRUE" to enable dynamic clock inversion, "FALSE" otherwise
   String delay_src;              // "IDATAIN" or "DATAIN"
   String high_performance_mode;  // "TRUE" to reduce jitter, "FALSE" to reduce power
   String idelay_type;            // "FIXED", "VAR_LOAD", or "VAR_LOAD_PIPE"
   Integer idelay_value;          // 0-31 input delay tap setting
   String pipe_sel;               // "TRUE" to select pipelined mode
   Integer refclk_frequency;      // idelayctrl clock input freq in MHz
   String signal_pattern;         // "DATA" or "CLOCK" input signal
}  IDELAYE2_Config;

instance DefaultValue#(IDELAYE2_Config);
   defaultValue =
   IDELAYE2_Config {
      cinvctrl_sel: "FALSE",
      delay_src: "IDATAIN",
      high_performance_mode: "FALSE",
      idelay_type: "FIXED",
      idelay_value: 0,
      pipe_sel: "FALSE",
      refclk_frequency: 200,
      signal_pattern: "DATA"
      };
endinstance

(* always_ready, always_enabled *)
interface IdelayE2;
   method Bit#(5) cntvalueout();
   method Action cinvctrl(Bit#(1) v);
   method Action cntvaluein(Bit#(5) v);
   method Action ld(Bit#(1) v);
   method Action ldpipeen(Bit#(1) v);
   method Action inc(Bool inc);
   method Action ce(Bit#(1) v);
   method Action datain(Bit#(1) v);
   method Action idatain(Bit#(1) v);
   method Action reset(Bit#(1) v);
   method Bit#(1) dataout();
endinterface

import "BVI" IDELAYE2 =
module mkIDELAYE2#(IDELAYE2_Config cfg, Clock serdes_clock)(IdelayE2);
   default_clock clk(C);
   //default_reset rst(REGRST);
   no_reset;
   input_clock serdes ()= serdes_clock;

   parameter CINVCTRL_SEL = cfg.cinvctrl_sel;
   parameter DELAY_SRC = cfg.delay_src;
   parameter HIGH_PERFORMANCE_MODE = cfg.high_performance_mode;
   parameter IDELAY_TYPE = cfg.idelay_type;
   parameter IDELAY_VALUE = cfg.idelay_value;
   parameter PIPE_SEL = cfg.pipe_sel;
   parameter REFCLK_FREQUENCY = cfg.refclk_frequency;
   parameter SIGNAL_PATTERN = cfg.signal_pattern;

   method CNTVALUEOUT cntvalueout();
   method cinvctrl(CINVCTRL) enable((*inhigh*) en0);
   method cntvaluein(CNTVALUEIN) enable((*inhigh*) en1);

   method ld(LD) enable((*inhigh*) en20);

   // is LDPIPEEN the enable for DATAIN?
   method ldpipeen(LDPIPEEN) enable((*inhigh*) en21);

   method DATAOUT dataout();
   method inc(INC) enable((*inhigh*) en5);
   method ce(CE) enable((*inhigh*) en4);
   method reset(REGRST) enable((*inhigh*) en7);
   method datain(DATAIN) enable((*inhigh*) en2);
   method idatain(IDATAIN) enable((*inhigh*) en3) clocked_by(serdes);

   schedule (datain, idatain, inc, ce) CF (datain, idatain, inc, ce);
   schedule (reset, cntvalueout, dataout, ld, datain, ldpipeen, inc, cinvctrl, cntvaluein, ce, idatain) CF (reset, cntvalueout, dataout, ld, datain, ldpipeen, inc, cinvctrl, cntvaluein, ce, idatain);
endmodule

////////////////////////////////////////////////////////////
typedef struct {
   String data_rate;
   Integer data_width;
   String dyn_clk_inv_en;
   String dyn_clkdiv_inv_en;
   Integer init_q1;
   Integer init_q2;
   Integer init_q3;
   Integer init_q4;
   String interface_type;
   String iobdelay;
   Integer num_ce;
   String ofb_used;
   String serdes_mode;
   Integer srval_q1;
   Integer srval_q2;
   Integer srval_q3;
   Integer srval_q4;
}  ISERDESE2_Config;

instance DefaultValue#(ISERDESE2_Config);
   defaultValue =
   ISERDESE2_Config {
      data_rate: "DDR",
      data_width: 8,
      dyn_clk_inv_en: "FALSE",
      dyn_clkdiv_inv_en: "FALSE",
      init_q1: 0,
      init_q2: 0,
      init_q3: 0,
      init_q4: 0,
      interface_type: "NETWORKING",
      iobdelay: "IBUF",
      num_ce: 1,
      ofb_used: "FALSE",
      serdes_mode: "MASTER",
      srval_q1: 0,
      srval_q2: 0,
      srval_q3: 0,
      srval_q4: 0
      };
endinstance

(* always_ready, always_enabled *)
interface IserdesE2;
   (* prefix = "" *)
   method Action d(Bit#(1) d);
   method Bit#(1) o();
   method Action bitslip(Bit#(1) bitslip);
   method Action ce1(Bit#(1) ce1);
   method Action ce2(Bit#(1) ce2);
   method Action ddly(Bit#(1) ddly);
   method Action shiftin1(Bit#(1) shiftin1);
   method Action shiftin2(Bit#(1) shiftin2);
   method Bit#(1) q1();
   method Bit#(1) q2();
   method Bit#(1) q3();
   method Bit#(1) q4();
   method Bit#(1) q5();
   method Bit#(1) q6();
   method Bit#(1) q7();
   method Bit#(1) q8();
   method Bit#(1) shiftout1();
   method Bit#(1) shiftout2();
   method Action ofb(Bit#(1) ofb);
   method Action dynclkdivsel(Bit#(1) dynclkdivsel);
   method Action dynclksel(Bit#(1) dynclksel);
   method Action oclk(Bit#(1) v);
   method Action oclkb(Bit#(1) v);
   method Action reset(Bit#(1) d);
endinterface

import "BVI" ISERDESE2 =
module mkISERDESE2#(ISERDESE2_Config cfg, Clock clk, Clock clkb)(IserdesE2);
   input_clock clk(CLK) = clk;
   input_clock clkb(CLKB) = clkb;
   default_clock clkdiv(CLKDIV);
   no_reset;

   parameter DATA_RATE = cfg.data_rate;
   parameter DATA_WIDTH = cfg.data_width;
   parameter DYN_CLK_INV_EN = cfg.dyn_clk_inv_en;
   parameter DYN_CLKDIV_INV_EN = cfg.dyn_clkdiv_inv_en;
   parameter INIT_Q1 = cfg.init_q1;
   parameter INIT_Q2 = cfg.init_q2;
   parameter INIT_Q3 = cfg.init_q3;
   parameter INIT_Q4 = cfg.init_q4;
   parameter INTERFACE_TYPE = cfg.interface_type;
   parameter IOBDELAY = cfg.iobdelay;
   parameter NUM_CE = cfg.num_ce;
   parameter OFB_USED = cfg.ofb_used;
   parameter SERDES_MODE = cfg.serdes_mode;
   parameter SRVAL_Q1 = cfg.srval_q1;
   parameter SRVAL_Q2 = cfg.srval_q2;
   parameter SRVAL_Q3 = cfg.srval_q3;
   parameter SRVAL_Q4 = cfg.srval_q4;

   port CLKDIVP = 0; // unused
   path (D, O);

   method d(D) enable ((*inhigh*) en0);
   method O o();
   method bitslip(BITSLIP) enable ((*inhigh*)enbitslip);
   method ce1(CE1) enable ((*inhigh*) en1);
   method ce2(CE2) enable ((*inhigh*) en2);
   method ddly(DDLY) enable ((*inhigh*) en3);
   method shiftin1(SHIFTIN1) enable ((*inhigh*) en4);
   method shiftin2(SHIFTIN2) enable ((*inhigh*) en5);
   method Q1 q1();
   method Q2 q2();
   method Q3 q3();
   method Q4 q4();
   method Q5 q5();
   method Q6 q6();
   method Q7 q7();
   method Q8 q8();
   method SHIFTOUT1 shiftout1();
   method SHIFTOUT2 shiftout2();
   method ofb(OFB) enable ((*inhigh*) en6);
   method oclk(OCLK) enable ((*inhigh*) en10);
   method oclkb(OCLKB) enable ((*inhigh*) en11);
   method dynclkdivsel(DYNCLKDIVSEL) enable ((*inhigh*) en7);
   method dynclksel(DYNCLKSEL) enable ((*inhigh*) en8);
   method reset(RST) enable ((*inhigh*) en14);

   schedule (reset, o, q1, q2, q3, q4, q5, q6, q7, q8, shiftout1, shiftout2, d, bitslip, ce1, ce2, ddly, shiftin1, shiftin2, ofb, dynclkdivsel, dynclksel, oclk, oclkb)
         CF (reset, o, q1, q2, q3, q4, q5, q6, q7, q8, shiftout1, shiftout2, d, bitslip, ce1, ce2, ddly, shiftin1, shiftin2, ofb, dynclkdivsel, dynclksel, oclk, oclkb);
endmodule

import "BVI" BUFR =
module mkBUFR5#(Clock clk)(ClockGenIfc);
   default_clock clkunused();
   default_reset rstn();

   parameter BUFR_DIVIDE = "5";

   input_clock clk(I) = clk;
   output_clock gen_clk(O);
   port   CE = True;
   port   CLR = False;
   path(I, O);
endmodule

import "BVI" BUFIO =
module mkBUFIO#(Clock clk)(ClockGenIfc);
   default_clock clkunused();
   default_reset rstn();
   input_clock clk(I) = clk;
   output_clock gen_clk(O);
   path(I, O);
endmodule

interface XbsvMMCME2;
   interface Clock     clkout0;
   interface Clock     clkout1;
   interface Clock     clkfbout;
   (* always_ready, always_enabled *)
   method    Bool      locked;
   (* always_enabled *)
   method    Action    clkfbin(Bit#(1) v);
endinterface

typedef struct {
   String      bandwidth;
   String      compensation;
   Real        clkfbout_mult_f;
   Real        clkfbout_phase;
   Real        clkin1_period;
   Real        clkin2_period;
   Integer     divclk_divide;
   Real        clkout0_divide_f;
   Real        clkout0_duty_cycle;
   Real        clkout0_phase;
   Integer     clkout1_divide;
   Real        clkout1_duty_cycle;
   Real        clkout1_phase;
   Real        ref_jitter1;
   Real        ref_jitter2;
} XbsvMMCMParams deriving (Bits, Eq);

import "BVI" MMCM_ADV =
module mkXbsvMMCM#(XbsvMMCMParams params)(XbsvMMCME2);
   //Reset reset <- exposeCurrentReset;
   //default_reset rst() = reset;
   no_reset;
   default_clock clk1(CLKIN1);
   parameter BANDWIDTH            = params.bandwidth;
   parameter COMPENSATION         = params.compensation;
   parameter CLKFBOUT_MULT_F      = params.clkfbout_mult_f;
   parameter CLKFBOUT_PHASE       = params.clkfbout_phase;
   parameter CLKIN1_PERIOD        = params.clkin1_period;
   parameter CLKIN2_PERIOD        = params.clkin2_period;
   parameter DIVCLK_DIVIDE        = params.divclk_divide;
   parameter CLKOUT0_DIVIDE_F     = params.clkout0_divide_f;
   parameter CLKOUT0_DUTY_CYCLE   = params.clkout0_duty_cycle;
   parameter CLKOUT0_PHASE        = params.clkout0_phase;
   parameter CLKOUT1_DIVIDE       = params.clkout1_divide;
   parameter CLKOUT1_DUTY_CYCLE   = params.clkout1_duty_cycle;
   parameter CLKOUT1_PHASE        = params.clkout1_phase;
   parameter REF_JITTER1          = params.ref_jitter1;
   parameter REF_JITTER2          = params.ref_jitter2;
   port CLKIN2       = Bit#(1)'(0);
   port CLKINSEL     = Bit#(1)'(1);
   port DADDR        = Bit#(7)'(0);
   port DCLK         = Bit#(1)'(0);
   port DEN          = Bit#(1)'(0);
   port DI           = Bit#(16)'(0);
   port DWE          = Bit#(1)'(0);
   port PSCLK        = Bit#(1)'(0);
   port PSEN         = Bit#(1)'(0);
   port PSINCDEC     = Bit#(1)'(0);
   port PWRDWN       = Bit#(1)'(0);
   output_clock clkfbout(CLKFBOUT);
   output_clock clkout0(CLKOUT0);
   output_clock clkout1(CLKOUT1);
   method LOCKED     locked()     clocked_by(no_clock) reset_by(no_reset);
   method            clkfbin(CLKFBIN) enable((*inhigh*)en1);
   schedule clkfbin C clkfbin;
   schedule locked CF (clkfbin, locked);
endmodule

(* always_ready, always_enabled *)
interface XbsvODDR#(type a);
   method    a            q();
   method    Action       s(Bool i);
   method    Action       ce(Bool i);
   method    Action       d1(a i);
   method    Action       d2(a i);
endinterface: XbsvODDR

import "BVI" ODDR =
module mkXbsvODDR#(ODDRParams#(a) params)(XbsvODDR#(a))
   provisos(Bits#(a, 1), DefaultValue#(a));

   if (params.srtype != "SYNC" &&
       params.srtype != "ASYNC")
      error("There are only two modes of reset of the ODDR cell SYNC and ASYNC.  Please specify one of those.");

   if (params.ddr_clk_edge != "OPPOSITE_EDGE" &&
       params.ddr_clk_edge != "SAME_EDGE")
      error("There are only two modes of operation of the ODDR cell OPPOSITE_EDGE and SAME_EDGE.  Please specify one of those.");

   no_reset;
   default_clock clk(C);
   //default_reset rst(R);
   port R = 0;

   parameter DDR_CLK_EDGE = params.ddr_clk_edge;
   parameter INIT         = pack(params.init);
   parameter SRTYPE       = params.srtype;

   method Q   q reset_by(no_reset);
   method     s(S)     enable((*inhigh*)en0) reset_by(no_reset);
   method     ce(CE)   enable((*inhigh*)en1) reset_by(no_reset);
   method     d1(D1)   enable((*inhigh*)en2) reset_by(no_reset);
   method     d2(D2)   enable((*inhigh*)en3) reset_by(no_reset);

   schedule (q)      SB (d1, d2);
   schedule (d1)     CF (d2);
   schedule (d1)     C  (d1);
   schedule (d2)     C  (d2);
   schedule (q)      CF (q);
   schedule (ce, s)  CF (ce, s);
   schedule (ce, s)  SB (d1, d2, q);
endmodule: mkXbsvODDR

interface MMCMHACK;
    interface XbsvMMCME2 mmcmadv;
endinterface

module mkMMCMHACK(MMCMHACK);
    XbsvMMCME2 mm <- mkXbsvMMCM(XbsvMMCMParams {
        bandwidth:"OPTIMIZED", compensation:"ZHOLD",
        clkfbout_mult_f:8.000, clkfbout_phase:0.0,
        clkin1_period:6.734007, clkin2_period:6.734007,
        clkout0_divide_f:8.000, clkout0_duty_cycle:0.5, clkout0_phase:0.0000,
        clkout1_divide:32, clkout1_duty_cycle:0.5, clkout1_phase:0.0000,
        divclk_divide:1, ref_jitter1:0.010, ref_jitter2:0.010
        });
    interface XbsvMMCME2 mmcmadv = mm;
endmodule

////////////////////////////////////////////////////////////

(* always_ready, always_enabled *)
interface IbufdsTest;
   (* prefix="" *)
   method Action in(Bit#(1) i, Bit#(1) ib);
   interface ReadOnly#(Bit#(1)) o;
endinterface

module mkIbufdsTest(IbufdsTest);
   Wire#(Bit#(1)) i_w <- mkDWire(0);
   Wire#(Bit#(1)) ib_w <- mkDWire(0);
   ReadOnly#(Bit#(1)) ibufds <- mkIBUFDS(i_w, ib_w);

   method Action in(Bit#(1) i, Bit#(1) ib);
       i_w <= i;
       ib_w <= ib;
   endmethod
   interface ReadOnly o = ibufds;
endmodule

(* always_ready, always_enabled *)
interface BIBUF#(numeric type sa);
    interface Inout#(Bit#(sa))     pad;
endinterface
import "BVI" GenBIBUF =
module mkBIBUF#(Inout#(a) v)(BIBUF#(sa)) provisos(Bits#(a, sa));
    let sa = fromInteger(valueOf(sa));
    parameter SIZE=sa;
    default_clock clk();
    default_reset rst();
    inout IO = v;
    ifc_inout pad(PAD);
endmodule

(* always_ready, always_enabled *)
interface B2C;
    interface Clock c;
endinterface
import "BVI" GenB2C =
module mkB2C#(Bit#(1) v)(B2C);
    default_clock no_clock;
    default_reset no_reset;
    output_clock c();
    port B = v;
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 Clocks       :: *;
import DefaultValue :: *;
import XilinxCells  :: *;
import Vector       :: *;

import "BVI" IBUFDS =
module mkIBUFDS#(Wire#(one_bit) i, Wire#(one_bit) ib)(ReadOnly#(one_bit)) provisos(Bits#(one_bit,1));
   default_clock clk();
   default_reset rstn();

   parameter CAPACITANCE = "DONT_CARE";
   parameter DIFF_TERM = 1;
   parameter IBUF_DELAY_VALUE = 0;
   parameter IFD_DELAY_VALUE = "AUTO";
   parameter IOSTANDARD = "DEFAULT";

   port I = i;
   port IB = ib;
   method O    _read;

   path(I, O);
   path(IB, O);

   schedule _read  CF _read;

endmodule: mkIBUFDS

import "BVI" IBUFDS =
module vMkClockIBUFDS#(Wire#(one_bit) i, Wire#(one_bit) ib)(ClockGenIfc) provisos(Bits#(one_bit,1));
   default_clock clk();
   default_reset rstn();
   parameter CAPACITANCE = "DONT_CARE";
   parameter DIFF_TERM = 1;
   parameter IBUF_DELAY_VALUE = 0;
   parameter IFD_DELAY_VALUE = "AUTO";
   parameter IOSTANDARD = "DEFAULT";
   port I = i;
   port IB = ib;
   //method O    _read;
   output_clock gen_clk(O);
   path(I, O);
   path(IB, O);
   //schedule _read  CF _read;
endmodule: vMkClockIBUFDS

module mkClockIBUFDS#(Wire#(one_bit) i, Wire#(one_bit) ib)(Clock) provisos(Bits#(one_bit,1));
   let _m <- vMkClockIBUFDS(i, ib);
   return _m.gen_clk;
endmodule: mkClockIBUFDS

import "BVI" OBUFT =
module mkOBUFT#(Wire#(one_bit) i, Wire#(one_bit) t)(ReadOnly#(one_bit)) provisos(Bits#(one_bit,1));
   default_clock clk();
   default_reset rstn();

   port I = i;
   port T = t;
   method O    _read;

   path(I, O);
   path(T, O);

   schedule _read  CF _read;

endmodule: mkOBUFT

typedef struct {
   String cinvctrl_sel;           // "TRUE" to enable dynamic clock inversion, "FALSE" otherwise
   String delay_src;              // "IDATAIN" or "DATAIN"
   String high_performance_mode;  // "TRUE" to reduce jitter, "FALSE" to reduce power
   String idelay_type;            // "FIXED", "VAR_LOAD", or "VAR_LOAD_PIPE"
   Integer idelay_value;          // 0-31 input delay tap setting
   String pipe_sel;               // "TRUE" to select pipelined mode
   Integer refclk_frequency;      // idelayctrl clock input freq in MHz
   String signal_pattern;         // "DATA" or "CLOCK" input signal
}  IDELAYE2_Config;

instance DefaultValue#(IDELAYE2_Config);
   defaultValue =
   IDELAYE2_Config {
      cinvctrl_sel: "FALSE",
      delay_src: "IDATAIN",
      high_performance_mode: "FALSE",
      idelay_type: "FIXED",
      idelay_value: 0,
      pipe_sel: "FALSE",
      refclk_frequency: 200,
      signal_pattern: "DATA"
      };
endinstance

(* always_ready, always_enabled *)
interface IdelayE2;
   method Bit#(5) cntvalueout();
   method Action cinvctrl(Bit#(1) v);
   method Action cntvaluein(Bit#(5) v);
   method Action ld(Bit#(1) v);
   method Action ldpipeen(Bit#(1) v);
   method Action inc(Bool inc);
   method Action ce(Bit#(1) v);
   method Action datain(Bit#(1) v);
   method Action idatain(Bit#(1) v);
   method Action reset(Bit#(1) v);
   method Bit#(1) dataout();
endinterface

import "BVI" IDELAYE2 =
module mkIDELAYE2#(IDELAYE2_Config cfg, Clock serdes_clock)(IdelayE2);
   default_clock clk(C);
   //default_reset rst(REGRST);
   no_reset;
   input_clock serdes ()= serdes_clock;

   parameter CINVCTRL_SEL = cfg.cinvctrl_sel;
   parameter DELAY_SRC = cfg.delay_src;
   parameter HIGH_PERFORMANCE_MODE = cfg.high_performance_mode;
   parameter IDELAY_TYPE = cfg.idelay_type;
   parameter IDELAY_VALUE = cfg.idelay_value;
   parameter PIPE_SEL = cfg.pipe_sel;
   parameter REFCLK_FREQUENCY = cfg.refclk_frequency;
   parameter SIGNAL_PATTERN = cfg.signal_pattern;

   method CNTVALUEOUT cntvalueout();
   method cinvctrl(CINVCTRL) enable((*inhigh*) en0);
   method cntvaluein(CNTVALUEIN) enable((*inhigh*) en1);

   method ld(LD) enable((*inhigh*) en20);

   // is LDPIPEEN the enable for DATAIN?
   method ldpipeen(LDPIPEEN) enable((*inhigh*) en21);

   method DATAOUT dataout();
   method inc(INC) enable((*inhigh*) en5);
   method ce(CE) enable((*inhigh*) en4);
   method reset(REGRST) enable((*inhigh*) en7);
   method datain(DATAIN) enable((*inhigh*) en2);
   method idatain(IDATAIN) enable((*inhigh*) en3) clocked_by(serdes);

   schedule (datain, idatain, inc, ce) CF (datain, idatain, inc, ce);
   schedule (reset, cntvalueout, dataout, ld, datain, ldpipeen, inc, cinvctrl, cntvaluein, ce, idatain) CF (reset, cntvalueout, dataout, ld, datain, ldpipeen, inc, cinvctrl, cntvaluein, ce, idatain);
endmodule

////////////////////////////////////////////////////////////
typedef struct {
   String data_rate;
   Integer data_width;
   String dyn_clk_inv_en;
   String dyn_clkdiv_inv_en;
   Integer init_q1;
   Integer init_q2;
   Integer init_q3;
   Integer init_q4;
   String interface_type;
   String iobdelay;
   Integer num_ce;
   String ofb_used;
   String serdes_mode;
   Integer srval_q1;
   Integer srval_q2;
   Integer srval_q3;
   Integer srval_q4;
}  ISERDESE2_Config;

instance DefaultValue#(ISERDESE2_Config);
   defaultValue =
   ISERDESE2_Config {
      data_rate: "DDR",
      data_width: 8,
      dyn_clk_inv_en: "FALSE",
      dyn_clkdiv_inv_en: "FALSE",
      init_q1: 0,
      init_q2: 0,
      init_q3: 0,
      init_q4: 0,
      interface_type: "NETWORKING",
      iobdelay: "IBUF",
      num_ce: 1,
      ofb_used: "FALSE",
      serdes_mode: "MASTER",
      srval_q1: 0,
      srval_q2: 0,
      srval_q3: 0,
      srval_q4: 0
      };
endinstance

(* always_ready, always_enabled *)
interface IserdesE2;
   (* prefix = "" *)
   method Action d(Bit#(1) d);
   method Bit#(1) o();
   method Action bitslip(Bit#(1) bitslip);
   method Action ce1(Bit#(1) ce1);
   method Action ce2(Bit#(1) ce2);
   method Action ddly(Bit#(1) ddly);
   method Action shiftin1(Bit#(1) shiftin1);
   method Action shiftin2(Bit#(1) shiftin2);
   method Bit#(1) q1();
   method Bit#(1) q2();
   method Bit#(1) q3();
   method Bit#(1) q4();
   method Bit#(1) q5();
   method Bit#(1) q6();
   method Bit#(1) q7();
   method Bit#(1) q8();
   method Bit#(1) shiftout1();
   method Bit#(1) shiftout2();
   method Action ofb(Bit#(1) ofb);
   method Action dynclkdivsel(Bit#(1) dynclkdivsel);
   method Action dynclksel(Bit#(1) dynclksel);
   method Action oclk(Bit#(1) v);
   method Action oclkb(Bit#(1) v);
   method Action reset(Bit#(1) d);
endinterface

import "BVI" ISERDESE2 =
module mkISERDESE2#(ISERDESE2_Config cfg, Clock clk, Clock clkb)(IserdesE2);
   input_clock clk(CLK) = clk;
   input_clock clkb(CLKB) = clkb;
   default_clock clkdiv(CLKDIV);
   no_reset;

   parameter DATA_RATE = cfg.data_rate;
   parameter DATA_WIDTH = cfg.data_width;
   parameter DYN_CLK_INV_EN = cfg.dyn_clk_inv_en;
   parameter DYN_CLKDIV_INV_EN = cfg.dyn_clkdiv_inv_en;
   parameter INIT_Q1 = cfg.init_q1;
   parameter INIT_Q2 = cfg.init_q2;
   parameter INIT_Q3 = cfg.init_q3;
   parameter INIT_Q4 = cfg.init_q4;
   parameter INTERFACE_TYPE = cfg.interface_type;
   parameter IOBDELAY = cfg.iobdelay;
   parameter NUM_CE = cfg.num_ce;
   parameter OFB_USED = cfg.ofb_used;
   parameter SERDES_MODE = cfg.serdes_mode;
   parameter SRVAL_Q1 = cfg.srval_q1;
   parameter SRVAL_Q2 = cfg.srval_q2;
   parameter SRVAL_Q3 = cfg.srval_q3;
   parameter SRVAL_Q4 = cfg.srval_q4;

   port CLKDIVP = 0; // unused
   path (D, O);

   method d(D) enable ((*inhigh*) en0);
   method O o();
   method bitslip(BITSLIP) enable ((*inhigh*)enbitslip);
   method ce1(CE1) enable ((*inhigh*) en1);
   method ce2(CE2) enable ((*inhigh*) en2);
   method ddly(DDLY) enable ((*inhigh*) en3);
   method shiftin1(SHIFTIN1) enable ((*inhigh*) en4);
   method shiftin2(SHIFTIN2) enable ((*inhigh*) en5);
   method Q1 q1();
   method Q2 q2();
   method Q3 q3();
   method Q4 q4();
   method Q5 q5();
   method Q6 q6();
   method Q7 q7();
   method Q8 q8();
   method SHIFTOUT1 shiftout1();
   method SHIFTOUT2 shiftout2();
   method ofb(OFB) enable ((*inhigh*) en6);
   method oclk(OCLK) enable ((*inhigh*) en10);
   method oclkb(OCLKB) enable ((*inhigh*) en11);
   method dynclkdivsel(DYNCLKDIVSEL) enable ((*inhigh*) en7);
   method dynclksel(DYNCLKSEL) enable ((*inhigh*) en8);
   method reset(RST) enable ((*inhigh*) en14);

   schedule (reset, o, q1, q2, q3, q4, q5, q6, q7, q8, shiftout1, shiftout2, d, bitslip, ce1, ce2, ddly, shiftin1, shiftin2, ofb, dynclkdivsel, dynclksel, oclk, oclkb)
         CF (reset, o, q1, q2, q3, q4, q5, q6, q7, q8, shiftout1, shiftout2, d, bitslip, ce1, ce2, ddly, shiftin1, shiftin2, ofb, dynclkdivsel, dynclksel, oclk, oclkb);
endmodule

import "BVI" BUFR =
module mkBUFR5#(Clock clk)(ClockGenIfc);
   default_clock clkunused();
   default_reset rstn();

   parameter BUFR_DIVIDE = "5";

   input_clock clk(I) = clk;
   output_clock gen_clk(O);
   port   CE = True;
   port   CLR = False;
   path(I, O);
endmodule

import "BVI" BUFIO =
module mkBUFIO#(Clock clk)(ClockGenIfc);
   default_clock clkunused();
   default_reset rstn();
   input_clock clk(I) = clk;
   output_clock gen_clk(O);
   path(I, O);
endmodule

interface XbsvMMCME2;
   interface Clock     clkout0;
   interface Clock     clkout1;
   interface Clock     clkfbout;
   (* always_ready, always_enabled *)
   method    Bool      locked;
   (* always_enabled *)
   method    Action    clkfbin(Bit#(1) v);
endinterface

typedef struct {
   String      bandwidth;
   String      compensation;
   Real        clkfbout_mult_f;
   Real        clkfbout_phase;
   Real        clkin1_period;
   Real        clkin2_period;
   Integer     divclk_divide;
   Real        clkout0_divide_f;
   Real        clkout0_duty_cycle;
   Real        clkout0_phase;
   Integer     clkout1_divide;
   Real        clkout1_duty_cycle;
   Real        clkout1_phase;
   Real        ref_jitter1;
   Real        ref_jitter2;
} XbsvMMCMParams deriving (Bits, Eq);

import "BVI" MMCM_ADV =
module mkXbsvMMCM#(XbsvMMCMParams params)(XbsvMMCME2);
   //Reset reset <- exposeCurrentReset;
   //default_reset rst() = reset;
   no_reset;
   default_clock clk1(CLKIN1);
   parameter BANDWIDTH            = params.bandwidth;
   parameter COMPENSATION         = params.compensation;
   parameter CLKFBOUT_MULT_F      = params.clkfbout_mult_f;
   parameter CLKFBOUT_PHASE       = params.clkfbout_phase;
   parameter CLKIN1_PERIOD        = params.clkin1_period;
   parameter CLKIN2_PERIOD        = params.clkin2_period;
   parameter DIVCLK_DIVIDE        = params.divclk_divide;
   parameter CLKOUT0_DIVIDE_F     = params.clkout0_divide_f;
   parameter CLKOUT0_DUTY_CYCLE   = params.clkout0_duty_cycle;
   parameter CLKOUT0_PHASE        = params.clkout0_phase;
   parameter CLKOUT1_DIVIDE       = params.clkout1_divide;
   parameter CLKOUT1_DUTY_CYCLE   = params.clkout1_duty_cycle;
   parameter CLKOUT1_PHASE        = params.clkout1_phase;
   parameter REF_JITTER1          = params.ref_jitter1;
   parameter REF_JITTER2          = params.ref_jitter2;
   port CLKIN2       = Bit#(1)'(0);
   port CLKINSEL     = Bit#(1)'(1);
   port DADDR        = Bit#(7)'(0);
   port DCLK         = Bit#(1)'(0);
   port DEN          = Bit#(1)'(0);
   port DI           = Bit#(16)'(0);
   port DWE          = Bit#(1)'(0);
   port PSCLK        = Bit#(1)'(0);
   port PSEN         = Bit#(1)'(0);
   port PSINCDEC     = Bit#(1)'(0);
   port PWRDWN       = Bit#(1)'(0);
   output_clock clkfbout(CLKFBOUT);
   output_clock clkout0(CLKOUT0);
   output_clock clkout1(CLKOUT1);
   method LOCKED     locked()     clocked_by(no_clock) reset_by(no_reset);
   method            clkfbin(CLKFBIN) enable((*inhigh*)en1);
   schedule clkfbin C clkfbin;
   schedule locked CF (clkfbin, locked);
endmodule

(* always_ready, always_enabled *)
interface XbsvODDR#(type a);
   method    a            q();
   method    Action       s(Bool i);
   method    Action       ce(Bool i);
   method    Action       d1(a i);
   method    Action       d2(a i);
endinterface: XbsvODDR

import "BVI" ODDR =
module mkXbsvODDR#(ODDRParams#(a) params)(XbsvODDR#(a))
   provisos(Bits#(a, 1), DefaultValue#(a));

   if (params.srtype != "SYNC" &&
       params.srtype != "ASYNC")
      error("There are only two modes of reset of the ODDR cell SYNC and ASYNC.  Please specify one of those.");

   if (params.ddr_clk_edge != "OPPOSITE_EDGE" &&
       params.ddr_clk_edge != "SAME_EDGE")
      error("There are only two modes of operation of the ODDR cell OPPOSITE_EDGE and SAME_EDGE.  Please specify one of those.");

   no_reset;
   default_clock clk(C);
   //default_reset rst(R);
   port R = 0;

   parameter DDR_CLK_EDGE = params.ddr_clk_edge;
   parameter INIT         = pack(params.init);
   parameter SRTYPE       = params.srtype;

   method Q   q reset_by(no_reset);
   method     s(S)     enable((*inhigh*)en0) reset_by(no_reset);
   method     ce(CE)   enable((*inhigh*)en1) reset_by(no_reset);
   method     d1(D1)   enable((*inhigh*)en2) reset_by(no_reset);
   method     d2(D2)   enable((*inhigh*)en3) reset_by(no_reset);

   schedule (q)      SB (d1, d2);
   schedule (d1)     CF (d2);
   schedule (d1)     C  (d1);
   schedule (d2)     C  (d2);
   schedule (q)      CF (q);
   schedule (ce, s)  CF (ce, s);
   schedule (ce, s)  SB (d1, d2, q);
endmodule: mkXbsvODDR

interface MMCMHACK;
    interface XbsvMMCME2 mmcmadv;
endinterface

module mkMMCMHACK(MMCMHACK);
    XbsvMMCME2 mm <- mkXbsvMMCM(XbsvMMCMParams {
        bandwidth:"OPTIMIZED", compensation:"ZHOLD",
        clkfbout_mult_f:8.000, clkfbout_phase:0.0,
        clkin1_period:6.734007, clkin2_period:6.734007,
        clkout0_divide_f:8.000, clkout0_duty_cycle:0.5, clkout0_phase:0.0000,
        clkout1_divide:32, clkout1_duty_cycle:0.5, clkout1_phase:0.0000,
        divclk_divide:1, ref_jitter1:0.010, ref_jitter2:0.010
        });
    interface XbsvMMCME2 mmcmadv = mm;
endmodule

////////////////////////////////////////////////////////////

(* always_ready, always_enabled *)
interface IbufdsTest;
   (* prefix="" *)
   method Action in(Bit#(1) i, Bit#(1) ib);
   interface ReadOnly#(Bit#(1)) o;
endinterface

module mkIbufdsTest(IbufdsTest);
   Wire#(Bit#(1)) i_w <- mkDWire(0);
   Wire#(Bit#(1)) ib_w <- mkDWire(0);
   ReadOnly#(Bit#(1)) ibufds <- mkIBUFDS(i_w, ib_w);

   method Action in(Bit#(1) i, Bit#(1) ib);
       i_w <= i;
       ib_w <= ib;
   endmethod
   interface ReadOnly o = ibufds;
endmodule

(* always_ready, always_enabled *)
interface BIBUF#(numeric type sa);
    interface Inout#(Bit#(sa))     pad;
endinterface
import "BVI" GenBIBUF =
module mkBIBUF#(Inout#(a) v)(BIBUF#(sa)) provisos(Bits#(a, sa));
    let sa = fromInteger(valueOf(sa));
    parameter SIZE=sa;
    default_clock clk();
    default_reset rst();
    inout IO = v;
    ifc_inout pad(PAD);
endmodule

(* always_ready, always_enabled *)
interface B2C;
    interface Clock c;
endinterface
import "BVI" GenB2C =
module mkB2C#(Bit#(1) v)(B2C);
    no_clock;
    no_reset;
    output_clock c();
    port B = v;
endmodule


Teste indecente

Teste indecente

import FIFOF::*;
import SpecialFIFOs::*;
import BRAM::*;
import Connectable::*;
import SysConfig::*;
import AsyncPulseSync::*;
import StatusLED::*;
import CycleCounter::*;
import ProgrammableCycleCounter::*;
import AvalonSlave::*;
import InterruptSender::*;

typedef Tuple2#(Bit#(NumFlags), TimeStamp) AcqFifoContents;

interface AcqSys;
	(* prefix="" *)
	interface InterruptSenderWires irqWires;
	(* prefix="" *)
	interface AvalonSlaveWires#(AvalonAddrSize, AvalonDataSize) avalonWires;
	(* prefix="" *)
	interface StatusLEDWires ledWires;
	(* prefix="CH" *)
	interface Vector#(NumInputs, AcqIn) inputs;
	(* always_ready, prefix="", result="STIM" *)
	method Stim stimuli;
endinterface

(* synthesize, clock_prefix="clk", reset_prefix="reset_n" *)
module mkAcqSys(AcqSys);
	AvalonSlave#(AvalonAddrSize, AvalonDataSize) avalon <- mkAvalonSlave;

	Vector#(NumInputs, SyncPulseIfc) inSyncs <- replicateM(mkAsyncPulseSync);
	Bit#(NumInputs) syncedIn = fromPulseVector(inSyncs);

	Array#(Reg#(Stim)) stimOut <- mkCReg(3, 0);
	CycleCounter#(CyclesStimRate) stimRate <- mkCycleCounter;
	Reg#(Bool) wordMatched <- mkReg(False);
	Bit#(NumFlags) flagIn = {wordMatched?1'b1:1'b0, stimRate.ticked?1'b1:1'b0, syncedIn};

	CycleCounter#(CyclesResolution) cycleCounter <- mkCycleCounter;
	StatusLED#(3) led <- mkStatusLED(flagIn, cycleCounter.ticked);
	Reg#(Bool) acqStarted <- mkReg(False);
	Reg#(TimeStamp) timestamp <- mkReg(0);
	Array#(Reg#(Bit#(NumFlags))) channelFlags <- mkCReg(2, 0);

	FIFOF#(AcqFifoContents) acqFifo <- mkSizedFIFOF(2*valueOf(NumFlags));
	RWire#(AcqFifoContents) acqFifoFirst <- mkRWire;
	FIFOF#(Stim) stimFifo <- mkFIFOF;

	BRAM2Port#(StimMemAddr, Stim) stimMem <- mkBRAM2Server(defaultValue);
	FIFOF#(void) stimMemPendRead <- mkFIFOF;  // to enforce order on responses
	Reg#(Bit#(TAdd#(StimMemAddrSize, 1))) stimMemSize <- mkReg(0);
	Reg#(Bit#(TAdd#(StimMemAddrSize, 1))) stimIndex <- mkReg(0);
	FIFOF#(Stim) stimFromMem <- mkFIFOF;

	ProgrammableCycleCounter#(AvalonDataSize) binBoundary <-
		mkProgrammableCycleCounter(fromInteger(defaultWordPeriod));
	Array#(Reg#(Bit#(1))) wordBit <- mkCReg(2, 0);
	Array#(Reg#(Word)) word <- mkCReg(2, 0);
	Reg#(Word) wordToMatch <- mkReg(32'hFFFFFFFF);
	Reg#(Word) wordMask <- mkReg(0);

	//mkConnection(stimMem.portA.response, toPut(stimFromMem));
    /*(* fire_when_enabled *)
    rule askshjasgsahsahgh;
        let data <- stimMem.portA.response.get;
        stimFromMem.enq(data);
    endrule*/

	(* fire_when_enabled *)
	rule peekAcqFifo;
		acqFifoFirst.wset(acqFifo.first);
	endrule

	(* fire_when_enabled *)
	rule answerStimMemRead;
		let resp <- stimMem.portB.response.get;
		avalon.busClient.response.put(extend(resp));
		stimMemPendRead.deq;
	endrule

	rule handleCmd(!stimMemPendRead.notEmpty);
		let cmd <- avalon.busClient.request.get;
		(*split*)
		if (cmd.addr[stimMemAddrSize] == 1'b0) begin
			(*split*)
			case (cmd) matches
				// Register @0x00: Enable/disable acquisition.
				tagged AvalonRequest{addr: 0, data: .x, command: Write}:
					action
						acqStarted <= x != 0;
						(*split*)
						if(x == 0) begin
							led.errorClear;
							acqFifo.clear;
							stimFifo.clear;
							//word[1] <= 0;
							//stimMemSize <= 0;
							//stimOut[2] <= 0;
						end
					endaction
				tagged AvalonRequest{addr: 0, data: .*, command: Read}:
					avalon.busClient.response.put(acqStarted ? 1 : 0);
				// Register @0x04: Read flags from the FIFO. MSB is zero if data is valid.
				tagged AvalonRequest{addr: 1, data: .*, command: Read}:
					action
						Bit#(NumFlags) flags = tpl_1(fromMaybe(tuple2(0,0), acqFifoFirst.wget));
						Bit#(TSub#(AvalonDataSize, 1)) extFlags = extend(flags);
						Bit#(1) invalidFlag = isValid(acqFifoFirst.wget) ? 0 : 1;
						avalon.busClient.response.put({invalidFlag, extFlags});
					endaction
				// Register @0x08: Read timestamp from the FIFO. WARNING: may block.
				tagged AvalonRequest{addr: 2, data: .*, command: Read}:
					action
						TimeStamp tstamp = tpl_2(acqFifo.first);
						avalon.busClient.response.put(tstamp);
						acqFifo.deq;
					endaction
				// Register @0x0c: Write sample to stimuli FIFO. WARNING: may block.
				tagged AvalonRequest{addr: 3, data: .x, command: Write}:
					stimFifo.enq(truncate(x));
				// Register @0x10: Read/write bin boundary period
				tagged AvalonRequest{addr: 4, data: .x, command: Write}:
					binBoundary.period <= x;
				tagged AvalonRequest{addr: 4, data: .*, command: Read}:
					avalon.busClient.response.put(binBoundary.period);
				// Register @0x14: Read/write word to match
				tagged AvalonRequest{addr: 5, data: .x, command: Write}:
					wordToMatch <= x;
				tagged AvalonRequest{addr: 5, data: .*, command: Read}:
					avalon.busClient.response.put(wordToMatch);
				// Register @0x18: Read/write word valid bits mask
				tagged AvalonRequest{addr: 6, data: .x, command: Write}:
					wordMask <= x;
				tagged AvalonRequest{addr: 6, data: .*, command: Read}:
					avalon.busClient.response.put(wordMask);
				// Register @0x1c: Read/write internal stimuli mem size
				// (size == 0) disables the word finder
				tagged AvalonRequest{addr: 7, data: .x, command: Write}:
					stimMemSize <= truncate(x);
				tagged AvalonRequest{addr: 7, data: .*, command: Read}:
					avalon.busClient.response.put(extend(stimMemSize));
				// Deal with reads to addresses not listed above
				tagged AvalonRequest{addr: .*, data: .*, command: Read}:
					avalon.busClient.response.put(32'hBADC0FFE);
			endcase
		end else begin
			if(cmd.command == Read)
				stimMemPendRead.enq(?);
			stimMem.portB.request.put(BRAMRequest{
				write: cmd.command == Write,
				address: truncate(cmd.addr),
				datain: truncate(cmd.data),
				responseOnWrite: False
			});
		end
	endrule

	(* fire_when_enabled *)
	rule stimLoadFifo(acqStarted && stimRate.ticked);
		(*split*)
		if(stimFifo.notEmpty) begin
			stimOut[0] <= stimFifo.first;
			stimFifo.deq;
		end else begin
			led.errorCondition[1].set;
		end
	endrule

	(* fire_when_enabled *)
	rule stimLoadMem(stimRate.ticked);
        let data <- stimMem.portA.response.get;
		stimOut[1] <= data;//stimFromMem.first;
		stimFromMem.deq;
	endrule

	(* fire_when_enabled *)
	rule timestampUpdate(acqStarted && cycleCounter.ticked);
		let flags = asReg(channelFlags[0]);
		Bit#(TSub#(NumFlags,1)) truncatedFlags = truncate(flags);
		(*split*)
		if(truncatedFlags != 0) begin
			(*split*)
			if(acqFifo.notFull) begin
				acqFifo.enq(tuple2(flags, timestamp));
			end else begin
				led.errorCondition[0].set;  // TX FIFO overflow
			end
		end
		flags <= 0;
		timestamp <= timestamp + 1;
	endrule

	(* fire_when_enabled, no_implicit_conditions *)
	rule blendChannelFlags(acqStarted);
		channelFlags[1] <= channelFlags[1] | flagIn;
	endrule

	(* fire_when_enabled, no_implicit_conditions *)
	rule wordUpdate(acqStarted && !wordMatched && binBoundary.ticked);
		let b = asReg(wordBit[0]);
		let updword = (word[0] << 1) | extend(b);
		if ((updword & wordMask) == wordToMatch) begin
			if (stimMemSize != 0) begin
				wordMatched <= True;
				stimIndex <= 0;
			end
			updword = 0;
		end
		word[0] <= updword;
		b <= 0;
	endrule

	(* fire_when_enabled, no_implicit_conditions *)
	rule blendWordBit(acqStarted);
		wordBit[1] <= wordBit[1] | flagIn[ chWord ];
	endrule

	(* fire_when_enabled *)
	rule queryStimMem(wordMatched);
		stimMem.portA.request.put(BRAMRequest{
			write: False,
			address: truncate(stimIndex),
			datain: ?,
			responseOnWrite: False
		});
        stimFromMem.enq(truncate(stimIndex));
		wordMatched <= stimIndex + 1 < stimMemSize;
		stimIndex <= stimIndex + 1;
	endrule

	method Stim stimuli = stimOut[0];

	interface irqWires = irqSender(acqFifo.notEmpty);
	interface avalonWires = avalon.slaveWires;
	interface ledWires = led.wires;
	interface inputs = Vector::map(toAcqIn, inSyncs);
endmodule

import FIFOF::*;
import SpecialFIFOs::*;
import BRAM::*;
import Connectable::*;
import SysConfig::*;
import AsyncPulseSync::*;
import StatusLED::*;
import CycleCounter::*;
import ProgrammableCycleCounter::*;
import AvalonSlave::*;
import InterruptSender::*;

typedef Tuple2#(Bit#(NumFlags), TimeStamp) AcqFifoContents;

interface AcqSys;
	(* prefix="" *)
	interface InterruptSenderWires irqWires;
	(* prefix="" *)
	interface AvalonSlaveWires#(AvalonAddrSize, AvalonDataSize) avalonWires;
	(* prefix="" *)
	interface StatusLEDWires ledWires;
	(* prefix="CH" *)
	interface Vector#(NumInputs, AcqIn) inputs;
	(* always_ready, prefix="", result="STIM" *)
	method Stim stimuli;
endinterface

(* synthesize, clock_prefix="clk", reset_prefix="reset_n" *)
module mkAcqSys(AcqSys);
	AvalonSlave#(AvalonAddrSize, AvalonDataSize) avalon <- mkAvalonSlave;

	Vector#(NumInputs, SyncPulseIfc) inSyncs <- replicateM(mkAsyncPulseSync);
	Bit#(NumInputs) syncedIn = fromPulseVector(inSyncs);

	Array#(Reg#(Stim)) stimOut <- mkCReg(3, 0);
	CycleCounter#(CyclesStimRate) stimRate <- mkCycleCounter;
	Reg#(Bool) wordMatched <- mkReg(False);
	Bit#(NumFlags) flagIn = {wordMatched?1'b1:1'b0, stimRate.ticked?1'b1:1'b0, syncedIn};

	CycleCounter#(CyclesResolution) cycleCounter <- mkCycleCounter;
	StatusLED#(3) led <- mkStatusLED(flagIn, cycleCounter.ticked);
	Reg#(Bool) acqStarted <- mkReg(False);
	Reg#(TimeStamp) timestamp <- mkReg(0);
	Array#(Reg#(Bit#(NumFlags))) channelFlags <- mkCReg(2, 0);

	FIFOF#(AcqFifoContents) acqFifo <- mkSizedFIFOF(2*valueOf(NumFlags));
	RWire#(AcqFifoContents) acqFifoFirst <- mkRWire;
	FIFOF#(Stim) stimFifo <- mkFIFOF;

	BRAM2Port#(StimMemAddr, Stim) stimMem <- mkBRAM2Server(defaultValue);
	FIFOF#(void) stimMemPendRead <- mkFIFOF;  // to enforce order on responses
	Reg#(Bit#(TAdd#(StimMemAddrSize, 1))) stimMemSize <- mkReg(0);
	Reg#(Bit#(TAdd#(StimMemAddrSize, 1))) stimIndex <- mkReg(0);
	FIFOF#(Stim) stimFromMem <- mkFIFOF;

	ProgrammableCycleCounter#(AvalonDataSize) binBoundary <-
		mkProgrammableCycleCounter(fromInteger(defaultWordPeriod));
	Array#(Reg#(Bit#(1))) wordBit <- mkCReg(2, 0);
	Array#(Reg#(Word)) word <- mkCReg(2, 0);
	Reg#(Word) wordToMatch <- mkReg(32'hFFFFFFFF);
	Reg#(Word) wordMask <- mkReg(0);

	mkConnection(stimMem.portA.response, toPut(stimFromMem));

	(* fire_when_enabled *)
	rule peekAcqFifo;
		acqFifoFirst.wset(acqFifo.first);
	endrule

	(* fire_when_enabled *)
	rule answerStimMemRead;
		let resp <- stimMem.portB.response.get;
		avalon.busClient.response.put(extend(resp));
		stimMemPendRead.deq;
	endrule

	rule handleCmd(!stimMemPendRead.notEmpty);
		let cmd <- avalon.busClient.request.get;
		(*split*)
		if (cmd.addr[stimMemAddrSize] == 1'b0) begin
			(*split*)
			case (cmd) matches
				// Register @0x00: Enable/disable acquisition.
				tagged AvalonRequest{addr: 0, data: .x, command: Write}:
					action
						acqStarted <= x != 0;
						(*split*)
						if(x == 0) begin
							led.errorClear;
							acqFifo.clear;
							stimFifo.clear;
							//word[1] <= 0;
							//stimMemSize <= 0;
							//stimOut[2] <= 0;
						end
					endaction
				tagged AvalonRequest{addr: 0, data: .*, command: Read}:
					avalon.busClient.response.put(acqStarted ? 1 : 0);
				// Register @0x04: Read flags from the FIFO. MSB is zero if data is valid.
				tagged AvalonRequest{addr: 1, data: .*, command: Read}:
					action
						Bit#(NumFlags) flags = tpl_1(fromMaybe(tuple2(0,0), acqFifoFirst.wget));
						Bit#(TSub#(AvalonDataSize, 1)) extFlags = extend(flags);
						Bit#(1) invalidFlag = isValid(acqFifoFirst.wget) ? 0 : 1;
						avalon.busClient.response.put({invalidFlag, extFlags});
					endaction
				// Register @0x08: Read timestamp from the FIFO. WARNING: may block.
				tagged AvalonRequest{addr: 2, data: .*, command: Read}:
					action
						TimeStamp tstamp = tpl_2(acqFifo.first);
						avalon.busClient.response.put(tstamp);
						acqFifo.deq;
					endaction
				// Register @0x0c: Write sample to stimuli FIFO. WARNING: may block.
				tagged AvalonRequest{addr: 3, data: .x, command: Write}:
					stimFifo.enq(truncate(x));
				// Register @0x10: Read/write bin boundary period
				tagged AvalonRequest{addr: 4, data: .x, command: Write}:
					binBoundary.period <= x;
				tagged AvalonRequest{addr: 4, data: .*, command: Read}:
					avalon.busClient.response.put(binBoundary.period);
				// Register @0x14: Read/write word to match
				tagged AvalonRequest{addr: 5, data: .x, command: Write}:
					wordToMatch <= x;
				tagged AvalonRequest{addr: 5, data: .*, command: Read}:
					avalon.busClient.response.put(wordToMatch);
				// Register @0x18: Read/write word valid bits mask
				tagged AvalonRequest{addr: 6, data: .x, command: Write}:
					wordMask <= x;
				tagged AvalonRequest{addr: 6, data: .*, command: Read}:
					avalon.busClient.response.put(wordMask);
				// Register @0x1c: Read/write internal stimuli mem size
				// (size == 0) disables the word finder
				tagged AvalonRequest{addr: 7, data: .x, command: Write}:
					stimMemSize <= truncate(x);
				tagged AvalonRequest{addr: 7, data: .*, command: Read}:
					avalon.busClient.response.put(extend(stimMemSize));
				// Deal with reads to addresses not listed above
				tagged AvalonRequest{addr: .*, data: .*, command: Read}:
					avalon.busClient.response.put(32'hBADC0FFE);
			endcase
		end else begin
			if(cmd.command == Read)
				stimMemPendRead.enq(?);
			stimMem.portB.request.put(BRAMRequest{
				write: cmd.command == Write,
				address: truncate(cmd.addr),
				datain: truncate(cmd.data),
				responseOnWrite: False
			});
		end
	endrule

	(* fire_when_enabled *)
	rule stimLoadFifo(acqStarted && stimRate.ticked);
		(*split*)
		if(stimFifo.notEmpty) begin
			stimOut[0] <= stimFifo.first;
			stimFifo.deq;
		end else begin
			led.errorCondition[1].set;
		end
	endrule

	(* fire_when_enabled *)
	rule stimLoadMem(stimRate.ticked);
		stimOut[1] <= stimFromMem.first;
		stimFromMem.deq;
	endrule

	(* fire_when_enabled *)
	rule timestampUpdate(acqStarted && cycleCounter.ticked);
		let flags = asReg(channelFlags[0]);
		Bit#(TSub#(NumFlags,1)) truncatedFlags = truncate(flags);
		(*split*)
		if(truncatedFlags != 0) begin
			(*split*)
			if(acqFifo.notFull) begin
				acqFifo.enq(tuple2(flags, timestamp));
			end else begin
				led.errorCondition[0].set;  // TX FIFO overflow
			end
		end
		flags <= 0;
		timestamp <= timestamp + 1;
	endrule

	(* fire_when_enabled, no_implicit_conditions *)
	rule blendChannelFlags(acqStarted);
		channelFlags[1] <= channelFlags[1] | flagIn;
	endrule

	(* fire_when_enabled, no_implicit_conditions *)
	rule wordUpdate(acqStarted && !wordMatched && binBoundary.ticked);
		let b = asReg(wordBit[0]);
		let updword = (word[0] << 1) | extend(b);
		if ((updword & wordMask) == wordToMatch) begin
			if (stimMemSize != 0) begin
				wordMatched <= True;
				stimIndex <= 0;
			end
			updword = 0;
		end
		word[0] <= updword;
		b <= 0;
	endrule

	(* fire_when_enabled, no_implicit_conditions *)
	rule blendWordBit(acqStarted);
		wordBit[1] <= wordBit[1] | flagIn[ chWord ];
	endrule

	(* fire_when_enabled *)
	rule queryStimMem(wordMatched);
		stimMem.portA.request.put(BRAMRequest{
			write: False,
			address: truncate(stimIndex),
			datain: ?,
			responseOnWrite: False
		});
		wordMatched <= stimIndex + 1 < stimMemSize;
		stimIndex <= stimIndex + 1;
	endrule

	method Stim stimuli = stimOut[0];

	interface irqWires = irqSender(acqFifo.notEmpty);
	interface avalonWires = avalon.slaveWires;
	interface ledWires = led.wires;
	interface inputs = Vector::map(toAcqIn, inSyncs);
endmodule


remove dead code

remove dead code

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

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

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

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

import Clocks        ::*;
import Vector        ::*;
import Connectable   ::*;
import ConnectalAlteraCells ::*;
import ConnectalClocks      ::*;

import ALTERA_XCVR_RECONFIG_WRAPPER        ::*;
import ALTERA_PCIE_RECONFIG_DRIVER_WRAPPER ::*;
import ALTERA_PCIE_WRAPPER                 ::*;
import ALTERA_PLL_WRAPPER                  ::*;

(* always_ready, always_enabled *)
interface PcieS5Lmi#(numeric type address_width, numeric type data_width);
   method Action           rden(Bit#(1) rden);
   method Action           wren(Bit#(1) wren);
   method Action           addr(Bit#(address_width) addr);
   method Action           din(Bit#(data_width) din);
   method Bit#(data_width) dout();
   method Bit#(1)          ack();
endinterface

(* always_ready, always_enabled *)
interface PcieS5RxSt#(numeric type data_width);
   method Bit#(1)          sop;
   method Bit#(1)          eop;
   method Bit#(data_width) data;
   method Action           ready(Bit#(1) ready);
   method Bit#(1)          valid;
   method Bit#(1)          err;
   method Bit#(2)          empty;
endinterface

(* always_ready, always_enabled *)
interface PcieS5TxSt#(numeric type data_width);
   method Action           sop(Bit#(1) sop);
   method Action           eop(Bit#(1) eop);
   method Action           valid(Bit#(1) valid);
   method Action           err(Bit#(1) err);
   method Action           empty(Bit#(2) empty);
   method Bit#(1)          ready;
   method Action           data(Bit#(data_width) data);
endinterface

(* always_ready, always_enabled *)
interface PcieS5Msi;
   method Bit#(1)  int_ack();
   method Action   int_sts (Bit#(1) int_sts);
   method Bit#(1)  msi_ack();
   method Action   msi_num(Bit#(5)num);
   method Action   msi_req(Bit#(1)req);
   method Action   msi_tc(Bit#(3)tc);
endinterface

(* always_ready, always_enabled *)
interface PcieS5RxSpecific;
   method Action   mask(Bit#(1) mask);
   method Bit#(8)  bar();
   method Bit#(16) be();
endinterface

(* always_ready, always_enabled *)
interface PcieS5TlCfg;
   method Bit#(4)  cfg_add();
   method Bit#(32) cfg_ctl();
   method Bit#(53) cfg_sts();
   method Action   cpl_pending(Bit#(1) cpl_pending);
   method Action   cpl_err(Bit#(7) cpl_err);
endinterface

(* always_ready, always_enabled *)
interface PcieS5HipRst;
   method Bit#(1) serdes_pll_locked();
   method Bit#(1) pld_clk_inuse();
   method Action  core_ready(Bit#(1) core_ready);
endinterface

(* always_ready, always_enabled *)
interface PcieS5TxCred;
   method Bit#(12) datafccp();
   method Bit#(12) datafcnp();
   method Bit#(12) datafcp();
   method Bit#(8)  hdrfccp();
   method Bit#(8)  hdrfcnp();
   method Bit#(8)  hdrfcp();
   method Bit#(6)  fchipcons();
   method Bit#(6)  fcinfinite();
endinterface

(* always_ready, always_enabled *)
interface PcieS5Rxin;
(* prefix="", result="in" *)   method Action in(Vector#(8, Bit#(1)) a);
endinterface

(* always_ready, always_enabled *)
interface PcieS5Txout;
   method Vector#(8, Bit#(1)) out();
endinterface

(* always_ready, always_enabled *)
interface PcieS5HipStatus;
   method Bit#(1) cor_ext_rcv;
   method Bit#(1) cor_ext_rpl;
   method Bit#(1) rpl;
   method Bit#(1) dlup;
   method Bit#(1) dlup_exit;
   method Bit#(1) ev128ns;
   method Bit#(1) ev1us;
   method Bit#(1) hotrst;
   method Bit#(4) int_status;
   method Bit#(1) l2_exit;
   method Bit#(4) lane_act;
   method Bit#(5) ltssmstate;
   method Bit#(1) rx_par_err;
   method Bit#(2) tx_par_err;
 (* prefix="", result="cfg_par_err" *)  method Bit#(1) cfg_par_err;
   method Bit#(12) ko_cpl_spc_data;
   method Bit#(8) ko_cpl_spc_header;
endinterface

interface PcieS5HipSerial;
   interface PcieS5Rxin rx;
   interface PcieS5Txout tx;
endinterface

`ifdef PCIES5_SIM
interface PcieS5HipPipe;
(* prefix="", result="rxdata" *)     method Action     rxdata    (Vector#(8, Bit#(8)) rxdata);
(* prefix="", result="rxdatak" *)    method Action     rxdatak   (Vector#(9, Bit#(1)) rxdatak);
(* prefix="", result="rxelecidle" *) method Action     rxelecidle(Vector#(8, Bit#(1)) rxelecidle);
(* prefix="", result="rxstatus" *)   method Action     rxstatus  (Vector#(8, Bit#(3)) rxstatus);
(* prefix="", result="rxvalid" *)    method Action     rxvalid   (Vector#(8, Bit#(1)) rxvalid);
(* prefix="", result="phystatus" *)  method Action     phystatus (Vector#(8, Bit#(1)) phystatus);
(* prefix="", result="sim_pipe_pclk_in" *) method Action sim_pipe_pclk_in(Bit#(1) sim_pipe_pclk_in);
    method Vector#(8, Bit#(1))    rxpolarity();
    method Vector#(8, Bit#(1))    txcompl();
    method Vector#(8, Bit#(8))    txdata();
    method Vector#(8, Bit#(1))    txdatak();
    method Vector#(8, Bit#(1))    txdeemph();
    method Vector#(8, Bit#(1))    txdetectrx();
    method Vector#(8, Bit#(1))    txelecidle();
    method Vector#(8, Bit#(3))    txmargin();
    method Vector#(8, Bit#(1))    txswing();
    method Vector#(8, Bit#(2))    powerdown();
    method Vector#(8, Bit#(3))    eidleinfersel();
    method Bit#(5)    sim_ltssmstate();
    method Bit#(2)    sim_pipe_rate();
endinterface
`endif

(* always_ready, always_enabled *)
interface PcieS5HipCtrl;
(* prefix="", result="test_in" *)        method Action test_in(Bit#(32) test_in);
(* prefix="", result="simu_mode_pipe" *) method Action simu_mode_pipe(Bit#(1) simu_mode_pipe);
endinterface

(* always_ready, always_enabled *)
interface PcieS5Wrap#(numeric type address_width, numeric type data_width, numeric type app_width);
   interface PcieS5Lmi#(address_width, data_width) lmi;
   interface PcieS5RxSt#(app_width) rx_st;
   interface PcieS5TxSt#(app_width) tx_st;
   interface PcieS5Msi msi;
   interface PcieS5RxSpecific rx_specific;
   interface PcieS5TlCfg tl;
   interface PcieS5HipRst hip_rst;
   interface PcieS5TxCred tx_cred;
   interface PcieS5Rxin rx;
   interface PcieS5Txout tx;
   interface PcieS5HipStatus hip_status;
`ifdef PCIES5_SIM
   interface PcieS5HipPipe hip_pipe;
`endif
   interface PcieS5HipCtrl hip_ctrl;
   interface Clock coreclkout_hip;
endinterface

//(* synthesize *)
module mkPcieS5Wrap#(Clock clk_100Mhz, Clock clk_50Mhz, Reset npor, Reset pin_perst)(PcieS5Wrap#(12, 32, 128));

   Vector#(8, Wire#(Bit#(1))) rx_in_wires <- replicateM(mkDWire(0));

//`ifdef PCIES5_SIM
   Vector#(8, Wire#(Bit#(8))) rxdata_wires <- replicateM(mkDWire(0));
   Vector#(8, Wire#(Bit#(1))) rxdatak_wires <- replicateM(mkDWire(0));
   Vector#(8, Wire#(Bit#(1))) rxelecidle_wires <- replicateM(mkDWire(0));
   Vector#(8, Wire#(Bit#(3))) rxstatus_wires  <- replicateM(mkDWire(0));
   Vector#(8, Wire#(Bit#(1))) rxvalid_wires   <- replicateM(mkDWire(0));
   Vector#(8, Wire#(Bit#(1))) phystatus_wires <- replicateM(mkDWire(0));
//`endif

   Clock default_clock <- exposeCurrentClock;
   Reset default_reset <- exposeCurrentReset;
   Reset reset_high <- invertCurrentReset;

   PcieWrap         pcie     <- mkPcieWrap(clk_100Mhz, npor, pin_perst, reset_high);

   Clock coreclk = pcie.coreclkout.hip;
   PcieReconfigWrap pcie_cfg <- mkPcieReconfigWrap(coreclk, clk_50Mhz, npor, reset_high, reset_high);
   XcvrReconfigWrap xcvr_cfg <- mkXcvrReconfigWrap(clk_50Mhz, reset_high, reset_high);

   (* no_implicit_conditions *)
   rule connectReconfigMgmt;
      xcvr_cfg.reconfig_mgmt.read(pcie_cfg.reconfig_mgmt.read);
      xcvr_cfg.reconfig_mgmt.write(pcie_cfg.reconfig_mgmt.write);
      xcvr_cfg.reconfig_mgmt.address(pcie_cfg.reconfig_mgmt.address);
      xcvr_cfg.reconfig_mgmt.writedata(pcie_cfg.reconfig_mgmt.writedata);
      pcie_cfg.reconfig_mgmt.readdata(xcvr_cfg.reconfig_mgmt.readdata);
      pcie_cfg.reconfig_mgmt.waitrequest(xcvr_cfg.reconfig_mgmt.waitrequest);
   endrule

   (* no_implicit_conditions *)
   rule connectCurrentSpeed;
      pcie_cfg.current.speed(pcie.current.speed);
   endrule

   (* no_implicit_conditions *)
   rule connect_xcvr_reconfig;
      pcie.reconfig.to_xcvr(xcvr_cfg.reconfig.to_xcvr);
      xcvr_cfg.reconfig.from_xcvr(pcie.reconfig.from_xcvr);
   endrule

   (* no_implicit_conditions *)
   rule connectBusy;
      pcie_cfg.reconfig_b.usy(xcvr_cfg.reconfig.busy);
   endrule

   (* no_implicit_conditions *)
   rule connectHipStatus;
      pcie_cfg.derr.cor_ext_rcv_drv(pcie.derr.cor_ext_rcv);
      pcie_cfg.derr.cor_ext_rpl_drv(pcie.derr.cor_ext_rpl);
      pcie_cfg.derr.rpl_drv(pcie.derr.rpl);
      pcie_cfg.dlup.drv(pcie.dl.up);
      pcie_cfg.dlup.exit_drv(pcie.dl.up_exit);
      pcie_cfg.ev128ns.drv(pcie.ev128.ns);
      pcie_cfg.ev1us.drv(pcie.ev1.us);
      pcie_cfg.hotrst.exit_drv(pcie.hotrst.exit);
      pcie_cfg.int_s.tatus_drv(pcie.int_s.tatus);
      pcie_cfg.lane.act_drv(pcie.lane.act);
      pcie_cfg.l2.exit_drv(pcie.l2.exit);
      pcie_cfg.ltssmstate.drv(pcie.ltssm.state);
      pcie_cfg.tx.par_err_drv(pcie.tx_par.err);
      pcie_cfg.rx.par_err_drv(pcie.rx_par.err);
      pcie_cfg.cfg.par_err_drv(pcie.cfg_par.err);
      pcie_cfg.ko.cpl_spc_data_drv(pcie.ko.cpl_spc_data);
      pcie_cfg.ko.cpl_spc_header_drv(pcie.ko.cpl_spc_header);
   endrule

   (* no_implicit_conditions *)
   rule power_mgmt;
      pcie.pm.auxpwr(0);
      pcie.pm.data(10'b0);
      pcie.pm_e.vent(0);
      pcie.pme.to_cr(0);
      pcie.hpg.ctrler(5'b0);
   endrule

   C2B c2b <- mkC2B(pcie.coreclkout.hip);
   rule pld_clk_rule;
      pcie.pld.clk(c2b.o());
   endrule

//`ifdef PCIES5_SIM
   (* no_implicit_conditions *)
   rule pcie_rx;
      pcie.rx.in0(rx_in_wires[0]);
      pcie.rx.in1(rx_in_wires[1]);
      pcie.rx.in2(rx_in_wires[2]);
      pcie.rx.in3(rx_in_wires[3]);
      pcie.rx.in4(rx_in_wires[4]);
      pcie.rx.in5(rx_in_wires[5]);
      pcie.rx.in6(rx_in_wires[6]);
      pcie.rx.in7(rx_in_wires[7]);
   endrule

   (* no_implicit_conditions *)
   rule pcie_rxdata;
      pcie.rxd.ata0(rxdata_wires[0]);
      pcie.rxd.ata1(rxdata_wires[1]);
      pcie.rxd.ata2(rxdata_wires[2]);
      pcie.rxd.ata3(rxdata_wires[3]);
      pcie.rxd.ata4(rxdata_wires[4]);
      pcie.rxd.ata5(rxdata_wires[5]);
      pcie.rxd.ata6(rxdata_wires[6]);
      pcie.rxd.ata7(rxdata_wires[7]);
   endrule

   (* no_implicit_conditions *)
   rule pcie_rxdatak;
      pcie.rxd.atak0(rxdatak_wires[0]);
      pcie.rxd.atak1(rxdatak_wires[1]);
      pcie.rxd.atak2(rxdatak_wires[2]);
      pcie.rxd.atak3(rxdatak_wires[3]);
      pcie.rxd.atak4(rxdatak_wires[4]);
      pcie.rxd.atak5(rxdatak_wires[5]);
      pcie.rxd.atak6(rxdatak_wires[6]);
      pcie.rxd.atak7(rxdatak_wires[7]);
   endrule

   (* no_implicit_conditions *)
   rule pcie_rxelecidle;
      pcie.rxe.lecidle0(rxelecidle_wires[0]);
      pcie.rxe.lecidle1(rxelecidle_wires[1]);
      pcie.rxe.lecidle2(rxelecidle_wires[2]);
      pcie.rxe.lecidle3(rxelecidle_wires[3]);
      pcie.rxe.lecidle4(rxelecidle_wires[4]);
      pcie.rxe.lecidle5(rxelecidle_wires[5]);
      pcie.rxe.lecidle6(rxelecidle_wires[6]);
      pcie.rxe.lecidle7(rxelecidle_wires[7]);
   endrule

   (* no_implicit_conditions *)
   rule pcie_rxstatus;
      pcie.rxs.tatus0(rxstatus_wires[0]);
      pcie.rxs.tatus1(rxstatus_wires[1]);
      pcie.rxs.tatus2(rxstatus_wires[2]);
      pcie.rxs.tatus3(rxstatus_wires[3]);
      pcie.rxs.tatus4(rxstatus_wires[4]);
      pcie.rxs.tatus5(rxstatus_wires[5]);
      pcie.rxs.tatus6(rxstatus_wires[6]);
      pcie.rxs.tatus7(rxstatus_wires[7]);
   endrule

   (* no_implicit_conditions *)
   rule pcie_rxvalid;
      pcie.rxv.alid0(rxvalid_wires[0]);
      pcie.rxv.alid1(rxvalid_wires[1]);
      pcie.rxv.alid2(rxvalid_wires[2]);
      pcie.rxv.alid3(rxvalid_wires[3]);
      pcie.rxv.alid4(rxvalid_wires[4]);
      pcie.rxv.alid5(rxvalid_wires[5]);
      pcie.rxv.alid6(rxvalid_wires[6]);
      pcie.rxv.alid7(rxvalid_wires[7]);
   endrule

   (* no_implicit_conditions *)
   rule pcie_phystatus;
      pcie.phy.status0(phystatus_wires[0]);
      pcie.phy.status1(phystatus_wires[1]);
      pcie.phy.status2(phystatus_wires[2]);
      pcie.phy.status3(phystatus_wires[3]);
      pcie.phy.status4(phystatus_wires[4]);
      pcie.phy.status5(phystatus_wires[5]);
      pcie.phy.status6(phystatus_wires[6]);
      pcie.phy.status7(phystatus_wires[7]);
   endrule
//`endif

   method Clock coreclkout_hip;
      return pcie.coreclkout.hip;
   endmethod

   interface PcieS5TlCfg tl;
      method Bit#(4) cfg_add();
         return pcie.tl.cfg_add;
      endmethod
      method Bit#(32) cfg_ctl();
         return pcie.tl.cfg_ctl;
      endmethod
      method Bit#(53) cfg_sts();
         return pcie.tl.cfg_sts;
      endmethod
      method cpl_pending = pcie.cpl.pending;
      method cpl_err = pcie.cpl.err;
   endinterface

   interface PcieS5Lmi lmi;
      method Bit#(32) dout();
         return pcie.lmi.dout;
      endmethod

      method Bit#(1) ack ();
         return pcie.lmi.ack;
      endmethod

      method rden = pcie.lmi.rden;
      method wren = pcie.lmi.wren;
      method addr = pcie.lmi.addr;
      method din = pcie.lmi.din;
   endinterface

   interface PcieS5RxSt rx_st;
      method Bit#(1)   sop();   return pcie.rx_s.t_sop;   endmethod
      method Bit#(1)   eop();   return pcie.rx_s.t_eop;   endmethod
      method Bit#(128) data();  return pcie.rx_s.t_data;  endmethod
      method Bit#(1)   valid(); return pcie.rx_s.t_valid; endmethod
      method Bit#(1)   err();   return pcie.rx_s.t_err;   endmethod
      method Bit#(2)   empty(); return pcie.rx_s.t_empty; endmethod
      method ready = pcie.rx_s.t_ready;
   endinterface

   interface PcieS5TxSt tx_st;
      method Bit#(1) ready (); return pcie.tx_s.t_ready; endmethod
      method sop   = pcie.tx_s.t_sop;
      method eop   = pcie.tx_s.t_eop;
      method valid = pcie.tx_s.t_valid;
      method err   = pcie.tx_s.t_err;
      method empty = pcie.tx_s.t_empty;
      method data  = pcie.tx_s.t_data;
   endinterface

   interface PcieS5Msi msi;
      method Bit#(1) int_ack(); return pcie.app.int_ack; endmethod
      method Bit#(1) msi_ack(); return pcie.app.msi_ack; endmethod

      method int_sts = pcie.app.int_sts;
      method msi_num = pcie.app.msi_num;
      method msi_req = pcie.app.msi_req;
      method msi_tc = pcie.app.msi_tc;
   endinterface

   interface PcieS5RxSpecific rx_specific;
      method mask = pcie.rx_s.t_mask;
      method Bit#(8) bar (); return pcie.rx_s.t_bar; endmethod
      method Bit#(16) be();  return pcie.rx_s.t_be;  endmethod
   endinterface

   interface PcieS5HipRst hip_rst;
      method Bit#(1) serdes_pll_locked(); return pcie.serdes.pll_locked; endmethod
      method Bit#(1) pld_clk_inuse(); return pcie.pld.clk_inuse; endmethod
      method core_ready = pcie.pld.core_ready;
   endinterface

   interface PcieS5TxCred tx_cred;
      method Bit#(12) datafccp(); return pcie.tx_cred.datafccp; endmethod
      method Bit#(12) datafcnp(); return pcie.tx_cred.datafcnp; endmethod
      method Bit#(12) datafcp();  return pcie.tx_cred.datafcp;  endmethod
      method Bit#(8) hdrfccp();   return pcie.tx_cred.hdrfccp;  endmethod
      method Bit#(8) hdrfcnp();   return pcie.tx_cred.hdrfcnp;  endmethod
      method Bit#(8) hdrfcp();    return pcie.tx_cred.hdrfcp;   endmethod
      method Bit#(6) fchipcons(); return pcie.tx_cred.fchipcons; endmethod
      method Bit#(6) fcinfinite();return pcie.tx_cred.fcinfinite;endmethod
   endinterface

   interface PcieS5Rxin rx;
      method Action in(Vector#(8, Bit#(1)) a);
         writeVReg(rx_in_wires, a);
      endmethod
   endinterface

   interface PcieS5Txout tx;
      method Vector#(8, Bit#(1)) out();
         Vector#(8, Bit#(1)) ret_val;
         ret_val[0] = pcie.tx.out0;
         ret_val[1] = pcie.tx.out1;
         ret_val[2] = pcie.tx.out2;
         ret_val[3] = pcie.tx.out3;
         ret_val[4] = pcie.tx.out4;
         ret_val[5] = pcie.tx.out5;
         ret_val[6] = pcie.tx.out6;
         ret_val[7] = pcie.tx.out7;
         return ret_val;
      endmethod
   endinterface

   interface PcieS5HipStatus hip_status;
      method Bit#(1) cor_ext_rcv; return pcie.derr.cor_ext_rcv; endmethod
      method Bit#(1) cor_ext_rpl; return pcie.derr.cor_ext_rpl; endmethod
      method Bit#(1) rpl;         return pcie.derr.rpl;         endmethod
      method Bit#(1) dlup;        return pcie.dl.up;            endmethod
      method Bit#(1) dlup_exit;   return pcie.dl.up_exit;       endmethod
      method Bit#(1) ev128ns;     return pcie.ev128.ns;         endmethod
      method Bit#(1) ev1us;       return pcie.ev1.us;           endmethod
      method Bit#(1) hotrst;      return pcie.hotrst.exit;      endmethod
      method Bit#(4) int_status;  return pcie.int_s.tatus;      endmethod
      method Bit#(1) l2_exit;     return pcie.l2.exit;          endmethod
      method Bit#(4) lane_act;    return pcie.lane.act;         endmethod
      method Bit#(5) ltssmstate;  return pcie.ltssm.state;      endmethod
      method Bit#(1) rx_par_err;  return pcie.rx_par.err;       endmethod
      method Bit#(2) tx_par_err;  return pcie.tx_par.err;       endmethod
      method Bit#(1) cfg_par_err; return pcie.cfg_par.err;      endmethod
      method Bit#(12) ko_cpl_spc_data; return pcie.ko.cpl_spc_data; endmethod
      method Bit#(8) ko_cpl_spc_header;return pcie.ko.cpl_spc_header;endmethod
   endinterface

`ifdef PCIES5_SIM
   interface PcieS5HipPipe hip_pipe;
      method Action rxdata(Vector#(8, Bit#(8)) a);
         writeVReg(rxdata_wires, a);
      endmethod

      method Action rxdatak(Vector#(8, Bit#(1)) a);
         writeVReg(rxdatak_wires, a);
      endmethod

      method Action rxelecidle(Vector#(8, Bit#(1)) a);
         writeVReg(rxelecidle_wires, a);
      endmethod

      method Action rxstatus(Vector#(8, Bit#(3)) a);
         writeVReg(rxstatus_wires, a);
      endmethod

      method Action rxvalid(Vector#(8, Bit#(1)) a);
         writeVReg(rxvalid_wires, a);
      endmethod

      method Action phystatus(Vector#(8, Bit#(1)) a);
         writeVReg(phystatus_wires, a);
      endmethod

      method rxpolarity();
         Vector#(8, Bit#(1)) retval = unpack({pcie.rxp.olarity7, pcie.rxp.olarity6, pcie.rxp.olarity5, pcie.rxp.olarity4, pcie.rxp.olarity3, pcie.rxp.olarity2, pcie.rxp.olarity1, pcie.rxp.olarity0});
         return retval;
      endmethod

      method txcompl();
         Vector#(8, Bit#(1)) retval = unpack({pcie.txc.ompl7, pcie.txc.ompl6, pcie.txc.ompl5, pcie.txc.ompl4, pcie.txc.ompl3, pcie.txc.ompl2, pcie.txc.ompl1, pcie.txc.ompl0});
         return retval;
      endmethod

      method txdata();
         Vector#(8, Bit#(8)) retval = unpack({pcie.txd.ata7, pcie.txd.ata6, pcie.txd.ata5, pcie.txd.ata4, pcie.txd.ata3, pcie.txd.ata2, pcie.txd.ata1, pcie.txd.ata0});
         return retval;
      endmethod

      method txdatak();
         Vector#(8, Bit#(1)) retval = unpack({pcie.txd.atak7, pcie.txd.atak6, pcie.txd.atak5, pcie.txd.atak4, pcie.txd.atak3, pcie.txd.atak2, pcie.txd.atak1, pcie.txd.atak0});
         return retval;
      endmethod

      method txdeemph();
         Vector#(8, Bit#(1)) retval = unpack({pcie.txd.eemph7, pcie.txd.eemph6, pcie.txd.eemph5, pcie.txd.eemph4, pcie.txd.eemph3, pcie.txd.eemph2, pcie.txd.eemph1, pcie.txd.eemph0});
         return retval;
      endmethod

      method txdetectrx();
         Vector#(8, Bit#(1)) retval = unpack({pcie.txd.etectrx7, pcie.txd.etectrx6, pcie.txd.etectrx5, pcie.txd.etectrx4, pcie.txd.etectrx3, pcie.txd.etectrx2, pcie.txd.etectrx1, pcie.txd.etectrx0});
         return retval;
      endmethod

      method txelecidle();
         Vector#(8, Bit#(1)) retval = unpack({pcie.txe.lecidle7, pcie.txe.lecidle6, pcie.txe.lecidle5, pcie.txe.lecidle4, pcie.txe.lecidle3, pcie.txe.lecidle2, pcie.txe.lecidle1, pcie.txe.lecidle0});
         return retval;
      endmethod

      method txmargin();
         Vector#(8, Bit#(3)) retval = unpack({pcie.txm.argin7, pcie.txm.argin6, pcie.txm.argin5, pcie.txm.argin4, pcie.txm.argin3, pcie.txm.argin2, pcie.txm.argin1, pcie.txm.argin0});
         return retval;
      endmethod

      method txswing();
         Vector#(8, Bit#(1)) retval = unpack({pcie.txs.wing7, pcie.txs.wing6, pcie.txs.wing5, pcie.txs.wing4, pcie.txs.wing3, pcie.txs.wing2, pcie.txs.wing1, pcie.txs.wing0});
         return retval;
      endmethod

      method powerdown();
         Vector#(8, Bit#(2)) retval = unpack({pcie.power.down7, pcie.power.down6, pcie.power.down5, pcie.power.down4, pcie.power.down3, pcie.power.down2, pcie.power.down1, pcie.power.down0});
         return retval;
      endmethod

      method eidleinfersel();
         Vector#(8, Bit#(3)) retval = unpack({pcie.eidle.infersel7, pcie.eidle.infersel6, pcie.eidle.infersel5, pcie.eidle.infersel4, pcie.eidle.infersel3, pcie.eidle.infersel2, pcie.eidle.infersel1, pcie.eidle.infersel0});
         return retval;
      endmethod

      method sim_pipe_pclk_in = pcie.sim.pipe_pclk_in;

      method sim_ltssmstate(); return pcie.sim.ltssmstate; endmethod
      method sim_pipe_rate(); return pcie.sim.pipe_rate; endmethod
   endinterface
`endif

   interface PcieS5HipCtrl hip_ctrl;
      method test_in = pcie.test.in;
      method simu_mode_pipe = pcie.simu.mode_pipe;
   endinterface
endmodule

// Altera PCIe HIP Reset

(* always_ready, always_enabled *)
interface AlteraPcieHipRs;
(* prefix="", result="dlup_exit" *)   method Action dlup_exit(Bit#(1) dlup_exit);
(* prefix="", result="hotrst_exit" *) method Action hotrst_exit(Bit#(1) hotrst_exit);
(* prefix="", result="l2_exit" *)     method Action l2_exit(Bit#(1) l2_exit);
(* prefix="", result="ltssm" *)       method Action ltssm(Bit#(5) ltssm);
(* prefix="", result="test_sim" *)    method Action test_sim(Bit#(1) test_sim);
   method Reset app_rstn;
endinterface

typedef enum {
   LTSSM_POL = 5'b00010,
   LTSSM_CPL = 5'b00011,
   LTSSM_DET = 5'b00000,
   LTSSM_RCV = 5'b01100,
   LTSSM_DIS = 5'b10000
} LTSSM deriving (Bits, Eq);

typedef enum {
   RCV_TIMEOUT = 23'd6000000
} TIMEOUT deriving (Bits, Eq);

typedef enum {
   RSTN_CNT_MAX = 11'h400,
   RSTN_CTN_MAX_SIM = 11'h20
} RSTN_CNT deriving (Bits, Eq);

//(* synthesize, no_default_clock, no_default_reset, clock_prefix="", reset_prefix="" *)
(* always_ready, always_enabled, no_default_clock, no_default_reset, clock_prefix="", reset_prefix="" *)
module mkAlteraPcieHipRs#(Clock pld_clk, Reset npor)(AlteraPcieHipRs);
   Reset npor_sync_pld_clk          <- mkAsyncReset(3, npor, pld_clk);
   Reg #(Bit#(5)) ltssm_r           <- mkReg(0, clocked_by(pld_clk), reset_by(npor_sync_pld_clk));
   Reg #(Bit#(1)) dlup_exit_r       <- mkReg(1, clocked_by(pld_clk), reset_by(npor_sync_pld_clk));
   Reg #(Bit#(1)) hotrst_exit_r     <- mkReg(1, clocked_by(pld_clk), reset_by(npor_sync_pld_clk));
   Reg #(Bit#(1)) l2_exit_r         <- mkReg(1, clocked_by(pld_clk), reset_by(npor_sync_pld_clk));
   Reg #(Bit#(11)) rsnt_cntn        <- mkReg(0, clocked_by(pld_clk), reset_by(npor_sync_pld_clk));
   Reg #(Bit#(23)) recovery_cnt     <- mkReg(0, clocked_by(pld_clk), reset_by(npor_sync_pld_clk));
   Reg #(Bit#(1)) recovery_rst      <- mkReg(0, clocked_by(pld_clk), reset_by(npor_sync_pld_clk));
   Reg #(Bit#(1)) exits_r           <- mkReg(0, clocked_by(pld_clk), reset_by(npor_sync_pld_clk));

   let app_rstn_out <- mkReset(0, True, pld_clk, clocked_by(pld_clk), reset_by(npor_sync_pld_clk));

   rule exit_v ((l2_exit_r == 1'b0) || (hotrst_exit_r == 1'b0) || (dlup_exit_r == 1'b0) || (ltssm_r == pack(LTSSM_DIS)) || (recovery_rst == 1'b1));
      exits_r <= 1'b1;
   endrule

   //Delay HIP reset upon npor
   rule delay_hip0 if (exits_r == 1'b1);
      rsnt_cntn <= 11'h3f0;
   endrule

   rule delay_hip1 if (exits_r != 1'b1);
      rsnt_cntn <= rsnt_cntn + 11'h1;
   endrule

   rule delay_hip2 if ((exits_r != 1'b1) && (rsnt_cntn == pack(RSTN_CNT_MAX)));
      app_rstn_out.assertReset;
   endrule

   // Monitor if LTSSM is frozen in RECOVERY state
   // Issue reset if timeout RCV_TIMEOUT
   rule recovery_cnt0 ((recovery_cnt != pack(RCV_TIMEOUT)) && (ltssm_r != pack(LTSSM_RCV)));
      recovery_cnt <= 23'b0;
   endrule

   rule recovery_cnt1 ((recovery_cnt == pack(RCV_TIMEOUT)) && (ltssm_r == pack(LTSSM_RCV)));
      recovery_cnt <= recovery_cnt;
   endrule

   rule recovery_cnt2 ((recovery_cnt != pack(RCV_TIMEOUT)) && (ltssm_r == pack(LTSSM_RCV)));
      recovery_cnt <= recovery_cnt + 23'h1;
   endrule

   rule recovery_rst0 (recovery_cnt == pack(RCV_TIMEOUT));
      recovery_rst <= 1'b1;
   endrule

   rule recovery_rst1 (ltssm_r != pack(LTSSM_RCV) && recovery_cnt != pack(RCV_TIMEOUT));
      recovery_rst <= 1'b0;
   endrule

   // interface
   method Action dlup_exit(Bit#(1) v);
      dlup_exit_r <= v;
   endmethod

   method Action ltssm(Bit#(5) v);
      ltssm_r <= v;
   endmethod

   method Action l2_exit(Bit#(1) v);
      l2_exit_r <= v;
   endmethod

   method Action hotrst_exit(Bit#(1) v);
      hotrst_exit_r <= v;
   endmethod

   method app_rstn;
      return app_rstn_out.new_rst;
   endmethod
endmodule

// Altera Pcie TL Configuration

interface AlteraPcieTlCfgSample;
   method Action tl_cfg_add(Bit#(4) tl_cfg_add);
   method Action tl_cfg_ctl(Bit#(32) tl_cfg_ctl);
   method Action tl_cfg_ctl_wr(Bit#(1) tl_cfg_ctl_wr);
   method Action tl_cfg_sts(Bit#(53) tl_cfg_sts);
   method Action tl_cfg_sts_wr(Bit#(1) tl_cfg_sts_wr);
   method Bit#(13) cfg_busdev;
   method Bit#(32) cfg_devcsr;
   method Bit#(32) cfg_lnkcsr;
   method Bit#(32) cfg_prmcsr;

   method Bit#(20) cfg_io_bas;
   method Bit#(20) cfg_io_lim;
   method Bit#(12) cfg_np_bas;
   method Bit#(12) cfg_np_lim;
   method Bit#(44) cfg_pr_bas;
   method Bit#(44) cfg_pr_lim;

   method Bit#(24) cfg_tcvcmap;
   method Bit#(16) cfg_msicsr;
endinterface

//(* synthesize *)
(* always_ready, always_enabled,  no_default_clock, no_default_reset, clock_prefix="", reset_prefix="" *)
module mkAlteraPcieTlCfgSample#(Clock pld_clk, Reset rstn)(AlteraPcieTlCfgSample);
   Reg #(Bit#(1)) tl_cfg_ctl_wr_r   <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));
   Reg #(Bit#(1)) tl_cfg_ctl_wr_rr  <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));
   Reg #(Bit#(1)) tl_cfg_ctl_wr_rrr <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));

   Reg #(Bit#(1)) tl_cfg_sts_wr_r   <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));
   Reg #(Bit#(1)) tl_cfg_sts_wr_rr  <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));
   Reg #(Bit#(1)) tl_cfg_sts_wr_rrr <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));

   Reg #(Bit#(4)) tl_cfg_add_wires    <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));
   Reg #(Bit#(32)) tl_cfg_ctl_wires   <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));
   Reg #(Bit#(53)) tl_cfg_sts_wires   <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));
   Reg #(Bit#(1)) tl_cfg_ctl_wr_wires <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));
   Reg #(Bit#(1)) tl_cfg_sts_wr_wires <- mkReg(0, clocked_by(pld_clk), reset_by(rstn));

   Vector#(13, Reg#(Bit#(1))) cfg_busdev_wires   <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));
   Vector#(32, Reg#(Bit#(1))) cfg_devcsr_wires   <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));
   Vector#(32, Reg#(Bit#(1))) cfg_lnkcsr_wires  <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));
   Vector#(32, Reg#(Bit#(1))) cfg_prmcsr_wires   <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));

   Vector#(20, Reg#(Bit#(1))) cfg_io_bas_wires   <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));
   Vector#(20, Reg#(Bit#(1))) cfg_io_lim_wires   <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));
   Vector#(12, Reg#(Bit#(1))) cfg_np_bas_wires   <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));
   Vector#(12, Reg#(Bit#(1))) cfg_np_lim_wires   <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));
   Vector#(44, Reg#(Bit#(1))) cfg_pr_bas_wires   <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));
   Vector#(44, Reg#(Bit#(1))) cfg_pr_lim_wires   <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));
   Vector#(24, Reg#(Bit#(1))) cfg_tcvcmap_wires  <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));
   Vector#(16, Reg#(Bit#(1))) cfg_msicsr_wires   <- replicateM(mkReg(0, clocked_by(pld_clk), reset_by(rstn)));

   rule tl_cfg;
      tl_cfg_ctl_wr_r   <= tl_cfg_ctl_wr_wires;
      tl_cfg_ctl_wr_rr  <= tl_cfg_ctl_wr_r;
      tl_cfg_ctl_wr_rrr <= tl_cfg_ctl_wr_rr;
      tl_cfg_sts_wr_r   <= tl_cfg_sts_wr_wires;
      tl_cfg_sts_wr_rr  <= tl_cfg_sts_wr_r;
      tl_cfg_sts_wr_rrr <= tl_cfg_sts_wr_rr;
   endrule

   rule cfg_constants (True);
      writeVReg(takeAt(25, cfg_prmcsr_wires), unpack(2'h0));
      writeVReg(takeAt(16, cfg_prmcsr_wires), unpack(8'h0));
      writeVReg(takeAt(20, cfg_devcsr_wires), unpack(12'h0));
   endrule

   // tl_cfg_sts sampling
   rule cfg_sts_sampling (tl_cfg_sts_wr_rrr != tl_cfg_sts_wr_rr);
      writeVReg(takeAt(16,  cfg_devcsr_wires), unpack(tl_cfg_sts_wires[52:49]));
      writeVReg(takeAt(16,  cfg_lnkcsr_wires), unpack(tl_cfg_sts_wires[46:31]));
      writeVReg(takeAt(27,  cfg_prmcsr_wires), unpack(tl_cfg_sts_wires[29:25]));
      writeVReg(takeAt(24,  cfg_prmcsr_wires), unpack(tl_cfg_sts_wires[24]));
   endrule

   // tl_cfg_ctl sampling
   rule cfg_ctl_sample (tl_cfg_ctl_wr_rrr != tl_cfg_ctl_wr_rr);
     case (tl_cfg_add_wires)
         4'h0:  writeVReg(take(cfg_devcsr_wires),  unpack(tl_cfg_ctl_wires[31:16]));
         4'h2:  writeVReg(take(cfg_lnkcsr_wires),  unpack(tl_cfg_ctl_wires[31:16]));
         4'h3:  writeVReg(take(cfg_prmcsr_wires),  unpack(tl_cfg_ctl_wires[23:8]));
         4'h5:  writeVReg(take(cfg_io_bas_wires),  unpack(tl_cfg_ctl_wires[19:0]));
         4'h6:  writeVReg(take(cfg_io_lim_wires),  unpack(tl_cfg_ctl_wires[19:0]));
         4'h7:begin
            writeVReg(take(cfg_np_bas_wires),  unpack(tl_cfg_ctl_wires[23:12]));
            writeVReg(take(cfg_np_lim_wires),  unpack(tl_cfg_ctl_wires[11:0]));
         end
         4'h8:  writeVReg(take(cfg_pr_bas_wires),  unpack(tl_cfg_ctl_wires[31:0]));
         4'h9:  writeVReg(takeAt(32, cfg_pr_bas_wires), unpack(tl_cfg_ctl_wires[11:0]));
         4'hA:  writeVReg(take(cfg_pr_lim_wires),  unpack(tl_cfg_ctl_wires[31:0]));
         4'hB:  writeVReg(takeAt(32, cfg_pr_lim_wires), unpack(tl_cfg_ctl_wires[11:0]));
         4'hD:  writeVReg(take(cfg_msicsr_wires),  unpack(tl_cfg_ctl_wires[15:0]));
         4'hE:  writeVReg(take(cfg_tcvcmap_wires), unpack(tl_cfg_ctl_wires[23:0]));
         4'hF:  writeVReg(take(cfg_busdev_wires),  unpack(tl_cfg_ctl_wires[12:0]));
      endcase
   endrule

   method Action tl_cfg_add(Bit#(4) v);
      tl_cfg_add_wires <= v;
   endmethod

   method Action tl_cfg_ctl(Bit#(32) v);
      tl_cfg_ctl_wires <= v;
   endmethod

   method Action tl_cfg_sts(Bit#(53) v);
      tl_cfg_sts_wires <= v;
   endmethod

   method Action tl_cfg_ctl_wr(Bit#(1) v);
      tl_cfg_ctl_wr_wires <= v;
   endmethod

   method Action tl_cfg_sts_wr(Bit#(1) v);
      tl_cfg_sts_wr_wires <= v;
   endmethod

   method cfg_busdev;
      return pack(readVReg(cfg_busdev_wires));
   endmethod

   method cfg_devcsr;
      return pack(readVReg(cfg_devcsr_wires));
   endmethod

   method cfg_lnkcsr;
      return pack(readVReg(cfg_lnkcsr_wires));
   endmethod

   method cfg_prmcsr;
      return pack(readVReg(cfg_prmcsr_wires));
   endmethod

   method cfg_io_bas;
      return pack(readVReg(cfg_io_bas_wires));
   endmethod

   method cfg_io_lim;
      return pack(readVReg(cfg_io_lim_wires));
   endmethod

   method cfg_np_bas;
      return pack(readVReg(cfg_np_bas_wires));
   endmethod

   method cfg_np_lim;
      return pack(readVReg(cfg_np_lim_wires));
   endmethod

   method cfg_pr_bas;
      return pack(readVReg(cfg_pr_bas_wires));
   endmethod

   method cfg_pr_lim;
      return pack(readVReg(cfg_pr_lim_wires));
   endmethod

   method cfg_tcvcmap;
      return pack(readVReg(cfg_tcvcmap_wires));
   endmethod

   method cfg_msicsr;
      return pack(readVReg(cfg_msicsr_wires));
   endmethod
endmodule