Skip to content

Commit 960d58b

Browse files
committed
Verilator-driven SDL simulation.
1 parent b09dbc3 commit 960d58b

13 files changed

+216
-48
lines changed

loader/Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11

22
OBJ := nes_loader.o osd.o util.o
33

4+
# Link libstdc++ statically: https://web.archive.org/web/20160313071116/http://www.trilithium.com/johan/2005/06/static-libstdc/
45
loader: $(OBJ)
5-
g++ -o loader $(OBJ)
6+
g++ -static-libgcc -static-libstdc++ -o loader $(OBJ)
67

78
%.o: %.cpp
89
g++ -std=c++17 -c $< -o $@

src/cpu.v

+3-3
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,9 @@ end
242242
// Program counter
243243
ProgramCounter pc(clk, ce, LoadPC, GotInterrupt, DIN, T, PC, JumpNoOverflow);
244244

245-
always @(posedge clk) if (!reset && ce && (PC == 'hc071 || PC == 'hc072)) begin
246-
$write("pc=c071/c072");
247-
end
245+
// always @(posedge clk) if (!reset && ce && (PC == 'hc071 || PC == 'hc072)) begin
246+
// $write("pc=c071/c072");
247+
// end
248248

249249
reg IsNMIInterrupt = 0;
250250
reg LastNMI = 0;

src/hw_uart.v

+5-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
// Example: 10 MHz Clock, 115200 baud UART
1818
// (10000000)/(115200) = 87
1919

20+
typedef logic [7:0] BYTE;
21+
2022
module uart_rx
2123
#(parameter CLKS_PER_BIT)
2224
(
@@ -71,7 +73,7 @@ module uart_rx
7173
// Check middle of start bit to make sure it's still low
7274
s_RX_START_BIT :
7375
begin
74-
if (r_Clock_Count == (CLKS_PER_BIT-1)/2)
76+
if (r_Clock_Count == BYTE'((CLKS_PER_BIT-1)/2))
7577
begin
7678
if (r_Rx_Data == 1'b0)
7779
begin
@@ -92,7 +94,7 @@ module uart_rx
9294
// Wait CLKS_PER_BIT-1 clock cycles to sample serial data
9395
s_RX_DATA_BITS :
9496
begin
95-
if (r_Clock_Count < CLKS_PER_BIT-1)
97+
if (r_Clock_Count < BYTE'(CLKS_PER_BIT-1))
9698
begin
9799
r_Clock_Count <= r_Clock_Count + 1;
98100
r_SM_Main <= s_RX_DATA_BITS;
@@ -121,7 +123,7 @@ module uart_rx
121123
s_RX_STOP_BIT :
122124
begin
123125
// Wait CLKS_PER_BIT-1 clock cycles for Stop bit to finish
124-
if (r_Clock_Count < CLKS_PER_BIT-1)
126+
if (r_Clock_Count < BYTE'(CLKS_PER_BIT-1))
125127
begin
126128
r_Clock_Count <= r_Clock_Count + 1;
127129
r_SM_Main <= s_RX_STOP_BIT;

src/memory_controller.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ wire [15:0] MemDout;
7272
reg [2:0] cycles;
7373
reg r_read_a, r_read_b;
7474
wire MemBusy, MemDataReady;
75-
wire fail_high, fail_low, tester_rd, tester_wr, tester_refresh, testing;
75+
wire tester_rd, tester_wr, tester_refresh;
7676
wire [25:0] tester_addr;
7777
wire [15:0] tester_din;
7878

src/mmu.v

+3-3
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,8 @@ module MMC5(input clk, input ce, input reset,
447447
always @(posedge clk) begin
448448
if (ce) begin
449449
if (prg_write && prg_ain[15:10] == 6'b010100) begin // $5000-$53FF
450-
if (prg_ain <= 16'h5113)
451-
$write("%X <= %X (%d)\n", prg_ain, prg_din, ppu_scanline);
450+
// if (prg_ain <= 16'h5113)
451+
// $write("%X <= %X (%d)\n", prg_ain, prg_din, ppu_scanline);
452452
casez(prg_ain[9:0])
453453
10'h100: prg_mode <= prg_din[1:0];
454454
10'h101: chr_mode <= prg_din[1:0];
@@ -1329,7 +1329,7 @@ module Mapper71(input clk, input ce, input reset,
13291329
ciram_select <= 0;
13301330
end else if (ce) begin
13311331
if (prg_ain[15] && prg_write) begin
1332-
$write("%X <= %X (bank = %x)\n", prg_ain, prg_din, prg_bank);
1332+
// $write("%X <= %X (bank = %x)\n", prg_ain, prg_din, prg_bank);
13331333
if (!prg_ain[14] && mapper232) // $8000-$BFFF Outer bank select (only on iNES 232)
13341334
prg_bank[3:2] <= prg_din[4:3];
13351335
if (prg_ain[14:13] == 0) // $8000-$9FFF Fire Hawk Mirroring

src/nes.v

+3-3
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ endmodule
123123
module NES(input clk, input reset, input ce,
124124
input [31:0] mapper_flags,
125125
output [15:0] sample, // sample generated from APU
126-
output [5:0] color, // pixel generated from PPU
126+
output [5:0] color /*verilator public*/, // pixel generated from PPU
127127
output joypad_strobe,// Set to 1 to strobe joypads. Then set to zero to keep the value.
128128
output [1:0] joypad_clock, // Set to 1 for each joypad to clock it.
129129
input [1:0] joypad_data, // Data for each joypad.
@@ -139,8 +139,8 @@ module NES(input clk, input reset, input ce,
139139
output memory_write, // is a write operation
140140
output [7:0] memory_dout,
141141

142-
output [8:0] cycle,
143-
output [8:0] scanline
142+
output [8:0] cycle /*verilator public*/,
143+
output [8:0] scanline /*verilator public*/
144144

145145
// output reg [31:0] dbgadr,
146146
// output [1:0] dbgctr

src/nes_tang20k.v

+27-11
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// nand2mario, 2022.9
44
//
55

6-
`timescale 1ns / 100ps
6+
// `timescale 1ns / 100ps
77

88
// Main clock frequency
99
localparam FREQ=32_250_000;
@@ -126,10 +126,12 @@ module NES_Tang20k(
126126
wire [7:0] uart_addr;
127127
wire uart_write;
128128
wire uart_error;
129+
`ifndef VERILATOR
129130
UartDemux
130131
#(.FREQ(FREQ), .BAUDRATE(BAUDRATE))
131132
uart_demux(clk, 1'b0, UART_RXD, uart_data, uart_addr, uart_write, uart_error);
132133
// uart_demux(clk, ~sys_resetn, UART_RXD, uart_data, uart_addr, uart_write, uart_error);
134+
`endif
133135

134136
// ROM loader
135137
reg [7:0] loader_conf; // bit 0 is reset
@@ -200,7 +202,7 @@ module NES_Tang20k(
200202
.clk(clk), .reset(loader_reset), .indata(loader_input), .indata_clk(loader_clk),
201203
.mem_addr(loader_addr), .mem_data(loader_write_data), .mem_write(loader_write),
202204
.mem_refresh(loader_refresh), .mapper_flags(mapper_flags),
203-
.done(loader_done), .error(loader_fail));
205+
.done(loader_done), .error(loader_fail), .loader_state(), .loader_bytes_left());
204206

205207
// The NES machine
206208
// nes_ce / 0 \___/ 1 \___/ 2 \___/ 3 \___/ 4 \___/ 5 \___/ 0 \___/
@@ -283,6 +285,7 @@ module NES_Tang20k(
283285
wire [1:0] rclkpos;
284286
wire [2:0] rclksel;
285287
wire [3:0] test_state;
288+
wire write_level_done, read_calib_done, ram_testing, fail_high, fail_low;
286289
MemoryController memory(.clk(clk), .pclk(pclk), .fclk(fclk), .ck(ck), .resetn(sys_resetn & nes_lock & mem_resetn),
287290
.read_a(memory_read_cpu && run_mem),
288291
.read_b(memory_read_ppu && run_mem),
@@ -506,15 +509,23 @@ endmodule
506509

507510

508511
`ifdef EMBED_GAME
509-
// zf: Feed INES data to Game_Loader
512+
// Feed INES data to Game_Loader
510513
module GameData (input clk, input reset, input start,
511514
output reg [7:0] odata, output reg odata_clk
512515
);
513516

514-
// 24KB+ buffer for ROM
515-
reg [7:0] INES[24719:0];
516-
reg [21:0] INES_SIZE = 24719;
517-
initial $readmemh("BattleCity.nes.hex", INES);
517+
// localparam [21:0] INES_SIZE = 24719;
518+
// localparam string INES_FILE="../BattleCity.nes.hex";
519+
520+
// localparam [21:0] INES_SIZE = 131088;
521+
// localparam string INES_FILE="../Contra.nes.hex";
522+
523+
localparam [21:0] INES_SIZE = 262160;
524+
localparam string INES_FILE="../SuperC.nes.hex";
525+
526+
// Buffer for ROM file
527+
reg [7:0] INES[INES_SIZE:0];
528+
initial $readmemh(INES_FILE, INES);
518529

519530
reg [1:0] state = 0;
520531
reg [21:0] addr = 0;
@@ -525,22 +536,27 @@ module GameData (input clk, input reset, input start,
525536
state <= 0;
526537
addr <= 0; // odata gets INES[0]
527538
odata_clk <= 0;
528-
end else if (start && state == 0) begin
539+
end else if (start && state == 2'd0) begin
529540
// start loading
530541
state <= 1;
531-
end else if (state==1) begin
542+
end else if (state == 2'd1) begin
532543
if (addr == INES_SIZE) begin
533544
// we've just sent the last byte
534-
state <= 2; // end of data
545+
state <= 2'd3; // end of data
535546
odata_clk <= 0;
536547
end else begin
537548
// pump data to Game_Loader
538549
/* verilator lint_off WIDTH */
539550
odata <= INES[addr];
540551
/* verilator lint_on WIDTH */
541552
odata_clk <= 1;
542-
addr <= addr + 1;
553+
state <= 2;
543554
end
555+
end else if (state == 2'd2) begin
556+
// wait one clock cycle, then send next byte
557+
odata_clk <= 0;
558+
addr <= addr + 1;
559+
state <= 1;
544560
end
545561
end
546562
endmodule

verilator/Makefile

+14-5
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11

2-
.PHONY: build sim verilate
3-
2+
CFLAGS_SDL=$(shell sdl2-config --cflags) -O3
3+
LIBS_SDL=$(shell sdl2-config --libs)
44

5+
.PHONY: build sim verilate clean
6+
57
build: ./obj_dir/VNES_Tang20k
68

7-
verilate: sim_main.cpp hdl/*.v
9+
verilate: ./obj_dir/VNES_Tang20k.cpp
10+
11+
./obj_dir/VNES_Tang20k.cpp: sim_main.cpp hdl/*.v
812
@echo
913
@echo "### VERILATE ####"
10-
verilator --top-module NES_Tang20k --trace -cc hdl/*.v --exe sim_main.cpp
14+
mkdir -p obj_dir
15+
cd obj_dir; ln -sf ../game.nes.hex .; ln -sf ../hdl/src/*.txt .
16+
# verilator --top-module NES_Tang20k --trace -cc -O3 -CFLAGS "$(CFLAGS_SDL)" -LDFLAGS "$(LIBS_SDL)" hdl/*.v --exe sim_main.cpp
17+
verilator --top-module NES_Tang20k -cc -O3 --exe -CFLAGS "$(CFLAGS_SDL)" -LDFLAGS "$(LIBS_SDL)" hdl/*.v sim_main.cpp
1118

1219
./obj_dir/VNES_Tang20k: verilate
1320
@echo
@@ -17,5 +24,7 @@ verilate: sim_main.cpp hdl/*.v
1724
sim: ./obj_dir/VNES_Tang20k
1825
@echo
1926
@echo "### SIMULATION ###"
20-
@echo "This will take some time..."
2127
@cd obj_dir && ./VNES_Tang20k
28+
29+
clean:
30+
rm -rf obj_dir

verilator/README

-1
This file was deleted.

verilator/README.md

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
This is a Verilator-driven graphical simulation of nestang. Should be useful in debugging game / mapper support, among other things.
2+
3+
To run the simulation:
4+
5+
```
6+
./setup.sh `pwd`/..
7+
hexdump -ve '1/1 "%02x\n"' game.nes > game.nes.hex
8+
# change INES_SIZE in nes_tang20k.v to reflect size of game.nes
9+
make sim
10+
```
11+
12+
You need to set up verilator / libsdl2 with something like:
13+
14+
```
15+
# Linux
16+
sudo apt install verilator libsdl2-dev
17+
18+
# Mac
19+
brew install verilator sdl2
20+
```
21+
22+
For an overview of verilator, see: https://www.itsembedded.com/dhd/verilator_2/

verilator/nes_palette.h

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
const unsigned NES_PALETTE[64] = {
4+
0x545454, 0x001e74, 0x081090, 0x300088, 0x440064, 0x5c0030, 0x540400, 0x3c1800,
5+
0x202a00, 0x083a00, 0x004000, 0x003c00, 0x00323c, 0x000000, 0x000000, 0x000000,
6+
0x989698, 0x084cc4, 0x3032ec, 0x5c1ee4, 0x8814b0, 0xa01464, 0x982220, 0x783c00,
7+
0x545a00, 0x287200, 0x087c00, 0x007628, 0x006678, 0x000000, 0x000000, 0x000000,
8+
0xeceeec, 0x4c9aec, 0x787cec, 0xb062ec, 0xe454ec, 0xec58b4, 0xec6a64, 0xd48820,
9+
0xa0aa00, 0x74c400, 0x4cd020, 0x38cc6c, 0x38b4cc, 0x3c3c3c, 0x000000, 0x000000,
10+
0xeceeec, 0xa8ccec, 0xbcbcec, 0xd4b2ec, 0xecaeec, 0xecaed4, 0xecb4b0, 0xe4c490,
11+
0xccd278, 0xb4de78, 0xa8e290, 0x98e2b4, 0xa0d6e4, 0xa0a2a0, 0x000000, 0x000000,
12+
};

verilator/setup.sh

100644100755
+17-16
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,22 @@ fi
1111
DIR=$1
1212

1313
mkdir -p hdl
14-
ln -s $DIR/src/apu.v hdl
15-
ln -s $DIR/src/compat.v hdl
16-
ln -s $DIR/src/cpu.v hdl
17-
ln -s $DIR/src/hw_sound.v hdl
18-
ln -s $DIR/src/hw_uart.v hdl
19-
ln -s $DIR/src/MicroCode.v hdl
20-
ln -s $DIR/src/mmu.v hdl
21-
ln -s $DIR/src/nes_tang20k.v hdl
22-
ln -s $DIR/src/nes.v hdl
23-
ln -s $DIR/src/ppu.v hdl
24-
ln -s $DIR/src/sdram.v hdl
14+
ln -sf $DIR/src/apu.v hdl
15+
ln -sf $DIR/src/compat.v hdl
16+
ln -sf $DIR/src/cpu.v hdl
17+
ln -sf $DIR/src/hw_sound.v hdl
18+
ln -sf $DIR/src/MicroCode.v hdl
19+
ln -sf $DIR/src/mmu.v hdl
20+
ln -sf $DIR/src/nes_tang20k.v hdl
21+
ln -sf $DIR/src/nes.v hdl
22+
ln -sf $DIR/src/ppu.v hdl
23+
ln -sf $DIR/src/memory_controller.v hdl
24+
ln -sf $DIR/src/game_loader.v hdl
25+
ln -sf $DIR/src hdl/src
2526

26-
mkdir -p obj_dir
27-
ln -s $DIR/src/oam_palette.txt obj_dir
28-
ln -s $DIR/src/*.hex obj_dir
27+
echo "hdl/ directory setup done."
2928

30-
31-
echo "Setup done."
29+
if [ ! -f game.nes.hex ]; then
30+
echo "You need game.nes.hex ROM file to do simulation. To generate from .nes files: "
31+
echo ' hexdump -ve '"'"'1/1 "%02x\\n'"'"' game.nes > game.nes.hex'
32+
fi

0 commit comments

Comments
 (0)