Digitaljs
Teaching-focused digital circuit simulator
Install / Use
/learn @tilk/DigitaljsREADME
![][digitaljs-logo]
DigitalJS
This project is a digital circuit simulator implemented in Javascript. It is designed to simulate circuits synthesized by hardware design tools like Yosys (Github repo here), and it has a companion project yosys2digitaljs, which converts Yosys output files to DigitalJS. It is also intended to be a teaching tool, therefore readability and ease of inspection is one of top concerns for the project.
You can try it out online. The web app is a separate Github project.
Conference paper
Marek Materzok. 2020. DigitalJS: a Visual Verilog Simulator for Teaching. In Proceedings of the 8th Computer Science Education Research Conference (CSERC '19). Association for Computing Machinery, New York, NY, USA, 110–115. https://doi.org/10.1145/3375258.3375272
Usage
You can use DigitalJS in your project by installing it from NPM:
npm install digitaljs
Or you can use the Webpack bundle directly.
To simulate a circuit represented using the JSON input format (described later)
and display it on a div named #paper, you need to run the following
JS code (see running example):
// create the simulation object
const circuit = new digitaljs.Circuit(input_goes_here);
// display on #paper
const paper = circuit.displayOn($('#paper'));
// activate real-time simulation
circuit.start();
Input format
Circuits are represented using JSON. The top-level object has three keys, devices,
connectors and subcircuits. Under devices is a list of all devices forming
the circuit, represented as an object, where keys are (unique and internal) device
names. Each device has a number of properties, which are represented by an object.
A mandatory property is type, which specifies the type of the device. Example
device:
"dev1": {
"type": "And",
"label": "AND1"
}
Under connectors is a list of connections between device ports, represented as an
array of objects with two keys, from and to. Both keys map to an object with two
keys, id and port; the first corresponds to a device name, and the second -- to
a valid port name for the device. A connection must lead from an output port to
an input port, and the bitwidth of both ports must be equal. Example connection:
{
"from": {
"id": "dev1",
"port": "out"
},
"to": {
"id": "dev2",
"port": "in"
}
}
Under subcircuits is a list of subcircuit definitions, represented as an object,
where keys are unique subcircuit names. A subcircuit name can be used as
a celltype for a device of type Subcircuit; this instantiates the subcircuit.
A subcircuit definition
follows the representation of whole circuits, with the exception that subcircuits
cannot (currently) define their own subcircuits. A subcircuit can include
Input and Output devices, these are mapped to ports on a subcircuit
instance.
Device types
- Unary gates:
Not,Repeater- Attributes:
bits(natural number) - Inputs:
in(bits-bit) - Outputs:
out(bits-bit)
- Attributes:
- N-ary gates:
And,Nand,Or,Nor,Xor,Xnor- Attributes:
bits(natural number),inputs(natural number, default 2) - Inputs:
in1,in2...inN(bits-bit,N=inputs) - Outputs:
out(bits-bit)
- Attributes:
- Reducing gates:
AndReduce,NandReduce,OrReduce,NorReduce,XorReduce,XnorReduce- Attributes:
bits(natural number) - Inputs:
in(bits-bit) - Outputs:
out(1-bit)
- Attributes:
- Bit shifts:
ShiftLeft,ShiftRight- Attributes:
bits.in1,bits.in2andbits.out(natural number),signed.in1,signed.in2,signed.outandfillx(boolean) - Inputs:
in1(bits.in1-bit),in2(bits.in2-bit) - Outputs:
out(bits.out-bit)
- Attributes:
- Comparisons:
Eq,Ne,Lt,Le,Gt,Ge- Attributes:
bits.in1andbits.in2(natural number),signed.in1andsigned.in2(boolean) - Inputs:
in1(bits.in1-bit),in2(bits.in2-bit) - Outputs:
out(1-bit)
- Attributes:
- Number constant:
Constant- Attributes:
constant(binary string) - Outputs:
out(constant.length-bit)
- Attributes:
- Unary arithmetic:
Negation,UnaryPlus- Attributes:
bits.inandbits.out(natural number),signed(boolean) - Inputs:
in(bits.in-bit) - Outputs:
out(bits.out-bit)
- Attributes:
- Binary arithmetic:
Addition,Subtraction,Multiplication,Division,Modulo,Power- Attributes:
bits.in1,bits.in2andbits.out(natural number),signed.in1andsigned.in2(boolean) - Inputs:
in1(bits.in1-bit),in2(bits.in2-bit) - Outputs:
out(bits.out-bit)
- Attributes:
- Multiplexer:
Mux- Attributes:
bits.in,bits.sel(natural number) - Inputs:
in0...inN(bits.in-bit,N= 2**bits.sel-1),sel(bits.sel-bit) - Outputs:
out(bits.in-bit)
- Attributes:
- One-hot multiplexer:
Mux1Hot- Attributes:
bits.in,bits.sel(natural number) - Inputs:
in0...inN(bits.in-bit,N=bits.sel),sel(bits.sel-bit) - Outputs:
out(bits.in-bit)
- Attributes:
- Sparse multiplexer:
MuxSparse- Attributes:
bits.in,bits.sel(natural number),inputs(list of natural numbers),default_input(optional boolean) - Inputs:
in0...inN(bits.in-bit,N=inputs.length, +1 ifdefault_inputis true) - Outputs:
out(bits.in-bit)
- Attributes:
- D flip-flop:
Dff- Attributes:
bits(natural number),polarity.clock,polarity.arst,polarity.srst,polarity.aload,polarity.set,polarity.clr,polarity.enable,enable_srst(optional booleans),initial(optional binary string),arst_value,srst_value(optional binary string),no_data(optional boolean) - Inputs:
in(bits-bit),clk(1-bit, ifpolarity.clockis present),arst(1-bit, ifpolarity.arstis present),srst(1-bit, ifpolarity.srstis present),en(1-bit, ifpolarity.enableis present),set(1-bit, ifpolarity.setis present),clr(1-bit, ifpolarity.clris present),ain(bits-bit, ifpolarity.aloadis present),aload(1-bit, ifpolarity.aloadis present) - Outputs:
out(bits-bit)
- Attributes:
- Memory:
Memory- Attributes:
bits,abits,words,offset(natural number),rdports(array of read port descriptors),wrports(array of write port descriptors),memdata(memory contents description) - Read port descriptor attributes:
enable_polarity,clock_polarity,arst_polarity,srst_polarity(optional booleans),init_value,arst_value,srst_value(optional binary strings),transparent,collision(optional booleans or arrays of booleans) - Write port descriptor attributes:
enable_polarity,clock_polarity,no_bit_enable(optional booleans) - Inputs (per read port):
rdKaddr(abits-bit),rdKen(1-bit, ifenable_polarityis present),rdKclk(1-bit, ifclock_polarityis present),rdKarst(1-bit, ifarst_polarityis present),rdKsrst(1-bit, ifsrst_polarityis present) - Outputs (per read port):
rdKdata(bits-bit) - Inputs (per write port):
wrKaddr(abits-bit),wrKdata(bits-bit),wrKen(1-bit (whenno_bit_enableis true) orbits-bit (otherwise), ifenable_polarityis present),wrKclk(1-bit, ifclock_polarityis present)
- Attributes:
- Clock source:
Clock- Outputs:
out(1-bit)
- Outputs:
- Button input:
Button- Outputs:
out(1-bit)
- Outputs:
- Lamp output:
Lamp- Inputs:
in(1-bit)
- Inputs:
- Number input:
NumEntry- Attributes:
bits(natural number),numbase(string) - Outputs:
out(bits-bit)
- Attributes:
- Number output:
NumDisplay- Attributes:
bits(natural number),numbase(string) - Inputs:
in(bits-bit)
- Attributes:
- Subcircuit input:
Input- Attributes:
bits(natural number) - Outputs:
out(bits-bit)
- Attributes:
- Subcircuit output:
Output- Attributes:
bits(natural number) - Inputs:
in(bits-bit)
- Attributes:
- 7 segment display output:
Display7- Inputs:
bits(8-bit only - most significant bit controls decimal point LED)
- Inputs:
- Bus grouping:
BusGroup- Attributes:
groups(array of natural numbers) - Inputs:
in0(groups[0]-bit) ...inN(groups[N]-bit) - Outputs:
out(sum-of-groups-bit)
- Attributes:
- Bus ungrouping:
BusUngroup- Attributes:
groups(array of natural numbers) - Inputs:
in(sum-of-groups-bit) - Outputs:
out0(groups[0]-bit) ...outN(groups[N]-bit)
- Attributes:
- Bus slicing:
BusSlice- Attributes:
slice.first,slice.count,slice.total(natural number) - Inputs:
in(slice.total-bit) - Outputs:
out(slice.count-bit)
- Attributes:
- Zero- and sign-extension:
ZeroExtend,SignExtend- Attributes:
extend.input,extend.output(natural number) - Inputs:
in(extend.input-bit) - Outputs:
out(extend.output-bit)
- Attributes:
- Finite state machines:
FSM- Attributes:
bits.in,bits.out,states,init_state,current_state(natural number),trans_table(array of transition descriptors) - Transition descriptor attributes:
ctrl_in,ctrl_out(binary strings),state_in,state_out(natural numbers) - Inputs:
clk(1-bit),arst(1-bit),in(bits.in-bit) - Outputs:
out(bits.out-bit)
- Attributes:
TODO
Some ideas for further developing the simulator.
- Use JointJS elementTools for configuring/removing gates.
- RAM/ROM import/export for Verilog format and Intel HEX.
- Framebuffer element with character/bitmap display.
- More editing capability: adding and removing blocks, modifying some of blocks' properties.
- Undo-redo capability.
- Saving and loading circuits, including layout and state.
- Generic handling of negation for unary/binary g
Related Skills
node-connect
340.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.1kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
340.2kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
84.1kCommit, push, and open a PR
