From 072f355849e9fa57ea10c7352b4a3346ec7f0a4a Mon Sep 17 00:00:00 2001 From: Gyorgy Szombathelyi Date: Wed, 13 Feb 2019 00:42:57 +0100 Subject: [PATCH] [Gameboy] Add GBC support --- cores/gameboy/gb.qsf | 1 + cores/gameboy/gb_mist.v | 36 +++++++-- cores/gameboy/gbc_bios.mif | 107 +++++++++++++++++++++++++ cores/gameboy/gbc_bios.qip | 3 + cores/gameboy/gbc_bios.v | 159 +++++++++++++++++++++++++++++++++++++ cores/gameboy/lcd.v | 77 +++++++++--------- 6 files changed, 340 insertions(+), 43 deletions(-) create mode 100644 cores/gameboy/gbc_bios.mif create mode 100644 cores/gameboy/gbc_bios.qip create mode 100644 cores/gameboy/gbc_bios.v diff --git a/cores/gameboy/gb.qsf b/cores/gameboy/gb.qsf index d6f9229..1251020 100644 --- a/cores/gameboy/gb.qsf +++ b/cores/gameboy/gb.qsf @@ -187,6 +187,7 @@ set_global_assignment -name VERILOG_FILE sprite.v set_global_assignment -name VERILOG_FILE sprite_sort.v set_global_assignment -name VERILOG_FILE timer.v set_global_assignment -name QIP_FILE boot_rom.qip +set_global_assignment -name QIP_FILE gbc_bios.qip set_global_assignment -name VHDL_FILE t80/T80.vhd set_global_assignment -name VHDL_FILE t80/Z80.vhd set_global_assignment -name VHDL_FILE t80/T80_Reg.vhd diff --git a/cores/gameboy/gb_mist.v b/cores/gameboy/gb_mist.v index 96503fb..ed0736e 100644 --- a/cores/gameboy/gb_mist.v +++ b/cores/gameboy/gb_mist.v @@ -68,17 +68,19 @@ wire [7:0] joystick_1; // the configuration string is returned to the io controller to allow // it to control the menu on the OSD parameter CONF_STR = { - "GAMEBOY;GB;", + "GAMEBOY;;", + "F,GBCGB ,Load;", "O1,LCD color,white,yellow;", "O2,Boot,Normal,Fast;", "T3,Reset" }; -parameter CONF_STR_LEN = 11+26+20+8; +parameter CONF_STR_LEN = 9+14+26+20+8; // the status register is controlled by the on screen display (OSD) wire [7:0] status; wire [1:0] buttons; +wire isGBC = dio_index[7:6] == 0; // include user_io module for arm controller communication user_io #(.STRLEN(CONF_STR_LEN)) user_io ( @@ -145,6 +147,7 @@ wire dio_download; wire [23:0] dio_addr; wire [15:0] dio_data; wire dio_write; +wire [7:0] dio_index; // TODO: RAM bank // http://fms.komkon.org/GameBoy/Tech/Carts.html @@ -202,7 +205,7 @@ wire [3:0] mbc5_ram_bank = mbc_ram_bank_reg & ram_mask; // in mode 0 (16/8 mode) the ram bank select signals are the upper rom address lines // in mode 1 (4/32 mode) the upper two rom address lines are 2'b00 -wire [6:0] mbc1_rom_bank_mode = { mbc1_mode?2'b00:mbc_ram_bank_reg, mbc_rom_bank_reg}; +wire [6:0] mbc1_rom_bank_mode = { mbc1_mode?2'b00:mbc_ram_bank_reg[1:0], mbc_rom_bank_reg[4:0]}; // mask address lines to enable proper mirroring wire [6:0] mbc1_rom_bank = mbc1_rom_bank_mode & rom_mask[6:0]; wire [3:0] mbc2_rom_bank = mbc_rom_bank_reg[3:0] & rom_mask[3:0]; //16 @@ -265,6 +268,8 @@ end reg [7:0] cart_mbc_type; reg [7:0] cart_rom_size; reg [7:0] cart_ram_size; +reg [7:0] cart_cgb_flag; +wire isGBC_game = (cart_cgb_flag == 8'h80 || cart_cgb_flag == 8'hC0); // only write sdram if the write attept comes from the cart ram area wire cart_ram_wr = cart_wr && mbc_ram_enable && ((cart_addr[15:13] == 3'b101 && ~mbc2) || (cart_addr[15:9] == 7'b1010000 && mbc2)); @@ -317,10 +322,12 @@ always @(posedge clk64) begin cart_mbc_type <= 8'h00; cart_rom_size <= 8'h00; cart_ram_size <= 8'h00; + cart_cgb_flag <= 8'h00; end else begin if(dio_download && dio_write) begin // cart is stored in 16 bit wide sdram, so addresses are shifted right case(dio_addr) + 24'h142: cart_cgb_flag <= dio_data[15:8]; 24'ha3: cart_mbc_type <= dio_data[7:0]; // $147 24'ha4: { cart_rom_size, cart_ram_size } <= dio_data; // $148/$149 endcase @@ -340,6 +347,7 @@ data_io data_io ( // external ram interface .ioctl_clkref ( clk8 ), + .ioctl_index ( dio_index ), .ioctl_wr ( dio_write ), .ioctl_addr ( dio_addr ), .ioctl_dout ( dio_data ) @@ -353,13 +361,22 @@ wire cart_rd; wire cart_wr; wire lcd_clkena; -wire [1:0] lcd_data; +wire [14:0] lcd_data; wire [1:0] lcd_mode; wire lcd_on; wire [15:0] audio_left; wire [15:0] audio_right; +wire [11:0] bios_addr; +wire [7:0] bios_do; + +gbc_bios gbc_bios ( + .clock ( clk64 ), + .address ( bios_addr ), + .q ( bios_do ) +); + // the gameboy itself gb gb ( .reset ( reset ), @@ -368,6 +385,8 @@ gb gb ( .fast_boot ( status[2] ), .joystick ( joystick ), + .isGBC ( isGBC ), + .isGBC_game ( isGBC_game ), // interface to the "external" game cartridge .cart_addr ( cart_addr ), @@ -376,6 +395,10 @@ gb gb ( .cart_do ( cart_do ), .cart_di ( cart_di ), + //gbc bios interface + .gbc_bios_addr ( bios_addr ), + .gbc_bios_do ( bios_do ), + // audio .audio_l ( audio_left ), .audio_r ( audio_right ), @@ -400,11 +423,12 @@ wire [5:0] video_r, video_g, video_b; wire video_hs, video_vs; lcd lcd ( - .clk64 ( clk64 ), + .clk ( clk64 ), .pclk_en( ce_pix ), - .clk ( clk4 ), + .clk4_en( clk4 ), .tint ( status[1] ), + .isGBC ( isGBC ), // serial interface .clkena ( lcd_clkena ), diff --git a/cores/gameboy/gbc_bios.mif b/cores/gameboy/gbc_bios.mif new file mode 100644 index 0000000..9c068b4 --- /dev/null +++ b/cores/gameboy/gbc_bios.mif @@ -0,0 +1,107 @@ +-- http://srecord.sourceforge.net/ +-- +-- Generated automatically by srec_cat -o --mif +-- +DEPTH = 2304; +WIDTH = 8; +ADDRESS_RADIX = HEX; +DATA_RADIX = HEX; +CONTENT BEGIN +0000: 31 FE FF 3E 02 C3 7C 00 D3 00 98 A0 12 D3 00 80 00 40 1E 53 D0 00 1F 42; +0018: 1C 00 14 2A 4D 19 8C 7E 00 7C 31 6E 4A 45 52 4A 00 00 FF 53 1F 7C FF 03; +0030: 1F 00 FF 1F A7 00 EF 1B 1F 00 EF 1B 00 7C 00 00 FF 03 CE ED 66 66 CC 0D; +0048: 00 0B 03 73 00 83 00 0C 00 0D 00 08 11 1F 88 89 00 0E DC CC 6E E6 DD DD; +0060: D9 99 BB BB 67 63 6E 0E EC CC DD DC 99 9F BB B9 33 3E 3C 42 B9 A5 B9 A5; +0078: 42 3C 58 43 E0 70 3E FC E0 47 CD 75 02 CD 00 02 26 D0 CD 03 02 21 00 FE; +0090: 0E A0 AF 22 0D 20 FC 11 04 01 21 10 80 4C 1A E2 0C CD C6 03 CD C7 03 13; +00A8: 7B FE 34 20 F1 11 72 00 06 08 1A 13 22 23 05 20 F9 CD F0 03 3E 01 E0 4F; +00C0: 3E 91 E0 40 21 B2 98 06 4E 0E 44 CD 91 02 AF E0 4F 0E 80 21 42 00 06 18; +00D8: F2 0C BE 20 FE 23 05 20 F7 21 34 01 06 19 78 86 2C 05 20 FB 86 20 FE CD; +00F0: 1C 03 18 02 00 00 CD D0 05 AF E0 70 3E 11 E0 50 00 00 00 00 00 00 00 00; +0108: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0138: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0168: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0198: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +01B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +01C8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +01E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +01F8: 00 00 00 00 00 00 00 00 21 00 80 AF 22 CB 6C 28 FB C9 2A 12 13 0D 20 FA; +0210: C9 E5 21 0F FF CB 86 CB 46 28 FC E1 C9 11 00 FF 21 03 D0 0E 0F 3E 30 12; +0228: 3E 20 12 1A 2F A1 CB 37 47 3E 10 12 1A 2F A1 B0 4F 7E A9 E6 F0 47 2A A9; +0240: A1 B0 32 47 79 77 3E 30 12 C9 3E 80 E0 68 E0 6A 0E 6B 2A E2 05 20 FB 4A; +0258: 09 43 0E 69 2A E2 05 20 FB C9 C5 D5 E5 21 00 D8 06 01 16 3F 1E 40 CD 4A; +0270: 02 E1 D1 C1 C9 3E 80 E0 26 E0 11 3E F3 E0 12 E0 25 3E 77 E0 24 21 30 FF; +0288: AF 0E 10 22 2F 0D 20 FB C9 CD 11 02 CD 62 02 79 FE 38 20 14 E5 AF E0 4F; +02A0: 21 A7 99 3E 38 22 3C FE 3F 20 FA 3E 01 E0 4F E1 C5 E5 21 43 01 CB 7E CC; +02B8: 89 05 E1 C1 CD 11 02 79 D6 30 D2 06 03 79 FE 01 CA 06 03 7D FE D1 28 21; +02D0: C5 06 03 0E 01 16 03 7E E6 F8 B1 22 15 20 F8 0C 79 FE 06 20 F0 11 11 00; +02E8: 19 05 20 E7 11 A1 FF 19 C1 04 78 1E 83 FE 62 28 06 1E C1 FE 64 20 07 7B; +0300: E0 13 3E 87 E0 14 FA 02 D0 FE 00 28 0A 3D EA 02 D0 79 FE 01 CA 91 02 0D; +0318: C2 91 02 C9 0E 26 CD 4A 03 CD 11 02 CD 62 02 0D 20 F4 CD 11 02 3E 01 E0; +0330: 4F CD 3E 03 CD 41 03 AF E0 4F CD 3E 03 C9 21 08 00 11 51 FF 0E 05 CD 0A; +0348: 02 C9 C5 D5 E5 21 40 D8 0E 20 7E E6 1F FE 1F 28 01 3C 57 2A 07 07 07 E6; +0360: 07 47 3A 07 07 07 E6 18 B0 FE 1F 28 01 3C 0F 0F 0F 47 E6 E0 B2 22 78 E6; +0378: 03 5F 7E 0F 0F E6 1F FE 1F 28 01 3C 07 07 B3 22 0D 20 C7 E1 D1 C1 C9 0E; +0390: 00 1A E6 F0 CB 49 28 02 CB 37 47 23 7E B0 22 1A E6 0F CB 49 20 02 CB 37; +03A8: 47 23 7E B0 22 13 CB 41 28 0D D5 11 F8 FF CB 49 28 03 11 08 00 19 D1 0C; +03C0: 79 FE 18 20 CC C9 47 D5 16 04 58 CB 10 17 CB 13 17 15 20 F6 D1 22 23 22; +03D8: 23 C9 3E 19 EA 10 99 21 2F 99 0E 0C 3D 28 08 32 0D 20 F9 2E 0F 18 F3 C9; +03F0: 3E 01 E0 4F CD 00 02 11 07 06 21 80 80 0E C0 1A 22 23 22 23 13 0D 20 F7; +0408: 11 04 01 CD 8F 03 01 A8 FF 09 CD 8F 03 01 F8 FF 09 11 72 00 0E 08 23 1A; +0420: 22 13 0D 20 F9 21 C2 98 06 08 3E 08 0E 10 22 0D 20 FC 11 10 00 19 05 20; +0438: F3 AF E0 4F 21 C2 98 3E 08 22 3C FE 18 20 02 2E E2 FE 28 20 03 21 02 99; +0450: FE 38 20 ED 21 D8 08 11 40 D8 06 08 3E FF 12 13 12 13 0E 02 CD 0A 02 3E; +0468: 00 12 13 12 13 13 13 05 20 EA CD 62 02 21 4B 01 7E FE 33 20 0B 2E 44 1E; +0480: 30 2A BB 20 49 1C 18 04 2E 4B 1E 01 2A BB 20 3E 2E 34 01 10 00 2A 80 47; +0498: 0D 20 FA EA 00 D0 21 C7 06 0E 00 2A B8 28 08 0C 79 FE 4F 20 F6 18 1F 79; +04B0: D6 41 38 1C 21 16 07 16 00 5F 19 FA 37 01 57 7E BA 28 0D 11 0E 00 19 79; +04C8: 83 4F D6 5E 38 ED 0E 00 21 33 07 06 00 09 7E E6 1F EA 08 D0 7E E6 E0 07; +04E0: 07 07 EA 0B D0 CD E9 04 C9 11 91 07 21 00 D9 FA 0B D0 47 0E 1E CB 40 20; +04F8: 02 13 13 1A 22 20 02 1B 1B CB 48 20 02 13 13 1A 22 13 13 20 02 1B 1B CB; +0510: 50 28 05 1B 2B 1A 22 13 1A 22 13 0D 20 D7 21 00 D9 11 00 DA CD 64 05 C9; +0528: 21 12 00 FA 05 D0 07 07 06 00 4F 09 11 40 D8 06 08 E5 0E 02 CD 0A 02 13; +0540: 13 13 13 13 13 E1 05 20 F0 11 42 D8 0E 02 CD 0A 02 11 4A D8 0E 02 CD 0A; +0558: 02 2B 2B 11 44 D8 0E 02 CD 0A 02 C9 0E 60 2A E5 C5 21 E8 07 06 00 4F 09; +0570: 0E 08 CD 0A 02 C1 E1 0D 20 EC C9 FA 08 D0 11 18 00 3C 3D 28 03 19 20 FA; +0588: C9 CD 1D 02 78 E6 FF 28 0F 21 E4 08 06 00 2A B9 28 08 04 78 FE 0C 20 F6; +05A0: 18 2D 78 EA 05 D0 3E 1E EA 02 D0 11 0B 00 19 56 7A E6 1F 5F 21 08 D0 3A; +05B8: 22 7B 77 7A E6 E0 07 07 07 5F 21 0B D0 3A 22 7B 77 CD E9 04 CD 28 05 C9; +05D0: CD 11 02 FA 43 01 CB 7F 28 04 E0 4C 18 28 3E 04 E0 4C 3E 01 E0 6C 21 00; +05E8: DA CD 7B 05 06 10 16 00 1E 08 CD 4A 02 21 7A 00 FA 00 D0 47 0E 02 2A B8; +0600: CC DA 03 0D 20 F8 C9 01 0F 3F 7E FF FF C0 00 C0 F0 F1 03 7C FC FE FE 03; +0618: 07 07 0F E0 E0 F0 F0 1E 3E 7E FE 0F 0F 1F 1F FF FF 00 00 01 01 01 03 FF; +0630: FF E1 E0 C0 F0 F9 FB 1F 7F F8 E0 F3 FD 3E 1E E0 F0 F9 7F 3E 7C F8 E0 F8; +0648: F0 F0 F8 00 00 7F 7F 07 0F 9F BF 9E 1F FF FF 0F 1E 3E 3C F1 FB 7F 7F FE; +0660: DE DF 9F 1F 3F 3E 3C F8 F8 00 00 03 03 07 07 FF FF C1 C0 F3 E7 F7 F3 C0; +0678: C0 C0 C0 1F 1F 1E 3E 3F 1F 3E 3E 80 00 00 00 7C 1F 07 00 0F FF FE 00 7C; +0690: F8 F0 00 1F 0F 0F 00 7C F8 F8 00 3F 3E 1C 00 0F 0F 0F 00 7C FF FF 00 00; +06A8: F8 F8 00 07 0F 0F 00 81 FF FF 00 F3 E1 80 00 E0 FF 7F 00 FC F0 C0 00 3E; +06C0: 7C 7C 00 00 00 00 00 00 88 16 36 D1 DB F2 3C 8C 92 3D 5C 58 C9 3E 70 1D; +06D8: 59 69 19 35 A8 14 AA 75 95 99 34 6F 15 FF 97 4B 90 17 10 39 F7 F6 A2 49; +06F0: 4E 43 68 E0 8B F0 CE 0C 29 E8 B7 86 9A 52 01 9D; +0700: 71 9C BD 5D 6D 67 3F 6B B3 46 28 A5 C6 D3 27 61 18 66 6A BF 0D F4 42 45; +0718: 46 41 41 52 42 45 4B 45 4B 20 52 2D 55 52 41 52 20 49 4E 41 49 4C 49 43; +0730: 45 20 52 7C 08 12 A3 A2 07 87 4B 20 12 65 A8 16 A9 86 B1 68 A0 87 66 12; +0748: A1 30 3C 12 85 12 64 1B 07 06 6F 6E 6E AE AF 6F B2 AF B2 A8 AB 6F AF 86; +0760: AE A2 A2 12 AF 13 12 A1 6E AF AF AD 06 4C 6E AF AF 12 7C AC A8 6A 6E 13; +0778: A0 2D A8 2B AC 64 AC 6D 87 BC 60 B4 13 72 7C B5 AE AE 7C 7C 65 A2 6C 64; +0790: 85 80 B0 40 88 20 68 DE 00 70 DE 20 78 20 20 38 20 B0 90 20 B0 A0 E0 B0; +07A8: C0 98 B6 48 80 E0 50 1E 1E 58 20 B8 E0 88 B0 10 20 00 10 20 E0 18 E0 18; +07C0: 00 18 E0 20 A8 E0 20 18 E0 00 20 18 D8 C8 18 E0 00 E0 40 28 28 28 18 E0; +07D8: 60 20 18 E0 00 00 08 E0 18 30 D0 D0 D0 20 E0 E8 FF 7F BF 32 D0 00 00 00; +07F0: 9F 63 79 42 B0 15 CB 04 FF 7F 31 6E 4A 45 00 00 FF 7F EF 1B 00 02 00 00; +0808: FF 7F 1F 42 F2 1C 00 00 FF 7F 94 52 4A 29 00 00 FF 7F FF 03 2F 01 00 00; +0820: FF 7F EF 03 D6 01 00 00 FF 7F B5 42 C8 3D 00 00 74 7E FF 03 80 01 00 00; +0838: FF 67 AC 77 13 1A 6B 2D D6 7E FF 4B 75 21 00 00 FF 53 5F 4A 52 7E 00 00; +0850: FF 4F D2 7E 4C 3A E0 1C ED 03 FF 7F 5F 25 00 00 6A 03 1F 02 FF 03 FF 7F; +0868: FF 7F DF 01 12 01 00 00 1F 23 5F 03 F2 00 09 00 FF 7F EA 03 1F 01 00 00; +0880: 9F 29 1A 00 0C 00 00 00 FF 7F 7F 02 1F 00 00 00 FF 7F E0 03 06 02 20 01; +0898: FF 7F EB 7E 1F 00 00 7C FF 7F FF 3F 00 7E 1F 00 FF 7F FF 03 1F 00 00 00; +08B0: FF 03 1F 00 0C 00 00 00 FF 7F 3F 03 93 01 00 00 00 00 00 42 7F 03 FF 7F; +08C8: FF 7F 8C 7E 00 7C 00 00 FF 7F EF 1B 80 61 00 00 FF 7F 00 7C E0 03 1F 7C; +08E0: 1F 00 FF 03 40 41 42 20 21 22 80 81 82 10 11 12 12 B0 79 B8 AD 16 17 07; +08F8: BA 05 7C 13 00 00 00 00; +END; diff --git a/cores/gameboy/gbc_bios.qip b/cores/gameboy/gbc_bios.qip new file mode 100644 index 0000000..69bd964 --- /dev/null +++ b/cores/gameboy/gbc_bios.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "gbc_bios.v"] diff --git a/cores/gameboy/gbc_bios.v b/cores/gameboy/gbc_bios.v new file mode 100644 index 0000000..fa5026d --- /dev/null +++ b/cores/gameboy/gbc_bios.v @@ -0,0 +1,159 @@ +// megafunction wizard: %ROM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: gbc_bios.v +// Megafunction Name(s): +// altsyncram +// +// Simulation Library Files(s): +// altera_mf +// ============================================================ +// ************************************************************ +// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +// +// 13.1.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 Altera Corporation +//Your use of Altera Corporation's design tools, logic functions +//and other software and tools, and its AMPP partner logic +//functions, and any output files from any of the foregoing +//(including device programming or simulation files), and any +//associated documentation or information are expressly subject +//to the terms and conditions of the Altera Program License +//Subscription Agreement, Altera MegaCore Function License +//Agreement, or other applicable license agreement, including, +//without limitation, that your use is for the sole purpose of +//programming logic devices manufactured by Altera and sold by +//Altera or its authorized distributors. Please refer to the +//applicable agreement for further details. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module gbc_bios ( + address, + clock, + q); + + input [11:0] address; + input clock; + output [7:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [7:0] sub_wire0; + wire [7:0] q = sub_wire0[7:0]; + + altsyncram altsyncram_component ( + .address_a (address), + .clock0 (clock), + .q_a (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .addressstall_a (1'b0), + .addressstall_b (1'b0), + .byteena_a (1'b1), + .byteena_b (1'b1), + .clock1 (1'b1), + .clocken0 (1'b1), + .clocken1 (1'b1), + .clocken2 (1'b1), + .clocken3 (1'b1), + .data_a ({8{1'b1}}), + .data_b (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_a (1'b0), + .wren_b (1'b0)); + defparam + altsyncram_component.address_aclr_a = "NONE", + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.init_file = "gbc_bios.mif", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 4096, + altsyncram_component.operation_mode = "ROM", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.widthad_a = 12, + altsyncram_component.width_a = 8, + altsyncram_component.width_byteena_a = 1; + + +endmodule + +// ============================================================ +// CNX file retrieval info +// ============================================================ +// Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0" +// Retrieval info: PRIVATE: AclrAddr NUMERIC "0" +// Retrieval info: PRIVATE: AclrByte NUMERIC "0" +// Retrieval info: PRIVATE: AclrOutput NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0" +// Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8" +// Retrieval info: PRIVATE: BlankMemory NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0" +// Retrieval info: PRIVATE: Clken NUMERIC "0" +// Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0" +// Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A" +// Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0" +// Retrieval info: PRIVATE: JTAG_ID STRING "NONE" +// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0" +// Retrieval info: PRIVATE: MIFfilename STRING "gbc_bios.mif" +// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegOutput NUMERIC "1" +// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0" +// Retrieval info: PRIVATE: SingleClock NUMERIC "1" +// Retrieval info: PRIVATE: UseDQRAM NUMERIC "0" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "12" +// Retrieval info: PRIVATE: WidthData NUMERIC "8" +// Retrieval info: PRIVATE: rden NUMERIC "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: INIT_FILE STRING "gbc_bios.mif" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram" +// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "8" +// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1" +// Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL "address[11..0]" +// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock" +// Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]" +// Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 0 +// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL gbc_bios.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL gbc_bios.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL gbc_bios.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL gbc_bios.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL gbc_bios_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL gbc_bios_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/cores/gameboy/lcd.v b/cores/gameboy/lcd.v index 985a1d3..d2d8958 100644 --- a/cores/gameboy/lcd.v +++ b/cores/gameboy/lcd.v @@ -4,24 +4,25 @@ // The gameboy lcd runs from a shift register which is filled at 4194304 pixels/sec module lcd ( - input clk64, input clk, + input clk4_en, input clkena, - input [1:0] data, + input [14:0] data, input [1:0] mode, + input isGBC, input tint, // pixel clock input pclk_en, input on, - - // VGA output - output reg hs, - output reg vs, - output [5:0] r, - output [5:0] g, - output [5:0] b + + // VGA output + output reg hs, + output reg vs, + output [5:0] r, + output [5:0] g, + output [5:0] b ); // Mode 00: h-blank @@ -30,25 +31,27 @@ module lcd ( // Mode 11: oam and vram // space for 2*160 pixel -reg [7:0] shift_reg_wptr; +reg [8:0] shift_reg_wptr; reg p_toggle; -reg [1:0] shift_reg [511:0]; +reg [14:0] shift_reg [511:0]; reg [1:0] last_mode_in; // shift register input always @(posedge clk) begin - last_mode_in <= mode; - // end of vsync - if(clkena) begin - shift_reg[{p_toggle, shift_reg_wptr}] <= data; - shift_reg_wptr <= shift_reg_wptr + 8'd1; - end - - // reset write pointer at end of hsync phase - if((mode != 2'b00) && (last_mode_in == 2'b00)) begin - shift_reg_wptr <= 8'd0; - p_toggle <= !p_toggle; + if(clk4_en) begin + if(clkena) begin + shift_reg[shift_reg_wptr] <= data; + shift_reg_wptr <= {p_toggle, shift_reg_wptr[7:0] + 1'd1}; + end + + last_mode_in <= mode; + + // reset write pointer at end of hsync phase + if((mode != 2'b00) && (last_mode_in == 2'b00)) begin + shift_reg_wptr <= 0; + p_toggle <= !p_toggle; + end end end @@ -70,12 +73,12 @@ reg[9:0] v_cnt; // vertical pixel counter // horizontal pixel counter reg [1:0] last_mode_h; -always@(posedge clk64) begin +always@(posedge clk) begin if (pclk_en) begin last_mode_h <= mode; if(h_cnt==H+HFP+HS+HBP-1) h_cnt <= 0; - else h_cnt <= h_cnt + 1; + else h_cnt <= h_cnt + 1'd1; // generate negative hsync signal if(h_cnt == H+HFP) hs <= 1'b0; @@ -90,12 +93,12 @@ end // veritical pixel counter reg [1:0] last_mode_v; -always@(posedge clk64) begin +always@(posedge clk) begin if (pclk_en) begin // the vertical counter is processed at the begin of each hsync if(h_cnt == H+HFP+HS+HBP-1) begin if(v_cnt==VS+VFP+V+VBP-1) v_cnt <= 0; - else v_cnt <= v_cnt + 1; + else v_cnt <= v_cnt + 1'd1; // generate positive vsync signal if(v_cnt == V+VFP) vs <= 1'b1; @@ -107,7 +110,7 @@ always@(posedge clk64) begin // end of mode 01 (vblank) // make and offset of - 4 for the 4 line delay of the scandoubler if((mode != 2'b01) && (last_mode_v == 2'b01)) - v_cnt <= 616-4; + v_cnt <= 10'd616-10'd4; end end end @@ -116,24 +119,24 @@ end // ------------------------------- pixel generator ------------------------------- // ------------------------------------------------------------------------------- reg blank; -reg [1:0] pixel_reg; -reg [7:0] shift_reg_rptr; +reg [14:0] pixel_reg; +reg [8:0] shift_reg_rptr; -always@(posedge clk64) begin +always@(posedge clk) begin if (pclk_en) begin // visible area? if((v_cnt < V) && (h_cnt < H)) begin blank <= 1'b0; - pixel_reg <= shift_reg[{!p_toggle, shift_reg_rptr}]; - shift_reg_rptr <= shift_reg_rptr + 8'd1; + pixel_reg <= shift_reg[shift_reg_rptr]; + shift_reg_rptr <= {!p_toggle, shift_reg_rptr[7:0] + 1'd1}; end else begin blank <= 1'b1; - shift_reg_rptr <= 8'd0; + shift_reg_rptr <= 0; end end end -wire [1:0] pixel = on?pixel_reg:2'b00; +wire [14:0] pixel = on?pixel_reg:15'd0; // gameboy "color" palette wire [5:0] yellow_r = (pixel==0)?6'b100111:(pixel==1)?6'b100000: // 1:100011 @@ -146,8 +149,8 @@ wire [5:0] yellow_b = (pixel==0)?6'b000100:(pixel==1)?6'b000010: // 1:000100 // greyscale wire [5:0] grey = (pixel==0)?6'd63:(pixel==1)?6'd42:(pixel==2)?6'd24:6'd0; -assign r = blank?6'b000000:tint?yellow_r:grey; -assign g = blank?6'b000000:tint?yellow_g:grey; -assign b = blank?6'b000000:tint?yellow_b:grey; +assign r = blank?6'b000000:isGBC ? {pixel_reg [4: 0], 1'b0} : (tint?yellow_r:grey); +assign g = blank?6'b000000:isGBC ? {pixel_reg [9: 5], 1'b0} : (tint?yellow_g:grey); +assign b = blank?6'b000000:isGBC ? {pixel_reg[14:10], 1'b0} : (tint?yellow_b:grey); endmodule