Sphinx HDL Diagrams

sphinx-hdl-diagrams is an extension to Sphinx to make it easier to write nice documentation from HDL source files, in the form of Verilog, nMigen, or RTLIL code.

You use the .. hdl-diagram RST directive to generate various styles of diagrams from HDL code.

Most of the time there will be a license header at the top of source code, which we might not want to show in the documentation. This extension also provides the .. no-license RST directive which works exactly like the .. literalinclude directive, but the lines option is overridden to only show the lines after the license header.

The project repository is hosted on GitHub.

Installation

Python 3.5+ is required.

pip install sphinxcontrib-hdl-diagrams

Or,

python3 -m pip install sphinxcontrib-hdl-diagrams

Sphinx integration

In your conf.py, add the following lines.

extensions = [
   ...,
   'sphinxcontrib_hdl_diagrams',
]

Non-python dependencies

These dependencies can either be installed on your system or you can install them using the conda environment.yml file.

Usage

hdl-diagram

The hdl-diagram RST directive can be used to generate a diagram from HDL code and include it in your documentation.

.. hdl-diagram:: file.v
   :type: XXXXX
   :module: XXXX
   :flatten:

Options

:type: - Verilog Diagram Types;

  • yosys-blackbox - Netlist rendered by Yosys.

  • yosys-aig - Verilog file run through aigmap before image is generated directly in Yosys.

  • netlistsvg - Render output with netlistsvg

:module: - Which module to diagram.

:flatten: - Use the Yosys flatten command before generating the image.

no-license

The no-license RST directive can be used to include code without license headers.

.. no-license:: file.v
   :language: verilog
   :linenos:
   :caption: examples/verilog/dff.v

Options

This directive merely overrides the lines and lineno-start options of the literalinclude directive. So, refer to literalinclude for the available options.

Directives
hdl-diagram

The hdl-diagram RST directive can be used to generate a diagram from HDL code and include it in your documentation.

.. hdl-diagram:: file.v
   :type: XXXXX
   :module: XXXX
   :flatten:

Note

The verilog-diagram directive is kept as an alias of this directive for compatibility purposes.

Options

:type: - Verilog Diagram Types;

  • yosys-blackbox - Netlist rendered by Yosys.

  • yosys-aig - Verilog file run through aigmap before image is generated directly in Yosys.

  • netlistsvg - Render output with netlistsvg

:module: - Which module to diagram.

:flatten: - Use the Yosys flatten command before generating the image.

Input Formats

This directive supports 3 input formats: Verilog code, nMigen code, and RTLIL.

Verilog
19module top (
20	input  clk,
21	output o
22);
23	reg [2:0] counter = 0;
24	always @(posedge clk)
25		counter <= counter + 1;
26	assign o = counter[2];
27endmodule
1.. hdl-diagram:: ../code/verilog/counter.v
2   :type: netlistsvg
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/counter.v
nMigen
21from nmigen import *
22from nmigen.back import rtlil
23
24
25class Counter(Elaboratable):
26    def __init__(self, width):
27        self.v = Signal(width, reset=2**width-1)
28        self.o = Signal()
29
30    def elaborate(self, platform):
31        m = Module()
32        m.d.sync += self.v.eq(self.v + 1)
33        m.d.comb += self.o.eq(self.v[-1])
34        return m
35
36
37ctr = Counter(width=16)
38print(rtlil.convert(ctr, ports=[ctr.o]))
1.. hdl-diagram:: ../code/nmigen/counter.py
2   :type: netlistsvg
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/nmigen/counter.py

Note

As hdl-diagram expects the nMigen script to write RTLIL code to stdout, make sure to include the following lines of code.

1from nmigen.back import rtlil
2print(rtlil.convert(..., ports=[...]))
RTLIL
 1attribute \generator "nMigen"
 2attribute \top 1
 3attribute \nmigen.hierarchy "top"
 4module \top
 5  attribute \src "counter.py:9"
 6  wire width 1 output 0 \o
 7  attribute \src "/usr/local/lib/python3.7/site-packages/nmigen/hdl/ir.py:526"
 8  wire width 1 input 1 \clk
 9  attribute \src "/usr/local/lib/python3.7/site-packages/nmigen/hdl/ir.py:526"
10  wire width 1 input 2 \rst
11  attribute \src "counter.py:8"
12  wire width 16 \v
13  attribute \src "counter.py:8"
14  wire width 16 \v$next
15  attribute \src "counter.py:13"
16  wire width 17 $1
17  attribute \src "counter.py:13"
18  wire width 17 $2
19  attribute \src "counter.py:13"
20  cell $add $3
21    parameter \A_SIGNED 1'0
22    parameter \A_WIDTH 5'10000
23    parameter \B_SIGNED 1'0
24    parameter \B_WIDTH 1'1
25    parameter \Y_WIDTH 5'10001
26    connect \A \v
27    connect \B 1'1
28    connect \Y $2
29  end
30  connect $1 $2
31  process $group_0
32    assign \v$next \v
33    assign \v$next $1 [15:0]
34    attribute \src "/usr/local/lib/python3.7/site-packages/nmigen/hdl/xfrm.py:530"
35    switch \rst
36      case 1'1
37        assign \v$next 16'1111111111111111
38    end
39    sync init
40      update \v 16'1111111111111111
41    sync posedge \clk
42      update \v \v$next
43  end
44  process $group_1
45    assign \o 1'0
46    assign \o \v [15]
47    sync init
48  end
49end
1.. hdl-diagram:: ../code/rtlil/counter.il
2   :type: netlistsvg
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/rtlil/counter.il
Diagram Types
Yosys BlackBox Diagram
RST Directive
1.. hdl-diagram:: ../code/verilog/dff.v
2   :type: yosys-bb
Result
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/dff.v
Yosys AIG Diagram
RST Directive
1.. hdl-diagram:: ../code/verilog/dff.v
2   :type: yosys-aig
Result
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/dff.v
NetlistSVG Diagram
RST Directive
1.. hdl-diagram:: ../code/verilog/dff.v
2   :type: netlistsvg
Result
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/dff.v
no-license

The no-license RST directive can be used to include code without license headers.

.. no-license:: file.v
   :language: verilog
   :linenos:
   :caption: examples/verilog/dff.v
Options

This directive merely overrides the lines and lineno-start options of the literalinclude directive. So, refer to literalinclude for the available options.

Example
Verilog Code Block (with license header)
RST Directive
1.. literalinclude:: ../code/verilog/dff.v
2   :language: verilog
3   :linenos:
Result
 1/*
 2 * Copyright (C) 2020-2021  The SymbiFlow Authors.
 3 *
 4 * Licensed under the Apache License, Version 2.0 (the "License");
 5 * you may not use this file except in compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *     https://www.apache.org/licenses/LICENSE-2.0
 9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * SPDX-License-Identifier: Apache-2.0
17 */
18
19// Single flip-flip test.
20module top(input clk, input di, output do);
21  always @( posedge clk )
22    do <= di;
23endmodule // top
Verilog Code Block (without license header)
RST Directive
1.. no-license:: ../code/verilog/dff.v
2   :language: verilog
3   :linenos:
Result
19// Single flip-flip test.
20module top(input clk, input di, output do);
21  always @( posedge clk )
22    do <= di;
23endmodule // top
Examples
Combinational Full Adder
Verilog Code
RST Directive
1.. no-license:: ../code/verilog/adder.v
2   :language: verilog
3   :linenos:
Result
19module ADDER (
20	a, b, cin,
21	sum, cout
22);
23	input wire a;
24	input wire b;
25	input wire cin;
26
27	output wire sum;
28	output wire cout;
29
30	// Full adder combinational logic
31	assign sum = a ^ b ^ cin;
32	assign cout = ((a ^ b) & cin) | (a & b);
33endmodule
Yosys BlackBox Diagram
RST Directive
1.. hdl-diagram:: ../code/verilog/adder.v
2   :type: yosys-bb
3   :module: ADDER
Result
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/adder.v
Yosys AIG Diagram
RST Directive
1.. hdl-diagram:: ../code/verilog/adder.v
2   :type: yosys-aig
3   :module: ADDER
Result
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/adder.v
NetlistSVG Diagram
RST Directive
1.. hdl-diagram:: ../code/verilog/adder.v
2   :type: netlistsvg
3   :module: ADDER
Result
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/adder.v
CARRY4 example for Series 7 FPGA
CARRY4 defined directly
19module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
20  assign O = S ^ {CO[2:0], CI | CYINIT};
21  assign CO[0] = S[0] ? CI | CYINIT : DI[0];
22  assign CO[1] = S[1] ? CO[0] : DI[1];
23  assign CO[2] = S[2] ? CO[1] : DI[2];
24  assign CO[3] = S[3] ? CO[2] : DI[3];
25endmodule
1.. hdl-diagram:: ../code/verilog/carry4-whole.v
2   :type: netlistsvg
3   :module: CARRY4
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/carry4-whole.v
CARRY4 defined by components
19`include "muxcy.v"
20`include "xorcy.v"
21
22module CARRY4(output [3:0] CO, O, input CI, CYINIT, input [3:0] DI, S);
23   wire CIN = CI | CYINIT;
24
25   MUXCY muxcy0 (.O(CO[0]), .CI(CIN),   .DI(DI[0]), .S(S[0]));
26   MUXCY muxcy1 (.O(CO[1]), .CI(CO[0]), .DI(DI[1]), .S(S[1]));
27   MUXCY muxcy2 (.O(CO[2]), .CI(CO[1]), .DI(DI[2]), .S(S[2]));
28   MUXCY muxcy3 (.O(CO[3]), .CI(CO[2]), .DI(DI[3]), .S(S[3]));
29
30   XORCY xorcy0 (.O(O[0]), .CI(CIN),   .LI(S[0]));
31   XORCY xorcy1 (.O(O[1]), .CI(CO[0]), .LI(S[1]));
32   XORCY xorcy2 (.O(O[2]), .CI(CO[1]), .LI(S[2]));
33   XORCY xorcy3 (.O(O[3]), .CI(CO[2]), .LI(S[3]));
34endmodule
19module MUXCY(output O, input CI, DI, S);
20  assign O = S ? CI : DI;
21endmodule
19module XORCY(output O, input CI, LI);
20  assign O = CI ^ LI;
21endmodule
MUXCY
1.. hdl-diagram:: ../code/verilog/muxcy.v
2   :type: netlistsvg
3   :caption: muxcy.v
4   :module: MUXCY
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/muxcy.v

muxcy.v

XORCY
1.. hdl-diagram:: ../code/verilog/xorcy.v
2   :type: netlistsvg
3   :caption: xorcy.v
4   :module: XORCY
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/xorcy.v

xorcy.v

CARRY4 without flatten
1.. hdl-diagram:: ../code/verilog/carry4-bits.v
2   :type: netlistsvg
3   :module: CARRY4
4   :caption: carry4-bits.v without flatten
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/carry4-bits.v

carry4-bits.v without flatten

CARRY4 with flatten
1.. hdl-diagram:: ../code/verilog/carry4-bits.v
2   :type: netlistsvg
3   :module: CARRY4
4   :flatten:
5   :caption: carry4-bits.v with flatten
/home/docs/checkouts/readthedocs.org/user_builds/mithro-sphinxcontrib-verilog-diagrams/checkouts/latest/docs/code/verilog/carry4-bits.v

carry4-bits.v with flatten