diff --git a/AtomCpuMon.xise b/AtomCpuMon.xise index 002c5f6..4ec1fa1 100644 --- a/AtomCpuMon.xise +++ b/AtomCpuMon.xise @@ -20,242 +20,242 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/firmware/AtomBusMon.c b/firmware/AtomBusMon.c index a0b5bbe..f82bb31 100644 --- a/firmware/AtomBusMon.c +++ b/firmware/AtomBusMon.c @@ -6,28 +6,32 @@ #include "hd44780.h" #include "status.h" -#define CTRL_PORT PORTB -#define CTRL_DDR DDRB -#define CTRL_DIN PINB +#ifdef EMBEDDED_6502 +#include "disassembler.h" +#endif -#define MUXSEL_PORT PORTD +#define CTRL_PORT PORTB +#define CTRL_DDR DDRB +#define CTRL_DIN PINB -#define STATUS_PORT PORTD -#define STATUS_DDR DDRD -#define STATUS_DIN PIND +#define MUXSEL_PORT PORTD -#define MUX_PORT PORTE -#define MUX_DDR DDRE -#define MUX_DIN PINE +#define STATUS_PORT PORTD +#define STATUS_DDR DDRD +#define STATUS_DIN PIND -#define OFFSET_IAL 0 -#define OFFSET_IAH 1 -#define OFFSET_BW_IAL 2 -#define OFFSET_BW_IAH 3 -#define OFFSET_BW_BAL 4 -#define OFFSET_BW_BAH 5 -#define OFFSET_BW_M 6 +#define MUX_PORT PORTE +#define MUX_DDR DDRE +#define MUX_DIN PINE +#define OFFSET_IAL 0 +#define OFFSET_IAH 1 +#define OFFSET_BW_IAL 2 +#define OFFSET_BW_IAH 3 +#define OFFSET_BW_BAL 4 +#define OFFSET_BW_BAH 5 +#define OFFSET_BW_M 6 +#define OFFSET_DATA 7 #define OFFSET_REG_A 8 #define OFFSET_REG_X 9 #define OFFSET_REG_Y 10 @@ -46,11 +50,14 @@ #define CMD_SINGLE_ENABLE 0x00 #define CMD_BRKPT_ENABLE 0x02 -#define CMD_LOAD_REG 0x04 +#define CMD_LOAD_BRKPT 0x04 #define CMD_RESET 0x06 #define CMD_STEP 0x08 #define CMD_WATCH_READ 0x09 #define CMD_FIFO_RST 0x0A +#define CMD_LOAD_MEM 0x0C +#define CMD_RD_MEM 0x0E +#define CMD_WR_MEM 0x0F // Control bits #define CMD_MASK 0x1F @@ -109,7 +116,7 @@ char *triggerStrings[NUM_TRIGGERS] = { #define VERSION "0.23" #ifdef EMBEDDED_6502 -#define NUM_CMDS 20 +#define NUM_CMDS 23 #else #define NUM_CMDS 19 #endif @@ -122,6 +129,8 @@ int single; long trace; long instructions = 1; +unsigned int memAddr = 0; + unsigned int breakpoints[MAXBKPTS] = { 0, 0, @@ -160,6 +169,9 @@ char *cmdStrings[NUM_CMDS] = { "help", #ifdef EMBEDDED_6502 "regs", + "mem", + "dis", + "write", #endif "reset", "step", @@ -340,7 +352,7 @@ int logDetails() { int lookupBreakpoint(char *params) { int i; - int n = 0; + int n = -1; sscanf(params, "%x", &n); // First, look assume n is an address, and try to map to an index for (i = 0; i < numbkpts; i++) { @@ -357,6 +369,37 @@ int lookupBreakpoint(char *params) { } +#ifdef EMBEDDED_6502 +unsigned int readMem(unsigned int addr) { + int i; + for (i = 0; i <= 15; i++) { + hwCmd(CMD_LOAD_MEM, addr & 1); + addr >>= 1; + } + hwCmd(CMD_RD_MEM, 0); + Delay_us(10); + return hwRead8(OFFSET_DATA); +} + +void writeMem(unsigned int addr, unsigned int data) { + int i; + for (i = 0; i <= 7; i++) { + hwCmd(CMD_LOAD_MEM, data & 1); + data >>= 1; + } + for (i = 0; i <= 15; i++) { + hwCmd(CMD_LOAD_MEM, addr & 1); + addr >>= 1; + } + hwCmd(CMD_WR_MEM, 0); +} + +unsigned int disMem(unsigned int addr) { + return disassemble(addr, readMem(addr), readMem(addr + 1), readMem(addr + 2)); +} + +#endif + /******************************************* * Commands *******************************************/ @@ -368,20 +411,22 @@ void doCmdHelp(char *params) { for (i = 0; i < NUM_CMDS; i++) { log0(" %s\n", cmdStrings[i]); } - log0("Trigger Codes:\n"); - for (i = 0; i < NUM_TRIGGERS; i++) { - log0(" %X = %s\n", i, triggerStrings[i]); - } } void doCmdAddr() { - unsigned int i_addr = hwRead16(OFFSET_IAL); + memAddr = hwRead16(OFFSET_IAL); // Update the LCD display #ifdef LCD - lcdAddr(i_addr); + lcdAddr(memAddr); #endif // Update the serial console - log0("%04X\n", i_addr); +#ifdef EMBEDDED_6502 + //log0("%04X\n", i_addr); + disMem(memAddr); +#else + log0("%04X\n", memAddr); +#endif + return; } void doCmdStep(char *params) { @@ -430,6 +475,38 @@ void doCmdRegs(char *params) { log0("PC=%04x; ", hwRead16(OFFSET_REG_PCL)); log0("\n"); } + +void doCmdMem(char *params) { + int i; + sscanf(params, "%x", &memAddr); + for (i = 0; i < 0x100; i++) { + if ((i & 15) == 0) { + log0("%04X ", memAddr + i); + } + log0("%02X ", readMem(memAddr + i)); + if ((i & 15) == 15) { + log0("\n"); + } + } + memAddr += 0x100; +} + +void doCmdDis(char *params) { + int i; + sscanf(params, "%x", &memAddr); + for (i = 0; i < 10; i++) { + memAddr = disMem(memAddr); + } +} + +void doCmdWrite(char *params) { + unsigned int addr; + unsigned int data; + sscanf(params, "%x %x", &addr, &data); + log0("Wr: %04X = %X\n", addr, data); + writeMem(addr, data); +} + #endif void doCmdTrace(char *params) { @@ -576,9 +653,13 @@ void doCmdWClearW(char *params) { } void doCmdTrigger(char *params) { - unsigned int trigger = -1; + int trigger = -1; int n = lookupBreakpoint(params); if (n < 0) { + log0("Trigger Codes:\n"); + for (trigger = 0; trigger < NUM_TRIGGERS; trigger++) { + log0(" %X = %s\n", trigger, triggerStrings[trigger]); + } return; } sscanf(params, "%*x %x", &trigger); @@ -601,7 +682,7 @@ void shiftBreakpointRegister(unsigned int addr, unsigned int mode, unsigned int reg |= addr; // Total size is 26 bits for (i = 0; i <= 25; i++) { - hwCmd(CMD_LOAD_REG, reg & 1); + hwCmd(CMD_LOAD_BRKPT, reg & 1); reg >>= 1; } } @@ -609,7 +690,9 @@ void shiftBreakpointRegister(unsigned int addr, unsigned int mode, unsigned int void doCmdContinue(char *params) { int i; int status; +#ifdef LCD unsigned int i_addr; +#endif // Step the 6502, otherwise the breakpoint happends again immediately hwCmd(CMD_STEP, 0); @@ -636,8 +719,8 @@ void doCmdContinue(char *params) { int cont = 1; do { // Update the LCD display - i_addr = hwRead16(OFFSET_IAL); #ifdef LCD + i_addr = hwRead16(OFFSET_IAL); lcdAddr(i_addr); #endif @@ -647,8 +730,7 @@ void doCmdContinue(char *params) { hwCmd(CMD_WATCH_READ, 0); } if (status & INTERRUPTED_MASK || Serial_ByteRecieved0()) { - log0("Interrupted at "); - doCmdAddr(); + log0("Interrupted\n"); cont = 0; } Delay_us(10); @@ -664,6 +746,9 @@ void doCmdContinue(char *params) { // Disable breakpoints hwCmd(CMD_BRKPT_ENABLE, 0); + + // Show current instruction + doCmdAddr(); } @@ -688,6 +773,9 @@ void (*cmdFuncs[NUM_CMDS])(char *params) = { doCmdHelp, #ifdef EMBEDDED_6502 doCmdRegs, + doCmdMem, + doCmdDis, + doCmdWrite, #endif doCmdReset, doCmdStep, diff --git a/firmware/Makefile.cpu b/firmware/Makefile.cpu index 9df9d23..38f6542 100644 --- a/firmware/Makefile.cpu +++ b/firmware/Makefile.cpu @@ -25,7 +25,7 @@ OBJCOPY=avr-objcopy CFLAGS=-DEMBEDDED_6502=1 -DF_CPU=${F_CPU}UL -DSERIAL_STATUS -DCOOKED_SERIAL -DNOUSART1 -mmcu=$(MCU) -Wall -Os -mcall-prologues -OBJECTS=AtomBusMon.o hd44780.o status.o +OBJECTS=AtomBusMon.o hd44780.o status.o disassembler.o load: avr.bit # sudo $(PROG) -v -f avr.bit diff --git a/firmware/disassembler.c b/firmware/disassembler.c new file mode 100644 index 0000000..3de7009 --- /dev/null +++ b/firmware/disassembler.c @@ -0,0 +1,118 @@ +#include "status.h" + +enum +{ + IMP, IMPA, IMM, ZP, ZPX, ZPY, INDX, INDY, IND, ABS, ABSX, ABSY, IND16, IND1X, BRA +}; + +char dopname[256][6] = +{ +/*00*/ "BRK", "ORA", "---", "---", "TSB", "ORA", "ASL", "---", "PHP", "ORA", "ASL", "---", "TSB", "ORA", "ASL", "---", +/*10*/ "BPL", "ORA", "ORA", "---", "TRB", "ORA", "ASL", "---", "CLC", "ORA", "INC", "---", "TRB", "ORA", "ASL", "---", +/*20*/ "JSR", "AND", "---", "---", "BIT", "AND", "ROL", "---", "PLP", "AND", "ROL", "---", "BIT", "AND", "ROL", "---", +/*30*/ "BMI", "AND", "AND", "---", "BIT", "AND", "ROL", "---", "SEC", "AND", "DEC", "---", "BIT", "AND", "ROL", "---", +/*40*/ "RTI", "EOR", "---", "---", "---", "EOR", "LSR", "---", "PHA", "EOR", "LSR", "---", "JMP", "EOR", "LSR", "---", +/*50*/ "BVC", "EOR", "EOR", "---", "---", "EOR", "LSR", "---", "CLI", "EOR", "PHY", "---", "---", "EOR", "LSR", "---", +/*60*/ "RTS", "ADC", "---", "---", "STZ", "ADC", "ROR", "---", "PLA", "ADC", "ROR", "---", "JMP", "ADC", "ROR", "---", +/*70*/ "BVS", "ADC", "ADC", "---", "STZ", "ADC", "ROR", "---", "SEI", "ADC", "PLY", "---", "JMP", "ADC", "ROR", "---", +/*80*/ "BRA", "STA", "---", "---", "STY", "STA", "STX", "---", "DEY", "BIT", "TXA", "---", "STY", "STA", "STX", "---", +/*90*/ "BCC", "STA", "STA", "---", "STY", "STA", "STX", "---", "TYA", "STA", "TXS", "---", "STZ", "STA", "STZ", "---", +/*A0*/ "LDY", "LDA", "LDX", "---", "LDY", "LDA", "LDX", "---", "TAY", "LDA", "TAX", "---", "LDY", "LDA", "LDX", "---", +/*B0*/ "BCS", "LDA", "LDA", "---", "LDY", "LDA", "LDX", "---", "CLV", "LDA", "TSX", "---", "LDY", "LDA", "LDX", "---", +/*C0*/ "CPY", "CMP", "---", "---", "CPY", "CMP", "DEC", "---", "INY", "CMP", "DEX", "WAI", "CPY", "CMP", "DEC", "---", +/*D0*/ "BNE", "CMP", "CMP", "---", "---", "CMP", "DEC", "---", "CLD", "CMP", "PHX", "STP", "---", "CMP", "DEC", "---", +/*E0*/ "CPX", "SBC", "---", "---", "CPX", "SBC", "INC", "---", "INX", "SBC", "NOP", "---", "CPX", "SBC", "INC", "---", +/*F0*/ "BEQ", "SBC", "SBC", "---", "---", "SBC", "INC", "---", "SED", "SBC", "PLX", "---", "---", "SBC", "INC", "---", +}; + +int dopaddr[256] = +{ +/*00*/ IMP, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, ABS, ABS, ABS, IMP, +/*10*/ BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMPA, IMP, ABS, ABSX, ABSX, IMP, +/*20*/ ABS, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, ABS, ABS, ABS, IMP, +/*30*/ BRA, INDY, IND, IMP, ZPX, ZPX, ZPX, IMP, IMP, ABSY, IMPA, IMP, ABSX, ABSX, ABSX, IMP, +/*40*/ IMP, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, ABS, ABS, ABS, IMP, +/*50*/ BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP, +/*60*/ IMP, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMPA, IMP, IND16, ABS, ABS, IMP, +/*70*/ BRA, INDY, IND, IMP, ZPX, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, IND1X, ABSX, ABSX, IMP, +/*80*/ BRA, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, +/*90*/ BRA, INDY, IND, IMP, ZPX, ZPX, ZPY, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP, +/*A0*/ IMM, INDX, IMM, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, +/*B0*/ BRA, INDY, IND, IMP, ZPX, ZPX, ZPY, IMP, IMP, ABSY, IMP, IMP, ABSX, ABSX, ABSY, IMP, +/*C0*/ IMM, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, +/*D0*/ BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP, +/*E0*/ IMM, INDX, IMP, IMP, ZP, ZP, ZP, IMP, IMP, IMM, IMP, IMP, ABS, ABS, ABS, IMP, +/*F0*/ BRA, INDY, IND, IMP, ZP, ZPX, ZPX, IMP, IMP, ABSY, IMP, IMP, ABS, ABSX, ABSX, IMP, +}; + +unsigned int disassemble(unsigned int addr, unsigned int op, unsigned int p1, unsigned int p2) +{ + unsigned int temp; + + log0("%04X : %s ", addr, dopname[op]); + switch (dopaddr[op]) + { + case IMP: + log0(" "); + break; + case IMPA: + log0("A "); + break; + case IMM: + log0("#%02X ", p1); + addr++; + break; + case ZP: + log0("%02X ", p1); + addr++; + break; + case ZPX: + log0("%02X,X ", p1); + addr++; + break; + case ZPY: + log0("%02X,Y ", p1); + addr++; + break; + case IND: + log0("(%02X) ", p1); + addr++; + break; + case INDX: + log0("(%02X,X) ", p1); + addr++; + break; + case INDY: + log0("(%02X),Y ", p1); + addr++; + break; + case ABS: + log0("%02X%02X ", p2, p1); + addr += 2; + break; + case ABSX: + log0("%02X%02X,X ", p2, p1); + addr += 2; + break; + case ABSY: + log0("%02X%02X,Y ", p2, p1); + addr += 2; + break; + case IND16: + log0("(%02X%02X) ", p2, p1); + addr += 2; + break; + case IND1X: + log0("(%02X%02X,X)", p2, p1); + addr += 2; + break; + case BRA: + temp = addr + 2 + (signed char)p1; + log0("%04X ", temp); + addr++; + break; + } + log0("\n"); + addr++; + return addr; +} diff --git a/firmware/disassembler.h b/firmware/disassembler.h new file mode 100644 index 0000000..8afdc26 --- /dev/null +++ b/firmware/disassembler.h @@ -0,0 +1,6 @@ +#ifndef __DISASSEMBLE_DEFINES__ +#define __DISASSEMBLE_DEFINES__ + +unsigned int disassemble(unsigned int addr, unsigned int op, unsigned int p1, unsigned int p2); + +#endif diff --git a/src/AtomCpuMon.vhd b/src/AtomCpuMon.vhd index 0368ad8..8f702f6 100644 --- a/src/AtomCpuMon.vhd +++ b/src/AtomCpuMon.vhd @@ -79,15 +79,21 @@ architecture behavioral of AtomCpuMon is signal Phi0_c : std_logic; signal Phi0_d : std_logic; signal cpu_clk : std_logic; + signal busmon_clk : std_logic; signal Regs : std_logic_vector(63 downto 0); + signal memory_rd : std_logic; + signal memory_wr : std_logic; + signal memory_addr : std_logic_vector(15 downto 0); + signal memory_dout : std_logic_vector(7 downto 0); + signal memory_din : std_logic_vector(7 downto 0); begin mon : entity work.BusMonCore port map ( clock49 => clock49, Addr => Addr_int, - Phi2 => Phi0, + Phi2 => busmon_clk, RNW => R_W_n_int, Sync => Sync_int, Rdy => Rdy_int, @@ -107,7 +113,12 @@ begin tmosi => tmosi, tdin => tdin, tcclk => tcclk, - Regs => Regs + Regs => Regs, + RdOut => memory_rd, + WrOut => memory_wr, + AddrOut => memory_addr, + DataOut => memory_dout, + DataIn => memory_din ); cpu_t65 : entity work.T65 port map ( @@ -140,12 +151,15 @@ begin end if; end process; - R_W_n <= R_W_n_int; - Addr <= Addr_int; + R_W_n <= '1' when memory_rd = '1' else '0' when memory_wr = '1' else R_W_n_int; + Addr <= memory_addr when (memory_rd = '1' or memory_wr = '1') else Addr_int; Sync <= Sync_int; - Din <= Data; - Data <= Dout when Phi0_d = '1' and R_W_n_int = '0' else (others => 'Z'); + Din <= Data; + memory_din <= Data; + Data <= memory_dout when cpu_clk = '0' and memory_wr = '1' else + Dout when cpu_clk = '0' and R_W_n_int = '0' and memory_rd = '0' else + (others => 'Z'); clk_gen : process(clock49) begin @@ -157,11 +171,10 @@ begin end if; end process; - Phi1 <= not (Phi0_b or Phi0_d); - Phi2 <= Phi0_b and Phi0_d; - - cpu_clk <= not Phi0_d; - + Phi1 <= not (Phi0_b or Phi0_d); + Phi2 <= Phi0_b and Phi0_d; + cpu_clk <= not Phi0_d; + busmon_clk <= Phi0_d; end behavioral; diff --git a/src/BusMonCore.vhd b/src/BusMonCore.vhd new file mode 100644 index 0000000..c356c22 --- /dev/null +++ b/src/BusMonCore.vhd @@ -0,0 +1,447 @@ +-------------------------------------------------------------------------------- +-- Copyright (c) 2015 David Banks +-- +-------------------------------------------------------------------------------- +-- ____ ____ +-- / /\/ / +-- /___/ \ / +-- \ \ \/ +-- \ \ +-- / / Filename : BusMonCore.vhd +-- /___/ /\ Timestamp : 30/05/2015 +-- \ \ / \ +-- \___\/\___\ +-- +--Design Name: AtomBusMon +--Device: XC3S250E + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; +use work.OhoPack.all ; + + +entity BusMonCore is + generic ( + num_comparators : integer := 8; + reg_width : integer := 26; + fifo_width : integer := 36 + ); + port ( + clock49 : in std_logic; + + -- 6502 Signals + Addr : in std_logic_vector(15 downto 0); + Phi2 : in std_logic; + RNW : in std_logic; + Sync : in std_logic; + Rdy : out std_logic; + nRST : inout std_logic; + + -- 6502 Registers + Regs : in std_logic_vector(63 downto 0); + + -- 6502 Memory Read/Write + RdOut : out std_logic; + WrOut : out std_logic; + AddrOut : out std_logic_vector(15 downto 0); + DataOut : out std_logic_vector(7 downto 0); + DataIn : in std_logic_vector(7 downto 0); + + -- External trigger inputs + trig : in std_logic_vector(1 downto 0); + + -- HD44780 LCD + lcd_rs : out std_logic; + lcd_rw : out std_logic; + lcd_e : out std_logic; + lcd_db : inout std_logic_vector(7 downto 4); + + -- AVR Serial Port + avr_RxD : in std_logic; + avr_TxD : out std_logic; + + -- GODIL Switches + sw1 : in std_logic; + nsw2 : in std_logic; + + -- GODIL LEDs + led3 : out std_logic; + led6 : out std_logic; + led8 : out std_logic; + + -- OHO_DY1 connected to test connector + tmosi : out std_logic; + tdin : out std_logic; + tcclk : out std_logic + ); +end BusMonCore; + +architecture behavioral of BusMonCore is + + signal clock_avr : std_logic; + signal nrst_avr : std_logic; + signal lcd_rw_int : std_logic; + signal lcd_db_in : std_logic_vector(7 downto 4); + signal lcd_db_out : std_logic_vector(7 downto 4); + signal dy_counter : std_logic_vector(31 downto 0); + signal dy_data : y2d_type ; + + signal mux : std_logic_vector(7 downto 0); + signal muxsel : std_logic_vector(3 downto 0); + signal cmd_edge : std_logic; + signal cmd_edge1 : std_logic; + signal cmd_edge2 : std_logic; + signal cmd : std_logic_vector(3 downto 0); + + signal addr_sync : std_logic_vector(15 downto 0); + signal addr_inst : std_logic_vector(15 downto 0); + + signal single : std_logic; + signal reset : std_logic; + signal step : std_logic; + + signal bw_status : std_logic_vector(fifo_width - 16 - 1 downto 0); + signal bw_status1 : std_logic_vector(fifo_width - 16 - 1 downto 0); + + signal brkpt_reg : std_logic_vector(num_comparators * reg_width - 1 downto 0); + signal brkpt_enable : std_logic; + signal brkpt_active : std_logic; + signal brkpt_active1 : std_logic; + signal watch_active : std_logic; + + signal fifo_din : std_logic_vector(fifo_width - 1 downto 0); + signal fifo_dout : std_logic_vector(fifo_width - 1 downto 0); + signal fifo_empty : std_logic; + signal fifo_rd : std_logic; + signal fifo_wr : std_logic; + signal fifo_rst : std_logic; + + signal memory_rd : std_logic; + signal memory_wr : std_logic; + signal addr_dout_reg : std_logic_vector(23 downto 0); + signal din_reg : std_logic_vector(7 downto 0); + +begin + + inst_dcm5 : entity work.DCM0 port map( + CLKIN_IN => clock49, + CLK0_OUT => clock_avr, + CLK0_OUT1 => open, + CLK2X_OUT => open + ); + + inst_oho_dy1 : entity work.Oho_Dy1 port map ( + dy_clock => clock49, + dy_rst_n => '1', + dy_data => dy_data, + dy_update => '1', + dy_frame => open, + dy_frameend => open, + dy_frameend_c => open, + dy_pwm => "1010", + dy_counter => dy_counter, + dy_sclk => tdin, + dy_ser => tcclk, + dy_rclk => tmosi + ); + + + Inst_AVR8: entity work.AVR8 port map( + clk16M => clock_avr, + nrst => nrst_avr, + + portain(0) => '0', + portain(1) => '0', + portain(2) => '0', + portain(3) => '0', + portain(4) => lcd_db_in(4), + portain(5) => lcd_db_in(5), + portain(6) => lcd_db_in(6), + portain(7) => lcd_db_in(7), + + portaout(0) => lcd_rs, + portaout(1) => lcd_rw_int, + portaout(2) => lcd_e, + portaout(3) => open, + portaout(4) => lcd_db_out(4), + portaout(5) => lcd_db_out(5), + portaout(6) => lcd_db_out(6), + portaout(7) => lcd_db_out(7), + + -- Command Port + portbin(0) => '0', + portbin(1) => '0', + portbin(2) => '0', + portbin(3) => '0', + portbin(4) => '0', + portbin(5) => '0', + portbin(6) => '0', + portbin(7) => '0', + portbout(0) => cmd(0), + portbout(1) => cmd(1), + portbout(2) => cmd(2), + portbout(3) => cmd(3), + portbout(4) => cmd_edge, + portbout(5) => open, + portbout(6) => open, + portbout(7) => open, + + -- Status Port + portdin(0) => '0', + portdin(1) => '0', + portdin(2) => '0', + portdin(3) => '0', + portdin(4) => '0', + portdin(5) => '0', + portdin(6) => sw1, + portdin(7) => not fifo_empty, + + portdout(0) => muxsel(0), + portdout(1) => muxsel(1), + portdout(2) => muxsel(2), + portdout(3) => muxsel(3), + portdout(4) => open, + portdout(5) => open, + portdout(6) => open, + portdout(7) => open, + + -- Mux Port + portein => mux, + porteout => open, + + spi_mosio => open, + spi_scko => open, + spi_misoi => '0', + + rxd => avr_RxD, + txd => avr_TxD + ); + + WatchEvents_inst : entity work.WatchEvents port map( + clk => Phi2, + srst => fifo_rst, + din => fifo_din, + wr_en => fifo_wr, + rd_en => fifo_rd, + dout => fifo_dout, + full => open, + empty => fifo_empty + ); + + + fifo_din <= bw_status1 & addr_inst; + + lcd_rw <= lcd_rw_int; + lcd_db <= lcd_db_out when lcd_rw_int = '0' else (others => 'Z'); + lcd_db_in <= lcd_db; + + led3 <= not trig(0); -- red + led6 <= not trig(1); -- red + led8 <= not brkpt_active; -- green + + nrst_avr <= nsw2; + + -- OHO DY1 Display for Testing + dy_data(0) <= hex & "0000" & Addr(3 downto 0); + dy_data(1) <= hex & "0000" & Addr(7 downto 4); + dy_data(2) <= hex & "0000" & "00" & (not nsw2) & sw1; + + mux <= addr_inst(7 downto 0) when muxsel = 0 else + addr_inst(15 downto 8) when muxsel = 1 else + fifo_dout(7 downto 0) when muxsel = 2 else + fifo_dout(15 downto 8) when muxsel = 3 else + fifo_dout(23 downto 16) when muxsel = 4 else + fifo_dout(31 downto 24) when muxsel = 5 else + "0000" & fifo_dout(35 downto 32) when muxsel = 6 else + din_reg when muxsel = 7 else + Regs(7 downto 0) when muxsel = 8 else + Regs(15 downto 8) when muxsel = 9 else + Regs(23 downto 16) when muxsel = 10 else + Regs(31 downto 24) when muxsel = 11 else + Regs(39 downto 32) when muxsel = 12 else + Regs(47 downto 40) when muxsel = 13 else + Regs(55 downto 48) when muxsel = 14 else + Regs(63 downto 56) when muxsel = 15 else + "10101010"; + + -- Combinatorial set of comparators to decode breakpoint/watch addresses + brkpt_active_process: process (brkpt_reg, brkpt_enable, Addr, Sync) + variable i : integer; + variable reg_addr : std_logic_vector(15 downto 0); + variable reg_mode_bi : std_logic; + variable reg_mode_bar : std_logic; + variable reg_mode_baw : std_logic; + variable reg_mode_wi : std_logic; + variable reg_mode_war : std_logic; + variable reg_mode_waw : std_logic; + variable bactive : std_logic; + variable wactive : std_logic; + variable status : std_logic_vector(19 downto 0); + variable trigval : std_logic; + begin + bactive := '0'; + wactive := '0'; + status := "00001010101010101010"; + if (brkpt_enable = '1') then + for i in 0 to num_comparators - 1 loop + reg_addr := brkpt_reg(i * reg_width + 15 downto i * reg_width); + reg_mode_bi := brkpt_reg(i * reg_width + 16); + reg_mode_bar := brkpt_reg(i * reg_width + 17); + reg_mode_baw := brkpt_reg(i * reg_width + 18); + reg_mode_wi := brkpt_reg(i * reg_width + 19); + reg_mode_war := brkpt_reg(i * reg_width + 20); + reg_mode_waw := brkpt_reg(i * reg_width + 21); + trigval := brkpt_reg(i * reg_width + 22 + to_integer(unsigned(trig))); + if (trigval = '1' and (Addr = reg_addr or + (reg_mode_bi = '0' and reg_mode_bar = '0' and reg_mode_baw = '0' and + (reg_mode_wi = '0' and reg_mode_war = '0' and reg_mode_waw = '0')))) then + if (Sync = '1') then + if (reg_mode_bi = '1') then + bactive := '1'; + status := "0001" & reg_addr; + end if; + if (reg_mode_wi = '1') then + wactive := '1'; + status := "1001" & reg_addr; + end if; + else + if (RNW = '1') then + if (reg_mode_bar = '1') then + bactive := '1'; + status := "0010" & reg_addr; + end if; + if (reg_mode_war = '1') then + wactive := '1'; + status := "1010" & reg_addr; + end if; + else + if (reg_mode_baw = '1') then + bactive := '1'; + status := "0100" & reg_addr; + end if; + if (reg_mode_waw = '1') then + wactive := '1'; + status := "1100" & reg_addr; + end if; + end if; + end if; + end if; + end loop; + end if; + watch_active <= wactive; + brkpt_active <= bactive; + bw_status <= status; + end process; + + -- 6502 Control Commands + -- 000x Enable/Disable single stepping + -- 001x Enable/Disable breakpoints / watches + -- 010x Load breakpoint register + -- 011x Reset + -- 1000 Single Step + -- 1001 FIFO Read + -- 1010 FIFO Reset + -- 110x Load memory address/data register + -- 1110 Read memory + -- 1111 Write memory + + risingProcess: process (Phi2) + begin + if rising_edge(Phi2) then + + -- Command processing + cmd_edge1 <= cmd_edge; + cmd_edge2 <= cmd_edge1; + fifo_rd <= '0'; + fifo_wr <= '0'; + fifo_rst <= '0'; + memory_rd <= '0'; + memory_wr <= '0'; + if (cmd_edge2 = '0' and cmd_edge1 = '1') then + if (cmd(3 downto 1) = "000") then + single <= cmd(0); + end if; + + if (cmd(3 downto 1) = "001") then + brkpt_enable <= cmd(0); + end if; + + if (cmd(3 downto 1) = "010") then + brkpt_reg <= cmd(0) & brkpt_reg(brkpt_reg'length - 1 downto 1); + end if; + + if (cmd(3 downto 1) = "110") then + addr_dout_reg <= cmd(0) & addr_dout_reg(addr_dout_reg'length - 1 downto 1); + end if; + + if (cmd(3 downto 1) = "011") then + reset <= cmd(0); + end if; + + if (cmd(3 downto 0) = "1001") then + fifo_rd <= '1'; + end if; + + if (cmd(3 downto 0) = "1010") then + fifo_rst <= '1'; + end if; + + if (cmd(3 downto 0) = "1110") then + memory_rd <= '1'; + end if; + + if (cmd(3 downto 0) = "1111") then + memory_wr <= '1'; + end if; + + end if; + + -- Single Stepping + if ((single = '0') or (cmd_edge2 = '0' and cmd_edge1 = '1' and cmd = "1000")) then + Rdy <= (not brkpt_active); + else + Rdy <= (not Sync); + end if; + + -- 6502 Reset needs to be open collector + if (reset = '1') then + nRST <= '0'; + else + nRST <= 'Z'; + end if; + + -- Latch instruction address for the whole cycle + if (Sync = '1') then + addr_inst <= Addr; + end if; + + -- Breakpoints and Watches written to the FIFO + brkpt_active1 <= brkpt_active; + bw_status1 <= bw_status; + if watch_active = '1' or (brkpt_active = '1' and brkpt_active1 = '0') then + fifo_wr <= '1'; + end if; + + end if; + end process; + + fallingProcess: process (Phi2) + begin + if falling_edge(Phi2) then + -- Latch memory read in response to a read command + if (memory_rd = '1') then + din_reg <= DataIn; + end if; + end if; + end process; + + RdOut <= memory_rd; + WrOut <= memory_wr; + AddrOut <= addr_dout_reg(23 downto 8); + DataOut <= addr_dout_reg(7 downto 0); + +end behavioral; + +