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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [soc/] [driver_sd/] [cmd.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 cmd(
9
    input               clk,
10
    input               rst_n,
11
 
12
    //
13
    input               sd_clk_is_one,
14
 
15
    //
16
    input               cmd_ready,
17
    input       [5:0]   cmd_index,
18
    input       [31:0]  cmd_arg,
19
    input       [7:0]   cmd_resp_length,
20
    input               cmd_resp_has_crc7,
21
 
22
    //
23
    output reg          reply_ready,
24
    output reg  [135:0] reply_contents,
25
    output              reply_error,
26
 
27
    //
28
    inout               sd_cmd
29
);
30
 
31
//------------------------------------------------------------------------------
32
 
33
reg sd_cmd_enable;
34
always @(posedge clk or negedge rst_n) begin
35
    if(rst_n == 1'b0)       sd_cmd_enable <= 1'b0;
36
    else if(sd_clk_is_one)  sd_cmd_enable <= cmd_start || cmd_cnt > 6'd0;
37
end
38
 
39
reg sd_cmd_output;
40
always @(posedge clk or negedge rst_n) begin
41
    if(rst_n == 1'b0)       sd_cmd_output <= 1'b1;
42
    else if(sd_clk_is_one)  sd_cmd_output <= (cmd_start)? 1'b0 : (cmd_cnt <= 6'd8 && cmd_cnt >= 6'd2)? cmd_crc7[0] : cmd_value[38];
43
end
44
 
45
assign sd_cmd = (sd_cmd_enable)? sd_cmd_output : 1'bZ;
46
 
47
reg sd_cmd_input;
48
always @(posedge clk or negedge rst_n) begin
49
    if(rst_n == 1'b0)           sd_cmd_input <= 1'b1;
50
    else if(~(sd_clk_is_one))   sd_cmd_input <= sd_cmd;
51
end
52
 
53
//------------------------------------------------------------------------------
54
 
55
reg [3:0] cmd_start_delay_cnt;
56
always @(posedge clk or negedge rst_n) begin
57
    if(rst_n == 1'b0)                                     cmd_start_delay_cnt <= 4'd0;
58
    else if(reply_ready || reply_error)                   cmd_start_delay_cnt <= 4'd8;
59
    else if(sd_clk_is_one && cmd_start_delay_cnt > 4'd0)  cmd_start_delay_cnt <= cmd_start_delay_cnt - 4'd1;
60
end
61
 
62
reg cmd_start_waiting;
63
always @(posedge clk or negedge rst_n) begin
64
    if(rst_n == 1'b0)                                                       cmd_start_waiting <= 1'b0;
65
    else if(cmd_start)                                                      cmd_start_waiting <= 1'b0;
66
    else if(cmd_ready && (cmd_start_delay_cnt > 4'd0 || ~(sd_clk_is_one)))  cmd_start_waiting <= 1'b1;
67
end
68
 
69
wire cmd_start = sd_clk_is_one && (cmd_ready || cmd_start_waiting) && cmd_start_delay_cnt == 4'd0;
70
 
71
reg [5:0] cmd_cnt;
72
always @(posedge clk or negedge rst_n) begin
73
    if(rst_n == 1'b0)                           cmd_cnt <= 6'd0;
74
    else if(cmd_start)                          cmd_cnt <= 6'd47;
75
    else if(sd_clk_is_one && cmd_cnt > 6'd0)    cmd_cnt <= cmd_cnt - 6'd1;
76
end
77
 
78
reg [38:0] cmd_value;
79
always @(posedge clk or negedge rst_n) begin
80
    if(rst_n == 1'b0)                           cmd_value <= 39'h7FFFFFFFFF;
81
    else if(cmd_ready)                          cmd_value <= { 1'b1, cmd_index, cmd_arg };
82
    else if(sd_clk_is_one && cmd_cnt > 6'd0)    cmd_value <= { cmd_value[37:0], 1'b1 }; //fill with 1 important
83
end
84
 
85
reg [6:0] cmd_crc7;
86
always @(posedge clk or negedge rst_n) begin
87
    if(rst_n == 1'b0)                           cmd_crc7 <= 7'd0;
88
    else if(sd_clk_is_one && cmd_cnt >= 6'd9)   cmd_crc7 <= { cmd_value[38] ^ cmd_crc7[0], cmd_crc7[6:5], cmd_crc7[4] ^ cmd_value[38] ^ cmd_crc7[0], cmd_crc7[3:1] };
89
    else if(sd_clk_is_one)                      cmd_crc7 <= { 1'b0, cmd_crc7[6:1] };
90
end
91
 
92
//------------------------------------------------------------------------------
93
 
94
wire resp_active = sd_clk_is_one && resp_cnt > 8'd0 && cmd_cnt == 6'd0 && ~(cmd_start_waiting) && ((resp_awaiting && sd_cmd_input == 1'b0) || ~(resp_awaiting));
95
 
96
reg [7:0] resp_cnt;
97
always @(posedge clk or negedge rst_n) begin
98
    if(rst_n == 1'b0)       resp_cnt <= 8'd0;
99
    else if(reply_error)    resp_cnt <= 8'd0;
100
    else if(cmd_ready)      resp_cnt <= cmd_resp_length;
101
    else if(resp_active)    resp_cnt <= resp_cnt - 8'd1;
102
end
103
 
104
reg resp_has_crc7;
105
always @(posedge clk or negedge rst_n) begin
106
    if(rst_n == 1'b0)   resp_has_crc7 <= 1'b0;
107
    else if(cmd_ready)  resp_has_crc7 <= cmd_resp_has_crc7;
108
end
109
 
110
reg resp_awaiting;
111
always @(posedge clk or negedge rst_n) begin
112
    if(rst_n == 1'b0)                                               resp_awaiting <= 1'b0;
113
    else if(reply_error)                                            resp_awaiting <= 1'b0;
114
    else if(sd_clk_is_one && cmd_cnt == 6'd1 && resp_cnt > 8'd0)    resp_awaiting <= 1'b1;
115
    else if(sd_clk_is_one && resp_awaiting && sd_cmd_input == 1'b0) resp_awaiting <= 1'b0;
116
end
117
 
118
always @(posedge clk or negedge rst_n) begin
119
    if(rst_n == 1'b0)       reply_contents <= 136'd0;
120
    else if(resp_active)    reply_contents <= { reply_contents[134:0], sd_cmd_input };
121
end
122
 
123
reg [6:0] resp_crc7;
124
always @(posedge clk or negedge rst_n) begin
125
    if(rst_n == 1'b0)                                               resp_crc7 <= 7'd0;
126
    else if(resp_active && resp_cnt >= 8'd9 && resp_cnt <= 8'd128)  resp_crc7 <= { sd_cmd_input ^ resp_crc7[0], resp_crc7[6:5], resp_crc7[4] ^ sd_cmd_input ^ resp_crc7[0], resp_crc7[3:1] };
127
    else if(resp_active)                                            resp_crc7 <= { 1'b0, resp_crc7[6:1] };
128
end
129
 
130
//------------------------------------------------------------------------------
131
 
132
reg resp_next_is_trans_bit;
133
always @(posedge clk or negedge rst_n) begin
134
    if(rst_n == 1'b0)                       resp_next_is_trans_bit <= 1'b0;
135
    else if(resp_active && resp_awaiting)   resp_next_is_trans_bit <= 1'b1;
136
    else if(resp_active)                    resp_next_is_trans_bit <= 1'b0;
137
end
138
 
139
wire resp_now_in_error = resp_active && (
140
    (resp_next_is_trans_bit && sd_cmd_input == 1'b1) ||                                     //transmission bit is '1'
141
    (resp_cnt == 8'd1 && sd_cmd_input == 1'b0) ||                                           //end bit is '0'
142
    (resp_cnt <= 8'd8 && resp_cnt >= 8'd2 && resp_has_crc7 && sd_cmd_input != resp_crc7[0]) //crc7 invalid
143
);
144
 
145
reg resp_had_error;
146
always @(posedge clk or negedge rst_n) begin
147
    if(rst_n == 1'b0)           resp_had_error <= 1'b0;
148
    else if(reply_error)        resp_had_error <= 1'b0;
149
    else if(resp_now_in_error)  resp_had_error <= 1'b1;
150
end
151
 
152
always @(posedge clk or negedge rst_n) begin
153
    if(rst_n == 1'b0)   reply_ready <= 1'b0;
154
    else                reply_ready <= (sd_clk_is_one && cmd_cnt == 6'd1 && resp_cnt == 8'd0) || (resp_active && resp_cnt == 8'd1 && ~(resp_now_in_error || resp_had_error));
155
end
156
 
157
//------------------------------------------------------------------------------
158
 
159
wire error_start = (sd_clk_is_one && cmd_cnt == 6'd1 && resp_cnt > 8'd0) || (resp_active && resp_cnt == 8'd1 && (resp_now_in_error || resp_had_error));
160
 
161
reg [6:0] error_delay_cnt;
162
always @(posedge clk or negedge rst_n) begin
163
    if(rst_n == 1'b0)                                               error_delay_cnt <= 7'd0;
164
    else if(sd_clk_is_one && resp_awaiting && sd_cmd_input == 1'b0) error_delay_cnt <= 7'd0;
165
    else if(error_start)                                            error_delay_cnt <= 7'd1;
166
    else if(sd_clk_is_one && error_delay_cnt > 7'd0)                error_delay_cnt <= error_delay_cnt + 7'd1;
167
end
168
 
169
assign reply_error = error_delay_cnt == 7'd127;
170
 
171
//------------------------------------------------------------------------------
172
 
173
endmodule

powered by: WebSVN 2.1.0

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