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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [soc/] [driver_sd/] [driver_sd.v] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright (c) 2014, Aleksander Osman
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * * Redistributions of source code must retain the above copyright notice, this
9
 *   list of conditions and the following disclaimer.
10
 *
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 *   this list of conditions and the following disclaimer in the documentation
13
 *   and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
 
27
module driver_sd(
28
 
29
    input           clk,
30
    input           rst_n,
31
 
32
    input       [1:0]   avs_address,
33
    output              avs_waitrequest,
34
    input               avs_read,
35
    output      [31:0]  avs_readdata,
36
    input               avs_write,
37
    input       [31:0]  avs_writedata,
38
 
39
    output reg  [31:0]  avm_address,
40
    input               avm_waitrequest,
41
    output reg          avm_read,
42
    input       [31:0]  avm_readdata,
43
    input               avm_readdatavalid,
44
    output reg          avm_write,
45
    output reg  [31:0]  avm_writedata,
46
 
47
    output reg      sd_clk,
48
    inout           sd_cmd,
49
    inout   [3:0]   sd_dat
50
);
51
 
52
//------------------------------------------------------------------------------
53
 
54
//------------------------------------------------------------------------------ Avalon master
55
 
56
reg data_read;
57
reg data_write;
58
reg [31:0] data_part_contents;
59
reg wait_for_readdatavalid;
60
 
61
always @(posedge clk or negedge rst_n) begin
62
        if(rst_n == 1'b0) begin
63
            avm_address             <= 32'd0;
64
                avm_read                <= 1'b0;
65
        avm_write               <= 1'b0;
66
        avm_writedata           <= 32'b0;
67
 
68
                data_read               <= 1'b0;
69
                data_write              <= 1'b0;
70
                data_part_contents      <= 32'd0;
71
        wait_for_readdatavalid  <= 1'b0;
72
        end
73
        else if(data_state == S_DATA_READ_READY_PART && data_read == 1'b0) begin
74
                if(avm_write && avm_waitrequest == 1'b0) begin
75
                        avm_write <= 1'b0;
76
 
77
                        data_read <= 1'b1;
78
                end
79
                else begin
80
                    avm_address   <= avalon_address_base + { 23'b0, part_counter, 2'b0 };
81
            avm_write     <= 1'b1;
82
            avm_writedata <= { data_part[7:0], data_part[15:8], data_part[23:16], data_part[31:24] };
83
                end
84
        end
85
        else if(data_state == S_DATA_WRITE_READY_PART && data_write == 1'b0) begin
86
                if(avm_read && avm_waitrequest == 1'b0) begin
87
            avm_read <= 1'b0;
88
        end
89
        else if(wait_for_readdatavalid && avm_readdatavalid) begin
90
            avm_read <= 1'b0;
91
            wait_for_readdatavalid <= 1'b0;
92
                        data_part_contents <= { avm_readdata[7:0], avm_readdata[15:8], avm_readdata[23:16], avm_readdata[31:24] };
93
 
94
                        data_write <= 1'b1;
95
                end
96
                else begin
97
                    avm_address             <= avalon_address_base + { 23'b0, part_counter, 2'b0 };
98
                        avm_read                <= 1'b1;
99
            wait_for_readdatavalid  <= 1'b1;
100
                end
101
        end
102
        else if(data_state != S_DATA_READ_READY_PART && data_state != S_DATA_WRITE_READY_PART) begin
103
                data_read <= 1'b0;
104
                data_write <= 1'b0;
105
        end
106
end
107
 
108
//------------------------------------------------------------------------------ Avalon slave
109
 
110
//read mutex
111
 
112
assign avs_readdata = (avs_address == 2'd0)? {29'd0, status[2:0]} : { 29'd0, mutex };
113
 
114
reg [2:0] mutex;
115
always @(posedge clk or negedge rst_n) begin
116
    if(rst_n == 1'b0)                                                               mutex <= 3'd0;
117
    else if(mutex == 3'd0 && avs_address == 2'd1 && avs_read && ~(avs_waitrequest)) mutex <= 3'd1;
118
    else if(mutex == 3'd0 && avs_address == 2'd2 && avs_read && ~(avs_waitrequest)) mutex <= 2'd2;
119
    else if(mutex == 3'd0 && avs_address == 2'd3 && avs_read && ~(avs_waitrequest)) mutex <= 3'd3;
120
    else if(mutex < 3'd4 && (status == STATUS_READ || status == STATUS_WRITE))      mutex <= 3'd4;
121
    else if(status == STATUS_IDLE && status_last != STATUS_IDLE)                    mutex <= 3'd0;
122
end
123
 
124
assign avs_waitrequest = control_state == S_CTRL_PRE_IDLE;
125
 
126
// write only
127
reg [31:0] sd_address;
128
reg [31:0] sd_block_count;
129
reg [1:0]  control;
130
reg [31:0] avalon_address_base;
131
 
132
localparam [1:0] CONTROL_IDLE   = 2'd0;
133
localparam [1:0] CONTROL_REINIT = 2'd1;
134
localparam [1:0] CONTROL_READ    = 2'd2;
135
localparam [1:0] CONTROL_WRITE   = 2'd3;
136
 
137
always @(posedge clk or negedge rst_n) begin
138
        if(rst_n == 1'b0) begin
139
                avalon_address_base <= 32'd0;
140
                sd_address          <= 32'd0;
141
                sd_block_count      <= 32'd0;
142
                control             <= 2'd0;
143
        end
144
        else begin
145
                if(control_state == S_CTRL_PRE_IDLE) begin
146
                        sd_block_count      <= sd_block_count - 32'd1;
147
                        sd_address          <= sd_address + 32'd1;
148
                        avalon_address_base <= avalon_address_base + 32'd512;
149
 
150
                        if(sd_block_count == 32'd1) control <= CONTROL_IDLE;
151
                end
152
                else if(avs_write) begin
153
                if(avs_address == 2'd0)         avalon_address_base <= avs_writedata;
154
                else if(avs_address == 2'd1)    sd_address          <= avs_writedata;
155
                else if(avs_address == 2'd2)    sd_block_count      <= avs_writedata;
156
                else if(avs_address == 2'd3)    control             <= avs_writedata[1:0];
157
        end
158
        end
159
 
160
end
161
 
162
//------------------------------------------------------------------------------ Control state machine
163
 
164
reg [3:0]  control_state;
165
reg [15:0] error_count;
166
reg [2:0]  status;
167
reg [37:0] cmd_send_contents;
168
 
169
reg start_cmd;
170
reg start_read;
171
reg start_write;
172
 
173
reg [2:0] status_last;
174
always @(posedge clk or negedge rst_n) begin
175
    if(rst_n == 1'b0)   status_last <= STATUS_INIT;
176
    else                status_last <= status;
177
end
178
 
179
`define CRC7_REVERSE crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6]
180
 
181
localparam [3:0] S_CTRL_INIT        = 4'd0;
182
localparam [3:0] S_CTRL_CMD0        = 4'd1;
183
localparam [3:0] S_CTRL_CMD8        = 4'd2;
184
localparam [3:0] S_CTRL_CMD55       = 4'd3;
185
localparam [3:0] S_CTRL_ACMD41      = 4'd4;
186
localparam [3:0] S_CTRL_CMD2        = 4'd5;
187
localparam [3:0] S_CTRL_CMD3        = 4'd6;
188
localparam [3:0] S_CTRL_CMD7        = 4'd7;
189
localparam [3:0] S_CTRL_PRE_IDLE    = 4'd8;
190
localparam [3:0] S_CTRL_IDLE        = 4'd9;
191
localparam [3:0] S_CTRL_CMD17_READ  = 4'd10;
192
localparam [3:0] S_CTRL_CMD24_WRITE = 4'd11;
193
 
194
localparam [2:0] STATUS_INIT        = 3'd0;
195
localparam [2:0] STATUS_INIT_ERROR  = 3'd1;
196
localparam [2:0] STATUS_IDLE        = 3'd2;
197
localparam [2:0] STATUS_READ        = 3'd3;
198
localparam [2:0] STATUS_WRITE       = 3'd4;
199
localparam [2:0] STATUS_ERROR       = 3'd5;
200
 
201
always @(posedge clk or negedge rst_n) begin
202
        if(rst_n == 1'b0) begin
203
                control_state <= S_CTRL_INIT;
204
                status <= STATUS_INIT;
205
                cmd_send_contents <= 38'd0;
206
                start_cmd <= 1'b0;
207
                start_read <= 1'b0;
208
                start_write <= 1'b0;
209
                error_count <= 16'd0;
210
        end
211
        else if(control_state == S_CTRL_INIT && error_count == 16'd65535) begin
212
                status <= STATUS_INIT_ERROR;
213
 
214
                if(control == CONTROL_REINIT) begin
215
                        error_count <= 16'd0;
216
                        control_state <= S_CTRL_INIT;
217
                end
218
        end
219
        else if(control_state == S_CTRL_INIT) begin
220
                status <= STATUS_INIT;
221
 
222
                if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
223
                    start_cmd <= 1'b1;
224
                        //CMD0, no arguments
225
                        cmd_send_contents <= { 6'd0, 32'd0 };
226
                        control_state <= S_CTRL_CMD0;
227
                end
228
        end
229
        else if(control_state == S_CTRL_CMD0) begin
230
 
231
                if(cmd_state == S_CMD_REPLY_ERROR) begin
232
                        error_count <= error_count + 16'd1;
233
                        control_state <= S_CTRL_INIT;
234
                end
235
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
236
                        start_cmd <= 1'b1;
237
                        //CMD8, supply voltage, check pattern
238
                        cmd_send_contents <= { 6'd8, 20'd0, 4'b0001, 8'b10101010 };
239
                        control_state <= S_CTRL_CMD8;
240
                end
241
                else start_cmd <= 1'b0;
242
        end
243
        else if(control_state == S_CTRL_CMD8) begin
244
                if(start_cmd == 1'b1) begin
245
                        start_cmd <= 1'b0;
246
                end
247
                else if(cmd_state == S_CMD_REPLY_ERROR ||
248
                        (cmd_state == S_CMD_IDLE && cmd_reply != { 1'b0, 1'b0, 6'd8, 20'd0, 4'b0001, 8'b10101010, `CRC7_REVERSE, 1'b1 })
249
                ) begin
250
                        error_count <= error_count + 16'd1;
251
                        control_state <= S_CTRL_INIT;
252
                end
253
                else if(cmd_state == S_CMD_IDLE) begin
254
                        start_cmd <= 1'b1;
255
                        //CMD55, RCA
256
                        cmd_send_contents <= { 6'd55, 16'd0, 16'd0};
257
                        control_state <= S_CTRL_CMD55;
258
                end
259
        end
260
        else if(control_state == S_CTRL_CMD55) begin
261
                if(start_cmd == 1'b1) begin
262
                        start_cmd <= 1'b0;
263
                end
264
                else if(cmd_state == S_CMD_REPLY_ERROR ||
265
                        (cmd_state == S_CMD_IDLE &&
266
                                (cmd_reply[47:40] != { 1'b0, 1'b0, 6'd55 } || cmd_reply[39:27] != 13'b0 || cmd_reply[24:21] != 4'b0 ||
267
                                 cmd_reply[13] != 1'b1 || cmd_reply[11] != 1'b0 || cmd_reply[7:0] != { `CRC7_REVERSE, 1'b1 }
268
                                )
269
                        )
270
                ) begin
271
                        error_count <= error_count + 16'd1;
272
                        control_state <= S_CTRL_INIT;
273
                end
274
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
275
                        start_cmd <= 1'b1;
276
                        //ACMD41, 
277
                        cmd_send_contents <= {  6'd41,                                                          //command index
278
                                                                        1'b0,                                                           //reserved bit
279
                                                                        1'b1,                                                           //host capacity support HCS(OCR[30])
280
                                                                        6'b0,                                                           //reserved bits
281
                                                                        24'b0001_0000_0000_0000_0000_0000       //VDD voltage window OCR[23:0]
282
                        };
283
                        control_state <= S_CTRL_ACMD41;
284
                end
285
        end
286
        else if(control_state == S_CTRL_ACMD41) begin
287
                if(start_cmd == 1'b1) begin
288
                        start_cmd <= 1'b0;
289
                end
290
                else if(cmd_state == S_CMD_REPLY_ERROR ||
291
                        (cmd_state == S_CMD_IDLE && (cmd_reply[47:40] != { 1'b0, 1'b0, 6'b111111 } ||
292
                                cmd_reply[39:38] != 2'b11 || cmd_reply[7:0] != {7'b1111111, 1'b1 })
293
                        )
294
                ) begin
295
                        if(error_count == 16'd65535) begin
296
                                control_state <= S_CTRL_INIT;
297
                        end
298
                        else begin
299
                                error_count <= error_count + 16'd1;
300
                                start_cmd <= 1'b1;
301
                                //CMD55, RCA
302
                                cmd_send_contents <= { 6'd55, 16'd0, 16'd0};
303
                                control_state <= S_CTRL_CMD55;
304
                        end
305
                end
306
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
307
                        start_cmd <= 1'b1;
308
                        //CMD2, no arguments
309
                        cmd_send_contents <= { 6'd2, 32'd0 };
310
                        control_state <= S_CTRL_CMD2;
311
                end
312
        end
313
        else if(control_state == S_CTRL_CMD2) begin
314
                if(start_cmd == 1'b1) begin
315
                        start_cmd <= 1'b0;
316
                end
317
                else if(cmd_state == S_CMD_REPLY_ERROR ||
318
                        (cmd_state == S_CMD_IDLE && cmd_reply[0] != 1'b1)
319
                ) begin
320
                        error_count <= error_count + 16'd1;
321
                        control_state <= S_CTRL_INIT;
322
                end
323
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
324
                        start_cmd <= 1'b1;
325
                        //CMD3, no arguments
326
                        cmd_send_contents <= { 6'd3, 32'd0 };
327
                        control_state <= S_CTRL_CMD3;
328
                end
329
        end
330
        else if(control_state == S_CTRL_CMD3) begin
331
                if(start_cmd == 1'b1) begin
332
                        start_cmd <= 1'b0;
333
                end
334
                else if(cmd_state == S_CMD_REPLY_ERROR ||
335
                        (cmd_state == S_CMD_IDLE &&
336
                                (cmd_reply[47:40] != { 1'b0, 1'b0, 6'd3 } ||
337
                                 /*23:8= 23,22,19,12:0 from card status*/
338
                                 cmd_reply[23:21] != 3'b0 || cmd_reply[13] != 1'b0 || cmd_reply[11] != 1'b0 ||
339
                                 cmd_reply[7:0] != { `CRC7_REVERSE, 1'b1 }
340
                                )
341
                        )
342
                ) begin
343
                        error_count <= error_count + 16'd1;
344
                        control_state <= S_CTRL_INIT;
345
                end
346
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
347
 
348
                        start_cmd <= 1'b1;
349
                        //CMD7, no arguments
350
                        cmd_send_contents <= {  6'd7,                           //command index
351
                                                                        cmd_reply[39:24],       //RCA
352
                                                                        16'd0                           //stuff bits
353
                        };
354
                        control_state <= S_CTRL_CMD7;
355
                end
356
        end
357
        else if(control_state == S_CTRL_CMD7) begin
358
                if(start_cmd == 1'b1) begin
359
                        start_cmd <= 1'b0;
360
                end
361
                else if(cmd_state == S_CMD_REPLY_ERROR ||
362
                        (cmd_state == S_CMD_IDLE &&
363
                                (cmd_reply[47:40] != { 1'b0, 1'b0, 6'd7 } || cmd_reply[39:27] != 13'b0 || cmd_reply[24:21] != 4'b0 ||
364
                                 cmd_reply[13] != 1'b0 || cmd_reply[11] != 1'b0 || cmd_reply[7:0] != { `CRC7_REVERSE, 1'b1 }
365
                                )
366
                        )
367
                ) begin
368
                        error_count <= error_count + 16'd1;
369
                        control_state <= S_CTRL_INIT;
370
                end
371
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
372
                        start_cmd <= 1'b0;
373
 
374
                        error_count <= 16'd0;
375
                        control_state <= S_CTRL_IDLE;
376
                end
377
        end
378
        else if(control_state == S_CTRL_PRE_IDLE) begin
379
                control_state <= S_CTRL_IDLE;
380
        end
381
        else if(control_state == S_CTRL_IDLE && error_count != 16'd0) begin
382
                status <= STATUS_ERROR;
383
 
384
                if(control == CONTROL_IDLE) begin
385
                        control_state <= S_CTRL_IDLE;
386
                        error_count <= 16'd0;
387
                end
388
                else if(control == CONTROL_REINIT) begin
389
                        control_state <= S_CTRL_INIT;
390
                        error_count <= 16'd0;
391
                end
392
        end
393
        else if(control_state == S_CTRL_IDLE) begin
394
                if(control == CONTROL_READ && sd_block_count != 32'd0) begin
395
                        status <= STATUS_READ;
396
                        start_cmd <= 1'b1;
397
                        start_read <= 1'b1;
398
                        //CMD17, sector address
399
                        cmd_send_contents <= {  6'd17,                          //command index
400
                                                                        sd_address[31:0] //sector address
401
                        };
402
                        control_state <= S_CTRL_CMD17_READ;
403
                end
404
                else if(control == CONTROL_WRITE && sd_block_count != 32'd0) begin
405
                        status <= STATUS_WRITE;
406
                        start_cmd <= 1'b1;
407
                        start_write <= 1'b1;
408
                        //CMD24, sector address
409
                        cmd_send_contents <= {  6'd24,                          //command index
410
                                                                        sd_address[31:0]         //sector address
411
                        };
412
                        control_state <= S_CTRL_CMD24_WRITE;
413
                end
414
                else begin
415
                        status <= STATUS_IDLE;
416
                end
417
        end
418
        else if(control_state == S_CTRL_CMD17_READ) begin
419
                if(start_cmd == 1'b1) begin
420
                        start_cmd <= 1'b0;
421
                end
422
                else if(cmd_state == S_CMD_REPLY_ERROR ||
423
                        (cmd_state == S_CMD_IDLE &&
424
                                (cmd_reply[47:40] != { 1'b0, 1'b0, 6'd17 } || cmd_reply[39:27] != 13'b0 || cmd_reply[24:21] != 4'b0 ||
425
                                 cmd_reply[13] != 1'b0 || cmd_reply[11] != 1'b0 || cmd_reply[7:0] != { `CRC7_REVERSE, 1'b1 }
426
                                )
427
                        )
428
                ) begin
429
                        error_count <= error_count + 16'd1;
430
                        control_state <= S_CTRL_IDLE;
431
                end
432
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_read == 1'b1) begin
433
                        start_read <= 1'b0;
434
                end
435
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_read == 1'b0 && data_state == S_DATA_READ_ERROR) begin
436
                        error_count <= error_count + 16'd1;
437
                        control_state <= S_CTRL_IDLE;
438
                end
439
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_read == 1'b0 && data_state == S_DATA_IDLE) begin
440
                        error_count <= 16'd0;
441
                        control_state <= S_CTRL_PRE_IDLE;
442
                end
443
        end
444
        else if(control_state == S_CTRL_CMD24_WRITE) begin
445
                if(start_cmd == 1'b1) begin
446
                        start_cmd <= 1'b0;
447
                end
448
                else if(cmd_state == S_CMD_REPLY_ERROR ||
449
                        (cmd_state == S_CMD_IDLE &&
450
                                (cmd_reply[47:40] != { 1'b0, 1'b0, 6'd24 } || cmd_reply[39:27] != 13'b0 || cmd_reply[24:21] != 4'b0 ||
451
                                 cmd_reply[13] != 1'b0 || cmd_reply[11] != 1'b0 || cmd_reply[7:0] != { `CRC7_REVERSE, 1'b1 }
452
                                )
453
                        )
454
                ) begin
455
                        error_count <= error_count + 16'd1;
456
                        control_state <= S_CTRL_IDLE;
457
                end
458
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_write == 1'b1) begin
459
                        start_write <= 1'b0;
460
                end
461
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_write == 1'b0 && data_state == S_DATA_WRITE_ERROR) begin
462
                        error_count <= error_count + 16'd1;
463
                        control_state <= S_CTRL_IDLE;
464
                end
465
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_write == 1'b0 && data_state == S_DATA_IDLE) begin
466
                        error_count <= 16'd0;
467
                        control_state <= S_CTRL_PRE_IDLE;
468
                end
469
        end
470
end
471
 
472
//------------------------------------------------------------------------------ SD interface
473
 
474
reg sd_cmd_reg = 1'b1;
475
reg sd_dat_reg = 1'b1;
476
 
477
assign sd_cmd = (sd_cmd_enable == 1'b1) ?  sd_cmd_reg : 1'bZ;
478
assign sd_dat[0] = (sd_data_enable == 1'b1) ? sd_dat_reg : 1'bZ;
479
 
480
assign sd_dat[3:1] = 3'bZ;
481
 
482
//CID register not interpreted: CRC7 not checked, always accepted
483
 
484
//---------------------------------------------------- SD data
485
 
486
reg         sd_data_enable;
487
reg [3:0]   data_state;
488
reg [23:0]  data_counter;
489
reg [6:0]   part_counter;
490
reg [15:0]  crc16;
491
reg [31:0]  data_part;
492
 
493
reg         clk_data_ena;
494
reg         clk_master_ena;
495
 
496
 
497
localparam [3:0] S_DATA_IDLE                                                             = 4'd0;
498
localparam [3:0] S_DATA_READ_START_BIT                                           = 4'd1;
499
localparam [3:0] S_DATA_READ_CONTENTS                                            = 4'd2;
500
localparam [3:0] S_DATA_READ_READY_PART                                          = 4'd3;
501
localparam [3:0] S_DATA_READ_READY_PART_CONTINUE                         = 4'd4;
502
localparam [3:0] S_DATA_READ_CRC16_END_BIT                                       = 4'd5;
503
localparam [3:0] S_DATA_READ_ERROR                                                       = 4'd6;
504
localparam [3:0] S_DATA_WRITE_START_BIT                                          = 4'd7;
505
localparam [3:0] S_DATA_WRITE_READY_PART                                         = 4'd8;
506
localparam [3:0] S_DATA_WRITE_CONTENTS                                           = 4'd9;
507
localparam [3:0] S_DATA_WRITE_CRC16_END_BIT                                      = 4'd10;
508
localparam [3:0] S_DATA_WRITE_CRC_STATUS_START                           = 4'd11;
509
localparam [3:0] S_DATA_WRITE_CRC_STATUS_CONTENTS_END_BIT        = 4'd12;
510
localparam [3:0] S_DATA_WRITE_BUSY_START                                         = 4'd13;
511
localparam [3:0] S_DATA_WRITE_BUSY_WAIT                                          = 4'd14;
512
localparam [3:0] S_DATA_WRITE_ERROR                                                      = 4'd15;
513
 
514
 
515
always @(posedge clk or negedge rst_n) begin
516
        if(rst_n == 1'b0) begin
517
                sd_data_enable  <= 1'b0;
518
                data_state              <= S_DATA_IDLE;
519
                data_counter    <= 24'd0;
520
                part_counter    <= 7'd0;
521
                crc16                   <= 16'd0;
522
                data_part               <= 32'd0;
523
                clk_data_ena    <= 1'b0;
524
                clk_master_ena  <= 1'b1;
525
                sd_dat_reg              <= 1'b1;
526
        end
527
        else if(data_state == S_DATA_IDLE) begin
528
                //do not wait for read command and reply
529
                if(start_read == 1'b1) begin
530
                        data_state <= S_DATA_READ_START_BIT;
531
                end
532
                //wait for write command and reply
533
                else if(start_write == 1'b1 && start_cmd == 1'b0 && cmd_state == S_CMD_IDLE) begin
534
                        data_state <= S_DATA_WRITE_START_BIT;
535
                end
536
        end
537
        else if(clk_counter == 2'd0) begin
538
 
539
                //wait for response and data simultaneously (data read)
540
                if(data_state == S_DATA_READ_START_BIT) begin
541
                        clk_data_ena <= 1'b1;
542
 
543
                        if(sd_dat[0] == 1'b0) begin
544
                                crc16 <= { sd_dat[0] ^ crc16[0], crc16[15:12], sd_dat[0] ^ crc16[11] ^ crc16[0], crc16[10:5],
545
                                        sd_dat[0] ^ crc16[4] ^ crc16[0], crc16[3:1] };
546
 
547
                                data_state <= S_DATA_READ_CONTENTS;
548
                                data_counter <= 24'd0;
549
                        end
550
                        else if(data_counter == 24'd65535) begin
551
                                data_state <= S_DATA_READ_ERROR;
552
                                data_counter <= 24'd0;
553
                        end
554
                        else data_counter <= data_counter + 24'd1;
555
                end
556
                else if(data_state == S_DATA_READ_CONTENTS) begin
557
                        crc16 <= { sd_dat[0] ^ crc16[0], crc16[15:12], sd_dat[0] ^ crc16[11] ^ crc16[0],
558
                                crc16[10:5], sd_dat[0] ^ crc16[4] ^ crc16[0], crc16[3:1] };
559
                        data_part <= { data_part[30:0], sd_dat[0] };
560
 
561
                        if(data_counter == 24'd30) begin
562
                                clk_master_ena <= 1'b0;
563
                                data_counter <= data_counter + 24'd1;
564
                        end
565
                        else if(data_counter == 24'd31) begin
566
                                data_state <= S_DATA_READ_READY_PART;
567
                                data_counter <= 24'd0;
568
                        end
569
                        else data_counter <= data_counter + 24'd1;
570
                end
571
                else if(data_state == S_DATA_READ_READY_PART) begin
572
                        if(data_read == 1'b1) begin
573
                                clk_master_ena <= 1'b1;
574
                                data_state <= S_DATA_READ_READY_PART_CONTINUE;
575
                        end
576
                end
577
                else if(data_state == S_DATA_READ_READY_PART_CONTINUE) begin
578
                        if(part_counter == 7'd127) begin
579
                                data_state <= S_DATA_READ_CRC16_END_BIT;
580
                                part_counter <= 7'd0;
581
                        end
582
                        else begin
583
                                data_state <= S_DATA_READ_CONTENTS;
584
                                part_counter <= part_counter + 7'd1;
585
                        end
586
                end
587
                else if(data_state == S_DATA_READ_CRC16_END_BIT) begin
588
                        data_part <= { sd_dat[0], data_part[31:1] };
589
 
590
                        if(data_counter == 24'd16) begin
591
                                if(data_part[31:16] != crc16[15:0] || sd_dat[0] != 1'b1) begin
592
                                        data_state <= S_DATA_READ_ERROR;
593
                                        data_counter <= 24'd0;
594
                                end
595
                                else begin
596
                                        clk_data_ena <= 1'b0;
597
                                        data_state <= S_DATA_IDLE;
598
                                        data_counter <= 24'd0;
599
                                        crc16 <= 16'd0;
600
                                end
601
                        end
602
                        else data_counter <= data_counter + 24'd1;
603
                end
604
                else if(data_state == S_DATA_READ_ERROR) begin
605
                        clk_data_ena <= 1'b0;
606
                        data_state <= S_DATA_IDLE;
607
                        data_counter <= 24'd0;
608
                        crc16 <= 16'd0;
609
                end
610
 
611
                //send data on data line, wait for crc status, wait while busy on data line (data write)
612
                else if(data_state == S_DATA_WRITE_START_BIT) begin
613
                        sd_dat_reg <= 1'b0;
614
                        crc16 <= { 1'b0 ^ crc16[0], crc16[15:12], 1'b0 ^ crc16[11] ^ crc16[0], crc16[10:5],
615
                                1'b0 ^ crc16[4] ^ crc16[0], crc16[3:1] };
616
 
617
                        sd_data_enable <= 1'b1;
618
                        clk_data_ena <= 1'b1;
619
                        data_counter <= 24'd0;
620
                        data_state <= S_DATA_WRITE_READY_PART;
621
                end
622
                else if(data_state == S_DATA_WRITE_READY_PART) begin
623
 
624
                        if(data_write == 1'b1) begin
625
                            clk_data_ena <= 1'b1;
626
                                data_state <= S_DATA_WRITE_CONTENTS;
627
                                data_part <= data_part_contents;
628
                        end
629
                        else begin
630
                            clk_data_ena <= 1'b0;
631
                        end
632
                end
633
                else if(data_state == S_DATA_WRITE_CONTENTS) begin
634
                        sd_dat_reg <= data_part[31];
635
                        crc16 <= { data_part[31] ^ crc16[0], crc16[15:12], data_part[31] ^ crc16[11] ^ crc16[0], crc16[10:5],
636
                                data_part[31] ^ crc16[4] ^ crc16[0], crc16[3:1] };
637
                        data_part <= { data_part[30:0], 1'b0 };
638
 
639
                        if(data_counter == 24'd31) begin
640
                                data_counter <= 24'd0;
641
 
642
                                if(part_counter == 7'd127) begin
643
                                        part_counter <= 7'd0;
644
                                        data_state <= S_DATA_WRITE_CRC16_END_BIT;
645
                                end
646
                                else begin
647
                                    clk_data_ena <= 1'b0;
648
                                        part_counter <= part_counter + 7'd1;
649
                                        data_state <= S_DATA_WRITE_READY_PART;
650
                                end
651
                        end
652
                        else data_counter <= data_counter + 24'd1;
653
                end
654
 
655
                else if(data_state == S_DATA_WRITE_CRC16_END_BIT) begin
656
                        sd_dat_reg <= crc16[0];
657
 
658
                        if(data_counter == 24'd16) begin
659
                            data_counter <= 24'd0;
660
                            crc16 <= 16'd0;
661
                                data_state <= S_DATA_WRITE_CRC_STATUS_START;
662
                        end
663
                        else begin
664
                                crc16 <= { 1'b1, crc16[15:1] };
665
                                data_counter <= data_counter + 24'd1;
666
                        end
667
 
668
                end
669
                else if(data_state == S_DATA_WRITE_CRC_STATUS_START) begin
670
                        sd_data_enable <= 1'b0;
671
 
672
                        if(sd_dat[0] == 1'b0) begin
673
                                data_state <= S_DATA_WRITE_CRC_STATUS_CONTENTS_END_BIT;
674
                                data_counter <= 24'b0;
675
                        end
676
                        else if(data_counter == 24'd65535) begin
677
                                data_state <= S_DATA_WRITE_ERROR;
678
                                data_counter <= 24'b0;
679
                        end
680
                        else data_counter <= data_counter + 24'd1;
681
                end
682
 
683
                else if(data_state == S_DATA_WRITE_CRC_STATUS_CONTENTS_END_BIT) begin
684
                        data_part <= { data_part[30:0], sd_dat[0] };
685
 
686
                        if(data_counter == 24'd3) begin
687
                                data_state <= S_DATA_WRITE_BUSY_START;
688
                                data_counter <= 24'b0;
689
                        end
690
                        else data_counter <= data_counter + 24'd1;
691
                end
692
                else if(data_state == S_DATA_WRITE_BUSY_START) begin
693
 
694
                        if(sd_dat[0] == 1'b0) begin
695
                                data_state <= S_DATA_WRITE_BUSY_WAIT;
696
                                data_counter <= 24'b0;
697
                        end
698
                        else if(data_counter == 24'd65535) begin
699
                                data_state <= S_DATA_WRITE_ERROR;
700
                                data_counter <= 24'b0;
701
                        end
702
                        else data_counter <= data_counter + 24'd1;
703
                end
704
                else if(data_state == S_DATA_WRITE_BUSY_WAIT) begin
705
                        if(sd_dat[0] == 1'b1 && data_part[3:0] != 4'b0101) begin
706
                                data_state <= S_DATA_WRITE_ERROR;
707
                                data_counter <= 24'd0;
708
                        end
709
                        else if(sd_dat[0] == 1'b1) begin
710
                                clk_data_ena <= 1'b0;
711
                                data_state <= S_DATA_IDLE;
712
                                data_counter <= 24'd0;
713
                        end
714
                        else if(data_counter == 24'hFFFFFF) begin
715
                                data_state <= S_DATA_WRITE_ERROR;
716
                                data_counter <= 24'd0;
717
                        end
718
                        else data_counter <= data_counter + 24'd1;
719
                end
720
                else if(data_state == S_DATA_WRITE_ERROR) begin
721
                        clk_data_ena <= 1'b0;
722
                        data_state <= S_DATA_IDLE;
723
                        data_counter <= 24'd0;
724
                end
725
        end
726
end
727
 
728
//------------------------------------------------------------------------------ SD command
729
 
730
reg             sd_cmd_enable;
731
reg [37:0]       cmd_send;
732
reg [47:0]       cmd_reply;
733
reg [3:0]        cmd_state;
734
reg [7:0]        cmd_counter;
735
reg [6:0]        crc7;
736
reg             clk_cmd_ena;
737
 
738
localparam [3:0] S_CMD_IDLE                                      = 4'd0;
739
localparam [3:0] S_CMD_SEND_START_ONES           = 4'd1;
740
localparam [3:0] S_CMD_SEND_START_BIT            = 4'd2;
741
localparam [3:0] S_CMD_SEND_START_HOST           = 4'd3;
742
localparam [3:0] S_CMD_SEND_CONTENTS             = 4'd4;
743
localparam [3:0] S_CMD_SEND_CRC7                         = 4'd5;
744
localparam [3:0] S_CMD_SEND_END_BIT                      = 4'd6;
745
localparam [3:0] S_CMD_SEND_END_ONES             = 4'd7;
746
localparam [3:0] S_CMD_REPLY_START_BIT           = 4'd8;
747
localparam [3:0] S_CMD_REPLY_CONTENTS            = 4'd9;
748
localparam [3:0] S_CMD_REPLY_CRC7_END_BIT        = 4'd10;
749
localparam [3:0] S_CMD_REPLY_FINISH_ONES         = 4'd11;
750
localparam [3:0] S_CMD_REPLY_ERROR                       = 4'd12;
751
 
752
always @(posedge clk or negedge rst_n) begin
753
        if(rst_n == 1'b0) begin
754
                sd_cmd_enable   <= 1'b0;
755
                cmd_send                <= 38'd0;
756
                cmd_reply               <= 48'd0;
757
                cmd_state               <= S_CMD_IDLE;
758
                cmd_counter     <= 8'd0;
759
                crc7                    <= 7'd0;
760
                clk_cmd_ena     <= 1'b0;
761
                sd_cmd_reg              <= 1'b1;
762
        end
763
        else if(cmd_state == S_CMD_IDLE) begin
764
                if(start_cmd == 1'b1) begin
765
                        cmd_state <= S_CMD_SEND_START_ONES;
766
                end
767
        end
768
        else if(clk_counter == 2'd0 && clk_master_ena == 1'b1) begin
769
 
770
                //send command
771
                if(cmd_state == S_CMD_SEND_START_ONES) begin
772
                        sd_cmd_enable <= 1'b1;
773
                        sd_cmd_reg <= 1'b1;
774
                        clk_cmd_ena <= 1'b1;
775
                        crc7 <= 7'd0;
776
 
777
                        if(cmd_counter == 8'd7) begin
778
                                cmd_state <= S_CMD_SEND_START_BIT;
779
                                cmd_counter <= 8'd0;
780
                        end
781
                        else cmd_counter <= cmd_counter + 8'd1;
782
                end
783
                else if(cmd_state == S_CMD_SEND_START_BIT) begin
784
                        sd_cmd_reg <= 1'b0;
785
                        crc7 <= { 1'b0 ^ crc7[0], crc7[6:5], 1'b0 ^ crc7[4] ^ crc7[0], crc7[3:1] };
786
 
787
                        cmd_state <= S_CMD_SEND_START_HOST;
788
                end
789
                else if(cmd_state == S_CMD_SEND_START_HOST) begin
790
                        sd_cmd_reg <= 1'b1;
791
                        crc7 <= { 1'b1 ^ crc7[0], crc7[6:5], 1'b1 ^ crc7[4] ^ crc7[0], crc7[3:1] };
792
 
793
                        cmd_send <= cmd_send_contents;
794
                        cmd_state <= S_CMD_SEND_CONTENTS;
795
                end
796
                else if(cmd_state == S_CMD_SEND_CONTENTS) begin
797
                        sd_cmd_reg <= cmd_send[37];
798
                        crc7 <= { cmd_send[37] ^ crc7[0], crc7[6:5], cmd_send[37] ^ crc7[4] ^ crc7[0], crc7[3:1] };
799
                        cmd_send <= { cmd_send[36:0], 1'b0 };
800
 
801
                        if(cmd_counter == 8'd37) begin
802
                                cmd_state <= S_CMD_SEND_CRC7;
803
                                cmd_counter <= 8'd0;
804
                        end
805
                        else cmd_counter <= cmd_counter + 8'd1;
806
                end
807
                else if(cmd_state == S_CMD_SEND_CRC7) begin
808
                        sd_cmd_reg <= crc7[0];
809
                        crc7 <= { 1'b0, crc7[6:1] };
810
 
811
                        if(cmd_counter == 8'd6) begin
812
                                cmd_state <= S_CMD_SEND_END_BIT;
813
                                cmd_counter <= 8'd0;
814
                        end
815
                        else cmd_counter <= cmd_counter + 8'd1;
816
                end
817
                else if(cmd_state == S_CMD_SEND_END_BIT) begin
818
                        sd_cmd_reg <= 1'b1;
819
 
820
                        // if CMD0: send ones
821
                        if(control_state == S_CTRL_CMD0) begin
822
                                cmd_state <= S_CMD_SEND_END_ONES;
823
                        end
824
                        else begin
825
                                crc7 <= 7'd0;
826
                                cmd_state <= S_CMD_REPLY_START_BIT;
827
                        end
828
                end
829
                else if(cmd_state == S_CMD_SEND_END_ONES) begin
830
                        sd_cmd_enable <= 1'b0;
831
                        sd_cmd_reg <= 1'b1;
832
 
833
                        if(cmd_counter == 8'd7) begin
834
                                clk_cmd_ena <= 1'b0;
835
                                cmd_state <= S_CMD_IDLE;
836
                                cmd_counter <= 8'd0;
837
                        end
838
                        else cmd_counter <= cmd_counter + 8'd1;
839
                end
840
 
841
                //wait for response: 48-bits with CRC7
842
                //wait for response: 48-bits without CRC7
843
                //wait for response: 136-bits (CMD2/R2)
844
                //wait for response and busy on data line simultaneously: (CMD7/R1b)
845
                else if(cmd_state == S_CMD_REPLY_START_BIT) begin
846
                        sd_cmd_enable <= 1'b0;
847
 
848
                        if(sd_cmd == 1'b0) begin
849
                                crc7 <= { sd_cmd ^ crc7[0], crc7[6:5], sd_cmd ^ crc7[4] ^ crc7[0], crc7[3:1] };
850
                                cmd_reply <= { cmd_reply[46:0], sd_cmd };
851
 
852
                                cmd_state <= S_CMD_REPLY_CONTENTS;
853
                                cmd_counter <= 8'd0;
854
                        end
855
                        else if(cmd_counter == 8'd255) begin
856
                                crc7 <= 7'd0;
857
                                cmd_state <= S_CMD_REPLY_ERROR;
858
                                cmd_counter <= 8'd0;
859
                        end
860
                        else cmd_counter <= cmd_counter + 8'd1;
861
                end
862
                else if(cmd_state == S_CMD_REPLY_CONTENTS) begin
863
                        crc7 <= { sd_cmd ^ crc7[0], crc7[6:5], sd_cmd ^ crc7[4] ^ crc7[0], crc7[3:1] };
864
                        cmd_reply <= { cmd_reply[46:0], sd_cmd };
865
 
866
                        if(     (control_state != S_CTRL_CMD2 && cmd_counter == 8'd38) ||
867
                                (control_state == S_CTRL_CMD2 && cmd_counter == 8'd126)
868
                        ) begin
869
                                cmd_state <= S_CMD_REPLY_CRC7_END_BIT;
870
                                cmd_counter <= 8'd0;
871
                        end
872
                        else cmd_counter <= cmd_counter + 8'd1;
873
                end
874
                else if(cmd_state == S_CMD_REPLY_CRC7_END_BIT) begin
875
                        cmd_reply <= { cmd_reply[46:0], sd_cmd };
876
 
877
                        if(cmd_counter == 8'd7) begin
878
                                cmd_state <= S_CMD_REPLY_FINISH_ONES;
879
                                cmd_counter <= 8'd0;
880
                        end
881
                        else cmd_counter <= cmd_counter + 8'd1;
882
                end
883
                //at least 2 clock cycles required for data write
884
                else if(cmd_state == S_CMD_REPLY_FINISH_ONES) begin
885
                        //check is sd_dat[0] busy for CMD7
886
                        if(cmd_counter >= 8'd7 && (control_state != S_CTRL_CMD7 || sd_dat[0] == 1'b1)) begin
887
                                clk_cmd_ena <= 1'b0;
888
                                cmd_state <= S_CMD_IDLE;
889
                                cmd_counter <= 8'd0;
890
                        end
891
                        else if(cmd_counter == 8'd255) begin
892
                                cmd_state <= S_CMD_REPLY_ERROR;
893
                                cmd_counter <= 8'd0;
894
                        end
895
                        else cmd_counter <= cmd_counter + 8'd1;
896
                end
897
                else if(cmd_state == S_CMD_REPLY_ERROR) begin
898
                        clk_cmd_ena <= 1'b0;
899
                        cmd_state <= S_CMD_IDLE;
900
                        cmd_counter <= 8'd0;
901
                end
902
        end
903
end
904
 
905
//------------------------------------------------------------------------------ SD clock
906
 
907
reg [1:0] clk_counter;
908
 
909
always @(posedge clk or negedge rst_n) begin
910
        if(rst_n == 1'b0) begin
911
                sd_clk      <= 1'b0;
912
                clk_counter <= 2'd0;
913
        end
914
        else if(clk_counter == 2'd0) begin
915
                if(clk_master_ena == 1'b1 && (clk_cmd_ena == 1'b1 || clk_data_ena == 1'b1)) begin
916
                        clk_counter <= clk_counter + 2'd1;
917
                end
918
        end
919
        else if(clk_counter == 2'd1) begin
920
                sd_clk      <= 1'b1;
921
                clk_counter <= clk_counter + 2'd1;
922
        end
923
        else if(clk_counter == 2'd2) begin
924
            clk_counter <= clk_counter + 2'd1;
925
        end
926
        else if(clk_counter == 2'd3) begin
927
                sd_clk      <= 1'b0;
928
                clk_counter <= clk_counter + 2'd1;
929
        end
930
end
931
 
932
endmodule
933
 

powered by: WebSVN 2.1.0

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