mirror of
https://github.com/mist-devel/mist-board.git
synced 2026-02-04 23:24:39 +00:00
BBC: Update T65 from C64
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
-- ****
|
||||
-- T65(b) core. In an effort to merge and maintain bug fixes ....
|
||||
--
|
||||
-- Ver 315 SzGy April 2020
|
||||
-- Reduced the IRQ detection delay when RDY is not asserted (NMI?)
|
||||
-- Undocumented opcodes behavior change during not RDY and page boundary crossing (VICE tests - cpu/sha, cpu/shs, cpu/shxy)
|
||||
--
|
||||
-- Ver 313 WoS January 2015
|
||||
-- Fixed issue that NMI has to be first if issued the same time as a BRK instruction is latched in
|
||||
-- Now all Lorenz CPU tests on FPGAARCADE C64 core (sources used: SVN version 1021) are OK! :D :D :D
|
||||
@@ -152,7 +156,8 @@ entity T65 is
|
||||
DO : out std_logic_vector(7 downto 0);
|
||||
-- 6502 registers (MSB) PC, SP, P, Y, X, A (LSB)
|
||||
Regs : out std_logic_vector(63 downto 0);
|
||||
DEBUG : out T_t65_dbg
|
||||
DEBUG : out T_t65_dbg;
|
||||
NMI_ack : out std_logic
|
||||
);
|
||||
end T65;
|
||||
|
||||
@@ -175,6 +180,8 @@ architecture rtl of T65 is
|
||||
signal IR : std_logic_vector(7 downto 0);
|
||||
signal MCycle : std_logic_vector(2 downto 0);
|
||||
|
||||
signal DO_r : std_logic_vector(7 downto 0);
|
||||
|
||||
signal Mode_r : std_logic_vector(1 downto 0);
|
||||
signal ALU_Op_r : T_ALU_Op;
|
||||
signal Write_Data_r : T_Write_Data;
|
||||
@@ -208,6 +215,7 @@ architecture rtl of T65 is
|
||||
signal Write_Data : T_Write_Data;
|
||||
signal Jump : std_logic_vector(1 downto 0);
|
||||
signal BAAdd : std_logic_vector(1 downto 0);
|
||||
signal BAQuirk : std_logic_vector(1 downto 0);
|
||||
signal BreakAtNA : std_logic;
|
||||
signal ADAdd : std_logic;
|
||||
signal AddY : std_logic;
|
||||
@@ -230,12 +238,15 @@ architecture rtl of T65 is
|
||||
signal Res_n_i : std_logic;
|
||||
signal Res_n_d : std_logic;
|
||||
|
||||
signal rdy_mod : std_logic; -- RDY signal turned off during the instruction
|
||||
signal really_rdy : std_logic;
|
||||
signal WRn_i : std_logic;
|
||||
|
||||
signal NMI_entered : std_logic;
|
||||
|
||||
begin
|
||||
NMI_ack <= NMIAct;
|
||||
|
||||
-- gate Rdy with read/write to make an "OK, it's really OK to stop the processor
|
||||
really_rdy <= Rdy or not(WRn_i);
|
||||
Sync <= '1' when MCycle = "000" else '0';
|
||||
@@ -265,6 +276,7 @@ begin
|
||||
IR => IR,
|
||||
MCycle => MCycle,
|
||||
P => P,
|
||||
Rdy_mod => rdy_mod,
|
||||
--outputs
|
||||
LCycle => LCycle,
|
||||
ALU_Op => ALU_Op,
|
||||
@@ -273,6 +285,7 @@ begin
|
||||
Write_Data => Write_Data,
|
||||
Jump => Jump,
|
||||
BAAdd => BAAdd,
|
||||
BAQuirk => BAQuirk,
|
||||
BreakAtNA => BreakAtNA,
|
||||
ADAdd => ADAdd,
|
||||
AddY => AddY,
|
||||
@@ -338,6 +351,13 @@ begin
|
||||
|
||||
elsif Clk'event and Clk = '1' then
|
||||
if (Enable = '1') then
|
||||
-- some instructions behavior changed by the Rdy line. Detect this at the correct cycles.
|
||||
if MCycle = "000" then
|
||||
rdy_mod <= '0';
|
||||
elsif ((MCycle = "011" and IR /= x"93") or (MCycle = "100" and IR = x"93")) and Rdy = '0' then
|
||||
rdy_mod <= '1';
|
||||
end if;
|
||||
|
||||
if (really_rdy = '1') then
|
||||
WRn_i <= not Write or RstCycle;
|
||||
|
||||
@@ -463,9 +483,6 @@ begin
|
||||
--This should happen after P has been pushed to stack
|
||||
tmpP(Flag_I) := '1';
|
||||
end if;
|
||||
if SO_n_o = '1' and SO_n = '0' then
|
||||
tmpP(Flag_V) := '1';
|
||||
end if;
|
||||
if RstCycle = '1' then
|
||||
tmpP(Flag_I) := '1';
|
||||
tmpP(Flag_D) := '0';
|
||||
@@ -474,16 +491,24 @@ begin
|
||||
|
||||
P<=tmpP;--new way
|
||||
|
||||
SO_n_o <= SO_n;
|
||||
if IR(4 downto 0)/="10000" or Jump/="01" then -- delay interrupts during branches (checked with Lorenz test and real 6510), not best way yet, though - but works...
|
||||
IRQ_n_o <= IRQ_n;
|
||||
end if;
|
||||
end if;
|
||||
|
||||
-- detect irq even if not rdy
|
||||
if IR(4 downto 0)/="10000" or Jump/="01" or really_rdy = '0' then -- delay interrupts during branches (checked with Lorenz test and real 6510), not best way yet, though - but works...
|
||||
IRQ_n_o <= IRQ_n;
|
||||
end if;
|
||||
-- detect nmi even if not rdy
|
||||
if IR(4 downto 0)/="10000" or Jump/="01" then -- delay interrupts during branches (checked with Lorenz test and real 6510) not best way yet, though - but works...
|
||||
NMI_n_o <= NMI_n;
|
||||
end if;
|
||||
end if;
|
||||
-- act immediately on SO pin change
|
||||
-- The signal is sampled on the trailing edge of phi1 and must be externally synchronized (from datasheet)
|
||||
SO_n_o <= SO_n;
|
||||
if SO_n_o = '1' and SO_n = '0' then
|
||||
P(Flag_V) <= '1';
|
||||
end if;
|
||||
|
||||
end if;
|
||||
end process;
|
||||
|
||||
@@ -505,8 +530,8 @@ begin
|
||||
DL <= (others => '0');
|
||||
elsif Clk'event and Clk = '1' then
|
||||
if (Enable = '1') then
|
||||
NMI_entered <= '0';
|
||||
if (really_rdy = '1') then
|
||||
NMI_entered <= '0';
|
||||
BusA_r <= BusA;
|
||||
BusB <= DI;
|
||||
|
||||
@@ -526,7 +551,13 @@ begin
|
||||
when "11" =>
|
||||
-- BA Adj
|
||||
if BAL(8) = '1' then
|
||||
BAH <= std_logic_vector(unsigned(BAH) + 1);
|
||||
-- Handle quirks with some undocumented opcodes crossing page boundary
|
||||
case BAQuirk is
|
||||
when "00" => BAH <= std_logic_vector(unsigned(BAH) + 1); -- no quirk
|
||||
when "01" => BAH <= std_logic_vector(unsigned(BAH) + 1) and DO_r;
|
||||
when "10" => BAH <= DO_r;
|
||||
when others => null;
|
||||
end case;
|
||||
end if;
|
||||
when others =>
|
||||
end case;
|
||||
@@ -604,8 +635,10 @@ begin
|
||||
-- This is the P that gets pushed on stack with correct B flag. I'm not sure if NMI also clears B, but I guess it does.
|
||||
PwithB<=(P and x"ef") when (IRQCycle='1' or NMICycle='1') else P;
|
||||
|
||||
DO <= DO_r;
|
||||
|
||||
with Write_Data_r select
|
||||
DO <=
|
||||
DO_r <=
|
||||
DL when Write_Data_DL,
|
||||
ABC(7 downto 0) when Write_Data_ABC,
|
||||
X(7 downto 0) when Write_Data_X,
|
||||
|
||||
@@ -61,6 +61,7 @@ entity T65_MCode is
|
||||
IR : in std_logic_vector(7 downto 0);
|
||||
MCycle : in T_Lcycle;
|
||||
P : in std_logic_vector(7 downto 0);
|
||||
Rdy_mod : in std_logic;
|
||||
LCycle : out T_Lcycle;
|
||||
ALU_Op : out T_ALU_Op;
|
||||
Set_BusA_To : out T_Set_BusA_To; -- DI,A,X,Y,S,P,DA,DAO,DAX,AAX
|
||||
@@ -68,6 +69,7 @@ entity T65_MCode is
|
||||
Write_Data : out T_Write_Data; -- DL,A,X,Y,S,P,PCL,PCH,AX,AXB,XB,YB
|
||||
Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
|
||||
BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
|
||||
BAQuirk : out std_logic_vector(1 downto 0); -- None,And,Copy
|
||||
BreakAtNA : out std_logic;
|
||||
ADAdd : out std_logic;
|
||||
AddY : out std_logic;
|
||||
@@ -106,7 +108,7 @@ begin
|
||||
not P(Flag_Z) when "110",
|
||||
P(Flag_Z) when others;
|
||||
|
||||
process (IR, MCycle, P, Branch, Mode)
|
||||
process (IR, MCycle, P, Branch, Mode, Rdy_mod)
|
||||
begin
|
||||
lCycle <= Cycle_1;
|
||||
Set_BusA_To <= Set_BusA_To_ABC;
|
||||
@@ -114,6 +116,7 @@ begin
|
||||
Write_Data <= Write_Data_DL;
|
||||
Jump <= (others => '0');
|
||||
BAAdd <= "00";
|
||||
BAQuirk <= "00";
|
||||
BreakAtNA <= '0';
|
||||
ADAdd <= '0';
|
||||
PCAdd <= '0';
|
||||
@@ -140,14 +143,22 @@ begin
|
||||
when "00" => -- IR: $80,$84,$88,$8C,$90,$94,$98,$9C
|
||||
Set_BusA_To <= Set_BusA_To_Y;
|
||||
if IR(4 downto 2)="111" then -- SYA ($9C)
|
||||
Write_Data <= Write_Data_YB;
|
||||
if Rdy_mod = '0' then
|
||||
Write_Data <= Write_Data_YB;
|
||||
else
|
||||
Write_Data <= Write_Data_Y;
|
||||
end if;
|
||||
else
|
||||
Write_Data <= Write_Data_Y;
|
||||
end if;
|
||||
when "10" => -- IR: $82,$86,$8A,$8E,$92,$96,$9A,$9E
|
||||
Set_BusA_To <= Set_BusA_To_X;
|
||||
if IR(4 downto 2)="111" then -- SXA ($9E)
|
||||
Write_Data <= Write_Data_XB;
|
||||
if Rdy_mod = '0' then
|
||||
Write_Data <= Write_Data_XB;
|
||||
else
|
||||
Write_Data <= Write_Data_X;
|
||||
end if;
|
||||
else
|
||||
Write_Data <= Write_Data_X;
|
||||
end if;
|
||||
@@ -159,7 +170,11 @@ begin
|
||||
Set_BusA_To <= Set_BusA_To_ABC;
|
||||
end if;
|
||||
if IR(4 downto 2)="111" or IR(4 downto 2)="110" or IR(4 downto 2)="100" then -- SHA ($9F, $93), SHS ($9B)
|
||||
Write_Data <= Write_Data_AXB;
|
||||
if Rdy_mod = '0' then
|
||||
Write_Data <= Write_Data_AXB;
|
||||
else
|
||||
Write_Data <= Write_Data_AX;
|
||||
end if;
|
||||
else
|
||||
Write_Data <= Write_Data_AX;
|
||||
end if;
|
||||
@@ -843,6 +858,9 @@ begin
|
||||
BAAdd <= "11"; -- BA Adj
|
||||
if IR(7 downto 5) = "100" then
|
||||
Write <= '1';
|
||||
if IR(3 downto 0) = x"3" then
|
||||
BAQuirk <= "10"; -- COPY
|
||||
end if;
|
||||
elsif IR(1)='0' or IR=x"B3" then -- Dont do this on $x3, except undoc LAXiy $B3 (says real CPU and Lorenz tests)
|
||||
BreakAtNA <= '1';
|
||||
end if;
|
||||
@@ -956,6 +974,9 @@ begin
|
||||
BAAdd <= "11"; -- BA adj
|
||||
if IR(7 downto 5) = "100" then--99/9b
|
||||
Write <= '1';
|
||||
if IR(3 downto 0) = x"B" then
|
||||
BAQuirk <= "01"; -- AND
|
||||
end if;
|
||||
elsif IR(1)='0' or IR=x"BB" then -- Dont do this on $xB, except undoc $BB (says real CPU and Lorenz tests)
|
||||
BreakAtNA <= '1';
|
||||
end if;
|
||||
@@ -1045,8 +1066,13 @@ begin
|
||||
Set_Addr_To <= Set_Addr_To_BA;
|
||||
when Cycle_3 =>
|
||||
BAAdd <= "11"; -- BA adj
|
||||
if IR(7 downto 5) = "100" then -- ($9E,$9F)
|
||||
if IR(7 downto 5) = "100" then -- ($9C,$9D,$9E,$9F)
|
||||
Write <= '1';
|
||||
case IR(1 downto 0) is
|
||||
when "00"|"10" => BAQuirk <= "01"; -- AND
|
||||
when "11" => BAQuirk <= "10"; -- COPY
|
||||
when others => null;
|
||||
end case;
|
||||
else
|
||||
BreakAtNA <= '1';
|
||||
end if;
|
||||
|
||||
@@ -284,7 +284,7 @@ T65 CPU (
|
||||
.Res_n (reset_n),
|
||||
.Enable (cpu_clken),
|
||||
.Clk (CLK32M_I),
|
||||
.Rdy (cpu_clken),
|
||||
.Rdy (cpu_ready),
|
||||
.Abort_n(cpu_abort_n),
|
||||
.NMI_n (cpu_nmi_n),
|
||||
.IRQ_n (cpu_irq_n),
|
||||
@@ -656,6 +656,7 @@ assign user_via_pa_in = user_via_pa_out;
|
||||
assign user_via_pb_in = user_via_pb_out;
|
||||
|
||||
|
||||
|
||||
assign MEM_ADR = cpu_a[15:0];
|
||||
assign VID_ADR = display_a;
|
||||
assign MEM_WE = ram_we;
|
||||
|
||||
Reference in New Issue
Block a user