All checks were successful
ci/woodpecker/push/test-workflow Pipeline was successful
The audio output is still messed up, but this commit gets everything as ready as it can get. Fixed up all the testbenches and added state machines for everything
162 lines
8.4 KiB
Plaintext
162 lines
8.4 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"]
|
|
|
|
// Send CMD55+CMD41 with arg 40100000 until card is ready
|
|
SEND2_CMD55 [label="SEND2_CMD55\ncmd=55\nstart=1"];
|
|
WAIT2_CMD55 [label="WAIT2_CMD55\nstart=0"];
|
|
LISTEN_RESPONSE2_CMD55 [label="LISTEN_RESPONSE2_CMD55\nresponse_type=1\nread_command.listen=1"]
|
|
WAIT_RESPONSE2_CMD55 [label="WAIT_RESPONSE2_CMD55\nread_command.listen=0"]
|
|
SEND_ACMD6[label="SEND_ACMD6\ncmd=6\narg=0x00000002\nstart=1"];
|
|
WAIT_ACMD6 [label="WAIT_ACMD6\nstart=0"];
|
|
LISTEN_RESPONSE_ACMD6 [label="LISTEN_RESPONSE_ACMD6\nresponse_type=1\nread_command.listen=1"]
|
|
WAIT_RESPONSE_ACMD6 [label="WAIT_RESPONSE_ACMD6\nread_command.listen=0\ncounter=100"];
|
|
|
|
WAIT_RESPONSE_CMD7 -> SEND2_CMD55 [label="read_command.received"]
|
|
SEND2_CMD55 -> WAIT2_CMD55;
|
|
WAIT2_CMD55 -> WAIT2_CMD55 [label="!send_command.ready"];
|
|
WAIT2_CMD55 -> LISTEN_RESPONSE2_CMD55 [label="send_command.ready"];
|
|
LISTEN_RESPONSE2_CMD55 -> WAIT_RESPONSE2_CMD55;
|
|
WAIT_RESPONSE2_CMD55 -> WAIT_RESPONSE2_CMD55 [label="!read_command.received"]
|
|
WAIT_RESPONSE2_CMD55 -> SEND_ACMD6 [label="read_command.received"]
|
|
SEND_ACMD6 -> WAIT_ACMD6
|
|
WAIT_ACMD6 -> WAIT_ACMD6 [label="!send_command.ready"]
|
|
WAIT_ACMD6 -> LISTEN_RESPONSE_ACMD6[label="send_command.ready"]
|
|
LISTEN_RESPONSE_ACMD6 -> WAIT_RESPONSE_ACMD6
|
|
WAIT_RESPONSE_ACMD6 -> WAIT_RESPONSE_ACMD6 [label="!read_command.received"]
|
|
|
|
// 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\ncounter=100"];
|
|
DELAY_CLOCK_SWITCH [label="DELAY_CLOCK_SWITCH\ncounter--"]
|
|
// 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_ACMD6 -> READY_TO_TRANSMIT [label="read_command.ready"]
|
|
READY_TO_TRANSMIT -> DELAY_CLOCK_SWITCH;
|
|
DELAY_CLOCK_SWITCH -> TRANSMIT [label="counter==0"];
|
|
DELAY_CLOCK_SWITCH -> DELAY_CLOCK_SWITCH [label="counter!=0"];
|
|
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"];
|
|
}
|