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 8

Go to most recent revision | 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
            data_in = fifo_send_data[1%$size(fifo_send_data)];
274
            for (i=2; i
275
                for (j=0; j<32/width-1; j++) begin
276
                    #SD_TCLK;
277
                    assert(rd == 0);
278
                end
279
                #SD_TCLK;
280
                assert(rd == 1);
281
                data_in = fifo_send_data[i%$size(fifo_send_data)];
282
            end
283
            #SD_TCLK;
284
            assert(rd == 0);
285
            data_in = fifo_send_data[0];
286
            blocks--;
287
        end
288
    end
289
endtask
290
 
291
task read_test;
292
    input integer bsize;
293
    input integer bcnt;
294
    input integer b_4bit;
295
    input bit crc_failure;
296
    begin
297
        blksize = bsize;
298
        blkcnt = bcnt;
299
        bus_4bit = b_4bit;
300
        start = 2; //read
301
        #SD_TCLK;
302
        blksize = 0;
303
        bus_4bit = 0;
304
        blkcnt = 0;
305
        start = 0;
306
        assert(busy == 1);
307
 
308
        #(20*SD_TCLK);
309
 
310
        fork
311
            sd_card_send(bsize, crc_failure ? 0 : bcnt, b_4bit ? 4 : 1, crc_failure);
312
            check_fifo_write(bsize, crc_failure ? 0 : bcnt, b_4bit ? 4 : 1);
313
        join
314
 
315
        #SD_TCLK;
316
        assert(busy == 0);
317
    end
318
endtask
319
 
320
task write_test;
321
    input integer bsize;
322
    input integer bcnt;
323
    input integer b_4bit;
324
    input bit crc_failure;
325
    begin
326
        blksize = bsize;
327
        blkcnt = bcnt;
328
        bus_4bit = b_4bit;
329
        start = 1; //write
330
        #SD_TCLK;
331
        blksize = 0;
332
        bus_4bit = 0;
333
        blkcnt = 0;
334
        start = 0;
335
        assert(busy == 1);
336
 
337
        fork
338
            check_fifo_read(bsize, crc_failure ? 0 : bcnt, b_4bit ? 4 : 1);
339
            sd_card_receive(bsize, crc_failure ? 0 : bcnt, b_4bit ? 4 : 1, crc_failure ? 3'b101 : 3'b010);
340
        join
341
 
342
        #(2*SD_TCLK);
343
        assert(busy == 0);
344
    end
345
endtask
346
 
347
sd_data_serial_host sd_data_serial_host_dut(
348
                        .sd_clk         (sd_clk),
349
                        .rst            (rst),
350
                        .data_in        (data_in),
351
                        .rd             (rd),
352
                        .data_out       (data_out),
353
                        .we             (we),
354
                        .DAT_oe_o       (DAT_oe_o),
355
                        .DAT_dat_o      (DAT_dat_o),
356
                        .DAT_dat_i      (DAT_dat_i),
357
                        .blksize        (blksize),
358
                        .bus_4bit       (bus_4bit),
359
                        .blkcnt         (blkcnt),
360
                        .start          (start),
361
                        .sd_data_busy   (sd_data_busy),
362
                        .busy           (busy),
363
                        .crc_ok         (crc_ok)
364
                    );
365
 
366
// Generating WB_CLK_I clock
367
always
368
begin
369
    sd_clk=0;
370
    forever #(SD_TCLK/2) sd_clk = ~sd_clk;
371
end
372
 
373
initial
374
begin
375
    rst = 1;
376
    DAT_dat_i = DATA_IDLE;
377
    data_in = fifo_send_data[0];
378
    blksize = 0;
379
    bus_4bit = 0;
380
    blkcnt = 0;
381
    start = 0;
382
 
383
    $display("sd_data_serial_host_tb start ...");
384
 
385
    #(3*SD_TCLK);
386
    rst = 0;
387
 
388
    assert(rd == 0);
389
    assert(we == 0);
390
    assert(DAT_oe_o == 0);
391
    assert(busy == 0);
392
 
393
    #(3*SD_TCLK);
394
 
395
    //tests with 1-bit mode and 4-bit mode
396
    //single block read and single block write
397
    //multiple block read and multiple block write
398
    //test with bad crc (wrong crc during read, wrong rcr in response)
399
 
400
    ///////////////////////////////////////////////////////////////
401
    //1-bit single block read
402
    read_test(64, 0, 0, 0);
403
 
404
    ///////////////////////////////////////////////////////////////
405
    //1-bit single block write
406
    write_test(128, 0, 0, 0);
407
 
408
    ///////////////////////////////////////////////////////////////
409
    //1-bit multiple block read
410
    read_test(32, 3, 0, 0);
411
 
412
    ///////////////////////////////////////////////////////////////
413
    //1-bit multiple block write
414
    write_test(16, 8, 0, 0);
415
 
416
    ///////////////////////////////////////////////////////////////
417
    //              4 - bit
418
    ///////////////////////////////////////////////////////////////
419
    //4-bit single block read
420
    read_test(256, 0, 1, 0);
421
 
422
    ///////////////////////////////////////////////////////////////
423
    //4-bit single block write
424
    write_test(512, 0, 1, 0);
425
 
426
    ///////////////////////////////////////////////////////////////
427
    //4-bit multiple block read
428
    read_test(8, 17, 1, 0);
429
 
430
    ///////////////////////////////////////////////////////////////
431
    //4-bit multiple block write
432
    write_test(4, 32, 1, 0);
433
 
434
    //////////////////////////////////////////////////////////////
435
    //      wierd configurations
436
    //4-bit single block read
437
    read_test(13, 0, 1, 0);
438
    write_test(19, 0, 1, 0);
439
 
440
    //////////////////////////////////////////////////////////////
441
    //      bad crc
442
    //
443
    read_test(32, 0, 1, 1);
444
    read_test(16, 3, 1, 1);
445
    write_test(18, 0, 1, 1);
446
    write_test(64, 2, 1, 1);
447
    read_test(32, 0, 1, 0);
448
    read_test(16, 3, 1, 0);
449
    write_test(18, 0, 1, 0);
450
    write_test(64, 2, 1, 0);
451
 
452
    //////////////////////////////////////////////////////////////
453
    //      TODO: xfer stopped in the middle
454
 
455
    #(100*SD_TCLK) $display("sd_data_serial_host_tb finish ...");
456
    $finish;
457
 
458
end
459
 
460
endmodule

powered by: WebSVN 2.1.0

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