diff --git a/cores/nes/mist/NES_mist.v b/cores/nes/mist/NES_mist.v index 57dddb5..dae2012 100644 --- a/cores/nes/mist/NES_mist.v +++ b/cores/nes/mist/NES_mist.v @@ -132,14 +132,15 @@ wire [1:0] switches; // it to control the menu on the OSD parameter CONF_STR = { "NES;NES;", - "O1,HQ2X,OFF,ON;", + "O1,HQ2X(VGA-Only),OFF,ON;", "T2,Start;", "T3,Select;", "T4,Reset;" }; -parameter CONF_STR_LEN = 8+15+9+10+9; +parameter CONF_STR_LEN = 8+25+9+10+9; wire [7:0] status; +wire scandoubler_disable; user_io #(.STRLEN(CONF_STR_LEN)) user_io( .conf_str ( CONF_STR ), @@ -152,6 +153,7 @@ user_io #(.STRLEN(CONF_STR_LEN)) user_io( .SWITCHES (switches ), .BUTTONS (buttons ), + .scandoubler_disable(scandoubler_disable), .JOY0 (joyA ), .JOY1 (joyB ), @@ -163,12 +165,6 @@ user_io #(.STRLEN(CONF_STR_LEN)) user_io( .ps2_clk ( ) ); -wire [4:0] nes_r; -wire [4:0] nes_g; -wire [4:0] nes_b; -wire nes_hs; -wire nes_vs; - // if "Start" or "Select" are selected from the menu keep them set for half a second // status 2 and 3 are start and select from the OSD reg [23:0] select_cnt; @@ -193,29 +189,7 @@ wire [7:0] nes_joy_A = { joyB[0], joyB[1], joyB[2], joyB[3], joyB[7] | strt, joyB[6] | sel, joyB[5], joyB[4] }; wire [7:0] nes_joy_B = { joyA[0], joyA[1], joyA[2], joyA[3], joyA[7], joyA[6], joyA[5], joyA[4] }; - -osd #(0,0,4) osd ( - .pclk ( clk ), - - // spi for OSD - .sdi ( SPI_DI ), - .sck ( SPI_SCK ), - .ss ( SPI_SS3 ), - - .red_in ( { nes_r, 1'b0} ), - .green_in ( { nes_g, 1'b0} ), - .blue_in ( { nes_b, 1'b0} ), - .hs_in ( nes_hs ), - .vs_in ( nes_vs ), - - .red_out ( VGA_R ), - .green_out ( VGA_G ), - .blue_out ( VGA_B ), - .hs_out ( VGA_HS ), - .vs_out ( VGA_VS ) -); - wire clock_locked; wire clk85; clk clock_21mhz(.inclk0(CLOCK_27[0]), .c0(clk85), .c1(SDRAM_CLK), .locked(clock_locked)); @@ -250,10 +224,6 @@ osd #(0,0,4) osd ( wire loader_clk; reg [7:0] loader_btn, loader_btn_2; - // NES Palette -> RGB332 conversion - reg [14:0] pallut[0:63]; - initial $readmemh("../src/nes_palette.txt", pallut); - wire [8:0] cycle; wire [8:0] scanline; wire [15:0] sample; @@ -385,20 +355,30 @@ data_io data_io ( .d ( loader_input ) ); - wire [14:0] doubler_pixel; - wire doubler_sync; - wire [9:0] vga_hcounter, doubler_x; - wire [9:0] vga_vcounter; - - VgaDriver vga(clk, nes_hs, nes_vs, nes_r, nes_g, nes_b, vga_hcounter, vga_vcounter, doubler_x, doubler_pixel, doubler_sync, 1'b0); - - wire [14:0] pixel_in = pallut[color]; - Hq2x hq2x(clk, pixel_in, !status[1], // enabled - scanline[8], // reset_frame - (cycle[8:3] == 42), // reset_line - doubler_x, // 0-511 for line 1, or 512-1023 for line 2. - doubler_sync, // new frame has just started - doubler_pixel); // pixel is outputted +wire nes_hs; +wire nes_vs; + +VgaDriver vga( + .clk(clk), + .sdi(SPI_DI), + .sck(SPI_SCK), + .ss(SPI_SS3), + .color(color), + .sync_frame(scanline[8]), + .sync_line((cycle[8:3] == 42)), + .mode(scandoubler_disable), + .vga_smooth(!status[1]), + .border(1'b0), + + .vga_h(nes_hs), + .vga_v(nes_vs), + .VGA_R(VGA_R), + .VGA_G(VGA_G), + .VGA_B(VGA_B) +); + +assign VGA_HS = scandoubler_disable ? ~(nes_hs ^ nes_vs) : nes_hs; +assign VGA_VS = scandoubler_disable ? 1'b1 : nes_vs; assign AUDIO_R = audio; assign AUDIO_L = audio; diff --git a/cores/nes/mist/user_io.v b/cores/nes/mist/user_io.v index 5e99b56..00c2aa2 100644 --- a/cores/nes/mist/user_io.v +++ b/cores/nes/mist/user_io.v @@ -34,6 +34,7 @@ module user_io #(parameter STRLEN=0) ( output [7:0] JOY1, output [1:0] BUTTONS, output [1:0] SWITCHES, + output scandoubler_disable, output reg [7:0] status, @@ -48,12 +49,13 @@ reg [2:0] bit_cnt; // counts bits 0-7 0-7 ... reg [7:0] byte_cnt; // counts bytes reg [7:0] joystick0; reg [7:0] joystick1; -reg [3:0] but_sw; +reg [4:0] but_sw; assign JOY0 = joystick0; assign JOY1 = joystick1; assign BUTTONS = but_sw[1:0]; assign SWITCHES = but_sw[3:2]; +assign scandoubler_disable = but_sw[4]; // this variant of user_io is for 8 bit cores (type == a4) only wire [7:0] core_type = 8'ha4; @@ -164,7 +166,7 @@ always@(posedge SPI_CLK or posedge SPI_SS_IO) begin if(byte_cnt != 0) begin if(cmd == 8'h01) - but_sw <= { sbuf[2:0], SPI_MOSI }; + but_sw <= { sbuf[3:0], SPI_MOSI }; if(cmd == 8'h02) joystick0 <= { sbuf, SPI_MOSI }; diff --git a/cores/nes/src/vga.v b/cores/nes/src/vga.v index 86331d7..47e2d19 100644 --- a/cores/nes/src/vga.v +++ b/cores/nes/src/vga.v @@ -1,47 +1,96 @@ // Copyright (c) 2012-2013 Ludvig Strigeus // This program is GPL Licensed. See COPYING for the full license. -module VgaDriver(input clk, - output reg vga_h, output reg vga_v, - output reg [4:0] vga_r, output reg[4:0] vga_g, output reg[4:0] vga_b, - output [9:0] vga_hcounter, - output [9:0] vga_vcounter, - output [9:0] next_pixel_x, // The pixel we need NEXT cycle. - input [14:0] pixel, // Pixel for current cycle. - input sync, - input border); +module VgaDriver( + input clk, + input [5:0] color, // Pixel for current cycle. + input sync_frame, + input sync_line, + input mode, + input vga_smooth, + input border, + + input sck, + input ss, + input sdi, + + output reg vga_h, + output reg vga_v, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B +); + +// NES Palette -> RGB555 conversion +reg [15:0] pallut[0:63]; +initial $readmemh("nes_palette.txt", pallut); +wire [14:0] pixel = pallut[color][14:0]; + // Horizontal and vertical counters reg [9:0] h, v; -wire hpicture = (h < 512); // 512 lines of picture -wire hsync_on = (h == 512 + 23 + 35); // HSync ON, 23+35 pixels front porch -wire hsync_off = (h == 512 + 23 + 35 + 82); // Hsync off, 82 pixels sync +wire hpicture = (h < 512); // 512 lines of picture +wire hsync_on = (h == 512 + 23 + (mode ? 18 : 35)); // HSync ON, 23+35 pixels front porch +wire hsync_off = (h == 512 + 23 + (mode ? 18 : 35) + 82); // Hsync off, 82 pixels sync wire hend = (h == 681); // End of line, 682 pixels. -wire vpicture = (v < 480); // 480 lines of picture -wire vsync_on = hsync_on && (v == 480 + 10); // Vsync ON, 10 lines front porch. -wire vsync_off = hsync_on && (v == 480 + 12); // Vsync OFF, 2 lines sync signal -wire vend = (v == 523); // End of picture, 524 lines. (Should really be 525 according to NTSC spec) +wire vpicture = (v < (480 >> mode)); // 480 lines of picture +wire vsync_on = hsync_on && (v == (mode ? 240 + 5 : 480 + 10)); // Vsync ON, 10 lines front porch. +wire vsync_off = hsync_on && (v == (mode ? 240 + 14 : 480 + 12)); // Vsync OFF, 2 lines sync signal +wire vend = (v == (523 >> mode)); // End of picture, 524 lines. (Should really be 525 according to NTSC spec) wire inpicture = hpicture && vpicture; -assign vga_hcounter = h; -assign vga_vcounter = v; -wire [9:0] new_h = (hend || sync) ? 0 : h + 1; -assign next_pixel_x = {sync ? 1'b0 : hend ? !v[0] : v[0], new_h[8:0]}; +wire [9:0] new_h = (hend || (mode ? sync_frame : doubler_sync)) ? 10'd0 : h + 10'd1; -always @(posedge clk) begin +wire [14:0] doubler_pixel; +wire doubler_sync; + +Hq2x hq2x(clk, pixel, vga_smooth, // enabled + sync_frame, // reset_frame + sync_line, // reset_line + {doubler_sync ? 1'b0 : hend ? !v[0] : v[0], new_h[8:0]}, // 0-511 for line 1, or 512-1023 for line 2. + doubler_sync, // new frame has just started + doubler_pixel); // pixel is outputted + +reg clk2 = 1'b0; +always @(posedge clk) clk2 <= ~clk2; +wire clkv = mode ? clk2 : clk; + +osd #(10'd0,10'd0,3'd4) osd ( + .pclk(clkv), + + .sck(sck), + .sdi(sdi), + .ss(ss), + + .red_in ({vga_r, 1'b0}), + .green_in({vga_g, 1'b0}), + .blue_in ({vga_b, 1'b0}), + .hs_in(vga_h), + .vs_in(vga_v), + + .red_out(VGA_R), + .green_out(VGA_G), + .blue_out(VGA_B) +); + +reg [4:0] vga_r; +reg [4:0] vga_g; +reg [4:0] vga_b; + +always @(posedge clkv) begin h <= new_h; - if (sync) begin + if(mode ? sync_frame : doubler_sync) begin vga_v <= 1; vga_h <= 1; v <= 0; end else begin - vga_h <= hsync_on ? 0 : hsync_off ? 1 : vga_h; + vga_h <= hsync_on ? 1'b0 : hsync_off ? 1'b1 : vga_h; if (hend) - v <= vend ? 0 : v + 1; - vga_v <= vsync_on ? 0 : vsync_off ? 1 : vga_v; - vga_r <= pixel[4:0]; - vga_g <= pixel[9:5]; - vga_b <= pixel[14:10]; - if (border && (h == 0 || h == 511 || v == 0 || v == 479)) begin + v <= vend ? 10'd0 : v + 10'd1; + vga_v <= vsync_on ? 1'b0 : vsync_off ? 1'b1 : vga_v; + vga_r <= mode ? pixel[4:0] : doubler_pixel[4:0]; + vga_g <= mode ? pixel[9:5] : doubler_pixel[9:5]; + vga_b <= mode ? pixel[14:10] : doubler_pixel[14:10]; + if (border && (h == 0 || h == 511 || v == 0 || v == (479 >> mode))) begin vga_r <= 4'b1111; vga_g <= 4'b1111; vga_b <= 4'b1111;