mirror of
https://github.com/Gehstock/Mist_FPGA.git
synced 2026-04-16 07:56:43 +00:00
Organize Files
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
#
|
||||
# Quartus II 64-Bit
|
||||
# Version 13.1.4 Build 182 03/12/2014 SJ Web Edition
|
||||
# Date created = 02:08:17 July 22, 2019
|
||||
# Date created = 21:40:59 July 23, 2019
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
@@ -49,9 +49,11 @@ set_global_assignment -name VHDL_FILE rtl/oricatmos.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/ula.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/ay8912.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/m6522.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/BASIC.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/ram48k.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/video.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/BASIC11.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/BASIC10.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/rom/BASIC22.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/T65/t65_MCode.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/T65/t65_alu.vhd
|
||||
set_global_assignment -name VHDL_FILE rtl/T65/t65.vhd
|
||||
@@ -214,10 +216,10 @@ set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -
|
||||
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
|
||||
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
|
||||
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
|
||||
# end DESIGN_PARTITION(Top)
|
||||
# -------------------------
|
||||
|
||||
# end ENTITY(OricAtmos_MiST)
|
||||
# --------------------------
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
||||
# --------------------------
|
||||
3
Computer_MiST/OricInFPGA_MiST/ReadMe.txt
Normal file
3
Computer_MiST/OricInFPGA_MiST/ReadMe.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
Oric 1 / Atmos
|
||||
|
||||
only 32768 kb ram
|
||||
BIN
Computer_MiST/OricInFPGA_MiST/Release/Oric_MiST(Rom1.0).rbf
Normal file
BIN
Computer_MiST/OricInFPGA_MiST/Release/Oric_MiST(Rom1.0).rbf
Normal file
Binary file not shown.
BIN
Computer_MiST/OricInFPGA_MiST/Release/Oric_MiST(Rom1.1uk).rbf
Normal file
BIN
Computer_MiST/OricInFPGA_MiST/Release/Oric_MiST(Rom1.1uk).rbf
Normal file
Binary file not shown.
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 176 KiB |
|
Before Width: | Height: | Size: 103 KiB After Width: | Height: | Size: 103 KiB |
@@ -55,9 +55,6 @@
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.std_logic_arith.all;
|
||||
use ieee.std_logic_unsigned.all;
|
||||
library WORK;
|
||||
library STD;
|
||||
USE STD.TEXTIO.ALL;
|
||||
|
||||
|
||||
entity oricatmos is
|
||||
@@ -67,8 +64,6 @@ entity oricatmos is
|
||||
K7_TAPEIN : in std_logic;
|
||||
K7_TAPEOUT : out std_logic;
|
||||
K7_REMOTE : out std_logic;
|
||||
-- PSG_RIGHT : out std_logic_vector(15 downto 0);
|
||||
-- PSG_LEFT : out std_logic_vector(15 downto 0);
|
||||
PSG_OUT : out std_logic_vector(15 downto 0);
|
||||
VIDEO_R : out std_logic;
|
||||
VIDEO_G : out std_logic;
|
||||
@@ -146,22 +141,19 @@ architecture RTL of oricatmos is
|
||||
|
||||
signal lSRAM_D : std_logic_vector(7 downto 0);
|
||||
signal ENA_1MHZ : std_logic;
|
||||
signal ROM_DO : std_logic_vector(7 downto 0);
|
||||
|
||||
signal ROM_DO : std_logic_vector(7 downto 0);
|
||||
|
||||
|
||||
signal ad : std_logic_vector(15 downto 0);
|
||||
signal SRAM_DO : std_logic_vector(7 downto 0);
|
||||
signal break : std_logic;
|
||||
signal ad : std_logic_vector(15 downto 0);
|
||||
signal SRAM_DO : std_logic_vector(7 downto 0);
|
||||
signal break : std_logic;
|
||||
|
||||
component keyboard port (
|
||||
clk_24 : in std_logic;
|
||||
clk : in std_logic;
|
||||
reset : in std_logic;
|
||||
|
||||
ps2_key : in std_logic_vector(10 downto 0);
|
||||
row : in std_logic_vector(7 downto 0);
|
||||
|
||||
col : in std_logic_vector(2 downto 0);
|
||||
ROWbit : out std_logic_vector(7 downto 0);
|
||||
swrst : out std_logic
|
||||
@@ -171,184 +163,141 @@ end component;
|
||||
begin
|
||||
RESETn <= not RESET;
|
||||
|
||||
------------------------------------------------------------
|
||||
-- GESTION CPU 6502
|
||||
------------------------------------------------------------
|
||||
cpu : entity work.T65
|
||||
port map (
|
||||
Mode => "00",
|
||||
Res_n => RESETn,
|
||||
Enable => '1',
|
||||
Clk => ula_phi2,
|
||||
Rdy => '1',
|
||||
Abort_n => '1',
|
||||
IRQ_n => cpu_irq,
|
||||
NMI_n => not break,
|
||||
SO_n => '1',
|
||||
R_W_n => cpu_rw,
|
||||
A => cpu_ad,
|
||||
DI => cpu_di,
|
||||
DO => cpu_do
|
||||
);
|
||||
inst_cpu : entity work.T65
|
||||
port map (
|
||||
Mode => "00",
|
||||
Res_n => RESETn,
|
||||
Enable => '1',
|
||||
Clk => ula_phi2,
|
||||
Rdy => '1',
|
||||
Abort_n => '1',
|
||||
IRQ_n => cpu_irq,
|
||||
NMI_n => not break,
|
||||
SO_n => '1',
|
||||
R_W_n => cpu_rw,
|
||||
A => cpu_ad,
|
||||
DI => cpu_di,
|
||||
DO => cpu_do
|
||||
);
|
||||
|
||||
ad <= ula_AD_SRAM when ula_PHI2 = '0' else cpu_ad(15 downto 0);
|
||||
|
||||
inst_ram : entity work.ram48k
|
||||
inst_ram : entity work.ram48k
|
||||
port map(
|
||||
clk => CLK_IN,
|
||||
cs => ula_CE_SRAM,
|
||||
oe => ula_OE_SRAM,
|
||||
we => ula_WE_SRAM,
|
||||
addr => ad,
|
||||
di => cpu_do,
|
||||
do => SRAM_DO
|
||||
);
|
||||
clk => CLK_IN,
|
||||
cs => ula_CE_SRAM,
|
||||
oe => ula_OE_SRAM,
|
||||
we => ula_WE_SRAM,
|
||||
addr => ad,
|
||||
di => cpu_do,
|
||||
do => SRAM_DO
|
||||
);
|
||||
|
||||
|
||||
inst_rom : entity work.BASIC
|
||||
inst_rom : entity work.BASIC11
|
||||
port map (
|
||||
clk => CLK_IN,
|
||||
addr => cpu_ad(13 downto 0),
|
||||
data => ROM_DO
|
||||
);
|
||||
clk => CLK_IN,
|
||||
addr => cpu_ad(13 downto 0),
|
||||
data => ROM_DO
|
||||
);
|
||||
|
||||
|
||||
------------------------------------------------------------
|
||||
-- GESTION ULA
|
||||
------------------------------------------------------------
|
||||
ulag : entity work.ULA
|
||||
port map (
|
||||
CLK => CLK_IN,
|
||||
PHI2 => ula_PHI2,
|
||||
CLK_4 => ula_CLK_4,
|
||||
RW => cpu_rw,
|
||||
RESETn => RESETn,
|
||||
MAPn => '1',
|
||||
DB => SRAM_DO,
|
||||
ADDR => cpu_ad(15 downto 0),
|
||||
inst_ula : entity work.ULA
|
||||
port map (
|
||||
CLK => CLK_IN,
|
||||
PHI2 => ula_PHI2,
|
||||
CLK_4 => ula_CLK_4,
|
||||
RW => cpu_rw,
|
||||
RESETn => RESETn,
|
||||
MAPn => '1',
|
||||
DB => SRAM_DO,
|
||||
ADDR => cpu_ad(15 downto 0),
|
||||
SRAM_AD => ula_AD_SRAM,
|
||||
SRAM_OE => ula_OE_SRAM,
|
||||
SRAM_CE => ula_CE_SRAM,
|
||||
SRAM_WE => ula_WE_SRAM,
|
||||
LATCH_SRAM => ula_LATCH_SRAM,
|
||||
CSIOn => ula_CSIOn,
|
||||
CSROMn => ula_CSROMn,
|
||||
CSRAMn => ula_CSRAMn,
|
||||
R => VIDEO_R,
|
||||
G => VIDEO_G,
|
||||
B => VIDEO_B,
|
||||
SYNC => VIDEO_SYNC,
|
||||
HSYNC => VIDEO_HSYNC,
|
||||
VSYNC => VIDEO_VSYNC
|
||||
);
|
||||
|
||||
SRAM_AD => ula_AD_SRAM,
|
||||
SRAM_OE => ula_OE_SRAM,
|
||||
SRAM_CE => ula_CE_SRAM,
|
||||
SRAM_WE => ula_WE_SRAM,
|
||||
LATCH_SRAM => ula_LATCH_SRAM,
|
||||
CSIOn => ula_CSIOn,
|
||||
CSROMn => ula_CSROMn,
|
||||
CSRAMn => ula_CSRAMn,
|
||||
R => VIDEO_R,
|
||||
G => VIDEO_G,
|
||||
B => VIDEO_B,
|
||||
SYNC => VIDEO_SYNC,
|
||||
HSYNC => VIDEO_HSYNC,
|
||||
VSYNC => VIDEO_VSYNC
|
||||
);
|
||||
|
||||
------------------------------------------------------------
|
||||
-- GESTION VIA
|
||||
------------------------------------------------------------
|
||||
ula_CSIO <= not(ula_CSIOn);
|
||||
inst_via : entity work.M6522
|
||||
ula_CSIO <= not(ula_CSIOn);
|
||||
inst_via : entity work.M6522
|
||||
port map (
|
||||
I_RS => cpu_ad(3 downto 0),
|
||||
I_DATA => cpu_do(7 downto 0),
|
||||
O_DATA => VIA_DO,
|
||||
O_DATA_OE_L => open,
|
||||
|
||||
I_RW_L => cpu_rw,
|
||||
I_CS1 => ula_CSIO,
|
||||
I_CS2_L => ula_IOCONTROL,
|
||||
|
||||
O_IRQ_L => cpu_irq, -- note, not open drain
|
||||
|
||||
-- PORT A
|
||||
I_CA1 => '1', -- PRT_ACK
|
||||
I_CA2 => '1', -- psg_bdir
|
||||
O_CA2 => psg_bdir, -- via_ca2_out
|
||||
O_CA2_OE_L => open,
|
||||
|
||||
I_PA => via_pa_in,
|
||||
O_PA => via_pa_out,
|
||||
O_PA_OE_L => via_pa_out_oe,
|
||||
|
||||
-- PORT B
|
||||
I_CB1 => K7_TAPEIN,
|
||||
O_CB1 => via_cb1_out,
|
||||
O_CB1_OE_L => via_cb1_oe_l,
|
||||
|
||||
I_CB2 => '1',
|
||||
O_CB2 => via_cb2_out,
|
||||
O_CB2_OE_L => via_cb2_oe_l,
|
||||
|
||||
I_PB => via_in,
|
||||
O_PB => via_out,
|
||||
O_PB_OE_L => via_oe_l,
|
||||
|
||||
--
|
||||
RESET_L => RESETn,
|
||||
I_P2_H => ula_phi2,
|
||||
ENA_4 => '1',
|
||||
CLK => ula_CLK_4
|
||||
);
|
||||
I_RS => cpu_ad(3 downto 0),
|
||||
I_DATA => cpu_do(7 downto 0),
|
||||
O_DATA => VIA_DO,
|
||||
I_RW_L => cpu_rw,
|
||||
I_CS1 => ula_CSIO,
|
||||
I_CS2_L => ula_IOCONTROL,
|
||||
O_IRQ_L => cpu_irq, -- note, not open drain
|
||||
I_CA1 => '1', -- PRT_ACK
|
||||
I_CA2 => '1', -- psg_bdir
|
||||
O_CA2 => psg_bdir, -- via_ca2_out
|
||||
I_PA => via_pa_in,
|
||||
O_PA => via_pa_out,
|
||||
O_PA_OE_L => via_pa_out_oe,
|
||||
I_CB1 => K7_TAPEIN,
|
||||
O_CB1 => via_cb1_out,
|
||||
O_CB1_OE_L => via_cb1_oe_l,
|
||||
I_CB2 => '1',
|
||||
O_CB2 => via_cb2_out,
|
||||
O_CB2_OE_L => via_cb2_oe_l,
|
||||
I_PB => via_in,
|
||||
O_PB => via_out,
|
||||
O_PB_OE_L => via_oe_l,
|
||||
RESET_L => RESETn,
|
||||
I_P2_H => ula_phi2,
|
||||
ENA_4 => '1',
|
||||
CLK => ula_CLK_4
|
||||
);
|
||||
|
||||
inst_psg : entity work.ay8912
|
||||
inst_psg : entity work.ay8912
|
||||
port map (
|
||||
cpuclk => CLK_IN,
|
||||
reset => RESETn,
|
||||
cs => '1',
|
||||
bc0 => psg_bdir,
|
||||
bdir => via_cb2_out,
|
||||
Data_in => via_pa_out,
|
||||
Data_out => via_pa_in,
|
||||
IO_A => x"FF",
|
||||
chanA => open,
|
||||
chanB => open,
|
||||
chanC => open,
|
||||
-- Arechts => PSG_RIGHT,
|
||||
-- Alinks => PSG_LEFT,
|
||||
Amono => PSG_OUT
|
||||
);
|
||||
cpuclk => CLK_IN,
|
||||
reset => RESETn,
|
||||
cs => '1',
|
||||
bc0 => psg_bdir,
|
||||
bdir => via_cb2_out,
|
||||
Data_in => via_pa_out,
|
||||
Data_out => via_pa_in,
|
||||
IO_A => x"FF",
|
||||
Amono => PSG_OUT
|
||||
);
|
||||
|
||||
inst_key : keyboard
|
||||
inst_key : keyboard
|
||||
port map(
|
||||
clk_24 => CLK_IN,
|
||||
clk => ula_phi2,
|
||||
reset => not RESETn,
|
||||
ps2_key => ps2_key,
|
||||
row => via_pa_out,
|
||||
col => via_out(2 downto 0),
|
||||
ROWbit => KEY_ROW,
|
||||
swrst => break
|
||||
);
|
||||
clk_24 => CLK_IN,
|
||||
clk => ula_phi2,
|
||||
reset => not RESETn,
|
||||
ps2_key => ps2_key,
|
||||
row => via_pa_out,
|
||||
col => via_out(2 downto 0),
|
||||
ROWbit => KEY_ROW,
|
||||
swrst => break
|
||||
);
|
||||
|
||||
-- Keyboard
|
||||
via_in <= x"F7" when (KEY_ROW or via_pa_out) = x"FF" else x"FF";
|
||||
|
||||
------------------------------------------------------------
|
||||
-- GESTION PORT K7
|
||||
------------------------------------------------------------
|
||||
K7_TAPEOUT <= via_out(7);
|
||||
K7_REMOTE <= via_out(6);
|
||||
|
||||
|
||||
|
||||
via_in <= x"F7" when (KEY_ROW or via_pa_out) = x"FF" else x"FF";
|
||||
K7_TAPEOUT <= via_out(7);
|
||||
K7_REMOTE <= via_out(6);
|
||||
ula_IOCONTROL <= '0'; -- ula_IOCONTROL <= IOCONTROL;
|
||||
process
|
||||
begin
|
||||
wait until rising_edge(clk_in);
|
||||
|
||||
-- expansion port
|
||||
if cpu_rw = '1' and ula_IOCONTROL = '1' and ula_CSIOn = '0' then
|
||||
cpu_di <= SRAM_DO;
|
||||
-- Via
|
||||
process begin
|
||||
wait until rising_edge(clk_in);
|
||||
if cpu_rw = '1' and ula_IOCONTROL = '1' and ula_CSIOn = '0' then
|
||||
cpu_di <= SRAM_DO;-- expansion port
|
||||
elsif cpu_rw = '1' and ula_IOCONTROL = '0' and ula_CSIOn = '0' and ula_LATCH_SRAM = '0' then
|
||||
cpu_di <= VIA_DO;
|
||||
-- ROM
|
||||
elsif cpu_rw = '1' and ula_IOCONTROL = '0' and ula_CSROMn = '0' then
|
||||
cpu_di <= ROM_DO;
|
||||
-- Read data
|
||||
cpu_di <= VIA_DO;-- Via
|
||||
elsif cpu_rw = '1' and ula_IOCONTROL = '0' and ula_CSROMn = '0' then
|
||||
cpu_di <= ROM_DO; -- ROM
|
||||
elsif cpu_rw = '1' and ula_IOCONTROL = '0' and ula_phi2 = '1' and ula_LATCH_SRAM = '0' then
|
||||
cpu_di <= SRAM_DO;
|
||||
cpu_di <= SRAM_DO;-- Read data
|
||||
end if;
|
||||
end process;
|
||||
end process;
|
||||
|
||||
end RTL;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all,ieee.numeric_std.all;
|
||||
|
||||
entity BASIC is
|
||||
entity BASIC22 is
|
||||
port (
|
||||
clk : in std_logic;
|
||||
addr : in std_logic_vector(13 downto 0);
|
||||
@@ -9,7 +9,7 @@ port (
|
||||
);
|
||||
end entity;
|
||||
|
||||
architecture prom of BASIC is
|
||||
architecture prom of BASIC22 is
|
||||
type rom is array(0 to 16383) of std_logic_vector(7 downto 0);
|
||||
signal rom_data: rom := (
|
||||
X"4C",X"CC",X"EC",X"4C",X"71",X"C4",X"72",X"C9",X"91",X"C6",X"86",X"E9",X"D0",X"E9",X"15",X"CD",
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
107
common/IO/PIA8255.v
Normal file
107
common/IO/PIA8255.v
Normal file
@@ -0,0 +1,107 @@
|
||||
/****************************************************************************
|
||||
PIA 8255
|
||||
|
||||
Version 050111
|
||||
|
||||
Copyright(C) 2004,2005 Tatsuyuki Satoh
|
||||
|
||||
This software is provided "AS IS", with NO WARRANTY.
|
||||
NON-COMMERCIAL USE ONLY
|
||||
|
||||
Histry:
|
||||
2005. 1.11 Ver.0.1
|
||||
|
||||
Note:
|
||||
|
||||
Distributing all and a part is prohibited.
|
||||
Because this version is developer-alpha version.
|
||||
|
||||
mode 0,1,2 handshake is not supported , mode 3 bit I/O only
|
||||
****************************************************************************/
|
||||
module PIA8255(
|
||||
I_RESET,
|
||||
I_A,
|
||||
I_CS,
|
||||
I_RD,
|
||||
I_WR,
|
||||
I_D,
|
||||
O_D,
|
||||
//
|
||||
I_PA,O_PA,
|
||||
//
|
||||
I_PB,O_PB,
|
||||
//
|
||||
I_PC,O_PC
|
||||
);
|
||||
input I_RESET;
|
||||
input [1:0] I_A;
|
||||
input I_CS;
|
||||
input I_WR;
|
||||
input I_RD;
|
||||
input [7:0] I_D;
|
||||
output [7:0] O_D;
|
||||
|
||||
input [7:0] I_PA,I_PB,I_PC;
|
||||
output [7:0] O_PA,O_PB,O_PC;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
reg [7:0] pa_o,pb_o,pc_o;
|
||||
reg pa_dir , pb_dir , pcl_dir , pch_dir;
|
||||
reg [1:0] pa_mode;
|
||||
reg pb_mode;
|
||||
|
||||
// wirte data
|
||||
always @(negedge I_WR or posedge I_RESET)
|
||||
begin
|
||||
if(I_RESET) begin
|
||||
pa_o <= 8'h00;
|
||||
pb_o <= 8'h00;
|
||||
pc_o <= 8'h00;
|
||||
pa_mode <= 2'b00;
|
||||
pa_dir <= 1'b1;
|
||||
pcl_dir <= 1'b1;
|
||||
pb_mode <= 1'b0;
|
||||
pb_dir <= 1'b1;
|
||||
pch_dir <= 1'b1;
|
||||
end else if(I_CS) begin
|
||||
case(I_A)
|
||||
2'b00:pa_o <= I_D;
|
||||
2'b01:pb_o <= I_D;
|
||||
2'b10:pc_o <= I_D;
|
||||
2'b11:begin
|
||||
if(I_D[7])
|
||||
begin
|
||||
// mode set
|
||||
pa_mode <= I_D[6:5];
|
||||
pa_dir <= I_D[4];
|
||||
pch_dir <= I_D[3];
|
||||
pb_mode <= I_D[2];
|
||||
pb_dir <= I_D[1];
|
||||
pcl_dir <= I_D[0];
|
||||
end else begin
|
||||
// bit operation
|
||||
pc_o[I_D[3:1]] <= I_D[0];
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// read data
|
||||
//wire read_gate = I_CS & I_RD;
|
||||
wire [7:0] pa_r = pa_dir ? I_PA : pa_o;
|
||||
wire [7:0] pb_r = pb_dir ? I_PB : pb_o;
|
||||
wire [7:0] pc_r = { pch_dir ? I_PC[7:4] : pc_o[7:4] , pcl_dir ? I_PC[3:0] : pc_o[3:0] };
|
||||
wire [7:0] ct_r = {1'b0,pa_mode,pa_dir,pcl_dir,pb_mode,pb_dir,pch_dir};
|
||||
|
||||
assign O_D = (I_A==2'b00) ? pa_r :
|
||||
(I_A==2'b01) ? pb_r :
|
||||
(I_A==2'b10) ? pc_r :
|
||||
ct_r;
|
||||
|
||||
// port output
|
||||
assign O_PA = pa_o;
|
||||
assign O_PB = pb_o;
|
||||
assign O_PC = pc_o;
|
||||
|
||||
endmodule
|
||||
138
common/IO/i8253.vhd
Normal file
138
common/IO/i8253.vhd
Normal file
@@ -0,0 +1,138 @@
|
||||
--
|
||||
-- i8253.vhd
|
||||
--
|
||||
-- Intel 8253 (PIT:Programmable Interval Timer) partiality compatible module
|
||||
-- for MZ-700 on FPGA
|
||||
--
|
||||
-- PIT main module
|
||||
--
|
||||
-- Nibbles Lab. 2005
|
||||
--
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
-- Uncomment the following lines to use the declarations that are
|
||||
-- provided for instantiating Xilinx primitive components.
|
||||
--library UNISIM;
|
||||
--use UNISIM.VComponents.all;
|
||||
|
||||
entity i8253 is
|
||||
Port ( RST : in std_logic;
|
||||
CLK : in std_logic;
|
||||
A : in std_logic_vector(1 downto 0);
|
||||
DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0);
|
||||
CS : in std_logic;
|
||||
WR : in std_logic;
|
||||
RD : in std_logic;
|
||||
CLK0 : in std_logic;
|
||||
GATE0 : in std_logic;
|
||||
OUT0 : out std_logic;
|
||||
CLK1 : in std_logic;
|
||||
GATE1 : in std_logic;
|
||||
OUT1 : out std_logic;
|
||||
CLK2 : in std_logic;
|
||||
GATE2 : in std_logic;
|
||||
OUT2 : out std_logic);
|
||||
end i8253;
|
||||
|
||||
architecture Behavioral of i8253 is
|
||||
|
||||
signal WRD0 : std_logic;
|
||||
signal WRD1 : std_logic;
|
||||
signal WRD2 : std_logic;
|
||||
signal WRM0 : std_logic;
|
||||
signal WRM1 : std_logic;
|
||||
signal WRM2 : std_logic;
|
||||
--signal RD0 : std_logic;
|
||||
signal RD1 : std_logic;
|
||||
signal RD2 : std_logic;
|
||||
signal DO0 : std_logic_vector(7 downto 0);
|
||||
signal DO1 : std_logic_vector(7 downto 0);
|
||||
signal DO2 : std_logic_vector(7 downto 0);
|
||||
|
||||
component counter0
|
||||
Port ( DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0);
|
||||
WRD : in std_logic;
|
||||
WRM : in std_logic;
|
||||
KCLK : in std_logic;
|
||||
CLK : in std_logic;
|
||||
GATE : in std_logic;
|
||||
POUT : out std_logic);
|
||||
end component;
|
||||
|
||||
component counter1
|
||||
Port ( DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0);
|
||||
WRD : in std_logic;
|
||||
WRM : in std_logic;
|
||||
KCLK : in std_logic;
|
||||
CLK : in std_logic;
|
||||
GATE : in std_logic;
|
||||
POUT : out std_logic);
|
||||
end component;
|
||||
|
||||
component counter2
|
||||
Port ( DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0);
|
||||
WRD : in std_logic;
|
||||
WRM : in std_logic;
|
||||
KCLK : in std_logic;
|
||||
RD : in std_logic;
|
||||
CLK : in std_logic;
|
||||
GATE : in std_logic;
|
||||
POUT : out std_logic);
|
||||
end component;
|
||||
|
||||
begin
|
||||
|
||||
WRD0<=WR when CS='0' and A="00" else '1';
|
||||
WRD1<=WR when CS='0' and A="01" else '1';
|
||||
WRD2<=WR when CS='0' and A="10" else '1';
|
||||
WRM0<=WR when CS='0' and A="11" and DI(7 downto 6)="00" else '1';
|
||||
WRM1<=WR when CS='0' and A="11" and DI(7 downto 6)="01" else '1';
|
||||
WRM2<=WR when CS='0' and A="11" and DI(7 downto 6)="10" else '1';
|
||||
-- RD0<=RD when CS='0' and A="00" else '1';
|
||||
RD1<=RD when CS='0' and A="01" else '1';
|
||||
RD2<=RD when CS='0' and A="10" else '1';
|
||||
|
||||
DO<=DO0 when CS='0' and A="00" else
|
||||
DO1 when CS='0' and A="01" else
|
||||
DO2 when CS='0' and A="10" else (others=>'1');
|
||||
|
||||
CTR0 : counter0 port map (
|
||||
DI => DI,
|
||||
DO => DO0,
|
||||
WRD => WRD0,
|
||||
WRM => WRM0,
|
||||
KCLK => CLK,
|
||||
CLK => CLK0,
|
||||
GATE => GATE0,
|
||||
POUT => OUT0);
|
||||
|
||||
CTR1 : counter1 port map (
|
||||
DI => DI,
|
||||
DO => DO1,
|
||||
WRD => WRD1,
|
||||
WRM => WRM1,
|
||||
KCLK => CLK,
|
||||
CLK => CLK1,
|
||||
GATE => GATE1,
|
||||
POUT => OUT1);
|
||||
|
||||
CTR2 : counter2 port map (
|
||||
DI => DI,
|
||||
DO => DO2,
|
||||
WRD => WRD2,
|
||||
WRM => WRM2,
|
||||
KCLK => CLK,
|
||||
RD => RD2,
|
||||
CLK => CLK2,
|
||||
GATE => GATE2,
|
||||
POUT => OUT2);
|
||||
|
||||
end Behavioral;
|
||||
174
common/RIOT.sv
Normal file
174
common/RIOT.sv
Normal file
@@ -0,0 +1,174 @@
|
||||
/* Atari on an FPGA
|
||||
Masters of Engineering Project
|
||||
Cornell University, 2007
|
||||
Daniel Beer
|
||||
RIOT.v
|
||||
Redesign of the MOS 6532 chip. Provides RAM, I/O and timers to the Atari.
|
||||
*/
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "riot.vh"
|
||||
module RIOT(A, // Address bus input
|
||||
Din, // Data bus input
|
||||
Dout, // Data bus output
|
||||
CS, // Chip select input
|
||||
CS_n, // Active low chip select input
|
||||
R_W_n, // Active low read/write input
|
||||
RS_n, // Active low rom select input
|
||||
RES_n, // Active low reset input
|
||||
IRQ_n, // Active low interrupt output
|
||||
CLK, // Clock input
|
||||
PAin, // 8 bit port A input
|
||||
PAout, // 8 bit port A output
|
||||
PBin, // 8 bit port B input
|
||||
PBout);// 8 bit port B output
|
||||
input [6:0] A;
|
||||
input [7:0] Din;
|
||||
output [7:0] Dout;
|
||||
input CS, CS_n, R_W_n, RS_n, RES_n, CLK;
|
||||
output IRQ_n;
|
||||
input [7:0] PAin, PBin;
|
||||
output [7:0] PAout, PBout; // Output register
|
||||
reg [7:0] Dout; // RAM allocation
|
||||
reg [7:0] RAM[127:0]; // I/O registers
|
||||
reg [7:0] DRA, DRB; // Data registers
|
||||
reg [7:0] DDRA, DDRB; // Data direction registers
|
||||
wire PA7;
|
||||
reg R_PA7;
|
||||
assign PA7 = (PAin[7] & ~DDRA[7]) | (DRA[7] & DDRA[7]);
|
||||
assign PAout = DRA & DDRA;
|
||||
assign PBout = DRB & DDRB;
|
||||
// Timer registers
|
||||
reg [8:0] Timer;
|
||||
reg [9:0] Prescaler;
|
||||
reg [1:0] Timer_Mode;
|
||||
reg Timer_Int_Flag, PA7_Int_Flag, Timer_Int_Enable, PA7_Int_Enable, PA7_Int_Mode; // Timer prescaler constants
|
||||
wire [9:0] PRESCALER_VALS[3:0];
|
||||
assign PRESCALER_VALS[0] = 10'd0;
|
||||
assign PRESCALER_VALS[1] = 10'd7;
|
||||
assign PRESCALER_VALS[2] = 10'd63;
|
||||
assign PRESCALER_VALS[3] = 10'd1023;
|
||||
// Interrupt
|
||||
assign IRQ_n = ~(Timer_Int_Flag & Timer_Int_Enable | PA7_Int_Flag & PA7_Int_Enable);
|
||||
// Operation decoding
|
||||
wire [6:0] op;
|
||||
reg [6:0] R_op;
|
||||
assign op = {RS_n, R_W_n, A[4:0]};
|
||||
// Registered data in
|
||||
reg [7:0] R_Din;
|
||||
integer cnt;
|
||||
// Software operations
|
||||
always @(posedge CLK)
|
||||
begin
|
||||
// Reset operation
|
||||
if (~RES_n) begin
|
||||
DRA <= 8'b0;
|
||||
DDRA <= 8'b0;
|
||||
DRB <= 8'b00010100;
|
||||
DDRB <= 8'b00010100;
|
||||
Timer_Int_Flag <= 1'b0;
|
||||
PA7_Int_Flag <= 1'b0;
|
||||
PA7_Int_Enable <= 1'b0;
|
||||
PA7_Int_Mode <= 1'b0;
|
||||
// Fill RAM with 0s
|
||||
for (cnt = 0; cnt < 128; cnt = cnt + 1)
|
||||
RAM[cnt] <= 8'b0;
|
||||
R_PA7 <= 1'b0;
|
||||
R_op <= `NOP;
|
||||
R_Din <= 8'b0;
|
||||
end
|
||||
// If the chip is enabled, execute an operation
|
||||
else if (CS & ~CS_n) begin
|
||||
// Register inputs for use later
|
||||
R_PA7 <= PA7;
|
||||
R_op <= op;
|
||||
R_Din <= Din;
|
||||
// Update the timer interrupt flag
|
||||
casex (op)
|
||||
`WRITE_TIMER: Timer_Int_Flag <= 1'b0;
|
||||
`READ_TIMER: Timer_Int_Flag <= 1'b0;
|
||||
default: if (Timer == 9'b111111111) Timer_Int_Flag <= 1'b1;
|
||||
endcase
|
||||
// Update the port A interrupt flag
|
||||
casex (op)
|
||||
`READ_INT_FLAG: PA7_Int_Flag <= 1'b0;
|
||||
default: PA7_Int_Flag <= PA7_Int_Flag | (PA7 != R_PA7 & PA7 == PA7_Int_Mode);
|
||||
endcase
|
||||
// Process the current operation
|
||||
casex(op) // RAM access
|
||||
`READ_RAM: Dout <= RAM[A];
|
||||
`WRITE_RAM: RAM[A] <= Din;
|
||||
// Port A data access
|
||||
`READ_DRA : Dout <= (PAin & ~DDRA) | (DRA & DDRA);
|
||||
`WRITE_DRA: DRA <= Din;
|
||||
// Port A direction register access
|
||||
`READ_DDRA: Dout <= DDRA;
|
||||
`WRITE_DDRA: DDRA <= Din;
|
||||
// Port B data access
|
||||
`READ_DRB: Dout <= (PBin & ~DDRB) | (DRB & DDRB);
|
||||
`WRITE_DRB: DRB <= Din;
|
||||
// Port B direction register access
|
||||
`READ_DDRB: Dout <= DDRB;
|
||||
`WRITE_DDRB: DDRB <= Din;
|
||||
// Timer access
|
||||
`READ_TIMER: Dout <= Timer[7:0];
|
||||
// Status register access
|
||||
`READ_INT_FLAG: Dout <= {Timer_Int_Flag, PA7_Int_Flag, 6'b0};
|
||||
// Enable the port A interrupt
|
||||
`WRITE_EDGE_DETECT: begin
|
||||
PA7_Int_Mode <= A[0]; PA7_Int_Enable <= A[1];
|
||||
end
|
||||
endcase
|
||||
end
|
||||
// Even if the chip is not enabled, update background functions
|
||||
else begin
|
||||
// Update the timer interrupt
|
||||
if (Timer == 9'b111111111)
|
||||
Timer_Int_Flag <= 1'b1;
|
||||
// Update the port A interrupt
|
||||
R_PA7 <= PA7;
|
||||
PA7_Int_Flag <= PA7_Int_Flag | (PA7 != R_PA7 & PA7 == PA7_Int_Mode);
|
||||
// Set the operation to a NOP
|
||||
R_op <=`NOP;
|
||||
end
|
||||
end
|
||||
// Update the timer at the negative edge of the clock
|
||||
always @(negedge CLK)begin
|
||||
// Reset operation
|
||||
if (~RES_n) begin
|
||||
Timer <= 9'b0;
|
||||
Timer_Mode <= 2'b0;
|
||||
Prescaler <= 10'b0;
|
||||
Timer_Int_Enable <= 1'b0;
|
||||
end
|
||||
// Otherwise, process timer operations
|
||||
else
|
||||
casex
|
||||
(R_op)
|
||||
// Write value to the timer and update the prescaler based on the address
|
||||
`WRITE_TIMER:begin
|
||||
Timer <= {1'b0, R_Din};
|
||||
Timer_Mode <= R_op[1:0];
|
||||
Prescaler <= PRESCALER_VALS[R_op[1:0]];
|
||||
Timer_Int_Enable <= R_op[3];
|
||||
end
|
||||
// Otherwise decrement the prescaler and if necessary the timer.
|
||||
// The prescaler holds a variable number of counts that must be
|
||||
// run before the timer is decremented
|
||||
default:if (Timer != 9'b100000000) begin
|
||||
if (Prescaler != 10'b0)
|
||||
Prescaler <= Prescaler - 10'b1;
|
||||
else begin
|
||||
if (Timer == 9'b0)
|
||||
begin
|
||||
Prescaler <= 10'b0;
|
||||
Timer_Mode <= 2'b0;
|
||||
end
|
||||
else
|
||||
Prescaler <= PRESCALER_VALS[Timer_Mode];
|
||||
Timer <= Timer - 9'b1;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
477
common/TIA.sv
Normal file
477
common/TIA.sv
Normal file
@@ -0,0 +1,477 @@
|
||||
/* Atari on an FPGA
|
||||
Masters of Engineering Project
|
||||
Cornell University, 2007
|
||||
Daniel Beer
|
||||
TIA.v
|
||||
Redesign of the Atari TIA chip. Provides the Atari with video generation,
|
||||
sound generation and I/O.
|
||||
*/
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`include "tia.vh"
|
||||
module TIA(A, // Address bus input
|
||||
Din, // Data bus input
|
||||
Dout, // Data bus output
|
||||
CS_n, // Active low chip select input
|
||||
CS, // Chip select input
|
||||
R_W_n, // Active low read/write input
|
||||
RDY, // CPU ready output
|
||||
MASTERCLK, // 3.58 Mhz pixel clock input
|
||||
CLK2, // 1.19 Mhz bus clock input
|
||||
idump_in, // Dumped I/O
|
||||
Ilatch, // Latched I/O
|
||||
HSYNC, // Video horizontal sync output
|
||||
HBLANK, // Video horizontal blank output
|
||||
VSYNC, // Video vertical sync output
|
||||
VBLANK, // Video vertical sync output
|
||||
COLOROUT, // Indexed color output
|
||||
RES_n, // Active low reset input
|
||||
AUD0, //audio pin 0
|
||||
AUD1, //audio pin 1
|
||||
audv0, //audio volume for use with external xformer module
|
||||
audv1); //audio volume for use with external xformer module
|
||||
input [5:0] A;
|
||||
input [7:0] Din;
|
||||
output [7:0] Dout;
|
||||
input [2:0] CS_n;
|
||||
input CS;
|
||||
input R_W_n;
|
||||
output RDY;
|
||||
input MASTERCLK;
|
||||
input CLK2;
|
||||
input [1:0] Ilatch;
|
||||
input [3:0] idump_in;
|
||||
output HSYNC, HBLANK;
|
||||
output VSYNC, VBLANK;
|
||||
output [7:0] COLOROUT;
|
||||
input RES_n;
|
||||
output AUD0, AUD1;
|
||||
output reg [3:0] audv0, audv1;
|
||||
// Data output register
|
||||
reg [7:0] Dout;
|
||||
// Video control signal registers
|
||||
wire HSYNC;
|
||||
reg VSYNC, VBLANK;
|
||||
// Horizontal pixel counter
|
||||
reg [7:0] hCount;
|
||||
reg [3:0] hCountReset;
|
||||
reg clk_30;
|
||||
reg [7:0] clk_30_count;
|
||||
|
||||
wire [3:0] Idump;
|
||||
|
||||
// Pixel counter update
|
||||
always @(posedge MASTERCLK)
|
||||
begin
|
||||
// Reset operation
|
||||
if (~RES_n) begin
|
||||
hCount <= 8'd0;
|
||||
hCountReset[3:1] <= 3'd0;
|
||||
clk_30 <= 0;
|
||||
clk_30_count <= 0;
|
||||
latchedInputs <= 2'b11;
|
||||
end
|
||||
else begin
|
||||
if (inputLatchReset)
|
||||
latchedInputs <= 2'b11;
|
||||
else
|
||||
latchedInputs <= latchedInputs & Ilatch;
|
||||
|
||||
if (clk_30_count == 57) begin
|
||||
clk_30 <= ~clk_30;
|
||||
clk_30_count <= 0;
|
||||
end else begin
|
||||
clk_30_count <= clk_30_count + 1;
|
||||
end
|
||||
// Increment the count and reset if necessary
|
||||
if ((hCountReset[3]) ||(hCount == 8'd227))
|
||||
hCount <= 8'd0;
|
||||
else
|
||||
hCount <= hCount + 8'd1;
|
||||
// Software resets are delayed by three cycles
|
||||
hCountReset[3:1] <= hCountReset[2:0];
|
||||
end
|
||||
end
|
||||
assign HSYNC = (hCount >= 8'd20) && (hCount < 8'd36);
|
||||
assign HBLANK = (hCount < 8'd68);
|
||||
// Screen object registers
|
||||
// These registers are set by the software and used to generate pixels
|
||||
reg [7:0] player0Pos, player1Pos, missile0Pos, missile1Pos, ballPos;
|
||||
reg [4:0] player0Size, player1Size;
|
||||
reg [7:0] player0Color, player1Color, ballColor, pfColor, bgColor;
|
||||
reg [3:0] player0Motion, player1Motion, missile0Motion, missile1Motion,
|
||||
ballMotion;
|
||||
reg missile0Enable, missile1Enable, ballEnable, R_ballEnable;
|
||||
reg [1:0] ballSize;
|
||||
reg [19:0] pfGraphic;
|
||||
reg [7:0] player0Graphic, player1Graphic;
|
||||
reg [7:0] R_player0Graphic, R_player1Graphic;
|
||||
reg pfReflect, player0Reflect, player1Reflect;
|
||||
reg prioCtrl;
|
||||
reg pfColorCtrl;
|
||||
reg [14:0] collisionLatch;
|
||||
reg missile0Lock, missile1Lock;
|
||||
reg player0VertDelay, player1VertDelay, ballVertDelay;
|
||||
reg [3:0] audc0, audc1;
|
||||
reg [4:0] audf0, audf1;
|
||||
// Pixel number calculation
|
||||
wire [7:0] pixelNum;
|
||||
|
||||
|
||||
//audio control
|
||||
audio audio_ctrl(.AUDC0(audc0),
|
||||
.AUDC1(audc1),
|
||||
.AUDF0(audf0),
|
||||
.AUDF1(audf1),
|
||||
.CLK_30(clk_30), //30khz clock
|
||||
.AUD0(AUD0),
|
||||
.AUD1(AUD1));
|
||||
|
||||
assign pixelNum = (hCount >= 8'd68) ? (hCount - 8'd68) : 8'd227;
|
||||
|
||||
// Pixel tests. For each pixel and screen object, a test is done based on the
|
||||
// screen objects register to determine if the screen object should show on that
|
||||
// pixel. The results of all the tests are fed into logic to pick which displayed
|
||||
// object has priority and color the pixel the color of that object.
|
||||
// Playfield pixel test
|
||||
wire [5:0] pfPixelNum;
|
||||
wire pfPixelOn, pfLeftPixelVal, pfRightPixelVal;
|
||||
assign pfPixelNum = pixelNum[7:2];
|
||||
assign pfLeftPixelVal = pfGraphic[pfPixelNum];
|
||||
assign pfRightPixelVal = (pfReflect == 1'b0)? pfGraphic[pfPixelNum - 6'd20]:
|
||||
pfGraphic[6'd39 - pfPixelNum];
|
||||
assign pfPixelOn = (pfPixelNum < 6'd20)? pfLeftPixelVal : pfRightPixelVal;
|
||||
// Player 0 sprite pixel test
|
||||
wire pl0PixelOn;
|
||||
wire [7:0] pl0Mask, pl0MaskDel;
|
||||
assign pl0MaskDel = (player0VertDelay)? R_player0Graphic : player0Graphic;
|
||||
assign pl0Mask = (!player0Reflect)? pl0MaskDel : {pl0MaskDel[0], pl0MaskDel[1],
|
||||
pl0MaskDel[2], pl0MaskDel[3],
|
||||
pl0MaskDel[4], pl0MaskDel[5],
|
||||
pl0MaskDel[6], pl0MaskDel[7]};
|
||||
objPixelOn player0_test(pixelNum, player0Pos, player0Size[2:0], pl0Mask, pl0PixelOn);
|
||||
// Player 1 sprite pixel test
|
||||
wire pl1PixelOn;
|
||||
wire [7:0] pl1Mask, pl1MaskDel;
|
||||
assign pl1MaskDel = (player1VertDelay)? R_player1Graphic : player1Graphic;
|
||||
assign pl1Mask = (!player1Reflect)? pl1MaskDel : {pl1MaskDel[0], pl1MaskDel[1],
|
||||
pl1MaskDel[2], pl1MaskDel[3],
|
||||
pl1MaskDel[4], pl1MaskDel[5],
|
||||
pl1MaskDel[6], pl1MaskDel[7]};
|
||||
objPixelOn player1_test(pixelNum, player1Pos, player1Size[2:0], pl1Mask, pl1PixelOn);
|
||||
// Missile 0 pixel test
|
||||
wire mis0PixelOn, mis0PixelOut;
|
||||
wire [7:0] mis0ActualPos;
|
||||
reg [7:0] mis0Mask;
|
||||
always @(player0Size)
|
||||
begin
|
||||
case(player0Size[4:3])
|
||||
2'd0: mis0Mask <= 8'h01;
|
||||
2'd1: mis0Mask <= 8'h03;
|
||||
2'd2: mis0Mask <= 8'h0F;
|
||||
2'd3: mis0Mask <= 8'hFF;
|
||||
endcase
|
||||
end
|
||||
assign mis0ActualPos = (missile0Lock)? player0Pos : missile0Pos;
|
||||
objPixelOn missile0_test(pixelNum, mis0ActualPos, player0Size[2:0], mis0Mask, mis0PixelOut);
|
||||
assign mis0PixelOn = mis0PixelOut && missile0Enable;
|
||||
// Missile 1 pixel test
|
||||
wire mis1PixelOn, mis1PixelOut;
|
||||
wire [7:0] mis1ActualPos;
|
||||
reg [7:0] mis1Mask;
|
||||
always @(player1Size)
|
||||
begin
|
||||
case(player1Size[4:3])
|
||||
2'd0: mis1Mask <= 8'h01;
|
||||
2'd1: mis1Mask <= 8'h03;
|
||||
2'd2: mis1Mask <= 8'h0F;
|
||||
2'd3: mis1Mask <= 8'hFF;
|
||||
endcase
|
||||
end
|
||||
assign mis1ActualPos = (missile1Lock)? player1Pos : missile1Pos;
|
||||
objPixelOn missile1_test(pixelNum, mis1ActualPos, player1Size[2:0], mis1Mask, mis1PixelOut);
|
||||
assign mis1PixelOn = mis1PixelOut && missile1Enable;
|
||||
// Ball pixel test
|
||||
wire ballPixelOut, ballPixelOn, ballEnableDel;
|
||||
reg [7:0] ballMask;
|
||||
always @(ballSize)
|
||||
begin
|
||||
case(ballSize)
|
||||
2'd0: ballMask <= 8'h01;
|
||||
2'd1: ballMask <= 8'h03;
|
||||
2'd2: ballMask <= 8'h0F;
|
||||
2'd3: ballMask <= 8'hFF;
|
||||
endcase
|
||||
end
|
||||
objPixelOn ball_test(pixelNum, ballPos, 3'd0, ballMask, ballPixelOut);
|
||||
assign ballEnableDel = ((ballVertDelay)? R_ballEnable : ballEnable);
|
||||
assign ballPixelOn = ballPixelOut && ballEnableDel;
|
||||
// Playfield color selection
|
||||
// The programmer can select a unique color for the playfield or have it match
|
||||
// the player's sprites colors
|
||||
reg [7:0] pfActualColor;
|
||||
always @(pfColorCtrl, pfColor, player0Color, player1Color, pfPixelNum)
|
||||
begin
|
||||
if (pfColorCtrl)
|
||||
begin
|
||||
if (pfPixelNum < 6'd20)
|
||||
pfActualColor <= player0Color;
|
||||
else
|
||||
pfActualColor <= player1Color;
|
||||
end
|
||||
else
|
||||
pfActualColor <= pfColor;
|
||||
end
|
||||
// Final pixel color selection
|
||||
reg [7:0] pixelColor;
|
||||
assign COLOROUT = (HBLANK)? 8'b0 : pixelColor;
|
||||
// This combinational logic uses a priority encoder like structure to select
|
||||
// the highest priority screen object and color the pixel.
|
||||
always @(prioCtrl, pfPixelOn, pl0PixelOn, pl1PixelOn, mis0PixelOn, mis1PixelOn,
|
||||
ballPixelOn, pfActualColor, player0Color, player1Color, bgColor)
|
||||
begin
|
||||
// Show the playfield behind the players
|
||||
if (!prioCtrl)
|
||||
begin
|
||||
if (pl0PixelOn || mis0PixelOn)
|
||||
pixelColor <= player0Color;
|
||||
else if (pl1PixelOn || mis1PixelOn)
|
||||
pixelColor <= player1Color;
|
||||
else if (pfPixelOn)
|
||||
pixelColor <= pfActualColor;
|
||||
else
|
||||
pixelColor <= bgColor;
|
||||
end
|
||||
// Otherwise, show the playfield in front of the players
|
||||
else begin
|
||||
if (pfPixelOn)
|
||||
pixelColor <= pfActualColor;
|
||||
else if (pl0PixelOn || mis0PixelOn)
|
||||
pixelColor <= player0Color;
|
||||
else if (pl1PixelOn || mis1PixelOn)
|
||||
pixelColor <= player1Color;
|
||||
else
|
||||
pixelColor <= bgColor;
|
||||
end
|
||||
end
|
||||
// Collision register and latching update
|
||||
wire [14:0] collisions;
|
||||
reg collisionLatchReset;
|
||||
assign collisions = {pl0PixelOn && pl1PixelOn, mis0PixelOn && mis1PixelOn,
|
||||
ballPixelOn && pfPixelOn,
|
||||
mis1PixelOn && pfPixelOn, mis1PixelOn && ballPixelOn,
|
||||
mis0PixelOn && pfPixelOn, mis0PixelOn && ballPixelOn,
|
||||
pl1PixelOn && pfPixelOn, pl1PixelOn && ballPixelOn,
|
||||
pl0PixelOn && pfPixelOn, pl0PixelOn && ballPixelOn,
|
||||
mis1PixelOn && pl0PixelOn, mis1PixelOn && pl1PixelOn,
|
||||
mis0PixelOn && pl1PixelOn, mis0PixelOn && pl0PixelOn};
|
||||
always @(posedge MASTERCLK, posedge collisionLatchReset)
|
||||
begin
|
||||
if (collisionLatchReset)
|
||||
collisionLatch <= 15'b000000000000000;
|
||||
else
|
||||
collisionLatch <= collisionLatch | collisions;
|
||||
end
|
||||
// WSYNC logic
|
||||
// When a WSYNC is signalled by the programmer, the CPU ready line is lowered
|
||||
// until the end of a scanline
|
||||
reg wSync, wSyncReset;
|
||||
always @(hCount, wSyncReset)
|
||||
begin
|
||||
if (hCount == 8'd0)
|
||||
wSync <= 1'b0;
|
||||
else if (wSyncReset && hCount > 8'd2)
|
||||
wSync <= 1'b1;
|
||||
end
|
||||
assign RDY = ~wSync;
|
||||
// Latched input registers and update
|
||||
wire [1:0] latchedInputsValue;
|
||||
reg inputLatchEnabled;
|
||||
reg inputLatchReset;
|
||||
reg [1:0] latchedInputs;
|
||||
|
||||
/*always_ff @(Ilatch, inputLatchReset)
|
||||
begin
|
||||
if (inputLatchReset)
|
||||
latchedInputs <= 2'b11;
|
||||
else
|
||||
latchedInputs <= latchedInputs & Ilatch;
|
||||
end*/
|
||||
|
||||
assign latchedInputsValue = (inputLatchEnabled)? latchedInputs : Ilatch;
|
||||
// Dumped input registers update
|
||||
reg inputDumpEnabled;
|
||||
assign Idump = (inputDumpEnabled)? 4'b0000 : idump_in;
|
||||
// Software operations
|
||||
always @(posedge CLK2)
|
||||
begin
|
||||
// Reset operation
|
||||
if (~RES_n) begin
|
||||
inputLatchReset <= 1'b0;
|
||||
collisionLatchReset <= 1'b0;
|
||||
hCountReset[0] <= 1'b0;
|
||||
wSyncReset <= 1'b0;
|
||||
Dout <= 8'b00000000;
|
||||
end
|
||||
// If the chip is enabled, execute an operation
|
||||
else if (CS) begin
|
||||
// Software reset signals
|
||||
inputLatchReset <= ({R_W_n, A[5:0]} == `VBLANK && Din[6] && !inputLatchEnabled);
|
||||
collisionLatchReset <= ({R_W_n, A[5:0]} == `CXCLR);
|
||||
hCountReset[0] <= ({R_W_n, A[5:0]} == `RSYNC);
|
||||
wSyncReset <= ({R_W_n, A[5:0]} == `WSYNC) && !wSync;
|
||||
case({R_W_n, A[5:0]})
|
||||
// Collision latch reads
|
||||
`CXM0P, `CXM0P_7800: Dout <= {collisionLatch[1:0],6'b000000};
|
||||
`CXM1P, `CXM1P_7800: Dout <= {collisionLatch[3:2],6'b000000};
|
||||
`CXP0FB, `CXP0FB_7800: Dout <= {collisionLatch[5:4],6'b000000};
|
||||
`CXP1FB, `CXP1FB_7800: Dout <= {collisionLatch[7:6],6'b000000};
|
||||
`CXM0FB, `CXM0FB_7800: Dout <= {collisionLatch[9:8],6'b000000};
|
||||
`CXM1FB, `CXM1FB_7800: Dout <= {collisionLatch[11:10],6'b000000};
|
||||
`CXBLPF, `CXBLPF_7800: Dout <= {collisionLatch[12],7'b0000000};
|
||||
`CXPPMM, `CXPPMM_7800: Dout <= {collisionLatch[14:13],6'b000000};
|
||||
// I/O reads
|
||||
`INPT0, `INPT0_7800: Dout <= {Idump[0], 7'b0000000};
|
||||
`INPT1, `INPT1_7800: Dout <= {Idump[1], 7'b0000000};
|
||||
`INPT2, `INPT2_7800: Dout <= {Idump[2], 7'b0000000};
|
||||
`INPT3, `INPT3_7800: Dout <= {Idump[3], 7'b0000000};
|
||||
`INPT4, `INPT4_7800: Dout <= {latchedInputsValue[0], 7'b0000000};
|
||||
`INPT5, `INPT5_7800: Dout <= {latchedInputsValue[1], 7'b0000000};
|
||||
// Video signals
|
||||
`VSYNC: VSYNC <= Din[1];
|
||||
`VBLANK: begin
|
||||
inputLatchEnabled <= Din[6];
|
||||
inputDumpEnabled <= Din[7];
|
||||
VBLANK <= Din[1];
|
||||
end
|
||||
`WSYNC:;
|
||||
`RSYNC:;
|
||||
// Screen object register access
|
||||
`NUSIZ0: player0Size <= {Din[5:4],Din[2:0]};
|
||||
`NUSIZ1: player1Size <= {Din[5:4],Din[2:0]};
|
||||
`COLUP0: player0Color <= Din;
|
||||
`COLUP1: player1Color <= Din;
|
||||
`COLUPF: pfColor <= Din;
|
||||
`COLUBK: bgColor <= Din;
|
||||
`CTRLPF: begin
|
||||
pfReflect <= Din[0];
|
||||
pfColorCtrl <= Din[1];
|
||||
prioCtrl <= Din[2];
|
||||
ballSize <= Din[5:4];
|
||||
end
|
||||
`REFP0: player0Reflect <= Din[3];
|
||||
`REFP1: player1Reflect <= Din[3];
|
||||
`PF0: pfGraphic[3:0] <= Din[7:4];
|
||||
`PF1: pfGraphic[11:4] <= {Din[0], Din[1], Din[2], Din[3],
|
||||
Din[4], Din[5], Din[6], Din[7]};
|
||||
`PF2: pfGraphic[19:12] <= Din[7:0];
|
||||
`RESP0: player0Pos <= pixelNum;
|
||||
`RESP1: player1Pos <= pixelNum;
|
||||
`RESM0: missile0Pos <= pixelNum;
|
||||
`RESM1: missile1Pos <= pixelNum;
|
||||
`RESBL: ballPos <= pixelNum;
|
||||
// Audio controls
|
||||
`AUDC0: audc0 <= Din[3:0];
|
||||
`AUDC1: audc1 <= Din[3:0];
|
||||
`AUDF0: audf0 <= Din[4:0];
|
||||
`AUDF1: audf1 <= Din[4:0];
|
||||
`AUDV0: audv0 <= Din[3:0];
|
||||
`AUDV1: audv1 <= Din[3:0];
|
||||
// Screen object register access
|
||||
`GRP0: begin
|
||||
player0Graphic <= {Din[0], Din[1], Din[2], Din[3],
|
||||
Din[4], Din[5], Din[6], Din[7]};
|
||||
R_player1Graphic <= player1Graphic;
|
||||
end
|
||||
`GRP1: begin
|
||||
player1Graphic <= {Din[0], Din[1], Din[2], Din[3],
|
||||
Din[4], Din[5], Din[6], Din[7]};
|
||||
R_player0Graphic <= player0Graphic;
|
||||
R_ballEnable <= ballEnable;
|
||||
end
|
||||
`ENAM0: missile0Enable <= Din[1];
|
||||
`ENAM1: missile1Enable <= Din[1];
|
||||
`ENABL: ballEnable <= Din[1];
|
||||
`HMP0: player0Motion <= Din[7:4];
|
||||
`HMP1: player1Motion <= Din[7:4];
|
||||
`HMM0: missile0Motion <= Din[7:4];
|
||||
`HMM1: missile1Motion <= Din[7:4];
|
||||
`HMBL: ballMotion <= Din[7:4];
|
||||
`VDELP0: player0VertDelay <= Din[0];
|
||||
`VDELP1: player1VertDelay <= Din[0];
|
||||
`VDELBL: ballVertDelay <= Din[0];
|
||||
`RESMP0: missile0Lock <= Din[1];
|
||||
`RESMP1: missile1Lock <= Din[1];
|
||||
// Strobed line that initiates an object move
|
||||
`HMOVE: begin
|
||||
player0Pos <= player0Pos - {{4{player0Motion[3]}},
|
||||
player0Motion[3:0]};
|
||||
player1Pos <= player1Pos - {{4{player1Motion[3]}},
|
||||
player1Motion[3:0]};
|
||||
missile0Pos <= missile0Pos - {{4{missile0Motion[3]}},
|
||||
missile0Motion[3:0]};
|
||||
missile1Pos <= missile1Pos - {{4{missile1Motion[3]}},
|
||||
missile1Motion[3:0]};
|
||||
ballPos <= ballPos - {{4{ballMotion[3]}},ballMotion[3:0]};
|
||||
end
|
||||
// Motion register clear
|
||||
`HMCLR: begin
|
||||
player0Motion <= Din[7:4];
|
||||
player1Motion <= Din[7:4];
|
||||
missile0Motion <= Din[7:4];
|
||||
missile1Motion <= Din[7:4];
|
||||
ballMotion <= Din[7:4];
|
||||
end
|
||||
`CXCLR:;
|
||||
default: Dout <= 8'b00000000;
|
||||
endcase
|
||||
end
|
||||
// If the chip is not enabled, do nothing
|
||||
else begin
|
||||
inputLatchReset <= 1'b0;
|
||||
collisionLatchReset <= 1'b0;
|
||||
hCountReset[0] <= 1'b0;
|
||||
wSyncReset <= 1'b0;
|
||||
Dout <= 8'b00000000;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
// objPixelOn module
|
||||
// Checks the pixel number against a stretched and possibly duplicated version of the
|
||||
// object.
|
||||
module objPixelOn(pixelNum, objPos, objSize, objMask, pixelOn);
|
||||
input [7:0] pixelNum, objPos, objMask;
|
||||
input [2:0] objSize;
|
||||
output pixelOn;
|
||||
wire [7:0] objIndex;
|
||||
wire [8:0] objByteIndex;
|
||||
wire objMaskOn, objPosOn;
|
||||
reg objSizeOn;
|
||||
reg [2:0] objMaskSel;
|
||||
assign objIndex = pixelNum - objPos - 8'd1;
|
||||
assign objByteIndex = 9'b1 << (objIndex[7:3]);
|
||||
always @(objSize, objByteIndex)
|
||||
begin
|
||||
case (objSize)
|
||||
3'd0: objSizeOn <= (objByteIndex & 9'b00000001) != 0;
|
||||
3'd1: objSizeOn <= (objByteIndex & 9'b00000101) != 0;
|
||||
3'd2: objSizeOn <= (objByteIndex & 9'b00010001) != 0;
|
||||
3'd3: objSizeOn <= (objByteIndex & 9'b00010101) != 0;
|
||||
3'd4: objSizeOn <= (objByteIndex & 9'b10000001) != 0;
|
||||
3'd5: objSizeOn <= (objByteIndex & 9'b00000011) != 0;
|
||||
3'd6: objSizeOn <= (objByteIndex & 9'b10010001) != 0;
|
||||
3'd7: objSizeOn <= (objByteIndex & 9'b00001111) != 0;
|
||||
endcase
|
||||
end
|
||||
always @(objSize, objIndex)
|
||||
begin
|
||||
case (objSize)
|
||||
3'd5: objMaskSel <= objIndex[3:1];
|
||||
3'd7: objMaskSel <= objIndex[4:2];
|
||||
default: objMaskSel <= objIndex[2:0];
|
||||
endcase
|
||||
end
|
||||
assign objMaskOn = objMask[objMaskSel];
|
||||
assign objPosOn = (pixelNum > objPos) && ({1'b0, pixelNum} <= {1'b0, objPos} + 9'd72);
|
||||
assign pixelOn = objSizeOn && objMaskOn && objPosOn;
|
||||
endmodule
|
||||
80
common/TTL/ls367.vhd
Normal file
80
common/TTL/ls367.vhd
Normal file
@@ -0,0 +1,80 @@
|
||||
--
|
||||
-- ls367.vhd
|
||||
--
|
||||
-- LS367 and the others circuit module
|
||||
-- for MZ-700 on FPGA
|
||||
--
|
||||
-- TEMPO generator
|
||||
-- TONE gate
|
||||
--
|
||||
-- Nibbles Lab. 2005
|
||||
--
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
use IEEE.STD_LOGIC_ARITH.ALL;
|
||||
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
||||
|
||||
-- Uncomment the following lines to use the declarations that are
|
||||
-- provided for instantiating Xilinx primitive components.
|
||||
--library UNISIM;
|
||||
--use UNISIM.VComponents.all;
|
||||
|
||||
entity ls367 is
|
||||
Port ( RST : in std_logic;
|
||||
CLKIN : in std_logic;
|
||||
CLKOUT : out std_logic;
|
||||
GATE : out std_logic;
|
||||
CS : in std_logic;
|
||||
WR : in std_logic;
|
||||
DI : in std_logic_vector(7 downto 0);
|
||||
DO : out std_logic_vector(7 downto 0));
|
||||
end ls367;
|
||||
|
||||
architecture Behavioral of ls367 is
|
||||
|
||||
--
|
||||
-- TEMPO counter
|
||||
--
|
||||
signal TCOUNT : std_logic_vector(15 downto 0);
|
||||
signal TEMPO : std_logic;
|
||||
--
|
||||
-- GATE control
|
||||
--
|
||||
signal GT : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
--
|
||||
-- TEMPO
|
||||
--
|
||||
process( CLKIN ) begin
|
||||
if( CLKIN'event and CLKIN='1' ) then
|
||||
TCOUNT<=TCOUNT+'1';
|
||||
if( TCOUNT=46976 ) then
|
||||
TCOUNT<=(others=>'0');
|
||||
TEMPO<=not TEMPO;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
DO(0)<=TEMPO;
|
||||
DO(7 downto 1)<=(others=>'1');
|
||||
CLKOUT<=TEMPO;
|
||||
|
||||
--
|
||||
-- TONE gate control
|
||||
--
|
||||
process( WR, RST ) begin
|
||||
if( RST='0' ) then
|
||||
GT<='0';
|
||||
elsif( WR'event and WR='1' ) then
|
||||
if( CS='0' ) then
|
||||
GT<=DI(0);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
GATE<=GT;
|
||||
|
||||
end Behavioral;
|
||||
26
common/riot.vh
Normal file
26
common/riot.vh
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Atari on an FPGA
|
||||
Masters of Engineering Project
|
||||
Cornell University, 2007
|
||||
Daniel Beer
|
||||
RIOT.h
|
||||
Header file that contains useful definitions for the RIOT module.
|
||||
*/
|
||||
`define READ_RAM 7'b01xxxxx
|
||||
`define WRITE_RAM 7'b00xxxxx
|
||||
`define READ_DRA 7'b11xx000
|
||||
`define WRITE_DRA 7'b10xx000
|
||||
`define READ_DDRA 7'b11xx001
|
||||
`define WRITE_DDRA 7'b10xx001
|
||||
`define READ_DRB 7'b11xx010
|
||||
`define WRITE_DRB 7'b10xx010
|
||||
`define READ_DDRB 7'b11xx011
|
||||
`define WRITE_DDRB 7'b10xx011
|
||||
`define WRITE_TIMER 7'b101x1xx
|
||||
`define READ_TIMER 7'b11xx1x0
|
||||
`define READ_INT_FLAG 7'b11xx1x1
|
||||
`define WRITE_EDGE_DETECT 7'b100x1x0
|
||||
`define NOP 7'b0100000
|
||||
`define TM_1 2'b00
|
||||
`define TM_8 2'b01
|
||||
`define TM_64 2'b10
|
||||
`define TM_1024 2'b11
|
||||
81
common/tia.vh
Normal file
81
common/tia.vh
Normal file
@@ -0,0 +1,81 @@
|
||||
/* Atari on an FPGA
|
||||
Masters of Engineering Project
|
||||
Cornell University, 2007
|
||||
Daniel Beer
|
||||
TIA.h
|
||||
Header file that contains useful definitions for the TIA module.
|
||||
*/
|
||||
`define CXM0P 7'h70
|
||||
`define CXM1P 7'h71
|
||||
`define CXP0FB 7'h72
|
||||
`define CXP1FB 7'h73
|
||||
`define CXM0FB 7'h74
|
||||
`define CXM1FB 7'h75
|
||||
`define CXBLPF 7'h76
|
||||
`define CXPPMM 7'h77
|
||||
`define INPT0 7'h78
|
||||
`define INPT1 7'h79
|
||||
`define INPT2 7'h7A
|
||||
`define INPT3 7'h7B
|
||||
`define INPT4 7'h7C
|
||||
`define INPT5 7'h7D
|
||||
`define VSYNC 7'h00
|
||||
`define VBLANK 7'h01
|
||||
`define WSYNC 7'h02
|
||||
`define RSYNC 7'h03
|
||||
`define NUSIZ0 7'h04
|
||||
`define NUSIZ1 7'h05
|
||||
`define COLUP0 7'h06
|
||||
`define COLUP1 7'h07
|
||||
`define COLUPF 7'h08
|
||||
`define COLUBK 7'h09
|
||||
`define CTRLPF 7'h0A
|
||||
`define REFP0 7'h0B
|
||||
`define REFP1 7'h0C
|
||||
`define PF0 7'h0D
|
||||
`define PF1 7'h0E
|
||||
`define PF2 7'h0F
|
||||
`define RESP0 7'h10
|
||||
`define RESP1 7'h11
|
||||
`define RESM0 7'h12
|
||||
`define RESM1 7'h13
|
||||
`define RESBL 7'h14
|
||||
`define AUDC0 7'h15
|
||||
`define AUDC1 7'h16
|
||||
`define AUDF0 7'h17
|
||||
`define AUDF1 7'h18
|
||||
`define AUDV0 7'h19
|
||||
`define AUDV1 7'h1A
|
||||
`define GRP0 7'h1B
|
||||
`define GRP1 7'h1C
|
||||
`define ENAM0 7'h1D
|
||||
`define ENAM1 7'h1E
|
||||
`define ENABL 7'h1F
|
||||
`define HMP0 7'h20
|
||||
`define HMP1 7'h21
|
||||
`define HMM0 7'h22
|
||||
`define HMM1 7'h23
|
||||
`define HMBL 7'h24
|
||||
`define VDELP0 7'h25
|
||||
`define VDELP1 7'h26
|
||||
`define VDELBL 7'h27
|
||||
`define RESMP0 7'h28
|
||||
`define RESMP1 7'h29
|
||||
`define HMOVE 7'h2A
|
||||
`define HMCLR 7'h2B
|
||||
`define CXCLR 7'h2C
|
||||
|
||||
`define CXM0P_7800 7'h40
|
||||
`define CXM1P_7800 7'h41
|
||||
`define CXP0FB_7800 7'h42
|
||||
`define CXP1FB_7800 7'h43
|
||||
`define CXM0FB_7800 7'h44
|
||||
`define CXM1FB_7800 7'h45
|
||||
`define CXBLPF_7800 7'h46
|
||||
`define CXPPMM_7800 7'h47
|
||||
`define INPT0_7800 7'h48
|
||||
`define INPT1_7800 7'h49
|
||||
`define INPT2_7800 7'h4A
|
||||
`define INPT3_7800 7'h4B
|
||||
`define INPT4_7800 7'h4C
|
||||
`define INPT5_7800 7'h4D
|
||||
Reference in New Issue
Block a user