Update 2021-03-29: netlistsvg has been updated by yours truly to fix some of the bugs that required workarounds in this blog post. This has been updated to remove those workarounds as they’re no longer required for the latest version of netlistsvg. A blog post about those changes is available here.
Block diagrams are a useful way of presenting state machines and other HDL code in a visual manner. They are useful for learning how the code works, documenting it for future programmers and reports, or debugging code that may not be working as expected.
While tools for generating block diagrams are already included in most HDL development environments, these are typically proprietary (though they may be free as in beer, they’re not free as in freedom). Here is how to generate a block diagram from VHDL using netlistsvg and the open source FPGA toolchain on Linux.
I would recommend downloading the latest FPGA toolchain binaries provided by Open Tool Forge here (or if you’re on an Arch-based distro, it’s available from the AUR as
fpga-toolchain-bin). Make sure to
export GHDL_PREFIX=$install_dir/lib/ghdl to wherever you installed the toolchain, and add the toolchain to your
netlistsvg is available via npm, and can be installed by running
npm install netlistsvg.
The procedure is as follows:
- Use GHDL to analyze and synthesize all of the source files. This is done by doing
ghdl -a *.vhdlassuming all of your files are in the same directory, and end with the
- For each of the VHDL entities for which a block diagram is needed:
- Use Yosys and ghdl-yosys-plugin to create the netlist for that entity
- Use netlistsvg to generate the SVG image
Here is an example of how to integrate this into a Makefile:
ENTITY=top alu counter simulate: ghdl -a *.vhdl svg: @$(MAKE) simulate -mkdir svg for en in $(ENTITY); do \ yosys -p "ghdl $$en; prep -top $$en; write_json -compat-int svg.json"; \ netlistsvg svg.json -o svg/$$en.svg; \ done
Here is another example of how to integrate this into a bash script:
export ENTITY=top alu counter ghdl -a *.vhdl mkdir svg for entity in $ENTITY; do yosys -p "ghdl $$entity; prep -top $$entity; write_json -compat-int svg.json"; netlistsvg svg.json -o svg/$$entity.svg; done
For both of these, replace
ENTITY=top alu counter with the list of entities you want to make block diagrams for.
Here’s an example from my blog post about running VGA on the Upduino FPGA:
library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity vga is port ( Clk : in std_logic; row, col : out unsigned(10 downto 0); HSYNC, VSYNC : out std_logic ); end vga; architecture synth of vga is signal H_A, H_F, H_S, H_B, H_T : integer := 0; signal V_A, V_F, V_S, V_B, V_T : integer := 0; signal vert, hori : unsigned(10 downto 0); begin -- 49.5 MHz / 800x600 H_A <= 800; H_F <= 16; H_S <= 80; H_B <= 160; H_T <= H_A + H_F + H_S + H_B; V_A <= 600; V_F <= 1; V_S <= 3; V_B <= 21; V_T <= V_A + V_F + V_S + V_B; process (Clk) begin if (rising_edge(Clk)) then if (hori < H_T - 1) then hori <= hori + 1; else hori <= (others => '0'); if (vert < V_T - 1) then vert <= vert + 1; else vert <= (others => '0'); end if; end if; if (hori >= (H_A + H_F) and hori <= (H_A + H_F + H_S)) then hsync <= '0'; else hsync <= '1'; end if; if (vert >= (V_A + V_F) and vert <= (V_A + V_F + V_S)) then vsync <= '0'; else vsync <= '1'; end if; row <= vert; col <= hori; end if; end process; end;
And that’s it! Assuming you did everything correctly (and the tools haven’t changed) this should work for generating block diagrams from VHDL using open source tools. To note as well there’s a Sphinx extension that uses Yosys and netlistsvg to embed block diagrams, but at the time of writing only supports Verilog. Here’s an example of it in action.
Special thanks to Neil Turley for developing and maintaining netlistsvg! Also thanks to all the amazing developers behind the open source FPGA toolchain!