1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-02-05 07:34:41 +00:00

C16: update CPU, use the real RDY line

This commit is contained in:
Gyorgy Szombathelyi
2020-05-17 21:37:32 +02:00
parent be41c2d936
commit 798a238686
3 changed files with 71 additions and 15 deletions

View File

@@ -67,9 +67,9 @@ T65 cpu_core(
.Mode (2'b00),
.Res_n (~reset),
.Enable(enable_cpu),
.Enable(enable),
.Clk(clk),
.Rdy(enable_cpu),
.Rdy(rdy),
.Abort_n(1),
.IRQ_n(irq_n),
.NMI_n(1),
@@ -183,6 +183,6 @@ always @*
end
assign port_out=port_data;
assign enable_cpu=(~rdy & ~we)?1'b0:enable; // When RDY is low and cpu would do a read, halt cpu
//assign enable_cpu=(~rdy & ~we)?1'b0:enable; // When RDY is low and cpu would do a read, halt cpu
endmodule

View File

@@ -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;
@@ -471,9 +491,11 @@ begin
P<=tmpP;--new way
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...
@@ -508,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;
@@ -529,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;
@@ -607,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,

View File

@@ -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;