diff --git a/common/video.vhd.sav b/common/video.vhd.sav deleted file mode 100644 index 608e662..0000000 --- a/common/video.vhd.sav +++ /dev/null @@ -1,1981 +0,0 @@ ---------------------------------------------------------------------------------------------------------- --- --- Name: video.vhd --- Created: July 2018 --- Author(s): Philip Smart --- Description: Sharp MZ series Video logic. --- This module fully emulates the Sharp MZ Personal Computer series video display --- logic plus extensions for MZ80K, MZ80C, MZ1200, MZ80A, MZ700, MZ80B & MZ2000. --- --- The display is capable of performing 40x25, 80x25 Mono/Colour display along with --- a Programmable Character Generator, the MZ-80B/2000 Graphics Options and a bit mapped --- 320x200/640x200 framebuffer. --- --- The design is slightly different to the original Sharp's in that I use a dual --- buffer technique, ie. the original 1K/2K VRAM + ARAM and a pixel mapped displaybuffer. --- During Horizontal/Vertical blanking, the VRAM+ARAM is copied and expanded into the display --- buffer which is then displayed during the next display window. Part of the reasoning --- was to cut down on snow/tearing on the older K/C models (but still provide the --- blanking signals so any original software works) and also allow the option of --- disabling the MZ80A/700 wait states. --- --- As an addition, I added a graphics framebuffer (320x200, 640x200 8 colours) --- the interface to which is, at the moment, non-standard, but as I get more details --- on add on cards, I can add mapping layers so this graphics framebuffer can be used --- by customised software. Pixels drawn in the graphics framebuffer can be blended into --- the main display buffer via programmable logic mode (ie. XOR, OR etc). --- --- The MZ80B/2000 use a standard VRAM + CG for 40/80 character display with a Graphics --- RAM option. These have been added and the output if blended into the display buffer. --- --- A lot of timing information can be found in the docs/SharpMZ_Notes.xlsx spreadsheet, --- but the main info is: --- MZ80K/C/1200/A (Monochrome) --- Signal Start End Period Comment --- 64uS 15.625KHz --- HDISPEN 0 320 40uS --- HBLANK 318 510 24uS --- BLNK 318 486 21uS --- HSYNC 393 438 5.625uS --- --- 16.64mS 60.10Hz --- VDISPEN 0 200 12.8mS --- VSYNC 219 223 256uS --- VBLANK 201 259 3.712mS not VDISPEN --- --- MZ700 (Colour) --- Signal Start End Period Comment --- 64.056uS 15.611KHz --- HDISPEN 0 320 36.088uS --- HBLANK 320 567 27.968uS --- BLNK 320 548 25.7126uS --- HSYNC 400 440 4.567375uS --- --- 16.654mS 50.0374Hz --- VDISPEN 0 200 12.8112mS --- VSYNC 212 215 0.19216ms --- VBLANK 201 311 7.1738mS not VDISPEN --- --- A Look Up Table was added to allow for VGA display resolutions and upscaling as necessary. --- All video parameters are now stored in the LUT. --- --- Copyright: (c) 2018 Philip Smart --- --- History: July 2018 - Initial module written. --- August 2018 - Main portions written, including the display buffer. --- September 2018 - Added the graphics framebuffer. --- - Reworked the transfer VRAM/GRAM -> Framebuffer logic, too conceptual --- and caused timing issues. --- Reworked the Framebuffer display, too conceptual. --- Added MZ80B/MZ2000 logic. --- October 2018 - Parameterised graphics modes via a LUT. --- November 2018 - Added VGA upscaling. --- ---------------------------------------------------------------------------------------------------------- --- This source file is free software: you can redistribute it and-or modify --- it under the terms of the GNU General Public License as published --- by the Free Software Foundation, either version 3 of the License, or --- (at your option) any later version. --- --- This source file is distributed in the hope that it will be useful, --- but WITHOUT ANY WARRANTY; without even the implied warranty of --- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --- GNU General Public License for more details. --- --- You should have received a copy of the GNU General Public License --- along with this program. If not, see . ---------------------------------------------------------------------------------------------------------- - -library ieee; -library pkgs; -use ieee.std_logic_1164.all; -use ieee.std_logic_unsigned.all; -use ieee.numeric_std.all; -use pkgs.clkgen_pkg.all; -use pkgs.mctrl_pkg.all; -use pkgs.functions_pkg.all; - -entity video is -Port ( - RST_n : in std_logic; -- Reset - - -- Different operations modes. - CONFIG : in std_logic_vector(CONFIG_WIDTH); - - -- Clocks - CLKBUS : in std_logic_vector(CLKBUS_WIDTH); -- Clock signals created by clkgen module. - - -- CPU Signals - T80_A : in std_logic_vector(13 downto 0); -- CPU Address Bus - T80_RD_n : in std_logic; -- CPU Read Signal - T80_WR_n : in std_logic; -- CPU Write Signal - T80_MREQ_n : in std_logic; -- CPU Memory Request - T80_BUSACK_n : in std_logic; -- CPU Bus Acknowledge - T80_WAIT_n : out std_logic; -- CPU Wait Request - T80_DI : in std_logic_vector(7 downto 0); -- CPU Data Bus in - T80_DO : out std_logic_vector(7 downto 0); -- CPU Data Bus out - - -- Selects. - CS_VRAM_n : in std_logic; -- VRAM Select - CS_MEM_G_n : in std_logic; -- Memory mapped Peripherals Select - CS_GRAM_n : in std_logic; -- Colour GRAM Select - CS_GRAM_80B_n : in std_logic; -- MZ80B GRAM Select - CS_IO_GFB_n : in std_logic; -- Framebuffer register IO Select range. - CS_IO_G_n : in std_logic; -- MZ80B Graphics Options IO Select range. - - -- Video Signals - VGATE_n : in std_logic; -- Video Output Control - INVERSE_n : in std_logic; -- Invert video display. - CONFIG_CHAR80 : in std_logic; -- 40 Char = 0, 80 Char = 1 select. - HBLANK : out std_logic; -- Horizontal Blanking - VBLANK : out std_logic; -- Vertical Blanking - HSYNC_n : out std_logic; -- Horizontal Sync - VSYNC_n : out std_logic; -- Vertical Sync - ROUT : out std_logic_vector(7 downto 0); -- Red Output - GOUT : out std_logic_vector(7 downto 0); -- Green Output - BOUT : out std_logic_vector(7 downto 0); -- Green Output - - -- HPS Interface - IOCTL_DOWNLOAD : in std_logic; -- HPS Downloading to FPGA. - IOCTL_UPLOAD : in std_logic; -- HPS Uploading from FPGA. - IOCTL_CLK : in std_logic; -- HPS I/O Clock.. - IOCTL_WR : in std_logic; -- HPS Write Enable to FPGA. - IOCTL_RD : in std_logic; -- HPS Read Enable from FPGA. - IOCTL_ADDR : in std_logic_vector(24 downto 0); -- HPS Address in FPGA to write into. - IOCTL_DOUT : in std_logic_vector(15 downto 0); -- HPS Data to be written into FPGA. - IOCTL_DIN : out std_logic_vector(15 downto 0) -- HPS Data to be read into HPS. -); -end video; - -architecture RTL of video is - -type VIDEOLUT is array (integer range 0 to 19, integer range 0 to 29) of integer range 0 to 2000; - --- Constants --- -constant MAX_SUBROW : integer := 8; - --- --- Video Timings for different machines and display configuration. --- -constant FB_PARAMS : VIDEOLUT := ( - --- Display window variables:- --- H_DSP_START, H_DSP_END,H_DSP_WND_START, H_DSP_WND_END, H_MNU_START, H_MNU_END, H_HDR_START, H_HDR_END, H_FTR_START, H_FTR_END, V_DSP_START, V_DSP_END,V_DSP_WND_START, V_DSP_WND_END, V_MNU_START, V_MNU_END, V_HDR_START, V_HDR_END, V_FTR_START, V_FTR_END, H_LINE_END, V_LINE_END, V_XFER_START, MAX_COLUMNS, H_SYNC_START, H_SYNC_END, V_SYNC_START, V_SYNC_END, H_PX, V_PX -( 0, 320, 0, 320, 32, 288, 0, 0, 0, 0, 0, 200, 0, 200, 36, 164, 0, 0, 0, 0, 511, 259, 10, 40, 320 + 73, 320 + 73 + 45, 200 + 19, 200 + 19 + 4, 0, 0), -- 0 MZ80B/2000 machines have a monochrome 60Hz display with scan of 512 x 260 for a 320x200 viewable area in 40Char mode. -( 0, 640, 0, 640, 192, 448, 0, 0, 0, 0, 0, 200, 0, 200, 36, 164, 0, 0, 0, 0, 1023, 259, 10, 80, 640 + 146, 640 + 146 + 90, 200 + 19, 200 + 19 + 4, 0, 0), -- 1 MZ80B/2000 machines have a monochrome 60Hz display with scan of 1024 x 260 for a 640x200 viewable area in 80Char mode. -( 0, 320, 0, 320, 32, 288, 0, 0, 0, 0, 0, 200, 0, 200, 36, 164, 0, 0, 0, 0, 511, 259, 10, 40, 320 + 73, 320 + 73 + 45, 200 + 19, 200 + 19 + 4, 0, 0), -- 2 MZ80K/C/1200/A machines have a monochrome 60Hz display with scan of 512 x 260 for a 320x200 viewable area. -( 0, 640, 0, 640, 192, 448, 0, 0, 0, 0, 0, 200, 0, 200, 36, 164, 0, 0, 0, 0, 1023, 259, 10, 80, 640 + 146, 640 + 146 + 90, 200 + 19, 200 + 19 + 4, 0, 0), -- 3 MZ80K/C/1200/A machines with an adapted monochrome 60Hz display with scan of 1024 x 260 for a 640x200 viewable area. -( 0, 320, 0, 320, 32, 288, 0, 0, 0, 0, 0, 200, 0, 200, 36, 164, 0, 0, 0, 0, 567, 311, 10, 40, 320 + 80, 320 + 80 + 40, 200 + 45, 200 + 45 + 3, 0, 0), -- 4 MZ700 has a colour 50Hz display with scan of 568 x 320 for a 320x200 viewable area. -( 0, 640, 0, 640, 192, 448, 0, 0, 0, 0, 0, 200, 0, 200, 36, 164, 0, 0, 0, 0, 1134, 311, 10, 80, 640 + 160, 640 + 160 + 80, 200 + 45, 200 + 45 + 3, 0, 0), -- 5 MZ700 has colour 50Hz display with scan of 1136 x 320 for a 640x200 viewable area. -( 0, 320, 0, 320, 32, 288, 0, 0, 0, 0, 0, 200, 0, 200, 36, 164, 0, 0, 0, 0, 511, 259, 10, 40, 320 + 73, 320 + 73 + 45, 200 + 19, 200 + 19 + 4, 0, 0), -- 6 MZ80K/C/1200/A machines with MZ700 style colour @ 60Hz display with scan of 512 x 260 for a 320x200 viewable area. -( 0, 640, 0, 640, 192, 448, 0, 0, 0, 0, 0, 200, 0, 200, 36, 164, 0, 0, 0, 0, 1023, 259, 10, 80, 640 + 146, 640 + 146 + 90, 200 + 19, 200 + 19 + 4, 0, 0), -- 7 MZ80K/C/1200/A machines with MZ700 style colour @ 60Hz display with scan of 1024 x 260 for a 640x200 viewable area. -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 847, 508, 10, 40, 640 + 40, 640 + 40 + 64, 480 + 1, 480 + 1 + 3, 1, 1), -- 8 640x480 @ 85Hz timings for 40Char mode monochrome. " -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 799, 524, 10, 40, 640 + 16, 640 + 16 + 96, 480 + 10, 480 + 10 + 2, 1, 1), -- 9 640x480 @ 60Hz timings for 40Char mode monochrome. -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 831, 508, 10, 80, 640 + 56, 640 + 56 + 56, 480 + 1, 480 + 1 + 3, 0, 1), -- 10 640x480 @ 85Hz timings for 80Char mode monochrome. " -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 799, 524, 10, 80, 640 + 16, 640 + 16 + 64, 480 + 10, 480 + 10 + 2, 0, 1), -- 11 640x480 @ 60Hz timings for 80Char mode monochrome. " -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 831, 508, 10, 40, 640 + 56, 640 + 56 + 56, 480 + 1, 480 + 1 + 3, 1, 1), -- 12 640x480 @ 85Hz timings for 80Char mode colour. " -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 799, 524, 10, 40, 640 + 16, 640 + 16 + 64, 480 + 10, 480 + 10 + 2, 1, 1), -- 13 640x480 @ 60Hz timings for 40Char mode colour. " -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 831, 508, 10, 80, 640 + 56, 640 + 56 + 56, 480 + 1, 480 + 1 + 3, 0, 1), -- 14 640x480 @ 85Hz timings for 80Char mode colour. " -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 799, 524, 10, 80, 640 + 16, 640 + 16 + 64, 480 + 10, 480 + 10 + 2, 0, 1), -- 15 640x480 @ 60Hz timings for 80Char mode colour. " -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 831, 519, 10, 40, 640 + 24, 640 + 24 + 40, 480 + 9, 480 + 9 + 2, 1, 1), -- 16 640x480 @ 75Hz timings for 40Char mode monochrome. -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 831, 519, 10, 80, 640 + 24, 640 + 24 + 40, 480 + 9, 480 + 9 + 2, 0, 1), -- 17 640x480 @ 75Hz timings for 80Char mode monochrome. -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 831, 519, 10, 40, 640 + 24, 640 + 24 + 40, 480 + 9, 480 + 9 + 2, 1, 1), -- 18 640x480 @ 75Hz timings for 40Char mode colour. -( 0, 640, 0, 640, 192, 448, 0, 640, 0, 640, 0, 480, 40, 440, 112, 368, 10, 25, 442, 478, 831, 519, 10, 80, 640 + 24, 640 + 24 + 40, 480 + 9, 480 + 9 + 2, 0, 1) -- 19 640x480 @ 75Hz timings for 80Char mode colour. -); - - --- --- Registers --- -signal VIDEOMODE : integer range 0 to 20; -signal VIDEOMODE_LAST : integer range 0 to 20; -signal VIDEOMODE_CHANGED : std_logic; -signal MAX_COLUMN : integer range 0 to 80; -signal FB_ADDR : std_logic_vector(13 downto 0); -- Frame buffer actual address -signal FB_ADDR_STATUS : std_logic_vector(11 downto 0); -- Status display frame buffer actual address -signal FB_ADDR_MENU : std_logic_vector(11 downto 0); -- Menu display frame buffer actual address -signal OFFSET_ADDR : std_logic_vector(7 downto 0); -- Display Offset - for MZ1200/80A machines with 2K VRAM -signal SR_G_DATA : std_logic_vector(7 downto 0); -- Shift Register to serialise Green pixels. -signal SR_R_DATA : std_logic_vector(7 downto 0); -- Shift Register to serialise Red pixels. -signal SR_B_DATA : std_logic_vector(7 downto 0); -- Shift Register to serialise Blue pixels. -signal SR_MNU_G_DATA : std_logic_vector(7 downto 0); -- Shift Register to serialise Menu pixels. -signal SR_MNU_R_DATA : std_logic_vector(7 downto 0); -- Shift Register to serialise Menu pixels. -signal SR_MNU_B_DATA : std_logic_vector(7 downto 0); -- Shift Register to serialise Menu pixels. -signal DISPLAY_DATA : std_logic_vector(23 downto 0); -signal DISPLAY_DATA_STATUS : std_logic_vector(23 downto 0); -signal DISPLAY_DATA_MENU : std_logic_vector(23 downto 0); -signal XFER_ADDR : std_logic_vector(10 downto 0); -signal XFER_SUB_ADDR : std_logic_vector(2 downto 0); -signal XFER_VRAM_DATA : std_logic_vector(15 downto 0); -signal XFER_GRAM_DATA : std_logic_vector(39 downto 0); -- 3 x 16Kb Colour Graphics + GRAM I (MZ80B) + GRAM II (MZ80B) -signal XFER_MAPPED_DATA : std_logic_vector(23 downto 0); -signal XFER_WEN : std_logic; -signal XFER_VRAM_ADDR : std_logic_vector(10 downto 0); -signal XFER_DST_ADDR : std_logic_vector(13 downto 0); -signal XFER_CGROM_ADDR : std_logic_vector(11 downto 0); -signal CGROM_DATA : std_logic_vector(7 downto 0); -- Font Data To Display -signal DISPLAY_INVERT : std_logic; -- Invert display Mode of MZ80A/1200 -signal H_SHIFT_CNT : integer range 0 to 7; -signal H_MNU_SHIFT_CNT : integer range 0 to 7; -signal H_PX : integer range 0 to 3; -- Variable to indicate if horizontal pixels should be multiplied (for conversion to alternate formats). -signal H_PX_CNT : integer range 0 to 3; -- Variable to indicate if horizontal pixels should be multiplied (for conversion to alternate formats). -signal V_PX : integer range 0 to 3; -- Variable to indicate if vertical pixels should be multiplied (for conversion to alternate formats). -signal V_PX_CNT : integer range 0 to 3; -- Variable to indicate if vertical pixels should be multiplied (for conversion to alternate formats). -signal V_XFER_START : integer range 0 to 2000; - --- --- CPU/Video Access --- -signal VRAM_VIDEO_DATA : std_logic_vector(7 downto 0); -- Display data output to CPU. -signal VRAM_ADDR : std_logic_vector(11 downto 0); -- VRAM Address. -signal VRAM_DI : std_logic_vector(7 downto 0); -- VRAM Data in. -signal VRAM_DO : std_logic_vector(7 downto 0); -- VRAM Data out. -signal VRAM_WEN : std_logic; -- VRAM Write enable signal. -signal VRAM_CLK : std_logic; -- Clock used to access the VRAM (CPU or IOCTL_CLK). -signal VRAM_CLK_EN : std_logic; -- Clock enable for VRAM. -signal GRAM_VIDEO_DATA : std_logic_vector(7 downto 0); -- Graphics display data output to CPU. -signal GRAM_ADDR : std_logic_vector(13 downto 0); -- Graphics RAM Address. -signal GRAM_DI_R : std_logic_vector(7 downto 0); -- Graphics Red RAM Data. -signal GRAM_DI_G : std_logic_vector(7 downto 0); -- Graphics Green RAM Data. -signal GRAM_DI_B : std_logic_vector(7 downto 0); -- Graphics Blue RAM Data. -signal GRAM_DI_GI : std_logic_vector(7 downto 0); -- Graphics Option GRAM I for MZ80B -signal GRAM_DI_GII : std_logic_vector(7 downto 0); -- Graphics Option GRAM II for MZ80B -signal GRAM_DO_R : std_logic_vector(7 downto 0); -- Graphics Red RAM Data out. -signal GRAM_DO_G : std_logic_vector(7 downto 0); -- Graphics Green RAM Data out. -signal GRAM_DO_B : std_logic_vector(7 downto 0); -- Graphics Blue RAM Data out. -signal GRAM_DO_GI : std_logic_vector(7 downto 0); -- Graphics Option GRAM I Data out for MZ80B. -signal GRAM_DO_GII : std_logic_vector(7 downto 0); -- Graphics Option GRAM II Data out for MZ80B. -signal GRAM_WEN_R : std_logic; -- Graphics Red RAM Write enable signal. -signal GRAM_WEN_G : std_logic; -- Graphics Green RAM Write enable signal. -signal GRAM_WEN_B : std_logic; -- Graphics Blue RAM Write enable signal. -signal GRAM_WEN_GI : std_logic; -- Graphics Option GRAM I Write enable signal for MZ80B. -signal GRAM_WEN_GII : std_logic; -- Graphics Option GRAM II Write enable signal for MZ80B. -signal GRAM_CLK : std_logic; -- Clock used to access the GRAM (CPU or IOCTL_CLK). -signal GRAM_CLK_EN : std_logic; -- Clock enable for GRAM. -signal GRAM_MODE : std_logic_vector(7 downto 0); -- Programmable mode register to control GRAM operations. -signal GRAM_R_FILTER : std_logic_vector(7 downto 0); -- Red pixel writer filter. -signal GRAM_G_FILTER : std_logic_vector(7 downto 0); -- Green pixel writer filter. -signal GRAM_B_FILTER : std_logic_vector(7 downto 0); -- Blue pixel writer filter. -signal GRAM_OPT_WRITE : std_logic; -- Graphics write to GRAMI (0) or GRAMII (1) for MZ80B/MZ2000 -signal GRAM_OPT_OUT1 : std_logic; -- Graphics enable GRAMI output to display -signal GRAM_OPT_OUT2 : std_logic; -- Graphics enable GRAMII output to display -signal T80_MA : std_logic_vector(11 downto 0); -- CPU Address Masked according to machine model. -signal CS_INVERT_n : std_logic; -- Chip Select to enable Inverse mode. -signal CS_SCROLL_n : std_logic; -- Chip Select to perform a hardware scroll. -signal CS_GRAM_OPT_n : std_logic; -- Chip Select to write the graphics options for MZ80B/MZ2000. -signal CS_FB_CTL_n : std_logic; -- Chip Select to write to the Graphics mode register. -signal CS_FB_RED_n : std_logic; -- Chip Select to write to the Red pixel per byte indirect write register. -signal CS_FB_GREEN_n : std_logic; -- Chip Select to write to the Green pixel per byte indirect write register. -signal CS_FB_BLUE_n : std_logic; -- Chip Select to write to the Blue pixel per byte indirect write register. -signal CS_PCG_n : std_logic; -signal WAITi_n : std_logic; -- Wait -signal WAITii_n : std_logic; -- Wait(delayed) -signal VWEN : std_logic; -- Write enable to VRAM. -signal GWEN_R : std_logic; -- Write enable to Red GRAM. -signal GWEN_G : std_logic; -- Write enable to Green GRAM. -signal GWEN_B : std_logic; -- Write enable to Blue GRAM. -signal GWEN_GI : std_logic; -- Write enable to for GRAMI option on MZ80B/2000. -signal GWEN_GII : std_logic; -- Write enable to for GRAMII option on MZ80B/2000. --- --- Internal Signals --- -signal H_COUNT : unsigned(10 downto 0); -- Horizontal pixel counter -signal H_BLANKi : std_logic; -- Horizontal Blanking -signal H_SYNC_ni : std_logic; -- Horizontal Blanking -signal H_DSP_START : integer range 0 to 2047; -signal H_DSP_END : integer range 0 to 2047; -signal H_DSP_WND_START : integer range 0 to 2047; -- Window within the horizontal display when data is output. -signal H_DSP_WND_END : integer range 0 to 2047; -signal H_MNU_START : integer range 0 to 2047; -signal H_MNU_END : integer range 0 to 2047; -signal H_HDR_START : integer range 0 to 2047; -signal H_HDR_END : integer range 0 to 2047; -signal H_FTR_START : integer range 0 to 2047; -signal H_FTR_END : integer range 0 to 2047; -signal H_SYNC_START : integer range 0 to 2047; -signal H_SYNC_END : integer range 0 to 2047; -signal H_LINE_END : integer range 0 to 2047; -signal V_COUNT : unsigned(10 downto 0); -- Vertical pixel counter -signal V_BLANKi : std_logic; -- Vertical Blanking -signal V_SYNC_ni : std_logic; -- Horizontal Blanking -signal V_DSP_START : integer range 0 to 2047; -signal V_DSP_END : integer range 0 to 2047; -signal V_DSP_WND_START : integer range 0 to 2047; -- Window within the vertical display when data is output. -signal V_DSP_WND_END : integer range 0 to 2047; -signal V_MNU_START : integer range 0 to 2047; -signal V_MNU_END : integer range 0 to 2047; -signal V_HDR_START : integer range 0 to 2047; -signal V_HDR_END : integer range 0 to 2047; -signal V_FTR_START : integer range 0 to 2047; -signal V_FTR_END : integer range 0 to 2047; -signal V_SYNC_START : integer range 0 to 2047; -signal V_SYNC_END : integer range 0 to 2047; -signal V_LINE_END : integer range 0 to 2047; -signal VRAM_WAIT : std_logic; -- Horizontal Blanking Memory Access --- --- CG-ROM --- -signal CGROM_DO : std_logic_vector(7 downto 0); -signal CGROM_BANK : std_logic_vector(3 downto 0); --- --- PCG --- -signal CGRAM_DO : std_logic_vector(7 downto 0); -signal CG_ADDR : std_logic_vector(11 downto 0); -signal CGRAM_ADDR : std_logic_vector(11 downto 0); -signal PCG_DATA : std_logic_vector(7 downto 0); -signal CGRAM_DI : std_logic_vector(7 downto 0); -signal CGRAM_WE_n : std_logic; -signal CGRAM_WEN : std_logic; -signal CGRAM_SEL : std_logic; --- --- HPS Control. --- -signal IOCTL_CS_VRAM_n : std_logic; -- Chip Select to allow the HPS to access the VRAM. -signal IOCTL_CS_GRAM_n : std_logic; -- Chip Select to allow the HPS to access the GRAM. -signal IOCTL_CS_GRAM_80B_n : std_logic; -- Chip Select to allow the HPS to access the MZ80B/2000 GRAM option memory. -signal IOCTL_CS_CGROM_n : std_logic; -signal IOCTL_CS_CGRAM_n : std_logic; -signal IOCTL_CS_STRAM_G_n : std_logic; -signal IOCTL_CS_STRAM_R_n : std_logic; -signal IOCTL_CS_STRAM_B_n : std_logic; -signal IOCTL_CS_MNURAM_G_n : std_logic; -signal IOCTL_CS_MNURAM_R_n : std_logic; -signal IOCTL_CS_MNURAM_B_n : std_logic; -signal IOCTL_CS_CONFIG_n : std_logic; -signal IOCTL_WEN_VRAM : std_logic; -- Write Enable to allow the HPS to write to VRAM. -signal IOCTL_WEN_GRAM_R : std_logic; -- Write Enable to allow the HPS to write to the Red GRAM. -signal IOCTL_WEN_GRAM_G : std_logic; -- Write Enable to allow the HPS to write to the Green GRAM. -signal IOCTL_WEN_GRAM_B : std_logic; -- Write Enable to allow the HPS to write to the Blue GRAM. -signal IOCTL_WEN_GRAM_GI : std_logic; -- Write Enable to allow the HPS to write to the MZ80B GRAM I Option RAM. -signal IOCTL_WEN_GRAM_GII : std_logic; -- Write Enable to allow the HPS to write to the MZ80B GRAM II Option RAM. -signal IOCTL_WEN_STRAM_G : std_logic; -- Write Enable to allow the HPS to write to the Status Frame Buffer RAM for Green. -signal IOCTL_WEN_STRAM_R : std_logic; -- Write Enable to allow the HPS to write to the Status Frame Buffer RAM for Red. -signal IOCTL_WEN_STRAM_B : std_logic; -- Write Enable to allow the HPS to write to the Status Frame Buffer RAM for Blue. -signal IOCTL_WEN_MNURAM_G : std_logic; -- Write Enable to allow the HPS to write to the Menu Frame Buffer RAM for Green. -signal IOCTL_WEN_MNURAM_R : std_logic; -- Write Enable to allow the HPS to write to the Menu Frame Buffer RAM for Red. -signal IOCTL_WEN_MNURAM_B : std_logic; -- Write Enable to allow the HPS to write to the Menu Frame Buffer RAM for Blue. -signal IOCTL_WEN_CGROM : std_logic; -signal IOCTL_WEN_CGRAM : std_logic; -signal IOCTL_DIN_VRAM : std_logic_vector(7 downto 0); -signal IOCTL_DIN_GRAM : std_logic_vector(7 downto 0); -signal IOCTL_DIN_PCG : std_logic_vector(15 downto 0); -signal IOCTL_DIN_CGROM : std_logic_vector(7 downto 0); -signal IOCTL_DIN_CGRAM : std_logic_vector(7 downto 0); -signal IOCTL_DIN_STRAM_G : std_logic_vector(15 downto 0); -signal IOCTL_DIN_STRAM_R : std_logic_vector(15 downto 0); -signal IOCTL_DIN_STRAM_B : std_logic_vector(15 downto 0); -signal IOCTL_DIN_MNURAM_G : std_logic_vector(15 downto 0); -signal IOCTL_DIN_MNURAM_R : std_logic_vector(15 downto 0); -signal IOCTL_DIN_MNURAM_B : std_logic_vector(15 downto 0); -signal IOCTL_DIN_CONFIG : std_logic_vector(15 downto 0); - --- --- Components --- -component dpram - generic ( - init_file : string; - widthad_a : natural; - width_a : natural; - widthad_b : natural; - width_b : natural; - outdata_reg_a : string := "UNREGISTERED"; - outdata_reg_b : string := "UNREGISTERED" - ); - Port ( - clock_a : in std_logic ; - clocken_a : in std_logic := '1'; - address_a : in std_logic_vector (widthad_a-1 downto 0); - data_a : in std_logic_vector (width_a-1 downto 0); - wren_a : in std_logic; - q_a : out std_logic_vector (width_a-1 downto 0); - - clock_b : in std_logic ; - clocken_b : in std_logic := '1'; - address_b : in std_logic_vector (widthad_b-1 downto 0); - data_b : in std_logic_vector (width_b-1 downto 0); - wren_b : in std_logic; - q_b : out std_logic_vector (width_b-1 downto 0) -); -end component; - -begin - --- --- Instantiation --- - --- Video memory as seen by the MZ Series. This is a 1K or 2K or 2K + 2K Attribute RAM --- organised as 4K x 8 on the CPU side and 2K x 16 on the display side, top bits are not used for MZ80K/C/1200/A. --- -VRAM0 : dpram -GENERIC MAP ( - init_file => null, - widthad_a => 12, - width_a => 8, - widthad_b => 11, - width_b => 16, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for CPU access. - clock_a => VRAM_CLK, - clocken_a => VRAM_CLK_EN, -- '1', - address_a => VRAM_ADDR, - data_a => VRAM_DI, - wren_a => VRAM_WEN, - q_a => VRAM_DO, - - -- Port B used for VRAM -> DISPLAY BUFFER transfer (SOURCE). - clock_b => CLKBUS(CKMASTER), - clocken_b => '1', - address_b => XFER_VRAM_ADDR, - data_b => (others => '0'), - wren_b => '0', - q_b => XFER_VRAM_DATA -); - --- Graphics frame buffer memory. This is an enhancement and allows for 320x200 or 640x200 pixel display in 8 colours. It matches --- the output frame buffer in size, so the contents are blended by a programmable logical operator (ie. OR) with the expanded Video --- Ram contents to create the output display. --- -GRAMG : dpram -- GREEN -GENERIC MAP ( - init_file => null, - widthad_a => 14, - width_a => 8, - widthad_b => 14, - width_b => 8, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for CPU access. - clock_a => GRAM_CLK, - clocken_a => GRAM_CLK_EN, --'1', - address_a => GRAM_ADDR, - data_a => GRAM_DI_G, - wren_a => GRAM_WEN_G, - q_a => GRAM_DO_G, - - -- Port B used for VRAM -> DISPLAY BUFFER transfer (SOURCE). - clock_b => CLKBUS(CKMASTER), - clocken_b => '1', - address_b => XFER_DST_ADDR, -- FB Destination address is used as GRAM is on a 1:1 mapping with FB. - data_b => (others => '0'), - wren_b => '0', - q_b => XFER_GRAM_DATA(7 downto 0) -); --- -GRAMR : dpram -- RED -GENERIC MAP ( - init_file => null, - widthad_a => 14, - width_a => 8, - widthad_b => 14, - width_b => 8, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for CPU access. - clock_a => GRAM_CLK, - clocken_a => GRAM_CLK_EN, --'1', - address_a => GRAM_ADDR, - data_a => GRAM_DI_R, - wren_a => GRAM_WEN_R, - q_a => GRAM_DO_R, - - -- Port B used for VRAM -> DISPLAY BUFFER transfer (SOURCE). - clock_b => CLKBUS(CKMASTER), - clocken_b => '1', - address_b => XFER_DST_ADDR, -- FB Destination address is used as GRAM is on a 1:1 mapping with FB. - data_b => (others => '0'), - wren_b => '0', - q_b => XFER_GRAM_DATA(15 downto 8) -); --- -GRAMB : dpram -- BLUE -GENERIC MAP ( - init_file => null, - widthad_a => 14, - width_a => 8, - widthad_b => 14, - width_b => 8, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for CPU access. - clock_a => GRAM_CLK, - clocken_a => GRAM_CLK_EN, -- '1', - address_a => GRAM_ADDR, - data_a => GRAM_DI_B, - wren_a => GRAM_WEN_B, - q_a => GRAM_DO_B, - - -- Port B used for VRAM -> DISPLAY BUFFER transfer (SOURCE). - clock_b => CLKBUS(CKMASTER), - clocken_b => '1', - address_b => XFER_DST_ADDR, -- FB Destination address is used as GRAM is on a 1:1 mapping with FB. - data_b => (others => '0'), - wren_b => '0', - q_b => XFER_GRAM_DATA(23 downto 16) -); - --- MZ80B Graphics RAM Option I --- -GRAMI : dpram -GENERIC MAP ( - init_file => null, - widthad_a => 13, - width_a => 8, - widthad_b => 13, - width_b => 8, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for CPU access. - clock_a => GRAM_CLK, - clocken_a => GRAM_CLK_EN, -- '1', - address_a => GRAM_ADDR(12 downto 0), - data_a => GRAM_DI_GI, - wren_a => GRAM_WEN_GI, - q_a => GRAM_DO_GI, - - -- Port B used for VRAM -> DISPLAY BUFFER transfer (SOURCE). - clock_b => CLKBUS(CKMASTER), - clocken_b => '1', - address_b => XFER_DST_ADDR(12 downto 0), -- FB Destination address is used as GRAM is on a 1:1 mapping with FB. - data_b => (others => '0'), - wren_b => '0', - q_b => XFER_GRAM_DATA(31 downto 24) -); - --- MZ80B Graphics RAM Option II --- -GRAMII : dpram -GENERIC MAP ( - init_file => null, - widthad_a => 13, - width_a => 8, - widthad_b => 13, - width_b => 8, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for CPU access. - clock_a => GRAM_CLK, - clocken_a => GRAM_CLK_EN, -- '1', - address_a => GRAM_ADDR(12 downto 0), - data_a => GRAM_DI_GII, - wren_a => GRAM_WEN_GII, - q_a => GRAM_DO_GII, - - -- Port B used for VRAM -> DISPLAY BUFFER transfer (SOURCE). - clock_b => CLKBUS(CKMASTER), - clocken_b => '1', - address_b => XFER_DST_ADDR(12 downto 0), -- FB Destination address is used as GRAM is on a 1:1 mapping with FB. - data_b => (others => '0'), - wren_b => '0', - q_b => XFER_GRAM_DATA(39 downto 32) -); - --- Display Buffer Memory, organised in a Row x Col format, where Address = (Row * MAX_COLUMN * 8) + Col, --- but in real terms it is a 320x200x3 or 640x200x3 frame buffer. --- -FRAMEBUF0 : dpram -GENERIC MAP ( - init_file => null, - widthad_a => 14, - width_a => 24, - widthad_b => 14, - width_b => 24, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for Display output. - clock_a => CLKBUS(CKMASTER), - clocken_a => '1', - address_a => FB_ADDR, - data_a => (others => '0'), - wren_a => '0', - q_a => DISPLAY_DATA, - - -- Port B used for VRAM -> DISPLAY BUFFER transfer (DESTINATION). - clock_b => CLKBUS(CKMASTER), - clocken_b => '1', - address_b => XFER_DST_ADDR, - data_b => XFER_MAPPED_DATA, - wren_b => XFER_WEN - --q_b => -); - --- A small pixel mapped buffer to display status information in the border area of the frame --- on VGA scaled output. --- -STATUSBUFG : dpram -GENERIC MAP ( - init_file => null, - widthad_a => 12, - width_a => 8, - widthad_b => 11, - width_b => 16, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for Display output. - clock_a => CLKBUS(CKVIDEO), - clocken_a => '1', - address_a => FB_ADDR_STATUS, - data_a => (others => '0'), - wren_a => '0', - q_a => DISPLAY_DATA_STATUS(7 downto 0), - - -- Port B used for IOCTL access. - clock_b => IOCTL_CLK, - clocken_b => '1', - address_b => IOCTL_ADDR(10 downto 0), - data_b => IOCTL_DOUT, - wren_b => IOCTL_WEN_STRAM_G, - q_b => IOCTL_DIN_STRAM_G -); --- -STATUSBUFR : dpram -GENERIC MAP ( - init_file => null, - widthad_a => 12, - width_a => 8, - widthad_b => 11, - width_b => 16, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for Display output. - clock_a => CLKBUS(CKVIDEO), - clocken_a => '1', - address_a => FB_ADDR_STATUS, - data_a => (others => '0'), - wren_a => '0', - q_a => DISPLAY_DATA_STATUS(15 downto 8), - - -- Port B used for IOCTL access. - clock_b => IOCTL_CLK, - clocken_b => '1', - address_b => IOCTL_ADDR(10 downto 0), - data_b => IOCTL_DOUT, - wren_b => IOCTL_WEN_STRAM_R, - q_b => IOCTL_DIN_STRAM_R -); --- -STATUSBUFB : dpram -GENERIC MAP ( - init_file => null, - widthad_a => 12, - width_a => 8, - widthad_b => 11, - width_b => 16, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for Display output. - clock_a => CLKBUS(CKVIDEO), - clocken_a => '1', - address_a => FB_ADDR_STATUS, - data_a => (others => '0'), - wren_a => '0', - q_a => DISPLAY_DATA_STATUS(23 downto 16), - - -- Port B used for IOCTL access. - clock_b => IOCTL_CLK, - clocken_b => '1', - address_b => IOCTL_ADDR(10 downto 0), - data_b => IOCTL_DOUT, - wren_b => IOCTL_WEN_STRAM_B, - q_b => IOCTL_DIN_STRAM_B -); --- -MENUBUFG : dpram -GENERIC MAP ( - init_file => null, - widthad_a => 12, - width_a => 8, - widthad_b => 11, - width_b => 16, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for Display output. - clock_a => CLKBUS(CKVIDEO), - clocken_a => '1', - address_a => FB_ADDR_MENU, - data_a => (others => '0'), - wren_a => '0', - q_a => DISPLAY_DATA_MENU(7 downto 0), - - -- Port B used for IOCTL access. - clock_b => IOCTL_CLK, - clocken_b => '1', - address_b => IOCTL_ADDR(10 downto 0), - data_b => IOCTL_DOUT, - wren_b => IOCTL_WEN_MNURAM_G, - q_b => IOCTL_DIN_MNURAM_G -); --- -MENUBUFR : dpram -GENERIC MAP ( - init_file => null, - widthad_a => 12, - width_a => 8, - widthad_b => 11, - width_b => 16, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for Display output. - clock_a => CLKBUS(CKVIDEO), - clocken_a => '1', - address_a => FB_ADDR_MENU, - data_a => (others => '0'), - wren_a => '0', - q_a => DISPLAY_DATA_MENU(15 downto 8), - - -- Port B used for IOCTL access. - clock_b => IOCTL_CLK, - clocken_b => '1', - address_b => IOCTL_ADDR(10 downto 0), - data_b => IOCTL_DOUT, - wren_b => IOCTL_WEN_MNURAM_R, - q_b => IOCTL_DIN_MNURAM_R -); --- -MENUBUFB : dpram -GENERIC MAP ( - init_file => null, - widthad_a => 12, - width_a => 8, - widthad_b => 11, - width_b => 16, - outdata_reg_b => "UNREGISTERED" -) -PORT MAP ( - -- Port A used for Display output. - clock_a => CLKBUS(CKVIDEO), - clocken_a => '1', - address_a => FB_ADDR_MENU, - data_a => (others => '0'), - wren_a => '0', - q_a => DISPLAY_DATA_MENU(23 downto 16), - - -- Port B used for IOCTL access. - clock_b => IOCTL_CLK, - clocken_b => '1', - address_b => IOCTL_ADDR(10 downto 0), - data_b => IOCTL_DOUT, - wren_b => IOCTL_WEN_MNURAM_B, - q_b => IOCTL_DIN_MNURAM_B -); - --- 0 = MZ80K CGROM = 2Kbytes -> 0000:07ff --- 1 = MZ80C CGROM = 2Kbytes -> 0800:0fff --- 2 = MZ1200 CGROM = 2Kbytes -> 1000:17ff --- 3 = MZ80A CGROM = 2Kbytes -> 1800:1fff --- 4 = MZ700 CGROM = 4Kbytes -> 2000:2fff --- -CGROM0 : dpram -GENERIC MAP ( - init_file => "./mif/combined_cgrom.mif", - widthad_a => 15, - width_a => 8, - widthad_b => 15, - width_b => 8 -) -PORT MAP ( - clock_a => CLKBUS(CKMASTER), - clocken_a => '1', - address_a => CGROM_BANK & CG_ADDR(10 downto 0), - data_a => (others => '0'), - wren_a => '0', - q_a => CGROM_DO, - - clock_b => IOCTL_CLK, - clocken_b => '1', - address_b => IOCTL_ADDR(14 downto 0), - data_b => IOCTL_DOUT(7 downto 0), - wren_b => IOCTL_WEN_CGROM, - q_b => IOCTL_DIN_CGROM -); - -CGRAM : dpram -GENERIC MAP ( - init_file => "./mif/combined_cgrom.mif", - widthad_a => 15, - width_a => 8, - widthad_b => 15, - width_b => 8 -) -PORT MAP ( - clock_a => CLKBUS(CKMASTER), - clocken_a => '1', - address_a => CGROM_BANK & CG_ADDR(10 downto 0), - data_a => CGRAM_DI, - wren_a => CGRAM_WEN, - q_a => CGRAM_DO, - - clock_b => IOCTL_CLK, - clocken_b => '1', - address_b => IOCTL_ADDR(14 downto 0), - data_b => IOCTL_DOUT(7 downto 0), - wren_b => IOCTL_WEN_CGRAM, - q_b => IOCTL_DIN_CGRAM -); - --- Clock as maximum system speed to minimise transfer time. --- -process( RST_n, CLKBUS(CKMASTER) ) - variable XFER_CYCLE : integer range 0 to 10; - variable XFER_ENABLED : std_logic; -- Enable transfer of VRAM/GRAM to framebuffer. - variable XFER_PAUSE : std_logic; -- Pause transfer of VRAM/GRAM to framebuffer during data display period. - variable XFER_SRC_COL : integer range 0 to 80; - variable XFER_DST_SUBROW : integer range 0 to 7; -begin - if RST_n='0' then - XFER_VRAM_ADDR <= (others => '0'); - XFER_DST_ADDR <= (others => '0'); - XFER_CGROM_ADDR <= (others => '0'); - XFER_ENABLED := '0'; - XFER_PAUSE := '0'; - XFER_SRC_COL := 0; - XFER_DST_SUBROW := 0; - XFER_CYCLE := 0; - XFER_WEN <= '0'; - XFER_MAPPED_DATA <= (others => '0'); - - -- Copy at end of Display based on the highest clock to minimise time, - -- - elsif rising_edge(CLKBUS(CKMASTER)) then - - -- Every time we reach the end of the visible display area we enable copying of the VRAM and GRAM into the - -- display framebuffer, ready for the next frame display. This starts to occur a fixed set of rows after - -- they have been displayed, initially only during the hblank period of a row, but the during the full row - -- in the vblank period. - -- - if V_COUNT = to_unsigned(V_XFER_START, V_COUNT'length) then - XFER_ENABLED := '1'; - --XFER_CYCLE := 0; - end if; - - -- During the actual data display, we pause until the start of the hblanking period. - -- - if XFER_WEN = '0' and H_BLANKi = '0' and V_BLANKi = '0' then -- XFER_WEN = '0' and (((V_COUNT >= V_DSP_START and V_COUNT < V_DSP_END) and (H_COUNT >= H_DSP_START and H_COUNT < H_DSP_END)) or (H_COUNT >= H_LINE_END-1)) then - XFER_PAUSE := '1'; - else - XFER_PAUSE := '0'; - end if; - - -- If we are in the active transfer window, start transfer. - -- - if XFER_ENABLED = '1' and XFER_PAUSE = '0' then - - -- Once we reach the end of the framebuffer, disable the copying until next frame. - -- - if XFER_DST_ADDR = 16383 then - XFER_ENABLED := '0'; - end if; - - -- Finite state machine to implement read, map and write. - case (XFER_CYCLE) is - - when 0 => - XFER_MAPPED_DATA <= (others => '0'); - XFER_CYCLE := 1; - - -- Get the source character and map via the PCG to a slice of the displayed character. - -- Recalculate the destination address based on this loops values. - when 1 => - -- Setup the PCG address based on the read character. - XFER_CGROM_ADDR <= XFER_VRAM_DATA(15) & XFER_VRAM_DATA(7 downto 0) & std_logic_vector(to_unsigned(XFER_DST_SUBROW, 3)); - XFER_CYCLE := 2; - - -- Graphics mode:- 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), - -- 5 = GRAM Output Enable 0 = active. - -- 4 = VRAM Output Enable, 0 = active. - -- 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), - -- 1/0 = Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used). - -- - -- Extra cycle for CGROM to latch, use time to decide which mode we are processing. - when 2 => - -- Check to see if VRAM is disabled, if it is, skip. - -- - if CONFIG(VRAMDISABLE) = '0' and GRAM_MODE(4) = '0' and (CONFIG(NORMAL) = '1' or CONFIG(NORMAL80) = '1') then - -- Monochrome modes? - XFER_CYCLE := 4; - - elsif CONFIG(VRAMDISABLE) = '0' and GRAM_MODE(4) = '0' and (CONFIG(COLOUR) = '1' or CONFIG(COLOUR80) = '1') then - -- Colour modes? - XFER_CYCLE := 3; - - else - -- Disabled or unrecognised mode. - XFER_CYCLE := 5; - end if; - - -- Colour modes? - -- Expand and store the slice of the character with colour expansion. - -- - when 3 => - if CGROM_DATA(7) = '0' then - XFER_MAPPED_DATA(7) <= XFER_VRAM_DATA(10); - XFER_MAPPED_DATA(15) <= XFER_VRAM_DATA(9); - XFER_MAPPED_DATA(23) <= XFER_VRAM_DATA(8); - else - XFER_MAPPED_DATA(7) <= XFER_VRAM_DATA(14); - XFER_MAPPED_DATA(15) <= XFER_VRAM_DATA(13); - XFER_MAPPED_DATA(23) <= XFER_VRAM_DATA(12); - end if; - if CGROM_DATA(6) = '0' then - XFER_MAPPED_DATA(6) <= XFER_VRAM_DATA(10); - XFER_MAPPED_DATA(14) <= XFER_VRAM_DATA(9); - XFER_MAPPED_DATA(22) <= XFER_VRAM_DATA(8); - else - XFER_MAPPED_DATA(6) <= XFER_VRAM_DATA(14); - XFER_MAPPED_DATA(14) <= XFER_VRAM_DATA(13); - XFER_MAPPED_DATA(22) <= XFER_VRAM_DATA(12); - end if; - if CGROM_DATA(5) = '0' then - XFER_MAPPED_DATA(5) <= XFER_VRAM_DATA(10); - XFER_MAPPED_DATA(13) <= XFER_VRAM_DATA(9); - XFER_MAPPED_DATA(21) <= XFER_VRAM_DATA(8); - else - XFER_MAPPED_DATA(5) <= XFER_VRAM_DATA(14); - XFER_MAPPED_DATA(13) <= XFER_VRAM_DATA(13); - XFER_MAPPED_DATA(21) <= XFER_VRAM_DATA(12); - end if; - if CGROM_DATA(4) = '0' then - XFER_MAPPED_DATA(4) <= XFER_VRAM_DATA(10); - XFER_MAPPED_DATA(12) <= XFER_VRAM_DATA(9); - XFER_MAPPED_DATA(20) <= XFER_VRAM_DATA(8); - else - XFER_MAPPED_DATA(4) <= XFER_VRAM_DATA(14); - XFER_MAPPED_DATA(12) <= XFER_VRAM_DATA(13); - XFER_MAPPED_DATA(20) <= XFER_VRAM_DATA(12); - end if; - if CGROM_DATA(3) = '0' then - XFER_MAPPED_DATA(3) <= XFER_VRAM_DATA(10); - XFER_MAPPED_DATA(11) <= XFER_VRAM_DATA(9); - XFER_MAPPED_DATA(19) <= XFER_VRAM_DATA(8); - else - XFER_MAPPED_DATA(3) <= XFER_VRAM_DATA(14); - XFER_MAPPED_DATA(11) <= XFER_VRAM_DATA(13); - XFER_MAPPED_DATA(19) <= XFER_VRAM_DATA(12); - end if; - if CGROM_DATA(2) = '0' then - XFER_MAPPED_DATA(2) <= XFER_VRAM_DATA(10); - XFER_MAPPED_DATA(10) <= XFER_VRAM_DATA(9); - XFER_MAPPED_DATA(18) <= XFER_VRAM_DATA(8); - else - XFER_MAPPED_DATA(2) <= XFER_VRAM_DATA(14); - XFER_MAPPED_DATA(10) <= XFER_VRAM_DATA(13); - XFER_MAPPED_DATA(18) <= XFER_VRAM_DATA(12); - end if; - if CGROM_DATA(1) = '0' then - XFER_MAPPED_DATA(1) <= XFER_VRAM_DATA(10); - XFER_MAPPED_DATA(9) <= XFER_VRAM_DATA(9); - XFER_MAPPED_DATA(17) <= XFER_VRAM_DATA(8); - else - XFER_MAPPED_DATA(1) <= XFER_VRAM_DATA(14); - XFER_MAPPED_DATA(9) <= XFER_VRAM_DATA(13); - XFER_MAPPED_DATA(17) <= XFER_VRAM_DATA(12); - end if; - if CGROM_DATA(0) = '0' then - XFER_MAPPED_DATA(0) <= XFER_VRAM_DATA(10); - XFER_MAPPED_DATA(8) <= XFER_VRAM_DATA(9); - XFER_MAPPED_DATA(16) <= XFER_VRAM_DATA(8); - else - XFER_MAPPED_DATA(0) <= XFER_VRAM_DATA(14); - XFER_MAPPED_DATA(8) <= XFER_VRAM_DATA(13); - XFER_MAPPED_DATA(16) <= XFER_VRAM_DATA(12); - end if; - XFER_CYCLE := 6; - - -- Monochrome modes? - -- Expand and store the slice of the character. - -- - when 4 => - if CGROM_DATA(7) = '1' then - XFER_MAPPED_DATA(7) <= '1'; - if CONFIG(MZ_KC) = '1' then - XFER_MAPPED_DATA(15) <= '1'; - XFER_MAPPED_DATA(23) <= '1'; - end if; - end if; - if CGROM_DATA(6) = '1' then - XFER_MAPPED_DATA(6) <= '1'; - if CONFIG(MZ_KC) = '1' then - XFER_MAPPED_DATA(14) <= '1'; - XFER_MAPPED_DATA(22) <= '1'; - end if; - end if; - if CGROM_DATA(5) = '1' then - XFER_MAPPED_DATA(5) <= '1'; - if CONFIG(MZ_KC) = '1' then - XFER_MAPPED_DATA(13) <= '1'; - XFER_MAPPED_DATA(21) <= '1'; - end if; - end if; - if CGROM_DATA(4) = '1' then - XFER_MAPPED_DATA(4) <= '1'; - if CONFIG(MZ_KC) = '1' then - XFER_MAPPED_DATA(12) <= '1'; - XFER_MAPPED_DATA(20) <= '1'; - end if; - end if; - if CGROM_DATA(3) = '1' then - XFER_MAPPED_DATA(3) <= '1'; - if CONFIG(MZ_KC) = '1' then - XFER_MAPPED_DATA(11) <= '1'; - XFER_MAPPED_DATA(19) <= '1'; - end if; - end if; - if CGROM_DATA(2) = '1' then - XFER_MAPPED_DATA(2) <= '1'; - if CONFIG(MZ_KC) = '1' then - XFER_MAPPED_DATA(10) <= '1'; - XFER_MAPPED_DATA(18) <= '1'; - end if; - end if; - if CGROM_DATA(1) = '1' then - XFER_MAPPED_DATA(1) <= '1'; - if CONFIG(MZ_KC) = '1' then - XFER_MAPPED_DATA(9) <= '1'; - XFER_MAPPED_DATA(17) <= '1'; - end if; - end if; - if CGROM_DATA(0) = '1' then - XFER_MAPPED_DATA(0) <= '1'; - if CONFIG(MZ_KC) = '1' then - XFER_MAPPED_DATA(8) <= '1'; - XFER_MAPPED_DATA(16) <= '1'; - end if; - end if; - XFER_CYCLE := 5; - - when 5 => - -- If invert option selected, invert green. - -- - if (CONFIG(MZ_80B) = '1' and INVERSE_n = '0') or (CONFIG(MZ_A) = '1' and DISPLAY_INVERT = '1') then - XFER_MAPPED_DATA(7 downto 0) <= not XFER_MAPPED_DATA(7 downto 0); - end if; - XFER_CYCLE := 6; - - when 6 => - -- Graphics ram enabled? - -- - if CONFIG(GRAMDISABLE) = '0' and GRAM_MODE(5) = '0' then - -- Merge in the graphics data using defined mode. - -- - case GRAM_MODE(7 downto 6) is - when "00" => - XFER_MAPPED_DATA <= XFER_MAPPED_DATA or reverse_vector(XFER_GRAM_DATA(23 downto 16)) & reverse_vector(XFER_GRAM_DATA(15 downto 8)) & reverse_vector(XFER_GRAM_DATA(7 downto 0)); - when "01" => - XFER_MAPPED_DATA <= XFER_MAPPED_DATA and reverse_vector(XFER_GRAM_DATA(23 downto 16)) & reverse_vector(XFER_GRAM_DATA(15 downto 8)) & reverse_vector(XFER_GRAM_DATA(7 downto 0)); - when "10" => - XFER_MAPPED_DATA <= XFER_MAPPED_DATA nand reverse_vector(XFER_GRAM_DATA(23 downto 16)) & reverse_vector(XFER_GRAM_DATA(15 downto 8)) & reverse_vector(XFER_GRAM_DATA(7 downto 0)); - when "11" => - XFER_MAPPED_DATA <= XFER_MAPPED_DATA xor reverse_vector(XFER_GRAM_DATA(23 downto 16)) & reverse_vector(XFER_GRAM_DATA(15 downto 8)) & reverse_vector(XFER_GRAM_DATA(7 downto 0)); - end case; - end if; - XFER_CYCLE := 7; - - when 7 => - -- For MZ80B, if enabled, blend in the graphics memory. - -- - if CONFIG(MZ_80B) = '1' and XFER_DST_ADDR < 8192 then - if GRAM_OPT_OUT1 = '1' and GRAM_OPT_OUT2 = '1' then - XFER_MAPPED_DATA(15 downto 8) <= XFER_MAPPED_DATA(15 downto 8) or reverse_vector(XFER_GRAM_DATA(31 downto 24)) or reverse_vector(XFER_GRAM_DATA(39 downto 32)); - elsif GRAM_OPT_OUT1 = '1' then - XFER_MAPPED_DATA(15 downto 8) <= XFER_MAPPED_DATA(15 downto 8) or reverse_vector(XFER_GRAM_DATA(31 downto 24)); - elsif GRAM_OPT_OUT2 = '1' then - XFER_MAPPED_DATA(15 downto 8) <= XFER_MAPPED_DATA(15 downto 8) or reverse_vector(XFER_GRAM_DATA(39 downto 32)); - end if; - end if; - XFER_CYCLE := 8; - - -- Commence write of mapped data. - when 8 => - XFER_WEN <= '1'; - XFER_CYCLE := 9; - - -- Complete write and update address. - when 9 => - -- Write cycle to framebuffer finished. - XFER_WEN <= '0'; - XFER_CYCLE := 10; - - when 10 => - -- For each source character, we generate 8 lines in the frame buffer. Thus we need to - -- process the same source row 8 times, each time incrementing the sub-row which is used - -- to extract the next pixel set from the CG. This data is thus written into the destination as:- - -- .. - -- .. - -- .. - -- - -- To achieve this, we keep a note of the column and sub-row, incrementing the source address until end of line - -- then winding it back if we are still rendering the Characters for a given row. - -- Destination address always increments every clock cycle to take the next pixel set. - -- - if XFER_SRC_COL < MAX_COLUMN - 1 then - XFER_SRC_COL := XFER_SRC_COL + 1; - XFER_VRAM_ADDR <= XFER_VRAM_ADDR + 1; - else - if XFER_DST_SUBROW < MAX_SUBROW -1 then - XFER_SRC_COL := 0; - XFER_DST_SUBROW := XFER_DST_SUBROW + 1; - XFER_VRAM_ADDR <= XFER_VRAM_ADDR - (MAX_COLUMN - 1); - else - XFER_SRC_COL := 0; - XFER_VRAM_ADDR <= XFER_VRAM_ADDR + 1; - XFER_DST_SUBROW := 0; - end if; - end if; - - -- Destination address increments every tick. - -- - XFER_DST_ADDR <= XFER_DST_ADDR + 1; - XFER_CYCLE := 0; - end case; - end if; - - -- On a new cycle, reset the transfer parameters. - -- - if V_COUNT = V_LINE_END and H_COUNT = H_LINE_END - 1 then - - -- Start of display, setup the start of VRAM for display according to machine. - if CONFIG(MZ_A) = '1' then - XFER_VRAM_ADDR <= (OFFSET_ADDR & "000"); - else - XFER_VRAM_ADDR <= (others => '0'); - end if; - XFER_DST_ADDR <= (others => '0'); - XFER_CGROM_ADDR <= (others => '0'); - XFER_SRC_COL := 0; - XFER_DST_SUBROW := 0; - XFER_CYCLE := 0; - XFER_ENABLED := '0'; - XFER_WEN <= '0'; - XFER_MAPPED_DATA <= (others => '0'); - end if; - end if; -end process; - --- Process to generate the video data signals. --- -process( RST_n, CLKBUS, VIDEOMODE_CHANGED ) -begin - -- On reset, set the basic parameters which hold the video signal generator in reset - -- then load up the required parameter set and generate the video signal. - -- - if RST_n = '0' then - H_DSP_START <= 0; - H_DSP_END <= 0; - H_DSP_WND_START <= 0; - H_DSP_WND_END <= 0; - H_MNU_START <= 0; - H_MNU_END <= 0; - H_HDR_START <= 0; - H_HDR_END <= 0; - H_FTR_START <= 0; - H_FTR_END <= 0; - V_DSP_START <= 0; - V_DSP_END <= 0; - V_DSP_WND_START <= 0; - V_DSP_WND_END <= 0; - V_MNU_START <= 0; - V_MNU_END <= 0; - V_HDR_START <= 0; - V_HDR_END <= 0; - V_FTR_START <= 0; - V_FTR_END <= 0; - MAX_COLUMN <= 0; - H_LINE_END <= 0; - V_LINE_END <= 0; - V_XFER_START <= 0; - H_COUNT <= (others => '0'); - V_COUNT <= (others => '0'); - H_BLANKi <= '1'; - V_BLANKi <= '1'; - H_SYNC_ni <= '1'; - V_SYNC_ni <= '1'; - H_PX_CNT <= 0; - V_PX_CNT <= 0; - H_SHIFT_CNT <= 0; - H_MNU_SHIFT_CNT <= 0; - VIDEOMODE_LAST <= 0; - VIDEOMODE_CHANGED <= '1'; - FB_ADDR <= (others => '0'); - FB_ADDR_STATUS <= (others => '0'); - FB_ADDR_MENU <= (others => '0'); - - elsif rising_edge(CLKBUS(CKVIDEO)) then - - -- If the video mode changes, reset the variables to the initial state. This occurs - -- at the end of a frame to minimise the monitor syncing incorrectly. - -- - VIDEOMODE_LAST <= VIDEOMODE; - if VIDEOMODE_LAST /= VIDEOMODE then - VIDEOMODE_CHANGED <= '1'; - end if; - if VIDEOMODE_CHANGED = '1' then - - -- Iniitialise control registers. - -- - FB_ADDR <= (others => '0'); - FB_ADDR_STATUS <= (others => '0'); - FB_ADDR_MENU <= (others => '0'); - VIDEOMODE_CHANGED <= '0'; - - -- Load up configuration from the look up table based on video mode. - -- - H_DSP_START <= FB_PARAMS(VIDEOMODE, 0); - H_DSP_END <= FB_PARAMS(VIDEOMODE, 1); - H_DSP_WND_START <= FB_PARAMS(VIDEOMODE, 2); - H_DSP_WND_END <= FB_PARAMS(VIDEOMODE, 3); - H_MNU_START <= FB_PARAMS(VIDEOMODE, 4); - H_MNU_END <= FB_PARAMS(VIDEOMODE, 5); - H_HDR_START <= FB_PARAMS(VIDEOMODE, 6); - H_HDR_END <= FB_PARAMS(VIDEOMODE, 7); - H_FTR_START <= FB_PARAMS(VIDEOMODE, 8); - H_FTR_END <= FB_PARAMS(VIDEOMODE, 9); - V_DSP_START <= FB_PARAMS(VIDEOMODE, 10); - V_DSP_END <= FB_PARAMS(VIDEOMODE, 11); - V_DSP_WND_START <= FB_PARAMS(VIDEOMODE, 12); - V_DSP_WND_END <= FB_PARAMS(VIDEOMODE, 13); - V_MNU_START <= FB_PARAMS(VIDEOMODE, 14); - V_MNU_END <= FB_PARAMS(VIDEOMODE, 15); - V_HDR_START <= FB_PARAMS(VIDEOMODE, 16); - V_HDR_END <= FB_PARAMS(VIDEOMODE, 17); - V_FTR_START <= FB_PARAMS(VIDEOMODE, 18); - V_FTR_END <= FB_PARAMS(VIDEOMODE, 19); - H_LINE_END <= FB_PARAMS(VIDEOMODE, 20); - V_LINE_END <= FB_PARAMS(VIDEOMODE, 21); - V_XFER_START <= FB_PARAMS(VIDEOMODE, 22); - MAX_COLUMN <= FB_PARAMS(VIDEOMODE, 23); - H_SYNC_START <= FB_PARAMS(VIDEOMODE, 24); - H_SYNC_END <= FB_PARAMS(VIDEOMODE, 25); - V_SYNC_START <= FB_PARAMS(VIDEOMODE, 26); - V_SYNC_END <= FB_PARAMS(VIDEOMODE, 27); - H_PX <= FB_PARAMS(VIDEOMODE, 28); - V_PX <= FB_PARAMS(VIDEOMODE, 29); - -- - H_COUNT <= (others => '0'); --to_unsigned(FB_PARAMS(VIDEOMODE, 16), H_COUNT'length); -- ((others => '0'); - V_COUNT <= (others => '0'); --to_unsigned(FB_PARAMS(VIDEOMODE, 17), V_COUNT'length); -- (others => '0'); - H_BLANKi <= '0'; - V_BLANKi <= '0'; - H_SYNC_ni <= '1'; - V_SYNC_ni <= '1'; - H_PX_CNT <= 0; - V_PX_CNT <= 0; - H_SHIFT_CNT <= 0; - H_MNU_SHIFT_CNT <= 0; - - else - - -- Activate/deactivate signals according to pixel position. - -- - if H_COUNT = H_DSP_START then H_BLANKi <= '0'; end if; - --if H_COUNT = H_LINE_END then H_BLANKi <= '0'; end if; - if H_COUNT = H_DSP_END then H_BLANKi <= '1'; end if; - if H_COUNT = H_SYNC_END then H_SYNC_ni <= '1'; end if; - if H_COUNT = H_SYNC_START then H_SYNC_ni <= '0'; end if; - if V_COUNT = V_DSP_START then V_BLANKi <= '0'; end if; - --if V_COUNT = V_LINE_END then V_BLANKi <= '0'; end if; - if V_COUNT = V_DSP_END then V_BLANKi <= '1'; end if; - if V_COUNT = V_SYNC_START then V_SYNC_ni <= '0'; end if; - if V_COUNT = V_SYNC_END then V_SYNC_ni <= '1'; end if; - - -- If we are in the active visible area, stream the required output based on the various buffers. - -- - if H_COUNT >= H_DSP_START and H_COUNT < H_DSP_END and V_COUNT >= V_DSP_START and V_COUNT < V_DSP_END then - - -- Update Horizontal Pixel multiplier. - -- - if H_PX_CNT = 0 then - - H_PX_CNT <= H_PX; - H_SHIFT_CNT <= H_SHIFT_CNT - 1; - - -- Main screen. - -- - if H_SHIFT_CNT = 0 then - if (V_COUNT >= V_DSP_WND_START and V_COUNT < V_DSP_WND_END) and (H_COUNT >= H_DSP_WND_START and H_COUNT < H_DSP_WND_END) then - - -- During the visible portion of the frame, data is stored in the frame buffer in bytes, 1 bit per pixel x 8 and 3 colors, - -- thus 1 x 8 x 3 or 24 bit. Read out the values into shift registers to be serialised. - -- - SR_G_DATA <= DISPLAY_DATA(7 downto 0); - SR_R_DATA <= DISPLAY_DATA(15 downto 8); - SR_B_DATA <= DISPLAY_DATA(23 downto 16); - FB_ADDR <= FB_ADDR + 1; - - -- Border. - -- - else - -- Generate a fixed colour border, ideal for debugging. - -- - SR_G_DATA <= (others => '0'); - SR_R_DATA <= "11111111"; - SR_B_DATA <= (others => '0'); - end if; - - elsif H_SHIFT_CNT /= 0 and H_COUNT >= H_DSP_START and H_COUNT < H_DSP_END and V_COUNT >= V_DSP_START and V_COUNT < V_DSP_END then - -- During the active display area, if the shift counter is not 0 and the horizontal multiplier is equal to the setting, - -- shift the data in the shift register to display the next pixel. - -- - SR_G_DATA <= SR_G_DATA(6 downto 0) & '0'; - SR_R_DATA <= SR_R_DATA(6 downto 0) & '0'; - SR_B_DATA <= SR_B_DATA(6 downto 0) & '0'; - end if; - else - H_PX_CNT <= H_PX_CNT - 1; - end if; - - -- If the Status areas or the menu is enabled, create a data stream for the status/menu data to be merged with the main data. - -- - if CONFIG(MENUENABLE) = '1' or CONFIG(STATUSENABLE) = '1' then - - H_MNU_SHIFT_CNT <= H_MNU_SHIFT_CNT - 1; - - -- On each reset of the shift counter, load up Menu, Header, Footer or blank data to be serialised. - -- - if H_MNU_SHIFT_CNT = 0 then - - -- OSD Menu - -- - if CONFIG(MENUENABLE) = '1' and H_MNU_SHIFT_CNT = 0 - and - ((V_COUNT >= V_MNU_START and V_COUNT < V_MNU_END) and (H_COUNT >= H_MNU_START and H_COUNT < H_MNU_END)) then - - -- Merge the OSD with the underlying screen data. - -- - SR_MNU_G_DATA <= DISPLAY_DATA_MENU( 7 downto 0); - SR_MNU_R_DATA <= DISPLAY_DATA_MENU(15 downto 8); - SR_MNU_B_DATA <= DISPLAY_DATA_MENU(23 downto 16); - FB_ADDR_MENU <= FB_ADDR_MENU + 1; - - -- Header/Footer - -- - elsif CONFIG(STATUSENABLE) = '1' and H_MNU_SHIFT_CNT = 0 - and - (((H_HDR_START /= H_HDR_END) and ((V_COUNT >= V_HDR_START and V_COUNT < V_HDR_END) and (H_COUNT >= H_HDR_START and H_COUNT < H_HDR_END))) - or - ((H_FTR_START /= H_FTR_END) and ((V_COUNT >= V_FTR_START and V_COUNT < V_FTR_END) and (H_COUNT >= H_FTR_START and H_COUNT < H_FTR_END)))) then - - -- During the visible portion of the unused header/footer, read out the status frame buffer, 1 bit per pixel x 8 and 3 colours. - -- - SR_MNU_G_DATA <= DISPLAY_DATA_STATUS( 7 downto 0); - SR_MNU_R_DATA <= DISPLAY_DATA_STATUS(15 downto 8); - SR_MNU_B_DATA <= DISPLAY_DATA_STATUS(23 downto 16); - FB_ADDR_STATUS <= FB_ADDR_STATUS + 1; - - -- Blank. - -- - else - -- Generate a fixed colour border, ideal for debugging. - -- - SR_MNU_G_DATA <= (others => '0'); - SR_MNU_R_DATA <= (others => '0'); - SR_MNU_B_DATA <= (others => '0'); - end if; - - -- Shift on each clock cycle to next active bit if not at start. - -- - elsif H_MNU_SHIFT_CNT /= 0 then - SR_MNU_G_DATA <= SR_MNU_G_DATA(6 downto 0) & '0'; - SR_MNU_R_DATA <= SR_MNU_R_DATA(6 downto 0) & '0'; - SR_MNU_B_DATA <= SR_MNU_B_DATA(6 downto 0) & '0'; - end if; - end if; - else - H_PX_CNT <= 0; - H_SHIFT_CNT <= 0; - H_MNU_SHIFT_CNT <= 0; - end if; - - -- Horizontal/Vertical counters are updated each clock cycle to accurately track pixel/timing. - -- - if H_COUNT = H_LINE_END then - H_COUNT <= (others => '0'); - H_PX_CNT <= 0; - - -- Update Vertical Pixel multiplier. - -- - if V_PX_CNT = 0 then - V_PX_CNT <= V_PX; - else - V_PX_CNT <= V_PX_CNT - 1; - end if; - - -- When we need to repeat a line due to pixel multiplying, wind back the framebuffer address to start of line. - -- - if V_COUNT >= V_DSP_WND_START and V_COUNT < V_DSP_WND_END and V_PX /= 0 and V_PX_CNT > 0 then - FB_ADDR <= FB_ADDR - MAX_COLUMN; - end if; - - -- For VGA, expand the vertical pixels according to setting. - -- - if CONFIG(MENUENABLE) = '1' and ((V_COUNT >= V_MNU_START and V_COUNT < V_MNU_END) and (H_COUNT >= H_MNU_START and H_COUNT < H_MNU_END)) and V_PX /= 0 and V_PX_CNT > 0 then - FB_ADDR_MENU <= FB_ADDR_MENU - 32; - end if; - - -- Once we have reached the end of the active vertical display, reset the framebuffer address. - -- - if V_COUNT = V_DSP_END then - FB_ADDR <= (others => '0'); - FB_ADDR_STATUS <= (others => '0'); - FB_ADDR_MENU <= (others => '0'); - end if; - - -- End of vertical line, increment to next or reset to beginning. - -- - if V_COUNT = V_LINE_END then - V_COUNT <= (others => '0'); - V_PX_CNT <= 0; - else - V_COUNT <= V_COUNT + 1; - end if; - else - H_COUNT <= H_COUNT + 1; - end if; - end if; - end if; -end process; - --- Control Registers --- --- MZ1200/80A: INVERT display, accessed at E014 --- SCROLL display, accessed at E200 - E2FF, the address determines the offset. --- F0-F3 clocks the i8253 gate for MZ80B. (not used in this module) --- F4-F7 set ths MZ80B/MZ2000 graphics options. Bit 0 = 0, Write to Graphics RAM I, Bit 0 = 1, Write to Graphics RAM II. --- Bit 1 = 1, blend Graphics RAM I output on display, Bit 2 = 1, blend Graphics RAM II output on display. --- --- IO Range for Graphics enhancements is set by the MCTRL DISPLAY2{7:3] register. --- x[0|8], sets the graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used). --- x[1|9], sets the Red bit mask (1 bit = 1 pixel, 8 pixels per byte). --- x[2|A], sets the Green bit mask (1 bit = 1 pixel, 8 pixels per byte). --- x[3|B], sets the Blue bit mask (1 bit = 1 pixel, 8 pixels per byte). --- x[4|C] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. This overrides all MZ700 page switching functions. --- x[5|D] switches out the graphics ram and returns to previous state. --- -process( RST_n, CLKBUS(CKMASTER) ) -begin - if RST_n='0' then - DISPLAY_INVERT <= '0'; - OFFSET_ADDR <= (others => '0'); - GRAM_MODE <= "00001100"; - GRAM_R_FILTER <= (others => '1'); - GRAM_G_FILTER <= (others => '1'); - GRAM_B_FILTER <= (others => '1'); - GRAM_OPT_WRITE <= '0'; - GRAM_OPT_OUT1 <= '0'; - GRAM_OPT_OUT2 <= '0'; - - elsif rising_edge(CLKBUS(CKMASTER)) then - - if CLKBUS(CKENCPU) = '1' then - - if CS_INVERT_n='0' and T80_RD_n='0' then - DISPLAY_INVERT <= T80_MA(0); - end if; - - if CS_SCROLL_n='0' and T80_RD_n='0' then - if CONFIG(NORMAL80) = '1' or CONFIG(COLOUR80) = '1' then - OFFSET_ADDR <= (others => '0'); - else - OFFSET_ADDR <= T80_A(7 downto 0); - end if; - end if; - - if CS_FB_CTL_n = '0' and T80_WR_n = '0' then - GRAM_MODE <= T80_DI; - end if; - - if CS_FB_RED_n = '0' and T80_WR_n = '0' then - GRAM_R_FILTER <= T80_DI; - end if; - - if CS_FB_GREEN_n = '0' and T80_WR_n = '0' then - GRAM_G_FILTER <= T80_DI; - end if; - - if CS_FB_BLUE_n = '0' and T80_WR_n = '0' then - GRAM_B_FILTER <= T80_DI; - end if; - - if CS_GRAM_OPT_n = '0' and T80_WR_n = '0' then - GRAM_OPT_WRITE <= T80_DI(0); - GRAM_OPT_OUT1 <= T80_DI(1); - GRAM_OPT_OUT2 <= T80_DI(2); - end if; - end if; - end if; -end process; - --- Enable Video Wait States - Original design has wait states inserted into the cycle if the CPU accesses the VRAM during display. In the updated design, the VRAM --- is copied into a framebuffer during the Vertical Blanking period so no wait states are needed. To keep consistency with the original design (for programs which depend on it), --- the wait states can be enabled by configuration. --- -process( T80_MREQ_n ) begin - if falling_edge(T80_MREQ_n) then - VRAM_WAIT <= H_BLANKi; - end if; -end process; --- --- Extend wait by 1 cycle -process( CLKBUS(CKMASTER) ) begin - if rising_edge(CLKBUS(CKMASTER)) then - if CLKBUS(CKENCPU) = '1' then - WAITii_n <= WAITi_n; - end if; - end if; -end process; - --- --- PCG Access Registers --- --- E010: PCG_DATA (byte to describe 8-pixel row of a character) --- E011: PCG_ADDR (offset in the PCG in 8-pixel row unit) -> up to 256/8 = 32 characters --- E012: PCG_CTRL --- bit 0-1: character selector -> (PCG_ADDR + 256*(PCG_CTRL&3)) -> address in the range of the upper 128 characters font --- bit 2 : font selector -> PCG_CTRL&2 == 0 -> 1st font else 2nd font --- bit 3 : select which font for display --- bit 4 : use programmable font for display --- bit 5 : set programmable upper font -> PCG_CTRL&20 == 0 -> fixed upper 128 characters else programmable upper 128 characters --- So if you want to change a character pattern (only doable in the upper 128 characters of a font), you need to: --- - set bit 5 to 1 : PCG_CTRL[5] = 1 --- - set the font to select : PCG_CTRL[2] = font_number --- - set the first row address of the character: PCG_ADDR[0..7] = row[0..7] and PCG_CTRL[0..1] = row[8..9] --- - set the 8 pixels of the row in PCG_DATA --- -process( RST_n, CLKBUS(CKMASTER) ) begin - if RST_n = '0' then - CGRAM_ADDR <= (others=>'0'); - PCG_DATA <= (others=>'0'); - CGRAM_WE_n <= '1'; - - elsif rising_edge(CLKBUS(CKMASTER)) then - - if CLKBUS(CKENCPU) = '1' then - - if CS_PCG_n = '0' and T80_WR_n = '0' then - -- Set the PCG Data to program to RAM. - if T80_A(1 downto 0) = "00" then - PCG_DATA <= T80_DI; - end if; - - -- Set the PCG Address in RAM. - if T80_A(1 downto 0) = "01" then - CGRAM_ADDR(7 downto 0) <= T80_DI; - end if; - - -- Set the PCG Control register. - if T80_A(1 downto 0) = "10" then - CGRAM_ADDR(11 downto 8) <= (T80_DI(2) and CONFIG(MZ_A)) & '1' & T80_DI(1 downto 0); - CGRAM_WE_n <= not T80_DI(4); - CGRAM_SEL <= T80_DI(5); - end if; - end if; - end if; - end if; -end process; - --- Process to allow the HPS or uC to read the configuration array. --- -process( IOCTL_CLK ) begin - if rising_edge(IOCTL_CLK) then - if IOCTL_ADDR(10) = '1' then - IOCTL_DIN_CONFIG <= "00000000000" & std_logic_vector(to_unsigned(VIDEOMODE, 5)); - else - IOCTL_DIN_CONFIG <= std_logic_vector(to_unsigned(FB_PARAMS(to_integer(unsigned(IOCTL_ADDR(4 downto 0))), to_integer(unsigned(IOCTL_ADDR(9 downto 5)))), IOCTL_DIN_CONFIG'length)); - end if; - end if; -end process; - --- --- CPU / RAM signals and selects. --- -WAITi_n <= '0' when CS_VRAM_n = '0' and VRAM_WAIT = '0' and H_BLANKi = '0' and (CONFIG(MZ_A) = '1' or CONFIG(MZ700) = '1') - else '1'; -T80_WAIT_n <= WAITi_n and WAITii_n when CONFIG(VRAMWAIT) = '1' - else '1'; -T80_MA <= "00" & T80_A(9 downto 0) when CONFIG(MZ_KC) = '1' - else - T80_A(11 downto 0); --- Program Character Generator RAM. E010 - Write cycle (Read cycle = reset memory swap). -CS_PCG_n <= '0' when CS_MEM_G_n = '0' and T80_A(10 downto 4) = "0000001" - else '1'; -- D010 -> D01f --- Invert display register. E014/E015 -CS_INVERT_n <= '0' when CS_MEM_G_n = '0' and CONFIG(MZ_A) = '1' and T80_MA(11 downto 9) = "000" and T80_MA(4 downto 2) = "101" - else '1'; --- Scroll display register. E200 - E2FF -CS_SCROLL_n <= '0' when CS_MEM_G_n = '0' and T80_A(11 downto 8)="0010" and CONFIG(MZ_A)='1' - else '1'; --- MZ80B/MZ2000 Graphics Options Register select. F4-F7 -CS_GRAM_OPT_n <= '0' when CS_IO_G_n = '0' and T80_A(1 downto 0) = "00" - else '1'; --- 0, sets the graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), --- 5 = GRAM Output Enable, 4 = VRAM Output Enable, --- 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), --- 1/0 = Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used). -CS_FB_CTL_n <= '0' when CS_IO_GFB_n = '0' and T80_A(2 downto 0) = "000" - else '1'; --- 01, sets the Red bit mask (1 bit = 1 pixel, 8 pixels per byte). -CS_FB_RED_n <= '0' when CS_IO_GFB_n = '0' and T80_A(2 downto 0) = "001" - else '1'; --- 02, sets the Green bit mask (1 bit = 1 pixel, 8 pixels per byte). -CS_FB_GREEN_n <= '0' when CS_IO_GFB_n = '0' and T80_A(2 downto 0) = "010" - else '1'; --- 03, sets the Blue bit mask (1 bit = 1 pixel, 8 pixels per byte). -CS_FB_BLUE_n <= '0' when CS_IO_GFB_n = '0' and T80_A(2 downto 0) = "011" - else '1'; - -T80_DO <= VRAM_VIDEO_DATA when T80_RD_n = '0' and CS_VRAM_n = '0' - else - GRAM_VIDEO_DATA when T80_RD_n = '0' and CS_GRAM_n = '0' - else - GRAM_DO_GI when T80_RD_n = '0' and CS_GRAM_80B_n = '0' and GRAM_OPT_WRITE = '0' - else - GRAM_DO_GII when T80_RD_n = '0' and CS_GRAM_80B_n = '0' and GRAM_OPT_WRITE = '1' - else - (others=>'0'); - -VRAM_ADDR <= T80_MA(10 downto 0) & T80_MA(11) when IOCTL_CS_VRAM_n = '1' - else - IOCTL_ADDR(10 downto 0) & IOCTL_ADDR(11); -VRAM_DI <= T80_DI when IOCTL_CS_VRAM_n = '1' - else - IOCTL_DOUT(7 downto 0); -VWEN <= '1' when T80_WR_n='0' and CS_VRAM_n = '0' - else '0'; -VRAM_WEN <= VWEN when IOCTL_CS_VRAM_n = '1' - else - IOCTL_WEN_VRAM; -VRAM_VIDEO_DATA <= VRAM_DO when IOCTL_CS_VRAM_n = '1' - else - (others=>'0'); -IOCTL_DIN_VRAM <= VRAM_DO when IOCTL_CS_VRAM_n = '0' - else - (others=>'0'); -VRAM_CLK <= CLKBUS(CKMASTER) when IOCTL_CS_VRAM_n = '1' - else - IOCTL_CLK; -VRAM_CLK_EN <= CLKBUS(CKENCPU) when IOCTL_CS_VRAM_n = '1' - else - '1'; - --- CGROM Data to CG RAM, either ROM -> RAM copy or Z80 provides map. --- -CGRAM_DI <= CGROM_DO when CGRAM_SEL = '1' -- Data from ROM - else - PCG_DATA when CGRAM_SEL = '0' -- Data from PCG - else (others=>'0'); -CGRAM_WEN <= not (CGRAM_WE_n or CS_PCG_n) and not T80_WR_n; - --- --- Font select --- -CGROM_DATA <= CGROM_DO when CONFIG(PCGRAM)='0' - else - PCG_DATA when CS_PCG_n='0' and T80_A(1 downto 0)="10" and T80_WR_n='0' - else - CGRAM_DO when CONFIG(PCGRAM)='1' - else (others => '1'); -CG_ADDR <= CGRAM_ADDR(11 downto 0) when CGRAM_WE_n = '0' - else XFER_CGROM_ADDR; -CGROM_BANK <= "0000" when CONFIG(MZ80K) = '1' - else - "0001" when CONFIG(MZ80C) = '1' - else - "0010" when CONFIG(MZ1200) = '1' - else - "0011" when CONFIG(MZ80A) = '1' - else - "0100" when CONFIG(MZ700) = '1' and XFER_CGROM_ADDR(11) = '0' - else - "0101" when CONFIG(MZ700) = '1' and XFER_CGROM_ADDR(11) = '1' - else - "0110" when CONFIG(MZ800) = '1' and XFER_CGROM_ADDR(11) = '0' - else - "0111" when CONFIG(MZ800) = '1' and XFER_CGROM_ADDR(11) = '1' - else - "1000" when CONFIG(MZ80B) = '1' - else - "1001" when CONFIG(MZ2000) = '1' - else - "1111"; - - --- As the Graphics RAM is an odd size, 16384 x 3 colour planes, it has to be in 3 seperate 16K blocks to avoid wasting memory (or having it synthesized away), --- thus there are 3 sets of signals, 1 per colour. --- -GRAM_ADDR <= T80_A(13 downto 0) when IOCTL_CS_GRAM_n = '1' - else - IOCTL_ADDR(13 downto 0); - -- direct writes when accessing individual pages. -GRAM_DI_R <= T80_DI when IOCTL_CS_GRAM_n = '1' and GRAM_MODE(3 downto 2) = "00" - else - T80_DI and GRAM_R_FILTER when IOCTL_CS_GRAM_n = '1' and GRAM_MODE(3 downto 2) = "11" - else - IOCTL_DOUT(7 downto 0) when IOCTL_CS_GRAM_n = '0' and IOCTL_ADDR(15 downto 14) = "00" - else - (others=>'0'); - -- direct writes when accessing individual pages. -GRAM_DI_G <= T80_DI when IOCTL_CS_GRAM_n = '1' and GRAM_MODE(3 downto 2) = "01" - else - T80_DI and GRAM_G_FILTER when IOCTL_CS_GRAM_n = '1' and GRAM_MODE(3 downto 2) = "11" - else - IOCTL_DOUT(7 downto 0) when IOCTL_CS_GRAM_n = '0' and IOCTL_ADDR(15 downto 14) = "01" - else - (others=>'0'); - -- direct writes when accessing individual pages. -GRAM_DI_B <= T80_DI when IOCTL_CS_GRAM_n = '1' and GRAM_MODE(3 downto 2) = "10" - else - T80_DI and GRAM_B_FILTER when IOCTL_CS_GRAM_n = '1' and GRAM_MODE(3 downto 2) = "11" - else - IOCTL_DOUT(7 downto 0) when IOCTL_CS_GRAM_n = '0' and IOCTL_ADDR(15 downto 14) = "10" - else - (others=>'0'); -GWEN_R <= '1' when T80_WR_n = '0' and CS_GRAM_n = '0' and GRAM_MODE(3 downto 2) = "00" - else - '1' when T80_WR_n = '0' and CS_GRAM_n = '0' and GRAM_MODE(3 downto 2) = "11" - else - '0'; -GRAM_WEN_R <= GWEN_R when IOCTL_CS_GRAM_n = '1' - else - IOCTL_WEN_GRAM_R; -GWEN_G <= '1' when T80_WR_n='0' and CS_GRAM_n = '0' and GRAM_MODE(3 downto 2) = "01" - else - '1' when T80_WR_n='0' and CS_GRAM_n = '0' and GRAM_MODE(3 downto 2) = "11" - else - '0'; -GRAM_WEN_G <= GWEN_G when IOCTL_CS_GRAM_n = '1' - else - IOCTL_WEN_GRAM_G; -GWEN_B <= '1' when T80_WR_n='0' and CS_GRAM_n = '0' and GRAM_MODE(3 downto 2) = "10" - else - '1' when T80_WR_n='0' and CS_GRAM_n = '0' and GRAM_MODE(3 downto 2) = "11" - else - '0'; -GRAM_WEN_B <= GWEN_B when IOCTL_CS_GRAM_n = '1' - else - IOCTL_WEN_GRAM_B; - -GRAM_VIDEO_DATA <= GRAM_DO_R when IOCTL_CS_GRAM_n = '1' and GRAM_MODE(1 downto 0) = "00" - else - GRAM_DO_G when IOCTL_CS_GRAM_n = '1' and GRAM_MODE(1 downto 0) = "01" - else - GRAM_DO_B when IOCTL_CS_GRAM_n = '1' and GRAM_MODE(1 downto 0) = "10" - else - (others=>'0'); -GRAM_CLK <= CLKBUS(CKMASTER) when IOCTL_CS_GRAM_n = '1' - else - IOCTL_CLK; -GRAM_CLK_EN <= CLKBUS(CKENCPU) when IOCTL_CS_GRAM_n = '1' - else - '1'; - --- MZ80B/MZ2000 Graphics Option RAM. --- -GRAM_DI_GI <= T80_DI when IOCTL_CS_GRAM_80B_n = '1' - else - IOCTL_DOUT(7 downto 0) when IOCTL_CS_GRAM_80B_n = '0' and IOCTL_ADDR(13) = '0' - else - (others=>'0'); -GRAM_DI_GII <= T80_DI when IOCTL_CS_GRAM_80B_n = '1' - else - IOCTL_DOUT(7 downto 0) when IOCTL_CS_GRAM_80B_n = '0' and IOCTL_ADDR(13) = '1' - else - (others=>'0'); -GWEN_GI <= '1' when T80_WR_n = '0' and CS_GRAM_80B_n = '0' and GRAM_OPT_WRITE = '0' - else - '0'; -GRAM_WEN_GI <= GWEN_GI when IOCTL_CS_GRAM_80B_n = '1' - else - IOCTL_WEN_GRAM_GI; -GWEN_GII <= '1' when T80_WR_n='0' and CS_GRAM_80B_n = '0' and GRAM_OPT_WRITE = '1' - else - '0'; -GRAM_WEN_GII <= GWEN_GII when IOCTL_CS_GRAM_80B_n = '1' - else - IOCTL_WEN_GRAM_GII; - --- --- HPS Access - match whole address, additional LE but easier to read. --- -IOCTL_WEN_VRAM <= '1' when IOCTL_CS_VRAM_n = '0' and IOCTL_WR = '1' - else '0'; -IOCTL_WEN_GRAM_R <= '1' when IOCTL_CS_GRAM_n = '0' and IOCTL_WR = '1' and IOCTL_ADDR(15 downto 14) = "00" - else '0'; -IOCTL_WEN_GRAM_G <= '1' when IOCTL_CS_GRAM_n = '0' and IOCTL_WR = '1' and IOCTL_ADDR(15 downto 14) = "01" - else '0'; -IOCTL_WEN_GRAM_B <= '1' when IOCTL_CS_GRAM_n = '0' and IOCTL_WR = '1' and IOCTL_ADDR(15 downto 14) = "10" - else '0'; -IOCTL_WEN_GRAM_GI <= '1' when IOCTL_CS_GRAM_80B_n = '0' and IOCTL_WR = '1' and IOCTL_ADDR(13) = '0' - else '0'; -IOCTL_WEN_GRAM_GII <= '1' when IOCTL_CS_GRAM_80B_n = '0' and IOCTL_WR = '1' and IOCTL_ADDR(13) = '1' - else '0'; -IOCTL_WEN_CGROM <= '1' when IOCTL_CS_CGROM_n = '0' and IOCTL_WR = '1' - else '0'; -IOCTL_WEN_CGRAM <= '1' when IOCTL_CS_CGRAM_n = '0' and IOCTL_WR = '1' - else '0'; -IOCTL_WEN_STRAM_G <= '1' when IOCTL_CS_STRAM_G_n = '0' and IOCTL_WR = '1' - else '0'; -IOCTL_WEN_STRAM_R <= '1' when IOCTL_CS_STRAM_R_n = '0' and IOCTL_WR = '1' - else '0'; -IOCTL_WEN_STRAM_B <= '1' when IOCTL_CS_STRAM_B_n = '0' and IOCTL_WR = '1' - else '0'; -IOCTL_WEN_MNURAM_G <= '1' when IOCTL_CS_MNURAM_G_n = '0' and IOCTL_WR = '1' - else '0'; -IOCTL_WEN_MNURAM_R <= '1' when IOCTL_CS_MNURAM_R_n = '0' and IOCTL_WR = '1' - else '0'; -IOCTL_WEN_MNURAM_B <= '1' when IOCTL_CS_MNURAM_B_n = '0' and IOCTL_WR = '1' - else '0'; -IOCTL_CS_VRAM_n <= '0' when IOCTL_ADDR(24 downto 12) = "0001100000000" - else '1'; -IOCTL_CS_GRAM_n <= '0' when IOCTL_ADDR(24 downto 16) = "000110001" and IOCTL_ADDR(15 downto 14) /= "11" - else '1'; -IOCTL_CS_GRAM_80B_n <= '0' when IOCTL_ADDR(24 downto 14) = "00011000111" - else '1'; -IOCTL_CS_CGROM_n <= '0' when IOCTL_ADDR(24 downto 17) = "00101000" - else '1'; -IOCTL_CS_CGRAM_n <= '0' when IOCTL_ADDR(24 downto 17) = "00110000" - else '1'; -IOCTL_CS_STRAM_G_n <= '0' when IOCTL_ADDR(24 downto 16) = "000110010" and IOCTL_ADDR(15 downto 12) = "0000" - else '1'; -IOCTL_CS_STRAM_R_n <= '0' when IOCTL_ADDR(24 downto 16) = "000110010" and IOCTL_ADDR(15 downto 12) = "0001" - else '1'; -IOCTL_CS_STRAM_B_n <= '0' when IOCTL_ADDR(24 downto 16) = "000110010" and IOCTL_ADDR(15 downto 12) = "0010" - else '1'; -IOCTL_CS_MNURAM_G_n <= '0' when IOCTL_ADDR(24 downto 16) = "000110010" and IOCTL_ADDR(15 downto 12) = "0100" - else '1'; -IOCTL_CS_MNURAM_R_n <= '0' when IOCTL_ADDR(24 downto 16) = "000110010" and IOCTL_ADDR(15 downto 12) = "0101" - else '1'; -IOCTL_CS_MNURAM_B_n <= '0' when IOCTL_ADDR(24 downto 16) = "000110010" and IOCTL_ADDR(15 downto 12) = "0110" - else '1'; -IOCTL_CS_CONFIG_n <= '0' when IOCTL_ADDR(24 downto 16) = "000110010" and IOCTL_ADDR(15 downto 12) = "1000" - else '1'; -IOCTL_DIN <= X"00" & IOCTL_DIN_VRAM when IOCTL_CS_VRAM_n = '0' and IOCTL_RD = '1' - else - X"00" & IOCTL_DIN_GRAM when IOCTL_CS_GRAM_n = '0' and IOCTL_RD = '1' - else - X"00" & IOCTL_DIN_CGROM when IOCTL_CS_CGROM_n = '0' and IOCTL_RD = '1' - else - X"00" & IOCTL_DIN_CGRAM when IOCTL_CS_CGRAM_n = '0' and IOCTL_RD = '1' - else - IOCTL_DIN_STRAM_G when IOCTL_CS_STRAM_G_n = '0' and IOCTL_RD = '1' - else - IOCTL_DIN_STRAM_R when IOCTL_CS_STRAM_R_n = '0' and IOCTL_RD = '1' - else - IOCTL_DIN_STRAM_B when IOCTL_CS_STRAM_B_n = '0' and IOCTL_RD = '1' - else - IOCTL_DIN_MNURAM_G when IOCTL_CS_MNURAM_G_n = '0' and IOCTL_RD = '1' - else - IOCTL_DIN_MNURAM_R when IOCTL_CS_MNURAM_R_n = '0' and IOCTL_RD = '1' - else - IOCTL_DIN_MNURAM_B when IOCTL_CS_MNURAM_B_n = '0' and IOCTL_RD = '1' - else - IOCTL_DIN_CONFIG when IOCTL_CS_CONFIG_n = '0' and IOCTL_RD = '1' - else - (others=>'0'); -IOCTL_DIN_GRAM <= GRAM_DO_R when IOCTL_CS_GRAM_n = '0' and IOCTL_ADDR(15 downto 14) = "00" - else - GRAM_DO_G when IOCTL_CS_GRAM_n = '0' and IOCTL_ADDR(15 downto 14) = "01" - else - GRAM_DO_B when IOCTL_CS_GRAM_n = '0' and IOCTL_ADDR(15 downto 14) = "10" - else - GRAM_DO_GI when IOCTL_CS_GRAM_80B_n = '0' and IOCTL_ADDR(13) = '0' - else - GRAM_DO_GII when IOCTL_CS_GRAM_80B_n = '0' and IOCTL_ADDR(13) = '1' - else - (others=>'0'); - --- Work out the current video mode, which is used to look up the parameters for frame generation. --- -VIDEOMODE <= 0 when CONFIG(VGAMODE) = "11" and CONFIG(MZ_80B) = '1' and CONFIG_CHAR80 = '0' - else - 1 when CONFIG(VGAMODE) = "11" and CONFIG(MZ_80B) = '1' and CONFIG_CHAR80 = '1' - else - 2 when CONFIG(VGAMODE) = "11" and CONFIG(NORMAL) = '1' - else - 3 when CONFIG(VGAMODE) = "11" and CONFIG(NORMAL80) = '1' - else - 4 when CONFIG(VGAMODE) = "11" and CONFIG(COLOUR) = '1' and CONFIG(MZ700) = '1' - else - 5 when CONFIG(VGAMODE) = "11" and CONFIG(COLOUR80) = '1' and CONFIG(MZ700) = '1' - else - 6 when CONFIG(VGAMODE) = "11" and CONFIG(COLOUR) = '1' - else - 7 when CONFIG(VGAMODE) = "11" and CONFIG(COLOUR80) = '1' - else - 8 when CONFIG(VGAMODE) = "00" and CONFIG(MZ_80B) = '1' and CONFIG_CHAR80 = '0' - else - 10 when CONFIG(VGAMODE) = "00" and CONFIG(MZ_80B) = '1' and CONFIG_CHAR80 = '1' - else - 9 when CONFIG(VGAMODE) = "01" and CONFIG(MZ_80B) = '1' and CONFIG_CHAR80 = '0' - else - 11 when CONFIG(VGAMODE) = "01" and CONFIG(MZ_80B) = '1' and CONFIG_CHAR80 = '1' - else - 8 when CONFIG(VGAMODE) = "00" and CONFIG(NORMAL) = '1' - else - 9 when CONFIG(VGAMODE) = "01" and CONFIG(NORMAL) = '1' - else - 10 when CONFIG(VGAMODE) = "00" and CONFIG(NORMAL80) = '1' - else - 11 when CONFIG(VGAMODE) = "01" and CONFIG(NORMAL80) = '1' - else - 12 when CONFIG(VGAMODE) = "00" and CONFIG(COLOUR) = '1' and CONFIG(MZ700) = '1' - else - 13 when CONFIG(VGAMODE) = "01" and CONFIG(COLOUR) = '1' and CONFIG(MZ700) = '1' - else - 18 when CONFIG(VGAMODE) = "10" and CONFIG(COLOUR) = '1' and CONFIG(MZ700) = '1' - else - 14 when CONFIG(VGAMODE) = "00" and CONFIG(COLOUR80) = '1' and CONFIG(MZ700) = '1' - else - 15 when CONFIG(VGAMODE) = "01" and CONFIG(COLOUR80) = '1' and CONFIG(MZ700) = '1' - else - 19 when CONFIG(VGAMODE) = "10" and CONFIG(COLOUR80) = '1' and CONFIG(MZ700) = '1' - else - 12 when CONFIG(VGAMODE) = "00" and CONFIG(COLOUR) = '1' - else - 13 when CONFIG(VGAMODE) = "01" and CONFIG(COLOUR) = '1' - else - 18 when CONFIG(VGAMODE) = "10" and CONFIG(COLOUR) = '1' - else - 14 when CONFIG(VGAMODE) = "00" and CONFIG(COLOUR80) = '1' - else - 15 when CONFIG(VGAMODE) = "01" and CONFIG(COLOUR80) = '1' - else - 19 when CONFIG(VGAMODE) = "10" and CONFIG(COLOUR80) = '1' - else - 16 when CONFIG(VGAMODE) = "10" and CONFIG(NORMAL) = '1' - else - 17 when CONFIG(VGAMODE) = "10" and CONFIG(NORMAL80) = '1' - else - 2; - - -- - -- Video Output Signals - -- - VBLANK <= V_BLANKi; - HBLANK <= H_BLANKi; - VSYNC_n <= V_SYNC_ni; - HSYNC_n <= H_SYNC_ni; - ROUT <= (others => SR_R_DATA(7) or SR_MNU_R_DATA(7)) when H_BLANKi='0' or VGATE_n='1' - else - (others => '0'); - GOUT <= (others => SR_G_DATA(7) or SR_MNU_R_DATA(7)) when H_BLANKi='0' or VGATE_n='1' - else - (others => '0'); - BOUT <= (others => SR_B_DATA(7) or SR_MNU_R_DATA(7)) when H_BLANKi='0' or VGATE_n='1' - else - (others => '0'); - -end RTL;