SDVD/design/sd/send_command.sv
Waylon Cude e32563131f
All checks were successful
ci/woodpecker/push/test-workflow Pipeline was successful
Added command signal driver module
2025-06-06 20:49:18 -07:00

104 lines
2.2 KiB
Systemverilog

module send_command(
input clk,
// The crc should be clocked way faster than the sender
input crc_clk,
input reset,
input start,
input [5:0] command,
input [31:0] arguments,
output logic ready,
output logic sd_cmd
);
logic [47:0] to_send;
logic crc_start;
wire crc_ready;
logic [6:0] crc;
logic [$clog2(48):0] counter;
logic send_sd_cmd;
enum logic [2:0] {READY, SEND_CRC, DELAY, WAIT_CRC, SEND_DATA} cur_state, next_state;
// We theoretically could speed up sd card initialization by hardcoding the
// CRCs for it, but wasting an extra couple of cycles at 400khz shouldn't
// really matter
crc_gen crcGen(crc_clk,reset,crc_start,to_send[47-:40],crc_ready,crc);
// State transitions
always_comb begin
case (cur_state)
READY:
if (start)
next_state = SEND_CRC;
else
next_state = READY;
SEND_CRC:
next_state = DELAY;
DELAY:
next_state = WAIT_CRC;
WAIT_CRC:
if (crc_ready)
next_state = SEND_DATA;
else
next_state = WAIT_CRC;
SEND_DATA:
if (counter != 0)
next_state = SEND_DATA;
else
next_state = READY;
default:
next_state = READY;
endcase
end
assign sd_cmd = send_sd_cmd ? 'z : 0;
assign ready = (cur_state == READY);
// Sequential logic
always_ff @(posedge clk) begin
// Default to high-z
send_sd_cmd <= 1;
case (cur_state)
READY:
begin
counter <= 48;
end
SEND_CRC:
begin
to_send <= {1'b0, 1'b1, command, arguments, 8'b1};
crc_start <= 1;
end
DELAY:
crc_start <= 0;
WAIT_CRC:
to_send[7:1] <= crc;
SEND_DATA:
begin
counter <= counter - 1;
send_sd_cmd <= to_send[counter-1];
end
default: ;
endcase
end
always_ff @(posedge clk) begin
if (reset) begin
cur_state <= READY;
counter <= 48;
end
else begin
cur_state <= next_state;
end
end
endmodule