139 lines
3.3 KiB
Systemverilog
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
|