
1. Overview
If the designer creates the product, the simulator is the person who ensures that the product has to meet the best quality when it reaches the customer.
The most important purpose of the tester is not just to find bugs (design defects) but to make sure the design works completely exactly as required. That is, not only the function is properly designed, but other parameters such as processing performance, response speed, ... if any, must also be guaranteed.
The cost for each fabrication and production of microchips is extremely expensive. Depending on the technology, if only trial production, the amount can be from tens to hundreds of USD for a batch of 20 to 40 chips. Just one error can cause the product to be completely discarded, so the inspection work is increasingly standardized, professional and has specific methods.
2. Content:
Verification Of UART Part – II
Verification Of UART Part - III
+ Verification Of UART Part - I
This testbench will slightly different from what we have seen till now.
So the verification components are split into following blocks |
|
We are going to have some more components that like reset. Logic to control when to terminate.
+ Verification Of UART Part – II
Device Under Test
1 //-----------------------------------------------------
2 // Design Name : uart
3 // File Name : uart.v
4 // Function : Simple UART
5 // Coder : Deepak Kumar Tala
6 //-----------------------------------------------------
7 module uart (
8 reset ,
9 txclk ,
10 ld_tx_data ,
11 tx_data ,
12 tx_enable ,
13 tx_out ,
14 tx_empty ,
15 rxclk ,
16 uld_rx_data ,
17 rx_data ,
18 rx_enable ,
19 rx_in ,
20 rx_empty
21 );
22 // Port declarations
23 input reset ;
24 input txclk ;
25 input ld_tx_data ;
26 input [7:0] tx_data ;
27 input tx_enable ;
28 output tx_out ;
29 output tx_empty ;
30 input rxclk ;
31 input uld_rx_data ;
32 output [7:0] rx_data ;
33 input rx_enable ;
34 input rx_in ;
35 output rx_empty ;
36
37 // Internal Variables
38 reg [7:0] tx_reg ;
39 reg tx_empty ;
40 reg tx_over_run ;
41 reg [3:0] tx_cnt ;
42 reg tx_out ;
43 reg [7:0] rx_reg ;
44 reg [7:0] rx_data ;
45 reg [3:0] rx_sample_cnt ;
46 reg [3:0] rx_cnt ;
47 reg rx_frame_err ;
48 reg rx_over_run ;
49 reg rx_empty ;
50 reg rx_d1 ;
51 reg rx_d2 ;
52 reg rx_busy ;
53
54 // UART RX Logic
55 always @ (posedge rxclk or posedge reset)
56 if (reset) begin
57 rx_reg <= 0;
58 rx_data <= 0;
59 rx_sample_cnt <= 0;
60 rx_cnt <= 0;
61 rx_frame_err <= 0;
62 rx_over_run <= 0;
63 rx_empty <= 1;
64 rx_d1 <= 1;
65 rx_d2 <= 1;
66 rx_busy <= 0;
67 end else begin
68 // Synchronize the asynch signal
69 rx_d1 <= rx_in;
70 rx_d2 <= rx_d1;
71 // Uload the rx data
72 if (uld_rx_data) begin
73 rx_data <= rx_reg;
74 rx_empty <= 1;
75 end
76 // Receive data only when rx is enabled
77 if (rx_enable) begin
78 // Check if just received start of frame
79 if ( ! rx_busy && ! rx_d2) begin
80 rx_busy <= 1;
81 rx_sample_cnt <= 1;
82 rx_cnt <= 0;
83 end
84 // Start of frame detected, Proceed with rest of data
85 if (rx_busy) begin
86 rx_sample_cnt <= rx_sample_cnt + 1;
87 // Logic to sample at middle of data
88 if (rx_sample_cnt == 7) begin
89 if ((rx_d2 == 1) && (rx_cnt == 0)) begin
90 rx_busy <= 0;
91 end else begin
92 rx_cnt <= rx_cnt + 1;
93 // Start storing the rx data
94 if (rx_cnt > 0 && rx_cnt < 9) begin
95 rx_reg[rx_cnt - 1] <= rx_d2;
96 end
97 if (rx_cnt == 9) begin
98 rx_busy <= 0;
99 // Check if End of frame received correctly
100 if (rx_d2 == 0) begin
101 rx_frame_err <= 1;
102 end else begin
103 rx_empty <= 0;
104 rx_frame_err <= 0;
105 // Check if last rx data was not unloaded,
106 rx_over_run <= (rx_empty) ? 0 : 1;
107 end
108 end
109 end
110 end
111 end
112 end
113 if ( ! rx_enable) begin
114 rx_busy <= 0;
115 end
116 end
117
118 // UART TX Logic
119 always @ (posedge txclk or posedge reset)
120 if (reset) begin
121 tx_reg <= 0;
122 tx_empty <= 1;
123 tx_over_run <= 0;
124 tx_out <= 1;
125 tx_cnt <= 0;
126 end else begin
127 if (ld_tx_data) begin
128 if ( ! tx_empty) begin
129 tx_over_run <= 0;
130 end else begin
131 tx_reg <= tx_data;
132 tx_empty <= 0;
133 end
134 end
135 if (tx_enable && ! tx_empty) begin
136 tx_cnt <= tx_cnt + 1;
137 if (tx_cnt == 0) begin
138 tx_out <= 0;
139 end
140 if (tx_cnt > 0 && tx_cnt < 9) begin
141 tx_out <= tx_reg[tx_cnt -1];
142 end
143 if (tx_cnt == 9) begin
144 tx_out <= 1;
145 tx_cnt <= 0;
146 tx_empty <= 1;
147 end
148 end
149 if ( ! tx_enable) begin
150 tx_cnt <= 0;
151 end
152 end
153
154 endmodule
HDL Testbench Top
1 `include "uart.v"
2 module top();
3
4 reg reset ;
5 reg txclk ;
6 reg ld_tx_data ;
7 reg [7:0] tx_data ;
8 reg tx_enable ;
9 wire tx_out ;
10 wire tx_empty ;
11 reg rxclk ;
12 reg uld_rx_data ;
13 wire [7:0] rx_data ;
14 reg rx_enable ;
15 wire rx_in ;
16 wire rx_empty ;
17 reg loopback ;
18 reg rx_tb_in ;
19
20 initial begin
21 reset = 0;
22 txclk = 0;
23 ld_tx_data = 0;
24 tx_data = 0;
25 tx_enable = 0;
26 rxclk = 0;
27 uld_rx_data = 0;
28 rx_enable = 0;
29 loopback = 0;
30 rx_tb_in = 1;
31 end
32 // Loopback control logic
33 assign rx_in = (loopback) ? tx_out : rx_tb_in;
34 // RX and TX Clock generation
35 always #1 rxclk = ~rxclk;
36 always #16 txclk = ~txclk;
37
38 // DUT Connected here
39 uart U (
40 .reset (reset),
41 .txclk (txclk),
42 .ld_tx_data (ld_tx_data),
43 .tx_data (tx_data),
44 .tx_enable (tx_enable),
45 .tx_out (tx_out),
46 .tx_empty (tx_empty),
47 .rxclk (rxclk),
48 .uld_rx_data (uld_rx_data),
49 .rx_data (rx_data),
50 .rx_enable (rx_enable),
51 .rx_in (rx_in),
52 .rx_empty (rx_empty)
53 );
54
55 endmodule
E Testbench Top
1 <'
2 import uart_clk.e;
3 import uart_sb.e;
4 import uart_txgen.e;
5
6 struct uart_tb {
7
8 sb : uart_sb;
9 txgen : uart_txgen;
10 keep txgen.sb == sb;
11
12 go()@sys.any is {
13 start txgen.goTxgen();
14 start terminate();
15 };
16
17 terminate()@sys.txclk is {
18 var timeout : uint = 0;
19 while ( ! txgen.isDone()) {
20 wait cycle;
21 };
22 wait [20]*cycle;
23 outf("%dns : Termintating the simulation\n",sys.time);
24 stop_run();
25 };
26 };
27
28 extend sys {
29 tb : uart_tb;
30 run() is also {
31 start tb.go();
32 };
33 };
34 '>
UART Clock
1 <'
2 extend sys {
3 event rxclk is rise('top.rxclk') @sim;
4 event txclk is rise('top.txclk') @sim;
5 };
6 '>
+ Verification Of UART Part - III
UART Scoreboard
1 <'
2 struct uart_sb {
3 ! tx : list of byte;
4 ! rx : list of byte;
5
6 txAdd(data : byte) is {
7 tx.push(data);
8 };
9
10 rxAdd(data : byte) is {
11 rx.push(data);
12 };
13
14 txCompare(data : byte) is {
15 var org_data : byte = tx.pop0();
16 if (data ! = org_data) {
17 outf("%dns : txCompare : Error : Expected data %x, Got %x\n",
18 sys.time, org_data, data);
19 };
20 };
21
22 rxCompare(data : byte) is {
23 var org_data : byte = rx.pop0();
24 if (data ! = org_data) {
25 outf("%dns : rxCompare : Error : Expected data %x, Got %x\n",
26 sys.time, org_data, data);
27 };
28 };
29
30 };
31 '>
UART Transcation Generator
1 <'
2 struct uart_txgen {
3 sb : uart_sb;
4
5 ! tx_done : bit;
6 ! rx_done : bit;
7
8 // Connects the transmitter output to recevier input
9 loopback : bit;
10 keep loopback == 0;
11 // Number of frames to send to transmitter
12 no_tx_cmds : uint;
13 keep no_tx_cmds == 1;
14 // Number of frames to send to receiver
15 no_rx_cmds : uint;
16 keep no_rx_cmds == 1;
17 // Delay the reading of data from receiver
18 rx_over_flow : bit;
19 keep rx_over_flow == 0;
20 // Send frame to transmitter before it has sent out last frame
21 tx_over_flow : bit;
22 keep tx_over_flow == 0;
23 // Insert framming error (stop bit) in frame sent to receiver
24 rx_frame_err : bit;
25 keep rx_frame_err == 0;
26
27 // Main method, which starts rest of methods
28 goTxgen()@sys.any is {
29 tx_done = 0;
30 rx_done = 0;
31 assertReset();
32 start txDriver();
33 start rxDriver();
34 start txMonitor();
35 start rxMonitor();
36 };
37 // This method asserts method
38 assertReset()@sys.rxclk is {
39 wait cycle;
40 'top.reset' = 1;
41 outf("%dns : Asserting reset to Uart\n",sys.time);
42 wait [5]*cycle;
43 'top.reset' = 0;
44 };
45
46 txDriver()@sys.txclk is {
47 var tx_timeout : uint = 0;
48 var tx_data : byte = 0;
49 'top.tx_enable' = 1;
50 for {var i : uint = 0; i < no_tx_cmds; i = i + 1} do {
51 gen tx_data;
52 sb.txAdd(tx_data);
53 if (loopback == 1) {
54 sb.rxAdd(tx_data);
55 };
56 // Check if uart is ready to accept data for transmission
57 while ('top.tx_empty' == 0) {
58 wait cycle;
59 tx_timeout =+ 1 ;
60 if (tx_timeout > 10) {
61 outf("%dns : txDriver : Warning : tx_empty is 0 for more then 10 clocks\n",
62 sys.time);
63 };
64 };
65 tx_timeout = 0;
66 // Drive the data in UART for transmitting
67 wait cycle;
68 'top.ld_tx_data' = 1;
69 'top.tx_data' = tx_data;
70 outf("%dns : txDriver : Transmitting data %x\n",sys.time, tx_data);
71 wait cycle;
72 'top.ld_tx_data' = 0;
73 'top.tx_data' = 0;
74 while ('top.tx_empty' == 1) {
75 wait cycle;
76 tx_timeout =+ 1 ;
77 if (tx_timeout > 10) {
78 outf("%dns : txDriver : Warning : tx_empty is 1 for more then 10 clocks\n",
79 sys.time);
80 };
81 };
82 tx_timeout = 0;
83 };
84 tx_done = 1;
85 };
86
87 rxDriver()@sys.txclk is {
88 var rx_data : byte = 0;
89 'top.rx_enable' = 1;
90 if (loopback == 1) {
91 'top.loopback' = 1;
92 } else {
93 'top.loopback' = 0;
94 for {var i : uint = 0; i < no_rx_cmds; i = i + 1} do {
95 gen rx_data;
96 sb.rxAdd(rx_data);
97 outf("%dns : rxDriver : Transmitting data %x\n",sys.time, rx_data);
98 wait cycle;
99 'top.rx_in' = 0;
100 for {var j : uint = 0; j < 8; j = j + 1} do {
101 wait cycle;
102 'top.rx_in' = rx_data[j:j];
103 };
104 wait cycle;
105 'top.rx_in' = 1;
106 wait cycle;
107 };
108 };
109 rx_done = 1;
110 };
111
112 txMonitor()@sys.txclk is {
113 var tx_data : byte = 0;
114 while (TRUE) {
115 wait cycle;
116 if ('top.tx_out' == 0) {
117 outf("%dns : txMonitor : Found start of frame\n",sys.time);
118 for {var i : uint = 0; i < 8; i = i + 1} do {
119 wait cycle;
120 tx_data[i:i] = 'top.tx_out';
121 };
122 wait cycle;
123 if ('top.tx_out' == 0) {
124 outf("%dns : txMonitor Error : Framing error detecting\n",sys.time);
125 sb.txCompare(8'b0);
126 } else {
127 outf("%dns : txMonitor : Sampled data %x\n",sys.time, tx_data);
128 sb.txCompare(tx_data);
129 };
130 };
131 };
132 };
133
134 rxMonitor()@sys.rxclk is {
135 var rx_data : byte = 0;
136 while (TRUE) {
137 wait cycle;
138 if ('top.rx_empty' == 0) {
139 'top.uld_rx_data' = 1;
140 wait cycle;
141 rx_data = 'top.rx_data';
142 'top.uld_rx_data' = 0;
143 outf("%dns : rxMonitor : Sampled data %x\n",sys.time, rx_data);
144 sb.rxCompare(rx_data);
145 wait cycle;
146 };
147 };
148 };
149
150 isDone() : bool is {
151 var status : bool = FALSE;
152 if (tx_done == 1 && rx_done == 1) {
153 status = TRUE;
154 };
155 return status;
156 };
157 };
158 '>
Bạn Có Đam Mê Với Vi Mạch hay Nhúng - Bạn Muốn Trau Dồi Thêm Kĩ Năng
Mong Muốn Có Thêm Cơ Hội Trong Công Việc
Và Trở Thành Một Người Có Giá Trị Hơn
Mong Muốn Có Thêm Cơ Hội Trong Công Việc
Và Trở Thành Một Người Có Giá Trị Hơn