diff --git a/Apple - 2_MiST/AppleII_MiST.qpf b/Apple - 2_MiST/AppleII_MiST.qpf new file mode 100644 index 00000000..8ccbb8a1 --- /dev/null +++ b/Apple - 2_MiST/AppleII_MiST.qpf @@ -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 = 14:22:52 May 18, 2018 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "13.1" +DATE = "14:22:52 May 18, 2018" + +# Revisions + +PROJECT_REVISION = "AppleII_MiST" diff --git a/Apple - 2_MiST/AppleII_MiST.qsf b/Apple - 2_MiST/AppleII_MiST.qsf new file mode 100644 index 00000000..f8f6171b --- /dev/null +++ b/Apple - 2_MiST/AppleII_MiST.qsf @@ -0,0 +1,203 @@ +# -------------------------------------------------------------------------- # +# +# 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 = 14:29:19 May 18, 2018 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# AppleII_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. +# +# -------------------------------------------------------------------------- # + + + +# Project-Wide Assignments +# ======================== +set_global_assignment -name ORIGINAL_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "19:15:38 MAY 09, 2018" +set_global_assignment -name LAST_QUARTUS_VERSION 13.1 +set_global_assignment -name VHDL_FILE rtl/video_generator.vhd +set_global_assignment -name VHDL_FILE rtl/vga_controller.vhd +set_global_assignment -name VHDL_FILE rtl/timing_generator.vhd +set_global_assignment -name VHDL_FILE rtl/spi_controller.vhd +set_global_assignment -name VHDL_FILE rtl/PS2_Ctrl.vhd +set_global_assignment -name VHDL_FILE rtl/main_roms.vhd +set_global_assignment -name VHDL_FILE rtl/keyboard.vhd +set_global_assignment -name VHDL_FILE rtl/disk_ii_rom.vhd +set_global_assignment -name VHDL_FILE rtl/disk_ii.vhd +set_global_assignment -name VHDL_FILE rtl/cpu6502.vhd +set_global_assignment -name QIP_FILE rtl/CLK28MPLL.qip +set_global_assignment -name VHDL_FILE rtl/character_rom.vhd +set_global_assignment -name VHDL_FILE rtl/apple2.vhd +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name VERILOG_FILE rtl/pll.v +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_global_assignment -name VHDL_FILE rtl/dac.vhd +set_global_assignment -name QIP_FILE rtl/ram.qip +set_global_assignment -name SYSTEMVERILOG_FILE rtl/AppleII_MiST.sv + +# Pin & Location Assignments +# ========================== +set_location_assignment PIN_7 -to LED +set_location_assignment PIN_54 -to CLOCK_27 +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_13 -to CONF_DATA0 +set_location_assignment PIN_49 -to SDRAM_A[0] +set_location_assignment PIN_44 -to SDRAM_A[1] +set_location_assignment PIN_42 -to SDRAM_A[2] +set_location_assignment PIN_39 -to SDRAM_A[3] +set_location_assignment PIN_4 -to SDRAM_A[4] +set_location_assignment PIN_6 -to SDRAM_A[5] +set_location_assignment PIN_8 -to SDRAM_A[6] +set_location_assignment PIN_10 -to SDRAM_A[7] +set_location_assignment PIN_11 -to SDRAM_A[8] +set_location_assignment PIN_28 -to SDRAM_A[9] +set_location_assignment PIN_50 -to SDRAM_A[10] +set_location_assignment PIN_30 -to SDRAM_A[11] +set_location_assignment PIN_32 -to SDRAM_A[12] +set_location_assignment PIN_83 -to SDRAM_DQ[0] +set_location_assignment PIN_79 -to SDRAM_DQ[1] +set_location_assignment PIN_77 -to SDRAM_DQ[2] +set_location_assignment PIN_76 -to SDRAM_DQ[3] +set_location_assignment PIN_72 -to SDRAM_DQ[4] +set_location_assignment PIN_71 -to SDRAM_DQ[5] +set_location_assignment PIN_69 -to SDRAM_DQ[6] +set_location_assignment PIN_68 -to SDRAM_DQ[7] +set_location_assignment PIN_86 -to SDRAM_DQ[8] +set_location_assignment PIN_87 -to SDRAM_DQ[9] +set_location_assignment PIN_98 -to SDRAM_DQ[10] +set_location_assignment PIN_99 -to SDRAM_DQ[11] +set_location_assignment PIN_100 -to SDRAM_DQ[12] +set_location_assignment PIN_101 -to SDRAM_DQ[13] +set_location_assignment PIN_103 -to SDRAM_DQ[14] +set_location_assignment PIN_104 -to SDRAM_DQ[15] +set_location_assignment PIN_58 -to SDRAM_BA[0] +set_location_assignment PIN_51 -to SDRAM_BA[1] +set_location_assignment PIN_85 -to SDRAM_DQMH +set_location_assignment PIN_67 -to SDRAM_DQML +set_location_assignment PIN_60 -to SDRAM_nRAS +set_location_assignment PIN_64 -to SDRAM_nCAS +set_location_assignment PIN_66 -to SDRAM_nWE +set_location_assignment PIN_59 -to SDRAM_nCS +set_location_assignment PIN_33 -to SDRAM_CKE +set_location_assignment PIN_43 -to SDRAM_CLK +set_location_assignment PLL_1 -to "pll:pll|altpll:altpll_component" + +# Classic Timing Assignments +# ========================== +set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 +set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 +set_global_assignment -name TIMEQUEST_MULTICORNER_ANALYSIS ON +set_global_assignment -name TIMEQUEST_DO_CCPP_REMOVAL ON + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name TOP_LEVEL_ENTITY AppleII_MiST +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 + +# Fitter Assignments +# ================== +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +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 RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO" + +# Assembler Assignments +# ===================== +set_global_assignment -name USE_CONFIGURATION_DEVICE OFF +set_global_assignment -name GENERATE_RBF_FILE ON + +# Power Estimation Assignments +# ============================ +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)" + +# Advanced I/O Timing Assignments +# =============================== +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 + +# -------------------------- +# start ENTITY(AppleII_MiST) + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + 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 + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(AppleII_MiST) +# ------------------------ +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Apple - 2_MiST/README.MD b/Apple - 2_MiST/README.MD new file mode 100644 index 00000000..9fa65e10 --- /dev/null +++ b/Apple - 2_MiST/README.MD @@ -0,0 +1,197 @@ +Apple II on MiST + + +This is a reconstruction of an 1980s-era Apple ][+ implemented in VHDL for +FPGAs. + +Stephen A. Edwards, sedwards@cs.columbia.edu +http://www1.cs.columbia.edu/~sedwards +------------------------------ +The current implementation uses the Altera DE1/DE2 board and takes +advantage of its off-chip SRAM, VGA DAC, SD card, audio CODEC, and +PS/2 keyboard interface. + +It was designed to be fairly easy to port: the apple2.vhd file should +be implementation-agnostic: it only assumes the external availability +of 48K of RAM and a keyboard. + +It contains a simple read-only Disk II emulator that expects +"nibblized" disk images written raw onto an SD or MMC card (i.e., it +does not use a FAT or any other type of filesystem). + +The VGA controller (not part of an original Apple) doubles each line +and interprets the Apple's NTSC-compatible color signals to produce a color +640 X 480 VGA display with non-standard dot timing. +------------------------------ +To compile under Altera's Quartus software, open the +apple2fpga_DE1.qpf or apple2fpga_DE2.qpf project file and compile. +------------------------------ +VHDL files, in order of elaboration: + +timing_generator.vhd Timing signal generation, video counters +character_rom.vhd The beautiful 5 X 8 uppercase-only text font +video_generator.vhd Text, lores, and hires mode shift registers +main_roms.vhd D000-FFFF ROMs: Applesoft and the Monitor +cpu6502.vhd The 6502 CPU core +apple2.vhd Top-level of the Apple: mostly address decode +disk_ii_rom.vhd C600-C6FF ROM: Disk II bootstrap ROM +disk_ii.vhd Read-only Disk II emulator +vga_controller.vhd NTSC-to-VGA color interpolation, line doubler +PS2_Ctrl.vhd Low-level PS/2 keyboard interface +keyboard.vhd PS/2 keyboard-to-Apple interface +spi_controller.vhd SD/MMC card controller: reads raw tracks +i2c_controller.vhd Simple I2C bus driver; initializes the codec +wm8731_audio.vhd Controller for the Wolfson WM8731 audio codec +DE1_TOP.vhd Top-level entity for the Altera DE1 board +DE2_TOP.vhd Top-level entity for the Altera DE2 board +CLK28MPLL.vhd Altera-specific configuration for 28 MHz PLL + +Other files: + +dsk2nib.c Converts a 140K .dsk image file to the raw 228K + .nib format used by the Disk II emulator + +dsknib.sln Visual C++ Express 2008 solution file for + generating dsknib.exe under Windows + +dsknib.vcproj Visual C++ Express 2008 project file for + generating dsknib.exe under Windows + +makenibs A shell (e.g., bash) script that assembles + collections of .dsk files into a file suitable + for directly writing onto an SD card + +rom2vhdl Script to convert raw ROM files into + synthesizable VHDL code. Used to produce main_roms.vhd + +apple2fpga_DE1.qpf DE1 board project file for Altera's Quartus +apple2fpga_DE2.qpf DE2 board project file for Altera's Quartus +DE1_TOP.qsf Mostly pin assignments for Altera's Quartus +DE1_TOP.sof A compiled bitstream for the DE1 board: the + result of compiling all the VHDL files in + Quartus; suitable for programming if you have a + DE1 board. +DE2_TOP.qsf Mostly pin assignments for Altera's Quartus +DE2_TOP.sof A compiled bitstream for the DE2 board: the + result of compiling all the VHDL files in + Quartus; suitable for programming if you have a + DE2 board. + +dos33master.nib Bootable disk image: Apple DOS 3.3 system master + +bios.a65 6502 assembly source for a "fake" BIOS +bios.rom Binary data for the "fake" BIOS + +Makefile Rules for creating the .zip, .vhd files, etc. +------------------------------ +Disk images + +The system expects a sequence of "nibblized" (227K) disk images on the +SD card starting at block 0. Switches on the DE1/DE2 board selects +which image appears to be in the drive; the image number is displayed +in hex on two of the seven-segment displays. + +Most Apple II disk images are in 140K .dsk files, which stores only +the disk's logical data, i.e., is not encoded. dsk2nib.c is a small C +program that expands .dsk files to .nib files. + +I used the "makenibs" script to find all the .dsk files in a tree of +directories, assemble them into an image suitable for downloading to +the SD card, and print an image number/file name cross-listing. + +To write .nib images to an SD/MMC card under Linux, I use + +dd if=dos33master.nib of=/dev/sdd + +Of course, your card may appear as something other than /dev/sdd. + +Under Windows, you can use dd.exe (http://www.chrysocome.net/dd): + +dd.exe if=dos33master.nib of=\\?\Device\Harddiskx\Partition0 + +where the correct "Harddiskx" can be determined using the dd.exe +"--list" option: + +dd.exe --list + +------------------------------ +ROMs + +This archive does NOT include a copy of the Apple ][+'s ROMs, which +are copyright Apple Computer. Instead, it includes a very trivial +BIOS that beeps, displays a text screen, then cycles through some +lores and hires graphics patterns when keys are pressed. This should +be enough to verify the graphics, sound, and keyboard are working (but +not the disk emulator). Source for this BIOS is in the bios.a65 file, +which I assembled using the xa65 cross-assembler. + +The system requires two ROM images: a 12K image of the system roms +(memory from 0xD000 - 0xFFFF) and a 256-byte image of the Disk II +controller bootstrap ROM (memory from 0xc600 - 0xc6ff if the card is +in the usual slot 6). + +Once you obtain them, run the "rom2vhdl" script to convert the binary +files into .vhd files that hold the data. The Makefile contains rules +for doing this. +------------------------------ +Operation + +For the DE1 board: +KEY[3] Reset +KEY[2..0] Game Port +SW[9] B&W/Color Display +SW[8..0] Disk Image # (0 to 511) +HEX[2..3] Disk Image # (0 to 255 => 00 to FF hex) +HEX[1..0] Track # (0 to 35 => 00 to 23 hex) +LEDR[9..0] PC[15..6] (CPU Program Counter in 64-byte page unit) +LEDG[3] Unused +LEDG[2] Disk Drive #2 Activity +LEDG[1] Disk Drive #1 Activity +LEDG[0] Speaker Activity + +For the DE2 board: +KEY[3] Reset +KEY[2..0] Game Port +SW[17] B&W/Color Display +SW[16..10] Unused +SW[9..0] Disk Image # (0 to 1023) +HEX[7..6] Disk Image # (0 to 255 => 00 to FF hex) +HEX[5..4] Track # (0 to 35 => 00 to 23 hex) +HEX[3..0] PC[15..0] (CPU Program Counter, 0000 to FFFF hex) +LEDR[17..16] Unused +LEDR[15..0] PC[15..12] (CPU Program Counter in 4Kbyte page unit decoded) +LEDG[8] Disk Drive #1 Activity +LEDG[7..4] Analog Joystick Activity +LEDG[3..1] Unused +LEDG[0] Speaker Activity + +------------------------------ +Credits: + +Peter Wendrich supplied the 6502 core: + +-- cpu65xx_fast.vhdl, part of FPGA-64, is made available strictly for personal +-- educational purposes. Distributed with apple2fgpa with permission. +-- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com). +-- All rights reserved. +-- http://www.syntiac.com/fpga64.html + +The low-level PS/2 keyboard controller is from ALSE: + +-- PS2_Ctrl.vhd +-- ------------------------------------------------ +-- Simplified PS/2 Controller (kbd, mouse...) +-- ------------------------------------------------ +-- Only the Receive function is implemented ! +-- (c) ALSE. http://www.alse-fr.com + +Michel Stempin (michel.stempin@wanadoo.fr): + - ported apple2fpga to the Altera DE1 board + - added SD/SDHC to MMC Flash disk comptatibility + - added i18n + French keymap + +I adapted the Apple ][ keyboard emulation from Alex Freed's FPGApple: +http://mirrow.com/FPGApple/ + + diff --git a/Apple - 2_MiST/clean.bat b/Apple - 2_MiST/clean.bat new file mode 100644 index 00000000..748b4d5b --- /dev/null +++ b/Apple - 2_MiST/clean.bat @@ -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 diff --git a/Apple - 2_MiST/rtl/AppleII_MiST.sv b/Apple - 2_MiST/rtl/AppleII_MiST.sv new file mode 100644 index 00000000..2d7b6a5a --- /dev/null +++ b/Apple - 2_MiST/rtl/AppleII_MiST.sv @@ -0,0 +1,193 @@ +module AppleII_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 CONF_DATA0, + input CLOCK_27 +); + +`include "rtl\build_id.v" + +localparam CONF_STR = { + "Apple II;;", + "O12,Screen Type , Green, White, Color;", + "O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;", + "T6,Reset;", + "V,v1.00.",`BUILD_DATE +}; + +wire CLK_28M, CLK_14M, CLK_7M; +wire pll_locked; + +pll pll +( + .inclk0(CLOCK_27), + .areset(0), + .c0(CLK_28M), + .c1(CLK_14M), + .c2(CLK_7M), + .locked(pll_locked) +); + +wire [31:0] status; +wire [1:0] buttons; +wire [1:0] switches; +wire power_on_reset; +wire reset = power_on_reset | status[0] | status[6] | buttons[1]; +wire [22:0] flash_clk; +wire scandoubler_disable; +wire ypbpr; +wire ps2_kbd_clk, ps2_kbd_data; +wire [9:0] audio; +wire hsync,vsync; +assign LED = 1; +wire blankn = ~(hblank | vblank); +wire hblank, vblank; +wire hs, vs; +wire VIDEO, COLOR_LINE, LD194, speaker; +wire read; +wire [7:0] K; +wire [9:0] r,g,b; + + +always @(CLK_14M) begin + if (flash_clk[22] == 1'b1) power_on_reset = 1'b0; +end + +always @(CLK_14M) begin + //rising_edge(CLK_14M) then flash_clk <= flash_clk + 1; +end + +video_mixer #(.LINE_LENGTH(640), .HALF_DEPTH(0)) video_mixer ( + .clk_sys(CLK_28M), + .ce_pix(CLK_7M), + .ce_pix_actual(CLK_7M), + .SPI_SCK(SPI_SCK), + .SPI_SS3(SPI_SS3), + .SPI_DI(SPI_DI), + .R(status[2:1] ? r[9:4] : 5'b0), + .G(g[9:4]), + .B(status[2:1] ? b[9:4] : 5'b0), + .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), + .scanlines(scandoubler_disable ? 2'b00 : {status[4:3] == 3, status[4:3] == 2}), + .hq2x(status[4:3]==1), + .ypbpr_full(1), + .line_start(0), + .mono(0) + ); + +mist_io #(.STRLEN(($size(CONF_STR)>>3))) mist_io ( + .clk_sys (CLK_28M ), + .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_kbd_clk ), + .ps2_kbd_data (ps2_kbd_data ), + .status (status ) + ); + + wire ram_we; + wire [13:0]ram_address; + wire [7:0]ram_data; + wire [7:0]ram_q; + +ram ram( + .clock(CLK_14M), + .address(ram_address), + .data(ram_data), + .q(ram_q), + .wren(ram_we) + ); + +apple2 apple2 ( + .CLK_14M (CLK_14M), + .CLK_2M (),//: out std_logic; + .PRE_PHASE_ZERO (),//: out std_logic; + .FLASH_CLK (),//: in std_logic; -- approx. 2 Hz flashing char clock + .reset (reset), + .ADDR (),//: out unsigned(15 downto 0); -- CPU address + .ram_addr (ram_address),//: out unsigned(15 downto 0); -- RAM address + .D (ram_data),//: out unsigned(7 downto 0); -- Data to RAM + .ram_do (ram_q),//: in unsigned(7 downto 0); -- Data from RAM + .PD (),//: in unsigned(7 downto 0); -- Data to CPU from peripherals + .ram_we (ram_we),//: out std_logic; -- RAM write enable + .VIDEO (VIDEO), + .COLOR_LINE (COLOR_LINE), + .HBL (hblank), + .VBL (vblank), + .LD194 (LD194), + .K (K), + .READ_KEY (read), + .AN (),//: out std_logic_vector(3 downto 0); -- Annunciator outputs +// GAMEPORT input bits: +// 7 6 5 4 3 2 1 0 +// pdl3 pdl2 pdl1 pdl0 pb3 pb2 pb1 casette + .GAMEPORT (),//: in std_logic_vector(7 downto 0); + .PDL_STROBE (),//: out std_logic; -- Pulses high when C07x read + .STB (),//: out std_logic; -- Pulses high when C04x read + .IO_SELECT (),//: out std_logic_vector(7 downto 0); + .DEVICE_SELECT (),//: out std_logic_vector(7 downto 0); + .pcDebugOut (),//: out unsigned(15 downto 0); + .opcodeDebugOut (),//: out unsigned(7 downto 0); + .speaker (speaker) + ); + +keyboard keyboard ( + .PS2_Clk (ps2_kbd_clk), + .PS2_Data (ps2_kbd_data), + .CLK_14M (CLK_14M), + .reset (reset), + .read (read), + .K (K), + ); + +vga_controller vga_controller ( + .CLK_28M (CLK_28M), + .VIDEO (VIDEO), + .COLOR_LINE (COLOR_LINE), + .COLOR (status[2:1]==2), + .HBL (hblank), + .VBL (vblank), + .LD194 (LD194), + .VGA_HS (hs), + .VGA_VS (vs), + .VGA_R (r), + .VGA_G (g), + .VGA_B (b), + ); + +dac dac ( + .CLK_DAC (CLK_28M), + .RST (), + .IN_DAC (speaker & 15'b0), + .OUT_DAC (AUDIO_L) + ); + +assign AUDIO_R = AUDIO_L; + + +endmodule diff --git a/Apple - 2_MiST/rtl/CLK28MPLL.qip b/Apple - 2_MiST/rtl/CLK28MPLL.qip new file mode 100644 index 00000000..cc9b8ee1 --- /dev/null +++ b/Apple - 2_MiST/rtl/CLK28MPLL.qip @@ -0,0 +1,5 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "8.0" +set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "CLK28MPLL.vhd"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "CLK28MPLL.cmp"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "CLK28MPLL.ppf"] diff --git a/Apple - 2_MiST/rtl/CLK28MPLL.vhd b/Apple - 2_MiST/rtl/CLK28MPLL.vhd new file mode 100644 index 00000000..fd691165 --- /dev/null +++ b/Apple - 2_MiST/rtl/CLK28MPLL.vhd @@ -0,0 +1,376 @@ +-- megafunction wizard: %ALTPLL% +-- GENERATION: STANDARD +-- VERSION: WM1.0 +-- MODULE: altpll + +-- ============================================================ +-- File Name: CLK28MPLL.vhd +-- Megafunction Name(s): +-- altpll +-- +-- Simulation Library Files(s): +-- altera_mf +-- ============================================================ +-- ************************************************************ +-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE! +-- +-- 8.0 Build 215 05/29/2008 SJ Full Version +-- ************************************************************ + + +--Copyright (C) 1991-2008 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 CLK28MPLL IS + PORT + ( + inclk0 : IN STD_LOGIC := '0'; + c0 : OUT STD_LOGIC ; + c1 : OUT STD_LOGIC + ); +END CLK28MPLL; + + +ARCHITECTURE SYN OF clk28mpll IS + + SIGNAL sub_wire0 : STD_LOGIC_VECTOR (5 DOWNTO 0); + SIGNAL sub_wire1 : STD_LOGIC ; + SIGNAL sub_wire2 : STD_LOGIC ; + SIGNAL sub_wire3 : STD_LOGIC ; + SIGNAL sub_wire4 : STD_LOGIC_VECTOR (1 DOWNTO 0); + SIGNAL sub_wire5_bv : BIT_VECTOR (0 DOWNTO 0); + SIGNAL sub_wire5 : STD_LOGIC_VECTOR (0 DOWNTO 0); + + + + COMPONENT altpll + GENERIC ( + 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; + compensate_clock : STRING; + inclk0_input_frequency : NATURAL; + intended_device_family : STRING; + lpm_hint : STRING; + lpm_type : STRING; + operation_mode : 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 + ); + PORT ( + inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0); + clk : OUT STD_LOGIC_VECTOR (5 DOWNTO 0) + ); + END COMPONENT; + +BEGIN + sub_wire5_bv(0 DOWNTO 0) <= "0"; + sub_wire5 <= To_stdlogicvector(sub_wire5_bv); + sub_wire2 <= sub_wire0(1); + sub_wire1 <= sub_wire0(0); + c0 <= sub_wire1; + c1 <= sub_wire2; + sub_wire3 <= inclk0; + sub_wire4 <= sub_wire5(0 DOWNTO 0) & sub_wire3; + + altpll_component : altpll + GENERIC MAP ( + clk0_divide_by => 250, + clk0_duty_cycle => 50, + clk0_multiply_by => 143, + clk0_phase_shift => "0", + clk1_divide_by => 500, + clk1_duty_cycle => 50, + clk1_multiply_by => 143, + clk1_phase_shift => "0", + compensate_clock => "CLK0", + inclk0_input_frequency => 20000, + intended_device_family => "Cyclone II", + lpm_hint => "CBX_MODULE_PREFIX=CLK28MPLL", + lpm_type => "altpll", + operation_mode => "NORMAL", + 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_UNUSED", + port_clk3 => "PORT_UNUSED", + 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" + ) + PORT MAP ( + inclk => sub_wire4, + 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 "0" +-- 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_CUSTOM STRING "0" +-- 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 "1" +-- 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 "e0" +-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "6" +-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "18" +-- Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "1" +-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +-- Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +-- 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 "1" +-- 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 "50.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 II" +-- 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: MIG_DEVICE_SPEED_GRADE STRING "Any" +-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0" +-- Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0" +-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "5" +-- Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "1" +-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "28.60000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.30000000" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "1" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "0" +-- 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_SHIFT_STEP_ENABLED_CHECK STRING "0" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "ps" +-- 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_ENA_CHECK STRING "0" +-- 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 "CLK14MPLL.mif" +-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0" +-- 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: 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_CLKENA0 STRING "0" +-- Retrieval info: PRIVATE: USE_CLKENA1 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: CLK0_DIVIDE_BY NUMERIC "250" +-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "143" +-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "500" +-- Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +-- Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "143" +-- Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20000" +-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II" +-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +-- 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_UNUSED" +-- Retrieval info: CONSTANT: PORT_clk3 STRING "PORT_UNUSED" +-- 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: USED_PORT: @clk 0 0 6 0 OUTPUT_CLK_EXT VCC "@clk[5..0]" +-- Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT_CLK_EXT VCC "@extclk[3..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: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +-- 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: @inclk 0 0 1 1 GND 0 0 0 0 +-- Retrieval info: GEN_FILE: TYPE_NORMAL CLK28MPLL.vhd TRUE FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL CLK28MPLL.ppf TRUE FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL CLK28MPLL.inc FALSE FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL CLK28MPLL.cmp TRUE FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL CLK28MPLL.bsf FALSE FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL CLK28MPLL_inst.vhd FALSE FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL CLK28MPLL_waveforms.html FALSE FALSE +-- Retrieval info: GEN_FILE: TYPE_NORMAL CLK28MPLL_wave*.jpg FALSE FALSE +-- Retrieval info: LIB_FILE: altera_mf +-- Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Apple - 2_MiST/rtl/PS2_Ctrl.vhd b/Apple - 2_MiST/rtl/PS2_Ctrl.vhd new file mode 100644 index 00000000..6421c754 --- /dev/null +++ b/Apple - 2_MiST/rtl/PS2_Ctrl.vhd @@ -0,0 +1,147 @@ +-- PS2_Ctrl.vhd +-- ------------------------------------------------ +-- Simplified PS/2 Controller (kbd, mouse...) +-- ------------------------------------------------ +-- Only the Receive function is implemented ! +-- (c) ALSE. http://www.alse-fr.com + +library IEEE; +use IEEE.Std_Logic_1164.all; +use IEEE.Numeric_Std.all; + +-- -------------------------------------- + Entity PS2_Ctrl is +-- -------------------------------------- + generic (FilterSize : positive := 8); + port( Clk : in std_logic; -- System Clock + Reset : in std_logic; -- System Reset + PS2_Clk : in std_logic; -- Keyboard Clock Line + PS2_Data : in std_logic; -- Keyboard Data Line + DoRead : in std_logic; -- From outside when reading the scan code + Scan_Err : out std_logic; -- To outside : Parity or Overflow error + Scan_DAV : out std_logic; -- To outside when a scan code has arrived + Scan_Code : out unsigned(7 downto 0) -- Eight bits Data Out + ); +end PS2_Ctrl; + +-- -------------------------------------- + Architecture ALSE_RTL of PS2_Ctrl is +-- -------------------------------------- +-- (c) ALSE. http://www.alse-fr.com +-- Author : Bert Cuzeau. +-- Fully synchronous solution, same Filter on PS2_Clk. +-- Still as compact as "Plain_wrong"... +-- Possible improvement : add TIMEOUT on PS2_Clk while shifting +-- Note: PS2_Data is resynchronized though this should not be +-- necessary (qualified by Fall_Clk and does not change at that time). +-- Note the tricks to correctly interpret 'H' as '1' in RTL simulation. + + signal PS2_Datr : std_logic; + + subtype Filter_t is std_logic_vector(FilterSize-1 downto 0); + signal Filter : Filter_t; + signal Fall_Clk : std_logic; + signal Bit_Cnt : unsigned(3 downto 0); + signal Parity : std_logic; + signal Scan_DAVi : std_logic; + + signal S_Reg : unsigned(8 downto 0); + + signal PS2_Clk_f : std_logic; + + Type State_t is (Idle, Shifting); + signal State : State_t; + +begin + +Scan_DAV <= Scan_DAVi; + +-- This filters digitally the raw clock signal coming from the keyboard : +-- * Eight consecutive PS2_Clk=1 makes the filtered_clock go high +-- * Eight consecutive PS2_Clk=0 makes the filtered_clock go low +-- Implies a (FilterSize+1) x Tsys_clock delay on Fall_Clk wrt Data +-- Also in charge of the re-synchronization of PS2_Data + +process (Clk,Reset) +begin + if Reset='1' then + PS2_Datr <= '0'; + PS2_Clk_f <= '0'; + Filter <= (others=>'0'); + Fall_Clk <= '0'; + elsif rising_edge (Clk) then + PS2_Datr <= PS2_Data and PS2_Data; -- also turns 'H' into '1' + Fall_Clk <= '0'; + Filter <= (PS2_Clk and PS2_CLK) & Filter(Filter'high downto 1); + if Filter = Filter_t'(others=>'1') then + PS2_Clk_f <= '1'; + elsif Filter = Filter_t'(others=>'0') then + PS2_Clk_f <= '0'; + if PS2_Clk_f = '1' then + Fall_Clk <= '1'; + end if; + end if; + end if; +end process; + + +-- This simple State Machine reads in the Serial Data +-- coming from the PS/2 peripheral. + +process(Clk,Reset) +begin + + if Reset='1' then + State <= Idle; + Bit_Cnt <= (others => '0'); + S_Reg <= (others => '0'); + Scan_Code <= (others => '0'); + Parity <= '0'; + Scan_Davi <= '0'; + Scan_Err <= '0'; + + elsif rising_edge (Clk) then + + if DoRead='1' then + Scan_Davi <= '0'; -- note: this assgnmnt can be overriden + end if; + + case State is + + when Idle => + Parity <= '0'; + Bit_Cnt <= (others => '0'); + -- note that we dont need to clear the Shift Register + if Fall_Clk='1' and PS2_Datr='0' then -- Start bit + Scan_Err <= '0'; + State <= Shifting; + end if; + + when Shifting => + if Bit_Cnt >= 9 then + if Fall_Clk='1' then -- Stop Bit + -- Error is (wrong Parity) or (Stop='0') or Overflow + Scan_Err <= (not Parity) or (not PS2_Datr) or Scan_DAVi; + Scan_Davi <= '1'; + Scan_Code <= S_Reg(7 downto 0); + State <= Idle; + end if; + elsif Fall_Clk='1' then + Bit_Cnt <= Bit_Cnt + 1; + S_Reg <= PS2_Datr & S_Reg (S_Reg'high downto 1); -- Shift right + Parity <= Parity xor PS2_Datr; + end if; + + when others => -- never reached + State <= Idle; + + end case; + + --Scan_Err <= '0'; -- to create an on-purpose error on Scan_Err ! + + end if; + +end process; + +end ALSE_RTL; + diff --git a/Apple - 2_MiST/rtl/apple2.vhd b/Apple - 2_MiST/rtl/apple2.vhd new file mode 100644 index 00000000..f3b697c1 --- /dev/null +++ b/Apple - 2_MiST/rtl/apple2.vhd @@ -0,0 +1,286 @@ +------------------------------------------------------------------------------- +-- +-- Top level of an Apple ][+ +-- +-- Stephen A. Edwards, sedwards@cs.columbia.edu +-- +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity apple2 is + port ( + CLK_14M : in std_logic; -- 14.31818 MHz master clock + CLK_2M : out std_logic; + PRE_PHASE_ZERO : out std_logic; + FLASH_CLK : in std_logic; -- approx. 2 Hz flashing char clock + reset : in std_logic; + ADDR : out unsigned(15 downto 0); -- CPU address + ram_addr : out unsigned(15 downto 0); -- RAM address + D : out unsigned(7 downto 0); -- Data to RAM + ram_do : in unsigned(7 downto 0); -- Data from RAM + PD : in unsigned(7 downto 0); -- Data to CPU from peripherals + ram_we : out std_logic; -- RAM write enable + VIDEO : out std_logic; + COLOR_LINE : out std_logic; + HBL : out std_logic; + VBL : out std_logic; + LD194 : out std_logic; + K : in unsigned(7 downto 0); -- Keyboard data + READ_KEY : out std_logic; -- Processor has read key + AN : out std_logic_vector(3 downto 0); -- Annunciator outputs + -- GAMEPORT input bits: + -- 7 6 5 4 3 2 1 0 + -- pdl3 pdl2 pdl1 pdl0 pb3 pb2 pb1 casette + GAMEPORT : in std_logic_vector(7 downto 0); + PDL_STROBE : out std_logic; -- Pulses high when C07x read + STB : out std_logic; -- Pulses high when C04x read + IO_SELECT : out std_logic_vector(7 downto 0); + DEVICE_SELECT : out std_logic_vector(7 downto 0); + pcDebugOut : out unsigned(15 downto 0); + opcodeDebugOut : out unsigned(7 downto 0); + speaker : out std_logic -- One-bit speaker output + ); +end apple2; + +architecture rtl of apple2 is + + -- Clocks + signal CLK_7M : std_logic; + signal Q3, RAS_N, CAS_N, AX : std_logic; + signal PHASE_ZERO, PRE_PHASE_ZERO_sig : std_logic; + signal COLOR_REF : std_logic; + + -- From the timing generator + signal VIDEO_ADDRESS : unsigned(15 downto 0); + signal LDPS_N : std_logic; + signal H0, VA, VB, VC, V2, V4 : std_logic; + signal BLANK, LD194_I : std_logic; + + signal HIRES : std_logic; -- from video generator B11 p6 + + -- Soft switches + signal soft_switches : std_logic_vector(7 downto 0) := "00000000"; + signal TEXT_MODE : std_logic; + signal MIXED_MODE : std_logic; + signal PAGE2 : std_logic; + signal HIRES_MODE : std_logic; + + -- CPU signals + signal D_IN : unsigned(7 downto 0); + signal A : unsigned(15 downto 0); + signal we : std_logic; + + -- Main ROM signals + signal rom_out : unsigned(7 downto 0); + signal rom_addr : unsigned(13 downto 0); + + -- Address decoder signals + signal RAM_SELECT : std_logic := '1'; + signal KEYBOARD_SELECT : std_logic := '0'; + signal SPEAKER_SELECT : std_logic; + signal SOFTSWITCH_SELECT : std_logic; + signal ROM_SELECT : std_logic; + signal GAMEPORT_SELECT : std_logic; + signal IO_STROBE : std_logic; + + -- Speaker signal + signal speaker_sig : std_logic := '0'; + + signal DL : unsigned(7 downto 0); -- Latched RAM data + +begin + + CLK_2M <= Q3; + PRE_PHASE_ZERO <= PRE_PHASE_ZERO_sig; + + ram_addr <= A when PHASE_ZERO = '1' else VIDEO_ADDRESS; + ram_we <= we and not RAS_N when PHASE_ZERO = '1' else '0'; + + -- Latch RAM data on the rising edge of RAS + RAM_data_latch : process (CLK_14M) + begin + if rising_edge(CLK_14M) then + if AX = '1' and CAS_N = '0' and RAS_N = '0' then + DL <= ram_do; + end if; + end if; + end process; + + ADDR <= A; + + -- Address decoding + rom_addr <= (A(13) and A(12)) & (not A(12)) & A(11 downto 0); + + address_decoder: process (A) + begin + ROM_SELECT <= '0'; + RAM_SELECT <= '0'; + KEYBOARD_SELECT <= '0'; + READ_KEY <= '0'; + SPEAKER_SELECT <= '0'; + SOFTSWITCH_SELECT <= '0'; + GAMEPORT_SELECT <= '0'; + PDL_STROBE <= '0'; + STB <= '0'; + IO_SELECT <= (others => '0'); + DEVICE_SELECT <= (others => '0'); + IO_STROBE <= '0'; + case A(15 downto 14) is + when "00" | "01" | "10" => -- 0000 - BFFF + RAM_SELECT <= '1'; + when "11" => -- C000 - FFFF + case A(13 downto 12) is + when "00" => -- C000 - CFFF + case A(11 downto 8) is + when x"0" => -- C000 - C0FF + case A(7 downto 4) is + when x"0" => -- C000 - C00F + KEYBOARD_SELECT <= '1'; + when x"1" => -- C010 - C01F + READ_KEY <= '1'; + when x"3" => -- C030 - C03F + SPEAKER_SELECT <= '1'; + when x"4" => + STB <= '1'; + when x"5" => -- C050 - C05F + SOFTSWITCH_SELECT <= '1'; + when x"6" => -- C060 - C06F + GAMEPORT_SELECT <= '1'; + when x"7" => -- C070 - C07F + PDL_STROBE <= '1'; + when x"8" | x"9" | x"A" | -- C080 - C0FF + x"B" | x"C" | x"D" | x"E" | x"F" => + DEVICE_SELECT(TO_INTEGER(A(6 downto 4))) <= '1'; + when others => null; + end case; + when x"1" | x"2" | x"3" | -- C100 - C7FF + x"4" | x"5" | x"6" | x"7" => + IO_SELECT(TO_INTEGER(A(10 downto 8))) <= '1'; + when x"8" | x"9" | x"A" | -- C800 - CFFF + x"B" | x"C" | x"D" | x"E" | x"F" => + IO_STROBE <= '1'; + when others => null; + end case; + when "01" | "10" | "11" => -- D000 - FFFF + ROM_SELECT <= '1'; + when others => + null; + end case; + when others => null; + end case; + end process address_decoder; + + speaker_ctrl: process (Q3) + begin + if rising_edge(Q3) then + if PRE_PHASE_ZERO_sig = '1' and SPEAKER_SELECT = '1' then + speaker_sig <= not speaker_sig; + end if; + end if; + end process speaker_ctrl; + + softswitches: process (Q3) + begin + if rising_edge(Q3) then + if PRE_PHASE_ZERO_sig = '1' and SOFTSWITCH_SELECT = '1' then + soft_switches(TO_INTEGER(A(3 downto 1))) <= A(0); + end if; + end if; + end process softswitches; + + TEXT_MODE <= soft_switches(0); + MIXED_MODE <= soft_switches(1); + PAGE2 <= soft_switches(2); + HIRES_MODE <= soft_switches(3); + AN <= soft_switches(7 downto 4); + + speaker <= speaker_sig; + + D_IN <= DL when RAM_SELECT = '1' else -- RAM + K when KEYBOARD_SELECT = '1' else -- Keyboard + GAMEPORT(TO_INTEGER(A(2 downto 0))) & "0000000" -- Gameport + when GAMEPORT_SELECT = '1' else + rom_out when ROM_SELECT = '1' else -- ROMs + PD; -- Peripherals + + LD194 <= LD194_I; + + timing : entity work.timing_generator port map ( + CLK_14M => CLK_14M, + CLK_7M => CLK_7M, + CAS_N => CAS_N, + RAS_N => RAS_N, + Q3 => Q3, + AX => AX, + PHI0 => PHASE_ZERO, + PRE_PHI0 => PRE_PHASE_ZERO_sig, + COLOR_REF => COLOR_REF, + TEXT_MODE => TEXT_MODE, + PAGE2 => PAGE2, + HIRES => HIRES, + VIDEO_ADDRESS => VIDEO_ADDRESS, + H0 => H0, + VA => VA, + VB => VB, + VC => VC, + V2 => V2, + V4 => V4, + VBL => VBL, + HBL => HBL, + BLANK => BLANK, + LDPS_N => LDPS_N, + LD194 => LD194_I); + + video_display : entity work.video_generator port map ( + CLK_14M => CLK_14M, + CLK_7M => CLK_7M, + AX => AX, + CAS_N => CAS_N, + TEXT_MODE => TEXT_MODE, + PAGE2 => PAGE2, + HIRES_MODE => HIRES_MODE, + MIXED_MODE => MIXED_MODE, + H0 => H0, + VA => VA, + VB => VB, + VC => VC, + V2 => V2, + V4 => V4, + BLANK => BLANK, + DL => DL, + LDPS_N => LDPS_N, + LD194 => LD194_I, + FLASH_CLK => FLASH_CLK, + HIRES => HIRES, + VIDEO => VIDEO, + COLOR_LINE => COLOR_LINE); + + cpu : entity work.cpu65xx + generic map ( + pipelineOpcode => false, + pipelineAluMux => false, + pipelineAluOut => false) + port map ( + clk => Q3, + enable => not PRE_PHASE_ZERO_sig, + reset => reset, + nmi_n => '1', + irq_n => '1', + di => D_IN, + do => D, + addr => A, + we => we, + debugPc => pcDebugOut, + debugOpcode => opcodeDebugOut + ); + + -- Original Apple had asynchronous ROMs. We use a synchronous ROM + -- that needs its address earlier, hence the odd clock. + roms : entity work.main_roms port map ( + addr => rom_addr, + clk => CLK_14M, + dout => rom_out); + +end rtl; diff --git a/Apple - 2_MiST/rtl/build_id.tcl b/Apple - 2_MiST/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Apple - 2_MiST/rtl/build_id.tcl @@ -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 \ No newline at end of file diff --git a/Apple - 2_MiST/rtl/build_id.v b/Apple - 2_MiST/rtl/build_id.v new file mode 100644 index 00000000..fa4fc18c --- /dev/null +++ b/Apple - 2_MiST/rtl/build_id.v @@ -0,0 +1,2 @@ +`define BUILD_DATE "180506" +`define BUILD_TIME "191822" diff --git a/Apple - 2_MiST/rtl/character_rom.vhd b/Apple - 2_MiST/rtl/character_rom.vhd new file mode 100644 index 00000000..33c50729 --- /dev/null +++ b/Apple - 2_MiST/rtl/character_rom.vhd @@ -0,0 +1,539 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity character_rom is + + port ( + addr : in unsigned(8 downto 0); + clk : in std_logic; + dout : out unsigned(4 downto 0)); +end character_rom; + +architecture rtl of character_rom is + type rom_array is array (0 to 511) of unsigned(4 downto 0); + + constant ROM : rom_array := ( + "01110", + "10001", + "10101", + "11101", + "01101", + "00001", + "11110", + "00000", + "00100", + "01010", + "10001", + "10001", + "11111", + "10001", + "10001", + "00000", + "01111", + "10001", + "10001", + "01111", + "10001", + "10001", + "01111", + "00000", + "01110", + "10001", + "00001", + "00001", + "00001", + "10001", + "01110", + "00000", + "01111", + "10001", + "10001", + "10001", + "10001", + "10001", + "01111", + "00000", + "11111", + "00001", + "00001", + "01111", + "00001", + "00001", + "11111", + "00000", + "11111", + "00001", + "00001", + "01111", + "00001", + "00001", + "00001", + "00000", + "11110", + "00001", + "00001", + "00001", + "11001", + "10001", + "11110", + "00000", + "10001", + "10001", + "10001", + "11111", + "10001", + "10001", + "10001", + "00000", + "01110", + "00100", + "00100", + "00100", + "00100", + "00100", + "01110", + "00000", + "10000", + "10000", + "10000", + "10000", + "10000", + "10001", + "01110", + "00000", + "10001", + "01001", + "00101", + "00011", + "00101", + "01001", + "10001", + "00000", + "00001", + "00001", + "00001", + "00001", + "00001", + "00001", + "11111", + "00000", + "10001", + "11011", + "10101", + "10101", + "10001", + "10001", + "10001", + "00000", + "10001", + "10001", + "10011", + "10101", + "11001", + "10001", + "10001", + "00000", + "01110", + "10001", + "10001", + "10001", + "10001", + "10001", + "01110", + "00000", + "01111", + "10001", + "10001", + "01111", + "00001", + "00001", + "00001", + "00000", + "01110", + "10001", + "10001", + "10001", + "10101", + "01001", + "10110", + "00000", + "01111", + "10001", + "10001", + "01111", + "00101", + "01001", + "10001", + "00000", + "01110", + "10001", + "00001", + "01110", + "10000", + "10001", + "01110", + "00000", + "11111", + "00100", + "00100", + "00100", + "00100", + "00100", + "00100", + "00000", + "10001", + "10001", + "10001", + "10001", + "10001", + "10001", + "01110", + "00000", + "10001", + "10001", + "10001", + "10001", + "10001", + "01010", + "00100", + "00000", + "10001", + "10001", + "10001", + "10101", + "10101", + "11011", + "10001", + "00000", + "10001", + "10001", + "01010", + "00100", + "01010", + "10001", + "10001", + "00000", + "10001", + "10001", + "01010", + "00100", + "00100", + "00100", + "00100", + "00000", + "11111", + "10000", + "01000", + "00100", + "00010", + "00001", + "11111", + "00000", + "11111", + "00011", + "00011", + "00011", + "00011", + "00011", + "11111", + "00000", + "00000", + "00001", + "00010", + "00100", + "01000", + "10000", + "00000", + "00000", + "11111", + "11000", + "11000", + "11000", + "11000", + "11000", + "11111", + "00000", + "00000", + "00000", + "00100", + "01010", + "10001", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "11111", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00100", + "00100", + "00100", + "00100", + "00100", + "00000", + "00100", + "00000", + "01010", + "01010", + "01010", + "00000", + "00000", + "00000", + "00000", + "00000", + "01010", + "01010", + "11111", + "01010", + "11111", + "01010", + "01010", + "00000", + "00100", + "11110", + "00101", + "01110", + "10100", + "01111", + "00100", + "00000", + "00011", + "10011", + "01000", + "00100", + "00010", + "11001", + "11000", + "00000", + "00010", + "00101", + "00101", + "00010", + "10101", + "01001", + "10110", + "00000", + "00100", + "00100", + "00100", + "00000", + "00000", + "00000", + "00000", + "00000", + "00100", + "00010", + "00001", + "00001", + "00001", + "00010", + "00100", + "00000", + "00100", + "01000", + "10000", + "10000", + "10000", + "01000", + "00100", + "00000", + "00100", + "10101", + "01110", + "00100", + "01110", + "10101", + "00100", + "00000", + "00000", + "00100", + "00100", + "11111", + "00100", + "00100", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00100", + "00100", + "00010", + "00000", + "00000", + "00000", + "00000", + "11111", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00000", + "00100", + "00000", + "00000", + "10000", + "01000", + "00100", + "00010", + "00001", + "00000", + "00000", + "01110", + "10001", + "11001", + "10101", + "10011", + "10001", + "01110", + "00000", + "00100", + "00110", + "00100", + "00100", + "00100", + "00100", + "01110", + "00000", + "01110", + "10001", + "10000", + "01100", + "00010", + "00001", + "11111", + "00000", + "11111", + "10000", + "01000", + "01100", + "10000", + "10001", + "01110", + "00000", + "01000", + "01100", + "01010", + "01001", + "11111", + "01000", + "01000", + "00000", + "11111", + "00001", + "01111", + "10000", + "10000", + "10001", + "01110", + "00000", + "11100", + "00010", + "00001", + "01111", + "10001", + "10001", + "01110", + "00000", + "11111", + "10000", + "01000", + "00100", + "00010", + "00010", + "00010", + "00000", + "01110", + "10001", + "10001", + "01110", + "10001", + "10001", + "01110", + "00000", + "01110", + "10001", + "10001", + "11110", + "10000", + "01000", + "00111", + "00000", + "00000", + "00000", + "00100", + "00000", + "00100", + "00000", + "00000", + "00000", + "00000", + "00000", + "00100", + "00000", + "00100", + "00100", + "00010", + "00000", + "01000", + "00100", + "00010", + "00001", + "00010", + "00100", + "01000", + "00000", + "00000", + "00000", + "11111", + "00000", + "11111", + "00000", + "00000", + "00000", + "00010", + "00100", + "01000", + "10000", + "01000", + "00100", + "00010", + "00000", + "01110", + "10001", + "01000", + "00100", + "00100", + "00000", + "00100", + "00000"); + +begin + + process (clk) + begin + if rising_edge(clk) then + dout <= ROM(TO_INTEGER(addr)); + end if; + end process; + +end rtl; diff --git a/Apple - 2_MiST/rtl/cpu6502.vhd b/Apple - 2_MiST/rtl/cpu6502.vhd new file mode 100644 index 00000000..1c521ffb --- /dev/null +++ b/Apple - 2_MiST/rtl/cpu6502.vhd @@ -0,0 +1,1598 @@ +-- ----------------------------------------------------------------------- +-- +-- FPGA 64 +-- +-- A fully functional commodore 64 implementation in a single FPGA +-- +-- ----------------------------------------------------------------------- +-- +-- Table driven, cycle exact 6502/6510 core +-- +-- ----------------------------------------------------------------------- +-- +-- cpu65xx_fast.vhdl, part of FPGA-64, is made available strictly for personal +-- educational purposes. Distributed with apple2fgpa with permission. +-- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com). +-- All rights reserved. +-- http://www.syntiac.com/fpga64.html +-- +-- ----------------------------------------------------------------------- + +library IEEE; +use ieee.std_logic_1164.ALL; +use ieee.numeric_std.ALL; + +entity cpu65xx is + generic ( + pipelineOpcode : boolean; + pipelineAluMux : boolean; + pipelineAluOut : boolean + ); + port ( + clk : in std_logic; + enable : in std_logic; + reset : in std_logic; + nmi_n : in std_logic; + irq_n : in std_logic; + so_n : in std_logic := '1'; + + di : in unsigned(7 downto 0); + do : out unsigned(7 downto 0); + addr : out unsigned(15 downto 0); + we : out std_logic; + + debugOpcode : out unsigned(7 downto 0); + debugPc : out unsigned(15 downto 0); + debugA : out unsigned(7 downto 0); + debugX : out unsigned(7 downto 0); + debugY : out unsigned(7 downto 0); + debugS : out unsigned(7 downto 0) + ); +end cpu65xx; + +-- ----------------------------------------------------------------------- + +-- Store Zp (3) => fetch, cycle2, cycleEnd +-- Store Zp,x (4) => fetch, cycle2, preWrite, cycleEnd +-- Read Zp,x (4) => fetch, cycle2, cycleRead, cycleRead2 +-- Rmw Zp,x (6) => fetch, cycle2, cycleRead, cycleRead2, cycleRmw, cycleEnd +-- Store Abs (4) => fetch, cycle2, cycle3, cycleEnd +-- Store Abs,x (5) => fetch, cycle2, cycle3, preWrite, cycleEnd +-- Rts (6) => fetch, cycle2, cycle3, cycleRead, cycleJump, cycleIncrEnd +-- Rti (6) => fetch, cycle2, stack1, stack2, stack3, cycleJump +-- Jsr (6) => fetch, cycle2, .. cycle5, cycle6, cycleJump +-- Jmp abs (-) => fetch, cycle2, .., cycleJump +-- Jmp (ind) (-) => fetch, cycle2, .., cycleJump +-- Brk / irq (6) => fetch, cycle2, stack2, stack3, stack4 +-- ----------------------------------------------------------------------- + +architecture fast of cpu65xx is +-- Statemachine + type cpuCycles is ( + opcodeFetch, -- New opcode is read and registers updated + cycle2, + cycle3, + cyclePreIndirect, + cycleIndirect, + cycleBranchTaken, + cycleBranchPage, + cyclePreRead, -- Cycle before read while doing zeropage indexed addressing. + cycleRead, -- Read cycle + cycleRead2, -- Second read cycle after page-boundary crossing. + cycleRmw, -- Calculate ALU output for read-modify-write instr. + cyclePreWrite, -- Cycle before write when doing indexed addressing. + cycleWrite, -- Write cycle for zeropage or absolute addressing. + cycleStack1, + cycleStack2, + cycleStack3, + cycleStack4, + cycleJump, -- Last cycle of Jsr, Jmp. Next fetch address is target addr. + cycleEnd + ); + signal theCpuCycle : cpuCycles; + signal nextCpuCycle : cpuCycles; + signal updateRegisters : boolean; + signal processIrq : std_logic; + signal nmiReg: std_logic; + signal nmiEdge: std_logic; + signal irqReg : std_logic; -- Delay IRQ input with one clock cycle. + signal soReg : std_logic; -- SO pin edge detection + +-- Opcode decoding + constant opcUpdateA : integer := 0; + constant opcUpdateX : integer := 1; + constant opcUpdateY : integer := 2; + constant opcUpdateS : integer := 3; + constant opcUpdateN : integer := 4; + constant opcUpdateV : integer := 5; + constant opcUpdateD : integer := 6; + constant opcUpdateI : integer := 7; + constant opcUpdateZ : integer := 8; + constant opcUpdateC : integer := 9; + + constant opcSecondByte : integer := 10; + constant opcAbsolute : integer := 11; + constant opcZeroPage : integer := 12; + constant opcIndirect : integer := 13; + constant opcStackAddr : integer := 14; -- Push/Pop address + constant opcStackData : integer := 15; -- Push/Pop status/data + constant opcJump : integer := 16; + constant opcBranch : integer := 17; + constant indexX : integer := 18; + constant indexY : integer := 19; + constant opcStackUp : integer := 20; + constant opcWrite : integer := 21; + constant opcRmw : integer := 22; + constant opcIncrAfter : integer := 23; -- Insert extra cycle to increment PC (RTS) + constant opcRti : integer := 24; + constant opcIRQ : integer := 25; + + constant opcInA : integer := 26; + constant opcInE : integer := 27; + constant opcInX : integer := 28; + constant opcInY : integer := 29; + constant opcInS : integer := 30; + constant opcInT : integer := 31; + constant opcInH : integer := 32; + constant opcInClear : integer := 33; + constant aluMode1From : integer := 34; + -- + constant aluMode1To : integer := 37; + constant aluMode2From : integer := 38; + -- + constant aluMode2To : integer := 40; + -- + constant opcInCmp : integer := 41; + constant opcInCpx : integer := 42; + constant opcInCpy : integer := 43; + + + subtype addrDef is unsigned(0 to 15); + -- + -- is Interrupt -----------------+ + -- instruction is RTI ----------------+| + -- PC++ on last cycle (RTS) ---------------+|| + -- RMW --------------+||| + -- Write -------------+|||| + -- Pop/Stack up -------------+||||| + -- Branch ---------+ |||||| + -- Jump ----------+| |||||| + -- Push or Pop data -------+|| |||||| + -- Push or Pop addr ------+||| |||||| + -- Indirect -----+|||| |||||| + -- ZeroPage ----+||||| |||||| + -- Absolute ---+|||||| |||||| + -- PC++ on cycle2 --+||||||| |||||| + -- |AZI||JBXY|WM||| + constant immediate : addrDef := "1000000000000000"; + constant implied : addrDef := "0000000000000000"; + -- Zero page + constant readZp : addrDef := "1010000000000000"; + constant writeZp : addrDef := "1010000000010000"; + constant rmwZp : addrDef := "1010000000001000"; + -- Zero page indexed + constant readZpX : addrDef := "1010000010000000"; + constant writeZpX : addrDef := "1010000010010000"; + constant rmwZpX : addrDef := "1010000010001000"; + constant readZpY : addrDef := "1010000001000000"; + constant writeZpY : addrDef := "1010000001010000"; + constant rmwZpY : addrDef := "1010000001001000"; + -- Zero page indirect + constant readIndX : addrDef := "1001000010000000"; + constant writeIndX : addrDef := "1001000010010000"; + constant rmwIndX : addrDef := "1001000010001000"; + constant readIndY : addrDef := "1001000001000000"; + constant writeIndY : addrDef := "1001000001010000"; + constant rmwIndY : addrDef := "1001000001001000"; + -- |AZI||JBXY|WM|| + -- Absolute + constant readAbs : addrDef := "1100000000000000"; + constant writeAbs : addrDef := "1100000000010000"; + constant rmwAbs : addrDef := "1100000000001000"; + constant readAbsX : addrDef := "1100000010000000"; + constant writeAbsX : addrDef := "1100000010010000"; + constant rmwAbsX : addrDef := "1100000010001000"; + constant readAbsY : addrDef := "1100000001000000"; + constant writeAbsY : addrDef := "1100000001010000"; + constant rmwAbsY : addrDef := "1100000001001000"; + -- PHA PHP + constant push : addrDef := "0000010000000000"; + -- PLA PLP + constant pop : addrDef := "0000010000100000"; + -- Jumps + constant jsr : addrDef := "1000101000000000"; + constant jumpAbs : addrDef := "1000001000000000"; + constant jumpInd : addrDef := "1100001000000000"; + constant relative : addrDef := "1000000100000000"; + -- Specials + constant rts : addrDef := "0000101000100100"; + constant rti : addrDef := "0000111000100010"; + constant brk : addrDef := "1000111000000001"; +-- constant : unsigned(0 to 0) := "0"; + constant xxxxxxxx : addrDef := "----------0---00"; + + -- A = accu + -- E = Accu | 0xEE (for ANE, LXA) + -- X = index X + -- Y = index Y + -- S = Stack pointer + -- H = indexH + -- + -- AEXYSTHc + constant aluInA : unsigned(0 to 7) := "10000000"; + constant aluInE : unsigned(0 to 7) := "01000000"; + constant aluInEXT : unsigned(0 to 7) := "01100100"; + constant aluInET : unsigned(0 to 7) := "01000100"; + constant aluInX : unsigned(0 to 7) := "00100000"; + constant aluInXH : unsigned(0 to 7) := "00100010"; + constant aluInY : unsigned(0 to 7) := "00010000"; + constant aluInYH : unsigned(0 to 7) := "00010010"; + constant aluInS : unsigned(0 to 7) := "00001000"; + constant aluInT : unsigned(0 to 7) := "00000100"; + constant aluInAX : unsigned(0 to 7) := "10100000"; + constant aluInAXH : unsigned(0 to 7) := "10100010"; + constant aluInAT : unsigned(0 to 7) := "10000100"; + constant aluInXT : unsigned(0 to 7) := "00100100"; + constant aluInST : unsigned(0 to 7) := "00001100"; + constant aluInSet : unsigned(0 to 7) := "00000000"; + constant aluInClr : unsigned(0 to 7) := "00000001"; + constant aluInXXX : unsigned(0 to 7) := "--------"; + + -- Most of the aluModes are just like the opcodes. + -- aluModeInp -> input is output. calculate N and Z + -- aluModeCmp -> Compare for CMP, CPX, CPY + -- aluModeFlg -> input to flags needed for PLP, RTI and CLC, SEC, CLV + -- aluModeInc -> for INC but also INX, INY + -- aluModeDec -> for DEC but also DEX, DEY + + subtype aluMode1 is unsigned(0 to 3); + subtype aluMode2 is unsigned(0 to 2); + subtype aluMode is unsigned(0 to 9); + + -- Logic/Shift ALU + constant aluModeInp : aluMode1 := "0000"; + constant aluModeP : aluMode1 := "0001"; + constant aluModeInc : aluMode1 := "0010"; + constant aluModeDec : aluMode1 := "0011"; + constant aluModeFlg : aluMode1 := "0100"; + constant aluModeBit : aluMode1 := "0101"; + -- 0110 + -- 0111 + constant aluModeLsr : aluMode1 := "1000"; + constant aluModeRor : aluMode1 := "1001"; + constant aluModeAsl : aluMode1 := "1010"; + constant aluModeRol : aluMode1 := "1011"; + -- 1100 + -- 1101 + -- 1110 + constant aluModeAnc : aluMode1 := "1111"; + + -- Arithmetic ALU + constant aluModePss : aluMode2 := "000"; + constant aluModeCmp : aluMode2 := "001"; + constant aluModeAdc : aluMode2 := "010"; + constant aluModeSbc : aluMode2 := "011"; + constant aluModeAnd : aluMode2 := "100"; + constant aluModeOra : aluMode2 := "101"; + constant aluModeEor : aluMode2 := "110"; + constant aluModeArr : aluMode2 := "111"; + + + constant aluInp : aluMode := aluModeInp & aluModePss & "---"; + constant aluP : aluMode := aluModeP & aluModePss & "---"; + constant aluInc : aluMode := aluModeInc & aluModePss & "---"; + constant aluDec : aluMode := aluModeDec & aluModePss & "---"; + constant aluFlg : aluMode := aluModeFlg & aluModePss & "---"; + constant aluBit : aluMode := aluModeBit & aluModeAnd & "---"; + constant aluRor : aluMode := aluModeRor & aluModePss & "---"; + constant aluLsr : aluMode := aluModeLsr & aluModePss & "---"; + constant aluRol : aluMode := aluModeRol & aluModePss & "---"; + constant aluAsl : aluMode := aluModeAsl & aluModePss & "---"; + + constant aluCmp : aluMode := aluModeInp & aluModeCmp & "100"; + constant aluCpx : aluMode := aluModeInp & aluModeCmp & "010"; + constant aluCpy : aluMode := aluModeInp & aluModeCmp & "001"; + constant aluAdc : aluMode := aluModeInp & aluModeAdc & "---"; + constant aluSbc : aluMode := aluModeInp & aluModeSbc & "---"; + constant aluAnd : aluMode := aluModeInp & aluModeAnd & "---"; + constant aluOra : aluMode := aluModeInp & aluModeOra & "---"; + constant aluEor : aluMode := aluModeInp & aluModeEor & "---"; + + constant aluSlo : aluMode := aluModeAsl & aluModeOra & "---"; + constant aluSre : aluMode := aluModeLsr & aluModeEor & "---"; + constant aluRra : aluMode := aluModeRor & aluModeAdc & "---"; + constant aluRla : aluMode := aluModeRol & aluModeAnd & "---"; + constant aluDcp : aluMode := aluModeDec & aluModeCmp & "100"; + constant aluIsc : aluMode := aluModeInc & aluModeSbc & "---"; + constant aluAnc : aluMode := aluModeAnc & aluModeAnd & "---"; + constant aluArr : aluMode := aluModeRor & aluModeArr & "---"; + constant aluSbx : aluMode := aluModeInp & aluModeCmp & "110"; + + constant aluXXX : aluMode := (others => '-'); + + + -- Stack operations. Push/Pop/None + constant stackInc : unsigned(0 to 0) := "0"; + constant stackDec : unsigned(0 to 0) := "1"; + constant stackXXX : unsigned(0 to 0) := "-"; + + subtype decodedBitsDef is unsigned(0 to 43); + type opcodeInfoTableDef is array(0 to 255) of decodedBitsDef; + constant opcodeInfoTable : opcodeInfoTableDef := ( + -- +------- Update register A + -- |+------ Update register X + -- ||+----- Update register Y + -- |||+---- Update register S + -- |||| +-- Update Flags + -- |||| | + -- |||| _|__ + -- |||| / \ + -- AXYS NVDIZC addressing aluInput aluMode + "0000" & "000100" & brk & aluInXXX & aluP, -- 00 BRK + "1000" & "100010" & readIndX & aluInT & aluOra, -- 01 ORA (zp,x) + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 02 *** JAM *** + "1000" & "100011" & rmwIndX & aluInT & aluSlo, -- 03 iSLO (zp,x) + "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 04 iNOP zp + "1000" & "100010" & readZp & aluInT & aluOra, -- 05 ORA zp + "0000" & "100011" & rmwZp & aluInT & aluAsl, -- 06 ASL zp + "1000" & "100011" & rmwZp & aluInT & aluSlo, -- 07 iSLO zp + "0000" & "000000" & push & aluInXXX & aluP, -- 08 PHP + "1000" & "100010" & immediate & aluInT & aluOra, -- 09 ORA imm + "1000" & "100011" & implied & aluInA & aluAsl, -- 0A ASL accu + "1000" & "100011" & immediate & aluInT & aluAnc, -- 0B iANC imm + "0000" & "000000" & readAbs & aluInXXX & aluXXX, -- 0C iNOP abs + "1000" & "100010" & readAbs & aluInT & aluOra, -- 0D ORA abs + "0000" & "100011" & rmwAbs & aluInT & aluAsl, -- 0E ASL abs + "1000" & "100011" & rmwAbs & aluInT & aluSlo, -- 0F iSLO abs + "0000" & "000000" & relative & aluInXXX & aluXXX, -- 10 BPL + "1000" & "100010" & readIndY & aluInT & aluOra, -- 11 ORA (zp),y + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 12 *** JAM *** + "1000" & "100011" & rmwIndY & aluInT & aluSlo, -- 13 iSLO (zp),y + "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 14 iNOP zp,x + "1000" & "100010" & readZpX & aluInT & aluOra, -- 15 ORA zp,x + "0000" & "100011" & rmwZpX & aluInT & aluAsl, -- 16 ASL zp,x + "1000" & "100011" & rmwZpX & aluInT & aluSlo, -- 17 iSLO zp,x + "0000" & "000001" & implied & aluInClr & aluFlg, -- 18 CLC + "1000" & "100010" & readAbsY & aluInT & aluOra, -- 19 ORA abs,y + "0000" & "000000" & implied & aluInXXX & aluXXX, -- 1A iNOP implied + "1000" & "100011" & rmwAbsY & aluInT & aluSlo, -- 1B iSLO abs,y + "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 1C iNOP abs,x + "1000" & "100010" & readAbsX & aluInT & aluOra, -- 1D ORA abs,x + "0000" & "100011" & rmwAbsX & aluInT & aluAsl, -- 1E ASL abs,x + "1000" & "100011" & rmwAbsX & aluInT & aluSlo, -- 1F iSLO abs,x + -- AXYS NVDIZC addressing aluInput aluMode + "0000" & "000000" & jsr & aluInXXX & aluXXX, -- 20 JSR + "1000" & "100010" & readIndX & aluInT & aluAnd, -- 21 AND (zp,x) + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 22 *** JAM *** + "1000" & "100011" & rmwIndX & aluInT & aluRla, -- 23 iRLA (zp,x) + "0000" & "110010" & readZp & aluInT & aluBit, -- 24 BIT zp + "1000" & "100010" & readZp & aluInT & aluAnd, -- 25 AND zp + "0000" & "100011" & rmwZp & aluInT & aluRol, -- 26 ROL zp + "1000" & "100011" & rmwZp & aluInT & aluRla, -- 27 iRLA zp + "0000" & "111111" & pop & aluInT & aluFlg, -- 28 PLP + "1000" & "100010" & immediate & aluInT & aluAnd, -- 29 AND imm + "1000" & "100011" & implied & aluInA & aluRol, -- 2A ROL accu + "1000" & "100011" & immediate & aluInT & aluAnc, -- 2B iANC imm + "0000" & "110010" & readAbs & aluInT & aluBit, -- 2C BIT abs + "1000" & "100010" & readAbs & aluInT & aluAnd, -- 2D AND abs + "0000" & "100011" & rmwAbs & aluInT & aluRol, -- 2E ROL abs + "1000" & "100011" & rmwAbs & aluInT & aluRla, -- 2F iRLA abs + "0000" & "000000" & relative & aluInXXX & aluXXX, -- 30 BMI + "1000" & "100010" & readIndY & aluInT & aluAnd, -- 31 AND (zp),y + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 32 *** JAM *** + "1000" & "100011" & rmwIndY & aluInT & aluRla, -- 33 iRLA (zp),y + "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 34 iNOP zp,x + "1000" & "100010" & readZpX & aluInT & aluAnd, -- 35 AND zp,x + "0000" & "100011" & rmwZpX & aluInT & aluRol, -- 36 ROL zp,x + "1000" & "100011" & rmwZpX & aluInT & aluRla, -- 37 iRLA zp,x + "0000" & "000001" & implied & aluInSet & aluFlg, -- 38 SEC + "1000" & "100010" & readAbsY & aluInT & aluAnd, -- 39 AND abs,y + "0000" & "000000" & implied & aluInXXX & aluXXX, -- 3A iNOP implied + "1000" & "100011" & rmwAbsY & aluInT & aluRla, -- 3B iRLA abs,y + "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 3C iNOP abs,x + "1000" & "100010" & readAbsX & aluInT & aluAnd, -- 3D AND abs,x + "0000" & "100011" & rmwAbsX & aluInT & aluRol, -- 3E ROL abs,x + "1000" & "100011" & rmwAbsX & aluInT & aluRla, -- 3F iRLA abs,x + -- AXYS NVDIZC addressing aluInput aluMode + "0000" & "111111" & rti & aluInT & aluFlg, -- 40 RTI + "1000" & "100010" & readIndX & aluInT & aluEor, -- 41 EOR (zp,x) + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 42 *** JAM *** + "1000" & "100011" & rmwIndX & aluInT & aluSre, -- 43 iSRE (zp,x) + "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 44 iNOP zp + "1000" & "100010" & readZp & aluInT & aluEor, -- 45 EOR zp + "0000" & "100011" & rmwZp & aluInT & aluLsr, -- 46 LSR zp + "1000" & "100011" & rmwZp & aluInT & aluSre, -- 47 iSRE zp + "0000" & "000000" & push & aluInA & aluInp, -- 48 PHA + "1000" & "100010" & immediate & aluInT & aluEor, -- 49 EOR imm + "1000" & "100011" & implied & aluInA & aluLsr, -- 4A LSR accu + "1000" & "100011" & immediate & aluInAT & aluLsr, -- 4B iALR imm + "0000" & "000000" & jumpAbs & aluInXXX & aluXXX, -- 4C JMP abs + "1000" & "100010" & readAbs & aluInT & aluEor, -- 4D EOR abs + "0000" & "100011" & rmwAbs & aluInT & aluLsr, -- 4E LSR abs + "1000" & "100011" & rmwAbs & aluInT & aluSre, -- 4F iSRE abs + "0000" & "000000" & relative & aluInXXX & aluXXX, -- 50 BVC + "1000" & "100010" & readIndY & aluInT & aluEor, -- 51 EOR (zp),y + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 52 *** JAM *** + "1000" & "100011" & rmwIndY & aluInT & aluSre, -- 53 iSRE (zp),y + "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 54 iNOP zp,x + "1000" & "100010" & readZpX & aluInT & aluEor, -- 55 EOR zp,x + "0000" & "100011" & rmwZpX & aluInT & aluLsr, -- 56 LSR zp,x + "1000" & "100011" & rmwZpX & aluInT & aluSre, -- 57 SRE zp,x + "0000" & "000100" & implied & aluInClr & aluXXX, -- 58 CLI + "1000" & "100010" & readAbsY & aluInT & aluEor, -- 59 EOR abs,y + "0000" & "000000" & implied & aluInXXX & aluXXX, -- 5A iNOP implied + "1000" & "100011" & rmwAbsY & aluInT & aluSre, -- 5B iSRE abs,y + "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 5C iNOP abs,x + "1000" & "100010" & readAbsX & aluInT & aluEor, -- 5D EOR abs,x + "0000" & "100011" & rmwAbsX & aluInT & aluLsr, -- 5E LSR abs,x + "1000" & "100011" & rmwAbsX & aluInT & aluSre, -- 5F SRE abs,x + -- AXYS NVDIZC addressing aluInput aluMode + "0000" & "000000" & rts & aluInXXX & aluXXX, -- 60 RTS + "1000" & "110011" & readIndX & aluInT & aluAdc, -- 61 ADC (zp,x) + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 62 *** JAM *** + "1000" & "110011" & rmwIndX & aluInT & aluRra, -- 63 iRRA (zp,x) + "0000" & "000000" & readZp & aluInXXX & aluXXX, -- 64 iNOP zp + "1000" & "110011" & readZp & aluInT & aluAdc, -- 65 ADC zp + "0000" & "100011" & rmwZp & aluInT & aluRor, -- 66 ROR zp + "1000" & "110011" & rmwZp & aluInT & aluRra, -- 67 iRRA zp + "1000" & "100010" & pop & aluInT & aluInp, -- 68 PLA + "1000" & "110011" & immediate & aluInT & aluAdc, -- 69 ADC imm + "1000" & "100011" & implied & aluInA & aluRor, -- 6A ROR accu + "1000" & "110011" & immediate & aluInAT & aluArr, -- 6B iARR imm + "0000" & "000000" & jumpInd & aluInXXX & aluXXX, -- 6C JMP indirect + "1000" & "110011" & readAbs & aluInT & aluAdc, -- 6D ADC abs + "0000" & "100011" & rmwAbs & aluInT & aluRor, -- 6E ROR abs + "1000" & "110011" & rmwAbs & aluInT & aluRra, -- 6F iRRA abs + "0000" & "000000" & relative & aluInXXX & aluXXX, -- 70 BVS + "1000" & "110011" & readIndY & aluInT & aluAdc, -- 71 ADC (zp),y + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 72 *** JAM *** + "1000" & "110011" & rmwIndY & aluInT & aluRra, -- 73 iRRA (zp),y + "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- 74 iNOP zp,x + "1000" & "110011" & readZpX & aluInT & aluAdc, -- 75 ADC zp,x + "0000" & "100011" & rmwZpX & aluInT & aluRor, -- 76 ROR zp,x + "1000" & "110011" & rmwZpX & aluInT & aluRra, -- 77 iRRA zp,x + "0000" & "000100" & implied & aluInSet & aluXXX, -- 78 SEI + "1000" & "110011" & readAbsY & aluInT & aluAdc, -- 79 ADC abs,y + "0000" & "000000" & implied & aluInXXX & aluXXX, -- 7A iNOP implied + "1000" & "110011" & rmwAbsY & aluInT & aluRra, -- 7B iRRA abs,y + "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- 7C iNOP abs,x + "1000" & "110011" & readAbsX & aluInT & aluAdc, -- 7D ADC abs,x + "0000" & "100011" & rmwAbsX & aluInT & aluRor, -- 7E ROR abs,x + "1000" & "110011" & rmwAbsX & aluInT & aluRra, -- 7F iRRA abs,x + -- AXYS NVDIZC addressing aluInput aluMode + "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 80 iNOP imm + "0000" & "000000" & writeIndX & aluInA & aluInp, -- 81 STA (zp,x) + "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 82 iNOP imm + "0000" & "000000" & writeIndX & aluInAX & aluInp, -- 83 iSAX (zp,x) + "0000" & "000000" & writeZp & aluInY & aluInp, -- 84 STY zp + "0000" & "000000" & writeZp & aluInA & aluInp, -- 85 STA zp + "0000" & "000000" & writeZp & aluInX & aluInp, -- 86 STX zp + "0000" & "000000" & writeZp & aluInAX & aluInp, -- 87 iSAX zp + "0010" & "100010" & implied & aluInY & aluDec, -- 88 DEY + "0000" & "000000" & immediate & aluInXXX & aluXXX, -- 84 iNOP imm + "1000" & "100010" & implied & aluInX & aluInp, -- 8A TXA + "1000" & "100010" & immediate & aluInEXT & aluInp, -- 8B iANE imm + "0000" & "000000" & writeAbs & aluInY & aluInp, -- 8C STY abs + "0000" & "000000" & writeAbs & aluInA & aluInp, -- 8D STA abs + "0000" & "000000" & writeAbs & aluInX & aluInp, -- 8E STX abs + "0000" & "000000" & writeAbs & aluInAX & aluInp, -- 8F iSAX abs + "0000" & "000000" & relative & aluInXXX & aluXXX, -- 90 BCC + "0000" & "000000" & writeIndY & aluInA & aluInp, -- 91 STA (zp),y + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- 92 *** JAM *** + "0000" & "000000" & writeIndY & aluInAXH & aluInp, -- 93 iAHX (zp),y + "0000" & "000000" & writeZpX & aluInY & aluInp, -- 94 STY zp,x + "0000" & "000000" & writeZpX & aluInA & aluInp, -- 95 STA zp,x + "0000" & "000000" & writeZpY & aluInX & aluInp, -- 96 STX zp,y + "0000" & "000000" & writeZpY & aluInAX & aluInp, -- 97 iSAX zp,y + "1000" & "100010" & implied & aluInY & aluInp, -- 98 TYA + "0000" & "000000" & writeAbsY & aluInA & aluInp, -- 99 STA abs,y + "0001" & "000000" & implied & aluInX & aluInp, -- 9A TXS + "0001" & "000000" & writeAbsY & aluInAXH & aluInp, -- 9B iSHS abs,y + "0000" & "000000" & writeAbsX & aluInYH & aluInp, -- 9C iSHY abs,x + "0000" & "000000" & writeAbsX & aluInA & aluInp, -- 9D STA abs,x + "0000" & "000000" & writeAbsY & aluInXH & aluInp, -- 9E iSHX abs,y + "0000" & "000000" & writeAbsY & aluInAXH & aluInp, -- 9F iAHX abs,y + -- AXYS NVDIZC addressing aluInput aluMode + "0010" & "100010" & immediate & aluInT & aluInp, -- A0 LDY imm + "1000" & "100010" & readIndX & aluInT & aluInp, -- A1 LDA (zp,x) + "0100" & "100010" & immediate & aluInT & aluInp, -- A2 LDX imm + "1100" & "100010" & readIndX & aluInT & aluInp, -- A3 LAX (zp,x) + "0010" & "100010" & readZp & aluInT & aluInp, -- A4 LDY zp + "1000" & "100010" & readZp & aluInT & aluInp, -- A5 LDA zp + "0100" & "100010" & readZp & aluInT & aluInp, -- A6 LDX zp + "1100" & "100010" & readZp & aluInT & aluInp, -- A7 iLAX zp + "0010" & "100010" & implied & aluInA & aluInp, -- A8 TAY + "1000" & "100010" & immediate & aluInT & aluInp, -- A9 LDA imm + "0100" & "100010" & implied & aluInA & aluInp, -- AA TAX + "1100" & "100010" & immediate & aluInET & aluInp, -- AB iLXA imm + "0010" & "100010" & readAbs & aluInT & aluInp, -- AC LDY abs + "1000" & "100010" & readAbs & aluInT & aluInp, -- AD LDA abs + "0100" & "100010" & readAbs & aluInT & aluInp, -- AE LDX abs + "1100" & "100010" & readAbs & aluInT & aluInp, -- AF iLAX abs + "0000" & "000000" & relative & aluInXXX & aluXXX, -- B0 BCS + "1000" & "100010" & readIndY & aluInT & aluInp, -- B1 LDA (zp),y + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- B2 *** JAM *** + "1100" & "100010" & readIndY & aluInT & aluInp, -- B3 iLAX (zp),y + "0010" & "100010" & readZpX & aluInT & aluInp, -- B4 LDY zp,x + "1000" & "100010" & readZpX & aluInT & aluInp, -- B5 LDA zp,x + "0100" & "100010" & readZpY & aluInT & aluInp, -- B6 LDX zp,y + "1100" & "100010" & readZpY & aluInT & aluInp, -- B7 iLAX zp,y + "0000" & "010000" & implied & aluInClr & aluFlg, -- B8 CLV + "1000" & "100010" & readAbsY & aluInT & aluInp, -- B9 LDA abs,y + "0100" & "100010" & implied & aluInS & aluInp, -- BA TSX + "1101" & "100010" & readAbsY & aluInST & aluInp, -- BB iLAS abs,y + "0010" & "100010" & readAbsX & aluInT & aluInp, -- BC LDY abs,x + "1000" & "100010" & readAbsX & aluInT & aluInp, -- BD LDA abs,x + "0100" & "100010" & readAbsY & aluInT & aluInp, -- BE LDX abs,y + "1100" & "100010" & readAbsY & aluInT & aluInp, -- BF iLAX abs,y + -- AXYS NVDIZC addressing aluInput aluMode + "0000" & "100011" & immediate & aluInT & aluCpy, -- C0 CPY imm + "0000" & "100011" & readIndX & aluInT & aluCmp, -- C1 CMP (zp,x) + "0000" & "000000" & immediate & aluInXXX & aluXXX, -- C2 iNOP imm + "0000" & "100011" & rmwIndX & aluInT & aluDcp, -- C3 iDCP (zp,x) + "0000" & "100011" & readZp & aluInT & aluCpy, -- C4 CPY zp + "0000" & "100011" & readZp & aluInT & aluCmp, -- C5 CMP zp + "0000" & "100010" & rmwZp & aluInT & aluDec, -- C6 DEC zp + "0000" & "100011" & rmwZp & aluInT & aluDcp, -- C7 iDCP zp + "0010" & "100010" & implied & aluInY & aluInc, -- C8 INY + "0000" & "100011" & immediate & aluInT & aluCmp, -- C9 CMP imm + "0100" & "100010" & implied & aluInX & aluDec, -- CA DEX + "0100" & "100011" & immediate & aluInT & aluSbx, -- CB SBX imm + "0000" & "100011" & readAbs & aluInT & aluCpy, -- CC CPY abs + "0000" & "100011" & readAbs & aluInT & aluCmp, -- CD CMP abs + "0000" & "100010" & rmwAbs & aluInT & aluDec, -- CE DEC abs + "0000" & "100011" & rmwAbs & aluInT & aluDcp, -- CF iDCP abs + "0000" & "000000" & relative & aluInXXX & aluXXX, -- D0 BNE + "0000" & "100011" & readIndY & aluInT & aluCmp, -- D1 CMP (zp),y + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- D2 *** JAM *** + "0000" & "100011" & rmwIndY & aluInT & aluDcp, -- D3 iDCP (zp),y + "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- D4 iNOP zp,x + "0000" & "100011" & readZpX & aluInT & aluCmp, -- D5 CMP zp,x + "0000" & "100010" & rmwZpX & aluInT & aluDec, -- D6 DEC zp,x + "0000" & "100011" & rmwZpX & aluInT & aluDcp, -- D7 iDCP zp,x + "0000" & "001000" & implied & aluInClr & aluXXX, -- D8 CLD + "0000" & "100011" & readAbsY & aluInT & aluCmp, -- D9 CMP abs,y + "0000" & "000000" & implied & aluInXXX & aluXXX, -- DA iNOP implied + "0000" & "100011" & rmwAbsY & aluInT & aluDcp, -- DB iDCP abs,y + "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- DC iNOP abs,x + "0000" & "100011" & readAbsX & aluInT & aluCmp, -- DD CMP abs,x + "0000" & "100010" & rmwAbsX & aluInT & aluDec, -- DE DEC abs,x + "0000" & "100011" & rmwAbsX & aluInT & aluDcp, -- DF iDCP abs,x + -- AXYS NVDIZC addressing aluInput aluMode + "0000" & "100011" & immediate & aluInT & aluCpx, -- E0 CPX imm + "1000" & "110011" & readIndX & aluInT & aluSbc, -- E1 SBC (zp,x) + "0000" & "000000" & immediate & aluInXXX & aluXXX, -- E2 iNOP imm + "1000" & "110011" & rmwIndX & aluInT & aluIsc, -- E3 iISC (zp,x) + "0000" & "100011" & readZp & aluInT & aluCpx, -- E4 CPX zp + "1000" & "110011" & readZp & aluInT & aluSbc, -- E5 SBC zp + "0000" & "100010" & rmwZp & aluInT & aluInc, -- E6 INC zp + "1000" & "110011" & rmwZp & aluInT & aluIsc, -- E7 iISC zp + "0100" & "100010" & implied & aluInX & aluInc, -- E8 INX + "1000" & "110011" & immediate & aluInT & aluSbc, -- E9 SBC imm + "0000" & "000000" & implied & aluInXXX & aluXXX, -- EA NOP + "1000" & "110011" & immediate & aluInT & aluSbc, -- EB SBC imm (illegal opc) + "0000" & "100011" & readAbs & aluInT & aluCpx, -- EC CPX abs + "1000" & "110011" & readAbs & aluInT & aluSbc, -- ED SBC abs + "0000" & "100010" & rmwAbs & aluInT & aluInc, -- EE INC abs + "1000" & "110011" & rmwAbs & aluInT & aluIsc, -- EF iISC abs + "0000" & "000000" & relative & aluInXXX & aluXXX, -- F0 BEQ + "1000" & "110011" & readIndY & aluInT & aluSbc, -- F1 SBC (zp),y + "----" & "------" & xxxxxxxx & aluInXXX & aluXXX, -- F2 *** JAM *** + "1000" & "110011" & rmwIndY & aluInT & aluIsc, -- F3 iISC (zp),y + "0000" & "000000" & readZpX & aluInXXX & aluXXX, -- F4 iNOP zp,x + "1000" & "110011" & readZpX & aluInT & aluSbc, -- F5 SBC zp,x + "0000" & "100010" & rmwZpX & aluInT & aluInc, -- F6 INC zp,x + "1000" & "110011" & rmwZpX & aluInT & aluIsc, -- F7 iISC zp,x + "0000" & "001000" & implied & aluInSet & aluXXX, -- F8 SED + "1000" & "110011" & readAbsY & aluInT & aluSbc, -- F9 SBC abs,y + "0000" & "000000" & implied & aluInXXX & aluXXX, -- FA iNOP implied + "1000" & "110011" & rmwAbsY & aluInT & aluIsc, -- FB iISC abs,y + "0000" & "000000" & readAbsX & aluInXXX & aluXXX, -- FC iNOP abs,x + "1000" & "110011" & readAbsX & aluInT & aluSbc, -- FD SBC abs,x + "0000" & "100010" & rmwAbsX & aluInT & aluInc, -- FE INC abs,x + "1000" & "110011" & rmwAbsX & aluInT & aluIsc -- FF iISC abs,x + ); + signal opcInfo : decodedBitsDef; + signal nextOpcInfo : decodedBitsDef; -- Next opcode (decoded) + signal nextOpcInfoReg : decodedBitsDef; -- Next opcode (decoded) pipelined + signal theOpcode : unsigned(7 downto 0); + signal nextOpcode : unsigned(7 downto 0); + +-- Program counter + signal PC : unsigned(15 downto 0); -- Program counter + +-- Address generation + type nextAddrDef is ( + nextAddrHold, + nextAddrIncr, + nextAddrIncrL, -- Increment low bits only (zeropage accesses) + nextAddrIncrH, -- Increment high bits only (page-boundary) + nextAddrDecrH, -- Decrement high bits (branch backwards) + nextAddrPc, + nextAddrIrq, + nextAddrReset, + nextAddrAbs, + nextAddrAbsIndexed, + nextAddrZeroPage, + nextAddrZPIndexed, + nextAddrStack, + nextAddrRelative + ); + signal nextAddr : nextAddrDef; + signal myAddr : unsigned(15 downto 0); + signal myAddrIncr : unsigned(15 downto 0); + signal myAddrIncrH : unsigned(7 downto 0); + signal myAddrDecrH : unsigned(7 downto 0); + signal theWe : std_logic; + + signal irqActive : std_logic; + +-- Output register + signal doReg : unsigned(7 downto 0); + +-- Buffer register + signal T : unsigned(7 downto 0); + +-- General registers + signal A: unsigned(7 downto 0); -- Accumulator + signal X: unsigned(7 downto 0); -- Index X + signal Y: unsigned(7 downto 0); -- Index Y + signal S: unsigned(7 downto 0); -- stack pointer + +-- Status register + signal C: std_logic; -- Carry + signal Z: std_logic; -- Zero flag + signal I: std_logic; -- Interrupt flag + signal D: std_logic; -- Decimal mode + signal V: std_logic; -- Overflow + signal N: std_logic; -- Negative + +-- ALU + -- ALU input + signal aluInput : unsigned(7 downto 0); + signal aluCmpInput : unsigned(7 downto 0); + -- ALU output + signal aluRegisterOut : unsigned(7 downto 0); + signal aluRmwOut : unsigned(7 downto 0); + signal aluC : std_logic; + signal aluZ : std_logic; + signal aluV : std_logic; + signal aluN : std_logic; + -- Pipeline registers + signal aluInputReg : unsigned(7 downto 0); + signal aluCmpInputReg : unsigned(7 downto 0); + signal aluRmwReg : unsigned(7 downto 0); + signal aluNineReg : unsigned(7 downto 0); + signal aluCReg : std_logic; + signal aluZReg : std_logic; + signal aluVReg : std_logic; + signal aluNReg : std_logic; + +-- Indexing + signal indexOut : unsigned(8 downto 0); + +begin +processAluInput: process(clk, opcInfo, A, X, Y, T, S) + variable temp : unsigned(7 downto 0); + begin + temp := (others => '1'); + if opcInfo(opcInA) = '1' then + temp := temp and A; + end if; + if opcInfo(opcInE) = '1' then + temp := temp and (A or X"EE"); + end if; + if opcInfo(opcInX) = '1' then + temp := temp and X; + end if; + if opcInfo(opcInY) = '1' then + temp := temp and Y; + end if; + if opcInfo(opcInS) = '1' then + temp := temp and S; + end if; + if opcInfo(opcInT) = '1' then + temp := temp and T; + end if; + if opcInfo(opcInClear) = '1' then + temp := (others => '0'); + end if; + if rising_edge(clk) then + aluInputReg <= temp; + end if; + + aluInput <= temp; + if pipelineAluMux then + aluInput <= aluInputReg; + end if; + end process; + +processCmpInput: process(clk, opcInfo, A, X, Y) + variable temp : unsigned(7 downto 0); + begin + temp := (others => '1'); + if opcInfo(opcInCmp) = '1' then + temp := temp and A; + end if; + if opcInfo(opcInCpx) = '1' then + temp := temp and X; + end if; + if opcInfo(opcInCpy) = '1' then + temp := temp and Y; + end if; + if rising_edge(clk) then + aluCmpInputReg <= temp; + end if; + + aluCmpInput <= temp; + if pipelineAluMux then + aluCmpInput <= aluCmpInputReg; + end if; + end process; + + -- ALU consists of two parts + -- Read-Modify-Write or index instructions: INC/DEC/ASL/LSR/ROR/ROL + -- Accumulator instructions: ADC, SBC, EOR, AND, EOR, ORA + -- Some instructions are both RMW and accumulator so for most + -- instructions the rmw results are routed through accu alu too. +processAlu: process(clk, opcInfo, aluInput, aluCmpInput, A, T, irqActive, N, V, D, I, Z, C) + variable lowBits: unsigned(5 downto 0); + variable nineBits: unsigned(8 downto 0); + variable rmwBits: unsigned(8 downto 0); + + variable varC : std_logic; + variable varZ : std_logic; + variable varV : std_logic; + variable varN : std_logic; + begin + lowBits := (others => '-'); + nineBits := (others => '-'); + rmwBits := (others => '-'); + varV := aluInput(6); -- Default for BIT / PLP / RTI + + -- Shift unit + case opcInfo(aluMode1From to aluMode1To) is + when aluModeInp => + rmwBits := C & aluInput; + when aluModeP => + rmwBits := C & N & V & '1' & (not irqActive) & D & I & Z & C; + when aluModeInc => + rmwBits := C & (aluInput + 1); + when aluModeDec => + rmwBits := C & (aluInput - 1); + when aluModeAsl => + rmwBits := aluInput & "0"; + when aluModeFlg => + rmwBits := aluInput(0) & aluInput; + when aluModeLsr => + rmwBits := aluInput(0) & "0" & aluInput(7 downto 1); + when aluModeRol => + rmwBits := aluInput & C; + when aluModeRoR => + rmwBits := aluInput(0) & C & aluInput(7 downto 1); + when aluModeAnc => + rmwBits := (aluInput(7) and A(7)) & aluInput; + when others => + rmwBits := C & aluInput; + end case; + + -- ALU + case opcInfo(aluMode2From to aluMode2To) is + when aluModeAdc => + lowBits := ("0" & A(3 downto 0) & rmwBits(8)) + ("0" & rmwBits(3 downto 0) & "1"); + ninebits := ("0" & A) + ("0" & rmwBits(7 downto 0)) + (B"00000000" & rmwBits(8)); + when aluModeSbc => + lowBits := ("0" & A(3 downto 0) & rmwBits(8)) + ("0" & (not rmwBits(3 downto 0)) & "1"); + ninebits := ("0" & A) + ("0" & (not rmwBits(7 downto 0))) + (B"00000000" & rmwBits(8)); + when aluModeCmp => + ninebits := ("0" & aluCmpInput) + ("0" & (not rmwBits(7 downto 0))) + "000000001"; + when aluModeAnd => + ninebits := rmwBits(8) & (A and rmwBits(7 downto 0)); + when aluModeEor => + ninebits := rmwBits(8) & (A xor rmwBits(7 downto 0)); + when aluModeOra => + ninebits := rmwBits(8) & (A or rmwBits(7 downto 0)); + when others => + ninebits := rmwBits; + end case; + + if (opcInfo(aluMode1From to aluMode1To) = aluModeFlg) then + varZ := rmwBits(1); + elsif ninebits(7 downto 0) = X"00" then + varZ := '1'; + else + varZ := '0'; + end if; + + case opcInfo(aluMode2From to aluMode2To) is + when aluModeAdc => + -- decimal mode low bits correction, is done after setting Z flag. + if D = '1' then + if lowBits(5 downto 1) > 9 then + ninebits(3 downto 0) := ninebits(3 downto 0) + 6; + if lowBits(5) = '0' then + ninebits(8 downto 4) := ninebits(8 downto 4) + 1; + end if; + end if; + end if; + when others => + null; + end case; + + if (opcInfo(aluMode1From to aluMode1To) = aluModeBit) + or (opcInfo(aluMode1From to aluMode1To) = aluModeFlg) then + varN := rmwBits(7); + else + varN := nineBits(7); + end if; + varC := ninebits(8); + if opcInfo(aluMode2From to aluMode2To) = aluModeArr then + varC := aluInput(7); + varV := aluInput(7) xor aluInput(6); + end if; + + case opcInfo(aluMode2From to aluMode2To) is + when aluModeAdc => + -- decimal mode high bits correction, is done after setting Z and N flags + varV := (A(7) xor ninebits(7)) and (rmwBits(7) xor ninebits(7)); + if D = '1' then + if ninebits(8 downto 4) > 9 then + ninebits(8 downto 4) := ninebits(8 downto 4) + 6; + varC := '1'; + end if; + end if; + when aluModeSbc => + varV := (A(7) xor ninebits(7)) and ((not rmwBits(7)) xor ninebits(7)); + if D = '1' then + -- Check for borrow (lower 4 bits) + if lowBits(5) = '0' then + ninebits(3 downto 0) := ninebits(3 downto 0) - 6; + end if; + -- Check for borrow (upper 4 bits) + if ninebits(8) = '0' then + ninebits(8 downto 4) := ninebits(8 downto 4) - 6; + end if; + end if; + when aluModeArr => + if D = '1' then + if (("0" & aluInput(3 downto 0)) + ("0000" & aluInput(0))) > 5 then + ninebits(3 downto 0) := ninebits(3 downto 0) + 6; + end if; + if (("0" & aluInput(7 downto 4)) + ("0000" & aluInput(4))) > 5 then + ninebits(8 downto 4) := ninebits(8 downto 4) + 6; + varC := '1'; + else + varC := '0'; + end if; + end if; + when others => + null; + end case; + + if rising_edge(clk) then + aluRmwReg <= rmwBits(7 downto 0); + aluNineReg <= ninebits(7 downto 0); + aluCReg <= varC; + aluZReg <= varZ; + aluVReg <= varV; + aluNReg <= varN; + end if; + + aluRmwOut <= rmwBits(7 downto 0); + aluRegisterOut <= ninebits(7 downto 0); + aluC <= varC; + aluZ <= varZ; + aluV <= varV; + aluN <= varN; + if pipelineAluOut then + aluRmwOut <= aluRmwReg; + aluRegisterOut <= aluNineReg; + aluC <= aluCReg; + aluZ <= aluZReg; + aluV <= aluVReg; + aluN <= aluNReg; + end if; + end process; + +calcInterrupt: process(clk) + begin + if rising_edge(clk) then + if enable = '1' then + if theCpuCycle = cycleStack4 + or reset = '1' then + nmiReg <= '1'; + end if; + + if nextCpuCycle /= cycleBranchTaken + and nextCpuCycle /= opcodeFetch then + irqReg <= irq_n; + nmiEdge <= nmi_n; + if (nmiEdge = '1') and (nmi_n = '0') then + nmiReg <= '0'; + end if; + end if; + -- The 'or opcInfo(opcSetI)' prevents NMI immediately after BRK or IRQ. + -- Presumably this is done in the real 6502/6510 to prevent a double IRQ. + processIrq <= not ((nmiReg and (irqReg or I)) or opcInfo(opcIRQ)); + end if; + end if; + end process; + +calcNextOpcode: process(clk, di, reset, processIrq) + variable myNextOpcode : unsigned(7 downto 0); + begin + -- Next opcode is read from input unless a reset or IRQ is pending. + myNextOpcode := di; + if reset = '1' then + myNextOpcode := X"4C"; + elsif processIrq = '1' then + myNextOpcode := X"00"; + end if; + + nextOpcode <= myNextOpcode; + end process; + + nextOpcInfo <= opcodeInfoTable(to_integer(nextOpcode)); + process(clk) + begin + if rising_edge(clk) then + nextOpcInfoReg <= nextOpcInfo; + end if; + end process; + + -- Read bits and flags from opcodeInfoTable and store in opcInfo. + -- This info is used to control the execution of the opcode. +calcOpcInfo: process(clk) + begin + if rising_edge(clk) then + if enable = '1' then + if (reset = '1') or (theCpuCycle = opcodeFetch) then + opcInfo <= nextOpcInfo; + if pipelineOpcode then + opcInfo <= nextOpcInfoReg; + end if; + end if; + end if; + end if; + end process; + +calcTheOpcode: process(clk) + begin + if rising_edge(clk) then + if enable = '1' then + if theCpuCycle = opcodeFetch then + irqActive <= '0'; + if processIrq = '1' then + irqActive <= '1'; + end if; + -- Fetch opcode + theOpcode <= nextOpcode; + end if; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- State machine +-- ----------------------------------------------------------------------- + process(enable, theCpuCycle, opcInfo) + begin + updateRegisters <= false; + if enable = '1' then + if opcInfo(opcRti) = '1' then + if theCpuCycle = cycleRead then + updateRegisters <= true; + end if; + elsif theCpuCycle = opcodeFetch then + updateRegisters <= true; + end if; + end if; + end process; + + debugOpcode <= theOpcode; + process(clk) + begin + if rising_edge(clk) then + if enable = '1' then + theCpuCycle <= nextCpuCycle; + end if; + if reset = '1' then + theCpuCycle <= cycle2; + end if; + end if; + end process; + + -- Determine the next cpu cycle. After the last cycle we always + -- go to opcodeFetch to get the next opcode. +calcNextCpuCycle: process(theCpuCycle, opcInfo, theOpcode, indexOut, T, N, V, C, Z) + begin + nextCpuCycle <= opcodeFetch; + + case theCpuCycle is + when opcodeFetch => + nextCpuCycle <= cycle2; + when cycle2 => + if opcInfo(opcBranch) = '1' then + if (N = theOpcode(5) and theOpcode(7 downto 6) = "00") + or (V = theOpcode(5) and theOpcode(7 downto 6) = "01") + or (C = theOpcode(5) and theOpcode(7 downto 6) = "10") + or (Z = theOpcode(5) and theOpcode(7 downto 6) = "11") then + -- Branch condition is true + nextCpuCycle <= cycleBranchTaken; + end if; + elsif (opcInfo(opcStackUp) = '1') then + nextCpuCycle <= cycleStack1; + elsif opcInfo(opcStackAddr) = '1' + and opcInfo(opcStackData) = '1' then + nextCpuCycle <= cycleStack2; + elsif opcInfo(opcStackAddr) = '1' then + nextCpuCycle <= cycleStack1; + elsif opcInfo(opcStackData) = '1' then + nextCpuCycle <= cycleWrite; + elsif opcInfo(opcAbsolute) = '1' then + nextCpuCycle <= cycle3; + elsif opcInfo(opcIndirect) = '1' then + if opcInfo(indexX) = '1' then + nextCpuCycle <= cyclePreIndirect; + else + nextCpuCycle <= cycleIndirect; + end if; + elsif opcInfo(opcZeroPage) = '1' then + if opcInfo(opcWrite) = '1' then + if (opcInfo(indexX) = '1') + or (opcInfo(indexY) = '1') then + nextCpuCycle <= cyclePreWrite; + else + nextCpuCycle <= cycleWrite; + end if; + else + if (opcInfo(indexX) = '1') + or (opcInfo(indexY) = '1') then + nextCpuCycle <= cyclePreRead; + else + nextCpuCycle <= cycleRead2; + end if; + end if; + elsif opcInfo(opcJump) = '1' then + nextCpuCycle <= cycleJump; + end if; + when cycle3 => + nextCpuCycle <= cycleRead; + if opcInfo(opcWrite) = '1' then + if (opcInfo(indexX) = '1') + or (opcInfo(indexY) = '1') then + nextCpuCycle <= cyclePreWrite; + else + nextCpuCycle <= cycleWrite; + end if; + end if; + if (opcInfo(opcIndirect) = '1') + and (opcInfo(indexX) = '1') then + if opcInfo(opcWrite) = '1' then + nextCpuCycle <= cycleWrite; + else + nextCpuCycle <= cycleRead2; + end if; + end if; + when cyclePreIndirect => + nextCpuCycle <= cycleIndirect; + when cycleIndirect => + nextCpuCycle <= cycle3; + when cycleBranchTaken => + if indexOut(8) /= T(7) then + -- Page boundary crossing during branch. + nextCpuCycle <= cycleBranchPage; + end if; + when cyclePreRead => + if opcInfo(opcZeroPage) = '1' then + nextCpuCycle <= cycleRead2; + end if; + when cycleRead => + if opcInfo(opcJump) = '1' then + nextCpuCycle <= cycleJump; + elsif indexOut(8) = '1' then + -- Page boundary crossing while indexed addressing. + nextCpuCycle <= cycleRead2; + elsif opcInfo(opcRmw) = '1' then + nextCpuCycle <= cycleRmw; + if opcInfo(indexX) = '1' + or opcInfo(indexY) = '1' then + -- 6510 needs extra cycle for indexed addressing + -- combined with RMW indexing + nextCpuCycle <= cycleRead2; + end if; + end if; + when cycleRead2 => + if opcInfo(opcRmw) = '1' then + nextCpuCycle <= cycleRmw; + end if; + when cycleRmw => + nextCpuCycle <= cycleWrite; + when cyclePreWrite => + nextCpuCycle <= cycleWrite; + when cycleStack1 => + nextCpuCycle <= cycleRead; + if opcInfo(opcStackAddr) = '1' then + nextCpuCycle <= cycleStack2; + end if; + when cycleStack2 => + nextCpuCycle <= cycleStack3; + if opcInfo(opcRti) = '1' then + nextCpuCycle <= cycleRead; + end if; + if opcInfo(opcStackData) = '0' + and opcInfo(opcStackUp) = '1' then + nextCpuCycle <= cycleJump; + end if; + when cycleStack3 => + nextCpuCycle <= cycleRead; + if opcInfo(opcStackData) = '0' + or opcInfo(opcStackUp) = '1' then + nextCpuCycle <= cycleJump; + elsif opcInfo(opcStackAddr) = '1' then + nextCpuCycle <= cycleStack4; + end if; + when cycleStack4 => + nextCpuCycle <= cycleRead; + when cycleJump => + if opcInfo(opcIncrAfter) = '1' then + -- Insert extra cycle + nextCpuCycle <= cycleEnd; + end if; + when others => + null; + end case; + end process; + +-- ----------------------------------------------------------------------- +-- T register +-- ----------------------------------------------------------------------- +calcT: process(clk) + begin + if rising_edge(clk) then + if enable = '1' then + case theCpuCycle is + when cycle2 => + T <= di; + when cycleStack1 | cycleStack2 => + if opcInfo(opcStackUp) = '1' then + -- Read from stack + T <= di; + end if; + when cycleIndirect | cycleRead | cycleRead2 => + T <= di; + when others => + null; + end case; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- A register +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if updateRegisters then + if opcInfo(opcUpdateA) = '1' then + A <= aluRegisterOut; + end if; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- X register +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if updateRegisters then + if opcInfo(opcUpdateX) = '1' then + X <= aluRegisterOut; + end if; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- Y register +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if updateRegisters then + if opcInfo(opcUpdateY) = '1' then + Y <= aluRegisterOut; + end if; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- C flag +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if updateRegisters then + if opcInfo(opcUpdateC) = '1' then + C <= aluC; + end if; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- Z flag +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if updateRegisters then + if opcInfo(opcUpdateZ) = '1' then + Z <= aluZ; + end if; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- I flag +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if updateRegisters then + if opcInfo(opcUpdateI) = '1' then + I <= aluInput(2); + end if; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- D flag +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if updateRegisters then + if opcInfo(opcUpdateD) = '1' then + D <= aluInput(3); + end if; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- V flag +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if updateRegisters then + if opcInfo(opcUpdateV) = '1' then + V <= aluV; + end if; + end if; + if enable = '1' then + if soReg = '1' and so_n = '0' then + V <= '1'; + end if; + soReg <= so_n; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- N flag +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if updateRegisters then + if opcInfo(opcUpdateN) = '1' then + N <= aluN; + end if; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- Stack pointer +-- ----------------------------------------------------------------------- + process(clk) + variable sIncDec : unsigned(7 downto 0); + variable updateFlag : boolean; + begin + if rising_edge(clk) then + + if opcInfo(opcStackUp) = '1' then + sIncDec := S + 1; + else + sIncDec := S - 1; + end if; + + if enable = '1' then + updateFlag := false; + case nextCpuCycle is + when cycleStack1 => + if (opcInfo(opcStackUp) = '1') + or (opcInfo(opcStackData) = '1') then + updateFlag := true; + end if; + when cycleStack2 => + updateFlag := true; + when cycleStack3 => + updateFlag := true; + when cycleStack4 => + updateFlag := true; + when cycleRead => + if opcInfo(opcRti) = '1' then + updateFlag := true; + end if; + when cycleWrite => + if opcInfo(opcStackData) = '1' then + updateFlag := true; + end if; + when others => + null; + end case; + if updateFlag then + S <= sIncDec; + end if; + end if; + if updateRegisters then + if opcInfo(opcUpdateS) = '1' then + S <= aluRegisterOut; + end if; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- Data out +-- ----------------------------------------------------------------------- +--calcDo: process(cpuNo, theCpuCycle, aluOut, PC, T) +calcDo: process(clk) + begin + if rising_edge(clk) then + if enable = '1' then + doReg <= aluRmwOut; + if opcInfo(opcInH) = '1' then + -- For illegal opcodes SHA, SHX, SHY, SHS + doReg <= aluRmwOut and myAddrIncrH; + end if; + + case nextCpuCycle is + when cycleStack2 => + if opcInfo(opcIRQ) = '1' + and irqActive = '0' then + doReg <= myAddrIncr(15 downto 8); + else + doReg <= PC(15 downto 8); + end if; + when cycleStack3 => + doReg <= PC(7 downto 0); + when cycleRmw => +-- do <= T; -- Read-modify-write write old value first. + doReg <= di; -- Read-modify-write write old value first. + when others => null; + end case; + end if; + end if; + end process; + do <= doReg; + + + +-- ----------------------------------------------------------------------- +-- Write enable +-- ----------------------------------------------------------------------- +calcWe: process(clk) + begin + if rising_edge(clk) then + if enable = '1' then + theWe <= '0'; + case nextCpuCycle is + when cycleStack1 => + if opcInfo(opcStackUp) = '0' + and ((opcInfo(opcStackAddr) = '0') + or (opcInfo(opcStackData) = '1')) then + theWe <= '1'; + end if; + when cycleStack2 | cycleStack3 | cycleStack4 => + if opcInfo(opcStackUp) = '0' then + theWe <= '1'; + end if; + when cycleRmw => + theWe <= '1'; + when cycleWrite => + theWe <= '1'; + when others => + null; + end case; + end if; + end if; + end process; + we <= theWe; + +-- ----------------------------------------------------------------------- +-- Program counter +-- ----------------------------------------------------------------------- +calcPC: process(clk) + begin + if rising_edge(clk) then + if enable = '1' then + case theCpuCycle is + when opcodeFetch => + PC <= myAddr; + when cycle2 => + if irqActive = '0' then + if opcInfo(opcSecondByte) = '1' then + PC <= myAddrIncr; + else + PC <= myAddr; + end if; + end if; + when cycle3 => + if opcInfo(opcAbsolute) = '1' then + PC <= myAddrIncr; + end if; + when others => + null; + end case; + end if; + end if; + end process; + debugPc <= PC; + +-- ----------------------------------------------------------------------- +-- Address generation +-- ----------------------------------------------------------------------- +calcNextAddr: process(theCpuCycle, opcInfo, indexOut, T, reset) + begin + nextAddr <= nextAddrIncr; + case theCpuCycle is + when cycle2 => + if opcInfo(opcStackAddr) = '1' + or opcInfo(opcStackData) = '1' then + nextAddr <= nextAddrStack; + elsif opcInfo(opcAbsolute) = '1' then + nextAddr <= nextAddrIncr; + elsif opcInfo(opcZeroPage) = '1' then + nextAddr <= nextAddrZeroPage; + elsif opcInfo(opcIndirect) = '1' then + nextAddr <= nextAddrZeroPage; + elsif opcInfo(opcSecondByte) = '1' then + nextAddr <= nextAddrIncr; + else + nextAddr <= nextAddrHold; + end if; + when cycle3 => + if (opcInfo(opcIndirect) = '1') + and (opcInfo(indexX) = '1') then + nextAddr <= nextAddrAbs; + else + nextAddr <= nextAddrAbsIndexed; + end if; + when cyclePreIndirect => + nextAddr <= nextAddrZPIndexed; + when cycleIndirect => + nextAddr <= nextAddrIncrL; + when cycleBranchTaken => + nextAddr <= nextAddrRelative; + when cycleBranchPage => + if T(7) = '0' then + nextAddr <= nextAddrIncrH; + else + nextAddr <= nextAddrDecrH; + end if; + when cyclePreRead => + nextAddr <= nextAddrZPIndexed; + when cycleRead => + nextAddr <= nextAddrPc; + if opcInfo(opcJump) = '1' then + -- Emulate 6510 bug, jmp(xxFF) fetches from same page. + -- Replace with nextAddrIncr if emulating 65C02 or later cpu. + nextAddr <= nextAddrIncrL; + elsif indexOut(8) = '1' then + nextAddr <= nextAddrIncrH; + elsif opcInfo(opcRmw) = '1' then + nextAddr <= nextAddrHold; + end if; + when cycleRead2 => + nextAddr <= nextAddrPc; + if opcInfo(opcRmw) = '1' then + nextAddr <= nextAddrHold; + end if; + when cycleRmw => + nextAddr <= nextAddrHold; + when cyclePreWrite => + nextAddr <= nextAddrHold; + if opcInfo(opcZeroPage) = '1' then + nextAddr <= nextAddrZPIndexed; + elsif indexOut(8) = '1' then + nextAddr <= nextAddrIncrH; + end if; + when cycleWrite => + nextAddr <= nextAddrPc; + when cycleStack1 => + nextAddr <= nextAddrStack; + when cycleStack2 => + nextAddr <= nextAddrStack; + when cycleStack3 => + nextAddr <= nextAddrStack; + if opcInfo(opcStackData) = '0' then + nextAddr <= nextAddrPc; + end if; + when cycleStack4 => + nextAddr <= nextAddrIrq; + when cycleJump => + nextAddr <= nextAddrAbs; + when others => + null; + end case; + if reset = '1' then + nextAddr <= nextAddrReset; + end if; + end process; + +indexAlu: process(opcInfo, myAddr, T, X, Y) + begin + if opcInfo(indexX) = '1' then + indexOut <= (B"0" & T) + (B"0" & X); + elsif opcInfo(indexY) = '1' then + indexOut <= (B"0" & T) + (B"0" & Y); + elsif opcInfo(opcBranch) = '1' then + indexOut <= (B"0" & T) + (B"0" & myAddr(7 downto 0)); + else + indexOut <= B"0" & T; + end if; + end process; + +calcAddr: process(clk) + begin + if rising_edge(clk) then + if enable = '1' then + case nextAddr is + when nextAddrIncr => myAddr <= myAddrIncr; + when nextAddrIncrL => myAddr(7 downto 0) <= myAddrIncr(7 downto 0); + when nextAddrIncrH => myAddr(15 downto 8) <= myAddrIncrH; + when nextAddrDecrH => myAddr(15 downto 8) <= myAddrDecrH; + when nextAddrPc => myAddr <= PC; + when nextAddrIrq => + myAddr <= X"FFFE"; + if nmiReg = '0' then + myAddr <= X"FFFA"; + end if; + when nextAddrReset => myAddr <= X"FFFC"; + when nextAddrAbs => myAddr <= di & T; + when nextAddrAbsIndexed => myAddr <= di & indexOut(7 downto 0); + when nextAddrZeroPage => myAddr <= "00000000" & di; + when nextAddrZPIndexed => myAddr <= "00000000" & indexOut(7 downto 0); + when nextAddrStack => myAddr <= "00000001" & S; + when nextAddrRelative => myAddr(7 downto 0) <= indexOut(7 downto 0); + when others => null; + end case; + end if; + end if; + end process; + + myAddrIncr <= myAddr + 1; + myAddrIncrH <= myAddr(15 downto 8) + 1; + myAddrDecrH <= myAddr(15 downto 8) - 1; + + addr <= myAddr; + + debugA <= A; + debugX <= X; + debugY <= Y; + debugS <= S; + +end architecture; + + diff --git a/Apple - 2_MiST/rtl/dac.vhd b/Apple - 2_MiST/rtl/dac.vhd new file mode 100644 index 00000000..1af6b8c1 --- /dev/null +++ b/Apple - 2_MiST/rtl/dac.vhd @@ -0,0 +1,65 @@ +-- +-- DAC.vhd +-- +-- Digital to analog convertor. +-- +-- Copyright (C)2001 SEILEBOST +-- All rights reserved. +-- +-- $Id: DAC.vhd, v0.2 2001/11/02 00:00:00 SEILEBOST $ +-- +-- from XAPP154.pdf & XAPP154.ZIP (XILINX APPLICATION) +-- +-- DAC 8 Bits ( method : sigma delta) +-- 2^N clock to convert with N = width of input +-- Ex : Bus 8 bits => 256 CLOCK master to convert an value. +-- Theorem Shannon : 2 x Fmax x 256 =< 16 MHz => Fmax = 31250 Hz +-- band of sound : 0 -> 20000 Hz : Ok !! + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_UNSIGNED.ALL; + +entity DAC is + Port ( CLK_DAC : in std_logic; + RST : in std_logic; + IN_DAC : in std_logic_vector(7 downto 0); + OUT_DAC : out std_logic ); +end DAC; + +architecture Behavioral of DAC is + +signal DeltaAdder : std_logic_vector(9 downto 0); +signal SigmaAdder : std_logic_vector(9 downto 0); +signal SigmaLatch : std_logic_vector(9 downto 0); +signal DeltaB : std_logic_vector(9 downto 0); + +begin + PROCESS(SigmaLatch, DeltaB) + BEGIN + DeltaB <= TRANSPORT ( SigmaLatch(9) & SigmaLatch(9) & "00000000"); + END PROCESS; + + PROCESS(IN_DAC, DeltaB, DeltaAdder) + BEGIN + DeltaAdder <= IN_DAC + DeltaB; + END PROCESS; + + PROCESS(DeltaAdder, SigmaLatch) + BEGIN + SigmaAdder <= DeltaAdder + SigmaLatch; + END PROCESS; + + PROCESS(CLK_DAC, RST) + BEGIN + if (RST = '1') then + SigmaLatch <= "0100000000"; + OUT_DAC <= '1'; + elsif (CLK_DAC'event and CLK_DAC = '1') then + SigmaLatch <= SigmaAdder; + OUT_DAC <= SigmaLatch(9); + end if; + END PROCESS; + +end Behavioral; diff --git a/Apple - 2_MiST/rtl/disk_ii.vhd b/Apple - 2_MiST/rtl/disk_ii.vhd new file mode 100644 index 00000000..8497abf2 --- /dev/null +++ b/Apple - 2_MiST/rtl/disk_ii.vhd @@ -0,0 +1,288 @@ +------------------------------------------------------------------------------- +-- +-- Disk II emulator +-- +-- This is read-only and only feeds "pre-nibblized" data to the processor +-- It has a single-track buffer and only supports one drive (1). +-- +-- Stephen A. Edwards, sedwards@cs.columbia.edu +-- +------------------------------------------------------------------------------- +-- +-- Each track is represented as 0x1A00 bytes +-- Each disk image consists of 35 * 0x1A00 bytes = 0x38A00 (227.5 K) +-- +-- X = $60 for slot 6 +-- +-- Off On +-- C080,X C081,X Phase 0 Head Stepper Motor Control +-- C082,X C083,X Phase 1 +-- C084,X C085,X Phase 2 +-- C086,X C087,X Phase 3 +-- C088,X C089,X Motor On +-- C08A,X C08B,X Select Drive 2 (select drive 1 when off) +-- C08C,X C08D,X Q6 (Shift/load?) +-- C08E,X C08F,X Q7 (Write request to drive) +-- +-- +-- Q7 Q6 +-- 0 0 Read +-- 0 1 Sense write protect +-- 1 0 Write +-- 1 1 Load Write Latch +-- +-- Reading a byte: +-- LDA $C08E,X set read mode +-- ... +-- READ LDA $C08C,X +-- BPL READ +-- +-- Sense write protect: +-- LDA $C08D,X +-- LDA $C08E,X +-- BMI PROTECTED +-- +-- Writing +-- STA $C08F,X set write mode +-- .. +-- LDA DATA +-- STA $C08D,X load byte to write +-- STA $C08C,X write byte to disk +-- +-- Data bytes must be written in 32 cycle loops. +-- +-- There are 70 phases for the head stepper and and 35 tracks, +-- i.e., two phase changes per track. +-- +-- The disk spins at 300 rpm; one new bit arrives every 4 us +-- The processor's clock is 1 MHz = 1 us, so it takes 8 * 4 = 32 cycles +-- for a new byte to arrive +-- +-- This corresponds to dividing the 2 MHz signal by 64 to get the byte clock +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity disk_ii is + port ( + CLK_14M : in std_logic; + CLK_2M : in std_logic; + PRE_PHASE_ZERO : in std_logic; + IO_SELECT : in std_logic; -- e.g., C600 - C6FF ROM + DEVICE_SELECT : in std_logic; -- e.g., C0E0 - C0EF I/O locations + RESET : in std_logic; + A : in unsigned(15 downto 0); + D_IN : in unsigned(7 downto 0); -- From 6502 + D_OUT : out unsigned(7 downto 0); -- To 6502 + TRACK : out unsigned(5 downto 0); -- Current track (0-34) + track_addr : out unsigned(13 downto 0); + D1_ACTIVE : out std_logic; -- Disk 1 motor on + D2_ACTIVE : out std_logic; -- Disk 2 motor on + ram_write_addr : in unsigned(13 downto 0); -- Address for track RAM + ram_di : in unsigned(7 downto 0); -- Data to track RAM + ram_we : in std_logic -- RAM write enable + ); +end disk_ii; + +architecture rtl of disk_ii is + + signal motor_phase : std_logic_vector(3 downto 0); + signal drive_on : std_logic; + signal drive2_select : std_logic; + signal q6, q7 : std_logic; + + signal rom_dout : unsigned(7 downto 0); + + -- Current phase of the head. This is in half-steps to assign + -- a unique position to the case, say, when both phase 0 and phase 1 are + -- on simultaneously. phase(7 downto 2) is the track number + signal phase : unsigned(7 downto 0); -- 0 - 139 + + -- Storage for one track worth of data in "nibblized" form + type track_ram is array(0 to 6655) of unsigned(7 downto 0); + -- Double-ported RAM for holding a track + signal track_memory : track_ram; + signal ram_do : unsigned(7 downto 0); + + -- Lower bit indicates whether disk data is "valid" or not + -- RAM address is track_byte_addr(14 downto 1) + -- This makes it look to the software like new data is constantly + -- being read into the shift register, which indicates the data is + -- not yet ready. + signal track_byte_addr : unsigned(14 downto 0); + signal read_disk : std_logic; -- When C08C accessed + +begin + + interpret_io : process (CLK_2M) + begin + if rising_edge(CLK_2M) then + if reset = '1' then + motor_phase <= (others => '0'); + drive_on <= '0'; + drive2_select <= '0'; + q6 <= '0'; + q7 <= '0'; + else + if PRE_PHASE_ZERO = '1' and DEVICE_SELECT = '1' then + if A(3) = '0' then -- C080 - C087 + motor_phase(TO_INTEGER(A(2 downto 1))) <= A(0); + else + case A(2 downto 1) is + when "00" => drive_on <= A(0); -- C088 - C089 + when "01" => drive2_select <= A(0); -- C08A - C08B + when "10" => q6 <= A(0); -- C08C - C08D + when "11" => q7 <= A(0); -- C08E - C08F + when others => null; + end case; + end if; + end if; + end if; + end if; + end process; + + D1_ACTIVE <= drive_on and not drive2_select; + D2_ACTIVE <= drive_on and drive2_select; + + -- There are two cases: + -- + -- Current phase is odd (between two poles) + -- | + -- V + -- -3-2-1 0 1 2 3 + -- X X X X + -- 0 1 2 3 + -- + -- + -- Current phase is even (under a pole) + -- | + -- V + -- -4-3-2-1 0 1 2 3 4 + -- X X X X X + -- 0 1 2 3 0 + -- + + update_phase : process (CLK_14M) + variable phase_change : integer; + variable new_phase : integer; + variable rel_phase : std_logic_vector(3 downto 0); + begin + if rising_edge(CLK_14M) then + if reset = '1' then + phase <= TO_UNSIGNED(70, 8); -- Deliberately odd to test reset + else + phase_change := 0; + new_phase := TO_INTEGER(phase); + rel_phase := motor_phase; + case phase(2 downto 1) is + when "00" => + rel_phase := rel_phase(1 downto 0) & rel_phase(3 downto 2); + when "01" => + rel_phase := rel_phase(2 downto 0) & rel_phase(3); + when "10" => null; + when "11" => + rel_phase := rel_phase(0) & rel_phase(3 downto 1); + when others => null; + end case; + + if phase(0) = '1' then -- Phase is odd + case rel_phase is + when "0000" => phase_change := 0; + when "0001" => phase_change := -3; + when "0010" => phase_change := -1; + when "0011" => phase_change := -2; + when "0100" => phase_change := 1; + when "0101" => phase_change := -1; + when "0110" => phase_change := 0; + when "0111" => phase_change := -1; + when "1000" => phase_change := 3; + when "1001" => phase_change := 0; + when "1010" => phase_change := 1; + when "1011" => phase_change := -3; + when "1111" => phase_change := 0; + when others => null; + end case; + else -- Phase is even + case rel_phase is + when "0000" => phase_change := 0; + when "0001" => phase_change := -2; + when "0010" => phase_change := 0; + when "0011" => phase_change := -1; + when "0100" => phase_change := 2; + when "0101" => phase_change := 0; + when "0110" => phase_change := 1; + when "0111" => phase_change := 0; + when "1000" => phase_change := 0; + when "1001" => phase_change := 1; + when "1010" => phase_change := 2; + when "1011" => phase_change := -2; + when "1111" => phase_change := 0; + when others => null; + end case; + end if; + + if new_phase + phase_change <= 0 then + new_phase := 0; + elsif new_phase + phase_change > 139 then + new_phase := 139; + else + new_phase := new_phase + phase_change; + end if; + phase <= TO_UNSIGNED(new_phase, 8); + end if; + end if; + end process; + + TRACK <= phase(7 downto 2); + + -- Dual-ported RAM holding the contents of the track + track_storage : process (CLK_14M) + begin + if rising_edge(CLK_14M) then + if ram_we = '1' then + track_memory(to_integer(ram_write_addr)) <= ram_di; + end if; + ram_do <= track_memory(to_integer(track_byte_addr(14 downto 1))); + end if; + end process; + + -- Go to the next byte when the disk is accessed or if the counter times out + read_head : process (CLK_2M) + variable byte_delay : unsigned(5 downto 0); -- Accounts for disk spin rate + begin + if rising_edge(CLK_2M) then + if reset = '1' then + track_byte_addr <= (others => '0'); + byte_delay := (others => '0'); + else + byte_delay := byte_delay - 1; + if (read_disk = '1' and PRE_PHASE_ZERO = '1') or byte_delay = 0 then + byte_delay := (others => '0'); + if track_byte_addr = X"33FE" then + track_byte_addr <= (others => '0'); + else + track_byte_addr <= track_byte_addr + 1; + end if; + end if; + end if; + end if; + end process; + + rom : entity work.disk_ii_rom port map ( + addr => A(7 downto 0), + clk => CLK_14M, + dout => rom_dout); + + read_disk <= '1' when DEVICE_SELECT = '1' and A(3 downto 0) = x"C" else + '0'; -- C08C + + D_OUT <= rom_dout when IO_SELECT = '1' else + ram_do when read_disk = '1' and track_byte_addr(0) = '0' else + (others => '0'); + + track_addr <= track_byte_addr(14 downto 1); + +end rtl; diff --git a/Apple - 2_MiST/rtl/disk_ii_rom.vhd b/Apple - 2_MiST/rtl/disk_ii_rom.vhd new file mode 100644 index 00000000..4711adab --- /dev/null +++ b/Apple - 2_MiST/rtl/disk_ii_rom.vhd @@ -0,0 +1,58 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity disk_ii_rom is + port ( + addr : in unsigned(7 downto 0); + clk : in std_logic; + dout : out unsigned(7 downto 0)); +end disk_ii_rom; + +architecture rtl of disk_ii_rom is + type rom_array is array(0 to 255) of unsigned(7 downto 0); + + constant ROM : rom_array := ( + X"a2", X"20", X"a0", X"00", X"a2", X"03", X"86", X"3c", + X"8a", X"0a", X"24", X"3c", X"f0", X"10", X"05", X"3c", + X"49", X"ff", X"29", X"7e", X"b0", X"08", X"4a", X"d0", + X"fb", X"98", X"9d", X"56", X"03", X"c8", X"e8", X"10", + X"e5", X"20", X"58", X"ff", X"ba", X"bd", X"00", X"01", + X"0a", X"0a", X"0a", X"0a", X"85", X"2b", X"aa", X"bd", + X"8e", X"c0", X"bd", X"8c", X"c0", X"bd", X"8a", X"c0", + X"bd", X"89", X"c0", X"a0", X"50", X"bd", X"80", X"c0", + X"98", X"29", X"03", X"0a", X"05", X"2b", X"aa", X"bd", + X"81", X"c0", X"a9", X"56", X"20", X"a8", X"fc", X"88", + X"10", X"eb", X"85", X"26", X"85", X"3d", X"85", X"41", + X"a9", X"08", X"85", X"27", X"18", X"08", X"bd", X"8c", + X"c0", X"10", X"fb", X"49", X"d5", X"d0", X"f7", X"bd", + X"8c", X"c0", X"10", X"fb", X"c9", X"aa", X"d0", X"f3", + X"ea", X"bd", X"8c", X"c0", X"10", X"fb", X"c9", X"96", + X"f0", X"09", X"28", X"90", X"df", X"49", X"ad", X"f0", + X"25", X"d0", X"d9", X"a0", X"03", X"85", X"40", X"bd", + X"8c", X"c0", X"10", X"fb", X"2a", X"85", X"3c", X"bd", + X"8c", X"c0", X"10", X"fb", X"25", X"3c", X"88", X"d0", + X"ec", X"28", X"c5", X"3d", X"d0", X"be", X"a5", X"40", + X"c5", X"41", X"d0", X"b8", X"b0", X"b7", X"a0", X"56", + X"84", X"3c", X"bc", X"8c", X"c0", X"10", X"fb", X"59", + X"d6", X"02", X"a4", X"3c", X"88", X"99", X"00", X"03", + X"d0", X"ee", X"84", X"3c", X"bc", X"8c", X"c0", X"10", + X"fb", X"59", X"d6", X"02", X"a4", X"3c", X"91", X"26", + X"c8", X"d0", X"ef", X"bc", X"8c", X"c0", X"10", X"fb", + X"59", X"d6", X"02", X"d0", X"87", X"a0", X"00", X"a2", + X"56", X"ca", X"30", X"fb", X"b1", X"26", X"5e", X"00", + X"03", X"2a", X"5e", X"00", X"03", X"2a", X"91", X"26", + X"c8", X"d0", X"ee", X"e6", X"27", X"e6", X"3d", X"a5", + X"3d", X"cd", X"00", X"08", X"a6", X"2b", X"90", X"db", + X"4c", X"01", X"08", X"00", X"00", X"00", X"00", X"00"); + +begin + +process (clk) + begin + if rising_edge(clk) then + dout <= ROM(TO_INTEGER(addr)); + end if; + end process; + +end rtl; diff --git a/Apple - 2_MiST/rtl/hq2x.sv b/Apple - 2_MiST/rtl/hq2x.sv new file mode 100644 index 00000000..f17732b6 --- /dev/null +++ b/Apple - 2_MiST/rtl/hq2x.sv @@ -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 diff --git a/Apple - 2_MiST/rtl/keyboard.vhd b/Apple - 2_MiST/rtl/keyboard.vhd new file mode 100644 index 00000000..4c5a72b4 --- /dev/null +++ b/Apple - 2_MiST/rtl/keyboard.vhd @@ -0,0 +1,390 @@ +------------------------------------------------------------------------------- +-- +-- PS/2 Keyboard interface for the Apple ][ +-- +-- Stephen A. Edwards, sedwards@cs.columbia.edu +-- After an original by Alex Freed +-- i18n & French keyboard by Michel Stempin +-- +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity keyboard is + + generic ( + KEYMAP : string := "EN-us" -- English US keymap + -- KEYMAP : string := "FR-fr" -- French keymap + ); + + port ( + PS2_Clk : in std_logic; -- From PS/2 port + PS2_Data : in std_logic; -- From PS/2 port + CLK_14M : in std_logic; + read : in std_logic; -- Read strobe + reset : in std_logic; + K : out unsigned(7 downto 0) -- Latched, decoded keyboard data + ); +end keyboard; + +architecture rtl of keyboard is + + signal code, latched_code : unsigned(7 downto 0); + signal code_available : std_logic; + signal ascii : unsigned(7 downto 0); -- decoded + signal shifted_code : unsigned(11 downto 0); + + signal key_pressed : std_logic; -- Key pressed & not read + signal ctrl, shift, alt : std_logic; + + -- Special PS/2 keyboard codes + constant KEY_UP_CODE : unsigned(7 downto 0) := X"F0"; + constant EXTENDED_CODE : unsigned(7 downto 0) := X"E0"; + constant LEFT_SHIFT : unsigned(7 downto 0) := X"12"; + constant RIGHT_SHIFT : unsigned(7 downto 0) := X"59"; + constant LEFT_CTRL : unsigned(7 downto 0) := X"14"; + constant ALT_GR : unsigned(7 downto 0) := X"11"; + + type states is (IDLE, + HAVE_CODE, + DECODE, + GOT_KEY_UP_CODE, + GOT_KEY_UP2, + GOT_KEY_UP3, + KEY_UP, + NORMAL_KEY + ); + + signal state, next_state : states; + +begin + + ps2_controller : entity work.PS2_Ctrl port map ( + Clk => CLK_14M, + Reset => reset, + PS2_Clk => PS2_Clk, + PS2_Data => PS2_Data, + DoRead => code_available, + Scan_DAV => code_available, + Scan_Code => code); + + K <= key_pressed & "00" & ascii(4 downto 0) when ctrl = '1' else + key_pressed & ascii(6 downto 0); + + shift_ctrl : process (CLK_14M, reset) + begin + if reset = '1' then + shift <= '0'; + ctrl <= '0'; + elsif rising_edge(CLK_14M) then + if state = HAVE_CODE then + if code = LEFT_SHIFT or code = RIGHT_SHIFT then + shift <= '1'; + elsif code = LEFT_CTRL then + ctrl <= '1'; + elsif code = ALT_GR then + alt <= '1'; + end if; + elsif state = KEY_UP then + if code = LEFT_SHIFT or code = RIGHT_SHIFT then + shift <= '0'; + elsif code = LEFT_CTRL then + ctrl <= '0'; + elsif code = ALT_GR then + alt <= '0'; + end if; + end if; + end if; + end process shift_ctrl; + + fsm : process (CLK_14M, reset) + begin + if reset = '1' then + state <= IDLE; + latched_code <= (others => '0'); + key_pressed <= '0'; + elsif rising_edge(CLK_14M) then + state <= next_state; + if read = '1' then key_pressed <= '0'; end if; + if state = NORMAL_KEY then + latched_code <= code ; + key_pressed <= '1'; + end if; + end if; + end process fsm; + + fsm_next_state : process (code, code_available, state) + begin + next_state <= state; + case state is + when IDLE => + if code_available = '1' then next_state <= HAVE_CODE; end if; + + when HAVE_CODE => + next_state <= DECODE; + + when DECODE => + if code = KEY_UP_CODE then + next_state <= GOT_KEY_UP_CODE; + elsif code = EXTENDED_CODE then -- Treat extended codes as normal + next_state <= IDLE; + elsif code = LEFT_SHIFT or code = RIGHT_SHIFT or code = LEFT_CTRL then + next_state <= IDLE; + else + next_state <= NORMAL_KEY; + end if; + + when GOT_KEY_UP_CODE => + next_state <= GOT_KEY_UP2; + + when GOT_KEY_UP2 => + next_state <= GOT_KEY_UP3; + + when GOT_KEY_UP3 => + if code_available = '1' then + next_state <= KEY_UP; + end if; + + when KEY_UP | NORMAL_KEY => + next_state <= IDLE; + end case; + end process fsm_next_state; + + -- PS/2 scancode to ASCII translation + + shifted_code <= "00" & alt & shift & latched_code; + + EN_us: if KEYMAP = "EN-us" generate + with shifted_code select + ascii <= + X"08" when X"066", -- Backspace ("backspace" key) + X"08" when X"166", -- Backspace ("backspace" key) + X"09" when X"00d", -- Horizontal Tab + X"09" when X"10d", -- Horizontal Tab + X"0d" when X"05a", -- Carriage return ("enter" key) + X"0d" when X"15a", -- Carriage return ("enter" key) + X"1b" when X"076", -- Escape ("esc" key) + X"1b" when X"176", -- Escape ("esc" key) + X"20" when X"029", -- Space + X"20" when X"129", -- Space + X"21" when X"116", -- ! + X"22" when X"152", -- " + X"23" when X"126", -- # + X"24" when X"125", -- $ + X"25" when X"12e", -- + X"26" when X"13d", -- + X"27" when X"052", -- + X"28" when X"146", -- + X"29" when X"145", -- + X"2a" when X"13e", -- * + X"2b" when X"155", -- + + X"2c" when X"041", -- , + X"2d" when X"04e", -- - + X"2e" when X"049", -- . + X"2f" when X"04a", -- / + X"30" when X"045", -- 0 + X"31" when X"016", -- 1 + X"32" when X"01e", -- 2 + X"33" when X"026", -- 3 + X"34" when X"025", -- 4 + X"35" when X"02e", -- 5 + X"36" when X"036", -- 6 + X"37" when X"03d", -- 7 + X"38" when X"03e", -- 8 + X"39" when X"046", -- 9 + X"3a" when X"14c", -- : + X"3b" when X"04c", -- ; + X"3c" when X"141", -- < + X"3d" when X"055", -- = + X"3e" when X"149", -- > + X"3f" when X"14a", -- ? + X"40" when X"11e", -- @ + X"41" when X"11c", -- A + X"42" when X"132", -- B + X"43" when X"121", -- C + X"44" when X"123", -- D + X"45" when X"124", -- E + X"46" when X"12b", -- F + X"47" when X"134", -- G + X"48" when X"133", -- H + X"49" when X"143", -- I + X"4a" when X"13b", -- J + X"4b" when X"142", -- K + X"4c" when X"14b", -- L + X"4d" when X"13a", -- M + X"4e" when X"131", -- N + X"4f" when X"144", -- O + X"50" when X"14d", -- P + X"51" when X"115", -- Q + X"52" when X"12d", -- R + X"53" when X"11b", -- S + X"54" when X"12c", -- T + X"55" when X"13c", -- U + X"56" when X"12a", -- V + X"57" when X"11d", -- W + X"58" when X"122", -- X + X"59" when X"135", -- Y + X"5a" when X"11a", -- Z + X"5b" when X"054", -- [ + X"5c" when X"05d", -- \ + X"5d" when X"05b", -- ] + X"5e" when X"136", -- ^ + X"5f" when X"14e", -- _ + X"60" when X"00e", -- ` + X"41" when X"01c", -- A + X"42" when X"032", -- B + X"43" when X"021", -- C + X"44" when X"023", -- D + X"45" when X"024", -- E + X"46" when X"02b", -- F + X"47" when X"034", -- G + X"48" when X"033", -- H + X"49" when X"043", -- I + X"4a" when X"03b", -- J + X"4b" when X"042", -- K + X"4c" when X"04b", -- L + X"4d" when X"03a", -- M + X"4e" when X"031", -- N + X"4f" when X"044", -- O + X"50" when X"04d", -- P + X"51" when X"015", -- Q + X"52" when X"02d", -- R + X"53" when X"01b", -- S + X"54" when X"02c", -- T + X"55" when X"03c", -- U + X"56" when X"02a", -- V + X"57" when X"01d", -- W + X"58" when X"022", -- X + X"59" when X"035", -- Y + X"5a" when X"01a", -- Z + X"7b" when X"154", -- { + X"7c" when X"15d", -- | + X"7d" when X"15b", -- } + X"7e" when X"10e", -- ~ + X"7f" when X"071", -- (Delete OR DEL on numeric keypad) + X"15" when X"074", -- right arrow (cntrl U) + X"08" when X"06b", -- left arrow (BS) + X"0B" when X"075", -- (up arrow) + X"0A" when X"072", -- (down arrow, ^J, LF) + X"7f" when X"171", -- (Delete OR DEL on numeric keypad) + X"00" when others; + end generate EN_us; + + FR_fr: if KEYMAP = "FR-fr" generate + with shifted_code select + ascii <= + X"08" when X"066", -- Backspace ("backspace" key) + X"08" when X"166", -- Backspace ("backspace" key) + X"09" when X"00d", -- Horizontal Tab + X"09" when X"10d", -- Horizontal Tab + X"0d" when X"05a", -- Carriage return ("enter" key) + X"0d" when X"15a", -- Carriage return ("enter" key) + X"1b" when X"076", -- Escape ("esc" key) + X"1b" when X"176", -- Escape ("esc" key) + X"20" when X"029", -- Space + X"20" when X"129", -- Space + X"21" when X"04a", -- ! + X"22" when X"026", -- " + X"23" when X"226", -- # + X"24" when X"05b", -- $ + X"25" when X"152", -- % + X"26" when X"016", -- & + X"27" when X"025", -- ' + X"28" when X"02e", -- ( + X"29" when X"04e", -- ) + X"2a" when X"05d", -- * + X"2b" when X"155", -- + + X"2c" when X"03a", -- , + X"2d" when X"036", -- - + X"2e" when X"141", -- . + X"2f" when X"149", -- / + X"30" when X"145", -- 0 + X"31" when X"116", -- 1 + X"32" when X"11e", -- 2 + X"33" when X"126", -- 3 + X"34" when X"125", -- 4 + X"35" when X"12e", -- 5 + X"36" when X"136", -- 6 + X"37" when X"13d", -- 7 + X"38" when X"13e", -- 8 + X"39" when X"146", -- 9 + X"3a" when X"049", -- : + X"3b" when X"041", -- ; + X"3c" when X"061", -- < + X"3d" when X"055", -- = + X"3e" when X"161", -- > + X"3f" when X"13a", -- ? + X"40" when X"245", -- @ + X"41" when X"115", -- A + X"42" when X"132", -- B + X"43" when X"121", -- C + X"44" when X"123", -- D + X"45" when X"124", -- E + X"46" when X"12b", -- F + X"47" when X"134", -- G + X"48" when X"133", -- H + X"49" when X"143", -- I + X"4a" when X"13b", -- J + X"4b" when X"142", -- K + X"4c" when X"14b", -- L + X"4d" when X"14c", -- M + X"4e" when X"131", -- N + X"4f" when X"144", -- O + X"50" when X"14d", -- P + X"51" when X"11c", -- Q + X"52" when X"12d", -- R + X"53" when X"11b", -- S + X"54" when X"12c", -- T + X"55" when X"13c", -- U + X"56" when X"12a", -- V + X"57" when X"11a", -- W + X"58" when X"122", -- X + X"59" when X"135", -- Y + X"5a" when X"11d", -- Z + X"5b" when X"22e", -- [ + X"5c" when X"23e", -- \ + X"5d" when X"24e", -- ] + X"5e" when X"054", -- ^ + X"5f" when X"03e", -- _ + X"60" when X"23d", -- ` + X"41" when X"015", -- A + X"42" when X"032", -- B + X"43" when X"021", -- C + X"44" when X"023", -- D + X"45" when X"024", -- E + X"46" when X"02b", -- F + X"47" when X"034", -- G + X"48" when X"033", -- H + X"49" when X"043", -- I + X"4a" when X"03b", -- J + X"4b" when X"042", -- K + X"4c" when X"04b", -- L + X"4d" when X"04c", -- M + X"4e" when X"031", -- N + X"4f" when X"044", -- O + X"50" when X"04d", -- P + X"51" when X"01c", -- Q + X"52" when X"02d", -- R + X"53" when X"01b", -- S + X"54" when X"02c", -- T + X"55" when X"03c", -- U + X"56" when X"02a", -- V + X"57" when X"01a", -- W + X"58" when X"022", -- X + X"59" when X"035", -- Y + X"5a" when X"01d", -- Z + X"7b" when X"225", -- { + X"7c" when X"236", -- | + X"7d" when X"255", -- } + X"7e" when X"21e", -- ~ + X"7f" when X"071", -- (Delete OR DEL on numeric keypad) + X"15" when X"074", -- right arrow (cntrl U) + X"08" when X"06b", -- left arrow (BS) + X"0B" when X"075", -- (up arrow) + X"0A" when X"072", -- (down arrow, ^J, LF) + X"7f" when X"171", -- (Delete OR DEL on numeric keypad) + X"00" when others; + end generate FR_fr; + +end rtl; diff --git a/Apple - 2_MiST/rtl/main_roms.vhd b/Apple - 2_MiST/rtl/main_roms.vhd new file mode 100644 index 00000000..8dc346d1 --- /dev/null +++ b/Apple - 2_MiST/rtl/main_roms.vhd @@ -0,0 +1,2075 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity main_roms is + port ( + addr : in unsigned(13 downto 0); + clk : in std_logic; + dout : out unsigned(7 downto 0)); +end main_roms; + +-- Hack: In Quartus II 9.1, memory blocks must be a power of 2 +-- in order to be inferred as altsyncram blocks +architecture rtl of main_roms is + type rom_array is array(0 to 16383) of unsigned(7 downto 0); + + constant ROM : rom_array := ( + X"6f", X"d8", X"65", X"d7", X"f8", X"dc", X"94", X"d9", + X"b1", X"db", X"30", X"f3", X"d8", X"df", X"e1", X"db", + X"8f", X"f3", X"98", X"f3", X"e4", X"f1", X"dd", X"f1", + X"d4", X"f1", X"24", X"f2", X"31", X"f2", X"40", X"f2", + X"d7", X"f3", X"e1", X"f3", X"e8", X"f6", X"fd", X"f6", + X"68", X"f7", X"6e", X"f7", X"e6", X"f7", X"57", X"fc", + X"20", X"f7", X"26", X"f7", X"74", X"f7", X"6c", X"f2", + X"6e", X"f2", X"72", X"f2", X"76", X"f2", X"7f", X"f2", + X"4e", X"f2", X"6a", X"d9", X"55", X"f2", X"85", X"f2", + X"a5", X"f2", X"ca", X"f2", X"17", X"f3", X"bb", X"f3", + X"9e", X"f3", X"61", X"f2", X"45", X"da", X"3d", X"d9", + X"11", X"d9", X"c8", X"d9", X"48", X"d8", X"f4", X"03", + X"20", X"d9", X"6a", X"d9", X"db", X"d9", X"6d", X"d8", + X"eb", X"d9", X"83", X"e7", X"c8", X"d8", X"af", X"d8", + X"12", X"e3", X"7a", X"e7", X"d4", X"da", X"95", X"d8", + X"a4", X"d6", X"69", X"d6", X"9f", X"db", X"48", X"d6", + X"90", X"eb", X"23", X"ec", X"af", X"eb", X"0a", X"00", + X"de", X"e2", X"12", X"d4", X"cd", X"df", X"ff", X"e2", + X"8d", X"ee", X"ae", X"ef", X"41", X"e9", X"09", X"ef", + X"ea", X"ef", X"f1", X"ef", X"3a", X"f0", X"9e", X"f0", + X"64", X"e7", X"d6", X"e6", X"c5", X"e3", X"07", X"e7", + X"e5", X"e6", X"46", X"e6", X"5a", X"e6", X"86", X"e6", + X"91", X"e6", X"79", X"c0", X"e7", X"79", X"a9", X"e7", + X"7b", X"81", X"e9", X"7b", X"68", X"ea", X"7d", X"96", + X"ee", X"50", X"54", X"df", X"46", X"4e", X"df", X"7f", + X"cf", X"ee", X"7f", X"97", X"de", X"64", X"64", X"df", + X"45", X"4e", X"c4", X"46", X"4f", X"d2", X"4e", X"45", + X"58", X"d4", X"44", X"41", X"54", X"c1", X"49", X"4e", + X"50", X"55", X"d4", X"44", X"45", X"cc", X"44", X"49", + X"cd", X"52", X"45", X"41", X"c4", X"47", X"d2", X"54", + X"45", X"58", X"d4", X"50", X"52", X"a3", X"49", X"4e", + X"a3", X"43", X"41", X"4c", X"cc", X"50", X"4c", X"4f", + X"d4", X"48", X"4c", X"49", X"ce", X"56", X"4c", X"49", + X"ce", X"48", X"47", X"52", X"b2", X"48", X"47", X"d2", + X"48", X"43", X"4f", X"4c", X"4f", X"52", X"bd", X"48", + X"50", X"4c", X"4f", X"d4", X"44", X"52", X"41", X"d7", + X"58", X"44", X"52", X"41", X"d7", X"48", X"54", X"41", + X"c2", X"48", X"4f", X"4d", X"c5", X"52", X"4f", X"54", + X"bd", X"53", X"43", X"41", X"4c", X"45", X"bd", X"53", + X"48", X"4c", X"4f", X"41", X"c4", X"54", X"52", X"41", + X"43", X"c5", X"4e", X"4f", X"54", X"52", X"41", X"43", + X"c5", X"4e", X"4f", X"52", X"4d", X"41", X"cc", X"49", + X"4e", X"56", X"45", X"52", X"53", X"c5", X"46", X"4c", + X"41", X"53", X"c8", X"43", X"4f", X"4c", X"4f", X"52", + X"bd", X"50", X"4f", X"d0", X"56", X"54", X"41", X"c2", + X"48", X"49", X"4d", X"45", X"4d", X"ba", X"4c", X"4f", + X"4d", X"45", X"4d", X"ba", X"4f", X"4e", X"45", X"52", + X"d2", X"52", X"45", X"53", X"55", X"4d", X"c5", X"52", + X"45", X"43", X"41", X"4c", X"cc", X"53", X"54", X"4f", + X"52", X"c5", X"53", X"50", X"45", X"45", X"44", X"bd", + X"4c", X"45", X"d4", X"47", X"4f", X"54", X"cf", X"52", + X"55", X"ce", X"49", X"c6", X"52", X"45", X"53", X"54", + X"4f", X"52", X"c5", X"a6", X"47", X"4f", X"53", X"55", + X"c2", X"52", X"45", X"54", X"55", X"52", X"ce", X"52", + X"45", X"cd", X"53", X"54", X"4f", X"d0", X"4f", X"ce", + X"57", X"41", X"49", X"d4", X"4c", X"4f", X"41", X"c4", + X"53", X"41", X"56", X"c5", X"44", X"45", X"c6", X"50", + X"4f", X"4b", X"c5", X"50", X"52", X"49", X"4e", X"d4", + X"43", X"4f", X"4e", X"d4", X"4c", X"49", X"53", X"d4", + X"43", X"4c", X"45", X"41", X"d2", X"47", X"45", X"d4", + X"4e", X"45", X"d7", X"54", X"41", X"42", X"a8", X"54", + X"cf", X"46", X"ce", X"53", X"50", X"43", X"a8", X"54", + X"48", X"45", X"ce", X"41", X"d4", X"4e", X"4f", X"d4", + X"53", X"54", X"45", X"d0", X"ab", X"ad", X"aa", X"af", + X"de", X"41", X"4e", X"c4", X"4f", X"d2", X"be", X"bd", + X"bc", X"53", X"47", X"ce", X"49", X"4e", X"d4", X"41", + X"42", X"d3", X"55", X"53", X"d2", X"46", X"52", X"c5", + X"53", X"43", X"52", X"4e", X"a8", X"50", X"44", X"cc", + X"50", X"4f", X"d3", X"53", X"51", X"d2", X"52", X"4e", + X"c4", X"4c", X"4f", X"c7", X"45", X"58", X"d0", X"43", + X"4f", X"d3", X"53", X"49", X"ce", X"54", X"41", X"ce", + X"41", X"54", X"ce", X"50", X"45", X"45", X"cb", X"4c", + X"45", X"ce", X"53", X"54", X"52", X"a4", X"56", X"41", + X"cc", X"41", X"53", X"c3", X"43", X"48", X"52", X"a4", + X"4c", X"45", X"46", X"54", X"a4", X"52", X"49", X"47", + X"48", X"54", X"a4", X"4d", X"49", X"44", X"a4", X"00", + X"4e", X"45", X"58", X"54", X"20", X"57", X"49", X"54", + X"48", X"4f", X"55", X"54", X"20", X"46", X"4f", X"d2", + X"53", X"59", X"4e", X"54", X"41", X"d8", X"52", X"45", + X"54", X"55", X"52", X"4e", X"20", X"57", X"49", X"54", + X"48", X"4f", X"55", X"54", X"20", X"47", X"4f", X"53", + X"55", X"c2", X"4f", X"55", X"54", X"20", X"4f", X"46", + X"20", X"44", X"41", X"54", X"c1", X"49", X"4c", X"4c", + X"45", X"47", X"41", X"4c", X"20", X"51", X"55", X"41", + X"4e", X"54", X"49", X"54", X"d9", X"4f", X"56", X"45", + X"52", X"46", X"4c", X"4f", X"d7", X"4f", X"55", X"54", + X"20", X"4f", X"46", X"20", X"4d", X"45", X"4d", X"4f", + X"52", X"d9", X"55", X"4e", X"44", X"45", X"46", X"27", + X"44", X"20", X"53", X"54", X"41", X"54", X"45", X"4d", + X"45", X"4e", X"d4", X"42", X"41", X"44", X"20", X"53", + X"55", X"42", X"53", X"43", X"52", X"49", X"50", X"d4", + X"52", X"45", X"44", X"49", X"4d", X"27", X"44", X"20", + X"41", X"52", X"52", X"41", X"d9", X"44", X"49", X"56", + X"49", X"53", X"49", X"4f", X"4e", X"20", X"42", X"59", + X"20", X"5a", X"45", X"52", X"cf", X"49", X"4c", X"4c", + X"45", X"47", X"41", X"4c", X"20", X"44", X"49", X"52", + X"45", X"43", X"d4", X"54", X"59", X"50", X"45", X"20", + X"4d", X"49", X"53", X"4d", X"41", X"54", X"43", X"c8", + X"53", X"54", X"52", X"49", X"4e", X"47", X"20", X"54", + X"4f", X"4f", X"20", X"4c", X"4f", X"4e", X"c7", X"46", + X"4f", X"52", X"4d", X"55", X"4c", X"41", X"20", X"54", + X"4f", X"4f", X"20", X"43", X"4f", X"4d", X"50", X"4c", + X"45", X"d8", X"43", X"41", X"4e", X"27", X"54", X"20", + X"43", X"4f", X"4e", X"54", X"49", X"4e", X"55", X"c5", + X"55", X"4e", X"44", X"45", X"46", X"27", X"44", X"20", + X"46", X"55", X"4e", X"43", X"54", X"49", X"4f", X"ce", + X"20", X"45", X"52", X"52", X"4f", X"52", X"07", X"00", + X"20", X"49", X"4e", X"20", X"00", X"0d", X"42", X"52", + X"45", X"41", X"4b", X"07", X"00", X"ba", X"e8", X"e8", + X"e8", X"e8", X"bd", X"01", X"01", X"c9", X"81", X"d0", + X"21", X"a5", X"86", X"d0", X"0a", X"bd", X"02", X"01", + X"85", X"85", X"bd", X"03", X"01", X"85", X"86", X"dd", + X"03", X"01", X"d0", X"07", X"a5", X"85", X"dd", X"02", + X"01", X"f0", X"07", X"8a", X"18", X"69", X"12", X"aa", + X"d0", X"d8", X"60", X"20", X"e3", X"d3", X"85", X"6d", + X"84", X"6e", X"38", X"a5", X"96", X"e5", X"9b", X"85", + X"5e", X"a8", X"a5", X"97", X"e5", X"9c", X"aa", X"e8", + X"98", X"f0", X"23", X"a5", X"96", X"38", X"e5", X"5e", + X"85", X"96", X"b0", X"03", X"c6", X"97", X"38", X"a5", + X"94", X"e5", X"5e", X"85", X"94", X"b0", X"08", X"c6", + X"95", X"90", X"04", X"b1", X"96", X"91", X"94", X"88", + X"d0", X"f9", X"b1", X"96", X"91", X"94", X"c6", X"97", + X"c6", X"95", X"ca", X"d0", X"f2", X"60", X"0a", X"69", + X"36", X"b0", X"35", X"85", X"5e", X"ba", X"e4", X"5e", + X"90", X"2e", X"60", X"c4", X"70", X"90", X"28", X"d0", + X"04", X"c5", X"6f", X"90", X"22", X"48", X"a2", X"09", + X"98", X"48", X"b5", X"93", X"ca", X"10", X"fa", X"20", + X"84", X"e4", X"a2", X"f7", X"68", X"95", X"9d", X"e8", + X"30", X"fa", X"68", X"a8", X"68", X"c4", X"70", X"90", + X"06", X"d0", X"05", X"c5", X"6f", X"b0", X"01", X"60", + X"a2", X"4d", X"24", X"d8", X"10", X"03", X"4c", X"e9", + X"f2", X"20", X"fb", X"da", X"20", X"5a", X"db", X"bd", + X"60", X"d2", X"48", X"20", X"5c", X"db", X"e8", X"68", + X"10", X"f5", X"20", X"83", X"d6", X"a9", X"50", X"a0", + X"d3", X"20", X"3a", X"db", X"a4", X"76", X"c8", X"f0", + X"03", X"20", X"19", X"ed", X"20", X"fb", X"da", X"a2", + X"dd", X"20", X"2e", X"d5", X"86", X"b8", X"84", X"b9", + X"46", X"d8", X"20", X"b1", X"00", X"aa", X"f0", X"ec", + X"a2", X"ff", X"86", X"76", X"90", X"06", X"20", X"59", + X"d5", X"4c", X"05", X"d8", X"a6", X"af", X"86", X"69", + X"a6", X"b0", X"86", X"6a", X"20", X"0c", X"da", X"20", + X"59", X"d5", X"84", X"0f", X"20", X"1a", X"d6", X"90", + X"44", X"a0", X"01", X"b1", X"9b", X"85", X"5f", X"a5", + X"69", X"85", X"5e", X"a5", X"9c", X"85", X"61", X"a5", + X"9b", X"88", X"f1", X"9b", X"18", X"65", X"69", X"85", + X"69", X"85", X"60", X"a5", X"6a", X"69", X"ff", X"85", + X"6a", X"e5", X"9c", X"aa", X"38", X"a5", X"9b", X"e5", + X"69", X"a8", X"b0", X"03", X"e8", X"c6", X"61", X"18", + X"65", X"5e", X"90", X"03", X"c6", X"5f", X"18", X"b1", + X"5e", X"91", X"60", X"c8", X"d0", X"f9", X"e6", X"5f", + X"e6", X"61", X"ca", X"d0", X"f2", X"ad", X"00", X"02", + X"f0", X"38", X"a5", X"73", X"a4", X"74", X"85", X"6f", + X"84", X"70", X"a5", X"69", X"85", X"96", X"65", X"0f", + X"85", X"94", X"a4", X"6a", X"84", X"97", X"90", X"01", + X"c8", X"84", X"95", X"20", X"93", X"d3", X"a5", X"50", + X"a4", X"51", X"8d", X"fe", X"01", X"8c", X"ff", X"01", + X"a5", X"6d", X"a4", X"6e", X"85", X"69", X"84", X"6a", + X"a4", X"0f", X"b9", X"fb", X"01", X"88", X"91", X"9b", + X"d0", X"f8", X"20", X"65", X"d6", X"a5", X"67", X"a4", + X"68", X"85", X"5e", X"84", X"5f", X"18", X"a0", X"01", + X"b1", X"5e", X"d0", X"0b", X"a5", X"69", X"85", X"af", + X"a5", X"6a", X"85", X"b0", X"4c", X"3c", X"d4", X"a0", + X"04", X"c8", X"b1", X"5e", X"d0", X"fb", X"c8", X"98", + X"65", X"5e", X"aa", X"a0", X"00", X"91", X"5e", X"a5", + X"5f", X"69", X"00", X"c8", X"91", X"5e", X"86", X"5e", + X"85", X"5f", X"90", X"d2", X"a2", X"80", X"86", X"33", + X"20", X"6a", X"fd", X"e0", X"ef", X"90", X"02", X"a2", + X"ef", X"a9", X"00", X"9d", X"00", X"02", X"8a", X"f0", + X"0b", X"bd", X"ff", X"01", X"29", X"7f", X"9d", X"ff", + X"01", X"ca", X"d0", X"f5", X"a9", X"00", X"a2", X"ff", + X"a0", X"01", X"60", X"20", X"0c", X"fd", X"29", X"7f", + X"60", X"a6", X"b8", X"ca", X"a0", X"04", X"84", X"13", + X"24", X"d6", X"10", X"08", X"68", X"68", X"20", X"65", + X"d6", X"4c", X"d2", X"d7", X"e8", X"bd", X"00", X"02", + X"24", X"13", X"70", X"04", X"c9", X"20", X"f0", X"f4", + X"85", X"0e", X"c9", X"22", X"f0", X"74", X"70", X"4d", + X"c9", X"3f", X"d0", X"04", X"a9", X"ba", X"d0", X"45", + X"c9", X"30", X"90", X"04", X"c9", X"3c", X"90", X"3d", + X"84", X"ad", X"a9", X"d0", X"85", X"9d", X"a9", X"cf", + X"85", X"9e", X"a0", X"00", X"84", X"0f", X"88", X"86", + X"b8", X"ca", X"c8", X"d0", X"02", X"e6", X"9e", X"e8", + X"bd", X"00", X"02", X"c9", X"20", X"f0", X"f8", X"38", + X"f1", X"9d", X"f0", X"ee", X"c9", X"80", X"d0", X"41", + X"05", X"0f", X"c9", X"c5", X"d0", X"0d", X"bd", X"01", + X"02", X"c9", X"4e", X"f0", X"34", X"c9", X"4f", X"f0", + X"30", X"a9", X"c5", X"a4", X"ad", X"e8", X"c8", X"99", + X"fb", X"01", X"b9", X"fb", X"01", X"f0", X"39", X"38", + X"e9", X"3a", X"f0", X"04", X"c9", X"49", X"d0", X"02", + X"85", X"13", X"38", X"e9", X"78", X"d0", X"86", X"85", + X"0e", X"bd", X"00", X"02", X"f0", X"df", X"c5", X"0e", + X"f0", X"db", X"c8", X"99", X"fb", X"01", X"e8", X"d0", + X"f0", X"a6", X"b8", X"e6", X"0f", X"b1", X"9d", X"c8", + X"d0", X"02", X"e6", X"9e", X"0a", X"90", X"f6", X"b1", + X"9d", X"d0", X"9d", X"bd", X"00", X"02", X"10", X"bb", + X"99", X"fd", X"01", X"c6", X"b9", X"a9", X"ff", X"85", + X"b8", X"60", X"a5", X"67", X"a6", X"68", X"a0", X"01", + X"85", X"9b", X"86", X"9c", X"b1", X"9b", X"f0", X"1f", + X"c8", X"c8", X"a5", X"51", X"d1", X"9b", X"90", X"18", + X"f0", X"03", X"88", X"d0", X"09", X"a5", X"50", X"88", + X"d1", X"9b", X"90", X"0c", X"f0", X"0a", X"88", X"b1", + X"9b", X"aa", X"88", X"b1", X"9b", X"b0", X"d7", X"18", + X"60", X"d0", X"fd", X"a9", X"00", X"85", X"d6", X"a8", + X"91", X"67", X"c8", X"91", X"67", X"a5", X"67", X"69", + X"02", X"85", X"69", X"85", X"af", X"a5", X"68", X"69", + X"00", X"85", X"6a", X"85", X"b0", X"20", X"97", X"d6", + X"a9", X"00", X"d0", X"2a", X"a5", X"73", X"a4", X"74", + X"85", X"6f", X"84", X"70", X"a5", X"69", X"a4", X"6a", + X"85", X"6b", X"84", X"6c", X"85", X"6d", X"84", X"6e", + X"20", X"49", X"d8", X"a2", X"55", X"86", X"52", X"68", + X"a8", X"68", X"a2", X"f8", X"9a", X"48", X"98", X"48", + X"a9", X"00", X"85", X"7a", X"85", X"14", X"60", X"18", + X"a5", X"67", X"69", X"ff", X"85", X"b8", X"a5", X"68", + X"69", X"ff", X"85", X"b9", X"60", X"90", X"0a", X"f0", + X"08", X"c9", X"c9", X"f0", X"04", X"c9", X"2c", X"d0", + X"e5", X"20", X"0c", X"da", X"20", X"1a", X"d6", X"20", + X"b7", X"00", X"f0", X"10", X"c9", X"c9", X"f0", X"04", + X"c9", X"2c", X"d0", X"84", X"20", X"b1", X"00", X"20", + X"0c", X"da", X"d0", X"ca", X"68", X"68", X"a5", X"50", + X"05", X"51", X"d0", X"06", X"a9", X"ff", X"85", X"50", + X"85", X"51", X"a0", X"01", X"b1", X"9b", X"f0", X"44", + X"20", X"58", X"d8", X"20", X"fb", X"da", X"c8", X"b1", + X"9b", X"aa", X"c8", X"b1", X"9b", X"c5", X"51", X"d0", + X"04", X"e4", X"50", X"f0", X"02", X"b0", X"2d", X"84", + X"85", X"20", X"24", X"ed", X"a9", X"20", X"a4", X"85", + X"29", X"7f", X"20", X"5c", X"db", X"a5", X"24", X"c9", + X"21", X"90", X"07", X"20", X"fb", X"da", X"a9", X"05", + X"85", X"24", X"c8", X"b1", X"9b", X"d0", X"1d", X"a8", + X"b1", X"9b", X"aa", X"c8", X"b1", X"9b", X"86", X"9b", + X"85", X"9c", X"d0", X"b6", X"a9", X"0d", X"20", X"5c", + X"db", X"4c", X"d2", X"d7", X"c8", X"d0", X"02", X"e6", + X"9e", X"b1", X"9d", X"60", X"10", X"cc", X"38", X"e9", + X"7f", X"aa", X"84", X"85", X"a0", X"d0", X"84", X"9d", + X"a0", X"cf", X"84", X"9e", X"a0", X"ff", X"ca", X"f0", + X"07", X"20", X"2c", X"d7", X"10", X"fb", X"30", X"f6", + X"a9", X"20", X"20", X"5c", X"db", X"20", X"2c", X"d7", + X"30", X"05", X"20", X"5c", X"db", X"d0", X"f6", X"20", + X"5c", X"db", X"a9", X"20", X"d0", X"98", X"a9", X"80", + X"85", X"14", X"20", X"46", X"da", X"20", X"65", X"d3", + X"d0", X"05", X"8a", X"69", X"0f", X"aa", X"9a", X"68", + X"68", X"a9", X"09", X"20", X"d6", X"d3", X"20", X"a3", + X"d9", X"18", X"98", X"65", X"b8", X"48", X"a5", X"b9", + X"69", X"00", X"48", X"a5", X"76", X"48", X"a5", X"75", + X"48", X"a9", X"c1", X"20", X"c0", X"de", X"20", X"6a", + X"dd", X"20", X"67", X"dd", X"a5", X"a2", X"09", X"7f", + X"25", X"9e", X"85", X"9e", X"a9", X"af", X"a0", X"d7", + X"85", X"5e", X"84", X"5f", X"4c", X"20", X"de", X"a9", + X"13", X"a0", X"e9", X"20", X"f9", X"ea", X"20", X"b7", + X"00", X"c9", X"c7", X"d0", X"06", X"20", X"b1", X"00", + X"20", X"67", X"dd", X"20", X"82", X"eb", X"20", X"15", + X"de", X"a5", X"86", X"48", X"a5", X"85", X"48", X"a9", + X"81", X"48", X"ba", X"86", X"f8", X"20", X"58", X"d8", + X"a5", X"b8", X"a4", X"b9", X"a6", X"76", X"e8", X"f0", + X"04", X"85", X"79", X"84", X"7a", X"a0", X"00", X"b1", + X"b8", X"d0", X"57", X"a0", X"02", X"b1", X"b8", X"18", + X"f0", X"34", X"c8", X"b1", X"b8", X"85", X"75", X"c8", + X"b1", X"b8", X"85", X"76", X"98", X"65", X"b8", X"85", + X"b8", X"90", X"02", X"e6", X"b9", X"24", X"f2", X"10", + X"14", X"a6", X"76", X"e8", X"f0", X"0f", X"a9", X"23", + X"20", X"5c", X"db", X"a6", X"75", X"a5", X"76", X"20", + X"24", X"ed", X"20", X"57", X"db", X"20", X"b1", X"00", + X"20", X"28", X"d8", X"4c", X"d2", X"d7", X"f0", X"62", + X"f0", X"2d", X"e9", X"80", X"90", X"11", X"c9", X"40", + X"b0", X"14", X"0a", X"a8", X"b9", X"01", X"d0", X"48", + X"b9", X"00", X"d0", X"48", X"4c", X"b1", X"00", X"4c", + X"46", X"da", X"c9", X"3a", X"f0", X"bf", X"4c", X"c9", + X"de", X"38", X"a5", X"67", X"e9", X"01", X"a4", X"68", + X"b0", X"01", X"88", X"85", X"7d", X"84", X"7e", X"60", + X"ad", X"00", X"c0", X"c9", X"83", X"f0", X"01", X"60", + X"20", X"53", X"d5", X"a2", X"ff", X"24", X"d8", X"10", + X"03", X"4c", X"e9", X"f2", X"c9", X"03", X"b0", X"01", + X"18", X"d0", X"3c", X"a5", X"b8", X"a4", X"b9", X"a6", + X"76", X"e8", X"f0", X"0c", X"85", X"79", X"84", X"7a", + X"a5", X"75", X"a4", X"76", X"85", X"77", X"84", X"78", + X"68", X"68", X"a9", X"5d", X"a0", X"d3", X"90", X"03", + X"4c", X"31", X"d4", X"4c", X"3c", X"d4", X"d0", X"17", + X"a2", X"d2", X"a4", X"7a", X"d0", X"03", X"4c", X"12", + X"d4", X"a5", X"79", X"85", X"b8", X"84", X"b9", X"a5", + X"77", X"a4", X"78", X"85", X"75", X"84", X"76", X"60", + X"38", X"a5", X"af", X"e5", X"67", X"85", X"50", X"a5", + X"b0", X"e5", X"68", X"85", X"51", X"20", X"f0", X"d8", + X"20", X"cd", X"fe", X"20", X"01", X"d9", X"4c", X"cd", + X"fe", X"20", X"f0", X"d8", X"20", X"fd", X"fe", X"18", + X"a5", X"67", X"65", X"50", X"85", X"69", X"a5", X"68", + X"65", X"51", X"85", X"6a", X"a5", X"52", X"85", X"d6", + X"20", X"01", X"d9", X"20", X"fd", X"fe", X"24", X"d6", + X"10", X"03", X"4c", X"65", X"d6", X"4c", X"f2", X"d4", + X"a9", X"50", X"a0", X"00", X"85", X"3c", X"84", X"3d", + X"a9", X"52", X"85", X"3e", X"84", X"3f", X"84", X"d6", + X"60", X"a5", X"67", X"a4", X"68", X"85", X"3c", X"84", + X"3d", X"a5", X"69", X"a4", X"6a", X"85", X"3e", X"84", + X"3f", X"60", X"08", X"c6", X"76", X"28", X"d0", X"03", + X"4c", X"65", X"d6", X"20", X"6c", X"d6", X"4c", X"35", + X"d9", X"a9", X"03", X"20", X"d6", X"d3", X"a5", X"b9", + X"48", X"a5", X"b8", X"48", X"a5", X"76", X"48", X"a5", + X"75", X"48", X"a9", X"b0", X"48", X"20", X"b7", X"00", + X"20", X"3e", X"d9", X"4c", X"d2", X"d7", X"20", X"0c", + X"da", X"20", X"a6", X"d9", X"a5", X"76", X"c5", X"51", + X"b0", X"0b", X"98", X"38", X"65", X"b8", X"a6", X"b9", + X"90", X"07", X"e8", X"b0", X"04", X"a5", X"67", X"a6", + X"68", X"20", X"1e", X"d6", X"90", X"1e", X"a5", X"9b", + X"e9", X"01", X"85", X"b8", X"a5", X"9c", X"e9", X"00", + X"85", X"b9", X"60", X"d0", X"fd", X"a9", X"ff", X"85", + X"85", X"20", X"65", X"d3", X"9a", X"c9", X"b0", X"f0", + X"0b", X"a2", X"16", X"2c", X"a2", X"5a", X"4c", X"12", + X"d4", X"4c", X"c9", X"de", X"68", X"68", X"c0", X"42", + X"f0", X"3b", X"85", X"75", X"68", X"85", X"76", X"68", + X"85", X"b8", X"68", X"85", X"b9", X"20", X"a3", X"d9", + X"98", X"18", X"65", X"b8", X"85", X"b8", X"90", X"02", + X"e6", X"b9", X"60", X"a2", X"3a", X"2c", X"a2", X"00", + X"86", X"0d", X"a0", X"00", X"84", X"0e", X"a5", X"0e", + X"a6", X"0d", X"85", X"0d", X"86", X"0e", X"b1", X"b8", + X"f0", X"e8", X"c5", X"0e", X"f0", X"e4", X"c8", X"c9", + X"22", X"d0", X"f3", X"f0", X"e9", X"68", X"68", X"68", + X"60", X"20", X"7b", X"dd", X"20", X"b7", X"00", X"c9", + X"ab", X"f0", X"05", X"a9", X"c4", X"20", X"c0", X"de", + X"a5", X"9d", X"d0", X"05", X"20", X"a6", X"d9", X"f0", + X"b7", X"20", X"b7", X"00", X"b0", X"03", X"4c", X"3e", + X"d9", X"4c", X"28", X"d8", X"20", X"f8", X"e6", X"48", + X"c9", X"b0", X"f0", X"04", X"c9", X"ab", X"d0", X"89", + X"c6", X"a1", X"d0", X"04", X"68", X"4c", X"2a", X"d8", + X"20", X"b1", X"00", X"20", X"0c", X"da", X"c9", X"2c", + X"f0", X"ee", X"68", X"60", X"a2", X"00", X"86", X"50", + X"86", X"51", X"b0", X"f7", X"e9", X"2f", X"85", X"0d", + X"a5", X"51", X"85", X"5e", X"c9", X"19", X"b0", X"d4", + X"a5", X"50", X"0a", X"26", X"5e", X"0a", X"26", X"5e", + X"65", X"50", X"85", X"50", X"a5", X"5e", X"65", X"51", + X"85", X"51", X"06", X"50", X"26", X"51", X"a5", X"50", + X"65", X"0d", X"85", X"50", X"90", X"02", X"e6", X"51", + X"20", X"b1", X"00", X"4c", X"12", X"da", X"20", X"e3", + X"df", X"85", X"85", X"84", X"86", X"a9", X"d0", X"20", + X"c0", X"de", X"a5", X"12", X"48", X"a5", X"11", X"48", + X"20", X"7b", X"dd", X"68", X"2a", X"20", X"6d", X"dd", + X"d0", X"18", X"68", X"10", X"12", X"20", X"72", X"eb", + X"20", X"0c", X"e1", X"a0", X"00", X"a5", X"a0", X"91", + X"85", X"c8", X"a5", X"a1", X"91", X"85", X"60", X"4c", + X"27", X"eb", X"68", X"a0", X"02", X"b1", X"a0", X"c5", + X"70", X"90", X"17", X"d0", X"07", X"88", X"b1", X"a0", + X"c5", X"6f", X"90", X"0e", X"a4", X"a1", X"c4", X"6a", + X"90", X"08", X"d0", X"0d", X"a5", X"a0", X"c5", X"69", + X"b0", X"07", X"a5", X"a0", X"a4", X"a1", X"4c", X"b7", + X"da", X"a0", X"00", X"b1", X"a0", X"20", X"d5", X"e3", + X"a5", X"8c", X"a4", X"8d", X"85", X"ab", X"84", X"ac", + X"20", X"d4", X"e5", X"a9", X"9d", X"a0", X"00", X"85", + X"8c", X"84", X"8d", X"20", X"35", X"e6", X"a0", X"00", + X"b1", X"8c", X"91", X"85", X"c8", X"b1", X"8c", X"91", + X"85", X"c8", X"b1", X"8c", X"91", X"85", X"60", X"20", + X"3d", X"db", X"20", X"b7", X"00", X"f0", X"24", X"f0", + X"29", X"c9", X"c0", X"f0", X"39", X"c9", X"c3", X"18", + X"f0", X"34", X"c9", X"2c", X"18", X"f0", X"1c", X"c9", + X"3b", X"f0", X"44", X"20", X"7b", X"dd", X"24", X"11", + X"30", X"dd", X"20", X"34", X"ed", X"20", X"e7", X"e3", + X"4c", X"cf", X"da", X"a9", X"0d", X"20", X"5c", X"db", + X"49", X"ff", X"60", X"a5", X"24", X"c9", X"18", X"90", + X"05", X"20", X"fb", X"da", X"d0", X"21", X"69", X"10", + X"29", X"f0", X"85", X"24", X"90", X"19", X"08", X"20", + X"f5", X"e6", X"c9", X"29", X"f0", X"03", X"4c", X"c9", + X"de", X"28", X"90", X"07", X"ca", X"8a", X"e5", X"24", + X"90", X"05", X"aa", X"e8", X"ca", X"d0", X"06", X"20", + X"b1", X"00", X"4c", X"d7", X"da", X"20", X"57", X"db", + X"d0", X"f2", X"20", X"e7", X"e3", X"20", X"00", X"e6", + X"aa", X"a0", X"00", X"e8", X"ca", X"f0", X"bb", X"b1", + X"5e", X"20", X"5c", X"db", X"c8", X"c9", X"0d", X"d0", + X"f3", X"20", X"00", X"db", X"4c", X"44", X"db", X"a9", + X"20", X"2c", X"a9", X"3f", X"09", X"80", X"c9", X"a0", + X"90", X"02", X"05", X"f3", X"20", X"ed", X"fd", X"29", + X"7f", X"48", X"a5", X"f1", X"20", X"a8", X"fc", X"68", + X"60", X"a5", X"15", X"f0", X"12", X"30", X"04", X"a0", + X"ff", X"d0", X"04", X"a5", X"7b", X"a4", X"7c", X"85", + X"75", X"84", X"76", X"4c", X"c9", X"de", X"68", X"24", + X"d8", X"10", X"05", X"a2", X"fe", X"4c", X"e9", X"f2", + X"a9", X"ef", X"a0", X"dc", X"20", X"3a", X"db", X"a5", + X"79", X"a4", X"7a", X"85", X"b8", X"84", X"b9", X"60", + X"20", X"06", X"e3", X"a2", X"01", X"a0", X"02", X"a9", + X"00", X"8d", X"01", X"02", X"a9", X"40", X"20", X"eb", + X"db", X"60", X"c9", X"22", X"d0", X"0e", X"20", X"81", + X"de", X"a9", X"3b", X"20", X"c0", X"de", X"20", X"3d", + X"db", X"4c", X"c7", X"db", X"20", X"5a", X"db", X"20", + X"06", X"e3", X"a9", X"2c", X"8d", X"ff", X"01", X"20", + X"2c", X"d5", X"ad", X"00", X"02", X"c9", X"03", X"d0", + X"10", X"4c", X"63", X"d8", X"20", X"5a", X"db", X"4c", + X"2c", X"d5", X"a6", X"7d", X"a4", X"7e", X"a9", X"98", + X"2c", X"a9", X"00", X"85", X"15", X"86", X"7f", X"84", + X"80", X"20", X"e3", X"df", X"85", X"85", X"84", X"86", + X"a5", X"b8", X"a4", X"b9", X"85", X"87", X"84", X"88", + X"a6", X"7f", X"a4", X"80", X"86", X"b8", X"84", X"b9", + X"20", X"b7", X"00", X"d0", X"1e", X"24", X"15", X"50", + X"0e", X"20", X"0c", X"fd", X"29", X"7f", X"8d", X"00", + X"02", X"a2", X"ff", X"a0", X"01", X"d0", X"08", X"30", + X"7f", X"20", X"5a", X"db", X"20", X"dc", X"db", X"86", + X"b8", X"84", X"b9", X"20", X"b1", X"00", X"24", X"11", + X"10", X"31", X"24", X"15", X"50", X"09", X"e8", X"86", + X"b8", X"a9", X"00", X"85", X"0d", X"f0", X"0c", X"85", + X"0d", X"c9", X"22", X"f0", X"07", X"a9", X"3a", X"85", + X"0d", X"a9", X"2c", X"18", X"85", X"0e", X"a5", X"b8", + X"a4", X"b9", X"69", X"00", X"90", X"01", X"c8", X"20", + X"ed", X"e3", X"20", X"3d", X"e7", X"20", X"7b", X"da", + X"4c", X"72", X"dc", X"48", X"ad", X"00", X"02", X"f0", + X"30", X"68", X"20", X"4a", X"ec", X"a5", X"12", X"20", + X"63", X"da", X"20", X"b7", X"00", X"f0", X"07", X"c9", + X"2c", X"f0", X"03", X"4c", X"71", X"db", X"a5", X"b8", + X"a4", X"b9", X"85", X"7f", X"84", X"80", X"a5", X"87", + X"a4", X"88", X"85", X"b8", X"84", X"b9", X"20", X"b7", + X"00", X"f0", X"33", X"20", X"be", X"de", X"4c", X"f1", + X"db", X"a5", X"15", X"d0", X"cc", X"4c", X"86", X"db", + X"20", X"a3", X"d9", X"c8", X"aa", X"d0", X"12", X"a2", + X"2a", X"c8", X"b1", X"b8", X"f0", X"5f", X"c8", X"b1", + X"b8", X"85", X"7b", X"c8", X"b1", X"b8", X"c8", X"85", + X"7c", X"b1", X"b8", X"aa", X"20", X"98", X"d9", X"e0", + X"83", X"d0", X"dd", X"4c", X"2b", X"dc", X"a5", X"7f", + X"a4", X"80", X"a6", X"15", X"10", X"03", X"4c", X"53", + X"d8", X"a0", X"00", X"b1", X"7f", X"f0", X"07", X"a9", + X"df", X"a0", X"dc", X"4c", X"3a", X"db", X"60", X"3f", + X"45", X"58", X"54", X"52", X"41", X"20", X"49", X"47", + X"4e", X"4f", X"52", X"45", X"44", X"0d", X"00", X"3f", + X"52", X"45", X"45", X"4e", X"54", X"45", X"52", X"0d", + X"00", X"d0", X"04", X"a0", X"00", X"f0", X"03", X"20", + X"e3", X"df", X"85", X"85", X"84", X"86", X"20", X"65", + X"d3", X"f0", X"04", X"a2", X"00", X"f0", X"69", X"9a", + X"e8", X"e8", X"e8", X"e8", X"8a", X"e8", X"e8", X"e8", + X"e8", X"e8", X"e8", X"86", X"60", X"a0", X"01", X"20", + X"f9", X"ea", X"ba", X"bd", X"09", X"01", X"85", X"a2", + X"a5", X"85", X"a4", X"86", X"20", X"be", X"e7", X"20", + X"27", X"eb", X"a0", X"01", X"20", X"b4", X"eb", X"ba", + X"38", X"fd", X"09", X"01", X"f0", X"17", X"bd", X"0f", + X"01", X"85", X"75", X"bd", X"10", X"01", X"85", X"76", + X"bd", X"12", X"01", X"85", X"b8", X"bd", X"11", X"01", + X"85", X"b9", X"4c", X"d2", X"d7", X"8a", X"69", X"11", + X"aa", X"9a", X"20", X"b7", X"00", X"c9", X"2c", X"d0", + X"f1", X"20", X"b1", X"00", X"20", X"ff", X"dc", X"20", + X"7b", X"dd", X"18", X"24", X"38", X"24", X"11", X"30", + X"03", X"b0", X"03", X"60", X"b0", X"fd", X"a2", X"a3", + X"4c", X"12", X"d4", X"a6", X"b8", X"d0", X"02", X"c6", + X"b9", X"c6", X"b8", X"a2", X"00", X"24", X"48", X"8a", + X"48", X"a9", X"01", X"20", X"d6", X"d3", X"20", X"60", + X"de", X"a9", X"00", X"85", X"89", X"20", X"b7", X"00", + X"38", X"e9", X"cf", X"90", X"17", X"c9", X"03", X"b0", + X"13", X"c9", X"01", X"2a", X"49", X"01", X"45", X"89", + X"c5", X"89", X"90", X"61", X"85", X"89", X"20", X"b1", + X"00", X"4c", X"98", X"dd", X"a6", X"89", X"d0", X"2c", + X"b0", X"7b", X"69", X"07", X"90", X"77", X"65", X"11", + X"d0", X"03", X"4c", X"97", X"e5", X"69", X"ff", X"85", + X"5e", X"0a", X"65", X"5e", X"a8", X"68", X"d9", X"b2", + X"d0", X"b0", X"67", X"20", X"6a", X"dd", X"48", X"20", + X"fd", X"dd", X"68", X"a4", X"87", X"10", X"17", X"aa", + X"f0", X"56", X"d0", X"5f", X"46", X"11", X"8a", X"2a", + X"a6", X"b8", X"d0", X"02", X"c6", X"b9", X"c6", X"b8", + X"a0", X"1b", X"85", X"89", X"d0", X"d7", X"d9", X"b2", + X"d0", X"b0", X"48", X"90", X"d9", X"b9", X"b4", X"d0", + X"48", X"b9", X"b3", X"d0", X"48", X"20", X"10", X"de", + X"a5", X"89", X"4c", X"86", X"dd", X"4c", X"c9", X"de", + X"a5", X"a2", X"be", X"b2", X"d0", X"a8", X"68", X"85", + X"5e", X"e6", X"5e", X"68", X"85", X"5f", X"98", X"48", + X"20", X"72", X"eb", X"a5", X"a1", X"48", X"a5", X"a0", + X"48", X"a5", X"9f", X"48", X"a5", X"9e", X"48", X"a5", + X"9d", X"48", X"6c", X"5e", X"00", X"a0", X"ff", X"68", + X"f0", X"23", X"c9", X"64", X"f0", X"03", X"20", X"6a", + X"dd", X"84", X"87", X"68", X"4a", X"85", X"16", X"68", + X"85", X"a5", X"68", X"85", X"a6", X"68", X"85", X"a7", + X"68", X"85", X"a8", X"68", X"85", X"a9", X"68", X"85", + X"aa", X"45", X"a2", X"85", X"ab", X"a5", X"9d", X"60", + X"a9", X"00", X"85", X"11", X"20", X"b1", X"00", X"b0", + X"03", X"4c", X"4a", X"ec", X"20", X"7d", X"e0", X"b0", + X"64", X"c9", X"2e", X"f0", X"f4", X"c9", X"c9", X"f0", + X"55", X"c9", X"c8", X"f0", X"e7", X"c9", X"22", X"d0", + X"0f", X"a5", X"b8", X"a4", X"b9", X"69", X"00", X"90", + X"01", X"c8", X"20", X"e7", X"e3", X"4c", X"3d", X"e7", + X"c9", X"c6", X"d0", X"10", X"a0", X"18", X"d0", X"38", + X"a5", X"9d", X"d0", X"03", X"a0", X"01", X"2c", X"a0", + X"00", X"4c", X"01", X"e3", X"c9", X"c2", X"d0", X"03", + X"4c", X"54", X"e3", X"c9", X"d2", X"90", X"03", X"4c", + X"0c", X"df", X"20", X"bb", X"de", X"20", X"7b", X"dd", + X"a9", X"29", X"2c", X"a9", X"28", X"2c", X"a9", X"2c", + X"a0", X"00", X"d1", X"b8", X"d0", X"03", X"4c", X"b1", + X"00", X"a2", X"10", X"4c", X"12", X"d4", X"a0", X"15", + X"68", X"68", X"4c", X"d7", X"dd", X"20", X"e3", X"df", + X"85", X"a0", X"84", X"a1", X"a6", X"11", X"f0", X"05", + X"a2", X"00", X"86", X"ac", X"60", X"a6", X"12", X"10", + X"0d", X"a0", X"00", X"b1", X"a0", X"aa", X"c8", X"b1", + X"a0", X"a8", X"8a", X"4c", X"f2", X"e2", X"4c", X"f9", + X"ea", X"20", X"b1", X"00", X"20", X"ec", X"f1", X"8a", + X"a4", X"f0", X"20", X"71", X"f8", X"a8", X"20", X"01", + X"e3", X"4c", X"b8", X"de", X"c9", X"d7", X"f0", X"e9", + X"0a", X"48", X"aa", X"20", X"b1", X"00", X"e0", X"cf", + X"90", X"20", X"20", X"bb", X"de", X"20", X"7b", X"dd", + X"20", X"be", X"de", X"20", X"6c", X"dd", X"68", X"aa", + X"a5", X"a1", X"48", X"a5", X"a0", X"48", X"8a", X"48", + X"20", X"f8", X"e6", X"68", X"a8", X"8a", X"48", X"4c", + X"3f", X"df", X"20", X"b2", X"de", X"68", X"a8", X"b9", + X"dc", X"cf", X"85", X"91", X"b9", X"dd", X"cf", X"85", + X"92", X"20", X"90", X"00", X"4c", X"6a", X"dd", X"a5", + X"a5", X"05", X"9d", X"d0", X"0b", X"a5", X"a5", X"f0", + X"04", X"a5", X"9d", X"d0", X"03", X"a0", X"00", X"2c", + X"a0", X"01", X"4c", X"01", X"e3", X"20", X"6d", X"dd", + X"b0", X"13", X"a5", X"aa", X"09", X"7f", X"25", X"a6", + X"85", X"a6", X"a9", X"a5", X"a0", X"00", X"20", X"b2", + X"eb", X"aa", X"4c", X"b0", X"df", X"a9", X"00", X"85", + X"11", X"c6", X"89", X"20", X"00", X"e6", X"85", X"9d", + X"86", X"9e", X"84", X"9f", X"a5", X"a8", X"a4", X"a9", + X"20", X"04", X"e6", X"86", X"a8", X"84", X"a9", X"aa", + X"38", X"e5", X"9d", X"f0", X"08", X"a9", X"01", X"90", + X"04", X"a6", X"9d", X"a9", X"ff", X"85", X"a2", X"a0", + X"ff", X"e8", X"c8", X"ca", X"d0", X"07", X"a6", X"a2", + X"30", X"0f", X"18", X"90", X"0c", X"b1", X"a8", X"d1", + X"9e", X"f0", X"ef", X"a2", X"ff", X"b0", X"02", X"a2", + X"01", X"e8", X"8a", X"2a", X"25", X"16", X"f0", X"02", + X"a9", X"01", X"4c", X"93", X"eb", X"20", X"fb", X"e6", + X"20", X"1e", X"fb", X"4c", X"01", X"e3", X"20", X"be", + X"de", X"aa", X"20", X"e8", X"df", X"20", X"b7", X"00", + X"d0", X"f4", X"60", X"a2", X"00", X"20", X"b7", X"00", + X"86", X"10", X"85", X"81", X"20", X"b7", X"00", X"20", + X"7d", X"e0", X"b0", X"03", X"4c", X"c9", X"de", X"a2", + X"00", X"86", X"11", X"86", X"12", X"4c", X"07", X"e0", + X"4c", X"28", X"f1", X"4c", X"3c", X"d4", X"00", X"20", + X"b1", X"00", X"90", X"05", X"20", X"7d", X"e0", X"90", + X"0b", X"aa", X"20", X"b1", X"00", X"90", X"fb", X"20", + X"7d", X"e0", X"b0", X"f6", X"c9", X"24", X"d0", X"06", + X"a9", X"ff", X"85", X"11", X"d0", X"10", X"c9", X"25", + X"d0", X"13", X"a5", X"14", X"30", X"c6", X"a9", X"80", + X"85", X"12", X"05", X"81", X"85", X"81", X"8a", X"09", + X"80", X"aa", X"20", X"b1", X"00", X"86", X"82", X"38", + X"05", X"14", X"e9", X"28", X"d0", X"03", X"4c", X"1e", + X"e1", X"24", X"14", X"30", X"02", X"70", X"f7", X"a9", + X"00", X"85", X"14", X"a5", X"69", X"a6", X"6a", X"a0", + X"00", X"86", X"9c", X"85", X"9b", X"e4", X"6c", X"d0", + X"04", X"c5", X"6b", X"f0", X"22", X"a5", X"81", X"d1", + X"9b", X"d0", X"08", X"a5", X"82", X"c8", X"d1", X"9b", + X"f0", X"6c", X"88", X"18", X"a5", X"9b", X"69", X"07", + X"90", X"e1", X"e8", X"d0", X"dc", X"c9", X"41", X"90", + X"05", X"e9", X"5b", X"38", X"e9", X"a5", X"60", X"68", + X"48", X"c9", X"d7", X"d0", X"0f", X"ba", X"bd", X"02", + X"01", X"c9", X"de", X"d0", X"07", X"a9", X"9a", X"a0", + X"e0", X"60", X"00", X"00", X"a5", X"6b", X"a4", X"6c", + X"85", X"9b", X"84", X"9c", X"a5", X"6d", X"a4", X"6e", + X"85", X"96", X"84", X"97", X"18", X"69", X"07", X"90", + X"01", X"c8", X"85", X"94", X"84", X"95", X"20", X"93", + X"d3", X"a5", X"94", X"a4", X"95", X"c8", X"85", X"6b", + X"84", X"6c", X"a0", X"00", X"a5", X"81", X"91", X"9b", + X"c8", X"a5", X"82", X"91", X"9b", X"a9", X"00", X"c8", + X"91", X"9b", X"c8", X"91", X"9b", X"c8", X"91", X"9b", + X"c8", X"91", X"9b", X"c8", X"91", X"9b", X"a5", X"9b", + X"18", X"69", X"02", X"a4", X"9c", X"90", X"01", X"c8", + X"85", X"83", X"84", X"84", X"60", X"a5", X"0f", X"0a", + X"69", X"05", X"65", X"9b", X"a4", X"9c", X"90", X"01", + X"c8", X"85", X"94", X"84", X"95", X"60", X"90", X"80", + X"00", X"00", X"20", X"b1", X"00", X"20", X"67", X"dd", + X"a5", X"a2", X"30", X"0d", X"a5", X"9d", X"c9", X"90", + X"90", X"09", X"a9", X"fe", X"a0", X"e0", X"20", X"b2", + X"eb", X"d0", X"7e", X"4c", X"f2", X"eb", X"a5", X"14", + X"d0", X"47", X"a5", X"10", X"05", X"12", X"48", X"a5", + X"11", X"48", X"a0", X"00", X"98", X"48", X"a5", X"82", + X"48", X"a5", X"81", X"48", X"20", X"02", X"e1", X"68", + X"85", X"81", X"68", X"85", X"82", X"68", X"a8", X"ba", + X"bd", X"02", X"01", X"48", X"bd", X"01", X"01", X"48", + X"a5", X"a0", X"9d", X"02", X"01", X"a5", X"a1", X"9d", + X"01", X"01", X"c8", X"20", X"b7", X"00", X"c9", X"2c", + X"f0", X"d2", X"84", X"0f", X"20", X"b8", X"de", X"68", + X"85", X"11", X"68", X"85", X"12", X"29", X"7f", X"85", + X"10", X"a6", X"6b", X"a5", X"6c", X"86", X"9b", X"85", + X"9c", X"c5", X"6e", X"d0", X"04", X"e4", X"6d", X"f0", + X"3f", X"a0", X"00", X"b1", X"9b", X"c8", X"c5", X"81", + X"d0", X"06", X"a5", X"82", X"d1", X"9b", X"f0", X"16", + X"c8", X"b1", X"9b", X"18", X"65", X"9b", X"aa", X"c8", + X"b1", X"9b", X"65", X"9c", X"90", X"d7", X"a2", X"6b", + X"2c", X"a2", X"35", X"4c", X"12", X"d4", X"a2", X"78", + X"a5", X"10", X"d0", X"f7", X"a5", X"14", X"f0", X"02", + X"38", X"60", X"20", X"ed", X"e0", X"a5", X"0f", X"a0", + X"04", X"d1", X"9b", X"d0", X"e1", X"4c", X"4b", X"e2", + X"a5", X"14", X"f0", X"05", X"a2", X"2a", X"4c", X"12", + X"d4", X"20", X"ed", X"e0", X"20", X"e3", X"d3", X"a9", + X"00", X"a8", X"85", X"ae", X"a2", X"05", X"a5", X"81", + X"91", X"9b", X"10", X"01", X"ca", X"c8", X"a5", X"82", + X"91", X"9b", X"10", X"02", X"ca", X"ca", X"86", X"ad", + X"a5", X"0f", X"c8", X"c8", X"c8", X"91", X"9b", X"a2", + X"0b", X"a9", X"00", X"24", X"10", X"50", X"08", X"68", + X"18", X"69", X"01", X"aa", X"68", X"69", X"00", X"c8", + X"91", X"9b", X"c8", X"8a", X"91", X"9b", X"20", X"ad", + X"e2", X"86", X"ad", X"85", X"ae", X"a4", X"5e", X"c6", + X"0f", X"d0", X"dc", X"65", X"95", X"b0", X"5d", X"85", + X"95", X"a8", X"8a", X"65", X"94", X"90", X"03", X"c8", + X"f0", X"52", X"20", X"e3", X"d3", X"85", X"6d", X"84", + X"6e", X"a9", X"00", X"e6", X"ae", X"a4", X"ad", X"f0", + X"05", X"88", X"91", X"94", X"d0", X"fb", X"c6", X"95", + X"c6", X"ae", X"d0", X"f5", X"e6", X"95", X"38", X"a5", + X"6d", X"e5", X"9b", X"a0", X"02", X"91", X"9b", X"a5", + X"6e", X"c8", X"e5", X"9c", X"91", X"9b", X"a5", X"10", + X"d0", X"62", X"c8", X"b1", X"9b", X"85", X"0f", X"a9", + X"00", X"85", X"ad", X"85", X"ae", X"c8", X"68", X"aa", + X"85", X"a0", X"68", X"85", X"a1", X"d1", X"9b", X"90", + X"0e", X"d0", X"06", X"c8", X"8a", X"d1", X"9b", X"90", + X"07", X"4c", X"96", X"e1", X"4c", X"10", X"d4", X"c8", + X"a5", X"ae", X"05", X"ad", X"18", X"f0", X"0a", X"20", + X"ad", X"e2", X"8a", X"65", X"a0", X"aa", X"98", X"a4", + X"5e", X"65", X"a1", X"86", X"ad", X"c6", X"0f", X"d0", + X"ca", X"85", X"ae", X"a2", X"05", X"a5", X"81", X"10", + X"01", X"ca", X"a5", X"82", X"10", X"02", X"ca", X"ca", + X"86", X"64", X"a9", X"00", X"20", X"b6", X"e2", X"8a", + X"65", X"94", X"85", X"83", X"98", X"65", X"95", X"85", + X"84", X"a8", X"a5", X"83", X"60", X"84", X"5e", X"b1", + X"9b", X"85", X"64", X"88", X"b1", X"9b", X"85", X"65", + X"a9", X"10", X"85", X"99", X"a2", X"00", X"a0", X"00", + X"8a", X"0a", X"aa", X"98", X"2a", X"a8", X"b0", X"a4", + X"06", X"ad", X"26", X"ae", X"90", X"0b", X"18", X"8a", + X"65", X"64", X"aa", X"98", X"65", X"65", X"a8", X"b0", + X"93", X"c6", X"99", X"d0", X"e3", X"60", X"a5", X"11", + X"f0", X"03", X"20", X"00", X"e6", X"20", X"84", X"e4", + X"38", X"a5", X"6f", X"e5", X"6d", X"a8", X"a5", X"70", + X"e5", X"6e", X"a2", X"00", X"86", X"11", X"85", X"9e", + X"84", X"9f", X"a2", X"90", X"4c", X"9b", X"eb", X"a4", + X"24", X"a9", X"00", X"38", X"f0", X"ec", X"a6", X"76", + X"e8", X"d0", X"a1", X"a2", X"95", X"2c", X"a2", X"e0", + X"4c", X"12", X"d4", X"20", X"41", X"e3", X"20", X"06", + X"e3", X"20", X"bb", X"de", X"a9", X"80", X"85", X"14", + X"20", X"e3", X"df", X"20", X"6a", X"dd", X"20", X"b8", + X"de", X"a9", X"d0", X"20", X"c0", X"de", X"48", X"a5", + X"84", X"48", X"a5", X"83", X"48", X"a5", X"b9", X"48", + X"a5", X"b8", X"48", X"20", X"95", X"d9", X"4c", X"af", + X"e3", X"a9", X"c2", X"20", X"c0", X"de", X"09", X"80", + X"85", X"14", X"20", X"ea", X"df", X"85", X"8a", X"84", + X"8b", X"4c", X"6a", X"dd", X"20", X"41", X"e3", X"a5", + X"8b", X"48", X"a5", X"8a", X"48", X"20", X"b2", X"de", + X"20", X"6a", X"dd", X"68", X"85", X"8a", X"68", X"85", + X"8b", X"a0", X"02", X"b1", X"8a", X"85", X"83", X"aa", + X"c8", X"b1", X"8a", X"f0", X"99", X"85", X"84", X"c8", + X"b1", X"83", X"48", X"88", X"10", X"fa", X"a4", X"84", + X"20", X"2b", X"eb", X"a5", X"b9", X"48", X"a5", X"b8", + X"48", X"b1", X"8a", X"85", X"b8", X"c8", X"b1", X"8a", + X"85", X"b9", X"a5", X"84", X"48", X"a5", X"83", X"48", + X"20", X"67", X"dd", X"68", X"85", X"8a", X"68", X"85", + X"8b", X"20", X"b7", X"00", X"f0", X"03", X"4c", X"c9", + X"de", X"68", X"85", X"b8", X"68", X"85", X"b9", X"a0", + X"00", X"68", X"91", X"8a", X"68", X"c8", X"91", X"8a", + X"68", X"c8", X"91", X"8a", X"68", X"c8", X"91", X"8a", + X"68", X"c8", X"91", X"8a", X"60", X"20", X"6a", X"dd", + X"a0", X"00", X"20", X"36", X"ed", X"68", X"68", X"a9", + X"ff", X"a0", X"00", X"f0", X"12", X"a6", X"a0", X"a4", + X"a1", X"86", X"8c", X"84", X"8d", X"20", X"52", X"e4", + X"86", X"9e", X"84", X"9f", X"85", X"9d", X"60", X"a2", + X"22", X"86", X"0d", X"86", X"0e", X"85", X"ab", X"84", + X"ac", X"85", X"9e", X"84", X"9f", X"a0", X"ff", X"c8", + X"b1", X"ab", X"f0", X"0c", X"c5", X"0d", X"f0", X"04", + X"c5", X"0e", X"d0", X"f3", X"c9", X"22", X"f0", X"01", + X"18", X"84", X"9d", X"98", X"65", X"ab", X"85", X"ad", + X"a6", X"ac", X"90", X"01", X"e8", X"86", X"ae", X"a5", + X"ac", X"f0", X"04", X"c9", X"02", X"d0", X"0b", X"98", + X"20", X"d5", X"e3", X"a6", X"ab", X"a4", X"ac", X"20", + X"e2", X"e5", X"a6", X"52", X"e0", X"5e", X"d0", X"05", + X"a2", X"bf", X"4c", X"12", X"d4", X"a5", X"9d", X"95", + X"00", X"a5", X"9e", X"95", X"01", X"a5", X"9f", X"95", + X"02", X"a0", X"00", X"86", X"a0", X"84", X"a1", X"88", + X"84", X"11", X"86", X"53", X"e8", X"e8", X"e8", X"86", + X"52", X"60", X"46", X"13", X"48", X"49", X"ff", X"38", + X"65", X"6f", X"a4", X"70", X"b0", X"01", X"88", X"c4", + X"6e", X"90", X"11", X"d0", X"04", X"c5", X"6d", X"90", + X"0b", X"85", X"6f", X"84", X"70", X"85", X"71", X"84", + X"72", X"aa", X"68", X"60", X"a2", X"4d", X"a5", X"13", + X"30", X"b8", X"20", X"84", X"e4", X"a9", X"80", X"85", + X"13", X"68", X"d0", X"d0", X"a6", X"73", X"a5", X"74", + X"86", X"6f", X"85", X"70", X"a0", X"00", X"84", X"8b", + X"a5", X"6d", X"a6", X"6e", X"85", X"9b", X"86", X"9c", + X"a9", X"55", X"a2", X"00", X"85", X"5e", X"86", X"5f", + X"c5", X"52", X"f0", X"05", X"20", X"23", X"e5", X"f0", + X"f7", X"a9", X"07", X"85", X"8f", X"a5", X"69", X"a6", + X"6a", X"85", X"5e", X"86", X"5f", X"e4", X"6c", X"d0", + X"04", X"c5", X"6b", X"f0", X"05", X"20", X"19", X"e5", + X"f0", X"f3", X"85", X"94", X"86", X"95", X"a9", X"03", + X"85", X"8f", X"a5", X"94", X"a6", X"95", X"e4", X"6e", + X"d0", X"07", X"c5", X"6d", X"d0", X"03", X"4c", X"62", + X"e5", X"85", X"5e", X"86", X"5f", X"a0", X"00", X"b1", + X"5e", X"aa", X"c8", X"b1", X"5e", X"08", X"c8", X"b1", + X"5e", X"65", X"94", X"85", X"94", X"c8", X"b1", X"5e", + X"65", X"95", X"85", X"95", X"28", X"10", X"d3", X"8a", + X"30", X"d0", X"c8", X"b1", X"5e", X"a0", X"00", X"0a", + X"69", X"05", X"65", X"5e", X"85", X"5e", X"90", X"02", + X"e6", X"5f", X"a6", X"5f", X"e4", X"95", X"d0", X"04", + X"c5", X"94", X"f0", X"ba", X"20", X"23", X"e5", X"f0", + X"f3", X"b1", X"5e", X"30", X"35", X"c8", X"b1", X"5e", + X"10", X"30", X"c8", X"b1", X"5e", X"f0", X"2b", X"c8", + X"b1", X"5e", X"aa", X"c8", X"b1", X"5e", X"c5", X"70", + X"90", X"06", X"d0", X"1e", X"e4", X"6f", X"b0", X"1a", + X"c5", X"9c", X"90", X"16", X"d0", X"04", X"e4", X"9b", + X"90", X"10", X"86", X"9b", X"85", X"9c", X"a5", X"5e", + X"a6", X"5f", X"85", X"8a", X"86", X"8b", X"a5", X"8f", + X"85", X"91", X"a5", X"8f", X"18", X"65", X"5e", X"85", + X"5e", X"90", X"02", X"e6", X"5f", X"a6", X"5f", X"a0", + X"00", X"60", X"a6", X"8b", X"f0", X"f7", X"a5", X"91", + X"29", X"04", X"4a", X"a8", X"85", X"91", X"b1", X"8a", + X"65", X"9b", X"85", X"96", X"a5", X"9c", X"69", X"00", + X"85", X"97", X"a5", X"6f", X"a6", X"70", X"85", X"94", + X"86", X"95", X"20", X"9a", X"d3", X"a4", X"91", X"c8", + X"a5", X"94", X"91", X"8a", X"aa", X"e6", X"95", X"a5", + X"95", X"c8", X"91", X"8a", X"4c", X"88", X"e4", X"a5", + X"a1", X"48", X"a5", X"a0", X"48", X"20", X"60", X"de", + X"20", X"6c", X"dd", X"68", X"85", X"ab", X"68", X"85", + X"ac", X"a0", X"00", X"b1", X"ab", X"18", X"71", X"a0", + X"90", X"05", X"a2", X"b0", X"4c", X"12", X"d4", X"20", + X"d5", X"e3", X"20", X"d4", X"e5", X"a5", X"8c", X"a4", + X"8d", X"20", X"04", X"e6", X"20", X"e6", X"e5", X"a5", + X"ab", X"a4", X"ac", X"20", X"04", X"e6", X"20", X"2a", + X"e4", X"4c", X"95", X"dd", X"a0", X"00", X"b1", X"ab", + X"48", X"c8", X"b1", X"ab", X"aa", X"c8", X"b1", X"ab", + X"a8", X"68", X"86", X"5e", X"84", X"5f", X"a8", X"f0", + X"0a", X"48", X"88", X"b1", X"5e", X"91", X"71", X"98", + X"d0", X"f8", X"68", X"18", X"65", X"71", X"85", X"71", + X"90", X"02", X"e6", X"72", X"60", X"20", X"6c", X"dd", + X"a5", X"a0", X"a4", X"a1", X"85", X"5e", X"84", X"5f", + X"20", X"35", X"e6", X"08", X"a0", X"00", X"b1", X"5e", + X"48", X"c8", X"b1", X"5e", X"aa", X"c8", X"b1", X"5e", + X"a8", X"68", X"28", X"d0", X"13", X"c4", X"70", X"d0", + X"0f", X"e4", X"6f", X"d0", X"0b", X"48", X"18", X"65", + X"6f", X"85", X"6f", X"90", X"02", X"e6", X"70", X"68", + X"86", X"5e", X"84", X"5f", X"60", X"c4", X"54", X"d0", + X"0c", X"c5", X"53", X"d0", X"08", X"85", X"52", X"e9", + X"03", X"85", X"53", X"a0", X"00", X"60", X"20", X"fb", + X"e6", X"8a", X"48", X"a9", X"01", X"20", X"dd", X"e3", + X"68", X"a0", X"00", X"91", X"9e", X"68", X"68", X"4c", + X"2a", X"e4", X"20", X"b9", X"e6", X"d1", X"8c", X"98", + X"90", X"04", X"b1", X"8c", X"aa", X"98", X"48", X"8a", + X"48", X"20", X"dd", X"e3", X"a5", X"8c", X"a4", X"8d", + X"20", X"04", X"e6", X"68", X"a8", X"68", X"18", X"65", + X"5e", X"85", X"5e", X"90", X"02", X"e6", X"5f", X"98", + X"20", X"e6", X"e5", X"4c", X"2a", X"e4", X"20", X"b9", + X"e6", X"18", X"f1", X"8c", X"49", X"ff", X"4c", X"60", + X"e6", X"a9", X"ff", X"85", X"a1", X"20", X"b7", X"00", + X"c9", X"29", X"f0", X"06", X"20", X"be", X"de", X"20", + X"f8", X"e6", X"20", X"b9", X"e6", X"ca", X"8a", X"48", + X"18", X"a2", X"00", X"f1", X"8c", X"b0", X"b8", X"49", + X"ff", X"c5", X"a1", X"90", X"b3", X"a5", X"a1", X"b0", + X"af", X"20", X"b8", X"de", X"68", X"a8", X"68", X"85", + X"91", X"68", X"68", X"68", X"aa", X"68", X"85", X"8c", + X"68", X"85", X"8d", X"a5", X"91", X"48", X"98", X"48", + X"a0", X"00", X"8a", X"f0", X"1d", X"60", X"20", X"dc", + X"e6", X"4c", X"01", X"e3", X"20", X"fd", X"e5", X"a2", + X"00", X"86", X"11", X"a8", X"60", X"20", X"dc", X"e6", + X"f0", X"08", X"a0", X"00", X"b1", X"5e", X"a8", X"4c", + X"01", X"e3", X"4c", X"99", X"e1", X"20", X"b1", X"00", + X"20", X"67", X"dd", X"20", X"08", X"e1", X"a6", X"a0", + X"d0", X"f0", X"a6", X"a1", X"4c", X"b7", X"00", X"20", + X"dc", X"e6", X"d0", X"03", X"4c", X"4e", X"e8", X"a6", + X"b8", X"a4", X"b9", X"86", X"ad", X"84", X"ae", X"a6", + X"5e", X"86", X"b8", X"18", X"65", X"5e", X"85", X"60", + X"a6", X"5f", X"86", X"b9", X"90", X"01", X"e8", X"86", + X"61", X"a0", X"00", X"b1", X"60", X"48", X"a9", X"00", + X"91", X"60", X"20", X"b7", X"00", X"20", X"4a", X"ec", + X"68", X"a0", X"00", X"91", X"60", X"a6", X"ad", X"a4", + X"ae", X"86", X"b8", X"84", X"b9", X"60", X"20", X"67", + X"dd", X"20", X"52", X"e7", X"20", X"be", X"de", X"4c", + X"f8", X"e6", X"a5", X"9d", X"c9", X"91", X"b0", X"9a", + X"20", X"f2", X"eb", X"a5", X"a0", X"a4", X"a1", X"84", + X"50", X"85", X"51", X"60", X"a5", X"50", X"48", X"a5", + X"51", X"48", X"20", X"52", X"e7", X"a0", X"00", X"b1", + X"50", X"a8", X"68", X"85", X"51", X"68", X"85", X"50", + X"4c", X"01", X"e3", X"20", X"46", X"e7", X"8a", X"a0", + X"00", X"91", X"50", X"60", X"20", X"46", X"e7", X"86", + X"85", X"a2", X"00", X"20", X"b7", X"00", X"f0", X"03", + X"20", X"4c", X"e7", X"86", X"86", X"a0", X"00", X"b1", + X"50", X"45", X"86", X"25", X"85", X"f0", X"f8", X"60", + X"a9", X"64", X"a0", X"ee", X"4c", X"be", X"e7", X"20", + X"e3", X"e9", X"a5", X"a2", X"49", X"ff", X"85", X"a2", + X"45", X"aa", X"85", X"ab", X"a5", X"9d", X"4c", X"c1", + X"e7", X"20", X"f0", X"e8", X"90", X"3c", X"20", X"e3", + X"e9", X"d0", X"03", X"4c", X"53", X"eb", X"a6", X"ac", + X"86", X"92", X"a2", X"a5", X"a5", X"a5", X"a8", X"f0", + X"ce", X"38", X"e5", X"9d", X"f0", X"24", X"90", X"12", + X"84", X"9d", X"a4", X"aa", X"84", X"a2", X"49", X"ff", + X"69", X"00", X"a0", X"00", X"84", X"92", X"a2", X"9d", + X"d0", X"04", X"a0", X"00", X"84", X"ac", X"c9", X"f9", + X"30", X"c7", X"a8", X"a5", X"ac", X"56", X"01", X"20", + X"07", X"e9", X"24", X"ab", X"10", X"57", X"a0", X"9d", + X"e0", X"a5", X"f0", X"02", X"a0", X"a5", X"38", X"49", + X"ff", X"65", X"92", X"85", X"ac", X"b9", X"04", X"00", + X"f5", X"04", X"85", X"a1", X"b9", X"03", X"00", X"f5", + X"03", X"85", X"a0", X"b9", X"02", X"00", X"f5", X"02", + X"85", X"9f", X"b9", X"01", X"00", X"f5", X"01", X"85", + X"9e", X"b0", X"03", X"20", X"9e", X"e8", X"a0", X"00", + X"98", X"18", X"a6", X"9e", X"d0", X"4a", X"a6", X"9f", + X"86", X"9e", X"a6", X"a0", X"86", X"9f", X"a6", X"a1", + X"86", X"a0", X"a6", X"ac", X"86", X"a1", X"84", X"ac", + X"69", X"08", X"c9", X"20", X"d0", X"e4", X"a9", X"00", + X"85", X"9d", X"85", X"a2", X"60", X"65", X"92", X"85", + X"ac", X"a5", X"a1", X"65", X"a9", X"85", X"a1", X"a5", + X"a0", X"65", X"a8", X"85", X"a0", X"a5", X"9f", X"65", + X"a7", X"85", X"9f", X"a5", X"9e", X"65", X"a6", X"85", + X"9e", X"4c", X"8d", X"e8", X"69", X"01", X"06", X"ac", + X"26", X"a1", X"26", X"a0", X"26", X"9f", X"26", X"9e", + X"10", X"f2", X"38", X"e5", X"9d", X"b0", X"c7", X"49", + X"ff", X"69", X"01", X"85", X"9d", X"90", X"0e", X"e6", + X"9d", X"f0", X"42", X"66", X"9e", X"66", X"9f", X"66", + X"a0", X"66", X"a1", X"66", X"ac", X"60", X"a5", X"a2", + X"49", X"ff", X"85", X"a2", X"a5", X"9e", X"49", X"ff", + X"85", X"9e", X"a5", X"9f", X"49", X"ff", X"85", X"9f", + X"a5", X"a0", X"49", X"ff", X"85", X"a0", X"a5", X"a1", + X"49", X"ff", X"85", X"a1", X"a5", X"ac", X"49", X"ff", + X"85", X"ac", X"e6", X"ac", X"d0", X"0e", X"e6", X"a1", + X"d0", X"0a", X"e6", X"a0", X"d0", X"06", X"e6", X"9f", + X"d0", X"02", X"e6", X"9e", X"60", X"a2", X"45", X"4c", + X"12", X"d4", X"a2", X"61", X"b4", X"04", X"84", X"ac", + X"b4", X"03", X"94", X"04", X"b4", X"02", X"94", X"03", + X"b4", X"01", X"94", X"02", X"a4", X"a4", X"94", X"01", + X"69", X"08", X"30", X"e8", X"f0", X"e6", X"e9", X"08", + X"a8", X"a5", X"ac", X"b0", X"14", X"16", X"01", X"90", + X"02", X"f6", X"01", X"76", X"01", X"76", X"01", X"76", + X"02", X"76", X"03", X"76", X"04", X"6a", X"c8", X"d0", + X"ec", X"18", X"60", X"81", X"00", X"00", X"00", X"00", + X"03", X"7f", X"5e", X"56", X"cb", X"79", X"80", X"13", + X"9b", X"0b", X"64", X"80", X"76", X"38", X"93", X"16", + X"82", X"38", X"aa", X"3b", X"20", X"80", X"35", X"04", + X"f3", X"34", X"81", X"35", X"04", X"f3", X"34", X"80", + X"80", X"00", X"00", X"00", X"80", X"31", X"72", X"17", + X"f8", X"20", X"82", X"eb", X"f0", X"02", X"10", X"03", + X"4c", X"99", X"e1", X"a5", X"9d", X"e9", X"7f", X"48", + X"a9", X"80", X"85", X"9d", X"a9", X"2d", X"a0", X"e9", + X"20", X"be", X"e7", X"a9", X"32", X"a0", X"e9", X"20", + X"66", X"ea", X"a9", X"13", X"a0", X"e9", X"20", X"a7", + X"e7", X"a9", X"18", X"a0", X"e9", X"20", X"5c", X"ef", + X"a9", X"37", X"a0", X"e9", X"20", X"be", X"e7", X"68", + X"20", X"d5", X"ec", X"a9", X"3c", X"a0", X"e9", X"20", + X"e3", X"e9", X"d0", X"03", X"4c", X"e2", X"e9", X"20", + X"0e", X"ea", X"a9", X"00", X"85", X"62", X"85", X"63", + X"85", X"64", X"85", X"65", X"a5", X"ac", X"20", X"b0", + X"e9", X"a5", X"a1", X"20", X"b0", X"e9", X"a5", X"a0", + X"20", X"b0", X"e9", X"a5", X"9f", X"20", X"b0", X"e9", + X"a5", X"9e", X"20", X"b5", X"e9", X"4c", X"e6", X"ea", + X"d0", X"03", X"4c", X"da", X"e8", X"4a", X"09", X"80", + X"a8", X"90", X"19", X"18", X"a5", X"65", X"65", X"a9", + X"85", X"65", X"a5", X"64", X"65", X"a8", X"85", X"64", + X"a5", X"63", X"65", X"a7", X"85", X"63", X"a5", X"62", + X"65", X"a6", X"85", X"62", X"66", X"62", X"66", X"63", + X"66", X"64", X"66", X"65", X"66", X"ac", X"98", X"4a", + X"d0", X"d6", X"60", X"85", X"5e", X"84", X"5f", X"a0", + X"04", X"b1", X"5e", X"85", X"a9", X"88", X"b1", X"5e", + X"85", X"a8", X"88", X"b1", X"5e", X"85", X"a7", X"88", + X"b1", X"5e", X"85", X"aa", X"45", X"a2", X"85", X"ab", + X"a5", X"aa", X"09", X"80", X"85", X"a6", X"88", X"b1", + X"5e", X"85", X"a5", X"a5", X"9d", X"60", X"a5", X"a5", + X"f0", X"1f", X"18", X"65", X"9d", X"90", X"04", X"30", + X"1d", X"18", X"2c", X"10", X"14", X"69", X"80", X"85", + X"9d", X"d0", X"03", X"4c", X"52", X"e8", X"a5", X"ab", + X"85", X"a2", X"60", X"a5", X"a2", X"49", X"ff", X"30", + X"05", X"68", X"68", X"4c", X"4e", X"e8", X"4c", X"d5", + X"e8", X"20", X"63", X"eb", X"aa", X"f0", X"10", X"18", + X"69", X"02", X"b0", X"f2", X"a2", X"00", X"86", X"ab", + X"20", X"ce", X"e7", X"e6", X"9d", X"f0", X"e7", X"60", + X"84", X"20", X"00", X"00", X"00", X"20", X"63", X"eb", + X"a9", X"50", X"a0", X"ea", X"a2", X"00", X"86", X"ab", + X"20", X"f9", X"ea", X"4c", X"69", X"ea", X"20", X"e3", + X"e9", X"f0", X"76", X"20", X"72", X"eb", X"a9", X"00", + X"38", X"e5", X"9d", X"85", X"9d", X"20", X"0e", X"ea", + X"e6", X"9d", X"f0", X"ba", X"a2", X"fc", X"a9", X"01", + X"a4", X"a6", X"c4", X"9e", X"d0", X"10", X"a4", X"a7", + X"c4", X"9f", X"d0", X"0a", X"a4", X"a8", X"c4", X"a0", + X"d0", X"04", X"a4", X"a9", X"c4", X"a1", X"08", X"2a", + X"90", X"09", X"e8", X"95", X"65", X"f0", X"32", X"10", + X"34", X"a9", X"01", X"28", X"b0", X"0e", X"06", X"a9", + X"26", X"a8", X"26", X"a7", X"26", X"a6", X"b0", X"e6", + X"30", X"ce", X"10", X"e2", X"a8", X"a5", X"a9", X"e5", + X"a1", X"85", X"a9", X"a5", X"a8", X"e5", X"a0", X"85", + X"a8", X"a5", X"a7", X"e5", X"9f", X"85", X"a7", X"a5", + X"a6", X"e5", X"9e", X"85", X"a6", X"98", X"4c", X"a6", + X"ea", X"a9", X"40", X"d0", X"ce", X"0a", X"0a", X"0a", + X"0a", X"0a", X"0a", X"85", X"ac", X"28", X"4c", X"e6", + X"ea", X"a2", X"85", X"4c", X"12", X"d4", X"a5", X"62", + X"85", X"9e", X"a5", X"63", X"85", X"9f", X"a5", X"64", + X"85", X"a0", X"a5", X"65", X"85", X"a1", X"4c", X"2e", + X"e8", X"85", X"5e", X"84", X"5f", X"a0", X"04", X"b1", + X"5e", X"85", X"a1", X"88", X"b1", X"5e", X"85", X"a0", + X"88", X"b1", X"5e", X"85", X"9f", X"88", X"b1", X"5e", + X"85", X"a2", X"09", X"80", X"85", X"9e", X"88", X"b1", + X"5e", X"85", X"9d", X"84", X"ac", X"60", X"a2", X"98", + X"2c", X"a2", X"93", X"a0", X"00", X"f0", X"04", X"a6", + X"85", X"a4", X"86", X"20", X"72", X"eb", X"86", X"5e", + X"84", X"5f", X"a0", X"04", X"a5", X"a1", X"91", X"5e", + X"88", X"a5", X"a0", X"91", X"5e", X"88", X"a5", X"9f", + X"91", X"5e", X"88", X"a5", X"a2", X"09", X"7f", X"25", + X"9e", X"91", X"5e", X"88", X"a5", X"9d", X"91", X"5e", + X"84", X"ac", X"60", X"a5", X"aa", X"85", X"a2", X"a2", + X"05", X"b5", X"a4", X"95", X"9c", X"ca", X"d0", X"f9", + X"86", X"ac", X"60", X"20", X"72", X"eb", X"a2", X"06", + X"b5", X"9c", X"95", X"a4", X"ca", X"d0", X"f9", X"86", + X"ac", X"60", X"a5", X"9d", X"f0", X"fb", X"06", X"ac", + X"90", X"f7", X"20", X"c6", X"e8", X"d0", X"f2", X"4c", + X"8f", X"e8", X"a5", X"9d", X"f0", X"09", X"a5", X"a2", + X"2a", X"a9", X"ff", X"b0", X"02", X"a9", X"01", X"60", + X"20", X"82", X"eb", X"85", X"9e", X"a9", X"00", X"85", + X"9f", X"a2", X"88", X"a5", X"9e", X"49", X"ff", X"2a", + X"a9", X"00", X"85", X"a1", X"85", X"a0", X"86", X"9d", + X"85", X"ac", X"85", X"a2", X"4c", X"29", X"e8", X"46", + X"a2", X"60", X"85", X"60", X"84", X"61", X"a0", X"00", + X"b1", X"60", X"c8", X"aa", X"f0", X"c4", X"b1", X"60", + X"45", X"a2", X"30", X"c2", X"e4", X"9d", X"d0", X"21", + X"b1", X"60", X"09", X"80", X"c5", X"9e", X"d0", X"19", + X"c8", X"b1", X"60", X"c5", X"9f", X"d0", X"12", X"c8", + X"b1", X"60", X"c5", X"a0", X"d0", X"0b", X"c8", X"a9", + X"7f", X"c5", X"ac", X"b1", X"60", X"e5", X"a1", X"f0", + X"28", X"a5", X"a2", X"90", X"02", X"49", X"ff", X"4c", + X"88", X"eb", X"a5", X"9d", X"f0", X"4a", X"38", X"e9", + X"a0", X"24", X"a2", X"10", X"09", X"aa", X"a9", X"ff", + X"85", X"a4", X"20", X"a4", X"e8", X"8a", X"a2", X"9d", + X"c9", X"f9", X"10", X"06", X"20", X"f0", X"e8", X"84", + X"a4", X"60", X"a8", X"a5", X"a2", X"29", X"80", X"46", + X"9e", X"05", X"9e", X"85", X"9e", X"20", X"07", X"e9", + X"84", X"a4", X"60", X"a5", X"9d", X"c9", X"a0", X"b0", + X"20", X"20", X"f2", X"eb", X"84", X"ac", X"a5", X"a2", + X"84", X"a2", X"49", X"80", X"2a", X"a9", X"a0", X"85", + X"9d", X"a5", X"a1", X"85", X"0d", X"4c", X"29", X"e8", + X"85", X"9e", X"85", X"9f", X"85", X"a0", X"85", X"a1", + X"a8", X"60", X"a0", X"00", X"a2", X"0a", X"94", X"99", + X"ca", X"10", X"fb", X"90", X"0f", X"c9", X"2d", X"d0", + X"04", X"86", X"a3", X"f0", X"04", X"c9", X"2b", X"d0", + X"05", X"20", X"b1", X"00", X"90", X"5b", X"c9", X"2e", + X"f0", X"2e", X"c9", X"45", X"d0", X"30", X"20", X"b1", + X"00", X"90", X"17", X"c9", X"c9", X"f0", X"0e", X"c9", + X"2d", X"f0", X"0a", X"c9", X"c8", X"f0", X"08", X"c9", + X"2b", X"f0", X"04", X"d0", X"07", X"66", X"9c", X"20", + X"b1", X"00", X"90", X"5c", X"24", X"9c", X"10", X"0e", + X"a9", X"00", X"38", X"e5", X"9a", X"4c", X"a0", X"ec", + X"66", X"9b", X"24", X"9b", X"50", X"c3", X"a5", X"9a", + X"38", X"e5", X"99", X"85", X"9a", X"f0", X"12", X"10", + X"09", X"20", X"55", X"ea", X"e6", X"9a", X"d0", X"f9", + X"f0", X"07", X"20", X"39", X"ea", X"c6", X"9a", X"d0", + X"f9", X"a5", X"a3", X"30", X"01", X"60", X"4c", X"d0", + X"ee", X"48", X"24", X"9b", X"10", X"02", X"e6", X"99", + X"20", X"39", X"ea", X"68", X"38", X"e9", X"30", X"20", + X"d5", X"ec", X"4c", X"61", X"ec", X"48", X"20", X"63", + X"eb", X"68", X"20", X"93", X"eb", X"a5", X"aa", X"45", + X"a2", X"85", X"ab", X"a6", X"9d", X"4c", X"c1", X"e7", + X"a5", X"9a", X"c9", X"0a", X"90", X"09", X"a9", X"64", + X"24", X"9c", X"30", X"11", X"4c", X"d5", X"e8", X"0a", + X"0a", X"18", X"65", X"9a", X"0a", X"18", X"a0", X"00", + X"71", X"b8", X"38", X"e9", X"30", X"85", X"9a", X"4c", + X"87", X"ec", X"9b", X"3e", X"bc", X"1f", X"fd", X"9e", + X"6e", X"6b", X"27", X"fd", X"9e", X"6e", X"6b", X"28", + X"00", X"a9", X"58", X"a0", X"d3", X"20", X"31", X"ed", + X"a5", X"76", X"a6", X"75", X"85", X"9e", X"86", X"9f", + X"a2", X"90", X"38", X"20", X"a0", X"eb", X"20", X"34", + X"ed", X"4c", X"3a", X"db", X"a0", X"01", X"a9", X"2d", + X"88", X"24", X"a2", X"10", X"04", X"c8", X"99", X"ff", + X"00", X"85", X"a2", X"84", X"ad", X"c8", X"a9", X"30", + X"a6", X"9d", X"d0", X"03", X"4c", X"57", X"ee", X"a9", + X"00", X"e0", X"80", X"f0", X"02", X"b0", X"09", X"a9", + X"14", X"a0", X"ed", X"20", X"7f", X"e9", X"a9", X"f7", + X"85", X"99", X"a9", X"0f", X"a0", X"ed", X"20", X"b2", + X"eb", X"f0", X"1e", X"10", X"12", X"a9", X"0a", X"a0", + X"ed", X"20", X"b2", X"eb", X"f0", X"02", X"10", X"0e", + X"20", X"39", X"ea", X"c6", X"99", X"d0", X"ee", X"20", + X"55", X"ea", X"e6", X"99", X"d0", X"dc", X"20", X"a0", + X"e7", X"20", X"f2", X"eb", X"a2", X"01", X"a5", X"99", + X"18", X"69", X"0a", X"30", X"09", X"c9", X"0b", X"b0", + X"06", X"69", X"ff", X"aa", X"a9", X"02", X"38", X"e9", + X"02", X"85", X"9a", X"86", X"99", X"8a", X"f0", X"02", + X"10", X"13", X"a4", X"ad", X"a9", X"2e", X"c8", X"99", + X"ff", X"00", X"8a", X"f0", X"06", X"a9", X"30", X"c8", + X"99", X"ff", X"00", X"84", X"ad", X"a0", X"00", X"a2", + X"80", X"a5", X"a1", X"18", X"79", X"6c", X"ee", X"85", + X"a1", X"a5", X"a0", X"79", X"6b", X"ee", X"85", X"a0", + X"a5", X"9f", X"79", X"6a", X"ee", X"85", X"9f", X"a5", + X"9e", X"79", X"69", X"ee", X"85", X"9e", X"e8", X"b0", + X"04", X"10", X"de", X"30", X"02", X"30", X"da", X"8a", + X"90", X"04", X"49", X"ff", X"69", X"0a", X"69", X"2f", + X"c8", X"c8", X"c8", X"c8", X"84", X"83", X"a4", X"ad", + X"c8", X"aa", X"29", X"7f", X"99", X"ff", X"00", X"c6", + X"99", X"d0", X"06", X"a9", X"2e", X"c8", X"99", X"ff", + X"00", X"84", X"ad", X"a4", X"83", X"8a", X"49", X"ff", + X"29", X"80", X"aa", X"c0", X"24", X"d0", X"aa", X"a4", + X"ad", X"b9", X"ff", X"00", X"88", X"c9", X"30", X"f0", + X"f8", X"c9", X"2e", X"f0", X"01", X"c8", X"a9", X"2b", + X"a6", X"9a", X"f0", X"2e", X"10", X"08", X"a9", X"00", + X"38", X"e5", X"9a", X"aa", X"a9", X"2d", X"99", X"01", + X"01", X"a9", X"45", X"99", X"00", X"01", X"8a", X"a2", + X"2f", X"38", X"e8", X"e9", X"0a", X"b0", X"fb", X"69", + X"3a", X"99", X"03", X"01", X"8a", X"99", X"02", X"01", + X"a9", X"00", X"99", X"04", X"01", X"f0", X"08", X"99", + X"ff", X"00", X"a9", X"00", X"99", X"00", X"01", X"a9", + X"00", X"a0", X"01", X"60", X"80", X"00", X"00", X"00", + X"00", X"fa", X"0a", X"1f", X"00", X"00", X"98", X"96", + X"80", X"ff", X"f0", X"bd", X"c0", X"00", X"01", X"86", + X"a0", X"ff", X"ff", X"d8", X"f0", X"00", X"00", X"03", + X"e8", X"ff", X"ff", X"ff", X"9c", X"00", X"00", X"00", + X"0a", X"ff", X"ff", X"ff", X"ff", X"20", X"63", X"eb", + X"a9", X"64", X"a0", X"ee", X"20", X"f9", X"ea", X"f0", + X"70", X"a5", X"a5", X"d0", X"03", X"4c", X"50", X"e8", + X"a2", X"8a", X"a0", X"00", X"20", X"2b", X"eb", X"a5", + X"aa", X"10", X"0f", X"20", X"23", X"ec", X"a9", X"8a", + X"a0", X"00", X"20", X"b2", X"eb", X"d0", X"03", X"98", + X"a4", X"0d", X"20", X"55", X"eb", X"98", X"48", X"20", + X"41", X"e9", X"a9", X"8a", X"a0", X"00", X"20", X"7f", + X"e9", X"20", X"09", X"ef", X"68", X"4a", X"90", X"0a", + X"a5", X"9d", X"f0", X"06", X"a5", X"a2", X"49", X"ff", + X"85", X"a2", X"60", X"81", X"38", X"aa", X"3b", X"29", + X"07", X"71", X"34", X"58", X"3e", X"56", X"74", X"16", + X"7e", X"b3", X"1b", X"77", X"2f", X"ee", X"e3", X"85", + X"7a", X"1d", X"84", X"1c", X"2a", X"7c", X"63", X"59", + X"58", X"0a", X"7e", X"75", X"fd", X"e7", X"c6", X"80", + X"31", X"72", X"18", X"10", X"81", X"00", X"00", X"00", + X"00", X"a9", X"db", X"a0", X"ee", X"20", X"7f", X"e9", + X"a5", X"ac", X"69", X"50", X"90", X"03", X"20", X"7a", + X"eb", X"85", X"92", X"20", X"66", X"eb", X"a5", X"9d", + X"c9", X"88", X"90", X"03", X"20", X"2b", X"ea", X"20", + X"23", X"ec", X"a5", X"0d", X"18", X"69", X"81", X"f0", + X"f3", X"38", X"e9", X"01", X"48", X"a2", X"05", X"b5", + X"a5", X"b4", X"9d", X"95", X"9d", X"94", X"a5", X"ca", + X"10", X"f5", X"a5", X"92", X"85", X"ac", X"20", X"aa", + X"e7", X"20", X"d0", X"ee", X"a9", X"e0", X"a0", X"ee", + X"20", X"72", X"ef", X"a9", X"00", X"85", X"ab", X"68", + X"20", X"10", X"ea", X"60", X"85", X"ad", X"84", X"ae", + X"20", X"21", X"eb", X"a9", X"93", X"20", X"7f", X"e9", + X"20", X"76", X"ef", X"a9", X"93", X"a0", X"00", X"4c", + X"7f", X"e9", X"85", X"ad", X"84", X"ae", X"20", X"1e", + X"eb", X"b1", X"ad", X"85", X"a3", X"a4", X"ad", X"c8", + X"98", X"d0", X"02", X"e6", X"ae", X"85", X"ad", X"a4", + X"ae", X"20", X"7f", X"e9", X"a5", X"ad", X"a4", X"ae", + X"18", X"69", X"05", X"90", X"01", X"c8", X"85", X"ad", + X"84", X"ae", X"20", X"be", X"e7", X"a9", X"98", X"a0", + X"00", X"c6", X"a3", X"d0", X"e4", X"60", X"98", X"35", + X"44", X"7a", X"68", X"28", X"b1", X"46", X"20", X"82", + X"eb", X"aa", X"30", X"18", X"a9", X"c9", X"a0", X"00", + X"20", X"f9", X"ea", X"8a", X"f0", X"e7", X"a9", X"a6", + X"a0", X"ef", X"20", X"7f", X"e9", X"a9", X"aa", X"a0", + X"ef", X"20", X"be", X"e7", X"a6", X"a1", X"a5", X"9e", + X"85", X"a1", X"86", X"9e", X"a9", X"00", X"85", X"a2", + X"a5", X"9d", X"85", X"ac", X"a9", X"80", X"85", X"9d", + X"20", X"2e", X"e8", X"a2", X"c9", X"a0", X"00", X"4c", + X"2b", X"eb", X"a9", X"66", X"a0", X"f0", X"20", X"be", + X"e7", X"20", X"63", X"eb", X"a9", X"6b", X"a0", X"f0", + X"a6", X"aa", X"20", X"5e", X"ea", X"20", X"63", X"eb", + X"20", X"23", X"ec", X"a9", X"00", X"85", X"ab", X"20", + X"aa", X"e7", X"a9", X"70", X"a0", X"f0", X"20", X"a7", + X"e7", X"a5", X"a2", X"48", X"10", X"0d", X"20", X"a0", + X"e7", X"a5", X"a2", X"30", X"09", X"a5", X"16", X"49", + X"ff", X"85", X"16", X"20", X"d0", X"ee", X"a9", X"70", + X"a0", X"f0", X"20", X"be", X"e7", X"68", X"10", X"03", + X"20", X"d0", X"ee", X"a9", X"75", X"a0", X"f0", X"4c", + X"5c", X"ef", X"20", X"21", X"eb", X"a9", X"00", X"85", + X"16", X"20", X"f1", X"ef", X"a2", X"8a", X"a0", X"00", + X"20", X"e7", X"ef", X"a9", X"93", X"a0", X"00", X"20", + X"f9", X"ea", X"a9", X"00", X"85", X"a2", X"a5", X"16", + X"20", X"62", X"f0", X"a9", X"8a", X"a0", X"00", X"4c", + X"66", X"ea", X"48", X"4c", X"23", X"f0", X"81", X"49", + X"0f", X"da", X"a2", X"83", X"49", X"0f", X"da", X"a2", + X"7f", X"00", X"00", X"00", X"00", X"05", X"84", X"e6", + X"1a", X"2d", X"1b", X"86", X"28", X"07", X"fb", X"f8", + X"87", X"99", X"68", X"89", X"01", X"87", X"23", X"35", + X"df", X"e1", X"86", X"a5", X"5d", X"e7", X"28", X"83", + X"49", X"0f", X"da", X"a2", X"a6", X"d3", X"c1", X"c8", + X"d4", X"c8", X"d5", X"c4", X"ce", X"ca", X"a5", X"a2", + X"48", X"10", X"03", X"20", X"d0", X"ee", X"a5", X"9d", + X"48", X"c9", X"81", X"90", X"07", X"a9", X"13", X"a0", + X"e9", X"20", X"66", X"ea", X"a9", X"ce", X"a0", X"f0", + X"20", X"5c", X"ef", X"68", X"c9", X"81", X"90", X"07", + X"a9", X"66", X"a0", X"f0", X"20", X"a7", X"e7", X"68", + X"10", X"03", X"4c", X"d0", X"ee", X"60", X"0b", X"76", + X"b3", X"83", X"bd", X"d3", X"79", X"1e", X"f4", X"a6", + X"f5", X"7b", X"83", X"fc", X"b0", X"10", X"7c", X"0c", + X"1f", X"67", X"ca", X"7c", X"de", X"53", X"cb", X"c1", + X"7d", X"14", X"64", X"70", X"4c", X"7d", X"b7", X"ea", + X"51", X"7a", X"7d", X"63", X"30", X"88", X"7e", X"7e", + X"92", X"44", X"99", X"3a", X"7e", X"4c", X"cc", X"91", + X"c7", X"7f", X"aa", X"aa", X"aa", X"13", X"81", X"00", + X"00", X"00", X"00", X"e6", X"b8", X"d0", X"02", X"e6", + X"b9", X"ad", X"60", X"ea", X"c9", X"3a", X"b0", X"0a", + X"c9", X"20", X"f0", X"ef", X"38", X"e9", X"30", X"38", + X"e9", X"d0", X"60", X"80", X"4f", X"c7", X"52", X"58", + X"a2", X"ff", X"86", X"76", X"a2", X"fb", X"9a", X"a9", + X"28", X"a0", X"f1", X"85", X"01", X"84", X"02", X"85", + X"04", X"84", X"05", X"20", X"73", X"f2", X"a9", X"4c", + X"85", X"00", X"85", X"03", X"85", X"90", X"85", X"0a", + X"a9", X"99", X"a0", X"e1", X"85", X"0b", X"84", X"0c", + X"a2", X"1c", X"bd", X"0a", X"f1", X"95", X"b0", X"86", + X"f1", X"ca", X"d0", X"f6", X"86", X"f2", X"8a", X"85", + X"a4", X"85", X"54", X"48", X"a9", X"03", X"85", X"8f", + X"20", X"fb", X"da", X"a9", X"01", X"8d", X"fd", X"01", + X"8d", X"fc", X"01", X"a2", X"55", X"86", X"52", X"a9", + X"00", X"a0", X"08", X"85", X"50", X"84", X"51", X"a0", + X"00", X"e6", X"51", X"b1", X"50", X"49", X"ff", X"91", + X"50", X"d1", X"50", X"d0", X"08", X"49", X"ff", X"91", + X"50", X"d1", X"50", X"f0", X"ec", X"a4", X"50", X"a5", + X"51", X"29", X"f0", X"84", X"73", X"85", X"74", X"84", + X"6f", X"85", X"70", X"a2", X"00", X"a0", X"08", X"86", + X"67", X"84", X"68", X"a0", X"00", X"84", X"d6", X"98", + X"91", X"67", X"e6", X"67", X"d0", X"02", X"e6", X"68", + X"a5", X"67", X"a4", X"68", X"20", X"e3", X"d3", X"20", + X"4b", X"d6", X"a9", X"3a", X"a0", X"db", X"85", X"04", + X"84", X"05", X"a9", X"3c", X"a0", X"d4", X"85", X"01", + X"84", X"02", X"6c", X"01", X"00", X"20", X"67", X"dd", + X"20", X"52", X"e7", X"6c", X"50", X"00", X"20", X"f8", + X"e6", X"8a", X"4c", X"8b", X"fe", X"20", X"f8", X"e6", + X"8a", X"4c", X"95", X"fe", X"20", X"f8", X"e6", X"e0", + X"30", X"b0", X"13", X"86", X"f0", X"a9", X"2c", X"20", + X"c0", X"de", X"20", X"f8", X"e6", X"e0", X"30", X"b0", + X"05", X"86", X"2c", X"86", X"2d", X"60", X"4c", X"99", + X"e1", X"20", X"ec", X"f1", X"e4", X"f0", X"b0", X"08", + X"a5", X"f0", X"85", X"2c", X"85", X"2d", X"86", X"f0", + X"a9", X"c5", X"20", X"c0", X"de", X"20", X"f8", X"e6", + X"e0", X"30", X"b0", X"e2", X"60", X"20", X"ec", X"f1", + X"8a", X"a4", X"f0", X"c0", X"28", X"b0", X"d7", X"4c", + X"00", X"f8", X"20", X"09", X"f2", X"8a", X"a4", X"2c", + X"c0", X"28", X"b0", X"ca", X"a4", X"f0", X"4c", X"19", + X"f8", X"20", X"09", X"f2", X"8a", X"a8", X"c0", X"28", + X"b0", X"bc", X"a5", X"f0", X"4c", X"28", X"f8", X"20", + X"f8", X"e6", X"8a", X"4c", X"64", X"f8", X"20", X"f8", + X"e6", X"ca", X"8a", X"c9", X"18", X"b0", X"a7", X"4c", + X"5b", X"fb", X"20", X"f8", X"e6", X"8a", X"49", X"ff", + X"aa", X"e8", X"86", X"f1", X"60", X"38", X"90", X"18", + X"66", X"f2", X"60", X"a9", X"ff", X"d0", X"02", X"a9", + X"3f", X"a2", X"00", X"85", X"32", X"86", X"f3", X"60", + X"a9", X"7f", X"a2", X"40", X"d0", X"f5", X"20", X"67", + X"dd", X"20", X"52", X"e7", X"a5", X"50", X"c5", X"6d", + X"a5", X"51", X"e5", X"6e", X"b0", X"03", X"4c", X"10", + X"d4", X"a5", X"50", X"85", X"73", X"85", X"6f", X"a5", + X"51", X"85", X"74", X"85", X"70", X"60", X"20", X"67", + X"dd", X"20", X"52", X"e7", X"a5", X"50", X"c5", X"73", + X"a5", X"51", X"e5", X"74", X"b0", X"e0", X"a5", X"50", + X"c5", X"69", X"a5", X"51", X"e5", X"6a", X"90", X"d6", + X"a5", X"50", X"85", X"69", X"a5", X"51", X"85", X"6a", + X"4c", X"6c", X"d6", X"a9", X"ab", X"20", X"c0", X"de", + X"a5", X"b8", X"85", X"f4", X"a5", X"b9", X"85", X"f5", + X"38", X"66", X"d8", X"a5", X"75", X"85", X"f6", X"a5", + X"76", X"85", X"f7", X"20", X"a6", X"d9", X"4c", X"98", + X"d9", X"86", X"de", X"a6", X"f8", X"86", X"df", X"a5", + X"75", X"85", X"da", X"a5", X"76", X"85", X"db", X"a5", + X"79", X"85", X"dc", X"a5", X"7a", X"85", X"dd", X"a5", + X"f4", X"85", X"b8", X"a5", X"f5", X"85", X"b9", X"a5", + X"f6", X"85", X"75", X"a5", X"f7", X"85", X"76", X"20", + X"b7", X"00", X"20", X"3e", X"d9", X"4c", X"d2", X"d7", + X"a5", X"da", X"85", X"75", X"a5", X"db", X"85", X"76", + X"a5", X"dc", X"85", X"b8", X"a5", X"dd", X"85", X"b9", + X"a6", X"df", X"9a", X"4c", X"d2", X"d7", X"4c", X"c9", + X"de", X"b0", X"fb", X"a6", X"af", X"86", X"69", X"a6", + X"b0", X"86", X"6a", X"20", X"0c", X"da", X"20", X"1a", + X"d6", X"a5", X"9b", X"85", X"60", X"a5", X"9c", X"85", + X"61", X"a9", X"2c", X"20", X"c0", X"de", X"20", X"0c", + X"da", X"e6", X"50", X"d0", X"02", X"e6", X"51", X"20", + X"1a", X"d6", X"a5", X"9b", X"c5", X"60", X"a5", X"9c", + X"e5", X"61", X"b0", X"01", X"60", X"a0", X"00", X"b1", + X"9b", X"91", X"60", X"e6", X"9b", X"d0", X"02", X"e6", + X"9c", X"e6", X"60", X"d0", X"02", X"e6", X"61", X"a5", + X"69", X"c5", X"9b", X"a5", X"6a", X"e5", X"9c", X"b0", + X"e6", X"a6", X"61", X"a4", X"60", X"d0", X"01", X"ca", + X"88", X"86", X"6a", X"84", X"69", X"4c", X"f2", X"d4", + X"ad", X"56", X"c0", X"ad", X"53", X"c0", X"4c", X"40", + X"fb", X"ad", X"54", X"c0", X"4c", X"39", X"fb", X"20", + X"d9", X"f7", X"a0", X"03", X"b1", X"9b", X"aa", X"88", + X"b1", X"9b", X"e9", X"01", X"b0", X"01", X"ca", X"85", + X"50", X"86", X"51", X"20", X"cd", X"fe", X"20", X"bc", + X"f7", X"4c", X"cd", X"fe", X"20", X"d9", X"f7", X"20", + X"fd", X"fe", X"a0", X"02", X"b1", X"9b", X"c5", X"50", + X"c8", X"b1", X"9b", X"e5", X"51", X"b0", X"03", X"4c", + X"10", X"d4", X"20", X"bc", X"f7", X"4c", X"fd", X"fe", + X"2c", X"55", X"c0", X"2c", X"52", X"c0", X"a9", X"40", + X"d0", X"08", X"a9", X"20", X"2c", X"54", X"c0", X"2c", + X"53", X"c0", X"85", X"e6", X"ad", X"57", X"c0", X"ad", + X"50", X"c0", X"a9", X"00", X"85", X"1c", X"a5", X"e6", + X"85", X"1b", X"a0", X"00", X"84", X"1a", X"a5", X"1c", + X"91", X"1a", X"20", X"7e", X"f4", X"c8", X"d0", X"f6", + X"e6", X"1b", X"a5", X"1b", X"29", X"1f", X"d0", X"ee", + X"60", X"85", X"e2", X"86", X"e0", X"84", X"e1", X"48", + X"29", X"c0", X"85", X"26", X"4a", X"4a", X"05", X"26", + X"85", X"26", X"68", X"85", X"27", X"0a", X"0a", X"0a", + X"26", X"27", X"0a", X"26", X"27", X"0a", X"66", X"26", + X"a5", X"27", X"29", X"1f", X"05", X"e6", X"85", X"27", + X"8a", X"c0", X"00", X"f0", X"05", X"a0", X"23", X"69", + X"04", X"c8", X"e9", X"07", X"b0", X"fb", X"84", X"e5", + X"aa", X"bd", X"b9", X"f4", X"85", X"30", X"98", X"4a", + X"a5", X"e4", X"85", X"1c", X"b0", X"28", X"60", X"20", + X"11", X"f4", X"a5", X"1c", X"51", X"26", X"25", X"30", + X"51", X"26", X"91", X"26", X"60", X"10", X"23", X"a5", + X"30", X"4a", X"b0", X"05", X"49", X"c0", X"85", X"30", + X"60", X"88", X"10", X"02", X"a0", X"27", X"a9", X"c0", + X"85", X"30", X"84", X"e5", X"a5", X"1c", X"0a", X"c9", + X"c0", X"10", X"06", X"a5", X"1c", X"49", X"7f", X"85", + X"1c", X"60", X"a5", X"30", X"0a", X"49", X"80", X"30", + X"dd", X"a9", X"81", X"c8", X"c0", X"28", X"90", X"e0", + X"a0", X"00", X"b0", X"dc", X"18", X"a5", X"d1", X"29", + X"04", X"f0", X"25", X"a9", X"7f", X"25", X"30", X"31", + X"26", X"d0", X"19", X"e6", X"ea", X"a9", X"7f", X"25", + X"30", X"10", X"11", X"18", X"a5", X"d1", X"29", X"04", + X"f0", X"0e", X"b1", X"26", X"45", X"1c", X"25", X"30", + X"d0", X"02", X"e6", X"ea", X"51", X"26", X"91", X"26", + X"a5", X"d1", X"65", X"d3", X"29", X"03", X"c9", X"02", + X"6a", X"b0", X"92", X"30", X"30", X"18", X"a5", X"27", + X"2c", X"b9", X"f5", X"d0", X"22", X"06", X"26", X"b0", + X"1a", X"2c", X"cd", X"f4", X"f0", X"05", X"69", X"1f", + X"38", X"b0", X"12", X"69", X"23", X"48", X"a5", X"26", + X"69", X"b0", X"b0", X"02", X"69", X"f0", X"85", X"26", + X"68", X"b0", X"02", X"69", X"1f", X"66", X"26", X"69", + X"fc", X"85", X"27", X"60", X"18", X"a5", X"27", X"69", + X"04", X"2c", X"b9", X"f5", X"d0", X"f3", X"06", X"26", + X"90", X"18", X"69", X"e0", X"18", X"2c", X"08", X"f5", + X"f0", X"12", X"a5", X"26", X"69", X"50", X"49", X"f0", + X"f0", X"02", X"49", X"f0", X"85", X"26", X"a5", X"e6", + X"90", X"02", X"69", X"e0", X"66", X"26", X"90", X"d1", + X"48", X"a9", X"00", X"85", X"e0", X"85", X"e1", X"85", + X"e2", X"68", X"48", X"38", X"e5", X"e0", X"48", X"8a", + X"e5", X"e1", X"85", X"d3", X"b0", X"0a", X"68", X"49", + X"ff", X"69", X"01", X"48", X"a9", X"00", X"e5", X"d3", + X"85", X"d1", X"85", X"d5", X"68", X"85", X"d0", X"85", + X"d4", X"68", X"85", X"e0", X"86", X"e1", X"98", X"18", + X"e5", X"e2", X"90", X"04", X"49", X"ff", X"69", X"fe", + X"85", X"d2", X"84", X"e2", X"66", X"d3", X"38", X"e5", + X"d0", X"aa", X"a9", X"ff", X"e5", X"d1", X"85", X"1d", + X"a4", X"e5", X"b0", X"05", X"0a", X"20", X"65", X"f4", + X"38", X"a5", X"d4", X"65", X"d2", X"85", X"d4", X"a5", + X"d5", X"e9", X"00", X"85", X"d5", X"b1", X"26", X"45", + X"1c", X"25", X"30", X"51", X"26", X"91", X"26", X"e8", + X"d0", X"04", X"e6", X"1d", X"f0", X"62", X"a5", X"d3", + X"b0", X"da", X"20", X"d3", X"f4", X"18", X"a5", X"d4", + X"65", X"d0", X"85", X"d4", X"a5", X"d5", X"65", X"d1", + X"50", X"d9", X"81", X"82", X"84", X"88", X"90", X"a0", + X"c0", X"1c", X"ff", X"fe", X"fa", X"f4", X"ec", X"e1", + X"d4", X"c5", X"b4", X"a1", X"8d", X"78", X"61", X"49", + X"31", X"18", X"ff", X"a5", X"26", X"0a", X"a5", X"27", + X"29", X"03", X"2a", X"05", X"26", X"0a", X"0a", X"0a", + X"85", X"e2", X"a5", X"27", X"4a", X"4a", X"29", X"07", + X"05", X"e2", X"85", X"e2", X"a5", X"e5", X"0a", X"65", + X"e5", X"0a", X"aa", X"ca", X"a5", X"30", X"29", X"7f", + X"e8", X"4a", X"d0", X"fc", X"85", X"e1", X"8a", X"18", + X"65", X"e5", X"90", X"02", X"e6", X"e1", X"85", X"e0", + X"60", X"86", X"1a", X"84", X"1b", X"aa", X"4a", X"4a", + X"4a", X"4a", X"85", X"d3", X"8a", X"29", X"0f", X"aa", + X"bc", X"ba", X"f5", X"84", X"d0", X"49", X"0f", X"aa", + X"bc", X"bb", X"f5", X"c8", X"84", X"d2", X"a4", X"e5", + X"a2", X"00", X"86", X"ea", X"a1", X"1a", X"85", X"d1", + X"a2", X"80", X"86", X"d4", X"86", X"d5", X"a6", X"e7", + X"a5", X"d4", X"38", X"65", X"d0", X"85", X"d4", X"90", + X"04", X"20", X"b3", X"f4", X"18", X"a5", X"d5", X"65", + X"d2", X"85", X"d5", X"90", X"03", X"20", X"b4", X"f4", + X"ca", X"d0", X"e5", X"a5", X"d1", X"4a", X"4a", X"4a", + X"d0", X"d4", X"e6", X"1a", X"d0", X"02", X"e6", X"1b", + X"a1", X"1a", X"d0", X"ca", X"60", X"86", X"1a", X"84", + X"1b", X"aa", X"4a", X"4a", X"4a", X"4a", X"85", X"d3", + X"8a", X"29", X"0f", X"aa", X"bc", X"ba", X"f5", X"84", + X"d0", X"49", X"0f", X"aa", X"bc", X"bb", X"f5", X"c8", + X"84", X"d2", X"a4", X"e5", X"a2", X"00", X"86", X"ea", + X"a1", X"1a", X"85", X"d1", X"a2", X"80", X"86", X"d4", + X"86", X"d5", X"a6", X"e7", X"a5", X"d4", X"38", X"65", + X"d0", X"85", X"d4", X"90", X"04", X"20", X"9c", X"f4", + X"18", X"a5", X"d5", X"65", X"d2", X"85", X"d5", X"90", + X"03", X"20", X"9d", X"f4", X"ca", X"d0", X"e5", X"a5", + X"d1", X"4a", X"4a", X"4a", X"d0", X"d4", X"e6", X"1a", + X"d0", X"02", X"e6", X"1b", X"a1", X"1a", X"d0", X"ca", + X"60", X"20", X"67", X"dd", X"20", X"52", X"e7", X"a4", + X"51", X"a6", X"50", X"c0", X"01", X"90", X"06", X"d0", + X"1d", X"e0", X"18", X"b0", X"19", X"8a", X"48", X"98", + X"48", X"a9", X"2c", X"20", X"c0", X"de", X"20", X"f8", + X"e6", X"e0", X"c0", X"b0", X"09", X"86", X"9d", X"68", + X"a8", X"68", X"aa", X"a5", X"9d", X"60", X"4c", X"06", + X"f2", X"20", X"f8", X"e6", X"e0", X"08", X"b0", X"f6", + X"bd", X"f6", X"f6", X"85", X"e4", X"60", X"00", X"2a", + X"55", X"7f", X"80", X"aa", X"d5", X"ff", X"c9", X"c1", + X"f0", X"0d", X"20", X"b9", X"f6", X"20", X"57", X"f4", + X"20", X"b7", X"00", X"c9", X"c1", X"d0", X"e6", X"20", + X"c0", X"de", X"20", X"b9", X"f6", X"84", X"9d", X"a8", + X"8a", X"a6", X"9d", X"20", X"3a", X"f5", X"4c", X"08", + X"f7", X"20", X"f8", X"e6", X"86", X"f9", X"60", X"20", + X"f8", X"e6", X"86", X"e7", X"60", X"20", X"f8", X"e6", + X"a5", X"e8", X"85", X"1a", X"a5", X"e9", X"85", X"1b", + X"8a", X"a2", X"00", X"c1", X"1a", X"f0", X"02", X"b0", + X"a5", X"0a", X"90", X"03", X"e6", X"1b", X"18", X"a8", + X"b1", X"1a", X"65", X"1a", X"aa", X"c8", X"b1", X"1a", + X"65", X"e9", X"85", X"1b", X"86", X"1a", X"20", X"b7", + X"00", X"c9", X"c5", X"d0", X"09", X"20", X"c0", X"de", + X"20", X"b9", X"f6", X"20", X"11", X"f4", X"a5", X"f9", + X"60", X"20", X"2d", X"f7", X"4c", X"05", X"f6", X"20", + X"2d", X"f7", X"4c", X"61", X"f6", X"a9", X"00", X"85", + X"3d", X"85", X"3f", X"a0", X"50", X"84", X"3c", X"c8", + X"84", X"3e", X"20", X"fd", X"fe", X"18", X"a5", X"73", + X"aa", X"ca", X"86", X"3e", X"e5", X"50", X"48", X"a5", + X"74", X"a8", X"e8", X"d0", X"01", X"88", X"84", X"3f", + X"e5", X"51", X"c5", X"6e", X"90", X"02", X"d0", X"03", + X"4c", X"10", X"d4", X"85", X"74", X"85", X"70", X"85", + X"3d", X"85", X"e9", X"68", X"85", X"e8", X"85", X"73", + X"85", X"6f", X"85", X"3c", X"20", X"fa", X"fc", X"a9", + X"03", X"4c", X"02", X"ff", X"18", X"a5", X"9b", X"65", + X"50", X"85", X"3e", X"a5", X"9c", X"65", X"51", X"85", + X"3f", X"a0", X"04", X"b1", X"9b", X"20", X"ef", X"e0", + X"a5", X"94", X"85", X"3c", X"a5", X"95", X"85", X"3d", + X"60", X"a9", X"40", X"85", X"14", X"20", X"e3", X"df", + X"a9", X"00", X"85", X"14", X"4c", X"f0", X"d8", X"20", + X"f8", X"e6", X"ca", X"8a", X"c9", X"28", X"90", X"0a", + X"e9", X"28", X"48", X"20", X"fb", X"da", X"68", X"4c", + X"ec", X"f7", X"85", X"24", X"60", X"cb", X"d2", X"d7", + X"4a", X"08", X"20", X"47", X"f8", X"28", X"a9", X"0f", + X"90", X"02", X"69", X"e0", X"85", X"2e", X"b1", X"26", + X"45", X"30", X"25", X"2e", X"51", X"26", X"91", X"26", + X"60", X"20", X"00", X"f8", X"c4", X"2c", X"b0", X"11", + X"c8", X"20", X"0e", X"f8", X"90", X"f6", X"69", X"01", + X"48", X"20", X"00", X"f8", X"68", X"c5", X"2d", X"90", + X"f5", X"60", X"a0", X"2f", X"d0", X"02", X"a0", X"27", + X"84", X"2d", X"a0", X"27", X"a9", X"00", X"85", X"30", + X"20", X"28", X"f8", X"88", X"10", X"f6", X"60", X"48", + X"4a", X"29", X"03", X"09", X"04", X"85", X"27", X"68", + X"29", X"18", X"90", X"02", X"69", X"7f", X"85", X"26", + X"0a", X"0a", X"05", X"26", X"85", X"26", X"60", X"a5", + X"30", X"18", X"69", X"03", X"29", X"0f", X"85", X"30", + X"0a", X"0a", X"0a", X"0a", X"05", X"30", X"85", X"30", + X"60", X"4a", X"08", X"20", X"47", X"f8", X"b1", X"26", + X"28", X"90", X"04", X"4a", X"4a", X"4a", X"4a", X"29", + X"0f", X"60", X"a6", X"3a", X"a4", X"3b", X"20", X"96", + X"fd", X"20", X"48", X"f9", X"a1", X"3a", X"a8", X"4a", + X"90", X"09", X"6a", X"b0", X"10", X"c9", X"a2", X"f0", + X"0c", X"29", X"87", X"4a", X"aa", X"bd", X"62", X"f9", + X"20", X"79", X"f8", X"d0", X"04", X"a0", X"80", X"a9", + X"00", X"aa", X"bd", X"a6", X"f9", X"85", X"2e", X"29", + X"03", X"85", X"2f", X"98", X"29", X"8f", X"aa", X"98", + X"a0", X"03", X"e0", X"8a", X"f0", X"0b", X"4a", X"90", + X"08", X"4a", X"4a", X"09", X"20", X"88", X"d0", X"fa", + X"c8", X"88", X"d0", X"f2", X"60", X"ff", X"ff", X"ff", + X"20", X"82", X"f8", X"48", X"b1", X"3a", X"20", X"da", + X"fd", X"a2", X"01", X"20", X"4a", X"f9", X"c4", X"2f", + X"c8", X"90", X"f1", X"a2", X"03", X"c0", X"04", X"90", + X"f2", X"68", X"a8", X"b9", X"c0", X"f9", X"85", X"2c", + X"b9", X"00", X"fa", X"85", X"2d", X"a9", X"00", X"a0", + X"05", X"06", X"2d", X"26", X"2c", X"2a", X"88", X"d0", + X"f8", X"69", X"bf", X"20", X"ed", X"fd", X"ca", X"d0", + X"ec", X"20", X"48", X"f9", X"a4", X"2f", X"a2", X"06", + X"e0", X"03", X"f0", X"1c", X"06", X"2e", X"90", X"0e", + X"bd", X"b3", X"f9", X"20", X"ed", X"fd", X"bd", X"b9", + X"f9", X"f0", X"03", X"20", X"ed", X"fd", X"ca", X"d0", + X"e7", X"60", X"88", X"30", X"e7", X"20", X"da", X"fd", + X"a5", X"2e", X"c9", X"e8", X"b1", X"3a", X"90", X"f2", + X"20", X"56", X"f9", X"aa", X"e8", X"d0", X"01", X"c8", + X"98", X"20", X"da", X"fd", X"8a", X"4c", X"da", X"fd", + X"a2", X"03", X"a9", X"a0", X"20", X"ed", X"fd", X"ca", + X"d0", X"f8", X"60", X"38", X"a5", X"2f", X"a4", X"3b", + X"aa", X"10", X"01", X"88", X"65", X"3a", X"90", X"01", + X"c8", X"60", X"04", X"20", X"54", X"30", X"0d", X"80", + X"04", X"90", X"03", X"22", X"54", X"33", X"0d", X"80", + X"04", X"90", X"04", X"20", X"54", X"33", X"0d", X"80", + X"04", X"90", X"04", X"20", X"54", X"3b", X"0d", X"80", + X"04", X"90", X"00", X"22", X"44", X"33", X"0d", X"c8", + X"44", X"00", X"11", X"22", X"44", X"33", X"0d", X"c8", + X"44", X"a9", X"01", X"22", X"44", X"33", X"0d", X"80", + X"04", X"90", X"01", X"22", X"44", X"33", X"0d", X"80", + X"04", X"90", X"26", X"31", X"87", X"9a", X"00", X"21", + X"81", X"82", X"00", X"00", X"59", X"4d", X"91", X"92", + X"86", X"4a", X"85", X"9d", X"ac", X"a9", X"ac", X"a3", + X"a8", X"a4", X"d9", X"00", X"d8", X"a4", X"a4", X"00", + X"1c", X"8a", X"1c", X"23", X"5d", X"8b", X"1b", X"a1", + X"9d", X"8a", X"1d", X"23", X"9d", X"8b", X"1d", X"a1", + X"00", X"29", X"19", X"ae", X"69", X"a8", X"19", X"23", + X"24", X"53", X"1b", X"23", X"24", X"53", X"19", X"a1", + X"00", X"1a", X"5b", X"5b", X"a5", X"69", X"24", X"24", + X"ae", X"ae", X"a8", X"ad", X"29", X"00", X"7c", X"00", + X"15", X"9c", X"6d", X"9c", X"a5", X"69", X"29", X"53", + X"84", X"13", X"34", X"11", X"a5", X"69", X"23", X"a0", + X"d8", X"62", X"5a", X"48", X"26", X"62", X"94", X"88", + X"54", X"44", X"c8", X"54", X"68", X"44", X"e8", X"94", + X"00", X"b4", X"08", X"84", X"74", X"b4", X"28", X"6e", + X"74", X"f4", X"cc", X"4a", X"72", X"f2", X"a4", X"8a", + X"00", X"aa", X"a2", X"a2", X"74", X"74", X"74", X"72", + X"44", X"68", X"b2", X"32", X"b2", X"00", X"22", X"00", + X"1a", X"1a", X"26", X"26", X"72", X"72", X"88", X"c8", + X"c4", X"ca", X"26", X"48", X"44", X"44", X"a2", X"c8", + X"85", X"45", X"68", X"48", X"0a", X"0a", X"0a", X"30", + X"03", X"6c", X"fe", X"03", X"28", X"20", X"4c", X"ff", + X"68", X"85", X"3a", X"68", X"85", X"3b", X"6c", X"f0", + X"03", X"20", X"82", X"f8", X"20", X"da", X"fa", X"4c", + X"65", X"ff", X"d8", X"20", X"84", X"fe", X"20", X"2f", + X"fb", X"20", X"93", X"fe", X"20", X"89", X"fe", X"ad", + X"58", X"c0", X"ad", X"5a", X"c0", X"ad", X"5d", X"c0", + X"ad", X"5f", X"c0", X"ad", X"ff", X"cf", X"2c", X"10", + X"c0", X"d8", X"20", X"3a", X"ff", X"ad", X"f3", X"03", + X"49", X"a5", X"cd", X"f4", X"03", X"d0", X"17", X"ad", + X"f2", X"03", X"d0", X"0f", X"a9", X"e0", X"cd", X"f3", + X"03", X"d0", X"08", X"a0", X"03", X"8c", X"f2", X"03", + X"4c", X"00", X"e0", X"6c", X"f2", X"03", X"20", X"60", + X"fb", X"a2", X"05", X"bd", X"fc", X"fa", X"9d", X"ef", + X"03", X"ca", X"d0", X"f7", X"a9", X"c8", X"86", X"00", + X"85", X"01", X"a0", X"07", X"c6", X"01", X"a5", X"01", + X"c9", X"c0", X"f0", X"d7", X"8d", X"f8", X"07", X"b1", + X"00", X"d9", X"01", X"fb", X"d0", X"ec", X"88", X"88", + X"10", X"f5", X"6c", X"00", X"00", X"ea", X"ea", X"20", + X"8e", X"fd", X"a9", X"45", X"85", X"40", X"a9", X"00", + X"85", X"41", X"a2", X"fb", X"a9", X"a0", X"20", X"ed", + X"fd", X"bd", X"1e", X"fa", X"20", X"ed", X"fd", X"a9", + X"bd", X"20", X"ed", X"fd", X"b5", X"4a", X"20", X"da", + X"fd", X"e8", X"30", X"e8", X"60", X"59", X"fa", X"00", + X"e0", X"45", X"20", X"ff", X"00", X"ff", X"03", X"ff", + X"3c", X"c1", X"d0", X"d0", X"cc", X"c5", X"a0", X"dd", + X"db", X"c4", X"c2", X"c1", X"ff", X"c3", X"ff", X"ff", + X"ff", X"c1", X"d8", X"d9", X"d0", X"d3", X"ad", X"70", + X"c0", X"a0", X"00", X"ea", X"ea", X"bd", X"64", X"c0", + X"10", X"04", X"c8", X"d0", X"f8", X"88", X"60", X"a9", + X"00", X"85", X"48", X"ad", X"56", X"c0", X"ad", X"54", + X"c0", X"ad", X"51", X"c0", X"a9", X"00", X"f0", X"0b", + X"ad", X"50", X"c0", X"ad", X"53", X"c0", X"20", X"36", + X"f8", X"a9", X"14", X"85", X"22", X"a9", X"00", X"85", + X"20", X"a9", X"28", X"85", X"21", X"a9", X"18", X"85", + X"23", X"a9", X"17", X"85", X"25", X"4c", X"22", X"fc", + X"20", X"58", X"fc", X"a0", X"08", X"b9", X"08", X"fb", + X"99", X"0e", X"04", X"88", X"d0", X"f7", X"60", X"ad", + X"f3", X"03", X"49", X"a5", X"8d", X"f4", X"03", X"60", + X"c9", X"8d", X"d0", X"18", X"ac", X"00", X"c0", X"10", + X"13", X"c0", X"93", X"d0", X"0f", X"2c", X"10", X"c0", + X"ac", X"00", X"c0", X"10", X"fb", X"c0", X"83", X"f0", + X"03", X"2c", X"10", X"c0", X"4c", X"fd", X"fb", X"38", + X"4c", X"2c", X"fc", X"a8", X"b9", X"48", X"fa", X"20", + X"97", X"fb", X"20", X"0c", X"fd", X"c9", X"ce", X"b0", + X"ee", X"c9", X"c9", X"90", X"ea", X"c9", X"cc", X"f0", + X"e6", X"d0", X"e8", X"ea", X"ea", X"ea", X"ea", X"ea", + X"ea", X"ea", X"ea", X"ea", X"ea", X"ea", X"ea", X"ea", + X"ea", X"48", X"4a", X"29", X"03", X"09", X"04", X"85", + X"29", X"68", X"29", X"18", X"90", X"02", X"69", X"7f", + X"85", X"28", X"0a", X"0a", X"05", X"28", X"85", X"28", + X"60", X"c9", X"87", X"d0", X"12", X"a9", X"40", X"20", + X"a8", X"fc", X"a0", X"c0", X"a9", X"0c", X"20", X"a8", + X"fc", X"ad", X"30", X"c0", X"88", X"d0", X"f5", X"60", + X"a4", X"24", X"91", X"28", X"e6", X"24", X"a5", X"24", + X"c5", X"21", X"b0", X"66", X"60", X"c9", X"a0", X"b0", + X"ef", X"a8", X"10", X"ec", X"c9", X"8d", X"f0", X"5a", + X"c9", X"8a", X"f0", X"5a", X"c9", X"88", X"d0", X"c9", + X"c6", X"24", X"10", X"e8", X"a5", X"21", X"85", X"24", + X"c6", X"24", X"a5", X"22", X"c5", X"25", X"b0", X"0b", + X"c6", X"25", X"a5", X"25", X"20", X"c1", X"fb", X"65", + X"20", X"85", X"28", X"60", X"49", X"c0", X"f0", X"28", + X"69", X"fd", X"90", X"c0", X"f0", X"da", X"69", X"fd", + X"90", X"2c", X"f0", X"de", X"69", X"fd", X"90", X"5c", + X"d0", X"e9", X"a4", X"24", X"a5", X"25", X"48", X"20", + X"24", X"fc", X"20", X"9e", X"fc", X"a0", X"00", X"68", + X"69", X"00", X"c5", X"23", X"90", X"f0", X"b0", X"ca", + X"a5", X"22", X"85", X"25", X"a0", X"00", X"84", X"24", + X"f0", X"e4", X"a9", X"00", X"85", X"24", X"e6", X"25", + X"a5", X"25", X"c5", X"23", X"90", X"b6", X"c6", X"25", + X"a5", X"22", X"48", X"20", X"24", X"fc", X"a5", X"28", + X"85", X"2a", X"a5", X"29", X"85", X"2b", X"a4", X"21", + X"88", X"68", X"69", X"01", X"c5", X"23", X"b0", X"0d", + X"48", X"20", X"24", X"fc", X"b1", X"28", X"91", X"2a", + X"88", X"10", X"f9", X"30", X"e1", X"a0", X"00", X"20", + X"9e", X"fc", X"b0", X"86", X"a4", X"24", X"a9", X"a0", + X"91", X"28", X"c8", X"c4", X"21", X"90", X"f9", X"60", + X"38", X"48", X"e9", X"01", X"d0", X"fc", X"68", X"e9", + X"01", X"d0", X"f6", X"60", X"e6", X"42", X"d0", X"02", + X"e6", X"43", X"a5", X"3c", X"c5", X"3e", X"a5", X"3d", + X"e5", X"3f", X"e6", X"3c", X"d0", X"02", X"e6", X"3d", + X"60", X"a0", X"4b", X"20", X"db", X"fc", X"d0", X"f9", + X"69", X"fe", X"b0", X"f5", X"a0", X"21", X"20", X"db", + X"fc", X"c8", X"c8", X"88", X"d0", X"fd", X"90", X"05", + X"a0", X"32", X"88", X"d0", X"fd", X"ac", X"20", X"c0", + X"a0", X"2c", X"ca", X"60", X"a2", X"08", X"48", X"20", + X"fa", X"fc", X"68", X"2a", X"a0", X"3a", X"ca", X"d0", + X"f5", X"60", X"20", X"fd", X"fc", X"88", X"ad", X"60", + X"c0", X"45", X"2f", X"10", X"f8", X"45", X"2f", X"85", + X"2f", X"c0", X"80", X"60", X"a4", X"24", X"b1", X"28", + X"48", X"29", X"3f", X"09", X"40", X"91", X"28", X"68", + X"6c", X"38", X"00", X"e6", X"4e", X"d0", X"02", X"e6", + X"4f", X"2c", X"00", X"c0", X"10", X"f5", X"91", X"28", + X"ad", X"00", X"c0", X"2c", X"10", X"c0", X"60", X"20", + X"0c", X"fd", X"20", X"a5", X"fb", X"20", X"0c", X"fd", + X"c9", X"9b", X"f0", X"f3", X"60", X"a5", X"32", X"48", + X"a9", X"ff", X"85", X"32", X"bd", X"00", X"02", X"20", + X"ed", X"fd", X"68", X"85", X"32", X"bd", X"00", X"02", + X"c9", X"88", X"f0", X"1d", X"c9", X"98", X"f0", X"0a", + X"e0", X"f8", X"90", X"03", X"20", X"3a", X"ff", X"e8", + X"d0", X"13", X"a9", X"dc", X"20", X"ed", X"fd", X"20", + X"8e", X"fd", X"a5", X"33", X"20", X"ed", X"fd", X"a2", + X"01", X"8a", X"f0", X"f3", X"ca", X"20", X"35", X"fd", + X"c9", X"95", X"d0", X"02", X"b1", X"28", X"c9", X"e0", + X"90", X"02", X"29", X"df", X"9d", X"00", X"02", X"c9", + X"8d", X"d0", X"b2", X"20", X"9c", X"fc", X"a9", X"8d", + X"d0", X"5b", X"a4", X"3d", X"a6", X"3c", X"20", X"8e", + X"fd", X"20", X"40", X"f9", X"a0", X"00", X"a9", X"ad", + X"4c", X"ed", X"fd", X"a5", X"3c", X"09", X"07", X"85", + X"3e", X"a5", X"3d", X"85", X"3f", X"a5", X"3c", X"29", + X"07", X"d0", X"03", X"20", X"92", X"fd", X"a9", X"a0", + X"20", X"ed", X"fd", X"b1", X"3c", X"20", X"da", X"fd", + X"20", X"ba", X"fc", X"90", X"e8", X"60", X"4a", X"90", + X"ea", X"4a", X"4a", X"a5", X"3e", X"90", X"02", X"49", + X"ff", X"65", X"3c", X"48", X"a9", X"bd", X"20", X"ed", + X"fd", X"68", X"48", X"4a", X"4a", X"4a", X"4a", X"20", + X"e5", X"fd", X"68", X"29", X"0f", X"09", X"b0", X"c9", + X"ba", X"90", X"02", X"69", X"06", X"6c", X"36", X"00", + X"c9", X"a0", X"90", X"02", X"25", X"32", X"84", X"35", + X"48", X"20", X"78", X"fb", X"68", X"a4", X"35", X"60", + X"c6", X"34", X"f0", X"9f", X"ca", X"d0", X"16", X"c9", + X"ba", X"d0", X"bb", X"85", X"31", X"a5", X"3e", X"91", + X"40", X"e6", X"40", X"d0", X"02", X"e6", X"41", X"60", + X"a4", X"34", X"b9", X"ff", X"01", X"85", X"31", X"60", + X"a2", X"01", X"b5", X"3e", X"95", X"42", X"95", X"44", + X"ca", X"10", X"f7", X"60", X"b1", X"3c", X"91", X"42", + X"20", X"b4", X"fc", X"90", X"f7", X"60", X"b1", X"3c", + X"d1", X"42", X"f0", X"1c", X"20", X"92", X"fd", X"b1", + X"3c", X"20", X"da", X"fd", X"a9", X"a0", X"20", X"ed", + X"fd", X"a9", X"a8", X"20", X"ed", X"fd", X"b1", X"42", + X"20", X"da", X"fd", X"a9", X"a9", X"20", X"ed", X"fd", + X"20", X"b4", X"fc", X"90", X"d9", X"60", X"20", X"75", + X"fe", X"a9", X"14", X"48", X"20", X"d0", X"f8", X"20", + X"53", X"f9", X"85", X"3a", X"84", X"3b", X"68", X"38", + X"e9", X"01", X"d0", X"ef", X"60", X"8a", X"f0", X"07", + X"b5", X"3c", X"95", X"3a", X"ca", X"10", X"f9", X"60", + X"a0", X"3f", X"d0", X"02", X"a0", X"ff", X"84", X"32", + X"60", X"a9", X"00", X"85", X"3e", X"a2", X"38", X"a0", + X"1b", X"d0", X"08", X"a9", X"00", X"85", X"3e", X"a2", + X"36", X"a0", X"f0", X"a5", X"3e", X"29", X"0f", X"f0", + X"06", X"09", X"c0", X"a0", X"00", X"f0", X"02", X"a9", + X"fd", X"94", X"00", X"95", X"01", X"60", X"ea", X"ea", + X"4c", X"00", X"e0", X"4c", X"03", X"e0", X"20", X"75", + X"fe", X"20", X"3f", X"ff", X"6c", X"3a", X"00", X"4c", + X"d7", X"fa", X"60", X"ea", X"60", X"ea", X"ea", X"ea", + X"ea", X"ea", X"4c", X"f8", X"03", X"a9", X"40", X"20", + X"c9", X"fc", X"a0", X"27", X"a2", X"00", X"41", X"3c", + X"48", X"a1", X"3c", X"20", X"ed", X"fe", X"20", X"ba", + X"fc", X"a0", X"1d", X"68", X"90", X"ee", X"a0", X"22", + X"20", X"ed", X"fe", X"f0", X"4d", X"a2", X"10", X"0a", + X"20", X"d6", X"fc", X"d0", X"fa", X"60", X"20", X"00", + X"fe", X"68", X"68", X"d0", X"6c", X"20", X"fa", X"fc", + X"a9", X"16", X"20", X"c9", X"fc", X"85", X"2e", X"20", + X"fa", X"fc", X"a0", X"24", X"20", X"fd", X"fc", X"b0", + X"f9", X"20", X"fd", X"fc", X"a0", X"3b", X"20", X"ec", + X"fc", X"81", X"3c", X"45", X"2e", X"85", X"2e", X"20", + X"ba", X"fc", X"a0", X"35", X"90", X"f0", X"20", X"ec", + X"fc", X"c5", X"2e", X"f0", X"0d", X"a9", X"c5", X"20", + X"ed", X"fd", X"a9", X"d2", X"20", X"ed", X"fd", X"20", + X"ed", X"fd", X"a9", X"87", X"4c", X"ed", X"fd", X"a5", + X"48", X"48", X"a5", X"45", X"a6", X"46", X"a4", X"47", + X"28", X"60", X"85", X"45", X"86", X"46", X"84", X"47", + X"08", X"68", X"85", X"48", X"ba", X"86", X"49", X"d8", + X"60", X"20", X"84", X"fe", X"20", X"2f", X"fb", X"20", + X"93", X"fe", X"20", X"89", X"fe", X"d8", X"20", X"3a", + X"ff", X"a9", X"aa", X"85", X"33", X"20", X"67", X"fd", + X"20", X"c7", X"ff", X"20", X"a7", X"ff", X"84", X"34", + X"a0", X"17", X"88", X"30", X"e8", X"d9", X"cc", X"ff", + X"d0", X"f8", X"20", X"be", X"ff", X"a4", X"34", X"4c", + X"73", X"ff", X"a2", X"03", X"0a", X"0a", X"0a", X"0a", + X"0a", X"26", X"3e", X"26", X"3f", X"ca", X"10", X"f8", + X"a5", X"31", X"d0", X"06", X"b5", X"3f", X"95", X"3d", + X"95", X"41", X"e8", X"f0", X"f3", X"d0", X"06", X"a2", + X"00", X"86", X"3e", X"86", X"3f", X"b9", X"00", X"02", + X"c8", X"49", X"b0", X"c9", X"0a", X"90", X"d3", X"69", + X"88", X"c9", X"fa", X"b0", X"cd", X"60", X"a9", X"fe", + X"48", X"b9", X"e3", X"ff", X"48", X"a5", X"31", X"a0", + X"00", X"84", X"31", X"60", X"bc", X"b2", X"be", X"b2", + X"ef", X"c4", X"b2", X"a9", X"bb", X"a6", X"a4", X"06", + X"95", X"07", X"02", X"05", X"f0", X"00", X"eb", X"93", + X"a7", X"c6", X"99", X"b2", X"c9", X"be", X"c1", X"35", + X"8c", X"c4", X"96", X"af", X"17", X"17", X"2b", X"1f", + X"83", X"7f", X"5d", X"cc", X"b5", X"fc", X"17", X"17", + X"f5", X"03", X"fb", X"03", X"62", X"fa", X"59", X"ff", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00", + X"00", X"00", X"00", X"00", X"00", X"00", X"00", X"00"); +begin + +process (clk) + begin + if rising_edge(clk) then + dout <= ROM(TO_INTEGER(addr)); + end if; + end process; + +end rtl; diff --git a/Apple - 2_MiST/rtl/mist_io.v b/Apple - 2_MiST/rtl/mist_io.v new file mode 100644 index 00000000..ad233a3b --- /dev/null +++ b/Apple - 2_MiST/rtl/mist_io.v @@ -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 +// +// 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 . +// +/////////////////////////////////////////////////////////////////////// + +// +// 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<= 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<= 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 diff --git a/Apple - 2_MiST/rtl/osd.v b/Apple - 2_MiST/rtl/osd.v new file mode 100644 index 00000000..c62c10af --- /dev/null +++ b/Apple - 2_MiST/rtl/osd.v @@ -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<> 1) + OSD_Y_OFFSET; +wire [9:0] v_osd_end = v_osd_start + (OSD_HEIGHT<= 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 diff --git a/Apple - 2_MiST/rtl/pll.qip b/Apple - 2_MiST/rtl/pll.qip new file mode 100644 index 00000000..afd958be --- /dev/null +++ b/Apple - 2_MiST/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Apple - 2_MiST/rtl/pll.v b/Apple - 2_MiST/rtl/pll.v new file mode 100644 index 00000000..077dd7c1 --- /dev/null +++ b/Apple - 2_MiST/rtl/pll.v @@ -0,0 +1,376 @@ +// megafunction wizard: %ALTPLL% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altpll + +// ============================================================ +// File Name: pll.v +// Megafunction Name(s): +// altpll +// +// 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. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module pll ( + areset, + inclk0, + c0, + c1, + c2, + locked); + + input areset; + input inclk0; + output c0; + output c1; + output c2; + output locked; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri0 areset; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [4:0] sub_wire0; + wire sub_wire2; + wire [0:0] sub_wire7 = 1'h0; + wire [2:2] sub_wire4 = sub_wire0[2:2]; + wire [0:0] sub_wire3 = sub_wire0[0:0]; + wire [1:1] sub_wire1 = sub_wire0[1:1]; + wire c1 = sub_wire1; + wire locked = sub_wire2; + wire c0 = sub_wire3; + wire c2 = sub_wire4; + wire sub_wire5 = inclk0; + wire [1:0] sub_wire6 = {sub_wire7, sub_wire5}; + + altpll altpll_component ( + .areset (areset), + .inclk (sub_wire6), + .clk (sub_wire0), + .locked (sub_wire2), + .activeclock (), + .clkbad (), + .clkena ({6{1'b1}}), + .clkloss (), + .clkswitch (1'b0), + .configupdate (1'b0), + .enable0 (), + .enable1 (), + .extclk (), + .extclkena ({4{1'b1}}), + .fbin (1'b1), + .fbmimicbidir (), + .fbout (), + .fref (), + .icdrclk (), + .pfdena (1'b1), + .phasecounterselect ({4{1'b1}}), + .phasedone (), + .phasestep (1'b1), + .phaseupdown (1'b1), + .pllena (1'b1), + .scanaclr (1'b0), + .scanclk (1'b0), + .scanclkena (1'b1), + .scandata (1'b0), + .scandataout (), + .scandone (), + .scanread (1'b0), + .scanwrite (1'b0), + .sclkout0 (), + .sclkout1 (), + .vcooverrange (), + .vcounderrange ()); + defparam + altpll_component.bandwidth_type = "AUTO", + altpll_component.clk0_divide_by = 33, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 35, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 66, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 35, + altpll_component.clk1_phase_shift = "0", + altpll_component.clk2_divide_by = 132, + altpll_component.clk2_duty_cycle = 50, + altpll_component.clk2_multiply_by = 35, + altpll_component.clk2_phase_shift = "0", + altpll_component.compensate_clock = "CLK0", + altpll_component.inclk0_input_frequency = 37037, + altpll_component.intended_device_family = "Cyclone III", + altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll", + altpll_component.lpm_type = "altpll", + altpll_component.operation_mode = "NORMAL", + altpll_component.pll_type = "AUTO", + altpll_component.port_activeclock = "PORT_UNUSED", + altpll_component.port_areset = "PORT_USED", + altpll_component.port_clkbad0 = "PORT_UNUSED", + altpll_component.port_clkbad1 = "PORT_UNUSED", + altpll_component.port_clkloss = "PORT_UNUSED", + altpll_component.port_clkswitch = "PORT_UNUSED", + altpll_component.port_configupdate = "PORT_UNUSED", + altpll_component.port_fbin = "PORT_UNUSED", + altpll_component.port_inclk0 = "PORT_USED", + altpll_component.port_inclk1 = "PORT_UNUSED", + altpll_component.port_locked = "PORT_USED", + altpll_component.port_pfdena = "PORT_UNUSED", + altpll_component.port_phasecounterselect = "PORT_UNUSED", + altpll_component.port_phasedone = "PORT_UNUSED", + altpll_component.port_phasestep = "PORT_UNUSED", + altpll_component.port_phaseupdown = "PORT_UNUSED", + altpll_component.port_pllena = "PORT_UNUSED", + altpll_component.port_scanaclr = "PORT_UNUSED", + altpll_component.port_scanclk = "PORT_UNUSED", + altpll_component.port_scanclkena = "PORT_UNUSED", + altpll_component.port_scandata = "PORT_UNUSED", + altpll_component.port_scandataout = "PORT_UNUSED", + altpll_component.port_scandone = "PORT_UNUSED", + altpll_component.port_scanread = "PORT_UNUSED", + altpll_component.port_scanwrite = "PORT_UNUSED", + altpll_component.port_clk0 = "PORT_USED", + altpll_component.port_clk1 = "PORT_USED", + altpll_component.port_clk2 = "PORT_USED", + altpll_component.port_clk3 = "PORT_UNUSED", + altpll_component.port_clk4 = "PORT_UNUSED", + altpll_component.port_clk5 = "PORT_UNUSED", + altpll_component.port_clkena0 = "PORT_UNUSED", + altpll_component.port_clkena1 = "PORT_UNUSED", + altpll_component.port_clkena2 = "PORT_UNUSED", + altpll_component.port_clkena3 = "PORT_UNUSED", + altpll_component.port_clkena4 = "PORT_UNUSED", + altpll_component.port_clkena5 = "PORT_UNUSED", + altpll_component.port_extclk0 = "PORT_UNUSED", + altpll_component.port_extclk1 = "PORT_UNUSED", + altpll_component.port_extclk2 = "PORT_UNUSED", + altpll_component.port_extclk3 = "PORT_UNUSED", + altpll_component.self_reset_on_loss_lock = "OFF", + altpll_component.width_clock = 5; + + +endmodule + +// ============================================================ +// 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 "33" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "66" +// Retrieval info: PRIVATE: DIV_FACTOR2 NUMERIC "132" +// 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: EFF_OUTPUT_FREQ_VALUE0 STRING "28.636364" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "14.318182" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE2 STRING "7.159091" +// 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 "1" +// 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: 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: MULT_FACTOR0 NUMERIC "35" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "35" +// Retrieval info: PRIVATE: MULT_FACTOR2 NUMERIC "35" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "28.63636000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "14.31818000" +// Retrieval info: PRIVATE: OUTPUT_FREQ2 STRING "7.15909000" +// 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_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT2 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_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "ps" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT2 STRING "ps" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1" +// 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: 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_CLKENA0 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0" +// Retrieval info: PRIVATE: USE_CLKENA2 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 "33" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "35" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "66" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "35" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK2_DIVIDE_BY NUMERIC "132" +// Retrieval info: CONSTANT: CLK2_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK2_MULTIPLY_BY NUMERIC "35" +// Retrieval info: CONSTANT: CLK2_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_USED" +// 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_USED" +// 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_UNUSED" +// 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: SELF_RESET_ON_LOSS_LOCK STRING "OFF" +// 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: areset 0 0 0 0 INPUT GND "areset" +// 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: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0" +// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked" +// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0 +// 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: locked 0 0 0 0 @locked 0 0 0 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v 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.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Apple - 2_MiST/rtl/ram.qip b/Apple - 2_MiST/rtl/ram.qip new file mode 100644 index 00000000..b96c7229 --- /dev/null +++ b/Apple - 2_MiST/rtl/ram.qip @@ -0,0 +1,3 @@ +set_global_assignment -name IP_TOOL_NAME "RAM: 1-PORT" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "ram.v"] diff --git a/Apple - 2_MiST/rtl/ram.v b/Apple - 2_MiST/rtl/ram.v new file mode 100644 index 00000000..5c37f64f --- /dev/null +++ b/Apple - 2_MiST/rtl/ram.v @@ -0,0 +1,172 @@ +// megafunction wizard: %RAM: 1-PORT% +// GENERATION: STANDARD +// VERSION: WM1.0 +// MODULE: altsyncram + +// ============================================================ +// File Name: ram.v +// 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. + + +// synopsys translate_off +`timescale 1 ps / 1 ps +// synopsys translate_on +module ram ( + address, + clock, + data, + wren, + q); + + input [13:0] address; + input clock; + input [15:0] data; + input wren; + output [15:0] q; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_off +`endif + tri1 clock; +`ifndef ALTERA_RESERVED_QIS +// synopsys translate_on +`endif + + wire [15:0] sub_wire0; + wire [15:0] q = sub_wire0[15:0]; + + altsyncram altsyncram_component ( + .address_a (address), + .clock0 (clock), + .data_a (data), + .wren_a (wren), + .q_a (sub_wire0), + .aclr0 (1'b0), + .aclr1 (1'b0), + .address_b (1'b1), + .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 (1'b1), + .eccstatus (), + .q_b (), + .rden_a (1'b1), + .rden_b (1'b1), + .wren_b (1'b0)); + defparam + altsyncram_component.clock_enable_input_a = "BYPASS", + altsyncram_component.clock_enable_output_a = "BYPASS", + altsyncram_component.intended_device_family = "Cyclone III", + altsyncram_component.lpm_hint = "ENABLE_RUNTIME_MOD=NO", + altsyncram_component.lpm_type = "altsyncram", + altsyncram_component.numwords_a = 16384, + altsyncram_component.operation_mode = "SINGLE_PORT", + altsyncram_component.outdata_aclr_a = "NONE", + altsyncram_component.outdata_reg_a = "CLOCK0", + altsyncram_component.power_up_uninitialized = "FALSE", + altsyncram_component.read_during_write_mode_port_a = "NEW_DATA_NO_NBE_READ", + altsyncram_component.widthad_a = 14, + altsyncram_component.width_a = 16, + altsyncram_component.width_byteena_a = 1; + + +endmodule + +// ============================================================ +// 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: AclrData 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 "1" +// 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: DataBusSeparated NUMERIC "1" +// 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 "" +// Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "16384" +// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0" +// Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3" +// Retrieval info: PRIVATE: RegAddr NUMERIC "1" +// Retrieval info: PRIVATE: RegData 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 "1" +// Retrieval info: PRIVATE: WRCONTROL_ACLR_A NUMERIC "0" +// Retrieval info: PRIVATE: WidthAddr NUMERIC "14" +// Retrieval info: PRIVATE: WidthData NUMERIC "16" +// Retrieval info: PRIVATE: rden NUMERIC "0" +// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all +// Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS" +// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS" +// 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 "SINGLE_PORT" +// Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE" +// Retrieval info: CONSTANT: OUTDATA_REG_A STRING "CLOCK0" +// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "FALSE" +// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_PORT_A STRING "NEW_DATA_NO_NBE_READ" +// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "14" +// Retrieval info: CONSTANT: WIDTH_A NUMERIC "16" +// 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: data 0 0 16 0 INPUT NODEFVAL "data[15..0]" +// Retrieval info: USED_PORT: q 0 0 16 0 OUTPUT NODEFVAL "q[15..0]" +// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT NODEFVAL "wren" +// 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: @data_a 0 0 16 0 data 0 0 16 0 +// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0 +// Retrieval info: CONNECT: q 0 0 16 0 @q_a 0 0 16 0 +// Retrieval info: GEN_FILE: TYPE_NORMAL ram.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL ram_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf diff --git a/Apple - 2_MiST/rtl/roms/apple_II.rom b/Apple - 2_MiST/rtl/roms/apple_II.rom new file mode 100644 index 00000000..cb94b9f0 Binary files /dev/null and b/Apple - 2_MiST/rtl/roms/apple_II.rom differ diff --git a/Apple - 2_MiST/rtl/roms/bios.a65 b/Apple - 2_MiST/rtl/roms/bios.a65 new file mode 100644 index 00000000..393d28db --- /dev/null +++ b/Apple - 2_MiST/rtl/roms/bios.a65 @@ -0,0 +1,255 @@ +; Trivial BIOS for an Apple II+ -- just enough to show the hardware works +; +; Stephen A. Edwards +; +; Assemble with "xa -A 53248 -bt 53248 ..." to start the code at $D000 + +gbasl = $26 +gbash = $27 +basl = $28 +bash = $29 + +text = $400 ; start of text/lores screen memory +bhires = $2000 ; start of hires screen memory +line8 = $428 +line9 = $4A8 +line10 = $528 +line11 = $5A8 + +line23 = $7D0 + +keyboard = $C000 +key_strobe = $C010 + +spkr = $C030 +grset = $C050 +txtset = $C051 +nomix = $C052 +mix = $C053 +page1 = $C054 +page2 = $C055 +lores = $C056 +hires = $C057 + +nmi_vector = $FFFA +nmi = reset +irq = reset + +reset: + cld + lda txtset + lda page1 + +; Clear the text screen + + lda #text + sta gbash + ldy #0 + ldx #4 + lda #$A0 ; Normal space +l0 + sta (gbasl),y + dey + bne l0 + inc gbash + dex + bne l0 + +; Play three tones + + ldy #0 +tone1 + lda #15 + jsr wait + sta spkr + dey + bne tone1 + +tone2 + lda #12 + jsr wait + sta spkr + dey + bne tone2 + +tone3 + lda #8 + jsr wait + sta spkr + dey + bne tone3 + +; Print some messages + lda #text + sta gbash + lda #hello + sta bash + jsr write_string + + lda #roms1 + sta bash + jsr write_string + + lda #line10 + sta gbash + lda #roms2 + sta bash + jsr write_string + + lda #line11 + sta gbash + lda #roms3 + sta bash + jsr write_string + + lda #line23 + sta gbash + lda #press + sta bash + jsr write_string + +wait_for_key + bit keyboard + bpl wait_for_key + sta key_strobe + +; Set lores mode + sta lores + sta nomix + sta grset + +; Fill the screen with colors + lda #0 +fill + ldx #text + stx gbash + ldy #0 + ldx #4 +l2 + sta (gbasl),y + adc #1 + dey + bne l2 + inc gbash + dex + bne l2 + + adc #1 + + bit keyboard + bpl fill + sta key_strobe + +; Wait for another keypress + +wait_key1 + bit keyboard + bpl wait_key1 + sta key_strobe + +; Set hires mode + sta hires + +; Fill the screen with colors + lda #0 +fillh + ldx #bhires + stx gbash + ldy #0 + ldx #$20 +l3 + sta (gbasl),y + adc #1 + dey + bne l3 + inc gbash + dex + bne l3 + + adc #1 + + bit keyboard + bpl fillh + sta key_strobe + +; Wait for another keypress + +wait_key2 + bit keyboard + bpl wait_key2 + sta key_strobe + + jmp reset + +done + rts +write_string + ldy #0 +l1 + lda (basl),y + beq done + ora #$80 + sta (gbasl),y + iny + bne l1 + rts + +; A quadratic delay + +wait sec +wait2 pha +wait3 sbc #1 + bne wait3 + pla + sbc #1 + bne wait2 + rts + + +hello .asc "APPLE2FPGA" + .byt 0 + +roms1 .asc "THIS IS NOT APPLE'S BIOS" + .byt 0 + +roms2 .asc "TO RUN APPLE PROGRAMS, GET A COPY OF THE" + .byt 0 + +roms3 .asc "ACTUAL APPLE II ROMS (D000-FFFF)" + .byt 0 + +press .asc "PRESS ANY KEY TO ADVANCE" + .byt 0 + +; Pad to the start of the NMI vector +here .dsb (nmi_vector - here) + + .word nmi + .word reset + .word irq diff --git a/Apple - 2_MiST/rtl/roms/bios.rom b/Apple - 2_MiST/rtl/roms/bios.rom new file mode 100644 index 00000000..2fefadd0 Binary files /dev/null and b/Apple - 2_MiST/rtl/roms/bios.rom differ diff --git a/Apple - 2_MiST/rtl/roms/slot6.rom b/Apple - 2_MiST/rtl/roms/slot6.rom new file mode 100644 index 00000000..56698b0f Binary files /dev/null and b/Apple - 2_MiST/rtl/roms/slot6.rom differ diff --git a/Apple - 2_MiST/rtl/scan_converter.vhd b/Apple - 2_MiST/rtl/scan_converter.vhd new file mode 100644 index 00000000..f3925b3b --- /dev/null +++ b/Apple - 2_MiST/rtl/scan_converter.vhd @@ -0,0 +1,229 @@ +-- (c) 2012 d18c7db(a)hotmail +-- +-- This program is free software; you can redistribute it and/or modify it under +-- the terms of the GNU General Public License version 3 or, at your option, +-- any later version as published by the Free Software Foundation. +-- +-- This program 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. +-- +-- For full details, see the GNU General Public License at www.gnu.org/licenses + +-------------------------------------------------------------------------------- +-- Video scan converter +-- +-- Horizonal Timing +-- _____________ ______________________ _____________________ +-- VIDEO (last) |____________| VIDEO |____________| VIDEO (next) +-- -hD----------|-hA-|hB|-hC-|----------hD----------|-hA-|hB|-hC-|----------hD--------- +-- __________________| |________________________________| |__________________________ +-- HSYNC |__| HSYNC |__| HSYNC + +-- Vertical Timing +-- _____________ ______________________ _____________________ +-- VIDEO (last)||____________||||||||||VIDEO|||||||||____________||||||||||VIDEO (next) +-- -vD----------|-vA-|vB|-vC-|----------vD----------|-vA-|vB|-vC-|----------vD--------- +-- __________________| |________________________________| |__________________________ +-- VSYNC |__| VSYNC |__| VSYNC + +-- Scan converter input and output timings compared to standard VGA +-- Resolution - Frame | Pixel | Front | HSYNC | Back | Active | HSYNC | Front | VSYNC | Back | Active | VSYNC +-- - Rate | Clock | Porch hA | Pulse hB | Porch hC | Video hD | Polarity | Porch vA | Pulse vB | Porch vC | Video vD | Polarity +------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- In 256x224 - 59.18Hz | 6.000 MHz | 38 pixels | 32 pixels | 58 pixels | 256 pixels | negative | 16 lines | 8 lines | 16 lines | 224 lines | negative +-- Out 640x480 - 59.18Hz | 24.000 MHz | 2 pixels | 92 pixels | 34 pixels | 640 pixels | negative | 17 lines | 2 lines | 29 lines | 480 lines | negative +-- VGA 640x480 - 59.94Hz | 25.175 MHz | 16 pixels | 96 pixels | 48 pixels | 640 pixels | negative | 10 lines | 2 lines | 33 lines | 480 lines | negative + +library ieee; + use ieee.std_logic_1164.all; + use ieee.std_logic_unsigned.all; + use ieee.numeric_std.all; + +--pragma translate_off + use ieee.std_logic_textio.all; + use std.textio.all; +--pragma translate_on + +entity VGA_SCANCONV is + generic ( + cstart : integer range 0 to 1023 := 144; -- composite sync start + clength : integer range 0 to 1023 := 640; -- composite sync length + + hA : integer range 0 to 1023 := 16; -- h front porch + hB : integer range 0 to 1023 := 96; -- h sync + hC : integer range 0 to 1023 := 48; -- h back porch + hD : integer range 0 to 1023 := 640; -- visible video + +-- vA : integer range 0 to 1023 := 16; -- v front porch + vB : integer range 0 to 1023 := 2; -- v sync + vC : integer range 0 to 1023 := 33; -- v back porch + vD : integer range 0 to 1023 := 480; -- visible video + + hpad : integer range 0 to 1023 := 0; -- H black border + vpad : integer range 0 to 1023 := 0 -- V black border + ); + port ( + I_VIDEO : in std_logic_vector(15 downto 0); + I_HSYNC : in std_logic; + I_VSYNC : in std_logic; + -- + O_VIDEO : out std_logic_vector(15 downto 0); + O_HSYNC : out std_logic; + O_VSYNC : out std_logic; + O_CMPBLK_N : out std_logic; + -- + CLK : in std_logic; + CLK_x2 : in std_logic + ); +end; + +architecture RTL of VGA_SCANCONV is + -- + -- input timing + -- + signal ivsync_last_x2 : std_logic := '1'; + signal ihsync_last : std_logic := '1'; + signal hpos_i : std_logic_vector( 9 downto 0) := (others => '0'); + + -- + -- output timing + -- + signal hpos_o : std_logic_vector(9 downto 0) := (others => '0'); + + signal vcnt : integer range 0 to 1023 := 0; + signal hcnt : integer range 0 to 1023 := 0; + signal hcnti : integer range 0 to 1023 := 0; + + signal CLK_x2_n : std_logic := '1'; + +begin + -- dual port line buffer, max line of 1024 pixels + u_ram : entity work.RAMB16_S18_S18 +-- generic map (INIT_A => X"00000", INIT_B => X"00000", SIM_COLLISION_CHECK => "ALL") -- "NONE", "WARNING", "GENERATE_X_ONLY", "ALL" + port map ( + -- input + q_a => open, + data_a => I_VIDEO, + + + address_a => hpos_i, + wren_a => '1', + rden_a => CLK, + + clock_a => CLK_x2, + + -- output + q_b => O_VIDEO, + data_b => x"0000", + + + address_b => hpos_o, + wren_b => '0', + rden_b => '1', + + clock_b => CLK_x2_n + ); + + CLK_x2_n <= not CLK_x2; + + -- horizontal counter for input video + p_hcounter : process + begin + wait until rising_edge(CLK_x2); + if CLK = '0' then + ihsync_last <= I_HSYNC; + + -- trigger off rising hsync + if I_HSYNC = '1' and ihsync_last = '0' then + hcnti <= 0; + else + hcnti <= hcnti + 1; + end if; + end if; + end process; + + -- increment write position during active video + p_ram_in : process + begin + wait until rising_edge(CLK_x2); + if CLK = '0' then + if (hcnti < cstart) or (hcnti >= (cstart + clength)) then + hpos_i <= (others => '0'); + else + hpos_i <= hpos_i + 1; + end if; + end if; + end process; + + -- VGA H and V counters, synchronized to input frame V sync, then H sync + p_out_ctrs : process + variable trigger : boolean; + begin + wait until rising_edge(CLK_x2); + ivsync_last_x2 <= I_VSYNC; + + if (I_VSYNC = '0') and (ivsync_last_x2 = '1') then + trigger := true; + elsif trigger and I_HSYNC = '0' then + trigger := false; + hcnt <= 0; + vcnt <= 0; + else + hcnt <= hcnt + 1; + if hcnt = (hA+hB+hC+hD+hpad+hpad-1) then + hcnt <= 0; + vcnt <= vcnt + 1; + end if; + end if; + end process; + + -- generate hsync + p_gen_hsync : process + begin + wait until rising_edge(CLK_x2); + -- H sync timing + if (hcnt < hB) then + O_HSYNC <= '0'; + else + O_HSYNC <= '1'; + end if; + end process; + + -- generate vsync + p_gen_vsync : process + begin + wait until rising_edge(CLK_x2); + -- V sync timing + if (vcnt < vB) then + O_VSYNC <= '0'; + else + O_VSYNC <= '1'; + end if; + end process; + + -- generate active output video + p_gen_active_vid : process + begin + wait until rising_edge(CLK_x2); + -- visible video area doubled from the original game + if ((hcnt >= (hB + hC + hpad)) and (hcnt < (hB + hC + hD + hpad))) and ((vcnt > 2*(vB + vC + vpad)) and (vcnt <= 2*(vB + vC + vD + vpad))) then + hpos_o <= hpos_o + 1; + else + hpos_o <= (others => '0'); + end if; + end process; + + -- generate blanking signal including additional borders to pad the input signal to standard VGA resolution + p_gen_blank : process + begin + wait until rising_edge(CLK_X2); + -- active video area 640x480 (VGA) after padding with blank borders + if ((hcnt >= (hB + hC)) and (hcnt < (hB + hC + hD + 2*hpad))) and ((vcnt > 2*(vB + vC)) and (vcnt <= 2*(vB + vC + vD + 2*vpad))) then + O_CMPBLK_N <= '1'; + else + O_CMPBLK_N <= '0'; + end if; + end process; + +end architecture RTL; diff --git a/Apple - 2_MiST/rtl/scandoubler.v b/Apple - 2_MiST/rtl/scandoubler.v new file mode 100644 index 00000000..0213d20c --- /dev/null +++ b/Apple - 2_MiST/rtl/scandoubler.v @@ -0,0 +1,195 @@ +// +// scandoubler.v +// +// Copyright (c) 2015 Till Harbaum +// 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 . + +// 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 diff --git a/Apple - 2_MiST/rtl/spi_controller.vhd b/Apple - 2_MiST/rtl/spi_controller.vhd new file mode 100644 index 00000000..24a6489b --- /dev/null +++ b/Apple - 2_MiST/rtl/spi_controller.vhd @@ -0,0 +1,471 @@ +------------------------------------------------------------------------------- +-- +-- SD/MMC interface (SPI-style) for the Apple ][ Emulator +-- +-- Michel Stempin (michel.stempin@wanadoo.fr) +-- Working with MMC/SD/SDHC cards +-- +-- From previous work by: +-- Stephen A. Edwards (sedwards@cs.columbia.edu) +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity spi_controller is + generic ( + BLOCK_SIZE : natural := 512; + BLOCK_BITS : natural := 9; + TRACK_SIZE : natural := 16#1A00# + ); + + port ( + -- Card Interface --------------------------------------------------------- + CS_N : out std_logic; -- MMC chip select + MOSI : out std_logic; -- Data to card (master out slave in) + MISO : in std_logic; -- Data from card (master in slave out) + SCLK : out std_logic; -- Card clock + -- Track buffer Interface ------------------------------------------------- + ram_write_addr : out unsigned(13 downto 0); + ram_di : out unsigned(7 downto 0); + ram_we : out std_logic; + track : in unsigned(5 downto 0); -- Track number (0-34) + image : in unsigned(9 downto 0); -- Which disk image to read + -- System Interface ------------------------------------------------------- + CLK_14M : in std_logic; -- System clock + reset : in std_logic + ); + +end spi_controller; + +architecture rtl of spi_controller is + + ----------------------------------------------------------------------------- + -- States of the combined MMC/SD/SDHC reset, track and command FSM + -- + type states is ( + -- Reset FSM + POWER_UP, + RAMP_UP, + CHECK_CMD0, + CHECK_CMD8, + CHECK_CMD55, + CHECK_ACMD41, + CHECK_CMD1, + CHECK_CMD58, + CHECK_SET_BLOCKLEN, + ERROR, + -- Track read FSM + IDLE, + READ_TRACK, + READ_BLOCK_WAIT, + READ_BLOCK_DATA, + READ_BLOCK_CRC, + -- SD command embedded FSM + WAIT_NRC, + SEND_CMD, + RECEIVE_BYTE_WAIT, + RECEIVE_BYTE); + -- + signal state, return_state : states; + -- + ----------------------------------------------------------------------------- + + signal slow_clk : boolean := true; + signal spi_clk : std_logic; + signal sclk_sig : std_logic; + + signal current_track : unsigned(5 downto 0); + signal current_image : unsigned(9 downto 0); + signal write_addr : unsigned(13 downto 0); + + signal command : std_logic_vector(5 downto 0); + signal argument : std_logic_vector(31 downto 0); + signal crc7 : std_logic_vector(6 downto 0); + signal command_out : std_logic_vector(55 downto 0); + signal recv_bytes : unsigned(39 downto 0); + type versions is (MMC, SD1x, SD2x); + signal version : versions; + signal high_capacity : boolean; + +begin + + ram_write_addr <= write_addr; + + ----------------------------------------------------------------------------- + -- Process var_clkgen + -- + -- Purpose: + -- Implements the variable speed clock for MMC compatibility. + -- If slow_clk is false, spi_clk == CLK_14M, thus SCLK = 7M + -- If slow_clk is true, spi_clk = CLK_14M / 32 and SCLK = 223.214kHz, which + -- is between 100kHz and 400kHz, as required for MMC compatibility. + -- + var_clkgen : process (CLK_14M, slow_clk) + variable var_clk : unsigned(4 downto 0) := (others => '0'); + begin + if slow_clk then + spi_clk <= var_clk(4); + if rising_edge(CLK_14M) then + var_clk := var_clk + 1; + end if; + else + spi_clk <= CLK_14M; + end if; + end process; + + SCLK <= sclk_sig; + -- + ----------------------------------------------------------------------------- + + + ----------------------------------------------------------------------------- + -- Process sd_fsm + -- + -- Purpose: + -- Implements the combined "SD Card init", "track read" and "command" FSMs. + -- + sd_fsm : process(spi_clk) + subtype cmd_t is std_logic_vector(5 downto 0); + constant CMD0 : cmd_t := std_logic_vector(to_unsigned(0, 6)); + constant CMD1 : cmd_t := std_logic_vector(to_unsigned(1, 6)); + constant CMD8 : cmd_t := std_logic_vector(to_unsigned(8, 6)); + constant CMD16 : cmd_t := std_logic_vector(to_unsigned(16, 6)); + constant CMD17 : cmd_t := std_logic_vector(to_unsigned(17, 6)); + constant CMD55 : cmd_t := std_logic_vector(to_unsigned(55, 6)); + constant CMD58 : cmd_t := std_logic_vector(to_unsigned(58, 6)); + constant ACMD41 : cmd_t := std_logic_vector(to_unsigned(41, 6)); + variable counter : unsigned(7 downto 0); + variable byte_counter : unsigned(BLOCK_BITS - 1 downto 0); + variable lba : unsigned(31 downto 0); + + begin + if rising_edge(spi_clk) then + ram_we <= '0'; + if reset = '1' then + state <= POWER_UP; + -- Deliberately out of range + current_track <= (others => '1'); + current_image <= (others => '1'); + sclk_sig <= '0'; + slow_clk <= true; + CS_N <= '1'; + command <= (others => '0'); + argument <= (others => '0'); + crc7 <= (others => '0'); + command_out <= (others => '1'); + counter := TO_UNSIGNED(0, 8); + byte_counter := TO_UNSIGNED(0, BLOCK_BITS); + write_addr <= (others => '0'); + high_capacity <= false; + version <= MMC; + lba := (others => '0'); + else + case state is + + --------------------------------------------------------------------- + -- SD Card init FSM + --------------------------------------------------------------------- + when POWER_UP => + counter := TO_UNSIGNED(224, 8); + state <= RAMP_UP; + + -- Output a series of 74 clock signals (or 1ms delay, whichever is + -- greater) to wake up the card + when RAMP_UP => + if counter = 0 then + CS_N <= '0'; + command <= CMD0; + argument <= (others => '0'); + crc7 <= "1001010"; + return_state <= CHECK_CMD0; + state <= WAIT_NRC; + else + counter := counter - 1; + sclk_sig <= not sclk_sig; + end if; + + -- CMD0: GO_IDLE_STATE ---------------------------------------------- + when CHECK_CMD0 => + if recv_bytes(7 downto 0) = x"01" then + command <= CMD8; + -- Propose 2.7-3.6V operating voltage and a "10101010" test pattern + argument <= x"000001aa"; + crc7 <= "1000011"; + return_state <= CHECK_CMD8; + state <= WAIT_NRC; + else + state <= ERROR; + end if; + + -- CMD8: SEND_IF_COND ----------------------------------------------- + when CHECK_CMD8 => + argument <= (others => '0'); + crc7 <= (others => '0'); + if recv_bytes(39 downto 32) <= x"01" then + -- This is an SD 2.x/3.x Card + version <= SD2x; + if recv_bytes(11 downto 8) /= "0001" or recv_bytes(7 downto 0) /= x"aa" then + -- Operating voltage or pattern check failure + state <= ERROR; + else + command <= CMD55; + high_capacity <= true; + return_state <= CHECK_CMD55; + state <= WAIT_NRC; + end if; + else + -- This is an MMC Card or an SD 1.x Card + version <= SD1x; + high_capacity <= false; + command <= CMD55; + return_state <= CHECK_CMD55; + state <= WAIT_NRC; + end if; + + -- CMD55: APP_CMD --------------------------------------------------- + when CHECK_CMD55 => + if recv_bytes(7 downto 0) = x"01" then + -- This is an SD Card + command <= ACMD41; + if high_capacity then + -- Ask for HCS (High Capacity Support) + argument <= x"40000000"; + end if; + return_state <= CHECK_ACMD41; + state <= WAIT_NRC; + else + -- This is an MMC Card + version <= MMC; + command <= CMD1; + return_state <= CHECK_CMD1; + state <= WAIT_NRC; + end if; + + -- ACMD41: SEND_OP_CMD (SD Card) ------------------------------------ + when CHECK_ACMD41 => + if recv_bytes(7 downto 0) = x"00" then + if version = SD2x then + -- This is an SD 2.x/3.x Card, read OCR + command <= CMD58; + argument <= (others => '0'); + return_state <= CHECK_CMD58; + state <= WAIT_NRC; + else + -- This is an SD 1.x Card, no HCS + command <= CMD16; + argument <= std_logic_vector(to_unsigned(BLOCK_SIZE, 32)); + return_state <= CHECK_SET_BLOCKLEN; + state <= WAIT_NRC; + end if; + elsif recv_bytes(7 downto 0) = x"01" then + -- Wait until the card goes out of idle state + command <= CMD55; + argument <= (others => '0'); + return_state <= CHECK_CMD55; + state <= WAIT_NRC; + else + -- Found an MMC card that understands CMD55, but not ACMD41 + command <= CMD1; + return_state <= CHECK_CMD1; + state <= WAIT_NRC; + end if; + + -- CMD1: SEND_OP_CMD (MMC Card) ------------------------------------- + when CHECK_CMD1 => + if recv_bytes(7 downto 0) <= x"01" then + command <= CMD16; + argument <= std_logic_vector(to_unsigned(BLOCK_SIZE, 32)); + return_state <= CHECK_SET_BLOCKLEN; + state <= WAIT_NRC; + else + -- Wait until the card goes out of idle state + command <= CMD1; + return_state <= CHECK_CMD1; + state <= WAIT_NRC; + end if; + + -- CMD58: READ_OCR -------------------------------------------------- + when CHECK_CMD58 => + if recv_bytes(7 downto 0) = x"00" then + if recv_bytes(30) = '1' then + high_capacity <= true; + else + high_capacity <= false; + end if; + command <= CMD16; + argument <= std_logic_vector(to_unsigned(BLOCK_SIZE, 32)); + return_state <= CHECK_SET_BLOCKLEN; + state <= WAIT_NRC; + else + state <= ERROR; + end if; + + -- CMD16: SET_BLOCKLEN (BLOCK_SIZE) --------------------------------- + when CHECK_SET_BLOCKLEN => + if recv_bytes(7 downto 0) = x"00" then + slow_clk <= false; + state <= IDLE; + else + state <= ERROR; + end if; + + -- Error state ------------------------------------------------------ + when ERROR => + sclk_sig <= '0'; + slow_clk <= true; + CS_N <= '1'; + + --------------------------------------------------------------------- + -- Embedded "read track" FSM + --------------------------------------------------------------------- + -- Idle state where we sit waiting for user image/track requests ---- + when IDLE => + if track /= current_track or image /= current_image then + -- Compute the LBA (Logical Block Address) from the given + -- image/track numbers. + -- Each Apple ][ floppy image contains 35 tracks, each consisting of + -- 16 x 256-byte sectors. + -- However, because of inter-sector gaps and address fields in + -- raw mode, the actual length is set to 0x1A00, so each image is + -- actually $1A00 bytes * 0x23 tracks = 0x38E00 bytes. + -- So: lba = image * 0x38E00 + track * 0x1A00 + -- In order to avoid multiplications by constants, we replace + -- them by direct add/sub of shifted image/track values: + -- 0x38E00 = 0011 1000 1110 0000 0000 + -- = 0x40000 - 0x8000 + 0x1000 - 0x200 + -- 0x01A00 = 0000 0001 1010 0000 0000 + -- = 0x1000 + 0x800 + 0x200 + lba := ("0000" & image & "000000000000000000") - + ( image & "000000000000000") + + ( image & "000000000000") - + ( image & "000000000") + + ( track & "000000000") + + ( track & "00000000000") + + ( track & "000000000000"); + if high_capacity then + -- For SDHC, blocks are addressed by blocks, not bytes + lba := lba srl BLOCK_BITS; + end if; + write_addr <= (others => '0'); + CS_N <= '0'; + state <= READ_TRACK; + current_track <= track; + current_image <= image; + else + CS_N <= '1'; + sclk_sig <= '1'; + end if; + + -- Read in a whole track into buffer memory ------------------------- + when READ_TRACK => + if write_addr = TRACK_SIZE then + state <= IDLE; + else + command <= CMD17; + argument <= std_logic_vector(lba); + return_state <= READ_BLOCK_WAIT; + state <= WAIT_NRC; + end if; + + -- Wait for a 0 bit to signal the start of the block ---------------- + when READ_BLOCK_WAIT => + if sclk_sig = '1' and MISO = '0' then + state <= READ_BLOCK_DATA; + byte_counter := TO_UNSIGNED(BLOCK_SIZE - 1, BLOCK_BITS); + counter := TO_UNSIGNED(7, 8); + return_state <= READ_BLOCK_DATA; + state <= RECEIVE_BYTE; + end if; + sclk_sig <= not sclk_sig; + + -- Read a block of data --------------------------------------------- + when READ_BLOCK_DATA => + ram_we <= '1'; + write_addr <= write_addr + 1; + if byte_counter = 0 then + counter := TO_UNSIGNED(7, 8); + return_state <= READ_BLOCK_CRC; + state <= RECEIVE_BYTE; + else + byte_counter := byte_counter - 1; + counter := TO_UNSIGNED(7, 8); + return_state <= READ_BLOCK_DATA; + state <= RECEIVE_BYTE; + end if; + + -- Read the block CRC ----------------------------------------------- + when READ_BLOCK_CRC => + counter := TO_UNSIGNED(7, 8); + return_state <= READ_TRACK; + if high_capacity then + lba := lba + 1; + else + lba := lba + BLOCK_SIZE; + end if; + state <= RECEIVE_BYTE; + + --------------------------------------------------------------------- + -- Embedded "command" FSM + --------------------------------------------------------------------- + -- Wait for card response in front of host command ------------------ + when WAIT_NRC => + counter := TO_UNSIGNED(63, 8); + command_out <= "11111111" & "01" & command & argument & crc7 & "1"; + sclk_sig <= not sclk_sig; + state <= SEND_CMD; + + -- Send a command to the card --------------------------------------- + when SEND_CMD => + if sclk_sig = '1' then + if counter = 0 then + state <= RECEIVE_BYTE_WAIT; + else + counter := counter - 1; + command_out <= command_out(54 downto 0) & "1"; + end if; + end if; + sclk_sig <= not sclk_sig; + + -- Wait for a "0", indicating the first bit of a response ----------- + when RECEIVE_BYTE_WAIT => + if sclk_sig = '1' then + if MISO = '0' then + recv_bytes <= (others => '0'); + if command = CMD8 or command = CMD58 then + -- This is an R7 response, but we already have read bit 39 + counter := TO_UNSIGNED(38,8); + else + -- This is a data byte or an r1 response, but we already read + -- bit 7 + counter := TO_UNSIGNED(6, 8); + end if; + state <= RECEIVE_BYTE; + end if; + end if; + sclk_sig <= not sclk_sig; + + -- Receive a byte --------------------------------------------------- + when RECEIVE_BYTE => + if sclk_sig = '1' then + recv_bytes <= recv_bytes(38 downto 0) & MISO; + if counter = 0 then + state <= return_state; + ram_di <= recv_bytes(6 downto 0) & MISO; + else + counter := counter - 1; + end if; + end if; + sclk_sig <= not sclk_sig; + + when others => null; + end case; + end if; + end if; + end process sd_fsm; + + MOSI <= command_out(55); + +end rtl; diff --git a/Apple - 2_MiST/rtl/timing_generator.vhd b/Apple - 2_MiST/rtl/timing_generator.vhd new file mode 100644 index 00000000..2612b89b --- /dev/null +++ b/Apple - 2_MiST/rtl/timing_generator.vhd @@ -0,0 +1,150 @@ +------------------------------------------------------------------------------- +-- +-- Apple ][ Timing logic +-- +-- Stephen A. Edwards, sedwards@cs.columbia.edu +-- +-- Taken more-or-less verbatim from the schematics in the +-- Apple ][ reference manual +-- +-- This takes a 14.31818 MHz master clock and divides it down to generate +-- the various lower-frequency signals (e.g., 7M, phase 0, colorburst) +-- as well as horizontal and vertical blanking and sync signals for the video +-- and the video addresses. +-- +------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity timing_generator is + + port ( + CLK_14M : in std_logic; -- 14.31818 MHz master clock + CLK_7M : buffer std_logic := '0'; + Q3 : buffer std_logic := '0'; -- 2 MHz signal in phase with PHI0 + RAS_N : buffer std_logic := '0'; + CAS_N : buffer std_logic := '0'; + AX : buffer std_logic := '0'; + PHI0 : buffer std_logic := '0'; -- 1.0 MHz processor clock + PRE_PHI0 : buffer std_logic := '0'; -- One 14M cycle before + COLOR_REF : buffer std_logic := '0'; -- 3.579545 MHz colorburst + + TEXT_MODE : in std_logic; + PAGE2 : in std_logic; + HIRES : in std_logic; + + VIDEO_ADDRESS : out unsigned(15 downto 0); + H0 : out std_logic; + VA : out std_logic; -- Character row address + VB : out std_logic; + VC : out std_logic; + V2 : out std_logic; + V4 : out std_logic; + HBL : buffer std_logic; -- Horizontal blanking + VBL : buffer std_logic; -- Vertical blanking + BLANK : out std_logic; -- Composite blanking + LDPS_N : out std_logic; + LD194 : out std_logic + ); + +end timing_generator; + +architecture rtl of timing_generator is + + signal H : unsigned(6 downto 0) := "0000000"; + signal V : unsigned(8 downto 0) := "011111010"; + signal COLOR_DELAY_N : std_logic; + +begin + + -- To generate the once-a-line hiccup: D1 pin 6 + COLOR_DELAY_N <= + not (not COLOR_REF and (not AX and not CAS_N) and PHI0 and not H(6)); + + -- The DRAM signal generator + C2_74S195: process (CLK_14M) + begin + if rising_edge(CLK_14M) then + if Q3 = '1' then -- shift + (Q3, CAS_N, AX, RAS_N) <= + unsigned'(CAS_N, AX, RAS_N, '0'); + else -- load + (Q3, CAS_N, AX, RAS_N) <= + unsigned'(RAS_N, AX, COLOR_DELAY_N, AX); + end if; + end if; + end process; + + -- The main clock signal generator + B1_74S175 : process (CLK_14M) + begin + if rising_edge(CLK_14M) then + COLOR_REF <= CLK_7M xor COLOR_REF; + CLK_7M <= not CLK_7M; + PHI0 <= PRE_PHI0; + if AX = '1' then + PRE_PHI0 <= not (Q3 xor PHI0); -- B1 pin 10 + end if; + end if; + end process; + + LDPS_N <= not (PHI0 and not AX and not CAS_N); + LD194 <= not (PHI0 and not AX and not CAS_N and not CLK_7M); + + -- Four four-bit presettable binary counters + -- Seven-bit horizontal counter counts 0, 40, 41, ..., 7F (65 states) + -- Nine-bit vertical counter counts $FA .. $1FF (262 states) + D11D12D13D14_74LS161 : process (CLK_14M) + begin + if rising_edge(CLK_14M) then + -- True the cycle before the rising edge of LDPS_N: emulates + -- the effects of using LDPS_N as the clock for the video counters + if (PHI0 and not AX and ((Q3 and RAS_N) or + (not Q3 and COLOR_DELAY_N))) = '1' then + if H(6) = '0' then H <= "1000000"; + else + H <= H + 1; + if H = "1111111" then + V <= V + 1; + if V = "111111111" then V <= "011111010"; end if; + end if; + end if; + end if; + end if; + + end process; + + H0 <= H(0); + VA <= V(0); + VB <= V(1); + VC <= V(2); + V2 <= V(5); + V4 <= V(7); + + HBL <= not (H(5) or (H(3) and H(4))); + VBL <= V(6) and V(7); + + BLANK <= HBL or VBL; + + -- V_SYNC <= VBL and V(5) and not V(4) and not V(3) and + -- not V(2) and (H(4) or H(3) or H(5)); + -- H_SYNC <= HBL and H(3) and not H(2); + + -- SYNC <= not (V_SYNC or H_SYNC); + -- COLOR_BURST <= HBL and H(2) and H(3) and (COLOR_REF or TEXT_MODE); + + -- Video address calculation + VIDEO_ADDRESS(2 downto 0) <= H(2 downto 0); + VIDEO_ADDRESS(6 downto 3) <= (not H(5) & V(6) & H(4) & H(3)) + + ( V(7) & not H(5) & V(7) & '1') + + ( "000" & V(6)); + VIDEO_ADDRESS(9 downto 7) <= V(5 downto 3); + VIDEO_ADDRESS(14 downto 10) <= + ( "00" & HBL & PAGE2 & not PAGE2) when HIRES = '0' else + (PAGE2 & not PAGE2 & V(2 downto 0)); + + VIDEO_ADDRESS(15) <= '0'; + +end rtl; diff --git a/Apple - 2_MiST/rtl/vga_controller.vhd b/Apple - 2_MiST/rtl/vga_controller.vhd new file mode 100644 index 00000000..674b7e8a --- /dev/null +++ b/Apple - 2_MiST/rtl/vga_controller.vhd @@ -0,0 +1,291 @@ +------------------------------------------------------------------------------- +-- +-- A VGA line-doubler for an Apple ][ +-- +-- Stephen A. Edwards, sedwards@cs.columbia.edu +-- +-- +-- FIXME: This is all wrong +-- +-- The Apple ][ uses a 14.31818 MHz master clock. It outputs a new +-- horizontal line every 65 * 14 + 2 = 912 14M cycles. The extra two +-- are from the "extended cycle" used to keep the 3.579545 MHz +-- colorburst signal in sync. Of these, 40 * 14 = 560 are active video. +-- +-- In graphics mode, the Apple effectively generates 140 four-bit pixels +-- output serially (i.e., with 3.579545 MHz pixel clock). In text mode, +-- it generates 280 one-bit pixels (i.e., with a 7.15909 MHz pixel clock). +-- +-- We capture 140 four-bit nibbles for each line and interpret them in +-- one of the two modes. In graphics mode, each is displayed as a +-- single pixel of one of 16 colors. In text mode, each is displayed +-- as two black or white pixels. +-- +-- The VGA display is nominally 640 X 480, but we use a 14.31818 MHz +-- dot clock. To stay in sync with the Apple, we generate a new line +-- every 912 / 2 = 456 14M cycles= 31.8 us, a 31.4 kHz horizontal +-- refresh rate. Of these, 280 will be active video. +-- +-- One set of suggested VGA timings: +-- +-- ______________________ ________ +-- ________| VIDEO |________| VIDEO +-- |-C-|----------D-----------|-E-| +-- __ ______________________________ ___________ +-- |_| |_| +-- |B| +-- |---------------A----------------| +-- +-- A = 31.77 us Scanline time +-- B = 3.77 us Horizontal sync time +-- C = 1.89 us Back porch +-- D = 25.17 us Active video +-- E = 0.94 us Front porch +-- +-- We use A = 456 / 14.31818 MHz = 31.84 us +-- B = 54 / 14.31818 MHz = 3.77 us +-- C = 106 / 14.31818 MHz = 7.40 us +-- D = 280 / 14.31818 MHz = 19.56 us +-- E = 16 / 14.31818 MHz = 1.12 us +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity vga_controller is + + port ( + CLK_28M : in std_logic; -- 14.31818 MHz master clock + + VIDEO : in std_logic; -- from the Apple video generator + COLOR_LINE : in std_logic; + COLOR : in std_logic; + HBL : in std_logic; + VBL : in std_logic; + LD194 : in std_logic; + + VGA_CLK : out std_logic; + VGA_HS : out std_logic; -- Active low + VGA_VS : out std_logic; -- Active low + VGA_BLANK : out std_logic; + VGA_R : out unsigned(9 downto 0); + VGA_G : out unsigned(9 downto 0); + VGA_B : out unsigned(9 downto 0) + ); + +end vga_controller; + +architecture rtl of vga_controller is + + -- Double-ported RAM (one read port, one write port) + -- that holds two lines of 560 pixels + type line_memory_t is array (0 to 2047) of std_logic; + signal line_memory : line_memory_t; + + -- RGB values from Linards Ticmanis, + -- http://newsgroups.derkeiler.com/Archive/Comp/comp.sys.apple2/2005-09/msg00534.html + + type basis_color is array(0 to 3) of unsigned(7 downto 0); + constant basis_r : basis_color := ( X"88", X"38", X"07", X"38" ); + constant basis_g : basis_color := ( X"22", X"24", X"67", X"52" ); + constant basis_b : basis_color := ( X"2C", X"A0", X"2C", X"07" ); + + signal ram_write_addr : unsigned(10 downto 0); + signal ram_we : std_logic; + signal ram_read_addr : unsigned(10 downto 0); + signal ram_data_out : std_logic; + + signal shift_reg : unsigned(5 downto 0); -- Last six pixels + + signal last_hbl : std_logic; + signal hcount : unsigned(10 downto 0); + signal hcount2 : unsigned(10 downto 0); + signal vcount : unsigned(5 downto 0); + signal even_line : std_logic; + signal hactive, hactive_early2, hactive_early1 : std_logic; + + constant VGA_SCANLINE : integer := 456*2; -- Must be 456*2 (set by the Apple) + + constant VGA_HSYNC : integer := 54 * 2; + constant VGA_BACK_PORCH : integer := 66 * 2; + constant VGA_ACTIVE : integer := 282 * 2; + constant VGA_FRONT_PORCH : integer := 54 * 2; + + -- VGA_HSYNC + VGA_BACK_PORCH + VGA_ACTIVE + VGA_FRONT_PORCH = VGA_SCANLINE + + constant VBL_TO_VSYNC : integer := 33; + constant VGA_VSYNC_LINES : integer := 3; + + signal VGA_VS_I, VGA_HS_I : std_logic; + + signal video_active : std_logic; + signal vbl_delayed, vbl_delayed2 : std_logic; + signal hbl_delayed : std_logic; + signal color_line_delayed_1, color_line_delayed_2 : std_logic; + +begin + + delay_hbl : process (CLK_28M) + begin + if rising_edge(CLK_28M) then + if LD194 = '0' then + hbl_delayed <= HBL; + end if; + end if; + end process; + + hcount_vcount_control : process (CLK_28M) + begin + if rising_edge(CLK_28M) then + if last_hbl = '1' and hbl_delayed = '0' then -- Falling edge + color_line_delayed_2 <= color_line_delayed_1; + color_line_delayed_1 <= COLOR; + hcount <= (others => '0'); + vbl_delayed2 <= vbl_delayed; + vbl_delayed <= VBL; + if vbl_delayed = '1' then + even_line <= '0'; + vcount <= vcount + 1; + else + vcount <= (others => '0'); + even_line <= not even_line; + end if; + else + hcount <= hcount + 1; + end if; + last_hbl <= hbl_delayed; + end if; + end process hcount_vcount_control; + + hsync_gen : process (CLK_28M) + begin + if rising_edge(CLK_28M) then + if hcount = VGA_ACTIVE + VGA_FRONT_PORCH or + hcount = VGA_SCANLINE + VGA_ACTIVE + VGA_FRONT_PORCH then + VGA_HS_I <= '0'; + elsif hcount = VGA_ACTIVE + VGA_FRONT_PORCH + VGA_HSYNC or + hcount = VGA_SCANLINE + VGA_ACTIVE + VGA_FRONT_PORCH + VGA_HSYNC then + VGA_HS_I <= '1'; + end if; + + hactive <= hactive_early1; + hactive_early1 <= hactive_early2; + + if hcount = VGA_SCANLINE - 1 or + hcount = VGA_SCANLINE + VGA_SCANLINE - 1 then + hactive_early2 <= '1'; + elsif hcount = VGA_ACTIVE or + hcount = VGA_ACTIVE + VGA_SCANLINE then + hactive_early2 <= '0'; + end if; + end if; + end process hsync_gen; + + VGA_HS <= VGA_HS_I; + + vsync_gen : process (CLK_28M) + begin + if rising_edge(CLK_28M) then + if vcount = VBL_TO_VSYNC then + VGA_VS_I <= '0'; + elsif vcount = VBL_TO_VSYNC + VGA_VSYNC_LINES then + VGA_VS_I <= '1'; + end if; + end if; + end process vsync_gen; + + VGA_VS <= VGA_VS_I; + + hcount2 <= hcount - VGA_SCANLINE; + + ram_read_addr <= + even_line & hcount(9 downto 0) when hcount < VGA_SCANLINE else + even_line & hcount2(9 downto 0); + + shifter: process (CLK_28M) + begin + if rising_edge(CLK_28M) then + shift_reg <= ram_data_out & shift_reg(5 downto 1); + end if; + end process; + + ram_write_addr <= (not even_line) & hcount(10 downto 1); + ram_we <= '1' when hcount(0) = '1' else '0'; + + video_active <= hactive and not vbl_delayed2; + + pixel_generator: process (CLK_28M) + variable r, g, b : unsigned(7 downto 0); + begin + if rising_edge(CLK_28M) then + r := X"00"; + g := X"00"; + b := X"00"; + if video_active = '1' then + + if color_line_delayed_2 = '0' then -- Monochrome mode + + if shift_reg(2) = '1' then + r := X"FF"; g := X"FF"; b := X"FF"; + end if; + + elsif shift_reg(0) = shift_reg(4) and shift_reg(5) = shift_reg(1) then + + -- Tint of adjacent pixels is consistent : display the color + + if shift_reg(1) = '1' then + r := r + basis_r(to_integer(hcount + 1)); + g := g + basis_g(to_integer(hcount + 1)); + b := b + basis_b(to_integer(hcount + 1)); + end if; + if shift_reg(2) = '1' then + r := r + basis_r(to_integer(hcount + 2)); + g := g + basis_g(to_integer(hcount + 2)); + b := b + basis_b(to_integer(hcount + 2)); + end if; + if shift_reg(3) = '1' then + r := r + basis_r(to_integer(hcount + 3)); + g := g + basis_g(to_integer(hcount + 3)); + b := b + basis_b(to_integer(hcount + 3)); + end if; + if shift_reg(4) = '1' then + r := r + basis_r(to_integer(hcount)); + g := g + basis_g(to_integer(hcount)); + b := b + basis_b(to_integer(hcount)); + end if; + else + + -- Tint is changing: display only black, gray, or white + + case shift_reg(3 downto 2) is + when "11" => r := X"FF"; g := X"FF"; b := X"FF"; + when "01" | "10" => r := X"80"; g := X"80"; b := X"80"; + when others => r := X"00"; g := X"00"; b := X"00"; + end case; + end if; + + end if; + + VGA_R <= r & r(7 downto 6); + VGA_G <= g & g(7 downto 6); + VGA_B <= b & b(7 downto 6); + + end if; + end process pixel_generator; + + -- The two-port RAM that stores the line data + line_storage : process (CLK_28M) + begin + if rising_edge(CLK_28M) then + if ram_we = '1' then + line_memory(to_integer(ram_write_addr)) <= VIDEO; + end if; + ram_data_out <= line_memory(to_integer(ram_read_addr)); + end if; + end process line_storage; + + VGA_CLK <= CLK_28M; + + VGA_BLANK <= video_active; + +end rtl; diff --git a/Apple - 2_MiST/rtl/video_generator.vhd b/Apple - 2_MiST/rtl/video_generator.vhd new file mode 100644 index 00000000..e24819f0 --- /dev/null +++ b/Apple - 2_MiST/rtl/video_generator.vhd @@ -0,0 +1,221 @@ +------------------------------------------------------------------------------- +-- +-- Apple ][ Video Generation Logic +-- +-- Stephen A. Edwards, sedwards@cs.columbia.edu +-- +-- This takes data from memory and various mode switches to produce the +-- serial one-bit video data stream. +-- +------------------------------------------------------------------------------- +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity video_generator is + + port ( + CLK_14M : in std_logic; -- 14.31818 MHz master clock + CLK_7M : in std_logic; + AX : in std_logic; + CAS_N : in std_logic; + TEXT_MODE : in std_logic; + PAGE2 : in std_logic; + HIRES_MODE : in std_logic; + MIXED_MODE : in std_logic; + H0 : in std_logic; + VA : in std_logic; + VB : in std_logic; + VC : in std_logic; + V2 : in std_logic; + V4 : in std_logic; + BLANK : in std_logic; + DL : in unsigned(7 downto 0); -- Data from RAM + LDPS_N : in std_logic; + LD194 : in std_logic; + FLASH_CLK : in std_logic; -- Low-frequency flashing text clock + HIRES : out std_logic; + VIDEO : out std_logic; + COLOR_LINE : out std_logic + ); + +end video_generator; + +architecture rtl of video_generator is + + signal char_rom_addr : unsigned(8 downto 0); + signal char_rom_out : unsigned(4 downto 0); + signal text_shiftreg : unsigned(5 downto 0); + signal invert_character : std_logic; + signal text_pixel : std_logic; -- B2 p11 + signal blank_delayed : std_logic; + signal video_sig : std_logic; -- output of B10 p5 + signal graph_shiftreg : unsigned(7 downto 0); + signal graphics_time_1, graphics_time_2, + graphics_time_3 : std_logic; -- B5 p2, B8 p15, B8 p2 + signal lores_time : std_logic; -- A11 p6 + signal pixel_select : std_logic_vector(1 downto 0); -- A10 p14, A10 p15 + signal hires_delayed : std_logic; -- A11 p9 + +begin + + ----------------------------------------------------------------------------- + -- + -- Text Mode Circuitry + -- + -- The character ROM drives a parallel-to-serial shift register + -- whose output is selectively inverted by inverted or flashing text + -- + ----------------------------------------------------------------------------- + + char_rom_addr <= DL(5 downto 0) & VC & VB & VA; + + thecharrom : entity work.character_rom + port map( + addr => char_rom_addr, + clk => CLK_14M, -- FIXME: a lower frequency? + dout => char_rom_out + ); + + -- Parallel-to-serial shifter for text mode + -- The Apple actually used LDPS_N as the clock, not 14M; this is equivalent + A3_74166: process (CLK_14M) + begin + if rising_edge(CLK_14M) then + if CLK_7M = '0' then + if LDPS_N = '0' then -- load + text_shiftreg <= char_rom_out & "0"; + else -- shift + text_shiftreg <= '0' & text_shiftreg(5 downto 1); + end if; + end if; + end if; + end process; + + -- Latch and decoder for flashing/inverted text + -- Comprises part of B11, B13, and A10 + flash_invert : process (CLK_14M) + begin + if rising_edge(CLK_14M) then + if LD194 = '0' then + invert_character <= not (DL(7) or (DL(6) and FLASH_CLK)); + end if; + end if; + end process; + + text_pixel <= text_shiftreg(0) xor invert_character; + + ----------------------------------------------------------------------------- + -- + -- Lores and Hires Mode Circuitry + -- + -- An eight-bit shift register that either shifts (hires mode) or rotates + -- the two nibbles (lores) followed by a mux that selects the video + -- data from the text mode display, the hires shift register (possibly + -- delayed by a 14M clock pulse), or one of the bits in the lores shift + -- register. + -- + ----------------------------------------------------------------------------- + + -- Original Apple clocked this shift register on the rising edge of RAS_N + B5B8_74LS174 : process (CLK_14M) + begin + if rising_edge(CLK_14M) then + if AX = '1' and CAS_N = '0' then + graphics_time_3 <= graphics_time_2; + graphics_time_2 <= graphics_time_1; + graphics_time_1 <= not (TEXT_MODE or (V2 and V4 and MIXED_MODE)); + end if; + end if; + end process; + + COLOR_LINE <= graphics_time_1; + + HIRES <= HIRES_MODE and graphics_time_3; -- to address generator + + lores_time <= not HIRES_MODE and graphics_time_3; + + A8A10_74LS194 : process (CLK_14M) + begin + if rising_edge(CLK_14M) then + if LD194 = '0' then + if lores_time = '1' then -- LORES mode + pixel_select <= VC & H0; + else -- HIRES mode + pixel_select <= graphics_time_1 & DL(7); + end if; + end if; + end if; + end process; + + -- Shift hires pixels by one 14M cycle to get orange and blue + A11_74LS74 : process (CLK_14M) + begin + if rising_edge(CLK_14M) then + hires_delayed <= graph_shiftreg(0); + end if; + end process; + + -- A pair of four-bit universal shift registers that either + -- shift the whole byte (hires mode) or rotate the two nibbles (lores mode) + B4B9_74LS194 : process (CLK_14M) + begin + if rising_edge(CLK_14M) then + if LD194 = '0' then + graph_shiftreg <= DL; + else + if lores_time = '1' then -- LORES configuration + graph_shiftreg <= graph_shiftreg(4) & graph_shiftreg(7 downto 5) & + graph_shiftreg(0) & graph_shiftreg(3 downto 1); + else -- HIRES configuration + if CLK_7M = '0' then + graph_shiftreg <= graph_shiftreg(4) & graph_shiftreg(7 downto 1); + end if; + end if; + end if; + end if; + end process; + + -- Synchronize BLANK to LD194 + A10_74LS194: process (CLK_14M) + begin + if rising_edge(CLK_14M) then + if LD194 = '0' then + blank_delayed <= BLANK; + end if; + end if; + end process; + + -- Video output mux and flip-flop + A9B10_74LS151 : process (CLK_14M) + begin + if rising_edge(CLK_14M) then + if blank_delayed = '0' then + if lores_time = '1' then -- LORES mode + case pixel_select is + when "00" => video_sig <= graph_shiftreg(0); + when "01" => video_sig <= graph_shiftreg(2); + when "10" => video_sig <= graph_shiftreg(4); + when "11" => video_sig <= graph_shiftreg(6); + when others => video_sig <= 'X'; + end case; + else + if pixel_select(1) = '0' then -- TEXT mode + video_sig <= text_pixel; + else -- HIRES mode + if pixel_select(0) = '1' then + video_sig <= hires_delayed; + else + video_sig <= graph_shiftreg(0); + end if; + end if; + end if; + else + video_sig <= '0'; + end if; + end if; + end process; + + VIDEO <= video_sig; + +end rtl; diff --git a/Apple - 2_MiST/rtl/video_mixer.sv b/Apple - 2_MiST/rtl/video_mixer.sv new file mode 100644 index 00000000..04cfd4ba --- /dev/null +++ b/Apple - 2_MiST/rtl/video_mixer.sv @@ -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 diff --git a/Apple - 2_MiST/snapshot/AppleII_MiST.rbf b/Apple - 2_MiST/snapshot/AppleII_MiST.rbf new file mode 100644 index 00000000..e25000fc Binary files /dev/null and b/Apple - 2_MiST/snapshot/AppleII_MiST.rbf differ