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

module t (  /*AUTOARG*/
    // Inputs
    clk,
    fastclk
);

  input clk;
  input fastclk;
  reg reset_l;

  int cyc;
  initial reset_l = 0;
  always @(posedge clk) begin
    if (cyc == 0) reset_l <= 1'b1;
    else if (cyc == 1) reset_l <= 1'b0;
    else if (cyc == 10) reset_l <= 1'b1;
  end

  t_clk t (  /*AUTOINST*/
      // Inputs
      .clk(clk),
      .fastclk(fastclk),
      .reset_l(reset_l)
  );
endmodule

module t_clk (  /*AUTOARG*/
    // Inputs
    clk,
    fastclk,
    reset_l
);

  input clk;
  input fastclk;
  input reset_l;

  // surefire lint_off STMINI
  // surefire lint_off CWECSB
  // surefire lint_off NBAJAM
  reg _ranit;
  initial _ranit = 0;
  // surefire lint_off UDDSMX
  reg [7:0] clk_clocks;
  initial clk_clocks = 0;  // surefire lint_off_line WRTWRT
  wire [7:0] clk_clocks_d1r;
  wire [7:0] clk_clocks_d1sr;
  wire [7:0] clk_clocks_cp2_d1r;
  wire [7:0] clk_clocks_cp2_d1sr;
  // verilator lint_off MULTIDRIVEN
  reg [7:0] int_clocks;
  initial int_clocks = 0;
  // verilator lint_on MULTIDRIVEN
  reg [7:0] int_clocks_copy;

  reg internal_clk;
  initial internal_clk = 0;
  reg reset_int_;

  always @(posedge clk) begin
`ifdef TEST_VERBOSE
    $write("[%0t] CLK1 %x\n", $time, reset_l);
`endif
    if (!reset_l) begin
      clk_clocks <= 0;
      int_clocks <= 0;
      internal_clk <= 1'b1;
      reset_int_ <= 0;
    end
    else begin
      internal_clk <= ~internal_clk;
      if (!_ranit) begin
        _ranit <= 1;
`ifdef TEST_VERBOSE
        $write("[%0t] t_clk: Running\n", $time);
`endif
        reset_int_ <= 1;
      end
    end
  end

  reg [7:0] sig_rst;
  always @(posedge clk or negedge reset_l) begin
`ifdef TEST_VERBOSE
    $write("[%0t] CLK2 %x sr=%x\n", $time, reset_l, sig_rst);
`endif
    if (!reset_l) begin
      sig_rst <= 0;
    end
    else begin
      sig_rst <= sig_rst + 1;  // surefire lint_off_line ASWIBB
    end
  end

  always @(posedge clk) begin
`ifdef TEST_VERBOSE
    $write("[%0t] CLK3 %x cc=%x sr=%x\n", $time, reset_l, clk_clocks, sig_rst);
`endif
    if (!reset_l) begin
      clk_clocks <= 0;
    end
    else begin
      clk_clocks <= clk_clocks + 8'd1;
      if (clk_clocks == 4) begin
        if (sig_rst !== 4) $stop;
        if (clk_clocks_d1r !== 3) $stop;
        if (int_clocks !== 2) $stop;
        if (int_clocks_copy !== 2) $stop;
        if (clk_clocks_d1r !== clk_clocks_cp2_d1r) $stop;
        if (clk_clocks_d1sr !== clk_clocks_cp2_d1sr) $stop;
        $write("*-* All Finished *-*\n");
        $finish;
      end
    end
  end

  reg [7:0] resetted;
  always @(posedge clk or negedge reset_int_) begin
`ifdef TEST_VERBOSE
    $write("[%0t] CLK4 %x\n", $time, reset_l);
`endif
    if (!reset_int_) begin
      resetted <= 0;
    end
    else begin
      resetted <= resetted + 8'd1;
    end
  end

  always @(int_clocks) begin
    int_clocks_copy = int_clocks;
  end

  always @(negedge internal_clk) begin
    int_clocks <= int_clocks + 8'd1;
  end

  t_clk_flop flopa (
      .clk(clk),
      .clk2(fastclk),
      .a(clk_clocks),
      .q(clk_clocks_d1r),
      .q2(clk_clocks_d1sr)
  );
  t_clk_flop flopb (
      .clk(clk),
      .clk2(fastclk),
      .a(clk_clocks),
      .q(clk_clocks_cp2_d1r),
      .q2(clk_clocks_cp2_d1sr)
  );
  t_clk_two two (  /*AUTOINST*/
      // Inputs
      .fastclk(fastclk),
      .reset_l(reset_l)
  );

endmodule

module t_clk_flop (  /*AUTOARG*/
    // Outputs
    q,
    q2,
    // Inputs
    clk,
    clk2,
    a
);
  parameter WIDTH = 8;
  input clk;
  input clk2;
  input [(WIDTH-1):0] a;
  output [(WIDTH-1):0] q;
  output [(WIDTH-1):0] q2;
  reg [(WIDTH-1):0] q;
  reg [(WIDTH-1):0] q2;
  always @(posedge clk) q <= a;
  always @(posedge clk2) q2 <= a;
endmodule

module t_clk_two (  /*AUTOARG*/
    // Inputs
    fastclk,
    reset_l
);
  input fastclk;
  input reset_l;
  reg clk2;
  reg [31:0] count;

  t_clk_twob tb (.*);

  wire reset_h = ~reset_l;
  always @(posedge fastclk) begin
    if (reset_h) clk2 <= 0;
    else clk2 <= ~clk2;
  end
  always @(posedge clk2) begin
    if (reset_h) count <= 0;
    else count <= count + 1;
  end
endmodule

module t_clk_twob (  /*AUTOARG*/
    // Inputs
    fastclk,
    reset_l
);
  input fastclk;
  input reset_l;

  always @(posedge fastclk) begin
    // Extra line coverage point, just to make sure coverage
    // hierarchy under inlining lands properly
    if (reset_l);
  end
endmodule
