// // verilator_coverage annotation // 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 %000005 case (enum_state) // [FSM coverage] %000001 // [fsm_arc t.enum_state::ANY->E_S0_IDLE[reset_include]] [reset arc, excluded from %] %000005 // [fsm_arc t.enum_state::E_S0_IDLE->E_S0_IDLE] %000001 // [fsm_arc t.enum_state::E_S0_IDLE->E_S1_BUSY] %000001 // [fsm_arc t.enum_state::E_S1_BUSY->E_S2_DONE] %000002 // [fsm_state t.enum_state::E_S0_IDLE] %000001 // [fsm_state t.enum_state::E_S1_BUSY] %000001 // [fsm_state t.enum_state::E_S2_DONE] 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 %000005 case (forced_state) // [FSM coverage] %000005 // [fsm_arc t.forced_state::40'h1->40'h1] %000001 // [fsm_arc t.forced_state::40'h1->40'h8000000002] %000001 // [fsm_arc t.forced_state::40'h8000000002->40'hffff000003] %000001 // [fsm_arc t.forced_state::ANY->40'h1[reset]] [reset arc, excluded from %] %000002 // [fsm_state t.forced_state::40'h1] %000001 // [fsm_state t.forced_state::40'h8000000002] %000001 // [fsm_state t.forced_state::40'hffff000003] 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 %000006 case (forced_case_if_state) // [FSM coverage] %000006 // [fsm_arc t.forced_case_if_state::40'h1->40'h1] %000001 // [fsm_arc t.forced_case_if_state::40'h1->40'h8000000002] %000001 // [fsm_arc t.forced_case_if_state::40'h8000000002->40'h1] %000001 // [fsm_arc t.forced_case_if_state::ANY->40'h1[reset]] [reset arc, excluded from %] %000002 // [fsm_state t.forced_case_if_state::40'h1] %000001 // [fsm_state t.forced_case_if_state::40'h8000000002] 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; %000005 if (param_state_q == L_S0_IDLE) begin // [FSM coverage] %000001 // [fsm_arc t.param_state_q::ANY->L_S0_IDLE[reset]] [reset arc, excluded from %] %000005 // [fsm_arc t.param_state_q::L_S0_IDLE->L_S0_IDLE] %000001 // [fsm_arc t.param_state_q::L_S0_IDLE->L_S1_BUSY] %000001 // [fsm_arc t.param_state_q::L_S1_BUSY->L_S2_DONE] %000001 // [fsm_arc t.param_state_q::L_S2_DONE->L_S0_IDLE] %000002 // [fsm_state t.param_state_q::L_S0_IDLE] %000001 // [fsm_state t.param_state_q::L_S1_BUSY] %000001 // [fsm_state t.param_state_q::L_S2_DONE] 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