Hi all.
It's been a while since I've posted anything here, I was sidetracked by a few *life hurdles*
One of the last FPGA projects I came up with was a 6502 disassembler written in VHDL, I thought it might be of interest to some members of the forum.
Features of note:
. Independent of host CPU
. Independent of host RAM
. Dynamic display (self modifying code and data changes show in real time)
. Disassembly and HexDump modes
. Small size
Currently just a proof of concept, I have it connected to a C64 ROM (and a PC font ROM for character output), though I plan to integrate it into a FPGA based 6502 system at a later date.
̶T̶h̶e̶r̶e̶ ̶a̶r̶e̶ ̶b̶a̶s̶i̶c̶a̶l̶l̶y̶ ̶n̶o̶ ̶c̶o̶m̶m̶e̶n̶t̶s̶ ̶i̶n̶ ̶t̶h̶e̶ ̶s̶o̶u̶r̶c̶e̶,̶ ̶I̶ ̶p̶l̶a̶n̶ ̶t̶o̶ ̶a̶d̶d̶r̶e̶s̶s̶ ̶t̶h̶i̶s̶ ̶s̶o̶o̶n̶.̶ * Source is now commented *
Currently only the 6502 is supported, though I'll add 65C02 support at a later date.
Disassembly of three random sections of the C64 BASIC ROM.
Attachment:
HardMon65-1.JPG [ 444.58 KiB | Viewed 868 times ]
Attachment:
HardMon65-2.JPG [ 440.11 KiB | Viewed 868 times ]
Attachment:
HardMon65-3.JPG [ 425.4 KiB | Viewed 868 times ]
HexDump mode.
Attachment:
HardMon65-4.JPG [ 474.71 KiB | Viewed 868 times ]
Source file:
Code:
--
-- Copyright (c) 2018-2022 Dylan Wakefield (Cray Ze Ape)
--
--
-- 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 <http://www.gnu.org/licenses/>.
--
-- ------------------------------------------
--
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity Test is
port(CLOCK_24 : in std_logic;
Vout: out unsigned(10 downto 0) -- rrr,ggg,bbb,hsync,vsync
);
end Test;
architecture Behavioral of Test is
type mnemonic_buffer_array is array(3 downto 0) of STD_LOGIC_VECTOR(7 downto 0);
signal mnemonic_buffer : mnemonic_buffer_array;
type address_text_array is array (3 downto 0) of std_logic_vector(7 downto 0);
signal address_text : address_text_array;
type line_text_array is array (39 downto 0) of std_logic_vector(7 downto 0);
signal line_text : line_text_array;
signal Pixel_Colour : unsigned(8 DOWNTO 0) := "000000000";
signal VGAout : unsigned(10 downto 0);
signal hcount : unsigned(10 downto 0):="00000000000";
signal vcount : unsigned(9 downto 0):="0000000000";
signal VGA : unsigned(8 downto 0):="000000000";
signal videoon, videov, videoh, hsync, vsync : std_ulogic:='0';
signal RST : std_ulogic:='0';
signal CLOCK_50 : std_ulogic;
signal inslookAddr : std_LOGIC_VECTOR(9 downto 0);
signal inslookData : std_LOGIC_VECTOR(7 downto 0);
signal ROMAddr : std_LOGIC_VECTOR(13 downto 0);
signal ROMData : std_LOGIC_VECTOR(7 downto 0);
signal charAddr : std_LOGIC_VECTOR(10 downto 0);
signal charData : std_LOGIC_VECTOR(7 downto 0);
signal CharX : unsigned (5 downto 0) := "000000";
signal CharY : unsigned (5 downto 0) := "000000";
signal Opp1 : std_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
signal Opp2 : std_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
signal Opp3 : std_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
signal Opp4 : std_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
signal Opp5 : std_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
signal Opp6 : std_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
signal Opp7 : std_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
signal Opp8 : std_LOGIC_VECTOR(7 DOWNTO 0) := "00000000";
begin
fontRom : work.CGAFontBold PORT MAP (
address => charAddr,
clock => CLOCK_50,
q => charData
);
inslookupRom : work.inslookup PORT MAP (
address => inslookAddr,
clock => CLOCK_50,
q => inslookData
);
C64ROM : work.C64ROM PORT MAP (
address => ROMAddr,
clock => CLOCK_50,
q => ROMData
);
vgapll : work.vgapll PORT MAP (
inclk0 => CLOCK_24,
c0 => CLOCK_50
);
hcounter: process (CLOCK_50, RST)
begin
if RST='1' then
hcount <= "0000000000";
elsif (rising_edge(CLOCK_50)) then
hcount <= hcount + 1;
if hcount=1039 then
hcount <= "00000000000";
end if;
end if;
end process;
vcounter: process (CLOCK_50, RST)
begin
if RST='1' then
vcount <= "0000000001";
elsif (rising_edge(CLOCK_50)) then
if hcount = 1039 then
vcount <= vcount + 1;
if vcount = 665 then
vcount <= "0000000000";
end if;
end if;
end if;
end process;
process (vcount)
begin
videov <= '1';
if vcount > 599 then
videov <= '0';
end if;
end process;
process (hcount)
begin
videoh <= '1';
if hcount > 799 then
videoh <= '0';
end if;
end process;
sync: process (CLOCK_50, RST)
begin
if RST='1' then
hsync <= '0';
vsync <= '0';
elsif (rising_edge(CLOCK_50)) then
hsync <= '1';
if (hcount <= 987 and hcount >= 855) then
hsync <= '0';
end if;
vsync <= '1';
if (vcount <= 645 and vcount >= 636) then
vsync <= '0';
end if;
end if;
end process;
DrawApp : PROCESS (CLOCK_50, RST)
VARIABLE pixelh : unsigned(10 DOWNTO 0) := "00000000000";
VARIABLE tttph : unsigned(10 DOWNTO 0) := "00000000000";
VARIABLE tttph2 : unsigned(10 DOWNTO 0) := "00000000000";
VARIABLE pixelv : unsigned(9 DOWNTO 0) := "0000000000";
VARIABLE Xchar : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Xchar2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Ychar : unsigned(6 DOWNTO 0) := "0000000";
VARIABLE address : unsigned(15 DOWNTO 0) := "0000000000000000";
VARIABLE addressrel : unsigned(15 DOWNTO 0) := "0000000000000000";
VARIABLE Address_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Address_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Address_ASCI_3 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Address_ASCI_4 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE RelAddress_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE RelAddress_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE RelAddress_ASCI_3 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE RelAddress_ASCI_4 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Opcode_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Opcode_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_1st_Byte_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_1st_Byte_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_2nd_Byte_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_2nd_Byte_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_3rd_Byte_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_3rd_Byte_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_4th_Byte_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_4th_Byte_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_5th_Byte_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_5th_Byte_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_6th_Byte_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_6th_Byte_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_7th_Byte_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_7th_Byte_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_8th_Byte_ASCI_1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Operand_8th_Byte_ASCI_2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE OpLen : unsigned(1 DOWNTO 0) := "00";
VARIABLE InsMode : unsigned(3 DOWNTO 0) := "0000";
VARIABLE DisplayMode : std_ulogic:='0';
VARIABLE Op1 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Op2 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Op3 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Op4 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Op5 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Op6 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Op7 : unsigned(7 DOWNTO 0) := "00000000";
VARIABLE Op8 : unsigned(7 DOWNTO 0) := "00000000";
BEGIN
IF (rising_edge(CLOCK_50)) THEN
pixelv := (vcount - 100)/2;
pixelh := (hcount - 10)/2;
Ychar := pixelv (9 DOWNTO 3);
tttph := (hcount - 6)/2; --kludge
tttph2 := (hcount - 8)/2; --kludge
--Pixel_Colour <= "111111111";
DisplayMode := '0';-- '0'=disassembly '1'=HexDump pixelv (6) for test (synth resource count)
IF vcount = "000000100" THEN
address := x"AD1E";--:= x"AD1E"; --x"A3B8";
END IF;
---------------------------------------------------------------------------------
-- Read 8 bytes from memory every text line (address increment is done elsewhere)
-- This will need to be adapted to suit a live system. A000 is start of ROM in
-- my proof of concept example and should be 0000 (removed) in a live system with
-- access to all of memory
---------------------------------------------------------------------------------
IF vcount(3 DOWNTO 0) = "0100" THEN
IF hcount = "0000000001" THEN
ROMAddr <= std_logic_vector(address - x"A000" + (hcount - 1))(13 DOWNTO 0);
END IF;
IF hcount = "00000000010" THEN
ROMAddr <= std_logic_vector(address - x"A000" + (hcount - 1))(13 DOWNTO 0);
END IF;
IF hcount = "00000000011" THEN
ROMAddr <= std_logic_vector(address - x"A000" + (hcount - 1))(13 DOWNTO 0);
Opp1 <= ROMData;
END IF;
IF hcount = "00000000100" THEN
ROMAddr <= std_logic_vector(address - x"A000" + (hcount - 1))(13 DOWNTO 0);
Opp2 <= ROMData;
END IF;
IF hcount = "00000000101" THEN
ROMAddr <= std_logic_vector(address - x"A000" + (hcount - 1))(13 DOWNTO 0);
Opp3 <= ROMData;
END IF;
IF hcount = "00000000110" THEN
ROMAddr <= std_logic_vector(address - x"A000" + (hcount - 1))(13 DOWNTO 0);
Opp4 <= ROMData;
END IF;
IF hcount = "00000000111" THEN
ROMAddr <= std_logic_vector(address - x"A000" + (hcount - 1))(13 DOWNTO 0);
Opp5 <= ROMData;
END IF;
IF hcount = "00000001000" THEN
ROMAddr <= std_logic_vector(address - x"A000" + (hcount - 1))(13 DOWNTO 0);
Opp6 <= ROMData;
END IF;
IF hcount = "00000001001" THEN
Opp7 <= ROMData;
END IF;
IF hcount = "00000001010" THEN
Opp8 <= ROMData;
END IF;
END IF;
-----------------------------------------------------------------
-- Type conversion from std_logic_vector to unsigned, we get this
-- for free and it makes the code below much simpler to read
-----------------------------------------------------------------
Op1 := unsigned(Opp1);
Op2 := unsigned(Opp2);
Op3 := unsigned(Opp3);
Op4 := unsigned(Opp4);
Op5 := unsigned(Opp5);
Op6 := unsigned(Opp6);
Op7 := unsigned(Opp7);
Op8 := unsigned(Opp8);
-----------------------------------------------------------------
addressrel := address + 2;
IF Op2(7) = '1' THEN
addressrel (7 DOWNTO 0) := addressrel (7 DOWNTO 0) + Op2;
ELSE addressrel := addressrel + Op2;
END IF;
IF pixelv >= 0 AND pixelv <= 199 AND pixelh >= 0 AND pixelh <= 320 THEN -- kludge - should be 319, but using 320 until after screen position changes (stops right hand char bleed in mem display).
Pixel_Colour <= "000000111";
Ychar := pixelv (9 DOWNTO 3);
Xchar2 := tttph (10 DOWNTO 3);
Xchar := tttph2 (10 DOWNTO 3);
IF Xchar >= 1 AND Xchar <= 40 THEN -- If we are within the 40 char text line
inslookAddr <= std_logic_vector(Op1) & std_logic_vector((Xchar(1 DOWNTO 0)) - 16); -- look up the instruction information based on opcode
IF Xchar = "00000011" THEN
OpLen := unsigned(inslookData (1 DOWNTO 0)); -- Get instruction length
InsMode := unsigned(inslookData (7 DOWNTO 4)); -- Get instruction mode (this is more for text formating than the actual instruction mode)
IF hcount (3 DOWNTO 0) = "0100" AND vcount (3 DOWNTO 0) = "0011" THEN
IF DisplayMode = '0' THEN
address := address + OpLen; -- Increment address to next opcode ( disassembly mode )
ELSIF DisplayMode = '1' THEN
address := address + 8; -- Increment address by 8 ( HexDump mode)
END IF;
END IF;
END IF;
---------------------------------------------------------
-- Convert address to ASCII
---------------------------------------------------------
Address_ASCI_1 := "0011" & address (15 DOWNTO 12);
IF address (15 DOWNTO 12) > 9 THEN
Address_ASCI_1 := "0100" & (address (15 DOWNTO 12) - 9);
END IF;
Address_ASCI_2 := "0011" & address (11 DOWNTO 8);
IF address (11 DOWNTO 8) > 9 THEN
Address_ASCI_2 := "0100" & (address (11 DOWNTO 8) - 9);
END IF;
Address_ASCI_3 := "0011" & address (7 DOWNTO 4);
IF address (7 DOWNTO 4) > 9 THEN
Address_ASCI_3 := "0100" & (address (7 DOWNTO 4) - 9);
END IF;
Address_ASCI_4 := "0011" & address (3 DOWNTO 0);
IF address (3 DOWNTO 0) > 9 THEN
Address_ASCI_4 := "0100" & (address (3 DOWNTO 0) - 9);
END IF;
---------------------------------------------------------
-- Convert Opcode to ASCII
---------------------------------------------------------
Opcode_ASCI_1 := "0011" & Op1 (7 DOWNTO 4);
IF Op1 (7 DOWNTO 4) > 9 THEN
Opcode_ASCI_1 := "0100" & (Op1 (7 DOWNTO 4) - 9);
END IF;
Opcode_ASCI_2 := "0011" & Op1 (3 DOWNTO 0);
IF Op1 (3 DOWNTO 0) > 9 THEN
Opcode_ASCI_2 := "0100" & (Op1 (3 DOWNTO 0) - 9);
END IF;
----------------------------------------------------------------------------------------------
-- Convert 1st byte of operand to ASCII ( or space if none, when in disassembly mode )
----------------------------------------------------------------------------------------------
IF DisplayMode = '0' THEN
Operand_1st_Byte_ASCI_1 := "00100000"; -- Space
Operand_1st_Byte_ASCI_2 := "00100000"; -- Space
END IF;
IF OpLen = 2 OR OpLen = 3 OR DisplayMode = '1' THEN
Operand_1st_Byte_ASCI_1 := "0011" & Op2 (7 DOWNTO 4);
IF Op2 (7 DOWNTO 4) > 9 THEN
Operand_1st_Byte_ASCI_1 := "0100" & (Op2 (7 DOWNTO 4) - 9);
END IF;
Operand_1st_Byte_ASCI_2 := "0011" & Op2 (3 DOWNTO 0);
IF Op2 (3 DOWNTO 0) > 9 THEN
Operand_1st_Byte_ASCI_2 := "0100" & (Op2 (3 DOWNTO 0) - 9);
END IF;
END IF;
----------------------------------------------------------------------------------------------
-- Convert 2nd byte of operand to ASCII ( or space if none, when in disassembly mode )
----------------------------------------------------------------------------------------------
IF DisplayMode = '0' THEN
Operand_2nd_Byte_ASCI_1 := "00100000"; -- Space
Operand_2nd_Byte_ASCI_2 := "00100000"; -- Space
END IF;
IF OpLen = 3 OR DisplayMode = '1' THEN
Operand_2nd_Byte_ASCI_1 := "0011" & Op3 (7 DOWNTO 4);
IF Op3 (7 DOWNTO 4) > 9 THEN
Operand_2nd_Byte_ASCI_1 := "0100" & (Op3 (7 DOWNTO 4) - 9);
END IF;
Operand_2nd_Byte_ASCI_2 := "0011" & Op3 (3 DOWNTO 0);
IF Op3 (3 DOWNTO 0) > 9 THEN
Operand_2nd_Byte_ASCI_2 := "0100" & (Op3 (3 DOWNTO 0) - 9);
END IF;
END IF;
---------------------------------------------------------------------
-- Convert 5 more values to ASCII for HexDump mode
---------------------------------------------------------------------
Operand_3rd_Byte_ASCI_1 := "0011" & Op4 (7 DOWNTO 4);
IF Op4 (7 DOWNTO 4) > 9 THEN
Operand_3rd_Byte_ASCI_1 := "0100" & (Op4 (7 DOWNTO 4) - 9);
END IF;
Operand_3rd_Byte_ASCI_2 := "0011" & Op4 (3 DOWNTO 0);
IF Op4 (3 DOWNTO 0) > 9 THEN
Operand_3rd_Byte_ASCI_2 := "0100" & (Op4 (3 DOWNTO 0) - 9);
END IF;
Operand_4th_Byte_ASCI_1 := "0011" & Op5 (7 DOWNTO 4);
IF Op5 (7 DOWNTO 4) > 9 THEN
Operand_4th_Byte_ASCI_1 := "0100" & (Op5 (7 DOWNTO 4) - 9);
END IF;
Operand_4th_Byte_ASCI_2 := "0011" & Op5 (3 DOWNTO 0);
IF Op5 (3 DOWNTO 0) > 9 THEN
Operand_4th_Byte_ASCI_2 := "0100" & (Op5 (3 DOWNTO 0) - 9);
END IF;
Operand_5th_Byte_ASCI_1 := "0011" & Op6 (7 DOWNTO 4);
IF Op6 (7 DOWNTO 4) > 9 THEN
Operand_5th_Byte_ASCI_1 := "0100" & (Op6 (7 DOWNTO 4) - 9);
END IF;
Operand_5th_Byte_ASCI_2 := "0011" & Op6 (3 DOWNTO 0);
IF Op6 (3 DOWNTO 0) > 9 THEN
Operand_5th_Byte_ASCI_2 := "0100" & (Op6 (3 DOWNTO 0) - 9);
END IF;
Operand_6th_Byte_ASCI_1 := "0011" & Op7 (7 DOWNTO 4);
IF Op7 (7 DOWNTO 4) > 9 THEN
Operand_6th_Byte_ASCI_1 := "0100" & (Op7 (7 DOWNTO 4) - 9);
END IF;
Operand_6th_Byte_ASCI_2 := "0011" & Op7 (3 DOWNTO 0);
IF Op7 (3 DOWNTO 0) > 9 THEN
Operand_6th_Byte_ASCI_2 := "0100" & (Op7 (3 DOWNTO 0) - 9);
END IF;
Operand_7th_Byte_ASCI_1 := "0011" & Op8 (7 DOWNTO 4);
IF Op8 (7 DOWNTO 4) > 9 THEN
Operand_7th_Byte_ASCI_1 := "0100" & (Op8 (7 DOWNTO 4) - 9);
END IF;
Operand_7th_Byte_ASCI_2 := "0011" & Op8 (3 DOWNTO 0);
IF Op8 (3 DOWNTO 0) > 9 THEN
Operand_7th_Byte_ASCI_2 := "0100" & (Op8 (3 DOWNTO 0) - 9);
END IF;
---------------------------------------------------------
-- Convert relative address to ASCII
---------------------------------------------------------
RelAddress_ASCI_1 := "0011" & addressrel (15 DOWNTO 12);
IF addressrel (15 DOWNTO 12) > 9 THEN
RelAddress_ASCI_1 := "0100" & (addressrel (15 DOWNTO 12) - 9);
END IF;
RelAddress_ASCI_2 := "0011" & addressrel (11 DOWNTO 8);
IF addressrel (11 DOWNTO 8) > 9 THEN
RelAddress_ASCI_2 := "0100" & (addressrel (11 DOWNTO 8) - 9);
END IF;
RelAddress_ASCI_3 := "0011" & addressrel (7 DOWNTO 4);
IF addressrel (7 DOWNTO 4) > 9 THEN
RelAddress_ASCI_3 := "0100" & (addressrel (7 DOWNTO 4) - 9);
END IF;
RelAddress_ASCI_4 := "0011" & addressrel (3 DOWNTO 0);
IF addressrel (3 DOWNTO 0) > 9 THEN
RelAddress_ASCI_4 := "0100" & (addressrel (3 DOWNTO 0) - 9);
END IF;
------------------------------------------------------------------------------------
-- Generate 40 character line of output text in line_text_array
------------------------------------------------------------------------------------
IF InsMode < 10 THEN
line_text (20) <= "00101000"; -- (
line_text (21) <= "00100100"; -- $
line_text (22) <= std_logic_vector(Operand_1st_Byte_ASCI_1); -- Indirect value byte 1 (X or Y is determined by InsMode 8 or 9 - see below)
line_text (23) <= std_logic_vector(Operand_1st_Byte_ASCI_2); -- Indirect value byte 2 (X or Y is determined by InsMode 8 or 9 - see below)
END IF;
IF InsMode < 8 THEN
line_text (20) <= "00100100"; -- $
line_text (21) <= std_logic_vector(Operand_2nd_Byte_ASCI_1); -- Address byte 1
line_text (22) <= std_logic_vector(Operand_2nd_Byte_ASCI_2); -- Address byte 2
line_text (23) <= std_logic_vector(Operand_1st_Byte_ASCI_1); -- Address byte 3
line_text (24) <= std_logic_vector(Operand_1st_Byte_ASCI_2); -- Address byte 4
END IF;
IF InsMode = 8 THEN
line_text (24) <= "00101100"; -- ,
line_text (25) <= "01011000"; -- X
line_text (26) <= "00101001"; -- )
END IF;
IF InsMode = 9 THEN
line_text (24) <= "00101001"; -- )
line_text (25) <= "00101100"; -- ,
line_text (26) <= "01011001"; -- Y
END IF;
IF InsMode = 6 OR InsMode = 7 OR InsMode = 9 THEN
line_text (25) <= "00101100"; -- ,
END IF;
IF InsMode = 6 THEN
line_text (26) <= "01011000"; -- X
END IF;
IF InsMode = 7 THEN
line_text (26) <= "01011001"; -- Y
END IF;
IF InsMode < 5 THEN
line_text (20) <= "00100100"; -- $
line_text (21) <= std_logic_vector(Operand_1st_Byte_ASCI_1); -- Zero Page Address byte 1
line_text (22) <= std_logic_vector(Operand_1st_Byte_ASCI_2); -- Zero Page Address byte 2
line_text (23) <= "00101100"; -- ,
line_text (24) <= "01011000"; -- X
END IF;
IF InsMode = 5 THEN
line_text (25) <= "00100000"; -- Space
line_text (26) <= "00100000"; -- Space
END IF;
IF InsMode = 3 THEN
line_text (24) <= "01011000"; -- X
line_text (25) <= "00100000"; -- Space
line_text (26) <= "00100000"; -- Space
END IF;
IF InsMode = 4 THEN
line_text (24) <= "01011001"; -- Y
line_text (25) <= "00100000"; -- Space
line_text (26) <= "00100000"; -- Space
END IF;
IF InsMode = 2 THEN
line_text (23) <= "00100000"; -- Space
line_text (24) <= "00100000"; -- Space
line_text (25) <= "00100000"; -- Space
line_text (26) <= "00100000"; -- Space
END IF;
IF InsMode = 1 THEN
line_text (20) <= "00100011"; -- #
line_text (21) <= "00100100"; -- $
line_text (22) <= std_logic_vector(Operand_1st_Byte_ASCI_1); -- Immediate value byte 1
line_text (23) <= std_logic_vector(Operand_1st_Byte_ASCI_2); -- Immediate value byte 2
line_text (24) <= "00100000"; -- Space
line_text (25) <= "00100000"; -- Space
line_text (26) <= "00100000"; -- Space
END IF;
IF InsMode = 0 THEN
line_text (20) <= "00100000"; -- Space
line_text (21) <= "00100000"; -- Space
line_text (22) <= "00100000"; -- Space
line_text (23) <= "00100000"; -- Space
line_text (24) <= "00100000"; -- Space
line_text (25) <= "00100000"; -- Space
line_text (26) <= "00100000"; -- Space
END IF;
IF InsMode = 10 THEN
line_text (20) <= "00100100"; -- $
line_text (21) <= std_logic_vector(RelAddress_ASCI_1); -- Address byte 1
line_text (22) <= std_logic_vector(RelAddress_ASCI_2); -- Address byte 2
line_text (23) <= std_logic_vector(RelAddress_ASCI_3); -- Address byte 3
line_text (24) <= std_logic_vector(RelAddress_ASCI_4); -- Address byte 4
line_text (25) <= "00100000"; -- Space
line_text (26) <= "00100000"; -- Space
END IF;
IF InsMode = 11 THEN
line_text (20) <= "00101000"; -- (
line_text (21) <= "00100100"; -- $
line_text (22) <= std_logic_vector(Operand_2nd_Byte_ASCI_1); -- Address byte 1
line_text (23) <= std_logic_vector(Operand_2nd_Byte_ASCI_2); -- Address byte 2
line_text (24) <= std_logic_vector(Operand_1st_Byte_ASCI_1); -- Address byte 3
line_text (25) <= std_logic_vector(Operand_1st_Byte_ASCI_2); -- Address byte 4
line_text (26) <= "00101001"; -- )
END IF;
IF InsMode = 12 THEN
line_text (20) <= "01000001"; -- A
line_text (21) <= "00100000"; -- Space
line_text (22) <= "00100000"; -- Space
line_text (23) <= "00100000"; -- Space
line_text (24) <= "00100000"; -- Space
line_text (25) <= "00100000"; -- Space
line_text (26) <= "00100000"; -- Space
END IF;
line_text (0) <= "00101110"; -- .
line_text (1) <= "00101100"; -- ,
line_text (2) <= std_logic_vector(Address_ASCI_1); -- 1st char of Address
line_text (3) <= std_logic_vector(Address_ASCI_2); -- 2nd char of Address
line_text (4) <= std_logic_vector(Address_ASCI_3); -- 3rd char of Address
line_text (5) <= std_logic_vector(Address_ASCI_4); -- 4th char of Address
line_text (6) <= "00100000"; -- Space
line_text (7) <= std_logic_vector(Opcode_ASCI_1); -- 1st char of Opcode ( 1st char of 1st byte in HexDump mode )
line_text (8) <= std_logic_vector(Opcode_ASCI_2); -- 2nd char of Opcode ( 2nd char of 1st byte in HexDump mode )
line_text (9) <= "00100000"; -- Space
line_text (10) <= std_logic_vector(Operand_1st_Byte_ASCI_1); -- 1st char 1st Operand ( 1st char of 2nd byte in HexDump mode )
line_text (11) <= std_logic_vector(Operand_1st_Byte_ASCI_2); -- 2nd char 1st Operand ( 2nd char of 2nd byte in HexDump mode )
line_text (12) <= "00100000"; -- Space
line_text (13) <= std_logic_vector(Operand_2nd_Byte_ASCI_1); -- 1st char 2nd Operand ( 1st char of 3rd byte in HexDump mode )
line_text (14) <= std_logic_vector(Operand_2nd_Byte_ASCI_2); -- 2nd char 2nd Operand ( 2nd char of 3rd byte in HexDump mode )
line_text (15) <= "00100000"; -- Space
line_text (to_integer(Xchar2)) <= inslookData; -- 3 char instruction mnemonic
line_text (19) <= "00100000"; -- Space
line_text (27) <= "00100000"; -- Space
line_text (28) <= "00100000"; -- Space
line_text (29) <= "00100000"; -- Space
line_text (30) <= "00100000"; -- Space
line_text (31) <= "00100000"; -- Space
line_text (32) <= "00100000"; -- Space
line_text (33) <= "00100000"; -- Space
line_text (34) <= "00100000"; -- Space
line_text (35) <= "00100000"; -- Space
line_text (36) <= "00100000"; -- Space
line_text (37) <= "00100000"; -- Space
line_text (38) <= "00100000"; -- Space
line_text (39) <= "00100000"; -- Space
IF DisplayMode = '1' THEN
line_text (1) <= "00111010"; -- :
line_text (15) <= "00100000"; -- Space
line_text (16) <= std_logic_vector(Operand_3rd_Byte_ASCI_1); -- 1st char of 4th byte in HexDump mode
line_text (17) <= std_logic_vector(Operand_3rd_Byte_ASCI_2); -- 2nd char of 4th byte in HexDump mode
line_text (18) <= "00100000"; -- Space
line_text (19) <= std_logic_vector(Operand_4th_Byte_ASCI_1); -- 1st char of 5th byte in HexDump mode
line_text (20) <= std_logic_vector(Operand_4th_Byte_ASCI_2); -- 2nd char of 5th byte in HexDump mode
line_text (21) <= "00100000"; -- Space
line_text (22) <= std_logic_vector(Operand_5th_Byte_ASCI_1); -- 1st char of 6th byte in HexDump mode
line_text (23) <= std_logic_vector(Operand_5th_Byte_ASCI_2); -- 2nd char of 6th byte in HexDump mode
line_text (24) <= "00100000"; -- Space
line_text (25) <= std_logic_vector(Operand_6th_Byte_ASCI_1); -- 1st char of 7th byte in HexDump mode
line_text (26) <= std_logic_vector(Operand_6th_Byte_ASCI_2); -- 2nd char of 7th byte in HexDump mode
line_text (27) <= "00100000"; -- Space
line_text (28) <= std_logic_vector(Operand_7th_Byte_ASCI_1); -- 1st char of 8th byte in HexDump mode
line_text (29) <= std_logic_vector(Operand_7th_Byte_ASCI_2); -- 2nd char of 8th byte in HexDump mode
line_text (30) <= "00100000"; -- Space
line_text (31) <= std_logic_vector(Op1); -- | 8 bytes of ASCII representation to right of hex values
line_text (32) <= std_logic_vector(Op2); -- |
line_text (33) <= std_logic_vector(Op3); -- |
line_text (34) <= std_logic_vector(Op4); -- |
line_text (35) <= std_logic_vector(Op5); -- |
line_text (36) <= std_logic_vector(Op6); -- |
line_text (37) <= std_logic_vector(Op7); -- |
line_text (38) <= std_logic_vector(Op8); -- |
line_text (39) <= "00100000"; -- Space
END IF;
---------------------------------------------------------------------
-- Display 40 character line from line_text_array
---------------------------------------------------------------------
charAddr <= line_text(to_integer((Xchar) - 1)) & std_logic_vector(pixelv(2 DOWNTO 0));
IF charData(to_integer(NOT pixelh(2 DOWNTO 0))) = '1' THEN
Pixel_Colour <= "111111111";
END IF;
----------------------------------------------------------------------
END IF;
END IF;
-- Draw border
IF vcount <= 10 OR vcount >= 590 OR
hcount <= 10 OR hcount >= 790 THEN
Pixel_Colour <= "111111111";
END IF;
END IF;
END PROCESS;
videoon <= videoh and videov;
VGA <= Pixel_Colour;
Vout(10 downto 2) <= VGA and videoon&videoon&videoon&videoon&videoon&videoon&videoon&videoon&videoon;
Vout(1 downto 0) <= hsync & vsync;
end Behavioral;
A small lookup ROM is also used, and can be created with the following .mif file.
Code:
-- http://srecord.sourceforge.net/
--
-- Generated automatically by srec_cat -o --mif
--
DEPTH = 1024;
WIDTH = 8;
ADDRESS_RADIX = HEX;
DATA_RADIX = HEX;
CONTENT BEGIN
0000: 42 52 4B 01 4F 52 41 82 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 4F 52 41 22;
0018: 41 53 4C 22 3F 3F 3F 01 50 48 50 01 4F 52 41 12 41 53 4C C1 3F 3F 3F 01;
0030: 3F 3F 3F 01 4F 52 41 53 41 53 4C 53 3F 3F 3F 01 42 50 4C A2 4F 52 41 92;
0048: 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 4F 52 41 32 41 53 4C 32 3F 3F 3F 01;
0060: 43 4C 43 01 4F 52 41 73 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 4F 52 41 63;
0078: 41 53 4C 63 3F 3F 3F 01 4A 53 52 53 41 4E 44 82 3F 3F 3F 01 3F 3F 3F 01;
0090: 42 49 54 22 41 4E 44 22 52 4F 4C 22 3F 3F 3F 01 50 4C 50 01 41 4E 44 12;
00A8: 52 4F 4C C1 3F 3F 3F 01 42 49 54 53 41 4E 44 53 52 4F 4C 53 3F 3F 3F 01;
00C0: 42 4D 49 A2 41 4E 44 92 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 41 4E 44 32;
00D8: 52 4F 4C 32 3F 3F 3F 01 53 45 43 01 41 4E 44 73 3F 3F 3F 01 3F 3F 3F 01;
00F0: 3F 3F 3F 01 41 4E 44 63 52 4F 4C 63 3F 3F 3F 01 52 54 49 01 45 4F 52 82;
0108: 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 45 4F 52 22 4C 53 52 22 3F 3F 3F 01;
0120: 50 48 41 01 45 4F 52 12 4C 53 52 C1 3F 3F 3F 01 4A 4D 50 53 45 4F 52 53;
0138: 4C 53 52 53 3F 3F 3F 01 42 56 43 A2 45 4F 52 92 3F 3F 3F 01 3F 3F 3F 01;
0150: 3F 3F 3F 01 45 4F 52 32 4C 53 52 32 3F 3F 3F 01 43 4C 49 01 45 4F 52 73;
0168: 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 45 4F 52 63 4C 53 52 63 3F 3F 3F 01;
0180: 52 54 53 01 41 44 43 82 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 41 44 43 22;
0198: 52 4F 52 22 3F 3F 3F 01 50 4C 41 01 41 44 43 12 52 4F 52 C1 3F 3F 3F 01;
01B0: 4A 4D 50 B3 41 44 43 53 52 4F 52 53 3F 3F 3F 01 42 56 53 A2 41 44 43 92;
01C8: 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 41 44 43 32 52 4F 52 32 3F 3F 3F 01;
01E0: 53 45 49 01 41 44 43 73 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 41 44 43 63;
01F8: 52 4F 52 63 3F 3F 3F 01 3F 3F 3F 01 53 54 41 82 3F 3F 3F 01 3F 3F 3F 01;
0210: 53 54 59 22 53 54 41 22 53 54 58 22 3F 3F 3F 01 44 45 59 01 3F 3F 3F 01;
0228: 54 58 41 01 3F 3F 3F 01 53 54 59 53 53 54 41 53 53 54 58 53 3F 3F 3F 01;
0240: 42 43 43 A2 53 54 41 92 3F 3F 3F 01 3F 3F 3F 01 53 54 59 32 53 54 41 32;
0258: 53 54 58 42 3F 3F 3F 01 54 59 41 01 53 54 41 73 54 58 53 01 3F 3F 3F 01;
0270: 3F 3F 3F 01 53 54 41 63 3F 3F 3F 01 3F 3F 3F 01 4C 44 59 12 4C 44 41 82;
0288: 4C 44 58 12 3F 3F 3F 01 4C 44 59 22 4C 44 41 22 4C 44 58 22 3F 3F 3F 01;
02A0: 54 41 59 01 4C 44 41 12 54 41 58 01 3F 3F 3F 01 4C 44 59 53 4C 44 41 53;
02B8: 4C 44 58 53 3F 3F 3F 01 42 43 53 A2 4C 44 41 92 3F 3F 3F 01 3F 3F 3F 01;
02D0: 4C 44 59 32 4C 44 41 32 4C 44 58 42 3F 3F 3F 01 43 4C 56 01 4C 44 41 73;
02E8: 54 53 58 01 3F 3F 3F 01 4C 44 59 63 4C 44 41 63 4C 44 58 73 3F 3F 3F 01;
0300: 43 50 59 12 43 4D 50 82 3F 3F 3F 01 3F 3F 3F 01 43 50 59 22 43 4D 50 22;
0318: 44 45 43 22 3F 3F 3F 01 49 4E 59 01 43 4D 50 12 44 45 58 01 3F 3F 3F 01;
0330: 43 50 59 53 43 4D 50 53 44 45 43 53 3F 3F 3F 01 42 4E 45 A2 43 4D 50 92;
0348: 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 43 4D 50 32 44 45 43 32 3F 3F 3F 01;
0360: 43 4C 44 01 43 4D 50 73 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 43 4D 50 63;
0378: 44 45 43 63 3F 3F 3F 01 43 50 58 12 53 42 43 82 3F 3F 3F 01 3F 3F 3F 01;
0390: 43 50 58 22 53 42 43 22 49 4E 43 22 3F 3F 3F 01 49 4E 58 01 53 42 43 12;
03A8: 4E 4F 50 01 3F 3F 3F 01 43 50 58 53 53 42 43 53 49 4E 43 53 3F 3F 3F 01;
03C0: 42 45 51 A2 53 42 43 92 3F 3F 3F 01 3F 3F 3F 01 3F 3F 3F 01 53 42 43 32;
03D8: 49 4E 43 32 3F 3F 3F 01 53 45 44 01 53 42 43 73 3F 3F 3F 01 3F 3F 3F 01;
03F0: 3F 3F 3F 01 53 42 43 63 49 4E 43 63 3F 3F 3F 01;
END;