OpenCores
URL https://opencores.org/ocsvn/sd_card_controller/sd_card_controller/trunk

Subversion Repositories sd_card_controller

[/] [sd_card_controller/] [trunk/] [bench/] [verilog/] [sd_data_serial_host_tb.sv] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 rozpruwacz
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
//// WISHBONE SD Card Controller IP Core                          ////
4
////                                                              ////
5
//// sd_data_serial_host_tb.sv                                    ////
6
////                                                              ////
7
//// This file is part of the WISHBONE SD Card                    ////
8
//// Controller IP Core project                                   ////
9 8 rozpruwacz
//// http://opencores.org/project,sd_card_controller              ////
10 3 rozpruwacz
////                                                              ////
11
//// Description                                                  ////
12
//// testbench for sd_data_serial_host module                     ////
13
////                                                              ////
14
//// Author(s):                                                   ////
15
////     - Marek Czerski, ma.czerski@gmail.com                    ////
16
////                                                              ////
17
//////////////////////////////////////////////////////////////////////
18
////                                                              ////
19
//// Copyright (C) 2013 Authors                                   ////
20
////                                                              ////
21
//// This source file may be used and distributed without         ////
22
//// restriction provided that this copyright statement is not    ////
23
//// removed from the file and that any derivative work contains  ////
24
//// the original copyright notice and the associated disclaimer. ////
25
////                                                              ////
26
//// This source file is free software; you can redistribute it   ////
27
//// and/or modify it under the terms of the GNU Lesser General   ////
28
//// Public License as published by the Free Software Foundation; ////
29
//// either version 2.1 of the License, or (at your option) any   ////
30
//// later version.                                               ////
31
////                                                              ////
32
//// This source is distributed in the hope that it will be       ////
33
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
34
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
35
//// PURPOSE. See the GNU Lesser General Public License for more  ////
36
//// details.                                                     ////
37
////                                                              ////
38
//// You should have received a copy of the GNU Lesser General    ////
39
//// Public License along with this source; if not, download it   ////
40
//// from http://www.opencores.org/lgpl.shtml                     ////
41
////                                                              ////
42
//////////////////////////////////////////////////////////////////////
43
 
44
`include "sd_defines.h"
45
 
46
module sd_data_serial_host_tb();
47
 
48
parameter SD_TCLK = 20; // 50 MHz -> timescale 1ns
49
parameter DATA_IDLE = 4'hf;
50
parameter DATA_START = 4'h0;
51
parameter DATA_END = 4'hf;
52
 
53
reg sd_clk;
54
reg rst;
55
//Tx Fifo
56
reg [31:0] data_in;
57
wire rd;
58
//Rx Fifo
59
wire[31:0] data_out;
60
wire we;
61
//tristate data
62
wire DAT_oe_o;
63
wire [3:0] DAT_dat_o;
64
reg [3:0] DAT_dat_i;
65
//Controll signals
66
reg [`BLKSIZE_W-1:0] blksize;
67
reg bus_4bit;
68
reg [`BLKCNT_W-1:0] blkcnt;
69
reg [1:0] start;
70
wire sd_data_busy;
71
wire busy;
72
wire crc_ok;
73
 
74
integer fifo_send_data[0:3] = {32'h12345678, 32'haabbccdd, 32'h9abcdef0, 32'h55aacc33};
75
//integer fifo_send_data[0:0] = {32'hffffffff};
76
reg [1:0] fifo_idx = 0;
77
integer fifo_receive_data[0:3] = {32'h00010203, 32'ha0a1a2a3, 32'hdeadbeef, 32'hbad00dad};
78
 
79
function [3:0] get_1or4_bits;
80
    input [3:0] data;
81
    input integer bits;
82
    begin
83
        if (bits == 1)
84
            get_1or4_bits = {3'b111, data[0]};
85
        else
86
            get_1or4_bits = data;
87
    end
88
endfunction
89
 
90
function integer crc16;
91
    input integer crc_in;
92
    input bit inb;
93
    begin
94
        inb = inb ^ crc_in[0];
95
        crc16 = crc_in >> 1;
96
        crc16 = crc16 ^ (16'h8408 & {16{inb}});
97
    end
98
endfunction
99
 
100
task sd_card_send;
101
    input integer bytes;
102
    input integer blocks;
103
    input integer width;
104
    input bit crc_failure;
105
    integer cycles;
106
    integer i, j;
107
    integer data_idx;
108
    integer shift;
109
    integer crc[0:3];
110
    reg [3:0] crc_out;
111
    begin
112
        assert(width == 1 || width == 4) else $stop;
113
        while (blocks+1) begin
114
            cycles = bytes*8/width;
115
            crc = {0, 0, 0, 0};
116
            //start bits
117
            DAT_dat_i = get_1or4_bits(DATA_START, width);
118
            #SD_TCLK;
119
            //data bits
120
            for (i=0; i
121
                data_idx = (i*width/32)%$size(fifo_receive_data);
122
                shift = (32-width)-((i*width)%32);
123
                DAT_dat_i = get_1or4_bits(fifo_receive_data[data_idx] >> shift, width);
124
                for (j=0; j<4; j++)
125
                    crc[j] = crc16(crc[j], DAT_dat_i[j]);
126
                #SD_TCLK;
127
            end
128
            //crc bits
129
            for (i=0; i<16; i++) begin
130
                for (j=0; j<4; j++)
131
                    crc_out[j] = crc[j] >> i;
132
                DAT_dat_i = get_1or4_bits(crc_failure ? 0 : crc_out, width);
133
                #SD_TCLK;
134
            end
135
            //stop bits
136
            DAT_dat_i = get_1or4_bits(DATA_END, width);
137
            #SD_TCLK;
138
            DAT_dat_i = get_1or4_bits(DATA_IDLE, width);
139
            #SD_TCLK;
140
            if (blocks)
141
                assert(busy == 1);
142
            assert(crc_ok == !crc_failure);
143
            blocks--;
144
        end
145
    end
146
endtask
147
 
148
task sd_card_receive;
149
    input integer bytes;
150
    input integer blocks;
151
    input integer width;
152
    input [2:0] crc_status;
153
    integer cycles;
154
    integer i, j;
155
    integer received_data;
156
    integer data_idx;
157
    integer shift;
158
    integer crc[0:3];
159
    integer crc_in[0:3];
160
    //reg [3:0] crc_out;
161
    begin
162
        assert(width == 1 || width == 4) else $stop;
163
        cycles = bytes*8/width;
164
 
165
        while(blocks+1) begin
166
            received_data = 0;
167
            crc = {0, 0, 0, 0};
168
            crc_in = {0, 0, 0, 0};
169
            //wait for start bits
170
            wait (DAT_dat_o == get_1or4_bits(DATA_START, width));
171
            assert(DAT_oe_o == 1);
172
            #(SD_TCLK/2);
173
            //data bits
174
            for (i=0; i
175
                #SD_TCLK;
176
                shift = (32-width)-((i*width)%32);
177
                for (j=0; j
178
                    received_data[shift+j] = DAT_dat_o[j];
179
                assert(DAT_oe_o == 1);
180
                if ((i*width)%32 == (32-width)) begin
181
                    data_idx = (i*width/32)%$size(fifo_send_data);
182
                    assert(fifo_send_data[data_idx] == received_data);
183
                end
184
                for (j=0; j
185
                    crc[j] = crc16(crc[j], DAT_dat_o[j]);
186
            end
187
            //crc bits
188
            for (i=0; i<16; i++) begin
189
                #SD_TCLK;
190
                assert(DAT_oe_o == 1);
191
                for (j=0; j
192
                    crc_in[j][i] = DAT_dat_o[j];
193
            end
194
            for (i=0; i
195
                assert(crc_in[i] == crc[i]);
196
            //stop bits
197
            #SD_TCLK;
198
            assert(DAT_oe_o == 1);
199
            assert(DAT_dat_o == DATA_END);
200
            #SD_TCLK;
201
            assert(DAT_oe_o == 0);
202
            #(2*SD_TCLK);
203
            //crc status
204
            //start bit
205
            DAT_dat_i = get_1or4_bits(DATA_START, 1);
206
            #SD_TCLK;
207
            //crc status bits
208
            for (i=0; i<$size(crc_status); i++) begin
209
                DAT_dat_i = {3'h7, crc_status[i]};
210
                #SD_TCLK;
211
            end
212
            //stop bit
213
            DAT_dat_i = get_1or4_bits(DATA_END, 1);
214
            #SD_TCLK;
215
            assert(sd_data_busy == 0);
216
            //busy bit
217
            DAT_dat_i = {3'h7, 1'b0};
218
            #(2*SD_TCLK);
219
            assert(sd_data_busy == 1);
220
            if (blocks)
221
                assert(busy == 1);
222
            if (crc_status == 3'b010)
223
                assert(crc_ok == 1);
224
            else
225
                assert(crc_ok == 0);
226
            #(10*SD_TCLK);
227
            DAT_dat_i = DATA_IDLE;
228
            blocks--;
229
        end
230
        #SD_TCLK;
231
    end
232
endtask
233
 
234
task check_fifo_write;
235
    input integer bytes;
236
    input integer blocks;
237
    input integer width;
238
    integer cycles, i, j;
239
    begin
240
        assert(width == 1 || width == 4) else $stop;
241
        cycles = bytes/4;
242
        while (blocks+1) begin
243
            wait (we == 1);
244
            #(SD_TCLK/2);
245
            assert(data_out == fifo_receive_data[0]);
246
            for (i=1; i
247
                for (j=0; j<32/width-1; j++) begin
248
                    #SD_TCLK;
249
                    assert(we == 0);
250
                end
251
                #SD_TCLK;
252
                assert(we == 1);
253
                assert(data_out == fifo_receive_data[i%$size(fifo_receive_data)]);
254
            end
255
            blocks--;
256
            #SD_TCLK;
257
        end
258
    end
259
endtask
260
 
261
task check_fifo_read;
262
    input integer bytes;
263
    input integer blocks;
264
    input integer width;
265
    integer cycles, i, j;
266
    begin
267
        assert(width == 1 || width == 4) else $stop;
268
        cycles = bytes/4;
269
        while (blocks+1) begin
270
            wait (rd == 1);
271
            #(SD_TCLK/2);
272
            assert(rd == 1);
273 12 rozpruwacz
            //read delay !!!
274
            #(2*SD_TCLK);
275 3 rozpruwacz
            data_in = fifo_send_data[1%$size(fifo_send_data)];
276
            for (i=2; i
277
                for (j=0; j<32/width-1; j++) begin
278
                    #SD_TCLK;
279 12 rozpruwacz
                    if (j == 32/width-3)
280
                        assert(rd == 1);
281
                    else
282
                        assert(rd == 0);
283 3 rozpruwacz
                end
284
                #SD_TCLK;
285 12 rozpruwacz
                assert(rd == 0);
286 3 rozpruwacz
                data_in = fifo_send_data[i%$size(fifo_send_data)];
287
            end
288
            #SD_TCLK;
289
            assert(rd == 0);
290
            data_in = fifo_send_data[0];
291
            blocks--;
292
        end
293
    end
294
endtask
295
 
296
task read_test;
297
    input integer bsize;
298
    input integer bcnt;
299
    input integer b_4bit;
300
    input bit crc_failure;
301
    begin
302
        blksize = bsize;
303
        blkcnt = bcnt;
304
        bus_4bit = b_4bit;
305
        start = 2; //read
306
        #SD_TCLK;
307
        blksize = 0;
308
        bus_4bit = 0;
309
        blkcnt = 0;
310
        start = 0;
311
        assert(busy == 1);
312
 
313
        #(20*SD_TCLK);
314
 
315
        fork
316
            sd_card_send(bsize, crc_failure ? 0 : bcnt, b_4bit ? 4 : 1, crc_failure);
317
            check_fifo_write(bsize, crc_failure ? 0 : bcnt, b_4bit ? 4 : 1);
318
        join
319
 
320
        #SD_TCLK;
321
        assert(busy == 0);
322
    end
323
endtask
324
 
325
task write_test;
326
    input integer bsize;
327
    input integer bcnt;
328
    input integer b_4bit;
329
    input bit crc_failure;
330
    begin
331
        blksize = bsize;
332
        blkcnt = bcnt;
333
        bus_4bit = b_4bit;
334
        start = 1; //write
335
        #SD_TCLK;
336
        blksize = 0;
337
        bus_4bit = 0;
338
        blkcnt = 0;
339
        start = 0;
340
        assert(busy == 1);
341
 
342
        fork
343
            check_fifo_read(bsize, crc_failure ? 0 : bcnt, b_4bit ? 4 : 1);
344
            sd_card_receive(bsize, crc_failure ? 0 : bcnt, b_4bit ? 4 : 1, crc_failure ? 3'b101 : 3'b010);
345
        join
346
 
347
        #(2*SD_TCLK);
348
        assert(busy == 0);
349
    end
350
endtask
351
 
352
sd_data_serial_host sd_data_serial_host_dut(
353
                        .sd_clk         (sd_clk),
354
                        .rst            (rst),
355
                        .data_in        (data_in),
356
                        .rd             (rd),
357
                        .data_out       (data_out),
358
                        .we             (we),
359
                        .DAT_oe_o       (DAT_oe_o),
360
                        .DAT_dat_o      (DAT_dat_o),
361
                        .DAT_dat_i      (DAT_dat_i),
362
                        .blksize        (blksize),
363
                        .bus_4bit       (bus_4bit),
364
                        .blkcnt         (blkcnt),
365
                        .start          (start),
366
                        .sd_data_busy   (sd_data_busy),
367
                        .busy           (busy),
368
                        .crc_ok         (crc_ok)
369
                    );
370
 
371
// Generating WB_CLK_I clock
372
always
373
begin
374
    sd_clk=0;
375
    forever #(SD_TCLK/2) sd_clk = ~sd_clk;
376
end
377
 
378
initial
379
begin
380
    rst = 1;
381
    DAT_dat_i = DATA_IDLE;
382
    data_in = fifo_send_data[0];
383
    blksize = 0;
384
    bus_4bit = 0;
385
    blkcnt = 0;
386
    start = 0;
387
 
388
    $display("sd_data_serial_host_tb start ...");
389
 
390
    #(3*SD_TCLK);
391
    rst = 0;
392
 
393
    assert(rd == 0);
394
    assert(we == 0);
395
    assert(DAT_oe_o == 0);
396
    assert(busy == 0);
397
 
398
    #(3*SD_TCLK);
399
 
400
    //tests with 1-bit mode and 4-bit mode
401
    //single block read and single block write
402
    //multiple block read and multiple block write
403
    //test with bad crc (wrong crc during read, wrong rcr in response)
404
 
405
    ///////////////////////////////////////////////////////////////
406
    //1-bit single block read
407
    read_test(64, 0, 0, 0);
408
 
409
    ///////////////////////////////////////////////////////////////
410
    //1-bit single block write
411
    write_test(128, 0, 0, 0);
412
 
413
    ///////////////////////////////////////////////////////////////
414
    //1-bit multiple block read
415
    read_test(32, 3, 0, 0);
416
 
417
    ///////////////////////////////////////////////////////////////
418
    //1-bit multiple block write
419
    write_test(16, 8, 0, 0);
420
 
421
    ///////////////////////////////////////////////////////////////
422
    //              4 - bit
423
    ///////////////////////////////////////////////////////////////
424
    //4-bit single block read
425
    read_test(256, 0, 1, 0);
426
 
427
    ///////////////////////////////////////////////////////////////
428
    //4-bit single block write
429
    write_test(512, 0, 1, 0);
430
 
431
    ///////////////////////////////////////////////////////////////
432
    //4-bit multiple block read
433
    read_test(8, 17, 1, 0);
434
 
435
    ///////////////////////////////////////////////////////////////
436
    //4-bit multiple block write
437
    write_test(4, 32, 1, 0);
438
 
439
    //////////////////////////////////////////////////////////////
440
    //      wierd configurations
441
    //4-bit single block read
442
    read_test(13, 0, 1, 0);
443
    write_test(19, 0, 1, 0);
444
 
445
    //////////////////////////////////////////////////////////////
446
    //      bad crc
447
    //
448
    read_test(32, 0, 1, 1);
449
    read_test(16, 3, 1, 1);
450
    write_test(18, 0, 1, 1);
451
    write_test(64, 2, 1, 1);
452
    read_test(32, 0, 1, 0);
453
    read_test(16, 3, 1, 0);
454
    write_test(18, 0, 1, 0);
455
    write_test(64, 2, 1, 0);
456
 
457
    //////////////////////////////////////////////////////////////
458
    //      TODO: xfer stopped in the middle
459
 
460
    #(100*SD_TCLK) $display("sd_data_serial_host_tb finish ...");
461
    $finish;
462
 
463
end
464
 
465
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.