SummerCart64/fw/rtl/cart/cart_control.v

256 lines
7.3 KiB
Coq
Raw Normal View History

module cart_control (
input i_clk,
input i_reset,
input i_n64_reset,
input i_n64_nmi,
input i_request,
input i_write,
output o_busy,
output reg o_ack,
input [10:0] i_address,
output reg [31:0] o_data,
input [31:0] i_data,
output reg o_sdram_writable,
output reg o_rom_switch,
output reg o_ddipl_enable,
output reg o_sram_enable,
output reg o_flashram_enable,
output reg o_sd_enable,
output reg o_eeprom_pi_enable,
output reg o_eeprom_enable,
output reg o_eeprom_16k_mode,
2021-03-11 00:10:32 +01:00
inout [7:0] io_gpio,
input i_debug_ready,
output reg o_debug_dma_start,
input i_debug_dma_busy,
output reg [3:0] o_debug_dma_bank,
output reg [23:0] o_debug_dma_address,
output reg [19:0] o_debug_dma_length,
output reg o_debug_fifo_request,
output reg o_debug_fifo_flush,
input [10:0] i_debug_fifo_items,
input [31:0] i_debug_fifo_data,
output reg [23:0] o_ddipl_address,
2021-02-27 15:56:46 +01:00
output reg [23:0] o_save_address
);
// Module parameters
parameter byte VERSION = "a";
// Register offsets
localparam [3:0] REG_SCR = 4'd0;
localparam [3:0] REG_BOOT = 4'd1;
localparam [3:0] REG_VERSION = 4'd2;
localparam [3:0] REG_GPIO = 4'd3;
localparam [3:0] REG_USB_SCR = 4'd4;
localparam [3:0] REG_USB_DMA_ADDR = 4'd5;
localparam [3:0] REG_USB_DMA_LEN = 4'd6;
localparam [3:0] REG_DDIPL_ADDR = 4'd7;
2021-03-11 00:10:32 +01:00
localparam [3:0] REG_SAVE_ADDR = 4'd8;
localparam [10:0] MEM_USB_FIFO_BASE = 11'h400;
// Input synchronization
reg r_reset_ff1, r_reset_ff2;
reg r_nmi_ff1, r_nmi_ff2;
always @(posedge i_clk) begin
{r_reset_ff2, r_reset_ff1} <= {r_reset_ff1, i_n64_reset};
{r_nmi_ff2, r_nmi_ff1} <= {r_nmi_ff1, i_n64_nmi};
end
// Registers
reg [15:0] r_bootloader;
reg r_skip_bootloader;
2021-03-11 00:10:32 +01:00
reg r_sram_768k_mode;
reg [7:0] r_gpio_o;
reg [7:0] r_gpio_i;
reg [7:0] r_gpio_dir;
reg [7:0] r_gpio_od;
// Bus controller
assign o_busy = 1'b0;
always @(posedge i_clk) begin
o_ack <= !i_reset && i_request && !i_write && !o_busy;
end
// Write logic
always @(posedge i_clk) begin
o_debug_dma_start <= 1'b0;
o_debug_fifo_flush <= 1'b0;
if (i_reset) begin
o_sdram_writable <= 1'b0;
o_rom_switch <= 1'b0;
o_ddipl_enable <= 1'b0;
o_sram_enable <= 1'b0;
o_flashram_enable <= 1'b0;
o_sd_enable <= 1'b0;
o_eeprom_pi_enable <= 1'b0;
o_eeprom_enable <= 1'b0;
o_eeprom_16k_mode <= 1'b0;
2021-02-27 15:56:46 +01:00
o_ddipl_address <= 24'hEF_8000;
o_save_address <= 24'hFF_8000;
o_debug_dma_bank <= 4'd1;
2021-02-27 15:56:46 +01:00
o_debug_dma_address <= 24'hCF_8000;
o_debug_dma_length <= 20'd0;
r_bootloader <= 16'h0000;
r_skip_bootloader <= 1'b0;
2021-03-11 00:10:32 +01:00
r_sram_768k_mode <= 1'b0;
r_gpio_o <= 8'h00;
r_gpio_dir <= 8'h00;
r_gpio_od <= 8'h00;
end else begin
if (i_request && i_write && !o_busy) begin
case (i_address[3:0])
REG_SCR: begin
{
r_skip_bootloader,
2021-03-11 00:10:32 +01:00
o_sd_enable,
o_flashram_enable,
2021-03-11 00:10:32 +01:00
r_sram_768k_mode,
o_sram_enable,
o_eeprom_pi_enable,
o_eeprom_16k_mode,
o_eeprom_enable,
o_ddipl_enable,
2021-03-11 00:10:32 +01:00
o_sdram_writable,
o_rom_switch
} <= i_data[10:0];
end
2021-02-27 15:56:46 +01:00
REG_BOOT: begin
r_bootloader <= i_data[15:0];
end
2021-02-27 15:56:46 +01:00
REG_GPIO: begin
2021-03-11 00:10:32 +01:00
{r_gpio_od, r_gpio_dir, r_gpio_o} <= {i_data[31:16], i_data[7:0]};
end
2021-02-27 15:56:46 +01:00
REG_USB_SCR: begin
{o_debug_fifo_flush, o_debug_dma_start} <= {i_data[2], i_data[0]};
end
2021-02-27 15:56:46 +01:00
REG_USB_DMA_ADDR: begin
{o_debug_dma_bank, o_debug_dma_address} <= {i_data[31:28], i_data[25:2]};
end
2021-02-27 15:56:46 +01:00
REG_USB_DMA_LEN: begin
o_debug_dma_length <= i_data[19:0];
end
2021-02-27 15:56:46 +01:00
REG_DDIPL_ADDR: begin
o_ddipl_address <= i_data[25:2];
end
2021-02-27 15:56:46 +01:00
2021-03-11 00:10:32 +01:00
REG_SAVE_ADDR: begin
2021-02-27 15:56:46 +01:00
o_save_address <= i_data[25:2];
end
2021-02-27 15:56:46 +01:00
default: begin end
endcase
end
if (!r_reset_ff2 || !r_nmi_ff2) begin
o_sdram_writable <= 1'b0;
o_rom_switch <= r_skip_bootloader;
o_debug_fifo_flush <= 1'b1;
end
end
end
// Read logic
always @(posedge i_clk) begin
o_debug_fifo_request <= 1'b0;
if (!i_reset && i_request && !i_write && !o_busy) begin
if (i_address < MEM_USB_FIFO_BASE) begin
o_data <= 32'h0000_0000;
case (i_address[3:0])
REG_SCR: begin
o_data[10:0] <= {
r_skip_bootloader,
2021-03-11 00:10:32 +01:00
o_sd_enable,
o_flashram_enable,
2021-03-11 00:10:32 +01:00
r_sram_768k_mode,
o_sram_enable,
o_eeprom_pi_enable,
o_eeprom_16k_mode,
o_eeprom_enable,
o_ddipl_enable,
2021-03-11 00:10:32 +01:00
o_sdram_writable,
o_rom_switch
};
end
2021-02-27 15:56:46 +01:00
REG_BOOT: begin
o_data[15:0] <= r_bootloader;
end
2021-02-27 15:56:46 +01:00
REG_VERSION: begin
o_data <= {"S", "6", "4", VERSION};
end
2021-02-27 15:56:46 +01:00
REG_GPIO: begin
2021-03-11 00:10:32 +01:00
o_data[31:0] <= {r_gpio_od, r_gpio_dir, io_gpio, r_gpio_o};
end
2021-02-27 15:56:46 +01:00
REG_USB_SCR: begin
{o_data[13:3], o_data[1:0]} <= {i_debug_fifo_items, i_debug_ready, i_debug_dma_busy};
end
2021-02-27 15:56:46 +01:00
REG_DDIPL_ADDR: begin
o_data[25:0] <= {o_ddipl_address, 2'b00};
end
2021-02-27 15:56:46 +01:00
2021-03-11 00:10:32 +01:00
REG_SAVE_ADDR: begin
2021-02-27 15:56:46 +01:00
o_data[25:0] <= {o_save_address, 2'b00};
end
2021-02-27 15:56:46 +01:00
default: begin end
endcase
end else begin
o_data <= i_debug_fifo_data;
o_debug_fifo_request <= 1'b1;
end
end
end
2021-03-11 00:10:32 +01:00
// GPIO logic
always @(*) begin
for (integer i = 0; i < 8; i = i + 1) begin
if (r_gpio_dir[i] && (!r_gpio_od[i] || (r_gpio_od[i] && !r_gpio_o[i]))) begin
io_gpio[i] = r_gpio_o[i];
end else begin
io_gpio[i] = 1'bZ;
end
end
end
endmodule