From ca3282b39366c29a084afb1249b517312e64419b Mon Sep 17 00:00:00 2001 From: Marcel Date: Sun, 18 Aug 2019 22:38:49 +0200 Subject: [PATCH] Acorn System 1 WIP --- .../Acorn - System1/Acorn_System1.qpf | 31 + .../Acorn - System1/Acorn_System1.qsf | 166 ++ .../Acorn - System1/Acorn_System1.srf | 6 + Computer_MiST/Acorn - System1/README.txt | 37 + .../Snapshot/Acorn_System1.rbf | Bin 0 -> 232758 bytes Computer_MiST/Acorn - System1/clean.bat | 15 + Computer_MiST/Acorn - System1/rtl/ALU.v | 108 ++ Computer_MiST/Acorn - System1/rtl/System1.v | 327 ++++ .../Acorn - System1/rtl/System1_MiST.sv | 296 +++ .../Acorn - System1/rtl/build_id.tcl | 35 + Computer_MiST/Acorn - System1/rtl/cpu.v | 1220 ++++++++++++ .../Acorn - System1/rtl/debounce.vhd | 58 + Computer_MiST/Acorn - System1/rtl/gen_ram.vhd | 82 + Computer_MiST/Acorn - System1/rtl/m6522.v | 1074 +++++++++++ Computer_MiST/Acorn - System1/rtl/pll.ppf | 10 + Computer_MiST/Acorn - System1/rtl/pll.qip | 4 + Computer_MiST/Acorn - System1/rtl/pll.v | 329 ++++ Computer_MiST/Acorn - System1/rtl/ps2_mouse.v | 78 + .../Acorn - System1/rtl/ps2_mouse.vhd | 173 ++ .../Acorn - System1/rtl/ps2_transceiver.vhd | 181 ++ .../Acorn - System1/rtl/roms/ONE.mif | 53 + .../Acorn - System1/rtl/roms/acrnsys1.bin | Bin 0 -> 512 bytes .../Acorn - System1/rtl/roms/acrnsys1.vhd | 54 + .../Acorn - System1/rtl/roms/monitor.mif | 32 + Computer_MiST/Acorn - System1/rtl/vga.v | 1638 +++++++++++++++++ 25 files changed, 6007 insertions(+) create mode 100644 Computer_MiST/Acorn - System1/Acorn_System1.qpf create mode 100644 Computer_MiST/Acorn - System1/Acorn_System1.qsf create mode 100644 Computer_MiST/Acorn - System1/Acorn_System1.srf create mode 100644 Computer_MiST/Acorn - System1/README.txt create mode 100644 Computer_MiST/Acorn - System1/Snapshot/Acorn_System1.rbf create mode 100644 Computer_MiST/Acorn - System1/clean.bat create mode 100644 Computer_MiST/Acorn - System1/rtl/ALU.v create mode 100644 Computer_MiST/Acorn - System1/rtl/System1.v create mode 100644 Computer_MiST/Acorn - System1/rtl/System1_MiST.sv create mode 100644 Computer_MiST/Acorn - System1/rtl/build_id.tcl create mode 100644 Computer_MiST/Acorn - System1/rtl/cpu.v create mode 100644 Computer_MiST/Acorn - System1/rtl/debounce.vhd create mode 100644 Computer_MiST/Acorn - System1/rtl/gen_ram.vhd create mode 100644 Computer_MiST/Acorn - System1/rtl/m6522.v create mode 100644 Computer_MiST/Acorn - System1/rtl/pll.ppf create mode 100644 Computer_MiST/Acorn - System1/rtl/pll.qip create mode 100644 Computer_MiST/Acorn - System1/rtl/pll.v create mode 100644 Computer_MiST/Acorn - System1/rtl/ps2_mouse.v create mode 100644 Computer_MiST/Acorn - System1/rtl/ps2_mouse.vhd create mode 100644 Computer_MiST/Acorn - System1/rtl/ps2_transceiver.vhd create mode 100644 Computer_MiST/Acorn - System1/rtl/roms/ONE.mif create mode 100644 Computer_MiST/Acorn - System1/rtl/roms/acrnsys1.bin create mode 100644 Computer_MiST/Acorn - System1/rtl/roms/acrnsys1.vhd create mode 100644 Computer_MiST/Acorn - System1/rtl/roms/monitor.mif create mode 100644 Computer_MiST/Acorn - System1/rtl/vga.v diff --git a/Computer_MiST/Acorn - System1/Acorn_System1.qpf b/Computer_MiST/Acorn - System1/Acorn_System1.qpf new file mode 100644 index 00000000..e17aa063 --- /dev/null +++ b/Computer_MiST/Acorn - System1/Acorn_System1.qpf @@ -0,0 +1,31 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 2016 Intel Corporation. All rights reserved. +# Your use of Intel 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 Intel Program License +# Subscription Agreement, the Intel Quartus Prime License Agreement, +# the Intel 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 Intel and sold by Intel or its +# authorized distributors. Please refer to the applicable +# agreement for further details. +# +# -------------------------------------------------------------------------- # +# +# Quartus Prime +# Version 16.1.0 Build 196 10/24/2016 SJ Lite Edition +# Date created = 11:17:10 October 25, 2017 +# +# -------------------------------------------------------------------------- # + +QUARTUS_VERSION = "16.1" +DATE = "11:17:10 October 25, 2017" + +# Revisions + +PROJECT_REVISION = "Acorn_System1" diff --git a/Computer_MiST/Acorn - System1/Acorn_System1.qsf b/Computer_MiST/Acorn - System1/Acorn_System1.qsf new file mode 100644 index 00000000..f7990cbc --- /dev/null +++ b/Computer_MiST/Acorn - System1/Acorn_System1.qsf @@ -0,0 +1,166 @@ +# -------------------------------------------------------------------------- # +# +# Copyright (C) 1991-2014 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.4 Build 182 03/12/2014 SJ Web Edition +# Date created = 16:10:44 August 12, 2019 +# +# -------------------------------------------------------------------------- # +# +# Notes: +# +# 1) The default values for assignments are stored in the file: +# Acorn_System1_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 15.1.0 +set_global_assignment -name PROJECT_CREATION_TIME_DATE "17:45:13 JUNE 17,2016" +set_global_assignment -name LAST_QUARTUS_VERSION 13.1 +set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files +set_global_assignment -name NUM_PARALLEL_PROCESSORS ALL +set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:rtl/build_id.tcl" + +# 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 + +# 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_DO_CCPP_REMOVAL ON + +# Analysis & Synthesis Assignments +# ================================ +set_global_assignment -name TOP_LEVEL_ENTITY System1_MiST +set_global_assignment -name FAMILY "Cyclone III" +set_global_assignment -name DEVICE_FILTER_PACKAGE TQFP +set_global_assignment -name DEVICE_FILTER_PIN_COUNT 144 +set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8 + +# Fitter Assignments +# ================== +set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF +set_global_assignment -name DEVICE EP3C25E144C8 +set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF +set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL" +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" +set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF +set_global_assignment -name ENABLE_NCE_PIN OFF + +# 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 + +# SignalTap II Assignments +# ======================== +set_global_assignment -name ENABLE_SIGNALTAP OFF +set_global_assignment -name USE_SIGNALTAP_FILE output_files/stp1.stp + +# 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_FAR_END_VMEAS "HALF SIGNAL SWING" -fall +set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall +set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise + +# ---------------------- +# start ENTITY(SNES_top) + + # start DESIGN_PARTITION(Top) + # --------------------------- + + # Incremental Compilation Assignments + # =================================== + + # end DESIGN_PARTITION(Top) + # ------------------------- + +# end ENTITY(SNES_top) +# -------------------- +set_global_assignment -name SYSTEMVERILOG_FILE rtl/System1_MiST.sv +set_global_assignment -name VERILOG_FILE rtl/System1.v +set_global_assignment -name VERILOG_FILE rtl/cpu.v +set_global_assignment -name VERILOG_FILE rtl/ALU.v +set_global_assignment -name VERILOG_FILE rtl/m6522.v +set_global_assignment -name VHDL_FILE rtl/roms/acrnsys1.vhd +set_global_assignment -name VHDL_FILE rtl/gen_ram.vhd +set_global_assignment -name VERILOG_FILE rtl/vga.v +set_global_assignment -name QIP_FILE ../../Mist_FPGA/common/mist/mist.qip +set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top +set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top +set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top +set_global_assignment -name VERILOG_FILE rtl/pll.v +set_global_assignment -name VHDL_FILE rtl/ps2_mouse.vhd +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/Computer_MiST/Acorn - System1/Acorn_System1.srf b/Computer_MiST/Acorn - System1/Acorn_System1.srf new file mode 100644 index 00000000..d63be27f --- /dev/null +++ b/Computer_MiST/Acorn - System1/Acorn_System1.srf @@ -0,0 +1,6 @@ +{ "" "" "" "Verilog HDL or VHDL warning at cpu.v(148): object \"brk\" assigned a value but never read" { } { } 0 10036 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Verilog HDL assignment warning at cpu.v(720): truncated value with size 32 to match size of target (1)" { } { } 0 10230 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Verilog HDL assignment warning at cpu.v(717): truncated value with size 32 to match size of target (1)" { } { } 0 10230 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Verilog HDL assignment warning at cpu.v(661): truncated value with size 32 to match size of target (8)" { } { } 0 10230 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Verilog HDL assignment warning at ALU.v(50): truncated value with size 32 to match size of target (1)" { } { } 0 10230 "" 0 0 "Quartus II" 0 -1 0 ""} +{ "" "" "" "Verilog HDL assignment warning at ALU.v(73): truncated value with size 9 to match size of target (8)" { } { } 0 10230 "" 0 0 "Quartus II" 0 -1 0 ""} diff --git a/Computer_MiST/Acorn - System1/README.txt b/Computer_MiST/Acorn - System1/README.txt new file mode 100644 index 00000000..8b80e55a --- /dev/null +++ b/Computer_MiST/Acorn - System1/README.txt @@ -0,0 +1,37 @@ +Acorn System 1 - Port to MiST + +ToDo: Mouse and Keyboard + + + + +This is a port of Acorn System 1 inspired by the work of David Banks. + + +This version has a huge 512 bytes of rom +and a massive 1024 bytes of memory. The display is the latest 9 digit (only 8 used )7 segment plus dp. +The keyboard is 25 soft touch positive click switches. + +My first computer was a system 1. I could spend hours entering one machine +code instruction at a time, then more hours debugging my mistakes. +Then switch off and it was all lost. +Ahh those were the days. + +I would think that this port will be of limited interest but I could not find any other +port of this machine. + +The mouse is the yellow dot on the screen. Left click to press switch. + +At present this is a basic system 1 there are no bells or whistles. +No input (tape) or output as yet. + +You will have to forgive the vga output, all hand drawn using several hundred 'if' statements. + +The quickest way to test is after load, press the rst key. Press 'm' key. +Enter '0015' and press 'm' again. +The address 0015 is the 3rd character from the right. The value shouls read 80. +type any hex character to change the value and the character will change. + + + +Dave Wood (oldgit) \ No newline at end of file diff --git a/Computer_MiST/Acorn - System1/Snapshot/Acorn_System1.rbf b/Computer_MiST/Acorn - System1/Snapshot/Acorn_System1.rbf new file mode 100644 index 0000000000000000000000000000000000000000..9acf5abb039d9f19866925032337abfed3c7f70a GIT binary patch literal 232758 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 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 diff --git a/Computer_MiST/Acorn - System1/rtl/System1.v b/Computer_MiST/Acorn - System1/rtl/System1.v new file mode 100644 index 00000000..fe4b842e --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/System1.v @@ -0,0 +1,327 @@ +// ======================================================================= +// +// +// An Acorn System1 implementation for the Mister +// +// Copyright (C) 2019 Dave Wood +// +// This program 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 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. 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/. +// ======================================================================= + + +module System1( + input clk25, + input reset, + output reg[8:0]ch0,ch1,ch2,ch3,ch4,ch5,ch6,ch7, + input sw0,sw1,sw2,sw3,sw4,sw5,sw6,sw7,sw8,sw9,swa,swb,swc,swd,swe,swf,swrst,swm,swl,swg,swr,swp,swU,sws,swD, +// Cassette / Sound + input cas_in, + output cas_out +); + +wire rom_cs; +wire [7:0] rom_dout; +acrnsys1 MONROM( + .clk(clk25 & rom_cs), + .addr(address[8:0]), + .data(rom_dout) +); + +wire ram_cs; +wire ram_wr = (!rnw & ram_cs); +wire [7:0] ram_dout; +gen_ram #( + .dWidth(8), + .aWidth(10)) +MRAM ( + .clk(clk25 & ram_cs), + .we(ram_wr), + .addr(address[9:0]), + .d(cpu_dout), + .q(ram_dout) +); + + // =============================================================== + // Wires/Reg definitions + // TODO: reorganize so all defined here + // =============================================================== + + + reg rnw; + + reg [15:0] address; + reg [7:0] cpu_dout; + + wire [7:0] via_dout; + + wire via_irq_n; + + wire [1:0] turbo = 2'b00; + reg lock; + reg [2:0] phase = 3'b000; + reg [2:0] scan = 3'b111; + wire [7:0] PA_out; + reg [7:0] PA_tmp = 8'b00000000; + + + + // =============================================================== + // Clock Enable Generation + // =============================================================== + + reg cpu_clken; + reg via1_clken; + reg via4_clken; + + reg [4:0] clkdiv = 5'b00000; // divider, from 25MHz down to 1, 2, 4 or 8MHz + + always @(posedge clk25) begin + if (clkdiv == 24) + clkdiv <= 0; + else + clkdiv <= clkdiv + 1; + case (turbo) + 2'b00: // 1MHz + begin + cpu_clken <= (clkdiv[3:0] == 0) & (clkdiv[4] == 0); + via1_clken <= (clkdiv[3:0] == 0) & (clkdiv[4] == 0); + via4_clken <= (clkdiv[1:0] == 0) & (clkdiv[4] == 0); + end + 2'b01: // 2MHz + begin + cpu_clken <= (clkdiv[2:0] == 0) & (clkdiv[4] == 0); + via1_clken <= (clkdiv[2:0] == 0) & (clkdiv[4] == 0); + via4_clken <= (clkdiv[0] == 0) & (clkdiv[4] == 0); + end + default: // 4MHz + begin + cpu_clken <= (clkdiv[1:0] == 0) & (clkdiv[4] == 0); + via1_clken <= (clkdiv[1:0] == 0) & (clkdiv[4] == 0); + via4_clken <= (clkdiv[4] == 0); + end + endcase + + end + + + // =============================================================== + // Cassette + // =============================================================== + + // The Atom drives cas_tone from 4MHz / 16 / 13 / 8 + // 208 = 16 * 13, and start with 1MHz and toggle + // so it's basically the same + + reg cas_tone = 1'b0; + reg [7:0] cas_div = 0; + + always @(posedge clk25) begin + + + if (cpu_clken) + begin + if (cas_div == 207) + begin + cas_div <= 0; + cas_tone <= !cas_tone; + end + else + cas_div <= cas_div + 1; + end + + end + + // this is a direct translation of the logic in the atom + // (two NAND gates and an inverter) +// assign cas_out = !(!(!cas_tone & pia_pc[1]) & pia_pc[0]); +// assign PB_in[7] = cas_in; + + + + // =============================================================== + // 6502 CPU + // =============================================================== + + wire [7:0] cpu_din; + wire [7:0] cpu_dout_c; + wire [15:0] address_c; + wire rnw_c; + + // Arlet's 6502 core is one of the smallest available + cpu CPU + ( + .clk(clk25), + .reset(swrst | reset), + .AB(address_c), + .DI(cpu_din), + .DO(cpu_dout_c), + .WE(rnw_c), + .IRQ(1'b0), //(!via_irq_n), + .NMI(1'b0), + .RDY(cpu_clken) + ); + + // The outputs of Arlets's 6502 core need registing + always @(posedge clk25) + begin + if (cpu_clken) + begin + address <= address_c; + cpu_dout <= cpu_dout_c; + rnw <= !rnw_c; + end + end + + // =============================================================== + // Address decoding logic and data in multiplexor + // =============================================================== + + // 0000-3FFF RAM + + // 0Exx-0Fxx 6522 VIA + + // FExx-FFxx Monitor Prom + + assign rom_cs = (address[15:9] == 7'b1111111); //FE00 - FFFF + wire via_cs = (address[15:9] == 7'b0000111); //0Exx + assign ram_cs = (address[15:10] == 6'b000000); //0000 - 003F + + assign cpu_din = via_cs ? via_dout : + ram_cs ? ram_dout : + rom_cs ? rom_dout : + 8'b11111111; + + // =============================================================== + // 6522 VIA at 0x0Exx + // =============================================================== + + wire [7:0] PB_out; + wire [7:0] PB_oe,PA_oe; + reg [7:0] PB_in; + wire pressed = (~sw0 & ~sw1 & ~sw2 & ~sw3 & ~sw4 & ~sw5 & ~sw6 & ~sw7 & ~sw8 & ~sw9 & ~swa & ~swb & ~swc & ~swd & ~swe & ~swf & ~swm & ~swl & ~swg & ~swr & ~swp & ~swU & ~sws & ~swD); + + always @(posedge via1_clken) begin + if (pressed) PB_in <= 8'b00111111; + if (phase == 3'b000 && PB_out[2:0] == 3'b111) begin + ch0 <= PA_out; + phase = 3'b001; + if (sw7) PB_in <= 8'b00011111; + if (swD) PB_in <= 8'b00101111; + if (swf) PB_in <= 8'b00110111; + end + if (phase == 3'b001 && PB_out[2:0] == 3'b110) begin + ch1 <= PA_out; + phase = 3'b010; + if (sw6) PB_in <= 8'b00011111; + if (swU) PB_in <= 8'b00101111; + if (swe) PB_in <= 8'b00110111; + end + if (phase == 3'b010 && PB_out[2:0] == 3'b101) begin + ch2 <= PA_out; + phase = 3'b011; + if (sw5) PB_in <= 8'b00011111; + if (swr) PB_in <= 8'b00101111; + if (swd) PB_in <= 8'b00110111; + end + if (phase == 3'b011 && PB_out[2:0] == 3'b100) begin + ch3 <= PA_out; + phase = 3'b100; + if (sw4) PB_in <= 8'b00011111; + if (swl) PB_in <= 8'b00101111; + if (swc) PB_in <= 8'b00110111; + end + if (phase == 3'b100 && PB_out[2:0] == 3'b011) begin + ch4 <= PA_out; + phase = 3'b101; + if (sw3) PB_in <= 8'b00011111; + if (sws) PB_in <= 8'b00101111; + if (swb) PB_in <= 8'b00110111; + end + if (phase == 3'b101 && PB_out[2:0] == 3'b010) begin + ch5 <= PA_out; + phase = 3'b110; + if (sw2) PB_in <= 8'b00011111; + if (swp) PB_in <= 8'b00101111; + if (swa) PB_in <= 8'b00110111; + end + if (phase == 3'b110 && PB_out[2:0] == 3'b001) begin + ch6 <= PA_out; + phase = 3'b111; + if (sw1) PB_in <= 8'b00011111; + if (swg) PB_in <= 8'b00101111; + if (sw9) PB_in <= 8'b00110111; + end + if (phase == 3'b111 && PB_out[2:0] == 3'b000) begin + ch7 <= PA_out; + phase = 3'b000; + if (sw0) PB_in <= 8'b00011111; + if (swm) PB_in <= 8'b00101111; + if (sw8) PB_in <= 8'b00110111; + end + end + + + m6522 VIA + ( + .I_RS(address[3:0]), + .I_DATA(cpu_dout), + .O_DATA(via_dout), + .O_DATA_OE_L(), + .I_RW_L(rnw), + .I_CS1(via_cs), + .I_CS2_L(1'b0), + .O_IRQ_L(via_irq_n), + .I_CA1(1'b0), + .I_CA2(1'b0), + .O_CA2(), + .O_CA2_OE_L(), + .I_PA(8'b0), + .O_PA(PA_out), + .O_PA_OE_L(PA_oe), + .I_CB1(1'b0), + .O_CB1(), + .O_CB1_OE_L(), + .I_CB2(1'b0), + .O_CB2(), + .O_CB2_OE_L(), + .I_PB(PB_in), + .O_PB(PB_out), + .O_PB_OE_L(PB_oe), + .I_P2_H(via1_clken), + .RESET_L(!reset), + .ENA_4(via4_clken), + .CLK(clk25) + ); + +/* + wire [7:0] digit_0 = 8'h3F; + wire [7:0] digit_1 = 8'h06; + wire [7:0] digit_2 = 8'h5B; + wire [7:0] digit_3 = 8'h4F; + wire [7:0] digit_4 = 8'h66; + wire [7:0] digit_5 = 8'h6D; + wire [7:0] digit_6 = 8'h7D; + wire [7:0] digit_7 = 8'h07; + wire [7:0] digit_8 = 8'h7F; + wire [7:0] digit_9 = 8'h6F; + wire [7:0] digit_A = 8'h77; + wire [7:0] digit_B = 8'h7C; + wire [7:0] digit_C = 8'h58; + wire [7:0] digit_D = 8'h5E; + wire [7:0] digit_E = 8'h79; + wire [7:0] digit_F = 8'h71; +*/ + + +endmodule diff --git a/Computer_MiST/Acorn - System1/rtl/System1_MiST.sv b/Computer_MiST/Acorn - System1/rtl/System1_MiST.sv new file mode 100644 index 00000000..20fb3392 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/System1_MiST.sv @@ -0,0 +1,296 @@ +module System1_MiST( + input CLOCK_27, + output [5:0] VGA_R, + output [5:0] VGA_G, + output [5:0] VGA_B, + output VGA_HS, + output VGA_VS, + output LED, + input SPI_SCK, + output SPI_DO, + input SPI_DI, + input SPI_SS2, + input SPI_SS3, + input CONF_DATA0 +); + +`include "build_id.v" +localparam CONF_STR = { + "System1;;", + "T6,Reset;", + "V,v1.00.",`BUILD_DATE +}; +wire clk_sys; +wire key_pressed; +wire [7:0] key_code; +wire key_strobe; +wire key_extended; +wire [8:0] mouse_x,mouse_y; +wire [7:0] mouse_flags; +wire [7:0] r, g, b; +wire hs, vs, hb, vb; +wire blankn = ~(hb | vb); +wire [1:0] buttons, switches; +wire ypbpr; +wire scandoublerD; +wire [31:0] status; + +assign LED = 1'b1; + +pll pll ( + .inclk0 (CLOCK_27 ), + .c0 (clk_sys )//25 + ); + +user_io #( + .STRLEN (($size(CONF_STR)>>3))) +user_io( + .clk_sys (clk_sys ), + .conf_str (CONF_STR ), + .SPI_CLK (SPI_SCK ), + .SPI_SS_IO (CONF_DATA0 ), + .SPI_MISO (SPI_DO ), + .SPI_MOSI (SPI_DI ), + .buttons (buttons ), + .switches (switches ), + .scandoubler_disable (scandoublerD ), + .ypbpr (ypbpr ), + .key_strobe (key_strobe ), + .key_pressed (key_pressed ), + .key_extended (key_extended ), + .key_code (key_code ), + .mouse_x (mouse_x ), + .mouse_y (mouse_y ), + .status (status ) + ); + +mist_video #(.COLOR_DEPTH(6)) mist_video( + .clk_sys (clk_sys ), + .SPI_SCK (SPI_SCK ), + .SPI_SS3 (SPI_SS3 ), + .SPI_DI (SPI_DI ), + .R (blankn ? r[7:2] : 0), + .G (blankn ? g[7:2] : 0), + .B (blankn ? b[7:2] : 0), + .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 ), + .ypbpr (ypbpr ) + ); + +wire reset = (status[0] | status[6] | buttons[1]); +wire [8:0] ch0,ch1,ch2,ch3,ch4,ch5,ch6,ch7; +wire sw0,sw1,sw2,sw3,sw4,sw5,sw6,sw7,sw8,sw9,swa,swb,swc,swd,swe,swf,swrst,swm,swl,swg,swr,swp,swUP,sws,swDW; + +System1 System1( + .clk25(clk_sys), + .reset(reset), + .ch0(ch0), + .ch1(ch1), + .ch2(ch2), + .ch3(ch3), + .ch4(ch4), + .ch5(ch5), + .ch6(ch6), + .ch7(ch7), + .sw0(sw0 | tsw0), + .sw1(sw1 | tsw1), + .sw2(sw2 | tsw2), + .sw3(sw3 | tsw3), + .sw4(sw4 | tsw4), + .sw5(sw5 | tsw5), + .sw6(sw6 | tsw6), + .sw7(sw7 | tsw7), + .sw8(sw8 | tsw8), + .sw9(sw9 | tsw9), + .swa(swa | tswa), + .swb(swb | tswb), + .swc(swc | tswc), + .swd(swd | tswd), + .swe(swe | tswe), + .swf(swf | tswf), + .swrst(swrst | tswrst), + .swm(swm | tswm), + .swl(swl | tswl), + .swg(swg | tswg), + .swr(swr | tswr), + .swp(swp | tswp), + .swU(swUP | tswUP), + .sws(sws | tsws), + .swD(swDW | tswDW), + .cas_in(1'b0), + .cas_out() +); + +vga vga( + .clk(clk_sys), + .rst(reset), + .mbtnL(mouse_flags[0]), + .mbtnR(mouse_flags[1]), + .mbtnM(mouse_flags[2]), + .mx(mouse_x),//mx), + .my(mouse_y),//my), + .ch0(ch0), + .ch1(ch1), + .ch2(ch2), + .ch3(ch3), + .ch4(ch4), + .ch5(ch5), + .ch6(ch6), + .ch7(ch7), + .osw0(sw0), + .osw1(sw1), + .osw2(sw2), + .osw3(sw3), + .osw4(sw4), + .osw5(sw5), + .osw6(sw6), + .osw7(sw7), + .osw8(sw8), + .osw9(sw9), + .oswa(swa), + .oswb(swb), + .oswc(swc), + .oswd(swd), + .oswe(swe), + .oswf(swf), + .oswrst(swrst), + .oswm(swm), + .oswl(swl), + .oswg(swg), + .oswr(swr), + .oswp(swp), + .oswU(swUP), + .osws(sws), + .oswD(swDW), + + + .r(r), + .g(g), + .b(b), + .hs(hs), + .vs(vs), + .hblank(hb), + .vblank(vb) +); +/* +wire [10:0] mx,my; +wire x1,y1,mbtnL,mbtnR,mbtnM; + +ps2_mouse mouse +( + .clk(clk_sys), + .ce(1'b1), + .reset(reset), + .ps2_mouse(ps2_mouse), + .mx(mx), + .my(my), + .mbtnL(mbtnL), + .mbtnR(mbtnR), + .mbtnM(mbtnM) +);*/ +/* +ps2_mouse #( + .clk_freq : INTEGER := 50_000_000; --system clock frequency in Hz + .ps2_debounce_counter_size : INTEGER := 8); --set such that 2^size/clk_freq = 5us (size = 8 for 50MHz) +MOUSE( + .clk : IN STD_LOGIC; --system clock input + .reset_n : IN STD_LOGIC; --active low asynchronous reset + .ps2_clk : INOUT STD_LOGIC; --clock signal from PS2 mouse + .ps2_data : INOUT STD_LOGIC; --data signal from PS2 mouse + .mouse_data : OUT STD_LOGIC_VECTOR(23 DOWNTO 0); --data received from mouse + .mouse_data_new : OUT STD_LOGIC + ); +*/ +reg tsw0 = 1'b0; +reg tsw1 = 1'b0; +reg tsw2 = 1'b0; +reg tsw3 = 1'b0; +reg tsw4 = 1'b0; +reg tsw5 = 1'b0; +reg tsw6 = 1'b0; +reg tsw7 = 1'b0; +reg tsw8 = 1'b0; +reg tsw9 = 1'b0; +reg tswa = 1'b0; +reg tswb = 1'b0; +reg tswc = 1'b0; +reg tswd = 1'b0; +reg tswe = 1'b0; +reg tswf = 1'b0; +reg tswm = 1'b0; +reg tswl = 1'b0; +reg tswg = 1'b0; +reg tswr = 1'b0; +reg tswp = 1'b0; +reg tswUP = 1'b0; +reg tsws = 1'b0; +reg tswDW = 1'b0; +reg tswrst = 1'b0; + + +always @(posedge clk_sys) begin + reg old_state; + old_state <= key_strobe; + + if(old_state != key_strobe) begin + casex(key_code) + 'h75: tswUP <= key_pressed; // up + 'h72: tswDW <= key_pressed; // down + + 'h45: tsw0 <= key_pressed; // 0 +// 'h70: tsw0 <= key_pressed; // 0 + + 'h16: tsw1 <= key_pressed; // 1 +// 'h69: tsw1 <= key_pressed; // 1 + + 'h1E: tsw2 <= key_pressed; // 2 +// 'h72: tsw2 <= key_pressed; // 2 + + 'h26: tsw3 <= key_pressed; // 3 +// 'h7A: tsw3 <= key_pressed; // 3 + + 'h25: tsw4 <= key_pressed; // 4 +// 'h6B: tsw4 <= key_pressed; // 4 + + 'h2E: tsw5 <= key_pressed; // 5 +// 'h73: tsw5 <= key_pressed; // 5 + + 'h36: tsw6 <= key_pressed; // 6 +// 'h74: tsw6 <= key_pressed; // 6 + + 'h3D: tsw7 <= key_pressed; // 7 +// 'h6C: tsw7 <= key_pressed; // 7 + + 'h3E: tsw8 <= key_pressed; // 8 +// 'h75: tsw8 <= key_pressed; // 8 + + 'h46: tsw9 <= key_pressed; // 9 +// 'h7D: tsw9 <= key_pressed; // 9 + + + 'h1C: tswa <= key_pressed; // a + 'h32: tswb <= key_pressed; // b + 'h21: tswc <= key_pressed; // c + 'h23: tswd <= key_pressed; // d + 'h24: tswe <= key_pressed; // e + 'h2B: tswf <= key_pressed; // f + 'h3A: tswm <= key_pressed; // m + 'h34: tswg <= key_pressed; // g + 'h4D: tswp <= key_pressed; // p + 'h1B: tsws <= key_pressed; // s + 'h4B: tswl <= key_pressed; // l + 'h2D: tswr <= key_pressed; // r +// 'h05: tswrst <= key_pressed; // F1 + endcase + end +end + + + +endmodule \ No newline at end of file diff --git a/Computer_MiST/Acorn - System1/rtl/build_id.tcl b/Computer_MiST/Acorn - System1/rtl/build_id.tcl new file mode 100644 index 00000000..938515d8 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/build_id.tcl @@ -0,0 +1,35 @@ +# ================================================================================ +# +# Build ID Verilog Module Script +# Jeff Wiencrot - 8/1/2011 +# +# Generates a Verilog module that contains a timestamp, +# from the current build. These values are available from the build_date, build_time, +# physical_address, and host_name output ports of the build_id module in the build_id.v +# Verilog source file. +# +# ================================================================================ + +proc generateBuildID_Verilog {} { + + # Get the timestamp (see: http://www.altera.com/support/examples/tcl/tcl-date-time-stamp.html) + set buildDate [ clock format [ clock seconds ] -format %y%m%d ] + set buildTime [ clock format [ clock seconds ] -format %H%M%S ] + + # Create a Verilog file for output + set outputFileName "rtl/build_id.v" + set outputFile [open $outputFileName "w"] + + # Output the Verilog source + puts $outputFile "`define BUILD_DATE \"$buildDate\"" + puts $outputFile "`define BUILD_TIME \"$buildTime\"" + close $outputFile + + # Send confirmation message to the Messages window + post_message "Generated build identification Verilog module: [pwd]/$outputFileName" + post_message "Date: $buildDate" + post_message "Time: $buildTime" +} + +# Comment out this line to prevent the process from automatically executing when the file is sourced: +generateBuildID_Verilog \ No newline at end of file diff --git a/Computer_MiST/Acorn - System1/rtl/cpu.v b/Computer_MiST/Acorn - System1/rtl/cpu.v new file mode 100644 index 00000000..ed8da623 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/cpu.v @@ -0,0 +1,1220 @@ +/* + * verilog model of 6502 CPU. + * + * (C) Arlet Ottens, + * + * Feel free to use this code in any project (commercial or not), as long as you + * keep this message, and the copyright notice. This code is provided "as is", + * without any warranties of any kind. + * + */ + +/* + * Note that not all 6502 interface signals are supported (yet). The goal + * is to create an Acorn Atom model, and the Atom didn't use all signals on + * the main board. + * + * The data bus is implemented as separate read/write buses. Combine them + * on the output pads if external memory is required. + */ + +module cpu( clk, reset, AB, DI, DO, WE, IRQ, NMI, RDY ); + +input clk; // CPU clock +input reset; // reset signal +output reg [15:0] AB; // address bus +input [7:0] DI; // data in, read bus +output [7:0] DO; // data out, write bus +output WE; // write enable +input IRQ; // interrupt request +input NMI; // non-maskable interrupt request +input RDY; // Ready signal. Pauses CPU when RDY=0 + +/* + * internal signals + */ + +reg [15:0] PC; // Program Counter +reg [7:0] ABL; // Address Bus Register LSB +reg [7:0] ABH; // Address Bus Register MSB +wire [7:0] ADD; // Adder Hold Register (registered in ALU) + +reg [7:0] DIHOLD; // Hold for Data In +reg DIHOLD_valid; // +wire [7:0] DIMUX; // + +reg [7:0] IRHOLD; // Hold for Instruction register +reg IRHOLD_valid; // Valid instruction in IRHOLD + +reg [7:0] AXYS[3:0]; // A, X, Y and S register file + +reg C = 0; // carry flag (init at zero to avoid X's in ALU sim) +reg Z = 0; // zero flag +reg I = 0; // interrupt flag +reg D = 0; // decimal flag +reg V = 0; // overflow flag +reg N = 0; // negative flag +wire AZ; // ALU Zero flag +wire AV; // ALU overflow flag +wire AN; // ALU negative flag +wire HC; // ALU half carry + +reg [7:0] AI; // ALU Input A +reg [7:0] BI; // ALU Input B +wire [7:0] DI; // Data In +wire [7:0] IR; // Instruction register +reg [7:0] DO; // Data Out +reg WE; // Write Enable +reg CI; // Carry In +wire CO; // Carry Out +wire [7:0] PCH = PC[15:8]; +wire [7:0] PCL = PC[7:0]; + +reg NMI_edge = 0; // captured NMI edge + +reg [1:0] regsel; // Select A, X, Y or S register +wire [7:0] regfile = AXYS[regsel]; // Selected register output + +parameter + SEL_A = 2'd0, + SEL_S = 2'd1, + SEL_X = 2'd2, + SEL_Y = 2'd3; + +/* + * define some signals for watching in simulator output + */ + + +`ifdef SIM +wire [7:0] A = AXYS[SEL_A]; // Accumulator +wire [7:0] X = AXYS[SEL_X]; // X register +wire [7:0] Y = AXYS[SEL_Y]; // Y register +wire [7:0] S = AXYS[SEL_S]; // Stack pointer +`endif + +wire [7:0] P = { N, V, 2'b11, D, I, Z, C }; + +/* + * instruction decoder/sequencer + */ + +reg [5:0] state; + +/* + * control signals + */ + +reg PC_inc; // Increment PC +reg [15:0] PC_temp; // intermediate value of PC + +reg [1:0] src_reg; // source register index +reg [1:0] dst_reg; // destination register index + +reg index_y; // if set, then Y is index reg rather than X +reg load_reg; // loading a register (A, X, Y, S) in this instruction +reg inc; // increment +reg write_back; // set if memory is read/modified/written +reg load_only; // LDA/LDX/LDY instruction +reg store; // doing store (STA/STX/STY) +reg adc_sbc; // doing ADC/SBC +reg compare; // doing CMP/CPY/CPX +reg shift; // doing shift/rotate instruction +reg rotate; // doing rotate (no shift) +reg backwards; // backwards branch +reg cond_true; // branch condition is true +reg [2:0] cond_code; // condition code bits from instruction +reg shift_right; // Instruction ALU shift/rotate right +reg alu_shift_right; // Current cycle shift right enable +reg [3:0] op; // Main ALU operation for instruction +reg [3:0] alu_op; // Current cycle ALU operation +reg adc_bcd; // ALU should do BCD style carry +reg adj_bcd; // results should be BCD adjusted + +/* + * some flip flops to remember we're doing special instructions. These + * get loaded at the DECODE state, and used later + */ +reg bit_ins; // doing BIT instruction +reg plp; // doing PLP instruction +reg php; // doing PHP instruction +reg clc; // clear carry +reg sec; // set carry +reg cld; // clear decimal +reg sed; // set decimal +reg cli; // clear interrupt +reg sei; // set interrupt +reg clv; // clear overflow +reg brk; // doing BRK + +reg res; // in reset + +/* + * ALU operations + */ + +parameter + OP_OR = 4'b1100, + OP_AND = 4'b1101, + OP_EOR = 4'b1110, + OP_ADD = 4'b0011, + OP_SUB = 4'b0111, + OP_ROL = 4'b1011, + OP_A = 4'b1111; + +/* + * Microcode state machine. Basically, every addressing mode has its own + * path through the state machine. Additional information, such as the + * operation, source and destination registers are decoded in parallel, and + * kept in separate flops. + */ + +parameter + ABS0 = 6'd0, // ABS - fetch LSB + ABS1 = 6'd1, // ABS - fetch MSB + ABSX0 = 6'd2, // ABS, X - fetch LSB and send to ALU (+X) + ABSX1 = 6'd3, // ABS, X - fetch MSB and send to ALU (+Carry) + ABSX2 = 6'd4, // ABS, X - Wait for ALU (only if needed) + BRA0 = 6'd5, // Branch - fetch offset and send to ALU (+PC[7:0]) + BRA1 = 6'd6, // Branch - fetch opcode, and send PC[15:8] to ALU + BRA2 = 6'd7, // Branch - fetch opcode (if page boundary crossed) + BRK0 = 6'd8, // BRK/IRQ - push PCH, send S to ALU (-1) + BRK1 = 6'd9, // BRK/IRQ - push PCL, send S to ALU (-1) + BRK2 = 6'd10, // BRK/IRQ - push P, send S to ALU (-1) + BRK3 = 6'd11, // BRK/IRQ - write S, and fetch @ fffe + DECODE = 6'd12, // IR is valid, decode instruction, and write prev reg + FETCH = 6'd13, // fetch next opcode, and perform prev ALU op + INDX0 = 6'd14, // (ZP,X) - fetch ZP address, and send to ALU (+X) + INDX1 = 6'd15, // (ZP,X) - fetch LSB at ZP+X, calculate ZP+X+1 + INDX2 = 6'd16, // (ZP,X) - fetch MSB at ZP+X+1 + INDX3 = 6'd17, // (ZP,X) - fetch data + INDY0 = 6'd18, // (ZP),Y - fetch ZP address, and send ZP to ALU (+1) + INDY1 = 6'd19, // (ZP),Y - fetch at ZP+1, and send LSB to ALU (+Y) + INDY2 = 6'd20, // (ZP),Y - fetch data, and send MSB to ALU (+Carry) + INDY3 = 6'd21, // (ZP),Y) - fetch data (if page boundary crossed) + JMP0 = 6'd22, // JMP - fetch PCL and hold + JMP1 = 6'd23, // JMP - fetch PCH + JMPI0 = 6'd24, // JMP IND - fetch LSB and send to ALU for delay (+0) + JMPI1 = 6'd25, // JMP IND - fetch MSB, proceed with JMP0 state + JSR0 = 6'd26, // JSR - push PCH, save LSB, send S to ALU (-1) + JSR1 = 6'd27, // JSR - push PCL, send S to ALU (-1) + JSR2 = 6'd28, // JSR - write S + JSR3 = 6'd29, // JSR - fetch MSB + PULL0 = 6'd30, // PLP/PLA - save next op in IRHOLD, send S to ALU (+1) + PULL1 = 6'd31, // PLP/PLA - fetch data from stack, write S + PULL2 = 6'd32, // PLP/PLA - prefetch op, but don't increment PC + PUSH0 = 6'd33, // PHP/PHA - send A to ALU (+0) + PUSH1 = 6'd34, // PHP/PHA - write A/P, send S to ALU (-1) + READ = 6'd35, // Read memory for read/modify/write (INC, DEC, shift) + REG = 6'd36, // Read register for reg-reg transfers + RTI0 = 6'd37, // RTI - send S to ALU (+1) + RTI1 = 6'd38, // RTI - read P from stack + RTI2 = 6'd39, // RTI - read PCL from stack + RTI3 = 6'd40, // RTI - read PCH from stack + RTI4 = 6'd41, // RTI - read PCH from stack + RTS0 = 6'd42, // RTS - send S to ALU (+1) + RTS1 = 6'd43, // RTS - read PCL from stack + RTS2 = 6'd44, // RTS - write PCL to ALU, read PCH + RTS3 = 6'd45, // RTS - load PC and increment + WRITE = 6'd46, // Write memory for read/modify/write + ZP0 = 6'd47, // Z-page - fetch ZP address + ZPX0 = 6'd48, // ZP, X - fetch ZP, and send to ALU (+X) + ZPX1 = 6'd49; // ZP, X - load from memory + +`ifdef SIM + +/* + * easy to read names in simulator output + */ +reg [8*6-1:0] statename; + +always @* + case( state ) + DECODE: statename = "DECODE"; + REG: statename = "REG"; + ZP0: statename = "ZP0"; + ZPX0: statename = "ZPX0"; + ZPX1: statename = "ZPX1"; + ABS0: statename = "ABS0"; + ABS1: statename = "ABS1"; + ABSX0: statename = "ABSX0"; + ABSX1: statename = "ABSX1"; + ABSX2: statename = "ABSX2"; + INDX0: statename = "INDX0"; + INDX1: statename = "INDX1"; + INDX2: statename = "INDX2"; + INDX3: statename = "INDX3"; + INDY0: statename = "INDY0"; + INDY1: statename = "INDY1"; + INDY2: statename = "INDY2"; + INDY3: statename = "INDY3"; + READ: statename = "READ"; + WRITE: statename = "WRITE"; + FETCH: statename = "FETCH"; + PUSH0: statename = "PUSH0"; + PUSH1: statename = "PUSH1"; + PULL0: statename = "PULL0"; + PULL1: statename = "PULL1"; + PULL2: statename = "PULL2"; + JSR0: statename = "JSR0"; + JSR1: statename = "JSR1"; + JSR2: statename = "JSR2"; + JSR3: statename = "JSR3"; + RTI0: statename = "RTI0"; + RTI1: statename = "RTI1"; + RTI2: statename = "RTI2"; + RTI3: statename = "RTI3"; + RTI4: statename = "RTI4"; + RTS0: statename = "RTS0"; + RTS1: statename = "RTS1"; + RTS2: statename = "RTS2"; + RTS3: statename = "RTS3"; + BRK0: statename = "BRK0"; + BRK1: statename = "BRK1"; + BRK2: statename = "BRK2"; + BRK3: statename = "BRK3"; + BRA0: statename = "BRA0"; + BRA1: statename = "BRA1"; + BRA2: statename = "BRA2"; + JMP0: statename = "JMP0"; + JMP1: statename = "JMP1"; + JMPI0: statename = "JMPI0"; + JMPI1: statename = "JMPI1"; + endcase + +//always @( PC ) +// $display( "%t, PC:%04x IR:%02x A:%02x X:%02x Y:%02x S:%02x C:%d Z:%d V:%d N:%d P:%02x", $time, PC, IR, A, X, Y, S, C, Z, V, N, P ); + +`endif + + + +/* + * Program Counter Increment/Load. First calculate the base value in + * PC_temp. + */ +always @* + case( state ) + DECODE: if( (~I & IRQ) | NMI_edge ) + PC_temp = { ABH, ABL }; + else + PC_temp = PC; + + + JMP1, + JMPI1, + JSR3, + RTS3, + RTI4: PC_temp = { DIMUX, ADD }; + + BRA1: PC_temp = { ABH, ADD }; + + BRA2: PC_temp = { ADD, PCL }; + + BRK2: PC_temp = res ? 16'hfffc : + NMI_edge ? 16'hfffa : 16'hfffe; + + default: PC_temp = PC; + endcase + +/* + * Determine wether we need PC_temp, or PC_temp + 1 + */ +always @* + case( state ) + DECODE: if( (~I & IRQ) | NMI_edge ) + PC_inc = 0; + else + PC_inc = 1; + + ABS0, + ABSX0, + FETCH, + BRA0, + BRA2, + BRK3, + JMPI1, + JMP1, + RTI4, + RTS3: PC_inc = 1; + + BRA1: PC_inc = CO ^~ backwards; + + default: PC_inc = 0; + endcase + +/* + * Set new PC + */ +always @(posedge clk) + if( RDY ) + PC <= PC_temp + PC_inc; + +/* + * Address Generator + */ + +parameter + ZEROPAGE = 8'h00, + STACKPAGE = 8'h01; + +always @* + case( state ) + ABSX1, + INDX3, + INDY2, + JMP1, + JMPI1, + RTI4, + ABS1: AB = { DIMUX, ADD }; + + BRA2, + INDY3, + ABSX2: AB = { ADD, ABL }; + + BRA1: AB = { ABH, ADD }; + + JSR0, + PUSH1, + RTS0, + RTI0, + BRK0: AB = { STACKPAGE, regfile }; + + BRK1, + JSR1, + PULL1, + RTS1, + RTS2, + RTI1, + RTI2, + RTI3, + BRK2: AB = { STACKPAGE, ADD }; + + INDY1, + INDX1, + ZPX1, + INDX2: AB = { ZEROPAGE, ADD }; + + ZP0, + INDY0: AB = { ZEROPAGE, DIMUX }; + + REG, + READ, + WRITE: AB = { ABH, ABL }; + + default: AB = PC; + endcase + +/* + * ABH/ABL pair is used for registering previous address bus state. + * This can be used to keep the current address, freeing up the original + * source of the address, such as the ALU or DI. + */ +always @(posedge clk) + if( state != PUSH0 && state != PUSH1 && RDY && + state != PULL0 && state != PULL1 && state != PULL2 ) + begin + ABL <= AB[7:0]; + ABH <= AB[15:8]; + end + +/* + * Data Out MUX + */ +always @* + case( state ) + WRITE: DO = ADD; + + JSR0, + BRK0: DO = PCH; + + JSR1, + BRK1: DO = PCL; + + PUSH1: DO = php ? P : ADD; + + BRK2: DO = (IRQ | NMI_edge) ? (P & 8'b1110_1111) : P; + + default: DO = regfile; + endcase + +/* + * Write Enable Generator + */ + +always @* + case( state ) + BRK0, // writing to stack or memory + BRK1, + BRK2, + JSR0, + JSR1, + PUSH1, + WRITE: WE = 1; + + INDX3, // only if doing a STA, STX or STY + INDY3, + ABSX2, + ABS1, + ZPX1, + ZP0: WE = store; + + default: WE = 0; + endcase + +/* + * register file, contains A, X, Y and S (stack pointer) registers. At each + * cycle only 1 of those registers needs to be accessed, so they combined + * in a small memory, saving resources. + */ + +reg write_register; // set when register file is written + +always @* + case( state ) + DECODE: write_register = load_reg & ~plp; + + PULL1, + RTS2, + RTI3, + BRK3, + JSR0, + JSR2 : write_register = 1; + + default: write_register = 0; + endcase + +/* + * BCD adjust logic + */ + +always @(posedge clk) + adj_bcd <= adc_sbc & D; // '1' when doing a BCD instruction + +reg [3:0] ADJL; +reg [3:0] ADJH; + +// adjustment term to be added to ADD[3:0] based on the following +// adj_bcd: '1' if doing ADC/SBC with D=1 +// adc_bcd: '1' if doing ADC with D=1 +// HC : half carry bit from ALU +always @* begin + casex( {adj_bcd, adc_bcd, HC} ) + 3'b0xx: ADJL = 4'd0; // no BCD instruction + 3'b100: ADJL = 4'd10; // SBC, and digital borrow + 3'b101: ADJL = 4'd0; // SBC, but no borrow + 3'b110: ADJL = 4'd0; // ADC, but no carry + 3'b111: ADJL = 4'd6; // ADC, and decimal/digital carry + endcase +end + +// adjustment term to be added to ADD[7:4] based on the following +// adj_bcd: '1' if doing ADC/SBC with D=1 +// adc_bcd: '1' if doing ADC with D=1 +// CO : carry out bit from ALU +always @* begin + casex( {adj_bcd, adc_bcd, CO} ) + 3'b0xx: ADJH = 4'd0; // no BCD instruction + 3'b100: ADJH = 4'd10; // SBC, and digital borrow + 3'b101: ADJH = 4'd0; // SBC, but no borrow + 3'b110: ADJH = 4'd0; // ADC, but no carry + 3'b111: ADJH = 4'd6; // ADC, and decimal/digital carry + endcase +end + +/* + * write to a register. Usually this is the (BCD corrected) output of the + * ALU, but in case of the JSR0 we use the S register to temporarily store + * the PCL. This is possible, because the S register itself is stored in + * the ALU during those cycles. + */ +always @(posedge clk) + if( write_register & RDY ) + AXYS[regsel] <= (state == JSR0) ? DIMUX : { ADD[7:4] + ADJH, ADD[3:0] + ADJL }; + +/* + * register select logic. This determines which of the A, X, Y or + * S registers will be accessed. + */ + +always @* + case( state ) + INDY1, + INDX0, + ZPX0, + ABSX0 : regsel = index_y ? SEL_Y : SEL_X; + + + DECODE : regsel = dst_reg; + + BRK0, + BRK3, + JSR0, + JSR2, + PULL0, + PULL1, + PUSH1, + RTI0, + RTI3, + RTS0, + RTS2 : regsel = SEL_S; + + default: regsel = src_reg; + endcase + +/* + * ALU + */ + +ALU ALU( .clk(clk), + .op(alu_op), + .right(alu_shift_right), + .AI(AI), + .BI(BI), + .CI(CI), + .BCD(adc_bcd & (state == FETCH)), + .CO(CO), + .OUT(ADD), + .V(AV), + .Z(AZ), + .N(AN), + .HC(HC), + .RDY(RDY) ); + +/* + * Select current ALU operation + */ + +always @* + case( state ) + READ: alu_op = op; + + BRA1: alu_op = backwards ? OP_SUB : OP_ADD; + + FETCH, + REG : alu_op = op; + + DECODE, + ABS1: alu_op = 1'bx; + + PUSH1, + BRK0, + BRK1, + BRK2, + JSR0, + JSR1: alu_op = OP_SUB; + + default: alu_op = OP_ADD; + endcase + +/* + * Determine shift right signal to ALU + */ + +always @* + if( state == FETCH || state == REG || state == READ ) + alu_shift_right = shift_right; + else + alu_shift_right = 0; + +/* + * Sign extend branch offset. + */ + +always @(posedge clk) + if( RDY ) + backwards <= DIMUX[7]; + +/* + * ALU A Input MUX + */ + +always @* + case( state ) + JSR1, + RTS1, + RTI1, + RTI2, + BRK1, + BRK2, + INDX1: AI = ADD; + + REG, + ZPX0, + INDX0, + ABSX0, + RTI0, + RTS0, + JSR0, + JSR2, + BRK0, + PULL0, + INDY1, + PUSH0, + PUSH1: AI = regfile; + + BRA0, + READ: AI = DIMUX; + + BRA1: AI = ABH; // don't use PCH in case we're + + FETCH: AI = load_only ? 0 : regfile; + + DECODE, + ABS1: AI = 8'hxx; // don't care + + default: AI = 0; + endcase + + +/* + * ALU B Input mux + */ + +always @* + case( state ) + BRA1, + RTS1, + RTI0, + RTI1, + RTI2, + INDX1, + READ, + REG, + JSR0, + JSR1, + JSR2, + BRK0, + BRK1, + BRK2, + PUSH0, + PUSH1, + PULL0, + RTS0: BI = 8'h00; + + BRA0: BI = PCL; + + DECODE, + ABS1: BI = 8'hxx; + + default: BI = DIMUX; + endcase + +/* + * ALU CI (carry in) mux + */ + +always @* + case( state ) + INDY2, + BRA1, + ABSX1: CI = CO; + + DECODE, + ABS1: CI = 1'bx; + + READ, + REG: CI = rotate ? C : + shift ? 0 : inc; + + FETCH: CI = rotate ? C : + compare ? 1 : + (shift | load_only) ? 0 : C; + + PULL0, + RTI0, + RTI1, + RTI2, + RTS0, + RTS1, + INDY0, + INDX1: CI = 1; + + default: CI = 0; + endcase + +/* + * Processor Status Register update + * + */ + +/* + * Update C flag when doing ADC/SBC, shift/rotate, compare + */ +always @(posedge clk ) + if( shift && state == WRITE ) + C <= CO; + else if( state == RTI2 ) + C <= DIMUX[0]; + else if( ~write_back && state == DECODE ) begin + if( adc_sbc | shift | compare ) + C <= CO; + else if( plp ) + C <= ADD[0]; + else begin + if( sec ) C <= 1; + if( clc ) C <= 0; + end + end + +/* + * Update Z, N flags when writing A, X, Y, Memory, or when doing compare + */ + +always @(posedge clk) + if( state == WRITE ) + Z <= AZ; + else if( state == RTI2 ) + Z <= DIMUX[1]; + else if( state == DECODE ) begin + if( plp ) + Z <= ADD[1]; + else if( (load_reg & (regsel != SEL_S)) | compare | bit_ins ) + Z <= AZ; + end + +always @(posedge clk) + if( state == WRITE ) + N <= AN; + else if( state == RTI2 ) + N <= DIMUX[7]; + else if( state == DECODE ) begin + if( plp ) + N <= ADD[7]; + else if( (load_reg & (regsel != SEL_S)) | compare ) + N <= AN; + end else if( state == FETCH && bit_ins ) + N <= DIMUX[7]; + +/* + * Update I flag + */ + +always @(posedge clk) + if( state == BRK3 ) + I <= 1; + else if( state == RTI2 ) + I <= DIMUX[2]; + else if( state == REG ) begin + if( sei ) I <= 1; + if( cli ) I <= 0; + end else if( state == DECODE ) + if( plp ) I <= ADD[2]; + +/* + * Update D flag + */ +always @(posedge clk ) + if( state == RTI2 ) + D <= DIMUX[3]; + else if( state == DECODE ) begin + if( sed ) D <= 1; + if( cld ) D <= 0; + if( plp ) D <= ADD[3]; + end + +/* + * Update V flag + */ +always @(posedge clk ) + if( state == RTI2 ) + V <= DIMUX[6]; + else if( state == DECODE ) begin + if( adc_sbc ) V <= AV; + if( clv ) V <= 0; + if( plp ) V <= ADD[6]; + end else if( state == FETCH && bit_ins ) + V <= DIMUX[6]; + +/* + * Instruction decoder + */ + +/* + * IR register/mux. Hold previous DI value in IRHOLD in PULL0 and PUSH0 + * states. In these states, the IR has been prefetched, and there is no + * time to read the IR again before the next decode. + */ + +always @(posedge clk ) + if( reset ) + IRHOLD_valid <= 0; + else if( RDY ) begin + if( state == PULL0 || state == PUSH0 ) begin + IRHOLD <= DIMUX; + IRHOLD_valid <= 1; + end else if( state == DECODE ) + IRHOLD_valid <= 0; + end + +assign IR = (IRQ & ~I) | NMI_edge ? 8'h00 : + IRHOLD_valid ? IRHOLD : DIMUX; + +always @(posedge clk ) + if( RDY ) + DIHOLD <= DI; + +assign DIMUX = ~RDY ? DIHOLD : DI; + +/* + * Microcode state machine + */ +always @(posedge clk or posedge reset) + if( reset ) + state <= BRK0; + else if( RDY ) case( state ) + DECODE : + casex ( IR ) + 8'b0000_0000: state <= BRK0; + 8'b0010_0000: state <= JSR0; + 8'b0010_1100: state <= ABS0; // BIT abs + 8'b0100_0000: state <= RTI0; // + 8'b0100_1100: state <= JMP0; + 8'b0110_0000: state <= RTS0; + 8'b0110_1100: state <= JMPI0; + 8'b0x00_1000: state <= PUSH0; + 8'b0x10_1000: state <= PULL0; + 8'b0xx1_1000: state <= REG; // CLC, SEC, CLI, SEI + 8'b1xx0_00x0: state <= FETCH; // IMM + 8'b1xx0_1100: state <= ABS0; // X/Y abs + 8'b1xxx_1000: state <= REG; // DEY, TYA, ... + 8'bxxx0_0001: state <= INDX0; + 8'bxxx0_01xx: state <= ZP0; + 8'bxxx0_1001: state <= FETCH; // IMM + 8'bxxx0_1101: state <= ABS0; // even E column + 8'bxxx0_1110: state <= ABS0; // even E column + 8'bxxx1_0000: state <= BRA0; // odd 0 column + 8'bxxx1_0001: state <= INDY0; // odd 1 column + 8'bxxx1_01xx: state <= ZPX0; // odd 4,5,6,7 columns + 8'bxxx1_1001: state <= ABSX0; // odd 9 column + 8'bxxx1_11xx: state <= ABSX0; // odd C, D, E, F columns + 8'bxxxx_1010: state <= REG; // A, TXA, ... NOP + endcase + + ZP0 : state <= write_back ? READ : FETCH; + + ZPX0 : state <= ZPX1; + ZPX1 : state <= write_back ? READ : FETCH; + + ABS0 : state <= ABS1; + ABS1 : state <= write_back ? READ : FETCH; + + ABSX0 : state <= ABSX1; + ABSX1 : state <= (CO | store | write_back) ? ABSX2 : FETCH; + ABSX2 : state <= write_back ? READ : FETCH; + + INDX0 : state <= INDX1; + INDX1 : state <= INDX2; + INDX2 : state <= INDX3; + INDX3 : state <= FETCH; + + INDY0 : state <= INDY1; + INDY1 : state <= INDY2; + INDY2 : state <= (CO | store) ? INDY3 : FETCH; + INDY3 : state <= FETCH; + + READ : state <= WRITE; + WRITE : state <= FETCH; + FETCH : state <= DECODE; + + REG : state <= DECODE; + + PUSH0 : state <= PUSH1; + PUSH1 : state <= DECODE; + + PULL0 : state <= PULL1; + PULL1 : state <= PULL2; + PULL2 : state <= DECODE; + + JSR0 : state <= JSR1; + JSR1 : state <= JSR2; + JSR2 : state <= JSR3; + JSR3 : state <= FETCH; + + RTI0 : state <= RTI1; + RTI1 : state <= RTI2; + RTI2 : state <= RTI3; + RTI3 : state <= RTI4; + RTI4 : state <= DECODE; + + RTS0 : state <= RTS1; + RTS1 : state <= RTS2; + RTS2 : state <= RTS3; + RTS3 : state <= FETCH; + + BRA0 : state <= cond_true ? BRA1 : DECODE; + BRA1 : state <= (CO ^ backwards) ? BRA2 : DECODE; + BRA2 : state <= DECODE; + + JMP0 : state <= JMP1; + JMP1 : state <= DECODE; + + JMPI0 : state <= JMPI1; + JMPI1 : state <= JMP0; + + BRK0 : state <= BRK1; + BRK1 : state <= BRK2; + BRK2 : state <= BRK3; + BRK3 : state <= JMP0; + + endcase + +/* + * Additional control signals + */ + +always @(posedge clk) + if( reset ) + res <= 1; + else if( state == DECODE ) + res <= 0; + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0xx01010, // ASLA, ROLA, LSRA, RORA + 8'b0xxxxx01, // ORA, AND, EOR, ADC + 8'b100x10x0, // DEY, TYA, TXA, TXS + 8'b1010xxx0, // LDA/LDX/LDY + 8'b10111010, // TSX + 8'b1011x1x0, // LDX/LDY + 8'b11001010, // DEX + 8'b1x1xxx01, // LDA, SBC + 8'bxxx01000: // DEY, TAY, INY, INX + load_reg <= 1; + + default: load_reg <= 0; + endcase + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'b1110_1000, // INX + 8'b1100_1010, // DEX + 8'b101x_xx10: // LDX, TAX, TSX + dst_reg <= SEL_X; + + 8'b0x00_1000, // PHP, PHA + 8'b1001_1010: // TXS + dst_reg <= SEL_S; + + 8'b1x00_1000, // DEY, DEX + 8'b101x_x100, // LDY + 8'b1010_x000: // LDY #imm, TAY + dst_reg <= SEL_Y; + + default: dst_reg <= SEL_A; + endcase + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'b1011_1010: // TSX + src_reg <= SEL_S; + + 8'b100x_x110, // STX + 8'b100x_1x10, // TXA, TXS + 8'b1110_xx00, // INX, CPX + 8'b1100_1010: // DEX + src_reg <= SEL_X; + + 8'b100x_x100, // STY + 8'b1001_1000, // TYA + 8'b1100_xx00, // CPY + 8'b1x00_1000: // DEY, INY + src_reg <= SEL_Y; + + default: src_reg <= SEL_A; + endcase + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'bxxx1_0001, // INDY + 8'b10x1_x110, // LDX/STX zpg/abs, Y + 8'bxxxx_1001: // abs, Y + index_y <= 1; + + default: index_y <= 0; + endcase + + +always @(posedge clk) + if( state == DECODE && RDY ) + casex( IR ) + 8'b100x_x1x0, // STX, STY + 8'b100x_xx01: // STA + store <= 1; + + default: store <= 0; + + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0xxx_x110, // ASL, ROL, LSR, ROR + 8'b11xx_x110: // DEC/INC + write_back <= 1; + + default: write_back <= 0; + endcase + + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b101x_xxxx: // LDA, LDX, LDY + load_only <= 1; + default: load_only <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b111x_x110, // INC + 8'b11x0_1000: // INX, INY + inc <= 1; + + default: inc <= 0; + endcase + +always @(posedge clk ) + if( (state == DECODE || state == BRK0) && RDY ) + casex( IR ) + 8'bx11x_xx01: // SBC, ADC + adc_sbc <= 1; + + default: adc_sbc <= 0; + endcase + +always @(posedge clk ) + if( (state == DECODE || state == BRK0) && RDY ) + casex( IR ) + 8'b011x_xx01: // ADC + adc_bcd <= D; + + default: adc_bcd <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0xxx_x110, // ASL, ROL, LSR, ROR (abs, absx, zpg, zpgx) + 8'b0xxx_1010: // ASL, ROL, LSR, ROR (acc) + shift <= 1; + + default: shift <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b11x0_0x00, // CPX, CPY (imm/zp) + 8'b11x0_1100, // CPX, CPY (abs) + 8'b110x_xx01: // CMP + compare <= 1; + + default: compare <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b01xx_xx10: // ROR, LSR + shift_right <= 1; + + default: shift_right <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0x1x_1010, // ROL A, ROR A + 8'b0x1x_x110: // ROR, ROL + rotate <= 1; + + default: rotate <= 0; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b00xx_xx10: // ROL, ASL + op <= OP_ROL; + + 8'b0010_x100: // BIT zp/abs + op <= OP_AND; + + 8'b01xx_xx10: // ROR, LSR + op <= OP_A; + + 8'b1000_1000, // DEY + 8'b1100_1010, // DEX + 8'b110x_x110, // DEC + 8'b11xx_xx01, // CMP, SBC + 8'b11x0_0x00, // CPX, CPY (imm, zpg) + 8'b11x0_1100: op <= OP_SUB; + + 8'b010x_xx01, // EOR + 8'b00xx_xx01: // ORA, AND + op <= { 2'b11, IR[6:5] }; + + default: op <= OP_ADD; + endcase + +always @(posedge clk ) + if( state == DECODE && RDY ) + casex( IR ) + 8'b0010_x100: // BIT zp/abs + bit_ins <= 1; + + default: bit_ins <= 0; + endcase + +/* + * special instructions + */ +always @(posedge clk ) + if( state == DECODE && RDY ) begin + php <= (IR == 8'h08); + clc <= (IR == 8'h18); + plp <= (IR == 8'h28); + sec <= (IR == 8'h38); + cli <= (IR == 8'h58); + sei <= (IR == 8'h78); + clv <= (IR == 8'hb8); + cld <= (IR == 8'hd8); + sed <= (IR == 8'hf8); + brk <= (IR == 8'h00); + end + +always @(posedge clk) + if( RDY ) + cond_code <= IR[7:5]; + +always @* + case( cond_code ) + 3'b000: cond_true = ~N; + 3'b001: cond_true = N; + 3'b010: cond_true = ~V; + 3'b011: cond_true = V; + 3'b100: cond_true = ~C; + 3'b101: cond_true = C; + 3'b110: cond_true = ~Z; + 3'b111: cond_true = Z; + endcase + + +reg NMI_1 = 0; // delayed NMI signal + +always @(posedge clk) + NMI_1 <= NMI; + +always @(posedge clk ) + if( NMI_edge && state == BRK3 ) + NMI_edge <= 0; + else if( NMI & ~NMI_1 ) + NMI_edge <= 1; + +endmodule diff --git a/Computer_MiST/Acorn - System1/rtl/debounce.vhd b/Computer_MiST/Acorn - System1/rtl/debounce.vhd new file mode 100644 index 00000000..271dc30b --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/debounce.vhd @@ -0,0 +1,58 @@ +-------------------------------------------------------------------------------- +-- +-- FileName: debounce.vhd +-- Dependencies: none +-- Design Software: Quartus II 32-bit Version 11.1 Build 173 SJ Full Version +-- +-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY +-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY +-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL +-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF +-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS +-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), +-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. +-- +-- Version History +-- Version 1.0 3/26/2012 Scott Larson +-- Initial Public Release +-- +-------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; +USE ieee.std_logic_unsigned.all; + +ENTITY debounce IS + GENERIC( + counter_size : INTEGER := 19); --counter size (19 bits gives 10.5ms with 50MHz clock) + PORT( + clk : IN STD_LOGIC; --input clock + button : IN STD_LOGIC; --input signal to be debounced + result : OUT STD_LOGIC); --debounced signal +END debounce; + +ARCHITECTURE logic OF debounce IS + SIGNAL flipflops : STD_LOGIC_VECTOR(1 DOWNTO 0); --input flip flops + SIGNAL counter_set : STD_LOGIC; --sync reset to zero + SIGNAL counter_out : STD_LOGIC_VECTOR(counter_size DOWNTO 0) := (OTHERS => '0'); --counter output +BEGIN + + counter_set <= flipflops(0) xor flipflops(1); --determine when to start/reset counter + + PROCESS(clk) + BEGIN + IF(clk'EVENT and clk = '1') THEN + flipflops(0) <= button; + flipflops(1) <= flipflops(0); + If(counter_set = '1') THEN --reset counter because input is changing + counter_out <= (OTHERS => '0'); + ELSIF(counter_out(counter_size) = '0') THEN --stable input time is not yet met + counter_out <= counter_out + 1; + ELSE --stable input time is met + result <= flipflops(1); + END IF; + END IF; + END PROCESS; +END logic; diff --git a/Computer_MiST/Acorn - System1/rtl/gen_ram.vhd b/Computer_MiST/Acorn - System1/rtl/gen_ram.vhd new file mode 100644 index 00000000..0794fdc0 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/gen_ram.vhd @@ -0,0 +1,82 @@ +-- ----------------------------------------------------------------------- +-- +-- Syntiac's generic VHDL support files. +-- +-- ----------------------------------------------------------------------- +-- Copyright 2005-2008 by Peter Wendrich (pwsoft@syntiac.com) +-- http://www.syntiac.com/fpga64.html +-- +-- Modified April 2016 by Dar (darfpga@aol.fr) +-- http://darfpga.blogspot.fr +-- Remove address register when writing +-- +-- ----------------------------------------------------------------------- +-- +-- gen_rwram.vhd +-- +-- ----------------------------------------------------------------------- +-- +-- generic ram. +-- +-- ----------------------------------------------------------------------- + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.numeric_std.ALL; + +-- ----------------------------------------------------------------------- + +entity gen_ram is + generic ( + dWidth : integer := 8; + aWidth : integer := 10 + ); + port ( + clk : in std_logic; + we : in std_logic; + addr : in std_logic_vector((aWidth-1) downto 0); + d : in std_logic_vector((dWidth-1) downto 0); + q : out std_logic_vector((dWidth-1) downto 0) + ); +end entity; + +-- ----------------------------------------------------------------------- + +architecture rtl of gen_ram is + subtype addressRange is integer range 0 to ((2**aWidth)-1); + type ramDef is array(addressRange) of std_logic_vector((dWidth-1) downto 0); + signal ram: ramDef; + + signal rAddrReg : std_logic_vector((aWidth-1) downto 0); + signal qReg : std_logic_vector((dWidth-1) downto 0); +begin +-- ----------------------------------------------------------------------- +-- Signals to entity interface +-- ----------------------------------------------------------------------- + q <= qReg; + +-- ----------------------------------------------------------------------- +-- Memory write +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then + if we = '1' then + ram(to_integer(unsigned(addr))) <= d; + end if; + end if; + end process; + +-- ----------------------------------------------------------------------- +-- Memory read +-- ----------------------------------------------------------------------- + process(clk) + begin + if rising_edge(clk) then +-- qReg <= ram(to_integer(unsigned(rAddrReg))); +-- rAddrReg <= addr; + qReg <= ram(to_integer(unsigned(addr))); + end if; + end process; +end architecture; + diff --git a/Computer_MiST/Acorn - System1/rtl/m6522.v b/Computer_MiST/Acorn - System1/rtl/m6522.v new file mode 100644 index 00000000..1dc9f617 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/m6522.v @@ -0,0 +1,1074 @@ +// +// A simulation model of VIC20 hardware - VIA implementation +// Copyright (c) MikeJ - March 2003 +// +// All rights reserved +// +// Redistribution and use in source and synthezised forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// Redistributions in synthesized form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// Neither the name of the author nor the names of other contributors may +// be used to endorse or promote products derived from this software without +// specific prior written permission. +// +// THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. +// +// You are responsible for any legal issues arising from your use of this code. +// +// The latest version of this file can be found at: www.fpgaarcade.com +// +// Email vic20@fpgaarcade.com +// +// +// Revision list +// +// version 005 Many fixes to all areas, VIA now passes all VICE tests +// version 004 fixes to PB7 T1 control and Mode 0 Shift Register operation +// version 003 fix reset of T1/T2 IFR flags if T1/T2 is reload via reg5/reg9 from wolfgang (WoS) +// Ported to numeric_std and simulation fix for signal initializations from arnim laeuger +// version 002 fix from Mark McDougall, untested +// version 001 initial release +// not very sure about the shift register, documentation is a bit light. + +module m6522 + ( + input [3:0] I_RS , + input [7:0] I_DATA , + output reg [7:0] O_DATA , + output O_DATA_OE_L , + + input I_RW_L , + input I_CS1 , + input I_CS2_L , + + output O_IRQ_L , // note, not open drain + + // port a + input I_CA1 , + input I_CA2 , + output reg O_CA2 , + output reg O_CA2_OE_L , + + input [7:0] I_PA , + output [7:0] O_PA , + output [7:0] O_PA_OE_L , + + // port b + input I_CB1 , + output O_CB1 , + output O_CB1_OE_L , + + input I_CB2 , + output reg O_CB2 , + output reg O_CB2_OE_L , + + input [7:0] I_PB , + output [7:0] O_PB , + output [7:0] O_PB_OE_L , + + input I_P2_H , // high for phase 2 clock ____////__ + input RESET_L , + input ENA_4 , // clk enable + input CLK + ); + + + + reg [1:0] phase = 2'b00; + reg p2_h_t1; + wire cs; + + // registers + reg [7:0] r_ddra; + reg [7:0] r_ora; + reg [7:0] r_ira; + + reg [7:0] r_ddrb; + reg [7:0] r_orb; + reg [7:0] r_irb; + + reg [7:0] r_t1l_l; + reg [7:0] r_t1l_h; + reg [7:0] r_t2l_l; + reg [7:0] r_t2l_h; // not in real chip + reg [7:0] r_sr; + reg [7:0] r_acr; + reg [7:0] r_pcr; + wire [7:0] r_ifr; + reg [6:0] r_ier; + + reg sr_write_ena; + reg sr_read_ena; + reg ifr_write_ena; + reg ier_write_ena; + wire [7:0] clear_irq; + reg [7:0] load_data; + + // timer 1 + reg [15:0] t1c = 16'hffff; // simulators may not catch up w/o init here... + reg t1c_active; + reg t1c_done; + reg t1_w_reset_int; + reg t1_r_reset_int; + reg t1_load_counter; + reg t1_reload_counter; + reg t1_int_enable = 1'b0; + reg t1_toggle; + reg t1_irq = 1'b0; + reg t1_pb7 = 1'b1; + reg t1_pb7_en_c; + reg t1_pb7_en_d; + + // timer 2 + reg [15:0] t2c = 16'hffff; // simulators may not catch up w/o init here... + reg t2c_active; + reg t2c_done; + reg t2_pb6; + reg t2_pb6_t1; + reg t2_cnt_clk = 1'b1; + reg t2_w_reset_int; + reg t2_r_reset_int; + reg t2_load_counter; + reg t2_reload_counter; + reg t2_int_enable = 1'b0; + reg t2_irq = 1'b0; + reg t2_sr_ena; + + // shift reg + reg [3:0] sr_cnt; + reg sr_cb1_oe_l; + reg sr_cb1_out; + reg sr_drive_cb2; + reg sr_strobe; + reg sr_do_shift = 1'b0; + reg sr_strobe_t1; + reg sr_strobe_falling; + reg sr_strobe_rising; + reg sr_irq; + reg sr_out; + reg sr_active; + + // io + reg w_orb_hs; + reg w_ora_hs; + reg r_irb_hs; + reg r_ira_hs; + + reg ca_hs_sr; + reg ca_hs_pulse; + reg cb_hs_sr; + reg cb_hs_pulse; + + wire cb1_in_mux; + reg ca1_ip_reg_c; + reg ca1_ip_reg_d; + reg cb1_ip_reg_c; + reg cb1_ip_reg_d; + wire ca1_int; + wire cb1_int; + reg ca1_irq; + reg cb1_irq; + + reg ca2_ip_reg_c; + reg ca2_ip_reg_d; + reg cb2_ip_reg_c; + reg cb2_ip_reg_d; + wire ca2_int; + wire cb2_int; + reg ca2_irq; + reg cb2_irq; + + reg final_irq; + + + always @(posedge CLK) begin + if (ENA_4 == 1'b1) begin + p2_h_t1 <= I_P2_H; + if ((p2_h_t1 == 1'b0) & (I_P2_H == 1'b1)) begin + phase <= 2'b11; + end + else begin + phase <= phase + 1'b1; + end + end + end + + // internal clock phase + assign cs = (I_CS1 == 1'b1 & I_CS2_L == 1'b0 & I_P2_H == 1'b1) ? 1'b1 : 1'b0; + + // peripheral control reg (pcr) + // 0 ca1 interrupt control (0 +ve edge, 1 -ve edge) + // 3..1 ca2 operation + // 000 input -ve edge + // 001 independend interrupt input -ve edge + // 010 input +ve edge + // 011 independend interrupt input +ve edge + // 100 handshake output + // 101 pulse output + // 110 low output + // 111 high output + // 7..4 as 3..0 for cb1,cb2 + + // auxiliary control reg (acr) + // 0 input latch PA (0 disable, 1 enable) + // 1 input latch PB (0 disable, 1 enable) + // 4..2 shift reg control + // 000 disable + // 001 shift in using t2 + // 010 shift in using o2 + // 011 shift in using ext clk + // 100 shift out free running t2 rate + // 101 shift out using t2 + // 101 shift out using o2 + // 101 shift out using ext clk + // 5 t2 timer control (0 timed interrupt, 1 count down with pulses on pb6) + // 7..6 t1 timer control + // 00 timed interrupt each time t1 is loaded pb7 disable + // 01 continuous interrupts pb7 disable + // 00 timed interrupt each time t1 is loaded pb7 one shot output + // 01 continuous interrupts pb7 square wave output + // + + always @(posedge CLK, negedge RESET_L) begin + if (RESET_L == 1'b0) begin + r_ora <= 8'h00; + r_orb <= 8'h00; + r_ddra <= 8'h00; + r_ddrb <= 8'h00; + r_acr <= 8'h00; + r_pcr <= 8'h00; + w_orb_hs <= 1'b0; + w_ora_hs <= 1'b0; + end else begin + if (ENA_4 == 1'b1) begin + w_orb_hs <= 1'b0; + w_ora_hs <= 1'b0; + if ((cs == 1'b1) & (I_RW_L == 1'b0)) begin + case (I_RS) + 4'h 0 : begin + r_orb <= I_DATA; + w_orb_hs <= 1'b1; + end + + 4'h 1 : begin + r_ora <= I_DATA; + w_ora_hs <= 1'b1; + end + + 4'h 2 : begin + r_ddrb <= I_DATA; + end + + 4'h 3 : begin + r_ddra <= I_DATA; + end + + + 4'h B : begin + r_acr <= I_DATA; + end + + 4'h C : begin + r_pcr <= I_DATA; + end + + 4'h F : begin + r_ora <= I_DATA; + end + endcase + end + + // Set timer PB7 state, only on rising edge of setting ACR(7) + if ((t1_pb7_en_d == 1'b0) & (t1_pb7_en_c == 1'b1)) begin + t1_pb7 <= 1'b1; + end + + if (t1_load_counter) begin + t1_pb7 <= 1'b0; // Reset internal timer 1 PB7 state on every timer load + end else if (t1_toggle == 1'b1) begin + t1_pb7 <= !t1_pb7; + end + end + end + end + + always @(posedge CLK, negedge RESET_L) begin + if (RESET_L == 1'b0) begin + // The spec says, this is not reset. + // Fact is that the 1541 VIA1 timer won't work, + // as the firmware ONLY sets the r_t1l_h latch!!!! + r_t1l_l <= 8'hff; // All latches default to FFFF + r_t1l_h <= 8'hff; + r_t2l_l <= 8'hff; + r_t2l_h <= 8'hff; + end else begin + if (ENA_4 == 1'b1) begin + t1_w_reset_int <= 1'b0; + t1_load_counter <= 1'b0; + + t2_w_reset_int <= 1'b0; + t2_load_counter <= 1'b0; + + load_data <= 8'h00; + sr_write_ena <= 1'b0; + ifr_write_ena <= 1'b0; + ier_write_ena <= 1'b0; + + if ((cs == 1'b1) & (I_RW_L == 1'b0)) begin + load_data <= I_DATA; + case (I_RS) + 4'h4: begin + r_t1l_l <= I_DATA; + end + + 4'h5: begin + r_t1l_h <= I_DATA; + t1_w_reset_int <= 1'b1; + t1_load_counter <= 1'b1; + end + + 4'h6: begin + r_t1l_l <= I_DATA; + end + + 4'h7: begin + r_t1l_h <= I_DATA; + t1_w_reset_int <= 1'b1; + end + + + 4'h8: begin + r_t2l_l <= I_DATA; + end + + 4'h9: begin + r_t2l_h <= I_DATA; + t2_w_reset_int <= 1'b1; + t2_load_counter <= 1'b1; + end + + 4'hA: begin + sr_write_ena <= 1'b1; + end + + 4'hD: begin + ifr_write_ena <= 1'b1; + end + + 4'hE: begin + ier_write_ena <= 1'b1; + end + + endcase + end + end + end + end + + assign O_DATA_OE_L = (cs == 1'b1 & I_RW_L == 1'b 1) ? 1'b0 : 1'b1; + + reg [7:0] orb; + + always @(*) begin + t1_r_reset_int <= 1'b0; + t2_r_reset_int <= 1'b0; + sr_read_ena <= 1'b0; + r_irb_hs <= 1'b0; + r_ira_hs <= 1'b0; + O_DATA <= 8'h00; // default + + orb = (r_irb & !r_ddrb) | (r_orb & r_ddrb); + + // If PB7 under timer control, assign value from timer + if (t1_pb7_en_d == 1'b1) begin + orb[7] = t1_pb7; + end + + if ((cs == 1'b1) & (I_RW_L == 1'b1)) begin + case (I_RS) + 4'h0: begin + O_DATA <= orb; r_irb_hs <= 1'b1; + end + 4'h1: begin + O_DATA <= (r_ira & !r_ddra) | (r_ora & r_ddra); + r_ira_hs <= 1'b1; + end + 4'h2: begin + O_DATA <= r_ddrb; + end + 4'h3: begin + O_DATA <= r_ddra; + end + 4'h4: begin + O_DATA <= t1c[7:0]; + t1_r_reset_int <= 1'b1; + end + 4'h5: begin + O_DATA <= t1c[15:8]; + end + 4'h6: begin + O_DATA <= r_t1l_l; + end + 4'h7: begin + O_DATA <= r_t1l_h; + end + 4'h8: begin + O_DATA <= t2c[7:0]; + t2_r_reset_int <= 1'b1; + end + 4'h9: begin + O_DATA <= t2c[15:8]; + end + 4'hA: begin + O_DATA <= r_sr; + sr_read_ena <= 1'b1; + end + 4'hB: begin + O_DATA <= r_acr; + end + 4'hC: begin + O_DATA <= r_pcr; + end + 4'hD: begin + O_DATA <= r_ifr; + end + 4'hE: begin + O_DATA <= (1'b0 & r_ier); + end + 4'hF: begin + O_DATA <= r_ira; + end + endcase + end + + end + + // + // IO + // + + + // if the shift register is enabled, cb1 may be an output + // in this case we should NOT listen to the input as + // CB1 interrupts are not generated by the shift register + + assign cb1_in_mux = (sr_cb1_oe_l === 1'b 1) ? I_CB1 : 1'b1; + + // ca1 control + assign ca1_int = (r_pcr[0] == 1'b0) ? + // negative edge + (ca1_ip_reg_d == 1'b1) & (ca1_ip_reg_c == 1'b0) : + // positive edge + (ca1_ip_reg_d == 1'b0) & (ca1_ip_reg_c == 1'b1); + + // cb1 control + assign cb1_int = (r_pcr[4] == 1'b0) ? + // negative edge + (cb1_ip_reg_d == 1'b1) & (cb1_ip_reg_c == 1'b0) : + // positive edge + (cb1_ip_reg_d == 1'b0) & (cb1_ip_reg_c == 1'b1); + + + assign ca2_int = (r_pcr[3] == 1'b1) ? + // ca2 input + 1'b0 : + (r_pcr[2] == 1'b0) ? + // ca2 negative edge + (ca2_ip_reg_d == 1'b1) & (ca2_ip_reg_c == 1'b0) : + // ca2 positive edge + (ca2_ip_reg_d == 1'b0) & (ca2_ip_reg_c == 1'b1); + + + assign cb2_int = (r_pcr[7] == 1'b1) ? + // cb2 input + 1'b0 : + (r_pcr[6] == 1'b0) ? + // cb2 negative edge + (cb2_ip_reg_d == 1'b1) & (cb2_ip_reg_c == 1'b0) : + // cb2 positive edge + (cb2_ip_reg_d == 1'b0) & (cb2_ip_reg_c == 1'b1); + + + + + + always @(posedge CLK, negedge RESET_L) begin + if (RESET_L == 1'b0) begin + O_CA2 <= 1'b1; // Pullup is default + O_CA2_OE_L <= 1'b1; + O_CB2 <= 1'b1; // Pullup is default + O_CB2_OE_L <= 1'b1; + + ca_hs_sr <= 1'b0; + ca_hs_pulse <= 1'b0; + cb_hs_sr <= 1'b0; + cb_hs_pulse <= 1'b0; + end else begin + if (ENA_4 == 1'b1) begin + // ca + if ((phase == 2'b00) & ((w_ora_hs == 1'b1) | (r_ira_hs == 1'b1))) begin + ca_hs_sr <= 1'b1; + end else if (ca1_int) begin + ca_hs_sr <= 1'b0; + end + + if (phase == 2'b00) begin + ca_hs_pulse <= w_ora_hs | r_ira_hs; + end + + O_CA2_OE_L <= !r_pcr[3]; // ca2 output + case (r_pcr[3:1]) + 3'b000: begin + O_CA2 <= I_CA2; // input, output follows input + end + 3'b001: begin + O_CA2 <= I_CA2; // input, output follows input + end + 3'b010: begin + O_CA2 <= I_CA2; // input, output follows input + end + 3'b011: begin + O_CA2 <= I_CA2; // input, output follows input + end + 3'b100: begin + O_CA2 <= !(ca_hs_sr); // handshake + end + 3'b101: begin + O_CA2 <= !(ca_hs_pulse); // pulse + end + 3'b110: begin + O_CA2 <= 1'b0; // low + end + 3'b111: begin + O_CA2 <= 1'b1; // high + end + endcase + + if ((phase == 2'b00) & (w_orb_hs == 1'b1)) begin + cb_hs_sr <= 1'b1; + end else if (cb1_int) begin + cb_hs_sr <= 1'b0; + end + + if (phase == 2'b00) begin + cb_hs_pulse <= w_orb_hs; + end + + O_CB2_OE_L <= !(r_pcr[7] | sr_drive_cb2); // cb2 output or serial + if (sr_drive_cb2 == 1'b1) begin // serial output + O_CB2 <= sr_out; + end + else begin + case (r_pcr[7:5]) + 3'b000: begin + O_CB2 <= I_CB2; // input, output follows input + end + 3'b001: begin + O_CB2 <= I_CB2; // input, output follows input + end + 3'b010: begin + O_CB2 <= I_CB2; // input, output follows input + end + 3'b011: begin + O_CB2 <= I_CB2; // input, output follows input + end + 3'b100: begin + O_CB2 <= !(cb_hs_sr); // handshake + end + 3'b101: begin + O_CB2 <= !(cb_hs_pulse); // pulse + end + 3'b110: begin + O_CB2 <= 1'b0; // low + end + 3'b111: begin + O_CB2 <= 1'b1; // high + end + endcase + end + end + end + end + + assign O_CB1 = sr_cb1_out; + assign O_CB1_OE_L = sr_cb1_oe_l; + + always @(posedge CLK, negedge RESET_L) begin + if (RESET_L == 1'b0) begin + ca1_irq <= 1'b0; + ca2_irq <= 1'b0; + cb1_irq <= 1'b0; + cb2_irq <= 1'b0; + end else begin + if (ENA_4 == 1'b1) begin + // not pretty + if (ca1_int) begin + ca1_irq <= 1'b1; + end else if ((r_ira_hs == 1'b1) | (w_ora_hs == 1'b1) | (clear_irq[1] == 1'b1)) begin + ca1_irq <= 1'b0; + end + + if (ca2_int) begin + ca2_irq <= 1'b1; + end + else begin + if ((((r_ira_hs == 1'b1) | (w_ora_hs == 1'b1)) & (r_pcr[1] == 1'b0)) | (clear_irq[0] == 1'b1)) begin + ca2_irq <= 1'b0; + end + end + + if (cb1_int) begin + cb1_irq <= 1'b1; + end else if ((r_irb_hs == 1'b1) | (w_orb_hs == 1'b1) | (clear_irq[4] == 1'b1)) begin + cb1_irq <= 1'b0; + end + + if (cb2_int) begin + cb2_irq <= 1'b1; + end + else begin + if ((((r_irb_hs == 1'b1) | (w_orb_hs == 1'b1)) & (r_pcr[5] == 1'b0)) | (clear_irq[3] == 1'b1)) begin + cb2_irq <= 1'b0; + end + end + end + end + end + + always @(posedge CLK, negedge RESET_L) begin + if (RESET_L == 1'b0) begin + ca1_ip_reg_c <= 1'b0; + ca1_ip_reg_d <= 1'b0; + + cb1_ip_reg_c <= 1'b0; + cb1_ip_reg_d <= 1'b0; + + ca2_ip_reg_c <= 1'b0; + ca2_ip_reg_d <= 1'b0; + + cb2_ip_reg_c <= 1'b0; + cb2_ip_reg_d <= 1'b0; + + r_ira <= 8'h00; + r_irb <= 8'h00; + + end else begin + if (ENA_4 == 1'b1) begin + // we have a fast clock, so we can have input registers + ca1_ip_reg_c <= I_CA1; + ca1_ip_reg_d <= ca1_ip_reg_c; + + cb1_ip_reg_c <= cb1_in_mux; + cb1_ip_reg_d <= cb1_ip_reg_c; + + ca2_ip_reg_c <= I_CA2; + ca2_ip_reg_d <= ca2_ip_reg_c; + + cb2_ip_reg_c <= I_CB2; + cb2_ip_reg_d <= cb2_ip_reg_c; + + if (r_acr[0] == 1'b0) begin + r_ira <= I_PA; + end + else begin // enable latching + if (ca1_int) begin + r_ira <= I_PA; + end + end + + if (r_acr[1] == 1'b0) begin + r_irb <= I_PB; + end + else begin // enable latching + if (cb1_int) begin + r_irb <= I_PB; + end + end + end + end + end + + + // data direction reg (ddr) 0 = input, 1 = output + assign O_PA = r_ora; + assign O_PA_OE_L = ~r_ddra; + + // If PB7 is timer driven output set PB7 to the timer state, otherwise use value in ORB register + assign O_PB = (t1_pb7_en_d == 1'b1) ? { t1_pb7 , r_orb[6:0]} : r_orb; + + // NOTE: r_ddrb(7) must be set to enable T1 output on PB7 - [various datasheets specify this] + assign O_PB_OE_L = ~r_ddrb; + + // + // Timer 1 + // + + // Detect change in r_acr(7), timer 1 mode for PB7 + always @(posedge CLK) begin + if (ENA_4 == 1'b1) begin + t1_pb7_en_c <= r_acr[7]; + t1_pb7_en_d <= t1_pb7_en_c; + end + end + + reg p_timer1_done; + always @(posedge CLK) begin + if (ENA_4 == 1'b1) begin + p_timer1_done = (t1c == 16'h0000); + t1c_done <= p_timer1_done & (phase == 2'b11); + if ((phase == 2'b11) & !t1_load_counter) begin // Don't set reload if T1L-H written + t1_reload_counter <= p_timer1_done; + end else if (t1_load_counter) begin // Cancel a reload when T1L-H written + t1_reload_counter <= 1'b0; + end + if (t1_load_counter) begin // done reset on load! + t1c_done <= 1'b0; + end + end + end + + always @(posedge CLK) begin + if (ENA_4 == 1'b1) begin + if (t1_load_counter | (t1_reload_counter & phase == 2'b11)) begin + t1c[ 7:0] <= r_t1l_l; + t1c[15:8] <= r_t1l_h; + // There is a need to write to Latch HI to enable interrupts for both continuous and one-shot modes + if (t1_load_counter) begin + t1_int_enable <= 1'b1; + end + end else if (phase == 2'b11) begin + t1c <= t1c - 1'b1; + end + + if (t1_load_counter | t1_reload_counter) begin + t1c_active <= 1'b1; + end else if (t1c_done) begin + t1c_active <= 1'b0; + end + + t1_toggle <= 1'b0; + if (t1c_active & t1c_done) begin + if (t1_int_enable) begin // Set interrupt only if T1L-H has been written + t1_toggle <= 1'b1; + t1_irq <= 1'b1; + if (r_acr[6] == 1'b0) begin // Disable further interrupts if in one shot mode + t1_int_enable <= 1'b0; + end + end + end else if (t1_w_reset_int | t1_r_reset_int | (clear_irq[6] == 1'b1)) begin + t1_irq <= 1'b0; + end + if (t1_load_counter) begin // irq reset on load! + t1_irq <= 1'b0; + end + end + end + + // + // Timer2 + // + + always @(posedge CLK) begin + if (ENA_4 == 1'b1) begin + if (phase == 2'b01) begin // leading edge p2_h + t2_pb6 <= I_PB[6]; + t2_pb6_t1 <= t2_pb6; + end + end + end + + // Ensure we don't start counting until the P2 clock after r_acr is changed + always @(posedge I_P2_H) begin + if (r_acr[5] == 1'b0) begin + t2_cnt_clk <= 1'b1; + end + else begin + t2_cnt_clk <= 1'b0; + end + end + + reg p_timer2_done; + reg p_timer2_done_sr; + always @(posedge CLK) begin + if (ENA_4 == 1'b1) begin + p_timer2_done = (t2c == 16'h0000); // Normal timer expires at 0000 + p_timer2_done_sr = (t2c[7:0] == 8'h00); // Shift register expires on low byte == 00 + t2c_done <= p_timer2_done & (phase == 2'b11); + if (phase == 2'b11) begin + t2_reload_counter <= p_timer2_done_sr; // Timer 2 is only reloaded when used for the shift register + end + if (t2_load_counter) begin // done reset on load! + t2c_done <= 1'b0; + end + end + end + + reg p_timer2_ena; + always @(posedge CLK) begin + if (ENA_4 == 1'b1) begin + if (t2_cnt_clk == 1'b1) begin + p_timer2_ena = 1'b1; + t2c_active <= 1'b1; + t2_int_enable <= 1'b1; + end + else begin + p_timer2_ena = (t2_pb6_t1 == 1'b1) & (t2_pb6 == 1'b0); // falling edge + end + + // Shift register reload is only active when shift register mode using T2 is enabled + if (t2_reload_counter & (phase == 2'b11) & ((r_acr[4:2] == 3'b001) | (r_acr[4:2] == 3'b100) | (r_acr[4:2] == 3'b101))) begin + t2c[7:0] <= r_t2l_l; // For shift register only low latch is loaded! + end else if (t2_load_counter) begin + t2_int_enable <= 1'b1; + t2c[ 7:0] <= r_t2l_l; + t2c[15:8] <= r_t2l_h; + end + else begin + if ((phase == 2'b11) & p_timer2_ena) begin // or count mode + t2c <= t2c - 1'b1; + end + end + + // Shift register strobe on T2 occurs one P2H clock after timer expires + // so enable the strobe when we roll over to FF + t2_sr_ena <= (t2c[7:0] == 8'hFF) & (phase == 2'b11); + + if (t2_load_counter) begin + t2c_active <= 1'b1; + end else if (t2c_done) begin + t2c_active <= 1'b0; + end + + if (t2c_active & t2c_done & t2_int_enable) begin + t2_int_enable <= 1'b0; + t2_irq <= 1'b1; + end else if (t2_w_reset_int | t2_r_reset_int | (clear_irq[5] == 1'b1)) begin + t2_irq <= 1'b0; + end + if (t2_load_counter) begin // irq reset on load! + t2_irq <= 1'b0; + end + end + end + + // + // Shift Register + // + + reg sr_dir_out ; + reg sr_ena ; + reg sr_cb1_op ; + reg sr_cb1_ip ; + reg sr_use_t2 ; + reg sr_free_run ; + reg sr_count_ena ; + + + always @(posedge CLK, negedge RESET_L) begin + if (RESET_L == 1'b0) begin + r_sr <= 8'h00; + sr_drive_cb2 <= 1'b0; + sr_cb1_oe_l <= 1'b1; + sr_cb1_out <= 1'b0; + sr_do_shift <= 1'b0; + sr_strobe <= 1'b1; + sr_cnt <= 4'b0000; + sr_irq <= 1'b0; + sr_out <= 1'b0; + sr_active <= 1'b0; + end else begin + if (ENA_4 == 1'b1) begin + // decode mode + sr_dir_out = r_acr[4]; // output on cb2 + sr_cb1_op = 1'b0; + sr_cb1_ip = 1'b0; + sr_use_t2 = 1'b0; + sr_free_run = 1'b0; + + // DMB: SR still runs even in disabled mode (on rising edge of CB1). + // It just doesn't generate any interrupts. + // Ref BBC micro advanced user guide p409 + + case (r_acr[4:2]) + // DMB: in disabled mode, configure cb1 as an input + 3'b000: begin + sr_ena = 1'b0; sr_cb1_ip = 1'b1; // 0x00 Mode 0 SR disabled + end + 3'b001: begin + sr_ena = 1'b1; sr_cb1_op = 1'b1; sr_use_t2 = 1'b1; // 0x04 Mode 1 Shift in under T2 control + end + 3'b010: begin + sr_ena = 1'b1; sr_cb1_op = 1'b1; // 0x08 Mode 2 Shift in under P2 control + end + 3'b011: begin + sr_ena = 1'b1; sr_cb1_ip = 1'b1; // 0x0C Mode 3 Shift in under control of ext clock + end + 3'b100: begin + sr_ena = 1'b1; sr_cb1_op = 1'b1; sr_use_t2 = 1'b1; sr_free_run = 1'b1; // 0x10 Mode 4 Shift out free running under T2 control + end + 3'b101: begin + sr_ena = 1'b1; sr_cb1_op = 1'b1; sr_use_t2 = 1'b1; // 0x14 Mode 5 Shift out under T2 control + end + 3'b110: begin + sr_ena = 1'b1; sr_cb1_op = 1'b1; // 0x18 Mode 6 Shift out under P2 control + end + 3'b111: begin + sr_ena = 1'b1; sr_cb1_ip = 1'b1; // 0x1C Mode 7 Shift out under control of ext clock + end + endcase + + // clock select + // DMB: in disabled mode, strobe from cb1 + if (sr_cb1_ip == 1'b1) begin + sr_strobe <= I_CB1; + end + else begin + if ((sr_cnt[3] == 1'b0) & (sr_free_run == 1'b0)) begin + sr_strobe <= 1'b1; + end + else begin + if (((sr_use_t2 == 1'b1) & t2_sr_ena) | + ((sr_use_t2 == 1'b0) & (phase == 2'b00))) begin + sr_strobe <= !sr_strobe; + end + end + end + + // latch on rising edge, shift on falling edge of P2 + if (sr_write_ena) begin + r_sr <= load_data; + sr_out <= r_sr[7]; + + end + else begin + // DMB: allow shifting in all modes + if (sr_dir_out == 1'b0) begin + // input + if ((sr_cnt[3] == 1'b1) | (sr_cb1_ip == 1'b1)) begin + if (sr_strobe_rising) begin + sr_do_shift <= 1'b1; + r_sr[0] <= I_CB2; + end else if (sr_do_shift) begin + sr_do_shift <= 1'b0; + r_sr[7:1] <= r_sr[6:0]; + end + end + end + else begin + // output + if ((sr_cnt[3] == 1'b1) | (sr_cb1_ip == 1'b1) | (sr_free_run == 1'b1)) begin + if (sr_strobe_falling) begin + sr_out <= r_sr[7]; + sr_do_shift <= 1'b1; + end else if (sr_do_shift) begin + sr_do_shift <= 1'b0; + r_sr <= r_sr[6:0] & r_sr[7]; + end + end + end + end + + // Set shift enabled flag, note does not get set for free_run mode ! + if ((sr_ena == 1'b1) & (sr_cnt[3] == 1'b1)) begin + sr_active <= 1'b1; + end else if ((sr_ena == 1'b1) & (sr_cnt[3] == 1'b0) & (phase == 2'b11)) begin + sr_active <= 1'b0; + end + + sr_count_ena = sr_strobe_rising; + + // DMB: reseting sr_count when not enabled cause the sr to + // start running immediately it was enabled, which is incorrect + // and broke the latest SmartSPI ROM on the BBC Micro + if ((sr_ena == 1'b1) & (sr_write_ena | sr_read_ena) & (!sr_active)) begin + // some documentation says sr bit in IFR must be set as well ? + sr_cnt <= 4'b1000; + end else if (sr_count_ena & (sr_cnt[3] == 1'b1)) begin + sr_cnt <= sr_cnt + 1'b1; + end + + if (sr_count_ena & (sr_cnt == 4'b1111) & (sr_ena == 1'b1) & (sr_free_run == 1'b0)) begin + sr_irq <= 1'b1; + end else if (sr_write_ena | sr_read_ena | (clear_irq[2] == 1'b1)) begin + sr_irq <= 1'b0; + end + + // assign ops + sr_drive_cb2 <= sr_dir_out; + sr_cb1_oe_l <= !sr_cb1_op; + sr_cb1_out <= sr_strobe; + end + end + end + + always @(posedge CLK) begin + if (ENA_4 == 1'b1) begin + sr_strobe_t1 <= sr_strobe; + sr_strobe_rising <= (sr_strobe_t1 == 1'b0) & (sr_strobe == 1'b1); + sr_strobe_falling <= (sr_strobe_t1 == 1'b1) & (sr_strobe == 1'b0); + end + end + + // + // Interrupts + // + + always @(posedge CLK, negedge RESET_L) begin + if (RESET_L == 1'b0) begin + r_ier <= 7'b0000000; + end else begin + if (ENA_4 == 1'b1) begin + if (ier_write_ena) begin + if (load_data[7] == 1'b1) begin + // set + r_ier <= r_ier | load_data[6:0]; + end + else begin + // clear + r_ier <= r_ier & !load_data[6:0]; + end + end + end + end + end + + assign O_IRQ_L = ~final_irq; + + assign r_ifr = {final_irq, t1_irq, t2_irq, cb1_irq, cb2_irq, sr_irq, ca1_irq, ca2_irq}; + + + always @(posedge CLK, negedge RESET_L) begin + if (RESET_L == 1'b0) begin + final_irq <= 1'b0; + end else begin + if (ENA_4 == 1'b1) begin + if ((r_ifr[6:0] & r_ier[6:0]) == 7'b0000000) begin + final_irq <= 1'b0; // no interrupts + end + else begin + final_irq <= 1'b1; + end + end + end + end + + assign clear_irq = ifr_write_ena ? load_data : 8'h00; + +endmodule diff --git a/Computer_MiST/Acorn - System1/rtl/pll.ppf b/Computer_MiST/Acorn - System1/rtl/pll.ppf new file mode 100644 index 00000000..71e6f03a --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/pll.ppf @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/Computer_MiST/Acorn - System1/rtl/pll.qip b/Computer_MiST/Acorn - System1/rtl/pll.qip new file mode 100644 index 00000000..afd958be --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/pll.qip @@ -0,0 +1,4 @@ +set_global_assignment -name IP_TOOL_NAME "ALTPLL" +set_global_assignment -name IP_TOOL_VERSION "13.1" +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"] +set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"] diff --git a/Computer_MiST/Acorn - System1/rtl/pll.v b/Computer_MiST/Acorn - System1/rtl/pll.v new file mode 100644 index 00000000..fb0f488a --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/pll.v @@ -0,0 +1,329 @@ +// 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.4 Build 182 03/12/2014 SJ Web Edition +// ************************************************************ + + +//Copyright (C) 1991-2014 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 ( + inclk0, + c0, + c1); + + input inclk0; + output c0; + output c1; + + wire [4:0] sub_wire0; + wire [0:0] sub_wire5 = 1'h0; + wire [1:1] sub_wire2 = sub_wire0[1:1]; + wire [0:0] sub_wire1 = sub_wire0[0:0]; + wire c0 = sub_wire1; + wire c1 = sub_wire2; + wire sub_wire3 = inclk0; + wire [1:0] sub_wire4 = {sub_wire5, sub_wire3}; + + altpll altpll_component ( + .inclk (sub_wire4), + .clk (sub_wire0), + .activeclock (), + .areset (1'b0), + .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 (), + .locked (), + .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 = 255, + altpll_component.clk0_duty_cycle = 50, + altpll_component.clk0_multiply_by = 236, + altpll_component.clk0_phase_shift = "0", + altpll_component.clk1_divide_by = 54, + altpll_component.clk1_duty_cycle = 50, + altpll_component.clk1_multiply_by = 25, + altpll_component.clk1_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_UNUSED", + 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_UNUSED", + 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_UNUSED", + 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.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 "255" +// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "54" +// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000" +// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "24.988235" +// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "12.500000" +// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0" +// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0" +// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0" +// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575" +// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1" +// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000" +// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000" +// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1" +// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz" +// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0" +// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available" +// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "deg" +// 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 "236" +// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "25" +// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1" +// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "25.00000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "12.50000000" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz" +// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 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_SHIFT_STEP_ENABLED_CHECK STRING "0" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg" +// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "deg" +// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1" +// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0" +// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0" +// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0" +// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif" +// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0" +// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1" +// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0" +// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0" +// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0" +// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000" +// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz" +// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500" +// Retrieval info: PRIVATE: SPREAD_USE STRING "0" +// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0" +// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1" +// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1" +// Retrieval info: PRIVATE: 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: BANDWIDTH_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "255" +// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "236" +// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "54" +// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50" +// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "25" +// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "0" +// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0" +// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037" +// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III" +// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll" +// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL" +// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO" +// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED" +// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED" +// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_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: 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: 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 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: GEN_FILE: TYPE_NORMAL pll.v TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE +// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE +// Retrieval info: LIB_FILE: altera_mf +// Retrieval info: CBX_MODULE_PREFIX: ON diff --git a/Computer_MiST/Acorn - System1/rtl/ps2_mouse.v b/Computer_MiST/Acorn - System1/rtl/ps2_mouse.v new file mode 100644 index 00000000..f60909f5 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/ps2_mouse.v @@ -0,0 +1,78 @@ +`timescale 1ns / 100ps + +// Dave Wood (oldgit) 2019 code taken from muliple sources +// thanks to the original designers. I just glue bits together. + +/* + * PS2 mouse protocol + * Bit 7 6 5 4 3 2 1 0 + * Byte 0: YOVR XOVR YSGN XSGN 1 MBUT RBUT LBUT + * Byte 1: XMOVE + * Byte 2: YMOVE + */ + +/* + * simple PS2 Mouse interface module + * starts with mouse pos(0,0) and keeps mouse location and updates. output is mouse pos(0--636/0--476) ! pos less 4 pixels for size + * mouse buttons 0 by default and 1 when pressed + */ +module ps2_mouse +( + input clk, + input ce, + + input reset, + + input [24:0] ps2_mouse, + + output reg [10:0] mx, my, + output reg mbtnL, + output reg mbtnR, + output reg mbtnM +); + +wire strobe = (old_stb != ps2_mouse[24]); +reg old_stb = 0; +always @(posedge clk) old_stb <= ps2_mouse[24]; + +/* Capture buttons state */ +always@(posedge clk or posedge reset) begin + if (reset) begin + mbtnL <= 1'b0; + mbtnR <= 1'b0; + mbtnM <= 1'b0; + end else if (strobe) begin + mbtnL <= ps2_mouse[0]; + mbtnR <= ps2_mouse[1]; + mbtnM <= ps2_mouse[2]; + end +end + // module parameters + parameter MAX_X = 635; + parameter MAX_Y = 475; + + // low level mouse driver + + wire [8:0] dx, dy; + + // Update "absolute" position of mouse + + wire sx = ps2_mouse[4]; // signs + wire sy = ps2_mouse[5]; + wire [8:0] ndx = sx ? {1'b0,~ps2_mouse[15:8]}+9'b000000001 : {1'b0,ps2_mouse[15:8]}; // magnitudes + wire [8:0] ndy = sy ? {1'b0,~ps2_mouse[23:16]}+9'b000000001 : {1'b0,ps2_mouse[23:16]}; + + always @(posedge clk) begin + mx <= reset ? 0 : + strobe ? (sx ? (mx>ndx ? mx - ndx : 0) + : (mx < MAX_X - ndx ? mx+ndx : MAX_X)) : mx; + // note Y is flipped for video cursor use of mouse + my <= reset ? 0 : + strobe ? (sy ? (my < MAX_Y - ndy ? my+ndy : MAX_Y) + : (my>ndy ? my - ndy : 0)) : my; +// strobe ? (sy ? (my>ndy ? my - ndy : 0) +// : (my < MAX_Y - ndy ? my+ndy : MAX_Y)) : my; + end + + +endmodule diff --git a/Computer_MiST/Acorn - System1/rtl/ps2_mouse.vhd b/Computer_MiST/Acorn - System1/rtl/ps2_mouse.vhd new file mode 100644 index 00000000..4c481b95 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/ps2_mouse.vhd @@ -0,0 +1,173 @@ +-------------------------------------------------------------------------------- +-- +-- FileName: ps2_mouse.vhd +-- Dependencies: ps2_transceiver.vhd, debounce.vhd +-- Design Software: Quartus II 64-bit Version 13.1.0 Build 162 SJ Web Edition +-- +-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY +-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY +-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL +-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF +-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS +-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), +-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. +-- +-- Version History +-- Version 1.0 2/16/2018 Scott Larson +-- Initial Public Release +-- +-------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +ENTITY ps2_mouse IS + GENERIC( + clk_freq : INTEGER := 50_000_000; --system clock frequency in Hz + ps2_debounce_counter_size : INTEGER := 8); --set such that 2^size/clk_freq = 5us (size = 8 for 50MHz) + PORT( + clk : IN STD_LOGIC; --system clock input + reset_n : IN STD_LOGIC; --active low asynchronous reset + ps2_clk : INOUT STD_LOGIC; --clock signal from PS2 mouse + ps2_data : INOUT STD_LOGIC; --data signal from PS2 mouse + mouse_data : OUT STD_LOGIC_VECTOR(23 DOWNTO 0); --data received from mouse + mouse_data_new : OUT STD_LOGIC); --new data packet available flag +END ps2_mouse; + +ARCHITECTURE logic OF ps2_mouse IS + TYPE machine IS(reset, rx_ack1, rx_bat, rx_id, ena_reporting, rx_ack2, stream); --needed states + SIGNAL state : machine := reset; --state machine + SIGNAL tx_ena : STD_LOGIC := '0'; --transmit enable for ps2_transceiver + SIGNAL tx_cmd : STD_LOGIC_VECTOR(8 DOWNTO 0); --command to transmit + SIGNAL tx_busy : STD_LOGIC; --ps2_transceiver busy signal + SIGNAL ps2_code : STD_LOGIC_VECTOR(7 DOWNTO 0); --PS/2 code received from ps2_transceiver + SIGNAL ps2_code_new : STD_LOGIC; --new PS/2 code available flag from ps2_transceiver + SIGNAL ps2_code_new_prev : STD_LOGIC; --previous value of ps2_code_new + SIGNAL packet_byte : INTEGER RANGE 0 TO 2 := 2; --counter to track which packet byte is being received + SIGNAL mouse_data_int : STD_LOGIC_VECTOR(23 DOWNTO 0); --internal mouse data register + + --component to control PS/2 bus interface to the mouse + COMPONENT ps2_transceiver IS + GENERIC( + clk_freq : INTEGER; --system clock frequency in Hz + debounce_counter_size : INTEGER); --set such that (2^size)/clk_freq = 5us (size = 8 for 50MHz) + PORT( + clk : IN STD_LOGIC; --system clock + reset_n : IN STD_LOGIC; --active low asynchronous reset + tx_ena : IN STD_LOGIC; --enable transmit + tx_cmd : IN STD_LOGIC_VECTOR(8 DOWNTO 0); --8-bit command to transmit, MSB is parity bit + tx_busy : OUT STD_LOGIC; --indicates transmit in progress + ack_error : OUT STD_LOGIC; --device acknowledge from transmit, '1' is error + ps2_code : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --code received from PS/2 bus + ps2_code_new : OUT STD_LOGIC; --flag that new PS/2 code is available on ps2_code bus + rx_error : OUT STD_LOGIC; --start, stop, or parity receive error detected, '1' is error + ps2_clk : INOUT STD_LOGIC; --PS/2 port clock signal + ps2_data : INOUT STD_LOGIC); --PS/2 port data signal + END COMPONENT; + +BEGIN + + --PS/2 transceiver to control transactions with mouse + ps2_transceiver_0: ps2_transceiver + GENERIC MAP(clk_freq => clk_freq, debounce_counter_size => ps2_debounce_counter_size) + PORT MAP(clk => clk, reset_n => reset_n, tx_ena => tx_ena, tx_cmd => tx_cmd, tx_busy => tx_busy, ack_error => OPEN, + ps2_code => ps2_code, ps2_code_new => ps2_code_new, rx_error => OPEN, ps2_clk => ps2_clk, ps2_data => ps2_data); + + + PROCESS(clk, reset_n) + BEGIN + IF(reset_n = '0') THEN --asynchronous reset + mouse_data_new <= '0'; --clear new mouse data available flag + mouse_data <= (OTHERS => '0'); --clear last mouse data packet received + state <= reset; --set state machine to reset the mouse + ELSIF(clk'EVENT AND clk = '1') THEN + ps2_code_new_prev <= ps2_code_new; --store previous value of the new PS/2 code flag + + CASE state IS + + WHEN reset => + IF(tx_busy = '0') THEN --transmit to mouse not yet in process + tx_ena <= '1'; --enable transmit to PS/2 mouse + tx_cmd <= "111111111"; --send reset command (0xFF) + state <= reset; --remain in reset state + ELSIF(tx_busy = '1') THEN --transmit to mouse is in process + tx_ena <= '0'; --clear transmit enable + state <= rx_ack1; --wait to receive an acknowledge from mouse + END IF; + + WHEN rx_ack1 => + IF(ps2_code_new_prev = '0' AND ps2_code_new = '1') THEN --new PS/2 code received + IF(ps2_code = "11111010") THEN --new PS/2 code is acknowledge (0xFA) + state <= rx_bat; --wait to receive new BAT completion code + ELSE --new PS/2 code was not an acknowledge + state <= reset; --reset mouse again + END IF; + ELSE --new PS/2 code not yet received + state <= rx_ack1; --wait to receive a code from mouse + END IF; + + WHEN rx_bat => + IF(ps2_code_new_prev = '0' AND ps2_code_new = '1') THEN --new PS/2 code received + IF(ps2_code = "10101010") THEN --new PS/2 code is BAT completion (0xAA) + state <= rx_id; --wait to receive device ID code + ELSE --new PS/2 code was not BAT completion + state <= reset; --reset mouse again + END IF; + ELSE --new PS/2 code not yet received + state <= rx_bat; --wait to receive a code from mouse + END IF; + + WHEN rx_id => + IF(ps2_code_new_prev = '0' AND ps2_code_new = '1') THEN --new PS/2 code received + IF(ps2_code = "00000000") THEN --new PS/2 code is a mouse device ID (0x00) + state <= ena_reporting; --send command to enable data reporting + ELSE --new PS/2 code is not a mouse device ID + state <= reset; --reset mouse again + END IF; + ELSE --new PS/2 code not yet received + state <= rx_id; --wait to receive a code from mouse + END IF; + + WHEN ena_reporting => + IF(tx_busy = '0') THEN --transmit to mouse not yet in process + tx_ena <= '1'; --enable transmit to PS/2 mouse + tx_cmd <= "011110100"; --send enable reporting command (0xF4) + state <= ena_reporting; --remain in ena_reporting state + ELSIF(tx_busy = '1') THEN --transmit to mouse is in process + tx_ena <= '0'; --clear transmit enable + state <= rx_ack2; --wait to receive an acknowledge from mouse + END IF; + + WHEN rx_ack2 => + IF(ps2_code_new_prev = '0' AND ps2_code_new = '1') THEN --new PS/2 code received + IF(ps2_code = "11111010") THEN --new PS/2 code is acknowledge (0xFA) + state <= stream; --proceed to collect and output data from mouse + ELSE --new PS/2 code was not an acknowledge + state <= reset; --reset mouse again + END IF; + ELSE --new PS/2 code not yet received + state <= rx_ack2; --wait to receive a code from mouse + END IF; + + WHEN stream => + IF(ps2_code_new_prev = '0' AND ps2_code_new = '1') THEN --new PS/2 code received + mouse_data_new <= '0'; --clear new data packet available flag + mouse_data_int(7+packet_byte*8 DOWNTO packet_byte*8) <= ps2_code; --store new mouse data byte + IF(packet_byte = 0) THEN --all bytes in packet received and presented + packet_byte <= 2; --clear packet byte counter + ELSE --not all bytes in packet received yet + packet_byte <= packet_byte - 1; --increment packet byte counter + END IF; + END IF; + IF(ps2_code_new_prev = '1' AND ps2_code_new = '1' AND packet_byte = 2) THEN --mouse data receive is complete + mouse_data <= mouse_data_int; --present new mouse data at output + mouse_data_new <= '1'; --set new data packet available flag + END IF; + + END CASE; + END IF; + END PROCESS; + +END logic; \ No newline at end of file diff --git a/Computer_MiST/Acorn - System1/rtl/ps2_transceiver.vhd b/Computer_MiST/Acorn - System1/rtl/ps2_transceiver.vhd new file mode 100644 index 00000000..0e385877 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/ps2_transceiver.vhd @@ -0,0 +1,181 @@ +-------------------------------------------------------------------------------- +-- +-- FileName: ps2_transceiver.vhd +-- Dependencies: debounce.vhd +-- Design Software: Quartus II 64-bit Version 13.1.0 Build 162 SJ Web Edition +-- +-- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY +-- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT +-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +-- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY +-- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL +-- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF +-- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS +-- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), +-- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. +-- +-- Version History +-- Version 1.0 1/19/2018 Scott Larson +-- Initial Public Release +-- +-------------------------------------------------------------------------------- + +LIBRARY ieee; +USE ieee.std_logic_1164.all; + +ENTITY ps2_transceiver IS + GENERIC( + clk_freq : INTEGER := 50_000_000; --system clock frequency in Hz + debounce_counter_size : INTEGER := 8); --set such that (2^size)/clk_freq = 5us (size = 8 for 50MHz) + PORT( + clk : IN STD_LOGIC; --system clock + reset_n : IN STD_LOGIC; --active low asynchronous reset + tx_ena : IN STD_LOGIC; --enable transmit + tx_cmd : IN STD_LOGIC_VECTOR(8 DOWNTO 0); --8-bit command to transmit, MSB is parity bit + tx_busy : OUT STD_LOGIC; --indicates transmit in progress + ack_error : OUT STD_LOGIC; --device acknowledge from transmit, '1' is error + ps2_code : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --code received from PS/2 + ps2_code_new : OUT STD_LOGIC; --flag that new PS/2 code is available on ps2_code bus + rx_error : OUT STD_LOGIC; --start, stop, or parity receive error detected, '1' is error + ps2_clk : INOUT STD_LOGIC; --PS/2 port clock signal + ps2_data : INOUT STD_LOGIC); --PS/2 port data signal +END ps2_transceiver; + +ARCHITECTURE logic OF ps2_transceiver IS + TYPE machine IS(receive, inhibit, transact, tx_complete); --needed states + SIGNAL state : machine := receive; --state machine + SIGNAL sync_ffs : STD_LOGIC_VECTOR(1 DOWNTO 0); --synchronizer flip-flops for PS/2 signals + SIGNAL ps2_clk_int : STD_LOGIC; --debounced input clock signal from PS/2 port + SIGNAL ps2_clk_int_prev : STD_LOGIC; --previous state of the ps2_clk_int signal + SIGNAL ps2_data_int : STD_LOGIC; --debounced input data signal from PS/2 port + SIGNAL ps2_word : STD_LOGIC_VECTOR(10 DOWNTO 0); --stores the ps2 data word (both tx and rx) + SIGNAL error : STD_LOGIC; --validate parity, start, and stop bits for received data + SIGNAL timer : INTEGER RANGE 0 TO clk_freq/10_000 := 0; --counter to determine both inhibit period and when PS/2 is idle + SIGNAL bit_cnt : INTEGER RANGE 0 TO 11 := 0; --count the number of clock pulses during transmit + + --declare debounce component for debouncing PS2 input signals + COMPONENT debounce IS + GENERIC( + counter_size : INTEGER); --debounce period (in seconds) = 2^counter_size/(clk freq in Hz) + PORT( + clk : IN STD_LOGIC; --input clock + button : IN STD_LOGIC; --input signal to be debounced + result : OUT STD_LOGIC); --debounced signal + END COMPONENT; +BEGIN + + --synchronizer flip-flops + PROCESS(clk) + BEGIN + IF(clk'EVENT AND clk = '1') THEN --rising edge of system clock + sync_ffs(0) <= ps2_clk; --synchronize PS/2 clock signal + sync_ffs(1) <= ps2_data; --synchronize PS/2 data signal + END IF; + END PROCESS; + + --debounce PS2 input signals + debounce_ps2_clk: debounce + GENERIC MAP(counter_size => debounce_counter_size) + PORT MAP(clk => clk, button => sync_ffs(0), result => ps2_clk_int); + debounce_ps2_data: debounce + GENERIC MAP(counter_size => debounce_counter_size) + PORT MAP(clk => clk, button => sync_ffs(1), result => ps2_data_int); + + --verify that parity, start, and stop bits are all correct for received data + error <= NOT (NOT ps2_word(0) AND ps2_word(10) AND (ps2_word(9) XOR ps2_word(8) XOR + ps2_word(7) XOR ps2_word(6) XOR ps2_word(5) XOR ps2_word(4) XOR ps2_word(3) XOR + ps2_word(2) XOR ps2_word(1))); + + --state machine to control transmit and receive processes + PROCESS(clk, reset_n) + BEGIN + IF(reset_n = '0') THEN --reset PS/2 transceiver + ps2_clk <= '0'; --inhibit communication on PS/2 bus + ps2_data <= 'Z'; --release PS/2 data line + tx_busy <= '1'; --indicate that no transmit is in progress + ack_error <= '0'; --clear acknowledge error flag + ps2_code <= (OTHERS => '0'); --clear received PS/2 code + ps2_code_new <= '0'; --clear new received PS/2 code flag + rx_error <= '0'; --clear receive error flag + state <= receive; --set state machine to receive state + ELSIF(clk'EVENT AND clk = '1') THEN --rising edge of system clock + ps2_clk_int_prev <= ps2_clk_int; --store previous value of the PS/2 clock signal + CASE state IS --implement state machine + + WHEN receive => + IF(tx_ena = '1') THEN --transmit requested + tx_busy <= '1'; --indicate transmit in progress + timer <= 0; --reset timer for inhibit timing + ps2_word(9 DOWNTO 0) <= tx_cmd & '0'; --load parity, command, and start bit into PS/2 data buffer + bit_cnt <= 0; --clear bit counter + state <= inhibit; --inhibit communication to begin transaction + ELSE --transmit not requested + tx_busy <= '0'; --indicate no transmit in progress + ps2_clk <= 'Z'; --release PS/2 clock port + ps2_data <= 'Z'; --release PS/2 data port + --clock in receive data + IF(ps2_clk_int_prev = '1' AND ps2_clk_int = '0') THEN --falling edge of PS2 clock + ps2_word <= ps2_data_int & ps2_word(10 DOWNTO 1); --shift contents of PS/2 data buffer + END IF; + --determine if PS/2 port is idle + IF(ps2_clk_int = '0') THEN --low PS2 clock, PS/2 is active + timer <= 0; --reset idle counter + ELSIF(timer < clk_freq/18_000) THEN --PS2 clock has been high less than a half clock period (<55us) + timer <= timer + 1; --continue counting + END IF; + --output received data and port status + IF(timer = clk_freq/18_000) THEN --idle threshold reached + IF(error = '0') THEN --no error detected + ps2_code_new <= '1'; --set flag that new PS/2 code is available + ps2_code <= ps2_word(8 DOWNTO 1); --output new PS/2 code + ELSIF(error = '1') THEN --error detected + rx_error <= '1'; --set receive error flag + END IF; + ELSE --PS/2 port active + rx_error <= '0'; --clear receive error flag + ps2_code_new <= '0'; --set flag that PS/2 transaction is in progress + END IF; + state <= receive; --continue streaming receive transactions + END IF; + + WHEN inhibit => + IF(timer < clk_freq/10_000) THEN --first 100us not complete + timer <= timer + 1; --increment timer + ps2_data <= 'Z'; --release data port + ps2_clk <= '0'; --inhibit communication + state <= inhibit; --continue inhibit + ELSE --100us complete + ps2_data <= ps2_word(0); --output start bit to PS/2 data port + state <= transact; --proceed to send bits + END IF; + + WHEN transact => + ps2_clk <= 'Z'; --release clock port + IF(ps2_clk_int_prev = '1' AND ps2_clk_int = '0') THEN --falling edge of PS2 clock + ps2_word <= ps2_data_int & ps2_word(10 DOWNTO 1); --shift contents of PS/2 data buffer + bit_cnt <= bit_cnt + 1; --count clock falling edges + END IF; + IF(bit_cnt < 10) THEN --all bits not sent + ps2_data <= ps2_word(0); --connect serial output of PS/2 data buffer to data port + ELSE --all bits sent + ps2_data <= 'Z'; --release data port + END IF; + IF(bit_cnt = 11) THEN --acknowledge bit received + ack_error <= ps2_data_int; --set error flag if acknowledge is not '0' + state <= tx_complete; --proceed to wait until the slave releases the bus + ELSE --acknowledge bit not received + state <= transact; --continue transaction + END IF; + + WHEN tx_complete => + IF(ps2_clk_int = '1' AND ps2_data_int = '1') THEN --device has released the bus + state <= receive; --proceed to receive data state + ELSE --bus not released by device + state <= tx_complete; --wait for device to release bus + END IF; + + END CASE; + END IF; + END PROCESS; + +END logic; \ No newline at end of file diff --git a/Computer_MiST/Acorn - System1/rtl/roms/ONE.mif b/Computer_MiST/Acorn - System1/rtl/roms/ONE.mif new file mode 100644 index 00000000..d51c8da2 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/roms/ONE.mif @@ -0,0 +1,53 @@ +-- http://srecord.sourceforge.net/ +-- +-- Generated automatically by srec -o --mif +-- +DEPTH = 1024; +WIDTH = 8; +ADDRESS_RADIX = HEX; +DATA_RADIX = HEX; +CONTENT BEGIN +0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0018: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0078: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +00A8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +00D8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +00F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0108: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0120: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0138: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0168: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0198: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +01B0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +01C8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +01E0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +01F8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0210: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0228: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0240: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0258: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0270: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0288: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +02A0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +02B8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +02D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +02E8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0318: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0330: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0348: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0360: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0378: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +0390: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +03A8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +03C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +03D8: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +03F0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00; +END; diff --git a/Computer_MiST/Acorn - System1/rtl/roms/acrnsys1.bin b/Computer_MiST/Acorn - System1/rtl/roms/acrnsys1.bin new file mode 100644 index 0000000000000000000000000000000000000000..da655178b4993e37c8d60d0062ca12afc17e6bc0 GIT binary patch literal 512 zcmW-dO=uHA6vt;bo7sHMZml2bDmwM!5b@Ac$gQ~usRXZDCYgylj|-pzJ|sZd4&gA5cCSn_q@#;iGx-V2=L|$~|qg#t+^b z;WuI|m5UbwljJw8&OEC30fRit62}>o`pQlfKNNK3hAi7E8ZY1ciU-zn6V&k?fpfyc zOv_BG1WF3!N8yhMay8O@xSQgdukWVotkRK)dIzIM1Ah>Wb&Mpsd`Sg!VOy+9`9IkM ztIkr_Fj|;MS?-biL3tE@cH{Cz>kQ*TRyU za;8RC^ON|s81th(loK-{VXnFw{wkg&r7C9|%DYb&hv7^ggpd?QAXJBiHjoK5EpDCz z&GUd{oUEN&sgk^#AH@V=Al^E&JNAiB+p1Fjes)7u$jo*^`3W`>3NhVTX{hP(BD{U` W?!CwQlh*2^TgwmbZ^ehgi~j?Vme}wB literal 0 HcmV?d00001 diff --git a/Computer_MiST/Acorn - System1/rtl/roms/acrnsys1.vhd b/Computer_MiST/Acorn - System1/rtl/roms/acrnsys1.vhd new file mode 100644 index 00000000..81976e40 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/roms/acrnsys1.vhd @@ -0,0 +1,54 @@ +library ieee; +use ieee.std_logic_1164.all,ieee.numeric_std.all; + +entity acrnsys1 is +port ( + clk : in std_logic; + addr : in std_logic_vector(8 downto 0); + data : out std_logic_vector(7 downto 0) +); +end entity; + +architecture prom of acrnsys1 is + type rom is array(0 to 511) of std_logic_vector(7 downto 0); + signal rom_data: rom := ( + X"A0",X"06",X"B5",X"00",X"20",X"6F",X"FE",X"CA",X"88",X"88",X"10",X"F6",X"86",X"1A",X"A2",X"07", + X"8E",X"22",X"0E",X"A0",X"00",X"B5",X"10",X"8D",X"21",X"0E",X"8E",X"20",X"0E",X"AD",X"20",X"0E", + X"29",X"3F",X"24",X"0F",X"10",X"18",X"C9",X"38",X"B0",X"06",X"86",X"19",X"A9",X"40",X"85",X"0F", + X"A1",X"00",X"88",X"D0",X"FB",X"CA",X"10",X"DB",X"A5",X"0E",X"30",X"D2",X"10",X"14",X"E4",X"19", + X"D0",X"EE",X"C9",X"38",X"90",X"04",X"A9",X"80",X"D0",X"E4",X"C5",X"0F",X"F0",X"E2",X"85",X"0F", + X"49",X"38",X"29",X"1F",X"C9",X"10",X"85",X"0D",X"A6",X"1A",X"8C",X"21",X"0E",X"60",X"A1",X"00", + X"A0",X"06",X"D0",X"0B",X"A0",X"03",X"B5",X"00",X"20",X"6F",X"FE",X"88",X"88",X"B5",X"01",X"C8", + X"48",X"20",X"7A",X"FE",X"88",X"68",X"4A",X"4A",X"4A",X"4A",X"84",X"1A",X"29",X"0F",X"A8",X"B9", + X"EA",X"FF",X"A4",X"1A",X"99",X"10",X"00",X"60",X"20",X"64",X"FE",X"20",X"0C",X"FE",X"B0",X"20", + X"A0",X"04",X"0A",X"0A",X"0A",X"0A",X"0A",X"36",X"00",X"36",X"01",X"88",X"D0",X"F8",X"F0",X"E8", + X"F6",X"06",X"D0",X"02",X"F6",X"07",X"B5",X"06",X"D5",X"08",X"D0",X"04",X"B5",X"07",X"D5",X"09", + X"60",X"A0",X"40",X"8C",X"22",X"0E",X"A0",X"07",X"8C",X"20",X"0E",X"6A",X"6A",X"20",X"CD",X"FE", + X"6A",X"8D",X"20",X"0E",X"88",X"10",X"F6",X"20",X"CD",X"FE",X"8C",X"20",X"0E",X"20",X"D0",X"FE", + X"84",X"1A",X"A0",X"48",X"88",X"D0",X"FD",X"88",X"D0",X"FD",X"A4",X"1A",X"60",X"A0",X"08",X"2C", + X"20",X"0E",X"30",X"FB",X"20",X"D0",X"FE",X"20",X"CD",X"FE",X"0E",X"20",X"0E",X"6A",X"88",X"D0", + X"F6",X"F0",X"DA",X"A2",X"FF",X"9A",X"8E",X"23",X"0E",X"86",X"0E",X"A0",X"80",X"A2",X"09",X"94", + X"0E",X"CA",X"D0",X"FB",X"20",X"0C",X"FE",X"90",X"F2",X"29",X"07",X"C9",X"04",X"90",X"25",X"F0", + X"6F",X"C9",X"06",X"F0",X"09",X"B0",X"0F",X"A5",X"0A",X"A6",X"0B",X"A4",X"0C",X"40",X"F6",X"00", + X"D0",X"0C",X"F6",X"01",X"B0",X"08",X"B5",X"00",X"D0",X"02",X"D6",X"01",X"D6",X"00",X"20",X"64", + X"FE",X"4C",X"45",X"FF",X"84",X"16",X"84",X"17",X"0A",X"AA",X"49",X"F7",X"85",X"10",X"20",X"88", + X"FE",X"E0",X"02",X"B0",X"15",X"20",X"5E",X"FE",X"20",X"0C",X"FE",X"B0",X"BC",X"A1",X"00",X"0A", + X"0A",X"0A",X"0A",X"05",X"0D",X"81",X"00",X"4C",X"45",X"FF",X"D0",X"03",X"6C",X"02",X"00",X"E0", + X"04",X"F0",X"36",X"A2",X"08",X"86",X"10",X"20",X"88",X"FE",X"A2",X"04",X"B5",X"05",X"20",X"B1", + X"FE",X"CA",X"D0",X"F8",X"A1",X"06",X"20",X"B1",X"FE",X"20",X"A0",X"FE",X"D0",X"F6",X"F0",X"2A", + X"A2",X"04",X"20",X"DD",X"FE",X"95",X"05",X"CA",X"D0",X"F8",X"20",X"DD",X"FE",X"81",X"06",X"8D", + X"21",X"0E",X"20",X"A0",X"FE",X"D0",X"F3",X"F0",X"11",X"A1",X"00",X"F0",X"06",X"85",X"18",X"A9", + X"00",X"F0",X"02",X"A5",X"18",X"81",X"00",X"20",X"5E",X"FE",X"4C",X"04",X"FF",X"6C",X"1C",X"00", + X"6C",X"1E",X"00",X"85",X"0A",X"86",X"0B",X"84",X"0C",X"68",X"48",X"85",X"0D",X"A2",X"0D",X"A9", + X"FF",X"85",X"0E",X"20",X"00",X"FE",X"BA",X"86",X"13",X"C8",X"84",X"12",X"D8",X"BD",X"02",X"01", + X"38",X"E5",X"1B",X"9D",X"02",X"01",X"85",X"11",X"BD",X"03",X"01",X"E9",X"00",X"9D",X"03",X"01", + X"85",X"10",X"A2",X"13",X"20",X"00",X"FE",X"4C",X"07",X"FF",X"3F",X"06",X"5B",X"4F",X"66",X"6D", + X"7D",X"07",X"7F",X"6F",X"77",X"7C",X"58",X"5E",X"79",X"71",X"AD",X"FF",X"F3",X"FE",X"B0",X"FF"); +begin +process(clk) +begin + if rising_edge(clk) then + data <= rom_data(to_integer(unsigned(addr))); + end if; +end process; +end architecture; diff --git a/Computer_MiST/Acorn - System1/rtl/roms/monitor.mif b/Computer_MiST/Acorn - System1/rtl/roms/monitor.mif new file mode 100644 index 00000000..f638fc1b --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/roms/monitor.mif @@ -0,0 +1,32 @@ +-- http://srecord.sourceforge.net/ +-- +-- Generated automatically by srec -o --mif +-- +DEPTH = 512; +WIDTH = 8; +ADDRESS_RADIX = HEX; +DATA_RADIX = HEX; +CONTENT BEGIN +0000: A0 06 B5 00 20 6F FE CA 88 88 10 F6 86 1A A2 07 8E 22 0E A0 00 B5 10 8D; +0018: 21 0E 8E 20 0E AD 20 0E 29 3F 24 0F 10 18 C9 38 B0 06 86 19 A9 40 85 0F; +0030: A1 00 88 D0 FB CA 10 DB A5 0E 30 D2 10 14 E4 19 D0 EE C9 38 90 04 A9 80; +0048: D0 E4 C5 0F F0 E2 85 0F 49 38 29 1F C9 10 85 0D A6 1A 8C 21 0E 60 A1 00; +0060: A0 06 D0 0B A0 03 B5 00 20 6F FE 88 88 B5 01 C8 48 20 7A FE 88 68 4A 4A; +0078: 4A 4A 84 1A 29 0F A8 B9 EA FF A4 1A 99 10 00 60 20 64 FE 20 0C FE B0 20; +0090: A0 04 0A 0A 0A 0A 0A 36 00 36 01 88 D0 F8 F0 E8 F6 06 D0 02 F6 07 B5 06; +00A8: D5 08 D0 04 B5 07 D5 09 60 A0 40 8C 22 0E A0 07 8C 20 0E 6A 6A 20 CD FE; +00C0: 6A 8D 20 0E 88 10 F6 20 CD FE 8C 20 0E 20 D0 FE 84 1A A0 48 88 D0 FD 88; +00D8: D0 FD A4 1A 60 A0 08 2C 20 0E 30 FB 20 D0 FE 20 CD FE 0E 20 0E 6A 88 D0; +00F0: F6 F0 DA A2 FF 9A 8E 23 0E 86 0E A0 80 A2 09 94 0E CA D0 FB 20 0C FE 90; +0108: F2 29 07 C9 04 90 25 F0 6F C9 06 F0 09 B0 0F A5 0A A6 0B A4 0C 40 F6 00; +0120: D0 0C F6 01 B0 08 B5 00 D0 02 D6 01 D6 00 20 64 FE 4C 45 FF 84 16 84 17; +0138: 0A AA 49 F7 85 10 20 88 FE E0 02 B0 15 20 5E FE 20 0C FE B0 BC A1 00 0A; +0150: 0A 0A 0A 05 0D 81 00 4C 45 FF D0 03 6C 02 00 E0 04 F0 36 A2 08 86 10 20; +0168: 88 FE A2 04 B5 05 20 B1 FE CA D0 F8 A1 06 20 B1 FE 20 A0 FE D0 F6 F0 2A; +0180: A2 04 20 DD FE 95 05 CA D0 F8 20 DD FE 81 06 8D 21 0E 20 A0 FE D0 F3 F0; +0198: 11 A1 00 F0 06 85 18 A9 00 F0 02 A5 18 81 00 20 5E FE 4C 04 FF 6C 1C 00; +01B0: 6C 1E 00 85 0A 86 0B 84 0C 68 48 85 0D A2 0D A9 FF 85 0E 20 00 FE BA 86; +01C8: 13 C8 84 12 D8 BD 02 01 38 E5 1B 9D 02 01 85 11 BD 03 01 E9 00 9D 03 01; +01E0: 85 10 A2 13 20 00 FE 4C 07 FF 3F 06 5B 4F 66 6D 7D 07 7F 6F 77 7C 58 5E; +01F8: 79 71 AD FF F3 FE B0 FF; +END; diff --git a/Computer_MiST/Acorn - System1/rtl/vga.v b/Computer_MiST/Acorn - System1/rtl/vga.v new file mode 100644 index 00000000..3bbd7cf4 --- /dev/null +++ b/Computer_MiST/Acorn - System1/rtl/vga.v @@ -0,0 +1,1638 @@ +// Display for Acorn system1 +// Dave Wood 2019 +// +// This is a complete mess and needs a re-write +// +// "Abandon all hope, ye who enter here." +// +// +// + +module vga ( + input clk, + input rst, + input wire x1,y1,mbtnL,mbtnR,mbtnM, + input wire [10:0] mx,my, + input wire [8:0] ch0,ch1,ch2,ch3,ch4,ch5,ch6,ch7, + output wire osw0,osw1,osw2,osw3,osw4,osw5,osw6,osw7,osw8,osw9,oswa,oswb,oswc,oswd,oswe,oswf,oswrst,oswm,oswl,oswg,oswr,oswp,oswU,osws,oswD, + output wire [7:0] r,g,b, + output reg hs, vs, hblank, vblank +); + +wire [9:0] dot_x = mx[9:0]; +wire [9:0] dot_y = my[9:0]; +reg [7:0] dispvar; +reg [23:0] pix_col; +//reg [9:0] mp; + + +assign r = pix_col[23:16]; +assign g = pix_col[15:8]; +assign b = pix_col[7:0]; + + +reg [9:0]hcount,vcount; +localparam hmax = 10'd799, vmax = 10'd524; + +reg sw0,sw1,sw2,sw3,sw4,sw5,sw6,sw7,sw8,sw9,swa,swb,swc,swd,swe,swf,swm,swl,swg,swr,swp,swU,sws,swD; +reg swrst=1'b0; +assign osw0 = sw0; +assign osw1 = sw1; +assign osw2 = sw2; +assign osw3 = sw3; +assign osw4 = sw4; +assign osw5 = sw5; +assign osw6 = sw6; +assign osw7 = sw7; +assign osw8 = sw8; +assign osw9 = sw9; +assign oswa = swa; +assign oswb = swb; +assign oswc = swc; +assign oswd = swd; +assign oswe = swe; +assign oswf = swf; +assign oswrst = swrst; +assign oswm = swm; +assign oswl = swl; +assign oswg = swg; +assign oswr = swr; +assign oswp = swp; +assign oswU = swU; +assign osws = sws; +assign oswD = swD; + +always @(posedge clk, posedge rst) begin + if (rst) begin + hcount <= 10'd0; + vcount <= 10'd0; + end else begin +// h & v pixel counters + if(hcount < hmax) + hcount <= hcount + 1'b1; + else begin + hcount <= 10'd0; + if(vcount < vmax) + vcount <= vcount + 1'b1; + else + vcount <= 10'd0; + end + +// v & h sync signals + if(hcount == 10'd656) + hs<=1'b1; + else if (hcount >= 10'd752) + hs<=1'b0; + if(vcount == 10'd490) + vs<=1'b1; + else if(vcount >= 10'd492) + vs<=1'b0; + +// h & v blanking signals + if(hcount >= 10'd640) + hblank <= 1'b1; + else + hblank <= 1'b0; + + if(vcount >= 10'd480) + vblank <= 1'b1; + else + vblank <= 1'b0; + + end +end + +always @(posedge clk, posedge rst) begin + if(rst) + pix_col <= black; + else begin +// borders + if(vcount == 10'd0 || vcount == 10'd479) + pix_col <= olive; + else if(hcount == 10'd0 || hcount == 10'd639) + pix_col <= teal; + else + pix_col <= black; + //eurocard + if(hcount >= 10'd100 && hcount <= 10'd484 && vcount >= 10'd110 && vcount <= 10'd370) + pix_col <= green; + + //ic1 & 8 + if(hcount >= 10'd112 && hcount <= 10'd113 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd116 && hcount <= 10'd117 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd120 && hcount <= 10'd121 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd124 && hcount <= 10'd125 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd128 && hcount <= 10'd129 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd132 && hcount <= 10'd133 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd136 && hcount <= 10'd137 && vcount == 10'd149) + pix_col <= silver; + + if(hcount >= 10'd154 && hcount <= 10'd155 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd158 && hcount <= 10'd159 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd162 && hcount <= 10'd163 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd166 && hcount <= 10'd167 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd170 && hcount <= 10'd171 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd174 && hcount <= 10'd175 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd178 && hcount <= 10'd179 && vcount == 10'd149) + pix_col <= silver; + if(hcount >= 10'd182 && hcount <= 10'd183 && vcount == 10'd149) + pix_col <= silver; + + if(hcount >= 10'd110 && hcount <= 10'd139 && vcount >= 10'd150 && vcount <= 10'd165) + pix_col <= black; + if(hcount >= 10'd152 && hcount <= 10'd185 && vcount >= 10'd150 && vcount <= 10'd165) + pix_col <= black; + + if(hcount >= 10'd112 && hcount <= 10'd113 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd116 && hcount <= 10'd117 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd120 && hcount <= 10'd121 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd124 && hcount <= 10'd125 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd128 && hcount <= 10'd129 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd132 && hcount <= 10'd133 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd136 && hcount <= 10'd137 && vcount == 10'd166) + pix_col <= silver; + + if(hcount >= 10'd154 && hcount <= 10'd155 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd158 && hcount <= 10'd159 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd162 && hcount <= 10'd163 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd166 && hcount <= 10'd167 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd170 && hcount <= 10'd171 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd174 && hcount <= 10'd175 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd178 && hcount <= 10'd179 && vcount == 10'd166) + pix_col <= silver; + if(hcount >= 10'd182 && hcount <= 10'd183 && vcount == 10'd166) + pix_col <= silver; + +// ic 2 & 4 + if(hcount >= 10'd112 && hcount <= 10'd113 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd116 && hcount <= 10'd117 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd120 && hcount <= 10'd121 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd124 && hcount <= 10'd125 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd128 && hcount <= 10'd129 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd132 && hcount <= 10'd133 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd136 && hcount <= 10'd137 && vcount == 10'd204) + pix_col <= silver; + + if(hcount >= 10'd158 && hcount <= 10'd159 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd162 && hcount <= 10'd163 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd166 && hcount <= 10'd167 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd170 && hcount <= 10'd171 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd174 && hcount <= 10'd175 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd178 && hcount <= 10'd179 && vcount == 10'd204) + pix_col <= silver; + if(hcount >= 10'd182 && hcount <= 10'd183 && vcount == 10'd204) + pix_col <= silver; + + if(hcount >= 10'd110 && hcount <= 10'd139 && vcount >= 10'd205 && vcount <= 10'd220) + pix_col <= black; + if(hcount >= 10'd156 && hcount <= 10'd185 && vcount >= 10'd205 && vcount <= 10'd220) + pix_col <= black; + if(hcount >= 10'd112 && hcount <= 10'd113 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd116 && hcount <= 10'd117 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd120 && hcount <= 10'd121 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd124 && hcount <= 10'd125 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd128 && hcount <= 10'd129 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd132 && hcount <= 10'd133 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd136 && hcount <= 10'd137 && vcount == 10'd221) + pix_col <= silver; + + if(hcount >= 10'd158 && hcount <= 10'd159 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd162 && hcount <= 10'd163 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd166 && hcount <= 10'd167 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd170 && hcount <= 10'd171 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd174 && hcount <= 10'd175 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd178 && hcount <= 10'd179 && vcount == 10'd221) + pix_col <= silver; + if(hcount >= 10'd182 && hcount <= 10'd183 && vcount == 10'd221) + pix_col <= silver; +// ic 3 &5 + + if(hcount >= 10'd112 && hcount <= 10'd113 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd116 && hcount <= 10'd117 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd120 && hcount <= 10'd121 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd124 && hcount <= 10'd125 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd128 && hcount <= 10'd129 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd132 && hcount <= 10'd133 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd136 && hcount <= 10'd137 && vcount == 10'd259) + pix_col <= silver; + + if(hcount >= 10'd158 && hcount <= 10'd159 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd162 && hcount <= 10'd163 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd166 && hcount <= 10'd167 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd170 && hcount <= 10'd171 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd174 && hcount <= 10'd175 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd178 && hcount <= 10'd179 && vcount == 10'd259) + pix_col <= silver; + if(hcount >= 10'd182 && hcount <= 10'd183 && vcount == 10'd259) + pix_col <= silver; + + if(hcount >= 10'd110 && hcount <= 10'd139 && vcount >= 10'd260 && vcount <= 10'd275) + pix_col <= black; + if(hcount >= 10'd156 && hcount <= 10'd185 && vcount >= 10'd260 && vcount <= 10'd275) + pix_col <= black; + if(hcount >= 10'd112 && hcount <= 10'd113 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd116 && hcount <= 10'd117 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd120 && hcount <= 10'd121 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd124 && hcount <= 10'd125 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd128 && hcount <= 10'd129 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd132 && hcount <= 10'd133 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd136 && hcount <= 10'd137 && vcount == 10'd276) + pix_col <= silver; + + if(hcount >= 10'd158 && hcount <= 10'd159 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd162 && hcount <= 10'd163 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd166 && hcount <= 10'd167 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd170 && hcount <= 10'd171 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd174 && hcount <= 10'd175 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd178 && hcount <= 10'd179 && vcount == 10'd276) + pix_col <= silver; + if(hcount >= 10'd182 && hcount <= 10'd183 && vcount == 10'd276) + pix_col <= silver; + +// ic 7 & 6 + if(hcount >= 10'd124 && hcount <= 10'd125 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd128 && hcount <= 10'd129 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd132 && hcount <= 10'd133 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd136 && hcount <= 10'd137 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd158 && hcount <= 10'd159 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd162 && hcount <= 10'd163 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd166 && hcount <= 10'd167 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd170 && hcount <= 10'd171 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd174 && hcount <= 10'd175 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd178 && hcount <= 10'd179 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd182 && hcount <= 10'd183 && vcount == 10'd314) + pix_col <= silver; + if(hcount >= 10'd122 && hcount <= 10'd139 && vcount >= 10'd315 && vcount <= 10'd330) + pix_col <= black; + if(hcount >= 10'd156 && hcount <= 10'd185 && vcount >= 10'd315 && vcount <= 10'd330) + pix_col <= black; + + if(hcount >= 10'd124 && hcount <= 10'd125 && vcount == 10'd331) + pix_col <= silver; + if(hcount >= 10'd128 && hcount <= 10'd129 && vcount == 10'd331) + pix_col <= silver; + if(hcount >= 10'd132 && hcount <= 10'd133 && vcount == 10'd331) + pix_col <= silver; + if(hcount >= 10'd136 && hcount <= 10'd137 && vcount == 10'd331) + pix_col <= silver; + if(hcount >= 10'd158 && hcount <= 10'd159 && vcount == 10'd331) + pix_col <= silver; + if(hcount >= 10'd162 && hcount <= 10'd163 && vcount == 10'd331) + pix_col <= silver; + if(hcount >= 10'd166 && hcount <= 10'd167 && vcount == 10'd331) + pix_col <= silver; + if(hcount >= 10'd170 && hcount <= 10'd171 && vcount == 10'd331) + pix_col <= silver; + if(hcount >= 10'd174 && hcount <= 10'd175 && vcount == 10'd331) + pix_col <= silver; + if(hcount >= 10'd178 && hcount <= 10'd179 && vcount == 10'd331) + pix_col <= silver; + if(hcount >= 10'd182 && hcount <= 10'd183 && vcount == 10'd331) + pix_col <= silver; + + //keybase + if(hcount >= 10'd200 && hcount <= 10'd466 && vcount >= 10'd120 && vcount <= 10'd360) + pix_col <= silver; + //slot + if(hcount >= 10'd244 && hcount <= 10'd336 && vcount >= 10'd200 && vcount <= 10'd204) + pix_col <= green; + //display + if(hcount >= 10'd230 && hcount <= 10'd346 && vcount >= 10'd140 && vcount <= 10'd176) + pix_col <= teal; + + +//chars +// left most - not connected + if(hcount >= 10'd235 && hcount <= 10'd244 && vcount >= 10'd150 && vcount <= 10'd164) begin + pix_col <= silver; + end +// character 7 left + if(hcount >= 10'd247 && hcount <= 10'd256 && vcount >= 10'd150 && vcount <= 10'd164) begin + if(hcount >= 10'd249 && hcount <= 10'd254 && vcount == 10'd152) + pix_col <= ch7[0] == 1'b1 ? red : silver; + else if(hcount == 10'd248 && vcount == 10'd153) + pix_col <= ch7[5] == 1'b1 ? red : silver; + else if(hcount == 10'd255 && vcount == 10'd153) + pix_col <= ch7[1] == 1'b1 ? red : silver; + else if(hcount == 10'd248 && vcount == 10'd154) + pix_col <= ch7[5] == 1'b1 ? red : silver; + else if(hcount == 10'd255 && vcount == 10'd154) + pix_col <= ch7[1] == 1'b1 ? red : silver; + else if(hcount == 10'd248 && vcount == 10'd155) + pix_col <= ch7[5] == 1'b1 ? red : silver; + else if(hcount == 10'd255 && vcount == 10'd155) + pix_col <= ch7[1] == 1'b1 ? red : silver; + else if(hcount == 10'd248 && vcount == 10'd156) + pix_col <= ch7[5] == 1'b1 ? red : silver; + else if(hcount == 10'd255 && vcount == 10'd156) + pix_col <= ch7[1] == 1'b1 ? red : silver; + else if(hcount >= 10'd249 && hcount <= 10'd254 && vcount == 10'd157) + pix_col <= ch7[6] == 1'b1 ? red : silver; + else if(hcount == 10'd248 && vcount == 10'd158) + pix_col <= ch7[4] == 1'b1 ? red : silver; + else if(hcount == 10'd255 && vcount == 10'd158) + pix_col <= ch7[2] == 1'b1 ? red : silver; + else if(hcount == 10'd248 && vcount == 10'd159) + pix_col <= ch7[4] == 1'b1 ? red : silver; + else if(hcount == 10'd255 && vcount == 10'd159) + pix_col <= ch7[2] == 1'b1 ? red : silver; + else if(hcount == 10'd248 && vcount == 10'd160) + pix_col <= ch7[4] == 1'b1 ? red : silver; + else if(hcount == 10'd255 && vcount == 10'd160) + pix_col <= ch7[2] == 1'b1 ? red : silver; + else if(hcount == 10'd248 && vcount == 10'd161) + pix_col <= ch7[4] == 1'b1 ? red : silver; + else if(hcount == 10'd255 && vcount == 10'd161) + pix_col <= ch7[2] == 1'b1 ? red : silver; + else if(hcount >= 10'd249 && hcount <= 10'd254 && vcount == 10'd162) + pix_col <= ch7[3] == 1'b1 ? red : silver; + else if(hcount == 10'd255 && vcount == 10'd164) + pix_col <= ch7[7] == 1'b1 ? red : silver; + else + pix_col <= silver; + + end +// character 6 + if(hcount >= 10'd259 && hcount <= 10'd268 && vcount >= 10'd150 && vcount <= 10'd164) begin + if(hcount >= 10'd261 && hcount <= 10'd266 && vcount == 10'd152) + pix_col <= ch6[0] == 1'b1 ? red : silver; + else if(hcount == 10'd260 && vcount == 10'd153) + pix_col <= ch6[5] == 1'b1 ? red : silver; + else if(hcount == 10'd267 && vcount == 10'd153) + pix_col <= ch6[1] == 1'b1 ? red : silver; + else if(hcount == 10'd260 && vcount == 10'd154) + pix_col <= ch6[5] == 1'b1 ? red : silver; + else if(hcount == 10'd267 && vcount == 10'd154) + pix_col <= ch6[1] == 1'b1 ? red : silver; + else if(hcount == 10'd260 && vcount == 10'd155) + pix_col <= ch6[5] == 1'b1 ? red : silver; + else if(hcount == 10'd267 && vcount == 10'd155) + pix_col <= ch6[1] == 1'b1 ? red : silver; + else if(hcount == 10'd260 && vcount == 10'd156) + pix_col <= ch6[5] == 1'b1 ? red : silver; + else if(hcount == 10'd267 && vcount == 10'd156) + pix_col <= ch6[1] == 1'b1 ? red : silver; + else if(hcount >= 10'd261 && hcount <= 10'd266 && vcount == 10'd157) + pix_col <= ch6[6] == 1'b1 ? red : silver; + else if(hcount == 10'd260 && vcount == 10'd158) + pix_col <= ch6[4] == 1'b1 ? red : silver; + else if(hcount == 10'd267 && vcount == 10'd158) + pix_col <= ch6[2] == 1'b1 ? red : silver; + else if(hcount == 10'd260 && vcount == 10'd159) + pix_col <= ch6[4] == 1'b1 ? red : silver; + else if(hcount == 10'd267 && vcount == 10'd159) + pix_col <= ch6[2] == 1'b1 ? red : silver; + else if(hcount == 10'd260 && vcount == 10'd160) + pix_col <= ch6[4] == 1'b1 ? red : silver; + else if(hcount == 10'd267 && vcount == 10'd160) + pix_col <= ch6[2] == 1'b1 ? red : silver; + else if(hcount == 10'd260 && vcount == 10'd161) + pix_col <= ch6[4] == 1'b1 ? red : silver; + else if(hcount == 10'd267 && vcount == 10'd161) + pix_col <= ch6[2] == 1'b1 ? red : silver; + else if(hcount >= 10'd261 && hcount <= 10'd266 && vcount == 10'd162) + pix_col <= ch6[3] == 1'b1 ? red : silver; + else if(hcount == 10'd267 && vcount == 10'd164) + pix_col <= ch6[7] == 1'b1 ? red : silver; + else + pix_col <= silver; + end +// character 5 + if(hcount >= 10'd271 && hcount <= 10'd280 && vcount >= 10'd150 && vcount <= 10'd164) begin + if(hcount >= 10'd273 && hcount <= 10'd278 && vcount == 10'd152) + pix_col <= ch5[0] == 1'b1 ? red : silver; + else if(hcount == 10'd272 && vcount == 10'd153) + pix_col <= ch5[5] == 1'b1 ? red : silver; + else if(hcount == 10'd279 && vcount == 10'd153) + pix_col <= ch5[1] == 1'b1 ? red : silver; + else if(hcount == 10'd272 && vcount == 10'd154) + pix_col <= ch5[5] == 1'b1 ? red : silver; + else if(hcount == 10'd279 && vcount == 10'd154) + pix_col <= ch5[1] == 1'b1 ? red : silver; + else if(hcount == 10'd272 && vcount == 10'd155) + pix_col <= ch5[5] == 1'b1 ? red : silver; + else if(hcount == 10'd279 && vcount == 10'd155) + pix_col <= ch5[1] == 1'b1 ? red : silver; + else if(hcount == 10'd272 && vcount == 10'd156) + pix_col <= ch5[5] == 1'b1 ? red : silver; + else if(hcount == 10'd279 && vcount == 10'd156) + pix_col <= ch5[1] == 1'b1 ? red : silver; + else if(hcount >= 10'd273 && hcount <= 10'd278 && vcount == 10'd157) + pix_col <= ch5[6] == 1'b1 ? red : silver; + else if(hcount == 10'd272 && vcount == 10'd158) + pix_col <= ch5[4] == 1'b1 ? red : silver; + else if(hcount == 10'd279 && vcount == 10'd158) + pix_col <= ch5[2] == 1'b1 ? red : silver; + else if(hcount == 10'd272 && vcount == 10'd159) + pix_col <= ch5[4] == 1'b1 ? red : silver; + else if(hcount == 10'd279 && vcount == 10'd159) + pix_col <= ch5[2] == 1'b1 ? red : silver; + else if(hcount == 10'd272 && vcount == 10'd160) + pix_col <= ch5[4] == 1'b1 ? red : silver; + else if(hcount == 10'd279 && vcount == 10'd160) + pix_col <= ch5[2] == 1'b1 ? red : silver; + else if(hcount == 10'd272 && vcount == 10'd161) + pix_col <= ch5[4] == 1'b1 ? red : silver; + else if(hcount == 10'd279 && vcount == 10'd161) + pix_col <= ch5[2] == 1'b1 ? red : silver; + else if(hcount >= 10'd273 && hcount <= 10'd278 && vcount == 10'd162) + pix_col <= ch5[3] == 1'b1 ? red : silver; + else if(hcount == 10'd279 && vcount == 10'd164) + pix_col <= ch5[7] == 1'b1 ? red : silver; + else + pix_col <= silver; + end +// character 4 + if(hcount >= 10'd283 && hcount <= 10'd292 && vcount >= 10'd150 && vcount <= 10'd164) begin + if(hcount >= 10'd285 && hcount <= 10'd290 && vcount == 10'd152) + pix_col <= ch4[0] == 1'b1 ? red : silver; + else if(hcount == 10'd284 && vcount == 10'd153) + pix_col <= ch4[5] == 1'b1 ? red : silver; + else if(hcount == 10'd291 && vcount == 10'd153) + pix_col <= ch4[1] == 1'b1 ? red : silver; + else if(hcount == 10'd284 && vcount == 10'd154) + pix_col <= ch4[5] == 1'b1 ? red : silver; + else if(hcount == 10'd291 && vcount == 10'd154) + pix_col <= ch4[1] == 1'b1 ? red : silver; + else if(hcount == 10'd284 && vcount == 10'd155) + pix_col <= ch4[5] == 1'b1 ? red : silver; + else if(hcount == 10'd291 && vcount == 10'd155) + pix_col <= ch4[1] == 1'b1 ? red : silver; + else if(hcount == 10'd284 && vcount == 10'd156) + pix_col <= ch4[5] == 1'b1 ? red : silver; + else if(hcount == 10'd291 && vcount == 10'd156) + pix_col <= ch4[1] == 1'b1 ? red : silver; + else if(hcount >= 10'd285 && hcount <= 10'd290 && vcount == 10'd157) + pix_col <= ch4[6] == 1'b1 ? red : silver; + else if(hcount == 10'd284 && vcount == 10'd158) + pix_col <= ch4[4] == 1'b1 ? red : silver; + else if(hcount == 10'd291 && vcount == 10'd158) + pix_col <= ch4[2] == 1'b1 ? red : silver; + else if(hcount == 10'd284 && vcount == 10'd159) + pix_col <= ch4[4] == 1'b1 ? red : silver; + else if(hcount == 10'd291 && vcount == 10'd159) + pix_col <= ch4[2] == 1'b1 ? red : silver; + else if(hcount == 10'd284 && vcount == 10'd160) + pix_col <= ch4[4] == 1'b1 ? red : silver; + else if(hcount == 10'd291 && vcount == 10'd160) + pix_col <= ch4[2] == 1'b1 ? red : silver; + else if(hcount == 10'd284 && vcount == 10'd161) + pix_col <= ch4[4] == 1'b1 ? red : silver; + else if(hcount == 10'd291 && vcount == 10'd161) + pix_col <= ch4[2] == 1'b1 ? red : silver; + else if(hcount >= 10'd285 && hcount <= 10'd290 && vcount == 10'd162) + pix_col <= ch4[3] == 1'b1 ? red : silver; + else if(hcount == 10'd291 && vcount == 10'd164) + pix_col <= ch4[7] == 1'b1 ? red : silver; + else + pix_col <= silver; + end +// character 3 + if(hcount >= 10'd295 && hcount <= 10'd304 && vcount >= 10'd150 && vcount <= 10'd164) begin + if(hcount >= 10'd297 && hcount <= 10'd302 && vcount == 10'd152) + pix_col <= ch3[0] == 1'b1 ? red : silver; + else if(hcount == 10'd296 && vcount == 10'd153) + pix_col <= ch3[5] == 1'b1 ? red : silver; + else if(hcount == 10'd303 && vcount == 10'd153) + pix_col <= ch3[1] == 1'b1 ? red : silver; + else if(hcount == 10'd296 && vcount == 10'd154) + pix_col <= ch3[5] == 1'b1 ? red : silver; + else if(hcount == 10'd303 && vcount == 10'd154) + pix_col <= ch3[1] == 1'b1 ? red : silver; + else if(hcount == 10'd296 && vcount == 10'd155) + pix_col <= ch3[5] == 1'b1 ? red : silver; + else if(hcount == 10'd303 && vcount == 10'd155) + pix_col <= ch3[1] == 1'b1 ? red : silver; + else if(hcount == 10'd296 && vcount == 10'd156) + pix_col <= ch3[5] == 1'b1 ? red : silver; + else if(hcount == 10'd303 && vcount == 10'd156) + pix_col <= ch3[1] == 1'b1 ? red : silver; + else if(hcount >= 10'd297 && hcount <= 10'd302 && vcount == 10'd157) + pix_col <= ch3[6] == 1'b1 ? red : silver; + else if(hcount == 10'd296 && vcount == 10'd158) + pix_col <= ch3[4] == 1'b1 ? red : silver; + else if(hcount == 10'd303 && vcount == 10'd158) + pix_col <= ch3[2] == 1'b1 ? red : silver; + else if(hcount == 10'd296 && vcount == 10'd159) + pix_col <= ch3[4] == 1'b1 ? red : silver; + else if(hcount == 10'd303 && vcount == 10'd159) + pix_col <= ch3[2] == 1'b1 ? red : silver; + else if(hcount == 10'd296 && vcount == 10'd160) + pix_col <= ch3[4] == 1'b1 ? red : silver; + else if(hcount == 10'd303 && vcount == 10'd160) + pix_col <= ch3[2] == 1'b1 ? red : silver; + else if(hcount == 10'd296 && vcount == 10'd161) + pix_col <= ch3[4] == 1'b1 ? red : silver; + else if(hcount == 10'd303 && vcount == 10'd161) + pix_col <= ch3[2] == 1'b1 ? red : silver; + else if(hcount >= 10'd297 && hcount <= 10'd302 && vcount == 10'd162) + pix_col <= ch3[3] == 1'b1 ? red : silver; + else if(hcount == 10'd303 && vcount == 10'd164) + pix_col <= ch3[7] == 1'b1 ? red : silver; + else + pix_col <= silver; + end +// character 2 + if(hcount >= 10'd307 && hcount <= 10'd316 && vcount >= 10'd150 && vcount <= 10'd164) begin + if(hcount >= 10'd309 && hcount <= 10'd314 && vcount == 10'd152) + pix_col <= ch2[0] == 1'b1 ? red : silver; + else if(hcount == 10'd308 && vcount == 10'd153) + pix_col <= ch2[5] == 1'b1 ? red : silver; + else if(hcount == 10'd315 && vcount == 10'd153) + pix_col <= ch2[1] == 1'b1 ? red : silver; + else if(hcount == 10'd308 && vcount == 10'd154) + pix_col <= ch2[5] == 1'b1 ? red : silver; + else if(hcount == 10'd315 && vcount == 10'd154) + pix_col <= ch2[1] == 1'b1 ? red : silver; + else if(hcount == 10'd308 && vcount == 10'd155) + pix_col <= ch2[5] == 1'b1 ? red : silver; + else if(hcount == 10'd315 && vcount == 10'd155) + pix_col <= ch2[1] == 1'b1 ? red : silver; + else if(hcount == 10'd308 && vcount == 10'd156) + pix_col <= ch2[5] == 1'b1 ? red : silver; + else if(hcount == 10'd315 && vcount == 10'd156) + pix_col <= ch2[1] == 1'b1 ? red : silver; + else if(hcount >= 10'd309 && hcount <= 10'd314 && vcount == 10'd157) + pix_col <= ch2[6] == 1'b1 ? red : silver; + else if(hcount == 10'd308 && vcount == 10'd158) + pix_col <= ch2[4] == 1'b1 ? red : silver; + else if(hcount == 10'd315 && vcount == 10'd158) + pix_col <= ch2[2] == 1'b1 ? red : silver; + else if(hcount == 10'd308 && vcount == 10'd159) + pix_col <= ch2[4] == 1'b1 ? red : silver; + else if(hcount == 10'd315 && vcount == 10'd159) + pix_col <= ch2[2] == 1'b1 ? red : silver; + else if(hcount == 10'd308 && vcount == 10'd160) + pix_col <= ch2[4] == 1'b1 ? red : silver; + else if(hcount == 10'd315 && vcount == 10'd160) + pix_col <= ch2[2] == 1'b1 ? red : silver; + else if(hcount == 10'd308 && vcount == 10'd161) + pix_col <= ch2[4] == 1'b1 ? red : silver; + else if(hcount == 10'd315 && vcount == 10'd161) + pix_col <= ch2[2] == 1'b1 ? red : silver; + else if(hcount >= 10'd309 && hcount <= 10'd314 && vcount == 10'd162) + pix_col <= ch2[3] == 1'b1 ? red : silver; + else if(hcount == 10'd315 && vcount == 10'd164) + pix_col <= ch2[7] == 1'b1 ? red : silver; + else + pix_col <= silver; + end +// character 1 + if(hcount >= 10'd319 && hcount <= 10'd328 && vcount >= 10'd150 && vcount <= 10'd164) begin + if(hcount >= 10'd321 && hcount <= 10'd326 && vcount == 10'd152) + pix_col <= ch1[0] == 1'b1 ? red : silver; + else if(hcount == 10'd320 && vcount == 10'd153) + pix_col <= ch1[5] == 1'b1 ? red : silver; + else if(hcount == 10'd327 && vcount == 10'd153) + pix_col <= ch1[1] == 1'b1 ? red : silver; + else if(hcount == 10'd320 && vcount == 10'd154) + pix_col <= ch1[5] == 1'b1 ? red : silver; + else if(hcount == 10'd327 && vcount == 10'd154) + pix_col <= ch1[1] == 1'b1 ? red : silver; + else if(hcount == 10'd320 && vcount == 10'd155) + pix_col <= ch1[5] == 1'b1 ? red : silver; + else if(hcount == 10'd327 && vcount == 10'd155) + pix_col <= ch1[1] == 1'b1 ? red : silver; + else if(hcount == 10'd320 && vcount == 10'd156) + pix_col <= ch1[5] == 1'b1 ? red : silver; + else if(hcount == 10'd327 && vcount == 10'd156) + pix_col <= ch1[1] == 1'b1 ? red : silver; + else if(hcount >= 10'd321 && hcount <= 10'd326 && vcount == 10'd157) + pix_col <= ch1[6] == 1'b1 ? red : silver; + else if(hcount == 10'd320 && vcount == 10'd158) + pix_col <= ch1[4] == 1'b1 ? red : silver; + else if(hcount == 10'd327 && vcount == 10'd158) + pix_col <= ch1[2] == 1'b1 ? red : silver; + else if(hcount == 10'd320 && vcount == 10'd159) + pix_col <= ch1[4] == 1'b1 ? red : silver; + else if(hcount == 10'd327 && vcount == 10'd159) + pix_col <= ch1[2] == 1'b1 ? red : silver; + else if(hcount == 10'd320 && vcount == 10'd160) + pix_col <= ch1[4] == 1'b1 ? red : silver; + else if(hcount == 10'd327 && vcount == 10'd160) + pix_col <= ch1[2] == 1'b1 ? red : silver; + else if(hcount == 10'd320 && vcount == 10'd161) + pix_col <= ch1[4] == 1'b1 ? red : silver; + else if(hcount == 10'd327 && vcount == 10'd161) + pix_col <= ch1[2] == 1'b1 ? red : silver; + else if(hcount >= 10'd321 && hcount <= 10'd326 && vcount == 10'd162) + pix_col <= ch1[3] == 1'b1 ? red : silver; + else if(hcount == 10'd327 && vcount == 10'd164) + pix_col <= ch1[7] == 1'b1 ? red : silver; + else + pix_col <= silver; + end +// character 0 right + if(hcount >= 10'd331 && hcount <= 10'd340 && vcount >= 10'd150 && vcount <= 10'd164) begin + if(hcount >= 10'd333 && hcount <= 10'd338 && vcount == 10'd152) + pix_col <= ch0[0] == 1'b1 ? red : silver; + else if(hcount == 10'd332 && vcount == 10'd153) + pix_col <= ch0[5] == 1'b1 ? red : silver; + else if(hcount == 10'd339 && vcount == 10'd153) + pix_col <= ch0[1] == 1'b1 ? red : silver; + else if(hcount == 10'd332 && vcount == 10'd154) + pix_col <= ch0[5] == 1'b1 ? red : silver; + else if(hcount == 10'd339 && vcount == 10'd154) + pix_col <= ch0[1] == 1'b1 ? red : silver; + else if(hcount == 10'd332 && vcount == 10'd155) + pix_col <= ch0[5] == 1'b1 ? red : silver; + else if(hcount == 10'd339 && vcount == 10'd155) + pix_col <= ch0[1] == 1'b1 ? red : silver; + else if(hcount == 10'd332 && vcount == 10'd156) + pix_col <= ch0[5] == 1'b1 ? red : silver; + else if(hcount == 10'd339 && vcount == 10'd156) + pix_col <= ch0[1] == 1'b1 ? red : silver; + else if(hcount >= 10'd333 && hcount <= 10'd338 && vcount == 10'd157) + pix_col <= ch0[6] == 1'b1 ? red : silver; + else if(hcount == 10'd332 && vcount == 10'd158) + pix_col <= ch0[4] == 1'b1 ? red : silver; + else if(hcount == 10'd339 && vcount == 10'd158) + pix_col <= ch0[2] == 1'b1 ? red : silver; + else if(hcount == 10'd332 && vcount == 10'd159) + pix_col <= ch0[4] == 1'b1 ? red : silver; + else if(hcount == 10'd339 && vcount == 10'd159) + pix_col <= ch0[2] == 1'b1 ? red : silver; + else if(hcount == 10'd332 && vcount == 10'd160) + pix_col <= ch0[4] == 1'b1 ? red : silver; + else if(hcount == 10'd339 && vcount == 10'd160) + pix_col <= ch0[2] == 1'b1 ? red : silver; + else if(hcount == 10'd332 && vcount == 10'd161) + pix_col <= ch0[4] == 1'b1 ? red : silver; + else if(hcount == 10'd339 && vcount == 10'd161) + pix_col <= ch0[2] == 1'b1 ? red : silver; + else if(hcount >= 10'd333 && hcount <= 10'd338 && vcount == 10'd162) + pix_col <= ch0[3] == 1'b1 ? red : silver; + else if(hcount == 10'd339 && vcount == 10'd164) + pix_col <= ch0[7] == 1'b1 ? red : silver; + else + pix_col <= silver; + end + + + +//keys +//rst + if(hcount >= 10'd408 && hcount <= 10'd432 && vcount >= 10'd196 && vcount <= 10'd208) //rst + pix_col <= swrst == 1'b1 ? grey : white; + +//1st row + if(hcount >= 10'd232 && hcount <= 10'd256 && vcount >= 10'd224 && vcount <= 10'd236) //c + pix_col <= swc == 1'b1 ? grey : white; + if(hcount >= 10'd264 && hcount <= 10'd288 && vcount >= 10'd224 && vcount <= 10'd236) //d + pix_col <= swd == 1'b1 ? grey : white; + if(hcount >= 10'd296 && hcount <= 10'd320 && vcount >= 10'd224 && vcount <= 10'd236) //e + pix_col <= swe == 1'b1 ? grey : white; + if(hcount >= 10'd328 && hcount <= 10'd352 && vcount >= 10'd224 && vcount <= 10'd236) //f + pix_col <= swf == 1'b1 ? grey : white; + if(hcount >= 10'd376 && hcount <= 10'd400 && vcount >= 10'd224 && vcount <= 10'd236) //m + pix_col <= swm == 1'b1 ? grey : white; + if(hcount >= 10'd408 && hcount <= 10'd432 && vcount >= 10'd224 && vcount <= 10'd236) //l + pix_col <= swl == 1'b1 ? grey : white; + +//2nd row + if(hcount >= 10'd232 && hcount <= 10'd256 && vcount >= 10'd252 && vcount <= 10'd264) //8 + pix_col <= sw8 == 1'b1 ? grey : white; + if(hcount >= 10'd264 && hcount <= 10'd288 && vcount >= 10'd252 && vcount <= 10'd264) //9 + pix_col <= sw9 == 1'b1 ? grey: white; + if(hcount >= 10'd296 && hcount <= 10'd320 && vcount >= 10'd252 && vcount <= 10'd264) //a + pix_col <= swa == 1'b1 ? grey : white; + if(hcount >= 10'd328 && hcount <= 10'd352 && vcount >= 10'd252 && vcount <= 10'd264) //b + pix_col <= swb == 1'b1 ? grey : white; + if(hcount >= 10'd376 && hcount <= 10'd400 && vcount >= 10'd252 && vcount <= 10'd264) //g + pix_col <= swg == 1'b1 ? grey : white; + if(hcount >= 10'd408 && hcount <= 10'd432 && vcount >= 10'd252 && vcount <= 10'd264) //r + pix_col <= swr == 1'b1 ? grey : white; + +//3rd row + if(hcount >= 10'd232 && hcount <= 10'd256 && vcount >= 10'd280 && vcount <= 10'd292) //4 + pix_col <= sw4 == 1'b1 ? grey : white; + if(hcount >= 10'd264 && hcount <= 10'd288 && vcount >= 10'd280 && vcount <= 10'd292) //5 + pix_col <= sw5 == 1'b1 ? grey: white; + if(hcount >= 10'd296 && hcount <= 10'd320 && vcount >= 10'd280 && vcount <= 10'd292) //6 + pix_col <= sw6 == 1'b1 ? grey : white; + if(hcount >= 10'd328 && hcount <= 10'd352 && vcount >= 10'd280 && vcount <= 10'd292) //7 + pix_col <= sw7 == 1'b1 ? grey : white; + if(hcount >= 10'd376 && hcount <= 10'd400 && vcount >= 10'd280 && vcount <= 10'd292) //p + pix_col <= swp == 1'b1 ? grey : white; + if(hcount >= 10'd408 && hcount <= 10'd432 && vcount >= 10'd280 && vcount <= 10'd292) //U + pix_col <= swU == 1'b1 ? grey : white; + +//4th row + if(hcount >= 10'd232 && hcount <= 10'd256 && vcount >= 10'd308 && vcount <= 10'd320) //0 + pix_col <= sw0 == 1'b1 ? grey : white; + if(hcount >= 10'd264 && hcount <= 10'd288 && vcount >= 10'd308 && vcount <= 10'd320) //1 + pix_col <= sw1 == 1'b1 ? grey: white; + if(hcount >= 10'd296 && hcount <= 10'd320 && vcount >= 10'd308 && vcount <= 10'd320) //2 + pix_col <= sw2 == 1'b1 ? grey : white; + if(hcount >= 10'd328 && hcount <= 10'd352 && vcount >= 10'd308 && vcount <= 10'd320) //3 + pix_col <= sw3 == 1'b1 ? grey : white; + if(hcount >= 10'd376 && hcount <= 10'd400 && vcount >= 10'd308 && vcount <= 10'd320) //s + pix_col <= sws == 1'b1 ? grey : white; + if(hcount >= 10'd408 && hcount <= 10'd432 && vcount >= 10'd308 && vcount <= 10'd320) //D + pix_col <= swD == 1'b1 ? grey : white; + +//rst + if(hcount >= 10'd414 && hcount <= 10'd415 && vcount == 10'd186) + pix_col <= black; + if(hcount == 10'd413 && vcount == 10'd187) + pix_col <= black; + if(hcount == 10'd413 && vcount == 10'd188) + pix_col <= black; + if(hcount == 10'd413 && vcount == 10'd189) + pix_col <= black; + if(hcount == 10'd413 && vcount == 10'd190) + pix_col <= black; + if(hcount == 10'd413 && vcount == 10'd191) + pix_col <= black; + if(hcount == 10'd413 && vcount == 10'd192) + pix_col <= black; + + + if(hcount >= 10'd419 && hcount <= 10'd421 && vcount == 10'd186) + pix_col <= black; + if(hcount == 10'd418 && vcount == 10'd187) + pix_col <= black; + if(hcount == 10'd422 && vcount == 10'd187) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd188) + pix_col <= black; + if(hcount == 10'd420 && vcount == 10'd189) + pix_col <= black; + if(hcount == 10'd421 && vcount == 10'd190) + pix_col <= black; + if(hcount == 10'd418 && vcount == 10'd191) + pix_col <= black; + if(hcount == 10'd422 && vcount == 10'd191) + pix_col <= black; + if(hcount >= 10'd419 && hcount <= 10'd421 && vcount == 10'd192) + pix_col <= black; + + if(hcount == 10'd427 && vcount == 10'd185) + pix_col <= black; + if(hcount == 10'd427 && vcount == 10'd186) + pix_col <= black; + if(hcount >= 10'd426 && hcount <= 10'd429 && vcount == 10'd187) + pix_col <= black; + if(hcount == 10'd427 && vcount == 10'd188) + pix_col <= black; + if(hcount == 10'd427 && vcount == 10'd189) + pix_col <= black; + if(hcount == 10'd427 && vcount == 10'd190) + pix_col <= black; + if(hcount == 10'd427 && vcount == 10'd191) + pix_col <= black; + if(hcount == 10'd427 && vcount == 10'd192) + pix_col <= black; + +//c + if(hcount >= 10'd243 && hcount <= 10'd245 && vcount == 10'd214) + pix_col <= black; + if(hcount == 10'd242 && vcount == 10'd215) + pix_col <= black; + if(hcount == 10'd246 && vcount == 10'd215) + pix_col <= black; + if(hcount == 10'd242 && vcount == 10'd216) + pix_col <= black; + if(hcount == 10'd242 && vcount == 10'd217) + pix_col <= black; + if(hcount == 10'd242 && vcount == 10'd218) + pix_col <= black; + if(hcount == 10'd242 && vcount == 10'd219) + pix_col <= black; + if(hcount == 10'd246 && vcount == 10'd219) + pix_col <= black; + if(hcount >= 10'd243 && hcount <= 10'd245 && vcount == 10'd220) + pix_col <= black; +//d + if(hcount == 10'd278 && vcount == 10'd213) + pix_col <= black; + if(hcount == 10'd278 && vcount == 10'd214) + pix_col <= black; + if(hcount >= 10'd275 && hcount <= 10'd278 && vcount == 10'd215) + pix_col <= black; + if(hcount == 10'd274 && vcount == 10'd216) + pix_col <= black; + if(hcount == 10'd278 && vcount == 10'd216) + pix_col <= black; + if(hcount == 10'd274 && vcount == 10'd217) + pix_col <= black; + if(hcount == 10'd278 && vcount == 10'd217) + pix_col <= black; + if(hcount == 10'd274 && vcount == 10'd218) + pix_col <= black; + if(hcount == 10'd278 && vcount == 10'd218) + pix_col <= black; + if(hcount == 10'd274 && vcount == 10'd219) + pix_col <= black; + if(hcount == 10'd278 && vcount == 10'd219) + pix_col <= black; + if(hcount >= 10'd275 && hcount <= 10'd277 && vcount == 10'd220) + pix_col <= black; +//e 307 + if(hcount >= 10'd306 && hcount <= 10'd308 && vcount == 10'd214) + pix_col <= black; + if(hcount == 10'd305 && vcount == 10'd215) + pix_col <= black; + if(hcount == 10'd309 && vcount == 10'd215) + pix_col <= black; + if(hcount == 10'd305 && vcount == 10'd216) + pix_col <= black; + if(hcount == 10'd309 && vcount == 10'd216) + pix_col <= black; + if(hcount >= 10'd305 && hcount <= 10'd309 && vcount == 10'd217) + pix_col <= black; +// if(hcount == 10'd305 && vcount == 10'd217) +// pix_col <= black; + if(hcount == 10'd305 && vcount == 10'd218) + pix_col <= black; + if(hcount == 10'd305 && vcount == 10'd219) + pix_col <= black; + if(hcount == 10'd309 && vcount == 10'd219) + pix_col <= black; + if(hcount >= 10'd306 && hcount <= 10'd308 && vcount == 10'd220) + pix_col <= black; +//f + if(hcount >= 10'd341 && hcount <= 10'd342 && vcount == 10'd213) + pix_col <= black; + if(hcount == 10'd340 && vcount == 10'd214) + pix_col <= black; + if(hcount >= 10'd339 && hcount <= 10'd342 && vcount == 10'd215) + pix_col <= black; + if(hcount == 10'd340 && vcount == 10'd216) + pix_col <= black; + if(hcount == 10'd340 && vcount == 10'd217) + pix_col <= black; + if(hcount == 10'd340 && vcount == 10'd218) + pix_col <= black; + if(hcount == 10'd340 && vcount == 10'd219) + pix_col <= black; + if(hcount == 10'd340 && vcount == 10'd220) + pix_col <= black; + +//m + if(hcount >= 10'd387 && hcount <= 10'd388 && vcount == 10'd214) + pix_col <= black; + if(hcount >= 10'd390 && hcount <= 10'd391 && vcount == 10'd214) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd215) + pix_col <= black; + if(hcount == 10'd389 && vcount == 10'd215) + pix_col <= black; + if(hcount == 10'd392 && vcount == 10'd215) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd216) + pix_col <= black; + if(hcount == 10'd389 && vcount == 10'd216) + pix_col <= black; + if(hcount == 10'd392 && vcount == 10'd216) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd217) + pix_col <= black; + if(hcount == 10'd389 && vcount == 10'd217) + pix_col <= black; + if(hcount == 10'd392 && vcount == 10'd217) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd218) + pix_col <= black; + if(hcount == 10'd389 && vcount == 10'd218) + pix_col <= black; + if(hcount == 10'd392 && vcount == 10'd218) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd219) + pix_col <= black; + if(hcount == 10'd389 && vcount == 10'd219) + pix_col <= black; + if(hcount == 10'd392 && vcount == 10'd219) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd220) + pix_col <= black; + if(hcount == 10'd389 && vcount == 10'd220) + pix_col <= black; + if(hcount == 10'd392 && vcount == 10'd220) + pix_col <= black; + +//l + if(hcount == 10'd420 && vcount == 10'd213) + pix_col <= black; + if(hcount == 10'd420 && vcount == 10'd214) + pix_col <= black; + if(hcount == 10'd420 && vcount == 10'd215) + pix_col <= black; + if(hcount == 10'd420 && vcount == 10'd216) + pix_col <= black; + if(hcount == 10'd420 && vcount == 10'd217) + pix_col <= black; + if(hcount == 10'd420 && vcount == 10'd218) + pix_col <= black; + if(hcount == 10'd420 && vcount == 10'd219) + pix_col <= black; + if(hcount == 10'd421 && vcount == 10'd220) + pix_col <= black; + + + + +//8 + if(hcount >= 10'd242 && hcount <= 10'd246 && vcount == 10'd240) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd241) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd241) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd242) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd242) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd243) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd243) + pix_col <= black; + if(hcount >= 10'd242 && hcount <= 10'd246 && vcount == 10'd244) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd245) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd245) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd246) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd246) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd247) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd247) + pix_col <= black; + if(hcount >= 10'd242 && hcount <= 10'd246 && vcount == 10'd248) + pix_col <= black; + + +//9 + if(hcount >= 10'd274 && hcount <= 10'd278 && vcount == 10'd240) + pix_col <= black; + if(hcount == 10'd273 && vcount == 10'd241) + pix_col <= black; + if(hcount == 10'd279 && vcount == 10'd241) + pix_col <= black; + if(hcount == 10'd273 && vcount == 10'd242) + pix_col <= black; + if(hcount == 10'd279 && vcount == 10'd242) + pix_col <= black; + if(hcount == 10'd273 && vcount == 10'd243) + pix_col <= black; + if(hcount == 10'd279 && vcount == 10'd243) + pix_col <= black; + if(hcount >= 10'd274 && hcount <= 10'd278 && vcount == 10'd244) + pix_col <= black; + + if(hcount == 10'd279 && vcount == 10'd245) + pix_col <= black; + + if(hcount == 10'd279 && vcount == 10'd246) + pix_col <= black; + + if(hcount == 10'd279 && vcount == 10'd247) + pix_col <= black; + if(hcount >= 10'd274 && hcount <= 10'd278 && vcount == 10'd248) + pix_col <= black; +//a + if(hcount >= 10'd307 && hcount <= 10'd309 && vcount == 10'd241) + pix_col <= black; + if(hcount == 10'd310 && vcount == 10'd242) + pix_col <= black; + if(hcount == 10'd310 && vcount == 10'd243) + pix_col <= black; + if(hcount >= 10'd307 && hcount <= 10'd310 && vcount == 10'd244) + pix_col <= black; +// if(hcount == 10'd306 && vcount == 10'd244) +// pix_col <= black; +// if(hcount == 10'd310 && vcount == 10'd244) +// pix_col <= black; + if(hcount == 10'd306 && vcount == 10'd245) + pix_col <= black; + if(hcount == 10'd310 && vcount == 10'd245) + pix_col <= black; + if(hcount == 10'd306 && vcount == 10'd246) + pix_col <= black; + if(hcount == 10'd310 && vcount == 10'd246) + pix_col <= black; + if(hcount == 10'd306 && vcount == 10'd247) + pix_col <= black; + if(hcount == 10'd310 && vcount == 10'd247) + pix_col <= black; + if(hcount >= 10'd307 && hcount <= 10'd310 && vcount == 10'd248) + pix_col <= black; +//b + if(hcount == 10'd338 && vcount == 10'd241) + pix_col <= black; + if(hcount == 10'd338 && vcount == 10'd242) + pix_col <= black; + if(hcount >= 10'd338 && hcount <= 10'd341 && vcount == 10'd243) + pix_col <= black; + if(hcount == 10'd338 && vcount == 10'd244) + pix_col <= black; + if(hcount == 10'd342 && vcount == 10'd244) + pix_col <= black; + if(hcount == 10'd338 && vcount == 10'd245) + pix_col <= black; + if(hcount == 10'd342 && vcount == 10'd245) + pix_col <= black; + if(hcount == 10'd338 && vcount == 10'd246) + pix_col <= black; + if(hcount == 10'd342 && vcount == 10'd246) + pix_col <= black; + if(hcount == 10'd338 && vcount == 10'd247) + pix_col <= black; + if(hcount == 10'd342 && vcount == 10'd247) + pix_col <= black; + if(hcount >= 10'd339 && hcount <= 10'd341 && vcount == 10'd248) + pix_col <= black; +//g + if(hcount >= 10'd387 && hcount <= 10'd390 && vcount == 10'd241) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd242) + pix_col <= black; + if(hcount == 10'd390 && vcount == 10'd242) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd243) + pix_col <= black; + if(hcount == 10'd390 && vcount == 10'd243) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd244) + pix_col <= black; + if(hcount == 10'd390 && vcount == 10'd244) + pix_col <= black; + if(hcount >= 10'd387 && hcount <= 10'd390 && vcount == 10'd245) + pix_col <= black; + if(hcount == 10'd390 && vcount == 10'd246) + pix_col <= black; + if(hcount == 10'd390 && vcount == 10'd247) + pix_col <= black; + if(hcount >= 10'd387 && hcount <= 10'd389 && vcount == 10'd248) + pix_col <= black; + +//r + if(hcount >= 10'd420 && hcount <= 10'd421 && vcount == 10'd242) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd243) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd244) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd245) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd246) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd247) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd248) + pix_col <= black; + + + +//4 + if(hcount == 10'd245 && vcount == 10'd268) + pix_col <= black; + if(hcount == 10'd244 && vcount == 10'd269) + pix_col <= black; + if(hcount == 10'd245 && vcount == 10'd269) + pix_col <= black; + if(hcount == 10'd243 && vcount == 10'd270) + pix_col <= black; + if(hcount == 10'd245 && vcount == 10'd270) + pix_col <= black; + if(hcount == 10'd242 && vcount == 10'd271) + pix_col <= black; + if(hcount == 10'd245 && vcount == 10'd271) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd272) + pix_col <= black; + if(hcount == 10'd245 && vcount == 10'd272) + pix_col <= black; + if(hcount >= 10'd240 && hcount <= 10'd246 && vcount == 10'd273) + pix_col <= black; + + if(hcount == 10'd245 && vcount == 10'd274) + pix_col <= black; + + if(hcount == 10'd245 && vcount == 10'd275) + pix_col <= black; + if(hcount == 10'd245 && vcount == 10'd276) + pix_col <= black; + +//5 + if(hcount >= 10'd273 && hcount <= 10'd279 && vcount == 10'd268) + pix_col <= black; + if(hcount == 10'd273 &&vcount == 10'd269) + pix_col <= black; + if(hcount == 10'd273 && vcount == 10'd270) + pix_col <= black; + if(hcount == 10'd273 && vcount == 10'd271) + pix_col <= black; + if(hcount >= 10'd274 && hcount <= 10'd278 && vcount == 10'd272) + pix_col <= black; + if(hcount == 10'd279 && vcount == 10'd273) + pix_col <= black; + if(hcount == 10'd279 && vcount == 10'd274) + pix_col <= black; + if(hcount == 10'd273 && vcount == 10'd275) + pix_col <= black; + if(hcount == 10'd279 && vcount == 10'd275) + pix_col <= black; + if(hcount >= 10'd274 && hcount <= 10'd278 && vcount == 10'd276) + pix_col <= black; +//6 + if(hcount >= 10'd305 && hcount <= 10'd309 && vcount == 10'd268) + pix_col <= black; + if(hcount == 10'd304 && vcount == 10'd269) + pix_col <= black; + if(hcount == 10'd310 && vcount == 10'd269) + pix_col <= black; + if(hcount == 10'd304 && vcount == 10'd270) + pix_col <= black; + if(hcount == 10'd304 && vcount == 10'd271) + pix_col <= black; + + if(hcount >= 10'd304 && hcount <= 10'd309 && vcount == 10'd272) + pix_col <= black; + + if(hcount == 10'd304 && vcount == 10'd273) + pix_col <= black; + if(hcount == 10'd310 && vcount == 10'd273) + pix_col <= black; + if(hcount == 10'd304 && vcount == 10'd274) + pix_col <= black; + if(hcount == 10'd310 && vcount == 10'd274) + pix_col <= black; + if(hcount == 10'd304 && vcount == 10'd275) + pix_col <= black; + if(hcount == 10'd310 && vcount == 10'd275) + pix_col <= black; + if(hcount >= 10'd305 && hcount <= 10'd309 && vcount == 10'd276) + pix_col <= black; +//7 + if(hcount >= 10'd336 && hcount <= 10'd342 && vcount == 10'd268) + pix_col <= black; + if(hcount == 10'd342 && vcount == 10'd269) + pix_col <= black; + + if(hcount == 10'd341 && vcount == 10'd270) + pix_col <= black; + + + if(hcount == 10'd341 && vcount == 10'd271) + pix_col <= black; + if(hcount == 10'd340 && vcount == 10'd272) + pix_col <= black; + + if(hcount == 10'd339 && vcount == 10'd273) + pix_col <= black; + + if(hcount == 10'd338 && vcount == 10'd274) + pix_col <= black; + + if(hcount == 10'd338 && vcount == 10'd275) + pix_col <= black; + + if(hcount == 10'd338 && vcount == 10'd276) + pix_col <= black; +//p + if(hcount >= 10'd386 && hcount <= 10'd389 && vcount == 10'd269) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd270) + pix_col <= black; + if(hcount == 10'd390 && vcount == 10'd270) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd271) + pix_col <= black; + if(hcount == 10'd390 && vcount == 10'd271) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd272) + pix_col <= black; + if(hcount == 10'd390 && vcount == 10'd272) + pix_col <= black; + if(hcount >= 10'd386 && hcount <= 10'd389 && vcount == 10'd273) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd274) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd275) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd276) + pix_col <= black; + + +//up + if(hcount == 10'd420 && vcount == 10'd268) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd269) + pix_col <= black; + if(hcount == 10'd421 && vcount == 10'd269) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd270) + pix_col <= black; + if(hcount == 10'd421 && vcount == 10'd270) + pix_col <= black; + if(hcount == 10'd418 && vcount == 10'd271) + pix_col <= black; + if(hcount == 10'd422 && vcount == 10'd271) + pix_col <= black; + if(hcount == 10'd418 && vcount == 10'd272) + pix_col <= black; + if(hcount == 10'd422 && vcount == 10'd272) + pix_col <= black; + if(hcount == 10'd417 && vcount == 10'd273) + pix_col <= black; + if(hcount == 10'd423 && vcount == 10'd273) + pix_col <= black; + if(hcount == 10'd417 && vcount == 10'd274) + pix_col <= black; + if(hcount == 10'd423 && vcount == 10'd274) + pix_col <= black; + if(hcount == 10'd416 && vcount == 10'd275) + pix_col <= black; + if(hcount == 10'd424 && vcount == 10'd275) + pix_col <= black; + if(hcount == 10'd416 && vcount == 10'd276) + pix_col <= black; + if(hcount == 10'd424 && vcount == 10'd276) + pix_col <= black; + + +//0 + if(hcount >= 10'd242 && hcount <= 10'd246 && vcount == 10'd296) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd297) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd297) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd298) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd298) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd299) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd299) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd300) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd300) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd301) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd301) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd302) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd302) + pix_col <= black; + if(hcount == 10'd241 && vcount == 10'd303) + pix_col <= black; + if(hcount == 10'd247 && vcount == 10'd303) + pix_col <= black; + if(hcount >= 10'd242 && hcount <= 10'd246 && vcount == 10'd304) + pix_col <= black; + +//1 + if(hcount == 10'd276 && vcount == 10'd296) + pix_col <= black; + if(hcount >= 10'd275 && hcount <= 10'd276 &&vcount == 10'd297) + pix_col <= black; + if(hcount == 10'd276 && vcount == 10'd298) + pix_col <= black; + if(hcount == 10'd276 && vcount == 10'd299) + pix_col <= black; + if(hcount == 10'd276 && vcount == 10'd300) + pix_col <= black; + if(hcount == 10'd276 && vcount == 10'd301) + pix_col <= black; + if(hcount == 10'd276 && vcount == 10'd302) + pix_col <= black; + if(hcount == 10'd276 && vcount == 10'd303) + pix_col <= black; + if(hcount == 10'd276 && vcount == 10'd304) + pix_col <= black; + +//2 + if(hcount >= 10'd306 && hcount <= 10'd308 && vcount == 10'd296) + pix_col <= black; + if(hcount == 10'd305 && vcount == 10'd297) + pix_col <= black; + if(hcount == 10'd309 && vcount == 10'd297) + pix_col <= black; + if(hcount == 10'd304 && vcount == 10'd298) + pix_col <= black; + if(hcount == 10'd310 && vcount == 10'd298) + pix_col <= black; + if(hcount == 10'd309 && vcount == 10'd299) + pix_col <= black; + if(hcount == 10'd308 && vcount == 10'd300) + pix_col <= black; + if(hcount == 10'd307 && vcount == 10'd301) + pix_col <= black; + if(hcount == 10'd306 && vcount == 10'd302) + pix_col <= black; + if(hcount == 10'd305 && vcount == 10'd303) + pix_col <= black; + if(hcount >= 10'd304 && hcount <= 10'd310 && vcount == 10'd304) + pix_col <= black; + +//3 + if(hcount >= 10'd338 && hcount <= 10'd340 && vcount == 10'd296) + pix_col <= black; + if(hcount == 10'd337 && vcount == 10'd297) + pix_col <= black; + if(hcount == 10'd341 && vcount == 10'd297) + pix_col <= black; + if(hcount == 10'd336 && vcount == 10'd298) + pix_col <= black; + if(hcount == 10'd342 && vcount == 10'd298) + pix_col <= black; + + if(hcount == 10'd342 && vcount == 10'd299) + pix_col <= black; + if(hcount == 10'd341 && vcount == 10'd300) + pix_col <= black; + + if(hcount == 10'd342 && vcount == 10'd301) + pix_col <= black; + + if(hcount == 10'd336 && vcount == 10'd302) + pix_col <= black; + if(hcount == 10'd342 && vcount == 10'd302) + pix_col <= black; + if(hcount == 10'd337 && vcount == 10'd303) + pix_col <= black; + if(hcount == 10'd341 && vcount == 10'd303) + pix_col <= black; + if(hcount >= 10'd338 && hcount <= 10'd340 && vcount == 10'd304) + pix_col <= black; + +//s + if(hcount >= 10'd387 && hcount <= 10'd389 && vcount == 10'd298) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd299) + pix_col <= black; + if(hcount == 10'd390 && vcount == 10'd299) + pix_col <= black; + if(hcount == 10'd387 && vcount == 10'd300) + pix_col <= black; + if(hcount == 10'd388 && vcount == 10'd301) + pix_col <= black; + if(hcount == 10'd389 && vcount == 10'd302) + pix_col <= black; + if(hcount == 10'd386 && vcount == 10'd303) + pix_col <= black; + if(hcount == 10'd390 && vcount == 10'd303) + pix_col <= black; + if(hcount >= 10'd387 && hcount <= 10'd389 && vcount == 10'd304) + pix_col <= black; + +//down + if(hcount == 10'd416 && vcount == 10'd296) + pix_col <= black; + if(hcount == 10'd424 && vcount == 10'd296) + pix_col <= black; + if(hcount == 10'd416 && vcount == 10'd297) + pix_col <= black; + if(hcount == 10'd424 && vcount == 10'd297) + pix_col <= black; + if(hcount == 10'd417 && vcount == 10'd298) + pix_col <= black; + if(hcount == 10'd423 && vcount == 10'd298) + pix_col <= black; + if(hcount == 10'd417 && vcount == 10'd299) + pix_col <= black; + if(hcount == 10'd423 && vcount == 10'd299) + pix_col <= black; + if(hcount == 10'd418 && vcount == 10'd300) + pix_col <= black; + if(hcount == 10'd422 && vcount == 10'd300) + pix_col <= black; + if(hcount == 10'd418 && vcount == 10'd301) + pix_col <= black; + if(hcount == 10'd422 && vcount == 10'd301) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd302) + pix_col <= black; + if(hcount == 10'd421 && vcount == 10'd302) + pix_col <= black; + if(hcount == 10'd419 && vcount == 10'd303) + pix_col <= black; + if(hcount == 10'd421 && vcount == 10'd303) + pix_col <= black; + if(hcount == 10'd420 && vcount == 10'd304) + pix_col <= black; + +// mouse buttons + if(hcount >= 10'd318 && hcount <= 10'd322 && vcount >= 10'd38 && vcount <= 10'd42) + pix_col <= mbtnR == 1'b0 ? red : lime; + if(hcount >= 10'd312 && hcount <= 10'd316 && vcount >= 10'd38 && vcount <= 10'd42) + pix_col <= mbtnM == 1'b0 ? red : blue; + if(hcount >= 10'd306 && hcount <= 10'd310 && vcount >= 10'd38 && vcount <= 10'd42) + pix_col <= mbtnL == 1'b0 ? red : yellow; +// mouse + if(hcount >= dot_x && hcount <= dot_x + 10'd4 && vcount >= dot_y && vcount <= dot_y + 10'd4) + pix_col <= mbtnL == 1'b0 ? yellow : aqua; + + end +end + +reg [7:0] tmp; +always @(posedge clk, posedge rst) begin + if(rst) + tmp <= 8'b10000000; + else begin +// if (mbtnM == 1'b1) +// mp <= my[9:0]; + if (mbtnL == 1'b1) begin + + + // key value + if(mx >= 10'd408 && mx <= 10'd432 && my >= 10'd196 && my <= 10'd208) + swrst <= 1'b1; + + if(mx >= 10'd232 && mx <= 10'd256 && my >= 10'd224 && my <= 10'd236) + swc <= 1'b1; + if(mx >= 10'd264 && mx <= 10'd288 && my >= 10'd224 && my <= 10'd236) + swd <= 1'b1; + if(mx >= 10'd296 && mx <= 10'd320 && my >= 10'd224 && my <= 10'd236) + swe <= 1'b1; + if(mx >= 10'd328 && mx <= 10'd352 && my >= 10'd224 && my <= 10'd236) + swf <= 1'b1; + if(mx >= 10'd376 && mx <= 10'd400 && my >= 10'd224 && my <= 10'd236) + swm <= 1'b1; + if(mx >= 10'd408 && mx <= 10'd432 && my >= 10'd224 && my <= 10'd236) + swl <= 1'b1; + + if(mx >= 10'd232 && mx <= 10'd256 && my >= 10'd252 && my <= 10'd264) + sw8 <= 1'b1; + if(mx >= 10'd264 && mx <= 10'd288 && my >= 10'd252 && my <= 10'd264) + sw9 <= 1'b1; + if(mx >= 10'd296 && mx <= 10'd320 && my >= 10'd252 && my <= 10'd264) + swa <= 1'b1; + if(mx >= 10'd328 && mx <= 10'd352 && my >= 10'd252 && my <= 10'd264) + swb <= 1'b1; + if(mx >= 10'd376 && mx <= 10'd400 && my >= 10'd252 && my <= 10'd264) + swg <= 1'b1; + if(mx >= 10'd408 && mx <= 10'd432 && my >= 10'd252 && my <= 10'd264) + swr <= 1'b1; + + if(mx >= 10'd232 && mx <= 10'd256 && my >= 10'd280 && my <= 10'd292) + sw4 <= 1'b1; + if(mx >= 10'd264 && mx <= 10'd288 && my >= 10'd280 && my <= 10'd292) + sw5 <= 1'b1; + if(mx >= 10'd296 && mx <= 10'd320 && my >= 10'd280 && my <= 10'd292) + sw6 <= 1'b1; + if(mx >= 10'd328 && mx <= 10'd352 && my >= 10'd280 && my <= 10'd292) + sw7 <= 1'b1; + if(mx >= 10'd376 && mx <= 10'd400 && my >= 10'd280 && my <= 10'd292) + swp <= 1'b1; + if(mx >= 10'd408 && mx <= 10'd432 && my >= 10'd280 && my <= 10'd292) + swU <= 1'b1; + + if(mx >= 10'd232 && mx <= 10'd256 && my >= 10'd308 && my <= 10'd320) + sw0 <= 1'b1; + if(mx >= 10'd264 && mx <= 10'd288 && my >= 10'd308 && my <= 10'd320) + sw1 <= 1'b1; + if(mx >= 10'd296 && mx <= 10'd320 && my >= 10'd308 && my <= 10'd320) + sw2 <= 1'b1; + if(mx >= 10'd328 && mx <= 10'd352 && my >= 10'd308 && my <= 10'd320) + sw3 <= 1'b1; + if(mx >= 10'd376 && mx <= 10'd400 && my >= 10'd308 && my <= 10'd320) + sws <= 1'b1; + if(mx >= 10'd408 && mx <= 10'd432 && my >= 10'd308 && my <= 10'd320) + swD <= 1'b1; + + + + end else begin + swrst <= 1'b0; + swc <= 1'b0; + swd <= 1'b0; + swe <= 1'b0; + swf <= 1'b0; + swm <= 1'b0; + swl <= 1'b0; + sw8 <= 1'b0; + sw9 <= 1'b0; + swa <= 1'b0; + swb <= 1'b0; + swg <= 1'b0; + swr <= 1'b0; + sw4 <= 1'b0; + sw5 <= 1'b0; + sw6 <= 1'b0; + sw7 <= 1'b0; + swp <= 1'b0; + swU <= 1'b0; + sw0 <= 1'b0; + sw1 <= 1'b0; + sw2 <= 1'b0; + sw3 <= 1'b0; + sws <= 1'b0; + swD <= 1'b0; + end + + + end +end + +// Take no notice - I change the values to suit +// without ghanging the name +// +// 24 bit colour + +wire [23:0] black = 24'h000000; +//wire [23:0] maroon = 24'hC00000; +wire [23:0] green = 24'h004000; +wire [23:0] olive = 24'h808000; +//wire [23:0] navy = 24'h000080; +//wire [23:0] purple = 24'h800080; +wire [23:0] teal = 24'h008080; +wire [23:0] silver = 24'hC0C0C0; +wire [23:0] grey = 24'h808080; +wire [23:0] red = 24'hFF0000; +wire [23:0] lime = 24'h00FF00; +wire [23:0] yellow = 24'hFFFF00; +wire [23:0] blue = 24'h0000FF; +//wire [23:0] fuchsia = 24'hFF00FF; +wire [23:0] aqua = 24'h00FFFF; +wire [23:0] white = 24'hFFFFFF; + +endmodule +