Skip to content

Commit 50c247b

Browse files
authored
Merge pull request #316 from Rodrigodd/test-cpu_instrs
Add bank switching and document Testing Workflow
2 parents 296b992 + fd00d0b commit 50c247b

2 files changed

Lines changed: 48 additions & 14 deletions

File tree

HDL/sm83/Icarus/Readme.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,13 @@ make verilator ROM=roms/cpu_instrs.mem CYCLES=1000000
4040
This will create a `dmg_waves3.fst` file that can be opened in [GTKWave](https://gtkwave.sourceforge.net/) or [Surfer](https://surfer-project.org/).
4141

4242
Note that `sm83.yosys.v` flattens the entire design, so the hierarchy is lost, and many signals are removed. If you need a particular signal, add a `(* keep *)` attribute to it.
43+
44+
Here's the corrected version of your text with typos and grammatical errors fixed:
45+
46+
## Testing
47+
48+
The CPU is tested by running individual test ROMs from blargg's [cpu_instrs](https://github.com/retrio/gb-test-roms/tree/master/cpu_instrs) test suite (as well as the single ROM version). These ROMs rely very little on other peripherals of the GameBoy besides the CPU core itself. The necessary peripherals are emulated in the module `Bogus_HW` in `run.v`.
49+
50+
In case of a test failure, a reference trace can be generated by running the emulator [Rodrigodd/gameroy](https://github.com/Rodrigodd/gameroy) with the [wave_trace feature enabled](https://github.com/Rodrigodd/gameroy/pull/17). More specifically [at this commit](https://github.com/Rodrigodd/gameroy/commit/62c91d15e51dd6fc7a87f94b889be6ed91f4e5df), which contains changes that make the emulator behave more like the simulation.
51+
52+
To assist in finding where the traces diverge, the tool [rodrigodd/fst-trace](https://github.com/rodrigodd/fst-merger/) can be used to merge both traces into a single file and create signals that compare some signals of both traces.

HDL/sm83/Icarus/run.v

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -143,52 +143,67 @@ module Bogus_HW ( CLK, RESET, MREQ, RD, WR, databus, addrbus, CPU_IRQ_TRIG, CPU_
143143
localparam REG_TMA = 16'hFF06;
144144
localparam REG_TAC = 16'hFF07;
145145

146+
// Simulate memory banking just enough for running cpu_instrs.gb
147+
reg [1:0] BANK_SELECTED = 1'b1;
148+
146149
// Timer registers
147-
reg [15:0] DIV = 0;
150+
reg [15:0] DIV = 16'haba9; // magic value that matches the reference emulator
148151
reg [7:0] TIMA = 0;
149152
reg [7:0] TMA = 0;
150153
reg [2:0] TAC = 0;
151154

155+
reg [4:0] IF = 0;
156+
reg tima_overflow = 0;
157+
152158
wire counter_bit = TAC[2] && (TAC[1:0] == 2'b00 ? DIV[9] : TAC[1:0] == 2'b01 ? DIV[3] : TAC[1:0] == 2'b10 ? DIV[5] : DIV[7]);
153159

154160
reg [7:0] bootrom[0:255];
155161
initial $readmemh("roms/boot.mem", bootrom);
156162

163+
reg [7:0] rom[0:65535];
157164
reg [7:0] mem[0:65535];
158165
reg [7:0] value;
159166

160167
reg in_boot = 1'b1;
161168

162-
assign CPU_IRQ_TRIG = mem[REG_IF];
169+
assign CPU_IRQ_TRIG = IF;
163170

164171
integer j;
165172
initial begin
166173
// Pre-fill the memory with some value so we don't run into `xx`
167-
for(j = 0; j < 65536; j = j+1)
174+
for(j = 0; j < 65536; j = j+1) begin
168175
mem[j] = 0;
169-
170-
mem[REG_IF] = 8'he0;
176+
rom[j] = 0;
177+
end
171178

172179
`define STRINGIFY(x) `"x`"
173180
`ifdef ROM
174-
$readmemh(`ROM, mem);
181+
$readmemh(`ROM, rom);
175182
`else
176-
$readmemh("roms/bogus_hw.mem", mem);
183+
$readmemh("roms/bogus_hw.mem", rom);
177184
`endif
178185
end
179186

180-
always @(posedge CLK) begin
187+
always @(negedge CLK) begin
181188
DIV <= DIV + 1;
182189
end
183190
always @(negedge counter_bit) begin
184191
if (RESET)
185192
TIMA <= 0;
186193
else if (TIMA == 255) begin
187-
TIMA <= TMA;
188-
mem[REG_IF] <= mem[REG_IF] | 4'h4;
194+
TIMA <= 0;
195+
tima_overflow = 1'b1;
189196
end else
190197
TIMA <= TIMA + 1;
191198
end
199+
wire tima_reload_delay = DIV[1] && ~counter_bit;
200+
always @(posedge tima_reload_delay) begin
201+
if (tima_overflow) begin
202+
TIMA <= TMA;
203+
IF[2] <= 1'b1;
204+
tima_overflow = 1'b0;
205+
end
206+
end
192207

193208
always @(posedge RD) begin
194209
// disable bootrom after entering ROM
@@ -200,7 +215,11 @@ module Bogus_HW ( CLK, RESET, MREQ, RD, WR, databus, addrbus, CPU_IRQ_TRIG, CPU_
200215
else if (ADR == REG_DIV) value <= DIV[15:8];
201216
else if (ADR == REG_TIMA) value <= TIMA;
202217
else if (ADR == REG_TMA) value <= TMA;
203-
else if (ADR == REG_TAC) value <= {5'b1, TAC};
218+
else if (ADR == REG_TAC) value <= {5'h1f, TAC};
219+
else if (ADR == REG_IF) value <= {3'h7, IF};
220+
else if (ADR >= 16'hff00 && ADR <= 16'hff7f) value <= 16'hff; // IO registers
221+
else if (ADR <= 16'h3fff) value <= rom[addrbus];
222+
else if (ADR <= 16'h7fff) value <= rom[{BANK_SELECTED[1:0], addrbus[13:0]}];
204223
else value <= mem[addrbus];
205224
end
206225

@@ -214,21 +233,26 @@ module Bogus_HW ( CLK, RESET, MREQ, RD, WR, databus, addrbus, CPU_IRQ_TRIG, CPU_
214233
wire serial_write = (ADR == REG_SERIAL_CONTROL);
215234

216235
always @(negedge WR) begin
217-
if (ADR == REG_IF) mem[ADR] <= DAT | 8'he0;
218-
else if (ADR == REG_DIV) DIV <= 0;
236+
if (ADR == REG_DIV) DIV <= 0;
219237
else if (ADR == REG_TIMA) TIMA <= DAT;
220238
else if (ADR == REG_TMA) TMA <= DAT;
221239
else if (ADR == REG_TAC) TAC <= DAT[2:0];
240+
else if (ADR == REG_IF) IF <= DAT[4:0];
241+
else if (ADR <= 16'h7fff) begin
242+
// ROM area, switch banks
243+
BANK_SELECTED <= DAT[1:0];
244+
end
222245
else
223246
mem[ADR] <= DAT;
224247

225248
if (serial_write) begin
226249
$write("%c", mem[REG_SERIAL_DATA]);
250+
$fflush();
227251
end
228252
end
229253

230254
always @(CPU_IRQ_ACK) begin
231-
mem[REG_IF] <= mem[REG_IF] & ~CPU_IRQ_ACK;
255+
IF <= IF & ~CPU_IRQ_ACK;
232256
end
233257

234258

0 commit comments

Comments
 (0)