1 |
202 |
olivier.gi |
/*===========================================================================*/
|
2 |
|
|
/* Copyright (C) 2001 Authors */
|
3 |
|
|
/* */
|
4 |
|
|
/* This source file may be used and distributed without restriction provided */
|
5 |
|
|
/* that this copyright statement is not removed from the file and that any */
|
6 |
|
|
/* derivative work contains the original copyright notice and the associated */
|
7 |
|
|
/* disclaimer. */
|
8 |
|
|
/* */
|
9 |
|
|
/* This source file is free software; you can redistribute it and/or modify */
|
10 |
|
|
/* it under the terms of the GNU Lesser General Public License as published */
|
11 |
|
|
/* by the Free Software Foundation; either version 2.1 of the License, or */
|
12 |
|
|
/* (at your option) any later version. */
|
13 |
|
|
/* */
|
14 |
|
|
/* This source is distributed in the hope that it will be useful, but WITHOUT*/
|
15 |
|
|
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
|
16 |
|
|
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
|
17 |
|
|
/* License for more details. */
|
18 |
|
|
/* */
|
19 |
|
|
/* You should have received a copy of the GNU Lesser General Public License */
|
20 |
|
|
/* along with this source; if not, write to the Free Software Foundation, */
|
21 |
|
|
/* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
22 |
|
|
/* */
|
23 |
|
|
/*===========================================================================*/
|
24 |
|
|
/* DMA INTERFACE */
|
25 |
|
|
/*---------------------------------------------------------------------------*/
|
26 |
|
|
/* Test the DMA interface: */
|
27 |
|
|
/* - Check DMA and Debug interface arbitration. */
|
28 |
|
|
/* */
|
29 |
|
|
/* Author(s): */
|
30 |
|
|
/* - Olivier Girard, olgirard@gmail.com */
|
31 |
|
|
/* */
|
32 |
|
|
/*---------------------------------------------------------------------------*/
|
33 |
|
|
/* $Rev$ */
|
34 |
|
|
/* $LastChangedBy$ */
|
35 |
|
|
/* $LastChangedDate$ */
|
36 |
|
|
/*===========================================================================*/
|
37 |
|
|
|
38 |
|
|
`define VERY_LONG_TIMEOUT
|
39 |
|
|
|
40 |
|
|
integer dbg_cnt_wr;
|
41 |
|
|
integer dbg_cnt_rd;
|
42 |
|
|
integer dbg_wr_error;
|
43 |
|
|
integer dbg_rd_error;
|
44 |
|
|
|
45 |
|
|
integer dbg_mem_ref_idx;
|
46 |
|
|
reg [15:0] dbg_pmem_reference[0:128];
|
47 |
|
|
reg [15:0] dbg_dmem_reference[0:128];
|
48 |
|
|
|
49 |
|
|
reg [15:0] dbg_if_buf;
|
50 |
|
|
|
51 |
|
|
reg [7:0] kk;
|
52 |
|
|
reg [15:0] dbg_rand_val;
|
53 |
|
|
reg dbg_rand_rd_wr;
|
54 |
|
|
reg dbg_rand_mem_sel;
|
55 |
|
|
reg [7:0] dbg_rand_offset;
|
56 |
|
|
reg [7:0] dbg_rand_size;
|
57 |
|
|
|
58 |
|
|
initial
|
59 |
|
|
begin
|
60 |
|
|
$display(" ===============================================");
|
61 |
|
|
$display("| START SIMULATION |");
|
62 |
|
|
$display(" ===============================================");
|
63 |
|
|
`ifdef DMA_IF_EN
|
64 |
|
|
`ifdef DBG_EN
|
65 |
|
|
|
66 |
|
|
// Skip verification if memory configuration is too small
|
67 |
|
|
if (~((`PMEM_SIZE>=4092) && (`DMEM_SIZE>=1024)))
|
68 |
|
|
begin
|
69 |
|
|
tb_skip_finish("| (PMEM size less than 4kB or DMEM size is less than 1kB) |");
|
70 |
|
|
end
|
71 |
|
|
|
72 |
|
|
#1 dbg_en = 1;
|
73 |
|
|
dbg_if_buf = 16'h0000;
|
74 |
|
|
dma_verif_on = 1;
|
75 |
|
|
|
76 |
|
|
dbg_cnt_wr = 0;
|
77 |
|
|
dbg_cnt_rd = 0;
|
78 |
|
|
dbg_wr_error = 0;
|
79 |
|
|
dbg_rd_error = 0;
|
80 |
|
|
|
81 |
|
|
repeat(30) @(posedge mclk);
|
82 |
|
|
stimulus_done = 0;
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
// Disable random delay on DMA inteface to maximize the number of transfer
|
86 |
|
|
dma_rand_wait_disable = 1;
|
87 |
|
|
|
88 |
|
|
// Initialize memory for debug interface random accesses
|
89 |
|
|
for (dbg_mem_ref_idx=0; dbg_mem_ref_idx < 128; dbg_mem_ref_idx=dbg_mem_ref_idx+1)
|
90 |
|
|
begin
|
91 |
|
|
dbg_rand_val = $urandom;
|
92 |
|
|
dbg_pmem_reference[dbg_mem_ref_idx] = dbg_rand_val;
|
93 |
|
|
pmem_0.mem[128+dbg_mem_ref_idx] = dbg_rand_val;
|
94 |
|
|
|
95 |
|
|
dbg_rand_val = $urandom;
|
96 |
|
|
dbg_dmem_reference[dbg_mem_ref_idx] = dbg_rand_val;
|
97 |
|
|
dmem_0.mem[128+dbg_mem_ref_idx] = dbg_rand_val;
|
98 |
|
|
end
|
99 |
|
|
|
100 |
|
|
// SEND UART SYNCHRONIZATION FRAME
|
101 |
|
|
`ifdef DBG_UART
|
102 |
|
|
dbg_uart_tx(DBG_SYNC);
|
103 |
|
|
`endif
|
104 |
|
|
|
105 |
|
|
// RUN CPU
|
106 |
|
|
dbg_if_wr(CPU_CTL, 16'h0002);
|
107 |
|
|
|
108 |
|
|
// Let CPU execute a bit before enabling the priority DMA
|
109 |
|
|
// (this will let the firmware enough time to disable the watchdog)
|
110 |
|
|
repeat(30) @(posedge mclk);
|
111 |
|
|
dma_priority = 1;
|
112 |
|
|
|
113 |
|
|
//--------------------------------
|
114 |
|
|
// Debug interface transfer
|
115 |
|
|
//--------------------------------
|
116 |
|
|
for (kk=0; kk < 50; kk=kk+1)
|
117 |
|
|
begin
|
118 |
|
|
// Ramdomly choose:
|
119 |
|
|
// - read or write access
|
120 |
|
|
// - Program or Data memory
|
121 |
|
|
// - transfer size
|
122 |
|
|
// - memory offset
|
123 |
|
|
dbg_rand_rd_wr = $urandom_range(0,1);
|
124 |
|
|
dbg_rand_mem_sel = $urandom_range(0,1);
|
125 |
|
|
dbg_rand_size = $urandom_range(10,63);
|
126 |
|
|
dbg_rand_offset = $urandom_range(0,63);
|
127 |
|
|
|
128 |
|
|
$display("START DBG BURST %d: write=%h / pmem_sel=%h / size=%d / offset=%d", kk, dbg_rand_rd_wr, dbg_rand_mem_sel, dbg_rand_size, dbg_rand_offset);
|
129 |
|
|
|
130 |
|
|
if (dbg_rand_rd_wr) dbg_if_burst_write_16b(dbg_rand_mem_sel, dbg_rand_offset, dbg_rand_size);
|
131 |
|
|
else dbg_if_burst_read_16b( dbg_rand_mem_sel, dbg_rand_offset, dbg_rand_size);
|
132 |
|
|
end
|
133 |
|
|
|
134 |
|
|
//--------------------------------
|
135 |
|
|
// End of test
|
136 |
|
|
//--------------------------------
|
137 |
|
|
|
138 |
|
|
// Remove DMA priority to let the CPU execute some code
|
139 |
|
|
dma_priority = 0;
|
140 |
|
|
|
141 |
|
|
// Update variable to let firmware finish execution
|
142 |
|
|
dbg_if_wr(MEM_ADDR, (16'h0000-`PMEM_SIZE));
|
143 |
|
|
dbg_if_wr(MEM_DATA, 16'h0001);
|
144 |
|
|
dbg_if_wr(MEM_CTL, 16'h0003);
|
145 |
|
|
|
146 |
|
|
$display("\n");
|
147 |
|
|
$display("DBG REPORT: Total Accesses: %-d Total RD: %-d Total WR: %-d", dbg_cnt_rd+dbg_cnt_wr, dbg_cnt_rd, dbg_cnt_wr);
|
148 |
|
|
$display(" Total Errors: %-d Error RD: %-d Error WR: %-d", dbg_rd_error+dbg_wr_error, dbg_rd_error, dbg_wr_error);
|
149 |
|
|
$display("\n");
|
150 |
|
|
|
151 |
|
|
stimulus_done = 1;
|
152 |
|
|
`else
|
153 |
|
|
tb_skip_finish("| (serial debug interface not included) |");
|
154 |
|
|
`endif
|
155 |
|
|
`else
|
156 |
|
|
tb_skip_finish("| (DMA interface support not included) |");
|
157 |
|
|
`endif
|
158 |
|
|
end
|
159 |
|
|
|
160 |
|
|
|
161 |
|
|
|
162 |
|
|
//-----------------------------------------------------
|
163 |
|
|
// Generic debug interface tasks
|
164 |
|
|
//-----------------------------------------------------
|
165 |
|
|
task dbg_if_wr;
|
166 |
|
|
input [7:0] dbg_reg;
|
167 |
|
|
input [15:0] dbg_data;
|
168 |
|
|
|
169 |
|
|
begin
|
170 |
|
|
`ifdef DBG_UART
|
171 |
|
|
dbg_uart_wr(dbg_reg, dbg_data);
|
172 |
|
|
`else
|
173 |
|
|
dbg_i2c_wr(dbg_reg, dbg_data);
|
174 |
|
|
`endif
|
175 |
|
|
end
|
176 |
|
|
endtask
|
177 |
|
|
|
178 |
|
|
task dbg_if_tx16;
|
179 |
|
|
input [15:0] dbg_data;
|
180 |
|
|
input is_last;
|
181 |
|
|
|
182 |
|
|
begin
|
183 |
|
|
`ifdef DBG_UART
|
184 |
|
|
dbg_uart_tx16(dbg_data);
|
185 |
|
|
`else
|
186 |
|
|
dbg_i2c_tx16(dbg_data, is_last);
|
187 |
|
|
`endif
|
188 |
|
|
end
|
189 |
|
|
endtask
|
190 |
|
|
|
191 |
|
|
task dbg_if_rx16;
|
192 |
|
|
input is_last;
|
193 |
|
|
|
194 |
|
|
begin
|
195 |
|
|
`ifdef DBG_UART
|
196 |
|
|
dbg_uart_rx16;
|
197 |
|
|
dbg_if_buf = dbg_uart_buf;
|
198 |
|
|
`else
|
199 |
|
|
repeat(30) @(posedge mclk);
|
200 |
|
|
dbg_i2c_rx16(is_last);
|
201 |
|
|
dbg_if_buf = dbg_i2c_buf;
|
202 |
|
|
`endif
|
203 |
|
|
end
|
204 |
|
|
endtask
|
205 |
|
|
|
206 |
|
|
//-----------------------------------------------------
|
207 |
|
|
// Debug interface burst tasks
|
208 |
|
|
//-----------------------------------------------------
|
209 |
|
|
|
210 |
|
|
task dbg_if_burst_write_16b;
|
211 |
|
|
input mem_sel; // 1: Program memory / 0: Data memory
|
212 |
|
|
input [15:0] offset;
|
213 |
|
|
input [15:0] size;
|
214 |
|
|
|
215 |
|
|
integer idx;
|
216 |
|
|
reg [15:0] data_val;
|
217 |
|
|
begin
|
218 |
|
|
if (mem_sel) dbg_if_wr(MEM_ADDR, ('h0000-`PMEM_SIZE+256+offset*2));
|
219 |
|
|
else dbg_if_wr(MEM_ADDR, (`PER_SIZE+256+offset*2));
|
220 |
|
|
dbg_if_wr(MEM_CNT, size-1);
|
221 |
|
|
dbg_if_wr(MEM_CTL, 16'h0003); // Start burst to 16 bit memory write
|
222 |
|
|
`ifdef DBG_I2C
|
223 |
|
|
dbg_i2c_burst_start(0);
|
224 |
|
|
`endif
|
225 |
|
|
for (idx=0; idx < size; idx=idx+1)
|
226 |
|
|
begin
|
227 |
|
|
data_val = $urandom;
|
228 |
|
|
if (mem_sel) dbg_pmem_reference[offset+idx] = data_val;
|
229 |
|
|
else dbg_dmem_reference[offset+idx] = data_val;
|
230 |
|
|
|
231 |
|
|
if (idx!=(size-1)) dbg_if_tx16(data_val, 0);
|
232 |
|
|
else dbg_if_tx16(data_val, 1);
|
233 |
|
|
|
234 |
|
|
dbg_cnt_wr = dbg_cnt_wr+1;
|
235 |
|
|
end
|
236 |
|
|
|
237 |
|
|
repeat(12) @(posedge mclk);
|
238 |
|
|
for (idx=0; idx < size; idx=idx+1)
|
239 |
|
|
begin
|
240 |
|
|
if ( mem_sel & (pmem_0.mem[128+offset+idx] !== dbg_pmem_reference[offset+idx])) begin dbg_wr_error=dbg_wr_error+1; tb_error("====== DBG INTERFACE PMEM WRITE ERROR ====="); end
|
241 |
|
|
else if (~mem_sel & (dmem_0.mem[128+offset+idx] !== dbg_dmem_reference[offset+idx])) begin dbg_wr_error=dbg_wr_error+1; tb_error("====== DBG INTERFACE DMEM WRITE ERROR ====="); end
|
242 |
|
|
end
|
243 |
|
|
end
|
244 |
|
|
endtask
|
245 |
|
|
|
246 |
|
|
task dbg_if_burst_read_16b;
|
247 |
|
|
input mem_sel; // 1: Program memory / 0: Data memory
|
248 |
|
|
input [15:0] offset;
|
249 |
|
|
input [15:0] size;
|
250 |
|
|
|
251 |
|
|
integer idx;
|
252 |
|
|
begin
|
253 |
|
|
if (mem_sel) dbg_if_wr(MEM_ADDR, ('h0000-`PMEM_SIZE+256+offset*2));
|
254 |
|
|
else dbg_if_wr(MEM_ADDR, (`PER_SIZE+256+offset*2));
|
255 |
|
|
dbg_if_wr(MEM_CNT, size-1);
|
256 |
|
|
dbg_if_wr(MEM_CTL, 16'h0001); // Start burst to 16 bit registers read
|
257 |
|
|
`ifdef DBG_I2C
|
258 |
|
|
dbg_i2c_burst_start(1);
|
259 |
|
|
`endif
|
260 |
|
|
for (idx=0; idx < size; idx=idx+1)
|
261 |
|
|
begin
|
262 |
|
|
if (idx!=(size-1)) dbg_if_rx16(0);
|
263 |
|
|
else dbg_if_rx16(1);
|
264 |
|
|
|
265 |
|
|
dbg_cnt_rd = dbg_cnt_rd+1;
|
266 |
|
|
|
267 |
|
|
// Make sure we don't read an X
|
268 |
|
|
if ( mem_sel & (dbg_if_buf === 16'hxxxx)) begin dbg_rd_error=dbg_rd_error+1; tb_error("====== DBG INTERFACE PMEM READ XXXXX ====="); end
|
269 |
|
|
else if (~mem_sel & (dbg_if_buf === 16'hxxxx)) begin dbg_rd_error=dbg_rd_error+1; tb_error("====== DBG INTERFACE DMEM READ XXXXX ====="); end
|
270 |
|
|
|
271 |
|
|
// Check result
|
272 |
|
|
if ( mem_sel & (dbg_if_buf !== dbg_pmem_reference[offset+idx])) begin dbg_rd_error=dbg_rd_error+1; tb_error("====== DBG INTERFACE PMEM READ ERROR ====="); end
|
273 |
|
|
else if (~mem_sel & (dbg_if_buf !== dbg_dmem_reference[offset+idx])) begin dbg_rd_error=dbg_rd_error+1; tb_error("====== DBG INTERFACE DMEM READ ERROR ====="); end
|
274 |
|
|
end
|
275 |
|
|
end
|
276 |
|
|
endtask
|