mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-25 15:16:53 +01:00
good stopping point
This commit is contained in:
parent
8bde0ccfb2
commit
8493c2edb1
2
build.sh
2
build.sh
@ -86,7 +86,7 @@ build_fpga () {
|
|||||||
|
|
||||||
pushd fw > /dev/null
|
pushd fw > /dev/null
|
||||||
if [ "$SKIP_FPGA_REBUILD" = true ] && [ -f output_files/SummerCart64.sof ]; then
|
if [ "$SKIP_FPGA_REBUILD" = true ] && [ -f output_files/SummerCart64.sof ]; then
|
||||||
echo Skipping FPGA build
|
quartus_cpf -c SummerCart64.cof
|
||||||
else
|
else
|
||||||
if [ "$DEBUG_ENABLED" = true ]; then
|
if [ "$DEBUG_ENABLED" = true ]; then
|
||||||
quartus_sh --set VERILOG_MACRO="DEBUG" ./SummerCart64.qpf
|
quartus_sh --set VERILOG_MACRO="DEBUG" ./SummerCart64.qpf
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#
|
#
|
||||||
# Quartus Prime
|
# Quartus Prime
|
||||||
# Version 21.1.0 Build 842 10/21/2021 SJ Lite Edition
|
# Version 21.1.0 Build 842 10/21/2021 SJ Lite Edition
|
||||||
# Date created = 13:29:40 November 11, 2021
|
# Date created = 19:00:58 February 02, 2022
|
||||||
#
|
#
|
||||||
# -------------------------------------------------------------------------- #
|
# -------------------------------------------------------------------------- #
|
||||||
#
|
#
|
||||||
@ -46,6 +46,7 @@ set_global_assignment -name LAST_QUARTUS_VERSION "21.1.0 Lite Edition"
|
|||||||
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
||||||
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
|
set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
|
||||||
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
|
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
|
||||||
|
set_global_assignment -name POST_MODULE_SCRIPT_FILE "quartus_sh:scripts/post_module.tcl"
|
||||||
set_global_assignment -name QSYS_FILE rtl/intel/flash/intel_flash.qsys
|
set_global_assignment -name QSYS_FILE rtl/intel/flash/intel_flash.qsys
|
||||||
set_global_assignment -name QIP_FILE rtl/intel/fifo/intel_fifo_8.qip
|
set_global_assignment -name QIP_FILE rtl/intel/fifo/intel_fifo_8.qip
|
||||||
set_global_assignment -name QIP_FILE rtl/intel/gpio/intel_gpio_ddro.qip
|
set_global_assignment -name QIP_FILE rtl/intel/gpio/intel_gpio_ddro.qip
|
||||||
@ -55,10 +56,8 @@ set_global_assignment -name SYSTEMVERILOG_FILE picorv32/picorv32.v
|
|||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_bus.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_cfg.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dd.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dd.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_dma.sv
|
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flash.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flash.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_flashram.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_gpio.sv
|
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_i2c.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_ram.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_sdram.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_sdram.sv
|
||||||
@ -67,6 +66,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_soc.sv
|
|||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_uart.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_uart.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_usb.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_wrapper.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_wrapper.sv
|
||||||
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_dma.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_sdram.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/memory/memory_sdram.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv
|
||||||
@ -83,7 +83,8 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/config.sv
|
|||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/sc64.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/sc64.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/system.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/system.sv
|
||||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/usb/usb_ft1248.sv
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/usb/usb_ft1248.sv
|
||||||
set_global_assignment -name POST_MODULE_SCRIPT_FILE "quartus_sh:scripts/post_module.tcl"
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vendor/vendor_flash.sv
|
||||||
|
set_global_assignment -name SYSTEMVERILOG_FILE rtl/vendor/vendor_reconfigure.sv
|
||||||
|
|
||||||
# Pin & Location Assignments
|
# Pin & Location Assignments
|
||||||
# ==========================
|
# ==========================
|
||||||
@ -164,8 +165,11 @@ set_location_assignment PIN_114 -to o_sd_clk
|
|||||||
set_location_assignment PIN_118 -to io_sd_cmd
|
set_location_assignment PIN_118 -to io_sd_cmd
|
||||||
set_location_assignment PIN_119 -to io_sd_dat[3]
|
set_location_assignment PIN_119 -to io_sd_dat[3]
|
||||||
set_location_assignment PIN_120 -to io_sd_dat[2]
|
set_location_assignment PIN_120 -to io_sd_dat[2]
|
||||||
|
set_location_assignment PIN_121 -to io_usb_miosi[5]
|
||||||
|
set_location_assignment PIN_122 -to io_usb_miosi[7]
|
||||||
set_location_assignment PIN_123 -to o_n64_irq
|
set_location_assignment PIN_123 -to o_n64_irq
|
||||||
set_location_assignment PIN_138 -to i_usb_pwren
|
set_location_assignment PIN_124 -to io_usb_miosi[6]
|
||||||
|
set_location_assignment PIN_126 -to io_usb_miosi[4]
|
||||||
set_location_assignment PIN_140 -to o_usb_cs
|
set_location_assignment PIN_140 -to o_usb_cs
|
||||||
set_location_assignment PIN_141 -to i_usb_miso
|
set_location_assignment PIN_141 -to i_usb_miso
|
||||||
|
|
||||||
@ -191,6 +195,7 @@ set_global_assignment -name VHDL_SHOW_LMF_MAPPING_MESSAGES OFF
|
|||||||
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
|
set_global_assignment -name VERILOG_INPUT_VERSION SYSTEMVERILOG_2005
|
||||||
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
|
set_global_assignment -name VERILOG_SHOW_LMF_MAPPING_MESSAGES OFF
|
||||||
set_global_assignment -name TOP_LEVEL_ENTITY SummerCart64
|
set_global_assignment -name TOP_LEVEL_ENTITY SummerCart64
|
||||||
|
set_global_assignment -name VERILOG_MACRO DEBUG
|
||||||
|
|
||||||
# Fitter Assignments
|
# Fitter Assignments
|
||||||
# ==================
|
# ==================
|
||||||
@ -200,7 +205,7 @@ set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
|
|||||||
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
|
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
|
||||||
set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE"
|
set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE"
|
||||||
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
|
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
|
||||||
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
|
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.0-V LVTTL"
|
||||||
|
|
||||||
# Assembler Assignments
|
# Assembler Assignments
|
||||||
# =====================
|
# =====================
|
||||||
@ -226,10 +231,8 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
|||||||
|
|
||||||
# Pin & Location Assignments
|
# Pin & Location Assignments
|
||||||
# ==========================
|
# ==========================
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_usb_miosi[*]
|
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_uart_rxd
|
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_uart_rxd
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_rtc_sda
|
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_rtc_sda
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_n64_si_dq
|
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_nmi
|
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_nmi
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_reset
|
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_reset
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_si_clk
|
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_si_clk
|
||||||
@ -239,25 +242,19 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
|||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_write
|
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_write
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_alel
|
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_alel
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_sdram_dq[*]
|
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_sdram_dq[*]
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_sd_*
|
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_usb_pwren
|
|
||||||
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_usb_miso
|
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_usb_clk
|
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_usb_miosi[*]
|
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_uart_txd
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_uart_txd
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_rtc_scl
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_rtc_scl
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_rtc_sda
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_rtc_sda
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_n64_pi_ad[*]
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_n64_pi_ad[*]
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_*
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_cs
|
||||||
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_ras
|
||||||
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_cas
|
||||||
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_we
|
||||||
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_a[*]
|
||||||
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sdram_ba[*]
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_sdram_dq[*]
|
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_sdram_dq[*]
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_sd_clk
|
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_sd_*
|
|
||||||
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_usb_cs
|
|
||||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_usb_miosi[*]
|
|
||||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_n64_pi_ad[*]
|
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_n64_pi_ad[*]
|
||||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_sdram_dq[*]
|
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_sdram_dq[*]
|
||||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_sd_*
|
|
||||||
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to io_rtc_sda
|
|
||||||
|
|
||||||
# Fitter Assignments
|
# Fitter Assignments
|
||||||
# ==================
|
# ==================
|
||||||
@ -272,7 +269,6 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
|||||||
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_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_pi_alel
|
||||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to o_n64_irq
|
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to o_n64_irq
|
||||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_pwren
|
|
||||||
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_miso
|
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_miso
|
||||||
|
|
||||||
# start DESIGN_PARTITION(Top)
|
# start DESIGN_PARTITION(Top)
|
||||||
|
@ -7,9 +7,9 @@ set sdram_pll_clk {system_inst|intel_pll_inst|altpll_component|auto_generated|pl
|
|||||||
# set sd_reg_clk {sd_interface_inst|sd_clk_inst|o_sd_clk|q}
|
# set sd_reg_clk {sd_interface_inst|sd_clk_inst|o_sd_clk|q}
|
||||||
|
|
||||||
create_generated_clock -name sdram_clk -source [get_pins $sdram_pll_clk] [get_ports {o_sdram_clk}]
|
create_generated_clock -name sdram_clk -source [get_pins $sdram_pll_clk] [get_ports {o_sdram_clk}]
|
||||||
|
create_clock -name usb_clk -period 40.0 [get_ports {o_usb_clk}]
|
||||||
# create_generated_clock -name sd_reg_clk -source [get_pins {sd_interface_inst|sd_clk_inst|o_sd_clk|clk}] -divide_by 2 [get_pins $sd_reg_clk]
|
# create_generated_clock -name sd_reg_clk -source [get_pins {sd_interface_inst|sd_clk_inst|o_sd_clk|clk}] -divide_by 2 [get_pins $sd_reg_clk]
|
||||||
# create_generated_clock -name sd_clk -source [get_pins $sd_reg_clk] [get_ports {o_sd_clk}]
|
# create_generated_clock -name sd_clk -source [get_pins $sd_reg_clk] [get_ports {o_sd_clk}]
|
||||||
|
|
||||||
create_generated_clock -name flash_se_neg_reg \
|
create_generated_clock -name flash_se_neg_reg \
|
||||||
-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}] \
|
-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}] \
|
||||||
-divide_by 2 \
|
-divide_by 2 \
|
||||||
@ -30,6 +30,7 @@ set_input_delay -clock [get_clocks {sdram_clk}] -max 5.4 [get_ports $sdram_input
|
|||||||
set_input_delay -clock [get_clocks {sdram_clk}] -min 2.5 [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]
|
set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks $sys_clk]
|
||||||
|
set_multicycle_path -hold -end 1 -from [get_clocks {sdram_clk}] -to [get_clocks $sys_clk]
|
||||||
|
|
||||||
|
|
||||||
# SD card timings
|
# SD card timings
|
||||||
@ -48,8 +49,17 @@ set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks
|
|||||||
|
|
||||||
# FT1248 timings
|
# FT1248 timings
|
||||||
|
|
||||||
set_false_path -to [get_ports {o_usb_clk io_usb_miosi[*] o_usb_cs}]
|
set_output_delay -clock [get_clocks {usb_clk}] -max 5.0 [get_ports {io_usb_miosi[*] o_usb_cs}]
|
||||||
set_false_path -from [get_ports {io_usb_miosi[*] i_usb_miso i_usb_pwren}]
|
set_output_delay -clock [get_clocks {usb_clk}] -min -5.0 [get_ports {io_usb_miosi[*] o_usb_cs}]
|
||||||
|
|
||||||
|
set_input_delay -clock [get_clocks {usb_clk}] -max 5.0 [get_ports {io_usb_miosi[*] i_usb_miso}]
|
||||||
|
set_input_delay -clock [get_clocks {usb_clk}] -min 5.0 [get_ports {io_usb_miosi[*] i_usb_miso}]
|
||||||
|
|
||||||
|
set_multicycle_path -setup -start 2 -from [get_clocks $sys_clk] -to [get_clocks {usb_clk}]
|
||||||
|
set_multicycle_path -hold -start 3 -from [get_clocks $sys_clk] -to [get_clocks {usb_clk}]
|
||||||
|
|
||||||
|
set_multicycle_path -setup -end 2 -from [get_clocks {usb_clk}] -to [get_clocks $sys_clk]
|
||||||
|
set_multicycle_path -hold -end 3 -from [get_clocks {usb_clk}] -to [get_clocks $sys_clk]
|
||||||
|
|
||||||
|
|
||||||
# N64, PI and SI timings
|
# N64, PI and SI timings
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit f9b1beb4cfd6b382157b54bc8f38c61d5ae7d785
|
Subproject commit f00a88c36eaab478b64ee27d8162e421049bcc66
|
@ -29,8 +29,7 @@ module SummerCart64 (
|
|||||||
output o_usb_clk,
|
output o_usb_clk,
|
||||||
output o_usb_cs,
|
output o_usb_cs,
|
||||||
input i_usb_miso,
|
input i_usb_miso,
|
||||||
inout [3:0] io_usb_miosi,
|
inout [7:0] io_usb_miosi,
|
||||||
input i_usb_pwren,
|
|
||||||
|
|
||||||
input i_uart_rxd,
|
input i_uart_rxd,
|
||||||
output o_uart_txd,
|
output o_uart_txd,
|
||||||
@ -42,10 +41,6 @@ module SummerCart64 (
|
|||||||
output o_led
|
output o_led
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [7:0] gpio_o;
|
|
||||||
logic [7:0] gpio_i;
|
|
||||||
logic [7:0] gpio_oe;
|
|
||||||
|
|
||||||
logic dd_interrupt;
|
logic dd_interrupt;
|
||||||
|
|
||||||
if_system sys (
|
if_system sys (
|
||||||
@ -56,7 +51,7 @@ module SummerCart64 (
|
|||||||
|
|
||||||
if_config cfg ();
|
if_config cfg ();
|
||||||
|
|
||||||
if_dma dma ();
|
if_memory_dma usb_dma ();
|
||||||
|
|
||||||
if_sdram sdram ();
|
if_sdram sdram ();
|
||||||
|
|
||||||
@ -70,7 +65,6 @@ module SummerCart64 (
|
|||||||
.dd_interrupt(dd_interrupt)
|
.dd_interrupt(dd_interrupt)
|
||||||
);
|
);
|
||||||
|
|
||||||
if_cpu_ram cpu_ram ();
|
|
||||||
|
|
||||||
system system_inst (
|
system system_inst (
|
||||||
.sys(sys)
|
.sys(sys)
|
||||||
@ -85,13 +79,12 @@ module SummerCart64 (
|
|||||||
n64_soc n64_soc_inst (
|
n64_soc n64_soc_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.cfg(cfg),
|
.cfg(cfg),
|
||||||
.dma(dma),
|
.usb_dma(usb_dma),
|
||||||
.sdram(sdram),
|
.sdram(sdram),
|
||||||
.flashram(flashram),
|
.flashram(flashram),
|
||||||
.si(si),
|
.si(si),
|
||||||
.flash(flash),
|
.flash(flash),
|
||||||
.dd(dd),
|
.dd(dd),
|
||||||
.cpu_ram(cpu_ram),
|
|
||||||
|
|
||||||
.n64_pi_alel(i_n64_pi_alel),
|
.n64_pi_alel(i_n64_pi_alel),
|
||||||
.n64_pi_aleh(i_n64_pi_aleh),
|
.n64_pi_aleh(i_n64_pi_aleh),
|
||||||
@ -114,17 +107,12 @@ module SummerCart64 (
|
|||||||
cpu_soc cpu_soc_inst (
|
cpu_soc cpu_soc_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.cfg(cfg),
|
.cfg(cfg),
|
||||||
.dma(dma),
|
.usb_dma(usb_dma),
|
||||||
.sdram(sdram),
|
.sdram(sdram),
|
||||||
.flashram(flashram),
|
.flashram(flashram),
|
||||||
.si(si),
|
.si(si),
|
||||||
.flash(flash),
|
.flash(flash),
|
||||||
.dd(dd),
|
.dd(dd),
|
||||||
.cpu_ram(cpu_ram),
|
|
||||||
|
|
||||||
.gpio_o(gpio_o),
|
|
||||||
.gpio_i(gpio_i),
|
|
||||||
.gpio_oe(gpio_oe),
|
|
||||||
|
|
||||||
.i2c_scl(o_rtc_scl),
|
.i2c_scl(o_rtc_scl),
|
||||||
.i2c_sda(io_rtc_sda),
|
.i2c_sda(io_rtc_sda),
|
||||||
@ -133,7 +121,6 @@ module SummerCart64 (
|
|||||||
.usb_cs(o_usb_cs),
|
.usb_cs(o_usb_cs),
|
||||||
.usb_miso(i_usb_miso),
|
.usb_miso(i_usb_miso),
|
||||||
.usb_miosi(io_usb_miosi),
|
.usb_miosi(io_usb_miosi),
|
||||||
.usb_pwren(i_usb_pwren),
|
|
||||||
|
|
||||||
.uart_rxd(i_uart_rxd),
|
.uart_rxd(i_uart_rxd),
|
||||||
.uart_txd(o_uart_txd),
|
.uart_txd(o_uart_txd),
|
||||||
@ -145,14 +132,7 @@ module SummerCart64 (
|
|||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
o_n64_irq = dd_interrupt ? 1'b0 : 1'bZ;
|
o_n64_irq = dd_interrupt ? 1'b0 : 1'bZ;
|
||||||
end
|
o_led = 1'bZ;
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
o_led = gpio_oe[0] ? gpio_o[0] : 1'bZ;
|
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
|
||||||
gpio_i <= {4'b0000, i_n64_nmi, i_n64_reset, gpio_o[1:0]};
|
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
interface if_cpu_bus ();
|
interface if_cpu_bus #(
|
||||||
|
parameter bit [3:0] NUM_DEVICES
|
||||||
localparam [3:0] NUM_DEVICES = sc64::__ID_CPU_END;
|
) ();
|
||||||
|
|
||||||
logic request;
|
logic request;
|
||||||
logic ack;
|
logic ack;
|
||||||
|
@ -18,7 +18,8 @@ module cpu_cfg (
|
|||||||
R_VERSION,
|
R_VERSION,
|
||||||
R_RECONFIGURE,
|
R_RECONFIGURE,
|
||||||
R_ISV_OFFSET,
|
R_ISV_OFFSET,
|
||||||
R_ISV_RD_PTR
|
R_ISV_RD_PTR,
|
||||||
|
R_FLASH
|
||||||
} e_reg_id;
|
} e_reg_id;
|
||||||
|
|
||||||
const logic [31:0] RECONFIGURE_MAGIC = 32'h52535446;
|
const logic [31:0] RECONFIGURE_MAGIC = 32'h52535446;
|
||||||
@ -39,7 +40,10 @@ module cpu_cfg (
|
|||||||
cfg.cpu_busy,
|
cfg.cpu_busy,
|
||||||
1'b0,
|
1'b0,
|
||||||
cfg.cmd_error,
|
cfg.cmd_error,
|
||||||
20'd0,
|
2'd0,
|
||||||
|
cfg.flash_erase_busy,
|
||||||
|
1'd0,
|
||||||
|
16'd0,
|
||||||
cfg.isv_enabled,
|
cfg.isv_enabled,
|
||||||
skip_bootloader,
|
skip_bootloader,
|
||||||
cfg.flashram_enabled,
|
cfg.flashram_enabled,
|
||||||
@ -73,6 +77,10 @@ module cpu_cfg (
|
|||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
always_ff @(posedge sys.clk) begin
|
||||||
|
cfg.flash_erase_start <= 1'b0;
|
||||||
|
cfg.flash_wp_enable <= 1'b0;
|
||||||
|
cfg.flash_wp_disable <= 1'b0;
|
||||||
|
|
||||||
if (sys.reset) begin
|
if (sys.reset) begin
|
||||||
cfg.cpu_ready <= 1'b0;
|
cfg.cpu_ready <= 1'b0;
|
||||||
cfg.cpu_busy <= 1'b0;
|
cfg.cpu_busy <= 1'b0;
|
||||||
@ -95,9 +103,11 @@ module cpu_cfg (
|
|||||||
cfg.sdram_writable <= 1'b0;
|
cfg.sdram_writable <= 1'b0;
|
||||||
isv_current_rd_ptr <= 16'd0;
|
isv_current_rd_ptr <= 16'd0;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (cfg.cmd_request) begin
|
if (cfg.cmd_request) begin
|
||||||
cfg.cpu_busy <= 1'b1;
|
cfg.cpu_busy <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (bus.request) begin
|
if (bus.request) begin
|
||||||
case (bus.address[5:2])
|
case (bus.address[5:2])
|
||||||
R_SCR: begin
|
R_SCR: begin
|
||||||
@ -105,8 +115,11 @@ module cpu_cfg (
|
|||||||
{
|
{
|
||||||
cfg.cpu_ready,
|
cfg.cpu_ready,
|
||||||
cfg.cpu_busy,
|
cfg.cpu_busy,
|
||||||
cfg.cmd_error
|
cfg.cmd_error,
|
||||||
} <= {bus.wdata[31:30], bus.wdata[28]};
|
cfg.flash_wp_disable,
|
||||||
|
cfg.flash_wp_enable,
|
||||||
|
cfg.flash_erase_start
|
||||||
|
} <= {bus.wdata[31:30], bus.wdata[28:26], bus.wdata[24]};
|
||||||
end
|
end
|
||||||
if (bus.wmask[0]) begin
|
if (bus.wmask[0]) begin
|
||||||
{
|
{
|
||||||
@ -156,31 +169,11 @@ module cpu_cfg (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
logic [1:0] ru_clk;
|
vendor_reconfigure vendor_reconfigure_inst (
|
||||||
logic ru_rconfig;
|
.clk(sys.clk),
|
||||||
logic ru_regout;
|
.reset(sys.reset),
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
.trigger_reconfiguration(trigger_reconfiguration)
|
||||||
if (sys.reset) begin
|
|
||||||
ru_clk <= 2'd0;
|
|
||||||
ru_rconfig <= 1'b0;
|
|
||||||
end else begin
|
|
||||||
ru_clk <= ru_clk + 1'd1;
|
|
||||||
|
|
||||||
if (ru_clk == 2'd1) begin
|
|
||||||
ru_rconfig <= trigger_reconfiguration;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
fiftyfivenm_rublock fiftyfivenm_rublock_inst (
|
|
||||||
.clk(ru_clk[1]),
|
|
||||||
.shiftnld(1'b0),
|
|
||||||
.captnupdt(1'b0),
|
|
||||||
.regin(1'b0),
|
|
||||||
.rsttimer(1'b0),
|
|
||||||
.rconfig(ru_rconfig),
|
|
||||||
.regout(ru_regout)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,222 +0,0 @@
|
|||||||
interface if_dma ();
|
|
||||||
|
|
||||||
localparam [1:0] NUM_DEVICES = sc64::__ID_DMA_END;
|
|
||||||
|
|
||||||
sc64::e_dma_id id;
|
|
||||||
|
|
||||||
logic rx_empty;
|
|
||||||
logic rx_read;
|
|
||||||
logic [7:0] rx_rdata;
|
|
||||||
logic tx_full;
|
|
||||||
logic tx_write;
|
|
||||||
logic [7:0] tx_wdata;
|
|
||||||
|
|
||||||
logic request;
|
|
||||||
logic ack;
|
|
||||||
logic write;
|
|
||||||
logic [31:0] address;
|
|
||||||
logic [15:0] rdata;
|
|
||||||
logic [15:0] wdata;
|
|
||||||
|
|
||||||
modport controller (
|
|
||||||
output id,
|
|
||||||
|
|
||||||
input rx_empty,
|
|
||||||
output rx_read,
|
|
||||||
input rx_rdata,
|
|
||||||
input tx_full,
|
|
||||||
output tx_write,
|
|
||||||
output tx_wdata,
|
|
||||||
|
|
||||||
output request,
|
|
||||||
input ack,
|
|
||||||
output write,
|
|
||||||
output address,
|
|
||||||
input rdata,
|
|
||||||
output wdata
|
|
||||||
);
|
|
||||||
|
|
||||||
modport memory (
|
|
||||||
input request,
|
|
||||||
output ack,
|
|
||||||
input write,
|
|
||||||
input address,
|
|
||||||
output rdata,
|
|
||||||
input wdata
|
|
||||||
);
|
|
||||||
|
|
||||||
logic [7:0] device_rx_rdata [(NUM_DEVICES - 1):0];
|
|
||||||
logic device_rx_empty [(NUM_DEVICES - 1):0];
|
|
||||||
logic device_tx_full [(NUM_DEVICES - 1):0];
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
rx_rdata = 8'd0;
|
|
||||||
rx_empty = 1'b0;
|
|
||||||
tx_full = 1'b0;
|
|
||||||
|
|
||||||
for (integer i = 0; i < NUM_DEVICES; i++) begin
|
|
||||||
rx_rdata = rx_rdata | (id == i[1:0] ? device_rx_rdata[i] : 8'd0);
|
|
||||||
rx_empty = rx_empty | (device_rx_empty[i] && id == i[1:0]);
|
|
||||||
tx_full = tx_full | (device_tx_full[i] && id == i[1:0]);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
genvar n;
|
|
||||||
generate
|
|
||||||
for (n = 0; n < NUM_DEVICES; n++) begin : at
|
|
||||||
logic device_selected;
|
|
||||||
logic device_rx_read;
|
|
||||||
logic device_tx_write;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
device_selected = id == n[1:0];
|
|
||||||
device_rx_read = device_selected && rx_read;
|
|
||||||
device_tx_write = device_selected && tx_write;
|
|
||||||
end
|
|
||||||
|
|
||||||
modport device (
|
|
||||||
output .rx_empty(device_rx_empty[n]),
|
|
||||||
input .rx_read(device_rx_read),
|
|
||||||
output .rx_rdata(device_rx_rdata[n]),
|
|
||||||
output .tx_full(device_tx_full[n]),
|
|
||||||
input .tx_write(device_tx_write),
|
|
||||||
input .tx_wdata(tx_wdata)
|
|
||||||
);
|
|
||||||
end
|
|
||||||
endgenerate
|
|
||||||
|
|
||||||
endinterface
|
|
||||||
|
|
||||||
|
|
||||||
module cpu_dma (
|
|
||||||
if_system.sys sys,
|
|
||||||
if_cpu_bus bus,
|
|
||||||
if_dma.controller dma
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef enum bit [2:0] {
|
|
||||||
S_IDLE,
|
|
||||||
S_FETCH,
|
|
||||||
S_TRANSFER
|
|
||||||
} e_state;
|
|
||||||
|
|
||||||
e_state state;
|
|
||||||
logic pending_stop;
|
|
||||||
logic direction;
|
|
||||||
logic [27:0] length;
|
|
||||||
logic [15:0] rdata_buffer;
|
|
||||||
logic byte_counter;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
bus.rdata = 32'd0;
|
|
||||||
if (bus.ack) begin
|
|
||||||
case (bus.address[3:2])
|
|
||||||
0: bus.rdata = {28'd0, state != S_IDLE, direction, 2'b00};
|
|
||||||
1: bus.rdata = dma.address;
|
|
||||||
2: bus.rdata = {2'b00, dma.id, length};
|
|
||||||
default: bus.rdata = 32'd0;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
|
||||||
bus.ack <= 1'b0;
|
|
||||||
if (bus.request) begin
|
|
||||||
bus.ack <= 1'b1;
|
|
||||||
end
|
|
||||||
|
|
||||||
dma.rx_read <= 1'b0;
|
|
||||||
dma.tx_write <= 1'b0;
|
|
||||||
|
|
||||||
if (sys.reset) begin
|
|
||||||
state <= S_IDLE;
|
|
||||||
pending_stop <= 1'b0;
|
|
||||||
dma.request <= 1'b0;
|
|
||||||
end else begin
|
|
||||||
if (bus.request && bus.address[3:2] == 0 && bus.wmask[0]) begin
|
|
||||||
pending_stop <= bus.wdata[1];
|
|
||||||
end
|
|
||||||
|
|
||||||
case (state)
|
|
||||||
S_IDLE: begin
|
|
||||||
pending_stop <= 1'b0;
|
|
||||||
|
|
||||||
if (bus.request) begin
|
|
||||||
case (bus.address[3:2])
|
|
||||||
0: if (bus.wmask[0]) begin
|
|
||||||
direction <= bus.wdata[2];
|
|
||||||
if (bus.wdata[0]) begin
|
|
||||||
state <= S_FETCH;
|
|
||||||
byte_counter <= 1'b0;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
1: if (&bus.wmask) begin
|
|
||||||
dma.address <= bus.wdata;
|
|
||||||
end
|
|
||||||
|
|
||||||
2: if (&bus.wmask) begin
|
|
||||||
{dma.id, length} <= {bus.wdata[29:1], 1'b0};
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
S_FETCH: begin
|
|
||||||
if (length != 28'd0 && !pending_stop) begin
|
|
||||||
if (direction) begin
|
|
||||||
if (!dma.rx_empty && !dma.rx_read) begin
|
|
||||||
dma.rx_read <= 1'b1;
|
|
||||||
dma.wdata <= {dma.wdata[7:0], dma.rx_rdata};
|
|
||||||
byte_counter <= ~byte_counter;
|
|
||||||
if (byte_counter) begin
|
|
||||||
state <= S_TRANSFER;
|
|
||||||
dma.request <= 1'b1;
|
|
||||||
dma.write <= 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
dma.request <= 1'b1;
|
|
||||||
dma.write <= 1'b0;
|
|
||||||
if (dma.ack) begin
|
|
||||||
state <= S_TRANSFER;
|
|
||||||
dma.request <= 1'b0;
|
|
||||||
rdata_buffer <= dma.rdata;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
state <= S_IDLE;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
S_TRANSFER: begin
|
|
||||||
if (direction) begin
|
|
||||||
if (dma.ack) begin
|
|
||||||
state <= S_FETCH;
|
|
||||||
dma.request <= 1'b0;
|
|
||||||
dma.address <= dma.address + 2'd2;
|
|
||||||
length <= length - 2'd2;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
if (!dma.tx_full && !dma.tx_write) begin
|
|
||||||
dma.tx_write <= 1'b1;
|
|
||||||
dma.tx_wdata <= byte_counter ? rdata_buffer[7:0] : rdata_buffer[15:8];
|
|
||||||
byte_counter <= ~byte_counter;
|
|
||||||
if (byte_counter) begin
|
|
||||||
state <= S_FETCH;
|
|
||||||
dma.address <= dma.address + 2'd2;
|
|
||||||
length <= length - 2'd2;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
default: begin
|
|
||||||
state <= S_IDLE;
|
|
||||||
dma.request <= 1'b0;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
@ -16,7 +16,7 @@ interface if_flash ();
|
|||||||
output wdata
|
output wdata
|
||||||
);
|
);
|
||||||
|
|
||||||
modport memory (
|
modport flash (
|
||||||
input request,
|
input request,
|
||||||
output ack,
|
output ack,
|
||||||
input write,
|
input write,
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
module cpu_gpio (
|
|
||||||
if_system.sys sys,
|
|
||||||
if_cpu_bus bus,
|
|
||||||
|
|
||||||
input [7:0] gpio_i,
|
|
||||||
output [7:0] gpio_o,
|
|
||||||
output [7:0] gpio_oe
|
|
||||||
);
|
|
||||||
|
|
||||||
logic [1:0][7:0] gpio_i_ff;
|
|
||||||
logic [7:0] gpio_o_value;
|
|
||||||
logic [7:0] gpio_oe_value;
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
|
||||||
bus.ack <= 1'b0;
|
|
||||||
if (bus.request) begin
|
|
||||||
bus.ack <= 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
bus.rdata = 32'd0;
|
|
||||||
if (bus.ack) begin
|
|
||||||
bus.rdata = {8'd0, gpio_oe_value, gpio_i_ff[1], gpio_o_value};
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
|
||||||
gpio_i_ff <= {gpio_i_ff[0], gpio_i};
|
|
||||||
gpio_o <= gpio_o_value;
|
|
||||||
gpio_oe <= gpio_oe_value;
|
|
||||||
|
|
||||||
if (sys.reset) begin
|
|
||||||
gpio_o_value <= 8'd0;
|
|
||||||
gpio_oe_value <= 8'd0;
|
|
||||||
end else if (bus.request) begin
|
|
||||||
if (bus.wmask[0]) gpio_o_value <= bus.wdata[7:0];
|
|
||||||
if (bus.wmask[2]) gpio_oe_value <= bus.wdata[23:16];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
endmodule
|
|
@ -1,36 +1,10 @@
|
|||||||
interface if_cpu_ram ();
|
|
||||||
|
|
||||||
logic write;
|
|
||||||
logic [12:0] address;
|
|
||||||
logic [15:0] rdata;
|
|
||||||
logic [15:0] wdata;
|
|
||||||
|
|
||||||
modport cpu (
|
|
||||||
input write,
|
|
||||||
input address,
|
|
||||||
output rdata,
|
|
||||||
input wdata
|
|
||||||
);
|
|
||||||
|
|
||||||
modport external (
|
|
||||||
output write,
|
|
||||||
output address,
|
|
||||||
input rdata,
|
|
||||||
output wdata
|
|
||||||
);
|
|
||||||
|
|
||||||
endinterface
|
|
||||||
|
|
||||||
|
|
||||||
module cpu_ram (
|
module cpu_ram (
|
||||||
if_system.sys sys,
|
if_system.sys sys,
|
||||||
if_cpu_bus bus,
|
if_cpu_bus bus
|
||||||
if_cpu_ram.cpu cpu_ram
|
|
||||||
);
|
);
|
||||||
|
|
||||||
logic [3:0][7:0] ram [0:4095];
|
logic [3:0][7:0] ram [0:8191];
|
||||||
logic [31:0] q_cpu;
|
logic [31:0] q;
|
||||||
logic [31:0] q_external;
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
always_ff @(posedge sys.clk) begin
|
||||||
bus.ack <= 1'b0;
|
bus.ack <= 1'b0;
|
||||||
@ -40,33 +14,19 @@ module cpu_ram (
|
|||||||
end
|
end
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
cpu_ram.rdata = cpu_ram.address[0] ? q_external[31:16] : q_external[15:0];
|
|
||||||
bus.rdata = 32'd0;
|
bus.rdata = 32'd0;
|
||||||
if (bus.ack) begin
|
if (bus.ack) begin
|
||||||
bus.rdata = q_cpu;
|
bus.rdata = q;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
always_ff @(posedge sys.clk) begin
|
||||||
q_cpu <= ram[bus.address[13:2]];
|
q <= ram[bus.address[14:2]];
|
||||||
if (bus.request) begin
|
if (bus.request) begin
|
||||||
if (bus.wmask[0]) ram[bus.address[13:2]][0] <= bus.wdata[7:0];
|
if (bus.wmask[0]) ram[bus.address[14:2]][0] <= bus.wdata[7:0];
|
||||||
if (bus.wmask[1]) ram[bus.address[13:2]][1] <= bus.wdata[15:8];
|
if (bus.wmask[1]) ram[bus.address[14:2]][1] <= bus.wdata[15:8];
|
||||||
if (bus.wmask[2]) ram[bus.address[13:2]][2] <= bus.wdata[23:16];
|
if (bus.wmask[2]) ram[bus.address[14:2]][2] <= bus.wdata[23:16];
|
||||||
if (bus.wmask[3]) ram[bus.address[13:2]][3] <= bus.wdata[31:24];
|
if (bus.wmask[3]) ram[bus.address[14:2]][3] <= bus.wdata[31:24];
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
|
||||||
q_external <= ram[cpu_ram.address[12:1]];
|
|
||||||
if (cpu_ram.write) begin
|
|
||||||
if (cpu_ram.address[0]) begin
|
|
||||||
ram[cpu_ram.address[12:1]][2] <= cpu_ram.wdata[7:0];
|
|
||||||
ram[cpu_ram.address[12:1]][3] <= cpu_ram.wdata[15:8];
|
|
||||||
end else begin
|
|
||||||
ram[cpu_ram.address[12:1]][0] <= cpu_ram.wdata[7:0];
|
|
||||||
ram[cpu_ram.address[12:1]][1] <= cpu_ram.wdata[15:8];
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
module cpu_soc (
|
module cpu_soc (
|
||||||
if_system.sys sys,
|
if_system.sys sys,
|
||||||
if_config.cpu cfg,
|
if_config.cpu cfg,
|
||||||
if_dma dma,
|
if_memory_dma usb_dma,
|
||||||
if_sdram.cpu sdram,
|
if_sdram.cpu sdram,
|
||||||
if_flashram.cpu flashram,
|
if_flashram.cpu flashram,
|
||||||
if_si.cpu si,
|
if_si.cpu si,
|
||||||
if_flash.cpu flash,
|
if_flash flash,
|
||||||
if_dd.cpu dd,
|
if_dd.cpu dd,
|
||||||
if_cpu_ram.cpu cpu_ram,
|
|
||||||
|
|
||||||
input [7:0] gpio_i,
|
|
||||||
output [7:0] gpio_o,
|
|
||||||
output [7:0] gpio_oe,
|
|
||||||
|
|
||||||
output i2c_scl,
|
output i2c_scl,
|
||||||
inout i2c_sda,
|
inout i2c_sda,
|
||||||
@ -19,8 +14,7 @@ module cpu_soc (
|
|||||||
output usb_clk,
|
output usb_clk,
|
||||||
output usb_cs,
|
output usb_cs,
|
||||||
input usb_miso,
|
input usb_miso,
|
||||||
inout [3:0] usb_miosi,
|
inout [7:0] usb_miosi,
|
||||||
input usb_pwren,
|
|
||||||
|
|
||||||
input uart_rxd,
|
input uart_rxd,
|
||||||
output uart_txd,
|
output uart_txd,
|
||||||
@ -30,98 +24,98 @@ module cpu_soc (
|
|||||||
inout [3:0] sd_dat
|
inout [3:0] sd_dat
|
||||||
);
|
);
|
||||||
|
|
||||||
if_cpu_bus bus ();
|
typedef enum bit [3:0] {
|
||||||
|
DEV_FLASH,
|
||||||
|
DEV_RAM,
|
||||||
|
DEV_CFG,
|
||||||
|
DEV_I2C,
|
||||||
|
DEV_USB,
|
||||||
|
DEV_UART,
|
||||||
|
DEV_DD,
|
||||||
|
DEV_SDRAM,
|
||||||
|
DEV_FLASHRAM,
|
||||||
|
DEV_SI,
|
||||||
|
__NUM_DEVICES
|
||||||
|
} e_bus_id;
|
||||||
|
|
||||||
|
if_cpu_bus #(
|
||||||
|
.NUM_DEVICES(__NUM_DEVICES)
|
||||||
|
) bus ();
|
||||||
|
|
||||||
cpu_wrapper cpu_wrapper_inst (
|
cpu_wrapper cpu_wrapper_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus)
|
.bus(bus)
|
||||||
);
|
);
|
||||||
|
|
||||||
cpu_ram cpu_ram_inst (
|
|
||||||
.sys(sys),
|
|
||||||
.bus(bus.at[sc64::ID_CPU_RAM].device),
|
|
||||||
.cpu_ram(cpu_ram)
|
|
||||||
);
|
|
||||||
|
|
||||||
cpu_flash cpu_flash_inst (
|
cpu_flash cpu_flash_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_CPU_FLASH].device),
|
.bus(bus.at[DEV_FLASH].device),
|
||||||
.flash(flash)
|
.flash(flash)
|
||||||
);
|
);
|
||||||
|
|
||||||
cpu_gpio cpu_gpio_inst (
|
cpu_ram cpu_ram_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_CPU_GPIO].device),
|
.bus(bus.at[DEV_RAM].device)
|
||||||
.gpio_i(gpio_i),
|
);
|
||||||
.gpio_o(gpio_o),
|
|
||||||
.gpio_oe(gpio_oe)
|
cpu_cfg cpu_cfg_inst (
|
||||||
|
.sys(sys),
|
||||||
|
.bus(bus.at[DEV_CFG].device),
|
||||||
|
.cfg(cfg)
|
||||||
);
|
);
|
||||||
|
|
||||||
cpu_i2c cpu_i2c_inst (
|
cpu_i2c cpu_i2c_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_CPU_I2C].device),
|
.bus(bus.at[DEV_I2C].device),
|
||||||
.i2c_scl(i2c_scl),
|
.i2c_scl(i2c_scl),
|
||||||
.i2c_sda(i2c_sda)
|
.i2c_sda(i2c_sda)
|
||||||
);
|
);
|
||||||
|
|
||||||
cpu_usb cpu_usb_inst (
|
cpu_usb cpu_usb_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_CPU_USB].device),
|
.bus(bus.at[DEV_USB].device),
|
||||||
.dma(dma.at[sc64::ID_DMA_USB].device),
|
.dma(usb_dma),
|
||||||
.usb_clk(usb_clk),
|
.usb_clk(usb_clk),
|
||||||
.usb_cs(usb_cs),
|
.usb_cs(usb_cs),
|
||||||
.usb_miso(usb_miso),
|
.usb_miso(usb_miso),
|
||||||
.usb_miosi(usb_miosi),
|
.usb_miosi(usb_miosi)
|
||||||
.usb_pwren(usb_pwren)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
generate
|
generate
|
||||||
if (sc64::CPU_HAS_UART) begin
|
if (sc64::CPU_HAS_UART) begin
|
||||||
cpu_uart cpu_uart_inst (
|
cpu_uart cpu_uart_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_CPU_UART].device),
|
.bus(bus.at[DEV_UART].device),
|
||||||
.uart_rxd(uart_rxd),
|
.uart_rxd(uart_rxd),
|
||||||
.uart_txd(uart_txd)
|
.uart_txd(uart_txd)
|
||||||
);
|
);
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
cpu_dma cpu_dma_inst (
|
cpu_dd cpu_dd_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_CPU_DMA].device),
|
.bus(bus.at[DEV_DD].device),
|
||||||
.dma(dma)
|
.dd(dd)
|
||||||
);
|
|
||||||
|
|
||||||
cpu_cfg cpu_cfg_inst (
|
|
||||||
.sys(sys),
|
|
||||||
.bus(bus.at[sc64::ID_CPU_CFG].device),
|
|
||||||
.cfg(cfg)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
cpu_sdram cpu_sdram_inst (
|
cpu_sdram cpu_sdram_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_CPU_SDRAM].device),
|
.bus(bus.at[DEV_SDRAM].device),
|
||||||
.sdram(sdram)
|
.sdram(sdram)
|
||||||
);
|
);
|
||||||
|
|
||||||
cpu_flashram cpu_flashram_inst (
|
cpu_flashram cpu_flashram_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_CPU_FLASHRAM].device),
|
.bus(bus.at[DEV_FLASHRAM].device),
|
||||||
.flashram(flashram)
|
.flashram(flashram)
|
||||||
);
|
);
|
||||||
|
|
||||||
cpu_si cpu_si_inst (
|
cpu_si cpu_si_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_CPU_SI].device),
|
.bus(bus.at[DEV_SI].device),
|
||||||
.si(si)
|
.si(si)
|
||||||
);
|
);
|
||||||
|
|
||||||
cpu_dd cpu_dd_inst (
|
|
||||||
.sys(sys),
|
|
||||||
.bus(bus.at[sc64::ID_CPU_DD].device),
|
|
||||||
.dd(dd)
|
|
||||||
);
|
|
||||||
|
|
||||||
assign sd_clk = 1'bZ;
|
assign sd_clk = 1'bZ;
|
||||||
assign sd_cmd = 1'bZ;
|
assign sd_cmd = 1'bZ;
|
||||||
assign sd_dat = 4'bZZZZ;
|
assign sd_dat = 4'bZZZZ;
|
||||||
|
@ -1,44 +1,27 @@
|
|||||||
module cpu_usb (
|
module cpu_usb (
|
||||||
if_system sys,
|
if_system sys,
|
||||||
if_cpu_bus bus,
|
if_cpu_bus bus,
|
||||||
if_dma dma,
|
if_memory_dma dma,
|
||||||
|
|
||||||
output usb_clk,
|
output usb_clk,
|
||||||
output usb_cs,
|
output usb_cs,
|
||||||
input usb_miso,
|
input usb_miso,
|
||||||
inout [3:0] usb_miosi,
|
inout [7:0] usb_miosi
|
||||||
input usb_pwren
|
|
||||||
);
|
);
|
||||||
|
|
||||||
logic rx_flush;
|
logic rx_flush;
|
||||||
logic rx_empty;
|
|
||||||
logic rx_read;
|
|
||||||
logic [7:0] rx_rdata;
|
|
||||||
|
|
||||||
logic tx_flush;
|
logic tx_flush;
|
||||||
logic tx_full;
|
logic usb_enable;
|
||||||
logic tx_write;
|
logic reset_pending;
|
||||||
logic [7:0] tx_wdata;
|
logic reset_ack;
|
||||||
|
logic write_buffer_flush;
|
||||||
|
|
||||||
logic rx_escape_valid;
|
typedef enum bit [1:0] {
|
||||||
logic rx_escape_ack;
|
R_SCR,
|
||||||
logic [7:0] rx_escape;
|
R_DATA,
|
||||||
|
R_ADDR,
|
||||||
logic cpu_rx_read;
|
R_LEN
|
||||||
logic cpu_tx_write;
|
} e_reg_id;
|
||||||
|
|
||||||
logic usb_enabled;
|
|
||||||
logic tx_force;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
dma.rx_empty = rx_empty;
|
|
||||||
rx_read = cpu_rx_read || dma.rx_read;
|
|
||||||
dma.rx_rdata = rx_rdata;
|
|
||||||
|
|
||||||
dma.tx_full = tx_full;
|
|
||||||
tx_write = cpu_tx_write || dma.tx_write;
|
|
||||||
tx_wdata = dma.tx_write ? dma.tx_wdata : bus.wdata[7:0];
|
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
always_ff @(posedge sys.clk) begin
|
||||||
bus.ack <= 1'b0;
|
bus.ack <= 1'b0;
|
||||||
@ -51,75 +34,93 @@ module cpu_usb (
|
|||||||
bus.rdata = 32'd0;
|
bus.rdata = 32'd0;
|
||||||
if (bus.ack) begin
|
if (bus.ack) begin
|
||||||
case (bus.address[3:2])
|
case (bus.address[3:2])
|
||||||
0: bus.rdata = {25'd0, rx_escape_valid, usb_pwren, usb_enabled, 2'b00, ~tx_full, ~rx_empty};
|
R_SCR: bus.rdata = {
|
||||||
1: bus.rdata = {24'd0, rx_rdata};
|
23'd0,
|
||||||
2: bus.rdata = {24'd0, rx_escape};
|
dma.busy,
|
||||||
|
1'b0,
|
||||||
|
reset_pending,
|
||||||
|
1'b0,
|
||||||
|
usb_enable,
|
||||||
|
2'b00,
|
||||||
|
~dma.tx_full,
|
||||||
|
~dma.rx_empty
|
||||||
|
};
|
||||||
|
R_DATA: bus.rdata = {24'd0, dma.rx_rdata};
|
||||||
default: bus.rdata = 32'd0;
|
default: bus.rdata = 32'd0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
always_ff @(posedge sys.clk) begin
|
||||||
|
dma.start <= 1'b0;
|
||||||
|
dma.stop <= 1'b0;
|
||||||
|
dma.cpu_rx_read <= 1'b0;
|
||||||
|
dma.cpu_tx_write <= 1'b0;
|
||||||
rx_flush <= 1'b0;
|
rx_flush <= 1'b0;
|
||||||
cpu_rx_read <= 1'b0;
|
|
||||||
|
|
||||||
tx_flush <= 1'b0;
|
tx_flush <= 1'b0;
|
||||||
cpu_tx_write <= 1'b0;
|
reset_ack <= 1'b0;
|
||||||
|
write_buffer_flush <= 1'b0;
|
||||||
rx_escape_ack <= 1'b0;
|
|
||||||
tx_force <= 1'b0;
|
|
||||||
|
|
||||||
if (sys.reset) begin
|
if (sys.reset) begin
|
||||||
usb_enabled <= 1'b0;
|
usb_enable <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
if (bus.request) begin
|
if (bus.request) begin
|
||||||
case (bus.address[2:2])
|
case (bus.address[3:2])
|
||||||
2'd0: begin
|
R_SCR: if (&bus.wmask) begin
|
||||||
if (bus.wmask[1]) begin
|
{dma.direction, dma.stop, dma.start} <= bus.wdata[11:9];
|
||||||
tx_force <= bus.wdata[8];
|
reset_ack <= bus.wdata[7];
|
||||||
end
|
{write_buffer_flush, usb_enable, tx_flush, rx_flush} <= bus.wdata[5:2];
|
||||||
if (bus.wmask[0]) begin
|
|
||||||
rx_escape_ack <= bus.wdata[7];
|
|
||||||
{usb_enabled, tx_flush, rx_flush} <= bus.wdata[4:2];
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
2'd1: begin
|
R_DATA: if (bus.wmask == 4'b0000) begin
|
||||||
if (bus.wmask[0]) begin
|
dma.cpu_rx_read <= 1'b1;
|
||||||
cpu_tx_write <= 1'b1;
|
end else if (bus.wmask == 4'b0001) begin
|
||||||
end else begin
|
dma.cpu_tx_write <= 1'b1;
|
||||||
cpu_rx_read <= 1'b1;
|
dma.cpu_tx_wdata <= bus.wdata[7:0];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
R_ADDR: if (&bus.wmask) begin
|
||||||
|
dma.starting_address <= bus.wdata;
|
||||||
|
end
|
||||||
|
|
||||||
|
R_LEN: if (&bus.wmask) begin
|
||||||
|
dma.transfer_length <= bus.wdata;
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
usb_ft1248 usb_ft1248_inst (
|
memory_dma usb_memory_dma_inst (
|
||||||
.sys(sys),
|
.clk(sys.clk),
|
||||||
|
.reset(~usb_enable),
|
||||||
|
.dma(dma)
|
||||||
|
);
|
||||||
|
|
||||||
.usb_enabled(usb_enabled),
|
usb_ft1248 usb_ft1248_inst (
|
||||||
.tx_force(tx_force),
|
.clk(sys.clk),
|
||||||
|
.reset(~usb_enable),
|
||||||
|
|
||||||
.usb_clk(usb_clk),
|
.usb_clk(usb_clk),
|
||||||
.usb_cs(usb_cs),
|
.usb_cs(usb_cs),
|
||||||
.usb_miso(usb_miso),
|
.usb_miso(usb_miso),
|
||||||
.usb_miosi(usb_miosi),
|
.usb_miosi(usb_miosi),
|
||||||
|
|
||||||
|
.reset_pending(reset_pending),
|
||||||
|
.reset_ack(reset_ack),
|
||||||
|
.write_buffer_flush(write_buffer_flush),
|
||||||
|
|
||||||
.rx_flush(rx_flush),
|
.rx_flush(rx_flush),
|
||||||
.rx_empty(rx_empty),
|
.rx_empty(dma.rx_empty),
|
||||||
.rx_read(rx_read),
|
.rx_almost_empty(dma.rx_almost_empty),
|
||||||
.rx_rdata(rx_rdata),
|
.rx_read(dma.rx_read),
|
||||||
|
.rx_rdata(dma.rx_rdata),
|
||||||
|
|
||||||
.tx_flush(tx_flush),
|
.tx_flush(tx_flush),
|
||||||
.tx_full(tx_full),
|
.tx_full(dma.tx_full),
|
||||||
.tx_write(tx_write),
|
.tx_almost_full(dma.tx_almost_full),
|
||||||
.tx_wdata(tx_wdata),
|
.tx_write(dma.tx_write),
|
||||||
|
.tx_wdata(dma.tx_wdata)
|
||||||
.rx_escape_valid(rx_escape_valid),
|
|
||||||
.rx_escape_ack(rx_escape_ack),
|
|
||||||
.rx_escape(rx_escape)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -28,12 +28,29 @@ module cpu_wrapper (
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
logic trap;
|
||||||
|
logic mem_valid;
|
||||||
|
logic mem_instr;
|
||||||
|
logic [31:0] mem_la_addr;
|
||||||
|
logic [31:0] mem_la_wdata;
|
||||||
|
logic [3:0] mem_la_wstrb;
|
||||||
|
logic pcpi_valid;
|
||||||
|
logic [31:0] pcpi_insn;
|
||||||
|
logic [31:0] pcpi_rs1;
|
||||||
|
logic [31:0] pcpi_rs2;
|
||||||
|
logic [31:0] eoi;
|
||||||
|
logic trace_valid;
|
||||||
|
logic [35:0] trace_data;
|
||||||
|
|
||||||
picorv32 #(
|
picorv32 #(
|
||||||
.ENABLE_COUNTERS(0),
|
.ENABLE_COUNTERS(0),
|
||||||
.ENABLE_COUNTERS64(0),
|
.ENABLE_COUNTERS64(0),
|
||||||
|
.TWO_STAGE_SHIFT(0),
|
||||||
|
.TWO_CYCLE_COMPARE(1),
|
||||||
|
.TWO_CYCLE_ALU(1),
|
||||||
.CATCH_MISALIGN(0),
|
.CATCH_MISALIGN(0),
|
||||||
.CATCH_ILLINSN(0),
|
.CATCH_ILLINSN(0),
|
||||||
.PROGADDR_RESET(sc64::CPU_RESET_VECTOR)
|
.PROGADDR_RESET(32'h0001_0000)
|
||||||
) cpu_inst (
|
) cpu_inst (
|
||||||
.clk(sys.clk),
|
.clk(sys.clk),
|
||||||
.resetn(~sys.reset),
|
.resetn(~sys.reset),
|
||||||
@ -43,7 +60,26 @@ module cpu_wrapper (
|
|||||||
.mem_ready(bus.ack),
|
.mem_ready(bus.ack),
|
||||||
.mem_rdata(bus.rdata),
|
.mem_rdata(bus.rdata),
|
||||||
.mem_la_read(mem_la_read),
|
.mem_la_read(mem_la_read),
|
||||||
.mem_la_write(mem_la_write)
|
.mem_la_write(mem_la_write),
|
||||||
|
|
||||||
|
.trap(trap),
|
||||||
|
.mem_valid(mem_valid),
|
||||||
|
.mem_instr(mem_instr),
|
||||||
|
.mem_la_addr(mem_la_addr),
|
||||||
|
.mem_la_wdata(mem_la_wdata),
|
||||||
|
.mem_la_wstrb(mem_la_wstrb),
|
||||||
|
.pcpi_valid(pcpi_valid),
|
||||||
|
.pcpi_insn(pcpi_insn),
|
||||||
|
.pcpi_rs1(pcpi_rs1),
|
||||||
|
.pcpi_rs2(pcpi_rs2),
|
||||||
|
.pcpi_wr(1'b0),
|
||||||
|
.pcpi_rd(32'd0),
|
||||||
|
.pcpi_wait(1'b0),
|
||||||
|
.pcpi_ready(1'b0),
|
||||||
|
.irq(32'd0),
|
||||||
|
.eoi(eoi),
|
||||||
|
.trace_valid(trace_valid),
|
||||||
|
.trace_data(trace_data)
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// scfifo
|
// scfifo
|
||||||
//
|
//
|
||||||
// Simulation Library Files(s):
|
// Simulation Library Files(s):
|
||||||
//
|
// altera_mf
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// ************************************************************
|
// ************************************************************
|
||||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||||
@ -43,6 +43,8 @@ module intel_fifo_8 (
|
|||||||
rdreq,
|
rdreq,
|
||||||
sclr,
|
sclr,
|
||||||
wrreq,
|
wrreq,
|
||||||
|
almost_empty,
|
||||||
|
almost_full,
|
||||||
empty,
|
empty,
|
||||||
full,
|
full,
|
||||||
q);
|
q);
|
||||||
@ -52,16 +54,22 @@ module intel_fifo_8 (
|
|||||||
input rdreq;
|
input rdreq;
|
||||||
input sclr;
|
input sclr;
|
||||||
input wrreq;
|
input wrreq;
|
||||||
|
output almost_empty;
|
||||||
|
output almost_full;
|
||||||
output empty;
|
output empty;
|
||||||
output full;
|
output full;
|
||||||
output [7:0] q;
|
output [7:0] q;
|
||||||
|
|
||||||
wire sub_wire0;
|
wire sub_wire0;
|
||||||
wire sub_wire1;
|
wire sub_wire1;
|
||||||
wire [7:0] sub_wire2;
|
wire sub_wire2;
|
||||||
wire empty = sub_wire0;
|
wire sub_wire3;
|
||||||
wire full = sub_wire1;
|
wire [7:0] sub_wire4;
|
||||||
wire [7:0] q = sub_wire2[7:0];
|
wire almost_empty = sub_wire0;
|
||||||
|
wire almost_full = sub_wire1;
|
||||||
|
wire empty = sub_wire2;
|
||||||
|
wire full = sub_wire3;
|
||||||
|
wire [7:0] q = sub_wire4[7:0];
|
||||||
|
|
||||||
scfifo scfifo_component (
|
scfifo scfifo_component (
|
||||||
.clock (clock),
|
.clock (clock),
|
||||||
@ -69,16 +77,18 @@ module intel_fifo_8 (
|
|||||||
.rdreq (rdreq),
|
.rdreq (rdreq),
|
||||||
.sclr (sclr),
|
.sclr (sclr),
|
||||||
.wrreq (wrreq),
|
.wrreq (wrreq),
|
||||||
.empty (sub_wire0),
|
.almost_empty (sub_wire0),
|
||||||
.full (sub_wire1),
|
.almost_full (sub_wire1),
|
||||||
.q (sub_wire2),
|
.empty (sub_wire2),
|
||||||
|
.full (sub_wire3),
|
||||||
|
.q (sub_wire4),
|
||||||
.aclr (),
|
.aclr (),
|
||||||
.almost_empty (),
|
|
||||||
.almost_full (),
|
|
||||||
.eccstatus (),
|
.eccstatus (),
|
||||||
.usedw ());
|
.usedw ());
|
||||||
defparam
|
defparam
|
||||||
scfifo_component.add_ram_output_register = "ON",
|
scfifo_component.add_ram_output_register = "OFF",
|
||||||
|
scfifo_component.almost_empty_value = 2,
|
||||||
|
scfifo_component.almost_full_value = 1023,
|
||||||
scfifo_component.intended_device_family = "MAX 10",
|
scfifo_component.intended_device_family = "MAX 10",
|
||||||
scfifo_component.lpm_numwords = 1024,
|
scfifo_component.lpm_numwords = 1024,
|
||||||
scfifo_component.lpm_showahead = "ON",
|
scfifo_component.lpm_showahead = "ON",
|
||||||
@ -95,10 +105,10 @@ endmodule
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
// CNX file retrieval info
|
// CNX file retrieval info
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
|
// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "1"
|
||||||
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
|
// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "2"
|
||||||
// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
|
// Retrieval info: PRIVATE: AlmostFull NUMERIC "1"
|
||||||
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
|
// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "1023"
|
||||||
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "1"
|
// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "1"
|
||||||
// Retrieval info: PRIVATE: Clock NUMERIC "0"
|
// Retrieval info: PRIVATE: Clock NUMERIC "0"
|
||||||
// Retrieval info: PRIVATE: Depth NUMERIC "1024"
|
// Retrieval info: PRIVATE: Depth NUMERIC "1024"
|
||||||
@ -109,7 +119,7 @@ endmodule
|
|||||||
// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
|
// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
|
||||||
// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
|
// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
|
||||||
// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
|
// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
|
||||||
// Retrieval info: PRIVATE: Optimize NUMERIC "1"
|
// Retrieval info: PRIVATE: Optimize NUMERIC "2"
|
||||||
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
|
||||||
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
|
||||||
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
|
// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
|
||||||
@ -128,7 +138,9 @@ endmodule
|
|||||||
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
|
// Retrieval info: PRIVATE: wsFull NUMERIC "1"
|
||||||
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
|
// Retrieval info: PRIVATE: wsUsedW NUMERIC "0"
|
||||||
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
|
||||||
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "ON"
|
// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "OFF"
|
||||||
|
// Retrieval info: CONSTANT: ALMOST_EMPTY_VALUE NUMERIC "2"
|
||||||
|
// Retrieval info: CONSTANT: ALMOST_FULL_VALUE NUMERIC "1023"
|
||||||
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
|
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
|
||||||
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
|
// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "1024"
|
||||||
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
|
// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
|
||||||
@ -138,6 +150,8 @@ endmodule
|
|||||||
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
|
// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
|
||||||
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
|
// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
|
||||||
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
|
// Retrieval info: CONSTANT: USE_EAB STRING "ON"
|
||||||
|
// Retrieval info: USED_PORT: almost_empty 0 0 0 0 OUTPUT NODEFVAL "almost_empty"
|
||||||
|
// Retrieval info: USED_PORT: almost_full 0 0 0 0 OUTPUT NODEFVAL "almost_full"
|
||||||
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
|
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL "clock"
|
||||||
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
|
// Retrieval info: USED_PORT: data 0 0 8 0 INPUT NODEFVAL "data[7..0]"
|
||||||
// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty"
|
// Retrieval info: USED_PORT: empty 0 0 0 0 OUTPUT NODEFVAL "empty"
|
||||||
@ -151,6 +165,8 @@ endmodule
|
|||||||
// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 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: @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: @wrreq 0 0 0 0 wrreq 0 0 0 0
|
||||||
|
// Retrieval info: CONNECT: almost_empty 0 0 0 0 @almost_empty 0 0 0 0
|
||||||
|
// Retrieval info: CONNECT: almost_full 0 0 0 0 @almost_full 0 0 0 0
|
||||||
// Retrieval info: CONNECT: empty 0 0 0 0 @empty 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: full 0 0 0 0 @full 0 0 0 0
|
||||||
// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
|
// Retrieval info: CONNECT: q 0 0 8 0 @q 0 0 8 0
|
||||||
@ -160,3 +176,4 @@ endmodule
|
|||||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8.bsf FALSE
|
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8.bsf FALSE
|
||||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8_inst.v FALSE
|
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8_inst.v FALSE
|
||||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8_bb.v FALSE
|
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8_bb.v FALSE
|
||||||
|
// Retrieval info: LIB_FILE: altera_mf
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// altpll
|
// altpll
|
||||||
//
|
//
|
||||||
// Simulation Library Files(s):
|
// Simulation Library Files(s):
|
||||||
//
|
// altera_mf
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// ************************************************************
|
// ************************************************************
|
||||||
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
|
||||||
@ -337,4 +337,5 @@ endmodule
|
|||||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll.bsf FALSE
|
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll.bsf FALSE
|
||||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_inst.v FALSE
|
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_inst.v FALSE
|
||||||
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_bb.v FALSE
|
// Retrieval info: GEN_FILE: TYPE_NORMAL intel_pll_bb.v FALSE
|
||||||
|
// Retrieval info: LIB_FILE: altera_mf
|
||||||
// Retrieval info: CBX_MODULE_PREFIX: ON
|
// Retrieval info: CBX_MODULE_PREFIX: ON
|
||||||
|
237
fw/rtl/memory/memory_dma.sv
Normal file
237
fw/rtl/memory/memory_dma.sv
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
interface if_memory_dma ();
|
||||||
|
|
||||||
|
logic request;
|
||||||
|
logic ack;
|
||||||
|
logic write;
|
||||||
|
logic [1:0] wmask;
|
||||||
|
logic [31:0] address;
|
||||||
|
logic [15:0] rdata;
|
||||||
|
logic [15:0] wdata;
|
||||||
|
|
||||||
|
logic start;
|
||||||
|
logic stop;
|
||||||
|
logic busy;
|
||||||
|
logic direction;
|
||||||
|
logic [31:0] transfer_length;
|
||||||
|
logic [31:0] starting_address;
|
||||||
|
|
||||||
|
logic dma_rx_read;
|
||||||
|
logic dma_tx_write;
|
||||||
|
logic [7:0] dma_tx_wdata;
|
||||||
|
|
||||||
|
logic cpu_rx_read;
|
||||||
|
logic cpu_tx_write;
|
||||||
|
logic [7:0] cpu_tx_wdata;
|
||||||
|
|
||||||
|
logic rx_empty;
|
||||||
|
logic rx_almost_empty;
|
||||||
|
logic rx_read;
|
||||||
|
logic [7:0] rx_rdata;
|
||||||
|
|
||||||
|
logic tx_full;
|
||||||
|
logic tx_almost_full;
|
||||||
|
logic tx_write;
|
||||||
|
logic [7:0] tx_wdata;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
rx_read = dma_rx_read || cpu_rx_read;
|
||||||
|
tx_write = dma_tx_write || cpu_tx_write;
|
||||||
|
tx_wdata = cpu_tx_write ? cpu_tx_wdata : dma_tx_wdata;
|
||||||
|
end
|
||||||
|
|
||||||
|
modport dma (
|
||||||
|
input start,
|
||||||
|
input stop,
|
||||||
|
output busy,
|
||||||
|
input direction,
|
||||||
|
input transfer_length,
|
||||||
|
input starting_address,
|
||||||
|
|
||||||
|
output request,
|
||||||
|
input ack,
|
||||||
|
output write,
|
||||||
|
output wmask,
|
||||||
|
output address,
|
||||||
|
input rdata,
|
||||||
|
output wdata,
|
||||||
|
|
||||||
|
input rx_empty,
|
||||||
|
input rx_almost_empty,
|
||||||
|
output dma_rx_read,
|
||||||
|
input rx_rdata,
|
||||||
|
|
||||||
|
input tx_full,
|
||||||
|
input tx_almost_full,
|
||||||
|
output dma_tx_write,
|
||||||
|
output dma_tx_wdata
|
||||||
|
);
|
||||||
|
|
||||||
|
modport cpu (
|
||||||
|
output start,
|
||||||
|
output stop,
|
||||||
|
input busy,
|
||||||
|
output direction,
|
||||||
|
output transfer_length,
|
||||||
|
output starting_address,
|
||||||
|
|
||||||
|
input rx_empty,
|
||||||
|
output cpu_rx_read,
|
||||||
|
input rx_rdata,
|
||||||
|
|
||||||
|
input tx_full,
|
||||||
|
output cpu_tx_write,
|
||||||
|
output cpu_tx_wdata
|
||||||
|
);
|
||||||
|
|
||||||
|
modport memory (
|
||||||
|
input request,
|
||||||
|
output ack,
|
||||||
|
input write,
|
||||||
|
input wmask,
|
||||||
|
input address,
|
||||||
|
output rdata,
|
||||||
|
input wdata
|
||||||
|
);
|
||||||
|
|
||||||
|
modport device (
|
||||||
|
output rx_empty,
|
||||||
|
output rx_almost_empty,
|
||||||
|
input rx_read,
|
||||||
|
output rx_rdata,
|
||||||
|
|
||||||
|
output tx_full,
|
||||||
|
output tx_almost_full,
|
||||||
|
input tx_write,
|
||||||
|
input tx_wdata
|
||||||
|
);
|
||||||
|
|
||||||
|
endinterface
|
||||||
|
|
||||||
|
|
||||||
|
module memory_dma (
|
||||||
|
input clk,
|
||||||
|
input reset,
|
||||||
|
if_memory_dma.dma dma
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef enum bit [0:0] {
|
||||||
|
STATE_FETCH,
|
||||||
|
STATE_TRANSFER
|
||||||
|
} e_state;
|
||||||
|
|
||||||
|
logic [31:0] remaining;
|
||||||
|
logic [15:0] data_buffer;
|
||||||
|
logic byte_counter;
|
||||||
|
e_state state;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
dma.dma_rx_read <= 1'b0;
|
||||||
|
dma.dma_tx_write <= 1'b0;
|
||||||
|
|
||||||
|
if (dma.dma_rx_read) begin
|
||||||
|
if (dma.address[0] || (remaining == 32'd1)) begin
|
||||||
|
dma.wdata <= {dma.rx_rdata, dma.rx_rdata};
|
||||||
|
end else begin
|
||||||
|
dma.wdata <= {dma.wdata[7:0], dma.rx_rdata};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (reset) begin
|
||||||
|
dma.busy <= 1'b0;
|
||||||
|
dma.request <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if (!dma.busy) begin
|
||||||
|
if (dma.start) begin
|
||||||
|
dma.busy <= 1'b1;
|
||||||
|
dma.write <= dma.direction;
|
||||||
|
dma.address <= dma.starting_address;
|
||||||
|
remaining <= dma.transfer_length;
|
||||||
|
byte_counter <= 1'd0;
|
||||||
|
state <= STATE_FETCH;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
if (dma.stop) begin
|
||||||
|
dma.busy <= 1'b0;
|
||||||
|
dma.request <= 1'b0;
|
||||||
|
end else if (remaining != 32'd0) begin
|
||||||
|
if (dma.write) begin
|
||||||
|
case (state)
|
||||||
|
STATE_FETCH: begin
|
||||||
|
if (!dma.rx_empty && !(dma.dma_rx_read && dma.rx_almost_empty)) begin
|
||||||
|
dma.dma_rx_read <= 1'b1;
|
||||||
|
if (dma.address[0]) begin
|
||||||
|
dma.wmask <= 2'b01;
|
||||||
|
state <= STATE_TRANSFER;
|
||||||
|
end else if (remaining == 32'd1) begin
|
||||||
|
dma.wmask <= 2'b10;
|
||||||
|
state <= STATE_TRANSFER;
|
||||||
|
end else begin
|
||||||
|
byte_counter <= byte_counter + 1'd1;
|
||||||
|
if (byte_counter) begin
|
||||||
|
dma.wmask <= 2'b11;
|
||||||
|
state <= STATE_TRANSFER;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_TRANSFER: begin
|
||||||
|
dma.request <= 1'b1;
|
||||||
|
if (dma.ack) begin
|
||||||
|
dma.request <= 1'b0;
|
||||||
|
if (dma.wmask != 2'b11) begin
|
||||||
|
dma.address <= dma.address + 1'd1;
|
||||||
|
remaining <= remaining - 1'd1;
|
||||||
|
end else begin
|
||||||
|
dma.address <= dma.address + 2'd2;
|
||||||
|
remaining <= remaining - 2'd2;
|
||||||
|
end
|
||||||
|
state <= STATE_FETCH;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end else begin
|
||||||
|
case (state)
|
||||||
|
STATE_FETCH: begin
|
||||||
|
dma.request <= 1'b1;
|
||||||
|
if (dma.ack) begin
|
||||||
|
dma.request <= 1'b0;
|
||||||
|
data_buffer <= dma.rdata;
|
||||||
|
state <= STATE_TRANSFER;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_TRANSFER: begin
|
||||||
|
if (!dma.tx_full && !(dma.dma_tx_write && dma.tx_almost_full)) begin
|
||||||
|
dma.dma_tx_write <= 1'b1;
|
||||||
|
if (dma.address[0]) begin
|
||||||
|
dma.address <= dma.address + 1'd1;
|
||||||
|
remaining <= remaining - 1'd1;
|
||||||
|
dma.dma_tx_wdata <= data_buffer[7:0];
|
||||||
|
state <= STATE_FETCH;
|
||||||
|
end else if (remaining == 32'd1) begin
|
||||||
|
dma.address <= dma.address + 1'd1;
|
||||||
|
remaining <= remaining - 1'd1;
|
||||||
|
dma.dma_tx_wdata <= data_buffer[15:8];
|
||||||
|
state <= STATE_FETCH;
|
||||||
|
end else begin
|
||||||
|
dma.dma_tx_wdata <= byte_counter ? data_buffer[7:0] : data_buffer[15:8];
|
||||||
|
byte_counter <= byte_counter + 1'd1;
|
||||||
|
if (byte_counter) begin
|
||||||
|
dma.address <= dma.address + 2'd2;
|
||||||
|
remaining <= remaining - 2'd2;
|
||||||
|
state <= STATE_FETCH;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
dma.busy <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -1,20 +1,10 @@
|
|||||||
module n64_bootloader (
|
module n64_bootloader (
|
||||||
if_system.sys sys,
|
if_system.sys sys,
|
||||||
if_n64_bus bus,
|
if_n64_bus bus,
|
||||||
if_flash.memory flash
|
if_config.flash cfg,
|
||||||
|
if_flash.flash flash
|
||||||
);
|
);
|
||||||
|
|
||||||
logic mem_request;
|
|
||||||
logic csr_ack;
|
|
||||||
logic data_ack;
|
|
||||||
logic write_ack;
|
|
||||||
logic data_busy;
|
|
||||||
logic mem_write;
|
|
||||||
logic [31:0] mem_address;
|
|
||||||
logic [31:0] csr_rdata;
|
|
||||||
logic [31:0] data_rdata;
|
|
||||||
logic [31:0] mem_wdata;
|
|
||||||
|
|
||||||
typedef enum bit [0:0] {
|
typedef enum bit [0:0] {
|
||||||
S_IDLE,
|
S_IDLE,
|
||||||
S_WAIT
|
S_WAIT
|
||||||
@ -28,97 +18,77 @@ module n64_bootloader (
|
|||||||
e_state state;
|
e_state state;
|
||||||
e_source_request source_request;
|
e_source_request source_request;
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
logic request;
|
||||||
csr_ack <= 1'b0;
|
logic ack;
|
||||||
write_ack <= 1'b0;
|
logic write;
|
||||||
|
logic [31:0] address;
|
||||||
|
logic [31:0] wdata;
|
||||||
|
logic [31:0] rdata;
|
||||||
|
|
||||||
|
always_ff @(posedge sys.clk) begin
|
||||||
if (sys.reset) begin
|
if (sys.reset) begin
|
||||||
state <= S_IDLE;
|
state <= S_IDLE;
|
||||||
mem_request <= 1'b0;
|
request <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
case (state)
|
case (state)
|
||||||
S_IDLE: begin
|
S_IDLE: begin
|
||||||
if (bus.request || flash.request) begin
|
if (bus.request || flash.request) begin
|
||||||
state <= S_WAIT;
|
state <= S_WAIT;
|
||||||
mem_request <= 1'b1;
|
request <= 1'b1;
|
||||||
if (bus.request) begin
|
if (bus.request) begin
|
||||||
mem_write <= 1'b0;
|
write <= 1'b0;
|
||||||
mem_address <= bus.address;
|
address <= bus.address;
|
||||||
mem_wdata <= bus.wdata;
|
wdata <= bus.wdata;
|
||||||
source_request <= T_N64;
|
source_request <= T_N64;
|
||||||
end else if (flash.request) begin
|
end else if (flash.request) begin
|
||||||
mem_write <= flash.write;
|
write <= flash.write;
|
||||||
mem_address <= flash.address;
|
address <= flash.address;
|
||||||
mem_wdata <= flash.wdata;
|
wdata <= flash.wdata;
|
||||||
source_request <= T_CPU;
|
source_request <= T_CPU;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
S_WAIT: begin
|
S_WAIT: begin
|
||||||
if (mem_address[27] && source_request != T_N64 && !csr_ack) begin
|
if (ack) begin
|
||||||
mem_request <= 1'b0;
|
|
||||||
csr_ack <= 1'b1;
|
|
||||||
end
|
|
||||||
if ((!mem_address[27] || source_request == T_N64) && !data_busy) begin
|
|
||||||
mem_request <= 1'b0;
|
|
||||||
end
|
|
||||||
if (!mem_address[27] && mem_write && !data_busy && !write_ack) begin
|
|
||||||
write_ack <= 1'b1;
|
|
||||||
end
|
|
||||||
if (csr_ack || data_ack || write_ack) begin
|
|
||||||
state <= S_IDLE;
|
state <= S_IDLE;
|
||||||
|
request <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
logic csr_or_data;
|
|
||||||
logic csr_read;
|
|
||||||
logic csr_write;
|
|
||||||
logic data_read;
|
|
||||||
logic data_write;
|
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
csr_or_data = mem_address[27] && source_request == T_CPU;
|
bus.ack = source_request == T_N64 && ack;
|
||||||
csr_read = csr_or_data && mem_request && !mem_write;
|
|
||||||
csr_write = csr_or_data && mem_request && mem_write;
|
|
||||||
data_read = !csr_or_data && mem_request && !mem_write;
|
|
||||||
data_write = !csr_or_data && mem_request && mem_write;
|
|
||||||
|
|
||||||
bus.ack = source_request == T_N64 && data_ack;
|
|
||||||
bus.rdata = 16'd0;
|
bus.rdata = 16'd0;
|
||||||
if (bus.ack && bus.address < 32'h00010000) begin
|
if (bus.ack && bus.address < 32'h00010000) begin
|
||||||
if (bus.address[1]) bus.rdata = {data_rdata[23:16], data_rdata[31:24]};
|
if (bus.address[1]) bus.rdata = {rdata[23:16], rdata[31:24]};
|
||||||
else bus.rdata = {data_rdata[7:0], data_rdata[15:8]};
|
else bus.rdata = {rdata[7:0], rdata[15:8]};
|
||||||
end
|
end
|
||||||
|
|
||||||
flash.ack = source_request == T_CPU && (csr_ack || data_ack || write_ack);
|
flash.ack = source_request == T_CPU && ack;
|
||||||
flash.rdata = 32'd0;
|
flash.rdata = 32'd0;
|
||||||
if (flash.ack) begin
|
if (flash.ack) begin
|
||||||
flash.rdata = csr_or_data ? csr_rdata : data_rdata;
|
flash.rdata = rdata;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
intel_flash intel_flash_inst (
|
vendor_flash vendor_flash_inst (
|
||||||
.clock(sys.clk),
|
.clk(sys.clk),
|
||||||
.reset_n(~sys.reset),
|
.reset(sys.reset),
|
||||||
|
|
||||||
.avmm_csr_addr(mem_address[2]),
|
.erase_start(cfg.flash_erase_start),
|
||||||
.avmm_csr_read(csr_read),
|
.erase_busy(cfg.flash_erase_busy),
|
||||||
.avmm_csr_writedata(mem_wdata),
|
.wp_enable(cfg.flash_wp_enable),
|
||||||
.avmm_csr_write(csr_write),
|
.wp_disable(cfg.flash_wp_disable),
|
||||||
.avmm_csr_readdata(csr_rdata),
|
|
||||||
|
|
||||||
.avmm_data_addr(mem_address[31:2]),
|
.request(request),
|
||||||
.avmm_data_read(data_read),
|
.ack(ack),
|
||||||
.avmm_data_writedata(mem_wdata),
|
.write(write),
|
||||||
.avmm_data_write(data_write),
|
.address(address),
|
||||||
.avmm_data_readdata(data_rdata),
|
.wdata(wdata),
|
||||||
.avmm_data_waitrequest(data_busy),
|
.rdata(rdata)
|
||||||
.avmm_data_readdatavalid(data_ack),
|
|
||||||
.avmm_data_burstcount(2'd1)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
module n64_cfg (
|
module n64_cfg (
|
||||||
if_system sys,
|
if_system sys,
|
||||||
if_n64_bus bus,
|
if_n64_bus bus,
|
||||||
if_config.n64 cfg,
|
if_config.n64 cfg
|
||||||
if_cpu_ram.external cpu_ram
|
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef enum bit [2:0] {
|
typedef enum bit [2:0] {
|
||||||
@ -32,10 +31,6 @@ module n64_cfg (
|
|||||||
logic [31:0] isv_id;
|
logic [31:0] isv_id;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
cpu_ram.write = bus.request && bus.write && (bus.address[15:14] == 2'b01);
|
|
||||||
cpu_ram.address = bus.address[13:1];
|
|
||||||
cpu_ram.wdata = {bus.wdata[7:0], bus.wdata[15:8]};
|
|
||||||
|
|
||||||
bus.rdata = 16'd0;
|
bus.rdata = 16'd0;
|
||||||
if (bus.ack) begin
|
if (bus.ack) begin
|
||||||
if (bus.address[15:14] == 2'b00) begin
|
if (bus.address[15:14] == 2'b00) begin
|
||||||
@ -54,14 +49,14 @@ module n64_cfg (
|
|||||||
R_DATA_1_L: bus.rdata = cfg.data[1][15:0];
|
R_DATA_1_L: bus.rdata = cfg.data[1][15:0];
|
||||||
R_VERSION_H: bus.rdata = sc64::SC64_VER[31:16];
|
R_VERSION_H: bus.rdata = sc64::SC64_VER[31:16];
|
||||||
R_VERSION_L: bus.rdata = sc64::SC64_VER[15:0];
|
R_VERSION_L: bus.rdata = sc64::SC64_VER[15:0];
|
||||||
|
default: bus.rdata = 16'd0;
|
||||||
endcase
|
endcase
|
||||||
end else if (bus.address[15:14] == 2'b01) begin
|
|
||||||
bus.rdata = {cpu_ram.rdata[7:0], cpu_ram.rdata[15:8]};
|
|
||||||
end else if (bus.address[15:14] == 2'b11) begin
|
end else if (bus.address[15:14] == 2'b11) begin
|
||||||
case (bus.address[4:1])
|
case (bus.address[4:1])
|
||||||
R_ISV_ID_H: bus.rdata = isv_id[31:16];
|
R_ISV_ID_H: bus.rdata = isv_id[31:16];
|
||||||
R_ISV_ID_L: bus.rdata = isv_id[15:0];
|
R_ISV_ID_L: bus.rdata = isv_id[15:0];
|
||||||
R_ISV_RD_PTR: bus.rdata = cfg.isv_rd_ptr;
|
R_ISV_RD_PTR: bus.rdata = cfg.isv_rd_ptr;
|
||||||
|
default: bus.rdata = 16'd0;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
module n64_sdram (
|
module n64_sdram (
|
||||||
if_system sys,
|
if_system sys,
|
||||||
if_n64_bus bus,
|
if_n64_bus bus,
|
||||||
if_dma.memory dma,
|
if_memory_dma.memory usb_dma,
|
||||||
if_sdram.memory sdram,
|
if_sdram.memory sdram,
|
||||||
|
|
||||||
output sdram_cs,
|
output sdram_cs,
|
||||||
@ -20,70 +20,52 @@ module n64_sdram (
|
|||||||
logic [15:0] mem_rdata;
|
logic [15:0] mem_rdata;
|
||||||
logic [15:0] mem_wdata;
|
logic [15:0] mem_wdata;
|
||||||
|
|
||||||
typedef enum bit [0:0] {
|
|
||||||
S_IDLE,
|
|
||||||
S_WAIT
|
|
||||||
} e_state;
|
|
||||||
|
|
||||||
typedef enum bit [1:0] {
|
typedef enum bit [1:0] {
|
||||||
T_BUS,
|
T_BUS,
|
||||||
T_DMA,
|
T_SDRAM,
|
||||||
T_SDRAM
|
T_USB_DMA
|
||||||
} e_source_request;
|
} e_source_request;
|
||||||
|
|
||||||
e_state state;
|
|
||||||
e_source_request source_request;
|
e_source_request source_request;
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
always_ff @(posedge sys.clk) begin
|
||||||
if (sys.reset) begin
|
if (sys.reset) begin
|
||||||
state <= S_IDLE;
|
|
||||||
mem_request <= 1'b0;
|
mem_request <= 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
case (state)
|
if (!mem_request && (bus.request || sdram.request || usb_dma.request)) begin
|
||||||
S_IDLE: begin
|
|
||||||
if (bus.request) begin
|
|
||||||
state <= S_WAIT;
|
|
||||||
mem_request <= 1'b1;
|
mem_request <= 1'b1;
|
||||||
|
if (bus.request) begin
|
||||||
mem_write <= bus.write;
|
mem_write <= bus.write;
|
||||||
mem_address <= bus.address;
|
mem_address <= bus.address;
|
||||||
mem_wdata <= bus.wdata;
|
mem_wdata <= bus.wdata;
|
||||||
source_request <= T_BUS;
|
source_request <= T_BUS;
|
||||||
end else if ((!bus.n64_active) && (sdram.request || dma.request)) begin
|
end else if (sdram.request) begin
|
||||||
state <= S_WAIT;
|
|
||||||
mem_request <= 1'b1;
|
|
||||||
if (sdram.request) begin
|
|
||||||
mem_write <= sdram.write;
|
mem_write <= sdram.write;
|
||||||
mem_address <= sdram.address;
|
mem_address <= sdram.address;
|
||||||
mem_wdata <= sdram.wdata;
|
mem_wdata <= sdram.wdata;
|
||||||
source_request <= T_SDRAM;
|
source_request <= T_SDRAM;
|
||||||
end else if (dma.request) begin
|
end else if (usb_dma.request) begin
|
||||||
mem_write <= dma.write;
|
mem_write <= usb_dma.write;
|
||||||
mem_address <= dma.address;
|
mem_address <= usb_dma.address;
|
||||||
mem_wdata <= dma.wdata;
|
mem_wdata <= usb_dma.wdata;
|
||||||
source_request <= T_DMA;
|
source_request <= T_USB_DMA;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
S_WAIT: begin
|
|
||||||
if (mem_ack) begin
|
if (mem_ack) begin
|
||||||
state <= S_IDLE;
|
|
||||||
mem_request <= 1'b0;
|
mem_request <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
bus.ack = source_request == T_BUS && mem_ack;
|
bus.ack = source_request == T_BUS && mem_ack;
|
||||||
bus.rdata = bus.ack ? mem_rdata : 16'd0;
|
bus.rdata = bus.ack ? mem_rdata : 16'd0;
|
||||||
|
|
||||||
dma.ack = source_request == T_DMA && mem_ack;
|
|
||||||
dma.rdata = mem_rdata;
|
|
||||||
|
|
||||||
sdram.ack = source_request == T_SDRAM && mem_ack;
|
sdram.ack = source_request == T_SDRAM && mem_ack;
|
||||||
sdram.rdata = mem_rdata;
|
sdram.rdata = mem_rdata;
|
||||||
|
|
||||||
|
usb_dma.ack = source_request == T_USB_DMA && mem_ack;
|
||||||
|
usb_dma.rdata = mem_rdata;
|
||||||
end
|
end
|
||||||
|
|
||||||
memory_sdram memory_sdram_inst (
|
memory_sdram memory_sdram_inst (
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
module n64_soc (
|
module n64_soc (
|
||||||
if_system sys,
|
if_system sys,
|
||||||
if_config cfg,
|
if_config cfg,
|
||||||
if_dma.memory dma,
|
if_memory_dma.memory usb_dma,
|
||||||
if_sdram.memory sdram,
|
if_sdram.memory sdram,
|
||||||
if_flashram.flashram flashram,
|
if_flashram.flashram flashram,
|
||||||
if_si.si si,
|
if_si.si si,
|
||||||
if_flash.memory flash,
|
if_flash.flash flash,
|
||||||
if_dd dd,
|
if_dd dd,
|
||||||
if_cpu_ram.external cpu_ram,
|
|
||||||
|
|
||||||
input n64_pi_alel,
|
input n64_pi_alel,
|
||||||
input n64_pi_aleh,
|
input n64_pi_aleh,
|
||||||
@ -52,7 +51,7 @@ module n64_soc (
|
|||||||
n64_sdram n64_sdram_inst (
|
n64_sdram n64_sdram_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_N64_SDRAM].device),
|
.bus(bus.at[sc64::ID_N64_SDRAM].device),
|
||||||
.dma(dma),
|
.usb_dma(usb_dma),
|
||||||
.sdram(sdram),
|
.sdram(sdram),
|
||||||
|
|
||||||
.sdram_cs(sdram_cs),
|
.sdram_cs(sdram_cs),
|
||||||
@ -67,6 +66,7 @@ module n64_soc (
|
|||||||
n64_bootloader n64_bootloader_inst (
|
n64_bootloader n64_bootloader_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_N64_BOOTLOADER].device),
|
.bus(bus.at[sc64::ID_N64_BOOTLOADER].device),
|
||||||
|
.cfg(cfg),
|
||||||
.flash(flash)
|
.flash(flash)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -91,8 +91,7 @@ module n64_soc (
|
|||||||
n64_cfg n64_cfg_inst (
|
n64_cfg n64_cfg_inst (
|
||||||
.sys(sys),
|
.sys(sys),
|
||||||
.bus(bus.at[sc64::ID_N64_CFG].device),
|
.bus(bus.at[sc64::ID_N64_CFG].device),
|
||||||
.cfg(cfg),
|
.cfg(cfg)
|
||||||
.cpu_ram(cpu_ram)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -20,6 +20,10 @@ interface if_config ();
|
|||||||
logic [25:0] save_offset;
|
logic [25:0] save_offset;
|
||||||
logic [25:0] isv_offset;
|
logic [25:0] isv_offset;
|
||||||
logic [15:0] isv_rd_ptr;
|
logic [15:0] isv_rd_ptr;
|
||||||
|
logic flash_erase_start;
|
||||||
|
logic flash_erase_busy;
|
||||||
|
logic flash_wp_enable;
|
||||||
|
logic flash_wp_disable;
|
||||||
|
|
||||||
modport pi (
|
modport pi (
|
||||||
input sdram_switch,
|
input sdram_switch,
|
||||||
@ -39,6 +43,13 @@ interface if_config ();
|
|||||||
output flashram_read_mode
|
output flashram_read_mode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
modport flash (
|
||||||
|
input flash_erase_start,
|
||||||
|
output flash_erase_busy,
|
||||||
|
input flash_wp_enable,
|
||||||
|
input flash_wp_disable
|
||||||
|
);
|
||||||
|
|
||||||
modport n64 (
|
modport n64 (
|
||||||
input cpu_ready,
|
input cpu_ready,
|
||||||
input cpu_busy,
|
input cpu_busy,
|
||||||
@ -70,7 +81,11 @@ interface if_config ();
|
|||||||
output ddipl_offset,
|
output ddipl_offset,
|
||||||
output save_offset,
|
output save_offset,
|
||||||
output isv_offset,
|
output isv_offset,
|
||||||
input isv_rd_ptr
|
input isv_rd_ptr,
|
||||||
|
output flash_erase_start,
|
||||||
|
input flash_erase_busy,
|
||||||
|
output flash_wp_enable,
|
||||||
|
output flash_wp_disable
|
||||||
);
|
);
|
||||||
|
|
||||||
endinterface
|
endinterface
|
||||||
|
@ -9,31 +9,8 @@ package sc64;
|
|||||||
__ID_N64_END
|
__ID_N64_END
|
||||||
} e_n64_id;
|
} e_n64_id;
|
||||||
|
|
||||||
typedef enum bit [3:0] {
|
|
||||||
ID_CPU_RAM,
|
|
||||||
ID_CPU_FLASH,
|
|
||||||
ID_CPU_GPIO,
|
|
||||||
ID_CPU_I2C,
|
|
||||||
ID_CPU_USB,
|
|
||||||
ID_CPU_UART,
|
|
||||||
ID_CPU_DMA,
|
|
||||||
ID_CPU_CFG,
|
|
||||||
ID_CPU_SDRAM,
|
|
||||||
ID_CPU_FLASHRAM,
|
|
||||||
ID_CPU_SI,
|
|
||||||
ID_CPU_DD,
|
|
||||||
__ID_CPU_END
|
|
||||||
} e_cpu_id;
|
|
||||||
|
|
||||||
typedef enum bit [1:0] {
|
|
||||||
ID_DMA_USB,
|
|
||||||
ID_DMA_SD,
|
|
||||||
__ID_DMA_END
|
|
||||||
} e_dma_id;
|
|
||||||
|
|
||||||
parameter bit [31:0] SC64_VER = 32'h53437632;
|
parameter bit [31:0] SC64_VER = 32'h53437632;
|
||||||
parameter int CLOCK_FREQUENCY = 32'd100_000_000;
|
parameter int CLOCK_FREQUENCY = 32'd100_000_000;
|
||||||
parameter bit [31:0] CPU_RESET_VECTOR = {4'(ID_CPU_FLASH), 28'h0010000};
|
|
||||||
parameter int UART_BAUD_RATE = 32'd1_000_000;
|
parameter int UART_BAUD_RATE = 32'd1_000_000;
|
||||||
|
|
||||||
`ifdef DEBUG
|
`ifdef DEBUG
|
||||||
|
@ -1,281 +1,242 @@
|
|||||||
module usb_ft1248 (
|
module usb_ft1248 (
|
||||||
if_system.sys sys,
|
input clk,
|
||||||
|
input reset,
|
||||||
input usb_enabled,
|
|
||||||
input tx_force,
|
|
||||||
|
|
||||||
output usb_clk,
|
output usb_clk,
|
||||||
output usb_cs,
|
output usb_cs,
|
||||||
input usb_miso,
|
input usb_miso,
|
||||||
inout [3:0] usb_miosi,
|
inout [7:0] usb_miosi,
|
||||||
|
|
||||||
|
output reset_pending,
|
||||||
|
input reset_ack,
|
||||||
|
input write_buffer_flush,
|
||||||
|
|
||||||
input rx_flush,
|
input rx_flush,
|
||||||
output rx_empty,
|
output rx_empty,
|
||||||
|
output rx_almost_empty,
|
||||||
input rx_read,
|
input rx_read,
|
||||||
output [7:0] rx_rdata,
|
output [7:0] rx_rdata,
|
||||||
|
|
||||||
input tx_flush,
|
input tx_flush,
|
||||||
output tx_full,
|
output tx_full,
|
||||||
|
output tx_almost_full,
|
||||||
input tx_write,
|
input tx_write,
|
||||||
input [7:0] tx_wdata,
|
input [7:0] tx_wdata
|
||||||
|
|
||||||
output rx_escape_valid,
|
|
||||||
input rx_escape_ack,
|
|
||||||
output [7:0] rx_escape
|
|
||||||
);
|
);
|
||||||
|
|
||||||
parameter bit [7:0] ESCAPE_CHARACTER = 8'h1B;
|
|
||||||
|
|
||||||
// FIFOs
|
|
||||||
|
|
||||||
logic rx_full;
|
logic rx_full;
|
||||||
|
logic rx_almost_full;
|
||||||
logic rx_write;
|
logic rx_write;
|
||||||
logic [7:0] rx_wdata;
|
|
||||||
|
|
||||||
logic tx_empty;
|
logic tx_empty;
|
||||||
|
logic tx_almost_empty;
|
||||||
logic tx_read;
|
logic tx_read;
|
||||||
logic [7:0] tx_rdata;
|
logic [7:0] tx_rdata;
|
||||||
|
|
||||||
logic rx_wdata_valid;
|
|
||||||
logic rx_escape_active;
|
|
||||||
|
|
||||||
intel_fifo_8 fifo_8_rx_inst (
|
intel_fifo_8 fifo_8_rx_inst (
|
||||||
.clock(sys.clk),
|
.clock(clk),
|
||||||
.sclr(rx_flush || !usb_enabled),
|
.sclr(reset || rx_flush),
|
||||||
|
|
||||||
.empty(rx_empty),
|
.empty(rx_empty),
|
||||||
|
.almost_empty(rx_almost_empty),
|
||||||
.rdreq(rx_read),
|
.rdreq(rx_read),
|
||||||
.q(rx_rdata),
|
.q(rx_rdata),
|
||||||
|
|
||||||
.full(rx_full),
|
.full(rx_full),
|
||||||
|
.almost_full(rx_almost_full),
|
||||||
.wrreq(rx_write),
|
.wrreq(rx_write),
|
||||||
.data(rx_wdata)
|
.data(usb_miosi)
|
||||||
);
|
);
|
||||||
|
|
||||||
intel_fifo_8 fifo_8_tx_inst (
|
intel_fifo_8 fifo_8_tx_inst (
|
||||||
.clock(sys.clk),
|
.clock(clk),
|
||||||
.sclr(tx_flush || !usb_enabled),
|
.sclr(reset || tx_flush),
|
||||||
|
|
||||||
.empty(tx_empty),
|
.empty(tx_empty),
|
||||||
|
.almost_empty(tx_almost_empty),
|
||||||
.rdreq(tx_read),
|
.rdreq(tx_read),
|
||||||
.q(tx_rdata),
|
.q(tx_rdata),
|
||||||
|
|
||||||
.full(tx_full),
|
.full(tx_full),
|
||||||
|
.almost_full(tx_almost_full),
|
||||||
.wrreq(tx_write),
|
.wrreq(tx_write),
|
||||||
.data(tx_wdata)
|
.data(tx_wdata)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
typedef enum bit [2:0] {
|
||||||
// Escape character detection
|
STATE_IDLE,
|
||||||
|
STATE_SELECT,
|
||||||
always_comb begin
|
STATE_COMMAND,
|
||||||
rx_write = 1'b0;
|
STATE_STATUS,
|
||||||
if (rx_wdata_valid) begin
|
STATE_DATA,
|
||||||
rx_write = rx_escape_active ? rx_wdata == ESCAPE_CHARACTER : rx_wdata != ESCAPE_CHARACTER;
|
STATE_DESELECT
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
|
||||||
if (sys.reset || !usb_enabled) begin
|
|
||||||
rx_escape_valid <= 1'b0;
|
|
||||||
rx_escape_active <= 1'b0;
|
|
||||||
end else begin
|
|
||||||
if (rx_escape_ack) begin
|
|
||||||
rx_escape_valid <= 1'b0;
|
|
||||||
end
|
|
||||||
|
|
||||||
if (rx_wdata_valid) begin
|
|
||||||
if (!rx_escape_active) begin
|
|
||||||
if (rx_wdata == ESCAPE_CHARACTER) begin
|
|
||||||
rx_escape_active <= 1'b1;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
rx_escape_active <= 1'b0;
|
|
||||||
rx_escape <= rx_wdata;
|
|
||||||
if (rx_wdata != ESCAPE_CHARACTER) begin
|
|
||||||
rx_escape_valid <= 1'b1;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
// FT1248 interface controller
|
|
||||||
|
|
||||||
typedef enum bit [1:0] {
|
|
||||||
S_TRY_RX,
|
|
||||||
S_TRY_TX,
|
|
||||||
S_COMMAND,
|
|
||||||
S_DATA
|
|
||||||
} e_state;
|
} e_state;
|
||||||
|
|
||||||
typedef enum bit [7:0] {
|
typedef enum bit [7:0] {
|
||||||
C_WRITE = 8'h00,
|
CMD_WRITE = 8'h00,
|
||||||
C_READ = 8'h04,
|
CMD_READ = 8'h40,
|
||||||
C_FORCE = 8'h80
|
CMD_READ_MODEM_STATUS = 8'h20,
|
||||||
|
CMD_WRITE_MODEM_STATUS = 8'h60,
|
||||||
|
CMD_WRITE_BUFFER_FLUSH = 8'h08
|
||||||
} e_command;
|
} e_command;
|
||||||
|
|
||||||
typedef enum bit [1:0] {
|
logic usb_miosi_oe;
|
||||||
P_PRE_RISING,
|
logic write_buffer_flush_pending;
|
||||||
P_RISING,
|
logic write_modem_status_pending;
|
||||||
P_PRE_FALLING,
|
logic [4:0] modem_status_counter;
|
||||||
P_FALLING
|
logic modem_status_read;
|
||||||
} e_clock_phase;
|
logic last_reset_status;
|
||||||
|
logic reset_reply;
|
||||||
|
logic [3:0] phase;
|
||||||
|
logic [7:0] usb_cmd;
|
||||||
e_state state;
|
e_state state;
|
||||||
|
|
||||||
logic [3:0] clock_phase;
|
|
||||||
|
|
||||||
logic usb_clk_output;
|
|
||||||
logic usb_cs_output;
|
|
||||||
logic [3:0] usb_miosi_input;
|
|
||||||
logic [3:0] usb_miosi_output;
|
|
||||||
logic [3:0] usb_miosi_output_data;
|
|
||||||
logic usb_miosi_output_enable;
|
|
||||||
logic usb_miosi_output_enable_data;
|
|
||||||
logic usb_miso_input;
|
|
||||||
|
|
||||||
logic tx_force_pending;
|
|
||||||
logic is_cmd_write;
|
|
||||||
logic is_cmd_tx_force;
|
|
||||||
logic [1:0] nibble_counter;
|
|
||||||
logic [7:0] tx_buffer;
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
|
||||||
if (sys.reset || state == S_TRY_RX || state == S_TRY_TX) begin
|
|
||||||
clock_phase <= 4'b0001;
|
|
||||||
end else begin
|
|
||||||
clock_phase <= {clock_phase[2:0], clock_phase[3]};
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
|
||||||
usb_clk <= usb_clk_output;
|
|
||||||
usb_cs <= usb_cs_output;
|
|
||||||
|
|
||||||
usb_miosi_input <= usb_miosi;
|
|
||||||
usb_miosi_output <= usb_miosi_output_data;
|
|
||||||
usb_miosi_output_enable <= usb_miosi_output_enable_data;
|
|
||||||
|
|
||||||
usb_miso_input <= usb_miso;
|
|
||||||
|
|
||||||
tx_buffer <= tx_rdata;
|
|
||||||
end
|
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
usb_miosi = usb_miosi_output_enable ? usb_miosi_output : 4'bZZZZ;
|
usb_miosi = 8'hZZ;
|
||||||
|
if (usb_miosi_oe) begin
|
||||||
|
usb_miosi = 8'h00;
|
||||||
|
if ((state == STATE_COMMAND) || (state == STATE_STATUS)) begin
|
||||||
|
usb_miosi = usb_cmd;
|
||||||
|
end
|
||||||
|
if ((state == STATE_DATA) || (state == STATE_DESELECT)) begin
|
||||||
|
if (usb_cmd == CMD_WRITE) begin
|
||||||
|
usb_miosi = tx_rdata;
|
||||||
|
end
|
||||||
|
if (usb_cmd == CMD_WRITE_MODEM_STATUS) begin
|
||||||
|
usb_miosi = {2'b00, reset_reply, 5'b00000};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
always_comb begin
|
always_ff @(posedge clk) begin
|
||||||
case (state)
|
rx_write <= 1'b0;
|
||||||
S_COMMAND: begin
|
|
||||||
usb_clk_output = clock_phase[P_PRE_FALLING] || clock_phase[P_FALLING];
|
|
||||||
usb_cs_output = 1'b0;
|
|
||||||
if (is_cmd_tx_force) begin
|
|
||||||
usb_miosi_output_data = nibble_counter[0] ? C_FORCE[3:0] : C_FORCE[7:4];
|
|
||||||
end else if (is_cmd_write) begin
|
|
||||||
usb_miosi_output_data = nibble_counter[0] ? C_WRITE[3:0] : C_WRITE[7:4];
|
|
||||||
end else begin
|
|
||||||
usb_miosi_output_data = nibble_counter[0] ? C_READ[3:0] : C_READ[7:4];
|
|
||||||
end
|
|
||||||
usb_miosi_output_enable_data = nibble_counter < 2'd2;
|
|
||||||
end
|
|
||||||
|
|
||||||
S_DATA: begin
|
|
||||||
usb_clk_output = clock_phase[P_PRE_FALLING] || clock_phase[P_FALLING];
|
|
||||||
usb_cs_output = 1'b0;
|
|
||||||
usb_miosi_output_data = nibble_counter[0] ? tx_buffer[7:4] : tx_buffer[3:0];
|
|
||||||
usb_miosi_output_enable_data = is_cmd_write;
|
|
||||||
end
|
|
||||||
|
|
||||||
default: begin
|
|
||||||
usb_clk_output = 1'b0;
|
|
||||||
usb_cs_output = 1'b1;
|
|
||||||
usb_miosi_output_data = 4'hF;
|
|
||||||
usb_miosi_output_enable_data = 1'b0;
|
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
always_ff @(posedge sys.clk) begin
|
|
||||||
rx_wdata_valid <= 1'b0;
|
|
||||||
tx_read <= 1'b0;
|
tx_read <= 1'b0;
|
||||||
|
modem_status_read <= 1'b0;
|
||||||
|
phase <= {phase[2:0], phase[3]};
|
||||||
|
|
||||||
if (clock_phase[P_RISING]) begin
|
if (reset) begin
|
||||||
nibble_counter <= nibble_counter + 1'd1;
|
usb_clk <= 1'b0;
|
||||||
|
usb_cs <= 1'b1;
|
||||||
|
usb_miosi_oe <= 1'b0;
|
||||||
|
reset_pending <= 1'b0;
|
||||||
|
write_buffer_flush_pending <= 1'b0;
|
||||||
|
write_modem_status_pending <= 1'b0;
|
||||||
|
modem_status_counter <= 5'd0;
|
||||||
|
last_reset_status <= 1'b0;
|
||||||
|
reset_reply <= 1'b0;
|
||||||
|
phase <= 4'b0001;
|
||||||
|
state <= STATE_IDLE;
|
||||||
|
end else begin
|
||||||
|
if (write_buffer_flush) begin
|
||||||
|
write_buffer_flush_pending <= 1'b1;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (sys.reset || !usb_enabled) begin
|
if (reset_ack) begin
|
||||||
state <= S_TRY_RX;
|
reset_pending <= 1'b0;
|
||||||
tx_force_pending <= 1'b0;
|
write_modem_status_pending <= 1'b1;
|
||||||
end else begin
|
reset_reply <= 1'b1;
|
||||||
if (tx_force) begin
|
end
|
||||||
tx_force_pending <= 1'b1;
|
|
||||||
|
if (modem_status_read) begin
|
||||||
|
last_reset_status <= usb_miosi[0];
|
||||||
|
if (!last_reset_status && usb_miosi[0]) begin
|
||||||
|
reset_pending <= 1'b1;
|
||||||
|
end
|
||||||
|
if (last_reset_status && !usb_miosi[0]) begin
|
||||||
|
write_modem_status_pending <= 1'b1;
|
||||||
|
reset_reply <= 1'b0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
case (state)
|
case (state)
|
||||||
S_TRY_RX: begin
|
STATE_IDLE: begin
|
||||||
if (!rx_full && !rx_escape_valid) begin
|
usb_cs <= 1'b0;
|
||||||
state <= S_COMMAND;
|
state <= STATE_SELECT;
|
||||||
is_cmd_write <= 1'b0;
|
if (write_modem_status_pending) begin
|
||||||
is_cmd_tx_force <= 1'b0;
|
usb_cmd <= CMD_WRITE_MODEM_STATUS;
|
||||||
nibble_counter <= 2'b11;
|
end else if (&modem_status_counter) begin
|
||||||
|
usb_cmd <= CMD_READ_MODEM_STATUS;
|
||||||
|
end else if (!tx_empty) begin
|
||||||
|
usb_cmd <= CMD_WRITE;
|
||||||
|
end else if (write_buffer_flush_pending) begin
|
||||||
|
usb_cmd <= CMD_WRITE_BUFFER_FLUSH;
|
||||||
|
end else if (!rx_full) begin
|
||||||
|
usb_cmd <= CMD_READ;
|
||||||
end else begin
|
end else begin
|
||||||
state <= S_TRY_TX;
|
usb_cs <= 1'b1;
|
||||||
|
modem_status_counter <= modem_status_counter + 1'd1;
|
||||||
|
state <= STATE_IDLE;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
S_TRY_TX: begin
|
STATE_SELECT: begin
|
||||||
if (!tx_empty) begin
|
phase <= 4'b0001;
|
||||||
state <= S_COMMAND;
|
state <= STATE_COMMAND;
|
||||||
is_cmd_write <= 1'b1;
|
end
|
||||||
is_cmd_tx_force <= 1'b0;
|
|
||||||
nibble_counter <= 2'b11;
|
STATE_COMMAND: begin
|
||||||
end else if (tx_force_pending) begin
|
if (phase[0]) begin
|
||||||
state <= S_COMMAND;
|
usb_clk <= 1'b1;
|
||||||
tx_force_pending <= 1'b0;
|
usb_miosi_oe <= 1'b1;
|
||||||
is_cmd_write <= 1'b1;
|
end else if (phase[2]) begin
|
||||||
is_cmd_tx_force <= 1'b1;
|
usb_clk <= 1'b0;
|
||||||
nibble_counter <= 2'b11;
|
end else if (phase[3]) begin
|
||||||
end else begin
|
state <= STATE_STATUS;
|
||||||
state <= S_TRY_RX;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
S_COMMAND: begin
|
STATE_STATUS: begin
|
||||||
if (clock_phase[P_RISING]) begin
|
if (phase[0]) begin
|
||||||
if (nibble_counter == 2'd2) begin
|
usb_clk <= 1'b1;
|
||||||
if (usb_miso_input || is_cmd_tx_force) begin
|
usb_miosi_oe <= 1'b0;
|
||||||
state <= is_cmd_write ? S_TRY_RX : S_TRY_TX;
|
end else if (phase[2]) begin
|
||||||
end else begin
|
usb_clk <= 1'b0;
|
||||||
state <= S_DATA;
|
end else if (phase[3]) begin
|
||||||
nibble_counter <= 2'd0;
|
state <= STATE_DATA;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
STATE_DATA: begin
|
||||||
|
if (phase[0]) begin
|
||||||
|
usb_clk <= 1'b1;
|
||||||
|
usb_miosi_oe <= (usb_cmd == CMD_WRITE) || (usb_cmd == CMD_WRITE_MODEM_STATUS);
|
||||||
|
end else if (phase[2]) begin
|
||||||
|
usb_clk <= 1'b0;
|
||||||
|
end else if (phase[3]) begin
|
||||||
|
if (usb_miso) begin
|
||||||
|
state <= STATE_DESELECT;
|
||||||
|
end else if (usb_cmd == CMD_WRITE) begin
|
||||||
|
tx_read <= 1'b1;
|
||||||
|
if (tx_almost_empty) begin
|
||||||
|
state <= STATE_DESELECT;
|
||||||
|
end
|
||||||
|
end else if (usb_cmd == CMD_READ) begin
|
||||||
|
rx_write <= 1'b1;
|
||||||
|
if (rx_almost_full) begin
|
||||||
|
state <= STATE_DESELECT;
|
||||||
|
end
|
||||||
|
end else if (usb_cmd == CMD_READ_MODEM_STATUS) begin
|
||||||
|
modem_status_read <= 1'b1;
|
||||||
|
state <= STATE_DESELECT;
|
||||||
|
end else if (usb_cmd == CMD_WRITE_MODEM_STATUS) begin
|
||||||
|
write_modem_status_pending <= 1'b0;
|
||||||
|
state <= STATE_DESELECT;
|
||||||
|
end else if (usb_cmd == CMD_WRITE_BUFFER_FLUSH) begin
|
||||||
|
write_buffer_flush_pending <= 1'b0;
|
||||||
|
state <= STATE_DESELECT;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
S_DATA: begin
|
STATE_DESELECT: begin
|
||||||
if (clock_phase[P_FALLING]) begin
|
usb_cs <= 1'b1;
|
||||||
if (nibble_counter[0]) begin
|
usb_miosi_oe <= 1'b0;
|
||||||
tx_read <= is_cmd_write;
|
if (phase[1]) begin
|
||||||
|
modem_status_counter <= modem_status_counter + 1'd1;
|
||||||
|
state <= STATE_IDLE;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (clock_phase[P_RISING]) begin
|
|
||||||
rx_wdata <= {usb_miosi_input, rx_wdata[7:4]};
|
|
||||||
if (nibble_counter[0]) begin
|
|
||||||
rx_wdata_valid <= !is_cmd_write;
|
|
||||||
end
|
|
||||||
if (usb_miso_input || (!is_cmd_write && (rx_full || rx_escape_valid)) || (is_cmd_write && tx_empty)) begin
|
|
||||||
state <= is_cmd_write ? S_TRY_RX : S_TRY_TX;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
default: begin
|
|
||||||
state <= S_TRY_RX;
|
|
||||||
end
|
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
175
fw/rtl/vendor/vendor_flash.sv
vendored
Normal file
175
fw/rtl/vendor/vendor_flash.sv
vendored
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
module vendor_flash (
|
||||||
|
input clk,
|
||||||
|
input reset,
|
||||||
|
|
||||||
|
input erase_start,
|
||||||
|
output erase_busy,
|
||||||
|
input wp_enable,
|
||||||
|
input wp_disable,
|
||||||
|
|
||||||
|
input request,
|
||||||
|
output ack,
|
||||||
|
input write,
|
||||||
|
input [31:0] address,
|
||||||
|
input [31:0] wdata,
|
||||||
|
output [31:0] rdata
|
||||||
|
);
|
||||||
|
|
||||||
|
const int FLASH_SECTORS = 3'd4;
|
||||||
|
|
||||||
|
typedef enum bit [1:0] {
|
||||||
|
STATE_START,
|
||||||
|
STATE_PENDING,
|
||||||
|
STATE_ERASING
|
||||||
|
} e_erase_state;
|
||||||
|
|
||||||
|
typedef enum bit [0:0] {
|
||||||
|
CSR_STATUS = 1'b0,
|
||||||
|
CSR_CONTROL = 1'b1
|
||||||
|
} e_flash_csr;
|
||||||
|
|
||||||
|
typedef enum bit [1:0] {
|
||||||
|
STATUS_IDLE = 2'b00,
|
||||||
|
STATUS_BUSY_ERASE = 2'b01,
|
||||||
|
STATUS_BUSY_WRITE = 2'b10,
|
||||||
|
STATUS_BUSY_READ = 2'b11
|
||||||
|
} e_flash_status;
|
||||||
|
|
||||||
|
logic csr_read;
|
||||||
|
logic csr_write;
|
||||||
|
e_flash_csr csr_address;
|
||||||
|
logic [31:0] csr_wdata;
|
||||||
|
logic [31:0] csr_rdata;
|
||||||
|
|
||||||
|
logic wp_setting;
|
||||||
|
logic [2:0] erase_sector;
|
||||||
|
e_erase_state state;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
csr_read <= 1'b0;
|
||||||
|
csr_write <= 1'b0;
|
||||||
|
csr_address <= CSR_STATUS;
|
||||||
|
|
||||||
|
if (reset) begin
|
||||||
|
erase_busy <= 1'b0;
|
||||||
|
wp_setting <= 1'b1;
|
||||||
|
end else if (!erase_busy) begin
|
||||||
|
if (erase_start) begin
|
||||||
|
erase_busy <= 1'b1;
|
||||||
|
erase_sector <= 3'd1;
|
||||||
|
state <= STATE_START;
|
||||||
|
end else if (wp_enable) begin
|
||||||
|
csr_write <= 1'b1;
|
||||||
|
csr_address <= CSR_CONTROL;
|
||||||
|
csr_wdata <= 32'hFFFF_FFFF;
|
||||||
|
wp_setting <= 1'b1;
|
||||||
|
end else if (wp_disable) begin
|
||||||
|
csr_write <= 1'b1;
|
||||||
|
csr_address <= CSR_CONTROL;
|
||||||
|
csr_wdata <= 32'hF07F_FFFF;
|
||||||
|
wp_setting <= 1'b0;
|
||||||
|
end
|
||||||
|
end else begin
|
||||||
|
csr_read <= 1'b1;
|
||||||
|
|
||||||
|
case (state)
|
||||||
|
STATE_START: begin
|
||||||
|
if (csr_read && (csr_rdata[1:0] == STATUS_IDLE)) begin
|
||||||
|
csr_read <= 1'b0;
|
||||||
|
csr_write <= 1'b1;
|
||||||
|
csr_address <= CSR_CONTROL;
|
||||||
|
csr_wdata <= {4'hF, {5{wp_setting}}, erase_sector, 20'hFFFFF};
|
||||||
|
state <= STATE_PENDING;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_PENDING: begin
|
||||||
|
if (csr_read && (csr_rdata[1:0] == STATUS_BUSY_ERASE)) begin
|
||||||
|
state <= STATE_ERASING;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
STATE_ERASING: begin
|
||||||
|
if (csr_read && (csr_rdata[1:0] == STATUS_IDLE)) begin
|
||||||
|
if (erase_sector == FLASH_SECTORS) begin
|
||||||
|
erase_busy <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
erase_sector <= erase_sector + 1'd1;
|
||||||
|
state <= STATE_START;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
logic data_read;
|
||||||
|
logic data_write;
|
||||||
|
logic data_busy;
|
||||||
|
logic data_ack;
|
||||||
|
logic [15:0] data_address;
|
||||||
|
logic [31:0] data_wdata;
|
||||||
|
logic [31:0] data_rdata;
|
||||||
|
|
||||||
|
logic pending;
|
||||||
|
logic write_ack;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
write_ack <= 1'b0;
|
||||||
|
|
||||||
|
if (reset) begin
|
||||||
|
data_read <= 1'b0;
|
||||||
|
data_write <= 1'b0;
|
||||||
|
pending <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
if (request && !pending && !erase_busy) begin
|
||||||
|
pending <= 1'b1;
|
||||||
|
if (write && !wp_setting) begin
|
||||||
|
data_write <= 1'b1;
|
||||||
|
end else begin
|
||||||
|
data_read <= 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if (data_read && !data_busy) begin
|
||||||
|
data_read <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (data_write && !data_busy) begin
|
||||||
|
data_write <= 1'b0;
|
||||||
|
pending <= 1'b0;
|
||||||
|
write_ack <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (data_ack) begin
|
||||||
|
pending <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
ack = data_ack || write_ack;
|
||||||
|
data_address = address[17:2];
|
||||||
|
end
|
||||||
|
|
||||||
|
intel_flash intel_flash_inst (
|
||||||
|
.clock(clk),
|
||||||
|
.reset_n(~reset),
|
||||||
|
|
||||||
|
.avmm_csr_read(csr_read),
|
||||||
|
.avmm_csr_write(csr_write),
|
||||||
|
.avmm_csr_addr(csr_address),
|
||||||
|
.avmm_csr_writedata(csr_wdata),
|
||||||
|
.avmm_csr_readdata(csr_rdata),
|
||||||
|
|
||||||
|
.avmm_data_read(data_read),
|
||||||
|
.avmm_data_write(data_write),
|
||||||
|
.avmm_data_waitrequest(data_busy),
|
||||||
|
.avmm_data_readdatavalid(data_ack),
|
||||||
|
.avmm_data_addr(data_address),
|
||||||
|
.avmm_data_writedata(wdata),
|
||||||
|
.avmm_data_readdata(rdata),
|
||||||
|
.avmm_data_burstcount(2'd1)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
42
fw/rtl/vendor/vendor_reconfigure.sv
vendored
Normal file
42
fw/rtl/vendor/vendor_reconfigure.sv
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
module vendor_reconfigure (
|
||||||
|
input clk,
|
||||||
|
input reset,
|
||||||
|
|
||||||
|
input trigger_reconfiguration
|
||||||
|
);
|
||||||
|
|
||||||
|
logic [1:0] ru_clk;
|
||||||
|
logic ru_rconfig;
|
||||||
|
logic ru_regout;
|
||||||
|
|
||||||
|
logic pending;
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (reset) begin
|
||||||
|
ru_clk <= 2'd0;
|
||||||
|
ru_rconfig <= 1'b0;
|
||||||
|
pending <= 1'b0;
|
||||||
|
end else begin
|
||||||
|
ru_clk <= ru_clk + 1'd1;
|
||||||
|
|
||||||
|
if (trigger_reconfiguration) begin
|
||||||
|
pending <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if (ru_clk == 2'd1) begin
|
||||||
|
ru_rconfig <= pending;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fiftyfivenm_rublock fiftyfivenm_rublock_inst (
|
||||||
|
.clk(ru_clk[1]),
|
||||||
|
.shiftnld(1'b0),
|
||||||
|
.captnupdt(1'b0),
|
||||||
|
.regin(1'b0),
|
||||||
|
.rsttimer(1'b0),
|
||||||
|
.rconfig(ru_rconfig),
|
||||||
|
.regout(ru_regout)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
@ -229,9 +229,6 @@ typedef struct {
|
|||||||
io32_t SR_CMD;
|
io32_t SR_CMD;
|
||||||
io32_t DATA[2];
|
io32_t DATA[2];
|
||||||
io32_t VERSION;
|
io32_t VERSION;
|
||||||
io32_t __padding[4092];
|
|
||||||
io32_t CPU_RAM[3840];
|
|
||||||
io32_t BUFFER[256];
|
|
||||||
} sc64_regs_t;
|
} sc64_regs_t;
|
||||||
|
|
||||||
#define SC64_BASE (0x1FFF0000UL)
|
#define SC64_BASE (0x1FFF0000UL)
|
||||||
|
@ -83,7 +83,7 @@ void sc64_set_time (rtc_time_t *t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t sc64_wait_drive_ready (drive_id_t drive) {
|
static uint32_t sc64_wait_drive_ready (drive_id_t drive) {
|
||||||
uint32_t args[2] = { (drive & 0xFF), 0 };
|
uint32_t args[2] = { ((drive & 0x01) << 31), 0 };
|
||||||
uint32_t result[2];
|
uint32_t result[2];
|
||||||
do {
|
do {
|
||||||
sc64_perform_cmd(SC64_CMD_DRIVE_BUSY, args, result);
|
sc64_perform_cmd(SC64_CMD_DRIVE_BUSY, args, result);
|
||||||
@ -92,7 +92,7 @@ static uint32_t sc64_wait_drive_ready (drive_id_t drive) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool sc64_storage_init (drive_id_t drive) {
|
bool sc64_storage_init (drive_id_t drive) {
|
||||||
uint32_t args[2] = { (drive & 0xFF), 0 };
|
uint32_t args[2] = { ((drive & 0x01) << 31), 0 };
|
||||||
if (sc64_perform_cmd(SC64_CMD_DRIVE_INIT, args, NULL)) {
|
if (sc64_perform_cmd(SC64_CMD_DRIVE_INIT, args, NULL)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ bool sc64_storage_init (drive_id_t drive) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool sc64_drive_start_rw (drive_id_t drive, bool write, uint32_t sector, uint32_t offset) {
|
static bool sc64_drive_start_rw (drive_id_t drive, bool write, uint32_t sector, uint32_t offset) {
|
||||||
uint32_t args[2] = { (((offset & 0xFFFFFF) << 8) | (drive & 0xFF)), sector };
|
uint32_t args[2] = { (((drive & 0x01) << 31) | (offset & 0x7FFFFFFF)), sector };
|
||||||
if (sc64_perform_cmd(write ? SC64_CMD_DRIVE_WRITE : SC64_CMD_DRIVE_READ, args, NULL)) {
|
if (sc64_perform_cmd(write ? SC64_CMD_DRIVE_WRITE : SC64_CMD_DRIVE_READ, args, NULL)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_
|
|||||||
uint32_t current_offset = 0;
|
uint32_t current_offset = 0;
|
||||||
uint32_t next_offset = SECTOR_SIZE;
|
uint32_t next_offset = SECTOR_SIZE;
|
||||||
|
|
||||||
if (sc64_drive_start_rw(drive, false, sector++, 0)) {
|
if (sc64_drive_start_rw(drive, false, sector++, 0x03FF0000UL)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
@ -124,12 +124,12 @@ bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (count > 1) {
|
if (count > 1) {
|
||||||
if (sc64_drive_start_rw(drive, false, sector++, next_offset)) {
|
if (sc64_drive_start_rw(drive, false, sector++, 0x03FF0000UL + next_offset)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
next_offset = next_offset ? 0 : SECTOR_SIZE;
|
next_offset = next_offset ? 0 : SECTOR_SIZE;
|
||||||
}
|
}
|
||||||
src = &SC64->BUFFER[current_offset / sizeof(io32_t)];
|
src = (io32_t *) (0x13FF0000UL + current_offset);
|
||||||
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
|
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
|
||||||
uint32_t data = pi_io_read(src + i);
|
uint32_t data = pi_io_read(src + i);
|
||||||
*dst++ = ((data >> 24) & 0xFF);
|
*dst++ = ((data >> 24) & 0xFF);
|
||||||
@ -146,7 +146,7 @@ bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_
|
|||||||
|
|
||||||
bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count) {
|
bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector, uint32_t count) {
|
||||||
uint8_t *src = (uint8_t *) (buffer);
|
uint8_t *src = (uint8_t *) (buffer);
|
||||||
io32_t *dst = SC64->BUFFER;
|
io32_t *dst = (io32_t *) (0x13FF0000UL);
|
||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
|
for (int i = 0; i < (SECTOR_SIZE / sizeof(uint32_t)); i++) {
|
||||||
@ -157,7 +157,7 @@ bool sc64_storage_write (drive_id_t drive, const void *buffer, uint32_t sector,
|
|||||||
data |= ((*src++) << 0);
|
data |= ((*src++) << 0);
|
||||||
pi_io_write((dst + i), data);
|
pi_io_write((dst + i), data);
|
||||||
}
|
}
|
||||||
if (sc64_drive_start_rw(drive, true, sector, 0)) {
|
if (sc64_drive_start_rw(drive, true, sector, 0x03FF0000UL)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (sc64_wait_drive_ready(drive)) {
|
if (sc64_wait_drive_ready(drive)) {
|
||||||
|
100
sw/pc/sc64.py
100
sw/pc/sc64.py
@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from ft232 import Ft232, Ft232Exception
|
from serial import Serial, SerialException
|
||||||
|
from serial.tools import list_ports
|
||||||
from io import TextIOWrapper
|
from io import TextIOWrapper
|
||||||
from typing import Union
|
from typing import Union
|
||||||
import argparse
|
import argparse
|
||||||
@ -9,7 +10,6 @@ import filecmp
|
|||||||
import helpers
|
import helpers
|
||||||
import os
|
import os
|
||||||
import progressbar
|
import progressbar
|
||||||
import re
|
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
@ -50,8 +50,6 @@ class SC64:
|
|||||||
__DEBUG_ID_TEXT = 0x01
|
__DEBUG_ID_TEXT = 0x01
|
||||||
__EVENT_ID_FSD_READ = 0xF0
|
__EVENT_ID_FSD_READ = 0xF0
|
||||||
__EVENT_ID_FSD_WRITE = 0xF1
|
__EVENT_ID_FSD_WRITE = 0xF1
|
||||||
__EVENT_ID_FSD_LOAD = 0xF2
|
|
||||||
__EVENT_ID_FSD_STORE = 0xF3
|
|
||||||
__EVENT_ID_DD_BLOCK = 0xF4
|
__EVENT_ID_DD_BLOCK = 0xF4
|
||||||
__EVENT_ID_IS_VIEWER = 0xF5
|
__EVENT_ID_IS_VIEWER = 0xF5
|
||||||
|
|
||||||
@ -76,7 +74,6 @@ class SC64:
|
|||||||
|
|
||||||
def __del__(self) -> None:
|
def __del__(self) -> None:
|
||||||
if (self.__usb):
|
if (self.__usb):
|
||||||
self.__reset_n64("release")
|
|
||||||
self.__usb.close()
|
self.__usb.close()
|
||||||
if (self.__fsd_file):
|
if (self.__fsd_file):
|
||||||
self.__fsd_file.close()
|
self.__fsd_file.close()
|
||||||
@ -101,14 +98,15 @@ class SC64:
|
|||||||
return (value + (align - 1)) & ~(align - 1)
|
return (value + (align - 1)) & ~(align - 1)
|
||||||
|
|
||||||
|
|
||||||
def __escape(self, data: bytes) -> bytes:
|
|
||||||
return re.sub(b"\x1B", b"\x1B\x1B", data)
|
|
||||||
|
|
||||||
|
|
||||||
def reset_link(self) -> None:
|
def reset_link(self) -> None:
|
||||||
self.__usb.write(b"\x1BR")
|
if (self.__usb):
|
||||||
time.sleep(0.1)
|
self.__usb.flush()
|
||||||
self.__usb.flushInput()
|
self.__usb.setDTR(1)
|
||||||
|
while (self.__usb.getDSR() == 0):
|
||||||
|
pass
|
||||||
|
self.__usb.setDTR(0)
|
||||||
|
while (self.__usb.getDSR() == 1):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def __read(self, bytes: int) -> bytes:
|
def __read(self, bytes: int) -> bytes:
|
||||||
@ -116,7 +114,7 @@ class SC64:
|
|||||||
|
|
||||||
|
|
||||||
def __write(self, data: bytes) -> None:
|
def __write(self, data: bytes) -> None:
|
||||||
self.__usb.write(self.__escape(data))
|
self.__usb.write(data)
|
||||||
|
|
||||||
|
|
||||||
def __read_long(self, length: int) -> bytes:
|
def __read_long(self, length: int) -> bytes:
|
||||||
@ -151,29 +149,28 @@ class SC64:
|
|||||||
self.__write_int(arg2)
|
self.__write_int(arg2)
|
||||||
|
|
||||||
|
|
||||||
def __reset_n64(self, type: str) -> None:
|
|
||||||
if (self.__usb):
|
|
||||||
if (type == "hold"):
|
|
||||||
self.__usb.cbus_setup(mask=1, init=0)
|
|
||||||
time.sleep(0.6)
|
|
||||||
elif (type == "release"):
|
|
||||||
self.__usb.cbus_setup(mask=0)
|
|
||||||
|
|
||||||
|
|
||||||
def __find_sc64(self) -> None:
|
def __find_sc64(self) -> None:
|
||||||
if (self.__usb != None and not self.__usb.closed):
|
ports = list_ports.comports()
|
||||||
|
device_found = False
|
||||||
|
|
||||||
|
if (self.__usb != None and self.__usb.isOpen()):
|
||||||
self.__usb.close()
|
self.__usb.close()
|
||||||
|
|
||||||
|
for p in ports:
|
||||||
|
if (p.vid == 0x0403 and p.pid == 0x6014 and p.serial_number.startswith("SC")):
|
||||||
try:
|
try:
|
||||||
self.__usb = Ft232(description="SummerCart64")
|
self.__usb = Serial(p.device, timeout=0.5, write_timeout=0.5)
|
||||||
self.__reset_n64("hold")
|
|
||||||
self.__usb.flushOutput()
|
|
||||||
self.reset_link()
|
self.reset_link()
|
||||||
self.__probe_device()
|
self.__probe_device()
|
||||||
except Ft232Exception as e:
|
except (SerialException, SC64Exception):
|
||||||
if (self.__usb):
|
if (self.__usb):
|
||||||
self.__usb.close()
|
self.__usb.close()
|
||||||
raise SC64Exception(f"No SummerCart64 device was found: {e}")
|
continue
|
||||||
|
device_found = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if (not device_found):
|
||||||
|
raise SC64Exception("No SummerCart64 device was found")
|
||||||
|
|
||||||
|
|
||||||
def __probe_device(self) -> None:
|
def __probe_device(self) -> None:
|
||||||
@ -197,25 +194,22 @@ class SC64:
|
|||||||
self.__read_cmd_status("C")
|
self.__read_cmd_status("C")
|
||||||
|
|
||||||
|
|
||||||
def __read_file_from_sdram(self, file: str, offset: int, length: int, align: int = 2) -> None:
|
def __read_file_from_sdram(self, file: str, offset: int, length: int) -> None:
|
||||||
with open(file, "wb") as f:
|
with open(file, "wb") as f:
|
||||||
transfer_size = self.__align(length, align)
|
self.__set_progress_init(length, os.path.basename(f.name))
|
||||||
self.__set_progress_init(transfer_size, os.path.basename(f.name))
|
self.__write_cmd("R", offset, length)
|
||||||
self.__write_cmd("R", offset, transfer_size)
|
|
||||||
while (f.tell() < length):
|
while (f.tell() < length):
|
||||||
chunk_size = min(self.__CHUNK_SIZE, length - f.tell())
|
chunk_size = min(self.__CHUNK_SIZE, length - f.tell())
|
||||||
f.write(self.__read(chunk_size))
|
f.write(self.__read(chunk_size))
|
||||||
self.__set_progress_value(f.tell())
|
self.__set_progress_value(f.tell())
|
||||||
if (transfer_size != length):
|
|
||||||
self.__read(transfer_size - length)
|
|
||||||
self.__read_cmd_status("R")
|
self.__read_cmd_status("R")
|
||||||
self.__set_progress_finish()
|
self.__set_progress_finish()
|
||||||
|
|
||||||
|
|
||||||
def __write_file_to_sdram(self, file: str, offset: int, align: int = 2, min_length: int = 0) -> None:
|
def __write_file_to_sdram(self, file: str, offset: int, min_length: int = 0) -> None:
|
||||||
with open(file, "rb") as f:
|
with open(file, "rb") as f:
|
||||||
length = os.fstat(f.fileno()).st_size
|
length = os.fstat(f.fileno()).st_size
|
||||||
transfer_size = self.__align(max(length, min_length), align)
|
transfer_size = max(length, min_length)
|
||||||
self.__set_progress_init(transfer_size, os.path.basename(f.name))
|
self.__set_progress_init(transfer_size, os.path.basename(f.name))
|
||||||
self.__write_cmd("W", offset, transfer_size)
|
self.__write_cmd("W", offset, transfer_size)
|
||||||
while (f.tell() < length):
|
while (f.tell() < length):
|
||||||
@ -243,7 +237,7 @@ class SC64:
|
|||||||
def __reconfigure(self) -> None:
|
def __reconfigure(self) -> None:
|
||||||
magic = self.__query_config(self.__CFG_ID_RECONFIGURE)
|
magic = self.__query_config(self.__CFG_ID_RECONFIGURE)
|
||||||
self.__change_config(self.__CFG_ID_RECONFIGURE, magic, ignore_response=True)
|
self.__change_config(self.__CFG_ID_RECONFIGURE, magic, ignore_response=True)
|
||||||
time.sleep(0.2)
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
|
||||||
def backup_firmware(self, file: str) -> None:
|
def backup_firmware(self, file: str) -> None:
|
||||||
@ -259,7 +253,6 @@ class SC64:
|
|||||||
self.__change_config(self.__CFG_ID_FLASH_PROGRAM, self.__UPDATE_OFFSET)
|
self.__change_config(self.__CFG_ID_FLASH_PROGRAM, self.__UPDATE_OFFSET)
|
||||||
self.__usb.timeout = saved_timeout
|
self.__usb.timeout = saved_timeout
|
||||||
self.__reconfigure()
|
self.__reconfigure()
|
||||||
self.__find_sc64()
|
|
||||||
|
|
||||||
|
|
||||||
def set_rtc(self, t: datetime) -> None:
|
def set_rtc(self, t: datetime) -> None:
|
||||||
@ -544,7 +537,7 @@ class SC64:
|
|||||||
data += struct.pack(">I", offset)
|
data += struct.pack(">I", offset)
|
||||||
self.__disk_lba_table[lba] = offset
|
self.__disk_lba_table[lba] = offset
|
||||||
self.__write_cmd("W", thb_table_offset, len(data))
|
self.__write_cmd("W", thb_table_offset, len(data))
|
||||||
self.__write(data)
|
self.__write(bytes(data))
|
||||||
self.__read_cmd_status("W")
|
self.__read_cmd_status("W")
|
||||||
id_mapping = {
|
id_mapping = {
|
||||||
"retail": self.__DD_DRIVE_ID_RETAIL,
|
"retail": self.__DD_DRIVE_ID_RETAIL,
|
||||||
@ -561,26 +554,28 @@ class SC64:
|
|||||||
def __debug_process_fsd_read(self, data: bytes) -> None:
|
def __debug_process_fsd_read(self, data: bytes) -> None:
|
||||||
sector = int.from_bytes(data[0:4], byteorder="little")
|
sector = int.from_bytes(data[0:4], byteorder="little")
|
||||||
offset = int.from_bytes(data[4:8], byteorder="little")
|
offset = int.from_bytes(data[4:8], byteorder="little")
|
||||||
|
count = int.from_bytes(data[8:12], byteorder="little")
|
||||||
|
|
||||||
if (self.__fsd_file):
|
if (self.__fsd_file):
|
||||||
self.__fsd_file.seek(sector * 512)
|
self.__fsd_file.seek(sector * 512)
|
||||||
self.__write_cmd("T", offset, 512)
|
self.__write_cmd("S", offset, count * 512)
|
||||||
self.__write(self.__fsd_file.read(512))
|
self.__write(self.__fsd_file.read(count * 512))
|
||||||
else:
|
else:
|
||||||
self.__write_cmd("T", offset, 0)
|
self.__write_cmd("S", offset, 0)
|
||||||
|
|
||||||
|
|
||||||
def __debug_process_fsd_write(self, data: bytes) -> None:
|
def __debug_process_fsd_write(self, data: bytes) -> None:
|
||||||
sector = int.from_bytes(data[0:4], byteorder="little")
|
sector = int.from_bytes(data[0:4], byteorder="little")
|
||||||
offset = int.from_bytes(data[4:8], byteorder="little")
|
offset = int.from_bytes(data[4:8], byteorder="little")
|
||||||
|
count = int.from_bytes(data[8:12], byteorder="little")
|
||||||
|
|
||||||
if (self.__fsd_file):
|
if (self.__fsd_file):
|
||||||
with helpers.lock_volume(self.__fsd_file):
|
with helpers.lock_volume(self.__fsd_file):
|
||||||
self.__fsd_file.seek(sector * 512)
|
self.__fsd_file.seek(sector * 512)
|
||||||
self.__write_cmd("F", offset, 512)
|
self.__write_cmd("L", offset, count * 512)
|
||||||
self.__fsd_file.write(self.__read(512))
|
self.__fsd_file.write(self.__read(count * 512))
|
||||||
else:
|
else:
|
||||||
self.__write_cmd("F", offset, 0)
|
self.__write_cmd("L", offset, 0)
|
||||||
|
|
||||||
|
|
||||||
def __debug_process_dd_block(self, data: bytes) -> None:
|
def __debug_process_dd_block(self, data: bytes) -> None:
|
||||||
@ -588,7 +583,7 @@ class SC64:
|
|||||||
sdram_offset = int.from_bytes(data[4:8], byteorder="little")
|
sdram_offset = int.from_bytes(data[4:8], byteorder="little")
|
||||||
disk_file_offset = int.from_bytes(data[8:12], byteorder="big")
|
disk_file_offset = int.from_bytes(data[8:12], byteorder="big")
|
||||||
block_length = int.from_bytes(data[12:16], byteorder="little")
|
block_length = int.from_bytes(data[12:16], byteorder="little")
|
||||||
|
print(f"DD BLOCK {disk_file_offset:08X} {block_length}")
|
||||||
if (self.__disk_file):
|
if (self.__disk_file):
|
||||||
self.__disk_file.seek(disk_file_offset)
|
self.__disk_file.seek(disk_file_offset)
|
||||||
if (transfer_mode):
|
if (transfer_mode):
|
||||||
@ -605,10 +600,8 @@ class SC64:
|
|||||||
def __debug_process_is_viewer(self, data: bytes) -> None:
|
def __debug_process_is_viewer(self, data: bytes) -> None:
|
||||||
length = int.from_bytes(data[0:4], byteorder="little")
|
length = int.from_bytes(data[0:4], byteorder="little")
|
||||||
address = int.from_bytes(data[4:8], byteorder="little")
|
address = int.from_bytes(data[4:8], byteorder="little")
|
||||||
offset = (address & 0x01)
|
self.__write_cmd("L", address, length)
|
||||||
transfer_length = self.__align(length + offset, 2)
|
text = self.__read(length)
|
||||||
self.__write_cmd("L", (address & 0xFFFFFFFE), transfer_length)
|
|
||||||
text = self.__read(transfer_length)[offset:][:length]
|
|
||||||
print(text.decode("EUC-JP", errors="backslashreplace"), end="")
|
print(text.decode("EUC-JP", errors="backslashreplace"), end="")
|
||||||
|
|
||||||
|
|
||||||
@ -625,13 +618,9 @@ class SC64:
|
|||||||
|
|
||||||
print("\r\n\033[34m --- Debug server started --- \033[0m\r\n")
|
print("\r\n\033[34m --- Debug server started --- \033[0m\r\n")
|
||||||
|
|
||||||
self.__usb.setTimeout(0.1)
|
|
||||||
|
|
||||||
start_indicator = bytearray()
|
start_indicator = bytearray()
|
||||||
dropped_bytes = 0
|
dropped_bytes = 0
|
||||||
|
|
||||||
self.__reset_n64("release")
|
|
||||||
|
|
||||||
while (True):
|
while (True):
|
||||||
while (start_indicator != b"DMA@"):
|
while (start_indicator != b"DMA@"):
|
||||||
start_indicator.append(self.__read_long(1)[0])
|
start_indicator.append(self.__read_long(1)[0])
|
||||||
@ -752,6 +741,8 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
sc64 = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sc64 = SC64()
|
sc64 = SC64()
|
||||||
|
|
||||||
@ -855,7 +846,6 @@ if __name__ == "__main__":
|
|||||||
pass
|
pass
|
||||||
finally:
|
finally:
|
||||||
if (sc64):
|
if (sc64):
|
||||||
sc64.reset_link()
|
|
||||||
if (disk_file):
|
if (disk_file):
|
||||||
print(f"Setting 64DD disk state to [Ejected]")
|
print(f"Setting 64DD disk state to [Ejected]")
|
||||||
sc64.set_dd_disk_state("ejected")
|
sc64.set_dd_disk_state("ejected")
|
||||||
|
@ -6,7 +6,7 @@ OBJDUMP = $(TOOLCHAIN)objdump
|
|||||||
SIZE = $(TOOLCHAIN)size
|
SIZE = $(TOOLCHAIN)size
|
||||||
|
|
||||||
FLAGS = -mabi=ilp32 -march=rv32i $(USER_FLAGS)
|
FLAGS = -mabi=ilp32 -march=rv32i $(USER_FLAGS)
|
||||||
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -MMD -MP
|
CFLAGS = -Os -Wall -ffunction-sections -fdata-sections -ffreestanding -fno-delete-null-pointer-checks -MMD -MP
|
||||||
LDFLAGS = -nostartfiles -Wl,--gc-sections
|
LDFLAGS = -nostartfiles -Wl,--gc-sections
|
||||||
|
|
||||||
SRC_DIR = src
|
SRC_DIR = src
|
||||||
@ -17,7 +17,6 @@ SRC_FILES = \
|
|||||||
process.c \
|
process.c \
|
||||||
usb.c \
|
usb.c \
|
||||||
cfg.c \
|
cfg.c \
|
||||||
dma.c \
|
|
||||||
joybus.c \
|
joybus.c \
|
||||||
rtc.c \
|
rtc.c \
|
||||||
i2c.c \
|
i2c.c \
|
||||||
@ -46,7 +45,7 @@ $(BUILD_DIR)/governor.elf: $(OBJS) SC64.ld
|
|||||||
@$(OBJDUMP) -D $@ > $(BUILD_DIR)/governor.lst
|
@$(OBJDUMP) -D $@ > $(BUILD_DIR)/governor.lst
|
||||||
|
|
||||||
$(BUILD_DIR)/governor.bin: $(BUILD_DIR)/governor.elf
|
$(BUILD_DIR)/governor.bin: $(BUILD_DIR)/governor.elf
|
||||||
@$(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0x10016800 $< $@
|
@$(OBJCOPY) -O binary --gap-fill 0xFF --pad-to 0x00016800 $< $@
|
||||||
|
|
||||||
$(BUILD_DIR)/governor.hex: $(BUILD_DIR)/governor.bin
|
$(BUILD_DIR)/governor.hex: $(BUILD_DIR)/governor.bin
|
||||||
@$(OBJCOPY) -I binary -O ihex $< $@
|
@$(OBJCOPY) -I binary -O ihex $< $@
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
MEMORY {
|
MEMORY {
|
||||||
ram (rwx) : org = 0x00000000, len = 15k
|
rom (rx) : org = 0x00010000, len = 26k
|
||||||
buffer (rw) : org = 0x00003C00, len = 1k
|
ram (rwx) : org = 0x10000000, len = 32k
|
||||||
rom (rx) : org = 0x10010000, len = 26k
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ENTRY(reset_handler)
|
ENTRY(reset_handler)
|
||||||
@ -45,10 +44,6 @@ SECTIONS {
|
|||||||
_ebss = .;
|
_ebss = .;
|
||||||
} > ram
|
} > ram
|
||||||
|
|
||||||
.buffer : {
|
|
||||||
*(.buffer)
|
|
||||||
} > buffer
|
|
||||||
|
|
||||||
__global_pointer$ = MIN(_ssdata + 0x800, MAX(_sdata + 0x800, _ebss - 0x800));
|
__global_pointer$ = MIN(_ssdata + 0x800, MAX(_sdata + 0x800, _ebss - 0x800));
|
||||||
__stack_pointer$ = ORIGIN(ram) + LENGTH(ram);
|
__stack_pointer$ = ORIGIN(ram) + LENGTH(ram);
|
||||||
}
|
}
|
||||||
|
@ -311,9 +311,7 @@ void process_cfg (void) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
if (args[0] == 0) {
|
if (args[0] & (1 << 31)) {
|
||||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
|
||||||
} else if (args[0] == 1) {
|
|
||||||
p.usb_drive_busy = false;
|
p.usb_drive_busy = false;
|
||||||
} else {
|
} else {
|
||||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||||
@ -321,10 +319,7 @@ void process_cfg (void) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xF1:
|
case 0xF1:
|
||||||
if (args[0] == 0) {
|
if (args[0] & (1 << 31)) {
|
||||||
args[0] = 0;
|
|
||||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
|
||||||
} else if (args[0] == 1) {
|
|
||||||
args[0] = p.usb_drive_busy;
|
args[0] = p.usb_drive_busy;
|
||||||
} else {
|
} else {
|
||||||
args[0] = 0;
|
args[0] = 0;
|
||||||
@ -334,14 +329,13 @@ void process_cfg (void) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xF2:
|
case 0xF2:
|
||||||
if ((args[0] & 0xFF) == 0) {
|
if (args[0] & (1 << 31)) {
|
||||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
if (!p.usb_drive_busy) {
|
||||||
} else if ((args[0] & 0xFF) == 1 && (!p.usb_drive_busy)) {
|
|
||||||
usb_event_t event;
|
usb_event_t event;
|
||||||
event.id = EVENT_ID_FSD_READ;
|
event.id = EVENT_ID_FSD_READ;
|
||||||
event.trigger = CALLBACK_BUFFER_WRITE;
|
event.trigger = CALLBACK_SDRAM_WRITE;
|
||||||
event.callback = set_usb_drive_not_busy;
|
event.callback = set_usb_drive_not_busy;
|
||||||
uint32_t data[2] = { args[1], (args[0] >> 8) };
|
uint32_t data[3] = { args[1], (args[0] & 0x7FFFFFFF), 1 };
|
||||||
if (usb_put_event(&event, data, sizeof(data))) {
|
if (usb_put_event(&event, data, sizeof(data))) {
|
||||||
p.usb_drive_busy = true;
|
p.usb_drive_busy = true;
|
||||||
} else {
|
} else {
|
||||||
@ -350,17 +344,19 @@ void process_cfg (void) {
|
|||||||
} else {
|
} else {
|
||||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xF3:
|
case 0xF3:
|
||||||
if ((args[0] & 0xFF) == 0) {
|
if (args[0] & (1 << 31)) {
|
||||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
if (!p.usb_drive_busy) {
|
||||||
} else if ((args[0] & 0xFF) == 1 && (!p.usb_drive_busy)) {
|
|
||||||
usb_event_t event;
|
usb_event_t event;
|
||||||
event.id = EVENT_ID_FSD_WRITE;
|
event.id = EVENT_ID_FSD_WRITE;
|
||||||
event.trigger = CALLBACK_BUFFER_READ;
|
event.trigger = CALLBACK_SDRAM_READ;
|
||||||
event.callback = set_usb_drive_not_busy;
|
event.callback = set_usb_drive_not_busy;
|
||||||
uint32_t data[2] = { args[1], (args[0] >> 8) };
|
uint32_t data[3] = { args[1], (args[0] & 0x7FFFFFFF), 1 };
|
||||||
if (usb_put_event(&event, data, sizeof(data))) {
|
if (usb_put_event(&event, data, sizeof(data))) {
|
||||||
p.usb_drive_busy = true;
|
p.usb_drive_busy = true;
|
||||||
} else {
|
} else {
|
||||||
@ -369,6 +365,9 @@ void process_cfg (void) {
|
|||||||
} else {
|
} else {
|
||||||
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
change_scr_bits(CFG_SCR_CMD_ERROR, true);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xFF:
|
case 0xFF:
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
#include "dma.h"
|
|
||||||
|
|
||||||
|
|
||||||
bool dma_busy (void) {
|
|
||||||
return DMA->SCR & DMA_SCR_BUSY;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dma_start (uint32_t memory_address, size_t length, enum dma_id id, enum dma_dir dir) {
|
|
||||||
DMA->MADDR = memory_address;
|
|
||||||
DMA->ID_LEN = ((id & 0x03) << 30) | (length & 0x3FFFFFFF);
|
|
||||||
DMA->SCR = ((dir == DMA_DIR_TO_SDRAM) ? DMA_SCR_DIR : 0) | DMA_SCR_START;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dma_stop (void) {
|
|
||||||
DMA->SCR = DMA_SCR_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void dma_init (void) {
|
|
||||||
dma_stop();
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
#ifndef DMA_H__
|
|
||||||
#define DMA_H__
|
|
||||||
|
|
||||||
|
|
||||||
#include "sys.h"
|
|
||||||
|
|
||||||
|
|
||||||
enum dma_dir {
|
|
||||||
DMA_DIR_TO_SDRAM,
|
|
||||||
DMA_DIR_FROM_SDRAM,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum dma_id {
|
|
||||||
DMA_ID_USB = 0,
|
|
||||||
DMA_ID_SD = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
bool dma_busy (void);
|
|
||||||
void dma_start (uint32_t memory_address, size_t length, enum dma_id id, enum dma_dir dir);
|
|
||||||
void dma_stop (void);
|
|
||||||
void dma_init (void);
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,6 +1,9 @@
|
|||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
|
|
||||||
|
|
||||||
|
static io32_t dummy;
|
||||||
|
|
||||||
|
|
||||||
uint32_t flash_size (void) {
|
uint32_t flash_size (void) {
|
||||||
return FLASH_SIZE;
|
return FLASH_SIZE;
|
||||||
}
|
}
|
||||||
@ -9,54 +12,30 @@ void flash_read (uint32_t sdram_offset) {
|
|||||||
io32_t *flash = (io32_t *) (FLASH_BASE);
|
io32_t *flash = (io32_t *) (FLASH_BASE);
|
||||||
io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset);
|
io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset);
|
||||||
|
|
||||||
for (size_t i = 0; i < FLASH_SIZE; i += 4) {
|
for (size_t i = 0; i < FLASH_SIZE; i += sizeof(io32_t)) {
|
||||||
*sdram++ = *flash++;
|
*sdram++ = *flash++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void flash_program (uint32_t sdram_offset) {
|
void flash_program (uint32_t sdram_offset) {
|
||||||
uint32_t cr;
|
|
||||||
|
|
||||||
io32_t *flash = (io32_t *) (FLASH_BASE);
|
io32_t *flash = (io32_t *) (FLASH_BASE);
|
||||||
io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset);
|
io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset);
|
||||||
|
|
||||||
cr = FLASH_CONFIG->CR;
|
CFG->SCR |= CFG_SCR_FLASH_WP_DISABLE;
|
||||||
for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) {
|
|
||||||
cr &= ~(1 << (FLASH_CR_WRITE_PROTECT_BIT + sector));
|
|
||||||
}
|
|
||||||
FLASH_CONFIG->CR = cr;
|
|
||||||
|
|
||||||
while ((FLASH_CONFIG->SR & FLASH_SR_STATUS_MASK) != FLASH_SR_STATUS_IDLE);
|
CFG->SCR |= CFG_SCR_FLASH_ERASE_START;
|
||||||
|
|
||||||
for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) {
|
while (CFG->SCR & CFG_SCR_FLASH_ERASE_BUSY);
|
||||||
cr = FLASH_CONFIG->CR;
|
|
||||||
cr &= ~(FLASH_CR_SECTOR_ERASE_MASK);
|
|
||||||
cr |= ((sector + 1) << FLASH_CR_SECTOR_ERASE_BIT);
|
|
||||||
FLASH_CONFIG->CR = cr;
|
|
||||||
|
|
||||||
while ((FLASH_CONFIG->SR & FLASH_SR_STATUS_MASK) == FLASH_SR_STATUS_BUSY_ERASE);
|
for (int i = 0; i < FLASH_SIZE; i += sizeof(io32_t)) {
|
||||||
|
|
||||||
if (!(FLASH_CONFIG->SR & FLASH_SR_ERASE_SUCCESSFUL)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FLASH_CONFIG->SR & FLASH_SR_ERASE_SUCCESSFUL) {
|
|
||||||
for (size_t word = 0; word < FLASH_SIZE; word += 4) {
|
|
||||||
*flash++ = *sdram++;
|
*flash++ = *sdram++;
|
||||||
|
|
||||||
if (!(FLASH_CONFIG->SR & FLASH_SR_WRITE_SUCCESSFUL)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cr = FLASH_CONFIG->CR;
|
CFG->SCR |= CFG_SCR_FLASH_WP_ENABLE;
|
||||||
cr |= FLASH_CR_SECTOR_ERASE_MASK;
|
|
||||||
for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) {
|
flash = (io32_t *) (FLASH_BASE);
|
||||||
cr |= (1 << (FLASH_CR_WRITE_PROTECT_BIT + sector));
|
|
||||||
}
|
dummy = *flash;
|
||||||
FLASH_CONFIG->CR = cr;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "sys.h"
|
#include "sys.h"
|
||||||
|
|
||||||
|
|
||||||
uint32_t flash_size(void);
|
uint32_t flash_size (void);
|
||||||
void flash_read (uint32_t sdram_offset);
|
void flash_read (uint32_t sdram_offset);
|
||||||
void flash_program (uint32_t sdram_offset);
|
void flash_program (uint32_t sdram_offset);
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include "process.h"
|
#include "process.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "cfg.h"
|
#include "cfg.h"
|
||||||
#include "dma.h"
|
|
||||||
#include "joybus.h"
|
#include "joybus.h"
|
||||||
#include "rtc.h"
|
#include "rtc.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
@ -29,7 +28,6 @@ __attribute__((naked)) void process_loop (void) {
|
|||||||
|
|
||||||
usb_init();
|
usb_init();
|
||||||
cfg_init();
|
cfg_init();
|
||||||
dma_init();
|
|
||||||
joybus_init();
|
joybus_init();
|
||||||
rtc_init();
|
rtc_init();
|
||||||
i2c_init();
|
i2c_init();
|
||||||
|
@ -21,54 +21,48 @@ typedef volatile uint16_t io16_t;
|
|||||||
typedef volatile uint32_t io32_t;
|
typedef volatile uint32_t io32_t;
|
||||||
|
|
||||||
|
|
||||||
#define RAM_BASE (0x00000000UL)
|
#define FLASH_BASE (0x00000000UL)
|
||||||
#define RAMBUFFER_SIZE (1024)
|
#define FLASH_SIZE (0x39800)
|
||||||
#define RAM_SIZE ((16 * 1024) - RAMBUFFER_SIZE)
|
|
||||||
#define RAMBUFFER_BASE (RAM_BASE + RAM_SIZE)
|
|
||||||
#define RAM (*((io32_t *) RAM_BASE))
|
|
||||||
#define RAMBUFFER (*((io8_t *) RAMBUFFER_BASE))
|
|
||||||
|
|
||||||
|
|
||||||
#define FLASH_BASE (0x10000000UL)
|
|
||||||
#define FLASH (*((io32_t *) FLASH_BASE))
|
#define FLASH (*((io32_t *) FLASH_BASE))
|
||||||
|
|
||||||
#define FLASH_SIZE (0x39800)
|
|
||||||
#define FLASH_NUM_SECTORS (4)
|
#define RAM_BASE (0x10000000UL)
|
||||||
|
#define RAM_SIZE (16 * 1024)
|
||||||
|
#define RAM (*((io32_t *) RAM_BASE))
|
||||||
|
|
||||||
|
|
||||||
typedef volatile struct flash_config_regs {
|
typedef volatile struct cfg_regs {
|
||||||
io32_t SR;
|
io32_t SCR;
|
||||||
io32_t CR;
|
io32_t DDIPL_OFFSET;
|
||||||
} flash_config_regs_t;
|
io32_t SAVE_OFFSET;
|
||||||
|
io8_t CMD;
|
||||||
|
io8_t __padding[3];
|
||||||
|
io32_t DATA[2];
|
||||||
|
io32_t VERSION;
|
||||||
|
io32_t RECONFIGURE;
|
||||||
|
io32_t ISV_OFFSET;
|
||||||
|
io16_t ISV_RD_PTR;
|
||||||
|
io16_t ISV_CURRENT_RD_PTR;
|
||||||
|
} cfg_regs_t;
|
||||||
|
|
||||||
#define FLASH_CONFIG_BASE (0x18000000UL)
|
#define CFG_BASE (0x20000000UL)
|
||||||
#define FLASH_CONFIG ((flash_config_regs_t *) FLASH_CONFIG_BASE)
|
#define CFG ((cfg_regs_t *) CFG_BASE)
|
||||||
|
|
||||||
#define FLASH_SR_STATUS_MASK (3 << 0)
|
#define CFG_SCR_SDRAM_SWITCH (1 << 0)
|
||||||
#define FLASH_SR_STATUS_IDLE (0)
|
#define CFG_SCR_SDRAM_WRITABLE (1 << 1)
|
||||||
#define FLASH_SR_STATUS_BUSY_ERASE (1)
|
#define CFG_SCR_DD_EN (1 << 2)
|
||||||
#define FLASH_SR_STATUS_BUSY_WRITE (2)
|
#define CFG_SCR_SRAM_EN (1 << 3)
|
||||||
#define FLASH_SR_STATUS_BUSY_READ (3)
|
#define CFG_SCR_SRAM_BANKED (1 << 4)
|
||||||
#define FLASH_SR_READ_SUCCESSFUL (1 << 2)
|
#define CFG_SCR_FLASHRAM_EN (1 << 5)
|
||||||
#define FLASH_SR_WRITE_SUCCESSFUL (1 << 3)
|
#define CFG_SCR_SKIP_BOOTLOADER (1 << 6)
|
||||||
#define FLASH_SR_ERASE_SUCCESSFUL (1 << 4)
|
#define CFG_SCR_ISV_EN (1 << 7)
|
||||||
#define FLASH_SR_WRITE_PROTECT_BIT (5)
|
#define CFG_SCR_FLASH_ERASE_START (1 << 24)
|
||||||
|
#define CFG_SCR_FLASH_ERASE_BUSY (1 << 25)
|
||||||
#define FLASH_CR_PAGE_ERASE_BIT (0)
|
#define CFG_SCR_FLASH_WP_ENABLE (1 << 26)
|
||||||
#define FLASH_CR_SECTOR_ERASE_BIT (20)
|
#define CFG_SCR_FLASH_WP_DISABLE (1 << 27)
|
||||||
#define FLASH_CR_SECTOR_ERASE_MASK (7 << FLASH_CR_SECTOR_ERASE_BIT)
|
#define CFG_SCR_CMD_ERROR (1 << 28)
|
||||||
#define FLASH_CR_WRITE_PROTECT_BIT (23)
|
#define CFG_SCR_CPU_BUSY (1 << 30)
|
||||||
|
#define CFG_SCR_CPU_READY (1 << 31)
|
||||||
|
|
||||||
typedef volatile struct gpio_regs {
|
|
||||||
io8_t ODR;
|
|
||||||
io8_t IDR;
|
|
||||||
io8_t OER;
|
|
||||||
io8_t __padding;
|
|
||||||
} gpio_regs_t;
|
|
||||||
|
|
||||||
#define GPIO_BASE (0x20000000UL)
|
|
||||||
#define GPIO ((gpio_regs_t *) GPIO_BASE)
|
|
||||||
|
|
||||||
|
|
||||||
typedef volatile struct i2c_regs {
|
typedef volatile struct i2c_regs {
|
||||||
@ -90,8 +84,8 @@ typedef volatile struct usb_regs {
|
|||||||
io32_t SCR;
|
io32_t SCR;
|
||||||
io8_t DR;
|
io8_t DR;
|
||||||
io8_t __padding_1[3];
|
io8_t __padding_1[3];
|
||||||
io8_t ESCAPE;
|
io32_t ADDR;
|
||||||
io8_t __padding_2[3];
|
io32_t LEN;
|
||||||
} usb_regs_t;
|
} usb_regs_t;
|
||||||
|
|
||||||
#define USB_BASE (0x40000000UL)
|
#define USB_BASE (0x40000000UL)
|
||||||
@ -101,11 +95,14 @@ typedef volatile struct usb_regs {
|
|||||||
#define USB_SCR_TXE (1 << 1)
|
#define USB_SCR_TXE (1 << 1)
|
||||||
#define USB_SCR_FLUSH_RX (1 << 2)
|
#define USB_SCR_FLUSH_RX (1 << 2)
|
||||||
#define USB_SCR_FLUSH_TX (1 << 3)
|
#define USB_SCR_FLUSH_TX (1 << 3)
|
||||||
#define USB_SCR_ENABLED (1 << 4)
|
#define USB_SCR_ENABLE (1 << 4)
|
||||||
#define USB_SCR_PWREN (1 << 5)
|
#define USB_SCR_FORCE_TX (1 << 5)
|
||||||
#define USB_SCR_ESCAPE_PENDING (1 << 6)
|
#define USB_SCR_RESET_PENDING (1 << 6)
|
||||||
#define USB_SCR_ESCAPE_ACK (1 << 7)
|
#define USB_SCR_RESET_ACK (1 << 7)
|
||||||
#define USB_SCR_FORCE_TX (1 << 8)
|
#define USB_SCR_DMA_BUSY (1 << 8)
|
||||||
|
#define USB_SCR_DMA_START (1 << 9)
|
||||||
|
#define USB_SCR_DMA_STOP (1 << 10)
|
||||||
|
#define USB_SCR_DMA_DIR (1 << 11)
|
||||||
|
|
||||||
|
|
||||||
typedef volatile struct uart_regs {
|
typedef volatile struct uart_regs {
|
||||||
@ -121,91 +118,6 @@ typedef volatile struct uart_regs {
|
|||||||
#define UART_SCR_TXE (1 << 1)
|
#define UART_SCR_TXE (1 << 1)
|
||||||
|
|
||||||
|
|
||||||
typedef volatile struct dma_regs {
|
|
||||||
io32_t SCR;
|
|
||||||
io32_t MADDR;
|
|
||||||
io32_t ID_LEN;
|
|
||||||
} dma_regs_t;
|
|
||||||
|
|
||||||
#define DMA_BASE (0x60000000UL)
|
|
||||||
#define DMA ((dma_regs_t *) DMA_BASE)
|
|
||||||
|
|
||||||
#define DMA_SCR_START (1 << 0)
|
|
||||||
#define DMA_SCR_STOP (1 << 1)
|
|
||||||
#define DMA_SCR_DIR (1 << 2)
|
|
||||||
#define DMA_SCR_BUSY (1 << 3)
|
|
||||||
|
|
||||||
|
|
||||||
typedef volatile struct cfg_regs {
|
|
||||||
io32_t SCR;
|
|
||||||
io32_t DDIPL_OFFSET;
|
|
||||||
io32_t SAVE_OFFSET;
|
|
||||||
io8_t CMD;
|
|
||||||
io8_t __padding[3];
|
|
||||||
io32_t DATA[2];
|
|
||||||
io32_t VERSION;
|
|
||||||
io32_t RECONFIGURE;
|
|
||||||
io32_t ISV_OFFSET;
|
|
||||||
io16_t ISV_RD_PTR;
|
|
||||||
io16_t ISV_CURRENT_RD_PTR;
|
|
||||||
} cfg_regs_t;
|
|
||||||
|
|
||||||
#define CFG_BASE (0x70000000UL)
|
|
||||||
#define CFG ((cfg_regs_t *) CFG_BASE)
|
|
||||||
|
|
||||||
#define CFG_SCR_SDRAM_SWITCH (1 << 0)
|
|
||||||
#define CFG_SCR_SDRAM_WRITABLE (1 << 1)
|
|
||||||
#define CFG_SCR_DD_EN (1 << 2)
|
|
||||||
#define CFG_SCR_SRAM_EN (1 << 3)
|
|
||||||
#define CFG_SCR_SRAM_BANKED (1 << 4)
|
|
||||||
#define CFG_SCR_FLASHRAM_EN (1 << 5)
|
|
||||||
#define CFG_SCR_SKIP_BOOTLOADER (1 << 6)
|
|
||||||
#define CFG_SCR_ISV_EN (1 << 7)
|
|
||||||
#define CFG_SCR_CMD_ERROR (1 << 28)
|
|
||||||
#define CFG_SCR_CPU_BUSY (1 << 30)
|
|
||||||
#define CFG_SCR_CPU_READY (1 << 31)
|
|
||||||
|
|
||||||
|
|
||||||
#define SDRAM_BASE (0x80000000UL)
|
|
||||||
#define SDRAM (*((io32_t *) SDRAM_BASE))
|
|
||||||
#define SDRAM_SIZE (64 * 1024 * 1024)
|
|
||||||
|
|
||||||
|
|
||||||
typedef volatile struct flashram_regs {
|
|
||||||
io32_t SCR;
|
|
||||||
io32_t __padding[31];
|
|
||||||
io32_t BUFFER[32];
|
|
||||||
} flashram_regs_t;
|
|
||||||
|
|
||||||
#define FLASHRAM_BASE (0x90000000UL)
|
|
||||||
#define FLASHRAM ((flashram_regs_t *) FLASHRAM_BASE)
|
|
||||||
|
|
||||||
#define FLASHRAM_OPERATION_PENDING (1 << 0)
|
|
||||||
#define FLASHRAM_OPERATION_DONE (1 << 1)
|
|
||||||
#define FLASHRAM_WRITE_OR_ERASE (1 << 2)
|
|
||||||
#define FLASHRAM_SECTOR_OR_ALL (1 << 3)
|
|
||||||
#define FLASHRAM_PAGE_BIT (8)
|
|
||||||
|
|
||||||
|
|
||||||
typedef volatile struct joybus_regs {
|
|
||||||
io32_t SCR;
|
|
||||||
io32_t DATA[3];
|
|
||||||
} joybus_regs_t;
|
|
||||||
|
|
||||||
#define JOYBUS_BASE (0xA0000000UL)
|
|
||||||
#define JOYBUS ((joybus_regs_t *) JOYBUS_BASE)
|
|
||||||
|
|
||||||
#define JOYBUS_SCR_RX_READY (1 << 0)
|
|
||||||
#define JOYBUS_SCR_RX_STOP_BIT (1 << 1)
|
|
||||||
#define JOYBUS_SCR_TX_START (1 << 2)
|
|
||||||
#define JOYBUS_SCR_TX_BUSY (1 << 3)
|
|
||||||
#define JOYBUS_SCR_RX_RESET (1 << 6)
|
|
||||||
#define JOYBUS_SCR_TX_RESET (1 << 7)
|
|
||||||
#define JOYBUS_SCR_RX_LENGTH_BIT (8)
|
|
||||||
#define JOYBUS_SCR_RX_LENGTH_MASK (0x7F << JOYBUS_SCR_RX_LENGTH_BIT)
|
|
||||||
#define JOYBUS_SCR_TX_LENGTH_BIT (16)
|
|
||||||
|
|
||||||
|
|
||||||
typedef volatile struct dd_regs {
|
typedef volatile struct dd_regs {
|
||||||
io32_t SCR;
|
io32_t SCR;
|
||||||
io16_t DATA;
|
io16_t DATA;
|
||||||
@ -224,7 +136,7 @@ typedef volatile struct dd_regs {
|
|||||||
io32_t SECTOR_BUFFER[64];
|
io32_t SECTOR_BUFFER[64];
|
||||||
} dd_regs_t;
|
} dd_regs_t;
|
||||||
|
|
||||||
#define DD_BASE (0xB0000000UL)
|
#define DD_BASE (0x60000000UL)
|
||||||
#define DD ((dd_regs_t *) DD_BASE)
|
#define DD ((dd_regs_t *) DD_BASE)
|
||||||
|
|
||||||
#define DD_SCR_HARD_RESET (1 << 0)
|
#define DD_SCR_HARD_RESET (1 << 0)
|
||||||
@ -255,6 +167,46 @@ typedef volatile struct dd_regs {
|
|||||||
#define DD_HEAD_TRACK_INDEX_LOCK (1 << 13)
|
#define DD_HEAD_TRACK_INDEX_LOCK (1 << 13)
|
||||||
|
|
||||||
|
|
||||||
|
#define SDRAM_BASE (0x70000000UL)
|
||||||
|
#define SDRAM (*((io32_t *) SDRAM_BASE))
|
||||||
|
#define SDRAM_SIZE (64 * 1024 * 1024)
|
||||||
|
|
||||||
|
|
||||||
|
typedef volatile struct flashram_regs {
|
||||||
|
io32_t SCR;
|
||||||
|
io32_t __padding[31];
|
||||||
|
io32_t BUFFER[32];
|
||||||
|
} flashram_regs_t;
|
||||||
|
|
||||||
|
#define FLASHRAM_BASE (0x80000000UL)
|
||||||
|
#define FLASHRAM ((flashram_regs_t *) FLASHRAM_BASE)
|
||||||
|
|
||||||
|
#define FLASHRAM_OPERATION_PENDING (1 << 0)
|
||||||
|
#define FLASHRAM_OPERATION_DONE (1 << 1)
|
||||||
|
#define FLASHRAM_WRITE_OR_ERASE (1 << 2)
|
||||||
|
#define FLASHRAM_SECTOR_OR_ALL (1 << 3)
|
||||||
|
#define FLASHRAM_PAGE_BIT (8)
|
||||||
|
|
||||||
|
|
||||||
|
typedef volatile struct joybus_regs {
|
||||||
|
io32_t SCR;
|
||||||
|
io32_t DATA[3];
|
||||||
|
} joybus_regs_t;
|
||||||
|
|
||||||
|
#define JOYBUS_BASE (0x90000000UL)
|
||||||
|
#define JOYBUS ((joybus_regs_t *) JOYBUS_BASE)
|
||||||
|
|
||||||
|
#define JOYBUS_SCR_RX_READY (1 << 0)
|
||||||
|
#define JOYBUS_SCR_RX_STOP_BIT (1 << 1)
|
||||||
|
#define JOYBUS_SCR_TX_START (1 << 2)
|
||||||
|
#define JOYBUS_SCR_TX_BUSY (1 << 3)
|
||||||
|
#define JOYBUS_SCR_RX_RESET (1 << 6)
|
||||||
|
#define JOYBUS_SCR_TX_RESET (1 << 7)
|
||||||
|
#define JOYBUS_SCR_RX_LENGTH_BIT (8)
|
||||||
|
#define JOYBUS_SCR_RX_LENGTH_MASK (0x7F << JOYBUS_SCR_RX_LENGTH_BIT)
|
||||||
|
#define JOYBUS_SCR_TX_LENGTH_BIT (16)
|
||||||
|
|
||||||
|
|
||||||
void reset_handler(void);
|
void reset_handler(void);
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
#include "dma.h"
|
|
||||||
#include "cfg.h"
|
#include "cfg.h"
|
||||||
#include "dd.h"
|
#include "dd.h"
|
||||||
|
|
||||||
@ -140,24 +139,12 @@ static bool rx_cmd (uint32_t *data) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_escape (void) {
|
|
||||||
if (USB->SCR & USB_SCR_ESCAPE_PENDING) {
|
|
||||||
if (USB->ESCAPE == 'R') {
|
|
||||||
if (p.dma_in_progress) {
|
|
||||||
dma_stop();
|
|
||||||
while (dma_busy());
|
|
||||||
}
|
|
||||||
usb_init();
|
|
||||||
}
|
|
||||||
USB->SCR |= USB_SCR_ESCAPE_ACK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void usb_init (void) {
|
void usb_init (void) {
|
||||||
USB->SCR = (USB_SCR_ENABLED | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX);
|
USB->SCR = (USB_SCR_DMA_STOP | USB_SCR_ENABLE | USB_SCR_FLUSH_TX | USB_SCR_FLUSH_RX);
|
||||||
|
|
||||||
p.state = STATE_IDLE;
|
p.state = STATE_IDLE;
|
||||||
|
p.dma_in_progress = false;
|
||||||
p.event_pending = false;
|
p.event_pending = false;
|
||||||
p.event_callback_pending = false;
|
p.event_callback_pending = false;
|
||||||
|
|
||||||
@ -170,7 +157,11 @@ void usb_init (void) {
|
|||||||
|
|
||||||
|
|
||||||
void process_usb (void) {
|
void process_usb (void) {
|
||||||
handle_escape();
|
if (USB->SCR & USB_SCR_RESET_PENDING) {
|
||||||
|
usb_init();
|
||||||
|
USB->SCR |= USB_SCR_RESET_ACK;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (p.state) {
|
switch (p.state) {
|
||||||
case STATE_IDLE:
|
case STATE_IDLE:
|
||||||
@ -247,11 +238,15 @@ void process_usb (void) {
|
|||||||
case 'W':
|
case 'W':
|
||||||
case 'L':
|
case 'L':
|
||||||
case 'S':
|
case 'S':
|
||||||
if (!dma_busy()) {
|
if (!(USB->SCR & USB_SCR_DMA_BUSY)) {
|
||||||
if (!p.dma_in_progress) {
|
if (!p.dma_in_progress) {
|
||||||
bool is_write = (p.cmd == 'W') || (p.cmd == 'S');
|
USB->ADDR = p.args[0];
|
||||||
enum dma_dir dir = is_write ? DMA_DIR_TO_SDRAM : DMA_DIR_FROM_SDRAM;
|
USB->LEN = p.args[1];
|
||||||
dma_start(p.args[0], p.args[1], DMA_ID_USB, dir);
|
if ((p.cmd == 'W') || (p.cmd == 'S')) {
|
||||||
|
USB->SCR |= (USB_SCR_DMA_DIR | USB_SCR_DMA_START);
|
||||||
|
} else {
|
||||||
|
USB->SCR |= USB_SCR_DMA_START;
|
||||||
|
}
|
||||||
p.dma_in_progress = true;
|
p.dma_in_progress = true;
|
||||||
} else {
|
} else {
|
||||||
if (p.cmd == 'L' || p.cmd == 'S') {
|
if (p.cmd == 'L' || p.cmd == 'S') {
|
||||||
@ -276,43 +271,6 @@ void process_usb (void) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'F':
|
|
||||||
case 'T':
|
|
||||||
while ((p.args[0] + p.counter) != (p.args[0] + p.args[1])) {
|
|
||||||
uint8_t *buffer = (uint8_t *) (RAMBUFFER_BASE + p.args[0] + p.counter);
|
|
||||||
if (p.cmd == 'F') {
|
|
||||||
if (tx_byte(*buffer)) {
|
|
||||||
p.counter += 1;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p.cmd == 'T') {
|
|
||||||
if (rx_byte(buffer)) {
|
|
||||||
p.counter += 1;
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((p.args[0] + p.counter) == (p.args[0] + p.args[1])) {
|
|
||||||
if (p.event_callback_pending) {
|
|
||||||
if (p.cmd == 'F' && p.event.trigger == CALLBACK_BUFFER_READ) {
|
|
||||||
p.event_callback_pending = false;
|
|
||||||
p.event.callback();
|
|
||||||
}
|
|
||||||
if (p.cmd == 'T' && p.event.trigger == CALLBACK_BUFFER_WRITE) {
|
|
||||||
p.event_callback_pending = false;
|
|
||||||
p.event.callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (p.cmd == 'F') {
|
|
||||||
USB->SCR |= USB_SCR_FORCE_TX;
|
|
||||||
}
|
|
||||||
p.state = STATE_IDLE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
p.error = true;
|
p.error = true;
|
||||||
p.state = STATE_RESPONSE;
|
p.state = STATE_RESPONSE;
|
||||||
|
@ -18,8 +18,6 @@ typedef enum {
|
|||||||
CALLBACK_NONE = 0,
|
CALLBACK_NONE = 0,
|
||||||
CALLBACK_SDRAM_WRITE = 1,
|
CALLBACK_SDRAM_WRITE = 1,
|
||||||
CALLBACK_SDRAM_READ = 2,
|
CALLBACK_SDRAM_READ = 2,
|
||||||
CALLBACK_BUFFER_WRITE = 3,
|
|
||||||
CALLBACK_BUFFER_READ = 4,
|
|
||||||
} usb_event_callback_t;
|
} usb_event_callback_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user