diff --git a/fw/SummerCart64.qsf b/fw/SummerCart64.qsf index 78c8bda..0c36a00 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 = 19:00:58 February 02, 2022 +# Date created = 19:19:14 February 04, 2022 # # -------------------------------------------------------------------------- # # @@ -88,11 +88,9 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/vendor/vendor_reconfigure.sv # Pin & Location Assignments # ========================== -set_location_assignment PIN_6 -to o_usb_clk -set_location_assignment PIN_7 -to io_usb_miosi[2] -set_location_assignment PIN_8 -to io_usb_miosi[3] -set_location_assignment PIN_10 -to io_usb_miosi[0] -set_location_assignment PIN_11 -to io_usb_miosi[1] +set_location_assignment PIN_6 -to o_usb_cs +set_location_assignment PIN_7 -to i_usb_miso +set_location_assignment PIN_8 -to o_usb_clk set_location_assignment PIN_12 -to i_uart_rxd set_location_assignment PIN_13 -to o_uart_txd set_location_assignment PIN_17 -to o_led @@ -165,13 +163,15 @@ 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_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 +set_location_assignment PIN_124 -to io_usb_miosi[7] +set_location_assignment PIN_127 -to io_usb_miosi[6] +set_location_assignment PIN_130 -to io_usb_miosi[4] +set_location_assignment PIN_131 -to io_usb_miosi[5] +set_location_assignment PIN_134 -to io_usb_miosi[3] +set_location_assignment PIN_135 -to io_usb_miosi[2] +set_location_assignment PIN_140 -to io_usb_miosi[1] +set_location_assignment PIN_141 -to io_usb_miosi[0] # Classic Timing Assignments # ========================== @@ -231,34 +231,39 @@ 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 i_uart_rxd - set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_rtc_sda 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_alel 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 i_n64_reset + set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_n64_si_clk + set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_uart_rxd + set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_usb_miso + set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_n64_pi_ad[*] + set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_rtc_sda set_instance_assignment -name FAST_INPUT_REGISTER ON -to io_sdram_dq[*] - 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_INPUT_REGISTER ON -to io_usb_miosi[*] set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_n64_pi_ad[*] - 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 io_rtc_sda + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_sdram_dq[*] + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to io_usb_miosi[*] + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_rtc_scl 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_sdram_cas + 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_we + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_uart_txd + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_usb_clk + set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_usb_cs 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_usb_miosi[*] # 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 io_n64_si_dq diff --git a/fw/SummerCart64.sdc b/fw/SummerCart64.sdc index 4cbd4d7..c8db83c 100644 --- a/fw/SummerCart64.sdc +++ b/fw/SummerCart64.sdc @@ -49,11 +49,11 @@ set_multicycle_path -hold -end 1 -from [get_clocks {sdram_clk}] -to [get_clocks # FT1248 timings -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_output_delay -clock [get_clocks {usb_clk}] -max 2.0 [get_ports {io_usb_miosi[*] o_usb_cs}] +set_output_delay -clock [get_clocks {usb_clk}] -min -1.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_input_delay -clock [get_clocks {usb_clk}] -min 2.5 [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}] diff --git a/fw/rtl/usb/usb_ft1248.sv b/fw/rtl/usb/usb_ft1248.sv index 3dd1de7..c746c5b 100644 --- a/fw/rtl/usb/usb_ft1248.sv +++ b/fw/rtl/usb/usb_ft1248.sv @@ -27,6 +27,7 @@ module usb_ft1248 ( logic rx_full; logic rx_almost_full; logic rx_write; + logic [7:0] rx_wdata; logic tx_empty; logic tx_almost_empty; @@ -45,7 +46,7 @@ module usb_ft1248 ( .full(rx_full), .almost_full(rx_almost_full), .wrreq(rx_write), - .data(usb_miosi) + .data(rx_wdata) ); intel_fifo_8 fifo_8_tx_inst ( @@ -63,6 +64,29 @@ module usb_ft1248 ( .data(tx_wdata) ); + logic [7:0] usb_miosi_out; + logic usb_oe; + + logic ft_clk; + logic ft_cs; + logic ft_miso; + logic [7:0] ft_miosi_in; + logic [7:0] ft_miosi_out; + logic ft_oe; + + always_ff @(posedge clk) begin + usb_clk <= ft_clk; + usb_cs <= ft_cs; + ft_miso <= usb_miso; + ft_miosi_in <= usb_miosi; + usb_miosi_out <= ft_miosi_out; + usb_oe <= ft_oe; + end + + always_comb begin + usb_miosi = usb_oe ? usb_miosi_out : 8'hZZ; + end + typedef enum bit [2:0] { STATE_IDLE, STATE_SELECT, @@ -80,163 +104,202 @@ module usb_ft1248 ( CMD_WRITE_BUFFER_FLUSH = 8'h08 } e_command; - 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; - - always_comb begin - usb_miosi = 8'hZZ; - if (usb_miosi_oe) begin - usb_miosi = 8'h00; - if ((state == STATE_COMMAND) || (state == STATE_STATUS)) begin - usb_miosi = usb_cmd; - end - if ((state == STATE_DATA) || (state == STATE_DESELECT)) begin - if (usb_cmd == CMD_WRITE) begin - usb_miosi = tx_rdata; - end - if (usb_cmd == CMD_WRITE_MODEM_STATUS) begin - usb_miosi = {2'b00, reset_reply, 5'b00000}; - end - end - end - end + e_state next_state; + e_command cmd; + e_command next_cmd; + logic [3:0] phase; + logic reset_reply; + logic last_reset_status; + logic [4:0] modem_status_counter; + logic write_modem_status_pending; + logic write_buffer_flush_pending; always_ff @(posedge clk) begin - rx_write <= 1'b0; - tx_read <= 1'b0; - modem_status_read <= 1'b0; + state <= next_state; + cmd <= next_cmd; + phase <= {phase[2:0], phase[3]}; + if (state == STATE_IDLE) begin + phase <= 4'b0100; + end 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; + modem_status_counter <= 5'd0; + write_modem_status_pending <= 1'b0; + write_buffer_flush_pending <= 1'b0; end else begin - 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 + if (write_buffer_flush) begin + write_buffer_flush_pending <= 1'b1; end + if (state == STATE_IDLE) begin + modem_status_counter <= modem_status_counter + 1'd1; + end + + if (!ft_miso && (state == STATE_DATA) && phase[3]) begin + if (cmd == CMD_READ_MODEM_STATUS) begin + last_reset_status <= ft_miosi_in[0]; + if (!last_reset_status && ft_miosi_in[0]) begin + reset_pending <= 1'b1; + end + if (last_reset_status && !ft_miosi_in[0]) begin + write_modem_status_pending <= 1'b1; + reset_reply <= 1'b0; + end + end + if (cmd == CMD_WRITE_MODEM_STATUS) begin + write_modem_status_pending <= 1'b0; + end + if (cmd == CMD_WRITE_BUFFER_FLUSH) begin + write_buffer_flush_pending <= 1'b0; + end + end + end + end + + always_comb begin + ft_clk = 1'b0; + ft_cs = 1'b1; + ft_miosi_out = 8'hFF; + ft_oe = 1'b0; + + if (state == STATE_SELECT) begin + ft_cs = 1'b0; + end + + if (state == STATE_COMMAND) begin + if (phase[0] || phase[1]) begin + ft_clk = 1'b1; + end + ft_cs = 1'b0; + ft_miosi_out = cmd; + ft_oe = 1'b1; + end + + if (state == STATE_STATUS) begin + if (phase[0] || phase[1]) begin + ft_clk = 1'b1; + end + ft_cs = 1'b0; + end + + if (state == STATE_DATA) begin + ft_cs = 1'b0; + if (phase[0] || phase[1]) begin + ft_clk = 1'b1; + end + if (cmd == CMD_WRITE) begin + ft_miosi_out = tx_rdata; + ft_oe = 1'b1; + end + if (cmd == CMD_WRITE_MODEM_STATUS) begin + ft_miosi_out = {2'b00, reset_reply, 5'b00000}; + ft_oe = 1'b1; + end + end + end + + always_comb begin + rx_write = 1'b0; + tx_read = 1'b0; + + rx_wdata = ft_miosi_in; + + if (!ft_miso && (state == STATE_DATA) && phase[3]) begin + if (cmd == CMD_WRITE) begin + tx_read = 1'b1; + end + if (cmd == CMD_READ) begin + rx_write = 1'b1; + end + end + end + + always_comb begin + next_state = state; + next_cmd = cmd; + + if (reset) begin + next_state = STATE_IDLE; + end else begin case (state) STATE_IDLE: begin - usb_cs <= 1'b0; - state <= STATE_SELECT; if (write_modem_status_pending) begin - usb_cmd <= CMD_WRITE_MODEM_STATUS; + next_state = STATE_SELECT; + next_cmd = CMD_WRITE_MODEM_STATUS; end else if (&modem_status_counter) begin - usb_cmd <= CMD_READ_MODEM_STATUS; + next_state = STATE_SELECT; + next_cmd = CMD_READ_MODEM_STATUS; end else if (!tx_empty) begin - usb_cmd <= CMD_WRITE; + next_state = STATE_SELECT; + next_cmd = CMD_WRITE; end else if (write_buffer_flush_pending) begin - usb_cmd <= CMD_WRITE_BUFFER_FLUSH; + next_state = STATE_SELECT; + next_cmd = CMD_WRITE_BUFFER_FLUSH; end else if (!rx_full) begin - usb_cmd <= CMD_READ; - end else begin - usb_cs <= 1'b1; - modem_status_counter <= modem_status_counter + 1'd1; - state <= STATE_IDLE; + next_state = STATE_SELECT; + next_cmd = CMD_READ; end end STATE_SELECT: begin - phase <= 4'b0001; - state <= STATE_COMMAND; + if (phase[3]) begin + next_state = STATE_COMMAND; + end 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; + if (phase[3]) begin + next_state = STATE_STATUS; end end 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; + if (phase[3]) begin + if (ft_miso) begin + next_state = STATE_DESELECT; + end else begin + next_state = STATE_DATA; + end end end STATE_DATA: begin - if (phase[0]) begin - usb_clk <= 1'b1; - usb_miosi_oe <= (usb_cmd == CMD_WRITE) || (usb_cmd == CMD_WRITE_MODEM_STATUS); - end else if (phase[2]) begin - usb_clk <= 1'b0; - end else if (phase[3]) begin - if (usb_miso) begin - state <= STATE_DESELECT; - end else if (usb_cmd == CMD_WRITE) begin - tx_read <= 1'b1; + if (phase[3]) begin + if (ft_miso) begin + next_state = STATE_DESELECT; + end else if (cmd == CMD_WRITE) begin if (tx_almost_empty) begin - state <= STATE_DESELECT; + next_state = STATE_DESELECT; end - end else if (usb_cmd == CMD_READ) begin - rx_write <= 1'b1; + end else if (cmd == CMD_READ) begin if (rx_almost_full) begin - state <= STATE_DESELECT; + next_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 else begin + next_state = STATE_DESELECT; end end 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; + next_state = STATE_IDLE; end end + + default: begin + next_state = STATE_IDLE; + end endcase end end diff --git a/sw/pc/sc64.py b/sw/pc/sc64.py index 6128e47..24384a2 100644 --- a/sw/pc/sc64.py +++ b/sw/pc/sc64.py @@ -157,9 +157,9 @@ class SC64: self.__usb.close() for p in ports: - if (p.vid == 0x0403 and p.pid == 0x6014 and p.serial_number.startswith("SC")): + if (p.vid == 0x0403 and p.pid == 0x6014 and p.serial_number.startswith("SC64")): try: - self.__usb = Serial(p.device, timeout=0.5, write_timeout=0.5) + self.__usb = Serial(p.device, timeout=1.0, write_timeout=1.0) self.reset_link() self.__probe_device() except (SerialException, SC64Exception):