Merge pull request #211 from paulb-nl/2p_wisdom

2p New release & Add Wisdom Tree / Mani 161 mappers & mapper selection.
This commit is contained in:
Alexey Melnikov
2022-08-09 04:05:11 +08:00
committed by GitHub
24 changed files with 3868 additions and 3148 deletions

View File

@@ -104,5 +104,41 @@ CONTENT BEGIN
08C8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00;
08E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00;
08F8: 00 00 00 00 00 00 00 00;
[0900..0FFF]: 00;
-- DMG
0900: 31 FE FF AF 21 FF 9F 32 CB 7C 20 FB 21 26 FF 0E;
0910: 11 3E 80 32 E2 0C 3E F3 E2 32 3E 77 77 3E FC E0;
0920: 47 F0 50 FE 42 28 75 11 04 01 21 10 80 1A 4F CD;
0930: A0 00 CD A0 00 13 7B FE 34 20 F2 11 B2 00 06 08;
0940: 1A 22 22 13 05 20 F9 3E 19 EA 10 99 21 2F 99 0E;
0950: 0C 3D 28 08 32 0D 20 F9 2E 0F 18 F3 67 3E 64 57;
0960: E0 42 3E 91 E0 40 04 1E 02 0E 0C F0 44 FE 90 20;
0970: FA 0D 20 F7 1D 20 F2 0E 13 24 7C 1E 83 FE 62 28;
0980: 06 1E C1 FE 64 20 06 7B E2 0C 3E 87 E2 F0 42 90;
0990: E0 42 15 20 D2 05 20 64 16 20 18 CB E0 40 18 5C;
09A0: 06 04 C5 CB 11 17 C1 CB 11 17 05 20 F5 22 23 22;
09B0: 23 C9 3C 42 B9 A5 B9 A5 42 3C FF FF FF FF FF FF;
09C0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF;
09D0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF;
09E0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF;
09F0: FF FF FF FF FF FF FF FF FF FF FF FF 3E 01 E0 50;
--SGB
0A00: 31 FE FF 21 00 80 22 CB 6C 28 FB 3E 80 E0 26 E0;
0A10: 11 3E F3 E0 12 E0 25 3E 77 E0 24 3E 00 E0 47 11;
0A20: 04 01 21 10 80 1A 47 CD C9 00 CD C9 00 13 7B EE;
0A30: 34 20 F2 11 EA 00 0E 08 1A 13 22 23 0D 20 F9 3E;
0A40: 19 EA 10 99 21 2F 99 0E 0C 3D 28 08 32 0D 20 F9;
0A50: 2E 0F 18 F5 3E 91 E0 40 3E F1 E0 80 21 04 01 AF;
0A60: 4F AF E2 3E 30 E2 F0 80 CD B7 00 E5 06 0E 16 00;
0A70: CD AD 00 82 57 05 20 F8 CD B7 00 E1 06 0E CD AD;
0A80: 00 CD B7 00 05 20 F7 3E 20 E2 3E 30 E2 F0 80 C6;
0A90: 02 E0 80 3E 58 BD 20 C9 0E 13 3E C1 E2 0C 3E 07;
0AA0: E2 3E FC E0 47 3E 01 21 60 C0 C3 FE 00 3E 4F BD;
0AB0: 38 02 2A C9 23 AF C9 5F 16 08 3E 10 CB 1B 38 01;
0AC0: 87 E2 3E 30 E2 15 C8 18 F1 3E 04 0E 00 CB 20 F5;
0AD0: CB 11 F1 CB 11 3D 20 F5 79 22 23 22 23 C9 E5 21;
0AE0: 0F FF CB 86 CB 46 28 FC E1 C9 3C 42 B9 A5 B9 A5;
0AF0: 42 3C 00 00 00 00 00 00 00 00 00 00 00 00 E0 50;
[0B00..0FFF]: 00;
END;

View File

@@ -30,7 +30,7 @@ module emu
input RESET,
//Must be passed to hps_io module
inout [45:0] HPS_BUS,
inout [48:0] HPS_BUS,
//Base video clock. Usually equals to CLK_SYS.
output CLK_VIDEO,
@@ -53,13 +53,14 @@ module emu
output VGA_F1,
output [1:0] VGA_SL,
output VGA_SCALER, // Force VGA scaler
output VGA_DISABLE, // analog out is off
input [11:0] HDMI_WIDTH,
input [11:0] HDMI_HEIGHT,
output HDMI_FREEZE,
output HDMI_FREEZE,
`ifdef MISTER_FB
// Use framebuffer in DDRAM (USE_FB=1 in qsf)
// Use framebuffer in DDRAM
// FB_FORMAT:
// [2:0] : 011=8bpp(palette) 100=16bpp 101=24bpp 110=32bpp
// [3] : 0=16bits 565 1=16bits 1555
@@ -187,6 +188,7 @@ assign LED_POWER = 0;
assign BUTTONS = 0;
assign HDMI_FREEZE = 0;
assign VGA_SCALER= 0;
assign VGA_DISABLE = 0;
assign AUDIO_MIX = status[8:7];
@@ -202,13 +204,14 @@ assign DDRAM_WE = 0;
// 0 1 2 3 4 5 6
// 01234567890123456789012345678901 23456789012345678901234567890123
// 0123456789ABCDEFGHIJKLMNOPQRSTUV 0123456789ABCDEFGHIJKLMNOPQRSTUV
// XXXXXX XXXXXXXXXXXXXXXXX X
// XXXXXX XXXX XXXXXXXXXXXX X XXXXX
`include "build_id.v"
localparam CONF_STR = {
"GAMEBOY2P;SS3E000000:40000;",
"FS1,GBCGB ,Load ROM;",
"OEF,System,Auto,Gameboy,Gameboy Color;",
"FS1,GBCGB BIN,Load ROM;",
"OEF,System,Auto,Gameboy,Gameboy Color,MegaDuck;",
"D7o79,Mapper,Auto,WisdomTree,Mani161,MBC1,MBC3;",
"-;",
"h2R9,Load Backup RAM;",
"h2RA,Save Backup RAM;",
@@ -219,6 +222,7 @@ localparam CONF_STR = {
"P1-;",
"P1ON,Seperator Line,Off,On;",
"P1OC,Inverted color,No,Yes;",
"h6P1o5,Use GBA Mode,No,Yes;",
"P1O12,Custom Palette,Off,Auto,On;",
"h1P1FC3,GBP,Load Palette;",
"P1-;",
@@ -233,7 +237,11 @@ localparam CONF_STR = {
"P2,Misc.;",
"P2-;",
"P2OB,Boot,Normal,Fast;",
"P2FC4,BIN,Load GBC Boot;",
"P2FC5,BIN,Load DMG Boot;",
"P2FC6,BIN,Load SGB Boot;",
"P2-;",
"P2o6,Rumble,On,Off;",
"-;",
"R0,Reset;",
@@ -288,9 +296,14 @@ wire sd_buff_wr;
wire img_mounted;
wire img_readonly;
wire [63:0] img_size;
wire [15:0] joy0_rumble, joy1_rumble;
wire [32:0] RTC_time;
wire sys_auto = (status[15:14] == 0);
wire sys_gbc = (status[15:14] == 2);
wire sys_megaduck = (status[15:14] == 3);
hps_io #(.CONF_STR(CONF_STR), .WIDE(1)) hps_io
(
.clk_sys(clk_sys),
@@ -318,7 +331,7 @@ hps_io #(.CONF_STR(CONF_STR), .WIDE(1)) hps_io
.buttons(buttons),
.status(status),
.status_menumask({1'b0,isGBC,(cart1_ready & cart2_ready),sav_supported,|tint,1'b0}),
.status_menumask({sys_megaduck,using_real_cgb_bios,1'b0,isGBC,(cart1_ready & cart2_ready),sav_supported,|tint,1'b0}),
.status_in(status),
.status_set(1'b0),
.direct_video(direct_video),
@@ -331,6 +344,9 @@ hps_io #(.CONF_STR(CONF_STR), .WIDE(1)) hps_io
.joystick_3(joystick_3),
.joystick_l_analog_0(joystick_analog_0),
.joystick_l_analog_1(joystick_analog_1),
.joystick_0_rumble(joy0_rumble),
.joystick_1_rumble(joy1_rumble),
.ps2_key(ps2_key),
@@ -363,9 +379,13 @@ wire [22:0] mbc2_addr;
wire gb2_nCS;
wire cart_download = ioctl_download && (filetype == 8'h01 || filetype == 8'h41 || filetype == 8'h80);
wire cart_download = ioctl_download && (filetype[5:0] == 6'h01 || filetype == 8'h80);
wire md_download = ioctl_download && (filetype == 8'h81);
wire palette_download = ioctl_download && (filetype == 3 /*|| !filetype*/);
wire bios_download = ioctl_download && (filetype == 8'h40);
wire cgb_boot_download = ioctl_download && (filetype == 4);
wire dmg_boot_download = ioctl_download && (filetype == 5);
wire sgb_boot_download = ioctl_download && (filetype == 6);
wire boot_download = cgb_boot_download | dmg_boot_download | sgb_boot_download;
wire [1:0] sdram_ds = cart_download ? 2'b11 : {mbc1_addr[0], ~mbc1_addr[0]};
wire [15:0] sdram_do;
@@ -427,10 +447,15 @@ wire cart_has_save;
wire [31:0] RTC_timestampOut;
wire [47:0] RTC_savedtimeOut;
wire RTC_inuse;
wire rumbling1, rumbling2;
wire [2:0] mapper_sel = status[41:39];
reg [127:0] palette = 128'h828214517356305A5F1A3B4900000000;
reg using_real_cgb_bios = 0;
always @(posedge clk_sys) begin
if (cgb_boot_download)
using_real_cgb_bios <= 1;
if (palette_download & ioctl_wr) begin
palette[127:0] <= {palette[111:0], ioctl_dout[7:0], ioctl_dout[15:8]};
end
@@ -438,18 +463,29 @@ end
assign AUDIO_S = 0;
wire reset = (RESET | status[0] | buttons[1] | cart_download | bk_loading);
wire reset = (RESET | status[0] | buttons[1] | cart_download | boot_download | bk_loading);
reg megaduck = 0;
reg isGBC = 0;
always @(posedge clk_sys) if(reset) begin
if(status[15:14]) isGBC <= status[15];
else if(cart_download) isGBC <= !filetype[7:4];
if (cart_download)
megaduck <= sys_megaduck;
if (md_download)
megaduck <= sys_auto || sys_megaduck;
if(~sys_auto) isGBC <= sys_gbc;
else if(cart_download) begin
if (!filetype[5:0]) isGBC <= isGBC_game;
else isGBC <= !filetype[7:6];
end
end
// core 1
wire speed1;
wire SaveStateBus_rst1;
assign joy0_rumble = {8'd0, ((rumbling1 & ~status[38]) ? 8'd128 : 8'd0)};
cart_top cart1 (
.reset ( reset ),
@@ -457,6 +493,8 @@ cart_top cart1 (
.ce_cpu ( ce1_cpu ),
.ce_cpu2x ( ce1_cpu2x ),
.speed ( speed1 ),
.megaduck ( megaduck ),
.mapper_sel ( mapper_sel ),
.cart_addr ( cart1_addr ),
.cart_a15 ( cart1_a15 ),
@@ -518,7 +556,9 @@ cart_top cart1 (
.Savestate_CRAMAddr ( 0 ),
.Savestate_CRAMRWrEn ( 0 ),
.Savestate_CRAMWriteData( 0 ),
.Savestate_CRAMReadData ( )
.Savestate_CRAMReadData ( ),
.rumbling (rumbling1)
);
wire [15:0] AUDIO_L1;
@@ -532,11 +572,10 @@ gb gb1 (
.ce ( ce1_cpu ), // the whole gameboy runs on 4mhnz
.ce_2x ( ce1_cpu2x ), // ~8MHz in dualspeed mode (GBC)
.fast_boot ( status[11] ),
.isGBC ( isGBC ),
.isGBC_game ( isGBC_game ),
.isSGB ( 1'b0 ),
.megaduck ( megaduck ),
.joy_p54 ( joy1_p54 ),
.joy_din ( joy1_do ),
@@ -552,9 +591,14 @@ gb gb1 (
.nCS ( gb1_nCS ),
//gbc bios interface
.gbc_bios_addr ( bios1_addr ),
.gbc_bios_do ( bios1_do ),
.boot_gba_en ( status[37] && using_real_cgb_bios ),
.cgb_boot_download ( cgb_boot_download ),
.dmg_boot_download ( dmg_boot_download ),
.sgb_boot_download ( sgb_boot_download ),
.ioctl_wr ( ioctl_wr ),
.ioctl_addr ( ioctl_addr ),
.ioctl_dout ( ioctl_dout ),
// audio
.audio_l ( AUDIO_L1 ),
@@ -622,24 +666,12 @@ wire [3:0] joy1_dir = ~{ joystick_0[2], joystick_0[3], joystick_0[1], joysti
wire [3:0] joy1_buttons = ~{ joystick_0[7], joystick_0[6], joystick_0[5], joystick_0[4] } | {4{joy1_p54[1]}};
wire [3:0] joy1_do = joy1_dir & joy1_buttons;
wire [7:0] bios1_do;
wire [11:0] bios1_addr;
dpram_dif #(12,8,11,16,"BootROMs/cgb_boot.mif") boot_rom_gbc1 (
.clock (clk_sys),
.address_a (bios1_addr),
.q_a (bios1_do),
.address_b (ioctl_addr[11:1]),
.wren_b (ioctl_wr && bios_download),
.data_b (ioctl_dout)
);
// core 2
wire speed2;
wire SaveStateBus_rst2;
assign joy1_rumble = {8'd0, ((rumbling2 & ~status[38]) ? 8'd128 : 8'd0)};
cart_top cart2 (
.reset ( reset ),
@@ -647,6 +679,8 @@ cart_top cart2 (
.ce_cpu ( ce2_cpu ),
.ce_cpu2x ( ce2_cpu2x ),
.speed ( speed2 ),
.megaduck ( megaduck ),
.mapper_sel ( mapper_sel ),
.cart_addr ( cart2_addr ),
.cart_a15 ( cart2_a15 ),
@@ -708,7 +742,9 @@ cart_top cart2 (
.Savestate_CRAMAddr ( 0 ),
.Savestate_CRAMRWrEn ( 0 ),
.Savestate_CRAMWriteData( 0 ),
.Savestate_CRAMReadData ( )
.Savestate_CRAMReadData ( ),
.rumbling (rumbling2)
);
wire [15:0] AUDIO_L2;
@@ -722,11 +758,11 @@ gb gb2 (
.ce ( ce2_cpu ), // the whole gameboy runs on 4mhnz
.ce_2x ( ce2_cpu2x ), // ~8MHz in dualspeed mode (GBC)
.fast_boot ( status[11] ),
.isGBC ( isGBC ),
.isGBC_game ( isGBC_game ),
.isSGB ( 1'b0 ),
.megaduck ( megaduck ),
.joy_p54 ( joy2_p54 ),
.joy_din ( joy2_do ),
@@ -742,9 +778,14 @@ gb gb2 (
.nCS ( gb2_nCS ),
//gbc bios interface
.gbc_bios_addr ( bios2_addr ),
.gbc_bios_do ( bios2_do ),
.boot_gba_en ( status[37] && using_real_cgb_bios ),
.cgb_boot_download ( cgb_boot_download ),
.dmg_boot_download ( dmg_boot_download ),
.sgb_boot_download ( sgb_boot_download ),
.ioctl_wr ( ioctl_wr ),
.ioctl_addr ( ioctl_addr ),
.ioctl_dout ( ioctl_dout ),
// audio
.audio_l ( AUDIO_L2 ),
@@ -812,20 +853,6 @@ wire [3:0] joy2_dir = ~{ joystick_1[2], joystick_1[3], joystick_1[1], joysti
wire [3:0] joy2_buttons = ~{ joystick_1[7], joystick_1[6], joystick_1[5], joystick_1[4] } | {4{joy2_p54[1]}};
wire [3:0] joy2_do = joy2_dir & joy2_buttons;
wire [7:0] bios2_do;
wire [11:0] bios2_addr;
dpram_dif #(12,8,11,16,"BootROMs/cgb_boot.mif") boot_rom_gbc2 (
.clock (clk_sys),
.address_a (bios2_addr),
.q_a (bios2_do),
.address_b (ioctl_addr[11:1]),
.wren_b (ioctl_wr && bios_download),
.data_b (ioctl_dout)
);
assign AUDIO_L = (status[17:16] == 3'd0) ? AUDIO_L1 :
(status[17:16] == 3'd1) ? AUDIO_L2 :
(status[17:16] == 3'd2) ? ({1'b0, AUDIO_L1[15:1]} + {1'b0, AUDIO_L2[15:1]}) :

View File

@@ -3,8 +3,8 @@ set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/ddram.sv
set_global_assignment -name VHDL_FILE rtl/spram.vhd
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
set_global_assignment -name VHDL_FILE rtl/boot_rom.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/cheatcodes.sv
set_global_assignment -name SYSTEMVERILOG_FILE rtl/megaswizzle.sv
set_global_assignment -name VERILOG_FILE rtl/video.v
set_global_assignment -name VERILOG_FILE rtl/timer.v
set_global_assignment -name VERILOG_FILE rtl/sprites.v
@@ -15,6 +15,7 @@ set_global_assignment -name VHDL_FILE rtl/bus_savestates.vhd
set_global_assignment -name VHDL_FILE rtl/reg_savestates.vhd
set_global_assignment -name VHDL_FILE rtl/gb_statemanager.vhd
set_global_assignment -name VHDL_FILE rtl/gb_savestates.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/savestate_ui.sv
set_global_assignment -name VERILOG_FILE rtl/gb.v
set_global_assignment -name VERILOG_FILE rtl/hdma.v
set_global_assignment -name VERILOG_FILE rtl/link.v
@@ -34,6 +35,7 @@ set_global_assignment -name VERILOG_FILE rtl/mappers/gb_camera.v
set_global_assignment -name VERILOG_FILE rtl/mappers/tama.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/mappers/rocket.sv
set_global_assignment -name VERILOG_FILE rtl/mappers/sachen.v
set_global_assignment -name VERILOG_FILE rtl/mappers/megaduck.v
set_global_assignment -name VERILOG_FILE rtl/mappers/misc.v
set_global_assignment -name SDC_FILE Gameboy.sdc
set_global_assignment -name SYSTEMVERILOG_FILE rtl/savestate_ui.sv
set_global_assignment -name SYSTEMVERILOG_FILE Gameboy.sv

Binary file not shown.

View File

@@ -1,107 +0,0 @@
library ieee;
use ieee.std_logic_1164.all,ieee.numeric_std.all;
entity boot_rom is
port (
clk : in std_logic;
addr : in std_logic_vector(7 downto 0);
data : out std_logic_vector(7 downto 0)
);
end entity;
architecture prom of boot_rom is
type rom is array(0 to 255) of std_logic_vector(7 downto 0);
signal rom_data: rom := (
X"31",X"FE",X"FF",X"AF",X"21",X"FF",X"9F",X"32",X"CB",X"7C",X"20",X"FB",X"21",X"26",X"FF",X"0E",
X"11",X"3E",X"80",X"32",X"E2",X"0C",X"3E",X"F3",X"E2",X"32",X"3E",X"77",X"77",X"3E",X"FC",X"E0",
X"47",X"F0",X"50",X"FE",X"42",X"28",X"75",X"11",X"04",X"01",X"21",X"10",X"80",X"1A",X"4F",X"CD",
X"A0",X"00",X"CD",X"A0",X"00",X"13",X"7B",X"FE",X"34",X"20",X"F2",X"11",X"B2",X"00",X"06",X"08",
X"1A",X"22",X"22",X"13",X"05",X"20",X"F9",X"3E",X"19",X"EA",X"10",X"99",X"21",X"2F",X"99",X"0E",
X"0C",X"3D",X"28",X"08",X"32",X"0D",X"20",X"F9",X"2E",X"0F",X"18",X"F3",X"67",X"3E",X"64",X"57",
X"E0",X"42",X"3E",X"91",X"E0",X"40",X"04",X"1E",X"02",X"0E",X"0C",X"F0",X"44",X"FE",X"90",X"20",
X"FA",X"0D",X"20",X"F7",X"1D",X"20",X"F2",X"0E",X"13",X"24",X"7C",X"1E",X"83",X"FE",X"62",X"28",
X"06",X"1E",X"C1",X"FE",X"64",X"20",X"06",X"7B",X"E2",X"0C",X"3E",X"87",X"E2",X"F0",X"42",X"90",
X"E0",X"42",X"15",X"20",X"D2",X"05",X"20",X"64",X"16",X"20",X"18",X"CB",X"E0",X"40",X"18",X"5C",
X"06",X"04",X"C5",X"CB",X"11",X"17",X"C1",X"CB",X"11",X"17",X"05",X"20",X"F5",X"22",X"23",X"22",
X"23",X"C9",X"3C",X"42",X"B9",X"A5",X"B9",X"A5",X"42",X"3C",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",
X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",
X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",
X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",
X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"FF",X"3E",X"01",X"E0",X"50");
begin
data <= rom_data(to_integer(unsigned(addr))) when rising_edge(clk);
end architecture;
library ieee;
use ieee.std_logic_1164.all,ieee.numeric_std.all;
entity fast_boot_rom is
port (
clk : in std_logic;
addr : in std_logic_vector(7 downto 0);
data : out std_logic_vector(7 downto 0)
);
end entity;
architecture prom of fast_boot_rom is
type rom is array(0 to 255) of std_logic_vector(7 downto 0);
signal rom_data: rom := (
X"31",X"FE",X"FF",X"21",X"00",X"80",X"22",X"CB",X"6C",X"28",X"FB",X"3E",X"80",X"E0",X"26",X"E0",
X"11",X"3E",X"F3",X"E0",X"12",X"E0",X"25",X"3E",X"77",X"E0",X"24",X"3E",X"FC",X"E0",X"47",X"11",
X"04",X"01",X"21",X"10",X"80",X"1A",X"47",X"CD",X"82",X"00",X"CD",X"82",X"00",X"13",X"7B",X"EE",
X"34",X"20",X"F2",X"11",X"B1",X"00",X"0E",X"08",X"1A",X"13",X"22",X"23",X"0D",X"20",X"F9",X"3E",
X"19",X"EA",X"10",X"99",X"21",X"2F",X"99",X"0E",X"0C",X"3D",X"28",X"08",X"32",X"0D",X"20",X"F9",
X"2E",X"0F",X"18",X"F5",X"3E",X"91",X"E0",X"40",X"06",X"2D",X"CD",X"A3",X"00",X"3E",X"83",X"CD",
X"AA",X"00",X"06",X"05",X"CD",X"A3",X"00",X"3E",X"C1",X"CD",X"AA",X"00",X"06",X"46",X"CD",X"A3",
X"00",X"21",X"B0",X"01",X"E5",X"F1",X"21",X"4D",X"01",X"01",X"13",X"00",X"11",X"D8",X"00",X"C3",
X"FE",X"00",X"3E",X"04",X"0E",X"00",X"CB",X"20",X"F5",X"CB",X"11",X"F1",X"CB",X"11",X"3D",X"20",
X"F5",X"79",X"22",X"23",X"22",X"23",X"C9",X"E5",X"21",X"0F",X"FF",X"CB",X"86",X"CB",X"46",X"28",
X"FC",X"E1",X"C9",X"CD",X"97",X"00",X"05",X"20",X"FA",X"C9",X"E0",X"13",X"3E",X"87",X"E0",X"14",
X"C9",X"3C",X"42",X"B9",X"A5",X"B9",X"A5",X"42",X"3C",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",
X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"00",X"E0",X"50");
begin
data <= rom_data(to_integer(unsigned(addr))) when rising_edge(clk);
end architecture;
library ieee;
use ieee.std_logic_1164.all,ieee.numeric_std.all;
entity boot_rom_sgb is
port (
clk : in std_logic;
addr : in std_logic_vector(7 downto 0);
data : out std_logic_vector(7 downto 0)
);
end entity;
architecture prom of boot_rom_sgb is
type rom is array(0 to 255) of std_logic_vector(7 downto 0);
signal rom_data: rom := (
x"31",x"FE",x"FF",x"21",x"00",x"80",x"22",x"CB",x"6C",x"28",x"FB",x"3E",x"80",x"E0",x"26",x"E0",
x"11",x"3E",x"F3",x"E0",x"12",x"E0",x"25",x"3E",x"77",x"E0",x"24",x"3E",x"00",x"E0",x"47",x"11",
x"04",x"01",x"21",x"10",x"80",x"1A",x"47",x"CD",x"C9",x"00",x"CD",x"C9",x"00",x"13",x"7B",x"EE",
x"34",x"20",x"F2",x"11",x"EA",x"00",x"0E",x"08",x"1A",x"13",x"22",x"23",x"0D",x"20",x"F9",x"3E",
x"19",x"EA",x"10",x"99",x"21",x"2F",x"99",x"0E",x"0C",x"3D",x"28",x"08",x"32",x"0D",x"20",x"F9",
x"2E",x"0F",x"18",x"F5",x"3E",x"91",x"E0",x"40",x"3E",x"F1",x"E0",x"80",x"21",x"04",x"01",x"AF",
x"4F",x"AF",x"E2",x"3E",x"30",x"E2",x"F0",x"80",x"CD",x"B7",x"00",x"E5",x"06",x"0E",x"16",x"00",
x"CD",x"AD",x"00",x"82",x"57",x"05",x"20",x"F8",x"CD",x"B7",x"00",x"E1",x"06",x"0E",x"CD",x"AD",
x"00",x"CD",x"B7",x"00",x"05",x"20",x"F7",x"3E",x"20",x"E2",x"3E",x"30",x"E2",x"F0",x"80",x"C6",
x"02",x"E0",x"80",x"3E",x"58",x"BD",x"20",x"C9",x"0E",x"13",x"3E",x"C1",x"E2",x"0C",x"3E",x"07",
x"E2",x"3E",x"FC",x"E0",x"47",x"3E",x"01",x"21",x"60",x"C0",x"C3",x"FE",x"00",x"3E",x"4F",x"BD",
x"38",x"02",x"2A",x"C9",x"23",x"AF",x"C9",x"5F",x"16",x"08",x"3E",x"10",x"CB",x"1B",x"38",x"01",
x"87",x"E2",x"3E",x"30",x"E2",x"15",x"C8",x"18",x"F1",x"3E",x"04",x"0E",x"00",x"CB",x"20",x"F5",
x"CB",x"11",x"F1",x"CB",x"11",x"3D",x"20",x"F5",x"79",x"22",x"23",x"22",x"23",x"C9",x"E5",x"21",
x"0F",x"FF",x"CB",x"86",x"CB",x"46",x"28",x"FC",x"E1",x"C9",x"3C",x"42",x"B9",x"A5",x"B9",x"A5",
x"42",x"3C",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"00",x"E0",x"50");
begin
data <= rom_data(to_integer(unsigned(addr))) when rising_edge(clk);
end architecture;

View File

@@ -5,6 +5,8 @@ module cart_top (
input ce_cpu,
input ce_cpu2x,
input speed,
input megaduck,
input [2:0] mapper_sel,
input [14:0] cart_addr,
input cart_a15,
@@ -66,7 +68,8 @@ module cart_top (
input [19:0] Savestate_CRAMAddr,
input Savestate_CRAMRWrEn,
input [7:0] Savestate_CRAMWriteData,
output [7:0] Savestate_CRAMReadData
output [7:0] Savestate_CRAMReadData,
output rumbling
);
///////////////////////////////////////////////////
@@ -121,6 +124,10 @@ mappers mappers (
.tama ( tama ),
.rocket ( rocket ),
.sachen ( sachen),
.wisdom_tree ( wisdom_tree ),
.mani161 ( mani161 ),
.megaduck ( megaduck_en ),
.isGBC_game ( isGBC_game ),
@@ -172,7 +179,8 @@ mappers mappers (
.mbc_addr ( mbc_addr ),
.ram_enabled ( mbc_ram_enable ),
.has_battery ( mbc_battery )
.has_battery ( mbc_battery ),
.rumbling ( cart_rumbling )
);
@@ -195,6 +203,7 @@ wire [3:0] ram_mask = // 0 - no ram
4'b1111; // 4 - 128k 16 banks
// ROM size
/*
wire [8:0] rom_mask =
(cart_rom_size == 0)? 9'b000000001: // 0 - 2 banks, 32k direct mapped
(cart_rom_size == 1)? 9'b000000011: // 1 - 4 banks = 64k
@@ -209,23 +218,33 @@ wire [8:0] rom_mask =
(cart_rom_size == 83)?9'b001111111: //$53 - 80 banks = 1.2M
(cart_rom_size == 84)?9'b001111111:
9'b001111111; //$54 - 96 banks = 1.5M
*/
wire mbc1 = (cart_mbc_type == 1) || (cart_mbc_type == 2) || (cart_mbc_type == 3);
reg [8:0] rom_mask; // get mask from file size
wire mbc1 = (mapper_sel_r == 3'd3) || (cart_mbc_type == 1) || (cart_mbc_type == 2) || (cart_mbc_type == 3);
wire mbc2 = (cart_mbc_type == 5) || (cart_mbc_type == 6);
//wire mmm01 = (cart_mbc_type == 11) || (cart_mbc_type == 12) || (cart_mbc_type == 13) || (cart_mbc_type == 14);
wire mbc3 = (cart_mbc_type == 15) || (cart_mbc_type == 16) || (cart_mbc_type == 17) || (cart_mbc_type == 18) || (cart_mbc_type == 19);
wire mbc3 = (mapper_sel_r == 3'd4) || (cart_mbc_type == 15) || (cart_mbc_type == 16) || (cart_mbc_type == 17) || (cart_mbc_type == 18) || (cart_mbc_type == 19);
wire mbc30 = mbc3 && ( (cart_rom_size == 7) || (cart_ram_size == 5) );
//wire mbc4 = (cart_mbc_type == 21) || (cart_mbc_type == 22) || (cart_mbc_type == 23);
wire mbc5 = (cart_mbc_type == 25) || (cart_mbc_type == 26) || (cart_mbc_type == 27) || (cart_mbc_type == 28) || (cart_mbc_type == 29) || (cart_mbc_type == 30);
wire mbc6 = (cart_mbc_type == 32);
wire mbc7 = (cart_mbc_type == 34);
wire rocket = (cart_mbc_type == 151) || (cart_mbc_type == 153);
wire megaduck_en = (cart_mbc_type == 250); // Use a wire to ensure enable is load while loading
wire gb_camera = (cart_mbc_type == 252);
wire tama = (cart_mbc_type == 253);
wire HuC3 = (cart_mbc_type == 254);
wire HuC1 = (cart_mbc_type == 255);
wire wisdom_tree = (mapper_sel_r == 3'd1);
wire mani161 = (mapper_sel_r == 3'd2);
wire has_rumble = (cart_mbc_type[7:2] == 6'b0001_11);
wire cart_rumbling;
assign rumbling = has_rumble & cart_rumbling;
assign isGBC_game = (cart_cgb_flag);
assign isSGB_game = (cart_sgb_flag == 8'h03 && cart_old_licensee == 8'h33);
@@ -244,6 +263,7 @@ wire mmm01_bank = (ioctl_addr[18:12] == 7'h78); // $78000+
wire cart_logo_match = &cart_logo_check;
reg old_cart_download;
reg [2:0] mapper_sel_r;
always @(posedge clk_sys) begin
old_cart_download <= cart_download;
@@ -254,70 +274,89 @@ always @(posedge clk_sys) begin
mbc1m <= 0;
mmm01 <= 0;
{ sachen, sachen_t1, sachen_t2 } <= 0;
mapper_sel_r <= mapper_sel;
end
if(cart_download & ioctl_wr) begin
if (~|ioctl_addr[24:12] || (mmm01_bank & mmm01) ) // MMM01 header is at the end of ROM
case(ioctl_addr[11:0])
12'h142: cart_cgb_flag <= ioctl_dout[15];
12'h146: begin
{cart_mbc_type, cart_sgb_flag} <= ioctl_dout;
// "Mani 4 in 1" have incorrectly set MBC3 in the header
if ( mmm01 && ioctl_dout[15:8] == 8'h11) cart_mbc_type <= 8'h0B;
end
12'h148: { cart_ram_size, cart_rom_size } <= ioctl_dout;
12'h14a: { cart_old_licensee } <= ioctl_dout[15:8];
endcase
// Sachen
if (~|ioctl_addr[24:12]) begin
case(ioctl_addr[11:0])
12'h100: sachen_t1 <= (ioctl_dout[15:8] != 8'hC3);
12'h140: sachen_t2 <= (ioctl_dout[ 7:0] == 8'hC3); // 0xC3 opcode is at $140 instead of $101
12'h150: begin /// CGB flag
if (sachen_t1 & sachen_t2) begin
sachen <= 1'b1;
cart_cgb_flag <= ioctl_dout[15];
cart_mbc_type <= 0;
cart_sgb_flag <= 0;
cart_ram_size <= 0;
cart_rom_size <= 0;
cart_old_licensee <= 0;
rom_mask <= ioctl_addr[22:14];
if (megaduck) begin
cart_cgb_flag <= 0;
cart_sgb_flag <= 0;
mapper_sel_r <= 0;
if (ioctl_addr > 'h100) // Make sure there's time to reset the banks in the mapper
cart_mbc_type <= 8'd250;
end else begin
if (~|ioctl_addr[24:12] || (mmm01_bank & mmm01) ) // MMM01 header is at the end of ROM
case(ioctl_addr[11:0])
12'h142: cart_cgb_flag <= ioctl_dout[15];
12'h146: begin
{cart_mbc_type, cart_sgb_flag} <= ioctl_dout;
// "Mani 4 in 1" have incorrectly set MBC3 in the header
if ( mmm01 && ioctl_dout[15:8] == 8'h11) cart_mbc_type <= 8'h0B;
end
12'h148: { cart_ram_size, cart_rom_size } <= ioctl_dout;
12'h14a: { cart_old_licensee } <= ioctl_dout[15:8];
endcase
// Disable other mappers when a specific mapper has been selected
if (|mapper_sel_r) begin
cart_mbc_type <= 8'd0;
mbc1m <= 0;
mmm01 <= 0;
sachen <= 0;
end else begin
// Sachen
if (~|ioctl_addr[24:12]) begin
case(ioctl_addr[11:0])
12'h100: sachen_t1 <= (ioctl_dout[15:8] != 8'hC3);
12'h140: sachen_t2 <= (ioctl_dout[ 7:0] == 8'hC3); // 0xC3 opcode is at $140 instead of $101
12'h150: begin /// CGB flag
if (sachen_t1 & sachen_t2) begin
sachen <= 1'b1;
cart_cgb_flag <= ioctl_dout[15];
cart_mbc_type <= 0;
cart_sgb_flag <= 0;
cart_ram_size <= 0;
cart_old_licensee <= 0;
end
end
endcase
end
//Store cart logo data
if (ioctl_addr >= 'h104 && ioctl_addr <= 'h112) begin
cart_logo_data[cart_logo_idx] <= ioctl_dout;
cart_logo_idx <= cart_logo_idx + 1'b1;
end
// MBC1 Multicart detect: Compare 8 words of logo data at second 256KByte bank ($40000)
// MMM01 detect: Compare the last bank every 512KByte ($78000+)
if ( mbc1m_bank | mmm01_bank ) begin
if (ioctl_addr[11:0] >= 12'h104 && ioctl_addr[11:0] <= 12'h112) begin
cart_logo_check[cart_logo_idx] <= (ioctl_dout == cart_logo_data[cart_logo_idx]);
cart_logo_idx <= cart_logo_idx + 1'b1;
if (&cart_logo_idx) begin
if (mbc1m_bank) mbc1m_check_end <= 1;
if (mmm01_bank) mmm01_check_end <= 1;
end
end
end
endcase
end
//Store cart logo data
if (ioctl_addr >= 'h104 && ioctl_addr <= 'h112) begin
cart_logo_data[cart_logo_idx] <= ioctl_dout;
cart_logo_idx <= cart_logo_idx + 1'b1;
end
if (mbc1m_check_end) begin
mbc1m_check_end <= 0;
mbc1m <= cart_logo_match;
end
// MBC1 Multicart detect: Compare 8 words of logo data at second 256KByte bank ($40000)
// MMM01 detect: Compare the last bank every 512KByte ($78000+)
if ( mbc1m_bank | mmm01_bank ) begin
if (ioctl_addr[11:0] >= 12'h104 && ioctl_addr[11:0] <= 12'h112) begin
cart_logo_check[cart_logo_idx] <= (ioctl_dout == cart_logo_data[cart_logo_idx]);
cart_logo_idx <= cart_logo_idx + 1'b1;
if (&cart_logo_idx) begin
if (mbc1m_bank) mbc1m_check_end <= 1;
if (mmm01_bank) mmm01_check_end <= 1;
if (mmm01_check_end) begin
mmm01_check_end <= 0;
mmm01 <= cart_logo_match;
if (cart_logo_match) mbc1m <= 0;
end
end
end
end
if (mbc1m_check_end) begin
mbc1m_check_end <= 0;
mbc1m <= cart_logo_match;
end
if (mmm01_check_end) begin
mmm01_check_end <= 0;
mmm01 <= cart_logo_match;
if (cart_logo_match) mbc1m <= 0;
end
end
assign ram_size = cart_ram_size;

134
rtl/gb.v
View File

@@ -26,7 +26,6 @@ module gb (
input ce,
input ce_2x,
input fast_boot,
input [7:0] joystick,
input isGBC,
input isGBC_game,
@@ -45,14 +44,22 @@ module gb (
// WRAM or Cart RAM CS
output nCS,
//gbc bios interface
output [11:0] gbc_bios_addr,
input [7:0] gbc_bios_do,
input cgb_boot_download,
input dmg_boot_download,
input sgb_boot_download,
input ioctl_wr,
input [24:0] ioctl_addr,
input [15:0] ioctl_dout,
input boot_gba_en,
// audio
output [15:0] audio_l,
output [15:0] audio_r,
// Megaduck?
input megaduck,
// lcd interface
output lcd_clkena,
output [14:0] lcd_data,
@@ -154,6 +161,7 @@ wire sel_zpram = (cpu_addr[15:7] == 9'b111111111) && // 127 bytes zero pageram a
(cpu_addr != 16'hffff);
wire sel_audio = (cpu_addr[15:8] == 8'hff) && // audio reg ff10 - ff3f and ff76/ff77 PCM12/PCM34 (undocumented registers)
((cpu_addr[7:5] == 3'b001) || (cpu_addr[7:4] == 4'b0001) || (cpu_addr[7:0] == 8'h76) || (cpu_addr[7:0] == 8'h77));
wire sel_ext_bus = sel_rom | sel_cram | sel_wram;
wire sel_boot_rom, sel_boot_rom_cgb;
@@ -203,9 +211,6 @@ wire hdma_sel_cram = hdma_source_addr[15:13] == 3'b101; // 8k cart ram at $a
wire hdma_sel_wram = hdma_source_addr[15:13] == 3'b110; // 8k WRAM at $c000-$dff0
wire hdma_sel_ext_bus = hdma_sel_rom | hdma_sel_cram;
// the boot roms sees a special $42 flag in $ff50 if it's supposed to to a fast boot
wire sel_fast = fast_boot && cpu_addr == 16'hff50 && boot_rom_enabled;
wire sc_start;
wire sc_shiftclock;
wire [7:0] sc_r = {sc_start,6'h3F,sc_shiftclock};
@@ -232,8 +237,8 @@ wire [7:0] joy_do;
wire [7:0] sb_o;
wire [7:0] timer_do;
wire [7:0] video_do;
wire [7:0] audio_do;
wire [7:0] bios_do;
reg [7:0] audio_do;
wire [7:0] boot_do;
wire [7:0] vram_do;
wire [7:0] vram1_do;
wire [7:0] zpram_do;
@@ -243,11 +248,10 @@ reg[7:0] FF72;
reg[7:0] FF73;
reg[7:0] FF74;
reg[2:0] FF75;
// http://gameboy.mongenel.com/dmg/asmmemmap.html
wire [7:0] cpu_di =
irq_ack?irq_vec:
sel_fast?8'h42: // fast boot flag
sel_if?{3'b111, if_r}: // interrupt flag register
sel_rp?8'h02:
sel_wram_bank?{5'h1f,wram_bank}:
@@ -261,7 +265,7 @@ wire [7:0] cpu_di =
sel_video_reg?video_do: // video registers
(sel_video_oam&&oam_cpu_allow)?video_do: // video object attribute memory
sel_audio?audio_do: // audio registers
sel_boot_rom?bios_do: // boot rom
sel_boot_rom?boot_do: // boot rom
isGBC&sel_wram ? wram_do: // wram on GBC
sel_ext_bus?ext_bus_di: // wram (DMG) + cartridge rom/ram
(sel_vram&&vram_cpu_allow)?(isGBC&&vram_bank)?vram1_do:vram_do: // vram (GBC bank 0+1)
@@ -307,7 +311,15 @@ wire cpu_stop;
wire genie_ovr;
wire [7:0] genie_data;
wire [15:0] cpu_addr_raw;
megaduck_swizzle md_swizz
(
.megaduck (megaduck),
.a_in (cpu_addr_raw),
.a_out (cpu_addr)
);
GBse cpu (
.RESET_n ( !reset_ss ),
.CLK_n ( clk_sys ),
@@ -324,7 +336,7 @@ GBse cpu (
.RFSH_n ( ),
.HALT_n ( ),
.BUSAK_n ( ),
.A ( cpu_addr ),
.A ( cpu_addr_raw ),
.DI ( genie_ovr ? genie_data : cpu_di),
.DO ( cpu_do ),
.STOP ( cpu_stop ),
@@ -383,6 +395,25 @@ end
wire audio_rd = !cpu_rd_n && sel_audio;
wire audio_wr = !cpu_wr_n_edge && sel_audio;
reg [7:0] snd_d_in;
wire [7:0] snd_d_out;
// Megaduck has reversed nybbles for some registers
always @(*) begin
snd_d_in = cpu_do;
audio_do = snd_d_out;
if (megaduck) begin
if (cpu_addr[7:4] == 1 && (cpu_addr_raw[3:0] == 1 || cpu_addr_raw[3:0] == 7))
snd_d_in = {cpu_do[3:0], cpu_do[7:4]};
if (cpu_addr[7:4] == 2 && (cpu_addr_raw[3:0] == 1 || cpu_addr_raw[3:0] == 2))
snd_d_in = {cpu_do[3:0], cpu_do[7:4]};
if (cpu_addr[7:4] == 1 && (cpu_addr_raw[3:0] == 1 || cpu_addr_raw[3:0] == 7))
audio_do = {snd_d_out[3:0], snd_d_out[7:4]};
if (cpu_addr[7:4] == 2 && (cpu_addr_raw[3:0] == 1 || cpu_addr_raw[3:0] == 2))
audio_do = {snd_d_out[3:0], snd_d_out[7:4]};
end
end
gbc_snd audio (
.clk ( clk_sys ),
@@ -394,8 +425,8 @@ gbc_snd audio (
.s1_read ( audio_rd ),
.s1_write ( audio_wr ),
.s1_addr ( cpu_addr[6:0] ),
.s1_readdata ( audio_do ),
.s1_writedata ( cpu_do ),
.s1_readdata ( snd_d_out ),
.s1_writedata ( snd_d_in ),
.snd_left ( audio_l ),
.snd_right ( audio_r ),
@@ -629,6 +660,7 @@ video video (
.ce_cpu ( ce_cpu ), //can be 2x in cgb double speed mode
.isGBC ( isGBC ),
.isGBC_game ( isGBC_game|boot_rom_enabled ), //enable GBC mode during bootstrap rom
.megaduck ( megaduck ),
.irq ( video_irq ),
.vblank_irq ( vblank_irq ),
@@ -854,41 +886,61 @@ end
// combine boot rom data with cartridge data
wire [7:0] boot_rom_do;
wire [7:0] fast_boot_rom_do;
wire [7:0] boot_rom_sgb_do;
wire [15:0] boot_rom_addr = (isGBC && hdma_rd) ? hdma_source_addr : cpu_addr;
// 0- FF bootrom 1st part
//100-1FF Cart Header
//200-8FF bootrom 2nd part
assign sel_boot_rom_cgb = isGBC && (boot_rom_addr[15:8] >= 8'h02 && boot_rom_addr[15:8] <= 8'h08);
assign sel_boot_rom = boot_rom_enabled && (!boot_rom_addr[15:8] || sel_boot_rom_cgb);
assign sel_boot_rom = boot_rom_enabled && (!boot_rom_addr[15:8] || sel_boot_rom_cgb) && ~megaduck;
assign bios_do = isGBC ? gbc_bios_do :
isSGB ? boot_rom_sgb_do :
fast_boot ? fast_boot_rom_do : boot_rom_do;
assign gbc_bios_addr = boot_rom_addr[11:0];
// $000-8FF: GBC
// $900-9FF: DMG
// $A00-AFF: SGB
wire [11:0] boot_addr =
isGBC ? boot_rom_addr[11:0] :
isSGB ? { 4'hA, boot_rom_addr[7:0] } :
{ 4'h9, boot_rom_addr[7:0] };
boot_rom boot_rom (
.addr ( cpu_addr[7:0] ),
.clk ( clk_sys ),
.data ( boot_rom_do )
wire boot_download = cgb_boot_download | dmg_boot_download | sgb_boot_download;
wire [10:0] boot_wr_addr =
dmg_boot_download ? {4'h9, ioctl_addr[7:1] } :
sgb_boot_download ? {4'hA, ioctl_addr[7:1] } :
ioctl_addr[11:1];
wire [7:0] boot_q;
dpram_dif #(12,8,11,16,"BootROMs/cgb_boot.mif") boot_rom (
.clock (clk_sys),
.address_a (boot_addr),
.q_a (boot_q),
.address_b (boot_wr_addr),
.wren_b (ioctl_wr && boot_download),
.data_b (ioctl_dout)
);
fast_boot_rom fast_boot_rom (
.addr ( cpu_addr[7:0] ),
.clk ( clk_sys ),
.data ( fast_boot_rom_do )
);
reg [7:0] boot_do_gba;
boot_rom_sgb boot_rom_sgb (
.addr ( cpu_addr[7:0] ),
.clk ( clk_sys ),
.data ( boot_rom_sgb_do)
);
always begin
case (boot_addr)
12'h0F2: boot_do_gba = 8'h00;
12'h0F3: boot_do_gba = 8'h00;
12'h0F5: boot_do_gba = 8'hCD;
12'h0F6: boot_do_gba = 8'hD0;
12'h0F7: boot_do_gba = 8'h05;
12'h0F8: boot_do_gba = 8'hAF;
12'h0F9: boot_do_gba = 8'hE0;
12'h0FA: boot_do_gba = 8'h70;
12'h0FB: boot_do_gba = 8'h04;
12'h409: boot_do_gba = 8'h80;
12'h40A: boot_do_gba = 8'hFF;
default: boot_do_gba = boot_q;
endcase
end
assign boot_do = (isGBC & boot_gba_en) ? boot_do_gba : boot_q;
// --------------------------------------------------------------------
// ------------------ External bus (WRAM, Cartridge) ------------------

View File

@@ -21,6 +21,10 @@ module mappers(
input tama,
input rocket,
input sachen,
input wisdom_tree,
input mani161,
input megaduck,
input isGBC_game,
@@ -72,7 +76,8 @@ module mappers(
output [22:0] mbc_addr,
output ram_enabled,
output has_battery
output has_battery,
output rumbling
);
@@ -92,12 +97,14 @@ tri0 RTC_inuse_b;
wire ce = speed ? ce_cpu2x : ce_cpu;
wire no_mapper = ~(mbc1 | mbc2 | mbc3 | mbc5 | mbc6 | mbc7 | mmm01 | huc1 | huc3 | gb_camera | tama | rocket | sachen);
wire no_mapper = ~(mbc1 | mbc2 | mbc3 | mbc5 | mbc6 | mbc7 | mmm01 | huc1 | huc3 | gb_camera | tama | rocket | sachen | wisdom_tree | mani161 | megaduck);
wire no_mapper_single_bank = no_mapper & ~rom_mask[1];
wire no_mapper_multi_bank = no_mapper & rom_mask[1]; // size > 32KB
wire rom_override = (rocket);
wire cart_oe_override = (mbc3 | mbc7 | huc1 | huc3 | gb_camera | tama);
mbc1 map_mbc1 (
.enable ( mbc1 ),
.enable ( mbc1 | no_mapper_multi_bank ),
.mbc1m ( mbc1m ),
.clk_sys ( clk_sys ),
@@ -233,7 +240,8 @@ mbc5 map_mbc5 (
.mbc_addr_b ( mbc_addr_b ),
.ram_enabled_b ( ram_enabled_b ),
.has_battery_b ( has_battery_b )
.has_battery_b ( has_battery_b ),
.rumbling ( rumbling )
);
mbc6 map_mbc6 (
@@ -556,15 +564,76 @@ sachen map_sachen (
.has_battery_b ( has_battery_b )
);
megaduck map_megaduck (
.enable ( megaduck ),
.clk_sys ( clk_sys ),
.ce_cpu ( ce ),
.savestate_load ( savestate_load ),
.savestate_data ( savestate_data ),
.savestate_back_b ( savestate_back_b ),
.has_ram ( has_ram ),
.ram_mask ( ram_mask ),
.rom_mask ( rom_mask ),
.cart_addr ( cart_addr ),
.cart_a15 ( cart_a15 ),
.cart_mbc_type ( cart_mbc_type ),
.cart_wr ( cart_wr ),
.cart_di ( cart_di ),
.cram_di ( cram_di ),
.cram_do_b ( cram_do_b ),
.cram_addr_b ( cram_addr_b ),
.mbc_addr_b ( mbc_addr_b ),
.ram_enabled_b ( ram_enabled_b ),
.has_battery_b ( has_battery_b )
);
// Mani 4-in-1 DMG 601 & Wisdom Tree 32KB bank mappers
misc_mapper map_misc (
.enable ( ~reset & (wisdom_tree | mani161) ),
.clk_sys ( clk_sys ),
.ce_cpu ( ce ),
.mapper_sel ( mani161 ),
.savestate_load ( savestate_load ),
.savestate_data ( savestate_data ),
.savestate_back_b ( savestate_back_b ),
.rom_mask ( rom_mask ),
.cart_addr ( cart_addr ),
.cart_a15 ( cart_a15 ),
.cart_wr ( cart_wr ),
.cart_di ( cart_di ),
.cram_di ( cram_di ),
.cram_do_b ( cram_do_b ),
.cram_addr_b ( cram_addr_b ),
.mbc_addr_b ( mbc_addr_b ),
.ram_enabled_b ( ram_enabled_b ),
.has_battery_b ( has_battery_b )
);
assign { cram_do } = { cram_do_b };
assign { savestate_back, savestate_back2 } = { savestate_back_b, savestate_back2_b };
assign { RTC_timestampOut, RTC_savedtimeOut, RTC_inuse } = { RTC_timestampOut_b, RTC_savedtimeOut_b, RTC_inuse_b };
assign { cram_wr_do, cram_wr } = { cram_wr_do_b, cram_wr_b };
assign mbc_addr = no_mapper ? {8'd0, cart_addr[14:0]} : mbc_addr_b;
assign cram_addr = no_mapper ? {4'd0, cart_addr[12:0]} : cram_addr_b;
assign has_battery = no_mapper ? (cart_mbc_type == 8'h09) : has_battery_b;
assign ram_enabled = no_mapper ? has_ram : ram_enabled_b;
assign mbc_addr = no_mapper_single_bank ? {8'd0, cart_addr[14:0]} : mbc_addr_b;
assign cram_addr = no_mapper_single_bank ? {4'd0, cart_addr[12:0]} : cram_addr_b;
assign has_battery = no_mapper_single_bank ? (cart_mbc_type == 8'h09) : has_battery_b;
assign ram_enabled = no_mapper_single_bank ? has_ram : ram_enabled_b;
assign rom_do = rom_override ? rom_do_b : rom_di;
assign cart_oe = cart_oe_override ? cart_oe_b : ((cart_rd & ~cart_a15) | (cram_rd & ram_enabled));

View File

@@ -26,7 +26,8 @@ module mbc5 (
inout [22:0] mbc_addr_b,
inout ram_enabled_b,
inout has_battery_b
inout has_battery_b,
output rumbling
);
wire [22:0] mbc_addr;
@@ -42,6 +43,7 @@ assign cram_addr_b = enable ? cram_addr : 17'hZ;
assign ram_enabled_b = enable ? ram_enabled : 1'hZ;
assign has_battery_b = enable ? has_battery : 1'hZ;
assign savestate_back_b = enable ? savestate_back : 16'hZ;
assign rumbling = mbc_ram_bank_reg[3];
wire [3:0] mbc5_ram_bank = mbc_ram_bank_reg & ram_mask;

89
rtl/mappers/megaduck.v Normal file
View File

@@ -0,0 +1,89 @@
module megaduck (
input enable,
input clk_sys,
input ce_cpu,
input savestate_load,
input [15:0] savestate_data,
inout [15:0] savestate_back_b,
input has_ram,
input [1:0] ram_mask,
input [6:0] rom_mask,
input [14:0] cart_addr,
input cart_a15,
input [7:0] cart_mbc_type,
input cart_wr,
input [7:0] cart_di,
input [7:0] cram_di,
inout [7:0] cram_do_b,
inout [16:0] cram_addr_b,
inout [22:0] mbc_addr_b,
inout ram_enabled_b,
inout has_battery_b
);
wire [22:0] mbc_addr;
wire ram_enabled;
wire [7:0] cram_do;
wire [16:0] cram_addr;
wire has_battery;
wire [15:0] savestate_back;
assign mbc_addr_b = enable ? mbc_addr : 23'hZ;
assign cram_do_b = enable ? cram_do : 8'hZ;
assign cram_addr_b = enable ? cram_addr : 17'hZ;
assign ram_enabled_b = enable ? ram_enabled : 1'hZ;
assign has_battery_b = enable ? has_battery : 1'hZ;
assign savestate_back_b = enable ? savestate_back : 16'hZ;
// Megaduck banks are pretty simple. They are broken up into chunks of 0x4000. So bank 0
// is 0-0x3fff, bank 1 is 0x4000-0x7fff and so on. On most carts, only the top 0x4000 of the rom
// can be bank switched and the bottom is fixed at bank 0. In this case, the bank number is
// written to address 0x0001. Note that the bank can never be less than 1 for the upper bank.
// On some roms, a ram address is written instead which changes the entire visible rom space
// instead of just the upper slot.
reg [7:0] bank_top, bank_bottom;
// --------------------- CPU register interface ------------------
assign savestate_back[ 7: 0] = bank_bottom;
assign savestate_back[15: 8] = bank_top; // The top bank can never be less than 1
always @(posedge clk_sys) begin
if(savestate_load & enable) begin
bank_bottom <= savestate_data[7:0];
bank_top <= savestate_data[15:8];
end else if(~enable) begin
bank_bottom <= 8'd0;
bank_top <= 8'd1;
end else if(ce_cpu) begin
if (cart_wr) begin
if (~cart_a15 && cart_addr == 1) begin
bank_top <= (cart_di[7:0] == 0) ? 8'd1 : cart_di;
end
else if (cart_a15 && ~cart_addr[14]) begin
bank_top <= {cart_di[6:0], 1'b1};
bank_bottom <= {cart_di[6:0], 1'b0};
end
end
end
end
assign mbc_addr = { 1'b0, (cart_addr[14] ? bank_top : bank_bottom), cart_addr[13:0] };
assign ram_enabled = 0;
assign cram_do = ram_enabled ? cram_di : 8'hFF;
assign cram_addr = 17'd0;
assign has_battery = 0;
endmodule

86
rtl/mappers/misc.v Normal file
View File

@@ -0,0 +1,86 @@
module misc_mapper (
input enable,
input clk_sys,
input ce_cpu,
input mapper_sel, // 0: Wisdom Tree, 1: Mani DMG-601
input savestate_load,
input [15:0] savestate_data,
inout [15:0] savestate_back_b,
input [8:0] rom_mask,
input [14:0] cart_addr,
input cart_a15,
input cart_wr,
input [7:0] cart_di,
input [7:0] cram_di,
inout [7:0] cram_do_b,
inout [16:0] cram_addr_b,
inout [22:0] mbc_addr_b,
inout ram_enabled_b,
inout has_battery_b
);
wire [22:0] mbc_addr;
wire ram_enabled;
wire [7:0] cram_do;
wire [16:0] cram_addr;
wire has_battery;
wire [15:0] savestate_back;
assign mbc_addr_b = enable ? mbc_addr : 23'hZ;
assign cram_do_b = enable ? cram_do : 8'hZ;
assign cram_addr_b = enable ? cram_addr : 17'hZ;
assign ram_enabled_b = enable ? ram_enabled : 1'hZ;
assign has_battery_b = enable ? has_battery : 1'hZ;
assign savestate_back_b = enable ? savestate_back : 16'hZ;
// --------------------- CPU register interface ------------------
reg [7:0] rom_bank_reg;
reg map_disable;
assign savestate_back[ 7: 0] = rom_bank_reg;
assign savestate_back[ 8] = map_disable;
assign savestate_back[15: 9] = 0;
always @(posedge clk_sys) begin
if(savestate_load & enable) begin
rom_bank_reg <= savestate_data[ 7: 0]; //8'd0;
map_disable <= savestate_data[ 8]; //1'b0;
end else if(~enable) begin
rom_bank_reg <= 8'd0;
map_disable <= 1'b0;
end else if(ce_cpu) begin
if (cart_wr & ~cart_a15) begin
if (mapper_sel) begin
// Mani DMG-601
if (~map_disable) begin
rom_bank_reg <= { 5'd0, cart_di[2:0] };
map_disable <= 1'b1;
end
end else begin
// Wisdom Tree
rom_bank_reg <= cart_addr[7:0];
end
end
end
end
// mask address lines to enable proper mirroring
wire [7:0] rom_bank = rom_bank_reg & rom_mask[8:1];
assign mbc_addr = { rom_bank, cart_addr[14:0] };
assign cram_do = 8'hFF;
assign cram_addr = { 4'b0000, cart_addr[12:0] };
assign ram_enabled = 0;
assign has_battery = 0;
endmodule

54
rtl/megaswizzle.sv Normal file
View File

@@ -0,0 +1,54 @@
module megaduck_swizzle
(
input megaduck,
input [15:0] a_in,
output [15:0] a_out
);
// Swizzle around MegaDuck register to match GB registers.
always_comb begin
a_out = a_in;
if (megaduck) begin
case (a_in)
16'hFF10: a_out = 16'hFF40; // LCDC
16'hFF11: a_out = 16'hFF41; // STAT
16'hFF12: a_out = 16'hFF42; // SCY
16'hFF13: a_out = 16'hFF43; // SCX
16'hFF18: a_out = 16'hFF44; // LY
16'hFF19: a_out = 16'hFF45; // LYC
16'hFF1A: a_out = 16'hFF46; // DMA
16'hFF1B: a_out = 16'hFF47; // BGP
16'hFF14: a_out = 16'hFF48; // OBP0
16'hFF15: a_out = 16'hFF49; // OBP1
16'hFF16: a_out = 16'hFF4A; // WY
16'hFF17: a_out = 16'hFF4B; // WX
16'hFF20: a_out = 16'hFF10; // Audio registers
16'hFF21: a_out = 16'hFF12;
16'hFF22: a_out = 16'hFF11;
16'hFF23: a_out = 16'hFF13;
16'hFF24: a_out = 16'hFF14;
16'hFF25: a_out = 16'hFF16;
16'hFF26: a_out = 16'hFF15;
16'hFF27: a_out = 16'hFF17;
16'hFF28: a_out = 16'hFF18;
16'hFF29: a_out = 16'hFF19;
16'hFF2A: a_out = 16'hFF1A;
16'hFF2B: a_out = 16'hFF1B;
16'hFF2C: a_out = 16'hFF1C;
16'hFF2D: a_out = 16'hFF1D;
16'hFF2E: a_out = 16'hFF1E;
16'hFF2F: a_out = 16'hFF1F;
16'hFF40: a_out = 16'hFF20; // The final 7 registers are after the audio ram
16'hFF41: a_out = 16'hFF22;
16'hFF42: a_out = 16'hFF21;
16'hFF43: a_out = 16'hFF23;
16'hFF44: a_out = 16'hFF24;
16'hFF45: a_out = 16'hFF26;
16'hFF46: a_out = 16'hFF25;
default: a_out = a_in;
endcase
end
end
endmodule

View File

@@ -27,7 +27,7 @@ package pReg_savestates is
constant REG_SAVESTATE_Video2 : regmap_type := ( 10, 61, 0, 1, x"00000000FFFFFC00");
constant REG_SAVESTATE_BPalette : regmap_type := ( 11, 63, 0, 8, x"0000000000000000");
constant REG_SAVESTATE_OPalette : regmap_type := ( 19, 63, 0, 8, x"0000000000000000");
constant REG_SAVESTATE_Video3 : regmap_type := ( 27, 62, 0, 1, x"0000000000000000");
constant REG_SAVESTATE_Video3 : regmap_type := ( 27, 63, 0, 1, x"0000000000000000");
constant REG_SAVESTATE_Sound1 : regmap_type := ( 28, 63, 0, 1, x"0000000000000000");
constant REG_SAVESTATE_Sound2 : regmap_type := ( 29, 54, 0, 1, x"0000000000000000");

View File

@@ -26,6 +26,7 @@ module video (
input ce_cpu, // 4 or 8Mhz
input isGBC,
input isGBC_game,
input megaduck,
// cpu register adn oam interface
input cpu_sel_oam,
@@ -82,12 +83,12 @@ wire [60:0] SS_Video1;
wire [60:0] SS_Video1_BACK;
wire [61:0] SS_Video2;
wire [61:0] SS_Video2_BACK;
wire [62:0] SS_Video3;
wire [62:0] SS_Video3_BACK;
wire [63:0] SS_Video3;
wire [63:0] SS_Video3_BACK;
eReg_SavestateV #(0, 9, 60, 0, 64'h0000000000000000) iREG_SAVESTATE_Video1 (clk, SaveStateBus_Din, SaveStateBus_Adr, SaveStateBus_wren, SaveStateBus_rst, SaveStateBus_wired_or[ 0], SS_Video1_BACK, SS_Video1);
eReg_SavestateV #(0, 10, 61, 0, 64'h00000000FFFFFC00) iREG_SAVESTATE_Video2 (clk, SaveStateBus_Din, SaveStateBus_Adr, SaveStateBus_wren, SaveStateBus_rst, SaveStateBus_wired_or[ 1], SS_Video2_BACK, SS_Video2);
eReg_SavestateV #(0, 27, 62, 0, 64'h0000000000000000) iREG_SAVESTATE_Video3 (clk, SaveStateBus_Din, SaveStateBus_Adr, SaveStateBus_wren, SaveStateBus_rst, SaveStateBus_wired_or[18], SS_Video3_BACK, SS_Video3);
eReg_SavestateV #(0, 27, 63, 0, 64'h0000000000000000) iREG_SAVESTATE_Video3 (clk, SaveStateBus_Din, SaveStateBus_Adr, SaveStateBus_wren, SaveStateBus_rst, SaveStateBus_wired_or[18], SS_Video3_BACK, SS_Video3);
wire [63:0] SS_BPAL [7:0];
wire [63:0] SS_BPAL_BACK [7:0];
@@ -138,19 +139,19 @@ wire [7:0] oam_di = dma_active?dma_data:cpu_di;
// $ff40 LCDC
reg [7:0] lcdc;
wire lcdc_on = lcdc[7];
wire lcdc_win_tile_map_sel = lcdc[6];
wire lcdc_win_ena = lcdc[5];
wire lcdc_tile_data_sel = lcdc[4];
wire lcdc_bg_tile_map_sel = lcdc[3];
wire lcdc_spr_siz = lcdc[2];
wire lcdc_spr_ena = lcdc[1];
wire lcdc_on = megaduck ? lcdc[7] : lcdc[7];
wire lcdc_win_tile_map_sel = megaduck ? lcdc[3] : lcdc[6];
wire lcdc_win_ena = megaduck ? lcdc[5] : lcdc[5];
wire lcdc_tile_data_sel = megaduck ? lcdc[4] : lcdc[4];
wire lcdc_bg_tile_map_sel = megaduck ? lcdc[2] : lcdc[3];
wire lcdc_spr_siz = megaduck ? lcdc[1] : lcdc[2];
wire lcdc_spr_ena = megaduck ? lcdc[0] : lcdc[1];
// "CGB in CGB Mode: BG and Window Master Priority
// When Bit 0 is cleared, the background and window lose their priority
// - the sprites will be always displayed on top of background and window,
// independently of the priority flags in OAM and BG Map attributes."
wire lcdc_bg_ena = lcdc[0] | (isGBC&&isGBC_game);
wire lcdc_bg_prio = lcdc[0];
wire lcdc_bg_ena = (megaduck ? lcdc[6] : lcdc[0]) | (isGBC&&isGBC_game);
wire lcdc_bg_prio = megaduck ? lcdc[6] : lcdc[0];
assign lcd_on = lcdc_on;
@@ -665,9 +666,9 @@ wire [9:0] bg_tile_map_addr = window_ena ? win_map_addr : bg_map_addr;
wire [2:0] tile_line = window_ena ? win_line[2:0] : bg_line[2:0];
reg window_match, window_ena_d;
reg wy_match, window_match, window_ena_d;
wire win_start = mode3 && lcdc_win_ena && ~sprite_fetch_hold && ~skip_en && ~bg_shift_empty && (v_cnt >= wy) && (pcnt == wx) && (wx < 8'hA7);
wire win_start = ~window_match & mode3 && lcdc_win_ena && ~sprite_fetch_hold && ~skip_en && ~bg_shift_empty && wy_match && (pcnt == wx) && (wx < 8'hA7);
assign window_ena = window_match & ~pcnt_reset & lcdc_win_ena;
assign SS_Video3_BACK[39:33] = h_cnt ;
@@ -676,6 +677,7 @@ assign SS_Video3_BACK[ 42] = window_match;
assign SS_Video3_BACK[ 43] = window_ena_d;
assign SS_Video3_BACK[48:44] = win_col ;
assign SS_Video3_BACK[56:49] = win_line ;
assign SS_Video3_BACK[ 63] = wy_match ;
always @(posedge clk) begin
@@ -686,6 +688,7 @@ always @(posedge clk) begin
window_ena_d <= SS_Video3[ 43]; // 1'b0;
win_col <= SS_Video3[48:44]; // 5'd0;
win_line <= SS_Video3[56:49]; // 8'd0;
wy_match <= SS_Video3[ 63]; // 1'b0;
end else if (!lcdc_on) begin
//reset counters
h_cnt <= 7'd0;
@@ -694,6 +697,7 @@ always @(posedge clk) begin
window_ena_d <= 1'b0;
win_col <= 5'd0;
win_line <= 8'd0;
wy_match <= 1'b0;
end else if (ce) begin
h_div_cnt <= h_div_cnt + 1'b1;
@@ -701,6 +705,12 @@ always @(posedge clk) begin
h_cnt <= hcnt_end ? 7'd0 : h_cnt + 1'b1;
end
if (vblank_l) begin
wy_match <= 1'b0;
end else if (h_clk_en & lcdc_win_ena & v_cnt == wy) begin
wy_match <= 1'b1;
end
if(win_start) begin
window_match <= 1'b1;
end
@@ -711,12 +721,16 @@ always @(posedge clk) begin
else if (window_ena_d & ~window_ena)
win_line <= win_line + 1'b1;
if (window_match & ~mode3_end_l & mode3_end) begin
// DMG glitch: If WX = A6 then window_match stays high through VBlank
// until WY > v_cnt which means the window always appears on line 0.
if (isGBC || wx != 8'hA6 || wy > v_cnt) begin
window_match <= 1'b0; // next line starts with background
if (window_match) begin
if (~mode3_end_l & mode3_end) begin
// DMG glitch: If WX = A6 then window_match stays high through VBlank
// until WY > v_cnt which means the window always appears on line 0.
if (isGBC || wx != 8'hA6 || wy > v_cnt) begin
window_match <= 1'b0; // next line starts with background
end
end
if (~lcdc_win_ena) window_match <= 1'b0;
end
// Increment when fetching is done and not waiting for sprites.

View File

@@ -174,15 +174,17 @@ module screen_rotate
input rotate_ccw,
input no_rotate,
input flip,
output video_rotated,
output FB_EN,
output [4:0] FB_FORMAT,
output [11:0] FB_WIDTH,
output [11:0] FB_HEIGHT,
output [31:0] FB_BASE,
output [13:0] FB_STRIDE,
input FB_VBL,
input FB_LL,
output FB_EN,
output [4:0] FB_FORMAT,
output reg [11:0] FB_WIDTH,
output reg [11:0] FB_HEIGHT,
output [31:0] FB_BASE,
output [13:0] FB_STRIDE,
input FB_VBL,
input FB_LL,
output DDRAM_CLK,
input DDRAM_BUSY,
@@ -196,6 +198,8 @@ module screen_rotate
parameter MEM_BASE = 7'b0010010; // buffer at 0x24000000, 3x8MB
reg do_flip;
assign DDRAM_CLK = CLK_VIDEO;
assign DDRAM_BURSTCNT = 1;
assign DDRAM_ADDR = {MEM_BASE, i_fb, ram_addr[22:3]};
@@ -207,8 +211,6 @@ assign DDRAM_RD = 0;
assign FB_EN = fb_en[2];
assign FB_FORMAT = 5'b00110;
assign FB_BASE = {MEM_BASE,o_fb,23'd0};
assign FB_WIDTH = vsz;
assign FB_HEIGHT = hsz;
assign FB_STRIDE = stride;
function [1:0] buf_next;
@@ -220,6 +222,19 @@ function [1:0] buf_next;
end
endfunction
assign video_rotated = ~no_rotate;
always @(posedge CLK_VIDEO) begin
do_flip <= no_rotate && flip;
if( do_flip ) begin
FB_WIDTH <= hsz;
FB_HEIGHT <= vsz;
end else begin
FB_WIDTH <= vsz;
FB_HEIGHT <= hsz;
end
end
reg [1:0] i_fb,o_fb;
always @(posedge CLK_VIDEO) begin
reg old_vbl,old_vs;
@@ -251,20 +266,23 @@ always @(posedge CLK_VIDEO) begin
if(CE_PIXEL) begin
old_vs <= VGA_VS;
old_de <= VGA_DE;
hcnt <= hcnt + 1'd1;
if(~old_de & VGA_DE) begin
hcnt <= 1;
vcnt <= vcnt + 1'd1;
end
if(old_de & ~VGA_DE) hsz <= hcnt;
if(old_de & ~VGA_DE) begin
hsz <= hcnt;
if( do_flip ) bwidth <= hcnt + 2'd3;
end
if(~old_vs & VGA_VS) begin
vsz <= vcnt;
bwidth <= vcnt + 2'd3;
if( !do_flip ) bwidth <= vcnt + 2'd3;
vcnt <= 0;
fb_en <= {fb_en[1:0], ~no_rotate};
fb_en <= {fb_en[1:0], ~no_rotate | flip};
end
if(old_vs & ~VGA_VS) bufsize <= hsz * stride;
if(old_vs & ~VGA_VS) bufsize <= (do_flip ? vsz : hsz ) * stride;
end
end
@@ -278,21 +296,25 @@ always @(posedge CLK_VIDEO) begin
reg old_vs, old_de;
ram_wr <= 0;
if(CE_PIXEL) begin
if(CE_PIXEL && FB_EN) begin
old_vs <= VGA_VS;
old_de <= VGA_DE;
if(~old_vs & VGA_VS) begin
next_addr <= rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00};
next_addr <=
do_flip ? bufsize-3'd4 :
rotate_ccw ? (bufsize - stride) : {vsz-1'd1, 2'b00};
hcnt <= rotate_ccw ? 3'd4 : {vsz-2'd2, 2'b00};
end
if(VGA_DE) begin
ram_wr <= 1;
ram_data <= {VGA_B,VGA_G,VGA_R};
ram_data <= {8'd0,VGA_B,VGA_G,VGA_R};
ram_addr <= next_addr;
next_addr <= rotate_ccw ? (next_addr - stride) : (next_addr + stride);
next_addr <=
do_flip ? next_addr-3'd4 :
rotate_ccw ? (next_addr - stride) : (next_addr + stride);
end
if(old_de & ~VGA_DE) begin
if(old_de & ~VGA_DE & ~do_flip) begin
next_addr <= rotate_ccw ? (bufsize - stride + hcnt) : hcnt;
hcnt <= rotate_ccw ? (hcnt + 3'd4) : (hcnt - 3'd4);
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,239 +0,0 @@
module hdmi_config
(
// Host Side
input iCLK,
input iRST_N,
input dvi_mode,
input audio_96k,
input [1:0] limited,
input ypbpr,
output reg done,
// I2C Side
output I2C_SCL,
inout I2C_SDA
);
// Internal Registers/Wires
reg mI2C_GO = 0;
wire mI2C_END;
wire mI2C_ACK;
reg [15:0] LUT_DATA;
reg [7:0] LUT_INDEX = 0;
i2c #(50_000_000, 20_000) i2c_av
(
.CLK(iCLK),
.I2C_SCL(I2C_SCL), // I2C CLOCK
.I2C_SDA(I2C_SDA), // I2C DATA
.I2C_ADDR('h39), // 0x39 is the Slave Address of the ADV7513 chip!
.I2C_WLEN(1),
.I2C_WDATA1(init_data[LUT_INDEX][15:8]), // SUB_ADDR
.I2C_WDATA2(init_data[LUT_INDEX][7:0]), // DATA
.START(mI2C_GO), // START transfer
.READ(0),
.END(mI2C_END), // END transfer
.ACK(mI2C_ACK) // ACK
);
////////////////////// Config Control ////////////////////////////
always@(posedge iCLK or negedge iRST_N) begin
reg [1:0] mSetup_ST = 0;
if(!iRST_N) begin
LUT_INDEX <= 0;
mSetup_ST <= 0;
mI2C_GO <= 0;
done <= 0;
end else begin
if(init_data[LUT_INDEX] != 16'hFFFF) begin
case(mSetup_ST)
0: begin
mI2C_GO <= 1;
mSetup_ST <= 1;
end
1: if(~mI2C_END) mSetup_ST <= 2;
2: begin
mI2C_GO <= 0;
if(mI2C_END) begin
mSetup_ST <= 0;
if(!mI2C_ACK) LUT_INDEX <= LUT_INDEX + 8'd1;
end
end
endcase
end
else done <= 1;
end
end
////////////////////////////////////////////////////////////////////
///////////////////// Config Data LUT //////////////////////////
wire [15:0] init_data[82] =
'{
16'h9803, // ADI required Write.
{8'hD6, 8'b1100_0000}, // [7:6] HPD Control...
// 00 = HPD is from both HPD pin or CDC HPD
// 01 = HPD is from CDC HPD
// 10 = HPD is from HPD pin
// 11 = HPD is always high
16'h4110, // Power Down control
16'h9A70, // ADI required Write.
16'h9C30, // ADI required Write.
{8'h9D, 8'b0110_0001}, // [7:4] must be b0110!.
// [3:2] b00 = Input clock not divided. b01 = Clk divided by 2. b10 = Clk divided by 4. b11 = invalid!
// [1:0] must be b01!
16'hA2A4, // ADI required Write.
16'hA3A4, // ADI required Write.
16'hE0D0, // ADI required Write.
16'h35_40,
16'h36_D9,
16'h37_0A,
16'h38_00,
16'h39_2D,
16'h3A_00,
{8'h16, 8'b0011_1000}, // Output Format 444 [7]=0.
// [6] must be 0!
// Colour Depth for Input Video data [5:4] b11 = 8-bit.
// Input Style [3:2] b10 = Style 1 (ignored when using 444 input).
// DDR Input Edge falling [1]=0 (not using DDR atm).
// Output Colour Space RGB [0]=0.
{8'h17, 8'b01100010}, // Aspect ratio 16:9 [1]=1, 4:3 [1]=0
{8'h18, ypbpr ? 8'h86 : limited[0] ? 8'h8D : limited[1] ? 8'h8E : 8'h00}, // CSC Scaling Factors and Coefficients for RGB Full->Limited.
{8'h19, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE}, // Taken from table in ADV7513 Programming Guide.
{8'h1A, ypbpr ? 8'h1A : 8'h00}, // CSC Channel A.
{8'h1B, ypbpr ? 8'h3F : 8'h00},
{8'h1C, ypbpr ? 8'h1E : 8'h00},
{8'h1D, ypbpr ? 8'hE2 : 8'h00},
{8'h1E, ypbpr ? 8'h07 : 8'h01},
{8'h1F, ypbpr ? 8'hE7 : 8'h00},
{8'h20, ypbpr ? 8'h04 : 8'h00}, // CSC Channel B.
{8'h21, ypbpr ? 8'h1C : 8'h00},
{8'h22, ypbpr ? 8'h08 : limited[0] ? 8'h0D : 8'h0E},
{8'h23, ypbpr ? 8'h11 : limited[0] ? 8'hBC : 8'hFE},
{8'h24, ypbpr ? 8'h01 : 8'h00},
{8'h25, ypbpr ? 8'h91 : 8'h00},
{8'h26, ypbpr ? 8'h01 : 8'h01},
{8'h27, 8'h00},
{8'h28, ypbpr ? 8'h1D : 8'h00}, // CSC Channel C.
{8'h29, ypbpr ? 8'hAE : 8'h00},
{8'h2A, ypbpr ? 8'h1B : 8'h00},
{8'h2B, ypbpr ? 8'h73 : 8'h00},
{8'h2C, ypbpr ? 8'h06 : limited[0] ? 8'h0D : 8'h0E},
{8'h2D, ypbpr ? 8'hDF : limited[0] ? 8'hBC : 8'hFE},
{8'h2E, ypbpr ? 8'h07 : 8'h01},
{8'h2F, ypbpr ? 8'hE7 : 8'h00},
{8'h3B, 8'b0000_0000}, // Pixel repetition [6:5] b00 AUTO. [4:3] b00 x1 mult of input clock. [2:1] b00 x1 pixel rep to send to HDMI Rx.
16'h4000, // General Control Packet Enable
{8'h48, 8'b0000_1000}, // [6]=0 Normal bus order!
// [5] DDR Alignment.
// [4:3] b01 Data right justified (for YCbCr 422 input modes).
16'h49A8, // ADI required Write.
16'h4C00, // ADI required Write.
{8'h55, 8'b0001_0000}, // [7] must be 0!. Set RGB444 in AVinfo Frame [6:5], Set active format [4].
// AVI InfoFrame Valid [4].
// Bar Info [3:2] b00 Bars invalid. b01 Bars vertical. b10 Bars horizontal. b11 Bars both.
// Scan Info [1:0] b00 (No data). b01 TV. b10 PC. b11 None.
{8'h57, 1'b0, // [7] IT Content. 0 - No. 1 - Yes (type set in register h59).
3'b000, // [6:4] Color space (ignored for RGB)
(ypbpr | limited) ? 2'b01 : 2'b10, // [3:2] RGB Quantization range
2'b00}, // [1:0] Non-Uniform Scaled: 00 - None. 01 - Horiz. 10 - Vert. 11 - Both.
16'h7301,
{8'h94, 8'b1000_0000}, // [7]=1 HPD Interrupt ENabled.
16'h9902, // ADI required Write.
16'h9B18, // ADI required Write.
16'h9F00, // ADI required Write.
{8'hA1, 8'b0000_0000}, // [6]=1 Monitor Sense Power Down DISabled.
16'hA408, // ADI required Write.
16'hA504, // ADI required Write.
16'hA600, // ADI required Write.
16'hA700, // ADI required Write.
16'hA800, // ADI required Write.
16'hA900, // ADI required Write.
16'hAA00, // ADI required Write.
16'hAB40, // ADI required Write.
{8'hAF, 6'b0000_01,~dvi_mode,1'b0}, // [7]=0 HDCP Disabled.
// [6:5] must be b00!
// [4]=0 Current frame is unencrypted
// [3:2] must be b01!
// [1]=1 HDMI Mode.
// [0] must be b0!
16'hB900, // ADI required Write.
{8'hBA, 8'b0110_0000}, // [7:5] Input Clock delay...
// b000 = -1.2ns.
// b001 = -0.8ns.
// b010 = -0.4ns.
// b011 = No delay.
// b100 = 0.4ns.
// b101 = 0.8ns.
// b110 = 1.2ns.
// b111 = 1.6ns.
16'hBB00, // ADI required Write.
16'hDE9C, // ADI required Write.
16'hE460, // ADI required Write.
16'hFA7D, // Nbr of times to search for good phase
// (Audio stuff on Programming Guide, Page 66)...
{8'h0A, 8'b0000_0000}, // [6:4] Audio Select. b000 = I2S.
// [3:2] Audio Mode. (HBR stuff, leave at 00!).
{8'h0B, 8'b0000_1110}, //
{8'h0C, 8'b0000_0100}, // [7] 0 = Use sampling rate from I2S stream. 1 = Use samp rate from I2C Register.
// [6] 0 = Use Channel Status bits from stream. 1 = Use Channel Status bits from I2C register.
// [2] 1 = I2S0 Enable.
// [1:0] I2S Format: 00 = Standard. 01 = Right Justified. 10 = Left Justified. 11 = AES.
{8'h0D, 8'b0001_0000}, // [4:0] I2S Bit (Word) Width for Right-Justified.
{8'h14, 8'b0000_0010}, // [3:0] Audio Word Length. b0010 = 16 bits.
{8'h15, audio_96k, 7'b010_0000}, // I2S Sampling Rate [7:4]. b0000 = (44.1KHz). b0010 = 48KHz.
// Input ID [3:1] b000 (0) = 24-bit RGB 444 or YCrCb 444 with Separate Syncs.
// Audio Clock Config
16'h0100, //
audio_96k ? 16'h0230 : 16'h0218, // Set N Value 12288/6144
16'h0300, //
16'h0701, //
16'h0822, // Set CTS Value 74250
16'h090A, //
16'hFFFF // END
};
////////////////////////////////////////////////////////////////////
endmodule

View File

@@ -24,13 +24,13 @@
// Use buffer to access SD card. It's time-critical part.
//
// WIDE=1 for 16 bit file I/O
// VDNUM 1..4
// VDNUM 1..10
// BLKSZ 0..7: 0 = 128, 1 = 256, 2 = 512(default), .. 7 = 16384
//
module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1, BLKSZ=2, PS2WE=0)
(
input clk_sys,
inout [45:0] HPS_BUS,
inout [48:0] HPS_BUS,
// buttons up to 32
output reg [31:0] joystick_0,
@@ -55,6 +55,13 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1,
output reg [15:0] joystick_r_analog_4,
output reg [15:0] joystick_r_analog_5,
input [15:0] joystick_0_rumble, // 15:8 - 'large' rumble motor magnitude, 7:0 'small' rumble motor magnitude
input [15:0] joystick_1_rumble,
input [15:0] joystick_2_rumble,
input [15:0] joystick_3_rumble,
input [15:0] joystick_4_rumble,
input [15:0] joystick_5_rumble,
// paddle 0..255
output reg [7:0] paddle_0,
output reg [7:0] paddle_1,
@@ -71,21 +78,47 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1,
output reg [8:0] spinner_4,
output reg [8:0] spinner_5,
// ps2 keyboard emulation
output ps2_kbd_clk_out,
output ps2_kbd_data_out,
input ps2_kbd_clk_in,
input ps2_kbd_data_in,
input [2:0] ps2_kbd_led_status,
input [2:0] ps2_kbd_led_use,
output ps2_mouse_clk_out,
output ps2_mouse_data_out,
input ps2_mouse_clk_in,
input ps2_mouse_data_in,
// ps2 alternative interface.
// [8] - extended, [9] - pressed, [10] - toggles with every press/release
output reg [10:0] ps2_key = 0,
// [24] - toggles with every event
output reg [24:0] ps2_mouse = 0,
output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements
output [1:0] buttons,
output forced_scandoubler,
output direct_video,
output reg [63:0] status,
input [63:0] status_in,
input status_set,
input [15:0] status_menumask,
input info_req,
input [7:0] info,
input video_rotated,
//toggle to force notify of video mode change
input new_vmode,
inout [21:0] gamma_bus,
output reg [127:0] status,
input [127:0] status_in,
input status_set,
input [15:0] status_menumask,
input info_req,
input [7:0] info,
// SD config
output reg [VD:0] img_mounted, // signaling that new image has been mounted
output reg img_readonly, // mounted as read only. valid only for active bit in img_mounted
@@ -111,7 +144,8 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1,
output reg [26:0] ioctl_addr, // in WIDE mode address will be incremented by 2
output reg [DW:0] ioctl_dout,
output reg ioctl_upload = 0, // signal indicating an active upload
input ioctl_upload_req,
input ioctl_upload_req, // request to save (must be supported on HPS side for specific core)
input [7:0] ioctl_upload_index,
input [DW:0] ioctl_din,
output reg ioctl_rd,
output reg [31:0] ioctl_file_ext,
@@ -131,31 +165,6 @@ module hps_io #(parameter CONF_STR, CONF_STR_BRAM=1, PS2DIV=0, WIDE=0, VDNUM=1,
output reg [7:0] uart_mode,
output reg [31:0] uart_speed,
// ps2 keyboard emulation
output ps2_kbd_clk_out,
output ps2_kbd_data_out,
input ps2_kbd_clk_in,
input ps2_kbd_data_in,
input [2:0] ps2_kbd_led_status,
input [2:0] ps2_kbd_led_use,
output ps2_mouse_clk_out,
output ps2_mouse_data_out,
input ps2_mouse_clk_in,
input ps2_mouse_data_in,
// ps2 alternative interface.
// [8] - extended, [9] - pressed, [10] - toggles with every press/release
output reg [10:0] ps2_key = 0,
// [24] - toggles with every event
output reg [24:0] ps2_mouse = 0,
output reg [15:0] ps2_mouse_ext = 0, // 15:8 - reserved(additional buttons), 7:0 - wheel movements
inout [21:0] gamma_bus,
// for core-specific extensions
inout [35:0] EXT_BUS
);
@@ -215,6 +224,7 @@ video_calc video_calc
.vs_hdmi(HPS_BUS[44]),
.f1(HPS_BUS[45]),
.new_vmode(new_vmode),
.video_rotated(video_rotated),
.par_num(byte_cnt[3:0]),
.dout(vc_dout)
@@ -256,7 +266,7 @@ always@(posedge clk_sys) begin : uio_block
reg [3:0] pdsp_idx;
reg ps2skip = 0;
reg [3:0] stflg = 0;
reg [63:0] status_req;
reg[127:0] status_req;
reg old_status_set = 0;
reg old_upload_req = 0;
reg upload_req = 0;
@@ -316,12 +326,23 @@ always@(posedge clk_sys) begin : uio_block
'h0X17,
'h0X18: begin sd_ack <= disk[VD:0]; sdn_ack <= io_din[11:8]; end
'h29: io_dout <= {4'hA, stflg};
'h2B: io_dout <= 1;
`ifdef MISTER_DISABLE_ADAPTIVE
'h2B: io_dout <= {HPS_BUS[48:46],4'b0110};
`else
'h2B: io_dout <= {HPS_BUS[48:46],4'b0111};
`endif
'h2F: io_dout <= 1;
'h32: io_dout <= gamma_bus[21];
'h36: begin io_dout <= info_n; info_n <= 0; end
'h39: io_dout <= 1;
'h3C: if(upload_req) begin io_dout <= 1; upload_req <= 0; end
'h3C: if(upload_req) begin io_dout <= {ioctl_upload_index, 8'd1}; upload_req <= 0; end
'h3E: io_dout <= 1; // shadow mask
'h003F: io_dout <= joystick_0_rumble;
'h013F: io_dout <= joystick_1_rumble;
'h023F: io_dout <= joystick_2_rumble;
'h033F: io_dout <= joystick_3_rumble;
'h043F: io_dout <= joystick_4_rumble;
'h053F: io_dout <= joystick_5_rumble;
endcase
sd_buff_addr <= 0;
@@ -447,13 +468,17 @@ always@(posedge clk_sys) begin : uio_block
// send image info
'h1d: if(byte_cnt<5) img_size[{byte_cnt-1'b1, 4'b0000} +:16] <= io_din;
// status, 64bit version
'h1e: if(!byte_cnt[MAX_W:3]) begin
case(byte_cnt[2:0])
1: status[15:00] <= io_din;
2: status[31:16] <= io_din;
3: status[47:32] <= io_din;
4: status[63:48] <= io_din;
// status, 128bit version
'h1e: if(!byte_cnt[MAX_W:4]) begin
case(byte_cnt[3:0])
1: status[15:00] <= io_din;
2: status[31:16] <= io_din;
3: status[47:32] <= io_din;
4: status[63:48] <= io_din;
5: status[79:64] <= io_din;
6: status[95:80] <= io_din;
7: status[111:96] <= io_din;
8: status[127:112] <= io_din;
endcase
end
@@ -483,12 +508,16 @@ always@(posedge clk_sys) begin : uio_block
'h24: TIMESTAMP[(byte_cnt-6'd1)<<4 +:16] <= io_din;
//status set
'h29: if(!byte_cnt[MAX_W:3]) begin
case(byte_cnt[2:0])
'h29: if(!byte_cnt[MAX_W:4]) begin
case(byte_cnt[3:0])
1: io_dout <= status_req[15:00];
2: io_dout <= status_req[31:16];
3: io_dout <= status_req[47:32];
4: io_dout <= status_req[63:48];
5: io_dout <= status_req[79:64];
6: io_dout <= status_req[95:80];
7: io_dout <= status_req[111:96];
8: io_dout <= status_req[127:112];
endcase
end
@@ -841,6 +870,7 @@ module video_calc
input vs_hdmi,
input f1,
input new_vmode,
input video_rotated,
input [3:0] par_num,
output reg [15:0] dout
@@ -848,7 +878,7 @@ module video_calc
always @(posedge clk_sys) begin
case(par_num)
1: dout <= {|vid_int, vid_nres};
1: dout <= {video_rotated, |vid_int, vid_nres};
2: dout <= vid_hcnt[15:0];
3: dout <= vid_hcnt[31:16];
4: dout <= vid_vcnt[15:0];

View File

@@ -5,11 +5,11 @@ module scanlines #(parameter v2=0)
input [1:0] scanlines,
input [23:0] din,
input hs_in,vs_in,
input de_in,
input de_in,ce_in,
output reg [23:0] dout,
output reg hs_out,vs_out,
output reg de_out
output reg de_out,ce_out
);
reg [1:0] scanline;
@@ -56,12 +56,13 @@ end
always @(posedge clk) begin
reg [23:0] dout1, dout2;
reg de1,de2,vs1,vs2,hs1,hs2;
reg de1,de2,vs1,vs2,hs1,hs2,ce1,ce2;
dout <= dout2; dout2 <= dout1; dout1 <= d;
vs_out <= vs2; vs2 <= vs1; vs1 <= vs_in;
hs_out <= hs2; hs2 <= hs1; hs1 <= hs_in;
de_out <= de2; de2 <= de1; de1 <= de_in;
ce_out <= ce2; ce2 <= ce1; ce1 <= ce_in;
end
endmodule

136
sys/shadowmask.sv Normal file
View File

@@ -0,0 +1,136 @@
module shadowmask
(
input clk,
input clk_sys,
input cmd_wr,
input [15:0] cmd_in,
input [23:0] din,
input hs_in,vs_in,
input de_in,
input brd_in,
input enable,
output reg [23:0] dout,
output reg hs_out,vs_out,
output reg de_out
);
reg [4:0] hmax;
reg [4:0] vmax;
reg [7:0] mask_idx;
reg mask_2x;
reg mask_rotate;
reg mask_enable;
reg [10:0] mask_lut[256];
always @(posedge clk) begin
reg [4:0] hcount;
reg [4:0] vcount;
reg [3:0] hindex;
reg [3:0] vindex;
reg [4:0] hmax2;
reg [4:0] vmax2;
reg [11:0] pcnt,pde;
reg old_hs, old_vs, old_brd;
reg next_v;
old_hs <= hs_in;
old_vs <= vs_in;
old_brd<= brd_in;
// hcount and vcount counts pixel rows and columns
// hindex and vindex half the value of the counters for double size patterns
// hindex2, vindex2 swap the h and v counters for drawing rotated masks
hindex <= mask_2x ? hcount[4:1] : hcount[3:0];
vindex <= mask_2x ? vcount[4:1] : vcount[3:0];
mask_idx <= mask_rotate ? {hindex,vindex} : {vindex,hindex};
// hmax and vmax store these sizes
// hmax2 and vmax2 swap the values to handle rotation
hmax2 <= ((mask_rotate ? vmax : hmax) << mask_2x) | mask_2x;
vmax2 <= ((mask_rotate ? hmax : vmax) << mask_2x) | mask_2x;
pcnt <= pcnt+1'd1;
if(old_brd && ~brd_in) pde <= pcnt-4'd3;
hcount <= hcount+1'b1;
if(hcount == hmax2 || pde == pcnt) hcount <= 0;
if(~old_brd && brd_in) next_v <= 1;
if(old_vs && ~vs_in) vcount <= 0;
if(old_hs && ~hs_in) begin
vcount <= vcount + next_v;
next_v <= 0;
pcnt <= 0;
if (vcount == vmax2) vcount <= 0;
end
end
reg [4:0] r_mul, g_mul, b_mul; // 1.4 fixed point multipliers
always @(posedge clk) begin
reg [10:0] lut;
lut <= mask_lut[mask_idx];
r_mul <= 5'b10000; g_mul <= 5'b10000; b_mul <= 5'b10000; // default 100% to all channels
if (mask_enable) begin
r_mul <= lut[10] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]};
g_mul <= lut[9] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]};
b_mul <= lut[8] ? {1'b1,lut[7:4]} : {1'b0,lut[3:0]};
end
end
always @(posedge clk) begin
reg [11:0] vid;
reg [7:0] r1, g1, b1;
reg [7:0] r2, g2, b2;
reg [7:0] r3_x, g3_x, b3_x; // 6.25% + 12.5%
reg [8:0] r3_y, g3_y, b3_y; // 25% + 50% + 100%
reg [8:0] r4, g4, b4;
// C1 - data input
{r1,g1,b1} <= din;
vid <= {vid[8:0],vs_in, hs_in, de_in};
// C2 - relax timings
{r2,g2,b2} <= {r1,g1,b1};
// C3 - perform multiplications
r3_x <= ({4{r_mul[0]}} & r2[7:4]) + ({8{r_mul[1]}} & r2[7:3]);
r3_y <= ({6{r_mul[2]}} & r2[7:2]) + ({7{r_mul[3]}} & r2[7:1]) + ({9{r_mul[4]}} & r2[7:0]);
g3_x <= ({4{g_mul[0]}} & g2[7:4]) + ({8{g_mul[1]}} & g2[7:3]);
g3_y <= ({6{g_mul[2]}} & g2[7:2]) + ({7{g_mul[3]}} & g2[7:1]) + ({9{g_mul[4]}} & g2[7:0]);
b3_x <= ({4{b_mul[0]}} & b2[7:4]) + ({8{b_mul[1]}} & b2[7:3]);
b3_y <= ({6{b_mul[2]}} & b2[7:2]) + ({7{b_mul[3]}} & b2[7:1]) + ({9{b_mul[4]}} & b2[7:0]);
// C4 - combine results
r4 <= r3_x + r3_y;
g4 <= g3_x + g3_y;
b4 <= b3_x + b3_y;
// C5 - clamp and output
dout <= {{8{r4[8]}} | r4[7:0], {8{g4[8]}} | g4[7:0], {8{b4[8]}} | b4[7:0]};
{vs_out,hs_out,de_out} <= vid[11:9];
end
// clock in mask commands
always @(posedge clk_sys) begin
reg m_enable;
reg [7:0] idx;
if (cmd_wr) begin
case(cmd_in[15:13])
3'b000: begin {m_enable, mask_rotate, mask_2x} <= cmd_in[3:1]; idx <= 0; end
3'b001: vmax <= cmd_in[3:0];
3'b010: hmax <= cmd_in[3:0];
3'b011: begin mask_lut[idx] <= cmd_in[10:0]; idx <= idx + 1'd1; end
endcase
end
mask_enable <= m_enable & enable;
end
endmodule

View File

@@ -7,6 +7,7 @@ set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) m
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hq2x.sv ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scandoubler.v ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) scanlines.v ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) shadowmask.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_cleaner.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) gamma_corr.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) video_mixer.sv ]
@@ -24,7 +25,6 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) i
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ltc2308.sv ]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sigma_delta_dac.v ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mt32pi.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) hdmi_config.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) mcp23009.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) f2sdram_safe_terminator.sv ]
set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) ddr_svc.sv ]

View File

@@ -45,6 +45,7 @@ set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to SDRAM2_
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to SDRAM2_*
set_instance_assignment -name FAST_OUTPUT_ENABLE_REGISTER ON -to SDRAM2_DQ[*]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to SDRAM2_DQ[*]
set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to SDRAM2_DQ[*]
set_instance_assignment -name ALLOW_SYNCH_CTRL_USAGE OFF -to *|SDRAM2_*
set_global_assignment -name VERILOG_MACRO "DUAL_SDRAM=1"
set_global_assignment -name VERILOG_MACRO "MISTER_DUAL_SDRAM=1"

View File

@@ -28,11 +28,12 @@ set_false_path -to [get_ports {VGA_*}]
set_false_path -to [get_ports {AUDIO_SPDIF}]
set_false_path -to [get_ports {AUDIO_L}]
set_false_path -to [get_ports {AUDIO_R}]
set_false_path -from {get_ports {SW[*]}}
set_false_path -to {cfg[*]}
set_false_path -from {cfg[*]}
set_false_path -from {VSET[*]}
set_false_path -to {wcalc[*] hcalc[*]}
set_false_path -to {hdmi_width[*] hdmi_height[*]}
set_false_path -to {hdmi_width[*] hdmi_height[*]}
set_multicycle_path -to {*_osd|osd_vcnt*} -setup 2
set_multicycle_path -to {*_osd|osd_vcnt*} -hold 1
@@ -55,6 +56,7 @@ set_false_path -from {FB_BASE[*] FB_BASE[*] FB_WIDTH[*] FB_HEIGHT[*] LFB_HMIN[*]
set_false_path -to {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]}
set_false_path -from {vol_att[*] scaler_flt[*] led_overtake[*] led_state[*]}
set_false_path -from {aflt_* acx* acy* areset* arc*}
set_false_path -from {arx* ary*}
set_false_path -from {vs_line*}
set_false_path -from {ascal|o_ihsize*}
@@ -62,7 +64,7 @@ set_false_path -from {ascal|o_ivsize*}
set_false_path -from {ascal|o_format*}
set_false_path -from {ascal|o_hdown}
set_false_path -from {ascal|o_vdown}
set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax*}
set_false_path -from {ascal|o_hmin* ascal|o_hmax* ascal|o_vmin* ascal|o_vmax* ascal|o_vrrmax* ascal|o_vrr}
set_false_path -from {ascal|o_hdisp* ascal|o_vdisp*}
set_false_path -from {ascal|o_htotal* ascal|o_vtotal*}
set_false_path -from {ascal|o_hsstart* ascal|o_vsstart* ascal|o_hsend* ascal|o_vsend*}

View File

@@ -168,7 +168,7 @@ assign LED = (led_overtake & led_state) | (~led_overtake & {1'b0,led_locked,1'b0
wire btn_r, btn_o, btn_u;
`ifdef MISTER_DUAL_SDRAM
assign {btn_r,btn_o,btn_u} = {mcp_btn[1],mcp_btn[2],mcp_btn[0]};
assign {btn_r,btn_o,btn_u} = SW[3] ? {mcp_btn[1],mcp_btn[2],mcp_btn[0]} : ~{SDRAM2_DQ[9],SDRAM2_DQ[13],SDRAM2_DQ[11]};
`else
assign {btn_r,btn_o,btn_u} = ~{BTN_RESET,BTN_OSD,BTN_USER} | {mcp_btn[1],mcp_btn[2],mcp_btn[0]};
`endif
@@ -212,13 +212,13 @@ end
// gp_in[31] = 0 - quick flag that FPGA is initialized (HPS reads 1 when FPGA is not in user mode)
// used to avoid lockups while JTAG loading
wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], SW[3], 8'd0, io_ver, io_ack, io_wide, io_dout};
wire [31:0] gp_in = {1'b0, btn_user | btn[1], btn_osd | btn[0], SW[3], 8'd0, io_ver, io_ack, io_wide, io_dout | io_dout_sys};
wire [31:0] gp_out;
wire [1:0] io_ver = 1; // 0 - obsolete. 1 - optimized HPS I/O. 2,3 - reserved for future.
wire io_wait;
wire io_wide;
wire [15:0] io_dout;
wire [15:0] io_dout;
wire [15:0] io_din = gp_outr[15:0];
wire io_clk = gp_outr[17];
wire io_ss0 = gp_outr[18];
@@ -270,7 +270,6 @@ reg [15:0] cfg;
reg cfg_set = 0;
wire vga_fb = cfg[12] | vga_force_scaler;
wire [1:0] hdmi_limited = {cfg[11],cfg[8]};
`ifdef MISTER_DEBUG_NOHDMI
wire direct_video = 1;
@@ -278,12 +277,11 @@ wire direct_video = 1;
wire direct_video = cfg[10];
`endif
wire dvi_mode = cfg[7];
wire audio_96k = cfg[6];
wire csync_en = cfg[3];
wire ypbpr_en = cfg[5];
wire io_osd_vga = io_ss1 & ~io_ss2;
`ifndef MISTER_DUAL_SDRAM
wire ypbpr_en = cfg[5];
wire sog = cfg[9];
wire vga_scaler = cfg[2] | vga_force_scaler;
`endif
@@ -295,8 +293,8 @@ reg [31:0] cfg_custom_p2;
reg [4:0] vol_att;
initial vol_att = 5'b11111;
reg [6:0] coef_addr;
reg [8:0] coef_data;
reg [11:0] coef_addr;
reg [9:0] coef_data;
reg coef_wr = 0;
wire[12:0] ARX, ARY;
@@ -304,12 +302,13 @@ reg [11:0] VSET = 0, HSET = 0;
reg FREESCALE = 0;
reg [2:0] scaler_flt;
reg lowlat = 0;
reg cfg_dis = 0;
reg cfg_done = 0;
reg vs_wait = 0;
reg [11:0] vs_line = 0;
reg scaler_out = 0;
reg vrr_mode = 0;
reg [31:0] aflt_rate = 7056000;
reg [39:0] acx = 4258969;
@@ -324,27 +323,33 @@ reg [12:0] arc1x = 0;
reg [12:0] arc1y = 0;
reg [12:0] arc2x = 0;
reg [12:0] arc2y = 0;
reg [15:0] io_dout_sys;
always@(posedge clk_sys) begin
reg [7:0] cmd;
reg has_cmd;
reg old_strobe;
reg [7:0] cnt = 0;
reg vs_d0,vs_d1,vs_d2;
reg [4:0] acx_att;
reg [7:0] fb_crc;
old_strobe <= io_strobe;
coef_wr <= 0;
`ifndef MISTER_DEBUG_NOHDMI
shadowmask_wr <= 0;
`endif
if(~io_uio) begin
has_cmd <= 0;
cmd <= 0;
areset <= 0;
acx_att <= 0;
acx <= acx >> acx_att;
io_dout_sys <= 0;
end
else
if(~old_strobe & io_strobe) begin
if(io_strobe) begin
io_dout_sys <= 0;
if(!has_cmd) begin
has_cmd <= 1;
cmd <= io_din[7:0];
@@ -361,8 +366,13 @@ always@(posedge clk_sys) begin
acy2 <= -24'd2023767;
areset <= 1;
end
if(io_din[7:0] == 'h20) io_dout_sys <= 'b11;
`ifndef MISTER_DEBUG_NOHDMI
if(io_din[7:0] == 'h40) io_dout_sys <= fb_crc;
`endif
end
else begin
cnt <= cnt + 1'd1;
if(cmd == 1) begin
cfg <= io_din;
cfg_set <= 1;
@@ -370,17 +380,16 @@ always@(posedge clk_sys) begin
end
if(cmd == 'h20) begin
cfg_set <= 0;
cnt <= cnt + 1'd1;
if(cnt<8) begin
case(cnt[2:0])
0: if(WIDTH != io_din[11:0]) WIDTH <= io_din[11:0];
1: if(HFP != io_din[11:0]) HFP <= io_din[11:0];
2: if(HS != io_din[11:0]) HS <= io_din[11:0];
3: if(HBP != io_din[11:0]) HBP <= io_din[11:0];
4: if(HEIGHT != io_din[11:0]) HEIGHT <= io_din[11:0];
5: if(VFP != io_din[11:0]) VFP <= io_din[11:0];
6: if(VS != io_din[11:0]) VS <= io_din[11:0];
7: if(VBP != io_din[11:0]) VBP <= io_din[11:0];
0: {HDMI_PR,vrr_mode,WIDTH} <= {io_din[15:14], io_din[11:0]};
1: HFP <= io_din[11:0];
2: HS <= {io_din[15], io_din[11:0]};
3: HBP <= io_din[11:0];
4: HEIGHT <= io_din[11:0];
5: VFP <= io_din[11:0];
6: VS <= {io_din[15],io_din[11:0]};
7: VBP <= io_din[11:0];
endcase
`ifndef MISTER_DEBUG_NOHDMI
if(cnt == 1) begin
@@ -397,12 +406,11 @@ always@(posedge clk_sys) begin
cfg_custom_t <= ~cfg_custom_t;
cnt[2:0] <= 3'b100;
end
if(cnt == 8) {lowlat,cfg_dis} <= io_din[15:14];
if(cnt == 8) {lowlat,cfg_done} <= {io_din[15],1'b1};
`endif
end
end
if(cmd == 'h2F) begin
cnt <= cnt + 1'd1;
case(cnt[3:0])
0: {LFB_EN,LFB_FLT,LFB_FMT} <= {io_din[15], io_din[14], io_din[5:0]};
1: LFB_BASE[15:0] <= io_din[15:0];
@@ -419,12 +427,14 @@ always@(posedge clk_sys) begin
if(cmd == 'h25) {led_overtake, led_state} <= io_din;
if(cmd == 'h26) vol_att <= io_din[4:0];
if(cmd == 'h27) VSET <= io_din[11:0];
if(cmd == 'h2A) {coef_wr,coef_addr,coef_data} <= {1'b1,io_din};
if(cmd == 'h2A) begin
if(cnt[0]) {coef_wr,coef_data} <= {1'b1,io_din[9:0]};
else coef_addr <= io_din[11:0];
end
if(cmd == 'h2B) scaler_flt <= io_din[2:0];
if(cmd == 'h37) {FREESCALE,HSET} <= {io_din[15],io_din[11:0]};
if(cmd == 'h38) vs_line <= io_din[11:0];
if(cmd == 'h39) begin
cnt <= cnt + 1'd1;
case(cnt[3:0])
0: acx_att <= io_din[4:0];
1: aflt_rate[15:0] <= io_din;
@@ -444,7 +454,6 @@ always@(posedge clk_sys) begin
endcase
end
if(cmd == 'h3A) begin
cnt <= cnt + 1'd1;
case(cnt[3:0])
0: arc1x <= io_din[12:0];
1: arc1y <= io_din[12:0];
@@ -452,9 +461,32 @@ always@(posedge clk_sys) begin
3: arc2y <= io_din[12:0];
endcase
end
`ifndef MISTER_DEBUG_NOHDMI
if(cmd == 'h3E) {shadowmask_wr,shadowmask_data} <= {1'b1, io_din};
if(cmd == 'h40) begin
case(cnt[3:0])
0: io_dout_sys <= {arxy, arx};
1: io_dout_sys <= {arxy, ary};
2: io_dout_sys <= {LFB_EN, FB_EN, FB_FMT};
3: io_dout_sys <= FB_WIDTH;
4: io_dout_sys <= FB_HEIGHT;
5: io_dout_sys <= FB_BASE[15:0];
6: io_dout_sys <= FB_BASE[31:16];
7: io_dout_sys <= FB_STRIDE;
endcase
end
`endif
end
end
`ifndef MISTER_DEBUG_NOHDMI
fb_crc <= {LFB_EN, FB_EN, FB_FMT}
^ FB_WIDTH[7:0] ^ FB_WIDTH[11:8]
^ FB_HEIGHT[7:0] ^ FB_HEIGHT[11:8]
^ arx[7:0] ^ arx[11:8] ^ arxy
^ ary[7:0] ^ ary[11:8];
`endif
vs_d0 <= HDMI_TX_VS;
if(vs_d0 == HDMI_TX_VS) vs_d1 <= vs_d0;
@@ -618,7 +650,7 @@ wire [15:0] vbuf_byteenable;
wire vbuf_write;
wire [23:0] hdmi_data;
wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl;
wire hdmi_vs, hdmi_hs, hdmi_de, hdmi_vbl, hdmi_brd;
wire freeze;
`ifndef MISTER_DEBUG_NOHDMI
@@ -627,6 +659,11 @@ wire clk_hdmi = hdmi_clk_out;
ascal
#(
.RAMBASE(32'h20000000),
`ifdef MISTER_SMALL_VBUF
.RAMSIZE(32'h00200000),
`else
.RAMSIZE(32'h00800000),
`endif
`ifndef MISTER_FB
.PALETTE2("false"),
`else
@@ -634,6 +671,13 @@ ascal
.PALETTE2("false"),
`endif
`endif
`ifdef MISTER_DISABLE_ADAPTIVE
.ADAPTIVE("false"),
`endif
`ifdef MISTER_DOWNSCALE_NN
.DOWNSCALE_NN("true"),
`endif
.FRAC(8),
.N_DW(128),
.N_AW(28)
)
@@ -667,19 +711,22 @@ ascal
.o_vs (hdmi_vs),
.o_de (hdmi_de),
.o_vbl (hdmi_vbl),
.o_brd (hdmi_brd),
.o_lltune (lltune),
.htotal (WIDTH + HFP + HBP + HS),
.htotal (WIDTH + HFP + HBP + HS[11:0]),
.hsstart (WIDTH + HFP),
.hsend (WIDTH + HFP + HS),
.hsend (WIDTH + HFP + HS[11:0]),
.hdisp (WIDTH),
.hmin (hmin),
.hmax (hmax),
.vtotal (HEIGHT + VFP + VBP + VS),
.vtotal (HEIGHT + VFP + VBP + VS[11:0]),
.vsstart (HEIGHT + VFP),
.vsend (HEIGHT + VFP + VS),
.vsend (HEIGHT + VFP + VS[11:0]),
.vdisp (HEIGHT),
.vmin (vmin),
.vmax (vmax),
.vrr (vrr_mode),
.vrrmax (HEIGHT + VBP + VS[11:0] + 12'd1),
.mode ({~lowlat,LFB_EN ? LFB_FLT : |scaler_flt,2'b00}),
.poly_clk (clk_sys),
@@ -789,37 +836,40 @@ reg [11:0] vmax;
reg [11:0] hdmi_height;
reg [11:0] hdmi_width;
reg [11:0] arx;
reg [11:0] ary;
reg arxy;
always @(posedge clk_vid) begin
reg [11:0] hmini,hmaxi,vmini,vmaxi;
reg [11:0] wcalc,videow,arx;
reg [11:0] hcalc,videoh,ary;
reg [11:0] wcalc,videow;
reg [11:0] hcalc,videoh;
reg [2:0] state;
reg xy;
hdmi_height <= (VSET && (VSET < HEIGHT)) ? VSET : HEIGHT;
hdmi_width <= (HSET && (HSET < WIDTH)) ? HSET : WIDTH;
hdmi_width <= (HSET && (HSET < WIDTH)) ? HSET << HDMI_PR : WIDTH << HDMI_PR;
if(!ARY) begin
if(ARX == 1) begin
arx <= arc1x[11:0];
ary <= arc1y[11:0];
xy <= arc1x[12] | arc1y[12];
arx <= arc1x[11:0];
ary <= arc1y[11:0];
arxy <= arc1x[12] | arc1y[12];
end
else if(ARX == 2) begin
arx <= arc2x[11:0];
ary <= arc2y[11:0];
xy <= arc2x[12] | arc2y[12];
arx <= arc2x[11:0];
ary <= arc2y[11:0];
arxy <= arc2x[12] | arc2y[12];
end
else begin
arx <= 0;
ary <= 0;
xy <= 0;
arx <= 0;
ary <= 0;
arxy <= 0;
end
end
else begin
arx <= ARX[11:0];
ary <= ARY[11:0];
xy <= ARX[12] | ARY[12];
arx <= ARX[11:0];
ary <= ARY[11:0];
arxy <= ARX[12] | ARY[12];
end
ar_md_start <= 0;
@@ -837,7 +887,7 @@ always @(posedge clk_vid) begin
hcalc <= hdmi_height;
state <= 6;
end
else if(xy) begin
else if(arxy) begin
wcalc <= arx;
hcalc <= ary;
state <= 6;
@@ -866,7 +916,7 @@ always @(posedge clk_vid) begin
end
6: begin
videow <= (wcalc > hdmi_width) ? hdmi_width : wcalc[11:0];
videow <= (wcalc > hdmi_width) ? (hdmi_width >> HDMI_PR) : (wcalc[11:0] >> HDMI_PR);
videoh <= (hcalc > hdmi_height) ? hdmi_height : hcalc[11:0];
end
@@ -892,7 +942,7 @@ pll_hdmi_adj pll_hdmi_adj
.reset_na(~reset_req),
.llena(lowlat),
.lltune({16{hdmi_config_done | cfg_dis}} & lltune),
.lltune({16{cfg_done}} & lltune),
.locked(led_locked),
.i_waitrequest(adj_waitrequest),
.i_write(adj_write),
@@ -940,14 +990,15 @@ pll_hdmi pll_hdmi
`endif
//1920x1080@60 PCLK=148.5MHz CEA
reg [11:0] WIDTH = 1920;
reg [11:0] HFP = 88;
reg [11:0] HS = 48;
reg [11:0] HBP = 148;
reg [11:0] HEIGHT = 1080;
reg [11:0] VFP = 4;
reg [11:0] VS = 5;
reg [11:0] VBP = 36;
reg [11:0] WIDTH = 1920;
reg [11:0] HFP = 88;
reg [12:0] HS = 48;
reg [11:0] HBP = 148;
reg [11:0] HEIGHT = 1080;
reg [11:0] VFP = 4;
reg [12:0] VS = 5;
reg [11:0] VBP = 36;
reg HDMI_PR = 0;
wire [63:0] reconfig_to_pll;
wire [63:0] reconfig_from_pll;
@@ -1020,22 +1071,6 @@ wire cfg_ready = 1;
`endif
wire hdmi_config_done;
hdmi_config hdmi_config
(
.iCLK(FPGA_CLK1_50),
.iRST_N(cfg_ready & ~HDMI_TX_INT & ~cfg_dis),
.done(hdmi_config_done),
.I2C_SCL(HDMI_I2C_SCL),
.I2C_SDA(HDMI_I2C_SDA),
.dvi_mode(dvi_mode),
.audio_96k(audio_96k),
.limited(hdmi_limited),
.ypbpr(ypbpr_en & direct_video)
);
assign HDMI_I2C_SCL = hdmi_scl_en ? 1'b0 : 1'bZ;
assign HDMI_I2C_SDA = hdmi_sda_en ? 1'b0 : 1'bZ;
@@ -1049,34 +1084,43 @@ cyclonev_hps_interface_peripheral_i2c hdmi_i2c
);
`ifndef MISTER_DEBUG_NOHDMI
wire [23:0] hdmi_data_sl;
wire hdmi_de_sl, hdmi_vs_sl, hdmi_hs_sl;
`ifdef MISTER_FB
reg dis_output;
always @(posedge clk_hdmi) begin
reg dis;
dis <= fb_force_blank;
dis <= fb_force_blank & ~LFB_EN;
dis_output <= dis;
end
`else
wire dis_output = 0;
`endif
scanlines #(1) HDMI_scanlines
wire [23:0] hdmi_data_mask;
wire hdmi_de_mask, hdmi_vs_mask, hdmi_hs_mask;
reg [15:0] shadowmask_data;
reg shadowmask_wr = 0;
shadowmask HDMI_shadowmask
(
.clk(clk_hdmi),
.clk_sys(clk_sys),
.cmd_wr(shadowmask_wr),
.cmd_in(shadowmask_data),
.scanlines(scanlines),
.din(dis_output ? 24'd0 : hdmi_data),
.hs_in(hdmi_hs),
.vs_in(hdmi_vs),
.de_in(hdmi_de),
.dout(hdmi_data_sl),
.hs_out(hdmi_hs_sl),
.vs_out(hdmi_vs_sl),
.de_out(hdmi_de_sl)
.brd_in(hdmi_brd),
.enable(~LFB_EN),
.dout(hdmi_data_mask),
.hs_out(hdmi_hs_mask),
.vs_out(hdmi_vs_mask),
.de_out(hdmi_de_mask)
);
wire [23:0] hdmi_data_osd;
@@ -1091,10 +1135,10 @@ osd hdmi_osd
.io_din(io_din),
.clk_video(clk_hdmi),
.din(hdmi_data_sl),
.hs_in(hdmi_hs_sl),
.vs_in(hdmi_vs_sl),
.de_in(hdmi_de_sl),
.din(hdmi_data_mask),
.hs_in(hdmi_hs_mask),
.vs_in(hdmi_vs_mask),
.de_in(hdmi_de_mask),
.dout(hdmi_data_osd),
.hs_out(hdmi_hs_osd),
@@ -1111,7 +1155,7 @@ reg dv_hs, dv_vs, dv_de;
always @(posedge clk_vid) begin
reg [23:0] dv_d1, dv_d2;
reg dv_de1, dv_de2, dv_hs1, dv_hs2, dv_vs1, dv_vs2;
reg [12:0] vsz, vcnt;
reg [12:0] vsz, vcnt, vcnt_l, vcnt_ll;
reg old_hs, old_vs;
reg vde;
reg [3:0] hss;
@@ -1123,7 +1167,11 @@ always @(posedge clk_vid) begin
if(~old_hs && vga_hs_osd) begin
old_vs <= vga_vs_osd;
if(~&vcnt) vcnt <= vcnt + 1'd1;
if(~old_vs & vga_vs_osd & ~f1) vsz <= vcnt;
if(~old_vs & vga_vs_osd) begin
if (vcnt != vcnt_ll || vcnt < vcnt_l) vsz <= vcnt;
vcnt_l <= vcnt;
vcnt_ll <= vcnt_l;
end
if(old_vs & ~vga_vs_osd) vcnt <= 0;
if(vcnt == 1) vde <= 1;
@@ -1190,13 +1238,21 @@ reg hdmi_out_de;
reg [23:0] hdmi_out_d;
always @(posedge hdmi_tx_clk) begin
reg [23:0] hdmi_dv_data;
reg hdmi_dv_hs, hdmi_dv_vs, hdmi_dv_de;
reg hs,vs,de;
reg [23:0] d;
hs <= (~vga_fb & direct_video) ? dv_hs : (direct_video & csync_en) ? hdmi_cs_osd : hdmi_hs_osd;
vs <= (~vga_fb & direct_video) ? dv_vs : hdmi_vs_osd;
de <= (~vga_fb & direct_video) ? dv_de : hdmi_de_osd;
d <= (~vga_fb & direct_video) ? dv_data : hdmi_data_osd;
hdmi_dv_data <= dv_data;
hdmi_dv_hs <= dv_hs;
hdmi_dv_vs <= dv_vs;
hdmi_dv_de <= dv_de;
hs <= (~vga_fb & direct_video) ? hdmi_dv_hs : (direct_video & csync_en) ? hdmi_cs_osd : hdmi_hs_osd;
vs <= (~vga_fb & direct_video) ? hdmi_dv_vs : hdmi_vs_osd;
de <= (~vga_fb & direct_video) ? hdmi_dv_de : hdmi_de_osd;
d <= (~vga_fb & direct_video) ? hdmi_dv_data : hdmi_data_osd;
hdmi_out_hs <= hs;
hdmi_out_vs <= vs;
@@ -1212,7 +1268,7 @@ assign HDMI_TX_D = hdmi_out_d;
///////////////////////// VGA output //////////////////////////////////
wire [23:0] vga_data_sl;
wire vga_de_sl, vga_vs_sl, vga_hs_sl;
wire vga_de_sl, vga_ce_sl, vga_vs_sl, vga_hs_sl;
scanlines #(0) VGA_scanlines
(
.clk(clk_vid),
@@ -1222,11 +1278,13 @@ scanlines #(0) VGA_scanlines
.hs_in(hs_fix),
.vs_in(vs_fix),
.de_in(de_emu),
.ce_in(ce_pix),
.dout(vga_data_sl),
.hs_out(vga_hs_sl),
.vs_out(vga_vs_sl),
.de_out(vga_de_sl)
.de_out(vga_de_sl),
.ce_out(vga_ce_sl)
);
wire [23:0] vga_data_osd;
@@ -1255,6 +1313,7 @@ wire vga_cs_osd;
csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd);
`ifndef MISTER_DUAL_SDRAM
wire VGA_DISABLE;
wire [23:0] vgas_o;
wire vgas_hs, vgas_vs, vgas_cs;
vga_out vga_scaler_out
@@ -1289,11 +1348,11 @@ csync csync_vga(clk_vid, vga_hs_osd, vga_vs_osd, vga_cs_osd);
wire cs1 = (vga_fb | vga_scaler) ? vgas_cs : vga_cs;
assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ : ((vga_fb | vga_scaler) ? ~vgas_vs : ~vga_vs) | csync_en;
assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : (vga_fb | vga_scaler) ? (csync_en ? ~vgas_cs : ~vgas_hs) : (csync_en ? ~vga_cs : ~vga_hs);
assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : vga_o[23:18];
assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : vga_o[15:10];
assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : vga_o[7:2] ;
assign VGA_VS = (VGA_EN | SW[3]) ? 1'bZ : (((vga_fb | vga_scaler) ? (~vgas_vs ^ VS[12]) : VGA_DISABLE ? 1'd1 : ~vga_vs) | csync_en);
assign VGA_HS = (VGA_EN | SW[3]) ? 1'bZ : ((vga_fb | vga_scaler) ? ((csync_en ? ~vgas_cs : ~vgas_hs) ^ HS[12]) : VGA_DISABLE ? 1'd1 : (csync_en ? ~vga_cs : ~vga_hs));
assign VGA_R = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[23:18] : VGA_DISABLE ? 6'd0 : vga_o[23:18];
assign VGA_G = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[15:10] : VGA_DISABLE ? 6'd0 : vga_o[15:10];
assign VGA_B = (VGA_EN | SW[3]) ? 6'bZZZZZZ : (vga_fb | vga_scaler) ? vgas_o[7:2] : VGA_DISABLE ? 6'd0 : vga_o[7:2] ;
`endif
reg video_sync = 0;
@@ -1461,13 +1520,13 @@ sync_fix sync_h(clk_vid, hs_emu, hs_fix);
wire [6:0] user_out, user_in;
assign clk_ihdmi= clk_vid;
assign ce_hpix = ce_pix;
assign hr_out = r_out;
assign hg_out = g_out;
assign hb_out = b_out;
assign hhs_fix = hs_fix;
assign hvs_fix = vs_fix;
assign hde_emu = de_emu;
assign ce_hpix = vga_ce_sl;
assign hr_out = vga_data_sl[23:16];
assign hg_out = vga_data_sl[15:8];
assign hb_out = vga_data_sl[7:0];
assign hhs_fix = vga_hs_sl;
assign hvs_fix = vga_vs_sl;
assign hde_emu = vga_de_sl;
wire uart_dtr;
wire uart_dsr;
@@ -1504,11 +1563,15 @@ wire [13:0] fb_stride;
assign fb_stride = 0;
`endif
reg [1:0] sl_r;
wire [1:0] sl = sl_r;
always @(posedge clk_sys) sl_r <= FB_EN ? 2'b00 : scanlines;
emu emu
(
.CLK_50M(FPGA_CLK2_50),
.RESET(reset),
.HPS_BUS({f1, HDMI_TX_VS,
.HPS_BUS({fb_en, sl, f1, HDMI_TX_VS,
clk_100m, clk_ihdmi,
ce_hpix, hde_emu, hhs_fix, hvs_fix,
io_wait, clk_sys, io_fpga, io_uio, io_strobe, io_wide, io_din, io_dout}),
@@ -1522,6 +1585,10 @@ emu emu
.VGA_F1(f1),
.VGA_SCALER(vga_force_scaler),
`ifndef MISTER_DUAL_SDRAM
.VGA_DISABLE(VGA_DISABLE),
`endif
.HDMI_WIDTH(direct_video ? 12'd0 : hdmi_width),
.HDMI_HEIGHT(direct_video ? 12'd0 : hdmi_height),
.HDMI_FREEZE(freeze),