Generating Timing Diagrams from Verilog Simulations¶
Introduction¶
It’s very handy to generate timing diagrams directly from simulations. Once you have a timing diagram version of the simulation, you can then edit the diagram, add text annotations to show signal relationships, and then save it as an PNG, PDF, or PS file. Then just paste the diagram into the document. This is nice for specifications, review presentations, and design notes.
With the new Python scripting feature, you can generate the timing diagrams automatically from Verilog simulations. This application note shows you a way to use Verilog to generate Python scripts that will automatically build timing diagrams.
The Verilog Example¶
The DUT (Device under Test) is a simple model of a 8 bit memory, sram_1024_8.v. The testbench, sram_tb.v, contains the code needed to generate stimulus for the DUT and sram_timing_diagram.v generates the Python script to automatically build a timing diagram which contains all the signals used by the memory model.
Download all the Verilog for this Example
Output Start and Finish Timing Diagram Functions¶
The first part of the initial block outputs the scripts needed to initialize the timing diagram script. After the simulation reaches the end time, a few more script functions are needed to zoom into the complete timing diagram. These set the timing diagram start and end time and then zoom in. The Python script name is “sram_td_script.py”. This could be changed to a verilog parameter.
1initial
2begin
3 file = $fopen("sram_td_script.py","w");
4 $fwrite(file,"from ta_py_lib 'ta.app' import \*\n");
5 $fwrite(file,"from ta_py_lib 'ta.logic' import \*\n");
6 $fwrite(file,"from ta_py_lib 'ta.commands' import \*\n");
7 $fwrite(file,"td = new_timing_diagram('taApp')"\n");
8 $fwrite(file,"start_script(td)\n");
9 #end_time
10 $fwrite(file,"set_end_time(td, %0d)\n",end_time);
11 $fwrite(file,"zoom_in_full(td)\n");
12 $fwrite(file,"stop_script(td)\n");
13 $fclose(file);
14end
Add and Monitor Each Signal Functions¶
An always block is needed for every signal. The code below shows what’s needed to monitor the address signal, addr[9:0]. The first time an event is detected, the signal is added to the timing diagram. After, an new edge is added to the signal when an event is detected. You can use this as a template for other signals.
1always @ (addr)
2begin
3 if ($time >= start_time && $time < end_time)
4 begin
5 if (addr_first == 0)
6 begin
7 $fwrite(file, "addr = add_digital_bus(td, 'addr[9:0]','%h','Hex')\n",addr);
8 addr_first = 1;
9 end
10 else
11 $fwrite(file, "add_edge(td, addr,%0d,'%h')\n",$time,addr);
12 end
13end
The SRAM Timing Diagram Component¶
1`timescale 1ns / 1ps
2
3module sram_timing_diagram ( clk, addr,
4 data, cs, we, oe);
5
6input clk;
7input [9:0] addr;
8input [7:0] data;
9input cs;
10input we;
11input oe;
12
13parameter integer start_time = 0;
14parameter integer end_time = 500;
15
16
17integer file;
18
19reg clk_first = 0;
20reg addr_first = 0;
21reg data_first = 0;
22reg cs_first = 0;
23reg we_first = 0;
24reg oe_first = 0;
25
26//initial $monitor("%d %b %h %h %b %b %b",$time,clk,addr,data,cs,we,oe);
27//initial $display("start_time = %d", start_time);
28//initial $display("end_time = %d", end_time);
29
30initial
31begin
32 file = $fopen("sram_td_script.py","w");
33 $fwrite(file,"from ta_py_lib.ta.app import \*\n");
34 $fwrite(file,"from ta_py_lib.td.logic import \*\n");
35 $fwrite(file,"from ta_py_lib.td.commands import \*\n");
36 $fwrite(file,"td = new_timing_diagram(taApp)\n");
37 $fwrite(file,"start_script(td)\n");
38 #end_time
39 $fwrite(file,"set_end_time(td, %0d)\n",end_time);
40 $fwrite(file,"zoom_in_full(td)\n");
41 $fwrite(file,"stop_script(td)\n");
42 $fclose(file);
43end
44
45always @ (clk)
46begin
47 if ($time >= start_time && $time < end_time)
48 begin
49 if (clk_first == 0)
50 begin
51 $fwrite(file, "clk = add_digital_signal(td,'clk','%b')\n",clk);
52 clk_first = 1;
53 end
54 else
55 $fwrite(file, "add_edge(clk,%0d,'%b')\n",$time,clk);
56 end
57end
58
59always @ (addr)
60begin
61 if ($time >= start_time && $time < end_time)
62 begin
63 if (addr_first == 0)
64 begin
65 $fwrite(file, "addr = add_digital_bus(td,'addr[9:0]','%h','Hex')\n",addr);
66 addr_first = 1;
67 end
68 else
69 $fwrite(file, "add_edge(addr,%0d,'%h')\n",$time,addr);
70 end
71end
72
73always @ (data)
74begin
75 if ($time >= start_time && $time < end_time)
76 begin
77 if (data_first == 0)
78 begin
79 $fwrite(file, "data = add_digital_bus(td,'data[7:0]','%h','Hex')\n",data);
80 data_first = 1;
81 end
82 else
83 $fwrite(file, "add_edge(data,%0d,'%h')\n",$time,data);
84 end
85end
86
87always @ (cs)
88begin
89 if ($time >= start_time && $time < end_time)
90 begin
91 if (cs_first == 0)
92 begin
93 $fwrite(file, "cs = add_digital_signal(td,'cs','%b')\n",cs);
94 cs_first = 1;
95 end
96 else
97 $fwrite(file, "add_edge(cs,%0d,'%b')\n",$time,cs);
98 end
99end
100
101always @ (we)
102begin
103 if ($time >= start_time && $time < end_time)
104 begin
105 if (we_first == 0)
106 begin
107 $fwrite(file, "we = add_digital_signal(td,'we','%b')\n",we);
108 we_first = 1;
109 end
110 else
111 $fwrite(file, "add_edge(we,%0d,'%b')\n",$time,we);
112 end
113end
114
115always @ (oe)
116begin
117 if ($time >= start_time && $time < end_time)
118 begin
119 if (oe_first == 0)
120 begin
121 $fwrite(file, "oe = add_digital_signal(td,'oe','%b')\n",oe);
122 oe_first = 1;
123 end
124 else
125 $fwrite(file, "add_edge(oe,%0d.0e-9,'%b')\n",$time,oe);
126 end
127end
128
129endmodule