6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun May 12, 2024 3:30 pm

All times are UTC




Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Wed Jan 26, 2022 5:18 pm 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
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
HardMon65-1.JPG [ 444.58 KiB | Viewed 868 times ]
Attachment:
HardMon65-2.JPG
HardMon65-2.JPG [ 440.11 KiB | Viewed 868 times ]
Attachment:
HardMon65-3.JPG
HardMon65-3.JPG [ 425.4 KiB | Viewed 868 times ]

HexDump mode.
Attachment:
HardMon65-4.JPG
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;


Last edited by Cray Ze on Fri Jan 28, 2022 12:27 am, edited 2 times in total.

Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 26, 2022 5:29 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10800
Location: England
How very unexpected - so the idea is that it reads a chunk of memory and disassembles what it finds? (As opposed to disassembling a trace of execution.)


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 26, 2022 5:38 pm 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
BigEd wrote:
How very unexpected - so the idea is that it reads a chunk of memory and disassembles what it finds? (As opposed to disassembling a trace of execution.)


Yes, in fact, there isn't even a CPU in my example. You could wire it up to monitor the address bus in a complete system to track access and follow along in real time.


Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 26, 2022 8:54 pm 
Offline

Joined: Tue Sep 03, 2002 12:58 pm
Posts: 298
That's pretty cool. It puts my 'debugger' to shame.

(On the left is a list of the addresses of the last few instructions. On the right is the current values of the user-visible registers. In binary. There's a button to execute the next instruction. It's been a lot better than nothing)


Attachments:
File comment: C640 'debugger'
IMG_0453.JPG
IMG_0453.JPG [ 123.27 KiB | Viewed 838 times ]
Top
 Profile  
Reply with quote  
PostPosted: Wed Jan 26, 2022 10:52 pm 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
Your debugger is keeping track of a lot of useful information though, and there's certainly nothing wrong with that.
I'm only disassembling memory at present, though will add some more bells and whistles when it's incorporated into a design with an actual CPU to keep track of.


Top
 Profile  
Reply with quote  
PostPosted: Fri Jan 28, 2022 12:20 am 
Offline

Joined: Sat May 02, 2015 6:59 pm
Posts: 134
I've added some comments to the source, renamed a couple signals/variables to better names, and done some general clean up.
I also found an optimization that saved 151 logic elements while making the code a little more clear.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: