Who
Carsten Wulff
Why
I wanted to make an example of using digital code rtl/dig.v in NGSPICE.
The circuit
In design/JNW_SV_SKY130A/JNWSW_CM.sch
you’ll find a current mirror, and a
5-bit current DAC.
What we want from the digital is to control the binary value of the current DAC.
The digital code
The digital code is shown below. The clk
controls the stepping, while the
reset
sets the output b=0
. When reset
is off, then the b
increments.
module dig(
input wire clk,
input wire reset,
output logic [4:0] b
);
logic rst = 0;
always_ff @(posedge clk) begin
if(reset)
rst <= 1;
else
rst <= 0;
end
always_ff @(posedge clk) begin
if(rst)
b <= 0;
else
b <= b + 1;
end // dig
endmodule
Compile RTL
The first thing we need to do is to translate the verilog into a compiled object that can be used in ngspice.
cd sim/JNWSW_CM
ngspice vlnggen ../../rtl/dig.v
Import object into spice file
I’m lazy. So I don’t want to do the same thing multiple times. As such, I’ve written a small script to help me instanciate the verilog
perl ../../tech/script/gensvinst ../../rtl/dig.v dig
The script generates an svninst.spi
file. The first section imports the
digital compiled library
adut [clk
+ reset
+ ]
+ [b.4
+ b.3
+ b.2
+ b.1
+ b.0
+ ] null dut
.model dut d_cosim simulation="../dig.so" delay=10p
Turns out that ngspice needs the digital inputs and outputs to be connected to something to calculate them (I think), so connect some resistors
* Inputs
Rsvi0 clk 0 1G
Rsvi1 reset 0 1G
* Outputs
Rsvi2 b.4 0 1G
Rsvi3 b.3 0 1G
Rsvi4 b.2 0 1G
Rsvi5 b.1 0 1G
Rsvi6 b.0 0 1G
For the busses I find it easier to read the value as a real, so translate the
buses from digital b[4:0]
to a real value dec_b
E_STATE_b dec_b 0 value={( 0
+ + 16*v(b.4)/AVDD
+ + 8*v(b.3)/AVDD
+ + 4*v(b.2)/AVDD
+ + 2*v(b.1)/AVDD
+ + 1*v(b.0)/AVDD
+)/1000}
.save v(dec_b)
Import in testbench
An example testbench can be seen below (sim/JNWSW_CM/tran.spi
)
VSS VSS 0 dc 0
VDD VDD_1V8 0 dc {AVDD}
VCLK clk 0 dc 0 pulse (0 {AVDD} 0 {TRF} {TRF} {PW_CLK} {PERIOD_CLK})
VRESET reset 0 dc {AVDD} pwl 0 {AVDD} {PW_CLK*2} {AVDD} {PW_CLK*2 + 1n} 0
.include ../xdut.spi
.include ../svinst.spi
* Translate names
VB0 b.0 b<0> dc 0
VB1 b.1 b<1> dc 0
VB2 b.2 b<2> dc 0
VB3 b.3 b<3> dc 0
VB4 b.4 b<4> dc 0
*- Bias current
IBPS 0 ibp dc 100n
* RC filter to calm the IDAC output
CDL IBN_DAC 0 10p
R1 IBN_DAC IBN_FILT 1k
VDAC IBN_FILT 0 dc 0.9
* The other bias currents
VI0 IBN_0 0 dc 0.9
VI1 IBN_1 0 dc 0.9
VI2 IBN_2 0 dc 0.9
...
Override default digital output voltage
We can override the output dac from digital to analog to ensure that the digital signals have the right levels
*- Override the default digital output bridge.
pre_set auto_bridge_d_out =
+ ( ".model auto_dac dac_bridge(out_low = 0.0 out_high = 1.8)"
+ "auto_bridge%d [ %s ] [ %s ] auto_dac" )
Running
You can run the whole thing with
cd sim/JNWSW_CM/
make typical