Complete rewrite from scratch, bootstrap WIP

Rewrite to use several bus multiplexers, resulting into a less messy
microarchitecture (hopefully). Some more room for cleanup though...

Supports every instruction from the bootstrap rom, more or less.
LY hacked at 0x90 to progress through vsync instantly.
No cartridge is present yet, so we will always fail checksum test and lock up.
This commit is contained in:
2023-10-01 23:00:56 +01:00
parent e713f8de87
commit fda176d3b5
23 changed files with 1425 additions and 956 deletions

18
sim/clkgen.sv Normal file
View File

@@ -0,0 +1,18 @@
module clkgen #(
PERIOD_NS = 10,
RESET_DELAY_NS = 45
) (
output logic clk,
output logic nreset
);
initial begin
clk <= 1'b1;
nreset <= 1'b0;
#RESET_DELAY_NS nreset <= 1'b1;
end
always
#(PERIOD_NS/2) clk <= ~clk;
endmodule

View File

@@ -1,18 +0,0 @@
module clkgen #(
PERIOD_NS = 10,
RESET_DELAY_NS = 100
) (
output logic clk_o,
output logic nreset_o
);
initial begin
clk_o <= 1'b1;
nreset_o <= 1'b0;
#RESET_DELAY_NS nreset_o <= 1'b1;
end
always
#(PERIOD_NS/2) clk_o <= ~clk_o;
endmodule

76
sim/tb_top.sv Normal file
View File

@@ -0,0 +1,76 @@
module tb_top;
logic clk;
logic nreset;
clkgen clkgen_inst (
.clk (clk),
.nreset(nreset)
);
gb gb_inst (
.clk (clk),
.nreset(nreset)
);
logic instr_valid;
logic instr_undef;
logic halted;
logic [15:0] current_pc;
logic [ 7:0] current_opcode[2:0];
logic we;
logic [15:0] last_write_address;
logic [ 7:0] last_write_value;
logic vram_sel;
logic hiram_sel;
assign halted = gb_inst.cpu_inst.ctrl_inst.halted_r;
assign instr_valid = gb_inst.cpu_inst.instr_valid;
assign instr_undef = gb_inst.cpu_inst.ctrl_inst.instr_undef;
assign current_opcode = gb_inst.cpu_inst.instr;
assign we = gb_inst.cpu_we;
assign vram_sel = gb_inst.vram_sel;
assign hiram_sel = gb_inst.hiram_sel;
always_ff @(posedge clk or negedge nreset) begin
if (!nreset)
current_pc <= '0;
else if (instr_valid)
current_pc <= gb_inst.cpu_inst.pc_r;
end
always_ff @(posedge clk or negedge nreset) begin
if (!nreset) begin
last_write_address <= '0;
last_write_value <= '0;
end else if (we) begin
last_write_address <= gb_inst.cpu_addr;
last_write_value <= gb_inst.cpu_wdata;
end
end
// SVA code here
`include "sva_common.svh"
`SVA_DEF_CLK(clk);
`SVA_DEF_NRESET(nreset);
`SVA_ASSERT_PROP_FATAL(undefined_opcode_pushed,
halted |-> !instr_undef,
$sformatf("PC: 0x%X | Undefined opcode pushed: 0x%X (0x%X, 0x%X)", current_pc, current_opcode[0], current_opcode[1], current_opcode[2])
);
logic selected_memory_implemented;
assign selected_memory_implemented = hiram_sel | vram_sel;
`SVA_ASSERT_PROP(write_to_unimplemented_memory,
we |-> selected_memory_implemented,
$sformatf("PC: 0x%X | Write to unimplemented memory: 0x%X <= 0x%X",
current_pc, last_write_address, last_write_value)
);
endmodule : tb_top

View File

@@ -1,50 +0,0 @@
module tb_top ();
logic clk;
logic nreset;
clkgen clkgen_inst (
.clk_o (clk),
.nreset_o(nreset)
);
gb gb_inst (
.clk_i (clk),
.nreset_i(nreset)
);
// Testbench code
logic instr_undef;
logic halted;
logic [15:0] last_pc;
logic [ 7:0] last_opcode;
logic [ 7:0] last_op1;
logic [ 7:0] last_op2;
logic we;
logic [15:0] address;
logic [ 7:0] wdata;
assign halted = gb_inst.cpu_inst.control_inst.halted_r;
assign instr_undef = gb_inst.cpu_inst.control_inst.is_undef;
assign last_pc = gb_inst.cpu_inst.control_inst.instr_pc_r;
assign last_opcode = gb_inst.cpu_inst.control_inst.instr_r;
assign last_op1 = gb_inst.cpu_inst.control_inst.operand0_r;
assign last_op2 = gb_inst.cpu_inst.control_inst.operand1_r;
assign we = gb_inst.we;
assign address = gb_inst.address;
assign wdata = gb_inst.wdata;
always @(posedge clk) begin
if (nreset && instr_undef & ~halted) begin
$display($sformatf("[%0t] %X: Undefined opcode %X | [%X | %X]", $time(), last_pc, last_opcode, last_op1, last_op2));
$fatal(0);
$finish();
end
if (nreset && we) begin
$display($sformatf("[%0t] Write: [%X] <= %X", $time(), address, wdata));
end
end
endmodule : tb_top