-
Notifications
You must be signed in to change notification settings - Fork 1
/
apb_if.sv
executable file
·192 lines (161 loc) · 7.04 KB
/
apb_if.sv
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
`ifndef APB_IF_SV
`define APB_IF_SV
interface apb_if (input clk, input rstn);
logic [31:0] paddr;
logic pwrite;
logic psel;
logic penable;
logic [31:0] pwdata;
logic [31:0] prdata;
logic pready;
logic pslverr;
// Control flags
bit has_checks = 1;
bit has_coverage = 1;
import uvm_pkg::*;
`include "uvm_macros.svh"
// Actual Signals
// USER: Add interface signals
clocking cb_mst @(posedge clk);
// USER: Add clocking block detail
default input #1ps output #1ps;
output paddr, pwrite, psel, penable, pwdata;
input prdata, pready, pslverr;
endclocking : cb_mst
// clocking cb_slv @(posedge clk);
// // USER: Add clocking block detail
// default input #1ps output #1ps;
// input paddr, pwrite, psel, penable, pwdata;
// output prdata, pready, pslverr;
// endclocking : cb_slv
clocking cb_mon @(posedge clk);
// USER: Add clocking block detail
default input #1ps output #1ps;
input paddr, pwrite, psel, penable, pwdata, prdata, pready, pslverr;
endclocking : cb_mon
// Coverage and assertions to be implemented here.
// USER: Add assertions/coverage here
// APB command covergroup
covergroup cg_apb_command @(posedge clk iff rstn);
pwrite: coverpoint pwrite{
type_option.weight = 0;
bins write = {1};
bins read = {0};
}
psel : coverpoint psel{
type_option.weight = 0;
bins sel = {1};
bins unsel = {0};
}
cmd : cross pwrite, psel{
bins cmd_write = binsof(psel.sel) && binsof(pwrite.write);
bins cmd_read = binsof(psel.sel) && binsof(pwrite.read);
bins cmd_idle = binsof(psel.unsel);
}
endgroup: cg_apb_command
// APB transaction timing group
covergroup cg_apb_trans_timing_group @(posedge clk iff rstn);
psel: coverpoint psel{
bins single = (0 => 1 => 1 => 0);
bins burst_2 = (0 => 1 [*4] => 0);
bins burst_4 = (0 => 1 [*8] => 0);
bins burst_8 = (0 => 1 [*16] => 0);
bins burst_16 = (0 => 1 [*32] => 0);
bins burst_32 = (0 => 1 [*64] => 0);
}
penable: coverpoint penable {
bins single = (0 => 1 => 0 [*2:10] => 1);
bins burst = (0 => 1 => 0 => 1);
}
endgroup: cg_apb_trans_timing_group
// APB write & read order group
covergroup cg_apb_write_read_order_group @(posedge clk iff (rstn && penable));
write_read_order: coverpoint pwrite{
bins write_write = (1 => 1);
bins write_read = (1 => 0);
bins read_write = (0 => 1);
bins read_read = (0 => 0);
}
endgroup: cg_apb_write_read_order_group
initial begin : coverage_control
if(has_coverage) begin
automatic cg_apb_command cg0 = new();
automatic cg_apb_trans_timing_group cg1 = new();
automatic cg_apb_write_read_order_group cg2 = new();
end
end
// PROPERY ASSERTION
property p_paddr_no_x;
@(posedge clk) psel |-> !$isunknown(paddr);
endproperty: p_paddr_no_x
assert property(p_paddr_no_x) else `uvm_error("ASSERT", "PADDR is unknown when PSEL is high")
property p_psel_rose_next_cycle_penable_rise;
@(posedge clk) $rose(psel) |=> $rose(penable);
endproperty: p_psel_rose_next_cycle_penable_rise
assert property(p_psel_rose_next_cycle_penable_rise) else `uvm_error("ASSERT", "PENABLE not rose after 1 cycle PSEL rose")
property p_penable_rose_next_cycle_fall;
@(posedge clk) penable && pready |=> $fell(penable);
endproperty: p_penable_rose_next_cycle_fall
assert property(p_penable_rose_next_cycle_fall) else `uvm_error("ASSERT", "PENABLE not fall after 1 cycle PENABLE rose")
property p_pwdata_stable_during_trans_phase;
@(posedge clk) ((psel && !penable) ##1 (psel && penable)) |-> $stable(pwdata);
endproperty: p_pwdata_stable_during_trans_phase
assert property(p_pwdata_stable_during_trans_phase) else `uvm_error("ASSERT", "PWDATA not stable during transaction phase")
property p_paddr_stable_until_next_trans;
logic[31:0] addr1, addr2;
@(posedge clk) first_match(($rose(penable),addr1=paddr) ##1 ((psel && !penable)[=1],addr2=$past(paddr))) |-> addr1 == addr2;
endproperty: p_paddr_stable_until_next_trans
assert property(p_paddr_stable_until_next_trans) else `uvm_error("ASSERT", "PADDR not stable until next transaction start")
property p_pwrite_stable_until_next_trans;
logic pwrite1, pwrite2;
@(posedge clk) first_match(($rose(penable),pwrite1=pwrite) ##1 ((psel && !penable)[=1],pwrite2=$past(pwrite))) |-> pwrite1 == pwrite2;
endproperty: p_pwrite_stable_until_next_trans
assert property(p_pwrite_stable_until_next_trans) else `uvm_error("ASSERT", "PWRITE not stable until next transaction start")
property p_prdata_available_once_penable_rose;
@(posedge clk) penable && !pwrite && pready |-> !$stable(prdata);
endproperty: p_prdata_available_once_penable_rose
assert property(p_prdata_available_once_penable_rose) else `uvm_error("ASSERT", "PRDATA not available once PENABLE rose")
// PROPERTY COVERAGE
property p_write_during_nonburst_trans;
@(posedge clk) $rose(penable) |-> pwrite throughout (##1 (!penable)[*2] ##1 penable[=1]);
endproperty: p_write_during_nonburst_trans
cover property(p_write_during_nonburst_trans);
property p_write_during_burst_trans;
@(posedge clk) $rose(penable) |-> pwrite throughout (##2 penable);
endproperty: p_write_during_burst_trans
cover property(p_write_during_burst_trans);
property p_write_read_burst_trans;
logic[31:0] addr;
@(posedge clk) ($rose(penable) && pwrite, addr=paddr) |-> (##2 ($rose(penable) && !pwrite && addr==paddr));
endproperty: p_write_read_burst_trans
cover property(p_write_read_burst_trans);
property p_write_twice_read_burst_trans;
logic[31:0] addr;
@(posedge clk) ($rose(penable) && pwrite, addr=paddr) |-> (##2 ($rose(penable) && pwrite && addr==paddr) ##2 ($rose(penable) && !pwrite && addr==paddr) );
endproperty: p_write_twice_read_burst_trans
cover property(p_write_twice_read_burst_trans);
property p_read_during_nonburst_trans;
@(posedge clk) $rose(penable) |-> !pwrite throughout (##1 (!penable)[*2] ##1 penable[=1]);
endproperty: p_read_during_nonburst_trans
cover property(p_read_during_nonburst_trans);
property p_read_during_burst_trans;
@(posedge clk) $rose(penable) |-> !pwrite throughout (##2 penable);
endproperty: p_read_during_burst_trans
cover property(p_read_during_burst_trans);
property p_read_write_read_burst_trans;
logic[31:0] addr;
@(posedge clk) ($rose(penable) && pwrite, addr=paddr) |-> ##2 ($rose(penable) && !pwrite && addr==paddr);
endproperty: p_read_write_read_burst_trans
cover property(p_read_write_read_burst_trans);
initial begin: assertion_control
fork
forever begin
wait(rstn == 0);
$assertoff();
wait(rstn == 1);
if(has_checks) $asserton();
end
join_none
end
endinterface : apb_if
`endif // APB_IF_SV