From 441c07787cdfe98abc4a2b0651ed513efe9d10e4 Mon Sep 17 00:00:00 2001 From: Sebastien Delestaing Date: Mon, 19 Sep 2016 09:51:08 +0200 Subject: [PATCH 1/5] Attempt to fix DRAM instability --- cores/nes/mist/sdram.v | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cores/nes/mist/sdram.v b/cores/nes/mist/sdram.v index 92b57ad..72671f7 100644 --- a/cores/nes/mist/sdram.v +++ b/cores/nes/mist/sdram.v @@ -48,7 +48,7 @@ module sdram ( ); // no burst configured -localparam RASCAS_DELAY = 3'd3; // tRCD=20ns -> 3 cycles@128MHz +localparam RASCAS_DELAY = 3'd2; // tRCD=20ns -> 2 cycles@85MHz localparam BURST_LENGTH = 3'b000; // 000=1, 001=2, 010=4, 011=8 localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved localparam CAS_LATENCY = 3'd3; // 2/3 allowed @@ -70,7 +70,7 @@ localparam STATE_LAST = 4'd15; // last state in cycle reg [3:0] q; always @(posedge clk) begin - // SDRAM (state machine) clock is 86MHz. Synchronize this to systems 21.477 Mhz clock + // SDRAM (state machine) clock is 85MHz. Synchronize this to systems 21.477 Mhz clock // force counter to pass state LAST->FIRST exactly after the rising edge of clkref if(((q == STATE_LAST) && ( clkref == 1)) || ((q == STATE_FIRST) && ( clkref == 0)) || @@ -82,13 +82,13 @@ end // --------------------------- startup/reset --------------------------- // --------------------------------------------------------------------- -// wait 1ms (32 8Mhz cycles) after FPGA config is done before going +// wait 1ms (85000 cycles) after FPGA config is done before going // into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0) -reg [4:0] reset; +reg [16:0] reset; always @(posedge clk) begin - if(init) reset <= 5'h1f; + if(init) reset <= 17'h14c08; else if((q == STATE_LAST) && (reset != 0)) - reset <= reset - 5'd1; + reset <= reset - 17'd1; end // --------------------------------------------------------------------- From f5f91da6a6ab2b9484c50fec7531b64687fed888 Mon Sep 17 00:00:00 2001 From: Sebastien Delestaing Date: Mon, 19 Sep 2016 15:15:49 +0200 Subject: [PATCH 2/5] Extend reset time after download --- cores/nes/mist/NES_mist.v | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/cores/nes/mist/NES_mist.v b/cores/nes/mist/NES_mist.v index 4070be1..3858988 100644 --- a/cores/nes/mist/NES_mist.v +++ b/cores/nes/mist/NES_mist.v @@ -222,14 +222,14 @@ wire [7:0] nes_joy_B = { joyA[0], joyA[1], joyA[2], joyA[3], clk clock_21mhz(.inclk0(CLOCK_27[0]), .c0(clk85), .c1(SDRAM_CLK), .locked(clock_locked)); // initial reset after pll startup -// reg [7:0] init_reset_cnt; -// wire init_reset = init_reset_cnt != 0; -// always @(posedge CLOCK_27[0]) begin -// if(!clock_locked) -// init_reset_cnt <= 8'd255; -// else if(init_reset_cnt != 0) -// init_reset_cnt <= init_reset_cnt - 8'd1; -// end + reg [7:0] download_reset_cnt; + wire download_reset = download_reset_cnt != 0; + always @(posedge CLOCK_27[0]) begin + if(downloading) + download_reset_cnt <= 8'd255; + else if(download_reset_cnt != 0) + download_reset_cnt <= download_reset_cnt - 8'd1; + end // hold machine in reset until first download starts reg init_reset; @@ -246,12 +246,6 @@ wire [7:0] nes_joy_B = { joyA[0], joyA[1], joyA[2], joyA[3], wire clk = clkcnt[1]; wire ps2_clk = clkcnt[12]; - - // Loader - wire [7:0] loader_input; - wire loader_clk; - reg [7:0] loader_btn, loader_btn_2; - wire [8:0] cycle; wire [8:0] scanline; wire [15:0] sample; @@ -282,9 +276,13 @@ wire [7:0] nes_joy_B = { joyA[0], joyA[1], joyA[2], joyA[3], last_joypad_clock <= joypad_clock; end + + // Loader + wire [7:0] loader_input; + wire loader_clk; wire [21:0] loader_addr; wire [7:0] loader_write_data; - wire loader_reset = !downloading; //loader_conf[0]; + wire loader_reset = !download_reset; //loader_conf[0]; wire loader_write; wire [31:0] mapper_flags; wire loader_done, loader_fail; @@ -292,8 +290,7 @@ wire [7:0] nes_joy_B = { joyA[0], joyA[1], joyA[2], joyA[3], loader_addr, loader_write_data, loader_write, mapper_flags, loader_done, loader_fail); -//TH wire reset_nes = (buttons[1] || !loader_done); - wire reset_nes = (init_reset || buttons[1] || arm_reset || reset_osd || downloading); + wire reset_nes = (init_reset || buttons[1] || arm_reset || reset_osd || download_reset); wire run_mem = (nes_ce == 0) && !reset_nes; wire run_nes = (nes_ce == 3) && !reset_nes; From f7ee9f1e4d255df6a3028bc25d231f3e378198c3 Mon Sep 17 00:00:00 2001 From: Sebastien Delestaing Date: Mon, 19 Sep 2016 15:51:47 +0200 Subject: [PATCH 3/5] Cleanup scanlines implementation --- cores/nes/src/video.v | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cores/nes/src/video.v b/cores/nes/src/video.v index 5a5d907..41878ed 100644 --- a/cores/nes/src/video.v +++ b/cores/nes/src/video.v @@ -76,9 +76,10 @@ always @(posedge clkv) begin end wire [14:0] pixel_v = (!hpicture || !vpicture) ? 15'd0 : mode ? pixel : doubler_pixel; -wire [4:0] vga_r = mode ? pixel_v[4:0] : (v[0] & scanlines) ? {1'b0, pixel_v[4:1]} : pixel_v[4:0]; -wire [4:0] vga_g = mode ? pixel_v[9:5] : (v[0] & scanlines) ? {1'b0, pixel_v[9:6]} : pixel_v[9:5]; -wire [4:0] vga_b = mode ? pixel_v[14:10] : (v[0] & scanlines) ? {1'b0, pixel_v[14:11]} : pixel_v[14:10]; +wire darker = !mode && v[0] && scanlines; +wire [4:0] vga_r = darker ? {1'b0, pixel_v[4:1]} : pixel_v[4:0]; +wire [4:0] vga_g = darker ? {1'b0, pixel_v[9:6]} : pixel_v[9:5]; +wire [4:0] vga_b = darker ? {1'b0, pixel_v[14:11]} : pixel_v[14:10]; wire sync_h = ((h >= (512 + 23 + (mode ? 18 : 35))) && (h < (512 + 23 + (mode ? 18 : 35) + 82))); wire sync_v = ((v >= (mode ? 240 + 5 : 480 + 10)) && (v < (mode ? 240 + 14 : 480 + 12))); assign VGA_HS = mode ? ~(sync_h ^ sync_v) : ~sync_h; From 2082bffe0966929d0379ca7db331611ea5353b9c Mon Sep 17 00:00:00 2001 From: Sebastien Delestaing Date: Tue, 20 Sep 2016 11:34:25 +0200 Subject: [PATCH 4/5] Cleanup more registers on reset --- cores/nes/mist/NES_mist.v | 31 ++++++++++++++++++------------- cores/nes/mist/keyboard.v | 4 +++- cores/nes/src/nes.v | 13 +++++++++---- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/cores/nes/mist/NES_mist.v b/cores/nes/mist/NES_mist.v index 3858988..0876851 100644 --- a/cores/nes/mist/NES_mist.v +++ b/cores/nes/mist/NES_mist.v @@ -212,9 +212,9 @@ end wire strt = (start_cnt != 0); wire sel = (select_cnt != 0); -wire [7:0] nes_joy_A = { joyB[0], joyB[1], joyB[2], joyB[3], +wire [7:0] nes_joy_A = reset_nes ? 8'd0 : { joyB[0], joyB[1], joyB[2], joyB[3], joyB[7] | strt, joyB[6] | sel, joyB[5], joyB[4] } | kbd_joy0; -wire [7:0] nes_joy_B = { joyA[0], joyA[1], joyA[2], joyA[3], +wire [7:0] nes_joy_B = reset_nes ? 8'd0 : { joyA[0], joyA[1], joyA[2], joyA[3], joyA[7], joyA[6], joyA[5], joyA[4] } | kbd_joy1; wire clock_locked; @@ -264,16 +264,22 @@ wire [7:0] nes_joy_B = { joyA[0], joyA[1], joyA[2], joyA[3], reg [1:0] nes_ce; - always @(posedge clk) begin - if (joypad_strobe) begin - joypad_bits <= nes_joy_A; - joypad_bits2 <= nes_joy_B; - end - if (!joypad_clock[0] && last_joypad_clock[0]) - joypad_bits <= {1'b0, joypad_bits[7:1]}; - if (!joypad_clock[1] && last_joypad_clock[1]) - joypad_bits2 <= {1'b0, joypad_bits2[7:1]}; - last_joypad_clock <= joypad_clock; + always @(posedge clk) begin + if (reset_nes) begin + joypad_bits <= 8'd0; + joypad_bits2 <= 8'd0; + last_joypad_clock <= 2'b00; + end else begin + if (joypad_strobe) begin + joypad_bits <= nes_joy_A; + joypad_bits2 <= nes_joy_B; + end + if (!joypad_clock[0] && last_joypad_clock[0]) + joypad_bits <= {1'b0, joypad_bits[7:1]}; + if (!joypad_clock[1] && last_joypad_clock[1]) + joypad_bits2 <= {1'b0, joypad_bits2[7:1]}; + last_joypad_clock <= joypad_clock; + end end @@ -291,7 +297,6 @@ wire [7:0] nes_joy_B = { joyA[0], joyA[1], joyA[2], joyA[3], mapper_flags, loader_done, loader_fail); wire reset_nes = (init_reset || buttons[1] || arm_reset || reset_osd || download_reset); - wire run_mem = (nes_ce == 0) && !reset_nes; wire run_nes = (nes_ce == 3) && !reset_nes; // NES is clocked at every 4th cycle. diff --git a/cores/nes/mist/keyboard.v b/cores/nes/mist/keyboard.v index 19f5b8e..ca87c1b 100644 --- a/cores/nes/mist/keyboard.v +++ b/cores/nes/mist/keyboard.v @@ -38,8 +38,10 @@ assign joystick_1 = joy_num ? buttons : 7'b0; always @(posedge reset or posedge clk) begin if(reset) begin - pressed <= 1'b1; + pressed <= 1'b0; e0 <= 1'b0; + joy_num <= 1'b0; + buttons <= 8'd0; end else begin if (keyb_valid) begin if (keyb_data == 8'HE0) diff --git a/cores/nes/src/nes.v b/cores/nes/src/nes.v index d0ac510..4270b5e 100644 --- a/cores/nes/src/nes.v +++ b/cores/nes/src/nes.v @@ -93,7 +93,7 @@ endmodule // Data read by PPU will be available on the next clock cycle. // Data read by CPU will be available within at most 2 clock cycles. -module MemoryMultiplex(input clk, input ce, +module MemoryMultiplex(input clk, input ce, input reset, input [21:0] prg_addr, input prg_read, input prg_write, input [7:0] prg_din, input [21:0] chr_addr, input chr_read, input chr_write, input [7:0] chr_din, // Access signals for the SRAM. @@ -108,7 +108,10 @@ module MemoryMultiplex(input clk, input ce, assign memory_read_ppu = chr_read; assign memory_read_cpu = !(chr_read || chr_write) && (prg_read || saved_prg_read); assign memory_dout = chr_write ? chr_din : prg_din; - always @(posedge clk) if (ce) begin + always @(posedge clk) if (reset) begin + saved_prg_read <= 0; + saved_prg_write <= 0; + end else if (ce) begin if (chr_read || chr_write) begin saved_prg_read <= prg_read || saved_prg_read; saved_prg_write <= prg_write || saved_prg_write; @@ -280,12 +283,14 @@ module NES(input clk, input reset, input ce, end // -- Multiplexes CPU and PPU accesses into one single RAM - MemoryMultiplex mem(clk, ce, prg_linaddr, prg_read && prg_allow, prg_write && prg_allow, prg_din, + MemoryMultiplex mem(clk, ce, reset, prg_linaddr, prg_read && prg_allow, prg_write && prg_allow, prg_din, chr_linaddr, chr_read, chr_write && (chr_allow || vram_ce), chr_from_ppu, memory_addr, memory_read_cpu, memory_read_ppu, memory_write, memory_dout); always @* begin - if (apu_cs) begin + if (reset) + from_data_bus <= 0; + else if (apu_cs) begin if (joypad1_cs) from_data_bus = {7'b0100000, joypad_data[0]}; else if (joypad2_cs) From 07b3ca267b1ea1902c333cc2c59ddfe8b9a95af0 Mon Sep 17 00:00:00 2001 From: Sebastien Delestaing Date: Tue, 20 Sep 2016 17:00:45 +0200 Subject: [PATCH 5/5] A lot of fixes to MMC1, some to MMC3 --- cores/nes/src/mmu.v | 57 +++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/cores/nes/src/mmu.v b/cores/nes/src/mmu.v index f35aa91..38a6332 100644 --- a/cores/nes/src/mmu.v +++ b/cores/nes/src/mmu.v @@ -59,16 +59,26 @@ module MMC1(input clk, input ce, input reset, // |++++- Select 16 KB PRG ROM bank (low bit ignored in 32 KB mode) // +----- PRG RAM chip enable (0: enabled; 1: disabled; ignored on MMC1A) reg [4:0] prg_bank; + + reg delay_ctrl; // used to delay fast-write to the control register + wire [3:0] last_prg_index = 4'b1111; // Update shift register always @(posedge clk) if (reset) begin - shift <= 1; - control <= 'hC; + shift <= 1; + control <= 5'b0_11_00; + chr_bank_0 <= 0; + chr_bank_1 <= 0; + prg_bank <= last_prg_index; + delay_ctrl <= 0; end else if (ce) begin - if (prg_write && prg_ain[15]) begin + if (delay_ctrl) + delay_ctrl <= delay_ctrl - 1'b1; + if (prg_write && prg_ain[15] && !delay_ctrl) begin if (prg_din[7]) begin shift <= 5'b10000; - control <= control | 'hC; + control <= control | 5'b0_11_00; + delay_ctrl <= 1'b1; // $write("MMC1 RESET!\n"); end else begin if (shift[0]) begin @@ -88,14 +98,15 @@ module MMC1(input clk, input ce, input reset, end // The PRG bank to load. Each increment here is 16kb. So valid values are 0..15. - reg [3:0] prgsel; + // prg_ain[14] selects bank0 ($8000) or bank1 ($C000) + reg [3:0] prgsel; always @* begin casez({control[3:2], prg_ain[14]}) - 3'b0?_?: prgsel = {prg_bank[3:1], prg_ain[14]}; - 3'b10_0: prgsel = 4'b0000; - 3'b10_1: prgsel = prg_bank[3:0]; - 3'b11_0: prgsel = prg_bank[3:0]; - 3'b11_1: prgsel = 4'b1111; + 3'b0?_?: prgsel = {prg_bank[3:1], prg_ain[14]}; // Swap 32Kb + 3'b10_0: prgsel = 4'b0000; // Swap 16Kb at $C000 with access at $8000, so select page 0 (hardcoded) + 3'b10_1: prgsel = prg_bank[3:0]; // Swap 16Kb at $C000 with $C000 access, so select page based on prg_bank (register 3) + 3'b11_0: prgsel = prg_bank[3:0]; // Swap 16Kb at $8000 with $8000 access, so select page based on prg_bank (register 3) + 3'b11_1: prgsel = last_prg_index; // Swap 16Kb at $8000 with $C000 access, so select last page (hardcoded) endcase end wire [21:0] prg_aout_tmp = {4'b00_00, prgsel, prg_ain[13:0]}; @@ -104,7 +115,7 @@ module MMC1(input clk, input ce, input reset, reg [4:0] chrsel; always @* begin casez({control[4], chr_ain[12]}) - 2'b0_?: chrsel = {chr_bank_0[4:1], chr_ain[12]}; + 2'b0_?: chrsel = {1'b0, chr_bank_0[3:1], chr_ain[12]}; 2'b1_0: chrsel = chr_bank_0; 2'b1_1: chrsel = chr_bank_1; endcase @@ -197,7 +208,7 @@ module MMC2(input clk, input ce, input reset, reg mirroring; reg latch_0, latch_1; - + // Update registers always @(posedge clk) if (ce) begin if (prg_write && prg_ain[15]) begin @@ -297,7 +308,7 @@ module MMC3(input clk, input ce, input reset, bank_select <= 0; prg_rom_bank_mode <= 0; chr_a12_invert <= 0; - mirroring <= 0; + mirroring <= ~flags[14]; // for mapper 206, otherwise it's mapper controlled {irq_enable, irq_reload} <= 0; {irq_latch, counter} <= 0; {ram_enable, ram_protect} <= 0; @@ -1096,8 +1107,16 @@ module Mapper28(input clk, input ce, input reset, // Allow writes to 0x5000 only when launching through the proper mapper ID. wire [7:0] mapper = flags[7:0]; - wire allow_select = (mapper == 8'd28); - + wire allow_select = (mapper == 8'd28); + + wire [7:0] prg_size = flags[13:11] == 0 ? 1 : + flags[13:11] == 1 ? 2 : + flags[13:11] == 2 ? 4 : + flags[13:11] == 3 ? 8 : + flags[13:11] == 4 ? 16 : + flags[13:11] == 5 ? 32 : + flags[13:11] == 6 ? 64 : 128; + always @(posedge clk) if (reset) begin mode[5:2] <= 0; // NROM mode, 32K mode outer[5:0] <= 6'h3f; // last bank @@ -1109,9 +1128,11 @@ module Mapper28(input clk, input ce, input reset, mode[1:0] <= flags[14] ? 2'b10 : 2'b11; // UNROM #2 - Current bank in $8000-$BFFF and fixed top half of outer bank in $C000-$FFFF - if (mapper == 2) - mode[5:2] <= 4'b1111; - + if (mapper == 2) begin + mode[5:4] <= (prg_size == 16)? 2'b11 : 2'b10; // Select 128 or 256Kb PRG ROM + mode[3:2] <= 2'b11; + end + // CNROM #3 - Fixed PRG bank, switchable CHR bank. if (mapper == 3) selreg <= 0;