mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-21 21:49:15 +01:00
[SC64][FW][SW] USB debug interface, SD Card interface and bootloader, SRAM save emulation, SDRAM constraints, general improvements (#3)
This commit is contained in:
parent
67fbbc40e4
commit
b2395a4726
11
README.md
11
README.md
@ -55,17 +55,14 @@ Instructions below are mostly written for Windows users and point to Windows spe
|
||||
|
||||
There are several issues with the project at the moment in order of importance. Keep in mind that core flashcart functionality is fully working:
|
||||
|
||||
- No debug interface for the [N64-UNFLoader](https://github.com/buu342/N64-UNFLoader).
|
||||
- No read functionality through USB interface.
|
||||
- No SRAM/FlashRAM save hardware implementation.
|
||||
- No SD card interface hardware implementation.
|
||||
- No save write-back to SD card hardware implementation.
|
||||
- No RTC hardware implementation.
|
||||
- No FlashRAM save emulation implementation.
|
||||
- No save write-back to SD card implementation.
|
||||
- No RTC implementation.
|
||||
|
||||
|
||||
## What's next
|
||||
|
||||
Current goal is to write debug module for the [N64-UNFLoader](https://github.com/buu342/N64-UNFLoader).
|
||||
Current goal is to fix bugs in SDRAM and PC modules.
|
||||
|
||||
|
||||
## Finished sample
|
||||
|
12
build_pcb.sh → build_pcb_v1.sh
Executable file → Normal file
12
build_pcb.sh → build_pcb_v1.sh
Executable file → Normal file
@ -3,12 +3,12 @@
|
||||
PACKAGES_FOLDER_NAME="packages"
|
||||
PACKAGE_FILE_NAME="SummerCart64_PCB"
|
||||
FILES=(
|
||||
"./hw/CAMOutputs"
|
||||
"./hw/v1/CAMOutputs"
|
||||
# Manually created files
|
||||
"./hw/SummerCart64_sch.pdf"
|
||||
"./hw/SummerCart64_brd_top.pdf"
|
||||
"./hw/SummerCart64_brd_bot.pdf"
|
||||
"./hw/SummerCart64_brd_place_top.pdf"
|
||||
"./hw/v1/SummerCart64_sch.pdf"
|
||||
"./hw/v1/SummerCart64_brd_top.pdf"
|
||||
"./hw/v1/SummerCart64_brd_bot.pdf"
|
||||
"./hw/v1/SummerCart64_brd_place_top.pdf"
|
||||
)
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ fi
|
||||
|
||||
|
||||
# Generate Gerbers
|
||||
pushd hw
|
||||
pushd hw/v1
|
||||
if [[ -e CAMOutputs ]]; then
|
||||
rm -rf CAMOutputs
|
||||
fi
|
@ -18,7 +18,7 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Quartus Prime
|
||||
# Version 20.1.0 Build 711 06/05/2020 SJ Lite Edition
|
||||
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
|
||||
# Date created = 00:00:00 November 06, 2020
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
@ -42,39 +42,105 @@
|
||||
# ========================
|
||||
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 20.1.0
|
||||
set_global_assignment -name PROJECT_CREATION_TIME_DATE "23:45:19 JULY 29, 2020"
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION "20.1.0 Lite Edition"
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION "20.1.1 Lite Edition"
|
||||
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
||||
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
|
||||
set_global_assignment -name SMART_RECOMPILE OFF
|
||||
set_global_assignment -name VERILOG_FILE rtl/cart/control.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/usb/pc.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/usb/ftdi_fsi.v
|
||||
set_global_assignment -name QSYS_FILE rtl/intel/flash/onchip_flash.qsys
|
||||
set_global_assignment -name VERILOG_FILE rtl/glue/device_arbiter.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/intel/gpio/gpio_ddro/altera_gpio_lite.sv -library gpio_ddro
|
||||
set_global_assignment -name NUM_PARALLEL_PROCESSORS 16
|
||||
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_n64_eeprom.qip
|
||||
set_global_assignment -name VERILOG_FILE rtl/memory/sdram.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/memory/embedded_flash.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/n64/si.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/n64/pi.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/n64/bank_decoder.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/top.v
|
||||
set_global_assignment -name QIP_FILE rtl/intel/ram/ram_sd_buffer.qip
|
||||
set_global_assignment -name QSYS_FILE rtl/intel/flash/onchip_flash.qsys
|
||||
set_global_assignment -name SDC_FILE constraints.sdc
|
||||
set_global_assignment -name QIP_FILE rtl/intel/fifo/fifo_ack.qip
|
||||
set_global_assignment -name SIGNALTAP_FILE output_files/signal_tap_logic_analyzer.stp
|
||||
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/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
|
||||
set_global_assignment -name VERILOG_FILE rtl/n64/n64_bank_decoder.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/n64/n64_pi.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/n64/n64_si.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/sd/sd_dma.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/sd/sd_interface.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/top.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/usb/usb_ftdi_fsi.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/usb/usb_pc.v
|
||||
set_global_assignment -name VERILOG_INCLUDE_FILE rtl/constants.vh
|
||||
set_global_assignment -name SLD_FILE db/signal_tap_logic_analyzer_auto_stripped.stp
|
||||
|
||||
# Pin & Location Assignments
|
||||
# ==========================
|
||||
set_location_assignment PIN_6 -to io_pmod[3]
|
||||
set_location_assignment PIN_7 -to io_pmod[4]
|
||||
set_location_assignment PIN_8 -to io_pmod[5]
|
||||
set_location_assignment PIN_10 -to io_pmod[6]
|
||||
set_location_assignment PIN_11 -to io_pmod[7]
|
||||
set_location_assignment PIN_12 -to o_ftdi_si
|
||||
set_location_assignment PIN_13 -to o_ftdi_clk
|
||||
set_location_assignment PIN_14 -to i_ftdi_so
|
||||
set_location_assignment PIN_15 -to i_ftdi_cts
|
||||
set_location_assignment PIN_17 -to o_led
|
||||
set_location_assignment PIN_21 -to o_rtc_scl
|
||||
set_location_assignment PIN_22 -to io_rtc_sda
|
||||
set_location_assignment PIN_24 -to io_n64_si_dq
|
||||
set_location_assignment PIN_25 -to i_n64_nmi
|
||||
set_location_assignment PIN_26 -to i_clk
|
||||
set_location_assignment PIN_98 -to io_sdram_dq[0]
|
||||
set_location_assignment PIN_97 -to io_sdram_dq[1]
|
||||
set_location_assignment PIN_96 -to io_sdram_dq[2]
|
||||
set_location_assignment PIN_93 -to io_sdram_dq[3]
|
||||
set_location_assignment PIN_92 -to io_sdram_dq[4]
|
||||
set_location_assignment PIN_91 -to io_sdram_dq[5]
|
||||
set_location_assignment PIN_90 -to io_sdram_dq[6]
|
||||
set_location_assignment PIN_27 -to i_n64_reset
|
||||
set_location_assignment PIN_28 -to i_n64_si_clk
|
||||
set_location_assignment PIN_29 -to i_n64_cic_clk
|
||||
set_location_assignment PIN_30 -to io_n64_cic_dq
|
||||
set_location_assignment PIN_32 -to io_n64_pi_ad[7]
|
||||
set_location_assignment PIN_33 -to io_n64_pi_ad[8]
|
||||
set_location_assignment PIN_38 -to io_n64_pi_ad[6]
|
||||
set_location_assignment PIN_39 -to io_n64_pi_ad[9]
|
||||
set_location_assignment PIN_41 -to io_n64_pi_ad[5]
|
||||
set_location_assignment PIN_43 -to io_n64_pi_ad[10]
|
||||
set_location_assignment PIN_44 -to io_n64_pi_ad[4]
|
||||
set_location_assignment PIN_45 -to io_n64_pi_ad[11]
|
||||
set_location_assignment PIN_46 -to i_n64_pi_aleh
|
||||
set_location_assignment PIN_47 -to i_n64_pi_read
|
||||
set_location_assignment PIN_48 -to i_n64_pi_write
|
||||
set_location_assignment PIN_50 -to i_n64_pi_alel
|
||||
set_location_assignment PIN_52 -to io_n64_pi_ad[12]
|
||||
set_location_assignment PIN_54 -to io_n64_pi_ad[3]
|
||||
set_location_assignment PIN_55 -to io_n64_pi_ad[13]
|
||||
set_location_assignment PIN_56 -to io_n64_pi_ad[2]
|
||||
set_location_assignment PIN_57 -to io_n64_pi_ad[14]
|
||||
set_location_assignment PIN_58 -to io_n64_pi_ad[1]
|
||||
set_location_assignment PIN_59 -to io_n64_pi_ad[15]
|
||||
set_location_assignment PIN_60 -to io_n64_pi_ad[0]
|
||||
set_location_assignment PIN_61 -to o_sdram_a[4]
|
||||
set_location_assignment PIN_62 -to o_sdram_a[5]
|
||||
set_location_assignment PIN_64 -to o_sdram_a[6]
|
||||
set_location_assignment PIN_65 -to o_sdram_a[7]
|
||||
set_location_assignment PIN_66 -to o_sdram_a[8]
|
||||
set_location_assignment PIN_69 -to o_sdram_a[9]
|
||||
set_location_assignment PIN_70 -to o_sdram_a[11]
|
||||
set_location_assignment PIN_74 -to o_sdram_a[12]
|
||||
set_location_assignment PIN_75 -to o_sdram_clk
|
||||
set_location_assignment PIN_76 -to o_sdram_a[3]
|
||||
set_location_assignment PIN_77 -to o_sdram_a[2]
|
||||
set_location_assignment PIN_78 -to o_sdram_a[1]
|
||||
set_location_assignment PIN_79 -to o_sdram_a[0]
|
||||
set_location_assignment PIN_80 -to o_sdram_a[10]
|
||||
set_location_assignment PIN_81 -to o_sdram_ba[1]
|
||||
set_location_assignment PIN_84 -to o_sdram_ba[0]
|
||||
set_location_assignment PIN_85 -to o_sdram_cs
|
||||
set_location_assignment PIN_86 -to o_sdram_ras
|
||||
set_location_assignment PIN_87 -to o_sdram_cas
|
||||
set_location_assignment PIN_88 -to o_sdram_we
|
||||
set_location_assignment PIN_89 -to io_sdram_dq[7]
|
||||
set_location_assignment PIN_90 -to io_sdram_dq[6]
|
||||
set_location_assignment PIN_91 -to io_sdram_dq[5]
|
||||
set_location_assignment PIN_92 -to io_sdram_dq[4]
|
||||
set_location_assignment PIN_93 -to io_sdram_dq[3]
|
||||
set_location_assignment PIN_96 -to io_sdram_dq[2]
|
||||
set_location_assignment PIN_97 -to io_sdram_dq[1]
|
||||
set_location_assignment PIN_98 -to io_sdram_dq[0]
|
||||
set_location_assignment PIN_99 -to io_sdram_dq[8]
|
||||
set_location_assignment PIN_100 -to io_sdram_dq[9]
|
||||
set_location_assignment PIN_101 -to io_sdram_dq[10]
|
||||
@ -83,85 +149,27 @@ set_location_assignment PIN_105 -to io_sdram_dq[12]
|
||||
set_location_assignment PIN_106 -to io_sdram_dq[13]
|
||||
set_location_assignment PIN_110 -to io_sdram_dq[14]
|
||||
set_location_assignment PIN_111 -to io_sdram_dq[15]
|
||||
set_location_assignment PIN_79 -to o_sdram_a[0]
|
||||
set_location_assignment PIN_78 -to o_sdram_a[1]
|
||||
set_location_assignment PIN_77 -to o_sdram_a[2]
|
||||
set_location_assignment PIN_76 -to o_sdram_a[3]
|
||||
set_location_assignment PIN_61 -to o_sdram_a[4]
|
||||
set_location_assignment PIN_62 -to o_sdram_a[5]
|
||||
set_location_assignment PIN_64 -to o_sdram_a[6]
|
||||
set_location_assignment PIN_65 -to o_sdram_a[7]
|
||||
set_location_assignment PIN_66 -to o_sdram_a[8]
|
||||
set_location_assignment PIN_69 -to o_sdram_a[9]
|
||||
set_location_assignment PIN_80 -to o_sdram_a[10]
|
||||
set_location_assignment PIN_70 -to o_sdram_a[11]
|
||||
set_location_assignment PIN_74 -to o_sdram_a[12]
|
||||
set_location_assignment PIN_84 -to o_sdram_ba[0]
|
||||
set_location_assignment PIN_81 -to o_sdram_ba[1]
|
||||
set_location_assignment PIN_75 -to o_sdram_clk
|
||||
set_location_assignment PIN_85 -to o_sdram_cs
|
||||
set_location_assignment PIN_87 -to o_sdram_cas
|
||||
set_location_assignment PIN_86 -to o_sdram_ras
|
||||
set_location_assignment PIN_88 -to o_sdram_we
|
||||
set_location_assignment PIN_112 -to io_sd_dat[1]
|
||||
set_location_assignment PIN_113 -to io_sd_dat[0]
|
||||
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_112 -to io_sd_dat[1]
|
||||
set_location_assignment PIN_113 -to io_sd_dat[0]
|
||||
set_location_assignment PIN_134 -to o_flash_cs
|
||||
set_location_assignment PIN_131 -to o_flash_clk
|
||||
set_location_assignment PIN_132 -to io_flash_dq[3]
|
||||
set_location_assignment PIN_136 -to io_flash_dq[2]
|
||||
set_location_assignment PIN_135 -to io_flash_dq[1]
|
||||
set_location_assignment PIN_130 -to io_flash_dq[0]
|
||||
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_127 -to io_sram_dq[2]
|
||||
set_location_assignment PIN_126 -to io_sram_dq[1]
|
||||
set_location_assignment PIN_121 -to io_sram_dq[0]
|
||||
set_location_assignment PIN_124 -to o_sram_cs
|
||||
set_location_assignment PIN_24 -to io_n64_si_dq
|
||||
set_location_assignment PIN_25 -to i_n64_nmi
|
||||
set_location_assignment PIN_27 -to i_n64_reset
|
||||
set_location_assignment PIN_28 -to i_n64_si_clk
|
||||
set_location_assignment PIN_46 -to i_n64_pi_aleh
|
||||
set_location_assignment PIN_50 -to i_n64_pi_alel
|
||||
set_location_assignment PIN_47 -to i_n64_pi_read
|
||||
set_location_assignment PIN_48 -to i_n64_pi_write
|
||||
set_location_assignment PIN_60 -to io_n64_pi_ad[0]
|
||||
set_location_assignment PIN_58 -to io_n64_pi_ad[1]
|
||||
set_location_assignment PIN_56 -to io_n64_pi_ad[2]
|
||||
set_location_assignment PIN_54 -to io_n64_pi_ad[3]
|
||||
set_location_assignment PIN_44 -to io_n64_pi_ad[4]
|
||||
set_location_assignment PIN_41 -to io_n64_pi_ad[5]
|
||||
set_location_assignment PIN_38 -to io_n64_pi_ad[6]
|
||||
set_location_assignment PIN_32 -to io_n64_pi_ad[7]
|
||||
set_location_assignment PIN_33 -to io_n64_pi_ad[8]
|
||||
set_location_assignment PIN_39 -to io_n64_pi_ad[9]
|
||||
set_location_assignment PIN_43 -to io_n64_pi_ad[10]
|
||||
set_location_assignment PIN_45 -to io_n64_pi_ad[11]
|
||||
set_location_assignment PIN_52 -to io_n64_pi_ad[12]
|
||||
set_location_assignment PIN_55 -to io_n64_pi_ad[13]
|
||||
set_location_assignment PIN_57 -to io_n64_pi_ad[14]
|
||||
set_location_assignment PIN_59 -to io_n64_pi_ad[15]
|
||||
set_location_assignment PIN_29 -to i_n64_cic_clk
|
||||
set_location_assignment PIN_30 -to io_n64_cic_dq
|
||||
set_location_assignment PIN_126 -to io_sram_dq[1]
|
||||
set_location_assignment PIN_127 -to io_sram_dq[2]
|
||||
set_location_assignment PIN_130 -to io_flash_dq[0]
|
||||
set_location_assignment PIN_131 -to o_flash_clk
|
||||
set_location_assignment PIN_132 -to io_flash_dq[3]
|
||||
set_location_assignment PIN_134 -to o_flash_cs
|
||||
set_location_assignment PIN_135 -to io_flash_dq[1]
|
||||
set_location_assignment PIN_136 -to io_flash_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]
|
||||
set_location_assignment PIN_6 -to io_pmod[3]
|
||||
set_location_assignment PIN_7 -to io_pmod[4]
|
||||
set_location_assignment PIN_8 -to io_pmod[5]
|
||||
set_location_assignment PIN_10 -to io_pmod[6]
|
||||
set_location_assignment PIN_11 -to io_pmod[7]
|
||||
set_location_assignment PIN_22 -to io_rtc_sda
|
||||
set_location_assignment PIN_21 -to o_rtc_scl
|
||||
set_location_assignment PIN_17 -to o_led
|
||||
set_location_assignment PIN_15 -to i_ftdi_cts
|
||||
set_location_assignment PIN_14 -to i_ftdi_so
|
||||
set_location_assignment PIN_13 -to o_ftdi_clk
|
||||
set_location_assignment PIN_12 -to o_ftdi_si
|
||||
|
||||
# Classic Timing Assignments
|
||||
# ==========================
|
||||
@ -210,7 +218,7 @@ set_global_assignment -name GENERATE_SVF_FILE ON
|
||||
|
||||
# Signal Tap Assignments
|
||||
# ======================
|
||||
set_global_assignment -name ENABLE_SIGNALTAP OFF
|
||||
set_global_assignment -name ENABLE_SIGNALTAP ON
|
||||
set_global_assignment -name USE_SIGNALTAP_FILE output_files/signal_tap_logic_analyzer.stp
|
||||
|
||||
# Power Estimation Assignments
|
||||
@ -249,14 +257,16 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
||||
|
||||
# Fitter Assignments
|
||||
# ==================
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_n64_si_dq
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_n64_cic_dq
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_cic_clk
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_nmi
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_aleh
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_alel
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_read
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_write
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_alel
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_cic_clk
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_reset
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_si_clk
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_n64_cic_dq
|
||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_n64_si_dq
|
||||
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to i_clk
|
||||
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to "pll:sys_pll|altpll:altpll_component|pll_altpll:auto_generated|wire_pll1_clk[0]"
|
||||
set_instance_assignment -name GLOBAL_SIGNAL GLOBAL_CLOCK -to "pll:sys_pll|altpll:altpll_component|pll_altpll:auto_generated|wire_pll1_clk[1]"
|
||||
|
@ -1,5 +1,61 @@
|
||||
create_clock -name i_clk -period 20 [get_ports i_clk]
|
||||
# Clocks
|
||||
|
||||
derive_pll_clocks -create_base_clocks
|
||||
|
||||
set sys_clk {sys_pll|altpll_component|auto_generated|pll1|clk[0]}
|
||||
set sdram_pll_clk {sys_pll|altpll_component|auto_generated|pll1|clk[1]}
|
||||
|
||||
create_generated_clock -name sdram_clk -source [get_pins $sdram_pll_clk] -master_clock $sdram_pll_clk [get_ports {o_sdram_clk}]
|
||||
create_generated_clock -name flash_se_neg_reg -divide_by 2 \
|
||||
-source [get_pins -compatibility_mode {*altera_onchip_flash:*onchip_flash_0|altera_onchip_flash_avmm_data_controller:avmm_data_controller|flash_se_neg_reg|clk}] \
|
||||
[get_pins -compatibility_mode {*altera_onchip_flash:*onchip_flash_0|altera_onchip_flash_avmm_data_controller:avmm_data_controller|flash_se_neg_reg|q}]
|
||||
|
||||
derive_clock_uncertainty
|
||||
|
||||
|
||||
# SDRAM timings
|
||||
|
||||
set sdram_outputs {o_sdram_cs o_sdram_ras o_sdram_cas o_sdram_we o_sdram_a[*] o_sdram_ba[*] io_sdram_dq[*]}
|
||||
set sdram_inputs {io_sdram_dq[*]}
|
||||
|
||||
set_output_delay -clock [get_clocks {sdram_clk}] -max 1.5 [get_ports $sdram_outputs]
|
||||
set_output_delay -clock [get_clocks {sdram_clk}] -min -0.8 [get_ports $sdram_outputs]
|
||||
|
||||
set_input_delay -clock [get_clocks {sdram_clk}] -max 5.4 [get_ports $sdram_inputs]
|
||||
set_input_delay -clock [get_clocks {sdram_clk}] -min 2.5 [get_ports $sdram_inputs]
|
||||
|
||||
set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks $sys_clk]
|
||||
|
||||
|
||||
# FTDI timings
|
||||
|
||||
set_false_path -to [get_ports {o_ftdi_clk o_ftdi_si}]
|
||||
set_false_path -from [get_ports {i_ftdi_so i_ftdi_cts}]
|
||||
|
||||
|
||||
# SD card timings
|
||||
|
||||
set_false_path -to [get_ports {o_sd_clk io_sd_cmd io_sd_dat[*]}]
|
||||
set_false_path -from [get_ports {io_sd_cmd io_sd_dat[*]}]
|
||||
|
||||
|
||||
# N64, PI and SI timings
|
||||
|
||||
set_false_path -from [get_ports {i_n64_reset i_n64_nmi}]
|
||||
|
||||
set_false_path -to [get_ports {io_n64_pi_ad[*]}]
|
||||
set_false_path -from [get_ports {i_n64_pi_* io_n64_pi_ad[*]}]
|
||||
|
||||
set_false_path -to [get_ports {io_n64_si_dq}]
|
||||
set_false_path -from [get_ports {i_n64_si_clk io_n64_si_dq}]
|
||||
|
||||
|
||||
# LED timings
|
||||
|
||||
set_false_path -to [get_ports {o_led}]
|
||||
|
||||
|
||||
# PMOD timings
|
||||
|
||||
set_false_path -to [get_ports {io_pmod[*]}]
|
||||
set_false_path -from [get_ports {io_pmod[*]}]
|
||||
|
218
fw/rtl/cart/cart_control.v
Normal file
218
fw/rtl/cart/cart_control.v
Normal file
@ -0,0 +1,218 @@
|
||||
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_sram_768k_mode,
|
||||
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,
|
||||
|
||||
output reg o_n64_reset_btn,
|
||||
|
||||
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_sram_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_SRAM_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;
|
||||
|
||||
|
||||
// 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_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_debug_dma_bank <= 4'd1;
|
||||
o_debug_dma_address <= 24'hFC_0000;
|
||||
o_debug_dma_length <= 20'd0;
|
||||
r_bootloader <= 16'h0000;
|
||||
end else begin
|
||||
if (i_request && i_write && !o_busy) begin
|
||||
case (i_address[3:0])
|
||||
REG_SCR: begin
|
||||
{
|
||||
o_flashram_enable,
|
||||
o_sram_768k_mode,
|
||||
o_sram_enable,
|
||||
o_sd_enable,
|
||||
o_eeprom_pi_enable,
|
||||
o_eeprom_16k_mode,
|
||||
o_eeprom_enable,
|
||||
o_ddipl_enable,
|
||||
o_rom_switch,
|
||||
o_sdram_writable
|
||||
} <= i_data[9: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
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (!r_reset_ff2 || !r_nmi_ff2) begin
|
||||
o_sdram_writable <= 1'b0;
|
||||
o_rom_switch <= 1'b0;
|
||||
o_n64_reset_btn <= 1'b1;
|
||||
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
|
||||
case (i_address[3:0])
|
||||
REG_SCR: begin
|
||||
o_data[9:0] <= {
|
||||
o_flashram_enable,
|
||||
o_sram_768k_mode,
|
||||
o_sram_enable,
|
||||
o_sd_enable,
|
||||
o_eeprom_pi_enable,
|
||||
o_eeprom_16k_mode,
|
||||
o_eeprom_enable,
|
||||
o_ddipl_enable,
|
||||
o_rom_switch,
|
||||
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
|
||||
end
|
||||
endcase
|
||||
end else begin
|
||||
o_data <= i_debug_fifo_data;
|
||||
o_debug_fifo_request <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
28
fw/rtl/cart/cart_led.v
Normal file
28
fw/rtl/cart/cart_led.v
Normal file
@ -0,0 +1,28 @@
|
||||
module cart_led (
|
||||
input i_clk,
|
||||
input i_reset,
|
||||
|
||||
input i_trigger,
|
||||
|
||||
output o_led
|
||||
);
|
||||
|
||||
localparam COUNTER_LOAD_VALUE = 5'd31;
|
||||
|
||||
reg [4:0] r_counter;
|
||||
|
||||
assign o_led = r_counter > 5'd0;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
r_counter <= 5'd0;
|
||||
end else begin
|
||||
if (i_trigger) begin
|
||||
r_counter <= COUNTER_LOAD_VALUE;
|
||||
end else if (r_counter > 5'd0) begin
|
||||
r_counter <= r_counter - 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -1,77 +0,0 @@
|
||||
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 [0:0] i_address,
|
||||
output reg [31:0] o_data,
|
||||
input [31:0] i_data,
|
||||
|
||||
output reg o_rom_switch,
|
||||
output reg o_eeprom_enable,
|
||||
output reg o_eeprom_16k_mode
|
||||
);
|
||||
|
||||
// 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 [31:0] r_bootloader;
|
||||
|
||||
|
||||
// Bus controller
|
||||
|
||||
assign o_busy = 1'b0;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
o_ack <= 1'b0;
|
||||
end else begin
|
||||
o_ack <= i_request && !i_write && !o_busy;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
o_rom_switch <= 1'b0;
|
||||
o_eeprom_enable <= 1'b0;
|
||||
o_eeprom_16k_mode <= 1'b0;
|
||||
r_bootloader <= 32'h0000_0000;
|
||||
end else begin
|
||||
if (i_request && i_write && !o_busy) begin
|
||||
case (i_address)
|
||||
1'd0: {o_eeprom_16k_mode, o_eeprom_enable, o_rom_switch} <= {i_data[4], i_data[3], i_data[1]};
|
||||
1'd1: r_bootloader <= i_data;
|
||||
endcase
|
||||
end
|
||||
if (!r_reset_ff2 || !r_nmi_ff2) begin
|
||||
o_rom_switch <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_request && !i_write && !o_busy) begin
|
||||
case (i_address)
|
||||
1'd0: o_data <= {o_eeprom_16k_mode, o_eeprom_enable, 1'b0, o_rom_switch, 1'b0};
|
||||
1'd1: o_data <= r_bootloader;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
8
fw/rtl/constants.vh
Normal file
8
fw/rtl/constants.vh
Normal file
@ -0,0 +1,8 @@
|
||||
`define VERSION "a"
|
||||
|
||||
`define BANK_INVALID 4'd0
|
||||
`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
|
@ -1,79 +1,87 @@
|
||||
module device_arbiter (
|
||||
module device_arbiter #(
|
||||
parameter NUM_CONTROLLERS = 2,
|
||||
parameter ADDRESS_WIDTH = 26,
|
||||
parameter [3:0] DEVICE_BANK = 4'd0,
|
||||
parameter ACK_FIFO_LENGTH = 4
|
||||
) (
|
||||
input i_clk,
|
||||
input i_reset,
|
||||
|
||||
input i_request_pri,
|
||||
input i_write_pri,
|
||||
output o_busy_pri,
|
||||
output o_ack_pri,
|
||||
input [3:0] i_bank_pri,
|
||||
input [25:0] i_address_pri,
|
||||
output [31:0] o_data_pri,
|
||||
input [31:0] i_data_pri,
|
||||
|
||||
input i_request_sec,
|
||||
input i_write_sec,
|
||||
output o_busy_sec,
|
||||
output o_ack_sec,
|
||||
input [3:0] i_bank_sec,
|
||||
input [25:0] i_address_sec,
|
||||
output [31:0] o_data_sec,
|
||||
input [31:0] i_data_sec,
|
||||
input [(NUM_CONTROLLERS - 1):0] i_request,
|
||||
input [(NUM_CONTROLLERS - 1):0] i_write,
|
||||
output reg [(NUM_CONTROLLERS - 1):0] o_busy,
|
||||
output reg [(NUM_CONTROLLERS - 1):0] o_ack,
|
||||
input [((NUM_CONTROLLERS * 4) - 1):0] i_bank,
|
||||
input [((NUM_CONTROLLERS * ADDRESS_WIDTH) - 1):0] i_address,
|
||||
output reg [((NUM_CONTROLLERS * 32) - 1):0] o_data,
|
||||
input [((NUM_CONTROLLERS * 32) - 1):0] i_data,
|
||||
|
||||
output o_request,
|
||||
output o_write,
|
||||
input i_busy,
|
||||
input i_ack,
|
||||
output [25:0] o_address,
|
||||
input [31:0] i_data,
|
||||
output [31:0] o_data
|
||||
output reg o_device_request,
|
||||
output reg o_device_write,
|
||||
input i_device_busy,
|
||||
input i_device_ack,
|
||||
output reg [(ADDRESS_WIDTH - 1):0] o_device_address,
|
||||
input [31:0] i_device_data,
|
||||
output reg [31:0] o_device_data
|
||||
);
|
||||
|
||||
parameter [3:0] DEVICE_BANK = 4'd0;
|
||||
localparam FIFO_ADDRESS_WIDTH = $clog2(ACK_FIFO_LENGTH);
|
||||
|
||||
wire w_request_pri = i_request_pri && i_bank_pri == DEVICE_BANK;
|
||||
wire w_request_sec = i_request_sec && i_bank_sec == DEVICE_BANK;
|
||||
reg [(NUM_CONTROLLERS - 1):0] r_request;
|
||||
reg [(NUM_CONTROLLERS - 1):0] r_request_successful;
|
||||
|
||||
wire w_request_pri_successful = w_request_pri && !o_busy_pri;
|
||||
wire w_request_sec_successful = w_request_sec && !o_busy_sec;
|
||||
reg [(NUM_CONTROLLERS - 1):0] r_ack_fifo_mem [0:(ACK_FIFO_LENGTH - 1)];
|
||||
|
||||
reg [(FIFO_ADDRESS_WIDTH - 1):0] r_ack_fifo_wrptr;
|
||||
reg [(FIFO_ADDRESS_WIDTH - 1):0] r_ack_fifo_rdptr;
|
||||
|
||||
wire w_read_fifo_ack_full;
|
||||
wire w_read_fifo_ack_pri_sec;
|
||||
wire w_ack_fifo_wrreq = |(r_request_successful & ~i_write);
|
||||
wire w_ack_fifo_rdreq = i_device_ack;
|
||||
|
||||
wire w_ack_fifo_full = (r_ack_fifo_wrptr + 1'd1) == r_ack_fifo_rdptr;
|
||||
|
||||
fifo_ack fifo_ack_inst (
|
||||
.clock(i_clk),
|
||||
.sclr(w_read_fifo_ack_reset),
|
||||
|
||||
.data(w_request_sec_successful && !i_write_sec),
|
||||
.wrreq((w_request_pri_successful && !i_write_pri) || (w_request_sec_successful && !i_write_sec)),
|
||||
.full(w_read_fifo_ack_full),
|
||||
|
||||
.rdreq(i_ack),
|
||||
.q(w_read_fifo_ack_pri_sec)
|
||||
);
|
||||
|
||||
assign o_busy_pri = w_request_pri && (i_busy || (!i_write_pri && w_read_fifo_ack_full));
|
||||
assign o_ack_pri = i_ack && !w_read_fifo_ack_pri_sec;
|
||||
assign o_data_pri = i_data;
|
||||
|
||||
assign o_busy_sec = w_request_sec && (i_request_pri || i_busy || (!i_write_sec && w_read_fifo_ack_full));
|
||||
assign o_ack_sec = i_ack && w_read_fifo_ack_pri_sec;
|
||||
assign o_data_sec = i_data;
|
||||
|
||||
assign o_request = w_request_pri || w_request_sec;
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
r_ack_fifo_wrptr <= {FIFO_ADDRESS_WIDTH{1'b0}};
|
||||
r_ack_fifo_rdptr <= {FIFO_ADDRESS_WIDTH{1'b0}};
|
||||
end else begin
|
||||
if (w_ack_fifo_wrreq) begin
|
||||
r_ack_fifo_mem[r_ack_fifo_wrptr] <= r_request_successful & ~i_write;
|
||||
r_ack_fifo_wrptr <= r_ack_fifo_wrptr + 1'd1;
|
||||
end
|
||||
if (w_ack_fifo_rdreq) begin
|
||||
r_ack_fifo_rdptr <= r_ack_fifo_rdptr + 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
o_write = 1'b0;
|
||||
o_address = 26'd0;
|
||||
o_data = 32'd0;
|
||||
if (w_request_pri_successful) begin
|
||||
o_write = i_write_pri;
|
||||
o_address = i_address_pri;
|
||||
o_data = i_data_pri;
|
||||
end else if (w_request_sec_successful) begin
|
||||
o_write = i_write_sec;
|
||||
o_address = i_address_sec;
|
||||
o_data = i_data_sec;
|
||||
for (integer i = 0; i < NUM_CONTROLLERS; i = i + 1) begin
|
||||
r_request[i] = i_request[i] && i_bank[(i * 4) +: 4] == DEVICE_BANK;
|
||||
o_busy[i] = r_request[i] && (
|
||||
i_device_busy ||
|
||||
|(r_request & (({{(NUM_CONTROLLERS - 1){1'b0}}, 1'b1} << i) - 1)) ||
|
||||
(!i_write[i] && w_ack_fifo_full)
|
||||
);
|
||||
end
|
||||
|
||||
r_request_successful = r_request & ~o_busy;
|
||||
o_ack = {NUM_CONTROLLERS{i_device_ack}} & r_ack_fifo_mem[r_ack_fifo_rdptr];
|
||||
o_data = {NUM_CONTROLLERS{i_device_data}};
|
||||
end
|
||||
|
||||
always @(*) begin
|
||||
o_device_request = |r_request;
|
||||
o_device_write = 1'b0;
|
||||
o_device_address = {ADDRESS_WIDTH{1'b0}};
|
||||
o_device_data = 32'h0000_0000;
|
||||
|
||||
for (integer i = (NUM_CONTROLLERS - 1); i >= 0 ; i = i - 1) begin
|
||||
if (r_request[i]) begin
|
||||
o_device_write = i_write[i];
|
||||
o_device_address = i_address[(i * ADDRESS_WIDTH) +: ADDRESS_WIDTH];
|
||||
o_device_data = i_data[(i * 32) +: 32];
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
set_global_assignment -name IP_TOOL_NAME "FIFO"
|
||||
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) "fifo_ack.v"]
|
||||
set_global_assignment -name IP_TOOL_NAME "FIFO"
|
||||
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) "fifo_usb.v"]
|
@ -1,163 +1,163 @@
|
||||
// megafunction wizard: %FIFO%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: scfifo
|
||||
|
||||
// ============================================================
|
||||
// File Name: fifo_ack.v
|
||||
// Megafunction Name(s):
|
||||
// scfifo
|
||||
//
|
||||
// Simulation Library Files(s):
|
||||
// altera_mf
|
||||
// ============================================================
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 20.1.0 Build 711 06/05/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 fifo_ack (
|
||||
clock,
|
||||
data,
|
||||
rdreq,
|
||||
sclr,
|
||||
wrreq,
|
||||
empty,
|
||||
full,
|
||||
q);
|
||||
|
||||
input clock;
|
||||
input [0:0] data;
|
||||
input rdreq;
|
||||
input sclr;
|
||||
input wrreq;
|
||||
output empty;
|
||||
output full;
|
||||
output [0:0] q;
|
||||
|
||||
wire sub_wire0;
|
||||
wire sub_wire1;
|
||||
wire [0:0] sub_wire2;
|
||||
wire empty = sub_wire0;
|
||||
wire full = sub_wire1;
|
||||
wire [0:0] q = sub_wire2[0:0];
|
||||
|
||||
scfifo scfifo_component (
|
||||
.clock (clock),
|
||||
.data (data),
|
||||
.rdreq (rdreq),
|
||||
.sclr (sclr),
|
||||
.wrreq (wrreq),
|
||||
.empty (sub_wire0),
|
||||
.full (sub_wire1),
|
||||
.q (sub_wire2),
|
||||
.aclr (),
|
||||
.almost_empty (),
|
||||
.almost_full (),
|
||||
.eccstatus (),
|
||||
.usedw ());
|
||||
defparam
|
||||
scfifo_component.add_ram_output_register = "OFF",
|
||||
scfifo_component.intended_device_family = "MAX 10",
|
||||
scfifo_component.lpm_numwords = 16,
|
||||
scfifo_component.lpm_showahead = "ON",
|
||||
scfifo_component.lpm_type = "scfifo",
|
||||
scfifo_component.lpm_width = 1,
|
||||
scfifo_component.lpm_widthu = 4,
|
||||
scfifo_component.overflow_checking = "ON",
|
||||
scfifo_component.underflow_checking = "ON",
|
||||
scfifo_component.use_eab = "OFF";
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
|
||||
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
|
||||
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Clock NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Depth NUMERIC "16"
|
||||
// Retrieval info: PRIVATE: Empty NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: Full NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10"
|
||||
// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Optimize NUMERIC "2"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: UsedW NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Width NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: diff_widths NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: output_width NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: rsFull NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: sc_sclr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
|
||||
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "16"
|
||||
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
|
||||
// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "1"
|
||||
// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "4"
|
||||
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
|
||||
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
|
||||
// Retrieval info: CONSTANT: USE_EAB STRING "OFF"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
|
||||
// Retrieval info: USED_PORT: data 0 0 1 0 INPUT NODEFVAL "data[0..0]"
|
||||
// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty"
|
||||
// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL "full"
|
||||
// Retrieval info: USED_PORT: q 0 0 1 0 OUTPUT NODEFVAL "q[0..0]"
|
||||
// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"
|
||||
// Retrieval info: USED_PORT: sclr 0 0 0 0 INPUT NODEFVAL "sclr"
|
||||
// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"
|
||||
// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
|
||||
// Retrieval info: CONNECT: @data 0 0 1 0 data 0 0 1 0
|
||||
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
|
||||
// Retrieval info: CONNECT: @sclr 0 0 0 0 sclr 0 0 0 0
|
||||
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
|
||||
// Retrieval info: CONNECT: empty 0 0 0 0 @empty 0 0 0 0
|
||||
// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
|
||||
// Retrieval info: CONNECT: q 0 0 1 0 @q 0 0 1 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_ack_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
||||
// megafunction wizard: %FIFO%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: scfifo
|
||||
|
||||
// ============================================================
|
||||
// File Name: fifo_usb.v
|
||||
// Megafunction Name(s):
|
||||
// scfifo
|
||||
//
|
||||
// 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 fifo_usb (
|
||||
clock,
|
||||
data,
|
||||
rdreq,
|
||||
sclr,
|
||||
wrreq,
|
||||
full,
|
||||
q,
|
||||
usedw);
|
||||
|
||||
input clock;
|
||||
input [31:0] data;
|
||||
input rdreq;
|
||||
input sclr;
|
||||
input wrreq;
|
||||
output full;
|
||||
output [31:0] q;
|
||||
output [9:0] usedw;
|
||||
|
||||
wire sub_wire0;
|
||||
wire [31:0] sub_wire1;
|
||||
wire [9:0] sub_wire2;
|
||||
wire full = sub_wire0;
|
||||
wire [31:0] q = sub_wire1[31:0];
|
||||
wire [9:0] usedw = sub_wire2[9:0];
|
||||
|
||||
scfifo scfifo_component (
|
||||
.clock (clock),
|
||||
.data (data),
|
||||
.rdreq (rdreq),
|
||||
.sclr (sclr),
|
||||
.wrreq (wrreq),
|
||||
.full (sub_wire0),
|
||||
.q (sub_wire1),
|
||||
.usedw (sub_wire2),
|
||||
.aclr (),
|
||||
.almost_empty (),
|
||||
.almost_full (),
|
||||
.eccstatus (),
|
||||
.empty ());
|
||||
defparam
|
||||
scfifo_component.add_ram_output_register = "OFF",
|
||||
scfifo_component.intended_device_family = "MAX 10",
|
||||
scfifo_component.lpm_numwords = 1024,
|
||||
scfifo_component.lpm_showahead = "ON",
|
||||
scfifo_component.lpm_type = "scfifo",
|
||||
scfifo_component.lpm_width = 32,
|
||||
scfifo_component.lpm_widthu = 10,
|
||||
scfifo_component.overflow_checking = "ON",
|
||||
scfifo_component.underflow_checking = "ON",
|
||||
scfifo_component.use_eab = "ON";
|
||||
|
||||
|
||||
endmodule
|
||||
|
||||
// ============================================================
|
||||
// CNX file retrieval info
|
||||
// ============================================================
|
||||
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
|
||||
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
|
||||
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Clock NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Depth NUMERIC "1024"
|
||||
// Retrieval info: PRIVATE: Empty NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Full NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "MAX 10"
|
||||
// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: Optimize NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: UsedW NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: Width NUMERIC "32"
|
||||
// Retrieval info: PRIVATE: dc_aclr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: diff_widths NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: output_width NUMERIC "32"
|
||||
// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: rsFull NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: sc_sclr NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
|
||||
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
|
||||
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
|
||||
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
|
||||
// Retrieval info: CONSTANT: LPM_TYPE STRING "scfifo"
|
||||
// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "32"
|
||||
// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "10"
|
||||
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
|
||||
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
|
||||
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
|
||||
// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL "data[31..0]"
|
||||
// Retrieval info: USED_PORT: full 0 0 0 0 OUTPUT NODEFVAL "full"
|
||||
// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL "q[31..0]"
|
||||
// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"
|
||||
// Retrieval info: USED_PORT: sclr 0 0 0 0 INPUT NODEFVAL "sclr"
|
||||
// Retrieval info: USED_PORT: usedw 0 0 10 0 OUTPUT NODEFVAL "usedw[9..0]"
|
||||
// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"
|
||||
// Retrieval info: CONNECT: @clock 0 0 0 0 clock 0 0 0 0
|
||||
// Retrieval info: CONNECT: @data 0 0 32 0 data 0 0 32 0
|
||||
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
|
||||
// Retrieval info: CONNECT: @sclr 0 0 0 0 sclr 0 0 0 0
|
||||
// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
|
||||
// Retrieval info: CONNECT: full 0 0 0 0 @full 0 0 0 0
|
||||
// Retrieval info: CONNECT: q 0 0 32 0 @q 0 0 32 0
|
||||
// Retrieval info: CONNECT: usedw 0 0 10 0 @usedw 0 0 10 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL fifo_usb_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
@ -60,7 +60,7 @@
|
||||
enabled="1"
|
||||
autoexport="1">
|
||||
<parameter name="AUTO_CLOCK_RATE" value="0" />
|
||||
<parameter name="CLOCK_FREQUENCY" value="90.0" />
|
||||
<parameter name="CLOCK_FREQUENCY" value="100.0" />
|
||||
<parameter name="CONFIGURATION_MODE">Single Compressed Image</parameter>
|
||||
<parameter name="CONFIGURATION_SCHEME">Internal Configuration</parameter>
|
||||
<parameter name="DATA_INTERFACE" value="Parallel" />
|
||||
|
@ -14,7 +14,7 @@
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 20.1.0 Build 711 06/05/2020 SJ Lite Edition
|
||||
// 20.1.1 Build 720 11/11/2020 SJ Lite Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
@ -99,14 +99,14 @@ module pll (
|
||||
.vcounderrange ());
|
||||
defparam
|
||||
altpll_component.bandwidth_type = "AUTO",
|
||||
altpll_component.clk0_divide_by = 5,
|
||||
altpll_component.clk0_divide_by = 1,
|
||||
altpll_component.clk0_duty_cycle = 50,
|
||||
altpll_component.clk0_multiply_by = 9,
|
||||
altpll_component.clk0_multiply_by = 2,
|
||||
altpll_component.clk0_phase_shift = "0",
|
||||
altpll_component.clk1_divide_by = 5,
|
||||
altpll_component.clk1_divide_by = 1,
|
||||
altpll_component.clk1_duty_cycle = 50,
|
||||
altpll_component.clk1_multiply_by = 9,
|
||||
altpll_component.clk1_phase_shift = "-2778",
|
||||
altpll_component.clk1_multiply_by = 2,
|
||||
altpll_component.clk1_phase_shift = "-1500",
|
||||
altpll_component.compensate_clock = "CLK0",
|
||||
altpll_component.inclk0_input_frequency = 20000,
|
||||
altpll_component.intended_device_family = "MAX 10",
|
||||
@ -184,8 +184,8 @@ endmodule
|
||||
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "90.000000"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "90.000000"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "100.000000"
|
||||
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "100.000000"
|
||||
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
|
||||
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
|
||||
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
|
||||
@ -213,8 +213,8 @@ endmodule
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "90.00000000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "90.00000000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "100.00000000"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1"
|
||||
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
|
||||
@ -222,7 +222,7 @@ endmodule
|
||||
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
|
||||
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "-90.00000000"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "-54.00000000"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
|
||||
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
|
||||
@ -263,14 +263,14 @@ endmodule
|
||||
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
|
||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
|
||||
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "5"
|
||||
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "1"
|
||||
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "9"
|
||||
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2"
|
||||
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
|
||||
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "5"
|
||||
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "1"
|
||||
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
|
||||
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "9"
|
||||
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "-2778"
|
||||
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "2"
|
||||
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "-1500"
|
||||
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
|
||||
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20000"
|
||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
|
||||
|
@ -14,7 +14,7 @@
|
||||
// ************************************************************
|
||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||
//
|
||||
// 20.1.0 Build 711 06/05/2020 SJ Lite Edition
|
||||
// 20.1.1 Build 720 11/11/2020 SJ Lite Edition
|
||||
// ************************************************************
|
||||
|
||||
|
||||
@ -110,12 +110,12 @@ module ram_n64_eeprom (
|
||||
altsyncram_component.operation_mode = "BIDIR_DUAL_PORT",
|
||||
altsyncram_component.outdata_aclr_a = "NONE",
|
||||
altsyncram_component.outdata_aclr_b = "NONE",
|
||||
altsyncram_component.outdata_reg_a = "CLOCK0",
|
||||
altsyncram_component.outdata_reg_b = "CLOCK0",
|
||||
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.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ",
|
||||
altsyncram_component.read_during_write_mode_port_b = "NEW_DATA_NO_NBE_READ",
|
||||
altsyncram_component.widthad_a = 11,
|
||||
altsyncram_component.widthad_b = 9,
|
||||
altsyncram_component.width_a = 8,
|
||||
@ -165,13 +165,13 @@ endmodule
|
||||
// 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 "1"
|
||||
// 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: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
|
||||
// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3"
|
||||
// Retrieval info: PRIVATE: REGdata NUMERIC "1"
|
||||
// Retrieval info: PRIVATE: REGq 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"
|
||||
@ -203,12 +203,12 @@ endmodule
|
||||
// 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 "CLOCK0"
|
||||
// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "CLOCK0"
|
||||
// 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: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ"
|
||||
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_B STRING "NEW_DATA_NO_NBE_READ"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "11"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "9"
|
||||
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
|
||||
|
4
fw/rtl/intel/ram/ram_sd_buffer.qip
Normal file
4
fw/rtl/intel/ram/ram_sd_buffer.qip
Normal file
@ -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_sd_buffer.v"]
|
243
fw/rtl/intel/ram/ram_sd_buffer.v
Normal file
243
fw/rtl/intel/ram/ram_sd_buffer.v
Normal file
@ -0,0 +1,243 @@
|
||||
// megafunction wizard: %RAM: 2-PORT%
|
||||
// GENERATION: STANDARD
|
||||
// VERSION: WM1.0
|
||||
// MODULE: altsyncram
|
||||
|
||||
// ============================================================
|
||||
// File Name: ram_sd_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_sd_buffer (
|
||||
address_a,
|
||||
address_b,
|
||||
clock,
|
||||
data_a,
|
||||
data_b,
|
||||
wren_a,
|
||||
wren_b,
|
||||
q_a,
|
||||
q_b);
|
||||
|
||||
input [8:0] address_a;
|
||||
input [6:0] address_b;
|
||||
input clock;
|
||||
input [7:0] data_a;
|
||||
input [31:0] data_b;
|
||||
input wren_a;
|
||||
input wren_b;
|
||||
output [7: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 [7:0] sub_wire0;
|
||||
wire [31:0] sub_wire1;
|
||||
wire [7:0] q_a = sub_wire0[7: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 = 512,
|
||||
altsyncram_component.numwords_b = 128,
|
||||
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 = 9,
|
||||
altsyncram_component.widthad_b = 7,
|
||||
altsyncram_component.width_a = 8,
|
||||
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 "4096"
|
||||
// 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 "1"
|
||||
// Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "8"
|
||||
// Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "32"
|
||||
// Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "8"
|
||||
// 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 "512"
|
||||
// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "128"
|
||||
// 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 "9"
|
||||
// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "7"
|
||||
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
|
||||
// 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 9 0 INPUT NODEFVAL "address_a[8..0]"
|
||||
// Retrieval info: USED_PORT: address_b 0 0 7 0 INPUT NODEFVAL "address_b[6..0]"
|
||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
|
||||
// Retrieval info: USED_PORT: data_a 0 0 8 0 INPUT NODEFVAL "data_a[7..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 8 0 OUTPUT NODEFVAL "q_a[7..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 9 0 address_a 0 0 9 0
|
||||
// Retrieval info: CONNECT: @address_b 0 0 7 0 address_b 0 0 7 0
|
||||
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
|
||||
// Retrieval info: CONNECT: @data_a 0 0 8 0 data_a 0 0 8 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 8 0 @q_a 0 0 8 0
|
||||
// Retrieval info: CONNECT: q_b 0 0 32 0 @q_b 0 0 32 0
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_sd_buffer.v TRUE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_sd_buffer.inc FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_sd_buffer.cmp FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_sd_buffer.bsf FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_sd_buffer_inst.v FALSE
|
||||
// Retrieval info: GEN_FILE: TYPE_NORMAL ram_sd_buffer_bb.v FALSE
|
||||
// Retrieval info: LIB_FILE: altera_mf
|
@ -37,7 +37,7 @@ module memory_embedded_flash (
|
||||
w_onchip_flash_o_data[7:0],
|
||||
w_onchip_flash_o_data[15:8],
|
||||
w_onchip_flash_o_data[23:16],
|
||||
w_onchip_flash_o_data[31:24],
|
||||
w_onchip_flash_o_data[31:24]
|
||||
};
|
||||
end
|
||||
end
|
||||
@ -45,7 +45,7 @@ module memory_embedded_flash (
|
||||
onchip_flash onchip_flash_inst (
|
||||
.clock(i_clk),
|
||||
.reset_n(~i_reset),
|
||||
.avmm_data_addr(i_address),
|
||||
.avmm_data_addr(i_address[14:0]),
|
||||
.avmm_data_read(r_onchip_flash_request),
|
||||
.avmm_data_readdata(w_onchip_flash_o_data),
|
||||
.avmm_data_waitrequest(w_onchip_flash_busy),
|
@ -6,9 +6,9 @@ module memory_sdram (
|
||||
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 reg [1:0] o_sdram_ba,
|
||||
output reg [12:0] o_sdram_a,
|
||||
inout reg [15:0] io_sdram_dq,
|
||||
|
||||
input i_request,
|
||||
input i_write,
|
||||
@ -21,7 +21,7 @@ module memory_sdram (
|
||||
|
||||
// SDRAM timings (in nanoseconds)
|
||||
|
||||
parameter real CLK_FREQ = 90_000_000.0;
|
||||
parameter real CLK_FREQ = 100_000_000.0;
|
||||
|
||||
parameter [2:0] CAS_LATENCY = 3'd2;
|
||||
|
||||
@ -163,7 +163,7 @@ module memory_sdram (
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
r_init_counter <= 1'd0;
|
||||
r_init_counter <= 16'd0;
|
||||
end else if (r_init_counter < INIT_DONE) begin
|
||||
r_init_counter <= r_init_counter + 1'd1;
|
||||
end
|
||||
@ -239,7 +239,7 @@ module memory_sdram (
|
||||
r_sdram_precharge <= 1'b1;
|
||||
end else if (w_init_refresh_1 || w_init_refresh_2) begin
|
||||
r_sdram_cmd <= CMD_REF;
|
||||
r_refresh_counter <= 1'd0;
|
||||
r_refresh_counter <= 10'd0;
|
||||
end else if (w_init_mode_reg) begin
|
||||
r_sdram_cmd <= CMD_MRS;
|
||||
end else if (w_init_done) begin
|
||||
@ -251,19 +251,19 @@ module memory_sdram (
|
||||
STATE_IDLE: begin
|
||||
if (w_refresh_pending) begin
|
||||
r_sdram_cmd <= CMD_REF;
|
||||
r_refresh_counter <= 1'd0;
|
||||
r_rcd_ras_rc_counter <= 1'd0;
|
||||
r_refresh_counter <= 10'd0;
|
||||
r_rcd_ras_rc_counter <= 5'd0;
|
||||
r_state <= STATE_REFRESHING;
|
||||
r_busy <= 1'b1;
|
||||
end else if (r_request_pending || r_cross_row_request) begin
|
||||
r_sdram_cmd <= CMD_ACT;
|
||||
r_rcd_ras_rc_counter <= 1'd0;
|
||||
r_rcd_ras_rc_counter <= 5'd0;
|
||||
r_state <= STATE_ACTIVATING;
|
||||
r_busy <= 1'b1;
|
||||
end else if (i_request && !o_busy) begin
|
||||
r_sdram_cmd <= CMD_ACT;
|
||||
r_sdram_data <= i_data;
|
||||
r_rcd_ras_rc_counter <= 1'd0;
|
||||
r_rcd_ras_rc_counter <= 5'd0;
|
||||
r_state <= STATE_ACTIVATING;
|
||||
r_request_pending <= 1'b1;
|
||||
r_write_pending <= i_write;
|
||||
@ -275,7 +275,7 @@ module memory_sdram (
|
||||
STATE_ACTIVATING: begin
|
||||
if (w_rcd_timing_met) begin
|
||||
r_sdram_cmd <= r_write_pending ? CMD_WRITE : CMD_READ;
|
||||
if (r_write_pending) r_wr_counter <= 1'd0;
|
||||
if (r_write_pending) r_wr_counter <= 2'd0;
|
||||
if (r_cross_row_request) begin
|
||||
r_cross_row_request <= 1'b0;
|
||||
r_busy <= 1'b0;
|
||||
@ -289,13 +289,13 @@ module memory_sdram (
|
||||
STATE_ACTIVE: begin
|
||||
if (r_wr_wait) begin
|
||||
if (w_wr_timing_met) begin
|
||||
r_rp_counter <= 1'd0;
|
||||
r_rp_counter <= 3'd0;
|
||||
r_state <= STATE_PRECHARGING;
|
||||
r_wr_wait <= 1'b0;
|
||||
end
|
||||
end else if (r_request_pending && !(r_write_pending && w_read_pending)) begin
|
||||
r_sdram_cmd <= r_write_pending ? CMD_WRITE : CMD_READ;
|
||||
if (r_write_pending) r_wr_counter <= 1'd0;
|
||||
if (r_write_pending) r_wr_counter <= 2'd0;
|
||||
r_current_word <= 1'b1;
|
||||
if (r_current_word) begin
|
||||
r_busy <= 1'b0;
|
||||
@ -305,14 +305,14 @@ module memory_sdram (
|
||||
if (w_ras_timing_met && w_wr_timing_met) begin
|
||||
r_sdram_cmd <= CMD_PRE;
|
||||
r_sdram_precharge <= 1'b1;
|
||||
r_rp_counter <= 1'd0;
|
||||
r_rp_counter <= 3'd0;
|
||||
r_state <= STATE_PRECHARGING;
|
||||
end
|
||||
end else if (i_request && !o_busy) begin
|
||||
r_sdram_data <= i_data;
|
||||
r_busy <= 1'b1;
|
||||
r_write_pending <= i_write;
|
||||
|
||||
|
||||
if (w_request_in_another_row || (i_write && w_read_pending)) begin
|
||||
r_request_pending <= 1'b1;
|
||||
r_current_word <= 1'b0;
|
||||
@ -322,19 +322,19 @@ module memory_sdram (
|
||||
end else begin
|
||||
r_sdram_cmd <= CMD_PRE;
|
||||
r_sdram_precharge <= 1'b1;
|
||||
r_rp_counter <= 1'd0;
|
||||
r_rp_counter <= 3'd0;
|
||||
r_state <= STATE_PRECHARGING;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
r_sdram_cmd <= i_write ? CMD_WRITE : CMD_READ;
|
||||
if (i_write) r_wr_counter <= 1'd0;
|
||||
if (i_write) r_wr_counter <= 2'd0;
|
||||
r_current_word <= 1'b1;
|
||||
if (w_next_address_in_another_row) begin
|
||||
r_sdram_precharge <= 1'b1;
|
||||
r_cross_row_request <= 1'b1;
|
||||
if (!i_write) begin
|
||||
r_rp_counter <= 1'd0;
|
||||
r_rp_counter <= 3'd0;
|
||||
r_state <= STATE_PRECHARGING;
|
||||
end else begin
|
||||
r_wr_wait <= 1'b1;
|
@ -1,42 +0,0 @@
|
||||
module n64_bank_decoder (
|
||||
input [31:0] i_address,
|
||||
output reg [25:0] o_translated_address,
|
||||
output reg [3:0] o_bank,
|
||||
output reg o_bank_prefetch
|
||||
);
|
||||
|
||||
localparam [3:0] BANK_INVALID = 4'd0;
|
||||
localparam [3:0] BANK_ROM = 4'd1;
|
||||
localparam [3:0] BANK_CART = 4'd2;
|
||||
localparam [3:0] BANK_EEPROM = 4'd3;
|
||||
|
||||
localparam [31:0] ROM_BASE = 32'h1000_0000;
|
||||
localparam [31:0] ROM_END = 32'h13FF_FFFF;
|
||||
|
||||
localparam [31:0] CART_BASE = 32'h1E00_0000;
|
||||
localparam [31:0] CART_END = 32'h1EFF_FFFF;
|
||||
|
||||
localparam [31:0] EEPROM_BASE = 32'h1D00_0000;
|
||||
localparam [31:0] EEPROM_END = 32'h1D00_07FF;
|
||||
|
||||
always @(*) begin
|
||||
o_bank = BANK_INVALID;
|
||||
o_bank_prefetch = 1'b0;
|
||||
o_translated_address = i_address[25:0];
|
||||
if (i_address >= ROM_BASE && i_address <= ROM_END) begin
|
||||
o_translated_address = i_address - ROM_BASE;
|
||||
o_bank = BANK_ROM;
|
||||
o_bank_prefetch = 1'b1;
|
||||
end
|
||||
if (i_address >= CART_BASE && i_address <= CART_END) begin
|
||||
o_translated_address = i_address - CART_BASE;
|
||||
o_bank = BANK_CART;
|
||||
end
|
||||
if (i_address >= EEPROM_BASE && i_address <= EEPROM_END) begin
|
||||
o_translated_address = i_address - EEPROM_BASE;
|
||||
o_bank = BANK_EEPROM;
|
||||
o_bank_prefetch = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
81
fw/rtl/n64/n64_bank_decoder.v
Normal file
81
fw/rtl/n64/n64_bank_decoder.v
Normal file
@ -0,0 +1,81 @@
|
||||
`include "../constants.vh"
|
||||
|
||||
module n64_bank_decoder (
|
||||
input [31:0] i_address,
|
||||
output reg [25:0] o_translated_address,
|
||||
output reg [3:0] o_bank,
|
||||
output reg o_bank_prefetch,
|
||||
output o_sram_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 [23:0] i_ddipl_address,
|
||||
input [23:0] i_sram_address
|
||||
);
|
||||
|
||||
localparam [31:0] DDIPL_BASE = 32'h0600_0000;
|
||||
localparam [31:0] DDIPL_END = 32'h063F_FFFF;
|
||||
|
||||
localparam [31:0] SRAM_BASE = 32'h0800_0000;
|
||||
localparam [31:0] SRAM_END = 32'h0800_7FFF;
|
||||
localparam [31:0] SRAM_768K_END = 32'h0801_7FFF;
|
||||
|
||||
localparam [31:0] ROM_BASE = 32'h1000_0000;
|
||||
localparam [31:0] ROM_END = 32'h13FF_FFFF;
|
||||
|
||||
localparam [31:0] CART_BASE = 32'h1E00_0000;
|
||||
localparam [31:0] CART_END = 32'h1E00_3FFF;
|
||||
|
||||
localparam [31:0] EEPROM_BASE = 32'h1E00_4000;
|
||||
localparam [31:0] EEPROM_END = 32'h1E00_47FF;
|
||||
|
||||
localparam [31:0] SD_BASE = 32'h1E00_8000;
|
||||
localparam [31:0] SD_END = 32'h1E00_83FF;
|
||||
|
||||
wire [25:0] w_ddipl_translated_address = i_address[25:0] + {i_ddipl_address, 2'd0};
|
||||
wire [25:0] w_sram_translated_address = i_address[25:0] + {i_sram_address, 2'd0};
|
||||
|
||||
always @(*) begin
|
||||
o_bank = `BANK_INVALID;
|
||||
o_bank_prefetch = 1'b0;
|
||||
o_translated_address = i_address[25:0];
|
||||
o_sram_request = 1'b0;
|
||||
|
||||
if ((i_address >= DDIPL_BASE) && (i_address <= DDIPL_END) && i_ddipl_enable) begin
|
||||
o_translated_address = w_ddipl_translated_address;
|
||||
o_bank = `BANK_SDRAM;
|
||||
o_bank_prefetch = 1'b1;
|
||||
end
|
||||
|
||||
if ((i_address >= SRAM_BASE) && ((i_address <= SRAM_END) || ((i_sram_768k_mode && (i_address <= SRAM_768K_END))))) begin
|
||||
if (i_sram_enable && !i_flashram_enable) begin
|
||||
o_translated_address = w_sram_translated_address;
|
||||
o_bank = `BANK_SDRAM;
|
||||
o_bank_prefetch = 1'b1;
|
||||
o_sram_request = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
if ((i_address >= ROM_BASE) && (i_address <= ROM_END)) begin
|
||||
o_bank = `BANK_SDRAM;
|
||||
o_bank_prefetch = 1'b1;
|
||||
end
|
||||
|
||||
if ((i_address >= CART_BASE) && (i_address <= CART_END)) begin
|
||||
o_bank = `BANK_CART;
|
||||
end
|
||||
|
||||
if ((i_address >= EEPROM_BASE) && (i_address <= EEPROM_END) && i_eeprom_enable) begin
|
||||
o_bank = `BANK_EEPROM;
|
||||
o_bank_prefetch = 1'b1;
|
||||
end
|
||||
|
||||
if ((i_address >= SD_BASE) && (i_address <= SD_END) && i_sd_enable) begin
|
||||
o_bank = `BANK_SD;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
@ -7,7 +7,7 @@ module n64_pi (
|
||||
input i_n64_pi_aleh,
|
||||
input i_n64_pi_read,
|
||||
input i_n64_pi_write,
|
||||
inout [15:0] io_n64_pi_ad,
|
||||
inout reg [15:0] io_n64_pi_ad,
|
||||
|
||||
output reg o_request,
|
||||
output reg o_write,
|
||||
@ -16,7 +16,19 @@ module n64_pi (
|
||||
output [3:0] o_bank,
|
||||
output reg [25:0] o_address,
|
||||
input [31:0] i_data,
|
||||
output reg [31:0] o_data
|
||||
output reg [31:0] o_data,
|
||||
|
||||
output o_sram_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 [23:0] i_ddipl_address,
|
||||
input [23:0] i_sram_address
|
||||
);
|
||||
|
||||
// Parameters
|
||||
@ -86,7 +98,16 @@ module n64_pi (
|
||||
.i_address(r_pi_address),
|
||||
.o_translated_address(w_translated_address),
|
||||
.o_bank(o_bank),
|
||||
.o_bank_prefetch(w_bank_prefetch)
|
||||
.o_bank_prefetch(w_bank_prefetch),
|
||||
.o_sram_request(o_sram_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_sd_enable(i_sd_enable),
|
||||
.i_eeprom_enable(i_eeprom_enable),
|
||||
.i_ddipl_address(i_ddipl_address),
|
||||
.i_sram_address(i_sram_address)
|
||||
);
|
||||
|
||||
|
||||
@ -121,11 +142,17 @@ module n64_pi (
|
||||
// Read buffer logic
|
||||
|
||||
reg [31:0] r_pi_read_buffer;
|
||||
reg r_prefetch_read;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (w_address_valid_op) begin
|
||||
r_prefetch_read <= w_prefetch;
|
||||
end
|
||||
if (i_ack) begin
|
||||
if (w_prefetch) r_pi_read_buffer <= i_data;
|
||||
else r_pi_output_data <= i_data;
|
||||
if (r_prefetch_read) r_pi_output_data <= i_data;
|
||||
r_prefetch_read <= 1'b0;
|
||||
end
|
||||
if (w_prefetch && w_bus_read_op) r_pi_output_data <= r_pi_read_buffer;
|
||||
end
|
||||
@ -148,21 +175,35 @@ module n64_pi (
|
||||
|
||||
// Bus request logic
|
||||
|
||||
wire w_bus_request_op = !o_request && ((w_address_valid_op && w_prefetch) || w_bus_read_op || w_bus_write_op);
|
||||
reg r_pending_request;
|
||||
reg r_pending_request_write;
|
||||
|
||||
wire w_bus_request_op = (w_address_valid_op && w_prefetch) || w_bus_read_op || w_bus_write_op;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
o_request <= 1'b0;
|
||||
o_write <= 1'b0;
|
||||
r_pending_request <= 1'b0;
|
||||
end else begin
|
||||
if (w_bus_request_op) begin
|
||||
o_request <= 1'b1;
|
||||
o_write <= w_bus_write_op;
|
||||
end
|
||||
if (o_request && !i_busy) begin
|
||||
o_request <= 1'b0;
|
||||
o_write <= 1'b0;
|
||||
end
|
||||
if (w_bus_request_op) begin
|
||||
if (o_request) begin
|
||||
r_pending_request <= 1'b1;
|
||||
r_pending_request_write <= w_bus_write_op;
|
||||
end else begin
|
||||
o_request <= 1'b1;
|
||||
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;
|
||||
r_pending_request <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -183,7 +224,7 @@ module n64_pi (
|
||||
r_first_transfer <= 1'b1;
|
||||
end
|
||||
if (w_first_transfer_clear_op) r_first_transfer <= 1'b0;
|
||||
if (w_address_increment_op) o_address[8:2] <= o_address[8:2] + 1'b1;
|
||||
if (w_address_increment_op) o_address[15:2] <= o_address[15:2] + 1'b1;
|
||||
end
|
||||
|
||||
endmodule
|
@ -10,7 +10,7 @@ module n64_si (
|
||||
input i_write,
|
||||
output o_busy,
|
||||
output reg o_ack,
|
||||
input [10:0] i_address,
|
||||
input [8:0] i_address,
|
||||
input [31:0] i_data,
|
||||
output [31:0] o_data,
|
||||
|
||||
@ -219,7 +219,7 @@ module n64_si (
|
||||
.wren_a(w_eeprom_write_op),
|
||||
.q_a(w_eeprom_o_data),
|
||||
|
||||
.address_b(i_address[10:2]),
|
||||
.address_b(i_address),
|
||||
.data_b({i_data[7:0], i_data[15:8], i_data[23:16], i_data[31:24]}),
|
||||
.wren_b(!i_reset && i_request && i_write),
|
||||
.q_b({o_data[7:0], o_data[15:8], o_data[23:16], o_data[31:24]})
|
||||
@ -227,11 +227,11 @@ module n64_si (
|
||||
|
||||
|
||||
// Bus logic
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
o_ack <= !i_reset && i_request;
|
||||
end
|
||||
|
||||
assign o_busy = 1'b0;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
o_ack <= !i_reset && i_request && !i_write;
|
||||
end
|
||||
|
||||
endmodule
|
62
fw/rtl/sd/sd_dma.v
Normal file
62
fw/rtl/sd/sd_dma.v
Normal file
@ -0,0 +1,62 @@
|
||||
module sd_dma (
|
||||
input i_clk,
|
||||
input i_reset,
|
||||
|
||||
input i_fifo_flush,
|
||||
input i_fifo_push,
|
||||
output o_fifo_full,
|
||||
output o_fifo_empty,
|
||||
input [31:0] i_fifo_data,
|
||||
|
||||
output reg o_request,
|
||||
output reg o_write,
|
||||
input i_busy,
|
||||
output reg [31:0] o_data
|
||||
);
|
||||
|
||||
reg [31:0] r_dma_fifo_mem [0:127];
|
||||
|
||||
reg [6:0] r_dma_fifo_wrptr;
|
||||
reg [6:0] r_dma_fifo_rdptr;
|
||||
|
||||
assign o_fifo_full = (r_dma_fifo_wrptr + 1'd1) == r_dma_fifo_rdptr;
|
||||
assign o_fifo_empty = r_dma_fifo_wrptr == r_dma_fifo_rdptr;
|
||||
|
||||
wire [31:0] w_rddata = r_dma_fifo_mem[r_dma_fifo_rdptr];
|
||||
|
||||
wire w_request_successful = o_request && !i_busy;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset || i_fifo_flush) begin
|
||||
r_dma_fifo_wrptr <= 7'd0;
|
||||
end else begin
|
||||
if (i_fifo_push) begin
|
||||
r_dma_fifo_wrptr <= r_dma_fifo_wrptr + 1'd1;
|
||||
r_dma_fifo_mem[r_dma_fifo_wrptr] <= i_fifo_data;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset || i_fifo_flush) begin
|
||||
o_request <= 1'b0;
|
||||
o_write <= 1'b1;
|
||||
r_dma_fifo_rdptr <= 7'd0;
|
||||
end else begin
|
||||
if (!o_request && !o_fifo_empty) begin
|
||||
o_request <= 1'b1;
|
||||
o_data <= w_rddata;
|
||||
r_dma_fifo_rdptr <= r_dma_fifo_rdptr + 1'd1;
|
||||
end
|
||||
if (w_request_successful) begin
|
||||
if (o_fifo_empty) begin
|
||||
o_request <= 1'b0;
|
||||
end else begin
|
||||
r_dma_fifo_rdptr <= r_dma_fifo_rdptr + 1'd1;
|
||||
o_data <= w_rddata;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
297
fw/rtl/sd/sd_interface.v
Normal file
297
fw/rtl/sd/sd_interface.v
Normal file
@ -0,0 +1,297 @@
|
||||
`include "../constants.vh"
|
||||
|
||||
module sd_interface (
|
||||
input i_clk,
|
||||
input i_reset,
|
||||
|
||||
output reg o_sd_clk,
|
||||
output reg o_sd_cs,
|
||||
output reg o_sd_mosi,
|
||||
input i_sd_miso,
|
||||
|
||||
input i_request,
|
||||
input i_write,
|
||||
output o_busy,
|
||||
output reg o_ack,
|
||||
input [7:0] i_address,
|
||||
output [31:0] o_data,
|
||||
input [31:0] i_data,
|
||||
|
||||
output o_dma_request,
|
||||
output o_dma_write,
|
||||
input i_dma_busy,
|
||||
input i_dma_ack,
|
||||
output reg [3:0] o_dma_bank,
|
||||
output reg [23:0] o_dma_address,
|
||||
input [31:0] i_dma_data,
|
||||
output [31:0] o_dma_data
|
||||
);
|
||||
|
||||
// Register offsets
|
||||
|
||||
localparam [2:0] REG_SD_SCR = 3'd0;
|
||||
localparam [2:0] REG_SD_CS = 3'd1;
|
||||
localparam [2:0] REG_SD_DR = 3'd2;
|
||||
localparam [2:0] REG_SD_MULTI = 3'd3;
|
||||
localparam [2:0] REG_SD_DMA_SCR = 3'd4;
|
||||
localparam [2:0] REG_SD_DMA_ADDR = 3'd5;
|
||||
|
||||
localparam [7:0] MEM_SD_BUFFER_BASE = 8'h80;
|
||||
|
||||
|
||||
// Bus controller
|
||||
|
||||
reg [8:0] r_o_data;
|
||||
|
||||
wire w_address_in_buffers = i_address >= MEM_SD_BUFFER_BASE;
|
||||
wire [31:0] w_sd_buffer_rx_o_data;
|
||||
|
||||
assign o_busy = 1'b0;
|
||||
assign o_data = w_address_in_buffers ? w_sd_buffer_rx_o_data : {23'd0, r_o_data};
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
o_ack <= !i_reset && i_request && !i_write && !o_busy;
|
||||
end
|
||||
|
||||
|
||||
// DMA controller
|
||||
|
||||
reg r_dma_fifo_flush;
|
||||
reg r_dma_fifo_push;
|
||||
reg [31:0] r_dma_fifo_data;
|
||||
|
||||
wire w_dma_fifo_full;
|
||||
wire w_dma_fifo_empty;
|
||||
|
||||
sd_dma sd_dma_inst (
|
||||
.i_clk(i_clk),
|
||||
.i_reset(i_reset),
|
||||
|
||||
.i_fifo_flush(r_dma_fifo_flush),
|
||||
.i_fifo_push(r_dma_fifo_push),
|
||||
.o_fifo_full(w_dma_fifo_full),
|
||||
.o_fifo_empty(w_dma_fifo_empty),
|
||||
.i_fifo_data(r_dma_fifo_data),
|
||||
|
||||
.o_request(o_dma_request),
|
||||
.o_write(o_dma_write),
|
||||
.i_busy(i_dma_busy),
|
||||
.o_data(o_dma_data)
|
||||
);
|
||||
|
||||
|
||||
// Bus <-> peripheral interface registers
|
||||
|
||||
reg r_spi_busy;
|
||||
|
||||
reg [2:0] r_spi_clk_div;
|
||||
reg r_spi_start;
|
||||
reg [7:0] r_spi_tx_data;
|
||||
reg [7:0] r_spi_rx_data;
|
||||
|
||||
reg r_spi_rx_only;
|
||||
|
||||
reg r_spi_start_multi;
|
||||
reg [8:0] r_spi_multi_length;
|
||||
reg r_spi_multi_dma;
|
||||
|
||||
|
||||
// Write logic
|
||||
|
||||
wire w_dma_request_successful = o_dma_request && !i_dma_busy;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
r_spi_start <= 1'b0;
|
||||
r_spi_start_multi <= 1'b0;
|
||||
r_dma_fifo_flush <= 1'b0;
|
||||
|
||||
if (i_reset) begin
|
||||
o_sd_cs <= 1'b1;
|
||||
o_dma_bank <= 4'd0;
|
||||
o_dma_address <= 24'd0;
|
||||
r_spi_clk_div <= 3'b111;
|
||||
end else if (i_request && i_write && !o_busy && !w_address_in_buffers) begin
|
||||
case (i_address[2:0])
|
||||
REG_SD_SCR: begin
|
||||
r_spi_clk_div <= i_data[3:1];
|
||||
end
|
||||
REG_SD_CS: if (!r_spi_busy) begin
|
||||
o_sd_cs <= i_data[0];
|
||||
end
|
||||
REG_SD_DR: if (!r_spi_busy) begin
|
||||
r_spi_start <= 1'b1;
|
||||
r_spi_tx_data <= i_data[7:0];
|
||||
r_spi_rx_only <= 1'b0;
|
||||
r_spi_multi_length <= 9'd0;
|
||||
r_spi_multi_dma <= 1'b0;
|
||||
end
|
||||
REG_SD_MULTI: if (!r_spi_busy) begin
|
||||
r_spi_start_multi <= 1'b1;
|
||||
{r_spi_multi_dma, r_spi_rx_only, r_spi_multi_length} <= i_data[10:0];
|
||||
end
|
||||
REG_SD_DMA_SCR: begin
|
||||
{r_dma_fifo_flush} <= i_data[0];
|
||||
end
|
||||
REG_SD_DMA_ADDR: begin
|
||||
{o_dma_bank, o_dma_address} <= {i_data[31:28], i_data[25:2]};
|
||||
end
|
||||
default: begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (w_dma_request_successful) begin
|
||||
o_dma_address <= o_dma_address + 1'd1;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Read logic
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (!i_reset && i_request && !i_write && !o_busy) begin
|
||||
if (!w_address_in_buffers) begin
|
||||
case (i_address[2:0])
|
||||
REG_SD_SCR: begin
|
||||
r_o_data[3:0] <= {r_spi_clk_div, r_spi_busy};
|
||||
end
|
||||
REG_SD_DR: begin
|
||||
r_o_data[8:0] <= {r_spi_busy, r_spi_rx_data};
|
||||
end
|
||||
REG_SD_DMA_SCR: begin
|
||||
r_o_data[1:0] <= {w_dma_fifo_full, w_dma_fifo_empty};
|
||||
end
|
||||
default: begin
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// Clock divider
|
||||
|
||||
reg [7:0] r_spi_clk_div_counter;
|
||||
reg r_spi_clk_prev_value;
|
||||
reg r_spi_clk_strobe;
|
||||
|
||||
wire w_spi_clk_div_selected = r_spi_clk_div_counter[r_spi_clk_div];
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
r_spi_clk_div_counter <= r_spi_clk_div_counter + 1'd1;
|
||||
r_spi_clk_prev_value <= w_spi_clk_div_selected;
|
||||
r_spi_clk_strobe <= (w_spi_clk_div_selected != r_spi_clk_prev_value) && !w_dma_fifo_full;
|
||||
end
|
||||
|
||||
|
||||
// Buffers
|
||||
|
||||
reg [8:0] r_spi_multi_tx_address;
|
||||
wire [7:0] w_spi_multi_tx_data;
|
||||
|
||||
ram_sd_buffer ram_sd_buffer_tx_inst (
|
||||
.clock(i_clk),
|
||||
|
||||
.address_a(r_spi_multi_tx_address),
|
||||
.q_a(w_spi_multi_tx_data),
|
||||
|
||||
.wren_b(!i_reset && i_request && i_write && !o_busy && w_address_in_buffers),
|
||||
.address_b(i_address[6:0]),
|
||||
.data_b({i_data[7:0], i_data[15:8], i_data[23:16], i_data[31:24]})
|
||||
);
|
||||
|
||||
reg r_spi_multi_rx_byte_write;
|
||||
reg [8:0] r_spi_multi_rx_address;
|
||||
|
||||
ram_sd_buffer ram_sd_buffer_rx_inst (
|
||||
.clock(i_clk),
|
||||
|
||||
.wren_a(r_spi_multi_rx_byte_write),
|
||||
.address_a(r_spi_multi_rx_address),
|
||||
.data_a(r_spi_rx_data),
|
||||
|
||||
.address_b(i_address[6:0]),
|
||||
.q_b({w_sd_buffer_rx_o_data[7:0], w_sd_buffer_rx_o_data[15:8], w_sd_buffer_rx_o_data[23:16], w_sd_buffer_rx_o_data[31:24]})
|
||||
);
|
||||
|
||||
|
||||
// Shifting operation
|
||||
|
||||
reg r_spi_multi;
|
||||
reg r_spi_first_bit;
|
||||
reg [3:0] r_spi_bit_clk;
|
||||
reg [6:0] r_spi_tx_shift;
|
||||
|
||||
wire [7:0] w_next_spi_tx_data = r_spi_rx_only ? 8'hFF : (r_spi_multi ? w_spi_multi_tx_data : r_spi_tx_data);
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
r_spi_multi_rx_byte_write <= 1'b0;
|
||||
|
||||
if (i_reset) begin
|
||||
o_sd_clk <= 1'b0;
|
||||
r_spi_bit_clk <= 4'd8;
|
||||
r_spi_multi_tx_address <= 9'd0;
|
||||
r_spi_multi_rx_address <= 9'd0;
|
||||
end else begin
|
||||
if (!r_spi_busy && (r_spi_start || r_spi_start_multi)) begin
|
||||
r_spi_busy <= 1'b1;
|
||||
r_spi_multi <= r_spi_start_multi;
|
||||
r_spi_first_bit <= 1'b1;
|
||||
end else if (r_spi_busy && r_spi_clk_strobe) begin
|
||||
if (r_spi_first_bit) begin
|
||||
r_spi_first_bit <= 1'b0;
|
||||
{o_sd_mosi, r_spi_tx_shift} <= w_next_spi_tx_data;
|
||||
r_spi_multi_tx_address <= r_spi_multi_tx_address + 1'd1;
|
||||
end else if (!o_sd_clk) begin
|
||||
o_sd_clk <= 1'b1;
|
||||
r_spi_rx_data <= {r_spi_rx_data[6:0], i_sd_miso};
|
||||
r_spi_bit_clk <= r_spi_bit_clk - 1'd1;
|
||||
if (r_spi_bit_clk == 4'd1) begin
|
||||
r_spi_multi_rx_byte_write <= 1'b1;
|
||||
end
|
||||
end else begin
|
||||
o_sd_clk <= 1'b0;
|
||||
if (r_spi_bit_clk == 4'd0) begin
|
||||
{o_sd_mosi, r_spi_tx_shift} <= w_next_spi_tx_data;
|
||||
r_spi_bit_clk <= 4'd8;
|
||||
r_spi_multi_tx_address <= r_spi_multi_tx_address + 1'd1;
|
||||
r_spi_multi_rx_address <= r_spi_multi_rx_address + 1'd1;
|
||||
if (r_spi_multi_rx_address == r_spi_multi_length) begin
|
||||
r_spi_busy <= 1'b0;
|
||||
r_spi_multi_tx_address <= 9'd0;
|
||||
r_spi_multi_rx_address <= 9'd0;
|
||||
end
|
||||
end else begin
|
||||
{o_sd_mosi, r_spi_tx_shift} <= {r_spi_tx_shift, 1'b0};
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// DMA RX FIFO controller
|
||||
|
||||
reg [1:0] r_dma_byte_counter;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
r_dma_fifo_push <= 1'b0;
|
||||
|
||||
if (i_reset) begin
|
||||
r_dma_byte_counter <= 2'd0;
|
||||
end else begin
|
||||
if (!r_spi_busy || (r_spi_busy && !r_spi_multi_dma)) begin
|
||||
if (r_dma_fifo_flush) begin
|
||||
r_dma_byte_counter <= 2'd0;
|
||||
end
|
||||
end else if (r_spi_multi_rx_byte_write && r_spi_multi_dma) begin
|
||||
r_dma_byte_counter <= r_dma_byte_counter + 1'd1;
|
||||
r_dma_fifo_data <= {r_dma_fifo_data[23:0], r_spi_rx_data};
|
||||
if (r_dma_byte_counter == 2'd3) begin
|
||||
r_dma_fifo_push <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
380
fw/rtl/top.v
380
fw/rtl/top.v
@ -1,3 +1,5 @@
|
||||
`include "constants.vh"
|
||||
|
||||
module top (
|
||||
input i_clk,
|
||||
|
||||
@ -6,8 +8,8 @@ module top (
|
||||
input i_ftdi_so,
|
||||
input i_ftdi_cts,
|
||||
|
||||
input i_n64_nmi,
|
||||
input i_n64_reset,
|
||||
input i_n64_nmi,
|
||||
|
||||
input i_n64_pi_alel,
|
||||
input i_n64_pi_aleh,
|
||||
@ -18,8 +20,8 @@ module top (
|
||||
input i_n64_si_clk,
|
||||
inout io_n64_si_dq,
|
||||
|
||||
input i_n64_cic_clk,
|
||||
inout io_n64_cic_dq,
|
||||
input i_n64_cic_clk, // TODO: to be removed
|
||||
inout io_n64_cic_dq, // TODO: to be removed
|
||||
|
||||
output o_sdram_clk,
|
||||
output o_sdram_cs,
|
||||
@ -34,9 +36,9 @@ module top (
|
||||
inout io_sd_cmd,
|
||||
inout [3:0] io_sd_dat,
|
||||
|
||||
output o_flash_clk,
|
||||
output o_flash_cs,
|
||||
inout [3:0] io_flash_dq,
|
||||
output o_flash_clk, // TODO: to be removed
|
||||
output o_flash_cs, // TODO: to be removed
|
||||
inout [3:0] io_flash_dq, // TODO: to be removed
|
||||
|
||||
output o_sram_clk,
|
||||
output o_sram_cs,
|
||||
@ -47,7 +49,7 @@ module top (
|
||||
|
||||
output o_led,
|
||||
|
||||
inout [7:0] io_pmod
|
||||
inout [7:0] io_pmod // TODO: to be removed
|
||||
);
|
||||
|
||||
// Clock and reset signals
|
||||
@ -58,6 +60,18 @@ module top (
|
||||
wire w_sys_reset = ~w_pll_lock;
|
||||
|
||||
|
||||
// Temporary signal names
|
||||
|
||||
wire w_n64_reset_btn;
|
||||
|
||||
assign io_n64_cic_dq = 1'bZ;
|
||||
assign {o_flash_clk, o_flash_cs, io_flash_dq} = 6'bZZZZZZ;
|
||||
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 (
|
||||
@ -78,14 +92,6 @@ module top (
|
||||
);
|
||||
|
||||
|
||||
// Bank ids
|
||||
|
||||
localparam [3:0] BANK_INVALID = 4'd0;
|
||||
localparam [3:0] BANK_ROM = 4'd1;
|
||||
localparam [3:0] BANK_CART = 4'd2;
|
||||
localparam [3:0] BANK_EEPROM = 4'd3;
|
||||
|
||||
|
||||
// N64 PI
|
||||
|
||||
wire w_n64_request;
|
||||
@ -113,14 +119,31 @@ module top (
|
||||
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_ack = w_n64_ack_cart_control || w_n64_ack_sdram || w_n64_ack_embedded_flash || w_n64_ack_eeprom;
|
||||
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 (
|
||||
@ -141,7 +164,19 @@ module top (
|
||||
.o_bank(w_n64_bank),
|
||||
.o_address(w_n64_address),
|
||||
.i_data(w_n64_i_data),
|
||||
.o_data(w_n64_o_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)
|
||||
);
|
||||
|
||||
|
||||
@ -168,6 +203,17 @@ module top (
|
||||
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;
|
||||
@ -177,7 +223,9 @@ module top (
|
||||
if (w_pc_ack_eeprom) w_pc_i_data = w_pc_i_data_eeprom;
|
||||
end
|
||||
|
||||
usb_pc usb_pc_inst (
|
||||
usb_pc #(
|
||||
.VERSION(`VERSION)
|
||||
) usb_pc_inst (
|
||||
.i_clk(w_sys_clk),
|
||||
.i_reset(w_sys_reset),
|
||||
|
||||
@ -193,7 +241,18 @@ module top (
|
||||
.o_bank(w_pc_bank),
|
||||
.o_address(w_pc_address),
|
||||
.i_data(w_pc_i_data),
|
||||
.o_data(w_pc_o_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)
|
||||
);
|
||||
|
||||
|
||||
@ -203,47 +262,44 @@ module top (
|
||||
wire w_cart_control_write;
|
||||
wire w_cart_control_busy;
|
||||
wire w_cart_control_ack;
|
||||
wire [25:0] w_cart_control_address;
|
||||
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 device_arbiter_cart_control_inst (
|
||||
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_pri(w_n64_request),
|
||||
.i_write_pri(w_n64_write),
|
||||
.o_busy_pri(w_n64_busy_cart_control),
|
||||
.o_ack_pri(w_n64_ack_cart_control),
|
||||
.i_bank_pri(w_n64_bank),
|
||||
.i_address_pri(w_n64_address[25:2]),
|
||||
.o_data_pri(w_n64_i_data_cart_control),
|
||||
.i_data_pri(w_n64_o_data),
|
||||
|
||||
.i_request_sec(w_pc_request),
|
||||
.i_write_sec(w_pc_write),
|
||||
.o_busy_sec(w_pc_busy_cart_control),
|
||||
.o_ack_sec(w_pc_ack_cart_control),
|
||||
.i_bank_sec(w_pc_bank),
|
||||
.i_address_sec(w_pc_address[25:2]),
|
||||
.o_data_sec(w_pc_i_data_cart_control),
|
||||
.i_data_sec(w_pc_o_data),
|
||||
|
||||
.o_request(w_cart_control_request),
|
||||
.o_write(w_cart_control_write),
|
||||
.i_busy(w_cart_control_busy),
|
||||
.i_ack(w_cart_control_ack),
|
||||
.o_address(w_cart_control_address),
|
||||
.i_data(w_cart_control_o_data),
|
||||
.o_data(w_cart_control_i_data)
|
||||
);
|
||||
defparam device_arbiter_cart_control_inst.DEVICE_BANK = BANK_CART;
|
||||
|
||||
cart_control cart_control_inst (
|
||||
.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),
|
||||
|
||||
@ -257,68 +313,158 @@ module top (
|
||||
.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_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_rom_switch && w_n64_request && !w_n64_write && w_n64_bank == BANK_ROM),
|
||||
.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[25:2]),
|
||||
.i_address(w_n64_address[20:2]),
|
||||
.o_data(w_n64_i_data_embedded_flash)
|
||||
);
|
||||
|
||||
|
||||
// SD card
|
||||
|
||||
wire w_sd_clk;
|
||||
wire w_sd_cs;
|
||||
wire w_sd_mosi;
|
||||
wire w_sd_miso;
|
||||
|
||||
assign o_sd_clk = w_sd_clk;
|
||||
assign io_sd_dat = {w_sd_cs, 3'bZZZ};
|
||||
assign io_sd_cmd = w_sd_mosi;
|
||||
assign w_sd_miso = io_sd_dat[0];
|
||||
|
||||
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),
|
||||
.o_sd_cs(w_sd_cs),
|
||||
.o_sd_mosi(w_sd_mosi),
|
||||
.i_sd_miso(w_sd_miso),
|
||||
|
||||
.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: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 [25:0] w_sdram_address;
|
||||
wire [24:0] w_sdram_address;
|
||||
wire [31:0] w_sdram_o_data;
|
||||
wire [31:0] w_sdram_i_data;
|
||||
|
||||
device_arbiter device_arbiter_sdram_inst (
|
||||
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_pri(w_rom_switch && w_n64_request),
|
||||
.i_write_pri(w_n64_write),
|
||||
.o_busy_pri(w_n64_busy_sdram),
|
||||
.o_ack_pri(w_n64_ack_sdram),
|
||||
.i_bank_pri(w_n64_bank),
|
||||
.i_address_pri(w_n64_address[25:1]),
|
||||
.o_data_pri(w_n64_i_data_sdram),
|
||||
.i_data_pri(w_n64_o_data),
|
||||
|
||||
.i_request_sec(w_pc_request),
|
||||
.i_write_sec(w_pc_write),
|
||||
.o_busy_sec(w_pc_busy_sdram),
|
||||
.o_ack_sec(w_pc_ack_sdram),
|
||||
.i_bank_sec(w_pc_bank),
|
||||
.i_address_sec(w_pc_address[25:1]),
|
||||
.o_data_sec(w_pc_i_data_sdram),
|
||||
.i_data_sec(w_pc_o_data),
|
||||
|
||||
.o_request(w_sdram_request),
|
||||
.o_write(w_sdram_write),
|
||||
.i_busy(w_sdram_busy),
|
||||
.i_ack(w_sdram_ack),
|
||||
.o_address(w_sdram_address),
|
||||
.i_data(w_sdram_o_data),
|
||||
.o_data(w_sdram_i_data)
|
||||
|
||||
.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)
|
||||
);
|
||||
defparam device_arbiter_sdram_inst.DEVICE_BANK = BANK_ROM;
|
||||
|
||||
memory_sdram memory_sdram_inst (
|
||||
.i_clk(w_sys_clk),
|
||||
@ -348,41 +494,35 @@ module top (
|
||||
wire w_eeprom_write;
|
||||
wire w_eeprom_busy;
|
||||
wire w_eeprom_ack;
|
||||
wire [25:0] w_eeprom_address;
|
||||
wire [8:0] w_eeprom_address;
|
||||
wire [31:0] w_eeprom_o_data;
|
||||
wire [31:0] w_eeprom_i_data;
|
||||
|
||||
device_arbiter device_arbiter_eeprom_inst (
|
||||
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_pri(w_n64_request),
|
||||
.i_write_pri(w_n64_write),
|
||||
.o_busy_pri(w_n64_busy_eeprom),
|
||||
.o_ack_pri(w_n64_ack_eeprom),
|
||||
.i_bank_pri(w_n64_bank),
|
||||
.i_address_pri(w_n64_address[25:2]),
|
||||
.o_data_pri(w_n64_i_data_eeprom),
|
||||
.i_data_pri(w_n64_o_data),
|
||||
|
||||
.i_request_sec(w_pc_request),
|
||||
.i_write_sec(w_pc_write),
|
||||
.o_busy_sec(w_pc_busy_eeprom),
|
||||
.o_ack_sec(w_pc_ack_eeprom),
|
||||
.i_bank_sec(w_pc_bank),
|
||||
.i_address_sec(w_pc_address[25:2]),
|
||||
.o_data_sec(w_pc_i_data_eeprom),
|
||||
.i_data_sec(w_pc_o_data),
|
||||
|
||||
.o_request(w_eeprom_request),
|
||||
.o_write(w_eeprom_write),
|
||||
.i_busy(w_eeprom_busy),
|
||||
.i_ack(w_eeprom_ack),
|
||||
.o_address(w_eeprom_address),
|
||||
.i_data(w_eeprom_o_data),
|
||||
.o_data(w_eeprom_i_data)
|
||||
|
||||
.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)
|
||||
);
|
||||
defparam device_arbiter_eeprom_inst.DEVICE_BANK = BANK_EEPROM;
|
||||
|
||||
n64_si n64_si_inst (
|
||||
.i_clk(w_sys_clk),
|
||||
@ -404,4 +544,18 @@ module top (
|
||||
.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
|
||||
|
@ -14,9 +14,25 @@ module usb_pc (
|
||||
output reg [3:0] o_bank,
|
||||
output reg [25:0] o_address,
|
||||
input [31:0] i_data,
|
||||
output reg [31:0] o_data
|
||||
output reg [31:0] o_data,
|
||||
|
||||
input i_debug_start,
|
||||
output o_debug_busy,
|
||||
input [3:0] i_debug_bank,
|
||||
input [23:0] i_debug_address,
|
||||
input [19:0] i_debug_length,
|
||||
|
||||
input i_debug_fifo_request,
|
||||
input i_debug_fifo_flush,
|
||||
output [10:0] o_debug_fifo_items,
|
||||
output [31:0] o_debug_fifo_data
|
||||
);
|
||||
|
||||
// Module parameters
|
||||
|
||||
parameter byte VERSION = "a";
|
||||
|
||||
|
||||
// FTDI transport
|
||||
|
||||
reg r_ftdi_rx_ready;
|
||||
@ -47,15 +63,38 @@ module usb_pc (
|
||||
);
|
||||
|
||||
|
||||
// Debug FIFO
|
||||
|
||||
wire w_fifo_usb_full;
|
||||
wire [9:0] w_fifo_usb_items;
|
||||
reg r_fifo_usb_write_request;
|
||||
reg [31:0] r_fifo_usb_data;
|
||||
|
||||
assign o_debug_fifo_items = {w_fifo_usb_full, w_fifo_usb_items};
|
||||
|
||||
fifo_usb fifo_usb_inst (
|
||||
.clock(i_clk),
|
||||
.sclr(i_debug_fifo_flush),
|
||||
|
||||
.full(w_fifo_usb_full),
|
||||
.usedw(w_fifo_usb_items),
|
||||
|
||||
.wrreq(r_fifo_usb_write_request),
|
||||
.data(r_fifo_usb_data),
|
||||
|
||||
.rdreq(i_debug_fifo_request),
|
||||
.q(o_debug_fifo_data)
|
||||
);
|
||||
|
||||
|
||||
// Command ids
|
||||
|
||||
localparam byte CMD_TRIGGER [0:2] = '{"C", "M", "D"};
|
||||
|
||||
localparam byte CMD_IDENTIFY = "I";
|
||||
localparam byte CMD_READ = "R";
|
||||
localparam byte CMD_WRITE = "W";
|
||||
localparam byte CMD_DEBUG_MODE = "D";
|
||||
localparam byte CMD_DEBUG_WRITE = "F";
|
||||
localparam byte CMD_DEBUG_WRITE = "D";
|
||||
localparam byte CMD_DEBUG_SEND = "Q";
|
||||
|
||||
localparam [1:0] RX_STAGE_CMD = 2'd0;
|
||||
localparam [1:0] RX_STAGE_PARAM = 2'd1;
|
||||
@ -87,12 +126,19 @@ module usb_pc (
|
||||
r_rx_stage <= RX_STAGE_CMD;
|
||||
r_rx_byte_counter <= 3'd0;
|
||||
end else begin
|
||||
if (i_debug_start) begin
|
||||
r_rx_stage <= RX_STAGE_IGNORE;
|
||||
r_rx_cmd <= CMD_DEBUG_SEND;
|
||||
r_tx_cmd <= CMD_DEBUG_SEND;
|
||||
r_tx_cmd_valid <= 1'b1;
|
||||
end
|
||||
|
||||
if (w_ftdi_rx_valid) begin
|
||||
r_rx_byte_counter <= r_rx_byte_counter + 3'd1;
|
||||
|
||||
case (r_rx_stage)
|
||||
RX_STAGE_CMD: begin
|
||||
if (w_ftdi_rx_data != CMD_TRIGGER[r_rx_byte_counter]) begin
|
||||
if (w_ftdi_rx_data != CMD_TRIGGER[r_rx_byte_counter[1:0]]) begin
|
||||
r_rx_byte_counter <= 3'd0;
|
||||
end
|
||||
|
||||
@ -107,13 +153,9 @@ module usb_pc (
|
||||
r_tx_cmd <= w_ftdi_rx_data;
|
||||
end
|
||||
|
||||
CMD_READ: r_rx_stage <= RX_STAGE_PARAM;
|
||||
|
||||
CMD_WRITE: r_rx_stage <= RX_STAGE_PARAM;
|
||||
|
||||
CMD_DEBUG_MODE: r_rx_stage <= RX_STAGE_PARAM;
|
||||
|
||||
CMD_DEBUG_WRITE: r_rx_stage <= RX_STAGE_DATA;
|
||||
CMD_DEBUG_WRITE: r_rx_stage <= RX_STAGE_PARAM;
|
||||
|
||||
default: r_rx_stage <= RX_STAGE_CMD;
|
||||
endcase
|
||||
@ -124,16 +166,6 @@ module usb_pc (
|
||||
r_rx_buffer <= {r_rx_buffer[55:0], w_ftdi_rx_data};
|
||||
|
||||
case (r_rx_cmd)
|
||||
CMD_READ: begin
|
||||
if (r_rx_byte_counter == 3'd7) begin
|
||||
r_rx_stage <= RX_STAGE_IGNORE;
|
||||
r_rx_byte_counter <= 3'd0;
|
||||
r_rx_param_valid <= 1'b1;
|
||||
r_tx_cmd_valid <= 1'b1;
|
||||
r_tx_cmd <= r_rx_cmd;
|
||||
end
|
||||
end
|
||||
|
||||
CMD_WRITE: begin
|
||||
if (r_rx_byte_counter == 3'd7) begin
|
||||
r_rx_stage <= RX_STAGE_DATA;
|
||||
@ -142,14 +174,6 @@ module usb_pc (
|
||||
end
|
||||
end
|
||||
|
||||
CMD_DEBUG_MODE: begin
|
||||
if (r_rx_byte_counter == 3'd3) begin
|
||||
r_rx_stage <= RX_STAGE_CMD;
|
||||
r_rx_byte_counter <= 3'd0;
|
||||
r_rx_param_valid <= 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
CMD_DEBUG_WRITE: begin
|
||||
if (r_rx_byte_counter == 3'd3) begin
|
||||
r_rx_stage <= RX_STAGE_DATA;
|
||||
@ -182,10 +206,13 @@ module usb_pc (
|
||||
end
|
||||
|
||||
CMD_DEBUG_WRITE: begin
|
||||
if (r_data_items_remaining == 20'd0) begin
|
||||
r_rx_stage <= RX_STAGE_CMD;
|
||||
if (r_rx_byte_counter == 3'd3) begin
|
||||
if (r_data_items_remaining == 20'd0) begin
|
||||
r_rx_stage <= RX_STAGE_CMD;
|
||||
end
|
||||
r_rx_byte_counter <= 3'd0;
|
||||
r_rx_buffer_valid <= 1'b1;
|
||||
end
|
||||
r_rx_buffer_valid <= 1'b1;
|
||||
end
|
||||
|
||||
default: begin
|
||||
@ -215,41 +242,44 @@ module usb_pc (
|
||||
|
||||
// Command parameter decoder
|
||||
|
||||
reg r_tx_debug_enabled;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
if (i_reset) begin
|
||||
r_tx_debug_enabled <= 1'b0;
|
||||
end else begin
|
||||
if (r_rx_param_valid) begin
|
||||
case (r_rx_cmd)
|
||||
CMD_READ, CMD_WRITE: begin
|
||||
o_address <= {r_rx_buffer[63:34], 2'b00};
|
||||
CMD_WRITE: begin
|
||||
o_address <= {r_rx_buffer[57:34], 2'b00};
|
||||
o_bank <= r_rx_buffer[27:24];
|
||||
r_data_items_remaining <= r_rx_buffer[19:0];
|
||||
end
|
||||
|
||||
CMD_DEBUG_MODE: begin
|
||||
r_tx_debug_enabled <= r_rx_buffer[0];
|
||||
end
|
||||
|
||||
CMD_DEBUG_WRITE: begin
|
||||
r_data_items_remaining <= r_rx_buffer[19:0];
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
if (r_tx_cmd_valid && r_tx_cmd == CMD_DEBUG_SEND) begin
|
||||
o_bank <= i_debug_bank;
|
||||
o_address <= {i_debug_address, 2'b00};
|
||||
r_data_items_remaining <= i_debug_length;
|
||||
end
|
||||
|
||||
if (o_request && !i_busy && r_data_items_remaining > 20'd0) begin
|
||||
o_address[25:2] <= o_address[25:2] + 1'd1;
|
||||
r_data_items_remaining <= r_data_items_remaining - 1'd1;
|
||||
end
|
||||
|
||||
if (r_fifo_usb_write_request && r_data_items_remaining > 20'd0) begin
|
||||
r_data_items_remaining <= r_data_items_remaining - 1'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// TX module
|
||||
|
||||
localparam byte IDENTIFY_STRING [0:3] = '{"S", "6", "4", "a"};
|
||||
localparam byte IDENTIFY_STRING [0:3] = '{"S", "6", "4", VERSION};
|
||||
localparam byte RSP_COMPLETE [0:2] = '{"C", "M", "P"};
|
||||
|
||||
localparam [1:0] TX_STAGE_IDLE = 2'd0;
|
||||
@ -268,7 +298,7 @@ module usb_pc (
|
||||
TX_STAGE_DATA: begin
|
||||
case (r_tx_cmd)
|
||||
CMD_IDENTIFY: r_ftdi_tx_data = IDENTIFY_STRING[r_tx_byte_counter];
|
||||
CMD_READ: r_ftdi_tx_data = r_i_data_buffer[(r_tx_byte_counter * 8) -: 8];
|
||||
CMD_DEBUG_SEND: r_ftdi_tx_data = r_i_data_buffer[(((4 - r_tx_byte_counter) * 8) - 1) -: 8];
|
||||
endcase
|
||||
end
|
||||
|
||||
@ -281,9 +311,16 @@ module usb_pc (
|
||||
|
||||
wire w_tx_successful = r_ftdi_tx_valid && !w_ftdi_tx_busy;
|
||||
|
||||
reg r_bus_data_request;
|
||||
reg r_bus_data_valid;
|
||||
reg r_bus_data_feisable;
|
||||
|
||||
assign o_debug_busy = r_tx_stage == TX_STAGE_DATA && r_tx_cmd == CMD_DEBUG_SEND;
|
||||
|
||||
always @(posedge i_clk) begin
|
||||
r_ftdi_tx_valid <= 1'b0;
|
||||
r_tx_done <= 1'b0;
|
||||
r_bus_data_request <= 1'b0;
|
||||
|
||||
if (i_reset) begin
|
||||
r_tx_stage <= TX_STAGE_IDLE;
|
||||
@ -295,11 +332,21 @@ module usb_pc (
|
||||
r_tx_byte_counter <= 2'd0;
|
||||
|
||||
if (r_tx_cmd_valid) begin
|
||||
r_ftdi_tx_valid <= 1'b1;
|
||||
|
||||
case (r_tx_cmd)
|
||||
CMD_IDENTIFY: r_tx_stage <= TX_STAGE_DATA;
|
||||
default: r_tx_stage <= TX_STAGE_RESPONSE;
|
||||
CMD_IDENTIFY: begin
|
||||
r_tx_stage <= TX_STAGE_DATA;
|
||||
r_ftdi_tx_valid <= 1'b1;
|
||||
end
|
||||
|
||||
CMD_DEBUG_SEND: begin
|
||||
r_bus_data_request <= 1'b1;
|
||||
r_tx_stage <= TX_STAGE_DATA;
|
||||
end
|
||||
|
||||
default: begin
|
||||
r_tx_stage <= TX_STAGE_RESPONSE;
|
||||
r_ftdi_tx_valid <= 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
@ -312,16 +359,34 @@ module usb_pc (
|
||||
CMD_IDENTIFY: begin
|
||||
r_tx_stage <= TX_STAGE_RESPONSE;
|
||||
end
|
||||
|
||||
CMD_READ: begin
|
||||
if (r_data_items_remaining == 20'd0) begin
|
||||
r_tx_stage <= TX_STAGE_RESPONSE;
|
||||
end
|
||||
end
|
||||
|
||||
default: r_tx_stage <= TX_STAGE_RESPONSE;
|
||||
endcase
|
||||
end
|
||||
|
||||
if (r_tx_cmd == CMD_DEBUG_SEND) begin
|
||||
r_ftdi_tx_valid <= 1'b0;
|
||||
|
||||
if (r_bus_data_valid) begin
|
||||
r_bus_data_feisable <= 1'b1;
|
||||
end
|
||||
|
||||
if (r_bus_data_feisable) begin
|
||||
r_ftdi_tx_valid <= 1'b1;
|
||||
end
|
||||
|
||||
if (w_tx_successful) begin
|
||||
if (r_tx_byte_counter == 2'd3 && r_bus_data_feisable) begin
|
||||
r_bus_data_request <= 1'b1;
|
||||
r_bus_data_feisable <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
if (w_tx_successful && r_data_items_remaining == 20'd0 && r_tx_byte_counter == 2'd3) begin
|
||||
r_bus_data_request <= 1'b0;
|
||||
r_tx_stage <= TX_STAGE_IDLE;
|
||||
r_tx_done <= 1'b1;
|
||||
r_bus_data_feisable <= 1'b0;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
TX_STAGE_RESPONSE: begin
|
||||
@ -344,6 +409,8 @@ module usb_pc (
|
||||
always @(posedge i_clk) begin
|
||||
o_request <= 1'b0;
|
||||
o_write <= 1'b0;
|
||||
r_bus_data_valid <= 1'b0;
|
||||
r_fifo_usb_write_request <= 1'b0;
|
||||
|
||||
if (i_reset) begin
|
||||
r_ftdi_rx_ready <= 1'b1;
|
||||
@ -366,13 +433,33 @@ module usb_pc (
|
||||
r_ftdi_rx_ready <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
CMD_DEBUG_WRITE: begin
|
||||
if (r_rx_buffer_valid) begin
|
||||
r_fifo_usb_data <= r_rx_buffer[31:0];
|
||||
r_fifo_usb_write_request <= 1'b1;
|
||||
end
|
||||
|
||||
if (w_fifo_usb_full) begin
|
||||
r_ftdi_rx_ready <= 1'b0;
|
||||
end else begin
|
||||
r_ftdi_rx_ready <= 1'b1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
// TODO: Read from bus
|
||||
// case (r_tx_cmd)
|
||||
// CMD_READ: begin
|
||||
// end
|
||||
// endcase
|
||||
if (r_bus_data_request) begin
|
||||
o_request <= 1'b1;
|
||||
end
|
||||
|
||||
if (o_request && i_busy) begin
|
||||
o_request <= 1'b1;
|
||||
end
|
||||
|
||||
if (i_ack) begin
|
||||
r_i_data_buffer <= i_data;
|
||||
r_bus_data_valid <= 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
0
hw/.gitignore → hw/v1/.gitignore
vendored
0
hw/.gitignore → hw/v1/.gitignore
vendored
@ -4225,15 +4225,6 @@ design rules under a new name.</description>
|
||||
<wire x1="-10.2" y1="2" x2="-5.8" y2="2" width="0.127" layer="1"/>
|
||||
<wire x1="-5.8" y1="2" x2="-3.1" y2="4.7" width="0.127" layer="1"/>
|
||||
</signal>
|
||||
<signal name="JTCK_C">
|
||||
<contactref element="J1" pad="44"/>
|
||||
<contactref element="RN2" pad="1"/>
|
||||
<wire x1="-15" y1="-6" x2="-15" y2="0.7" width="0.127" layer="1"/>
|
||||
<wire x1="-7.3" y1="2.9" x2="-5.5" y2="4.7" width="0.127" layer="1"/>
|
||||
<wire x1="-5.5" y1="4.7" x2="-5.5" y2="5.325" width="0.127" layer="1"/>
|
||||
<wire x1="-15" y1="0.7" x2="-12.8" y2="2.9" width="0.127" layer="1"/>
|
||||
<wire x1="-12.8" y1="2.9" x2="-7.3" y2="2.9" width="0.127" layer="1"/>
|
||||
</signal>
|
||||
<signal name="CLK_SDRAM">
|
||||
<contactref element="U2" pad="38"/>
|
||||
<contactref element="U1" pad="75"/>
|
||||
@ -5588,6 +5579,15 @@ design rules under a new name.</description>
|
||||
<wire x1="-41.3" y1="24.8" x2="-42.355" y2="24.8" width="0.127" layer="1"/>
|
||||
<wire x1="-42.355" y1="24.8" x2="-42.365" y2="24.81" width="0.127" layer="1"/>
|
||||
</signal>
|
||||
<signal name="/INT_C">
|
||||
<contactref element="J1" pad="44"/>
|
||||
<contactref element="RN2" pad="1"/>
|
||||
<wire x1="-7.3" y1="2.9" x2="-5.5" y2="4.7" width="0.127" layer="1"/>
|
||||
<wire x1="-5.5" y1="4.7" x2="-5.5" y2="5.325" width="0.127" layer="1"/>
|
||||
<wire x1="-15" y1="0.7" x2="-12.8" y2="2.9" width="0.127" layer="1"/>
|
||||
<wire x1="-12.8" y1="2.9" x2="-7.3" y2="2.9" width="0.127" layer="1"/>
|
||||
<wire x1="-15" y1="-6" x2="-15" y2="0.7" width="0.127" layer="1"/>
|
||||
</signal>
|
||||
</signals>
|
||||
<mfgpreviewcolors>
|
||||
<mfgpreviewcolor name="soldermaskcolor" color="0xC8008000"/>
|
@ -6,7 +6,7 @@
|
||||
<setting alwaysvectorfont="no"/>
|
||||
<setting verticaltext="up"/>
|
||||
</settings>
|
||||
<grid distance="0.5" unitdist="mm" unit="mm" style="lines" multiple="1" display="yes" altdistance="5" altunitdist="mil" altunit="mil"/>
|
||||
<grid distance="0.1" unitdist="inch" unit="inch" style="lines" multiple="1" display="yes" altdistance="0.01" altunitdist="inch" altunit="inch"/>
|
||||
<layers>
|
||||
<layer number="1" name="Top" color="4" fill="1" visible="yes" active="yes"/>
|
||||
<layer number="2" name="Route2" color="16" fill="1" visible="yes" active="yes"/>
|
||||
@ -796,7 +796,7 @@
|
||||
<pin name="AD7" x="20.32" y="25.4" length="middle" rot="R180"/>
|
||||
<pin name="3V3@42" x="-20.32" y="35.56" length="middle" direction="pwr"/>
|
||||
<pin name="CIC_DATA_CLK" x="20.32" y="-30.48" length="middle" direction="out" rot="R180"/>
|
||||
<pin name="JTCK" x="20.32" y="-17.78" length="middle" direction="in" rot="R180"/>
|
||||
<pin name="/INT" x="20.32" y="-17.78" length="middle" direction="in" function="dot" rot="R180"/>
|
||||
<pin name="/NMI" x="20.32" y="-15.24" length="middle" direction="out" function="dot" rot="R180"/>
|
||||
<pin name="VIDEO_SYNC" x="20.32" y="-38.1" length="middle" direction="out" rot="R180"/>
|
||||
<pin name="GND@47" x="-20.32" y="0" length="middle" direction="pwr"/>
|
||||
@ -1191,6 +1191,7 @@
|
||||
<devices>
|
||||
<device name="" package="N64_EDGE">
|
||||
<connects>
|
||||
<connect gate=">NAME" pin="/INT" pad="44"/>
|
||||
<connect gate=">NAME" pin="/NMI" pad="45"/>
|
||||
<connect gate=">NAME" pin="/READ" pad="10"/>
|
||||
<connect gate=">NAME" pin="/RESET" pad="20"/>
|
||||
@ -1233,7 +1234,6 @@
|
||||
<connect gate=">NAME" pin="GND@48" pad="48"/>
|
||||
<connect gate=">NAME" pin="GND@50" pad="50"/>
|
||||
<connect gate=">NAME" pin="GND@6" pad="6"/>
|
||||
<connect gate=">NAME" pin="JTCK" pad="44"/>
|
||||
<connect gate=">NAME" pin="KEY@14" pad="14"/>
|
||||
<connect gate=">NAME" pin="KEY@39" pad="39"/>
|
||||
<connect gate=">NAME" pin="LAUDIO" pad="24"/>
|
@ -802,7 +802,7 @@
|
||||
<pin name="AD7" x="20.32" y="25.4" length="middle" rot="R180"/>
|
||||
<pin name="3V3@42" x="-20.32" y="35.56" length="middle" direction="pwr"/>
|
||||
<pin name="CIC_DATA_CLK" x="20.32" y="-30.48" length="middle" direction="out" rot="R180"/>
|
||||
<pin name="JTCK" x="20.32" y="-17.78" length="middle" direction="in" rot="R180"/>
|
||||
<pin name="/INT" x="20.32" y="-17.78" length="middle" direction="in" function="dot" rot="R180"/>
|
||||
<pin name="/NMI" x="20.32" y="-15.24" length="middle" direction="out" function="dot" rot="R180"/>
|
||||
<pin name="VIDEO_SYNC" x="20.32" y="-38.1" length="middle" direction="out" rot="R180"/>
|
||||
<pin name="GND@47" x="-20.32" y="0" length="middle" direction="pwr"/>
|
||||
@ -1197,6 +1197,7 @@
|
||||
<devices>
|
||||
<device name="" package="N64_EDGE">
|
||||
<connects>
|
||||
<connect gate=">NAME" pin="/INT" pad="44"/>
|
||||
<connect gate=">NAME" pin="/NMI" pad="45"/>
|
||||
<connect gate=">NAME" pin="/READ" pad="10"/>
|
||||
<connect gate=">NAME" pin="/RESET" pad="20"/>
|
||||
@ -1239,7 +1240,6 @@
|
||||
<connect gate=">NAME" pin="GND@48" pad="48"/>
|
||||
<connect gate=">NAME" pin="GND@50" pad="50"/>
|
||||
<connect gate=">NAME" pin="GND@6" pad="6"/>
|
||||
<connect gate=">NAME" pin="JTCK" pad="44"/>
|
||||
<connect gate=">NAME" pin="KEY@14" pad="14"/>
|
||||
<connect gate=">NAME" pin="KEY@39" pad="39"/>
|
||||
<connect gate=">NAME" pin="LAUDIO" pad="24"/>
|
||||
@ -16374,18 +16374,6 @@ Source: http://www.st.com/stonline/products/literature/ds/7194/ld1117axx.pdf</de
|
||||
<pinref part="RN2" gate="D" pin="1"/>
|
||||
</segment>
|
||||
</net>
|
||||
<net name="JTCK_C" class="0">
|
||||
<segment>
|
||||
<pinref part="J1" gate=">NAME" pin="JTCK"/>
|
||||
<wire x1="274.32" y1="287.02" x2="281.94" y2="287.02" width="0.1524" layer="91"/>
|
||||
<label x="281.94" y="287.02" size="1.27" layer="95" xref="yes"/>
|
||||
</segment>
|
||||
<segment>
|
||||
<pinref part="RN2" gate="A" pin="1"/>
|
||||
<wire x1="175.26" y1="337.82" x2="182.88" y2="337.82" width="0.1524" layer="91"/>
|
||||
<label x="182.88" y="337.82" size="1.27" layer="95" rot="MR180" xref="yes"/>
|
||||
</segment>
|
||||
</net>
|
||||
<net name="CLK_SDRAM" class="0">
|
||||
<segment>
|
||||
<pinref part="U2" gate="G$1" pin="CLK"/>
|
||||
@ -17858,6 +17846,18 @@ Source: http://www.st.com/stonline/products/literature/ds/7194/ld1117axx.pdf</de
|
||||
<pinref part="S1" gate="G$1" pin="3"/>
|
||||
</segment>
|
||||
</net>
|
||||
<net name="/INT_C" class="0">
|
||||
<segment>
|
||||
<pinref part="J1" gate=">NAME" pin="/INT"/>
|
||||
<wire x1="274.32" y1="287.02" x2="281.94" y2="287.02" width="0.1524" layer="91"/>
|
||||
<label x="281.94" y="287.02" size="1.27" layer="95" xref="yes"/>
|
||||
</segment>
|
||||
<segment>
|
||||
<pinref part="RN2" gate="A" pin="1"/>
|
||||
<wire x1="175.26" y1="337.82" x2="182.88" y2="337.82" width="0.1524" layer="91"/>
|
||||
<label x="182.88" y="337.82" size="1.27" layer="95" rot="MR180" xref="yes"/>
|
||||
</segment>
|
||||
</net>
|
||||
</nets>
|
||||
</sheet>
|
||||
</sheets>
|
0
hw/v2/.gitkeep
Normal file
0
hw/v2/.gitkeep
Normal file
@ -6,7 +6,7 @@ HEADERPATH = $(ROOTDIR)/mips64-elf/lib
|
||||
N64TOOL = $(ROOTDIR)/bin/n64tool
|
||||
HEADERNAME = header
|
||||
LINK_FLAGS = -L$(ROOTDIR)/mips64-elf/lib -ldragon -lc -lm -ldragonsys -Tn64.ld
|
||||
CFLAGS = -std=gnu99 -march=vr4300 -mtune=vr4300 -Os -Wall -Werror -I$(ROOTDIR)/mips64-elf/include
|
||||
CFLAGS = -std=gnu99 -march=vr4300 -mtune=vr4300 -Os -Wall -I./src -I./src/boot -I./src/fatfs -I./src/sc64 -I$(ROOTDIR)/mips64-elf/include
|
||||
ASFLAGS = -mtune=vr4300 -march=vr4300
|
||||
CC = $(GCCN64PREFIX)gcc
|
||||
AS = $(GCCN64PREFIX)as
|
||||
@ -14,7 +14,7 @@ LD = $(GCCN64PREFIX)ld
|
||||
OBJCOPY = $(GCCN64PREFIX)objcopy
|
||||
OBJDUMP = $(GCCN64PREFIX)objdump
|
||||
|
||||
SRC_DIRS = src
|
||||
SRC_DIRS = src src/boot src/fatfs src/sc64
|
||||
SRC_FILES = $(wildcard $(patsubst %, %/*.c, . $(SRC_DIRS)))
|
||||
OBJ_FILES = $(addprefix build/, $(notdir $(SRC_FILES:.c=.o)))
|
||||
VPATH = $(SRC_DIRS)
|
||||
|
@ -1,90 +0,0 @@
|
||||
#ifndef BOOT_H__
|
||||
#define BOOT_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define BOOT_CRC32_5101 (0x587BD543)
|
||||
#define BOOT_CRC32_6101 (0x6170A4A1)
|
||||
#define BOOT_CRC32_7102 (0x009E9EA3)
|
||||
#define BOOT_CRC32_X102 (0x90BB6CB5)
|
||||
#define BOOT_CRC32_X103 (0x0B050EE0)
|
||||
#define BOOT_CRC32_X105 (0x98BC2C86)
|
||||
#define BOOT_CRC32_X106 (0xACC8580A)
|
||||
#define BOOT_CRC32_8303 (0x0E018159)
|
||||
|
||||
#define BOOT_SEED_5101 (0x0000AC00)
|
||||
#define BOOT_SEED_X101 (0x00043F3F)
|
||||
#define BOOT_SEED_X102 (0x00003F3F)
|
||||
#define BOOT_SEED_X103 (0x0000783F)
|
||||
#define BOOT_SEED_X105 (0x0000913F)
|
||||
#define BOOT_SEED_X106 (0x0000853F)
|
||||
#define BOOT_SEED_8303 (0x0000DD00)
|
||||
|
||||
#define BOOT_SEED_IPL3(x) (((x) & 0x0000FF00) >> 8)
|
||||
#define BOOT_SEED_OS_VERSION(x) (((x) & 0x00040000) >> 18)
|
||||
|
||||
typedef enum cic_type_e {
|
||||
E_CIC_TYPE_UNKNOWN,
|
||||
E_CIC_TYPE_5101,
|
||||
E_CIC_TYPE_X101,
|
||||
E_CIC_TYPE_X102,
|
||||
E_CIC_TYPE_X103,
|
||||
E_CIC_TYPE_X105,
|
||||
E_CIC_TYPE_X106,
|
||||
E_CIC_TYPE_8303,
|
||||
E_CIC_TYPE_END,
|
||||
} cic_type_t;
|
||||
|
||||
typedef enum tv_type_e {
|
||||
E_TV_TYPE_PAL,
|
||||
E_TV_TYPE_NTSC,
|
||||
E_TV_TYPE_MPAL,
|
||||
E_TV_TYPE_UNKNOWN,
|
||||
} tv_type_t;
|
||||
|
||||
struct cart_header_s {
|
||||
uint32_t pi_conf;
|
||||
uint32_t clock_rate;
|
||||
uint32_t boot_addr;
|
||||
uint32_t release_addr;
|
||||
uint32_t crc_1;
|
||||
uint32_t crc_2;
|
||||
uint32_t __unused_1[2];
|
||||
char name[20];
|
||||
uint32_t __unused_2;
|
||||
uint32_t format;
|
||||
char id[2];
|
||||
char country_code;
|
||||
uint8_t version;
|
||||
uint32_t boot_code[1008];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
typedef struct cart_header_s cart_header_t;
|
||||
|
||||
struct os_boot_config_s {
|
||||
uint32_t tv_type;
|
||||
uint32_t rom_type;
|
||||
uint32_t rom_base;
|
||||
uint32_t reset_type;
|
||||
uint32_t cic_id;
|
||||
uint32_t version;
|
||||
uint32_t mem_size;
|
||||
uint8_t app_nmi_buffer[64];
|
||||
uint32_t __unused[37];
|
||||
uint32_t mem_size_6105;
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
typedef struct os_boot_config_s os_boot_config_t;
|
||||
|
||||
#define OS_BOOT_CONFIG_BASE (0xA0000300)
|
||||
#define OS_BOOT_CONFIG ((os_boot_config_t *) OS_BOOT_CONFIG_BASE)
|
||||
|
||||
#define OS_BOOT_ROM_TYPE_GAME_PAK (0)
|
||||
#define OS_BOOT_ROM_TYPE_DD (1)
|
||||
|
||||
cart_header_t *boot_load_cart_header(void);
|
||||
cic_type_t boot_get_cic_type(cart_header_t *cart_header);
|
||||
tv_type_t boot_get_tv_type(cart_header_t *cart_header);
|
||||
void boot(cart_header_t *cart_header, cic_type_t cic_type, tv_type_t tv_type);
|
||||
|
||||
#endif
|
@ -1,41 +1,45 @@
|
||||
#include <libdragon.h>
|
||||
|
||||
#include "boot.h"
|
||||
#include "crc32.h"
|
||||
#include "n64_regs.h"
|
||||
|
||||
static cart_header_t global_cart_header __attribute__((aligned(8)));
|
||||
|
||||
static const struct crc32_to_cic_seed crc32_to_cic_seed[] = {
|
||||
{ .ipl3_crc32 = 0x587BD543, .cic_seed = 0x00AC }, // CIC5101
|
||||
{ .ipl3_crc32 = 0x6170A4A1, .cic_seed = 0x013F }, // CIC6101
|
||||
{ .ipl3_crc32 = 0x009E9EA3, .cic_seed = 0x013F }, // CIC7102
|
||||
{ .ipl3_crc32 = 0x90BB6CB5, .cic_seed = 0x003F }, // CICx102
|
||||
{ .ipl3_crc32 = 0x0B050EE0, .cic_seed = 0x0078 }, // CICx103
|
||||
{ .ipl3_crc32 = 0x98BC2C86, .cic_seed = 0x0091 }, // CICx105
|
||||
{ .ipl3_crc32 = 0xACC8580A, .cic_seed = 0x0085 }, // CICx106
|
||||
{ .ipl3_crc32 = 0x10C68B18, .cic_seed = 0x00DD }, // JP 64DD dev
|
||||
{ .ipl3_crc32 = 0x0E018159, .cic_seed = 0x00DD }, // JP 64DD retail
|
||||
{ .ipl3_crc32 = 0x8FEBA21E, .cic_seed = 0x00DE }, // US 64DD retail
|
||||
};
|
||||
|
||||
|
||||
static cart_header_t global_cart_header __attribute__((aligned(16)));
|
||||
|
||||
|
||||
cart_header_t *boot_load_cart_header(void) {
|
||||
cart_header_t *cart_header_pointer = &global_cart_header;
|
||||
|
||||
data_cache_hit_writeback_invalidate(cart_header_pointer, sizeof(cart_header_t));
|
||||
dma_read(cart_header_pointer, CART_BASE, sizeof(cart_header_t));
|
||||
data_cache_hit_invalidate(cart_header_pointer, sizeof(cart_header_t));
|
||||
platform_pi_dma_read(cart_header_pointer, CART_BASE, sizeof(cart_header_t));
|
||||
platform_cache_invalidate(cart_header_pointer, sizeof(cart_header_t));
|
||||
|
||||
return cart_header_pointer;
|
||||
}
|
||||
|
||||
cic_type_t boot_get_cic_type(cart_header_t *cart_header) {
|
||||
switch (crc32_calculate(cart_header->boot_code, sizeof(cart_header->boot_code))) {
|
||||
case BOOT_CRC32_5101:
|
||||
return E_CIC_TYPE_5101;
|
||||
case BOOT_CRC32_6101:
|
||||
case BOOT_CRC32_7102:
|
||||
return E_CIC_TYPE_X101;
|
||||
case BOOT_CRC32_X102:
|
||||
return E_CIC_TYPE_X102;
|
||||
case BOOT_CRC32_X103:
|
||||
return E_CIC_TYPE_X103;
|
||||
case BOOT_CRC32_X105:
|
||||
return E_CIC_TYPE_X105;
|
||||
case BOOT_CRC32_X106:
|
||||
return E_CIC_TYPE_X106;
|
||||
case BOOT_CRC32_8303:
|
||||
return E_CIC_TYPE_8303;
|
||||
default:
|
||||
return E_CIC_TYPE_UNKNOWN;
|
||||
uint16_t boot_get_cic_seed(cart_header_t *cart_header) {
|
||||
uint16_t cic_seed = crc32_to_cic_seed[3].cic_seed;
|
||||
uint32_t ipl3_crc32 = crc32_calculate(cart_header->boot_code, sizeof(cart_header->boot_code));
|
||||
|
||||
for (size_t i = 0; i < ARRAY_ITEMS(crc32_to_cic_seed); i++) {
|
||||
if (crc32_to_cic_seed[i].ipl3_crc32 == ipl3_crc32) {
|
||||
cic_seed = crc32_to_cic_seed[i].cic_seed;
|
||||
}
|
||||
}
|
||||
|
||||
return cic_seed;
|
||||
}
|
||||
|
||||
tv_type_t boot_get_tv_type(cart_header_t *cart_header) {
|
||||
@ -66,22 +70,18 @@ tv_type_t boot_get_tv_type(cart_header_t *cart_header) {
|
||||
}
|
||||
}
|
||||
|
||||
void boot(cart_header_t *cart_header, cic_type_t cic_type, tv_type_t tv_type) {
|
||||
void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type, uint32_t ddipl_override) {
|
||||
uint32_t is_x105_boot = (cic_seed == crc32_to_cic_seed[5].cic_seed);
|
||||
uint32_t is_ddipl_boot = (
|
||||
ddipl_override ||
|
||||
(cic_seed == crc32_to_cic_seed[7].cic_seed) ||
|
||||
(cic_seed == crc32_to_cic_seed[8].cic_seed) ||
|
||||
(cic_seed == crc32_to_cic_seed[9].cic_seed)
|
||||
);
|
||||
tv_type_t os_tv_type = tv_type == E_TV_TYPE_UNKNOWN ? OS_BOOT_CONFIG->tv_type : tv_type;
|
||||
|
||||
volatile uint64_t gpr_regs[32];
|
||||
|
||||
const uint32_t cic_seeds[] = {
|
||||
BOOT_SEED_X102,
|
||||
BOOT_SEED_5101,
|
||||
BOOT_SEED_X101,
|
||||
BOOT_SEED_X102,
|
||||
BOOT_SEED_X103,
|
||||
BOOT_SEED_X105,
|
||||
BOOT_SEED_X106,
|
||||
BOOT_SEED_8303,
|
||||
};
|
||||
|
||||
while (!(SP->status & SP_STATUS_HALT));
|
||||
|
||||
SP->status = SP_STATUS_CLEAR_INTERRUPT | SP_STATUS_SET_HALT;
|
||||
@ -119,7 +119,7 @@ void boot(cart_header_t *cart_header, cic_type_t cic_type, tv_type_t tv_type) {
|
||||
SP_MEM->imem[6] = 0x8DA80024; // lw t0, 0x0024(t5)
|
||||
SP_MEM->imem[7] = 0x3C0BB000; // lui t3, 0xB000
|
||||
|
||||
if (cic_type == E_CIC_TYPE_X105) {
|
||||
if (is_x105_boot) {
|
||||
OS_BOOT_CONFIG->mem_size_6105 = OS_BOOT_CONFIG->mem_size;
|
||||
}
|
||||
|
||||
@ -128,11 +128,11 @@ void boot(cart_header_t *cart_header, cic_type_t cic_type, tv_type_t tv_type) {
|
||||
}
|
||||
|
||||
gpr_regs[CPU_REG_T3] = CPU_ADDRESS_IN_REG(SP_MEM->dmem[16]);
|
||||
gpr_regs[CPU_REG_S3] = OS_BOOT_ROM_TYPE_GAME_PAK;
|
||||
gpr_regs[CPU_REG_S3] = is_ddipl_boot ? OS_BOOT_ROM_TYPE_DD : OS_BOOT_ROM_TYPE_GAME_PAK;
|
||||
gpr_regs[CPU_REG_S4] = os_tv_type;
|
||||
gpr_regs[CPU_REG_S5] = OS_BOOT_CONFIG->reset_type;
|
||||
gpr_regs[CPU_REG_S6] = BOOT_SEED_IPL3(cic_seeds[cic_type]);
|
||||
gpr_regs[CPU_REG_S7] = BOOT_SEED_OS_VERSION(cic_seeds[cic_type]);
|
||||
gpr_regs[CPU_REG_S6] = BOOT_SEED_IPL3(cic_seed);
|
||||
gpr_regs[CPU_REG_S7] = BOOT_SEED_OS_VERSION(cic_seed);
|
||||
gpr_regs[CPU_REG_SP] = CPU_ADDRESS_IN_REG(SP_MEM->imem[ARRAY_ITEMS(SP_MEM->imem) - 4]);
|
||||
gpr_regs[CPU_REG_RA] = CPU_ADDRESS_IN_REG(SP_MEM->imem[(os_tv_type == E_TV_TYPE_PAL) ? 341 : 340]);
|
||||
|
71
sw/bootloader/src/boot/boot.h
Normal file
71
sw/bootloader/src/boot/boot.h
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef BOOT_H__
|
||||
#define BOOT_H__
|
||||
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
struct crc32_to_cic_seed {
|
||||
uint32_t ipl3_crc32;
|
||||
uint16_t cic_seed;
|
||||
};
|
||||
|
||||
typedef enum tv_type_e {
|
||||
E_TV_TYPE_PAL,
|
||||
E_TV_TYPE_NTSC,
|
||||
E_TV_TYPE_MPAL,
|
||||
E_TV_TYPE_UNKNOWN,
|
||||
} tv_type_t;
|
||||
|
||||
struct cart_header_s {
|
||||
uint32_t pi_conf;
|
||||
uint32_t clock_rate;
|
||||
uint32_t boot_addr;
|
||||
uint32_t release_addr;
|
||||
uint32_t crc_1;
|
||||
uint32_t crc_2;
|
||||
uint32_t __unused_1[2];
|
||||
char name[20];
|
||||
uint32_t __unused_2;
|
||||
uint32_t format;
|
||||
char id[2];
|
||||
char country_code;
|
||||
uint8_t version;
|
||||
uint32_t boot_code[1008];
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
typedef struct cart_header_s cart_header_t;
|
||||
|
||||
struct os_boot_config_s {
|
||||
uint32_t tv_type;
|
||||
uint32_t rom_type;
|
||||
uint32_t rom_base;
|
||||
uint32_t reset_type;
|
||||
uint32_t cic_id;
|
||||
uint32_t version;
|
||||
uint32_t mem_size;
|
||||
uint8_t app_nmi_buffer[64];
|
||||
uint32_t __unused[37];
|
||||
uint32_t mem_size_6105;
|
||||
} __attribute__((packed, aligned(1)));
|
||||
|
||||
typedef struct os_boot_config_s os_boot_config_t;
|
||||
|
||||
|
||||
#define OS_BOOT_CONFIG_BASE (0xA0000300)
|
||||
#define OS_BOOT_CONFIG ((os_boot_config_t *) OS_BOOT_CONFIG_BASE)
|
||||
|
||||
#define OS_BOOT_ROM_TYPE_GAME_PAK (0)
|
||||
#define OS_BOOT_ROM_TYPE_DD (1)
|
||||
|
||||
#define BOOT_SEED_IPL3(x) (((x) & 0x000000FF) >> 0)
|
||||
#define BOOT_SEED_OS_VERSION(x) (((x) & 0x00000100) >> 8)
|
||||
|
||||
|
||||
cart_header_t *boot_load_cart_header(void);
|
||||
uint16_t boot_get_cic_seed(cart_header_t *cart_header);
|
||||
tv_type_t boot_get_tv_type(cart_header_t *cart_header);
|
||||
void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type, uint32_t ddipl_override);
|
||||
|
||||
|
||||
#endif
|
@ -1,6 +1,7 @@
|
||||
#include "crc32.h"
|
||||
|
||||
const uint32_t crc_table[256] = {
|
||||
|
||||
static const uint32_t crc_table[256] = {
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||
@ -35,14 +36,15 @@ const uint32_t crc_table[256] = {
|
||||
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D,
|
||||
};
|
||||
|
||||
|
||||
uint32_t crc32_calculate(void *buffer, size_t length) {
|
||||
uint32_t crc32 = 0xFFFFFFFF;
|
||||
|
||||
|
||||
uint8_t *byte_pointer = (uint8_t *) buffer;
|
||||
|
||||
while (length--) {
|
||||
crc32 = (crc32 >> 8) ^ crc_table[(crc32 & 0xFF) ^ (*byte_pointer++)];
|
||||
}
|
||||
|
||||
|
||||
return ~crc32;
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
#ifndef CRC32_H__
|
||||
#define CRC32_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
uint32_t crc32_calculate(void *buffer, size_t length);
|
||||
|
||||
|
||||
#endif
|
@ -1,12 +1,16 @@
|
||||
#ifndef N64_REGS_H__
|
||||
#define N64_REGS_H__
|
||||
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
#define ARRAY_ITEMS(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
|
||||
#define CPU_ADDRESS_IN_REG(x) ((0xFFFFFFFFULL << 32) | ((uint32_t) (&(x))))
|
||||
|
||||
|
||||
#define CPU_REG_Z0 (0)
|
||||
#define CPU_REG_AT (1)
|
||||
#define CPU_REG_V0 (2)
|
||||
@ -40,6 +44,7 @@
|
||||
#define CPU_REG_FP (30)
|
||||
#define CPU_REG_RA (31)
|
||||
|
||||
|
||||
typedef struct SP_MEM_s {
|
||||
volatile uint32_t dmem[1024];
|
||||
volatile uint32_t imem[1024];
|
||||
@ -109,12 +114,14 @@ typedef struct PI_regs_s {
|
||||
volatile uint32_t dom2_rls;
|
||||
} PI_regs_t;
|
||||
|
||||
|
||||
#define SP_MEM_BASE (0xA4000000)
|
||||
#define SP_REGS_BASE (0xA4040000)
|
||||
#define DP_CMD_REGS_BASE (0xA4100000)
|
||||
#define VI_REGS_BASE (0xA4400000)
|
||||
#define AI_REGS_BASE (0xA4500000)
|
||||
#define PI_REGS_BASE (0xA4600000)
|
||||
#define DDIPL_BASE (0xA6000000)
|
||||
#define CART_BASE (0xB0000000)
|
||||
|
||||
#define SP_MEM ((volatile SP_MEM_t *) SP_MEM_BASE)
|
||||
@ -123,6 +130,7 @@ typedef struct PI_regs_s {
|
||||
#define VI ((volatile VI_regs_t *) VI_REGS_BASE)
|
||||
#define AI ((volatile AI_regs_t *) AI_REGS_BASE)
|
||||
#define PI ((volatile PI_regs_t *) PI_REGS_BASE)
|
||||
#define DDIPL ((volatile uint32_t *) DDIPL_BASE)
|
||||
#define CART ((volatile uint32_t *) CART_BASE)
|
||||
|
||||
#define SP_STATUS_HALT (1 << 0)
|
||||
@ -142,4 +150,5 @@ typedef struct PI_regs_s {
|
||||
#define PI_STATUS_RESET_CONTROLLER (1 << 0)
|
||||
#define PI_STATUS_CLEAR_INTERRUPT (1 << 1)
|
||||
|
||||
|
||||
#endif
|
45
sw/bootloader/src/error_display.c
Normal file
45
sw/bootloader/src/error_display.c
Normal file
@ -0,0 +1,45 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "error_display.h"
|
||||
|
||||
|
||||
void error_display_and_halt(menu_load_error_t error, const char *path) {
|
||||
init_interrupts();
|
||||
|
||||
display_init(RESOLUTION_320x240, DEPTH_32_BPP, 2, GAMMA_NONE, ANTIALIAS_RESAMPLE);
|
||||
|
||||
console_init();
|
||||
console_set_render_mode(RENDER_MANUAL);
|
||||
console_clear();
|
||||
|
||||
printf("SC64 Bootloader ver. %d.%02d error:\n\n%2d: ", BOOTLOADER_VERSION_MAJOR, BOOTLOADER_VERSION_MINOR, error);
|
||||
|
||||
switch (error) {
|
||||
case E_MENU_OK:
|
||||
printf("No error :O");
|
||||
break;
|
||||
case E_MENU_ERROR_NOT_SC64:
|
||||
printf("SummerCart64 not detected");
|
||||
break;
|
||||
case E_MENU_ERROR_NO_CARD:
|
||||
printf("SD Card not detected");
|
||||
break;
|
||||
case E_MENU_ERROR_NO_FILESYSTEM:
|
||||
printf("No filesystem (FAT or exFAT)\nfound on SD Card");
|
||||
break;
|
||||
case E_MENU_ERROR_NO_FILE:
|
||||
printf("Unable to locate menu file:\n(%s)", path);
|
||||
break;
|
||||
case E_MENU_ERROR_READ_ERROR:
|
||||
printf("Error while reading data from\nSD Card");
|
||||
break;
|
||||
case E_MENU_ERROR_OTHER_ERROR:
|
||||
default:
|
||||
printf("Unknown error");
|
||||
break;
|
||||
}
|
||||
|
||||
console_render();
|
||||
|
||||
while (1);
|
||||
}
|
22
sw/bootloader/src/error_display.h
Normal file
22
sw/bootloader/src/error_display.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef ERROR_DISPLAY_H__
|
||||
#define ERROR_DISPLAY_H__
|
||||
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
typedef enum menu_load_error_e {
|
||||
E_MENU_OK,
|
||||
E_MENU_ERROR_NOT_SC64,
|
||||
E_MENU_ERROR_NO_CARD,
|
||||
E_MENU_ERROR_NO_FILESYSTEM,
|
||||
E_MENU_ERROR_NO_FILE,
|
||||
E_MENU_ERROR_READ_ERROR,
|
||||
E_MENU_ERROR_OTHER_ERROR,
|
||||
} menu_load_error_t;
|
||||
|
||||
|
||||
void error_display_and_halt(menu_load_error_t error, const char *path);
|
||||
|
||||
|
||||
#endif
|
346
sw/bootloader/src/fatfs/00history.txt
Normal file
346
sw/bootloader/src/fatfs/00history.txt
Normal file
@ -0,0 +1,346 @@
|
||||
----------------------------------------------------------------------------
|
||||
Revision history of FatFs module
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
R0.00 (February 26, 2006)
|
||||
|
||||
Prototype.
|
||||
|
||||
|
||||
|
||||
R0.01 (April 29, 2006)
|
||||
|
||||
The first release.
|
||||
|
||||
|
||||
|
||||
R0.02 (June 01, 2006)
|
||||
|
||||
Added FAT12 support.
|
||||
Removed unbuffered mode.
|
||||
Fixed a problem on small (<32M) partition.
|
||||
|
||||
|
||||
|
||||
R0.02a (June 10, 2006)
|
||||
|
||||
Added a configuration option (_FS_MINIMUM).
|
||||
|
||||
|
||||
|
||||
R0.03 (September 22, 2006)
|
||||
|
||||
Added f_rename().
|
||||
Changed option _FS_MINIMUM to _FS_MINIMIZE.
|
||||
|
||||
|
||||
|
||||
R0.03a (December 11, 2006)
|
||||
|
||||
Improved cluster scan algorithm to write files fast.
|
||||
Fixed f_mkdir() creates incorrect directory on FAT32.
|
||||
|
||||
|
||||
|
||||
R0.04 (February 04, 2007)
|
||||
|
||||
Added f_mkfs().
|
||||
Supported multiple drive system.
|
||||
Changed some interfaces for multiple drive system.
|
||||
Changed f_mountdrv() to f_mount().
|
||||
|
||||
|
||||
|
||||
R0.04a (April 01, 2007)
|
||||
|
||||
Supported multiple partitions on a physical drive.
|
||||
Added a capability of extending file size to f_lseek().
|
||||
Added minimization level 3.
|
||||
Fixed an endian sensitive code in f_mkfs().
|
||||
|
||||
|
||||
|
||||
R0.04b (May 05, 2007)
|
||||
|
||||
Added a configuration option _USE_NTFLAG.
|
||||
Added FSINFO support.
|
||||
Fixed DBCS name can result FR_INVALID_NAME.
|
||||
Fixed short seek (<= csize) collapses the file object.
|
||||
|
||||
|
||||
|
||||
R0.05 (August 25, 2007)
|
||||
|
||||
Changed arguments of f_read(), f_write() and f_mkfs().
|
||||
Fixed f_mkfs() on FAT32 creates incorrect FSINFO.
|
||||
Fixed f_mkdir() on FAT32 creates incorrect directory.
|
||||
|
||||
|
||||
|
||||
R0.05a (February 03, 2008)
|
||||
|
||||
Added f_truncate() and f_utime().
|
||||
Fixed off by one error at FAT sub-type determination.
|
||||
Fixed btr in f_read() can be mistruncated.
|
||||
Fixed cached sector is not flushed when create and close without write.
|
||||
|
||||
|
||||
|
||||
R0.06 (April 01, 2008)
|
||||
|
||||
Added fputc(), fputs(), fprintf() and fgets().
|
||||
Improved performance of f_lseek() on moving to the same or following cluster.
|
||||
|
||||
|
||||
|
||||
R0.07 (April 01, 2009)
|
||||
|
||||
Merged Tiny-FatFs as a configuration option. (_FS_TINY)
|
||||
Added long file name feature. (_USE_LFN)
|
||||
Added multiple code page feature. (_CODE_PAGE)
|
||||
Added re-entrancy for multitask operation. (_FS_REENTRANT)
|
||||
Added auto cluster size selection to f_mkfs().
|
||||
Added rewind option to f_readdir().
|
||||
Changed result code of critical errors.
|
||||
Renamed string functions to avoid name collision.
|
||||
|
||||
|
||||
|
||||
R0.07a (April 14, 2009)
|
||||
|
||||
Septemberarated out OS dependent code on reentrant cfg.
|
||||
Added multiple sector size feature.
|
||||
|
||||
|
||||
|
||||
R0.07c (June 21, 2009)
|
||||
|
||||
Fixed f_unlink() can return FR_OK on error.
|
||||
Fixed wrong cache control in f_lseek().
|
||||
Added relative path feature.
|
||||
Added f_chdir() and f_chdrive().
|
||||
Added proper case conversion to extended character.
|
||||
|
||||
|
||||
|
||||
R0.07e (November 03, 2009)
|
||||
|
||||
Septemberarated out configuration options from ff.h to ffconf.h.
|
||||
Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH.
|
||||
Fixed name matching error on the 13 character boundary.
|
||||
Added a configuration option, _LFN_UNICODE.
|
||||
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
|
||||
|
||||
|
||||
|
||||
R0.08 (May 15, 2010)
|
||||
|
||||
Added a memory configuration option. (_USE_LFN = 3)
|
||||
Added file lock feature. (_FS_SHARE)
|
||||
Added fast seek feature. (_USE_FASTSEEK)
|
||||
Changed some types on the API, XCHAR->TCHAR.
|
||||
Changed .fname in the FILINFO structure on Unicode cfg.
|
||||
String functions support UTF-8 encoding files on Unicode cfg.
|
||||
|
||||
|
||||
|
||||
R0.08a (August 16, 2010)
|
||||
|
||||
Added f_getcwd(). (_FS_RPATH = 2)
|
||||
Added sector erase feature. (_USE_ERASE)
|
||||
Moved file lock semaphore table from fs object to the bss.
|
||||
Fixed f_mkfs() creates wrong FAT32 volume.
|
||||
|
||||
|
||||
|
||||
R0.08b (January 15, 2011)
|
||||
|
||||
Fast seek feature is also applied to f_read() and f_write().
|
||||
f_lseek() reports required table size on creating CLMP.
|
||||
Extended format syntax of f_printf().
|
||||
Ignores duplicated directory separators in given path name.
|
||||
|
||||
|
||||
|
||||
R0.09 (September 06, 2011)
|
||||
|
||||
f_mkfs() supports multiple partition to complete the multiple partition feature.
|
||||
Added f_fdisk().
|
||||
|
||||
|
||||
|
||||
R0.09a (August 27, 2012)
|
||||
|
||||
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
|
||||
Changed option name _FS_SHARE to _FS_LOCK.
|
||||
Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
|
||||
|
||||
|
||||
|
||||
R0.09b (January 24, 2013)
|
||||
|
||||
Added f_setlabel() and f_getlabel().
|
||||
|
||||
|
||||
|
||||
R0.10 (October 02, 2013)
|
||||
|
||||
Added selection of character encoding on the file. (_STRF_ENCODE)
|
||||
Added f_closedir().
|
||||
Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
|
||||
Added forced mount feature with changes of f_mount().
|
||||
Improved behavior of volume auto detection.
|
||||
Improved write throughput of f_puts() and f_printf().
|
||||
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
|
||||
Fixed f_write() can be truncated when the file size is close to 4GB.
|
||||
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect value on error.
|
||||
|
||||
|
||||
|
||||
R0.10a (January 15, 2014)
|
||||
|
||||
Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
|
||||
Added a configuration option of minimum sector size. (_MIN_SS)
|
||||
2nd argument of f_rename() can have a drive number and it will be ignored.
|
||||
Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10)
|
||||
Fixed f_close() invalidates the file object without volume lock.
|
||||
Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10)
|
||||
Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07)
|
||||
|
||||
|
||||
|
||||
R0.10b (May 19, 2014)
|
||||
|
||||
Fixed a hard error in the disk I/O layer can collapse the directory entry.
|
||||
Fixed LFN entry is not deleted when delete/rename an object with lossy converted SFN. (appeared at R0.07)
|
||||
|
||||
|
||||
|
||||
R0.10c (November 09, 2014)
|
||||
|
||||
Added a configuration option for the platforms without RTC. (_FS_NORTC)
|
||||
Changed option name _USE_ERASE to _USE_TRIM.
|
||||
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b)
|
||||
Fixed a potential problem of FAT access that can appear on disk error.
|
||||
Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08)
|
||||
|
||||
|
||||
|
||||
R0.11 (February 09, 2015)
|
||||
|
||||
Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND)
|
||||
Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c)
|
||||
Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)
|
||||
|
||||
|
||||
|
||||
R0.11a (September 05, 2015)
|
||||
|
||||
Fixed wrong media change can lead a deadlock at thread-safe configuration.
|
||||
Added code page 771, 860, 861, 863, 864, 865 and 869. (_CODE_PAGE)
|
||||
Removed some code pages actually not exist on the standard systems. (_CODE_PAGE)
|
||||
Fixed errors in the case conversion teble of code page 437 and 850 (ff.c).
|
||||
Fixed errors in the case conversion teble of Unicode (cc*.c).
|
||||
|
||||
|
||||
|
||||
R0.12 (April 12, 2016)
|
||||
|
||||
Added support for exFAT file system. (_FS_EXFAT)
|
||||
Added f_expand(). (_USE_EXPAND)
|
||||
Changed some members in FINFO structure and behavior of f_readdir().
|
||||
Added an option _USE_CHMOD.
|
||||
Removed an option _WORD_ACCESS.
|
||||
Fixed errors in the case conversion table of Unicode (cc*.c).
|
||||
|
||||
|
||||
|
||||
R0.12a (July 10, 2016)
|
||||
|
||||
Added support for creating exFAT volume with some changes of f_mkfs().
|
||||
Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed.
|
||||
f_forward() is available regardless of _FS_TINY.
|
||||
Fixed f_mkfs() creates wrong volume. (appeared at R0.12)
|
||||
Fixed wrong memory read in create_name(). (appeared at R0.12)
|
||||
Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD.
|
||||
|
||||
|
||||
|
||||
R0.12b (September 04, 2016)
|
||||
|
||||
Made f_rename() be able to rename objects with the same name but case.
|
||||
Fixed an error in the case conversion teble of code page 866. (ff.c)
|
||||
Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12)
|
||||
Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12)
|
||||
Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12)
|
||||
Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12)
|
||||
Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12)
|
||||
Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12)
|
||||
|
||||
|
||||
|
||||
R0.12c (March 04, 2017)
|
||||
|
||||
Improved write throughput at the fragmented file on the exFAT volume.
|
||||
Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN.
|
||||
Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12)
|
||||
Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c)
|
||||
|
||||
|
||||
|
||||
R0.13 (May 21, 2017)
|
||||
|
||||
Changed heading character of configuration keywords "_" to "FF_".
|
||||
Removed ASCII-only configuration, FF_CODE_PAGE = 1. Use FF_CODE_PAGE = 437 instead.
|
||||
Added f_setcp(), run-time code page configuration. (FF_CODE_PAGE = 0)
|
||||
Improved cluster allocation time on stretch a deep buried cluster chain.
|
||||
Improved processing time of f_mkdir() with large cluster size by using FF_USE_LFN = 3.
|
||||
Improved NoFatChain flag of the fragmented file to be set after it is truncated and got contiguous.
|
||||
Fixed archive attribute is left not set when a file on the exFAT volume is renamed. (appeared at R0.12)
|
||||
Fixed exFAT FAT entry can be collapsed when write or lseek operation to the existing file is done. (appeared at R0.12c)
|
||||
Fixed creating a file can fail when a new cluster allocation to the exFAT directory occures. (appeared at R0.12c)
|
||||
|
||||
|
||||
|
||||
R0.13a (October 14, 2017)
|
||||
|
||||
Added support for UTF-8 encoding on the API. (FF_LFN_UNICODE = 2)
|
||||
Added options for file name output buffer. (FF_LFN_BUF, FF_SFN_BUF).
|
||||
Added dynamic memory allocation option for working buffer of f_mkfs() and f_fdisk().
|
||||
Fixed f_fdisk() and f_mkfs() create the partition table with wrong CHS parameters. (appeared at R0.09)
|
||||
Fixed f_unlink() can cause lost clusters at fragmented file on the exFAT volume. (appeared at R0.12c)
|
||||
Fixed f_setlabel() rejects some valid characters for exFAT volume. (appeared at R0.12)
|
||||
|
||||
|
||||
|
||||
R0.13b (April 07, 2018)
|
||||
|
||||
Added support for UTF-32 encoding on the API. (FF_LFN_UNICODE = 3)
|
||||
Added support for Unix style volume ID. (FF_STR_VOLUME_ID = 2)
|
||||
Fixed accesing any object on the exFAT root directory beyond the cluster boundary can fail. (appeared at R0.12c)
|
||||
Fixed f_setlabel() does not reject some invalid characters. (appeared at R0.09b)
|
||||
|
||||
|
||||
|
||||
R0.13c (October 14, 2018)
|
||||
Supported stdint.h for C99 and later. (integer.h was included in ff.h)
|
||||
Fixed reading a directory gets infinite loop when the last directory entry is not empty. (appeared at R0.12)
|
||||
Fixed creating a sub-directory in the fragmented sub-directory on the exFAT volume collapses FAT chain of the parent directory. (appeared at R0.12)
|
||||
Fixed f_getcwd() cause output buffer overrun when the buffer has a valid drive number. (appeared at R0.13b)
|
||||
|
||||
|
||||
|
||||
R0.14 (October 14, 2019)
|
||||
Added support for 64-bit LBA and GUID partition table (FF_LBA64 = 1)
|
||||
Changed some API functions, f_mkfs() and f_fdisk().
|
||||
Fixed f_open() function cannot find the file with file name in length of FF_MAX_LFN characters.
|
||||
Fixed f_readdir() function cannot retrieve long file names in length of FF_MAX_LFN - 1 characters.
|
||||
Fixed f_readdir() function returns file names with wrong case conversion. (appeared at R0.12)
|
||||
Fixed f_mkfs() function can fail to create exFAT volume in the second partition. (appeared at R0.12)
|
||||
|
||||
|
||||
R0.14a (December 5, 2020)
|
||||
Limited number of recursive calls in f_findnext().
|
||||
Fixed old floppy disks formatted with MS-DOS 2.x and 3.x cannot be mounted.
|
||||
Fixed some compiler warnings.
|
||||
|
21
sw/bootloader/src/fatfs/00readme.txt
Normal file
21
sw/bootloader/src/fatfs/00readme.txt
Normal file
@ -0,0 +1,21 @@
|
||||
FatFs Module Source Files R0.14a
|
||||
|
||||
|
||||
FILES
|
||||
|
||||
00readme.txt This file.
|
||||
00history.txt Revision history.
|
||||
ff.c FatFs module.
|
||||
ffconf.h Configuration file of FatFs module.
|
||||
ff.h Common include file for FatFs and application module.
|
||||
diskio.h Common include file for FatFs and disk I/O module.
|
||||
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
||||
ffunicode.c Optional Unicode utility functions.
|
||||
ffsystem.c An example of optional O/S related functions.
|
||||
|
||||
|
||||
Low level disk I/O module is not included in this archive because the FatFs
|
||||
module is only a generic file system layer and it does not depend on any specific
|
||||
storage device. You need to provide a low level disk I/O module written to
|
||||
control the storage device that attached to the target system.
|
||||
|
84
sw/bootloader/src/fatfs/diskio.c
Normal file
84
sw/bootloader/src/fatfs/diskio.c
Normal file
@ -0,0 +1,84 @@
|
||||
#include "ff.h"
|
||||
#include "diskio.h"
|
||||
|
||||
#include "sc64_sd.h"
|
||||
|
||||
|
||||
DSTATUS disk_status(BYTE pdrv) {
|
||||
if (pdrv > 0) {
|
||||
return STA_NOINIT;
|
||||
}
|
||||
|
||||
return sc64_sd_get_status() ? 0 : STA_NOINIT;
|
||||
}
|
||||
|
||||
DSTATUS disk_initialize(BYTE pdrv) {
|
||||
if (pdrv > 0) {
|
||||
return STA_NOINIT;
|
||||
}
|
||||
|
||||
if (!sc64_sd_get_status()) {
|
||||
if (sc64_sd_init()) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return STA_NOINIT;
|
||||
}
|
||||
|
||||
DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
|
||||
uint8_t success;
|
||||
uint8_t response;
|
||||
|
||||
if ((pdrv > 0) || (count == 0)) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
if (!sc64_sd_get_status()) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
if (count == 1) {
|
||||
success = sc64_sd_cmd_send(CMD17, sector, &response);
|
||||
|
||||
if (!success || response) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
success = sc64_sd_block_read(buff, SD_BLOCK_SIZE, FALSE);
|
||||
|
||||
if (!success) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
} else {
|
||||
success = sc64_sd_cmd_send(CMD18, sector, &response);
|
||||
|
||||
if (!success || response) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
success = sc64_sd_block_read(buff, SD_BLOCK_SIZE, FALSE);
|
||||
|
||||
if (!success) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
buff += SD_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
success = sc64_sd_cmd_send(CMD12, 0, &response);
|
||||
|
||||
if (!success || response) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
|
||||
return RES_PARERR;
|
||||
}
|
77
sw/bootloader/src/fatfs/diskio.h
Normal file
77
sw/bootloader/src/fatfs/diskio.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*-----------------------------------------------------------------------/
|
||||
/ Low level disk interface modlue include file (C)ChaN, 2019 /
|
||||
/-----------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _DISKIO_DEFINED
|
||||
#define _DISKIO_DEFINED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Status of Disk Functions */
|
||||
typedef BYTE DSTATUS;
|
||||
|
||||
/* Results of Disk Functions */
|
||||
typedef enum {
|
||||
RES_OK = 0, /* 0: Successful */
|
||||
RES_ERROR, /* 1: R/W Error */
|
||||
RES_WRPRT, /* 2: Write Protected */
|
||||
RES_NOTRDY, /* 3: Not Ready */
|
||||
RES_PARERR /* 4: Invalid Parameter */
|
||||
} DRESULT;
|
||||
|
||||
|
||||
/*---------------------------------------*/
|
||||
/* Prototypes for disk control functions */
|
||||
|
||||
|
||||
DSTATUS disk_initialize (BYTE pdrv);
|
||||
DSTATUS disk_status (BYTE pdrv);
|
||||
DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count);
|
||||
DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count);
|
||||
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||
|
||||
|
||||
/* Disk Status Bits (DSTATUS) */
|
||||
|
||||
#define STA_NOINIT 0x01 /* Drive not initialized */
|
||||
#define STA_NODISK 0x02 /* No medium in the drive */
|
||||
#define STA_PROTECT 0x04 /* Write protected */
|
||||
|
||||
|
||||
/* Command code for disk_ioctrl fucntion */
|
||||
|
||||
/* Generic command (Used by FatFs) */
|
||||
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
|
||||
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
|
||||
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
|
||||
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
|
||||
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
|
||||
|
||||
/* Generic command (Not used by FatFs) */
|
||||
#define CTRL_POWER 5 /* Get/Set power status */
|
||||
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
|
||||
#define CTRL_EJECT 7 /* Eject media */
|
||||
#define CTRL_FORMAT 8 /* Create physical format on the media */
|
||||
|
||||
/* MMC/SDC specific ioctl command */
|
||||
#define MMC_GET_TYPE 10 /* Get card type */
|
||||
#define MMC_GET_CSD 11 /* Get CSD */
|
||||
#define MMC_GET_CID 12 /* Get CID */
|
||||
#define MMC_GET_OCR 13 /* Get OCR */
|
||||
#define MMC_GET_SDSTAT 14 /* Get SD status */
|
||||
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
|
||||
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
|
||||
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
|
||||
|
||||
/* ATA/CF specific ioctl command */
|
||||
#define ATA_GET_REV 20 /* Get F/W revision */
|
||||
#define ATA_GET_MODEL 21 /* Get model name */
|
||||
#define ATA_GET_SN 22 /* Get serial number */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
6876
sw/bootloader/src/fatfs/ff.c
Normal file
6876
sw/bootloader/src/fatfs/ff.c
Normal file
File diff suppressed because it is too large
Load Diff
424
sw/bootloader/src/fatfs/ff.h
Normal file
424
sw/bootloader/src/fatfs/ff.h
Normal file
@ -0,0 +1,424 @@
|
||||
/*----------------------------------------------------------------------------/
|
||||
/ FatFs - Generic FAT Filesystem module R0.14a /
|
||||
/-----------------------------------------------------------------------------/
|
||||
/
|
||||
/ Copyright (C) 2020, ChaN, all right reserved.
|
||||
/
|
||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||
/ source and binary forms, with or without modification, are permitted provided
|
||||
/ that the following condition is met:
|
||||
|
||||
/ 1. Redistributions of source code must retain the above copyright notice,
|
||||
/ this condition and the following disclaimer.
|
||||
/
|
||||
/ This software is provided by the copyright holder and contributors "AS IS"
|
||||
/ and any warranties related to this software are DISCLAIMED.
|
||||
/ The copyright owner or contributors be NOT LIABLE for any damages caused
|
||||
/ by use of this software.
|
||||
/
|
||||
/----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef FF_DEFINED
|
||||
#define FF_DEFINED 80196 /* Revision ID */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "ffconf.h" /* FatFs configuration options */
|
||||
|
||||
#if FF_DEFINED != FFCONF_DEF
|
||||
#error Wrong configuration file (ffconf.h).
|
||||
#endif
|
||||
|
||||
|
||||
/* Integer types used for FatFs API */
|
||||
|
||||
#if defined(_WIN32) /* Main development platform */
|
||||
#define FF_INTDEF 2
|
||||
#include <windows.h>
|
||||
typedef unsigned __int64 QWORD;
|
||||
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
|
||||
#define FF_INTDEF 2
|
||||
#include <stdint.h>
|
||||
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||
typedef uint16_t WORD; /* 16-bit unsigned integer */
|
||||
typedef uint32_t DWORD; /* 32-bit unsigned integer */
|
||||
typedef uint64_t QWORD; /* 64-bit unsigned integer */
|
||||
typedef WORD WCHAR; /* UTF-16 character type */
|
||||
#else /* Earlier than C99 */
|
||||
#define FF_INTDEF 1
|
||||
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||
typedef unsigned short WORD; /* 16-bit unsigned integer */
|
||||
typedef unsigned long DWORD; /* 32-bit unsigned integer */
|
||||
typedef WORD WCHAR; /* UTF-16 character type */
|
||||
#endif
|
||||
|
||||
|
||||
/* Definitions of volume management */
|
||||
|
||||
#if FF_MULTI_PARTITION /* Multiple partition configuration */
|
||||
typedef struct {
|
||||
BYTE pd; /* Physical drive number */
|
||||
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
|
||||
} PARTITION;
|
||||
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
|
||||
#endif
|
||||
|
||||
#if FF_STR_VOLUME_ID
|
||||
#ifndef FF_VOLUME_STRS
|
||||
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Type of path name strings on FatFs API */
|
||||
|
||||
#ifndef _INC_TCHAR
|
||||
#define _INC_TCHAR
|
||||
|
||||
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
|
||||
typedef WCHAR TCHAR;
|
||||
#define _T(x) L ## x
|
||||
#define _TEXT(x) L ## x
|
||||
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
|
||||
typedef char TCHAR;
|
||||
#define _T(x) u8 ## x
|
||||
#define _TEXT(x) u8 ## x
|
||||
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
|
||||
typedef DWORD TCHAR;
|
||||
#define _T(x) U ## x
|
||||
#define _TEXT(x) U ## x
|
||||
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
|
||||
#error Wrong FF_LFN_UNICODE setting
|
||||
#else /* ANSI/OEM code in SBCS/DBCS */
|
||||
typedef char TCHAR;
|
||||
#define _T(x) x
|
||||
#define _TEXT(x) x
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Type of file size and LBA variables */
|
||||
|
||||
#if FF_FS_EXFAT
|
||||
#if FF_INTDEF != 2
|
||||
#error exFAT feature wants C99 or later
|
||||
#endif
|
||||
typedef QWORD FSIZE_t;
|
||||
#if FF_LBA64
|
||||
typedef QWORD LBA_t;
|
||||
#else
|
||||
typedef DWORD LBA_t;
|
||||
#endif
|
||||
#else
|
||||
#if FF_LBA64
|
||||
#error exFAT needs to be enabled when enable 64-bit LBA
|
||||
#endif
|
||||
typedef DWORD FSIZE_t;
|
||||
typedef DWORD LBA_t;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Filesystem object structure (FATFS) */
|
||||
|
||||
typedef struct {
|
||||
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||
BYTE pdrv; /* Associated physical drive */
|
||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||
WORD id; /* Volume mount ID */
|
||||
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||
WORD csize; /* Cluster size [sectors] */
|
||||
#if FF_MAX_SS != FF_MIN_SS
|
||||
WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */
|
||||
#endif
|
||||
#if FF_USE_LFN
|
||||
WCHAR* lfnbuf; /* LFN working buffer */
|
||||
#endif
|
||||
#if FF_FS_EXFAT
|
||||
BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */
|
||||
#endif
|
||||
#if FF_FS_REENTRANT
|
||||
FF_SYNC_t sobj; /* Identifier of sync object */
|
||||
#endif
|
||||
#if !FF_FS_READONLY
|
||||
DWORD last_clst; /* Last allocated cluster */
|
||||
DWORD free_clst; /* Number of free clusters */
|
||||
#endif
|
||||
#if FF_FS_RPATH
|
||||
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||
#if FF_FS_EXFAT
|
||||
DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */
|
||||
DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */
|
||||
DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */
|
||||
#endif
|
||||
#endif
|
||||
DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */
|
||||
DWORD fsize; /* Size of an FAT [sectors] */
|
||||
LBA_t volbase; /* Volume base sector */
|
||||
LBA_t fatbase; /* FAT base sector */
|
||||
LBA_t dirbase; /* Root directory base sector/cluster */
|
||||
LBA_t database; /* Data base sector */
|
||||
#if FF_FS_EXFAT
|
||||
LBA_t bitbase; /* Allocation bitmap base sector */
|
||||
#endif
|
||||
LBA_t winsect; /* Current sector appearing in the win[] */
|
||||
BYTE win[FF_MAX_SS] __attribute__((aligned(16))); /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||
} FATFS;
|
||||
|
||||
|
||||
|
||||
/* Object ID and allocation information (FFOBJID) */
|
||||
|
||||
typedef struct {
|
||||
FATFS* fs; /* Pointer to the hosting volume of this object */
|
||||
WORD id; /* Hosting volume mount ID */
|
||||
BYTE attr; /* Object attribute */
|
||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
|
||||
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||
#if FF_FS_EXFAT
|
||||
DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */
|
||||
DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */
|
||||
DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */
|
||||
DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
|
||||
DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */
|
||||
#endif
|
||||
#if FF_FS_LOCK
|
||||
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||
#endif
|
||||
} FFOBJID;
|
||||
|
||||
|
||||
|
||||
/* File object structure (FIL) */
|
||||
|
||||
typedef struct {
|
||||
FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
|
||||
BYTE flag; /* File status flags */
|
||||
BYTE err; /* Abort flag (error code) */
|
||||
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */
|
||||
DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */
|
||||
LBA_t sect; /* Sector number appearing in buf[] (0:invalid) */
|
||||
#if !FF_FS_READONLY
|
||||
LBA_t dir_sect; /* Sector number containing the directory entry (not used at exFAT) */
|
||||
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */
|
||||
#endif
|
||||
#if FF_USE_FASTSEEK
|
||||
DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */
|
||||
#endif
|
||||
#if !FF_FS_TINY
|
||||
BYTE buf[FF_MAX_SS] __attribute__((aligned(16))); /* File private data read/write window */
|
||||
#endif
|
||||
} FIL;
|
||||
|
||||
|
||||
|
||||
/* Directory object structure (DIR) */
|
||||
|
||||
typedef struct {
|
||||
FFOBJID obj; /* Object identifier */
|
||||
DWORD dptr; /* Current read/write offset */
|
||||
DWORD clust; /* Current cluster */
|
||||
LBA_t sect; /* Current sector (0:Read operation has terminated) */
|
||||
BYTE* dir; /* Pointer to the directory item in the win[] */
|
||||
BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */
|
||||
#if FF_USE_LFN
|
||||
DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */
|
||||
#endif
|
||||
#if FF_USE_FIND
|
||||
const TCHAR* pat; /* Pointer to the name matching pattern */
|
||||
#endif
|
||||
} DIR;
|
||||
|
||||
|
||||
|
||||
/* File information structure (FILINFO) */
|
||||
|
||||
typedef struct {
|
||||
FSIZE_t fsize; /* File size */
|
||||
WORD fdate; /* Modified date */
|
||||
WORD ftime; /* Modified time */
|
||||
BYTE fattrib; /* File attribute */
|
||||
#if FF_USE_LFN
|
||||
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
|
||||
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
|
||||
#else
|
||||
TCHAR fname[12 + 1]; /* File name */
|
||||
#endif
|
||||
} FILINFO;
|
||||
|
||||
|
||||
|
||||
/* Format parameter structure (MKFS_PARM) */
|
||||
|
||||
typedef struct {
|
||||
BYTE fmt; /* Format option (FM_FAT, FM_FAT32, FM_EXFAT and FM_SFD) */
|
||||
BYTE n_fat; /* Number of FATs */
|
||||
UINT align; /* Data area alignment (sector) */
|
||||
UINT n_root; /* Number of root directory entries */
|
||||
DWORD au_size; /* Cluster size (byte) */
|
||||
} MKFS_PARM;
|
||||
|
||||
|
||||
|
||||
/* File function return code (FRESULT) */
|
||||
|
||||
typedef enum {
|
||||
FR_OK = 0, /* (0) Succeeded */
|
||||
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
|
||||
FR_INT_ERR, /* (2) Assertion failed */
|
||||
FR_NOT_READY, /* (3) The physical drive cannot work */
|
||||
FR_NO_FILE, /* (4) Could not find the file */
|
||||
FR_NO_PATH, /* (5) Could not find the path */
|
||||
FR_INVALID_NAME, /* (6) The path name format is invalid */
|
||||
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
|
||||
FR_EXIST, /* (8) Access denied due to prohibited access */
|
||||
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
|
||||
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
|
||||
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
||||
FR_NOT_ENABLED, /* (12) The volume has no work area */
|
||||
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
|
||||
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */
|
||||
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
||||
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
|
||||
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
||||
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */
|
||||
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
||||
} FRESULT;
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* FatFs module application interface */
|
||||
|
||||
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
|
||||
FRESULT f_close (FIL* fp); /* Close an open file object */
|
||||
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */
|
||||
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */
|
||||
FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */
|
||||
FRESULT f_truncate (FIL* fp); /* Truncate the file */
|
||||
FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */
|
||||
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
|
||||
FRESULT f_closedir (DIR* dp); /* Close an open directory */
|
||||
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
|
||||
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
|
||||
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
|
||||
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
|
||||
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
|
||||
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
|
||||
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
|
||||
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */
|
||||
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */
|
||||
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
|
||||
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
|
||||
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
|
||||
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
|
||||
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
||||
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
||||
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
||||
FRESULT f_expand (FIL* fp, FSIZE_t fsz, BYTE opt); /* Allocate a contiguous block to the file */
|
||||
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
|
||||
FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void* work, UINT len); /* Create a FAT volume */
|
||||
FRESULT f_fdisk (BYTE pdrv, const LBA_t ptbl[], void* work); /* Divide a physical drive into some partitions */
|
||||
FRESULT f_setcp (WORD cp); /* Set current code page */
|
||||
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
|
||||
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
|
||||
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
|
||||
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
|
||||
|
||||
#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize))
|
||||
#define f_error(fp) ((fp)->err)
|
||||
#define f_tell(fp) ((fp)->fptr)
|
||||
#define f_size(fp) ((fp)->obj.objsize)
|
||||
#define f_rewind(fp) f_lseek((fp), 0)
|
||||
#define f_rewinddir(dp) f_readdir((dp), 0)
|
||||
#define f_rmdir(path) f_unlink(path)
|
||||
#define f_unmount(path) f_mount(0, path, 0)
|
||||
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Additional user defined functions */
|
||||
|
||||
/* RTC function */
|
||||
#if !FF_FS_READONLY && !FF_FS_NORTC
|
||||
DWORD get_fattime (void);
|
||||
#endif
|
||||
|
||||
/* LFN support functions */
|
||||
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
|
||||
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
|
||||
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
|
||||
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
|
||||
#endif
|
||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
||||
void ff_memfree (void* mblock); /* Free memory block */
|
||||
#endif
|
||||
|
||||
/* Sync functions */
|
||||
#if FF_FS_REENTRANT
|
||||
int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */
|
||||
int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */
|
||||
void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */
|
||||
int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/*--------------------------------------------------------------*/
|
||||
/* Flags and offset address */
|
||||
|
||||
|
||||
/* File access mode and open method flags (3rd argument of f_open) */
|
||||
#define FA_READ 0x01
|
||||
#define FA_WRITE 0x02
|
||||
#define FA_OPEN_EXISTING 0x00
|
||||
#define FA_CREATE_NEW 0x04
|
||||
#define FA_CREATE_ALWAYS 0x08
|
||||
#define FA_OPEN_ALWAYS 0x10
|
||||
#define FA_OPEN_APPEND 0x30
|
||||
|
||||
/* Fast seek controls (2nd argument of f_lseek) */
|
||||
#define CREATE_LINKMAP ((FSIZE_t)0 - 1)
|
||||
|
||||
/* Format options (2nd argument of f_mkfs) */
|
||||
#define FM_FAT 0x01
|
||||
#define FM_FAT32 0x02
|
||||
#define FM_EXFAT 0x04
|
||||
#define FM_ANY 0x07
|
||||
#define FM_SFD 0x08
|
||||
|
||||
/* Filesystem type (FATFS.fs_type) */
|
||||
#define FS_FAT12 1
|
||||
#define FS_FAT16 2
|
||||
#define FS_FAT32 3
|
||||
#define FS_EXFAT 4
|
||||
|
||||
/* File attribute bits for directory entry (FILINFO.fattrib) */
|
||||
#define AM_RDO 0x01 /* Read only */
|
||||
#define AM_HID 0x02 /* Hidden */
|
||||
#define AM_SYS 0x04 /* System */
|
||||
#define AM_DIR 0x10 /* Directory */
|
||||
#define AM_ARC 0x20 /* Archive */
|
||||
|
||||
#include "ff_extensions.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FF_DEFINED */
|
82
sw/bootloader/src/fatfs/ff_extensions.c.inc
Normal file
82
sw/bootloader/src/fatfs/ff_extensions.c.inc
Normal file
@ -0,0 +1,82 @@
|
||||
FRESULT fe_load(const TCHAR *path, UINT max_length, transfer_function_t transfer_function) {
|
||||
FRESULT fresult;
|
||||
FATFS *fs;
|
||||
FIL fil;
|
||||
UINT bytes_to_read;
|
||||
|
||||
FIL *fp = &fil;
|
||||
|
||||
UINT cluster_sector;
|
||||
DWORD cluster;
|
||||
LBA_t starting_sector;
|
||||
UINT sector_count;
|
||||
UINT bytes_processed;
|
||||
|
||||
|
||||
if ((fresult = f_open(fp, path, FA_READ)) != FR_OK) {
|
||||
return fresult;
|
||||
}
|
||||
|
||||
fresult = validate(&fp->obj, &fs);
|
||||
if (fresult != FR_OK || (fresult = (FRESULT) fp->err) != FR_OK) {
|
||||
LEAVE_FF(fs, fresult);
|
||||
}
|
||||
|
||||
bytes_to_read = (fp->obj.objsize > max_length) ? max_length : fp->obj.objsize;
|
||||
bytes_to_read += ((bytes_to_read % SS(fs)) != 0) ? (SS(fs) - (bytes_to_read % SS(fs))) : 0;
|
||||
|
||||
while (bytes_to_read) {
|
||||
cluster_sector = (UINT) (fp->fptr / SS(fs) & (fs->csize - 1));
|
||||
|
||||
if (cluster_sector == 0) {
|
||||
if (fp->fptr == 0) {
|
||||
cluster = fp->obj.sclust;
|
||||
} else {
|
||||
#if FF_USE_FASTSEEK
|
||||
if (fp->cltbl) {
|
||||
cluster = clmt_clust(fp, fp->fptr);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
cluster = get_fat(&fp->obj, fp->clust);
|
||||
}
|
||||
}
|
||||
|
||||
if (cluster < 2) {
|
||||
LEAVE_FF(fs, FR_INT_ERR);
|
||||
}
|
||||
|
||||
if (cluster == 0xFFFFFFFF) {
|
||||
LEAVE_FF(fs, FR_DISK_ERR);
|
||||
}
|
||||
|
||||
fp->clust = cluster;
|
||||
}
|
||||
|
||||
starting_sector = clst2sect(fs, fp->clust);
|
||||
|
||||
if (starting_sector == 0) {
|
||||
LEAVE_FF(fs, FR_INT_ERR);
|
||||
}
|
||||
|
||||
starting_sector += cluster_sector;
|
||||
|
||||
sector_count = bytes_to_read / SS(fs);
|
||||
|
||||
if (cluster_sector + sector_count > fs->csize) {
|
||||
sector_count = fs->csize - cluster_sector;
|
||||
}
|
||||
|
||||
if (transfer_function(fs->pdrv, fp->fptr, starting_sector, sector_count) != RES_OK) {
|
||||
LEAVE_FF(fs, FR_DISK_ERR);
|
||||
}
|
||||
|
||||
fp->sect = starting_sector;
|
||||
|
||||
bytes_processed = sector_count * SS(fs);
|
||||
fp->fptr += bytes_processed;
|
||||
bytes_to_read -= bytes_processed;
|
||||
}
|
||||
|
||||
LEAVE_FF(fs, FR_OK);
|
||||
}
|
14
sw/bootloader/src/fatfs/ff_extensions.h
Normal file
14
sw/bootloader/src/fatfs/ff_extensions.h
Normal file
@ -0,0 +1,14 @@
|
||||
#ifndef FF_EXTENSIONS_H__
|
||||
#define FF_EXTENSIONS_H__
|
||||
|
||||
|
||||
#include "diskio.h"
|
||||
|
||||
|
||||
typedef DRESULT (*transfer_function_t)(BYTE, FSIZE_t, LBA_t, UINT);
|
||||
|
||||
|
||||
FRESULT fe_load(const TCHAR *path, UINT max_length, transfer_function_t transfer_function);
|
||||
|
||||
|
||||
#endif
|
298
sw/bootloader/src/fatfs/ffconf.h
Normal file
298
sw/bootloader/src/fatfs/ffconf.h
Normal file
@ -0,0 +1,298 @@
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ FatFs Functional Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FFCONF_DEF 80196 /* Revision ID */
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Function Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_FS_READONLY 1
|
||||
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
||||
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
|
||||
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
|
||||
/ and optional writing functions as well. */
|
||||
|
||||
|
||||
#define FF_FS_MINIMIZE 3
|
||||
/* This option defines minimization level to remove some basic API functions.
|
||||
/
|
||||
/ 0: Basic functions are fully enabled.
|
||||
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
|
||||
/ are removed.
|
||||
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
|
||||
/ 3: f_lseek() function is removed in addition to 2. */
|
||||
|
||||
|
||||
#define FF_USE_STRFUNC 0
|
||||
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
|
||||
/
|
||||
/ 0: Disable string functions.
|
||||
/ 1: Enable without LF-CRLF conversion.
|
||||
/ 2: Enable with LF-CRLF conversion. */
|
||||
|
||||
|
||||
#define FF_USE_FIND 0
|
||||
/* This option switches filtered directory read functions, f_findfirst() and
|
||||
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
||||
|
||||
|
||||
#define FF_USE_MKFS 0
|
||||
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_FASTSEEK 0
|
||||
/* This option switches fast seek function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_EXPAND 0
|
||||
/* This option switches f_expand function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_CHMOD 0
|
||||
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
|
||||
/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */
|
||||
|
||||
|
||||
#define FF_USE_LABEL 0
|
||||
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||
/ (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
#define FF_USE_FORWARD 0
|
||||
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Locale and Namespace Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_CODE_PAGE 437
|
||||
/* This option specifies the OEM code page to be used on the target system.
|
||||
/ Incorrect code page setting can cause a file open failure.
|
||||
/
|
||||
/ 437 - U.S.
|
||||
/ 720 - Arabic
|
||||
/ 737 - Greek
|
||||
/ 771 - KBL
|
||||
/ 775 - Baltic
|
||||
/ 850 - Latin 1
|
||||
/ 852 - Latin 2
|
||||
/ 855 - Cyrillic
|
||||
/ 857 - Turkish
|
||||
/ 860 - Portuguese
|
||||
/ 861 - Icelandic
|
||||
/ 862 - Hebrew
|
||||
/ 863 - Canadian French
|
||||
/ 864 - Arabic
|
||||
/ 865 - Nordic
|
||||
/ 866 - Russian
|
||||
/ 869 - Greek 2
|
||||
/ 932 - Japanese (DBCS)
|
||||
/ 936 - Simplified Chinese (DBCS)
|
||||
/ 949 - Korean (DBCS)
|
||||
/ 950 - Traditional Chinese (DBCS)
|
||||
/ 0 - Include all code pages above and configured by f_setcp()
|
||||
*/
|
||||
|
||||
|
||||
#define FF_USE_LFN 2
|
||||
#define FF_MAX_LFN 255
|
||||
/* The FF_USE_LFN switches the support for LFN (long file name).
|
||||
/
|
||||
/ 0: Disable LFN. FF_MAX_LFN has no effect.
|
||||
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
|
||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||
/
|
||||
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
|
||||
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
|
||||
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
|
||||
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
|
||||
/ be in range of 12 to 255. It is recommended to be set it 255 to fully support LFN
|
||||
/ specification.
|
||||
/ When use stack for the working buffer, take care on stack overflow. When use heap
|
||||
/ memory for the working buffer, memory management functions, ff_memalloc() and
|
||||
/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */
|
||||
|
||||
|
||||
#define FF_LFN_UNICODE 0
|
||||
/* This option switches the character encoding on the API when LFN is enabled.
|
||||
/
|
||||
/ 0: ANSI/OEM in current CP (TCHAR = char)
|
||||
/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
|
||||
/ 2: Unicode in UTF-8 (TCHAR = char)
|
||||
/ 3: Unicode in UTF-32 (TCHAR = DWORD)
|
||||
/
|
||||
/ Also behavior of string I/O functions will be affected by this option.
|
||||
/ When LFN is not enabled, this option has no effect. */
|
||||
|
||||
|
||||
#define FF_LFN_BUF 255
|
||||
#define FF_SFN_BUF 12
|
||||
/* This set of options defines size of file name members in the FILINFO structure
|
||||
/ which is used to read out directory items. These values should be suffcient for
|
||||
/ the file names to read. The maximum possible length of the read file name depends
|
||||
/ on character encoding. When LFN is not enabled, these options have no effect. */
|
||||
|
||||
|
||||
#define FF_STRF_ENCODE 3
|
||||
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
|
||||
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
|
||||
/ This option selects assumption of character encoding ON THE FILE to be
|
||||
/ read/written via those functions.
|
||||
/
|
||||
/ 0: ANSI/OEM in current CP
|
||||
/ 1: Unicode in UTF-16LE
|
||||
/ 2: Unicode in UTF-16BE
|
||||
/ 3: Unicode in UTF-8
|
||||
*/
|
||||
|
||||
|
||||
#define FF_FS_RPATH 0
|
||||
/* This option configures support for relative path.
|
||||
/
|
||||
/ 0: Disable relative path and remove related functions.
|
||||
/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
|
||||
/ 2: f_getcwd() function is available in addition to 1.
|
||||
*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ Drive/Volume Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_VOLUMES 1
|
||||
/* Number of volumes (logical drives) to be used. (1-10) */
|
||||
|
||||
|
||||
#define FF_STR_VOLUME_ID 0
|
||||
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
|
||||
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
||||
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
||||
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
||||
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
|
||||
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
|
||||
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
|
||||
/ not defined, a user defined volume string table needs to be defined as:
|
||||
/
|
||||
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
|
||||
*/
|
||||
|
||||
|
||||
#define FF_MULTI_PARTITION 0
|
||||
/* This option switches support for multiple volumes on the physical drive.
|
||||
/ By default (0), each logical drive number is bound to the same physical drive
|
||||
/ number and only an FAT volume found on the physical drive will be mounted.
|
||||
/ When this function is enabled (1), each logical drive number can be bound to
|
||||
/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
|
||||
/ funciton will be available. */
|
||||
|
||||
|
||||
#define FF_MIN_SS 512
|
||||
#define FF_MAX_SS 512
|
||||
/* This set of options configures the range of sector size to be supported. (512,
|
||||
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
|
||||
/ harddisk. But a larger value may be required for on-board flash memory and some
|
||||
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
|
||||
/ for variable sector size mode and disk_ioctl() function needs to implement
|
||||
/ GET_SECTOR_SIZE command. */
|
||||
|
||||
|
||||
#define FF_LBA64 1
|
||||
/* This option switches support for 64-bit LBA. (0:Disable or 1:Enable)
|
||||
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
|
||||
|
||||
|
||||
#define FF_MIN_GPT 0x10000000
|
||||
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
|
||||
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
|
||||
|
||||
|
||||
#define FF_USE_TRIM 0
|
||||
/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable)
|
||||
/ To enable Trim function, also CTRL_TRIM command should be implemented to the
|
||||
/ disk_ioctl() function. */
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------/
|
||||
/ System Configurations
|
||||
/---------------------------------------------------------------------------*/
|
||||
|
||||
#define FF_FS_TINY 0
|
||||
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
||||
/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes.
|
||||
/ Instead of private sector buffer eliminated from the file object, common sector
|
||||
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
|
||||
|
||||
|
||||
#define FF_FS_EXFAT 1
|
||||
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
||||
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
|
||||
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
||||
|
||||
|
||||
#define FF_FS_NORTC 1
|
||||
#define FF_NORTC_MON 1
|
||||
#define FF_NORTC_MDAY 1
|
||||
#define FF_NORTC_YEAR 2020
|
||||
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
|
||||
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
|
||||
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
|
||||
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
|
||||
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
|
||||
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
|
||||
/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect.
|
||||
/ These options have no effect in read-only configuration (FF_FS_READONLY = 1). */
|
||||
|
||||
|
||||
#define FF_FS_NOFSINFO 0
|
||||
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
||||
/ option, and f_getfree() function at first time after volume mount will force
|
||||
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
||||
/
|
||||
/ bit0=0: Use free cluster count in the FSINFO if available.
|
||||
/ bit0=1: Do not trust free cluster count in the FSINFO.
|
||||
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
|
||||
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
|
||||
*/
|
||||
|
||||
|
||||
#define FF_FS_LOCK 0
|
||||
/* The option FF_FS_LOCK switches file lock function to control duplicated file open
|
||||
/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY
|
||||
/ is 1.
|
||||
/
|
||||
/ 0: Disable file lock function. To avoid volume corruption, application program
|
||||
/ should avoid illegal open, remove and rename to the open objects.
|
||||
/ >0: Enable file lock function. The value defines how many files/sub-directories
|
||||
/ can be opened simultaneously under file lock control. Note that the file
|
||||
/ lock control is independent of re-entrancy. */
|
||||
|
||||
|
||||
/* #include <somertos.h> // O/S definitions */
|
||||
#define FF_FS_REENTRANT 0
|
||||
#define FF_FS_TIMEOUT 1000
|
||||
#define FF_SYNC_t HANDLE
|
||||
/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
|
||||
/ module itself. Note that regardless of this option, file access to different
|
||||
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
||||
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
|
||||
/ to the same volume is under control of this function.
|
||||
/
|
||||
/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect.
|
||||
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
||||
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
|
||||
/ function, must be added to the project. Samples are available in
|
||||
/ option/syscall.c.
|
||||
/
|
||||
/ The FF_FS_TIMEOUT defines timeout period in unit of time tick.
|
||||
/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
|
||||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
||||
/ included somewhere in the scope of ff.h. */
|
||||
|
||||
|
||||
|
||||
/*--- End of configuration options ---*/
|
170
sw/bootloader/src/fatfs/ffsystem.c
Normal file
170
sw/bootloader/src/fatfs/ffsystem.c
Normal file
@ -0,0 +1,170 @@
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Sample Code of OS Dependent Functions for FatFs */
|
||||
/* (C)ChaN, 2018 */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "ff.h"
|
||||
|
||||
|
||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Allocate a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
|
||||
UINT msize /* Number of bytes to allocate */
|
||||
)
|
||||
{
|
||||
return malloc(msize); /* Allocate a new memory block with POSIX API */
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Free a memory block */
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void ff_memfree (
|
||||
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
|
||||
)
|
||||
{
|
||||
free(mblock); /* Free the memory block with POSIX API */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if FF_FS_REENTRANT /* Mutal exclusion */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Create a Synchronization Object */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called in f_mount() function to create a new
|
||||
/ synchronization object for the volume, such as semaphore and mutex.
|
||||
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
|
||||
*/
|
||||
|
||||
//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
|
||||
|
||||
|
||||
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
|
||||
BYTE vol, /* Corresponding volume (logical drive number) */
|
||||
FF_SYNC_t* sobj /* Pointer to return the created sync object */
|
||||
)
|
||||
{
|
||||
/* Win32 */
|
||||
*sobj = CreateMutex(NULL, FALSE, NULL);
|
||||
return (int)(*sobj != INVALID_HANDLE_VALUE);
|
||||
|
||||
/* uITRON */
|
||||
// T_CSEM csem = {TA_TPRI,1,1};
|
||||
// *sobj = acre_sem(&csem);
|
||||
// return (int)(*sobj > 0);
|
||||
|
||||
/* uC/OS-II */
|
||||
// OS_ERR err;
|
||||
// *sobj = OSMutexCreate(0, &err);
|
||||
// return (int)(err == OS_NO_ERR);
|
||||
|
||||
/* FreeRTOS */
|
||||
// *sobj = xSemaphoreCreateMutex();
|
||||
// return (int)(*sobj != NULL);
|
||||
|
||||
/* CMSIS-RTOS */
|
||||
// *sobj = osMutexCreate(&Mutex[vol]);
|
||||
// return (int)(*sobj != NULL);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Delete a Synchronization Object */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called in f_mount() function to delete a synchronization
|
||||
/ object that created with ff_cre_syncobj() function. When a 0 is returned,
|
||||
/ the f_mount() function fails with FR_INT_ERR.
|
||||
*/
|
||||
|
||||
int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */
|
||||
FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
|
||||
)
|
||||
{
|
||||
/* Win32 */
|
||||
return (int)CloseHandle(sobj);
|
||||
|
||||
/* uITRON */
|
||||
// return (int)(del_sem(sobj) == E_OK);
|
||||
|
||||
/* uC/OS-II */
|
||||
// OS_ERR err;
|
||||
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err);
|
||||
// return (int)(err == OS_NO_ERR);
|
||||
|
||||
/* FreeRTOS */
|
||||
// vSemaphoreDelete(sobj);
|
||||
// return 1;
|
||||
|
||||
/* CMSIS-RTOS */
|
||||
// return (int)(osMutexDelete(sobj) == osOK);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Request Grant to Access the Volume */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called on entering file functions to lock the volume.
|
||||
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
|
||||
*/
|
||||
|
||||
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
|
||||
FF_SYNC_t sobj /* Sync object to wait */
|
||||
)
|
||||
{
|
||||
/* Win32 */
|
||||
return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0);
|
||||
|
||||
/* uITRON */
|
||||
// return (int)(wai_sem(sobj) == E_OK);
|
||||
|
||||
/* uC/OS-II */
|
||||
// OS_ERR err;
|
||||
// OSMutexPend(sobj, FF_FS_TIMEOUT, &err));
|
||||
// return (int)(err == OS_NO_ERR);
|
||||
|
||||
/* FreeRTOS */
|
||||
// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE);
|
||||
|
||||
/* CMSIS-RTOS */
|
||||
// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* Release Grant to Access the Volume */
|
||||
/*------------------------------------------------------------------------*/
|
||||
/* This function is called on leaving file functions to unlock the volume.
|
||||
*/
|
||||
|
||||
void ff_rel_grant (
|
||||
FF_SYNC_t sobj /* Sync object to be signaled */
|
||||
)
|
||||
{
|
||||
/* Win32 */
|
||||
ReleaseMutex(sobj);
|
||||
|
||||
/* uITRON */
|
||||
// sig_sem(sobj);
|
||||
|
||||
/* uC/OS-II */
|
||||
// OSMutexPost(sobj);
|
||||
|
||||
/* FreeRTOS */
|
||||
// xSemaphoreGive(sobj);
|
||||
|
||||
/* CMSIS-RTOS */
|
||||
// osMutexRelease(sobj);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
15593
sw/bootloader/src/fatfs/ffunicode.c
Normal file
15593
sw/bootloader/src/fatfs/ffunicode.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,30 +1,74 @@
|
||||
#include <libdragon.h>
|
||||
|
||||
#include "boot.h"
|
||||
#include "error_display.h"
|
||||
|
||||
#include "sc64.h"
|
||||
#include "sc64_sd_fs.h"
|
||||
|
||||
|
||||
static const char *MENU_FILE_PATH = "SC64/MENU.z64";
|
||||
|
||||
|
||||
int main(void) {
|
||||
init_interrupts();
|
||||
if (sc64_get_version() != SC64_CART_VERSION_A) {
|
||||
error_display_and_halt(E_MENU_ERROR_NOT_SC64, MENU_FILE_PATH);
|
||||
}
|
||||
|
||||
sc64_enable_sdram();
|
||||
sc64_enable_rom_switch();
|
||||
|
||||
cic_type_t cic_type = sc64_get_cic_type();
|
||||
tv_type_t tv_type = sc64_get_tv_type();
|
||||
uint32_t boot_mode = sc64_get_boot_mode();
|
||||
|
||||
cart_header_t *cart_header = boot_load_cart_header();
|
||||
uint32_t skip_menu = (boot_mode & SC64_CART_BOOT_SKIP_MENU);
|
||||
uint32_t cic_seed_override = (boot_mode & SC64_CART_BOOT_CIC_SEED_OVERRIDE);
|
||||
uint32_t tv_type_override = (boot_mode & SC64_CART_BOOT_TV_TYPE_OVERRIDE);
|
||||
uint32_t ddipl_override = (boot_mode & SC64_CART_BOOT_DDIPL_OVERRIDE);
|
||||
tv_type_t tv_type = ((boot_mode & SC64_CART_BOOT_TV_TYPE_MASK) >> SC64_CART_BOOT_TV_TYPE_BIT);
|
||||
uint16_t cic_seed = ((boot_mode & SC64_CART_BOOT_CIC_SEED_MASK) >> SC64_CART_BOOT_CIC_SEED_BIT);
|
||||
|
||||
// Try to guess CIC and TV type from ROM in SDRAM if no override is provided
|
||||
if (cic_type == E_CIC_TYPE_UNKNOWN || tv_type == E_TV_TYPE_UNKNOWN) {
|
||||
if (cic_type == E_CIC_TYPE_UNKNOWN) {
|
||||
cic_type = boot_get_cic_type(cart_header);
|
||||
if (!skip_menu) {
|
||||
sc64_sd_fs_error_t sd_error = sc64_sd_fs_load_rom(MENU_FILE_PATH);
|
||||
|
||||
menu_load_error_t error = E_MENU_OK;
|
||||
|
||||
switch (sd_error) {
|
||||
case SC64_SD_FS_NO_CARD:
|
||||
error = E_MENU_ERROR_NO_CARD;
|
||||
break;
|
||||
case SC64_SD_FS_NO_FILESYSTEM:
|
||||
error = E_MENU_ERROR_NO_FILESYSTEM;
|
||||
break;
|
||||
case SC64_SD_FS_NO_FILE:
|
||||
error = E_MENU_ERROR_NO_FILE;
|
||||
break;
|
||||
case SC64_SD_FS_READ_ERROR:
|
||||
error = E_MENU_ERROR_READ_ERROR;
|
||||
break;
|
||||
case SC64_SD_FS_OTHER_ERROR:
|
||||
error = E_MENU_ERROR_OTHER_ERROR;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (tv_type == E_TV_TYPE_UNKNOWN) {
|
||||
tv_type = boot_get_tv_type(cart_header);
|
||||
if (error != E_MENU_OK) {
|
||||
error_display_and_halt(error, MENU_FILE_PATH);
|
||||
}
|
||||
}
|
||||
|
||||
disable_interrupts();
|
||||
if (ddipl_override) {
|
||||
sc64_enable_ddipl();
|
||||
} else {
|
||||
sc64_disable_ddipl();
|
||||
}
|
||||
|
||||
boot(cart_header, cic_type, tv_type);
|
||||
cart_header_t *cart_header = boot_load_cart_header();
|
||||
|
||||
if (!cic_seed_override) {
|
||||
cic_seed = boot_get_cic_seed(cart_header);
|
||||
}
|
||||
|
||||
if (!tv_type_override) {
|
||||
tv_type = boot_get_tv_type(cart_header);
|
||||
}
|
||||
|
||||
boot(cart_header, cic_seed, tv_type, ddipl_override);
|
||||
}
|
||||
|
30
sw/bootloader/src/platform.h
Normal file
30
sw/bootloader/src/platform.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef PLATFORM_H__
|
||||
#define PLATFORM_H__
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libdragon.h>
|
||||
|
||||
|
||||
#define BOOTLOADER_VERSION_MAJOR (1)
|
||||
#define BOOTLOADER_VERSION_MINOR (0)
|
||||
|
||||
|
||||
#define TRUE (1)
|
||||
#define FALSE (0)
|
||||
|
||||
#define __IO volatile
|
||||
|
||||
typedef uint32_t reg_t;
|
||||
|
||||
#define platform_cache_writeback(rdram, length) data_cache_hit_writeback_invalidate(rdram, length)
|
||||
#define platform_cache_invalidate(rdram, length) data_cache_hit_invalidate(rdram, length)
|
||||
#define platform_pi_io_write(pi, value) io_write((uint32_t) (pi), value)
|
||||
#define platform_pi_io_read(pi) io_read((uint32_t) (pi))
|
||||
#define platform_pi_dma_write(rdram, pi, length) dma_write(rdram, (uint32_t) (pi), length)
|
||||
#define platform_pi_dma_read(rdram, pi, length) dma_read(rdram, (uint32_t) (pi), length)
|
||||
|
||||
|
||||
#endif
|
@ -1,47 +0,0 @@
|
||||
#include <libdragon.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "sc64.h"
|
||||
#include "sc64_regs.h"
|
||||
|
||||
static void sc64_enable_peripheral(uint32_t mask) {
|
||||
uint32_t config = io_read(SC64_CONFIG_REG);
|
||||
|
||||
config |= mask;
|
||||
|
||||
io_write(SC64_CONFIG_REG, config);
|
||||
}
|
||||
|
||||
static void sc64_disable_peripheral(uint32_t mask) {
|
||||
uint32_t config = io_read(SC64_CONFIG_REG);
|
||||
|
||||
config &= ~mask;
|
||||
|
||||
io_write(SC64_CONFIG_REG, config);
|
||||
}
|
||||
|
||||
void sc64_enable_sdram(void) {
|
||||
sc64_enable_peripheral(SC64_CONFIG_SDRAM_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_disable_sdram(void) {
|
||||
sc64_disable_peripheral(SC64_CONFIG_SDRAM_ENABLE);
|
||||
}
|
||||
|
||||
cic_type_t sc64_get_cic_type(void) {
|
||||
uint32_t boot = io_read(SC64_BOOT_REG);
|
||||
|
||||
cic_type_t cic_type = (cic_type_t)(SC64_BOOT_CIC_TYPE(boot));
|
||||
|
||||
return (cic_type >= E_CIC_TYPE_END) ? E_CIC_TYPE_UNKNOWN : cic_type;
|
||||
}
|
||||
|
||||
tv_type_t sc64_get_tv_type(void) {
|
||||
uint32_t boot = io_read(SC64_BOOT_REG);
|
||||
|
||||
if ((SC64_BOOT_CIC_TYPE(boot) == E_CIC_TYPE_UNKNOWN) || (SC64_BOOT_CIC_TYPE(boot) >= E_CIC_TYPE_END)) {
|
||||
return E_TV_TYPE_UNKNOWN;
|
||||
} else {
|
||||
return (tv_type_t)(SC64_BOOT_TV_TYPE(boot));
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
#ifndef SC64_H__
|
||||
#define SC64_H__
|
||||
|
||||
#include "boot.h"
|
||||
|
||||
void sc64_enable_sdram(void);
|
||||
void sc64_disable_sdram(void);
|
||||
cic_type_t sc64_get_cic_type(void);
|
||||
tv_type_t sc64_get_tv_type(void);
|
||||
|
||||
#endif
|
128
sw/bootloader/src/sc64/sc64.c
Normal file
128
sw/bootloader/src/sc64/sc64.c
Normal file
@ -0,0 +1,128 @@
|
||||
#include "sc64.h"
|
||||
|
||||
|
||||
static void sc64_enable_peripheral(uint32_t mask) {
|
||||
uint32_t config = platform_pi_io_read(&SC64_CART->scr);
|
||||
|
||||
config |= mask;
|
||||
|
||||
platform_pi_io_write(&SC64_CART->scr, config);
|
||||
}
|
||||
|
||||
static void sc64_disable_peripheral(uint32_t mask) {
|
||||
uint32_t config = platform_pi_io_read(&SC64_CART->scr);
|
||||
|
||||
config &= ~mask;
|
||||
|
||||
platform_pi_io_write(&SC64_CART->scr, config);
|
||||
}
|
||||
|
||||
uint32_t sc64_get_scr(void) {
|
||||
return platform_pi_io_read(&SC64_CART->scr);
|
||||
}
|
||||
|
||||
void sc64_set_scr(uint32_t scr) {
|
||||
platform_pi_io_write(&SC64_CART->scr, scr);
|
||||
}
|
||||
|
||||
void sc64_enable_flashram(void) {
|
||||
sc64_enable_peripheral(SC64_CART_SCR_FLASHRAM_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_disable_flashram(void) {
|
||||
sc64_disable_peripheral(SC64_CART_SCR_FLASHRAM_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_enable_sram(uint8_t mode_768k) {
|
||||
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) {
|
||||
sc64_disable_peripheral(SC64_CART_SCR_SRAM_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_enable_sd(void) {
|
||||
sc64_enable_peripheral(SC64_CART_SCR_SD_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_disable_sd(void) {
|
||||
sc64_disable_peripheral(SC64_CART_SCR_SD_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_enable_eeprom_pi(void) {
|
||||
sc64_enable_peripheral(SC64_CART_SCR_EEPROM_PI_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_disable_eeprom_pi(void) {
|
||||
sc64_disable_peripheral(SC64_CART_SCR_EEPROM_PI_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_enable_eeprom(uint8_t mode_16k) {
|
||||
sc64_enable_peripheral(SC64_CART_SCR_EEPROM_ENABLE);
|
||||
if (mode_16k) {
|
||||
sc64_enable_peripheral(SC64_CART_SCR_EEPROM_16K_MODE);
|
||||
} else {
|
||||
sc64_disable_peripheral(SC64_CART_SCR_EEPROM_16K_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
void sc64_disable_eeprom(void) {
|
||||
sc64_disable_peripheral(SC64_CART_SCR_EEPROM_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_enable_ddipl(void) {
|
||||
sc64_enable_peripheral(SC64_CART_SCR_DDIPL_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_disable_ddipl(void) {
|
||||
sc64_disable_peripheral(SC64_CART_SCR_DDIPL_ENABLE);
|
||||
}
|
||||
|
||||
void sc64_enable_rom_switch(void) {
|
||||
sc64_enable_peripheral(SC64_CART_SCR_ROM_SWITCH);
|
||||
}
|
||||
|
||||
void sc64_disable_rom_switch(void) {
|
||||
sc64_disable_peripheral(SC64_CART_SCR_ROM_SWITCH);
|
||||
}
|
||||
|
||||
void sc64_enable_sdram_writable(void) {
|
||||
sc64_enable_peripheral(SC64_CART_SCR_SDRAM_WRITABLE);
|
||||
}
|
||||
|
||||
void sc64_disable_sdram_writable(void) {
|
||||
sc64_disable_peripheral(SC64_CART_SCR_SDRAM_WRITABLE);
|
||||
}
|
||||
|
||||
uint32_t sc64_get_boot_mode(void) {
|
||||
return platform_pi_io_read(&SC64_CART->boot);
|
||||
}
|
||||
|
||||
void sc64_set_boot_mode(uint32_t boot) {
|
||||
platform_pi_io_write(&SC64_CART->boot, boot);
|
||||
}
|
||||
|
||||
uint32_t sc64_get_version(void) {
|
||||
return platform_pi_io_read(&SC64_CART->version);
|
||||
}
|
||||
|
||||
uint32_t sc64_get_ddipl_address(void) {
|
||||
return platform_pi_io_read(&SC64_CART->ddipl_addr) & SC64_CART_DDIPL_ADDR_ADDRESS_MASK;
|
||||
}
|
||||
|
||||
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) {
|
||||
return platform_pi_io_read(&SC64_CART->sram_addr) & SC64_CART_SRAM_ADDR_ADDRESS_MASK;
|
||||
}
|
||||
|
||||
void sc64_set_sram_address(uint32_t address) {
|
||||
platform_pi_io_write(&SC64_CART->sram_addr, address & SC64_CART_SRAM_ADDR_ADDRESS_MASK);
|
||||
}
|
38
sw/bootloader/src/sc64/sc64.h
Normal file
38
sw/bootloader/src/sc64/sc64.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef SC64_H__
|
||||
#define SC64_H__
|
||||
|
||||
|
||||
#include "sc64_regs.h"
|
||||
|
||||
|
||||
#define SC64_SDRAM_SIZE (64 * 1024 * 1024)
|
||||
|
||||
|
||||
uint32_t sc64_get_scr(void);
|
||||
void sc64_set_scr(uint32_t scr);
|
||||
void sc64_enable_flashram(void);
|
||||
void sc64_disable_flashram(void);
|
||||
void sc64_enable_sram(uint8_t mode_768k);
|
||||
void sc64_disable_sram(void);
|
||||
void sc64_enable_sd(void);
|
||||
void sc64_disable_sd(void);
|
||||
void sc64_enable_eeprom_pi(void);
|
||||
void sc64_disable_eeprom_pi(void);
|
||||
void sc64_enable_eeprom(uint8_t mode_16k);
|
||||
void sc64_disable_eeprom(void);
|
||||
void sc64_enable_ddipl(void);
|
||||
void sc64_disable_ddipl(void);
|
||||
void sc64_enable_rom_switch(void);
|
||||
void sc64_disable_rom_switch(void);
|
||||
void sc64_enable_sdram_writable(void);
|
||||
void sc64_disable_sdram_writable(void);
|
||||
uint32_t sc64_get_boot_mode(void);
|
||||
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);
|
||||
|
||||
|
||||
#endif
|
163
sw/bootloader/src/sc64/sc64_regs.h
Normal file
163
sw/bootloader/src/sc64/sc64_regs.h
Normal file
@ -0,0 +1,163 @@
|
||||
#ifndef SC64_REGS_H__
|
||||
#define SC64_REGS_H__
|
||||
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
// Bank definitions
|
||||
|
||||
#define SC64_BANK_INVALID (0)
|
||||
#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)
|
||||
|
||||
|
||||
// Cart Interface Registers
|
||||
|
||||
typedef struct sc64_cart_registers {
|
||||
__IO reg_t scr; // Cart status and config
|
||||
__IO reg_t boot; // Boot behavior override
|
||||
__IO reg_t version; // Cart firmware version
|
||||
__IO reg_t gpio; // Fixed I/O control
|
||||
__IO reg_t usb_scr; // USB interface status and control
|
||||
__IO reg_t usb_dma_addr; // USB bank and address for DMA to PC
|
||||
__IO reg_t usb_dma_len; // USB transfer length for DMA to PC
|
||||
__IO reg_t ddipl_addr; // 64 Disk Drive IPL location in SDRAM
|
||||
__IO reg_t sram_addr; // SRAM save emulation location in SDRAM
|
||||
__IO reg_t __reserved[1015];
|
||||
__IO reg_t usb_fifo[1024]; // USB data from PC read FIFO memory end
|
||||
} sc64_cart_registers_t;
|
||||
|
||||
#define SC64_CART_BASE (0x1E000000)
|
||||
|
||||
#define SC64_CART ((__IO sc64_cart_registers_t *) SC64_CART_BASE)
|
||||
|
||||
#define SC64_CART_SCR_FLASHRAM_ENABLE (1 << 9)
|
||||
#define SC64_CART_SCR_SRAM_768K_MODE (1 << 8)
|
||||
#define SC64_CART_SCR_SRAM_ENABLE (1 << 7)
|
||||
#define SC64_CART_SCR_SD_ENABLE (1 << 6)
|
||||
#define SC64_CART_SCR_EEPROM_PI_ENABLE (1 << 5)
|
||||
#define SC64_CART_SCR_EEPROM_16K_MODE (1 << 4)
|
||||
#define SC64_CART_SCR_EEPROM_ENABLE (1 << 3)
|
||||
#define SC64_CART_SCR_DDIPL_ENABLE (1 << 2)
|
||||
#define SC64_CART_SCR_ROM_SWITCH (1 << 1)
|
||||
#define SC64_CART_SCR_SDRAM_WRITABLE (1 << 0)
|
||||
|
||||
#define SC64_CART_BOOT_SKIP_MENU (1 << 15)
|
||||
#define SC64_CART_BOOT_CIC_SEED_OVERRIDE (1 << 14)
|
||||
#define SC64_CART_BOOT_TV_TYPE_OVERRIDE (1 << 13)
|
||||
#define SC64_CART_BOOT_DDIPL_OVERRIDE (1 << 12)
|
||||
#define SC64_CART_BOOT_TV_TYPE_BIT (10)
|
||||
#define SC64_CART_BOOT_TV_TYPE_MASK (0x3 << SC64_CART_BOOT_TV_TYPE_BIT)
|
||||
#define SC64_CART_BOOT_CIC_SEED_BIT (0)
|
||||
#define SC64_CART_BOOT_CIC_SEED_MASK (0x1FF << SC64_CART_BOOT_CIC_SEED_BIT)
|
||||
|
||||
#define SC64_CART_VERSION_A (0x53363461)
|
||||
|
||||
#define SC64_CART_GPIO_RESET_BUTTON (1 << 0)
|
||||
|
||||
#define SC64_CART_USB_SCR_FIFO_ITEMS_BIT (3)
|
||||
#define SC64_CART_USB_SCR_FIFO_ITEMS_MASK (0x7FF << SC64_CART_USB_SCR_FIFO_ITEMS_BIT)
|
||||
#define SC64_CART_USB_SCR_READY (1 << 1)
|
||||
#define SC64_CART_USB_SCR_DMA_BUSY (1 << 0)
|
||||
#define SC64_CART_USB_SCR_FIFO_FLUSH (1 << 2)
|
||||
#define SC64_CART_USB_SCR_DMA_START (1 << 0)
|
||||
|
||||
#define SC64_CART_USB_SCR_FIFO_ITEMS(i) (((i) & SC64_CART_USB_SCR_FIFO_ITEMS_MASK) >> SC64_CART_USB_SCR_FIFO_ITEMS_BIT)
|
||||
|
||||
#define SC64_CART_USB_DMA_ADDR_BANK_BIT (28)
|
||||
#define SC64_CART_USB_DMA_ADDR_BANK_MASK (0xF << SC64_CART_USB_DMA_ADDR_BANK_BIT)
|
||||
#define SC64_CART_USB_DMA_ADDR_ADDRESS_BIT (0)
|
||||
#define SC64_CART_USB_DMA_ADDR_ADDRESS_MASK (0x3FFFFFC << SC64_CART_USB_DMA_ADDR_ADDRESS_BIT)
|
||||
|
||||
#define SC64_CART_USB_DMA_ADDR(b, a) ((((b) << SC64_CART_USB_DMA_ADDR_BANK_BIT) & SC64_CART_USB_DMA_ADDR_BANK_MASK) | (((a) << SC64_CART_USB_DMA_ADDR_ADDRESS_BIT) & SC64_CART_USB_DMA_ADDR_ADDRESS_MASK))
|
||||
|
||||
#define SC64_CART_USB_DMA_LEN_LENGTH_BIT (0)
|
||||
#define SC64_CART_USB_DMA_LEN_LENGTH_MASK (0xFFFFF << SC64_CART_USB_DMA_LEN_LENGTH_BIT)
|
||||
|
||||
#define SC64_CART_USB_DMA_LEN(l) ((((l) - 1) << SC64_CART_USB_DMA_LEN_LENGTH_BIT) & SC64_CART_USB_DMA_LEN_LENGTH_MASK)
|
||||
|
||||
#define SC64_CART_DDIPL_ADDR_ADDRESS_BIT (0)
|
||||
#define SC64_CART_DDIPL_ADDR_ADDRESS_MASK (0x3FFFFFC << SC64_CART_DDIPL_ADDR_ADDRESS_BIT)
|
||||
#define SC64_CART_DDIPL_ADDR_DEFAULT (0x3C00000)
|
||||
|
||||
#define SC64_CART_DDIPL_ADDR(a) (((a) << SC64_CART_DDIPL_ADDR_ADDRESS_BIT) & SC64_CART_DDIPL_ADDR_ADDRESS_MASK)
|
||||
|
||||
#define SC64_CART_SRAM_ADDR_ADDRESS_BIT (0)
|
||||
#define SC64_CART_SRAM_ADDR_ADDRESS_MASK (0x3FFFFFC << SC64_CART_SRAM_ADDR_ADDRESS_BIT)
|
||||
#define SC64_CART_SRAM_ADDR_DEFAULT (0x3FF8000)
|
||||
|
||||
#define SC64_CART_SRAM_ADDR(a) (((a) << SC64_CART_SRAM_ADDR_ADDRESS_BIT) & SC64_CART_SRAM_ADDR_ADDRESS_MASK)
|
||||
|
||||
|
||||
// EEPROM Registers
|
||||
|
||||
typedef struct sc64_eeprom_registers {
|
||||
__IO reg_t mem[512]; // EEPROM memory
|
||||
} sc64_eeprom_registers_t;
|
||||
|
||||
#define SC64_EEPROM_BASE (0x1E004000)
|
||||
|
||||
#define SC64_EEPROM ((__IO sc64_sd_registers_t *) SC64_EEPROM_BASE)
|
||||
|
||||
|
||||
// SD Card Interface Registers
|
||||
|
||||
typedef struct sc64_sd_registers {
|
||||
__IO reg_t scr; // Clock prescaler and busy flag
|
||||
__IO reg_t cs; // Chip select pin control
|
||||
__IO reg_t dr; // Data to be sent and return value
|
||||
__IO reg_t multi; // Multi byte transmission
|
||||
__IO reg_t dma_scr; // DMA configuration
|
||||
__IO reg_t dma_addr; // DMA starting address
|
||||
__IO reg_t __reserved[122];
|
||||
__IO reg_t buffer[128]; // Multi byte transmission buffer
|
||||
} sc64_sd_registers_t;
|
||||
|
||||
#define SC64_SD_BASE (0x1E008000)
|
||||
|
||||
#define SC64_SD ((__IO sc64_sd_registers_t *) SC64_SD_BASE)
|
||||
|
||||
#define SC64_SC_SCR_PRESCALER_BIT (1)
|
||||
#define SC64_SD_SCR_PRESCALER_MASK (0x7 << SC64_SC_SCR_PRESCALER_BIT)
|
||||
#define SC64_SD_SCR_PRESCALER_2 (0 << SC64_SC_SCR_PRESCALER_BIT)
|
||||
#define SC64_SD_SCR_PRESCALER_4 (1 << SC64_SC_SCR_PRESCALER_BIT)
|
||||
#define SC64_SD_SCR_PRESCALER_8 (2 << SC64_SC_SCR_PRESCALER_BIT)
|
||||
#define SC64_SD_SCR_PRESCALER_16 (3 << SC64_SC_SCR_PRESCALER_BIT)
|
||||
#define SC64_SD_SCR_PRESCALER_32 (4 << SC64_SC_SCR_PRESCALER_BIT)
|
||||
#define SC64_SD_SCR_PRESCALER_64 (5 << SC64_SC_SCR_PRESCALER_BIT)
|
||||
#define SC64_SD_SCR_PRESCALER_128 (6 << SC64_SC_SCR_PRESCALER_BIT)
|
||||
#define SC64_SD_SCR_PRESCALER_256 (7 << SC64_SC_SCR_PRESCALER_BIT)
|
||||
#define SC64_SD_SCR_BUSY (1 << 0)
|
||||
|
||||
#define SC64_SD_CS_PIN (1 << 0)
|
||||
|
||||
#define SC64_SD_DR_BUSY (1 << 8)
|
||||
#define SC64_SD_DR_DATA_BIT (0)
|
||||
#define SC64_SD_DR_DATA_MASK (0xFF << SC64_SD_DR_DATA_BIT)
|
||||
|
||||
#define SC64_SD_DR_DATA(d) (((d) & SC64_SD_DR_DATA_MASK) >> SC64_SD_DR_DATA_BIT)
|
||||
|
||||
#define SC64_SD_MULTI_DMA (1 << 10)
|
||||
#define SC64_SD_MULTI_RX_ONLY (1 << 9)
|
||||
#define SC64_SD_MULTI_LENGTH_BIT (0)
|
||||
#define SC64_SD_MULTI_LENGTH_MASK (0x1FF << SC64_SD_MULTI_LENGTH_BIT)
|
||||
|
||||
#define SC64_SD_MULTI(d, r, l) ((d ? (SC64_SD_MULTI_DMA) : 0) | ((r) ? (SC64_SD_MULTI_RX_ONLY) : 0) | ((((l) - 1) & SC64_SD_MULTI_LENGTH_MASK) << SC64_SD_MULTI_LENGTH_BIT))
|
||||
|
||||
#define SC64_SD_DMA_SCR_FLUSH (1 << 0)
|
||||
#define SC64_SD_DMA_SCR_FIFO_FULL (1 << 1)
|
||||
#define SC64_SD_DMA_SCR_FIFO_EMPTY (1 << 0)
|
||||
|
||||
#define SC64_SD_DMA_ADDR_BANK_BIT (28)
|
||||
#define SC64_SD_DMA_ADDR_BANK_MASK (0xF << SC64_SD_DMA_ADDR_BANK_BIT)
|
||||
#define SC64_SD_DMA_ADDR_ADDRESS_BIT (0)
|
||||
#define SC64_SD_DMA_ADDR_ADDRESS_MASK (0x3FFFFFC << SC64_SD_DMA_ADDR_ADDRESS_BIT)
|
||||
|
||||
#define SC64_SD_DMA_ADDR(b, a) ((((b) << SC64_SD_DMA_ADDR_BANK_BIT) & SC64_SD_DMA_ADDR_BANK_MASK) | (((a) << SC64_SD_DMA_ADDR_ADDRESS_BIT) & SC64_SD_DMA_ADDR_ADDRESS_MASK))
|
||||
|
||||
|
||||
#endif
|
331
sw/bootloader/src/sc64/sc64_sd.c
Normal file
331
sw/bootloader/src/sc64/sc64_sd.c
Normal file
@ -0,0 +1,331 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "sc64.h"
|
||||
#include "sc64_sd.h"
|
||||
|
||||
|
||||
static const size_t SC64_SD_BUFFER_SIZE = sizeof(SC64_SD->buffer);
|
||||
|
||||
static uint8_t sd_spi_dma_buffer[sizeof(SC64_SD->buffer)] __attribute__((aligned(16)));
|
||||
static uint8_t sd_card_initialized = FALSE;
|
||||
static uint8_t sd_card_type_block = FALSE;
|
||||
|
||||
|
||||
static void sc64_sd_spi_set_prescaler(uint8_t prescaler) {
|
||||
uint32_t scr = platform_pi_io_read(&SC64_SD->scr);
|
||||
|
||||
scr = (scr & ~SC64_SD_SCR_PRESCALER_MASK) | (prescaler & SC64_SD_SCR_PRESCALER_MASK);
|
||||
|
||||
platform_pi_io_write(&SC64_SD->scr, scr);
|
||||
}
|
||||
|
||||
static void sc64_sd_spi_set_chip_select(uint8_t select) {
|
||||
platform_pi_io_write(&SC64_SD->cs, (select == TRUE) ? 0 : SC64_SD_CS_PIN);
|
||||
}
|
||||
|
||||
static uint8_t sc64_sd_spi_exchange(uint8_t data) {
|
||||
uint32_t dr;
|
||||
|
||||
platform_pi_io_write(&SC64_SD->dr, (uint32_t) (data & SC64_SD_DR_DATA_MASK));
|
||||
|
||||
do {
|
||||
dr = platform_pi_io_read(&SC64_SD->dr);
|
||||
} while (dr & SC64_SD_DR_BUSY);
|
||||
|
||||
return (uint8_t) SC64_SD_DR_DATA(dr);
|
||||
}
|
||||
|
||||
static uint8_t sc64_sd_spi_read(void) {
|
||||
return sc64_sd_spi_exchange(0xFF);
|
||||
}
|
||||
|
||||
static void sc64_sd_spi_release(void) {
|
||||
sc64_sd_spi_set_chip_select(FALSE);
|
||||
sc64_sd_spi_read();
|
||||
}
|
||||
|
||||
static void sc64_sd_spi_multi_write(uint8_t *data, size_t length) {
|
||||
size_t remaining = length;
|
||||
size_t offset = 0;
|
||||
|
||||
do {
|
||||
size_t block_size = remaining < SC64_SD_BUFFER_SIZE ? remaining : SC64_SD_BUFFER_SIZE;
|
||||
uint32_t dma_transfer_length = block_size + ((block_size % 4) ? (4 - (block_size % 4)) : 0);
|
||||
|
||||
memcpy(sd_spi_dma_buffer, data + offset, block_size);
|
||||
|
||||
platform_cache_writeback(sd_spi_dma_buffer, dma_transfer_length);
|
||||
platform_pi_dma_write(sd_spi_dma_buffer, &SC64_SD->buffer, dma_transfer_length);
|
||||
|
||||
platform_pi_io_write(&SC64_SD->multi, SC64_SD_MULTI(FALSE, FALSE, block_size));
|
||||
|
||||
while (platform_pi_io_read(&SC64_SD->scr) & SC64_SD_SCR_BUSY);
|
||||
|
||||
remaining -= block_size;
|
||||
offset += block_size;
|
||||
} while (remaining > 0);
|
||||
}
|
||||
|
||||
static void sc64_sd_spi_multi_read(uint8_t *data, size_t length, uint8_t is_buffer_aligned) {
|
||||
size_t remaining = length;
|
||||
size_t offset = 0;
|
||||
|
||||
do {
|
||||
size_t block_size = remaining < SC64_SD_BUFFER_SIZE ? remaining : SC64_SD_BUFFER_SIZE;
|
||||
uint32_t dma_transfer_length = block_size + ((block_size % 4) ? (4 - (block_size % 4)) : 0);
|
||||
uint8_t *buffer_pointer = is_buffer_aligned ? (data + offset) : sd_spi_dma_buffer;
|
||||
|
||||
platform_pi_io_write(&SC64_SD->multi, SC64_SD_MULTI(FALSE, TRUE, block_size));
|
||||
|
||||
while (platform_pi_io_read(&SC64_SD->scr) & SC64_SD_SCR_BUSY);
|
||||
|
||||
platform_pi_dma_read(buffer_pointer, &SC64_SD->buffer, dma_transfer_length);
|
||||
platform_cache_invalidate(buffer_pointer, dma_transfer_length);
|
||||
|
||||
if (!is_buffer_aligned) {
|
||||
memcpy(data + offset, sd_spi_dma_buffer, block_size);
|
||||
}
|
||||
|
||||
remaining -= block_size;
|
||||
offset += block_size;
|
||||
} while (remaining > 0);
|
||||
}
|
||||
|
||||
static void sc64_sd_spi_multi_read_dma(size_t length) {
|
||||
size_t remaining = length;
|
||||
|
||||
do {
|
||||
size_t block_size = remaining < SC64_SD_BUFFER_SIZE ? remaining : SC64_SD_BUFFER_SIZE;
|
||||
|
||||
platform_pi_io_write(&SC64_SD->multi, SC64_SD_MULTI(TRUE, TRUE, block_size));
|
||||
|
||||
while (platform_pi_io_read(&SC64_SD->scr) & SC64_SD_SCR_BUSY);
|
||||
|
||||
remaining -= block_size;
|
||||
} while (remaining > 0);
|
||||
}
|
||||
|
||||
static uint8_t sc64_sd_wait_ready(void) {
|
||||
uint8_t response;
|
||||
|
||||
for (size_t attempts = 10000; attempts > 0; --attempts) {
|
||||
response = sc64_sd_spi_read();
|
||||
|
||||
if (response == SD_NOT_BUSY_RESPONSE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
uint8_t sc64_sd_init(void) {
|
||||
uint32_t arg;
|
||||
uint8_t success;
|
||||
uint8_t response[5];
|
||||
uint8_t *short_response = &response[0];
|
||||
uint32_t *extended_response = (uint32_t *) &response[1];
|
||||
uint8_t sd_version_2_or_later;
|
||||
uint8_t status_data[64] __attribute__((aligned(16)));
|
||||
|
||||
if (!sd_card_initialized) {
|
||||
sc64_enable_sd();
|
||||
|
||||
platform_pi_io_write(&SC64_SD->dma_scr, SC64_SD_DMA_SCR_FLUSH);
|
||||
|
||||
sc64_sd_spi_set_prescaler(SC64_SD_SCR_PRESCALER_256);
|
||||
sc64_sd_spi_release();
|
||||
|
||||
sc64_sd_spi_set_chip_select(TRUE);
|
||||
|
||||
for (uint8_t dummy_clocks = 10; dummy_clocks > 0; --dummy_clocks) {
|
||||
sc64_sd_spi_read();
|
||||
}
|
||||
|
||||
do {
|
||||
success = sc64_sd_cmd_send(CMD0, 0, response);
|
||||
if (!(success && *short_response == R1_IN_IDLE_STATE)) break;
|
||||
|
||||
arg = CMD8_ARG_SUPPLY_VOLTAGE_27_36_V | CMD8_ARG_CHECK_PATTERN_AA;
|
||||
success = sc64_sd_cmd_send(CMD8, CMD8_ARG_SUPPLY_VOLTAGE_27_36_V | CMD8_ARG_CHECK_PATTERN_AA, response);
|
||||
if (!success) {
|
||||
break;
|
||||
} else if (*short_response & R1_ILLEGAL_COMMAND) {
|
||||
sd_version_2_or_later = FALSE;
|
||||
} else if (
|
||||
((*extended_response & R7_VOLTAGE_ACCEPTED_MASK) == R7_SUPPLY_VOLTAGE_27_36_V) &&
|
||||
((*extended_response & R7_CHECK_PATTERN_MASK) == R7_CHECK_PATTERN_AA)
|
||||
) {
|
||||
sd_version_2_or_later = TRUE;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
success = sc64_sd_cmd_send(CMD58, 0, response);
|
||||
if (!success || (!(*extended_response & R3_27_36_V_MASK))) break;
|
||||
|
||||
arg = sd_version_2_or_later ? ACMD41_ARG_HCS : 0;
|
||||
for (size_t attempts = 0; attempts < 10000; attempts++) {
|
||||
success = sc64_sd_cmd_send(ACMD41, arg, response);
|
||||
if (!success || (!(*short_response & R1_IN_IDLE_STATE))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!success) break;
|
||||
|
||||
success = sc64_sd_cmd_send(CMD58, 0, response);
|
||||
if (!success) break;
|
||||
sd_card_type_block = (*extended_response & R3_CCS) ? TRUE : FALSE;
|
||||
|
||||
sc64_sd_spi_set_prescaler(SC64_SD_SCR_PRESCALER_4);
|
||||
|
||||
// Set high speed mode
|
||||
success = sc64_sd_cmd_send(CMD6, 0x00000001, response);
|
||||
if (!success) break;
|
||||
success = sc64_sd_block_read(status_data, 64, FALSE);
|
||||
if (!success) break;
|
||||
if (status_data[13] & 0x02) {
|
||||
success = sc64_sd_cmd_send(CMD6, 0x80000001, response);
|
||||
if (!success) break;
|
||||
success = sc64_sd_block_read(status_data, 64, FALSE);
|
||||
if (!success) break;
|
||||
sc64_sd_spi_read();
|
||||
sc64_sd_spi_set_prescaler(SC64_SD_SCR_PRESCALER_2);
|
||||
}
|
||||
|
||||
sd_card_initialized = TRUE;
|
||||
|
||||
return TRUE;
|
||||
} while (0);
|
||||
|
||||
sc64_sd_deinit();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void sc64_sd_deinit(void) {
|
||||
sd_card_initialized = FALSE;
|
||||
|
||||
sc64_sd_spi_release();
|
||||
|
||||
while (platform_pi_io_read(&SC64_SD->scr) & SC64_SD_SCR_BUSY);
|
||||
|
||||
platform_pi_io_write(&SC64_SD->dma_scr, SC64_SD_DMA_SCR_FLUSH);
|
||||
|
||||
sc64_sd_spi_set_prescaler(SC64_SD_SCR_PRESCALER_256);
|
||||
|
||||
sc64_disable_sd();
|
||||
}
|
||||
|
||||
uint8_t sc64_sd_get_status(void) {
|
||||
return sd_card_initialized ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void sc64_sd_dma_wait_for_finish(void) {
|
||||
while (!(platform_pi_io_read(&SC64_SD->dma_scr) & SC64_SD_DMA_SCR_FIFO_EMPTY));
|
||||
}
|
||||
|
||||
void sc64_sd_dma_set_address(uint8_t bank, uint32_t address) {
|
||||
platform_pi_io_write(&SC64_SD->dma_addr, SC64_SD_DMA_ADDR(bank, address));
|
||||
}
|
||||
|
||||
uint8_t sc64_sd_cmd_send(uint8_t cmd, uint32_t arg, uint8_t *response) {
|
||||
uint8_t cmd_data[7];
|
||||
uint8_t cmd_data_length;
|
||||
uint8_t is_long_response;
|
||||
|
||||
if (cmd & ACMD_MARK) {
|
||||
sc64_sd_cmd_send(CMD55, 0, response);
|
||||
|
||||
if (*response & ~(R1_IN_IDLE_STATE)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (sc64_sd_wait_ready() != SD_NOT_BUSY_RESPONSE) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((cmd == CMD17 || cmd == CMD18) && sd_card_type_block) {
|
||||
|
||||
}
|
||||
|
||||
cmd_data[0] = cmd & ~ACMD_MARK; // Command index
|
||||
cmd_data[5] = 0x01; // CRC7 and stop bit
|
||||
cmd_data[6] = 0xFF; // CMD12 stuff byte
|
||||
|
||||
cmd_data_length = 6;
|
||||
is_long_response = FALSE;
|
||||
|
||||
switch (cmd) {
|
||||
case CMD0:
|
||||
cmd_data[5] = 0x95;
|
||||
break;
|
||||
case CMD8:
|
||||
cmd_data[5] = 0x87;
|
||||
is_long_response = TRUE;
|
||||
break;
|
||||
case CMD12:
|
||||
cmd_data_length = 7;
|
||||
break;
|
||||
case CMD17:
|
||||
case CMD18:
|
||||
if (!sd_card_type_block) {
|
||||
arg *= SD_BLOCK_SIZE;
|
||||
}
|
||||
break;
|
||||
case CMD58:
|
||||
is_long_response = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
cmd_data[1] = (uint8_t) (arg >> 24); // Command argument
|
||||
cmd_data[2] = (uint8_t) (arg >> 16);
|
||||
cmd_data[3] = (uint8_t) (arg >> 8);
|
||||
cmd_data[4] = (uint8_t) (arg >> 0);
|
||||
|
||||
sc64_sd_spi_multi_write(cmd_data, cmd_data_length);
|
||||
|
||||
for (uint32_t response_timeout = 0; response_timeout < 8; response_timeout++) {
|
||||
*response = sc64_sd_spi_read();
|
||||
|
||||
if (!(*response & RESPONSE_START_BIT)) {
|
||||
if (is_long_response) {
|
||||
sc64_sd_spi_multi_read(response + 1, 4, FALSE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
uint8_t sc64_sd_block_read(uint8_t *buffer, size_t length, uint8_t dma) {
|
||||
uint8_t token;
|
||||
uint8_t crc[2];
|
||||
|
||||
for (size_t attempts = 10000; attempts > 0; --attempts) {
|
||||
token = sc64_sd_spi_read();
|
||||
|
||||
if (token != SD_NOT_BUSY_RESPONSE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (token != DATA_TOKEN_BLOCK_READ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (dma) {
|
||||
sc64_sd_spi_multi_read_dma(length);
|
||||
} else {
|
||||
sc64_sd_spi_multi_read(buffer, length, TRUE);
|
||||
}
|
||||
sc64_sd_spi_multi_read(crc, 2, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
66
sw/bootloader/src/sc64/sc64_sd.h
Normal file
66
sw/bootloader/src/sc64/sc64_sd.h
Normal file
@ -0,0 +1,66 @@
|
||||
#ifndef SC64_SD_H__
|
||||
#define SC64_SD_H__
|
||||
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
#define RESPONSE_START_BIT (1 << 7)
|
||||
|
||||
#define R1_PARAMETER_ERROR (1 << 6)
|
||||
#define R1_ADDRESS_ERROR (1 << 5)
|
||||
#define R1_ERASE_SEQUENCE_ERROR (1 << 4)
|
||||
#define R1_COM_CRC_ERROR (1 << 3)
|
||||
#define R1_ILLEGAL_COMMAND (1 << 2)
|
||||
#define R1_ERASE_RESET (1 << 1)
|
||||
#define R1_IN_IDLE_STATE (1 << 0)
|
||||
|
||||
#define R3_27_36_V_BIT (15)
|
||||
#define R3_27_36_V_MASK (0x1FF << R3_27_36_V_BIT)
|
||||
#define R3_CCS (1 << 30)
|
||||
|
||||
#define R7_COMMAND_VERSION_BIT (28)
|
||||
#define R7_COMMAND_VERSION_MASK (0xF << R7_COMMAND_VERSION_BIT)
|
||||
#define R7_VOLTAGE_ACCEPTED_BIT (8)
|
||||
#define R7_VOLTAGE_ACCEPTED_MASK (0xF << R7_VOLTAGE_ACCEPTED_BIT)
|
||||
#define R7_CHECK_PATTERN_BIT (0)
|
||||
#define R7_CHECK_PATTERN_MASK (0xFF << R7_CHECK_PATTERN_BIT)
|
||||
|
||||
#define R7_SUPPLY_VOLTAGE_27_36_V (1 << 8)
|
||||
#define R7_CHECK_PATTERN_AA (0xAA << 0)
|
||||
|
||||
#define SD_NOT_BUSY_RESPONSE (0xFF)
|
||||
|
||||
#define CMD_START_BIT (1 << 6)
|
||||
#define ACMD_MARK (1 << 7)
|
||||
|
||||
#define CMD0 (CMD_START_BIT | 0)
|
||||
#define CMD6 (CMD_START_BIT | 6)
|
||||
#define CMD8 (CMD_START_BIT | 8)
|
||||
#define CMD12 (CMD_START_BIT | 12)
|
||||
#define CMD17 (CMD_START_BIT | 17)
|
||||
#define CMD18 (CMD_START_BIT | 18)
|
||||
#define CMD55 (CMD_START_BIT | 55)
|
||||
#define CMD58 (CMD_START_BIT | 58)
|
||||
#define ACMD41 (ACMD_MARK | CMD_START_BIT | 41)
|
||||
|
||||
#define CMD8_ARG_SUPPLY_VOLTAGE_27_36_V (1 << 8)
|
||||
#define CMD8_ARG_CHECK_PATTERN_AA (0xAA << 0)
|
||||
|
||||
#define ACMD41_ARG_HCS (1 << 30)
|
||||
|
||||
#define DATA_TOKEN_BLOCK_READ (0xFE)
|
||||
|
||||
#define SD_BLOCK_SIZE (512)
|
||||
|
||||
|
||||
uint8_t sc64_sd_init(void);
|
||||
void sc64_sd_deinit(void);
|
||||
uint8_t sc64_sd_get_status(void);
|
||||
void sc64_sd_dma_wait_for_finish(void);
|
||||
void sc64_sd_dma_set_address(uint8_t bank, uint32_t address);
|
||||
uint8_t sc64_sd_cmd_send(uint8_t cmd, uint32_t arg, uint8_t *response);
|
||||
uint8_t sc64_sd_block_read(uint8_t *buffer, size_t length, uint8_t dma);
|
||||
|
||||
|
||||
#endif
|
96
sw/bootloader/src/sc64/sc64_sd_fs.c
Normal file
96
sw/bootloader/src/sc64/sc64_sd_fs.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include "ff.h"
|
||||
#include "diskio.h"
|
||||
|
||||
#include "sc64.h"
|
||||
#include "sc64_sd.h"
|
||||
#include "sc64_sd_fs.h"
|
||||
|
||||
|
||||
static DRESULT sc64_sd_fs_load_with_dma(BYTE pdrv, FSIZE_t offset, LBA_t sector, UINT count) {
|
||||
uint8_t success;
|
||||
uint8_t response;
|
||||
|
||||
if ((pdrv > 0) || (count == 0)) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
if (!sc64_sd_get_status()) {
|
||||
return RES_NOTRDY;
|
||||
}
|
||||
|
||||
sc64_sd_dma_set_address(SC64_BANK_SDRAM, (uint32_t) offset);
|
||||
|
||||
success = sc64_sd_cmd_send(CMD18, sector, &response);
|
||||
|
||||
if (!success || response) {
|
||||
return RES_PARERR;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
success = sc64_sd_block_read(NULL, SD_BLOCK_SIZE, TRUE);
|
||||
|
||||
if (!success) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
success = sc64_sd_cmd_send(CMD12, 0, &response);
|
||||
|
||||
if (!success || response) {
|
||||
return RES_ERROR;
|
||||
}
|
||||
|
||||
sc64_sd_dma_wait_for_finish();
|
||||
|
||||
return RES_OK;
|
||||
}
|
||||
|
||||
sc64_sd_fs_error_t sc64_sd_fs_load_rom(const char *path) {
|
||||
FRESULT fresult;
|
||||
FATFS fatfs;
|
||||
|
||||
sc64_sd_fs_error_t error = SC64_SD_FS_OK;
|
||||
|
||||
do {
|
||||
fresult = f_mount(&fatfs, "", 1);
|
||||
if (fresult != FR_OK) {
|
||||
switch (fresult) {
|
||||
case FR_DISK_ERR:
|
||||
case FR_NOT_READY:
|
||||
error = SC64_SD_FS_NO_CARD;
|
||||
break;
|
||||
case FR_NO_FILESYSTEM:
|
||||
error = SC64_SD_FS_NO_FILESYSTEM;
|
||||
break;
|
||||
default:
|
||||
error = SC64_SD_FS_OTHER_ERROR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
fresult = fe_load(path, SC64_SDRAM_SIZE, sc64_sd_fs_load_with_dma);
|
||||
if (fresult) {
|
||||
switch (fresult) {
|
||||
case FR_DISK_ERR:
|
||||
case FR_NOT_READY:
|
||||
error = SC64_SD_FS_READ_ERROR;
|
||||
break;
|
||||
case FR_NO_FILE:
|
||||
case FR_NO_PATH:
|
||||
error = SC64_SD_FS_NO_FILE;
|
||||
break;
|
||||
default:
|
||||
error = SC64_SD_FS_OTHER_ERROR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
f_unmount("");
|
||||
|
||||
sc64_sd_deinit();
|
||||
|
||||
return error;
|
||||
}
|
21
sw/bootloader/src/sc64/sc64_sd_fs.h
Normal file
21
sw/bootloader/src/sc64/sc64_sd_fs.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef SC64_SD_FS_H__
|
||||
#define SC64_SD_FS_H__
|
||||
|
||||
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
typedef enum sc64_sd_fs_error_e {
|
||||
SC64_SD_FS_OK,
|
||||
SC64_SD_FS_NO_CARD,
|
||||
SC64_SD_FS_NO_FILESYSTEM,
|
||||
SC64_SD_FS_NO_FILE,
|
||||
SC64_SD_FS_READ_ERROR,
|
||||
SC64_SD_FS_OTHER_ERROR,
|
||||
} sc64_sd_fs_error_t;
|
||||
|
||||
|
||||
sc64_sd_fs_error_t sc64_sd_fs_load_rom(const char *path);
|
||||
|
||||
|
||||
#endif
|
@ -1,21 +0,0 @@
|
||||
#ifndef SC64_REGS_H__
|
||||
#define SC64_REGS_H__
|
||||
|
||||
// SummerCart64 config register
|
||||
|
||||
#define SC64_CONFIG_REG (0x1E000000)
|
||||
|
||||
#define SC64_CONFIG_SDRAM_ENABLE (1 << 1)
|
||||
|
||||
// Boot CIC and TV type override register
|
||||
|
||||
#define SC64_BOOT_REG (0x1E000004)
|
||||
|
||||
#define SC64_BOOT_CIC_TYPE_MSK (0x0F)
|
||||
#define SC64_BOOT_CIC_TYPE_BIT (0)
|
||||
#define SC64_BOOT_CIC_TYPE(x) (((x) & SC64_BOOT_CIC_TYPE_MSK) >> SC64_BOOT_CIC_TYPE_BIT)
|
||||
#define SC64_BOOT_TV_TYPE_MSK (0x30)
|
||||
#define SC64_BOOT_TV_TYPE_BIT (4)
|
||||
#define SC64_BOOT_TV_TYPE(x) (((x) & SC64_BOOT_TV_TYPE_MSK) >> SC64_BOOT_TV_TYPE_BIT)
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user