1
0
mirror of https://github.com/Gehstock/Mist_FPGA.git synced 2026-03-10 20:33:41 +00:00

Convert Apple 2 WXEDA -> MiST

This commit is contained in:
Gehstock
2018-05-18 16:48:33 +02:00
parent 8bf6131cf5
commit 6d57e8bf77
37 changed files with 10258 additions and 0 deletions

View File

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

View File

@@ -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

197
Apple - 2_MiST/README.MD Normal file
View File

@@ -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/

38
Apple - 2_MiST/clean.bat Normal file
View File

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

View File

@@ -0,0 +1,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

View File

@@ -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"]

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

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

View File

@@ -0,0 +1,2 @@
`define BUILD_DATE "180506"
`define BUILD_TIME "191822"

View File

@@ -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;

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

454
Apple - 2_MiST/rtl/hq2x.sv Normal file
View File

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

View File

@@ -0,0 +1,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;

File diff suppressed because it is too large Load Diff

View File

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

179
Apple - 2_MiST/rtl/osd.v Normal file
View File

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

View File

@@ -0,0 +1,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"]

376
Apple - 2_MiST/rtl/pll.v Normal file
View File

@@ -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

View File

@@ -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"]

172
Apple - 2_MiST/rtl/ram.v Normal file
View File

@@ -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

Binary file not shown.

View File

@@ -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 gbasl
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+15
sta gbasl
lda #>text
sta gbash
lda #<hello
sta basl
lda #>hello
sta bash
jsr write_string
lda #<line8+8
sta gbasl
lda #<roms1
sta basl
lda #>roms1
sta bash
jsr write_string
lda #<line10
sta gbasl
lda #>line10
sta gbash
lda #<roms2
sta basl
lda #>roms2
sta bash
jsr write_string
lda #<line11
sta gbasl
lda #>line11
sta gbash
lda #<roms3
sta basl
lda #>roms3
sta bash
jsr write_string
lda #<line23
sta gbasl
lda #>line23
sta gbash
lda #<press
sta basl
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 gbasl
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 gbasl
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

Binary file not shown.

Binary file not shown.

View File

@@ -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;

View File

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

View File

@@ -0,0 +1,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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

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

Binary file not shown.