Implementation of DigitalJs for Liascript DigitalJS Source
Put the JSON of your circuit into Markdown ticks and put the makro @DigiSim.evalJson
at the first line of your markdown and the circuit will be evaluated and shown.
{
"devices": {
"dev0": {
"label": "s",
"position": {
"x": 0,
"y": 20
},
"celltype": "$button",
"propagation": 0
},
"dev1": {
"label": "r",
"position": {
"x": 155,
"y": 75
},
"celltype": "$button",
"propagation": 0
},
"dev2": {
"label": "q",
"position": {
"x": 480,
"y": 55
},
"celltype": "$lamp",
"propagation": 1
},
"dev3": {
"label": "nq",
"position": {
"x": 325,
"y": 0
},
"celltype": "$lamp",
"propagation": 1
},
"dev6": {
"label": "$or$_input.sv:7$1",
"position": {
"x": 310,
"y": 50
},
"celltype": "$nor",
"propagation": 1,
"bits": 1
},
"dev7": {
"label": "$or$_input.sv:8$3",
"position": {
"x": 140,
"y": 15
},
"celltype": "$nor",
"propagation": 1,
"bits": 1
}
},
"connectors": [
{
"from": {
"id": "dev0",
"port": "out"
},
"to": {
"id": "dev7",
"port": "in1"
},
"name": "s",
"vertices": []
},
{
"from": {
"id": "dev1",
"port": "out"
},
"to": {
"id": "dev6",
"port": "in1"
},
"name": "r",
"vertices": []
},
{
"from": {
"id": "dev6",
"port": "out"
},
"to": {
"id": "dev2",
"port": "in"
},
"name": "q",
"vertices": []
},
{
"from": {
"id": "dev6",
"port": "out"
},
"to": {
"id": "dev7",
"port": "in2"
},
"name": "q",
"vertices": []
},
{
"from": {
"id": "dev7",
"port": "out"
},
"to": {
"id": "dev3",
"port": "in"
},
"name": "nq",
"vertices": []
},
{
"from": {
"id": "dev7",
"port": "out"
},
"to": {
"id": "dev6",
"port": "in2"
},
"name": "nq",
"vertices": []
}
],
"subcircuits": {}
}
To get the JSON of a circuit you have to visite the website if Yosys2digitaljs and put the Verilog representation of the circuit in the text field on the website. Afterwards you have to click the save button near the timer in the upper right corner and save the JSON on your computer. The simply copy the JSON from the file into the LiaScript Document.
You can also write the JSON by hand. A document of the JSON format will also be included in this documentation.
It is also possible to put multiple circuits on the same site of your LiaScript document as shown below.
D-Latch
{
"devices": {
"dev0": {
"label": "d",
"position": {
"x": 0,
"y": 32.5
},
"celltype": "$button",
"propagation": 0
},
"dev1": {
"label": "e",
"position": {
"x": 0,
"y": 82.5
},
"celltype": "$button",
"propagation": 0
},
"dev2": {
"label": "q",
"position": {
"x": 660,
"y": 65
},
"celltype": "$lamp",
"propagation": 1
},
"dev3": {
"label": "nq",
"position": {
"x": 660,
"y": 10
},
"celltype": "$lamp",
"propagation": 1
},
"dev4": {
"position": {
"x": 275,
"y": 95
},
"celltype": "$and",
"propagation": 1,
"bits": 1
},
"dev5": {
"position": {
"x": 290,
"y": -5
},
"celltype": "$and",
"propagation": 1,
"bits": 1
},
"dev7": {
"position": {
"x": 95,
"y": 105
},
"celltype": "$not",
"propagation": 1,
"bits": 1
},
"dev9": {
"position": {
"x": 450,
"y": 5
},
"celltype": "$nor",
"propagation": 1,
"bits": 1
},
"dev10": {
"position": {
"x": 440,
"y": 105
},
"celltype": "$nor",
"propagation": 1,
"bits": 1
}
},
"connectors": [
{
"from": {
"id": "dev0",
"port": "out"
},
"to": {
"id": "dev5",
"port": "in2"
},
"name": "d",
"vertices": []
},
{
"from": {
"id": "dev0",
"port": "out"
},
"to": {
"id": "dev7",
"port": "in"
},
"name": "d",
"vertices": []
},
{
"from": {
"id": "dev1",
"port": "out"
},
"to": {
"id": "dev4",
"port": "in1"
},
"name": "e",
"vertices": []
},
{
"from": {
"id": "dev1",
"port": "out"
},
"to": {
"id": "dev5",
"port": "in1"
},
"name": "e",
"vertices": []
},
{
"from": {
"id": "dev10",
"port": "out"
},
"to": {
"id": "dev2",
"port": "in"
},
"name": "q",
"vertices": []
},
{
"from": {
"id": "dev10",
"port": "out"
},
"to": {
"id": "dev9",
"port": "in2"
},
"name": "q",
"vertices": []
},
{
"from": {
"id": "dev9",
"port": "out"
},
"to": {
"id": "dev3",
"port": "in"
},
"name": "nq",
"vertices": []
},
{
"from": {
"id": "dev9",
"port": "out"
},
"to": {
"id": "dev10",
"port": "in2"
},
"name": "nq",
"vertices": []
},
{
"from": {
"id": "dev7",
"port": "out"
},
"to": {
"id": "dev4",
"port": "in2"
},
"name": "nd",
"vertices": []
},
{
"from": {
"id": "dev4",
"port": "out"
},
"to": {
"id": "dev10",
"port": "in1"
},
"name": "r",
"vertices": []
},
{
"from": {
"id": "dev5",
"port": "out"
},
"to": {
"id": "dev9",
"port": "in1"
},
"name": "s",
"vertices": []
}
],
"subcircuits": {}
}
Priority encoder
{
"devices": {
"dev0": {
"label": "y",
"position": {
"x": 901.09375,
"y": 191.5
},
"celltype": "$numdisplay",
"propagation": 0,
"numbase": "hex",
"bits": 2
},
"dev1": {
"label": "valid",
"position": {
"x": 903.109375,
"y": 241.5
},
"celltype": "$lamp",
"propagation": 1
},
"dev2": {
"label": "a",
"position": {
"x": 0,
"y": 120.5
},
"celltype": "$numentry",
"propagation": 0,
"numbase": "hex",
"bits": 4
},
"dev3": {
"label": "$procmux$3",
"position": {
"x": 603.609375,
"y": 187.5
},
"celltype": "$pmux",
"propagation": 1,
"bits": {
"in": 3,
"sel": 4
}
},
"dev4": {
"label": "$procmux$4_CMP0",
"position": {
"x": 303.5625,
"y": 0
},
"celltype": "$eq",
"propagation": 1,
"bits": {
"in1": 4,
"in2": 1
},
"signed": {
"in1": false,
"in2": false
}
},
"dev5": {
"label": "$procmux$5_CMP0",
"position": {
"x": 303.5625,
"y": 60
},
"celltype": "$eq",
"propagation": 1,
"bits": {
"in1": 3,
"in2": 1
},
"signed": {
"in1": false,
"in2": false
}
},
"dev6": {
"label": "$procmux$6_CMP0",
"position": {
"x": 303.5625,
"y": 145.5
},
"celltype": "$eq",
"propagation": 1,
"bits": {
"in1": 2,
"in2": 1
},
"signed": {
"in1": false,
"in2": false
}
},
"dev7": {
"position": {
"x": 459.5859375,
"y": 99.5
},
"celltype": "$busgroup",
"propagation": 0,
"groups": [
1,
1,
1,
1
]
},
"dev8": {
"position": {
"x": 453.5625,
"y": 49.5
},
"celltype": "$constant",
"propagation": 0,
"numbase": "hex",
"constant": "000"
},
"dev9": {
"position": {
"x": 453.5625,
"y": 191.5
},
"celltype": "$constant",
"propagation": 0,
"numbase": "hex",
"constant": "111"
},
"dev10": {
"position": {
"x": 453.5625,
"y": 241.5
},
"celltype": "$constant",
"propagation": 0,
"numbase": "hex",
"constant": "101"
},
"dev11": {
"position": {
"x": 453.5625,
"y": 291.5
},
"celltype": "$constant",
"propagation": 0,
"numbase": "hex",
"constant": "011"
},
"dev12": {
"position": {
"x": 453.5625,
"y": 341.5
},
"celltype": "$constant",
"propagation": 0,
"numbase": "hex",
"constant": "001"
},
"dev13": {
"position": {
"x": 160.8125,
"y": 65
},
"celltype": "$constant",
"propagation": 0,
"numbase": "hex",
"constant": "1"
},
"dev14": {
"position": {
"x": 753.609375,
"y": 194.5
},
"celltype": "$busslice",
"propagation": 0,
"slice": {
"first": 1,
"count": 2,
"total": 3
}
},
"dev15": {
"position": {
"x": 758.34375,
"y": 244.5
},
"celltype": "$busslice",
"propagation": 0,
"slice": {
"first": 0,
"count": 1,
"total": 3
}
},
"dev16": {
"position": {
"x": 156.078125,
"y": 119.5
},
"celltype": "$busslice",
"propagation": 0,
"slice": {
"first": 1,
"count": 3,
"total": 4
}
},
"dev17": {
"position": {
"x": 156.078125,
"y": 163.5
},
"celltype": "$busslice",
"propagation": 0,
"slice": {
"first": 2,
"count": 2,
"total": 4
}
},
"dev18": {
"position": {
"x": 309.5546875,
"y": 205.5
},
"celltype": "$busslice",
"propagation": 0,
"slice": {
"first": 3,
"count": 1,
"total": 4
}
}
},
"connectors": [
{
"from": {
"id": "dev14",
"port": "out"
},
"to": {
"id": "dev0",
"port": "in"
},
"name": "y",
"vertices": []
},
{
"from": {
"id": "dev15",
"port": "out"
},
"to": {
"id": "dev1",
"port": "in"
},
"name": "valid",
"vertices": []
},
{
"from": {
"id": "dev2",
"port": "out"
},
"to": {
"id": "dev4",
"port": "in1"
},
"name": "a",
"vertices": []
},
{
"from": {
"id": "dev2",
"port": "out"
},
"to": {
"id": "dev16",
"port": "in"
},
"name": "a",
"vertices": []
},
{
"from": {
"id": "dev2",
"port": "out"
},
"to": {
"id": "dev17",
"port": "in"
},
"name": "a",
"vertices": []
},
{
"from": {
"id": "dev2",
"port": "out"
},
"to": {
"id": "dev18",
"port": "in"
},
"name": "a",
"vertices": []
},
{
"from": {
"id": "dev8",
"port": "out"
},
"to": {
"id": "dev3",
"port": "in0"
},
"vertices": []
},
{
"from": {
"id": "dev7",
"port": "out"
},
"to": {
"id": "dev3",
"port": "sel"
},
"vertices": []
},
{
"from": {
"id": "dev3",
"port": "out"
},
"to": {
"id": "dev14",
"port": "in"
},
"vertices": []
},
{
"from": {
"id": "dev3",
"port": "out"
},
"to": {
"id": "dev15",
"port": "in"
},
"vertices": []
},
{
"from": {
"id": "dev9",
"port": "out"
},
"to": {
"id": "dev3",
"port": "in1"
},
"vertices": []
},
{
"from": {
"id": "dev10",
"port": "out"
},
"to": {
"id": "dev3",
"port": "in2"
},
"vertices": []
},
{
"from": {
"id": "dev11",
"port": "out"
},
"to": {
"id": "dev3",
"port": "in3"
},
"vertices": []
},
{
"from": {
"id": "dev12",
"port": "out"
},
"to": {
"id": "dev3",
"port": "in4"
},
"vertices": []
},
{
"from": {
"id": "dev13",
"port": "out"
},
"to": {
"id": "dev4",
"port": "in2"
},
"vertices": []
},
{
"from": {
"id": "dev13",
"port": "out"
},
"to": {
"id": "dev5",
"port": "in2"
},
"vertices": []
},
{
"from": {
"id": "dev13",
"port": "out"
},
"to": {
"id": "dev6",
"port": "in2"
},
"vertices": []
},
{
"from": {
"id": "dev4",
"port": "out"
},
"to": {
"id": "dev7",
"port": "in3"
},
"vertices": []
},
{
"from": {
"id": "dev16",
"port": "out"
},
"to": {
"id": "dev5",
"port": "in1"
},
"vertices": []
},
{
"from": {
"id": "dev5",
"port": "out"
},
"to": {
"id": "dev7",
"port": "in2"
},
"vertices": []
},
{
"from": {
"id": "dev17",
"port": "out"
},
"to": {
"id": "dev6",
"port": "in1"
},
"vertices": []
},
{
"from": {
"id": "dev6",
"port": "out"
},
"to": {
"id": "dev7",
"port": "in1"
},
"vertices": []
},
{
"from": {
"id": "dev18",
"port": "out"
},
"to": {
"id": "dev7",
"port": "in0"
},
"vertices": []
}
],
"subcircuits": {}
}
{
"devices": {
"dev0": {
"label": "s",
"position": {
"x": 0,
"y": 20
},
"celltype": "$button",
"propagation": 0
},
"dev1": {
"label": "r",
"position": {
"x": 155,
"y": 75
},
"celltype": "$button",
"propagation": 0
},
"dev2": {
"label": "q",
"position": {
"x": 480,
"y": 55
},
"celltype": "$lamp",
"propagation": 1
},
"dev3": {
"label": "nq",
"position": {
"x": 325,
"y": 0
},
"celltype": "$lamp",
"propagation": 1
},
"dev6": {
"label": "$or$_input.sv:7$1",
"position": {
"x": 310,
"y": 50
},
"celltype": "$nor",
"propagation": 1,
"bits": 1
},
"dev7": {
"label": "$or$_input.sv:8$3",
"position": {
"x": 140,
"y": 15
},
"celltype": "$nor",
"propagation": 1,
"bits": 1
}
},
"connectors": [
{
"from": {
"id": "dev0",
"port": "out"
},
"to": {
"id": "dev7",
"port": "in1"
},
"name": "s",
"vertices": []
},
{
"from": {
"id": "dev1",
"port": "out"
},
"to": {
"id": "dev6",
"port": "in1"
},
"name": "r",
"vertices": []
},
{
"from": {
"id": "dev6",
"port": "out"
},
"to": {
"id": "dev2",
"port": "in"
},
"name": "q",
"vertices": []
},
{
"from": {
"id": "dev6",
"port": "out"
},
"to": {
"id": "dev7",
"port": "in2"
},
"name": "q",
"vertices": []
},
{
"from": {
"id": "dev7",
"port": "out"
},
"to": {
"id": "dev3",
"port": "in"
},
"name": "nq",
"vertices": []
},
{
"from": {
"id": "dev7",
"port": "out"
},
"to": {
"id": "dev6",
"port": "in2"
},
"name": "nq",
"vertices": []
}
],
"subcircuits": {}
}
@DigiSim.runJson
Using the @onload
-macro you cant predefine circuits which can later be inserted into the document with the @DigiSim.insertCircuit(name)
macro by giving the name of the circuit.
@DigiSim.insertCircuit(sr_latch)
You can also use a pseudo RTL code to define your circuit as demostrated below.
__Don't__ use the `finalizeJSON(name)` function in the code, or your circuit will not be shown!
// Init components
AND(["and1", "and2"], ["and3"], "AND1");
OR(["or1", "or2"], ["or3"], "OR1");
XOR(["xor1", "xor2"], ["xor3"], "XOR1");
Button("btn1", "BUTTON1");
Button("btn2", "BUTTON2");
Button("btn3", "BUTTON3");
Button("btn4", "BUTTON4");
Lamp("lmp1", "LAMP1");
// IO IN
wire("btn1", "and1");
wire("btn2", "and2");
wire("btn3", "or1");
wire("btn4", "or2");
// AND, OR -> XOR
wire("and3", "xor1");
wire("or3", "xor2");
// IO OUT
wire("xor3", "lmp1", "Main Output");
// Init components
AND(["and1", "and2"], ["and3"], "AND1");
OR(["or1", "or2"], ["or3"], "OR1");
XOR(["xor1", "xor2"], ["xor3"], "XOR1");
Button("btn1", "BUTTON1");
Button("btn2", "BUTTON2");
Button("btn3", "BUTTON3");
Button("btn4", "BUTTON4");
Lamp("lmp1", "LAMP1");
// IO IN
wire("btn1", "and1");
wire("btn2", "and2");
wire("btn3", "or1");
wire("btn4", "or2");
// AND, OR -> XOR
wire("and3", "xor1");
wire("or3", "xor2");
// IO OUT
wire("xor3", "lmp1", "Main Output");
To create a circuit you have to call some functions to create components for your circuit and then you can connect them with the wire(outpurname, inputname, label)
function.
To save your circuit you must call the finalizeJSON(name)
function, which saves a json representation of your circuit and resests the global state so that you can create the next circuit.
Example:
@onload
Button("btn1", "");
Button("btn2", "");
Button("btn3", "");
Button("btn4", "");
AND(["and1", "and2"], ["and3"], "AND1");
OR(["or1", "or2"], ["or3"], "OR1");
XOR(["xor1", "xor2"], ["xor3"], "XOR1");
Lamp("lmp1", "Main Output");
wire("btn1", "and1", "");
wire("btn2", "and2", "");
wire("btn3", "or1", "");
wire("btn4", "or2", "");
wire("and3", "xor1", "");
wire("or3", "xor2", "");
wire("xor3", "lmp1", "");
finalizeJSON("ex1");
@end
If you use the @DigiSim.eval
-macro you dont have to use the finalizeJSON(name)
to save your circuit! If you use it in the code it will not display your circuit!
You can simply use this functions to create logic gates in your circuits.
`inputs`: Array of strings with the name of your inputs. `type: [String]`
`outputs`: Array of strings with the name of your outputs. `type: [String]`
`label`: Name that will be displayed next to the component. `type: String`
`bits`: Size of your data bus in bits. `type: Int`
`pos`: Position of the circuit. `type: {x: Int, y: Int}`
All of these parameters are the same for the upcoming functions.
If the parameter is called `input` instead of `inputs` it is not an array of strings but a single string. The same apllies to `output` and `outputs`.
AND(inputs, outputs, label, bits=1, pos=undefined);
NAND(inputs, outputs, label, bits=1, pos=undefined);
OR(inputs, outputs, label, bits=1, pos=undefined);
NOR(inputs, outputs, label, bits=1, pos=undefined);
XOR(inputs, outputs, label, bits=1, pos=undefined);
XNOR(inputs, outputs, label, bits=1, pos=undefined);
NOT(inputs, outputs, label, bits=1, pos=undefined);
These gates take a bus of the given bit size and reduce its size to 1 bit.
ReducingAND(input, output, label, bits, pos=undefined)
ReducingNAND(input, output, label, bits, pos=undefined)
ReducingOR(input, output, label, bits, pos=undefined)
ReducingNOR(input, output, label, bits, pos=undefined)
ReducingXOR(input, output, label, bits, pos=undefined)
ReducingXNOR(input, output, label, bits, pos=undefined) // does currently not work properly and produces a reducing xor gate
Components that can handle input/output operations.
`bitsIn/bitsOut`: Determines the bus size only of the input/output of the component. `type: Int`
`base`: Base of the number system the should be used `possible values: "hex", "bin", "oct"`
`value`: Numeric value that is constantly output by the component. `type: Int`
Button(output, label, pos=undefined)
Lamp(input, label, pos=undefined)
NumberInput(output, label, bitsOut, base, pos=undefined)
NumberOutput(input, label, bitsIn, base, pos=undefined)
NumberConstant(output, label, value, pos=undefined)
Unary operations that can be performed on numbers.
`signed`: Determines wheter the numbers are signed or unsigned. `type: Boolean`
Negator(input, output, label, bitsIn, bitsOut, signed, pos=undefined)
Binary operations that can be performed on numbers.
Add(inputs, output, label, bitsIn, bitsOut, signed, pos=undefined)
Subtract(inputs, output, label, bitsIn, bitsOut, signed, pos=undefined)
Multiply(inputs, output, label, bitsIn, bitsOut, signed, pos=undefined)
Divide(inputs, output, label, bitsIn, bitsOut, signed, pos=undefined)
Modulo(inputs, output, label, bitsIn, bitsOut, signed, pos=undefined)
Pow(inputs, output, label, bitsIn, bitsOut, signed, pos=undefined)
Comparison operations that can be performed on numbers.
Equals(inputs, output, label, bitsIn, signed, pos=undefined)
NotEquals(inputs, output, label, bitsIn, signed, pos=undefined)
LessThan(inputs, output, label, bitsIn, signed, pos=undefined)
LessThanOrEqual(inputs, output, label, bitsIn, signed, pos=undefined)
GreaterThan(inputs, output, label, bitsIn, signed, pos=undefined)
GreaterThanOrEqual(inputs, output, label, bitsIn, signed, pos=undefined)
Shift operations that can be performed on numbers.
ShiftLeft(inputs, output, label, bitsIn, bitsOut, signed, pos=undefined)
ShiftRight(inputs, output, label, bitsIn, bitsOut, signed, pos=undefined)
`bitsSel`: Determines the bus size of the select input. `type: Int`
Number of inputs: 2 ^ bitSel
Multiplexer(inputs, selInput, output, label, bitsIn, bitsSel, pos=undefined)