1 |
12 |
juko |
/*
|
2 |
|
|
* .--------------. .----------------. .------------.
|
3 |
|
|
* | .------------. | .--------------. | .----------. |
|
4 |
|
|
* | | ____ ____ | | | ____ ____ | | | ______ | |
|
5 |
|
|
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
|
6 |
|
|
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
|
7 |
|
|
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
|
8 |
|
|
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
|
9 |
|
|
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
|
10 |
|
|
* | | | | | | | | | | | |
|
11 |
|
|
* |_| | '------------' | '--------------' | '----------' |
|
12 |
|
|
* '--------------' '----------------' '------------'
|
13 |
|
|
*
|
14 |
|
|
* openHMC - An Open Source Hybrid Memory Cube Controller
|
15 |
|
|
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
|
16 |
|
|
* www.ziti.uni-heidelberg.de
|
17 |
|
|
* B6, 26
|
18 |
|
|
* 68159 Mannheim
|
19 |
|
|
* Germany
|
20 |
|
|
*
|
21 |
|
|
* Contact: openhmc@ziti.uni-heidelberg.de
|
22 |
|
|
* http://ra.ziti.uni-heidelberg.de/openhmc
|
23 |
|
|
*
|
24 |
|
|
* This source file is free software: you can redistribute it and/or modify
|
25 |
|
|
* it under the terms of the GNU Lesser General Public License as published by
|
26 |
|
|
* the Free Software Foundation, either version 3 of the License, or
|
27 |
|
|
* (at your option) any later version.
|
28 |
|
|
*
|
29 |
|
|
* This source file is distributed in the hope that it will be useful,
|
30 |
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
31 |
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
32 |
|
|
* GNU Lesser General Public License for more details.
|
33 |
|
|
*
|
34 |
|
|
* You should have received a copy of the GNU Lesser General Public License
|
35 |
|
|
* along with this source file. If not, see .
|
36 |
|
|
*
|
37 |
|
|
*
|
38 |
|
|
*/
|
39 |
|
|
|
40 |
|
|
//
|
41 |
|
|
//
|
42 |
|
|
// AXI4 Stream Interface
|
43 |
|
|
//
|
44 |
|
|
//
|
45 |
|
|
|
46 |
|
|
`ifndef AXI4_STREAM_IF_SV
|
47 |
|
|
`define AXI4_STREAM_IF_SV
|
48 |
|
|
|
49 |
15 |
juko |
interface axi4_stream_if #(parameter DATA_BYTES = 16, parameter TUSER_WIDTH = 16) ();
|
50 |
12 |
juko |
|
51 |
|
|
//--
|
52 |
|
|
//-- Interface signals
|
53 |
|
|
//--
|
54 |
|
|
|
55 |
15 |
juko |
logic ACLK; //-- Clock (All signals sampled on the rising edge)
|
56 |
|
|
logic ARESET_N; //-- Global Reset
|
57 |
|
|
|
58 |
12 |
juko |
logic TVALID; // Master valid
|
59 |
|
|
logic TREADY; // Slave ready
|
60 |
|
|
logic [8*DATA_BYTES-1:0] TDATA; //-- Master data
|
61 |
|
|
logic [TUSER_WIDTH-1:0] TUSER; //-- Master sideband signals
|
62 |
|
|
|
63 |
|
|
|
64 |
|
|
//--
|
65 |
|
|
//--DEBUG signals
|
66 |
|
|
//--
|
67 |
|
|
|
68 |
|
|
logic [DATA_BYTES/16-1:0] DEBUG_VALIDS; //-- contains the HMC-VALID Flags
|
69 |
|
|
logic [DATA_BYTES/16-1:0] DEBUG_HEADERS; //-- contains the HMC-HEADER Flags
|
70 |
|
|
logic [DATA_BYTES/16-1:0] DEBUG_TAILS; //-- contains the HMC-TAIL Flags
|
71 |
|
|
|
72 |
15 |
juko |
|
73 |
12 |
juko |
//-- assigning the debug signals to TUSER
|
74 |
|
|
assign DEBUG_VALIDS = TUSER[1*(DATA_BYTES /16)-1: (0* DATA_BYTES /16)];
|
75 |
|
|
assign DEBUG_HEADERS = TUSER[2*(DATA_BYTES /16)-1: (1* DATA_BYTES /16)];
|
76 |
|
|
assign DEBUG_TAILS = TUSER[3*(DATA_BYTES /16)-1: (2* DATA_BYTES /16)];
|
77 |
|
|
|
78 |
|
|
//--
|
79 |
|
|
//-- Interface Coverage
|
80 |
|
|
//--
|
81 |
|
|
|
82 |
|
|
covergroup axi4_cg @ (posedge ACLK);
|
83 |
|
|
option.per_instance = 1;
|
84 |
|
|
T_VALID : coverpoint TVALID;
|
85 |
|
|
T_READY : coverpoint TREADY;
|
86 |
|
|
|
87 |
|
|
//-- cover the amount of consecutive AXI4 transactions
|
88 |
|
|
CONSECUTIVE_TRANSACTIONS: coverpoint {TVALID , TREADY}{
|
89 |
|
|
bins transactions_single = (0,1,2 =>3 => 0,1,2);
|
90 |
|
|
bins transactions_1_5[] = (0,1,2 =>3[*2:10] => 0,1,2);
|
91 |
|
|
bins transactions_11_50[] = (0,1,2 =>3[*11:50] => 0,1,2);
|
92 |
|
|
bins transactions_huge = (0,1,2 =>3[*51:100000]=> 0,1,2);
|
93 |
|
|
}
|
94 |
|
|
|
95 |
|
|
//-- cover the waiting time after TVALID is set until TREADY in clock cycles
|
96 |
|
|
TRANSACTION_WAITING: coverpoint {TVALID , TREADY}{
|
97 |
|
|
bins zero_waiting_time = (0,1 => 3);
|
98 |
|
|
bins low_waiting_time[] = (2[*1:5] => 3);
|
99 |
|
|
bins medium_waiting_time[] = (2[*6:15] => 3);
|
100 |
|
|
bins high_waiting_time = (2[*16:100000] => 3);
|
101 |
|
|
illegal_bins illegal = (2 => 0);
|
102 |
|
|
}
|
103 |
|
|
|
104 |
|
|
//-- Pause between Transactions
|
105 |
|
|
TRANSACTION_PAUSE: coverpoint {TVALID , TREADY}{
|
106 |
|
|
bins low_waiting_time[] = (3 => 0[*1:5] => 2,3);
|
107 |
|
|
bins medium_waiting_time[] = (3 => 0[*6:15] => 2,3);
|
108 |
|
|
bins high_waiting_time = (3 => 0[*16:100] => 2,3);
|
109 |
|
|
}
|
110 |
|
|
|
111 |
|
|
//-- cover the time TREADY is active until deassertion or TVALID in clock cycles
|
112 |
|
|
READY_WITHOUT_VALID: coverpoint {TVALID , TREADY}{
|
113 |
|
|
bins short_ready_time[] = (1[*1:5] => 3,0);
|
114 |
|
|
bins medium_ready_time[] = (1[*6:15] => 3,0);
|
115 |
|
|
bins high_ready_time = (1[*16:100000]=> 3,0);
|
116 |
|
|
}
|
117 |
|
|
|
118 |
|
|
//--cover all available transitions of TVALID/TREADY
|
119 |
|
|
CASES_VALID_READY : cross T_VALID, T_READY;
|
120 |
|
|
TRANSITIONS: coverpoint {TVALID, TREADY}{
|
121 |
|
|
bins transition[] = ( 0,1,3 => [0:3]), (2 => 2,3) ;
|
122 |
|
|
}
|
123 |
|
|
|
124 |
|
|
//-- cover active VALID Flags
|
125 |
|
|
VALID_FLAGS : coverpoint DEBUG_VALIDS;
|
126 |
|
|
|
127 |
|
|
VALID_TRANSITIONS : coverpoint DEBUG_VALIDS {
|
128 |
|
|
bins transition [] = ( [1:(1<<($size(DEBUG_VALIDS))) -1] => [1:(1<<($size(DEBUG_VALIDS))) -1] );
|
129 |
|
|
}
|
130 |
|
|
|
131 |
|
|
//-- cover active HEADER Flags
|
132 |
|
|
HDR_FLAGS : coverpoint DEBUG_HEADERS;
|
133 |
|
|
|
134 |
|
|
HDR_TRANSITIONS : coverpoint DEBUG_HEADERS {
|
135 |
|
|
bins transition [] = ( [1:1<<($size(DEBUG_HEADERS)) -1] => [1:1<<($size(DEBUG_HEADERS)) -1] );
|
136 |
|
|
}
|
137 |
|
|
|
138 |
|
|
//-- cover active TAIL Flags
|
139 |
|
|
TAIL_FLAGS : coverpoint DEBUG_TAILS;
|
140 |
|
|
|
141 |
|
|
TAIL_TRANSITIONS : coverpoint DEBUG_TAILS {
|
142 |
|
|
bins transition [] = ( [1:1<<($size(DEBUG_TAILS)) -1] => [1:1<<($size(DEBUG_TAILS)) -1] );
|
143 |
|
|
}
|
144 |
|
|
|
145 |
|
|
CROSS_HDR_TAILS : cross HDR_FLAGS, TAIL_FLAGS;
|
146 |
|
|
|
147 |
|
|
HDR_TAILS : coverpoint { DEBUG_HEADERS != {$size(DEBUG_HEADERS){1'b0}} ,DEBUG_TAILS != {$size(DEBUG_TAILS){1'b0}} };
|
148 |
|
|
|
149 |
|
|
|
150 |
|
|
|
151 |
|
|
endgroup
|
152 |
|
|
|
153 |
|
|
//-- creating an instance of the covergroup
|
154 |
|
|
axi4_cg axi4 = new();
|
155 |
|
|
|
156 |
|
|
|
157 |
|
|
|
158 |
|
|
//--
|
159 |
|
|
//-- Interface Assertions
|
160 |
|
|
//--
|
161 |
|
|
|
162 |
|
|
|
163 |
|
|
//property reset_synchronous_deassert_p;
|
164 |
|
|
// @(edge ACLK)
|
165 |
|
|
// !ARESET_N |-> ARESET_N[->1];
|
166 |
|
|
//
|
167 |
|
|
//endproperty
|
168 |
|
|
|
169 |
15 |
juko |
// chk_reset_tvalid : assert property (
|
170 |
|
|
// //-- TVALID must be inactive during Reset
|
171 |
|
|
// @(posedge ACLK)
|
172 |
|
|
// !ARESET_N |-> TVALID == 1'b0
|
173 |
|
|
// );
|
174 |
12 |
juko |
|
175 |
|
|
|
176 |
|
|
chk_valid_hold : assert property (
|
177 |
|
|
//-- if TVALID is set it must be active until TREADY
|
178 |
|
|
@(posedge ACLK) disable iff(!ARESET_N)
|
179 |
|
|
(TVALID == 1 && TREADY == 0) |=> (TVALID==1)
|
180 |
|
|
);
|
181 |
|
|
|
182 |
|
|
|
183 |
|
|
chk_valid_headers : assert property (
|
184 |
|
|
//-- check if HEADER Flags are a subset of VALID Flags
|
185 |
|
|
@(posedge ACLK) disable iff (!ARESET_N)
|
186 |
|
|
(TVALID == 1'b1) |-> (DEBUG_VALIDS | DEBUG_HEADERS
|
187 |
|
|
== DEBUG_VALIDS)
|
188 |
|
|
);
|
189 |
|
|
|
190 |
|
|
|
191 |
|
|
chk_valid_tails : assert property (
|
192 |
|
|
//-- check if TAIL Flags are a subset of VALID Flags
|
193 |
|
|
@(posedge ACLK) disable iff (!ARESET_N)
|
194 |
|
|
(TVALID == 1'b1) |-> (DEBUG_VALIDS | DEBUG_TAILS
|
195 |
|
|
== DEBUG_VALIDS)
|
196 |
|
|
);
|
197 |
|
|
|
198 |
|
|
|
199 |
|
|
check_spanning_hmc_pkts : assert property (
|
200 |
|
|
//-- check that TVALID stays high if a hmc_packet ranges over multiple axi cycles
|
201 |
|
|
//-- starts if more header than tails
|
202 |
|
|
//-- completes if more tails than header
|
203 |
|
|
@(posedge ACLK ) disable iff (!ARESET_N)
|
204 |
|
|
(TVALID && ( $countones(DEBUG_HEADERS) > $countones(DEBUG_TAILS) ))
|
205 |
|
|
|=> (TVALID == 1) throughout ( $countones(DEBUG_HEADERS) < $countones(DEBUG_TAILS) )[->1]
|
206 |
|
|
);
|
207 |
|
|
|
208 |
15 |
juko |
time clk_rise;
|
209 |
|
|
time reset_rise;
|
210 |
12 |
juko |
|
211 |
15 |
juko |
always @(posedge ACLK) begin
|
212 |
|
|
if(ARESET_N == 0)
|
213 |
|
|
clk_rise <= $time();
|
214 |
|
|
end
|
215 |
|
|
|
216 |
|
|
always @(posedge ARESET_N) begin
|
217 |
|
|
reset_rise <= $time();
|
218 |
|
|
end
|
219 |
|
|
|
220 |
|
|
//TODO TODO ADD
|
221 |
|
|
// check_sync_reset : assert property (
|
222 |
|
|
// @(posedge ACLK)
|
223 |
|
|
// $rose(ARESET_N) |=> (reset_rise == clk_rise)
|
224 |
|
|
// );
|
225 |
12 |
juko |
|
226 |
|
|
property data_hold_p;
|
227 |
|
|
//-- if TVALID is set TDATA must not be changed until TREADY
|
228 |
|
|
logic [8*DATA_BYTES-1:0] m_data;
|
229 |
|
|
|
230 |
|
|
@(posedge ACLK) disable iff(!ARESET_N)
|
231 |
|
|
(TVALID == 1 && TREADY == 0,m_data = TDATA) |=> (TDATA == m_data);
|
232 |
|
|
endproperty : data_hold_p
|
233 |
|
|
|
234 |
|
|
property user_hold_p;
|
235 |
|
|
//-- if TVALID is set TUSER must not be changed until TREADY
|
236 |
|
|
logic [TUSER_WIDTH-1:0] m_user;
|
237 |
|
|
|
238 |
|
|
@(posedge ACLK) disable iff(!ARESET_N)
|
239 |
|
|
(TVALID == 1 && TREADY == 0,m_user = TUSER) |=> (TUSER == m_user);
|
240 |
|
|
endproperty : user_hold_p
|
241 |
|
|
|
242 |
|
|
chk_data_hold : assert property( data_hold_p);
|
243 |
|
|
chk_user_hold : assert property( user_hold_p);
|
244 |
|
|
|
245 |
|
|
|
246 |
|
|
|
247 |
|
|
endinterface : axi4_stream_if
|
248 |
|
|
|
249 |
|
|
`endif // AXI4_STREAM_IF_SV
|
250 |
|
|
|