From 17311eed905683bdf09a58132e76f3e164690129 Mon Sep 17 00:00:00 2001 From: Polprzewodnikowy Date: Mon, 6 Sep 2021 12:59:37 +0200 Subject: [PATCH] usb debug and si stuff --- fw/SummerCart64.qsf | 105 +++++++++--------- fw/rtl/SummerCart64.sv | 4 + fw/rtl/cpu/cpu_si.sv | 59 ++++++++++ fw/rtl/cpu/cpu_soc.sv | 7 ++ fw/rtl/n64/n64_dd.sv | 83 ++++++++++++++ fw/rtl/n64/n64_pi.sv | 4 +- fw/rtl/n64/n64_si.sv | 222 ++++++++++++++++++++++++++++++++++++++ fw/rtl/n64/n64_soc.sv | 56 ++-------- fw/rtl/system/dd.sv | 40 ------- fw/rtl/system/sc64.sv | 3 +- sw/riscv/SC64.ld | 2 +- sw/riscv/src/controller.c | 206 +++++++++++++++++++++++++++++------ sw/riscv/src/controller.h | 47 ++++++++ sw/riscv/src/driver.c | 76 +++++++++++++ sw/riscv/src/driver.h | 29 +++++ sw/riscv/src/sys.h | 19 ++++ 16 files changed, 790 insertions(+), 172 deletions(-) create mode 100644 fw/rtl/cpu/cpu_si.sv create mode 100644 fw/rtl/n64/n64_dd.sv create mode 100644 fw/rtl/n64/n64_si.sv delete mode 100644 fw/rtl/system/dd.sv create mode 100644 sw/riscv/src/controller.h diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index 3cf5236..476cc80 100644 --- a/fw/SummerCart64.qsf +++ b/fw/SummerCart64.qsf @@ -63,6 +63,7 @@ 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 +set_global_assignment -name SYSTEMVERILOG_FILE rtl/cpu/cpu_si.sv 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 @@ -72,10 +73,12 @@ 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 set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_cfg.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_dd.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_flashram.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi_fifo.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_sdram.sv +set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_si.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_soc.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/SummerCart64.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/system/config.sv @@ -241,66 +244,66 @@ 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 i_uart_cts - 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 - set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_n64_pi_ad[*] - set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_aleh - set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_read - 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_uart_rts - 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 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 +set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_usb_miosi[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_uart_rxd +set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_uart_cts +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 +set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_n64_pi_ad[*] +set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_aleh +set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_pi_read +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_uart_rts +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 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 # ================== - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_usb_miosi[*] - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_nmi - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_uart_rxd - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_uart_cts - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_n64_si_dq - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_reset - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_si_clk - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_aleh - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_read - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_write - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_alel - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to o_n64_irq - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_pwren - set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_usb_miso +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_usb_miosi[*] +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_nmi +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_uart_rxd +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_uart_cts +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to io_n64_si_dq +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_reset +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_si_clk +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_aleh +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_read +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_write +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to i_n64_pi_alel +set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to 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) # --------------------------- # Incremental Compilation Assignments # =================================== - set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top - set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top - set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top # end DESIGN_PARTITION(Top) # ------------------------- diff --git a/fw/rtl/SummerCart64.sv b/fw/rtl/SummerCart64.sv index ccb416a..0474b97 100644 --- a/fw/rtl/SummerCart64.sv +++ b/fw/rtl/SummerCart64.sv @@ -62,6 +62,8 @@ module SummerCart64 ( if_flashram flashram (); + if_si si (); + system system_inst ( .sys(sys) ); @@ -78,6 +80,7 @@ module SummerCart64 ( .dma(dma), .sdram(sdram), .flashram(flashram), + .si(si), .n64_pi_alel(i_n64_pi_alel), .n64_pi_aleh(i_n64_pi_aleh), @@ -103,6 +106,7 @@ module SummerCart64 ( .dma(dma), .sdram(sdram), .flashram(flashram), + .si(si), .gpio_o(gpio_o), .gpio_i(gpio_i), diff --git a/fw/rtl/cpu/cpu_si.sv b/fw/rtl/cpu/cpu_si.sv new file mode 100644 index 0000000..2197d68 --- /dev/null +++ b/fw/rtl/cpu/cpu_si.sv @@ -0,0 +1,59 @@ +module cpu_si ( + if_system.sys sys, + if_cpu_bus bus, + if_si.cpu si +); + 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 + case (bus.address[3:2]) + 0: bus.rdata = { + 20'd0, + si.rx_length[6:3], + 4'd0, + si.tx_busy, + 1'b0, + si.rx_data[0], + si.rx_ready + }; + 1: bus.rdata = {si.rx_data[56:49], si.rx_data[64:57], si.rx_data[72:65], si.rx_data[80:73]}; + 2: bus.rdata = {si.rx_data[24:17], si.rx_data[32:25], si.rx_data[40:33], si.rx_data[48:41]}; + 3: bus.rdata = {16'd0, si.rx_data[8:1], si.rx_data[16:9]}; + default: bus.rdata = 32'd0; + endcase + end + end + + always_comb begin + si.tx_data = {bus.wdata[7:0], bus.wdata[15:8], bus.wdata[23:16], bus.wdata[31:24]}; + si.tx_length = bus.wdata[22:16]; + end + + always_ff @(posedge sys.clk) begin + si.tx_reset <= 1'b0; + si.rx_reset <= 1'b0; + si.tx_start <= 1'b0; + si.tx_wmask <= 3'b000; + + if (bus.request && (&bus.wmask)) begin + case (bus.address[3:2]) + 0: begin + si.tx_reset <= bus.wdata[7]; + si.rx_reset <= bus.wdata[6]; + si.tx_start <= bus.wdata[2]; + end + 1: si.tx_wmask[0] <= 1'b1; + 2: si.tx_wmask[1] <= 1'b1; + 3: si.tx_wmask[2] <= 1'b1; + endcase + end + end + +endmodule diff --git a/fw/rtl/cpu/cpu_soc.sv b/fw/rtl/cpu/cpu_soc.sv index 2889149..5a9303a 100644 --- a/fw/rtl/cpu/cpu_soc.sv +++ b/fw/rtl/cpu/cpu_soc.sv @@ -4,6 +4,7 @@ module cpu_soc ( if_dma dma, if_sdram.cpu sdram, if_flashram.cpu flashram, + if_si.cpu si, input [7:0] gpio_i, output [7:0] gpio_o, @@ -104,4 +105,10 @@ module cpu_soc ( .flashram(flashram) ); + cpu_si cpu_si_inst ( + .sys(sys), + .bus(bus.at[sc64::ID_CPU_SI].device), + .si(si) + ); + endmodule diff --git a/fw/rtl/n64/n64_dd.sv b/fw/rtl/n64/n64_dd.sv new file mode 100644 index 0000000..51e5812 --- /dev/null +++ b/fw/rtl/n64/n64_dd.sv @@ -0,0 +1,83 @@ +interface if_dd(); + + logic hard_reset; + logic cmd_request; + logic cmd_ack; + logic [7:0] command; + logic [15:0] status; + logic [15:0] data_input; + logic [15:0] data_output; + logic bm_request; + logic [15:0] bm_control; + logic [15:0] bm_status; + + modport n64 ( + output hard_reset, + output cmd_request, + input cmd_ack, + output command, + input status, + output data_input, + input data_output, + output bm_request, + output bm_control, + input bm_status + ); + + modport cpu ( + input hard_reset, + input cmd_request, + output cmd_ack, + input command, + output status, + input data_input, + output data_output, + input bm_request, + input bm_control, + output bm_status + ); + +endinterface + + +module n64_dd ( + if_system.sys sys, + if_n64_bus bus +); + + typedef enum bit [0:0] { + S_IDLE, + S_WAIT + } e_state; + + e_state state; + + always_comb begin + bus.rdata = 16'h0000; + if (bus.ack) begin + bus.rdata = !bus.address[1] ? 16'h0040 : 16'h0000; + end + end + + always_ff @(posedge sys.clk) begin + bus.ack <= 1'b0; + + if (sys.reset) begin + state <= S_IDLE; + end else begin + case (state) + S_IDLE: begin + if (bus.request) begin + state <= S_WAIT; + bus.ack <= 1'b1; + end + end + + S_WAIT: begin + state <= S_IDLE; + end + endcase + end + end + +endmodule diff --git a/fw/rtl/n64/n64_pi.sv b/fw/rtl/n64/n64_pi.sv index b5fb99c..ce83be3 100644 --- a/fw/rtl/n64/n64_pi.sv +++ b/fw/rtl/n64/n64_pi.sv @@ -61,7 +61,7 @@ module n64_pi ( ); - // Control signals input synchronization + // Control signals and input synchronization logic [2:0] n64_pi_alel_ff; logic [2:0] n64_pi_aleh_ff; @@ -207,7 +207,7 @@ module n64_pi ( if (cfg.dd_enabled) begin if (n64_pi_ad_input == 16'h0500) begin n64_pi_address_valid <= 1'b1; - next_id <= sc64::ID_N64_DDREGS; + next_id <= sc64::ID_N64_DD; end if (n64_pi_ad_input >= 16'h0600 && n64_pi_ad_input < 16'h0640) begin n64_pi_address_valid <= 1'b1; diff --git a/fw/rtl/n64/n64_si.sv b/fw/rtl/n64/n64_si.sv new file mode 100644 index 0000000..c2bac1d --- /dev/null +++ b/fw/rtl/n64/n64_si.sv @@ -0,0 +1,222 @@ +interface if_si (); + + logic rx_reset; + logic rx_ready; + logic [6:0] rx_length; + logic [80:0] rx_data; + + logic tx_reset; + logic tx_start; + logic tx_busy; + logic [2:0] tx_wmask; + logic [6:0] tx_length; + logic [31:0] tx_data; + + modport si ( + input rx_reset, + output rx_ready, + output rx_length, + output rx_data, + input tx_reset, + input tx_start, + output tx_busy, + input tx_wmask, + input tx_length, + input tx_data + ); + + modport cpu ( + output rx_reset, + input rx_ready, + input rx_length, + input rx_data, + output tx_reset, + output tx_start, + input tx_busy, + output tx_wmask, + output tx_length, + output tx_data + ); + +endinterface + +module n64_si ( + if_system.sys sys, + if_si.si si, + + input n64_si_clk, + inout n64_si_dq +); + + // Control signals and input synchronization + + logic [1:0] n64_si_clk_ff; + + always_ff @(posedge sys.clk) begin + n64_si_clk_ff <= {n64_si_clk_ff[0], n64_si_clk}; + end + + logic si_reset; + logic si_clk; + logic si_dq; + + always_comb begin + si_reset = sys.n64_hard_reset; + si_clk = n64_si_clk_ff[1]; + si_dq = n64_si_dq; + end + + logic last_si_clk; + + always_ff @(posedge sys.clk) begin + last_si_clk <= si_clk; + end + + logic si_clk_rising_edge; + logic si_clk_falling_edge; + + always_comb begin + si_clk_rising_edge = !si_reset && !last_si_clk && si_clk; + si_clk_falling_edge = !si_reset && last_si_clk && !si_clk; + end + + logic si_dq_output_enable; + logic si_dq_output_enable_data; + + always_ff @(posedge sys.clk) begin + si_dq_output_enable <= si_dq_output_enable_data; + end + + always_comb begin + n64_si_dq = si_dq_output_enable ? 1'b0 : 1'bZ; + end + + + // Data register and shifter + + logic [80:0] trx_data; + logic rx_shift; + logic tx_shift; + + always_comb begin + si.rx_data = trx_data; + end + + always_ff @(posedge sys.clk) begin + if (si.tx_wmask[0]) trx_data[80:49] <= si.tx_data; + if (si.tx_wmask[1]) trx_data[48:17] <= si.tx_data; + if (si.tx_wmask[2]) trx_data[16:0] <= si.tx_data[16:0]; + + if (rx_shift || tx_shift) begin + trx_data <= {trx_data[79:0], rx_sub_bit_counter < 2'd2}; + end + end + + + // RX path + + typedef enum bit [0:0] { + S_RX_IDLE, + S_RX_WAITING + } e_rx_state; + + e_rx_state rx_state; + + logic [1:0] rx_sub_bit_counter; + logic [3:0] rx_timeout_counter; + + always_ff @(posedge sys.clk) begin + rx_shift <= 1'b0; + + if (si_clk_rising_edge) begin + if (rx_timeout_counter < 4'd8) begin + rx_timeout_counter <= rx_timeout_counter + 1'd1; + end else if (si.rx_length > 7'd0) begin + si.rx_ready <= 1'b1; + end + end + + if (sys.reset || si.rx_reset) begin + rx_state <= S_RX_IDLE; + si.rx_ready <= 1'b0; + si.rx_length <= 7'd0; + end else if (!si.tx_busy) begin + case (rx_state) + S_RX_IDLE: begin + if (si_clk_rising_edge && !si_dq) begin + rx_state <= S_RX_WAITING; + rx_sub_bit_counter <= 2'd0; + rx_timeout_counter <= 3'd0; + end + end + + S_RX_WAITING: begin + if (si_clk_rising_edge) begin + if (si_dq) begin + rx_state <= S_RX_IDLE; + rx_shift <= 1'b1; + si.rx_length <= si.rx_length + 1'd1; + end else if (rx_sub_bit_counter < 2'd3) begin + rx_sub_bit_counter <= rx_sub_bit_counter + 1'd1; + end + end + end + endcase + end + end + + + // TX path + + typedef enum bit [0:0] { + S_TX_IDLE, + S_TX_SENDING + } e_tx_state; + + e_tx_state tx_state; + + logic [2:0] tx_sub_bit_counter; + logic [6:0] tx_bit_counter; + + always_ff @(posedge sys.clk) begin + tx_shift <= 1'b0; + + if (sys.reset || si.tx_reset) begin + tx_state <= S_TX_IDLE; + si_dq_output_enable_data <= 1'b0; + si.tx_busy <= 1'b0; + end else begin + case (tx_state) + S_TX_IDLE: begin + if (si.tx_start) begin + tx_state <= S_TX_SENDING; + tx_sub_bit_counter <= 3'd0; + tx_bit_counter <= si.tx_length; + si.tx_busy <= 1'b1; + end + end + + S_TX_SENDING: begin + if (si_clk_falling_edge) begin + tx_sub_bit_counter <= tx_sub_bit_counter + 1'd1; + if (tx_sub_bit_counter == 3'd7) begin + tx_shift <= 1'b1; + if (tx_bit_counter > 7'd1) begin + tx_bit_counter <= tx_bit_counter - 1'd1; + end else begin + tx_state <= S_TX_IDLE; + si.tx_busy <= 1'b0; + end + end + if (trx_data[80]) begin + si_dq_output_enable_data <= tx_sub_bit_counter < 3'd2; + end else begin + si_dq_output_enable_data <= tx_sub_bit_counter < 3'd6; + end + end + end + endcase + end + end + +endmodule diff --git a/fw/rtl/n64/n64_soc.sv b/fw/rtl/n64/n64_soc.sv index 2c26cb2..1f38904 100644 --- a/fw/rtl/n64/n64_soc.sv +++ b/fw/rtl/n64/n64_soc.sv @@ -4,6 +4,7 @@ module n64_soc ( if_dma.memory dma, if_sdram.memory sdram, if_flashram.flashram flashram, + if_si.si si, input n64_pi_alel, input n64_pi_aleh, @@ -37,6 +38,14 @@ module n64_soc ( .n64_pi_ad(n64_pi_ad) ); + n64_si n64_si_inst ( + .sys(sys), + .si(si), + + .n64_si_clk(n64_si_clk), + .n64_si_dq(n64_si_dq) + ); + n64_sdram n64_sdram_inst ( .sys(sys), .bus(bus.at[sc64::ID_N64_SDRAM].device), @@ -64,9 +73,9 @@ module n64_soc ( .flashram(flashram) ); - n64_dummy n64_ddregs_inst ( + n64_dd n64_dd_inst ( .sys(sys), - .bus(bus.at[sc64::ID_N64_DDREGS].device) + .bus(bus.at[sc64::ID_N64_DD].device) ); n64_cfg n64_cfg_inst ( @@ -76,46 +85,3 @@ module n64_soc ( ); endmodule - - -module n64_dummy ( - if_system.sys sys, - if_n64_bus bus -); - - typedef enum bit [0:0] { - S_IDLE, - S_WAIT - } e_state; - - e_state state; - - always_comb begin - bus.rdata = 16'h0000; - if (bus.ack) begin - bus.rdata = !bus.address[1] ? 16'h0040 : 16'h0000; - end - end - - always_ff @(posedge sys.clk) begin - bus.ack <= 1'b0; - - if (sys.reset) begin - state <= S_IDLE; - end else begin - case (state) - S_IDLE: begin - if (bus.request) begin - state <= S_WAIT; - bus.ack <= 1'b1; - end - end - - S_WAIT: begin - state <= S_IDLE; - end - endcase - end - end - -endmodule diff --git a/fw/rtl/system/dd.sv b/fw/rtl/system/dd.sv deleted file mode 100644 index 53b184d..0000000 --- a/fw/rtl/system/dd.sv +++ /dev/null @@ -1,40 +0,0 @@ -interface if_dd(); - - logic hard_reset; - logic cmd_request; - logic cmd_ack; - logic [7:0] command; - logic [15:0] status; - logic [15:0] data_input; - logic [15:0] data_output; - logic bm_request; - logic [15:0] bm_control; - logic [15:0] bm_status; - - modport n64 ( - output hard_reset, - output cmd_request, - input cmd_ack, - output command, - input status, - output data_input, - input data_output, - output bm_request, - output bm_control, - input bm_status - ); - - modport cpu ( - input hard_reset, - input cmd_request, - output cmd_ack, - input command, - output status, - input data_input, - output data_output, - input bm_request, - input bm_control, - output bm_status - ); - -endinterface \ No newline at end of file diff --git a/fw/rtl/system/sc64.sv b/fw/rtl/system/sc64.sv index 38d6eea..9044d52 100644 --- a/fw/rtl/system/sc64.sv +++ b/fw/rtl/system/sc64.sv @@ -4,7 +4,7 @@ package sc64; ID_N64_SDRAM, ID_N64_BOOTLOADER, ID_N64_FLASHRAM, - ID_N64_DDREGS, + ID_N64_DD, ID_N64_CFG, __ID_N64_END } e_n64_id; @@ -20,6 +20,7 @@ package sc64; ID_CPU_CFG, ID_CPU_SDRAM, ID_CPU_FLASHRAM, + ID_CPU_SI, __ID_CPU_END } e_cpu_id; diff --git a/sw/riscv/SC64.ld b/sw/riscv/SC64.ld index d7302a4..22abc7c 100644 --- a/sw/riscv/SC64.ld +++ b/sw/riscv/SC64.ld @@ -3,7 +3,7 @@ MEMORY { ROM (rx) : org = 0x10000000, len = 128 } -__stack_pointer = ORIGIN(RAM) + LENGTH(RAM) - 4; +__stack_pointer = ORIGIN(RAM) + LENGTH(RAM) - 16; ENTRY(reset_handler) diff --git a/sw/riscv/src/controller.c b/sw/riscv/src/controller.c index 6a65eab..100f58d 100644 --- a/sw/riscv/src/controller.c +++ b/sw/riscv/src/controller.c @@ -1,16 +1,28 @@ #include "sys.h" #include "driver.h" +#include "controller.h" static e_cfg_save_type_t save_type = CFG_SAVE_TYPE_NONE; static uint16_t cic_seed = 0xFFFF; static uint8_t tv_type = 0xFF; +static bool eeprom_enabled = false; +static bool n64_to_pc_pending = false; +static uint32_t n64_to_pc_address; +static uint32_t n64_to_pc_length; + +static bool pc_to_n64_ready = false; +static uint32_t pc_to_n64_arg; +static uint32_t pc_to_n64_address; +static uint32_t pc_to_n64_length; void process_usb (void); void process_cfg (void); void process_flashram (void); +void process_si (void); +bool debug_decide (uint32_t *args); void config_update (uint32_t *args); void config_query (uint32_t *args); @@ -23,6 +35,7 @@ void main (void) { dma_abort(); usb_flush_rx(); usb_flush_tx(); + si_reset(); cfg_set_sdram_switch(true); cfg_set_save_type(CFG_SAVE_TYPE_NONE); @@ -33,21 +46,11 @@ void main (void) { process_usb(); process_cfg(); process_flashram(); + process_si(); } } -typedef enum { - USB_STATE_IDLE, - USB_STATE_ARGS, - USB_STATE_DATA, - USB_STATE_RESPONSE, -} e_usb_state_t; - -#define USB_CMD_TOKEN (0x434D4400) -#define USB_CMP_TOKEN (0x434D5000) -#define USB_ERR_TOKEN (0x45525200) - void process_usb (void) { static e_usb_state_t state = USB_STATE_IDLE; static uint8_t cmd; @@ -60,14 +63,20 @@ void process_usb (void) { case USB_STATE_IDLE: if (usb_rx_word(&args[0])) { if ((args[0] & 0xFFFFFF00) == USB_CMD_TOKEN) { - state = USB_STATE_ARGS; cmd = args[0] & 0xFF; error = false; processing = false; current_word = 0; + state = USB_STATE_ARGS; } else { - state = USB_STATE_RESPONSE; + cmd = '!'; error = true; + state = USB_STATE_RESPONSE; + } + } else if (n64_to_pc_pending) { + if (!dma_busy()) { + dma_start(n64_to_pc_address, n64_to_pc_length, DMA_ID_USB, DMA_DIR_FROM_SDRAM); + state = USB_STATE_N64_TO_PC; } } break; @@ -112,11 +121,15 @@ void process_usb (void) { break; case 'D': + cfg_set_usb_waiting(true); + pc_to_n64_arg = args[0]; + pc_to_n64_length = args[1]; + state = USB_STATE_PC_TO_N64; break; default: - state = USB_STATE_RESPONSE; error = true; + state = USB_STATE_RESPONSE; break; } break; @@ -126,6 +139,28 @@ void process_usb (void) { state = USB_STATE_IDLE; } break; + + case USB_STATE_N64_TO_PC: + if (!dma_busy()) { + n64_to_pc_pending = false; + state = USB_STATE_IDLE; + } + break; + + case USB_STATE_PC_TO_N64: + if (!dma_busy()) { + if (!processing) { + if (pc_to_n64_ready) { + dma_start(pc_to_n64_address, pc_to_n64_length, DMA_ID_USB, DMA_DIR_TO_SDRAM); + processing = true; + } + } else { + pc_to_n64_ready = false; + processing = false; + state = USB_STATE_IDLE; + } + } + break; default: state = USB_STATE_IDLE; @@ -136,6 +171,7 @@ void process_usb (void) { void process_cfg (void) { uint8_t cmd; uint32_t args[2]; + bool error; if (cfg_get_command(&cmd, args)) { switch (cmd) { @@ -148,8 +184,10 @@ void process_cfg (void) { config_query(args); cfg_set_response(args, false); break; - + case 'D': + error = debug_decide(args); + cfg_set_response(args, error); break; default: @@ -181,15 +219,124 @@ void process_flashram (void) { } } +void process_si (void) { + uint8_t rx_data[10]; + uint8_t tx_data[10]; + uint32_t *save_data; + uint32_t *data_offset; -typedef enum { - CONFIG_UPDATE_SDRAM_SWITCH, - CONFIG_UPDATE_SDRAM_WRITABLE, - CONFIG_UPDATE_DD_ENABLE, - CONFIG_UPDATE_SAVE_TYPE, - CONFIG_UPDATE_CIC_SEED, - CONFIG_UPDATE_TV_TYPE -} e_config_update_t; + if (si_rx_ready()) { + if (si_rx_stop_bit()) { + si_rx(rx_data); + + if (eeprom_enabled) { + save_data = (uint32_t *) (SDRAM_BASE + cfg_get_save_offset() + (rx_data[1] * 8)); + + switch (rx_data[0]) { + case SI_CMD_EEPROM_STATUS: + tx_data[0] = 0x00; + tx_data[1] = save_type == CFG_SAVE_TYPE_EEPROM_4K ? SI_EEPROM_ID_4K : SI_EEPROM_ID_16K; + tx_data[2] = 0x00; + si_tx(tx_data, 3); + break; + case SI_CMD_EEPROM_READ: + data_offset = (uint32_t *) (&tx_data[0]); + data_offset[0] = swapb(save_data[0]); + data_offset[1] = swapb(save_data[1]); + si_tx(tx_data, 8); + break; + case SI_CMD_EEPROM_WRITE: + data_offset = (uint32_t *) (&rx_data[2]); + save_data[0] = swapb(data_offset[0]); + save_data[1] = swapb(data_offset[1]); + tx_data[0] = 0x00; + si_tx(tx_data, 1); + break; + } + } + + switch (rx_data[0]) { + case SI_CMD_RTC_STATUS: + tx_data[0] = 0x00; + tx_data[1] = 0x10; + tx_data[2] = 0x00; + si_tx(tx_data, 3); + break; + case SI_CMD_RTC_READ: + if (rx_data[1] == 0) { + tx_data[0] = 0x03; + tx_data[1] = 0x00; + tx_data[2] = 0x00; + tx_data[3] = 0x00; + tx_data[4] = 0x00; + tx_data[5] = 0x00; + tx_data[6] = 0x00; + tx_data[7] = 0x00; + } else { + tx_data[0] = 0x00; + tx_data[1] = 0x00; + tx_data[2] = 0x92; + tx_data[3] = 0x06; + tx_data[4] = 0x01; + tx_data[5] = 0x09; + tx_data[6] = 0x21; + tx_data[7] = 0x01; + } + tx_data[8] = 0x00; + si_tx(tx_data, 9); + break; + case SI_CMD_RTC_WRITE: + tx_data[0] = 0x00; + si_tx(tx_data, 1); + break; + } + } + + si_rx_reset(); + } +} + +bool debug_decide (uint32_t *args) { + switch (args[0]) { + case DEBUG_WRITE_ADDRESS: + if (!n64_to_pc_pending) { + n64_to_pc_address = args[1]; + } else { + return true; + } + break; + case DEBUG_WRITE_LENGTH_START: + if (!n64_to_pc_pending) { + n64_to_pc_length = args[1]; + n64_to_pc_pending = true; + } else { + return true; + } + break; + case DEBUG_WRITE_STATUS: + args[1] = n64_to_pc_pending; + break; + case DEBUG_READ_ARG: + args[1] = pc_to_n64_arg; + break; + case DEBUG_READ_LENGTH: + args[1] = pc_to_n64_length; + break; + case DEBUG_READ_ADDRESS_START: + if (!pc_to_n64_ready) { + pc_to_n64_ready = true; + pc_to_n64_address = args[1]; + cfg_set_usb_waiting(false); + } else { + return true; + } + break; + default: + return true; + } + + return false; +} void config_update (uint32_t *args) { switch (args[0]) { @@ -204,6 +351,10 @@ void config_update (uint32_t *args) { break; case CONFIG_UPDATE_SAVE_TYPE: save_type = args[1] & 0x07; + eeprom_enabled = ( + save_type == CFG_SAVE_TYPE_EEPROM_4K || + save_type == CFG_SAVE_TYPE_EEPROM_16K + ); cfg_set_save_type(save_type); break; case CONFIG_UPDATE_CIC_SEED: @@ -215,15 +366,6 @@ void config_update (uint32_t *args) { } } -typedef enum { - CONFIG_QUERY_STATUS, - CONFIG_QUERY_SAVE_TYPE, - CONFIG_QUERY_CIC_SEED, - CONFIG_QUERY_TV_TYPE, - CONFIG_QUERY_SAVE_OFFSET, - CONFIG_QUERY_DD_OFFSET, -} e_config_query_t; - void config_query (uint32_t *args) { switch (args[0]) { case CONFIG_QUERY_STATUS: diff --git a/sw/riscv/src/controller.h b/sw/riscv/src/controller.h new file mode 100644 index 0000000..9064594 --- /dev/null +++ b/sw/riscv/src/controller.h @@ -0,0 +1,47 @@ +#ifndef CONTROLLER_H__ +#define CONTROLLER_H__ + + +#define USB_CMD_TOKEN (0x434D4400) +#define USB_CMP_TOKEN (0x434D5000) +#define USB_ERR_TOKEN (0x45525200) + + +typedef enum { + USB_STATE_IDLE, + USB_STATE_ARGS, + USB_STATE_DATA, + USB_STATE_RESPONSE, + USB_STATE_N64_TO_PC, + USB_STATE_PC_TO_N64, +} e_usb_state_t; + +typedef enum { + DEBUG_WRITE_ADDRESS, + DEBUG_WRITE_LENGTH_START, + DEBUG_WRITE_STATUS, + DEBUG_READ_ARG, + DEBUG_READ_LENGTH, + DEBUG_READ_ADDRESS_START, +} e_debug_t; + +typedef enum { + CONFIG_UPDATE_SDRAM_SWITCH, + CONFIG_UPDATE_SDRAM_WRITABLE, + CONFIG_UPDATE_DD_ENABLE, + CONFIG_UPDATE_SAVE_TYPE, + CONFIG_UPDATE_CIC_SEED, + CONFIG_UPDATE_TV_TYPE +} e_config_update_t; + +typedef enum { + CONFIG_QUERY_STATUS, + CONFIG_QUERY_SAVE_TYPE, + CONFIG_QUERY_CIC_SEED, + CONFIG_QUERY_TV_TYPE, + CONFIG_QUERY_SAVE_OFFSET, + CONFIG_QUERY_DD_OFFSET, +} e_config_query_t; + + +#endif diff --git a/sw/riscv/src/driver.c b/sw/riscv/src/driver.c index 5216089..692132a 100644 --- a/sw/riscv/src/driver.c +++ b/sw/riscv/src/driver.c @@ -255,3 +255,79 @@ void cfg_set_response (uint32_t *args, bool error) { } CFG->SCR &= ~(CFG_SCR_CPU_BUSY); } + + +// SI + +bool si_rx_ready (void) { + return SI->SCR & SI_SCR_RX_READY; +} + +bool si_rx_stop_bit (void) { + return SI->SCR & SI_SCR_RX_STOP_BIT; +} + +bool si_tx_busy (void) { + return SI->SCR & SI_SCR_TX_BUSY; +} + +void si_rx_reset (void) { + SI->SCR = SI_SCR_RX_RESET; +} + +void si_reset (void) { + SI->SCR = SI_SCR_TX_RESET | SI_SCR_RX_RESET; +} + +void si_rx (uint8_t *data) { + uint32_t rx_length = (SI->SCR & SI_SCR_RX_LENGTH_MASK) >> SI_SCR_RX_LENGTH_BIT; + for (size_t i = 0; i < rx_length; i++) { + data[i] = ((uint8_t *) SI->DATA)[(10 - rx_length) + i]; + } +} + +void si_tx (uint8_t *data, size_t length) { + for (size_t i = 0; i < ((length + 3) / 4); i++) { + SI->DATA[i] = ((uint32_t *) data)[i]; + } + SI->DATA[length / 4] |= (0x80 << ((length % 4) * 8)); + SI->SCR = (((length * 8) + 1) << SI_SCR_TX_LENGTH_BIT) | SI_SCR_TX_START; +} + + +// misc + +const char hex_char_map[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' +}; + +void print (const char *text) { + while (*text != '\0') { + while (!(UART->SCR & UART_SCR_TXE)); + UART->DR = *text++; + } +} + +void print_02hex (uint8_t number) { + char buffer[3]; + buffer[0] = hex_char_map[(number >> 4) & 0x0F]; + buffer[1] = hex_char_map[number & 0x0F]; + buffer[2] = '\0'; + print(buffer); +} + +void print_08hex (uint32_t number) { + print_02hex((number >> 24) & 0xFF); + print_02hex((number >> 16) & 0xFF); + print_02hex((number >> 8) & 0xFF); + print_02hex((number >> 0) & 0xFF); +} + +uint32_t swapb (uint32_t data) { + return ( + (data << 24) | + ((data << 8) & 0x00FF0000) | + ((data >> 8) & 0x0000FF00) | + (data >> 24) + ); +} diff --git a/sw/riscv/src/driver.h b/sw/riscv/src/driver.h index d745b46..9bb5038 100644 --- a/sw/riscv/src/driver.h +++ b/sw/riscv/src/driver.h @@ -92,4 +92,33 @@ bool cfg_get_command (uint8_t *cmd, uint32_t *args); void cfg_set_response (uint32_t *args, bool error); +// SI + +#define SI_CMD_EEPROM_STATUS (0x00) +#define SI_CMD_EEPROM_READ (0x04) +#define SI_CMD_EEPROM_WRITE (0x05) +#define SI_CMD_RTC_STATUS (0x06) +#define SI_CMD_RTC_READ (0x07) +#define SI_CMD_RTC_WRITE (0x08) + +#define SI_EEPROM_ID_4K (0x80) +#define SI_EEPROM_ID_16K (0xC0) + +bool si_rx_ready (void); +bool si_rx_stop_bit (void); +bool si_tx_busy (void); +void si_rx_reset (void); +void si_reset (void); +void si_rx (uint8_t *data); +void si_tx (uint8_t *data, size_t length); + + +// misc + +void print (const char *text); +void print_02hex (uint8_t number); +void print_08hex (uint32_t number); +uint32_t swapb (uint32_t data); + + #endif diff --git a/sw/riscv/src/sys.h b/sw/riscv/src/sys.h index bdc4286..5a5e570 100644 --- a/sw/riscv/src/sys.h +++ b/sw/riscv/src/sys.h @@ -137,4 +137,23 @@ typedef volatile struct flashram_regs { #define FLASHRAM_PAGE_BIT (8) +typedef volatile struct si_regs { + io32_t SCR; + io32_t DATA[3]; +} si_regs_t; + +#define SI_BASE (0xA0000000UL) +#define SI ((si_regs_t *) SI_BASE) + +#define SI_SCR_RX_READY (1 << 0) +#define SI_SCR_RX_STOP_BIT (1 << 1) +#define SI_SCR_TX_START (1 << 2) +#define SI_SCR_TX_BUSY (1 << 3) +#define SI_SCR_RX_RESET (1 << 6) +#define SI_SCR_TX_RESET (1 << 7) +#define SI_SCR_RX_LENGTH_BIT (8) +#define SI_SCR_RX_LENGTH_MASK (0x7F << SI_SCR_RX_LENGTH_BIT) +#define SI_SCR_TX_LENGTH_BIT (16) + + #endif