SDVD/design/sd/read_command.sv
2025-06-10 02:51:18 -07:00

139 lines
3.3 KiB
Systemverilog

/****
* 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