1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-02-14 11:54:11 +00:00

Some Updates from Slingshot

This commit is contained in:
Gehstock
2020-05-22 15:58:19 +02:00
parent be46871c2b
commit 402bca25b9
4 changed files with 124 additions and 50 deletions

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
@@ -130,14 +134,16 @@ library IEEE;
entity T65 is
port(
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
BCD_en : in std_logic := '1'; -- '0' => 2A03/2A07, '1' => others
Res_n : in std_logic;
Enable : in std_logic;
Clk : in std_logic;
Rdy : in std_logic;
Abort_n : in std_logic;
IRQ_n : in std_logic;
NMI_n : in std_logic;
SO_n : in std_logic;
Rdy : in std_logic := '1';
Abort_n : in std_logic := '1';
IRQ_n : in std_logic := '1';
NMI_n : in std_logic := '1';
SO_n : in std_logic := '1';
R_W_n : out std_logic;
Sync : out std_logic;
EF : out std_logic;
@@ -176,7 +182,10 @@ 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 BCD_en_r : std_logic;
signal ALU_Op_r : T_ALU_Op;
signal Write_Data_r : T_Write_Data;
signal Set_Addr_To_r : T_Set_Addr_To;
@@ -209,6 +218,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;
@@ -231,6 +241,7 @@ 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;
@@ -268,6 +279,7 @@ begin
IR => IR,
MCycle => MCycle,
P => P,
Rdy_mod => rdy_mod,
--outputs
LCycle => LCycle,
ALU_Op => ALU_Op,
@@ -276,6 +288,7 @@ begin
Write_Data => Write_Data,
Jump => Jump,
BAAdd => BAAdd,
BAQuirk => BAQuirk,
BreakAtNA => BreakAtNA,
ADAdd => ADAdd,
AddY => AddY,
@@ -299,6 +312,7 @@ begin
alu : entity work.T65_ALU
port map(
Mode => Mode_r,
BCD_en => BCD_en_r,
Op => ALU_Op_r,
BusA => BusA_r,
BusB => BusB,
@@ -330,6 +344,7 @@ begin
DBR <= (others => '0');
Mode_r <= (others => '0');
BCD_en_r <= '1';
ALU_Op_r <= ALU_OP_BIT;
Write_Data_r <= Write_Data_DL;
Set_Addr_To_r <= Set_Addr_To_PBR;
@@ -341,6 +356,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;
@@ -352,6 +374,7 @@ begin
if MCycle = "000" then
Mode_r <= Mode;
BCD_en_r <= BCD_en;
if IRQCycle = '0' and NMICycle = '0' then
PC <= PC + 1;
@@ -474,9 +497,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...
@@ -532,7 +557,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;
@@ -610,8 +641,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

@@ -57,6 +57,7 @@ use work.T65_Pack.all;
entity T65_ALU is
port(
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
BCD_en : in std_logic;
Op : in T_ALU_OP;
BusA : in std_logic_vector(7 downto 0);
BusB : in std_logic_vector(7 downto 0);
@@ -83,7 +84,7 @@ architecture rtl of T65_ALU is
begin
process (P_In, BusA, BusB)
process (P_In, BusA, BusB, BCD_en)
variable AL : unsigned(6 downto 0);
variable AH : unsigned(6 downto 0);
variable C : std_logic;
@@ -102,7 +103,7 @@ begin
ADC_Z <= '0';
end if;
if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then
if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' and BCD_en = '1' then
AL(6 downto 1) := AL(6 downto 1) + 6;
end if;
@@ -116,7 +117,7 @@ begin
if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
-- pragma translate_on
if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then
if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' and BCD_en = '1' then
AH(6 downto 1) := AH(6 downto 1) + 6;
end if;
@@ -125,7 +126,7 @@ begin
ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
end process;
process (Op, P_In, BusA, BusB)
process (Op, P_In, BusA, BusB, BCD_en)
variable AL : unsigned(6 downto 0);
variable AH : unsigned(5 downto 0);
variable C : std_logic;
@@ -165,7 +166,7 @@ begin
SBX_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
if P_In(Flag_D) = '1' then
if P_In(Flag_D) = '1' and BCD_en = '1' then
if AL(5) = '1' then
AL(5 downto 1) := AL(5 downto 1) - 6;
end if;
@@ -181,7 +182,7 @@ begin
process (Op, P_In, BusA, BusB,
ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q,
SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q,
SBX_Q)
SBX_Q, BCD_en)
variable Q_t : std_logic_vector(7 downto 0);
variable Q2_t : std_logic_vector(7 downto 0);
begin
@@ -226,7 +227,7 @@ begin
Q_t := P_In(Flag_C) & (BusA(7 downto 1) and BusB(7 downto 1));
P_Out(Flag_V) <= Q_t(5) xor Q_t(6);
Q2_t := Q_t;
if P_In(Flag_D)='1' then
if P_In(Flag_D)='1' and BCD_en = '1' then
if (BusA(3 downto 0) and BusB(3 downto 0)) > "0100" then
Q2_t(3 downto 0) := std_logic_vector(unsigned(Q_t(3 downto 0)) + x"6");
end if;

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;

View File

@@ -27,13 +27,15 @@ module osd (
output [5:0] B_out
);
parameter OSD_X_OFFSET = 10'd0;
parameter OSD_Y_OFFSET = 10'd0;
parameter OSD_X_OFFSET = 11'd0;
parameter OSD_Y_OFFSET = 11'd0;
parameter OSD_COLOR = 3'd0;
parameter OSD_AUTO_CE = 1'b1;
localparam OSD_WIDTH = 10'd256;
localparam OSD_HEIGHT = 10'd128;
localparam OSD_WIDTH = 11'd256;
localparam OSD_HEIGHT = 11'd128;
localparam OSD_WIDTH_PADDED = OSD_WIDTH + (OSD_WIDTH >> 1); // 25% padding left and right
// *********************************************************************************
// spi client
@@ -84,36 +86,40 @@ end
// *********************************************************************************
// horizontal counter
reg [9:0] h_cnt;
reg [9:0] hs_low, hs_high;
wire hs_pol = hs_high < hs_low;
wire [9:0] dsp_width = hs_pol ? hs_low : hs_high;
reg [10:0] h_cnt;
reg [10:0] hs_low, hs_high;
wire hs_pol = hs_high < hs_low;
wire [10:0] dsp_width = hs_pol ? hs_low : hs_high;
// vertical counter
reg [9:0] v_cnt;
reg [9:0] vs_low, vs_high;
wire vs_pol = vs_high < vs_low;
wire [9:0] dsp_height = vs_pol ? vs_low : vs_high;
reg [10:0] v_cnt;
reg [10:0] vs_low, vs_high;
wire vs_pol = vs_high < vs_low;
wire [10:0] dsp_height = vs_pol ? vs_low : vs_high;
wire doublescan = (dsp_height>350);
reg auto_ce_pix;
always @(posedge clk_sys) begin
integer cnt = 0;
integer pixsz, pixcnt;
reg hs;
reg [15:0] cnt = 0;
reg [1:0] pixsz;
reg [1:0] pixcnt;
reg hs;
cnt <= cnt + 1;
cnt <= cnt + 1'd1;
hs <= HSync;
pixcnt <= pixcnt + 1;
pixcnt <= pixcnt + 1'd1;
if(pixcnt == pixsz) pixcnt <= 0;
auto_ce_pix <= !pixcnt;
if(hs && ~HSync) begin
cnt <= 0;
if (cnt <= 512) pixsz = 0;
else pixsz <= (cnt >> 9) - 1;
cnt <= 0;
if(cnt <= OSD_WIDTH_PADDED * 2) pixsz <= 0;
else if(cnt <= OSD_WIDTH_PADDED * 3) pixsz <= 1;
else if(cnt <= OSD_WIDTH_PADDED * 4) pixsz <= 2;
else pixsz <= 3;
pixcnt <= 0;
auto_ce_pix <= 1;
end
@@ -161,14 +167,22 @@ always @(posedge clk_sys) begin
end
// area in which OSD is being displayed
wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET;
wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH;
wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<<doublescan))>> 1) + OSD_Y_OFFSET;
wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<<doublescan);
wire [9:0] osd_hcnt = h_cnt - h_osd_start;
wire [9:0] osd_vcnt = v_cnt - v_osd_start;
wire [9:0] osd_hcnt_next = osd_hcnt + 2'd1; // one pixel offset for osd pixel
wire [9:0] osd_hcnt_next2 = osd_hcnt + 2'd2; // two pixel offset for osd byte address register
reg [10:0] h_osd_start;
reg [10:0] h_osd_end;
reg [10:0] v_osd_start;
reg [10:0] v_osd_end;
always @(posedge clk_sys) begin
h_osd_start <= ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET;
h_osd_end <= h_osd_start + OSD_WIDTH;
v_osd_start <= ((dsp_height- (OSD_HEIGHT<<doublescan))>> 1) + OSD_Y_OFFSET;
v_osd_end <= v_osd_start + (OSD_HEIGHT<<doublescan);
end
wire [10:0] osd_hcnt = h_cnt - h_osd_start;
wire [10:0] osd_vcnt = v_cnt - v_osd_start;
wire [10:0] osd_hcnt_next = osd_hcnt + 2'd1; // one pixel offset for osd pixel
wire [10:0] osd_hcnt_next2 = osd_hcnt + 2'd2; // two pixel offset for osd byte address register
reg osd_de;
reg [10:0] osd_buffer_addr;