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_init(
|
9 |
|
|
input clk,
|
10 |
|
|
input rst_n,
|
11 |
|
|
|
12 |
|
|
//
|
13 |
|
|
input operation_init,
|
14 |
|
|
output operation_finished_ok,
|
15 |
|
|
output operation_finished_with_error,
|
16 |
|
|
|
17 |
|
|
//
|
18 |
|
|
output cmd_ready,
|
19 |
|
|
output [5:0] cmd_index,
|
20 |
|
|
output [31:0] cmd_arg,
|
21 |
|
|
output [7:0] cmd_resp_length,
|
22 |
|
|
output cmd_resp_has_crc7,
|
23 |
|
|
|
24 |
|
|
input reply_ready,
|
25 |
|
|
input [135:0] reply_contents,
|
26 |
|
|
input reply_error,
|
27 |
|
|
|
28 |
|
|
//
|
29 |
|
|
input current_dat0
|
30 |
|
|
);
|
31 |
|
|
|
32 |
|
|
//------------------------------------------------------------------------------
|
33 |
|
|
|
34 |
|
|
reg [23:0] initial_delay;
|
35 |
|
|
always @(posedge clk or negedge rst_n) begin
|
36 |
|
|
if(rst_n == 1'b0) initial_delay <= 24'd0;
|
37 |
|
|
else if(initial_delay[23] == 1'b0) initial_delay <= initial_delay + 24'd1;
|
38 |
|
|
end
|
39 |
|
|
|
40 |
|
|
assign operation_finished_with_error =
|
41 |
|
|
(reply_error && (state == S_CMD0 || state == S_CMD8 || state == S_CMD55_FOR_41 || state == S_ACMD41 || state == S_CMD2 || state == S_CMD3 || state == S_CMD7 || state == S_CMD55_FOR_6 || state == S_ACMD6)) ||
|
42 |
|
|
(state == S_CMD0 && reply_ready && ~(valid_cmd0)) ||
|
43 |
|
|
(state == S_CMD8 && reply_ready && ~(valid_cmd8)) ||
|
44 |
|
|
(state == S_CMD55_FOR_41 && reply_ready && ~(valid_cmd55)) ||
|
45 |
|
|
(state == S_ACMD41 && reply_ready && ~(valid_acmd41) && ~(valid_acmd41_but_busy)) ||
|
46 |
|
|
(state == S_CMD2 && reply_ready && ~(valid_cmd2)) ||
|
47 |
|
|
(state == S_CMD3 && reply_ready && ~(valid_cmd3)) ||
|
48 |
|
|
(state == S_CMD7 && reply_ready && ~(valid_cmd7) && ~(valid_cmd7_but_busy)) ||
|
49 |
|
|
(state == S_CMD55_FOR_6 && reply_ready && ~(valid_cmd55)) ||
|
50 |
|
|
(state == S_ACMD6 && reply_ready && ~(valid_acmd6));
|
51 |
|
|
|
52 |
|
|
assign operation_finished_ok = state == S_ACMD6 && reply_ready && valid_acmd6;
|
53 |
|
|
|
54 |
|
|
//------------------------------------------------------------------------------
|
55 |
|
|
|
56 |
|
|
wire prepare_cmd0 = state == S_IDLE && initial_delay[23] && operation_init;
|
57 |
|
|
wire valid_cmd0 = 1'b1; //always valid
|
58 |
|
|
|
59 |
|
|
wire prepare_cmd8 = state == S_CMD0 && reply_ready && valid_cmd0;
|
60 |
|
|
wire valid_cmd8 = reply_contents[45:40] == 6'd8 && reply_contents[19:16] == 4'b0001 && reply_contents[15:8] == 8'b11010010; //command index; accepted volage 2.7-3.6 V; check pattern echo
|
61 |
|
|
|
62 |
|
|
wire prepare_cmd55_for_41 = (state == S_CMD8 && reply_ready && valid_cmd8) || repeat_acmd41;
|
63 |
|
|
wire valid_cmd55 = reply_contents[45:40] == 6'd55 && reply_contents[39:27] == 13'd0 && reply_contents[24:21] == 4'b0; //command index; R1[31:19] no errors; R1[16:13] no errors
|
64 |
|
|
|
65 |
|
|
wire prepare_acmd41 = state == S_CMD55_FOR_41 && reply_ready && valid_cmd55;
|
66 |
|
|
wire valid_acmd41 = reply_contents[39:38] == 2'b11; //initialization complete and SDHC or SDXC;
|
67 |
|
|
wire valid_acmd41_but_busy = reply_contents[39] == 1'b0 && acmd41_busy_cnt < 20'hFFFFF; //initialization not complete
|
68 |
|
|
wire repeat_acmd41 = state == S_ACMD41 && reply_ready && valid_acmd41_but_busy;
|
69 |
|
|
|
70 |
|
|
wire prepare_cmd2 = state == S_ACMD41 && reply_ready && valid_acmd41;
|
71 |
|
|
wire valid_cmd2 = 1'b1; //always valid
|
72 |
|
|
|
73 |
|
|
wire prepare_cmd3 = state == S_CMD2 && reply_ready && valid_cmd2;
|
74 |
|
|
wire valid_cmd3 = reply_contents[45:40] == 6'd3 && reply_contents[23:21] == 3'b0; //command index; R1[23,22,19] no errors
|
75 |
|
|
wire [15:0] cmd3_new_rca = reply_contents[39:24];
|
76 |
|
|
|
77 |
|
|
wire prepare_cmd7 = state == S_CMD3 && reply_ready && valid_cmd3;
|
78 |
|
|
wire valid_cmd7_common = reply_contents[45:40] == 6'd7 && reply_contents[39:27] == 13'd0 && reply_contents[24:21] == 4'b0; //command index; R1[31:19] no errors; R1[16:13] no errors
|
79 |
|
|
wire valid_cmd7 = valid_cmd7_common && current_dat0;
|
80 |
|
|
wire valid_cmd7_but_busy = valid_cmd7_common && ~(current_dat0);
|
81 |
|
|
|
82 |
|
|
wire prepare_cmd55_for_6 = (state == S_CMD7 && reply_ready && valid_cmd7) || (state == S_WAIT_DAT0 && current_dat0);
|
83 |
|
|
|
84 |
|
|
wire prepare_acmd6 = state == S_CMD55_FOR_6 && reply_ready && valid_cmd55;
|
85 |
|
|
wire valid_acmd6 = reply_contents[45:40] == 6'd6 && reply_contents[39:27] == 13'd0 && reply_contents[24:21] == 4'b0; //command index; R1[31:19] no errors; R1[16:13] no errors
|
86 |
|
|
|
87 |
|
|
//------------------------------------------------------------------------------
|
88 |
|
|
|
89 |
|
|
reg [19:0] acmd41_busy_cnt;
|
90 |
|
|
always @(posedge clk or negedge rst_n) begin
|
91 |
|
|
if(rst_n == 1'b0) acmd41_busy_cnt <= 20'd0;
|
92 |
|
|
else if(prepare_cmd0) acmd41_busy_cnt <= 20'd0;
|
93 |
|
|
else if(repeat_acmd41) acmd41_busy_cnt <= acmd41_busy_cnt + 20'd1;
|
94 |
|
|
end
|
95 |
|
|
|
96 |
|
|
reg [15:0] rca;
|
97 |
|
|
always @(posedge clk or negedge rst_n) begin
|
98 |
|
|
if(rst_n == 1'b0) rca <= 16'd0;
|
99 |
|
|
else if(prepare_cmd7) rca <= cmd3_new_rca;
|
100 |
|
|
end
|
101 |
|
|
|
102 |
|
|
//------------------------------------------------------------------------------
|
103 |
|
|
|
104 |
|
|
localparam [3:0] S_IDLE = 4'd0;
|
105 |
|
|
localparam [3:0] S_CMD0 = 4'd1;
|
106 |
|
|
localparam [3:0] S_CMD8 = 4'd2;
|
107 |
|
|
localparam [3:0] S_CMD55_FOR_41 = 4'd3;
|
108 |
|
|
localparam [3:0] S_ACMD41 = 4'd4;
|
109 |
|
|
localparam [3:0] S_CMD2 = 4'd5;
|
110 |
|
|
localparam [3:0] S_CMD3 = 4'd6;
|
111 |
|
|
localparam [3:0] S_CMD7 = 4'd7;
|
112 |
|
|
localparam [3:0] S_WAIT_DAT0 = 4'd8;
|
113 |
|
|
localparam [3:0] S_CMD55_FOR_6 = 4'd9;
|
114 |
|
|
localparam [3:0] S_ACMD6 = 4'd10;
|
115 |
|
|
|
116 |
|
|
reg [3:0] state;
|
117 |
|
|
always @(posedge clk or negedge rst_n) begin
|
118 |
|
|
if(rst_n == 1'b0) state <= S_IDLE;
|
119 |
|
|
|
120 |
|
|
else if(operation_finished_with_error) state <= S_IDLE;
|
121 |
|
|
|
122 |
|
|
else if(prepare_cmd0) state <= S_CMD0;
|
123 |
|
|
else if(prepare_cmd8) state <= S_CMD8;
|
124 |
|
|
else if(prepare_cmd55_for_41) state <= S_CMD55_FOR_41;
|
125 |
|
|
else if(prepare_acmd41) state <= S_ACMD41;
|
126 |
|
|
else if(repeat_acmd41) state <= S_CMD55_FOR_41;
|
127 |
|
|
else if(prepare_cmd2) state <= S_CMD2;
|
128 |
|
|
else if(prepare_cmd3) state <= S_CMD3;
|
129 |
|
|
else if(prepare_cmd7) state <= S_CMD7;
|
130 |
|
|
else if(state == S_CMD7 && reply_ready && valid_cmd7_but_busy) state <= S_WAIT_DAT0;
|
131 |
|
|
else if(prepare_cmd55_for_6) state <= S_CMD55_FOR_6;
|
132 |
|
|
else if(prepare_acmd6) state <= S_ACMD6;
|
133 |
|
|
|
134 |
|
|
else if(operation_finished_ok) state <= S_IDLE;
|
135 |
|
|
end
|
136 |
|
|
|
137 |
|
|
//------------------------------------------------------------------------------
|
138 |
|
|
|
139 |
|
|
assign cmd_ready = prepare_cmd0 || prepare_cmd8 || prepare_cmd55_for_41 || prepare_acmd41 || prepare_cmd2 || prepare_cmd3 || prepare_cmd7 || prepare_cmd55_for_6 || prepare_acmd6;
|
140 |
|
|
|
141 |
|
|
assign cmd_index =
|
142 |
|
|
(prepare_cmd0)? 6'd0 :
|
143 |
|
|
(prepare_cmd8)? 6'd8 :
|
144 |
|
|
(prepare_cmd55_for_41)? 6'd55 :
|
145 |
|
|
(prepare_acmd41)? 6'd41 :
|
146 |
|
|
(prepare_cmd2)? 6'd2 :
|
147 |
|
|
(prepare_cmd3)? 6'd3 :
|
148 |
|
|
(prepare_cmd7)? 6'd7 :
|
149 |
|
|
(prepare_cmd55_for_6)? 6'd55 :
|
150 |
|
|
(prepare_acmd6)? 6'd6 :
|
151 |
|
|
6'd0;
|
152 |
|
|
|
153 |
|
|
assign cmd_arg =
|
154 |
|
|
(prepare_cmd0)? 32'd0 : //stuff bits
|
155 |
|
|
|
156 |
|
|
(prepare_cmd8)? { 20'b0, //reserved
|
157 |
|
|
4'b0001, //VHS voltage supplied 2.7-3.6 V
|
158 |
|
|
8'b11010010 } : //check pattern;
|
159 |
|
|
|
160 |
|
|
(prepare_cmd55_for_41)? { 16'd0, //RCA
|
161 |
|
|
16'd0 } : //stuff bits
|
162 |
|
|
|
163 |
|
|
(prepare_acmd41)? { 1'b0, //busy
|
164 |
|
|
1'b1, //Host Capacity Support (1=SDHC or SDXC)
|
165 |
|
|
1'b0, //reserved FB(0)
|
166 |
|
|
1'b0, //SDXC Power Control (0=power saving)
|
167 |
|
|
3'b0, //reserved
|
168 |
|
|
1'b0, //switching to 1.8V request
|
169 |
|
|
16'b0011000000000000, //voltage window field OCR[23:08]: 3.2-3.3 and 3.3-3.4
|
170 |
|
|
8'b0 } : //reseved;
|
171 |
|
|
|
172 |
|
|
(prepare_cmd2)? 32'd0 : //stuff bits
|
173 |
|
|
|
174 |
|
|
(prepare_cmd3)? 32'd0 : //stuff bits
|
175 |
|
|
|
176 |
|
|
(prepare_cmd7)? { cmd3_new_rca, //RCA
|
177 |
|
|
16'd0 } : //stuff bits
|
178 |
|
|
|
179 |
|
|
(prepare_cmd55_for_6)? { rca, //RCA
|
180 |
|
|
16'd0 } : //stuff bits
|
181 |
|
|
|
182 |
|
|
(prepare_acmd6)? { 30'd0, //stuff bits
|
183 |
|
|
2'b10 } : //4 bit bus
|
184 |
|
|
|
185 |
|
|
32'd0;
|
186 |
|
|
|
187 |
|
|
assign cmd_resp_length =
|
188 |
|
|
(prepare_cmd0)? 8'd0 :
|
189 |
|
|
(prepare_cmd8)? 8'd48 : //R7
|
190 |
|
|
(prepare_cmd55_for_41)? 8'd48 : //R1
|
191 |
|
|
(prepare_acmd41)? 8'd48 : //R3 OCR
|
192 |
|
|
(prepare_cmd2)? 8'd136 : //R2
|
193 |
|
|
(prepare_cmd3)? 8'd48 : //R6
|
194 |
|
|
(prepare_cmd7)? 8'd48 : //R1b
|
195 |
|
|
(prepare_cmd55_for_6)? 8'd48 : //R1
|
196 |
|
|
(prepare_acmd6)? 8'd48 : //R1
|
197 |
|
|
8'd0;
|
198 |
|
|
|
199 |
|
|
assign cmd_resp_has_crc7 =
|
200 |
|
|
(prepare_cmd0)? 1'b0 :
|
201 |
|
|
(prepare_cmd8)? 1'b1 :
|
202 |
|
|
(prepare_cmd55_for_41)? 1'b1 :
|
203 |
|
|
(prepare_acmd41)? 1'b0 :
|
204 |
|
|
(prepare_cmd2)? 1'b1 :
|
205 |
|
|
(prepare_cmd3)? 1'b1 :
|
206 |
|
|
(prepare_cmd7)? 1'b1 :
|
207 |
|
|
(prepare_cmd55_for_6)? 1'b1 :
|
208 |
|
|
(prepare_acmd6)? 1'b1 :
|
209 |
|
|
1'b1;
|
210 |
|
|
|
211 |
|
|
//------------------------------------------------------------------------------
|
212 |
|
|
// synthesis translate_off
|
213 |
|
|
wire _unused_ok = &{ 1'b0, reply_contents[135:46], reply_contents[20], reply_contents[7:0], 1'b0 };
|
214 |
|
|
// synthesis translate_on
|
215 |
|
|
//------------------------------------------------------------------------------
|
216 |
|
|
|
217 |
|
|
endmodule
|