FSM viewer: Verilog and SystemVerilog code to state diagram

Paste a state machine in Verilog or SystemVerilog and see its state diagram, live, beside your code, every state and arrow linked to its lines.

Limit
64 KiB and 32 states read; long names draw fewer
Published
Authorship
Drafted with AI assistance, reviewed by İsmail

Read this page in Turkish

One module of Verilog or SystemVerilog, up to 64 KiB.

sequence_detector: 5 states, 10 transitions, binary codes.

sig_inline 37!sig_inline 38!sig_insig_insig_in!sig_inline 46sig_inline 49!sig_inline 50!sig_inline 53sig_inline 54rst_nlines 23–29IDLES1S10S101lines 48–51S1011found=1

Run plays this scenario from the start; driving an input continues from here.

A state machine that runs: a state diagram and its waveform on one time axis. Inputs: rst_n, sig_in. Outputs: found. clk runs at 8 ticks a period. It has 5 states, IDLE, S1, S10, S101 and S1011, and starts in IDLE on reset; 10 transitions. The waveform shows clk, rst_n, sig_in, state, found.

Figure 1. Press Run: the reset holds sequence_detector in IDLE, then lets it go; drive the inputs with the buttons under the drawing.

sequence_detector.sv
// Detects the bit sequence 1011 on sig_in, with overlap: 1011011 is found twice.
//
// Reset style for this module: asynchronous, active low. One style per page,
// stated up front, so nothing on the page has to be read twice.
module sequence_detector (
    input  logic clk,
    input  logic rst_n,
    input  logic sig_in,
    output logic found
);

  typedef enum logic [2:0] {
    IDLE  = 3'd0,
    S1    = 3'd1,
    S10   = 3'd2,
    S101  = 3'd3,
    S1011 = 3'd4
  } state_t;

  state_t state, next;

  // The state register: the only flip-flops in the module.
  always_ff @(posedge clk or negedge rst_n) begin
    if (!rst_n) begin
      state <= IDLE;
    end else begin
      state <= next;
    end
  end

  // Next state. The default assignment holds the state when no branch fires,
  // so no arm can leave a latch behind.
  always_comb begin
    next = state;
    unique case (state)
      IDLE: begin
        if (sig_in) next = S1;
        else if (!sig_in) next = IDLE;
      end
      S1: begin
        if (!sig_in) next = S10;
        else if (sig_in) next = S1;
      end
      S10: begin
        if (sig_in) next = S101;
        else if (!sig_in) next = IDLE;
      end
      S101: begin
        if (sig_in) next = S1011;
        else if (!sig_in) next = S10;
      end
      S1011: begin
        if (!sig_in) next = S10;
        else if (sig_in) next = S1;
      end
      default: next = IDLE;
    endcase
  end

  // Moore output: a function of the state alone.
  always_comb begin
    found = 1'b0;
    unique case (state)
      S1011:   found = 1'b1;
      default: found = 1'b0;
    endcase
  end

endmodule

How to read the result

The drawing is your module read back. Each stadium is a state, named as your code names it, with its Moore outputs under the name. Each arrow is a transition, labelled with its condition as the code tests it and, on a Mealy machine, with the outputs it drives on the way. The short arrow into one state is the reset.

The drawing and the code are linked both ways. Point at a state, or reach it from the keyboard, and the lines that make it light up in your code beside the figure: the arm of the case for a state, the branch of its if for an arrow, the port's line for an input's button. Point at a line and its part of the drawing lights.

The figure runs one scenario, Reset. Press Run: the reset holds the machine in its reset state, from the start if the reset is asynchronous and from the first clock edge if it is synchronous, and then lets it go. From there you drive the inputs with the buttons under the drawing, and the waveform records every edge: the clock, the reset, the inputs, the state and the outputs, the first twelve of them.

When the layout cannot draw a machine, two tables take the figure's place: the states with their outputs, and the transitions with their conditions, each row lighting its lines as a part of a drawing does. The sentence above them says why, in the layout's own terms: how many grid units the states need, or which label found no room.

What it reads

One module, in SystemVerilog or Verilog: a state register reset under if (rst) or if (!rst_n), synchronous or asynchronous and whatever the reset is called, the next state computed in a combinational block or in the clocked block itself, and outputs assigned per state or per transition. The styles of the textbooks and the courses read: parameter codes in Verilog-1995, parameter and localparam codes in Verilog-2001, an enum in SystemVerilog, one, two or three processes, state names in any case and up to 24 characters, and binary, Gray and one-hot codes.

It reads exactly or not at all. The condition on an arrow is the condition under which your code takes that branch, worked out over every path through the state's code, never a guess at what the code meant. To hold it to that, every machine of the tool's test corpus that it reads was run on the same inputs in Icarus Verilog, from its own code, and in the figure's engine, from the drawing: three runs of 220 clock periods with resets among them, the state and every output compared at every tick, with no difference.

What it does not read, and what to do

Code it cannot read is refused by name, at its line and column, and Go to line selects it in the field. The commonest refusal is a second register beside the state: a counter, a timer, a flag. The figure's conditions are the machine's inputs, so a machine that reads its own counter has no drawing that would be true of it. Make what the machine reads of the counter an input, count_done rather than count == 4'd9, and paste it again. A bit select in a condition, and an encoding of your own, codes in an order that is not binary, Gray or one-hot, are refused the same way, each sentence saying what the viewer reads instead.

Limits

The field takes 64 KiB. The viewer reads up to 32 states, 8 inputs and 8 outputs, and state names of up to 24 characters. Signal names are lowercase letters, digits and _, and a vector is ranged [msb:0]: a textbook that writes Clock or reg [2:1] y is refused at that line. A link to your code holds 3,900 characters, which every machine in the corpus fits; a longer module can be pasted but not linked.

How much draws depends on the names more than on the number of states. Of the 42 machines in the corpus the viewer reads, 24 draw, all of them of 2 to 6 states, and the rest show as tables: long port names make long arrow labels, and long output names make wide stadiums.

Your code never leaves the page. The reading and the drawing happen in your browser, and a link is made only when you ask for one.

Found an error? Send a correction