aboutsummaryrefslogtreecommitdiffstats
path: root/hdl/sdio_to_spi.v
diff options
context:
space:
mode:
Diffstat (limited to 'hdl/sdio_to_spi.v')
-rw-r--r--hdl/sdio_to_spi.v235
1 files changed, 235 insertions, 0 deletions
diff --git a/hdl/sdio_to_spi.v b/hdl/sdio_to_spi.v
new file mode 100644
index 0000000..6e83ca0
--- /dev/null
+++ b/hdl/sdio_to_spi.v
@@ -0,0 +1,235 @@
+`timescale 1ns / 1ps
+
+module sdio_to_spi (
+ input wire sd_clk,
+ inout wire sd_cmd,
+ inout wire [3:0] sd_dat,
+
+ output reg sd_cmd_dir,
+ output reg [3:0] sd_dat_dir,
+
+ input wire clk_sys,
+ input wire rst_n,
+
+ output reg [7:0] cmd_opcode,
+ output reg [31:0] cmd_address,
+ output reg [15:0] cmd_length,
+ output reg cmd_valid,
+ input wire cmd_ready,
+
+ output reg [7:0] data_out,
+ output reg data_out_valid,
+ input wire data_out_ready,
+
+ input wire [7:0] data_in,
+ input wire data_in_valid,
+ output reg data_in_ready,
+
+ output reg [3:0] sdio_state,
+ output reg [3:0] status_reg
+);
+
+ localparam CMD0_GO_IDLE_STATE = 6'h00;
+ localparam CMD2_ALL_SEND_CID = 6'h02;
+ localparam CMD3_SEND_RELATIVE_ADDR = 6'h03;
+ localparam CMD7_SELECT_CARD = 6'h07;
+ localparam CMD8_SEND_IF_COND = 6'h08;
+ localparam CMD9_SEND_CSD = 6'h09;
+ localparam CMD12_STOP_TRANSMISSION = 6'h0C;
+ localparam CMD16_SET_BLOCKLEN = 6'h10;
+ localparam CMD17_READ_SINGLE_BLOCK = 6'h11;
+ localparam CMD18_READ_MULTIPLE_BLOCK = 6'h12;
+ localparam CMD24_WRITE_BLOCK = 6'h18;
+ localparam CMD25_WRITE_MULTIPLE_BLOCK = 6'h19;
+ localparam CMD55_APP_CMD = 6'h37;
+ localparam ACMD41_SD_SEND_OP_COND = 6'h29;
+
+ localparam STATE_IDLE = 4'h0;
+ localparam STATE_CMD_RX = 4'h1;
+ localparam STATE_CMD_PROCESS = 4'h2;
+ localparam STATE_RESP_TX = 4'h3;
+ localparam STATE_DATA_RX = 4'h4;
+ localparam STATE_DATA_TX = 4'h5;
+ localparam STATE_WAIT_SPI = 4'h6;
+ localparam STATE_ERROR = 4'h7;
+
+ localparam SPI_READ = 8'h03;
+ localparam SPI_FAST_READ = 8'h0B;
+ localparam SPI_PP = 8'h02;
+ localparam SPI_SE = 8'h20;
+ localparam SPI_BE = 8'hD8;
+ localparam SPI_CE = 8'hC7;
+ localparam SPI_RDSR = 8'h05;
+ localparam SPI_WREN = 8'h06;
+ localparam SPI_RDID = 8'h9F;
+
+ reg [47:0] cmd_reg;
+ reg [5:0] cmd_index;
+ reg cmd_start;
+ reg cmd_done;
+
+ reg [135:0] resp_reg;
+ reg [6:0] resp_bit_count;
+ reg resp_start;
+ reg resp_done;
+
+ reg [31:0] block_size;
+ reg [31:0] rca;
+ reg card_selected;
+ reg [3:0] dat_bus_width;
+
+ reg [15:0] data_counter;
+ reg [7:0] crc7;
+ reg [15:0] crc16;
+
+ always @(posedge sd_clk or negedge rst_n) begin
+ if (!rst_n) begin
+ cmd_reg <= 48'h0;
+ cmd_index <= 6'd0;
+ cmd_start <= 1'b0;
+ cmd_done <= 1'b0;
+ sd_cmd_dir <= 1'b1;
+ sdio_state <= STATE_IDLE;
+ end else begin
+ case (sdio_state)
+ STATE_IDLE: begin
+ cmd_start <= 1'b0;
+ cmd_done <= 1'b0;
+ sd_cmd_dir <= 1'b1;
+
+ if (sd_cmd === 1'b0) begin
+ sdio_state <= STATE_CMD_RX;
+ cmd_index <= 6'd1;
+ cmd_reg <= 48'h0;
+ end
+ end
+
+ STATE_CMD_RX: begin
+ if (cmd_index < 6'd48) begin
+ cmd_reg[47] <= sd_cmd;
+ cmd_reg <= cmd_reg << 1;
+ cmd_index <= cmd_index + 1;
+ end else begin
+ sdio_state <= STATE_CMD_PROCESS;
+ cmd_start <= 1'b1;
+ cmd_done <= 1'b0;
+ end
+ end
+
+ STATE_CMD_PROCESS: begin
+ cmd_start <= 1'b0;
+ if (cmd_ready && cmd_valid) begin
+ sdio_state <= STATE_RESP_TX;
+ resp_start <= 1'b1;
+ end
+ end
+
+ STATE_RESP_TX: begin
+ resp_start <= 1'b0;
+ sd_cmd_dir <= 1'b0;
+ if (resp_done) begin
+ if (cmd_reg[45:40] == CMD17_READ_SINGLE_BLOCK ||
+ cmd_reg[45:40] == CMD18_READ_MULTIPLE_BLOCK) begin
+ sdio_state <= STATE_DATA_TX;
+ end else if (cmd_reg[45:40] == CMD24_WRITE_BLOCK ||
+ cmd_reg[45:40] == CMD25_WRITE_MULTIPLE_BLOCK) begin
+ sdio_state <= STATE_DATA_RX;
+ end else begin
+ sdio_state <= STATE_IDLE;
+ end
+ end
+ end
+
+ STATE_DATA_RX: begin
+ end
+
+ STATE_DATA_TX: begin
+ end
+
+ STATE_WAIT_SPI: begin
+ end
+
+ STATE_ERROR: begin
+ end
+ endcase
+ end
+ end
+
+ always @(*) begin
+ cmd_valid = 1'b0;
+ cmd_opcode = 8'h00;
+ cmd_address = 32'h0;
+ cmd_length = 16'h0;
+
+ if (cmd_start && !cmd_done) begin
+ case (cmd_reg[45:40])
+ CMD17_READ_SINGLE_BLOCK: begin
+ cmd_valid = 1'b1;
+ cmd_opcode = SPI_READ;
+ cmd_address = cmd_reg[39:8];
+ cmd_length = block_size;
+ end
+
+ CMD24_WRITE_BLOCK: begin
+ cmd_valid = 1'b1;
+ cmd_opcode = SPI_PP;
+ cmd_address = cmd_reg[39:8];
+ cmd_length = block_size;
+ end
+
+ CMD9_SEND_CSD: begin
+ cmd_valid = 1'b0;
+ end
+
+ CMD2_ALL_SEND_CID: begin
+ cmd_valid = 1'b0;
+ end
+
+ default: begin
+ cmd_valid = 1'b0;
+ end
+ endcase
+ end
+ end
+
+ always @(posedge sd_clk) begin
+ if (resp_start) begin
+ case (cmd_reg[45:40])
+ CMD0_GO_IDLE_STATE: begin
+ resp_reg <= {136{1'b1}};
+ end
+
+ CMD8_SEND_IF_COND: begin
+ resp_reg <= {8'hAA, 24'h0, 8'h01};
+ end
+
+ CMD17_READ_SINGLE_BLOCK,
+ CMD24_WRITE_BLOCK: begin
+ resp_reg <= {8'h00, 120'h0};
+ end
+
+ default: begin
+ resp_reg <= {136{1'b1}};
+ end
+ endcase
+ end
+ end
+
+ always @(posedge sd_clk) begin
+ if (!rst_n) begin
+ data_out_valid <= 1'b0;
+ data_in_ready <= 1'b0;
+ sd_dat_dir <= 4'b1111;
+ end else begin
+ end
+ end
+
+ initial begin
+ block_size = 32'd512;
+ rca = 32'h00010000;
+ card_selected = 1'b0;
+ dat_bus_width = 4'b0001;
+ status_reg = 4'b0000;
+ end
+
+endmodule \ No newline at end of file