From 35968d1da648d4985d6cc09b818b856c7b7e1208 Mon Sep 17 00:00:00 2001 From: Giles Atkinson <“gatk555@gmail.com”> Date: Mon, 10 Jun 2024 11:40:37 +0100 Subject: [PATCH] Add additional examples of Verilog co-simulation and share the Verilog source and large parts of the example circuits between Verilator and Icarus Verilog. Verilog source file adc.v has improved style: all assignments in the always block are now non-blocking. --- examples/xspice/icarus_verilog/555.cir | 10 ++ examples/xspice/icarus_verilog/README.txt | 46 ++++++++++ examples/xspice/icarus_verilog/adc.cir | 10 ++ examples/xspice/icarus_verilog/delay.cir | 10 ++ examples/xspice/icarus_verilog/pwm.cir | 12 +++ examples/xspice/verilator/555.cir | 11 +++ examples/xspice/verilator/555.shared | 60 ++++++++++++ examples/xspice/verilator/555.v | 26 ++++++ examples/xspice/verilator/README.txt | 36 ++++++-- examples/xspice/verilator/adc.cir | 101 +------------------- examples/xspice/verilator/adc.shared | 107 ++++++++++++++++++++++ examples/xspice/verilator/adc.v | 18 ++-- examples/xspice/verilator/delay.cir | 11 +++ examples/xspice/verilator/delay.v | 14 +++ examples/xspice/verilator/pwm.cir | 12 +++ examples/xspice/verilator/pwm.v | 34 +++++++ 16 files changed, 405 insertions(+), 113 deletions(-) create mode 100644 examples/xspice/icarus_verilog/555.cir create mode 100644 examples/xspice/icarus_verilog/README.txt create mode 100644 examples/xspice/icarus_verilog/adc.cir create mode 100644 examples/xspice/icarus_verilog/delay.cir create mode 100644 examples/xspice/icarus_verilog/pwm.cir create mode 100644 examples/xspice/verilator/555.cir create mode 100644 examples/xspice/verilator/555.shared create mode 100644 examples/xspice/verilator/555.v create mode 100644 examples/xspice/verilator/adc.shared create mode 100644 examples/xspice/verilator/delay.cir create mode 100644 examples/xspice/verilator/delay.v create mode 100644 examples/xspice/verilator/pwm.cir create mode 100644 examples/xspice/verilator/pwm.v diff --git a/examples/xspice/icarus_verilog/555.cir b/examples/xspice/icarus_verilog/555.cir new file mode 100644 index 000000000..165ceb2f8 --- /dev/null +++ b/examples/xspice/icarus_verilog/555.cir @@ -0,0 +1,10 @@ +Verilog-controlled simple timer. + +* This is the model for an RS flip-flop implemented by Icarus Verilog. + +.model vlog_ff d_cosim simulation="ivlng" sim_args=["555"] + +* The bulk of the circuit is in a shared file. + +.include ../verilator/555.shared +.end diff --git a/examples/xspice/icarus_verilog/README.txt b/examples/xspice/icarus_verilog/README.txt new file mode 100644 index 000000000..f61f9498b --- /dev/null +++ b/examples/xspice/icarus_verilog/README.txt @@ -0,0 +1,46 @@ +The circuits in this directory illustrate the use of the d_cosim +XSPICE code model as a container for a Verilog simulation using +Icarus Verilog. Icarus Verilog must be built with the --enable-libvvp option, +so that its simulation engine is available as a dynamic library. +The Verilog source code and included parts of the circuit definitions +can be found in the adjacent "verilator" directory. + +The example circuits are: + +555.cir: The probably familiar NE555 oscillator provides a minimal example +of combined simulation with SPICE and Verilog. +The digital part of the IC, a simple SR flip-flop, is expressed in Verilog. + +delay.v: A very simple example of using delays in Verilog to generate +waveform outputs. + +pwm.c: Verilog delays controlling a pulse-width modulated output generate +an approximate sine wave. + +adc.cir: Slightly more complex Verilog describes the controlling part +of a switched-capacitor ADC. + +Before a simulation can be run, the associated Verilog code must be compiled: + + iverilog -o 555 ../verilator/555.v + +Similar compilations are needed to prepare the other examples. + +The simulations require additional dynamic libraries, ivlng.so (or ivlng.DLL) +and ivlng.vpi: they are expected to be in the usual installation location. + +To use the versions in a built source tree that has not been installed, +the .model definitions in the circuit files must be changed to the ugly: + +.model vlog_ff d_cosim sim_args=["555"] ++ simulation = "../../../release/src/xspice/verilog/.libs/ivlng" ++ lib_args = [ "libvvp" ++ "../../../release/src/xspice/verilog/.libs/ivlngvpi.so" ] + +Or for Windows builds using MSVC: + +.model vlog_ff d_cosim sim_args=["555"] ++ simulation = "..\..\..\visualc\xspice\verilog\ivlng.DLL" ++ lib_args = [ "libvvp" ++ "..\..\..\visualc\xspice\verilog\shim.vpi" ] + diff --git a/examples/xspice/icarus_verilog/adc.cir b/examples/xspice/icarus_verilog/adc.cir new file mode 100644 index 000000000..b717c1439 --- /dev/null +++ b/examples/xspice/icarus_verilog/adc.cir @@ -0,0 +1,10 @@ +Simulation of a switched-capacitor SAR ADC with Verilator and d_cosim + +* Model line for the digital control implemented by Icarus Verilog. + +.model dut d_cosim simulation="ivlng" sim_args=["adc"] + +* The bulk of the circuit is in a shared file. + +.include ../verilator/adc.shared +.end diff --git a/examples/xspice/icarus_verilog/delay.cir b/examples/xspice/icarus_verilog/delay.cir new file mode 100644 index 000000000..efa0cdcee --- /dev/null +++ b/examples/xspice/icarus_verilog/delay.cir @@ -0,0 +1,10 @@ +* Waveform generation by Verilog delays + +adut null [ d4 d3 d2 d1 d0 ] ring +.model ring d_cosim simulation="ivlng" sim_args = [ "delay" ] + +.control +tran 20u 100u +plot d4 d3 d2 d1 d0 digitop +.endc +.end diff --git a/examples/xspice/icarus_verilog/pwm.cir b/examples/xspice/icarus_verilog/pwm.cir new file mode 100644 index 000000000..6de998c43 --- /dev/null +++ b/examples/xspice/icarus_verilog/pwm.cir @@ -0,0 +1,12 @@ +* Waveform generation by PWM in Verilog + +adut null [ out ] pwm_sin +.model pwm_sin d_cosim simulation="ivlng" sim_args = [ "pwm" ] + +r1 out smooth 100k +c1 smooth 0 1u +.control +tran 1m 2 +plot out-3.3 smooth +.endc +.end diff --git a/examples/xspice/verilator/555.cir b/examples/xspice/verilator/555.cir new file mode 100644 index 000000000..f8d408645 --- /dev/null +++ b/examples/xspice/verilator/555.cir @@ -0,0 +1,11 @@ +Verilog-controlled simple timer. + +* This is the model for an RS flip-flop implemented by Verilator. + +.model vlog_ff d_cosim simulation="./555" + +* The bulk of the circuit is in a shared file. + +.include 555.shared +.end + diff --git a/examples/xspice/verilator/555.shared b/examples/xspice/verilator/555.shared new file mode 100644 index 000000000..3c763675b --- /dev/null +++ b/examples/xspice/verilator/555.shared @@ -0,0 +1,60 @@ +* This file is not intended to be used directly, but by 555.cir. +* That allows it to be shared by different implemnetations. + +* This sub-circuit simulates the NE555 timer IC, with the very simple +* digital part as a Verilog module. + +.subckt NE555 trigger threshold reset control output discharge vcc ground + +* Resistor chain + +r1 vcc control 5k +r2 control trigger_ref 5k +r3 trigger_ref ground 5k + +* Two XSPICE ADC instances serve as comparators. + +.model comparator adc_bridge(in_low = -0.0001 in_high = 0.0001) +athresh_comparator [%vd threshold control] [over_threshold] comparator +atrigger_comparator [%vd trigger_ref trigger] [under_trigger] comparator + +* A tiny Verilog module supplies the flip-flop. +* The model is supplied by the outer circuit file. + +averilog [ under_trigger over_threshold reset ] [ output qbar ] vlog_ff + +* The discharge transistor and its base resistor. + +rbase qbar discharge_base 10k +qdischarge discharge discharge_base ground npn_transistor +.model npn_transistor npn + +.ends ; Ends subcircuit NE555 + + +* The usual 555 oscillator with threshold connected to discharge. + +.param vcc=12 + +X555 trigger_threshold trigger_threshold reset control output discharge vcc 0 ne555 + +r1 vcc discharge 10k +r2 discharge trigger_threshold 10k +Ct trigger_threshold 0 1uF ic=0 + +* A resistive load forces analog output. + +rload output 0 1k + +* A voltage source for power. + +Vcc vcc 0 {vcc} + +* Pulse the Reset signal low for 2uS each 51mS + +Vpulse reset 0 PULSE {vcc} 0.2 0 1u 1u 2u 51m + +.control +tran 10u 200m uic +plot trigger_threshold output x555.under_trigger-3 x555.over_threshold-1.5 +.endc diff --git a/examples/xspice/verilator/555.v b/examples/xspice/verilator/555.v new file mode 100644 index 000000000..acd7d6c91 --- /dev/null +++ b/examples/xspice/verilator/555.v @@ -0,0 +1,26 @@ +// Very simple logic for a 555 timer simulation + +`timescale 1us/100ns + +module VL555(Trigger, Threshold, Reset, Q, Qbar); + input wire Trigger, Threshold, Reset; // Reset is active low. + output reg Q; + output wire Qbar; + + wire ireset, go; + + assign Qbar = !Q; + + // The datasheet implies that Trigger overrides Threshold. + + assign go = Trigger & Reset; + assign ireset = (Threshold & !Trigger) | !Reset; + + initial begin + Q = 0; + end + + always @(posedge(go), posedge(ireset)) begin + Q = go; + end +endmodule diff --git a/examples/xspice/verilator/README.txt b/examples/xspice/verilator/README.txt index e919ceab5..a8e39ab63 100644 --- a/examples/xspice/verilator/README.txt +++ b/examples/xspice/verilator/README.txt @@ -1,10 +1,32 @@ -The circuit adc.cir in this directory illustrates the use of the d_cosim -XSPICE code model as a container for a Verilog simulation. Before the -simulation can be run, the Verilog code must be compiled by Verilator -using the command: +The circuits in this directory illustrate the use of the d_cosim +XSPICE code model as a container for a Verilog simulation, using the +Verilator compiler. The example circuits are: - ngspice vlnggen adc.v +555.cir: The probably familiar NE555 oscillator provides a minimal example +of combined simulation with SPICE and Verilog. The digital part of the IC, +a simple SR flip-flop, is expressed in Verilog. -That should create a shared library file, adc.so (or adc.DLL on Windows) +delay.v: A very simple example of using delays in Verilog to generate +waveform outputs. + +pwm.c: Verilog delays controlling a pulse-width modulated output generate +an approximate sine wave. + +adc.cir: Slightly more complex Verilog describes the controlling part +of a switched-capacitor ADC. + +Before a simulation can be run, the associated Verilog code must be compiled +by Verilator using a command script that is included with ngspice: + + ngspice vlnggen 555.v + +That should create a shared library file, 555.so (or 555.DLL on Windows) that will be loaded by the d_cosim code model. The compiled Verilog code that -it contains will be executed during simulation. +it contains will be executed during simulation. Similar compilations +are needed to prepare the other examples, but for Verilog with delays the +command looks like: + + ngspice vlnggen -- --timing delay.v + +(The "--" prevents "--timing" from being treated as a ngspice option, so it is +passed on to Verilator.) diff --git a/examples/xspice/verilator/adc.cir b/examples/xspice/verilator/adc.cir index 133a7dbf6..3ef5a433b 100644 --- a/examples/xspice/verilator/adc.cir +++ b/examples/xspice/verilator/adc.cir @@ -1,103 +1,10 @@ Simulation of a switched-capacitor SAR ADC with Verilator and d_cosim -.subckt sar_adc input vref start valid d5 d4 d3 d2 d1 d0 clk +* Model line for the digital control implemented by Verilator. -* A transmission gate connects the input to the capacitor set. +.model dut d_cosim simulation="./adc" -xsample input iin sample vref tgate -rin iin test_v 1k +* The bulk of the circuit is in a shared file. -* Capacitors and controlling inverters - -xb5 test_v vref d5 ccap c=1p -xb4 test_v vref d4 ccap c={1p / 2} -xb3 test_v vref d3 ccap c={1p / 4} -xb2 test_v vref d2 ccap c={1p / 8} -xb1 test_v vref d1 ccap c={1p / 16} -xb0 test_v vref d0 ccap c={1p / 32} -clast test_v 0 {1p / 32} - -* An XSPICE ADC bridge functions as a comparator. - -acomp [%vd(test_v vref)] [comp] comparator -.model comparator adc_bridge in_low=0 in_high=0 - -* The digital portion of the circuit is specified in compiled Verilog. -* Outputs inverted to cancel the inverter in subcircuit ccap, -* and produce the correct numerical output value. - -adut [ Clk Comp Start] [Sample Valid ~d5 ~d4 ~d3 ~d2 ~d1 ~d0] null dut -.model dut d_cosim simulation="./adc.so" -.ends // SUBCKT sar_adc - -* Some MOS transistors complete the circuit. -* Models from https://homepages.rpi.edu/~sawyes/AIMSPICE_TutorialManual.pdf - -.model p1 pmos -+ level=2 vto=-0.5 kp=8.5e-6 gamma=0.4 phi=0.65 lambda=0.05 xj=0.5e-6 -.model n1 nmos -+ level=2 vto=0.5 kp=24e-6 gamma=0.15 phi=0.65 lambda=0.015 xj=0.5e-6 - -* Use those for an inverter. - -.subckt ainv in out vdd -mn out in 0 0 n1 -mp out in vdd vdd p1 -.ends - -* A transmission gate modelled by a switch. - -.subckt mos_tgate a b ctl vdd -mn a ctl b b n1 -xinv ctl ictl vdd ainv -mp b ictl a a p1 -.ends - -.subckt tgate a b ctl vdd -switch a b ctl 0 tg -.model tg sw vt=1.5 ron=2k -.ends - -* The per-bit subcircuit in the adc - -.subckt ccap in vcc ctl c=10p -xinv ctl tail vcc ainv -cb in tail {c} -.ends - -**** End of the ADC and its subcircuits. Begin test circuit **** - -.param vcc=3.3 -vcc vcc 0 {vcc} - -* Digital clock signal - -aclock 0 clk clock -.model clock d_osc cntl_array=[-1 1] freq_array=[1Meg 1Meg] - -* A simple DAC so that the result may be compared to the input. - -r5 d5 sum 2 -r4 d4 sum 4 -r3 d3 sum 8 -r2 d2 sum 16 -r1 d1 sum 32 -r0 d0 sum 64 - -vamm sum 0 0 - -* Pulse the Start signal high for 1.3uS each 10uS - -Vpulse Start 0 PULSE 0 {vcc} 0.2u 10n 10n 1.3u 10u -Vtest input 0 PULSE 0 3 0 200u 200u 1u 401u - -* The ADC for testing - -xtest input vcc start valid d5 d4 d3 d2 d1 d0 clk sar_adc - - -.control -tran 100n 250u -plot input xtest.test_v vamm#branch clk/2 start/3 xtest.sample/3 valid -.endc +.include adc.shared .end diff --git a/examples/xspice/verilator/adc.shared b/examples/xspice/verilator/adc.shared new file mode 100644 index 000000000..0501f5dd3 --- /dev/null +++ b/examples/xspice/verilator/adc.shared @@ -0,0 +1,107 @@ +* This file is not intended to be used directly, but by adc.cir. +* That allows it to be shared by different implemnetations. + +* Simulation of a switched-capacitor SAR ADC with Verilator and d_cosim + +.subckt sar_adc input vref start valid d5 d4 d3 d2 d1 d0 clk + +* A transmission gate connects the input to the capacitor set. + +xsample input iin sample vref tgate +rin iin test_v 1k + +* Capacitors and controlling inverters + +xb5 test_v vref d5 ccap c=1p +xb4 test_v vref d4 ccap c={1p / 2} +xb3 test_v vref d3 ccap c={1p / 4} +xb2 test_v vref d2 ccap c={1p / 8} +xb1 test_v vref d1 ccap c={1p / 16} +xb0 test_v vref d0 ccap c={1p / 32} +clast test_v 0 {1p / 32} + +* An XSPICE ADC bridge functions as a comparator. + +acomp [%vd(test_v vref)] [comp] comparator +.model comparator adc_bridge in_low=0 in_high=0 + +* The digital portion of the circuit is specified in compiled Verilog. +* Outputs inverted to cancel the inverter in subcircuit ccap, +* and produce the correct numerical output value. The model definition +* is supplied by the calling circuit file. + +adut [ Clk Comp Start] [Sample Valid ~d5 ~d4 ~d3 ~d2 ~d1 ~d0] dut +.ends // SUBCKT sar_adc + +* Some MOS transistors complete the circuit. +* Models from https://homepages.rpi.edu/~sawyes/AIMSPICE_TutorialManual.pdf + +.model p1 pmos ++ level=2 vto=-0.5 kp=8.5e-6 gamma=0.4 phi=0.65 lambda=0.05 xj=0.5e-6 +.model n1 nmos ++ level=2 vto=0.5 kp=24e-6 gamma=0.15 phi=0.65 lambda=0.015 xj=0.5e-6 + +* Use those for an inverter. + +.subckt ainv in out vdd +mn out in 0 0 n1 +mp out in vdd vdd p1 +.ends + +* A transmission gate modelled by a switch. + +.subckt mos_tgate a b ctl vdd +mn a ctl b b n1 +xinv ctl ictl vdd ainv +mp b ictl a a p1 +.ends + +.subckt tgate a b ctl vdd +switch a b ctl 0 tg +.model tg sw vt=1.5 ron=2k +.ends + +* The per-bit subcircuit in the adc + +.subckt ccap in vcc ctl c=10p +xinv ctl tail vcc ainv +cb in tail {c} +.ends + +**** End of the ADC and its subcircuits. Begin test circuit **** + + +.param vcc=3.3 +vcc vcc 0 {vcc} + +* Digital clock signal + +aclock 0 clk clock +.model clock d_osc cntl_array=[-1 1] freq_array=[1Meg 1Meg] + +* A simple DAC so that the result may be compared to the input. + +r5 d5 sum 2 +r4 d4 sum 4 +r3 d3 sum 8 +r2 d2 sum 16 +r1 d1 sum 32 +r0 d0 sum 64 + +vamm sum 0 0 + +* Pulse the Start signal high for 1.3uS each 10uS + +Vpulse Start 0 PULSE 0 {vcc} 0.2u 10n 10n 1.3u 10u +Vtest input 0 PULSE 0 3 0 200u 200u 1u 401u + +* The ADC for testing + +xtest input vcc start valid d5 d4 d3 d2 d1 d0 clk sar_adc + + +.control +tran 100n 250u +plot input xtest.test_v vamm#branch clk/2 start/3 xtest.sample/3 valid +.endc +.end diff --git a/examples/xspice/verilator/adc.v b/examples/xspice/verilator/adc.v index 14bfcaccf..c063f1794 100644 --- a/examples/xspice/verilator/adc.v +++ b/examples/xspice/verilator/adc.v @@ -1,5 +1,7 @@ // Digital control for a successive approximation ADC with switched capacitors. +`timescale 100ns/100ns + module adc(Clk, Comp, Start, Sample, Done, Result); input wire Clk, Comp, Start; output reg Sample, Done; @@ -22,14 +24,12 @@ module adc(Clk, Comp, Start, Sample, Done, Result); if (Running) begin if (Sample) begin Sample <= 0; - SR[Bits - 1] = 1; - Result[Bits - 1] = 1; + SR[Bits - 1] <= 1; + Result[Bits - 1] <= 1; end else if (SR != 0) begin - if (Comp) - Result &= ~SR; - SR >>= 1; - Result |= SR; - if (SR == 0) begin + Result <= (Comp ? (Result & ~SR) : Result) | (SR >> 1); + SR <= SR >> 1; + if (SR == 1) begin Running <= 0; Done <= 1; end @@ -38,8 +38,8 @@ module adc(Clk, Comp, Start, Sample, Done, Result); Running <= 1; Sample <= 1; Done <= 0; - SR = 0; - Result = 0; + SR <= 0; + Result <= 0; end end endmodule diff --git a/examples/xspice/verilator/delay.cir b/examples/xspice/verilator/delay.cir new file mode 100644 index 000000000..d68ebaafb --- /dev/null +++ b/examples/xspice/verilator/delay.cir @@ -0,0 +1,11 @@ +* Waveform generation by Verilog delays +* + +adut null [ d4 d3 d2 d1 d0 ] ring +.model ring d_cosim simulation="./delay" + +.control +tran 20u 100u +plot d4 d3 d2 d1 d0 digitop +.endc +.end diff --git a/examples/xspice/verilator/delay.v b/examples/xspice/verilator/delay.v new file mode 100644 index 000000000..64fc68c80 --- /dev/null +++ b/examples/xspice/verilator/delay.v @@ -0,0 +1,14 @@ +`timescale 1us/100ns + +module delay(out); + output reg [4:0] out; + reg t; + + initial out = 0; + always begin + #1; + t = out[4]; + out <<= 1; + out[0] = ~t; + end +endmodule; // delay diff --git a/examples/xspice/verilator/pwm.cir b/examples/xspice/verilator/pwm.cir new file mode 100644 index 000000000..5f259d5ab --- /dev/null +++ b/examples/xspice/verilator/pwm.cir @@ -0,0 +1,12 @@ +* Waveform generation by PWM in Verilog + +adut null [ out ] pwm_sin +.model pwm_sin d_cosim simulation="./pwm" + +r1 out smooth 100k +c1 smooth 0 1u +.control +tran 1m 2 +plot out-3.3 smooth +.endc +.end diff --git a/examples/xspice/verilator/pwm.v b/examples/xspice/verilator/pwm.v new file mode 100644 index 000000000..5262a0c30 --- /dev/null +++ b/examples/xspice/verilator/pwm.v @@ -0,0 +1,34 @@ +`timescale 1us/100ns + +//`include "constants.vams" +`define M_TWO_PI 6.28318530717958647652 + +module pwm(out); + output reg out; + parameter Cycles = 1000, Samples = 1000; + integer i, j, width; + real sine; + + initial begin + i = 0; + j = 0; + width = Cycles / 2; + out = 0; + end + + always begin + #1; + ++i; + if (i == width) + out = 0; + if (i == Cycles) begin + i = 0; + ++j; + if (j == Samples) + j = 0; + sine = $sin(j * `M_TWO_PI / Samples); + width = $rtoi(Samples * (1.0 + sine) / 2.0); + out = (width == 0) ? 0 : 1; + end + end +endmodule // pwm