diff --git a/fw/project/lcmxo2/sc64.ldf b/fw/project/lcmxo2/sc64.ldf
index 7b10953..9bdab48 100644
--- a/fw/project/lcmxo2/sc64.ldf
+++ b/fw/project/lcmxo2/sc64.ldf
@@ -42,9 +42,6 @@
-
-
-
diff --git a/fw/rtl/n64/n64_cfg.sv b/fw/rtl/n64/n64_cfg.sv
index 3b13546..70dd91f 100644
--- a/fw/rtl/n64/n64_cfg.sv
+++ b/fw/rtl/n64/n64_cfg.sv
@@ -9,7 +9,7 @@ module n64_cfg (
output logic irq
);
- typedef enum bit [2:0] {
+ typedef enum bit [3:0] {
REG_STATUS,
REG_COMMAND,
REG_DATA_0_H,
@@ -17,61 +17,118 @@ module n64_cfg (
REG_DATA_1_H,
REG_DATA_1_L,
REG_VERSION_H,
- REG_VERSION_L
+ REG_VERSION_L,
+ REG_KEY_H,
+ REG_KEY_L
} e_reg;
logic cfg_error;
always_comb begin
reg_bus.rdata = 16'd0;
- if (reg_bus.address[16] && (reg_bus.address[15:4] == 12'd0)) begin
- case (reg_bus.address[3:1])
+ if (reg_bus.address[16] && (reg_bus.address[15:5] == 11'd0)) begin
+ case (reg_bus.address[4:1])
REG_STATUS: reg_bus.rdata = {
n64_scb.cfg_pending,
cfg_error,
14'd0
};
+ REG_COMMAND: reg_bus.rdata = {8'd0, n64_scb.cfg_cmd};
REG_DATA_0_H: reg_bus.rdata = n64_scb.cfg_wdata[0][31:16];
REG_DATA_0_L: reg_bus.rdata = n64_scb.cfg_wdata[0][15:0];
REG_DATA_1_H: reg_bus.rdata = n64_scb.cfg_wdata[1][31:16];
REG_DATA_1_L: reg_bus.rdata = n64_scb.cfg_wdata[1][15:0];
REG_VERSION_H: reg_bus.rdata = n64_scb.cfg_version[31:16];
REG_VERSION_L: reg_bus.rdata = n64_scb.cfg_version[15:0];
+ REG_KEY_H: reg_bus.rdata = 16'd0;
+ REG_KEY_L: reg_bus.rdata = 16'd0;
endcase
end
end
+ logic unlock_flag;
+ logic lock_sequence_counter;
+
always_ff @(posedge clk) begin
+ if (n64_scb.cfg_done) begin
+ n64_scb.cfg_pending <= 1'b0;
+ cfg_error <= n64_scb.cfg_error;
+ end
+
+ if (n64_scb.cfg_irq) begin
+ irq <= 1'b1;
+ end
+
+ if (unlock_flag) begin
+ n64_scb.cfg_unlock <= 1'b1;
+ end
+
if (reset || n64_scb.n64_reset) begin
n64_scb.cfg_pending <= 1'b0;
n64_scb.cfg_cmd <= 8'h00;
irq <= 1'b0;
cfg_error <= 1'b0;
- end else begin
- if (n64_scb.cfg_done) begin
- n64_scb.cfg_pending <= 1'b0;
- cfg_error <= n64_scb.cfg_error;
- end
-
- if (n64_scb.cfg_irq) begin
- irq <= 1'b1;
- end
-
- if (reg_bus.write) begin
- if (reg_bus.address[16] && (reg_bus.address[15:4] == 12'd0)) begin
- case (reg_bus.address[3:1])
- REG_COMMAND: begin
- n64_scb.cfg_pending <= 1'b1;
- n64_scb.cfg_cmd <= reg_bus.wdata[7:0];
- cfg_error <= 1'b0;
+ lock_sequence_counter <= 1'd0;
+ end else if (n64_scb.cfg_unlock) begin
+ if (reg_bus.write && reg_bus.address[16] && (reg_bus.address[15:5] == 11'd0)) begin
+ case (reg_bus.address[4:1])
+ REG_COMMAND: begin
+ n64_scb.cfg_pending <= 1'b1;
+ n64_scb.cfg_cmd <= reg_bus.wdata[7:0];
+ cfg_error <= 1'b0;
+ end
+ REG_DATA_0_H: n64_scb.cfg_rdata[0][31:16] <= reg_bus.wdata;
+ REG_DATA_0_L: n64_scb.cfg_rdata[0][15:0] <= reg_bus.wdata;
+ REG_DATA_1_H: n64_scb.cfg_rdata[1][31:16] <= reg_bus.wdata;
+ REG_DATA_1_L: n64_scb.cfg_rdata[1][15:0] <= reg_bus.wdata;
+ REG_VERSION_L: irq <= 1'b0;
+ REG_KEY_H, REG_KEY_L: begin
+ lock_sequence_counter <= lock_sequence_counter + 1'd1;
+ if (reg_bus.wdata != 16'hFFFF) begin
+ lock_sequence_counter <= 1'd0;
end
- REG_DATA_0_H: n64_scb.cfg_rdata[0][31:16] <= reg_bus.wdata;
- REG_DATA_0_L: n64_scb.cfg_rdata[0][15:0] <= reg_bus.wdata;
- REG_DATA_1_H: n64_scb.cfg_rdata[1][31:16] <= reg_bus.wdata;
- REG_DATA_1_L: n64_scb.cfg_rdata[1][15:0] <= reg_bus.wdata;
- REG_VERSION_L: irq <= 1'b0;
- endcase
- end
+ if (lock_sequence_counter == 1'd1) begin
+ n64_scb.cfg_unlock <= (reg_bus.wdata != 16'hFFFF);
+ end
+ end
+ endcase
+ end
+ end
+ end
+
+ const bit [15:0] UNLOCK_SEQUENCE [4] = {
+ 16'h5F55,
+ 16'h4E4C,
+ 16'h4F43,
+ 16'h4B5F
+ };
+
+ logic [1:0] unlock_sequence_counter;
+
+ always_ff @(posedge clk) begin
+ unlock_flag <= 1'b0;
+
+ if (reset || n64_scb.n64_reset || n64_scb.n64_nmi) begin
+ unlock_sequence_counter <= 2'd0;
+ end else if (!n64_scb.cfg_unlock) begin
+ if (reg_bus.write && reg_bus.address[16] && (reg_bus.address[15:5] == 11'd0)) begin
+ case (reg_bus.address[4:1])
+ REG_KEY_H, REG_KEY_L: begin
+ for (int index = 0; index < $size(UNLOCK_SEQUENCE); index++) begin
+ if (index == unlock_sequence_counter) begin
+ if (reg_bus.wdata == UNLOCK_SEQUENCE[index]) begin
+ unlock_sequence_counter <= unlock_sequence_counter + 1'd1;
+ if (index == ($size(UNLOCK_SEQUENCE) - 1'd1)) begin
+ unlock_flag <= 1'b1;
+ unlock_sequence_counter <= 2'd0;
+ end
+ end else begin
+ unlock_sequence_counter <= 2'd0;
+ end
+ end
+ end
+ end
+ endcase
end
end
end
diff --git a/fw/rtl/n64/n64_lock.sv b/fw/rtl/n64/n64_lock.sv
deleted file mode 100644
index 5679260..0000000
--- a/fw/rtl/n64/n64_lock.sv
+++ /dev/null
@@ -1,52 +0,0 @@
-module n64_lock (
- input clk,
- input reset,
-
- n64_reg_bus.lock reg_bus,
-
- n64_scb.lock n64_scb,
-);
-
- const bit [15:0] UNLOCK_SEQUENCE [4] = {
- 16'h5F55,
- 16'h4E4C,
- 16'h4F43,
- 16'h4B5F
- };
-
- always_comb begin
- reg_bus.rdata = 16'd0;
- end
-
- logic [1:0] sequence_counter;
-
- always_ff @(posedge clk) begin
- if (reset || n64_scb.n64_reset || n64_scb.n64_nmi) begin
- n64_scb.cfg_unlock <= 1'b0;
- sequence_counter <= 2'd0;
- end else begin
- if (reg_bus.write) begin
- if (reg_bus.address[16] && (reg_bus.address[15:2] == 14'd0)) begin
- for (int i = 0; i < $size(UNLOCK_SEQUENCE); i++) begin
- if (sequence_counter == i) begin
- if (reg_bus.wdata == UNLOCK_SEQUENCE[i]) begin
- sequence_counter <= sequence_counter + 1'd1;
- if (i == ($size(UNLOCK_SEQUENCE) - 1'd1)) begin
- n64_scb.cfg_unlock <= 1'b1;
- sequence_counter <= 2'd0;
- end
- end else begin
- n64_scb.cfg_unlock <= 1'b0;
- sequence_counter <= 2'd0;
- end
- end
- end
- end else begin
- n64_scb.cfg_unlock <= 1'b0;
- sequence_counter <= 2'd0;
- end
- end
- end
- end
-
-endmodule
diff --git a/fw/rtl/n64/n64_pi.sv b/fw/rtl/n64/n64_pi.sv
index 924e750..176f49b 100644
--- a/fw/rtl/n64/n64_pi.sv
+++ b/fw/rtl/n64/n64_pi.sv
@@ -139,7 +139,6 @@ module n64_pi (
write_port <= PORT_NONE;
reg_bus.dd_select <= 1'b0;
reg_bus.flashram_select <= 1'b0;
- reg_bus.lock_select <= 1'b0;
reg_bus.cfg_select <= 1'b0;
end else if (aleh_op) begin
read_port <= PORT_NONE;
@@ -147,7 +146,6 @@ module n64_pi (
mem_offset <= 32'd0;
reg_bus.dd_select <= 1'b0;
reg_bus.flashram_select <= 1'b0;
- reg_bus.lock_select <= 1'b0;
reg_bus.cfg_select <= 1'b0;
if (n64_scb.dd_enabled) begin
@@ -222,24 +220,18 @@ module n64_pi (
mem_offset <= (-32'h1400_0000) + FLASH_OFFSET;
end
- if (n64_pi_dq_in >= 16'h1FFD && n64_pi_dq_in < 16'h1FFE) begin
- read_port <= PORT_NONE;
- write_port <= PORT_REG;
- reg_bus.lock_select <= 1'b1;
- end
-
if (n64_scb.cfg_unlock) begin
if (n64_pi_dq_in >= 16'h1FFE && n64_pi_dq_in < 16'h1FFF) begin
read_port <= PORT_MEM;
write_port <= PORT_MEM;
mem_offset <= (-32'h1FFE_0000) + BUFFER_OFFSET;
end
+ end
- if (n64_pi_dq_in >= 16'h1FFF && n64_pi_dq_in < 16'h2000) begin
- read_port <= PORT_REG;
- write_port <= PORT_REG;
- reg_bus.cfg_select <= 1'b1;
- end
+ if (n64_pi_dq_in >= 16'h1FFF && n64_pi_dq_in < 16'h2000) begin
+ read_port <= n64_scb.cfg_unlock ? PORT_REG : PORT_NONE;
+ write_port <= PORT_REG;
+ reg_bus.cfg_select <= 1'b1;
end
end
end
diff --git a/fw/rtl/n64/n64_reg_bus.sv b/fw/rtl/n64/n64_reg_bus.sv
index 969edd5..07573b7 100644
--- a/fw/rtl/n64/n64_reg_bus.sv
+++ b/fw/rtl/n64/n64_reg_bus.sv
@@ -2,7 +2,6 @@ interface n64_reg_bus ();
logic flashram_select;
logic dd_select;
- logic lock_select;
logic cfg_select;
logic read;
@@ -13,14 +12,12 @@ interface n64_reg_bus ();
logic [15:0] flashram_rdata;
logic [15:0] dd_rdata;
- logic [15:0] lock_rdata;
logic [15:0] cfg_rdata;
modport controller (
output flashram_select,
output dd_select,
output cfg_select,
- output lock_select,
output read,
output write,
@@ -37,9 +34,6 @@ interface n64_reg_bus ();
if (dd_select) begin
rdata = dd_rdata;
end
- if (lock_select) begin
- rdata = lock_rdata;
- end
if (cfg_select) begin
rdata = cfg_rdata;
end
@@ -61,14 +55,6 @@ interface n64_reg_bus ();
input wdata
);
- modport lock (
- input .read(read && lock_select),
- input .write(write && lock_select),
- input address,
- output .rdata(lock_rdata),
- input wdata
- );
-
modport cfg (
input .read(read && cfg_select),
input .write(write && cfg_select),
diff --git a/fw/rtl/n64/n64_scb.sv b/fw/rtl/n64/n64_scb.sv
index 9cf6d3f..bdb9aa1 100644
--- a/fw/rtl/n64/n64_scb.sv
+++ b/fw/rtl/n64/n64_scb.sv
@@ -161,16 +161,11 @@ interface n64_scb ();
input dd_wdata
);
- modport lock (
+ modport cfg (
input n64_reset,
input n64_nmi,
- output cfg_unlock
- );
-
- modport cfg (
- input n64_reset,
-
+ output cfg_unlock,
output cfg_pending,
input cfg_done,
input cfg_error,
diff --git a/fw/rtl/n64/n64_top.sv b/fw/rtl/n64/n64_top.sv
index f6fd911..c63eafc 100644
--- a/fw/rtl/n64/n64_top.sv
+++ b/fw/rtl/n64/n64_top.sv
@@ -67,15 +67,6 @@ module n64_top (
.n64_scb(n64_scb)
);
- n64_lock n64_lock_inst (
- .clk(clk),
- .reset(reset),
-
- .reg_bus(reg_bus),
-
- .n64_scb(n64_scb)
- );
-
n64_cfg n64_cfg_inst (
.clk(clk),
.reset(reset),
diff --git a/sw/bootloader/src/io.h b/sw/bootloader/src/io.h
index 512a4ea..b1435ad 100644
--- a/sw/bootloader/src/io.h
+++ b/sw/bootloader/src/io.h
@@ -225,14 +225,6 @@ typedef struct {
#define PIFRAM ((io8_t *) PIFRAM_BASE)
-typedef struct {
- io32_t KEY;
-} sc64_lock_t;
-
-#define SC64_LOCK_BASE (0x1FFD0000UL)
-#define SC64_LOCK ((sc64_lock_t *) SC64_LOCK_BASE)
-
-
typedef struct {
io8_t BUFFER[8192];
io8_t EEPROM[2048];
@@ -248,6 +240,7 @@ typedef struct {
io32_t SR_CMD;
io32_t DATA[2];
io32_t VERSION;
+ io32_t KEY;
} sc64_regs_t;
#define SC64_REGS_BASE (0x1FFF0000UL)
@@ -256,6 +249,11 @@ typedef struct {
#define SC64_SR_CMD_ERROR (1 << 30)
#define SC64_SR_CPU_BUSY (1 << 31)
+#define SC64_KEY_RESET (0x00000000UL)
+#define SC64_KEY_UNLOCK_1 (0x5F554E4CUL)
+#define SC64_KEY_UNLOCK_2 (0x4F434B5FUL)
+#define SC64_KEY_LOCK (0xFFFFFFFFUL)
+
typedef struct {
uint32_t tv_type;
diff --git a/sw/bootloader/src/sc64.c b/sw/bootloader/src/sc64.c
index ce2a047..e601146 100644
--- a/sw/bootloader/src/sc64.c
+++ b/sw/bootloader/src/sc64.c
@@ -41,13 +41,14 @@ static bool sc64_execute_cmd (uint8_t cmd, uint32_t *args, uint32_t *result) {
}
void sc64_unlock (void) {
- pi_io_write(&SC64_LOCK->KEY, 0x00000000);
- pi_io_write(&SC64_LOCK->KEY, 0x5F554E4C);
- pi_io_write(&SC64_LOCK->KEY, 0x4F434B5F);
+ pi_io_write(&SC64_REGS->KEY, SC64_KEY_RESET);
+ pi_io_write(&SC64_REGS->KEY, SC64_KEY_UNLOCK_1);
+ pi_io_write(&SC64_REGS->KEY, SC64_KEY_UNLOCK_2);
}
void sc64_lock (void) {
- pi_io_write(&SC64_LOCK->KEY, 0x00000000);
+ pi_io_write(&SC64_REGS->KEY, SC64_KEY_RESET);
+ pi_io_write(&SC64_REGS->KEY, SC64_KEY_LOCK);
}
bool sc64_check_presence (void) {