Merge R800 multiplier by TobiFlex

This commit is contained in:
Gyorgy Szombathelyi
2020-08-21 15:33:57 +02:00
parent 6d9358c94d
commit 35ea9d4286
6 changed files with 175 additions and 31 deletions

2
README
View File

@@ -26,7 +26,7 @@
-- ****
-- Z80 compatible microprocessor core
--
-- Version : 0247
-- Version : 0250
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
-- All rights reserved
--

71
T80.vhd
View File

@@ -21,7 +21,7 @@
-- ****
-- Z80 compatible microprocessor core
--
-- Version : 0247
-- Version : 0250
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
-- All rights reserved
--
@@ -73,6 +73,7 @@
-- 0240 : Added interrupt ack fix by Mike Johnson, changed (IX/IY+d) timing and changed flags in GB mode
-- 0242 : Added I/O wait, fixed refresh address, moved some registers to RAM
-- 0247 : Fixed bus req/ack cycle
-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15
--
library IEEE;
@@ -118,6 +119,7 @@ entity T80 is
IntCycle_n : out std_logic;
IntE : out std_logic;
Stop : out std_logic;
R800_mode : in std_logic := '0';
out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255
REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A
@@ -155,6 +157,9 @@ architecture rtl of T80 is
signal IR : std_logic_vector(7 downto 0); -- Instruction register
signal ISet : std_logic_vector(1 downto 0); -- Instruction set selector
signal RegBusA_r : std_logic_vector(15 downto 0);
signal MULU_Prod32 : std_logic_vector(31 downto 0);
signal MULU_tmp : std_logic_vector(31 downto 0);
signal MULU_Fakt1 : std_logic_vector(15 downto 0);
signal ID16 : signed(15 downto 0);
signal Save_Mux : std_logic_vector(7 downto 0);
@@ -245,6 +250,8 @@ architecture rtl of T80 is
signal I_RRD : std_logic;
signal I_RXDD : std_logic;
signal I_INRC : std_logic;
signal I_MULUB : std_logic;
signal I_MULU : std_logic;
signal SetWZ : std_logic_vector(1 downto 0);
signal SetDI : std_logic;
signal SetEI : std_logic;
@@ -326,6 +333,8 @@ begin
I_RLD => I_RLD,
I_RRD => I_RRD,
I_INRC => I_INRC,
I_MULUB => I_MULUB,
I_MULU => I_MULU,
SetWZ => SetWZ,
SetDI => SetDI,
SetEI => SetEI,
@@ -333,7 +342,8 @@ begin
Halt => Halt,
NoRead => NoRead_int,
Write => Write_int,
XYbit_undoc => XYbit_undoc);
XYbit_undoc => XYbit_undoc,
R800_mode => R800_mode);
alu : T80_ALU
generic map(
@@ -874,6 +884,42 @@ begin
end if;
end process;
---------------------------------------------------------------------------
--
-- Multiply
--
---------------------------------------------------------------------------
process (CLK_n, ACC, RegBusB, MULU_tmp, MULU_Fakt1, MULU_Prod32)
begin
MULU_tmp(31 downto 12) <= std_logic_vector((unsigned(MULU_Fakt1)*unsigned(MULU_Prod32(3 downto 0)))+unsigned("0000"&MULU_Prod32(31 downto 16)));
MULU_tmp(11 downto 0) <= MULU_Prod32(15 downto 4);
if rising_edge(CLK_n) then
if ClkEn = '1' then
if T_Res='1' then
if I_MULUB='1' then
MULU_Prod32(7 downto 0) <= ACC;
MULU_Prod32(15 downto 8) <= "--------";
MULU_Prod32(31 downto 16) <= X"0000";
MULU_Fakt1(7 downto 0) <= "00000000";
if Set_BusB_To(0) = '1' then
MULU_Fakt1(15 downto 8) <= RegBusB(7 downto 0);
else
MULU_Fakt1(15 downto 8) <= RegBusB(15 downto 8);
end if;
else
MULU_Prod32(15 downto 0) <= RegBusA;
MULU_Prod32(31 downto 16) <= X"0000";
MULU_Fakt1 <= RegBusB;
end if;
else
MULU_Prod32 <= MULU_tmp;
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------
--
-- BC('), DE('), HL('), IX and IY
@@ -929,7 +975,7 @@ begin
(TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and IncDec_16(1 downto 0) = "10" else
-- EX HL,DL
Alternate & "10" when ExchangeDH = '1' and TState = 3 else
Alternate & "01" when ExchangeDH = '1' and TState = 4 else
Alternate & "01" when (ExchangeDH = '1' or I_MULU = '1') and TState = 4 else
-- LDHLSP
"010" when LDHLSP = '1' and TState = 4 else
-- Bus A / Write
@@ -944,7 +990,7 @@ begin
ID16 <= signed(RegBusA) - 1 when IncDec_16(3) = '1' else
signed(RegBusA) + 1;
process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r,
process (Save_ALU_r, Auto_Wait_t1, ALU_OP_r, Read_To_Reg_r, I_MULU, T_Res,
ExchangeDH, IncDec_16, MCycle, TState, Wait_n, LDHLSP)
begin
RegWEH <= '0';
@@ -959,6 +1005,11 @@ begin
end case;
end if;
if I_MULU = '1' and (T_Res = '1' or TState = 4) then -- TState = 4 DE write
RegWEH <= '1';
RegWEL <= '1';
end if;
if ExchangeDH = '1' and (TState = 3 or TState = 4) then
RegWEH <= '1';
RegWEL <= '1';
@@ -981,12 +1032,22 @@ begin
TmpAddr2 <= std_logic_vector(unsigned(signed(SP) + signed(Save_Mux)));
process (Save_Mux, RegBusB, RegBusA_r, ID16,
process (Save_Mux, RegBusB, RegBusA_r, ID16, I_MULU, MULU_Prod32, MULU_tmp, T_Res,
ExchangeDH, IncDec_16, MCycle, TState, Wait_n, LDHLSP, TmpAddr2)
begin
RegDIH <= Save_Mux;
RegDIL <= Save_Mux;
if I_MULU = '1' then
if T_Res = '1' then
RegDIH <= MULU_Prod32(31 downto 24);
RegDIL <= MULU_Prod32(23 downto 16);
else
RegDIH <= MULU_tmp(15 downto 8); -- TState = 4 DE write
RegDIL <= MULU_tmp(7 downto 0);
end if;
end if;
if LDHLSP = '1' and MCycle = "010" and TState = 4 then
RegDIH <= TmpAddr2(15 downto 8);
RegDIL <= TmpAddr2(7 downto 0);

View File

@@ -19,7 +19,7 @@
-- ****
-- Z80 compatible microprocessor core
--
-- Version : 0242
-- Version : 0250
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
-- All rights reserved
--
@@ -69,6 +69,7 @@
-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes
-- 0240mj1 fix for HL inc/dec for INI, IND, INIR, INDR, OUTI, OUTD, OTIR, OTDR
-- 0242 : Fixed I/O instruction timing, cleanup
-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15
--
library IEEE;
@@ -140,6 +141,8 @@ entity T80_MCode is
I_RLD : out std_logic;
I_RRD : out std_logic;
I_INRC : out std_logic;
I_MULUB : out std_logic;
I_MULU : out std_logic;
SetWZ : out std_logic_vector(1 downto 0);
SetDI : out std_logic;
SetEI : out std_logic;
@@ -147,7 +150,8 @@ entity T80_MCode is
Halt : out std_logic;
NoRead : out std_logic;
Write : out std_logic;
XYbit_undoc : out std_logic
XYbit_undoc : out std_logic;
R800_mode : in std_logic
);
end T80_MCode;
@@ -185,7 +189,7 @@ architecture rtl of T80_MCode is
begin
process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State)
process (IR, ISet, MCycle, F, NMICycle, IntCycle, XY_State, R800_mode)
variable DDD : std_logic_vector(2 downto 0);
variable SSS : std_logic_vector(2 downto 0);
variable DPair : std_logic_vector(1 downto 0);
@@ -243,6 +247,8 @@ begin
I_RLD <= '0';
I_RRD <= '0';
I_INRC <= '0';
I_MULUB <= '0';
I_MULU <= '0';
SetDI <= '0';
SetEI <= '0';
IMode <= "11";
@@ -1769,13 +1775,13 @@ begin
| "10101100"|"10101101"|"10101110"|"10101111"
| "10110100"|"10110101"|"10110110"|"10110111"
| "10111100"|"10111101"|"10111110"|"10111111"
|"11000000"|"11000001"|"11000010"|"11000011"|"11000100"|"11000101"|"11000110"|"11000111"
|"11001000"|"11001001"|"11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111"
|"11010000"|"11010001"|"11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111"
|"11011000"|"11011001"|"11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111"
|"11000000"| "11000010" |"11000100"|"11000101"|"11000110"|"11000111"
|"11001000"| "11001010"|"11001011"|"11001100"|"11001101"|"11001110"|"11001111"
|"11010000"| "11010010"|"11010011"|"11010100"|"11010101"|"11010110"|"11010111"
|"11011000"| "11011010"|"11011011"|"11011100"|"11011101"|"11011110"|"11011111"
|"11100000"|"11100001"|"11100010"|"11100011"|"11100100"|"11100101"|"11100110"|"11100111"
|"11101000"|"11101001"|"11101010"|"11101011"|"11101100"|"11101101"|"11101110"|"11101111"
|"11110000"|"11110001"|"11110010"|"11110011"|"11110100"|"11110101"|"11110110"|"11110111"
|"11110000"|"11110001"|"11110010" |"11110100"|"11110101"|"11110110"|"11110111"
|"11111000"|"11111001"|"11111010"|"11111011"|"11111100"|"11111101"|"11111110"|"11111111" =>
null; -- NOP, undocumented
when "01110111"|"01111111" =>
@@ -2159,6 +2165,46 @@ begin
TStates <= "101";
when others => null;
end case;
when "11000001"|"11001001"|"11010001"|"11011001" =>
--R800 MULUB
if R800_mode = '1' then
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
NoRead <= '1';
I_MULUB <= '1';
Set_BusB_To(2 downto 0) <= IR(5 downto 3);
Set_BusB_To(3) <= '0';
when 2 =>
NoRead <= '1';
I_MULU <= '1';
Set_BusA_To(2 downto 0) <= "100";
when others => null;
end case;
end if;
when "11000011"|"11110011" =>
--R800 MULUW
if R800_mode = '1' then
MCycles <= "010";
case to_integer(unsigned(MCycle)) is
when 1 =>
NoRead <= '1';
if DPAIR = "11" then
Set_BusB_To(3 downto 0) <= "1000";
else
Set_BusB_To(2 downto 1) <= DPAIR;
Set_BusB_To(0) <= '0';
Set_BusB_To(3) <= '0';
end if;
Set_BusA_To(2 downto 0) <= "100";
when 2 =>
TStates <= "101";
NoRead <= '1';
I_MULU <= '1';
Set_BusA_To(2 downto 0) <= "100";
when others => null;
end case;
end if;
end case;
end case;

View File

@@ -11,7 +11,7 @@
--
-- Z80 compatible microprocessor core
--
-- Version : 0242
-- Version : 0250
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
@@ -105,6 +105,7 @@ package T80_Pack is
IntCycle_n : out std_logic;
IntE : out std_logic;
Stop : out std_logic;
R800_mode : in std_logic := '0';
out0 : in std_logic := '0'; -- 0 => OUT(C),0, 1 => OUT(C),255
REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A
DIRSet : in std_logic := '0';
@@ -199,6 +200,8 @@ package T80_Pack is
I_RLD : out std_logic;
I_RRD : out std_logic;
I_INRC : out std_logic;
I_MULUB : out std_logic;
I_MULU : out std_logic;
SetWZ : out std_logic_vector(1 downto 0);
SetDI : out std_logic;
SetEI : out std_logic;
@@ -206,7 +209,8 @@ package T80_Pack is
Halt : out std_logic;
NoRead : out std_logic;
Write : out std_logic;
XYbit_undoc : out std_logic
XYbit_undoc : out std_logic;
R800_mode : in std_logic
);
end component;

View File

@@ -10,7 +10,7 @@
--
-- Z80 compatible microprocessor core, asynchronous top level
--
-- Version : 0247
-- Version : 0250
--
-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
--
@@ -67,6 +67,11 @@
--
-- 0247 : Fixed bus req/ack cycle
--
-- 0247a: 7th of September, 2003 by Kazuhiro Tsujikawa (tujikawa@hat.hi-ho.ne.jp)
-- Fixed IORQ_n, RD_n, WR_n bus timing
--
-- 0250 : Added R800 Multiplier by TobiFlex 2017.10.15
--
library IEEE;
use IEEE.std_logic_1164.all;
@@ -75,10 +80,12 @@ use work.T80_Pack.all;
entity T80a is
generic(
Mode : integer := 0 -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
IOWait : integer := 1 -- 0 => Single I/O cycle, 1 => Std I/O cycle
);
port(
RESET_n : in std_logic;
R800_mode : in std_logic;
CLK_n : in std_logic;
WAIT_n : in std_logic;
INT_n : in std_logic;
@@ -92,8 +99,8 @@ entity T80a is
RFSH_n : out std_logic;
HALT_n : out std_logic;
BUSAK_n : out std_logic;
A : out std_logic_vector(15 downto 0);
D : inout std_logic_vector(7 downto 0)
A : out std_logic_vector(15 downto 0);
D : inout std_logic_vector(7 downto 0)
);
end T80a;
@@ -107,12 +114,14 @@ architecture rtl of T80a is
signal Write : std_logic;
signal MREQ : std_logic;
signal MReq_Inhibit : std_logic;
signal IReq_Inhibit : std_logic; -- 0247a
signal Req_Inhibit : std_logic;
signal RD : std_logic;
signal MREQ_n_i : std_logic;
signal IORQ_n_i : std_logic;
signal RD_n_i : std_logic;
signal WR_n_i : std_logic;
signal WR_n_j : std_logic; -- 0247a
signal RFSH_n_i : std_logic;
signal BUSAK_n_i : std_logic;
signal A_i : std_logic_vector(15 downto 0);
@@ -129,11 +138,12 @@ begin
BUSAK_n <= BUSAK_n_i;
MREQ_n_i <= not MREQ or (Req_Inhibit and MReq_Inhibit);
RD_n_i <= not RD or Req_Inhibit;
WR_n_j <= WR_n_i; -- 0247a
MREQ_n <= MREQ_n_i when BUSAK_n_i = '1' else 'Z';
IORQ_n <= IORQ_n_i when BUSAK_n_i = '1' else 'Z';
IORQ_n <= IORQ_n_i or IReq_Inhibit when BUSAK_n_i = '1' else 'Z'; -- 0247a
RD_n <= RD_n_i when BUSAK_n_i = '1' else 'Z';
WR_n <= WR_n_i when BUSAK_n_i = '1' else 'Z';
WR_n <= WR_n_j when BUSAK_n_i = '1' else 'Z'; -- 0247a
RFSH_n <= RFSH_n_i when BUSAK_n_i = '1' else 'Z';
A <= A_i when BUSAK_n_i = '1' else (others => 'Z');
D <= DO when Write = '1' and BUSAK_n_i = '1' else (others => 'Z');
@@ -150,8 +160,9 @@ begin
u0 : T80
generic map(
Mode => Mode,
IOWait => 1)
IOWait => IOWait)
port map(
R800_mode => R800_mode,
CEN => CEN,
M1_n => M1_n,
IORQ => IORQ,
@@ -184,24 +195,40 @@ begin
end if;
end process;
process (Reset_s,CLK_n)
process (CLK_n) -- 0247a
begin
if CLK_n'event and CLK_n = '1' then
IReq_Inhibit <= not IORQ;
end if;
end process;
process (Reset_s,CLK_n) -- 0247a
begin
if Reset_s = '0' then
WR_n_i <= '1';
elsif CLK_n'event and CLK_n = '1' then
WR_n_i <= '1';
if TState = "001" then -- To short for IO writes !!!!!!!!!!!!!!!!!!!
WR_n_i <= not Write;
elsif CLK_n'event and CLK_n = '0' then
if (IORQ = '0') then
if TState = "010" then
WR_n_i <= not Write;
elsif Tstate = "011" then
WR_n_i <= '1';
end if;
else
if TState = "001" and IORQ_n_i = '0' then
WR_n_i <= not Write;
elsif Tstate = "011" then
WR_n_i <= '1';
end if;
end if;
end if;
end process;
process (Reset_s,CLK_n)
process (Reset_s,CLK_n) -- 0247a
begin
if Reset_s = '0' then
Req_Inhibit <= '0';
elsif CLK_n'event and CLK_n = '1' then
if MCycle = "001" and TState = "010" then
if MCycle = "001" and TState = "010" and wait_s = '1' then
Req_Inhibit <= '1';
else
Req_Inhibit <= '0';
@@ -246,9 +273,13 @@ begin
end if;
else
if TState = "001" and NoRead = '0' then
RD <= not Write;
IORQ_n_i <= not IORQ;
MREQ <= not IORQ;
if IORQ = '0' then
RD <= not Write;
elsif IORQ_n_i = '0' then
RD <= not Write;
end if;
end if;
if TState = "011" then
RD <= '0';

View File

@@ -83,6 +83,7 @@ entity T80pa is
A : out std_logic_vector(15 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
R800_mode : in std_logic := '0';
REG : out std_logic_vector(211 downto 0); -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A
DIRSet : in std_logic := '0';
DIR : in std_logic_vector(211 downto 0) := (others => '0') -- IFF2, IFF1, IM, IY, HL', DE', BC', IX, HL, DE, BC, PC, SP, R, I, F', A', F, A
@@ -135,6 +136,7 @@ begin
MC => MCycle,
TS => TState,
OUT0 => OUT0,
R800_mode => R800_mode,
IntCycle_n => IntCycle_n,
DIRSet => DIRSet,
DIR => DIR