In this guide you’ll learn how to use a Python tool to convert a lookup table into a Wokwi design. This can help save time in implementing complex digital logic.
Thanks to community member maehw for writing this article.
You have already learned about combinational logic that can be described by using a truth table, e.g. the full adder.
Let’s now have a look at at a decoder which converts a binary coded decimal digit (0..9) to control a 7-segment display. The input range can be covered using four bits (0..15=2^4-1), i.e. four input signals. We specify that valid input values are in the range 0..9, other values will show a blank display.
The truth table below maps the four input signals (w
, x
, y
and z
) to the seven output signals (A
to G
) driving the seven segments of the display:
BCD | Binary | w | x | y | z | A | B | C | D | E | F | G |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0000 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
1 | 0001 | 0 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
2 | 0010 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
3 | 0011 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |
4 | 0100 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 |
5 | 0101 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 |
6 | 0110 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 |
7 | 0111 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 |
8 | 1000 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
9 | 1001 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 |
- | 1010 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- | 1011 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- | 1100 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- | 1101 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- | 1110 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
- | 1111 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Some examples:
The decimal digit 0
is represented as 0000
in binary. We want to switch on all seven segments except segment G
- the middle segment. This is why we set output signals A
to F
to 1
and output signal G
to 0
.
The decimal digit 1
is represented as 0001
in binary (starting with the most significant bit on the left). We now only want to switch on the top-right and the bottom-right segments (segments B and C), thus placing a 1
only for output signals B
and C
and setting all other values to 0
.
The decimal digit 8
is represented as 1000
in binary. We now want to switch on all seven segments, thus placing a 1
for output every output signal.
There are also some binary values that cannot be represented by a single decimal digit, e.g. 1101
(decimal value of 2^4 + 2^3 + 2^0 = 8 + 4 + 1 = 13). This is why we set all output signals to 0
in order to completely blank out the display.
maehw wrote a Python based tool called wokwi-lookup-table-generator which can be used to generate a Wokwi schematic from truth tables. The generator implements the those truth tables in conjunctive normal form which means only using AND and OR gates.
Follow the install instructions to install it.
As a first step, the truth tables are re-written as equations functions of boolean algebra (using so called minterms, or “sum of products”) for every output signal.
The conversion from truth table to boolean algebra is done with a Python implementation of the Quine McCluskey algorithm. Please note that these optimizations are not really required as the ASIC toolchain will take care of optimization (and know the kind of hardware cells being available on the target hardware), but it helps to understand how digital designs are implemented.
In the next step those functions of boolean algebra are laid out as Wokwi schematic by placing all required AND and OR gates and connecting them with each other.
In order to run the tool, the truth table needs to be converted into JSON format. The names of the input signals are listed in the inputs
array.
The same way a single column of the truth table describes if an output signal is a 1 or a 0, so does a row in the JSON outputs
dictionary:
{
"version": 1,
"description": "Lookup table to translate a binary coded decimal (BCD) number to wokwi 7-segment display (https://docs.wokwi.com/parts/wokwi-7segment). Valid values are in the range 0..9, other values will show a blank display.",
"inputs": ["w", "x", "y", "z"],
"outputs": {
"A": [1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
"B": [1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
"C": [1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
"D": [1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0],
"E": [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0],
"F": [1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0],
"G": [0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0]
}
}
We’re now ready to run the generator by specifying the logic input file (-f
) and the Wokwi schematic output file (-o
):
python3 generate.py -f ./demos/bcd_7segment_lut.logic.json -o bcd_7segment_lut.diagram.json --tinytapeout
Also make sure to activate the flag --tinytapeout
(or -tt
) so that the default parts from the tinytapeout Wokwi template are also generated.
We can then open and inspect the output file with Wokwi’s diagram.json file format. It defines the parts (basically AND and OR gates) and the connections between those parts:
{
"version": 1,
"author": "maehw",
"editor": "wokwi",
"parts": [
{
"type": "wokwi-gate-buffer",
"id": "input_a",
"top": 0,
"left": 0,
"attrs": {}
},
{
"type": "wokwi-gate-not",
"id": "input_not_a",
"top": 60,
"left": 0,
"attrs": {}
},
...
],
"connections": [
[
"input_not_a:IN",
"input_a:IN",
"black",
[
"h-20",
"*",
"h-20"
]
],
...
]
}
Let’s simulate the design!
tiny-tapeout-poc-new-internal-pulls.ino
to tab diagram.json
.bcd_7segment_lut.diagram.json
.(The finished generated demo project can be found here: https://wokwi.com/projects/347688030570545747)
As manual verification can be quite tedious, especially for designs with many input signals, wokwi-lookup-table-generator
provides an option for automated verification: call the tool again, but replace the --tinytapeout
(or -tt
) flag with the --test
(or -t
) flag.
python3 generate.py -f ./demos/bcd_7segment_lut.logic.json -o bcd_7segment_lut.diagram.json --test
Adding the flag will have the following two effects:
bcd_7segment_lut.diagram.json
.sketch.ino
is created.When we inspect bcd_7segment_lut.diagram.json
we will find four major modifications (compared to when using the --tinytapeout
flag instead of --test
):
The default parts from the Wokwi template have been removed.
The parts list is extended by an Arduino Mega:
{
"type": "wokwi-arduino-mega",
"id": "mega",
"top": -400,
"left": -500,
"rotate": 90,
"attrs": {}
}
A section for including a serial monitor is added:
"serialMonitor": {
"display": "always",
"newline": "lf"
}
And the fourth major change is that the generated digital design’s inputs and outputs are automatically wired with digital I/O pins of the Arduino Mega.
The sketch.ino
file contains generated code to automatically verify the digital design by applying all possible input combinations and checking the digital design outputs against the expectations from the truth table.
This is what the lookup table of expected value looks like in the sketch.ino
code for our BCD to 7-segment decoder:
uint16_t expected_out_val[2 << (DESIGN_NUM_USED_INPUTS-1)] = {
0b1111110,
0b0110000,
0b1101101,
0b1111001,
0b0110011,
0b1011011,
0b0011111,
0b1110000,
0b1101111,
0b1110011,
0b0000000,
0b0000000,
0b0000000,
0b0000000,
0b0000000,
0b0000000,
};
Let’s simulate and verify the design!
tiny-tapeout-poc-new-internal-pulls.ino
select the whole file content, delete it and replace it with the contents of the newly generated sketch.ino
file.tiny-tapeout-poc-new-internal-pulls.ino
to tab diagram.json
.bcd_7segment_lut.diagram.json
.(The finished generated demo project can be found here: https://wokwi.com/projects/347688283983053395)
Here is a snippet from Wokwi’s serial monitor showing the results of the verification run:
Design has 4 inputs.
Design has 7 outputs.
Testing all 2^4 input combinations.
Stop verification on error? Yes
Wrote input: 0b0000
Expected output: 0b1111110
Read back output: 0b1111110
[PASS]
Wrote input: 0b0001
Expected output: 0b0110000
Read back output: 0b0110000
[PASS]
Wrote input: 0b0010
Expected output: 0b1101101
Read back output: 0b1101101
[PASS]
...
Wrote input: 0b1110
Expected output: 0b0000000
Read back output: 0b0000000
[PASS]
Wrote input: 0b1111
Expected output: 0b0000000
Read back output: 0b0000000
[PASS]
[PASSED]
wokwi-lookup-table-generator
wokwi-lookup-table-generator
work internally?