--- /dev/null
+// Copyright 2017 University of Cambridge.
+// Copyright and related rights are licensed under the Solderpad Hardware
+// License, Version 0.51 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at
+// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
+// or agreed to in writing, software, hardware and materials distributed under
+// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+// See LICENSE for license details.
+
+`default_nettype none
+
+ module sd_bus(
+ input msoc_clk,
+ input sd_clk,
+ input rstn,
+ input [31:0] core_lsu_addr,
+ input wire [31:0] core_lsu_wdata,
+ input core_sd_we,
+ input wire sd_detect,
+ input wire [3:0] fifo_status,
+ input wire [31:0] rx_fifo_status,
+ input wire [31:0] tx_fifo_status,
+ input wire [31:0] data_out_tx_fifo,
+ input sd_cmd_to_host,
+ input [3:0] sd_dat_to_host,
+ //---------------Output ports---------------
+ output reg [31:0] sd_cmd_resp_sel,
+ output wire [31:0] data_in_rx_fifo,
+ output tx_rd_fifo,
+ output rx_wr_fifo,
+ output wire [12:0] sd_transf_cnt,
+ output reg sd_reset,
+ output reg [7:0] clock_divider_sd_clk,
+ output reg sd_data_rst,
+ output reg sd_clk_rst,
+ output reg sd_cmd_oe,
+ output reg sd_cmd_to_mem,
+ output reg sd_dat_oe,
+ output reg [3:0] sd_dat_to_mem,
+ output wire [31:0] sd_status
+ );
+ wire sd_cmd_oe_pos;
+ wire sd_cmd_to_mem_pos;
+ wire sd_dat_oe_pos;
+ wire [3:0] sd_dat_to_mem_pos;
+
+ reg sd_cmd_to_host_dly;
+ reg [3:0] sd_dat_to_host_dly;
+
+ wire [133:0] sd_cmd_response;
+ wire [31:0] sd_cmd_wait, sd_data_wait;
+ wire [6:0] sd_cmd_crc_val;
+ wire [47:0] sd_cmd_packet;
+ wire sd_cmd_finish, sd_data_finish, sd_cmd_crc_ok, sd_cmd_index_ok;
+ wire [4:0] sd_data_crc_s;
+ wire [3:0] sd_data_crc_lane_ok;
+ wire [15:0] sd_crc_din[3:0];
+ wire [15:0] sd_crc_calc[3:0];
+
+ reg [2:0] sd_data_start;
+ reg [11:0] sd_blksize;
+
+ reg [2:0] sd_cmd_setting;
+ reg [5:0] sd_cmd_i;
+ reg [31:0] sd_cmd_arg;
+ reg [31:0] sd_cmd_timeout;
+ reg sd_cmd_start, sd_cmd_rst, dmy;
+ wire [5:0] sd_cmd_state;
+ wire [6:0] sd_data_state;
+
+always @(negedge sd_clk or negedge rstn)
+ if (rstn == 0)
+ begin
+ sd_cmd_oe <= 1'b0;
+ sd_cmd_to_mem <= 1'b0;
+ sd_dat_oe <= 1'b0;
+ sd_dat_to_mem <= 4'b0;
+ end
+ else
+ begin
+ sd_cmd_oe <= sd_cmd_oe_pos;
+ sd_cmd_to_mem <= sd_cmd_to_mem_pos;
+ sd_dat_oe <= sd_dat_oe_pos;
+ sd_dat_to_mem <= sd_dat_to_mem_pos;
+ end // else: !if(!rstn)
+
+ always @(posedge msoc_clk or negedge rstn)
+ if (rstn == 0)
+ begin
+ sd_blksize <= 0;
+ sd_data_start <= 0;
+ clock_divider_sd_clk <= 0;
+ sd_cmd_i <= 0;
+ sd_cmd_arg <= 0;
+ sd_cmd_setting <= 0;
+ sd_cmd_start <= 0;
+ sd_reset <= 0;
+ sd_data_rst <= 0;
+ sd_cmd_rst <= 0;
+ sd_clk_rst <= 0;
+ sd_cmd_timeout <= 15;
+ end
+ else
+ begin
+ if (core_sd_we)
+ case(core_lsu_addr[5:2])
+ 1: clock_divider_sd_clk <= core_lsu_wdata[7:0];
+ 2: sd_cmd_arg <= core_lsu_wdata;
+ 3: sd_cmd_i <= core_lsu_wdata[5:0];
+ 4: {sd_data_start,sd_cmd_setting} <= core_lsu_wdata[5:0];
+ 5: sd_cmd_start <= core_lsu_wdata[0];
+ 6: {sd_reset,sd_clk_rst,sd_data_rst,sd_cmd_rst} <= core_lsu_wdata[3:0];
+ 8: sd_blksize <= core_lsu_wdata[11:0];
+ 9: sd_cmd_timeout <= core_lsu_wdata;
+ endcase
+ end
+
+ always_comb
+ case(core_lsu_addr[6:2])
+ 0: sd_cmd_resp_sel = sd_cmd_response[38:7];
+ 1: sd_cmd_resp_sel = sd_cmd_response[70:39];
+ 2: sd_cmd_resp_sel = sd_cmd_response[102:71];
+ 3: sd_cmd_resp_sel = {1'b0,sd_cmd_response[133:103]};
+ 4: sd_cmd_resp_sel = sd_cmd_wait;
+ 5: sd_cmd_resp_sel = {sd_status[31:4],fifo_status[3:0]};
+ 6: sd_cmd_resp_sel = sd_cmd_packet[31:0];
+ 7: sd_cmd_resp_sel = {16'b0,sd_cmd_packet[47:32]};
+ 8: sd_cmd_resp_sel = sd_data_wait;
+ 9: sd_cmd_resp_sel = {19'b0,sd_transf_cnt};
+ 10: sd_cmd_resp_sel = rx_fifo_status;
+ 11: sd_cmd_resp_sel = tx_fifo_status;
+ 12: sd_cmd_resp_sel = {31'b0,sd_detect};
+ 13: sd_cmd_resp_sel = {26'b0,sd_cmd_state};
+ 14: sd_cmd_resp_sel = {25'b0,sd_data_state};
+ 15: sd_cmd_resp_sel = {23'b0,sd_data_crc_s,sd_data_crc_lane_ok};
+ 16: sd_cmd_resp_sel = {32'b0};
+ 17: sd_cmd_resp_sel = {24'b0,clock_divider_sd_clk};
+ 18: sd_cmd_resp_sel = sd_cmd_arg;
+ 19: sd_cmd_resp_sel = {26'b0,sd_cmd_i};
+ 20: sd_cmd_resp_sel = {26'b0,sd_data_start,sd_cmd_setting[2:0]};
+ 21: sd_cmd_resp_sel = {31'b0,sd_cmd_start};
+ 22: sd_cmd_resp_sel = {28'b0,sd_reset,sd_clk_rst,sd_data_rst,sd_cmd_rst};
+ 23: sd_cmd_resp_sel = {32'b1};
+ 24: sd_cmd_resp_sel = {20'b0,sd_blksize};
+ 25: sd_cmd_resp_sel = sd_cmd_timeout;
+ 26: sd_cmd_resp_sel = {sd_crc_din[1],sd_crc_din[0]};
+ 27: sd_cmd_resp_sel = {sd_crc_din[3],sd_crc_din[2]};
+ 28: sd_cmd_resp_sel = {sd_crc_calc[1],sd_crc_calc[0]};
+ 29: sd_cmd_resp_sel = {sd_crc_calc[3],sd_crc_calc[2]};
+ default: sd_cmd_resp_sel = 32'HDEADBEEF;
+ endcase // case (core_lsu_addr[6:2])
+
+ sd_top sdtop(
+ .sd_clk (sd_clk),
+ .cmd_rst (~(sd_cmd_rst&rstn)),
+ .data_rst (~(sd_data_rst&rstn)),
+ .setting_i (sd_cmd_setting),
+ .timeout_i (sd_cmd_timeout),
+ .cmd_i (sd_cmd_i),
+ .arg_i (sd_cmd_arg),
+ .start_i (sd_cmd_start),
+ .sd_data_start_i(sd_data_start),
+ .sd_blksize_i(sd_blksize),
+ .sd_data_i(data_out_tx_fifo),
+ .sd_dat_to_host(sd_dat_to_host),
+ .sd_cmd_to_host(sd_cmd_to_host),
+ .finish_cmd_o(sd_cmd_finish),
+ .finish_data_o(sd_data_finish),
+ .response0_o(sd_cmd_response[38:7]),
+ .response1_o(sd_cmd_response[70:39]),
+ .response2_o(sd_cmd_response[102:71]),
+ .response3_o(sd_cmd_response[133:103]),
+ .crc_ok_o (sd_cmd_crc_ok),
+ .index_ok_o (sd_cmd_index_ok),
+ .sd_transf_cnt(sd_transf_cnt),
+ .wait_o(sd_cmd_wait),
+ .wait_data_o(sd_data_wait),
+ .status_o(sd_status[31:4]),
+ .packet0_o(sd_cmd_packet[31:0]),
+ .packet1_o(sd_cmd_packet[47:32]),
+ .crc_val_o(sd_cmd_crc_val),
+ .crc_actual_o(sd_cmd_response[6:0]),
+ .sd_rd_o(tx_rd_fifo),
+ .sd_we_o(rx_wr_fifo),
+ .sd_data_o(data_in_rx_fifo),
+ .sd_dat_to_mem(sd_dat_to_mem_pos),
+ .sd_cmd_to_mem(sd_cmd_to_mem_pos),
+ .sd_dat_oe(sd_dat_oe_pos),
+ .sd_cmd_oe(sd_cmd_oe_pos),
+ .sd_cmd_state(sd_cmd_state),
+ .sd_data_state(sd_data_state),
+ .sd_data_crc_s(sd_data_crc_s),
+ .sd_data_crc_lane_ok(sd_data_crc_lane_ok),
+ .sd_crc_din(sd_crc_din),
+ .sd_crc_calc(sd_crc_calc)
+ );
+
+endmodule // chip_top
+`default_nettype wire
--- /dev/null
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// WISHBONE SD Card Controller IP Core ////
+//// ////
+//// sd_clock_divider.v ////
+//// ////
+//// This file is part of the WISHBONE SD Card ////
+//// Controller IP Core project ////
+//// http://opencores.org/project,sd_card_controller ////
+//// ////
+//// Description ////
+//// Control of sd card clock rate ////
+//// ////
+//// 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+module sd_clock_divider (
+ input CLK,
+ input [7:0] DIVIDER,
+ input RST,
+ output SD_CLK
+ );
+
+ reg [7:0] ClockDiv;
+ reg SD_CLK_O;
+
+ BUFG SD_CLK_buf_inst (
+ .O(SD_CLK), // 1-bit output: Clock output
+ .I(SD_CLK_O) // 1-bit input: Clock input
+ );
+
+ always @(posedge CLK or posedge RST)
+ begin
+ if (RST) begin
+ ClockDiv <= 8'b0000_0000;
+ SD_CLK_O <= 0;
+ end
+ else if (ClockDiv == DIVIDER) begin
+ ClockDiv <= 0;
+ SD_CLK_O <= ~SD_CLK_O;
+ end else begin
+ ClockDiv <= ClockDiv + 8'h1;
+ SD_CLK_O <= SD_CLK_O;
+ end
+ end
+
+endmodule
+
+
--- /dev/null
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// WISHBONE SD Card Controller IP Core ////
+//// ////
+//// sd_cmd_serial_host.v ////
+//// ////
+//// This file is part of the WISHBONE SD Card ////
+//// Controller IP Core project ////
+//// http://opencores.org/project,sd_card_controller ////
+//// ////
+//// Description ////
+//// Module resposible for sending and receiving commands ////
+//// through 1-bit sd card command 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+module sd_cmd_serial_host (
+ sd_clk,
+ rst,
+ setting_i,
+ cmd_i,
+ start_i,
+ timeout_i,
+ response_o,
+ crc_ok_o,
+ index_ok_o,
+ finish_o,
+ wait_reg_o,
+ crc_val_o,
+ packet_o,
+ start_data_o,
+ cmd_dat_i,
+ cmd_out_o,
+ cmd_oe_o
+ );
+
+//-------------Internal Constant-------------
+parameter INIT_DELAY = 74;
+parameter BITS_TO_SEND = 48;
+parameter CMD_SIZE = 40;
+parameter RESP_SIZE_LONG = 127;
+parameter RESP_SIZE_SHORT = 39;
+//---------------Input ports---------------
+input wire sd_clk;
+input wire rst;
+input [2:0] setting_i;
+input [37:0] cmd_i;
+input wire start_i;
+input wire cmd_dat_i;
+input [31:0] timeout_i;
+//---------------Output ports---------------
+output reg [BITS_TO_SEND-1:0] packet_o;
+output reg [RESP_SIZE_LONG+6:0] response_o;
+output reg finish_o;
+output reg crc_ok_o;
+output reg index_ok_o;
+output reg cmd_oe_o;
+output reg cmd_out_o;
+output reg start_data_o;
+output wire [6:0] crc_val_o;
+output reg [31:0] wait_reg_o;
+//---------------Internal variable-----------
+ reg [CMD_SIZE-1:0] cmd_buff;
+ reg cmd_dat_reg;
+ reg [7:0] resp_len;
+ reg with_response, with_data;
+
+//CRC
+reg crc_rst;
+reg crc_enable;
+reg crc_bit;
+//-Internal Counterns
+reg [7:0] counter;
+//-State Machine
+parameter STATE_SIZE = 6;
+parameter
+ INIT = 6'h00,
+ IDLE = 6'h01,
+ SETUP_CRC = 6'h02,
+ WRITE = 6'h04,
+ READ_WAIT = 6'h08,
+ READ = 6'h10,
+ FINISH_RD_WR = 6'h20;
+reg [STATE_SIZE-1:0] state;
+reg [STATE_SIZE-1:0] next_state;
+
+//------------------------------------------
+sd_crc_7 CRC_7(
+ crc_bit,
+ crc_enable,
+ sd_clk,
+ crc_rst,
+ crc_val_o);
+
+//------------------------------------------
+always @(state or counter or start_i or with_response or cmd_dat_reg or resp_len or timeout_i or wait_reg_o)
+begin: FSM_COMBO
+ case(state)
+ INIT: begin
+ if (counter >= INIT_DELAY) begin
+ next_state = IDLE;
+ end
+ else begin
+ next_state = INIT;
+ end
+ end
+ IDLE: begin
+ if (start_i) begin
+ next_state = SETUP_CRC;
+ end
+ else begin
+ next_state = IDLE;
+ end
+ end
+ SETUP_CRC:
+ next_state = WRITE;
+ WRITE:
+ if (counter >= BITS_TO_SEND && with_response) begin
+ next_state = READ_WAIT;
+ end
+ else if (counter >= BITS_TO_SEND) begin
+ next_state = FINISH_RD_WR;
+ end
+ else begin
+ next_state = WRITE;
+ end
+ READ_WAIT:
+ if ((wait_reg_o >= 3) && !cmd_dat_reg) begin // allow time for bus to change direction
+ next_state = READ;
+ end
+ else if (wait_reg_o >= timeout_i) begin // prevent hang if card did not respond
+ next_state = FINISH_RD_WR;
+ end
+ else begin
+ next_state = READ_WAIT;
+ end
+ READ:
+ if (counter >= resp_len+8) begin
+ next_state = FINISH_RD_WR;
+ end
+ else begin
+ next_state = READ;
+ end
+ FINISH_RD_WR:
+ if (start_i)
+ next_state = FINISH_RD_WR;
+ else
+ next_state = IDLE;
+ default:
+ next_state = INIT;
+ endcase
+end
+
+always @(posedge sd_clk or posedge rst)
+begin: COMMAND_DECODER
+ if (rst) begin
+ resp_len <= 0;
+ with_response <= 0;
+ with_data <= 0;
+ cmd_buff <= 0;
+ end
+ else begin
+ if (start_i == 1) begin
+ resp_len <= setting_i[1] ? RESP_SIZE_LONG : RESP_SIZE_SHORT;
+ with_response <= setting_i[0];
+ with_data <= setting_i[2];
+ cmd_buff <= {2'b01,cmd_i};
+ end
+ end
+end
+
+//----------------Seq logic------------
+always @(posedge sd_clk or posedge rst)
+begin: FSM_SEQ
+ if (rst) begin
+ state <= INIT;
+ end
+ else begin
+ state <= next_state;
+ end
+end
+
+//-------------OUTPUT_LOGIC-------
+always @(posedge sd_clk or posedge rst)
+begin: FSM_OUT
+ if (rst) begin
+ crc_enable <= 0;
+ cmd_oe_o = 1;
+ cmd_out_o = 1;
+ response_o <= 0;
+ finish_o <= 0;
+ crc_rst <= 1;
+ crc_bit <= 0;
+ index_ok_o <= 0;
+ crc_ok_o <= 0;
+ counter <= 0;
+ cmd_dat_reg <= 0;
+ packet_o <= 0;
+ start_data_o <= 0;
+ wait_reg_o <= 0;
+ end
+ else begin
+ case(state)
+ INIT: begin
+ counter <= counter+1;
+ cmd_oe_o = 1;
+ cmd_out_o = 1;
+ end
+ IDLE: begin
+ cmd_oe_o = 0; //Put CMD to Z
+ counter <= 0;
+ crc_rst <= 1;
+ crc_enable <= 0;
+ index_ok_o <= 0;
+ finish_o <= 0;
+ start_data_o <= 0;
+ end
+ SETUP_CRC: begin
+ crc_rst <= 0;
+ crc_enable <= 1;
+ response_o <= 0;
+ packet_o <= 0;
+ crc_bit <= cmd_buff[CMD_SIZE-1];
+ end
+ WRITE: begin
+ cmd_dat_reg <= 1'b1;
+ if (counter < BITS_TO_SEND-8) begin // 1->40 CMD, (41 >= CNT && CNT <=47) CRC, 48 stop_bit
+ cmd_oe_o = 1;
+ cmd_out_o = cmd_buff[CMD_SIZE-1-counter];
+ if (counter < BITS_TO_SEND-9) begin //1 step ahead
+ crc_bit <= cmd_buff[CMD_SIZE-2-counter];
+ end else begin
+ crc_enable <= 0;
+ end
+ end
+ else if (counter < BITS_TO_SEND-1) begin
+ cmd_oe_o = 1;
+ crc_enable <= 0;
+ cmd_out_o = crc_val_o[BITS_TO_SEND-counter-2];
+ end
+ else if (counter == BITS_TO_SEND-1) begin
+ cmd_oe_o = 1;
+ cmd_out_o = 1'b1;
+ end
+ else begin
+ cmd_oe_o = 0;
+ cmd_out_o = 1'b1;
+ end
+ counter <= counter+1;
+ wait_reg_o <= 0;
+ if (cmd_oe_o) packet_o <= {packet_o[BITS_TO_SEND-2:0],cmd_out_o};
+ end
+ READ_WAIT: begin
+ cmd_dat_reg <= cmd_dat_i;
+ crc_enable <= 0;
+ crc_rst <= 1;
+ counter <= 1;
+ cmd_oe_o = 0;
+ wait_reg_o <= wait_reg_o + 1;
+ end
+ READ: begin
+ cmd_dat_reg <= cmd_dat_i;
+ crc_rst <= 0;
+ crc_enable <= (resp_len != RESP_SIZE_LONG || counter > 7);
+ cmd_oe_o = 0;
+ if (counter <= resp_len)
+ crc_bit <= cmd_dat_reg;
+ else
+ begin
+ crc_enable <= 0;
+ end
+ if (counter <= resp_len+7) begin
+ response_o <= {response_o[RESP_SIZE_LONG+5:0],cmd_dat_reg};
+ end
+ else begin
+ crc_enable <= 0;
+ crc_ok_o <= (response_o[6:0] == crc_val_o);
+ start_data_o <= with_data;
+ end
+ counter <= counter + 1;
+ end
+ FINISH_RD_WR: begin
+ index_ok_o <= (cmd_buff[37:32] == response_o[125:120]);
+ finish_o <= 1;
+ crc_enable <= 0;
+ counter <= 0;
+ cmd_oe_o = 0;
+ end // case: FINISH_RD_WR
+ default:;
+ endcase
+ end
+end
+
+endmodule
+
+
--- /dev/null
+// ==========================================================================
+// CRC Generation Unit - Linear Feedback Shift Register implementation
+// (c) Kay Gorontzi, GHSi.de, distributed under the terms of LGPL
+// ==========================================================================
+module sd_crc_16(BITVAL, ENABLE, BITSTRB, CLEAR, CRC);
+ input BITVAL; // Next input bit
+ input ENABLE; // Enable calculation
+ input BITSTRB; // Current bit valid (Clock)
+ input CLEAR; // Init CRC value
+ output [15:0] CRC; // Current output CRC value
+
+ reg [15:0] CRC; // We need output registers
+ wire inv;
+
+ assign inv = BITVAL ^ CRC[15]; // XOR required?
+
+ always @(posedge BITSTRB or posedge CLEAR) begin
+ if (CLEAR) begin
+ CRC <= 0; // Init before calculation
+ end
+ else begin
+ if (ENABLE == 1) begin
+ CRC[15] <= CRC[14];
+ CRC[14] <= CRC[13];
+ CRC[13] <= CRC[12];
+ CRC[12] <= CRC[11] ^ inv;
+ CRC[11] <= CRC[10];
+ CRC[10] <= CRC[9];
+ CRC[9] <= CRC[8];
+ CRC[8] <= CRC[7];
+ CRC[7] <= CRC[6];
+ CRC[6] <= CRC[5];
+ CRC[5] <= CRC[4] ^ inv;
+ CRC[4] <= CRC[3];
+ CRC[3] <= CRC[2];
+ CRC[2] <= CRC[1];
+ CRC[1] <= CRC[0];
+ CRC[0] <= inv;
+ end
+ end
+ end
+
+endmodule
--- /dev/null
+// ==========================================================================
+// CRC Generation Unit - Linear Feedback Shift Register implementation
+// (c) Kay Gorontzi, GHSi.de, distributed under the terms of LGPL
+// ==========================================================================
+module sd_crc_7(BITVAL, ENABLE, BITSTRB, CLEAR, CRC);
+ input BITVAL; // Next input bit
+ input ENABLE; // Enable calculation
+ input BITSTRB; // Current bit valid (Clock)
+ input CLEAR; // Init CRC value
+ output [6:0] CRC; // Current output CRC value
+
+ reg [6:0] CRC; // We need output registers
+ wire inv;
+
+ assign inv = BITVAL ^ CRC[6]; // XOR required?
+
+ always @(posedge BITSTRB or posedge CLEAR) begin
+ if (CLEAR) begin
+ CRC <= 0; // Init before calculation
+ end
+ else begin
+ if (ENABLE == 1) begin
+ CRC[6] <= CRC[5];
+ CRC[5] <= CRC[4];
+ CRC[4] <= CRC[3];
+ CRC[3] <= CRC[2] ^ inv;
+ CRC[2] <= CRC[1];
+ CRC[1] <= CRC[0];
+ CRC[0] <= inv;
+ end
+ end
+ end
+
+endmodule
--- /dev/null
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// WISHBONE SD Card Controller IP Core ////
+//// ////
+//// sd_data_serial_host.v ////
+//// ////
+//// This file is part of the WISHBONE SD Card ////
+//// Controller IP Core project ////
+//// http://opencores.org/project,sd_card_controller ////
+//// ////
+//// Description ////
+//// Module resposible for sending and receiving data through ////
+//// 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.h"
+
+module sd_data_serial_host(
+ input sd_clk,
+ input rst,
+ //Tx Fifo
+ input [31:0] data_in,
+ output reg rd,
+ //Rx Fifo
+ output reg [31:0] data_out,
+ output reg we,
+ //tristate data
+ output reg DAT_oe_o,
+ output reg [3:0] DAT_dat_o,
+ input [3:0] DAT_dat_i,
+ //Control signals
+ input [`BLKSIZE_W-1:0] blksize,
+ input bus_4bit,
+ input [`BLKCNT_W-1:0] blkcnt,
+ input [1:0] start,
+ input [1:0] byte_alignment,
+ input [31:0] timeout_i,
+ output sd_data_busy,
+ output busy,
+ output crc_ok,
+ output reg finish_o,
+ output reg [31:0] wait_reg_o,
+ output reg [`BLKSIZE_W-1+4:0] transf_cnt_o
+ );
+
+reg [4:0] crc_s;
+reg [3:0] crc_lane_ok;
+reg [15:0] crc_din[3:0];
+wire [15:0] crc_calc[3:0];
+reg [31:0] data_out0;
+reg we0;
+reg [3:0] DAT_dat_reg;
+reg [`BLKSIZE_W-1+4:0] data_cycles;
+reg bus_4bit_reg;
+//CRC16
+ reg [4:0] crc_in;
+reg crc_rst;
+parameter SIZE = 7;
+reg [SIZE-1:0] state;
+reg [SIZE-1:0] next_state;
+parameter IDLE = 7'b0000001;
+parameter WRITE_DAT = 7'b0000010;
+parameter WRITE_CRC = 7'b0000100;
+parameter WRITE_BUSY = 7'b0001000;
+parameter READ_WAIT = 7'b0010000;
+parameter READ_DAT = 7'b0100000;
+parameter FINISH = 7'b1000000;
+reg [2:0] crc_status;
+reg busy_int;
+reg [`BLKSIZE_W-1:0] blksize_reg;
+reg [4:0] crc_c;
+ reg [3:0] crnt_din;
+reg [4:0] data_index;
+
+ integer k;
+genvar i;
+generate
+ for(i=0; i<4; i=i+1) begin: CRC_16_gen
+ sd_crc_16 CRC_16_i (crc_in[i], crc_in[4], ~sd_clk, crc_rst, crc_calc[i]);
+ end
+endgenerate
+
+assign busy = (state != IDLE) && (state != FINISH);
+assign sd_data_busy = !DAT_dat_reg[0];
+assign crc_ok = &crc_lane_ok;
+
+always @(posedge sd_clk or posedge rst)
+begin: FSM_OUT
+ if (rst) begin
+ state <= IDLE;
+ DAT_oe_o <= 0;
+ crc_in <= 0;
+ crc_rst <= 1;
+ transf_cnt_o <= 0;
+ crc_c <= 15;
+ rd <= 0;
+ crc_c <= 0;
+ DAT_dat_o <= 0;
+ crc_status <= 0;
+ crc_lane_ok <= 0;
+ crc_s <= 0;
+ we0 <= 0;
+ we <= 0;
+ data_out0 <= 0;
+ busy_int <= 0;
+ data_index <= 0;
+ data_cycles <= 0;
+ bus_4bit_reg <= 0;
+ wait_reg_o <= 0;
+ finish_o <= 0;
+ DAT_dat_reg <= 0;
+ data_out <= 0;
+ transf_cnt_o <= 0;
+ end
+ else begin
+ // sd data input pad register
+ DAT_dat_reg <= DAT_dat_i;
+ crnt_din = 4'hf;
+ if (we0) data_out <= data_out0;
+ we <= we0;
+ case(state)
+ IDLE: begin
+ for (k = 0; k < 4; k=k+1)
+ crc_din[k] <= 0;
+ DAT_oe_o <= 0;
+ DAT_dat_o <= 4'b1111;
+ crc_in <= 0;
+ crc_rst <= 1;
+ transf_cnt_o <= 0;
+ crc_c <= 16;
+ crc_status <= 0;
+ crc_lane_ok <= 0;
+ crc_s <= 0;
+ we0 <= 0;
+ rd <= 0;
+ data_index <= 0;
+ blksize_reg <= blksize;
+ data_cycles <= (bus_4bit ? {2'b0,blksize,1'b0} + 'd2 : {blksize,3'b0} + 'd8);
+ bus_4bit_reg <= bus_4bit;
+ wait_reg_o <= 0;
+ finish_o <= 0;
+ data_out <= 0;
+ if (start == 2'b01)
+ state <= WRITE_DAT;
+ else if (start == 2'b10)
+ state <= READ_WAIT;
+ end
+ WRITE_DAT: begin
+ transf_cnt_o <= transf_cnt_o + 16'h1;
+ rd <= 0;
+ //special case
+ if (transf_cnt_o == 0) begin
+ crc_rst <= 0;
+ data_index <= 0;
+ crnt_din = bus_4bit_reg ? 4'h0 : 4'he;
+ rd <= 1;
+ DAT_oe_o <= 1;
+ DAT_dat_o <= crnt_din;
+ end
+ else if (transf_cnt_o < data_cycles+16) begin /* send the write data */
+ if (bus_4bit_reg) begin
+ crnt_din = {
+ data_in[31-({data_index[2:0],2'b00})],
+ data_in[30-({data_index[2:0],2'b00})],
+ data_in[29-({data_index[2:0],2'b00})],
+ data_in[28-({data_index[2:0],2'b00})]
+ };
+ if (data_index[2:0] == 3'h7 && transf_cnt_o < data_cycles-2) begin
+ begin
+ rd <= 1;
+ end
+ end
+ end
+ else begin
+ crnt_din = {3'h7, data_in[31-data_index]};
+ if (data_index == 29/*not 31 - read delay !!!*/) begin
+ begin
+ rd <= 1;
+ end
+ end
+ end
+ data_index <= data_index + 5'h1;
+ if (transf_cnt_o < data_cycles-1)
+ begin
+ crc_in <= {1'b1,crnt_din};
+ DAT_dat_o <= crnt_din;
+ end
+ else if (crc_c!=0) begin /* send the CRC */
+ crc_in <= 0;
+ crc_c <= crc_c - 5'h1;
+ DAT_oe_o <= 1;
+ DAT_dat_o[0] <= crc_calc[0][crc_c-1];
+ if (bus_4bit_reg)
+ DAT_dat_o[3:1] <= {crc_calc[3][crc_c-1], crc_calc[2][crc_c-1], crc_calc[1][crc_c-1]};
+ else
+ DAT_dat_o[3:1] <= {3'h7};
+ end
+ else /* send the stop bit */
+ begin
+ crc_in <= 0;
+ DAT_oe_o <= 1;
+ DAT_dat_o <= 4'hf;
+ end
+ end
+ else begin /* wait for write ack */
+ DAT_oe_o <= 0;
+ crc_s[4] <= DAT_dat_reg[0];
+ if (!DAT_dat_reg[0])
+ state <= WRITE_CRC;
+ end
+ end
+ WRITE_CRC: begin /* get write ack */
+ DAT_oe_o <= 0;
+ crc_status <= crc_status + 3'h1;
+ crc_s[3-crc_status[1:0]] <= DAT_dat_reg[0];
+ busy_int <= 1;
+ if (crc_status == 3)
+ state <= WRITE_BUSY;
+ end
+ WRITE_BUSY: begin /* wait for write completion */
+ busy_int <= !DAT_dat_reg[0];
+ if (!busy_int)
+ state <= FINISH;
+ end
+ READ_WAIT: begin /* wait for a start bit in read mode */
+ DAT_oe_o <= 0;
+ crc_rst <= 0;
+ crc_in <= 0;
+ crc_c <= 15;// end
+ transf_cnt_o <= 0;
+ data_index <= 0;
+ wait_reg_o <= wait_reg_o + 1;
+ if ((wait_reg_o >= 3) && !DAT_dat_reg[0]) begin // allow time for bus to change direction
+ state <= READ_DAT;
+ end
+ else if (wait_reg_o >= timeout_i) begin // prevent hang if card did not respond
+ state <= FINISH;
+ end
+ end
+ READ_DAT: begin /* read the data and calculate CRC */
+ we0 <= 0;
+ if (transf_cnt_o < data_cycles-2) begin
+ if (bus_4bit_reg) begin
+ if (&data_index[2:0])
+ begin
+ we0 <= 1;
+ end;
+ data_out0[31-({data_index[2:0],2'b00})] <= DAT_dat_reg[3];
+ data_out0[30-({data_index[2:0],2'b00})] <= DAT_dat_reg[2];
+ data_out0[29-({data_index[2:0],2'b00})] <= DAT_dat_reg[1];
+ data_out0[28-({data_index[2:0],2'b00})] <= DAT_dat_reg[0];
+ end
+ else begin
+ if (&data_index)
+ begin
+ we0 <= 1;
+ end;
+ data_out0[31-data_index] <= DAT_dat_reg[0];
+ end
+ data_index <= data_index + 5'h1;
+ crc_in <= {1'b1,DAT_dat_reg};
+ transf_cnt_o <= transf_cnt_o + 16'h1;
+ end
+ else if (crc_c != 5'h1f) begin
+ for (k = 0; k < 4; k=k+1)
+ begin
+ crc_din[k][crc_c[3:0]] <= DAT_dat_reg[k];
+ end
+ transf_cnt_o <= transf_cnt_o + 16'h1;
+ crc_in <= 0;
+ we0 <=0;
+ crc_c <= crc_c - 5'h1;
+ end
+ else
+ begin
+ for (k = 0; k < 4; k=k+1)
+ crc_lane_ok[k] <= crc_calc[k] == crc_din[k];
+ state <= FINISH;
+ end
+ end // case: READ_DAT
+ FINISH:
+ begin
+ finish_o <= 1;
+ if (start == 2'b00)
+ state <= IDLE;
+ end
+ default:
+ state <= IDLE;
+ endcase; // case (state)
+ //abort
+ if (start == 2'b11)
+ state <= IDLE;
+ end
+end
+
+endmodule
+
+
+
+
+
--- /dev/null
+//////////////////////////////////////////////////////////////////////
+//// ////
+//// WISHBONE SD Card Controller IP Core ////
+//// ////
+//// sd_defines.h ////
+//// ////
+//// This file is part of the WISHBONE SD Card ////
+//// Controller IP Core project ////
+//// http://opencores.org/project,sd_card_controller ////
+//// ////
+//// Description ////
+//// Header file with common definitions ////
+//// ////
+//// 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 ////
+//// ////
+//////////////////////////////////////////////////////////////////////
+
+//global defines
+`define BLKSIZE_W 12
+`define BLKCNT_W 16
+`define CMD_TIMEOUT_W 24
+`define DATA_TIMEOUT_W 24
+
+//cmd module interrupts
+`define INT_CMD_SIZE 5
+`define INT_CMD_CC 0
+`define INT_CMD_EI 1
+`define INT_CMD_CTE 2
+`define INT_CMD_CCRCE 3
+`define INT_CMD_CIE 4
+
+//data module interrupts
+`define INT_DATA_SIZE 5
+`define INT_DATA_CC 0
+`define INT_DATA_EI 1
+`define INT_DATA_CTE 2
+`define INT_DATA_CCRCE 3
+`define INT_DATA_CFE 4
+
+//command register defines
+`define CMD_REG_SIZE 14
+`define CMD_RESPONSE_CHECK 1:0
+`define CMD_BUSY_CHECK 2
+`define CMD_CRC_CHECK 3
+`define CMD_IDX_CHECK 4
+`define CMD_WITH_DATA 6:5
+`define CMD_INDEX 13:8
+
+//register addreses
+`define argument 8'h00
+`define command 8'h04
+`define resp0 8'h08
+`define resp1 8'h0c
+`define resp2 8'h10
+`define resp3 8'h14
+`define data_timeout 8'h18
+`define controller 8'h1c
+`define cmd_timeout 8'h20
+`define clock_d 8'h24
+`define reset 8'h28
+`define voltage 8'h2c
+`define capa 8'h30
+`define cmd_isr 8'h34
+`define cmd_iser 8'h38
+`define data_isr 8'h3c
+`define data_iser 8'h40
+`define blksize 8'h44
+`define blkcnt 8'h48
+`define dst_src_addr 8'h60
+
+//wb module defines
+`define RESET_BLOCK_SIZE 12'd511
+`define RESET_CLK_DIV 0
+`define SUPPLY_VOLTAGE_mV 3300
--- /dev/null
+//
+// (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved.
+//
+// This file contains confidential and proprietary information
+// of Xilinx, Inc. and is protected under U.S. and
+// international copyright and other intellectual property
+// laws.
+//
+// DISCLAIMER
+// This disclaimer is not a license and does not grant any
+// rights to the materials distributed herewith. Except as
+// otherwise provided in a valid license issued to you by
+// Xilinx, and to the maximum extent permitted by applicable
+// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
+// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
+// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
+// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
+// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
+// (2) Xilinx shall not be liable (whether in contract or tort,
+// including negligence, or under any other theory of
+// liability) for any loss or damage of any kind or nature
+// related to, arising under or in connection with these
+// materials, including for any direct, or any indirect,
+// special, incidental, or consequential loss or damage
+// (including loss of data, profits, goodwill, or any type of
+// loss or damage suffered as a result of any action brought
+// by a third party) even if such damage or loss was
+// reasonably foreseeable or Xilinx had been advised of the
+// possibility of the same.
+//
+// CRITICAL APPLICATIONS
+// Xilinx products are not designed or intended to be fail-
+// safe, or for use in any application requiring fail-safe
+// performance, such as life-support or safety devices or
+// systems, Class III medical devices, nuclear facilities,
+// applications related to the deployment of airbags, or any
+// other applications that could lead to death, personal
+// injury, or severe property or environmental damage
+// (individually and collectively, "Critical
+// Applications"). Customer assumes the sole risk and
+// liability of any use of Xilinx products in Critical
+// Applications, subject only to applicable laws and
+// regulations governing limitations on product liability.
+//
+// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
+// PART OF THIS FILE AT ALL TIMES.
+//
+
+// Copyright 2015 ETH Zurich and University of Bologna.
+// Copyright and related rights are licensed under the Solderpad Hardware
+// License, Version 0.51 (the "License"); you may not use this file except in
+// compliance with the License. You may obtain a copy of the License at
+// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
+// or agreed to in writing, software, hardware and materials distributed under
+// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+// CONDITIONS OF ANY KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations under the License.
+// See LICENSE for license details.
+
+`default_nettype none
+
+module sd_top(
+ input wire sd_clk,
+ input wire cmd_rst,
+ input wire data_rst,
+ input wire [2:0] setting_i,
+ input wire start_i,
+ input wire [31:0] arg_i,
+ input wire [5:0] cmd_i,
+ input wire [31:0] timeout_i,
+ input wire [2:0] sd_data_start_i,
+ input wire [1:0] sd_align_i,
+ input wire [15:0] sd_blkcnt_i,
+ input wire [11:0] sd_blksize_i,
+ input wire [31:0] sd_data_i,
+ input wire [3:0] sd_dat_to_host,
+ input wire sd_cmd_to_host,
+//---------------Output ports---------------
+ output wire [31:0] response0_o,
+ output wire [63:32] response1_o,
+ output wire [95:64] response2_o,
+ output wire [126:96] response3_o,
+ output wire [31:0] wait_o,
+ output wire [31:0] wait_data_o,
+ output wire [31:4] status_o,
+ output wire [31:0] packet0_o,
+ output wire [15:0] packet1_o,
+ output wire [6:0] crc_val_o,
+ output wire [6:0] crc_actual_o,
+ output wire finish_cmd_o,
+ output wire finish_data_o,
+ output wire crc_ok_o,
+ output wire index_ok_o,
+ output wire sd_rd_o,
+ output wire sd_we_o,
+ output wire [31:0] sd_data_o,
+ output wire [15:0] transf_cnt_o,
+ output wire [3:0] sd_dat_to_mem,
+ output wire sd_cmd_to_mem,
+ output wire sd_cmd_oe,
+ output wire sd_dat_oe,
+ output reg [8:0] sd_xfr_addr);
+
+ reg sd_cmd_to_host_dly;
+ reg [3:0] sd_dat_to_host_dly;
+
+ wire start_data;
+ wire data_crc_ok;
+ wire sd_busy, sd_data_busy;
+
+ assign status_o = {1'b0,crc_val_o[6:0],
+ 1'b0,crc_actual_o[6:0],
+ 5'b0,finish_data_o,sd_data_busy,finish_cmd_o,
+ index_ok_o,crc_ok_o,data_crc_ok,sd_busy};
+
+always @(negedge sd_clk)
+ begin
+ if (data_rst)
+ sd_xfr_addr <= 0;
+ else
+ begin
+ if (sd_rd_o|sd_we_o)
+ sd_xfr_addr <= sd_xfr_addr + 1;
+ end
+ sd_cmd_to_host_dly <= sd_cmd_to_host;
+ sd_dat_to_host_dly <= sd_dat_to_host;
+ end
+
+sd_cmd_serial_host cmd_serial_host0(
+ .sd_clk (sd_clk),
+ .rst (cmd_rst),
+ .setting_i (setting_i),
+ .cmd_i ({cmd_i,arg_i}),
+ .start_i (start_i),
+ .timeout_i (timeout_i),
+ .finish_o (finish_cmd_o),
+ .response_o ({response3_o,response2_o,response1_o,response0_o,crc_actual_o}),
+ .crc_ok_o (crc_ok_o),
+ .crc_val_o (crc_val_o),
+ .packet_o ({packet1_o,packet0_o}),
+ .index_ok_o (index_ok_o),
+ .wait_reg_o (wait_o),
+ .start_data_o(start_data),
+ .cmd_dat_i (sd_cmd_to_host_dly),
+ .cmd_out_o (sd_cmd_to_mem),
+ .cmd_oe_o (sd_cmd_oe)
+ );
+
+sd_data_serial_host data_serial_host0(
+ .sd_clk (sd_clk),
+ .rst (data_rst),
+ .data_in (sd_data_i),
+ .rd (sd_rd_o),
+ .data_out (sd_data_o),
+ .we (sd_we_o),
+ .finish_o (finish_data_o),
+ .DAT_oe_o (sd_dat_oe),
+ .DAT_dat_o (sd_dat_to_mem),
+ .DAT_dat_i (sd_dat_to_host_dly),
+ .blksize (sd_blksize_i),
+ .bus_4bit (sd_data_start_i[2]),
+ .blkcnt (sd_blkcnt_i),
+ .start (start_data ? sd_data_start_i[1:0] : 2'b00),
+ .byte_alignment (sd_align_i),
+ .timeout_i (timeout_i),
+ .sd_data_busy (sd_data_busy),
+ .busy (sd_busy),
+ .wait_reg_o (wait_data_o),
+ .crc_ok (data_crc_ok),
+ .transf_cnt_o (transf_cnt_o)
+ );
+
+endmodule // chip_top
+`default_nettype wire