mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 15:16:53 +01:00
256 lines
7.3 KiB
Verilog
256 lines
7.3 KiB
Verilog
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,
|
|
|
|
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,
|
|
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;
|
|
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;
|
|
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;
|
|
o_ddipl_address <= 24'hEF_8000;
|
|
o_save_address <= 24'hFF_8000;
|
|
o_debug_dma_bank <= 4'd1;
|
|
o_debug_dma_address <= 24'hCF_8000;
|
|
o_debug_dma_length <= 20'd0;
|
|
r_bootloader <= 16'h0000;
|
|
r_skip_bootloader <= 1'b0;
|
|
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,
|
|
o_sd_enable,
|
|
o_flashram_enable,
|
|
r_sram_768k_mode,
|
|
o_sram_enable,
|
|
o_eeprom_pi_enable,
|
|
o_eeprom_16k_mode,
|
|
o_eeprom_enable,
|
|
o_ddipl_enable,
|
|
o_sdram_writable,
|
|
o_rom_switch
|
|
} <= i_data[10:0];
|
|
end
|
|
|
|
REG_BOOT: begin
|
|
r_bootloader <= i_data[15:0];
|
|
end
|
|
|
|
REG_GPIO: begin
|
|
{r_gpio_od, r_gpio_dir, r_gpio_o} <= {i_data[31:16], i_data[7:0]};
|
|
end
|
|
|
|
REG_USB_SCR: begin
|
|
{o_debug_fifo_flush, o_debug_dma_start} <= {i_data[2], i_data[0]};
|
|
end
|
|
|
|
REG_USB_DMA_ADDR: begin
|
|
{o_debug_dma_bank, o_debug_dma_address} <= {i_data[31:28], i_data[25:2]};
|
|
end
|
|
|
|
REG_USB_DMA_LEN: begin
|
|
o_debug_dma_length <= i_data[19:0];
|
|
end
|
|
|
|
REG_DDIPL_ADDR: begin
|
|
o_ddipl_address <= i_data[25:2];
|
|
end
|
|
|
|
REG_SAVE_ADDR: begin
|
|
o_save_address <= i_data[25:2];
|
|
end
|
|
|
|
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,
|
|
o_sd_enable,
|
|
o_flashram_enable,
|
|
r_sram_768k_mode,
|
|
o_sram_enable,
|
|
o_eeprom_pi_enable,
|
|
o_eeprom_16k_mode,
|
|
o_eeprom_enable,
|
|
o_ddipl_enable,
|
|
o_sdram_writable,
|
|
o_rom_switch
|
|
};
|
|
end
|
|
|
|
REG_BOOT: begin
|
|
o_data[15:0] <= r_bootloader;
|
|
end
|
|
|
|
REG_VERSION: begin
|
|
o_data <= {"S", "6", "4", VERSION};
|
|
end
|
|
|
|
REG_GPIO: begin
|
|
o_data[31:0] <= {r_gpio_od, r_gpio_dir, io_gpio, r_gpio_o};
|
|
end
|
|
|
|
REG_USB_SCR: begin
|
|
{o_data[13:3], o_data[1:0]} <= {i_debug_fifo_items, i_debug_ready, i_debug_dma_busy};
|
|
end
|
|
|
|
REG_DDIPL_ADDR: begin
|
|
o_data[25:0] <= {o_ddipl_address, 2'b00};
|
|
end
|
|
|
|
REG_SAVE_ADDR: begin
|
|
o_data[25:0] <= {o_save_address, 2'b00};
|
|
end
|
|
|
|
default: begin end
|
|
endcase
|
|
end else begin
|
|
o_data <= i_debug_fifo_data;
|
|
o_debug_fifo_request <= 1'b1;
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
// 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
|