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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [rtl/] [soc/] [driver_sd/] [driver_sd.v] - Diff between revs 2 and 7

Show entire file | Details | Blame | View Log

Rev 2 Rev 7
Line 1... Line 1...
/*
/*
 * Copyright (c) 2014, Aleksander Osman
 * This file is subject to the terms and conditions of the BSD License. See
 * All rights reserved.
 * the file "LICENSE" in the main directory of this archive for more details.
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * Copyright (C) 2014 Aleksander Osman
 * modification, are permitted provided that the following conditions are met:
 
 *
 
 * * Redistributions of source code must retain the above copyright notice, this
 
 *   list of conditions and the following disclaimer.
 
 *
 
 * * Redistributions in binary form must reproduce the above copyright notice,
 
 *   this list of conditions and the following disclaimer in the documentation
 
 *   and/or other materials provided with the distribution.
 
 *
 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 */
 */
 
 
module driver_sd(
module driver_sd(
 
 
    input           clk,
    input           clk,
    input           rst_n,
    input           rst_n,
 
 
 
    //
    input       [1:0]   avs_address,
    input       [1:0]   avs_address,
    output              avs_waitrequest,
 
    input               avs_read,
    input               avs_read,
    output      [31:0]  avs_readdata,
    output      [31:0]  avs_readdata,
    input               avs_write,
    input               avs_write,
    input       [31:0]  avs_writedata,
    input       [31:0]  avs_writedata,
 
 
    output reg  [31:0]  avm_address,
    //
 
    output      [31:0]  avm_address,
    input               avm_waitrequest,
    input               avm_waitrequest,
    output reg          avm_read,
    output              avm_read,
    input       [31:0]  avm_readdata,
    input       [31:0]  avm_readdata,
    input               avm_readdatavalid,
    input               avm_readdatavalid,
    output reg          avm_write,
    output              avm_write,
    output reg  [31:0]  avm_writedata,
    output      [31:0]  avm_writedata,
 
 
 
    //
    output reg      sd_clk,
    output reg      sd_clk,
    inout           sd_cmd,
    inout           sd_cmd,
    inout   [3:0]   sd_dat
    inout   [3:0]   sd_dat
);
);
 
 
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
 
 
//------------------------------------------------------------------------------ Avalon master
 
 
 
reg data_read;
 
reg data_write;
 
reg [31:0] data_part_contents;
 
reg wait_for_readdatavalid;
 
 
 
always @(posedge clk or negedge rst_n) begin
 
        if(rst_n == 1'b0) begin
 
            avm_address             <= 32'd0;
 
                avm_read                <= 1'b0;
 
        avm_write               <= 1'b0;
 
        avm_writedata           <= 32'b0;
 
 
 
                data_read               <= 1'b0;
 
                data_write              <= 1'b0;
 
                data_part_contents      <= 32'd0;
 
        wait_for_readdatavalid  <= 1'b0;
 
        end
 
        else if(data_state == S_DATA_READ_READY_PART && data_read == 1'b0) begin
 
                if(avm_write && avm_waitrequest == 1'b0) begin
 
                        avm_write <= 1'b0;
 
 
 
                        data_read <= 1'b1;
 
                end
 
                else begin
 
                    avm_address   <= avalon_address_base + { 23'b0, part_counter, 2'b0 };
 
            avm_write     <= 1'b1;
 
            avm_writedata <= { data_part[7:0], data_part[15:8], data_part[23:16], data_part[31:24] };
 
                end
 
        end
 
        else if(data_state == S_DATA_WRITE_READY_PART && data_write == 1'b0) begin
 
                if(avm_read && avm_waitrequest == 1'b0) begin
 
            avm_read <= 1'b0;
 
        end
 
        else if(wait_for_readdatavalid && avm_readdatavalid) begin
 
            avm_read <= 1'b0;
 
            wait_for_readdatavalid <= 1'b0;
 
                        data_part_contents <= { avm_readdata[7:0], avm_readdata[15:8], avm_readdata[23:16], avm_readdata[31:24] };
 
 
 
                        data_write <= 1'b1;
 
                end
 
                else begin
 
                    avm_address             <= avalon_address_base + { 23'b0, part_counter, 2'b0 };
 
                        avm_read                <= 1'b1;
 
            wait_for_readdatavalid  <= 1'b1;
 
                end
 
        end
 
        else if(data_state != S_DATA_READ_READY_PART && data_state != S_DATA_WRITE_READY_PART) begin
 
                data_read <= 1'b0;
 
                data_write <= 1'b0;
 
        end
 
end
 
 
 
//------------------------------------------------------------------------------ Avalon slave
 
 
 
//read mutex
 
 
 
assign avs_readdata = (avs_address == 2'd0)? {29'd0, status[2:0]} : { 29'd0, mutex };
 
 
 
reg [2:0] mutex;
 
always @(posedge clk or negedge rst_n) begin
 
    if(rst_n == 1'b0)                                                               mutex <= 3'd0;
 
    else if(mutex == 3'd0 && avs_address == 2'd1 && avs_read && ~(avs_waitrequest)) mutex <= 3'd1;
 
    else if(mutex == 3'd0 && avs_address == 2'd2 && avs_read && ~(avs_waitrequest)) mutex <= 2'd2;
 
    else if(mutex == 3'd0 && avs_address == 2'd3 && avs_read && ~(avs_waitrequest)) mutex <= 3'd3;
 
    else if(mutex < 3'd4 && (status == STATUS_READ || status == STATUS_WRITE))      mutex <= 3'd4;
 
    else if(status == STATUS_IDLE && status_last != STATUS_IDLE)                    mutex <= 3'd0;
 
end
 
 
 
assign avs_waitrequest = control_state == S_CTRL_PRE_IDLE;
 
 
 
// write only
 
reg [31:0] sd_address;
 
reg [31:0] sd_block_count;
 
reg [1:0]  control;
 
reg [31:0] avalon_address_base;
 
 
 
localparam [1:0] CONTROL_IDLE   = 2'd0;
 
localparam [1:0] CONTROL_REINIT = 2'd1;
 
localparam [1:0] CONTROL_READ    = 2'd2;
 
localparam [1:0] CONTROL_WRITE   = 2'd3;
 
 
 
always @(posedge clk or negedge rst_n) begin
 
        if(rst_n == 1'b0) begin
 
                avalon_address_base <= 32'd0;
 
                sd_address          <= 32'd0;
 
                sd_block_count      <= 32'd0;
 
                control             <= 2'd0;
 
        end
 
        else begin
 
                if(control_state == S_CTRL_PRE_IDLE) begin
 
                        sd_block_count      <= sd_block_count - 32'd1;
 
                        sd_address          <= sd_address + 32'd1;
 
                        avalon_address_base <= avalon_address_base + 32'd512;
 
 
 
                        if(sd_block_count == 32'd1) control <= CONTROL_IDLE;
 
                end
 
                else if(avs_write) begin
 
                if(avs_address == 2'd0)         avalon_address_base <= avs_writedata;
 
                else if(avs_address == 2'd1)    sd_address          <= avs_writedata;
 
                else if(avs_address == 2'd2)    sd_block_count      <= avs_writedata;
 
                else if(avs_address == 2'd3)    control             <= avs_writedata[1:0];
 
        end
 
        end
 
 
 
end
 
 
 
//------------------------------------------------------------------------------ Control state machine
 
 
 
reg [3:0]  control_state;
 
reg [15:0] error_count;
 
reg [2:0]  status;
 
reg [37:0] cmd_send_contents;
 
 
 
reg start_cmd;
 
reg start_read;
 
reg start_write;
 
 
 
reg [2:0] status_last;
 
always @(posedge clk or negedge rst_n) begin
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0)   status_last <= STATUS_INIT;
    if(rst_n == 1'b0)                               sd_clk <= 1'b0;
    else                status_last <= status;
    else if(write_stop_sd_clk || read_stop_sd_clk)  sd_clk <= 1'b0;
end
    else                                            sd_clk <= ~(sd_clk);
 
 
`define CRC7_REVERSE crc7[0],crc7[1],crc7[2],crc7[3],crc7[4],crc7[5],crc7[6]
 
 
 
localparam [3:0] S_CTRL_INIT        = 4'd0;
 
localparam [3:0] S_CTRL_CMD0        = 4'd1;
 
localparam [3:0] S_CTRL_CMD8        = 4'd2;
 
localparam [3:0] S_CTRL_CMD55       = 4'd3;
 
localparam [3:0] S_CTRL_ACMD41      = 4'd4;
 
localparam [3:0] S_CTRL_CMD2        = 4'd5;
 
localparam [3:0] S_CTRL_CMD3        = 4'd6;
 
localparam [3:0] S_CTRL_CMD7        = 4'd7;
 
localparam [3:0] S_CTRL_PRE_IDLE    = 4'd8;
 
localparam [3:0] S_CTRL_IDLE        = 4'd9;
 
localparam [3:0] S_CTRL_CMD17_READ  = 4'd10;
 
localparam [3:0] S_CTRL_CMD24_WRITE = 4'd11;
 
 
 
localparam [2:0] STATUS_INIT        = 3'd0;
 
localparam [2:0] STATUS_INIT_ERROR  = 3'd1;
 
localparam [2:0] STATUS_IDLE        = 3'd2;
 
localparam [2:0] STATUS_READ        = 3'd3;
 
localparam [2:0] STATUS_WRITE       = 3'd4;
 
localparam [2:0] STATUS_ERROR       = 3'd5;
 
 
 
always @(posedge clk or negedge rst_n) begin
 
        if(rst_n == 1'b0) begin
 
                control_state <= S_CTRL_INIT;
 
                status <= STATUS_INIT;
 
                cmd_send_contents <= 38'd0;
 
                start_cmd <= 1'b0;
 
                start_read <= 1'b0;
 
                start_write <= 1'b0;
 
                error_count <= 16'd0;
 
        end
 
        else if(control_state == S_CTRL_INIT && error_count == 16'd65535) begin
 
                status <= STATUS_INIT_ERROR;
 
 
 
                if(control == CONTROL_REINIT) begin
 
                        error_count <= 16'd0;
 
                        control_state <= S_CTRL_INIT;
 
                end
 
        end
 
        else if(control_state == S_CTRL_INIT) begin
 
                status <= STATUS_INIT;
 
 
 
                if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
 
                    start_cmd <= 1'b1;
 
                        //CMD0, no arguments
 
                        cmd_send_contents <= { 6'd0, 32'd0 };
 
                        control_state <= S_CTRL_CMD0;
 
                end
 
        end
 
        else if(control_state == S_CTRL_CMD0) begin
 
 
 
                if(cmd_state == S_CMD_REPLY_ERROR) begin
 
                        error_count <= error_count + 16'd1;
 
                        control_state <= S_CTRL_INIT;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
 
                        start_cmd <= 1'b1;
 
                        //CMD8, supply voltage, check pattern
 
                        cmd_send_contents <= { 6'd8, 20'd0, 4'b0001, 8'b10101010 };
 
                        control_state <= S_CTRL_CMD8;
 
                end
 
                else start_cmd <= 1'b0;
 
        end
 
        else if(control_state == S_CTRL_CMD8) begin
 
                if(start_cmd == 1'b1) begin
 
                        start_cmd <= 1'b0;
 
                end
 
                else if(cmd_state == S_CMD_REPLY_ERROR ||
 
                        (cmd_state == S_CMD_IDLE && cmd_reply != { 1'b0, 1'b0, 6'd8, 20'd0, 4'b0001, 8'b10101010, `CRC7_REVERSE, 1'b1 })
 
                ) begin
 
                        error_count <= error_count + 16'd1;
 
                        control_state <= S_CTRL_INIT;
 
                end
 
                else if(cmd_state == S_CMD_IDLE) begin
 
                        start_cmd <= 1'b1;
 
                        //CMD55, RCA
 
                        cmd_send_contents <= { 6'd55, 16'd0, 16'd0};
 
                        control_state <= S_CTRL_CMD55;
 
                end
 
        end
 
        else if(control_state == S_CTRL_CMD55) begin
 
                if(start_cmd == 1'b1) begin
 
                        start_cmd <= 1'b0;
 
                end
 
                else if(cmd_state == S_CMD_REPLY_ERROR ||
 
                        (cmd_state == S_CMD_IDLE &&
 
                                (cmd_reply[47:40] != { 1'b0, 1'b0, 6'd55 } || cmd_reply[39:27] != 13'b0 || cmd_reply[24:21] != 4'b0 ||
 
                                 cmd_reply[13] != 1'b1 || cmd_reply[11] != 1'b0 || cmd_reply[7:0] != { `CRC7_REVERSE, 1'b1 }
 
                                )
 
                        )
 
                ) begin
 
                        error_count <= error_count + 16'd1;
 
                        control_state <= S_CTRL_INIT;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
 
                        start_cmd <= 1'b1;
 
                        //ACMD41, 
 
                        cmd_send_contents <= {  6'd41,                                                          //command index
 
                                                                        1'b0,                                                           //reserved bit
 
                                                                        1'b1,                                                           //host capacity support HCS(OCR[30])
 
                                                                        6'b0,                                                           //reserved bits
 
                                                                        24'b0001_0000_0000_0000_0000_0000       //VDD voltage window OCR[23:0]
 
                        };
 
                        control_state <= S_CTRL_ACMD41;
 
                end
 
        end
 
        else if(control_state == S_CTRL_ACMD41) begin
 
                if(start_cmd == 1'b1) begin
 
                        start_cmd <= 1'b0;
 
                end
 
                else if(cmd_state == S_CMD_REPLY_ERROR ||
 
                        (cmd_state == S_CMD_IDLE && (cmd_reply[47:40] != { 1'b0, 1'b0, 6'b111111 } ||
 
                                cmd_reply[39:38] != 2'b11 || cmd_reply[7:0] != {7'b1111111, 1'b1 })
 
                        )
 
                ) begin
 
                        if(error_count == 16'd65535) begin
 
                                control_state <= S_CTRL_INIT;
 
                        end
 
                        else begin
 
                                error_count <= error_count + 16'd1;
 
                                start_cmd <= 1'b1;
 
                                //CMD55, RCA
 
                                cmd_send_contents <= { 6'd55, 16'd0, 16'd0};
 
                                control_state <= S_CTRL_CMD55;
 
                        end
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
 
                        start_cmd <= 1'b1;
 
                        //CMD2, no arguments
 
                        cmd_send_contents <= { 6'd2, 32'd0 };
 
                        control_state <= S_CTRL_CMD2;
 
                end
 
        end
 
        else if(control_state == S_CTRL_CMD2) begin
 
                if(start_cmd == 1'b1) begin
 
                        start_cmd <= 1'b0;
 
                end
 
                else if(cmd_state == S_CMD_REPLY_ERROR ||
 
                        (cmd_state == S_CMD_IDLE && cmd_reply[0] != 1'b1)
 
                ) begin
 
                        error_count <= error_count + 16'd1;
 
                        control_state <= S_CTRL_INIT;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
 
                        start_cmd <= 1'b1;
 
                        //CMD3, no arguments
 
                        cmd_send_contents <= { 6'd3, 32'd0 };
 
                        control_state <= S_CTRL_CMD3;
 
                end
 
        end
 
        else if(control_state == S_CTRL_CMD3) begin
 
                if(start_cmd == 1'b1) begin
 
                        start_cmd <= 1'b0;
 
                end
 
                else if(cmd_state == S_CMD_REPLY_ERROR ||
 
                        (cmd_state == S_CMD_IDLE &&
 
                                (cmd_reply[47:40] != { 1'b0, 1'b0, 6'd3 } ||
 
                                 /*23:8= 23,22,19,12:0 from card status*/
 
                                 cmd_reply[23:21] != 3'b0 || cmd_reply[13] != 1'b0 || cmd_reply[11] != 1'b0 ||
 
                                 cmd_reply[7:0] != { `CRC7_REVERSE, 1'b1 }
 
                                )
 
                        )
 
                ) begin
 
                        error_count <= error_count + 16'd1;
 
                        control_state <= S_CTRL_INIT;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
 
 
 
                        start_cmd <= 1'b1;
 
                        //CMD7, no arguments
 
                        cmd_send_contents <= {  6'd7,                           //command index
 
                                                                        cmd_reply[39:24],       //RCA
 
                                                                        16'd0                           //stuff bits
 
                        };
 
                        control_state <= S_CTRL_CMD7;
 
                end
 
        end
 
        else if(control_state == S_CTRL_CMD7) begin
 
                if(start_cmd == 1'b1) begin
 
                        start_cmd <= 1'b0;
 
                end
 
                else if(cmd_state == S_CMD_REPLY_ERROR ||
 
                        (cmd_state == S_CMD_IDLE &&
 
                                (cmd_reply[47:40] != { 1'b0, 1'b0, 6'd7 } || cmd_reply[39:27] != 13'b0 || cmd_reply[24:21] != 4'b0 ||
 
                                 cmd_reply[13] != 1'b0 || cmd_reply[11] != 1'b0 || cmd_reply[7:0] != { `CRC7_REVERSE, 1'b1 }
 
                                )
 
                        )
 
                ) begin
 
                        error_count <= error_count + 16'd1;
 
                        control_state <= S_CTRL_INIT;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0) begin
 
                        start_cmd <= 1'b0;
 
 
 
                        error_count <= 16'd0;
 
                        control_state <= S_CTRL_IDLE;
 
                end
 
        end
 
        else if(control_state == S_CTRL_PRE_IDLE) begin
 
                control_state <= S_CTRL_IDLE;
 
        end
 
        else if(control_state == S_CTRL_IDLE && error_count != 16'd0) begin
 
                status <= STATUS_ERROR;
 
 
 
                if(control == CONTROL_IDLE) begin
 
                        control_state <= S_CTRL_IDLE;
 
                        error_count <= 16'd0;
 
                end
 
                else if(control == CONTROL_REINIT) begin
 
                        control_state <= S_CTRL_INIT;
 
                        error_count <= 16'd0;
 
                end
 
        end
 
        else if(control_state == S_CTRL_IDLE) begin
 
                if(control == CONTROL_READ && sd_block_count != 32'd0) begin
 
                        status <= STATUS_READ;
 
                        start_cmd <= 1'b1;
 
                        start_read <= 1'b1;
 
                        //CMD17, sector address
 
                        cmd_send_contents <= {  6'd17,                          //command index
 
                                                                        sd_address[31:0] //sector address
 
                        };
 
                        control_state <= S_CTRL_CMD17_READ;
 
                end
 
                else if(control == CONTROL_WRITE && sd_block_count != 32'd0) begin
 
                        status <= STATUS_WRITE;
 
                        start_cmd <= 1'b1;
 
                        start_write <= 1'b1;
 
                        //CMD24, sector address
 
                        cmd_send_contents <= {  6'd24,                          //command index
 
                                                                        sd_address[31:0]         //sector address
 
                        };
 
                        control_state <= S_CTRL_CMD24_WRITE;
 
                end
 
                else begin
 
                        status <= STATUS_IDLE;
 
                end
 
        end
 
        else if(control_state == S_CTRL_CMD17_READ) begin
 
                if(start_cmd == 1'b1) begin
 
                        start_cmd <= 1'b0;
 
                end
 
                else if(cmd_state == S_CMD_REPLY_ERROR ||
 
                        (cmd_state == S_CMD_IDLE &&
 
                                (cmd_reply[47:40] != { 1'b0, 1'b0, 6'd17 } || cmd_reply[39:27] != 13'b0 || cmd_reply[24:21] != 4'b0 ||
 
                                 cmd_reply[13] != 1'b0 || cmd_reply[11] != 1'b0 || cmd_reply[7:0] != { `CRC7_REVERSE, 1'b1 }
 
                                )
 
                        )
 
                ) begin
 
                        error_count <= error_count + 16'd1;
 
                        control_state <= S_CTRL_IDLE;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_read == 1'b1) begin
 
                        start_read <= 1'b0;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_read == 1'b0 && data_state == S_DATA_READ_ERROR) begin
 
                        error_count <= error_count + 16'd1;
 
                        control_state <= S_CTRL_IDLE;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_read == 1'b0 && data_state == S_DATA_IDLE) begin
 
                        error_count <= 16'd0;
 
                        control_state <= S_CTRL_PRE_IDLE;
 
                end
 
        end
 
        else if(control_state == S_CTRL_CMD24_WRITE) begin
 
                if(start_cmd == 1'b1) begin
 
                        start_cmd <= 1'b0;
 
                end
 
                else if(cmd_state == S_CMD_REPLY_ERROR ||
 
                        (cmd_state == S_CMD_IDLE &&
 
                                (cmd_reply[47:40] != { 1'b0, 1'b0, 6'd24 } || cmd_reply[39:27] != 13'b0 || cmd_reply[24:21] != 4'b0 ||
 
                                 cmd_reply[13] != 1'b0 || cmd_reply[11] != 1'b0 || cmd_reply[7:0] != { `CRC7_REVERSE, 1'b1 }
 
                                )
 
                        )
 
                ) begin
 
                        error_count <= error_count + 16'd1;
 
                        control_state <= S_CTRL_IDLE;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_write == 1'b1) begin
 
                        start_write <= 1'b0;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_write == 1'b0 && data_state == S_DATA_WRITE_ERROR) begin
 
                        error_count <= error_count + 16'd1;
 
                        control_state <= S_CTRL_IDLE;
 
                end
 
                else if(cmd_state == S_CMD_IDLE && start_cmd == 1'b0 && start_write == 1'b0 && data_state == S_DATA_IDLE) begin
 
                        error_count <= 16'd0;
 
                        control_state <= S_CTRL_PRE_IDLE;
 
                end
 
        end
 
end
end
 
 
//------------------------------------------------------------------------------ SD interface
//------------------------------------------------------------------------------
 
 
reg sd_cmd_reg = 1'b1;
wire current_dat0;
reg sd_dat_reg = 1'b1;
 
 
 
assign sd_cmd = (sd_cmd_enable == 1'b1) ?  sd_cmd_reg : 1'bZ;
wire wr_data_done;
assign sd_dat[0] = (sd_data_enable == 1'b1) ? sd_dat_reg : 1'bZ;
wire wr_data_last_in_sector;
 
wire wr_error;
 
wire wr_finished_sector;
 
 
 
wire        rd_data_done;
 
wire        rd_data_last_in_sector;
 
wire [31:0] rd_data;
 
wire        rd_error;
 
 
 
dat dat_inst(
 
    .clk                    (clk),
 
    .rst_n                  (rst_n),
 
 
 
    //
 
    .sd_clk_is_one          (sd_clk),                   //input
 
 
 
    //
 
    .wr_async_data_ready    (wr_async_data_ready),      //input
 
    .wr_async_data          (wr_async_data),            //input [31:0]
 
    .wr_data_done           (wr_data_done),             //output
 
    .wr_data_last_in_sector (wr_data_last_in_sector),   //output
 
    .wr_error               (wr_error),                 //output
 
    .wr_finished_sector     (wr_finished_sector),       //output
 
 
 
    //
 
    .rd_async_start         (rd_async_start),           //input
 
    .rd_async_abort         (rd_async_abort),           //input
 
    .rd_data_done           (rd_data_done),             //output
 
    .rd_data_last_in_sector (rd_data_last_in_sector),   //output
 
    .rd_data                (rd_data),                  //output [31:0]
 
    .rd_error               (rd_error),                 //output
 
 
assign sd_dat[3:1] = 3'bZ;
    //
 
    .current_dat0           (current_dat0),             //output
//CID register not interpreted: CRC7 not checked, always accepted
 
 
 
//---------------------------------------------------- SD data
 
 
 
reg         sd_data_enable;
 
reg [3:0]   data_state;
 
reg [23:0]  data_counter;
 
reg [6:0]   part_counter;
 
reg [15:0]  crc16;
 
reg [31:0]  data_part;
 
 
 
reg         clk_data_ena;
 
reg         clk_master_ena;
 
 
 
 
 
localparam [3:0] S_DATA_IDLE                                                             = 4'd0;
 
localparam [3:0] S_DATA_READ_START_BIT                                           = 4'd1;
 
localparam [3:0] S_DATA_READ_CONTENTS                                            = 4'd2;
 
localparam [3:0] S_DATA_READ_READY_PART                                          = 4'd3;
 
localparam [3:0] S_DATA_READ_READY_PART_CONTINUE                         = 4'd4;
 
localparam [3:0] S_DATA_READ_CRC16_END_BIT                                       = 4'd5;
 
localparam [3:0] S_DATA_READ_ERROR                                                       = 4'd6;
 
localparam [3:0] S_DATA_WRITE_START_BIT                                          = 4'd7;
 
localparam [3:0] S_DATA_WRITE_READY_PART                                         = 4'd8;
 
localparam [3:0] S_DATA_WRITE_CONTENTS                                           = 4'd9;
 
localparam [3:0] S_DATA_WRITE_CRC16_END_BIT                                      = 4'd10;
 
localparam [3:0] S_DATA_WRITE_CRC_STATUS_START                           = 4'd11;
 
localparam [3:0] S_DATA_WRITE_CRC_STATUS_CONTENTS_END_BIT        = 4'd12;
 
localparam [3:0] S_DATA_WRITE_BUSY_START                                         = 4'd13;
 
localparam [3:0] S_DATA_WRITE_BUSY_WAIT                                          = 4'd14;
 
localparam [3:0] S_DATA_WRITE_ERROR                                                      = 4'd15;
 
 
 
 
    //
 
    .sd_dat                 (sd_dat)                    //inout [3:0]
 
);
 
 
always @(posedge clk or negedge rst_n) begin
//------------------------------------------------------------------------------
        if(rst_n == 1'b0) begin
 
                sd_data_enable  <= 1'b0;
 
                data_state              <= S_DATA_IDLE;
 
                data_counter    <= 24'd0;
 
                part_counter    <= 7'd0;
 
                crc16                   <= 16'd0;
 
                data_part               <= 32'd0;
 
                clk_data_ena    <= 1'b0;
 
                clk_master_ena  <= 1'b1;
 
                sd_dat_reg              <= 1'b1;
 
        end
 
        else if(data_state == S_DATA_IDLE) begin
 
                //do not wait for read command and reply
 
                if(start_read == 1'b1) begin
 
                        data_state <= S_DATA_READ_START_BIT;
 
                end
 
                //wait for write command and reply
 
                else if(start_write == 1'b1 && start_cmd == 1'b0 && cmd_state == S_CMD_IDLE) begin
 
                        data_state <= S_DATA_WRITE_START_BIT;
 
                end
 
        end
 
        else if(clk_counter == 2'd0) begin
 
 
 
                //wait for response and data simultaneously (data read)
wire         reply_ready;
                if(data_state == S_DATA_READ_START_BIT) begin
wire [135:0] reply_contents;
                        clk_data_ena <= 1'b1;
wire         reply_error;
 
 
                        if(sd_dat[0] == 1'b0) begin
wire        cmd_ready         = (operation_write)? write_cmd_ready         : (operation_read)? read_cmd_ready         : (operation_init)? init_cmd_ready         : 1'b0;
                                crc16 <= { sd_dat[0] ^ crc16[0], crc16[15:12], sd_dat[0] ^ crc16[11] ^ crc16[0], crc16[10:5],
wire [5:0]  cmd_index         = (operation_write)? write_cmd_index         : (operation_read)? read_cmd_index         : (operation_init)? init_cmd_index         : 6'b0;
                                        sd_dat[0] ^ crc16[4] ^ crc16[0], crc16[3:1] };
wire [31:0] cmd_arg           = (operation_write)? write_cmd_arg           : (operation_read)? read_cmd_arg           : (operation_init)? init_cmd_arg           : 32'b0;
 
wire [7:0]  cmd_resp_length   = (operation_write)? write_cmd_resp_length   : (operation_read)? read_cmd_resp_length   : (operation_init)? init_cmd_resp_length   : 8'b0;
 
wire        cmd_resp_has_crc7 = (operation_write)? write_cmd_resp_has_crc7 : (operation_read)? read_cmd_resp_has_crc7 : (operation_init)? init_cmd_resp_has_crc7 : 1'b0;
 
 
 
cmd cmd_inst(
 
    .clk                (clk),
 
    .rst_n              (rst_n),
 
 
 
    //
 
    .sd_clk_is_one      (sd_clk),               //input
 
 
 
    //
 
    .cmd_ready          (cmd_ready),            //input
 
    .cmd_index          (cmd_index),            //input [5:0]
 
    .cmd_arg            (cmd_arg),              //input [31:0]
 
    .cmd_resp_length    (cmd_resp_length),      //input [7:0]
 
    .cmd_resp_has_crc7  (cmd_resp_has_crc7),    //input
 
 
 
    //
 
    .reply_ready        (reply_ready),          //output
 
    .reply_contents     (reply_contents),       //output [135:0]
 
    .reply_error        (reply_error),          //output
 
 
                                data_state <= S_DATA_READ_CONTENTS;
    //
                                data_counter <= 24'd0;
    .sd_cmd             (sd_cmd)                //inout
                        end
);
                        else if(data_counter == 24'd65535) begin
 
                                data_state <= S_DATA_READ_ERROR;
 
                                data_counter <= 24'd0;
 
                        end
 
                        else data_counter <= data_counter + 24'd1;
 
                end
 
                else if(data_state == S_DATA_READ_CONTENTS) begin
 
                        crc16 <= { sd_dat[0] ^ crc16[0], crc16[15:12], sd_dat[0] ^ crc16[11] ^ crc16[0],
 
                                crc16[10:5], sd_dat[0] ^ crc16[4] ^ crc16[0], crc16[3:1] };
 
                        data_part <= { data_part[30:0], sd_dat[0] };
 
 
 
                        if(data_counter == 24'd30) begin
 
                                clk_master_ena <= 1'b0;
 
                                data_counter <= data_counter + 24'd1;
 
                        end
 
                        else if(data_counter == 24'd31) begin
 
                                data_state <= S_DATA_READ_READY_PART;
 
                                data_counter <= 24'd0;
 
                        end
 
                        else data_counter <= data_counter + 24'd1;
 
                end
 
                else if(data_state == S_DATA_READ_READY_PART) begin
 
                        if(data_read == 1'b1) begin
 
                                clk_master_ena <= 1'b1;
 
                                data_state <= S_DATA_READ_READY_PART_CONTINUE;
 
                        end
 
                end
 
                else if(data_state == S_DATA_READ_READY_PART_CONTINUE) begin
 
                        if(part_counter == 7'd127) begin
 
                                data_state <= S_DATA_READ_CRC16_END_BIT;
 
                                part_counter <= 7'd0;
 
                        end
 
                        else begin
 
                                data_state <= S_DATA_READ_CONTENTS;
 
                                part_counter <= part_counter + 7'd1;
 
                        end
 
                end
 
                else if(data_state == S_DATA_READ_CRC16_END_BIT) begin
 
                        data_part <= { sd_dat[0], data_part[31:1] };
 
 
 
                        if(data_counter == 24'd16) begin
//------------------------------------------------------------------------------
                                if(data_part[31:16] != crc16[15:0] || sd_dat[0] != 1'b1) begin
 
                                        data_state <= S_DATA_READ_ERROR;
 
                                        data_counter <= 24'd0;
 
                                end
 
                                else begin
 
                                        clk_data_ena <= 1'b0;
 
                                        data_state <= S_DATA_IDLE;
 
                                        data_counter <= 24'd0;
 
                                        crc16 <= 16'd0;
 
                                end
 
                        end
 
                        else data_counter <= data_counter + 24'd1;
 
                end
 
                else if(data_state == S_DATA_READ_ERROR) begin
 
                        clk_data_ena <= 1'b0;
 
                        data_state <= S_DATA_IDLE;
 
                        data_counter <= 24'd0;
 
                        crc16 <= 16'd0;
 
                end
 
 
 
                //send data on data line, wait for crc status, wait while busy on data line (data write)
wire [31:0] read_data;
                else if(data_state == S_DATA_WRITE_START_BIT) begin
wire        read_done;
                        sd_dat_reg <= 1'b0;
 
                        crc16 <= { 1'b0 ^ crc16[0], crc16[15:12], 1'b0 ^ crc16[11] ^ crc16[0], crc16[10:5],
 
                                1'b0 ^ crc16[4] ^ crc16[0], crc16[3:1] };
 
 
 
                        sd_data_enable <= 1'b1;
 
                        clk_data_ena <= 1'b1;
 
                        data_counter <= 24'd0;
 
                        data_state <= S_DATA_WRITE_READY_PART;
 
                end
 
                else if(data_state == S_DATA_WRITE_READY_PART) begin
 
 
 
                        if(data_write == 1'b1) begin
wire        write_done;
                            clk_data_ena <= 1'b1;
 
                                data_state <= S_DATA_WRITE_CONTENTS;
 
                                data_part <= data_part_contents;
 
                        end
 
                        else begin
 
                            clk_data_ena <= 1'b0;
 
                        end
 
                end
 
                else if(data_state == S_DATA_WRITE_CONTENTS) begin
 
                        sd_dat_reg <= data_part[31];
 
                        crc16 <= { data_part[31] ^ crc16[0], crc16[15:12], data_part[31] ^ crc16[11] ^ crc16[0], crc16[10:5],
 
                                data_part[31] ^ crc16[4] ^ crc16[0], crc16[3:1] };
 
                        data_part <= { data_part[30:0], 1'b0 };
 
 
 
                        if(data_counter == 24'd31) begin
 
                                data_counter <= 24'd0;
 
 
 
                                if(part_counter == 7'd127) begin
 
                                        part_counter <= 7'd0;
 
                                        data_state <= S_DATA_WRITE_CRC16_END_BIT;
 
                                end
 
                                else begin
 
                                    clk_data_ena <= 1'b0;
 
                                        part_counter <= part_counter + 7'd1;
 
                                        data_state <= S_DATA_WRITE_READY_PART;
 
                                end
 
                        end
 
                        else data_counter <= data_counter + 24'd1;
 
                end
 
 
 
                else if(data_state == S_DATA_WRITE_CRC16_END_BIT) begin
avalon_master avalon_master_inst(
                        sd_dat_reg <= crc16[0];
    .clk                    (clk),
 
    .rst_n                  (rst_n),
 
 
 
    //
 
    .avm_address            (avm_address),          //output [31:0]
 
    .avm_waitrequest        (avm_waitrequest),      //input
 
    .avm_read               (avm_read),             //output
 
    .avm_readdata           (avm_readdata),         //input [31:0]
 
    .avm_readdatavalid      (avm_readdatavalid),    //input
 
    .avm_write              (avm_write),            //output
 
    .avm_writedata          (avm_writedata),        //output [31:0]
 
 
 
    //
 
    .avalon_address_base    (avalon_address_base),  //input [31:0]
 
 
 
    //
 
    .read_start             (read_start),           //input
 
    .read_next              (read_next),            //input
 
    .read_data              (read_data),            //output [31:0]
 
    .read_done              (read_done),            //output
 
 
 
    //
 
    .write_start            (write_start),          //input
 
    .write_next             (write_next),           //input
 
    .write_data             (write_data),           //input [31:0]
 
    .write_done             (write_done)            //output
 
);
 
 
                        if(data_counter == 24'd16) begin
//------------------------------------------------------------------------------
                            data_counter <= 24'd0;
 
                            crc16 <= 16'd0;
 
                                data_state <= S_DATA_WRITE_CRC_STATUS_START;
 
                        end
 
                        else begin
 
                                crc16 <= { 1'b1, crc16[15:1] };
 
                                data_counter <= data_counter + 24'd1;
 
                        end
 
 
 
                end
wire operation_write;
                else if(data_state == S_DATA_WRITE_CRC_STATUS_START) begin
wire operation_read;
                        sd_data_enable <= 1'b0;
wire operation_init;
 
 
 
wire operation_sector_last;
 
 
 
wire [31:0] sd_address;
 
wire [31:0] avalon_address_base;
 
 
 
wire operation_sector_update       = (operation_write && write_operation_sector_update)       || (operation_read && read_operation_sector_update);
 
wire operation_finished_ok         = (operation_write && write_operation_finished_ok)         || (operation_read && read_operation_finished_ok)         || (operation_init && init_operation_finished_ok);
 
wire operation_finished_with_error = (operation_write && write_operation_finished_with_error) || (operation_read && read_operation_finished_with_error) || (operation_init && init_operation_finished_with_error);
 
 
 
avalon_slave avalon_slave_inst(
 
    .clk                            (clk),
 
    .rst_n                          (rst_n),
 
 
 
    //
 
    .avs_address                    (avs_address),                      //input [1:0]
 
    .avs_read                       (avs_read),                         //input
 
    .avs_readdata                   (avs_readdata),                     //output [31:0]
 
    .avs_write                      (avs_write),                        //input
 
    .avs_writedata                  (avs_writedata),                    //input [31:0]
 
 
 
    //
 
    .operation_init                 (operation_init),                   //output
 
    .operation_read                 (operation_read),                   //output
 
    .operation_write                (operation_write),                  //output
 
 
 
    .operation_sector_update        (operation_sector_update),          //input
 
    .operation_sector_last          (operation_sector_last),            //output
 
 
 
    .operation_finished_ok          (operation_finished_ok),            //input
 
    .operation_finished_with_error  (operation_finished_with_error),    //input
 
 
 
    //
 
    .sd_address                     (sd_address),                       //output [31:0]
 
    .avalon_address_base            (avalon_address_base)               //output [31:0]
 
);
 
 
                        if(sd_dat[0] == 1'b0) begin
//------------------------------------------------------------------------------
                                data_state <= S_DATA_WRITE_CRC_STATUS_CONTENTS_END_BIT;
 
                                data_counter <= 24'b0;
 
                        end
 
                        else if(data_counter == 24'd65535) begin
 
                                data_state <= S_DATA_WRITE_ERROR;
 
                                data_counter <= 24'b0;
 
                        end
 
                        else data_counter <= data_counter + 24'd1;
 
                end
 
 
 
                else if(data_state == S_DATA_WRITE_CRC_STATUS_CONTENTS_END_BIT) begin
wire init_operation_finished_ok;
                        data_part <= { data_part[30:0], sd_dat[0] };
wire init_operation_finished_with_error;
 
 
                        if(data_counter == 24'd3) begin
wire        init_cmd_ready;
                                data_state <= S_DATA_WRITE_BUSY_START;
wire [5:0]  init_cmd_index;
                                data_counter <= 24'b0;
wire [31:0] init_cmd_arg;
                        end
wire [7:0]  init_cmd_resp_length;
                        else data_counter <= data_counter + 24'd1;
wire        init_cmd_resp_has_crc7;
                end
 
                else if(data_state == S_DATA_WRITE_BUSY_START) begin
card_init card_init_inst(
 
    .clk                            (clk),
 
    .rst_n                          (rst_n),
 
 
 
    //
 
    .operation_init                 (operation_init),                       //input
 
    .operation_finished_ok          (init_operation_finished_ok),           //output
 
    .operation_finished_with_error  (init_operation_finished_with_error),   //output
 
 
 
    //
 
    .cmd_ready                      (init_cmd_ready),                       //output
 
    .cmd_index                      (init_cmd_index),                       //output [5:0]
 
    .cmd_arg                        (init_cmd_arg),                         //output [31:0]
 
    .cmd_resp_length                (init_cmd_resp_length),                 //output [7:0]
 
    .cmd_resp_has_crc7              (init_cmd_resp_has_crc7),               //output
 
 
 
    .reply_ready                    (reply_ready),                          //input
 
    .reply_contents                 (reply_contents),                       //input [135:0]
 
    .reply_error                    (reply_error),                          //input
 
 
                        if(sd_dat[0] == 1'b0) begin
    //
                                data_state <= S_DATA_WRITE_BUSY_WAIT;
    .current_dat0                   (current_dat0)                          //input
                                data_counter <= 24'b0;
);
                        end
 
                        else if(data_counter == 24'd65535) begin
 
                                data_state <= S_DATA_WRITE_ERROR;
 
                                data_counter <= 24'b0;
 
                        end
 
                        else data_counter <= data_counter + 24'd1;
 
                end
 
                else if(data_state == S_DATA_WRITE_BUSY_WAIT) begin
 
                        if(sd_dat[0] == 1'b1 && data_part[3:0] != 4'b0101) begin
 
                                data_state <= S_DATA_WRITE_ERROR;
 
                                data_counter <= 24'd0;
 
                        end
 
                        else if(sd_dat[0] == 1'b1) begin
 
                                clk_data_ena <= 1'b0;
 
                                data_state <= S_DATA_IDLE;
 
                                data_counter <= 24'd0;
 
                        end
 
                        else if(data_counter == 24'hFFFFFF) begin
 
                                data_state <= S_DATA_WRITE_ERROR;
 
                                data_counter <= 24'd0;
 
                        end
 
                        else data_counter <= data_counter + 24'd1;
 
                end
 
                else if(data_state == S_DATA_WRITE_ERROR) begin
 
                        clk_data_ena <= 1'b0;
 
                        data_state <= S_DATA_IDLE;
 
                        data_counter <= 24'd0;
 
                end
 
        end
 
end
 
 
 
//------------------------------------------------------------------------------ SD command
 
 
 
reg             sd_cmd_enable;
 
reg [37:0]       cmd_send;
 
reg [47:0]       cmd_reply;
 
reg [3:0]        cmd_state;
 
reg [7:0]        cmd_counter;
 
reg [6:0]        crc7;
 
reg             clk_cmd_ena;
 
 
 
localparam [3:0] S_CMD_IDLE                                      = 4'd0;
 
localparam [3:0] S_CMD_SEND_START_ONES           = 4'd1;
 
localparam [3:0] S_CMD_SEND_START_BIT            = 4'd2;
 
localparam [3:0] S_CMD_SEND_START_HOST           = 4'd3;
 
localparam [3:0] S_CMD_SEND_CONTENTS             = 4'd4;
 
localparam [3:0] S_CMD_SEND_CRC7                         = 4'd5;
 
localparam [3:0] S_CMD_SEND_END_BIT                      = 4'd6;
 
localparam [3:0] S_CMD_SEND_END_ONES             = 4'd7;
 
localparam [3:0] S_CMD_REPLY_START_BIT           = 4'd8;
 
localparam [3:0] S_CMD_REPLY_CONTENTS            = 4'd9;
 
localparam [3:0] S_CMD_REPLY_CRC7_END_BIT        = 4'd10;
 
localparam [3:0] S_CMD_REPLY_FINISH_ONES         = 4'd11;
 
localparam [3:0] S_CMD_REPLY_ERROR                       = 4'd12;
 
 
 
always @(posedge clk or negedge rst_n) begin
//------------------------------------------------------------------------------
        if(rst_n == 1'b0) begin
 
                sd_cmd_enable   <= 1'b0;
 
                cmd_send                <= 38'd0;
 
                cmd_reply               <= 48'd0;
 
                cmd_state               <= S_CMD_IDLE;
 
                cmd_counter     <= 8'd0;
 
                crc7                    <= 7'd0;
 
                clk_cmd_ena     <= 1'b0;
 
                sd_cmd_reg              <= 1'b1;
 
        end
 
        else if(cmd_state == S_CMD_IDLE) begin
 
                if(start_cmd == 1'b1) begin
 
                        cmd_state <= S_CMD_SEND_START_ONES;
 
                end
 
        end
 
        else if(clk_counter == 2'd0 && clk_master_ena == 1'b1) begin
 
 
 
                //send command
wire read_operation_sector_update;
                if(cmd_state == S_CMD_SEND_START_ONES) begin
wire read_operation_finished_ok;
                        sd_cmd_enable <= 1'b1;
wire read_operation_finished_with_error;
                        sd_cmd_reg <= 1'b1;
 
                        clk_cmd_ena <= 1'b1;
wire rd_async_start;
                        crc7 <= 7'd0;
wire rd_async_abort;
 
 
                        if(cmd_counter == 8'd7) begin
wire read_stop_sd_clk;
                                cmd_state <= S_CMD_SEND_START_BIT;
 
                                cmd_counter <= 8'd0;
wire        read_cmd_ready;
                        end
wire [5:0]  read_cmd_index;
                        else cmd_counter <= cmd_counter + 8'd1;
wire [31:0] read_cmd_arg;
                end
wire [7:0]  read_cmd_resp_length;
                else if(cmd_state == S_CMD_SEND_START_BIT) begin
wire        read_cmd_resp_has_crc7;
                        sd_cmd_reg <= 1'b0;
 
                        crc7 <= { 1'b0 ^ crc7[0], crc7[6:5], 1'b0 ^ crc7[4] ^ crc7[0], crc7[3:1] };
wire        write_start;
 
wire        write_next;
 
wire [31:0] write_data;
 
 
 
card_read card_read_inst(
 
    .clk                            (clk),
 
    .rst_n                          (rst_n),
 
 
 
    //
 
    .operation_read                 (operation_read),                       //input
 
 
 
    .operation_sector_last          (operation_sector_last),                //input
 
    .operation_sector_update        (read_operation_sector_update),         //output
 
 
 
    .operation_finished_ok          (read_operation_finished_ok),           //output
 
    .operation_finished_with_error  (read_operation_finished_with_error),   //output
 
 
 
    //
 
    .cmd_ready                      (read_cmd_ready),                       //output
 
    .cmd_index                      (read_cmd_index),                       //output [5:0]
 
    .cmd_arg                        (read_cmd_arg),                         //output [31:0]
 
    .cmd_resp_length                (read_cmd_resp_length),                 //output [7:0]
 
    .cmd_resp_has_crc7              (read_cmd_resp_has_crc7),               //output
 
 
 
    .reply_ready                    (reply_ready),                          //input
 
    .reply_contents                 (reply_contents),                       //input [135:0]
 
    .reply_error                    (reply_error),                          //input
 
 
 
    //
 
    .write_start                    (write_start),                          //output
 
    .write_next                     (write_next),                           //output
 
    .write_data                     (write_data),                           //output [31:0]
 
    .write_done                     (write_done),                           //input
 
 
 
    //
 
    .rd_async_start                 (rd_async_start),                       //output
 
    .rd_async_abort                 (rd_async_abort),                       //output
 
    .rd_data_done                   (rd_data_done),                         //input
 
    .rd_data_last_in_sector         (rd_data_last_in_sector),               //input
 
    .rd_data                        (rd_data),                              //input [31:0]
 
    .rd_error                       (rd_error),                             //input
 
 
                        cmd_state <= S_CMD_SEND_START_HOST;
    //
                end
    .sd_address                     (sd_address),                           //input [31:0]
                else if(cmd_state == S_CMD_SEND_START_HOST) begin
 
                        sd_cmd_reg <= 1'b1;
 
                        crc7 <= { 1'b1 ^ crc7[0], crc7[6:5], 1'b1 ^ crc7[4] ^ crc7[0], crc7[3:1] };
 
 
 
                        cmd_send <= cmd_send_contents;
    //
                        cmd_state <= S_CMD_SEND_CONTENTS;
    .current_dat0                   (current_dat0),                         //input
                end
 
                else if(cmd_state == S_CMD_SEND_CONTENTS) begin
 
                        sd_cmd_reg <= cmd_send[37];
 
                        crc7 <= { cmd_send[37] ^ crc7[0], crc7[6:5], cmd_send[37] ^ crc7[4] ^ crc7[0], crc7[3:1] };
 
                        cmd_send <= { cmd_send[36:0], 1'b0 };
 
 
 
                        if(cmd_counter == 8'd37) begin
 
                                cmd_state <= S_CMD_SEND_CRC7;
 
                                cmd_counter <= 8'd0;
 
                        end
 
                        else cmd_counter <= cmd_counter + 8'd1;
 
                end
 
                else if(cmd_state == S_CMD_SEND_CRC7) begin
 
                        sd_cmd_reg <= crc7[0];
 
                        crc7 <= { 1'b0, crc7[6:1] };
 
 
 
                        if(cmd_counter == 8'd6) begin
 
                                cmd_state <= S_CMD_SEND_END_BIT;
 
                                cmd_counter <= 8'd0;
 
                        end
 
                        else cmd_counter <= cmd_counter + 8'd1;
 
                end
 
                else if(cmd_state == S_CMD_SEND_END_BIT) begin
 
                        sd_cmd_reg <= 1'b1;
 
 
 
                        // if CMD0: send ones
    //
                        if(control_state == S_CTRL_CMD0) begin
    .stop_sd_clk                    (read_stop_sd_clk)                      //output
                                cmd_state <= S_CMD_SEND_END_ONES;
);
                        end
 
                        else begin
 
                                crc7 <= 7'd0;
 
                                cmd_state <= S_CMD_REPLY_START_BIT;
 
                        end
 
                end
 
                else if(cmd_state == S_CMD_SEND_END_ONES) begin
 
                        sd_cmd_enable <= 1'b0;
 
                        sd_cmd_reg <= 1'b1;
 
 
 
                        if(cmd_counter == 8'd7) begin
 
                                clk_cmd_ena <= 1'b0;
 
                                cmd_state <= S_CMD_IDLE;
 
                                cmd_counter <= 8'd0;
 
                        end
 
                        else cmd_counter <= cmd_counter + 8'd1;
 
                end
 
 
 
                //wait for response: 48-bits with CRC7
//------------------------------------------------------------------------------
                //wait for response: 48-bits without CRC7
 
                //wait for response: 136-bits (CMD2/R2)
 
                //wait for response and busy on data line simultaneously: (CMD7/R1b)
 
                else if(cmd_state == S_CMD_REPLY_START_BIT) begin
 
                        sd_cmd_enable <= 1'b0;
 
 
 
                        if(sd_cmd == 1'b0) begin
 
                                crc7 <= { sd_cmd ^ crc7[0], crc7[6:5], sd_cmd ^ crc7[4] ^ crc7[0], crc7[3:1] };
 
                                cmd_reply <= { cmd_reply[46:0], sd_cmd };
 
 
 
                                cmd_state <= S_CMD_REPLY_CONTENTS;
wire write_operation_sector_update;
                                cmd_counter <= 8'd0;
wire write_operation_finished_ok;
                        end
wire write_operation_finished_with_error;
                        else if(cmd_counter == 8'd255) begin
 
                                crc7 <= 7'd0;
wire read_start;
                                cmd_state <= S_CMD_REPLY_ERROR;
wire read_next;
                                cmd_counter <= 8'd0;
 
                        end
wire write_stop_sd_clk;
                        else cmd_counter <= cmd_counter + 8'd1;
 
                end
wire        write_cmd_ready;
                else if(cmd_state == S_CMD_REPLY_CONTENTS) begin
wire [5:0]  write_cmd_index;
                        crc7 <= { sd_cmd ^ crc7[0], crc7[6:5], sd_cmd ^ crc7[4] ^ crc7[0], crc7[3:1] };
wire [31:0] write_cmd_arg;
                        cmd_reply <= { cmd_reply[46:0], sd_cmd };
wire [7:0]  write_cmd_resp_length;
 
wire        write_cmd_resp_has_crc7;
                        if(     (control_state != S_CTRL_CMD2 && cmd_counter == 8'd38) ||
 
                                (control_state == S_CTRL_CMD2 && cmd_counter == 8'd126)
wire        wr_async_data_ready;
                        ) begin
wire [31:0] wr_async_data;
                                cmd_state <= S_CMD_REPLY_CRC7_END_BIT;
 
                                cmd_counter <= 8'd0;
card_write card_write_inst(
                        end
    .clk                            (clk),
                        else cmd_counter <= cmd_counter + 8'd1;
    .rst_n                          (rst_n),
                end
 
                else if(cmd_state == S_CMD_REPLY_CRC7_END_BIT) begin
    //
                        cmd_reply <= { cmd_reply[46:0], sd_cmd };
    .operation_write                (operation_write),                      //input
 
 
 
    .operation_sector_last          (operation_sector_last),                //input
 
    .operation_sector_update        (write_operation_sector_update),        //output
 
 
 
    .operation_finished_ok          (write_operation_finished_ok),          //output
 
    .operation_finished_with_error  (write_operation_finished_with_error),  //output
 
 
 
    //
 
    .cmd_ready                      (write_cmd_ready),                      //output
 
    .cmd_index                      (write_cmd_index),                      //output [5:0]
 
    .cmd_arg                        (write_cmd_arg),                        //output [31:0]
 
    .cmd_resp_length                (write_cmd_resp_length),                //output [7:0]
 
    .cmd_resp_has_crc7              (write_cmd_resp_has_crc7),              //output
 
 
 
    .reply_ready                    (reply_ready),                          //input
 
    .reply_contents                 (reply_contents),                       //input [135:0]
 
    .reply_error                    (reply_error),                          //input
 
 
 
    //
 
    .read_start                     (read_start),                           //output
 
    .read_next                      (read_next),                            //output
 
    .read_data                      (read_data),                            //input [31:0]
 
    .read_done                      (read_done),                            //input
 
 
 
    //
 
    .wr_async_data_ready            (wr_async_data_ready),                  //output
 
    .wr_async_data                  (wr_async_data),                        //output [31:0]
 
    .wr_data_done                   (wr_data_done),                         //input
 
    .wr_data_last_in_sector         (wr_data_last_in_sector),               //input
 
    .wr_error                       (wr_error),                             //input
 
    .wr_finished_sector             (wr_finished_sector),                   //input
 
 
                        if(cmd_counter == 8'd7) begin
    //
                                cmd_state <= S_CMD_REPLY_FINISH_ONES;
    .sd_address                     (sd_address),                           //input [31:0]
                                cmd_counter <= 8'd0;
 
                        end
 
                        else cmd_counter <= cmd_counter + 8'd1;
 
                end
 
                //at least 2 clock cycles required for data write
 
                else if(cmd_state == S_CMD_REPLY_FINISH_ONES) begin
 
                        //check is sd_dat[0] busy for CMD7
 
                        if(cmd_counter >= 8'd7 && (control_state != S_CTRL_CMD7 || sd_dat[0] == 1'b1)) begin
 
                                clk_cmd_ena <= 1'b0;
 
                                cmd_state <= S_CMD_IDLE;
 
                                cmd_counter <= 8'd0;
 
                        end
 
                        else if(cmd_counter == 8'd255) begin
 
                                cmd_state <= S_CMD_REPLY_ERROR;
 
                                cmd_counter <= 8'd0;
 
                        end
 
                        else cmd_counter <= cmd_counter + 8'd1;
 
                end
 
                else if(cmd_state == S_CMD_REPLY_ERROR) begin
 
                        clk_cmd_ena <= 1'b0;
 
                        cmd_state <= S_CMD_IDLE;
 
                        cmd_counter <= 8'd0;
 
                end
 
        end
 
end
 
 
 
//------------------------------------------------------------------------------ SD clock
    //
 
    .current_dat0                   (current_dat0),                         //input
 
 
reg [1:0] clk_counter;
    //
 
    .stop_sd_clk                    (write_stop_sd_clk)                     //output
 
);
 
 
always @(posedge clk or negedge rst_n) begin
//------------------------------------------------------------------------------
        if(rst_n == 1'b0) begin
 
                sd_clk      <= 1'b0;
 
                clk_counter <= 2'd0;
 
        end
 
        else if(clk_counter == 2'd0) begin
 
                if(clk_master_ena == 1'b1 && (clk_cmd_ena == 1'b1 || clk_data_ena == 1'b1)) begin
 
                        clk_counter <= clk_counter + 2'd1;
 
                end
 
        end
 
        else if(clk_counter == 2'd1) begin
 
                sd_clk      <= 1'b1;
 
                clk_counter <= clk_counter + 2'd1;
 
        end
 
        else if(clk_counter == 2'd2) begin
 
            clk_counter <= clk_counter + 2'd1;
 
        end
 
        else if(clk_counter == 2'd3) begin
 
                sd_clk      <= 1'b0;
 
                clk_counter <= clk_counter + 2'd1;
 
        end
 
end
 
 
 
endmodule
endmodule
 
 
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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