/****
 * read_command.sv - reads the sd command line and listens for sd command
 *                   responses.
 * 
 * @author: Waylon Cude, Dilanthi Prentice
 * @date: 6/12/2025
 *
 * **/
module read_command(
    input logic clk,
    input logic reset,
    input logic listen,
    // 8 types of responses??? so hard to tell
    input logic[2:0] response_type,
    input logic sd_cmd,
    output logic received,
    // This has to be large enough to capture each possible response
    output logic [135:0] out_data
);

enum logic [2:0] {IDLE,START,LISTEN,RECEIVING,DONE} state, next_state;

// This should be large enough to capture the largest 136-bit response
logic [$clog2(136):0] counter;
logic [135:0] data_reg;
logic received_reg;

logic [2:0] response_type_reg;

// recevied was set a cycle before the data was actually ready
// and if it's just a register it holds for too long
// use both for maximum reactivity
assign received = received_reg && !listen;

always_comb begin
    case (state)
        IDLE:
            if (listen)
                next_state=START;
            else
                next_state=IDLE;
        START:
            if (sd_cmd == 0)
                next_state=RECEIVING;
            else
                next_state=LISTEN;
        LISTEN:
            // check for the start bit
            if (sd_cmd == 0)
                next_state=RECEIVING;
            else
                next_state=LISTEN;
        RECEIVING:
            if (counter == 0)
                next_state=DONE;
            else
                next_state=RECEIVING;
        DONE:
            if (listen)
                next_state=START;
            else
                next_state=DONE;
        default:
            next_state=IDLE;
    endcase
end

always_ff @(posedge clk) begin
    case (state)
        IDLE:
        begin
            // This defaulted to 1 ... oops
            received_reg <= 0;
            out_data <= 0;
            if (listen)
                response_type_reg <= response_type;
        end

        START:
        begin
            received_reg <= 0;
            // off-by-one/cycle timing issues accumulated to a counter offset
            // of 3.
            // 3 in simulation, 2 in reality????
            counter <= get_bits(response_type_reg) - 2;
            data_reg <= 0;
        end

        LISTEN: 
            // This is kinda a hack
            // I don't fully understand why the receiving state misses two
            // whole bits, I get why it misses the first but not the second...
            data_reg[0] <= sd_cmd;

        RECEIVING:
        begin
            counter <= counter - 1;
            data_reg <= {data_reg[134:0],sd_cmd};
        end

        DONE:
        begin
            out_data <= data_reg;
            received_reg <= 1;
            if (listen) begin
                received_reg <= 0;
                response_type_reg <= response_type;
            end
        end

        default: ;

    endcase

end

always_ff @(posedge clk) begin
    if (reset)
        state<=IDLE;
    else
        state<=next_state;
end


function automatic logic [$clog2(136):0] get_bits(logic [2:0] response);
    case (response)
        // Response 2 is extra long
        2: 
            return 136;
        // Most responses are 48 bits
        default:
            return 48;
    endcase
endfunction



endmodule
