mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-23 22:29:15 +01:00
554 lines
16 KiB
Verilog
554 lines
16 KiB
Verilog
`include "constants.vh"
|
|
|
|
module top (
|
|
input i_clk,
|
|
|
|
output o_ftdi_clk,
|
|
output o_ftdi_si,
|
|
input i_ftdi_so,
|
|
input i_ftdi_cts,
|
|
|
|
input i_n64_reset,
|
|
input i_n64_nmi,
|
|
|
|
input i_n64_pi_alel,
|
|
input i_n64_pi_aleh,
|
|
input i_n64_pi_read,
|
|
input i_n64_pi_write,
|
|
inout [15:0] io_n64_pi_ad,
|
|
|
|
input i_n64_si_clk,
|
|
inout io_n64_si_dq,
|
|
|
|
output o_sdram_clk,
|
|
output o_sdram_cs,
|
|
output o_sdram_ras,
|
|
output o_sdram_cas,
|
|
output o_sdram_we,
|
|
output [1:0] o_sdram_ba,
|
|
output [12:0] o_sdram_a,
|
|
inout [15:0] io_sdram_dq,
|
|
|
|
output o_sd_clk,
|
|
inout io_sd_cmd,
|
|
inout [3:0] io_sd_dat,
|
|
|
|
output o_sram_clk,
|
|
output o_sram_cs,
|
|
inout [3:0] io_sram_dq,
|
|
|
|
output o_rtc_scl,
|
|
inout io_rtc_sda,
|
|
|
|
output o_led,
|
|
|
|
inout [7:0] io_pmod
|
|
);
|
|
|
|
// Clock and reset signals
|
|
|
|
wire w_sys_clk;
|
|
wire w_sdram_clk;
|
|
wire w_pll_lock;
|
|
wire w_sys_reset = ~w_pll_lock;
|
|
|
|
|
|
// Temporary signal names
|
|
|
|
wire w_n64_reset_btn;
|
|
|
|
assign {o_sram_clk, o_sram_cs, io_sram_dq} = 6'bZZZZZZ;
|
|
assign {o_rtc_scl, io_rtc_sda} = 2'bZZ;
|
|
assign io_pmod[3] = w_n64_reset_btn ? 1'bZ : 1'b0;
|
|
assign {io_pmod[7:4], io_pmod[2:0]} = 7'bZZZZZZZ;
|
|
|
|
|
|
// PLL clock generator
|
|
|
|
pll sys_pll (
|
|
.inclk0(i_clk),
|
|
.c0(w_sys_clk),
|
|
.c1(w_sdram_clk),
|
|
.locked(w_pll_lock)
|
|
);
|
|
|
|
|
|
// SDRAM clock output
|
|
|
|
gpio_ddro sdram_clk_ddro (
|
|
.outclock(w_sdram_clk),
|
|
.outclocken(1'b1),
|
|
.din({1'b0, 1'b1}),
|
|
.pad_out(o_sdram_clk)
|
|
);
|
|
|
|
|
|
// SD clock output
|
|
|
|
wire w_sd_clk;
|
|
|
|
gpio_ddro sd_clk_ddro (
|
|
.outclock(w_sd_clk),
|
|
.outclocken(1'b1),
|
|
.din({1'b0, 1'b1}),
|
|
.pad_out(o_sd_clk)
|
|
);
|
|
|
|
|
|
// N64 PI
|
|
|
|
wire w_n64_request;
|
|
wire w_n64_write;
|
|
wire w_n64_busy;
|
|
wire w_n64_ack;
|
|
wire [3:0] w_n64_bank;
|
|
wire [25:0] w_n64_address;
|
|
wire [31:0] w_n64_i_data;
|
|
wire [31:0] w_n64_o_data;
|
|
|
|
wire w_n64_busy_cart_control;
|
|
wire w_n64_ack_cart_control;
|
|
wire [31:0] w_n64_i_data_cart_control;
|
|
|
|
wire w_n64_busy_sdram;
|
|
wire w_n64_ack_sdram;
|
|
wire [31:0] w_n64_i_data_sdram;
|
|
|
|
wire w_n64_busy_embedded_flash;
|
|
wire w_n64_ack_embedded_flash;
|
|
wire [31:0] w_n64_i_data_embedded_flash;
|
|
|
|
wire w_n64_busy_eeprom;
|
|
wire w_n64_ack_eeprom;
|
|
wire [31:0] w_n64_i_data_eeprom;
|
|
|
|
wire w_n64_busy_sd;
|
|
wire w_n64_ack_sd;
|
|
wire [31:0] w_n64_i_data_sd;
|
|
|
|
wire w_sram_request;
|
|
|
|
wire w_ddipl_enable;
|
|
wire w_sram_enable;
|
|
wire w_sram_768k_mode;
|
|
wire w_flashram_enable;
|
|
wire w_sd_enable;
|
|
wire w_eeprom_pi_enable;
|
|
|
|
wire [23:0] w_ddipl_address;
|
|
wire [23:0] w_sram_address;
|
|
|
|
always @(*) begin
|
|
w_n64_busy = w_n64_busy_cart_control || w_n64_busy_sdram || w_n64_busy_embedded_flash || w_n64_busy_eeprom || w_n64_busy_sd;
|
|
w_n64_ack = w_n64_ack_cart_control || w_n64_ack_sdram || w_n64_ack_embedded_flash || w_n64_ack_eeprom || w_n64_ack_sd;
|
|
w_n64_i_data = 32'h0000_0000;
|
|
if (w_n64_ack_cart_control) w_n64_i_data = w_n64_i_data_cart_control;
|
|
if (w_n64_ack_sdram) w_n64_i_data = w_n64_i_data_sdram;
|
|
if (w_n64_ack_embedded_flash) w_n64_i_data = w_n64_i_data_embedded_flash;
|
|
if (w_n64_ack_eeprom) w_n64_i_data = w_n64_i_data_eeprom;
|
|
if (w_n64_ack_sd) w_n64_i_data = w_n64_i_data_sd;
|
|
end
|
|
|
|
n64_pi n64_pi_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.i_n64_reset(i_n64_reset),
|
|
.i_n64_pi_alel(i_n64_pi_alel),
|
|
.i_n64_pi_aleh(i_n64_pi_aleh),
|
|
.i_n64_pi_read(i_n64_pi_read),
|
|
.i_n64_pi_write(i_n64_pi_write),
|
|
.io_n64_pi_ad(io_n64_pi_ad),
|
|
|
|
.o_request(w_n64_request),
|
|
.o_write(w_n64_write),
|
|
.i_busy(w_n64_busy),
|
|
.i_ack(w_n64_ack),
|
|
.o_bank(w_n64_bank),
|
|
.o_address(w_n64_address),
|
|
.i_data(w_n64_i_data),
|
|
.o_data(w_n64_o_data),
|
|
|
|
.o_sram_request(w_sram_request),
|
|
|
|
.i_ddipl_enable(w_ddipl_enable),
|
|
.i_sram_enable(w_sram_enable),
|
|
.i_sram_768k_mode(w_sram_768k_mode),
|
|
.i_flashram_enable(w_flashram_enable),
|
|
.i_sd_enable(w_sd_enable),
|
|
.i_eeprom_enable(w_eeprom_pi_enable),
|
|
|
|
.i_ddipl_address(w_ddipl_address),
|
|
.i_sram_address(w_sram_address)
|
|
);
|
|
|
|
|
|
// PC USB
|
|
|
|
wire w_pc_request;
|
|
wire w_pc_write;
|
|
wire w_pc_busy;
|
|
wire w_pc_ack;
|
|
wire [3:0] w_pc_bank;
|
|
wire [25:0] w_pc_address;
|
|
wire [31:0] w_pc_i_data;
|
|
wire [31:0] w_pc_o_data;
|
|
|
|
wire w_pc_busy_cart_control;
|
|
wire w_pc_ack_cart_control;
|
|
wire [31:0] w_pc_i_data_cart_control;
|
|
|
|
wire w_pc_busy_sdram;
|
|
wire w_pc_ack_sdram;
|
|
wire [31:0] w_pc_i_data_sdram;
|
|
|
|
wire w_pc_busy_eeprom;
|
|
wire w_pc_ack_eeprom;
|
|
wire [31:0] w_pc_i_data_eeprom;
|
|
|
|
wire w_debug_dma_start;
|
|
wire w_debug_dma_busy;
|
|
wire [3:0] w_debug_dma_bank;
|
|
wire [23:0] w_debug_dma_address;
|
|
wire [19:0] w_debug_dma_length;
|
|
|
|
wire w_debug_fifo_request;
|
|
wire w_debug_fifo_flush;
|
|
wire [10:0] w_debug_fifo_items;
|
|
wire [31:0] w_debug_fifo_data;
|
|
|
|
always @(*) begin
|
|
w_pc_busy = w_pc_busy_cart_control || w_pc_busy_sdram || w_pc_busy_eeprom;
|
|
w_pc_ack = w_pc_ack_cart_control || w_pc_ack_sdram || w_pc_ack_eeprom;
|
|
w_pc_i_data = 32'h0000_0000;
|
|
if (w_pc_ack_cart_control) w_pc_i_data = w_pc_i_data_cart_control;
|
|
if (w_pc_ack_sdram) w_pc_i_data = w_pc_i_data_sdram;
|
|
if (w_pc_ack_eeprom) w_pc_i_data = w_pc_i_data_eeprom;
|
|
end
|
|
|
|
usb_pc #(
|
|
.VERSION(`VERSION)
|
|
) usb_pc_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.o_ftdi_clk(o_ftdi_clk),
|
|
.o_ftdi_si(o_ftdi_si),
|
|
.i_ftdi_so(i_ftdi_so),
|
|
.i_ftdi_cts(i_ftdi_cts),
|
|
|
|
.o_request(w_pc_request),
|
|
.o_write(w_pc_write),
|
|
.i_busy(w_pc_busy),
|
|
.i_ack(w_pc_ack),
|
|
.o_bank(w_pc_bank),
|
|
.o_address(w_pc_address),
|
|
.i_data(w_pc_i_data),
|
|
.o_data(w_pc_o_data),
|
|
|
|
.i_debug_start(w_debug_dma_start),
|
|
.o_debug_busy(w_debug_dma_busy),
|
|
.i_debug_bank(w_debug_dma_bank),
|
|
.i_debug_address(w_debug_dma_address),
|
|
.i_debug_length(w_debug_dma_length),
|
|
|
|
.i_debug_fifo_request(w_debug_fifo_request),
|
|
.i_debug_fifo_flush(w_debug_fifo_flush),
|
|
.o_debug_fifo_items(w_debug_fifo_items),
|
|
.o_debug_fifo_data(w_debug_fifo_data)
|
|
);
|
|
|
|
|
|
// Cart interface
|
|
|
|
wire w_cart_control_request;
|
|
wire w_cart_control_write;
|
|
wire w_cart_control_busy;
|
|
wire w_cart_control_ack;
|
|
wire [10:0] w_cart_control_address;
|
|
wire [31:0] w_cart_control_o_data;
|
|
wire [31:0] w_cart_control_i_data;
|
|
|
|
wire w_sdram_writable;
|
|
wire w_rom_switch;
|
|
wire w_eeprom_enable;
|
|
wire w_eeprom_16k_mode;
|
|
|
|
device_arbiter #(
|
|
.NUM_CONTROLLERS(2),
|
|
.ADDRESS_WIDTH(11),
|
|
.DEVICE_BANK(`BANK_CART)
|
|
) device_arbiter_cart_control_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.i_request({w_pc_request, w_n64_request}),
|
|
.i_write({w_pc_write, w_n64_write}),
|
|
.o_busy({w_pc_busy_cart_control, w_n64_busy_cart_control}),
|
|
.o_ack({w_pc_ack_cart_control, w_n64_ack_cart_control}),
|
|
.i_bank({w_pc_bank, w_n64_bank}),
|
|
.i_address({w_pc_address[12:2], w_n64_address[12:2]}),
|
|
.o_data({w_pc_i_data_cart_control, w_n64_i_data_cart_control}),
|
|
.i_data({w_pc_o_data, w_n64_o_data}),
|
|
|
|
.o_device_request(w_cart_control_request),
|
|
.o_device_write(w_cart_control_write),
|
|
.i_device_busy(w_cart_control_busy),
|
|
.i_device_ack(w_cart_control_ack),
|
|
.o_device_address(w_cart_control_address),
|
|
.i_device_data(w_cart_control_o_data),
|
|
.o_device_data(w_cart_control_i_data)
|
|
);
|
|
|
|
cart_control #(
|
|
.VERSION(`VERSION)
|
|
) cart_control_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.i_n64_reset(i_n64_reset),
|
|
.i_n64_nmi(i_n64_nmi),
|
|
|
|
.i_request(w_cart_control_request),
|
|
.i_write(w_cart_control_write),
|
|
.o_busy(w_cart_control_busy),
|
|
.o_ack(w_cart_control_ack),
|
|
.i_address(w_cart_control_address),
|
|
.o_data(w_cart_control_o_data),
|
|
.i_data(w_cart_control_i_data),
|
|
|
|
.o_sdram_writable(w_sdram_writable),
|
|
.o_rom_switch(w_rom_switch),
|
|
.o_ddipl_enable(w_ddipl_enable),
|
|
.o_sram_enable(w_sram_enable),
|
|
.o_sram_768k_mode(w_sram_768k_mode),
|
|
.o_flashram_enable(w_flashram_enable),
|
|
.o_sd_enable(w_sd_enable),
|
|
.o_eeprom_pi_enable(w_eeprom_pi_enable),
|
|
.o_eeprom_enable(w_eeprom_enable),
|
|
.o_eeprom_16k_mode(w_eeprom_16k_mode),
|
|
|
|
.o_n64_reset_btn(w_n64_reset_btn),
|
|
|
|
.i_debug_ready(1'b1),
|
|
|
|
.o_debug_dma_start(w_debug_dma_start),
|
|
.i_debug_dma_busy(w_debug_dma_busy),
|
|
.o_debug_dma_bank(w_debug_dma_bank),
|
|
.o_debug_dma_address(w_debug_dma_address),
|
|
.o_debug_dma_length(w_debug_dma_length),
|
|
|
|
.o_debug_fifo_request(w_debug_fifo_request),
|
|
.o_debug_fifo_flush(w_debug_fifo_flush),
|
|
.i_debug_fifo_items(w_debug_fifo_items),
|
|
.i_debug_fifo_data(w_debug_fifo_data),
|
|
|
|
.o_ddipl_address(w_ddipl_address),
|
|
.o_sram_address(w_sram_address)
|
|
);
|
|
|
|
|
|
// Embedded flash
|
|
|
|
wire w_embedded_flash_request_n64 = w_n64_request && !w_rom_switch && !w_n64_write && w_n64_bank == `BANK_SDRAM;
|
|
|
|
memory_embedded_flash memory_embedded_flash_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.i_request(w_embedded_flash_request_n64),
|
|
.o_busy(w_n64_busy_embedded_flash),
|
|
.o_ack(w_n64_ack_embedded_flash),
|
|
.i_address(w_n64_address[20:2]),
|
|
.o_data(w_n64_i_data_embedded_flash)
|
|
);
|
|
|
|
|
|
// SD card
|
|
|
|
wire w_n64_request_sd = w_n64_request && w_n64_bank == `BANK_SD;
|
|
|
|
wire w_sd_dma_request;
|
|
wire w_sd_dma_write;
|
|
wire w_sd_dma_busy;
|
|
wire w_sd_dma_ack;
|
|
wire [3:0] w_sd_dma_bank;
|
|
wire [23:0] w_sd_dma_address;
|
|
wire [31:0] w_sd_dma_i_data;
|
|
wire [31:0] w_sd_dma_o_data;
|
|
|
|
wire w_sd_dma_busy_sdram;
|
|
wire w_sd_dma_ack_sdram;
|
|
wire [31:0] w_sd_dma_i_data_sdram;
|
|
|
|
wire w_sd_dma_busy_eeprom;
|
|
wire w_sd_dma_ack_eeprom;
|
|
wire [31:0] w_sd_dma_i_data_eeprom;
|
|
|
|
always @(*) begin
|
|
w_sd_dma_busy = w_sd_dma_busy_sdram || w_sd_dma_busy_eeprom;
|
|
w_sd_dma_ack = w_sd_dma_ack_sdram || w_sd_dma_ack_eeprom;
|
|
w_sd_dma_i_data = 32'h0000_0000;
|
|
if (w_sd_dma_ack_sdram) w_sd_dma_i_data = w_sd_dma_i_data_sdram;
|
|
if (w_sd_dma_ack_eeprom) w_sd_dma_i_data = w_sd_dma_i_data_eeprom;
|
|
end
|
|
|
|
sd_interface sd_interface_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.o_sd_clk(w_sd_clk),
|
|
.io_sd_cmd(io_sd_cmd),
|
|
.io_sd_dat(io_sd_dat),
|
|
|
|
.i_request(w_n64_request_sd),
|
|
.i_write(w_n64_write),
|
|
.o_busy(w_n64_busy_sd),
|
|
.o_ack(w_n64_ack_sd),
|
|
.i_address({w_n64_address[9], w_n64_address[4:2]}),
|
|
.o_data(w_n64_i_data_sd),
|
|
.i_data(w_n64_o_data),
|
|
|
|
.o_dma_request(w_sd_dma_request),
|
|
.o_dma_write(w_sd_dma_write),
|
|
.i_dma_busy(w_sd_dma_busy),
|
|
.i_dma_ack(w_sd_dma_ack),
|
|
.o_dma_bank(w_sd_dma_bank),
|
|
.o_dma_address(w_sd_dma_address),
|
|
.i_dma_data(w_sd_dma_i_data),
|
|
.o_dma_data(w_sd_dma_o_data)
|
|
);
|
|
|
|
|
|
// SDRAM
|
|
|
|
wire w_sdram_request_n64 = w_n64_request && w_rom_switch && (!w_n64_write || (w_n64_write && (w_sdram_writable || w_sram_request)));
|
|
|
|
wire w_sdram_request;
|
|
wire w_sdram_write;
|
|
wire w_sdram_busy;
|
|
wire w_sdram_ack;
|
|
wire [24:0] w_sdram_address;
|
|
wire [31:0] w_sdram_o_data;
|
|
wire [31:0] w_sdram_i_data;
|
|
|
|
device_arbiter #(
|
|
.NUM_CONTROLLERS(3),
|
|
.ADDRESS_WIDTH(25),
|
|
.DEVICE_BANK(`BANK_SDRAM)
|
|
) device_arbiter_sdram_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.i_request({w_sd_dma_request, w_pc_request, w_sdram_request_n64}),
|
|
.i_write({w_sd_dma_write, w_pc_write, w_n64_write}),
|
|
.o_busy({w_sd_dma_busy_sdram, w_pc_busy_sdram, w_n64_busy_sdram}),
|
|
.o_ack({w_sd_dma_ack_sdram, w_pc_ack_sdram, w_n64_ack_sdram}),
|
|
.i_bank({w_sd_dma_bank, w_pc_bank, w_n64_bank}),
|
|
.i_address({{w_sd_dma_address, 1'b0}, w_pc_address[25:1], w_n64_address[25:1]}),
|
|
.o_data({w_sd_dma_i_data_sdram, w_pc_i_data_sdram, w_n64_i_data_sdram}),
|
|
.i_data({w_sd_dma_o_data, w_pc_o_data, w_n64_o_data}),
|
|
|
|
.o_device_request(w_sdram_request),
|
|
.o_device_write(w_sdram_write),
|
|
.i_device_busy(w_sdram_busy),
|
|
.i_device_ack(w_sdram_ack),
|
|
.o_device_address(w_sdram_address),
|
|
.i_device_data(w_sdram_o_data),
|
|
.o_device_data(w_sdram_i_data)
|
|
);
|
|
|
|
memory_sdram memory_sdram_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.o_sdram_cs(o_sdram_cs),
|
|
.o_sdram_ras(o_sdram_ras),
|
|
.o_sdram_cas(o_sdram_cas),
|
|
.o_sdram_we(o_sdram_we),
|
|
.o_sdram_ba(o_sdram_ba),
|
|
.o_sdram_a(o_sdram_a),
|
|
.io_sdram_dq(io_sdram_dq),
|
|
|
|
.i_request(w_sdram_request),
|
|
.i_write(w_sdram_write),
|
|
.o_busy(w_sdram_busy),
|
|
.o_ack(w_sdram_ack),
|
|
.i_address(w_sdram_address),
|
|
.o_data(w_sdram_o_data),
|
|
.i_data(w_sdram_i_data)
|
|
);
|
|
|
|
|
|
// EEPROM 4/16k
|
|
|
|
wire w_eeprom_request;
|
|
wire w_eeprom_write;
|
|
wire w_eeprom_busy;
|
|
wire w_eeprom_ack;
|
|
wire [8:0] w_eeprom_address;
|
|
wire [31:0] w_eeprom_o_data;
|
|
wire [31:0] w_eeprom_i_data;
|
|
|
|
device_arbiter #(
|
|
.NUM_CONTROLLERS(3),
|
|
.ADDRESS_WIDTH(9),
|
|
.DEVICE_BANK(`BANK_EEPROM)
|
|
) device_arbiter_eeprom_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.i_request({w_sd_dma_request, w_pc_request, w_n64_request}),
|
|
.i_write({w_sd_dma_write, w_pc_write, w_n64_write}),
|
|
.o_busy({w_sd_dma_busy_eeprom, w_pc_busy_eeprom, w_n64_busy_eeprom}),
|
|
.o_ack({w_sd_dma_ack_eeprom, w_pc_ack_eeprom, w_n64_ack_eeprom}),
|
|
.i_bank({w_sd_dma_bank, w_pc_bank, w_n64_bank}),
|
|
.i_address({w_sd_dma_address[8:0], w_pc_address[10:2], w_n64_address[10:2]}),
|
|
.o_data({w_sd_dma_i_data_eeprom, w_pc_i_data_eeprom, w_n64_i_data_eeprom}),
|
|
.i_data({w_sd_dma_o_data, w_pc_o_data, w_n64_o_data}),
|
|
|
|
.o_device_request(w_eeprom_request),
|
|
.o_device_write(w_eeprom_write),
|
|
.i_device_busy(w_eeprom_busy),
|
|
.i_device_ack(w_eeprom_ack),
|
|
.o_device_address(w_eeprom_address),
|
|
.i_device_data(w_eeprom_o_data),
|
|
.o_device_data(w_eeprom_i_data)
|
|
);
|
|
|
|
n64_si n64_si_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.i_n64_reset(i_n64_reset),
|
|
.i_n64_si_clk(i_n64_si_clk),
|
|
.io_n64_si_dq(io_n64_si_dq),
|
|
|
|
.i_request(w_eeprom_request),
|
|
.i_write(w_eeprom_write),
|
|
.o_busy(w_eeprom_busy),
|
|
.o_ack(w_eeprom_ack),
|
|
.i_address(w_eeprom_address),
|
|
.i_data(w_eeprom_i_data),
|
|
.o_data(w_eeprom_o_data),
|
|
|
|
.i_eeprom_enable(w_eeprom_enable),
|
|
.i_eeprom_16k_mode(w_eeprom_16k_mode)
|
|
);
|
|
|
|
|
|
// LED
|
|
|
|
wire w_led_trigger = (w_n64_request && !w_n64_busy) || (w_pc_request && !w_pc_busy);
|
|
|
|
cart_led cart_led_inst (
|
|
.i_clk(w_sys_clk),
|
|
.i_reset(w_sys_reset),
|
|
|
|
.i_trigger(w_led_trigger),
|
|
|
|
.o_led(o_led)
|
|
);
|
|
|
|
endmodule
|