This commit is contained in:
Polprzewodnikowy 2021-08-26 00:22:39 +02:00
parent d550d9c184
commit 1722b3cd3f
10 changed files with 399 additions and 116 deletions

View File

@ -19,7 +19,7 @@
# #
# Quartus Prime # Quartus Prime
# Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition # Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition
# Date created = 16:40:13 August 18, 2021 # Date created = 23:35:14 August 23, 2021
# #
# -------------------------------------------------------------------------- # # -------------------------------------------------------------------------- #
# #
@ -48,8 +48,8 @@ set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON set_global_assignment -name FLOW_ENABLE_POWER_ANALYZER ON
set_global_assignment -name QSYS_FILE rtl/intel/flash/intel_flash.qsys set_global_assignment -name QSYS_FILE rtl/intel/flash/intel_flash.qsys
set_global_assignment -name QSYS_FILE rtl/intel/snp/intel_snp.qsys set_global_assignment -name QSYS_FILE rtl/intel/snp/intel_snp.qsys
# set_global_assignment -name QIP_FILE rtl/intel/fifo/fifo8.qip
set_global_assignment -name QIP_FILE rtl/intel/fifo/intel_fifo_8.qip set_global_assignment -name QIP_FILE rtl/intel/fifo/intel_fifo_8.qip
set_global_assignment -name QIP_FILE rtl/intel/gpio/intel_gpio_ddro.qip
set_global_assignment -name QIP_FILE rtl/intel/pll/intel_pll.qip set_global_assignment -name QIP_FILE rtl/intel/pll/intel_pll.qip
set_global_assignment -name SDC_FILE SummerCart64.sdc set_global_assignment -name SDC_FILE SummerCart64.sdc
set_global_assignment -name SIGNALTAP_FILE stp.stp set_global_assignment -name SIGNALTAP_FILE stp.stp
@ -71,6 +71,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bootloader.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_bus.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_cfg.sv set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_cfg.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_pi.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_sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/n64/n64_soc.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/SummerCart64.sv
@ -302,6 +303,23 @@ set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
# end ENTITY(SummerCart64) # end ENTITY(SummerCart64)
# ------------------------ # ------------------------
set_global_assignment -name QIP_FILE rtl/intel/gpio/intel_gpio_ddro.qip
# ------------------------------
# start ENTITY(altera_gpio_lite)
# Project-Wide Assignments
# ========================
# end ENTITY(altera_gpio_lite)
# ----------------------------
# -----------------------------
# start ENTITY(intel_gpio_ddro)
# Project-Wide Assignments
# ========================
# end ENTITY(intel_gpio_ddro)
# ---------------------------
set_global_assignment -name SIGNALTAP_FILE output_files/signaltap.stp
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@ -67,6 +67,10 @@ __NAKED__ int main (void) {
GPIO_OE = (1 << 0); GPIO_OE = (1 << 0);
GPIO_O = 0; // (1 << 0); GPIO_O = 0; // (1 << 0);
CFG_SCR |= CFG_SCR_SRAM_EN | CFG_SCR_SDRAM_SWITCH | CFG_SCR_DD_EN;
CFG_DD_OFFSET = 0;//0x3BE0000;
CFG_SAVE_OFFSET = 0x3FE0000;
DMA_SCR = DMA_SCR_STOP; DMA_SCR = DMA_SCR_STOP;
USB_SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_TX; USB_SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_TX;
@ -156,6 +160,19 @@ __NAKED__ int main (void) {
CFG_SCR &= ~CFG_SCR_SDRAM_SWITCH; CFG_SCR &= ~CFG_SCR_SDRAM_SWITCH;
} }
} }
if (cmd == 'D') {
print_02hex(arg1 >> 24);
print_02hex(arg1 >> 16);
print_02hex(arg1 >> 8);
print_02hex(arg1 >> 0);
print(" ");
print_02hex(arg2 >> 24);
print_02hex(arg2 >> 16);
print_02hex(arg2 >> 8);
print_02hex(arg2 >> 0);
print("\r\n");
}
print("\r\n");
CFG_RESPONSE = 0; CFG_RESPONSE = 0;
} }
} }

View File

@ -14,7 +14,7 @@ static const uint8_t rtc_bit_mask[7] = {
static uint8_t i2c_is_busy (void) { static uint8_t i2c_is_busy (void) {
return (I2C_SR & I2C_SR_BUSY); return (I2C_SCR & I2C_SCR_BUSY);
} }
static void i2c_wait_busy (void) { static void i2c_wait_busy (void) {
@ -22,22 +22,22 @@ static void i2c_wait_busy (void) {
} }
static uint8_t i2c_has_ack (void) { static uint8_t i2c_has_ack (void) {
return (I2C_SR & I2C_SR_ACK); return (I2C_SCR & I2C_SCR_ACK);
} }
static void i2c_start (void) { static void i2c_start (void) {
i2c_wait_busy(); i2c_wait_busy();
I2C_SR = I2C_SR_START; I2C_SCR = I2C_SCR_START;
} }
static void i2c_stop (void) { static void i2c_stop (void) {
i2c_wait_busy(); i2c_wait_busy();
I2C_SR = I2C_SR_STOP; I2C_SCR = I2C_SCR_STOP;
} }
static uint8_t i2c_write (uint8_t data) { static uint8_t i2c_write (uint8_t data) {
i2c_wait_busy(); i2c_wait_busy();
I2C_SR = 0; I2C_SCR = 0;
I2C_DR = data; I2C_DR = data;
i2c_wait_busy(); i2c_wait_busy();
return i2c_has_ack(); return i2c_has_ack();
@ -45,7 +45,7 @@ static uint8_t i2c_write (uint8_t data) {
static void i2c_read (uint8_t *data, uint8_t cfg) { static void i2c_read (uint8_t *data, uint8_t cfg) {
i2c_wait_busy(); i2c_wait_busy();
I2C_SR = cfg; I2C_SCR = cfg;
I2C_DR = 0xFF; I2C_DR = 0xFF;
i2c_wait_busy(); i2c_wait_busy();
*data = I2C_DR; *data = I2C_DR;
@ -74,7 +74,7 @@ static uint8_t i2c_rx (uint8_t address, uint8_t *data, size_t length) {
i2c_start(); i2c_start();
result |= i2c_write(RTC_ADDR | I2C_ADDR_READ); result |= i2c_write(RTC_ADDR | I2C_ADDR_READ);
for (size_t i = 0; i < length; i++) { for (size_t i = 0; i < length; i++) {
i2c_read(data++, (i == (length - 1)) ? 0 : I2C_SR_MACK); i2c_read(data++, (i == (length - 1)) ? 0 : I2C_SCR_MACK);
} }
i2c_stop(); i2c_stop();

View File

@ -6,60 +6,78 @@
#include <stdint.h> #include <stdint.h>
#define __NAKED__ __attribute__((naked)) #define __NAKED__ __attribute__((naked))
typedef volatile uint8_t * io8_t; typedef volatile uint8_t * io8_t;
typedef volatile uint32_t * io32_t; typedef volatile uint32_t * io32_t;
#define RAM (*((io32_t) 0x00000000)) #define RAM (*((io32_t) 0x00000000))
#define BOOTLOADER (*((io32_t) 0x10000000))
#define GPIO (*((io32_t) 0x20000000))
#define GPIO_O (*((io8_t) 0x20000000))
#define GPIO_I (*((io8_t) 0x20000001))
#define GPIO_OE (*((io8_t) 0x20000002))
#define I2C_SR (*((io8_t) 0x30000000))
#define I2C_DR (*((io8_t) 0x30000004))
#define USB_SCR (*((io8_t) 0x40000000))
#define USB_DR (*((io8_t) 0x40000004))
#define UART_SCR (*((io8_t) 0x50000000))
#define UART_DR (*((io8_t) 0x50000004))
#define DMA_SCR (*((io8_t) 0x60000000))
#define DMA_MADDR (*((io32_t) 0x60000004))
#define DMA_ID_LEN (*((io32_t) 0x60000008))
#define SDRAM (*((io32_t) 0x68000000))
#define CFG_SCR (*((io32_t) 0x70000000))
#define CFG_DD_OFFSET (*((io32_t) 0x70000004))
#define CFG_SAVE_OFFSET (*((io32_t) 0x70000008))
#define CFG_COMMAND (*((io8_t) 0x7000000C))
#define CFG_ARG_1 (*((io32_t) 0x70000010))
#define CFG_ARG_2 (*((io32_t) 0x70000014))
#define CFG_RESPONSE (*((io32_t) 0x70000018))
#define I2C_SR_START (1 << 0)
#define I2C_SR_STOP (1 << 1)
#define I2C_SR_MACK (1 << 2)
#define I2C_SR_ACK (1 << 3)
#define I2C_SR_BUSY (1 << 4)
#define I2C_ADDR_READ (1 << 0)
#define USB_SCR_RXNE (1 << 0) #define BOOTLOADER (*((io32_t) 0x10000000))
#define USB_SCR_TXE (1 << 1)
#define USB_SCR_FLUSH_RX (1 << 2)
#define USB_SCR_FLUSH_TX (1 << 3)
#define UART_SCR_RXNE (1 << 0)
#define UART_SCR_TXE (1 << 1)
#define DMA_SCR_START (1 << 0) #define GPIO (*((io32_t) 0x20000000))
#define DMA_SCR_STOP (1 << 1) #define GPIO_O (*((io8_t) 0x20000000))
#define DMA_SCR_DIR (1 << 2) #define GPIO_I (*((io8_t) 0x20000001))
#define DMA_SCR_BUSY (1 << 3) #define GPIO_OE (*((io8_t) 0x20000002))
#define DMA_ID_USB (0)
#define DMA_ID_SD (1)
#define CFG_SCR_CPU_BUSY (1 << 30) #define I2C_SCR (*((io8_t) 0x30000000))
#define CFG_SCR_SDRAM_SWITCH (1 << 0) #define I2C_DR (*((io8_t) 0x30000004))
#define I2C_SCR_START (1 << 0)
#define I2C_SCR_STOP (1 << 1)
#define I2C_SCR_MACK (1 << 2)
#define I2C_SCR_ACK (1 << 3)
#define I2C_SCR_BUSY (1 << 4)
#define I2C_ADDR_READ (1 << 0)
#define USB_SCR (*((io8_t) 0x40000000))
#define USB_DR (*((io8_t) 0x40000004))
#define USB_SCR_RXNE (1 << 0)
#define USB_SCR_TXE (1 << 1)
#define USB_SCR_FLUSH_RX (1 << 2)
#define USB_SCR_FLUSH_TX (1 << 3)
#define UART_SCR (*((io8_t) 0x50000000))
#define UART_DR (*((io8_t) 0x50000004))
#define UART_SCR_RXNE (1 << 0)
#define UART_SCR_TXE (1 << 1)
#define DMA_SCR (*((io8_t) 0x60000000))
#define DMA_MADDR (*((io32_t) 0x60000004))
#define DMA_ID_LEN (*((io32_t) 0x60000008))
#define DMA_SCR_START (1 << 0)
#define DMA_SCR_STOP (1 << 1)
#define DMA_SCR_DIR (1 << 2)
#define DMA_SCR_BUSY (1 << 3)
#define SDRAM (*((io32_t) 0x68000000))
#define CFG_SCR (*((io32_t) 0x70000000))
#define CFG_DD_OFFSET (*((io32_t) 0x70000004))
#define CFG_SAVE_OFFSET (*((io32_t) 0x70000008))
#define CFG_COMMAND (*((io8_t) 0x7000000C))
#define CFG_ARG_1 (*((io32_t) 0x70000010))
#define CFG_ARG_2 (*((io32_t) 0x70000014))
#define CFG_RESPONSE (*((io32_t) 0x70000018))
#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_FLASHRAM_EN (1 << 4)
#define CFG_SCR_CPU_BUSY (1 << 30)
#define CFG_SCR_CPU_RUNNING (1 << 31)
#endif #endif

View File

@ -42,6 +42,7 @@ module n64_cfg (
S_IDLE: begin S_IDLE: begin
if (bus.request) begin if (bus.request) begin
state <= S_WAIT; state <= S_WAIT;
bus.ack <= 1'b1;
if (bus.write) begin if (bus.write) begin
case (bus.address[4:1]) case (bus.address[4:1])
// ... // ...
@ -65,7 +66,6 @@ module n64_cfg (
end end
S_WAIT: begin S_WAIT: begin
bus.ack <= 1'b1;
state <= S_IDLE; state <= S_IDLE;
end end
endcase endcase

View File

@ -10,6 +10,57 @@ module n64_pi (
inout [15:0] n64_pi_ad inout [15:0] n64_pi_ad
); );
// FIFOs
logic read_fifo_flush;
logic read_fifo_full;
logic read_fifo_write;
logic [15:0] read_fifo_wdata;
logic read_fifo_empty;
logic read_fifo_read;
logic [15:0] read_fifo_rdata;
n64_pi_fifo read_fifo_inst (
.sys(sys),
.flush(read_fifo_flush),
.full(read_fifo_full),
.write(read_fifo_write),
.wdata(read_fifo_wdata),
.empty(read_fifo_empty),
.read(read_fifo_read),
.rdata(read_fifo_rdata)
);
logic write_fifo_flush;
logic write_fifo_full;
logic write_fifo_write;
logic [15:0] write_fifo_wdata;
logic write_fifo_empty;
logic write_fifo_read;
logic [15:0] write_fifo_rdata;
n64_pi_fifo write_fifo_inst (
.sys(sys),
.flush(write_fifo_flush),
.full(write_fifo_full),
.write(write_fifo_write),
.wdata(write_fifo_wdata),
.empty(write_fifo_empty),
.read(write_fifo_read),
.rdata(write_fifo_rdata)
);
// Control signals input synchronization // Control signals input synchronization
logic [2:0] n64_pi_alel_ff; logic [2:0] n64_pi_alel_ff;
@ -28,7 +79,6 @@ module n64_pi (
logic pi_aleh; logic pi_aleh;
logic pi_alel; logic pi_alel;
logic pi_read; logic pi_read;
logic pi_read_delayed;
logic pi_write; logic pi_write;
always_comb begin always_comb begin
@ -36,10 +86,10 @@ module n64_pi (
pi_aleh = n64_pi_aleh_ff[2]; pi_aleh = n64_pi_aleh_ff[2];
pi_alel = n64_pi_alel_ff[2]; pi_alel = n64_pi_alel_ff[2];
pi_read = n64_pi_read_ff[1]; pi_read = n64_pi_read_ff[1];
pi_read_delayed = n64_pi_read_ff[2];
pi_write = n64_pi_write_ff[2]; pi_write = n64_pi_write_ff[2];
end end
// PI bus state and event generator // PI bus state and event generator
typedef enum bit [1:0] { typedef enum bit [1:0] {
@ -68,20 +118,22 @@ module n64_pi (
logic alel_op; logic alel_op;
logic read_op; logic read_op;
logic write_op; logic write_op;
logic end_op;
always_comb begin always_comb begin
aleh_op = !pi_reset && last_pi_mode != PI_MODE_HIGH && pi_mode == PI_MODE_HIGH; aleh_op = !pi_reset && last_pi_mode != PI_MODE_HIGH && pi_mode == PI_MODE_HIGH;
alel_op = !pi_reset && last_pi_mode == PI_MODE_HIGH && pi_mode == PI_MODE_LOW; alel_op = !pi_reset && last_pi_mode == PI_MODE_HIGH && pi_mode == PI_MODE_LOW;
read_op = !pi_reset && pi_mode == PI_MODE_VALID && last_read && !pi_read; read_op = !pi_reset && pi_mode == PI_MODE_VALID && last_read && !pi_read;
write_op = !pi_reset && pi_mode == PI_MODE_VALID && last_write && !pi_write; write_op = !pi_reset && pi_mode == PI_MODE_VALID && last_write && !pi_write;
end_op = !pi_reset && last_pi_mode == PI_MODE_VALID && pi_mode != PI_MODE_VALID;
end end
// Input and output data sampling // Input and output data sampling
logic [15:0] n64_pi_ad_input; logic [15:0] n64_pi_ad_input;
logic [15:0] n64_pi_ad_output; logic [15:0] n64_pi_ad_output;
logic [15:0] n64_pi_ad_output_data; logic [15:0] n64_pi_ad_output_data;
logic [15:0] n64_pi_ad_output_data_buffer;
logic n64_pi_ad_output_enable; logic n64_pi_ad_output_enable;
logic n64_pi_ad_output_enable_data; logic n64_pi_ad_output_enable_data;
@ -91,38 +143,65 @@ module n64_pi (
always_comb begin always_comb begin
n64_pi_ad = n64_pi_ad_output_enable ? n64_pi_ad_output : 16'hZZZZ; n64_pi_ad = n64_pi_ad_output_enable ? n64_pi_ad_output : 16'hZZZZ;
n64_pi_ad_output_enable_data = !pi_reset && pi_mode == PI_MODE_VALID && n64_pi_address_valid && !pi_read_delayed; n64_pi_ad_output_enable_data = !pi_reset && pi_mode == PI_MODE_VALID && n64_pi_address_valid && !n64_pi_read_ff[2];
end end
always_ff @(posedge sys.clk) begin always_ff @(posedge sys.clk) begin
n64_pi_ad_input <= n64_pi_ad; n64_pi_ad_input <= n64_pi_ad;
n64_pi_ad_output <= n64_pi_ad_output_data; n64_pi_ad_output <= n64_pi_ad_output_data;
n64_pi_ad_output_enable <= n64_pi_ad_output_enable_data; n64_pi_ad_output_enable <= n64_pi_ad_output_enable_data;
if (read_op) begin end
n64_pi_ad_output_data <= n64_pi_ad_output_data_buffer;
end logic wait_for_read_fifo;
if (pending_operation && bus.ack) begin logic wait_for_write_fifo;
n64_pi_ad_output_data <= bus.rdata;
always_comb begin
read_fifo_write = bus.ack && !bus.write;
read_fifo_wdata = bus.rdata;
write_fifo_wdata = n64_pi_ad_input;
end
always_ff @(posedge sys.clk) begin
read_fifo_read <= 1'b0;
write_fifo_write <= 1'b0;
if (sys.reset || sys.n64_hard_reset) begin
wait_for_read_fifo <= 1'b0;
wait_for_write_fifo <= 1'b0;
end else begin
if (read_op || wait_for_read_fifo) begin
if (read_fifo_empty) begin
wait_for_read_fifo <= 1'b1;
end else begin
n64_pi_ad_output_data <= read_fifo_rdata;
read_fifo_read <= 1'b1;
wait_for_read_fifo <= 1'b0;
end
end
if (write_op || wait_for_write_fifo) begin
if (write_fifo_full) begin
wait_for_write_fifo <= 1'b1;
end else begin
write_fifo_write <= 1'b1;
wait_for_write_fifo <= 1'b0;
end
end
end end
end end
// Internal bus controller
typedef enum bit [0:0] { // Address decoding
S_IDLE,
S_WAIT
} e_state;
e_state state;
logic first_operation;
sc64::e_n64_id next_id; sc64::e_n64_id next_id;
logic [25:0] next_offset; logic [31:0] next_offset;
logic sram_selected;
always_ff @(posedge sys.clk) begin always_ff @(posedge sys.clk) begin
if (aleh_op) begin if (aleh_op) begin
n64_pi_address_valid <= 1'b0; n64_pi_address_valid <= 1'b0;
next_offset <= 32'd0; next_offset <= 32'd0;
sram_selected <= 1'b0;
if (cfg.dd_enabled) begin if (cfg.dd_enabled) begin
if (n64_pi_ad_input == 16'h0500) begin if (n64_pi_ad_input == 16'h0500) begin
n64_pi_address_valid <= 1'b1; n64_pi_address_valid <= 1'b1;
@ -131,20 +210,20 @@ module n64_pi (
if (n64_pi_ad_input >= 16'h0600 && n64_pi_ad_input < 16'h0640) begin if (n64_pi_ad_input >= 16'h0600 && n64_pi_ad_input < 16'h0640) begin
n64_pi_address_valid <= 1'b1; n64_pi_address_valid <= 1'b1;
next_id <= sc64::ID_N64_SDRAM; next_id <= sc64::ID_N64_SDRAM;
next_offset <= cfg.dd_offset; next_offset <= cfg.dd_offset + 32'h0A00_0000;
end end
end end
if (n64_pi_ad_input >= 16'h0800 && n64_pi_ad_input < 16'h0802) begin if (n64_pi_ad_input >= 16'h0800 && n64_pi_ad_input < 16'h0802) begin
if (cfg.sram_enabled) begin if (cfg.sram_enabled) begin
n64_pi_address_valid <= 1'b1; n64_pi_address_valid <= 1'b1;
next_id <= sc64::ID_N64_SDRAM; next_id <= sc64::ID_N64_SDRAM;
next_offset <= cfg.save_offset; next_offset <= cfg.save_offset + 32'h0800_0000;
sram_selected <= 1'b1;
end else if (cfg.flashram_enabled) begin end else if (cfg.flashram_enabled) begin
n64_pi_address_valid <= 1'b1; n64_pi_address_valid <= 1'b1;
next_id <= sc64::ID_N64_FLASHRAM; next_id <= sc64::ID_N64_FLASHRAM;
if (cfg.flashram_read_mode) begin if (cfg.flashram_read_mode) begin
next_id <= sc64::ID_N64_SDRAM; next_offset <= cfg.save_offset + 32'h0800_0000;
next_offset <= cfg.save_offset;
end end
end end
end end
@ -159,46 +238,81 @@ module n64_pi (
end end
end end
always_ff @(posedge sys.clk) begin
if (sys.reset || sys.n64_hard_reset || sys.n64_soft_reset) begin
state <= S_IDLE;
bus.request <= 1'b0;
pending_operation <= 1'b0;
end else begin
case (state)
S_IDLE: begin
if (aleh_op) begin
bus.address[31:16] <= n64_pi_ad_input;
end
if (alel_op) begin
bus.address <= {bus.address[31:16], n64_pi_ad_input[15:1], 1'b0} + next_offset;
end
if (n64_pi_address_valid && (alel_op || read_op || write_op || pending_operation)) begin
state <= S_WAIT;
bus.id <= next_id;
bus.request <= 1'b1;
bus.write <= write_op || (pending_operation && pending_write);
if (!alel_op && !(first_operation && write_op)) begin
bus.address[31:1] <= bus.address[31:1] + 1'd1;
end
bus.wdata <= n64_pi_ad_input;
first_operation <= alel_op;
pending_operation <= 1'b0;
end
end
S_WAIT: begin // Bus controller
if (bus.ack) begin
state <= S_IDLE; logic can_read;
bus.request <= 1'b0; logic first_write_op;
n64_pi_ad_output_data_buffer <= bus.rdata; logic load_starting_address;
sc64::e_n64_id starting_id;
logic [31:0] starting_address;
always_ff @(posedge sys.clk) begin
read_fifo_flush <= 1'b0;
write_fifo_read <= 1'b0;
if (sys.reset || sys.n64_hard_reset) begin
bus.request <= 1'b0;
read_fifo_flush <= 1'b1;
write_fifo_flush <= 1'b1;
end else begin
write_fifo_flush <= starting_id == sc64::ID_N64_SDRAM && !cfg.sdram_writable && !sram_selected;
if (aleh_op) begin
starting_address[31:16] <= n64_pi_ad_input;
end
if (alel_op) begin
read_fifo_flush <= 1'b1;
can_read <= 1'b1;
first_write_op <= 1'b1;
load_starting_address <= 1'b1;
starting_id <= next_id;
starting_address <= {starting_address[31:16], n64_pi_ad_input[15:1], 1'b0} + next_offset;
end
if (write_op) begin
can_read <= 1'b0;
if (first_write_op) begin
first_write_op <= 1'b0;
load_starting_address <= 1'b1;
end
end
if (!bus.request) begin
if (!write_fifo_empty) begin
bus.request <= 1'b1;
bus.write <= 1'b1;
if (load_starting_address) begin
bus.id <= starting_id;
bus.address <= starting_address;
load_starting_address <= 1'b0;
end end
if (read_op || write_op) begin bus.wdata <= write_fifo_rdata;
pending_operation <= 1'b1; write_fifo_read <= 1'b1;
pending_write <= write_op; end else if (!read_fifo_full && can_read) begin
bus.request <= 1'b1;
bus.write <= 1'b0;
if (load_starting_address) begin
bus.id <= starting_id;
if (starting_id == sc64::ID_N64_FLASHRAM && cfg.flashram_read_mode) begin
bus.id <= sc64::ID_N64_SDRAM;
end
bus.address <= starting_address;
load_starting_address <= 1'b0;
end end
end end
endcase end else begin
if (bus.ack) begin
bus.request <= 1'b0;
bus.address <= bus.address + 2'd2;
end
end
if (end_op) begin
can_read <= 1'b0;
end
end end
end end

43
fw/rtl/n64/n64_pi_fifo.sv Normal file
View File

@ -0,0 +1,43 @@
module n64_pi_fifo (
if_system.sys sys,
input flush,
output full,
input write,
input [15:0] wdata,
output empty,
input read,
output [15:0] rdata
);
logic [15:0] fifo_mem [0:3];
logic [2:0] fifo_wr_ptr;
logic [2:0] fifo_rd_ptr;
logic empty_or_full;
always_comb begin
rdata = fifo_mem[fifo_rd_ptr[1:0]];
empty_or_full = fifo_wr_ptr[1:0] == fifo_rd_ptr[1:0];
empty = empty_or_full && fifo_wr_ptr[2] == fifo_rd_ptr[2];
full = empty_or_full && fifo_wr_ptr[2] != fifo_rd_ptr[2];
end
always_ff @(posedge sys.clk) begin
if (sys.reset || flush) begin
fifo_wr_ptr <= 3'd0;
fifo_rd_ptr <= 3'd0;
end else begin
if (write) begin
fifo_mem[fifo_wr_ptr[1:0]] <= wdata;
fifo_wr_ptr <= fifo_wr_ptr + 1'd1;
end
if (read) begin
fifo_rd_ptr <= fifo_rd_ptr + 1'd1;
end
end
end
endmodule

View File

@ -54,6 +54,16 @@ module n64_soc (
.bus(bus.at[sc64::ID_N64_BOOTLOADER].device) .bus(bus.at[sc64::ID_N64_BOOTLOADER].device)
); );
n64_dummy n64_flashram_inst (
.sys(sys),
.bus(bus.at[sc64::ID_N64_FLASHRAM].device)
);
n64_dummy n64_ddregs_inst (
.sys(sys),
.bus(bus.at[sc64::ID_N64_DDREGS].device)
);
n64_cfg n64_cfg_inst ( n64_cfg n64_cfg_inst (
.sys(sys), .sys(sys),
.bus(bus.at[sc64::ID_N64_CFG].device), .bus(bus.at[sc64::ID_N64_CFG].device),
@ -61,3 +71,46 @@ module n64_soc (
); );
endmodule 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'h0180 : 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

View File

@ -33,7 +33,7 @@ cart_header_t *boot_load_cart_header(void) {
} }
uint16_t boot_get_cic_seed(cart_header_t *cart_header) { uint16_t boot_get_cic_seed(cart_header_t *cart_header) {
uint16_t cic_seed = crc32_to_cic_seed[3].cic_seed; uint16_t cic_seed = crc32_to_cic_seed[7].cic_seed;
uint32_t ipl3_crc32 = crc32_calculate(cart_header->boot_code, sizeof(cart_header->boot_code)); uint32_t ipl3_crc32 = crc32_calculate(cart_header->boot_code, sizeof(cart_header->boot_code));
for (size_t i = 0; i < ARRAY_ITEMS(crc32_to_cic_seed); i++) { for (size_t i = 0; i < ARRAY_ITEMS(crc32_to_cic_seed); i++) {
@ -140,6 +140,11 @@ void boot(cart_header_t *cart_header, uint16_t cic_seed, tv_type_t tv_type) {
gpr_regs[CPU_REG_SP] = CPU_ADDRESS_IN_REG(SP_MEM->imem[ARRAY_ITEMS(SP_MEM->imem) - 4]); gpr_regs[CPU_REG_SP] = CPU_ADDRESS_IN_REG(SP_MEM->imem[ARRAY_ITEMS(SP_MEM->imem) - 4]);
gpr_regs[CPU_REG_RA] = CPU_ADDRESS_IN_REG(SP_MEM->imem[(os_tv_type == TV_PAL) ? 341 : 340]); gpr_regs[CPU_REG_RA] = CPU_ADDRESS_IN_REG(SP_MEM->imem[(os_tv_type == TV_PAL) ? 341 : 340]);
print_debug((uint32_t) gpr_regs[CPU_REG_T3], (uint32_t) gpr_regs[CPU_REG_S3]);
print_debug((uint32_t) gpr_regs[CPU_REG_S4], (uint32_t) gpr_regs[CPU_REG_S5]);
print_debug((uint32_t) gpr_regs[CPU_REG_S6], (uint32_t) gpr_regs[CPU_REG_S7]);
print_debug((uint32_t) gpr_regs[CPU_REG_SP], (uint32_t) gpr_regs[CPU_REG_RA]);
__asm__ ( __asm__ (
".set noat \n\t" ".set noat \n\t"
".set noreorder \n\t" ".set noreorder \n\t"

View File

@ -16,6 +16,19 @@ typedef struct sc64_cart_registers {
#define SC64_CFG_SCR_CPU_BUSY (1 << 30) #define SC64_CFG_SCR_CPU_BUSY (1 << 30)
#define CMD_SDRAM_SWITCH 'S' #define CMD_SDRAM_SWITCH 'S'
#define CMD_DEBUG 'D'
void print_debug(uint32_t a1, uint32_t a2) {
uint32_t scr = 0;
do {
scr = platform_pi_io_read(&SC64_CFG->SCR);
} while (scr & SC64_CFG_SCR_CPU_BUSY);
platform_pi_io_write(&SC64_CFG->ARG[0], a1);
platform_pi_io_write(&SC64_CFG->ARG[1], a2);
platform_pi_io_write(&SC64_CFG->COMMAND, (uint32_t) CMD_DEBUG);
}
int main(void) { int main(void) {
OS_BOOT_CONFIG->tv_type = TV_NTSC; OS_BOOT_CONFIG->tv_type = TV_NTSC;
@ -41,5 +54,7 @@ int main(void) {
uint16_t cic_seed = boot_get_cic_seed(cart_header); uint16_t cic_seed = boot_get_cic_seed(cart_header);
tv_type_t tv_type = boot_get_tv_type(cart_header); tv_type_t tv_type = boot_get_tv_type(cart_header);
print_debug(cic_seed << 16 | (tv_type & 0x03), cart_header->pi_conf);
boot(cart_header, cic_seed, tv_type); boot(cart_header, cic_seed, tv_type);
} }