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

Reupload Electron

This commit is contained in:
Gehstock
2018-10-05 22:38:42 +02:00
parent e2e9260aac
commit 3f2dc35722
31 changed files with 8972 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2013 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus II 64-Bit
# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition
# Date created = 07:11:53 March 09, 2017
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "13.1"
DATE = "07:11:53 March 09, 2017"
# Revisions
PROJECT_REVISION = "AtomElectron_Mist"

View File

@@ -0,0 +1,126 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2013 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus II 64-Bit
# Version 13.1.0 Build 162 10/23/2013 SJ Web Edition
# Date created = 07:11:53 March 09, 2017
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# AtomElectron_Mist_assignment_defaults.qdf
# If this file doesn't exist, see file:
# assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
# file is updated automatically by the Quartus II software
# and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #
set_location_assignment PIN_54 -to CLOCK_27
set_location_assignment PIN_7 -to LED
set_location_assignment PIN_144 -to VGA_R[5]
set_location_assignment PIN_143 -to VGA_R[4]
set_location_assignment PIN_142 -to VGA_R[3]
set_location_assignment PIN_141 -to VGA_R[2]
set_location_assignment PIN_137 -to VGA_R[1]
set_location_assignment PIN_135 -to VGA_R[0]
set_location_assignment PIN_133 -to VGA_B[5]
set_location_assignment PIN_132 -to VGA_B[4]
set_location_assignment PIN_125 -to VGA_B[3]
set_location_assignment PIN_121 -to VGA_B[2]
set_location_assignment PIN_120 -to VGA_B[1]
set_location_assignment PIN_115 -to VGA_B[0]
set_location_assignment PIN_114 -to VGA_G[5]
set_location_assignment PIN_113 -to VGA_G[4]
set_location_assignment PIN_112 -to VGA_G[3]
set_location_assignment PIN_111 -to VGA_G[2]
set_location_assignment PIN_110 -to VGA_G[1]
set_location_assignment PIN_106 -to VGA_G[0]
set_location_assignment PIN_136 -to VGA_VS
set_location_assignment PIN_119 -to VGA_HS
set_location_assignment PIN_65 -to AUDIO_L
set_location_assignment PIN_80 -to AUDIO_R
set_location_assignment PIN_105 -to SPI_DO
set_location_assignment PIN_88 -to SPI_DI
set_location_assignment PIN_126 -to SPI_SCK
set_location_assignment PIN_127 -to SPI_SS2
set_location_assignment PIN_91 -to SPI_SS3
set_location_assignment PIN_90 -to SPI_SS4
set_location_assignment PIN_13 -to CONF_DATA0
set_global_assignment -name FAMILY "Cyclone III"
set_global_assignment -name DEVICE EP3C25E144C8
set_global_assignment -name TOP_LEVEL_ENTITY AtomElectron_Mist
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1
set_global_assignment -name PROJECT_CREATION_TIME_DATE "07:11:53 MARCH 09, 2017"
set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1"
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)"
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
set_global_assignment -name SEARCH_PATH roms/ -tag from_archive
set_global_assignment -name SEARCH_PATH src/ -tag from_archive
set_global_assignment -name SEARCH_PATH src/MC6522/ -tag from_archive
set_global_assignment -name SEARCH_PATH src/RAM/ -tag from_archive
set_global_assignment -name SEARCH_PATH src/T6502/ -tag from_archive
set_global_assignment -name SEARCH_PATH src/ps2kybrd/ -tag from_archive
set_global_assignment -name VHDL_FILE rtl/ElectronULA.vhd
set_global_assignment -name VHDL_FILE rtl/RomSmelk3006.vhd
set_global_assignment -name VHDL_FILE rtl/RomOS100.vhd
set_global_assignment -name VHDL_FILE rtl/RomBasic2.vhd
set_global_assignment -name VHDL_FILE rtl/RAM_32K_DualPort.vhd
set_global_assignment -name VHDL_FILE rtl/ps2_intf.vhd
set_global_assignment -name VHDL_FILE rtl/m6522.vhd
set_global_assignment -name VHDL_FILE rtl/keyboard.vhd
set_global_assignment -name VHDL_FILE rtl/T65/T65_Pack.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
set_global_assignment -name SYSTEMVERILOG_FILE rtl/AtomElectron_Mist.sv
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_global_assignment -name VHDL_FILE rtl/ElectronFpga_core.vhd
set_global_assignment -name VHDL_FILE rtl/pll.vhd
set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv
set_global_assignment -name VERILOG_FILE rtl/scandoubler.v
set_global_assignment -name VERILOG_FILE rtl/osd.v
set_global_assignment -name VERILOG_FILE rtl/mist_io.v
set_global_assignment -name SYSTEMVERILOG_FILE rtl/hq2x.sv
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

Binary file not shown.

View File

@@ -0,0 +1,38 @@
@echo off
del /s *.bak
del /s *.orig
del /s *.rej
del /s *~
rmdir /s /q db
rmdir /s /q incremental_db
rmdir /s /q output_files
rmdir /s /q simulation
rmdir /s /q greybox_tmp
rmdir /s /q hc_output
rmdir /s /q .qsys_edit
rmdir /s /q hps_isw_handoff
rmdir /s /q sys\.qsys_edit
rmdir /s /q sys\vip
cd sys
for /d %%i in (*_sim) do rmdir /s /q "%%~nxi"
cd ..
for /d %%i in (*_sim) do rmdir /s /q "%%~nxi"
del build_id.v
del c5_pin_model_dump.txt
del PLLJ_PLLSPE_INFO.txt
del /s *.qws
del /s *.ppf
del /s *.ddb
del /s *.csv
del /s *.cmp
del /s *.sip
del /s *.spd
del /s *.bsf
del /s *.f
del /s *.sopcinfo
del /s *.xml
del *.cdf
del *.rpt
del /s new_rtl_netlist
del /s old_rtl_netlist
pause

View File

@@ -0,0 +1,134 @@
module AtomElectron_Mist
(
output LED,
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B,
output VGA_HS,
output VGA_VS,
output AUDIO_L,
output AUDIO_R,
input SPI_SCK,
output SPI_DO,
input SPI_DI,
input SPI_SS2,
input SPI_SS3,
input SPI_SS4,
input CONF_DATA0,
input CLOCK_27
);
`include "rtl\build_id.v"
localparam CONF_STR = {
"Electron;;",
"T6,Reset;",
"V,v1.00.",`BUILD_DATE
};
wire clk_16M00, clk_33M33, clk_40M00, clk_4M00;
wire ps2_clk, ps2_data;
wire [31:0] status;
wire [1:0] buttons;
wire [1:0] switches;
wire [7:0] kbjoy;
wire [7:0] joystick_0;
wire [7:0] joystick_1;
wire scandoubler_disable;
wire ypbpr;
wire hs, vs;
wire [2:0] r,g,b;
wire pwrup_RSTn;
wire reset = ~(status[0] || status[6] || buttons[1]);
wire ERSTn;
reg [7:0]reset_ctr = 8'b0;
pll pll(
.inclk0(CLOCK_27),
.c0(clk_40M00),
.c1(clk_16M00),
.c2(clk_33M33),
.c3(clk_4M00)//8,3325
);
ElectronFpga_core ElectronFpga_core(
.clk_16M00(clk_16M00),
.clk_33M33(clk_33M33),
.clk_40M00(clk_40M00),
.ps2_clk(ps2_clk),
.ps2_data(ps2_data),
.ERSTn(ERSTn),
.RESET(reset),
.red(r),
.green(g),
.blue(b),
.vsync(vs),
.hsync(hs),
.audiol(AUDIO_L),
.audioR(AUDIO_R),
.casIn(),
.casOut(),
.LED1(LED),
.SDMISO(),
.SDSS(),
.SDCLK(),
.SDMOSI()
);
assign ERSTn = pwrup_RSTn;
always @ (posedge clk_16M00)
begin
if (pwrup_RSTn == 1'b0) reset_ctr <= reset_ctr + 1;
end
assign pwrup_RSTn = reset_ctr[7];
video_mixer #(.LINE_LENGTH(480), .HALF_DEPTH(0)) video_mixer
(
.clk_sys(clk_33M33),
.ce_pix(clk_4M00),
.ce_pix_actual(clk_4M00),
.SPI_SCK(SPI_SCK),
.SPI_SS3(SPI_SS3),
.SPI_DI(SPI_DI),
.R({r,r}),
.G({g,g}),
.B({b,b}),
.HSync(hs),
.VSync(vs),
.VGA_R(VGA_R),
.VGA_G(VGA_G),
.VGA_B(VGA_B),
.VGA_VS(VGA_VS),
.VGA_HS(VGA_HS),
.scandoubler_disable(1'b1),//scandoubler_disable),
.ypbpr_full(1),
.line_start(0),
.mono(0)
);
mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io
(
.clk_sys (clk_33M33 ),
.conf_str (CONF_STR ),
.SPI_SCK (SPI_SCK ),
.CONF_DATA0 (CONF_DATA0 ),
.SPI_SS2 (SPI_SS2 ),
.SPI_DO (SPI_DO ),
.SPI_DI (SPI_DI ),
.buttons (buttons ),
.switches (switches ),
.scandoubler_disable(scandoubler_disable),
.ypbpr (ypbpr ),
.ps2_kbd_clk (ps2_clk),
.ps2_kbd_data (ps2_data),
.joystick_0 (joystick_0 ),
.joystick_1 (joystick_1 ),
.status (status )
);
endmodule

View File

@@ -0,0 +1,113 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2015 David Banks
--------------------------------------------------------------------------------
-- ____ ____
-- / /\/ /
-- /___/ \ /
-- \ \ \/
-- \ \
-- / / Filename : ElectronFpga.vhf
-- /___/ /\ Timestamp : 28/07/2015
-- \ \ / \
-- \___\/\___\
--
--Design Name: ElectronFpga
--Device: Spartan6 LX9
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity ElectronFpga_MiST is
port (
CLOCK_27 : in std_logic;
VGA_R : out std_logic_vector (2 downto 0);
VGA_G : out std_logic_vector (2 downto 0);
VGA_B : out std_logic_vector (2 downto 0);
VGA_VS : out std_logic;
VGA_HS : out std_logic;
AUDIO_L : out std_logic;
AUDIO_R : out std_logic;
casIn : in std_logic;
casOut : out std_logic;
LED : out std_logic;
SDMISO : in std_logic;
SDSS : out std_logic;
SDCLK : out std_logic;
SDMOSI : out std_logic
);
end;
architecture behavioral of ElectronFpga_MiST is
signal clk_16M00 : std_logic;
signal clk_33M33 : std_logic;
signal clk_40M00 : std_logic;
signal ERSTn : std_logic;
signal ps2_clk : std_logic;
signal ps2_data : std_logic;
signal pwrup_RSTn : std_logic;
signal reset_ctr : std_logic_vector (7 downto 0) := (others => '0');
component pll27
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC
);
end component;
begin
pll27_inst : pll27 PORT MAP (
inclk0 => CLOCK_27,
c0 => clk_40M00,
c1 => clk_16M00,
c2 => clk_33M33
);
inst_ElectronFpga_core : entity work.ElectronFpga_core
port map (
clk_16M00 => clk_16M00,
clk_33M33 => clk_33M33,
clk_40M00 => clk_40M00,
ps2_clk => ps2_clk,
ps2_data => ps2_data,
ERSTn => ERSTn,
red => VGA_R,
green => VGA_G,
blue => VGA_B,
vsync => VGA_VS,
hsync => VGA_HS,
audiol => AUDIO_L,
audioR => AUDIO_R,
casIn => casIn,
casOut => casOut,
LED1 => LED,
SDMISO => SDMISO,
SDSS => SDSS,
SDCLK => SDCLK,
SDMOSI => SDMOSI
);
ERSTn <= pwrup_RSTn;
-- This internal counter forces power up reset to happen
-- This is needed by the GODIL to initialize some of the registers
ResetProcess : process (clk_16M00)
begin
if rising_edge(clk_16M00) then
if (pwrup_RSTn = '0') then
reset_ctr <= reset_ctr + 1;
end if;
end if;
end process;
pwrup_RSTn <= reset_ctr(7);
end behavioral;

View File

@@ -0,0 +1,106 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2015 David Banks
--------------------------------------------------------------------------------
-- ____ ____
-- / /\/ /
-- /___/ \ /
-- \ \ \/
-- \ \
-- / / Filename : ElectronFpga.vhf
-- /___/ /\ Timestamp : 28/07/2015
-- \ \ / \
-- \___\/\___\
--
--Design Name: ElectronFpga
--Device: Spartan6 LX9
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity ElectronFpga_MiST is
port (
CLOCK_27 : in std_logic;
VGA_R : out std_logic_vector (2 downto 0);
VGA_G : out std_logic_vector (2 downto 0);
VGA_B : out std_logic_vector (2 downto 0);
VGA_VS : out std_logic;
VGA_HS : out std_logic;
AUDIO_L : out std_logic;
AUDIO_R : out std_logic;
casIn : in std_logic;
casOut : out std_logic;
LED : out std_logic;
SDMISO : in std_logic;
SDSS : out std_logic;
SDCLK : out std_logic;
SDMOSI : out std_logic
);
end;
architecture behavioral of ElectronFpga_MiST is
signal clk_16M00 : std_logic;
signal clk_33M33 : std_logic;
signal clk_40M00 : std_logic;
signal ERSTn : std_logic;
signal ps2_clk : std_logic;
signal ps2_data : std_logic;
signal pwrup_RSTn : std_logic;
signal reset_ctr : std_logic_vector (7 downto 0) := (others => '0');
begin
pll_inst : entity work.pll
PORT MAP (
inclk0 => CLOCK_27,
c0 => clk_40M00,
c1 => clk_16M00,
c2 => clk_33M33
);
inst_ElectronFpga_core : entity work.ElectronFpga_core
port map (
clk_16M00 => clk_16M00,
clk_33M33 => clk_33M33,
clk_40M00 => clk_40M00,
ps2_clk => ps2_clk,
ps2_data => ps2_data,
ERSTn => ERSTn,
red => VGA_R,
green => VGA_G,
blue => VGA_B,
vsync => VGA_VS,
hsync => VGA_HS,
audiol => AUDIO_L,
audioR => AUDIO_R,
casIn => casIn,
casOut => casOut,
LED1 => LED,
SDMISO => SDMISO,
SDSS => SDSS,
SDCLK => SDCLK,
SDMOSI => SDMOSI
);
ERSTn <= pwrup_RSTn;
-- This internal counter forces power up reset to happen
-- This is needed by the GODIL to initialize some of the registers
ResetProcess : process (clk_16M00)
begin
if rising_edge(clk_16M00) then
if (pwrup_RSTn = '0') then
reset_ctr <= reset_ctr + 1;
end if;
end if;
end process;
pwrup_RSTn <= reset_ctr(7);
end behavioral;

View File

@@ -0,0 +1,400 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2015 David Banks
--------------------------------------------------------------------------------
-- ____ ____
-- / /\/ /
-- /___/ \ /
-- \ \ \/
-- \ \
-- / / Filename : ElectronFpga_core.vhd
-- /___/ /\ Timestamp : 28/07/2015
-- \ \ / \
-- \___\/\___\
--
--Design Name: ElectronFpga_core
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity ElectronFpga_core is
port (
clk_16M00 : in std_logic;
clk_33M33 : in std_logic;
clk_40M00 : in std_logic;
ps2_clk : in std_logic;
ps2_data : in std_logic;
ERSTn : in std_logic;
RESET : in std_logic;
red : out std_logic_vector (2 downto 0);
green : out std_logic_vector (2 downto 0);
blue : out std_logic_vector (2 downto 0);
vsync : out std_logic;
hsync : out std_logic;
audiol : out std_logic;
audioR : out std_logic;
casIn : in std_logic;
casOut : out std_logic;
LED1 : out std_logic;
-- LED2 : out std_logic;
SDMISO : in std_logic;
SDSS : out std_logic;
SDCLK : out std_logic;
SDMOSI : out std_logic
-- DIP : in std_logic_vector(1 downto 0);
-- test : out std_logic_vector(7 downto 0)
);
end;
architecture behavioral of ElectronFpga_core is
signal RSTn : std_logic;
signal cpu_R_W_n : std_logic;
signal cpu_addr : std_logic_vector (15 downto 0);
signal cpu_din : std_logic_vector (7 downto 0);
signal cpu_dout : std_logic_vector (7 downto 0);
signal cpu_IRQ_n : std_logic;
signal cpu_NMI_n : std_logic;
signal ROM_n : std_logic;
signal rom_basic_data : std_logic_vector (7 downto 0);
signal rom_os_data : std_logic_vector (7 downto 0);
signal rom_mmc_data : std_logic_vector (7 downto 0);
signal ula_data : std_logic_vector (7 downto 0);
signal clken_counter : std_logic_vector (3 downto 0);
signal cpu_cycle : std_logic;
signal cpu_clken : std_logic;
signal cpu_clken_1 : std_logic;
signal cpu_clken_2 : std_logic;
signal cpu_clken_4 : std_logic;
signal key_break : std_logic;
signal key_turbo : std_logic_vector(1 downto 0);
signal sound : std_logic;
signal kbd_data : std_logic_vector(3 downto 0);
signal ula_irq_n : std_logic;
signal via1_clken : std_logic;
signal via1_clken_1 : std_logic;
signal via1_clken_2 : std_logic;
signal via1_clken_4 : std_logic;
signal via4_clken : std_logic;
signal via4_clken_1 : std_logic;
signal via4_clken_2 : std_logic;
signal via4_clken_4 : std_logic;
signal mc6522_enable : std_logic;
signal mc6522_data : std_logic_vector(7 downto 0);
signal mc6522_irq_n : std_logic;
-- Port A is not really used, so signals directly loop back out to in
signal mc6522_ca2 : std_logic;
signal mc6522_porta : std_logic_vector(7 downto 0);
-- Port B is used for the MMBEEB style SDCard Interface
signal mc6522_cb1_in : std_logic;
signal mc6522_cb1_out : std_logic;
signal mc6522_cb1_oe_l : std_logic;
signal mc6522_cb2_in : std_logic;
signal mc6522_portb_in : std_logic_vector(7 downto 0);
signal mc6522_portb_out : std_logic_vector(7 downto 0);
signal mc6522_portb_oe_l : std_logic_vector(7 downto 0);
signal sdclk_int : std_logic;
signal rom_latch : std_logic_vector(3 downto 0);
signal contention : std_logic;
signal contention1 : std_logic;
signal contention2 : std_logic;
signal rom_access : std_logic; -- always at 2mhz, no contention
signal ram_access : std_logic; -- 1MHz/2Mhz/Stopped
signal clk_state : std_logic_vector(2 downto 0);
signal scanSW : std_logic; --q
signal mode_video : std_logic_vector(1 downto 0);
begin
cpu : entity work.T65 port map (
Mode => "00",
Abort_n => '1',
SO_n => '1',
Res_n => RSTn or RESET,
Enable => cpu_clken,
Clk => clk_16M00,
Rdy => '1',
IRQ_n => cpu_IRQ_n,
NMI_n => cpu_NMI_n,
R_W_n => cpu_R_W_n,
Sync => open,
A(23 downto 16) => open,
A(15 downto 0) => cpu_addr(15 downto 0),
DI => cpu_din,
DO => cpu_dout
);
rom_basic : entity work.RomBasic2 port map(
clock => clk_16M00,
address => cpu_addr(13 downto 0),
q => rom_basic_data
);
rom_os : entity work.RomOS100 port map(
clock => clk_16M00,
address => cpu_addr(13 downto 0),
q => rom_os_data
);
-- rom_mmc : entity work.RomSmelk3006 port map(
-- clock => clk_16M00,
-- address => cpu_addr(13 downto 0),
-- q => rom_mmc_data
-- );
via : entity work.M6522 port map(
I_RS => cpu_addr(3 downto 0),
I_DATA => cpu_dout(7 downto 0),
O_DATA => mc6522_data(7 downto 0),
I_RW_L => cpu_R_W_n,
I_CS1 => mc6522_enable,
I_CS2_L => '0',
O_IRQ_L => mc6522_irq_n,
I_CA1 => '0',
I_CA2 => mc6522_ca2,
O_CA2 => mc6522_ca2,
O_CA2_OE_L => open,
I_PA => mc6522_porta,
O_PA => mc6522_porta,
O_PA_OE_L => open,
I_CB1 => mc6522_cb1_in,
O_CB1 => mc6522_cb1_out,
O_CB1_OE_L => mc6522_cb1_oe_l,
I_CB2 => mc6522_cb2_in,
O_CB2 => open,
O_CB2_OE_L => open,
I_PB => mc6522_portb_in,
O_PB => mc6522_portb_out,
O_PB_OE_L => mc6522_portb_oe_l,
RESET_L => RSTn or RESET,
I_P2_H => via1_clken,
ENA_4 => via4_clken,
CLK => clk_16M00);
-- SDCLK is driven from either PB1 or CB1 depending on the SR Mode
sdclk_int <= mc6522_portb_out(1) when mc6522_portb_oe_l(1) = '0' else
mc6522_cb1_out when mc6522_cb1_oe_l = '0' else
'1';
SDCLK <= sdclk_int;
mc6522_cb1_in <= sdclk_int;
-- SDMOSI is always driven from PB0
SDMOSI <= mc6522_portb_out(0) when mc6522_portb_oe_l(0) = '0' else
'1';
-- SDMISO is always read from CB2
mc6522_cb2_in <= SDMISO;
-- SDSS is hardwired to 0 (always selected) as there is only one slave attached
SDSS <= '0';
ula : entity work.ElectronULA port map (
clk_16M00 => clk_16M00,
clk_33M33 => clk_33M33,
clk_40M00 => clk_40M00,
-- CPU Interface
cpu_clken => cpu_clken,
addr => cpu_addr,
data_in => cpu_dout,
data_out => ula_data,
R_W_n => cpu_R_W_n,
RST_n => RSTn or RESET,
IRQ_n => ula_irq_n,
NMI_n => cpu_NMI_n,
-- Rom Enable
ROM_n => ROM_n,
-- Video
red => red,
green => green,
blue => blue,
vsync => vsync,
hsync => hsync,
-- Audio
sound => sound,
-- Casette
casIn => casIn,
casOut => casOut,
-- Keyboard
kbd => kbd_data,
-- MISC
-- caps => LED1,
-- motor => LED2,
rom_latch => rom_latch,
-- mode_init => DIP,
mode_init => mode_video, --00 = RGB, 10 = VGA 50Hz
contention => contention
);
input : entity work.keyboard port map(
clk => clk_16M00,
rst_n => ERSTn, -- to avoid a loop when break pressed!
ps2_clk => ps2_clk,
ps2_data => ps2_data,
col => kbd_data,
row => cpu_addr(13 downto 0),
break => key_break,
turbo => key_turbo
,scanSW => scanSW --q
);
mc6522_enable <= '1' when cpu_addr(15 downto 4) = x"fcb" else '0';
cpu_IRQ_n <= mc6522_irq_n AND ula_irq_n;
cpu_NMI_n <= '1';
RSTn <= (ERSTn and key_break) or RESET;
audiol <= sound;
audior <= sound;
cpu_din <= rom_basic_data when ROM_n = '0' and cpu_addr(14) = '0' else
rom_os_data when ROM_n = '0' and cpu_addr(14) = '1' else
rom_mmc_data when cpu_addr(15 downto 14) = "10" and rom_latch = "0111" else
mc6522_data when mc6522_enable = '1' else
ula_data;
--------------------------------------------------------
-- clock enable generator
--------------------------------------------------------
-- ROM accesses always happen at 2Mhz
rom_access <= not ROM_n;
-- RAM accesses always happen at 1Mhz and subber contention
ram_access <= not cpu_addr(15);
-- IO accesses always happen at 1MHz and don't suffer contention
clk_gen1 : process(clk_16M00, RSTn)
begin
if RSTn = '0' then
clken_counter <= (others => '0');
elsif rising_edge(clk_16M00) then
-- clock state machine
if clken_counter(0) = '1' and clken_counter(1) = '1' then
case clk_state is
when "000" =>
if rom_access = '1' then
-- 2MHz no contention
clk_state <= "001";
else
-- 1MHz, possible contention
clk_state <= "101";
end if;
when "001" =>
-- CPU is clocked in this state
clk_state <= "010";
when "010" =>
if rom_access = '1' then
-- 2MHz no contention
clk_state <= "011";
else
-- 1MHz, possible contention
clk_state <= "111";
end if;
when "011" =>
-- CPU is clocked in this state
clk_state <= "000";
when "100" =>
clk_state <= "101";
when "101" =>
clk_state <= "110";
when "110" =>
if ram_access = '1' and contention2 = '1' then
clk_state <= "111";
else
clk_state <= "011";
end if;
when "111" =>
clk_state <= "100";
when others => null;
end case;
end if;
-- clken counter
clken_counter <= clken_counter + 1;
-- Synchronize contention signal
contention1 <= contention;
contention2 <= contention1;
-- 1MHz
-- cpu_clken active on cycle 0
-- address/data changes on cycle 1
cpu_clken_1 <= clken_counter(0) and clken_counter(1) and clken_counter(2) and clken_counter(3);
via1_clken_1 <= clken_counter(0) and clken_counter(1) and clken_counter(2) and clken_counter(3);
via4_clken_1 <= clken_counter(0) and clken_counter(1);
-- 2MHz
-- cpu_clken active on cycle 0, 8
-- address/data changes on cycle 1, 9
cpu_clken_2 <= clken_counter(0) and clken_counter(1) and clken_counter(2);
via1_clken_2 <= clken_counter(0) and clken_counter(1) and clken_counter(2);
via4_clken_2 <= clken_counter(0);
-- 4MHz - no contention
-- cpu_clken active on cycle 0, 4, 8, 12
-- address/data changes on cycle 1, 5, 9, 13
cpu_clken_4 <= clken_counter(0) and clken_counter(1);
via1_clken_4 <= clken_counter(0) and clken_counter(1);
via4_clken_4 <= '1';
end if;
end process;
clk_gen2 : process(key_turbo, clken_counter, clk_state,
cpu_clken_1, cpu_clken_2, cpu_clken_4,
via1_clken_1, via1_clken_2, via1_clken_4,
via4_clken_1, via4_clken_2, via4_clken_4)
begin
case (key_turbo) is
when "01" =>
-- 2Mhz Contention
cpu_clken <= '0';
via1_clken <= '0';
via4_clken <= '0';
if clken_counter(0) = '1' and clken_counter(1) = '1' then
-- 1MHz/2MHz/Stopped
if clk_state = "001" or clk_state = "011" then
cpu_clken <= '1';
end if;
-- 1MHz fixed
if clk_state = "011" or clk_state = "111" then
via1_clken <= '1';
end if;
-- 4MHz fixed
via4_clken <= '1';
end if;
when "10" =>
-- 2Mhz No Contention
cpu_clken <= cpu_clken_2;
via1_clken <= via1_clken_2;
via4_clken <= via4_clken_2;
when "11" =>
-- 4MHz No contention
cpu_clken <= cpu_clken_4;
via1_clken <= via1_clken_4;
via4_clken <= via4_clken_4;
when others =>
-- 1MHz No Contention
cpu_clken <= cpu_clken_1;
via1_clken <= via1_clken_1;
via4_clken <= via4_clken_1;
end case;
end process;
LED1 <= not sdclk_int; --Q
--00 = RGB, 10 = VGA 50Hz
mode_video <= "10";--scanSW & '0';
end behavioral;

View File

@@ -0,0 +1,817 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2015 David Banks
--------------------------------------------------------------------------------
-- ____ ____
-- / /\/ /
-- /___/ \ /
-- \ \ \/
-- \ \
-- / / Filename : ElectronFpga_core.vhd
-- /___/ /\ Timestamp : 28/07/2015
-- \ \ / \
-- \___\/\___\
--
--Design Name: ElectronFpga_core
-- TODO:
-- Implement Cassette Out
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity ElectronULA is
port (
clk_16M00 : in std_logic;
clk_33M33 : in std_logic;
clk_40M00 : in std_logic;
-- CPU Interface
cpu_clken : in std_logic;
addr : in std_logic_vector(15 downto 0);
data_in : in std_logic_vector(7 downto 0);
data_out : out std_logic_vector(7 downto 0);
R_W_n : in std_logic;
RST_n : in std_logic;
IRQ_n : out std_logic;
NMI_n : in std_logic;
-- Rom Enable
ROM_n : out std_logic;
-- Video
red : out std_logic_vector(2 downto 0);
green : out std_logic_vector(2 downto 0);
blue : out std_logic_vector(2 downto 0);
vsync : out std_logic;
hsync : out std_logic;
-- Audio
sound : out std_logic;
-- Keyboard
kbd : in std_logic_vector(3 downto 0);
-- Casette
casIn : in std_logic;
casOut : out std_logic;
-- MISC
caps : out std_logic;
motor : out std_logic;
rom_latch : out std_logic_vector(3 downto 0);
mode_init : in std_logic_vector(1 downto 0);
contention: out std_logic
);
end;
architecture behavioral of ElectronULA is
signal hsync_int : std_logic;
signal vsync_int : std_logic;
signal ram_we : std_logic;
signal ram_data : std_logic_vector(7 downto 0);
signal master_irq : std_logic;
signal power_on_reset : std_logic := '1';
signal rtc_counter : std_logic_vector(18 downto 0);
signal general_counter: std_logic_vector(15 downto 0);
signal sound_bit : std_logic;
signal isr_data : std_logic_vector(7 downto 0);
-- ULA Registers
signal isr : std_logic_vector(6 downto 2);
signal ier : std_logic_vector(6 downto 2);
signal screen_base : std_logic_vector(14 downto 6);
signal data_shift : std_logic_vector(7 downto 0);
signal page_enable : std_logic;
signal page : std_logic_vector(2 downto 0);
signal counter : std_logic_vector(7 downto 0);
signal display_mode : std_logic_vector(2 downto 0);
signal comms_mode : std_logic_vector(1 downto 0);
type palette_type is array (0 to 7) of std_logic_vector (7 downto 0);
signal palette : palette_type;
signal hsync_start : std_logic_vector(10 downto 0);
signal hsync_end : std_logic_vector(10 downto 0);
signal h_active : std_logic_vector(10 downto 0);
signal h_total : std_logic_vector(10 downto 0);
signal h_count : std_logic_vector(10 downto 0);
signal h_count1 : std_logic_vector(10 downto 0);
signal vsync_start : std_logic_vector(9 downto 0);
signal vsync_end : std_logic_vector(9 downto 0);
signal v_active_gph : std_logic_vector(9 downto 0);
signal v_active_txt : std_logic_vector(9 downto 0);
signal v_total : std_logic_vector(9 downto 0);
signal v_count : std_logic_vector(9 downto 0);
signal v_rtc : std_logic_vector(9 downto 0);
signal v_display : std_logic_vector(9 downto 0);
signal char_row : std_logic_vector(3 downto 0);
signal row_offset : std_logic_vector(14 downto 0);
signal col_offset : std_logic_vector(9 downto 0);
signal screen_addr : std_logic_vector(14 downto 0);
signal screen_data : std_logic_vector(7 downto 0);
-- Screen Mode Registers
signal mode : std_logic_vector(1 downto 0);
-- the 256 byte page that the mode starts at
signal mode_base : std_logic_vector(7 downto 0);
-- the number of bits per pixel (0 = 1BPP, 1 = 2BPP, 2=4BPP)
signal mode_bpp : std_logic_vector(1 downto 0);
-- a '1' indicates a text mode (modes 3 and 6)
signal mode_text : std_logic;
-- a '1' indicates a 40-col mode (modes 4, 5 and 6)
signal mode_40 : std_logic;
-- the number of bytes to increment row_offset when moving from one char row to the next
signal mode_rowstep : std_logic_vector(9 downto 0);
signal display_intr : std_logic;
signal display_intr1 : std_logic;
signal display_intr2 : std_logic;
signal rtc_intr : std_logic;
signal rtc_intr1 : std_logic;
signal rtc_intr2 : std_logic;
signal clk_video : std_logic;
signal ctrl_caps : std_logic;
signal field : std_logic;
signal caps_int : std_logic;
signal motor_int : std_logic;
-- Supports changing the jumpers
signal mode_init_copy : std_logic_vector(1 downto 0);
-- Stable copies sampled once per frame
signal screen_base1 : std_logic_vector(14 downto 6);
signal mode_base1 : std_logic_vector(7 downto 0);
-- Tape Interface
signal cintone : std_logic;
signal cindat : std_logic;
signal databits : std_logic_vector(3 downto 0);
signal casIn1 : std_logic;
signal casIn2 : std_logic;
signal casIn3 : std_logic;
signal ignore_next : std_logic;
-- Helper function to cast an std_logic value to an integer
function sl2int (x: std_logic) return integer is
begin
if x = '1' then
return 1;
else
return 0;
end if;
end;
-- Helper function to cast an std_logic_vector value to an integer
function slv2int (x: std_logic_vector) return integer is
begin
return to_integer(unsigned(x));
end;
begin
-- video timing constants
-- mode 00 - RGB/s @ 50Hz non-interlaced
-- mode 01 - RGB/s @ 50Hz interlaced
-- mode 10 - SVGA @ 50Hz
-- mode 11 - SVGA @ 60Hz
clk_video <= clk_40M00 when mode = "11" else
clk_33M33 when mode = "10" else
clk_16M00;
hsync_start <= std_logic_vector(to_unsigned(759, 11)) when mode = "11" else
std_logic_vector(to_unsigned(759, 11)) when mode = "10" else
std_logic_vector(to_unsigned(762, 11));
hsync_end <= std_logic_vector(to_unsigned(887, 11)) when mode = "11" else
std_logic_vector(to_unsigned(887, 11)) when mode = "10" else
std_logic_vector(to_unsigned(837, 11));
h_total <= std_logic_vector(to_unsigned(1055, 11)) when mode = "11" else
std_logic_vector(to_unsigned(1055, 11)) when mode = "10" else
std_logic_vector(to_unsigned(1023, 11));
h_active <= std_logic_vector(to_unsigned(640, 11));
vsync_start <= std_logic_vector(to_unsigned(556, 10)) when mode = "11" else
std_logic_vector(to_unsigned(556, 10)) when mode = "10" else
std_logic_vector(to_unsigned(274, 10));
vsync_end <= std_logic_vector(to_unsigned(560, 10)) when mode = "11" else
std_logic_vector(to_unsigned(560, 10)) when mode = "10" else
std_logic_vector(to_unsigned(277, 10));
v_total <= std_logic_vector(to_unsigned(627, 10)) when mode = "11" else
std_logic_vector(to_unsigned(627, 10)) when mode = "10" else
std_logic_vector(to_unsigned(311, 10)) when field = '0' else
std_logic_vector(to_unsigned(312, 10));
v_active_gph <= std_logic_vector(to_unsigned(512, 10)) when mode = "11" else
std_logic_vector(to_unsigned(512, 10)) when mode = "10" else
std_logic_vector(to_unsigned(256, 10));
v_active_txt <= std_logic_vector(to_unsigned(500, 10)) when mode = "11" else
std_logic_vector(to_unsigned(500, 10)) when mode = "10" else
std_logic_vector(to_unsigned(250, 10));
v_display <= std_logic_vector(to_unsigned(513, 10)) when mode = "11" else
std_logic_vector(to_unsigned(513, 10)) when mode = "10" else
std_logic_vector(to_unsigned(256, 10));
v_rtc <= std_logic_vector(to_unsigned(201, 10)) when mode = "11" else
std_logic_vector(to_unsigned(201, 10)) when mode = "10" else
std_logic_vector(to_unsigned(100, 10));
ram : entity work.RAM_32K_DualPort port map(
-- Port A is the 6502 port
clka => clk_16M00,
wea => ram_we,
addra => addr(14 downto 0),
dina => data_in,
douta => ram_data,
-- Port B is the VGA Port
clkb => clk_video,
web => '0',
addrb => screen_addr,
dinb => x"00",
doutb => screen_data
);
sound <= sound_bit;
-- FIXME: This should probably be gate with a clock enable
ram_we <= '1' when addr(15) = '0' and R_W_n = '0' else '0';
-- The external ROM is enabled:
-- - When the address is C000-FBFF and FF00-FFFF (i.e. OS Rom)
-- - When the address is 8000-BFFF and the ROM 10 or 11 is paged in (101x)
ROM_n <= '0' when addr(15 downto 14) = "11" and addr(15 downto 8) /= x"FC" and addr(15 downto 8) /= x"FD" and addr(15 downto 8) /= x"FE" else
'0' when addr(15 downto 14) = "10" and page_enable = '1' and page(2 downto 1) = "01" else
'1';
-- ULA Reads + RAM Reads + KBD Reads
data_out <= ram_data when addr(15) = '0' else
"0000" & kbd when addr(15 downto 14) = "10" and page_enable = '1' and page(2 downto 1) = "00" else
isr_data when addr(15 downto 8) = x"FE" and addr(3 downto 0) = x"0" else
data_shift when addr(15 downto 8) = x"FE" and addr(3 downto 0) = x"4" else
x"F1"; -- todo FIXEME
-- Register FEx0 is the Interrupt Status Register (Read Only)
-- Bit 7 always reads as 1
-- Bits 6..2 refect in interrups status regs
-- Bit 1 is the power up reset bit, cleared by the first read after power up
-- Bit 0 is the OR of bits 6..2
master_irq <= (isr(6) and ier(6)) or
(isr(5) and ier(5)) or
(isr(4) and ier(4)) or
(isr(3) and ier(3)) or
(isr(2) and ier(2));
IRQ_n <= not master_irq;
isr_data <= '1' & isr(6 downto 2) & power_on_reset & master_irq;
rom_latch <= page_enable & page;
process (clk_16M00, RST_n)
begin
if (RST_n = '0') then
isr <= (others => '0');
ier <= (others => '0');
screen_base <= (others => '0');
data_shift <= (others => '0');
page_enable <= '0';
page <= (others => '0');
counter <= (others => '0');
comms_mode <= "01";
motor_int <= '0';
caps_int <= '0';
rtc_counter <= (others => '0');
general_counter <= (others => '0');
sound_bit <= '0';
mode <= mode_init;
mode_init_copy <= mode_init;
ctrl_caps <= '0';
cindat <= '0';
cintone <= '0';
elsif rising_edge(clk_16M00) then
-- Detect control+caps 1...4 and change video format
if (addr = x"9fff" and page_enable = '1' and page(2 downto 1) = "00") then
if (kbd(2 downto 1) = "11") then
ctrl_caps <= '1';
else
ctrl_caps <= '0';
end if;
end if;
-- Detect "1" being pressed
if (addr = x"afff" and page_enable = '1' and page(2 downto 1) = "00" and ctrl_caps = '1' and kbd(0) = '1') then
mode <= "00";
end if;
-- Detect "2" being pressed
if (addr = x"b7ff" and page_enable = '1' and page(2 downto 1) = "00" and ctrl_caps = '1' and kbd(0) = '1') then
mode <= "01";
end if;
-- Detect "3" being pressed
if (addr = x"bbff" and page_enable = '1' and page(2 downto 1) = "00" and ctrl_caps = '1' and kbd(0) = '1') then
mode <= "10";
end if;
-- Detect "4" being pressed
if (addr = x"bdff" and page_enable = '1' and page(2 downto 1) = "00" and ctrl_caps = '1' and kbd(0) = '1') then
mode <= "11";
end if;
-- Detect Jumpers being changed
if (mode_init_copy /= mode_init) then
mode <= mode_init;
mode_init_copy <= mode_init;
end if;
-- Synchronize the display interrupt signal from the VGA clock domain
display_intr1 <= display_intr;
display_intr2 <= display_intr1;
-- Generate the display end interrupt on the rising edge (line 256 of the screen)
if (display_intr2 = '0' and display_intr1 = '1') then
isr(2) <= '1';
end if;
-- Synchronize the rtc interrupt signal from the VGA clock domain
rtc_intr1 <= rtc_intr;
rtc_intr2 <= rtc_intr1;
if (mode = "11") then
-- For 60Hz frame rates we must synthesise a the 50Hz real time clock interrupt
-- In theory the counter limit should be 319999, but there are additional
-- rtc ticks if not rtc interrupt is received between two display interrupts
-- hence the correction factor of 6/5. This comes from the probability
-- of the there not being a 50Hz rtc interrupts between any two successive
-- 60Hz display interrupts.
if (rtc_counter = 383999) then
rtc_counter <= (others => '0');
isr(3) <= '1';
else
rtc_counter <= rtc_counter + 1;
end if;
else
-- Generate the rtc interrupt on the rising edge (line 100 of the screen)
if (rtc_intr2 = '0' and rtc_intr1 = '1') then
isr(3) <= '1';
end if;
end if;
if (comms_mode = "00") then
if (casIn2 = '0') then
general_counter <= (others => '0');
else
general_counter <= general_counter + 1;
end if;
elsif (comms_mode = "01") then
-- Sound Frequency = 1MHz / [16 * (S + 1)]
if (general_counter = 0) then
general_counter <= counter & "00000000";
sound_bit <= not sound_bit;
else
general_counter <= general_counter - 1;
end if;
end if;
-- Tape Interface Receive
casIn1 <= casIn;
casIn2 <= casIn1;
casIn3 <= casIn2;
if (comms_mode = "00" and motor_int = '1') then
-- Only take actions on the falling edge of casIn
-- On the falling edge, general_counter will contain length of
-- the previous high pulse in 16MHz cycles.
-- A 1200Hz pulse is 6666 cycles
-- A 2400Hz pulse is 3333 cycles
-- A threshold in between would be 5000 cycles.
-- Ignore pulses shorter then say 500 cycles as these are
-- probably just noise.
if (casIn3 = '1' and casIn2 = '0' and general_counter > 500) then
-- a Pulse of length > 500 cycles has been detected
if (cindat = '0' and cintone = '0' and general_counter <= 5000) then
-- High Tone detected
cindat <= '0';
cintone <= '1';
databits <= (others => '0');
-- Generate the high tone detect interrupt
isr(6) <= '1';
elsif (cindat = '0' and cintone = '1' and general_counter > 5000) then
-- Start bit detected
cindat <= '1';
cintone <= '0';
databits <= (others => '0');
elsif (cindat = '1' and ignore_next = '1') then
-- Ignoring the second pulse in a bit at 2400Hz
ignore_next <= '0';
elsif (cindat = '1' and databits < 9) then
if (databits < 8) then
if (general_counter > 5000) then
-- shift in a zero
data_shift <= '0' & data_shift(7 downto 1);
else
-- shift in a one
data_shift <= '1' & data_shift(7 downto 1);
end if;
-- Generate the receive data int as soon as the
-- last bit has been shifted in.
if (databits = 7) then
isr(4) <= '1';
end if;
end if;
-- Ignore the second pulse in a bit at 2400Hz
if (general_counter > 5000) then
ignore_next <= '0';
else
ignore_next <= '1';
end if;
-- Move on to the next data bit
databits <= databits + 1;
elsif (cindat = '1' and databits = 9) then
if (general_counter > 5000) then
-- Found next start bit...
cindat <= '1';
cintone <= '0';
databits <= (others => '0');
else
-- Back in tone again
cindat <= '0';
cintone <= '1';
databits <= (others => '0');
-- Generate the high tone detect interrupt
isr(6) <= '1';
end if;
end if;
end if;
else
cindat <= '0';
cintone <= '0';
databits <= (others => '0');
ignore_next <= '0';
end if;
-- ULA Writes
if (cpu_clken = '1') then
if (addr(15 downto 8) = x"FE") then
if (R_W_n = '1') then
-- Clear the power on reset flag on the first read of the ISR (FEx0)
if (addr(3 downto 0) = x"0") then
power_on_reset <= '0';
end if;
-- Clear the RDFull interrupts on reading the data_shift register
if (addr(3 downto 0) = x"4") then
isr(4) <= '0';
end if;
else
case addr(3 downto 0) is
when x"0" =>
ier(6 downto 2) <= data_in(6 downto 2);
when x"1" =>
when x"2" =>
screen_base(8 downto 6) <= data_in(7 downto 5);
when x"3" =>
screen_base(14 downto 9) <= data_in(5 downto 0);
when x"4" =>
data_shift <= data_in;
-- Clear the TDEmpty interrupt on writing the
-- data_shift register
isr(5) <= '0';
when x"5" =>
if (data_in(6) = '1') then
-- Clear High Tone Detect IRQ
isr(6) <= '0';
end if;
if (data_in(5) = '1') then
-- Clear Real Time Clock IRQ
isr(3) <= '0';
end if;
if (data_in(4) = '1') then
-- Clear Display End IRQ
isr(2) <= '0';
end if;
if (page_enable = '1' and page(2) = '0') then
-- Roms 8-11 currently selected, so only selecting 8-15 will be honoured
if (data_in(3) = '1') then
page_enable <= data_in(3);
page <= data_in(2 downto 0);
end if;
else
-- Roms 0-7 or 12-15 currently selected, so anything goes
page_enable <= data_in(3);
page <= data_in(2 downto 0);
end if;
when x"6" =>
counter <= data_in;
when x"7" =>
caps_int <= data_in(7);
motor_int <= data_in(6);
case (data_in(5 downto 3)) is
when "000" =>
mode_base <= x"30";
mode_bpp <= "00";
mode_40 <= '0';
mode_text <= '0';
mode_rowstep <= std_logic_vector(to_unsigned(633, 10)); -- 640 - 7
when "001" =>
mode_base <= x"30";
mode_bpp <= "01";
mode_40 <= '0';
mode_text <= '0';
mode_rowstep <= std_logic_vector(to_unsigned(633, 10)); -- 640 - 7
when "010" =>
mode_base <= x"30";
mode_bpp <= "10";
mode_40 <= '0';
mode_text <= '0';
mode_rowstep <= std_logic_vector(to_unsigned(633, 10)); -- 640 - 7
when "011" =>
mode_base <= x"40";
mode_bpp <= "00";
mode_40 <= '0';
mode_text <= '1';
mode_rowstep <= std_logic_vector(to_unsigned(631, 10)); -- 640 - 9
when "100" =>
mode_base <= x"58";
mode_bpp <= "00";
mode_40 <= '1';
mode_text <= '0';
mode_rowstep <= std_logic_vector(to_unsigned(313, 10)); -- 320 - 7
when "101" =>
mode_base <= x"60";
mode_bpp <= "01";
mode_40 <= '1';
mode_text <= '0';
mode_rowstep <= std_logic_vector(to_unsigned(313, 10)); -- 320 - 7
when "110" =>
mode_base <= x"60";
mode_bpp <= "00";
mode_40 <= '1';
mode_text <= '1';
mode_rowstep <= std_logic_vector(to_unsigned(311, 10)); -- 320 - 9
when "111" =>
-- mode 7 seems to default to mode 4
mode_base <= x"58";
mode_bpp <= "00";
mode_40 <= '1';
mode_text <= '0';
mode_rowstep <= std_logic_vector(to_unsigned(313, 10)); -- 320 - 7
when others =>
end case;
comms_mode <= data_in(2 downto 1);
when others =>
-- A '1' in the palatte data means disable the colour
-- Invert the stored palette, to make the palette logic simpler
palette(slv2int(addr(2 downto 0))) <= data_in xor "11111111";
end case;
end if;
end if;
end if;
end if;
end process;
-- SGVA timing at 60Hz with a 40.000MHz Pixel Clock
-- Horizontal 800 + 40 + 128 + 88 = total 1056
-- Vertical 600 + 1 + 4 + 23 = total 628
-- Within the the 640x512 is centred so starts at 80,44
-- Horizontal 640 + (80 + 40) + 128 + (88 + 80) = total 1056
-- Vertical 512 + (44 + 1) + 4 + (23 + 44) = total 628
-- RGBs timing at 50Hz with a 16.000MHz Pixel Clock
-- Horizontal 640 + (96 + 26) + 75 + (91 + 96) = total 1024
-- Vertical 256 + (16 + 2) + 3 + (19 + 16) = total 312
process (clk_video)
variable pixel : std_logic_vector(3 downto 0);
begin
if rising_edge(clk_video) then
-- pipeline h_count by one cycle to compensate the register in the RAM
h_count1 <= h_count;
if (h_count = h_total) then
h_count <= (others => '0');
col_offset <= (others => '0');
if (v_count = v_total) then
v_count <= (others => '0');
char_row <= (others => '0');
row_offset <= (others => '0');
screen_base1 <= screen_base;
mode_base1 <= mode_base;
if (mode = "01") then
-- Interlaced, so alternate odd and even fields
field <= not field;
else
-- Non-interlaced, so odd fields only
field <= '0';
end if;
else
v_count <= v_count + 1;
if (v_count(0) = '1' or mode(1) = '0') then
if ((mode_text = '0' and char_row = 7) or (mode_text = '1' and char_row = 9)) then
char_row <= (others => '0');
row_offset <= row_offset + mode_rowstep;
else
char_row <= char_row + 1;
row_offset <= row_offset + 1;
end if;
end if;
end if;
else
h_count <= h_count + 1;
if ((mode_40 = '0' and h_count(2 downto 0) = "111") or
(mode_40 = '1' and h_count(3 downto 0) = "1111")) then
col_offset <= col_offset + 8;
end if;
end if;
-- RGB Data
if (h_count1 >= h_active or (mode_text = '0' and v_count >= v_active_gph) or (mode_text = '1' and v_count >= v_active_txt) or char_row >= 8) then
-- blanking and border are always black
red <= (others => '0');
green <= (others => '0');
blue <= (others => '0');
contention <= '0';
else
-- Indicate possible memory contention on active scan lines
contention <= not mode_40;
-- rendering an actual pixel
if (mode_bpp = 0) then
-- 1 bit per pixel, map to colours 0 and 8 for the palette lookup
if (mode_40 = '1') then
pixel := screen_data(7 - slv2int(h_count1(3 downto 1))) & "000";
else
pixel := screen_data(7 - slv2int(h_count1(2 downto 0))) & "000";
end if;
elsif (mode_bpp = 1) then
-- 2 bits per pixel, map to colours 0, 2, 8, 10 for the palette lookup
if (mode_40 = '1') then
pixel := screen_data(7 - slv2int(h_count1(3 downto 2))) & "0" &
screen_data(3 - slv2int(h_count1(3 downto 2))) & "0";
else
pixel := screen_data(7 - slv2int(h_count1(2 downto 1))) & "0" &
screen_data(3 - slv2int(h_count1(2 downto 1))) & "0";
end if;
else
-- 4 bits per pixel, map directly for the palette lookup
if (mode_40 = '1') then
pixel := screen_data(7 - sl2int(h_count1(3))) &
screen_data(5 - sl2int(h_count1(3))) &
screen_data(3 - sl2int(h_count1(3))) &
screen_data(1 - sl2int(h_count1(3)));
else
pixel := screen_data(7 - sl2int(h_count1(2))) &
screen_data(5 - sl2int(h_count1(2))) &
screen_data(3 - sl2int(h_count1(2))) &
screen_data(1 - sl2int(h_count1(2)));
end if;
end if;
-- Implement Color Palette
case (pixel) is
when "0000" =>
red <= (others => palette(1)(0));
green <= (others => palette(1)(4));
blue <= (others => palette(0)(4));
when "0001" =>
red <= (others => palette(7)(0));
green <= (others => palette(7)(4));
blue <= (others => palette(6)(4));
when "0010" =>
red <= (others => palette(1)(1));
green <= (others => palette(1)(5));
blue <= (others => palette(0)(5));
when "0011" =>
red <= (others => palette(7)(1));
green <= (others => palette(7)(5));
blue <= (others => palette(6)(5));
when "0100" =>
red <= (others => palette(3)(0));
green <= (others => palette(3)(4));
blue <= (others => palette(2)(4));
when "0101" =>
red <= (others => palette(5)(0));
green <= (others => palette(5)(4));
blue <= (others => palette(4)(4));
when "0110" =>
red <= (others => palette(3)(1));
green <= (others => palette(3)(5));
blue <= (others => palette(2)(5));
when "0111" =>
red <= (others => palette(5)(1));
green <= (others => palette(5)(5));
blue <= (others => palette(4)(5));
when "1000" =>
red <= (others => palette(1)(2));
green <= (others => palette(0)(2));
blue <= (others => palette(0)(6));
when "1001" =>
red <= (others => palette(7)(2));
green <= (others => palette(6)(2));
blue <= (others => palette(6)(6));
when "1010" =>
red <= (others => palette(1)(3));
green <= (others => palette(0)(3));
blue <= (others => palette(0)(7));
when "1011" =>
red <= (others => palette(7)(3));
green <= (others => palette(6)(3));
blue <= (others => palette(6)(7));
when "1100" =>
red <= (others => palette(3)(2));
green <= (others => palette(2)(2));
blue <= (others => palette(2)(6));
when "1101" =>
red <= (others => palette(5)(2));
green <= (others => palette(4)(2));
blue <= (others => palette(4)(6));
when "1110" =>
red <= (others => palette(3)(3));
green <= (others => palette(2)(3));
blue <= (others => palette(2)(7));
when "1111" =>
red <= (others => palette(5)(3));
green <= (others => palette(4)(3));
blue <= (others => palette(4)(7));
when others =>
end case;
end if;
-- Vertical Sync
if (field = '0') then
-- first field of interlaced scanning (or non interlaced)
-- vsync starts at the begging of the line
if (h_count1 = 0) then
if (v_count = vsync_start) then
vsync_int <= '0';
elsif (v_count = vsync_end) then
vsync_int <= '1';
end if;
end if;
else
-- second field of intelaced scanning
-- vsync starts half way through the line
if (h_count1 = ('0' & h_total(10 downto 1))) then
if (v_count = vsync_start) then
vsync_int <= '0';
elsif (v_count = vsync_end) then
vsync_int <= '1';
end if;
end if;
end if;
-- Horizontal Sync
if (h_count1 = hsync_start) then
hsync_int <= '0';
if (v_count = v_display) then
display_intr <= '1';
end if;
if (v_count = v_rtc) then
rtc_intr <= '1';
end if;
elsif (h_count1 = hsync_end) then
hsync_int <= '1';
display_intr <= '0';
rtc_intr <= '0';
end if;
end if;
end process;
process (screen_base1, mode_base1, row_offset, col_offset)
variable tmp: std_logic_vector(15 downto 0);
begin
tmp := ("0" & screen_base1 & "000000") + row_offset + col_offset;
if (tmp(15) = '1') then
tmp := tmp + (mode_base1 & "00000000");
end if;
screen_addr <= tmp(14 downto 0);
end process;
vsync <= '1' when mode(1) = '0' else vsync_int;
hsync <= hsync_int and vsync_int when mode(1) = '0' else hsync_int;
caps <= caps_int;
motor <= motor_int;
casOut <= '0';
end behavioral;

View File

@@ -0,0 +1,48 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity RAM_32K_DualPort is
port (
clka : in std_logic;
wea : in std_logic;
addra : in std_logic_vector(14 downto 0);
dina : in std_logic_vector(7 downto 0);
douta : out std_logic_vector(7 downto 0);
clkb : in std_logic;
web : in std_logic;
addrb : in std_logic_vector(14 downto 0);
dinb : in std_logic_vector(7 downto 0);
doutb : out std_logic_vector(7 downto 0)
);
end;
architecture behavioral of RAM_32K_DualPort is
type ram_type is array (32767 downto 0) of std_logic_vector (7 downto 0);
shared variable RAM : ram_type;
begin
process (clka)
begin
if rising_edge(clka) then
if (wea = '1') then
RAM(conv_integer(addra)) := dina;
end if;
douta <= RAM(conv_integer(addra));
end if;
end process;
process (clkb)
begin
if rising_edge(clkb) then
if (web = '1') then
RAM(conv_integer(addrb)) := dinb;
end if;
doutb <= RAM(conv_integer(addrb));
end if;
end process;
end behavioral;

View File

@@ -0,0 +1,169 @@
-- megafunction wizard: %ROM: 1-PORT%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altsyncram
-- ============================================================
-- File Name: RomBasic2.vhd
-- Megafunction Name(s):
-- altsyncram
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 13.0.1 Build 232 06/12/2013 SP 1 SJ Full Version
-- ************************************************************
--Copyright (C) 1991-2013 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY RomBasic2 IS
PORT
(
address : IN STD_LOGIC_VECTOR (13 DOWNTO 0);
clock : IN STD_LOGIC := '1';
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END RomBasic2;
ARCHITECTURE SYN OF rombasic2 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
COMPONENT altsyncram
GENERIC (
address_aclr_a : STRING;
clock_enable_input_a : STRING;
clock_enable_output_a : STRING;
init_file : STRING;
intended_device_family : STRING;
lpm_hint : STRING;
lpm_type : STRING;
numwords_a : NATURAL;
operation_mode : STRING;
outdata_aclr_a : STRING;
outdata_reg_a : STRING;
widthad_a : NATURAL;
width_a : NATURAL;
width_byteena_a : NATURAL
);
PORT (
address_a : IN STD_LOGIC_VECTOR (13 DOWNTO 0);
clock0 : IN STD_LOGIC ;
q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END COMPONENT;
BEGIN
q <= sub_wire0(7 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
address_aclr_a => "NONE",
clock_enable_input_a => "BYPASS",
clock_enable_output_a => "BYPASS",
init_file => "../rtl/roms/basic2.hex",
intended_device_family => "Cyclone III",
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
lpm_type => "altsyncram",
numwords_a => 16384,
operation_mode => "ROM",
outdata_aclr_a => "NONE",
outdata_reg_a => "CLOCK0",
widthad_a => 14,
width_a => 8,
width_byteena_a => 1
)
PORT MAP (
address_a => address,
clock0 => clock,
q_a => sub_wire0
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
-- Retrieval info: PRIVATE: AclrByte NUMERIC "0"
-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: Clken NUMERIC "0"
-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
-- Retrieval info: PRIVATE: MIFfilename STRING "../rtl/roms/basic2.hex"
-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "16384"
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
-- Retrieval info: PRIVATE: RegAddr NUMERIC "1"
-- Retrieval info: PRIVATE: RegOutput NUMERIC "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: SingleClock NUMERIC "1"
-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
-- Retrieval info: PRIVATE: WidthAddr NUMERIC "14"
-- Retrieval info: PRIVATE: WidthData NUMERIC "8"
-- Retrieval info: PRIVATE: rden NUMERIC "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
-- Retrieval info: CONSTANT: INIT_FILE STRING "../rtl/roms/basic2.hex"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "16384"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "14"
-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
-- Retrieval info: USED_PORT: address 0 0 14 0 INPUT NODEFVAL "address[13..0]"
-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
-- Retrieval info: CONNECT: @address_a 0 0 14 0 address 0 0 14 0
-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomBasic2.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomBasic2.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomBasic2.cmp FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomBasic2.bsf FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomBasic2_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,169 @@
-- megafunction wizard: %ROM: 1-PORT%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altsyncram
-- ============================================================
-- File Name: RomOS100.vhd
-- Megafunction Name(s):
-- altsyncram
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 13.0.1 Build 232 06/12/2013 SP 1 SJ Full Version
-- ************************************************************
--Copyright (C) 1991-2013 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY RomOS100 IS
PORT
(
address : IN STD_LOGIC_VECTOR (13 DOWNTO 0);
clock : IN STD_LOGIC := '1';
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END RomOS100;
ARCHITECTURE SYN OF romos100 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
COMPONENT altsyncram
GENERIC (
address_aclr_a : STRING;
clock_enable_input_a : STRING;
clock_enable_output_a : STRING;
init_file : STRING;
intended_device_family : STRING;
lpm_hint : STRING;
lpm_type : STRING;
numwords_a : NATURAL;
operation_mode : STRING;
outdata_aclr_a : STRING;
outdata_reg_a : STRING;
widthad_a : NATURAL;
width_a : NATURAL;
width_byteena_a : NATURAL
);
PORT (
address_a : IN STD_LOGIC_VECTOR (13 DOWNTO 0);
clock0 : IN STD_LOGIC ;
q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END COMPONENT;
BEGIN
q <= sub_wire0(7 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
address_aclr_a => "NONE",
clock_enable_input_a => "BYPASS",
clock_enable_output_a => "BYPASS",
init_file => "../rtl/roms/os100.hex",
intended_device_family => "Cyclone III",
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
lpm_type => "altsyncram",
numwords_a => 16384,
operation_mode => "ROM",
outdata_aclr_a => "NONE",
outdata_reg_a => "CLOCK0",
widthad_a => 14,
width_a => 8,
width_byteena_a => 1
)
PORT MAP (
address_a => address,
clock0 => clock,
q_a => sub_wire0
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
-- Retrieval info: PRIVATE: AclrByte NUMERIC "0"
-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: Clken NUMERIC "0"
-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
-- Retrieval info: PRIVATE: MIFfilename STRING "../rtl/roms/os100.hex"
-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "16384"
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
-- Retrieval info: PRIVATE: RegAddr NUMERIC "1"
-- Retrieval info: PRIVATE: RegOutput NUMERIC "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: SingleClock NUMERIC "1"
-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
-- Retrieval info: PRIVATE: WidthAddr NUMERIC "14"
-- Retrieval info: PRIVATE: WidthData NUMERIC "8"
-- Retrieval info: PRIVATE: rden NUMERIC "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
-- Retrieval info: CONSTANT: INIT_FILE STRING "../rtl/roms/os100.hex"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "16384"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "14"
-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
-- Retrieval info: USED_PORT: address 0 0 14 0 INPUT NODEFVAL "address[13..0]"
-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
-- Retrieval info: CONNECT: @address_a 0 0 14 0 address 0 0 14 0
-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomOS100.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomOS100.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomOS100.cmp FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomOS100.bsf FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomOS100_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,143 @@
-- megafunction wizard: %ROM: 1-PORT%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altsyncram
-- ============================================================
-- File Name: RomSmelk3006.vhd
-- Megafunction Name(s):
-- altsyncram
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 13.1.0 Build 162 10/23/2013 SJ Web Edition
-- ************************************************************
--Copyright (C) 1991-2013 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.altera_mf_components.all;
ENTITY RomSmelk3006 IS
PORT
(
address : IN STD_LOGIC_VECTOR (13 DOWNTO 0);
clock : IN STD_LOGIC := '1';
q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
);
END RomSmelk3006;
ARCHITECTURE SYN OF romsmelk3006 IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
BEGIN
q <= sub_wire0(7 DOWNTO 0);
altsyncram_component : altsyncram
GENERIC MAP (
address_aclr_a => "NONE",
clock_enable_input_a => "BYPASS",
clock_enable_output_a => "BYPASS",
init_file => "./roms/smelk3006.hex",
intended_device_family => "Cyclone III",
lpm_hint => "ENABLE_RUNTIME_MOD=NO",
lpm_type => "altsyncram",
numwords_a => 16384,
operation_mode => "ROM",
outdata_aclr_a => "NONE",
outdata_reg_a => "CLOCK0",
widthad_a => 14,
width_a => 8,
width_byteena_a => 1
)
PORT MAP (
address_a => address,
clock0 => clock,
q_a => sub_wire0
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
-- Retrieval info: PRIVATE: AclrByte NUMERIC "0"
-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
-- Retrieval info: PRIVATE: Clken NUMERIC "0"
-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
-- Retrieval info: PRIVATE: MIFfilename STRING "./roms/smelk3006.hex"
-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "16384"
-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
-- Retrieval info: PRIVATE: RegAddr NUMERIC "1"
-- Retrieval info: PRIVATE: RegOutput NUMERIC "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: SingleClock NUMERIC "1"
-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
-- Retrieval info: PRIVATE: WidthAddr NUMERIC "14"
-- Retrieval info: PRIVATE: WidthData NUMERIC "8"
-- Retrieval info: PRIVATE: rden NUMERIC "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: ADDRESS_ACLR_A STRING "NONE"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
-- Retrieval info: CONSTANT: INIT_FILE STRING "./roms/smelk3006.hex"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "16384"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0"
-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "14"
-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
-- Retrieval info: USED_PORT: address 0 0 14 0 INPUT NODEFVAL "address[13..0]"
-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL "q[7..0]"
-- Retrieval info: CONNECT: @address_a 0 0 14 0 address 0 0 14 0
-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomSmelk3006.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomSmelk3006.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomSmelk3006.cmp TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomSmelk3006.bsf FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL RomSmelk3006_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf

View File

@@ -0,0 +1,666 @@
-- ****
-- T65(b) core. In an effort to merge and maintain bug fixes ....
--
-- Ver 313 WoS January 2015
-- Fixed issue that NMI has to be first if issued the same time as a BRK instruction is latched in
-- Now all Lorenz CPU tests on FPGAARCADE C64 core (sources used: SVN version 1021) are OK! :D :D :D
-- This is just a starting point to go for optimizations and detailed fixes (the Lorenz test can't find)
--
-- Ver 312 WoS January 2015
-- Undoc opcode timing fixes for $B3 (LAX iy) and $BB (LAS ay)
-- Added comments in MCode section to find handling of individual opcodes more easily
-- All "basic" Lorenz instruction test (individual functional checks, CPUTIMING check) work now with
-- actual FPGAARCADE C64 core (sources used: SVN version 1021).
--
-- Ver 305, 306, 307, 308, 309, 310, 311 WoS January 2015
-- Undoc opcode fixes (now all Lorenz test on instruction functionality working, except timing issues on $B3 and $BB):
-- SAX opcode
-- SHA opcode
-- SHX opcode
-- SHY opcode
-- SHS opcode
-- LAS opcode
-- alternate SBC opcode
-- fixed NOP with immediate param (caused Lorenz trap test to fail)
-- IRQ and NMI timing fixes (in conjuction with branches)
--
-- Ver 304 WoS December 2014
-- Undoc opcode fixes:
-- ARR opcode
-- ANE/XAA opcode
-- Corrected issue with NMI/IRQ prio (when asserted the same time)
--
-- Ver 303 ost(ML) July 2014
-- (Sorry for some scratchpad comments that may make little sense)
-- Mods and some 6502 undocumented instructions.
-- Not correct opcodes acc. to Lorenz tests (incomplete list):
-- NOPN (nop)
-- NOPZX (nop + byte 172)
-- NOPAX (nop + word da ... da: byte 0)
-- ASOZ (byte $07 + byte 172)
--
-- Ver 303,302 WoS April 2014
-- Bugfixes for NMI from foft
-- Bugfix for BRK command (and its special flag)
--
-- Ver 300,301 WoS January 2014
-- More merging
-- Bugfixes by ehenciak added, started tidyup *bust*
--
-- MikeJ March 2005
-- Latest version from www.fpgaarcade.com (original www.opencores.org)
-- ****
--
-- 65xx compatible microprocessor core
--
-- FPGAARCADE SVN: $Id: T65.vhd 1347 2015-05-27 20:07:34Z wolfgang.scherr $
--
-- Copyright (c) 2002...2015
-- Daniel Wallner (jesus <at> opencores <dot> org)
-- Mike Johnson (mikej <at> fpgaarcade <dot> com)
-- Wolfgang Scherr (WoS <at> pin4 <dot> at>
-- Morten Leikvoll ()
--
-- 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(s), 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.
--
-- ----- IMPORTANT NOTES -----
--
-- Limitations:
-- 65C02 and 65C816 modes are incomplete (and definitely untested after all 6502 undoc fixes)
-- 65C02 supported : inc, dec, phx, plx, phy, ply
-- 65D02 missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8
-- Some interface signals behave incorrect
-- NMI interrupt handling not nice, needs further rework (to cycle-based encoding).
--
-- Usage:
-- The enable signal allows clock gating / throttling without using the ready signal.
-- Set it to constant '1' when using the Clk input as the CPU clock directly.
--
-- TAKE CARE you route the DO signal back to the DI signal while R_W_n='0',
-- otherwise some undocumented opcodes won't work correctly.
-- EXAMPLE:
-- CPU : entity work.T65
-- port map (
-- R_W_n => cpu_rwn_s,
-- [....all other ports....]
-- DI => cpu_din_s,
-- DO => cpu_dout_s
-- );
-- cpu_din_s <= cpu_dout_s when cpu_rwn_s='0' else
-- [....other sources from peripherals and memories...]
--
-- ----- IMPORTANT NOTES -----
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T65_Pack.all;
entity T65 is
port(
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
Res_n : in std_logic;
Enable : in std_logic;
Clk : in std_logic;
Rdy : in std_logic;
Abort_n : in std_logic;
IRQ_n : in std_logic;
NMI_n : in std_logic;
SO_n : in std_logic;
R_W_n : out std_logic;
Sync : out std_logic;
EF : out std_logic;
MF : out std_logic;
XF : out std_logic;
ML_n : out std_logic;
VP_n : out std_logic;
VDA : out std_logic;
VPA : out std_logic;
A : out std_logic_vector(23 downto 0);
DI : in std_logic_vector(7 downto 0);
DO : out std_logic_vector(7 downto 0);
DEBUG : out T_t65_dbg
);
end T65;
architecture rtl of T65 is
-- Registers
signal ABC, X, Y, D : std_logic_vector(15 downto 0);
signal P, AD, DL : std_logic_vector(7 downto 0) := x"00";
signal PwithB : std_logic_vector(7 downto 0);--ML:New way to push P with correct B state to stack
signal BAH : std_logic_vector(7 downto 0);
signal BAL : std_logic_vector(8 downto 0);
signal PBR : std_logic_vector(7 downto 0);
signal DBR : std_logic_vector(7 downto 0);
signal PC : unsigned(15 downto 0);
signal S : unsigned(15 downto 0);
signal EF_i : std_logic;
signal MF_i : std_logic;
signal XF_i : std_logic;
signal IR : std_logic_vector(7 downto 0);
signal MCycle : std_logic_vector(2 downto 0);
signal Mode_r : std_logic_vector(1 downto 0);
signal ALU_Op_r : T_ALU_Op;
signal Write_Data_r : T_Write_Data;
signal Set_Addr_To_r : T_Set_Addr_To;
signal PCAdder : unsigned(8 downto 0);
signal RstCycle : std_logic;
signal IRQCycle : std_logic;
signal NMICycle : std_logic;
signal SO_n_o : std_logic;
signal IRQ_n_o : std_logic;
signal NMI_n_o : std_logic;
signal NMIAct : std_logic;
signal Break : std_logic;
-- ALU signals
signal BusA : std_logic_vector(7 downto 0);
signal BusA_r : std_logic_vector(7 downto 0);
signal BusB : std_logic_vector(7 downto 0);
signal BusB_r : std_logic_vector(7 downto 0);
signal ALU_Q : std_logic_vector(7 downto 0);
signal P_Out : std_logic_vector(7 downto 0);
-- Micro code outputs
signal LCycle : std_logic_vector(2 downto 0);
signal ALU_Op : T_ALU_Op;
signal Set_BusA_To : T_Set_BusA_To;
signal Set_Addr_To : T_Set_Addr_To;
signal Write_Data : T_Write_Data;
signal Jump : std_logic_vector(1 downto 0);
signal BAAdd : std_logic_vector(1 downto 0);
signal BreakAtNA : std_logic;
signal ADAdd : std_logic;
signal AddY : std_logic;
signal PCAdd : std_logic;
signal Inc_S : std_logic;
signal Dec_S : std_logic;
signal LDA : std_logic;
signal LDP : std_logic;
signal LDX : std_logic;
signal LDY : std_logic;
signal LDS : std_logic;
signal LDDI : std_logic;
signal LDALU : std_logic;
signal LDAD : std_logic;
signal LDBAL : std_logic;
signal LDBAH : std_logic;
signal SaveP : std_logic;
signal Write : std_logic;
signal Res_n_i : std_logic;
signal Res_n_d : std_logic;
signal really_rdy : std_logic;
signal WRn_i : std_logic;
signal NMI_entered : std_logic;
begin
-- gate Rdy with read/write to make an "OK, it's really OK to stop the processor
really_rdy <= Rdy or not(WRn_i);
Sync <= '1' when MCycle = "000" else '0';
EF <= EF_i;
MF <= MF_i;
XF <= XF_i;
R_W_n <= WRn_i;
ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1';
VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1';
VDA <= '1' when Set_Addr_To_r /= Set_Addr_To_PBR else '0';
VPA <= '1' when Jump(1) = '0' else '0';
-- debugging signals
DEBUG.I <= IR;
DEBUG.A <= ABC(7 downto 0);
DEBUG.X <= X(7 downto 0);
DEBUG.Y <= Y(7 downto 0);
DEBUG.S <= std_logic_vector(S(7 downto 0));
DEBUG.P <= P;
mcode : entity work.T65_MCode
port map(
--inputs
Mode => Mode_r,
IR => IR,
MCycle => MCycle,
P => P,
--outputs
LCycle => LCycle,
ALU_Op => ALU_Op,
Set_BusA_To => Set_BusA_To,
Set_Addr_To => Set_Addr_To,
Write_Data => Write_Data,
Jump => Jump,
BAAdd => BAAdd,
BreakAtNA => BreakAtNA,
ADAdd => ADAdd,
AddY => AddY,
PCAdd => PCAdd,
Inc_S => Inc_S,
Dec_S => Dec_S,
LDA => LDA,
LDP => LDP,
LDX => LDX,
LDY => LDY,
LDS => LDS,
LDDI => LDDI,
LDALU => LDALU,
LDAD => LDAD,
LDBAL => LDBAL,
LDBAH => LDBAH,
SaveP => SaveP,
Write => Write
);
alu : entity work.T65_ALU
port map(
Mode => Mode_r,
Op => ALU_Op_r,
BusA => BusA_r,
BusB => BusB,
P_In => P,
P_Out => P_Out,
Q => ALU_Q
);
-- the 65xx design requires at least two clock cycles before
-- starting its reset sequence (according to datasheet)
process (Res_n_i, Clk)
begin
if Res_n = '0' then
Res_n_i <= '0';
Res_n_d <= '0';
elsif Clk'event and Clk = '1' then
Res_n_i <= Res_n_d;
Res_n_d <= '1';
end if;
end process;
process (Res_n_i, Clk)
begin
if Res_n_i = '0' then
PC <= (others => '0'); -- Program Counter
IR <= "00000000";
S <= (others => '0'); -- Dummy
D <= (others => '0');
PBR <= (others => '0');
DBR <= (others => '0');
Mode_r <= (others => '0');
ALU_Op_r <= ALU_OP_BIT;
Write_Data_r <= Write_Data_DL;
Set_Addr_To_r <= Set_Addr_To_PBR;
WRn_i <= '1';
EF_i <= '1';
MF_i <= '1';
XF_i <= '1';
elsif Clk'event and Clk = '1' then
if (Enable = '1') then
if (really_rdy = '1') then
WRn_i <= not Write or RstCycle;
D <= (others => '1'); -- Dummy
PBR <= (others => '1'); -- Dummy
DBR <= (others => '1'); -- Dummy
EF_i <= '0'; -- Dummy
MF_i <= '0'; -- Dummy
XF_i <= '0'; -- Dummy
if MCycle = "000" then
Mode_r <= Mode;
if IRQCycle = '0' and NMICycle = '0' then
PC <= PC + 1;
end if;
if IRQCycle = '1' or NMICycle = '1' then
IR <= "00000000";
else
IR <= DI;
end if;
if LDS = '1' then -- LAS won't work properly if not limited to machine cycle 0
S(7 downto 0) <= unsigned(ALU_Q);
end if;
end if;
ALU_Op_r <= ALU_Op;
Write_Data_r <= Write_Data;
if Break = '1' then
Set_Addr_To_r <= Set_Addr_To_PBR;
else
Set_Addr_To_r <= Set_Addr_To;
end if;
if Inc_S = '1' then
S <= S + 1;
end if;
if Dec_S = '1' and RstCycle = '0' then
S <= S - 1;
end if;
if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then
PC <= PC + 1;
end if;
--
-- jump control logic
--
case Jump is
when "01" =>
PC <= PC + 1;
when "10" =>
PC <= unsigned(DI & DL);
when "11" =>
if PCAdder(8) = '1' then
if DL(7) = '0' then
PC(15 downto 8) <= PC(15 downto 8) + 1;
else
PC(15 downto 8) <= PC(15 downto 8) - 1;
end if;
end if;
PC(7 downto 0) <= PCAdder(7 downto 0);
when others => null;
end case;
end if;
end if;
end if;
end process;
PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1'
else "0" & PC(7 downto 0);
process (Res_n_i, Clk)
variable tmpP:std_logic_vector(7 downto 0);--Lets try to handle loading P at mcycle=0 and set/clk flags at same cycle
begin
if Res_n_i = '0' then
P <= x"00"; -- ensure we have nothing set on reset
elsif Clk'event and Clk = '1' then
tmpP:=P;
if (Enable = '1') then
if (really_rdy = '1') then
if MCycle = "000" then
if LDA = '1' then
ABC(7 downto 0) <= ALU_Q;
end if;
if LDX = '1' then
X(7 downto 0) <= ALU_Q;
end if;
if LDY = '1' then
Y(7 downto 0) <= ALU_Q;
end if;
if (LDA or LDX or LDY) = '1' then
tmpP:=P_Out;
end if;
end if;
if SaveP = '1' then
tmpP:=P_Out;
end if;
if LDP = '1' then
tmpP:=ALU_Q;
end if;
if IR(4 downto 0) = "11000" then
case IR(7 downto 5) is
when "000" =>--0x18(clc)
tmpP(Flag_C) := '0';
when "001" =>--0x38(sec)
tmpP(Flag_C) := '1';
when "010" =>--0x58(cli)
tmpP(Flag_I) := '0';
when "011" =>--0x78(sei)
tmpP(Flag_I) := '1';
when "101" =>--0xb8(clv)
tmpP(Flag_V) := '0';
when "110" =>--0xd8(cld)
tmpP(Flag_D) := '0';
when "111" =>--0xf8(sed)
tmpP(Flag_D) := '1';
when others =>
end case;
end if;
tmpP(Flag_B) := '1';
if IR = "00000000" and MCycle = "100" and RstCycle = '0' then
--This should happen after P has been pushed to stack
tmpP(Flag_I) := '1';
end if;
if SO_n_o = '1' and SO_n = '0' then
tmpP(Flag_V) := '1';
end if;
if RstCycle = '1' then
tmpP(Flag_I) := '0';
tmpP(Flag_D) := '0';
end if;
tmpP(Flag_1) := '1';
P<=tmpP;--new way
SO_n_o <= SO_n;
if IR(4 downto 0)/="10000" or Jump/="01" then -- delay interrupts during branches (checked with Lorenz test and real 6510), not best way yet, though - but works...
IRQ_n_o <= IRQ_n;
end if;
end if;
-- detect nmi even if not rdy
if IR(4 downto 0)/="10000" or Jump/="01" then -- delay interrupts during branches (checked with Lorenz test and real 6510) not best way yet, though - but works...
NMI_n_o <= NMI_n;
end if;
end if;
end if;
end process;
---------------------------------------------------------------------------
--
-- Buses
--
---------------------------------------------------------------------------
process (Res_n_i, Clk)
begin
if Res_n_i = '0' then
BusA_r <= (others => '0');
BusB <= (others => '0');
BusB_r <= (others => '0');
AD <= (others => '0');
BAL <= (others => '0');
BAH <= (others => '0');
DL <= (others => '0');
elsif Clk'event and Clk = '1' then
if (Enable = '1') then
NMI_entered <= '0';
if (really_rdy = '1') then
BusA_r <= BusA;
BusB <= DI;
-- not really nice, but no better way found yet !
if Set_Addr_To_r = Set_Addr_To_PBR or Set_Addr_To_r = Set_Addr_To_ZPG then
BusB_r <= std_logic_vector(unsigned(DI(7 downto 0)) + 1); -- required for SHA
end if;
case BAAdd is
when "01" =>
-- BA Inc
AD <= std_logic_vector(unsigned(AD) + 1);
BAL <= std_logic_vector(unsigned(BAL) + 1);
when "10" =>
-- BA Add
BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9));
when "11" =>
-- BA Adj
if BAL(8) = '1' then
BAH <= std_logic_vector(unsigned(BAH) + 1);
end if;
when others =>
end case;
-- modified to use Y register as well
if ADAdd = '1' then
if (AddY = '1') then
AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0)));
else
AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0)));
end if;
end if;
if IR = "00000000" then
BAL <= (others => '1');
BAH <= (others => '1');
if RstCycle = '1' then
BAL(2 downto 0) <= "100";
elsif NMICycle = '1' or (NMIAct = '1' and MCycle="100") or NMI_entered='1' then
BAL(2 downto 0) <= "010";
if MCycle="100" then
NMI_entered <= '1';
end if;
else
BAL(2 downto 0) <= "110";
end if;
if Set_addr_To_r = Set_Addr_To_BA then
BAL(0) <= '1';
end if;
end if;
if LDDI = '1' then
DL <= DI;
end if;
if LDALU = '1' then
DL <= ALU_Q;
end if;
if LDAD = '1' then
AD <= DI;
end if;
if LDBAL = '1' then
BAL(7 downto 0) <= DI;
end if;
if LDBAH = '1' then
BAH <= DI;
end if;
end if;
end if;
end if;
end process;
Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8));
with Set_BusA_To select
BusA <=
DI when Set_BusA_To_DI,
ABC(7 downto 0) when Set_BusA_To_ABC,
X(7 downto 0) when Set_BusA_To_X,
Y(7 downto 0) when Set_BusA_To_Y,
std_logic_vector(S(7 downto 0)) when Set_BusA_To_S,
P when Set_BusA_To_P,
ABC(7 downto 0) and DI when Set_BusA_To_DA,
(ABC(7 downto 0) or x"ee") and DI when Set_BusA_To_DAO,--ee for OAL instruction. constant may be different on other platforms.TODO:Move to generics
(ABC(7 downto 0) or x"ee") and DI and X(7 downto 0) when Set_BusA_To_DAX,--XAA, ee for OAL instruction. constant may be different on other platforms.TODO:Move to generics
ABC(7 downto 0) and X(7 downto 0) when Set_BusA_To_AAX,--SAX, SHA
(others => '-') when Set_BusA_To_DONTCARE;--Can probably remove this
with Set_Addr_To_r select
A <=
"0000000000000001" & std_logic_vector(S(7 downto 0)) when Set_Addr_To_SP,
DBR & "00000000" & AD when Set_Addr_To_ZPG,
"00000000" & BAH & BAL(7 downto 0) when Set_Addr_To_BA,
PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when Set_Addr_To_PBR;
-- This is the P that gets pushed on stack with correct B flag. I'm not sure if NMI also clears B, but I guess it does.
PwithB<=(P and x"ef") when (IRQCycle='1' or NMICycle='1') else P;
with Write_Data_r select
DO <=
DL when Write_Data_DL,
ABC(7 downto 0) when Write_Data_ABC,
X(7 downto 0) when Write_Data_X,
Y(7 downto 0) when Write_Data_Y,
std_logic_vector(S(7 downto 0)) when Write_Data_S,
PwithB when Write_Data_P,
std_logic_vector(PC(7 downto 0)) when Write_Data_PCL,
std_logic_vector(PC(15 downto 8)) when Write_Data_PCH,
ABC(7 downto 0) and X(7 downto 0) when Write_Data_AX,
ABC(7 downto 0) and X(7 downto 0) and BusB_r(7 downto 0) when Write_Data_AXB, -- no better way found yet...
X(7 downto 0) and BusB_r(7 downto 0) when Write_Data_XB, -- no better way found yet...
Y(7 downto 0) and BusB_r(7 downto 0) when Write_Data_YB, -- no better way found yet...
(others=>'-') when Write_Data_DONTCARE;--Can probably remove this
-------------------------------------------------------------------------
--
-- Main state machine
--
-------------------------------------------------------------------------
process (Res_n_i, Clk)
begin
if Res_n_i = '0' then
MCycle <= "001";
RstCycle <= '1';
IRQCycle <= '0';
NMICycle <= '0';
NMIAct <= '0';
elsif Clk'event and Clk = '1' then
if (Enable = '1') then
if (really_rdy = '1') then
if MCycle = LCycle or Break = '1' then
MCycle <= "000";
RstCycle <= '0';
IRQCycle <= '0';
NMICycle <= '0';
if NMIAct = '1' and IR/=x"00" then -- delay NMI further if we just executed a BRK
NMICycle <= '1';
NMIAct <= '0'; -- reset NMI edge detector if we start processing the NMI
elsif IRQ_n_o = '0' and P(Flag_I) = '0' then
IRQCycle <= '1';
end if;
else
MCycle <= std_logic_vector(unsigned(MCycle) + 1);
end if;
end if;
--detect NMI even if not rdy
if NMI_n_o = '1' and (NMI_n = '0' and (IR(4 downto 0)/="10000" or Jump/="01")) then -- branches have influence on NMI start (not best way yet, though - but works...)
NMIAct <= '1';
end if;
-- we entered NMI during BRK instruction
if NMI_entered='1' then
NMIAct <= '0';
end if;
end if;
end if;
end process;
end;

View File

@@ -0,0 +1,291 @@
-- ****
-- T65(b) core. In an effort to merge and maintain bug fixes ....
--
-- See list of changes in T65 top file (T65.vhd)...
--
-- ****
-- 65xx compatible microprocessor core
--
-- FPGAARCADE SVN: $Id: T65_ALU.vhd 1234 2015-02-28 20:14:50Z wolfgang.scherr $
--
-- Copyright (c) 2002...2015
-- Daniel Wallner (jesus <at> opencores <dot> org)
-- Mike Johnson (mikej <at> fpgaarcade <dot> com)
-- Wolfgang Scherr (WoS <at> pin4 <dot> at>
-- Morten Leikvoll ()
--
-- 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(s), 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.
--
-- Limitations :
-- See in T65 top file (T65.vhd)...
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.T65_Pack.all;
entity T65_ALU is
port(
Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
Op : in T_ALU_OP;
BusA : in std_logic_vector(7 downto 0);
BusB : in std_logic_vector(7 downto 0);
P_In : in std_logic_vector(7 downto 0);
P_Out : out std_logic_vector(7 downto 0);
Q : out std_logic_vector(7 downto 0)
);
end T65_ALU;
architecture rtl of T65_ALU is
-- AddSub variables (temporary signals)
signal ADC_Z : std_logic;
signal ADC_C : std_logic;
signal ADC_V : std_logic;
signal ADC_N : std_logic;
signal ADC_Q : std_logic_vector(7 downto 0);
signal SBC_Z : std_logic;
signal SBC_C : std_logic;
signal SBC_V : std_logic;
signal SBC_N : std_logic;
signal SBC_Q : std_logic_vector(7 downto 0);
signal SBX_Q : std_logic_vector(7 downto 0);
begin
process (P_In, BusA, BusB)
variable AL : unsigned(6 downto 0);
variable AH : unsigned(6 downto 0);
variable C : std_logic;
begin
AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7);
AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
-- pragma translate_off
if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
-- pragma translate_on
if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
ADC_Z <= '1';
else
ADC_Z <= '0';
end if;
if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then
AL(6 downto 1) := AL(6 downto 1) + 6;
end if;
C := AL(6) or AL(5);
AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
ADC_N <= AH(4);
ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7));
-- pragma translate_off
if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
-- pragma translate_on
if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then
AH(6 downto 1) := AH(6 downto 1) + 6;
end if;
ADC_C <= AH(6) or AH(5);
ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
end process;
process (Op, P_In, BusA, BusB)
variable AL : unsigned(6 downto 0);
variable AH : unsigned(5 downto 0);
variable C : std_logic;
variable CT : std_logic;
begin
CT:='0';
if( Op=ALU_OP_AND or --"0001" These OpCodes used to have LSB set
Op=ALU_OP_ADC or --"0011"
Op=ALU_OP_EQ2 or --"0101"
Op=ALU_OP_SBC or --"0111"
Op=ALU_OP_ROL or --"1001"
Op=ALU_OP_ROR or --"1011"
-- Op=ALU_OP_EQ3 or --"1101"
Op=ALU_OP_INC --"1111"
) then
CT:='1';
end if;
C := P_In(Flag_C) or not CT;--was: or not Op(0);
AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6);
AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6);
-- pragma translate_off
if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
if is_x(std_logic_vector(AH)) then AH := "000000"; end if;
-- pragma translate_on
if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
SBC_Z <= '1';
else
SBC_Z <= '0';
end if;
SBC_C <= not AH(5);
SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7));
SBC_N <= AH(4);
SBX_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
if P_In(Flag_D) = '1' then
if AL(5) = '1' then
AL(5 downto 1) := AL(5 downto 1) - 6;
end if;
AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6);
if AH(5) = '1' then
AH(5 downto 1) := AH(5 downto 1) - 6;
end if;
end if;
SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
end process;
process (Op, P_In, BusA, BusB,
ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q,
SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q)
variable Q_t : std_logic_vector(7 downto 0);
variable Q2_t : std_logic_vector(7 downto 0);
begin
-- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
-- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
P_Out <= P_In;
Q_t := BusA;
case Op is
when ALU_OP_OR=>
Q_t := BusA or BusB;
when ALU_OP_AND=>
Q_t := BusA and BusB;
when ALU_OP_EOR=>
Q_t := BusA xor BusB;
when ALU_OP_ADC=>
P_Out(Flag_V) <= ADC_V;
P_Out(Flag_C) <= ADC_C;
Q_t := ADC_Q;
when ALU_OP_CMP=>
P_Out(Flag_C) <= SBC_C;
when ALU_OP_SAX=>
P_Out(Flag_C) <= SBC_C;
Q_t := SBX_Q; -- undoc: subtract (A & X) - (immediate)
when ALU_OP_SBC=>
P_Out(Flag_V) <= SBC_V;
P_Out(Flag_C) <= SBC_C;
Q_t := SBC_Q; -- undoc: subtract (A & X) - (immediate), then decimal correction
when ALU_OP_ASL=>
Q_t := BusA(6 downto 0) & "0";
P_Out(Flag_C) <= BusA(7);
when ALU_OP_ROL=>
Q_t := BusA(6 downto 0) & P_In(Flag_C);
P_Out(Flag_C) <= BusA(7);
when ALU_OP_LSR=>
Q_t := "0" & BusA(7 downto 1);
P_Out(Flag_C) <= BusA(0);
when ALU_OP_ROR=>
Q_t := P_In(Flag_C) & BusA(7 downto 1);
P_Out(Flag_C) <= BusA(0);
when ALU_OP_ARR=>
Q_t := P_In(Flag_C) & (BusA(7 downto 1) and BusB(7 downto 1));
P_Out(Flag_V) <= Q_t(5) xor Q_t(6);
Q2_t := Q_t;
if P_In(Flag_D)='1' then
if (BusA(3 downto 0) and BusB(3 downto 0)) > "0100" then
Q2_t(3 downto 0) := std_logic_vector(unsigned(Q_t(3 downto 0)) + x"6");
end if;
if (BusA(7 downto 4) and BusB(7 downto 4)) > "0100" then
Q2_t(7 downto 4) := std_logic_vector(unsigned(Q_t(7 downto 4)) + x"6");
P_Out(Flag_C) <= '1';
else
P_Out(Flag_C) <= '0';
end if;
else
P_Out(Flag_C) <= Q_t(6);
end if;
when ALU_OP_BIT=>
P_Out(Flag_V) <= BusB(6);
when ALU_OP_DEC=>
Q_t := std_logic_vector(unsigned(BusA) - 1);
when ALU_OP_INC=>
Q_t := std_logic_vector(unsigned(BusA) + 1);
when others =>
null;
--EQ1,EQ2,EQ3 passes BusA to Q_t and P_in to P_out
end case;
case Op is
when ALU_OP_ADC=>
P_Out(Flag_N) <= ADC_N;
P_Out(Flag_Z) <= ADC_Z;
when ALU_OP_CMP|ALU_OP_SBC|ALU_OP_SAX=>
P_Out(Flag_N) <= SBC_N;
P_Out(Flag_Z) <= SBC_Z;
when ALU_OP_EQ1=>--dont touch P
when ALU_OP_BIT=>
P_Out(Flag_N) <= BusB(7);
if (BusA and BusB) = "00000000" then
P_Out(Flag_Z) <= '1';
else
P_Out(Flag_Z) <= '0';
end if;
when ALU_OP_ANC=>
P_Out(Flag_N) <= Q_t(7);
P_Out(Flag_C) <= Q_t(7);
if Q_t = "00000000" then
P_Out(Flag_Z) <= '1';
else
P_Out(Flag_Z) <= '0';
end if;
when others =>
P_Out(Flag_N) <= Q_t(7);
if Q_t = "00000000" then
P_Out(Flag_Z) <= '1';
else
P_Out(Flag_Z) <= '0';
end if;
end case;
if Op=ALU_OP_ARR then
-- handled above in ARR code
Q <= Q2_t;
else
Q <= Q_t;
end if;
end process;
end;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
-- ****
-- T65(b) core. In an effort to merge and maintain bug fixes ....
--
-- See list of changes in T65 top file (T65.vhd)...
--
-- ****
-- 65xx compatible microprocessor core
--
-- FPGAARCADE SVN: $Id: T65_Pack.vhd 1234 2015-02-28 20:14:50Z wolfgang.scherr $
--
-- Copyright (c) 2002...2015
-- Daniel Wallner (jesus <at> opencores <dot> org)
-- Mike Johnson (mikej <at> fpgaarcade <dot> com)
-- Wolfgang Scherr (WoS <at> pin4 <dot> at>
-- Morten Leikvoll ()
--
-- 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(s), 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.
--
-- Limitations :
-- See in T65 top file (T65.vhd)...
library IEEE;
use IEEE.std_logic_1164.all;
package T65_Pack is
constant Flag_C : integer := 0;
constant Flag_Z : integer := 1;
constant Flag_I : integer := 2;
constant Flag_D : integer := 3;
constant Flag_B : integer := 4;
constant Flag_1 : integer := 5;
constant Flag_V : integer := 6;
constant Flag_N : integer := 7;
subtype T_Lcycle is std_logic_vector(2 downto 0);
constant Cycle_sync :T_Lcycle:="000";
constant Cycle_1 :T_Lcycle:="001";
constant Cycle_2 :T_Lcycle:="010";
constant Cycle_3 :T_Lcycle:="011";
constant Cycle_4 :T_Lcycle:="100";
constant Cycle_5 :T_Lcycle:="101";
constant Cycle_6 :T_Lcycle:="110";
constant Cycle_7 :T_Lcycle:="111";
function CycleNext(c:T_Lcycle) return T_Lcycle;
type T_Set_BusA_To is
(
Set_BusA_To_DI,
Set_BusA_To_ABC,
Set_BusA_To_X,
Set_BusA_To_Y,
Set_BusA_To_S,
Set_BusA_To_P,
Set_BusA_To_DA,
Set_BusA_To_DAO,
Set_BusA_To_DAX,
Set_BusA_To_AAX,
Set_BusA_To_DONTCARE
);
type T_Set_Addr_To is
(
Set_Addr_To_SP,
Set_Addr_To_ZPG,
Set_Addr_To_PBR,
Set_Addr_To_BA
);
type T_Write_Data is
(
Write_Data_DL,
Write_Data_ABC,
Write_Data_X,
Write_Data_Y,
Write_Data_S,
Write_Data_P,
Write_Data_PCL,
Write_Data_PCH,
Write_Data_AX,
Write_Data_AXB,
Write_Data_XB,
Write_Data_YB,
Write_Data_DONTCARE
);
type T_ALU_OP is
(
ALU_OP_OR, --"0000"
ALU_OP_AND, --"0001"
ALU_OP_EOR, --"0010"
ALU_OP_ADC, --"0011"
ALU_OP_EQ1, --"0100" EQ1 does not change N,Z flags, EQ2/3 does.
ALU_OP_EQ2, --"0101" Not sure yet whats the difference between EQ2&3. They seem to do the same ALU op
ALU_OP_CMP, --"0110"
ALU_OP_SBC, --"0111"
ALU_OP_ASL, --"1000"
ALU_OP_ROL, --"1001"
ALU_OP_LSR, --"1010"
ALU_OP_ROR, --"1011"
ALU_OP_BIT, --"1100"
-- ALU_OP_EQ3, --"1101"
ALU_OP_DEC, --"1110"
ALU_OP_INC, --"1111"
ALU_OP_ARR,
ALU_OP_ANC,
ALU_OP_SAX,
ALU_OP_XAA
-- ALU_OP_UNDEF--"----"--may be replaced with any?
);
type T_t65_dbg is record
I : std_logic_vector(7 downto 0); -- instruction
A : std_logic_vector(7 downto 0); -- A reg
X : std_logic_vector(7 downto 0); -- X reg
Y : std_logic_vector(7 downto 0); -- Y reg
S : std_logic_vector(7 downto 0); -- stack pointer
P : std_logic_vector(7 downto 0); -- processor flags
end record;
end;
package body T65_Pack is
function CycleNext(c:T_Lcycle) return T_Lcycle is
begin
case(c) is
when Cycle_sync=>
return Cycle_1;
when Cycle_1=>
return Cycle_2;
when Cycle_2=>
return Cycle_3;
when Cycle_3=>
return Cycle_4;
when Cycle_4=>
return Cycle_5;
when Cycle_5=>
return Cycle_6;
when Cycle_6=>
return Cycle_7;
when Cycle_7=>
return Cycle_sync;
when others=>
return Cycle_sync;
end case;
end CycleNext;
end T65_Pack;

View File

@@ -0,0 +1,35 @@
# ================================================================================
#
# Build ID Verilog Module Script
# Jeff Wiencrot - 8/1/2011
#
# Generates a Verilog module that contains a timestamp,
# from the current build. These values are available from the build_date, build_time,
# physical_address, and host_name output ports of the build_id module in the build_id.v
# Verilog source file.
#
# ================================================================================
proc generateBuildID_Verilog {} {
# Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html)
set buildDate [ clock format [ clock seconds ] -format %y%m%d ]
set buildTime [ clock format [ clock seconds ] -format %H%M%S ]
# Create a Verilog file for output
set outputFileName "rtl/build_id.v"
set outputFile [open $outputFileName "w"]
# Output the Verilog source
puts $outputFile "`define BUILD_DATE \"$buildDate\""
puts $outputFile "`define BUILD_TIME \"$buildTime\""
close $outputFile
# Send confirmation message to the Messages window
post_message "Generated build identification Verilog module: [pwd]/$outputFileName"
post_message "Date: $buildDate"
post_message "Time: $buildTime"
}
# Comment out this line to prevent the process from automatically executing when the file is sourced:
generateBuildID_Verilog

View File

@@ -0,0 +1,2 @@
`define BUILD_DATE "180123"
`define BUILD_TIME "014157"

View File

@@ -0,0 +1,454 @@
//
//
// Copyright (c) 2012-2013 Ludvig Strigeus
// Copyright (c) 2017 Sorgelig
//
// This program is GPL Licensed. See COPYING for the full license.
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
`define BITS_TO_FIT(N) ( \
N <= 2 ? 0 : \
N <= 4 ? 1 : \
N <= 8 ? 2 : \
N <= 16 ? 3 : \
N <= 32 ? 4 : \
N <= 64 ? 5 : \
N <= 128 ? 6 : \
N <= 256 ? 7 : \
N <= 512 ? 8 : \
N <=1024 ? 9 : 10 )
module hq2x_in #(parameter LENGTH, parameter DWIDTH)
(
input clk,
input [AWIDTH:0] rdaddr,
input rdbuf,
output[DWIDTH:0] q,
input [AWIDTH:0] wraddr,
input wrbuf,
input [DWIDTH:0] data,
input wren
);
localparam AWIDTH = `BITS_TO_FIT(LENGTH);
wire [DWIDTH:0] out[2];
assign q = out[rdbuf];
hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]);
hq2x_buf #(.NUMWORDS(LENGTH), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]);
endmodule
module hq2x_out #(parameter LENGTH, parameter DWIDTH)
(
input clk,
input [AWIDTH:0] rdaddr,
input [1:0] rdbuf,
output[DWIDTH:0] q,
input [AWIDTH:0] wraddr,
input [1:0] wrbuf,
input [DWIDTH:0] data,
input wren
);
localparam AWIDTH = `BITS_TO_FIT(LENGTH*2);
wire [DWIDTH:0] out[4];
assign q = out[rdbuf];
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf0(clk,data,rdaddr,wraddr,wren && (wrbuf == 0),out[0]);
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf1(clk,data,rdaddr,wraddr,wren && (wrbuf == 1),out[1]);
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf2(clk,data,rdaddr,wraddr,wren && (wrbuf == 2),out[2]);
hq2x_buf #(.NUMWORDS(LENGTH*2), .AWIDTH(AWIDTH), .DWIDTH(DWIDTH)) buf3(clk,data,rdaddr,wraddr,wren && (wrbuf == 3),out[3]);
endmodule
module hq2x_buf #(parameter NUMWORDS, parameter AWIDTH, parameter DWIDTH)
(
input clock,
input [DWIDTH:0] data,
input [AWIDTH:0] rdaddress,
input [AWIDTH:0] wraddress,
input wren,
output [DWIDTH:0] q
);
altsyncram altsyncram_component (
.address_a (wraddress),
.clock0 (clock),
.data_a (data),
.wren_a (wren),
.address_b (rdaddress),
.q_b(q),
.aclr0 (1'b0),
.aclr1 (1'b0),
.addressstall_a (1'b0),
.addressstall_b (1'b0),
.byteena_a (1'b1),
.byteena_b (1'b1),
.clock1 (1'b1),
.clocken0 (1'b1),
.clocken1 (1'b1),
.clocken2 (1'b1),
.clocken3 (1'b1),
.data_b ({(DWIDTH+1){1'b1}}),
.eccstatus (),
.q_a (),
.rden_a (1'b1),
.rden_b (1'b1),
.wren_b (1'b0));
defparam
altsyncram_component.address_aclr_b = "NONE",
altsyncram_component.address_reg_b = "CLOCK0",
altsyncram_component.clock_enable_input_a = "BYPASS",
altsyncram_component.clock_enable_input_b = "BYPASS",
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.intended_device_family = "Cyclone III",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = NUMWORDS,
altsyncram_component.numwords_b = NUMWORDS,
altsyncram_component.operation_mode = "DUAL_PORT",
altsyncram_component.outdata_aclr_b = "NONE",
altsyncram_component.outdata_reg_b = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "FALSE",
altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE",
altsyncram_component.widthad_a = AWIDTH+1,
altsyncram_component.widthad_b = AWIDTH+1,
altsyncram_component.width_a = DWIDTH+1,
altsyncram_component.width_b = DWIDTH+1,
altsyncram_component.width_byteena_a = 1;
endmodule
////////////////////////////////////////////////////////////////////////////////////////////////////////
module DiffCheck
(
input [17:0] rgb1,
input [17:0] rgb2,
output result
);
wire [5:0] r = rgb1[5:1] - rgb2[5:1];
wire [5:0] g = rgb1[11:7] - rgb2[11:7];
wire [5:0] b = rgb1[17:13] - rgb2[17:13];
wire [6:0] t = $signed(r) + $signed(b);
wire [6:0] gx = {g[5], g};
wire [7:0] y = $signed(t) + $signed(gx);
wire [6:0] u = $signed(r) - $signed(b);
wire [7:0] v = $signed({g, 1'b0}) - $signed(t);
// if y is inside (-24..24)
wire y_inside = (y < 8'h18 || y >= 8'he8);
// if u is inside (-4, 4)
wire u_inside = (u < 7'h4 || u >= 7'h7c);
// if v is inside (-6, 6)
wire v_inside = (v < 8'h6 || v >= 8'hfA);
assign result = !(y_inside && u_inside && v_inside);
endmodule
module InnerBlend
(
input [8:0] Op,
input [5:0] A,
input [5:0] B,
input [5:0] C,
output [5:0] O
);
function [8:0] mul6x3;
input [5:0] op1;
input [2:0] op2;
begin
mul6x3 = 9'd0;
if(op2[0]) mul6x3 = mul6x3 + op1;
if(op2[1]) mul6x3 = mul6x3 + {op1, 1'b0};
if(op2[2]) mul6x3 = mul6x3 + {op1, 2'b00};
end
endfunction
wire OpOnes = Op[4];
wire [8:0] Amul = mul6x3(A, Op[7:5]);
wire [8:0] Bmul = mul6x3(B, {Op[3:2], 1'b0});
wire [8:0] Cmul = mul6x3(C, {Op[1:0], 1'b0});
wire [8:0] At = Amul;
wire [8:0] Bt = (OpOnes == 0) ? Bmul : {3'b0, B};
wire [8:0] Ct = (OpOnes == 0) ? Cmul : {3'b0, C};
wire [9:0] Res = {At, 1'b0} + Bt + Ct;
assign O = Op[8] ? A : Res[9:4];
endmodule
module Blend
(
input [5:0] rule,
input disable_hq2x,
input [17:0] E,
input [17:0] A,
input [17:0] B,
input [17:0] D,
input [17:0] F,
input [17:0] H,
output [17:0] Result
);
reg [1:0] input_ctrl;
reg [8:0] op;
localparam BLEND0 = 9'b1_xxx_x_xx_xx; // 0: A
localparam BLEND1 = 9'b0_110_0_10_00; // 1: (A * 12 + B * 4) >> 4
localparam BLEND2 = 9'b0_100_0_10_10; // 2: (A * 8 + B * 4 + C * 4) >> 4
localparam BLEND3 = 9'b0_101_0_10_01; // 3: (A * 10 + B * 4 + C * 2) >> 4
localparam BLEND4 = 9'b0_110_0_01_01; // 4: (A * 12 + B * 2 + C * 2) >> 4
localparam BLEND5 = 9'b0_010_0_11_11; // 5: (A * 4 + (B + C) * 6) >> 4
localparam BLEND6 = 9'b0_111_1_xx_xx; // 6: (A * 14 + B + C) >> 4
localparam AB = 2'b00;
localparam AD = 2'b01;
localparam DB = 2'b10;
localparam BD = 2'b11;
wire is_diff;
DiffCheck diff_checker(rule[1] ? B : H, rule[0] ? D : F, is_diff);
always @* begin
case({!is_diff, rule[5:2]})
1,17: {op, input_ctrl} = {BLEND1, AB};
2,18: {op, input_ctrl} = {BLEND1, DB};
3,19: {op, input_ctrl} = {BLEND1, BD};
4,20: {op, input_ctrl} = {BLEND2, DB};
5,21: {op, input_ctrl} = {BLEND2, AB};
6,22: {op, input_ctrl} = {BLEND2, AD};
8: {op, input_ctrl} = {BLEND0, 2'bxx};
9: {op, input_ctrl} = {BLEND0, 2'bxx};
10: {op, input_ctrl} = {BLEND0, 2'bxx};
11: {op, input_ctrl} = {BLEND1, AB};
12: {op, input_ctrl} = {BLEND1, AB};
13: {op, input_ctrl} = {BLEND1, AB};
14: {op, input_ctrl} = {BLEND1, DB};
15: {op, input_ctrl} = {BLEND1, BD};
24: {op, input_ctrl} = {BLEND2, DB};
25: {op, input_ctrl} = {BLEND5, DB};
26: {op, input_ctrl} = {BLEND6, DB};
27: {op, input_ctrl} = {BLEND2, DB};
28: {op, input_ctrl} = {BLEND4, DB};
29: {op, input_ctrl} = {BLEND5, DB};
30: {op, input_ctrl} = {BLEND3, BD};
31: {op, input_ctrl} = {BLEND3, DB};
default: {op, input_ctrl} = 11'bx;
endcase
// Setting op[8] effectively disables HQ2X because blend will always return E.
if (disable_hq2x) op[8] = 1;
end
// Generate inputs to the inner blender. Valid combinations.
// 00: E A B
// 01: E A D
// 10: E D B
// 11: E B D
wire [17:0] Input1 = E;
wire [17:0] Input2 = !input_ctrl[1] ? A :
!input_ctrl[0] ? D : B;
wire [17:0] Input3 = !input_ctrl[0] ? B : D;
InnerBlend inner_blend1(op, Input1[5:0], Input2[5:0], Input3[5:0], Result[5:0]);
InnerBlend inner_blend2(op, Input1[11:6], Input2[11:6], Input3[11:6], Result[11:6]);
InnerBlend inner_blend3(op, Input1[17:12], Input2[17:12], Input3[17:12], Result[17:12]);
endmodule
////////////////////////////////////////////////////////////////////////////////////////////////////
module Hq2x #(parameter LENGTH, parameter HALF_DEPTH)
(
input clk,
input ce_x4,
input [DWIDTH:0] inputpixel,
input mono,
input disable_hq2x,
input reset_frame,
input reset_line,
input [1:0] read_y,
input [AWIDTH+1:0] read_x,
output [DWIDTH:0] outpixel
);
localparam AWIDTH = `BITS_TO_FIT(LENGTH);
localparam DWIDTH = HALF_DEPTH ? 8 : 17;
wire [5:0] hqTable[256] = '{
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39,
19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 35, 35, 23, 15, 7, 35,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43,
19, 19, 26, 58, 19, 19, 26, 58, 23, 15, 51, 35, 23, 15, 7, 43,
19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 35, 35, 23, 61, 51, 35,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35,
19, 19, 26, 11, 19, 19, 26, 11, 23, 61, 7, 35, 23, 61, 7, 43,
19, 19, 26, 11, 19, 19, 26, 58, 23, 15, 51, 35, 23, 61, 7, 43,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 47, 35, 23, 15, 55, 39,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 35,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 55, 39, 23, 15, 51, 43,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 39, 23, 15, 7, 43,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 51, 39,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 35,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 51, 35, 23, 15, 7, 43,
19, 19, 26, 11, 19, 19, 26, 11, 23, 15, 7, 35, 23, 15, 7, 43
};
reg [17:0] Prev0, Prev1, Prev2, Curr0, Curr1, Next0, Next1, Next2;
reg [17:0] A, B, D, F, G, H;
reg [7:0] pattern, nextpatt;
reg [1:0] i;
reg [7:0] y;
wire curbuf = y[0];
reg prevbuf = 0;
wire iobuf = !curbuf;
wire diff0, diff1;
DiffCheck diffcheck0(Curr1, (i == 0) ? Prev0 : (i == 1) ? Curr0 : (i == 2) ? Prev2 : Next1, diff0);
DiffCheck diffcheck1(Curr1, (i == 0) ? Prev1 : (i == 1) ? Next0 : (i == 2) ? Curr2 : Next2, diff1);
wire [7:0] new_pattern = {diff1, diff0, pattern[7:2]};
wire [17:0] X = (i == 0) ? A : (i == 1) ? Prev1 : (i == 2) ? Next1 : G;
wire [17:0] blend_result;
Blend blender(hqTable[nextpatt], disable_hq2x, Curr0, X, B, D, F, H, blend_result);
reg Curr2_addr1;
reg [AWIDTH:0] Curr2_addr2;
wire [17:0] Curr2 = HALF_DEPTH ? h2rgb(Curr2tmp) : Curr2tmp;
wire [DWIDTH:0] Curr2tmp;
reg [AWIDTH:0] wrin_addr2;
reg [DWIDTH:0] wrpix;
reg wrin_en;
function [17:0] h2rgb;
input [8:0] v;
begin
h2rgb = mono ? {v[5:3],v[2:0], v[5:3],v[2:0], v[5:3],v[2:0]} : {v[8:6],v[8:6],v[5:3],v[5:3],v[2:0],v[2:0]};
end
endfunction
function [8:0] rgb2h;
input [17:0] v;
begin
rgb2h = mono ? {3'b000, v[17:15], v[14:12]} : {v[17:15], v[11:9], v[5:3]};
end
endfunction
hq2x_in #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_in
(
.clk(clk),
.rdaddr(Curr2_addr2),
.rdbuf(Curr2_addr1),
.q(Curr2tmp),
.wraddr(wrin_addr2),
.wrbuf(iobuf),
.data(wrpix),
.wren(wrin_en)
);
reg [1:0] wrout_addr1;
reg [AWIDTH+1:0] wrout_addr2;
reg wrout_en;
reg [DWIDTH:0] wrdata;
hq2x_out #(.LENGTH(LENGTH), .DWIDTH(DWIDTH)) hq2x_out
(
.clk(clk),
.rdaddr(read_x),
.rdbuf(read_y),
.q(outpixel),
.wraddr(wrout_addr2),
.wrbuf(wrout_addr1),
.data(wrdata),
.wren(wrout_en)
);
always @(posedge clk) begin
reg [AWIDTH:0] offs;
reg old_reset_line;
reg old_reset_frame;
wrout_en <= 0;
wrin_en <= 0;
if(ce_x4) begin
pattern <= new_pattern;
if(~&offs) begin
if (i == 0) begin
Curr2_addr1 <= prevbuf;
Curr2_addr2 <= offs;
end
if (i == 1) begin
Prev2 <= Curr2;
Curr2_addr1 <= curbuf;
Curr2_addr2 <= offs;
end
if (i == 2) begin
Next2 <= HALF_DEPTH ? h2rgb(inputpixel) : inputpixel;
wrpix <= inputpixel;
wrin_addr2 <= offs;
wrin_en <= 1;
end
if (i == 3) begin
offs <= offs + 1'd1;
end
if(HALF_DEPTH) wrdata <= rgb2h(blend_result);
else wrdata <= blend_result;
wrout_addr1 <= {curbuf, i[1]};
wrout_addr2 <= {offs, i[1]^i[0]};
wrout_en <= 1;
end
if(i==3) begin
nextpatt <= {new_pattern[7:6], new_pattern[3], new_pattern[5], new_pattern[2], new_pattern[4], new_pattern[1:0]};
{A, G} <= {Prev0, Next0};
{B, F, H, D} <= {Prev1, Curr2, Next1, Curr0};
{Prev0, Prev1} <= {Prev1, Prev2};
{Curr0, Curr1} <= {Curr1, Curr2};
{Next0, Next1} <= {Next1, Next2};
end else begin
nextpatt <= {nextpatt[5], nextpatt[3], nextpatt[0], nextpatt[6], nextpatt[1], nextpatt[7], nextpatt[4], nextpatt[2]};
{B, F, H, D} <= {F, H, D, B};
end
i <= i + 1'b1;
if(old_reset_line && ~reset_line) begin
old_reset_frame <= reset_frame;
offs <= 0;
i <= 0;
y <= y + 1'd1;
prevbuf <= curbuf;
if(old_reset_frame & ~reset_frame) begin
y <= 0;
prevbuf <= 0;
end
end
old_reset_line <= reset_line;
end
end
endmodule // Hq2x

View File

@@ -0,0 +1,186 @@
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use ieee.std_logic_unsigned.all;
entity keyboard is
port (
clk : in std_logic;
rst_n : in std_logic;
ps2_clk : in std_logic;
ps2_data : in std_logic;
col : out std_logic_vector(3 downto 0);
row : in std_logic_vector(13 downto 0);
break : out std_logic;
turbo : out std_logic_vector(1 downto 0)
;scanSW : buffer std_logic --q
);
end entity;
architecture rtl of keyboard is
type key_matrix is array(0 to 13) of std_logic_vector(3 downto 0);
signal keys : key_matrix;
signal release : std_logic;
signal extended : std_logic;
signal keyb_data : std_logic_vector(7 downto 0);
signal keyb_valid : std_logic;
signal keyb_error : std_logic;
begin
ps2 : entity work.ps2_intf port map (
CLK => clk,
nRESET => rst_n,
PS2_CLK => ps2_clk,
PS2_DATA => ps2_data,
DATA => keyb_data,
VALID => keyb_valid,
error => keyb_error
);
process(keys, row)
variable i : integer;
variable tmp : std_logic_vector(3 downto 0);
begin
tmp := "1111";
for i in 0 to 13 loop
if (row(i) = '0') then
tmp := tmp and keys(i);
end if;
end loop;
col <= tmp xor "1111";
end process;
process(clk, rst_n)
begin
if rst_n = '0' then
release <= '0';
extended <= '0';
turbo <= "00"; -- 1MHz
break <= '1';
keys( 0) <= (others => '1');
keys( 1) <= (others => '1');
keys( 2) <= (others => '1');
keys( 3) <= (others => '1');
keys( 4) <= (others => '1');
keys( 5) <= (others => '1');
keys( 6) <= (others => '1');
keys( 7) <= (others => '1');
keys( 8) <= (others => '1');
keys( 9) <= (others => '1');
keys(10) <= (others => '1');
keys(11) <= (others => '1');
keys(12) <= (others => '1');
keys(13) <= (others => '1');
elsif rising_edge(clk) then
if keyb_valid = '1' then
if keyb_data = X"e0" then
extended <= '1';
elsif keyb_data = X"f0" then
release <= '1';
else
release <= '0';
extended <= '0';
case keyb_data is
-- Special keys
when X"05" => turbo <= "00"; -- F1 (1MHz)
when X"06" => turbo <= "01"; -- F2 (2MMz)
when X"04" => turbo <= "10"; -- F3 (4MHz)
when X"0C" => turbo <= "11"; -- F4 (8MHz)
when X"09" => break <= release; -- F10 (BREAK)
-- Key Matrix
when X"74" => keys( 0)(0) <= release; -- RIGHT
when X"69" => keys( 0)(1) <= release; -- END (COPY)
-- keys( 0)(2) -- NC
when X"29" => keys( 0)(3) <= release; -- SPACE
when X"6B" => keys( 1)(0) <= release; -- LEFT
when X"72" => keys( 1)(1) <= release; -- DOWN
when X"5B" => keys( 1)(1) <= release; -- ]
when X"5A" => keys( 1)(2) <= release; -- RETURN
when X"66" => keys( 1)(3) <= release; -- BACKSPACE (DELETE)
when X"4E" => keys( 2)(0) <= release; -- -
when X"75" => keys( 2)(1) <= release; -- UP
when X"54" => keys( 2)(1) <= release; -- [
when X"52" => keys( 2)(2) <= release; -- ' full colon substitute
-- keys( 2)(3) -- NC
when X"45" => keys( 3)(0) <= release; -- 0
when X"4D" => keys( 3)(1) <= release; -- P
when X"4C" => keys( 3)(2) <= release; -- ;
when X"4A" => keys( 3)(3) <= release; -- /
when X"46" => keys( 4)(0) <= release; -- 9
when X"44" => keys( 4)(1) <= release; -- O
when X"4B" => keys( 4)(2) <= release; -- L
when X"49" => keys( 4)(3) <= release; -- .
when X"3E" => keys( 5)(0) <= release; -- 8
when X"43" => keys( 5)(1) <= release; -- I
when X"42" => keys( 5)(2) <= release; -- K
when X"41" => keys( 5)(3) <= release; -- ,
when X"3D" => keys( 6)(0) <= release; -- 7
when X"3C" => keys( 6)(1) <= release; -- U
when X"3B" => keys( 6)(2) <= release; -- J
when X"3A" => keys( 6)(3) <= release; -- M
when X"36" => keys( 7)(0) <= release; -- 6
when X"35" => keys( 7)(1) <= release; -- Y
when X"33" => keys( 7)(2) <= release; -- H
when X"31" => keys( 7)(3) <= release; -- N
when X"2E" => keys( 8)(0) <= release; -- 5
when X"2C" => keys( 8)(1) <= release; -- T
when X"34" => keys( 8)(2) <= release; -- G
when X"32" => keys( 8)(3) <= release; -- B
when X"25" => keys( 9)(0) <= release; -- 4
when X"2D" => keys( 9)(1) <= release; -- R
when X"2B" => keys( 9)(2) <= release; -- F
when X"2A" => keys( 9)(3) <= release; -- V
when X"26" => keys(10)(0) <= release; -- 3
when X"24" => keys(10)(1) <= release; -- E
when X"23" => keys(10)(2) <= release; -- D
when X"21" => keys(10)(3) <= release; -- C
when X"1E" => keys(11)(0) <= release; -- 2
when X"1D" => keys(11)(1) <= release; -- W
when X"1B" => keys(11)(2) <= release; -- S
when X"22" => keys(11)(3) <= release; -- X
when X"16" => keys(12)(0) <= release; -- 1
when X"15" => keys(12)(1) <= release; -- Q
when X"1C" => keys(12)(2) <= release; -- A
when X"1A" => keys(12)(3) <= release; -- Z
when X"76" => keys(13)(0) <= release; -- ESCAPE
when X"58" => keys(13)(1) <= release; -- CAPS LOCK
when X"14" => keys(13)(2) <= release; -- LEFT/RIGHT CTRL (CTRL)
when X"7D" => scanSW <= '1'; -- pgUP (VGA)
when X"7A" => scanSW <= '0'; -- pgDN (RGB)
when X"12" | X"59" =>
if (extended = '0') then -- Ignore fake shifts
keys(13)(3) <= release; -- Left SHIFT -- Right SHIFT
end if;
when others => null;
end case;
end if;
end if;
end if;
end process;
end architecture;

View File

@@ -0,0 +1,920 @@
--
-- A simulation model of VIC20 hardware
-- Copyright (c) MikeJ - March 2003
--
-- 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 CODE 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.
--
-- You are responsible for any legal issues arising from your use of this code.
--
-- The latest version of this file can be found at: www.fpgaarcade.com
--
-- Email vic20@fpgaarcade.com
--
--
-- Revision list
--
-- version 004 fixes to PB7 T1 control and Mode 0 Shift Register operation
-- version 003 fix reset of T1/T2 IFR flags if T1/T2 is reload via reg5/reg9 from wolfgang (WoS)
-- Ported to numeric_std and simulation fix for signal initializations from arnim laeuger
-- version 002 fix from Mark McDougall, untested
-- version 001 initial release
-- not very sure about the shift register, documentation is a bit light.
library ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;
entity M6522 is
port (
I_RS : in std_logic_vector(3 downto 0);
I_DATA : in std_logic_vector(7 downto 0);
O_DATA : out std_logic_vector(7 downto 0);
O_DATA_OE_L : out std_logic;
I_RW_L : in std_logic;
I_CS1 : in std_logic;
I_CS2_L : in std_logic;
O_IRQ_L : out std_logic; -- note, not open drain
-- port a
I_CA1 : in std_logic;
I_CA2 : in std_logic;
O_CA2 : out std_logic;
O_CA2_OE_L : out std_logic;
I_PA : in std_logic_vector(7 downto 0);
O_PA : out std_logic_vector(7 downto 0);
O_PA_OE_L : out std_logic_vector(7 downto 0);
-- port b
I_CB1 : in std_logic;
O_CB1 : out std_logic;
O_CB1_OE_L : out std_logic;
I_CB2 : in std_logic;
O_CB2 : out std_logic;
O_CB2_OE_L : out std_logic;
I_PB : in std_logic_vector(7 downto 0);
O_PB : out std_logic_vector(7 downto 0);
O_PB_OE_L : out std_logic_vector(7 downto 0);
I_P2_H : in std_logic; -- high for phase 2 clock ____----__
RESET_L : in std_logic;
ENA_4 : in std_logic; -- clk enable
CLK : in std_logic
);
end;
architecture RTL of M6522 is
signal phase : std_logic_vector(1 downto 0):="00";
signal p2_h_t1 : std_logic;
signal cs : std_logic;
-- registers
signal r_ddra : std_logic_vector(7 downto 0);
signal r_ora : std_logic_vector(7 downto 0);
signal r_ira : std_logic_vector(7 downto 0);
signal r_ddrb : std_logic_vector(7 downto 0);
signal r_orb : std_logic_vector(7 downto 0);
signal r_irb : std_logic_vector(7 downto 0);
signal r_t1l_l : std_logic_vector(7 downto 0);
signal r_t1l_h : std_logic_vector(7 downto 0);
signal r_t2l_l : std_logic_vector(7 downto 0);
signal r_t2l_h : std_logic_vector(7 downto 0); -- not in real chip
signal r_sr : std_logic_vector(7 downto 0);
signal r_acr : std_logic_vector(7 downto 0);
signal r_pcr : std_logic_vector(7 downto 0);
signal r_ifr : std_logic_vector(7 downto 0);
signal r_ier : std_logic_vector(6 downto 0);
signal sr_write_ena : boolean;
signal sr_read_ena : boolean;
signal ifr_write_ena : boolean;
signal ier_write_ena : boolean;
signal clear_irq : std_logic_vector(7 downto 0);
signal load_data : std_logic_vector(7 downto 0);
-- timer 1
signal t1c : std_logic_vector(15 downto 0) := (others => '1'); -- simulators may not catch up w/o init here...
signal t1c_active : boolean;
signal t1c_done : boolean;
signal t1_w_reset_int : boolean;
signal t1_r_reset_int : boolean;
signal t1_load_counter : boolean;
signal t1_reload_counter : boolean;
signal t1_toggle : std_logic;
signal t1_irq : std_logic := '0';
-- timer 2
signal t2c : std_logic_vector(15 downto 0) := (others => '1'); -- simulators may not catch up w/o init here...
signal t2c_active : boolean;
signal t2c_done : boolean;
signal t2_pb6 : std_logic;
signal t2_pb6_t1 : std_logic;
signal t2_w_reset_int : boolean;
signal t2_r_reset_int : boolean;
signal t2_load_counter : boolean;
signal t2_reload_counter : boolean;
signal t2_irq : std_logic := '0';
signal t2_sr_ena : boolean;
-- shift reg
signal sr_cnt : std_logic_vector(3 downto 0);
signal sr_cb1_oe_l : std_logic;
signal sr_cb1_out : std_logic;
signal sr_drive_cb2 : std_logic;
signal sr_strobe : std_logic;
signal sr_strobe_t1 : std_logic;
signal sr_strobe_falling : boolean;
signal sr_strobe_rising : boolean;
signal sr_irq : std_logic;
signal sr_out : std_logic;
signal sr_off_delay : std_logic;
-- io
signal w_orb_hs : std_logic;
signal w_ora_hs : std_logic;
signal r_irb_hs : std_logic;
signal r_ira_hs : std_logic;
signal ca_hs_sr : std_logic;
signal ca_hs_pulse : std_logic;
signal cb_hs_sr : std_logic;
signal cb_hs_pulse : std_logic;
signal cb1_in_mux : std_logic;
signal ca1_ip_reg : std_logic;
signal cb1_ip_reg : std_logic;
signal ca1_int : boolean;
signal cb1_int : boolean;
signal ca1_irq : std_logic;
signal cb1_irq : std_logic;
signal ca2_ip_reg : std_logic;
signal cb2_ip_reg : std_logic;
signal ca2_int : boolean;
signal cb2_int : boolean;
signal ca2_irq : std_logic;
signal cb2_irq : std_logic;
signal final_irq : std_logic;
begin
p_phase : process
begin
-- internal clock phase
wait until rising_edge(CLK);
if (ENA_4 = '1') then
p2_h_t1 <= I_P2_H;
if (p2_h_t1 = '0') and (I_P2_H = '1') then
phase <= "11";
else
phase <= phase + "1";
end if;
end if;
end process;
p_cs : process(I_CS1, I_CS2_L, I_P2_H)
begin
cs <= '0';
if (I_CS1 = '1') and (I_CS2_L = '0') and (I_P2_H = '1') then
cs <= '1';
end if;
end process;
-- peripheral control reg (pcr)
-- 0 ca1 interrupt control (0 +ve edge, 1 -ve edge)
-- 3..1 ca2 operation
-- 000 input -ve edge
-- 001 independend interrupt input -ve edge
-- 010 input +ve edge
-- 011 independend interrupt input +ve edge
-- 100 handshake output
-- 101 pulse output
-- 110 low output
-- 111 high output
-- 7..4 as 3..0 for cb1,cb2
-- auxiliary control reg (acr)
-- 0 input latch PA (0 disable, 1 enable)
-- 1 input latch PB (0 disable, 1 enable)
-- 4..2 shift reg control
-- 000 disable
-- 001 shift in using t2
-- 010 shift in using o2
-- 011 shift in using ext clk
-- 100 shift out free running t2 rate
-- 101 shift out using t2
-- 101 shift out using o2
-- 101 shift out using ext clk
-- 5 t2 timer control (0 timed interrupt, 1 count down with pulses on pb6)
-- 7..6 t1 timer control
-- 00 timed interrupt each time t1 is loaded pb7 disable
-- 01 continuous interrupts pb7 disable
-- 00 timed interrupt each time t1 is loaded pb7 one shot output
-- 01 continuous interrupts pb7 square wave output
--
p_write_reg_reset : process(RESET_L, CLK)
begin
if (RESET_L = '0') then
r_ora <= x"00"; r_orb <= x"00";
r_ddra <= x"00"; r_ddrb <= x"00";
r_acr <= x"00"; r_pcr <= x"00";
w_orb_hs <= '0';
w_ora_hs <= '0';
elsif rising_edge(CLK) then
if (ENA_4 = '1') then
w_orb_hs <= '0';
w_ora_hs <= '0';
if (cs = '1') and (I_RW_L = '0') then
case I_RS is
when x"0" => r_orb <= I_DATA; w_orb_hs <= '1';
when x"1" => r_ora <= I_DATA; w_ora_hs <= '1';
when x"2" => r_ddrb <= I_DATA;
when x"3" => r_ddra <= I_DATA;
when x"B" => r_acr <= I_DATA;
when x"C" => r_pcr <= I_DATA;
when x"F" => r_ora <= I_DATA;
when others => null;
end case;
end if;
if r_acr(7) = '1' then
-- DMB: Forgetting to clear B7 broke Acornsoft Planetoid
if t1_load_counter then
r_orb(7) <= '0'; -- writing T1C-H resets bit 7
elsif t1_toggle = '1' then
r_orb(7) <= not r_orb(7); -- toggle
end if;
end if;
end if;
end if;
end process;
p_write_reg : process (RESET_L, CLK) is
begin
if (RESET_L = '0') then
-- The spec says, this is not reset.
-- Fact is that the 1541 VIA1 timer won't work,
-- as the firmware ONLY sets the r_t1l_h latch!!!!
r_t1l_l <= (others => '0');
r_t1l_h <= (others => '0');
r_t2l_l <= (others => '0');
r_t2l_h <= (others => '0');
elsif rising_edge(CLK) then
if (ENA_4 = '1') then
t1_w_reset_int <= false;
t1_load_counter <= false;
t2_w_reset_int <= false;
t2_load_counter <= false;
load_data <= x"00";
sr_write_ena <= false;
ifr_write_ena <= false;
ier_write_ena <= false;
if (cs = '1') and (I_RW_L = '0') then
load_data <= I_DATA;
case I_RS is
when x"4" => r_t1l_l <= I_DATA;
when x"5" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
t1_load_counter <= true;
when x"6" => r_t1l_l <= I_DATA;
when x"7" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
when x"8" => r_t2l_l <= I_DATA;
when x"9" => r_t2l_h <= I_DATA; t2_w_reset_int <= true;
t2_load_counter <= true;
when x"A" => sr_write_ena <= true;
when x"D" => ifr_write_ena <= true;
when x"E" => ier_write_ena <= true;
when others => null;
end case;
end if;
end if;
end if;
end process;
p_oe : process(cs, I_RW_L)
begin
O_DATA_OE_L <= '1';
if (cs = '1') and (I_RW_L = '1') then
O_DATA_OE_L <= '0';
end if;
end process;
p_read : process(cs, I_RW_L, I_RS, r_irb, r_ira, r_ddrb, r_ddra, t1c, r_t1l_l,
r_t1l_h, t2c, r_sr, r_acr, r_pcr, r_ifr, r_ier, r_orb)
begin
t1_r_reset_int <= false;
t2_r_reset_int <= false;
sr_read_ena <= false;
r_irb_hs <= '0';
r_ira_hs <= '0';
O_DATA <= x"00"; -- default
if (cs = '1') and (I_RW_L = '1') then
case I_RS is
--when x"0" => O_DATA <= r_irb; r_irb_hs <= '1';
-- fix from Mark McDougall, untested
when x"0" => O_DATA <= (r_irb and not r_ddrb) or (r_orb and r_ddrb); r_irb_hs <= '1';
when x"1" => O_DATA <= r_ira; r_ira_hs <= '1';
when x"2" => O_DATA <= r_ddrb;
when x"3" => O_DATA <= r_ddra;
when x"4" => O_DATA <= t1c( 7 downto 0); t1_r_reset_int <= true;
when x"5" => O_DATA <= t1c(15 downto 8);
when x"6" => O_DATA <= r_t1l_l;
when x"7" => O_DATA <= r_t1l_h;
when x"8" => O_DATA <= t2c( 7 downto 0); t2_r_reset_int <= true;
when x"9" => O_DATA <= t2c(15 downto 8);
when x"A" => O_DATA <= r_sr; sr_read_ena <= true;
when x"B" => O_DATA <= r_acr;
when x"C" => O_DATA <= r_pcr;
when x"D" => O_DATA <= r_ifr;
when x"E" => O_DATA <= ('0' & r_ier);
when x"F" => O_DATA <= r_ira;
when others => null;
end case;
end if;
end process;
--
-- IO
--
p_ca1_cb1_sel : process(sr_cb1_oe_l, sr_cb1_out, I_CB1)
begin
-- if the shift register is enabled, cb1 may be an output
-- in this case, we should listen to the CB1_OUT for the interrupt
if (sr_cb1_oe_l = '1') then
cb1_in_mux <= I_CB1;
else
cb1_in_mux <= sr_cb1_out;
end if;
end process;
p_ca1_cb1_int : process(r_pcr, ca1_ip_reg, I_CA1, cb1_ip_reg, cb1_in_mux)
begin
if (r_pcr(0) = '0') then -- ca1 control
-- negative edge
ca1_int <= (ca1_ip_reg = '1') and (I_CA1 = '0');
else
-- positive edge
ca1_int <= (ca1_ip_reg = '0') and (I_CA1 = '1');
end if;
if (r_pcr(4) = '0') then -- cb1 control
-- negative edge
cb1_int <= (cb1_ip_reg = '1') and (cb1_in_mux = '0');
else
-- positive edge
cb1_int <= (cb1_ip_reg = '0') and (cb1_in_mux = '1');
end if;
end process;
p_ca2_cb2_int : process(r_pcr, ca2_ip_reg, I_CA2, cb2_ip_reg, I_CB2)
begin
ca2_int <= false;
if (r_pcr(3) = '0') then -- ca2 input
if (r_pcr(2) = '0') then -- ca2 edge
-- negative edge
ca2_int <= (ca2_ip_reg = '1') and (I_CA2 = '0');
else
-- positive edge
ca2_int <= (ca2_ip_reg = '0') and (I_CA2 = '1');
end if;
end if;
cb2_int <= false;
if (r_pcr(7) = '0') then -- cb2 input
if (r_pcr(6) = '0') then -- cb2 edge
-- negative edge
cb2_int <= (cb2_ip_reg = '1') and (I_CB2 = '0');
else
-- positive edge
cb2_int <= (cb2_ip_reg = '0') and (I_CB2 = '1');
end if;
end if;
end process;
p_ca2_cb2 : process(RESET_L, CLK)
begin
if (RESET_L = '0') then
O_CA2 <= '0';
O_CA2_OE_L <= '1';
O_CB2 <= '0';
O_CB2_OE_L <= '1';
ca_hs_sr <= '0';
ca_hs_pulse <= '0';
cb_hs_sr <= '0';
cb_hs_pulse <= '0';
elsif rising_edge(CLK) then
if (ENA_4 = '1') then
-- ca
if (phase = "00") and ((w_ora_hs = '1') or (r_ira_hs = '1')) then
ca_hs_sr <= '1';
elsif ca1_int then
ca_hs_sr <= '0';
end if;
if (phase = "00") then
ca_hs_pulse <= w_ora_hs or r_ira_hs;
end if;
O_CA2_OE_L <= not r_pcr(3); -- ca2 output
case r_pcr(3 downto 1) is
when "000" => O_CA2 <= '0'; -- input
when "001" => O_CA2 <= '0'; -- input
when "010" => O_CA2 <= '0'; -- input
when "011" => O_CA2 <= '0'; -- input
when "100" => O_CA2 <= not (ca_hs_sr); -- handshake
when "101" => O_CA2 <= not (ca_hs_pulse); -- pulse
when "110" => O_CA2 <= '0'; -- low
when "111" => O_CA2 <= '1'; -- high
when others => null;
end case;
-- cb
if (phase = "00") and (w_orb_hs = '1') then
cb_hs_sr <= '1';
elsif cb1_int then
cb_hs_sr <= '0';
end if;
if (phase = "00") then
cb_hs_pulse <= w_orb_hs;
end if;
O_CB2_OE_L <= not (r_pcr(7) or sr_drive_cb2); -- cb2 output or serial
if (sr_drive_cb2 = '1') then -- serial output
O_CB2 <= sr_out;
else
case r_pcr(7 downto 5) is
when "000" => O_CB2 <= '0'; -- input
when "001" => O_CB2 <= '0'; -- input
when "010" => O_CB2 <= '0'; -- input
when "011" => O_CB2 <= '0'; -- input
when "100" => O_CB2 <= not (cb_hs_sr); -- handshake
when "101" => O_CB2 <= not (cb_hs_pulse); -- pulse
when "110" => O_CB2 <= '0'; -- low
when "111" => O_CB2 <= '1'; -- high
when others => null;
end case;
end if;
end if;
end if;
end process;
O_CB1 <= sr_cb1_out;
O_CB1_OE_L <= sr_cb1_oe_l;
p_ca_cb_irq : process(RESET_L, CLK)
begin
if (RESET_L = '0') then
ca1_irq <= '0';
ca2_irq <= '0';
cb1_irq <= '0';
cb2_irq <= '0';
elsif rising_edge(CLK) then
if (ENA_4 = '1') then
-- not pretty
if ca1_int then
ca1_irq <= '1';
elsif (r_ira_hs = '1') or (w_ora_hs = '1') or (clear_irq(1) = '1') then
ca1_irq <= '0';
end if;
if ca2_int then
ca2_irq <= '1';
else
if (((r_ira_hs = '1') or (w_ora_hs = '1')) and (r_pcr(1) = '0')) or
(clear_irq(0) = '1') then
ca2_irq <= '0';
end if;
end if;
if cb1_int then
cb1_irq <= '1';
elsif (r_irb_hs = '1') or (w_orb_hs = '1') or (clear_irq(4) = '1') then
cb1_irq <= '0';
end if;
if cb2_int then
cb2_irq <= '1';
else
if (((r_irb_hs = '1') or (w_orb_hs = '1')) and (r_pcr(5) = '0')) or
(clear_irq(3) = '1') then
cb2_irq <= '0';
end if;
end if;
end if;
end if;
end process;
p_input_reg : process(RESET_L, CLK)
begin
if (RESET_L = '0') then
ca1_ip_reg <= '0';
cb1_ip_reg <= '0';
ca2_ip_reg <= '0';
cb2_ip_reg <= '0';
r_ira <= x"00";
r_irb <= x"00";
elsif rising_edge(CLK) then
if (ENA_4 = '1') then
-- we have a fast clock, so we can have input registers
ca1_ip_reg <= I_CA1;
cb1_ip_reg <= cb1_in_mux;
ca2_ip_reg <= I_CA2;
cb2_ip_reg <= I_CB2;
if (r_acr(0) = '0') then
r_ira <= I_PA;
else -- enable latching
if ca1_int then
r_ira <= I_PA;
end if;
end if;
if (r_acr(1) = '0') then
r_irb <= I_PB;
else -- enable latching
if cb1_int then
r_irb <= I_PB;
end if;
end if;
end if;
end if;
end process;
p_buffers : process(r_ddra, r_ora, r_ddrb, r_acr, r_orb)
begin
-- data direction reg (ddr) 0 = input, 1 = output
O_PA <= r_ora;
O_PA_OE_L <= not r_ddra;
if (r_acr(7) = '1') then -- not clear if r_ddrb(7) must be 1 as well
O_PB_OE_L(7) <= '0'; -- an output if under t1 control
else
O_PB_OE_L(7) <= not (r_ddrb(7));
end if;
O_PB_OE_L(6 downto 0) <= not r_ddrb(6 downto 0);
O_PB(7 downto 0) <= r_orb(7 downto 0);
end process;
--
-- Timer 1
--
p_timer1_done : process
variable done : boolean;
begin
wait until rising_edge(CLK);
if (ENA_4 = '1') then
done := (t1c = x"0000");
t1c_done <= done and (phase = "11");
if (phase = "11") then
t1_reload_counter <= done and (r_acr(6) = '1');
end if;
if t1_load_counter then -- done reset on load!
t1c_done <= false;
end if;
end if;
end process;
p_timer1 : process
begin
wait until rising_edge(CLK);
if (ENA_4 = '1') then
if t1_load_counter or (t1_reload_counter and phase = "11") then
t1c( 7 downto 0) <= r_t1l_l;
t1c(15 downto 8) <= r_t1l_h;
elsif (phase="11") then
t1c <= t1c - "1";
end if;
if t1_load_counter or t1_reload_counter then
t1c_active <= true;
elsif t1c_done then
t1c_active <= false;
end if;
t1_toggle <= '0';
if t1c_active and t1c_done then
t1_toggle <= '1';
t1_irq <= '1';
elsif t1_w_reset_int or t1_r_reset_int or (clear_irq(6) = '1') then
t1_irq <= '0';
end if;
if t1_load_counter then -- irq reset on load!
t1_irq <= '0';
end if;
end if;
end process;
--
-- Timer2
--
p_timer2_pb6_input : process
begin
wait until rising_edge(CLK);
if (ENA_4 = '1') then
if (phase = "01") then -- leading edge p2_h
t2_pb6 <= I_PB(6);
t2_pb6_t1 <= t2_pb6;
end if;
end if;
end process;
p_timer2_done : process
variable done : boolean;
begin
wait until rising_edge(CLK);
if (ENA_4 = '1') then
done := (t2c = x"0000");
t2c_done <= done and (phase = "11");
if (phase = "11") then
t2_reload_counter <= done;
end if;
if t2_load_counter then -- done reset on load!
t2c_done <= false;
end if;
end if;
end process;
p_timer2 : process
variable ena : boolean;
begin
wait until rising_edge(CLK);
if (ENA_4 = '1') then
if (r_acr(5) = '0') then
ena := true;
else
ena := (t2_pb6_t1 = '1') and (t2_pb6 = '0'); -- falling edge
end if;
if t2_load_counter or (t2_reload_counter and phase = "11") then
-- not sure if t2c_reload should be here. Does timer2 just continue to
-- count down, or is it reloaded ? Reloaded makes more sense if using
-- it to generate a clock for the shift register.
t2c( 7 downto 0) <= r_t2l_l;
t2c(15 downto 8) <= r_t2l_h;
else
if (phase="11") and ena then -- or count mode
t2c <= t2c - "1";
end if;
end if;
t2_sr_ena <= (t2c(7 downto 0) = x"00") and (phase = "11");
if t2_load_counter then
t2c_active <= true;
elsif t2c_done then
t2c_active <= false;
end if;
if t2c_active and t2c_done then
t2_irq <= '1';
elsif t2_w_reset_int or t2_r_reset_int or (clear_irq(5) = '1') then
t2_irq <= '0';
end if;
if t2_load_counter then -- irq reset on load!
t2_irq <= '0';
end if;
end if;
end process;
--
-- Shift Register
--
p_sr : process(RESET_L, CLK)
variable dir_out : std_logic;
variable ena : std_logic;
variable cb1_op : std_logic;
variable cb1_ip : std_logic;
variable use_t2 : std_logic;
variable free_run : std_logic;
variable sr_count_ena : boolean;
begin
if (RESET_L = '0') then
r_sr <= x"00";
sr_drive_cb2 <= '0';
sr_cb1_oe_l <= '1';
sr_cb1_out <= '0';
sr_strobe <= '1';
sr_cnt <= "0000";
sr_irq <= '0';
sr_out <= '1';
sr_off_delay <= '0';
elsif rising_edge(CLK) then
if (ENA_4 = '1') then
-- decode mode
dir_out := r_acr(4); -- output on cb2
cb1_op := '0';
cb1_ip := '0';
use_t2 := '0';
free_run := '0';
-- DMB: SR still runs even in disabled mode (on rising edge of CB1).
-- It just doesn't generate any interrupts.
-- Ref BBC micro advanced user guide p409
case r_acr(4 downto 2) is
-- DMB: in disabled mode, configure cb1 as an input
when "000" => ena := '0'; cb1_ip := '1';
when "001" => ena := '1'; cb1_op := '1'; use_t2 := '1';
when "010" => ena := '1'; cb1_op := '1';
when "011" => ena := '1'; cb1_ip := '1';
when "100" => ena := '1'; use_t2 := '1'; free_run := '1';
when "101" => ena := '1'; cb1_op := '1'; use_t2 := '1';
when "110" => ena := '1';
when "111" => ena := '1'; cb1_ip := '1';
when others => null;
end case;
-- clock select
-- DMB: in disabled mode, strobe from cb1
if (cb1_ip = '1') then
sr_strobe <= I_CB1;
else
if (sr_cnt(3) = '0') and (free_run = '0') then
sr_strobe <= '1';
else
if ((use_t2 = '1') and t2_sr_ena) or
((use_t2 = '0') and (phase = "00")) then
sr_strobe <= not sr_strobe;
end if;
end if;
end if;
-- latch on rising edge, shift on falling edge
if sr_write_ena then
r_sr <= load_data;
else
-- DMB: allow shifting in all modes
if (dir_out = '0') then
-- input
if (sr_cnt(3) = '1') or (cb1_ip = '1') then
if sr_strobe_rising then
r_sr(0) <= I_CB2;
elsif sr_strobe_falling then
r_sr(7 downto 1) <= r_sr(6 downto 0);
end if;
end if;
sr_out <= '1';
else
-- output
if (sr_cnt(3) = '1') or (sr_off_delay = '1') or (cb1_ip = '1') or (free_run = '1') then
if sr_strobe_falling then
r_sr(7 downto 1) <= r_sr(6 downto 0);
r_sr(0) <= r_sr(7);
sr_out <= r_sr(7);
end if;
else
sr_out <= '1';
end if;
end if;
end if;
sr_count_ena := sr_strobe_rising;
-- DMB: reseting sr_count when not enabled cause the sr to
-- start running immediately it was enabled, which is incorrect
-- and broke the latest SmartSPI ROM on the BBC Micro
if ena = '1' and (sr_write_ena or sr_read_ena) then
-- some documentation says sr bit in IFR must be set as well ?
sr_cnt <= "1000";
elsif sr_count_ena and (sr_cnt(3) = '1') then
sr_cnt <= sr_cnt + "1";
end if;
if (phase = "00") then
sr_off_delay <= sr_cnt(3); -- give some hold time when shifting out
end if;
if sr_count_ena and (sr_cnt = "1111") and (ena = '1') and (free_run = '0') then
sr_irq <= '1';
elsif sr_write_ena or sr_read_ena or (clear_irq(2) = '1') then
sr_irq <= '0';
end if;
-- assign ops
sr_drive_cb2 <= dir_out;
sr_cb1_oe_l <= not cb1_op;
sr_cb1_out <= sr_strobe;
end if;
end if;
end process;
p_sr_strobe_rise_fall : process
begin
wait until rising_edge(CLK);
if (ENA_4 = '1') then
sr_strobe_t1 <= sr_strobe;
sr_strobe_rising <= (sr_strobe_t1 = '0') and (sr_strobe = '1');
sr_strobe_falling <= (sr_strobe_t1 = '1') and (sr_strobe = '0');
end if;
end process;
--
-- Interrupts
--
p_ier : process(RESET_L, CLK)
begin
if (RESET_L = '0') then
r_ier <= "0000000";
elsif rising_edge(CLK) then
if (ENA_4 = '1') then
if ier_write_ena then
if (load_data(7) = '1') then
-- set
r_ier <= r_ier or load_data(6 downto 0);
else
-- clear
r_ier <= r_ier and not load_data(6 downto 0);
end if;
end if;
end if;
end if;
end process;
p_ifr : process(t1_irq, t2_irq, final_irq, ca1_irq, ca2_irq, sr_irq,
cb1_irq, cb2_irq)
begin
r_ifr(7) <= final_irq;
r_ifr(6) <= t1_irq;
r_ifr(5) <= t2_irq;
r_ifr(4) <= cb1_irq;
r_ifr(3) <= cb2_irq;
r_ifr(2) <= sr_irq;
r_ifr(1) <= ca1_irq;
r_ifr(0) <= ca2_irq;
O_IRQ_L <= not final_irq;
end process;
p_irq : process(RESET_L, CLK)
begin
if (RESET_L = '0') then
final_irq <= '0';
elsif rising_edge(CLK) then
if (ENA_4 = '1') then
if ((r_ifr(6 downto 0) and r_ier(6 downto 0)) = "0000000") then
final_irq <= '0'; -- no interrupts
else
final_irq <= '1';
end if;
end if;
end if;
end process;
p_clear_irq : process(ifr_write_ena, load_data)
begin
clear_irq <= x"00";
if ifr_write_ena then
clear_irq <= load_data;
end if;
end process;
end architecture RTL;

View File

@@ -0,0 +1,491 @@
//
// mist_io.v
//
// mist_io for the MiST board
// http://code.google.com/p/mist-board/
//
// Copyright (c) 2014 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
///////////////////////////////////////////////////////////////////////
//
// Use buffer to access SD card. It's time-critical part.
// Made module synchroneous with 2 clock domains: clk_sys and SPI_SCK
// (Sorgelig)
//
// for synchronous projects default value for PS2DIV is fine for any frequency of system clock.
// clk_ps2 = clk_sys/(PS2DIV*2)
//
module mist_io #(parameter STRLEN=0, parameter PS2DIV=100)
(
// parameter STRLEN and the actual length of conf_str have to match
input [(8*STRLEN)-1:0] conf_str,
// Global clock. It should be around 100MHz (higher is better).
input clk_sys,
// Global SPI clock from ARM. 24MHz
input SPI_SCK,
input CONF_DATA0,
input SPI_SS2,
output SPI_DO,
input SPI_DI,
output reg [7:0] joystick_0,
output reg [7:0] joystick_1,
output reg [15:0] joystick_analog_0,
output reg [15:0] joystick_analog_1,
output [1:0] buttons,
output [1:0] switches,
output scandoubler_disable,
output ypbpr,
output reg [31:0] status,
// SD config
input sd_conf,
input sd_sdhc,
output img_mounted, // signaling that new image has been mounted
output reg [31:0] img_size, // size of image in bytes
// SD block level access
input [31:0] sd_lba,
input sd_rd,
input sd_wr,
output reg sd_ack,
output reg sd_ack_conf,
// SD byte level access. Signals for 2-PORT altsyncram.
output reg [8:0] sd_buff_addr,
output reg [7:0] sd_buff_dout,
input [7:0] sd_buff_din,
output reg sd_buff_wr,
// ps2 keyboard emulation
output ps2_kbd_clk,
output reg ps2_kbd_data,
output ps2_mouse_clk,
output reg ps2_mouse_data,
input ps2_caps_led,
// ARM -> FPGA download
output reg ioctl_download = 0, // signal indicating an active download
output reg [7:0] ioctl_index, // menu index used to upload the file
output ioctl_wr,
output reg [24:0] ioctl_addr,
output reg [7:0] ioctl_dout
);
reg [7:0] b_data;
reg [6:0] sbuf;
reg [7:0] cmd;
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
reg [9:0] byte_cnt; // counts bytes
reg [7:0] but_sw;
reg [2:0] stick_idx;
reg mount_strobe = 0;
assign img_mounted = mount_strobe;
assign buttons = but_sw[1:0];
assign switches = but_sw[3:2];
assign scandoubler_disable = but_sw[4];
assign ypbpr = but_sw[5];
wire [7:0] spi_dout = { sbuf, SPI_DI};
// this variant of user_io is for 8 bit cores (type == a4) only
wire [7:0] core_type = 8'ha4;
// command byte read by the io controller
wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd };
reg spi_do;
assign SPI_DO = CONF_DATA0 ? 1'bZ : spi_do;
wire [7:0] kbd_led = { 2'b01, 4'b0000, ps2_caps_led, 1'b1};
// drive MISO only when transmitting core id
always@(negedge SPI_SCK) begin
if(!CONF_DATA0) begin
// first byte returned is always core type, further bytes are
// command dependent
if(byte_cnt == 0) begin
spi_do <= core_type[~bit_cnt];
end else begin
case(cmd)
// reading config string
8'h14: begin
// returning a byte from string
if(byte_cnt < STRLEN + 1) spi_do <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];
else spi_do <= 0;
end
// reading sd card status
8'h16: begin
if(byte_cnt == 1) spi_do <= sd_cmd[~bit_cnt];
else if((byte_cnt >= 2) && (byte_cnt < 6)) spi_do <= sd_lba[{5-byte_cnt, ~bit_cnt}];
else spi_do <= 0;
end
// reading sd card write data
8'h18:
spi_do <= b_data[~bit_cnt];
// reading keyboard LED status
8'h1f:
spi_do <= kbd_led[~bit_cnt];
default:
spi_do <= 0;
endcase
end
end
end
reg b_wr2,b_wr3;
always @(negedge clk_sys) begin
b_wr3 <= b_wr2;
sd_buff_wr <= b_wr3;
end
// SPI receiver
always@(posedge SPI_SCK or posedge CONF_DATA0) begin
if(CONF_DATA0) begin
b_wr2 <= 0;
bit_cnt <= 0;
byte_cnt <= 0;
sd_ack <= 0;
sd_ack_conf <= 0;
end else begin
b_wr2 <= 0;
sbuf <= spi_dout[6:0];
bit_cnt <= bit_cnt + 1'd1;
if(bit_cnt == 5) begin
if (byte_cnt == 0) sd_buff_addr <= 0;
if((byte_cnt != 0) & (sd_buff_addr != 511)) sd_buff_addr <= sd_buff_addr + 1'b1;
if((byte_cnt == 1) & ((cmd == 8'h17) | (cmd == 8'h19))) sd_buff_addr <= 0;
end
// finished reading command byte
if(bit_cnt == 7) begin
if(~&byte_cnt) byte_cnt <= byte_cnt + 8'd1;
if(byte_cnt == 0) begin
cmd <= spi_dout;
if(spi_dout == 8'h19) begin
sd_ack_conf <= 1;
sd_buff_addr <= 0;
end
if((spi_dout == 8'h17) || (spi_dout == 8'h18)) begin
sd_ack <= 1;
sd_buff_addr <= 0;
end
if(spi_dout == 8'h18) b_data <= sd_buff_din;
mount_strobe <= 0;
end else begin
case(cmd)
// buttons and switches
8'h01: but_sw <= spi_dout;
8'h02: joystick_0 <= spi_dout;
8'h03: joystick_1 <= spi_dout;
// store incoming ps2 mouse bytes
8'h04: begin
ps2_mouse_fifo[ps2_mouse_wptr] <= spi_dout;
ps2_mouse_wptr <= ps2_mouse_wptr + 1'd1;
end
// store incoming ps2 keyboard bytes
8'h05: begin
ps2_kbd_fifo[ps2_kbd_wptr] <= spi_dout;
ps2_kbd_wptr <= ps2_kbd_wptr + 1'd1;
end
8'h15: status[7:0] <= spi_dout;
// send SD config IO -> FPGA
// flag that download begins
// sd card knows data is config if sd_dout_strobe is asserted
// with sd_ack still being inactive (low)
8'h19,
// send sector IO -> FPGA
// flag that download begins
8'h17: begin
sd_buff_dout <= spi_dout;
b_wr2 <= 1;
end
8'h18: b_data <= sd_buff_din;
// joystick analog
8'h1a: begin
// first byte is joystick index
if(byte_cnt == 1) stick_idx <= spi_dout[2:0];
else if(byte_cnt == 2) begin
// second byte is x axis
if(stick_idx == 0) joystick_analog_0[15:8] <= spi_dout;
else if(stick_idx == 1) joystick_analog_1[15:8] <= spi_dout;
end else if(byte_cnt == 3) begin
// third byte is y axis
if(stick_idx == 0) joystick_analog_0[7:0] <= spi_dout;
else if(stick_idx == 1) joystick_analog_1[7:0] <= spi_dout;
end
end
// notify image selection
8'h1c: mount_strobe <= 1;
// send image info
8'h1d: if(byte_cnt<5) img_size[(byte_cnt-1)<<3 +:8] <= spi_dout;
// status, 32bit version
8'h1e: if(byte_cnt<5) status[(byte_cnt-1)<<3 +:8] <= spi_dout;
default: ;
endcase
end
end
end
end
/////////////////////////////// PS2 ///////////////////////////////
// 8 byte fifos to store ps2 bytes
localparam PS2_FIFO_BITS = 3;
reg clk_ps2;
always @(negedge clk_sys) begin
integer cnt;
cnt <= cnt + 1'd1;
if(cnt == PS2DIV) begin
clk_ps2 <= ~clk_ps2;
cnt <= 0;
end
end
// keyboard
reg [7:0] ps2_kbd_fifo[1<<PS2_FIFO_BITS];
reg [PS2_FIFO_BITS-1:0] ps2_kbd_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_kbd_rptr;
// ps2 transmitter state machine
reg [3:0] ps2_kbd_tx_state;
reg [7:0] ps2_kbd_tx_byte;
reg ps2_kbd_parity;
assign ps2_kbd_clk = clk_ps2 || (ps2_kbd_tx_state == 0);
// ps2 transmitter
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
reg ps2_kbd_r_inc;
always@(posedge clk_sys) begin
reg old_clk;
old_clk <= clk_ps2;
if(~old_clk & clk_ps2) begin
ps2_kbd_r_inc <= 0;
if(ps2_kbd_r_inc) ps2_kbd_rptr <= ps2_kbd_rptr + 1'd1;
// transmitter is idle?
if(ps2_kbd_tx_state == 0) begin
// data in fifo present?
if(ps2_kbd_wptr != ps2_kbd_rptr) begin
// load tx register from fifo
ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
ps2_kbd_r_inc <= 1;
// reset parity
ps2_kbd_parity <= 1;
// start transmitter
ps2_kbd_tx_state <= 1;
// put start bit on data line
ps2_kbd_data <= 0; // start bit is 0
end
end else begin
// transmission of 8 data bits
if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin
ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits
ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down
if(ps2_kbd_tx_byte[0])
ps2_kbd_parity <= !ps2_kbd_parity;
end
// transmission of parity
if(ps2_kbd_tx_state == 9) ps2_kbd_data <= ps2_kbd_parity;
// transmission of stop bit
if(ps2_kbd_tx_state == 10) ps2_kbd_data <= 1; // stop bit is 1
// advance state machine
if(ps2_kbd_tx_state < 11) ps2_kbd_tx_state <= ps2_kbd_tx_state + 1'd1;
else ps2_kbd_tx_state <= 0;
end
end
end
// mouse
reg [7:0] ps2_mouse_fifo[1<<PS2_FIFO_BITS];
reg [PS2_FIFO_BITS-1:0] ps2_mouse_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_mouse_rptr;
// ps2 transmitter state machine
reg [3:0] ps2_mouse_tx_state;
reg [7:0] ps2_mouse_tx_byte;
reg ps2_mouse_parity;
assign ps2_mouse_clk = clk_ps2 || (ps2_mouse_tx_state == 0);
// ps2 transmitter
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
reg ps2_mouse_r_inc;
always@(posedge clk_sys) begin
reg old_clk;
old_clk <= clk_ps2;
if(~old_clk & clk_ps2) begin
ps2_mouse_r_inc <= 0;
if(ps2_mouse_r_inc) ps2_mouse_rptr <= ps2_mouse_rptr + 1'd1;
// transmitter is idle?
if(ps2_mouse_tx_state == 0) begin
// data in fifo present?
if(ps2_mouse_wptr != ps2_mouse_rptr) begin
// load tx register from fifo
ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
ps2_mouse_r_inc <= 1;
// reset parity
ps2_mouse_parity <= 1;
// start transmitter
ps2_mouse_tx_state <= 1;
// put start bit on data line
ps2_mouse_data <= 0; // start bit is 0
end
end else begin
// transmission of 8 data bits
if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin
ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits
ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down
if(ps2_mouse_tx_byte[0])
ps2_mouse_parity <= !ps2_mouse_parity;
end
// transmission of parity
if(ps2_mouse_tx_state == 9) ps2_mouse_data <= ps2_mouse_parity;
// transmission of stop bit
if(ps2_mouse_tx_state == 10) ps2_mouse_data <= 1; // stop bit is 1
// advance state machine
if(ps2_mouse_tx_state < 11) ps2_mouse_tx_state <= ps2_mouse_tx_state + 1'd1;
else ps2_mouse_tx_state <= 0;
end
end
end
/////////////////////////////// DOWNLOADING ///////////////////////////////
reg [7:0] data_w;
reg [24:0] addr_w;
reg rclk = 0;
localparam UIO_FILE_TX = 8'h53;
localparam UIO_FILE_TX_DAT = 8'h54;
localparam UIO_FILE_INDEX = 8'h55;
// data_io has its own SPI interface to the io controller
always@(posedge SPI_SCK, posedge SPI_SS2) begin
reg [6:0] sbuf;
reg [7:0] cmd;
reg [4:0] cnt;
reg [24:0] addr;
if(SPI_SS2) cnt <= 0;
else begin
rclk <= 0;
// don't shift in last bit. It is evaluated directly
// when writing to ram
if(cnt != 15) sbuf <= { sbuf[5:0], SPI_DI};
// increase target address after write
if(rclk) addr <= addr + 1'd1;
// count 0-7 8-15 8-15 ...
if(cnt < 15) cnt <= cnt + 1'd1;
else cnt <= 8;
// finished command byte
if(cnt == 7) cmd <= {sbuf, SPI_DI};
// prepare/end transmission
if((cmd == UIO_FILE_TX) && (cnt == 15)) begin
// prepare
if(SPI_DI) begin
addr <= 0;
ioctl_download <= 1;
end else begin
addr_w <= addr;
ioctl_download <= 0;
end
end
// command 0x54: UIO_FILE_TX
if((cmd == UIO_FILE_TX_DAT) && (cnt == 15)) begin
addr_w <= addr;
data_w <= {sbuf, SPI_DI};
rclk <= 1;
end
// expose file (menu) index
if((cmd == UIO_FILE_INDEX) && (cnt == 15)) ioctl_index <= {sbuf, SPI_DI};
end
end
assign ioctl_wr = |ioctl_wrd;
reg [1:0] ioctl_wrd;
always@(negedge clk_sys) begin
reg rclkD, rclkD2;
rclkD <= rclk;
rclkD2 <= rclkD;
ioctl_wrd<= {ioctl_wrd[0],1'b0};
if(rclkD & ~rclkD2) begin
ioctl_dout <= data_w;
ioctl_addr <= addr_w;
ioctl_wrd <= 2'b11;
end
end
endmodule

View File

@@ -0,0 +1,179 @@
// A simple OSD implementation. Can be hooked up between a cores
// VGA output and the physical VGA pins
module osd (
// OSDs pixel clock, should be synchronous to cores pixel clock to
// avoid jitter.
input clk_sys,
// SPI interface
input SPI_SCK,
input SPI_SS3,
input SPI_DI,
// VGA signals coming from core
input [5:0] R_in,
input [5:0] G_in,
input [5:0] B_in,
input HSync,
input VSync,
// VGA signals going to video connector
output [5:0] R_out,
output [5:0] G_out,
output [5:0] B_out
);
parameter OSD_X_OFFSET = 10'd0;
parameter OSD_Y_OFFSET = 10'd0;
parameter OSD_COLOR = 3'd0;
localparam OSD_WIDTH = 10'd256;
localparam OSD_HEIGHT = 10'd128;
// *********************************************************************************
// spi client
// *********************************************************************************
// this core supports only the display related OSD commands
// of the minimig
reg osd_enable;
(* ramstyle = "no_rw_check" *) reg [7:0] osd_buffer[2047:0]; // the OSD buffer itself
// the OSD has its own SPI interface to the io controller
always@(posedge SPI_SCK, posedge SPI_SS3) begin
reg [4:0] cnt;
reg [10:0] bcnt;
reg [7:0] sbuf;
reg [7:0] cmd;
if(SPI_SS3) begin
cnt <= 0;
bcnt <= 0;
end else begin
sbuf <= {sbuf[6:0], SPI_DI};
// 0:7 is command, rest payload
if(cnt < 15) cnt <= cnt + 1'd1;
else cnt <= 8;
if(cnt == 7) begin
cmd <= {sbuf[6:0], SPI_DI};
// lower three command bits are line address
bcnt <= {sbuf[1:0], SPI_DI, 8'h00};
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
if(sbuf[6:3] == 4'b0100) osd_enable <= SPI_DI;
end
// command 0x20: OSDCMDWRITE
if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin
osd_buffer[bcnt] <= {sbuf[6:0], SPI_DI};
bcnt <= bcnt + 1'd1;
end
end
end
// *********************************************************************************
// video timing and sync polarity anaylsis
// *********************************************************************************
// horizontal counter
reg [9:0] h_cnt;
reg [9:0] hs_low, hs_high;
wire hs_pol = hs_high < hs_low;
wire [9:0] dsp_width = hs_pol ? hs_low : hs_high;
// vertical counter
reg [9:0] v_cnt;
reg [9:0] vs_low, vs_high;
wire vs_pol = vs_high < vs_low;
wire [9:0] dsp_height = vs_pol ? vs_low : vs_high;
wire doublescan = (dsp_height>350);
reg ce_pix;
always @(negedge clk_sys) begin
integer cnt = 0;
integer pixsz, pixcnt;
reg hs;
cnt <= cnt + 1;
hs <= HSync;
pixcnt <= pixcnt + 1;
if(pixcnt == pixsz) pixcnt <= 0;
ce_pix <= !pixcnt;
if(hs && ~HSync) begin
cnt <= 0;
pixsz <= (cnt >> 9) - 1;
pixcnt <= 0;
ce_pix <= 1;
end
end
always @(posedge clk_sys) begin
reg hsD, hsD2;
reg vsD, vsD2;
if(ce_pix) begin
// bring hsync into local clock domain
hsD <= HSync;
hsD2 <= hsD;
// falling edge of HSync
if(!hsD && hsD2) begin
h_cnt <= 0;
hs_high <= h_cnt;
end
// rising edge of HSync
else if(hsD && !hsD2) begin
h_cnt <= 0;
hs_low <= h_cnt;
v_cnt <= v_cnt + 1'd1;
end else begin
h_cnt <= h_cnt + 1'd1;
end
vsD <= VSync;
vsD2 <= vsD;
// falling edge of VSync
if(!vsD && vsD2) begin
v_cnt <= 0;
vs_high <= v_cnt;
end
// rising edge of VSync
else if(vsD && !vsD2) begin
v_cnt <= 0;
vs_low <= v_cnt;
end
end
end
// area in which OSD is being displayed
wire [9:0] h_osd_start = ((dsp_width - OSD_WIDTH)>> 1) + OSD_X_OFFSET;
wire [9:0] h_osd_end = h_osd_start + OSD_WIDTH;
wire [9:0] v_osd_start = ((dsp_height- (OSD_HEIGHT<<doublescan))>> 1) + OSD_Y_OFFSET;
wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<<doublescan);
wire [9:0] osd_hcnt = h_cnt - h_osd_start + 1'd1; // one pixel offset for osd_byte register
wire [9:0] osd_vcnt = v_cnt - v_osd_start;
wire osd_de = osd_enable &&
(HSync != hs_pol) && (h_cnt >= h_osd_start) && (h_cnt < h_osd_end) &&
(VSync != vs_pol) && (v_cnt >= v_osd_start) && (v_cnt < v_osd_end);
reg [7:0] osd_byte;
always @(posedge clk_sys) if(ce_pix) osd_byte <= osd_buffer[{doublescan ? osd_vcnt[7:5] : osd_vcnt[6:4], osd_hcnt[7:0]}];
wire osd_pixel = osd_byte[doublescan ? osd_vcnt[4:2] : osd_vcnt[3:1]];
assign R_out = !osd_de ? R_in : {osd_pixel, osd_pixel, OSD_COLOR[2], R_in[5:3]};
assign G_out = !osd_de ? G_in : {osd_pixel, osd_pixel, OSD_COLOR[1], G_in[5:3]};
assign B_out = !osd_de ? B_in : {osd_pixel, osd_pixel, OSD_COLOR[0], B_in[5:3]};
endmodule

View File

@@ -0,0 +1,446 @@
-- megafunction wizard: %ALTPLL%
-- GENERATION: STANDARD
-- VERSION: WM1.0
-- MODULE: altpll
-- ============================================================
-- File Name: pll.vhd
-- Megafunction Name(s):
-- altpll
--
-- Simulation Library Files(s):
-- altera_mf
-- ============================================================
-- ************************************************************
-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
--
-- 13.0.1 Build 232 06/12/2013 SP 1 SJ Full Version
-- ************************************************************
--Copyright (C) 1991-2013 Altera Corporation
--Your use of Altera Corporation's design tools, logic functions
--and other software and tools, and its AMPP partner logic
--functions, and any output files from any of the foregoing
--(including device programming or simulation files), and any
--associated documentation or information are expressly subject
--to the terms and conditions of the Altera Program License
--Subscription Agreement, Altera MegaCore Function License
--Agreement, or other applicable license agreement, including,
--without limitation, that your use is for the sole purpose of
--programming logic devices manufactured by Altera and sold by
--Altera or its authorized distributors. Please refer to the
--applicable agreement for further details.
LIBRARY ieee;
USE ieee.std_logic_1164.all;
LIBRARY altera_mf;
USE altera_mf.all;
ENTITY pll IS
PORT
(
inclk0 : IN STD_LOGIC := '0';
c0 : OUT STD_LOGIC ;
c1 : OUT STD_LOGIC ;
c2 : OUT STD_LOGIC ;
c3 : OUT STD_LOGIC
);
END pll;
ARCHITECTURE SYN OF pll IS
SIGNAL sub_wire0 : STD_LOGIC_VECTOR (4 DOWNTO 0);
SIGNAL sub_wire1 : STD_LOGIC ;
SIGNAL sub_wire2 : STD_LOGIC ;
SIGNAL sub_wire3 : STD_LOGIC ;
SIGNAL sub_wire4 : STD_LOGIC ;
SIGNAL sub_wire5 : STD_LOGIC ;
SIGNAL sub_wire6 : STD_LOGIC_VECTOR (1 DOWNTO 0);
SIGNAL sub_wire7_bv : BIT_VECTOR (0 DOWNTO 0);
SIGNAL sub_wire7 : STD_LOGIC_VECTOR (0 DOWNTO 0);
COMPONENT altpll
GENERIC (
bandwidth_type : STRING;
clk0_divide_by : NATURAL;
clk0_duty_cycle : NATURAL;
clk0_multiply_by : NATURAL;
clk0_phase_shift : STRING;
clk1_divide_by : NATURAL;
clk1_duty_cycle : NATURAL;
clk1_multiply_by : NATURAL;
clk1_phase_shift : STRING;
clk2_divide_by : NATURAL;
clk2_duty_cycle : NATURAL;
clk2_multiply_by : NATURAL;
clk2_phase_shift : STRING;
clk3_divide_by : NATURAL;
clk3_duty_cycle : NATURAL;
clk3_multiply_by : NATURAL;
clk3_phase_shift : STRING;
compensate_clock : STRING;
inclk0_input_frequency : NATURAL;
intended_device_family : STRING;
lpm_hint : STRING;
lpm_type : STRING;
operation_mode : STRING;
pll_type : STRING;
port_activeclock : STRING;
port_areset : STRING;
port_clkbad0 : STRING;
port_clkbad1 : STRING;
port_clkloss : STRING;
port_clkswitch : STRING;
port_configupdate : STRING;
port_fbin : STRING;
port_inclk0 : STRING;
port_inclk1 : STRING;
port_locked : STRING;
port_pfdena : STRING;
port_phasecounterselect : STRING;
port_phasedone : STRING;
port_phasestep : STRING;
port_phaseupdown : STRING;
port_pllena : STRING;
port_scanaclr : STRING;
port_scanclk : STRING;
port_scanclkena : STRING;
port_scandata : STRING;
port_scandataout : STRING;
port_scandone : STRING;
port_scanread : STRING;
port_scanwrite : STRING;
port_clk0 : STRING;
port_clk1 : STRING;
port_clk2 : STRING;
port_clk3 : STRING;
port_clk4 : STRING;
port_clk5 : STRING;
port_clkena0 : STRING;
port_clkena1 : STRING;
port_clkena2 : STRING;
port_clkena3 : STRING;
port_clkena4 : STRING;
port_clkena5 : STRING;
port_extclk0 : STRING;
port_extclk1 : STRING;
port_extclk2 : STRING;
port_extclk3 : STRING;
width_clock : NATURAL
);
PORT (
clk : OUT STD_LOGIC_VECTOR (4 DOWNTO 0);
inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0)
);
END COMPONENT;
BEGIN
sub_wire7_bv(0 DOWNTO 0) <= "0";
sub_wire7 <= To_stdlogicvector(sub_wire7_bv);
sub_wire4 <= sub_wire0(2);
sub_wire3 <= sub_wire0(0);
sub_wire2 <= sub_wire0(3);
sub_wire1 <= sub_wire0(1);
c1 <= sub_wire1;
c3 <= sub_wire2;
c0 <= sub_wire3;
c2 <= sub_wire4;
sub_wire5 <= inclk0;
sub_wire6 <= sub_wire7(0 DOWNTO 0) & sub_wire5;
altpll_component : altpll
GENERIC MAP (
bandwidth_type => "AUTO",
clk0_divide_by => 25,
clk0_duty_cycle => 50,
clk0_multiply_by => 37,
clk0_phase_shift => "0",
clk1_divide_by => 125,
clk1_duty_cycle => 50,
clk1_multiply_by => 74,
clk1_phase_shift => "0",
clk2_divide_by => 30,
clk2_duty_cycle => 50,
clk2_multiply_by => 37,
clk2_phase_shift => "0",
clk3_divide_by => 120,
clk3_duty_cycle => 50,
clk3_multiply_by => 37,
clk3_phase_shift => "0",
compensate_clock => "CLK0",
inclk0_input_frequency => 37037,
intended_device_family => "Cyclone III",
lpm_hint => "CBX_MODULE_PREFIX=pll",
lpm_type => "altpll",
operation_mode => "NORMAL",
pll_type => "AUTO",
port_activeclock => "PORT_UNUSED",
port_areset => "PORT_UNUSED",
port_clkbad0 => "PORT_UNUSED",
port_clkbad1 => "PORT_UNUSED",
port_clkloss => "PORT_UNUSED",
port_clkswitch => "PORT_UNUSED",
port_configupdate => "PORT_UNUSED",
port_fbin => "PORT_UNUSED",
port_inclk0 => "PORT_USED",
port_inclk1 => "PORT_UNUSED",
port_locked => "PORT_UNUSED",
port_pfdena => "PORT_UNUSED",
port_phasecounterselect => "PORT_UNUSED",
port_phasedone => "PORT_UNUSED",
port_phasestep => "PORT_UNUSED",
port_phaseupdown => "PORT_UNUSED",
port_pllena => "PORT_UNUSED",
port_scanaclr => "PORT_UNUSED",
port_scanclk => "PORT_UNUSED",
port_scanclkena => "PORT_UNUSED",
port_scandata => "PORT_UNUSED",
port_scandataout => "PORT_UNUSED",
port_scandone => "PORT_UNUSED",
port_scanread => "PORT_UNUSED",
port_scanwrite => "PORT_UNUSED",
port_clk0 => "PORT_USED",
port_clk1 => "PORT_USED",
port_clk2 => "PORT_USED",
port_clk3 => "PORT_USED",
port_clk4 => "PORT_UNUSED",
port_clk5 => "PORT_UNUSED",
port_clkena0 => "PORT_UNUSED",
port_clkena1 => "PORT_UNUSED",
port_clkena2 => "PORT_UNUSED",
port_clkena3 => "PORT_UNUSED",
port_clkena4 => "PORT_UNUSED",
port_clkena5 => "PORT_UNUSED",
port_extclk0 => "PORT_UNUSED",
port_extclk1 => "PORT_UNUSED",
port_extclk2 => "PORT_UNUSED",
port_extclk3 => "PORT_UNUSED",
width_clock => 5
)
PORT MAP (
inclk => sub_wire6,
clk => sub_wire0
);
END SYN;
-- ============================================================
-- CNX file retrieval info
-- ============================================================
-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "25"
-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "125"
-- Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "30"
-- Retrieval info: PRIVATE: DIV_FACTOR3 NUMERIC "120"
-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE2 STRING "50.00000000"
-- Retrieval info: PRIVATE: DUTY_CYCLE3 STRING "50.00000000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "39.959999"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "15.984000"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "33.299999"
-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE3 STRING "8.325000"
-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0"
-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT2 STRING "ps"
-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT3 STRING "ps"
-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK2 STRING "0"
-- Retrieval info: PRIVATE: MIRROR_CLK3 STRING "0"
-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "37"
-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "74"
-- Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "37"
-- Retrieval info: PRIVATE: MULT_FACTOR3 NUMERIC "37"
-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "40.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "16.00000000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "33.33333300"
-- Retrieval info: PRIVATE: OUTPUT_FREQ3 STRING "8.33250000"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE2 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE3 STRING "0"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 STRING "MHz"
-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT3 STRING "MHz"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT2 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT3 STRING "0.00000000"
-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "deg"
-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT3 STRING "deg"
-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
-- Retrieval info: PRIVATE: SPREAD_USE STRING "0"
-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK2 STRING "1"
-- Retrieval info: PRIVATE: STICKY_CLK3 STRING "1"
-- Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
-- Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
-- Retrieval info: PRIVATE: USE_CLK0 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK1 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK2 STRING "1"
-- Retrieval info: PRIVATE: USE_CLK3 STRING "1"
-- Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA2 STRING "0"
-- Retrieval info: PRIVATE: USE_CLKENA3 STRING "0"
-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
-- Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "25"
-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "37"
-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "125"
-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "74"
-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "30"
-- Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "37"
-- Retrieval info: CONSTANT: CLK2_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: CLK3_DIVIDE_BY NUMERIC "120"
-- Retrieval info: CONSTANT: CLK3_DUTY_CYCLE NUMERIC "50"
-- Retrieval info: CONSTANT: CLK3_MULTIPLY_BY NUMERIC "37"
-- Retrieval info: CONSTANT: CLK3_PHASE_SHIFT STRING "0"
-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037"
-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
-- Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_USED"
-- Retrieval info: CONSTANT: PORT_clk4 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clk5 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena2 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena4 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_clkena5 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk0 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk1 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk2 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: PORT_extclk3 STRING "PORT_UNUSED"
-- Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
-- Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]"
-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
-- Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
-- Retrieval info: USED_PORT: c2 0 0 0 0 OUTPUT_CLK_EXT VCC "c2"
-- Retrieval info: USED_PORT: c3 0 0 0 0 OUTPUT_CLK_EXT VCC "c3"
-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
-- Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
-- Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
-- Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
-- Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
-- Retrieval info: CONNECT: c2 0 0 0 0 @clk 0 0 1 2
-- Retrieval info: CONNECT: c3 0 0 0 0 @clk 0 0 1 3
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.vhd TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
-- Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.vhd FALSE
-- Retrieval info: LIB_FILE: altera_mf
-- Retrieval info: CBX_MODULE_PREFIX: ON

View File

@@ -0,0 +1,6 @@
pll_inst : pll PORT MAP (
inclk0 => inclk0_sig,
c0 => c0_sig,
c1 => c1_sig,
c2 => c2_sig
);

View File

@@ -0,0 +1,119 @@
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
-- This is input-only for the time being
entity ps2_intf is
generic (filter_length : positive := 8);
port(
CLK : in std_logic;
nRESET : in std_logic;
-- PS/2 interface (could be bi-dir)
PS2_CLK : in std_logic;
PS2_DATA : in std_logic;
-- Byte-wide data interface - only valid for one clock
-- so must be latched externally if required
DATA : out std_logic_vector(7 downto 0);
VALID : out std_logic;
error : out std_logic
);
end ps2_intf;
architecture ps2_intf_arch of ps2_intf is
--subtype filter_t is std_logic_vector(filter_length-1 downto 0);
--signal clk_filter : filter_t;
signal clk_filter : std_logic_vector(7 downto 0);
signal ps2_clk_in : std_logic;
signal ps2_dat_in : std_logic;
-- Goes high when a clock falling edge is detected
signal clk_edge : std_logic;
signal bit_count : unsigned (3 downto 0);
signal shiftreg : std_logic_vector(8 downto 0);
signal parity : std_logic;
begin
-- Register input signals
process(nRESET, CLK)
begin
if nRESET = '0' then
ps2_clk_in <= '1';
ps2_dat_in <= '1';
clk_filter <= (others => '1');
clk_edge <= '0';
elsif rising_edge(CLK) then
-- Register inputs (and filter clock)
ps2_dat_in <= PS2_DATA;
clk_filter <= PS2_CLK & clk_filter(7 downto 1);
clk_edge <= '0';
if clk_filter = x"ff" then
-- Filtered clock is high
ps2_clk_in <= '1';
elsif clk_filter = x"00" then
-- Filter clock is low, check for edge
if ps2_clk_in = '1' then
clk_edge <= '1';
end if;
ps2_clk_in <= '0';
end if;
end if;
end process;
-- Shift in keyboard data
process(nRESET, CLK)
begin
if nRESET = '0' then
bit_count <= (others => '0');
shiftreg <= (others => '0');
parity <= '0';
DATA <= (others => '0');
VALID <= '0';
error <= '0';
elsif rising_edge(CLK) then
-- Clear flags
VALID <= '0';
error <= '0';
if clk_edge = '1' then
-- We have a new bit from the keyboard for processing
if bit_count = 0 then
-- Idle state, check for start bit (0) only and don't
-- start counting bits until we get it
parity <= '0';
if ps2_dat_in = '0' then
-- This is a start bit
bit_count <= bit_count + 1;
end if;
else
-- Running. 8-bit data comes in LSb first followed by
-- a single stop bit (1)
if bit_count < 10 then
-- Shift in data and parity (9 bits)
bit_count <= bit_count + 1;
shiftreg <= ps2_dat_in & shiftreg(shiftreg'high downto 1);
parity <= parity xor ps2_dat_in; -- Calculate parity
elsif ps2_dat_in = '1' then
-- Valid stop bit received
bit_count <= (others => '0'); -- back to idle
if parity = '1' then
-- Parity correct, submit data to host
DATA <= shiftreg(7 downto 0);
VALID <= '1';
else
-- Error
error <= '1';
end if;
else
-- Invalid stop bit
bit_count <= (others => '0'); -- back to idle
error <= '1';
end if;
end if;
end if;
end if;
end process;
end ps2_intf_arch;

View File

@@ -0,0 +1,514 @@
:020000040000FA
:20000000C901F01F60EA600E01424153494300284329313938322041636F726E0A0D00005A
:20002000800000A98420F4FF86068407A98320F4FF8418A200861F8E02048E0304CA86232B
:20004000A20A8E0004CA8E0104A9012511050D050E050F0510D00CA941850DA952850EA948
:2000600057850FA9028D0202A9B48D0302584CDD8A414E4480004142539400414353950036
:20008000414456414C9600415343970041534E980041544E99004155544FC61042474554CD
:2000A0009A0142505554D503434F4C4F5552FB0243414C4CD602434841494ED702434852B4
:2000C00024BD00434C454152D801434C4F5345D903434C47DA01434C53DB01434F539B00BE
:2000E000434F554E549C0144415441DC204445479D00444546DD0044454C455445C71044DD
:200100004956810044494DDE0244524157DF02454E4450524F43E101454E44E001454E5668
:20012000454C4F5045E202454C53458B144556414CA00045524C9E014552524F52850445FC
:200140004F46C501454F5282004552529F01455850A100455854A201464F52E30246414C92
:200160005345A301464EA408474F544FE51247455424BE00474554A500474F535542E41216
:2001800047434F4CE60248494D454D9343494E505554E8024946E702494E4B455924BF00B7
:2001A000494E4B4559A600494E54A800494E53545228A7004C495354C9104C494E45860064
:2001C0004C4F4144C8024C4F4D454D92434C4F43414CEA024C4546542428C0004C454EA9D0
:2001E000004C4554E9044C4F47AB004C4EAA004D49442428C1004D4F4445EB024D4F448300
:20020000004D4F5645EC024E455854ED024E4557CA014E4F54AC004F4C44CB014F4EEE0201
:200220004F464687004F5284004F50454E494E8E004F50454E4F5554AE004F50454E555031
:20024000AD004F53434C49FF025052494E54F1025041474590435054528F435049AF0150A5
:200260004C4F54F002504F494E5428B00050524F43F20A504F53B10152455455524EF8018E
:20028000524550454154F5005245504F5254F60152454144F30252454DF42052554EF901DD
:2002A000524144B200524553544F5245F71252494748542428C200524E44B30152454E552A
:2002C0004D424552CC1053544550880053415645CD0253474EB40053494EB500535152B673
:2002E00000535043890053545224C300535452494E472428C400534F554E44D40253544F73
:2003000050FA0154414EB7005448454E8C14544FB800544142288A005452414345FC125474
:20032000494D45914354525545B901554E54494CFD02555352BA00564455EF0256414CBB57
:200340000056504F53BC015749445448FE0250414745D000505452CF0054494D45D1004C1A
:200360004F4D454DD20048494D454DD3007847C0B4FC036AD4339EDA076F8DF7C29FA6E935
:200380009146CA95B9ADE278D1FEA8D1807CCB416DB1498898B4BEDCC4D22F76BDBF26CC99
:2003A00039EE94C2B8AC31249CDAB6A3F32A3083C96F5D4C58D22A8D99BDC47D7D2FE8C8B3
:2003C0005672C488CC7AC244E4239AE495152FF19A041F7DE4E4E6B611D08E95B1A0C2BFFA
:2003E000BFAEAEAEAFADA8ABACA8A9BFA9AEABAFAFABAABFAEB1AFACACACAEA7ABACBFBF19
:20040000ABABABABAFABA9A7A6AEACABACABB3AFB0AFB0AFB0B0AC908FBFB58A8A8FBE98CC
:20042000BF92929292B4BF8EBF92BF8E8E8B8B91938A93B4B7B8B89398BA8B939393B6B9BE
:2004400094938D93BB8BBBBFBAB8BD8A9392BBB4BE4B83848996B8B9D8D9F001108190895C
:2004600093A3A4A93839780113216373B1A9C50CC3D3C4F24183B081436C72ECF2A3C3181C
:200480001934B072989981989914350A0D0D0D0D1010252539414141414A4A4C4C4C5050C4
:2004A0005253535308080809090A0A0A05153E040D304C0632494910250E0E09292A3030ED
:2004C0004E4E4E3E160018D858B8CA88E8C8EA48086828406038F878AAA8BA8A9A9890B0C2
:2004E000F030D010507021410161C1A1E106462666C6E6E0C0204C20A2A0818684A9FF858B
:20050000284CA38BA903852820978AC95DF0EE206D98C60A20BA85C60AA5284A9060A51EAD
:200520006904853FA5382045B5A5372062B5A2FCA4391002A4368438F01CA000E8D00D20CC
:2005400025BCA63F2065B5CAD0FAA2FDB13A2062B5C8C638D0E6E8100C2065B52058B5203F
:2005600058B54C5685A000B10BC93AF00AC90DF00A200EB5C8D0F0C40A90F62025BCA40AB0
:2005800088C8B10BC93AF004C90DD0F520599888B10BC93AF00CA50CC907D0034CF68A2029
:2005A00090984C0885208295F05AB0582094BD203AAE852720B4B4202788A20320978AA0AF
:2005C00000843DC93AF064C90DF060C95CF05CC92EF0D2C60AA40AE60AB10B302AC920F056
:2005E00010A0050A0A0A0A263D263E88D0F8CAD0E4A23AA53DDD5084D007BC8A84C43EF087
:200600001FCAD0F14C2A98A222C980F013E8C982F00EE8C984D0EDE60AC8B10BC941D0E4BD
:20062000BDC4848529A001E01AB048AD400485378439A628E004AE410486389006AD3C0424
:20064000AE3D04853A863B98F0281004A436F02288B9290024391003B90006913AEE4004E5
:20066000D003EE41049008EE3C04D003EE3D0498D0DE60E022B04020218818A52AED400433
:20068000A8A52BED4104C00188E900F025C9FFF01CA5284AF00F00014F7574206F662072BF
:2006A000616E676500A8842AA0024C2B869830F610DF9810F130DAE029B01820978AC9235C
:2006C000D018202F88202188A52BF0DC00024279746500E036D06820978AC928D037202198
:2006E0008820978AC929D01320978AC92CD01E202C8820978AC959D014F0CDC92CD00E206D
:20070000978AC958D00720978AC929F0BB0003496E64657800C60A20218820978AC92CD048
:2007200014202C8820978AC958F00AC959D0DE202F884C9A87203288A52BD0F34CA886E09A
:200740002FB02BE02DB00920978AC941F019C60A20218820978AC92CD0DE202C8820978AE3
:20076000C958F0D44C0D87203288A001D02EE032B016E031F00C20978AC923D0034CC586BF
:20078000C60A2021884C3587E033F00BB02420978AC928F00AC60A202188A0034C2B862051
:2007A0002C88202C8820218820978AC929F0EB4C0D87E039B05DA53D4901291F48E037B051
:2007C0002F20978AC923D004684CC586C60A20218868853720978AC92CF0034C3587209745
:2007E0008A291FC537D006202C884C35874C0D8720218868853720978AC92CD01320978A52
:20080000291FC537D0E7202C88A52BF0034CCC864C3887D025202188A52A8528A0004C2B4C
:2008200086201D9B20F092A41B840A60202F88203288A529186904852960A201A40AE60AB8
:20084000B10BC942F012E8C957F00DA204C944F007C953F0154C2A988A48202188A229206B
:2008600044BE68A84C2B864C0E8CA52848201D9BD0F5688528202788A0FFD0E84818986539
:20088000378539A000986538853A689137C8B1399137C90DD0F760290F853D843EC8B137BC
:2008A000C93AB036C9309032290F48A63EA53D0A263E30210A263E301C653D853D8A653E44
:2008C000063D2A3010B00E853E68653D853D90CDE63E10C94868A000386088A98D207C88FA
:2008E000A53769028539A5386900853AB137913988D0F9A003A53E0940913788A53D293F82
:200900000940913788A53D29C0853DA53E29C04A4A053D4A4A49549137204489204489201C
:200920004489A0001860C97BB0FAC95FB00EC95BB0F2C941B006C93AB0EAC93060C92ED0BB
:20094000F560B137E637D002E63860204489B13760A000843B843CB137C90DF0EDC920D045
:2009600005204489D0F1C926D012204B89203689B0F8C94190E1C94790F0B0DBC922D00C1B
:20098000204B89C922F0DAC90DD0F560C93AD006843B843CF0CBC92CF0C7C92AD005A53B4C
:2009A000D04160C92EF00E2036899033A63CF0052097889034B137203D8990062044894CB8
:2009C000B589A2FF863B843C4C57892026899013A000B13720268990E92044894CD289C9EC
:2009E00041B009A2FF863B843C4C6189C958B0DBA2718639A280863AD13990D6D00FC8B17D
:200A0000393034D137F0F7B137C92EF00BC8B13910FBC9FED00FB0B8C8B139301AE639D0BA
:200A2000F8E63AD0F438C898653985399002E63AA000B1374CF889AAC8B139853D884A905F
:200A400007B137202689B0888A243D5007A63BD00318694088207C88A000A2FFA53D4A4A86
:200A60009004863B843C4A9004843B843C4A901148C8B13720268990062044894C728A88FF
:200A8000684A9002863C4AB00D4C6189A41BE61BB119C920F0F660A40AE60AB10BC920F027
:200AA000F66000054D697373696E67202C00208C8AC92CD0ED60205798A5188538A90085B6
:200AC000379137206FBED02B205798206FBED026205798000053544F5000205798A90DA4BF
:200AE000188413A000841284209112A9FFC89112C884122020BDA007840CA000840BA9331A
:200B00008516A9B48517A93E2002BCA9338516A9B48517A2FF8628863C9A203ABDA8A50BF2
:200B20008537A50C8538843B840A20578920DF979006208DBC4CF38A20978AC9C6B072905E
:200B40007E4CF68A4C0485BAE0FCB00DADFF01C9A4D006201D9B4C4C9800074E6F20A400A3
:200B6000A40A88B10BC93DF0DEC92AF006C95BF0D3D023206D98A60BA40C20F7FFA90DA4F6
:200B80000A88C8D10BD0FBC98BF0F2A50CC907F0B0209098D00DC60A205798A000B10BC9D4
:200BA0003AD0E4A40AE60AB10BC920F0F6C9CF900EAABDDF828537BD518385386C3700A6CD
:200BC0000B8619A60C861A841B20DD95D01BB090861B20419820FC94A205E42CD001E820E3
:200BE0003195C60A208295F02290102094BD201398A527D019201E8C4C9B8B2094BD2013A5
:200C000098A527F00920B4B44C9B8B4C2A98000654797065206D69736D617463680020EA47
:200C2000BDA52CC980F07BA002B12AC536B055A502852CA503852DA536C908900669079001
:200C400002A9FF1848AAB12AA000712A4502D00FC8712A4503D008852D8AC838F12AAA8A96
:200C6000186502A8A5036900C404AAE505B0488402860368A002912A88A52DF007912A8880
:200C8000A52C912AA003A536912AF0158888B12A852D88B12A852CB90006912CC8C436D0CB
:200CA000F66020BABEC000F00BB90006912A88D0F8AD0006912A6000004E6F20726F6F6D59
:200CC00000A539C980F027903AA000B104AAF015B137E9018539C8B137E900853AB10491DA
:200CE00039C8CAD0F8A104A00391374CDCBDA000B104AAF00AC8B104889137C8CAD0F6A9A5
:200D00000DD0E6A000B1049137C8C439B018B1049137C8B1049137C8B1049137C8C439B0EA
:200D200005B1049137C898184CE1BDC60A20A9BF9848208C8AC92CD03E20299B2085A368CA
:200D4000A8A52720D4FFAAF01B300CA203B52A20D4FFCA10F830D9A204BD6C0420D4FFCA59
:200D600010F730CCA53620D4FFAAF0C4BDFF0520D4FFCAD0F7F0B968840A4C988B2025BCF0
:200D80004C968BA9008514851520978AC93AF0F0C90DF0ECC98BF0E8D03820978AC923F0E3
:200DA0008AC60A4CBB8DAD0004F010A51EF00CED0004B0F9A82065B5C8D0FA18AD00048579
:200DC00014661520978AC93AF0B3C90DF0AFC98BF0ABC97EF0EBC92CF0CCC93BF0A520703D
:200DE0008E90E0A51448A51548C61B20299B688515688514A51B850A98F01320DF9EA514EA
:200E000038E5369009F007A82065B588D0FAA536F0B1A000B900062058B5C8C436D0F5F03C
:200E2000A24CA28AC92CD0F9A52A482056AE20F092A91F20EEFF6820EEFF2056944C6A8E65
:200E400020DD92208C8AC929D0DAA52AE51EF01AA8B00C2025BCF00320E392A42AF00B207F
:200E600065B588D0FAF0032025BC18A41B840A60A60B8619A60C861AA60A861BC927F0E793
:200E8000C98AF0BCC989F0D0386020978A20708E90F7C922F011386000094D697373696EC3
:200EA000672022002058B5C8B119C90DF0EAC922D0F2C8841BB119C922D0AFF0E7205798EC
:200EC000A910D0082057982028BCA90C20EEFF4C9B8B201D9B20EE922094BDA0008C00061F
:200EE0008CFF06208C8AC92CD022A41B20D595F02AACFF06C8A52A990006C8A52B990006C3
:200F0000C8A52C990006EE00064CE08EC61B20529820EABD201E8FD84C9B8B4C43AEAD0C2C
:200F2000044AAD0404AE6004AC64046C2A004C2A9820DF9790F82094BD20978AC92CD0EE61
:200F400020DF9790E9205798A52A8539A52B853A20EABD202DBC207B98202292A539C52AB3
:200F6000A53AE52BB0ED4CF38AA90A20D8AE20DF972094BDA90A20D8AE20978AC92CD00D50
:200F800020DF97A52BD058A52AF054E60AC60A4C5798A512853BA513853CA5188538A901A1
:200FA00085376020698FA239200DBE206FBE20928FA000B1373030913BC8B137913B3898A9
:200FC000653B853BAAA53C6900853CE406E507B005209F9090DB0000CC20737061636500BF
:200FE0000053696C6C7900209A8FA000B137301DA53A9137A539C8913718A52A653985396E
:20100000A900653A297F853A209F9090DDA518850CA000840BC8B10B3020A004B10BC98D5E
:20102000F01BC8C90DD0F5B10B300FA003B10B18650B850B90E4E60CB0E04CF38A20EB976F
:2010400020928FA000B1373037B13BC8C52BD021B13BC52AD01BB137853D88B137853EA484
:201060000A88A50B8537A50C853820F588A40AD0AB209F90A53B6902853B90C7E63CB0C3F8
:2010800020CFBF4661696C656420617420C8B10B852BC8B10B852A201F992025BCF0CEC882
:2010A000B137653785379003E638186020698FA52A4820EABD2094BD202399A9202002BCDD
:2010C00020EABD205189208DBC2020BD684818652A852A90E0E62B10DC4CF38A4C1892C6F1
:2010E0000A208295F041B03F2094BD20DD92202292A52D052CD03018A52A6502A8A52B658D
:2011000003AAC404E505B0D4A502852AA503852B84028603A900852C852DA940852720B4BA
:20112000B42027884C0B92000A42616420DE0020978A9818650BA60C9002E818E9008537EA
:201140008AE9008538A205863FA60A205995C001F0D5C928F015C924F004C925D00AC63F0B
:20116000C8E8B137C928F0034CDF908439860A206994D0B320FC94A201203195A53F48A93D
:20118000014820D8AE2094BD202188A52B29C0052C052DD09220229268A8A52A9102C8A5F5
:2011A0002B9102C8984820319220978AC92CF0D5C929F0034C279168851568853FA90085A6
:2011C00040203692A000A5159102652A852A9002E62BA5038538A502853718652AA8A52B32
:2011E0006503B034AAC404E505B02D84028603A5376515A8A90085379002E6389137C8D0E8
:2012000002E638C402D0F5E438D0F120978AC92CF0034C968B4C2F91000BDE2073706163F4
:201220006500E62AD00AE62BD006E62CD002E62D60A23F200DBEA200A0004640663F900B4D
:201240001898652AA88A652BAAB00F062A262BA53F0540D0E5842A862B604C279120EB9265
:20126000A52A85068504A52B850785054C9B8B20EB92A52A85008502A52B85018503202F8E
:20128000BDF00720EB92A52B85184C9B8B2057982020BDF0F520DF97B00BC9EEF019C987CC
:2012A000F01E202188205798A52A8521A52B8522A9FF85204C9B8BE60A205798A9FFD0EE38
:2012C000E60A205798A900F0E920EB92A22AA000842EA90220F1FF4C9B8B20AE8A20299B69
:2012E0004CF09220ECADF00F300A60200798A527F00510F64CE4A34C0E8C20ECADF0F830BE
:20130000E94CBEA2A50B8519A50C851AA50A851BA9F22097B12052984C9B8BA003A90091EF
:201320002AF01EBAE0FCB043208295F026200DB3A42C30E72094BDA90020D8AE852720B498
:20134000B4BAFE0601A41B840A20978AC92CF0D34C968B4C988BBAE0FCB00AADFF01C9F240
:20136000D0034C5798000D4E6F20F2000C4E6F7420EA001942616420EB00202188A52A4831
:2013800020DA92205298A91220EEFF4CDA93A911482021882057984CDA93A91648202188D3
:2013A00020579820E7BEE0FFD02DC0FFD029A504C506D0BEA505C507D0B8A62AA98520F4B3
:2013C000FFE40298E50390AAE41298E51390A386068604840784052028BC6820EEFF20569C
:2013E000944C9B8BA904D002A90548201D9B4CFD93202188A52A4820AE8A20299B20EE9202
:201400002094BD20DA92205298A91920EEFF6820EEFF200BBEA53720EEFFA53820EEFF20A5
:201420005694A52B20EEFF4C9B8BA52B20EEFF20978AC93AF01DC90DF019C98BF015C60A3D
:2014400020218820569420978AC92CF0E2C93BD0E1F0D74C968BA52A6C0E02A001B137A054
:20146000F6C9F2F00AA0F8D006A001B1370AA8B90004853AB90104853BA53BF035A000B1C8
:201480003A853CC8B13A853DC8B13AD00D88C439D021C8B012C8B13AF019D137D015C439A6
:2014A000D0F3C8B13AD00C98653A852AA53B6900852B60A53DF0FBA000B13C853AC8B13CCD
:2014C000853BC8B13CD00D88C439D0ADC8B012C8B13CF0A5D137D0A1C439D0F3C8B13CD026
:2014E0009898653C852AA53D6900852B60A001B137AAA9F6E0F2F009A9F8D005A001B13775
:201500000A853AA904853BB13AF00BAA88B13A853A863BC810F1A503913AA50288913A9844
:20152000C89102C439F031C8B1379102C439D0F760A900C89102CAD0FA389865029002E684
:2015400003A403C405900FD004C5049009A900A001913A4CB78C850260A001B137C93090A6
:2015600018C940B00CC93AB010C001F00CE8C8D0EAC95FB005C95B90F460C97B90EF60207C
:20158000319520C995D01DB01B20FC94A205E42CD0EDE8D0EAC921F00CC924F013493FF03B
:2015A00006A9003860A90448E61B20E3924C9F96E61B20E392A52BF006A980852C3860000A
:2015C00008242072616E676500A50B8519A50C851AA40A88C8841BB119C920F0F7C9409044
:2015E000B4C95BB01A0A0A852AA904852BC8B119C8C925D00AA204862CB119C928D066A21C
:2016000005862CA51B186519A61A9002E818E9008537B001CA8638A61BA001B137C941B089
:201620000CC930901CC93AB018E8C8D0EEC95BB004E8C8D0E6C95F9008C97BB004E8C8D04A
:20164000DA88F02FC924F067C925D008C62CC8E8C8B137888439C928F04C206994F0188690
:201660001BA41BB119C921F016C93FF00E18841BA9FF60A9003860A9001860A900F002A96B
:201680000448C8841B202CB320F092A52B48A52A4820E3921868652A852A68652B852B6864
:2016A000852C18A9FF60E8E63920DF964C6196E8C88439C8C62CB137C928F00D206994F070
:2016C000B6861BA981852C3860E88439C62C20DF96A981852C3860000E4172726179002074
:2016E0006994F0F3861BA52C48A52A48A52B48A000B12AC90490759820D8AEA901852D201A
:2017000094BD20DD92E61BE02CD0CCA239200DBEA43C68853868853748A5384820BA9784EF
:201720002DB137853FC8B1378540A52A6539852AA52B653A852B203692A00038B137E52D66
:20174000C903B0BB2094BD2056AE20F092688538688537A239200DBEA43C20BA9718A539C5
:20176000652A852AA53A652B852B90112056AE20F092688538688537A00120BA9768852C31
:20178000C905D017A62BA52A062A262B062A262B652A852A8A652B852B9008062A262B06CB
:2017A0002A262B98652A852A9003E62B18A537652A852AA538652B852B60A52B29C0052C9B
:2017C000052DD00DA52AD137C8A52BF137B002C860000F53756273637269707400E60AA427
:2017E0000AB10BC920F0F6C98DD01AC8B10B0A0AAA29C0C8510B852A8A0A0AC8510B852BA4
:20180000C8840A38601860A50B8519A50C851AA50A851BA41BE61BB119C920F0F6C93DF026
:201820002800044D697374616B65001053796E746178206572726F7200114573636170656B
:2018400000208C8AC93DD0D96020299B8AA41B4C6198A41B4C5998A40A88C8B10BC920F042
:20186000F9C93AF008C90DF004C98BD0BD1898650B850B9002E60CA001840A24FF30B960FA
:2018800020579888B10BC93AF0F5A50CC907F02CC8B10B3027A520F0139848C8B10B488899
:2018A000B10BA86820EAAE20059968A8C83898650B850B9002E60CA001840A604CF68A4C13
:2018C0000E8C201D9BF0F8100320E4A3A41B840AA52A052B052C052DF017E08CF0034CA3F0
:2018E0008BE60A20DF9790F620AFB92077984CD2B8A40AB10BC90DF009C8C98BD0F5840A1C
:20190000F0E14C878BA52AC521A52BE522B0ACA95B2058B5201F99A95D2058B54C65B5A965
:2019200000F002A9058514A204A900953F38A52AFD6B99A8A52BFDB9999008852B842AF690
:201940003FD0EBCA10E3A205CAF004B53FF0F98637A514F00BE537F007A82065B588D0FAD6
:20196000B53F09302058B5CA10F660010A64E810A000843DA518853EA001B13DC52BB00E58
:20198000A003B13D653D853D90EEE63EB0EAD014A002B13DC52A90E8D00A98653D853D90D5
:2019A00003E63E18A0026000124469766973696F6E206279207A65726F0000000327A820C2
:2019C000F092A52D482071AD201D9E8627A820F092688538452D85372071ADA239200DBE04
:2019E000843D843E843F8440A52D052A052B052CF0B5A02088F0410639263A263B263C10EB
:201A0000F32639263A263B263C263D263E263F264038A53DE52A48A53EE52B48A53FE52C1E
:201A2000AAA540E52D900C8540863F68853E68853DB002686888D0C960862720EABD2051A2
:201A4000BD20BEA2201EA2207EBD20B5A34C629A2051BD20429C8627A820FD92207EBD20A3
:201A60004EA3A627A000A53B2980853BA52E2980C53BD01EA53DC530D019A53EC531D013D9
:201A8000A53FC532D00DA540C533D007A541C534D001606A453B2AA901604C0E8C8AF04705
:201AA00030AE2094BD20429CA8F0EF308CA52D4980852D38A000B104E52A852AC8B104E59C
:201AC0002B852BC8B104E52C852CC8B104A0004980E52D052A052B052C0818A904650485A9
:201AE000049002E605286020B2BD20429CA8D0AA8637A636A000B1048539C536B001AA86A6
:201B00003AA000C43AF00AC8B104D9FF05F0F4D004A539C5360820DCBDA6372860A50B85AD
:201B200019A50C851AA50A851B20729BE084F00AE082F021C61BA8852760206B9BA820F07C
:201B400092A003B104192A00992A008810F520FFBDA940D0D7206B9BA820F092A003B104D4
:201B6000592A00992A008810F530E3A820F0922094BD209C9BE080F00160A820F0922094BE
:201B8000BD209C9BA820F092A003B104392A00992A008810F520FFBDA940D0D920429CE090
:201BA0003FB004E03CB00160F016E03EF03AAA209E9AD00188842A842B842C842DA9406055
:201BC000AAA41BB119C93DF00BC93EF012209D9A90E2B0E1E61B209D9AF0D990D7B0D6E67A
:201BE0001B209D9AD0CEF0CDAAA41BB119C93DF009209D9AF0BFB0BC90BBE61B209D9AB021
:201C0000B390B20013537472696E6720746F6F206C6F6E670020B2BD20209EA8D06A188616
:201C200037A000B1046536B0DAAA48A436B9FF059DFF05CA88D0F620CBBD688536A6379871
:201C4000F00320D19DE02BF005E02DF06860A8F0C4303820CE9DA8F02F304CA00018B1043F
:201C6000652A852AC8B104652B852BC8B104652C852CC8B104652D852D18A5046904850432
:201C8000A94090C1E605B0BD4C0E8C2051BD20D19DA8F0F48627300320BEA2207EBD2000A9
:201CA000A5A627A9FFD09E862720EABD2051BD20BEA24C9B9CA8F0D0302720CE9DA8F0C84D
:201CC000303838A000B104E52A852AC8B104E52B852BC8B104E52C852CC8B104E52D4C7783
:201CE0009C2051BD20D19DA8F09E8627300320BEA2207EBD20FDA44CA19C862720EABD20BD
:201D000051BD20BEA2207EBD20D0A44CA19C20BEA220EABD2051BD20BEA24C2C9D20BEA233
:201D20002051BD20209E8627A820FD92207EBD2056A6A9FFA6274CD49D4C0E8CA8F0FA3042
:201D4000DFA52DC52CD0D6A8F004C9FFD0CF452B30CB201D9E8627A8F0DF30B5A52DC52C26
:201D6000D0ACA8F004C9FFD0A5452B30A1A52D482071ADA2392044BE20EABD68452D85371B
:201D80002071ADA000A200843F8440463A663990151898652AA88A652BAAA53F652C853F94
:201DA000A540652D8540062A262B262C262DA539053AD0D7843D863EA53708A23D2056AF90
:201DC0002810032093ADA6274CD49D4C3C9D2094BD20209EE02AF0F3E02FF009E083F02101
:201DE000E081F02660A820FD922051BD20209E8627A820FD92207EBD20ADA6A627A9FFD092
:201E0000D320BE99A538084CBB9D20BE992639263A263B263C243708A2394CBD9D2094BDA1
:201E200020ECAD48A41BE61BB119C920F0F6AA68E05EF00160A820FD922051BD20FA92A5D1
:201E400030C987B0432086A4D00F207EBD20B5A3A54A2012ABA9FFD0CA2081A3A504854B48
:201E6000A505854C20B5A3A54A2012AB207DA3207EBD20B5A32001A820D1AA2094AA20EDC1
:201E8000A72056A6A9FFD09B2081A32099A6D0DC98100320E4A3A200A000B92A0048290F26
:201EA000953F684A4A4A4AE8953FE8C8C004D0EACAF004B53FF0F9B53FC90A900269066908
:201EC000302066A0CA10F0601007A92D852E2066A0A530C981B04E20F4A1C6494CD19EAE72
:201EE0000204E0039002A2008637AD0104F006C90AB0069006E002F002A90A8538854EA981
:201F000000853685492415308798300320BEA220DAA1D0B4A537D005A9304C66A04C9C9F7B
:201F20002099A6D00FC9849010D006A531C9A09008204DA2E6494CD19EA53585272085A302
:201F4000A54E8538A637E002D012654930528538C90B9008A90A8538A90085372086A6A90D
:201F6000A08531A9838530A638F006204DA2CAD0FA20F5A7204EA3A5278542200BA5A530AE
:201F8000C984B00E66316632663366346635E630D0ECA531C9A0B088A538D011C901F04632
:201FA0002086A6A9008549A54E8538E638A901C537F033A449300CC438B02BA9008549C888
:201FC00098D023A537C902F006A901C0FFD017A9302066A0A92E2066A0A930E649F0052070
:201FE00066A0D0F7A980854E2040A0C64ED005A92E2066A0C638D0F0A43788F01888F01180
:20200000A43688B90006C930F0F8C92EF001C88436A549F02AA9452066A0A549100AA92D5A
:202020002066A038A900E5492052A0A537F010A920A44930032066A0E000D0034C66A06009
:20204000A5314A4A4A4A2064A0A531290F85314C97A1A2FF38E8E90AB0FB690A488AF0037F
:202060002064A0680930863BA6369D0006A63BE6366018863520DAA1A9FF60A200863186A9
:202080003286338634863586488649C92EF011C93AB0DFE92F30DB8535C8B119C92ED0087B
:2020A000A548D044E648D0F1C945F035C93AB038E92F9034A631E0189008A648D0DBE64907
:2020C000B0D7A648F002C6492097A16535853590C8E634D0C4E633D0C0E632D0BCE631D0A4
:2020E000B82040A165498549841BA5490548F02F20DAA1F026A9A88530A900852F852E20CB
:2021000003A3A549300BF01020F4A1C649D0F9F007204DA2E649D0F9205CA638A9FF60A55E
:2021200032852D29800531D0CCA535852AA534852BA533852CA9403860204BA149FF386038
:20214000C8B119C92DF0F2C92BD003C8B119C93AB022E92F901E854AC8B119C93AB011E913
:202160002F900DC88543A54A0A0A654A0A654360A54A1860A9001860A53565428535A534A3
:2021800065418534A53365408533A532653F8532A531653E85316048A634A53148A532488B
:2021A000A53348A5350A26342633263226310A2634263326322631653585358A653485341D
:2021C0006865338533686532853268653106352634263326322A85316860A5310532053360
:2021E00005340535F007A52ED009A90160852E8530852F6018A530690385309002E62F206E
:202200001EA22042A22042A22078A1901066316632663366346635E630D002E62F60A52EF0
:20222000853BA52F853CA530853DA531853EA532853FA5338540A5348541A5358542602021
:202240001EA2463E663F6640664166426038A530E9048530B002C62F203FA22008A2203FC0
:20226000A22042A22042A22042A22008A2A900853EA531853FA5328540A5338541A5348548
:2022800042A5352A2008A2A900853E853FA5318540A5328541A5338542A5342A2008A2A5B5
:2022A000322AA531653585359013E634D00FE633D00BE632D007E631D0034C0BA260A20034
:2022C0008635862FA52D10052093ADA2FF862EA52A8534A52B8533A52C8532A52D8531A929
:2022E000A085304C03A3852E8530852F60482086A668F0F81007852EA90038E52E8531A91A
:20230000888530A53130E50532053305340535F0D5A530A43130D5D021A6328631A6338660
:2023200032A6348633A6358634843538E9088530B0E1C62F90DDA43130B206352634263314
:2023400026322631E9008530B0ECC62F90E8A004B14B854188B14B854088B14B853F88B1F7
:202360004B853B888442843CB14B853D053B053F05400541F004A53B0980853E60A971D00D
:2023800006A976D002A96C854BA904854CA000A530914BC8A52E2980852EA531297F052EEA
:2023A000914BA532C8914BA533C8914BA534C8914B6020F5A7A004B14B853488B14B85331C
:2023C00088B14B853288B14B852E88B14B85308435842F052E053205330534F004A52E093B
:2023E0008085316020FEA3A531852DA532852CA533852BA534852A60201EA24C86A6A530D9
:2024000010F62053A420DAA1D032F05CA530C9A0B054C999B02669088530A5408541A53F87
:202420008540A53E853FA534853EA5338534A5328533A5318532A9008531F0D046316632B9
:2024400066336634663E663F66406641E630D0BC4C6CA6A900853B853C853D853E853F85BB
:20246000408541854260D0E8A52E101938A900E5348534A900E5338533A900E5328532A92F
:2024800000E531853160A5303007A900854A4CDAA120FEA3A534854A20E8A4A9808530A62C
:2024A000311010452E852E1005E64A4CB0A4C64A206CA44C03A3E634D00CE633D008E6328F
:2024C000D004E631F08A60206CA420B6A44C6CA420FDA44C7EAD204EA3208DA3A53B852E05
:2024E000A53C852FA53D8530A53E8531A53F8532A5408533A5418534A542853560207EADF4
:20250000204EA3F0F7200BA54C5CA620DAA1F0CCA00038A530E53DF0779037C925B0DD488E
:202520002938F0194A4A4AAAA5418542A5408541A53F8540A53E853F843ECAD0EB68290722
:20254000F04EAA463E663F664066416642CAD0F3F03E38A53DE530C925B081482938F019BA
:202560004A4A4AAAA5348535A5338534A5328533A53185328431CAD0EB682907F00EAA46D3
:20258000316632663366346635CAD0F3A53D8530A52E453B1049A531C53ED01BA532C53F35
:2025A000D015A533C540D00FA534C541D009A535C542D0034C86A6B02A38A542E5358535C9
:2025C000A541E5348534A540E5338533A53FE5328532A53EE5318531A53B852E4C03A31890
:2025E0004C08A238A535E5428535A534E5418534A533E5408533A532E53F8532A531E53EDA
:2026000085314C03A36020DAA1F0FA204EA3D0034C86A618A530653D9003E62F18E97F8595
:2026200030B002C62FA205A000B53095429430CAD0F7A52E453B852EA020463E663F6640D6
:202640006641664206462645264426439004182078A188D0E5602006A62003A3A535C9806A
:20266000901AF012A9FF20A4A24C7CA60014546F6F2062696700A53409018534A90085359B
:20268000A52FF01410E6A900852E852F853085318532853385348535602086A6A08084318E
:2026A000C8843098602085A32099A6D03A20DAA1F009201EA220B5A3D037604CA79920FAFC
:2026C0009220D3A9A54A4820E9A7208DA3E64A209EA920E9A720D6A468854A209EA920E90D
:2026E000A720E7A6A9FF6020DAA1F0AC204EA3F0CAA52E453B852E38A530E53DB003C62F9F
:2027000038698085309003E62F18A220B018A531C53ED010A532C53FD00AA533C540D0047A
:20272000A534C5419019A534E5418534A533E5408533A532E53F8532A531E53E85313826E5
:20274000462645264426430634263326322631CAD0BAA207B018A531C53ED010A532C53F5A
:20276000D00AA533C540D004A534C5419019A534E5418534A533E5408533A532E53F853227
:20278000A531E53E85313826350634263326322631CAD0C00635A5468534A5458533A544F1
:2027A0008532A54385314C59A600152D766520726F6F740020FA9220DAA1F02A30EB208557
:2027C000A3A5304A69408530A905854A20EDA7208DA3A96C854B20ADA6A971854B2000A551
:2027E000C630C64AD0E9A9FF60A97BD00AA971D006A976D002A96C854BA904854C6020FA56
:202800009220DAA1F002100C00164C6F672072616E6765002053A4A080843B843EC8843DD7
:20282000A630F006A531C9B59002E8888A4884302005A5A97B2087A3A973A0A82097A820D5
:20284000E9A72056A62056A62000A52085A36838E98120EDA2A96E854BA9A8854C2056A6C5
:2028600020F5A72000A5A9FF607F5E5BD8AA80317217F8067A1238A50B88790E9FF37C2A22
:20288000AC3FB5863401A27A7F638E37EC823FFFFFC17FFFFFFFFF854D844E2085A3A000A7
:2028A000B14D8548E64DD002E64EA54D854BA54E854C20B5A320F5A720ADA618A54D69056F
:2028C000854D854BA54E6900854E854C2000A5C648D0E26020DAA84C27A920FA9220DAA16C
:2028E0001008462E20EAA84C16A92081A320B1A920DAA1F00920F1A720ADA64C0AA920559E
:20290000AA20B5A3A9FF6020FA9220DAA1F0F5100A462E201BA9A980852E60A530C9819004
:202920001520A5A62036A92048AA2000A5204CAA2000A54C7EADA530C97390C82081A32022
:2029400053A4A980853D853E853B2005A5A95AA0A92097A820D1AAA9FF600985A359E86721
:20296000801C9D07368057BB78DF80CA9A0E83848CBBCA6E81959606DE810AC76C527F7DE4
:20298000AD90A182FB62572F806D63382C20FA9220D3A9E64A4C9EA920FA9220D3A9A54AFE
:2029A0002902F00620AAA94C7EAD464A901520C3A92085A32056A6208DA32099A620D0A4A4
:2029C0004CB7A72081A32056A6A972A0AA2097A84CD1AAA530C998B05F2085A32055AA2096
:2029E0004EA3A52E853BC63D2005A520E7A620FEA3A534854A053305320531F038A9A085D5
:202A000030A0008435A531852E1003206CA42003A3207DA32048AA2056A620F5A72000A5AC
:202A2000208DA320EDA720B5A3204CAA2056A620F5A74C00A54CB2A3001741636375726134
:202A40006379206C6F737400A959D002A95E854BA9AA854C60A963D0F581C91000006F15DA
:202A6000777A6181490FDAA27B0EFA351286652EE0D305848AEA0C1B841ABEBB2B843745B3
:202A800055AB82D555577C83C0000005810000000020FA92A530C987901ED006A431C0B351
:202AA0009016A52E10062086A6A9FF6000184578702072616E6765002086A420DAAA208132
:202AC000A3A9E4854BA9AA854C20B5A3A54A2012AB20F1A72056A6A9FF60A9E9A0AA20971F
:202AE000A8A9FF60822DF854580783E020865B82805393B883200006A1820000216382C036
:202B0000000002828000000C81000000008100000000AA1009CA8A49FF4820A5A6684820C1
:202B200085A32099A668F00A38E901482056A64C25AB6020E392A62AA98020F4FF8A4CEA49
:202B4000AE20DD922094BD20AE8A2056AE20F092A52A48A52B4820EABD68852D68852CA2DE
:202B60002AA90920F1FFA52E30334CD8AEA98620F4FF8A4CD8AEA98620F4FF984CD8AE20F7
:202B8000DAA1F01E101A301520ECADF05930F0A52D052C052B052AF00CA52D10034CC4AC1C
:202BA000A9014CD8AEA9406020FEA7A069A9A8D00720FA92A068A9AA844B854C2056A6A9EE
:202BC000FF6020FA92A06DA9AAD0ED20FEA8E630A86020E392201E8F852A862B842C086807
:202BE000852DD8A940604C0E8C20ECADD0F8E636A436A90D99FF0520B2BDA51948A51A48B6
:202C0000A51B48A404A605C884198437D001E8861A8638A0FF843BC8841B20558920299B7B
:202C200020DCBD68851B68851A688519A5276020ECADD067A436A900990006A51948A51AC3
:202C400048A51B48A900851BA9008519A906851A208C8AC92DF00FC92BD003208C8AC61B3D
:202C6000207BA04C73AC208C8AC61B207BA09003208FAD85274C23AC20ECADF01E101BA50F
:202C80002E0820FEA328100DA53E053F05400541F00320C7A420E7A3A940604C0E8C20ECE3
:202CA000ADD0F8A536F01DAD00064CD8AE20ADAFC000D0108A4CEAAE20B5BFAAA97F20F42E
:202CC000FF8AF0E6A9FF852A852B852C852DA9406020E392A203B52A49FF952ACA10F7A948
:202CE000406020299BD0B4E02CD018E61B20B2BD20299BD0A6A901852AE61BE029F013E0A8
:202D00002CF0034CA28A20B2BD2056AE20F09220CBBDA000A62AD002A201862A8ACA862D83
:202D200018650485379865058538B10438E52D9021E536901D6900852B20DCBDA000A636D1
:202D4000F00BB137D90006D010C8CAD0F5A52A4CD8AE20DCBDA900F0F6E62AC62BF0F6E6C4
:202D600037D0D9E638D0D54C0E8C20ECADF0F83006242D301E103320DAA1100D300520DA2A
:202D8000A1F006A52E4980852EA9FF602002AEF0D630EB38A900A8E52A852A98E52B852BF5
:202DA00098E52C852C98E52D852DA94060208C8AC922F015A200B1199D0006C8E8C90DF069
:202DC00004C92CD0F1884CE1ADA200C8B119C90DF017C89D0006E8C922D0F1B119C922F022
:202DE000EACA8636841BA900604C988EA41BE61BB119C920F0F6C92DF092C922F0CBC92BDE
:202E0000D003208C8AC98E9007C9C6B0364CB18BC93FB00CC92EB012C926F051C928F036FA
:202E2000C61B20DD95F0094C2CB3207BA0901460A5282902D00DB00B861BAD4004AC4104A9
:202E40004CEAAE001A4E6F2073756368207661726961626C650020299BE61BE029D002A816
:202E600060001B4D697373696E67202900A200862A862B862C862DA41BB119C9309023C94E
:202E80003A900AE937C90A9019C910B0150A0A0A0AA2030A262A262B262C262DCA10F4C871
:202EA000D0D78A1005841BA94060001C4261642048455800A22AA000A90120F1FFA940604D
:202EC000A900A4184CEAAE4C43AEA900F00A4C0E8C20ECADD0F8A536A000F00EA41BB11960
:202EE000C950D0E3E61BA512A413852A842BA900852C852DA94060A51E4CD8AEA500A40105
:202F00004CEAAEA506A4074CEAAEE61B2056AE20F092A52D3029052C052BD008A52AF04C5D
:202F2000C901F04520BEA22051BD2069AF207EBD2006A62003A320E4A3202292A94060A259
:202F40000D2044BEA940851160A41BB119C928F0B92087AFA20DB500852AB501852BB502BA
:202F6000852CB503852DA940602087AFA200862E862F8635A9808530B50D9531E8E004D0CF
:202F8000F72059A6A9FF60A020A50F4A4A4A45116A260D260E260F2610261188D0EB60A4B1
:202FA00009A5084CEAAEA000B1FD4CEAAE20E392A981A62AA42B4CF4FF20E0FF4CD8AE20B7
:202FC000E0FF8D0006A9018536A9006020299BD062E02CD061E61B20B2BD2056AE20F09268
:202FE00020CBBDA52AC536B0028536A9006020299BD040E02CD03FE61B20B2BD2056AE2006
:20300000F09220CBBDA53638E52A9017F017AAA52A8536F010A000BD0006990006E8C8C60A
:203020002AD0F4A9006020ADAF8AC000F094A9008536604C0E8C4CA28A20299BD0F5E02C78
:20304000D0F420B2BDE61B20DD92A52A48A9FF852AE61BE029F00AE02CD0DB2056AE20F030
:203060009220CBBD68A818F006E536B0C18898852CAAA000A53638E52CC52AB002852AA538
:203080002AF0ABBD0006990006C8E8C42AD0F48436A90060208C8AA0FFC97EF004A000C66E
:2030A0001B984820ECADF017A8688515AD0304D008853720F99EA9006020DF9EA900604CB1
:2030C0000E8C20DD922094BD20AE8A2056AED0EF20EABDA436F01EA52AF01DC62AF016A2F8
:2030E00000BD0006990006E8C8F010E43690F2C62AD0EC8436A900608536604C039C6885C0
:203100000C68850B001D4E6F207375636820A42FF200A518850CA900850BA001B10B30DE27
:20312000A003C8B10BC920F0F9C9DDF00FA003B10B18650B850B90E2E60CB0DEC8840A2012
:20314000978A98AA18650BA40C9002C818E900853C98E900853DA000C8E8B13CD137D0CD93
:20316000C439D0F4C8B13C202689B0C18AA8206D9820ED94A201203195A000A50B9102C86D
:20318000A50C91022039954CF4B1001E4261642063616C6C00A9A48527BA8A186504202E1F
:2031A000BEA0008A9104E8C8BD00019104E0FFD0F59AA52748A50A48A50B48A50C48A51B95
:2031C000AA186519A41A9002C818E901853798E9008538A002205B95C002F0AE861B8884DC
:2031E00039205B94D0034C12B1A000B12A850BC8B12A850CA90048850A20978AC928F04D77
:20320000C60AA51B48A51948A51A4820A38B68851A68851968851B68F00C853F200BBE2035
:20322000C18CC63FD0F668850C68850B68850A68A000B104AA9AC8E8B1049D0001E0FFD0DB
:20324000F598650485049002E605A52760A51B48A51948A51A48208295F05AA51B850A68F9
:20326000851A68851968851B68AAA52C48A52B48A52A48E88A48200DB320978AC92CF0CDBA
:20328000C929D031A90048208C8AC928D02720299B2090BDA527852D2094BD68AAE88A4820
:2032A000208C8AC92CF0E7C929D00A6868854D854EE44DF015A2FB9A68850C68850B001F4E
:2032C000417267756D656E74730020EABD68852A68852B68852C3021A52DF0D98527A237B8
:2032E0002044BEA5271009207EBD20B5A34CF3B220EABD20B7B44C03B3A52DD0B820CBBDAD
:2033000020218CC64DD0C3A54E484C02B2A42CC004D005A2372044BE202CB3082090BD28FF
:20332000F0073005A2372056AF4C94BDA42C3054F01DC005F01EA003B12A852D88B12A857A
:203340002C88B12AAA88B12A852A862BA94060B12A4CEAAE88B12A853488B12A853388B1F9
:203360002A853288B12A852E88B12A85308435842F052E053205330534F004A52E09808522
:2033800031A9FF60C080F01FA003B12A8536F016A001B12A853888B12A8537A43688B137C4
:2033A00099000698D0F760A52BF015A000B12A990006490DF004C8D0F49884366020E392A3
:2033C000A52A4CC2AFA00084088409A61886388437A60CE007F02AA60B204289C90DD01963
:2033E000E437A50CE53890192042890900301285092042898508204289E437A50CE538B07B
:20340000D86020C5B38420B1FDD008A9338516A9B48517A516850BA517850C203ABDAA8663
:203420000AA9DA20F4FFA97E20F4FFA2FF86289A4CA38BF63AE79EF122206174206C696E2F
:203440006520223B9E3AE08BF13AE00D202188A203A52A48A52B488A4820DA9268AACAD088
:20346000F0205298A52A853DA52B853EA007A205D01D202188A20DA52A488A4820DA92689E
:20348000AACAD0F3205298A52A8544A20CA008689537CA10FA98A237A00020F1FF4C9B8B62
:2034A000202188205298A42A8884234C9B8B4C0E8C20299B200BBEA539C905F023A527F09C
:2034C000ED100320E4A3A000A52A9137A539F00FA52BC89137A52CC89137A52DC8913760AE
:2034E000A527F0CA300320BEA2A000A5309137C8A52E2980852EA531297F052E9137C8A579
:20350000329137C8A5339137C8A5349137608537C9809044A9718538A9808539843AA0008B
:20352000C8B13810FBC537F00DC898386538853890ECE639B0E8A000B13830062058B5C8FD
:20354000D0F6A43A60484A4A4A4A2050B568290FC90A900269066930C90DD00B20EEFF4CBB
:2035600028BC2045B5A92048A523C51EB0032025BC68E61E6C0E02251FF00E8AF00B30E519
:203580002065B52058B5CAD0F760E60A201D9B204C9820EE92A52A851F4CF68AC8B10BC9DB
:2035A0004FF0E7A900853B853C20D8AE20DF97082094BDA9FF852AA97F852B289011209757
:2035C0008AC92CF01320EABD2094BDC60A100C20978AC92CF002C60A20DF97A52A8531A58D
:2035E0002B8532205798206FBE20EABD207099A53D850BA53E850C901688B0062025BC20B2
:203600006D98B10B852BC8B10B852AC8C8840AA52A18E531A52BE53290034CF68A202399C9
:20362000A2FF864DA9012077B5A63BA9022077B5A63CA9042077B5A40AB10BC90DF0BDC9B7
:2036400022D00EA9FF454D854DA9222058B5C8D0E8244D10F6C98DD00F20EB97840AA90061
:203660008514201F994C37B6C9E3D002E63BC9EDD006A63BF002C63BC9F5D002E63CC9FD29
:20368000D006A63CF002C63C200EB5C8D0AB00204E6F20E30020C995D009A626F0F0B0378E
:2036A0004C2A98B0FBA626F0E5A52ADDF104D00EA52BDDF204D007A52CDDF304F0198A3847
:2036C000E90FAA8626D0E2002143616E2774204D6174636820E300BDF104852ABDF2048573
:2036E0002BBCF304C005F07EA000B12A7DF404912A8537C8B12A7DF504912A8538C8B12A1E
:203700007DF604912A8539C8B12A7DF704912AA8A53738FDF9048537A538FDFA048538A537
:2037200039FDFB04853998FDFC04053705380539F00F985DF7045DFC041004B0049012B0E4
:2037400010BCFE04BDFF04840B850C2077984CA38BA52638E90F8526A41B840A20978AC915
:203760002CD03E4C95B62054B3A5261869F4854BA905854C2000A5A52A8537A52B853820C5
:20378000E9B4A52685271869F9854BA905854C205F9AF0ADBDF5043004B0A690B490A2B030
:2037A000B04C968B0022E3207661726961626C650023546F6F206D616E7920E37300244E6F
:2037C0006F20B800208295F0DBB0D92094BD20419820B1B4A426C096B0D6A537990005A563
:2037E00038990105A539990205AA208C8AC9B8D0CCE005F05A20DD92A426A52A990805A5D5
:203800002B990905A52C990A05A52D990B05A90120D8AE208C8AC988D00520DD92A41B8464
:203820000AA426A52A990305A52B990405A52C990505A52D990605208098A426A50B990D90
:2038400005A50C990E051898690F85264CA38B20299B20FD92A526186908854BA905854C83
:20386000208DA32099A6208C8AC988D00820299B20FD92A41B840AA526186903854BA9058D
:20388000854C208DA34C37B8209AB9205798A425C01AB00EA50B99CC05A50C99E605E6258F
:2038A00090300025546F6F206D616E7920E47300264E6F20E400205798A625F0F2C625BC5B
:2038C000CB05BDE505840B850C4C9B8B209AB9205798A520F003200599A43DA53E840B850F
:2038E0000C4CA38B205798A9338516A9B485174C9B8B20978AC987F0EBA40A88206D98A5E5
:203900000B8516A50C85174C7D8B0027EE2073796E7461780020978AC985F0D6C60A201D22
:203920009B20F092A41BC8840AE0E5F004E0E4D0D98A48A52B052C052DD042A62AF03ECA30
:20394000F01AA40AB10BC8C90DF032C93AF02EC98BF02AC92CD0EDCAD0EA840A209AB96805
:20396000C9E4F0062077984CD2B8A40AB10BC8C90DF004C93AD0F588840A4C8BB8A40A6820
:20398000B10BC8C98BF00EC90DD0F50028EE2072616E676500840A4CE39820DF97B01020A8
:2039A0001D9B20F092A51B850AA52B297F852B207099B0016000294E6F2073756368206CB7
:2039C000696E65004C0E8C4C2A98840A4C988BC60A20A9BFA51B850A844D20978AC92CD03C
:2039E000E9A54D48208295F0DEA51B850A68854D082094BDA44D20D7FF852728901BA5276B
:203A0000D0C220D7FF8536AAF00920D7FF9DFF05CAD0F7201E8C4CDAB9A527F0A7300CA2AE
:203A20000320D7FF952ACA10F8300EA20420D7FF9D6C04CA10F720B2A320B4B44CDAB96800
:203A4000684C988B20978AC923F084C986F003C60A18664D464DA9FF854E208A8EB00A20F1
:203A60008A8E90FBA2FF864E1808064D28664DC92CF0E7C93BF0E3C60AA54D48A54E4820D8
:203A80008295F0BB68854E68854DA51B850A08244D7006A54EC9FFD017244D1005A93F2081
:203AA00058B520FCBB8436064D18664D244D701D851BA9008519A906851A20ADAD208C8A67
:203AC000C92CF006C90DD0F5A0FEC8844E28B00C2094BD2034AC20B4B44C5ABAA900852796
:203AE00020218C4C5ABAA000843DA418843E20978AC60AC93AF010C90DF00CC98BF0082068
:203B00009AB9A0012055BE205798A53D851CA53E851D4C9B8B20978AC92CF0034C968B203F
:203B20008295F0F1B00C2050BB2094BD20B1B44C40BB2050BB2094BD20ADAD8527201E8CDD
:203B400018A51B6519851CA51A6900851D4C15BBA51B850AA51C8519A51D851AA000841B3A
:203B6000208C8AC92CF049C9DCF045C90DF00B208C8AC92CF03AC90DD0F5A41BB119301C71
:203B8000C8C8B119AAC8B119C920F0F9C9DCF01D8A186519851990E2E61AB0DE002A4F755F
:203BA00074206F6620DC002B4E6F20F500C8841B60201D9B204C9820EE92A624F0E8A52AEF
:203BC000052B052C052DF005C6244C9B8BBCA305BDB7054CDDB8002C546F6F206D616E7910
:203BE00020F57300A624E014B0EC206D98A50B9DA405A50C9DB805E6244CA38BA000A906EA
:203C0000D0072058B5A000A90784378538A9EE8539A920853AA0FF843BC8A2379820F1FF54
:203C200090064C389820E7FFA900851E60207099B04EA53DE9028537853D8512A53EE9004B
:203C400085388513853EA003B13718653785379002E638A000B1379112C90DF009C8D0F51A
:203C6000E638E613D0EFC8D004E638E613B137911230092081BC2081BC4C5DBC2092BE1850
:203C800060C8D004E613E638B137911260843B202DBCA007843CA000A90DD13BF072C8D19A
:203CA0003BD0FBC8C8C8843FE63FA5128539A513853A2092BE8537A513853888A506C51227
:203CC000A507E513B010206FBE2020BD00008620737061636500B139913798D004C63AC6A0
:203CE0003888986539A63A9001E8C53D8AE53EB0E538A001A52B913DC8A52A913DC8A53FA9
:203D0000913D2056BEA0FFC8B13B913DC90DD0F7602057982020BDA518850C860B4C0B8BB6
:203D2000A51285008502A51385018503203ABDA280A9009D7F04CAD0FA60A518851DA506FA
:203D40008504A5078505A900852485268525851C60A50438E905202EBEA000A5309104C84F
:203D6000A52E2980852EA531297F052E9104C8A5329104C8A5339104C8A534910460A50426
:203D800018854B69058504A505854C6900850560F02030BDA50438E904202EBEA003A52D2A
:203DA000910488A52C910488A52B910488A52A91046018A504E536202EBEA436F008B9FFD5
:203DC00005910488D0F8A536910460A000B1048536F009A8B10499FF0588D0F8A000B10481
:203DE00038650485049023E60560A003B104852D88B104852C88B104852B88B104852A18B2
:203E0000A504690485049002E60560A237A003B104950388B104950288B104950188B10479
:203E2000950018A5046904850490DFE605608504B002C605A405C4039007D004C502900143
:203E4000604CB78CA52A9500A52B9501A52C9502A52D9503601898653D853D9002E63EA00D
:203E6000016020DDBEA8A9FF843DA23720DDFFA5188513A0008412C888B112C90DD01FC815
:203E8000B112300CA003B112F014182093BED0E8C81898651285129002E613A0016020CF77
:203EA000BF0D4261642070726F6772616D0DEA4CF68AA9008537A9068538A436A90D99005A
:203EC000066020D2BEA200A00620F7FF4C9B8B4C0E8C201D9BD0F820B2BE4C4C9820D2BE06
:203EE000888439A518853AA98220F4FF863B843CA90060206FBEA5128545A5138546A9231C
:203F0000853DA980853EA518854220DDBE863F844086438444864784488541A8A23720DDBD
:203F2000FF4C9B8B2062BE4CF38A2062BE4C14BD20A9BF4820139820EE9268A8A22AA901E9
:203F400020DAFF4C9B8B38A9002A2A4820B5BFA22A6820DAFFA9406020A9BF4820AE8A2027
:203F6000499820EE9268A8A52A20D4FF4C9B8B20B5BF20D7FF4CD8AEA940D006A980D00266
:203F8000A9C04820ECADD00E20BABEA200A0066820CEFF4CD8AE4C0E8C20A9BF205298A4B6
:203FA0002AA90020CEFF4C9B8BA50A851BA50B8519A50C851A208C8AC923D00720E392A4B0
:203FC0002A9860002D4D697373696E67202300688537688538A000F00320E3FF204B891093
:203FE000F86C37002057982025BCA001B1FDF006200EB5C8D0F64C9B8B00526F67657200EF
:00000001FF

View File

@@ -0,0 +1,514 @@
:020000040000FA
:20000000000000000000000018181818180018006C6C6C000000000036367F367F36360000
:200020000C3F683E0B7E180060660C1830660600386C6C386D663B000C18300000000000FE
:200040000C18303030180C0030180C0C0C18300000187E3C7E1800000018187E18180000CE
:2000600000000000001818300000007E00000000000000000018180000060C1830600000B8
:200080003C666E7E76663C001838181818187E003C66060C18307E003C66061C06663C00A6
:2000A0000C1C3C6C7E0C0C007E607C0606663C001C30607C66663C007E060C18303030006A
:2000C0003C66663C66663C003C66663E060C38000000181800181800000018180018183054
:2000E0000C18306030180C0000007E007E00000030180C060C1830003C660C181800180058
:200100003C666E6A6E603C003C66667E666666007C66667C66667C003C66606060663C0033
:20012000786C6666666C78007E60607C60607E007E60607C606060003C66606E66663C007B
:200140006666667E666666007E18181818187E003E0C0C0C0C6C3800666C7870786C660033
:200160006060606060607E0063777F6B6B6363006666767E6E6666003C66666666663C005C
:200180007C66667C606060003C6666666A6C36007C66667C6C6666003C66603C06663C001F
:2001A0007E181818181818006666666666663C0066666666663C180063636B6B7F7763004A
:2001C00066663C183C6666006666663C181818007E060C1830607E007C60606060607C00B3
:2001E000006030180C0600003E06060606063E00183C66420000000000000000000000FFB0
:200200001C36307C30307E0000003C063E663E0060607C6666667C0000003C6660663C0050
:2002200006063E6666663E0000003C667E603C001C30307C3030300000003E66663E063C36
:2002400060607C66666666001800381818183C0018003818181818706060666C786C6600FA
:200260003818181818183C000000367F6B6B630000007C666666660000003C6666663C00E6
:2002800000007C66667C606000003E66663E060700006C766060600000003E603C067C0027
:2002A00030307C3030301C000000666666663E0000006666663C18000000636B6B7F36006C
:2002C0000000663C183C660000006666663E063C00007E0C18307E000C18187018180C00D8
:2002E00018181800181818003018180E18183000316B460000000000FFFFFFFFFFFFFFFFC6
:200300004C12CB0D41636F726E20456C656374726F6E2000080D0D001122334455667788B2
:2003200099AABBCCDDEEFF0055AAFF8BB51C272E358B4B3EE26AD9F65E132C6CA5C441F66D
:2003400021ECF23886028B74A11625ABC41FC5C5C5C5C4E6C5C5C6C5C6C7C5C5C74F4E5BCC
:20036000C7C55F57786BCAC43C7CC74ECA00000280050007800A000C800F001180140016C5
:200380008019001B801E0020802300258028002A802D002F8032003480370039803C003EA5
:2003A0008041004380460048804B004D801F1F1F181F1F184F27134F271327081020080847
:2003C0001008AA55884422118040201008040201030F0101030100FF0000FFFFFFFF0000F5
:2003E000FF000FF0FF00030C0F30333C3FC0C3CCCFF0F3FCFF0703010007030000000102F0
:2004000002030304000602504028203040586040809DD295D2818B5962D2D2D2D204050614
:20042000000102FFF00F0011224488183C3C7E7E007E3CAE6A02D05424D0501620E2C420F8
:20044000C1CC300EC90DD00AA9BD2030C54E5F03A90DC97FF011C920900F24D0300620DF46
:20046000CE20E2C54CD8C4A920A8B92BC38D5D03B94CC3304AAA09F08D6A028A4A4A4A4A6A
:200480001869C38D5E0324D0701F18609D2402E88E6A02D01724D030157005205FD218602C
:2004A00020E2C420C1CC205FD220DFC41860AC5E03C0C4D0F7AAA5D04A90D08A4CAEDE8D2D
:2004C0005E0398C908900649FFC9F249FF24D0302608205FD2289003A5D04A24D050AC2044
:2004E000C1CC0848A218A064201ACD2042CEA5D0490285D06828604906D004A97F90319089
:2005000003A5D04A60A5D029206020DED620FBDE4CDED6A0008C6902A904D007200AC5A91B
:2005200094499505D0D00B200AC5A90A492F49DB25D085D060AD6103F0FAA920D0E5200513
:20054000C5D05ACE1803AE1803EC0803301EA5D638ED4F03AAA5D7E900CD4E03B0036D5422
:200560000386D6100438ED540385D760AD0A038D1803CE69021003EE6902AE1903EC0B0305
:20058000F006CE19034C42CE182096CCA90824D0D00520D1C9D00320DDCC4C28C6A2008653
:2005A000D9201ED0A6D938BD2403E9089D2403B003DE2503A5D8D01E201ED0F019A6D9BD8D
:2005C0000403E001B002E9069D2403BD0503E9009D25038AF0084CC9D02005C5F094A202E2
:2005E000D04EA5D02920D046AE1803EC0A03B010EE1803A5D66D4F03AAA5D769004C61C543
:20060000AD08038D18031820D8CAAE1903EC0903B005EE190390142096CCA90824D0D0057F
:2006200020E1C9D003203BCD20E8CD4C42CEA20086D9201ED0A6D918BD240369089D240305
:200640009003FE2503A5D8D01E201ED0F019A6D9BD0003E001900269069D2403BD01036950
:20066000009D25038AF0084CC9D02005C5F097A2024C9FC5AE5503AD2103CD23039076DDDC
:20068000ADC3F002B06FAD2203A8DDB4C3F002B06438ED2003305EA82087CAA9082023C55D
:2006A000A220A00820A1D32024CEB06F60A003B1F09928038810F820DED6A228205AD0A289
:2006C000282075D7D01BB1D40A26D806D108B00246D828D0F3A5D82D600320DED6A004D01F
:2006E0000CA9FFD0F52D6003AABD6F03C891F0A900C004D0F7602005C5D06EA5D02908D09D
:20070000034C9DCBAE0B038E190320E8CDAE1903EC0903E890F12005C5D032A9008D230374
:200720008D2203F0052005C5D0CB2046C718AD22036D08038D1803AD2303186D0B038D194A
:20074000032024CE90AFA218A0284C1ACDA206A0262099D3A200A0242099D34CC9D020059A
:20076000C5D0F120AACD4C42CE204DC7AD6103F033AE5A03AC5C0320C4CFA200A0282093B2
:20078000D338AD0603ED0203A8C88C3003A22CA02820BCD5AD2E03D003CE2F03CE2E03CEB2
:2007A0003003D0E960A810132D6003087885D8AD4B0329F005D88D4B032898A000F007484A
:2007C00020A5C768A002AA1001C82D600385D8AD600329071865D8AABDDEC3995703C002C1
:2007E000B00DAD570349FF85D34D580385D260AD220399590360A9008D2203AD6003290774
:2008000020BFC7A98020BFC7AE60038E1F03E003F01190208E20032041C8CE2003CE1F0353
:2008200010F560A2078E20032041C84E2003CE1F0310F560A207203EC8A2008E1F038E203B
:2008400003AD2003AE1F03180878290F85FB8A2D6003A8A5FBB003996F03C90890054D488A
:200860000285FB98AE6003E003F01F901C4A4A084A282AAA982CCDC3F001382A0A2906A845
:20088000C90490094902A8B0040AAAA00086FAA5FB4A20C5C8A5FBC820C5C82860AAC8B120
:2008A000F0B0A4A5D848AE6003BC6F03C008900E8A489829074D4802382048C868AACA1005
:2008C000E86885D8602903AABD23C4A6FA3D27C485FCBD27C449FF39040805FC990408AAC3
:2008E000AD4B032930D0048A9908FE60AD23034C30CBAD1B03C9209045484A4A4A4A4AAA40
:20090000BDC8C32C6703D0200D67038D67038A29031869BF85DDBD670385DBA00084DA843A
:20092000DCB1DC91DA88D0F968204FCFA007B91C0391DC8810F860AD1F03186C2602C901CB
:20094000F029B0F738AD1C03490AD0EFAD1D0349202960F008207AC9A9EF4C30C5A9104CC9
:2009600023C5207AC9A0008C5F0360AC1C03F0EDC002F0EE90DFA00AD0ED0878AD4B03099C
:20098000408D4B032860AE6103F0AC4C71CF18AD5F036D4A038D4A03AD4B03303390054983
:2009A000408D4B032940F007AD6003E904093F85FBA5D02930D019AAAD600385FAA0073828
:2009C000BD0C0845FB91D6986907A8E846FAD0F060AE5003AD5103204FCCB0146D54039052
:2009E0000FAE5003AD510320C9CA100438ED54038D51038E5003484A8D03FE8A6A8D02FE40
:200A00006860A900A22C9D0003CA10FAAE5503BCB4C38C0A032087CABCADC38C0903A00379
:200A20008C2303C88C2103CE2203CE20032042CE2038CAA9F74C30C52080CAA21CA02C2061
:200A400028D30D2D033039A220205AD0A21C205AD0AD1F030D1D033027AD2303D022AE55C6
:200A600003AD210385D8AD200346D86A46D8D0106A4ADDB4C3F0021007A000A21C2093D3FA
:200A8000A210A0284C22CDC898A0008C4D038D4C03AD4F034AF0090E4C032E4D034A90F7FB
:200AA00060A220A00C20A1D34CC9D0203EC52005C5D00985DCA9C085DD4CE2CEA97F204F4A
:200AC000CFAE5A03A0004C94CE488A186D5203AA686D5303602009CB20D1E7900230F6A5E4
:200AE000D049042946D02AAD69023022AD1903CD0903901A4A4A386D69026D0B03CD0903C2
:200B0000900C1820D1E73810FAA9FF8D6902EE69026048A27FA90085D09DFF02CAD0FAA273
:200B2000049D0B08CAD0FA205ECC68A27F8E660320DADA8E550308788DF402AD820229C7C5
:200B40000DF4028D82028D07FE28BDCFC38D6003BDBBC38D4F03BDF5C38D6103D002A90786
:200B60000AA8B9C1C38D63030A10FD8D6203BCFBC38C5603B907C48D5403B90BC48D4E035D
:200B8000984A4901AABD0FC48D5203E88E5303A9432030C520F6C72002CA2076C9A200ADC9
:200BA0004E0320F0C92061C52003CCA9008D69028D18038D1903A206AC4E0394D995D8C89D
:200BC000CACA10F7A8AD580391D891DA91DC91DE88D0F5A20618B5D9690495D93006CACADA
:200BE00010F430E1A9DFD002A9EF08782D4B038D4B032930D00BA007B904089908FE881041
:200C0000F72860A920D00BF0DFAD55032904D02FA91008780D4B038D4B0328290FAABD6F0C
:200C200003C90890034D480248A0072032CC684AA0062903AABD23C49908FE888810F960BF
:200C4000204FCFA000B1DCC891F0C008D0F760488A38ED5203AA68ED5303CD4E0360A90F1A
:200C60008D6703A90CA0069968038810FAE0079002A2068E4602AD4302A200EC4602B00B12
:200C8000BC1DC49968036901E8D0F08D4402A8F0CCA2114CA8F0A90224D0D002503EAD091E
:200CA000039003AD0B0370088D190368684C2BC608CD6503F025289004CE650360EE6503BB
:200CC000600848AC4F0388A9FFC01FD002A93F85D8B1D645D891D68810F76828602097CD32
:200CE000AD09038D19032042CE204FCCB0036D540385D986D885DAB00620AFCD4C0ACD2000
:200D0000C9CA20C9CA30F22074CDA5DAA6D885D786D6C6DCD0D3A228A018A902D006A22447
:200D2000A014A90485D8BD000348B900039D000368990003E8C8C6D8D0EC602097CDAC0BE8
:200D4000038C19032042CE20C9CA100438ED540385D986D885DA900620AFCD4C66CD20C9C0
:200D6000CA30F52074CDA5DAA6D885D786D6C6DCD0D5F0A2AE4D03F010A000B1D891D6C83F
:200D8000D0F9E6D7E6D9CAD0F2AC4C03F00888B1D891D698D0F8602016CD38AD0903ED0B6B
:200DA0000385DCD00568684C16CDAD08031070A5D84838AD0A03ED080385DDAC4F0388B17B
:200DC000D891D68810F9A20218B5D66D4F0395D6B5D76900100438ED540395D7CACAF0E875
:200DE000C6DD10D76885D860AD18034820AACD2042CE38AD0A03ED080385DAAD5803AC4F21
:200E0000038891D6D0FB8A186D4F03AAA5D76900100438ED540386D685D7C6DA10DD688D5B
:200E200018033860AE1803EC080330F6EC0A03F00210EFAE1903EC0B0330E7EC0903F0026A
:200E400010E0AD19030AA8B96DC385D7B96EC3AC530388D00346D76A6D500385D6A5D76D10
:200E60005103A8AD1803AE4F03E010F00390020A0A0A0A9002C8C80A9002C81865D685D6DD
:200E8000AA986900100438ED540385D71860AE5903AC5B0320C4CF209DD3A00084DAB1DC61
:200EA000F01385DB100320F4CFEE2403D003EE250306DBD0EFA228A0242099D3AC2603D07C
:200EC00003CE2703CE2603A4DAC8C008D0CEA228A0244CA1D3A22B86DCA2C486DDD003203B
:200EE0004FCFAE6003A5D02920D0A3A007E003F00EB03CB1DC05D245D391D68810F560B19D
:200F0000DC484A4A4A4AAABD17C305D245D391D698186908A868290FAABD17C305D245D355
:200F200091D698E908A810D76098E92130FAA8B1DC85DA38A90026DAF0EF2A06DA2AAABD17
:200F400027C305D245D391D618986908A890E50A2A2A85DC29032AAA290369BFA8BDC8C310
:200F60002C6703F003BC670384DDA5DC29F885DC60A220205ED0AD1F03C904F06DA0052927
:200F800003F00E4AB00388D008AABC5B03BD5903AA20C4CFAD1F0330230A103B29F00AF02F
:200FA000464940F0144820EDCF684960F011C940D00AA90285DA4C1DD44C00D54C37C9850C
:200FC000DA4CD6D38A19D7C359D8C385DE8A19D6C359DBC385DF600A30E20A0A100320FC58
:200FE000CF20FED04CEACF20FCCF201ECDA024A2204CA1D3A2242075D7F006602073D7D031
:2010000013AC1A03A5D125DE11D485D8A5DF25D145D891D460B1D405DE45DF91D460A224C6
:20102000A00084D8A0022039D006D806D8CACAA0002039D0E8E8A5D860BD0203D90003BDC8
:201040000303F901033010B90403DD0203B90503FD03031004E6D8E6D860A9FFD003AD1FB0
:201060000385D8A0022087D020BED0A000CACA2087D0AC6103C003F005B00620BED020BE94
:20108000D0AD5603D0386018A5D82904F009BD020348BD0303900EBD020379100348BD0396
:2010A0000379110318991103790D039D03036899100318790C039D02039003FE0303BD0302
:2010C000030A7E03037E020360A010209FD3A202A00220E6D0A200A004AD6103884AD0FC49
:2010E000AD5603F001C81E10033E110388D0F73820F4D0E8BD1003FD0C039D10036020242B
:20110000D3AD2B034D2903300FAD2A03CD2803AD2B03ED29034C2BD1AD2803186D2A03AA27
:20112000AD29036D2B03D0038AF00A6AA2004D2B031002A20286DCBD11C48D5D03BD12C433
:201140008D5E03BD29031004A224D002A22086DDA02C20A1D3A5DD490485DB05DCAA209716
:20116000D3AD1F0329100A0A0A85D9A22C2020D085DAF006A94005D985D9A6DB2020D0240B
:20118000DAF00160A6DCF0024A4A2902F0078A0904AA2097D32043D3A5DC4902AAA8AD2905
:2011A000034D2B031001E8BD15C48D3203BD19C48D3303A97F8D340324D97029BD03C4AA53
:2011C00038BD0003F92C0385D8BD0103F92D03A4D8AA100320B2D3AAC8D001E88AF002A083
:2011E0000084DDF0098A4A6A090245DC85DCA22C207AD7A6DAD002C6DBCAA5D9F01F101021
:201200002C34031005CE3403D023EE34030A100D86DAA22C2075D7A6DA0900D010A5D12574
:20122000DE11D485D8A5DF25D145D891D438AD3503ED37038D3503AD3603ED3803B0118535
:20124000D8AD35036D39038D3503A5D86D3A03188D360308B0096C320388100320EAD26C19
:201260005D03C8C008D0F818A5D46D520385D4A5D56D5303100438ED540385D5A0006C5D7A
:201280000346D190DA2004D36C5D0306D190D02014D36C5D0388100C20EAD2D00746D190FF
:2012A000032004D328E8D004E6DBF00A24D97007B035C6DDD03160A5DC86DA2902AAB019B9
:2012C00024DC300AFE2C03D010FE2D03900BBD2C03D003DE2D03DE2C038A4902AAFE2C0378
:2012E000D003FE2D03A6DA4CFAD138A5D4ED520385D4A5D5ED5303CD4E03B0036D54038533
:20130000D5A00760AD620385D1A5D4690785D49002E6D560AD630385D1A5D4D002C6D5E962
:201320000885D460A028A220202FD3E8E8C8C838BD0403FD0003990003BD0503FD010399E9
:20134000010360A5DCD007A228A02A201ACDA228A03720A1D338A6DCAD3003FD2C03A8ADE6
:201360003103FD2D03300320B2D385DB84DAA235207ED34A9D0103986A9D0003CACABC044D
:2013800003BD0503100C20B2D39D050348989D04036860A908D00CA030A902D006A028A28B
:2013A00024A90485D8BD0003990003E8C8C6D8D0F460489849FFA86849FFC8D00318690194
:2013C000602073D7D008B1D44D5A0385D8606868EE26034C5CD420C1D325D1D0F3A20020ED
:2013E000A8D4F02DAC1A0306D1B005208AD490212014D3B1D44D5A0385D8D012388A6D61CB
:20140000039004E6D91007AA2015D038B0E2208AD4A00020C2D4A020A2242022CD20C1D3C9
:20142000A20420A8D48AD002C6D9CA2062D490272004D3B1D44D5A0385D8A5DAD0EDA5D85C
:20144000D012388A6D61039004E6D91007AA2015D038B0DC2062D4A00420C2D420EACF4C65
:20146000C9D0A5D118900E68E8D004E6D9101646D1B01205D148A5D124D8086845DA482836
:20148000F0E56845D185D14C01D0A90018900AE8D004E6D910EF0AB00B05D124D8F0F045F5
:2014A000D14A90E16A38B0DDBD000338ED2003A8BD0103ED2103300320B2D385D998AA0572
:2014C000D96084D88AA8A5D93002A900A6D8D00320B2D34818987D00038D2003687D0103E5
:2014E0008D210360A90320EBD4A90748201ECD20C9D0A20368A8BD100391F088CA10F760D5
:20150000A220A03E2093D32048D5A214A024204CD52048D5A220A02A2028D3AD2B038D322F
:2015200003A2282070D3A02E20EFCF201ECD18206ED5201ECDA2202020CD38206ED5A23EF4
:20154000A0202093D34CEACFA220A014BD0203D90203BD0303F9030330134C22CDAD180322
:2015600038ED0803AAAD190338ED0B03A86008A220A0352028D3AD36038D3D03A2332070BB
:20158000D3A03920EFCF38AD2203ED26038D1B03AD2303ED27038D1C030D1B03F01720B856
:2015A000D5A233208AD6A228208AD6EE1B03D0EEEE1C03D0E92890B5A239A02E86DCBD00F2
:2015C00003D90003BD0103F90103300698A4DCAA86DC84DDB9000348B9010348A6DD2020E7
:2015E000D0F00DC902D03DA204A4DD2099D3A6DD207AD7A6DC2020D04AD0299002A200A4F2
:20160000DD38B90003FD000385DAB90103FD010385DBA9000A05D1A4DAD014C6DB1010854B
:20162000D12001D0A6DD689D0103689D000360C6DAAA10E085D12001D0A6DAE8D002E6DB78
:201640008A4846DB6AAC6103C003F005900646DB6A46DB4AAC1A03AAF00F9838E908A8B04E
:2016600002C6D52015D0CAD0F1682D6103F0B5AAA9000A0D6303CAD0F985D19838E908A87D
:20168000B002C6D52004D04C24D6FE0803D003FE090338BD0003FD02039D0003BD0103FD85
:2016A00003039D01031030BD0A03300BFE0603D011FE07034CC2D6BD0603D003DE0703DE0B
:2016C000060318BD00037D04039D0003BD01037D05039D010330D06020DED62033C4087853
:2016E00048A5D02930D027AD600385D8AD4B0349808D4B03A200A00738B1D648BD0C08911F
:20170000D6689D0C08E8986907A846D8D0EB68286020DED6A00784D8A90185D9AD62038503
:20172000DAB1D64D58031824DAF0013826D9B00A46DA90F3986907A890E2A4D8A5D9992828
:20174000038810D2A2208A48204FCF68AAA007B92803D1DCD0088810F68AE07FD00DE8A547
:20176000DC18690885DCD0E58AD0DB20DED6AC5503AA60A2202020D0D06ABD020349FFA819
:2017800029078D1A03984A4A4A0AA8B96DC385D8B96EC3AC5603F00346D86A6D500385D47E
:2017A000A5D86D510385D5BD010385D8BD0003482D61036D6103A8B9C1C385D168AC610356
:2017C000C003F005B0060A26D80A26D829F81865D485D4A5D865D5100438ED540385D5AC73
:2017E0001A03A9006048A9A0AE6A02D04524D0D04120DED67012A218A0642099D320C1CCB1
:20180000A9022023C50E5F03A9BF2030C568297F2033C4A9402023C54CDED6A92024D05003
:20182000C1D0BF2011D7F00B4820DED620E2C520DED66860AE55038A2907A8BEFBC3BD0B2A
:20184000C4A200A8607EE033DB47DB89DB14DD44E5BCE52DDE50DCD6F1CCF020F480F4A289
:20186000FF20F3E8F0A2FFA2FFA2FFA2FFDFEA21E2D2E141DFA2FFA2FFA2FF90019F0DA09B
:2018800002D3ED00030000FF0000000000000000FF040400FF0019191932080000000000F9
:2018A000FF000000000050000390640681000000001B01D0E0F0010101000000FFFFFF009F
:2018C000000000000000000005FF000A0000000000FFA9408D000D78D8A2FF9AE88E00FE79
:2018E0008E8D02A9F88D05FEAD00FE2902490248F009AD58024AC901D0184AA20486018539
:2019000000A89100C8D0FBC8E60110F68D8E028E8402A23A201EEC08680AA29BA08D68F0D3
:2019200009A07E900FA087EE8D02EE8D02A9FF8D8F02A290A900E0C39002A9FF9D0002E8BB
:20194000D0F48EF7028AA2E29500E8D0FBB944D899FF0188D0F7A90785ED84FC5878A5FC16
:20196000F00320C2EEAD8F0220DADA09848D82028D07FE8D04FEA20C8E5B028E00FE207618
:20198000E9AE8402F00320C0E7A200209FE3A203AC0780B90080DD97DCD034C8CA10F4A68B
:2019A000F48AA8C8C010B02B9849FF85FAA97F85FB20A9E38C05FEB1FA20A9E38E05FED193
:2019C000FAD0E0E6FAD0EAE6FBA5FBC98490E2A6F4100DAD06809DA002298FD0038E4B02F4
:2019E000E8E01090A6AD8F022000C3A0CA205FE2207BE8208BF0A9818DE0FCADE0FC6A90B9
:201A000015A9018DE0FCADE0FC6AB00AA2FF20A8F0D003CE7A02A00EA20120A8F0A20220AE
:201A2000A8F08C43028C4402A2FEAC7A0220A8F02D6702101DA0022034DCAD8D02F00EA973
:201A40000720EEFF20DED620D5CE20DED6A0132034DC38207BE820D1E708684A4A4A4A4DAC
:201A60008F022908A8A20320A8F0F01C98D014A98D20A5E7A209A0F0CE670220F7FFEE6758
:201A800002D005A90020A7E7AD8D02D005AE8C02101EA20FBDA0022A3016CA10F7A9002C77
:201AA0007A02303300F94C616E67756167653F0018088E8C02209FE3A980A0082036DC8486
:201AC000FD20E7FF20E7FFA9008D5D0228A9012C7A0230034C00804C00042907C90790020D
:201AE000A906AA0A0A0A6085FC68482910D0176C0402A6F484F420A9E38C05FEA000B1F6B8
:201B000048209FE368608A48BABD0301D838E90185FDBD0401E90085FE86F0A20620A8F046
:201B2000A5F48D4A02AE8C022000DB68AAA5FC586C0202A000203CDCAD67026AB0FE20E774
:201B4000FF20E7FF4C83DAD8A5FC488A489848A9DB48A98148AC00FE984A9013982D5B02D5
:201B600029FEAA290C24258A2970F0204CDFF4A20520A8F0F08F686868A868AA6885FC6C9F
:201B8000060268A868AA6885FCA5FC408AA0202908D0328A2904F0D7208EC9AD5102F01BD4
:201BA000CE5102D016AE5202AD4802F003AE530249078D48028E510220A3C8A0042002E2F4
:201BC000CE4002A0108C05FEAD8302AA490F48A838BD90026900999002CAF00388D0F26808
:201BE0008D8302A205FE9A02D008CAD0F8A0052002E2ADB002D008ADB102F006CEB102CEA3
:201C0000B0022C7802100BEE7802582093E878CE7802AD4202F00BA5EC05ED18F001382066
:201C200049ECAC4902F005A21520A8F02CC60230144CF9DEA9C385FEA90085FDC8B1FD2009
:201C4000E3FFAAD0F7608EB0028CB102A9FFD002A90085E68A489848AC5602F0143866EB81
:201C600020D7FF0846EB289025A9008D560220CEFF24FF3016AE4102202EE3901124E65057
:201C8000F0ADB0020DB102D0E8B00538A91B85E668A868AAA5E660294328002EDDBA0546B0
:201CA00058E0B0FF4241534943DDA100434154DDBA05434F4445E0B68845584543F5EA00AC
:201CC00048454C50EED5FF4B4559E095FF4C4F4144DFAA004C494E45E461014D4F544F5214
:201CE000E0B6894F5054E0B68B52554EDDBA04524F4DE0B68D53415645DFAC0053504F4F15
:201D00004CDFEF0054415045E0B68C5456E0B690DDBA030086F284F3A90820BADDA000B14B
:201D2000F2C90DF004C8D0F760A0FF20C2DDF070C92AF0F720C3DDF067C97CF063C92FD0E9
:201D400008C82092DDA902D07184E6A200F0135D9BDC29DFD017C818B023E8B1F22051E2D5
:201D600090EDBD9BDC3018B1F2C92EF00418A4E688C8E8E8BD99DCF03110F830DBCACA48D8
:201D8000BD9CDC4820C3DD1808208DDD40BD9DDC300E98BC9DDC1865F2AA98A4F39001C83A
:201DA00060AE4B023004384CB1DAA4E6A20420A8F0F0EDA5E62096DDA9036C1E020A290136
:201DC00010F8C8B1F2C920F0F9C90D6090F520C3DDC92CD0F4C86020C3DD2006DE90378552
:201DE000E62005DE9019AAA5E60AB02A0AB02765E6B0230AB02085E68A65E6B01990E0A640
:201E0000E6C90D3860C8B1F2C93AB00AC9309006290F6020CEDD18602006DEB00E29DFC949
:201E200047B0F0C94190EC08E93728C860488A489848BABD0301482C60021008A8A90420E5
:201E400095E3B05918A9022C7C02D005684820D8D6A9082C7C02D0029005684820A4DEAD80
:201E60007C026A9022A4EA88101D684808782C4F0208A2022068DF28100CA21320A8F0F024
:201E800005A2022009DF28A9102C7C02D00FAC5702F00A68483866EB20D4FF46EB6868A853
:201EA00068AA68602C7C027020CD8602F01B0878AAA9042C7C02D0108AA2032068DFB008FF
:201EC0002CC602100320CADE2860AD8502F03AC903B00BA21420A8F0F0EFA203D02B18A918
:201EE0000120FBDE6EC60260D01CA208587820F4DECA10F8E009901160A900A203AC8502BD
:201F00002095E36C2202AE410218480878B0198A2904F014AD6B02F00C8A48A8A21720A833
:201F2000F068AAD0032083E9387EC302E002B00BA9008D68028D5D028D6A02200BE5286803
:201F4000605007BDCC029DD5026008780838BDD502FDCC02B00438FDB5E1289006187DB5C5
:201F6000E149FFA000AA286078201EE2900D20E5E73008482050E96858B0ED6048A9009D21
:201F8000E2029DE3029DE4029DE502686084E62A2A2A2AA0042A3EE2023EE3023EE4023E85
:201FA000E502B03188D0EEA4E660A9FF86F284F38EE2028CE30248A202207CDFA0FF8CE835
:201FC00002C820FCE7200EE890FB6848F062201BE0B03BF03E00FC4261642061646472653A
:201FE000737300A21020A8F0F02320E8F5A9000884E6AC57028D5702F00320CEFFA4E628E9
:20200000F00BA98020CEFFA8F0748D570260D06EEEE802A2E2A002684CDDFF20C3DD201899
:20202000DE900C207CDF208DDF2018DEB0F83860A20A201BE09047B8B1F2C92BD0042CBC20
:20204000D8C8A20E201BE0903508500FA2FC18BDF0017DF4019DF401E8D0F4A203BDEC0285
:202060009DE8029DE402CA10F428F0A7A206201BE0900BF09EA202201BE09002F09500FE09
:2020800042616420636F6D6D616E6400FB426164206B65790020D7DD90F1E010B0ED20CEFF
:2020A000DD08AE100B9848203FE168A828D0366020D7DD90C98A48A90085E585E420CCDD70
:2020C000F01820D7DD90B786E520CEDDF00C20D7DD90AB86E420C3DDD0A4A4E4A6E5682063
:2020E000F4FF709A603820FDE7200EE8B008E8F09A9D000B90F3D0930878203FE1A210E423
:20210000E6F00EBD000BD9000BD006AD100B9D000BCA10EB28600878AD100B38F9000B8593
:20212000FB8A48A210BD000B38F9000B9008F006C5FBB00285FBCA10EC68AAA5FB28600894
:20214000788A48A4E62016E1B9000BA81865FBAA85FAAD6802F00D00FA4B657920696E2039
:2021600075736500CE84026838E5FA85FAF00CBD010B99010BC8E8C6FAD0F49848A4E6A216
:2021800010BD000BD9000B9007F005E5FB9D000BCA10EEAD100B99000B688D100BAAEE840F
:2021A000022860030A080707070707090000C0C05060708000E00040C0F0F0F0F0C0BDAC6B
:2021C000E185FABDA3E185FB602CBCD87001B86C2C020878BDCC02DDD502F072A820BEE173
:2021E000B1FA701A48C898D003BDB5E19DCC02E002900ADDD502D005A0002002E268A82890
:20220000186008784885FAB9B502F04198A4FA20E2E76828186098A0022002E2A8986C2A23
:2022200002087848BCD502C8D003BCB5E198DDCC02F00FBCD5029DD50220BEE16891FA2831
:20224000186068E002B007A0012002E248682838604829DFC9419004C95B9001386860A2AB
:20226000008A2D4502D0B6984D6C020D7502D0A6AD58026A98B00AA0062002E290032080ED
:20228000E41860C9A09005AD7302B003AD7202F0214AD031A5F448AD8C02301920A0E3ADDD
:2022A00006802910F00FA9032000808C5D026820A0E34C33E3B989EE8D5C02B9A9EEA8B0F9
:2022C000EA6A68B0BC98484A4A4A4A4904A8B96502C901F07E68900D290F187965021860D4
:2022E000204BE668AA20CEE1B066E001D005AC4502D05CA81059C9909004C9B09085290FFD
:20230000C90B90C1697B48AD7D02D0B5AD7C026A6A68B0D1C987D00D8A48201BD8A8F0C069
:2023200068AA981860A88A489820E5D768AA2C5F0230608A2D4502D0ACAD5D02D027AD68CC
:2023400002F0A2AC7902B9010BEE7902CE680218B0466068290FA82016E18D6802B9000BD4
:202360008D7902D0C9AAA5F448AD8C02301920A0E3AD06802910F00FA902200080CE5D0227
:202380006820A0E3981860AC5C02B959EFA8EE5C02D0EAA9066C2402482050E96838608AFD
:2023A00085F420A9E38D05FE6048A90C8D05FE6860F2E580E732E58FE78FE767E780E73885
:2023C000E538E59CE49EE48DE784E7C2E4C3E4E8DE38E538E5C0E7AEE75ECCF4DE64E41439
:2023E000EF38E507CC76E948E6D1E7E3DF10F051EC4FECE4DE7FE480E468E4BEDD11E5D049
:20240000E4EBE4DDEF34D837D85DD511D75FE48AE41DE2BDDDA5E7A5E7B1DAA8F089E8CE44
:20242000E18FE88AE8A8FFA3FF32F085E8C9E161E2E8EEA2FF38E5B3FF38E538E5B8E7945A
:20244000E761E4F3E6C6E6D9E6C2E6D5E6D4E5DCE5FEE57FE6ADC640CCE5C69DC8E4D4A9F7
:20246000006C0002EE490260A20024FF1011AD7602D00A588D690220EAF520EADEA2FF1880
:2024800066FF2C7A0210E04C0304AD820229BFE000F00209408D82028D07FE60C818B952CA
:2024A00002488A99520268A8AD5102D0138E5102A9009002A9078D4802984820A3C868A84A
:2024C000500B98E00AB007BCB5029DB50298AA6098300B582046DCB003AAA900A8608A29D1
:2024E0000FF0118A497FAA204CEC2AA2FFA0FFB002E8C8608AF0072038E518D0EE60A201B5
:20250000D0D88A49FFAAE002B850032CBCD86C2E0230EFF00D2038E5F007BCFB02BDF7028F
:20252000AA602038E5F002A200ACF702A9008DF702608A0D4102F0BBA20720A8F0A6F0A46C
:20254000F149006048087885EF86F084F1A207C9739040C9A19009C9A6903E18A9A16900FA
:20256000E9590A3884F1A82C5E0210078AB82095E3701AB9B2E385FBB9B1E385FAA5EFA4E1
:20258000F1B004A000B1F038A6F020BFEE6A282A68B860A000C91990C90808686820A8F00B
:2025A000D005A6F04C8DE528682CBCD860A5EB3032A90825E2D004A98825BB604808788506
:2025C000EF86F084F1A208C9E0B091C90EB0CA69490A909020E6E5A1FA91F06020E6E5B15D
:2025E000F081FAA9006085FAC8B1F085FBA004A20060D0FB00F74F5320312E303000AD6207
:2026000002D047AD6B02D005C8B1F0C920A208B08A88B1F020A4E620BAE60904AA9005207D
:202620000ADFA00120BAE685FA08A006B1F048A004B1F048A002B1F02A38E9020A0A05FA0A
:202640002068DF902C686828A6D060AD6202D0FAAD6B02F005A2164CA8F00878AD63022051
:20266000A4E6AAAD6402201EE2AD660248AD650248386E140868201EE268201EE22860AE32
:202680006202D0C6AE6B02D084E9010A0A0A0A090FAAA900A010C00EB002B1F09DC008CA54
:2026A00088D0F36029030904CD2508F00C4818AE25088D2508200ADF6860B1F0C9102903D4
:2026C000C860A20FD003AE8302A004BD8C0291F0E88810F760A90FD006AD8302490F18485C
:2026E000AAA004B1F09D8C02E88810F768B0E58D830260A004B1F099B00288C002B0F6B1A9
:20270000F085E9888C6902B1F085E8589007A90788C820EEFF20E0FFB049AAAD7C026A6A31
:202720008AB005AE6A02D0EAC97FD007C000F0E588B0DFC915D00D98F0DBA97F20EEFF88E0
:20274000D0FAF0D191E8C90DF013CCB202B0BFCDB30290BECDB402F0B890B6B0B520E7FF01
:202760002095E3A5FF2A60587824FF30372CC60210F520FDDEA00084F186F02038E5A905CF
:2027800009F0D00ED007A2328E5402A20869CF1869E986F0A8B99001AA25F145F099900100
:2027A000B99101A860498C0A8D47024C94F0AD40025878CD4002F0F9BC0103BD0003AA6000
:2027C000A9108D8402A2009D000BE8D0FA8E8402600878A94020E5E7300518B8204CEC28E3
:2027E0002A606C2002901248AD820209808D07FE297F8D82028D07FE6824FF601866E420D3
:20280000C3DDC8C922F002881866E4C90D60A90085E5B1F2C90DD00624E43052101BC92053
:20282000904CD00624E43040500FC922D01024E41036C8B1F2C922F02F20C3DD3860C97CE4
:20284000D026C8B1F2C97CF01FC922F01BC921D005C8A980D0BAC9209014C93FF00820F3F3
:20286000EF2CBCD87003A97FB8C805E5186000FD42616420737472696E6700AD8702494CA6
:20288000D0074C8702989D00FE60989D00FC60BC00FC60AD6B02D005AD1408D00160AE2594
:2028A00008BDC3023005AD1B08D0032093E9AD1B08F011C9FFF010CE1C08D00B2001EACEDB
:2028C0001B08D0032093E9AC1D08C0FFF05FAD1E08F005CE1E08D055AD1908C903F04EB915
:2028E000C008297F8D1E08AD1A08D02AEE1908AD1908C903D010AC1D08B9C008302FA90009
:202900008D1908201FEAAD1908186D1D08A8B9C4088D1A08F017CE1A08AD1D08186D19081D
:20292000A8B9C108F007186D1F08201FEAA5EA0D6202D0410878AD820229F90D2008CD8239
:2029400002F0068D82028D07FE28AD21088D06FEAD2208F020A5EAD01C8A48EE2408AE242D
:2029600008BD93E8AE92025D9AE82D22080D23088D06FE68AA60A2048E25082083E9E8E0AF
:2029800007D0F8A9008D1B089DC3028D14082014EAF09AAE25082014EABDC302F008A90040
:2029A0009DC3028D1B0820C9E1B05C087820CEE1482904F00E682014EA20CEE120CEE12821
:2029C0004CFEE9A9028D20086829F80A900BC9F0D005A9008D2008A9FF8D1D08A0018C1EA5
:2029E00008888C1A088C1F08888C190820CEE18D180820CEE12848AD18082026EA688D1BE9
:202A000008A9058D1C0860087820C9E19005A9008D140828A9008D2008A9008D2208608DEB
:202A20001F08186D1808482903AAAD2508C904D018682904F00BBD8AEA8D2308BD2DEDD0FD
:202A4000DABD8EEA8D2108D0D0E8A9008D2108684A4AC90C9007EE2108E90CD0F5A8AD211B
:202A60000848B97EEAC007E902CAD0F98D210868A8F0064E210888D0FACE2108D09B00F0C9
:202A8000E3D6CBBFB5AAA0978F874080C0803B76F076A9EF85F560E6F5A4F5A20D0820A8CB
:202AA000F028C9019860A20EA0FF4C9DEAADCB0385F6ADCC0385F7A5F560A2FF8E420208B7
:202AC000AD8202297F48A9102C5A02D0046809804868CD8202F0068D82028D07FE6860501D
:202AE00008EE4202B0084C06EC90034C53ECAD5A02291FA23B201EEC8E7702B810052CBC74
:202B0000D80940CA201EEC90B610020980CA201EEC100209208D5A02A6ECF012201EEC30B9
:202B200010E4EC86ECD007A20086EC2013EC4CDDEBE4ECD0EEA5E7F026C6E7D022ADBF02E8
:202B400085E7AD55028DBF02AD5A02A6ECE0B9D0112C7702100249308D5A02A90085E74C28
:202B6000DDEBBD4FEDAE5A028E7702AAC9219054C926B011A9C02C7702F004A4EDF00618BA
:202B80008A696AD03EAD77024910F0382E77029009A4EDD096BD99EEB0292E7702900AA4EA
:202BA000EDD088BDB7EFAAB00A2E77029008BD0BF0B0102E77022E7702B0088A2051E2B0BF
:202BC000024920AA8ACD6C02D007AE7502D00286E7A82034EDAD5902D003205FE2A6EDF038
:202BE0000B201EEC86ED3004A20086EDA6EDD016A0EC2076ED300C2050E9A5EC85ED86EC52
:202C00002013EC4CBAEAA5ECD0F9A0ED2076ED30F210EBA20186E7AE54028EBF0260F02843
:202C2000488A293F4820F8EC85FCA6F4A90820A0E3082038ED2825FCF002A98085FC209FAE
:202C4000E36805FCAA68A4FC602CBCD86C2802A201B0F98A103F297FA82050E9BE40EE20E6
:202C60001EEC8A60500F2082EC900A2CC002F0054DC002F00CA2FF4AE890FCA9002ACA10DF
:202C8000FC601848A5FA4DC102D008A5FB4DC202D001386860E88A297FAA78A5F448A908A1
:202CA00020A0E3A9FFA88DC0028EC102AD0080290FF03684FAA29F86FBA2002038ED290F97
:202CC000F030A0044A901248BD08EECDC1029008CDC002B0038DC00268E888D0E7A5FB4918
:202CE000C0386A66FA85FBB0D2AEC0026820A0E38A60E8E8E8E810E50848293F4A4AAABD63
:202D000017ED85FB8DC202BD25ED85FA8DC102682903AABD86F02860BFBFBFBFBFBFBFBF4F
:202D2000BEBDBBB7AF9FFEFDFBF7EFDFBF7FFFFFFFFFFFFF58788A60A4FAC8F00588B9000F
:202D4000BF60A5FBC9BBB016C9AF900CF004ADFFB760A5FFADFFAF60A5FFADFF9F60A5FB51
:202D6000C9BD9006F00AADFFBE60A5FFADFFBB60A5FFADFFBD60B8B90000F0092CBCD82051
:202D8000F8EC8DC002A5F448A90885F48D05FEA0FF84FAA2AF86FBAD00A0290FF018203891
:202DA000ED290FF0052064ECD020A5FB49C0386A66FA85FBB0E8A99F85FBADFF9F2903F0A7
:202DC000052064ECD004A28030032047F06820A0E38A602321002022240D7F2D253A003017
:202DE000703B2F396F6C2E38696B2C37756A6D3679686E35746762347266763365646332F2
:202E00007773783171617A1B704001003010416131215142112232521233436313235364B1
:202E20003444545524354565152546662636566727375768173948FF192949597969FF6294
:202E40003B3A0000000000000000000000000000352C28240018000C08080000000000001C
:202E600000312D251C191410090900000000000034302E29201D1511050D00000000000034
:202E80003936332A211E1A100E0A00000000000000322F2622231612050B000000000000E1
:202EA0000037072B271F1B171305000000000000380000000000000004045D7E5C7D7B6C3E
:202EC000FA006CFEFD1C1D1E1F003132333435363738393A3BA20920A8F020BAF90D4F53E4
:202EE00020312E30300D00600878A2008E4802AD53028D510220A3C8286001020304050682
:202F00000708090A0B0C0D0E0F101112131415161718191ACE4902607F00040C12161A1D00
:202F20002124292C3135393D41454A4E52565B5E65696F72727276767A0408060404030482
:202F4000030503050404040404050404040503070406030000040004054155544F52454EF5
:202F6000554D424552434F4C4F555244524157454C5345464F52474F544F444547494E50D4
:202F80005554524144434841494E4C4953544D4F44454E4558544F4C440D504C4F544C4FE8
:202FA00043414C52554E0D535445505448454E554E54494C564455524553544F5245505293
:202FC0004F43524550454154454E444C4F4144534156455052494E545B5E7C5F60AC440205
:202FE000A200603C3D3E3F402122232425262728292A2BC97FF0119003492060C960D00257
:20300000A95FC9409002291F602F21424F4F540D84ECBD40EE85ED60414243444546474883
:20302000494A4B4C4D4E4F505152535455565758595ABC00FE607FACADAEAF8081828384FC
:203040008586878889AAABA2FFE84A90FC86FCA5FA49FFF00DA200E84A90FC8A0A0A05FCB4
:20306000AA60A5FB293F493FA208D0EB909192939495969798999A9B9C9D9E9FA0A1A2A353
:20308000A4A5A6A7A8A9010204087FA9A185E3A9198DD103A90620BADDA20EBD56D89D1137
:2030A00002CAD0F786C2A20FA5F4488AA20FFEA002DEA002100D48209FE368200380AAF09C
:2030C00005A6F4CA10E86820A0E38A60C000D0090900D005AD4702090160A3F477F55AF274
:2030E0007DE05AF280F2E2DFC907B0ED86BC0AAABDDBF048BDDAF048A6BC6008482082FA44
:20310000ADC20348208BF568F01AA203A9FF48BDBE0395B06835B0CA10F4C9FFD006205959
:20312000FA4CD5DFADCA034A68F00E90132063FA00D54C6F636B6564009005A9038D5802FC
:20314000A93025BBF004A5C1D00A9848205CFB68A82035F72024F9D05320FAFA2CCA033032
:203160000820DAF820DBF6D0D7A002B9BC0391C8C8C00AD0F6ADC80391C8C8ADC903186D5B
:20318000C60391C8C8A9006DC70391C8C8A90091C8C8B9BD0391C8C8C012D0F6282059FAAD
:2031A00024BA30070820B6F90D0028602091F5D08F7886F284F3A00020FCE7A200200EE8C7
:2031C000B00DF0089DD203E8E00BD0F14C6EE8A9009DD20358604886C884C9A000B1C8AA19
:2031E000C8B1C8A820B1F1A002B1C899BC0399AE00C8C00AD0F368F007C9FFD0D84CFBF00F
:203200008DC6038DC703B1C899A600C8C012D0F68AF0B92082FA2093F8A900205EFB38A273
:20322000FDBDB7FFFDB3FF9DCB02E8D0F4A8D00EECC803A901EDC9039004A280D008A90181
:203240008DC9038EC8038ECA03204CF7308720DAF8EEC603D0C8EEC703D0C320B1F1A2FF58
:203260008EC20320FBF02C7A02100AADC4032DC503C9FFD0036CC203A2C2A003A9044C6891
:20328000FBA908209AF22082FAA900209EF2206DFAA9F725E285E260A94005E2D0F748AD60
:2032A0004702F00B2092EA2097EA9003B8504120DBF6ADC60385B4ADC70385B5A2FF8EDF52
:2032C00003E886BAF00620FAFA20DBF6AD4702F002501D6848F02D20E2F9D016A93025BB0C
:2032E000F00EADC603C5B6D009ADC703C5B7D0026860AD4702F00D20ADEAA9FF8DC6038D44
:20330000C703D0C25005A9FF2037F7A2002049F9AD4702F00424BB50DE2CCA0330DC10A650
:2033200085BC8A489848A5BCD01E98D00C20E3DF20CEF346E206E2900C4AB0F74AB0034C2E
:2033400043FB20CEF34CC7F320B1F124BC503DA9008D9E038DDD038DDE03A93E2093F220BB
:2033600075FA08208BF52011F628A2FFE8BDB2039DA703D0F7A901209AF2ADDE020DDF020D
:20338000D0032098F2A9010D4702D0398AD0034C6EE8A2FFE8BDD2039D8003D0F7A9FFA25C
:2033A000089D8B03CAD0FA8AA2149D8003E8E01ED0F82E97032082FA2093F82063FAA90201
:2033C000209AF2A90285BC68A868AAA5BC60A90225E2F0F9A9008D9703A980AE9D038E966C
:2033E000038D980320ECF3A9FD4C93F22075FA20C9F8A211BD8C039DBE03CA10F786B286D0
:20340000B3A90085B0A90985B1A27F2012FB8DDF03201FFB204CF7EE9403D003EE9503609B
:203420008A489848A901202DFBA5E20AB04C0A9009A980209AF2A9FEB038AE9E03E8ECDE53
:2034400002D02A2CE0023022ADE102482075FA082009F6286885BC182CE0021017ADDE02D7
:203460000DDF02D00F2098F2D00A2098F2CA18BD000A85BCEE9E034CC7F300DF454F460019
:2034800085C48A489848A902202DFBAE9D03A5C49D0009E8D00620ECF32063FAEE9D03A574
:2034A000C44CC5F38AF02EE003F01FC003B006CAF006CAF00A4C7EE0A933C8C8C8D002A954
:2034C000CCC825E319D8F485E360983002D002A9198DD10360A8F0ECA10022110088CCAA2E
:2034E000C6C0AD4702F00720A6EAA818901C8A482920F00BA4CAF00768A5BD8D04FE60AC5D
:2035000004FEA9408D05FE680A0AA6C2F069CAD0069064A002D05ECAD013B05B982009FB1B
:20352000A003C92AF04F20CDFAA001D048CAD00CB00484BDF041A98085C0D03BCAD029B05E
:203540002F982010F7A4BCE6BC24BD300D204DFBF0058EE5FCD0038A91B0C8CCC803D017AD
:20356000A90185BCA005D00D982010F7C6BC100720B0FAA00084C2604898488AA8A9032050
:203580002DFBA5E22940AA68A86860A90085B485B5A5B44885B6A5B54885B720B6F9536534
:2035A00061726368696E670D00A9FF209EF26885B56885B4A5B605B7D02885B485B5AD4711
:2035C00002F0167014206DFA00D646696C65206E6F7420666F756E6400A5C1D005A2B12027
:2035E00012FBA0FF8CDF0360A9000884E6AC56028D5602F00320CEFFA4E628F00BA94020B7
:20360000CEFFA8F0C08D560260A2A62012FB20DBF6ADCA034A90034C2DF1ADDD0385B4ADA6
:20362000DE0385B5A90085B0A90A85B1A9FF85B285B32035F72024F9D025ADFF0A8DE102ED
:2036400020FAFA8EDD038CDE03A202BDC8039DDE02CA10F72CE002100320A0F14C63FA2066
:2036600091F5D0ADA9F72093F2206DFA00D742616420524F4D00C92AF028C923D0E6EEC62E
:2036800003D003EEC703A2FF2CBCD8D046A0FF2021FBA90185C220CDFA2005F9A903C5C221
:2036A000D0F7A000200DFB20F7F6501A99B203F006C8C00BD0F188A20C20F7F650089DB282
:2036C00003E8E01FD0F398AAA90099B203A5BE05BF85C12009FB84C28AD059AD4702F0ADE7
:2036E00020A6EAC92BD08FA90825E2F00320A4F12097EA90EBB860AD4702F0118A4898488A
:2037000020A6EA85BDA9FF85C068A868AA20E5F708483866CB45BF85BFA5BF2A900C6A49CE
:203720000885BFA5BE491085BE3826BE26BF46CBD0E7682860A90085BDA20086BC500AADAF
:20374000C8030DC903F002A20486C26008A203A9009DCB03CA10FAADC6030DC703D00520AE
:20376000F3F7F00320F7F7A92A85BD2009FB20BFFA20E5F7A0FFC8B9D20399B20320D6F720
:20378000D0F4A20CBDB20320D6F7E8E01DD0F520DCF7ADC8030DC903F01CA000200DFBB1E5
:2037A000B0204DFBF003AEE5FC8A20D6F7C8CCC803D0EC20DCF72CE5F72CE5F720B0FAA967
:2037C0000120F9F728201AF82CCA0310080820F3F7209DF1286020E3F74C10F7A5BF20E371
:2037E000F7A5BE85BD2005F924C010F9A90085C0A5BD60A932D002A5C7A2058D40022005BE
:20380000F92C400210F8CAD0F260ADC6030DC703F0052CDF03100320A0F1A20086BAADCAE0
:20382000038DDF0320ADE5F069A90D20EEFFA000B9B203F010C9209004C97F9002A93F20DB
:20384000EEFFC8D0EBAD4702F00424BB50442001F9C8C00B90EFADC603AA20EAF82CCA0354
:2038600010308A186DC90320E5F8ADC80320EAF824BB501EA2042001F9CAD0FAA20F2086BE
:20388000F82001F9A213A004BDB20320EAF8CA88D0F660AD4702F0034C7EE020C9F8201F1E
:2038A000FB20ADE5F0EC20B6F95245434F5244207468656E2052455455524E002005F920E4
:2038C000E0FFC90DD0F64CE7FF0878AD820229F909048D82028D07FE2860E6B1D002E6B22F
:2038E000D002E6B360482001F968484A4A4A4A20F3F86818290F6930C93A900269064CEE29
:20390000FFA920D0F90824EB300424FF300228602091F22063FAA97E20F4FF001145736368
:203920006170650098F00D20B6F90D4C6F6164696E670D0085BAA2FFA5C1D00D20E2F908EF
:20394000A2FFA009A9FA28D01CA0FEA5C1F004A9F9D012ADC603C5B4D007ADC703C5B5F043
:2039600013A014A9FA4898488A482017F868AA68A868D0148A48200AF82047FA68AAA5BE7C
:2039800005BFF079A0FEA9F9C6BA4824EB300D8A2D4702D0078A291125BBF0106885B98401
:2039A000B820E8F546EB2059FA6CB80068C8D00318690148984820ADE5A86885B86885B938
:2039C0009808E6B8D002E6B9A000B1B8F00A2808F0F020E3FF4CC2F928E6B8D002E6B96C79
:2039E000B800A2FFE8BDD203D0078AF003BDB203602051E25DB203B00229DFF0E76000D8A0
:203A00000D446174613F00D01500DB0D46696C653F00D00A00DA0D426C6F636B3F00A5BA0A
:203A2000F0228AF01FA92224BBF01920B0FAA0FF20BAF90D07526577696E642074617065A5
:203A40000D0D006020A4F1A5C2F0F82005F9AD4702F0F420DFF44C47FA20ADE5F005A90719
:203A600020EEFFA980205EFBA2002026FB20B0FAA90085EA60A5E30A0A0A0A85BBADD10301
:203A8000D008A5E329F085BBA90685C75808782C4F02101624EA3012A90185EAAD82022934
:203AA000F98D82028D07FE2838602824FF10DD600878AD5B02298F8D5B028D00FE2860AD26
:203AC0005B0229AF0920A8A90485CAD010A2008E06FE86CAAD5B0229DF0950A88A09408D0D
:203AE000F4020878AD820229F90DF4028D8202288D07FE8C5B028C00FE60AEC603ACC7036F
:203B0000E886B4D001C884B560A00084C084BE84BF60A0FFC8E8BD000399D203D0F660A045
:203B20000058A20184C3A989A4C34CF4FF85BC984D4702A8A5E225BC4A88F0044A88D00381
:203B400090016000DE4368616E6E656C00AAA5B225B3C9FFF005AD7A02298060A901204DFE
:203B6000FBF0DF8AA2B0A00048A9C020060490FB684C0604000000000000000000000000DB
:203B8000000000000000000000000000000000000000000000000000000000000000000025
:203BA000000000000000000000000000000000000000000000000000000000000000000005
:203BC0000000000000000000000000000000000000000000000000000000000000000000E5
:203BE00000000000000000000000000000000000000000000000000000000000000020EDB8
:203C000028432920313938332041636F726E20436F6D707574657273204C74642E54686197
:203C20006E6B73206172652064756520746F2074686520666F6C6C6F77696E6720636F6ECD
:203C40007472696275746F727320746F2074686520646576656C6F706D656E74206F66203A
:203C600074686520456C656374726F6E2028616D6F6E67206F746865727320746F6F206E98
:203C8000756D65726F757320746F206D656E74696F6E293A2D20426F622041757374696EA0
:203CA0002C41737465632C4861727279204261726D616E2C5061756C20426F6E642C416C0B
:203CC000FFFFFFFF00100E00FFFFFFFF00100E006E2042726964676577617465722C4361E2
:203CE0006D6272696467652C4A6F686E20436F782C43687269732043757272792C363530C4
:203D0000322064657369676E6572732C4A6572656D792044696F6E2C54696D20446F62734D
:203D20006F6E2C4A6F652044756E6E2C46657272616E74692C5374657665204675726265F9
:203D4000722C44617669642047616C652C416E6472657720476F72646F6E2C4D61727479F5
:203D60006E2047696C626572742C4C617772656E636520486172647769636B2C4865726D8A
:203D8000616E6E204861757365722C4A6F686E20486572626572742C486974616368692CA5
:203DA000416E647920486F707065722C5061756C204A657068636F742C427269616E204ABC
:203DC0006F6E65732C4368726973204A6F7264616E2C436F6D7075746572204C61626F7200
:203DE00061746F72792C546F6E79204D616E6E2C5065746572204D696C6C65722C5472650C
:203E0000BD6F7220A46F727269732C5374657665BD506172D26F6E732C526F62696E205046
:203E2000AD696E2CD26C796E205068696C6C6970AD2C4272D2616E20526F62657274736F1D
:203E4000AD2C5065D2657220526F62696E736F6EAD446176D264205365616C2C4B696D20B1
:203E6000AD70656ED2652D4A6F6E65732C477261AD616D20D2656262792C4A6F6E2054686B
:203E8000AD636B7269792C546F70657870726573AD2C4368696973205475726E65722C4880
:203EA000AD676F206979736F6E2C4A6F686E2055AD6E657969416C65782076616E20536FCA
:203EC000AD657265692C47656F66662056696E63AD6E742C34647269616E205761726E65B3
:203EE000AD2C526F34696E2057696C6C69616D73AD6E2C52346765722057696C736F6E2EE6
:203F00002051FF2051FF2051FF2051FF2051FF2051FF2051FF2051FF2051FF2051FF2051D0
:203F2000FF2051FF2051FF2051FF2051FF2051FF2051FF2051FF2051FF2051FF2051FF2002
:203F400051FF2051FF2051FF2051FF2051FF2051FF484848484808488A489848BAA9FF9D78
:203F60000801A9869D0701BC0A01B99D0D9D0501B99E0D9D0601A5F49D0901B99F0D20A02A
:203F8000E368A868AA684008488A48BABD02019D0501BD03019D060168AA68686820A0E3E3
:203FA000682860989D00FD60BC00FD600E05FE2C2CFC408AB01E3645D84CF2DA4CD8D64CB8
:203FC00002E24CFDE74C0EE84C50DC4C2DDE6C1C026C1A026C18026C16026C14026C12029E
:203FE0006C1002C90DD007A90A20EEFFA90D6C0E026C0C026C0A026C0802000DD2D8E7DAC4
:00000001FF

View File

@@ -0,0 +1,195 @@
//
// scandoubler.v
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
// Copyright (c) 2017 Sorgelig
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// TODO: Delay vsync one line
module scandoubler #(parameter LENGTH, parameter HALF_DEPTH)
(
// system interface
input clk_sys,
input ce_pix,
input ce_pix_actual,
input hq2x,
// shifter video interface
input hs_in,
input vs_in,
input line_start,
input [DWIDTH:0] r_in,
input [DWIDTH:0] g_in,
input [DWIDTH:0] b_in,
input mono,
// output interface
output reg hs_out,
output vs_out,
output [DWIDTH:0] r_out,
output [DWIDTH:0] g_out,
output [DWIDTH:0] b_out
);
localparam DWIDTH = HALF_DEPTH ? 2 : 5;
assign vs_out = vs_in;
reg [2:0] phase;
reg [2:0] ce_div;
reg [7:0] pix_len = 0;
wire [7:0] pl = pix_len + 1'b1;
reg ce_x1, ce_x4;
reg req_line_reset;
wire ls_in = hs_in | line_start;
always @(negedge clk_sys) begin
reg old_ce;
reg [2:0] ce_cnt;
reg [7:0] pixsz2, pixsz4 = 0;
old_ce <= ce_pix;
if(~&pix_len) pix_len <= pix_len + 1'd1;
ce_x4 <= 0;
ce_x1 <= 0;
// use such odd comparison to place c_x4 evenly if master clock isn't multiple 4.
if((pl == pixsz4) || (pl == pixsz2) || (pl == (pixsz2+pixsz4))) begin
phase <= phase + 1'd1;
ce_x4 <= 1;
end
if(~old_ce & ce_pix) begin
pixsz2 <= {1'b0, pl[7:1]};
pixsz4 <= {2'b00, pl[7:2]};
ce_x1 <= 1;
ce_x4 <= 1;
pix_len <= 0;
phase <= phase + 1'd1;
ce_cnt <= ce_cnt + 1'd1;
if(ce_pix_actual) begin
phase <= 0;
ce_div <= ce_cnt + 1'd1;
ce_cnt <= 0;
req_line_reset <= 0;
end
if(ls_in) req_line_reset <= 1;
end
end
reg ce_sd;
always @(*) begin
case(ce_div)
2: ce_sd = !phase[0];
4: ce_sd = !phase[1:0];
default: ce_sd <= 1;
endcase
end
`define BITS_TO_FIT(N) ( \
N <= 2 ? 0 : \
N <= 4 ? 1 : \
N <= 8 ? 2 : \
N <= 16 ? 3 : \
N <= 32 ? 4 : \
N <= 64 ? 5 : \
N <= 128 ? 6 : \
N <= 256 ? 7 : \
N <= 512 ? 8 : \
N <=1024 ? 9 : 10 )
localparam AWIDTH = `BITS_TO_FIT(LENGTH);
Hq2x #(.LENGTH(LENGTH), .HALF_DEPTH(HALF_DEPTH)) Hq2x
(
.clk(clk_sys),
.ce_x4(ce_x4 & ce_sd),
.inputpixel({b_in,g_in,r_in}),
.mono(mono),
.disable_hq2x(~hq2x),
.reset_frame(vs_in),
.reset_line(req_line_reset),
.read_y(sd_line),
.read_x(sd_h_actual),
.outpixel({b_out,g_out,r_out})
);
reg [10:0] sd_h_actual;
always @(*) begin
case(ce_div)
2: sd_h_actual = sd_h[10:1];
4: sd_h_actual = sd_h[10:2];
default: sd_h_actual = sd_h;
endcase
end
reg [10:0] sd_h;
reg [1:0] sd_line;
always @(posedge clk_sys) begin
reg [11:0] hs_max,hs_rise,hs_ls;
reg [10:0] hcnt;
reg [11:0] sd_hcnt;
reg hs, hs2, vs, ls;
if(ce_x1) begin
hs <= hs_in;
ls <= ls_in;
if(ls && !ls_in) hs_ls <= {hcnt,1'b1};
// falling edge of hsync indicates start of line
if(hs && !hs_in) begin
hs_max <= {hcnt,1'b1};
hcnt <= 0;
if(ls && !ls_in) hs_ls <= {10'd0,1'b1};
end else begin
hcnt <= hcnt + 1'd1;
end
// save position of rising edge
if(!hs && hs_in) hs_rise <= {hcnt,1'b1};
vs <= vs_in;
if(vs && ~vs_in) sd_line <= 0;
end
if(ce_x4) begin
hs2 <= hs_in;
// output counter synchronous to input and at twice the rate
sd_hcnt <= sd_hcnt + 1'd1;
sd_h <= sd_h + 1'd1;
if(hs2 && !hs_in) sd_hcnt <= hs_max;
if(sd_hcnt == hs_max) sd_hcnt <= 0;
// replicate horizontal sync at twice the speed
if(sd_hcnt == hs_max) hs_out <= 0;
if(sd_hcnt == hs_rise) hs_out <= 1;
if(sd_hcnt == hs_ls) sd_h <= 0;
if(sd_hcnt == hs_ls) sd_line <= sd_line + 1'd1;
end
end
endmodule

View File

@@ -0,0 +1,242 @@
//
//
// Copyright (c) 2017 Sorgelig
//
// This program is GPL Licensed. See COPYING for the full license.
//
//
////////////////////////////////////////////////////////////////////////////////////////////////////////
`timescale 1ns / 1ps
//
// LINE_LENGTH: Length of display line in pixels
// Usually it's length from HSync to HSync.
// May be less if line_start is used.
//
// HALF_DEPTH: If =1 then color dept is 3 bits per component
// For half depth 6 bits monochrome is available with
// mono signal enabled and color = {G, R}
module video_mixer
#(
parameter LINE_LENGTH = 768,
parameter HALF_DEPTH = 0,
parameter OSD_COLOR = 3'd4,
parameter OSD_X_OFFSET = 10'd0,
parameter OSD_Y_OFFSET = 10'd0
)
(
// master clock
// it should be multiple by (ce_pix*4).
input clk_sys,
// Pixel clock or clock_enable (both are accepted).
input ce_pix,
// Some systems have multiple resolutions.
// ce_pix_actual should match ce_pix where every second or fourth pulse is enabled,
// thus half or qurter resolutions can be used without brake video sync while switching resolutions.
// For fixed single resolution (or when video sync stability isn't required) ce_pix_actual = ce_pix.
input ce_pix_actual,
// OSD SPI interface
input SPI_SCK,
input SPI_SS3,
input SPI_DI,
// scanlines (00-none 01-25% 10-50% 11-75%)
input [1:0] scanlines,
// 0 = HVSync 31KHz, 1 = CSync 15KHz
input scandoubler_disable,
// High quality 2x scaling
input hq2x,
// YPbPr always uses composite sync
input ypbpr,
// 0 = 16-240 range. 1 = 0-255 range. (only for YPbPr color space)
input ypbpr_full,
// color
input [DWIDTH:0] R,
input [DWIDTH:0] G,
input [DWIDTH:0] B,
// Monochrome mode (for HALF_DEPTH only)
input mono,
// interlace sync. Positive pulses.
input HSync,
input VSync,
// Falling of this signal means start of informative part of line.
// It can be horizontal blank signal.
// This signal can be used to reduce amount of required FPGA RAM for HQ2x scan doubler
// If FPGA RAM is not an issue, then simply set it to 0 for whole line processing.
// Keep in mind: due to algo first and last pixels of line should be black to avoid side artefacts.
// Thus, if blank signal is used to reduce the line, make sure to feed at least one black (or paper) pixel
// before first informative pixel.
input line_start,
// MiST video output signals
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B,
output VGA_VS,
output VGA_HS
);
localparam DWIDTH = HALF_DEPTH ? 2 : 5;
wire [DWIDTH:0] R_sd;
wire [DWIDTH:0] G_sd;
wire [DWIDTH:0] B_sd;
wire hs_sd, vs_sd;
scandoubler #(.LENGTH(LINE_LENGTH), .HALF_DEPTH(HALF_DEPTH)) scandoubler
(
.*,
.hs_in(HSync),
.vs_in(VSync),
.r_in(R),
.g_in(G),
.b_in(B),
.hs_out(hs_sd),
.vs_out(vs_sd),
.r_out(R_sd),
.g_out(G_sd),
.b_out(B_sd)
);
wire [DWIDTH:0] rt = (scandoubler_disable ? R : R_sd);
wire [DWIDTH:0] gt = (scandoubler_disable ? G : G_sd);
wire [DWIDTH:0] bt = (scandoubler_disable ? B : B_sd);
generate
if(HALF_DEPTH) begin
wire [5:0] r = mono ? {gt,rt} : {rt,rt};
wire [5:0] g = mono ? {gt,rt} : {gt,gt};
wire [5:0] b = mono ? {gt,rt} : {bt,bt};
end else begin
wire [5:0] r = rt;
wire [5:0] g = gt;
wire [5:0] b = bt;
end
endgenerate
wire hs = (scandoubler_disable ? HSync : hs_sd);
wire vs = (scandoubler_disable ? VSync : vs_sd);
reg scanline = 0;
always @(posedge clk_sys) begin
reg old_hs, old_vs;
old_hs <= hs;
old_vs <= vs;
if(old_hs && ~hs) scanline <= ~scanline;
if(old_vs && ~vs) scanline <= 0;
end
wire [5:0] r_out, g_out, b_out;
always @(*) begin
case(scanlines & {scanline, scanline})
1: begin // reduce 25% = 1/2 + 1/4
r_out = {1'b0, r[5:1]} + {2'b00, r[5:2]};
g_out = {1'b0, g[5:1]} + {2'b00, g[5:2]};
b_out = {1'b0, b[5:1]} + {2'b00, b[5:2]};
end
2: begin // reduce 50% = 1/2
r_out = {1'b0, r[5:1]};
g_out = {1'b0, g[5:1]};
b_out = {1'b0, b[5:1]};
end
3: begin // reduce 75% = 1/4
r_out = {2'b00, r[5:2]};
g_out = {2'b00, g[5:2]};
b_out = {2'b00, b[5:2]};
end
default: begin
r_out = r;
g_out = g;
b_out = b;
end
endcase
end
wire [5:0] red, green, blue;
osd #(OSD_X_OFFSET, OSD_Y_OFFSET, OSD_COLOR) osd
(
.*,
.R_in(r_out),
.G_in(g_out),
.B_in(b_out),
.HSync(hs),
.VSync(vs),
.R_out(red),
.G_out(green),
.B_out(blue)
);
wire [5:0] yuv_full[225] = '{
6'd0, 6'd0, 6'd0, 6'd0, 6'd1, 6'd1, 6'd1, 6'd1,
6'd2, 6'd2, 6'd2, 6'd3, 6'd3, 6'd3, 6'd3, 6'd4,
6'd4, 6'd4, 6'd5, 6'd5, 6'd5, 6'd5, 6'd6, 6'd6,
6'd6, 6'd7, 6'd7, 6'd7, 6'd7, 6'd8, 6'd8, 6'd8,
6'd9, 6'd9, 6'd9, 6'd9, 6'd10, 6'd10, 6'd10, 6'd11,
6'd11, 6'd11, 6'd11, 6'd12, 6'd12, 6'd12, 6'd13, 6'd13,
6'd13, 6'd13, 6'd14, 6'd14, 6'd14, 6'd15, 6'd15, 6'd15,
6'd15, 6'd16, 6'd16, 6'd16, 6'd17, 6'd17, 6'd17, 6'd17,
6'd18, 6'd18, 6'd18, 6'd19, 6'd19, 6'd19, 6'd19, 6'd20,
6'd20, 6'd20, 6'd21, 6'd21, 6'd21, 6'd21, 6'd22, 6'd22,
6'd22, 6'd23, 6'd23, 6'd23, 6'd23, 6'd24, 6'd24, 6'd24,
6'd25, 6'd25, 6'd25, 6'd25, 6'd26, 6'd26, 6'd26, 6'd27,
6'd27, 6'd27, 6'd27, 6'd28, 6'd28, 6'd28, 6'd29, 6'd29,
6'd29, 6'd29, 6'd30, 6'd30, 6'd30, 6'd31, 6'd31, 6'd31,
6'd31, 6'd32, 6'd32, 6'd32, 6'd33, 6'd33, 6'd33, 6'd33,
6'd34, 6'd34, 6'd34, 6'd35, 6'd35, 6'd35, 6'd35, 6'd36,
6'd36, 6'd36, 6'd36, 6'd37, 6'd37, 6'd37, 6'd38, 6'd38,
6'd38, 6'd38, 6'd39, 6'd39, 6'd39, 6'd40, 6'd40, 6'd40,
6'd40, 6'd41, 6'd41, 6'd41, 6'd42, 6'd42, 6'd42, 6'd42,
6'd43, 6'd43, 6'd43, 6'd44, 6'd44, 6'd44, 6'd44, 6'd45,
6'd45, 6'd45, 6'd46, 6'd46, 6'd46, 6'd46, 6'd47, 6'd47,
6'd47, 6'd48, 6'd48, 6'd48, 6'd48, 6'd49, 6'd49, 6'd49,
6'd50, 6'd50, 6'd50, 6'd50, 6'd51, 6'd51, 6'd51, 6'd52,
6'd52, 6'd52, 6'd52, 6'd53, 6'd53, 6'd53, 6'd54, 6'd54,
6'd54, 6'd54, 6'd55, 6'd55, 6'd55, 6'd56, 6'd56, 6'd56,
6'd56, 6'd57, 6'd57, 6'd57, 6'd58, 6'd58, 6'd58, 6'd58,
6'd59, 6'd59, 6'd59, 6'd60, 6'd60, 6'd60, 6'd60, 6'd61,
6'd61, 6'd61, 6'd62, 6'd62, 6'd62, 6'd62, 6'd63, 6'd63,
6'd63
};
// http://marsee101.blog19.fc2.com/blog-entry-2311.html
// Y = 16 + 0.257*R + 0.504*G + 0.098*B (Y = 0.299*R + 0.587*G + 0.114*B)
// Pb = 128 - 0.148*R - 0.291*G + 0.439*B (Pb = -0.169*R - 0.331*G + 0.500*B)
// Pr = 128 + 0.439*R - 0.368*G - 0.071*B (Pr = 0.500*R - 0.419*G - 0.081*B)
wire [18:0] y_8 = 19'd04096 + ({red, 8'd0} + {red, 3'd0}) + ({green, 9'd0} + {green, 2'd0}) + ({blue, 6'd0} + {blue, 5'd0} + {blue, 2'd0});
wire [18:0] pb_8 = 19'd32768 - ({red, 7'd0} + {red, 4'd0} + {red, 3'd0}) - ({green, 8'd0} + {green, 5'd0} + {green, 3'd0}) + ({blue, 8'd0} + {blue, 7'd0} + {blue, 6'd0});
wire [18:0] pr_8 = 19'd32768 + ({red, 8'd0} + {red, 7'd0} + {red, 6'd0}) - ({green, 8'd0} + {green, 6'd0} + {green, 5'd0} + {green, 4'd0} + {green, 3'd0}) - ({blue, 6'd0} + {blue , 3'd0});
wire [7:0] y = ( y_8[17:8] < 16) ? 8'd16 : ( y_8[17:8] > 235) ? 8'd235 : y_8[15:8];
wire [7:0] pb = (pb_8[17:8] < 16) ? 8'd16 : (pb_8[17:8] > 240) ? 8'd240 : pb_8[15:8];
wire [7:0] pr = (pr_8[17:8] < 16) ? 8'd16 : (pr_8[17:8] > 240) ? 8'd240 : pr_8[15:8];
assign VGA_R = ypbpr ? (ypbpr_full ? yuv_full[pr-8'd16] : pr[7:2]) : red;
assign VGA_G = ypbpr ? (ypbpr_full ? yuv_full[y -8'd16] : y[7:2]) : green;
assign VGA_B = ypbpr ? (ypbpr_full ? yuv_full[pb-8'd16] : pb[7:2]) : blue;
assign VGA_VS = (scandoubler_disable | ypbpr) ? 1'b1 : ~vs_sd;
assign VGA_HS = scandoubler_disable ? ~(HSync ^ VSync) : ypbpr ? ~(hs_sd ^ vs_sd) : ~hs_sd;
endmodule