SDVD/doc/sd_controller.gv
Waylon Cude fe227d1b61
All checks were successful
ci/woodpecker/push/test-workflow Pipeline was successful
Broken SD card
How tf did it break bro
2025-06-09 15:41:13 -07:00

137 lines
6.9 KiB
Plaintext

digraph sd_controller {
// Rough steps
INIT [shape=doublecircle, label="INIT\ncounter=80\nclk_source=slow"];
node [shape=ellipse]
// Tick at slow speed (100khz? 400khz?) for 80 ticks
WAIT [label="WAIT\ncounter--"];
// Send CMD0 with arg 0
SEND_CMD0 [label="SEND_CMD0\ncmd=0\narg=0\nstart=1"];
// There is no response to CMD0, so tick for 20 more cycles then send CMD8
WAIT_CMD0 [label="WAIT_CMD0\ncounter=20\nstart=0"];
DELAY_CMD0 [label="DELAY_CMD0\ncounter--"];
// Send CMD8
SEND_CMD8 [label="SEND_CMD8\ncmd=8\narg=0x1AA\nstart=1"];
WAIT_CMD8 [label="WAIT_CMD8\nstart=0"];
LISTEN_RESPONSE_CMD8 [label="LISTEN_RESPONSE_CMD8\nresponse_type=7\nread_command.listen=1"]
WAIT_RESPONSE_CMD8 [label="WAIT_RESPONSE_CMD8\nread_command.listen=0"];
INIT -> WAIT;
WAIT -> WAIT [label="counter!=0"];
WAIT -> SEND_CMD0 [label="counter==0"];
SEND_CMD0 -> WAIT_CMD0;
WAIT_CMD0 -> DELAY_CMD0 [label="send_command.ready"];
WAIT_CMD0 -> WAIT_CMD0 [label="!send_command.ready"]
DELAY_CMD0 -> DELAY_CMD0 [label="counter!=0"];
DELAY_CMD0 -> SEND_CMD8 [label="counter==0"]
SEND_CMD8 -> WAIT_CMD8;
WAIT_CMD8 -> WAIT_CMD8 [label="!send_command.ready"]
WAIT_CMD8 -> LISTEN_RESPONSE_CMD8 [label="send_command.ready"]
LISTEN_RESPONSE_CMD8 -> WAIT_RESPONSE_CMD8;
WAIT_RESPONSE_CMD8 -> WAIT_RESPONSE_CMD8 [label="!read_command.received"]
// Send CMD55+CMD41 with arg 40100000 until card is ready
SEND_CMD55 [label="SEND_CMD55\ncmd=55\narg=0\nstart=1"];
WAIT_CMD55 [label="WAIT_CMD55\nstart=0"];
LISTEN_RESPONSE_CMD55 [label="LISTEN_RESPONSE_CMD55\nresponse_type=1\nread_command.listen=1"]
WAIT_RESPONSE_CMD55 [label="WAIT_RESPONSE_CMD55\nread_command.listen=0"]
SEND_ACMD41 [label="SEND_ACMD41\ncmd=41\narg=0x40100000\nstart=1"];
WAIT_ACMD41 [label="WAIT_ACMD41\nstart=0"];
LISTEN_RESPONSE_ACMD41 [label="LISTEN_RESPONSE_ACMD41\nresponse_type=3\nread_command.listen=1"]
WAIT_RESPONSE_ACMD41 [label="WAIT_RESPONSE_ACMD41\nread_command.listen=0\ncounter=100"];
// Delay trying this again
ACMD41_DELAY [label="ACMD41_DELAY\ncounter--"];
// Card is ready when bit31 is high
WAIT_RESPONSE_CMD8 -> SEND_CMD55 [label="read_command.received"]
SEND_CMD55 -> WAIT_CMD55;
WAIT_CMD55 -> WAIT_CMD55 [label="!send_command.ready"];
WAIT_CMD55 -> LISTEN_RESPONSE_CMD55 [label="send_command.ready"];
LISTEN_RESPONSE_CMD55 -> WAIT_RESPONSE_CMD55;
WAIT_RESPONSE_CMD55 -> WAIT_RESPONSE_CMD55 [label="!read_command.received"]
WAIT_RESPONSE_CMD55 -> SEND_ACMD41 [label="read_command.received"]
SEND_ACMD41 -> WAIT_ACMD41
WAIT_ACMD41 -> WAIT_ACMD41 [label="!send_command.ready"]
WAIT_ACMD41 -> LISTEN_RESPONSE_ACMD41[label="send_command.ready"]
LISTEN_RESPONSE_ACMD41 -> WAIT_RESPONSE_ACMD41
WAIT_RESPONSE_ACMD41 -> WAIT_RESPONSE_ACMD41 [label="!read_command.received"]
WAIT_RESPONSE_ACMD41 -> ACMD41_DELAY [label="read_command.received && !out_data[39]"]
ACMD41_DELAY -> ACMD41_DELAY [label="counter!=0"]
ACMD41_DELAY -> SEND_CMD55 [label="counter==0"]
// CMD2 with argument 0, dont need response
SEND_CMD2 [label="SEND_CMD2\ncmd=2\narg=0\nsend_command.start=1"];
WAIT_CMD2 [label="WAIT_CMD2\nsend_command.start=0"];
LISTEN_RESPONSE_CMD2 [label="LISTEN_RESPONSE_CMD2\nresponse_type=2\nread_command.listen=1"];
WAIT_RESPONSE_CMD2 [label="WAIT_RESPONSE_CMD2\nread_command.listen=0"];
WAIT_RESPONSE_ACMD41 -> SEND_CMD2 [label="read_command.received && out_data[39]"]
SEND_CMD2 -> WAIT_CMD2;
WAIT_CMD2 -> WAIT_CMD2 [label="!send_command.ready"]
WAIT_CMD2 -> LISTEN_RESPONSE_CMD2 [label="send_command.ready"]
LISTEN_RESPONSE_CMD2 -> WAIT_RESPONSE_CMD2;
WAIT_RESPONSE_CMD2 -> WAIT_RESPONSE_CMD2 [label="!read_command.received"]
// CMD3 with argument 0 to get RCA
SEND_CMD3 [label="SEND_CMD3\ncmd=3\narg=0\nsend_command.start=1"];
WAIT_CMD3 [label="WAIT_CMD3\nsend_command.start=0"];
LISTEN_RESPONSE_CMD3 [label="LISTEN_RESPONSE_CMD3\nresponse_type=6\nread_command.listen=1"];
WAIT_RESPONSE_CMD3 [label="WAIT_RESPONSE_CMD3\nread_command.listen=0"];
WAIT_RESPONSE_CMD2 -> SEND_CMD3 [label="read_command.received"]
SEND_CMD3 -> WAIT_CMD3
WAIT_CMD3 -> WAIT_CMD3 [label="!send_command.ready"]
WAIT_CMD3 -> LISTEN_RESPONSE_CMD3 [label="send_command.ready"]
LISTEN_RESPONSE_CMD3 -> WAIT_RESPONSE_CMD3;
WAIT_RESPONSE_CMD3 -> WAIT_RESPONSE_CMD3 [label="!read_command.received"]
// CMD7 to select the correct card given the RCA
SEND_CMD7 [label="SEND_CMD7\ncmd=7\narg={out_data[39:24],16'h0000}\nsend_command.start=1"];
WAIT_CMD7 [label="WAIT_CMD7\nsend_command.start=0"];
LISTEN_RESPONSE_CMD7 [label="LISTEN_RESPONSE_CMD7\nresponse_type=1\nread_command.listen=1"];
WAIT_RESPONSE_CMD7 [label="WAIT_RESPONSE_CMD7\nread_command.listen=0"];
WAIT_RESPONSE_CMD3 -> SEND_CMD7[label="read_command.received"]
SEND_CMD7 -> WAIT_CMD7;
WAIT_CMD7 -> WAIT_CMD7 [label="!send_command.ready"]
WAIT_CMD7 -> LISTEN_RESPONSE_CMD7 [label="send_command.ready"]
LISTEN_RESPONSE_CMD7 -> WAIT_RESPONSE_CMD7;
WAIT_RESPONSE_CMD7 -> WAIT_RESPONSE_CMD7 [label="!read_command.ready"]
// Now we can finally read blocks with CMD17
// Swap over to the fast clock
READY_TO_TRANSMIT [label="READY_TO_TRANSMIT\nclk_source=fast\naddress=0\nbuffer_half=0"];
// There are two sets of states because we need to read two blocks at once
TRANSMIT [label="TRANSMIT\ncmd=17\narg=address\nsend_command.start=1"];
WAIT_TRANSMIT [label="WAIT_TRANSMIT\nsend_command.start=0\ncounter=4114"];
WAIT_END [label="WAIT_END\ncounter--"];
FINISH_TRANSMIT [label="FINISH_TRANSMIT\naddress++"]
TRANSMIT2 [label="TRANSMIT2\ncmd=17\narg=address\nsend_command.start=1"];
WAIT_TRANSMIT2 [label="WAIT_TRANSMIT2\nsend_command.start=0\ncounter=4114"];
WAIT_END2 [label="WAIT_END2\ncounter--"];
FINISH_TRANSMIT2 [label="FINISH_TRANSMIT2\naddress++\nsd_buffer_half=!sd_buffer_half"]
// Wait for the buffer to be free, then go back to TRANSMIT
WAIT_FOR_BUFFER [label="WAIT_FOR_BUFFER\nready=1"];
WAIT_RESPONSE_CMD7 -> READY_TO_TRANSMIT [label="read_command.ready"]
READY_TO_TRANSMIT -> TRANSMIT;
TRANSMIT -> WAIT_TRANSMIT;
WAIT_TRANSMIT -> WAIT_TRANSMIT [label="sd_data==1"]
WAIT_TRANSMIT -> WAIT_END [label="sd_data==0"]
WAIT_END -> WAIT_END [label="counter!=0"]
WAIT_END -> FINISH_TRANSMIT [label="counter==0"]
FINISH_TRANSMIT -> TRANSMIT2;
TRANSMIT2 -> WAIT_TRANSMIT2;
WAIT_TRANSMIT2 -> WAIT_TRANSMIT2 [label="sd_data==1"]
WAIT_TRANSMIT2 -> WAIT_END2 [label="sd_data==0"]
WAIT_END2 -> WAIT_END2 [label="counter!=0"]
WAIT_END2 -> FINISH_TRANSMIT2 [label="counter==0"]
FINISH_TRANSMIT2 -> WAIT_FOR_BUFFER;
WAIT_FOR_BUFFER -> WAIT_FOR_BUFFER [label="sd_buffer_half==audio_buffer.address_half"];
WAIT_FOR_BUFFER -> TRANSMIT [label="sd_buffer_half!=audio_buffer.address_half"];
}