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
|
//
// Copyright 2015 Ettus Research LLC
//
`ifndef INCLUDED_SIM_SET_RB_LIB
`define INCLUDED_SIM_SET_RB_LIB
interface settings_bus_t #(
parameter SR_AWIDTH = 8,
parameter SR_DWIDTH = 32,
parameter RB_AWIDTH = 8,
parameter RB_DWIDTH = 64,
parameter NUM_BUSES = 1
)(
input clk
);
logic [NUM_BUSES-1:0] set_stb;
logic [NUM_BUSES*SR_AWIDTH-1:0] set_addr;
logic [NUM_BUSES*SR_DWIDTH-1:0] set_data;
logic [NUM_BUSES-1:0] rb_stb;
logic [NUM_BUSES*RB_AWIDTH-1:0] rb_addr;
logic [NUM_BUSES*RB_DWIDTH-1:0] rb_data;
modport master (output set_stb, output set_addr, output set_data,
input rb_stb, output rb_addr, input rb_data);
modport slave (input set_stb, input set_addr, input set_data,
output rb_stb, input rb_addr, output rb_data);
endinterface
interface settings_bus_master #(
parameter SR_AWIDTH = 8,
parameter SR_DWIDTH = 32,
parameter RB_AWIDTH = 8,
parameter RB_DWIDTH = 64,
parameter NUM_BUSES = 1,
parameter TIMEOUT = 65535 // readback() timeout
)(
input clk
);
settings_bus_t #(
.SR_AWIDTH(SR_AWIDTH), .SR_DWIDTH(SR_DWIDTH),
.RB_AWIDTH(RB_AWIDTH), .RB_DWIDTH(RB_DWIDTH),
.NUM_BUSES(NUM_BUSES))
settings_bus (.clk(clk));
// Reset signals / properties used by this interface
task automatic reset;
settings_bus.set_stb = 0;
settings_bus.set_addr = 0;
settings_bus.set_data = 0;
settings_bus.rb_addr = 0;
endtask
// Push a transaction onto the settings bus
// Args:
// - set_addr: Settings bus address
// - set_data: Settings bus data
// - rb_addr: Readback bus address
task automatic write (
input logic [SR_AWIDTH-1:0] set_addr,
input logic [SR_DWIDTH-1:0] set_data,
input logic [RB_AWIDTH-1:0] rb_addr = 'd0,
input int bus = 0); // Optional
begin
if (clk) @(negedge clk);
settings_bus.set_stb[bus] = 1'b1;
settings_bus.set_addr[SR_AWIDTH*bus +: SR_AWIDTH] = set_addr;
settings_bus.set_data[SR_DWIDTH*bus +: SR_DWIDTH] = set_data;
settings_bus.rb_addr[RB_AWIDTH*bus +: RB_AWIDTH] = rb_addr;
@(negedge clk);
settings_bus.set_stb[bus] = 1'b0;
settings_bus.set_addr[SR_AWIDTH*bus +: SR_AWIDTH] = 'd0;
settings_bus.set_data[SR_DWIDTH*bus +: SR_DWIDTH] = 'd0;
settings_bus.rb_addr[RB_AWIDTH*bus +: RB_AWIDTH] = 'd0;
end
endtask
// Pull a transaction from the readback bus. Typically called immediately after write().
// Args:
// - rb_data: Readback data
task automatic readback (
output logic [RB_DWIDTH-1:0] rb_data,
input int bus = 0);
begin
integer timeout_counter = 0;
if (clk & ~settings_bus.rb_stb[bus]) @(negedge clk);
while (~settings_bus.rb_stb[bus]) begin
if (timeout_counter < TIMEOUT) begin
timeout_counter++;
end else begin
$error("settings_bus_t::readback(): Timeout waiting for readback strobe!");
break;
end
@(negedge clk);
end
rb_data = settings_bus.rb_data[RB_DWIDTH*bus +: RB_DWIDTH];
end
endtask
endinterface
interface settings_bus_slave #(
parameter SR_AWIDTH = 8,
parameter SR_DWIDTH = 32,
parameter RB_AWIDTH = 8,
parameter RB_DWIDTH = 64,
parameter NUM_BUSES = 1,
parameter TIMEOUT = 65535 // read() timeout
)(
input clk
);
settings_bus_t #(
.SR_AWIDTH(SR_AWIDTH), .SR_DWIDTH(SR_DWIDTH),
.RB_AWIDTH(RB_AWIDTH), .RB_DWIDTH(RB_DWIDTH),
.NUM_BUSES(NUM_BUSES))
settings_bus (.clk(clk));
// Reset signals / properties used by this interface
task automatic reset;
settings_bus.rb_stb = 0;
settings_bus.rb_data = 0;
endtask
// Pull a transaction from the settings bus
// Args:
// - set_addr: Settings bus address
// - set_data: Settings bus data
// - rb_addr: Readback bus address
task automatic read (
output logic [SR_AWIDTH-1:0] set_addr,
output logic [SR_DWIDTH-1:0] set_data,
output logic [RB_AWIDTH-1:0] rb_addr,
input int bus = 0);
begin
integer timeout_counter = 0;
while (~settings_bus.set_stb[bus]) begin
@(negedge clk);
if (timeout_counter < TIMEOUT) begin
timeout_counter++;
end else begin
$error("settings_bus_t::read(): Timeout waitling for settings bus strobe!");
break;
end
end
set_addr = settings_bus.set_addr[SR_AWIDTH*bus +: SR_AWIDTH];
set_data = settings_bus.set_data[SR_DWIDTH*bus +: SR_DWIDTH];
rb_addr = settings_bus.rb_addr[RB_AWIDTH*bus +: RB_AWIDTH];
@(negedge clk);
end
endtask
// Push a transaction onto the readback bus, typically called immediately after read()
// Args:
// - rb_data: Readback data
task writeback (
input logic [RB_AWIDTH-1:0] rb_data,
input int bus = 0);
begin
if (clk & ~settings_bus.set_stb[bus]) @(negedge clk);
settings_bus.rb_stb[bus] = 1'b1;
settings_bus.rb_data[RB_DWIDTH*bus +: RB_DWIDTH] = rb_data;
@(negedge clk);
settings_bus.rb_stb[bus] = 1'b0;
settings_bus.rb_data[RB_DWIDTH*bus +: RB_DWIDTH] = 'd0;
end
endtask
endinterface
`endif
|