WaveDrom-rs

This is the book for wavedrom-rs. It provides a reference on the features of wavedrom-rs and aims to be an extension of the original Hitcherhiker's Guide to WaveDrom.

This book teaches you how to generate beautiful Digital Timing Diagrams such as the one illustrated below. These diagrams are easy to edit and extend.

clkreqdonestateIdleFetchCalculateProcessReturnIdle
{
    signal: [
        { name: "clk",  wave: "p........." },
        { name: "req",  wave: "010......." },
        { name: "done", wave: "0......10." },
        {
            name: "state",
            wave: "==.=.=.==.",
            data: [ 'Idle', 'Fetch', 'Calculate', 'Process', 'Return', 'Idle' ]
        }
    ]
}

This book has sections.

  1. Installation of wavedrom-rs for different environments
  2. Capabilities of wavedrom-rs

Note on WaveDrom-js

Wavedrom-rs is a port of a JavaScript implementation with the same name. This project is not officially associated with that project, but does try to be an complete replacement for the Digital Timing Diagram part of this project.

This project currently supports all features of the JavaScript project with exception of:

  • JavaScript skins
  • Custom tspans through JsonML in headers and footers

There is currently no plan to implement these features.

In turn, wavedrom-rs improves on its JavaScript counterpart in several areas.

  • Proper handling of UTF-8 character widths
  • Minimization of SVG in several areas
  • More customization editor
  • More correct rendering of edges
  • JSON skins

Rust Crate

Wavedrom-rs can be used as a Rust crate to programmatically generate diagrams. The documentation for this can be found at docs.rs.

Command-Line Interface

There is an official Command-Line Interface for wavedrom that can easily be incorporated into scripts or workflows. This binary is available from the GitHub releases.

A binary can be downloaded from here and be put into a location corresponding to a operating system.

For Mac and Linux, /usr/bin/local is a good place to store the binary.

Compilation from source

It is possible to compile from the GitHub directory. This generates the most up-to-date binary, but may be less stable. This requires git and the Rust toolchain cargo to be installed.

git clone https://github.com/coastalwhite/wavedrom-rs
cargo install --path=./wavedrom

Editor Website

The editor website uses WebAssembly to run a only instance of wavedrom. It also allows easy customization, importation and exportation of skins. The official instance can be found here.

MdBook Preprocessor

This offers an integration for wavedrom-rs with mdbook.

Getting started

First, install the preprocessor utilizing the Rust Toolchain.

cargo install mdbook-wavedrom-rs

Then, add the preprocessor to the list of preprocessors in your mdbook configuration file book.toml.

# book.toml

[preprocessor.wavedrom-rs]

Afterwards, you should be able to add a wavedrom codeblock, which should automatically get replaced by a wavedrom-rs diagram when building the mdbook.

# Chapter 1

```wavedrom
{
    signal: [
        { name: "clk", wave: "p......." },
        { name: "pulses", wave: "0..10.10" },
    ]
}
```

Add a skin

A WaveDrom skin can be added by adding a path to a skin file in the skin property.

# book.toml

[preprocessor.wavedrom-rs]
skin = "path/to/skin.json5"

GitHub CI

To incorporate wavedrom-rs into your CI/CD workflow you can download and run the Command-Line Interface. This is done with the following code. Remember to replace the file.svg and diagram.svg with your desired input and output file.

- name: WaveDrom-rs render
  run: |
       curl -sLO https://github.com/coastalwhite/wavedrom-rs/releases/download/v0.1.0/wavedrom-x86_64-unknown-linux-gnu.tar.xz
       tar xvf wavedrom-x86_64-unknown-linux-gnu.tar.xz 
       chmod +x wavedrom-x86_64-unknown-linux-gnu/wavedrom
       mv wavedrom-x86_64-unknown-linux-gnu/wavedrom /usr/local/bin/wavedrom
       wavedrom -i file.json -o diagram.svg

The same can be done for the MdBook Preprocessor. Afterwards, it can be used by mdbook as a preprocessor.

- name: WaveDrom-rs MdBook
  run: |
       curl -sLO https://github.com/coastalwhite/wavedrom-rs/releases/download/v0.1.0/mdbook-wavedrom-rs-x86_64-unknown-linux-gnu.tar.xz
       tar xvf mdbook-wavedrom-rs-x86_64-unknown-linux-gnu.tar.xz 
       chmod +x mdbook-wavedrom-rs-x86_64-unknown-linux-gnu/mdbook-wavedrom-rs
       mv mdbook-wavedrom-rs-x86_64-unknown-linux-gnu/mdbook-wavedrom-rs /usr/local/bin/mdbook-wavedrom-rs

Signal Types

This section lists all the different signal types.

Top & Bottom

The Top and Bottom signals correspond to the logical on and off states. They are represented by a 1 and 0. Transitions to and from these states takes a certain amount of time.

{
    signal: [
        { wave: "101010101" },
        { wave: "000111110" },

        // You can create a vertical gap with an empty signal
        {},

        // You can continue a signal with '.'
        { wave: "1.0.1.0.1" },
    ]
}

Clock

Clock Signals are periodic signals. There are several ways to manage a close signal.

  • Positive edge clock with p and P
  • Negative edge clock with n and N
  • Manual positive edge or High with h or H
  • Manual negitive edge or Low with l or L

The state's case determines whether to place a edge marker.

  • Lowercase does NOT contain a edge marker
  • Uppercase does contain a edge marker

The period of a clock signal can be controlled with the period option. Any fractional period will get rounded up to an integer.

posedge clkposedge clk markedposedge clk period=2negedge clknegedge clk markednegedge clk period=2manualmanual marked
{
    signal: [
        { name: "posedge clk",          wave: "p......." },
        { name: "posedge clk marked",   wave: "P......." },
        { name: "posedge clk period=2", wave: "p.",       period: 4 },
        {},
        { name: "negedge clk",          wave: "n......." },
        { name: "negedge clk marked",   wave: "N......." },
        { name: "negedge clk period=2", wave: "n...",     period: 2 },
        {},
        { name: "manual",               wave: "hlh.l..." },
        { name: "manual marked",        wave: "HLH.L..." },
    ]
}

High Impedance & Undefined

The High Impedance is given by a z and is represented by a straight centered line. The Undefined is given by a x and is represented by hatch pattern.

A Undefined line needs to be extended with a . to avoid a transition.

dataresponse
{
    signal: [
        { name: "data",     wave: "0z..1z.x.." },
        { name: "response", wave: "0x..1x.z.." },
    ]
}

Data Types

To display general data in signal, we have the data property and several states that can contain data. The data states corresponding to the numbers 2 to 9 with different background colors. Similarly, the = state can also be used as a data state. The data property defines the data that goes into the data states. If the data property is given a string, the string is split over whitespace and filled into states. The data property can also be defined with an array.

Data states need to be extended using the . state, otherwise it is transited to a new data state.

data stateswith textabcdefghicontinuedFirst StateSecond StateThird State
{
    signal: [
        { name: "data states", wave: "023456789=0" },
        { name: "with text",   wave: "023456789=0", data: "a b c d e f g h i" },
        {},
        { name: "continued",   wave: "2..2..2....", data: [
            "First State",
            "Second State",
            "Third State",
        ]}
    ]
}

Gaps

Gaps in the signal can be added with the | state. This extends the previous signal by one and placed a gap indicator over extension cycle.

clkreqdone
{
    signal: [
        { name: "clk",  wave: "p..|.." },
        { name: "req",  wave: "010|.." },
        { name: "done", wave: "0..|10" },
    ]
}

Up & Down

The Up and Down states are used to gradually transition to a logical 1 and 0. Up and Down are represented with a u and d.

updown
{
    signal: [
        { name: "up",   wave: "0..u..0..u" },
        { name: "down", wave: "1.d.1.d..1" },
    ]
}

Signal Groups

A sequence of signals can be grouped by putting them into an array. A name / label for the group can also be added by starting the array with a string.

embedgroupABCDE
{
    signal: [
        [
            "group",
            { name: "A", wave: "p...." },
            [
                "embed",
                { name: "B", wave: "2...." },
                { name: "C", wave: "3...." },
            ],
        ],
        [
            { name: "D", wave: "4...." },
            { name: "E", wave: "5...." },
        ]
    ]
}

Header & Footer

Both the head and the foot properties can be used to add header and footer text.

Hello World!ABCDEBye World!
{
    signal: [
        { name: "A", wave: "2....." },
        { name: "B", wave: "3....." },
        { name: "C", wave: "4....." },
        { name: "D", wave: "5....." },
        { name: "E", wave: "6....." },
    ],
    head: {
        text: "Hello World!",
    },
    foot: {
        text: "Bye World!",
    }
}

Cycle Enumeration Marker

The head.tick and the foot.tock properties can be set to add cycle enumeration markers. The every property defines every how many cycles a marker should be put.

424344454647ABCDE135
{
    signal: [
        { name: "A", wave: "2....." },
        { name: "B", wave: "3....." },
        { name: "C", wave: "4....." },
        { name: "D", wave: "5....." },
        { name: "E", wave: "6....." },
    ],
    head: {
        tick: 42,
    },
    foot: {
        tock: 1,
        every: 2,
    }
}

Edges

Edges or arrows can be used to better highlight certain properties of the diagram. An edge is defined as between two nodes. Nodes are defined on signals and then edges are defined as <start><type><end> [label] in the edge property.

ABCDEabt1cat2cdtime 3deeffgghhisome texthj
{ signal: [
  { name: 'A', wave: '01........0.',  node: '.a........j' },
  { name: 'B', wave: '0.1.......0.',  node: '..b.......i' },
  { name: 'C', wave: '0..1....0...',  node: '...c....h..' },
  { name: 'D', wave: '0...1..0....',  node: '....d..g...' },
  { name: 'E', wave: '0....10.....',  node: '.....ef....' }
  ],
  edge: [
    'a~b t1', 'c-~a t2', 'c-~>d time 3', 'd~-e',
    'e~>f', 'f->g', 'g-~>h', 'h~>i some text', 'h~->j'
  ]
}

There are several types of arrows.

IdentifierTypeProperty
~SplineStart and ending horizontal
-~SplineStart horizontal
~-SplineEnding horizontal
-SharpShortest path
+SharpShortest path with bars
`--`Sharp
`-`Sharp
`-`Sharp

For all except the + the < and > can be appended to add arrows at the beginning and the end.

Skins

Skins allow customization of font sizes, colors, dimensions, paddings and spacings. Skins are created with a JSON that can contain any subset of the assemble and render options.

A template skin file can be found in the repository. Skins can also be previewed, edited and exported from the editor by opening the Render Settings.