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

Subversion Repositories ao486

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 8 alfik
/*
2
 * This file is subject to the terms and conditions of the BSD License. See
3
 * the file "LICENSE" in the main directory of this archive for more details.
4
 *
5
 * Copyright (C) 2014 Aleksander Osman
6
 */
7
 
8
module card_read(
9
    input               clk,
10
    input               rst_n,
11
 
12
    //
13
    input               operation_read,
14
 
15
    input               operation_sector_last,
16
    output              operation_sector_update,
17
 
18
    output              operation_finished_ok,
19
    output              operation_finished_with_error,
20
 
21
    //
22
    output              cmd_ready,
23
    output      [5:0]   cmd_index,
24
    output      [31:0]  cmd_arg,
25
    output      [7:0]   cmd_resp_length,
26
    output              cmd_resp_has_crc7,
27
 
28
    input               reply_ready,
29
    input       [135:0] reply_contents,
30
    input               reply_error,
31
 
32
    //
33
    output              write_start,
34
    output              write_next,
35
    output      [31:0]  write_data,
36
    input               write_done,
37
 
38
    //
39
    output              rd_async_start,
40
    output              rd_async_abort,
41
    input               rd_data_done,
42
    input               rd_data_last_in_sector,
43
    input       [31:0]  rd_data,
44
    input               rd_error,
45
 
46
    //
47
    input       [31:0]  sd_address,
48
 
49
    //
50
    input               current_dat0,
51
 
52
    //
53
    output              stop_sd_clk
54
);
55
 
56
//------------------------------------------------------------------------------
57
 
58
localparam [2:0] S_IDLE             = 3'd0;
59
localparam [2:0] S_CMD18            = 3'd1;
60
localparam [2:0] S_WAIT_FOR_DATA    = 3'd2;
61
localparam [2:0] S_CMD12            = 3'd3;
62
localparam [2:0] S_WAIT_FOR_DAT0    = 3'd4;
63
localparam [2:0] S_FAILED_CMD12     = 3'd5;
64
 
65
wire prepare_cmd18 = state == S_IDLE && operation_read;
66
wire valid_cmd18   = reply_contents[45:40] == 6'd18 && reply_contents[39:27] == 13'd0 && reply_contents[24:21] == 4'b0; //command index; R1[31:19] no errors; R1[16:13] no errors
67
 
68
wire stop_because_of_error = (state == S_CMD18 && (reply_error || (reply_ready && ~(valid_cmd18)))) || ((state == S_CMD18 || state == S_WAIT_FOR_DATA) && rd_error);
69
wire prepare_cmd12         = stop_because_of_error || (operation_sector_update && operation_sector_last);
70
wire valid_cmd12_common    = reply_contents[45:40] == 6'd12 && reply_contents[39:27] == 13'd0 && reply_contents[24:21] == 4'b0; //command index; R1[31:19] no errors; R1[16:13] no errors
71
wire valid_cmd12           = valid_cmd12_common && current_dat0;
72
wire valid_cmd12_but_busy  = valid_cmd12_common && ~(current_dat0);
73
 
74
wire prepare_failed_cmd12  = state == S_CMD12 && (reply_error || (reply_ready && ~(valid_cmd12_common)));
75
 
76
reg [2:0] state;
77
always @(posedge clk or negedge rst_n) begin
78
    if(rst_n == 1'b0)                                                   state <= S_IDLE;
79
 
80
    else if(operation_finished_with_error)                              state <= S_IDLE;
81
 
82
    else if(prepare_cmd18)                                              state <= S_CMD18;
83
    else if(state == S_CMD18 && reply_ready && valid_cmd18)             state <= S_WAIT_FOR_DATA;
84
 
85
    else if(prepare_cmd12)                                              state <= S_CMD12;
86
    else if(state == S_CMD12 && reply_ready && valid_cmd12_but_busy)    state <= S_WAIT_FOR_DAT0;
87
    else if(prepare_failed_cmd12)                                       state <= S_FAILED_CMD12;
88
 
89
    else if(operation_finished_ok)                                      state <= S_IDLE;
90
end
91
 
92
reg was_error;
93
always @(posedge clk or negedge rst_n) begin
94
    if(rst_n == 1'b0)                                                   was_error <= 1'b0;
95
    else if(prepare_cmd18)                                              was_error <= 1'b0;
96
    else if(stop_because_of_error || rd_error || prepare_failed_cmd12)  was_error <= 1'b1;
97
end
98
 
99
wire finishing = (state == S_CMD12 && reply_ready && valid_cmd12) || (state == S_WAIT_FOR_DAT0 && current_dat0) || state == S_FAILED_CMD12;
100
 
101
assign operation_finished_ok         = finishing && ~(was_error);
102
assign operation_finished_with_error = finishing && was_error;
103
 
104
//------------------------------------------------------------------------------
105
 
106
reg first_write;
107
always @(posedge clk or negedge rst_n) begin
108
    if(rst_n == 1'b0)       first_write <= 1'b0;
109
    else if(prepare_cmd18)  first_write <= 1'b1;
110
    else if(write_start)    first_write <= 1'b0;
111
end
112
 
113
reg [3:0] write_cnt;
114
always @(posedge clk or negedge rst_n) begin
115
    if(rst_n == 1'b0)                               write_cnt <= 4'd0;
116
    else if(write_start || write_next)              write_cnt <= 4'd1;
117
    else if(write_done)                             write_cnt <= 4'd0;
118
    else if(write_cnt > 4'd0 && write_cnt < 4'd14)  write_cnt <= write_cnt + 4'd1;
119
end
120
 
121
assign stop_sd_clk = write_cnt == 4'd14;
122
 
123
assign write_start = first_write    && rd_data_done && (state == S_CMD18 || state == S_WAIT_FOR_DATA);
124
assign write_next  = ~(first_write) && rd_data_done && (state == S_CMD18 || state == S_WAIT_FOR_DATA);
125
assign write_data  = rd_data;
126
 
127
assign rd_async_start = prepare_cmd18;
128
assign rd_async_abort = operation_finished_ok || operation_finished_with_error;
129
 
130
assign operation_sector_update = rd_data_done && rd_data_last_in_sector;
131
 
132
//------------------------------------------------------------------------------
133
 
134
assign cmd_ready = prepare_cmd18 || prepare_cmd12;
135
 
136
assign cmd_index         = (prepare_cmd18)? 6'd18      : 6'd12;
137
assign cmd_arg           = (prepare_cmd18)? sd_address : 32'd0; //cmd18: sector address; cmd12: stuff bits
138
assign cmd_resp_length   = 8'd48;                               //cmd18: R1; cmd12: R1b
139
assign cmd_resp_has_crc7 = 1'b1;
140
 
141
//------------------------------------------------------------------------------
142
// synthesis translate_off
143
wire _unused_ok = &{ 1'b0, reply_contents[135:46], reply_contents[26:25], reply_contents[20:0], 1'b0 };
144
// synthesis translate_on
145
//------------------------------------------------------------------------------
146
 
147
endmodule

powered by: WebSVN 2.1.0

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