blob: a9e25cf03fe205d4e09ec7ca220ecf27c3573647 [file] [log] [blame]
lowRISC Contributors802543a2019-08-31 12:12:56 +01001// Copyright lowRISC contributors.
2// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3// SPDX-License-Identifier: Apache-2.0
4//
Cindy Chen68e557f2020-11-11 10:24:14 -08005// xbar_${xbar.name}_tb module generated by `tlgen.py` tool for smoke check
lowRISC Contributors802543a2019-08-31 12:12:56 +01006<%
7 import random
8%>
9module xbar_${xbar.name}_tb;
10
11 import tlul_pkg::*;
12
13 // Clock generator
14% for clock in xbar.clocks:
15 localparam CLK_${clock.upper()}_PERIOD = ${random.randint(10,40)};
16% endfor
17
18% for clock in xbar.clocks:
19 logic clk_${clock};
20 initial begin
21 clk_${clock} = 1'b0;
22 forever begin
23 #(CLK_${clock.upper()}_PERIOD/2)
24 clk_${clock} = ~clk_${clock};
25 end
26 end
27
28% endfor
29
30 // One reset but synchronized to multiple reset
31 logic rst_n ;
32 initial begin
33 rst_n = 1'b0;
34 #117ns
35 rst_n = 1'b1;
36 end
37
38% for clock in xbar.clocks:
39 logic rst_${clock}_n;
40 initial begin
41 rst_${clock}_n = 1'b0;
42
43 wait(rst_n == 1'b1);
44 @(negedge clk_${clock});
45 rst_${clock}_n = 1'b1;
46 end
47
48% endfor
49
50 // Signals
51% for node in xbar.hosts + xbar.devices:
52 tl_h2d_t tl_${node.name}_h2d ;
53 tl_d2h_t tl_${node.name}_d2h ;
54% endfor
55
56 // Instance of xbar_${xbar.name}
57 xbar_${xbar.name} dut (
58% for clock in xbar.clocks:
59 .clk_${clock}_i (clk_${clock}),
60 .rst_${clock}_ni (rst_${clock}_n),
61% endfor
62
63 // Host interfaces
64% for node in xbar.hosts:
65 .tl_${node.name}_i (tl_${node.name}_h2d),
66 .tl_${node.name}_o (tl_${node.name}_d2h),
67% endfor
68
69 // Device interfaces
70% for node in xbar.devices:
71 .tl_${node.name}_o (tl_${node.name}_h2d),
72 .tl_${node.name}_i (tl_${node.name}_d2h),
73% endfor
74
75 .scanmode_i (1'b0)
76
77 );
78
79 task automatic tl_write(ref clk, ref tl_h2d_t tl_h2d, ref tl_d2h_t tl_d2h,
80 input [31:0] addr, input [31:0] wdata);
81 tl_h2d.a_address = addr;
82 tl_h2d.a_opcode = PutFullData;
83 tl_h2d.a_param = '0;
84 tl_h2d.a_size = 2'h2;
85 tl_h2d.a_user = '0;
86 tl_h2d.a_data = wdata;
87 tl_h2d.a_mask = 'hF;
88 tl_h2d.a_source = 0;
89 tl_h2d.a_valid = 1'b1;
90 @(posedge clk iff tl_d2h.a_ready == 1'b1);
91 tl_h2d.a_valid = 1'b0;
92 tl_h2d.d_ready = 1'b1;
93 @(posedge clk iff tl_d2h.d_valid == 1'b1);
94 if (tl_d2h.d_error == 1'b1) $error("TL-UL interface error occurred");
95 tl_h2d.d_ready = 1'b0;
96 endtask : tl_write
97
98 task automatic tl_read(ref clk, ref tl_h2d_t tl_h2d, ref tl_d2h_t tl_d2h,
99 input [31:0] addr, output logic [31:0] rdata);
100 tl_h2d.a_address = addr;
101 tl_h2d.a_opcode = Get;
102 tl_h2d.a_param = '0;
103 tl_h2d.a_size = 2'h2;
104 tl_h2d.a_user = '0;
105 tl_h2d.a_source = 0;
106 tl_h2d.a_valid = 1'b1;
107 @(posedge clk iff tl_d2h.a_ready == 1'b1);
108 tl_h2d.a_valid = 1'b0;
109 tl_h2d.d_ready = 1'b1;
110 @(posedge clk iff tl_d2h.d_valid == 1'b1);
111 if (tl_d2h.d_error == 1'b1) $error("TL-UL interface error occurred");
112 rdata = tl_d2h.d_data;
113 tl_h2d.d_ready = 1'b0;
114 endtask : tl_read
115
116 task automatic tl_compare(ref clk, ref tl_h2d_t tl_h2d, ref tl_d2h_t tl_d2h,
117 input [31:0] addr, input [31:0] wdata);
118 automatic logic [31:0] rdata;
119 tl_write(clk, tl_h2d, tl_d2h, addr, wdata);
120 tl_read(clk, tl_h2d, tl_d2h, addr, rdata);
121 if (wdata != rdata) $error("Addr(%x) mismatch: Exp(%x), Got(%x)", addr, wdata, rdata);
122 endtask : tl_compare
123
124 // Transaction generator
125 //
126 // Goal: Each host creates random sequence
127 // 1. select random device
128 // 2. select random burst (not implemented)
129 // 3. select random address range within the device
130 // 4. Write and read then compare
131 // Note: There's chance that another host updates content at the same address location when a host
132 // reads. This is unavoidable but the change is unlikely. But remind that it is possible.
133 typedef struct {
134 logic [31:0] addr_from;
135 logic [31:0] addr_to;
136 } addr_range_t;
137% for host in xbar.hosts:
138<%
139 clkname = "clk_" + host.clocks[0]
140 rstname = "rst_" + host.clocks[0] + "_n"
141 num_dev = len(xbar.get_s1n_if_exist(host).ds)
142
143 addrs = list(map(xbar.get_addr, xbar.get_devices_from_host(host)))
144%>\
145 addr_range_t ${host.name}_map [${num_dev}] = '{
146% for addr in addrs:
147% if loop.last:
148 '{addr_from: 32'h${"%x"%(addr[0])}, addr_to: 32'h${"%x" %(addr[1])}}
149% else:
150 '{addr_from: 32'h${"%x"%(addr[0])}, addr_to: 32'h${"%x" %(addr[1])}},
151% endif
152% endfor
153 };
154 initial begin
155 // Wait until reset is released
156 tl_${host.name}_h2d.a_valid = 1'b0;
157 tl_${host.name}_h2d.d_ready = 1'b0;
158 wait(${rstname} == 1'b1);
159 @(negedge ${clkname});
160 forever begin
161 // choose among the device
162 automatic int dev_sel = $urandom_range(${num_dev-1},0);
163
164 // determine address
165 automatic logic [31:0] addr = $urandom_range(${host.name}_map[dev_sel].addr_to,
166 ${host.name}_map[dev_sel].addr_from);
167 addr = addr & 32'h FFFF_FFFC;
168
169 // compare
170 tl_compare(${clkname}, tl_${host.name}_h2d, tl_${host.name}_d2h, addr, $urandom());
171 end
172 end
173% endfor
174
175 // Instantiate generic TL-UL sram
176% for device in xbar.devices:
177<%
178 tl_h2d_sig = "tl_" + device.name + "_h2d"
179 tl_d2h_sig = "tl_" + device.name + "_d2h"
180%>
181 device_sram u_device_${device.name} (
182 .clk_i (clk_${device.clocks[0]}),
183 .tl_i (${tl_h2d_sig}),
184 .tl_o (${tl_d2h_sig})
185 );
186% endfor
187
188 initial begin
189 #100us
190 $finish(1);
191 end
192endmodule
193
194