Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[Verilog] Creating comprehensive testbenches - Should timing be tested?

Status
Not open for further replies.

pigtwo

Member level 4
Joined
Jul 16, 2015
Messages
70
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Activity points
2,771
Hello all,

I have a general question about creating testbenches using Verilog(or System Verilog). Currently I'm complete garbage at creating testbenches. I usually just generate an appropriate clock and reset signal then maybe generate some very basic static data to give to the module. Then I look at the simulation to see if I find any problems. Obviously this isn't very robust and is extremely labor intensive if you need to change things. Just as an example of a type of testbench I would create below is a recent testbench I created.

Code Verilog - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
module LED_Grid_TB();
    
    reg clk_50, reset;
    
    wire we;
    wire [15:0] testdata1;
    assign testdata1 = (we) ? 16'b000111100000010 : 16'bz;
 
    reg[9:0] counter;
    reg data_read, rx, clk_rs;
    
    reg[9:0] packet1, packet2, packet3, packet4, packet5, packet6, state;
    reg[7:0] testpacket;
    LED_Grid LED_Grid1(
                            .CLOCK_50(clk_50),
                            .RESET(reset),
                            .CS_SRAM(),
                            .WE_SRAM(we),
                            .OE_SRAM(),
                            .BHE_SRAM(),
                            .BLE_SRAM(),
                            .ADDRESS_SRAM(),
                            .DATA_SRAM(testdata1),
                            .NEO_DATA_OUT(),
                            .RS232_TX(rx)
                            );
    
    initial
    begin
        testpacket = 8'b00000000;
        clk_50 = 0;
        reset = 0;
        clk_rs = 0;
        rx = 1;
        counter = 0;
        //packet1 = 10'b1011001100;
        packet1 = 10'b1001001100;
        //packet1 = 10'b1010101010;
        packet2 = 10'b1000001000;
        packet3 = 10'b1010001000;
        packet4 = 10'b1001000000;
        packet5 = 10'b1000010000;
        packet6 = {1'b1, testpacket, 1'b0};
        state = 0;
        
        #20
        reset = 1;
        
    end
 
    always @*
        forever #10 clk_50 = !clk_50;
        
    always @*
        forever #160 clk_rs = !clk_rs;
 
    always @(posedge clk_rs)
    begin
        counter = counter;
        packet1 = packet1;
        packet2 = packet2;
        packet3 = packet3;
        packet4 = packet4;
        packet5 = packet5;
        packet6 = packet6;
        state = state;
        rx = 1;
        
        case(state)
            0:
            begin
                if(counter != 10)
                begin
                    rx = packet1[0];
                    packet1 = {1'b0,packet1[9:1]};
                    counter = counter + 1;
                    state = 0;
                end
                else
                begin
                    counter = 0;
                    state = 1;
                end
            end
            
            1:
            begin
                counter = counter + 1;
                state = 1;
                rx = 1;
                if(counter == 10)
                begin
                    state = 2;
                    counter = 0;
                end
            end
            
            
            2:
            begin
                if(counter != 10)
                begin
                    rx = packet2[0];
                    packet2 = {1'b0,packet2[9:1]};
                    counter = counter + 1;
                    state = 2;
                end
                else
                begin
                    counter = 0;
                    state = 3;
                end
            end
            
            3:
            begin
                counter = counter + 1;
                state = 3;
                rx = 1;
                if(counter == 10)
                begin
                    state = 4;
                    counter = 0;
                end
            end
            
            4:
            begin
                if(counter != 10)
                begin
                    rx = packet3[0];
                    packet3 = {1'b0,packet3[9:1]};
                    counter = counter + 1;
                    state = 4;
                end
                else
                begin
                    counter = 0;
                    state = 5;
                end 
            end
            
            5:
            begin
                counter = counter + 1;
                state = 5;
                rx = 1;
                if(counter == 10)
                begin
                    state = 6;
                    counter = 0;
                end
            end
 
            6:
            begin
                if(counter != 10)
                begin
                    rx = packet4[0];
                    packet4 = {1'b0,packet4[9:1]};
                    counter = counter + 1;
                    state = 6;
                end
                else
                begin
                    counter = 0;
                    state = 7;
                end 
            end
 
            7:
            begin
                counter = counter + 1;
                state = 7;
                rx = 1;
                if(counter == 10)
                begin
                    state = 8;
                    counter = 0;
                end
            end
 
            8:
            begin
                if(counter != 10)
                begin
                    rx = packet5[0];
                    packet5 = {1'b0,packet5[9:1]};
                    counter = counter + 1;
                    state = 8;
                end
                else
                begin
                    counter = 0;
                    state = 9;
                end 
            end
 
            9:
            begin
                counter = counter + 1;
                state = 9;
                rx = 1;
                if(counter == 10)
                begin
                    state = 10;
                    counter = 0;
                end
            end
            
            10:
            begin
                if(counter != 10)
                begin
                    rx = packet6[0];
                    packet6 = {1'b0,packet6[9:1]};
                    counter = counter + 1;
                    state = 10;
                end
                else
                begin
                    counter = 0;
                    testpacket = testpacket + 1;
                    state = 11;
                end             
            end
            
            11: 
            begin
                counter = 0;
                packet1 = 10'b1011001100;
                //packet1 = 10'b1010101010;
                packet2 = 10'b1000000000;
                packet3 = 10'b1000000000;
                packet4 = 10'b1000000000;
                packet5 = 10'b1000000000;
                packet6 = {1'b1, testpacket, 1'b0};
                state = 0;
                rx = 1;
            end
            
            
        endcase
        
    end
 
endmodule


Obviously this is bad so I'm looking to improve. So I have a couple of general questions regarding all of this.

1. I'm currently working with an ADC where to start a conversion you pull the conv line low. Then after 650ns the conversion is complete. Once the conversion is complete you can pull the CS line low to start clocking out the data. When creating a test bench would you try to write it such that it would tell you if you brought the CS line low too early? For example if I pull conv low then 100ns later pull CS low, could you write your testbench such that it would give you an error saying you violated that timing? Or is this outside the scope of typical testbenches?

2. Does anyone have any resources for creating comprehensive test benches? I've looked online but most the things I find do basically the same thing I'm doing now. I'm guessing I need to learn System Verilog to make very comprehensive testbenches. I found this book(https://www.amazon.com/SystemVerilog-Verification-Learning-Testbench-Language/dp/1461407141/ref=dp_ob_title_bk) which seems like what I'm looking for but I'm not sure because I know very little about the subject.

Any other advice or suggests are greatly appreciated!

Thank you!

- - - Updated - - -

I forgot to mention that all the testbenches I want to create would be used to test code eventually implemented on a FPGA.
 

1. You can definitely do this. You can use assertions in Verilog/SV or if you want to get really serious you can use SVA (SystemVerilog Assertions). With these you can define the behaviour you expect, and it will be constantly checking to ensure that behaviour holds, otherwise you get an error. SVA is definitely a more advanced test benching topic though, so dont go feet first into this approach. SVA syntax can be rather confusing.
What I will say is that most testbenches and guides for testbenching are aimed at fully synchronous design, where all data occurs on the edges of clocks. There is nothing to say your design and testbench cannot do that, but testing for timing doesnt usually come into testbenching, but it can be done.

2. mentor's Verification Acedemy can be helpful https://verificationacademy.com/topics
and https://www.asic-world.com/verilog/index.html has a very useful Verilog Guide.

And as handy pick-up books, the doulos golden reference guides are very handy A5 spiral bound books (although the SV guide is 450 pages, you probably wont use most of it).


Comments on your code:
Dont generate clocks inside a forever loop inside an always block. You either use a forever loop inside an initial block, or just inside an always block:


Code Verilog - [expand]
1
2
3
4
5
6
7
initial begin
  forever #10 clk_50 = !clk_50;
end
 
always begin
  #160 clk_rs = !clk_rs;
end



This is because an always block is an infinite loop itself, so putting a forever loop in it seems pointless.

Also, your test code looks like logic code. While this is not a problem, in a testbench you are free to be more abstract and direct with your coding. System Verilog supports OO, which allows you to define things like packets as a class. You can then use an interface to control how that packet is driven onto an interface. This means your packet and interface are completely separated, meaning you could use the same packet definition on any interface. While this is far more complex than you need, It is just to highlight the potential you can have with verification.
 

Thank you for the response and sorry for the delay in responding. In regards to question 1, since checking timing doesn't seem completely necessary at this point I'll probably try to skip it until later. Is SV worth learning to make better testbenches or can Verilog work as well? I just notice that a lot of places mention that most simulators can't use a lot of the things SV has so I'm worried about sinking time into something I can't use.

I think the main source of my current confusion is about the scope of an average testbench. If I'm writing a testbench for a module that interfaces with an ADC I assume I would have to create some sort of model for the ADC and then something that inputs signals and reads the output and verifies them. Would you create this model such that it checked for violations in the signals or would it just respond and provide data when necessary? For example with this ADC model it expects you to pull the conv line low then after 650 ns then it will start clocking out data on the falling edge of sclk. Would you write the model such that it would raise an error if conv is pulled low again? Or would you just wait for 650ns(#650) then start responding to changes in sclk?

I realize my questions are sort of poorly formed and vague so I probably just need to learn more non-synthesizable verilog(of which I know almost none) to completely understand what tools are available to me.

Also, your test code looks like logic code.
I think this actually is my problem. When I think about writing a testbench I basically imagine a giant state machine similar to the DUT itself. Which lead me to making this thread because I thought there must be a better way to do this and I'm doing it badly. Probably the best thing for me to do is to just attempt to write the testbench in my way and then submit it here so someone can point out better ways to do things.

And thank you for those links, I've still looking through them as there is a lot there(especially the verification academy link).
 

All paid for simulators (and the free versions of) will all support SV. Verilog itself no longer exists, Verilog became SystemVerilog in 2005, What was verilog is technically a subset of SV 2005 (now up to version 2012, maybe a later revision too?)
You wont need all of the crazy stuff SV includes. Most stuff you write will probably come under Verilog anyway.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top