1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-02-12 02:27:03 +00:00

Merge pull request #35 from sebdel/master

[NES] Stabilization and MMC1 fixes by Sebdel
This commit is contained in:
Newsdee
2016-09-20 23:28:48 +08:00
committed by GitHub
6 changed files with 93 additions and 62 deletions

View File

@@ -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;
@@ -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;
@@ -270,21 +264,31 @@ 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
// 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,9 +296,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 run_mem = (nes_ce == 0) && !reset_nes;
wire reset_nes = (init_reset || buttons[1] || arm_reset || reset_osd || download_reset);
wire run_nes = (nes_ce == 3) && !reset_nes;
// NES is clocked at every 4th cycle.

View File

@@ -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)

View File

@@ -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
// ---------------------------------------------------------------------

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;