Add logic to store and readback data from SD card

After a data read (e.g. CMD17) the data received from the SD card is
stored into a buffer which can be read back one byte at a time by the
CPU through address 5.

There is also a flag which is set when data is received. This can be
checked by reading the CMD register, which doubles as the status
register.
This commit is contained in:
Byron Lathi
2022-04-11 13:57:56 -05:00
parent 51c348bc7c
commit 87d1457d94
2 changed files with 277 additions and 5 deletions

View File

@@ -23,6 +23,12 @@ logic [5:0] cmd;
logic [47:0] rxcmd_buf;
logic [31:0] rx_val;
logic [7:0] rxdata_buf [512];
logic [9:0] data_count;
logic [15:0] data_crc;
assign rx_val = rxcmd_buf[39:8];
always_comb begin
@@ -31,29 +37,36 @@ always_comb begin
if (addr < 4'h4) begin
data_out = rx_val[8 * addr +: 8];
end else if (addr == 4'h4) begin
data_out = read_flag;
data_out = {data_flag, read_flag};
end else if (addr == 4'h5) begin
data_out = rxdata_buf[data_count];
end
end
logic read_flag, next_read_flag;
logic data_flag, next_data_flag;
typedef enum bit [2:0] {IDLE, LOAD, CRC, TXCMD, RXCMD} macro_t;
typedef enum bit [2:0] {IDLE, LOAD, CRC, TXCMD, RXCMD, TXDATA, RXDATA, RXDCRC} macro_t;
struct packed {
macro_t macro;
logic [5:0] count;
logic [8:0] count;
logic [2:0] d_bit_count;
} state, next_state;
always_ff @(posedge clk) begin
if (rst) begin
state.macro <= IDLE;
state.count <= '0;
state.d_bit_count <= '1;
read_flag <= '0;
data_flag <= '0;
data_count <= '0;
end else begin
if (state.macro == TXCMD || state.macro == CRC) begin
if (sd_clk) begin
state <= next_state;
end
end else if (state.macro == RXCMD) begin
end else if (state.macro == RXCMD || state.macro == RXDATA || state.macro == RXDCRC) begin
if (~sd_clk) begin
state <= next_state;
end
@@ -64,6 +77,7 @@ always_ff @(posedge clk) begin
if (sd_clk) begin
read_flag <= next_read_flag;
data_flag <= next_data_flag;
end
if (cs & ~rw) begin
@@ -73,9 +87,23 @@ always_ff @(posedge clk) begin
cmd <= data;
end
end
if (cs & addr == 4'h5 && sd_clk) begin
data_count <= data_count + 1;
end
if (state.macro == RXCMD) begin
rxcmd_buf[6'd46-state.count] <= i_sd_cmd; //we probabily missed bit 47
end
if (state.macro == RXDATA && ~sd_clk) begin
rxdata_buf[state.count][state.d_bit_count] <= i_sd_data;
end
if (state.macro == RXDCRC && ~sd_clk) begin
data_crc[4'd15-state.count] <= i_sd_data;
end
end
logic [6:0] crc;
@@ -98,6 +126,7 @@ crc7 u_crc7(
always_comb begin
next_state = state;
next_read_flag = read_flag;
next_data_flag = data_flag;
case (state.macro)
IDLE: begin
@@ -105,6 +134,10 @@ always_comb begin
next_state.macro = RXCMD;
end
if (~i_sd_data) begin
next_state.macro = RXDATA;
end
if (addr == 4'h4 & cs & ~rw) begin // transmit if cpu writes to cmd
next_state.macro = LOAD;
end
@@ -112,6 +145,10 @@ always_comb begin
if (addr == 4'h4 & cs & rw) begin
next_read_flag = '0;
end
if (addr == 4'h5 & cs) begin
next_data_flag = '0;
end
end
LOAD: begin
@@ -140,6 +177,28 @@ always_comb begin
next_state.count = '0;
end
end
RXDATA: begin
if (state.count < 511 || (state.count == 511 && state.d_bit_count > 0)) begin
if (state.d_bit_count == 8'h0) begin
next_state.count = state.count + 9'b1;
end
next_state.d_bit_count = state.d_bit_count - 8'h1;
end else begin
next_data_flag = '1;
next_state.macro = RXDCRC;
next_state.count = '0;
end
end
RXDCRC: begin
if (state.count < 16) begin
next_state.count = state.count + 9'b1;
end else begin
next_state.macro = IDLE;
next_state.count = '0;
end
end
endcase
end