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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [soc/] [driver_sd/] [card_init.v] - Rev 8

Compare with Previous | Blame | View Log

/*
 * This file is subject to the terms and conditions of the BSD License. See
 * the file "LICENSE" in the main directory of this archive for more details.
 *
 * Copyright (C) 2014 Aleksander Osman
 */
 
module card_init(
    input               clk,
    input               rst_n,
 
    //
    input               operation_init,
    output              operation_finished_ok,
    output              operation_finished_with_error,
 
    //
    output              cmd_ready,
    output      [5:0]   cmd_index,
    output      [31:0]  cmd_arg,
    output      [7:0]   cmd_resp_length,
    output              cmd_resp_has_crc7,
 
    input               reply_ready,
    input       [135:0] reply_contents,
    input               reply_error,
 
    //
    input               current_dat0
);
 
//------------------------------------------------------------------------------
 
reg [23:0] initial_delay;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)                   initial_delay <= 24'd0;
    else if(initial_delay[23] == 1'b0)  initial_delay <= initial_delay + 24'd1;
end
 
assign operation_finished_with_error = 
    (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)) ||
    (state == S_CMD0         && reply_ready && ~(valid_cmd0))  ||
    (state == S_CMD8         && reply_ready && ~(valid_cmd8))  ||
    (state == S_CMD55_FOR_41 && reply_ready && ~(valid_cmd55)) ||
    (state == S_ACMD41       && reply_ready && ~(valid_acmd41) && ~(valid_acmd41_but_busy)) ||
    (state == S_CMD2         && reply_ready && ~(valid_cmd2)) ||
    (state == S_CMD3         && reply_ready && ~(valid_cmd3)) ||
    (state == S_CMD7         && reply_ready && ~(valid_cmd7) && ~(valid_cmd7_but_busy)) ||
    (state == S_CMD55_FOR_6  && reply_ready && ~(valid_cmd55)) ||
    (state == S_ACMD6        && reply_ready && ~(valid_acmd6));
 
assign operation_finished_ok = state == S_ACMD6 && reply_ready && valid_acmd6;
 
//------------------------------------------------------------------------------
 
wire prepare_cmd0           = state == S_IDLE && initial_delay[23] && operation_init;
wire valid_cmd0             = 1'b1; //always valid
 
wire prepare_cmd8           = state == S_CMD0 && reply_ready && valid_cmd0;
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
 
wire prepare_cmd55_for_41   = (state == S_CMD8 && reply_ready && valid_cmd8) || repeat_acmd41;
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
 
wire prepare_acmd41         = state == S_CMD55_FOR_41 && reply_ready && valid_cmd55;
wire valid_acmd41           = reply_contents[39:38] == 2'b11;                            //initialization complete and SDHC or SDXC;
wire valid_acmd41_but_busy  = reply_contents[39] == 1'b0 && acmd41_busy_cnt < 20'hFFFFF; //initialization not complete
wire repeat_acmd41          = state == S_ACMD41 && reply_ready && valid_acmd41_but_busy;
 
wire prepare_cmd2           = state == S_ACMD41 && reply_ready && valid_acmd41;
wire valid_cmd2             = 1'b1; //always valid
 
wire prepare_cmd3           = state == S_CMD2 && reply_ready && valid_cmd2;
wire valid_cmd3             = reply_contents[45:40] == 6'd3 && reply_contents[23:21] == 3'b0; //command index; R1[23,22,19] no errors
wire [15:0] cmd3_new_rca    = reply_contents[39:24];
 
wire prepare_cmd7           = state == S_CMD3 && reply_ready && valid_cmd3;
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
wire valid_cmd7             = valid_cmd7_common && current_dat0; 
wire valid_cmd7_but_busy    = valid_cmd7_common && ~(current_dat0);
 
wire prepare_cmd55_for_6    = (state == S_CMD7 && reply_ready && valid_cmd7) || (state == S_WAIT_DAT0 && current_dat0);
 
wire prepare_acmd6          = state == S_CMD55_FOR_6 && reply_ready && valid_cmd55;
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
 
//------------------------------------------------------------------------------
 
reg [19:0] acmd41_busy_cnt;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)       acmd41_busy_cnt <= 20'd0;
    else if(prepare_cmd0)   acmd41_busy_cnt <= 20'd0;
    else if(repeat_acmd41)  acmd41_busy_cnt <= acmd41_busy_cnt + 20'd1;
end
 
reg [15:0] rca;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)       rca <= 16'd0;
    else if(prepare_cmd7)   rca <= cmd3_new_rca;
end
 
//------------------------------------------------------------------------------
 
localparam [3:0] S_IDLE         = 4'd0;
localparam [3:0] S_CMD0         = 4'd1;
localparam [3:0] S_CMD8         = 4'd2;
localparam [3:0] S_CMD55_FOR_41 = 4'd3;
localparam [3:0] S_ACMD41       = 4'd4;
localparam [3:0] S_CMD2         = 4'd5;
localparam [3:0] S_CMD3         = 4'd6;
localparam [3:0] S_CMD7         = 4'd7;
localparam [3:0] S_WAIT_DAT0    = 4'd8;
localparam [3:0] S_CMD55_FOR_6  = 4'd9;
localparam [3:0] S_ACMD6        = 4'd10;
 
reg [3:0] state;
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)                                               state <= S_IDLE;
 
    else if(operation_finished_with_error)                          state <= S_IDLE;
 
    else if(prepare_cmd0)                                           state <= S_CMD0;
    else if(prepare_cmd8)                                           state <= S_CMD8;
    else if(prepare_cmd55_for_41)                                   state <= S_CMD55_FOR_41;
    else if(prepare_acmd41)                                         state <= S_ACMD41;
    else if(repeat_acmd41)                                          state <= S_CMD55_FOR_41;
    else if(prepare_cmd2)                                           state <= S_CMD2;
    else if(prepare_cmd3)                                           state <= S_CMD3;
    else if(prepare_cmd7)                                           state <= S_CMD7;
    else if(state == S_CMD7 && reply_ready && valid_cmd7_but_busy)  state <= S_WAIT_DAT0;
    else if(prepare_cmd55_for_6)                                    state <= S_CMD55_FOR_6;
    else if(prepare_acmd6)                                          state <= S_ACMD6;
 
    else if(operation_finished_ok)                                  state <= S_IDLE;
end
 
//------------------------------------------------------------------------------
 
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;
 
assign cmd_index =
    (prepare_cmd0)?         6'd0 :
    (prepare_cmd8)?         6'd8 :
    (prepare_cmd55_for_41)? 6'd55 :
    (prepare_acmd41)?       6'd41 :
    (prepare_cmd2)?         6'd2 :
    (prepare_cmd3)?         6'd3 :
    (prepare_cmd7)?         6'd7 :
    (prepare_cmd55_for_6)?  6'd55 :
    (prepare_acmd6)?        6'd6 :
                            6'd0;
 
assign cmd_arg =
    (prepare_cmd0)?         32'd0 :             //stuff bits
 
    (prepare_cmd8)?         { 20'b0,            //reserved
                              4'b0001,          //VHS voltage supplied 2.7-3.6 V
                              8'b11010010 } :   //check pattern;
 
    (prepare_cmd55_for_41)? { 16'd0,            //RCA
                              16'd0 } :         //stuff bits
 
    (prepare_acmd41)?       { 1'b0,                   //busy
                              1'b1,                   //Host Capacity Support (1=SDHC or SDXC)
                              1'b0,                   //reserved FB(0)
                              1'b0,                   //SDXC Power Control (0=power saving)
                              3'b0,                   //reserved
                              1'b0,                   //switching to 1.8V request
                              16'b0011000000000000,   //voltage window field OCR[23:08]: 3.2-3.3 and 3.3-3.4
                              8'b0 } :                //reseved;
 
    (prepare_cmd2)?         32'd0 :             //stuff bits
 
    (prepare_cmd3)?         32'd0 :             //stuff bits
 
    (prepare_cmd7)?         { cmd3_new_rca,     //RCA
                              16'd0 } :         //stuff bits
 
    (prepare_cmd55_for_6)?  { rca,              //RCA
                              16'd0 } :         //stuff bits
 
    (prepare_acmd6)?        { 30'd0,            //stuff bits
                              2'b10 } :         //4 bit bus
 
                            32'd0;
 
assign cmd_resp_length =
    (prepare_cmd0)?         8'd0 :
    (prepare_cmd8)?         8'd48 :  //R7
    (prepare_cmd55_for_41)? 8'd48 :  //R1
    (prepare_acmd41)?       8'd48 :  //R3 OCR
    (prepare_cmd2)?         8'd136 : //R2
    (prepare_cmd3)?         8'd48 :  //R6
    (prepare_cmd7)?         8'd48 :  //R1b
    (prepare_cmd55_for_6)?  8'd48 :  //R1
    (prepare_acmd6)?        8'd48 :  //R1
                            8'd0;
 
assign cmd_resp_has_crc7 =
    (prepare_cmd0)?         1'b0 :
    (prepare_cmd8)?         1'b1 :
    (prepare_cmd55_for_41)? 1'b1 :
    (prepare_acmd41)?       1'b0 :
    (prepare_cmd2)?         1'b1 :
    (prepare_cmd3)?         1'b1 :
    (prepare_cmd7)?         1'b1 :
    (prepare_cmd55_for_6)?  1'b1 :
    (prepare_acmd6)?        1'b1 :
                            1'b1;
 
//------------------------------------------------------------------------------
// synthesis translate_off
wire _unused_ok = &{ 1'b0, reply_contents[135:46], reply_contents[20], reply_contents[7:0], 1'b0 };
// synthesis translate_on
//------------------------------------------------------------------------------
 
endmodule
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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