Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: ben0109/Papilio-Master-System
base: ea22870bd6
...
head fork: ben0109/Papilio-Master-System
compare: 1e3dd2aa81
  • 8 commits
  • 13 files changed
  • 0 commit comments
  • 1 contributor
View
170 vhdl/src/main.vhd
@@ -6,10 +6,11 @@ entity main is
port (
clk: in STD_LOGIC;
- ram_ce: out STD_LOGIC;
- ram_be: out STD_LOGIC;
- ram_oe: out STD_LOGIC;
- ram_we: out STD_LOGIC;
+ ram_cs_n: out STD_LOGIC;
+ ram_we_n: out STD_LOGIC;
+ ram_oe_n: out STD_LOGIC;
+ ram_ble_n: out STD_LOGIC;
+ ram_bhe_n: out STD_LOGIC;
ram_a: out STD_LOGIC_VECTOR(18 downto 0);
ram_d: inout STD_LOGIC_VECTOR(15 downto 0);
@@ -18,9 +19,9 @@ entity main is
audio_out: out STD_LOGIC;
- red: out STD_LOGIC_VECTOR(1 downto 0);
- green: out STD_LOGIC_VECTOR(1 downto 0);
- blue: out STD_LOGIC_VECTOR(1 downto 0);
+ red: out STD_LOGIC;
+ green: out STD_LOGIC;
+ blue: out STD_LOGIC;
hsync: out STD_LOGIC;
vsync: out STD_LOGIC;
@@ -44,7 +45,7 @@ architecture Behavioral of main is
end component;
-- component dummy_z80 is
- component T80s is
+ component T80se is
generic(
Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
T2Write : integer := 0; -- 0 => WR_n active in T3, /=0 => WR_n active in T2
@@ -53,8 +54,9 @@ architecture Behavioral of main is
port(
RESET_n: in std_logic;
CLK_n: in std_logic;
+ CLKEN: in std_logic;
WAIT_n: in std_logic;
- INT_n: in std_logic;
+ INT_n: in std_logic;
NMI_n: in std_logic;
BUSRQ_n: in std_logic;
M1_n: out std_logic;
@@ -207,11 +209,11 @@ architecture Behavioral of main is
signal io_WR_n: std_logic;
signal io_D_out: std_logic_vector(7 downto 0);
- signal ram_RD_n: std_logic;
+-- signal ram_RD_n: std_logic;
signal ram_WR_n: std_logic;
signal ram_D_out: std_logic_vector(7 downto 0);
- signal rom_RD_n: std_logic;
+-- signal rom_RD_n: std_logic;
signal rom_WR_n: std_logic;
signal rom_D_out: std_logic_vector(7 downto 0);
@@ -219,7 +221,7 @@ architecture Behavioral of main is
signal spi_WR_n: std_logic;
signal spi_D_out: std_logic_vector(7 downto 0);
- signal boot_rom_RD_n: std_logic;
+-- signal boot_rom_RD_n: std_logic;
signal boot_rom_D_out: std_logic_vector(7 downto 0);
signal uart_WR_n: std_logic;
@@ -231,6 +233,9 @@ architecture Behavioral of main is
signal y: unsigned(7 downto 0);
+ signal redV: std_logic_vector(1 downto 0);
+ signal greenV: std_logic_vector(1 downto 0);
+ signal blueV: std_logic_vector(1 downto 0);
@@ -254,12 +259,13 @@ begin
-- z80_inst: dummy_z80
- z80_inst: T80s
+ z80_inst: T80se
port map(
RESET_n => RESET_n,
CLK_n => clk_cpu,
+ CLKEN => '1',
WAIT_n => '1',
- INT_n => '1',--IRQ_n,
+ INT_n => IRQ_n,
NMI_n => '1',
BUSRQ_n => '1',
M1_n => open,
@@ -285,10 +291,14 @@ begin
color => color,
hsync => hsync,
vsync => vsync,
- red => red,
- green => green,
- blue => blue
+ red => redV,
+ green => greenV,
+ blue => blueV
);
+
+ red <= redV(1);
+ green <= greenV(1);
+ blue <= blueV(1);
vdp_inst: vdp
port map (
@@ -340,7 +350,7 @@ begin
ram_inst: ram
port map(
clk => clk_cpu,
- RD_n => ram_RD_n,
+ RD_n => '0',--ram_RD_n,
WR_n => ram_WR_n,
A => A(12 downto 0),
D_in => D_in,
@@ -349,7 +359,7 @@ begin
boot_rom_inst: boot_rom
port map(
clk => clk_cpu,
- RD_n => boot_rom_RD_n,
+ RD_n => '0',--boot_rom_RD_n,
A => A(12 downto 0),
D_out => boot_rom_D_out);
@@ -384,89 +394,67 @@ begin
-- glue logic
- reset_n <= '0' when reset_counter>0 else '1';
-
- process (clk_cpu)
- begin
- if rising_edge(clk_cpu) then
- if reset_counter>0 then
- reset_counter <= reset_counter - 1;
- end if;
- end if;
- end process;
-
- with io_n&A select
- vdp_WR_n <= WR_n when "0--------10------",
- '1' when others;
+ vdp_WR_n <= WR_n when io_n='0' and A(7 downto 6)="10" else '1';
- with io_n&A select
- vdp_RD_n <= RD_n when "0--------01------",
- RD_n when "0--------10------",
- '1' when others;
-
- with io_n&A select
- psg_WR_n <= WR_n when "0--------01------",
- '1' when others;
+ vdp_RD_n <= RD_n when io_n='0' and (A(7 downto 6)="01" or A(7 downto 6)="10") else '1';
+
+ psg_WR_n <= WR_n when io_n='0' and A(7 downto 6)="01" else '1';
- with io_n&A select
- ctl_WR_n <= WR_n when "0--------00-----0",
- '1' when others;
+ ctl_WR_n <= WR_n when io_n='0' and A(7 downto 6)="00" and A(0)='0' else '1';
- with io_n&A select
- io_WR_n <= WR_n when "0--------00-----1",
- '1' when others;
+ io_WR_n <= WR_n when io_n='0' and A(7 downto 6)="00" and A(0)='1' else '1';
- with io_n&A select
- io_RD_n <= RD_n when "0--------11------",
- '1' when others;
-
- with io_n&A select
- ram_WR_n <= WR_n when "111--------------",
- '1' when others;
+ io_RD_n <= RD_n when io_n='0' and A(7 downto 6)="11" else '1';
- with io_n&A select
- spi_RD_n <= bootloader or RD_n when "0--------00------",
- '1' when others;
+ spi_RD_n <= bootloader or RD_n when io_n='0' and A(7 downto 5)="000" else '1';
- with io_n&A select
- spi_WR_n <= bootloader or WR_n when "0--------110-----",
- '1' when others;
+ spi_WR_n <= bootloader or WR_n when io_n='0' and A(7 downto 5)="110" else '1';
- with io_n&A select
- uart_WR_n<= bootloader or WR_n when "0--------111-----",
- '1' when others;
+ uart_WR_n<= bootloader or WR_n when io_n='0' and A(7 downto 5)="111" else '1';
+
+ ram_WR_n <= WR_n when io_n='1' and A(15 downto 14)="11" else '1';
- with io_n&A select
- rom_WR_n <= bootloader or WR_n when "110--------------",
- '1' when others;
+ rom_WR_n <= bootloader or WR_n when io_n='1' and A(15 downto 14)="10" else '1';
process (clk_cpu)
begin
if rising_edge(clk_cpu) then
- if ctl_WR_n='0' then
- -- memory control
+ -- memory control
+ if reset_counter>0 then
+ reset_counter <= reset_counter - 1;
+ elsif ctl_WR_n='0' then
if bootloader='0' then
- bootloader <= D_in(7);
+ bootloader <= '1';
+ reset_counter <= (others=>'1');
end if;
end if;
end if;
end process;
+ reset_n <= '0' when reset_counter>0 else '1';
+
+ irom_D_out <= boot_rom_D_out when bootloader='0' and A(15 downto 14)="00" else rom_D_out;
- with bootloader select
- irom_D_out <= boot_rom_D_out when '0',
- rom_D_out when others;
-
- with io_n&A select
- D_out <= spi_D_out when "0--------000-----",
- uart_D_out when "0--------001-----",
- vdp_D_out when "0--------01------",
- vdp_D_out when "0--------10------",
- io_D_out when "0--------11------",
- irom_D_out when "100--------------",
- irom_D_out when "101--------------",
- irom_D_out when "110--------------",
- ram_D_out when "111--------------",
- (others=>'-') when others;
+ process (io_n,A,spi_D_out,uart_D_out,vdp_D_out,vdp_D_out,io_D_out,irom_D_out,irom_D_out,irom_D_out,ram_D_out)
+ begin
+ if io_n='0' then
+ case A(7 downto 5) is
+ when "000" =>
+ D_out <= spi_D_out;
+ when "001" =>
+ D_out <= uart_D_out;
+ when "110"|"111" =>
+ D_out <= io_D_out;
+ when others =>
+ D_out <= vdp_D_out;
+ end case;
+ else
+ if A(15 downto 14)="11" then
+ D_out <= ram_D_out;
+ else
+ D_out <= irom_D_out;
+ end if;
+ end if;
+ end process;
-- external ram control
@@ -485,10 +473,12 @@ begin
end if;
end process;
- ram_ce <= '1';
- ram_be <= '0';
- ram_oe <= RD_n;
- ram_we <= rom_WR_n;
+ ram_cs_n <= '0';
+ ram_oe_n <= RD_n;
+ ram_we_n <= rom_WR_n;
+ ram_ble_n <= '0';
+ ram_bhe_n <= '0';
+
ram_a(13 downto 0) <= A(13 downto 0);
process (A,bank0,bank1,bank2)
begin
@@ -508,9 +498,7 @@ begin
end case;
end process;
- with RD_n select
- ram_d(7 downto 0) <= (others=>'Z') when '0',
- D_in when others;
+ ram_d(7 downto 0) <= (others=>'Z') when RD_n='0' else D_in;
ram_d(15 downto 8) <= (others=>'Z');
rom_D_out <= ram_d(7 downto 0);
View
138 vhdl/src/papilio_plus.ucf
@@ -0,0 +1,138 @@
+# UCF file for the Papilio Plus board
+# Generated by pin_converter, written by Kevin Lindsey
+# https://github.com/thelonious/papilio_pins/tree/development/pin_converter
+
+# Main board wing pin [] to FPGA pin Pxx map
+# -------C------- -------B------- -------A-------
+# [GND] [C00] P114 [GND] [B00] P99 P100 [A15]
+# [2V5] [C01] P115 [2V5] [B01] P97 P98 [A14]
+# [3V3] [C02] P116 [3V3] [B02] P92 P93 [A13]
+# [5V0] [C03] P117 [5V0] [B03] P87 P88 [A12]
+# [C04] P118 [B04] P84 P85 [A11] [5V0]
+# [C05] P119 [B05] P82 P83 [A10] [3V3]
+# [C06] P120 [B06] P80 P81 [A09] [2V5]
+# [C07] P121 [B07] P78 P79 [A08] [GND]
+# [GND] [C08] P123 [GND] [B08] P74 P75 [A07]
+# [2V5] [C09] P124 [2V5] [B09] P95 P67 [A06]
+# [3V3] [C10] P126 [3V3] [B10] P62 P66 [A05]
+# [5V0] [C11] P127 [5V0] [B11] P59 P61 [A04]
+# [C12] P131 [B12] P57 P58 [A03] [5V0]
+# [C13] P132 [B13] P55 P56 [A02] [3V3]
+# [C14] P133 [B14] P50 P51 [A01] [2V5]
+# [C15] P134 [B15] P47 P48 [A00] [GND]
+
+## Prohibit the automatic placement of pins that are connected to VCC or GND for configuration.
+CONFIG PROHIBIT=P144;
+CONFIG PROHIBIT=P69;
+CONFIG PROHIBIT=P60;
+
+NET CLK LOC="P94" | IOSTANDARD=LVTTL | PERIOD=31.25ns; # CLK
+
+#NET RX LOC="P101" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # RX
+NET TX LOC="P105" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # TX
+
+NET "joy_1<5>" LOC="P48" | IOSTANDARD=LVTTL | PULLUP ;
+NET "joy_1_gnd" LOC="P51" | IOSTANDARD=LVTTL ;
+NET "joy_1<4>" LOC="P56" | IOSTANDARD=LVTTL | PULLUP ;
+#NET A(3) LOC="P58" | IOSTANDARD=LVTTL; # A3
+NET "joy_1<3>" LOC="P61" | IOSTANDARD=LVTTL | PULLUP ;
+NET "joy_1<2>" LOC="P66" | IOSTANDARD=LVTTL | PULLUP ;
+NET "joy_1<1>" LOC="P67" | IOSTANDARD=LVTTL | PULLUP ;
+NET "joy_1<0>" LOC="P75" | IOSTANDARD=LVTTL | PULLUP ;
+
+NET "vsync" LOC="P79" | IOSTANDARD=LVTTL; # A8
+NET "hsync" LOC="P81" | IOSTANDARD=LVTTL; # A9
+NET "blue" LOC="P83" | IOSTANDARD=LVTTL; # A10
+NET "audio_out" LOC="P85" | IOSTANDARD=LVTTL; # A11
+#NET A(12) LOC="P88" | IOSTANDARD=LVTTL; # A12
+#NET A(13) LOC="P93" | IOSTANDARD=LVTTL; # A13
+NET "green" LOC="P98" | IOSTANDARD=LVTTL; # A14
+NET "red" LOC="P100" | IOSTANDARD=LVTTL; # A15
+
+#NET B(0) LOC="P99" | IOSTANDARD=LVTTL; # B0
+NET "spi_do" LOC="P97" | IOSTANDARD=LVTTL; # B1
+NET "spi_sclk" LOC="P92" | IOSTANDARD=LVTTL; # B2
+NET "spi_di" LOC="P87" | IOSTANDARD=LVTTL; # B3
+NET "spi_cs_n" LOC="P84" | IOSTANDARD=LVTTL; # B4
+#NET B(5) LOC="P82" | IOSTANDARD=LVTTL; # B5
+#NET B(6) LOC="P80" | IOSTANDARD=LVTTL; # B6
+#NET B(7) LOC="P78" | IOSTANDARD=LVTTL; # B7
+
+#NET B(8) LOC="P74" | IOSTANDARD=LVTTL; # B8
+#NET B(9) LOC="P95" | IOSTANDARD=LVTTL; # B9
+#NET B(10) LOC="P62" | IOSTANDARD=LVTTL; # B10
+#NET B(11) LOC="P59" | IOSTANDARD=LVTTL; # B11
+#NET B(12) LOC="P57" | IOSTANDARD=LVTTL; # B12
+#NET B(13) LOC="P55" | IOSTANDARD=LVTTL; # B13
+#NET B(14) LOC="P50" | IOSTANDARD=LVTTL; # B14
+#NET B(15) LOC="P47" | IOSTANDARD=LVTTL; # B15
+
+#NET C(0) LOC="P114" | IOSTANDARD=LVTTL; # C0
+#NET C(1) LOC="P115" | IOSTANDARD=LVTTL; # C1
+#NET C(2) LOC="P116" | IOSTANDARD=LVTTL; # C2
+#NET C(3) LOC="P117" | IOSTANDARD=LVTTL; # C3
+#NET C(4) LOC="P118" | IOSTANDARD=LVTTL; # C4
+#NET C(5) LOC="P119" | IOSTANDARD=LVTTL; # C5
+#NET C(6) LOC="P120" | IOSTANDARD=LVTTL; # C6
+#NET C(7) LOC="P121" | IOSTANDARD=LVTTL; # C7
+
+#NET C(8) LOC="P123" | IOSTANDARD=LVTTL; # C8
+#NET C(9) LOC="P124" | IOSTANDARD=LVTTL; # C9
+#NET C(10) LOC="P126" | IOSTANDARD=LVTTL; # C10
+#NET C(11) LOC="P127" | IOSTANDARD=LVTTL; # C11
+#NET C(12) LOC="P131" | IOSTANDARD=LVTTL; # C12
+#NET C(13) LOC="P132" | IOSTANDARD=LVTTL; # C13
+#NET C(14) LOC="P133" | IOSTANDARD=LVTTL; # C14
+#NET C(15) LOC="P134" | IOSTANDARD=LVTTL; # C15
+
+NET ram_a(0) LOC="P7" | IOSTANDARD=LVTTL; # ADDR0
+NET ram_a(1) LOC="P6" | IOSTANDARD=LVTTL; # ADDR1
+NET ram_a(2) LOC="P8" | IOSTANDARD=LVTTL; # ADDR2
+NET ram_a(3) LOC="P9" | IOSTANDARD=LVTTL; # ADDR3
+NET ram_a(4) LOC="P10" | IOSTANDARD=LVTTL; # ADDR4
+NET ram_a(5) LOC="P141" | IOSTANDARD=LVTTL; # ADDR5
+NET ram_a(6) LOC="P140" | IOSTANDARD=LVTTL; # ADDR6
+NET ram_a(7) LOC="P139" | IOSTANDARD=LVTTL; # ADDR7
+NET ram_a(8) LOC="P138" | IOSTANDARD=LVTTL; # ADDR8
+NET ram_a(9) LOC="P137" | IOSTANDARD=LVTTL; # ADDR9
+NET ram_a(10) LOC="P46" | IOSTANDARD=LVTTL; # ADDR10
+NET ram_a(11) LOC="P45" | IOSTANDARD=LVTTL; # ADDR11
+NET ram_a(12) LOC="P44" | IOSTANDARD=LVTTL; # ADDR12
+NET ram_a(13) LOC="P43" | IOSTANDARD=LVTTL; # ADDR13
+NET ram_a(14) LOC="P41" | IOSTANDARD=LVTTL; # ADDR14
+NET ram_a(15) LOC="P29" | IOSTANDARD=LVTTL; # ADDR15
+NET ram_a(16) LOC="P30" | IOSTANDARD=LVTTL; # ADDR16
+NET ram_a(17) LOC="P32" | IOSTANDARD=LVTTL; # ADDR17
+NET ram_a(18) LOC="P40" | IOSTANDARD=LVTTL; # ADDR18
+
+NET ram_d(0) LOC="P12" | IOSTANDARD=LVTTL; # DATA0
+NET ram_d(1) LOC="P14" | IOSTANDARD=LVTTL; # DATA1
+NET ram_d(2) LOC="P15" | IOSTANDARD=LVTTL; # DATA2
+NET ram_d(3) LOC="P16" | IOSTANDARD=LVTTL; # DATA3
+NET ram_d(4) LOC="P5" | IOSTANDARD=LVTTL; # DATA4
+NET ram_d(5) LOC="P2" | IOSTANDARD=LVTTL; # DATA5
+NET ram_d(6) LOC="P1" | IOSTANDARD=LVTTL; # DATA6
+NET ram_d(7) LOC="P143" | IOSTANDARD=LVTTL; # DATA7
+#NET ram_d(8) LOC="P39" | IOSTANDARD=LVTTL; # DATA8
+#NET ram_d(9) LOC="P35" | IOSTANDARD=LVTTL; # DATA9
+#NET ram_d(10) LOC="P34" | IOSTANDARD=LVTTL; # DATA10
+#NET ram_d(11) LOC="P33" | IOSTANDARD=LVTTL; # DATA11
+#NET ram_d(12) LOC="P17" | IOSTANDARD=LVTTL; # DATA12
+#NET ram_d(13) LOC="P21" | IOSTANDARD=LVTTL; # DATA13
+#NET ram_d(14) LOC="P22" | IOSTANDARD=LVTTL; # DATA14
+#NET ram_d(15) LOC="P23" | IOSTANDARD=LVTTL; # DATA15
+
+NET ram_CS_n LOC="P11" | IOSTANDARD=LVTTL; # nCS
+NET ram_WE_n LOC="P142" | IOSTANDARD=LVTTL; # nWE
+NET ram_OE_n LOC="P27" | IOSTANDARD=LVTTL; # nOE
+NET ram_BLE_n LOC="P24" | IOSTANDARD=LVTTL; # nBLE
+NET ram_BHE_n LOC="P26" | IOSTANDARD=LVTTL; # nBHE
+
+#NET JTAG_TMS LOC="P107" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TMS
+#NET JTAG_TCK LOC="P109" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TCK
+#NET JTAG_TDI LOC="P110" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TDI
+#NET JTAG_TDO LOC="P106" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # JTAG_TDO
+#NET FLASH_CS LOC="P38" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CS
+#NET FLASH_CK LOC="P70" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_CK
+#NET FLASH_SI LOC="P64" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST; # FLASH_SI
+#NET FLASH_SO LOC="P65" | IOSTANDARD=LVTTL | DRIVE=8 | SLEW=FAST | PULLUP; # FLASH_SO
View
17 vhdl/src/vdp_background.vhd
@@ -42,7 +42,7 @@ begin
process (clk) begin
if (rising_edge(clk)) then
if (reset='1') then
- x <= scroll_x+248;
+ x <= 248-scroll_x;
else
x <= x + 1;
end if;
@@ -101,10 +101,17 @@ begin
if (rising_edge(clk)) then
case x(2 downto 0) is
when "111" =>
- shift0 <= data0;
- shift1 <= data1;
- shift2 <= data2;
- shift3 <= vram_D;
+ if flip_x='0' then
+ shift0 <= data0;
+ shift1 <= data1;
+ shift2 <= data2;
+ shift3 <= vram_D;
+ else
+ shift0 <= data0(0)&data0(1)&data0(2)&data0(3)&data0(4)&data0(5)&data0(6)&data0(7);
+ shift1 <= data1(0)&data1(1)&data1(2)&data1(3)&data1(4)&data1(5)&data1(6)&data1(7);
+ shift2 <= data2(0)&data2(1)&data2(2)&data2(3)&data2(4)&data2(5)&data2(6)&data2(7);
+ shift3 <= vram_D(0)&vram_D(1)&vram_D(2)&vram_D(3)&vram_D(4)&vram_D(5)&vram_D(6)&vram_D(7);
+ end if;
color(4) <= palette;
priority <= priority_latch;
when others =>
View
19 vhdl/src/vdp_main.vhd
@@ -64,6 +64,7 @@ architecture Behavioral of vdp_main is
color: out std_logic_vector(3 downto 0));
end component;
+ signal bg_y: unsigned(7 downto 0);
signal bg_vram_A: std_logic_vector(13 downto 0);
signal bg_color: std_logic_vector(4 downto 0);
signal bg_priority: std_logic;
@@ -76,14 +77,24 @@ architecture Behavioral of vdp_main is
signal hbl_irq: std_logic;
begin
+
+ process (y,bg_scroll_y)
+ variable sum: unsigned(8 downto 0);
+ begin
+ sum := ('0'&y)+('0'&bg_scroll_y);
+ if (sum>=224) then
+ sum := sum-224;
+ end if;
+ bg_y <= sum(7 downto 0);
+ end process;
vdp_bg_inst: vdp_background
port map (
clk => clk,
address => bg_address,
- scroll_x => (others=>'0'),
+ scroll_x => bg_scroll_x,--(others=>'0'),
reset => line_reset,
- y => y,
+ y => bg_y,
vram_A => bg_vram_A,
vram_D => vram_D,
@@ -104,7 +115,7 @@ begin
color => spr_color);
- vbl_irq <= frame_reset or irq_frame_en;
+ vbl_irq <= frame_reset and irq_frame_en;
hbl_irq <= '0';
color <= cram_D;
@@ -115,7 +126,7 @@ begin
begin
if x<256 and y<192 then
spr_active := not spr_color="0000";
- bg_active := not bg_color="0000";
+ bg_active := not bg_color(3 downto 0)="0000";
if (bg_priority='0' and spr_active) or (bg_priority='1' and not bg_active) then
cram_A <= "1"&spr_color;
else
View
1,073 vhdl/t80/T80.vhd
@@ -0,0 +1,1073 @@
+--
+-- Z80 compatible microprocessor core
+--
+-- Version : 0247
+--
+-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t80/
+--
+-- Limitations :
+--
+-- File history :
+--
+-- 0208 : First complete release
+--
+-- 0210 : Fixed wait and halt
+--
+-- 0211 : Fixed Refresh addition and IM 1
+--
+-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
+--
+-- 0232 : Removed refresh address output for Mode > 1 and added DJNZ M1_n fix by Mike Johnson
+--
+-- 0235 : Added clock enable and IM 2 fix by Mike Johnson
+--
+-- 0237 : Changed 8080 I/O address output, added IntE output
+--
+-- 0238 : Fixed (IX/IY+d) timing and 16 bit ADC and SBC zero flag
+--
+-- 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
+--
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+use work.T80_Pack.all;
+
+entity T80 is
+ generic(
+ Mode : integer := 0; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
+ IOWait : integer := 0; -- 1 => Single cycle I/O, 1 => Std I/O cycle
+ Flag_C : integer := 0;
+ Flag_N : integer := 1;
+ Flag_P : integer := 2;
+ Flag_X : integer := 3;
+ Flag_H : integer := 4;
+ Flag_Y : integer := 5;
+ Flag_Z : integer := 6;
+ Flag_S : integer := 7
+ );
+ port(
+ RESET_n : in std_logic;
+ CLK_n : in std_logic;
+ CEN : in std_logic;
+ WAIT_n : in std_logic;
+ INT_n : in std_logic;
+ NMI_n : in std_logic;
+ BUSRQ_n : in std_logic;
+ M1_n : out std_logic;
+ IORQ : out std_logic;
+ NoRead : out std_logic;
+ Write : out std_logic;
+ RFSH_n : out std_logic;
+ HALT_n : out std_logic;
+ BUSAK_n : out std_logic;
+ A : out std_logic_vector(15 downto 0);
+ DInst : in std_logic_vector(7 downto 0);
+ DI : in std_logic_vector(7 downto 0);
+ DO : out std_logic_vector(7 downto 0);
+ MC : out std_logic_vector(2 downto 0);
+ TS : out std_logic_vector(2 downto 0);
+ IntCycle_n : out std_logic;
+ IntE : out std_logic;
+ Stop : out std_logic
+ );
+end T80;
+
+architecture rtl of T80 is
+
+ constant aNone : std_logic_vector(2 downto 0) := "111";
+ constant aBC : std_logic_vector(2 downto 0) := "000";
+ constant aDE : std_logic_vector(2 downto 0) := "001";
+ constant aXY : std_logic_vector(2 downto 0) := "010";
+ constant aIOA : std_logic_vector(2 downto 0) := "100";
+ constant aSP : std_logic_vector(2 downto 0) := "101";
+ constant aZI : std_logic_vector(2 downto 0) := "110";
+
+ -- Registers
+ signal ACC, F : std_logic_vector(7 downto 0);
+ signal Ap, Fp : std_logic_vector(7 downto 0);
+ signal I : std_logic_vector(7 downto 0);
+ signal R : unsigned(7 downto 0);
+ signal SP, PC : unsigned(15 downto 0);
+ signal RegDIH : std_logic_vector(7 downto 0);
+ signal RegDIL : std_logic_vector(7 downto 0);
+ signal RegBusA : std_logic_vector(15 downto 0);
+ signal RegBusB : std_logic_vector(15 downto 0);
+ signal RegBusC : std_logic_vector(15 downto 0);
+ signal RegAddrA_r : std_logic_vector(2 downto 0);
+ signal RegAddrA : std_logic_vector(2 downto 0);
+ signal RegAddrB_r : std_logic_vector(2 downto 0);
+ signal RegAddrB : std_logic_vector(2 downto 0);
+ signal RegAddrC : std_logic_vector(2 downto 0);
+ signal RegWEH : std_logic;
+ signal RegWEL : std_logic;
+ signal Alternate : std_logic;
+
+ -- Help Registers
+ signal TmpAddr : std_logic_vector(15 downto 0); -- Temporary address register
+ 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 ID16 : signed(15 downto 0);
+ signal Save_Mux : std_logic_vector(7 downto 0);
+
+ signal TState : unsigned(2 downto 0);
+ signal MCycle : std_logic_vector(2 downto 0);
+ signal IntE_FF1 : std_logic;
+ signal IntE_FF2 : std_logic;
+ signal Halt_FF : std_logic;
+ signal BusReq_s : std_logic;
+ signal BusAck : std_logic;
+ signal ClkEn : std_logic;
+ signal NMI_s : std_logic;
+ signal INT_s : std_logic;
+ signal IStatus : std_logic_vector(1 downto 0);
+
+ signal DI_Reg : std_logic_vector(7 downto 0);
+ signal T_Res : std_logic;
+ signal XY_State : std_logic_vector(1 downto 0);
+ signal Pre_XY_F_M : std_logic_vector(2 downto 0);
+ signal NextIs_XY_Fetch : std_logic;
+ signal XY_Ind : std_logic;
+ signal No_BTR : std_logic;
+ signal BTR_r : std_logic;
+ signal Auto_Wait : std_logic;
+ signal Auto_Wait_t1 : std_logic;
+ signal Auto_Wait_t2 : std_logic;
+ signal IncDecZ : std_logic;
+
+ -- ALU signals
+ signal BusB : std_logic_vector(7 downto 0);
+ signal BusA : std_logic_vector(7 downto 0);
+ signal ALU_Q : std_logic_vector(7 downto 0);
+ signal F_Out : std_logic_vector(7 downto 0);
+
+ -- Registered micro code outputs
+ signal Read_To_Reg_r : std_logic_vector(4 downto 0);
+ signal Arith16_r : std_logic;
+ signal Z16_r : std_logic;
+ signal ALU_Op_r : std_logic_vector(3 downto 0);
+ signal Save_ALU_r : std_logic;
+ signal PreserveC_r : std_logic;
+ signal MCycles : std_logic_vector(2 downto 0);
+
+ -- Micro code outputs
+ signal MCycles_d : std_logic_vector(2 downto 0);
+ signal TStates : std_logic_vector(2 downto 0);
+ signal IntCycle : std_logic;
+ signal NMICycle : std_logic;
+ signal Inc_PC : std_logic;
+ signal Inc_WZ : std_logic;
+ signal IncDec_16 : std_logic_vector(3 downto 0);
+ signal Prefix : std_logic_vector(1 downto 0);
+ signal Read_To_Acc : std_logic;
+ signal Read_To_Reg : std_logic;
+ signal Set_BusB_To : std_logic_vector(3 downto 0);
+ signal Set_BusA_To : std_logic_vector(3 downto 0);
+ signal ALU_Op : std_logic_vector(3 downto 0);
+ signal Save_ALU : std_logic;
+ signal PreserveC : std_logic;
+ signal Arith16 : std_logic;
+ signal Set_Addr_To : std_logic_vector(2 downto 0);
+ signal Jump : std_logic;
+ signal JumpE : std_logic;
+ signal JumpXY : std_logic;
+ signal Call : std_logic;
+ signal RstP : std_logic;
+ signal LDZ : std_logic;
+ signal LDW : std_logic;
+ signal LDSPHL : std_logic;
+ signal IORQ_i : std_logic;
+ signal Special_LD : std_logic_vector(2 downto 0);
+ signal ExchangeDH : std_logic;
+ signal ExchangeRp : std_logic;
+ signal ExchangeAF : std_logic;
+ signal ExchangeRS : std_logic;
+ signal I_DJNZ : std_logic;
+ signal I_CPL : std_logic;
+ signal I_CCF : std_logic;
+ signal I_SCF : std_logic;
+ signal I_RETN : std_logic;
+ signal I_BT : std_logic;
+ signal I_BC : std_logic;
+ signal I_BTR : std_logic;
+ signal I_RLD : std_logic;
+ signal I_RRD : std_logic;
+ signal I_INRC : std_logic;
+ signal SetDI : std_logic;
+ signal SetEI : std_logic;
+ signal IMode : std_logic_vector(1 downto 0);
+ signal Halt : std_logic;
+
+begin
+
+ mcode : T80_MCode
+ generic map(
+ Mode => Mode,
+ Flag_C => Flag_C,
+ Flag_N => Flag_N,
+ Flag_P => Flag_P,
+ Flag_X => Flag_X,
+ Flag_H => Flag_H,
+ Flag_Y => Flag_Y,
+ Flag_Z => Flag_Z,
+ Flag_S => Flag_S)
+ port map(
+ IR => IR,
+ ISet => ISet,
+ MCycle => MCycle,
+ F => F,
+ NMICycle => NMICycle,
+ IntCycle => IntCycle,
+ MCycles => MCycles_d,
+ TStates => TStates,
+ Prefix => Prefix,
+ Inc_PC => Inc_PC,
+ Inc_WZ => Inc_WZ,
+ IncDec_16 => IncDec_16,
+ Read_To_Acc => Read_To_Acc,
+ Read_To_Reg => Read_To_Reg,
+ Set_BusB_To => Set_BusB_To,
+ Set_BusA_To => Set_BusA_To,
+ ALU_Op => ALU_Op,
+ Save_ALU => Save_ALU,
+ PreserveC => PreserveC,
+ Arith16 => Arith16,
+ Set_Addr_To => Set_Addr_To,
+ IORQ => IORQ_i,
+ Jump => Jump,
+ JumpE => JumpE,
+ JumpXY => JumpXY,
+ Call => Call,
+ RstP => RstP,
+ LDZ => LDZ,
+ LDW => LDW,
+ LDSPHL => LDSPHL,
+ Special_LD => Special_LD,
+ ExchangeDH => ExchangeDH,
+ ExchangeRp => ExchangeRp,
+ ExchangeAF => ExchangeAF,
+ ExchangeRS => ExchangeRS,
+ I_DJNZ => I_DJNZ,
+ I_CPL => I_CPL,
+ I_CCF => I_CCF,
+ I_SCF => I_SCF,
+ I_RETN => I_RETN,
+ I_BT => I_BT,
+ I_BC => I_BC,
+ I_BTR => I_BTR,
+ I_RLD => I_RLD,
+ I_RRD => I_RRD,
+ I_INRC => I_INRC,
+ SetDI => SetDI,
+ SetEI => SetEI,
+ IMode => IMode,
+ Halt => Halt,
+ NoRead => NoRead,
+ Write => Write);
+
+ alu : T80_ALU
+ generic map(
+ Mode => Mode,
+ Flag_C => Flag_C,
+ Flag_N => Flag_N,
+ Flag_P => Flag_P,
+ Flag_X => Flag_X,
+ Flag_H => Flag_H,
+ Flag_Y => Flag_Y,
+ Flag_Z => Flag_Z,
+ Flag_S => Flag_S)
+ port map(
+ Arith16 => Arith16_r,
+ Z16 => Z16_r,
+ ALU_Op => ALU_Op_r,
+ IR => IR(5 downto 0),
+ ISet => ISet,
+ BusA => BusA,
+ BusB => BusB,
+ F_In => F,
+ Q => ALU_Q,
+ F_Out => F_Out);
+
+ ClkEn <= CEN and not BusAck;
+
+ T_Res <= '1' when TState = unsigned(TStates) else '0';
+
+ NextIs_XY_Fetch <= '1' when XY_State /= "00" and XY_Ind = '0' and
+ ((Set_Addr_To = aXY) or
+ (MCycle = "001" and IR = "11001011") or
+ (MCycle = "001" and IR = "00110110")) else '0';
+
+ Save_Mux <= BusB when ExchangeRp = '1' else
+ DI_Reg when Save_ALU_r = '0' else
+ ALU_Q;
+
+ process (RESET_n, CLK_n)
+ begin
+ if RESET_n = '0' then
+ PC <= (others => '0'); -- Program Counter
+ A <= (others => '0');
+ TmpAddr <= (others => '0');
+ IR <= "00000000";
+ ISet <= "00";
+ XY_State <= "00";
+ IStatus <= "00";
+ MCycles <= "000";
+ DO <= "00000000";
+
+ ACC <= (others => '1');
+ F <= (others => '1');
+ Ap <= (others => '1');
+ Fp <= (others => '1');
+ I <= (others => '0');
+ R <= (others => '0');
+ SP <= (others => '1');
+ Alternate <= '0';
+
+ Read_To_Reg_r <= "00000";
+ F <= (others => '1');
+ Arith16_r <= '0';
+ BTR_r <= '0';
+ Z16_r <= '0';
+ ALU_Op_r <= "0000";
+ Save_ALU_r <= '0';
+ PreserveC_r <= '0';
+ XY_Ind <= '0';
+
+ elsif CLK_n'event and CLK_n = '1' then
+
+ if ClkEn = '1' then
+
+ ALU_Op_r <= "0000";
+ Save_ALU_r <= '0';
+ Read_To_Reg_r <= "00000";
+
+ MCycles <= MCycles_d;
+
+ if IMode /= "11" then
+ IStatus <= IMode;
+ end if;
+
+ Arith16_r <= Arith16;
+ PreserveC_r <= PreserveC;
+ if ISet = "10" and ALU_OP(2) = '0' and ALU_OP(0) = '1' and MCycle = "011" then
+ Z16_r <= '1';
+ else
+ Z16_r <= '0';
+ end if;
+
+ if MCycle = "001" and TState(2) = '0' then
+ -- MCycle = 1 and TState = 1, 2, or 3
+
+ if TState = 2 and Wait_n = '1' then
+ if Mode < 2 then
+ A(7 downto 0) <= std_logic_vector(R);
+ A(15 downto 8) <= I;
+ R(6 downto 0) <= R(6 downto 0) + 1;
+ end if;
+
+ if Jump = '0' and Call = '0' and NMICycle = '0' and IntCycle = '0' and not (Halt_FF = '1' or Halt = '1') then
+ PC <= PC + 1;
+ end if;
+
+ if IntCycle = '1' and IStatus = "01" then
+ IR <= "11111111";
+ elsif Halt_FF = '1' or (IntCycle = '1' and IStatus = "10") or NMICycle = '1' then
+ IR <= "00000000";
+ else
+ IR <= DInst;
+ end if;
+
+ ISet <= "00";
+ if Prefix /= "00" then
+ if Prefix = "11" then
+ if IR(5) = '1' then
+ XY_State <= "10";
+ else
+ XY_State <= "01";
+ end if;
+ else
+ if Prefix = "10" then
+ XY_State <= "00";
+ XY_Ind <= '0';
+ end if;
+ ISet <= Prefix;
+ end if;
+ else
+ XY_State <= "00";
+ XY_Ind <= '0';
+ end if;
+ end if;
+
+ else
+ -- either (MCycle > 1) OR (MCycle = 1 AND TState > 3)
+
+ if MCycle = "110" then
+ XY_Ind <= '1';
+ if Prefix = "01" then
+ ISet <= "01";
+ end if;
+ end if;
+
+ if T_Res = '1' then
+ BTR_r <= (I_BT or I_BC or I_BTR) and not No_BTR;
+ if Jump = '1' then
+ A(15 downto 8) <= DI_Reg;
+ A(7 downto 0) <= TmpAddr(7 downto 0);
+ PC(15 downto 8) <= unsigned(DI_Reg);
+ PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0));
+ elsif JumpXY = '1' then
+ A <= RegBusC;
+ PC <= unsigned(RegBusC);
+ elsif Call = '1' or RstP = '1' then
+ A <= TmpAddr;
+ PC <= unsigned(TmpAddr);
+ elsif MCycle = MCycles and NMICycle = '1' then
+ A <= "0000000001100110";
+ PC <= "0000000001100110";
+ elsif MCycle = "011" and IntCycle = '1' and IStatus = "10" then
+ A(15 downto 8) <= I;
+ A(7 downto 0) <= TmpAddr(7 downto 0);
+ PC(15 downto 8) <= unsigned(I);
+ PC(7 downto 0) <= unsigned(TmpAddr(7 downto 0));
+ else
+ case Set_Addr_To is
+ when aXY =>
+ if XY_State = "00" then
+ A <= RegBusC;
+ else
+ if NextIs_XY_Fetch = '1' then
+ A <= std_logic_vector(PC);
+ else
+ A <= TmpAddr;
+ end if;
+ end if;
+ when aIOA =>
+ if Mode = 3 then
+ -- Memory map I/O on GBZ80
+ A(15 downto 8) <= (others => '1');
+ elsif Mode = 2 then
+ -- Duplicate I/O address on 8080
+ A(15 downto 8) <= DI_Reg;
+ else
+ A(15 downto 8) <= ACC;
+ end if;
+ A(7 downto 0) <= DI_Reg;
+ when aSP =>
+ A <= std_logic_vector(SP);
+ when aBC =>
+ if Mode = 3 and IORQ_i = '1' then
+ -- Memory map I/O on GBZ80
+ A(15 downto 8) <= (others => '1');
+ A(7 downto 0) <= RegBusC(7 downto 0);
+ else
+ A <= RegBusC;
+ end if;
+ when aDE =>
+ A <= RegBusC;
+ when aZI =>
+ if Inc_WZ = '1' then
+ A <= std_logic_vector(unsigned(TmpAddr) + 1);
+ else
+ A(15 downto 8) <= DI_Reg;
+ A(7 downto 0) <= TmpAddr(7 downto 0);
+ end if;
+ when others =>
+ A <= std_logic_vector(PC);
+ end case;
+ end if;
+
+ Save_ALU_r <= Save_ALU;
+ ALU_Op_r <= ALU_Op;
+
+ if I_CPL = '1' then
+ -- CPL
+ ACC <= not ACC;
+ F(Flag_Y) <= not ACC(5);
+ F(Flag_H) <= '1';
+ F(Flag_X) <= not ACC(3);
+ F(Flag_N) <= '1';
+ end if;
+ if I_CCF = '1' then
+ -- CCF
+ F(Flag_C) <= not F(Flag_C);
+ F(Flag_Y) <= ACC(5);
+ F(Flag_H) <= F(Flag_C);
+ F(Flag_X) <= ACC(3);
+ F(Flag_N) <= '0';
+ end if;
+ if I_SCF = '1' then
+ -- SCF
+ F(Flag_C) <= '1';
+ F(Flag_Y) <= ACC(5);
+ F(Flag_H) <= '0';
+ F(Flag_X) <= ACC(3);
+ F(Flag_N) <= '0';
+ end if;
+ end if;
+
+ if TState = 2 and Wait_n = '1' then
+ if ISet = "01" and MCycle = "111" then
+ IR <= DInst;
+ end if;
+ if JumpE = '1' then
+ PC <= unsigned(signed(PC) + signed(DI_Reg));
+ elsif Inc_PC = '1' then
+ PC <= PC + 1;
+ end if;
+ if BTR_r = '1' then
+ PC <= PC - 2;
+ end if;
+ if RstP = '1' then
+ TmpAddr <= (others =>'0');
+ TmpAddr(5 downto 3) <= IR(5 downto 3);
+ end if;
+ end if;
+ if TState = 3 and MCycle = "110" then
+ TmpAddr <= std_logic_vector(signed(RegBusC) + signed(DI_Reg));
+ end if;
+
+ if (TState = 2 and Wait_n = '1') or (TState = 4 and MCycle = "001") then
+ if IncDec_16(2 downto 0) = "111" then
+ if IncDec_16(3) = '1' then
+ SP <= SP - 1;
+ else
+ SP <= SP + 1;
+ end if;
+ end if;
+ end if;
+
+ if LDSPHL = '1' then
+ SP <= unsigned(RegBusC);
+ end if;
+ if ExchangeAF = '1' then
+ Ap <= ACC;
+ ACC <= Ap;
+ Fp <= F;
+ F <= Fp;
+ end if;
+ if ExchangeRS = '1' then
+ Alternate <= not Alternate;
+ end if;
+ end if;
+
+ if TState = 3 then
+ if LDZ = '1' then
+ TmpAddr(7 downto 0) <= DI_Reg;
+ end if;
+ if LDW = '1' then
+ TmpAddr(15 downto 8) <= DI_Reg;
+ end if;
+
+ if Special_LD(2) = '1' then
+ case Special_LD(1 downto 0) is
+ when "00" =>
+ ACC <= I;
+ F(Flag_P) <= IntE_FF2;
+ when "01" =>
+ ACC <= std_logic_vector(R);
+ F(Flag_P) <= IntE_FF2;
+ when "10" =>
+ I <= ACC;
+ when others =>
+ R <= unsigned(ACC);
+ end case;
+ end if;
+ end if;
+
+ if (I_DJNZ = '0' and Save_ALU_r = '1') or ALU_Op_r = "1001" then
+ if Mode = 3 then
+ F(6) <= F_Out(6);
+ F(5) <= F_Out(5);
+ F(7) <= F_Out(7);
+ if PreserveC_r = '0' then
+ F(4) <= F_Out(4);
+ end if;
+ else
+ F(7 downto 1) <= F_Out(7 downto 1);
+ if PreserveC_r = '0' then
+ F(Flag_C) <= F_Out(0);
+ end if;
+ end if;
+ end if;
+ if T_Res = '1' and I_INRC = '1' then
+ F(Flag_H) <= '0';
+ F(Flag_N) <= '0';
+ if DI_Reg(7 downto 0) = "00000000" then
+ F(Flag_Z) <= '1';
+ else
+ F(Flag_Z) <= '0';
+ end if;
+ F(Flag_S) <= DI_Reg(7);
+ F(Flag_P) <= not (DI_Reg(0) xor DI_Reg(1) xor DI_Reg(2) xor DI_Reg(3) xor
+ DI_Reg(4) xor DI_Reg(5) xor DI_Reg(6) xor DI_Reg(7));
+ end if;
+
+ if TState = 1 and Auto_Wait_t1 = '0' then
+ DO <= BusB;
+ if I_RLD = '1' then
+ DO(3 downto 0) <= BusA(3 downto 0);
+ DO(7 downto 4) <= BusB(3 downto 0);
+ end if;
+ if I_RRD = '1' then
+ DO(3 downto 0) <= BusB(7 downto 4);
+ DO(7 downto 4) <= BusA(3 downto 0);
+ end if;
+ end if;
+
+ if T_Res = '1' then
+ Read_To_Reg_r(3 downto 0) <= Set_BusA_To;
+ Read_To_Reg_r(4) <= Read_To_Reg;
+ if Read_To_Acc = '1' then
+ Read_To_Reg_r(3 downto 0) <= "0111";
+ Read_To_Reg_r(4) <= '1';
+ end if;
+ end if;
+
+ if TState = 1 and I_BT = '1' then
+ F(Flag_X) <= ALU_Q(3);
+ F(Flag_Y) <= ALU_Q(1);
+ F(Flag_H) <= '0';
+ F(Flag_N) <= '0';
+ end if;
+ if I_BC = '1' or I_BT = '1' then
+ F(Flag_P) <= IncDecZ;
+ end if;
+
+ if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or
+ (Save_ALU_r = '1' and ALU_OP_r /= "0111") then
+ case Read_To_Reg_r is
+ when "10111" =>
+ ACC <= Save_Mux;
+ when "10110" =>
+ DO <= Save_Mux;
+ when "11000" =>
+ SP(7 downto 0) <= unsigned(Save_Mux);
+ when "11001" =>
+ SP(15 downto 8) <= unsigned(Save_Mux);
+ when "11011" =>
+ F <= Save_Mux;
+ when others =>
+ end case;
+ end if;
+
+ end if;
+
+ end if;
+
+ end process;
+
+---------------------------------------------------------------------------
+--
+-- BC('), DE('), HL('), IX and IY
+--
+---------------------------------------------------------------------------
+ process (CLK_n)
+ begin
+ if CLK_n'event and CLK_n = '1' then
+ if ClkEn = '1' then
+ -- Bus A / Write
+ RegAddrA_r <= Alternate & Set_BusA_To(2 downto 1);
+ if XY_Ind = '0' and XY_State /= "00" and Set_BusA_To(2 downto 1) = "10" then
+ RegAddrA_r <= XY_State(1) & "11";
+ end if;
+
+ -- Bus B
+ RegAddrB_r <= Alternate & Set_BusB_To(2 downto 1);
+ if XY_Ind = '0' and XY_State /= "00" and Set_BusB_To(2 downto 1) = "10" then
+ RegAddrB_r <= XY_State(1) & "11";
+ end if;
+
+ -- Address from register
+ RegAddrC <= Alternate & Set_Addr_To(1 downto 0);
+ -- Jump (HL), LD SP,HL
+ if (JumpXY = '1' or LDSPHL = '1') then
+ RegAddrC <= Alternate & "10";
+ end if;
+ if ((JumpXY = '1' or LDSPHL = '1') and XY_State /= "00") or (MCycle = "110") then
+ RegAddrC <= XY_State(1) & "11";
+ end if;
+
+ if I_DJNZ = '1' and Save_ALU_r = '1' and Mode < 2 then
+ IncDecZ <= F_Out(Flag_Z);
+ end if;
+ if (TState = 2 or (TState = 3 and MCycle = "001")) and IncDec_16(2 downto 0) = "100" then
+ if ID16 = 0 then
+ IncDecZ <= '0';
+ else
+ IncDecZ <= '1';
+ end if;
+ end if;
+
+ RegBusA_r <= RegBusA;
+ end if;
+ end if;
+ end process;
+
+ RegAddrA <=
+ -- 16 bit increment/decrement
+ Alternate & IncDec_16(1 downto 0) when (TState = 2 or
+ (TState = 3 and MCycle = "001" and IncDec_16(2) = '1')) and XY_State = "00" else
+ XY_State(1) & "11" when (TState = 2 or
+ (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
+ -- Bus A / Write
+ RegAddrA_r;
+
+ RegAddrB <=
+ -- EX HL,DL
+ Alternate & "01" when ExchangeDH = '1' and TState = 3 else
+ -- Bus B
+ RegAddrB_r;
+
+ 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,
+ ExchangeDH, IncDec_16, MCycle, TState, Wait_n)
+ begin
+ RegWEH <= '0';
+ RegWEL <= '0';
+ if (TState = 1 and Save_ALU_r = '0' and Auto_Wait_t1 = '0') or
+ (Save_ALU_r = '1' and ALU_OP_r /= "0111") then
+ case Read_To_Reg_r is
+ when "10000" | "10001" | "10010" | "10011" | "10100" | "10101" =>
+ RegWEH <= not Read_To_Reg_r(0);
+ RegWEL <= Read_To_Reg_r(0);
+ when others =>
+ end case;
+ end if;
+
+ if ExchangeDH = '1' and (TState = 3 or TState = 4) then
+ RegWEH <= '1';
+ RegWEL <= '1';
+ end if;
+
+ if IncDec_16(2) = '1' and ((TState = 2 and Wait_n = '1' and MCycle /= "001") or (TState = 3 and MCycle = "001")) then
+ case IncDec_16(1 downto 0) is
+ when "00" | "01" | "10" =>
+ RegWEH <= '1';
+ RegWEL <= '1';
+ when others =>
+ end case;
+ end if;
+ end process;
+
+ process (Save_Mux, RegBusB, RegBusA_r, ID16,
+ ExchangeDH, IncDec_16, MCycle, TState, Wait_n)
+ begin
+ RegDIH <= Save_Mux;
+ RegDIL <= Save_Mux;
+
+ if ExchangeDH = '1' and TState = 3 then
+ RegDIH <= RegBusB(15 downto 8);
+ RegDIL <= RegBusB(7 downto 0);
+ end if;
+ if ExchangeDH = '1' and TState = 4 then
+ RegDIH <= RegBusA_r(15 downto 8);
+ RegDIL <= RegBusA_r(7 downto 0);
+ end if;
+
+ if IncDec_16(2) = '1' and ((TState = 2 and MCycle /= "001") or (TState = 3 and MCycle = "001")) then
+ RegDIH <= std_logic_vector(ID16(15 downto 8));
+ RegDIL <= std_logic_vector(ID16(7 downto 0));
+ end if;
+ end process;
+
+ Regs : T80_Reg
+ port map(
+ Clk => CLK_n,
+ CEN => ClkEn,
+ WEH => RegWEH,
+ WEL => RegWEL,
+ AddrA => RegAddrA,
+ AddrB => RegAddrB,
+ AddrC => RegAddrC,
+ DIH => RegDIH,
+ DIL => RegDIL,
+ DOAH => RegBusA(15 downto 8),
+ DOAL => RegBusA(7 downto 0),
+ DOBH => RegBusB(15 downto 8),
+ DOBL => RegBusB(7 downto 0),
+ DOCH => RegBusC(15 downto 8),
+ DOCL => RegBusC(7 downto 0));
+
+---------------------------------------------------------------------------
+--
+-- Buses
+--
+---------------------------------------------------------------------------
+ process (CLK_n)
+ begin
+ if CLK_n'event and CLK_n = '1' then
+ if ClkEn = '1' then
+ case Set_BusB_To is
+ when "0111" =>
+ BusB <= ACC;
+ when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" =>
+ if Set_BusB_To(0) = '1' then
+ BusB <= RegBusB(7 downto 0);
+ else
+ BusB <= RegBusB(15 downto 8);
+ end if;
+ when "0110" =>
+ BusB <= DI_Reg;
+ when "1000" =>
+ BusB <= std_logic_vector(SP(7 downto 0));
+ when "1001" =>
+ BusB <= std_logic_vector(SP(15 downto 8));
+ when "1010" =>
+ BusB <= "00000001";
+ when "1011" =>
+ BusB <= F;
+ when "1100" =>
+ BusB <= std_logic_vector(PC(7 downto 0));
+ when "1101" =>
+ BusB <= std_logic_vector(PC(15 downto 8));
+ when "1110" =>
+ BusB <= "00000000";
+ when others =>
+ BusB <= "--------";
+ end case;
+
+ case Set_BusA_To is
+ when "0111" =>
+ BusA <= ACC;
+ when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" =>
+ if Set_BusA_To(0) = '1' then
+ BusA <= RegBusA(7 downto 0);
+ else
+ BusA <= RegBusA(15 downto 8);
+ end if;
+ when "0110" =>
+ BusA <= DI_Reg;
+ when "1000" =>
+ BusA <= std_logic_vector(SP(7 downto 0));
+ when "1001" =>
+ BusA <= std_logic_vector(SP(15 downto 8));
+ when "1010" =>
+ BusA <= "00000000";
+ when others =>
+ BusB <= "--------";
+ end case;
+ end if;
+ end if;
+ end process;
+
+---------------------------------------------------------------------------
+--
+-- Generate external control signals
+--
+---------------------------------------------------------------------------
+ process (RESET_n,CLK_n)
+ begin
+ if RESET_n = '0' then
+ RFSH_n <= '1';
+ elsif CLK_n'event and CLK_n = '1' then
+ if CEN = '1' then
+ if MCycle = "001" and ((TState = 2 and Wait_n = '1') or TState = 3) then
+ RFSH_n <= '0';
+ else
+ RFSH_n <= '1';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ MC <= std_logic_vector(MCycle);
+ TS <= std_logic_vector(TState);
+ DI_Reg <= DI;
+ HALT_n <= not Halt_FF;
+ BUSAK_n <= not BusAck;
+ IntCycle_n <= not IntCycle;
+ IntE <= IntE_FF1;
+ IORQ <= IORQ_i;
+ Stop <= I_DJNZ;
+
+-------------------------------------------------------------------------
+--
+-- Syncronise inputs
+--
+-------------------------------------------------------------------------
+ process (RESET_n, CLK_n)
+ variable OldNMI_n : std_logic;
+ begin
+ if RESET_n = '0' then
+ BusReq_s <= '0';
+ INT_s <= '0';
+ NMI_s <= '0';
+ OldNMI_n := '0';
+ elsif CLK_n'event and CLK_n = '1' then
+ if CEN = '1' then
+ BusReq_s <= not BUSRQ_n;
+ INT_s <= not INT_n;
+ if NMICycle = '1' then
+ NMI_s <= '0';
+ elsif NMI_n = '0' and OldNMI_n = '1' then
+ NMI_s <= '1';
+ end if;
+ OldNMI_n := NMI_n;
+ end if;
+ end if;
+ end process;
+
+-------------------------------------------------------------------------
+--
+-- Main state machine
+--
+-------------------------------------------------------------------------
+ process (RESET_n, CLK_n)
+ begin
+ if RESET_n = '0' then
+ MCycle <= "001";
+ TState <= "000";
+ Pre_XY_F_M <= "000";
+ Halt_FF <= '0';
+ BusAck <= '0';
+ NMICycle <= '0';
+ IntCycle <= '0';
+ IntE_FF1 <= '0';
+ IntE_FF2 <= '0';
+ No_BTR <= '0';
+ Auto_Wait_t1 <= '0';
+ Auto_Wait_t2 <= '0';
+ M1_n <= '1';
+ elsif CLK_n'event and CLK_n = '1' then
+ if CEN = '1' then
+ if T_Res = '1' then
+ Auto_Wait_t1 <= '0';
+ else
+ Auto_Wait_t1 <= Auto_Wait or IORQ_i;
+ end if;
+ Auto_Wait_t2 <= Auto_Wait_t1;
+ No_BTR <= (I_BT and (not IR(4) or not F(Flag_P))) or
+ (I_BC and (not IR(4) or F(Flag_Z) or not F(Flag_P))) or
+ (I_BTR and (not IR(4) or F(Flag_Z)));
+ if TState = 2 then
+ if SetEI = '1' then
+ IntE_FF1 <= '1';
+ IntE_FF2 <= '1';
+ end if;
+ if I_RETN = '1' then
+ IntE_FF1 <= IntE_FF2;
+ end if;
+ end if;
+ if TState = 3 then
+ if SetDI = '1' then
+ IntE_FF1 <= '0';
+ IntE_FF2 <= '0';
+ end if;
+ end if;
+ if IntCycle = '1' or NMICycle = '1' then
+ Halt_FF <= '0';
+ end if;
+ if MCycle = "001" and TState = 2 and Wait_n = '1' then
+ M1_n <= '1';
+ end if;
+ if BusReq_s = '1' and BusAck = '1' then
+ else
+ BusAck <= '0';
+ if TState = 2 and Wait_n = '0' then
+ elsif T_Res = '1' then
+ if Halt = '1' then
+ Halt_FF <= '1';
+ end if;
+ if BusReq_s = '1' then
+ BusAck <= '1';
+ else
+ TState <= "001";
+ if NextIs_XY_Fetch = '1' then
+ MCycle <= "110";
+ Pre_XY_F_M <= MCycle;
+ if IR = "00110110" and Mode = 0 then
+ Pre_XY_F_M <= "010";
+ end if;
+ elsif (MCycle = "111") or
+ (MCycle = "110" and Mode = 1 and ISet /= "01") then
+ MCycle <= std_logic_vector(unsigned(Pre_XY_F_M) + 1);
+ elsif (MCycle = MCycles) or
+ No_BTR = '1' or
+ (MCycle = "010" and I_DJNZ = '1' and IncDecZ = '1') then
+ M1_n <= '0';
+ MCycle <= "001";
+ IntCycle <= '0';
+ NMICycle <= '0';
+ if NMI_s = '1' and Prefix = "00" then
+ NMICycle <= '1';
+ IntE_FF1 <= '0';
+ elsif (IntE_FF1 = '1' and INT_s = '1') and Prefix = "00" and SetEI = '0' then
+ IntCycle <= '1';
+ IntE_FF1 <= '0';
+ IntE_FF2 <= '0';
+ end if;
+ else
+ MCycle <= std_logic_vector(unsigned(MCycle) + 1);
+ end if;
+ end if;
+ else
+ if (Auto_Wait = '1' and Auto_Wait_t2 = '0') nor
+ (IOWait = 1 and IORQ_i = '1' and Auto_Wait_t1 = '0') then
+ TState <= TState + 1;
+ end if;
+ end if;
+ end if;
+ if TState = 0 then
+ M1_n <= '0';
+ end if;
+ end if;
+ end if;
+ end process;
+
+ process (IntCycle, NMICycle, MCycle)
+ begin
+ Auto_Wait <= '0';
+ if IntCycle = '1' or NMICycle = '1' then
+ if MCycle = "001" then
+ Auto_Wait <= '1';
+ end if;
+ end if;
+ end process;
+
+end;
View
185 vhdl/t80/T8080se.vhd
@@ -0,0 +1,185 @@
+--
+-- 8080 compatible microprocessor core, synchronous top level with clock enable
+-- Different timing than the original 8080
+-- Inputs needs to be synchronous and outputs may glitch
+--
+-- Version : 0242
+--
+-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t80/
+--
+-- Limitations :
+-- STACK status output not supported
+--
+-- File history :
+--
+-- 0237 : First version
+--
+-- 0238 : Updated for T80 interface change
+--
+-- 0240 : Updated for T80 interface change
+--
+-- 0242 : Updated for T80 interface change
+--
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+use work.T80_Pack.all;
+
+entity T8080se is
+ generic(
+ Mode : integer := 2; -- 0 => Z80, 1 => Fast Z80, 2 => 8080, 3 => GB
+ T2Write : integer := 0 -- 0 => WR_n active in T3, /=0 => WR_n active in T2
+ );
+ port(
+ RESET_n : in std_logic;
+ CLK : in std_logic;
+ CLKEN : in std_logic;
+ READY : in std_logic;
+ HOLD : in std_logic;
+ INT : in std_logic;
+ INTE : out std_logic;
+ DBIN : out std_logic;
+ SYNC : out std_logic;
+ VAIT : out std_logic;
+ HLDA : out std_logic;
+ WR_n : out std_logic;
+ A : out std_logic_vector(15 downto 0);
+ DI : in std_logic_vector(7 downto 0);
+ DO : out std_logic_vector(7 downto 0)
+ );
+end T8080se;
+
+architecture rtl of T8080se is
+
+ signal IntCycle_n : std_logic;
+ signal NoRead : std_logic;
+ signal Write : std_logic;
+ signal IORQ : std_logic;
+ signal INT_n : std_logic;
+ signal HALT_n : std_logic;
+ signal BUSRQ_n : std_logic;
+ signal BUSAK_n : std_logic;
+ signal DO_i : std_logic_vector(7 downto 0);
+ signal DI_Reg : std_logic_vector(7 downto 0);
+ signal MCycle : std_logic_vector(2 downto 0);
+ signal TState : std_logic_vector(2 downto 0);
+ signal One : std_logic;
+
+begin
+
+ INT_n <= not INT;
+ BUSRQ_n <= HOLD;
+ HLDA <= not BUSAK_n;
+ SYNC <= '1' when TState = "001" else '0';
+ VAIT <= '1' when TState = "010" else '0';
+ One <= '1';
+
+ DO(0) <= not IntCycle_n when TState = "001" else DO_i(0); -- INTA
+ DO(1) <= Write when TState = "001" else DO_i(1); -- WO_n
+ DO(2) <= DO_i(2); -- STACK not supported !!!!!!!!!!
+ DO(3) <= not HALT_n when TState = "001" else DO_i(3); -- HLTA
+ DO(4) <= IORQ and Write when TState = "001" else DO_i(4); -- OUT
+ DO(5) <= DO_i(5) when TState /= "001" else '1' when MCycle = "001" else '0'; -- M1
+ DO(6) <= IORQ and not Write when TState = "001" else DO_i(6); -- INP
+ DO(7) <= not IORQ and not Write and IntCycle_n when TState = "001" else DO_i(7); -- MEMR
+
+ u0 : T80
+ generic map(
+ Mode => Mode,
+ IOWait => 0)
+ port map(
+ CEN => CLKEN,
+ M1_n => open,
+ IORQ => IORQ,
+ NoRead => NoRead,
+ Write => Write,
+ RFSH_n => open,
+ HALT_n => HALT_n,
+ WAIT_n => READY,
+ INT_n => INT_n,
+ NMI_n => One,
+ RESET_n => RESET_n,
+ BUSRQ_n => One,
+ BUSAK_n => BUSAK_n,
+ CLK_n => CLK,
+ A => A,
+ DInst => DI,
+ DI => DI_Reg,
+ DO => DO_i,
+ MC => MCycle,
+ TS => TState,
+ IntCycle_n => IntCycle_n,
+ IntE => INTE);
+
+ process (RESET_n, CLK)
+ begin
+ if RESET_n = '0' then
+ DBIN <= '0';
+ WR_n <= '1';
+ DI_Reg <= "00000000";
+ elsif CLK'event and CLK = '1' then
+ if CLKEN = '1' then
+ DBIN <= '0';
+ WR_n <= '1';
+ if MCycle = "001" then
+ if TState = "001" or (TState = "010" and READY = '0') then
+ DBIN <= IntCycle_n;
+ end if;
+ else
+ if (TState = "001" or (TState = "010" and READY = '0')) and NoRead = '0' and Write = '0' then
+ DBIN <= '1';
+ end if;
+ if T2Write = 0 then
+ if TState = "010" and Write = '1' then
+ WR_n <= '0';
+ end if;
+ else
+ if (TState = "001" or (TState = "010" and READY = '0')) and Write = '1' then
+ WR_n <= '0';
+ end if;
+ end if;
+ end if;
+ if TState = "010" and READY = '1' then
+ DI_Reg <= DI;
+ end if;
+ end if;
+ end if;
+ end process;
+
+end;
View
351 vhdl/t80/T80_ALU.vhd
@@ -0,0 +1,351 @@
+--
+-- Z80 compatible microprocessor core
+--
+-- Version : 0247
+--
+-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t80/
+--
+-- Limitations :
+--
+-- File history :
+--
+-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
+--
+-- 0238 : Fixed zero flag for 16 bit SBC and ADC
+--
+-- 0240 : Added GB operations
+--
+-- 0242 : Cleanup
+--
+-- 0247 : Cleanup
+--
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+entity T80_ALU is
+ generic(
+ Mode : integer := 0;
+ Flag_C : integer := 0;
+ Flag_N : integer := 1;
+ Flag_P : integer := 2;
+ Flag_X : integer := 3;
+ Flag_H : integer := 4;
+ Flag_Y : integer := 5;
+ Flag_Z : integer := 6;
+ Flag_S : integer := 7
+ );
+ port(
+ Arith16 : in std_logic;
+ Z16 : in std_logic;
+ ALU_Op : in std_logic_vector(3 downto 0);
+ IR : in std_logic_vector(5 downto 0);
+ ISet : in std_logic_vector(1 downto 0);
+ BusA : in std_logic_vector(7 downto 0);
+ BusB : in std_logic_vector(7 downto 0);
+ F_In : in std_logic_vector(7 downto 0);
+ Q : out std_logic_vector(7 downto 0);
+ F_Out : out std_logic_vector(7 downto 0)
+ );
+end T80_ALU;
+
+architecture rtl of T80_ALU is
+
+ procedure AddSub(A : std_logic_vector;
+ B : std_logic_vector;
+ Sub : std_logic;
+ Carry_In : std_logic;
+ signal Res : out std_logic_vector;
+ signal Carry : out std_logic) is
+ variable B_i : unsigned(A'length - 1 downto 0);
+ variable Res_i : unsigned(A'length + 1 downto 0);
+ begin
+ if Sub = '1' then
+ B_i := not unsigned(B);
+ else
+ B_i := unsigned(B);
+ end if;
+ Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1");
+ Carry <= Res_i(A'length + 1);
+ Res <= std_logic_vector(Res_i(A'length downto 1));
+ end;
+
+ -- AddSub variables (temporary signals)
+ signal UseCarry : std_logic;
+ signal Carry7_v : std_logic;
+ signal Overflow_v : std_logic;
+ signal HalfCarry_v : std_logic;
+ signal Carry_v : std_logic;
+ signal Q_v : std_logic_vector(7 downto 0);
+
+ signal BitMask : std_logic_vector(7 downto 0);
+
+begin
+
+ with IR(5 downto 3) select BitMask <= "00000001" when "000",
+ "00000010" when "001",
+ "00000100" when "010",
+ "00001000" when "011",
+ "00010000" when "100",
+ "00100000" when "101",
+ "01000000" when "110",
+ "10000000" when others;
+
+ UseCarry <= not ALU_Op(2) and ALU_Op(0);
+ AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v);
+ AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v);
+ AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v);
+ OverFlow_v <= Carry_v xor Carry7_v;
+
+ process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16)
+ variable Q_t : std_logic_vector(7 downto 0);
+ variable DAA_Q : unsigned(8 downto 0);
+ begin
+ Q_t := "--------";
+ F_Out <= F_In;
+ DAA_Q := "---------";
+ case ALU_Op is
+ when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" =>
+ F_Out(Flag_N) <= '0';
+ F_Out(Flag_C) <= '0';
+ case ALU_OP(2 downto 0) is
+ when "000" | "001" => -- ADD, ADC
+ Q_t := Q_v;
+ F_Out(Flag_C) <= Carry_v;
+ F_Out(Flag_H) <= HalfCarry_v;
+ F_Out(Flag_P) <= OverFlow_v;
+ when "010" | "011" | "111" => -- SUB, SBC, CP
+ Q_t := Q_v;
+ F_Out(Flag_N) <= '1';
+ F_Out(Flag_C) <= not Carry_v;
+ F_Out(Flag_H) <= not HalfCarry_v;
+ F_Out(Flag_P) <= OverFlow_v;
+ when "100" => -- AND
+ Q_t(7 downto 0) := BusA and BusB;
+ F_Out(Flag_H) <= '1';
+ when "101" => -- XOR
+ Q_t(7 downto 0) := BusA xor BusB;
+ F_Out(Flag_H) <= '0';
+ when others => -- OR "110"
+ Q_t(7 downto 0) := BusA or BusB;
+ F_Out(Flag_H) <= '0';
+ end case;
+ if ALU_Op(2 downto 0) = "111" then -- CP
+ F_Out(Flag_X) <= BusB(3);
+ F_Out(Flag_Y) <= BusB(5);
+ else
+ F_Out(Flag_X) <= Q_t(3);
+ F_Out(Flag_Y) <= Q_t(5);
+ end if;
+ if Q_t(7 downto 0) = "00000000" then
+ F_Out(Flag_Z) <= '1';
+ if Z16 = '1' then
+ F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC
+ end if;
+ else
+ F_Out(Flag_Z) <= '0';
+ end if;
+ F_Out(Flag_S) <= Q_t(7);
+ case ALU_Op(2 downto 0) is
+ when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP
+ when others =>
+ F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
+ Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
+ end case;
+ if Arith16 = '1' then
+ F_Out(Flag_S) <= F_In(Flag_S);
+ F_Out(Flag_Z) <= F_In(Flag_Z);
+ F_Out(Flag_P) <= F_In(Flag_P);
+ end if;
+ when "1100" =>
+ -- DAA
+ F_Out(Flag_H) <= F_In(Flag_H);
+ F_Out(Flag_C) <= F_In(Flag_C);
+ DAA_Q(7 downto 0) := unsigned(BusA);
+ DAA_Q(8) := '0';
+ if F_In(Flag_N) = '0' then
+ -- After addition
+ -- Alow > 9 or H = 1
+ if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
+ if (DAA_Q(3 downto 0) > 9) then
+ F_Out(Flag_H) <= '1';
+ else
+ F_Out(Flag_H) <= '0';
+ end if;
+ DAA_Q := DAA_Q + 6;
+ end if;
+ -- new Ahigh > 9 or C = 1
+ if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then
+ DAA_Q := DAA_Q + 96; -- 0x60
+ end if;
+ else
+ -- After subtraction
+ if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
+ if DAA_Q(3 downto 0) > 5 then
+ F_Out(Flag_H) <= '0';
+ end if;
+ DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6;
+ end if;
+ if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then
+ DAA_Q := DAA_Q - 352; -- 0x160
+ end if;
+ end if;
+ F_Out(Flag_X) <= DAA_Q(3);
+ F_Out(Flag_Y) <= DAA_Q(5);
+ F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8);
+ Q_t := std_logic_vector(DAA_Q(7 downto 0));
+ if DAA_Q(7 downto 0) = "00000000" then
+ F_Out(Flag_Z) <= '1';
+ else
+ F_Out(Flag_Z) <= '0';
+ end if;
+ F_Out(Flag_S) <= DAA_Q(7);
+ F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor
+ DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7));
+ when "1101" | "1110" =>
+ -- RLD, RRD
+ Q_t(7 downto 4) := BusA(7 downto 4);
+ if ALU_Op(0) = '1' then
+ Q_t(3 downto 0) := BusB(7 downto 4);
+ else
+ Q_t(3 downto 0) := BusB(3 downto 0);
+ end if;
+ F_Out(Flag_H) <= '0';
+ F_Out(Flag_N) <= '0';
+ F_Out(Flag_X) <= Q_t(3);
+ F_Out(Flag_Y) <= Q_t(5);
+ if Q_t(7 downto 0) = "00000000" then
+ F_Out(Flag_Z) <= '1';
+ else
+ F_Out(Flag_Z) <= '0';
+ end if;
+ F_Out(Flag_S) <= Q_t(7);
+ F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
+ Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
+ when "1001" =>
+ -- BIT
+ Q_t(7 downto 0) := BusB and BitMask;
+ F_Out(Flag_S) <= Q_t(7);
+ if Q_t(7 downto 0) = "00000000" then
+ F_Out(Flag_Z) <= '1';
+ F_Out(Flag_P) <= '1';
+ else
+ F_Out(Flag_Z) <= '0';
+ F_Out(Flag_P) <= '0';
+ end if;
+ F_Out(Flag_H) <= '1';
+ F_Out(Flag_N) <= '0';
+ F_Out(Flag_X) <= '0';
+ F_Out(Flag_Y) <= '0';
+ if IR(2 downto 0) /= "110" then
+ F_Out(Flag_X) <= BusB(3);
+ F_Out(Flag_Y) <= BusB(5);
+ end if;
+ when "1010" =>
+ -- SET
+ Q_t(7 downto 0) := BusB or BitMask;
+ when "1011" =>
+ -- RES
+ Q_t(7 downto 0) := BusB and not BitMask;
+ when "1000" =>
+ -- ROT
+ case IR(5 downto 3) is
+ when "000" => -- RLC
+ Q_t(7 downto 1) := BusA(6 downto 0);
+ Q_t(0) := BusA(7);
+ F_Out(Flag_C) <= BusA(7);
+ when "010" => -- RL
+ Q_t(7 downto 1) := BusA(6 downto 0);
+ Q_t(0) := F_In(Flag_C);
+ F_Out(Flag_C) <= BusA(7);
+ when "001" => -- RRC
+ Q_t(6 downto 0) := BusA(7 downto 1);
+ Q_t(7) := BusA(0);
+ F_Out(Flag_C) <= BusA(0);
+ when "011" => -- RR
+ Q_t(6 downto 0) := BusA(7 downto 1);
+ Q_t(7) := F_In(Flag_C);
+ F_Out(Flag_C) <= BusA(0);
+ when "100" => -- SLA
+ Q_t(7 downto 1) := BusA(6 downto 0);
+ Q_t(0) := '0';
+ F_Out(Flag_C) <= BusA(7);
+ when "110" => -- SLL (Undocumented) / SWAP
+ if Mode = 3 then
+ Q_t(7 downto 4) := BusA(3 downto 0);
+ Q_t(3 downto 0) := BusA(7 downto 4);
+ F_Out(Flag_C) <= '0';
+ else
+ Q_t(7 downto 1) := BusA(6 downto 0);
+ Q_t(0) := '1';
+ F_Out(Flag_C) <= BusA(7);
+ end if;
+ when "101" => -- SRA
+ Q_t(6 downto 0) := BusA(7 downto 1);
+ Q_t(7) := BusA(7);
+ F_Out(Flag_C) <= BusA(0);
+ when others => -- SRL
+ Q_t(6 downto 0) := BusA(7 downto 1);
+ Q_t(7) := '0';
+ F_Out(Flag_C) <= BusA(0);
+ end case;
+ F_Out(Flag_H) <= '0';
+ F_Out(Flag_N) <= '0';
+ F_Out(Flag_X) <= Q_t(3);
+ F_Out(Flag_Y) <= Q_t(5);
+ F_Out(Flag_S) <= Q_t(7);
+ if Q_t(7 downto 0) = "00000000" then
+ F_Out(Flag_Z) <= '1';
+ else
+ F_Out(Flag_Z) <= '0';
+ end if;
+ F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
+ Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
+ if ISet = "00" then
+ F_Out(Flag_P) <= F_In(Flag_P);
+ F_Out(Flag_S) <= F_In(Flag_S);
+ F_Out(Flag_Z) <= F_In(Flag_Z);
+ end if;
+ when others =>
+ null;
+ end case;
+ Q <= Q_t;
+ end process;
+
+end;
View
1,938 vhdl/t80/T80_MCode.vhd
@@ -0,0 +1,1938 @@
+--
+-- Z80 compatible microprocessor core
+--
+-- Version : 0242
+--
+-- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
+--
+-- All rights reserved
+--
+-- Redistribution and use in source and synthezised forms, with or without
+-- modification, are permitted provided that the following conditions are met:
+--
+-- Redistributions of source code must retain the above copyright notice,
+-- this list of conditions and the following disclaimer.
+--
+-- Redistributions in synthesized form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in the
+-- documentation and/or other materials provided with the distribution.
+--
+-- Neither the name of the author nor the names of other contributors may
+-- be used to endorse or promote products derived from this software without
+-- specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+-- POSSIBILITY OF SUCH DAMAGE.
+--
+-- Please report bugs to the author, but before you do so, please
+-- make sure that this is not a derivative work and that
+-- you have the latest version of this file.
+--
+-- The latest version of this file can be found at:
+-- http://www.opencores.org/cvsweb.shtml/t80/
+--
+-- Limitations :
+--
+-- File history :
+--
+-- 0208 : First complete release
+--
+-- 0211 : Fixed IM 1
+--
+-- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
+--
+-- 0235 : Added IM 2 fix by Mike Johnson
+--
+-- 0238 : Added NoRead signal
+--
+-- 0238b: Fixed instruction timing for POP and DJNZ
+--
+-- 0240 : Added (IX/IY+d) states, removed op-codes from mode 2 and added all remaining mode 3 op-codes
+--
+-- 0242 : Fixed I/O instruction timing, cleanup
+--
+
+library IEEE;
+use IEEE.std_logic_1164.all;
+use IEEE.numeric_std.all;
+
+entity T80_MCode is
+ generic(
+ Mode : integer := 0;
+ Flag_C : integer := 0;
+ Flag_N : integer := 1;
+ Flag_P : integer := 2;
+ Flag_X : integer := 3;
+ Flag_H : integer := 4;
+ Flag_Y : integer := 5;
+ Flag_Z : integer := 6;
+ Flag_S : integer := 7
+ );
+ port(
+ IR : in std_logic_vector(7 downto 0);
+ ISet : in std_logic_vector(1 downto 0);
+ MCycle : in std_logic_vector(2 downto 0);
+ F : in std_logic_vector(7 downto 0);
+ NMICycle : in std_logic;
+ IntCycle : in std_logic;
+ MCycles : out std_logic_vector(2 downto 0);
+ TStates : out std_logic_vector(2 downto 0);
+ Prefix : out std_logic_vector(1 downto 0); -- None,BC,ED,DD/FD
+ Inc_PC : out std_logic;
+ Inc_WZ : out std_logic;
+ IncDec_16 : out std_logic_vector(3 downto 0); -- BC,DE,HL,SP 0 is inc
+ Read_To_Reg : out std_logic;
+ Read_To_Acc : out std_logic;
+ Set_BusA_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI/DB,A,SP(L),SP(M),0,F
+ Set_BusB_To : out std_logic_vector(3 downto 0); -- B,C,D,E,H,L,DI,A,SP(L),SP(M),1,F,PC(L),PC(M),0
+ ALU_Op : out std_logic_vector(3 downto 0);
+ -- ADD, ADC, SUB, SBC, AND, XOR, OR, CP, ROT, BIT, SET, RES, DAA, RLD, RRD, None
+ Save_ALU : out std_logic;
+ PreserveC : out std_logic;
+ Arith16 : out std_logic;
+ Set_Addr_To : out std_logic_vector(2 downto 0); -- aNone,aXY,aIOA,aSP,aBC,aDE,aZI
+ IORQ : out std_logic;
+ Jump : out std_logic;
+ JumpE : out std_logic;
+ JumpXY : out std_logic;
+ Call : out std_logic;
+ RstP : out std_logic;
+ LDZ : out std_logic;
+ LDW : out std_logic;
+ LDSPHL : out std_logic;
+ Special_LD : out std_logic_vector(2 downto 0); -- A,I;A,R;I,A;R,A;None
+ ExchangeDH : out std_logic;
+ ExchangeRp : out std_logic;
+ ExchangeAF : out std_logic;
+ ExchangeRS : out std_logic;
+ I_DJNZ : out std_logic;
+ I_CPL : out std_logic;
+ I_CCF : out std_logic;