Verilog Simulation & Debugging Toolsmedia.ee.ntu.edu.tw/Crash_course/2019/RTL_verification.pdfThe...
Transcript of Verilog Simulation & Debugging Toolsmedia.ee.ntu.edu.tw/Crash_course/2019/RTL_verification.pdfThe...
Verilog Simulation
Tools &Verification
Outline
NC-Verilog
nLint
nWave
Nicotb
2
NC-Verilog
3
Introduction to NC-Verilog
The Cadence® NC-Verilog® simulator is a Verilog digital
logic simulator.
We can use NC-Verilog to
Compiles the Verilog source files.
Elaborates the design and generates a simulation snapshot.
Simulates the snapshot.
4
Before Using NC-Verilog
Source the environment settings of CAD tools.
If you try entering the command "ncverilog" but it turns
out "command not found," it means there's something
wrong with the "*.cshrc" file or the software license is out
of date.
tool 2
5
source /usr/cad/cadence/CIC/incisiv.cshrc
Running Verilog
Run the Verilog simulation:
"+access+r" is added to enable waveform file dumping.
*.fsdb has smaller file size than *.vcd. But $fsdbDumpfile
cannot work without sourcing verdi.cshrc.
6
ncverilog testbench.v design.v +access+r
or
Simulation Results
Check the simulation result to see if the Verilog design is
finished correctly.
7
nLint
8
Introduction to nLint
nLint is a comprehensive HDL design rule checker fully
integrated with the Debussy debugging system
(Developed by SpringSoft).
We can use nLint to check the coding style of our design
and if it is synthesizable.
9
Start nLint
Type the following command:
The token "&" enable you to use the terminal while nLint is
running in the background.
No gui command
10
nLint -gui &
Just ignore this warning.
nLint design.sv -sv -out screen
Specify the Design File
11
1
12
1
2
3
4
5
Start Checking
13
1
14
Not all the warnings or errors are valuable.
nWave
15
Introduction to nWave
nWave is one of the best waveform (*.vcd or *.fsdb)
viewer.
We can debug easily by checking the waveform file
dumped during simulation.
16
Start nWave
Type the following command:
Also, the token "&" enable you to use the terminal while
Verdi is running in the background.
17
nWave &
Just ignore this warning.
Open the FSDB File
18
1
19
1
2
3
Choose Signals
20
1
21
Choose signals we
are interested in.
1
2
3 4
Browse the Whole Waveform
22
1
Browse the Specified Interval
23
press & drag
24
Search for Specified Signal
25
1
2 34,5,…
26
cursor position
(Search by rising oe)
Jump to the cursor position (Used when we are lost)
Change Sign Representation
27
1
2
3
Change Radix Representation
28
2
1
3
4
Leading zeros
29
Change Signal Position
30
1
2
Press middle mouse button,
drag and then drop.
Signal Aliasing
31
1
2
3
4
32
1
2
3
Note that signal aliasing is a strict one-to-
one correspondence so the value
represented in the viewer must exactly
represent what format your filter expects.
(e.g., binary, hexadecimal)
6
4
5
33
Reload the Waveform
Remember to reload the waveform whenever finishing
another Verilog simulation.
Shift+L
34
1
Nicotb
35
UVM (Universal Verfication Methodology).
(We usually call this overall platform as testbench.)
What Forms Verification?
36
https://verificationacademy.comGenerate Golden Data Your RTL
Drive data to input ports
Monitor output ports and collect data
The non-RTL parts can be implemented without Verilog!
This is usuallyed called co-simulation (co-sim).
The Non-RTL Parts
37
Instantiate (make a copy of) your module.
Driver to send data.
Monitor to receive and collect them.
Driver and Monitor might follow specific protocols.
The collected data are compared by Scoreboard.
Golden (Mostly text file in Verilog, or programmatically when co-simed.)
Generated by your RTL module and collected by Monitor.
Brief Conclusions - A Testbench Must
38
Verilog provide external C accesses through VPI.
https://en.wikipedia.org/wiki/Verilog_Procedural_Interface
Based on C, people develops Java, Python... versions.
AFAIK, there are quite a lot Python based frameworks.
myhdl: https://github.com/myhdl/myhdl
cocotb: https://github.com/potentialventures/cocotb
nicotb: https://github.com/johnjohnlin/nicotb
No Need for Verify RTL with Verilog
39
We focus on this today.
Bridging Python and Verilog (Events)
Add these lines in Python
○ rst_out_ev, ck_ev = CreateEvents(["rst_out", "ck_ev",])
Add this lines in Verilog
○ `Pos(rst_out, rst)`PosIf(ck_ev, clk, rst)
This means, whenever a clk posedge in Python, ck_ev is triggered
Mostly your submodules use 1 reset and clock and you just copy it.
That is,
Python yield ck_ev = Verilog @posedge clk
However, simply writing yield in Python doesn't make thing easier.
We will explain later.
40
Bridging Python and Verilog (Wires)
● API to connect Verilog wires
○ my_data_bus = CreateBus((
("", "a_signal", (4,2)),
("dut", "sig"),
))
The Verilog to be connected
○ logic [7:0] a_signal [4][2];
DUT my_dut(
.clk(clk),
.sig(sig)
)
41
hierarchy: toplevel → ""
name: a_signal
shape: (4,2)
Bridging Python and Verilog (Wires)
API to connect Verilog wires
○ my_data_bus = CreateBus((
("", "a_signal", (4,2)),
("dut", "sig"),
))
The Verilog to be connected
○ logic [7:0] a_signal [4][2];
DUT dut(
.clk(clk),
.sig(sig)
)
42
hierarchy: "dut" (nested: "dut.a.b")
name: sig
shape: not a array
Some Notes
Make use of Python unpack easily.
a = CreateBus(A)b = CreateBus(B)c = CreateBus(C)a, b, c = CreateBuses([A, B, C])
● This is the method of Nicotb, every framework has its method connecting
Verilog to Python (or whatever).
43
For example, your code:
○ module Dut(
input clk,
input rst,
input irdy,
output logic iack,
input [10:0] iint,
output logic ordy,
input oack,
output logic [10:0] oint
);
You can test every module with the same API.
Interface Reuse → Testbench Reuse
44
DutInput Output
Dataflow graph.
First, you need to create the buses
irdy = CreateBus((("dut", "irdy")))iack = CreateBus((("dut", "iack")))iint = CreateBus((("dut", "iint")))ordy = CreateBus((("dut", "ordy")))oack = CreateBus((("dut", "oack")))oint = CreateBus((("dut", "oint")))
Then, construct the classes in Python.
master = TwoWire.Master(irdy, iack, iint, ck_ev, A=1, B=5)slave = TwoWire.Slave(
ordy, oack, oint, ck_ev, callbacks=[test.Get])
Convert Bus into Protocol
45
Generate golden data for Scoreboard (not today's main issue).
Ns = np.array([0,8,7], dtype=np.int32)# this create a column vector [0, 0, 1, 2, ..., 8, 0, 1, ..., 7]golden = np.concatenate([
np.arange(N+1, dtype=np.int32) for N in Ns])[:,np.newaxis]test.Expect((golden,))
What should I Expect?
Check at Scoreboard
46
Look at the data bus.
ordy = CreateBus((("dut", "ordy")))oack = CreateBus((("dut", "oack")))oint = CreateBus((("dut", "oint")))
Slave put that to Scoreboard.
st = Stacker(1+9+8, [bg.Get]) # PS: 1+9+8+=18bg = BusGetter(callbacks=[st.Get])slave = TwoWire.Slave(
ordy, oack, oint, ck_ev, callbacks=[bg.Get])
oint is a bus with one scalar (aka, not an array), so you get a tuple of size ([18,
1],).
Data Format in Nicotb
47
The actual code is slightly more
complex than above pages, while
you can just copy and modify.
Look at the data bus.
oint = CreateBus((("dut", "aaa")("dut", "bbb", (1,))("dut", "ccc", (12,3))
))
In this example, the tuple size is ([18, 1], [18, 1], [18, 12, 3]).
Data Format in Nicotb
48
Look at the data bus.
golden = np.concatenate([np.arange(N+1, dtype=np.int32) for N in Ns
])[:,np.newaxis]test.Expect((golden,))
golden is a tuple of size ([18, 1],).
np.concatenate generate a array of size [18,], namely a row vector.
The [:, np.newaxis] is the standard method converting Numpy row vector to a
column vector (vertical one).
Back to Our Example
49
Prepare the RTL for design under test (DUT).
Script for loading Python automatically (Makefile).
SystemVerilog wrapper.
Python testbench.
Prepare input data and golden (it's your task).
Send the data.
Check the data at scoreboard.
We are Almost Done!
50
OO
O
△
OX
O
OX
O O
O
Drive Verilog Wire In Python (Quite Easy!)
master = TwoWire.Master(irdy, iack, iint, ck_ev, A=1, B=5)values = master.valuesdef it():
for N in Ns:values.iint[0] = Nyield values
yield from master.SendIter(it())
yield from master.SendIter(it(), latency=100)
51
Access data bus by name
values.iint is a Numpy array of size (1,)
This randomly drive the input.
This drive data every 100 cycles.
Probability = A/B (default = 1/5)
Note
values = master.valuesdef it():
for N in Ns:values.iint[0] = Nyield values
yield from master.SendIter(it())yield from master.SendIter(it(), latency=100)
52
This part is only Python generator syntax,
it has no relationship with waiting Verilog
posedge!!!
Every 100 cycles (ignore probability)
Prepare a Verilog Wrapper
`Pos(rst_out, rst)`PosIf(ck_ev, clk, rst)
always #1 clk = ~clk;initial begin
clk = 0;rst = 1;#1 $NicotbInit();#11 rst = 0;#10 rst = 1;#1000 $display("Timeout");$NicotbFinal();$finish;
end
assign oack = ordy && ocanack;Dut dut(clk,rst,irdy,iack,iint,ordy,oack,oint);
53
Declare your module here!
While you might not understand it,
this template requires almost no
modifications!
Declare your module here!
(Prepare a Makefile)
NICOTB=~/nicotb/libIRUN=/opt/CAD/INCISIV/cur/tools.lnx86/bin/64bit/irun
%: %.svGLOG_logtostderr=1 \TEST=$(if $(TEST),$(TEST),$@) \TOPMODULE=$(if $(TOPMODULE),$(TOPMODULE),$@) \PYTHONPATH=$(NICOTB)/python:`pwd` \$(IRUN) +access+rw -loadvpi $(NICOTB)/cpp/nicotb.so:VpiBoot \$(NICOTB)/verilog/Utils.sv $<
54
Modify according to your path
(irun = ncverilog)
You must prepare XXX_test.py and XXX_test.sv under current directory
(see previous pages). Also, the top level testbench module is XXX_test.
Then, just type make XXX. The lab in these days is an example.
● Introduce the idea behind SystemVerilog UVM.
With Python, you can do the same thing much easily.
We introduce Nicotb today.
Document: https://johnjohnlin.github.io/nicotb/
And there are many choices.
myhdl: https://github.com/myhdl/myhdl
cocotb: https://github.com/potentialventures/cocotb
Conclusions
55
The End