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