// DESCRIPTION: Verilator: FSM coverage supports wide sparse state values
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0

module t (
    input logic clk
);

  typedef enum logic [39:0] {
    E_S0_IDLE = 40'h0000_0000_01,
    E_S1_BUSY = 40'h8000_0000_02,
    E_S2_DONE = 40'hffff_0000_03
  } enum_state_t;

  localparam logic [47:0] L_S0_IDLE = 48'h0000_0000_0001;
  localparam logic [47:0] L_S1_BUSY = 48'h8000_0000_0002;
  localparam logic [47:0] L_S2_DONE = 48'hffff_0000_0003;

  enum_state_t enum_state  /*verilator fsm_reset_arc*/;
  logic rst;
  logic start;
  integer cyc;
  logic [39:0] forced_state  /*verilator fsm_state*/;
  logic [39:0] forced_case_if_state  /*verilator fsm_state*/;
  logic [47:0] param_state_q;
  logic [47:0] param_state_d;

  initial begin
    rst = 1'b1;
    start = 1'b0;
    cyc = 0;
  end

  always @(posedge clk) begin
    cyc <= cyc + 1;
    if (cyc == 1) rst <= 1'b0;
    if (cyc == 2) start <= 1'b1;
    if (cyc == 3) start <= 1'b0;
    if (cyc == 8) begin
      $write("*-* All Finished *-*\n");
      $finish;
    end
  end

  always_ff @(posedge clk) begin
    if (rst) begin
      enum_state <= E_S0_IDLE;
    end
    else begin
      case (enum_state)
        E_S0_IDLE: enum_state <= start ? E_S1_BUSY : E_S0_IDLE;
        E_S1_BUSY: enum_state <= E_S2_DONE;
        default: enum_state <= E_S0_IDLE;
      endcase
    end
  end

  always_ff @(posedge clk) begin
    if (rst) begin
      forced_state <= 40'h0000_0000_01;
    end
    else begin
      case (forced_state)
        40'h0000_0000_01: forced_state <= start ? 40'h8000_0000_02 : 40'h0000_0000_01;
        40'h8000_0000_02: forced_state <= 40'hffff_0000_03;
        default: forced_state <= 40'h0000_0000_01;
      endcase
    end
  end

  always_ff @(posedge clk) begin
    if (rst) begin
      forced_case_if_state <= 40'h0000_0000_01;
    end
    else begin
      case (forced_case_if_state)
        40'h0000_0000_01: begin
          if (start) begin
            forced_case_if_state <= 40'h8000_0000_02;
          end
          else begin
            forced_case_if_state <= 40'h0000_0000_01;
          end
        end
        40'h8000_0000_02: forced_case_if_state <= 40'h0000_0000_01;
        default: forced_case_if_state <= 40'h0000_0000_01;
      endcase
    end
  end
  always_comb begin
    param_state_d = param_state_q;
    if (param_state_q == L_S0_IDLE) begin
      param_state_d = start ? L_S1_BUSY : L_S0_IDLE;
    end
    else if (param_state_q == L_S1_BUSY) begin
      param_state_d = L_S2_DONE;
    end
    else if (param_state_q == L_S2_DONE) begin
      param_state_d = L_S0_IDLE;
    end
  end

  always_ff @(posedge clk) begin
    if (rst) begin
      param_state_q <= L_S0_IDLE;
    end
    else begin
      param_state_q <= param_state_d;
    end
  end

endmodule
