////////////////////////////////////////////////////////////////////// //// //// //// WISHBONE SD Card Controller IP Core //// //// //// //// sd_data_master.v //// //// //// //// This file is part of the WISHBONE SD Card //// //// Controller IP Core project //// //// http://opencores.org/project,sd_card_controller //// //// //// //// Description //// //// State machine resposible for controlling data transfers //// //// on 4-bit sd card data interface //// //// //// //// Author(s): //// //// - Marek Czerski, ma.czerski@gmail.com //// //// //// ////////////////////////////////////////////////////////////////////// //// //// //// Copyright (C) 2013 Authors //// //// //// //// Based on original work by //// //// Adam Edvardsson (adam.edvardsson@orsoc.se) //// //// //// //// Copyright (C) 2009 Authors //// //// //// //// This source file may be used and distributed without //// //// restriction provided that this copyright statement is not //// //// removed from the file and that any derivative work contains //// //// the original copyright notice and the associated disclaimer. //// //// //// //// This source file is free software; you can redistribute it //// //// and/or modify it under the terms of the GNU Lesser General //// //// Public License as published by the Free Software Foundation; //// //// either version 2.1 of the License, or (at your option) any //// //// later version. //// //// //// //// This source is distributed in the hope that it will be //// //// useful, but WITHOUT ANY WARRANTY; without even the implied //// //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// //// PURPOSE. See the GNU Lesser General Public License for more //// //// details. //// //// //// //// You should have received a copy of the GNU Lesser General //// //// Public License along with this source; if not, download it //// //// from http://www.opencores.org/lgpl.shtml //// //// //// ////////////////////////////////////////////////////////////////////// `include "sd_defines.v" module sd_data_master ( input sd_clk, input rst, input start_tx_i, input start_rx_i, //Output to SD-Host Reg output reg d_write_o, output reg d_read_o, //To fifo filler output reg start_tx_fifo_o, output reg start_rx_fifo_o, input tx_fifo_empty_i, input tx_fifo_full_i, input rx_fifo_full_i, //SD-DATA_Host input xfr_complete_i, input crc_ok_i, //status output output reg [`INT_DATA_SIZE-1:0] int_status_o, input int_status_rst_i ); reg tx_cycle; parameter SIZE = 3; reg [SIZE-1:0] state; reg [SIZE-1:0] next_state; parameter IDLE = 3'b000; parameter START_TX_FIFO = 3'b001; parameter START_RX_FIFO = 3'b010; parameter DATA_TRANSFER = 3'b100; reg trans_done; always @(state or start_tx_i or start_rx_i or tx_fifo_full_i or xfr_complete_i or trans_done) begin: FSM_COMBO case(state) IDLE: begin if (start_tx_i == 1) begin next_state <= START_TX_FIFO; end else if (start_rx_i == 1) begin next_state <= START_RX_FIFO; end else begin next_state <= IDLE; end end START_TX_FIFO: begin if (tx_fifo_full_i == 1 && xfr_complete_i == 0) next_state <= DATA_TRANSFER; else next_state <= START_TX_FIFO; end START_RX_FIFO: begin if (xfr_complete_i == 0) next_state <= DATA_TRANSFER; else next_state <= START_RX_FIFO; end DATA_TRANSFER: begin if (trans_done) next_state <= IDLE; else next_state <= DATA_TRANSFER; end default: next_state <= IDLE; endcase end //----------------Seq logic------------ always @(posedge sd_clk or posedge rst) begin: FSM_SEQ if (rst) begin state <= IDLE; end else begin state <= next_state; end end //Output logic----------------- always @(posedge sd_clk or posedge rst) begin if (rst) begin start_tx_fifo_o <= 0; start_rx_fifo_o <= 0; d_write_o <= 0; d_read_o <= 0; trans_done <= 0; tx_cycle <= 0; int_status_o <= 0; end else begin case(state) IDLE: begin start_tx_fifo_o <= 0; start_rx_fifo_o <= 0; d_write_o <= 0; d_read_o <= 0; trans_done <= 0; tx_cycle <= 0; end START_RX_FIFO: begin start_rx_fifo_o <= 1; start_tx_fifo_o <= 0; tx_cycle <= 0; d_read_o <= 1; end START_TX_FIFO: begin start_rx_fifo_o <= 0; start_tx_fifo_o <= 1; tx_cycle <= 1; if (tx_fifo_full_i == 1) d_write_o <= 1; end DATA_TRANSFER: begin d_read_o <= 0; d_write_o <= 0; if (tx_cycle) begin if (tx_fifo_empty_i) begin if (!trans_done) int_status_o[`INT_DATA_CFE] <= 1; trans_done <= 1; //stop sd_data_serial_host d_write_o <= 1; d_read_o <= 1; end end else begin if (rx_fifo_full_i) begin if (!trans_done) int_status_o[`INT_DATA_CFE] <= 1; trans_done <= 1; //stop sd_data_serial_host d_write_o <= 1; d_read_o <= 1; end end if (xfr_complete_i) begin //Transfer complete d_write_o <= 0; d_read_o <= 0; trans_done <= 1; if (!crc_ok_i) begin //Wrong CRC and Data line free. if (!trans_done) int_status_o[`INT_DATA_CCRCE] <= 1; end else if (crc_ok_i) begin //Data Line free if (!trans_done) int_status_o[`INT_DATA_CC] <= 1; end end end endcase if (int_status_rst_i) int_status_o<=0; end end endmodule