This commit is contained in:
Polprzewodnikowy 2021-08-27 21:43:30 +02:00
parent 7fa3302299
commit b297bd3f25
21 changed files with 618 additions and 399 deletions

View File

@ -298,7 +298,6 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
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_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
# end DESIGN_PARTITION(Top)
# -------------------------
@ -322,4 +321,6 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
# ========================
# end ENTITY(intel_gpio_ddro)
# ---------------------------
# ---------------------------
set_global_assignment -name SLD_FILE db/signaltap_auto_stripped.stp
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

View File

@ -17,8 +17,8 @@ FLAGS=\
all: controller.bin print_size
controller.elf: prv32_rwx.ld main.c rtc.c startup.S
@$(CROSS)gcc $(FLAGS) main.c rtc.c startup.S -o controller.elf
controller.elf: prv32_rwx.ld main.c init.c process.c
@$(CROSS)gcc $(FLAGS) main.c init.c process.c -o controller.elf
controller.bin: controller.elf
@$(CROSS)objcopy -O binary controller.elf tmp.bin

17
fw/cpu/controller/init.c Normal file
View File

@ -0,0 +1,17 @@
#include "sys.h"
void init (void) {
DMA->SCR = DMA_SCR_STOP;
USB->SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_TX;
GPIO->ODR = 0;
GPIO->OER = (1 << 0);
CFG->SCR = CFG_SCR_SDRAM_SWITCH;
CFG->DD_OFFSET = 0x3BE0000;
CFG->SAVE_OFFSET = 0x3FE0000;
while (!(UART->SCR & UART_SCR_TXE));
UART->DR = '$';
}

8
fw/cpu/controller/init.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef INIT_H__
#define INIT_H__
void init (void);
#endif

View File

@ -1,227 +1,9 @@
#include "sys.h"
#include "rtc.h"
#include "init.h"
#include "process.h"
volatile int counter = 0;
void print (const char *text) {
while (*text != '\0') {
while (!(UART_SCR & UART_SCR_TXE));
UART_DR = *text++;
}
__attribute__((naked)) void main (void) {
__asm__("la sp, __stack_pointer");
init();
process();
}
const char hex_char_map[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
void print_02hex (unsigned char number) {
char buffer[3];
buffer[0] = hex_char_map[number >> 4];
buffer[1] = hex_char_map[number & 0x0F];
buffer[2] = '\0';
print(buffer);
}
const char *weekday_names[7] = {
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
};
void print_nice_date(uint8_t *date) {
print_02hex(date[4]);
print(".");
print_02hex(date[5]);
print(".20");
print_02hex(date[6]);
print(" (");
print(weekday_names[date[3] - 1]);
print(") ");
print_02hex(date[2]);
print(":");
print_02hex(date[1]);
print(":");
print_02hex(date[0]);
}
const char CMD[3] = {'C', 'M', 'D'};
const char CMD_R = 'R';
const char CMD_W = 'W';
const char CMP[3] = {'C', 'M', 'P'};
__NAKED__ int main (void) {
uint8_t data;
uint8_t cmd = '-';
uint32_t arg1, arg2;
char tmp[2];
tmp[1] = 0;
GPIO_OE = (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;
USB_SCR = USB_SCR_FLUSH_TX | USB_SCR_FLUSH_TX;
print("CPU START\r\n");
while (1) {
arg1 = 0;
arg2 = 0;
if (USB_SCR & USB_SCR_RXNE) {
for (int i = 0; i < 4; i++) {
while (!(USB_SCR & USB_SCR_RXNE));
data = USB_DR;
if (i < 3 && data != CMD[i]) {
i = 0;
print("Wrong data ");
print_02hex(data);
print("\r\n");
} else {
cmd = data;
}
}
print("Received CMD");
tmp[0] = cmd;
print(tmp);
print("\r\n");
for (int i = 0; i < 4; i++) {
while (!(USB_SCR & USB_SCR_RXNE));
arg1 = (arg1 << 8) | USB_DR;
}
print("Received ARG_1 0x");
for (int i = 0; i < 4; i++) {
print_02hex((uint8_t) (arg1 >> ((3 - i) * 8)));
}
print("\r\n");
for (int i = 0; i < 4; i++) {
while (!(USB_SCR & USB_SCR_RXNE));
arg2 = (arg2 << 8) | USB_DR;
}
print("Received ARG_2 0x");
for (int i = 0; i < 4; i++) {
print_02hex((uint8_t) (arg2 >> ((3 - i) * 8)));
}
print("\r\n");
DMA_MADDR = arg1;
DMA_ID_LEN = arg2;
DMA_SCR = (cmd == CMD_W ? DMA_SCR_DIR : 0) | DMA_SCR_START;
print("Started DMA\r\n");
while (DMA_SCR & DMA_SCR_BUSY);
print("Finished DMA\r\n");
for (int i = 0; i < 4; i++) {
while (!(USB_SCR & USB_SCR_TXE));
if (i < 3) {
USB_DR = CMP[i];
} else {
USB_DR = cmd;
}
}
print("Sent response CMP");
tmp[0] = cmd;
print(tmp);
print("\r\n\r\n");
} else if (CFG_SCR & CFG_SCR_CPU_BUSY) {
uint8_t cmd = CFG_COMMAND;
arg1 = CFG_ARG_1;
arg2 = CFG_ARG_2;
print("Received N64 CMD");
tmp[0] = cmd;
print(tmp);
print("\r\n");
if (cmd == 'S') {
if (arg1) {
CFG_SCR |= CFG_SCR_SDRAM_SWITCH;
} else {
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;
}
}
}
// __NAKED__ int main (void) {
// uint8_t rtc_data[7];
// uint8_t rtc_new_data[7];
// int index = 0;
// GPIO_OE = (1 << 0);
// GPIO_O = (1 << 0);
// rtc_init();
// while (!(USB_SR & USB_SR_TXE));
// USB_DR = 0x55;
// USB_DR = 0xAA;
// USB_DR = 0x00;
// USB_DR = 'D';
// USB_DR = 'E';
// USB_DR = 'A';
// USB_DR = 'D';
// USB_DR = 0xFF;
// USB_DR = 0xAA;
// USB_DR = 0x55;
// while (1) {
// GPIO_O = (1 << 0);
// print("\033[2J\033[H\r\n --- Hello --- \r\n\r\n");
// print(" RTC Data:\r\n\r\n ");
// rtc_get_time(rtc_data);
// print_nice_date(rtc_data);
// print("\r\n");
// GPIO_O = 0x00;
// while (counter++ < 0x0003FFFF);
// counter = 0;
// if (USB_SR & USB_SR_RXNE) {
// rtc_new_data[index++] = USB_DR;
// if (index == 7) {
// index = 0;
// rtc_set_time(rtc_new_data);
// }
// }
// }
// }

267
fw/cpu/controller/process.c Normal file
View File

@ -0,0 +1,267 @@
#include "sys.h"
#include "process.h"
static const uint8_t cmd_token[3] = { 'C', 'M', 'D' };
static const uint8_t cmp_token[3] = { 'C', 'M', 'P' };
static const uint8_t err_token[3] = { 'E', 'R', 'R' };
static uint8_t save_type = 0;
static uint16_t cic_type = 0xFFFF;
static uint8_t tv_type = 0xFF;
void process_usb (void);
void process_cfg (void);
void process_dd (void);
void process_si (void);
void process_uart (void);
void cfg_set_save_type (uint8_t type);
void cfg_update_config (uint32_t *args);
void process (void) {
while (1) {
process_usb();
process_cfg();
process_dd();
process_si();
process_uart();
}
}
void process_usb (void) {
static int state = 0;
static uint8_t current_byte = 0;
static uint8_t cmd;
static uint32_t args[2];
static uint8_t is_error;
static uint8_t dma_started;
uint8_t data;
switch (state) {
case 0: {
if (USB->SCR & USB_SCR_RXNE) {
data = USB->DR;
if (current_byte == 3) {
state = 1;
current_byte = 0;
cmd = data;
args[0] = 0;
args[1] = 0;
is_error = 0;
dma_started = 0;
break;
}
if (data != cmd_token[current_byte]) {
current_byte = 0;
break;
}
current_byte += 1;
}
break;
}
case 1: {
if (USB->SCR & USB_SCR_RXNE) {
data = USB->DR;
uint32_t *p = args + (current_byte >= 4 ? 1 : 0);
*p = (*p << 8) | data;
current_byte += 1;
if (current_byte == 8) {
state = 2;
current_byte = 0;
break;
}
}
break;
}
case 2: {
if (cmd == 'R' || cmd == 'W') {
if (!dma_started) {
if (!(DMA->SCR & DMA_SCR_BUSY)) {
DMA->MADDR = args[0];
DMA->ID_LEN = args[1];
DMA->SCR = (cmd == 'W' ? DMA_SCR_DIR : 0) | DMA_SCR_START;
dma_started = 1;
}
} else {
if (!(DMA->SCR & DMA_SCR_BUSY)) {
state = 3;
}
}
} else if (cmd == 'C') {
cfg_update_config(args);
state = 3;
} else {
state = 3;
is_error = 1;
}
break;
}
case 3: {
if (USB->SCR & USB_SCR_TXE) {
const uint8_t *p = is_error ? err_token : cmp_token;
USB->DR = (current_byte < 3) ? p[current_byte] : cmd;
current_byte += 1;
if (current_byte == 4) {
state = 0;
current_byte = 0;
}
}
break;
}
default: {
state = 0;
break;
}
}
}
void process_cfg (void) {
static uint8_t state = 0;
static uint8_t cmd;
static uint32_t args[3];
switch (state) {
case 0: {
if (CFG->SCR & CFG_SCR_CPU_BUSY) {
state = 1;
cmd = CFG->CMD;
args[0] = CFG->DATA[0];
args[1] = CFG->DATA[1];
}
break;
}
case 1: {
if (cmd == 'C') {
cfg_update_config(args);
CFG->DATA[0] = (save_type << 8) | (CFG->SCR & 0x07);
CFG->DATA[1] = (tv_type << 16) | cic_type;
state = 2;
} else {
CFG->DATA[0] = 0xFFFFFFFF;
CFG->DATA[1] = 0xFFFFFFFF;
state = 2;
}
break;
}
case 2: {
CFG->SCR &= ~(CFG_SCR_CPU_BUSY);
state = 0;
break;
}
default: {
state = 0;
break;
}
}
}
void process_dd (void) {
}
void process_si (void) {
}
void process_uart (void) {
if (UART->SCR & UART_SCR_RXNE) {
uint8_t data = UART->DR;
if (data == '/') {
while (!(UART->SCR & UART_SCR_TXE));
UART->DR = '>';
void (*bootloader) (void) = (void *) &BOOTLOADER;
bootloader();
}
}
}
void cfg_set_save_type (uint8_t type) {
CFG->SCR &= ~(CFG_SCR_FLASHRAM_EN | CFG_SCR_SRAM_EN);
switch (type) {
case 0: {
break;
}
case 1: {
CFG->SAVE_OFFSET = SDRAM_SIZE - 512;
break;
}
case 2: {
CFG->SAVE_OFFSET = SDRAM_SIZE - 2048;
break;
}
case 3: {
CFG->SAVE_OFFSET = SDRAM_SIZE - (32 * 1024);
CFG->SCR |= CFG_SCR_SRAM_EN;
break;
}
case 4: {
CFG->SAVE_OFFSET = SDRAM_SIZE - (256 * 1024);
CFG->SCR |= CFG_SCR_FLASHRAM_EN;
break;
}
case 5: {
CFG->SAVE_OFFSET = SDRAM_SIZE - (3 * 32 * 1024);
CFG->SCR |= CFG_SCR_SRAM_EN;
break;
}
case 6: {
CFG->SAVE_OFFSET = 0x01618000;
CFG->SCR |= CFG_SCR_FLASHRAM_EN;
break;
}
default: {
return;
}
}
save_type = type;
}
void cfg_update_config (uint32_t *args) {
switch (args[0]) {
case 0: {
if (args[1]) {
CFG->SCR |= CFG_SCR_SDRAM_SWITCH;
} else {
CFG->SCR &= ~CFG_SCR_SDRAM_SWITCH;
}
break;
}
case 1: {
if (args[1]) {
CFG->SCR |= CFG_SCR_SDRAM_WRITABLE;
} else {
CFG->SCR &= ~CFG_SCR_SDRAM_WRITABLE;
}
break;
}
case 2: {
if (args[1]) {
CFG->SCR |= CFG_SCR_DD_EN;
} else {
CFG->SCR &= ~CFG_SCR_DD_EN;
}
break;
}
case 3: {
cfg_set_save_type(args[1] & 0xFF);
break;
}
case 4: {
cic_type = args[1] & 0xFFFF;
break;
}
case 5: {
tv_type = args[1] & 0xFF;
break;
}
}
}

View File

@ -0,0 +1,8 @@
#ifndef PROCESS_H__
#define PROCESS_H__
void process (void);
#endif

View File

@ -6,14 +6,14 @@ MEMORY
__ram_size = LENGTH(ram);
__stack_pointer = ORIGIN(ram) + LENGTH(ram) - 16;
ENTRY(reset_handler)
ENTRY(main)
SECTIONS
{
.ram :
{
. = ALIGN(4);
*(.text.startup);
*(.text.main);
. = ALIGN(4);
*(.text .text* .rodata .rodata* .srodata .srodata*);
. = ALIGN(4);

View File

@ -1,5 +0,0 @@
.section .text.startup
.global reset_handler
reset_handler:
la sp, __stack_pointer
j main

View File

@ -6,25 +6,36 @@
#include <stdint.h>
#define __NAKED__ __attribute__((naked))
typedef volatile uint8_t * io8_t;
typedef volatile uint32_t * io32_t;
#define RAM (*((io32_t) 0x00000000))
typedef volatile uint8_t io8_t;
typedef volatile uint32_t io32_t;
#define BOOTLOADER (*((io32_t) 0x10000000))
#define RAM_BASE (0x00000000)
#define RAM (*((io32_t *) RAM_BASE))
#define GPIO (*((io32_t) 0x20000000))
#define GPIO_O (*((io8_t) 0x20000000))
#define GPIO_I (*((io8_t) 0x20000001))
#define GPIO_OE (*((io8_t) 0x20000002))
#define BOOTLOADER_BASE (0x10000000)
#define BOOTLOADER (*((io32_t *) BOOTLOADER_BASE))
#define I2C_SCR (*((io8_t) 0x30000000))
#define I2C_DR (*((io8_t) 0x30000004))
typedef volatile struct gpio_regs {
io8_t ODR;
io8_t IDR;
io8_t OER;
io8_t __padding;
} gpio_regs_t;
#define GPIO_BASE (0x20000000)
#define GPIO ((gpio_regs_t *) GPIO_BASE)
typedef volatile struct i2c_regs {
io32_t SCR;
io32_t DR;
} i2c_regs_t;
#define I2C_BASE (0x30000000)
#define I2C ((i2c_regs_t *) I2C_BASE)
#define I2C_SCR_START (1 << 0)
#define I2C_SCR_STOP (1 << 1)
@ -34,8 +45,14 @@ typedef volatile uint32_t * io32_t;
#define I2C_ADDR_READ (1 << 0)
#define USB_SCR (*((io8_t) 0x40000000))
#define USB_DR (*((io8_t) 0x40000004))
typedef volatile struct usb_regs {
io32_t SCR;
io8_t DR;
io8_t __padding[3];
} usb_regs_t;
#define USB_BASE (0x40000000)
#define USB ((usb_regs_t *) USB_BASE)
#define USB_SCR_RXNE (1 << 0)
#define USB_SCR_TXE (1 << 1)
@ -43,16 +60,27 @@ typedef volatile uint32_t * io32_t;
#define USB_SCR_FLUSH_TX (1 << 3)
#define UART_SCR (*((io8_t) 0x50000000))
#define UART_DR (*((io8_t) 0x50000004))
typedef volatile struct uart_regs {
io32_t SCR;
io8_t DR;
io8_t __padding[3];
} uart_regs_t;
#define UART_BASE (0x50000000)
#define UART ((uart_regs_t *) UART_BASE)
#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))
typedef volatile struct dma_regs {
io32_t SCR;
io32_t MADDR;
io32_t ID_LEN;
} dma_regs_t;
#define DMA_BASE (0x60000000)
#define DMA ((dma_regs_t *) DMA_BASE)
#define DMA_SCR_START (1 << 0)
#define DMA_SCR_STOP (1 << 1)
@ -60,16 +88,17 @@ typedef volatile uint32_t * io32_t;
#define DMA_SCR_BUSY (1 << 3)
#define SDRAM (*((io32_t) 0x68000000))
typedef volatile struct cfg_regs {
io32_t SCR;
io32_t DD_OFFSET;
io32_t SAVE_OFFSET;
io8_t CMD;
io8_t __padding[3];
io32_t DATA[3];
} cfg_regs_t;
#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_BASE (0x70000000)
#define CFG ((cfg_regs_t *) CFG_BASE)
#define CFG_SCR_SDRAM_SWITCH (1 << 0)
#define CFG_SCR_SDRAM_WRITABLE (1 << 1)
@ -77,7 +106,12 @@ typedef volatile uint32_t * io32_t;
#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)
#define CFG_SCR_CPU_READY (1 << 31)
#define SDRAM_BASE (0x80000000)
#define SDRAM (*((io32_t *) SDRAM_BASE)
#define SDRAM_SIZE (64 * 1024 * 1024)
#endif

View File

@ -9,14 +9,10 @@ module cpu_cfg (
R_DD_OFFSET,
R_SAVE_OFFSET,
R_COMMAND,
R_ARG_1,
R_ARG_2,
R_RESPONSE,
R_BOOTSTRAP
R_DATA_0,
R_DATA_1
} e_reg_id;
logic bootstrap_pending;
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
if (bus.request) begin
@ -29,10 +25,9 @@ module cpu_cfg (
if (bus.ack) begin
case (bus.address[4:2])
R_SCR: bus.rdata = {
cfg.cpu_bootstrapped,
cfg.cpu_ready,
cfg.cpu_busy,
bootstrap_pending,
24'd0,
25'd0,
cfg.flashram_enabled,
cfg.sram_enabled,
cfg.dd_enabled,
@ -41,18 +36,26 @@ module cpu_cfg (
};
R_DD_OFFSET: bus.rdata = {6'd0, cfg.dd_offset};
R_SAVE_OFFSET: bus.rdata = {6'd0, cfg.save_offset};
R_COMMAND: bus.rdata = {24'd0, cfg.command};
R_ARG_1: bus.rdata = cfg.arg[0];
R_ARG_2: bus.rdata = cfg.arg[1];
R_RESPONSE: bus.rdata = cfg.response;
R_BOOTSTRAP: bus.rdata = cfg.arg[0];
R_COMMAND: bus.rdata = {24'd0, cfg.cmd};
R_DATA_0: bus.rdata = cfg.data[0];
R_DATA_1: bus.rdata = cfg.data[1];
default: bus.rdata = 32'd0;
endcase
end
end
always_comb begin
cfg.wdata = bus.wdata;
cfg.data_write = 2'b00;
if (bus.request && (&bus.wmask)) begin
cfg.data_write[0] = bus.address[4:2] == R_DATA_0;
cfg.data_write[1] = bus.address[4:2] == R_DATA_1;
end
end
always_ff @(posedge sys.clk) begin
if (sys.reset) begin
cfg.cpu_bootstrapped <= 1'b0;
cfg.cpu_ready <= 1'b0;
cfg.cpu_busy <= 1'b0;
cfg.sdram_switch <= 1'b0;
cfg.sdram_writable <= 1'b0;
@ -61,22 +64,20 @@ module cpu_cfg (
cfg.flashram_enabled <= 1'b0;
cfg.dd_offset <= 26'h3BE_0000;
cfg.save_offset <= 26'h3FE_0000;
bootstrap_pending <= 1'b0;
end else begin
if (sys.n64_soft_reset) begin
cfg.sdram_switch <= 1'b0;
cfg.sdram_writable <= 1'b0;
end
if (cfg.request) begin
if (cfg.cmd_request) begin
cfg.cpu_busy <= 1'b1;
end
if (cfg.boot_write) begin
bootstrap_pending <= 1'b1;
end
if (bus.request) begin
case (bus.address[4:2])
R_SCR: begin
if (bus.wmask[3]) begin
cfg.cpu_bootstrapped <= bus.wdata[31];
cfg.cpu_ready <= bus.wdata[31];
cfg.cpu_busy <= bus.wdata[30];
end
if (bus.wmask[0]) begin
{
@ -100,19 +101,6 @@ module cpu_cfg (
cfg.save_offset <= bus.wdata[25:0];
end
end
R_RESPONSE: begin
if (&bus.wmask) begin
cfg.cpu_busy <= 1'b0;
cfg.response <= bus.wdata;
end
end
R_BOOTSTRAP: begin
if (!(|bus.wmask)) begin
bootstrap_pending <= 1'b0;
end
end
endcase
end
end

View File

@ -101,6 +101,7 @@ module cpu_dma (
} e_state;
e_state state;
logic pending_stop;
logic direction;
logic [27:0] length;
logic [15:0] rdata_buffer;
@ -129,10 +130,17 @@ module cpu_dma (
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
@ -155,7 +163,7 @@ module cpu_dma (
end
S_FETCH: begin
if (length != 28'd0) begin
if (length != 28'd0 && !pending_stop) begin
if (direction) begin
if (!dma.rx_empty && !dma.rx_read) begin
dma.rx_read <= 1'b1;

View File

@ -4,6 +4,17 @@ module n64_cfg (
if_config.n64 cfg
);
typedef enum bit [3:0] {
R_SR,
R_COMMAND,
R_DATA_0_H,
R_DATA_0_L,
R_DATA_1_H,
R_DATA_1_L,
R_VERSION_H,
R_VERSION_L
} e_reg_id;
typedef enum bit [0:0] {
S_IDLE,
S_WAIT
@ -15,20 +26,14 @@ module n64_cfg (
bus.rdata = 16'd0;
if (bus.ack) begin
case (bus.address[4:1])
0: bus.rdata = {cfg.cpu_bootstrapped, cfg.cpu_busy, 14'd0};
// ...
3: bus.rdata = {8'd0, cfg.command};
4: bus.rdata = cfg.arg[0][31:16];
5: bus.rdata = cfg.arg[0][15:0];
6: bus.rdata = cfg.arg[1][31:16];
7: bus.rdata = cfg.arg[1][15:0];
8: bus.rdata = cfg.response[31:16];
9: bus.rdata = cfg.response[15:0];
10: bus.rdata = cfg.arg[0][31:16];
11: bus.rdata = cfg.arg[0][15:0];
// ...
14: bus.rdata = 16'h5343;
15: bus.rdata = 16'h7632;
R_SR: bus.rdata = {cfg.cpu_ready, cfg.cpu_busy, 14'd0};
R_COMMAND: bus.rdata = {8'd0, cfg.cmd};
R_DATA_0_H: bus.rdata = cfg.data[0][31:16];
R_DATA_0_L: bus.rdata = cfg.data[0][15:0];
R_DATA_1_H: bus.rdata = cfg.data[1][31:16];
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
@ -36,8 +41,10 @@ module n64_cfg (
always_ff @(posedge sys.clk) begin
bus.ack <= 1'b0;
cfg.request <= 1'b0;
cfg.boot_write <= 1'b0;
cfg.cmd_request <= 1'b0;
if (cfg.data_write[0]) cfg.data[0] <= cfg.wdata;
if (cfg.data_write[1]) cfg.data[1] <= cfg.wdata;
if (sys.reset) begin
state <= S_IDLE;
@ -49,21 +56,14 @@ module n64_cfg (
bus.ack <= 1'b1;
if (bus.write) begin
case (bus.address[4:1])
// ...
3: begin
cfg.command <= bus.wdata[7:0];
cfg.request <= 1'b1;
end
4: cfg.arg[0][31:16] <= bus.wdata;
5: cfg.arg[0][15:0] <= bus.wdata;
6: cfg.arg[1][31:16] <= bus.wdata;
7: cfg.arg[1][15:0] <= bus.wdata;
// ...
10: cfg.arg[0][31:16] <= bus.wdata;
11: begin
cfg.arg[0][15:0] <= bus.wdata;
cfg.boot_write <= 1'b1;
R_COMMAND: begin
cfg.cmd <= bus.wdata[7:0];
cfg.cmd_request <= 1'b1;
end
R_DATA_0_H: cfg.data[0][31:16] <= bus.wdata;
R_DATA_0_L: cfg.data[0][15:0] <= bus.wdata;
R_DATA_1_H: cfg.data[1][31:16] <= bus.wdata;
R_DATA_1_L: cfg.data[1][15:0] <= bus.wdata;
endcase
end
end

View File

@ -88,7 +88,7 @@ module n64_dummy (
always_comb begin
bus.rdata = 16'h0000;
if (bus.ack) begin
bus.rdata = !bus.address[1] ? 16'h0180 : 16'h0000;
bus.rdata = !bus.address[1] ? 16'h0040 : 16'h0000;
end
end

View File

@ -1,12 +1,12 @@
interface if_config ();
logic cpu_bootstrapped;
logic cpu_ready;
logic cpu_busy;
logic request;
logic [7:0] command;
logic [31:0] arg [0:1];
logic [31:0] response;
logic boot_write;
logic cmd_request;
logic [7:0] cmd;
logic [31:0] data [0:1];
logic [1:0] data_write;
logic [31:0] wdata;
logic sdram_switch;
logic sdram_writable;
logic dd_enabled;
@ -32,23 +32,23 @@ interface if_config ();
);
modport n64 (
input cpu_bootstrapped,
input cpu_ready,
input cpu_busy,
output request,
output command,
output arg,
input response,
output boot_write
output cmd_request,
output cmd,
output data,
input data_write,
input wdata
);
modport cpu (
output cpu_bootstrapped,
output cpu_ready,
output cpu_busy,
input request,
input command,
input arg,
output response,
input boot_write,
input cmd_request,
input cmd,
input data,
output data_write,
output wdata,
output sdram_switch,
output sdram_writable,
output dd_enabled,

40
fw/rtl/system/dd.sv Normal file
View File

@ -0,0 +1,40 @@
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

View File

@ -27,6 +27,8 @@ package sc64;
__ID_DMA_END
} e_dma_id;
parameter bit [31:0] SC64_VER = 32'h53437632;
parameter int CLOCK_FREQUENCY = 32'd100_000_000;
parameter int UART_BAUD_RATE = 32'd1_000_000;

View File

@ -1,6 +1,7 @@
#include "boot.h"
#include "crc32.h"
#include "n64_regs.h"
// #include "sc64.h"
static const struct crc32_to_cic_seed {
@ -140,10 +141,9 @@ 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_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]);
// sc64_print_debug((uint32_t) gpr_regs[CPU_REG_T3], (uint32_t) gpr_regs[CPU_REG_S3], (uint32_t) gpr_regs[CPU_REG_S4]);
// sc64_print_debug((uint32_t) gpr_regs[CPU_REG_S5], (uint32_t) gpr_regs[CPU_REG_S6], (uint32_t) gpr_regs[CPU_REG_S7]);
// sc64_print_debug((uint32_t) gpr_regs[CPU_REG_SP], (uint32_t) gpr_regs[CPU_REG_RA], 0);
__asm__ (
".set noat \n\t"

View File

@ -1,62 +1,21 @@
#include "sc64.h"
#include "boot/boot.h"
typedef struct sc64_cart_registers {
__IO reg_t SCR;
__IO reg_t COMMAND;
__IO reg_t ARG[2];
__IO reg_t RESPONSE;
__IO reg_t BOOTSTRAP;
__IO reg_t ___unused;
__IO reg_t VERSION;
} sc64_cfg_registers_t;
#define SC64_CFG_BASE (0x1FFF0000)
#define SC64_CFG ((__IO sc64_cfg_registers_t *) SC64_CFG_BASE)
#define SC64_CFG_SCR_CPU_BOOTSTRAPPED (1 << 31)
#define SC64_CFG_SCR_CPU_BUSY (1 << 30)
#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) {
OS_BOOT_CONFIG->tv_type = TV_NTSC;
uint32_t scr = 0;
while (!sc64_check_presence());
do {
scr = platform_pi_io_read(&SC64_CFG->SCR);
} while (!(scr & SC64_CFG_SCR_CPU_BOOTSTRAPPED));
sc64_wait_cpu_ready();
do {
scr = platform_pi_io_read(&SC64_CFG->SCR);
} while (scr & SC64_CFG_SCR_CPU_BUSY);
platform_pi_io_write(&SC64_CFG->ARG[0], 1);
platform_pi_io_write(&SC64_CFG->COMMAND, (uint32_t) CMD_SDRAM_SWITCH);
do {
scr = platform_pi_io_read(&SC64_CFG->SCR);
} while (scr & SC64_CFG_SCR_CPU_BUSY);
sc64_set_config(SC64_CONFIG_SDRAM_SWITCH, true);
cart_header_t *cart_header = boot_load_cart_header();
uint16_t cic_seed = boot_get_cic_seed(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);
// sc64_print_debug(cic_seed << 16 | (tv_type & 0x03), cart_header->pi_conf, cart_header->boot_addr);
boot(cart_header, cic_seed, tv_type);
}

60
sw/bootloader/src/sc64.c Normal file
View File

@ -0,0 +1,60 @@
#include "sc64.h"
typedef struct sc64_cart_registers {
__IO reg_t SR_CMD;
__IO reg_t DATA[2];
__IO reg_t VERSION;
} sc64_cfg_registers_t;
#define SC64_CFG_BASE (0x1FFF0000)
#define SC64_CFG ((__IO sc64_cfg_registers_t *) SC64_CFG_BASE)
bool sc64_check_presence(void) {
uint32_t version = platform_pi_io_read(&SC64_CFG->VERSION);
return (version == 0x53437632);
}
void sc64_wait_cpu_ready(void) {
uint32_t sr;
do {
sr = platform_pi_io_read(&SC64_CFG->SR_CMD);
} while (sr & SC64_CFG_SCR_CPU_READY);
}
void sc64_wait_cpu_busy(void) {
uint32_t sr;
do {
sr = platform_pi_io_read(&SC64_CFG->SR_CMD);
} while (sr & SC64_CFG_SCR_CPU_BUSY);
}
void sc64_perform_cmd(uint8_t cmd, uint32_t *args) {
for (int i = 0; i < 2; i++) {
platform_pi_io_write(&SC64_CFG->DATA[i], args[i]);
}
platform_pi_io_write(&SC64_CFG->SR_CMD, (uint32_t) cmd);
sc64_wait_cpu_busy();
for (int i = 0; i < 2; i++) {
args[i] = platform_pi_io_read(&SC64_CFG->DATA[i]);
}
}
void sc64_set_config(uint32_t type, uint32_t value) {
uint32_t args[2] = { type, value };
sc64_perform_cmd(SC64_CMD_CONFIG, args);
}
void sc64_get_config(sc64_config_t *config) {
uint32_t args[2] = { SC64_CONFIG_NOP, 0 };
sc64_perform_cmd(SC64_CMD_CONFIG, args);
config->___raw_data[0] = args[0];
config->___raw_data[1] = args[1];
}
void sc64_print_debug(uint32_t a1, uint32_t a2, uint32_t a3) {
// uint32_t args[3] = { a1, a2, a3 };
// sc64_perform_cmd(SC64_CMD_DEBUG, args);
}

50
sw/bootloader/src/sc64.h Normal file
View File

@ -0,0 +1,50 @@
#ifndef SC64_H__
#define SC64_H__
#include "platform.h"
#define SC64_CFG_SCR_CPU_READY (1 << 31)
#define SC64_CFG_SCR_CPU_BUSY (1 << 30)
#define SC64_CMD_CONFIG 'C'
#define SC64_CMD_DEBUG 'D'
#define SC64_CONFIG_SDRAM_SWITCH 0
#define SC64_CONFIG_SDRAM_WRITABLE 1
#define SC64_CONFIG_DD_ENABLE 2
#define SC64_CONFIG_SAVE_TYPE 3
#define SC64_CONFIG_CIC_TYPE 4
#define SC64_CONFIG_TV_TYPE 5
#define SC64_CONFIG_NOP 0xFFFFFFFF
typedef struct sc64_config {
union {
uint32_t ___raw_data[2];
struct {
uint8_t ___unused_1[2];
uint8_t save_type;
uint8_t ___unused_2: 1;
uint8_t dd_enable: 1;
uint8_t sdram_writable: 1;
uint8_t sdram_switch: 1;
uint8_t ___unused_3;
uint8_t tv_type;
uint16_t cic_type;
};
};
} sc64_config_t;
bool sc64_check_presence(void);
void sc64_wait_cpu_ready(void);
void sc64_wait_cpu_busy(void);
void sc64_perform_cmd(uint8_t cmd, uint32_t *args);
void sc64_set_config(uint32_t type, uint32_t value);
void sc64_get_config(sc64_config_t *config);
void sc64_print_debug(uint32_t a1, uint32_t a2, uint32_t a3);
#endif