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
|
//
// Copyright 2016 Ettus Research
//
`ifndef INCLUDED_SIM_AXIS_LIB
`define INCLUDED_SIM_AXIS_LIB
interface axis_t #(parameter DWIDTH = 32, parameter NUM_STREAMS = 1)(input clk);
logic [NUM_STREAMS*DWIDTH-1:0] tdata;
logic [NUM_STREAMS-1:0] tvalid;
logic [NUM_STREAMS-1:0] tlast;
logic [NUM_STREAMS-1:0] tready;
modport master (
output tdata,
output tvalid,
output tlast,
input tready);
modport slave (
input tdata,
input tvalid,
input tlast,
output tready);
endinterface
// Interface to push data onto a master AXI-stream bus
interface axis_master #(parameter DWIDTH = 32, parameter NUM_STREAMS = 1)(input clk);
axis_t #(.DWIDTH(DWIDTH), .NUM_STREAMS(NUM_STREAMS)) axis(.clk(clk));
// Check that stream is actually in use
function void check_stream(int stream);
assert (stream < NUM_STREAMS) else
$error("axis_master::check_stream(): Tried to perform operation on unused stream %0d", stream);
endfunction
// Reset signals / properties used by this interface
task automatic reset;
begin
axis.tvalid = 0;
axis.tlast = 0;
axis.tdata = 0;
end
endtask
// Push a word onto the AXI-Stream bus and wait for it to transfer
// Args:
// - word: The data to push onto the bus
// - eop (optional): End of packet (asserts tlast)
// - stream: Stream to use (Optional)
task automatic push_word (
input logic [DWIDTH-1:0] word,
input logic eop = 1'b0,
input int stream = 0);
begin
check_stream(stream);
if (clk) @(negedge clk); // Align with negative edge
axis.tvalid[stream] = 1;
axis.tlast[stream] = eop;
axis.tdata[DWIDTH*stream +: DWIDTH] = word;
@(posedge clk); // Put sample on data bus
while(~axis.tready[stream]) @(posedge clk); // Wait until receiver ready
@(negedge clk); // Put sample on data bus
axis.tvalid[stream] = 0;
axis.tlast[stream] = 0;
end
endtask
// Push a bubble cycle onto the AXI-Stream bus
// Args:
// - stream: Stream to use (Optional)
task automatic push_bubble (input int stream = 0);
begin
check_stream(stream);
axis.tvalid[stream] = 0;
@(negedge clk);
end
endtask
// Push a packet with random data onto to the AXI Stream bus
// Args:
// - num_samps: Packet size.
task automatic push_rand_pkt (
input int num_samps,
input int stream = 0);
begin
check_stream(stream);
if (clk) @(negedge clk);
repeat(num_samps-1) begin
push_word({(((DWIDTH-1)/32)+1){$random}}, 0, stream);
end
push_word({(((DWIDTH-1)/32)+1){$random}}, 1, stream);
end
endtask
// Push a packet with a ramp on to the AXI Stream bus
// Args:
// - num_samps: Packet size.
// - ramp_start: Start value for the ramp
// - ramp_inc: Increment per clock cycle
// - stream: Stream to use (Optional)
task automatic push_ramp_pkt (
input integer num_samps,
input [DWIDTH-1:0] ramp_start,
input [DWIDTH-1:0] ramp_inc,
input int stream = 0);
begin
automatic integer counter = 0;
check_stream(stream);
if (clk) @(negedge clk);
repeat(num_samps-1) begin
push_word(ramp_start+(counter*ramp_inc), 0, stream);
counter = counter + 1;
end
push_word(ramp_start+(counter*ramp_inc), 1, stream);
end
endtask
endinterface
// Interface to push data onto a master AXI-stream bus
interface axis_slave #(parameter DWIDTH = 32, parameter NUM_STREAMS = 1)(input clk);
axis_t #(.DWIDTH(DWIDTH), .NUM_STREAMS(NUM_STREAMS)) axis(.clk(clk));
// Check that stream is actually in use
function void check_stream(int stream);
assert (stream < NUM_STREAMS) else
$error("axis_slave::check_stream(): Tried to perform operation on unused stream %0d", stream);
endfunction
// Reset signals / properties used by this interface
task automatic reset;
begin
axis.tready = 0;
end
endtask
// Pull a word from the AXI Stream bus and
// return the data and last
// Args:
// - word: The data pulled from the bus
// - eop: End of packet (tlast)
// - stream: Stream to use (Optional)
task automatic pull_word (
output logic [DWIDTH-1:0] word,
output logic eop,
input int stream = 0);
begin
check_stream(stream);
if (clk) @(negedge clk);
axis.tready[stream] = 1;
while(~axis.tvalid[stream]) @(posedge clk);
word = axis.tdata[DWIDTH*stream +: DWIDTH];
eop = axis.tlast[stream];
@(negedge clk);
axis.tready[stream] = 0;
end
endtask
// Wait for a sample to be transferred on the AXI Stream
// bus and return the data and last. Note, this task only
// observes the bus and does not affect the AXI control
// signals.
// Args:
// - word: The data pulled from the bus
// - eop: End of packet (tlast)
// - stream: Stream to use (Optional)
task automatic copy_word (
output logic [DWIDTH-1:0] word,
output logic eop,
input int stream = 0);
begin
check_stream(stream);
while(~(axis.tready[stream]&axis.tvalid[stream])) @(posedge clk); // Wait until sample is transferred
word = axis.tdata[DWIDTH*stream +: DWIDTH];
eop = axis.tlast[stream];
@(negedge clk);
end
endtask
// Wait for a bubble cycle on the AXI Stream bus
// Args:
// - stream: Stream to use (Optional)
task automatic wait_for_bubble (
input int stream = 0);
begin
check_stream(stream);
while(axis.tready[stream]&axis.tvalid[stream]) @(posedge clk);
@(negedge clk);
end
endtask
// Wait for a packet to finish on the bus
// Args:
// - stream: Stream to use (Optional)
task automatic wait_for_pkt (
input int stream = 0);
begin
check_stream(stream);
while(~(axis.tready[stream]&axis.tvalid[stream]&axis.tlast[stream])) @(posedge clk);
@(negedge clk);
end
endtask
// Drop a word on the bus
// Args:
// - stream: Stream to use (Optional)
task automatic drop_word (
input int stream = 0);
begin
logic [DWIDTH-1:0] dropped_word;
logic dropped_eop;
pull_word(dropped_word, dropped_eop, stream);
end
endtask
endinterface
`endif
|