1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-01-19 17:27:59 +00:00

IremM62: rewritten video controller specifically for Irem HW

This commit is contained in:
Gyorgy Szombathelyi 2020-03-08 22:45:57 +01:00
parent 8cc7636a5c
commit 28336b943f
9 changed files with 242 additions and 135 deletions

View File

@ -44,40 +44,6 @@ set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL
set_global_assignment -name LAST_QUARTUS_VERSION "13.1 SP4.26"
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
set_global_assignment -name SMART_RECOMPILE ON
set_global_assignment -name SYSTEMVERILOG_FILE rtl/IremM62_MiST.sv
set_global_assignment -name VHDL_FILE rtl/target_top.vhd
set_global_assignment -name VHDL_FILE rtl/platform_variant_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/platform_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/platform.vhd
set_global_assignment -name VHDL_FILE rtl/pace_pkg_body.vhd
set_global_assignment -name VHDL_FILE rtl/pace_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/pace.vhd
set_global_assignment -name VHDL_FILE rtl/Graphics.VHD
set_global_assignment -name VHDL_FILE rtl/video_mixer.vhd
set_global_assignment -name VHDL_FILE rtl/video_controller_pkg_body.vhd
set_global_assignment -name VHDL_FILE rtl/video_controller_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/video_controller.vhd
set_global_assignment -name VHDL_FILE rtl/tilemapctl.vhd
set_global_assignment -name VHDL_FILE rtl/bitmapctl_e.vhd
set_global_assignment -name VHDL_FILE rtl/spritereg.vhd
set_global_assignment -name VHDL_FILE rtl/spritectl.vhd
set_global_assignment -name VHDL_FILE rtl/sprite_pkg_body.vhd
set_global_assignment -name VHDL_FILE rtl/sprite_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/sprite_array.vhd
set_global_assignment -name VHDL_FILE rtl/Inputs.VHD
set_global_assignment -name VHDL_FILE rtl/input_mapper.vhd
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
set_global_assignment -name VHDL_FILE rtl/sprom.vhd
set_global_assignment -name VHDL_FILE rtl/spram.vhd
set_global_assignment -name VHDL_FILE rtl/clk_div.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
set_global_assignment -name VHDL_FILE rtl/cpu68.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/YM2149.sv
set_global_assignment -name VHDL_FILE rtl/Sound_Board.vhd
set_global_assignment -name QIP_FILE ../../common/mist/mist.qip
set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../common/CPU/T80/Z80.vhd
# Pin & Location Assignments
# ==========================
@ -200,7 +166,7 @@ set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
# SignalTap II Assignments
# ========================
set_global_assignment -name ENABLE_SIGNALTAP OFF
set_global_assignment -name USE_SIGNALTAP_FILE output_files/cpu.stp
set_global_assignment -name USE_SIGNALTAP_FILE output_files/sprite.stp
# Power Estimation Assignments
# ============================
@ -268,8 +234,42 @@ set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
# end ENTITY(IremM62_MiST)
# ---------------------------
set_global_assignment -name SIGNALTAP_FILE output_files/sp.stp
set_location_assignment PLL_1 -to pll|altpll_component|auto_generated|pll1
set_global_assignment -name SYSTEMVERILOG_FILE rtl/IremM62_MiST.sv
set_global_assignment -name VHDL_FILE rtl/target_top.vhd
set_global_assignment -name VHDL_FILE rtl/platform_variant_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/platform_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/platform.vhd
set_global_assignment -name VHDL_FILE rtl/pace_pkg_body.vhd
set_global_assignment -name VHDL_FILE rtl/pace_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/pace.vhd
set_global_assignment -name VHDL_FILE rtl/Graphics.VHD
set_global_assignment -name VHDL_FILE rtl/video_mixer.vhd
set_global_assignment -name VHDL_FILE rtl/iremm62_video_controller.vhd
set_global_assignment -name VHDL_FILE rtl/video_controller_pkg_body.vhd
set_global_assignment -name VHDL_FILE rtl/video_controller_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/tilemapctl.vhd
set_global_assignment -name VHDL_FILE rtl/bitmapctl_e.vhd
set_global_assignment -name VHDL_FILE rtl/spritereg.vhd
set_global_assignment -name VHDL_FILE rtl/spritectl.vhd
set_global_assignment -name VHDL_FILE rtl/sprite_pkg_body.vhd
set_global_assignment -name VHDL_FILE rtl/sprite_pkg.vhd
set_global_assignment -name VHDL_FILE rtl/sprite_array.vhd
set_global_assignment -name VHDL_FILE rtl/Inputs.VHD
set_global_assignment -name VHDL_FILE rtl/input_mapper.vhd
set_global_assignment -name VHDL_FILE rtl/dpram.vhd
set_global_assignment -name VHDL_FILE rtl/sprom.vhd
set_global_assignment -name VHDL_FILE rtl/spram.vhd
set_global_assignment -name VHDL_FILE rtl/clk_div.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/sdram.sv
set_global_assignment -name VHDL_FILE rtl/pll_mist.vhd
set_global_assignment -name VHDL_FILE rtl/cpu68.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/YM2149.sv
set_global_assignment -name VHDL_FILE rtl/Sound_Board.vhd
set_global_assignment -name QIP_FILE ../../common/mist/mist.qip
set_global_assignment -name QIP_FILE ../../common/CPU/T80/T80.qip
set_global_assignment -name VHDL_FILE ../../common/CPU/T80/Z80.vhd
set_global_assignment -name SIGNALTAP_FILE output_files/sp.stp
set_global_assignment -name SIGNALTAP_FILE output_files/tilemap.stp
set_global_assignment -name SIGNALTAP_FILE output_files/sprite.stp
set_global_assignment -name SIGNALTAP_FILE output_files/cpu.stp

View File

@ -52,7 +52,6 @@ architecture SYN of Graphics is
signal rgb_data : RGB_t;
-- before OSD is mixed in
signal video_o_s : to_VIDEO_t;
signal irem62_hsize : integer range 0 to 511;
begin
@ -73,32 +72,13 @@ begin
graphics_o.vblank <= video_o_s.vblank;
--graphics_o.vblank <= from_video_ctl.vblank;
irem62_hsize <= 384+16 when hires = '1' else 256+16;
pace_video_controller_inst : entity work.pace_video_controller
generic map
(
CONFIG => PACE_VIDEO_CONTROLLER_TYPE,
DELAY => PACE_VIDEO_PIPELINE_DELAY,
--H_SIZE => PACE_VIDEO_H_SIZE,
V_SIZE => PACE_VIDEO_V_SIZE,
L_CROP => PACE_VIDEO_L_CROP,
R_CROP => PACE_VIDEO_R_CROP,
H_SCALE => PACE_VIDEO_H_SCALE,
V_SCALE => PACE_VIDEO_V_SCALE,
H_SYNC_POL => PACE_VIDEO_H_SYNC_POLARITY,
V_SYNC_POL => PACE_VIDEO_V_SYNC_POLARITY,
BORDER_RGB => PACE_VIDEO_BORDER_RGB
)
iremm62_video_controller_inst : entity work.iremm62_video_controller
port map
(
-- clocking etc
video_i => video_i,
H_SIZE => irem62_hsize,
-- register interface
reg_i.h_scale => "000",
reg_i.v_scale => "000",
hires => hires,
-- video data signals (in)
rgb_i => rgb_data,
@ -207,6 +187,7 @@ begin
(
reset => video_i.reset,
hwsel => hwsel,
hires => hires,
video_ctl => from_video_ctl,
@ -229,6 +210,7 @@ begin
(
reset => video_i.reset,
hwsel => hwsel,
hires => hires,
video_ctl => from_video_ctl,
@ -262,6 +244,7 @@ begin
sprite_prom => sprite_prom,
hwsel => hwsel,
hires => hires,
-- register interface
reg_i => sprite_reg_i,

View File

@ -109,7 +109,7 @@ wire snd_vma;
wire [14:0] chr1_addr;
wire [31:0] chr1_do;
wire [14:0] sp_addr;
wire [15:0] sp_addr;
wire [31:0] sp_do;
/* ROM structure

View File

@ -0,0 +1,129 @@
library IEEE;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library work;
use work.video_controller_pkg.all;
entity iremm62_video_controller is
port
(
-- clocking etc
video_i : in from_VIDEO_t;
hires : in std_logic;
-- video input data
rgb_i : in RGB_t;
-- control signals (out)
video_ctl_o : out from_VIDEO_CTL_t;
-- video output control & data
video_o : out to_VIDEO_t
);
end iremm62_video_controller;
architecture SYN of iremm62_video_controller is
alias clk : std_logic is video_i.clk;
alias clk_ena : std_logic is video_i.clk_ena;
alias reset : std_logic is video_i.reset;
signal hcnt : unsigned(9 downto 0);
signal vcnt : unsigned(8 downto 0);
signal hsync : std_logic;
signal vsync : std_logic;
signal hblank : std_logic;
signal vblank : std_logic;
begin
-------------------
-- Video scanner --
-------------------
-- hcnt [x080..x0FF-x100..x1FF] => 128+256 = 384 pixels, 384/6.144Mhz => 1 line is 62.5us (16.000KHz) (lores)
-- hcnt [x080..x0FF-x100..x27F] => 128+384 = 512 pixels, 512/8.192Mhz => 1 line is 62.5us (16.000KHz) (hires)
-- vcnt [x0E6..x0FF-x100..x1FF] => 26+256 = 282 lines, 1 frame is 260 x 62.5us = 17.625ms (56.74Hz)
process (reset, clk, clk_ena)
begin
if reset='1' then
hcnt <= (others=>'0');
vcnt <= '0'&X"FC";
elsif rising_edge(clk) and clk_ena = '1'then
hcnt <= hcnt + 1;
if (hires = '0' and hcnt = "01"&x"FF") or hcnt = "10"&x"7F" then
hcnt <= "00"&x"80";
vcnt <= vcnt + 1;
if vcnt = '1'&x"FF" then
-- vcnt <= '0'&x"E6"; -- from M52 schematics
vcnt <= '0'&x"C8"; -- 312 lines/PAL 50 Hz
end if;
end if;
end if;
end process;
process (reset, clk, clk_ena)
begin
if reset = '1' then
hsync <= '0';
vsync <= '0';
hblank <= '1';
vblank <= '1';
elsif rising_edge(clk) and clk_ena = '1' then
-- display blank
if hcnt = "00"&x"FF" then
hblank <= '0';
if vcnt = '1'&x"00" then
vblank <= '0';
end if;
end if;
if (hires = '0' and hcnt = "01"&x"FF") or hcnt = "10"&x"7F" then
hblank <= '1';
if vcnt = '1'&x"FF" then
vblank <= '1';
end if;
end if;
-- display sync
if hcnt = "00"&x"8B" then
hsync <= '1';
if vcnt = '0'&x"F2" then
vsync <= '1';
end if;
end if;
if hcnt = "00"&x"B1" then
hsync <= '0';
if vcnt = '0'&x"F4" then
vsync <= '0';
end if;
end if;
-- registered rgb output
if hblank = '1' or vblank = '1' then
video_o.rgb <= RGB_BLACK;
else
video_o.rgb <= rgb_i;
end if;
end if;
end process;
video_o.hsync <= hsync;
video_o.vsync <= vsync;
video_o.hblank <= hblank;
video_o.vblank <= vblank;
video_ctl_o.stb <= '1';
video_ctl_o.x <= '0'&std_logic_vector(hcnt);
video_ctl_o.y <= "00"&std_logic_vector(vcnt);
-- blank signal goes to tilemap/spritectl
video_ctl_o.hblank <= hblank;
video_ctl_o.vblank <= vblank;
-- pass-through for tile/bitmap & sprite controllers
video_ctl_o.clk <= clk;
video_ctl_o.clk_ena <= clk_ena;
-- for video DACs and TFT output
video_o.clk <= clk;
end SYN;

View File

@ -553,7 +553,7 @@ begin
-- tilemap_o(1).tile_d(23 downto 0) <= chr_rom_d(0) & chr_rom_d(1) & chr_rom_d(2);
-- external sprite ROMs
gfx2_addr <= '0' & sprite_i.a(14 downto 0);
gfx2_addr <= sprite_i.a(15 downto 0);
sprite_o.d(23 downto 0) <= gfx2_do(7 downto 0) & gfx2_do(15 downto 8) & gfx2_do(23 downto 16);
-- internal sprite ROMs

View File

@ -22,6 +22,7 @@ entity sprite_array is
reset : in std_logic;
hwsel : in integer;
hires : in std_logic;
sprite_prom : in prom_a(0 to 31);
-- register interface
@ -86,8 +87,8 @@ begin
else
i := i + 1;
end if;
row_a <= ctl_o(i).a;
end if;
row_a <= ctl_o(i).a;
end if;
end process;
@ -156,6 +157,7 @@ begin
port map
(
hwsel => hwsel,
hires => hires,
-- sprite registers
reg_i => reg_o(i),

View File

@ -61,6 +61,7 @@ package sprite_pkg is
(
reset : in std_logic;
hwsel : integer;
hires : in std_logic;
sprite_prom : in prom_a(0 to 31);
-- register interface

View File

@ -19,6 +19,7 @@ entity spritectl is
port
(
hwsel : in integer range 0 to 15;
hires : in std_logic;
-- sprite registers
reg_i : in from_SPRITE_REG_t;
@ -39,73 +40,63 @@ architecture SYN of spritectl is
alias clk : std_logic is video_ctl.clk;
alias clk_ena : std_logic is video_ctl.clk_ena;
signal ld_r : std_logic;
signal left_d : std_logic;
signal hblank_r : std_logic;
signal rowStore : std_logic_vector(47 downto 0); -- saved row of spt to show during visibile period
signal rowCount : unsigned(5 downto 0);
-- which part of the sprite is being drawn
alias segment : unsigned(1 downto 0) is rowCount(5 downto 4);
begin
process (clk, clk_ena, left_d, rowCount, reg_i)
process (clk, clk_ena, reg_i)
variable pel : std_logic_vector(2 downto 0);
variable x : unsigned(video_ctl.x'range);
variable y : unsigned(video_ctl.y'range);
variable xMat : boolean; -- raster in between left edge and end of line
variable yMat : boolean; -- raster is between first and last line of sprite
variable yMatNext : boolean;
variable height : unsigned(1 downto 0);
variable rowCount : unsigned(5 downto 0);
-- which part of the sprite is being drawn
alias segment : unsigned(1 downto 0) is rowCount(5 downto 4);
variable code : std_logic_vector(9 downto 0);
variable code : std_logic_vector(10 downto 0);
begin
if rising_edge(clk) then
if clk_ena = '1' then
ld_r <= ctl_i.ld;
hblank_r <= video_ctl.hblank;
if video_ctl.hblank = '1' then
x := unsigned(reg_i.x) - video_ctl.video_h_offset + PACE_VIDEO_PIPELINE_DELAY - 2;
y := 256 + 128 - 18 - unsigned(reg_i.y);
yMat := yMatNext;
else
-- determine if the sprite is visible on the next line during active display
y := 640 - unsigned(reg_i.y) - unsigned(video_ctl.y) - 3;
-- hande sprite height, placement
code := reg_i.n(9 downto 0); -- default
code := reg_i.n(10 downto 0); -- default
rowCount := (others => '0');
yMatNext := false;
case ctl_i.height is
when 0 =>
-- normal height
if y(video_ctl.y'left downto 4) = 0 then
yMatNext := true;
rowCount := "00" & not y(3 downto 0);
end if;
when 1 =>
-- double height
y := y - 16;
if y(video_ctl.y'left downto 5) = 0 then
yMatNext := true;
rowCount := '0' & not y(4 downto 0);
end if;
when 2 =>
-- quadruple height
y := y - 3*16;
if y(video_ctl.y'left downto 6) = 0 then
yMatNext := true;
rowCount := not y(5 downto 0);
end if;
when others =>
null;
end case;
height := to_unsigned(ctl_i.height,2);
height(0) := height (0) or height(1);
-- count row at start of hblank
if hblank_r = '0' then
if y = unsigned(video_ctl.y) then
-- start counting sprite row
rowCount <= (others => '0');
yMat := true;
elsif rowCount = height & "1111" then
yMat := false;
else
rowCount <= rowCount + 1;
end if;
-- stop sprites wrapping from bottom of screen
if y = 0 then
yMat := false;
end if;
end if;
case ctl_i.height is
when 1 =>
-- double height
@ -125,30 +116,39 @@ begin
null;
end case;
if ld_r = '0' and ctl_i.ld = '1' then
xMat := false;
left_d <= not left_d; -- switch sprite half
if yMat then
if left_d = '1' then
-- store first half of the sprite line data
rowStore(39 downto 32) <= ctl_i.d(23 downto 16);
rowStore(23 downto 16) <= ctl_i.d(15 downto 8);
rowStore( 7 downto 0) <= ctl_i.d( 7 downto 0);
else
-- load sprite data
rowStore(47 downto 40) <= ctl_i.d(23 downto 16);
rowStore(31 downto 24) <= ctl_i.d(15 downto 8);
rowStore(15 downto 8) <= ctl_i.d( 7 downto 0);
end if;
else
rowStore <= (others => '0');
end if;
-- generate sprite data address
ctl_o.a(15 downto 5) <= code;
ctl_o.a(4) <= '0';
if reg_i.yflip = '0' then
ctl_o.a(3 downto 0) <= std_logic_vector(rowCount(3 downto 0));
else
ctl_o.a(3 downto 0) <= not std_logic_vector(rowCount(3 downto 0));
end if;
else
left_d <= '0';
end if; -- hblank='1'
end if; -- hblank='0'
if ctl_i.ld = '1' then
xMat := false;
ctl_o.a(4) <= not ctl_o.a(4); -- switch sprite half
if yMat then
if ctl_o.a(4) = '1' then
-- store first half of the sprite line data
rowStore(39 downto 32) <= ctl_i.d(23 downto 16);
rowStore(23 downto 16) <= ctl_i.d(15 downto 8);
rowStore( 7 downto 0) <= ctl_i.d( 7 downto 0);
else
-- load sprite data
rowStore(47 downto 40) <= ctl_i.d(23 downto 16);
rowStore(31 downto 24) <= ctl_i.d(15 downto 8);
rowStore(15 downto 8) <= ctl_i.d( 7 downto 0);
end if;
else
rowStore <= (others => '0');
end if;
end if;
if video_ctl.stb = '1' then
x := unsigned(reg_i.x) + 256 - 64 + PACE_VIDEO_PIPELINE_DELAY - 2;
if hires = '0' then x := x - 64; end if;
if x = unsigned(video_ctl.x) then
xMat := true;
@ -183,17 +183,7 @@ begin
end if; -- clk_ena='1'
end if; -- rising_edge(clk)
-- generate sprite data address
ctl_o.a(15) <= '0'; -- unused
ctl_o.a(14 downto 5) <= code;
ctl_o.a(4) <= left_d;
if reg_i.yflip = '0' then
ctl_o.a(3 downto 0) <= std_logic_vector(rowCount(3 downto 0));
else
ctl_o.a(3 downto 0) <= not std_logic_vector(rowCount(3 downto 0));
end if;
end process;
end architecture SYN;
end architecture SYN;

View File

@ -23,6 +23,7 @@ entity tilemapCtl is
(
reset : in std_logic;
hwsel : in integer;
hires : in std_logic;
-- video control signals
video_ctl : in from_VIDEO_CTL_t;
@ -60,10 +61,11 @@ begin
ctl_o.tile_a(ctl_o.tile_a'left downto 15) <= (others => '0');
-- tilemap scroll
x <= std_logic_vector(video_ctl.video_h_offset + unsigned(video_ctl.x)) when unsigned(y) < 6*8 and HWSEL = HW_KUNGFUM else
std_logic_vector(video_ctl.video_h_offset + unsigned(video_ctl.x) + unsigned(hscroll(8 downto 0)));
y <= std_logic_vector(unsigned(video_ctl.y) + unsigned(vscroll(8 downto 0)) + 128) when hwsel = HW_SPELUNKR else
std_logic_vector(unsigned(video_ctl.y) + unsigned(vscroll(8 downto 0))); -- when rot_en = '0' else video_ctl.x;
x <= std_logic_vector(unsigned(video_ctl.x) - 256 + 128) when unsigned(y) < 6*8 and HWSEL = HW_KUNGFUM else
std_logic_vector(unsigned(video_ctl.x) - 256 + unsigned(hscroll(8 downto 0)) + 64) when hires = '1' else
std_logic_vector(unsigned(video_ctl.x) - 256 + unsigned(hscroll(8 downto 0)) + 128);
y <= std_logic_vector(unsigned(video_ctl.y) - 256 + unsigned(vscroll(8 downto 0)) + 128) when hwsel = HW_SPELUNKR else
std_logic_vector(unsigned(video_ctl.y) - 256 + unsigned(vscroll(8 downto 0))); -- when rot_en = '0' else video_ctl.x;
-- generate pixel
process (clk, clk_ena)