mirror of
https://github.com/nippur72/Apple1_MiST.git
synced 2024-12-13 20:29:23 +00:00
fork Gehstock's project
This commit is contained in:
parent
fe6a59aed6
commit
03281591f6
25
.gitignore
vendored
Normal file
25
.gitignore
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
Test
|
||||
build_id.v
|
||||
db
|
||||
history.db
|
||||
greybox_tmp
|
||||
incremental_db
|
||||
output_files
|
||||
simulation
|
||||
PLLJ_PLLSPE_INFO.txt
|
||||
*.bak
|
||||
*.orig
|
||||
*.rej
|
||||
*.qdf
|
||||
*.rpt
|
||||
*.smsg
|
||||
*.summary
|
||||
*.done
|
||||
*.jdi
|
||||
*.pin
|
||||
*.sof
|
||||
*.qws
|
||||
*.ppf
|
||||
*.ddb
|
||||
*.srf
|
||||
|
15
README.md
Normal file
15
README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Apple1_MIST
|
||||
|
||||
Apple1 implementation for the MiST FPGA.
|
||||
|
||||
This was forked from [Gehstock's project](https://github.com/Gehstock/Mist_FPGA).
|
||||
|
||||
## CHANGELOG
|
||||
|
||||
2021-12-28
|
||||
|
||||
- 15 kHz video output (NTSC) and use of MiST scandoubler/video pipeline
|
||||
- more accurate 7x8 character matrix (5x7 + hardware spacing)
|
||||
- clock is now derived from 14.31818 instead of 25 MHz (more accurate)
|
||||
- serial port communication feature is disabled/removed
|
||||
|
30
apple-one.qpf
Normal file
30
apple-one.qpf
Normal 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 = 21:11:27 January 26, 2018
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
|
||||
QUARTUS_VERSION = "13.1"
|
||||
DATE = "21:11:27 January 26, 2018"
|
||||
|
||||
# Revisions
|
||||
|
||||
PROJECT_REVISION = "apple-one"
|
192
apple-one.qsf
Normal file
192
apple-one.qsf
Normal file
@ -0,0 +1,192 @@
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# 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 = 11:23:36 April 10, 2018
|
||||
#
|
||||
# -------------------------------------------------------------------------- #
|
||||
#
|
||||
# Notes:
|
||||
#
|
||||
# 1) The default values for assignments are stored in the file:
|
||||
# apple-one_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 "21:11:27 JANUARY 26, 2018"
|
||||
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
|
||||
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files
|
||||
|
||||
# Classic Timing Assignments
|
||||
# ==========================
|
||||
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
|
||||
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
|
||||
|
||||
# Analysis & Synthesis Assignments
|
||||
# ================================
|
||||
set_global_assignment -name FAMILY "Cyclone III"
|
||||
set_global_assignment -name TOP_LEVEL_ENTITY apple1_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 ERROR_CHECK_FREQUENCY_DIVISOR 1
|
||||
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "2.5 V"
|
||||
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
|
||||
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
|
||||
set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF
|
||||
set_global_assignment -name ENABLE_NCE_PIN OFF
|
||||
set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF
|
||||
set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
|
||||
set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
|
||||
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"
|
||||
|
||||
# EDA Netlist Writer Assignments
|
||||
# ==============================
|
||||
set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)"
|
||||
|
||||
# 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 EDA_TOOL_SETTINGS(eda_simulation)
|
||||
# ---------------------------------------
|
||||
|
||||
# EDA Netlist Writer Assignments
|
||||
# ==============================
|
||||
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation
|
||||
|
||||
# end EDA_TOOL_SETTINGS(eda_simulation)
|
||||
# -------------------------------------
|
||||
|
||||
# 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)
|
||||
# -------------------------
|
||||
|
||||
# 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 PLL_1 -to "pll:pll|altpll:altpll_component"
|
||||
|
||||
set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl"
|
||||
|
||||
|
||||
# end ENTITY(apple1_mist)
|
||||
# -----------------------
|
||||
set_global_assignment -name VERILOG_FILE "rtl/mist-modules/user_io.v"
|
||||
set_global_assignment -name VERILOG_FILE "rtl/mist-modules/sd_card.v"
|
||||
set_global_assignment -name VERILOG_FILE "rtl/mist-modules/scandoubler.v"
|
||||
set_global_assignment -name VERILOG_FILE "rtl/mist-modules/rgb2ypbpr.v"
|
||||
set_global_assignment -name VERILOG_FILE "rtl/mist-modules/osd.v"
|
||||
set_global_assignment -name VERILOG_FILE "rtl/mist-modules/mist_video.v"
|
||||
set_global_assignment -name QIP_FILE "rtl/mist-modules/mist_core.qip"
|
||||
set_global_assignment -name VHDL_FILE "rtl/mist-modules/mist.vhd"
|
||||
set_global_assignment -name QIP_FILE "rtl/mist-modules/mist.qip"
|
||||
set_global_assignment -name VERILOG_FILE "rtl/mist-modules/data_io.v"
|
||||
set_global_assignment -name VHDL_FILE "rtl/mist-modules/dac.vhd"
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE "rtl/mist-modules/cofi.sv"
|
||||
set_global_assignment -name VERILOG_FILE "rtl/mist-modules/arcade_inputs.v"
|
||||
set_global_assignment -name VERILOG_FILE rtl/arlet_6502/cpu.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/arlet_6502/ALU.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/arlet_6502/arlet_6502.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/apple1.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/clock.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/pwr_reset.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/ram.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/rom_basic.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/rom_wozmon.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/vram.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/uart.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/ps2keyboard.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/vga.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/async_tx_rx.v
|
||||
set_global_assignment -name VERILOG_FILE rtl/font_rom.v
|
||||
set_global_assignment -name SYSTEMVERILOG_FILE rtl/video_mixer.sv
|
||||
set_global_assignment -name VERILOG_FILE rtl/scandoubler.v
|
||||
set_global_assignment -name QIP_FILE rtl/pll.qip
|
||||
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 SYSTEMVERILOG_FILE rtl/apple1_mist.sv
|
||||
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
|
37
clean.bat
Normal file
37
clean.bat
Normal file
@ -0,0 +1,37 @@
|
||||
@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 /s new_rtl_netlist
|
||||
del /s old_rtl_netlist
|
||||
|
||||
pause
|
263
rtl/apple1.v
Normal file
263
rtl/apple1.v
Normal file
@ -0,0 +1,263 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
//
|
||||
// Description: Apple1 hardware core
|
||||
//
|
||||
// Author.....: Alan Garfield
|
||||
// Niels A. Moseley
|
||||
// Date.......: 26-1-2018
|
||||
//
|
||||
|
||||
module apple1(
|
||||
input clk14, // 25 MHz master clock
|
||||
input rst_n, // active low synchronous reset (needed for simulation)
|
||||
|
||||
// I/O interface to computer
|
||||
input uart_rx, // asynchronous serial data input from computer
|
||||
output uart_tx, // asynchronous serial data output to computer
|
||||
output uart_cts, // clear to send flag to computer
|
||||
|
||||
// I/O interface to keyboard
|
||||
input ps2_clk, // PS/2 keyboard serial clock input
|
||||
input ps2_din, // PS/2 keyboard serial data input
|
||||
input ps2_select, // Input to select the PS/2 keyboard instead of the UART
|
||||
|
||||
// Outputs to VGA display
|
||||
output vga_h_sync, // hozizontal VGA sync pulse
|
||||
output vga_v_sync, // vertical VGA sync pulse
|
||||
output vga_red, // red VGA signal
|
||||
output vga_grn, // green VGA signal
|
||||
output vga_blu, // blue VGA signal
|
||||
input vga_cls, // clear screen button
|
||||
|
||||
// Debugging ports
|
||||
output [15:0] pc_monitor // spy for program counter / debugging
|
||||
);
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Registers and Wires
|
||||
|
||||
wire [15:0] ab;
|
||||
wire [7:0] dbi;
|
||||
wire [7:0] dbo;
|
||||
wire we;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Clocks
|
||||
|
||||
wire cpu_clken;
|
||||
clock clock(
|
||||
.clk14(clk14),
|
||||
.rst_n(rst_n),
|
||||
.cpu_clken(cpu_clken)
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Reset
|
||||
|
||||
wire rst;
|
||||
pwr_reset pwr_reset(
|
||||
.clk14(clk14),
|
||||
.rst_n(rst_n),
|
||||
.enable(cpu_clken),
|
||||
.rst(rst)
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// 6502
|
||||
|
||||
arlet_6502 arlet_6502(
|
||||
.clk (clk14),
|
||||
.enable (cpu_clken),
|
||||
.rst (rst),
|
||||
.ab (ab),
|
||||
.dbi (dbi),
|
||||
.dbo (dbo),
|
||||
.we (we),
|
||||
.irq_n (1'b1),
|
||||
.nmi_n (1'b1),
|
||||
.ready (cpu_clken),
|
||||
.pc_monitor (pc_monitor)
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Address Decoding
|
||||
|
||||
wire ram_cs = (ab[15:13] == 3'b000); // 0x0000 -> 0x1FFF
|
||||
|
||||
// font mode, background and foreground colour
|
||||
wire vga_mode_cs = (ab[15:2] == 14'b11000000000000); // 0xC000 -> 0xC003
|
||||
|
||||
// RX: Either keyboard or UART input
|
||||
// TX: Always VGA and UART output
|
||||
wire rx_cs = (ab[15:1] == 15'b110100000001000); // 0xD010 -> 0xD011
|
||||
wire tx_cs = (ab[15:1] == 15'b110100000001001); // 0xD012 -> 0xD013
|
||||
|
||||
// select UART on transmit but only receive when PS/2 is not selected.
|
||||
wire uart_cs = tx_cs | ((~ps2_select) & rx_cs);
|
||||
|
||||
// select PS/2 keyboard input when selected.
|
||||
wire ps2kb_cs = ps2_select & rx_cs;
|
||||
|
||||
// VGA always get characters when they are sent.
|
||||
wire vga_cs = tx_cs;
|
||||
|
||||
wire basic_cs = (ab[15:12] == 4'b1110); // 0xE000 -> 0xEFFF
|
||||
wire rom_cs = (ab[15:8] == 8'b11111111); // 0xFF00 -> 0xFFFF
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// RAM and ROM
|
||||
|
||||
// RAM
|
||||
wire [7:0] ram_dout;
|
||||
ram ram(
|
||||
.clk(clk14),
|
||||
.address(ab[12:0]),
|
||||
.w_en(we & ram_cs),
|
||||
.din(dbo),
|
||||
.dout(ram_dout)
|
||||
);
|
||||
|
||||
// WozMon ROM
|
||||
wire [7:0] rom_dout;
|
||||
rom_wozmon rom_wozmon(
|
||||
.clk(clk14),
|
||||
.address(ab[7:0]),
|
||||
.dout(rom_dout)
|
||||
);
|
||||
|
||||
// Basic ROM
|
||||
wire [7:0] basic_dout;
|
||||
rom_basic rom_basic(
|
||||
.clk(clk14),
|
||||
.address(ab[11:0]),
|
||||
.dout(basic_dout)
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Peripherals
|
||||
|
||||
// UART
|
||||
wire [7:0] uart_dout;
|
||||
uart #(
|
||||
`ifdef SIM
|
||||
100, 10, 2 // for simulation don't need real baud rates
|
||||
`else
|
||||
25000000, 115200, 8 // 25MHz, 115200 baud, 8 times RX oversampling
|
||||
`endif
|
||||
) my_uart(
|
||||
.clk(clk14),
|
||||
.enable(uart_cs & cpu_clken),
|
||||
.rst(rst),
|
||||
|
||||
.uart_rx(uart_rx),
|
||||
.uart_tx(uart_tx),
|
||||
.uart_cts(uart_cts),
|
||||
|
||||
.address(ab[1:0]), // for uart
|
||||
.w_en(we & uart_cs),
|
||||
.din(dbo),
|
||||
.dout(uart_dout)
|
||||
);
|
||||
|
||||
// PS/2 keyboard interface
|
||||
wire [7:0] ps2_dout;
|
||||
ps2keyboard keyboard(
|
||||
.clk14(clk14),
|
||||
.rst(rst),
|
||||
.key_clk(ps2_clk),
|
||||
.key_din(ps2_din),
|
||||
.cs(ps2kb_cs),
|
||||
.address(ab[0]),
|
||||
.dout(ps2_dout)
|
||||
);
|
||||
|
||||
// VGA Display interface
|
||||
reg [2:0] fg_colour;
|
||||
reg [2:0] bg_colour;
|
||||
reg [1:0] font_mode;
|
||||
reg [7:0] vga_mode_dout;
|
||||
|
||||
vga vga(
|
||||
.clk14(clk14),
|
||||
.enable(vga_cs & cpu_clken),
|
||||
.rst(rst),
|
||||
|
||||
.vga_h_sync(vga_h_sync),
|
||||
.vga_v_sync(vga_v_sync),
|
||||
.vga_red(vga_red),
|
||||
.vga_grn(vga_grn),
|
||||
.vga_blu(vga_blu),
|
||||
|
||||
.address(ab[0]),
|
||||
.w_en(we & vga_cs),
|
||||
.din(dbo),
|
||||
.mode(font_mode),
|
||||
.fg_colour(fg_colour),
|
||||
.bg_colour(bg_colour),
|
||||
.clr_screen(vga_cls)
|
||||
);
|
||||
|
||||
// Handle font mode and foreground and background
|
||||
// colours. This so isn't Apple One authentic, but
|
||||
// it can't hurt to have some fun. :D
|
||||
always @(posedge clk14 or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
begin
|
||||
font_mode <= 2'b0;
|
||||
fg_colour <= 3'd7;
|
||||
bg_colour <= 3'd0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
case (ab[1:0])
|
||||
2'b00:
|
||||
begin
|
||||
vga_mode_dout = {6'b0, font_mode};
|
||||
if (vga_mode_cs & we & cpu_clken)
|
||||
font_mode <= dbo[1:0];
|
||||
end
|
||||
2'b01:
|
||||
begin
|
||||
vga_mode_dout = {5'b0, fg_colour};
|
||||
if (vga_mode_cs & we & cpu_clken)
|
||||
fg_colour <= dbo[2:0];
|
||||
end
|
||||
2'b10:
|
||||
begin
|
||||
vga_mode_dout = {5'b0, bg_colour};
|
||||
if (vga_mode_cs & we & cpu_clken)
|
||||
bg_colour <= dbo[2:0];
|
||||
end
|
||||
default:
|
||||
vga_mode_dout = 8'b0;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// CPU Data In MUX
|
||||
|
||||
// link up chip selected device to cpu input
|
||||
assign dbi = ram_cs ? ram_dout :
|
||||
rom_cs ? rom_dout :
|
||||
basic_cs ? basic_dout :
|
||||
uart_cs ? uart_dout :
|
||||
ps2kb_cs ? ps2_dout :
|
||||
vga_mode_cs ? vga_mode_dout :
|
||||
8'hFF;
|
||||
endmodule
|
201
rtl/apple1_mist.sv
Normal file
201
rtl/apple1_mist.sv
Normal file
@ -0,0 +1,201 @@
|
||||
// Apple-1 for MiST
|
||||
//
|
||||
// Forked from Gehstock's implementation https://github.com/Gehstock/Mist_FPGA
|
||||
//
|
||||
//
|
||||
|
||||
// TODO integrate with mist-modules
|
||||
// TODO load binary files into memory
|
||||
// TODO support ACI interface for load and save
|
||||
// TODO additional RAM with SDRAM
|
||||
// TODO reset key from keyboard
|
||||
// TODO cls key from keyboard
|
||||
// TODO power on-off
|
||||
// TODO special expansion boards: TMS9918, SID
|
||||
// TODO white/green/amber switch?
|
||||
// TODO reset if pll not locked
|
||||
// TODO rename "vga" into "display"
|
||||
// TODO reorganize file structure
|
||||
// TODO check ps2 clock
|
||||
|
||||
|
||||
module apple1_mist(
|
||||
input CLOCK_27,
|
||||
|
||||
// SPI interface to arm io controller
|
||||
input SPI_SCK,
|
||||
output SPI_DO,
|
||||
input SPI_DI,
|
||||
//input SPI_SS2,
|
||||
input SPI_SS3,
|
||||
//input SPI_SS4,
|
||||
input CONF_DATA0,
|
||||
|
||||
// SDRAM interface
|
||||
inout [15:0] SDRAM_DQ, // SDRAM Data bus 16 Bits
|
||||
output [12:0] SDRAM_A, // SDRAM Address bus 13 Bits
|
||||
output SDRAM_DQML, // SDRAM Low-byte Data Mask
|
||||
output SDRAM_DQMH, // SDRAM High-byte Data Mask
|
||||
output SDRAM_nWE, // SDRAM Write Enable
|
||||
output SDRAM_nCAS, // SDRAM Column Address Strobe
|
||||
output SDRAM_nRAS, // SDRAM Row Address Strobe
|
||||
output SDRAM_nCS, // SDRAM Chip Select
|
||||
output [1:0] SDRAM_BA, // SDRAM Bank Address
|
||||
output SDRAM_CLK, // SDRAM Clock
|
||||
output SDRAM_CKE, // SDRAM Clock Enable
|
||||
|
||||
// VGA interface
|
||||
output [5:0] VGA_R,
|
||||
output [5:0] VGA_G,
|
||||
output [5:0] VGA_B,
|
||||
output VGA_HS,
|
||||
output VGA_VS,
|
||||
|
||||
// other
|
||||
output LED,
|
||||
input UART_RX,
|
||||
output AUDIO_L,
|
||||
output AUDIO_R
|
||||
);
|
||||
|
||||
`include "rtl\build_id.v"
|
||||
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
/***************************************** @user_io ***************************************/
|
||||
/******************************************************************************************/
|
||||
/******************************************************************************************/
|
||||
|
||||
localparam CONF_STR = {
|
||||
"APPLE 1;;",
|
||||
"O34,Scandoubler Fx,None,HQ2x,CRT 25%,CRT 50%;",
|
||||
"T6,Reset;",
|
||||
"V,v1.00.",`BUILD_DATE
|
||||
};
|
||||
|
||||
localparam conf_str_len = $size(CONF_STR)>>3;
|
||||
|
||||
wire st_reset_switch = buttons[1];
|
||||
wire st_menu_reset = status[6];
|
||||
|
||||
wire clk14; // the 14.31818 MHz clock
|
||||
wire clk_osd; // x4 clock for the OSD menu
|
||||
wire r, g, b;
|
||||
wire hs, vs;
|
||||
|
||||
wire [31:0] status;
|
||||
wire [1:0] buttons;
|
||||
wire [1:0] switches;
|
||||
|
||||
wire scandoubler_disable;
|
||||
wire ypbpr;
|
||||
wire no_csync;
|
||||
|
||||
wire ps2_kbd_clk;
|
||||
wire ps2_kbd_data;
|
||||
|
||||
assign LED = 1;
|
||||
|
||||
wire reset_button = status[0] | st_menu_reset | st_reset_switch;
|
||||
|
||||
|
||||
pll pll
|
||||
(
|
||||
.inclk0(CLOCK_27),
|
||||
.c0(clk_osd),
|
||||
.c1(clk14),
|
||||
.locked(),
|
||||
.areset()
|
||||
);
|
||||
|
||||
apple1 apple1
|
||||
(
|
||||
.clk14(clk14),
|
||||
.rst_n(~reset_button),
|
||||
|
||||
.uart_rx(), // uart not connected
|
||||
.uart_tx(), // uart not connected
|
||||
.uart_cts(), // uart not connected
|
||||
|
||||
.ps2_clk(ps2_kbd_clk),
|
||||
.ps2_din(ps2_kbd_data),
|
||||
.ps2_select(1'b1),
|
||||
|
||||
.vga_h_sync(hs),
|
||||
.vga_v_sync(vs),
|
||||
.vga_red(r),
|
||||
.vga_grn(g),
|
||||
.vga_blu(b),
|
||||
|
||||
.vga_cls(), // clear screen button (not connected yet)
|
||||
.pc_monitor() // debug program counter (not used)
|
||||
);
|
||||
|
||||
mist_video
|
||||
#(
|
||||
.COLOR_DEPTH(1),
|
||||
.OSD_AUTO_CE(1)
|
||||
)
|
||||
mist_video
|
||||
(
|
||||
.clk_sys(clk_osd), // 2x the VDP clock for the scandoubler
|
||||
|
||||
// OSD SPI interface
|
||||
.SPI_DI(SPI_DI),
|
||||
.SPI_SCK(SPI_SCK),
|
||||
.SPI_SS3(SPI_SS3),
|
||||
|
||||
.scanlines(2'b00), // scanlines (00-none 01-25% 10-50% 11-75%)
|
||||
.ce_divider(1), // non-scandoubled pixel clock divider 0 - clk_sys/4, 1 - clk_sys/2
|
||||
.scandoubler_disable(scandoubler_disable),
|
||||
|
||||
.no_csync(no_csync), // 1 = disable csync without scandoubler
|
||||
.ypbpr(ypbpr), // 1 = YPbPr output on composite sync
|
||||
|
||||
.rotate(2'b00), // Rotate OSD [0] - rotate [1] - left or right
|
||||
.blend(0), // composite-like blending
|
||||
|
||||
// video input
|
||||
.R(r),
|
||||
.G(g),
|
||||
.B(b),
|
||||
.HSync(hs),
|
||||
.VSync(vs),
|
||||
|
||||
// MiST video output signals
|
||||
.VGA_R(VGA_R),
|
||||
.VGA_G(VGA_G),
|
||||
.VGA_B(VGA_B),
|
||||
.VGA_VS(VGA_VS),
|
||||
.VGA_HS(VGA_HS),
|
||||
);
|
||||
|
||||
user_io
|
||||
#(
|
||||
.STRLEN(conf_str_len)
|
||||
//.PS2DIV(14) // ps2 clock divider: CLOCK / 14 must be approx = 15 Khz
|
||||
)
|
||||
user_io (
|
||||
.conf_str (CONF_STR ),
|
||||
|
||||
.clk_sys (clk14 ),
|
||||
|
||||
.SPI_CLK (SPI_SCK ),
|
||||
.SPI_SS_IO (CONF_DATA0 ),
|
||||
.SPI_MISO (SPI_DO ),
|
||||
.SPI_MOSI (SPI_DI ),
|
||||
|
||||
.status (status ),
|
||||
.buttons (buttons ),
|
||||
.switches (switches ),
|
||||
|
||||
.scandoubler_disable ( scandoubler_disable ),
|
||||
.ypbpr ( ypbpr ),
|
||||
.no_csync ( no_csync ),
|
||||
|
||||
// ps2 interface
|
||||
.ps2_kbd_clk (ps2_kbd_clk ),
|
||||
.ps2_kbd_data (ps2_kbd_data )
|
||||
);
|
||||
|
||||
endmodule
|
108
rtl/arlet_6502/ALU.v
Normal file
108
rtl/arlet_6502/ALU.v
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* ALU.
|
||||
*
|
||||
* AI and BI are 8 bit inputs. Result in OUT.
|
||||
* CI is Carry In.
|
||||
* CO is Carry Out.
|
||||
*
|
||||
* op[3:0] is defined as follows:
|
||||
*
|
||||
* 0011 AI + BI
|
||||
* 0111 AI - BI
|
||||
* 1011 AI + AI
|
||||
* 1100 AI | BI
|
||||
* 1101 AI & BI
|
||||
* 1110 AI ^ BI
|
||||
* 1111 AI
|
||||
*
|
||||
*/
|
||||
|
||||
module ALU( clk, op, right, AI, BI, CI, CO, BCD, OUT, V, Z, N, HC, RDY );
|
||||
input clk;
|
||||
input right;
|
||||
input [3:0] op; // operation
|
||||
input [7:0] AI;
|
||||
input [7:0] BI;
|
||||
input CI;
|
||||
input BCD; // BCD style carry
|
||||
output [7:0] OUT;
|
||||
output CO;
|
||||
output V;
|
||||
output Z;
|
||||
output N;
|
||||
output HC;
|
||||
input RDY;
|
||||
|
||||
reg [7:0] OUT;
|
||||
reg CO;
|
||||
wire V;
|
||||
wire Z;
|
||||
reg N;
|
||||
reg HC;
|
||||
|
||||
reg AI7;
|
||||
reg BI7;
|
||||
reg [8:0] temp_logic;
|
||||
reg [7:0] temp_BI;
|
||||
reg [4:0] temp_l;
|
||||
reg [4:0] temp_h;
|
||||
wire [8:0] temp = { temp_h, temp_l[3:0] };
|
||||
wire adder_CI = (right | (op[3:2] == 2'b11)) ? 0 : CI;
|
||||
|
||||
// calculate the logic operations. The 'case' can be done in 1 LUT per
|
||||
// bit. The 'right' shift is a simple mux that can be implemented by
|
||||
// F5MUX.
|
||||
always @* begin
|
||||
case( op[1:0] )
|
||||
2'b00: temp_logic = AI | BI;
|
||||
2'b01: temp_logic = AI & BI;
|
||||
2'b10: temp_logic = AI ^ BI;
|
||||
2'b11: temp_logic = AI;
|
||||
endcase
|
||||
|
||||
if( right )
|
||||
temp_logic = { AI[0], CI, AI[7:1] };
|
||||
end
|
||||
|
||||
// Add logic result to BI input. This only makes sense when logic = AI.
|
||||
// This stage can be done in 1 LUT per bit, using carry chain logic.
|
||||
always @* begin
|
||||
case( op[3:2] )
|
||||
2'b00: temp_BI = BI; // A+B
|
||||
2'b01: temp_BI = ~BI; // A-B
|
||||
2'b10: temp_BI = temp_logic; // A+A
|
||||
2'b11: temp_BI = 0; // A+0
|
||||
endcase
|
||||
end
|
||||
|
||||
// HC9 is the half carry bit when doing BCD add
|
||||
wire HC9 = BCD & (temp_l[3:1] >= 3'd5);
|
||||
|
||||
// CO9 is the carry-out bit when doing BCD add
|
||||
wire CO9 = BCD & (temp_h[3:1] >= 3'd5);
|
||||
|
||||
// combined half carry bit
|
||||
wire temp_HC = temp_l[4] | HC9;
|
||||
|
||||
// perform the addition as 2 separate nibble, so we get
|
||||
// access to the half carry flag
|
||||
always @* begin
|
||||
temp_l = temp_logic[3:0] + temp_BI[3:0] + adder_CI;
|
||||
temp_h = temp_logic[8:4] + temp_BI[7:4] + temp_HC;
|
||||
end
|
||||
|
||||
// calculate the flags
|
||||
always @(posedge clk)
|
||||
if( RDY ) begin
|
||||
AI7 <= AI[7];
|
||||
BI7 <= temp_BI[7];
|
||||
OUT <= temp[7:0];
|
||||
CO <= temp[8] | CO9;
|
||||
N <= temp[7];
|
||||
HC <= temp_HC;
|
||||
end
|
||||
|
||||
assign V = AI7 ^ BI7 ^ CO ^ N;
|
||||
assign Z = ~|OUT;
|
||||
|
||||
endmodule
|
72
rtl/arlet_6502/arlet_6502.v
Normal file
72
rtl/arlet_6502/arlet_6502.v
Normal file
@ -0,0 +1,72 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
//
|
||||
// Description: A wrapper for Arlet Ottens 6502 CPU core
|
||||
//
|
||||
// Author.....: Alan Garfield
|
||||
// Niels A. Moseley
|
||||
// Date.......: 26-1-2018
|
||||
//
|
||||
|
||||
module arlet_6502(
|
||||
input clk, // clock signal
|
||||
input enable, // clock enable strobe
|
||||
input rst, // active high reset signal
|
||||
output reg [15:0] ab, // address bus
|
||||
input [7:0] dbi, // 8-bit data bus (input)
|
||||
output reg [7:0] dbo, // 8-bit data bus (output)
|
||||
output reg we, // active high write enable strobe
|
||||
input irq_n, // active low interrupt request
|
||||
input nmi_n, // active low non-maskable interrupt
|
||||
input ready, // CPU updates when ready = 1
|
||||
output [15:0] pc_monitor // program counter monitor signal for debugging
|
||||
);
|
||||
|
||||
wire [7:0] dbo_c;
|
||||
wire [15:0] ab_c;
|
||||
wire we_c;
|
||||
|
||||
cpu arlet_cpu(
|
||||
.clk(clk),
|
||||
.reset(rst),
|
||||
.AB(ab_c),
|
||||
.DI(dbi),
|
||||
.DO(dbo_c),
|
||||
.WE(we_c),
|
||||
.IRQ(~irq_n),
|
||||
.NMI(~nmi_n),
|
||||
.RDY(ready),
|
||||
.PC_MONITOR(pc_monitor)
|
||||
);
|
||||
|
||||
always @(posedge clk or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
begin
|
||||
ab <= 16'd0;
|
||||
dbo <= 8'd0;
|
||||
we <= 1'b0;
|
||||
end
|
||||
else
|
||||
if (enable)
|
||||
begin
|
||||
ab <= ab_c;
|
||||
dbo <= dbo_c;
|
||||
we <= we_c;
|
||||
end
|
||||
end
|
||||
endmodule
|
66
rtl/arlet_6502/chip_6502.v
Normal file
66
rtl/arlet_6502/chip_6502.v
Normal file
@ -0,0 +1,66 @@
|
||||
`include "../rtl/cpu/aholme/chip_6502_nodes.inc"
|
||||
|
||||
module LOGIC (
|
||||
input [`NUM_NODES-1:0] i,
|
||||
output [`NUM_NODES-1:0] o);
|
||||
|
||||
`include "chip_6502_logic.inc"
|
||||
endmodule
|
||||
|
||||
|
||||
module chip_6502 (
|
||||
input clk, // FPGA clock
|
||||
input phi, // 6502 clock
|
||||
input res,
|
||||
input so,
|
||||
input rdy,
|
||||
input nmi,
|
||||
input irq,
|
||||
input [7:0] dbi,
|
||||
output [7:0] dbo,
|
||||
output rw,
|
||||
output sync,
|
||||
output [15:0] ab);
|
||||
|
||||
// Node states
|
||||
wire [`NUM_NODES-1:0] no;
|
||||
reg [`NUM_NODES-1:0] ni;
|
||||
reg [`NUM_NODES-1:0] q = 0;
|
||||
|
||||
LOGIC logic_00 (.i(ni), .o(no));
|
||||
|
||||
always @ (posedge clk)
|
||||
q <= no;
|
||||
|
||||
always @* begin
|
||||
ni = q;
|
||||
|
||||
ni[`NODE_vcc ] = 1'b1;
|
||||
ni[`NODE_vss ] = 1'b0;
|
||||
ni[`NODE_res ] = res;
|
||||
ni[`NODE_clk0] = phi;
|
||||
ni[`NODE_so ] = so;
|
||||
ni[`NODE_rdy ] = rdy;
|
||||
ni[`NODE_nmi ] = nmi;
|
||||
ni[`NODE_irq ] = irq;
|
||||
|
||||
{ni[`NODE_db7],ni[`NODE_db6],ni[`NODE_db5],ni[`NODE_db4],
|
||||
ni[`NODE_db3],ni[`NODE_db2],ni[`NODE_db1],ni[`NODE_db0]} = dbi[7:0];
|
||||
end
|
||||
|
||||
assign dbo[7:0] = {
|
||||
no[`NODE_db7],no[`NODE_db6],no[`NODE_db5],no[`NODE_db4],
|
||||
no[`NODE_db3],no[`NODE_db2],no[`NODE_db1],no[`NODE_db0]
|
||||
};
|
||||
|
||||
assign ab[15:0] = {
|
||||
no[`NODE_ab15], no[`NODE_ab14], no[`NODE_ab13], no[`NODE_ab12],
|
||||
no[`NODE_ab11], no[`NODE_ab10], no[`NODE_ab9], no[`NODE_ab8],
|
||||
no[`NODE_ab7], no[`NODE_ab6], no[`NODE_ab5], no[`NODE_ab4],
|
||||
no[`NODE_ab3], no[`NODE_ab2], no[`NODE_ab1], no[`NODE_ab0]
|
||||
};
|
||||
|
||||
assign rw = no[`NODE_rw];
|
||||
assign sync = no[`NODE_sync];
|
||||
|
||||
endmodule
|
10
rtl/arlet_6502/chip_6502_mux.v
Normal file
10
rtl/arlet_6502/chip_6502_mux.v
Normal file
@ -0,0 +1,10 @@
|
||||
module MUX #(
|
||||
parameter N=1
|
||||
) (
|
||||
output wire o,
|
||||
input wire i,
|
||||
input wire [N-1:0] s,
|
||||
input wire [N-1:0] d);
|
||||
|
||||
assign o = (|s) ? &(d|(~s)) : i;
|
||||
endmodule
|
1244
rtl/arlet_6502/cpu.v
Normal file
1244
rtl/arlet_6502/cpu.v
Normal file
File diff suppressed because it is too large
Load Diff
227
rtl/async_tx_rx.v
Normal file
227
rtl/async_tx_rx.v
Normal file
@ -0,0 +1,227 @@
|
||||
////////////////////////////////////////////////////////
|
||||
// RS-232 RX and TX module
|
||||
// (c) fpga4fun.com & KNJN LLC - 2003 to 2016
|
||||
|
||||
// The RS-232 settings are fixed
|
||||
// TX: 8-bit data, 2 stop, no-parity
|
||||
// RX: 8-bit data, 1 stop, no-parity (the receiver can accept more stop bits of course)
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
module async_transmitter(
|
||||
input clk,
|
||||
input rst,
|
||||
input TxD_start,
|
||||
input [7:0] TxD_data,
|
||||
output TxD,
|
||||
output TxD_busy
|
||||
);
|
||||
|
||||
// Assert TxD_start for (at least) one clock cycle to start transmission of TxD_data
|
||||
// TxD_data is latched so that it doesn't have to stay valid while it is being sent
|
||||
|
||||
parameter ClkFrequency = 25000000; // 25MHz
|
||||
parameter Baud = 115200;
|
||||
|
||||
////////////////////////////////
|
||||
wire BitTick;
|
||||
BaudTickGen #(ClkFrequency, Baud) tickgen(.clk(clk), .rst(rst), .enable(TxD_busy), .tick(BitTick));
|
||||
|
||||
reg [3:0] TxD_state;
|
||||
reg [7:0] TxD_shift;
|
||||
|
||||
wire TxD_ready = (TxD_state==0);
|
||||
assign TxD_busy = ~TxD_ready;
|
||||
|
||||
always @(posedge clk or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
begin
|
||||
TxD_state <= 0;
|
||||
TxD_shift <= 0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
if(TxD_ready & TxD_start)
|
||||
TxD_shift <= TxD_data;
|
||||
else
|
||||
if(TxD_state[3] & BitTick)
|
||||
TxD_shift <= (TxD_shift >> 1);
|
||||
|
||||
case(TxD_state)
|
||||
4'b0000: if(TxD_start) TxD_state <= 4'b0100;
|
||||
4'b0100: if(BitTick) TxD_state <= 4'b1000; // start bit
|
||||
4'b1000: if(BitTick) TxD_state <= 4'b1001; // bit 0
|
||||
4'b1001: if(BitTick) TxD_state <= 4'b1010; // bit 1
|
||||
4'b1010: if(BitTick) TxD_state <= 4'b1011; // bit 2
|
||||
4'b1011: if(BitTick) TxD_state <= 4'b1100; // bit 3
|
||||
4'b1100: if(BitTick) TxD_state <= 4'b1101; // bit 4
|
||||
4'b1101: if(BitTick) TxD_state <= 4'b1110; // bit 5
|
||||
4'b1110: if(BitTick) TxD_state <= 4'b1111; // bit 6
|
||||
4'b1111: if(BitTick) TxD_state <= 4'b0010; // bit 7
|
||||
4'b0010: if(BitTick) TxD_state <= 4'b0011; // stop1
|
||||
4'b0011: if(BitTick) TxD_state <= 4'b0000; // stop2
|
||||
default: if(BitTick) TxD_state <= 4'b0000;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
assign TxD = (TxD_state<4) | (TxD_state[3] & TxD_shift[0]);
|
||||
endmodule
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
module async_receiver(
|
||||
input clk,
|
||||
input rst,
|
||||
input RxD,
|
||||
output reg RxD_data_ready,
|
||||
output reg [7:0] RxD_data, // data received, valid only (for one clock cycle) when RxD_data_ready is asserted
|
||||
|
||||
// We also detect if a gap occurs in the received stream of characters
|
||||
// That can be useful if multiple characters are sent in burst
|
||||
// so that multiple characters can be treated as a "packet"
|
||||
output RxD_idle, // asserted when no data has been received for a while
|
||||
output reg RxD_endofpacket = 0 // asserted for one clock cycle when a packet has been detected (i.e. RxD_idle is going high)
|
||||
);
|
||||
|
||||
parameter ClkFrequency = 25000000; // 12MHz
|
||||
parameter Baud = 115200;
|
||||
|
||||
parameter Oversampling = 8; // needs to be a power of 2
|
||||
// we oversample the RxD line at a fixed rate to capture each RxD data bit at the "right" time
|
||||
// 8 times oversampling by default, use 16 for higher quality reception
|
||||
|
||||
////////////////////////////////
|
||||
reg [3:0] RxD_state;
|
||||
|
||||
wire OversamplingTick;
|
||||
BaudTickGen #(ClkFrequency, Baud, Oversampling) tickgen(.clk(clk), .rst(rst), .enable(1'b1), .tick(OversamplingTick));
|
||||
|
||||
// synchronize RxD to our clk domain
|
||||
reg [1:0] RxD_sync; // 2'b11
|
||||
always @(posedge clk or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
RxD_sync <= 2'b11;
|
||||
else
|
||||
if(OversamplingTick) RxD_sync <= {RxD_sync[0], RxD};
|
||||
end
|
||||
|
||||
// and filter it
|
||||
reg [1:0] Filter_cnt; // 2'b11
|
||||
reg RxD_bit; // 1'b1
|
||||
always @(posedge clk or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
begin
|
||||
Filter_cnt <= 2'b11;
|
||||
RxD_bit <= 1'b1;
|
||||
end
|
||||
else
|
||||
if(OversamplingTick)
|
||||
begin
|
||||
if(RxD_sync[1]==1'b1 && Filter_cnt!=2'b11) Filter_cnt <= Filter_cnt + 1'd1;
|
||||
else if(RxD_sync[1]==1'b0 && Filter_cnt!=2'b00) Filter_cnt <= Filter_cnt - 1'd1;
|
||||
|
||||
if(Filter_cnt==2'b11) RxD_bit <= 1'b1;
|
||||
else if(Filter_cnt==2'b00) RxD_bit <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
// and decide when is the good time to sample the RxD line
|
||||
function integer log2(input integer v);
|
||||
begin
|
||||
log2=0;
|
||||
while(v>>log2)
|
||||
log2 = log2 + 1;
|
||||
end
|
||||
endfunction
|
||||
|
||||
localparam l2o = log2(Oversampling);
|
||||
reg [l2o-2:0] OversamplingCnt;
|
||||
|
||||
always @(posedge clk)
|
||||
if(OversamplingTick) OversamplingCnt <= (RxD_state==0) ? 1'd0 : OversamplingCnt + 1'd1;
|
||||
|
||||
wire sampleNow = OversamplingTick && (OversamplingCnt==Oversampling/2-1);
|
||||
|
||||
// now we can accumulate the RxD bits in a shift-register
|
||||
always @(posedge clk or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
RxD_state <= 0;
|
||||
else
|
||||
case(RxD_state)
|
||||
4'b0000: if(~RxD_bit) RxD_state <= 4'b0001; // start bit found?
|
||||
4'b0001: if(sampleNow) RxD_state <= 4'b1000; // sync start bit to sampleNow
|
||||
4'b1000: if(sampleNow) RxD_state <= 4'b1001; // bit 0
|
||||
4'b1001: if(sampleNow) RxD_state <= 4'b1010; // bit 1
|
||||
4'b1010: if(sampleNow) RxD_state <= 4'b1011; // bit 2
|
||||
4'b1011: if(sampleNow) RxD_state <= 4'b1100; // bit 3
|
||||
4'b1100: if(sampleNow) RxD_state <= 4'b1101; // bit 4
|
||||
4'b1101: if(sampleNow) RxD_state <= 4'b1110; // bit 5
|
||||
4'b1110: if(sampleNow) RxD_state <= 4'b1111; // bit 6
|
||||
4'b1111: if(sampleNow) RxD_state <= 4'b0010; // bit 7
|
||||
4'b0010: if(sampleNow) RxD_state <= 4'b0000; // stop bit
|
||||
default: RxD_state <= 4'b0000;
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge clk or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
RxD_data <= 0;
|
||||
else
|
||||
if (sampleNow && RxD_state[3]) RxD_data <= {RxD_bit, RxD_data[7:1]};
|
||||
end
|
||||
|
||||
always @(posedge clk or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
RxD_data_ready <= 0;
|
||||
else
|
||||
RxD_data_ready <= (sampleNow && RxD_state==4'b0010 && RxD_bit); // make sure a stop bit is received
|
||||
end
|
||||
|
||||
reg [l2o+1:0] GapCnt;
|
||||
always @(posedge clk or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
GapCnt <= 0;
|
||||
else
|
||||
if (RxD_state!=0) GapCnt<=0; else if(OversamplingTick & ~GapCnt[log2(Oversampling)+1]) GapCnt <= GapCnt + 1'h1;
|
||||
end
|
||||
|
||||
assign RxD_idle = GapCnt[l2o+1];
|
||||
always @(posedge clk)
|
||||
RxD_endofpacket <= OversamplingTick & ~GapCnt[l2o+1] & &GapCnt[l2o:0];
|
||||
|
||||
endmodule
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
module BaudTickGen(
|
||||
input clk, rst, enable,
|
||||
output tick // generate a tick at the specified baud rate * oversampling
|
||||
);
|
||||
|
||||
parameter ClkFrequency = 25000000;
|
||||
parameter Baud = 115200;
|
||||
parameter Oversampling = 1;
|
||||
|
||||
function integer log2(input integer v); begin log2=0; while(v>>log2) log2=log2+1; end endfunction
|
||||
|
||||
localparam AccWidth = log2(ClkFrequency/Baud)+8; // +/- 2% max timing error over a byte
|
||||
reg [AccWidth:0] Acc;
|
||||
localparam ShiftLimiter = log2(Baud*Oversampling >> (31-AccWidth)); // this makes sure Inc calculation doesn't overflow
|
||||
localparam Inc = ((Baud*Oversampling << (AccWidth-ShiftLimiter))+(ClkFrequency>>(ShiftLimiter+1)))/(ClkFrequency>>ShiftLimiter);
|
||||
|
||||
always @(posedge clk)
|
||||
begin
|
||||
if (rst)
|
||||
Acc <= 0;
|
||||
else
|
||||
if(enable) Acc <= Acc[AccWidth-1:0] + Inc[AccWidth:0]; else Acc <= Inc[AccWidth:0];
|
||||
end
|
||||
assign tick = Acc[AccWidth];
|
||||
|
||||
endmodule
|
35
rtl/build_id.tcl
Normal file
35
rtl/build_id.tcl
Normal 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
|
55
rtl/clock.v
Normal file
55
rtl/clock.v
Normal file
@ -0,0 +1,55 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
//
|
||||
// Description: Clock divider to provide clock enables for
|
||||
// devices.
|
||||
//
|
||||
// Author.....: Alan Garfield
|
||||
// Niels A. Moseley
|
||||
// Date.......: 29-1-2018
|
||||
//
|
||||
|
||||
module clock
|
||||
(
|
||||
input clk14, // 14MHz clock master clock
|
||||
input rst_n, // active low synchronous reset
|
||||
|
||||
// Clock enables
|
||||
output reg cpu_clken // 1MHz clock enable for the CPU and devices
|
||||
);
|
||||
|
||||
// generate clock enable once every
|
||||
// 14 clocks. This will (hopefully) make
|
||||
// the 6502 run at 1 MHz
|
||||
//
|
||||
// the clock division counter is synchronously
|
||||
// reset using rst_n to avoid undefined signals
|
||||
// in simulation
|
||||
//
|
||||
|
||||
reg [4:0] clk_div;
|
||||
always @(posedge clk14)
|
||||
begin
|
||||
if ((clk_div == 14) || (rst_n == 1'b0))
|
||||
clk_div <= 0;
|
||||
else
|
||||
clk_div <= clk_div + 1'b1;
|
||||
|
||||
cpu_clken <= (clk_div[4:0] == 0);
|
||||
end
|
||||
|
||||
endmodule
|
72
rtl/debounce.v
Normal file
72
rtl/debounce.v
Normal file
@ -0,0 +1,72 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
//
|
||||
// Description: PS/2 keyboard debounce logic to be used for the
|
||||
// clock line
|
||||
//
|
||||
// Author.....: Niels A. Moseley
|
||||
// Date.......: 8-2-2018
|
||||
//
|
||||
|
||||
module debounce(
|
||||
input clk14, // 25MHz clock
|
||||
input rst, // active high reset
|
||||
|
||||
input sig_in, // input signal
|
||||
output reg sig_out // debounced output signal
|
||||
);
|
||||
|
||||
wire clk_enb; // enable triggering at clk14 divided by 64
|
||||
reg [5:0] clk_div; // clock divider counter
|
||||
|
||||
reg sig_ff1; // first input signal synchronizer
|
||||
reg sig_ff2; // second input signal synchronizer
|
||||
|
||||
assign clk_enb = (clk_div == 6'd0);
|
||||
|
||||
// clock divider
|
||||
always @(posedge clk14 or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
clk_div <= 6'd0;
|
||||
else
|
||||
clk_div <= clk_div + 6'd1;
|
||||
end
|
||||
|
||||
// debounce timer
|
||||
always @(posedge clk14 or posedge rst)
|
||||
begin
|
||||
if (rst)
|
||||
begin
|
||||
sig_out <= 1'b0;
|
||||
sig_ff1 <= 1'b0;
|
||||
sig_ff2 <= 1'b0;
|
||||
end
|
||||
else if (clk_enb)
|
||||
begin
|
||||
// this runs ar approximately 391k Hz
|
||||
// giving a debounce time of around 2.5us
|
||||
sig_ff1 <= sig_in;
|
||||
sig_ff2 <= sig_ff1;
|
||||
if ((sig_ff1 ^ sig_ff2) == 1'd0)
|
||||
begin
|
||||
sig_out <= sig_ff2;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
70
rtl/font_rom.v
Normal file
70
rtl/font_rom.v
Normal file
@ -0,0 +1,70 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||