mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-30 09:04:14 +01:00
247 lines
7.8 KiB
Verilog
247 lines
7.8 KiB
Verilog
module sd_regs (
|
|
input i_clk,
|
|
input i_reset,
|
|
|
|
output reg [1:0] o_sd_clk_config,
|
|
|
|
output reg [5:0] o_command_index,
|
|
output reg [31:0] o_command_argument,
|
|
output reg o_command_long_response,
|
|
output reg o_command_skip_response,
|
|
input [5:0] i_command_index,
|
|
input [31:0] i_command_response,
|
|
output reg o_command_start,
|
|
input i_command_busy,
|
|
input i_command_timeout,
|
|
input i_command_response_crc_error,
|
|
|
|
output reg o_dat_width,
|
|
output reg o_dat_direction,
|
|
output reg [6:0] o_dat_block_size,
|
|
output reg [7:0] o_dat_num_blocks,
|
|
output reg o_dat_start,
|
|
output reg o_dat_stop,
|
|
input i_dat_busy,
|
|
input i_dat_write_busy,
|
|
input i_dat_crc_error,
|
|
input i_dat_write_error,
|
|
input i_dat_write_ok,
|
|
|
|
output reg o_rx_fifo_flush,
|
|
output reg o_rx_fifo_pop,
|
|
input i_rx_fifo_empty,
|
|
input i_rx_fifo_full,
|
|
input i_rx_fifo_overrun,
|
|
input [8:0] i_rx_fifo_items,
|
|
input [31:0] i_rx_fifo_data,
|
|
|
|
output reg o_tx_fifo_flush,
|
|
output o_tx_fifo_push,
|
|
input i_tx_fifo_empty,
|
|
input i_tx_fifo_full,
|
|
input i_tx_fifo_underrun,
|
|
input [8:0] i_tx_fifo_items,
|
|
output [31:0] o_tx_fifo_data,
|
|
|
|
output [3:0] o_dma_bank,
|
|
output [23:0] o_dma_address,
|
|
output [14:0] o_dma_length,
|
|
input [3:0] i_dma_bank,
|
|
input [23:0] i_dma_address,
|
|
input [14:0] i_dma_left,
|
|
output o_dma_load_bank_address,
|
|
output o_dma_load_length,
|
|
output reg o_dma_direction,
|
|
output reg o_dma_start,
|
|
output reg o_dma_stop,
|
|
input i_dma_busy,
|
|
|
|
input i_request,
|
|
input i_write,
|
|
output o_busy,
|
|
output reg o_ack,
|
|
input [3:0] i_address,
|
|
output reg [31:0] o_data,
|
|
input [31:0] i_data
|
|
);
|
|
|
|
localparam [2:0] SD_REG_SCR = 3'd0;
|
|
localparam [2:0] SD_REG_ARG = 3'd1;
|
|
localparam [2:0] SD_REG_CMD = 3'd2;
|
|
localparam [2:0] SD_REG_RSP = 3'd3;
|
|
localparam [2:0] SD_REG_DAT = 3'd4;
|
|
localparam [2:0] SD_REG_DMA_SCR = 3'd5;
|
|
localparam [2:0] SD_REG_DMA_ADDR = 3'd6;
|
|
localparam [2:0] SD_REG_DMA_LEN = 3'd7;
|
|
|
|
wire w_write_request = i_request && i_write && !o_busy;
|
|
wire w_read_request = i_request && !i_write && !o_busy;
|
|
|
|
always @(*) begin
|
|
o_dma_bank = i_data[31:28];
|
|
o_dma_address = i_data[25:2];
|
|
o_dma_length = i_data[14:0];
|
|
o_dma_load_bank_address = w_write_request && !i_address[3] && (i_address[2:0] == SD_REG_DMA_ADDR);
|
|
o_dma_load_length = w_write_request && !i_address[3] && (i_address[2:0] == SD_REG_DMA_LEN);
|
|
o_tx_fifo_data = i_data;
|
|
o_tx_fifo_push = w_write_request && i_address[3] && !i_tx_fifo_full && !i_dma_busy;
|
|
o_busy = 1'b0;
|
|
end
|
|
|
|
always @(posedge i_clk) begin
|
|
o_command_start <= 1'b0;
|
|
o_dat_start <= 1'b0;
|
|
o_rx_fifo_flush <= 1'b0;
|
|
o_tx_fifo_flush <= 1'b0;
|
|
o_dma_start <= 1'b0;
|
|
o_dat_stop <= 1'b0;
|
|
o_dma_stop <= 1'b0;
|
|
|
|
if (i_reset) begin
|
|
o_sd_clk_config <= 2'd0;
|
|
o_dat_width <= 1'b0;
|
|
o_dat_direction <= 1'b0;
|
|
o_dat_block_size <= 7'd0;
|
|
o_dat_num_blocks <= 8'd0;
|
|
o_dma_direction <= 1'b0;
|
|
end else if (w_write_request) begin
|
|
if (!i_address[3]) begin
|
|
case (i_address[2:0])
|
|
SD_REG_SCR: begin
|
|
if (!i_command_busy && !i_dat_busy) begin
|
|
o_sd_clk_config <= i_data[1:0];
|
|
end
|
|
if (!i_dat_busy) begin
|
|
o_dat_width <= i_data[2];
|
|
end
|
|
end
|
|
|
|
SD_REG_ARG: begin
|
|
if (!i_command_busy) begin
|
|
o_command_argument <= i_data;
|
|
end
|
|
end
|
|
|
|
SD_REG_CMD: begin
|
|
if (!i_command_busy) begin
|
|
{
|
|
o_command_skip_response,
|
|
o_command_long_response,
|
|
o_command_start,
|
|
o_command_index
|
|
} <= i_data[8:0];
|
|
end
|
|
end
|
|
|
|
SD_REG_RSP: begin
|
|
end
|
|
|
|
SD_REG_DAT: begin
|
|
if (!i_dat_busy || i_data[1]) begin
|
|
{
|
|
o_tx_fifo_flush,
|
|
o_rx_fifo_flush,
|
|
o_dat_num_blocks,
|
|
o_dat_block_size,
|
|
o_dat_direction,
|
|
o_dat_stop,
|
|
o_dat_start
|
|
} <= i_data[19:0];
|
|
end
|
|
end
|
|
|
|
SD_REG_DMA_SCR: begin
|
|
if (!i_dma_busy || i_data[1]) begin
|
|
{
|
|
o_dma_direction,
|
|
o_dma_stop,
|
|
o_dma_start
|
|
} <= i_data[2:0];
|
|
end
|
|
end
|
|
|
|
SD_REG_DMA_ADDR: begin
|
|
end
|
|
|
|
SD_REG_DMA_LEN: begin
|
|
end
|
|
endcase
|
|
end
|
|
end
|
|
end
|
|
|
|
always @(posedge i_clk) begin
|
|
o_rx_fifo_pop <= 1'b0;
|
|
o_ack <= 1'b0;
|
|
|
|
if (i_reset) begin
|
|
o_data <= 32'h0000_0000;
|
|
end else if (w_read_request) begin
|
|
o_ack <= 1'b1;
|
|
|
|
if (!i_address[3]) begin
|
|
case (i_address[2:0])
|
|
SD_REG_SCR: begin
|
|
o_data <= {29'd0, o_dat_width, o_sd_clk_config};
|
|
end
|
|
|
|
SD_REG_ARG: begin
|
|
o_data <= o_command_argument;
|
|
end
|
|
|
|
SD_REG_CMD: begin
|
|
o_data <= {
|
|
23'd0,
|
|
i_command_response_crc_error,
|
|
i_command_timeout,
|
|
i_command_busy,
|
|
i_command_index
|
|
};
|
|
end
|
|
|
|
SD_REG_RSP: begin
|
|
o_data <= i_command_response;
|
|
end
|
|
|
|
SD_REG_DAT: begin
|
|
o_data <= {
|
|
3'd0,
|
|
i_dat_write_ok,
|
|
i_dat_write_error,
|
|
i_dat_write_busy,
|
|
i_tx_fifo_items,
|
|
i_tx_fifo_full,
|
|
i_tx_fifo_empty,
|
|
i_tx_fifo_underrun,
|
|
i_rx_fifo_items,
|
|
i_rx_fifo_full,
|
|
i_rx_fifo_empty,
|
|
i_rx_fifo_overrun,
|
|
i_dat_crc_error,
|
|
i_dat_busy
|
|
};
|
|
end
|
|
|
|
SD_REG_DMA_SCR: begin
|
|
o_data <= {29'd0, o_dma_direction, 1'b0, i_dma_busy};
|
|
end
|
|
|
|
SD_REG_DMA_ADDR: begin
|
|
o_data <= {i_dma_bank, 2'd0, i_dma_address, 2'b00};
|
|
end
|
|
|
|
SD_REG_DMA_LEN: begin
|
|
o_data <= {17'd0, i_dma_left};
|
|
end
|
|
endcase
|
|
end else begin
|
|
if (!i_rx_fifo_empty && !i_dma_busy) begin
|
|
o_rx_fifo_pop <= 1'b1;
|
|
end
|
|
o_data <= i_rx_fifo_data;
|
|
end
|
|
end
|
|
end
|
|
|
|
endmodule
|