add verilog sd-wishbone
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 21 Jul 2018 10:52:58 +0000 (11:52 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Sat, 21 Jul 2018 10:52:58 +0000 (11:52 +0100)
src/bsv/bsv_lib/sd/sd.tgz [new file with mode: 0644]
src/bsv/bsv_lib/sd/sd_bus.sv [new file with mode: 0644]
src/bsv/bsv_lib/sd/sd_clock_divider.v [new file with mode: 0644]
src/bsv/bsv_lib/sd/sd_cmd_serial_host.v [new file with mode: 0644]
src/bsv/bsv_lib/sd/sd_crc_16.v [new file with mode: 0644]
src/bsv/bsv_lib/sd/sd_crc_7.v [new file with mode: 0644]
src/bsv/bsv_lib/sd/sd_data_serial_host.sv [new file with mode: 0644]
src/bsv/bsv_lib/sd/sd_defines.h [new file with mode: 0644]
src/bsv/bsv_lib/sd/sd_top.sv [new file with mode: 0644]

diff --git a/src/bsv/bsv_lib/sd/sd.tgz b/src/bsv/bsv_lib/sd/sd.tgz
new file mode 100644 (file)
index 0000000..120aa40
Binary files /dev/null and b/src/bsv/bsv_lib/sd/sd.tgz differ
diff --git a/src/bsv/bsv_lib/sd/sd_bus.sv b/src/bsv/bsv_lib/sd/sd_bus.sv
new file mode 100644 (file)
index 0000000..220a31b
--- /dev/null
@@ -0,0 +1,201 @@
+// 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
diff --git a/src/bsv/bsv_lib/sd/sd_clock_divider.v b/src/bsv/bsv_lib/sd/sd_clock_divider.v
new file mode 100644 (file)
index 0000000..147ff5d
--- /dev/null
@@ -0,0 +1,81 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+//// 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
+
+
diff --git a/src/bsv/bsv_lib/sd/sd_cmd_serial_host.v b/src/bsv/bsv_lib/sd/sd_cmd_serial_host.v
new file mode 100644 (file)
index 0000000..692b238
--- /dev/null
@@ -0,0 +1,329 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+//// 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
+
+
diff --git a/src/bsv/bsv_lib/sd/sd_crc_16.v b/src/bsv/bsv_lib/sd/sd_crc_16.v
new file mode 100644 (file)
index 0000000..5dbd439
--- /dev/null
@@ -0,0 +1,43 @@
+// ==========================================================================
+// 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
diff --git a/src/bsv/bsv_lib/sd/sd_crc_7.v b/src/bsv/bsv_lib/sd/sd_crc_7.v
new file mode 100644 (file)
index 0000000..7cb5bae
--- /dev/null
@@ -0,0 +1,34 @@
+// ==========================================================================
+// 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
diff --git a/src/bsv/bsv_lib/sd/sd_data_serial_host.sv b/src/bsv/bsv_lib/sd/sd_data_serial_host.sv
new file mode 100644 (file)
index 0000000..971dc38
--- /dev/null
@@ -0,0 +1,334 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+//// 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
+
+
+
+
+
diff --git a/src/bsv/bsv_lib/sd/sd_defines.h b/src/bsv/bsv_lib/sd/sd_defines.h
new file mode 100644 (file)
index 0000000..87d8133
--- /dev/null
@@ -0,0 +1,105 @@
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+//// 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
diff --git a/src/bsv/bsv_lib/sd/sd_top.sv b/src/bsv/bsv_lib/sd/sd_top.sv
new file mode 100644 (file)
index 0000000..fad49e3
--- /dev/null
@@ -0,0 +1,174 @@
+// 
+// (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