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
|
`timescale 1ns/1ps
module b200_io_tb();
//
// Xilinx Mandatory Simulation Primitive for global signals.
//
wire GSR, GTS;
glbl glbl( );
//
// Test bench declarations
//
reg [7:0] count;
wire [11:0] i0 = {4'hA,count};
wire [11:0] q0 = {4'hB,count};
wire [11:0] i1 = {4'hC,count};
wire [11:0] q1 = {4'hD,count};
reg tb_clk = 0;
// RX sample bus.
reg rx_clk = 0; // Simulated clock from AD9361 for RX sample interface, radio_clk derived from this.
reg rx_frame;
reg [11:0] rx_data;
// TX sample bus.
wire tx_clk;
wire tx_frame;
wire [11:0] tx_data;
// Internal FPGA interface(s)
reg reset = 1;
wire radio_clk;
reg mimo;
wire [11:0] rx_i0, rx_q0, rx_i1, rx_q1;
reg [11:0] tx_i0, tx_q0, tx_i1, tx_q1;
// Set tb_clk to 100MHz.
// rx_clk is half the frequency of tb_clk, and tb_clk posedges are miday between edges on the rx_clk
always #10 tb_clk = ~tb_clk;
always @(negedge tb_clk) rx_clk <= ~rx_clk;
b200_io dut
(
.reset(reset),
.mimo(mimo),
// Baseband sample interface
.radio_clk(radio_clk),
.rx_i0(rx_i0),
.rx_q0(rx_q0),
.rx_i1(rx_i1),
.rx_q1(rx_q1),
.tx_i0(tx_i0),
.tx_q0(tx_q0),
.tx_i1(tx_i1),
.tx_q1(tx_q1),
// Catalina interface
.rx_clk(rx_clk),
.rx_frame(rx_frame),
.rx_data(rx_data),
.tx_clk(tx_clk),
.tx_frame(tx_frame),
.tx_data(tx_data)
);
// Internal Loopback Rx -> Tx.
always @(posedge radio_clk)
begin
tx_i0 <= rx_i0;
tx_q0 <= rx_q0;
tx_i1 <= rx_i1;
tx_q1 <= rx_q1;
end
//
// Task's for stimulus
//
task siso_burst;
input [7:0] len;
begin
rx_frame <= 0;
mimo <= 0;
count <= 0;
// Now give configuration a chance to perculate
@(posedge rx_clk);
@(posedge rx_clk);
@(posedge rx_clk);
@(posedge rx_clk);
// Now entering main stimulus loop just after rising edge of rx_clk
repeat(len)
begin
// Drive I data so that it surrounds a falling edge on rx_clk
@(posedge tb_clk);
rx_data <= i0;
rx_frame <= 1;
// Drive Q data so that it surrounds a rising edge on rx_clk
@(posedge tb_clk);
rx_data <= q0;
rx_frame <= 0;
// Increment test data pattern
count <= count + 1;
end // repeat (len)
@(posedge rx_clk);
@(posedge rx_clk);
end
endtask // BURST
task mimo_burst;
input [7:0] len;
begin
rx_frame <= 0;
mimo <= 1;
count <= 0;
// Now give configuration a chance to perculate
@(posedge rx_clk);
@(posedge rx_clk);
@(posedge rx_clk);
@(posedge rx_clk);
// Now entering main stimulus loop just after rising edge of rx_clk
repeat(len)
// REMEMBER! B210 PCB markings for radio channels are swapped w.r.t AD9361's channels.
// "Ch0" as indicated here is "Ch1" inside AD9361
begin
// Drive I data for Ch1 so that it surrounds a falling edge on rx_clk
@(posedge tb_clk);
rx_data <= i1;
rx_frame <= 1;
// Drive Q data for Ch1 so that it surrounds a rising edge on rx_clk
@(posedge tb_clk);
rx_data <= q1;
// Drive I data for Ch0 so that it surrounds a falling edge on rx_clk
@(posedge tb_clk);
rx_data <= i0;
rx_frame <= 0;
// Drive Q data for Ch0 so that it surrounds a rising edge on rx_clk
@(posedge tb_clk);
rx_data <= q0;
// Increment test data pattern
count <= count + 1;
end
@(posedge rx_clk);
@(posedge rx_clk);
end
endtask // MIMO_BURST
// Pull in local simulation script here.
`include "simulation_script.v"
endmodule // b200_io_tb
|