// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2005 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0

module t (
    clk
);
  input clk;

  reg [0:0] d1;
  reg [2:0] d3;
  reg [7:0] d8;

  wire [0:0] q1;
  wire [2:0] q3;
  wire [7:0] q8;

  reg ena;

  condff #(12) condff (
      .clk(clk),
      .sen(1'b0),
      .ena(ena),
      .d({d8, d3, d1}),
      .q({q8, q3, q1})
  );

  integer cyc;
  initial cyc = 1;
  always @(posedge clk) begin
    if (cyc != 0) begin
      //$write("%x %x %x %x\n", cyc, q8, q3, q1);
      cyc <= cyc + 1;
      if (cyc == 1) begin
        d1 <= 1'b1;
        d3 <= 3'h1;
        d8 <= 8'h11;
        ena <= 1'b1;
      end
      if (cyc == 2) begin
        d1 <= 1'b0;
        d3 <= 3'h2;
        d8 <= 8'h33;
        ena <= 1'b0;
      end
      if (cyc == 3) begin
        d1 <= 1'b1;
        d3 <= 3'h3;
        d8 <= 8'h44;
        ena <= 1'b1;
        if (q8 != 8'h11) $stop;
      end
      if (cyc == 4) begin
        d1 <= 1'b1;
        d3 <= 3'h4;
        d8 <= 8'h77;
        ena <= 1'b1;
        if (q8 != 8'h11) $stop;
      end
      if (cyc == 5) begin
        d1 <= 1'b1;
        d3 <= 3'h0;
        d8 <= 8'h88;
        ena <= 1'b1;
        if (q8 != 8'h44) $stop;
      end
      if (cyc == 6) begin
        if (q8 != 8'h77) $stop;
      end
      if (cyc == 7) begin
        if (q8 != 8'h88) $stop;
      end
      //
      if (cyc == 20) begin
        $write("*-* All Finished *-*\n");
        $finish;
      end
    end
  end
endmodule

module condff (
    clk,
    sen,
    ena,
    d,
    q
);
  parameter WIDTH = 1;
  input clk;

  input sen;
  input ena;
  input [WIDTH-1:0] d;
  output [WIDTH-1:0] q;

  condffimp #(
      .WIDTH(WIDTH)
  ) imp (
      .clk(clk),
      .sen(sen),
      .ena(ena),
      .d(d),
      .q(q)
  );
endmodule

module condffimp (
    clk,
    sen,
    ena,
    d,
    q
);
  parameter WIDTH = 1;
  input clk;
  input sen;
  input ena;
  input [WIDTH-1:0] d;
  output reg [WIDTH-1:0] q;
  wire gatedclk;

  clockgate clockgate (
      .clk(clk),
      .sen(sen),
      .ena(ena),
      .gatedclk(gatedclk)
  );

  always @(posedge gatedclk) begin
    if (gatedclk === 1'bX) begin
      q <= {WIDTH{1'bX}};
    end
    else begin
      q <= d;
    end
  end

endmodule

module clockgate (
    clk,
    sen,
    ena,
    gatedclk
);
  input clk;
  input sen;
  input ena;
  output gatedclk;

  reg ena_b;
  wire gatedclk = clk & ena_b;

  // verilator lint_off COMBDLY
  // verilator lint_off LATCH
  always @(clk or ena or sen) begin
    if (~clk) begin
      ena_b <= ena | sen;
    end
    else begin
      if ((clk ^ sen) === 1'bX) ena_b <= 1'bX;
    end
  end
  // verilator lint_on LATCH
  // verilator lint_on COMBDLY

endmodule
