114 lines
2.5 KiB
Systemverilog
114 lines
2.5 KiB
Systemverilog
/***
|
|
* send_command.sv - sends sd card commands. It takes in a command and an
|
|
* argument and will figure out the necessary crc.
|
|
*
|
|
* @author: Waylon Cude, Dilanthi Prentice
|
|
* @date: 6/12/2025
|
|
*
|
|
* */
|
|
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 wire sd_cmd
|
|
);
|
|
(* MARK_DEBUG = "TRUE" *)
|
|
logic [47:0] to_send;
|
|
|
|
logic crc_start;
|
|
wire crc_ready;
|
|
logic [6:0] crc;
|
|
|
|
logic [$clog2(48):0] counter;
|
|
|
|
(* MARK_DEBUG = "TRUE" *)
|
|
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 != 1)
|
|
next_state = SEND_DATA;
|
|
else
|
|
next_state = READY;
|
|
default:
|
|
next_state = READY;
|
|
endcase
|
|
|
|
end
|
|
|
|
assign sd_cmd = send_sd_cmd ? 'z : 0;
|
|
// BUG SPOTTED: Too slow, make the output more reactive
|
|
// Added start input check to achieve this
|
|
assign ready = (cur_state == READY && !start);
|
|
// 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;
|
|
end
|
|
else begin
|
|
cur_state <= next_state;
|
|
end
|
|
end
|
|
|
|
|
|
endmodule
|