diff --git a/build.sh b/build.sh index e630d35..5ef217b 100755 --- a/build.sh +++ b/build.sh @@ -86,7 +86,7 @@ build_fpga () { pushd fw > /dev/null if [ "$SKIP_FPGA_REBUILD" = true ] && [ -f output_files/SummerCart64.sof ]; then - echo Skipping FPGA build + quartus_cpf -c SummerCart64.cof else if [ "$DEBUG_ENABLED" = true ]; then quartus_sh --set VERILOG_MACRO="DEBUG" ./SummerCart64.qpf diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index d24b06c..78c8bda 100644 --- a/fw/SummerCart64.qsf +++ b/fw/SummerCart64.qsf @@ -19,7 +19,7 @@ # # Quartus Prime # 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 NUM_PARALLEL_PROCESSORS ALL 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 QIP_FILE rtl/intel/fifo/intel_fifo_8.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_cfg.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_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_ram.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_usb.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/n64/n64_bootloader.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/system.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 # ========================== @@ -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_119 -to io_sd_dat[3] 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_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_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_SHOW_LMF_MAPPING_MESSAGES OFF set_global_assignment -name TOP_LEVEL_ENTITY SummerCart64 +set_global_assignment -name VERILOG_MACRO DEBUG # 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 INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE" 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 # ===================== @@ -226,10 +231,8 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" - # 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 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_reset 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_alel 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_rtc_scl 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 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 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_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 # ================== @@ -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_alel 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 # start DESIGN_PARTITION(Top) diff --git a/fw/SummerCart64.sdc b/fw/SummerCart64.sdc index 530e475..4cbd4d7 100644 --- a/fw/SummerCart64.sdc +++ b/fw/SummerCart64.sdc @@ -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} 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_clk -source [get_pins $sd_reg_clk] [get_ports {o_sd_clk}] - 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}] \ -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_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 @@ -48,8 +49,17 @@ set_multicycle_path -setup -end 2 -from [get_clocks {sdram_clk}] -to [get_clocks # FT1248 timings -set_false_path -to [get_ports {o_usb_clk 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}] -max 5.0 [get_ports {io_usb_miosi[*] o_usb_cs}] +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 diff --git a/fw/picorv32 b/fw/picorv32 index f9b1beb..f00a88c 160000 --- a/fw/picorv32 +++ b/fw/picorv32 @@ -1 +1 @@ -Subproject commit f9b1beb4cfd6b382157b54bc8f38c61d5ae7d785 +Subproject commit f00a88c36eaab478b64ee27d8162e421049bcc66 diff --git a/fw/rtl/SummerCart64.sv b/fw/rtl/SummerCart64.sv index 4fa55c3..ac2b36f 100644 --- a/fw/rtl/SummerCart64.sv +++ b/fw/rtl/SummerCart64.sv @@ -29,8 +29,7 @@ module SummerCart64 ( output o_usb_clk, output o_usb_cs, input i_usb_miso, - inout [3:0] io_usb_miosi, - input i_usb_pwren, + inout [7:0] io_usb_miosi, input i_uart_rxd, output o_uart_txd, @@ -42,10 +41,6 @@ module SummerCart64 ( output o_led ); - logic [7:0] gpio_o; - logic [7:0] gpio_i; - logic [7:0] gpio_oe; - logic dd_interrupt; if_system sys ( @@ -56,7 +51,7 @@ module SummerCart64 ( if_config cfg (); - if_dma dma (); + if_memory_dma usb_dma (); if_sdram sdram (); @@ -70,7 +65,6 @@ module SummerCart64 ( .dd_interrupt(dd_interrupt) ); - if_cpu_ram cpu_ram (); system system_inst ( .sys(sys) @@ -85,13 +79,12 @@ module SummerCart64 ( n64_soc n64_soc_inst ( .sys(sys), .cfg(cfg), - .dma(dma), + .usb_dma(usb_dma), .sdram(sdram), .flashram(flashram), .si(si), .flash(flash), .dd(dd), - .cpu_ram(cpu_ram), .n64_pi_alel(i_n64_pi_alel), .n64_pi_aleh(i_n64_pi_aleh), @@ -114,18 +107,13 @@ module SummerCart64 ( cpu_soc cpu_soc_inst ( .sys(sys), .cfg(cfg), - .dma(dma), + .usb_dma(usb_dma), .sdram(sdram), .flashram(flashram), .si(si), .flash(flash), .dd(dd), - .cpu_ram(cpu_ram), - .gpio_o(gpio_o), - .gpio_i(gpio_i), - .gpio_oe(gpio_oe), - .i2c_scl(o_rtc_scl), .i2c_sda(io_rtc_sda), @@ -133,7 +121,6 @@ module SummerCart64 ( .usb_cs(o_usb_cs), .usb_miso(i_usb_miso), .usb_miosi(io_usb_miosi), - .usb_pwren(i_usb_pwren), .uart_rxd(i_uart_rxd), .uart_txd(o_uart_txd), @@ -145,14 +132,7 @@ module SummerCart64 ( always_comb begin o_n64_irq = dd_interrupt ? 1'b0 : 1'bZ; - end - - 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]}; + o_led = 1'bZ; end endmodule diff --git a/fw/rtl/cpu/cpu_bus.sv b/fw/rtl/cpu/cpu_bus.sv index 13579af..b2b1e14 100644 --- a/fw/rtl/cpu/cpu_bus.sv +++ b/fw/rtl/cpu/cpu_bus.sv @@ -1,6 +1,6 @@ -interface if_cpu_bus (); - - localparam [3:0] NUM_DEVICES = sc64::__ID_CPU_END; +interface if_cpu_bus #( + parameter bit [3:0] NUM_DEVICES +) (); logic request; logic ack; diff --git a/fw/rtl/cpu/cpu_cfg.sv b/fw/rtl/cpu/cpu_cfg.sv index dcbcb18..5468996 100644 --- a/fw/rtl/cpu/cpu_cfg.sv +++ b/fw/rtl/cpu/cpu_cfg.sv @@ -18,7 +18,8 @@ module cpu_cfg ( R_VERSION, R_RECONFIGURE, R_ISV_OFFSET, - R_ISV_RD_PTR + R_ISV_RD_PTR, + R_FLASH } e_reg_id; const logic [31:0] RECONFIGURE_MAGIC = 32'h52535446; @@ -39,7 +40,10 @@ module cpu_cfg ( cfg.cpu_busy, 1'b0, cfg.cmd_error, - 20'd0, + 2'd0, + cfg.flash_erase_busy, + 1'd0, + 16'd0, cfg.isv_enabled, skip_bootloader, cfg.flashram_enabled, @@ -73,6 +77,10 @@ module cpu_cfg ( end 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 cfg.cpu_ready <= 1'b0; cfg.cpu_busy <= 1'b0; @@ -95,9 +103,11 @@ module cpu_cfg ( cfg.sdram_writable <= 1'b0; isv_current_rd_ptr <= 16'd0; end + if (cfg.cmd_request) begin cfg.cpu_busy <= 1'b1; end + if (bus.request) begin case (bus.address[5:2]) R_SCR: begin @@ -105,8 +115,11 @@ module cpu_cfg ( { cfg.cpu_ready, cfg.cpu_busy, - cfg.cmd_error - } <= {bus.wdata[31:30], bus.wdata[28]}; + cfg.cmd_error, + cfg.flash_wp_disable, + cfg.flash_wp_enable, + cfg.flash_erase_start + } <= {bus.wdata[31:30], bus.wdata[28:26], bus.wdata[24]}; end if (bus.wmask[0]) begin { @@ -156,31 +169,11 @@ module cpu_cfg ( end end - logic [1:0] ru_clk; - logic ru_rconfig; - logic ru_regout; + vendor_reconfigure vendor_reconfigure_inst ( + .clk(sys.clk), + .reset(sys.reset), - always_ff @(posedge sys.clk) begin - 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) + .trigger_reconfiguration(trigger_reconfiguration) ); endmodule diff --git a/fw/rtl/cpu/cpu_dma.sv b/fw/rtl/cpu/cpu_dma.sv deleted file mode 100644 index 45b2989..0000000 --- a/fw/rtl/cpu/cpu_dma.sv +++ /dev/null @@ -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 diff --git a/fw/rtl/cpu/cpu_flash.sv b/fw/rtl/cpu/cpu_flash.sv index a7c3b6f..fbc0cc3 100644 --- a/fw/rtl/cpu/cpu_flash.sv +++ b/fw/rtl/cpu/cpu_flash.sv @@ -16,7 +16,7 @@ interface if_flash (); output wdata ); - modport memory ( + modport flash ( input request, output ack, input write, diff --git a/fw/rtl/cpu/cpu_gpio.sv b/fw/rtl/cpu/cpu_gpio.sv deleted file mode 100644 index 4877713..0000000 --- a/fw/rtl/cpu/cpu_gpio.sv +++ /dev/null @@ -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 diff --git a/fw/rtl/cpu/cpu_ram.sv b/fw/rtl/cpu/cpu_ram.sv index 62c7af7..3e8cb90 100644 --- a/fw/rtl/cpu/cpu_ram.sv +++ b/fw/rtl/cpu/cpu_ram.sv @@ -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 ( if_system.sys sys, - if_cpu_bus bus, - if_cpu_ram.cpu cpu_ram + if_cpu_bus bus ); - logic [3:0][7:0] ram [0:4095]; - logic [31:0] q_cpu; - logic [31:0] q_external; + logic [3:0][7:0] ram [0:8191]; + logic [31:0] q; always_ff @(posedge sys.clk) begin bus.ack <= 1'b0; @@ -40,33 +14,19 @@ module cpu_ram ( end always_comb begin - cpu_ram.rdata = cpu_ram.address[0] ? q_external[31:16] : q_external[15:0]; bus.rdata = 32'd0; if (bus.ack) begin - bus.rdata = q_cpu; + bus.rdata = q; end end 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.wmask[0]) ram[bus.address[13:2]][0] <= bus.wdata[7:0]; - if (bus.wmask[1]) ram[bus.address[13:2]][1] <= bus.wdata[15:8]; - if (bus.wmask[2]) ram[bus.address[13:2]][2] <= bus.wdata[23:16]; - if (bus.wmask[3]) ram[bus.address[13: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 + if (bus.wmask[0]) ram[bus.address[14:2]][0] <= bus.wdata[7:0]; + if (bus.wmask[1]) ram[bus.address[14:2]][1] <= bus.wdata[15:8]; + if (bus.wmask[2]) ram[bus.address[14:2]][2] <= bus.wdata[23:16]; + if (bus.wmask[3]) ram[bus.address[14:2]][3] <= bus.wdata[31:24]; end end diff --git a/fw/rtl/cpu/cpu_soc.sv b/fw/rtl/cpu/cpu_soc.sv index 95e5053..36eac9b 100644 --- a/fw/rtl/cpu/cpu_soc.sv +++ b/fw/rtl/cpu/cpu_soc.sv @@ -1,17 +1,12 @@ module cpu_soc ( if_system.sys sys, if_config.cpu cfg, - if_dma dma, + if_memory_dma usb_dma, if_sdram.cpu sdram, if_flashram.cpu flashram, if_si.cpu si, - if_flash.cpu flash, + if_flash flash, 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, inout i2c_sda, @@ -19,8 +14,7 @@ module cpu_soc ( output usb_clk, output usb_cs, input usb_miso, - inout [3:0] usb_miosi, - input usb_pwren, + inout [7:0] usb_miosi, input uart_rxd, output uart_txd, @@ -30,98 +24,98 @@ module cpu_soc ( 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 ( .sys(sys), .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 ( .sys(sys), - .bus(bus.at[sc64::ID_CPU_FLASH].device), + .bus(bus.at[DEV_FLASH].device), .flash(flash) ); - cpu_gpio cpu_gpio_inst ( + cpu_ram cpu_ram_inst ( .sys(sys), - .bus(bus.at[sc64::ID_CPU_GPIO].device), - .gpio_i(gpio_i), - .gpio_o(gpio_o), - .gpio_oe(gpio_oe) + .bus(bus.at[DEV_RAM].device) + ); + + cpu_cfg cpu_cfg_inst ( + .sys(sys), + .bus(bus.at[DEV_CFG].device), + .cfg(cfg) ); cpu_i2c cpu_i2c_inst ( .sys(sys), - .bus(bus.at[sc64::ID_CPU_I2C].device), + .bus(bus.at[DEV_I2C].device), .i2c_scl(i2c_scl), .i2c_sda(i2c_sda) ); cpu_usb cpu_usb_inst ( .sys(sys), - .bus(bus.at[sc64::ID_CPU_USB].device), - .dma(dma.at[sc64::ID_DMA_USB].device), + .bus(bus.at[DEV_USB].device), + .dma(usb_dma), .usb_clk(usb_clk), .usb_cs(usb_cs), .usb_miso(usb_miso), - .usb_miosi(usb_miosi), - .usb_pwren(usb_pwren) + .usb_miosi(usb_miosi) ); generate if (sc64::CPU_HAS_UART) begin cpu_uart cpu_uart_inst ( .sys(sys), - .bus(bus.at[sc64::ID_CPU_UART].device), + .bus(bus.at[DEV_UART].device), .uart_rxd(uart_rxd), .uart_txd(uart_txd) ); end endgenerate - cpu_dma cpu_dma_inst ( + cpu_dd cpu_dd_inst ( .sys(sys), - .bus(bus.at[sc64::ID_CPU_DMA].device), - .dma(dma) - ); - - cpu_cfg cpu_cfg_inst ( - .sys(sys), - .bus(bus.at[sc64::ID_CPU_CFG].device), - .cfg(cfg) + .bus(bus.at[DEV_DD].device), + .dd(dd) ); cpu_sdram cpu_sdram_inst ( .sys(sys), - .bus(bus.at[sc64::ID_CPU_SDRAM].device), + .bus(bus.at[DEV_SDRAM].device), .sdram(sdram) ); cpu_flashram cpu_flashram_inst ( .sys(sys), - .bus(bus.at[sc64::ID_CPU_FLASHRAM].device), + .bus(bus.at[DEV_FLASHRAM].device), .flashram(flashram) ); cpu_si cpu_si_inst ( .sys(sys), - .bus(bus.at[sc64::ID_CPU_SI].device), + .bus(bus.at[DEV_SI].device), .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_cmd = 1'bZ; assign sd_dat = 4'bZZZZ; diff --git a/fw/rtl/cpu/cpu_usb.sv b/fw/rtl/cpu/cpu_usb.sv index 76e86d2..f832483 100644 --- a/fw/rtl/cpu/cpu_usb.sv +++ b/fw/rtl/cpu/cpu_usb.sv @@ -1,44 +1,27 @@ module cpu_usb ( if_system sys, if_cpu_bus bus, - if_dma dma, + if_memory_dma dma, output usb_clk, output usb_cs, input usb_miso, - inout [3:0] usb_miosi, - input usb_pwren + inout [7:0] usb_miosi ); logic rx_flush; - logic rx_empty; - logic rx_read; - logic [7:0] rx_rdata; - logic tx_flush; - logic tx_full; - logic tx_write; - logic [7:0] tx_wdata; + logic usb_enable; + logic reset_pending; + logic reset_ack; + logic write_buffer_flush; - logic rx_escape_valid; - logic rx_escape_ack; - logic [7:0] rx_escape; - - logic cpu_rx_read; - logic cpu_tx_write; - - 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 + typedef enum bit [1:0] { + R_SCR, + R_DATA, + R_ADDR, + R_LEN + } e_reg_id; always_ff @(posedge sys.clk) begin bus.ack <= 1'b0; @@ -51,75 +34,93 @@ module cpu_usb ( bus.rdata = 32'd0; if (bus.ack) begin case (bus.address[3:2]) - 0: bus.rdata = {25'd0, rx_escape_valid, usb_pwren, usb_enabled, 2'b00, ~tx_full, ~rx_empty}; - 1: bus.rdata = {24'd0, rx_rdata}; - 2: bus.rdata = {24'd0, rx_escape}; + R_SCR: bus.rdata = { + 23'd0, + 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; endcase end end 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; - cpu_rx_read <= 1'b0; - tx_flush <= 1'b0; - cpu_tx_write <= 1'b0; - - rx_escape_ack <= 1'b0; - tx_force <= 1'b0; + reset_ack <= 1'b0; + write_buffer_flush <= 1'b0; if (sys.reset) begin - usb_enabled <= 1'b0; + usb_enable <= 1'b0; end else begin if (bus.request) begin - case (bus.address[2:2]) - 2'd0: begin - if (bus.wmask[1]) begin - tx_force <= bus.wdata[8]; - end - if (bus.wmask[0]) begin - rx_escape_ack <= bus.wdata[7]; - {usb_enabled, tx_flush, rx_flush} <= bus.wdata[4:2]; - end + case (bus.address[3:2]) + R_SCR: if (&bus.wmask) begin + {dma.direction, dma.stop, dma.start} <= bus.wdata[11:9]; + reset_ack <= bus.wdata[7]; + {write_buffer_flush, usb_enable, tx_flush, rx_flush} <= bus.wdata[5:2]; end - 2'd1: begin - if (bus.wmask[0]) begin - cpu_tx_write <= 1'b1; - end else begin - cpu_rx_read <= 1'b1; - end + R_DATA: if (bus.wmask == 4'b0000) begin + dma.cpu_rx_read <= 1'b1; + end else if (bus.wmask == 4'b0001) begin + dma.cpu_tx_write <= 1'b1; + dma.cpu_tx_wdata <= bus.wdata[7:0]; + 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 endcase end end end - usb_ft1248 usb_ft1248_inst ( - .sys(sys), + memory_dma usb_memory_dma_inst ( + .clk(sys.clk), + .reset(~usb_enable), + .dma(dma) + ); - .usb_enabled(usb_enabled), - .tx_force(tx_force), + usb_ft1248 usb_ft1248_inst ( + .clk(sys.clk), + .reset(~usb_enable), .usb_clk(usb_clk), .usb_cs(usb_cs), .usb_miso(usb_miso), .usb_miosi(usb_miosi), + .reset_pending(reset_pending), + .reset_ack(reset_ack), + .write_buffer_flush(write_buffer_flush), + .rx_flush(rx_flush), - .rx_empty(rx_empty), - .rx_read(rx_read), - .rx_rdata(rx_rdata), + .rx_empty(dma.rx_empty), + .rx_almost_empty(dma.rx_almost_empty), + .rx_read(dma.rx_read), + .rx_rdata(dma.rx_rdata), .tx_flush(tx_flush), - .tx_full(tx_full), - .tx_write(tx_write), - .tx_wdata(tx_wdata), - - .rx_escape_valid(rx_escape_valid), - .rx_escape_ack(rx_escape_ack), - .rx_escape(rx_escape) + .tx_full(dma.tx_full), + .tx_almost_full(dma.tx_almost_full), + .tx_write(dma.tx_write), + .tx_wdata(dma.tx_wdata) ); endmodule diff --git a/fw/rtl/cpu/cpu_wrapper.sv b/fw/rtl/cpu/cpu_wrapper.sv index aaededc..e248db0 100644 --- a/fw/rtl/cpu/cpu_wrapper.sv +++ b/fw/rtl/cpu/cpu_wrapper.sv @@ -28,12 +28,29 @@ module cpu_wrapper ( 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 #( .ENABLE_COUNTERS(0), .ENABLE_COUNTERS64(0), + .TWO_STAGE_SHIFT(0), + .TWO_CYCLE_COMPARE(1), + .TWO_CYCLE_ALU(1), .CATCH_MISALIGN(0), .CATCH_ILLINSN(0), - .PROGADDR_RESET(sc64::CPU_RESET_VECTOR) + .PROGADDR_RESET(32'h0001_0000) ) cpu_inst ( .clk(sys.clk), .resetn(~sys.reset), @@ -43,7 +60,26 @@ module cpu_wrapper ( .mem_ready(bus.ack), .mem_rdata(bus.rdata), .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 diff --git a/fw/rtl/intel/fifo/intel_fifo_8.v b/fw/rtl/intel/fifo/intel_fifo_8.v index 88316a2..bf49b7b 100644 --- a/fw/rtl/intel/fifo/intel_fifo_8.v +++ b/fw/rtl/intel/fifo/intel_fifo_8.v @@ -9,7 +9,7 @@ // scfifo // // Simulation Library Files(s): -// +// altera_mf // ============================================================ // ************************************************************ // THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! @@ -43,6 +43,8 @@ module intel_fifo_8 ( rdreq, sclr, wrreq, + almost_empty, + almost_full, empty, full, q); @@ -52,16 +54,22 @@ module intel_fifo_8 ( input rdreq; input sclr; input wrreq; + output almost_empty; + output almost_full; output empty; output full; output [7:0] q; wire sub_wire0; wire sub_wire1; - wire [7:0] sub_wire2; - wire empty = sub_wire0; - wire full = sub_wire1; - wire [7:0] q = sub_wire2[7:0]; + wire sub_wire2; + wire sub_wire3; + wire [7:0] sub_wire4; + 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 ( .clock (clock), @@ -69,16 +77,18 @@ module intel_fifo_8 ( .rdreq (rdreq), .sclr (sclr), .wrreq (wrreq), - .empty (sub_wire0), - .full (sub_wire1), - .q (sub_wire2), + .almost_empty (sub_wire0), + .almost_full (sub_wire1), + .empty (sub_wire2), + .full (sub_wire3), + .q (sub_wire4), .aclr (), - .almost_empty (), - .almost_full (), .eccstatus (), .usedw ()); 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.lpm_numwords = 1024, scfifo_component.lpm_showahead = "ON", @@ -95,10 +105,10 @@ endmodule // ============================================================ // CNX file retrieval info // ============================================================ -// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0" -// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1" -// Retrieval info: PRIVATE: AlmostFull NUMERIC "0" -// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1" +// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "1" +// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "2" +// Retrieval info: PRIVATE: AlmostFull NUMERIC "1" +// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "1023" // Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "1" // Retrieval info: PRIVATE: Clock NUMERIC "0" // Retrieval info: PRIVATE: Depth NUMERIC "1024" @@ -109,7 +119,7 @@ endmodule // Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0" // Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0" // Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0" -// Retrieval info: PRIVATE: Optimize NUMERIC "1" +// Retrieval info: PRIVATE: Optimize NUMERIC "2" // Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" // Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" // Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0" @@ -128,7 +138,9 @@ endmodule // Retrieval info: PRIVATE: wsFull NUMERIC "1" // Retrieval info: PRIVATE: wsUsedW NUMERIC "0" // Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all -// Retrieval info: CONSTANT: ADD_RAM_OUTPUT_REGISTER STRING "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: LPM_NUMWORDS NUMERIC "1024" // Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON" @@ -138,6 +150,8 @@ endmodule // Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON" // Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON" // Retrieval info: CONSTANT: USE_EAB STRING "ON" +// Retrieval info: USED_PORT: 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: data 0 0 8 0 INPUT NODEFVAL "data[7..0]" // 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: @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: 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: full 0 0 0 0 @full 0 0 0 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_inst.v FALSE // Retrieval info: GEN_FILE: TYPE_NORMAL intel_fifo_8_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/fw/rtl/intel/pll/intel_pll.v b/fw/rtl/intel/pll/intel_pll.v index 64aa37d..3b945a9 100644 --- a/fw/rtl/intel/pll/intel_pll.v +++ b/fw/rtl/intel/pll/intel_pll.v @@ -9,7 +9,7 @@ // altpll // // Simulation Library Files(s): -// +// altera_mf // ============================================================ // ************************************************************ // 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_inst.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 diff --git a/fw/rtl/memory/memory_dma.sv b/fw/rtl/memory/memory_dma.sv new file mode 100644 index 0000000..b036f67 --- /dev/null +++ b/fw/rtl/memory/memory_dma.sv @@ -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 diff --git a/fw/rtl/n64/n64_bootloader.sv b/fw/rtl/n64/n64_bootloader.sv index f513efb..52cde36 100644 --- a/fw/rtl/n64/n64_bootloader.sv +++ b/fw/rtl/n64/n64_bootloader.sv @@ -1,20 +1,10 @@ module n64_bootloader ( if_system.sys sys, 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] { S_IDLE, S_WAIT @@ -28,97 +18,77 @@ module n64_bootloader ( e_state state; e_source_request source_request; - always_ff @(posedge sys.clk) begin - csr_ack <= 1'b0; - write_ack <= 1'b0; + logic request; + logic ack; + logic write; + logic [31:0] address; + logic [31:0] wdata; + logic [31:0] rdata; + always_ff @(posedge sys.clk) begin if (sys.reset) begin state <= S_IDLE; - mem_request <= 1'b0; + request <= 1'b0; end else begin case (state) S_IDLE: begin if (bus.request || flash.request) begin state <= S_WAIT; - mem_request <= 1'b1; + request <= 1'b1; if (bus.request) begin - mem_write <= 1'b0; - mem_address <= bus.address; - mem_wdata <= bus.wdata; + write <= 1'b0; + address <= bus.address; + wdata <= bus.wdata; source_request <= T_N64; end else if (flash.request) begin - mem_write <= flash.write; - mem_address <= flash.address; - mem_wdata <= flash.wdata; + write <= flash.write; + address <= flash.address; + wdata <= flash.wdata; source_request <= T_CPU; end end end S_WAIT: begin - if (mem_address[27] && source_request != T_N64 && !csr_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 + if (ack) begin state <= S_IDLE; + request <= 1'b0; end end endcase end end - logic csr_or_data; - logic csr_read; - logic csr_write; - logic data_read; - logic data_write; - always_comb begin - csr_or_data = mem_address[27] && source_request == T_CPU; - 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.ack = source_request == T_N64 && ack; bus.rdata = 16'd0; if (bus.ack && bus.address < 32'h00010000) begin - if (bus.address[1]) bus.rdata = {data_rdata[23:16], data_rdata[31:24]}; - else bus.rdata = {data_rdata[7:0], data_rdata[15:8]}; + if (bus.address[1]) bus.rdata = {rdata[23:16], rdata[31:24]}; + else bus.rdata = {rdata[7:0], rdata[15:8]}; end - flash.ack = source_request == T_CPU && (csr_ack || data_ack || write_ack); + flash.ack = source_request == T_CPU && ack; flash.rdata = 32'd0; if (flash.ack) begin - flash.rdata = csr_or_data ? csr_rdata : data_rdata; + flash.rdata = rdata; end end - intel_flash intel_flash_inst ( - .clock(sys.clk), - .reset_n(~sys.reset), + vendor_flash vendor_flash_inst ( + .clk(sys.clk), + .reset(sys.reset), - .avmm_csr_addr(mem_address[2]), - .avmm_csr_read(csr_read), - .avmm_csr_writedata(mem_wdata), - .avmm_csr_write(csr_write), - .avmm_csr_readdata(csr_rdata), + .erase_start(cfg.flash_erase_start), + .erase_busy(cfg.flash_erase_busy), + .wp_enable(cfg.flash_wp_enable), + .wp_disable(cfg.flash_wp_disable), - .avmm_data_addr(mem_address[31:2]), - .avmm_data_read(data_read), - .avmm_data_writedata(mem_wdata), - .avmm_data_write(data_write), - .avmm_data_readdata(data_rdata), - .avmm_data_waitrequest(data_busy), - .avmm_data_readdatavalid(data_ack), - .avmm_data_burstcount(2'd1) + .request(request), + .ack(ack), + .write(write), + .address(address), + .wdata(wdata), + .rdata(rdata) ); endmodule diff --git a/fw/rtl/n64/n64_cfg.sv b/fw/rtl/n64/n64_cfg.sv index 74a07e0..0c8443c 100644 --- a/fw/rtl/n64/n64_cfg.sv +++ b/fw/rtl/n64/n64_cfg.sv @@ -1,8 +1,7 @@ module n64_cfg ( if_system sys, if_n64_bus bus, - if_config.n64 cfg, - if_cpu_ram.external cpu_ram + if_config.n64 cfg ); typedef enum bit [2:0] { @@ -32,10 +31,6 @@ module n64_cfg ( logic [31:0] isv_id; 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; if (bus.ack) 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_VERSION_H: bus.rdata = sc64::SC64_VER[31:16]; R_VERSION_L: bus.rdata = sc64::SC64_VER[15:0]; + default: bus.rdata = 16'd0; 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 case (bus.address[4:1]) R_ISV_ID_H: bus.rdata = isv_id[31:16]; R_ISV_ID_L: bus.rdata = isv_id[15:0]; R_ISV_RD_PTR: bus.rdata = cfg.isv_rd_ptr; + default: bus.rdata = 16'd0; endcase end end diff --git a/fw/rtl/n64/n64_sdram.sv b/fw/rtl/n64/n64_sdram.sv index 273e6b0..e95eb2e 100644 --- a/fw/rtl/n64/n64_sdram.sv +++ b/fw/rtl/n64/n64_sdram.sv @@ -1,7 +1,7 @@ module n64_sdram ( if_system sys, if_n64_bus bus, - if_dma.memory dma, + if_memory_dma.memory usb_dma, if_sdram.memory sdram, output sdram_cs, @@ -20,58 +20,40 @@ module n64_sdram ( logic [15:0] mem_rdata; logic [15:0] mem_wdata; - typedef enum bit [0:0] { - S_IDLE, - S_WAIT - } e_state; - typedef enum bit [1:0] { T_BUS, - T_DMA, - T_SDRAM + T_SDRAM, + T_USB_DMA } e_source_request; - e_state state; e_source_request source_request; always_ff @(posedge sys.clk) begin if (sys.reset) begin - state <= S_IDLE; mem_request <= 1'b0; end else begin - case (state) - S_IDLE: begin - if (bus.request) begin - state <= S_WAIT; - mem_request <= 1'b1; - mem_write <= bus.write; - mem_address <= bus.address; - mem_wdata <= bus.wdata; - source_request <= T_BUS; - end else if ((!bus.n64_active) && (sdram.request || dma.request)) begin - state <= S_WAIT; - mem_request <= 1'b1; - if (sdram.request) begin - mem_write <= sdram.write; - mem_address <= sdram.address; - mem_wdata <= sdram.wdata; - source_request <= T_SDRAM; - end else if (dma.request) begin - mem_write <= dma.write; - mem_address <= dma.address; - mem_wdata <= dma.wdata; - source_request <= T_DMA; - end - end + if (!mem_request && (bus.request || sdram.request || usb_dma.request)) begin + mem_request <= 1'b1; + if (bus.request) begin + mem_write <= bus.write; + mem_address <= bus.address; + mem_wdata <= bus.wdata; + source_request <= T_BUS; + end else if (sdram.request) begin + mem_write <= sdram.write; + mem_address <= sdram.address; + mem_wdata <= sdram.wdata; + source_request <= T_SDRAM; + end else if (usb_dma.request) begin + mem_write <= usb_dma.write; + mem_address <= usb_dma.address; + mem_wdata <= usb_dma.wdata; + source_request <= T_USB_DMA; end - - S_WAIT: begin - if (mem_ack) begin - state <= S_IDLE; - mem_request <= 1'b0; - end - end - endcase + end + if (mem_ack) begin + mem_request <= 1'b0; + end end end @@ -79,11 +61,11 @@ module n64_sdram ( bus.ack = source_request == T_BUS && mem_ack; 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.rdata = mem_rdata; + + usb_dma.ack = source_request == T_USB_DMA && mem_ack; + usb_dma.rdata = mem_rdata; end memory_sdram memory_sdram_inst ( diff --git a/fw/rtl/n64/n64_soc.sv b/fw/rtl/n64/n64_soc.sv index 722ce28..52447b4 100644 --- a/fw/rtl/n64/n64_soc.sv +++ b/fw/rtl/n64/n64_soc.sv @@ -1,13 +1,12 @@ module n64_soc ( if_system sys, if_config cfg, - if_dma.memory dma, + if_memory_dma.memory usb_dma, if_sdram.memory sdram, if_flashram.flashram flashram, if_si.si si, - if_flash.memory flash, + if_flash.flash flash, if_dd dd, - if_cpu_ram.external cpu_ram, input n64_pi_alel, input n64_pi_aleh, @@ -52,7 +51,7 @@ module n64_soc ( n64_sdram n64_sdram_inst ( .sys(sys), .bus(bus.at[sc64::ID_N64_SDRAM].device), - .dma(dma), + .usb_dma(usb_dma), .sdram(sdram), .sdram_cs(sdram_cs), @@ -67,6 +66,7 @@ module n64_soc ( n64_bootloader n64_bootloader_inst ( .sys(sys), .bus(bus.at[sc64::ID_N64_BOOTLOADER].device), + .cfg(cfg), .flash(flash) ); @@ -91,8 +91,7 @@ module n64_soc ( n64_cfg n64_cfg_inst ( .sys(sys), .bus(bus.at[sc64::ID_N64_CFG].device), - .cfg(cfg), - .cpu_ram(cpu_ram) + .cfg(cfg) ); endmodule diff --git a/fw/rtl/system/config.sv b/fw/rtl/system/config.sv index 0381415..00fb1b4 100644 --- a/fw/rtl/system/config.sv +++ b/fw/rtl/system/config.sv @@ -20,6 +20,10 @@ interface if_config (); logic [25:0] save_offset; logic [25:0] isv_offset; logic [15:0] isv_rd_ptr; + logic flash_erase_start; + logic flash_erase_busy; + logic flash_wp_enable; + logic flash_wp_disable; modport pi ( input sdram_switch, @@ -39,6 +43,13 @@ interface if_config (); output flashram_read_mode ); + modport flash ( + input flash_erase_start, + output flash_erase_busy, + input flash_wp_enable, + input flash_wp_disable + ); + modport n64 ( input cpu_ready, input cpu_busy, @@ -70,7 +81,11 @@ interface if_config (); output ddipl_offset, output save_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 diff --git a/fw/rtl/system/sc64.sv b/fw/rtl/system/sc64.sv index 224d5c2..1e0dd73 100644 --- a/fw/rtl/system/sc64.sv +++ b/fw/rtl/system/sc64.sv @@ -9,31 +9,8 @@ package sc64; __ID_N64_END } 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 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; `ifdef DEBUG diff --git a/fw/rtl/usb/usb_ft1248.sv b/fw/rtl/usb/usb_ft1248.sv index 2426cd6..3dd1de7 100644 --- a/fw/rtl/usb/usb_ft1248.sv +++ b/fw/rtl/usb/usb_ft1248.sv @@ -1,280 +1,241 @@ module usb_ft1248 ( - if_system.sys sys, - - input usb_enabled, - input tx_force, + input clk, + input reset, output usb_clk, output usb_cs, 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, output rx_empty, + output rx_almost_empty, input rx_read, output [7:0] rx_rdata, input tx_flush, output tx_full, + output tx_almost_full, input tx_write, - input [7:0] tx_wdata, - - output rx_escape_valid, - input rx_escape_ack, - output [7:0] rx_escape + input [7:0] tx_wdata ); - parameter bit [7:0] ESCAPE_CHARACTER = 8'h1B; - - // FIFOs - logic rx_full; + logic rx_almost_full; logic rx_write; - logic [7:0] rx_wdata; logic tx_empty; + logic tx_almost_empty; logic tx_read; logic [7:0] tx_rdata; - logic rx_wdata_valid; - logic rx_escape_active; - intel_fifo_8 fifo_8_rx_inst ( - .clock(sys.clk), - .sclr(rx_flush || !usb_enabled), + .clock(clk), + .sclr(reset || rx_flush), .empty(rx_empty), + .almost_empty(rx_almost_empty), .rdreq(rx_read), .q(rx_rdata), .full(rx_full), + .almost_full(rx_almost_full), .wrreq(rx_write), - .data(rx_wdata) + .data(usb_miosi) ); intel_fifo_8 fifo_8_tx_inst ( - .clock(sys.clk), - .sclr(tx_flush || !usb_enabled), + .clock(clk), + .sclr(reset || tx_flush), .empty(tx_empty), + .almost_empty(tx_almost_empty), .rdreq(tx_read), .q(tx_rdata), .full(tx_full), + .almost_full(tx_almost_full), .wrreq(tx_write), .data(tx_wdata) ); - - // Escape character detection - - always_comb begin - rx_write = 1'b0; - if (rx_wdata_valid) begin - rx_write = rx_escape_active ? rx_wdata == ESCAPE_CHARACTER : rx_wdata != ESCAPE_CHARACTER; - 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 + typedef enum bit [2:0] { + STATE_IDLE, + STATE_SELECT, + STATE_COMMAND, + STATE_STATUS, + STATE_DATA, + STATE_DESELECT } e_state; typedef enum bit [7:0] { - C_WRITE = 8'h00, - C_READ = 8'h04, - C_FORCE = 8'h80 + CMD_WRITE = 8'h00, + CMD_READ = 8'h40, + CMD_READ_MODEM_STATUS = 8'h20, + CMD_WRITE_MODEM_STATUS = 8'h60, + CMD_WRITE_BUFFER_FLUSH = 8'h08 } e_command; - typedef enum bit [1:0] { - P_PRE_RISING, - P_RISING, - P_PRE_FALLING, - P_FALLING - } e_clock_phase; - + logic usb_miosi_oe; + logic write_buffer_flush_pending; + logic write_modem_status_pending; + logic [4:0] modem_status_counter; + logic modem_status_read; + logic last_reset_status; + logic reset_reply; + logic [3:0] phase; + logic [7:0] usb_cmd; 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 - usb_miosi = usb_miosi_output_enable ? usb_miosi_output : 4'bZZZZ; - end - - always_comb begin - case (state) - 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]; + 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 - 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 end - always_ff @(posedge sys.clk) begin - rx_wdata_valid <= 1'b0; + always_ff @(posedge clk) begin + rx_write <= 1'b0; tx_read <= 1'b0; + modem_status_read <= 1'b0; + phase <= {phase[2:0], phase[3]}; - if (clock_phase[P_RISING]) begin - nibble_counter <= nibble_counter + 1'd1; - end - - if (sys.reset || !usb_enabled) begin - state <= S_TRY_RX; - tx_force_pending <= 1'b0; + if (reset) begin + 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 (tx_force) begin - tx_force_pending <= 1'b1; + if (write_buffer_flush) begin + write_buffer_flush_pending <= 1'b1; + end + + if (reset_ack) begin + reset_pending <= 1'b0; + write_modem_status_pending <= 1'b1; + reset_reply <= 1'b1; + end + + 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 case (state) - S_TRY_RX: begin - if (!rx_full && !rx_escape_valid) begin - state <= S_COMMAND; - is_cmd_write <= 1'b0; - is_cmd_tx_force <= 1'b0; - nibble_counter <= 2'b11; + STATE_IDLE: begin + usb_cs <= 1'b0; + state <= STATE_SELECT; + if (write_modem_status_pending) begin + usb_cmd <= CMD_WRITE_MODEM_STATUS; + 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 - state <= S_TRY_TX; + usb_cs <= 1'b1; + modem_status_counter <= modem_status_counter + 1'd1; + state <= STATE_IDLE; end end - S_TRY_TX: begin - if (!tx_empty) begin - state <= S_COMMAND; - is_cmd_write <= 1'b1; - is_cmd_tx_force <= 1'b0; - nibble_counter <= 2'b11; - end else if (tx_force_pending) begin - state <= S_COMMAND; - tx_force_pending <= 1'b0; - is_cmd_write <= 1'b1; - is_cmd_tx_force <= 1'b1; - nibble_counter <= 2'b11; - end else begin - state <= S_TRY_RX; + STATE_SELECT: begin + phase <= 4'b0001; + state <= STATE_COMMAND; + end + + STATE_COMMAND: begin + if (phase[0]) begin + usb_clk <= 1'b1; + usb_miosi_oe <= 1'b1; + end else if (phase[2]) begin + usb_clk <= 1'b0; + end else if (phase[3]) begin + state <= STATE_STATUS; end end - S_COMMAND: begin - if (clock_phase[P_RISING]) begin - if (nibble_counter == 2'd2) begin - if (usb_miso_input || is_cmd_tx_force) begin - state <= is_cmd_write ? S_TRY_RX : S_TRY_TX; - end else begin - state <= S_DATA; - nibble_counter <= 2'd0; + STATE_STATUS: begin + if (phase[0]) begin + usb_clk <= 1'b1; + usb_miosi_oe <= 1'b0; + end else if (phase[2]) begin + usb_clk <= 1'b0; + end else if (phase[3]) begin + state <= STATE_DATA; + 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 - S_DATA: begin - if (clock_phase[P_FALLING]) begin - if (nibble_counter[0]) begin - tx_read <= is_cmd_write; - end + STATE_DESELECT: begin + usb_cs <= 1'b1; + usb_miosi_oe <= 1'b0; + if (phase[1]) begin + modem_status_counter <= modem_status_counter + 1'd1; + state <= STATE_IDLE; 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 end diff --git a/fw/rtl/vendor/vendor_flash.sv b/fw/rtl/vendor/vendor_flash.sv new file mode 100644 index 0000000..b19f9a2 --- /dev/null +++ b/fw/rtl/vendor/vendor_flash.sv @@ -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 diff --git a/fw/rtl/vendor/vendor_reconfigure.sv b/fw/rtl/vendor/vendor_reconfigure.sv new file mode 100644 index 0000000..70e3f55 --- /dev/null +++ b/fw/rtl/vendor/vendor_reconfigure.sv @@ -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 diff --git a/sw/n64/src/io.h b/sw/n64/src/io.h index e6897cf..94d7818 100644 --- a/sw/n64/src/io.h +++ b/sw/n64/src/io.h @@ -229,9 +229,6 @@ typedef struct { io32_t SR_CMD; io32_t DATA[2]; io32_t VERSION; - io32_t __padding[4092]; - io32_t CPU_RAM[3840]; - io32_t BUFFER[256]; } sc64_regs_t; #define SC64_BASE (0x1FFF0000UL) diff --git a/sw/n64/src/sc64.c b/sw/n64/src/sc64.c index d4316f4..6194561 100644 --- a/sw/n64/src/sc64.c +++ b/sw/n64/src/sc64.c @@ -83,7 +83,7 @@ void sc64_set_time (rtc_time_t *t) { } 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]; do { 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) { - 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)) { 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) { - 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)) { 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 next_offset = SECTOR_SIZE; - if (sc64_drive_start_rw(drive, false, sector++, 0)) { + if (sc64_drive_start_rw(drive, false, sector++, 0x03FF0000UL)) { return true; } while (count > 0) { @@ -124,12 +124,12 @@ bool sc64_storage_read (drive_id_t drive, void *buffer, uint32_t sector, uint32_ return true; } 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; } 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++) { uint32_t data = pi_io_read(src + i); *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) { uint8_t *src = (uint8_t *) (buffer); - io32_t *dst = SC64->BUFFER; + io32_t *dst = (io32_t *) (0x13FF0000UL); while (count > 0) { 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); 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; } if (sc64_wait_drive_ready(drive)) { diff --git a/sw/pc/sc64.py b/sw/pc/sc64.py index 6d47130..6128e47 100644 --- a/sw/pc/sc64.py +++ b/sw/pc/sc64.py @@ -1,7 +1,8 @@ #!/usr/bin/env python3 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 typing import Union import argparse @@ -9,7 +10,6 @@ import filecmp import helpers import os import progressbar -import re import struct import sys import time @@ -50,8 +50,6 @@ class SC64: __DEBUG_ID_TEXT = 0x01 __EVENT_ID_FSD_READ = 0xF0 __EVENT_ID_FSD_WRITE = 0xF1 - __EVENT_ID_FSD_LOAD = 0xF2 - __EVENT_ID_FSD_STORE = 0xF3 __EVENT_ID_DD_BLOCK = 0xF4 __EVENT_ID_IS_VIEWER = 0xF5 @@ -76,7 +74,6 @@ class SC64: def __del__(self) -> None: if (self.__usb): - self.__reset_n64("release") self.__usb.close() if (self.__fsd_file): self.__fsd_file.close() @@ -101,14 +98,15 @@ class SC64: 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: - self.__usb.write(b"\x1BR") - time.sleep(0.1) - self.__usb.flushInput() + if (self.__usb): + self.__usb.flush() + 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: @@ -116,7 +114,7 @@ class SC64: def __write(self, data: bytes) -> None: - self.__usb.write(self.__escape(data)) + self.__usb.write(data) def __read_long(self, length: int) -> bytes: @@ -151,29 +149,28 @@ class SC64: 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: - 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() - try: - self.__usb = Ft232(description="SummerCart64") - self.__reset_n64("hold") - self.__usb.flushOutput() - self.reset_link() - self.__probe_device() - except Ft232Exception as e: - if (self.__usb): - self.__usb.close() - raise SC64Exception(f"No SummerCart64 device was found: {e}") + for p in ports: + if (p.vid == 0x0403 and p.pid == 0x6014 and p.serial_number.startswith("SC")): + try: + self.__usb = Serial(p.device, timeout=0.5, write_timeout=0.5) + self.reset_link() + self.__probe_device() + except (SerialException, SC64Exception): + if (self.__usb): + self.__usb.close() + continue + device_found = True + break + + if (not device_found): + raise SC64Exception("No SummerCart64 device was found") def __probe_device(self) -> None: @@ -197,25 +194,22 @@ class SC64: 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: - transfer_size = self.__align(length, align) - self.__set_progress_init(transfer_size, os.path.basename(f.name)) - self.__write_cmd("R", offset, transfer_size) + self.__set_progress_init(length, os.path.basename(f.name)) + self.__write_cmd("R", offset, length) while (f.tell() < length): chunk_size = min(self.__CHUNK_SIZE, length - f.tell()) f.write(self.__read(chunk_size)) self.__set_progress_value(f.tell()) - if (transfer_size != length): - self.__read(transfer_size - length) self.__read_cmd_status("R") 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: 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.__write_cmd("W", offset, transfer_size) while (f.tell() < length): @@ -243,7 +237,7 @@ class SC64: def __reconfigure(self) -> None: magic = self.__query_config(self.__CFG_ID_RECONFIGURE) 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: @@ -259,7 +253,6 @@ class SC64: self.__change_config(self.__CFG_ID_FLASH_PROGRAM, self.__UPDATE_OFFSET) self.__usb.timeout = saved_timeout self.__reconfigure() - self.__find_sc64() def set_rtc(self, t: datetime) -> None: @@ -544,7 +537,7 @@ class SC64: data += struct.pack(">I", offset) self.__disk_lba_table[lba] = offset self.__write_cmd("W", thb_table_offset, len(data)) - self.__write(data) + self.__write(bytes(data)) self.__read_cmd_status("W") id_mapping = { "retail": self.__DD_DRIVE_ID_RETAIL, @@ -561,26 +554,28 @@ class SC64: def __debug_process_fsd_read(self, data: bytes) -> None: sector = int.from_bytes(data[0:4], byteorder="little") offset = int.from_bytes(data[4:8], byteorder="little") + count = int.from_bytes(data[8:12], byteorder="little") if (self.__fsd_file): self.__fsd_file.seek(sector * 512) - self.__write_cmd("T", offset, 512) - self.__write(self.__fsd_file.read(512)) + self.__write_cmd("S", offset, count * 512) + self.__write(self.__fsd_file.read(count * 512)) else: - self.__write_cmd("T", offset, 0) + self.__write_cmd("S", offset, 0) def __debug_process_fsd_write(self, data: bytes) -> None: sector = int.from_bytes(data[0:4], byteorder="little") offset = int.from_bytes(data[4:8], byteorder="little") + count = int.from_bytes(data[8:12], byteorder="little") if (self.__fsd_file): with helpers.lock_volume(self.__fsd_file): self.__fsd_file.seek(sector * 512) - self.__write_cmd("F", offset, 512) - self.__fsd_file.write(self.__read(512)) + self.__write_cmd("L", offset, count * 512) + self.__fsd_file.write(self.__read(count * 512)) else: - self.__write_cmd("F", offset, 0) + self.__write_cmd("L", offset, 0) 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") disk_file_offset = int.from_bytes(data[8:12], byteorder="big") block_length = int.from_bytes(data[12:16], byteorder="little") - + print(f"DD BLOCK {disk_file_offset:08X} {block_length}") if (self.__disk_file): self.__disk_file.seek(disk_file_offset) if (transfer_mode): @@ -605,10 +600,8 @@ class SC64: def __debug_process_is_viewer(self, data: bytes) -> None: length = int.from_bytes(data[0:4], byteorder="little") address = int.from_bytes(data[4:8], byteorder="little") - offset = (address & 0x01) - transfer_length = self.__align(length + offset, 2) - self.__write_cmd("L", (address & 0xFFFFFFFE), transfer_length) - text = self.__read(transfer_length)[offset:][:length] + self.__write_cmd("L", address, length) + text = self.__read(length) 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") - self.__usb.setTimeout(0.1) - start_indicator = bytearray() dropped_bytes = 0 - self.__reset_n64("release") - while (True): while (start_indicator != b"DMA@"): start_indicator.append(self.__read_long(1)[0]) @@ -752,6 +741,8 @@ if __name__ == "__main__": args = parser.parse_args() + sc64 = None + try: sc64 = SC64() @@ -855,7 +846,6 @@ if __name__ == "__main__": pass finally: if (sc64): - sc64.reset_link() if (disk_file): print(f"Setting 64DD disk state to [Ejected]") sc64.set_dd_disk_state("ejected") diff --git a/sw/riscv/Makefile b/sw/riscv/Makefile index 4d24214..9f8ff65 100644 --- a/sw/riscv/Makefile +++ b/sw/riscv/Makefile @@ -6,7 +6,7 @@ OBJDUMP = $(TOOLCHAIN)objdump SIZE = $(TOOLCHAIN)size 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 SRC_DIR = src @@ -17,7 +17,6 @@ SRC_FILES = \ process.c \ usb.c \ cfg.c \ - dma.c \ joybus.c \ rtc.c \ i2c.c \ @@ -46,7 +45,7 @@ $(BUILD_DIR)/governor.elf: $(OBJS) SC64.ld @$(OBJDUMP) -D $@ > $(BUILD_DIR)/governor.lst $(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 @$(OBJCOPY) -I binary -O ihex $< $@ diff --git a/sw/riscv/SC64.ld b/sw/riscv/SC64.ld index 69d4601..50075c3 100644 --- a/sw/riscv/SC64.ld +++ b/sw/riscv/SC64.ld @@ -1,7 +1,6 @@ MEMORY { - ram (rwx) : org = 0x00000000, len = 15k - buffer (rw) : org = 0x00003C00, len = 1k - rom (rx) : org = 0x10010000, len = 26k + rom (rx) : org = 0x00010000, len = 26k + ram (rwx) : org = 0x10000000, len = 32k } ENTRY(reset_handler) @@ -45,10 +44,6 @@ SECTIONS { _ebss = .; } > ram - .buffer : { - *(.buffer) - } > buffer - __global_pointer$ = MIN(_ssdata + 0x800, MAX(_sdata + 0x800, _ebss - 0x800)); __stack_pointer$ = ORIGIN(ram) + LENGTH(ram); } diff --git a/sw/riscv/src/cfg.c b/sw/riscv/src/cfg.c index ba05a48..9d720f8 100644 --- a/sw/riscv/src/cfg.c +++ b/sw/riscv/src/cfg.c @@ -311,9 +311,7 @@ void process_cfg (void) { break; case 0xF0: - if (args[0] == 0) { - change_scr_bits(CFG_SCR_CMD_ERROR, true); - } else if (args[0] == 1) { + if (args[0] & (1 << 31)) { p.usb_drive_busy = false; } else { change_scr_bits(CFG_SCR_CMD_ERROR, true); @@ -321,10 +319,7 @@ void process_cfg (void) { break; case 0xF1: - if (args[0] == 0) { - args[0] = 0; - change_scr_bits(CFG_SCR_CMD_ERROR, true); - } else if (args[0] == 1) { + if (args[0] & (1 << 31)) { args[0] = p.usb_drive_busy; } else { args[0] = 0; @@ -334,18 +329,20 @@ void process_cfg (void) { break; case 0xF2: - if ((args[0] & 0xFF) == 0) { - change_scr_bits(CFG_SCR_CMD_ERROR, true); - } else if ((args[0] & 0xFF) == 1 && (!p.usb_drive_busy)) { - usb_event_t event; - event.id = EVENT_ID_FSD_READ; - event.trigger = CALLBACK_BUFFER_WRITE; - event.callback = set_usb_drive_not_busy; - uint32_t data[2] = { args[1], (args[0] >> 8) }; - if (usb_put_event(&event, data, sizeof(data))) { - p.usb_drive_busy = true; + if (args[0] & (1 << 31)) { + if (!p.usb_drive_busy) { + usb_event_t event; + event.id = EVENT_ID_FSD_READ; + event.trigger = CALLBACK_SDRAM_WRITE; + event.callback = set_usb_drive_not_busy; + uint32_t data[3] = { args[1], (args[0] & 0x7FFFFFFF), 1 }; + if (usb_put_event(&event, data, sizeof(data))) { + p.usb_drive_busy = true; + } else { + return; + } } else { - return; + change_scr_bits(CFG_SCR_CMD_ERROR, true); } } else { change_scr_bits(CFG_SCR_CMD_ERROR, true); @@ -353,18 +350,20 @@ void process_cfg (void) { break; case 0xF3: - if ((args[0] & 0xFF) == 0) { - change_scr_bits(CFG_SCR_CMD_ERROR, true); - } else if ((args[0] & 0xFF) == 1 && (!p.usb_drive_busy)) { - usb_event_t event; - event.id = EVENT_ID_FSD_WRITE; - event.trigger = CALLBACK_BUFFER_READ; - event.callback = set_usb_drive_not_busy; - uint32_t data[2] = { args[1], (args[0] >> 8) }; - if (usb_put_event(&event, data, sizeof(data))) { - p.usb_drive_busy = true; + if (args[0] & (1 << 31)) { + if (!p.usb_drive_busy) { + usb_event_t event; + event.id = EVENT_ID_FSD_WRITE; + event.trigger = CALLBACK_SDRAM_READ; + event.callback = set_usb_drive_not_busy; + uint32_t data[3] = { args[1], (args[0] & 0x7FFFFFFF), 1 }; + if (usb_put_event(&event, data, sizeof(data))) { + p.usb_drive_busy = true; + } else { + return; + } } else { - return; + change_scr_bits(CFG_SCR_CMD_ERROR, true); } } else { change_scr_bits(CFG_SCR_CMD_ERROR, true); diff --git a/sw/riscv/src/dma.c b/sw/riscv/src/dma.c deleted file mode 100644 index 243a558..0000000 --- a/sw/riscv/src/dma.c +++ /dev/null @@ -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(); -} diff --git a/sw/riscv/src/dma.h b/sw/riscv/src/dma.h deleted file mode 100644 index 75462a7..0000000 --- a/sw/riscv/src/dma.h +++ /dev/null @@ -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 diff --git a/sw/riscv/src/flash.c b/sw/riscv/src/flash.c index 4c7e957..69a7b86 100644 --- a/sw/riscv/src/flash.c +++ b/sw/riscv/src/flash.c @@ -1,6 +1,9 @@ #include "flash.h" +static io32_t dummy; + + uint32_t flash_size (void) { return FLASH_SIZE; } @@ -9,54 +12,30 @@ void flash_read (uint32_t sdram_offset) { io32_t *flash = (io32_t *) (FLASH_BASE); 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++; } } void flash_program (uint32_t sdram_offset) { - uint32_t cr; - io32_t *flash = (io32_t *) (FLASH_BASE); io32_t *sdram = (io32_t *) (SDRAM_BASE + sdram_offset); - cr = FLASH_CONFIG->CR; - for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) { - cr &= ~(1 << (FLASH_CR_WRITE_PROTECT_BIT + sector)); - } - FLASH_CONFIG->CR = cr; + CFG->SCR |= CFG_SCR_FLASH_WP_DISABLE; - 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++) { - cr = FLASH_CONFIG->CR; - cr &= ~(FLASH_CR_SECTOR_ERASE_MASK); - cr |= ((sector + 1) << FLASH_CR_SECTOR_ERASE_BIT); - FLASH_CONFIG->CR = cr; + while (CFG->SCR & CFG_SCR_FLASH_ERASE_BUSY); - while ((FLASH_CONFIG->SR & FLASH_SR_STATUS_MASK) == FLASH_SR_STATUS_BUSY_ERASE); - - if (!(FLASH_CONFIG->SR & FLASH_SR_ERASE_SUCCESSFUL)) { - break; - } + for (int i = 0; i < FLASH_SIZE; i += sizeof(io32_t)) { + *flash++ = *sdram++; } - if (FLASH_CONFIG->SR & FLASH_SR_ERASE_SUCCESSFUL) { - for (size_t word = 0; word < FLASH_SIZE; word += 4) { - *flash++ = *sdram++; + CFG->SCR |= CFG_SCR_FLASH_WP_ENABLE; - if (!(FLASH_CONFIG->SR & FLASH_SR_WRITE_SUCCESSFUL)) { - break; - } - } - } + flash = (io32_t *) (FLASH_BASE); - cr = FLASH_CONFIG->CR; - cr |= FLASH_CR_SECTOR_ERASE_MASK; - for (size_t sector = 0; sector < FLASH_NUM_SECTORS; sector++) { - cr |= (1 << (FLASH_CR_WRITE_PROTECT_BIT + sector)); - } - FLASH_CONFIG->CR = cr; + dummy = *flash; return; } diff --git a/sw/riscv/src/flash.h b/sw/riscv/src/flash.h index 89de167..e368fdb 100644 --- a/sw/riscv/src/flash.h +++ b/sw/riscv/src/flash.h @@ -5,7 +5,7 @@ #include "sys.h" -uint32_t flash_size(void); +uint32_t flash_size (void); void flash_read (uint32_t sdram_offset); void flash_program (uint32_t sdram_offset); diff --git a/sw/riscv/src/process.c b/sw/riscv/src/process.c index 1b00aeb..c5dfe10 100644 --- a/sw/riscv/src/process.c +++ b/sw/riscv/src/process.c @@ -1,7 +1,6 @@ #include "process.h" #include "usb.h" #include "cfg.h" -#include "dma.h" #include "joybus.h" #include "rtc.h" #include "i2c.h" @@ -29,7 +28,6 @@ __attribute__((naked)) void process_loop (void) { usb_init(); cfg_init(); - dma_init(); joybus_init(); rtc_init(); i2c_init(); diff --git a/sw/riscv/src/sys.h b/sw/riscv/src/sys.h index b6a9011..29b3610 100644 --- a/sw/riscv/src/sys.h +++ b/sw/riscv/src/sys.h @@ -21,54 +21,48 @@ typedef volatile uint16_t io16_t; typedef volatile uint32_t io32_t; -#define RAM_BASE (0x00000000UL) -#define RAMBUFFER_SIZE (1024) -#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_BASE (0x00000000UL) +#define FLASH_SIZE (0x39800) #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 { - io32_t SR; - io32_t CR; -} flash_config_regs_t; +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 FLASH_CONFIG_BASE (0x18000000UL) -#define FLASH_CONFIG ((flash_config_regs_t *) FLASH_CONFIG_BASE) +#define CFG_BASE (0x20000000UL) +#define CFG ((cfg_regs_t *) CFG_BASE) -#define FLASH_SR_STATUS_MASK (3 << 0) -#define FLASH_SR_STATUS_IDLE (0) -#define FLASH_SR_STATUS_BUSY_ERASE (1) -#define FLASH_SR_STATUS_BUSY_WRITE (2) -#define FLASH_SR_STATUS_BUSY_READ (3) -#define FLASH_SR_READ_SUCCESSFUL (1 << 2) -#define FLASH_SR_WRITE_SUCCESSFUL (1 << 3) -#define FLASH_SR_ERASE_SUCCESSFUL (1 << 4) -#define FLASH_SR_WRITE_PROTECT_BIT (5) - -#define FLASH_CR_PAGE_ERASE_BIT (0) -#define FLASH_CR_SECTOR_ERASE_BIT (20) -#define FLASH_CR_SECTOR_ERASE_MASK (7 << FLASH_CR_SECTOR_ERASE_BIT) -#define FLASH_CR_WRITE_PROTECT_BIT (23) - - -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) +#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_FLASH_ERASE_START (1 << 24) +#define CFG_SCR_FLASH_ERASE_BUSY (1 << 25) +#define CFG_SCR_FLASH_WP_ENABLE (1 << 26) +#define CFG_SCR_FLASH_WP_DISABLE (1 << 27) +#define CFG_SCR_CMD_ERROR (1 << 28) +#define CFG_SCR_CPU_BUSY (1 << 30) +#define CFG_SCR_CPU_READY (1 << 31) typedef volatile struct i2c_regs { @@ -90,8 +84,8 @@ typedef volatile struct usb_regs { io32_t SCR; io8_t DR; io8_t __padding_1[3]; - io8_t ESCAPE; - io8_t __padding_2[3]; + io32_t ADDR; + io32_t LEN; } usb_regs_t; #define USB_BASE (0x40000000UL) @@ -101,11 +95,14 @@ typedef volatile struct usb_regs { #define USB_SCR_TXE (1 << 1) #define USB_SCR_FLUSH_RX (1 << 2) #define USB_SCR_FLUSH_TX (1 << 3) -#define USB_SCR_ENABLED (1 << 4) -#define USB_SCR_PWREN (1 << 5) -#define USB_SCR_ESCAPE_PENDING (1 << 6) -#define USB_SCR_ESCAPE_ACK (1 << 7) -#define USB_SCR_FORCE_TX (1 << 8) +#define USB_SCR_ENABLE (1 << 4) +#define USB_SCR_FORCE_TX (1 << 5) +#define USB_SCR_RESET_PENDING (1 << 6) +#define USB_SCR_RESET_ACK (1 << 7) +#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 { @@ -121,91 +118,6 @@ typedef volatile struct uart_regs { #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 { io32_t SCR; io16_t DATA; @@ -224,7 +136,7 @@ typedef volatile struct dd_regs { io32_t SECTOR_BUFFER[64]; } dd_regs_t; -#define DD_BASE (0xB0000000UL) +#define DD_BASE (0x60000000UL) #define DD ((dd_regs_t *) DD_BASE) #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 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); diff --git a/sw/riscv/src/usb.c b/sw/riscv/src/usb.c index 5b33572..4616304 100644 --- a/sw/riscv/src/usb.c +++ b/sw/riscv/src/usb.c @@ -1,5 +1,4 @@ #include "usb.h" -#include "dma.h" #include "cfg.h" #include "dd.h" @@ -140,24 +139,12 @@ static bool rx_cmd (uint32_t *data) { 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) { - 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.dma_in_progress = false; p.event_pending = false; p.event_callback_pending = false; @@ -170,7 +157,11 @@ void usb_init (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) { case STATE_IDLE: @@ -247,11 +238,15 @@ void process_usb (void) { case 'W': case 'L': case 'S': - if (!dma_busy()) { + if (!(USB->SCR & USB_SCR_DMA_BUSY)) { if (!p.dma_in_progress) { - bool is_write = (p.cmd == 'W') || (p.cmd == 'S'); - enum dma_dir dir = is_write ? DMA_DIR_TO_SDRAM : DMA_DIR_FROM_SDRAM; - dma_start(p.args[0], p.args[1], DMA_ID_USB, dir); + USB->ADDR = p.args[0]; + USB->LEN = p.args[1]; + 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; } else { if (p.cmd == 'L' || p.cmd == 'S') { @@ -276,43 +271,6 @@ void process_usb (void) { } 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: p.error = true; p.state = STATE_RESPONSE; diff --git a/sw/riscv/src/usb.h b/sw/riscv/src/usb.h index efac87d..5387d9e 100644 --- a/sw/riscv/src/usb.h +++ b/sw/riscv/src/usb.h @@ -18,8 +18,6 @@ typedef enum { CALLBACK_NONE = 0, CALLBACK_SDRAM_WRITE = 1, CALLBACK_SDRAM_READ = 2, - CALLBACK_BUFFER_WRITE = 3, - CALLBACK_BUFFER_READ = 4, } usb_event_callback_t; typedef struct {