Add SD Card controller for sending commands

Adds the start of the SD card controller which is capable of sending
commands using the SD protocol.

It is accessed by writing the arguments first and triggered by writing
the command number.
This commit is contained in:
Byron Lathi
2022-04-08 12:28:17 -05:00
parent 552fe8b6f8
commit f89ecfa038
2 changed files with 125 additions and 0 deletions

124
hw/fpga/sd_controller.sv Normal file
View File

@@ -0,0 +1,124 @@
module sd_controller(
input clk,
input rst,
input [3:0] addr,
input [7:0] data,
input cs,
input i_sd_cmd,
output logic o_sd_cmd,
input i_sd_data,
output logic o_sd_dat
);
logic [31:0] arg;
logic [5:0] cmd;
logic [47:0] rxcmd_buf;
typedef enum bit [1:0] {IDLE, CRC, TXCMD, RXCMD} macro_t;
struct packed {
macro_t macro;
logic [5:0] count;
} state, next_state;
always_ff @(posedge clk) begin
if (rst) begin
state.macro <= IDLE;
state.count <= '0;
end else begin
state <= next_state;
end
if (state.macro == IDLE) begin
if (cs) begin
if (addr < 4'h4) begin
arg[8 * addr +: 8] <= data;
end else if (addr == 4'h4) begin
cmd <= data;
end
end
end else if (state.macro == RXCMD) begin
rxcmd_buf[6'd46-state.count] <= i_sd_cmd; //we probabily missed bit 47
end
end
logic [6:0] crc;
logic load_crc;
logic crc_valid;
logic [39:0] _packet;
assign _packet = {1'b0, 1'b1, cmd, arg};
logic [47:0] packet_crc;
assign packet_crc = {_packet, crc, 1'b1};
crc7 u_crc7(
.clk(clk),
.rst(rst),
.load(load_crc),
.data_in(_packet),
.crc_out(crc),
.valid(crc_valid)
);
always_comb begin
next_state = state;
case (state.macro)
IDLE: begin
if (~i_sd_cmd) begin // receive data if sd pulls cmd low
next_state.macro = RXCMD;
end
if (addr == 4'h4 & cs) begin // transmit if cpu writes to cmd
next_state.macro = CRC;
end
end
CRC: begin
next_state.macro = TXCMD;
end
TXCMD: begin
if (state.count < 47) begin
next_state.count = state.count + 6'b1;
end else begin
next_state.macro = IDLE;
next_state.count = '0;
end
end
RXCMD: begin
if (state.count < 47) begin
next_state.count = state.count + 6'b1;
end else begin
next_state.macro = IDLE;
next_state.count = '0;
end
end
endcase
end
always_comb begin
o_sd_cmd = '1; //default to 1
o_sd_dat = '1;
load_crc = '0;
case (state.macro)
IDLE:;
CRC: begin
load_crc = '1;
end
TXCMD: begin
o_sd_cmd = packet_crc[6'd47 - state.count];
end
RXCMD:;
endcase
end
endmodule

View File

@@ -350,6 +350,7 @@ set_location_assignment PIN_V22 -to DRAM_LDQM
set_location_assignment PIN_U22 -to DRAM_RAS_N
set_location_assignment PIN_J21 -to DRAM_UDQM
set_location_assignment PIN_V20 -to DRAM_WE_N
set_global_assignment -name SYSTEMVERILOG_FILE sd_controller.sv
set_global_assignment -name SYSTEMVERILOG_FILE crc7.sv
set_global_assignment -name SYSTEMVERILOG_FILE memory_mapper.sv
set_global_assignment -name SYSTEMVERILOG_FILE board_io.sv