Why
There are many pieces of software around to design and simulate FSM, I didn’t need any of that. By their structure, writing FSM code is somewhat tedious and repetitive and, whenever I do, I manage to make a lot of mistakes, also reading back after some time its flow and behavior is sometimes a little difficult. What I wanted was a very quick and dirty tool that could write more verbose HDL code from a cleaner description, and this is exactly what I did.
How
The Python script takes as input a JSON file, with some general information (name of the entity/module to produce, reset active high or low), input ports, output ports and a list of states. For each state you can write the value for the output signals and the conditions for which it will change to the next state.
Warning: since I mostly use VHDL in my projects, this script works very well in generating VHDL code but, although it is designed to also generate Verilog and SystemVerilog code, as of now Verilog is not implemented, and SystemVerilog code isn’t generated well. The most difficult part is creating a JSON syntax that can easily be translated in all the three languages. Some examples:
- logic types are completely different among them. I chose to use the SystemVerilog
logicsyntax since it’s the one I find more general and compact. The script will convert it to VHDL usingstd_logicandstd_logic_vector - string literals require some transformation, but I think work mostly well
- conditional change of states based on input signals are instead more trick; as of now, the script uses the VHDL syntax and is unable to translate to SystemVerilog code, this will be changed in the future
As always, I’m open to suggestions and contributions, feel free to make a pull request :)
Example
Let’s consider the classic example of an FSM with a single input and a single output, that is true when the input has been true for the last two clock cycles (basically it recognizes the sequence “11”).

This particular FSM can be described with the following JOSN file.
{
"name": "recognize_sequence_10",
"reset": "high",
"in":
{
"w": "logic"
},
"out":
{
"z": ["logic", 0]
},
"states":
{
"A":
{
"next":
{
"B": "w = '1'"
}
},
"B":
{
"next":
{
"C": "w = '1'",
"A": "w = '0'"
}
},
"C":
{
"out": {"z": 1},
"next":
{
"A": "w = '0'"
}
}
}
}
And the script will generate the following VHDL file. See the README.md file in the attached repository for more detail on the syntax and the command to generate the file.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--------------------------------------------------------------------------------
-- this VHDL file has been generated automatically from a template --
-- DO NOT modify manually !!! --
--------------------------------------------------------------------------------
entity recognize_sequence_10 is
port(
clk : in std_logic;
rst : in std_logic;
w : in std_logic;
z : out std_logic
);
end entity;
architecture fsm of recognize_sequence_10 is
type FSMState_t is (A, B, C);
signal fsm_state : FSMState_t := A;
begin
fsm_proc: process(clk, rst) is
begin
if rst = '1' then
fsm_state <= A;
z <= '0';
elsif rising_edge(CLK) then
-- default assignments
z <= '0';
case fsm_state is
-- case A
when A =>
if (w = '1') then
fsm_state <= B;
end if;
-- case B
when B =>
if (w = '1') then
fsm_state <= C;
elsif (w = '0') then
fsm_state <= A;
end if;
-- case C
when C =>
z <= '1';
if (w = '0') then
fsm_state <= A;
end if;
end case;
end if;
end process;
end architecture;