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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [soc/] [driver_sd/] [card_write.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_write(
9
    input               clk,
10
    input               rst_n,
11
 
12
    //
13
    input               operation_write,
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              read_start,
34
    output              read_next,
35
    input       [31:0]  read_data,
36
    input               read_done,
37
 
38
    //
39
    output reg          wr_async_data_ready,
40
    output reg  [31:0]  wr_async_data,
41
    input               wr_data_done,
42
    input               wr_data_last_in_sector,
43
    input               wr_error,
44
    input               wr_finished_sector,
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_CMD25            = 3'd1;
60
localparam [2:0] S_WAIT_FOR_DATA    = 3'd2;
61
localparam [2:0] S_WAIT_FOR_DAT0    = 3'd3;
62
localparam [2:0] S_CMD12            = 3'd4;
63
localparam [2:0] S_FAILED_CMD12     = 3'd5;
64
 
65
wire prepare_cmd25 = state == S_IDLE && operation_write;
66
wire valid_cmd25   = reply_contents[45:40] == 6'd25 && 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_CMD25 && (reply_error || (reply_ready && ~(valid_cmd25)))) || (state == S_WAIT_FOR_DATA && operation_sector_update && wr_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_cmd25)                                              state <= S_CMD25;
83
    else if(state == S_CMD25 && reply_ready && valid_cmd25)             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_cmd25)                                  was_error <= 1'b0;
96
    else if(stop_because_of_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_read;
107
always @(posedge clk or negedge rst_n) begin
108
    if(rst_n == 1'b0)       first_read <= 1'b0;
109
    else if(prepare_cmd25)  first_read <= 1'b1;
110
    else if(read_start)     first_read <= 1'b0;
111
end
112
 
113
reg [3:0] read_cnt;
114
always @(posedge clk or negedge rst_n) begin
115
    if(rst_n == 1'b0)                               read_cnt <= 4'd0;
116
    else if(read_start || read_next)                read_cnt <= 4'd1;
117
    else if(read_done)                              read_cnt <= 4'd0;
118
    else if(read_cnt > 4'd0 && read_cnt < 4'd14)    read_cnt <= read_cnt + 4'd1;
119
end
120
 
121
assign stop_sd_clk = read_cnt == 4'd14;
122
 
123
assign operation_sector_update = wr_finished_sector;
124
 
125
wire read_condition = state == S_WAIT_FOR_DATA && ~(wr_async_data_ready) && read_cnt == 4'd0 && ~(read_finished);
126
assign read_start   = read_condition && first_read;
127
assign read_next    = read_condition && ~(first_read);
128
 
129
reg read_finished;
130
always @(posedge clk or negedge rst_n) begin
131
    if(rst_n == 1'b0)                               read_finished <= 1'b0;
132
    else if(wr_data_done && wr_data_last_in_sector) read_finished <= 1'b1;
133
    else if(operation_sector_update)                read_finished <= 1'b0;
134
end
135
 
136
always @(posedge clk or negedge rst_n) begin
137
    if(rst_n == 1'b0)       wr_async_data_ready <= 1'b0;
138
    else if(wr_data_done)   wr_async_data_ready <= 1'b0;
139
    else if(read_done)      wr_async_data_ready <= 1'b1;
140
end
141
 
142
always @(posedge clk or negedge rst_n) begin
143
    if(rst_n == 1'b0)       wr_async_data <= 32'b0;
144
    else if(read_done)      wr_async_data <= read_data;
145
end
146
 
147
//------------------------------------------------------------------------------
148
 
149
assign cmd_ready = prepare_cmd25 || prepare_cmd12;
150
 
151
assign cmd_index         = (prepare_cmd25)? 6'd25      : 6'd12;
152
assign cmd_arg           = (prepare_cmd25)? sd_address : 32'd0; //cmd25: sector address; cmd12: stuff bits
153
assign cmd_resp_length   = 8'd48;                               //cmd25: R1; cmd12: R1b
154
assign cmd_resp_has_crc7 = 1'b1;
155
 
156
//------------------------------------------------------------------------------
157
 
158
//------------------------------------------------------------------------------
159
// synthesis translate_off
160
wire _unused_ok = &{ 1'b0, reply_contents[135:46], reply_contents[26:25], reply_contents[20:0], 1'b0 };
161
// synthesis translate_on
162
//------------------------------------------------------------------------------
163
 
164
endmodule

powered by: WebSVN 2.1.0

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