diff --git a/AtomFast6502.xise b/AtomFast6502.xise index 07884d0..b1f9bbf 100644 --- a/AtomFast6502.xise +++ b/AtomFast6502.xise @@ -20,7 +20,7 @@ - + @@ -36,7 +36,7 @@ - + @@ -216,7 +216,7 @@ - + @@ -236,22 +236,22 @@ - + - + - + - + @@ -261,6 +261,14 @@ + + + + + + + + diff --git a/src/AtomFast6502.bmm b/src/AtomFast6502.bmm index f4b771d..1e2be6a 100644 --- a/src/AtomFast6502.bmm +++ b/src/AtomFast6502.bmm @@ -2,39 +2,39 @@ ADDRESS_MAP avrmap PPC405 0 ADDRESS_SPACE rom_code RAMB16 [0x00000000:0x000047ff] BUS_BLOCK - mon/Inst_AVR8/PM_Inst/RAM_Word0 [15:0]; + core/mon/Inst_AVR8/PM_Inst/RAM_Word0 [15:0]; END_BUS_BLOCK; BUS_BLOCK - mon/Inst_AVR8/PM_Inst/RAM_Word1 [15:0]; + core/mon/Inst_AVR8/PM_Inst/RAM_Word1 [15:0]; END_BUS_BLOCK; BUS_BLOCK - mon/Inst_AVR8/PM_Inst/RAM_Word2 [15:0]; + core/mon/Inst_AVR8/PM_Inst/RAM_Word2 [15:0]; END_BUS_BLOCK; BUS_BLOCK - mon/Inst_AVR8/PM_Inst/RAM_Word3 [15:0]; + core/mon/Inst_AVR8/PM_Inst/RAM_Word3 [15:0]; END_BUS_BLOCK; BUS_BLOCK - mon/Inst_AVR8/PM_Inst/RAM_Word4 [15:0]; + core/mon/Inst_AVR8/PM_Inst/RAM_Word4 [15:0]; END_BUS_BLOCK; BUS_BLOCK - mon/Inst_AVR8/PM_Inst/RAM_Word5 [15:0]; + core/mon/Inst_AVR8/PM_Inst/RAM_Word5 [15:0]; END_BUS_BLOCK; BUS_BLOCK - mon/Inst_AVR8/PM_Inst/RAM_Word6 [15:0]; + core/mon/Inst_AVR8/PM_Inst/RAM_Word6 [15:0]; END_BUS_BLOCK; BUS_BLOCK - mon/Inst_AVR8/PM_Inst/RAM_Word7 [15:0]; + core/mon/Inst_AVR8/PM_Inst/RAM_Word7 [15:0]; END_BUS_BLOCK; BUS_BLOCK - mon/Inst_AVR8/PM_Inst/RAM_Word8 [15:0]; + core/mon/Inst_AVR8/PM_Inst/RAM_Word8 [15:0]; END_BUS_BLOCK; END_ADDRESS_SPACE; diff --git a/src/AtomFast6502.ucf b/src/AtomFast6502.ucf index ecd084e..76d7335 100644 --- a/src/AtomFast6502.ucf +++ b/src/AtomFast6502.ucf @@ -2,7 +2,9 @@ NET "clock49" LOC="P89" | IOSTANDARD = LVCMOS33 | PERIOD = 20.35ns ; # 49.152 MHz Oscillator NET "clock49" CLOCK_DEDICATED_ROUTE = FALSE; -PIN "mon/inst_dcm0/DCM_INST.CLKIN" CLOCK_DEDICATED_ROUTE = FALSE; +PIN "inst_dcm0/DCM_INST.CLKIN" CLOCK_DEDICATED_ROUTE = FALSE; +NET "Phi0" CLOCK_DEDICATED_ROUTE = FALSE; +PIN "inst_dcm2/DCM_INST.CLKIN" CLOCK_DEDICATED_ROUTE = FALSE; #NET "VSS" LOC="P16" | IOSTANDARD = LVCMOS33 ; # 6502 pin 1 #NET "Rdy" LOC="P95" | IOSTANDARD = LVCMOS33 ; # 6502 pin 2 @@ -67,7 +69,7 @@ NET "avr_RxD" LOC="P15" | IOSTANDARD = LVCMOS33 ; NET "trig<0>" LOC="P62" | IOSTANDARD = LVCMOS33 ; NET "trig<1>" LOC="P63" | IOSTANDARD = LVCMOS33 ; -NET "fakeTube_n" LOC="P65" | IOSTANDARD = LVCMOS33 ; +#NET "fakeTube_n" LOC="P65" | IOSTANDARD = LVCMOS33 ; # NET "" LOC="P48" | IOSTANDARD = LVCMOS33 ; # connector pin E2 # NET "" LOC="P49" | IOSTANDARD = LVCMOS33 ; # connector pin E3 diff --git a/src/AtomFast6502.vhd b/src/AtomFast6502.vhd index e3b3d77..014f226 100644 --- a/src/AtomFast6502.vhd +++ b/src/AtomFast6502.vhd @@ -14,6 +14,22 @@ -- --Design Name: AtomBusMon --Device: XC3S250E +-- +-- This desing uses a DCM to generate a 16x internal clock from Phi0 +-- Output signals can be placed in units of 1/16th Phi0 +-- +-- There are two constraints to be aware of: +-- +-- 1. There is no defined phase relationship between Phi0 and Phi1/2 +-- This is because Phi is typically too slow for a Spartan -6 DLL +-- If the host system also uses Phi0, then this may cause problems. +-- +-- 2. Phi0 must be a single frequency clock, or the DCM will not lock +-- This will not, therefore, work in a Beeb because of the clock +-- stretching when IO devices are accessed. +-- +-- The Atom satisfies both of these constraints. +-- library ieee; use ieee.std_logic_1164.all; @@ -21,7 +37,6 @@ use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; use work.OhoPack.all ; - entity AtomFast6502 is generic ( UseT65Core : boolean := true; @@ -47,9 +62,6 @@ entity AtomFast6502 is -- External trigger inputs trig : in std_logic_vector(1 downto 0); - -- Jumpers - fakeTube_n : in std_logic; - -- Serial Console avr_RxD : in std_logic; avr_TxD : out std_logic; @@ -72,168 +84,156 @@ entity AtomFast6502 is end AtomFast6502; architecture behavioral of AtomFast6502 is - - signal Din : std_logic_vector(7 downto 0); - - -- Signal from the internal core - signal Dout0 : std_logic_vector(7 downto 0); - signal Addr0 : std_logic_vector(15 downto 0); - signal R_W_n0 : std_logic; - signal Sync0 : std_logic; - - -- Delayed signals for the outside world - signal Dout1 : std_logic_vector(7 downto 0); - signal Addr1 : std_logic_vector(15 downto 0); - signal R_W_n1 : std_logic; - signal Sync1 : std_logic; - signal Rdy_int : std_logic; - - signal cpu_addr_us: unsigned (15 downto 0); - signal cpu_dout_us: unsigned (7 downto 0); - - signal clock_16x : std_logic; - signal cpu_clk : std_logic; - signal busmon_clk : std_logic; - signal R_W_n_int : std_logic; - + + -- Clocking + signal clock_avr : std_logic; + signal clock_16x : std_logic; + signal clk_div : std_logic_vector(3 downto 0); signal cpu_clken : std_logic; signal cpu_dataen : std_logic; - - signal clk_div : std_logic_vector(3 downto 0); + signal busmon_clken : std_logic; - signal Phi1_int : std_logic; - signal Phi2_int : std_logic; + -- DCM watchdog signal dcm_reset : std_logic; - signal dcm_count : std_logic_vector(9 downto 0); signal dcm_locked : std_logic; + signal dcm_count : std_logic_vector(9 downto 0); signal edge0 : std_logic; signal edge1 : std_logic; - - signal Regs : std_logic_vector(63 downto 0); - signal Regs1 : std_logic_vector(255 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); - signal memory_done : std_logic; + signal Din : std_logic_vector(7 downto 0); + + signal Addr0 : std_logic_vector(15 downto 0); + signal R_W_n0 : std_logic; + signal Sync0 : std_logic; + signal Dout0 : std_logic_vector(7 downto 0); + + signal Addr1 : std_logic_vector(15 downto 0); + signal R_W_n1 : std_logic; + signal Sync1 : std_logic; + signal Dout1 : std_logic_vector(7 downto 0); + + signal IRQ_n_sync : std_logic; + signal NMI_n_sync : std_logic; + + signal Res_n_in : std_logic; + signal Res_n_out : std_logic; begin - mon : entity work.BusMonCore port map ( - clock49 => clock49, - Addr => Addr1, - Data => Data, - Phi2 => busmon_clk, - Rd_n => not R_W_n1, - Wr_n => R_W_n1, - RdIO_n => '1', - WrIO_n => '1', - Sync => Sync1, - Rdy => Rdy_int, - nRSTin => Res_n, - nRSTout => Res_n, - CountCycle => Rdy_int, - trig => trig, - lcd_rs => open, - lcd_rw => open, - lcd_e => open, - lcd_db => open, - avr_RxD => avr_RxD, - avr_TxD => avr_TxD, - sw1 => sw1, - nsw2 => nsw2, - led3 => led3, - led6 => led6, - led8 => led8, - tmosi => tmosi, - tdin => tdin, - tcclk => tcclk, - Regs => Regs1, - RdMemOut=> memory_rd, - WrMemOut=> memory_wr, - RdIOOut => open, - WrIOOut => open, - AddrOut => memory_addr, - DataOut => memory_dout, - DataIn => memory_din, - Done => memory_done, - SS_Step => open, - SS_Single => open + inst_dcm0 : entity work.DCM0 port map( + CLKIN_IN => clock49, + CLK0_OUT => clock_avr, + CLK0_OUT1 => open, + CLK2X_OUT => open ); - Regs1(63 downto 0) <= Regs; - Regs1(255 downto 64) <= (others => '0'); - GenT65Core: if UseT65Core generate - inst_t65: entity work.T65 port map ( - mode => "00", - Abort_n => '1', - SO_n => SO_n, - Res_n => Res_n, - Enable => cpu_clken, - Clk => clock_16x, - Rdy => Rdy_int, - IRQ_n => IRQ_n, - NMI_n => NMI_n, - R_W_n => R_W_n0, - Sync => Sync0, - A(23 downto 16) => open, - A(15 downto 0) => Addr0, - DI => Din, - DO => Dout0, - Regs => Regs - ); - end generate; - - GenAlanDCore: if UseAlanDCore generate - inst_r65c02: entity work.r65c02 port map ( - reset => RES_n, - clk => clock_16x, - enable => cpu_clken, - nmi_n => NMI_n, - irq_n => IRQ_n, - di => unsigned(Din), - do => cpu_dout_us, - addr => cpu_addr_us, - nwe => R_W_n0, - sync => Sync0, - sync_irq => open, - Regs => Regs - ); - Dout0 <= std_logic_vector(cpu_dout_us); - Addr0 <= std_logic_vector(cpu_addr_us); - end generate; - - - - - Phi1 <= Phi1_int; - Phi2 <= Phi2_int; - busmon_clk <= Phi2_int; - Din <= Data; - - - Addr <= memory_addr when (memory_rd = '1' or memory_wr = '1') else Addr1; - R_W_n <= '1' when memory_rd = '1' else '0' when memory_wr = '1' else R_W_n1; - Sync <= Sync1; - - Data <= memory_dout when cpu_dataen = '1' and memory_wr = '1' else - Dout1 when cpu_dataen = '1' and R_W_n1 = '0' and memory_rd = '0' else - (others => 'Z'); - - memory_done <= memory_rd or memory_wr; - - - - inst_dcm2 : entity work.DCM2 port map( CLKIN_IN => Phi0, CLKFX_OUT => clock_16x, LOCKED => dcm_locked, RESET => dcm_reset ); + + core : entity work.MOS6502CpuMonCore + generic map ( + UseT65Core => UseT65Core, + UseAlanDCore => UseAlanDCore + ) + port map ( + clock_avr => clock_avr, + busmon_clk => clock_16x, + busmon_clken => busmon_clken, + cpu_clk => clock_16x, + cpu_clken => cpu_clken, + IRQ_n => IRQ_n_sync, + NMI_n => NMI_n_sync, + Sync => Sync0, + Addr => Addr0, + R_W_n => R_W_n0, + Din => Din, + Dout => Dout0, + SO_n => SO_n, + Res_n_in => Res_n_in, + Res_n_out => Res_n_out, + Rdy => '1', + trig => trig, + avr_RxD => avr_RxD, + avr_TxD => avr_TxD, + sw1 => sw1, + nsw2 => nsw2, + led3 => led3, + led6 => led6, + led8 => led8, + tmosi => tmosi, + tdin => tdin, + tcclk => tcclk + ); + -- Tristate buffer driving reset back out + Res_n_in <= Res_n; + Res_n <= '0' when Res_n_out <= '0' else 'Z'; + + sync_gen : process(clock_16x) + begin + if rising_edge(clock_16x) then + NMI_n_sync <= NMI_n; + IRQ_n_sync <= IRQ_n; + end if; + end process; + + Addr <= Addr1; + R_W_n <= R_W_n1; + Sync <= Sync1; + Data <= Dout1 when cpu_dataen = '1' and R_W_n1 = '0' else (others => 'Z'); + + -- Din is registered in cpu_clken in BusMonCore + Din <= Data; + + process(clock_16x) + begin + if rising_edge(clock_16x) then + -- internal clock running 16x Phi0 + clk_div <= clk_div + 1; + -- clock the CPU on cycle 0 + if (clk_div = "1111") then + cpu_clken <= '1'; + else + cpu_clken <= '0'; + end if; + -- clock the Busmon out of phase with the cpu + -- exactly which cycle is not critical + if (clk_div = "0111") then + busmon_clken <= '1'; + else + busmon_clken <= '0'; + end if; + -- toggle Phi1/2 on cycles 0 and 8 + if (clk_div = "0000") then + Phi1 <= '1'; + Phi2 <= '0'; + elsif (clk_div = "1000") then + Phi1 <= '0'; + Phi2 <= '1'; + end if; + -- Skew address by one cycle wrt Phi1/2 + -- and hold for a complete cycle + if (clk_div = "0001") then + Addr1 <= Addr0; + R_W_n1 <= R_W_n0; + Sync1 <= Sync0; + end if; + -- Skew data release by one cycle wrt Phi1/2 + if (clk_div = "1000") then + cpu_dataen <= '1'; + Dout1 <= Dout0; + elsif (clk_div = "0001") then + cpu_dataen <= '0'; + Dout1 <= (others => '1'); + end if; + end if; + end process; + + -- This reset the DCM if is seems to have stopped outputting a clock process(clock49) begin if rising_edge(clock49) then @@ -252,61 +252,6 @@ begin end if; end if; end process; - --- -- for some reason this did not work reliably.... --- process(clock49) --- begin --- if rising_edge(clock49) then --- edge0 <= dcm_locked; --- edge1 <= edge0; --- if (dcm_count = "0000000000") then --- dcm_reset <= '0'; --- if (edge0 = '0' and edge1 = '1') then --- dcm_count <= dcm_count + 1; --- end if; --- else --- dcm_reset <= '1'; --- dcm_count <= dcm_count + 1; --- end if; --- end if; --- end process; - - process(clock_16x) - begin - if rising_edge(clock_16x) then - -- internal clock running 16x Phi0 - clk_div <= clk_div + 1; - -- clock the CPU on cycle 0 - if (clk_div = "1111") then - cpu_clken <= '1'; - else - cpu_clken <= '0'; - end if; - -- toggle Phi1/2 on cycles 0 and 8 - if (clk_div = "0000") then - Phi1_int <= '1'; - Phi2_int <= '0'; - memory_din <= Data; - elsif (clk_div = "1000") then - Phi1_int <= '0'; - Phi2_int <= '1'; - end if; - -- Skew address by one cycles, and hold for a complete cycle - if (clk_div = "0001") then - Addr1 <= Addr0; - R_W_n1 <= R_W_n0; - Sync1 <= Sync0; - end if; - -- Skew data by one cycle - if (clk_div = "1000") then - cpu_dataen <= '1'; - Dout1 <= Dout0; - elsif (clk_div = "0001") then - cpu_dataen <= '0'; - Dout1 <= (others => '1'); - end if; - end if; - end process; end behavioral;