From c4c101b6d386538226fac551157afee0b58b58ce Mon Sep 17 00:00:00 2001 From: Polprzewodnikowy Date: Sat, 27 Feb 2021 15:56:46 +0100 Subject: [PATCH] flashram working --- fw/SummerCart64.qsf | 10 +- fw/rtl/cart/cart_control.v | 40 ++- fw/rtl/constants.vh | 3 +- fw/rtl/flashram/flashram_controller.v | 301 ++++++++++++++++++ .../intel/ram/ram_flashram_write_buffer.qip | 4 + fw/rtl/intel/ram/ram_flashram_write_buffer.v | 243 ++++++++++++++ fw/rtl/n64/n64_bank_decoder.v | 71 +---- fw/rtl/n64/n64_pi.v | 42 ++- fw/rtl/sd/sd_interface.v | 4 +- fw/rtl/top.v | 183 ++++++++--- sw/bootloader/src/main.c | 15 +- sw/bootloader/src/sc64/sc64.c | 11 +- sw/bootloader/src/sc64/sc64.h | 6 +- sw/bootloader/src/sc64/sc64_regs.h | 3 +- sw/bootloader/src/sc64/sc64_sd_fs.c | 20 +- 15 files changed, 770 insertions(+), 186 deletions(-) create mode 100644 fw/rtl/flashram/flashram_controller.v create mode 100644 fw/rtl/intel/ram/ram_flashram_write_buffer.qip create mode 100644 fw/rtl/intel/ram/ram_flashram_write_buffer.v diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index 3c41e7a..a8beb51 100644 --- a/fw/SummerCart64.qsf +++ b/fw/SummerCart64.qsf @@ -19,7 +19,7 @@ # # Quartus Prime # Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition -# Date created = 01:35:54 February 19, 2021 +# Date created = 15:52:44 February 27, 2021 # # -------------------------------------------------------------------------- # # @@ -51,6 +51,7 @@ set_global_assignment -name QIP_FILE rtl/intel/fifo/fifo_sd.qip set_global_assignment -name QIP_FILE rtl/intel/fifo/fifo_usb.qip set_global_assignment -name QIP_FILE rtl/intel/gpio/gpio_ddro.qip set_global_assignment -name QIP_FILE rtl/intel/pll/pll.qip +set_global_assignment -name QIP_FILE rtl/intel/ram/ram_flashram_write_buffer.qip set_global_assignment -name QIP_FILE rtl/intel/ram/ram_n64_eeprom.qip set_global_assignment -name QSYS_FILE rtl/intel/flash/onchip_flash.qsys set_global_assignment -name SDC_FILE constraints.sdc @@ -58,6 +59,7 @@ set_global_assignment -name SIGNALTAP_FILE output_files/signal_tap_logic_analyze set_global_assignment -name SYSTEMVERILOG_FILE rtl/intel/gpio/gpio_ddro/altera_gpio_lite.sv -library gpio_ddro set_global_assignment -name VERILOG_FILE rtl/cart/cart_control.v set_global_assignment -name VERILOG_FILE rtl/cart/cart_led.v +set_global_assignment -name VERILOG_FILE rtl/flashram/flashram_controller.v set_global_assignment -name VERILOG_FILE rtl/glue/device_arbiter.v set_global_assignment -name VERILOG_FILE rtl/memory/memory_embedded_flash.v set_global_assignment -name VERILOG_FILE rtl/memory/memory_sdram.v @@ -160,12 +162,6 @@ set_location_assignment PIN_114 -to o_sd_clk set_location_assignment PIN_118 -to io_sd_cmd set_location_assignment PIN_119 -to io_sd_dat[3] set_location_assignment PIN_120 -to io_sd_dat[2] -set_location_assignment PIN_121 -to io_sram_dq[0] -set_location_assignment PIN_122 -to o_sram_clk -set_location_assignment PIN_123 -to io_sram_dq[3] -set_location_assignment PIN_124 -to o_sram_cs -set_location_assignment PIN_126 -to io_sram_dq[1] -set_location_assignment PIN_127 -to io_sram_dq[2] set_location_assignment PIN_138 -to io_pmod[0] set_location_assignment PIN_140 -to io_pmod[1] set_location_assignment PIN_141 -to io_pmod[2] diff --git a/fw/rtl/cart/cart_control.v b/fw/rtl/cart/cart_control.v index 9819429..794f7d0 100644 --- a/fw/rtl/cart/cart_control.v +++ b/fw/rtl/cart/cart_control.v @@ -17,7 +17,6 @@ module cart_control ( output reg o_rom_switch, output reg o_ddipl_enable, output reg o_sram_enable, - output reg o_sram_768k_mode, output reg o_flashram_enable, output reg o_sd_enable, output reg o_eeprom_pi_enable, @@ -40,7 +39,7 @@ module cart_control ( input [31:0] i_debug_fifo_data, output reg [23:0] o_ddipl_address, - output reg [23:0] o_sram_address + output reg [23:0] o_save_address ); // Module parameters @@ -100,17 +99,16 @@ module cart_control ( o_rom_switch <= 1'b0; o_ddipl_enable <= 1'b0; o_sram_enable <= 1'b0; - o_sram_768k_mode <= 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_n64_reset_btn <= 1'b1; - o_ddipl_address <= 24'hF0_0000; - o_sram_address <= 24'hFF_E000; + o_ddipl_address <= 24'hEF_8000; + o_save_address <= 24'hFF_8000; o_debug_dma_bank <= 4'd1; - o_debug_dma_address <= 24'hFC_0000; + o_debug_dma_address <= 24'hCF_8000; o_debug_dma_length <= 20'd0; r_bootloader <= 16'h0000; r_skip_bootloader <= 1'b0; @@ -121,7 +119,6 @@ module cart_control ( { r_skip_bootloader, o_flashram_enable, - o_sram_768k_mode, o_sram_enable, o_sd_enable, o_eeprom_pi_enable, @@ -130,31 +127,38 @@ module cart_control ( o_ddipl_enable, o_rom_switch, o_sdram_writable - } <= i_data[10:0]; + } <= {i_data[10:9], i_data[7:0]}; end + REG_BOOT: begin r_bootloader <= i_data[15:0]; end + REG_GPIO: begin o_n64_reset_btn <= ~i_data[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_SRAM_ADDR: begin - o_sram_address <= i_data[25:2]; - end - default: begin + o_save_address <= i_data[25:2]; end + + default: begin end endcase end @@ -182,7 +186,7 @@ module cart_control ( o_data[10:0] <= { r_skip_bootloader, o_flashram_enable, - o_sram_768k_mode, + 1'b0, o_sram_enable, o_sd_enable, o_eeprom_pi_enable, @@ -193,26 +197,32 @@ module cart_control ( o_sdram_writable }; 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[2:0] <= {r_nmi_ff2, r_reset_ff2, ~o_n64_reset_btn}; 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_SRAM_ADDR: begin - o_data[25:0] <= {o_sram_address, 2'b00}; - end - default: begin + o_data[25:0] <= {o_save_address, 2'b00}; end + + default: begin end endcase end else begin o_data <= i_debug_fifo_data; diff --git a/fw/rtl/constants.vh b/fw/rtl/constants.vh index 853aa00..b319f19 100644 --- a/fw/rtl/constants.vh +++ b/fw/rtl/constants.vh @@ -4,5 +4,4 @@ `define BANK_SDRAM 4'd1 `define BANK_CART 4'd2 `define BANK_EEPROM 4'd3 -`define BANK_FLASHRAM 4'd4 -`define BANK_SD 4'd5 +`define BANK_SD 4'd4 diff --git a/fw/rtl/flashram/flashram_controller.v b/fw/rtl/flashram/flashram_controller.v new file mode 100644 index 0000000..0a199c3 --- /dev/null +++ b/fw/rtl/flashram/flashram_controller.v @@ -0,0 +1,301 @@ +`include "../constants.vh" + +module flashram_controller ( + input i_clk, + input i_reset, + + input [23:0] i_save_address, + + output o_flashram_read_mode, + + input i_request, + input i_write, + output o_busy, + output reg o_ack, + input [14:0] i_address, + output reg [31:0] o_data, + input [31:0] i_data, + + output reg o_mem_request, + output reg o_mem_write, + input i_mem_busy, + input i_mem_ack, + output reg [3:0] o_mem_bank, + output reg [23:0] o_mem_address, + output reg [31:0] o_mem_data, + input [31:0] i_mem_data +); + + // State machine and command decoder + + localparam [31:0] FLASH_TYPE_ID = 32'h1111_8001; + localparam [31:0] FLASH_MODEL_ID = 32'h00C2_001D; + + localparam [7:0] CMD_STATUS_MODE = 8'hD2; + localparam [7:0] CMD_READID_MODE = 8'hE1; + localparam [7:0] CMD_READ_MODE = 8'hF0; + localparam [7:0] CMD_ERASE_SECTOR = 8'h4B; + localparam [7:0] CMD_ERASE_CHIP = 8'h3C; + localparam [7:0] CMD_WRITE_MODE = 8'hB4; + localparam [7:0] CMD_ERASE_START = 8'h78; + localparam [7:0] CMD_WRITE_START = 8'hA5; + + localparam STATE_STATUS = 0; + localparam STATE_ID = 1; + localparam STATE_READ = 2; + localparam STATE_ERASE = 3; + localparam STATE_WRITE = 4; + localparam STATE_EXECUTE = 5; + + localparam [1:0] EXECUTE_WRITE = 2'b00; + localparam [1:0] EXECUTE_ERASE_SECTOR = 2'b10; + localparam [1:0] EXECUTE_ERASE_CHIP = 2'b11; + + reg [5:0] r_flashram_state; + reg [9:0] r_sector_offset; + reg [1:0] r_execute_mode; + reg r_execute_start; + reg r_execute_done; + + assign o_flashram_read_mode = r_flashram_state[STATE_READ]; + + wire w_cmd_request = i_request && i_write && i_address[14] && !r_flashram_state[STATE_EXECUTE]; + wire [7:0] w_cmd_op = i_data[31:24]; + + always @(posedge i_clk) begin + r_execute_start <= 1'b0; + + if (i_reset || r_execute_done) begin + r_flashram_state <= (1'b1 << STATE_STATUS); + end else begin + if (w_cmd_request) begin + r_flashram_state <= 6'b000000; + + if (w_cmd_op == CMD_STATUS_MODE) begin + r_flashram_state[STATE_STATUS] <= 1'b1; + end + + if (w_cmd_op == CMD_READID_MODE) begin + r_flashram_state[STATE_ID] <= 1'b1; + end + + if (w_cmd_op == CMD_READ_MODE) begin + r_flashram_state[STATE_READ] <= 1'b1; + end + + if (w_cmd_op == CMD_ERASE_SECTOR) begin + r_flashram_state[STATE_ERASE] <= 1'b1; + r_sector_offset <= {i_data[9:7], 7'd0}; + r_execute_mode <= EXECUTE_ERASE_SECTOR; + end + + if (w_cmd_op == CMD_ERASE_CHIP) begin + r_flashram_state[STATE_ERASE] <= 1'b1; + r_sector_offset <= 10'd0; + r_execute_mode <= EXECUTE_ERASE_CHIP; + end + + if (w_cmd_op == CMD_WRITE_MODE) begin + r_flashram_state[STATE_WRITE] <= 1'b1; + end + + if (w_cmd_op == CMD_ERASE_START) begin + if (r_flashram_state[STATE_ERASE]) begin + r_flashram_state[STATE_EXECUTE] <= 1'b1; + r_execute_start <= 1'b1; + end + end + + if (w_cmd_op == CMD_WRITE_START) begin + r_flashram_state[STATE_EXECUTE] <= 1'b1; + r_sector_offset <= i_data[9:0]; + r_execute_mode <= EXECUTE_WRITE; + r_execute_start <= 1'b1; + end + end + end + end + + + // Status controller + + reg r_erase_busy; + reg r_erase_done; + + reg r_write_busy; + reg r_write_done; + + wire [3:0] w_status = {r_erase_done, r_write_done, r_erase_busy, r_write_busy}; + + wire w_status_write_request = i_request && i_write && !i_address[14] && r_flashram_state[STATE_STATUS]; + + always @(posedge i_clk) begin + if (i_reset) begin + r_erase_busy <= 1'b0; + r_write_busy <= 1'b0; + r_erase_done <= 1'b0; + r_write_done <= 1'b0; + end else begin + if (w_status_write_request) begin + r_erase_done <= r_erase_done & i_data[3]; + r_write_done <= r_write_done & i_data[1]; + end + + if (r_execute_start) begin + if (r_execute_mode == EXECUTE_WRITE) begin + r_write_busy <= 1'b1; + r_write_done <= 1'b0; + end else begin + r_erase_busy <= 1'b1; + r_erase_done <= 1'b0; + end + end + + if (r_execute_done) begin + if (r_execute_mode == EXECUTE_WRITE) begin + r_write_busy <= 1'b0; + r_write_done <= 1'b1; + end else begin + r_erase_busy <= 1'b0; + r_erase_done <= 1'b1; + end + end + end + end + + + // Bus controller + + assign o_busy = 1'b0; + + wire [31:0] w_write_buffer_o_data; + + wire w_flashram_controller_read_request = i_request && !i_write && !o_busy && !r_flashram_state[STATE_READ]; + + always @(posedge i_clk) begin + o_ack <= 1'b0; + + if (w_flashram_controller_read_request) begin + o_ack <= 1'b1; + o_data <= {12'h000, w_status, 12'h000, w_status}; + + if (r_flashram_state[STATE_ID]) begin + o_data <= i_address[0] ? FLASH_MODEL_ID : FLASH_TYPE_ID; + end + + if (r_flashram_state[STATE_WRITE]) begin + o_data <= w_write_buffer_o_data; + end + end + end + + + // Page write buffer + + reg [4:0] r_write_buffer_address; + + wire [31:0] w_write_buffer_o_mem_data; + + wire w_write_buffer_request = i_request && i_write && !o_busy && !i_address[14] && r_flashram_state[STATE_WRITE]; + + ram_flashram_write_buffer ram_flashram_write_buffer_inst ( + .clock(i_clk), + + .wren_a(w_write_buffer_request), + .address_a(i_address[4:0]), + .data_a(i_data), + .q_a(w_write_buffer_o_data), + + .wren_b(i_mem_ack), + .address_b(r_write_buffer_address), + .data_b(i_mem_data & w_write_buffer_o_mem_data), + .q_b(w_write_buffer_o_mem_data) + ); + + + // Memory controller + + reg [15:0] r_items_left; + + wire w_execute_done = !r_execute_start && (r_items_left == 16'd0) && r_flashram_state[STATE_EXECUTE]; + wire w_read_phase_done = w_execute_done && !o_mem_write && i_mem_ack; + wire w_write_phase_done = w_execute_done && o_mem_write; + + wire w_mem_request_successful = o_mem_request && !i_mem_busy; + wire w_address_reset = r_execute_start || w_read_phase_done; + wire w_write_buffer_address_increment = o_mem_write ? w_mem_request_successful : i_mem_ack; + + always @(posedge i_clk) begin + r_execute_done <= w_write_phase_done; + end + + always @(posedge i_clk) begin + if (w_address_reset) begin + case (r_execute_mode) + EXECUTE_WRITE: r_items_left <= 16'h20; + EXECUTE_ERASE_SECTOR: r_items_left <= 16'h1000; + EXECUTE_ERASE_CHIP: r_items_left <= 16'h8000; + default: r_items_left <= 16'd0; + endcase + end + + if (w_mem_request_successful) begin + r_items_left <= r_items_left - 1'd1; + end + end + + always @(posedge i_clk) begin + if (i_reset) begin + o_mem_request <= 1'b0; + end else begin + if (r_items_left > 16'd0) begin + o_mem_request <= 1'b1; + end + + if (w_mem_request_successful) begin + o_mem_request <= 1'b0; + end + end + end + + always @(posedge i_clk) begin + if (r_execute_start) begin + if (r_execute_mode == EXECUTE_WRITE) begin + o_mem_write <= 1'b0; + end else begin + o_mem_write <= 1'b1; + end + end + + if (w_read_phase_done) begin + o_mem_write <= 1'b1; + end + end + + always @(posedge i_clk) begin + o_mem_bank <= `BANK_SDRAM; + end + + always @(posedge i_clk) begin + if (w_address_reset) begin + o_mem_address <= i_save_address + {9'd0, r_sector_offset, 5'd0}; + r_write_buffer_address <= 5'd0; + end else begin + if (w_mem_request_successful) begin + o_mem_address <= o_mem_address + 1'd1; + end + + if (w_write_buffer_address_increment) begin + r_write_buffer_address <= r_write_buffer_address + 1'd1; + end + end + end + + always @(*) begin + o_mem_data = 32'hFFFF_FFFF; + if (r_execute_mode == EXECUTE_WRITE) begin + o_mem_data = w_write_buffer_o_mem_data; + end + end + +endmodule diff --git a/fw/rtl/intel/ram/ram_flashram_write_buffer.qip b/fw/rtl/intel/ram/ram_flashram_write_buffer.qip new file mode 100644 index 0000000..8e30c84 --- /dev/null +++ b/fw/rtl/intel/ram/ram_flashram_write_buffer.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT" +set_global_assignment -name IP_TOOL_VERSION "20.1" +set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "ram_flashram_write_buffer.v"] diff --git a/fw/rtl/intel/ram/ram_flashram_write_buffer.v b/fw/rtl/intel/ram/ram_flashram_write_buffer.v new file mode 100644 index 0000000..72458bb --- /dev/null +++ b/fw/rtl/intel/ram/ram_flashram_write_buffer.v @@ -0,0 +1,243 @@ +// megafunction wizard: %RAM: 2-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: ram_flashram_write_buffer.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 20.1.1 Build 720 11/11/2020 SJ Lite Edition +// ************************************************************ + + +//Copyright (C) 2020 Intel Corporation. All rights reserved. +//Your use of Intel Corporation's design tools, logic functions +//and other software and tools, and any partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Intel Program License +//Subscription Agreement, the Intel Quartus Prime License Agreement, +//the Intel FPGA IP License Agreement, or other applicable license +//agreement, including, without limitation, that your use is for +//the sole purpose of programming logic devices manufactured by +//Intel and sold by Intel or its authorized distributors. Please +//refer to the applicable agreement for further details, at +//https://fpgasoftware.intel.com/eula. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module ram_flashram_write_buffer ( + address_a, + address_b, + clock, + data_a, + data_b, + wren_a, + wren_b, + q_a, + q_b); + + input [4:0] address_a; + input [4:0] address_b; + input clock; + input [31:0] data_a; + input [31:0] data_b; + input wren_a; + input wren_b; + output [31:0] q_a; + output [31:0] q_b; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock; + tri0 wren_a; + tri0 wren_b; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [31:0] sub_wire0; + wire [31:0] sub_wire1; + wire [31:0] q_a = sub_wire0[31:0]; + wire [31:0] q_b = sub_wire1[31:0]; + + altsyncram altsyncram_component ( + .address_a (address_a), + .address_b (address_b), + .clock0 (clock), + .data_a (data_a), + .data_b (data_b), + .wren_a (wren_a), + .wren_b (wren_b), + .q_a (sub_wire0), + .q_b (sub_wire1), + .aclr0 (1'b0), + .aclr1 (1'b0), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .eccstatus (), + .rden_a (1'b1), + .rden_b (1'b1)); + defparam + altsyncram_component.address_reg_b = "CLOCK0", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_input_b = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.clock_enable_output_b = "BYPASS", + altsyncram_component.indata_reg_b = "CLOCK0", + altsyncram_component.intended_device_family = "MAX 10", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 32, + altsyncram_component.numwords_b = 32, + altsyncram_component.operation_mode = "BIDIR_DUAL_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_aclr_b = "NONE", + altsyncram_component.outdata_reg_a = "UNREGISTERED", + altsyncram_component.outdata_reg_b = "UNREGISTERED", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_WITH_NBE_READ", + altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_WITH_NBE_READ", + altsyncram_component.widthad_a = 5, + altsyncram_component.widthad_b = 5, + altsyncram_component.width_a = 32, + altsyncram_component.width_b = 32, + altsyncram_component.width_byteena_a = 1, + altsyncram_component.width_byteena_b = 1, + altsyncram_component.wrcontrol_wraddress_reg_b = "CLOCK0"; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "1" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "0" +// Retrieval info: PRIVATE: CLRdata NUMERIC "0" +// Retrieval info: PRIVATE: CLRq NUMERIC "0" +// Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0" +// Retrieval info: PRIVATE: CLRrren NUMERIC "0" +// Retrieval info: PRIVATE: CLRwraddress NUMERIC "0" +// Retrieval info: PRIVATE: CLRwren NUMERIC "0" +// Retrieval info: PRIVATE: Clock NUMERIC "0" +// Retrieval info: PRIVATE: Clock_A NUMERIC "0" +// Retrieval info: PRIVATE: Clock_B NUMERIC "0" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "1" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MEMSIZE NUMERIC "1024" +// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "" +// Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "3" +// Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "4" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "4" +// Retrieval info: PRIVATE: REGdata NUMERIC "1" +// Retrieval info: PRIVATE: REGq NUMERIC "0" +// Retrieval info: PRIVATE: REGrdaddress NUMERIC "0" +// Retrieval info: PRIVATE: REGrren NUMERIC "0" +// Retrieval info: PRIVATE: REGwraddress NUMERIC "1" +// Retrieval info: PRIVATE: REGwren NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0" +// Retrieval info: PRIVATE: UseDPRAM NUMERIC "1" +// Retrieval info: PRIVATE: VarWidth NUMERIC "0" +// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "32" +// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "32" +// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "32" +// Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "32" +// Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "1" +// Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0" +// Retrieval info: PRIVATE: enable NUMERIC "0" +// Retrieval info: PRIVATE: rden NUMERIC "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK0" +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS" +// Retrieval info: CONSTANT: INDATA_REG_B STRING "CLOCK0" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "32" +// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "32" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "BIDIR_DUAL_PORT" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED" +// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "DONT_CARE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_WITH_NBE_READ" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_WITH_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "5" +// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "5" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "32" +// Retrieval info: CONSTANT: WIDTH_B NUMERIC "32" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_B NUMERIC "1" +// Retrieval info: CONSTANT: WRCONTROL_WRADDRESS_REG_B STRING "CLOCK0" +// Retrieval info: USED_PORT: address_a 0 0 5 0 INPUT NODEFVAL "address_a[4..0]" +// Retrieval info: USED_PORT: address_b 0 0 5 0 INPUT NODEFVAL "address_b[4..0]" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: data_a 0 0 32 0 INPUT NODEFVAL "data_a[31..0]" +// Retrieval info: USED_PORT: data_b 0 0 32 0 INPUT NODEFVAL "data_b[31..0]" +// Retrieval info: USED_PORT: q_a 0 0 32 0 OUTPUT NODEFVAL "q_a[31..0]" +// Retrieval info: USED_PORT: q_b 0 0 32 0 OUTPUT NODEFVAL "q_b[31..0]" +// Retrieval info: USED_PORT: wren_a 0 0 0 0 INPUT GND "wren_a" +// Retrieval info: USED_PORT: wren_b 0 0 0 0 INPUT GND "wren_b" +// Retrieval info: CONNECT: @address_a 0 0 5 0 address_a 0 0 5 0 +// Retrieval info: CONNECT: @address_b 0 0 5 0 address_b 0 0 5 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: @data_a 0 0 32 0 data_a 0 0 32 0 +// Retrieval info: CONNECT: @data_b 0 0 32 0 data_b 0 0 32 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren_a 0 0 0 0 +// Retrieval info: CONNECT: @wren_b 0 0 0 0 wren_b 0 0 0 0 +// Retrieval info: CONNECT: q_a 0 0 32 0 @q_a 0 0 32 0 +// Retrieval info: CONNECT: q_b 0 0 32 0 @q_b 0 0 32 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL ram_flashram_write_buffer.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram_flashram_write_buffer.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram_flashram_write_buffer.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram_flashram_write_buffer.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram_flashram_write_buffer_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram_flashram_write_buffer_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/fw/rtl/n64/n64_bank_decoder.v b/fw/rtl/n64/n64_bank_decoder.v index ede9d99..3a25a3c 100644 --- a/fw/rtl/n64/n64_bank_decoder.v +++ b/fw/rtl/n64/n64_bank_decoder.v @@ -4,46 +4,44 @@ module n64_bank_decoder ( input i_clk, input i_address_high_op, - input i_address_low_op, input [15:0] i_n64_pi_ad, output reg [3:0] o_bank, output reg o_prefetch, - output reg o_ddipl_request, - output reg o_sram_request, + output reg o_ddipl_pi_request, + output reg o_sram_pi_request, + output reg o_flashram_pi_request, input i_ddipl_enable, input i_sram_enable, - input i_sram_768k_mode, input i_flashram_enable, - input i_eeprom_enable, + input i_eeprom_pi_enable, input i_sd_enable ); - reg r_address_high_lsb; - always @(posedge i_clk) begin if (i_address_high_op) begin o_bank <= `BANK_INVALID; o_prefetch <= 1'b1; - o_ddipl_request <= 1'b0; - o_sram_request <= 1'b0; + o_ddipl_pi_request <= 1'b0; + o_sram_pi_request <= 1'b0; + o_flashram_pi_request <= 1'b0; casez (i_n64_pi_ad) 16'b0000011000??????: begin // DDIPL if (i_ddipl_enable) begin o_bank <= `BANK_SDRAM; - o_ddipl_request <= 1'b1; + o_ddipl_pi_request <= 1'b1; end end 16'b000010000000000?: begin // SRAM / FlashRAM - r_address_high_lsb <= i_n64_pi_ad[0]; - if (i_flashram_enable && !i_n64_pi_ad[0]) begin - o_bank <= `BANK_FLASHRAM; + if (i_flashram_enable) begin + o_bank <= `BANK_SDRAM; + o_flashram_pi_request <= 1'b1; end else if (i_sram_enable) begin o_bank <= `BANK_SDRAM; - o_sram_request <= 1'b1; + o_sram_pi_request <= 1'b1; end end @@ -57,7 +55,7 @@ module n64_bank_decoder ( end 16'b0001111000000001: begin // EEPROM - if (i_eeprom_enable) begin + if (i_eeprom_pi_enable) begin o_bank <= `BANK_EEPROM; end end @@ -68,49 +66,6 @@ module n64_bank_decoder ( o_prefetch <= 1'b0; end end - default: begin end - endcase - end - - if (i_address_low_op) begin - case (o_bank) - `BANK_SDRAM: begin - if (o_sram_request) begin - if (i_sram_768k_mode) begin - if (r_address_high_lsb && i_n64_pi_ad[1]) begin - o_bank <= `BANK_INVALID; - end - end else begin - if (i_n64_pi_ad[1]) begin - o_bank <= `BANK_INVALID; - end - end - end - end - - `BANK_CART: begin - if (i_n64_pi_ad[15:14] != 2'b00) begin - o_bank <= `BANK_INVALID; - end - end - - `BANK_EEPROM: begin - if (i_n64_pi_ad[15:11] != 5'b00000) begin - o_bank <= `BANK_INVALID; - end - end - - `BANK_FLASHRAM: begin - if (r_address_high_lsb) begin - o_bank <= `BANK_INVALID; - end - end - - `BANK_SD: begin - if (i_n64_pi_ad[15:10] != 6'b000000) begin - o_bank <= `BANK_INVALID; - end - end default: begin end endcase diff --git a/fw/rtl/n64/n64_pi.v b/fw/rtl/n64/n64_pi.v index 39de9e8..f538103 100644 --- a/fw/rtl/n64/n64_pi.v +++ b/fw/rtl/n64/n64_pi.v @@ -20,17 +20,19 @@ module n64_pi ( input [31:0] i_data, output reg [31:0] o_data, - output o_sram_request, + output o_sram_pi_request, + output o_flashram_pi_request, input i_ddipl_enable, input i_sram_enable, - input i_sram_768k_mode, input i_flashram_enable, input i_sd_enable, - input i_eeprom_enable, + input i_eeprom_pi_enable, input [23:0] i_ddipl_address, - input [23:0] i_sram_address + input [23:0] i_save_address, + + input i_flashram_read_mode ); // Parameters @@ -88,7 +90,7 @@ module n64_pi ( // Bank decoder, address translator and prefetch signal wire w_bank_prefetch; - wire w_ddipl_request; + wire w_ddipl_pi_request; wire w_prefetch = !PREFETCH_DISABLE && w_bank_prefetch; @@ -96,19 +98,18 @@ module n64_pi ( .i_clk(i_clk), .i_address_high_op(w_address_high_op), - .i_address_low_op(w_address_low_op), .i_n64_pi_ad(io_n64_pi_ad), .o_bank(o_bank), .o_prefetch(w_bank_prefetch), - .o_ddipl_request(w_ddipl_request), - .o_sram_request(o_sram_request), + .o_ddipl_pi_request(w_ddipl_pi_request), + .o_sram_pi_request(o_sram_pi_request), + .o_flashram_pi_request(o_flashram_pi_request), .i_ddipl_enable(i_ddipl_enable), .i_sram_enable(i_sram_enable), - .i_sram_768k_mode(i_sram_768k_mode), .i_flashram_enable(i_flashram_enable), - .i_eeprom_enable(i_eeprom_enable), + .i_eeprom_pi_enable(i_eeprom_pi_enable), .i_sd_enable(i_sd_enable) ); @@ -124,6 +125,7 @@ module n64_pi ( if (r_address_valid_op) begin r_word_counter <= 1'b0; end + if (w_read_op || w_write_op) begin r_word_counter <= ~r_word_counter; end @@ -153,11 +155,13 @@ module n64_pi ( end if (i_ack) begin r_prefetch_read <= 1'b0; + if (w_prefetch) begin r_pi_read_buffer <= i_data; end else begin r_pi_output_data <= i_data; end + if (r_prefetch_read) begin r_pi_output_data <= i_data; end @@ -201,6 +205,7 @@ module n64_pi ( o_request <= 1'b0; o_write <= 1'b0; end + if (w_bus_request_op) begin if (o_request) begin r_pending_request <= 1'b1; @@ -210,6 +215,7 @@ module n64_pi ( o_write <= w_bus_write_op; end end + if (r_pending_request && !i_busy) begin o_request <= 1'b1; o_write <= r_pending_request_write; @@ -224,7 +230,7 @@ module n64_pi ( wire [9:0] w_pi_high_address = io_n64_pi_ad[9:0]; wire [15:0] w_pi_low_address = {io_n64_pi_ad[15:1], 1'b0}; wire [25:0] w_ddipl_translated_address = o_address + {i_ddipl_address, 2'b00}; - wire [25:0] w_sram_translated_address = o_address + {i_sram_address, 2'b00}; + wire [25:0] w_save_translated_address = o_address + {i_save_address, 2'b00}; reg r_first_transfer; reg [14:0] r_address_low_buffer; @@ -241,13 +247,19 @@ module n64_pi ( if (r_address_valid_op) begin r_first_transfer <= w_prefetch; r_address_low_buffer <= o_address[15:1]; - if (w_ddipl_request) begin + + if (w_ddipl_pi_request) begin o_address <= w_ddipl_translated_address; r_address_low_buffer <= w_ddipl_translated_address[15:1]; end - if (o_sram_request) begin - o_address <= w_sram_translated_address; - r_address_low_buffer <= w_sram_translated_address[15:1]; + + if (o_sram_pi_request) begin + o_address <= w_save_translated_address; + r_address_low_buffer <= w_save_translated_address[15:1]; + end + + if (o_flashram_pi_request && i_flashram_read_mode) begin + o_address <= w_save_translated_address; end end diff --git a/fw/rtl/sd/sd_interface.v b/fw/rtl/sd/sd_interface.v index 27ea16a..9fd3ec6 100644 --- a/fw/rtl/sd/sd_interface.v +++ b/fw/rtl/sd/sd_interface.v @@ -20,8 +20,8 @@ module sd_interface ( input i_dma_ack, output [3:0] o_dma_bank, output [23:0] o_dma_address, - input [31:0] i_dma_data, - output [31:0] o_dma_data + output [31:0] o_dma_data, + input [31:0] i_dma_data ); // Clock generator diff --git a/fw/rtl/top.v b/fw/rtl/top.v index 4860aee..dbc052b 100644 --- a/fw/rtl/top.v +++ b/fw/rtl/top.v @@ -33,10 +33,6 @@ module top ( 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, @@ -57,7 +53,6 @@ module top ( 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; @@ -110,42 +105,63 @@ module top ( 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_sdram; + wire w_n64_ack_sdram; + wire [31:0] w_n64_i_data_sdram; + wire w_n64_busy_eeprom; wire w_n64_ack_eeprom; wire [31:0] w_n64_i_data_eeprom; + wire w_n64_busy_flashram; + wire w_n64_ack_flashram; + wire [31:0] w_n64_i_data_flashram; + wire w_n64_busy_sd; wire w_n64_ack_sd; wire [31:0] w_n64_i_data_sd; - wire w_sram_request; + wire w_sram_pi_request; + wire w_flashram_pi_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; + wire [23:0] w_save_address; + + wire w_flashram_read_mode; 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_busy = ( + w_n64_busy_cart_control || + w_n64_busy_embedded_flash || + w_n64_busy_sdram || + w_n64_busy_eeprom || + w_n64_busy_flashram || + w_n64_busy_sd + ); + w_n64_ack = ( + w_n64_ack_cart_control || + w_n64_ack_embedded_flash || + w_n64_ack_sdram || + w_n64_ack_eeprom || + w_n64_ack_flashram || + 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_sdram) w_n64_i_data = w_n64_i_data_sdram; if (w_n64_ack_eeprom) w_n64_i_data = w_n64_i_data_eeprom; + if (w_n64_ack_flashram) w_n64_i_data = w_n64_i_data_flashram; if (w_n64_ack_sd) w_n64_i_data = w_n64_i_data_sd; end @@ -169,17 +185,19 @@ module top ( .i_data(w_n64_i_data), .o_data(w_n64_o_data), - .o_sram_request(w_sram_request), + .o_sram_pi_request(w_sram_pi_request), + .o_flashram_pi_request(w_flashram_pi_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_eeprom_pi_enable(w_eeprom_pi_enable), .i_ddipl_address(w_ddipl_address), - .i_sram_address(w_sram_address) + .i_save_address(w_save_address), + + .i_flashram_read_mode(w_flashram_read_mode) ); @@ -321,7 +339,6 @@ module top ( .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), @@ -330,7 +347,7 @@ module top ( .o_n64_reset_btn(w_n64_reset_btn), - .i_debug_ready(1'b1), + .i_debug_ready(1'b1), // TODO: Detect USB cable insertion .o_debug_dma_start(w_debug_dma_start), .i_debug_dma_busy(w_debug_dma_busy), @@ -344,29 +361,16 @@ module top ( .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) + .o_save_address(w_save_address) ); // SD card - wire w_n64_request_sd = w_n64_request && w_n64_bank == `BANK_SD; + wire w_n64_request_sd = ( + w_n64_request && + w_n64_bank == `BANK_SD + ); wire w_sd_dma_request; wire w_sd_dma_write; @@ -415,14 +419,83 @@ module top ( .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) + .o_dma_data(w_sd_dma_o_data), + .i_dma_data(w_sd_dma_i_data) + ); + + + // FlashRAM + + wire w_flashram_request_n64 = ( + w_n64_request && + w_flashram_pi_request && + w_n64_bank == `BANK_SDRAM + ); + + wire w_flashram_dma_request; + wire w_flashram_dma_write; + wire w_flashram_dma_busy; + wire w_flashram_dma_ack; + wire [3:0] w_flashram_dma_bank; + wire [23:0] w_flashram_dma_address; + wire [31:0] w_flashram_dma_i_data; + wire [31:0] w_flashram_dma_o_data; + + flashram_controller flashram_controller_inst ( + .i_clk(w_sys_clk), + .i_reset(w_sys_reset), + + .i_save_address(w_save_address), + + .o_flashram_read_mode(w_flashram_read_mode), + + .i_request(w_flashram_request_n64), + .i_write(w_n64_write), + .o_busy(w_n64_busy_flashram), + .o_ack(w_n64_ack_flashram), + .i_address(w_n64_address[16:2]), + .o_data(w_n64_i_data_flashram), + .i_data(w_n64_o_data), + + .o_mem_request(w_flashram_dma_request), + .o_mem_write(w_flashram_dma_write), + .i_mem_busy(w_flashram_dma_busy), + .i_mem_ack(w_flashram_dma_ack), + .o_mem_bank(w_flashram_dma_bank), + .o_mem_address(w_flashram_dma_address), + .o_mem_data(w_flashram_dma_o_data), + .i_mem_data(w_flashram_dma_i_data) + ); + + + // Embedded flash in FPGA + + 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) ); // 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_n64 = w_n64_request && ( + (w_rom_switch && (w_sdram_writable || !w_n64_write) && !w_flashram_pi_request) || + w_sram_pi_request || + (w_flashram_pi_request && w_flashram_read_mode && !w_n64_write) + ); wire w_sdram_request; wire w_sdram_write; @@ -433,21 +506,21 @@ module top ( wire [31:0] w_sdram_i_data; device_arbiter #( - .NUM_CONTROLLERS(3), + .NUM_CONTROLLERS(4), .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}), + .i_request({w_flashram_dma_request, w_sd_dma_request, w_pc_request, w_sdram_request_n64}), + .i_write({w_flashram_dma_write, w_sd_dma_write, w_pc_write, w_n64_write}), + .o_busy({w_flashram_dma_busy, w_sd_dma_busy_sdram, w_pc_busy_sdram, w_n64_busy_sdram}), + .o_ack({w_flashram_dma_ack, w_sd_dma_ack_sdram, w_pc_ack_sdram, w_n64_ack_sdram}), + .i_bank({w_flashram_dma_bank, w_sd_dma_bank, w_pc_bank, w_n64_bank}), + .i_address({{w_flashram_dma_address, 1'b0}, {w_sd_dma_address, 1'b0}, w_pc_address[25:1], w_n64_address[25:1]}), + .o_data({w_flashram_dma_i_data, w_sd_dma_i_data_sdram, w_pc_i_data_sdram, w_n64_i_data_sdram}), + .i_data({w_flashram_dma_o_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), @@ -480,7 +553,7 @@ module top ( ); - // EEPROM 4/16k + // N64 SI (EEPROM 4/16k and RTC) wire w_eeprom_request; wire w_eeprom_write; @@ -539,7 +612,11 @@ module top ( // LED - wire w_led_trigger = (w_n64_request && !w_n64_busy) || (w_pc_request && !w_pc_busy) || (w_sd_dma_request && !w_sd_dma_busy); + wire w_led_trigger = ( + (w_n64_request && !w_n64_busy) || + (w_pc_request && !w_pc_busy) || + (w_sd_dma_request && !w_sd_dma_busy) + ); cart_led cart_led_inst ( .i_clk(w_sys_clk), diff --git a/sw/bootloader/src/main.c b/sw/bootloader/src/main.c index e278996..b5e3956 100644 --- a/sw/bootloader/src/main.c +++ b/sw/bootloader/src/main.c @@ -93,15 +93,16 @@ int main(void) { switch (config.save_type) { case 1: sc64_enable_eeprom(false); break; case 2: sc64_enable_eeprom(true); break; - case 3: sc64_enable_sram(false); break; - case 4: sc64_enable_sram(true); break; - case 5: sc64_enable_flashram(); break; + case 3: + case 4: sc64_enable_sram(); break; + case 5: + case 6: sc64_enable_flashram(); break; } - if (config.save_type == 3) { - sc64_set_sram_address(SC64_SDRAM_SIZE - (32 * 1024)); - } else if (config.save_type == 4) { - sc64_set_sram_address(SC64_SDRAM_SIZE - (3 * 32 * 1024)); + if (config.save_type >= 3 || config.save_type <= 5) { + sc64_set_save_address(SC64_SDRAM_SIZE - (128 * 1024)); + } else if (config.save_type == 6) { + sc64_set_save_address(0x01618000); } if (rom_loaded && (config.save[0] != '\0') && config.save_writeback) { diff --git a/sw/bootloader/src/sc64/sc64.c b/sw/bootloader/src/sc64/sc64.c index 2dd6767..15f0d78 100644 --- a/sw/bootloader/src/sc64/sc64.c +++ b/sw/bootloader/src/sc64/sc64.c @@ -41,13 +41,8 @@ void sc64_disable_flashram(void) { sc64_disable_peripheral(SC64_CART_SCR_FLASHRAM_ENABLE); } -void sc64_enable_sram(bool mode_768k) { +void sc64_enable_sram(void) { sc64_enable_peripheral(SC64_CART_SCR_SRAM_ENABLE); - if (mode_768k) { - sc64_enable_peripheral(SC64_CART_SCR_SRAM_768K_MODE); - } else { - sc64_disable_peripheral(SC64_CART_SCR_SRAM_768K_MODE); - } } void sc64_disable_sram(void) { @@ -127,10 +122,10 @@ void sc64_set_ddipl_address(uint32_t address) { platform_pi_io_write(&SC64_CART->DDIPL_ADDR, address & SC64_CART_DDIPL_ADDR_ADDRESS_MASK); } -uint32_t sc64_get_sram_address(void) { +uint32_t sc64_get_save_address(void) { return platform_pi_io_read(&SC64_CART->SRAM_ADDR) & SC64_CART_SRAM_ADDR_ADDRESS_MASK; } -void sc64_set_sram_address(uint32_t address) { +void sc64_set_save_address(uint32_t address) { platform_pi_io_write(&SC64_CART->SRAM_ADDR, address & SC64_CART_SRAM_ADDR_ADDRESS_MASK); } diff --git a/sw/bootloader/src/sc64/sc64.h b/sw/bootloader/src/sc64/sc64.h index 0b30bee..81f9788 100644 --- a/sw/bootloader/src/sc64/sc64.h +++ b/sw/bootloader/src/sc64/sc64.h @@ -14,7 +14,7 @@ void sc64_enable_skip_bootloader(void); void sc64_disable_skip_bootloader(void); void sc64_enable_flashram(void); void sc64_disable_flashram(void); -void sc64_enable_sram(bool mode_768k); +void sc64_enable_sram(void); void sc64_disable_sram(void); void sc64_enable_sd(void); void sc64_disable_sd(void); @@ -33,8 +33,8 @@ void sc64_set_boot_mode(uint32_t boot); uint32_t sc64_get_version(void); uint32_t sc64_get_ddipl_address(void); void sc64_set_ddipl_address(uint32_t address); -uint32_t sc64_get_sram_address(void); -void sc64_set_sram_address(uint32_t address); +uint32_t sc64_get_save_address(void); +void sc64_set_save_address(uint32_t address); #endif diff --git a/sw/bootloader/src/sc64/sc64_regs.h b/sw/bootloader/src/sc64/sc64_regs.h index 06c543e..ab56e5a 100644 --- a/sw/bootloader/src/sc64/sc64_regs.h +++ b/sw/bootloader/src/sc64/sc64_regs.h @@ -11,8 +11,7 @@ #define SC64_BANK_SDRAM (1) #define SC64_BANK_CART (2) #define SC64_BANK_EEPROM (3) -#define SC64_BANK_FLASHRAM (4) -#define SC64_BANK_SD (5) +#define SC64_BANK_SD (4) // Cart Interface Registers diff --git a/sw/bootloader/src/sc64/sc64_sd_fs.c b/sw/bootloader/src/sc64/sc64_sd_fs.c index 3a274ae..5a00f42 100644 --- a/sw/bootloader/src/sc64/sc64_sd_fs.c +++ b/sw/bootloader/src/sc64/sc64_sd_fs.c @@ -156,14 +156,10 @@ sc64_sd_fs_error_t sc64_sd_fs_load_save(const char *path) { length = (scr & SC64_CART_SCR_EEPROM_16K_MODE) ? 2048 : 512; current_bank = SC64_BANK_EEPROM; current_offset = 0; - } else if (scr & SC64_CART_SCR_SRAM_ENABLE) { - length = ((scr & SC64_CART_SCR_SRAM_768K_MODE) ? 3 : 1) * (32 * 1024); + } else if (scr & (SC64_CART_SCR_SRAM_ENABLE | SC64_CART_SCR_FLASHRAM_ENABLE)) { + length = 128 * 1024; current_bank = SC64_BANK_SDRAM; - current_offset = sc64_get_sram_address(); - } else if (scr & SC64_CART_SCR_FLASHRAM_ENABLE) { // TODO: FlashRAM - length = 0; - current_bank = SC64_BANK_FLASHRAM; - current_offset = 0; + current_offset = sc64_get_save_address(); } if ((length == 0) || (path == NULL)) { @@ -203,14 +199,10 @@ sc64_sd_fs_error_t sc64_sd_fs_store_save(const char *path) { platform_pi_dma_read(save_buffer, &SC64_EEPROM->MEM, length); platform_cache_invalidate(save_buffer, length); sc64_disable_eeprom_pi(); - } else if (scr & SC64_CART_SCR_SRAM_ENABLE) { - length = ((scr & SC64_CART_SCR_SRAM_768K_MODE) ? 3 : 1) * (32 * 1024); - platform_pi_dma_read(save_buffer, sc64_get_sram_address(), length); + } else if (scr & (SC64_CART_SCR_SRAM_ENABLE | SC64_CART_SCR_FLASHRAM_ENABLE)) { + length = 128 * 1024; + platform_pi_dma_read(save_buffer, sc64_get_save_address(), length); platform_cache_invalidate(save_buffer, length); - } else if (scr & SC64_CART_SCR_FLASHRAM_ENABLE) { // TODO: FlashRAM - length = 0; - // platform_pi_dma_read(save_buffer, 0, length); - // platform_cache_invalidate(save_buffer, length); } if ((length == 0) || (path == NULL)) {