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

Subversion Repositories sd_card_controller

[/] [sd_card_controller/] [trunk/] [rtl/] [verilog/] [sd_data_serial_host.v] - 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.v                                        ////
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
//// Module resposible for sending and receiving data through     ////
13
//// 4-bit sd card data interface                                 ////
14
////                                                              ////
15
//// Author(s):                                                   ////
16
////     - Marek Czerski, ma.czerski@gmail.com                    ////
17
////                                                              ////
18
//////////////////////////////////////////////////////////////////////
19
////                                                              ////
20
//// Copyright (C) 2013 Authors                                   ////
21
////                                                              ////
22
//// Based on original work by                                    ////
23
////     Adam Edvardsson (adam.edvardsson@orsoc.se)               ////
24
////                                                              ////
25
////     Copyright (C) 2009 Authors                               ////
26
////                                                              ////
27
//// This source file may be used and distributed without         ////
28
//// restriction provided that this copyright statement is not    ////
29
//// removed from the file and that any derivative work contains  ////
30
//// the original copyright notice and the associated disclaimer. ////
31
////                                                              ////
32
//// This source file is free software; you can redistribute it   ////
33
//// and/or modify it under the terms of the GNU Lesser General   ////
34
//// Public License as published by the Free Software Foundation; ////
35
//// either version 2.1 of the License, or (at your option) any   ////
36
//// later version.                                               ////
37
////                                                              ////
38
//// This source is distributed in the hope that it will be       ////
39
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
40
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
41
//// PURPOSE. See the GNU Lesser General Public License for more  ////
42
//// details.                                                     ////
43
////                                                              ////
44
//// You should have received a copy of the GNU Lesser General    ////
45
//// Public License along with this source; if not, download it   ////
46
//// from http://www.opencores.org/lgpl.shtml                     ////
47
////                                                              ////
48
//////////////////////////////////////////////////////////////////////
49
`include "sd_defines.h"
50
 
51
module sd_data_serial_host(
52
           input sd_clk,
53
           input rst,
54
           //Tx Fifo
55
           input [31:0] data_in,
56
           output reg rd,
57
           //Rx Fifo
58
           output reg [31:0] data_out,
59
           output reg we,
60
           //tristate data
61
           output reg DAT_oe_o,
62
           output reg[3:0] DAT_dat_o,
63
           input [3:0] DAT_dat_i,
64
           //Controll signals
65
           input [`BLKSIZE_W-1:0] blksize,
66
           input bus_4bit,
67
           input [`BLKCNT_W-1:0] blkcnt,
68
           input [1:0] start,
69
           output sd_data_busy,
70
           output busy,
71
           output reg crc_ok
72
       );
73
 
74
reg [3:0] DAT_dat_reg;
75
reg [`BLKSIZE_W-1+3:0] data_cycles;
76
reg bus_4bit_reg;
77
//CRC16
78
reg [3:0] crc_in;
79
reg crc_en;
80
reg crc_rst;
81
wire [15:0] crc_out [3:0];
82
reg [15:0] transf_cnt;
83
parameter SIZE = 6;
84
reg [SIZE-1:0] state;
85
reg [SIZE-1:0] next_state;
86
parameter IDLE       = 6'b000001;
87
parameter WRITE_DAT  = 6'b000010;
88
parameter WRITE_CRC  = 6'b000100;
89
parameter WRITE_BUSY = 6'b001000;
90
parameter READ_WAIT  = 6'b010000;
91
parameter READ_DAT   = 6'b100000;
92
reg [2:0] crc_status;
93
reg busy_int;
94
reg [`BLKCNT_W-1:0] blkcnt_reg;
95
reg next_block;
96
wire start_bit;
97
reg [4:0] crc_c;
98
reg [3:0] last_din;
99
reg [2:0] crc_s ;
100
reg [4:0] data_send_index;
101
 
102
//sd data input pad register
103
always @(posedge sd_clk)
104
    DAT_dat_reg <= DAT_dat_i;
105
 
106
genvar i;
107
generate
108
    for(i=0; i<4; i=i+1) begin: CRC_16_gen
109
        sd_crc_16 CRC_16_i (crc_in[i],crc_en, sd_clk, crc_rst, crc_out[i]);
110
    end
111
endgenerate
112
 
113
assign busy = (state != IDLE);
114
assign start_bit = !DAT_dat_reg[0];
115
assign sd_data_busy = !DAT_dat_reg[0];
116
 
117
always @(state or start or start_bit or  transf_cnt or data_cycles or crc_status or crc_ok or busy_int or next_block)
118
begin: FSM_COMBO
119
    case(state)
120
        IDLE: begin
121
            if (start == 2'b01)
122
                next_state <= WRITE_DAT;
123
            else if  (start == 2'b10)
124
                next_state <= READ_WAIT;
125
            else
126
                next_state <= IDLE;
127
        end
128
        WRITE_DAT: begin
129
            if (transf_cnt >= data_cycles+21 && start_bit)
130
                next_state <= WRITE_CRC;
131
            else if (start == 2'b11)
132
                next_state <= IDLE;
133
            else
134
                next_state <= WRITE_DAT;
135
        end
136
        WRITE_CRC: begin
137
            if (crc_status == 3)
138
                next_state <= WRITE_BUSY;
139
            else
140
                next_state <= WRITE_CRC;
141
        end
142
        WRITE_BUSY: begin
143
            if (!busy_int && next_block && crc_ok)
144
                next_state <= WRITE_DAT;
145
            else if (!busy_int)
146
                next_state <= IDLE;
147
            else
148
                next_state <= WRITE_BUSY;
149
        end
150
        READ_WAIT: begin
151
            if (start_bit)
152
                next_state <= READ_DAT;
153
            else
154
                next_state <= READ_WAIT;
155
        end
156
        READ_DAT: begin
157
            if (transf_cnt == data_cycles+17 && next_block && crc_ok)
158
                next_state <= READ_WAIT;
159
            else if (transf_cnt == data_cycles+17)
160
                next_state <= IDLE;
161
            else if (start == 2'b11)
162
                next_state <= IDLE;
163
            else
164
                next_state <= READ_DAT;
165
        end
166
        default: next_state <= IDLE;
167
    endcase
168
end
169
 
170
always @(posedge sd_clk or posedge rst)
171
begin: FSM_OUT
172
    if (rst) begin
173
        state <= IDLE;
174
        DAT_oe_o <= 0;
175
        crc_en <= 0;
176
        crc_rst <= 1;
177
        transf_cnt <= 0;
178
        crc_c <= 15;
179
        rd <= 0;
180
        last_din <= 0;
181
        crc_c <= 0;
182
        crc_in <= 0;
183
        DAT_dat_o <= 0;
184
        crc_status <= 0;
185
        crc_s <= 0;
186
        we <= 0;
187
        data_out <= 0;
188
        crc_ok <= 0;
189
        busy_int <= 0;
190
        data_send_index <= 0;
191
        next_block <= 0;
192
        blkcnt_reg <= 0;
193
        data_cycles <= 0;
194
        bus_4bit_reg <= 0;
195
    end
196
    else begin
197
        state <= next_state;
198
        case(state)
199
            IDLE: begin
200
                DAT_oe_o <= 0;
201
                DAT_dat_o <= 4'b1111;
202
                crc_en <= 0;
203
                crc_rst <= 1;
204
                transf_cnt <= 0;
205
                crc_c <= 16;
206
                crc_status <= 0;
207
                crc_s <= 0;
208
                we <= 0;
209
                rd <= 0;
210
                data_send_index <= 0;
211
                next_block <= 0;
212
                blkcnt_reg <= blkcnt;
213
                data_cycles <= (bus_4bit ? (blksize << 1) : (blksize << 3));
214
                bus_4bit_reg <= bus_4bit;
215
            end
216
            WRITE_DAT: begin
217
                crc_ok <= 0;
218
                transf_cnt <= transf_cnt + 16'h1;
219
                next_block <= 0;
220
                rd <= 0;
221
                if (transf_cnt == 1) begin
222
                    crc_rst <= 0;
223
                    crc_en <= 1;
224
                    if (bus_4bit_reg) begin
225
                        last_din <= data_in[31:28];
226
                        crc_in <= data_in[31:28];
227
                    end
228
                    else begin
229
                        last_din <= {3'h7, data_in[31]};
230
                        crc_in <= {3'h7, data_in[31]};
231
                    end
232
                    DAT_oe_o <= 1;
233
                    DAT_dat_o <= bus_4bit_reg ? 4'h0 : 4'he;
234
                    data_send_index <= 1;
235
                end
236
                else if ((transf_cnt >= 2) && (transf_cnt <= data_cycles+1)) begin
237
                    DAT_oe_o<=1;
238
                    if (bus_4bit_reg) begin
239
                        last_din <= {
240
                            data_in[31-(data_send_index[2:0]<<2)],
241
                            data_in[30-(data_send_index[2:0]<<2)],
242
                            data_in[29-(data_send_index[2:0]<<2)],
243
                            data_in[28-(data_send_index[2:0]<<2)]
244
                            };
245
                        crc_in <= {
246
                            data_in[31-(data_send_index[2:0]<<2)],
247
                            data_in[30-(data_send_index[2:0]<<2)],
248
                            data_in[29-(data_send_index[2:0]<<2)],
249
                            data_in[28-(data_send_index[2:0]<<2)]
250
                            };
251
                        if (data_send_index[2:0] == 3'h7) begin
252
                            rd <= 1;
253
                            data_send_index <= 0;
254
                        end
255
                        else
256
                            data_send_index<=data_send_index + 5'h1;
257
                    end
258
                    else begin
259
                        last_din <= {3'h7, data_in[31-data_send_index]};
260
                        crc_in <= {3'h7, data_in[31-data_send_index]};
261
                        if (data_send_index == 31) begin
262
                            rd <= 1;
263
                            data_send_index <= 0;
264
                        end
265
                        else
266
                            data_send_index<=data_send_index + 5'h1;
267
                    end
268
                    DAT_dat_o<= last_din;
269
                    if (transf_cnt == data_cycles+1)
270
                        crc_en<=0;
271
                end
272
                else if (transf_cnt > data_cycles+1 & crc_c!=0) begin
273
                    crc_en <= 0;
274
                    crc_c <= crc_c - 5'h1;
275
                    DAT_oe_o <= 1;
276
                    DAT_dat_o[0] <= crc_out[0][crc_c-1];
277
                    if (bus_4bit_reg)
278
                        DAT_dat_o[3:1] <= {crc_out[3][crc_c-1], crc_out[2][crc_c-1], crc_out[1][crc_c-1]};
279
                    else
280
                        DAT_dat_o[3:1] <= {3'h7};
281
                end
282
                else if (transf_cnt == data_cycles+18) begin
283
                    DAT_oe_o <= 1;
284
                    DAT_dat_o <= 4'hf;
285
                end
286
                else if (transf_cnt >= data_cycles+19) begin
287
                    DAT_oe_o <= 0;
288
                end
289
            end
290
            WRITE_CRC: begin
291
                DAT_oe_o <= 0;
292
                if (crc_status < 3)
293
                    crc_s[crc_status] <= DAT_dat_reg[0];
294
                crc_status <= crc_status + 3'h1;
295
                busy_int <= 1;
296
            end
297
            WRITE_BUSY: begin
298
                if (crc_s == 3'b010)
299
                    crc_ok <= 1;
300
                else
301
                    crc_ok <= 0;
302
                busy_int <= !DAT_dat_reg[0];
303
                next_block <= (blkcnt_reg != 0);
304
                if (next_state != WRITE_BUSY) begin
305
                    blkcnt_reg <= blkcnt_reg - `BLKCNT_W'h1;
306
                    crc_rst <= 1;
307
                    crc_c <= 16;
308
                    crc_status <= 0;
309
                end
310
                transf_cnt <= 0;
311
            end
312
            READ_WAIT: begin
313
                DAT_oe_o <= 0;
314
                crc_rst <= 0;
315
                crc_en <= 1;
316
                crc_in <= 0;
317
                crc_c <= 15;// end
318
                next_block <= 0;
319
                transf_cnt <= 0;
320
            end
321
            READ_DAT: begin
322
                if (transf_cnt < data_cycles) begin
323
                    if (bus_4bit_reg) begin
324
                        we <= (transf_cnt[2:0] == 7);
325
                        data_out[31-(transf_cnt[2:0]<<2)] <= DAT_dat_reg[3];
326
                        data_out[30-(transf_cnt[2:0]<<2)] <= DAT_dat_reg[2];
327
                        data_out[29-(transf_cnt[2:0]<<2)] <= DAT_dat_reg[1];
328
                        data_out[28-(transf_cnt[2:0]<<2)] <= DAT_dat_reg[0];
329
                    end
330
                    else begin
331
                        we <= (transf_cnt[4:0] == 31);
332
                        data_out[31-transf_cnt[4:0]] <= DAT_dat_reg[0];
333
                    end
334
                    crc_in <= DAT_dat_reg;
335
                    crc_ok <= 1;
336
                    transf_cnt <= transf_cnt + 16'h1;
337
                end
338
                else if (transf_cnt <= data_cycles+16) begin
339
                    transf_cnt <= transf_cnt + 16'h1;
340
                    crc_en <= 0;
341
                    last_din <= DAT_dat_reg;
342
                    we<=0;
343
                    if (transf_cnt > data_cycles) begin
344
                        crc_c <= crc_c - 5'h1;
345
                        if  (crc_out[0][crc_c] != last_din[0])
346
                            crc_ok <= 0;
347
                        if  (crc_out[1][crc_c] != last_din[1] && bus_4bit_reg)
348
                            crc_ok<=0;
349
                        if  (crc_out[2][crc_c] != last_din[2] && bus_4bit_reg)
350
                            crc_ok <= 0;
351
                        if  (crc_out[3][crc_c] != last_din[3] && bus_4bit_reg)
352
                            crc_ok <= 0;
353
                        if (crc_c == 0) begin
354
                            next_block <= (blkcnt_reg != 0);
355
                            blkcnt_reg <= blkcnt_reg - `BLKCNT_W'h1;
356
                            crc_rst <= 1;
357
                        end
358
                    end
359
                end
360
            end
361
        endcase
362
    end
363
end
364
 
365
endmodule
366
 
367
 
368
 
369
 
370
 

powered by: WebSVN 2.1.0

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