Fix state transitions with regard to clock

The SD card expects data to transition on falling edges and be stable on
rising edges.

Additionally, writes from the CPU were not handled with correct timing.

Now, there is an extra state when writing to the command register so
that the command is properly latched before the CRC is calculated.
This commit is contained in:
Byron Lathi
2022-04-10 17:52:07 -05:00
parent 50b0860137
commit 1128b986eb

View File

@@ -1,16 +1,18 @@
module sd_controller(
input clk,
input sd_clk,
input rst,
input [2:0] addr,
input [7:0] data,
input cs,
input rw,
input i_sd_cmd,
output logic o_sd_cmd,
input i_sd_data,
output logic o_sd_dat
output logic o_sd_data
);
logic [31:0] arg;
@@ -18,7 +20,7 @@ logic [5:0] cmd;
logic [47:0] rxcmd_buf;
typedef enum bit [1:0] {IDLE, CRC, TXCMD, RXCMD} macro_t;
typedef enum bit [2:0] {IDLE, LOAD, CRC, TXCMD, RXCMD} macro_t;
struct packed {
macro_t macro;
logic [5:0] count;
@@ -29,18 +31,23 @@ always_ff @(posedge clk) begin
state.macro <= IDLE;
state.count <= '0;
end else begin
state <= next_state;
if (state.macro == TXCMD || state.macro == CRC) begin
if (sd_clk) begin
state <= next_state;
end
end else begin
state <= next_state;
end
end
if (state.macro == IDLE) begin
if (cs) begin
if (addr < 4'h4) begin
arg[8 * addr +: 8] <= data;
end else if (addr == 4'h4) begin
cmd <= data;
end
if (cs & ~rw) begin
if (addr < 4'h4) begin
arg[8 * addr +: 8] <= data;
end else if (addr == 4'h4) begin
cmd <= data;
end
end else if (state.macro == RXCMD) begin
end
if (state.macro == RXCMD) begin
rxcmd_buf[6'd46-state.count] <= i_sd_cmd; //we probabily missed bit 47
end
end
@@ -71,11 +78,15 @@ always_comb begin
next_state.macro = RXCMD;
end
if (addr == 4'h4 & cs) begin // transmit if cpu writes to cmd
next_state.macro = CRC;
if (addr == 4'h4 & cs & ~rw) begin // transmit if cpu writes to cmd
next_state.macro = LOAD;
end
end
LOAD: begin
next_state.macro = CRC;
end
CRC: begin
next_state.macro = TXCMD;
end
@@ -102,7 +113,7 @@ end
always_comb begin
o_sd_cmd = '1; //default to 1
o_sd_dat = '1;
o_sd_data = '1;
load_crc = '0;