Demo commit
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
This commit is contained in:
2025-06-10 13:26:35 -07:00
parent fe227d1b61
commit f840d27b8e
27 changed files with 1300 additions and 274 deletions
+19 -15
View File
@@ -4,8 +4,7 @@
module read_data(
input clk,
input reset,
input sd_data,
(* MARK_DEBUG = "TRUE" *)
input [3:0] sd_data,
audio_buffer_interface.driver buffer
);
// Block data is a start bit, 512 bytes sent msb first, then a CRC16 and end
@@ -16,7 +15,7 @@ module read_data(
// played. However, as long as the sd card controller doesn't request extra
// blocks this shouldn't be an issue
localparam BLOCK_SIZE=512*8+16+2;
localparam BLOCK_SIZE=512*2+16*4+2;
logic [$clog2(BLOCK_SIZE):0] counter;
logic [7:0] byte_shift;
@@ -28,36 +27,41 @@ assign buffer.clka = clk;
always_ff @(posedge clk) begin
if (reset) begin
buffer.ena <= 0;
buffer.addra <= '1;
// Start negative so adding bytes will get us to the right address
buffer.addra <= 0 - 512;
buffer.dina <= 0;
end
else begin
// We ignore the lower 17 bits of the block
if (counter > 16) begin
// We ignore the lower 16*4+1 bits of the block
// CRC is apparently sent on each line, back to back
if (counter > 16*4) begin
counter <= counter - 1;
byte_shift <= {byte_shift[6:0],sd_data};
byte_shift <= {byte_shift[3:0],sd_data};
byte_counter <= byte_counter - 1;
// Store received byte in audio buffer and reset counter
if (byte_counter == 0) begin
byte_counter <= 7;
buffer.dina <= byte_shift;//{byte_shift[6:0],sd_data};
byte_counter <= 1;
buffer.dina <= {byte_shift[3:0],sd_data};
buffer.ena <= 1;
end
// Turn the enable signal off so we don't accidentally write
// anything weird
if (byte_counter == 4) begin
buffer.ena <= 0;
buffer.addra <= buffer.addra + 1;
if (byte_counter == 1) begin
buffer.addra <= buffer.addra - 1;
end
end
else if (counter != 0)
else if (counter != 0) begin
counter<=counter-1;
buffer.ena <= 0;
end
else if (sd_data == 0) begin
counter <= BLOCK_SIZE-1;
byte_counter <= 8;
// In wide bus mode we read bytes in a descending order
buffer.addra <= buffer.addra + 1024;
counter <= BLOCK_SIZE;
byte_counter <= 3;
end
end
end
+64 -12
View File
@@ -14,7 +14,7 @@ module sd_controller(
input logic crc_clk,
input logic reset,
(* MARK_DEBUG = "TRUE" *)
input logic sd_data,
input logic [3:0] sd_data,
inout logic sd_cmd,
output logic ready,
output wire clk,
@@ -22,7 +22,6 @@ module sd_controller(
audio_buffer_interface.driver buffer
);
// NOTE: this gets encoded as one-hot, even if in here I set it as a logic[5:0]
(* MARK_DEBUG = "TRUE" *)
enum logic [5:0] {
INIT,WAIT,SEND_CMD0,WAIT_CMD0,DELAY_CMD0, // last 4
SEND_CMD8,WAIT_CMD8,LISTEN_RESPONSE_CMD8,WAIT_RESPONSE_CMD8, // last 8
@@ -31,13 +30,15 @@ enum logic [5:0] {
SEND_CMD2,WAIT_CMD2,LISTEN_RESPONSE_CMD2,WAIT_RESPONSE_CMD2, //21
SEND_CMD3,WAIT_CMD3,LISTEN_RESPONSE_CMD3,WAIT_RESPONSE_CMD3, //25
SEND_CMD7,WAIT_CMD7,LISTEN_RESPONSE_CMD7,WAIT_RESPONSE_CMD7, //29
SEND2_CMD55,WAIT2_CMD55,LISTEN_RESPONSE2_CMD55,WAIT_RESPONSE2_CMD55,
SEND_ACMD6,WAIT_ACMD6,LISTEN_RESPONSE_ACMD6,WAIT_RESPONSE_ACMD6,
READY_TO_TRANSMIT,
DELAY_CLOCK_SWITCH,
TRANSMIT,WAIT_TRANSMIT,WAIT_END,FINISH_TRANSMIT,
TRANSMIT2,WAIT_TRANSMIT2,WAIT_END2,FINISH_TRANSMIT2,
WAIT_FOR_BUFFER
} state, next_state;
(* MARK_DEBUG = "TRUE" *)
logic fast_clk_enable;
assign clk = fast_clk_enable ? fast_clk : slow_clk;
@@ -49,7 +50,6 @@ logic [31:0] address;
logic send_command_start;//, send_command_start_fast;
(* MARK_DEBUG = "TRUE" *)
logic [5:0] cmd;
(* MARK_DEBUG = "TRUE" *)
logic [31:0] arg;
(* MARK_DEBUG = "TRUE" *)
wire send_command_ready;//, send_command_ready_fast;
@@ -189,7 +189,7 @@ always_comb begin
next_state=WAIT_RESPONSE_CMD7;
WAIT_RESPONSE_CMD7:
if (read_command_received)
next_state=READY_TO_TRANSMIT;
next_state=SEND2_CMD55;
else
next_state=WAIT_RESPONSE_CMD7;
@@ -230,8 +230,42 @@ always_comb begin
else
next_state=ACMD41_DELAY;
SEND2_CMD55:
next_state=WAIT2_CMD55;
WAIT2_CMD55:
if (send_command_ready)
next_state=LISTEN_RESPONSE2_CMD55;
else
next_state=WAIT2_CMD55;
LISTEN_RESPONSE2_CMD55:
next_state=WAIT_RESPONSE2_CMD55;
WAIT_RESPONSE2_CMD55:
if (read_command_received)
next_state=SEND_ACMD6;
else
next_state=WAIT_RESPONSE2_CMD55;
SEND_ACMD6:
next_state=WAIT_ACMD6;
WAIT_ACMD6:
if (send_command_ready)
next_state=LISTEN_RESPONSE_ACMD6;
else
next_state=WAIT_ACMD6;
LISTEN_RESPONSE_ACMD6:
next_state=WAIT_RESPONSE_ACMD6;
WAIT_RESPONSE_ACMD6:
if (read_command_received)
next_state=READY_TO_TRANSMIT;
else
next_state=WAIT_RESPONSE_ACMD6;
READY_TO_TRANSMIT:
next_state=TRANSMIT;
next_state=DELAY_CLOCK_SWITCH;
DELAY_CLOCK_SWITCH:
if (counter == 0)
next_state = TRANSMIT;
else
next_state = DELAY_CLOCK_SWITCH;
TRANSMIT:
next_state=WAIT_TRANSMIT;
WAIT_TRANSMIT:
@@ -310,7 +344,14 @@ always_ff @(posedge clk) begin
arg <= 0;
send_command_start <=1;
end
LISTEN_RESPONSE_CMD55: begin
SEND2_CMD55: begin
cmd <= 55;
// the arg should be the same as the preceding command
// and otherwise we'll lose the RCA bits
//arg <= 0;
send_command_start <=1;
end
LISTEN_RESPONSE_CMD55,LISTEN_RESPONSE2_CMD55: begin
response_type <= 1;
read_command_listen <= 1;
end
@@ -327,6 +368,15 @@ always_ff @(posedge clk) begin
read_command_listen<=0;
counter<=100;
end
SEND_ACMD6: begin
cmd <= 6;
arg <= 'b10;
send_command_start <=1;
end
LISTEN_RESPONSE_ACMD6: begin
response_type <= 1;
read_command_listen <= 1;
end
SEND_CMD2: begin
cmd <= 2;
arg <= 0;
@@ -358,6 +408,8 @@ always_ff @(posedge clk) begin
fast_clk_enable <= 1;
address <= 0;
sd_buffer_half <= 0;
// Wait to actually transmit until clock is running and stable
counter <= 100;
end
TRANSMIT, TRANSMIT2: begin
cmd <= 17;
@@ -366,7 +418,7 @@ always_ff @(posedge clk) begin
end
WAIT_TRANSMIT, WAIT_TRANSMIT2: begin
send_command_start <= 0;
counter <= 411;
counter <= 512*2+16+1;
end
FINISH_TRANSMIT:
address <= address +1;
@@ -377,12 +429,12 @@ always_ff @(posedge clk) begin
WAIT_FOR_BUFFER:
ready <= 1;
// The logic is simple enough in these to group them
WAIT, DELAY_CMD0, ACMD41_DELAY, WAIT_END, WAIT_END2:
WAIT, DELAY_CMD0, ACMD41_DELAY, WAIT_END, WAIT_END2, DELAY_CLOCK_SWITCH:
counter <= counter - 1;
WAIT_CMD8,WAIT_CMD55,WAIT_ACMD41,WAIT_CMD2,WAIT_CMD3,WAIT_CMD7:
WAIT_CMD8,WAIT_CMD55,WAIT_ACMD41,WAIT2_CMD55,WAIT_ACMD6,WAIT_CMD2,WAIT_CMD3,WAIT_CMD7:
send_command_start<=0;
WAIT_RESPONSE_CMD8,WAIT_RESPONSE_CMD55,WAIT_RESPONSE_CMD2,WAIT_RESPONSE_CMD3,
WAIT_RESPONSE_CMD7:
WAIT_RESPONSE_CMD8,WAIT_RESPONSE_CMD55,WAIT_RESPONSE2_CMD55,WAIT_RESPONSE_ACMD6,
WAIT_RESPONSE_CMD2,WAIT_RESPONSE_CMD3,WAIT_RESPONSE_CMD7:
read_command_listen<=0;
default: ;