import byucc.jhdl.base.CellInterface;
import byucc.jhdl.base.Node;
import byucc.jhdl.base.Wire;
import byucc.jhdl.Logic.Logic;
import byucc.jhdl.Xilinx.Virtex.ibuf;
import byucc.jhdl.Xilinx.Virtex.ibufg;
import byucc.jhdl.Xilinx.Virtex.bufg;
import byucc.jhdl.Xilinx.Virtex.obuf;
/** Design to be used with tbCustomClockCell to demonstrate use of
 * user-defined clocks and tri-state bus wires with Stimulators
 * @author Anthony L. Slade */
public class CustomClockCell extends Logic {
  public static final int WIRE_WIDTH = 4;
  public static CellInterface cell_interface[] = {
    in("clk",1),
    in("inputA",WIRE_WIDTH),
    in("inputB",WIRE_WIDTH),
    in("enable",1),
    out("output",WIRE_WIDTH)
  };
  public CustomClockCell(Node parent,Wire inClk,
			 Wire inAWire,Wire inBWire,
			 Wire inEnable,Wire outWire) {
    super(parent);
    Wire clk = connect("clk",inClk);
    Wire inputA = connect("inputA",inAWire);
    Wire inputB = connect("inputB",inBWire);
    Wire enable = connect("enable",inEnable);
    Wire output = connect("output",outWire);

    Wire inputA_buf = wire(WIRE_WIDTH,"inputA_buf");
    Wire inputB_buf = wire(WIRE_WIDTH,"inputB_buf");

    Wire and_out = and(inputA_buf,inputB_buf);

    Wire clk_ibuf_buf = this.wire(1,"clk_ibuf_buf");
    Wire clk_ibuf = this.wire(1,"clk_ibuf");
    ibufg ibg = new ibufg(this,"clk_ibg",clk,clk_ibuf);
    bufg bg = new bufg(this,"clk_bg",clk_ibuf,clk_ibuf_buf);
    ibg.isSimulateable(true);
    bg.isSimulateable(false);

    // This is where we add a custom, user-defined clock:
    this.clockDriver(clk_ibuf_buf,"11110000","customDefaultClk");
    setDefaultClock(clk_ibuf_buf);

    Wire reg_out = regce(clk_ibuf_buf,and_out,enable,"and_reg");

    for ( int wi = 0; wi < WIRE_WIDTH; ++wi ) {
      new ibuf(this,"inputA_buffer"+wi,inputA.gw(wi),inputA_buf.gw(wi));
      new ibuf(this,"inputB_buffer"+wi,inputB.gw(wi),inputB_buf.gw(wi));
      new obuf(this,"output_obuf"+wi,reg_out.gw(wi),output.gw(wi));
    }
  }
}

