summaryrefslogtreecommitdiffstats
path: root/de1
diff options
context:
space:
mode:
authorroot <root@ka-ata-killa.ourano.james.local>2021-02-24 23:45:58 +0000
committerroot <root@ka-ata-killa.ourano.james.local>2021-02-24 23:45:58 +0000
commit1575d4f53805f177474b5bb96daebede9b2dfb73 (patch)
tree91f6819f7280088bb9344fae7dbef8c43a0a04c0 /de1
downloadbase-master.tar.gz
base-master.tar.bz2
base-master.zip
Diffstat (limited to 'de1')
-rw-r--r--de1/docs/WM8731_v4.9.pdfbin0 -> 811183 bytes
m---------de1/fpga-bbc0
-rw-r--r--de1/fpga-bbc-pq/.gitignore2
-rw-r--r--de1/fpga-bbc-pq/master/audio-16bit-48k.patch186
-rw-r--r--de1/fpga-bbc-pq/master/build-system.patch66
-rw-r--r--de1/fpga-bbc-pq/master/cpu-core-fixes.patch3881
-rw-r--r--de1/fpga-bbc-pq/master/dram-floating-pins.patch193
-rw-r--r--de1/fpga-bbc-pq/master/endstop0
-rw-r--r--de1/fpga-bbc-pq/master/fix-warnings.patch43
-rw-r--r--de1/fpga-bbc-pq/master/gitignore.patch24
-rw-r--r--de1/fpga-bbc-pq/master/keyboard-fixes.patch53
-rw-r--r--de1/fpga-bbc-pq/master/keyboard.patch787
-rw-r--r--de1/fpga-bbc-pq/master/line-endings.patch17558
-rw-r--r--de1/fpga-bbc-pq/master/missing-process-sensitivity.patch234
-rw-r--r--de1/fpga-bbc-pq/master/other-floating-pins.patch57
-rw-r--r--de1/fpga-bbc-pq/master/other.patch0
-rw-r--r--de1/fpga-bbc-pq/master/saa5050-fixes.patch13
-rw-r--r--de1/fpga-bbc-pq/master/saa5050-rom.patch472
-rw-r--r--de1/fpga-bbc-pq/master/scan-rate-converter.patch457
-rw-r--r--de1/fpga-bbc-pq/master/series16
-rw-r--r--de1/fpga-bbc-pq/master/sn76489-fixes.patch634
-rw-r--r--de1/fpga-flash-nor/Makefile63
-rw-r--r--de1/fpga-flash-nor/crc32_d8.v96
-rw-r--r--de1/fpga-flash-nor/de1flash.fit.smsg8
-rw-r--r--de1/fpga-flash-nor/de1flash.map.smsg2
-rw-r--r--de1/fpga-flash-nor/de1flash.qpf30
-rw-r--r--de1/fpga-flash-nor/de1flash.qsf348
-rw-r--r--de1/fpga-flash-nor/de1flash.tcl423
-rw-r--r--de1/fpga-flash-nor/de1flash.v893
-rw-r--r--de1/fpga-flash-nor/fl_fifo.qip4
-rw-r--r--de1/fpga-flash-nor/fl_fifo.v185
-rw-r--r--de1/fpga-flash-nor/hexled.v72
-rw-r--r--de1/fpga-flash-nor/pll.qip5
-rw-r--r--de1/fpga-flash-nor/pll.v323
-rw-r--r--de1/fpga-flash-nor/protocol.txt64
-rwxr-xr-xde1/fpga-flash-nor/quartus_wrap15
-rw-r--r--de1/fpga-flash-nor/vjtag_mega.qip6
-rw-r--r--de1/fpga-flash-nor/vjtag_mega.v181
38 files changed, 27394 insertions, 0 deletions
diff --git a/de1/docs/WM8731_v4.9.pdf b/de1/docs/WM8731_v4.9.pdf
new file mode 100644
index 0000000..83d7028
--- /dev/null
+++ b/de1/docs/WM8731_v4.9.pdf
Binary files differ
diff --git a/de1/fpga-bbc b/de1/fpga-bbc
new file mode 160000
+Subproject c2e7e51a5affdc3d58d71534199b9770a362612
diff --git a/de1/fpga-bbc-pq/.gitignore b/de1/fpga-bbc-pq/.gitignore
new file mode 100644
index 0000000..f5038c3
--- /dev/null
+++ b/de1/fpga-bbc-pq/.gitignore
@@ -0,0 +1,2 @@
+status
+*~
diff --git a/de1/fpga-bbc-pq/master/audio-16bit-48k.patch b/de1/fpga-bbc-pq/master/audio-16bit-48k.patch
new file mode 100644
index 0000000..315a9fd
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/audio-16bit-48k.patch
@@ -0,0 +1,186 @@
+diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd
+index 5cc666c..462e507 100644
+--- a/bbc_micro_de1.vhd
++++ b/bbc_micro_de1.vhd
+@@ -437,7 +437,7 @@ component sn76489_top is
+ we_n_i : in std_logic;
+ ready_o : out std_logic;
+ d_i : in std_logic_vector(0 to 7);
+- aout_o : out signed(0 to 7)
++ aout_o : out signed(0 to 15)
+ );
+
+ end component;
+@@ -445,7 +445,7 @@ end component;
+ component i2s_intf is
+ generic(
+ mclk_rate : positive := 12000000;
+- sample_rate : positive := 8000;
++ sample_rate : positive := 48000;
+ preamble : positive := 1; -- I2S
+ word_length : positive := 16
+ );
+@@ -713,7 +713,7 @@ signal keyb_break : std_logic;
+ -- Sound generator
+ signal sound_ready : std_logic;
+ signal sound_di : std_logic_vector(7 downto 0);
+-signal sound_ao : signed(7 downto 0);
++signal sound_ao : signed(15 downto 0);
+ signal pcm_inl : std_logic_vector(15 downto 0);
+ signal pcm_inr : std_logic_vector(15 downto 0);
+
+@@ -938,13 +938,13 @@ begin
+ clock, mhz4_clken,
+ reset_n, '0', sound_enable_n,
+ sound_ready, sound_di,
+- sound_ao
++ sound_ao
+ );
+ i2s : i2s_intf port map (
+ CLOCK_24(0), reset_n,
+ pcm_inl, pcm_inr,
+- std_logic_vector(sound_ao) & "00000000",
+- std_logic_vector(sound_ao) & "00000000",
++ std_logic_vector(sound_ao),
++ std_logic_vector(sound_ao),
+ AUD_XCK, AUD_DACLRCK,
+ AUD_BCLK, AUD_DACDAT, AUD_ADCDAT
+ );
+diff --git a/i2c_loader.vhd b/i2c_loader.vhd
+index 61bdd22..e0a7115 100644
+--- a/i2c_loader.vhd
++++ b/i2c_loader.vhd
+@@ -84,8 +84,8 @@ constant init_regs : regs := (
+ X"0C", X"62",
+ -- Format 16-bit I2S, no bit inversion or phase changes
+ X"0E", X"02",
+- -- Sampling control, 8 kHz USB mode (MCLK = 250fs * 6)
+- X"10", X"0D",
++ -- Sampling control, 48 kHz USB mode (MCLK = 250fs)
++ X"10", X"01",
+ -- Activate
+ X"12", X"01"
+ );
+diff --git a/i2s_intf.vhd b/i2s_intf.vhd
+index 49b6efb..dc00622 100644
+--- a/i2s_intf.vhd
++++ b/i2s_intf.vhd
+@@ -43,7 +43,7 @@ use IEEE.STD_LOGIC_UNSIGNED.ALL;
+ entity i2s_intf is
+ generic(
+ mclk_rate : positive := 12000000;
+- sample_rate : positive := 8000;
++ sample_rate : positive := 48000;
+ preamble : positive := 1; -- I2S
+ word_length : positive := 16
+ );
+diff --git a/sn76489-1.0/sn76489_attenuator.vhd b/sn76489-1.0/sn76489_attenuator.vhd
+index 444064e..a160a05 100644
+--- a/sn76489-1.0/sn76489_attenuator.vhd
++++ b/sn76489-1.0/sn76489_attenuator.vhd
+@@ -53,7 +53,7 @@ entity sn76489_attenuator is
+ port (
+ attenuation_i : in std_logic_vector(0 to 3);
+ factor_i : in signed(0 to 1);
+- product_o : out signed(0 to 7)
++ product_o : out signed(0 to 15)
+ );
+
+ end sn76489_attenuator;
+@@ -83,7 +83,7 @@ begin
+
+ type volume_t is array (natural range 0 to 15) of natural;
+ constant volume_c : volume_t :=
+- (31, 25, 20, 16, 12, 10, 8, 6, 5, 4, 3, 2, 2, 2, 1, 0);
++ ( 1905, 1514, 1202, 955, 758, 602, 479, 380, 302, 240, 191, 151, 120, 95, 76, 0);
+
+ variable attenuation_v : unsigned(attenuation_i'range);
+ variable volume_v : signed(product_o'range);
+diff --git a/sn76489-1.0/sn76489_comp_pack-p.vhd b/sn76489-1.0/sn76489_comp_pack-p.vhd
+index c5fcc90..88c5c23 100644
+--- a/sn76489-1.0/sn76489_comp_pack-p.vhd
++++ b/sn76489-1.0/sn76489_comp_pack-p.vhd
+@@ -18,7 +18,7 @@ package sn76489_comp_pack is
+ port (
+ attenuation_i : in std_logic_vector(0 to 3);
+ factor_i : in signed(0 to 1);
+- product_o : out signed(0 to 7)
++ product_o : out signed(0 to 15)
+ );
+ end component;
+
+@@ -33,7 +33,7 @@ package sn76489_comp_pack is
+ rst_a_i : in std_logic_vector(0 to 3);
+ rst_cnt_i: in std_logic_vector(0 to 9);
+ ff_o : out std_logic;
+- tone_o : out signed(0 to 7)
++ tone_o : out signed(0 to 15)
+ );
+ end component;
+
+@@ -46,7 +46,7 @@ package sn76489_comp_pack is
+ d_i : in std_logic_vector(0 to 7);
+ addr_i : in std_logic_vector(0 to 1);
+ tone3_ff_i : in std_logic;
+- noise_o : out signed(0 to 7)
++ noise_o : out signed(0 to 15)
+ );
+ end component;
+
+@@ -74,7 +74,7 @@ package sn76489_comp_pack is
+ we_n_i : in std_logic;
+ ready_o : out std_logic;
+ d_i : in std_logic_vector(0 to 7);
+- aout_o : out signed(0 to 7)
++ aout_o : out signed(0 to 15)
+ );
+ end component;
+
+diff --git a/sn76489-1.0/sn76489_noise.vhd b/sn76489-1.0/sn76489_noise.vhd
+index 035adab..a19df77 100644
+--- a/sn76489-1.0/sn76489_noise.vhd
++++ b/sn76489-1.0/sn76489_noise.vhd
+@@ -58,7 +58,7 @@ entity sn76489_noise is
+ d_i : in std_logic_vector(0 to 7);
+ addr_i : in std_logic_vector(0 to 1);
+ tone3_ff_i : in std_logic;
+- noise_o : out signed(0 to 7)
++ noise_o : out signed(0 to 15)
+ );
+
+ end sn76489_noise;
+@@ -81,7 +81,7 @@ architecture rtl of sn76489_noise is
+ shift_source_q : std_logic;
+ signal shift_rise_edge_s : boolean;
+
+- signal lfsr_q : std_logic_vector(0 to 7);
++ signal lfsr_q : std_logic_vector(0 to 15);
+
+ signal freq_s : signed(0 to 1);
+
+diff --git a/sn76489-1.0/sn76489_tone.vhd b/sn76489-1.0/sn76489_tone.vhd
+index f1b6885..4421423 100644
+--- a/sn76489-1.0/sn76489_tone.vhd
++++ b/sn76489-1.0/sn76489_tone.vhd
+@@ -60,7 +60,7 @@ entity sn76489_tone is
+ rst_a_i : in std_logic_vector(0 to 3);
+ rst_cnt_i: in std_logic_vector(0 to 9);
+ ff_o : out std_logic;
+- tone_o : out signed(0 to 7)
++ tone_o : out signed(0 to 15)
+ );
+
+ end sn76489_tone;
+diff --git a/sn76489-1.0/sn76489_top.vhd b/sn76489-1.0/sn76489_top.vhd
+index 2f6a01c..512521f 100644
+--- a/sn76489-1.0/sn76489_top.vhd
++++ b/sn76489-1.0/sn76489_top.vhd
+@@ -72,7 +72,7 @@ entity sn76489_top is
+ we_n_i : in std_logic;
+ ready_o : out std_logic;
+ d_i : in std_logic_vector(0 to 7);
+- aout_o : out signed(0 to 7)
++ aout_o : out signed(0 to 15)
+ );
+
+ end sn76489_top;
diff --git a/de1/fpga-bbc-pq/master/build-system.patch b/de1/fpga-bbc-pq/master/build-system.patch
new file mode 100644
index 0000000..7b9f40f
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/build-system.patch
@@ -0,0 +1,66 @@
+diff --git a/Makefile b/Makefile
+new file mode 100644
+index 0000000..dc728fe
+--- /dev/null
++++ b/Makefile
+@@ -0,0 +1,39 @@
++PROJ=bbc_micro_de1
++
++SRCS=$(wildcard *.vhd *.v *.qsf *.qpf T65/*.vhd sn76489-1.0/*.vhd roms roms/saa5050/saa5050.hex)
++SOF=${PROJ}.sof
++
++default: load_sof.stamp
++
++sta.stamp:asm.stamp
++ ./quartus_wrap quartus_sta ${PROJ} -c ${PROJ}
++ touch $@
++
++asm.stamp:fit.stamp
++ ./quartus_wrap quartus_asm --read_settings_files=off --write_settings_files=off ${PROJ} -c ${PROJ}
++ touch $@
++
++${SOF}:asm.stamp
++
++fit.stamp: ans.stamp
++ ./quartus_wrap quartus_fit --read_settings_files=off --write_settings_files=off ${PROJ} -c ${PROJ}
++ touch $@
++
++ans.stamp: source.stamp
++ ./quartus_wrap quartus_map --read_settings_files=on --write_settings_files=off ${PROJ} -c ${PROJ}
++ touch $@
++
++source.stamp:${SRCS}
++ touch source.stamp
++
++load_sof.stamp: ${SOF}
++ ./quartus_wrap quartus_pgm -m JTAG -o "p;${SOF}" -c 1
++ #touch $@
++
++clean:
++ /bin/rm -rf db incremental_db
++ /bin/rm -f *.stamp ${SOF} *.rpt *.html *.summary *.pin *.jdi *.qws *.pof *.done *.rom
++
++
++
++
+diff --git a/quartus_wrap b/quartus_wrap
+new file mode 100755
+index 0000000..e818413
+--- /dev/null
++++ b/quartus_wrap
+@@ -0,0 +1,15 @@
++#!/bin/bash
++
++AD=/software/apps/altera/quartus_ii_13.0sp1
++if [ $(uname -m ) == "x86_64" ]; then
++ LL=linux64
++else
++ LL=linux
++fi
++QUARTUS_ROOTDIR="${AD}/quartus"
++PATH="${AD}/quartus/bin:${AD}/quartus/sopc_builder/bin:${AD}/nios2eds/sdk2/bin:${AD}/nios2eds/bin:${AD}/nios2eds/bin/gnu/H-i686-pc-linux-gnu/bin:${PATH}"
++LD_LIBRARY_PATH="${AD}/quartus/${LL}:/software/apps/altera/libcompat/32:/software/apps/altera/libcompat/64:${LD_LIBRARY_PATH}"
++
++export LD_LIBRARY_PATH PATH QUARTUS_ROOTDIR
++
++"$@"
diff --git a/de1/fpga-bbc-pq/master/cpu-core-fixes.patch b/de1/fpga-bbc-pq/master/cpu-core-fixes.patch
new file mode 100644
index 0000000..4319a09
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/cpu-core-fixes.patch
@@ -0,0 +1,3881 @@
+diff --git a/T65/T65.vhd b/T65/T65.vhd
+index 09253fe..bea8434 100644
+--- a/T65/T65.vhd
++++ b/T65/T65.vhd
+@@ -1,7 +1,20 @@
+ -- ****
+ -- T65(b) core. In an effort to merge and maintain bug fixes ....
+ --
++-- Ver 303 ost(ML) July 2014
++-- (Sorry for some scratchpad comments that may make little sense)
++-- Mods and some 6502 undocumented instructions.
+ --
++-- Not correct opcodes acc. to Lorenz tests (incomplete list):
++-- NOPN (nop)
++-- NOPZX (nop + byte 172)
++-- NOPAX (nop + word da ... da: byte 0)
++-- ASOZ (byte $07 + byte 172)
++--
++-- Wolfgang April 2014
++-- Ver 303 Bugfixes for NMI from foft
++-- Ver 302 Bugfix for BRK command
++-- Wolfgang January 2014
+ -- Ver 301 more merging
+ -- Ver 300 Bugfixes by ehenciak added, started tidyup *bust*
+ -- MikeJ March 2005
+@@ -69,345 +82,376 @@ library IEEE;
+ -- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use
+ -- the ready signal to limit the CPU.
+ entity T65 is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
+- Res_n : in std_logic;
+- Enable : in std_logic;
+- Clk : in std_logic;
+- Rdy : in std_logic;
+- Abort_n : in std_logic;
+- IRQ_n : in std_logic;
+- NMI_n : in std_logic;
+- SO_n : in std_logic;
+- R_W_n : out std_logic;
+- Sync : out std_logic;
+- EF : out std_logic;
+- MF : out std_logic;
+- XF : out std_logic;
+- ML_n : out std_logic;
+- VP_n : out std_logic;
+- VDA : out std_logic;
+- VPA : out std_logic;
+- A : out std_logic_vector(23 downto 0);
+- DI : in std_logic_vector(7 downto 0);
+- DO : out std_logic_vector(7 downto 0)
+- );
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
++ Res_n : in std_logic;
++ Enable : in std_logic;
++ Clk : in std_logic;
++ Rdy : in std_logic;
++ Abort_n : in std_logic;
++ IRQ_n : in std_logic;
++ NMI_n : in std_logic;
++ SO_n : in std_logic;
++ R_W_n : out std_logic;
++ Sync : out std_logic;
++ EF : out std_logic;
++ MF : out std_logic;
++ XF : out std_logic;
++ ML_n : out std_logic;
++ VP_n : out std_logic;
++ VDA : out std_logic;
++ VPA : out std_logic;
++ A : out std_logic_vector(23 downto 0);
++ DI : in std_logic_vector(7 downto 0);--NOTE:Make sure DI equals DO when writing. This is important for DCP/DCM undoc instruction. TODO:convert to inout
++ DO : out std_logic_vector(7 downto 0);
++ -- 6502 registers (MSB) PC, SP, P, Y, X, A (LSB)
++ Regs : out std_logic_vector(63 downto 0)
++ );
+ end T65;
+
+ architecture rtl of T65 is
+
+- -- Registers
+- signal ABC, X, Y, D : std_logic_vector(15 downto 0);
+- signal P, AD, DL : std_logic_vector(7 downto 0) := x"00";
+- signal BAH : std_logic_vector(7 downto 0);
+- signal BAL : std_logic_vector(8 downto 0);
+- signal PBR : std_logic_vector(7 downto 0);
+- signal DBR : std_logic_vector(7 downto 0);
+- signal PC : unsigned(15 downto 0);
+- signal S : unsigned(15 downto 0);
+- signal EF_i : std_logic;
+- signal MF_i : std_logic;
+- signal XF_i : std_logic;
+-
+- signal IR : std_logic_vector(7 downto 0);
+- signal MCycle : std_logic_vector(2 downto 0);
+-
+- signal Mode_r : std_logic_vector(1 downto 0);
+- signal ALU_Op_r : std_logic_vector(3 downto 0);
+- signal Write_Data_r : std_logic_vector(2 downto 0);
+- signal Set_Addr_To_r : std_logic_vector(1 downto 0);
+- signal PCAdder : unsigned(8 downto 0);
+-
+- signal RstCycle : std_logic;
+- signal IRQCycle : std_logic;
+- signal NMICycle : std_logic;
+-
+- signal B_o : std_logic;
+- signal SO_n_o : std_logic;
+- signal IRQ_n_o : std_logic;
+- signal NMI_n_o : std_logic;
+- signal NMIAct : std_logic;
+-
+- signal Break : std_logic;
+-
+- -- ALU signals
+- signal BusA : std_logic_vector(7 downto 0);
+- signal BusA_r : std_logic_vector(7 downto 0);
+- signal BusB : std_logic_vector(7 downto 0);
+- signal ALU_Q : std_logic_vector(7 downto 0);
+- signal P_Out : std_logic_vector(7 downto 0);
+-
+- -- Micro code outputs
+- signal LCycle : std_logic_vector(2 downto 0);
+- signal ALU_Op : std_logic_vector(3 downto 0);
+- signal Set_BusA_To : std_logic_vector(2 downto 0);
+- signal Set_Addr_To : std_logic_vector(1 downto 0);
+- signal Write_Data : std_logic_vector(2 downto 0);
+- signal Jump : std_logic_vector(1 downto 0);
+- signal BAAdd : std_logic_vector(1 downto 0);
+- signal BreakAtNA : std_logic;
+- signal ADAdd : std_logic;
+- signal AddY : std_logic;
+- signal PCAdd : std_logic;
+- signal Inc_S : std_logic;
+- signal Dec_S : std_logic;
+- signal LDA : std_logic;
+- signal LDP : std_logic;
+- signal LDX : std_logic;
+- signal LDY : std_logic;
+- signal LDS : std_logic;
+- signal LDDI : std_logic;
+- signal LDALU : std_logic;
+- signal LDAD : std_logic;
+- signal LDBAL : std_logic;
+- signal LDBAH : std_logic;
+- signal SaveP : std_logic;
+- signal Write : std_logic;
+-
+- signal really_rdy : std_logic;
+- signal R_W_n_i : std_logic;
++ -- Registers
++ signal ABC, X, Y, D : std_logic_vector(15 downto 0);
++ signal P, AD, DL : std_logic_vector(7 downto 0) := x"00";
++ signal PwithB : std_logic_vector(7 downto 0);--ML:New way to push P with correct B state to stack
++ signal BAH : std_logic_vector(7 downto 0);
++ signal BAL : std_logic_vector(8 downto 0);
++ signal PBR : std_logic_vector(7 downto 0);
++ signal DBR : std_logic_vector(7 downto 0);
++ signal PC : unsigned(15 downto 0);
++ signal S : unsigned(15 downto 0);
++ signal EF_i : std_logic;
++ signal MF_i : std_logic;
++ signal XF_i : std_logic;
++
++ signal IR : std_logic_vector(7 downto 0);
++ signal MCycle : std_logic_vector(2 downto 0);
++
++ signal Mode_r : std_logic_vector(1 downto 0);
++ signal ALU_Op_r : T_ALU_Op;
++ signal Write_Data_r : T_Write_Data;
++ signal Set_Addr_To_r : T_Set_Addr_To;
++ signal PCAdder : unsigned(8 downto 0);
++
++ signal RstCycle : std_logic;
++ signal IRQCycle : std_logic;
++ signal NMICycle : std_logic;
++
++ signal SO_n_o : std_logic;
++ signal IRQ_n_o : std_logic;
++ signal NMI_n_o : std_logic;
++ signal NMIAct : std_logic;
++
++ signal Break : std_logic;
++
++ -- ALU signals
++ signal BusA : std_logic_vector(7 downto 0);
++ signal BusA_r : std_logic_vector(7 downto 0);
++ signal BusB : std_logic_vector(7 downto 0);
++ signal ALU_Q : std_logic_vector(7 downto 0);
++ signal P_Out : std_logic_vector(7 downto 0);
++
++ -- Micro code outputs
++ signal LCycle : std_logic_vector(2 downto 0);
++ signal ALU_Op : T_ALU_Op;
++ signal Set_BusA_To : T_Set_BusA_To;
++ signal Set_Addr_To : T_Set_Addr_To;
++ signal Write_Data : T_Write_Data;
++ signal Jump : std_logic_vector(1 downto 0);
++ signal BAAdd : std_logic_vector(1 downto 0);
++ signal BreakAtNA : std_logic;
++ signal ADAdd : std_logic;
++ signal AddY : std_logic;
++ signal PCAdd : std_logic;
++ signal Inc_S : std_logic;
++ signal Dec_S : std_logic;
++ signal LDA : std_logic;
++ signal LDP : std_logic;
++ signal LDX : std_logic;
++ signal LDY : std_logic;
++ signal LDS : std_logic;
++ signal LDDI : std_logic;
++ signal LDALU : std_logic;
++ signal LDAD : std_logic;
++ signal LDBAL : std_logic;
++ signal LDBAH : std_logic;
++ signal SaveP : std_logic;
++ signal Write : std_logic;
++ signal ALUmore : std_logic;
++
++ signal really_rdy : std_logic;
++ signal R_W_n_i : std_logic;
++ signal R_W_n_i_d : std_logic;
++
++ signal NMIActClear : std_logic; -- MWW hack
+
+ begin
+- -- ehenciak : gate Rdy with read/write to make an "OK, it's
+- -- really OK to stop the processor now if Rdy is
+- -- deasserted" signal
+- really_rdy <= Rdy or not(R_W_n_i);
+-
+- -- ehenciak : Drive R_W_n_i off chip.
+- R_W_n <= R_W_n_i;
+-
+- Sync <= '1' when MCycle = "000" else '0';
+- EF <= EF_i;
+- MF <= MF_i;
+- XF <= XF_i;
+- ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1';
+- VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1';
+- VDA <= '1' when Set_Addr_To_r /= "00" else '0'; -- Incorrect !!!!!!!!!!!!
+- VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!!
+-
+- mcode : T65_MCode
+- port map(
+- Mode => Mode_r,
+- IR => IR,
+- MCycle => MCycle,
+- P => P,
+- LCycle => LCycle,
+- ALU_Op => ALU_Op,
+- Set_BusA_To => Set_BusA_To,
+- Set_Addr_To => Set_Addr_To,
+- Write_Data => Write_Data,
+- Jump => Jump,
+- BAAdd => BAAdd,
+- BreakAtNA => BreakAtNA,
+- ADAdd => ADAdd,
+- AddY => AddY,
+- PCAdd => PCAdd,
+- Inc_S => Inc_S,
+- Dec_S => Dec_S,
+- LDA => LDA,
+- LDP => LDP,
+- LDX => LDX,
+- LDY => LDY,
+- LDS => LDS,
+- LDDI => LDDI,
+- LDALU => LDALU,
+- LDAD => LDAD,
+- LDBAL => LDBAL,
+- LDBAH => LDBAH,
+- SaveP => SaveP,
+- Write => Write
+- );
+-
+- alu : T65_ALU
+- port map(
+- Mode => Mode_r,
+- Op => ALU_Op_r,
+- BusA => BusA_r,
+- BusB => BusB,
+- P_In => P,
+- P_Out => P_Out,
+- Q => ALU_Q
+- );
+-
+- process (Res_n, Clk)
+- begin
+- if Res_n = '0' then
+- PC <= (others => '0'); -- Program Counter
+- IR <= "00000000";
+- S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!!
+- D <= (others => '0');
+- PBR <= (others => '0');
+- DBR <= (others => '0');
+-
+- Mode_r <= (others => '0');
+- ALU_Op_r <= "1100";
+- Write_Data_r <= "000";
+- Set_Addr_To_r <= "00";
+-
+- R_W_n_i <= '1';
+- EF_i <= '1';
+- MF_i <= '1';
+- XF_i <= '1';
+-
+- elsif Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (really_rdy = '1') then
+- R_W_n_i <= not Write or RstCycle;
+-
+- D <= (others => '1'); -- Dummy
+- PBR <= (others => '1'); -- Dummy
+- DBR <= (others => '1'); -- Dummy
+- EF_i <= '0'; -- Dummy
+- MF_i <= '0'; -- Dummy
+- XF_i <= '0'; -- Dummy
+-
+- if MCycle = "000" then
+- Mode_r <= Mode;
+-
+- if IRQCycle = '0' and NMICycle = '0' then
+- PC <= PC + 1;
+- end if;
+-
+- if IRQCycle = '1' or NMICycle = '1' then
+- IR <= "00000000";
+- else
+- IR <= DI;
+- end if;
+- end if;
+-
+- ALU_Op_r <= ALU_Op;
+- Write_Data_r <= Write_Data;
+- if Break = '1' then
+- Set_Addr_To_r <= "00";
+- else
+- Set_Addr_To_r <= Set_Addr_To;
+- end if;
+-
+- if Inc_S = '1' then
+- S <= S + 1;
+- end if;
+- if Dec_S = '1' and RstCycle = '0' then
+- S <= S - 1;
+- end if;
+- if LDS = '1' then
+- S(7 downto 0) <= unsigned(ALU_Q);
+- end if;
+-
+- if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then
+- PC <= PC + 1;
+- end if;
+- --
+- -- jump control logic
+- --
+- case Jump is
+- when "01" =>
+- PC <= PC + 1;
+-
+- when "10" =>
+- PC <= unsigned(DI & DL);
+-
+- when "11" =>
+- if PCAdder(8) = '1' then
+- if DL(7) = '0' then
+- PC(15 downto 8) <= PC(15 downto 8) + 1;
+- else
+- PC(15 downto 8) <= PC(15 downto 8) - 1;
+- end if;
+- end if;
+- PC(7 downto 0) <= PCAdder(7 downto 0);
+-
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1'
+- else "0" & PC(7 downto 0);
+-
+- process (Clk)
+- begin
+- if Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (really_rdy = '1') then
+- if MCycle = "000" then
+- if LDA = '1' then
+- ABC(7 downto 0) <= ALU_Q;
+- end if;
+- if LDX = '1' then
+- X(7 downto 0) <= ALU_Q;
+- end if;
+- if LDY = '1' then
+- Y(7 downto 0) <= ALU_Q;
+- end if;
+- if (LDA or LDX or LDY) = '1' then
+- P <= P_Out;
+- end if;
+- end if;
+- if SaveP = '1' then
+- P <= P_Out;
+- end if;
+- if LDP = '1' then
+- P <= ALU_Q;
+- end if;
+- if IR(4 downto 0) = "11000" then
+- case IR(7 downto 5) is
+- when "000" =>
+- P(Flag_C) <= '0';
+- when "001" =>
+- P(Flag_C) <= '1';
+- when "010" =>
+- P(Flag_I) <= '0';
+- when "011" =>
+- P(Flag_I) <= '1';
+- when "101" =>
+- P(Flag_V) <= '0';
+- when "110" =>
+- P(Flag_D) <= '0';
+- when "111" =>
+- P(Flag_D) <= '1';
+- when others =>
+- end case;
+- end if;
+-
+- --if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then
+- -- P(Flag_B) <= '1';
+- --end if;
+- --if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
+- -- P(Flag_I) <= '1';
+- -- P(Flag_B) <= B_o;
+- --end if;
+-
+- -- B=1 always on the 6502
+- P(Flag_B) <= '1';
+- if IR = "00000000" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
+- if MCycle = "011" then
+- -- B=0 in *copy* of P pushed onto the stack
+- P(Flag_B) <= '0';
+- elsif MCycle = "100" then
+- P(Flag_I) <= '1';
++ -- workaround for ready-handling
++ -- ehenciak : Drive R_W_n_i off chip.
++ R_W_n <= R_W_n_i;
++
++ -- ehenciak : gate Rdy with read/write to make an "OK, it's
++ -- really OK to stop the processor now if Rdy is
++ -- deasserted" signal
++ really_rdy <= Rdy or not(R_W_n_i);
++ ----
++
++ Sync <= '1' when MCycle = "000" else '0';
++ EF <= EF_i;
++ MF <= MF_i;
++ XF <= XF_i;
++ ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1';
++ VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1';
++ VDA <= '1' when Set_Addr_To_r /= Set_Addr_To_PBR else '0'; -- Incorrect !!!!!!!!!!!!
++ VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!!
++
++ Regs <= std_logic_vector(PC) & std_logic_vector(S)& P & Y(7 downto 0) & X(7 downto 0) & ABC(7 downto 0);
++
++ mcode : T65_MCode
++ port map(
++--inputs
++ Mode => Mode_r,
++ IR => IR,
++ MCycle => MCycle,
++ P => P,
++--outputs
++ LCycle => LCycle,
++ ALU_Op => ALU_Op,
++ Set_BusA_To => Set_BusA_To,
++ Set_Addr_To => Set_Addr_To,
++ Write_Data => Write_Data,
++ Jump => Jump,
++ BAAdd => BAAdd,
++ BreakAtNA => BreakAtNA,
++ ADAdd => ADAdd,
++ AddY => AddY,
++ PCAdd => PCAdd,
++ Inc_S => Inc_S,
++ Dec_S => Dec_S,
++ LDA => LDA,
++ LDP => LDP,
++ LDX => LDX,
++ LDY => LDY,
++ LDS => LDS,
++ LDDI => LDDI,
++ LDALU => LDALU,
++ LDAD => LDAD,
++ LDBAL => LDBAL,
++ LDBAH => LDBAH,
++ SaveP => SaveP,
++ ALUmore => ALUmore,
++ Write => Write
++ );
++
++ alu : T65_ALU
++ port map(
++ Mode => Mode_r,
++ Op => ALU_Op_r,
++ BusA => BusA_r,
++ BusB => BusB,
++ P_In => P,
++ P_Out => P_Out,
++ Q => ALU_Q
++ );
++
++
++ process (Res_n, Clk)
++ begin
++ if Res_n = '0' then
++ PC <= (others => '0'); -- Program Counter
++ IR <= "00000000";
++ S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!!
++ D <= (others => '0');
++ PBR <= (others => '0');
++ DBR <= (others => '0');
++
++ Mode_r <= (others => '0');
++ ALU_Op_r <= ALU_OP_BIT;
++ Write_Data_r <= Write_Data_DL;
++ Set_Addr_To_r <= Set_Addr_To_PBR;
++
++ R_W_n_i <= '1';
++ EF_i <= '1';
++ MF_i <= '1';
++ XF_i <= '1';
++
++ elsif Clk'event and Clk = '1' then
++ if (Enable = '1') then
++ if (really_rdy = '1') then
++ R_W_n_i <= not Write or RstCycle;
++
++ D <= (others => '1'); -- Dummy
++ PBR <= (others => '1'); -- Dummy
++ DBR <= (others => '1'); -- Dummy
++ EF_i <= '0'; -- Dummy
++ MF_i <= '0'; -- Dummy
++ XF_i <= '0'; -- Dummy
++
++ if MCycle = "000" then
++ Mode_r <= Mode;
++
++ if IRQCycle = '0' and NMICycle = '0' then
++ PC <= PC + 1;
++ end if;
++
++ if IRQCycle = '1' or NMICycle = '1' then
++ IR <= "00000000";
++ else
++ IR <= DI;
++ end if;
++ end if;
++
++ ALU_Op_r <= ALU_Op;
++ Write_Data_r <= Write_Data;
++ if Break = '1' then
++ Set_Addr_To_r <= Set_Addr_To_PBR;
++ else
++ Set_Addr_To_r <= Set_Addr_To;
++ end if;
++
++ if Inc_S = '1' then
++ S <= S + 1;
++ end if;
++ if Dec_S = '1' and RstCycle = '0' then
++ S <= S - 1;
++ end if;
++ if LDS = '1' then
++ S(7 downto 0) <= unsigned(ALU_Q);
++ end if;
++
++ if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then
++ PC <= PC + 1;
+ end if;
+- end if;
+-
+- if SO_n_o = '1' and SO_n = '0' then
+- P(Flag_V) <= '1';
+- end if;
+- if RstCycle = '1' and Mode_r /= "00" then
+- P(Flag_1) <= '1';
+- P(Flag_D) <= '0';
+- P(Flag_I) <= '1';
+- end if;
+- P(Flag_1) <= '1';
+-
+- B_o <= P(Flag_B);
+- SO_n_o <= SO_n;
+- IRQ_n_o <= IRQ_n;
+- NMI_n_o <= NMI_n;
+- end if;
+- end if;
+- end if;
+- end process;
++ --
++ -- jump control logic
++ --
++ case Jump is
++ when "01" =>
++ PC <= PC + 1;
++
++ when "10" =>
++ PC <= unsigned(DI & DL);
++
++ when "11" =>
++ if PCAdder(8) = '1' then
++ if DL(7) = '0' then
++ PC(15 downto 8) <= PC(15 downto 8) + 1;
++ else
++ PC(15 downto 8) <= PC(15 downto 8) - 1;
++ end if;
++ end if;
++ PC(7 downto 0) <= PCAdder(7 downto 0);
++
++ when others => null;
++ end case;
++ end if;
++ end if;
++ end if;
++ end process;
++
++ PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1'
++ else "0" & PC(7 downto 0);
++
++ process (Res_n, Clk)
++ variable tmpP:std_logic_vector(7 downto 0);--ML:Lets try to handle loading P at mcycle=0 and set/clk flags at same cycle
++ begin
++ if Res_n = '0' then
++ P <= x"00"; -- ensure we have nothing set on reset (e.g. B flag!)
++ elsif Clk'event and Clk = '1' then
++ tmpP:=P;
++ if (Enable = '1') then
++ if (really_rdy = '1') then
++ if MCycle = "000" then
++ if LDA = '1' then
++ ABC(7 downto 0) <= ALU_Q;
++ end if;
++ if LDX = '1' then
++ X(7 downto 0) <= ALU_Q;
++ end if;
++ if LDY = '1' then
++ Y(7 downto 0) <= ALU_Q;
++ end if;
++ if (LDA or LDX or LDY) = '1' then
++-- P <= P_Out;-- Replaced with:
++ tmpP:=P_Out;
++ end if;
++ end if;
++ if SaveP = '1' then
++-- P <= P_Out;-- Replaced with:
++ tmpP:=P_Out;
++ end if;
++ if LDP = '1' then
++-- P <= ALU_Q;-- Replaced with: --ML:no need anymore: AND x"EF"; -- NEVER set B on RTI and PLP
++ tmpP:=ALU_Q;
++ end if;
++ if IR(4 downto 0) = "11000" then
++ case IR(7 downto 5) is
++ when "000" =>--0x18(clc)
++-- P(Flag_C) <= '0';-- Replaced with:
++ tmpP(Flag_C) := '0';
++ when "001" =>--0x38(sec)
++-- P(Flag_C) <= '1';
++ tmpP(Flag_C) := '1';
++ when "010" =>--0x58(cli)
++-- P(Flag_I) <= '0';
++ tmpP(Flag_I) := '0';
++ when "011" =>--0x78(sei)
++-- P(Flag_I) <= '1';
++ tmpP(Flag_I) := '1';
++ when "101" =>--0xb8(clv)
++-- P(Flag_V) <= '0';
++ tmpP(Flag_V) := '0';
++ when "110" =>--0xd8(cld)
++-- P(Flag_D) <= '0';
++ tmpP(Flag_D) := '0';
++ when "111" =>--0xf8(sed)
++-- P(Flag_D) <= '1';
++ tmpP(Flag_D) := '1';
++ when others =>
++ end case;
++ end if;
++ --ML:Removed change of B flag, its constant '1' in P
++ --ML:The B flag appears to be locked to '1', but when pushed to stack, the SR data on the stack has the B flag cleared on interrupts, set on BRK instr.
++ --ML:The state of the B flag on warm reset apparently is unchanged (not confirmed, please do if you know)
++ --ML:The state of the B flag on cold reset is uncertain, but my guess would be set, unless it can be used to detect cold from warm reset.
++ --Since we cant (well, won't) simulate B=0 on cold reset, we just behave as if it was constant 1.
++-- P(Flag_B) <= '1';
++ tmpP(Flag_B) := '1';
++-- if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then -- BRK
++-- P(Flag_B) <= '1';
++-- elsif IR = "00001000" then -- PHP
++-- P(Flag_B) <= '1';
++-- else
++-- P(Flag_B) <= '0'; --> not the best way, but we keep B zero except for BRK and PHP opcodes
++-- end if;
++ if IR = "00000000" and MCycle = "100" and RstCycle = '0' then --and (NMICycle = '1' or IRQCycle = '1') then
++ --This should happen after P has been pushed to stack
++-- P(Flag_I) <= '1';
++ tmpP(Flag_I) := '1';
++ end if;
++ if SO_n_o = '1' and SO_n = '0' then
++-- P(Flag_V) <= '1';
++ tmpP(Flag_V) := '1';
++ end if;
++ if RstCycle = '1' then
++-- P(Flag_I) <= '0';
++-- P(Flag_D) <= '0';
++ tmpP(Flag_I) := '1';
++ tmpP(Flag_D) := '0';
++ end if;
++-- P(Flag_1) <= '1';
++ tmpP(Flag_1) := '1';
++
++ P<=tmpP;--new way
++
++ SO_n_o <= SO_n;
++ IRQ_n_o <= IRQ_n;
++ end if;
++ NMI_n_o <= NMI_n; -- MWW: detect nmi even if not rdy
++ end if;
++ end if;
++ end process;
+
+ ---------------------------------------------------------------------------
+ --
+@@ -415,109 +459,125 @@ begin
+ --
+ ---------------------------------------------------------------------------
+
+- process (Res_n, Clk)
+- begin
+- if Res_n = '0' then
+- BusA_r <= (others => '0');
+- BusB <= (others => '0');
+- AD <= (others => '0');
+- BAL <= (others => '0');
+- BAH <= (others => '0');
+- DL <= (others => '0');
+- elsif Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (Rdy = '1') then
+- BusA_r <= BusA;
+- BusB <= DI;
+-
+- case BAAdd is
+- when "01" =>
+- -- BA Inc
+- AD <= std_logic_vector(unsigned(AD) + 1);
+- BAL <= std_logic_vector(unsigned(BAL) + 1);
+- when "10" =>
+- -- BA Add
+- BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9));
+- when "11" =>
+- -- BA Adj
+- if BAL(8) = '1' then
+- BAH <= std_logic_vector(unsigned(BAH) + 1);
+- end if;
+- when others =>
+- end case;
+-
+- -- ehenciak : modified to use Y register as well (bugfix)
+- if ADAdd = '1' then
+- if (AddY = '1') then
+- AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0)));
+- else
+- AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0)));
+- end if;
+- end if;
+-
+- if IR = "00000000" then
+- BAL <= (others => '1');
+- BAH <= (others => '1');
+- if RstCycle = '1' then
+- BAL(2 downto 0) <= "100";
+- elsif NMICycle = '1' then
+- BAL(2 downto 0) <= "010";
+- else
+- BAL(2 downto 0) <= "110";
+- end if;
+- if Set_addr_To_r = "11" then
+- BAL(0) <= '1';
+- end if;
+- end if;
+-
+-
+- if LDDI = '1' then
+- DL <= DI;
+- end if;
+- if LDALU = '1' then
+- DL <= ALU_Q;
+- end if;
+- if LDAD = '1' then
+- AD <= DI;
+- end if;
+- if LDBAL = '1' then
+- BAL(7 downto 0) <= DI;
+- end if;
+- if LDBAH = '1' then
+- BAH <= DI;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8));
+-
+-
+- with Set_BusA_To select
+- BusA <= DI when "000",
+- ABC(7 downto 0) when "001",
+- X(7 downto 0) when "010",
+- Y(7 downto 0) when "011",
+- std_logic_vector(S(7 downto 0)) when "100",
+- P when "101",
+- (others => '-') when others;
+-
+- with Set_Addr_To_r select
+- A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01",
+- DBR & "00000000" & AD when "10",
+- "00000000" & BAH & BAL(7 downto 0) when "11",
+- PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others;
+-
+- with Write_Data_r select
+- DO <= DL when "000",
+- ABC(7 downto 0) when "001",
+- X(7 downto 0) when "010",
+- Y(7 downto 0) when "011",
+- std_logic_vector(S(7 downto 0)) when "100",
+- P when "101",
+- std_logic_vector(PC(7 downto 0)) when "110",
+- std_logic_vector(PC(15 downto 8)) when others;
++ process (Res_n, Clk)
++ begin
++ if Res_n = '0' then
++ BusA_r <= (others => '0');
++ BusB <= (others => '0');
++ AD <= (others => '0');
++ BAL <= (others => '0');
++ BAH <= (others => '0');
++ DL <= (others => '0');
++ elsif Clk'event and Clk = '1' then
++ if (Enable = '1') then
++ if (really_rdy = '1') then
++ --if (Rdy = '1') then
++ BusA_r <= BusA;
++ if ALUmore='1' then
++ BusB <= ALU_Q;
++ else
++ BusB <= DI;
++ end if;
++
++ case BAAdd is
++ when "01" =>
++ -- BA Inc
++ AD <= std_logic_vector(unsigned(AD) + 1);
++ BAL <= std_logic_vector(unsigned(BAL) + 1);
++ when "10" =>
++ -- BA Add
++ BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9));
++ when "11" =>
++ -- BA Adj
++ if BAL(8) = '1' then
++ BAH <= std_logic_vector(unsigned(BAH) + 1);
++ end if;
++ when others =>
++ end case;
++
++ -- ehenciak : modified to use Y register as well (bugfix)
++ if ADAdd = '1' then
++ if (AddY = '1') then
++ AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0)));
++ else
++ AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0)));
++ end if;
++ end if;
++
++ NMIActClear <= '0';
++ if IR = "00000000" then
++ BAL <= (others => '1');
++ BAH <= (others => '1');
++ if RstCycle = '1' then
++ BAL(2 downto 0) <= "100";
++ elsif NMICycle = '1' then
++ BAL(2 downto 0) <= "010";
++ elsif NMIAct = '1' then -- MWW, force this to be changed by NMI, even if in midstream IRQ/brk
++ BAL(2 downto 0) <= "010";
++ NMIActClear <= '1';
++ else
++ BAL(2 downto 0) <= "110";
++ end if;
++ if Set_addr_To_r = Set_Addr_To_BA then
++ BAL(0) <= '1';
++ end if;
++ end if;
++
++
++ if LDDI = '1' then
++ DL <= DI;
++ end if;
++ if LDALU = '1' then
++ DL <= ALU_Q;
++ end if;
++ if LDAD = '1' then
++ AD <= DI;
++ end if;
++ if LDBAL = '1' then
++ BAL(7 downto 0) <= DI;
++ end if;
++ if LDBAH = '1' then
++ BAH <= DI;
++ end if;
++ end if;
++ end if;
++ end if;
++ end process;
++
++ Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8));
++
++ with Set_BusA_To select
++ BusA <=
++ DI when Set_BusA_To_DI,
++ ABC(7 downto 0) when Set_BusA_To_ABC,
++ X(7 downto 0) when Set_BusA_To_X,
++ Y(7 downto 0) when Set_BusA_To_Y,
++ std_logic_vector(S(7 downto 0)) when Set_BusA_To_S,
++ P when Set_BusA_To_P,
++ (others => '-') when Set_BusA_To_DONTCARE;--Can probably remove this
++
++ with Set_Addr_To_r select
++ A <=
++ "0000000000000001" & std_logic_vector(S(7 downto 0)) when Set_Addr_To_S,
++ DBR & "00000000" & AD when Set_Addr_To_AD,
++ "00000000" & BAH & BAL(7 downto 0) when Set_Addr_To_BA,
++ PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when Set_Addr_To_PBR;
++
++ --ML:This is the P that gets pushed on stack with correct B flag. I'm not sure if NMI also clears B, but I guess it does.
++ PwithB<=(P and x"ef") when (IRQCycle='1' or NMICycle='1') else P;
++
++ with Write_Data_r select
++ DO <=
++ DL when Write_Data_DL,
++ ABC(7 downto 0) when Write_Data_ABC,
++ X(7 downto 0) when Write_Data_X,
++ Y(7 downto 0) when Write_Data_Y,
++ std_logic_vector(S(7 downto 0)) when Write_Data_S,
++ PwithB when Write_Data_P,
++ std_logic_vector(PC(7 downto 0)) when Write_Data_PCL,
++ std_logic_vector(PC(15 downto 8)) when Write_Data_PCH,
++ (others=>'-') when Write_Data_DONTCARE;--Can probably remove this
++
+
+ -------------------------------------------------------------------------
+ --
+@@ -525,40 +585,44 @@ begin
+ --
+ -------------------------------------------------------------------------
+
+- process (Res_n, Clk)
+- begin
+- if Res_n = '0' then
+- MCycle <= "001";
+- RstCycle <= '1';
+- IRQCycle <= '0';
+- NMICycle <= '0';
+- NMIAct <= '0';
+- elsif Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (really_rdy = '1') then
+- if MCycle = LCycle or Break = '1' then
+- MCycle <= "000";
+- RstCycle <= '0';
+- IRQCycle <= '0';
+- NMICycle <= '0';
+- if NMIAct = '1' then
+- NMICycle <= '1';
+- elsif IRQ_n_o = '0' and P(Flag_I) = '0' then
+- IRQCycle <= '1';
+- end if;
+- else
+- MCycle <= std_logic_vector(unsigned(MCycle) + 1);
+- end if;
+-
+- if NMICycle = '1' then
+- NMIAct <= '0';
+- end if;
+- if NMI_n_o = '1' and NMI_n = '0' then
+- NMIAct <= '1';
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
++ process (Res_n, Clk)
++ begin
++ if Res_n = '0' then
++ MCycle <= "001";
++ RstCycle <= '1';
++ IRQCycle <= '0';
++ NMICycle <= '0';
++ NMIAct <= '0';
++ elsif Clk'event and Clk = '1' then
++ if (Enable = '1') then
++ if (really_rdy = '1') then
++ if (NMIActClear = '1') then
++ NMIAct <= '0';
++ end if;
++
++ if MCycle = LCycle or Break = '1' then
++ MCycle <= "000";
++ RstCycle <= '0';
++ IRQCycle <= '0';
++ NMICycle <= '0';
++ if NMIAct = '1' then
++ NMICycle <= '1';
++ elsif IRQ_n_o = '0' and P(Flag_I) = '0' then
++ IRQCycle <= '1';
++ end if;
++ else
++ MCycle <= std_logic_vector(unsigned(MCycle) + 1);
++ end if;
++
++ if NMICycle = '1' then
++ NMIAct <= '0';
++ end if;
++ end if;
++ if NMI_n_o = '1' and NMI_n = '0' then -- MWW: detect nmi even if not rdy
++ NMIAct <= '1';
++ end if;
++ end if;
++ end if;
++ end process;
+
+ end;
+diff --git a/T65/T65_ALU.vhd b/T65/T65_ALU.vhd
+index b1f6d63..49ae4a1 100644
+--- a/T65/T65_ALU.vhd
++++ b/T65/T65_ALU.vhd
+@@ -2,6 +2,8 @@
+ -- T65(b) core. In an effort to merge and maintain bug fixes ....
+ --
+ --
++-- Ver 303 ost(ML) July 2014
++-- ALU opcodes to vhdl types
+ -- Ver 300 Bugfixes by ehenciak added
+ -- MikeJ March 2005
+ -- Latest version from www.fpgaarcade.com (original www.opencores.org)
+@@ -62,199 +64,201 @@ use IEEE.numeric_std.all;
+ use work.T65_Pack.all;
+
+ entity T65_ALU is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+- Op : in std_logic_vector(3 downto 0);
+- BusA : in std_logic_vector(7 downto 0);
+- BusB : in std_logic_vector(7 downto 0);
+- P_In : in std_logic_vector(7 downto 0);
+- P_Out : out std_logic_vector(7 downto 0);
+- Q : out std_logic_vector(7 downto 0)
+- );
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
++ Op : in T_ALU_OP;
++ BusA : in std_logic_vector(7 downto 0);
++ BusB : in std_logic_vector(7 downto 0);
++ P_In : in std_logic_vector(7 downto 0);
++ P_Out : out std_logic_vector(7 downto 0);
++ Q : out std_logic_vector(7 downto 0)
++ );
+ end T65_ALU;
+
+ architecture rtl of T65_ALU is
+
+- -- AddSub variables (temporary signals)
+- signal ADC_Z : std_logic;
+- signal ADC_C : std_logic;
+- signal ADC_V : std_logic;
+- signal ADC_N : std_logic;
+- signal ADC_Q : std_logic_vector(7 downto 0);
+- signal SBC_Z : std_logic;
+- signal SBC_C : std_logic;
+- signal SBC_V : std_logic;
+- signal SBC_N : std_logic;
+- signal SBC_Q : std_logic_vector(7 downto 0);
++ -- AddSub variables (temporary signals)
++ signal ADC_Z : std_logic;
++ signal ADC_C : std_logic;
++ signal ADC_V : std_logic;
++ signal ADC_N : std_logic;
++ signal ADC_Q : std_logic_vector(7 downto 0);
++ signal SBC_Z : std_logic;
++ signal SBC_C : std_logic;
++ signal SBC_V : std_logic;
++ signal SBC_N : std_logic;
++ signal SBC_Q : std_logic_vector(7 downto 0);
+
+ begin
+
+- process (P_In, BusA, BusB)
+- variable AL : unsigned(6 downto 0);
+- variable AH : unsigned(6 downto 0);
+- variable C : std_logic;
+- begin
+- AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7);
+- AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
++ process (P_In, BusA, BusB)
++ variable AL : unsigned(6 downto 0);
++ variable AH : unsigned(6 downto 0);
++ variable C : std_logic;
++ begin
++ AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7);
++ AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
+
+ -- pragma translate_off
+- if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
+- if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
++ if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
++ if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
+ -- pragma translate_on
+
+- if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
+- ADC_Z <= '1';
+- else
+- ADC_Z <= '0';
+- end if;
++ if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
++ ADC_Z <= '1';
++ else
++ ADC_Z <= '0';
++ end if;
+
+- if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then
+- AL(6 downto 1) := AL(6 downto 1) + 6;
+- end if;
++ if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then
++ AL(6 downto 1) := AL(6 downto 1) + 6;
++ end if;
+
+- C := AL(6) or AL(5);
+- AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
++ C := AL(6) or AL(5);
++ AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
+
+- ADC_N <= AH(4);
+- ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7));
++ ADC_N <= AH(4);
++ ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7));
+
+ -- pragma translate_off
+- if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
++ if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
+ -- pragma translate_on
+
+- if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then
+- AH(6 downto 1) := AH(6 downto 1) + 6;
+- end if;
++ if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then
++ AH(6 downto 1) := AH(6 downto 1) + 6;
++ end if;
+
+- ADC_C <= AH(6) or AH(5);
++ ADC_C <= AH(6) or AH(5);
+
+- ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
+- end process;
++ ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
++ end process;
+
+- process (Op, P_In, BusA, BusB)
+- variable AL : unsigned(6 downto 0);
+- variable AH : unsigned(5 downto 0);
+- variable C : std_logic;
+- begin
+- C := P_In(Flag_C) or not Op(0);
+- AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6);
+- AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6);
++ process (Op, P_In, BusA, BusB)
++ variable AL : unsigned(6 downto 0);
++ variable AH : unsigned(5 downto 0);
++ variable C : std_logic;
++ variable CT : std_logic;
++ begin
++ CT:='0';
++ if( Op=ALU_OP_AND or --"0001" These OpCodes used to have LSB set
++ Op=ALU_OP_ADC or --"0011"
++ Op=ALU_OP_EQ2 or --"0101"
++ Op=ALU_OP_SBC or --"0111"
++ Op=ALU_OP_ROL or --"1001"
++ Op=ALU_OP_ROR or --"1011"
++ Op=ALU_OP_EQ3 or --"1101"
++ Op=ALU_OP_INC --"1111"
++ ) then
++ CT:='1';
++ end if;
++
++ C := P_In(Flag_C) or not CT;--was: or not Op(0);
++ AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6);
++ AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6);
+
+ -- pragma translate_off
+- if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
+- if is_x(std_logic_vector(AH)) then AH := "000000"; end if;
++ if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
++ if is_x(std_logic_vector(AH)) then AH := "000000"; end if;
+ -- pragma translate_on
+
+- if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
+- SBC_Z <= '1';
+- else
+- SBC_Z <= '0';
+- end if;
++ if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
++ SBC_Z <= '1';
++ else
++ SBC_Z <= '0';
++ end if;
+
+- SBC_C <= not AH(5);
+- SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7));
+- SBC_N <= AH(4);
++ SBC_C <= not AH(5);
++ SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7));
++ SBC_N <= AH(4);
+
+- if P_In(Flag_D) = '1' then
+- if AL(5) = '1' then
+- AL(5 downto 1) := AL(5 downto 1) - 6;
+- end if;
+- AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6);
+- if AH(5) = '1' then
+- AH(5 downto 1) := AH(5 downto 1) - 6;
+- end if;
+- end if;
++ if P_In(Flag_D) = '1' then
++ if AL(5) = '1' then
++ AL(5 downto 1) := AL(5 downto 1) - 6;
++ end if;
++ AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6);
++ if AH(5) = '1' then
++ AH(5 downto 1) := AH(5 downto 1) - 6;
++ end if;
++ end if;
+
+- SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
+- end process;
++ SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
++ end process;
+
+- process (Op, P_In, BusA, BusB,
+- ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q,
+- SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q)
+- variable Q_t : std_logic_vector(7 downto 0);
+- begin
+- -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
+- -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
+- P_Out <= P_In;
+- Q_t := BusA;
+- case Op(3 downto 0) is
+- when "0000" =>
+- -- ORA
+- Q_t := BusA or BusB;
+- when "0001" =>
+- -- AND
+- Q_t := BusA and BusB;
+- when "0010" =>
+- -- EOR
+- Q_t := BusA xor BusB;
+- when "0011" =>
+- -- ADC
+- P_Out(Flag_V) <= ADC_V;
+- P_Out(Flag_C) <= ADC_C;
+- Q_t := ADC_Q;
+- when "0101" | "1101" =>
+- -- LDA
+- when "0110" =>
+- -- CMP
+- P_Out(Flag_C) <= SBC_C;
+- when "0111" =>
+- -- SBC
+- P_Out(Flag_V) <= SBC_V;
+- P_Out(Flag_C) <= SBC_C;
+- Q_t := SBC_Q;
+- when "1000" =>
+- -- ASL
+- Q_t := BusA(6 downto 0) & "0";
+- P_Out(Flag_C) <= BusA(7);
+- when "1001" =>
+- -- ROL
+- Q_t := BusA(6 downto 0) & P_In(Flag_C);
+- P_Out(Flag_C) <= BusA(7);
+- when "1010" =>
+- -- LSR
+- Q_t := "0" & BusA(7 downto 1);
+- P_Out(Flag_C) <= BusA(0);
+- when "1011" =>
+- -- ROR
+- Q_t := P_In(Flag_C) & BusA(7 downto 1);
+- P_Out(Flag_C) <= BusA(0);
+- when "1100" =>
+- -- BIT
+- P_Out(Flag_V) <= BusB(6);
+- when "1110" =>
+- -- DEC
+- Q_t := std_logic_vector(unsigned(BusA) - 1);
+- when "1111" =>
+- -- INC
+- Q_t := std_logic_vector(unsigned(BusA) + 1);
+- when others =>
+- end case;
++ process (Op, P_In, BusA, BusB,
++ ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q,
++ SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q)
++ variable Q_t : std_logic_vector(7 downto 0);
++ begin
++ -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
++ -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
++ P_Out <= P_In;
++ Q_t := BusA;
++ case Op is
++ when ALU_OP_OR=>
++ Q_t := BusA or BusB;
++ when ALU_OP_AND=>
++ Q_t := BusA and BusB;
++ when ALU_OP_EOR=>
++ Q_t := BusA xor BusB;
++ when ALU_OP_ADC=>
++ P_Out(Flag_V) <= ADC_V;
++ P_Out(Flag_C) <= ADC_C;
++ Q_t := ADC_Q;
++ when ALU_OP_EQ2|ALU_OP_EQ3=>
++ -- LDA
++ when ALU_OP_CMP=>
++ P_Out(Flag_C) <= SBC_C;
++ when ALU_OP_SBC=>
++ P_Out(Flag_V) <= SBC_V;
++ P_Out(Flag_C) <= SBC_C;
++ Q_t := SBC_Q;
++ when ALU_OP_ASL=>
++ Q_t := BusA(6 downto 0) & "0";
++ P_Out(Flag_C) <= BusA(7);
++ when ALU_OP_ROL=>
++ Q_t := BusA(6 downto 0) & P_In(Flag_C);
++ P_Out(Flag_C) <= BusA(7);
++ when ALU_OP_LSR=>
++ Q_t := "0" & BusA(7 downto 1);
++ P_Out(Flag_C) <= BusA(0);
++ when ALU_OP_ROR=>
++ Q_t := P_In(Flag_C) & BusA(7 downto 1);
++ P_Out(Flag_C) <= BusA(0);
++ when ALU_OP_BIT=>
++ P_Out(Flag_V) <= BusB(6);
++ when ALU_OP_DEC=>
++ Q_t := std_logic_vector(unsigned(BusA) - 1);
++ when ALU_OP_INC=>
++ Q_t := std_logic_vector(unsigned(BusA) + 1);
++ when others =>
++ --EQ1,EQ2,EQ3 passes BusA to Q_t
++ end case;
+
+- case Op(3 downto 0) is
+- when "0011" =>
+- P_Out(Flag_N) <= ADC_N;
+- P_Out(Flag_Z) <= ADC_Z;
+- when "0110" | "0111" =>
+- P_Out(Flag_N) <= SBC_N;
+- P_Out(Flag_Z) <= SBC_Z;
+- when "0100" =>
+- when "1100" =>
+- P_Out(Flag_N) <= BusB(7);
+- if (BusA and BusB) = "00000000" then
+- P_Out(Flag_Z) <= '1';
+- else
+- P_Out(Flag_Z) <= '0';
+- end if;
+- when others =>
+- P_Out(Flag_N) <= Q_t(7);
+- if Q_t = "00000000" then
+- P_Out(Flag_Z) <= '1';
+- else
+- P_Out(Flag_Z) <= '0';
+- end if;
+- end case;
++ case Op is
++ when ALU_OP_ADC=>
++ P_Out(Flag_N) <= ADC_N;
++ P_Out(Flag_Z) <= ADC_Z;
++ when ALU_OP_CMP|ALU_OP_SBC=>
++ P_Out(Flag_N) <= SBC_N;
++ P_Out(Flag_Z) <= SBC_Z;
++ when ALU_OP_EQ1=>
++ when ALU_OP_BIT=>
++ P_Out(Flag_N) <= BusB(7);
++ if (BusA and BusB) = "00000000" then
++ P_Out(Flag_Z) <= '1';
++ else
++ P_Out(Flag_Z) <= '0';
++ end if;
++ when others =>
++ P_Out(Flag_N) <= Q_t(7);
++ if Q_t = "00000000" then
++ P_Out(Flag_Z) <= '1';
++ else
++ P_Out(Flag_Z) <= '0';
++ end if;
++ end case;
+
+- Q <= Q_t;
+- end process;
++ Q <= Q_t;
++ end process;
+
+ end;
+diff --git a/T65/T65_MCode.vhd b/T65/T65_MCode.vhd
+index 6c6c864..bfc4005 100644
+--- a/T65/T65_MCode.vhd
++++ b/T65/T65_MCode.vhd
+@@ -2,9 +2,17 @@
+ -- T65(b) core. In an effort to merge and maintain bug fixes ....
+ --
+ --
++-- Ver 303 ost(ML) July 2014
++-- (Sorry for some scratchpad comments that may make little sense)
++-- Mods and some 6502 undocumented instructions.
++-- Undoc opcodes learnt from:
++-- "Extra Instructions Of The 65XX Series CPU"
++-- By: Adam Vardy (abe0084@infonet.st-johns.nf.ca)
++-- [File created: 22, Aug. 1995... 27, Sept. 1996]
+ -- Ver 302 minor timing fixes
+ -- Ver 301 Jump timing fixed
+ -- Ver 300 Bugfixes by ehenciak added
++-- Wolfgang January 2014
+ -- MikeJ March 2005
+ -- Latest version from www.fpgaarcade.com (original www.opencores.org)
+ --
+@@ -65,988 +73,1324 @@
+ library IEEE;
+ use IEEE.std_logic_1164.all;
+ use IEEE.numeric_std.all;
++use ieee.std_logic_unsigned.all;
+ use work.T65_Pack.all;
+
+ entity T65_MCode is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+- IR : in std_logic_vector(7 downto 0);
+- MCycle : in std_logic_vector(2 downto 0);
+- P : in std_logic_vector(7 downto 0);
+- LCycle : out std_logic_vector(2 downto 0);
+- ALU_Op : out std_logic_vector(3 downto 0);
+- Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
+- Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
+- Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
+- Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
+- BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
+- BreakAtNA : out std_logic;
+- ADAdd : out std_logic;
+- AddY : out std_logic;
+- PCAdd : out std_logic;
+- Inc_S : out std_logic;
+- Dec_S : out std_logic;
+- LDA : out std_logic;
+- LDP : out std_logic;
+- LDX : out std_logic;
+- LDY : out std_logic;
+- LDS : out std_logic;
+- LDDI : out std_logic;
+- LDALU : out std_logic;
+- LDAD : out std_logic;
+- LDBAL : out std_logic;
+- LDBAH : out std_logic;
+- SaveP : out std_logic;
+- Write : out std_logic
+- );
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
++ IR : in std_logic_vector(7 downto 0);
++ MCycle : in std_logic_vector(2 downto 0);
++ P : in std_logic_vector(7 downto 0);
++ LCycle : out std_logic_vector(2 downto 0);
++ ALU_Op : out T_ALU_Op;
++ Set_BusA_To : out T_Set_BusA_To;-- DI,A,X,Y,S,P
++ Set_Addr_To : out T_Set_Addr_To;-- PC Adder,S,AD,BA
++ Write_Data : out T_Write_Data;-- DL,A,X,Y,S,P,PCL,PCH,A&X
++ Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
++ BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
++ BreakAtNA : out std_logic;
++ ADAdd : out std_logic;
++ AddY : out std_logic;
++ PCAdd : out std_logic;
++ Inc_S : out std_logic;
++ Dec_S : out std_logic;
++ LDA : out std_logic;
++ LDP : out std_logic;
++ LDX : out std_logic;
++ LDY : out std_logic;
++ LDS : out std_logic;
++ LDDI : out std_logic;
++ LDALU : out std_logic;
++ LDAD : out std_logic;
++ LDBAL : out std_logic;
++ LDBAH : out std_logic;
++ SaveP : out std_logic;
++ ALUmore : out std_logic;
++ Write : out std_logic
++ );
+ end T65_MCode;
+
+ architecture rtl of T65_MCode is
+
+- signal Branch : std_logic;
++ signal Branch : std_logic;
++ --ML:I need the Lcycle locally, so I made it a signal.
++ signal tLcycle:std_logic_vector(Lcycle'range);
++ signal tALUmore:std_logic;
++
++ --Some simulation debug values. Put an unique number for each assignment and identify it in simulation.
++ signal dbg_Set_BusA_To :integer:=0; --sim debug value to find where Set_BusA_To gets set.
++ signal dbg_LCycle :integer:=0; --sim debug value to fin where tLCycle gets set.
++ signal dbg_Set_Addr_To :integer:=0; --sim debug value to fin where Set_Addr_To gets set.
+
+ begin
+
+- with IR(7 downto 5) select
+- Branch <= not P(Flag_N) when "000",
+- P(Flag_N) when "001",
+- not P(Flag_V) when "010",
+- P(Flag_V) when "011",
+- not P(Flag_C) when "100",
+- P(Flag_C) when "101",
+- not P(Flag_Z) when "110",
+- P(Flag_Z) when others;
++ with IR(7 downto 5) select
++ Branch <= not P(Flag_N) when "000",
++ P(Flag_N) when "001",
++ not P(Flag_V) when "010",
++ P(Flag_V) when "011",
++ not P(Flag_C) when "100",
++ P(Flag_C) when "101",
++ not P(Flag_Z) when "110",
++ P(Flag_Z) when others;
+
+- process (IR, MCycle, P, Branch, Mode)
+- begin
+- LCycle <= "001";
+- Set_BusA_To <= "001"; -- A
+- Set_Addr_To <= (others => '0');
+- Write_Data <= (others => '0');
+- Jump <= (others => '0');
+- BAAdd <= "00";
+- BreakAtNA <= '0';
+- ADAdd <= '0';
+- PCAdd <= '0';
+- Inc_S <= '0';
+- Dec_S <= '0';
+- LDA <= '0';
+- LDP <= '0';
+- LDX <= '0';
+- LDY <= '0';
+- LDS <= '0';
+- LDDI <= '0';
+- LDALU <= '0';
+- LDAD <= '0';
+- LDBAL <= '0';
+- LDBAH <= '0';
+- SaveP <= '0';
+- Write <= '0';
+- AddY <= '0';
++ LCycle<=tLCycle;
++ ALUmore<=tALUmore;
+
+- case IR(7 downto 5) is
+- when "100" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- Set_BusA_To <= "011"; -- Y
+- Write_Data <= "011"; -- Y
+- when "10" =>
+- Set_BusA_To <= "010"; -- X
+- Write_Data <= "010"; -- X
+- when others =>
+- Write_Data <= "001"; -- A
+- end case;
+- --}}}
+- when "101" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- if IR(4) /= '1' or IR(2) /= '0' then
+- LDY <= '1';
+- end if;
+- when "10" =>
+- LDX <= '1';
+- when others =>
+- LDA <= '1';
+- end case;
+- Set_BusA_To <= "000"; -- DI
+- --}}}
+- when "110" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- if IR(4) = '0' then
+- LDY <= '1';
+- end if;
+- Set_BusA_To <= "011"; -- Y
+- when others =>
+- Set_BusA_To <= "001"; -- A
+- end case;
+- --}}}
+- when "111" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- if IR(4) = '0' then
+- LDX <= '1';
+- end if;
+- Set_BusA_To <= "010"; -- X
+- when others =>
+- Set_BusA_To <= "001"; -- A
+- end case;
+- --}}}
+- when others =>
+- end case;
++ process (IR, MCycle, P, Branch, Mode,tALUmore)
++ begin
++ tLCycle <= "001";
++ Set_BusA_To <= Set_BusA_To_ABC;
++ Set_Addr_To <= Set_Addr_To_PBR;
++ Write_Data <= Write_Data_DL;
++ Jump <= (others => '0');
++ BAAdd <= "00";
++ BreakAtNA <= '0';
++ ADAdd <= '0';
++ PCAdd <= '0';
++ Inc_S <= '0';
++ Dec_S <= '0';
++ LDA <= '0';
++ LDP <= '0';
++ LDX <= '0';
++ LDY <= '0';
++ LDS <= '0';
++ LDDI <= '0';
++ LDALU <= '0';
++ LDAD <= '0';
++ LDBAL <= '0';
++ LDBAH <= '0';
++ SaveP <= '0';
++ Write <= '0';
++ AddY <= '0';
++ tALUmore <='0';
++
++ case IR(7 downto 5) is
++ when "100" =>--covers 8x,9x
++ --{{{
++ case IR(1 downto 0) is
++ when "00" =>
++ Set_BusA_To <= Set_BusA_To_Y;
++ dbg_Set_BusA_To<=1;
++ Write_Data <= Write_Data_Y;
++ when "10" =>
++ Set_BusA_To <= Set_BusA_To_X;
++ dbg_Set_BusA_To<=2;
++ Write_Data <= Write_Data_X;
++ when others =>
++ Write_Data <= Write_Data_ABC;
++ end case;
++ --}}}
++ when "101" =>--covers ax,bx
++ --{{{
++ case IR(1 downto 0) is
++ when "00" =>
++ if IR(4) /= '1' or IR(2) /= '0' then--only for ax or b4,bc
++ LDY <= '1';
++ end if;
++ when "10" =>
++ LDX <= '1';
++ when "11" =>--undoc (beware OAL(ab),LAS(bb)=>Dont know what will happen)
++ LDX<='1';
++ LDA<='1';
++ when others =>
++ LDA <= '1';
++ end case;
++ Set_BusA_To <= Set_BusA_To_DI;
++ dbg_Set_BusA_To<=4;
++ --}}}
++ when "110" =>--covers cx,dx
++ --{{{
++ case IR(1 downto 0) is
++ when "00" =>
++ if IR(4) = '0' then--only for cx
++ LDY <= '1';
++ end if;
++ Set_BusA_To <= Set_BusA_To_Y;
++ dbg_Set_BusA_To<=5;
++ when others =>
++ Set_BusA_To <= Set_BusA_To_ABC;
++ dbg_Set_BusA_To<=6;
++ end case;
++ --}}}
++ when "111" =>--covers ex,fx
++ --{{{
++ case IR(1 downto 0) is
++ when "00" =>
++ if IR(4) = '0' then--only ex
++ LDX <= '1';
++ end if;
++ Set_BusA_To <= Set_BusA_To_X;
++ dbg_Set_BusA_To<=7;
++ when others =>
++ Set_BusA_To <= Set_BusA_To_ABC;
++ dbg_Set_BusA_To<=8;
++ end case;
++ --}}}
++ when others =>
++ end case;
+
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- Set_BusA_To <= "000"; -- DI
+- end if;
++-- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then--covers 0x-7x,cx-fx x=2,6,a,e
++ if IR(7 downto 6) /= "10" and IR(1) = '1' and (mode="00" or IR(0)='0') then--covers 0x-7x,cx-fx x=2,3,6,7,a,b,e,f, for 6502 undocs
++-- if Mode="00" and IR(0)='1' and ((IR(3 downto 2)="11" and MCycle = "101") or (IR(3 downto 2)="01" and MCycle = "100"))then
++ --if Mode="00" and IR(0)='1' and MCycle+1 = tLCycle then
++ if tALUmore='1' then
++ Set_BusA_To <= Set_BusA_To_ABC;--For added compare to DCP/DCM
++ dbg_Set_BusA_To<=99;
++ else
++ Set_BusA_To <= Set_BusA_To_DI;
++ dbg_Set_BusA_To<=9;
++ end if;
++ end if;
+
+- case IR(4 downto 0) is
+- when "00000" | "01000" | "01010" | "11000" | "11010" =>
+- --{{{
+- -- Implied
+- case IR is
+- when "00000000" =>
+- -- BRK
+- LCycle <= "110";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "111"; -- PCH
+- Write <= '1';
+- when 2 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "110"; -- PCL
+- Write <= '1';
+- when 3 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "101"; -- P
+- Write <= '1';
+- when 4 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- LDDI <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 6 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- when "00100000" =>
+- -- JSR
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDDI <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "111"; -- PCH
+- Write <= '1';
+- when 3 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "110"; -- PCL
+- Write <= '1';
+- when 4 =>
+- Dec_S <= '1';
+- when 5 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- when "01000000" =>
+- -- RTI
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 3 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Set_BusA_To <= "000"; -- DI
+- when 4 =>
+- LDP <= '1';
+- Inc_S <= '1';
+- LDDI <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 5 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- when "01100000" =>
+- -- RTS
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 3 =>
+- Inc_S <= '1';
+- LDDI <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 4 =>
+- Jump <= "10"; -- DIDL
+- when 5 =>
+- Jump <= "01";
+- when others =>
+- end case;
+- when "00001000" | "01001000" | "01011010" | "11011010" =>
+- -- PHP, PHA, PHY*, PHX*
+- LCycle <= "010";
+- if Mode = "00" and IR(1) = '1' then
+- LCycle <= "001";
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- case IR(7 downto 4) is
+- when "0000" =>
+- Write_Data <= "101"; -- P
+- when "0100" =>
+- Write_Data <= "001"; -- A
+- when "0101" =>
+- Write_Data <= "011"; -- Y
+- when "1101" =>
+- Write_Data <= "010"; -- X
+- when others =>
+- end case;
+- Write <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Dec_S <= '1';
+- when others =>
+- end case;
+- when "00101000" | "01101000" | "01111010" | "11111010" =>
+- -- PLP, PLA, PLY*, PLX*
+- LCycle <= "011";
+- if Mode = "00" and IR(1) = '1' then
+- LCycle <= "001";
+- end if;
+- case IR(7 downto 4) is
+- when "0010" =>
+- LDP <= '1';
+- when "0110" =>
+- LDA <= '1';
+- when "0111" =>
+- if Mode /= "00" then
+- LDY <= '1';
+- end if;
+- when "1111" =>
+- if Mode /= "00" then
+- LDX <= '1';
+- end if;
+- when others =>
+- end case;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- SaveP <= '1';
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 3 =>
+- Set_BusA_To <= "000"; -- DI
+- when others =>
+- end case;
+- when "10100000" | "11000000" | "11100000" =>
+- -- LDY, CPY, CPX
+- -- Immediate
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- when others =>
+- end case;
+- when "10001000" =>
+- -- DEY
+- LDY <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "011"; -- Y
+- when others =>
+- end case;
+- when "11001010" =>
+- -- DEX
+- LDX <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "010"; -- X
+- when others =>
+- end case;
+- when "00011010" | "00111010" =>
+- -- INC*, DEC*
+- if Mode /= "00" then
+- LDA <= '1'; -- A
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "100"; -- S
+- when others =>
+- end case;
+- when "00001010" | "00101010" | "01001010" | "01101010" =>
+- -- ASL, ROL, LSR, ROR
+- LDA <= '1'; -- A
+- Set_BusA_To <= "001"; -- A
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- when others =>
+- end case;
+- when "10001010" | "10011000" =>
+- -- TYA, TXA
+- LDA <= '1'; -- A
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- when others =>
+- end case;
+- when "10101010" | "10101000" =>
+- -- TAX, TAY
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "001"; -- A
+- when others =>
+- end case;
+- when "10011010" =>
+- -- TXS
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- LDS <= '1';
+- when 1 =>
+- when others =>
+- end case;
+- when "10111010" =>
+- -- TSX
+- LDX <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "100"; -- S
+- when others =>
+- end case;
++ case IR(4 downto 0) is
++ when "00000" | "01000" | "01010" | "11000" | "11010" =>
++ --{{{
++ -- Implied
++ case IR is
++ when "00000000" =>
++ -- BRK
++ tLCycle <= "110";
++ dbg_LCycle<=1;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=1;
++ Write_Data <= Write_Data_PCH;
++ Write <= '1';
++ when 2 =>
++ Dec_S <= '1';
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=2;
++ Write_Data <= Write_Data_PCL;
++ Write <= '1';
++ when 3 =>
++ Dec_S <= '1';
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=3;
++ Write_Data <= Write_Data_P;
++ Write <= '1';
++ when 4 =>
++ Dec_S <= '1';
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=4;
++ when 5 =>
++ LDDI <= '1';
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=5;
++ when 6 =>
++ Jump <= "10"; -- DIDL
++ when others =>
++ end case;
++ when "00100000" =>
++ -- JSR
++ tLCycle <= "101";
++ dbg_LCycle<=2;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDDI <= '1';
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=6;
++ when 2 =>
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=7;
++ Write_Data <= Write_Data_PCH;
++ Write <= '1';
++ when 3 =>
++ Dec_S <= '1';
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=8;
++ Write_Data <= Write_Data_PCL;
++ Write <= '1';
++ when 4 =>
++ Dec_S <= '1';
++ when 5 =>
++ Jump <= "10"; -- DIDL
++ when others =>
++ end case;
++ when "01000000" =>
++ -- RTI
++ tLCycle <= "101";
++ dbg_LCycle<=3;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=9;
++ when 2 =>
++ Inc_S <= '1';
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=10;
++ when 3 =>
++ Inc_S <= '1';
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=11;
++ Set_BusA_To <= Set_BusA_To_DI;
++ dbg_Set_BusA_To<=10;
++ when 4 =>
++ LDP <= '1';
++ Inc_S <= '1';
++ LDDI <= '1';
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=12;
++ when 5 =>
++ Jump <= "10"; -- DIDL
++ when others =>
++ end case;
++ when "01100000" =>
++ -- RTS
++ tLCycle <= "101";
++ dbg_LCycle<=4;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=13;
++ when 2 =>
++ Inc_S <= '1';
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=14;
++ when 3 =>
++ Inc_S <= '1';
++ LDDI <= '1';
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=15;
++ when 4 =>
++ Jump <= "10"; -- DIDL
++ when 5 =>
++ Jump <= "01";
++ when others =>
++ end case;
++ when "00001000" | "01001000" | "01011010" | "11011010" =>
++ -- PHP, PHA, PHY*, PHX*
++ tLCycle <= "010";
++ dbg_LCycle<=5;
++ if Mode = "00" and IR(1) = '1' then--2 cycle nop
++ tLCycle <= "001";
++ dbg_LCycle<=6;
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ if mode/="00" or IR(1)='0' then --wrong on 6502
++ Write <= '1';
++ case IR(7 downto 4) is
++ when "0000" =>
++ Write_Data <= Write_Data_P;
++ when "0100" =>
++ Write_Data <= Write_Data_ABC;
++ when "0101" => --not correct unsupporte
++ if Mode /= "00" then
++ Write_Data <= Write_Data_Y;
++ else
++ Write <= '0';
++ end if;
++ when "1101" =>
++ if Mode /= "00" then
++ Write_Data <= Write_Data_X;
++ else
++ Write <= '0';
++ end if;
++ when others =>
++ end case;
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=16;
++ end if;
++ when 2 =>
++ Dec_S <= '1';
++ when others =>
++ end case;
++ when "00101000" | "01101000" | "01111010" | "11111010" =>
++ -- PLP, PLA, PLY*, PLX*
++ tLCycle <= "011";
++ dbg_LCycle<=7;
++ if Mode = "00" and IR(1) = '1' then--2 cycle nop
++ tLCycle <= "001";
++ dbg_LCycle<=8;
++ end if;
++ case IR(7 downto 4) is
++ when "0010" =>--plp
++ LDP <= '1';
++ when "0110" =>--pla
++ LDA <= '1';
++ when "0111" =>--ply not for 6502
++ if Mode /= "00" then
++ LDY <= '1';
++ end if;
++ when "1111" =>--plx not for 6502
++ if Mode /= "00" then
++ LDX <= '1';
++ end if;
++ when others =>
++ end case;
+
+- -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" =>
+- -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX
+- -- case to_integer(unsigned(MCycle)) is
+- -- when 1 =>
+- -- when others =>
+- -- end case;
+- when others =>
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when others =>
+- end case;
+- end case;
+- --}}}
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ if Mode /= "00" or IR(1) = '0' then--wrong on 6502
++ SaveP <= '1';
++ end if;
++ when 1 =>
++ if Mode /= "00" or IR(1) = '0' then--wrong on 6502
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=17;
++ -- MWW This is wrong, ALU_OP is not populated yet, so previous op's P_out can be saved (This was caused by ROL followed by PLA - THE ISSUE MAY BE DEEPER!)
++ --SaveP <= '1'; --MWW
++ LDP <= '0';--MWW
++ end if;
++ when 2 =>
++ Inc_S <= '1';
++ Set_Addr_To <= Set_Addr_To_S;
++ dbg_Set_Addr_To<=18;
++ --SaveP <= '1';--MWW
++ LDP <= '0'; --MWW
++ when 3 =>
++ Set_BusA_To <= Set_BusA_To_DI;
++ dbg_Set_BusA_To<=11;
++ when others =>
++ end case;
++ when "10100000" | "11000000" | "11100000" =>
++ -- LDY, CPY, CPX
++ -- Immediate
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ when others =>
++ end case;
++ when "10001000" =>
++ -- DEY
++ LDY <= '1';
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Set_BusA_To <= Set_BusA_To_Y;
++ dbg_Set_BusA_To<=12;
++ when others =>
++ end case;
++ when "11001010" =>
++ -- DEX
++ LDX <= '1';
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Set_BusA_To <= Set_BusA_To_X;
++ dbg_Set_BusA_To<=13;
++ when others =>
++ end case;
++ when "00011010" | "00111010" =>
++ -- INC*, DEC*
++ if Mode /= "00" then
++ LDA <= '1'; -- A
++ else
++ tLCycle <= "001";--undoc 2 cycle nop..can I just load tLCycle counter like this?
++ dbg_LCycle<=9;
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Set_BusA_To <= Set_BusA_To_S;
++ dbg_Set_BusA_To<=14;
++ when others =>
++ end case;
++ when "00001010" | "00101010" | "01001010" | "01101010" =>
++ -- ASL, ROL, LSR, ROR
++ LDA <= '1'; -- A
++ Set_BusA_To <= Set_BusA_To_ABC;
++ dbg_Set_BusA_To<=15;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ when others =>
++ end case;
++ when "10001010" | "10011000" =>
++ -- TYA, TXA
++ LDA <= '1'; -- A
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ when others =>
++ end case;
++ when "10101010" | "10101000" =>
++ -- TAX, TAY
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Set_BusA_To <= Set_BusA_To_ABC;
++ dbg_Set_BusA_To<=16;
++ when others =>
++ end case;
++ when "10011010" =>
++ -- TXS
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ LDS <= '1';
++ when 1 =>
++ when others =>
++ end case;
++ when "10111010" =>
++ -- TSX
++ LDX <= '1';
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Set_BusA_To <= Set_BusA_To_S;
++ dbg_Set_BusA_To<=17;
++ when others =>
++ end case;
+
+- when "00001" | "00011" =>
+- --{{{
+- -- Zero Page Indexed Indirect (d,x)
+- LCycle <= "101";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- ADAdd <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- BAAdd <= "01"; -- DB Inc
+- LDBAL <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 4 =>
+- LDBAH <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- when others =>
+- end case;
+- --}}}
++ -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" =>
++ -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX
++ -- case to_integer(unsigned(MCycle)) is
++ -- when 1 =>
++ -- when others =>
++ -- end case;
++ when others =>
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when others =>
++ end case;
++ end case;
++ --}}}
+
+- when "01001" | "01011" =>
+- --{{{
+- -- Immediate
+- LDA <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- when others =>
+- end case;
++ when "00001" | "00011" =>
++ --{{{
++ -- Zero Page Indexed Indirect (d,x)
++ tLCycle <= "101";
++ dbg_LCycle<=10;
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ if Mode="00" and IR(1)='1' then--b3
++ LDX <= '1';--undoc, can load both A and X
++ end if;
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=19;
++ when 2 =>
++ ADAdd <= '1';
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=20;
++ when 3 =>
++ BAAdd <= "01"; -- DB Inc
++ LDBAL <= '1';
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=21;
++ when 4 =>
++ LDBAH <= '1';
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=22;
++ when 5 =>
++ if Mode="00" and IR(1)='1' then
++ tALUmore <= '1';--ML:For undoc ASO support
++ end if;
++ when 0 =>
++ if Mode="00" and IR(1)='1' then
++ SaveP <= '1';--ML:For undoc DCP/DCM support, save again after compare
++ end if;
++ when others =>
++ end case;
++ --}}}
+
+- --}}}
++ when "01001" | "01011" =>
++ --{{{
++ -- Immediate
++ LDA <= '1';
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ when others =>
++ end case;
+
+- when "00010" | "10010" =>
+- --{{{
+- -- Immediate, KIL
+- LDX <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- if IR = "10100010" then
+- -- LDX
+- Jump <= "01";
+- else
+- -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+- end if;
+- when others =>
+- end case;
+- --}}}
++ --}}}
+
+- when "00100" =>
+- --{{{
+- -- Zero Page
+- LCycle <= "010";
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- if IR(7 downto 5) = "001" then
+- SaveP <= '1';
+- end if;
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- when others =>
+- end case;
+- --}}}
++ when "00010" | "10010" =>
++ --{{{
++ -- Immediate, SKB, KIL
+
+- when "00101" | "00110" | "00111" =>
+- --{{{
+- -- Zero Page
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "100";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- LDALU <= '1';
+- SaveP <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 4 =>
+- when others =>
+- end case;
+- else
+- LCycle <= "010";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ if IR = "10100010" then
++ -- LDX
++ Jump <= "01";
++ LDX <= '1';--ML:Moved, Lorenz test showed X changing on SKB (NOPx)
++ elsif IR(7 downto 4)="1000" or IR(7 downto 4)="1100" or IR(7 downto 4)="1110" then
++ -- SKB skip next byte undoc
++ else
++ -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
++ end if;
++ when others =>
++ end case;
++ --}}}
+
+- when "01100" =>
+- --{{{
+- -- Absolute
+- if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then
+- -- JMP
+- if IR(5) = '0' then
+- --LCycle <= "011";
+- LCycle <= "010";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDDI <= '1';
+- when 2 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- else
+- --LCycle <= "101";
+- LCycle <= "100"; -- mikej
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDDI <= '1';
+- LDBAL <= '1';
+- when 2 =>
+- LDBAH <= '1';
+- if Mode /= "00" then
+- Jump <= "10"; -- DIDL
+- end if;
+- if Mode = "00" then
+- Set_Addr_To <= "11"; -- BA
+- end if;
+- when 3 =>
+- LDDI <= '1';
+- if Mode = "00" then
+- Set_Addr_To <= "11"; -- BA
+- BAAdd <= "01"; -- DB Inc
+- else
+- Jump <= "01";
+- end if;
+- when 4 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- end if;
+- else
+- LCycle <= "011";
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- if IR(7 downto 5) = "001" then
+- SaveP <= '1';
+- end if;
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- LDBAH <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
++ when "00100" =>
++ --{{{
++ -- Zero Page
++ tLCycle <= "010";
++ dbg_LCycle<=11;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ if IR(7 downto 5) = "001" then--24=BIT zpg
++ SaveP <= '1';
++ end if;
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ if IR(7 downto 5) = "100" then--84=sty zpg (the only write in this group)
++ Write <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=23;
++ when 2 =>
++ when others =>
++ end case;
++ --}}}
+
+- when "01101" | "01110" | "01111" =>
+- --{{{
+- -- Absolute
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- Write <= '1';
+- LDALU <= '1';
+- SaveP <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- SaveP <= '0'; -- MIKEJ was 1
+- when others =>
+- end case;
+- else
+- LCycle <= "011";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- LDBAH <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
++ when "00101" | "00110" | "00111" =>
++ --{{{
++ -- Zero Page
++-- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then--0x-7x,cx-fx, x=2,6,a,e
++ if IR(7 downto 6) /= "10" and IR(1) = '1' and (mode="00" or IR(0)='0') then--covers 0x-7x,cx-fx x=2,3,6,7,a,b,e,f, for 6502 undocs
++ -- Read-Modify-Write
++ if Mode="00" and IR(0)='1' then
++ LDA<='1';
++ end if;
++ tLCycle <= "100";
++ dbg_LCycle<=12;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=24;
++ when 2 =>
++ LDDI <= '1';
++ if Mode="00" then--The old 6500 writes back what is just read, before changing. The 65c does another read
++ Write <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=25;
++ when 3 =>
++ LDALU <= '1';
++ SaveP <= '1';
++ Write <= '1';
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=26;
++ when 4 =>
++ if Mode="00" and IR(0)='1' then
++ tALUmore <= '1';--ML:For undoc DCP/DCM support
++ end if;
++ when 0 =>
++ if Mode="00" and IR(0)='1' then
++ SaveP <= '1';--ML:For undoc DCP/DCM support, save again after compare
++ end if;
++ when others =>
++ end case;
++ else
++ tLCycle <= "010";
++ dbg_LCycle<=13;
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ if Mode="00" and IR(1)='1' then--b3
++ LDX <= '1';--undoc, can load both A and X
++ end if;
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=27;
++ when 2 =>
++ when others =>
++ end case;
++ end if;
++ --}}}
+
+- when "10000" =>
+- --{{{
+- -- Relative
++ when "01100" =>
++ --{{{
++ -- Absolute
++ if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then--4c,6c
++ -- JMP
++ if IR(5) = '0' then
++ --tLCycle <= "011";
++ tLCycle <= "010";
++ dbg_LCycle<=14;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDDI <= '1';
++ when 2 =>
++ Jump <= "10"; -- DIDL
++ when others =>
++ end case;
++ else
++ --tLCycle <= "101";
++ tLCycle <= "100"; -- mikej
++ dbg_LCycle<=15;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDDI <= '1';
++ LDBAL <= '1';
++ when 2 =>
++ LDBAH <= '1';
++ if Mode /= "00" then
++ Jump <= "10"; -- DIDL
++ end if;
++ if Mode = "00" then
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=28;
++ end if;
++ when 3 =>
++ LDDI <= '1';
++ if Mode = "00" then
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=29;
++ BAAdd <= "01"; -- DB Inc
++ else
++ Jump <= "01";
++ end if;
++ when 4 =>
++ Jump <= "10"; -- DIDL
++ when others =>
++ end case;
++ end if;
++ else
++ tLCycle <= "011";
++ dbg_LCycle<=16;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ if IR(7 downto 5) = "001" then--2c-BIT
++ SaveP <= '1';
++ end if;
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ LDBAH <= '1';
++ if IR(7 downto 5) = "100" then--80, sty, the only write in this group
++ Write <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=30;
++ when 3 =>
++ when others =>
++ end case;
++ end if;
++ --}}}
+
+- -- This circuit dictates when the last
+- -- microcycle occurs for the branch depending on
+- -- whether or not the branch is taken and if a page
+- -- is crossed...
+- if (Branch = '1') then
++ when "01101" | "01110" | "01111" =>
++ --{{{
++ -- Absolute
++-- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then--0x-7x,cx-fx, x=2,6,a,e
++ if IR(7 downto 6) /= "10" and IR(1) = '1' and (mode="00" or IR(0)='0') then--covers 0x-7x,cx-fx x=2,3,6,7,a,b,e,f, for 6502 undocs
++ -- Read-Modify-Write
++ tLCycle <= "101";
++ dbg_LCycle<=17;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ LDBAH <= '1';
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=31;
++ when 3 =>
++ LDDI <= '1';
++ if Mode="00" then--The old 6500 writes back what is just read, before changing. The 65c does another read
++ Write <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=32;
++ when 4 =>
++ Write <= '1';
++ LDALU <= '1';
++ SaveP <= '1';
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=33;
++ when 5 =>
++ --SaveP <= '0'; -- MIKEJ was 1
++ if Mode="00" and IR(0)='1' then
++ tALUmore <= '1';--ML:For undoc DCP/DCM support
++ end if;
++ when 0 =>
++ if Mode="00" and IR(0)='1' then
++ SaveP <= '1';--ML:For undoc DCP/DCM support, save again after compare
++ end if;
++ when others =>
++ end case;
++ else
++ tLCycle <= "011";
++ dbg_LCycle<=18;
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ if Mode="00" and IR(1)='1' then--b3
++ LDX <= '1';--undoc, can load both A and X
++ end if;
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ LDBAH <= '1';
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=34;
++ when 3 =>
++ when others =>
++ end case;
++ end if;
++ --}}}
+
+- LCycle <= "011"; -- We're done @ T3 if branching...upper
+- -- level logic will stop at T2 if no page cross
+- -- (See the Break signal)
+- else
++ when "10000" =>
++ --{{{
++ -- Relative
+
+- LCycle <= "001";
++ -- This circuit dictates when the last
++ -- microcycle occurs for the branch depending on
++ -- whether or not the branch is taken and if a page
++ -- is crossed...
++ if (Branch = '1') then
++ tLCycle <= "011"; -- We're done @ T3 if branching...upper
++ -- level logic will stop at T2 if no page cross
++ -- (See the Break signal)
++ dbg_LCycle<=19;
++ else
++ tLCycle <= "001";
++ dbg_LCycle<=20;
+
+- end if;
++ end if;
+
+- -- This decodes the current microcycle and takes the
+- -- proper course of action...
+- case to_integer(unsigned(MCycle)) is
++ -- This decodes the current microcycle and takes the
++ -- proper course of action...
++ case to_integer(unsigned(MCycle)) is
+
+- -- On the T1 microcycle, increment the program counter
+- -- and instruct the upper level logic to fetch the offset
+- -- from the Din bus and store it in the data latches. This
+- -- will be the last microcycle if the branch isn't taken.
+- when 1 =>
++ -- On the T1 microcycle, increment the program counter
++ -- and instruct the upper level logic to fetch the offset
++ -- from the Din bus and store it in the data latches. This
++ -- will be the last microcycle if the branch isn't taken.
++ when 1 =>
+
+- Jump <= "01"; -- Increments the PC by one (PC will now be PC+2)
+- -- from microcycle T0.
++ Jump <= "01"; -- Increments the PC by one (PC will now be PC+2)
++ -- from microcycle T0.
+
+- LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route
+- -- the Din bus to the memory data latch (DL)
+- -- so that the branch offset is fetched.
++ LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route
++ -- the Din bus to the memory data latch (DL)
++ -- so that the branch offset is fetched.
+
+- -- In microcycle T2, tell the logic in the top level to
+- -- add the offset. If the most significant byte of the
+- -- program counter (i.e. the current "page") does not need
+- -- updating, we are done here...the Break signal at the
+- -- T65.vhd level takes care of that...
+- when 2 =>
++ -- In microcycle T2, tell the logic in the top level to
++ -- add the offset. If the most significant byte of the
++ -- program counter (i.e. the current "page") does not need
++ -- updating, we are done here...the Break signal at the
++ -- T65.vhd level takes care of that...
++ when 2 =>
+
+- Jump <= "11"; -- Tell the PC Jump logic to use relative mode.
++ Jump <= "11"; -- Tell the PC Jump logic to use relative mode.
+
+- PCAdd <= '1'; -- This tells the PC adder to update itself with
+- -- the current offset recently fetched from
+- -- memory.
++ PCAdd <= '1'; -- This tells the PC adder to update itself with
++ -- the current offset recently fetched from
++ -- memory.
+
+- -- The following is microcycle T3 :
+- -- The program counter should be completely updated
+- -- on this cycle after the page cross is detected.
+- -- We don't need to do anything here...
+- when 3 =>
++ -- The following is microcycle T3 :
++ -- The program counter should be completely updated
++ -- on this cycle after the page cross is detected.
++ -- We don't need to do anything here...
++ when 3 =>
+
+
+- when others => null; -- Do nothing.
++ when others => null; -- Do nothing.
+
+- end case;
+- --}}}
++ end case;
++ --}}}
+
+- when "10001" | "10011" =>
+- --{{{
+- -- Zero Page Indirect Indexed (d),y
+- LCycle <= "101";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- LDBAL <= '1';
+- BAAdd <= "01"; -- DB Inc
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- Set_BusA_To <= "011"; -- Y
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- BAAdd <= "11"; -- BA Adj
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- else
+- BreakAtNA <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- when others =>
+- end case;
+- --}}}
++ when "10001" | "10011" =>
++ --{{{
++ -- Zero Page Indirect Indexed (d),y
++ tLCycle <= "101";
++ dbg_LCycle<=21;
++ if IR(7 downto 6) /= "10" then--91,b1,93,b3 only
++ LDA <= '1';
++ if Mode="00" and IR(1)='1' then--b3
++ LDX <= '1';--undoc, can load both A and X
++ end if;
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=35;
++ when 2 =>
++ LDBAL <= '1';
++ BAAdd <= "01"; -- DB Inc
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=36;
++ when 3 =>
++ Set_BusA_To <= Set_BusA_To_Y;
++ dbg_Set_BusA_To<=18;
++ BAAdd <= "10"; -- BA Add
++ LDBAH <= '1';
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=37;
++ when 4 =>
++ BAAdd <= "11"; -- BA Adj
++ if IR(7 downto 5) = "100" or IR(1)='1' then
++ Write <= '1';
++ else
++ BreakAtNA <= '1';
++ if Mode="00" and IR(1)='1' then
++ tALUmore <= '1';--ML:For undoc
++ end if;
++ end if;
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=38;
++ when 5 =>
++ if Mode="00" and IR(1)='1' then
++ tALUmore <= '1';--ML:For undoc
++ end if;
++ when 0 =>
++ if Mode="00" and IR(1)='1' then
++ SaveP <= '1';--ML:For undoc
++ end if;
++ when others =>
++ end case;
++ --}}}
+
+- when "10100" | "10101" | "10110" | "10111" =>
+- --{{{
+- -- Zero Page, X
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- ADAdd <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 4 =>
+- LDALU <= '1';
+- SaveP <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 5 =>
+- when others =>
+- end case;
+- else
+- LCycle <= "011";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- ADAdd <= '1';
+- -- Added this check for Y reg. use...
+- if (IR(3 downto 0) = "0110") then
+- AddY <= '1';
+- end if;
++ when "10100" | "10101" | "10110" | "10111" =>
++ --{{{
++ -- Zero Page, X
++-- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then--16,36,56,76,d6,f6
++ if IR(7 downto 6) /= "10" and IR(1) = '1' and (Mode="00" or IR(0)='0') then--covers 0x-7x,cx-fx x=2,3,6,7,a,b,e,f, for 6502 undocs
++ -- Read-Modify-Write
++ if Mode="00" and IR(0)='1' then
++ LDA<='1';
++ end if;
++ tLCycle <= "101";
++ dbg_LCycle<=22;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=39;
++ when 2 =>
++ ADAdd <= '1';
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=40;
++ when 3 =>
++ LDDI <= '1';
++ if Mode="00" then--The old 6500 writes back what is just read, before changing. The 65c does another read
++ Write <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=41;
++ when 4 =>
++ LDALU <= '1';
++ SaveP <= '1';
++ Write <= '1';
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=42;
++ when 5 =>
++ if Mode="00" and IR(0)='1' then
++ tALUmore <= '1';--ML:For undoc DCP/DCM support
++ end if;
++ when 0 =>
++ if Mode="00" and IR(0)='1' then
++ SaveP <= '1';--ML:For undoc DCP/DCM support, save again after compare
++ end if;
++ when others =>
++ end case;
++ elsif Mode="00" and IR(7 downto 6)/="10" and IR(4)='1' and IR(1 downto 0)="00" then --covers 1x,3x,5x,7x,dx,fx, for skb/nopzx 6502 undocs
++ tLCycle <= "011";--SKB's at x4
++ dbg_LCycle<=222;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";--skip a byte
++ when others=>
++ end case;
++ else
++ tLCycle <= "011";
++ dbg_LCycle<=23;
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ if Mode="00" and IR(1 downto 0)="11" then--x7
++ LDX <= '1';--undoc, can load both A and X
++ end if;
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=43;
++ when 2 =>
++ ADAdd <= '1';
++ -- Added this check for Y reg. use...
++ if (IR(3 downto 0) = "0110") then--96,b6
++ AddY <= '1';
++ end if;
+
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "10"; -- AD
+- when 3 => null;
+- when others =>
+- end case;
+- end if;
+- --}}}
++ if IR(7 downto 5) = "100" then--94,95,96,97 the only write instruction
++ Write <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_AD;
++ dbg_Set_Addr_To<=44;
++ when 3 => null;
++ when others =>
++ end case;
++ end if;
++ --}}}
+
+- when "11001" | "11011" =>
+- --{{{
+- -- Absolute Y
+- LCycle <= "100";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- Set_BusA_To <= "011"; -- Y
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- BAAdd <= "11"; -- BA adj
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- else
+- BreakAtNA <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- when others =>
+- end case;
+- --}}}
++ when "11001" | "11011" =>
++ --{{{
++ -- Absolute Y
++ tLCycle <= "100";
++ dbg_LCycle<=24;
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ if Mode="00" and IR(1 downto 0)="11" then--xb
++ LDX <= '1';--undoc, can load both A and X
++ end if;
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ Set_BusA_To <= Set_BusA_To_Y;
++ dbg_Set_BusA_To<=19;
++ BAAdd <= "10"; -- BA Add
++ LDBAH <= '1';
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=45;
++ when 3 =>
++ BAAdd <= "11"; -- BA adj
++-- if IR(7 downto 5) = "100" then--99/9b
++ if IR(7 downto 5) = "100" or IR(1)='1' then
++ Write <= '1';
++ else
++ BreakAtNA <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=46;
++ when 4 =>
++ if Mode="00" and IR(1)='1' then
++ tALUmore <= '1';--ML:For undoc
++ end if;
++ when 0 =>
++ if Mode="00" and IR(1)='1' then
++ SaveP <= '1';--ML:For undoc
++ end if;
++ when others =>
++ end case;
++ --}}}
+
+- when "11100" | "11101" | "11110" | "11111" =>
+- --{{{
+- -- Absolute X
++ when "11100" | "11101" | "11110" | "11111" =>
++ --{{{
++ -- Absolute X
+
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "110";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- Set_BusA_To <= "010"; -- X
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- BAAdd <= "11"; -- BA adj
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- LDALU <= '1';
+- SaveP <= '1';
+- Write <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 6 =>
+- when others =>
+- end case;
+- else
+- LCycle <= "100";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- -- mikej
+- -- special case 0xBE which uses Y reg as index!!
+- if (IR = "10111110") then
+- Set_BusA_To <= "011"; -- Y
+- else
+- Set_BusA_To <= "010"; -- X
+- end if;
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- BAAdd <= "11"; -- BA adj
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- else
+- BreakAtNA <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
+- when others =>
+- end case;
+- end process;
++-- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then--1x,3x,5x,7x,dx,fx, x=c,d,e,f
++ if IR(7 downto 6) /= "10" and IR(1) = '1' and (Mode="00" or IR(0)='0') then--covers 0x-7x,cx-fx x=2,3,6,7,a,b,e,f, for 6502 undocs
++ -- Read-Modify-Write
++ tLCycle <= "110";
++ dbg_LCycle<=25;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ Set_BusA_To <= Set_BusA_To_X;
++ dbg_Set_BusA_To<=20;
++ BAAdd <= "10"; -- BA Add
++ LDBAH <= '1';
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=47;
++ when 3 =>
++ BAAdd <= "11"; -- BA adj
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=48;
++ when 4 =>
++ LDDI <= '1';
++ if Mode="00" then--The old 6500 writes back what is just read, before changing. The 65c does another read
++ Write <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=49;
++ when 5 =>
++ LDALU <= '1';
++ SaveP <= '1';
++ Write <= '1';
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=50;
++ when 6 =>
++ if Mode="00" and IR(0)='1' then
++ tALUmore <= '1';--ML:For undoc DCP/DCM support
++ end if;
++ when 0 =>
++ if Mode="00" and IR(0)='1' then
++ SaveP <= '1';--ML:For undoc DCP/DCM support, save again after compare
++ end if;
++ when others =>
++ end case;
++-- elsif Mode="00" and IR(7 downto 6)/="10" and IR(4)='1' and IR(1 downto 0)="00" then --covers 1x,3x,5x,7x,dx,fx, for 6502 skw/nopax undocs
++-- tLCycle <= "100";--SKW's at xc
++-- dbg_LCycle<=260;
++-- case to_integer(unsigned(MCycle)) is
++-- when 1 =>
++-- Jump <= "01";--skip a byte
++-- when 2 =>
++-- Jump <= "01";--skip a byte
++-- when 3 =>
++-- BreakAtNA <= '1';
++-- when others=>
++-- end case;
++ else--9c,9d,9e,9f,bc,bd,be,bf
++ tLCycle <= "100";
++ dbg_LCycle<=26;
++ if IR(7 downto 6) /= "10" then
++ if Mode/="00" or IR(4)='0' or IR(1 downto 0)/="00" then --covers 1x,3x,5x,7x,dx,fx, for 6502 skw/nopax undocs
++ LDA <= '1';
++ if Mode="00" and IR(1 downto 0)="11" then--9f,bf
++ LDX <= '1';--undoc, can load both A and X
++ end if;
++ end if;
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ -- mikej
++ -- special case 0xBE which uses Y reg as index!! (added undoc 9e,9f,bf)
++-- if (IR = "10-1111-") then
++ if(IR(7 downto 6)="10" and IR(4 downto 1)="1111") then
++ Set_BusA_To <= Set_BusA_To_Y;
++ dbg_Set_BusA_To<=21;
++ else
++ Set_BusA_To <= Set_BusA_To_X;
++ dbg_Set_BusA_To<=22;
++ end if;
++ BAAdd <= "10"; -- BA Add
++ LDBAH <= '1';
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=51;
++ when 3 =>
++ BAAdd <= "11"; -- BA adj
++ if IR(7 downto 5) = "100" then--9x
++ Write <= '1';
++ else
++ BreakAtNA <= '1';
++ end if;
++ Set_Addr_To <= Set_Addr_To_BA;
++ dbg_Set_Addr_To<=52;
++ when 4 =>
++ when others =>
++ end case;
++ end if;
++ --}}}
++ when others =>
++ end case;
++ end process;
+
+- process (IR, MCycle)
+- begin
+- -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
+- -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
+- case IR(1 downto 0) is
+- when "00" =>
+- --{{{
+- case IR(4 downto 2) is
+- when "000" | "001" | "011" =>
+- case IR(7 downto 5) is
+- when "110" | "111" =>
+- -- CP
+- ALU_Op <= "0110";
+- when "101" =>
+- -- LD
+- ALU_Op <= "0101";
+- when "001" =>
+- -- BIT
+- ALU_Op <= "1100";
+- when others =>
+- -- NOP/ST
+- ALU_Op <= "0100";
+- end case;
+- when "010" =>
+- case IR(7 downto 5) is
+- when "111" | "110" =>
+- -- IN
+- ALU_Op <= "1111";
+- when "100" =>
+- -- DEY
+- ALU_Op <= "1110";
+- when others =>
+- -- LD
+- ALU_Op <= "1101";
+- end case;
+- when "110" =>
+- case IR(7 downto 5) is
+- when "100" =>
+- -- TYA
+- ALU_Op <= "1101";
+- when others =>
+- ALU_Op <= "----";
+- end case;
+- when others =>
+- case IR(7 downto 5) is
+- when "101" =>
+- -- LD
+- ALU_Op <= "1101";
+- when others =>
+- ALU_Op <= "0100";
+- end case;
+- end case;
+- --}}}
+- when "01" => -- OR
+- --{{{
+- ALU_Op(3) <= '0';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- --}}}
+- when "10" =>
+- --{{{
+- ALU_Op(3) <= '1';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- case IR(7 downto 5) is
+- when "000" =>
+- if IR(4 downto 2) = "110" then
+- -- INC
+- ALU_Op <= "1111";
+- end if;
+- when "001" =>
+- if IR(4 downto 2) = "110" then
+- -- DEC
+- ALU_Op <= "1110";
+- end if;
+- when "100" =>
+- if IR(4 downto 2) = "010" then
+- -- TXA
+- ALU_Op <= "0101";
+- else
+- ALU_Op <= "0100";
+- end if;
+- when others =>
+- end case;
+- --}}}
+- when others =>
+- --{{{
+- case IR(7 downto 5) is
+- when "100" =>
+- ALU_Op <= "0100";
+- when others =>
+- if MCycle = "000" then
+- ALU_Op(3) <= '0';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- else
+- ALU_Op(3) <= '1';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- end if;
+- end case;
+- --}}}
+- end case;
+- end process;
++ process (IR, MCycle, Mode,tALUmore)
++ begin
++ -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
++ -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
++ case IR(1 downto 0) is
++ when "00" =>
++ --{{{
++ case IR(4 downto 2) is
++ when "000" | "001" | "011" =>-- "---0 xx00", xx!="10"
++ case IR(7 downto 5) is
++ when "110" | "111" =>--c0,c4,cc,e0,e5,ec
++ -- CP
++ ALU_Op <= ALU_OP_CMP;
++ when "101" =>--a0,a4,ac
++ -- LD
++ ALU_Op <= ALU_OP_EQ2;
++ when "001" =>--20,24,2c (20 is ignored, as its a jmp)
++ -- BIT
++ ALU_Op <= ALU_OP_BIT;
++ when others =>--other x0,x4,xc
++ -- NOP/ST
++ ALU_Op <= ALU_OP_EQ1;
++ end case;
++ when "010" =>-- "---0 1000"
++ case IR(7 downto 5) is
++ when "111" | "110" =>--c8,e8
++ -- IN
++ ALU_Op <= ALU_OP_INC;
++ when "100" =>--88
++ -- DEY
++ ALU_Op <= ALU_OP_DEC;
++ when others =>
++ -- LD
++ ALU_Op <= ALU_OP_EQ3;
++ end case;
++ when "110" =>-- "---1 1000"
++ case IR(7 downto 5) is
++ when "100" =>--98
++ -- TYA
++ ALU_Op <= ALU_OP_EQ3;
++ when others =>
++ ALU_Op <= ALU_OP_UNDEF;
++ end case;
++ when others =>-- "---x xx00"
++ case IR(7 downto 5) is
++ when "101" =>--ax,bx
++ -- LD
++ ALU_Op <= ALU_OP_EQ3;
++ when others =>
++ ALU_Op <= ALU_OP_EQ1;
++ end case;
++ end case;
++ --}}}
++ when "01" => -- OR
++ --{{{
++ case(to_integer(unsigned(IR(7 downto 5)))) is
++ when 0=>
++ ALU_Op<=ALU_OP_OR;
++ when 1=>
++ ALU_Op<=ALU_OP_AND;
++ when 2=>
++ ALU_Op<=ALU_OP_EOR;
++ when 3=>
++ ALU_Op<=ALU_OP_ADC;
++ when 4=>
++ ALU_Op<=ALU_OP_EQ1;--sta
++ when 5=>
++ ALU_Op<=ALU_OP_EQ2;--lda
++ when 6=>
++ ALU_Op<=ALU_OP_CMP;
++ when others=>
++ ALU_Op<=ALU_OP_SBC;
++ end case;
++--ML:replaced by above case()
++-- ALU_Op(3) <= '0';
++-- ALU_Op(2 downto 0) <= IR(7 downto 5);
++ --}}}
++ when "10" =>
++ --{{{
++ case(to_integer(unsigned(IR(7 downto 5)))) is
++ when 0=>
++ ALU_Op<=ALU_OP_ASL;
++ when 1=>
++ ALU_Op<=ALU_OP_ROL;
++ when 2=>
++ ALU_Op<=ALU_OP_LSR;
++ when 3=>
++ ALU_Op<=ALU_OP_ROR;
++ when 4=>
++ ALU_Op<=ALU_OP_BIT;
++ when 5=>
++ ALU_Op<=ALU_OP_EQ3;--ldx
++ when 6=>
++ ALU_Op<=ALU_OP_DEC;
++ when others=>
++ ALU_Op<=ALU_OP_INC;
++ end case;
++--ML:replaced by above case()
++-- ALU_Op(3) <= '1';
++-- ALU_Op(2 downto 0) <= IR(7 downto 5);
++ case IR(7 downto 5) is
++ when "000" =>
++ if IR(4 downto 2) = "110" and Mode/="00" then--ML:00011010,1a->inc acc, not on 6502
++ -- INC
++ ALU_Op <= ALU_OP_INC;
++ end if;
++ when "001" =>
++ if IR(4 downto 2) = "110" and Mode/="00" then--ML:00111010,3a->dec acc, not on 6502
++ -- DEC
++ ALU_Op <= ALU_OP_DEC;
++ end if;
++ when "100" =>
++ if IR(4 downto 2) = "010" then --10001010,8a->TXA
++ -- TXA
++ ALU_Op <= ALU_OP_EQ2;
++ else --100xxx10, 82,86,8e,92,96,9a,9e
++ ALU_Op <= ALU_OP_EQ1;
++ end if;
++ when others =>
++ end case;
++ --}}}
++ when others =>--"11" undoc double alu ops
++ --{{{
++ case IR(7 downto 5) is
++ when "101" =>--ax,bx
++ ALU_Op <= ALU_OP_EQ1;
++ when others =>
++-- if MCycle >= tLCycle then
++ if tALUmore='1' then
++ case(to_integer(unsigned(IR(7 downto 5)))) is
++ when 0=>
++ ALU_Op<=ALU_OP_OR;
++ when 1=>
++ ALU_Op<=ALU_OP_AND;
++ when 2=>
++ ALU_Op<=ALU_OP_EOR;
++ when 3=>
++ ALU_Op<=ALU_OP_ADC;
++ when 4=>
++ ALU_Op<=ALU_OP_EQ1;--sta
++ when 5=>
++ ALU_Op<=ALU_OP_EQ2;--lda
++ when 6=>
++ ALU_Op<=ALU_OP_CMP;
++ when others=>
++ ALU_Op<=ALU_OP_SBC;
++ end case;
++--replaced by above case()
++-- ALU_Op(3) <= '0';
++-- ALU_Op(2 downto 0) <= IR(7 downto 5);
++ else
++ case(to_integer(unsigned(IR(7 downto 5)))) is
++ when 0=>
++ ALU_Op<=ALU_OP_ASL;
++ when 1=>
++ ALU_Op<=ALU_OP_ROL;
++ when 2=>
++ ALU_Op<=ALU_OP_LSR;
++ when 3=>
++ ALU_Op<=ALU_OP_ROR;
++ when 4=>
++ ALU_Op<=ALU_OP_BIT;
++ when 5=>
++ ALU_Op<=ALU_OP_EQ3;--ldx
++ when 6=>
++ ALU_Op<=ALU_OP_DEC;
++ when others=>
++ ALU_Op<=ALU_OP_INC;
++ end case;
++--replaced by above case()
++-- ALU_Op(3) <= '1';
++-- ALU_Op(2 downto 0) <= IR(7 downto 5);
++ end if;
++ end case;
++ --}}}
++ end case;
++ end process;
+
+ end;
+diff --git a/T65/T65_Pack.vhd b/T65/T65_Pack.vhd
+index e025e1b..1c9178d 100644
+--- a/T65/T65_Pack.vhd
++++ b/T65/T65_Pack.vhd
+@@ -2,6 +2,8 @@
+ -- T65(b) core. In an effort to merge and maintain bug fixes ....
+ --
+ --
++-- Ver 303 ost(ML) July 2014
++-- "magic" constants converted to vhdl types
+ -- Ver 300 Bugfixes by ehenciak added
+ -- MikeJ March 2005
+ -- Latest version from www.fpgaarcade.com (original www.opencores.org)
+@@ -59,59 +61,110 @@ use IEEE.std_logic_1164.all;
+
+ package T65_Pack is
+
+- constant Flag_C : integer := 0;
+- constant Flag_Z : integer := 1;
+- constant Flag_I : integer := 2;
+- constant Flag_D : integer := 3;
+- constant Flag_B : integer := 4;
+- constant Flag_1 : integer := 5;
+- constant Flag_V : integer := 6;
+- constant Flag_N : integer := 7;
++ constant Flag_C : integer := 0;
++ constant Flag_Z : integer := 1;
++ constant Flag_I : integer := 2;
++ constant Flag_D : integer := 3;
++ constant Flag_B : integer := 4;
++ constant Flag_1 : integer := 5;
++ constant Flag_V : integer := 6;
++ constant Flag_N : integer := 7;
+
+- component T65_MCode
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+- IR : in std_logic_vector(7 downto 0);
+- MCycle : in std_logic_vector(2 downto 0);
+- P : in std_logic_vector(7 downto 0);
+- LCycle : out std_logic_vector(2 downto 0);
+- ALU_Op : out std_logic_vector(3 downto 0);
+- Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
+- Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
+- Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
+- Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
+- BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
+- BreakAtNA : out std_logic;
+- ADAdd : out std_logic;
+- AddY : out std_logic;
+- PCAdd : out std_logic;
+- Inc_S : out std_logic;
+- Dec_S : out std_logic;
+- LDA : out std_logic;
+- LDP : out std_logic;
+- LDX : out std_logic;
+- LDY : out std_logic;
+- LDS : out std_logic;
+- LDDI : out std_logic;
+- LDALU : out std_logic;
+- LDAD : out std_logic;
+- LDBAL : out std_logic;
+- LDBAH : out std_logic;
+- SaveP : out std_logic;
+- Write : out std_logic
+- );
+- end component;
++ type T_Set_BusA_To is
++ (
++ Set_BusA_To_DI,
++ Set_BusA_To_ABC,
++ Set_BusA_To_X,
++ Set_BusA_To_Y,
++ Set_BusA_To_S,
++ Set_BusA_To_P,
++ Set_BusA_To_DONTCARE
++ );
++ type T_Set_Addr_To is
++ (
++ Set_Addr_To_S,
++ Set_Addr_To_AD,
++ Set_Addr_To_PBR,
++ Set_Addr_To_BA
++ );
++ type T_Write_Data is
++ (
++ Write_Data_DL,
++ Write_Data_ABC,
++ Write_Data_X,
++ Write_Data_Y,
++ Write_Data_S,
++ Write_Data_P,
++ Write_Data_PCL,
++ Write_Data_PCH,
++ Write_Data_DONTCARE
++ );
++ type T_ALU_OP is
++ (
++ ALU_OP_OR, --"0000"
++ ALU_OP_AND, --"0001"
++ ALU_OP_EOR, --"0010"
++ ALU_OP_ADC, --"0011"
++ ALU_OP_EQ1, --"0100" EQ1 does not change N,Z flags, EQ2/3 does.
++ ALU_OP_EQ2, --"0101"Not sure yet whats the difference between EQ2&3. They seem to do the same ALU op
++ ALU_OP_CMP, --"0110"
++ ALU_OP_SBC, --"0111"
++ ALU_OP_ASL, --"1000"
++ ALU_OP_ROL, --"1001"
++ ALU_OP_LSR, --"1010"
++ ALU_OP_ROR, --"1011"
++ ALU_OP_BIT, --"1100"
++ ALU_OP_EQ3, --"1101"
++ ALU_OP_DEC, --"1110"
++ ALU_OP_INC, --"1111"
++ ALU_OP_UNDEF--"----"--may be replaced with any?
++ );
+
+- component T65_ALU
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
+- Op : in std_logic_vector(3 downto 0);
+- BusA : in std_logic_vector(7 downto 0);
+- BusB : in std_logic_vector(7 downto 0);
+- P_In : in std_logic_vector(7 downto 0);
+- P_Out : out std_logic_vector(7 downto 0);
+- Q : out std_logic_vector(7 downto 0)
+- );
+- end component;
++ component T65_MCode
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
++ IR : in std_logic_vector(7 downto 0);
++ MCycle : in std_logic_vector(2 downto 0);
++ P : in std_logic_vector(7 downto 0);
++ LCycle : out std_logic_vector(2 downto 0);
++ ALU_Op : out T_ALU_Op;
++ Set_BusA_To : out T_Set_BusA_To;-- DI,A,X,Y,S,P
++ Set_Addr_To : out T_Set_Addr_To;-- PC Adder,S,AD,BA
++ Write_Data : out T_Write_Data;-- DL,A,X,Y,S,P,PCL,PCH
++ Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
++ BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
++ BreakAtNA : out std_logic;
++ ADAdd : out std_logic;
++ AddY : out std_logic;
++ PCAdd : out std_logic;
++ Inc_S : out std_logic;
++ Dec_S : out std_logic;
++ LDA : out std_logic;
++ LDP : out std_logic;
++ LDX : out std_logic;
++ LDY : out std_logic;
++ LDS : out std_logic;
++ LDDI : out std_logic;
++ LDALU : out std_logic;
++ LDAD : out std_logic;
++ LDBAL : out std_logic;
++ LDBAH : out std_logic;
++ SaveP : out std_logic;
++ ALUmore : out std_logic;
++ Write : out std_logic
++ );
++ end component;
++
++ component T65_ALU
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
++ Op : in T_ALU_Op;
++ BusA : in std_logic_vector(7 downto 0);
++ BusB : in std_logic_vector(7 downto 0);
++ P_In : in std_logic_vector(7 downto 0);
++ P_Out : out std_logic_vector(7 downto 0);
++ Q : out std_logic_vector(7 downto 0)
++ );
++ end component;
+
+ end;
diff --git a/de1/fpga-bbc-pq/master/dram-floating-pins.patch b/de1/fpga-bbc-pq/master/dram-floating-pins.patch
new file mode 100644
index 0000000..2c75184
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/dram-floating-pins.patch
@@ -0,0 +1,193 @@
+diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd
+index 2788103..fa7b2e8 100644
+--- a/bbc_micro_de1.vhd
++++ b/bbc_micro_de1.vhd
+@@ -70,7 +70,7 @@ generic (
+ -- 5 Not used
+ -- 6 Not used
+ -- 7 MOS
+- ROM_OFFSET : std_logic_vector(7 downto 0) := "00001000"
++ ROM_OFFSET : std_logic_vector(21 downto 0) := std_logic_vector(to_unsigned(16#20000#,22))
+ );
+ port (
+ -- Clocks
+@@ -663,6 +663,7 @@ signal sys_via_ca2_out : std_logic;
+ signal sys_via_ca2_oe_n : std_logic;
+ signal sys_via_pa_in : std_logic_vector(7 downto 0);
+ signal sys_via_pa_out : std_logic_vector(7 downto 0);
++signal effective_sys_via_pa_out : std_logic_vector(7 downto 0);
+ signal sys_via_pa_oe_n : std_logic_vector(7 downto 0);
+ signal sys_via_cb1_in : std_logic := '0';
+ signal sys_via_cb1_out : std_logic;
+@@ -745,6 +746,9 @@ signal romsel : std_logic_vector(3 downto 0);
+
+ signal mhz1_enable : std_logic; -- Set for access to any 1 MHz peripheral
+
++signal video_data : std_logic_vector (7 downto 0);
++signal cpu_ram_di : std_logic_vector (7 downto 0);
++
+ begin
+ -------------------------
+ -- COMPONENT INSTANCES
+@@ -800,6 +804,8 @@ begin
+ cpu_a,
+ cpu_di,
+ cpu_do );
++
++ crtc_lpstb <='0';
+
+ crtc : mc6845 port map (
+ clock,
+@@ -826,7 +832,7 @@ begin
+ vidproc_enable,
+ cpu_a(0),
+ cpu_do,
+- SRAM_DQ(7 downto 0),
++ video_data,
+ vidproc_invert_n,
+ vidproc_disen,
+ crtc_cursor,
+@@ -850,7 +856,7 @@ begin
+ reset_n,
+ clock, -- Data input is synchronised from the bus clock domain
+ vid_clken,
+- SRAM_DQ(6 downto 0),
++ video_data(6 downto 0),
+ ttxt_glr,
+ ttxt_dew,
+ ttxt_crs,
+@@ -889,6 +895,8 @@ begin
+ mhz4_clken,
+ clock
+ );
++
++ effective_sys_via_pa_out <= sys_via_pa_out or sys_via_pa_oe_n;
+
+ -- User VIA
+ user_via : m6522 port map (
+@@ -1118,7 +1126,7 @@ begin
+
+ -- CPU data bus mux and interrupts
+ cpu_di <=
+- SRAM_DQ(7 downto 0) when ram_enable = '1' else
++ cpu_ram_di when ram_enable = '1' else
+ FL_DQ when rom_enable = '1' else
+ FL_DQ when mos_enable = '1' else
+ crtc_do when crtc_enable = '1' else
+@@ -1137,19 +1145,17 @@ begin
+ FL_CE_N <= '0';
+ FL_OE_N <= '0';
+ FL_WE_N <= '1';
+- FL_ADDR(21 downto 17) <= ROM_OFFSET(7 downto 3);
+- FL_ADDR(16 downto 14) <=
+- "111" when mos_enable = '1' else
+- "0" & romsel(1 downto 0);
++ FL_ADDR(21 downto 17) <= ROM_OFFSET(21 downto 17);
++ FL_ADDR(16 downto 14) <= "111" when mos_enable = '1' else "0" & romsel(1 downto 0);
+ FL_ADDR(13 downto 0) <= cpu_a(13 downto 0);
+
+ -- SRAM bus
+ SRAM_UB_N <= '1';
+ SRAM_LB_N <= '0';
+- SRAM_CE_N <= '0';
++ SRAM_CE_N <= clock;
+ SRAM_OE_N <= '0';
+- SRAM_DQ(15 downto 8) <= (others => '0');
+-
++ video_data <= SRAM_DQ(7 downto 0);
++
+ -- Synchronous outputs to SRAM
+ process(clock,reset_n)
+ variable ram_write : std_logic;
+@@ -1158,23 +1164,25 @@ begin
+
+ if reset_n = '0' then
+ SRAM_WE_N <= '1';
+- SRAM_DQ(7 downto 0) <= (others => 'Z');
++ SRAM_DQ(15 downto 0) <= (others => 'Z');
+ elsif rising_edge(clock) then
+- -- Default to inputs
+- SRAM_DQ(7 downto 0) <= (others => 'Z');
+-
+ -- Register SRAM signals to outputs (clock must be at least 2x CPU clock)
+ if vid_clken = '1' then
+- -- Fetch data from previous CPU cycle
++ -- set up bus for CPU cycle
+ SRAM_WE_N <= not ram_write;
+ SRAM_ADDR <= "00" & cpu_a(15 downto 0);
+ if ram_write = '1' then
++ SRAM_DQ(15 downto 8) <=(others =>'0');
+ SRAM_DQ(7 downto 0) <= cpu_do;
++ else
++ SRAM_DQ(15 downto 0) <= (others => 'Z');
+ end if;
+ else
+- -- Fetch data from previous display cycle
++ cpu_ram_di <= SRAM_DQ(7 downto 0);
++ -- setup crtc cycle
+ SRAM_WE_N <= '1';
+ SRAM_ADDR <= "000" & display_a;
++ SRAM_DQ(15 downto 0) <= (others => 'Z');
+ end if;
+ end if;
+ end process;
+@@ -1242,24 +1250,25 @@ begin
+
+ -- Connections to System VIA
+ -- ADC
+- sys_via_cb1_in <= '1'; -- /EOC
++ sys_via_cb1_in <= '0'; -- EOC
+ -- CRTC
+ sys_via_ca1_in <= crtc_vsync;
+ sys_via_cb2_in <= crtc_lpstb;
+ -- Keyboard
+ sys_via_ca2_in <= keyb_int;
+ sys_via_pa_in(7) <= keyb_out;
+- sys_via_pa_in(6 downto 0) <= sys_via_pa_out(6 downto 0); -- Must loop back output pins or keyboard won't work
+- keyb_column <= sys_via_pa_out(3 downto 0);
+- keyb_row <= sys_via_pa_out(6 downto 4);
++ sys_via_pa_in(6 downto 0) <= effective_sys_via_pa_out(6 downto 0); -- Must loop back output pins or keyboard won't work
++ keyb_column <= effective_sys_via_pa_out(3 downto 0);
++ keyb_row <= effective_sys_via_pa_out(6 downto 4);
+ -- Sound
+- sound_di <= sys_via_pa_out;
++ sound_di <= effective_sys_via_pa_out;
+ -- Others (idle until missing bits implemented)
+ sys_via_pb_in(7 downto 4) <= (others => '1');
+
+ -- Connections to User VIA (user port is output on green LEDs)
+ user_via_ca1_in <= '1'; -- Pulled up
+ --LEDG <= user_via_pb_out;
++ --LEDG(7 downto 2) <= (others => '0');
+
+ -- MMBEEB
+ user_via_cb1_in <= user_via_pb_out(1);
+@@ -1290,15 +1299,15 @@ begin
+ disp_addr_offs <= ic32(5 downto 4);
+ caps_lock_led_n <= ic32(6);
+ shift_lock_led_n <= ic32(7);
++
+
+ process(clock,reset_n)
+ variable bit_num : integer;
+ begin
+ bit_num := to_integer(unsigned(sys_via_pb_out(2 downto 0)));
+-
+ if reset_n = '0' then
+- ic32 <= (others => '0');
+- elsif rising_edge(clock) then
++ ic32 <= (others => '1');
++ elsif rising_edge(clock) then -- the real beep latches this on the 1MHz bus clock exactly once per sys_via_enable
+ ic32(bit_num) <= sys_via_pb_out(3);
+ end if;
+ end process;
+@@ -1311,6 +1320,9 @@ begin
+ -- DEBUG STUFF
+ -----------------
+
++ DRAM_DQ <= (others => 'Z');
++ DRAM_DQ <= (others => 'Z');
++
+ GPIO_0(0) <= not (crtc_hsync xor crtc_vsync);
+ GPIO_0(1) <= crtc_de;
+
diff --git a/de1/fpga-bbc-pq/master/endstop b/de1/fpga-bbc-pq/master/endstop
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/endstop
diff --git a/de1/fpga-bbc-pq/master/fix-warnings.patch b/de1/fpga-bbc-pq/master/fix-warnings.patch
new file mode 100644
index 0000000..cb144a6
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/fix-warnings.patch
@@ -0,0 +1,43 @@
+diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd
+index 0985580..9234f82 100644
+--- a/bbc_micro_de1.vhd
++++ b/bbc_micro_de1.vhd
+@@ -159,11 +159,12 @@ port (
+ SD_MISO : in std_logic;
+
+ -- GPIO
+- GPIO_0 : inout std_logic_vector(35 downto 0);
+- GPIO_1 : inout std_logic_vector(35 downto 0)
++ GPIO_0 : out std_logic_vector(35 downto 0);
++ GPIO_1 : out std_logic_vector(35 downto 0)
+ );
+ end entity;
+
++-- altera message_off 10036
+ architecture rtl of bbc_micro_de1 is
+
+ ------------------------------
+diff --git a/mc6845.vhd b/mc6845.vhd
+index c28152d..59407d1 100644
+--- a/mc6845.vhd
++++ b/mc6845.vhd
+@@ -70,6 +70,7 @@ port (
+ );
+ end entity;
+
++-- altera message_off 10036
+ architecture rtl of mc6845 is
+
+ -- Host-accessible registers
+diff --git a/saa5050.vhd b/saa5050.vhd
+index d082339..ad09624 100644
+--- a/saa5050.vhd
++++ b/saa5050.vhd
+@@ -85,6 +85,7 @@ port (
+ );
+ end entity;
+
++-- altera message_off 10036
+ architecture rtl of saa5050 is
+
+ component saa5050_rom IS
diff --git a/de1/fpga-bbc-pq/master/gitignore.patch b/de1/fpga-bbc-pq/master/gitignore.patch
new file mode 100644
index 0000000..c4702f2
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/gitignore.patch
@@ -0,0 +1,24 @@
+diff --git a/.gitignore b/.gitignore
+new file mode 100644
+index 0000000..f3f2537
+--- /dev/null
++++ b/.gitignore
+@@ -0,0 +1,18 @@
++*.stamp
++bbc_micro_de1.asm.rpt
++bbc_micro_de1.fit.rpt
++bbc_micro_de1.fit.smsg
++bbc_micro_de1.fit.summary
++bbc_micro_de1.flow.rpt
++bbc_micro_de1.jdi
++bbc_micro_de1.map.rpt
++bbc_micro_de1.map.summary
++bbc_micro_de1.pin
++bbc_micro_de1.pof
++bbc_micro_de1.qpf
++bbc_micro_de1.sof
++bbc_micro_de1_assignment_defaults.qdf
++db/
++fit.stamp
++incremental_db/
++source.stamp
diff --git a/de1/fpga-bbc-pq/master/keyboard-fixes.patch b/de1/fpga-bbc-pq/master/keyboard-fixes.patch
new file mode 100644
index 0000000..c12e167
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/keyboard-fixes.patch
@@ -0,0 +1,53 @@
+diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd
+index 7de7276..08145ca 100644
+--- a/bbc_micro_de1.vhd
++++ b/bbc_micro_de1.vhd
+@@ -922,6 +922,9 @@ begin
+ clock
+ );
+
++ --LEDG(0) <= not PS2_CLK;
++ --LEDG(1) <= not PS2_DAT;
++
+ -- Keyboard
+ keyb : keyboard port map (
+ clock, hard_reset_n, mhz1_clken,
+diff --git a/keyboard.vhd b/keyboard.vhd
+index d3dd8f4..c1893c6 100644
+--- a/keyboard.vhd
++++ b/keyboard.vhd
+@@ -73,6 +73,7 @@ port (
+ );
+ end entity;
+
++-- altera message_off 10036
+ architecture rtl of keyboard is
+
+ -- PS/2 interface
+@@ -208,6 +209,13 @@ begin
+ KEYPRESS <= '0';
+ end if;
+ end process;
++
++ keys(10) <= (others => '0');
++ keys(11) <= (others => '0');
++ keys(12) <= (others => '0');
++ keys(13) <= (others => '0');
++ keys(14) <= (others => '0');
++ keys(15) <= (others => '0');
+
+ -- Decode PS/2 data
+ process(CLOCK,nRESET)
+@@ -229,12 +237,6 @@ begin
+ keys(8) <= (others => '0');
+ keys(9) <= (others => '0');
+ -- These non-existent rows are used in the BBC master
+- keys(10) <= (others => '0');
+- keys(11) <= (others => '0');
+- keys(12) <= (others => '0');
+- keys(13) <= (others => '0');
+- keys(14) <= (others => '0');
+- keys(15) <= (others => '0');
+ elsif rising_edge(CLOCK) then
+ -- Copy DIP switches through to row 0
+ keys(2)(0) <= DIP_SWITCH(7);
diff --git a/de1/fpga-bbc-pq/master/keyboard.patch b/de1/fpga-bbc-pq/master/keyboard.patch
new file mode 100644
index 0000000..ffeefc3
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/keyboard.patch
@@ -0,0 +1,787 @@
+diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd
+index 462e507..7de7276 100644
+--- a/bbc_micro_de1.vhd
++++ b/bbc_micro_de1.vhd
+@@ -398,8 +398,8 @@ port (
+ CLKEN_1MHZ : in std_logic;
+
+ -- PS/2 interface
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
++ PS2_CLK : inout std_logic;
++ PS2_DATA : inout std_logic;
+
+ -- If 1 then column is incremented automatically at
+ -- 1 MHz rate
+@@ -416,7 +416,9 @@ port (
+ BREAK_OUT : out std_logic;
+
+ -- DIP switch inputs
+- DIP_SWITCH : in std_logic_vector(7 downto 0)
++ DIP_SWITCH : in std_logic_vector(7 downto 0);
++
++ DEBUG : out std_logic_vector(7 downto 0)
+ );
+ end component;
+
+@@ -930,7 +932,8 @@ begin
+ keyb_out,
+ keyb_int,
+ keyb_break,
+- SW(7 downto 0)
++ SW(7 downto 0),
++ LEDG
+ );
+
+ -- Sound generator (and drive logic for I2S codec)
+diff --git a/keyboard.vhd b/keyboard.vhd
+index cba4054..d3dd8f4 100644
+--- a/keyboard.vhd
++++ b/keyboard.vhd
+@@ -50,8 +50,8 @@ port (
+ CLKEN_1MHZ : in std_logic;
+
+ -- PS/2 interface
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
++ PS2_CLK : inout std_logic;
++ PS2_DATA : inout std_logic;
+
+ -- If 1 then column is incremented automatically at
+ -- 1 MHz rate
+@@ -68,31 +68,57 @@ port (
+ BREAK_OUT : out std_logic;
+
+ -- DIP switch inputs
+- DIP_SWITCH : in std_logic_vector(7 downto 0)
++ DIP_SWITCH : in std_logic_vector(7 downto 0);
++ DEBUG : out std_logic_vector(7 downto 0)
+ );
+ end entity;
+
+ architecture rtl of keyboard is
+
+ -- PS/2 interface
+-component ps2_intf is
+-generic (filter_length : positive := 8);
++--component ps2_intf is
++--generic (filter_length : positive := 8);
++--port(
++-- CLK : in std_logic;
++-- nRESET : in std_logic;
++--
++-- -- PS/2 interface (could be bi-dir)
++-- PS2_CLK : inout std_logic;
++-- PS2_DATA : inout std_logic;
++--
++-- -- Byte-wide data interface - only valid for one clock
++-- -- so must be latched externally if required
++-- DATA : out std_logic_vector(7 downto 0);
++-- VALID : out std_logic;
++-- ERROR : out std_logic;
++-- DEBUG : out std_logic_vector(7 downto 0)
++-- );
++--end component;
++
++component ps2_keyboard is
+ port(
+ CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- -- PS/2 interface (could be bi-dir)
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
+-
+- -- Byte-wide data interface - only valid for one clock
+- -- so must be latched externally if required
+- DATA : out std_logic_vector(7 downto 0);
+- VALID : out std_logic;
+- ERROR : out std_logic
+- );
++ RESET : in std_logic;
++ PS2_CLK_O : out std_logic;
++ PS2_DATA_O : out std_logic;
++ PS2_CLK_I : in std_logic;
++ PS2_DATA_I : in std_logic;
++ RX_EXTENDED : out std_logic;
++ RX_RELEASED : out std_logic;
++ RX_SHIFT_KEY_ON : out std_logic;
++ RX_SCAN_CODE : out std_logic_vector(7 downto 0);
++ RX_ASCII : out std_logic_vector(7 downto 0);
++ RX_DATA_READY : out std_logic;
++ RX_READ : in std_logic;
++ TX_DATA : in std_logic_vector(7 downto 0);
++ TX_WRITE : in std_logic;
++ TX_WRITE_ACK_O : out std_logic;
++ TX_ERROR_NO_KEYBOARD_ACK : out std_logic;
++ TRANSLATE : in std_logic
++);
+ end component;
+
++
+ -- Interface to PS/2 block
+ signal keyb_data : std_logic_vector(7 downto 0);
+ signal keyb_valid : std_logic;
+@@ -104,13 +130,46 @@ signal keys : key_matrix;
+ signal col : unsigned(3 downto 0);
+ signal release : std_logic;
+ signal extended : std_logic;
++
++signal rx_extended : std_logic;
++signal rx_release : std_logic;
++signal rx_shift_key_on : std_logic;
++signal rx_ascii : std_logic_vector(7 downto 0);
++signal tx_write_ack : std_logic;
++signal tx_error : std_logic;
++
++signal ps2_clk_o : std_logic;
++signal ps2_data_o: std_logic;
++signal tx_data : std_logic_vector(7 downto 0);
++signal tx_write : std_logic;
+ begin
+
+- ps2 : ps2_intf port map (
+- CLOCK, nRESET,
+- PS2_CLK, PS2_DATA,
+- keyb_data, keyb_valid, keyb_error
+- );
++ PS2_CLK <='0' when ps2_clk_o='0' else 'Z';
++ PS2_DATA <='0' when ps2_data_o='0' else 'Z';
++
++
++
++ ps2 : ps2_keyboard port map (
++ CLOCK, not nRESET,
++ ps2_clk_o,ps2_data_o,
++ PS2_CLK,PS2_DATA,
++ rx_extended,rx_release,
++ rx_shift_key_on, keyb_data,rx_ascii,
++ keyb_valid,keyb_valid,tx_data,
++ tx_write,tx_write_ack,tx_error,'0');
++
++
++ process(CLOCK,nRESET,tx_write_ack) begin
++ if nRESET = '0' then
++ tx_write <= '1';
++ tx_data <= to_stdlogicvector(x"F4");
++ elsif rising_edge(CLOCK) then
++ if tx_write_ack='1' then
++ tx_write<='0';
++ end if;
++ end if;
++ end process;
++
+
+ -- Column counts automatically when AUTOSCAN is enabled, otherwise
+ -- value is loaded from external input
+@@ -188,6 +247,7 @@ begin
+ keys(9)(0) <= DIP_SWITCH(0);
+
+ if keyb_valid = '1' then
++ DEBUG <= keyb_data;
+ -- Decode keyboard input
+ if keyb_data = X"e0" then
+ -- Extended key code follows
+diff --git a/ps2_keyboard.v b/ps2_keyboard.v
+new file mode 100644
+index 0000000..0f21c7c
+--- /dev/null
++++ b/ps2_keyboard.v
+@@ -0,0 +1,597 @@
++//-------------------------------------------------------------------------------------
++
++
++`define TOTAL_BITS 11
++`define EXTEND_CODE 16'hE0
++`define RELEASE_CODE 16'hF0
++`define LEFT_SHIFT 16'h12
++`define RIGHT_SHIFT 16'h59
++
++
++module ps2_keyboard (
++ clk,
++ reset,
++ ps2_clk_o,
++ ps2_data_o,
++ ps2_clk_i,
++ ps2_data_i,
++ rx_extended,
++ rx_released,
++ rx_shift_key_on,
++ rx_scan_code,
++ rx_ascii,
++ rx_data_ready, // rx_read_o
++ rx_read, // rx_read_ack_i
++ tx_data,
++ tx_write,
++ tx_write_ack_o,
++ tx_error_no_keyboard_ack,
++ translate
++ );
++
++// Parameters
++
++// The timer value can be up to (2^bits) inclusive.
++parameter TIMER_60USEC_VALUE_PP = 2950; // Number of sys_clks for 60usec.
++parameter TIMER_60USEC_BITS_PP = 12; // Number of bits needed for timer
++parameter TIMER_5USEC_VALUE_PP = 186; // Number of sys_clks for debounce
++parameter TIMER_5USEC_BITS_PP = 8; // Number of bits needed for timer
++parameter TRAP_SHIFT_KEYS_PP = 0; // Default: No shift key trap.
++
++// State encodings, provided as parameters
++// for flexibility to the one instantiating the module.
++// In general, the default values need not be changed.
++
++// State "m1_rx_clk_l" has been chosen on purpose. Since the input
++// synchronizing flip-flops initially contain zero, it takes one clk
++// for them to update to reflect the actual (idle = high) status of
++// the I/O lines from the keyboard. Therefore, choosing 0 for m1_rx_clk_l
++// allows the state machine to transition to m1_rx_clk_h when the true
++// values of the input signals become present at the outputs of the
++// synchronizing flip-flops. This initial transition is harmless, and it
++// eliminates the need for a "reset" pulse before the interface can operate.
++
++parameter m1_rx_clk_h = 1;
++parameter m1_rx_clk_l = 0;
++parameter m1_rx_falling_edge_marker = 13;
++parameter m1_rx_rising_edge_marker = 14;
++parameter m1_tx_force_clk_l = 3;
++parameter m1_tx_first_wait_clk_h = 10;
++parameter m1_tx_first_wait_clk_l = 11;
++parameter m1_tx_reset_timer = 12;
++parameter m1_tx_wait_clk_h = 2;
++parameter m1_tx_clk_h = 4;
++parameter m1_tx_clk_l = 5;
++parameter m1_tx_wait_keyboard_ack = 6;
++parameter m1_tx_done_recovery = 7;
++parameter m1_tx_error_no_keyboard_ack = 8;
++parameter m1_tx_rising_edge_marker = 9;
++parameter m2_rx_data_ready = 1;
++parameter m2_rx_data_ready_ack = 0;
++
++
++// I/O declarations
++input clk;
++input reset;
++output ps2_clk_o ;
++output ps2_data_o ;
++input ps2_clk_i ;
++input ps2_data_i ;
++output rx_extended;
++output rx_released;
++output rx_shift_key_on;
++output [7:0] rx_scan_code;
++output [7:0] rx_ascii;
++output rx_data_ready;
++input rx_read;
++input [7:0] tx_data;
++input tx_write;
++output tx_write_ack_o;
++output tx_error_no_keyboard_ack;
++input translate ;
++
++reg rx_extended;
++reg rx_released;
++reg [7:0] rx_scan_code;
++reg [7:0] rx_ascii;
++reg rx_data_ready;
++reg tx_error_no_keyboard_ack;
++
++// Internal signal declarations
++wire timer_60usec_done;
++wire timer_5usec_done;
++wire extended;
++wire released;
++wire shift_key_on;
++
++ // NOTE: These two signals used to be one. They
++ // were split into two signals because of
++ // shift key trapping. With shift key
++ // trapping, no event is generated externally,
++ // but the "hold" data must still be cleared
++ // anyway regardless, in preparation for the
++ // next scan codes.
++wire rx_output_event; // Used only to clear: hold_released, hold_extended
++wire rx_output_strobe; // Used to produce the actual output.
++
++wire tx_parity_bit;
++wire rx_shifting_done;
++wire tx_shifting_done;
++wire [11:0] shift_key_plus_code;
++
++reg [`TOTAL_BITS-1:0] q;
++reg [3:0] m1_state;
++reg [3:0] m1_next_state;
++reg m2_state;
++reg m2_next_state;
++reg [3:0] bit_count;
++reg enable_timer_60usec;
++reg enable_timer_5usec;
++reg [TIMER_60USEC_BITS_PP-1:0] timer_60usec_count;
++reg [TIMER_5USEC_BITS_PP-1:0] timer_5usec_count;
++reg [7:0] ascii; // "REG" type only because a case statement is used.
++reg left_shift_key;
++reg right_shift_key;
++reg hold_extended; // Holds prior value, cleared at rx_output_strobe
++reg hold_released; // Holds prior value, cleared at rx_output_strobe
++reg ps2_clk_s; // Synchronous version of this input
++reg ps2_data_s; // Synchronous version of this input
++reg ps2_clk_hi_z; // Without keyboard, high Z equals 1 due to pullups.
++reg ps2_data_hi_z; // Without keyboard, high Z equals 1 due to pullups.
++
++//--------------------------------------------------------------------------
++// Module code
++
++assign ps2_clk_o = ps2_clk_hi_z ;
++assign ps2_data_o = ps2_data_hi_z ;
++
++// Input "synchronizing" logic -- synchronizes the inputs to the state
++// machine clock, thus avoiding errors related to
++// spurious state machine transitions.
++always @(posedge clk)
++begin
++ ps2_clk_s <= ps2_clk_i;
++ ps2_data_s <= ps2_data_i;
++end
++
++// State register
++always @(posedge clk)
++begin : m1_state_register
++ if (reset) m1_state <= m1_rx_clk_h;
++ else m1_state <= m1_next_state;
++end
++
++// State transition logic
++always @(m1_state
++ or q
++ or tx_shifting_done
++ or tx_write
++ or ps2_clk_s
++ or ps2_data_s
++ or timer_60usec_done
++ or timer_5usec_done
++ )
++begin : m1_state_logic
++
++ // Output signals default to this value, unless changed in a state condition.
++ ps2_clk_hi_z <= 1;
++ ps2_data_hi_z <= 1;
++ tx_error_no_keyboard_ack <= 0;
++ enable_timer_60usec <= 0;
++ enable_timer_5usec <= 0;
++
++ case (m1_state)
++
++ m1_rx_clk_h :
++ begin
++ enable_timer_60usec <= 1;
++ if (tx_write) m1_next_state <= m1_tx_reset_timer;
++ else if (~ps2_clk_s) m1_next_state <= m1_rx_falling_edge_marker;
++ else m1_next_state <= m1_rx_clk_h;
++ end
++
++ m1_rx_falling_edge_marker :
++ begin
++ enable_timer_60usec <= 0;
++ m1_next_state <= m1_rx_clk_l;
++ end
++
++ m1_rx_rising_edge_marker :
++ begin
++ enable_timer_60usec <= 0;
++ m1_next_state <= m1_rx_clk_h;
++ end
++
++
++ m1_rx_clk_l :
++ begin
++ enable_timer_60usec <= 1;
++ if (tx_write) m1_next_state <= m1_tx_reset_timer;
++ else if (ps2_clk_s) m1_next_state <= m1_rx_rising_edge_marker;
++ else m1_next_state <= m1_rx_clk_l;
++ end
++
++ m1_tx_reset_timer:
++ begin
++ enable_timer_60usec <= 0;
++ m1_next_state <= m1_tx_force_clk_l;
++ end
++
++ m1_tx_force_clk_l :
++ begin
++ enable_timer_60usec <= 1;
++ ps2_clk_hi_z <= 0; // Force the ps2_clk line low.
++ if (timer_60usec_done) m1_next_state <= m1_tx_first_wait_clk_h;
++ else m1_next_state <= m1_tx_force_clk_l;
++ end
++
++ m1_tx_first_wait_clk_h :
++ begin
++ enable_timer_5usec <= 1;
++ ps2_data_hi_z <= 0; // Start bit.
++ if (~ps2_clk_s && timer_5usec_done)
++ m1_next_state <= m1_tx_clk_l;
++ else
++ m1_next_state <= m1_tx_first_wait_clk_h;
++ end
++
++ // This state must be included because the device might possibly
++ // delay for up to 10 milliseconds before beginning its clock pulses.
++ // During that waiting time, we cannot drive the data (q[0]) because it
++ // is possibly 1, which would cause the keyboard to abort its receive
++ // and the expected clocks would then never be generated.
++ m1_tx_first_wait_clk_l :
++ begin
++ ps2_data_hi_z <= 0;
++ if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
++ else m1_next_state <= m1_tx_first_wait_clk_l;
++ end
++
++ m1_tx_wait_clk_h :
++ begin
++ enable_timer_5usec <= 1;
++ ps2_data_hi_z <= q[0];
++ if (ps2_clk_s && timer_5usec_done)
++ m1_next_state <= m1_tx_rising_edge_marker;
++ else
++ m1_next_state <= m1_tx_wait_clk_h;
++ end
++
++ m1_tx_rising_edge_marker :
++ begin
++ ps2_data_hi_z <= q[0];
++ m1_next_state <= m1_tx_clk_h;
++ end
++
++ m1_tx_clk_h :
++ begin
++ ps2_data_hi_z <= q[0];
++ if (tx_shifting_done) m1_next_state <= m1_tx_wait_keyboard_ack;
++ else if (~ps2_clk_s) m1_next_state <= m1_tx_clk_l;
++ else m1_next_state <= m1_tx_clk_h;
++ end
++
++ m1_tx_clk_l :
++ begin
++ ps2_data_hi_z <= q[0];
++ if (ps2_clk_s) m1_next_state <= m1_tx_wait_clk_h;
++ else m1_next_state <= m1_tx_clk_l;
++ end
++
++ m1_tx_wait_keyboard_ack :
++ begin
++ if (~ps2_clk_s && ps2_data_s)
++ m1_next_state <= m1_tx_error_no_keyboard_ack;
++ else if (~ps2_clk_s && ~ps2_data_s)
++ m1_next_state <= m1_tx_done_recovery;
++ else m1_next_state <= m1_tx_wait_keyboard_ack;
++ end
++
++ m1_tx_done_recovery :
++ begin
++ if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
++ else m1_next_state <= m1_tx_done_recovery;
++ end
++
++ m1_tx_error_no_keyboard_ack :
++ begin
++ tx_error_no_keyboard_ack <= 1;
++ if (ps2_clk_s && ps2_data_s) m1_next_state <= m1_rx_clk_h;
++ else m1_next_state <= m1_tx_error_no_keyboard_ack;
++ end
++
++ default : m1_next_state <= m1_rx_clk_h;
++ endcase
++end
++
++// State register
++always @(posedge clk)
++begin : m2_state_register
++ if (reset) m2_state <= m2_rx_data_ready_ack;
++ else m2_state <= m2_next_state;
++end
++
++// State transition logic
++always @(m2_state or rx_output_strobe or rx_read)
++begin : m2_state_logic
++ case (m2_state)
++ m2_rx_data_ready_ack:
++ begin
++ rx_data_ready <= 1'b0;
++ if (rx_output_strobe) m2_next_state <= m2_rx_data_ready;
++ else m2_next_state <= m2_rx_data_ready_ack;
++ end
++ m2_rx_data_ready:
++ begin
++ rx_data_ready <= 1'b1;
++ if (rx_read) m2_next_state <= m2_rx_data_ready_ack;
++ else m2_next_state <= m2_rx_data_ready;
++ end
++ default : m2_next_state <= m2_rx_data_ready_ack;
++ endcase
++end
++
++// This is the bit counter
++always @(posedge clk)
++begin
++ if ( reset
++ || rx_shifting_done
++ || (m1_state == m1_tx_wait_keyboard_ack) // After tx is done.
++ ) bit_count <= 0; // normal reset
++ else if (timer_60usec_done
++ && (m1_state == m1_rx_clk_h)
++ && (ps2_clk_s)
++ ) bit_count <= 0; // rx watchdog timer reset
++ else if ( (m1_state == m1_rx_falling_edge_marker) // increment for rx
++ ||(m1_state == m1_tx_rising_edge_marker) // increment for tx
++ )
++ bit_count <= bit_count + 1;
++end
++// This signal is high for one clock at the end of the timer count.
++assign rx_shifting_done = (bit_count == `TOTAL_BITS);
++assign tx_shifting_done = (bit_count == `TOTAL_BITS-1);
++
++// This is the signal which enables loading of the shift register.
++// It also indicates "ack" to the device writing to the transmitter.
++assign tx_write_ack_o = ( (tx_write && (m1_state == m1_rx_clk_h))
++ ||(tx_write && (m1_state == m1_rx_clk_l))
++ );
++
++// This is the ODD parity bit for the transmitted word.
++assign tx_parity_bit = ~^tx_data;
++
++// This is the shift register
++always @(posedge clk)
++begin
++ if (reset) q <= 0;
++ else if (tx_write_ack_o) q <= {1'b1,tx_parity_bit,tx_data,1'b0};
++ else if ( (m1_state == m1_rx_falling_edge_marker)
++ ||(m1_state == m1_tx_rising_edge_marker) )
++ q <= {ps2_data_s,q[`TOTAL_BITS-1:1]};
++end
++
++// This is the 60usec timer counter
++always @(posedge clk)
++begin
++ if (~enable_timer_60usec) timer_60usec_count <= 0;
++ else if (~timer_60usec_done) timer_60usec_count <= timer_60usec_count + 1;
++end
++assign timer_60usec_done = (timer_60usec_count == (TIMER_60USEC_VALUE_PP - 1));
++
++// This is the 5usec timer counter
++always @(posedge clk)
++begin
++ if (~enable_timer_5usec) timer_5usec_count <= 0;
++ else if (~timer_5usec_done) timer_5usec_count <= timer_5usec_count + 1;
++end
++assign timer_5usec_done = (timer_5usec_count == TIMER_5USEC_VALUE_PP - 1);
++
++
++// Create the signals which indicate special scan codes received.
++// These are the "unlatched versions."
++`ifdef PS2_TRAP_EXTENDED
++assign extended = (q[8:1] == `EXTEND_CODE) && rx_shifting_done && translate ;
++`else
++assign extended = 1'b0 ;
++`endif
++assign released = (q[8:1] == `RELEASE_CODE) && rx_shifting_done && translate ;
++
++// Store the special scan code status bits
++// Not the final output, but an intermediate storage place,
++// until the entire set of output data can be assembled.
++always @(posedge clk)
++begin
++ if (reset || rx_output_event)
++ begin
++ hold_extended <= 0;
++ hold_released <= 0;
++ end
++ else
++ begin
++ if (rx_shifting_done && extended) hold_extended <= 1;
++ if (rx_shifting_done && released) hold_released <= 1;
++ end
++end
++
++
++// These bits contain the status of the two shift keys
++always @(posedge clk)
++begin
++ if (reset) left_shift_key <= 0;
++ else if ((q[8:1] == `LEFT_SHIFT) && rx_shifting_done && ~hold_released)
++ left_shift_key <= 1;
++ else if ((q[8:1] == `LEFT_SHIFT) && rx_shifting_done && hold_released)
++ left_shift_key <= 0;
++end
++
++always @(posedge clk)
++begin
++ if (reset) right_shift_key <= 0;
++ else if ((q[8:1] == `RIGHT_SHIFT) && rx_shifting_done && ~hold_released)
++ right_shift_key <= 1;
++ else if ((q[8:1] == `RIGHT_SHIFT) && rx_shifting_done && hold_released)
++ right_shift_key <= 0;
++end
++
++assign rx_shift_key_on = left_shift_key || right_shift_key;
++
++// Output the special scan code flags, the scan code and the ascii
++always @(posedge clk)
++begin
++ if (reset)
++ begin
++ rx_extended <= 0;
++ rx_released <= 0;
++ rx_scan_code <= 0;
++ rx_ascii <= 0;
++ end
++ else if (rx_output_strobe)
++ begin
++ rx_extended <= hold_extended;
++ rx_released <= hold_released;
++ rx_scan_code <= q[8:1];
++ rx_ascii <= ascii;
++ end
++end
++
++// Store the final rx output data only when all extend and release codes
++// are received and the next (actual key) scan code is also ready.
++// (the presence of rx_extended or rx_released refers to the
++// the current latest scan code received, not the previously latched flags.)
++assign rx_output_event = (rx_shifting_done
++ && ~extended
++ && ~released
++ );
++
++assign rx_output_strobe = (rx_shifting_done
++ && ~extended
++ && ~released
++ && ( (TRAP_SHIFT_KEYS_PP == 0)
++ || ( (q[8:1] != `RIGHT_SHIFT)
++ &&(q[8:1] != `LEFT_SHIFT)
++ )
++ )
++ );
++
++// This part translates the scan code into an ASCII value...
++// Only the ASCII codes which I considered important have been included.
++// if you want more, just add the appropriate case statement lines...
++// (You will need to know the keyboard scan codes you wish to assign.)
++// The entries are listed in ascending order of ASCII value.
++assign shift_key_plus_code = {3'b0,rx_shift_key_on,q[8:1]};
++always @(shift_key_plus_code)
++begin
++ casez (shift_key_plus_code)
++ 12'h?66 : ascii <= 8'h08; // Backspace ("backspace" key)
++ 12'h?0d : ascii <= 8'h09; // Horizontal Tab
++ 12'h?5a : ascii <= 8'h0d; // Carriage return ("enter" key)
++ 12'h?76 : ascii <= 8'h1b; // Escape ("esc" key)
++ 12'h?29 : ascii <= 8'h20; // Space
++ 12'h116 : ascii <= 8'h21; // !
++ 12'h152 : ascii <= 8'h22; // "
++ 12'h126 : ascii <= 8'h23; // #
++ 12'h125 : ascii <= 8'h24; // $
++ 12'h12e : ascii <= 8'h25; // %
++ 12'h13d : ascii <= 8'h26; // &
++ 12'h052 : ascii <= 8'h27; // '
++ 12'h146 : ascii <= 8'h28; // (
++ 12'h145 : ascii <= 8'h29; // )
++ 12'h13e : ascii <= 8'h2a; // *
++ 12'h155 : ascii <= 8'h2b; // +
++ 12'h041 : ascii <= 8'h2c; // ,
++ 12'h04e : ascii <= 8'h2d; // -
++ 12'h049 : ascii <= 8'h2e; // .
++ 12'h04a : ascii <= 8'h2f; // /
++ 12'h045 : ascii <= 8'h30; // 0
++ 12'h016 : ascii <= 8'h31; // 1
++ 12'h01e : ascii <= 8'h32; // 2
++ 12'h026 : ascii <= 8'h33; // 3
++ 12'h025 : ascii <= 8'h34; // 4
++ 12'h02e : ascii <= 8'h35; // 5
++ 12'h036 : ascii <= 8'h36; // 6
++ 12'h03d : ascii <= 8'h37; // 7
++ 12'h03e : ascii <= 8'h38; // 8
++ 12'h046 : ascii <= 8'h39; // 9
++ 12'h14c : ascii <= 8'h3a; // :
++ 12'h04c : ascii <= 8'h3b; // ;
++ 12'h141 : ascii <= 8'h3c; // <
++ 12'h055 : ascii <= 8'h3d; // =
++ 12'h149 : ascii <= 8'h3e; // >
++ 12'h14a : ascii <= 8'h3f; // ?
++ 12'h11e : ascii <= 8'h40; // @
++ 12'h11c : ascii <= 8'h41; // A
++ 12'h132 : ascii <= 8'h42; // B
++ 12'h121 : ascii <= 8'h43; // C
++ 12'h123 : ascii <= 8'h44; // D
++ 12'h124 : ascii <= 8'h45; // E
++ 12'h12b : ascii <= 8'h46; // F
++ 12'h134 : ascii <= 8'h47; // G
++ 12'h133 : ascii <= 8'h48; // H
++ 12'h143 : ascii <= 8'h49; // I
++ 12'h13b : ascii <= 8'h4a; // J
++ 12'h142 : ascii <= 8'h4b; // K
++ 12'h14b : ascii <= 8'h4c; // L
++ 12'h13a : ascii <= 8'h4d; // M
++ 12'h131 : ascii <= 8'h4e; // N
++ 12'h144 : ascii <= 8'h4f; // O
++ 12'h14d : ascii <= 8'h50; // P
++ 12'h115 : ascii <= 8'h51; // Q
++ 12'h12d : ascii <= 8'h52; // R
++ 12'h11b : ascii <= 8'h53; // S
++ 12'h12c : ascii <= 8'h54; // T
++ 12'h13c : ascii <= 8'h55; // U
++ 12'h12a : ascii <= 8'h56; // V
++ 12'h11d : ascii <= 8'h57; // W
++ 12'h122 : ascii <= 8'h58; // X
++ 12'h135 : ascii <= 8'h59; // Y
++ 12'h11a : ascii <= 8'h5a; // Z
++ 12'h054 : ascii <= 8'h5b; // [
++ 12'h05d : ascii <= 8'h5c; // \
++ 12'h05b : ascii <= 8'h5d; // ]
++ 12'h136 : ascii <= 8'h5e; // ^
++ 12'h14e : ascii <= 8'h5f; // _
++ 12'h00e : ascii <= 8'h60; // `
++ 12'h01c : ascii <= 8'h61; // a
++ 12'h032 : ascii <= 8'h62; // b
++ 12'h021 : ascii <= 8'h63; // c
++ 12'h023 : ascii <= 8'h64; // d
++ 12'h024 : ascii <= 8'h65; // e
++ 12'h02b : ascii <= 8'h66; // f
++ 12'h034 : ascii <= 8'h67; // g
++ 12'h033 : ascii <= 8'h68; // h
++ 12'h043 : ascii <= 8'h69; // i
++ 12'h03b : ascii <= 8'h6a; // j
++ 12'h042 : ascii <= 8'h6b; // k
++ 12'h04b : ascii <= 8'h6c; // l
++ 12'h03a : ascii <= 8'h6d; // m
++ 12'h031 : ascii <= 8'h6e; // n
++ 12'h044 : ascii <= 8'h6f; // o
++ 12'h04d : ascii <= 8'h70; // p
++ 12'h015 : ascii <= 8'h71; // q
++ 12'h02d : ascii <= 8'h72; // r
++ 12'h01b : ascii <= 8'h73; // s
++ 12'h02c : ascii <= 8'h74; // t
++ 12'h03c : ascii <= 8'h75; // u
++ 12'h02a : ascii <= 8'h76; // v
++ 12'h01d : ascii <= 8'h77; // w
++ 12'h022 : ascii <= 8'h78; // x
++ 12'h035 : ascii <= 8'h79; // y
++ 12'h01a : ascii <= 8'h7a; // z
++ 12'h154 : ascii <= 8'h7b; // {
++ 12'h15d : ascii <= 8'h7c; // |
++ 12'h15b : ascii <= 8'h7d; // }
++ 12'h10e : ascii <= 8'h7e; // ~
++ 12'h?71 : ascii <= 8'h7f; // (Delete OR DEL on numeric keypad)
++ default : ascii <= 8'h2e; // '.' used for unlisted characters.
++ endcase
++end
++
++
++endmodule
++
++//`undefine TOTAL_BITS
++//`undefine EXTEND_CODE
++//`undefine RELEASE_CODE
++//`undefine LEFT_SHIFT
++//`undefine RIGHT_SHIFT
++
diff --git a/de1/fpga-bbc-pq/master/line-endings.patch b/de1/fpga-bbc-pq/master/line-endings.patch
new file mode 100644
index 0000000..dd090b6
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/line-endings.patch
@@ -0,0 +1,17558 @@
+diff --git a/CII_Starter_pin_assignments.csv b/CII_Starter_pin_assignments.csv
+index f46adb0..3e1f8de 100644
+--- a/CII_Starter_pin_assignments.csv
++++ b/CII_Starter_pin_assignments.csv
+@@ -1,455 +1,455 @@
+-
+-# Note: The column header names should not be changed if you wish to import this .csv file into the Quartus II software.
+-
+-From,To,Assignment Name,Value,Enabled
+-,GPIO_0[0],Location,PIN_A13,Yes
+-,GPIO_0[1],Location,PIN_B13,Yes
+-,GPIO_0[2],Location,PIN_A14,Yes
+-,GPIO_0[3],Location,PIN_B14,Yes
+-,GPIO_0[4],Location,PIN_A15,Yes
+-,GPIO_0[5],Location,PIN_B15,Yes
+-,GPIO_0[6],Location,PIN_A16,Yes
+-,GPIO_0[7],Location,PIN_B16,Yes
+-,GPIO_0[8],Location,PIN_A17,Yes
+-,GPIO_0[9],Location,PIN_B17,Yes
+-,GPIO_0[10],Location,PIN_A18,Yes
+-,GPIO_0[11],Location,PIN_B18,Yes
+-,GPIO_0[12],Location,PIN_A19,Yes
+-,GPIO_0[13],Location,PIN_B19,Yes
+-,GPIO_0[14],Location,PIN_A20,Yes
+-,GPIO_0[15],Location,PIN_B20,Yes
+-,GPIO_0[16],Location,PIN_C21,Yes
+-,GPIO_0[17],Location,PIN_C22,Yes
+-,GPIO_0[18],Location,PIN_D21,Yes
+-,GPIO_0[19],Location,PIN_D22,Yes
+-,GPIO_0[20],Location,PIN_E21,Yes
+-,GPIO_0[21],Location,PIN_E22,Yes
+-,GPIO_0[22],Location,PIN_F21,Yes
+-,GPIO_0[23],Location,PIN_F22,Yes
+-,GPIO_0[24],Location,PIN_G21,Yes
+-,GPIO_0[25],Location,PIN_G22,Yes
+-,GPIO_0[26],Location,PIN_J21,Yes
+-,GPIO_0[27],Location,PIN_J22,Yes
+-,GPIO_0[28],Location,PIN_K21,Yes
+-,GPIO_0[29],Location,PIN_K22,Yes
+-,GPIO_0[30],Location,PIN_J19,Yes
+-,GPIO_0[31],Location,PIN_J20,Yes
+-,GPIO_0[32],Location,PIN_J18,Yes
+-,GPIO_0[33],Location,PIN_K20,Yes
+-,GPIO_0[34],Location,PIN_L19,Yes
+-,GPIO_0[35],Location,PIN_L18,Yes
+-,GPIO_1[0],Location,PIN_H12,Yes
+-,GPIO_1[1],Location,PIN_H13,Yes
+-,GPIO_1[2],Location,PIN_H14,Yes
+-,GPIO_1[3],Location,PIN_G15,Yes
+-,GPIO_1[4],Location,PIN_E14,Yes
+-,GPIO_1[5],Location,PIN_E15,Yes
+-,GPIO_1[6],Location,PIN_F15,Yes
+-,GPIO_1[7],Location,PIN_G16,Yes
+-,GPIO_1[8],Location,PIN_F12,Yes
+-,GPIO_1[9],Location,PIN_F13,Yes
+-,GPIO_1[10],Location,PIN_C14,Yes
+-,GPIO_1[11],Location,PIN_D14,Yes
+-,GPIO_1[12],Location,PIN_D15,Yes
+-,GPIO_1[13],Location,PIN_D16,Yes
+-,GPIO_1[14],Location,PIN_C17,Yes
+-,GPIO_1[15],Location,PIN_C18,Yes
+-,GPIO_1[16],Location,PIN_C19,Yes
+-,GPIO_1[17],Location,PIN_C20,Yes
+-,GPIO_1[18],Location,PIN_D19,Yes
+-,GPIO_1[19],Location,PIN_D20,Yes
+-,GPIO_1[20],Location,PIN_E20,Yes
+-,GPIO_1[21],Location,PIN_F20,Yes
+-,GPIO_1[22],Location,PIN_E19,Yes
+-,GPIO_1[23],Location,PIN_E18,Yes
+-,GPIO_1[24],Location,PIN_G20,Yes
+-,GPIO_1[25],Location,PIN_G18,Yes
+-,GPIO_1[26],Location,PIN_G17,Yes
+-,GPIO_1[27],Location,PIN_H17,Yes
+-,GPIO_1[28],Location,PIN_J15,Yes
+-,GPIO_1[29],Location,PIN_H18,Yes
+-,GPIO_1[30],Location,PIN_N22,Yes
+-,GPIO_1[31],Location,PIN_N21,Yes
+-,GPIO_1[32],Location,PIN_P15,Yes
+-,GPIO_1[33],Location,PIN_N15,Yes
+-,GPIO_1[34],Location,PIN_P17,Yes
+-,GPIO_1[35],Location,PIN_P18,Yes
+-,GPIO_0[0],I/O Standard,LVTTL,Yes
+-,GPIO_0[1],I/O Standard,LVTTL,Yes
+-,GPIO_0[2],I/O Standard,LVTTL,Yes
+-,GPIO_0[3],I/O Standard,LVTTL,Yes
+-,GPIO_0[4],I/O Standard,LVTTL,Yes
+-,GPIO_0[5],I/O Standard,LVTTL,Yes
+-,GPIO_0[6],I/O Standard,LVTTL,Yes
+-,GPIO_0[7],I/O Standard,LVTTL,Yes
+-,GPIO_0[8],I/O Standard,LVTTL,Yes
+-,GPIO_0[9],I/O Standard,LVTTL,Yes
+-,GPIO_0[10],I/O Standard,LVTTL,Yes
+-,GPIO_0[11],I/O Standard,LVTTL,Yes
+-,GPIO_0[12],I/O Standard,LVTTL,Yes
+-,GPIO_0[13],I/O Standard,LVTTL,Yes
+-,GPIO_0[14],I/O Standard,LVTTL,Yes
+-,GPIO_0[15],I/O Standard,LVTTL,Yes
+-,GPIO_0[16],I/O Standard,LVTTL,Yes
+-,GPIO_0[17],I/O Standard,LVTTL,Yes
+-,GPIO_0[18],I/O Standard,LVTTL,Yes
+-,GPIO_0[19],I/O Standard,LVTTL,Yes
+-,GPIO_0[20],I/O Standard,LVTTL,Yes
+-,GPIO_0[21],I/O Standard,LVTTL,Yes
+-,GPIO_0[22],I/O Standard,LVTTL,Yes
+-,GPIO_0[23],I/O Standard,LVTTL,Yes
+-,GPIO_0[24],I/O Standard,LVTTL,Yes
+-,GPIO_0[25],I/O Standard,LVTTL,Yes
+-,GPIO_0[26],I/O Standard,LVTTL,Yes
+-,GPIO_0[27],I/O Standard,LVTTL,Yes
+-,GPIO_0[28],I/O Standard,LVTTL,Yes
+-,GPIO_0[29],I/O Standard,LVTTL,Yes
+-,GPIO_0[30],I/O Standard,LVTTL,Yes
+-,GPIO_0[31],I/O Standard,LVTTL,Yes
+-,GPIO_0[32],I/O Standard,LVTTL,Yes
+-,GPIO_0[33],I/O Standard,LVTTL,Yes
+-,GPIO_0[34],I/O Standard,LVTTL,Yes
+-,GPIO_0[35],I/O Standard,LVTTL,Yes
+-,GPIO_1[0],I/O Standard,LVTTL,Yes
+-,GPIO_1[1],I/O Standard,LVTTL,Yes
+-,GPIO_1[2],I/O Standard,LVTTL,Yes
+-,GPIO_1[3],I/O Standard,LVTTL,Yes
+-,GPIO_1[4],I/O Standard,LVTTL,Yes
+-,GPIO_1[5],I/O Standard,LVTTL,Yes
+-,GPIO_1[6],I/O Standard,LVTTL,Yes
+-,GPIO_1[7],I/O Standard,LVTTL,Yes
+-,GPIO_1[8],I/O Standard,LVTTL,Yes
+-,GPIO_1[9],I/O Standard,LVTTL,Yes
+-,GPIO_1[10],I/O Standard,LVTTL,Yes
+-,GPIO_1[11],I/O Standard,LVTTL,Yes
+-,GPIO_1[12],I/O Standard,LVTTL,Yes
+-,GPIO_1[13],I/O Standard,LVTTL,Yes
+-,GPIO_1[14],I/O Standard,LVTTL,Yes
+-,GPIO_1[15],I/O Standard,LVTTL,Yes
+-,GPIO_1[16],I/O Standard,LVTTL,Yes
+-,GPIO_1[17],I/O Standard,LVTTL,Yes
+-,GPIO_1[18],I/O Standard,LVTTL,Yes
+-,GPIO_1[19],I/O Standard,LVTTL,Yes
+-,GPIO_1[20],I/O Standard,LVTTL,Yes
+-,GPIO_1[21],I/O Standard,LVTTL,Yes
+-,GPIO_1[22],I/O Standard,LVTTL,Yes
+-,GPIO_1[23],I/O Standard,LVTTL,Yes
+-,GPIO_1[24],I/O Standard,LVTTL,Yes
+-,GPIO_1[25],I/O Standard,LVTTL,Yes
+-,GPIO_1[26],I/O Standard,LVTTL,Yes
+-,GPIO_1[27],I/O Standard,LVTTL,Yes
+-,GPIO_1[28],I/O Standard,LVTTL,Yes
+-,GPIO_1[29],I/O Standard,LVTTL,Yes
+-,GPIO_1[30],I/O Standard,LVTTL,Yes
+-,GPIO_1[31],I/O Standard,LVTTL,Yes
+-,GPIO_1[32],I/O Standard,LVTTL,Yes
+-,GPIO_1[33],I/O Standard,LVTTL,Yes
+-,GPIO_1[34],I/O Standard,LVTTL,Yes
+-,GPIO_1[35],I/O Standard,LVTTL,Yes
+-,SW[0],Location,PIN_L22,Yes
+-,SW[1],Location,PIN_L21,Yes
+-,SW[2],Location,PIN_M22,Yes
+-,SW[3],Location,PIN_V12,Yes
+-,SW[4],Location,PIN_W12,Yes
+-,SW[5],Location,PIN_U12,Yes
+-,SW[6],Location,PIN_U11,Yes
+-,SW[7],Location,PIN_M2,Yes
+-,SW[8],Location,PIN_M1,Yes
+-,SW[9],Location,PIN_L2,Yes
+-,SW[0],I/O Standard,LVTTL,Yes
+-,SW[1],I/O Standard,LVTTL,Yes
+-,SW[2],I/O Standard,LVTTL,Yes
+-,SW[3],I/O Standard,LVTTL,Yes
+-,SW[4],I/O Standard,LVTTL,Yes
+-,SW[5],I/O Standard,LVTTL,Yes
+-,SW[6],I/O Standard,LVTTL,Yes
+-,SW[7],I/O Standard,LVTTL,Yes
+-,SW[8],I/O Standard,LVTTL,Yes
+-,SW[9],I/O Standard,LVTTL,Yes
+-,HEX0[0],Location,PIN_J2,Yes
+-,HEX0[1],Location,PIN_J1,Yes
+-,HEX0[2],Location,PIN_H2,Yes
+-,HEX0[3],Location,PIN_H1,Yes
+-,HEX0[4],Location,PIN_F2,Yes
+-,HEX0[5],Location,PIN_F1,Yes
+-,HEX0[6],Location,PIN_E2,Yes
+-,HEX1[0],Location,PIN_E1,Yes
+-,HEX1[1],Location,PIN_H6,Yes
+-,HEX1[2],Location,PIN_H5,Yes
+-,HEX1[3],Location,PIN_H4,Yes
+-,HEX1[4],Location,PIN_G3,Yes
+-,HEX1[5],Location,PIN_D2,Yes
+-,HEX1[6],Location,PIN_D1,Yes
+-,HEX2[0],Location,PIN_G5,Yes
+-,HEX2[1],Location,PIN_G6,Yes
+-,HEX2[2],Location,PIN_C2,Yes
+-,HEX2[3],Location,PIN_C1,Yes
+-,HEX2[4],Location,PIN_E3,Yes
+-,HEX2[5],Location,PIN_E4,Yes
+-,HEX2[6],Location,PIN_D3,Yes
+-,HEX3[0],Location,PIN_F4,Yes
+-,HEX3[1],Location,PIN_D5,Yes
+-,HEX3[2],Location,PIN_D6,Yes
+-,HEX3[3],Location,PIN_J4,Yes
+-,HEX3[4],Location,PIN_L8,Yes
+-,HEX3[5],Location,PIN_F3,Yes
+-,HEX3[6],Location,PIN_D4,Yes
+-,HEX0[0],I/O Standard,LVTTL,Yes
+-,HEX0[1],I/O Standard,LVTTL,Yes
+-,HEX0[2],I/O Standard,LVTTL,Yes
+-,HEX0[3],I/O Standard,LVTTL,Yes
+-,HEX0[4],I/O Standard,LVTTL,Yes
+-,HEX0[5],I/O Standard,LVTTL,Yes
+-,HEX0[6],I/O Standard,LVTTL,Yes
+-,HEX1[0],I/O Standard,LVTTL,Yes
+-,HEX1[1],I/O Standard,LVTTL,Yes
+-,HEX1[2],I/O Standard,LVTTL,Yes
+-,HEX1[3],I/O Standard,LVTTL,Yes
+-,HEX1[4],I/O Standard,LVTTL,Yes
+-,HEX1[5],I/O Standard,LVTTL,Yes
+-,HEX1[6],I/O Standard,LVTTL,Yes
+-,HEX2[0],I/O Standard,LVTTL,Yes
+-,HEX2[1],I/O Standard,LVTTL,Yes
+-,HEX2[2],I/O Standard,LVTTL,Yes
+-,HEX2[3],I/O Standard,LVTTL,Yes
+-,HEX2[4],I/O Standard,LVTTL,Yes
+-,HEX2[5],I/O Standard,LVTTL,Yes
+-,HEX2[6],I/O Standard,LVTTL,Yes
+-,HEX3[0],I/O Standard,LVTTL,Yes
+-,HEX3[1],I/O Standard,LVTTL,Yes
+-,HEX3[2],I/O Standard,LVTTL,Yes
+-,HEX3[3],I/O Standard,LVTTL,Yes
+-,HEX3[4],I/O Standard,LVTTL,Yes
+-,HEX3[5],I/O Standard,LVTTL,Yes
+-,HEX3[6],I/O Standard,LVTTL,Yes
+-,KEY[0],Location,PIN_R22,Yes
+-,KEY[1],Location,PIN_R21,Yes
+-,KEY[2],Location,PIN_T22,Yes
+-,KEY[3],Location,PIN_T21,Yes
+-,LEDR[0],Location,PIN_R20,Yes
+-,LEDR[1],Location,PIN_R19,Yes
+-,LEDR[2],Location,PIN_U19,Yes
+-,LEDR[3],Location,PIN_Y19,Yes
+-,LEDR[4],Location,PIN_T18,Yes
+-,LEDR[5],Location,PIN_V19,Yes
+-,LEDR[6],Location,PIN_Y18,Yes
+-,LEDR[7],Location,PIN_U18,Yes
+-,LEDR[8],Location,PIN_R18,Yes
+-,LEDR[9],Location,PIN_R17,Yes
+-,LEDG[0],Location,PIN_U22,Yes
+-,LEDG[1],Location,PIN_U21,Yes
+-,LEDG[2],Location,PIN_V22,Yes
+-,LEDG[3],Location,PIN_V21,Yes
+-,LEDG[4],Location,PIN_W22,Yes
+-,LEDG[5],Location,PIN_W21,Yes
+-,LEDG[6],Location,PIN_Y22,Yes
+-,LEDG[7],Location,PIN_Y21,Yes
+-,KEY[0],I/O Standard,LVTTL,Yes
+-,KEY[1],I/O Standard,LVTTL,Yes
+-,KEY[2],I/O Standard,LVTTL,Yes
+-,KEY[3],I/O Standard,LVTTL,Yes
+-,LEDR[0],I/O Standard,LVTTL,Yes
+-,LEDR[1],I/O Standard,LVTTL,Yes
+-,LEDR[2],I/O Standard,LVTTL,Yes
+-,LEDR[3],I/O Standard,LVTTL,Yes
+-,LEDR[4],I/O Standard,LVTTL,Yes
+-,LEDR[5],I/O Standard,LVTTL,Yes
+-,LEDR[6],I/O Standard,LVTTL,Yes
+-,LEDR[7],I/O Standard,LVTTL,Yes
+-,LEDR[8],I/O Standard,LVTTL,Yes
+-,LEDR[9],I/O Standard,LVTTL,Yes
+-,LEDG[0],I/O Standard,LVTTL,Yes
+-,LEDG[1],I/O Standard,LVTTL,Yes
+-,LEDG[2],I/O Standard,LVTTL,Yes
+-,LEDG[3],I/O Standard,LVTTL,Yes
+-,LEDG[4],I/O Standard,LVTTL,Yes
+-,LEDG[5],I/O Standard,LVTTL,Yes
+-,LEDG[6],I/O Standard,LVTTL,Yes
+-,LEDG[7],I/O Standard,LVTTL,Yes
+-,CLOCK_27[0],Location,PIN_D12,Yes
+-,CLOCK_27[1],Location,PIN_E12,Yes
+-,CLOCK_24[0],Location,PIN_B12,Yes
+-,CLOCK_24[1],Location,PIN_A12,Yes
+-,CLOCK_50,Location,PIN_L1,Yes
+-,EXT_CLOCK,Location,PIN_M21,Yes
+-,CLOCK_27[1],I/O Standard,LVTTL,Yes
+-,CLOCK_24[0],I/O Standard,LVTTL,Yes
+-,CLOCK_24[1],I/O Standard,LVTTL,Yes
+-,CLOCK_50,I/O Standard,LVTTL,Yes
+-,EXT_CLOCK,I/O Standard,LVTTL,Yes
+-,PS2_CLK,Location,PIN_H15,Yes
+-,PS2_DAT,Location,PIN_J14,Yes
+-,UART_RXD,Location,PIN_F14,Yes
+-,UART_TXD,Location,PIN_G12,Yes
+-,PS2_CLK,I/O Standard,LVTTL,Yes
+-,PS2_DAT,I/O Standard,LVTTL,Yes
+-,UART_RXD,I/O Standard,LVTTL,Yes
+-,UART_TXD,I/O Standard,LVTTL,Yes
+-,TDI,Location,PIN_E8,Yes
+-,TCS,Location,PIN_D8,Yes
+-,TCK,Location,PIN_C7,Yes
+-,TDO,Location,PIN_D7,Yes
+-,TDI,I/O Standard,LVTTL,Yes
+-,TCS,I/O Standard,LVTTL,Yes
+-,TCK,I/O Standard,LVTTL,Yes
+-,TDO,I/O Standard,LVTTL,Yes
+-,VGA_R[0],Location,PIN_D9,Yes
+-,VGA_R[1],Location,PIN_C9,Yes
+-,VGA_R[2],Location,PIN_A7,Yes
+-,VGA_R[3],Location,PIN_B7,Yes
+-,VGA_G[0],Location,PIN_B8,Yes
+-,VGA_G[1],Location,PIN_C10,Yes
+-,VGA_G[2],Location,PIN_B9,Yes
+-,VGA_G[3],Location,PIN_A8,Yes
+-,VGA_B[0],Location,PIN_A9,Yes
+-,VGA_B[1],Location,PIN_D11,Yes
+-,VGA_B[2],Location,PIN_A10,Yes
+-,VGA_B[3],Location,PIN_B10,Yes
+-,VGA_HS,Location,PIN_A11,Yes
+-,VGA_VS,Location,PIN_B11,Yes
+-,VGA_R[0],I/O Standard,LVTTL,Yes
+-,VGA_R[1],I/O Standard,LVTTL,Yes
+-,VGA_R[2],I/O Standard,LVTTL,Yes
+-,VGA_R[3],I/O Standard,LVTTL,Yes
+-,VGA_G[0],I/O Standard,LVTTL,Yes
+-,VGA_G[1],I/O Standard,LVTTL,Yes
+-,VGA_G[2],I/O Standard,LVTTL,Yes
+-,VGA_G[3],I/O Standard,LVTTL,Yes
+-,VGA_B[0],I/O Standard,LVTTL,Yes
+-,VGA_B[1],I/O Standard,LVTTL,Yes
+-,VGA_B[2],I/O Standard,LVTTL,Yes
+-,VGA_B[3],I/O Standard,LVTTL,Yes
+-,VGA_HS,I/O Standard,LVTTL,Yes
+-,VGA_VS,I/O Standard,LVTTL,Yes
+-,I2C_SCLK,Location,PIN_A3,Yes
+-,I2C_SDAT,Location,PIN_B3,Yes
+-,AUD_ADCLRCK,Location,PIN_A6,Yes
+-,AUD_ADCDAT,Location,PIN_B6,Yes
+-,AUD_DACLRCK,Location,PIN_A5,Yes
+-,AUD_DACDAT,Location,PIN_B5,Yes
+-,AUD_XCK,Location,PIN_B4,Yes
+-,AUD_BCLK,Location,PIN_A4,Yes
+-,I2C_SCLK,I/O Standard,LVTTL,Yes
+-,I2C_SDAT,I/O Standard,LVTTL,Yes
+-,AUD_ADCLRCK,I/O Standard,LVTTL,Yes
+-,AUD_ADCDAT,I/O Standard,LVTTL,Yes
+-,AUD_DACLRCK,I/O Standard,LVTTL,Yes
+-,AUD_DACDAT,I/O Standard,LVTTL,Yes
+-,AUD_XCK,I/O Standard,LVTTL,Yes
+-,AUD_BCLK,I/O Standard,LVTTL,Yes
+-,DRAM_ADDR[0],Location,PIN_W4,Yes
+-,DRAM_ADDR[1],Location,PIN_W5,Yes
+-,DRAM_ADDR[2],Location,PIN_Y3,Yes
+-,DRAM_ADDR[3],Location,PIN_Y4,Yes
+-,DRAM_ADDR[4],Location,PIN_R6,Yes
+-,DRAM_ADDR[5],Location,PIN_R5,Yes
+-,DRAM_ADDR[6],Location,PIN_P6,Yes
+-,DRAM_ADDR[7],Location,PIN_P5,Yes
+-,DRAM_ADDR[8],Location,PIN_P3,Yes
+-,DRAM_ADDR[9],Location,PIN_N4,Yes
+-,DRAM_ADDR[10],Location,PIN_W3,Yes
+-,DRAM_ADDR[11],Location,PIN_N6,Yes
+-,DRAM_BA_0,Location,PIN_U3,Yes
+-,DRAM_BA_1,Location,PIN_V4,Yes
+-,DRAM_CAS_N,Location,PIN_T3,Yes
+-,DRAM_CKE,Location,PIN_N3,Yes
+-,DRAM_CLK,Location,PIN_U4,Yes
+-,DRAM_CS_N,Location,PIN_T6,Yes
+-,DRAM_DQ[0],Location,PIN_U1,Yes
+-,DRAM_DQ[1],Location,PIN_U2,Yes
+-,DRAM_DQ[2],Location,PIN_V1,Yes
+-,DRAM_DQ[3],Location,PIN_V2,Yes
+-,DRAM_DQ[4],Location,PIN_W1,Yes
+-,DRAM_DQ[5],Location,PIN_W2,Yes
+-,DRAM_DQ[6],Location,PIN_Y1,Yes
+-,DRAM_DQ[7],Location,PIN_Y2,Yes
+-,DRAM_DQ[8],Location,PIN_N1,Yes
+-,DRAM_DQ[9],Location,PIN_N2,Yes
+-,DRAM_DQ[10],Location,PIN_P1,Yes
+-,DRAM_DQ[11],Location,PIN_P2,Yes
+-,DRAM_DQ[12],Location,PIN_R1,Yes
+-,DRAM_DQ[13],Location,PIN_R2,Yes
+-,DRAM_DQ[14],Location,PIN_T1,Yes
+-,DRAM_DQ[15],Location,PIN_T2,Yes
+-,DRAM_LDQM,Location,PIN_R7,Yes
+-,DRAM_RAS_N,Location,PIN_T5,Yes
+-,DRAM_UDQM,Location,PIN_M5,Yes
+-,DRAM_WE_N,Location,PIN_R8,Yes
+-,FL_ADDR[0],Location,PIN_AB20,Yes
+-,FL_ADDR[1],Location,PIN_AA14,Yes
+-,FL_ADDR[2],Location,PIN_Y16,Yes
+-,FL_ADDR[3],Location,PIN_R15,Yes
+-,FL_ADDR[4],Location,PIN_T15,Yes
+-,FL_ADDR[5],Location,PIN_U15,Yes
+-,FL_ADDR[6],Location,PIN_V15,Yes
+-,FL_ADDR[7],Location,PIN_W15,Yes
+-,FL_ADDR[8],Location,PIN_R14,Yes
+-,FL_ADDR[9],Location,PIN_Y13,Yes
+-,FL_ADDR[10],Location,PIN_R12,Yes
+-,FL_ADDR[11],Location,PIN_T12,Yes
+-,FL_ADDR[12],Location,PIN_AB14,Yes
+-,FL_ADDR[13],Location,PIN_AA13,Yes
+-,FL_ADDR[14],Location,PIN_AB13,Yes
+-,FL_ADDR[15],Location,PIN_AA12,Yes
+-,FL_ADDR[16],Location,PIN_AB12,Yes
+-,FL_ADDR[17],Location,PIN_AA20,Yes
+-,FL_ADDR[18],Location,PIN_U14,Yes
+-,FL_ADDR[19],Location,PIN_V14,Yes
+-,FL_ADDR[20],Location,PIN_U13,Yes
+-,FL_ADDR[21],Location,PIN_R13,Yes
+-,FL_DQ[0],Location,PIN_AB16,Yes
+-,FL_DQ[1],Location,PIN_AA16,Yes
+-,FL_DQ[2],Location,PIN_AB17,Yes
+-,FL_DQ[3],Location,PIN_AA17,Yes
+-,FL_DQ[4],Location,PIN_AB18,Yes
+-,FL_DQ[5],Location,PIN_AA18,Yes
+-,FL_DQ[6],Location,PIN_AB19,Yes
+-,FL_DQ[7],Location,PIN_AA19,Yes
+-,FL_OE_N,Location,PIN_AA15,Yes
+-,FL_RST_N,Location,PIN_W14,Yes
+-,FL_WE_N,Location,PIN_Y14,Yes
+-,FL_CE_N,Location,PIN_AB15,Yes
+-,SRAM_ADDR[0],Location,PIN_AA3,Yes
+-,SRAM_ADDR[1],Location,PIN_AB3,Yes
+-,SRAM_ADDR[2],Location,PIN_AA4,Yes
+-,SRAM_ADDR[3],Location,PIN_AB4,Yes
+-,SRAM_ADDR[4],Location,PIN_AA5,Yes
+-,SRAM_ADDR[5],Location,PIN_AB10,Yes
+-,SRAM_ADDR[6],Location,PIN_AA11,Yes
+-,SRAM_ADDR[7],Location,PIN_AB11,Yes
+-,SRAM_ADDR[8],Location,PIN_V11,Yes
+-,SRAM_ADDR[9],Location,PIN_W11,Yes
+-,SRAM_ADDR[10],Location,PIN_R11,Yes
+-,SRAM_ADDR[11],Location,PIN_T11,Yes
+-,SRAM_ADDR[12],Location,PIN_Y10,Yes
+-,SRAM_ADDR[13],Location,PIN_U10,Yes
+-,SRAM_ADDR[14],Location,PIN_R10,Yes
+-,SRAM_ADDR[15],Location,PIN_T7,Yes
+-,SRAM_ADDR[16],Location,PIN_Y6,Yes
+-,SRAM_ADDR[17],Location,PIN_Y5,Yes
+-,SRAM_CE_N,Location,PIN_AB5,Yes
+-,SRAM_DQ[0],Location,PIN_AA6,Yes
+-,SRAM_DQ[1],Location,PIN_AB6,Yes
+-,SRAM_DQ[2],Location,PIN_AA7,Yes
+-,SRAM_DQ[3],Location,PIN_AB7,Yes
+-,SRAM_DQ[4],Location,PIN_AA8,Yes
+-,SRAM_DQ[5],Location,PIN_AB8,Yes
+-,SRAM_DQ[6],Location,PIN_AA9,Yes
+-,SRAM_DQ[7],Location,PIN_AB9,Yes
+-,SRAM_DQ[8],Location,PIN_Y9,Yes
+-,SRAM_DQ[9],Location,PIN_W9,Yes
+-,SRAM_DQ[10],Location,PIN_V9,Yes
+-,SRAM_DQ[11],Location,PIN_U9,Yes
+-,SRAM_DQ[12],Location,PIN_R9,Yes
+-,SRAM_DQ[13],Location,PIN_W8,Yes
+-,SRAM_DQ[14],Location,PIN_V8,Yes
+-,SRAM_DQ[15],Location,PIN_U8,Yes
+-,SRAM_LB_N,Location,PIN_Y7,Yes
+-,SRAM_OE_N,Location,PIN_T8,Yes
+-,SRAM_UB_N,Location,PIN_W7,Yes
+-,SRAM_WE_N,Location,PIN_AA10,Yes
+-,SD_nCS,Location,PIN_U20,Yes
+-,SD_MOSI,Location,PIN_Y20,Yes
+-,SD_SCLK,Location,PIN_V20,Yes
+-,SD_MISO,Location,PIN_W20,Yes
+-
++
++# Note: The column header names should not be changed if you wish to import this .csv file into the Quartus II software.
++
++From,To,Assignment Name,Value,Enabled
++,GPIO_0[0],Location,PIN_A13,Yes
++,GPIO_0[1],Location,PIN_B13,Yes
++,GPIO_0[2],Location,PIN_A14,Yes
++,GPIO_0[3],Location,PIN_B14,Yes
++,GPIO_0[4],Location,PIN_A15,Yes
++,GPIO_0[5],Location,PIN_B15,Yes
++,GPIO_0[6],Location,PIN_A16,Yes
++,GPIO_0[7],Location,PIN_B16,Yes
++,GPIO_0[8],Location,PIN_A17,Yes
++,GPIO_0[9],Location,PIN_B17,Yes
++,GPIO_0[10],Location,PIN_A18,Yes
++,GPIO_0[11],Location,PIN_B18,Yes
++,GPIO_0[12],Location,PIN_A19,Yes
++,GPIO_0[13],Location,PIN_B19,Yes
++,GPIO_0[14],Location,PIN_A20,Yes
++,GPIO_0[15],Location,PIN_B20,Yes
++,GPIO_0[16],Location,PIN_C21,Yes
++,GPIO_0[17],Location,PIN_C22,Yes
++,GPIO_0[18],Location,PIN_D21,Yes
++,GPIO_0[19],Location,PIN_D22,Yes
++,GPIO_0[20],Location,PIN_E21,Yes
++,GPIO_0[21],Location,PIN_E22,Yes
++,GPIO_0[22],Location,PIN_F21,Yes
++,GPIO_0[23],Location,PIN_F22,Yes
++,GPIO_0[24],Location,PIN_G21,Yes
++,GPIO_0[25],Location,PIN_G22,Yes
++,GPIO_0[26],Location,PIN_J21,Yes
++,GPIO_0[27],Location,PIN_J22,Yes
++,GPIO_0[28],Location,PIN_K21,Yes
++,GPIO_0[29],Location,PIN_K22,Yes
++,GPIO_0[30],Location,PIN_J19,Yes
++,GPIO_0[31],Location,PIN_J20,Yes
++,GPIO_0[32],Location,PIN_J18,Yes
++,GPIO_0[33],Location,PIN_K20,Yes
++,GPIO_0[34],Location,PIN_L19,Yes
++,GPIO_0[35],Location,PIN_L18,Yes
++,GPIO_1[0],Location,PIN_H12,Yes
++,GPIO_1[1],Location,PIN_H13,Yes
++,GPIO_1[2],Location,PIN_H14,Yes
++,GPIO_1[3],Location,PIN_G15,Yes
++,GPIO_1[4],Location,PIN_E14,Yes
++,GPIO_1[5],Location,PIN_E15,Yes
++,GPIO_1[6],Location,PIN_F15,Yes
++,GPIO_1[7],Location,PIN_G16,Yes
++,GPIO_1[8],Location,PIN_F12,Yes
++,GPIO_1[9],Location,PIN_F13,Yes
++,GPIO_1[10],Location,PIN_C14,Yes
++,GPIO_1[11],Location,PIN_D14,Yes
++,GPIO_1[12],Location,PIN_D15,Yes
++,GPIO_1[13],Location,PIN_D16,Yes
++,GPIO_1[14],Location,PIN_C17,Yes
++,GPIO_1[15],Location,PIN_C18,Yes
++,GPIO_1[16],Location,PIN_C19,Yes
++,GPIO_1[17],Location,PIN_C20,Yes
++,GPIO_1[18],Location,PIN_D19,Yes
++,GPIO_1[19],Location,PIN_D20,Yes
++,GPIO_1[20],Location,PIN_E20,Yes
++,GPIO_1[21],Location,PIN_F20,Yes
++,GPIO_1[22],Location,PIN_E19,Yes
++,GPIO_1[23],Location,PIN_E18,Yes
++,GPIO_1[24],Location,PIN_G20,Yes
++,GPIO_1[25],Location,PIN_G18,Yes
++,GPIO_1[26],Location,PIN_G17,Yes
++,GPIO_1[27],Location,PIN_H17,Yes
++,GPIO_1[28],Location,PIN_J15,Yes
++,GPIO_1[29],Location,PIN_H18,Yes
++,GPIO_1[30],Location,PIN_N22,Yes
++,GPIO_1[31],Location,PIN_N21,Yes
++,GPIO_1[32],Location,PIN_P15,Yes
++,GPIO_1[33],Location,PIN_N15,Yes
++,GPIO_1[34],Location,PIN_P17,Yes
++,GPIO_1[35],Location,PIN_P18,Yes
++,GPIO_0[0],I/O Standard,LVTTL,Yes
++,GPIO_0[1],I/O Standard,LVTTL,Yes
++,GPIO_0[2],I/O Standard,LVTTL,Yes
++,GPIO_0[3],I/O Standard,LVTTL,Yes
++,GPIO_0[4],I/O Standard,LVTTL,Yes
++,GPIO_0[5],I/O Standard,LVTTL,Yes
++,GPIO_0[6],I/O Standard,LVTTL,Yes
++,GPIO_0[7],I/O Standard,LVTTL,Yes
++,GPIO_0[8],I/O Standard,LVTTL,Yes
++,GPIO_0[9],I/O Standard,LVTTL,Yes
++,GPIO_0[10],I/O Standard,LVTTL,Yes
++,GPIO_0[11],I/O Standard,LVTTL,Yes
++,GPIO_0[12],I/O Standard,LVTTL,Yes
++,GPIO_0[13],I/O Standard,LVTTL,Yes
++,GPIO_0[14],I/O Standard,LVTTL,Yes
++,GPIO_0[15],I/O Standard,LVTTL,Yes
++,GPIO_0[16],I/O Standard,LVTTL,Yes
++,GPIO_0[17],I/O Standard,LVTTL,Yes
++,GPIO_0[18],I/O Standard,LVTTL,Yes
++,GPIO_0[19],I/O Standard,LVTTL,Yes
++,GPIO_0[20],I/O Standard,LVTTL,Yes
++,GPIO_0[21],I/O Standard,LVTTL,Yes
++,GPIO_0[22],I/O Standard,LVTTL,Yes
++,GPIO_0[23],I/O Standard,LVTTL,Yes
++,GPIO_0[24],I/O Standard,LVTTL,Yes
++,GPIO_0[25],I/O Standard,LVTTL,Yes
++,GPIO_0[26],I/O Standard,LVTTL,Yes
++,GPIO_0[27],I/O Standard,LVTTL,Yes
++,GPIO_0[28],I/O Standard,LVTTL,Yes
++,GPIO_0[29],I/O Standard,LVTTL,Yes
++,GPIO_0[30],I/O Standard,LVTTL,Yes
++,GPIO_0[31],I/O Standard,LVTTL,Yes
++,GPIO_0[32],I/O Standard,LVTTL,Yes
++,GPIO_0[33],I/O Standard,LVTTL,Yes
++,GPIO_0[34],I/O Standard,LVTTL,Yes
++,GPIO_0[35],I/O Standard,LVTTL,Yes
++,GPIO_1[0],I/O Standard,LVTTL,Yes
++,GPIO_1[1],I/O Standard,LVTTL,Yes
++,GPIO_1[2],I/O Standard,LVTTL,Yes
++,GPIO_1[3],I/O Standard,LVTTL,Yes
++,GPIO_1[4],I/O Standard,LVTTL,Yes
++,GPIO_1[5],I/O Standard,LVTTL,Yes
++,GPIO_1[6],I/O Standard,LVTTL,Yes
++,GPIO_1[7],I/O Standard,LVTTL,Yes
++,GPIO_1[8],I/O Standard,LVTTL,Yes
++,GPIO_1[9],I/O Standard,LVTTL,Yes
++,GPIO_1[10],I/O Standard,LVTTL,Yes
++,GPIO_1[11],I/O Standard,LVTTL,Yes
++,GPIO_1[12],I/O Standard,LVTTL,Yes
++,GPIO_1[13],I/O Standard,LVTTL,Yes
++,GPIO_1[14],I/O Standard,LVTTL,Yes
++,GPIO_1[15],I/O Standard,LVTTL,Yes
++,GPIO_1[16],I/O Standard,LVTTL,Yes
++,GPIO_1[17],I/O Standard,LVTTL,Yes
++,GPIO_1[18],I/O Standard,LVTTL,Yes
++,GPIO_1[19],I/O Standard,LVTTL,Yes
++,GPIO_1[20],I/O Standard,LVTTL,Yes
++,GPIO_1[21],I/O Standard,LVTTL,Yes
++,GPIO_1[22],I/O Standard,LVTTL,Yes
++,GPIO_1[23],I/O Standard,LVTTL,Yes
++,GPIO_1[24],I/O Standard,LVTTL,Yes
++,GPIO_1[25],I/O Standard,LVTTL,Yes
++,GPIO_1[26],I/O Standard,LVTTL,Yes
++,GPIO_1[27],I/O Standard,LVTTL,Yes
++,GPIO_1[28],I/O Standard,LVTTL,Yes
++,GPIO_1[29],I/O Standard,LVTTL,Yes
++,GPIO_1[30],I/O Standard,LVTTL,Yes
++,GPIO_1[31],I/O Standard,LVTTL,Yes
++,GPIO_1[32],I/O Standard,LVTTL,Yes
++,GPIO_1[33],I/O Standard,LVTTL,Yes
++,GPIO_1[34],I/O Standard,LVTTL,Yes
++,GPIO_1[35],I/O Standard,LVTTL,Yes
++,SW[0],Location,PIN_L22,Yes
++,SW[1],Location,PIN_L21,Yes
++,SW[2],Location,PIN_M22,Yes
++,SW[3],Location,PIN_V12,Yes
++,SW[4],Location,PIN_W12,Yes
++,SW[5],Location,PIN_U12,Yes
++,SW[6],Location,PIN_U11,Yes
++,SW[7],Location,PIN_M2,Yes
++,SW[8],Location,PIN_M1,Yes
++,SW[9],Location,PIN_L2,Yes
++,SW[0],I/O Standard,LVTTL,Yes
++,SW[1],I/O Standard,LVTTL,Yes
++,SW[2],I/O Standard,LVTTL,Yes
++,SW[3],I/O Standard,LVTTL,Yes
++,SW[4],I/O Standard,LVTTL,Yes
++,SW[5],I/O Standard,LVTTL,Yes
++,SW[6],I/O Standard,LVTTL,Yes
++,SW[7],I/O Standard,LVTTL,Yes
++,SW[8],I/O Standard,LVTTL,Yes
++,SW[9],I/O Standard,LVTTL,Yes
++,HEX0[0],Location,PIN_J2,Yes
++,HEX0[1],Location,PIN_J1,Yes
++,HEX0[2],Location,PIN_H2,Yes
++,HEX0[3],Location,PIN_H1,Yes
++,HEX0[4],Location,PIN_F2,Yes
++,HEX0[5],Location,PIN_F1,Yes
++,HEX0[6],Location,PIN_E2,Yes
++,HEX1[0],Location,PIN_E1,Yes
++,HEX1[1],Location,PIN_H6,Yes
++,HEX1[2],Location,PIN_H5,Yes
++,HEX1[3],Location,PIN_H4,Yes
++,HEX1[4],Location,PIN_G3,Yes
++,HEX1[5],Location,PIN_D2,Yes
++,HEX1[6],Location,PIN_D1,Yes
++,HEX2[0],Location,PIN_G5,Yes
++,HEX2[1],Location,PIN_G6,Yes
++,HEX2[2],Location,PIN_C2,Yes
++,HEX2[3],Location,PIN_C1,Yes
++,HEX2[4],Location,PIN_E3,Yes
++,HEX2[5],Location,PIN_E4,Yes
++,HEX2[6],Location,PIN_D3,Yes
++,HEX3[0],Location,PIN_F4,Yes
++,HEX3[1],Location,PIN_D5,Yes
++,HEX3[2],Location,PIN_D6,Yes
++,HEX3[3],Location,PIN_J4,Yes
++,HEX3[4],Location,PIN_L8,Yes
++,HEX3[5],Location,PIN_F3,Yes
++,HEX3[6],Location,PIN_D4,Yes
++,HEX0[0],I/O Standard,LVTTL,Yes
++,HEX0[1],I/O Standard,LVTTL,Yes
++,HEX0[2],I/O Standard,LVTTL,Yes
++,HEX0[3],I/O Standard,LVTTL,Yes
++,HEX0[4],I/O Standard,LVTTL,Yes
++,HEX0[5],I/O Standard,LVTTL,Yes
++,HEX0[6],I/O Standard,LVTTL,Yes
++,HEX1[0],I/O Standard,LVTTL,Yes
++,HEX1[1],I/O Standard,LVTTL,Yes
++,HEX1[2],I/O Standard,LVTTL,Yes
++,HEX1[3],I/O Standard,LVTTL,Yes
++,HEX1[4],I/O Standard,LVTTL,Yes
++,HEX1[5],I/O Standard,LVTTL,Yes
++,HEX1[6],I/O Standard,LVTTL,Yes
++,HEX2[0],I/O Standard,LVTTL,Yes
++,HEX2[1],I/O Standard,LVTTL,Yes
++,HEX2[2],I/O Standard,LVTTL,Yes
++,HEX2[3],I/O Standard,LVTTL,Yes
++,HEX2[4],I/O Standard,LVTTL,Yes
++,HEX2[5],I/O Standard,LVTTL,Yes
++,HEX2[6],I/O Standard,LVTTL,Yes
++,HEX3[0],I/O Standard,LVTTL,Yes
++,HEX3[1],I/O Standard,LVTTL,Yes
++,HEX3[2],I/O Standard,LVTTL,Yes
++,HEX3[3],I/O Standard,LVTTL,Yes
++,HEX3[4],I/O Standard,LVTTL,Yes
++,HEX3[5],I/O Standard,LVTTL,Yes
++,HEX3[6],I/O Standard,LVTTL,Yes
++,KEY[0],Location,PIN_R22,Yes
++,KEY[1],Location,PIN_R21,Yes
++,KEY[2],Location,PIN_T22,Yes
++,KEY[3],Location,PIN_T21,Yes
++,LEDR[0],Location,PIN_R20,Yes
++,LEDR[1],Location,PIN_R19,Yes
++,LEDR[2],Location,PIN_U19,Yes
++,LEDR[3],Location,PIN_Y19,Yes
++,LEDR[4],Location,PIN_T18,Yes
++,LEDR[5],Location,PIN_V19,Yes
++,LEDR[6],Location,PIN_Y18,Yes
++,LEDR[7],Location,PIN_U18,Yes
++,LEDR[8],Location,PIN_R18,Yes
++,LEDR[9],Location,PIN_R17,Yes
++,LEDG[0],Location,PIN_U22,Yes
++,LEDG[1],Location,PIN_U21,Yes
++,LEDG[2],Location,PIN_V22,Yes
++,LEDG[3],Location,PIN_V21,Yes
++,LEDG[4],Location,PIN_W22,Yes
++,LEDG[5],Location,PIN_W21,Yes
++,LEDG[6],Location,PIN_Y22,Yes
++,LEDG[7],Location,PIN_Y21,Yes
++,KEY[0],I/O Standard,LVTTL,Yes
++,KEY[1],I/O Standard,LVTTL,Yes
++,KEY[2],I/O Standard,LVTTL,Yes
++,KEY[3],I/O Standard,LVTTL,Yes
++,LEDR[0],I/O Standard,LVTTL,Yes
++,LEDR[1],I/O Standard,LVTTL,Yes
++,LEDR[2],I/O Standard,LVTTL,Yes
++,LEDR[3],I/O Standard,LVTTL,Yes
++,LEDR[4],I/O Standard,LVTTL,Yes
++,LEDR[5],I/O Standard,LVTTL,Yes
++,LEDR[6],I/O Standard,LVTTL,Yes
++,LEDR[7],I/O Standard,LVTTL,Yes
++,LEDR[8],I/O Standard,LVTTL,Yes
++,LEDR[9],I/O Standard,LVTTL,Yes
++,LEDG[0],I/O Standard,LVTTL,Yes
++,LEDG[1],I/O Standard,LVTTL,Yes
++,LEDG[2],I/O Standard,LVTTL,Yes
++,LEDG[3],I/O Standard,LVTTL,Yes
++,LEDG[4],I/O Standard,LVTTL,Yes
++,LEDG[5],I/O Standard,LVTTL,Yes
++,LEDG[6],I/O Standard,LVTTL,Yes
++,LEDG[7],I/O Standard,LVTTL,Yes
++,CLOCK_27[0],Location,PIN_D12,Yes
++,CLOCK_27[1],Location,PIN_E12,Yes
++,CLOCK_24[0],Location,PIN_B12,Yes
++,CLOCK_24[1],Location,PIN_A12,Yes
++,CLOCK_50,Location,PIN_L1,Yes
++,EXT_CLOCK,Location,PIN_M21,Yes
++,CLOCK_27[1],I/O Standard,LVTTL,Yes
++,CLOCK_24[0],I/O Standard,LVTTL,Yes
++,CLOCK_24[1],I/O Standard,LVTTL,Yes
++,CLOCK_50,I/O Standard,LVTTL,Yes
++,EXT_CLOCK,I/O Standard,LVTTL,Yes
++,PS2_CLK,Location,PIN_H15,Yes
++,PS2_DAT,Location,PIN_J14,Yes
++,UART_RXD,Location,PIN_F14,Yes
++,UART_TXD,Location,PIN_G12,Yes
++,PS2_CLK,I/O Standard,LVTTL,Yes
++,PS2_DAT,I/O Standard,LVTTL,Yes
++,UART_RXD,I/O Standard,LVTTL,Yes
++,UART_TXD,I/O Standard,LVTTL,Yes
++,TDI,Location,PIN_E8,Yes
++,TCS,Location,PIN_D8,Yes
++,TCK,Location,PIN_C7,Yes
++,TDO,Location,PIN_D7,Yes
++,TDI,I/O Standard,LVTTL,Yes
++,TCS,I/O Standard,LVTTL,Yes
++,TCK,I/O Standard,LVTTL,Yes
++,TDO,I/O Standard,LVTTL,Yes
++,VGA_R[0],Location,PIN_D9,Yes
++,VGA_R[1],Location,PIN_C9,Yes
++,VGA_R[2],Location,PIN_A7,Yes
++,VGA_R[3],Location,PIN_B7,Yes
++,VGA_G[0],Location,PIN_B8,Yes
++,VGA_G[1],Location,PIN_C10,Yes
++,VGA_G[2],Location,PIN_B9,Yes
++,VGA_G[3],Location,PIN_A8,Yes
++,VGA_B[0],Location,PIN_A9,Yes
++,VGA_B[1],Location,PIN_D11,Yes
++,VGA_B[2],Location,PIN_A10,Yes
++,VGA_B[3],Location,PIN_B10,Yes
++,VGA_HS,Location,PIN_A11,Yes
++,VGA_VS,Location,PIN_B11,Yes
++,VGA_R[0],I/O Standard,LVTTL,Yes
++,VGA_R[1],I/O Standard,LVTTL,Yes
++,VGA_R[2],I/O Standard,LVTTL,Yes
++,VGA_R[3],I/O Standard,LVTTL,Yes
++,VGA_G[0],I/O Standard,LVTTL,Yes
++,VGA_G[1],I/O Standard,LVTTL,Yes
++,VGA_G[2],I/O Standard,LVTTL,Yes
++,VGA_G[3],I/O Standard,LVTTL,Yes
++,VGA_B[0],I/O Standard,LVTTL,Yes
++,VGA_B[1],I/O Standard,LVTTL,Yes
++,VGA_B[2],I/O Standard,LVTTL,Yes
++,VGA_B[3],I/O Standard,LVTTL,Yes
++,VGA_HS,I/O Standard,LVTTL,Yes
++,VGA_VS,I/O Standard,LVTTL,Yes
++,I2C_SCLK,Location,PIN_A3,Yes
++,I2C_SDAT,Location,PIN_B3,Yes
++,AUD_ADCLRCK,Location,PIN_A6,Yes
++,AUD_ADCDAT,Location,PIN_B6,Yes
++,AUD_DACLRCK,Location,PIN_A5,Yes
++,AUD_DACDAT,Location,PIN_B5,Yes
++,AUD_XCK,Location,PIN_B4,Yes
++,AUD_BCLK,Location,PIN_A4,Yes
++,I2C_SCLK,I/O Standard,LVTTL,Yes
++,I2C_SDAT,I/O Standard,LVTTL,Yes
++,AUD_ADCLRCK,I/O Standard,LVTTL,Yes
++,AUD_ADCDAT,I/O Standard,LVTTL,Yes
++,AUD_DACLRCK,I/O Standard,LVTTL,Yes
++,AUD_DACDAT,I/O Standard,LVTTL,Yes
++,AUD_XCK,I/O Standard,LVTTL,Yes
++,AUD_BCLK,I/O Standard,LVTTL,Yes
++,DRAM_ADDR[0],Location,PIN_W4,Yes
++,DRAM_ADDR[1],Location,PIN_W5,Yes
++,DRAM_ADDR[2],Location,PIN_Y3,Yes
++,DRAM_ADDR[3],Location,PIN_Y4,Yes
++,DRAM_ADDR[4],Location,PIN_R6,Yes
++,DRAM_ADDR[5],Location,PIN_R5,Yes
++,DRAM_ADDR[6],Location,PIN_P6,Yes
++,DRAM_ADDR[7],Location,PIN_P5,Yes
++,DRAM_ADDR[8],Location,PIN_P3,Yes
++,DRAM_ADDR[9],Location,PIN_N4,Yes
++,DRAM_ADDR[10],Location,PIN_W3,Yes
++,DRAM_ADDR[11],Location,PIN_N6,Yes
++,DRAM_BA_0,Location,PIN_U3,Yes
++,DRAM_BA_1,Location,PIN_V4,Yes
++,DRAM_CAS_N,Location,PIN_T3,Yes
++,DRAM_CKE,Location,PIN_N3,Yes
++,DRAM_CLK,Location,PIN_U4,Yes
++,DRAM_CS_N,Location,PIN_T6,Yes
++,DRAM_DQ[0],Location,PIN_U1,Yes
++,DRAM_DQ[1],Location,PIN_U2,Yes
++,DRAM_DQ[2],Location,PIN_V1,Yes
++,DRAM_DQ[3],Location,PIN_V2,Yes
++,DRAM_DQ[4],Location,PIN_W1,Yes
++,DRAM_DQ[5],Location,PIN_W2,Yes
++,DRAM_DQ[6],Location,PIN_Y1,Yes
++,DRAM_DQ[7],Location,PIN_Y2,Yes
++,DRAM_DQ[8],Location,PIN_N1,Yes
++,DRAM_DQ[9],Location,PIN_N2,Yes
++,DRAM_DQ[10],Location,PIN_P1,Yes
++,DRAM_DQ[11],Location,PIN_P2,Yes
++,DRAM_DQ[12],Location,PIN_R1,Yes
++,DRAM_DQ[13],Location,PIN_R2,Yes
++,DRAM_DQ[14],Location,PIN_T1,Yes
++,DRAM_DQ[15],Location,PIN_T2,Yes
++,DRAM_LDQM,Location,PIN_R7,Yes
++,DRAM_RAS_N,Location,PIN_T5,Yes
++,DRAM_UDQM,Location,PIN_M5,Yes
++,DRAM_WE_N,Location,PIN_R8,Yes
++,FL_ADDR[0],Location,PIN_AB20,Yes
++,FL_ADDR[1],Location,PIN_AA14,Yes
++,FL_ADDR[2],Location,PIN_Y16,Yes
++,FL_ADDR[3],Location,PIN_R15,Yes
++,FL_ADDR[4],Location,PIN_T15,Yes
++,FL_ADDR[5],Location,PIN_U15,Yes
++,FL_ADDR[6],Location,PIN_V15,Yes
++,FL_ADDR[7],Location,PIN_W15,Yes
++,FL_ADDR[8],Location,PIN_R14,Yes
++,FL_ADDR[9],Location,PIN_Y13,Yes
++,FL_ADDR[10],Location,PIN_R12,Yes
++,FL_ADDR[11],Location,PIN_T12,Yes
++,FL_ADDR[12],Location,PIN_AB14,Yes
++,FL_ADDR[13],Location,PIN_AA13,Yes
++,FL_ADDR[14],Location,PIN_AB13,Yes
++,FL_ADDR[15],Location,PIN_AA12,Yes
++,FL_ADDR[16],Location,PIN_AB12,Yes
++,FL_ADDR[17],Location,PIN_AA20,Yes
++,FL_ADDR[18],Location,PIN_U14,Yes
++,FL_ADDR[19],Location,PIN_V14,Yes
++,FL_ADDR[20],Location,PIN_U13,Yes
++,FL_ADDR[21],Location,PIN_R13,Yes
++,FL_DQ[0],Location,PIN_AB16,Yes
++,FL_DQ[1],Location,PIN_AA16,Yes
++,FL_DQ[2],Location,PIN_AB17,Yes
++,FL_DQ[3],Location,PIN_AA17,Yes
++,FL_DQ[4],Location,PIN_AB18,Yes
++,FL_DQ[5],Location,PIN_AA18,Yes
++,FL_DQ[6],Location,PIN_AB19,Yes
++,FL_DQ[7],Location,PIN_AA19,Yes
++,FL_OE_N,Location,PIN_AA15,Yes
++,FL_RST_N,Location,PIN_W14,Yes
++,FL_WE_N,Location,PIN_Y14,Yes
++,FL_CE_N,Location,PIN_AB15,Yes
++,SRAM_ADDR[0],Location,PIN_AA3,Yes
++,SRAM_ADDR[1],Location,PIN_AB3,Yes
++,SRAM_ADDR[2],Location,PIN_AA4,Yes
++,SRAM_ADDR[3],Location,PIN_AB4,Yes
++,SRAM_ADDR[4],Location,PIN_AA5,Yes
++,SRAM_ADDR[5],Location,PIN_AB10,Yes
++,SRAM_ADDR[6],Location,PIN_AA11,Yes
++,SRAM_ADDR[7],Location,PIN_AB11,Yes
++,SRAM_ADDR[8],Location,PIN_V11,Yes
++,SRAM_ADDR[9],Location,PIN_W11,Yes
++,SRAM_ADDR[10],Location,PIN_R11,Yes
++,SRAM_ADDR[11],Location,PIN_T11,Yes
++,SRAM_ADDR[12],Location,PIN_Y10,Yes
++,SRAM_ADDR[13],Location,PIN_U10,Yes
++,SRAM_ADDR[14],Location,PIN_R10,Yes
++,SRAM_ADDR[15],Location,PIN_T7,Yes
++,SRAM_ADDR[16],Location,PIN_Y6,Yes
++,SRAM_ADDR[17],Location,PIN_Y5,Yes
++,SRAM_CE_N,Location,PIN_AB5,Yes
++,SRAM_DQ[0],Location,PIN_AA6,Yes
++,SRAM_DQ[1],Location,PIN_AB6,Yes
++,SRAM_DQ[2],Location,PIN_AA7,Yes
++,SRAM_DQ[3],Location,PIN_AB7,Yes
++,SRAM_DQ[4],Location,PIN_AA8,Yes
++,SRAM_DQ[5],Location,PIN_AB8,Yes
++,SRAM_DQ[6],Location,PIN_AA9,Yes
++,SRAM_DQ[7],Location,PIN_AB9,Yes
++,SRAM_DQ[8],Location,PIN_Y9,Yes
++,SRAM_DQ[9],Location,PIN_W9,Yes
++,SRAM_DQ[10],Location,PIN_V9,Yes
++,SRAM_DQ[11],Location,PIN_U9,Yes
++,SRAM_DQ[12],Location,PIN_R9,Yes
++,SRAM_DQ[13],Location,PIN_W8,Yes
++,SRAM_DQ[14],Location,PIN_V8,Yes
++,SRAM_DQ[15],Location,PIN_U8,Yes
++,SRAM_LB_N,Location,PIN_Y7,Yes
++,SRAM_OE_N,Location,PIN_T8,Yes
++,SRAM_UB_N,Location,PIN_W7,Yes
++,SRAM_WE_N,Location,PIN_AA10,Yes
++,SD_nCS,Location,PIN_U20,Yes
++,SD_MOSI,Location,PIN_Y20,Yes
++,SD_SCLK,Location,PIN_V20,Yes
++,SD_MISO,Location,PIN_W20,Yes
++
+diff --git a/T65/T65.vhd b/T65/T65.vhd
+index 4a21d79..09253fe 100644
+--- a/T65/T65.vhd
++++ b/T65/T65.vhd
+@@ -1,564 +1,564 @@
+--- ****
+--- T65(b) core. In an effort to merge and maintain bug fixes ....
+---
+---
+--- Ver 301 more merging
+--- Ver 300 Bugfixes by ehenciak added, started tidyup *bust*
+--- MikeJ March 2005
+--- Latest version from www.fpgaarcade.com (original www.opencores.org)
+---
+--- ****
+---
+--- 65xx compatible microprocessor core
+---
+--- Version : 0246
+---
+--- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- Please report bugs to the author, but before you do so, please
+--- make sure that this is not a derivative work and that
+--- you have the latest version of this file.
+---
+--- The latest version of this file can be found at:
+--- http://www.opencores.org/cvsweb.shtml/t65/
+---
+--- Limitations :
+---
+--- 65C02 and 65C816 modes are incomplete
+--- Undocumented instructions are not supported
+--- Some interface signals behaves incorrect
+---
+--- File history :
+---
+--- 0246 : First release
+---
+-
+-library IEEE;
+- use IEEE.std_logic_1164.all;
+- use IEEE.numeric_std.all;
+- use work.T65_Pack.all;
+-
+--- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use
+--- the ready signal to limit the CPU.
+-entity T65 is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
+- Res_n : in std_logic;
+- Enable : in std_logic;
+- Clk : in std_logic;
+- Rdy : in std_logic;
+- Abort_n : in std_logic;
+- IRQ_n : in std_logic;
+- NMI_n : in std_logic;
+- SO_n : in std_logic;
+- R_W_n : out std_logic;
+- Sync : out std_logic;
+- EF : out std_logic;
+- MF : out std_logic;
+- XF : out std_logic;
+- ML_n : out std_logic;
+- VP_n : out std_logic;
+- VDA : out std_logic;
+- VPA : out std_logic;
+- A : out std_logic_vector(23 downto 0);
+- DI : in std_logic_vector(7 downto 0);
+- DO : out std_logic_vector(7 downto 0)
+- );
+-end T65;
+-
+-architecture rtl of T65 is
+-
+- -- Registers
+- signal ABC, X, Y, D : std_logic_vector(15 downto 0);
+- signal P, AD, DL : std_logic_vector(7 downto 0) := x"00";
+- signal BAH : std_logic_vector(7 downto 0);
+- signal BAL : std_logic_vector(8 downto 0);
+- signal PBR : std_logic_vector(7 downto 0);
+- signal DBR : std_logic_vector(7 downto 0);
+- signal PC : unsigned(15 downto 0);
+- signal S : unsigned(15 downto 0);
+- signal EF_i : std_logic;
+- signal MF_i : std_logic;
+- signal XF_i : std_logic;
+-
+- signal IR : std_logic_vector(7 downto 0);
+- signal MCycle : std_logic_vector(2 downto 0);
+-
+- signal Mode_r : std_logic_vector(1 downto 0);
+- signal ALU_Op_r : std_logic_vector(3 downto 0);
+- signal Write_Data_r : std_logic_vector(2 downto 0);
+- signal Set_Addr_To_r : std_logic_vector(1 downto 0);
+- signal PCAdder : unsigned(8 downto 0);
+-
+- signal RstCycle : std_logic;
+- signal IRQCycle : std_logic;
+- signal NMICycle : std_logic;
+-
+- signal B_o : std_logic;
+- signal SO_n_o : std_logic;
+- signal IRQ_n_o : std_logic;
+- signal NMI_n_o : std_logic;
+- signal NMIAct : std_logic;
+-
+- signal Break : std_logic;
+-
+- -- ALU signals
+- signal BusA : std_logic_vector(7 downto 0);
+- signal BusA_r : std_logic_vector(7 downto 0);
+- signal BusB : std_logic_vector(7 downto 0);
+- signal ALU_Q : std_logic_vector(7 downto 0);
+- signal P_Out : std_logic_vector(7 downto 0);
+-
+- -- Micro code outputs
+- signal LCycle : std_logic_vector(2 downto 0);
+- signal ALU_Op : std_logic_vector(3 downto 0);
+- signal Set_BusA_To : std_logic_vector(2 downto 0);
+- signal Set_Addr_To : std_logic_vector(1 downto 0);
+- signal Write_Data : std_logic_vector(2 downto 0);
+- signal Jump : std_logic_vector(1 downto 0);
+- signal BAAdd : std_logic_vector(1 downto 0);
+- signal BreakAtNA : std_logic;
+- signal ADAdd : std_logic;
+- signal AddY : std_logic;
+- signal PCAdd : std_logic;
+- signal Inc_S : std_logic;
+- signal Dec_S : std_logic;
+- signal LDA : std_logic;
+- signal LDP : std_logic;
+- signal LDX : std_logic;
+- signal LDY : std_logic;
+- signal LDS : std_logic;
+- signal LDDI : std_logic;
+- signal LDALU : std_logic;
+- signal LDAD : std_logic;
+- signal LDBAL : std_logic;
+- signal LDBAH : std_logic;
+- signal SaveP : std_logic;
+- signal Write : std_logic;
+-
+- signal really_rdy : std_logic;
+- signal R_W_n_i : std_logic;
+-
+-begin
+- -- ehenciak : gate Rdy with read/write to make an "OK, it's
+- -- really OK to stop the processor now if Rdy is
+- -- deasserted" signal
+- really_rdy <= Rdy or not(R_W_n_i);
+-
+- -- ehenciak : Drive R_W_n_i off chip.
+- R_W_n <= R_W_n_i;
+-
+- Sync <= '1' when MCycle = "000" else '0';
+- EF <= EF_i;
+- MF <= MF_i;
+- XF <= XF_i;
+- ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1';
+- VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1';
+- VDA <= '1' when Set_Addr_To_r /= "00" else '0'; -- Incorrect !!!!!!!!!!!!
+- VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!!
+-
+- mcode : T65_MCode
+- port map(
+- Mode => Mode_r,
+- IR => IR,
+- MCycle => MCycle,
+- P => P,
+- LCycle => LCycle,
+- ALU_Op => ALU_Op,
+- Set_BusA_To => Set_BusA_To,
+- Set_Addr_To => Set_Addr_To,
+- Write_Data => Write_Data,
+- Jump => Jump,
+- BAAdd => BAAdd,
+- BreakAtNA => BreakAtNA,
+- ADAdd => ADAdd,
+- AddY => AddY,
+- PCAdd => PCAdd,
+- Inc_S => Inc_S,
+- Dec_S => Dec_S,
+- LDA => LDA,
+- LDP => LDP,
+- LDX => LDX,
+- LDY => LDY,
+- LDS => LDS,
+- LDDI => LDDI,
+- LDALU => LDALU,
+- LDAD => LDAD,
+- LDBAL => LDBAL,
+- LDBAH => LDBAH,
+- SaveP => SaveP,
+- Write => Write
+- );
+-
+- alu : T65_ALU
+- port map(
+- Mode => Mode_r,
+- Op => ALU_Op_r,
+- BusA => BusA_r,
+- BusB => BusB,
+- P_In => P,
+- P_Out => P_Out,
+- Q => ALU_Q
+- );
+-
+- process (Res_n, Clk)
+- begin
+- if Res_n = '0' then
+- PC <= (others => '0'); -- Program Counter
+- IR <= "00000000";
+- S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!!
+- D <= (others => '0');
+- PBR <= (others => '0');
+- DBR <= (others => '0');
+-
+- Mode_r <= (others => '0');
+- ALU_Op_r <= "1100";
+- Write_Data_r <= "000";
+- Set_Addr_To_r <= "00";
+-
+- R_W_n_i <= '1';
+- EF_i <= '1';
+- MF_i <= '1';
+- XF_i <= '1';
+-
+- elsif Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (really_rdy = '1') then
+- R_W_n_i <= not Write or RstCycle;
+-
+- D <= (others => '1'); -- Dummy
+- PBR <= (others => '1'); -- Dummy
+- DBR <= (others => '1'); -- Dummy
+- EF_i <= '0'; -- Dummy
+- MF_i <= '0'; -- Dummy
+- XF_i <= '0'; -- Dummy
+-
+- if MCycle = "000" then
+- Mode_r <= Mode;
+-
+- if IRQCycle = '0' and NMICycle = '0' then
+- PC <= PC + 1;
+- end if;
+-
+- if IRQCycle = '1' or NMICycle = '1' then
+- IR <= "00000000";
+- else
+- IR <= DI;
+- end if;
+- end if;
+-
+- ALU_Op_r <= ALU_Op;
+- Write_Data_r <= Write_Data;
+- if Break = '1' then
+- Set_Addr_To_r <= "00";
+- else
+- Set_Addr_To_r <= Set_Addr_To;
+- end if;
+-
+- if Inc_S = '1' then
+- S <= S + 1;
+- end if;
+- if Dec_S = '1' and RstCycle = '0' then
+- S <= S - 1;
+- end if;
+- if LDS = '1' then
+- S(7 downto 0) <= unsigned(ALU_Q);
+- end if;
+-
+- if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then
+- PC <= PC + 1;
+- end if;
+- --
+- -- jump control logic
+- --
+- case Jump is
+- when "01" =>
+- PC <= PC + 1;
+-
+- when "10" =>
+- PC <= unsigned(DI & DL);
+-
+- when "11" =>
+- if PCAdder(8) = '1' then
+- if DL(7) = '0' then
+- PC(15 downto 8) <= PC(15 downto 8) + 1;
+- else
+- PC(15 downto 8) <= PC(15 downto 8) - 1;
+- end if;
+- end if;
+- PC(7 downto 0) <= PCAdder(7 downto 0);
+-
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1'
+- else "0" & PC(7 downto 0);
+-
+- process (Clk)
+- begin
+- if Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (really_rdy = '1') then
+- if MCycle = "000" then
+- if LDA = '1' then
+- ABC(7 downto 0) <= ALU_Q;
+- end if;
+- if LDX = '1' then
+- X(7 downto 0) <= ALU_Q;
+- end if;
+- if LDY = '1' then
+- Y(7 downto 0) <= ALU_Q;
+- end if;
+- if (LDA or LDX or LDY) = '1' then
+- P <= P_Out;
+- end if;
+- end if;
+- if SaveP = '1' then
+- P <= P_Out;
+- end if;
+- if LDP = '1' then
+- P <= ALU_Q;
+- end if;
+- if IR(4 downto 0) = "11000" then
+- case IR(7 downto 5) is
+- when "000" =>
+- P(Flag_C) <= '0';
+- when "001" =>
+- P(Flag_C) <= '1';
+- when "010" =>
+- P(Flag_I) <= '0';
+- when "011" =>
+- P(Flag_I) <= '1';
+- when "101" =>
+- P(Flag_V) <= '0';
+- when "110" =>
+- P(Flag_D) <= '0';
+- when "111" =>
+- P(Flag_D) <= '1';
+- when others =>
+- end case;
+- end if;
+-
+- --if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then
+- -- P(Flag_B) <= '1';
+- --end if;
+- --if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
+- -- P(Flag_I) <= '1';
+- -- P(Flag_B) <= B_o;
+- --end if;
+-
+- -- B=1 always on the 6502
+- P(Flag_B) <= '1';
+- if IR = "00000000" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
+- if MCycle = "011" then
+- -- B=0 in *copy* of P pushed onto the stack
+- P(Flag_B) <= '0';
+- elsif MCycle = "100" then
+- P(Flag_I) <= '1';
+- end if;
+- end if;
+-
+- if SO_n_o = '1' and SO_n = '0' then
+- P(Flag_V) <= '1';
+- end if;
+- if RstCycle = '1' and Mode_r /= "00" then
+- P(Flag_1) <= '1';
+- P(Flag_D) <= '0';
+- P(Flag_I) <= '1';
+- end if;
+- P(Flag_1) <= '1';
+-
+- B_o <= P(Flag_B);
+- SO_n_o <= SO_n;
+- IRQ_n_o <= IRQ_n;
+- NMI_n_o <= NMI_n;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+----------------------------------------------------------------------------
+---
+--- Buses
+---
+----------------------------------------------------------------------------
+-
+- process (Res_n, Clk)
+- begin
+- if Res_n = '0' then
+- BusA_r <= (others => '0');
+- BusB <= (others => '0');
+- AD <= (others => '0');
+- BAL <= (others => '0');
+- BAH <= (others => '0');
+- DL <= (others => '0');
+- elsif Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (Rdy = '1') then
+- BusA_r <= BusA;
+- BusB <= DI;
+-
+- case BAAdd is
+- when "01" =>
+- -- BA Inc
+- AD <= std_logic_vector(unsigned(AD) + 1);
+- BAL <= std_logic_vector(unsigned(BAL) + 1);
+- when "10" =>
+- -- BA Add
+- BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9));
+- when "11" =>
+- -- BA Adj
+- if BAL(8) = '1' then
+- BAH <= std_logic_vector(unsigned(BAH) + 1);
+- end if;
+- when others =>
+- end case;
+-
+- -- ehenciak : modified to use Y register as well (bugfix)
+- if ADAdd = '1' then
+- if (AddY = '1') then
+- AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0)));
+- else
+- AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0)));
+- end if;
+- end if;
+-
+- if IR = "00000000" then
+- BAL <= (others => '1');
+- BAH <= (others => '1');
+- if RstCycle = '1' then
+- BAL(2 downto 0) <= "100";
+- elsif NMICycle = '1' then
+- BAL(2 downto 0) <= "010";
+- else
+- BAL(2 downto 0) <= "110";
+- end if;
+- if Set_addr_To_r = "11" then
+- BAL(0) <= '1';
+- end if;
+- end if;
+-
+-
+- if LDDI = '1' then
+- DL <= DI;
+- end if;
+- if LDALU = '1' then
+- DL <= ALU_Q;
+- end if;
+- if LDAD = '1' then
+- AD <= DI;
+- end if;
+- if LDBAL = '1' then
+- BAL(7 downto 0) <= DI;
+- end if;
+- if LDBAH = '1' then
+- BAH <= DI;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8));
+-
+-
+- with Set_BusA_To select
+- BusA <= DI when "000",
+- ABC(7 downto 0) when "001",
+- X(7 downto 0) when "010",
+- Y(7 downto 0) when "011",
+- std_logic_vector(S(7 downto 0)) when "100",
+- P when "101",
+- (others => '-') when others;
+-
+- with Set_Addr_To_r select
+- A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01",
+- DBR & "00000000" & AD when "10",
+- "00000000" & BAH & BAL(7 downto 0) when "11",
+- PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others;
+-
+- with Write_Data_r select
+- DO <= DL when "000",
+- ABC(7 downto 0) when "001",
+- X(7 downto 0) when "010",
+- Y(7 downto 0) when "011",
+- std_logic_vector(S(7 downto 0)) when "100",
+- P when "101",
+- std_logic_vector(PC(7 downto 0)) when "110",
+- std_logic_vector(PC(15 downto 8)) when others;
+-
+--------------------------------------------------------------------------
+---
+--- Main state machine
+---
+--------------------------------------------------------------------------
+-
+- process (Res_n, Clk)
+- begin
+- if Res_n = '0' then
+- MCycle <= "001";
+- RstCycle <= '1';
+- IRQCycle <= '0';
+- NMICycle <= '0';
+- NMIAct <= '0';
+- elsif Clk'event and Clk = '1' then
+- if (Enable = '1') then
+- if (really_rdy = '1') then
+- if MCycle = LCycle or Break = '1' then
+- MCycle <= "000";
+- RstCycle <= '0';
+- IRQCycle <= '0';
+- NMICycle <= '0';
+- if NMIAct = '1' then
+- NMICycle <= '1';
+- elsif IRQ_n_o = '0' and P(Flag_I) = '0' then
+- IRQCycle <= '1';
+- end if;
+- else
+- MCycle <= std_logic_vector(unsigned(MCycle) + 1);
+- end if;
+-
+- if NMICycle = '1' then
+- NMIAct <= '0';
+- end if;
+- if NMI_n_o = '1' and NMI_n = '0' then
+- NMIAct <= '1';
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+-end;
++-- ****
++-- T65(b) core. In an effort to merge and maintain bug fixes ....
++--
++--
++-- Ver 301 more merging
++-- Ver 300 Bugfixes by ehenciak added, started tidyup *bust*
++-- MikeJ March 2005
++-- Latest version from www.fpgaarcade.com (original www.opencores.org)
++--
++-- ****
++--
++-- 65xx compatible microprocessor core
++--
++-- Version : 0246
++--
++-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
++--
++-- All rights reserved
++--
++-- Redistribution and use in source and synthezised forms, with or without
++-- modification, are permitted provided that the following conditions are met:
++--
++-- Redistributions of source code must retain the above copyright notice,
++-- this list of conditions and the following disclaimer.
++--
++-- Redistributions in synthesized form must reproduce the above copyright
++-- notice, this list of conditions and the following disclaimer in the
++-- documentation and/or other materials provided with the distribution.
++--
++-- Neither the name of the author nor the names of other contributors may
++-- be used to endorse or promote products derived from this software without
++-- specific prior written permission.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++-- Please report bugs to the author, but before you do so, please
++-- make sure that this is not a derivative work and that
++-- you have the latest version of this file.
++--
++-- The latest version of this file can be found at:
++-- http://www.opencores.org/cvsweb.shtml/t65/
++--
++-- Limitations :
++--
++-- 65C02 and 65C816 modes are incomplete
++-- Undocumented instructions are not supported
++-- Some interface signals behaves incorrect
++--
++-- File history :
++--
++-- 0246 : First release
++--
++
++library IEEE;
++ use IEEE.std_logic_1164.all;
++ use IEEE.numeric_std.all;
++ use work.T65_Pack.all;
++
++-- ehenciak 2-23-2005 : Added the enable signal so that one doesn't have to use
++-- the ready signal to limit the CPU.
++entity T65 is
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
++ Res_n : in std_logic;
++ Enable : in std_logic;
++ Clk : in std_logic;
++ Rdy : in std_logic;
++ Abort_n : in std_logic;
++ IRQ_n : in std_logic;
++ NMI_n : in std_logic;
++ SO_n : in std_logic;
++ R_W_n : out std_logic;
++ Sync : out std_logic;
++ EF : out std_logic;
++ MF : out std_logic;
++ XF : out std_logic;
++ ML_n : out std_logic;
++ VP_n : out std_logic;
++ VDA : out std_logic;
++ VPA : out std_logic;
++ A : out std_logic_vector(23 downto 0);
++ DI : in std_logic_vector(7 downto 0);
++ DO : out std_logic_vector(7 downto 0)
++ );
++end T65;
++
++architecture rtl of T65 is
++
++ -- Registers
++ signal ABC, X, Y, D : std_logic_vector(15 downto 0);
++ signal P, AD, DL : std_logic_vector(7 downto 0) := x"00";
++ signal BAH : std_logic_vector(7 downto 0);
++ signal BAL : std_logic_vector(8 downto 0);
++ signal PBR : std_logic_vector(7 downto 0);
++ signal DBR : std_logic_vector(7 downto 0);
++ signal PC : unsigned(15 downto 0);
++ signal S : unsigned(15 downto 0);
++ signal EF_i : std_logic;
++ signal MF_i : std_logic;
++ signal XF_i : std_logic;
++
++ signal IR : std_logic_vector(7 downto 0);
++ signal MCycle : std_logic_vector(2 downto 0);
++
++ signal Mode_r : std_logic_vector(1 downto 0);
++ signal ALU_Op_r : std_logic_vector(3 downto 0);
++ signal Write_Data_r : std_logic_vector(2 downto 0);
++ signal Set_Addr_To_r : std_logic_vector(1 downto 0);
++ signal PCAdder : unsigned(8 downto 0);
++
++ signal RstCycle : std_logic;
++ signal IRQCycle : std_logic;
++ signal NMICycle : std_logic;
++
++ signal B_o : std_logic;
++ signal SO_n_o : std_logic;
++ signal IRQ_n_o : std_logic;
++ signal NMI_n_o : std_logic;
++ signal NMIAct : std_logic;
++
++ signal Break : std_logic;
++
++ -- ALU signals
++ signal BusA : std_logic_vector(7 downto 0);
++ signal BusA_r : std_logic_vector(7 downto 0);
++ signal BusB : std_logic_vector(7 downto 0);
++ signal ALU_Q : std_logic_vector(7 downto 0);
++ signal P_Out : std_logic_vector(7 downto 0);
++
++ -- Micro code outputs
++ signal LCycle : std_logic_vector(2 downto 0);
++ signal ALU_Op : std_logic_vector(3 downto 0);
++ signal Set_BusA_To : std_logic_vector(2 downto 0);
++ signal Set_Addr_To : std_logic_vector(1 downto 0);
++ signal Write_Data : std_logic_vector(2 downto 0);
++ signal Jump : std_logic_vector(1 downto 0);
++ signal BAAdd : std_logic_vector(1 downto 0);
++ signal BreakAtNA : std_logic;
++ signal ADAdd : std_logic;
++ signal AddY : std_logic;
++ signal PCAdd : std_logic;
++ signal Inc_S : std_logic;
++ signal Dec_S : std_logic;
++ signal LDA : std_logic;
++ signal LDP : std_logic;
++ signal LDX : std_logic;
++ signal LDY : std_logic;
++ signal LDS : std_logic;
++ signal LDDI : std_logic;
++ signal LDALU : std_logic;
++ signal LDAD : std_logic;
++ signal LDBAL : std_logic;
++ signal LDBAH : std_logic;
++ signal SaveP : std_logic;
++ signal Write : std_logic;
++
++ signal really_rdy : std_logic;
++ signal R_W_n_i : std_logic;
++
++begin
++ -- ehenciak : gate Rdy with read/write to make an "OK, it's
++ -- really OK to stop the processor now if Rdy is
++ -- deasserted" signal
++ really_rdy <= Rdy or not(R_W_n_i);
++
++ -- ehenciak : Drive R_W_n_i off chip.
++ R_W_n <= R_W_n_i;
++
++ Sync <= '1' when MCycle = "000" else '0';
++ EF <= EF_i;
++ MF <= MF_i;
++ XF <= XF_i;
++ ML_n <= '0' when IR(7 downto 6) /= "10" and IR(2 downto 1) = "11" and MCycle(2 downto 1) /= "00" else '1';
++ VP_n <= '0' when IRQCycle = '1' and (MCycle = "101" or MCycle = "110") else '1';
++ VDA <= '1' when Set_Addr_To_r /= "00" else '0'; -- Incorrect !!!!!!!!!!!!
++ VPA <= '1' when Jump(1) = '0' else '0'; -- Incorrect !!!!!!!!!!!!
++
++ mcode : T65_MCode
++ port map(
++ Mode => Mode_r,
++ IR => IR,
++ MCycle => MCycle,
++ P => P,
++ LCycle => LCycle,
++ ALU_Op => ALU_Op,
++ Set_BusA_To => Set_BusA_To,
++ Set_Addr_To => Set_Addr_To,
++ Write_Data => Write_Data,
++ Jump => Jump,
++ BAAdd => BAAdd,
++ BreakAtNA => BreakAtNA,
++ ADAdd => ADAdd,
++ AddY => AddY,
++ PCAdd => PCAdd,
++ Inc_S => Inc_S,
++ Dec_S => Dec_S,
++ LDA => LDA,
++ LDP => LDP,
++ LDX => LDX,
++ LDY => LDY,
++ LDS => LDS,
++ LDDI => LDDI,
++ LDALU => LDALU,
++ LDAD => LDAD,
++ LDBAL => LDBAL,
++ LDBAH => LDBAH,
++ SaveP => SaveP,
++ Write => Write
++ );
++
++ alu : T65_ALU
++ port map(
++ Mode => Mode_r,
++ Op => ALU_Op_r,
++ BusA => BusA_r,
++ BusB => BusB,
++ P_In => P,
++ P_Out => P_Out,
++ Q => ALU_Q
++ );
++
++ process (Res_n, Clk)
++ begin
++ if Res_n = '0' then
++ PC <= (others => '0'); -- Program Counter
++ IR <= "00000000";
++ S <= (others => '0'); -- Dummy !!!!!!!!!!!!!!!!!!!!!
++ D <= (others => '0');
++ PBR <= (others => '0');
++ DBR <= (others => '0');
++
++ Mode_r <= (others => '0');
++ ALU_Op_r <= "1100";
++ Write_Data_r <= "000";
++ Set_Addr_To_r <= "00";
++
++ R_W_n_i <= '1';
++ EF_i <= '1';
++ MF_i <= '1';
++ XF_i <= '1';
++
++ elsif Clk'event and Clk = '1' then
++ if (Enable = '1') then
++ if (really_rdy = '1') then
++ R_W_n_i <= not Write or RstCycle;
++
++ D <= (others => '1'); -- Dummy
++ PBR <= (others => '1'); -- Dummy
++ DBR <= (others => '1'); -- Dummy
++ EF_i <= '0'; -- Dummy
++ MF_i <= '0'; -- Dummy
++ XF_i <= '0'; -- Dummy
++
++ if MCycle = "000" then
++ Mode_r <= Mode;
++
++ if IRQCycle = '0' and NMICycle = '0' then
++ PC <= PC + 1;
++ end if;
++
++ if IRQCycle = '1' or NMICycle = '1' then
++ IR <= "00000000";
++ else
++ IR <= DI;
++ end if;
++ end if;
++
++ ALU_Op_r <= ALU_Op;
++ Write_Data_r <= Write_Data;
++ if Break = '1' then
++ Set_Addr_To_r <= "00";
++ else
++ Set_Addr_To_r <= Set_Addr_To;
++ end if;
++
++ if Inc_S = '1' then
++ S <= S + 1;
++ end if;
++ if Dec_S = '1' and RstCycle = '0' then
++ S <= S - 1;
++ end if;
++ if LDS = '1' then
++ S(7 downto 0) <= unsigned(ALU_Q);
++ end if;
++
++ if IR = "00000000" and MCycle = "001" and IRQCycle = '0' and NMICycle = '0' then
++ PC <= PC + 1;
++ end if;
++ --
++ -- jump control logic
++ --
++ case Jump is
++ when "01" =>
++ PC <= PC + 1;
++
++ when "10" =>
++ PC <= unsigned(DI & DL);
++
++ when "11" =>
++ if PCAdder(8) = '1' then
++ if DL(7) = '0' then
++ PC(15 downto 8) <= PC(15 downto 8) + 1;
++ else
++ PC(15 downto 8) <= PC(15 downto 8) - 1;
++ end if;
++ end if;
++ PC(7 downto 0) <= PCAdder(7 downto 0);
++
++ when others => null;
++ end case;
++ end if;
++ end if;
++ end if;
++ end process;
++
++ PCAdder <= resize(PC(7 downto 0),9) + resize(unsigned(DL(7) & DL),9) when PCAdd = '1'
++ else "0" & PC(7 downto 0);
++
++ process (Clk)
++ begin
++ if Clk'event and Clk = '1' then
++ if (Enable = '1') then
++ if (really_rdy = '1') then
++ if MCycle = "000" then
++ if LDA = '1' then
++ ABC(7 downto 0) <= ALU_Q;
++ end if;
++ if LDX = '1' then
++ X(7 downto 0) <= ALU_Q;
++ end if;
++ if LDY = '1' then
++ Y(7 downto 0) <= ALU_Q;
++ end if;
++ if (LDA or LDX or LDY) = '1' then
++ P <= P_Out;
++ end if;
++ end if;
++ if SaveP = '1' then
++ P <= P_Out;
++ end if;
++ if LDP = '1' then
++ P <= ALU_Q;
++ end if;
++ if IR(4 downto 0) = "11000" then
++ case IR(7 downto 5) is
++ when "000" =>
++ P(Flag_C) <= '0';
++ when "001" =>
++ P(Flag_C) <= '1';
++ when "010" =>
++ P(Flag_I) <= '0';
++ when "011" =>
++ P(Flag_I) <= '1';
++ when "101" =>
++ P(Flag_V) <= '0';
++ when "110" =>
++ P(Flag_D) <= '0';
++ when "111" =>
++ P(Flag_D) <= '1';
++ when others =>
++ end case;
++ end if;
++
++ --if IR = "00000000" and MCycle = "011" and RstCycle = '0' and NMICycle = '0' and IRQCycle = '0' then
++ -- P(Flag_B) <= '1';
++ --end if;
++ --if IR = "00000000" and MCycle = "100" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
++ -- P(Flag_I) <= '1';
++ -- P(Flag_B) <= B_o;
++ --end if;
++
++ -- B=1 always on the 6502
++ P(Flag_B) <= '1';
++ if IR = "00000000" and RstCycle = '0' and (NMICycle = '1' or IRQCycle = '1') then
++ if MCycle = "011" then
++ -- B=0 in *copy* of P pushed onto the stack
++ P(Flag_B) <= '0';
++ elsif MCycle = "100" then
++ P(Flag_I) <= '1';
++ end if;
++ end if;
++
++ if SO_n_o = '1' and SO_n = '0' then
++ P(Flag_V) <= '1';
++ end if;
++ if RstCycle = '1' and Mode_r /= "00" then
++ P(Flag_1) <= '1';
++ P(Flag_D) <= '0';
++ P(Flag_I) <= '1';
++ end if;
++ P(Flag_1) <= '1';
++
++ B_o <= P(Flag_B);
++ SO_n_o <= SO_n;
++ IRQ_n_o <= IRQ_n;
++ NMI_n_o <= NMI_n;
++ end if;
++ end if;
++ end if;
++ end process;
++
++---------------------------------------------------------------------------
++--
++-- Buses
++--
++---------------------------------------------------------------------------
++
++ process (Res_n, Clk)
++ begin
++ if Res_n = '0' then
++ BusA_r <= (others => '0');
++ BusB <= (others => '0');
++ AD <= (others => '0');
++ BAL <= (others => '0');
++ BAH <= (others => '0');
++ DL <= (others => '0');
++ elsif Clk'event and Clk = '1' then
++ if (Enable = '1') then
++ if (Rdy = '1') then
++ BusA_r <= BusA;
++ BusB <= DI;
++
++ case BAAdd is
++ when "01" =>
++ -- BA Inc
++ AD <= std_logic_vector(unsigned(AD) + 1);
++ BAL <= std_logic_vector(unsigned(BAL) + 1);
++ when "10" =>
++ -- BA Add
++ BAL <= std_logic_vector(resize(unsigned(BAL(7 downto 0)),9) + resize(unsigned(BusA),9));
++ when "11" =>
++ -- BA Adj
++ if BAL(8) = '1' then
++ BAH <= std_logic_vector(unsigned(BAH) + 1);
++ end if;
++ when others =>
++ end case;
++
++ -- ehenciak : modified to use Y register as well (bugfix)
++ if ADAdd = '1' then
++ if (AddY = '1') then
++ AD <= std_logic_vector(unsigned(AD) + unsigned(Y(7 downto 0)));
++ else
++ AD <= std_logic_vector(unsigned(AD) + unsigned(X(7 downto 0)));
++ end if;
++ end if;
++
++ if IR = "00000000" then
++ BAL <= (others => '1');
++ BAH <= (others => '1');
++ if RstCycle = '1' then
++ BAL(2 downto 0) <= "100";
++ elsif NMICycle = '1' then
++ BAL(2 downto 0) <= "010";
++ else
++ BAL(2 downto 0) <= "110";
++ end if;
++ if Set_addr_To_r = "11" then
++ BAL(0) <= '1';
++ end if;
++ end if;
++
++
++ if LDDI = '1' then
++ DL <= DI;
++ end if;
++ if LDALU = '1' then
++ DL <= ALU_Q;
++ end if;
++ if LDAD = '1' then
++ AD <= DI;
++ end if;
++ if LDBAL = '1' then
++ BAL(7 downto 0) <= DI;
++ end if;
++ if LDBAH = '1' then
++ BAH <= DI;
++ end if;
++ end if;
++ end if;
++ end if;
++ end process;
++
++ Break <= (BreakAtNA and not BAL(8)) or (PCAdd and not PCAdder(8));
++
++
++ with Set_BusA_To select
++ BusA <= DI when "000",
++ ABC(7 downto 0) when "001",
++ X(7 downto 0) when "010",
++ Y(7 downto 0) when "011",
++ std_logic_vector(S(7 downto 0)) when "100",
++ P when "101",
++ (others => '-') when others;
++
++ with Set_Addr_To_r select
++ A <= "0000000000000001" & std_logic_vector(S(7 downto 0)) when "01",
++ DBR & "00000000" & AD when "10",
++ "00000000" & BAH & BAL(7 downto 0) when "11",
++ PBR & std_logic_vector(PC(15 downto 8)) & std_logic_vector(PCAdder(7 downto 0)) when others;
++
++ with Write_Data_r select
++ DO <= DL when "000",
++ ABC(7 downto 0) when "001",
++ X(7 downto 0) when "010",
++ Y(7 downto 0) when "011",
++ std_logic_vector(S(7 downto 0)) when "100",
++ P when "101",
++ std_logic_vector(PC(7 downto 0)) when "110",
++ std_logic_vector(PC(15 downto 8)) when others;
++
++-------------------------------------------------------------------------
++--
++-- Main state machine
++--
++-------------------------------------------------------------------------
++
++ process (Res_n, Clk)
++ begin
++ if Res_n = '0' then
++ MCycle <= "001";
++ RstCycle <= '1';
++ IRQCycle <= '0';
++ NMICycle <= '0';
++ NMIAct <= '0';
++ elsif Clk'event and Clk = '1' then
++ if (Enable = '1') then
++ if (really_rdy = '1') then
++ if MCycle = LCycle or Break = '1' then
++ MCycle <= "000";
++ RstCycle <= '0';
++ IRQCycle <= '0';
++ NMICycle <= '0';
++ if NMIAct = '1' then
++ NMICycle <= '1';
++ elsif IRQ_n_o = '0' and P(Flag_I) = '0' then
++ IRQCycle <= '1';
++ end if;
++ else
++ MCycle <= std_logic_vector(unsigned(MCycle) + 1);
++ end if;
++
++ if NMICycle = '1' then
++ NMIAct <= '0';
++ end if;
++ if NMI_n_o = '1' and NMI_n = '0' then
++ NMIAct <= '1';
++ end if;
++ end if;
++ end if;
++ end if;
++ end process;
++
++end;
+diff --git a/T65/T65_ALU.vhd b/T65/T65_ALU.vhd
+index d9d25e1..b1f6d63 100644
+--- a/T65/T65_ALU.vhd
++++ b/T65/T65_ALU.vhd
+@@ -1,260 +1,260 @@
+--- ****
+--- T65(b) core. In an effort to merge and maintain bug fixes ....
+---
+---
+--- Ver 300 Bugfixes by ehenciak added
+--- MikeJ March 2005
+--- Latest version from www.fpgaarcade.com (original www.opencores.org)
+---
+--- ****
+---
+--- 6502 compatible microprocessor core
+---
+--- Version : 0245
+---
+--- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- Please report bugs to the author, but before you do so, please
+--- make sure that this is not a derivative work and that
+--- you have the latest version of this file.
+---
+--- The latest version of this file can be found at:
+--- http://www.opencores.org/cvsweb.shtml/t65/
+---
+--- Limitations :
+---
+--- File history :
+---
+--- 0245 : First version
+---
+-
+-library IEEE;
+-use IEEE.std_logic_1164.all;
+-use IEEE.numeric_std.all;
+-use work.T65_Pack.all;
+-
+-entity T65_ALU is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+- Op : in std_logic_vector(3 downto 0);
+- BusA : in std_logic_vector(7 downto 0);
+- BusB : in std_logic_vector(7 downto 0);
+- P_In : in std_logic_vector(7 downto 0);
+- P_Out : out std_logic_vector(7 downto 0);
+- Q : out std_logic_vector(7 downto 0)
+- );
+-end T65_ALU;
+-
+-architecture rtl of T65_ALU is
+-
+- -- AddSub variables (temporary signals)
+- signal ADC_Z : std_logic;
+- signal ADC_C : std_logic;
+- signal ADC_V : std_logic;
+- signal ADC_N : std_logic;
+- signal ADC_Q : std_logic_vector(7 downto 0);
+- signal SBC_Z : std_logic;
+- signal SBC_C : std_logic;
+- signal SBC_V : std_logic;
+- signal SBC_N : std_logic;
+- signal SBC_Q : std_logic_vector(7 downto 0);
+-
+-begin
+-
+- process (P_In, BusA, BusB)
+- variable AL : unsigned(6 downto 0);
+- variable AH : unsigned(6 downto 0);
+- variable C : std_logic;
+- begin
+- AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7);
+- AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
+-
+--- pragma translate_off
+- if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
+- if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
+--- pragma translate_on
+-
+- if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
+- ADC_Z <= '1';
+- else
+- ADC_Z <= '0';
+- end if;
+-
+- if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then
+- AL(6 downto 1) := AL(6 downto 1) + 6;
+- end if;
+-
+- C := AL(6) or AL(5);
+- AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
+-
+- ADC_N <= AH(4);
+- ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7));
+-
+--- pragma translate_off
+- if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
+--- pragma translate_on
+-
+- if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then
+- AH(6 downto 1) := AH(6 downto 1) + 6;
+- end if;
+-
+- ADC_C <= AH(6) or AH(5);
+-
+- ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
+- end process;
+-
+- process (Op, P_In, BusA, BusB)
+- variable AL : unsigned(6 downto 0);
+- variable AH : unsigned(5 downto 0);
+- variable C : std_logic;
+- begin
+- C := P_In(Flag_C) or not Op(0);
+- AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6);
+- AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6);
+-
+--- pragma translate_off
+- if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
+- if is_x(std_logic_vector(AH)) then AH := "000000"; end if;
+--- pragma translate_on
+-
+- if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
+- SBC_Z <= '1';
+- else
+- SBC_Z <= '0';
+- end if;
+-
+- SBC_C <= not AH(5);
+- SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7));
+- SBC_N <= AH(4);
+-
+- if P_In(Flag_D) = '1' then
+- if AL(5) = '1' then
+- AL(5 downto 1) := AL(5 downto 1) - 6;
+- end if;
+- AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6);
+- if AH(5) = '1' then
+- AH(5 downto 1) := AH(5 downto 1) - 6;
+- end if;
+- end if;
+-
+- SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
+- end process;
+-
+- process (Op, P_In, BusA, BusB,
+- ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q,
+- SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q)
+- variable Q_t : std_logic_vector(7 downto 0);
+- begin
+- -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
+- -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
+- P_Out <= P_In;
+- Q_t := BusA;
+- case Op(3 downto 0) is
+- when "0000" =>
+- -- ORA
+- Q_t := BusA or BusB;
+- when "0001" =>
+- -- AND
+- Q_t := BusA and BusB;
+- when "0010" =>
+- -- EOR
+- Q_t := BusA xor BusB;
+- when "0011" =>
+- -- ADC
+- P_Out(Flag_V) <= ADC_V;
+- P_Out(Flag_C) <= ADC_C;
+- Q_t := ADC_Q;
+- when "0101" | "1101" =>
+- -- LDA
+- when "0110" =>
+- -- CMP
+- P_Out(Flag_C) <= SBC_C;
+- when "0111" =>
+- -- SBC
+- P_Out(Flag_V) <= SBC_V;
+- P_Out(Flag_C) <= SBC_C;
+- Q_t := SBC_Q;
+- when "1000" =>
+- -- ASL
+- Q_t := BusA(6 downto 0) & "0";
+- P_Out(Flag_C) <= BusA(7);
+- when "1001" =>
+- -- ROL
+- Q_t := BusA(6 downto 0) & P_In(Flag_C);
+- P_Out(Flag_C) <= BusA(7);
+- when "1010" =>
+- -- LSR
+- Q_t := "0" & BusA(7 downto 1);
+- P_Out(Flag_C) <= BusA(0);
+- when "1011" =>
+- -- ROR
+- Q_t := P_In(Flag_C) & BusA(7 downto 1);
+- P_Out(Flag_C) <= BusA(0);
+- when "1100" =>
+- -- BIT
+- P_Out(Flag_V) <= BusB(6);
+- when "1110" =>
+- -- DEC
+- Q_t := std_logic_vector(unsigned(BusA) - 1);
+- when "1111" =>
+- -- INC
+- Q_t := std_logic_vector(unsigned(BusA) + 1);
+- when others =>
+- end case;
+-
+- case Op(3 downto 0) is
+- when "0011" =>
+- P_Out(Flag_N) <= ADC_N;
+- P_Out(Flag_Z) <= ADC_Z;
+- when "0110" | "0111" =>
+- P_Out(Flag_N) <= SBC_N;
+- P_Out(Flag_Z) <= SBC_Z;
+- when "0100" =>
+- when "1100" =>
+- P_Out(Flag_N) <= BusB(7);
+- if (BusA and BusB) = "00000000" then
+- P_Out(Flag_Z) <= '1';
+- else
+- P_Out(Flag_Z) <= '0';
+- end if;
+- when others =>
+- P_Out(Flag_N) <= Q_t(7);
+- if Q_t = "00000000" then
+- P_Out(Flag_Z) <= '1';
+- else
+- P_Out(Flag_Z) <= '0';
+- end if;
+- end case;
+-
+- Q <= Q_t;
+- end process;
+-
+-end;
++-- ****
++-- T65(b) core. In an effort to merge and maintain bug fixes ....
++--
++--
++-- Ver 300 Bugfixes by ehenciak added
++-- MikeJ March 2005
++-- Latest version from www.fpgaarcade.com (original www.opencores.org)
++--
++-- ****
++--
++-- 6502 compatible microprocessor core
++--
++-- Version : 0245
++--
++-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
++--
++-- All rights reserved
++--
++-- Redistribution and use in source and synthezised forms, with or without
++-- modification, are permitted provided that the following conditions are met:
++--
++-- Redistributions of source code must retain the above copyright notice,
++-- this list of conditions and the following disclaimer.
++--
++-- Redistributions in synthesized form must reproduce the above copyright
++-- notice, this list of conditions and the following disclaimer in the
++-- documentation and/or other materials provided with the distribution.
++--
++-- Neither the name of the author nor the names of other contributors may
++-- be used to endorse or promote products derived from this software without
++-- specific prior written permission.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++-- Please report bugs to the author, but before you do so, please
++-- make sure that this is not a derivative work and that
++-- you have the latest version of this file.
++--
++-- The latest version of this file can be found at:
++-- http://www.opencores.org/cvsweb.shtml/t65/
++--
++-- Limitations :
++--
++-- File history :
++--
++-- 0245 : First version
++--
++
++library IEEE;
++use IEEE.std_logic_1164.all;
++use IEEE.numeric_std.all;
++use work.T65_Pack.all;
++
++entity T65_ALU is
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
++ Op : in std_logic_vector(3 downto 0);
++ BusA : in std_logic_vector(7 downto 0);
++ BusB : in std_logic_vector(7 downto 0);
++ P_In : in std_logic_vector(7 downto 0);
++ P_Out : out std_logic_vector(7 downto 0);
++ Q : out std_logic_vector(7 downto 0)
++ );
++end T65_ALU;
++
++architecture rtl of T65_ALU is
++
++ -- AddSub variables (temporary signals)
++ signal ADC_Z : std_logic;
++ signal ADC_C : std_logic;
++ signal ADC_V : std_logic;
++ signal ADC_N : std_logic;
++ signal ADC_Q : std_logic_vector(7 downto 0);
++ signal SBC_Z : std_logic;
++ signal SBC_C : std_logic;
++ signal SBC_V : std_logic;
++ signal SBC_N : std_logic;
++ signal SBC_Q : std_logic_vector(7 downto 0);
++
++begin
++
++ process (P_In, BusA, BusB)
++ variable AL : unsigned(6 downto 0);
++ variable AH : unsigned(6 downto 0);
++ variable C : std_logic;
++ begin
++ AL := resize(unsigned(BusA(3 downto 0) & P_In(Flag_C)), 7) + resize(unsigned(BusB(3 downto 0) & "1"), 7);
++ AH := resize(unsigned(BusA(7 downto 4) & AL(5)), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
++
++-- pragma translate_off
++ if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
++ if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
++-- pragma translate_on
++
++ if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
++ ADC_Z <= '1';
++ else
++ ADC_Z <= '0';
++ end if;
++
++ if AL(5 downto 1) > 9 and P_In(Flag_D) = '1' then
++ AL(6 downto 1) := AL(6 downto 1) + 6;
++ end if;
++
++ C := AL(6) or AL(5);
++ AH := resize(unsigned(BusA(7 downto 4) & C), 7) + resize(unsigned(BusB(7 downto 4) & "1"), 7);
++
++ ADC_N <= AH(4);
++ ADC_V <= (AH(4) xor BusA(7)) and not (BusA(7) xor BusB(7));
++
++-- pragma translate_off
++ if is_x(std_logic_vector(AH)) then AH := "0000000"; end if;
++-- pragma translate_on
++
++ if AH(5 downto 1) > 9 and P_In(Flag_D) = '1' then
++ AH(6 downto 1) := AH(6 downto 1) + 6;
++ end if;
++
++ ADC_C <= AH(6) or AH(5);
++
++ ADC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
++ end process;
++
++ process (Op, P_In, BusA, BusB)
++ variable AL : unsigned(6 downto 0);
++ variable AH : unsigned(5 downto 0);
++ variable C : std_logic;
++ begin
++ C := P_In(Flag_C) or not Op(0);
++ AL := resize(unsigned(BusA(3 downto 0) & C), 7) - resize(unsigned(BusB(3 downto 0) & "1"), 6);
++ AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(5)), 6);
++
++-- pragma translate_off
++ if is_x(std_logic_vector(AL)) then AL := "0000000"; end if;
++ if is_x(std_logic_vector(AH)) then AH := "000000"; end if;
++-- pragma translate_on
++
++ if AL(4 downto 1) = 0 and AH(4 downto 1) = 0 then
++ SBC_Z <= '1';
++ else
++ SBC_Z <= '0';
++ end if;
++
++ SBC_C <= not AH(5);
++ SBC_V <= (AH(4) xor BusA(7)) and (BusA(7) xor BusB(7));
++ SBC_N <= AH(4);
++
++ if P_In(Flag_D) = '1' then
++ if AL(5) = '1' then
++ AL(5 downto 1) := AL(5 downto 1) - 6;
++ end if;
++ AH := resize(unsigned(BusA(7 downto 4) & "0"), 6) - resize(unsigned(BusB(7 downto 4) & AL(6)), 6);
++ if AH(5) = '1' then
++ AH(5 downto 1) := AH(5 downto 1) - 6;
++ end if;
++ end if;
++
++ SBC_Q <= std_logic_vector(AH(4 downto 1) & AL(4 downto 1));
++ end process;
++
++ process (Op, P_In, BusA, BusB,
++ ADC_Z, ADC_C, ADC_V, ADC_N, ADC_Q,
++ SBC_Z, SBC_C, SBC_V, SBC_N, SBC_Q)
++ variable Q_t : std_logic_vector(7 downto 0);
++ begin
++ -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
++ -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
++ P_Out <= P_In;
++ Q_t := BusA;
++ case Op(3 downto 0) is
++ when "0000" =>
++ -- ORA
++ Q_t := BusA or BusB;
++ when "0001" =>
++ -- AND
++ Q_t := BusA and BusB;
++ when "0010" =>
++ -- EOR
++ Q_t := BusA xor BusB;
++ when "0011" =>
++ -- ADC
++ P_Out(Flag_V) <= ADC_V;
++ P_Out(Flag_C) <= ADC_C;
++ Q_t := ADC_Q;
++ when "0101" | "1101" =>
++ -- LDA
++ when "0110" =>
++ -- CMP
++ P_Out(Flag_C) <= SBC_C;
++ when "0111" =>
++ -- SBC
++ P_Out(Flag_V) <= SBC_V;
++ P_Out(Flag_C) <= SBC_C;
++ Q_t := SBC_Q;
++ when "1000" =>
++ -- ASL
++ Q_t := BusA(6 downto 0) & "0";
++ P_Out(Flag_C) <= BusA(7);
++ when "1001" =>
++ -- ROL
++ Q_t := BusA(6 downto 0) & P_In(Flag_C);
++ P_Out(Flag_C) <= BusA(7);
++ when "1010" =>
++ -- LSR
++ Q_t := "0" & BusA(7 downto 1);
++ P_Out(Flag_C) <= BusA(0);
++ when "1011" =>
++ -- ROR
++ Q_t := P_In(Flag_C) & BusA(7 downto 1);
++ P_Out(Flag_C) <= BusA(0);
++ when "1100" =>
++ -- BIT
++ P_Out(Flag_V) <= BusB(6);
++ when "1110" =>
++ -- DEC
++ Q_t := std_logic_vector(unsigned(BusA) - 1);
++ when "1111" =>
++ -- INC
++ Q_t := std_logic_vector(unsigned(BusA) + 1);
++ when others =>
++ end case;
++
++ case Op(3 downto 0) is
++ when "0011" =>
++ P_Out(Flag_N) <= ADC_N;
++ P_Out(Flag_Z) <= ADC_Z;
++ when "0110" | "0111" =>
++ P_Out(Flag_N) <= SBC_N;
++ P_Out(Flag_Z) <= SBC_Z;
++ when "0100" =>
++ when "1100" =>
++ P_Out(Flag_N) <= BusB(7);
++ if (BusA and BusB) = "00000000" then
++ P_Out(Flag_Z) <= '1';
++ else
++ P_Out(Flag_Z) <= '0';
++ end if;
++ when others =>
++ P_Out(Flag_N) <= Q_t(7);
++ if Q_t = "00000000" then
++ P_Out(Flag_Z) <= '1';
++ else
++ P_Out(Flag_Z) <= '0';
++ end if;
++ end case;
++
++ Q <= Q_t;
++ end process;
++
++end;
+diff --git a/T65/T65_MCode.vhd b/T65/T65_MCode.vhd
+index 3fd40d8..6c6c864 100644
+--- a/T65/T65_MCode.vhd
++++ b/T65/T65_MCode.vhd
+@@ -1,1052 +1,1052 @@
+--- ****
+--- T65(b) core. In an effort to merge and maintain bug fixes ....
+---
+---
+--- Ver 302 minor timing fixes
+--- Ver 301 Jump timing fixed
+--- Ver 300 Bugfixes by ehenciak added
+--- MikeJ March 2005
+--- Latest version from www.fpgaarcade.com (original www.opencores.org)
+---
+--- ****
+---
+--- 65xx compatible microprocessor core
+---
+--- Version : 0246 + fix
+---
+--- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- Please report bugs to the author, but before you do so, please
+--- make sure that this is not a derivative work and that
+--- you have the latest version of this file.
+---
+--- The latest version of this file can be found at:
+--- http://www.opencores.org/cvsweb.shtml/t65/
+---
+--- Limitations :
+---
+--- 65C02
+--- supported : inc, dec, phx, plx, phy, ply
+--- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8
+---
+--- File history :
+---
+--- 0246 : First release
+---
+-
+-library IEEE;
+-use IEEE.std_logic_1164.all;
+-use IEEE.numeric_std.all;
+-use work.T65_Pack.all;
+-
+-entity T65_MCode is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+- IR : in std_logic_vector(7 downto 0);
+- MCycle : in std_logic_vector(2 downto 0);
+- P : in std_logic_vector(7 downto 0);
+- LCycle : out std_logic_vector(2 downto 0);
+- ALU_Op : out std_logic_vector(3 downto 0);
+- Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
+- Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
+- Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
+- Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
+- BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
+- BreakAtNA : out std_logic;
+- ADAdd : out std_logic;
+- AddY : out std_logic;
+- PCAdd : out std_logic;
+- Inc_S : out std_logic;
+- Dec_S : out std_logic;
+- LDA : out std_logic;
+- LDP : out std_logic;
+- LDX : out std_logic;
+- LDY : out std_logic;
+- LDS : out std_logic;
+- LDDI : out std_logic;
+- LDALU : out std_logic;
+- LDAD : out std_logic;
+- LDBAL : out std_logic;
+- LDBAH : out std_logic;
+- SaveP : out std_logic;
+- Write : out std_logic
+- );
+-end T65_MCode;
+-
+-architecture rtl of T65_MCode is
+-
+- signal Branch : std_logic;
+-
+-begin
+-
+- with IR(7 downto 5) select
+- Branch <= not P(Flag_N) when "000",
+- P(Flag_N) when "001",
+- not P(Flag_V) when "010",
+- P(Flag_V) when "011",
+- not P(Flag_C) when "100",
+- P(Flag_C) when "101",
+- not P(Flag_Z) when "110",
+- P(Flag_Z) when others;
+-
+- process (IR, MCycle, P, Branch, Mode)
+- begin
+- LCycle <= "001";
+- Set_BusA_To <= "001"; -- A
+- Set_Addr_To <= (others => '0');
+- Write_Data <= (others => '0');
+- Jump <= (others => '0');
+- BAAdd <= "00";
+- BreakAtNA <= '0';
+- ADAdd <= '0';
+- PCAdd <= '0';
+- Inc_S <= '0';
+- Dec_S <= '0';
+- LDA <= '0';
+- LDP <= '0';
+- LDX <= '0';
+- LDY <= '0';
+- LDS <= '0';
+- LDDI <= '0';
+- LDALU <= '0';
+- LDAD <= '0';
+- LDBAL <= '0';
+- LDBAH <= '0';
+- SaveP <= '0';
+- Write <= '0';
+- AddY <= '0';
+-
+- case IR(7 downto 5) is
+- when "100" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- Set_BusA_To <= "011"; -- Y
+- Write_Data <= "011"; -- Y
+- when "10" =>
+- Set_BusA_To <= "010"; -- X
+- Write_Data <= "010"; -- X
+- when others =>
+- Write_Data <= "001"; -- A
+- end case;
+- --}}}
+- when "101" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- if IR(4) /= '1' or IR(2) /= '0' then
+- LDY <= '1';
+- end if;
+- when "10" =>
+- LDX <= '1';
+- when others =>
+- LDA <= '1';
+- end case;
+- Set_BusA_To <= "000"; -- DI
+- --}}}
+- when "110" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- if IR(4) = '0' then
+- LDY <= '1';
+- end if;
+- Set_BusA_To <= "011"; -- Y
+- when others =>
+- Set_BusA_To <= "001"; -- A
+- end case;
+- --}}}
+- when "111" =>
+- --{{{
+- case IR(1 downto 0) is
+- when "00" =>
+- if IR(4) = '0' then
+- LDX <= '1';
+- end if;
+- Set_BusA_To <= "010"; -- X
+- when others =>
+- Set_BusA_To <= "001"; -- A
+- end case;
+- --}}}
+- when others =>
+- end case;
+-
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- Set_BusA_To <= "000"; -- DI
+- end if;
+-
+- case IR(4 downto 0) is
+- when "00000" | "01000" | "01010" | "11000" | "11010" =>
+- --{{{
+- -- Implied
+- case IR is
+- when "00000000" =>
+- -- BRK
+- LCycle <= "110";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "111"; -- PCH
+- Write <= '1';
+- when 2 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "110"; -- PCL
+- Write <= '1';
+- when 3 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "101"; -- P
+- Write <= '1';
+- when 4 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- LDDI <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 6 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- when "00100000" =>
+- -- JSR
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDDI <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "111"; -- PCH
+- Write <= '1';
+- when 3 =>
+- Dec_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Write_Data <= "110"; -- PCL
+- Write <= '1';
+- when 4 =>
+- Dec_S <= '1';
+- when 5 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- when "01000000" =>
+- -- RTI
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 3 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- Set_BusA_To <= "000"; -- DI
+- when 4 =>
+- LDP <= '1';
+- Inc_S <= '1';
+- LDDI <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 5 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- when "01100000" =>
+- -- RTS
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 3 =>
+- Inc_S <= '1';
+- LDDI <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 4 =>
+- Jump <= "10"; -- DIDL
+- when 5 =>
+- Jump <= "01";
+- when others =>
+- end case;
+- when "00001000" | "01001000" | "01011010" | "11011010" =>
+- -- PHP, PHA, PHY*, PHX*
+- LCycle <= "010";
+- if Mode = "00" and IR(1) = '1' then
+- LCycle <= "001";
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- case IR(7 downto 4) is
+- when "0000" =>
+- Write_Data <= "101"; -- P
+- when "0100" =>
+- Write_Data <= "001"; -- A
+- when "0101" =>
+- Write_Data <= "011"; -- Y
+- when "1101" =>
+- Write_Data <= "010"; -- X
+- when others =>
+- end case;
+- Write <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Dec_S <= '1';
+- when others =>
+- end case;
+- when "00101000" | "01101000" | "01111010" | "11111010" =>
+- -- PLP, PLA, PLY*, PLX*
+- LCycle <= "011";
+- if Mode = "00" and IR(1) = '1' then
+- LCycle <= "001";
+- end if;
+- case IR(7 downto 4) is
+- when "0010" =>
+- LDP <= '1';
+- when "0110" =>
+- LDA <= '1';
+- when "0111" =>
+- if Mode /= "00" then
+- LDY <= '1';
+- end if;
+- when "1111" =>
+- if Mode /= "00" then
+- LDX <= '1';
+- end if;
+- when others =>
+- end case;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- SaveP <= '1';
+- when 1 =>
+- Set_Addr_To <= "01"; -- S
+- when 2 =>
+- Inc_S <= '1';
+- Set_Addr_To <= "01"; -- S
+- when 3 =>
+- Set_BusA_To <= "000"; -- DI
+- when others =>
+- end case;
+- when "10100000" | "11000000" | "11100000" =>
+- -- LDY, CPY, CPX
+- -- Immediate
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- when others =>
+- end case;
+- when "10001000" =>
+- -- DEY
+- LDY <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "011"; -- Y
+- when others =>
+- end case;
+- when "11001010" =>
+- -- DEX
+- LDX <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "010"; -- X
+- when others =>
+- end case;
+- when "00011010" | "00111010" =>
+- -- INC*, DEC*
+- if Mode /= "00" then
+- LDA <= '1'; -- A
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "100"; -- S
+- when others =>
+- end case;
+- when "00001010" | "00101010" | "01001010" | "01101010" =>
+- -- ASL, ROL, LSR, ROR
+- LDA <= '1'; -- A
+- Set_BusA_To <= "001"; -- A
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- when others =>
+- end case;
+- when "10001010" | "10011000" =>
+- -- TYA, TXA
+- LDA <= '1'; -- A
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- when others =>
+- end case;
+- when "10101010" | "10101000" =>
+- -- TAX, TAY
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "001"; -- A
+- when others =>
+- end case;
+- when "10011010" =>
+- -- TXS
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- LDS <= '1';
+- when 1 =>
+- when others =>
+- end case;
+- when "10111010" =>
+- -- TSX
+- LDX <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Set_BusA_To <= "100"; -- S
+- when others =>
+- end case;
+-
+- -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" =>
+- -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX
+- -- case to_integer(unsigned(MCycle)) is
+- -- when 1 =>
+- -- when others =>
+- -- end case;
+- when others =>
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when others =>
+- end case;
+- end case;
+- --}}}
+-
+- when "00001" | "00011" =>
+- --{{{
+- -- Zero Page Indexed Indirect (d,x)
+- LCycle <= "101";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- ADAdd <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- BAAdd <= "01"; -- DB Inc
+- LDBAL <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 4 =>
+- LDBAH <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- when others =>
+- end case;
+- --}}}
+-
+- when "01001" | "01011" =>
+- --{{{
+- -- Immediate
+- LDA <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- when others =>
+- end case;
+-
+- --}}}
+-
+- when "00010" | "10010" =>
+- --{{{
+- -- Immediate, KIL
+- LDX <= '1';
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- if IR = "10100010" then
+- -- LDX
+- Jump <= "01";
+- else
+- -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+- end if;
+- when others =>
+- end case;
+- --}}}
+-
+- when "00100" =>
+- --{{{
+- -- Zero Page
+- LCycle <= "010";
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- if IR(7 downto 5) = "001" then
+- SaveP <= '1';
+- end if;
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- when others =>
+- end case;
+- --}}}
+-
+- when "00101" | "00110" | "00111" =>
+- --{{{
+- -- Zero Page
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "100";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- LDALU <= '1';
+- SaveP <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 4 =>
+- when others =>
+- end case;
+- else
+- LCycle <= "010";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
+-
+- when "01100" =>
+- --{{{
+- -- Absolute
+- if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then
+- -- JMP
+- if IR(5) = '0' then
+- --LCycle <= "011";
+- LCycle <= "010";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDDI <= '1';
+- when 2 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- else
+- --LCycle <= "101";
+- LCycle <= "100"; -- mikej
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDDI <= '1';
+- LDBAL <= '1';
+- when 2 =>
+- LDBAH <= '1';
+- if Mode /= "00" then
+- Jump <= "10"; -- DIDL
+- end if;
+- if Mode = "00" then
+- Set_Addr_To <= "11"; -- BA
+- end if;
+- when 3 =>
+- LDDI <= '1';
+- if Mode = "00" then
+- Set_Addr_To <= "11"; -- BA
+- BAAdd <= "01"; -- DB Inc
+- else
+- Jump <= "01";
+- end if;
+- when 4 =>
+- Jump <= "10"; -- DIDL
+- when others =>
+- end case;
+- end if;
+- else
+- LCycle <= "011";
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- if IR(7 downto 5) = "001" then
+- SaveP <= '1';
+- end if;
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- LDBAH <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
+-
+- when "01101" | "01110" | "01111" =>
+- --{{{
+- -- Absolute
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- Write <= '1';
+- LDALU <= '1';
+- SaveP <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- SaveP <= '0'; -- MIKEJ was 1
+- when others =>
+- end case;
+- else
+- LCycle <= "011";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- LDBAH <= '1';
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
+-
+- when "10000" =>
+- --{{{
+- -- Relative
+-
+- -- This circuit dictates when the last
+- -- microcycle occurs for the branch depending on
+- -- whether or not the branch is taken and if a page
+- -- is crossed...
+- if (Branch = '1') then
+-
+- LCycle <= "011"; -- We're done @ T3 if branching...upper
+- -- level logic will stop at T2 if no page cross
+- -- (See the Break signal)
+- else
+-
+- LCycle <= "001";
+-
+- end if;
+-
+- -- This decodes the current microcycle and takes the
+- -- proper course of action...
+- case to_integer(unsigned(MCycle)) is
+-
+- -- On the T1 microcycle, increment the program counter
+- -- and instruct the upper level logic to fetch the offset
+- -- from the Din bus and store it in the data latches. This
+- -- will be the last microcycle if the branch isn't taken.
+- when 1 =>
+-
+- Jump <= "01"; -- Increments the PC by one (PC will now be PC+2)
+- -- from microcycle T0.
+-
+- LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route
+- -- the Din bus to the memory data latch (DL)
+- -- so that the branch offset is fetched.
+-
+- -- In microcycle T2, tell the logic in the top level to
+- -- add the offset. If the most significant byte of the
+- -- program counter (i.e. the current "page") does not need
+- -- updating, we are done here...the Break signal at the
+- -- T65.vhd level takes care of that...
+- when 2 =>
+-
+- Jump <= "11"; -- Tell the PC Jump logic to use relative mode.
+-
+- PCAdd <= '1'; -- This tells the PC adder to update itself with
+- -- the current offset recently fetched from
+- -- memory.
+-
+- -- The following is microcycle T3 :
+- -- The program counter should be completely updated
+- -- on this cycle after the page cross is detected.
+- -- We don't need to do anything here...
+- when 3 =>
+-
+-
+- when others => null; -- Do nothing.
+-
+- end case;
+- --}}}
+-
+- when "10001" | "10011" =>
+- --{{{
+- -- Zero Page Indirect Indexed (d),y
+- LCycle <= "101";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- LDBAL <= '1';
+- BAAdd <= "01"; -- DB Inc
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- Set_BusA_To <= "011"; -- Y
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- BAAdd <= "11"; -- BA Adj
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- else
+- BreakAtNA <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- when others =>
+- end case;
+- --}}}
+-
+- when "10100" | "10101" | "10110" | "10111" =>
+- --{{{
+- -- Zero Page, X
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "101";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- ADAdd <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 3 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 4 =>
+- LDALU <= '1';
+- SaveP <= '1';
+- Write <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 5 =>
+- when others =>
+- end case;
+- else
+- LCycle <= "011";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDAD <= '1';
+- Set_Addr_To <= "10"; -- AD
+- when 2 =>
+- ADAdd <= '1';
+- -- Added this check for Y reg. use...
+- if (IR(3 downto 0) = "0110") then
+- AddY <= '1';
+- end if;
+-
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- end if;
+- Set_Addr_To <= "10"; -- AD
+- when 3 => null;
+- when others =>
+- end case;
+- end if;
+- --}}}
+-
+- when "11001" | "11011" =>
+- --{{{
+- -- Absolute Y
+- LCycle <= "100";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- Set_BusA_To <= "011"; -- Y
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- BAAdd <= "11"; -- BA adj
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- else
+- BreakAtNA <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- when others =>
+- end case;
+- --}}}
+-
+- when "11100" | "11101" | "11110" | "11111" =>
+- --{{{
+- -- Absolute X
+-
+- if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
+- -- Read-Modify-Write
+- LCycle <= "110";
+- case to_integer(unsigned(MCycle)) is
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- Set_BusA_To <= "010"; -- X
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- BAAdd <= "11"; -- BA adj
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- LDDI <= '1';
+- Write <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 5 =>
+- LDALU <= '1';
+- SaveP <= '1';
+- Write <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 6 =>
+- when others =>
+- end case;
+- else
+- LCycle <= "100";
+- if IR(7 downto 6) /= "10" then
+- LDA <= '1';
+- end if;
+- case to_integer(unsigned(MCycle)) is
+- when 0 =>
+- when 1 =>
+- Jump <= "01";
+- LDBAL <= '1';
+- when 2 =>
+- Jump <= "01";
+- -- mikej
+- -- special case 0xBE which uses Y reg as index!!
+- if (IR = "10111110") then
+- Set_BusA_To <= "011"; -- Y
+- else
+- Set_BusA_To <= "010"; -- X
+- end if;
+- BAAdd <= "10"; -- BA Add
+- LDBAH <= '1';
+- Set_Addr_To <= "11"; -- BA
+- when 3 =>
+- BAAdd <= "11"; -- BA adj
+- if IR(7 downto 5) = "100" then
+- Write <= '1';
+- else
+- BreakAtNA <= '1';
+- end if;
+- Set_Addr_To <= "11"; -- BA
+- when 4 =>
+- when others =>
+- end case;
+- end if;
+- --}}}
+- when others =>
+- end case;
+- end process;
+-
+- process (IR, MCycle)
+- begin
+- -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
+- -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
+- case IR(1 downto 0) is
+- when "00" =>
+- --{{{
+- case IR(4 downto 2) is
+- when "000" | "001" | "011" =>
+- case IR(7 downto 5) is
+- when "110" | "111" =>
+- -- CP
+- ALU_Op <= "0110";
+- when "101" =>
+- -- LD
+- ALU_Op <= "0101";
+- when "001" =>
+- -- BIT
+- ALU_Op <= "1100";
+- when others =>
+- -- NOP/ST
+- ALU_Op <= "0100";
+- end case;
+- when "010" =>
+- case IR(7 downto 5) is
+- when "111" | "110" =>
+- -- IN
+- ALU_Op <= "1111";
+- when "100" =>
+- -- DEY
+- ALU_Op <= "1110";
+- when others =>
+- -- LD
+- ALU_Op <= "1101";
+- end case;
+- when "110" =>
+- case IR(7 downto 5) is
+- when "100" =>
+- -- TYA
+- ALU_Op <= "1101";
+- when others =>
+- ALU_Op <= "----";
+- end case;
+- when others =>
+- case IR(7 downto 5) is
+- when "101" =>
+- -- LD
+- ALU_Op <= "1101";
+- when others =>
+- ALU_Op <= "0100";
+- end case;
+- end case;
+- --}}}
+- when "01" => -- OR
+- --{{{
+- ALU_Op(3) <= '0';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- --}}}
+- when "10" =>
+- --{{{
+- ALU_Op(3) <= '1';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- case IR(7 downto 5) is
+- when "000" =>
+- if IR(4 downto 2) = "110" then
+- -- INC
+- ALU_Op <= "1111";
+- end if;
+- when "001" =>
+- if IR(4 downto 2) = "110" then
+- -- DEC
+- ALU_Op <= "1110";
+- end if;
+- when "100" =>
+- if IR(4 downto 2) = "010" then
+- -- TXA
+- ALU_Op <= "0101";
+- else
+- ALU_Op <= "0100";
+- end if;
+- when others =>
+- end case;
+- --}}}
+- when others =>
+- --{{{
+- case IR(7 downto 5) is
+- when "100" =>
+- ALU_Op <= "0100";
+- when others =>
+- if MCycle = "000" then
+- ALU_Op(3) <= '0';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- else
+- ALU_Op(3) <= '1';
+- ALU_Op(2 downto 0) <= IR(7 downto 5);
+- end if;
+- end case;
+- --}}}
+- end case;
+- end process;
+-
+-end;
++-- ****
++-- T65(b) core. In an effort to merge and maintain bug fixes ....
++--
++--
++-- Ver 302 minor timing fixes
++-- Ver 301 Jump timing fixed
++-- Ver 300 Bugfixes by ehenciak added
++-- MikeJ March 2005
++-- Latest version from www.fpgaarcade.com (original www.opencores.org)
++--
++-- ****
++--
++-- 65xx compatible microprocessor core
++--
++-- Version : 0246 + fix
++--
++-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
++--
++-- All rights reserved
++--
++-- Redistribution and use in source and synthezised forms, with or without
++-- modification, are permitted provided that the following conditions are met:
++--
++-- Redistributions of source code must retain the above copyright notice,
++-- this list of conditions and the following disclaimer.
++--
++-- Redistributions in synthesized form must reproduce the above copyright
++-- notice, this list of conditions and the following disclaimer in the
++-- documentation and/or other materials provided with the distribution.
++--
++-- Neither the name of the author nor the names of other contributors may
++-- be used to endorse or promote products derived from this software without
++-- specific prior written permission.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++-- Please report bugs to the author, but before you do so, please
++-- make sure that this is not a derivative work and that
++-- you have the latest version of this file.
++--
++-- The latest version of this file can be found at:
++-- http://www.opencores.org/cvsweb.shtml/t65/
++--
++-- Limitations :
++--
++-- 65C02
++-- supported : inc, dec, phx, plx, phy, ply
++-- missing : bra, ora, lda, cmp, sbc, tsb*2, trb*2, stz*2, bit*2, wai, stp, jmp, bbr*8, bbs*8
++--
++-- File history :
++--
++-- 0246 : First release
++--
++
++library IEEE;
++use IEEE.std_logic_1164.all;
++use IEEE.numeric_std.all;
++use work.T65_Pack.all;
++
++entity T65_MCode is
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
++ IR : in std_logic_vector(7 downto 0);
++ MCycle : in std_logic_vector(2 downto 0);
++ P : in std_logic_vector(7 downto 0);
++ LCycle : out std_logic_vector(2 downto 0);
++ ALU_Op : out std_logic_vector(3 downto 0);
++ Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
++ Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
++ Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
++ Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
++ BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
++ BreakAtNA : out std_logic;
++ ADAdd : out std_logic;
++ AddY : out std_logic;
++ PCAdd : out std_logic;
++ Inc_S : out std_logic;
++ Dec_S : out std_logic;
++ LDA : out std_logic;
++ LDP : out std_logic;
++ LDX : out std_logic;
++ LDY : out std_logic;
++ LDS : out std_logic;
++ LDDI : out std_logic;
++ LDALU : out std_logic;
++ LDAD : out std_logic;
++ LDBAL : out std_logic;
++ LDBAH : out std_logic;
++ SaveP : out std_logic;
++ Write : out std_logic
++ );
++end T65_MCode;
++
++architecture rtl of T65_MCode is
++
++ signal Branch : std_logic;
++
++begin
++
++ with IR(7 downto 5) select
++ Branch <= not P(Flag_N) when "000",
++ P(Flag_N) when "001",
++ not P(Flag_V) when "010",
++ P(Flag_V) when "011",
++ not P(Flag_C) when "100",
++ P(Flag_C) when "101",
++ not P(Flag_Z) when "110",
++ P(Flag_Z) when others;
++
++ process (IR, MCycle, P, Branch, Mode)
++ begin
++ LCycle <= "001";
++ Set_BusA_To <= "001"; -- A
++ Set_Addr_To <= (others => '0');
++ Write_Data <= (others => '0');
++ Jump <= (others => '0');
++ BAAdd <= "00";
++ BreakAtNA <= '0';
++ ADAdd <= '0';
++ PCAdd <= '0';
++ Inc_S <= '0';
++ Dec_S <= '0';
++ LDA <= '0';
++ LDP <= '0';
++ LDX <= '0';
++ LDY <= '0';
++ LDS <= '0';
++ LDDI <= '0';
++ LDALU <= '0';
++ LDAD <= '0';
++ LDBAL <= '0';
++ LDBAH <= '0';
++ SaveP <= '0';
++ Write <= '0';
++ AddY <= '0';
++
++ case IR(7 downto 5) is
++ when "100" =>
++ --{{{
++ case IR(1 downto 0) is
++ when "00" =>
++ Set_BusA_To <= "011"; -- Y
++ Write_Data <= "011"; -- Y
++ when "10" =>
++ Set_BusA_To <= "010"; -- X
++ Write_Data <= "010"; -- X
++ when others =>
++ Write_Data <= "001"; -- A
++ end case;
++ --}}}
++ when "101" =>
++ --{{{
++ case IR(1 downto 0) is
++ when "00" =>
++ if IR(4) /= '1' or IR(2) /= '0' then
++ LDY <= '1';
++ end if;
++ when "10" =>
++ LDX <= '1';
++ when others =>
++ LDA <= '1';
++ end case;
++ Set_BusA_To <= "000"; -- DI
++ --}}}
++ when "110" =>
++ --{{{
++ case IR(1 downto 0) is
++ when "00" =>
++ if IR(4) = '0' then
++ LDY <= '1';
++ end if;
++ Set_BusA_To <= "011"; -- Y
++ when others =>
++ Set_BusA_To <= "001"; -- A
++ end case;
++ --}}}
++ when "111" =>
++ --{{{
++ case IR(1 downto 0) is
++ when "00" =>
++ if IR(4) = '0' then
++ LDX <= '1';
++ end if;
++ Set_BusA_To <= "010"; -- X
++ when others =>
++ Set_BusA_To <= "001"; -- A
++ end case;
++ --}}}
++ when others =>
++ end case;
++
++ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
++ Set_BusA_To <= "000"; -- DI
++ end if;
++
++ case IR(4 downto 0) is
++ when "00000" | "01000" | "01010" | "11000" | "11010" =>
++ --{{{
++ -- Implied
++ case IR is
++ when "00000000" =>
++ -- BRK
++ LCycle <= "110";
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Set_Addr_To <= "01"; -- S
++ Write_Data <= "111"; -- PCH
++ Write <= '1';
++ when 2 =>
++ Dec_S <= '1';
++ Set_Addr_To <= "01"; -- S
++ Write_Data <= "110"; -- PCL
++ Write <= '1';
++ when 3 =>
++ Dec_S <= '1';
++ Set_Addr_To <= "01"; -- S
++ Write_Data <= "101"; -- P
++ Write <= '1';
++ when 4 =>
++ Dec_S <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 5 =>
++ LDDI <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 6 =>
++ Jump <= "10"; -- DIDL
++ when others =>
++ end case;
++ when "00100000" =>
++ -- JSR
++ LCycle <= "101";
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDDI <= '1';
++ Set_Addr_To <= "01"; -- S
++ when 2 =>
++ Set_Addr_To <= "01"; -- S
++ Write_Data <= "111"; -- PCH
++ Write <= '1';
++ when 3 =>
++ Dec_S <= '1';
++ Set_Addr_To <= "01"; -- S
++ Write_Data <= "110"; -- PCL
++ Write <= '1';
++ when 4 =>
++ Dec_S <= '1';
++ when 5 =>
++ Jump <= "10"; -- DIDL
++ when others =>
++ end case;
++ when "01000000" =>
++ -- RTI
++ LCycle <= "101";
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Set_Addr_To <= "01"; -- S
++ when 2 =>
++ Inc_S <= '1';
++ Set_Addr_To <= "01"; -- S
++ when 3 =>
++ Inc_S <= '1';
++ Set_Addr_To <= "01"; -- S
++ Set_BusA_To <= "000"; -- DI
++ when 4 =>
++ LDP <= '1';
++ Inc_S <= '1';
++ LDDI <= '1';
++ Set_Addr_To <= "01"; -- S
++ when 5 =>
++ Jump <= "10"; -- DIDL
++ when others =>
++ end case;
++ when "01100000" =>
++ -- RTS
++ LCycle <= "101";
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Set_Addr_To <= "01"; -- S
++ when 2 =>
++ Inc_S <= '1';
++ Set_Addr_To <= "01"; -- S
++ when 3 =>
++ Inc_S <= '1';
++ LDDI <= '1';
++ Set_Addr_To <= "01"; -- S
++ when 4 =>
++ Jump <= "10"; -- DIDL
++ when 5 =>
++ Jump <= "01";
++ when others =>
++ end case;
++ when "00001000" | "01001000" | "01011010" | "11011010" =>
++ -- PHP, PHA, PHY*, PHX*
++ LCycle <= "010";
++ if Mode = "00" and IR(1) = '1' then
++ LCycle <= "001";
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ case IR(7 downto 4) is
++ when "0000" =>
++ Write_Data <= "101"; -- P
++ when "0100" =>
++ Write_Data <= "001"; -- A
++ when "0101" =>
++ Write_Data <= "011"; -- Y
++ when "1101" =>
++ Write_Data <= "010"; -- X
++ when others =>
++ end case;
++ Write <= '1';
++ Set_Addr_To <= "01"; -- S
++ when 2 =>
++ Dec_S <= '1';
++ when others =>
++ end case;
++ when "00101000" | "01101000" | "01111010" | "11111010" =>
++ -- PLP, PLA, PLY*, PLX*
++ LCycle <= "011";
++ if Mode = "00" and IR(1) = '1' then
++ LCycle <= "001";
++ end if;
++ case IR(7 downto 4) is
++ when "0010" =>
++ LDP <= '1';
++ when "0110" =>
++ LDA <= '1';
++ when "0111" =>
++ if Mode /= "00" then
++ LDY <= '1';
++ end if;
++ when "1111" =>
++ if Mode /= "00" then
++ LDX <= '1';
++ end if;
++ when others =>
++ end case;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ SaveP <= '1';
++ when 1 =>
++ Set_Addr_To <= "01"; -- S
++ when 2 =>
++ Inc_S <= '1';
++ Set_Addr_To <= "01"; -- S
++ when 3 =>
++ Set_BusA_To <= "000"; -- DI
++ when others =>
++ end case;
++ when "10100000" | "11000000" | "11100000" =>
++ -- LDY, CPY, CPX
++ -- Immediate
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ when others =>
++ end case;
++ when "10001000" =>
++ -- DEY
++ LDY <= '1';
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Set_BusA_To <= "011"; -- Y
++ when others =>
++ end case;
++ when "11001010" =>
++ -- DEX
++ LDX <= '1';
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Set_BusA_To <= "010"; -- X
++ when others =>
++ end case;
++ when "00011010" | "00111010" =>
++ -- INC*, DEC*
++ if Mode /= "00" then
++ LDA <= '1'; -- A
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Set_BusA_To <= "100"; -- S
++ when others =>
++ end case;
++ when "00001010" | "00101010" | "01001010" | "01101010" =>
++ -- ASL, ROL, LSR, ROR
++ LDA <= '1'; -- A
++ Set_BusA_To <= "001"; -- A
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ when others =>
++ end case;
++ when "10001010" | "10011000" =>
++ -- TYA, TXA
++ LDA <= '1'; -- A
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ when others =>
++ end case;
++ when "10101010" | "10101000" =>
++ -- TAX, TAY
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Set_BusA_To <= "001"; -- A
++ when others =>
++ end case;
++ when "10011010" =>
++ -- TXS
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ LDS <= '1';
++ when 1 =>
++ when others =>
++ end case;
++ when "10111010" =>
++ -- TSX
++ LDX <= '1';
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Set_BusA_To <= "100"; -- S
++ when others =>
++ end case;
++
++ -- when "00011000" | "00111000" | "01011000" | "01111000" | "10111000" | "11011000" | "11111000" | "11001000" | "11101000" =>
++ -- -- CLC, SEC, CLI, SEI, CLV, CLD, SED, INY, INX
++ -- case to_integer(unsigned(MCycle)) is
++ -- when 1 =>
++ -- when others =>
++ -- end case;
++ when others =>
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when others =>
++ end case;
++ end case;
++ --}}}
++
++ when "00001" | "00011" =>
++ --{{{
++ -- Zero Page Indexed Indirect (d,x)
++ LCycle <= "101";
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 2 =>
++ ADAdd <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 3 =>
++ BAAdd <= "01"; -- DB Inc
++ LDBAL <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 4 =>
++ LDBAH <= '1';
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ end if;
++ Set_Addr_To <= "11"; -- BA
++ when 5 =>
++ when others =>
++ end case;
++ --}}}
++
++ when "01001" | "01011" =>
++ --{{{
++ -- Immediate
++ LDA <= '1';
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ when others =>
++ end case;
++
++ --}}}
++
++ when "00010" | "10010" =>
++ --{{{
++ -- Immediate, KIL
++ LDX <= '1';
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ if IR = "10100010" then
++ -- LDX
++ Jump <= "01";
++ else
++ -- KIL !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
++ end if;
++ when others =>
++ end case;
++ --}}}
++
++ when "00100" =>
++ --{{{
++ -- Zero Page
++ LCycle <= "010";
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ if IR(7 downto 5) = "001" then
++ SaveP <= '1';
++ end if;
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ end if;
++ Set_Addr_To <= "10"; -- AD
++ when 2 =>
++ when others =>
++ end case;
++ --}}}
++
++ when "00101" | "00110" | "00111" =>
++ --{{{
++ -- Zero Page
++ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
++ -- Read-Modify-Write
++ LCycle <= "100";
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 2 =>
++ LDDI <= '1';
++ Write <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 3 =>
++ LDALU <= '1';
++ SaveP <= '1';
++ Write <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 4 =>
++ when others =>
++ end case;
++ else
++ LCycle <= "010";
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ end if;
++ Set_Addr_To <= "10"; -- AD
++ when 2 =>
++ when others =>
++ end case;
++ end if;
++ --}}}
++
++ when "01100" =>
++ --{{{
++ -- Absolute
++ if IR(7 downto 6) = "01" and IR(4 downto 0) = "01100" then
++ -- JMP
++ if IR(5) = '0' then
++ --LCycle <= "011";
++ LCycle <= "010";
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDDI <= '1';
++ when 2 =>
++ Jump <= "10"; -- DIDL
++ when others =>
++ end case;
++ else
++ --LCycle <= "101";
++ LCycle <= "100"; -- mikej
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDDI <= '1';
++ LDBAL <= '1';
++ when 2 =>
++ LDBAH <= '1';
++ if Mode /= "00" then
++ Jump <= "10"; -- DIDL
++ end if;
++ if Mode = "00" then
++ Set_Addr_To <= "11"; -- BA
++ end if;
++ when 3 =>
++ LDDI <= '1';
++ if Mode = "00" then
++ Set_Addr_To <= "11"; -- BA
++ BAAdd <= "01"; -- DB Inc
++ else
++ Jump <= "01";
++ end if;
++ when 4 =>
++ Jump <= "10"; -- DIDL
++ when others =>
++ end case;
++ end if;
++ else
++ LCycle <= "011";
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ if IR(7 downto 5) = "001" then
++ SaveP <= '1';
++ end if;
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ LDBAH <= '1';
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ end if;
++ Set_Addr_To <= "11"; -- BA
++ when 3 =>
++ when others =>
++ end case;
++ end if;
++ --}}}
++
++ when "01101" | "01110" | "01111" =>
++ --{{{
++ -- Absolute
++ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
++ -- Read-Modify-Write
++ LCycle <= "101";
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ LDBAH <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 3 =>
++ LDDI <= '1';
++ Write <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 4 =>
++ Write <= '1';
++ LDALU <= '1';
++ SaveP <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 5 =>
++ SaveP <= '0'; -- MIKEJ was 1
++ when others =>
++ end case;
++ else
++ LCycle <= "011";
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ LDBAH <= '1';
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ end if;
++ Set_Addr_To <= "11"; -- BA
++ when 3 =>
++ when others =>
++ end case;
++ end if;
++ --}}}
++
++ when "10000" =>
++ --{{{
++ -- Relative
++
++ -- This circuit dictates when the last
++ -- microcycle occurs for the branch depending on
++ -- whether or not the branch is taken and if a page
++ -- is crossed...
++ if (Branch = '1') then
++
++ LCycle <= "011"; -- We're done @ T3 if branching...upper
++ -- level logic will stop at T2 if no page cross
++ -- (See the Break signal)
++ else
++
++ LCycle <= "001";
++
++ end if;
++
++ -- This decodes the current microcycle and takes the
++ -- proper course of action...
++ case to_integer(unsigned(MCycle)) is
++
++ -- On the T1 microcycle, increment the program counter
++ -- and instruct the upper level logic to fetch the offset
++ -- from the Din bus and store it in the data latches. This
++ -- will be the last microcycle if the branch isn't taken.
++ when 1 =>
++
++ Jump <= "01"; -- Increments the PC by one (PC will now be PC+2)
++ -- from microcycle T0.
++
++ LDDI <= '1'; -- Tells logic in top level (T65.vhd) to route
++ -- the Din bus to the memory data latch (DL)
++ -- so that the branch offset is fetched.
++
++ -- In microcycle T2, tell the logic in the top level to
++ -- add the offset. If the most significant byte of the
++ -- program counter (i.e. the current "page") does not need
++ -- updating, we are done here...the Break signal at the
++ -- T65.vhd level takes care of that...
++ when 2 =>
++
++ Jump <= "11"; -- Tell the PC Jump logic to use relative mode.
++
++ PCAdd <= '1'; -- This tells the PC adder to update itself with
++ -- the current offset recently fetched from
++ -- memory.
++
++ -- The following is microcycle T3 :
++ -- The program counter should be completely updated
++ -- on this cycle after the page cross is detected.
++ -- We don't need to do anything here...
++ when 3 =>
++
++
++ when others => null; -- Do nothing.
++
++ end case;
++ --}}}
++
++ when "10001" | "10011" =>
++ --{{{
++ -- Zero Page Indirect Indexed (d),y
++ LCycle <= "101";
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 2 =>
++ LDBAL <= '1';
++ BAAdd <= "01"; -- DB Inc
++ Set_Addr_To <= "10"; -- AD
++ when 3 =>
++ Set_BusA_To <= "011"; -- Y
++ BAAdd <= "10"; -- BA Add
++ LDBAH <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 4 =>
++ BAAdd <= "11"; -- BA Adj
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ else
++ BreakAtNA <= '1';
++ end if;
++ Set_Addr_To <= "11"; -- BA
++ when 5 =>
++ when others =>
++ end case;
++ --}}}
++
++ when "10100" | "10101" | "10110" | "10111" =>
++ --{{{
++ -- Zero Page, X
++ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
++ -- Read-Modify-Write
++ LCycle <= "101";
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 2 =>
++ ADAdd <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 3 =>
++ LDDI <= '1';
++ Write <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 4 =>
++ LDALU <= '1';
++ SaveP <= '1';
++ Write <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 5 =>
++ when others =>
++ end case;
++ else
++ LCycle <= "011";
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDAD <= '1';
++ Set_Addr_To <= "10"; -- AD
++ when 2 =>
++ ADAdd <= '1';
++ -- Added this check for Y reg. use...
++ if (IR(3 downto 0) = "0110") then
++ AddY <= '1';
++ end if;
++
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ end if;
++ Set_Addr_To <= "10"; -- AD
++ when 3 => null;
++ when others =>
++ end case;
++ end if;
++ --}}}
++
++ when "11001" | "11011" =>
++ --{{{
++ -- Absolute Y
++ LCycle <= "100";
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ Set_BusA_To <= "011"; -- Y
++ BAAdd <= "10"; -- BA Add
++ LDBAH <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 3 =>
++ BAAdd <= "11"; -- BA adj
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ else
++ BreakAtNA <= '1';
++ end if;
++ Set_Addr_To <= "11"; -- BA
++ when 4 =>
++ when others =>
++ end case;
++ --}}}
++
++ when "11100" | "11101" | "11110" | "11111" =>
++ --{{{
++ -- Absolute X
++
++ if IR(7 downto 6) /= "10" and IR(1 downto 0) = "10" then
++ -- Read-Modify-Write
++ LCycle <= "110";
++ case to_integer(unsigned(MCycle)) is
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ Set_BusA_To <= "010"; -- X
++ BAAdd <= "10"; -- BA Add
++ LDBAH <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 3 =>
++ BAAdd <= "11"; -- BA adj
++ Set_Addr_To <= "11"; -- BA
++ when 4 =>
++ LDDI <= '1';
++ Write <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 5 =>
++ LDALU <= '1';
++ SaveP <= '1';
++ Write <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 6 =>
++ when others =>
++ end case;
++ else
++ LCycle <= "100";
++ if IR(7 downto 6) /= "10" then
++ LDA <= '1';
++ end if;
++ case to_integer(unsigned(MCycle)) is
++ when 0 =>
++ when 1 =>
++ Jump <= "01";
++ LDBAL <= '1';
++ when 2 =>
++ Jump <= "01";
++ -- mikej
++ -- special case 0xBE which uses Y reg as index!!
++ if (IR = "10111110") then
++ Set_BusA_To <= "011"; -- Y
++ else
++ Set_BusA_To <= "010"; -- X
++ end if;
++ BAAdd <= "10"; -- BA Add
++ LDBAH <= '1';
++ Set_Addr_To <= "11"; -- BA
++ when 3 =>
++ BAAdd <= "11"; -- BA adj
++ if IR(7 downto 5) = "100" then
++ Write <= '1';
++ else
++ BreakAtNA <= '1';
++ end if;
++ Set_Addr_To <= "11"; -- BA
++ when 4 =>
++ when others =>
++ end case;
++ end if;
++ --}}}
++ when others =>
++ end case;
++ end process;
++
++ process (IR, MCycle)
++ begin
++ -- ORA, AND, EOR, ADC, NOP, LD, CMP, SBC
++ -- ASL, ROL, LSR, ROR, BIT, LD, DEC, INC
++ case IR(1 downto 0) is
++ when "00" =>
++ --{{{
++ case IR(4 downto 2) is
++ when "000" | "001" | "011" =>
++ case IR(7 downto 5) is
++ when "110" | "111" =>
++ -- CP
++ ALU_Op <= "0110";
++ when "101" =>
++ -- LD
++ ALU_Op <= "0101";
++ when "001" =>
++ -- BIT
++ ALU_Op <= "1100";
++ when others =>
++ -- NOP/ST
++ ALU_Op <= "0100";
++ end case;
++ when "010" =>
++ case IR(7 downto 5) is
++ when "111" | "110" =>
++ -- IN
++ ALU_Op <= "1111";
++ when "100" =>
++ -- DEY
++ ALU_Op <= "1110";
++ when others =>
++ -- LD
++ ALU_Op <= "1101";
++ end case;
++ when "110" =>
++ case IR(7 downto 5) is
++ when "100" =>
++ -- TYA
++ ALU_Op <= "1101";
++ when others =>
++ ALU_Op <= "----";
++ end case;
++ when others =>
++ case IR(7 downto 5) is
++ when "101" =>
++ -- LD
++ ALU_Op <= "1101";
++ when others =>
++ ALU_Op <= "0100";
++ end case;
++ end case;
++ --}}}
++ when "01" => -- OR
++ --{{{
++ ALU_Op(3) <= '0';
++ ALU_Op(2 downto 0) <= IR(7 downto 5);
++ --}}}
++ when "10" =>
++ --{{{
++ ALU_Op(3) <= '1';
++ ALU_Op(2 downto 0) <= IR(7 downto 5);
++ case IR(7 downto 5) is
++ when "000" =>
++ if IR(4 downto 2) = "110" then
++ -- INC
++ ALU_Op <= "1111";
++ end if;
++ when "001" =>
++ if IR(4 downto 2) = "110" then
++ -- DEC
++ ALU_Op <= "1110";
++ end if;
++ when "100" =>
++ if IR(4 downto 2) = "010" then
++ -- TXA
++ ALU_Op <= "0101";
++ else
++ ALU_Op <= "0100";
++ end if;
++ when others =>
++ end case;
++ --}}}
++ when others =>
++ --{{{
++ case IR(7 downto 5) is
++ when "100" =>
++ ALU_Op <= "0100";
++ when others =>
++ if MCycle = "000" then
++ ALU_Op(3) <= '0';
++ ALU_Op(2 downto 0) <= IR(7 downto 5);
++ else
++ ALU_Op(3) <= '1';
++ ALU_Op(2 downto 0) <= IR(7 downto 5);
++ end if;
++ end case;
++ --}}}
++ end case;
++ end process;
++
++end;
+diff --git a/T65/T65_Pack.vhd b/T65/T65_Pack.vhd
+index f8d603c..e025e1b 100644
+--- a/T65/T65_Pack.vhd
++++ b/T65/T65_Pack.vhd
+@@ -1,117 +1,117 @@
+--- ****
+--- T65(b) core. In an effort to merge and maintain bug fixes ....
+---
+---
+--- Ver 300 Bugfixes by ehenciak added
+--- MikeJ March 2005
+--- Latest version from www.fpgaarcade.com (original www.opencores.org)
+---
+--- ****
+---
+--- 65xx compatible microprocessor core
+---
+--- Version : 0246
+---
+--- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- Please report bugs to the author, but before you do so, please
+--- make sure that this is not a derivative work and that
+--- you have the latest version of this file.
+---
+--- The latest version of this file can be found at:
+--- http://www.opencores.org/cvsweb.shtml/t65/
+---
+--- Limitations :
+---
+--- File history :
+---
+-
+-library IEEE;
+-use IEEE.std_logic_1164.all;
+-
+-package T65_Pack is
+-
+- constant Flag_C : integer := 0;
+- constant Flag_Z : integer := 1;
+- constant Flag_I : integer := 2;
+- constant Flag_D : integer := 3;
+- constant Flag_B : integer := 4;
+- constant Flag_1 : integer := 5;
+- constant Flag_V : integer := 6;
+- constant Flag_N : integer := 7;
+-
+- component T65_MCode
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
+- IR : in std_logic_vector(7 downto 0);
+- MCycle : in std_logic_vector(2 downto 0);
+- P : in std_logic_vector(7 downto 0);
+- LCycle : out std_logic_vector(2 downto 0);
+- ALU_Op : out std_logic_vector(3 downto 0);
+- Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
+- Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
+- Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
+- Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
+- BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
+- BreakAtNA : out std_logic;
+- ADAdd : out std_logic;
+- AddY : out std_logic;
+- PCAdd : out std_logic;
+- Inc_S : out std_logic;
+- Dec_S : out std_logic;
+- LDA : out std_logic;
+- LDP : out std_logic;
+- LDX : out std_logic;
+- LDY : out std_logic;
+- LDS : out std_logic;
+- LDDI : out std_logic;
+- LDALU : out std_logic;
+- LDAD : out std_logic;
+- LDBAL : out std_logic;
+- LDBAH : out std_logic;
+- SaveP : out std_logic;
+- Write : out std_logic
+- );
+- end component;
+-
+- component T65_ALU
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
+- Op : in std_logic_vector(3 downto 0);
+- BusA : in std_logic_vector(7 downto 0);
+- BusB : in std_logic_vector(7 downto 0);
+- P_In : in std_logic_vector(7 downto 0);
+- P_Out : out std_logic_vector(7 downto 0);
+- Q : out std_logic_vector(7 downto 0)
+- );
+- end component;
+-
+-end;
++-- ****
++-- T65(b) core. In an effort to merge and maintain bug fixes ....
++--
++--
++-- Ver 300 Bugfixes by ehenciak added
++-- MikeJ March 2005
++-- Latest version from www.fpgaarcade.com (original www.opencores.org)
++--
++-- ****
++--
++-- 65xx compatible microprocessor core
++--
++-- Version : 0246
++--
++-- Copyright (c) 2002 Daniel Wallner (jesus@opencores.org)
++--
++-- All rights reserved
++--
++-- Redistribution and use in source and synthezised forms, with or without
++-- modification, are permitted provided that the following conditions are met:
++--
++-- Redistributions of source code must retain the above copyright notice,
++-- this list of conditions and the following disclaimer.
++--
++-- Redistributions in synthesized form must reproduce the above copyright
++-- notice, this list of conditions and the following disclaimer in the
++-- documentation and/or other materials provided with the distribution.
++--
++-- Neither the name of the author nor the names of other contributors may
++-- be used to endorse or promote products derived from this software without
++-- specific prior written permission.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++-- Please report bugs to the author, but before you do so, please
++-- make sure that this is not a derivative work and that
++-- you have the latest version of this file.
++--
++-- The latest version of this file can be found at:
++-- http://www.opencores.org/cvsweb.shtml/t65/
++--
++-- Limitations :
++--
++-- File history :
++--
++
++library IEEE;
++use IEEE.std_logic_1164.all;
++
++package T65_Pack is
++
++ constant Flag_C : integer := 0;
++ constant Flag_Z : integer := 1;
++ constant Flag_I : integer := 2;
++ constant Flag_D : integer := 3;
++ constant Flag_B : integer := 4;
++ constant Flag_1 : integer := 5;
++ constant Flag_V : integer := 6;
++ constant Flag_N : integer := 7;
++
++ component T65_MCode
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65816
++ IR : in std_logic_vector(7 downto 0);
++ MCycle : in std_logic_vector(2 downto 0);
++ P : in std_logic_vector(7 downto 0);
++ LCycle : out std_logic_vector(2 downto 0);
++ ALU_Op : out std_logic_vector(3 downto 0);
++ Set_BusA_To : out std_logic_vector(2 downto 0); -- DI,A,X,Y,S,P
++ Set_Addr_To : out std_logic_vector(1 downto 0); -- PC Adder,S,AD,BA
++ Write_Data : out std_logic_vector(2 downto 0); -- DL,A,X,Y,S,P,PCL,PCH
++ Jump : out std_logic_vector(1 downto 0); -- PC,++,DIDL,Rel
++ BAAdd : out std_logic_vector(1 downto 0); -- None,DB Inc,BA Add,BA Adj
++ BreakAtNA : out std_logic;
++ ADAdd : out std_logic;
++ AddY : out std_logic;
++ PCAdd : out std_logic;
++ Inc_S : out std_logic;
++ Dec_S : out std_logic;
++ LDA : out std_logic;
++ LDP : out std_logic;
++ LDX : out std_logic;
++ LDY : out std_logic;
++ LDS : out std_logic;
++ LDDI : out std_logic;
++ LDALU : out std_logic;
++ LDAD : out std_logic;
++ LDBAL : out std_logic;
++ LDBAH : out std_logic;
++ SaveP : out std_logic;
++ Write : out std_logic
++ );
++ end component;
++
++ component T65_ALU
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
++ Op : in std_logic_vector(3 downto 0);
++ BusA : in std_logic_vector(7 downto 0);
++ BusB : in std_logic_vector(7 downto 0);
++ P_In : in std_logic_vector(7 downto 0);
++ P_Out : out std_logic_vector(7 downto 0);
++ Q : out std_logic_vector(7 downto 0)
++ );
++ end component;
++
++end;
+diff --git a/bbc_micro.qpf b/bbc_micro.qpf
+index 52e0fd0..c2ade9e 100644
+--- a/bbc_micro.qpf
++++ b/bbc_micro.qpf
+@@ -1,30 +1,30 @@
+-# -------------------------------------------------------------------------- #
+-#
+-# Copyright (C) 1991-2009 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
+-# Version 9.1 Build 222 10/21/2009 SJ Web Edition
+-# Date created = 20:48:44 July 12, 2011
+-#
+-# -------------------------------------------------------------------------- #
+-
+-QUARTUS_VERSION = "9.1"
+-DATE = "20:48:44 July 12, 2011"
+-
+-# Revisions
+-
+-PROJECT_REVISION = "bbc_micro_de1"
++# -------------------------------------------------------------------------- #
++#
++# Copyright (C) 1991-2009 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
++# Version 9.1 Build 222 10/21/2009 SJ Web Edition
++# Date created = 20:48:44 July 12, 2011
++#
++# -------------------------------------------------------------------------- #
++
++QUARTUS_VERSION = "9.1"
++DATE = "20:48:44 July 12, 2011"
++
++# Revisions
++
++PROJECT_REVISION = "bbc_micro_de1"
+diff --git a/bbc_micro_de1.qsf b/bbc_micro_de1.qsf
+index be8b1f2..0ae4816 100644
+--- a/bbc_micro_de1.qsf
++++ b/bbc_micro_de1.qsf
+@@ -1,537 +1,537 @@
+-# -------------------------------------------------------------------------- #
+-#
+-# Copyright (C) 1991-2009 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
+-# Version 9.1 Build 222 10/21/2009 SJ Web Edition
+-# Date created = 20:48:44 July 12, 2011
+-#
+-# -------------------------------------------------------------------------- #
+-#
+-# Notes:
+-#
+-# 1) The default values for assignments are stored in the file:
+-# bbc_micro_de1_assignment_defaults.qdf
+-# If this file doesn't exist, see file:
+-# assignment_defaults.qdf
+-#
+-# 2) Altera recommends that you do not modify this file. This
+-# file is updated automatically by the Quartus II software
+-# and any changes you make may be lost or overwritten.
+-#
+-# -------------------------------------------------------------------------- #
+-
+-
+-set_global_assignment -name FAMILY "Cyclone II"
+-set_global_assignment -name DEVICE EP2C20F484C7
+-set_global_assignment -name TOP_LEVEL_ENTITY bbc_micro_de1
+-set_global_assignment -name ORIGINAL_QUARTUS_VERSION 9.1
+-set_global_assignment -name PROJECT_CREATION_TIME_DATE "20:48:44 JULY 12, 2011"
+-set_global_assignment -name LAST_QUARTUS_VERSION 9.1
+-set_global_assignment -name USE_GENERATED_PHYSICAL_CONSTRAINTS OFF -section_id eda_blast_fpga
+-set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA
+-set_global_assignment -name DEVICE_FILTER_PIN_COUNT 484
+-set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 7
+-set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
+-set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
+-set_location_assignment PIN_A13 -to GPIO_0[0]
+-set_location_assignment PIN_B13 -to GPIO_0[1]
+-set_location_assignment PIN_A14 -to GPIO_0[2]
+-set_location_assignment PIN_B14 -to GPIO_0[3]
+-set_location_assignment PIN_A15 -to GPIO_0[4]
+-set_location_assignment PIN_B15 -to GPIO_0[5]
+-set_location_assignment PIN_A16 -to GPIO_0[6]
+-set_location_assignment PIN_B16 -to GPIO_0[7]
+-set_location_assignment PIN_A17 -to GPIO_0[8]
+-set_location_assignment PIN_B17 -to GPIO_0[9]
+-set_location_assignment PIN_A18 -to GPIO_0[10]
+-set_location_assignment PIN_B18 -to GPIO_0[11]
+-set_location_assignment PIN_A19 -to GPIO_0[12]
+-set_location_assignment PIN_B19 -to GPIO_0[13]
+-set_location_assignment PIN_A20 -to GPIO_0[14]
+-set_location_assignment PIN_B20 -to GPIO_0[15]
+-set_location_assignment PIN_C21 -to GPIO_0[16]
+-set_location_assignment PIN_C22 -to GPIO_0[17]
+-set_location_assignment PIN_D21 -to GPIO_0[18]
+-set_location_assignment PIN_D22 -to GPIO_0[19]
+-set_location_assignment PIN_E21 -to GPIO_0[20]
+-set_location_assignment PIN_E22 -to GPIO_0[21]
+-set_location_assignment PIN_F21 -to GPIO_0[22]
+-set_location_assignment PIN_F22 -to GPIO_0[23]
+-set_location_assignment PIN_G21 -to GPIO_0[24]
+-set_location_assignment PIN_G22 -to GPIO_0[25]
+-set_location_assignment PIN_J21 -to GPIO_0[26]
+-set_location_assignment PIN_J22 -to GPIO_0[27]
+-set_location_assignment PIN_K21 -to GPIO_0[28]
+-set_location_assignment PIN_K22 -to GPIO_0[29]
+-set_location_assignment PIN_J19 -to GPIO_0[30]
+-set_location_assignment PIN_J20 -to GPIO_0[31]
+-set_location_assignment PIN_J18 -to GPIO_0[32]
+-set_location_assignment PIN_K20 -to GPIO_0[33]
+-set_location_assignment PIN_L19 -to GPIO_0[34]
+-set_location_assignment PIN_L18 -to GPIO_0[35]
+-set_location_assignment PIN_H12 -to GPIO_1[0]
+-set_location_assignment PIN_H13 -to GPIO_1[1]
+-set_location_assignment PIN_H14 -to GPIO_1[2]
+-set_location_assignment PIN_G15 -to GPIO_1[3]
+-set_location_assignment PIN_E14 -to GPIO_1[4]
+-set_location_assignment PIN_E15 -to GPIO_1[5]
+-set_location_assignment PIN_F15 -to GPIO_1[6]
+-set_location_assignment PIN_G16 -to GPIO_1[7]
+-set_location_assignment PIN_F12 -to GPIO_1[8]
+-set_location_assignment PIN_F13 -to GPIO_1[9]
+-set_location_assignment PIN_C14 -to GPIO_1[10]
+-set_location_assignment PIN_D14 -to GPIO_1[11]
+-set_location_assignment PIN_D15 -to GPIO_1[12]
+-set_location_assignment PIN_D16 -to GPIO_1[13]
+-set_location_assignment PIN_C17 -to GPIO_1[14]
+-set_location_assignment PIN_C18 -to GPIO_1[15]
+-set_location_assignment PIN_C19 -to GPIO_1[16]
+-set_location_assignment PIN_C20 -to GPIO_1[17]
+-set_location_assignment PIN_D19 -to GPIO_1[18]
+-set_location_assignment PIN_D20 -to GPIO_1[19]
+-set_location_assignment PIN_E20 -to GPIO_1[20]
+-set_location_assignment PIN_F20 -to GPIO_1[21]
+-set_location_assignment PIN_E19 -to GPIO_1[22]
+-set_location_assignment PIN_E18 -to GPIO_1[23]
+-set_location_assignment PIN_G20 -to GPIO_1[24]
+-set_location_assignment PIN_G18 -to GPIO_1[25]
+-set_location_assignment PIN_G17 -to GPIO_1[26]
+-set_location_assignment PIN_H17 -to GPIO_1[27]
+-set_location_assignment PIN_J15 -to GPIO_1[28]
+-set_location_assignment PIN_H18 -to GPIO_1[29]
+-set_location_assignment PIN_N22 -to GPIO_1[30]
+-set_location_assignment PIN_N21 -to GPIO_1[31]
+-set_location_assignment PIN_P15 -to GPIO_1[32]
+-set_location_assignment PIN_N15 -to GPIO_1[33]
+-set_location_assignment PIN_P17 -to GPIO_1[34]
+-set_location_assignment PIN_P18 -to GPIO_1[35]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[7]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[8]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[9]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[10]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[11]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[12]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[13]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[14]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[15]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[16]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[17]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[18]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[19]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[20]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[21]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[22]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[23]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[24]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[25]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[26]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[27]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[28]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[29]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[30]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[31]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[32]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[33]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[34]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[35]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[7]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[8]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[9]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[10]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[11]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[12]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[13]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[14]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[15]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[16]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[17]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[18]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[19]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[20]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[21]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[22]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[23]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[24]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[25]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[26]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[27]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[28]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[29]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[30]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[31]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[32]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[33]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[34]
+-set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[35]
+-set_location_assignment PIN_L22 -to SW[0]
+-set_location_assignment PIN_L21 -to SW[1]
+-set_location_assignment PIN_M22 -to SW[2]
+-set_location_assignment PIN_V12 -to SW[3]
+-set_location_assignment PIN_W12 -to SW[4]
+-set_location_assignment PIN_U12 -to SW[5]
+-set_location_assignment PIN_U11 -to SW[6]
+-set_location_assignment PIN_M2 -to SW[7]
+-set_location_assignment PIN_M1 -to SW[8]
+-set_location_assignment PIN_L2 -to SW[9]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[7]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[8]
+-set_instance_assignment -name IO_STANDARD LVTTL -to SW[9]
+-set_location_assignment PIN_J2 -to HEX0[0]
+-set_location_assignment PIN_J1 -to HEX0[1]
+-set_location_assignment PIN_H2 -to HEX0[2]
+-set_location_assignment PIN_H1 -to HEX0[3]
+-set_location_assignment PIN_F2 -to HEX0[4]
+-set_location_assignment PIN_F1 -to HEX0[5]
+-set_location_assignment PIN_E2 -to HEX0[6]
+-set_location_assignment PIN_E1 -to HEX1[0]
+-set_location_assignment PIN_H6 -to HEX1[1]
+-set_location_assignment PIN_H5 -to HEX1[2]
+-set_location_assignment PIN_H4 -to HEX1[3]
+-set_location_assignment PIN_G3 -to HEX1[4]
+-set_location_assignment PIN_D2 -to HEX1[5]
+-set_location_assignment PIN_D1 -to HEX1[6]
+-set_location_assignment PIN_G5 -to HEX2[0]
+-set_location_assignment PIN_G6 -to HEX2[1]
+-set_location_assignment PIN_C2 -to HEX2[2]
+-set_location_assignment PIN_C1 -to HEX2[3]
+-set_location_assignment PIN_E3 -to HEX2[4]
+-set_location_assignment PIN_E4 -to HEX2[5]
+-set_location_assignment PIN_D3 -to HEX2[6]
+-set_location_assignment PIN_F4 -to HEX3[0]
+-set_location_assignment PIN_D5 -to HEX3[1]
+-set_location_assignment PIN_D6 -to HEX3[2]
+-set_location_assignment PIN_J4 -to HEX3[3]
+-set_location_assignment PIN_L8 -to HEX3[4]
+-set_location_assignment PIN_F3 -to HEX3[5]
+-set_location_assignment PIN_D4 -to HEX3[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[6]
+-set_location_assignment PIN_R22 -to KEY[0]
+-set_location_assignment PIN_R21 -to KEY[1]
+-set_location_assignment PIN_T22 -to KEY[2]
+-set_location_assignment PIN_T21 -to KEY[3]
+-set_location_assignment PIN_R20 -to LEDR[0]
+-set_location_assignment PIN_R19 -to LEDR[1]
+-set_location_assignment PIN_U19 -to LEDR[2]
+-set_location_assignment PIN_Y19 -to LEDR[3]
+-set_location_assignment PIN_T18 -to LEDR[4]
+-set_location_assignment PIN_V19 -to LEDR[5]
+-set_location_assignment PIN_Y18 -to LEDR[6]
+-set_location_assignment PIN_U18 -to LEDR[7]
+-set_location_assignment PIN_R18 -to LEDR[8]
+-set_location_assignment PIN_R17 -to LEDR[9]
+-set_location_assignment PIN_U22 -to LEDG[0]
+-set_location_assignment PIN_U21 -to LEDG[1]
+-set_location_assignment PIN_V22 -to LEDG[2]
+-set_location_assignment PIN_V21 -to LEDG[3]
+-set_location_assignment PIN_W22 -to LEDG[4]
+-set_location_assignment PIN_W21 -to LEDG[5]
+-set_location_assignment PIN_Y22 -to LEDG[6]
+-set_location_assignment PIN_Y21 -to LEDG[7]
+-set_instance_assignment -name IO_STANDARD LVTTL -to KEY[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to KEY[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to KEY[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to KEY[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[7]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[8]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[9]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[4]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[5]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[6]
+-set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[7]
+-set_location_assignment PIN_D12 -to CLOCK_27[0]
+-set_location_assignment PIN_E12 -to CLOCK_27[1]
+-set_location_assignment PIN_B12 -to CLOCK_24[0]
+-set_location_assignment PIN_A12 -to CLOCK_24[1]
+-set_location_assignment PIN_L1 -to CLOCK_50
+-set_location_assignment PIN_M21 -to EXT_CLOCK
+-set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_27[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_24[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_24[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_50
+-set_instance_assignment -name IO_STANDARD LVTTL -to EXT_CLOCK
+-set_location_assignment PIN_H15 -to PS2_CLK
+-set_location_assignment PIN_J14 -to PS2_DAT
+-set_location_assignment PIN_F14 -to UART_RXD
+-set_location_assignment PIN_G12 -to UART_TXD
+-set_instance_assignment -name IO_STANDARD LVTTL -to PS2_CLK
+-set_instance_assignment -name IO_STANDARD LVTTL -to PS2_DAT
+-set_instance_assignment -name IO_STANDARD LVTTL -to UART_RXD
+-set_instance_assignment -name IO_STANDARD LVTTL -to UART_TXD
+-set_location_assignment PIN_E8 -to TDI
+-set_location_assignment PIN_D8 -to TCS
+-set_location_assignment PIN_C7 -to TCK
+-set_location_assignment PIN_D7 -to TDO
+-set_instance_assignment -name IO_STANDARD LVTTL -to TDI
+-set_instance_assignment -name IO_STANDARD LVTTL -to TCS
+-set_instance_assignment -name IO_STANDARD LVTTL -to TCK
+-set_instance_assignment -name IO_STANDARD LVTTL -to TDO
+-set_location_assignment PIN_D9 -to VGA_R[0]
+-set_location_assignment PIN_C9 -to VGA_R[1]
+-set_location_assignment PIN_A7 -to VGA_R[2]
+-set_location_assignment PIN_B7 -to VGA_R[3]
+-set_location_assignment PIN_B8 -to VGA_G[0]
+-set_location_assignment PIN_C10 -to VGA_G[1]
+-set_location_assignment PIN_B9 -to VGA_G[2]
+-set_location_assignment PIN_A8 -to VGA_G[3]
+-set_location_assignment PIN_A9 -to VGA_B[0]
+-set_location_assignment PIN_D11 -to VGA_B[1]
+-set_location_assignment PIN_A10 -to VGA_B[2]
+-set_location_assignment PIN_B10 -to VGA_B[3]
+-set_location_assignment PIN_A11 -to VGA_HS
+-set_location_assignment PIN_B11 -to VGA_VS
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[0]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[1]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[2]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[3]
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_HS
+-set_instance_assignment -name IO_STANDARD LVTTL -to VGA_VS
+-set_location_assignment PIN_A3 -to I2C_SCLK
+-set_location_assignment PIN_B3 -to I2C_SDAT
+-set_location_assignment PIN_A6 -to AUD_ADCLRCK
+-set_location_assignment PIN_B6 -to AUD_ADCDAT
+-set_location_assignment PIN_A5 -to AUD_DACLRCK
+-set_location_assignment PIN_B5 -to AUD_DACDAT
+-set_location_assignment PIN_B4 -to AUD_XCK
+-set_location_assignment PIN_A4 -to AUD_BCLK
+-set_instance_assignment -name IO_STANDARD LVTTL -to I2C_SCLK
+-set_instance_assignment -name IO_STANDARD LVTTL -to I2C_SDAT
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_ADCLRCK
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_ADCDAT
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_DACLRCK
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_DACDAT
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_XCK
+-set_instance_assignment -name IO_STANDARD LVTTL -to AUD_BCLK
+-set_location_assignment PIN_W4 -to DRAM_ADDR[0]
+-set_location_assignment PIN_W5 -to DRAM_ADDR[1]
+-set_location_assignment PIN_Y3 -to DRAM_ADDR[2]
+-set_location_assignment PIN_Y4 -to DRAM_ADDR[3]
+-set_location_assignment PIN_R6 -to DRAM_ADDR[4]
+-set_location_assignment PIN_R5 -to DRAM_ADDR[5]
+-set_location_assignment PIN_P6 -to DRAM_ADDR[6]
+-set_location_assignment PIN_P5 -to DRAM_ADDR[7]
+-set_location_assignment PIN_P3 -to DRAM_ADDR[8]
+-set_location_assignment PIN_N4 -to DRAM_ADDR[9]
+-set_location_assignment PIN_W3 -to DRAM_ADDR[10]
+-set_location_assignment PIN_N6 -to DRAM_ADDR[11]
+-set_location_assignment PIN_U3 -to DRAM_BA_0
+-set_location_assignment PIN_V4 -to DRAM_BA_1
+-set_location_assignment PIN_T3 -to DRAM_CAS_N
+-set_location_assignment PIN_N3 -to DRAM_CKE
+-set_location_assignment PIN_U4 -to DRAM_CLK
+-set_location_assignment PIN_T6 -to DRAM_CS_N
+-set_location_assignment PIN_U1 -to DRAM_DQ[0]
+-set_location_assignment PIN_U2 -to DRAM_DQ[1]
+-set_location_assignment PIN_V1 -to DRAM_DQ[2]
+-set_location_assignment PIN_V2 -to DRAM_DQ[3]
+-set_location_assignment PIN_W1 -to DRAM_DQ[4]
+-set_location_assignment PIN_W2 -to DRAM_DQ[5]
+-set_location_assignment PIN_Y1 -to DRAM_DQ[6]
+-set_location_assignment PIN_Y2 -to DRAM_DQ[7]
+-set_location_assignment PIN_N1 -to DRAM_DQ[8]
+-set_location_assignment PIN_N2 -to DRAM_DQ[9]
+-set_location_assignment PIN_P1 -to DRAM_DQ[10]
+-set_location_assignment PIN_P2 -to DRAM_DQ[11]
+-set_location_assignment PIN_R1 -to DRAM_DQ[12]
+-set_location_assignment PIN_R2 -to DRAM_DQ[13]
+-set_location_assignment PIN_T1 -to DRAM_DQ[14]
+-set_location_assignment PIN_T2 -to DRAM_DQ[15]
+-set_location_assignment PIN_R7 -to DRAM_LDQM
+-set_location_assignment PIN_T5 -to DRAM_RAS_N
+-set_location_assignment PIN_M5 -to DRAM_UDQM
+-set_location_assignment PIN_R8 -to DRAM_WE_N
+-set_location_assignment PIN_AB20 -to FL_ADDR[0]
+-set_location_assignment PIN_AA14 -to FL_ADDR[1]
+-set_location_assignment PIN_Y16 -to FL_ADDR[2]
+-set_location_assignment PIN_R15 -to FL_ADDR[3]
+-set_location_assignment PIN_T15 -to FL_ADDR[4]
+-set_location_assignment PIN_U15 -to FL_ADDR[5]
+-set_location_assignment PIN_V15 -to FL_ADDR[6]
+-set_location_assignment PIN_W15 -to FL_ADDR[7]
+-set_location_assignment PIN_R14 -to FL_ADDR[8]
+-set_location_assignment PIN_Y13 -to FL_ADDR[9]
+-set_location_assignment PIN_R12 -to FL_ADDR[10]
+-set_location_assignment PIN_T12 -to FL_ADDR[11]
+-set_location_assignment PIN_AB14 -to FL_ADDR[12]
+-set_location_assignment PIN_AA13 -to FL_ADDR[13]
+-set_location_assignment PIN_AB13 -to FL_ADDR[14]
+-set_location_assignment PIN_AA12 -to FL_ADDR[15]
+-set_location_assignment PIN_AB12 -to FL_ADDR[16]
+-set_location_assignment PIN_AA20 -to FL_ADDR[17]
+-set_location_assignment PIN_U14 -to FL_ADDR[18]
+-set_location_assignment PIN_V14 -to FL_ADDR[19]
+-set_location_assignment PIN_U13 -to FL_ADDR[20]
+-set_location_assignment PIN_R13 -to FL_ADDR[21]
+-set_location_assignment PIN_AB16 -to FL_DQ[0]
+-set_location_assignment PIN_AA16 -to FL_DQ[1]
+-set_location_assignment PIN_AB17 -to FL_DQ[2]
+-set_location_assignment PIN_AA17 -to FL_DQ[3]
+-set_location_assignment PIN_AB18 -to FL_DQ[4]
+-set_location_assignment PIN_AA18 -to FL_DQ[5]
+-set_location_assignment PIN_AB19 -to FL_DQ[6]
+-set_location_assignment PIN_AA19 -to FL_DQ[7]
+-set_location_assignment PIN_AA15 -to FL_OE_N
+-set_location_assignment PIN_W14 -to FL_RST_N
+-set_location_assignment PIN_Y14 -to FL_WE_N
+-set_location_assignment PIN_AA3 -to SRAM_ADDR[0]
+-set_location_assignment PIN_AB3 -to SRAM_ADDR[1]
+-set_location_assignment PIN_AA4 -to SRAM_ADDR[2]
+-set_location_assignment PIN_AB4 -to SRAM_ADDR[3]
+-set_location_assignment PIN_AA5 -to SRAM_ADDR[4]
+-set_location_assignment PIN_AB10 -to SRAM_ADDR[5]
+-set_location_assignment PIN_AA11 -to SRAM_ADDR[6]
+-set_location_assignment PIN_AB11 -to SRAM_ADDR[7]
+-set_location_assignment PIN_V11 -to SRAM_ADDR[8]
+-set_location_assignment PIN_W11 -to SRAM_ADDR[9]
+-set_location_assignment PIN_R11 -to SRAM_ADDR[10]
+-set_location_assignment PIN_T11 -to SRAM_ADDR[11]
+-set_location_assignment PIN_Y10 -to SRAM_ADDR[12]
+-set_location_assignment PIN_U10 -to SRAM_ADDR[13]
+-set_location_assignment PIN_R10 -to SRAM_ADDR[14]
+-set_location_assignment PIN_T7 -to SRAM_ADDR[15]
+-set_location_assignment PIN_Y6 -to SRAM_ADDR[16]
+-set_location_assignment PIN_Y5 -to SRAM_ADDR[17]
+-set_location_assignment PIN_AB5 -to SRAM_CE_N
+-set_location_assignment PIN_AA6 -to SRAM_DQ[0]
+-set_location_assignment PIN_AB6 -to SRAM_DQ[1]
+-set_location_assignment PIN_AA7 -to SRAM_DQ[2]
+-set_location_assignment PIN_AB7 -to SRAM_DQ[3]
+-set_location_assignment PIN_AA8 -to SRAM_DQ[4]
+-set_location_assignment PIN_AB8 -to SRAM_DQ[5]
+-set_location_assignment PIN_AA9 -to SRAM_DQ[6]
+-set_location_assignment PIN_AB9 -to SRAM_DQ[7]
+-set_location_assignment PIN_Y9 -to SRAM_DQ[8]
+-set_location_assignment PIN_W9 -to SRAM_DQ[9]
+-set_location_assignment PIN_V9 -to SRAM_DQ[10]
+-set_location_assignment PIN_U9 -to SRAM_DQ[11]
+-set_location_assignment PIN_R9 -to SRAM_DQ[12]
+-set_location_assignment PIN_W8 -to SRAM_DQ[13]
+-set_location_assignment PIN_V8 -to SRAM_DQ[14]
+-set_location_assignment PIN_U8 -to SRAM_DQ[15]
+-set_location_assignment PIN_Y7 -to SRAM_LB_N
+-set_location_assignment PIN_T8 -to SRAM_OE_N
+-set_location_assignment PIN_W7 -to SRAM_UB_N
+-set_location_assignment PIN_AA10 -to SRAM_WE_N
+-set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED WITH WEAK PULL-UP"
+-set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
+-set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
+-set_global_assignment -name LL_ROOT_REGION ON -section_id "Root Region"
+-set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region"
+-set_global_assignment -name MISC_FILE "U:/git_repos/fpga/bbc/bbc_micro_de1.dpf"
+-set_location_assignment PIN_AB15 -to FL_CE_N
+-set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
+-set_global_assignment -name STRATIX_CONFIGURATION_DEVICE EPCS4
+-set_global_assignment -name RESERVE_ASDO_AFTER_CONFIGURATION "AS INPUT TRI-STATED"
+-set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
+-set_location_assignment PIN_U20 -to SD_nCS
+-set_location_assignment PIN_V20 -to SD_SCLK
+-set_location_assignment PIN_Y20 -to SD_MOSI
+-set_location_assignment PIN_W20 -to SD_MISO
+-set_global_assignment -name VHDL_FILE saa5050.vhd
+-set_global_assignment -name VHDL_FILE i2s_intf.vhd
+-set_global_assignment -name VHDL_FILE i2c_loader.vhd
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_comp_pack-p.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_noise.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_tone.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_top.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_attenuator.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_clock_div.vhd"
+-set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_latch_ctrl.vhd"
+-set_global_assignment -name VHDL_FILE ps2_intf.vhd
+-set_global_assignment -name VHDL_FILE m6522.vhd
+-set_global_assignment -name VHDL_FILE seg7.vhd
+-set_global_assignment -name VHDL_FILE vidproc.vhd
+-set_global_assignment -name VHDL_FILE mc6845.vhd
+-set_global_assignment -name VHDL_FILE T65/T65_Pack.vhd
+-set_global_assignment -name VHDL_FILE T65/T65.vhd
+-set_global_assignment -name VHDL_FILE T65/T65_ALU.vhd
+-set_global_assignment -name VHDL_FILE T65/T65_MCode.vhd
+-set_global_assignment -name QIP_FILE pll32.qip
+-set_global_assignment -name VHDL_FILE bbc_micro_de1.vhd
+-set_global_assignment -name VHDL_FILE bbc_micro_de1_tb.vhd
+-set_global_assignment -name VHDL_FILE m6522_tb.vhd
+-set_global_assignment -name VHDL_FILE keyboard.vhd
+-set_global_assignment -name VHDL_FILE debugger.vhd
+-set_global_assignment -name QIP_FILE saa5050_rom.qip
++# -------------------------------------------------------------------------- #
++#
++# Copyright (C) 1991-2009 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
++# Version 9.1 Build 222 10/21/2009 SJ Web Edition
++# Date created = 20:48:44 July 12, 2011
++#
++# -------------------------------------------------------------------------- #
++#
++# Notes:
++#
++# 1) The default values for assignments are stored in the file:
++# bbc_micro_de1_assignment_defaults.qdf
++# If this file doesn't exist, see file:
++# assignment_defaults.qdf
++#
++# 2) Altera recommends that you do not modify this file. This
++# file is updated automatically by the Quartus II software
++# and any changes you make may be lost or overwritten.
++#
++# -------------------------------------------------------------------------- #
++
++
++set_global_assignment -name FAMILY "Cyclone II"
++set_global_assignment -name DEVICE EP2C20F484C7
++set_global_assignment -name TOP_LEVEL_ENTITY bbc_micro_de1
++set_global_assignment -name ORIGINAL_QUARTUS_VERSION 9.1
++set_global_assignment -name PROJECT_CREATION_TIME_DATE "20:48:44 JULY 12, 2011"
++set_global_assignment -name LAST_QUARTUS_VERSION 9.1
++set_global_assignment -name USE_GENERATED_PHYSICAL_CONSTRAINTS OFF -section_id eda_blast_fpga
++set_global_assignment -name DEVICE_FILTER_PACKAGE FBGA
++set_global_assignment -name DEVICE_FILTER_PIN_COUNT 484
++set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 7
++set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
++set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
++set_location_assignment PIN_A13 -to GPIO_0[0]
++set_location_assignment PIN_B13 -to GPIO_0[1]
++set_location_assignment PIN_A14 -to GPIO_0[2]
++set_location_assignment PIN_B14 -to GPIO_0[3]
++set_location_assignment PIN_A15 -to GPIO_0[4]
++set_location_assignment PIN_B15 -to GPIO_0[5]
++set_location_assignment PIN_A16 -to GPIO_0[6]
++set_location_assignment PIN_B16 -to GPIO_0[7]
++set_location_assignment PIN_A17 -to GPIO_0[8]
++set_location_assignment PIN_B17 -to GPIO_0[9]
++set_location_assignment PIN_A18 -to GPIO_0[10]
++set_location_assignment PIN_B18 -to GPIO_0[11]
++set_location_assignment PIN_A19 -to GPIO_0[12]
++set_location_assignment PIN_B19 -to GPIO_0[13]
++set_location_assignment PIN_A20 -to GPIO_0[14]
++set_location_assignment PIN_B20 -to GPIO_0[15]
++set_location_assignment PIN_C21 -to GPIO_0[16]
++set_location_assignment PIN_C22 -to GPIO_0[17]
++set_location_assignment PIN_D21 -to GPIO_0[18]
++set_location_assignment PIN_D22 -to GPIO_0[19]
++set_location_assignment PIN_E21 -to GPIO_0[20]
++set_location_assignment PIN_E22 -to GPIO_0[21]
++set_location_assignment PIN_F21 -to GPIO_0[22]
++set_location_assignment PIN_F22 -to GPIO_0[23]
++set_location_assignment PIN_G21 -to GPIO_0[24]
++set_location_assignment PIN_G22 -to GPIO_0[25]
++set_location_assignment PIN_J21 -to GPIO_0[26]
++set_location_assignment PIN_J22 -to GPIO_0[27]
++set_location_assignment PIN_K21 -to GPIO_0[28]
++set_location_assignment PIN_K22 -to GPIO_0[29]
++set_location_assignment PIN_J19 -to GPIO_0[30]
++set_location_assignment PIN_J20 -to GPIO_0[31]
++set_location_assignment PIN_J18 -to GPIO_0[32]
++set_location_assignment PIN_K20 -to GPIO_0[33]
++set_location_assignment PIN_L19 -to GPIO_0[34]
++set_location_assignment PIN_L18 -to GPIO_0[35]
++set_location_assignment PIN_H12 -to GPIO_1[0]
++set_location_assignment PIN_H13 -to GPIO_1[1]
++set_location_assignment PIN_H14 -to GPIO_1[2]
++set_location_assignment PIN_G15 -to GPIO_1[3]
++set_location_assignment PIN_E14 -to GPIO_1[4]
++set_location_assignment PIN_E15 -to GPIO_1[5]
++set_location_assignment PIN_F15 -to GPIO_1[6]
++set_location_assignment PIN_G16 -to GPIO_1[7]
++set_location_assignment PIN_F12 -to GPIO_1[8]
++set_location_assignment PIN_F13 -to GPIO_1[9]
++set_location_assignment PIN_C14 -to GPIO_1[10]
++set_location_assignment PIN_D14 -to GPIO_1[11]
++set_location_assignment PIN_D15 -to GPIO_1[12]
++set_location_assignment PIN_D16 -to GPIO_1[13]
++set_location_assignment PIN_C17 -to GPIO_1[14]
++set_location_assignment PIN_C18 -to GPIO_1[15]
++set_location_assignment PIN_C19 -to GPIO_1[16]
++set_location_assignment PIN_C20 -to GPIO_1[17]
++set_location_assignment PIN_D19 -to GPIO_1[18]
++set_location_assignment PIN_D20 -to GPIO_1[19]
++set_location_assignment PIN_E20 -to GPIO_1[20]
++set_location_assignment PIN_F20 -to GPIO_1[21]
++set_location_assignment PIN_E19 -to GPIO_1[22]
++set_location_assignment PIN_E18 -to GPIO_1[23]
++set_location_assignment PIN_G20 -to GPIO_1[24]
++set_location_assignment PIN_G18 -to GPIO_1[25]
++set_location_assignment PIN_G17 -to GPIO_1[26]
++set_location_assignment PIN_H17 -to GPIO_1[27]
++set_location_assignment PIN_J15 -to GPIO_1[28]
++set_location_assignment PIN_H18 -to GPIO_1[29]
++set_location_assignment PIN_N22 -to GPIO_1[30]
++set_location_assignment PIN_N21 -to GPIO_1[31]
++set_location_assignment PIN_P15 -to GPIO_1[32]
++set_location_assignment PIN_N15 -to GPIO_1[33]
++set_location_assignment PIN_P17 -to GPIO_1[34]
++set_location_assignment PIN_P18 -to GPIO_1[35]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[4]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[5]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[6]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[7]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[8]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[9]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[10]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[11]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[12]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[13]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[14]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[15]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[16]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[17]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[18]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[19]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[20]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[21]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[22]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[23]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[24]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[25]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[26]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[27]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[28]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[29]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[30]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[31]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[32]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[33]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[34]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_0[35]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[4]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[5]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[6]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[7]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[8]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[9]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[10]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[11]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[12]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[13]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[14]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[15]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[16]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[17]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[18]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[19]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[20]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[21]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[22]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[23]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[24]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[25]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[26]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[27]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[28]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[29]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[30]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[31]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[32]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[33]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[34]
++set_instance_assignment -name IO_STANDARD LVTTL -to GPIO_1[35]
++set_location_assignment PIN_L22 -to SW[0]
++set_location_assignment PIN_L21 -to SW[1]
++set_location_assignment PIN_M22 -to SW[2]
++set_location_assignment PIN_V12 -to SW[3]
++set_location_assignment PIN_W12 -to SW[4]
++set_location_assignment PIN_U12 -to SW[5]
++set_location_assignment PIN_U11 -to SW[6]
++set_location_assignment PIN_M2 -to SW[7]
++set_location_assignment PIN_M1 -to SW[8]
++set_location_assignment PIN_L2 -to SW[9]
++set_instance_assignment -name IO_STANDARD LVTTL -to SW[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to SW[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to SW[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to SW[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to SW[4]
++set_instance_assignment -name IO_STANDARD LVTTL -to SW[5]
++set_instance_assignment -name IO_STANDARD LVTTL -to SW[6]
++set_instance_assignment -name IO_STANDARD LVTTL -to SW[7]
++set_instance_assignment -name IO_STANDARD LVTTL -to SW[8]
++set_instance_assignment -name IO_STANDARD LVTTL -to SW[9]
++set_location_assignment PIN_J2 -to HEX0[0]
++set_location_assignment PIN_J1 -to HEX0[1]
++set_location_assignment PIN_H2 -to HEX0[2]
++set_location_assignment PIN_H1 -to HEX0[3]
++set_location_assignment PIN_F2 -to HEX0[4]
++set_location_assignment PIN_F1 -to HEX0[5]
++set_location_assignment PIN_E2 -to HEX0[6]
++set_location_assignment PIN_E1 -to HEX1[0]
++set_location_assignment PIN_H6 -to HEX1[1]
++set_location_assignment PIN_H5 -to HEX1[2]
++set_location_assignment PIN_H4 -to HEX1[3]
++set_location_assignment PIN_G3 -to HEX1[4]
++set_location_assignment PIN_D2 -to HEX1[5]
++set_location_assignment PIN_D1 -to HEX1[6]
++set_location_assignment PIN_G5 -to HEX2[0]
++set_location_assignment PIN_G6 -to HEX2[1]
++set_location_assignment PIN_C2 -to HEX2[2]
++set_location_assignment PIN_C1 -to HEX2[3]
++set_location_assignment PIN_E3 -to HEX2[4]
++set_location_assignment PIN_E4 -to HEX2[5]
++set_location_assignment PIN_D3 -to HEX2[6]
++set_location_assignment PIN_F4 -to HEX3[0]
++set_location_assignment PIN_D5 -to HEX3[1]
++set_location_assignment PIN_D6 -to HEX3[2]
++set_location_assignment PIN_J4 -to HEX3[3]
++set_location_assignment PIN_L8 -to HEX3[4]
++set_location_assignment PIN_F3 -to HEX3[5]
++set_location_assignment PIN_D4 -to HEX3[6]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[4]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[5]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX0[6]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[4]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[5]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX1[6]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[4]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[5]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX2[6]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[4]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[5]
++set_instance_assignment -name IO_STANDARD LVTTL -to HEX3[6]
++set_location_assignment PIN_R22 -to KEY[0]
++set_location_assignment PIN_R21 -to KEY[1]
++set_location_assignment PIN_T22 -to KEY[2]
++set_location_assignment PIN_T21 -to KEY[3]
++set_location_assignment PIN_R20 -to LEDR[0]
++set_location_assignment PIN_R19 -to LEDR[1]
++set_location_assignment PIN_U19 -to LEDR[2]
++set_location_assignment PIN_Y19 -to LEDR[3]
++set_location_assignment PIN_T18 -to LEDR[4]
++set_location_assignment PIN_V19 -to LEDR[5]
++set_location_assignment PIN_Y18 -to LEDR[6]
++set_location_assignment PIN_U18 -to LEDR[7]
++set_location_assignment PIN_R18 -to LEDR[8]
++set_location_assignment PIN_R17 -to LEDR[9]
++set_location_assignment PIN_U22 -to LEDG[0]
++set_location_assignment PIN_U21 -to LEDG[1]
++set_location_assignment PIN_V22 -to LEDG[2]
++set_location_assignment PIN_V21 -to LEDG[3]
++set_location_assignment PIN_W22 -to LEDG[4]
++set_location_assignment PIN_W21 -to LEDG[5]
++set_location_assignment PIN_Y22 -to LEDG[6]
++set_location_assignment PIN_Y21 -to LEDG[7]
++set_instance_assignment -name IO_STANDARD LVTTL -to KEY[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to KEY[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to KEY[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to KEY[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[4]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[5]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[6]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[7]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[8]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDR[9]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[4]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[5]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[6]
++set_instance_assignment -name IO_STANDARD LVTTL -to LEDG[7]
++set_location_assignment PIN_D12 -to CLOCK_27[0]
++set_location_assignment PIN_E12 -to CLOCK_27[1]
++set_location_assignment PIN_B12 -to CLOCK_24[0]
++set_location_assignment PIN_A12 -to CLOCK_24[1]
++set_location_assignment PIN_L1 -to CLOCK_50
++set_location_assignment PIN_M21 -to EXT_CLOCK
++set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_27[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_24[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_24[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to CLOCK_50
++set_instance_assignment -name IO_STANDARD LVTTL -to EXT_CLOCK
++set_location_assignment PIN_H15 -to PS2_CLK
++set_location_assignment PIN_J14 -to PS2_DAT
++set_location_assignment PIN_F14 -to UART_RXD
++set_location_assignment PIN_G12 -to UART_TXD
++set_instance_assignment -name IO_STANDARD LVTTL -to PS2_CLK
++set_instance_assignment -name IO_STANDARD LVTTL -to PS2_DAT
++set_instance_assignment -name IO_STANDARD LVTTL -to UART_RXD
++set_instance_assignment -name IO_STANDARD LVTTL -to UART_TXD
++set_location_assignment PIN_E8 -to TDI
++set_location_assignment PIN_D8 -to TCS
++set_location_assignment PIN_C7 -to TCK
++set_location_assignment PIN_D7 -to TDO
++set_instance_assignment -name IO_STANDARD LVTTL -to TDI
++set_instance_assignment -name IO_STANDARD LVTTL -to TCS
++set_instance_assignment -name IO_STANDARD LVTTL -to TCK
++set_instance_assignment -name IO_STANDARD LVTTL -to TDO
++set_location_assignment PIN_D9 -to VGA_R[0]
++set_location_assignment PIN_C9 -to VGA_R[1]
++set_location_assignment PIN_A7 -to VGA_R[2]
++set_location_assignment PIN_B7 -to VGA_R[3]
++set_location_assignment PIN_B8 -to VGA_G[0]
++set_location_assignment PIN_C10 -to VGA_G[1]
++set_location_assignment PIN_B9 -to VGA_G[2]
++set_location_assignment PIN_A8 -to VGA_G[3]
++set_location_assignment PIN_A9 -to VGA_B[0]
++set_location_assignment PIN_D11 -to VGA_B[1]
++set_location_assignment PIN_A10 -to VGA_B[2]
++set_location_assignment PIN_B10 -to VGA_B[3]
++set_location_assignment PIN_A11 -to VGA_HS
++set_location_assignment PIN_B11 -to VGA_VS
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_R[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_G[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[0]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[1]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[2]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_B[3]
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_HS
++set_instance_assignment -name IO_STANDARD LVTTL -to VGA_VS
++set_location_assignment PIN_A3 -to I2C_SCLK
++set_location_assignment PIN_B3 -to I2C_SDAT
++set_location_assignment PIN_A6 -to AUD_ADCLRCK
++set_location_assignment PIN_B6 -to AUD_ADCDAT
++set_location_assignment PIN_A5 -to AUD_DACLRCK
++set_location_assignment PIN_B5 -to AUD_DACDAT
++set_location_assignment PIN_B4 -to AUD_XCK
++set_location_assignment PIN_A4 -to AUD_BCLK
++set_instance_assignment -name IO_STANDARD LVTTL -to I2C_SCLK
++set_instance_assignment -name IO_STANDARD LVTTL -to I2C_SDAT
++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_ADCLRCK
++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_ADCDAT
++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_DACLRCK
++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_DACDAT
++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_XCK
++set_instance_assignment -name IO_STANDARD LVTTL -to AUD_BCLK
++set_location_assignment PIN_W4 -to DRAM_ADDR[0]
++set_location_assignment PIN_W5 -to DRAM_ADDR[1]
++set_location_assignment PIN_Y3 -to DRAM_ADDR[2]
++set_location_assignment PIN_Y4 -to DRAM_ADDR[3]
++set_location_assignment PIN_R6 -to DRAM_ADDR[4]
++set_location_assignment PIN_R5 -to DRAM_ADDR[5]
++set_location_assignment PIN_P6 -to DRAM_ADDR[6]
++set_location_assignment PIN_P5 -to DRAM_ADDR[7]
++set_location_assignment PIN_P3 -to DRAM_ADDR[8]
++set_location_assignment PIN_N4 -to DRAM_ADDR[9]
++set_location_assignment PIN_W3 -to DRAM_ADDR[10]
++set_location_assignment PIN_N6 -to DRAM_ADDR[11]
++set_location_assignment PIN_U3 -to DRAM_BA_0
++set_location_assignment PIN_V4 -to DRAM_BA_1
++set_location_assignment PIN_T3 -to DRAM_CAS_N
++set_location_assignment PIN_N3 -to DRAM_CKE
++set_location_assignment PIN_U4 -to DRAM_CLK
++set_location_assignment PIN_T6 -to DRAM_CS_N
++set_location_assignment PIN_U1 -to DRAM_DQ[0]
++set_location_assignment PIN_U2 -to DRAM_DQ[1]
++set_location_assignment PIN_V1 -to DRAM_DQ[2]
++set_location_assignment PIN_V2 -to DRAM_DQ[3]
++set_location_assignment PIN_W1 -to DRAM_DQ[4]
++set_location_assignment PIN_W2 -to DRAM_DQ[5]
++set_location_assignment PIN_Y1 -to DRAM_DQ[6]
++set_location_assignment PIN_Y2 -to DRAM_DQ[7]
++set_location_assignment PIN_N1 -to DRAM_DQ[8]
++set_location_assignment PIN_N2 -to DRAM_DQ[9]
++set_location_assignment PIN_P1 -to DRAM_DQ[10]
++set_location_assignment PIN_P2 -to DRAM_DQ[11]
++set_location_assignment PIN_R1 -to DRAM_DQ[12]
++set_location_assignment PIN_R2 -to DRAM_DQ[13]
++set_location_assignment PIN_T1 -to DRAM_DQ[14]
++set_location_assignment PIN_T2 -to DRAM_DQ[15]
++set_location_assignment PIN_R7 -to DRAM_LDQM
++set_location_assignment PIN_T5 -to DRAM_RAS_N
++set_location_assignment PIN_M5 -to DRAM_UDQM
++set_location_assignment PIN_R8 -to DRAM_WE_N
++set_location_assignment PIN_AB20 -to FL_ADDR[0]
++set_location_assignment PIN_AA14 -to FL_ADDR[1]
++set_location_assignment PIN_Y16 -to FL_ADDR[2]
++set_location_assignment PIN_R15 -to FL_ADDR[3]
++set_location_assignment PIN_T15 -to FL_ADDR[4]
++set_location_assignment PIN_U15 -to FL_ADDR[5]
++set_location_assignment PIN_V15 -to FL_ADDR[6]
++set_location_assignment PIN_W15 -to FL_ADDR[7]
++set_location_assignment PIN_R14 -to FL_ADDR[8]
++set_location_assignment PIN_Y13 -to FL_ADDR[9]
++set_location_assignment PIN_R12 -to FL_ADDR[10]
++set_location_assignment PIN_T12 -to FL_ADDR[11]
++set_location_assignment PIN_AB14 -to FL_ADDR[12]
++set_location_assignment PIN_AA13 -to FL_ADDR[13]
++set_location_assignment PIN_AB13 -to FL_ADDR[14]
++set_location_assignment PIN_AA12 -to FL_ADDR[15]
++set_location_assignment PIN_AB12 -to FL_ADDR[16]
++set_location_assignment PIN_AA20 -to FL_ADDR[17]
++set_location_assignment PIN_U14 -to FL_ADDR[18]
++set_location_assignment PIN_V14 -to FL_ADDR[19]
++set_location_assignment PIN_U13 -to FL_ADDR[20]
++set_location_assignment PIN_R13 -to FL_ADDR[21]
++set_location_assignment PIN_AB16 -to FL_DQ[0]
++set_location_assignment PIN_AA16 -to FL_DQ[1]
++set_location_assignment PIN_AB17 -to FL_DQ[2]
++set_location_assignment PIN_AA17 -to FL_DQ[3]
++set_location_assignment PIN_AB18 -to FL_DQ[4]
++set_location_assignment PIN_AA18 -to FL_DQ[5]
++set_location_assignment PIN_AB19 -to FL_DQ[6]
++set_location_assignment PIN_AA19 -to FL_DQ[7]
++set_location_assignment PIN_AA15 -to FL_OE_N
++set_location_assignment PIN_W14 -to FL_RST_N
++set_location_assignment PIN_Y14 -to FL_WE_N
++set_location_assignment PIN_AA3 -to SRAM_ADDR[0]
++set_location_assignment PIN_AB3 -to SRAM_ADDR[1]
++set_location_assignment PIN_AA4 -to SRAM_ADDR[2]
++set_location_assignment PIN_AB4 -to SRAM_ADDR[3]
++set_location_assignment PIN_AA5 -to SRAM_ADDR[4]
++set_location_assignment PIN_AB10 -to SRAM_ADDR[5]
++set_location_assignment PIN_AA11 -to SRAM_ADDR[6]
++set_location_assignment PIN_AB11 -to SRAM_ADDR[7]
++set_location_assignment PIN_V11 -to SRAM_ADDR[8]
++set_location_assignment PIN_W11 -to SRAM_ADDR[9]
++set_location_assignment PIN_R11 -to SRAM_ADDR[10]
++set_location_assignment PIN_T11 -to SRAM_ADDR[11]
++set_location_assignment PIN_Y10 -to SRAM_ADDR[12]
++set_location_assignment PIN_U10 -to SRAM_ADDR[13]
++set_location_assignment PIN_R10 -to SRAM_ADDR[14]
++set_location_assignment PIN_T7 -to SRAM_ADDR[15]
++set_location_assignment PIN_Y6 -to SRAM_ADDR[16]
++set_location_assignment PIN_Y5 -to SRAM_ADDR[17]
++set_location_assignment PIN_AB5 -to SRAM_CE_N
++set_location_assignment PIN_AA6 -to SRAM_DQ[0]
++set_location_assignment PIN_AB6 -to SRAM_DQ[1]
++set_location_assignment PIN_AA7 -to SRAM_DQ[2]
++set_location_assignment PIN_AB7 -to SRAM_DQ[3]
++set_location_assignment PIN_AA8 -to SRAM_DQ[4]
++set_location_assignment PIN_AB8 -to SRAM_DQ[5]
++set_location_assignment PIN_AA9 -to SRAM_DQ[6]
++set_location_assignment PIN_AB9 -to SRAM_DQ[7]
++set_location_assignment PIN_Y9 -to SRAM_DQ[8]
++set_location_assignment PIN_W9 -to SRAM_DQ[9]
++set_location_assignment PIN_V9 -to SRAM_DQ[10]
++set_location_assignment PIN_U9 -to SRAM_DQ[11]
++set_location_assignment PIN_R9 -to SRAM_DQ[12]
++set_location_assignment PIN_W8 -to SRAM_DQ[13]
++set_location_assignment PIN_V8 -to SRAM_DQ[14]
++set_location_assignment PIN_U8 -to SRAM_DQ[15]
++set_location_assignment PIN_Y7 -to SRAM_LB_N
++set_location_assignment PIN_T8 -to SRAM_OE_N
++set_location_assignment PIN_W7 -to SRAM_UB_N
++set_location_assignment PIN_AA10 -to SRAM_WE_N
++set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED WITH WEAK PULL-UP"
++set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
++set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
++set_global_assignment -name LL_ROOT_REGION ON -section_id "Root Region"
++set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region"
++set_global_assignment -name MISC_FILE "U:/git_repos/fpga/bbc/bbc_micro_de1.dpf"
++set_location_assignment PIN_AB15 -to FL_CE_N
++set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
++set_global_assignment -name STRATIX_CONFIGURATION_DEVICE EPCS4
++set_global_assignment -name RESERVE_ASDO_AFTER_CONFIGURATION "AS INPUT TRI-STATED"
++set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
++set_location_assignment PIN_U20 -to SD_nCS
++set_location_assignment PIN_V20 -to SD_SCLK
++set_location_assignment PIN_Y20 -to SD_MOSI
++set_location_assignment PIN_W20 -to SD_MISO
++set_global_assignment -name VHDL_FILE saa5050.vhd
++set_global_assignment -name VHDL_FILE i2s_intf.vhd
++set_global_assignment -name VHDL_FILE i2c_loader.vhd
++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_comp_pack-p.vhd"
++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_noise.vhd"
++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_tone.vhd"
++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_top.vhd"
++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_attenuator.vhd"
++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_clock_div.vhd"
++set_global_assignment -name VHDL_FILE "sn76489-1.0/sn76489_latch_ctrl.vhd"
++set_global_assignment -name VHDL_FILE ps2_intf.vhd
++set_global_assignment -name VHDL_FILE m6522.vhd
++set_global_assignment -name VHDL_FILE seg7.vhd
++set_global_assignment -name VHDL_FILE vidproc.vhd
++set_global_assignment -name VHDL_FILE mc6845.vhd
++set_global_assignment -name VHDL_FILE T65/T65_Pack.vhd
++set_global_assignment -name VHDL_FILE T65/T65.vhd
++set_global_assignment -name VHDL_FILE T65/T65_ALU.vhd
++set_global_assignment -name VHDL_FILE T65/T65_MCode.vhd
++set_global_assignment -name QIP_FILE pll32.qip
++set_global_assignment -name VHDL_FILE bbc_micro_de1.vhd
++set_global_assignment -name VHDL_FILE bbc_micro_de1_tb.vhd
++set_global_assignment -name VHDL_FILE m6522_tb.vhd
++set_global_assignment -name VHDL_FILE keyboard.vhd
++set_global_assignment -name VHDL_FILE debugger.vhd
++set_global_assignment -name QIP_FILE saa5050_rom.qip
+ set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
+\ No newline at end of file
+diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd
+index e109c36..0fca9de 100644
+--- a/bbc_micro_de1.vhd
++++ b/bbc_micro_de1.vhd
+@@ -1,1265 +1,1265 @@
+--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- BBC B Micro
+---
+--- Terasic DE1 top-level
+---
+--- (C) 2011 Mike Stirling
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+--- Generic top-level entity for Altera DE1 board
+-entity bbc_micro_de1 is
+-generic (
+- -- ROM offset
+- -- The 4MB Flash is used in 16KB banks as a simple mechanism for
+- -- different machines to address different parts of the ROM, saving
+- -- on re-flashing each time a new machine is run on the board.
+- -- This generic sets the upper 8 address bits.
+- -- Note that the lower bits may be ignored by the implementation,
+- -- e.g. where ROMs are bigger than 16K or where multiple banks
+- -- are required. In this case it is important to ensure that the
+- -- ROM images are aligned correctly (such that these ignored bits are 0).
+- --
+- -- For the BBC the ROMs start in bank 8 (the first 8 banks are used by
+- -- the Spectrum project). The particular bank is selected by the sideways
+- -- ROM paging register, and bank 7 is used for the MOS. Recommended layout
+- -- is:
+- --
+- -- 0 Sideways
+- -- 1 Sideways
+- -- 2 Sideways - SuperMMC (DFS)
+- -- 3 Sideways - BASIC
+- -- 4 Not used
+- -- 5 Not used
+- -- 6 Not used
+- -- 7 MOS
+- ROM_OFFSET : std_logic_vector(7 downto 0) := "00001000"
+- );
+-port (
+- -- Clocks
+- CLOCK_24 : in std_logic_vector(1 downto 0);
+- CLOCK_27 : in std_logic_vector(1 downto 0);
+- CLOCK_50 : in std_logic;
+- EXT_CLOCK : in std_logic;
+-
+- -- Switches
+- SW : in std_logic_vector(9 downto 0);
+- -- Buttons
+- KEY : in std_logic_vector(3 downto 0);
+-
+- -- 7 segment displays
+- HEX0 : out std_logic_vector(6 downto 0);
+- HEX1 : out std_logic_vector(6 downto 0);
+- HEX2 : out std_logic_vector(6 downto 0);
+- HEX3 : out std_logic_vector(6 downto 0);
+- -- Red LEDs
+- LEDR : out std_logic_vector(9 downto 0);
+- -- Green LEDs
+- LEDG : out std_logic_vector(7 downto 0);
+-
+- -- VGA
+- VGA_R : out std_logic_vector(3 downto 0);
+- VGA_G : out std_logic_vector(3 downto 0);
+- VGA_B : out std_logic_vector(3 downto 0);
+- VGA_HS : out std_logic;
+- VGA_VS : out std_logic;
+-
+- -- Serial
+- UART_RXD : in std_logic;
+- UART_TXD : out std_logic;
+-
+- -- PS/2 Keyboard
+- PS2_CLK : inout std_logic;
+- PS2_DAT : inout std_logic;
+-
+- -- I2C
+- I2C_SCLK : inout std_logic;
+- I2C_SDAT : inout std_logic;
+-
+- -- Audio
+- AUD_XCK : out std_logic;
+- AUD_BCLK : out std_logic;
+- AUD_ADCLRCK : out std_logic;
+- AUD_ADCDAT : in std_logic;
+- AUD_DACLRCK : out std_logic;
+- AUD_DACDAT : out std_logic;
+-
+- -- SRAM
+- SRAM_ADDR : out std_logic_vector(17 downto 0);
+- SRAM_DQ : inout std_logic_vector(15 downto 0);
+- SRAM_CE_N : out std_logic;
+- SRAM_OE_N : out std_logic;
+- SRAM_WE_N : out std_logic;
+- SRAM_UB_N : out std_logic;
+- SRAM_LB_N : out std_logic;
+-
+- -- SDRAM
+- DRAM_ADDR : out std_logic_vector(11 downto 0);
+- DRAM_DQ : inout std_logic_vector(15 downto 0);
+- DRAM_BA_0 : in std_logic;
+- DRAM_BA_1 : in std_logic;
+- DRAM_CAS_N : in std_logic;
+- DRAM_CKE : in std_logic;
+- DRAM_CLK : in std_logic;
+- DRAM_CS_N : in std_logic;
+- DRAM_LDQM : in std_logic;
+- DRAM_RAS_N : in std_logic;
+- DRAM_UDQM : in std_logic;
+- DRAM_WE_N : in std_logic;
+-
+- -- Flash
+- FL_ADDR : out std_logic_vector(21 downto 0);
+- FL_DQ : inout std_logic_vector(7 downto 0);
+- FL_RST_N : out std_logic;
+- FL_OE_N : out std_logic;
+- FL_WE_N : out std_logic;
+- FL_CE_N : out std_logic;
+-
+- -- SD card (SPI mode)
+- SD_nCS : out std_logic;
+- SD_MOSI : out std_logic;
+- SD_SCLK : out std_logic;
+- SD_MISO : in std_logic;
+-
+- -- GPIO
+- GPIO_0 : inout std_logic_vector(35 downto 0);
+- GPIO_1 : inout std_logic_vector(35 downto 0)
+- );
+-end entity;
+-
+-architecture rtl of bbc_micro_de1 is
+-
+-------------------------------
+--- PLL (32 MHz master clock)
+-------------------------------
+-
+-component pll32 IS
+- PORT
+- (
+- areset : IN STD_LOGIC := '0';
+- inclk0 : IN STD_LOGIC := '0';
+- c0 : OUT STD_LOGIC ;
+- locked : OUT STD_LOGIC
+- );
+-end component;
+-
+----------
+--- CPU
+----------
+-
+-component T65 is
+- port(
+- Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
+- Res_n : in std_logic;
+- Enable : in std_logic;
+- Clk : in std_logic;
+- Rdy : in std_logic;
+- Abort_n : in std_logic;
+- IRQ_n : in std_logic;
+- NMI_n : in std_logic;
+- SO_n : in std_logic;
+- R_W_n : out std_logic;
+- Sync : out std_logic;
+- EF : out std_logic;
+- MF : out std_logic;
+- XF : out std_logic;
+- ML_n : out std_logic;
+- VP_n : out std_logic;
+- VDA : out std_logic;
+- VPA : out std_logic;
+- A : out std_logic_vector(23 downto 0);
+- DI : in std_logic_vector(7 downto 0);
+- DO : out std_logic_vector(7 downto 0)
+- );
+-end component;
+-
+------------------
+--- MC6845 CRTC
+------------------
+-
+-component mc6845 is
+-port (
+- CLOCK : in std_logic;
+- CLKEN : in std_logic;
+- nRESET : in std_logic;
+-
+- -- Bus interface
+- ENABLE : in std_logic;
+- R_nW : in std_logic;
+- RS : in std_logic;
+- DI : in std_logic_vector(7 downto 0);
+- DO : out std_logic_vector(7 downto 0);
+-
+- -- Display interface
+- VSYNC : out std_logic;
+- HSYNC : out std_logic;
+- DE : out std_logic;
+- CURSOR : out std_logic;
+- LPSTB : in std_logic;
+-
+- -- Memory interface
+- MA : out std_logic_vector(13 downto 0);
+- RA : out std_logic_vector(4 downto 0)
+- );
+-end component;
+-
+--------------------------
+--- "VIDPROC" Video ULA
+--------------------------
+-
+-component vidproc is
+-port (
+- CLOCK : in std_logic;
+- -- Clock enable qualifies display cycles (interleaved with CPU cycles)
+- CLKEN : in std_logic;
+- nRESET : in std_logic;
+-
+- -- Clock enable output to CRTC
+- CLKEN_CRTC : out std_logic;
+-
+- -- Bus interface
+- ENABLE : in std_logic;
+- A0 : in std_logic;
+- -- CPU data bus (for register writes)
+- DI_CPU : in std_logic_vector(7 downto 0);
+- -- Display RAM data bus (for display data fetch)
+- DI_RAM : in std_logic_vector(7 downto 0);
+-
+- -- Control interface
+- nINVERT : in std_logic;
+- DISEN : in std_logic;
+- CURSOR : in std_logic;
+-
+- -- Video in (teletext mode)
+- R_IN : in std_logic;
+- G_IN : in std_logic;
+- B_IN : in std_logic;
+-
+- -- Video out
+- R : out std_logic;
+- G : out std_logic;
+- B : out std_logic
+- );
+-end component;
+-
+---------------------------------
+--- SAA5050 Teletext Generator
+---------------------------------
+-
+-component saa5050 is
+-port (
+- CLOCK : in std_logic;
+- -- 6 MHz dot clock enable
+- CLKEN : in std_logic;
+- -- Async reset
+- nRESET : in std_logic;
+-
+- -- Character data input (in the bus clock domain)
+- DI_CLOCK : in std_logic;
+- DI_CLKEN : in std_logic;
+- DI : in std_logic_vector(6 downto 0);
+-
+- -- Timing inputs
+- -- General line reset (not used)
+- GLR : in std_logic; -- /HSYNC
+- -- Data entry window - high during VSYNC.
+- -- Resets ROM row counter and drives 'flash' signal
+- DEW : in std_logic; -- VSYNC
+- -- Character rounding select - high during even field
+- CRS : in std_logic; -- FIELD
+- -- Load output shift register enable - high during active video
+- LOSE : in std_logic; -- DE
+-
+- -- Video out
+- R : out std_logic;
+- G : out std_logic;
+- B : out std_logic;
+- Y : out std_logic
+- );
+-end component;
+-
+---------------
+--- 6522 VIA
+---------------
+-
+-component M6522 is
+- port (
+-
+- I_RS : in std_logic_vector(3 downto 0);
+- I_DATA : in std_logic_vector(7 downto 0);
+- O_DATA : out std_logic_vector(7 downto 0);
+- O_DATA_OE_L : out std_logic;
+-
+- I_RW_L : in std_logic;
+- I_CS1 : in std_logic;
+- I_CS2_L : in std_logic;
+-
+- O_IRQ_L : out std_logic; -- note, not open drain
+- -- port a
+- I_CA1 : in std_logic;
+- I_CA2 : in std_logic;
+- O_CA2 : out std_logic;
+- O_CA2_OE_L : out std_logic;
+-
+- I_PA : in std_logic_vector(7 downto 0);
+- O_PA : out std_logic_vector(7 downto 0);
+- O_PA_OE_L : out std_logic_vector(7 downto 0);
+-
+- -- port b
+- I_CB1 : in std_logic;
+- O_CB1 : out std_logic;
+- O_CB1_OE_L : out std_logic;
+-
+- I_CB2 : in std_logic;
+- O_CB2 : out std_logic;
+- O_CB2_OE_L : out std_logic;
+-
+- I_PB : in std_logic_vector(7 downto 0);
+- O_PB : out std_logic_vector(7 downto 0);
+- O_PB_OE_L : out std_logic_vector(7 downto 0);
+-
+- -- FIXME: Revisit timing in this component. Does it really need a 4x clock?
+- I_P2_H : in std_logic; -- high for phase 2 clock ____----__
+- RESET_L : in std_logic;
+- ENA_4 : in std_logic; -- clk enable (4x system clock rate)
+- CLK : in std_logic
+- );
+-end component;
+-
+------------------------------
+--- PS/2 Keyboard Emulation
+------------------------------
+-
+-component keyboard is
+-port (
+- CLOCK : in std_logic;
+- nRESET : in std_logic;
+- CLKEN_1MHZ : in std_logic;
+-
+- -- PS/2 interface
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
+-
+- -- If 1 then column is incremented automatically at
+- -- 1 MHz rate
+- AUTOSCAN : in std_logic;
+-
+- COLUMN : in std_logic_vector(3 downto 0);
+- ROW : in std_logic_vector(2 downto 0);
+-
+- -- 1 when currently selected key is down (AUTOSCAN disabled)
+- KEYPRESS : out std_logic;
+- -- 1 when any key is down (except row 0)
+- INT : out std_logic;
+- -- BREAK key output - 1 when pressed
+- BREAK_OUT : out std_logic;
+-
+- -- DIP switch inputs
+- DIP_SWITCH : in std_logic_vector(7 downto 0)
+- );
+-end component;
+-
+------------------------------
+--- SN76489 sound generator
+------------------------------
+-
+-component sn76489_top is
+-
+- generic (
+- clock_div_16_g : integer := 1
+- );
+- port (
+- clock_i : in std_logic;
+- clock_en_i : in std_logic;
+- res_n_i : in std_logic;
+- ce_n_i : in std_logic;
+- we_n_i : in std_logic;
+- ready_o : out std_logic;
+- d_i : in std_logic_vector(0 to 7);
+- aout_o : out signed(0 to 7)
+- );
+-
+-end component;
+-
+-component i2s_intf is
+-generic(
+- mclk_rate : positive := 12000000;
+- sample_rate : positive := 8000;
+- preamble : positive := 1; -- I2S
+- word_length : positive := 16
+- );
+-
+-port (
+- -- 2x MCLK in (e.g. 24 MHz for WM8731 USB mode)
+- CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- -- Parallel IO
+- PCM_INL : out std_logic_vector(word_length - 1 downto 0);
+- PCM_INR : out std_logic_vector(word_length - 1 downto 0);
+- PCM_OUTL : in std_logic_vector(word_length - 1 downto 0);
+- PCM_OUTR : in std_logic_vector(word_length - 1 downto 0);
+-
+- -- Codec interface (right justified mode)
+- -- MCLK is generated at half of the CLK input
+- I2S_MCLK : out std_logic;
+- -- LRCLK is equal to the sample rate and is synchronous to
+- -- MCLK. It must be related to MCLK by the oversampling ratio
+- -- given in the codec datasheet.
+- I2S_LRCLK : out std_logic;
+-
+- -- Data is shifted out on the falling edge of BCLK, sampled
+- -- on the rising edge. The bit rate is determined such that
+- -- it is fast enough to fit preamble + word_length bits into
+- -- each LRCLK half cycle. The last cycle of each word may be
+- -- stretched to fit to LRCLK. This is OK at least for the
+- -- WM8731 codec.
+- -- The first falling edge of each timeslot is always synchronised
+- -- with the LRCLK edge.
+- I2S_BCLK : out std_logic;
+- -- Output bitstream
+- I2S_DOUT : out std_logic;
+- -- Input bitstream
+- I2S_DIN : in std_logic
+- );
+-end component;
+-
+-component i2c_loader is
+-generic (
+- -- Address of slave to be loaded
+- device_address : integer := 16#1a#;
+- -- Number of retries to allow before stopping
+- num_retries : integer := 0;
+- -- Length of clock divider in bits. Resulting bus frequency is
+- -- CLK/2^(log2_divider + 2)
+- log2_divider : integer := 6
+-);
+-
+-port (
+- CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- I2C_SCL : inout std_logic;
+- I2C_SDA : inout std_logic;
+-
+- IS_DONE : out std_logic;
+- IS_ERROR : out std_logic
+- );
+-end component;
+-
+-component debugger is
+-generic (
+- -- Set this for a reasonable half flash duration relative to the
+- -- clock frequency
+- flash_divider : natural := 24
+- );
+-port (
+- CLOCK : in std_logic;
+- nRESET : in std_logic;
+- -- CPU clock enable in
+- CLKEN_IN : in std_logic;
+- -- Gated clock enable back out to CPU
+- CLKEN_OUT : out std_logic;
+- -- CPU IRQ in
+- nIRQ_IN : in std_logic;
+- -- Gated IRQ back out to CPU (no interrupts when single stepping)
+- nIRQ_OUT : out std_logic;
+-
+- -- CPU
+- A_CPU : in std_logic_vector(15 downto 0);
+- R_nW : in std_logic;
+- SYNC : in std_logic;
+-
+- -- Aux bus input for display in hex
+- AUX_BUS : in std_logic_vector(15 downto 0);
+-
+- -- Controls
+- -- RUN or HALT CPU
+- RUN : in std_logic;
+- -- Push button to single-step in HALT mode
+- nSTEP : in std_logic;
+- -- Push button to cycle display mode
+- nMODE : in std_logic;
+- -- Push button to cycle display digit in edit mode
+- nDIGIT : in std_logic;
+- -- Push button to cycle digit value in edit mode
+- nSET : in std_logic;
+-
+- -- Output to display
+- DIGIT3 : out std_logic_vector(6 downto 0);
+- DIGIT2 : out std_logic_vector(6 downto 0);
+- DIGIT1 : out std_logic_vector(6 downto 0);
+- DIGIT0 : out std_logic_vector(6 downto 0);
+-
+- LED_BREAKPOINT : out std_logic;
+- LED_WATCHPOINT : out std_logic
+- );
+-end component;
+-
+--------------
+--- Signals
+--------------
+-
+--- Master clock - 32 MHz
+-signal pll_reset : std_logic;
+-signal pll_locked : std_logic;
+-signal clock : std_logic;
+-signal hard_reset_n : std_logic;
+-signal reset_n : std_logic;
+-
+--- Clock enable counter
+--- CPU and video cycles are interleaved. The CPU runs at 2 MHz (every 16th
+--- cycle) and the video subsystem is enabled on every odd cycle.
+-signal clken_counter : unsigned(4 downto 0);
+-signal cpu_cycle : std_logic; -- Qualifies all 2 MHz cycles
+-signal cpu_cycle_mask : std_logic; -- Set to mask CPU cycles until 1 MHz cycle is complete
+-signal cpu_clken : std_logic; -- 2 MHz cycles in which the CPU is enabled
+-signal cpu_debug_clken : std_logic; -- CPU clken return from hardware debugger
+--- IO cycles are out of phase with the CPU
+-signal vid_clken : std_logic; -- 16 MHz video cycles
+-signal mhz4_clken : std_logic; -- Used by 6522
+-signal mhz2_clken : std_logic; -- Used for latching CPU address for clock stretch
+-signal mhz1_clken : std_logic; -- 1 MHz bus and associated peripherals, 6522 phase 2
+--- SAA5050 needs a 6 MHz clock enable relative to a 24 MHz clock
+-signal ttxt_clken_counter : unsigned(1 downto 0);
+-signal ttxt_clken : std_logic;
+-
+--- Debugger connections
+-signal debug_irq_in_n : std_logic;
+-signal debug_aux : std_logic_vector(15 downto 0);
+-
+--- CPU signals
+-signal cpu_mode : std_logic_vector(1 downto 0);
+-signal cpu_ready : std_logic;
+-signal cpu_abort_n : std_logic;
+-signal cpu_irq_n : std_logic;
+-signal cpu_nmi_n : std_logic;
+-signal cpu_so_n : std_logic;
+-signal cpu_r_nw : std_logic;
+-signal cpu_sync : std_logic;
+-signal cpu_ef : std_logic;
+-signal cpu_mf : std_logic;
+-signal cpu_xf : std_logic;
+-signal cpu_ml_n : std_logic;
+-signal cpu_vp_n : std_logic;
+-signal cpu_vda : std_logic;
+-signal cpu_vpa : std_logic;
+-signal cpu_a : std_logic_vector(23 downto 0);
+-signal cpu_di : std_logic_vector(7 downto 0);
+-signal cpu_do : std_logic_vector(7 downto 0);
+-
+--- CRTC signals
+-signal crtc_clken : std_logic;
+-signal crtc_do : std_logic_vector(7 downto 0);
+-signal crtc_vsync : std_logic;
+-signal crtc_hsync : std_logic;
+-signal crtc_de : std_logic;
+-signal crtc_cursor : std_logic;
+-signal crtc_lpstb : std_logic := '0';
+-signal crtc_ma : std_logic_vector(13 downto 0);
+-signal crtc_ra : std_logic_vector(4 downto 0);
+-
+--- Decoded display address after address translation for hardware
+--- scrolling
+-signal display_a : std_logic_vector(14 downto 0);
+-
+--- "VIDPROC" signals
+-signal vidproc_invert_n : std_logic;
+-signal vidproc_disen : std_logic;
+-signal r_in : std_logic;
+-signal g_in : std_logic;
+-signal b_in : std_logic;
+-signal r_out : std_logic;
+-signal g_out : std_logic;
+-signal b_out : std_logic;
+-
+--- SAA5050 signals
+-signal ttxt_glr : std_logic;
+-signal ttxt_dew : std_logic;
+-signal ttxt_crs : std_logic;
+-signal ttxt_lose : std_logic;
+-signal ttxt_r : std_logic;
+-signal ttxt_g : std_logic;
+-signal ttxt_b : std_logic;
+-signal ttxt_y : std_logic;
+-
+--- System VIA signals
+-signal sys_via_do : std_logic_vector(7 downto 0);
+-signal sys_via_do_oe_n : std_logic;
+-signal sys_via_irq_n : std_logic;
+-signal sys_via_ca1_in : std_logic := '0';
+-signal sys_via_ca2_in : std_logic := '0';
+-signal sys_via_ca2_out : std_logic;
+-signal sys_via_ca2_oe_n : std_logic;
+-signal sys_via_pa_in : std_logic_vector(7 downto 0);
+-signal sys_via_pa_out : std_logic_vector(7 downto 0);
+-signal sys_via_pa_oe_n : std_logic_vector(7 downto 0);
+-signal sys_via_cb1_in : std_logic := '0';
+-signal sys_via_cb1_out : std_logic;
+-signal sys_via_cb1_oe_n : std_logic;
+-signal sys_via_cb2_in : std_logic := '0';
+-signal sys_via_cb2_out : std_logic;
+-signal sys_via_cb2_oe_n : std_logic;
+-signal sys_via_pb_in : std_logic_vector(7 downto 0);
+-signal sys_via_pb_out : std_logic_vector(7 downto 0);
+-signal sys_via_pb_oe_n : std_logic_vector(7 downto 0);
+-
+--- User VIA signals
+-signal user_via_do : std_logic_vector(7 downto 0);
+-signal user_via_do_oe_n : std_logic;
+-signal user_via_irq_n : std_logic;
+-signal user_via_ca1_in : std_logic := '0';
+-signal user_via_ca2_in : std_logic := '0';
+-signal user_via_ca2_out : std_logic;
+-signal user_via_ca2_oe_n : std_logic;
+-signal user_via_pa_in : std_logic_vector(7 downto 0);
+-signal user_via_pa_out : std_logic_vector(7 downto 0);
+-signal user_via_pa_oe_n : std_logic_vector(7 downto 0);
+-signal user_via_cb1_in : std_logic := '0';
+-signal user_via_cb1_out : std_logic;
+-signal user_via_cb1_oe_n : std_logic;
+-signal user_via_cb2_in : std_logic := '0';
+-signal user_via_cb2_out : std_logic;
+-signal user_via_cb2_oe_n : std_logic;
+-signal user_via_pb_in : std_logic_vector(7 downto 0);
+-signal user_via_pb_out : std_logic_vector(7 downto 0);
+-signal user_via_pb_oe_n : std_logic_vector(7 downto 0);
+-
+--- IC32 latch on System VIA
+-signal ic32 : std_logic_vector(7 downto 0);
+-signal sound_enable_n : std_logic;
+-signal speech_read_n : std_logic;
+-signal speech_write_n : std_logic;
+-signal keyb_enable_n : std_logic;
+-signal disp_addr_offs : std_logic_vector(1 downto 0);
+-signal caps_lock_led_n : std_logic;
+-signal shift_lock_led_n : std_logic;
+-
+--- Keyboard
+-signal keyb_column : std_logic_vector(3 downto 0);
+-signal keyb_row : std_logic_vector(2 downto 0);
+-signal keyb_out : std_logic;
+-signal keyb_int : std_logic;
+-signal keyb_break : std_logic;
+-
+--- Sound generator
+-signal sound_ready : std_logic;
+-signal sound_di : std_logic_vector(7 downto 0);
+-signal sound_ao : signed(7 downto 0);
+-signal pcm_inl : std_logic_vector(15 downto 0);
+-signal pcm_inr : std_logic_vector(15 downto 0);
+-
+--- Memory enables
+-signal ram_enable : std_logic; -- 0x0000
+-signal rom_enable : std_logic; -- 0x8000 (BASIC/sideways ROMs)
+-signal mos_enable : std_logic; -- 0xC000
+--- IO region enables
+-signal io_fred : std_logic; -- 0xFC00 (1 MHz bus)
+-signal io_jim : std_logic; -- 0xFD00 (1 MHz bus)
+-signal io_sheila : std_logic; -- 0xFE00 (System peripherals)
+--- SHIELA
+-signal crtc_enable : std_logic; -- 0xFE00-FE07
+-signal acia_enable : std_logic; -- 0xFE08-FE0F
+-signal serproc_enable : std_logic; -- 0xFE10-FE1F
+-signal vidproc_enable : std_logic; -- 0xFE20-FE2F
+-signal romsel_enable : std_logic; -- 0xFE30-FE3F
+-signal sys_via_enable : std_logic; -- 0xFE40-FE5F
+-signal user_via_enable : std_logic; -- 0xFE60-FE7F
+-signal fddc_enable : std_logic; -- 0xFE80-FE9F
+-signal adlc_enable : std_logic; -- 0xFEA0-FEBF (Econet)
+-signal adc_enable : std_logic; -- 0xFEC0-FEDF
+-signal tube_enable : std_logic; -- 0xFEE0-FEFF
+-
+--- ROM select latch
+-signal romsel : std_logic_vector(3 downto 0);
+-
+-signal mhz1_enable : std_logic; -- Set for access to any 1 MHz peripheral
+-
+-begin
+- -------------------------
+- -- COMPONENT INSTANCES
+- -------------------------
+-
+- -- 32 MHz master clock
+- pll: pll32 port map (
+- pll_reset,
+- CLOCK_24(0),
+- clock,
+- pll_locked );
+-
+- -- Hardware debugger block (single-step, breakpoints)
+- debug: debugger port map (
+- clock,
+- hard_reset_n,
+- cpu_clken,
+- cpu_debug_clken,
+- debug_irq_in_n,
+- cpu_irq_n,
+- cpu_a(15 downto 0), cpu_r_nw, cpu_sync,
+- debug_aux,
+- SW(8), -- RUN
+- KEY(3), -- STEP
+- KEY(2), -- MODE
+- KEY(1), -- DIGIT
+- KEY(0), -- SET
+- HEX3, HEX2, HEX1, HEX0,
+- LEDR(3), -- BREAKPOINT
+- LEDR(2) -- WATCHPOINT
+- );
+-
+- -- 6502 CPU
+- cpu : T65 port map (
+- cpu_mode,
+- reset_n,
+- cpu_debug_clken,
+- clock,
+- cpu_ready,
+- cpu_abort_n,
+- cpu_irq_n,
+- cpu_nmi_n,
+- cpu_so_n,
+- cpu_r_nw,
+- cpu_sync,
+- cpu_ef,
+- cpu_mf,
+- cpu_xf,
+- cpu_ml_n,
+- cpu_vp_n,
+- cpu_vda,
+- cpu_vpa,
+- cpu_a,
+- cpu_di,
+- cpu_do );
+-
+- crtc : mc6845 port map (
+- clock,
+- crtc_clken,
+- reset_n,
+- crtc_enable,
+- cpu_r_nw,
+- cpu_a(0),
+- cpu_do,
+- crtc_do,
+- crtc_vsync,
+- crtc_hsync,
+- crtc_de,
+- crtc_cursor,
+- crtc_lpstb,
+- crtc_ma,
+- crtc_ra );
+-
+- video_ula : vidproc port map (
+- clock,
+- vid_clken,
+- reset_n,
+- crtc_clken,
+- vidproc_enable,
+- cpu_a(0),
+- cpu_do,
+- SRAM_DQ(7 downto 0),
+- vidproc_invert_n,
+- vidproc_disen,
+- crtc_cursor,
+- r_in, g_in, b_in,
+- r_out, g_out, b_out
+- );
+-
+- teletext : saa5050 port map (
+- CLOCK_24(0), -- This runs at 6 MHz, which we can't derive from the 32 MHz clock
+- ttxt_clken,
+- reset_n,
+- clock, -- Data input is synchronised from the bus clock domain
+- vid_clken,
+- SRAM_DQ(6 downto 0),
+- ttxt_glr,
+- ttxt_dew,
+- ttxt_crs,
+- ttxt_lose,
+- ttxt_r, ttxt_g, ttxt_b, ttxt_y
+- );
+-
+- -- System VIA
+- system_via : m6522 port map (
+- cpu_a(3 downto 0),
+- cpu_do,
+- sys_via_do,
+- sys_via_do_oe_n,
+- cpu_r_nw,
+- sys_via_enable,
+- '0', -- nCS2
+- sys_via_irq_n,
+- sys_via_ca1_in,
+- sys_via_ca2_in,
+- sys_via_ca2_out,
+- sys_via_ca2_oe_n,
+- sys_via_pa_in,
+- sys_via_pa_out,
+- sys_via_pa_oe_n,
+- sys_via_cb1_in,
+- sys_via_cb1_out,
+- sys_via_cb1_oe_n,
+- sys_via_cb2_in,
+- sys_via_cb2_out,
+- sys_via_cb2_oe_n,
+- sys_via_pb_in,
+- sys_via_pb_out,
+- sys_via_pb_oe_n,
+- mhz1_clken,
+- hard_reset_n, -- System VIA is reset by power on reset only
+- mhz4_clken,
+- clock
+- );
+-
+- -- User VIA
+- user_via : m6522 port map (
+- cpu_a(3 downto 0),
+- cpu_do,
+- user_via_do,
+- user_via_do_oe_n,
+- cpu_r_nw,
+- user_via_enable,
+- '0', -- nCS2
+- user_via_irq_n,
+- user_via_ca1_in,
+- user_via_ca2_in,
+- user_via_ca2_out,
+- user_via_ca2_oe_n,
+- user_via_pa_in,
+- user_via_pa_out,
+- user_via_pa_oe_n,
+- user_via_cb1_in,
+- user_via_cb1_out,
+- user_via_cb1_oe_n,
+- user_via_cb2_in,
+- user_via_cb2_out,
+- user_via_cb2_oe_n,
+- user_via_pb_in,
+- user_via_pb_out,
+- user_via_pb_oe_n,
+- mhz1_clken,
+- reset_n,
+- mhz4_clken,
+- clock
+- );
+-
+- -- Keyboard
+- keyb : keyboard port map (
+- clock, hard_reset_n, mhz1_clken,
+- PS2_CLK, PS2_DAT,
+- keyb_enable_n,
+- keyb_column,
+- keyb_row,
+- keyb_out,
+- keyb_int,
+- keyb_break,
+- SW(7 downto 0)
+- );
+-
+- -- Sound generator (and drive logic for I2S codec)
+- sound : sn76489_top port map (
+- clock, mhz4_clken,
+- reset_n, '0', sound_enable_n,
+- sound_ready, sound_di,
+- sound_ao
+- );
+- i2s : i2s_intf port map (
+- CLOCK_24(0), reset_n,
+- pcm_inl, pcm_inr,
+- std_logic_vector(sound_ao) & "00000000",
+- std_logic_vector(sound_ao) & "00000000",
+- AUD_XCK, AUD_DACLRCK,
+- AUD_BCLK, AUD_DACDAT, AUD_ADCDAT
+- );
+- i2c : i2c_loader
+- generic map (
+- log2_divider => 7
+- )
+- port map (
+- clock, reset_n,
+- I2C_SCLK, I2C_SDAT,
+- LEDR(5), -- IS_DONE
+- LEDR(4) -- IS_ERROR
+- );
+-
+- -- Asynchronous reset
+- -- PLL is reset by external reset switch
+- pll_reset <= not SW(9);
+- -- Keyboard and System VIA are reset by external reset switch or PLL being out of lock
+- hard_reset_n <= not (pll_reset or not pll_locked);
+- -- Rest of system is reset by all of the above plus the keyboard BREAK key
+- reset_n <= hard_reset_n and not keyb_break;
+-
+- -- Clock enable generation - 32 MHz clock split into 32 cycles
+- -- CPU is on 0 and 16 (but can be masked by 1 MHz bus accesses)
+- -- Video is on all odd cycles (16 MHz)
+- -- 1 MHz cycles are on cycle 31 (1 MHz)
+- vid_clken <= clken_counter(0); -- 1,3,5...
+- mhz4_clken <= clken_counter(0) and clken_counter(1) and clken_counter(2); -- 7/15/23/31
+- mhz2_clken <= mhz4_clken and clken_counter(3); -- 15/31
+- mhz1_clken <= mhz2_clken and clken_counter(4); -- 31
+- cpu_cycle <= not (clken_counter(0) or clken_counter(1) or clken_counter(2) or clken_counter(3)); -- 0/16
+- cpu_clken <= cpu_cycle and not cpu_cycle_mask;
+-
+- clk_gen: process(clock,reset_n)
+- begin
+- if reset_n = '0' then
+- clken_counter <= (others => '0');
+- elsif rising_edge(clock) then
+- clken_counter <= clken_counter + 1;
+- end if;
+- end process;
+-
+- cycle_stretch: process(clock,reset_n)
+- begin
+- if reset_n = '0' then
+- cpu_cycle_mask <= '0';
+- elsif rising_edge(clock) and mhz2_clken = '1' then
+- if mhz1_enable = '1' and cpu_cycle_mask = '0' then
+- -- Block CPU cycles until 1 MHz cycle has completed
+- cpu_cycle_mask <= '1';
+- end if;
+- if mhz1_clken = '1' then
+- -- CPU can run again
+- -- FIXME: This may not be correct in terms of CPU cycles, but it
+- -- should work
+- cpu_cycle_mask <= '0';
+- end if;
+- end if;
+- end process;
+-
+- ttxt_clk_gen: process(CLOCK_24(0),reset_n)
+- begin
+- if reset_n = '0' then
+- ttxt_clken_counter <= (others => '0');
+- elsif rising_edge(CLOCK_24(0)) then
+- ttxt_clken_counter <= ttxt_clken_counter + 1;
+- end if;
+- end process;
+-
+- -- 6 MHz clock enable for SAA5050
+- ttxt_clken <= '1' when ttxt_clken_counter = 0 else '0';
+-
+- -- CPU configuration and fixed signals
+- cpu_mode <= "00"; -- 6502
+- cpu_ready <= '1';
+- cpu_abort_n <= '1';
+- cpu_nmi_n <= '1';
+- cpu_so_n <= '1';
+-
+- -- Address decoding
+- -- 0x0000 = 32 KB SRAM
+- -- 0x8000 = 16 KB BASIC/Sideways ROMs
+- -- 0xC000 = 16 KB MOS ROM
+- --
+- -- IO regions are mapped into a hole in the MOS. There are three regions:
+- -- 0xFC00 = FRED
+- -- 0xFD00 = JIM
+- -- 0xFE00 = SHEILA
+- ram_enable <= not cpu_a(15);
+- rom_enable <= cpu_a(15) and not cpu_a(14);
+- mos_enable <= cpu_a(15) and cpu_a(14) and not (io_fred or io_jim or io_sheila);
+- io_fred <= '1' when cpu_a(15 downto 8) = "11111100" else '0';
+- io_jim <= '1' when cpu_a(15 downto 8) = "11111101" else '0';
+- io_sheila <= '1' when cpu_a(15 downto 8) = "11111110" else '0';
+- -- The following IO regions are accessed at 1 MHz and hence will stall the
+- -- CPU accordingly
+- mhz1_enable <= io_fred or io_jim or
+- adc_enable or sys_via_enable or user_via_enable or
+- serproc_enable or acia_enable or crtc_enable;
+-
+- -- SHEILA address demux
+- -- All the system peripherals are mapped into this page as follows:
+- -- 0xFE00 - 0xFE07 = MC6845 CRTC
+- -- 0xFE08 - 0xFE0F = MC6850 ACIA (Serial/Tape)
+- -- 0xFE10 - 0xFE1F = Serial ULA
+- -- 0xFE20 - 0xFE2F = Video ULA
+- -- 0xFE30 - 0xFE3F = Paged ROM select latch
+- -- 0xFE40 - 0xFE5F = System VIA (6522)
+- -- 0xFE60 - 0xFE7F = User VIA (6522)
+- -- 0xFE80 - 0xFE9F = 8271 Floppy disc controller
+- -- 0xFEA0 - 0xFEBF = 68B54 ADLC for Econet
+- -- 0xFEC0 - 0xFEDF = uPD7002 ADC
+- -- 0xFEE0 - 0xFEFF = Tube ULA
+- process(cpu_a,io_sheila)
+- begin
+- -- All regions normally de-selected
+- crtc_enable <= '0';
+- acia_enable <= '0';
+- serproc_enable <= '0';
+- vidproc_enable <= '0';
+- romsel_enable <= '0';
+- sys_via_enable <= '0';
+- user_via_enable <= '0';
+- fddc_enable <= '0';
+- adlc_enable <= '0';
+- adc_enable <= '0';
+- tube_enable <= '0';
+-
+- if io_sheila = '1' then
+- case cpu_a(7 downto 5) is
+- when "000" =>
+- -- 0xFE00
+- if cpu_a(4) = '0' then
+- if cpu_a(3) = '0' then
+- -- 0xFE00
+- crtc_enable <= '1';
+- else
+- -- 0xFE08
+- acia_enable <= '1';
+- end if;
+- else
+- -- 0xFE10
+- serproc_enable <= '1';
+- end if;
+- when "001" =>
+- -- 0xFE20
+- if cpu_a(4) = '0' then
+- -- 0xFE20
+- vidproc_enable <= '1';
+- else
+- -- 0xFE30
+- romsel_enable <= '1';
+- end if;
+- when "010" => sys_via_enable <= '1'; -- 0xFE40
+- when "011" => user_via_enable <= '1'; -- 0xFE60
+- when "100" => fddc_enable <= '1'; -- 0xFE80
+- when "101" => adlc_enable <= '1'; -- 0xFEA0
+- when "110" => adc_enable <= '1'; -- 0xFEC0
+- when "111" => tube_enable <= '1'; -- 0xFEE0
+- when others =>
+- null;
+- end case;
+- end if;
+- end process;
+-
+- -- CPU data bus mux and interrupts
+- cpu_di <=
+- SRAM_DQ(7 downto 0) when ram_enable = '1' else
+- FL_DQ when rom_enable = '1' else
+- FL_DQ when mos_enable = '1' else
+- crtc_do when crtc_enable = '1' else
+- "00000010" when acia_enable = '1' else
+- sys_via_do when sys_via_enable = '1' else
+- user_via_do when user_via_enable = '1' else
+- (others => '0'); -- un-decoded locations are pulled down by RP1
+- debug_irq_in_n <= sys_via_irq_n and user_via_irq_n; -- route IRQ through debugger
+- --cpu_irq_n <= sys_via_irq_n and user_via_irq_n;
+-
+- -- ROMs are in external flash and split into 16K slots (since this also suits other
+- -- computers that might be run on the same board).
+- -- The first 8 slots are allocated for use here, and the first 4 are decoded as
+- -- the sideways ROMs. Slot 7 is used for the MOS.
+- FL_RST_N <= reset_n;
+- FL_CE_N <= '0';
+- FL_OE_N <= '0';
+- FL_WE_N <= '1';
+- FL_ADDR(21 downto 17) <= ROM_OFFSET(7 downto 3);
+- FL_ADDR(16 downto 14) <=
+- "111" when mos_enable = '1' else
+- "0" & romsel(1 downto 0);
+- FL_ADDR(13 downto 0) <= cpu_a(13 downto 0);
+-
+- -- SRAM bus
+- SRAM_UB_N <= '1';
+- SRAM_LB_N <= '0';
+- SRAM_CE_N <= '0';
+- SRAM_OE_N <= '0';
+- SRAM_DQ(15 downto 8) <= (others => '0');
+-
+- -- Synchronous outputs to SRAM
+- process(clock,reset_n)
+- variable ram_write : std_logic;
+- begin
+- ram_write := ram_enable and not cpu_r_nw;
+-
+- if reset_n = '0' then
+- SRAM_WE_N <= '1';
+- SRAM_DQ(7 downto 0) <= (others => 'Z');
+- elsif rising_edge(clock) then
+- -- Default to inputs
+- SRAM_DQ(7 downto 0) <= (others => 'Z');
+-
+- -- Register SRAM signals to outputs (clock must be at least 2x CPU clock)
+- if vid_clken = '1' then
+- -- Fetch data from previous CPU cycle
+- SRAM_WE_N <= not ram_write;
+- SRAM_ADDR <= "00" & cpu_a(15 downto 0);
+- if ram_write = '1' then
+- SRAM_DQ(7 downto 0) <= cpu_do;
+- end if;
+- else
+- -- Fetch data from previous display cycle
+- SRAM_WE_N <= '1';
+- SRAM_ADDR <= "000" & display_a;
+- end if;
+- end if;
+- end process;
+-
+- -- Address translation logic for calculation of display address
+- process(crtc_ma,crtc_ra,disp_addr_offs)
+- variable aa : unsigned(3 downto 0);
+- begin
+- if crtc_ma(12) = '0' then
+- -- No adjustment
+- aa := unsigned(crtc_ma(11 downto 8));
+- else
+- -- Address adjusted according to screen mode to compensate for
+- -- wrap at 0x8000.
+- case disp_addr_offs is
+- when "00" =>
+- -- Mode 3 - restart at 0x4000
+- aa := unsigned(crtc_ma(11 downto 8)) + 8;
+- when "01" =>
+- -- Mode 6 - restart at 0x6000
+- aa := unsigned(crtc_ma(11 downto 8)) + 12;
+- when "10" =>
+- -- Mode 0,1,2 - restart at 0x3000
+- aa := unsigned(crtc_ma(11 downto 8)) + 6;
+- when "11" =>
+- -- Mode 4,5 - restart at 0x5800
+- aa := unsigned(crtc_ma(11 downto 8)) + 11;
+- when others =>
+- null;
+- end case;
+- end if;
+-
+- if crtc_ma(13) = '0' then
+- -- HI RES
+- display_a <= std_logic_vector(aa(3 downto 0)) & crtc_ma(7 downto 0) & crtc_ra(2 downto 0);
+- else
+- -- TTX VDU
+- display_a <= std_logic(aa(3)) & "1111" & crtc_ma(9 downto 0);
+- end if;
+- end process;
+-
+- -- VIDPROC
+- vidproc_invert_n <= '1';
+- vidproc_disen <= crtc_de and not crtc_ra(3); -- DISEN is masked off by RA(3) for MODEs 3 and 6
+- r_in <= ttxt_r;
+- g_in <= ttxt_g;
+- b_in <= ttxt_b;
+-
+- -- SAA5050
+- ttxt_glr <= not crtc_hsync;
+- ttxt_dew <= crtc_vsync;
+- ttxt_crs <= not crtc_ra(0);
+- ttxt_lose <= crtc_de;
+-
+- -- CRTC drives video out (CSYNC on HSYNC output, VSYNC high)
+- VGA_HS <= not (crtc_hsync xor crtc_vsync);
+- VGA_VS <= '1';
+- VGA_R <= r_out & r_out & r_out & r_out;
+- VGA_G <= g_out & g_out & g_out & g_out;
+- VGA_B <= b_out & b_out & b_out & b_out;
+-
+- -- Connections to System VIA
+- -- ADC
+- sys_via_cb1_in <= '1'; -- /EOC
+- -- CRTC
+- sys_via_ca1_in <= crtc_vsync;
+- sys_via_cb2_in <= crtc_lpstb;
+- -- Keyboard
+- sys_via_ca2_in <= keyb_int;
+- sys_via_pa_in(7) <= keyb_out;
+- sys_via_pa_in(6 downto 0) <= sys_via_pa_out(6 downto 0); -- Must loop back output pins or keyboard won't work
+- keyb_column <= sys_via_pa_out(3 downto 0);
+- keyb_row <= sys_via_pa_out(6 downto 4);
+- -- Sound
+- sound_di <= sys_via_pa_out;
+- -- Others (idle until missing bits implemented)
+- sys_via_pb_in(7 downto 4) <= (others => '1');
+-
+- -- Connections to User VIA (user port is output on green LEDs)
+- user_via_ca1_in <= '1'; -- Pulled up
+- --LEDG <= user_via_pb_out;
+-
+- -- MMBEEB
+- user_via_cb1_in <= user_via_pb_out(1);
+- SD_SCLK <= user_via_pb_out(1); -- SCLK
+- SD_MOSI <= user_via_pb_out(0); -- SDO
+- SD_nCS <= '0'; -- CS
+- user_via_cb2_in <= SD_MISO; -- SDI
+- user_via_pb_in <= user_via_pb_out;
+-
+- -- ROM select latch
+- process(clock,reset_n)
+- begin
+- if reset_n = '0' then
+- romsel <= (others => '0');
+- elsif rising_edge(clock) then
+- if romsel_enable = '1' and cpu_r_nw = '0' then
+- romsel <= cpu_do(3 downto 0);
+- end if;
+- end if;
+- end process;
+-
+- -- IC32 latch
+- sound_enable_n <= ic32(0);
+- speech_write_n <= ic32(1);
+- speech_read_n <= ic32(2);
+- keyb_enable_n <= ic32(3);
+- disp_addr_offs <= ic32(5 downto 4);
+- caps_lock_led_n <= ic32(6);
+- shift_lock_led_n <= ic32(7);
+-
+- process(clock,reset_n)
+- variable bit_num : integer;
+- begin
+- bit_num := to_integer(unsigned(sys_via_pb_out(2 downto 0)));
+-
+- if reset_n = '0' then
+- ic32 <= (others => '0');
+- elsif rising_edge(clock) then
+- ic32(bit_num) <= sys_via_pb_out(3);
+- end if;
+- end process;
+-
+- -- Keyboard LEDs
+- LEDR(0) <= not caps_lock_led_n;
+- LEDR(1) <= not shift_lock_led_n;
+-
+- -----------------
+- -- DEBUG STUFF
+- -----------------
+-
+- GPIO_0(0) <= not (crtc_hsync xor crtc_vsync);
+- GPIO_0(1) <= crtc_de;
+-
+-end architecture;
++-- BBC Micro for Altera DE1
++--
++-- Copyright (c) 2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++-- BBC B Micro
++--
++-- Terasic DE1 top-level
++--
++-- (C) 2011 Mike Stirling
++
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.NUMERIC_STD.ALL;
++
++-- Generic top-level entity for Altera DE1 board
++entity bbc_micro_de1 is
++generic (
++ -- ROM offset
++ -- The 4MB Flash is used in 16KB banks as a simple mechanism for
++ -- different machines to address different parts of the ROM, saving
++ -- on re-flashing each time a new machine is run on the board.
++ -- This generic sets the upper 8 address bits.
++ -- Note that the lower bits may be ignored by the implementation,
++ -- e.g. where ROMs are bigger than 16K or where multiple banks
++ -- are required. In this case it is important to ensure that the
++ -- ROM images are aligned correctly (such that these ignored bits are 0).
++ --
++ -- For the BBC the ROMs start in bank 8 (the first 8 banks are used by
++ -- the Spectrum project). The particular bank is selected by the sideways
++ -- ROM paging register, and bank 7 is used for the MOS. Recommended layout
++ -- is:
++ --
++ -- 0 Sideways
++ -- 1 Sideways
++ -- 2 Sideways - SuperMMC (DFS)
++ -- 3 Sideways - BASIC
++ -- 4 Not used
++ -- 5 Not used
++ -- 6 Not used
++ -- 7 MOS
++ ROM_OFFSET : std_logic_vector(7 downto 0) := "00001000"
++ );
++port (
++ -- Clocks
++ CLOCK_24 : in std_logic_vector(1 downto 0);
++ CLOCK_27 : in std_logic_vector(1 downto 0);
++ CLOCK_50 : in std_logic;
++ EXT_CLOCK : in std_logic;
++
++ -- Switches
++ SW : in std_logic_vector(9 downto 0);
++ -- Buttons
++ KEY : in std_logic_vector(3 downto 0);
++
++ -- 7 segment displays
++ HEX0 : out std_logic_vector(6 downto 0);
++ HEX1 : out std_logic_vector(6 downto 0);
++ HEX2 : out std_logic_vector(6 downto 0);
++ HEX3 : out std_logic_vector(6 downto 0);
++ -- Red LEDs
++ LEDR : out std_logic_vector(9 downto 0);
++ -- Green LEDs
++ LEDG : out std_logic_vector(7 downto 0);
++
++ -- VGA
++ VGA_R : out std_logic_vector(3 downto 0);
++ VGA_G : out std_logic_vector(3 downto 0);
++ VGA_B : out std_logic_vector(3 downto 0);
++ VGA_HS : out std_logic;
++ VGA_VS : out std_logic;
++
++ -- Serial
++ UART_RXD : in std_logic;
++ UART_TXD : out std_logic;
++
++ -- PS/2 Keyboard
++ PS2_CLK : inout std_logic;
++ PS2_DAT : inout std_logic;
++
++ -- I2C
++ I2C_SCLK : inout std_logic;
++ I2C_SDAT : inout std_logic;
++
++ -- Audio
++ AUD_XCK : out std_logic;
++ AUD_BCLK : out std_logic;
++ AUD_ADCLRCK : out std_logic;
++ AUD_ADCDAT : in std_logic;
++ AUD_DACLRCK : out std_logic;
++ AUD_DACDAT : out std_logic;
++
++ -- SRAM
++ SRAM_ADDR : out std_logic_vector(17 downto 0);
++ SRAM_DQ : inout std_logic_vector(15 downto 0);
++ SRAM_CE_N : out std_logic;
++ SRAM_OE_N : out std_logic;
++ SRAM_WE_N : out std_logic;
++ SRAM_UB_N : out std_logic;
++ SRAM_LB_N : out std_logic;
++
++ -- SDRAM
++ DRAM_ADDR : out std_logic_vector(11 downto 0);
++ DRAM_DQ : inout std_logic_vector(15 downto 0);
++ DRAM_BA_0 : in std_logic;
++ DRAM_BA_1 : in std_logic;
++ DRAM_CAS_N : in std_logic;
++ DRAM_CKE : in std_logic;
++ DRAM_CLK : in std_logic;
++ DRAM_CS_N : in std_logic;
++ DRAM_LDQM : in std_logic;
++ DRAM_RAS_N : in std_logic;
++ DRAM_UDQM : in std_logic;
++ DRAM_WE_N : in std_logic;
++
++ -- Flash
++ FL_ADDR : out std_logic_vector(21 downto 0);
++ FL_DQ : inout std_logic_vector(7 downto 0);
++ FL_RST_N : out std_logic;
++ FL_OE_N : out std_logic;
++ FL_WE_N : out std_logic;
++ FL_CE_N : out std_logic;
++
++ -- SD card (SPI mode)
++ SD_nCS : out std_logic;
++ SD_MOSI : out std_logic;
++ SD_SCLK : out std_logic;
++ SD_MISO : in std_logic;
++
++ -- GPIO
++ GPIO_0 : inout std_logic_vector(35 downto 0);
++ GPIO_1 : inout std_logic_vector(35 downto 0)
++ );
++end entity;
++
++architecture rtl of bbc_micro_de1 is
++
++------------------------------
++-- PLL (32 MHz master clock)
++------------------------------
++
++component pll32 IS
++ PORT
++ (
++ areset : IN STD_LOGIC := '0';
++ inclk0 : IN STD_LOGIC := '0';
++ c0 : OUT STD_LOGIC ;
++ locked : OUT STD_LOGIC
++ );
++end component;
++
++---------
++-- CPU
++---------
++
++component T65 is
++ port(
++ Mode : in std_logic_vector(1 downto 0); -- "00" => 6502, "01" => 65C02, "10" => 65C816
++ Res_n : in std_logic;
++ Enable : in std_logic;
++ Clk : in std_logic;
++ Rdy : in std_logic;
++ Abort_n : in std_logic;
++ IRQ_n : in std_logic;
++ NMI_n : in std_logic;
++ SO_n : in std_logic;
++ R_W_n : out std_logic;
++ Sync : out std_logic;
++ EF : out std_logic;
++ MF : out std_logic;
++ XF : out std_logic;
++ ML_n : out std_logic;
++ VP_n : out std_logic;
++ VDA : out std_logic;
++ VPA : out std_logic;
++ A : out std_logic_vector(23 downto 0);
++ DI : in std_logic_vector(7 downto 0);
++ DO : out std_logic_vector(7 downto 0)
++ );
++end component;
++
++-----------------
++-- MC6845 CRTC
++-----------------
++
++component mc6845 is
++port (
++ CLOCK : in std_logic;
++ CLKEN : in std_logic;
++ nRESET : in std_logic;
++
++ -- Bus interface
++ ENABLE : in std_logic;
++ R_nW : in std_logic;
++ RS : in std_logic;
++ DI : in std_logic_vector(7 downto 0);
++ DO : out std_logic_vector(7 downto 0);
++
++ -- Display interface
++ VSYNC : out std_logic;
++ HSYNC : out std_logic;
++ DE : out std_logic;
++ CURSOR : out std_logic;
++ LPSTB : in std_logic;
++
++ -- Memory interface
++ MA : out std_logic_vector(13 downto 0);
++ RA : out std_logic_vector(4 downto 0)
++ );
++end component;
++
++-------------------------
++-- "VIDPROC" Video ULA
++-------------------------
++
++component vidproc is
++port (
++ CLOCK : in std_logic;
++ -- Clock enable qualifies display cycles (interleaved with CPU cycles)
++ CLKEN : in std_logic;
++ nRESET : in std_logic;
++
++ -- Clock enable output to CRTC
++ CLKEN_CRTC : out std_logic;
++
++ -- Bus interface
++ ENABLE : in std_logic;
++ A0 : in std_logic;
++ -- CPU data bus (for register writes)
++ DI_CPU : in std_logic_vector(7 downto 0);
++ -- Display RAM data bus (for display data fetch)
++ DI_RAM : in std_logic_vector(7 downto 0);
++
++ -- Control interface
++ nINVERT : in std_logic;
++ DISEN : in std_logic;
++ CURSOR : in std_logic;
++
++ -- Video in (teletext mode)
++ R_IN : in std_logic;
++ G_IN : in std_logic;
++ B_IN : in std_logic;
++
++ -- Video out
++ R : out std_logic;
++ G : out std_logic;
++ B : out std_logic
++ );
++end component;
++
++--------------------------------
++-- SAA5050 Teletext Generator
++--------------------------------
++
++component saa5050 is
++port (
++ CLOCK : in std_logic;
++ -- 6 MHz dot clock enable
++ CLKEN : in std_logic;
++ -- Async reset
++ nRESET : in std_logic;
++
++ -- Character data input (in the bus clock domain)
++ DI_CLOCK : in std_logic;
++ DI_CLKEN : in std_logic;
++ DI : in std_logic_vector(6 downto 0);
++
++ -- Timing inputs
++ -- General line reset (not used)
++ GLR : in std_logic; -- /HSYNC
++ -- Data entry window - high during VSYNC.
++ -- Resets ROM row counter and drives 'flash' signal
++ DEW : in std_logic; -- VSYNC
++ -- Character rounding select - high during even field
++ CRS : in std_logic; -- FIELD
++ -- Load output shift register enable - high during active video
++ LOSE : in std_logic; -- DE
++
++ -- Video out
++ R : out std_logic;
++ G : out std_logic;
++ B : out std_logic;
++ Y : out std_logic
++ );
++end component;
++
++--------------
++-- 6522 VIA
++--------------
++
++component M6522 is
++ port (
++
++ I_RS : in std_logic_vector(3 downto 0);
++ I_DATA : in std_logic_vector(7 downto 0);
++ O_DATA : out std_logic_vector(7 downto 0);
++ O_DATA_OE_L : out std_logic;
++
++ I_RW_L : in std_logic;
++ I_CS1 : in std_logic;
++ I_CS2_L : in std_logic;
++
++ O_IRQ_L : out std_logic; -- note, not open drain
++ -- port a
++ I_CA1 : in std_logic;
++ I_CA2 : in std_logic;
++ O_CA2 : out std_logic;
++ O_CA2_OE_L : out std_logic;
++
++ I_PA : in std_logic_vector(7 downto 0);
++ O_PA : out std_logic_vector(7 downto 0);
++ O_PA_OE_L : out std_logic_vector(7 downto 0);
++
++ -- port b
++ I_CB1 : in std_logic;
++ O_CB1 : out std_logic;
++ O_CB1_OE_L : out std_logic;
++
++ I_CB2 : in std_logic;
++ O_CB2 : out std_logic;
++ O_CB2_OE_L : out std_logic;
++
++ I_PB : in std_logic_vector(7 downto 0);
++ O_PB : out std_logic_vector(7 downto 0);
++ O_PB_OE_L : out std_logic_vector(7 downto 0);
++
++ -- FIXME: Revisit timing in this component. Does it really need a 4x clock?
++ I_P2_H : in std_logic; -- high for phase 2 clock ____----__
++ RESET_L : in std_logic;
++ ENA_4 : in std_logic; -- clk enable (4x system clock rate)
++ CLK : in std_logic
++ );
++end component;
++
++-----------------------------
++-- PS/2 Keyboard Emulation
++-----------------------------
++
++component keyboard is
++port (
++ CLOCK : in std_logic;
++ nRESET : in std_logic;
++ CLKEN_1MHZ : in std_logic;
++
++ -- PS/2 interface
++ PS2_CLK : in std_logic;
++ PS2_DATA : in std_logic;
++
++ -- If 1 then column is incremented automatically at
++ -- 1 MHz rate
++ AUTOSCAN : in std_logic;
++
++ COLUMN : in std_logic_vector(3 downto 0);
++ ROW : in std_logic_vector(2 downto 0);
++
++ -- 1 when currently selected key is down (AUTOSCAN disabled)
++ KEYPRESS : out std_logic;
++ -- 1 when any key is down (except row 0)
++ INT : out std_logic;
++ -- BREAK key output - 1 when pressed
++ BREAK_OUT : out std_logic;
++
++ -- DIP switch inputs
++ DIP_SWITCH : in std_logic_vector(7 downto 0)
++ );
++end component;
++
++-----------------------------
++-- SN76489 sound generator
++-----------------------------
++
++component sn76489_top is
++
++ generic (
++ clock_div_16_g : integer := 1
++ );
++ port (
++ clock_i : in std_logic;
++ clock_en_i : in std_logic;
++ res_n_i : in std_logic;
++ ce_n_i : in std_logic;
++ we_n_i : in std_logic;
++ ready_o : out std_logic;
++ d_i : in std_logic_vector(0 to 7);
++ aout_o : out signed(0 to 7)
++ );
++
++end component;
++
++component i2s_intf is
++generic(
++ mclk_rate : positive := 12000000;
++ sample_rate : positive := 8000;
++ preamble : positive := 1; -- I2S
++ word_length : positive := 16
++ );
++
++port (
++ -- 2x MCLK in (e.g. 24 MHz for WM8731 USB mode)
++ CLK : in std_logic;
++ nRESET : in std_logic;
++
++ -- Parallel IO
++ PCM_INL : out std_logic_vector(word_length - 1 downto 0);
++ PCM_INR : out std_logic_vector(word_length - 1 downto 0);
++ PCM_OUTL : in std_logic_vector(word_length - 1 downto 0);
++ PCM_OUTR : in std_logic_vector(word_length - 1 downto 0);
++
++ -- Codec interface (right justified mode)
++ -- MCLK is generated at half of the CLK input
++ I2S_MCLK : out std_logic;
++ -- LRCLK is equal to the sample rate and is synchronous to
++ -- MCLK. It must be related to MCLK by the oversampling ratio
++ -- given in the codec datasheet.
++ I2S_LRCLK : out std_logic;
++
++ -- Data is shifted out on the falling edge of BCLK, sampled
++ -- on the rising edge. The bit rate is determined such that
++ -- it is fast enough to fit preamble + word_length bits into
++ -- each LRCLK half cycle. The last cycle of each word may be
++ -- stretched to fit to LRCLK. This is OK at least for the
++ -- WM8731 codec.
++ -- The first falling edge of each timeslot is always synchronised
++ -- with the LRCLK edge.
++ I2S_BCLK : out std_logic;
++ -- Output bitstream
++ I2S_DOUT : out std_logic;
++ -- Input bitstream
++ I2S_DIN : in std_logic
++ );
++end component;
++
++component i2c_loader is
++generic (
++ -- Address of slave to be loaded
++ device_address : integer := 16#1a#;
++ -- Number of retries to allow before stopping
++ num_retries : integer := 0;
++ -- Length of clock divider in bits. Resulting bus frequency is
++ -- CLK/2^(log2_divider + 2)
++ log2_divider : integer := 6
++);
++
++port (
++ CLK : in std_logic;
++ nRESET : in std_logic;
++
++ I2C_SCL : inout std_logic;
++ I2C_SDA : inout std_logic;
++
++ IS_DONE : out std_logic;
++ IS_ERROR : out std_logic
++ );
++end component;
++
++component debugger is
++generic (
++ -- Set this for a reasonable half flash duration relative to the
++ -- clock frequency
++ flash_divider : natural := 24
++ );
++port (
++ CLOCK : in std_logic;
++ nRESET : in std_logic;
++ -- CPU clock enable in
++ CLKEN_IN : in std_logic;
++ -- Gated clock enable back out to CPU
++ CLKEN_OUT : out std_logic;
++ -- CPU IRQ in
++ nIRQ_IN : in std_logic;
++ -- Gated IRQ back out to CPU (no interrupts when single stepping)
++ nIRQ_OUT : out std_logic;
++
++ -- CPU
++ A_CPU : in std_logic_vector(15 downto 0);
++ R_nW : in std_logic;
++ SYNC : in std_logic;
++
++ -- Aux bus input for display in hex
++ AUX_BUS : in std_logic_vector(15 downto 0);
++
++ -- Controls
++ -- RUN or HALT CPU
++ RUN : in std_logic;
++ -- Push button to single-step in HALT mode
++ nSTEP : in std_logic;
++ -- Push button to cycle display mode
++ nMODE : in std_logic;
++ -- Push button to cycle display digit in edit mode
++ nDIGIT : in std_logic;
++ -- Push button to cycle digit value in edit mode
++ nSET : in std_logic;
++
++ -- Output to display
++ DIGIT3 : out std_logic_vector(6 downto 0);
++ DIGIT2 : out std_logic_vector(6 downto 0);
++ DIGIT1 : out std_logic_vector(6 downto 0);
++ DIGIT0 : out std_logic_vector(6 downto 0);
++
++ LED_BREAKPOINT : out std_logic;
++ LED_WATCHPOINT : out std_logic
++ );
++end component;
++
++-------------
++-- Signals
++-------------
++
++-- Master clock - 32 MHz
++signal pll_reset : std_logic;
++signal pll_locked : std_logic;
++signal clock : std_logic;
++signal hard_reset_n : std_logic;
++signal reset_n : std_logic;
++
++-- Clock enable counter
++-- CPU and video cycles are interleaved. The CPU runs at 2 MHz (every 16th
++-- cycle) and the video subsystem is enabled on every odd cycle.
++signal clken_counter : unsigned(4 downto 0);
++signal cpu_cycle : std_logic; -- Qualifies all 2 MHz cycles
++signal cpu_cycle_mask : std_logic; -- Set to mask CPU cycles until 1 MHz cycle is complete
++signal cpu_clken : std_logic; -- 2 MHz cycles in which the CPU is enabled
++signal cpu_debug_clken : std_logic; -- CPU clken return from hardware debugger
++-- IO cycles are out of phase with the CPU
++signal vid_clken : std_logic; -- 16 MHz video cycles
++signal mhz4_clken : std_logic; -- Used by 6522
++signal mhz2_clken : std_logic; -- Used for latching CPU address for clock stretch
++signal mhz1_clken : std_logic; -- 1 MHz bus and associated peripherals, 6522 phase 2
++-- SAA5050 needs a 6 MHz clock enable relative to a 24 MHz clock
++signal ttxt_clken_counter : unsigned(1 downto 0);
++signal ttxt_clken : std_logic;
++
++-- Debugger connections
++signal debug_irq_in_n : std_logic;
++signal debug_aux : std_logic_vector(15 downto 0);
++
++-- CPU signals
++signal cpu_mode : std_logic_vector(1 downto 0);
++signal cpu_ready : std_logic;
++signal cpu_abort_n : std_logic;
++signal cpu_irq_n : std_logic;
++signal cpu_nmi_n : std_logic;
++signal cpu_so_n : std_logic;
++signal cpu_r_nw : std_logic;
++signal cpu_sync : std_logic;
++signal cpu_ef : std_logic;
++signal cpu_mf : std_logic;
++signal cpu_xf : std_logic;
++signal cpu_ml_n : std_logic;
++signal cpu_vp_n : std_logic;
++signal cpu_vda : std_logic;
++signal cpu_vpa : std_logic;
++signal cpu_a : std_logic_vector(23 downto 0);
++signal cpu_di : std_logic_vector(7 downto 0);
++signal cpu_do : std_logic_vector(7 downto 0);
++
++-- CRTC signals
++signal crtc_clken : std_logic;
++signal crtc_do : std_logic_vector(7 downto 0);
++signal crtc_vsync : std_logic;
++signal crtc_hsync : std_logic;
++signal crtc_de : std_logic;
++signal crtc_cursor : std_logic;
++signal crtc_lpstb : std_logic := '0';
++signal crtc_ma : std_logic_vector(13 downto 0);
++signal crtc_ra : std_logic_vector(4 downto 0);
++
++-- Decoded display address after address translation for hardware
++-- scrolling
++signal display_a : std_logic_vector(14 downto 0);
++
++-- "VIDPROC" signals
++signal vidproc_invert_n : std_logic;
++signal vidproc_disen : std_logic;
++signal r_in : std_logic;
++signal g_in : std_logic;
++signal b_in : std_logic;
++signal r_out : std_logic;
++signal g_out : std_logic;
++signal b_out : std_logic;
++
++-- SAA5050 signals
++signal ttxt_glr : std_logic;
++signal ttxt_dew : std_logic;
++signal ttxt_crs : std_logic;
++signal ttxt_lose : std_logic;
++signal ttxt_r : std_logic;
++signal ttxt_g : std_logic;
++signal ttxt_b : std_logic;
++signal ttxt_y : std_logic;
++
++-- System VIA signals
++signal sys_via_do : std_logic_vector(7 downto 0);
++signal sys_via_do_oe_n : std_logic;
++signal sys_via_irq_n : std_logic;
++signal sys_via_ca1_in : std_logic := '0';
++signal sys_via_ca2_in : std_logic := '0';
++signal sys_via_ca2_out : std_logic;
++signal sys_via_ca2_oe_n : std_logic;
++signal sys_via_pa_in : std_logic_vector(7 downto 0);
++signal sys_via_pa_out : std_logic_vector(7 downto 0);
++signal sys_via_pa_oe_n : std_logic_vector(7 downto 0);
++signal sys_via_cb1_in : std_logic := '0';
++signal sys_via_cb1_out : std_logic;
++signal sys_via_cb1_oe_n : std_logic;
++signal sys_via_cb2_in : std_logic := '0';
++signal sys_via_cb2_out : std_logic;
++signal sys_via_cb2_oe_n : std_logic;
++signal sys_via_pb_in : std_logic_vector(7 downto 0);
++signal sys_via_pb_out : std_logic_vector(7 downto 0);
++signal sys_via_pb_oe_n : std_logic_vector(7 downto 0);
++
++-- User VIA signals
++signal user_via_do : std_logic_vector(7 downto 0);
++signal user_via_do_oe_n : std_logic;
++signal user_via_irq_n : std_logic;
++signal user_via_ca1_in : std_logic := '0';
++signal user_via_ca2_in : std_logic := '0';
++signal user_via_ca2_out : std_logic;
++signal user_via_ca2_oe_n : std_logic;
++signal user_via_pa_in : std_logic_vector(7 downto 0);
++signal user_via_pa_out : std_logic_vector(7 downto 0);
++signal user_via_pa_oe_n : std_logic_vector(7 downto 0);
++signal user_via_cb1_in : std_logic := '0';
++signal user_via_cb1_out : std_logic;
++signal user_via_cb1_oe_n : std_logic;
++signal user_via_cb2_in : std_logic := '0';
++signal user_via_cb2_out : std_logic;
++signal user_via_cb2_oe_n : std_logic;
++signal user_via_pb_in : std_logic_vector(7 downto 0);
++signal user_via_pb_out : std_logic_vector(7 downto 0);
++signal user_via_pb_oe_n : std_logic_vector(7 downto 0);
++
++-- IC32 latch on System VIA
++signal ic32 : std_logic_vector(7 downto 0);
++signal sound_enable_n : std_logic;
++signal speech_read_n : std_logic;
++signal speech_write_n : std_logic;
++signal keyb_enable_n : std_logic;
++signal disp_addr_offs : std_logic_vector(1 downto 0);
++signal caps_lock_led_n : std_logic;
++signal shift_lock_led_n : std_logic;
++
++-- Keyboard
++signal keyb_column : std_logic_vector(3 downto 0);
++signal keyb_row : std_logic_vector(2 downto 0);
++signal keyb_out : std_logic;
++signal keyb_int : std_logic;
++signal keyb_break : std_logic;
++
++-- Sound generator
++signal sound_ready : std_logic;
++signal sound_di : std_logic_vector(7 downto 0);
++signal sound_ao : signed(7 downto 0);
++signal pcm_inl : std_logic_vector(15 downto 0);
++signal pcm_inr : std_logic_vector(15 downto 0);
++
++-- Memory enables
++signal ram_enable : std_logic; -- 0x0000
++signal rom_enable : std_logic; -- 0x8000 (BASIC/sideways ROMs)
++signal mos_enable : std_logic; -- 0xC000
++-- IO region enables
++signal io_fred : std_logic; -- 0xFC00 (1 MHz bus)
++signal io_jim : std_logic; -- 0xFD00 (1 MHz bus)
++signal io_sheila : std_logic; -- 0xFE00 (System peripherals)
++-- SHIELA
++signal crtc_enable : std_logic; -- 0xFE00-FE07
++signal acia_enable : std_logic; -- 0xFE08-FE0F
++signal serproc_enable : std_logic; -- 0xFE10-FE1F
++signal vidproc_enable : std_logic; -- 0xFE20-FE2F
++signal romsel_enable : std_logic; -- 0xFE30-FE3F
++signal sys_via_enable : std_logic; -- 0xFE40-FE5F
++signal user_via_enable : std_logic; -- 0xFE60-FE7F
++signal fddc_enable : std_logic; -- 0xFE80-FE9F
++signal adlc_enable : std_logic; -- 0xFEA0-FEBF (Econet)
++signal adc_enable : std_logic; -- 0xFEC0-FEDF
++signal tube_enable : std_logic; -- 0xFEE0-FEFF
++
++-- ROM select latch
++signal romsel : std_logic_vector(3 downto 0);
++
++signal mhz1_enable : std_logic; -- Set for access to any 1 MHz peripheral
++
++begin
++ -------------------------
++ -- COMPONENT INSTANCES
++ -------------------------
++
++ -- 32 MHz master clock
++ pll: pll32 port map (
++ pll_reset,
++ CLOCK_24(0),
++ clock,
++ pll_locked );
++
++ -- Hardware debugger block (single-step, breakpoints)
++ debug: debugger port map (
++ clock,
++ hard_reset_n,
++ cpu_clken,
++ cpu_debug_clken,
++ debug_irq_in_n,
++ cpu_irq_n,
++ cpu_a(15 downto 0), cpu_r_nw, cpu_sync,
++ debug_aux,
++ SW(8), -- RUN
++ KEY(3), -- STEP
++ KEY(2), -- MODE
++ KEY(1), -- DIGIT
++ KEY(0), -- SET
++ HEX3, HEX2, HEX1, HEX0,
++ LEDR(3), -- BREAKPOINT
++ LEDR(2) -- WATCHPOINT
++ );
++
++ -- 6502 CPU
++ cpu : T65 port map (
++ cpu_mode,
++ reset_n,
++ cpu_debug_clken,
++ clock,
++ cpu_ready,
++ cpu_abort_n,
++ cpu_irq_n,
++ cpu_nmi_n,
++ cpu_so_n,
++ cpu_r_nw,
++ cpu_sync,
++ cpu_ef,
++ cpu_mf,
++ cpu_xf,
++ cpu_ml_n,
++ cpu_vp_n,
++ cpu_vda,
++ cpu_vpa,
++ cpu_a,
++ cpu_di,
++ cpu_do );
++
++ crtc : mc6845 port map (
++ clock,
++ crtc_clken,
++ reset_n,
++ crtc_enable,
++ cpu_r_nw,
++ cpu_a(0),
++ cpu_do,
++ crtc_do,
++ crtc_vsync,
++ crtc_hsync,
++ crtc_de,
++ crtc_cursor,
++ crtc_lpstb,
++ crtc_ma,
++ crtc_ra );
++
++ video_ula : vidproc port map (
++ clock,
++ vid_clken,
++ reset_n,
++ crtc_clken,
++ vidproc_enable,
++ cpu_a(0),
++ cpu_do,
++ SRAM_DQ(7 downto 0),
++ vidproc_invert_n,
++ vidproc_disen,
++ crtc_cursor,
++ r_in, g_in, b_in,
++ r_out, g_out, b_out
++ );
++
++ teletext : saa5050 port map (
++ CLOCK_24(0), -- This runs at 6 MHz, which we can't derive from the 32 MHz clock
++ ttxt_clken,
++ reset_n,
++ clock, -- Data input is synchronised from the bus clock domain
++ vid_clken,
++ SRAM_DQ(6 downto 0),
++ ttxt_glr,
++ ttxt_dew,
++ ttxt_crs,
++ ttxt_lose,
++ ttxt_r, ttxt_g, ttxt_b, ttxt_y
++ );
++
++ -- System VIA
++ system_via : m6522 port map (
++ cpu_a(3 downto 0),
++ cpu_do,
++ sys_via_do,
++ sys_via_do_oe_n,
++ cpu_r_nw,
++ sys_via_enable,
++ '0', -- nCS2
++ sys_via_irq_n,
++ sys_via_ca1_in,
++ sys_via_ca2_in,
++ sys_via_ca2_out,
++ sys_via_ca2_oe_n,
++ sys_via_pa_in,
++ sys_via_pa_out,
++ sys_via_pa_oe_n,
++ sys_via_cb1_in,
++ sys_via_cb1_out,
++ sys_via_cb1_oe_n,
++ sys_via_cb2_in,
++ sys_via_cb2_out,
++ sys_via_cb2_oe_n,
++ sys_via_pb_in,
++ sys_via_pb_out,
++ sys_via_pb_oe_n,
++ mhz1_clken,
++ hard_reset_n, -- System VIA is reset by power on reset only
++ mhz4_clken,
++ clock
++ );
++
++ -- User VIA
++ user_via : m6522 port map (
++ cpu_a(3 downto 0),
++ cpu_do,
++ user_via_do,
++ user_via_do_oe_n,
++ cpu_r_nw,
++ user_via_enable,
++ '0', -- nCS2
++ user_via_irq_n,
++ user_via_ca1_in,
++ user_via_ca2_in,
++ user_via_ca2_out,
++ user_via_ca2_oe_n,
++ user_via_pa_in,
++ user_via_pa_out,
++ user_via_pa_oe_n,
++ user_via_cb1_in,
++ user_via_cb1_out,
++ user_via_cb1_oe_n,
++ user_via_cb2_in,
++ user_via_cb2_out,
++ user_via_cb2_oe_n,
++ user_via_pb_in,
++ user_via_pb_out,
++ user_via_pb_oe_n,
++ mhz1_clken,
++ reset_n,
++ mhz4_clken,
++ clock
++ );
++
++ -- Keyboard
++ keyb : keyboard port map (
++ clock, hard_reset_n, mhz1_clken,
++ PS2_CLK, PS2_DAT,
++ keyb_enable_n,
++ keyb_column,
++ keyb_row,
++ keyb_out,
++ keyb_int,
++ keyb_break,
++ SW(7 downto 0)
++ );
++
++ -- Sound generator (and drive logic for I2S codec)
++ sound : sn76489_top port map (
++ clock, mhz4_clken,
++ reset_n, '0', sound_enable_n,
++ sound_ready, sound_di,
++ sound_ao
++ );
++ i2s : i2s_intf port map (
++ CLOCK_24(0), reset_n,
++ pcm_inl, pcm_inr,
++ std_logic_vector(sound_ao) & "00000000",
++ std_logic_vector(sound_ao) & "00000000",
++ AUD_XCK, AUD_DACLRCK,
++ AUD_BCLK, AUD_DACDAT, AUD_ADCDAT
++ );
++ i2c : i2c_loader
++ generic map (
++ log2_divider => 7
++ )
++ port map (
++ clock, reset_n,
++ I2C_SCLK, I2C_SDAT,
++ LEDR(5), -- IS_DONE
++ LEDR(4) -- IS_ERROR
++ );
++
++ -- Asynchronous reset
++ -- PLL is reset by external reset switch
++ pll_reset <= not SW(9);
++ -- Keyboard and System VIA are reset by external reset switch or PLL being out of lock
++ hard_reset_n <= not (pll_reset or not pll_locked);
++ -- Rest of system is reset by all of the above plus the keyboard BREAK key
++ reset_n <= hard_reset_n and not keyb_break;
++
++ -- Clock enable generation - 32 MHz clock split into 32 cycles
++ -- CPU is on 0 and 16 (but can be masked by 1 MHz bus accesses)
++ -- Video is on all odd cycles (16 MHz)
++ -- 1 MHz cycles are on cycle 31 (1 MHz)
++ vid_clken <= clken_counter(0); -- 1,3,5...
++ mhz4_clken <= clken_counter(0) and clken_counter(1) and clken_counter(2); -- 7/15/23/31
++ mhz2_clken <= mhz4_clken and clken_counter(3); -- 15/31
++ mhz1_clken <= mhz2_clken and clken_counter(4); -- 31
++ cpu_cycle <= not (clken_counter(0) or clken_counter(1) or clken_counter(2) or clken_counter(3)); -- 0/16
++ cpu_clken <= cpu_cycle and not cpu_cycle_mask;
++
++ clk_gen: process(clock,reset_n)
++ begin
++ if reset_n = '0' then
++ clken_counter <= (others => '0');
++ elsif rising_edge(clock) then
++ clken_counter <= clken_counter + 1;
++ end if;
++ end process;
++
++ cycle_stretch: process(clock,reset_n)
++ begin
++ if reset_n = '0' then
++ cpu_cycle_mask <= '0';
++ elsif rising_edge(clock) and mhz2_clken = '1' then
++ if mhz1_enable = '1' and cpu_cycle_mask = '0' then
++ -- Block CPU cycles until 1 MHz cycle has completed
++ cpu_cycle_mask <= '1';
++ end if;
++ if mhz1_clken = '1' then
++ -- CPU can run again
++ -- FIXME: This may not be correct in terms of CPU cycles, but it
++ -- should work
++ cpu_cycle_mask <= '0';
++ end if;
++ end if;
++ end process;
++
++ ttxt_clk_gen: process(CLOCK_24(0),reset_n)
++ begin
++ if reset_n = '0' then
++ ttxt_clken_counter <= (others => '0');
++ elsif rising_edge(CLOCK_24(0)) then
++ ttxt_clken_counter <= ttxt_clken_counter + 1;
++ end if;
++ end process;
++
++ -- 6 MHz clock enable for SAA5050
++ ttxt_clken <= '1' when ttxt_clken_counter = 0 else '0';
++
++ -- CPU configuration and fixed signals
++ cpu_mode <= "00"; -- 6502
++ cpu_ready <= '1';
++ cpu_abort_n <= '1';
++ cpu_nmi_n <= '1';
++ cpu_so_n <= '1';
++
++ -- Address decoding
++ -- 0x0000 = 32 KB SRAM
++ -- 0x8000 = 16 KB BASIC/Sideways ROMs
++ -- 0xC000 = 16 KB MOS ROM
++ --
++ -- IO regions are mapped into a hole in the MOS. There are three regions:
++ -- 0xFC00 = FRED
++ -- 0xFD00 = JIM
++ -- 0xFE00 = SHEILA
++ ram_enable <= not cpu_a(15);
++ rom_enable <= cpu_a(15) and not cpu_a(14);
++ mos_enable <= cpu_a(15) and cpu_a(14) and not (io_fred or io_jim or io_sheila);
++ io_fred <= '1' when cpu_a(15 downto 8) = "11111100" else '0';
++ io_jim <= '1' when cpu_a(15 downto 8) = "11111101" else '0';
++ io_sheila <= '1' when cpu_a(15 downto 8) = "11111110" else '0';
++ -- The following IO regions are accessed at 1 MHz and hence will stall the
++ -- CPU accordingly
++ mhz1_enable <= io_fred or io_jim or
++ adc_enable or sys_via_enable or user_via_enable or
++ serproc_enable or acia_enable or crtc_enable;
++
++ -- SHEILA address demux
++ -- All the system peripherals are mapped into this page as follows:
++ -- 0xFE00 - 0xFE07 = MC6845 CRTC
++ -- 0xFE08 - 0xFE0F = MC6850 ACIA (Serial/Tape)
++ -- 0xFE10 - 0xFE1F = Serial ULA
++ -- 0xFE20 - 0xFE2F = Video ULA
++ -- 0xFE30 - 0xFE3F = Paged ROM select latch
++ -- 0xFE40 - 0xFE5F = System VIA (6522)
++ -- 0xFE60 - 0xFE7F = User VIA (6522)
++ -- 0xFE80 - 0xFE9F = 8271 Floppy disc controller
++ -- 0xFEA0 - 0xFEBF = 68B54 ADLC for Econet
++ -- 0xFEC0 - 0xFEDF = uPD7002 ADC
++ -- 0xFEE0 - 0xFEFF = Tube ULA
++ process(cpu_a,io_sheila)
++ begin
++ -- All regions normally de-selected
++ crtc_enable <= '0';
++ acia_enable <= '0';
++ serproc_enable <= '0';
++ vidproc_enable <= '0';
++ romsel_enable <= '0';
++ sys_via_enable <= '0';
++ user_via_enable <= '0';
++ fddc_enable <= '0';
++ adlc_enable <= '0';
++ adc_enable <= '0';
++ tube_enable <= '0';
++
++ if io_sheila = '1' then
++ case cpu_a(7 downto 5) is
++ when "000" =>
++ -- 0xFE00
++ if cpu_a(4) = '0' then
++ if cpu_a(3) = '0' then
++ -- 0xFE00
++ crtc_enable <= '1';
++ else
++ -- 0xFE08
++ acia_enable <= '1';
++ end if;
++ else
++ -- 0xFE10
++ serproc_enable <= '1';
++ end if;
++ when "001" =>
++ -- 0xFE20
++ if cpu_a(4) = '0' then
++ -- 0xFE20
++ vidproc_enable <= '1';
++ else
++ -- 0xFE30
++ romsel_enable <= '1';
++ end if;
++ when "010" => sys_via_enable <= '1'; -- 0xFE40
++ when "011" => user_via_enable <= '1'; -- 0xFE60
++ when "100" => fddc_enable <= '1'; -- 0xFE80
++ when "101" => adlc_enable <= '1'; -- 0xFEA0
++ when "110" => adc_enable <= '1'; -- 0xFEC0
++ when "111" => tube_enable <= '1'; -- 0xFEE0
++ when others =>
++ null;
++ end case;
++ end if;
++ end process;
++
++ -- CPU data bus mux and interrupts
++ cpu_di <=
++ SRAM_DQ(7 downto 0) when ram_enable = '1' else
++ FL_DQ when rom_enable = '1' else
++ FL_DQ when mos_enable = '1' else
++ crtc_do when crtc_enable = '1' else
++ "00000010" when acia_enable = '1' else
++ sys_via_do when sys_via_enable = '1' else
++ user_via_do when user_via_enable = '1' else
++ (others => '0'); -- un-decoded locations are pulled down by RP1
++ debug_irq_in_n <= sys_via_irq_n and user_via_irq_n; -- route IRQ through debugger
++ --cpu_irq_n <= sys_via_irq_n and user_via_irq_n;
++
++ -- ROMs are in external flash and split into 16K slots (since this also suits other
++ -- computers that might be run on the same board).
++ -- The first 8 slots are allocated for use here, and the first 4 are decoded as
++ -- the sideways ROMs. Slot 7 is used for the MOS.
++ FL_RST_N <= reset_n;
++ FL_CE_N <= '0';
++ FL_OE_N <= '0';
++ FL_WE_N <= '1';
++ FL_ADDR(21 downto 17) <= ROM_OFFSET(7 downto 3);
++ FL_ADDR(16 downto 14) <=
++ "111" when mos_enable = '1' else
++ "0" & romsel(1 downto 0);
++ FL_ADDR(13 downto 0) <= cpu_a(13 downto 0);
++
++ -- SRAM bus
++ SRAM_UB_N <= '1';
++ SRAM_LB_N <= '0';
++ SRAM_CE_N <= '0';
++ SRAM_OE_N <= '0';
++ SRAM_DQ(15 downto 8) <= (others => '0');
++
++ -- Synchronous outputs to SRAM
++ process(clock,reset_n)
++ variable ram_write : std_logic;
++ begin
++ ram_write := ram_enable and not cpu_r_nw;
++
++ if reset_n = '0' then
++ SRAM_WE_N <= '1';
++ SRAM_DQ(7 downto 0) <= (others => 'Z');
++ elsif rising_edge(clock) then
++ -- Default to inputs
++ SRAM_DQ(7 downto 0) <= (others => 'Z');
++
++ -- Register SRAM signals to outputs (clock must be at least 2x CPU clock)
++ if vid_clken = '1' then
++ -- Fetch data from previous CPU cycle
++ SRAM_WE_N <= not ram_write;
++ SRAM_ADDR <= "00" & cpu_a(15 downto 0);
++ if ram_write = '1' then
++ SRAM_DQ(7 downto 0) <= cpu_do;
++ end if;
++ else
++ -- Fetch data from previous display cycle
++ SRAM_WE_N <= '1';
++ SRAM_ADDR <= "000" & display_a;
++ end if;
++ end if;
++ end process;
++
++ -- Address translation logic for calculation of display address
++ process(crtc_ma,crtc_ra,disp_addr_offs)
++ variable aa : unsigned(3 downto 0);
++ begin
++ if crtc_ma(12) = '0' then
++ -- No adjustment
++ aa := unsigned(crtc_ma(11 downto 8));
++ else
++ -- Address adjusted according to screen mode to compensate for
++ -- wrap at 0x8000.
++ case disp_addr_offs is
++ when "00" =>
++ -- Mode 3 - restart at 0x4000
++ aa := unsigned(crtc_ma(11 downto 8)) + 8;
++ when "01" =>
++ -- Mode 6 - restart at 0x6000
++ aa := unsigned(crtc_ma(11 downto 8)) + 12;
++ when "10" =>
++ -- Mode 0,1,2 - restart at 0x3000
++ aa := unsigned(crtc_ma(11 downto 8)) + 6;
++ when "11" =>
++ -- Mode 4,5 - restart at 0x5800
++ aa := unsigned(crtc_ma(11 downto 8)) + 11;
++ when others =>
++ null;
++ end case;
++ end if;
++
++ if crtc_ma(13) = '0' then
++ -- HI RES
++ display_a <= std_logic_vector(aa(3 downto 0)) & crtc_ma(7 downto 0) & crtc_ra(2 downto 0);
++ else
++ -- TTX VDU
++ display_a <= std_logic(aa(3)) & "1111" & crtc_ma(9 downto 0);
++ end if;
++ end process;
++
++ -- VIDPROC
++ vidproc_invert_n <= '1';
++ vidproc_disen <= crtc_de and not crtc_ra(3); -- DISEN is masked off by RA(3) for MODEs 3 and 6
++ r_in <= ttxt_r;
++ g_in <= ttxt_g;
++ b_in <= ttxt_b;
++
++ -- SAA5050
++ ttxt_glr <= not crtc_hsync;
++ ttxt_dew <= crtc_vsync;
++ ttxt_crs <= not crtc_ra(0);
++ ttxt_lose <= crtc_de;
++
++ -- CRTC drives video out (CSYNC on HSYNC output, VSYNC high)
++ VGA_HS <= not (crtc_hsync xor crtc_vsync);
++ VGA_VS <= '1';
++ VGA_R <= r_out & r_out & r_out & r_out;
++ VGA_G <= g_out & g_out & g_out & g_out;
++ VGA_B <= b_out & b_out & b_out & b_out;
++
++ -- Connections to System VIA
++ -- ADC
++ sys_via_cb1_in <= '1'; -- /EOC
++ -- CRTC
++ sys_via_ca1_in <= crtc_vsync;
++ sys_via_cb2_in <= crtc_lpstb;
++ -- Keyboard
++ sys_via_ca2_in <= keyb_int;
++ sys_via_pa_in(7) <= keyb_out;
++ sys_via_pa_in(6 downto 0) <= sys_via_pa_out(6 downto 0); -- Must loop back output pins or keyboard won't work
++ keyb_column <= sys_via_pa_out(3 downto 0);
++ keyb_row <= sys_via_pa_out(6 downto 4);
++ -- Sound
++ sound_di <= sys_via_pa_out;
++ -- Others (idle until missing bits implemented)
++ sys_via_pb_in(7 downto 4) <= (others => '1');
++
++ -- Connections to User VIA (user port is output on green LEDs)
++ user_via_ca1_in <= '1'; -- Pulled up
++ --LEDG <= user_via_pb_out;
++
++ -- MMBEEB
++ user_via_cb1_in <= user_via_pb_out(1);
++ SD_SCLK <= user_via_pb_out(1); -- SCLK
++ SD_MOSI <= user_via_pb_out(0); -- SDO
++ SD_nCS <= '0'; -- CS
++ user_via_cb2_in <= SD_MISO; -- SDI
++ user_via_pb_in <= user_via_pb_out;
++
++ -- ROM select latch
++ process(clock,reset_n)
++ begin
++ if reset_n = '0' then
++ romsel <= (others => '0');
++ elsif rising_edge(clock) then
++ if romsel_enable = '1' and cpu_r_nw = '0' then
++ romsel <= cpu_do(3 downto 0);
++ end if;
++ end if;
++ end process;
++
++ -- IC32 latch
++ sound_enable_n <= ic32(0);
++ speech_write_n <= ic32(1);
++ speech_read_n <= ic32(2);
++ keyb_enable_n <= ic32(3);
++ disp_addr_offs <= ic32(5 downto 4);
++ caps_lock_led_n <= ic32(6);
++ shift_lock_led_n <= ic32(7);
++
++ process(clock,reset_n)
++ variable bit_num : integer;
++ begin
++ bit_num := to_integer(unsigned(sys_via_pb_out(2 downto 0)));
++
++ if reset_n = '0' then
++ ic32 <= (others => '0');
++ elsif rising_edge(clock) then
++ ic32(bit_num) <= sys_via_pb_out(3);
++ end if;
++ end process;
++
++ -- Keyboard LEDs
++ LEDR(0) <= not caps_lock_led_n;
++ LEDR(1) <= not shift_lock_led_n;
++
++ -----------------
++ -- DEBUG STUFF
++ -----------------
++
++ GPIO_0(0) <= not (crtc_hsync xor crtc_vsync);
++ GPIO_0(1) <= crtc_de;
++
++end architecture;
+diff --git a/bbc_micro_de1_tb.vhd b/bbc_micro_de1_tb.vhd
+index 82012ec..9197958 100644
+--- a/bbc_micro_de1_tb.vhd
++++ b/bbc_micro_de1_tb.vhd
+@@ -1,299 +1,299 @@
+--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity bbc_micro_tb is
+-end entity;
+-
+-architecture tb of bbc_micro_tb is
+-component bbc_micro_de1 is
+-port (
+- -- Clocks
+- CLOCK_24 : in std_logic_vector(1 downto 0);
+- CLOCK_27 : in std_logic_vector(1 downto 0);
+- CLOCK_50 : in std_logic;
+- EXT_CLOCK : in std_logic;
+-
+- -- Switches
+- SW : in std_logic_vector(9 downto 0);
+- -- Buttons
+- KEY : in std_logic_vector(3 downto 0);
+-
+- -- 7 segment displays
+- HEX0 : out std_logic_vector(6 downto 0);
+- HEX1 : out std_logic_vector(6 downto 0);
+- HEX2 : out std_logic_vector(6 downto 0);
+- HEX3 : out std_logic_vector(6 downto 0);
+- -- Red LEDs
+- LEDR : out std_logic_vector(9 downto 0);
+- -- Green LEDs
+- LEDG : out std_logic_vector(7 downto 0);
+-
+- -- VGA
+- VGA_R : out std_logic_vector(3 downto 0);
+- VGA_G : out std_logic_vector(3 downto 0);
+- VGA_B : out std_logic_vector(3 downto 0);
+- VGA_HS : out std_logic;
+- VGA_VS : out std_logic;
+-
+- -- Serial
+- UART_RXD : in std_logic;
+- UART_TXD : out std_logic;
+-
+- -- PS/2 Keyboard
+- PS2_CLK : inout std_logic;
+- PS2_DAT : inout std_logic;
+-
+- -- I2C
+- I2C_SCLK : inout std_logic;
+- I2C_SDAT : inout std_logic;
+-
+- -- Audio
+- AUD_XCK : out std_logic;
+- AUD_BCLK : out std_logic;
+- AUD_ADCLRCK : out std_logic;
+- AUD_ADCDAT : in std_logic;
+- AUD_DACLRCK : out std_logic;
+- AUD_DACDAT : out std_logic;
+-
+- -- SRAM
+- SRAM_ADDR : out std_logic_vector(17 downto 0);
+- SRAM_DQ : inout std_logic_vector(15 downto 0);
+- SRAM_CE_N : out std_logic;
+- SRAM_OE_N : out std_logic;
+- SRAM_WE_N : out std_logic;
+- SRAM_UB_N : out std_logic;
+- SRAM_LB_N : out std_logic;
+-
+- -- SDRAM
+- DRAM_ADDR : out std_logic_vector(11 downto 0);
+- DRAM_DQ : inout std_logic_vector(15 downto 0);
+- DRAM_BA_0 : in std_logic;
+- DRAM_BA_1 : in std_logic;
+- DRAM_CAS_N : in std_logic;
+- DRAM_CKE : in std_logic;
+- DRAM_CLK : in std_logic;
+- DRAM_CS_N : in std_logic;
+- DRAM_LDQM : in std_logic;
+- DRAM_RAS_N : in std_logic;
+- DRAM_UDQM : in std_logic;
+- DRAM_WE_N : in std_logic;
+-
+- -- Flash
+- FL_ADDR : out std_logic_vector(21 downto 0);
+- FL_DQ : inout std_logic_vector(7 downto 0);
+- FL_RST_N : in std_logic;
+- FL_OE_N : in std_logic;
+- FL_WE_N : in std_logic;
+-
+- -- GPIO
+- GPIO_0 : inout std_logic_vector(35 downto 0);
+- GPIO_1 : inout std_logic_vector(35 downto 0)
+- );
+-end component;
+-
+-
+-signal clock_24 : std_logic_vector(1 downto 0) := "00";
+-signal clock_27 : std_logic_vector(1 downto 0) := "00";
+-signal clock_50 : std_logic := '0';
+-signal ext_clock : std_logic := '0';
+-signal sw : std_logic_vector(9 downto 0);
+-signal key : std_logic_vector(3 downto 0);
+-signal hex0 : std_logic_vector(6 downto 0);
+-signal hex1 : std_logic_vector(6 downto 0);
+-signal hex2 : std_logic_vector(6 downto 0);
+-signal hex3 : std_logic_vector(6 downto 0);
+-signal ledr : std_logic_vector(9 downto 0);
+-signal ledg : std_logic_vector(7 downto 0);
+-signal vga_r : std_logic_vector(3 downto 0);
+-signal vga_g : std_logic_vector(3 downto 0);
+-signal vga_b : std_logic_vector(3 downto 0);
+-signal vga_hs : std_logic;
+-signal vga_vs : std_logic;
+-signal uart_rxd : std_logic;
+-signal uart_txd : std_logic;
+-signal ps2_clk : std_logic;
+-signal ps2_dat : std_logic;
+-signal i2c_sclk : std_logic;
+-signal i2c_sdat : std_logic;
+-signal aud_xck : std_logic;
+-signal aud_bclk : std_logic;
+-signal aud_adclrck : std_logic;
+-signal aud_adcdat : std_logic;
+-signal aud_daclrck : std_logic;
+-signal aud_dacdat : std_logic;
+-signal sram_addr : std_logic_vector(17 downto 0);
+-signal sram_dq : std_logic_vector(15 downto 0);
+-signal sram_ce_n : std_logic;
+-signal sram_oe_n : std_logic;
+-signal sram_we_n : std_logic;
+-signal sram_ub_n : std_logic;
+-signal sram_lb_n : std_logic;
+-signal dram_addr : std_logic_vector(11 downto 0);
+-signal dram_dq : std_logic_vector(15 downto 0);
+-signal dram_ba_0 : std_logic;
+-signal dram_ba_1 : std_logic;
+-signal dram_cas_n : std_logic;
+-signal dram_cke : std_logic;
+-signal dram_clk : std_logic;
+-signal dram_cs_n : std_logic;
+-signal dram_ldqm : std_logic;
+-signal dram_ras_n : std_logic;
+-signal dram_udqm : std_logic;
+-signal dram_we_n : std_logic;
+-signal fl_addr : std_logic_vector(21 downto 0);
+-signal fl_dq : std_logic_vector(7 downto 0);
+-signal fl_rst_n : std_logic;
+-signal fl_oe_n : std_logic;
+-signal fl_we_n : std_logic;
+-signal gpio_0 : std_logic_vector(35 downto 0);
+-signal gpio_1 : std_logic_vector(35 downto 0);
+-
+-signal n_reset : std_logic := '0';
+-signal n_slow : std_logic := '1';
+-
+-type ram_t is array(0 to 65535) of std_logic_vector(15 downto 0);
+-signal ram : ram_t;
+-signal ram_a : std_logic_vector(15 downto 0);
+-begin
+-
+- uut: bbc_micro_de1 port map (
+- clock_24,
+- clock_27,
+- clock_50,
+- ext_clock,
+- sw,
+- key,
+- hex0,
+- hex1,
+- hex2,
+- hex3,
+- ledr,
+- ledg,
+- vga_r,
+- vga_g,
+- vga_b,
+- vga_hs,
+- vga_vs,
+- uart_rxd,
+- uart_txd,
+- ps2_clk,
+- ps2_dat,
+- i2c_sclk,
+- i2c_sdat,
+- aud_xck,
+- aud_bclk,
+- aud_adclrck,
+- aud_adcdat,
+- aud_daclrck,
+- aud_dacdat,
+- sram_addr,
+- sram_dq,
+- sram_ce_n,
+- sram_oe_n,
+- sram_we_n,
+- sram_ub_n,
+- sram_lb_n,
+- dram_addr,
+- dram_dq,
+- dram_ba_0,
+- dram_ba_1,
+- dram_cas_n,
+- dram_cke,
+- dram_clk,
+- dram_cs_n,
+- dram_ldqm,
+- dram_ras_n,
+- dram_udqm,
+- dram_we_n,
+- fl_addr,
+- fl_dq,
+- fl_rst_n,
+- fl_oe_n,
+- fl_we_n,
+- gpio_0,
+- gpio_1
+- );
+-
+- sw <= n_reset & n_slow & "00000101";
+- clock_50 <= not clock_50 after 10 ns;
+- clock_27(0) <= not clock_27(0) after 18.5 ns;
+- clock_27(1) <= not clock_27(1) after 18.5 ns;
+- clock_24(0) <= not clock_24(0) after 20.8 ns;
+- clock_24(1) <= not clock_24(1) after 20.8 ns;
+-
+- reset: process
+- begin
+- wait for 100 ns;
+- n_reset <= '1';
+- end process;
+-
+- sram: process(sram_addr,sram_dq,sram_ce_n,sram_oe_n,sram_we_n,sram_ub_n,sram_lb_n)
+- begin
+- if sram_ce_n = '0' then
+- if sram_oe_n = '0' and sram_we_n = '1' then
+- if sram_ub_n = '0' then
+- sram_dq(15 downto 8) <= ram(to_integer(unsigned(sram_addr(15 downto 0))))(15 downto 8);
+- else
+- sram_dq(15 downto 8) <= (others => 'Z');
+- end if;
+- if sram_lb_n = '0' then
+- sram_dq(7 downto 0) <= ram(to_integer(unsigned(sram_addr(15 downto 0))))(7 downto 0);
+- else
+- sram_dq(7 downto 0) <= (others => 'Z');
+- end if;
+- else
+- sram_dq(15 downto 0) <= (others => 'Z');
+- if sram_we_n = '0' then
+- if sram_ub_n = '0' then
+- ram(to_integer(unsigned(sram_addr(15 downto 0))))(15 downto 8) <= sram_dq(15 downto 8);
+- end if;
+- if sram_lb_n = '0' then
+- ram(to_integer(unsigned(sram_addr(15 downto 0))))(7 downto 0) <= sram_dq(7 downto 0);
+- end if;
+- end if;
+- end if;
+- else
+- sram_dq <= (others => 'Z');
+- end if;
+- end process;
+-
+-
+-end architecture;
++-- BBC Micro for Altera DE1
++--
++-- Copyright (c) 2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.NUMERIC_STD.ALL;
++
++entity bbc_micro_tb is
++end entity;
++
++architecture tb of bbc_micro_tb is
++component bbc_micro_de1 is
++port (
++ -- Clocks
++ CLOCK_24 : in std_logic_vector(1 downto 0);
++ CLOCK_27 : in std_logic_vector(1 downto 0);
++ CLOCK_50 : in std_logic;
++ EXT_CLOCK : in std_logic;
++
++ -- Switches
++ SW : in std_logic_vector(9 downto 0);
++ -- Buttons
++ KEY : in std_logic_vector(3 downto 0);
++
++ -- 7 segment displays
++ HEX0 : out std_logic_vector(6 downto 0);
++ HEX1 : out std_logic_vector(6 downto 0);
++ HEX2 : out std_logic_vector(6 downto 0);
++ HEX3 : out std_logic_vector(6 downto 0);
++ -- Red LEDs
++ LEDR : out std_logic_vector(9 downto 0);
++ -- Green LEDs
++ LEDG : out std_logic_vector(7 downto 0);
++
++ -- VGA
++ VGA_R : out std_logic_vector(3 downto 0);
++ VGA_G : out std_logic_vector(3 downto 0);
++ VGA_B : out std_logic_vector(3 downto 0);
++ VGA_HS : out std_logic;
++ VGA_VS : out std_logic;
++
++ -- Serial
++ UART_RXD : in std_logic;
++ UART_TXD : out std_logic;
++
++ -- PS/2 Keyboard
++ PS2_CLK : inout std_logic;
++ PS2_DAT : inout std_logic;
++
++ -- I2C
++ I2C_SCLK : inout std_logic;
++ I2C_SDAT : inout std_logic;
++
++ -- Audio
++ AUD_XCK : out std_logic;
++ AUD_BCLK : out std_logic;
++ AUD_ADCLRCK : out std_logic;
++ AUD_ADCDAT : in std_logic;
++ AUD_DACLRCK : out std_logic;
++ AUD_DACDAT : out std_logic;
++
++ -- SRAM
++ SRAM_ADDR : out std_logic_vector(17 downto 0);
++ SRAM_DQ : inout std_logic_vector(15 downto 0);
++ SRAM_CE_N : out std_logic;
++ SRAM_OE_N : out std_logic;
++ SRAM_WE_N : out std_logic;
++ SRAM_UB_N : out std_logic;
++ SRAM_LB_N : out std_logic;
++
++ -- SDRAM
++ DRAM_ADDR : out std_logic_vector(11 downto 0);
++ DRAM_DQ : inout std_logic_vector(15 downto 0);
++ DRAM_BA_0 : in std_logic;
++ DRAM_BA_1 : in std_logic;
++ DRAM_CAS_N : in std_logic;
++ DRAM_CKE : in std_logic;
++ DRAM_CLK : in std_logic;
++ DRAM_CS_N : in std_logic;
++ DRAM_LDQM : in std_logic;
++ DRAM_RAS_N : in std_logic;
++ DRAM_UDQM : in std_logic;
++ DRAM_WE_N : in std_logic;
++
++ -- Flash
++ FL_ADDR : out std_logic_vector(21 downto 0);
++ FL_DQ : inout std_logic_vector(7 downto 0);
++ FL_RST_N : in std_logic;
++ FL_OE_N : in std_logic;
++ FL_WE_N : in std_logic;
++
++ -- GPIO
++ GPIO_0 : inout std_logic_vector(35 downto 0);
++ GPIO_1 : inout std_logic_vector(35 downto 0)
++ );
++end component;
++
++
++signal clock_24 : std_logic_vector(1 downto 0) := "00";
++signal clock_27 : std_logic_vector(1 downto 0) := "00";
++signal clock_50 : std_logic := '0';
++signal ext_clock : std_logic := '0';
++signal sw : std_logic_vector(9 downto 0);
++signal key : std_logic_vector(3 downto 0);
++signal hex0 : std_logic_vector(6 downto 0);
++signal hex1 : std_logic_vector(6 downto 0);
++signal hex2 : std_logic_vector(6 downto 0);
++signal hex3 : std_logic_vector(6 downto 0);
++signal ledr : std_logic_vector(9 downto 0);
++signal ledg : std_logic_vector(7 downto 0);
++signal vga_r : std_logic_vector(3 downto 0);
++signal vga_g : std_logic_vector(3 downto 0);
++signal vga_b : std_logic_vector(3 downto 0);
++signal vga_hs : std_logic;
++signal vga_vs : std_logic;
++signal uart_rxd : std_logic;
++signal uart_txd : std_logic;
++signal ps2_clk : std_logic;
++signal ps2_dat : std_logic;
++signal i2c_sclk : std_logic;
++signal i2c_sdat : std_logic;
++signal aud_xck : std_logic;
++signal aud_bclk : std_logic;
++signal aud_adclrck : std_logic;
++signal aud_adcdat : std_logic;
++signal aud_daclrck : std_logic;
++signal aud_dacdat : std_logic;
++signal sram_addr : std_logic_vector(17 downto 0);
++signal sram_dq : std_logic_vector(15 downto 0);
++signal sram_ce_n : std_logic;
++signal sram_oe_n : std_logic;
++signal sram_we_n : std_logic;
++signal sram_ub_n : std_logic;
++signal sram_lb_n : std_logic;
++signal dram_addr : std_logic_vector(11 downto 0);
++signal dram_dq : std_logic_vector(15 downto 0);
++signal dram_ba_0 : std_logic;
++signal dram_ba_1 : std_logic;
++signal dram_cas_n : std_logic;
++signal dram_cke : std_logic;
++signal dram_clk : std_logic;
++signal dram_cs_n : std_logic;
++signal dram_ldqm : std_logic;
++signal dram_ras_n : std_logic;
++signal dram_udqm : std_logic;
++signal dram_we_n : std_logic;
++signal fl_addr : std_logic_vector(21 downto 0);
++signal fl_dq : std_logic_vector(7 downto 0);
++signal fl_rst_n : std_logic;
++signal fl_oe_n : std_logic;
++signal fl_we_n : std_logic;
++signal gpio_0 : std_logic_vector(35 downto 0);
++signal gpio_1 : std_logic_vector(35 downto 0);
++
++signal n_reset : std_logic := '0';
++signal n_slow : std_logic := '1';
++
++type ram_t is array(0 to 65535) of std_logic_vector(15 downto 0);
++signal ram : ram_t;
++signal ram_a : std_logic_vector(15 downto 0);
++begin
++
++ uut: bbc_micro_de1 port map (
++ clock_24,
++ clock_27,
++ clock_50,
++ ext_clock,
++ sw,
++ key,
++ hex0,
++ hex1,
++ hex2,
++ hex3,
++ ledr,
++ ledg,
++ vga_r,
++ vga_g,
++ vga_b,
++ vga_hs,
++ vga_vs,
++ uart_rxd,
++ uart_txd,
++ ps2_clk,
++ ps2_dat,
++ i2c_sclk,
++ i2c_sdat,
++ aud_xck,
++ aud_bclk,
++ aud_adclrck,
++ aud_adcdat,
++ aud_daclrck,
++ aud_dacdat,
++ sram_addr,
++ sram_dq,
++ sram_ce_n,
++ sram_oe_n,
++ sram_we_n,
++ sram_ub_n,
++ sram_lb_n,
++ dram_addr,
++ dram_dq,
++ dram_ba_0,
++ dram_ba_1,
++ dram_cas_n,
++ dram_cke,
++ dram_clk,
++ dram_cs_n,
++ dram_ldqm,
++ dram_ras_n,
++ dram_udqm,
++ dram_we_n,
++ fl_addr,
++ fl_dq,
++ fl_rst_n,
++ fl_oe_n,
++ fl_we_n,
++ gpio_0,
++ gpio_1
++ );
++
++ sw <= n_reset & n_slow & "00000101";
++ clock_50 <= not clock_50 after 10 ns;
++ clock_27(0) <= not clock_27(0) after 18.5 ns;
++ clock_27(1) <= not clock_27(1) after 18.5 ns;
++ clock_24(0) <= not clock_24(0) after 20.8 ns;
++ clock_24(1) <= not clock_24(1) after 20.8 ns;
++
++ reset: process
++ begin
++ wait for 100 ns;
++ n_reset <= '1';
++ end process;
++
++ sram: process(sram_addr,sram_dq,sram_ce_n,sram_oe_n,sram_we_n,sram_ub_n,sram_lb_n)
++ begin
++ if sram_ce_n = '0' then
++ if sram_oe_n = '0' and sram_we_n = '1' then
++ if sram_ub_n = '0' then
++ sram_dq(15 downto 8) <= ram(to_integer(unsigned(sram_addr(15 downto 0))))(15 downto 8);
++ else
++ sram_dq(15 downto 8) <= (others => 'Z');
++ end if;
++ if sram_lb_n = '0' then
++ sram_dq(7 downto 0) <= ram(to_integer(unsigned(sram_addr(15 downto 0))))(7 downto 0);
++ else
++ sram_dq(7 downto 0) <= (others => 'Z');
++ end if;
++ else
++ sram_dq(15 downto 0) <= (others => 'Z');
++ if sram_we_n = '0' then
++ if sram_ub_n = '0' then
++ ram(to_integer(unsigned(sram_addr(15 downto 0))))(15 downto 8) <= sram_dq(15 downto 8);
++ end if;
++ if sram_lb_n = '0' then
++ ram(to_integer(unsigned(sram_addr(15 downto 0))))(7 downto 0) <= sram_dq(7 downto 0);
++ end if;
++ end if;
++ end if;
++ else
++ sram_dq <= (others => 'Z');
++ end if;
++ end process;
++
++
++end architecture;
+diff --git a/debugger.vhd b/debugger.vhd
+index 1d78bd5..a7a9d7d 100644
+--- a/debugger.vhd
++++ b/debugger.vhd
+@@ -1,300 +1,300 @@
+--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+---
+--- General purpose hardware debugger
+---
+--- (C) 2011 Mike Stirling
+---
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity debugger is
+-generic (
+- -- Set this for a reasonable half flash duration relative to the
+- -- clock frequency
+- flash_divider : natural := 24
+- );
+-port (
+- CLOCK : in std_logic;
+- nRESET : in std_logic;
+- -- CPU clock enable in
+- CLKEN_IN : in std_logic;
+- -- Gated clock enable back out to CPU
+- CLKEN_OUT : out std_logic;
+- -- CPU IRQ in
+- nIRQ_IN : in std_logic;
+- -- Gated IRQ back out to CPU (no interrupts when single stepping)
+- nIRQ_OUT : out std_logic;
+-
+- -- CPU
+- A_CPU : in std_logic_vector(15 downto 0);
+- R_nW : in std_logic;
+- SYNC : in std_logic;
+-
+- -- Aux bus input for display in hex
+- AUX_BUS : in std_logic_vector(15 downto 0);
+-
+- -- Controls
+- -- RUN or HALT CPU
+- RUN : in std_logic;
+- -- Push button to single-step in HALT mode
+- nSTEP : in std_logic;
+- -- Push button to cycle display mode
+- nMODE : in std_logic;
+- -- Push button to cycle display digit in edit mode
+- nDIGIT : in std_logic;
+- -- Push button to cycle digit value in edit mode
+- nSET : in std_logic;
+-
+- -- Output to display
+- DIGIT3 : out std_logic_vector(6 downto 0);
+- DIGIT2 : out std_logic_vector(6 downto 0);
+- DIGIT1 : out std_logic_vector(6 downto 0);
+- DIGIT0 : out std_logic_vector(6 downto 0);
+-
+- LED_BREAKPOINT : out std_logic;
+- LED_WATCHPOINT : out std_logic
+- );
+-end entity;
+-
+-architecture rtl of debugger is
+-
+-component seg7 is
+-port (
+- D : in std_logic_vector(3 downto 0);
+- Q : out std_logic_vector(6 downto 0)
+-);
+-end component;
+-
+--- Current display mode
+-type mode_t is (modeAddress,modeBreak,modeWatch,modeAux);
+-signal mode : mode_t;
+--- Current edit digit
+-signal digit : unsigned(1 downto 0);
+--- For flashing selected digit
+-signal counter : unsigned(flash_divider-1 downto 0);
+-signal flash : std_logic;
+--- Selected breakpoint address (stop on instruction fetch)
+-signal breakpoint : std_logic_vector(15 downto 0);
+--- Selected watchpoint address (stop on write)
+-signal watchpoint : std_logic_vector(15 downto 0);
+--- Address of last instruction fetch
+-signal instr_addr : std_logic_vector(15 downto 0);
+--- Break flags
+-signal halt : std_logic;
+--- Set when a request to resume has been received but before
+--- the CPU has run
+-signal resuming : std_logic;
+-
+--- Display interface
+-signal a_display : std_logic_vector(15 downto 0);
+-signal d3_display : std_logic_vector(6 downto 0);
+-signal d2_display : std_logic_vector(6 downto 0);
+-signal d1_display : std_logic_vector(6 downto 0);
+-signal d0_display : std_logic_vector(6 downto 0);
+-
+--- Registered button inputs
+-signal r_step_n : std_logic;
+-signal r_mode_n : std_logic;
+-signal r_digit_n : std_logic;
+-signal r_set_n : std_logic;
+-
+-begin
+- -- Mask CPU clock enable
+- CLKEN_OUT <= CLKEN_IN and not halt;
+- -- Mask interrupt
+- nIRQ_OUT <= nIRQ_IN or not RUN;
+-
+- -- Route selected address to display
+- a_display <= instr_addr when mode = modeAddress else
+- breakpoint when mode = modeBreak else
+- watchpoint when mode = modeWatch else
+- AUX_BUS when mode = modeAux else
+- (others => '0');
+-
+- -- Generate display digits from binary
+- d3 : seg7 port map (a_display(15 downto 12),d3_display);
+- d2 : seg7 port map (a_display(11 downto 8),d2_display);
+- d1 : seg7 port map (a_display(7 downto 4),d1_display);
+- d0 : seg7 port map (a_display(3 downto 0),d0_display);
+-
+- -- Flash selected digit in edit modes
+- DIGIT3 <= d3_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "11") else "1111111";
+- DIGIT2 <= d2_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "10") else "1111111";
+- DIGIT1 <= d1_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "01") else "1111111";
+- DIGIT0 <= d0_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "00") else "1111111";
+-
+- -- Show mode on LEDs
+- LED_BREAKPOINT <= '1' when mode = modeBreak or mode = modeAux else '0';
+- LED_WATCHPOINT <= '1' when mode = modeWatch or mode = modeAux else '0';
+-
+- -- Flash counter
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- counter <= (others => '0');
+- flash <= '0';
+- elsif rising_edge(CLOCK) then
+- counter <= counter + 1;
+- if counter = 0 then
+- flash <= not flash;
+- end if;
+- end if;
+- end process;
+-
+- -- Register buttons, select input mode and digit
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- r_mode_n <= '1';
+- r_digit_n <= '1';
+- r_set_n <= '1';
+- mode <= modeAddress;
+- digit <= (others => '0');
+- elsif rising_edge(CLOCK) then
+- -- Register buttons
+- r_mode_n <= nMODE;
+- r_digit_n <= nDIGIT;
+- r_set_n <= nSET;
+-
+- if r_mode_n = '1' and nMODE = '0' then
+- -- Increment mode
+- if mode = modeAddress then
+- mode <= modeBreak;
+- elsif mode = modeBreak then
+- mode <= modeWatch;
+- elsif mode = modeWatch then
+- mode <= modeAux;
+- else
+- mode <= modeAddress;
+- end if;
+- end if;
+- if r_digit_n = '1' and nDIGIT = '0' then
+- -- Increment digit
+- digit <= digit + 1;
+- end if;
+- end if;
+- end process;
+-
+- -- Set watchpoint address
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- watchpoint <= (others => '1');
+- elsif rising_edge(CLOCK) and mode = modeWatch then
+- if r_set_n = '1' and nSET = '0' then
+- -- Increment selected digit on each button press
+- case digit is
+- when "00" => watchpoint(3 downto 0) <= std_logic_vector(unsigned(watchpoint(3 downto 0)) + 1);
+- when "01" => watchpoint(7 downto 4) <= std_logic_vector(unsigned(watchpoint(7 downto 4)) + 1);
+- when "10" => watchpoint(11 downto 8) <= std_logic_vector(unsigned(watchpoint(11 downto 8)) + 1);
+- when "11" => watchpoint(15 downto 12) <= std_logic_vector(unsigned(watchpoint(15 downto 12)) + 1);
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end process;
+-
+- -- Set breakpoint address
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- breakpoint <= (others => '1');
+- elsif rising_edge(CLOCK) and mode = modeBreak then
+- if r_set_n = '1' and nSET = '0' then
+- -- Increment selected digit on each button press
+- case digit is
+- when "00" => breakpoint(3 downto 0) <= std_logic_vector(unsigned(breakpoint(3 downto 0)) + 1);
+- when "01" => breakpoint(7 downto 4) <= std_logic_vector(unsigned(breakpoint(7 downto 4)) + 1);
+- when "10" => breakpoint(11 downto 8) <= std_logic_vector(unsigned(breakpoint(11 downto 8)) + 1);
+- when "11" => breakpoint(15 downto 12) <= std_logic_vector(unsigned(breakpoint(15 downto 12)) + 1);
+-
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end process;
+-
+- -- CPU control logic
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- r_step_n <= '1';
+- halt <= '0';
+- resuming <= '0';
+- instr_addr <= (others => '0');
+- elsif rising_edge(CLOCK) then
+- -- Register single-step button
+- r_step_n <= nSTEP;
+-
+- -- Once the CPU has run we can trigger a new halt
+- if CLKEN_IN = '1' then
+- resuming <= '0';
+- end if;
+-
+- if SYNC = '1' then
+- -- Latch address of instruction fetch
+- instr_addr <= A_CPU;
+- end if;
+-
+- -- Check for halt conditions if we are not resuming from a previous halt
+- if resuming = '0' then
+- if RUN = '0' and SYNC = '1' then
+- -- If not in RUN mode then halt on any instruction fetch
+- -- (single-step)
+- halt <= '1';
+- end if;
+- if A_CPU = breakpoint and SYNC = '1' then
+- -- Halt CPU when instruction fetched from breakpoint address
+- halt <= '1';
+- end if;
+- if A_CPU = watchpoint and SYNC = '0' and R_nW = '0' then
+- -- Halt CPU when data write to watchpoint address
+- halt <= '1';
+- end if;
+- end if;
+-
+- -- Resume or single step when user presses "STEP" button
+- if r_step_n = '1' and nSTEP = '0' then
+- resuming <= '1';
+- halt <= '0';
+- end if;
+- end if;
+- end process;
+-end architecture;
++-- BBC Micro for Altera DE1
++--
++-- Copyright (c) 2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++--
++-- General purpose hardware debugger
++--
++-- (C) 2011 Mike Stirling
++--
++
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.NUMERIC_STD.ALL;
++
++entity debugger is
++generic (
++ -- Set this for a reasonable half flash duration relative to the
++ -- clock frequency
++ flash_divider : natural := 24
++ );
++port (
++ CLOCK : in std_logic;
++ nRESET : in std_logic;
++ -- CPU clock enable in
++ CLKEN_IN : in std_logic;
++ -- Gated clock enable back out to CPU
++ CLKEN_OUT : out std_logic;
++ -- CPU IRQ in
++ nIRQ_IN : in std_logic;
++ -- Gated IRQ back out to CPU (no interrupts when single stepping)
++ nIRQ_OUT : out std_logic;
++
++ -- CPU
++ A_CPU : in std_logic_vector(15 downto 0);
++ R_nW : in std_logic;
++ SYNC : in std_logic;
++
++ -- Aux bus input for display in hex
++ AUX_BUS : in std_logic_vector(15 downto 0);
++
++ -- Controls
++ -- RUN or HALT CPU
++ RUN : in std_logic;
++ -- Push button to single-step in HALT mode
++ nSTEP : in std_logic;
++ -- Push button to cycle display mode
++ nMODE : in std_logic;
++ -- Push button to cycle display digit in edit mode
++ nDIGIT : in std_logic;
++ -- Push button to cycle digit value in edit mode
++ nSET : in std_logic;
++
++ -- Output to display
++ DIGIT3 : out std_logic_vector(6 downto 0);
++ DIGIT2 : out std_logic_vector(6 downto 0);
++ DIGIT1 : out std_logic_vector(6 downto 0);
++ DIGIT0 : out std_logic_vector(6 downto 0);
++
++ LED_BREAKPOINT : out std_logic;
++ LED_WATCHPOINT : out std_logic
++ );
++end entity;
++
++architecture rtl of debugger is
++
++component seg7 is
++port (
++ D : in std_logic_vector(3 downto 0);
++ Q : out std_logic_vector(6 downto 0)
++);
++end component;
++
++-- Current display mode
++type mode_t is (modeAddress,modeBreak,modeWatch,modeAux);
++signal mode : mode_t;
++-- Current edit digit
++signal digit : unsigned(1 downto 0);
++-- For flashing selected digit
++signal counter : unsigned(flash_divider-1 downto 0);
++signal flash : std_logic;
++-- Selected breakpoint address (stop on instruction fetch)
++signal breakpoint : std_logic_vector(15 downto 0);
++-- Selected watchpoint address (stop on write)
++signal watchpoint : std_logic_vector(15 downto 0);
++-- Address of last instruction fetch
++signal instr_addr : std_logic_vector(15 downto 0);
++-- Break flags
++signal halt : std_logic;
++-- Set when a request to resume has been received but before
++-- the CPU has run
++signal resuming : std_logic;
++
++-- Display interface
++signal a_display : std_logic_vector(15 downto 0);
++signal d3_display : std_logic_vector(6 downto 0);
++signal d2_display : std_logic_vector(6 downto 0);
++signal d1_display : std_logic_vector(6 downto 0);
++signal d0_display : std_logic_vector(6 downto 0);
++
++-- Registered button inputs
++signal r_step_n : std_logic;
++signal r_mode_n : std_logic;
++signal r_digit_n : std_logic;
++signal r_set_n : std_logic;
++
++begin
++ -- Mask CPU clock enable
++ CLKEN_OUT <= CLKEN_IN and not halt;
++ -- Mask interrupt
++ nIRQ_OUT <= nIRQ_IN or not RUN;
++
++ -- Route selected address to display
++ a_display <= instr_addr when mode = modeAddress else
++ breakpoint when mode = modeBreak else
++ watchpoint when mode = modeWatch else
++ AUX_BUS when mode = modeAux else
++ (others => '0');
++
++ -- Generate display digits from binary
++ d3 : seg7 port map (a_display(15 downto 12),d3_display);
++ d2 : seg7 port map (a_display(11 downto 8),d2_display);
++ d1 : seg7 port map (a_display(7 downto 4),d1_display);
++ d0 : seg7 port map (a_display(3 downto 0),d0_display);
++
++ -- Flash selected digit in edit modes
++ DIGIT3 <= d3_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "11") else "1111111";
++ DIGIT2 <= d2_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "10") else "1111111";
++ DIGIT1 <= d1_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "01") else "1111111";
++ DIGIT0 <= d0_display when (mode = modeAddress or mode = modeAux or flash = '1' or digit /= "00") else "1111111";
++
++ -- Show mode on LEDs
++ LED_BREAKPOINT <= '1' when mode = modeBreak or mode = modeAux else '0';
++ LED_WATCHPOINT <= '1' when mode = modeWatch or mode = modeAux else '0';
++
++ -- Flash counter
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ counter <= (others => '0');
++ flash <= '0';
++ elsif rising_edge(CLOCK) then
++ counter <= counter + 1;
++ if counter = 0 then
++ flash <= not flash;
++ end if;
++ end if;
++ end process;
++
++ -- Register buttons, select input mode and digit
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ r_mode_n <= '1';
++ r_digit_n <= '1';
++ r_set_n <= '1';
++ mode <= modeAddress;
++ digit <= (others => '0');
++ elsif rising_edge(CLOCK) then
++ -- Register buttons
++ r_mode_n <= nMODE;
++ r_digit_n <= nDIGIT;
++ r_set_n <= nSET;
++
++ if r_mode_n = '1' and nMODE = '0' then
++ -- Increment mode
++ if mode = modeAddress then
++ mode <= modeBreak;
++ elsif mode = modeBreak then
++ mode <= modeWatch;
++ elsif mode = modeWatch then
++ mode <= modeAux;
++ else
++ mode <= modeAddress;
++ end if;
++ end if;
++ if r_digit_n = '1' and nDIGIT = '0' then
++ -- Increment digit
++ digit <= digit + 1;
++ end if;
++ end if;
++ end process;
++
++ -- Set watchpoint address
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ watchpoint <= (others => '1');
++ elsif rising_edge(CLOCK) and mode = modeWatch then
++ if r_set_n = '1' and nSET = '0' then
++ -- Increment selected digit on each button press
++ case digit is
++ when "00" => watchpoint(3 downto 0) <= std_logic_vector(unsigned(watchpoint(3 downto 0)) + 1);
++ when "01" => watchpoint(7 downto 4) <= std_logic_vector(unsigned(watchpoint(7 downto 4)) + 1);
++ when "10" => watchpoint(11 downto 8) <= std_logic_vector(unsigned(watchpoint(11 downto 8)) + 1);
++ when "11" => watchpoint(15 downto 12) <= std_logic_vector(unsigned(watchpoint(15 downto 12)) + 1);
++ when others => null;
++ end case;
++ end if;
++ end if;
++ end process;
++
++ -- Set breakpoint address
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ breakpoint <= (others => '1');
++ elsif rising_edge(CLOCK) and mode = modeBreak then
++ if r_set_n = '1' and nSET = '0' then
++ -- Increment selected digit on each button press
++ case digit is
++ when "00" => breakpoint(3 downto 0) <= std_logic_vector(unsigned(breakpoint(3 downto 0)) + 1);
++ when "01" => breakpoint(7 downto 4) <= std_logic_vector(unsigned(breakpoint(7 downto 4)) + 1);
++ when "10" => breakpoint(11 downto 8) <= std_logic_vector(unsigned(breakpoint(11 downto 8)) + 1);
++ when "11" => breakpoint(15 downto 12) <= std_logic_vector(unsigned(breakpoint(15 downto 12)) + 1);
++
++ when others => null;
++ end case;
++ end if;
++ end if;
++ end process;
++
++ -- CPU control logic
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ r_step_n <= '1';
++ halt <= '0';
++ resuming <= '0';
++ instr_addr <= (others => '0');
++ elsif rising_edge(CLOCK) then
++ -- Register single-step button
++ r_step_n <= nSTEP;
++
++ -- Once the CPU has run we can trigger a new halt
++ if CLKEN_IN = '1' then
++ resuming <= '0';
++ end if;
++
++ if SYNC = '1' then
++ -- Latch address of instruction fetch
++ instr_addr <= A_CPU;
++ end if;
++
++ -- Check for halt conditions if we are not resuming from a previous halt
++ if resuming = '0' then
++ if RUN = '0' and SYNC = '1' then
++ -- If not in RUN mode then halt on any instruction fetch
++ -- (single-step)
++ halt <= '1';
++ end if;
++ if A_CPU = breakpoint and SYNC = '1' then
++ -- Halt CPU when instruction fetched from breakpoint address
++ halt <= '1';
++ end if;
++ if A_CPU = watchpoint and SYNC = '0' and R_nW = '0' then
++ -- Halt CPU when data write to watchpoint address
++ halt <= '1';
++ end if;
++ end if;
++
++ -- Resume or single step when user presses "STEP" button
++ if r_step_n = '1' and nSTEP = '0' then
++ resuming <= '1';
++ halt <= '0';
++ end if;
++ end if;
++ end process;
++end architecture;
+diff --git a/i2c_loader.vhd b/i2c_loader.vhd
+index 35da643..61bdd22 100644
+--- a/i2c_loader.vhd
++++ b/i2c_loader.vhd
+@@ -1,304 +1,304 @@
+--- ZX Spectrum for Altera DE1
+---
+--- Copyright (c) 2009-2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.STD_LOGIC_ARITH.ALL;
+-use IEEE.STD_LOGIC_UNSIGNED.ALL;
+-use IEEE.STD_LOGIC_MISC.ALL; -- for AND_REDUCE
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity i2c_loader is
+-generic (
+- -- Address of slave to be loaded
+- device_address : integer := 16#1a#;
+- -- Number of retries to allow before stopping
+- num_retries : integer := 0;
+- -- Length of clock divider in bits. Resulting bus frequency is
+- -- CLK/2^(log2_divider + 2)
+- log2_divider : integer := 6
+-);
+-
+-port (
+- CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- I2C_SCL : inout std_logic;
+- I2C_SDA : inout std_logic;
+-
+- IS_DONE : out std_logic;
+- IS_ERROR : out std_logic
+- );
+-end i2c_loader;
+-
+-architecture i2c_loader_arch of i2c_loader is
+-type regs is array(0 to 19) of std_logic_vector(7 downto 0);
+-constant init_regs : regs := (
+- -- Left line in, 0dB, unmute
+- X"00", X"17",
+- -- Right line in, 0dB, unmute
+- X"02", X"17",
+- -- Left headphone out, 0dB
+- X"04", X"79",
+- -- Right headphone out, 0dB
+- X"06", X"79",
+- -- Audio path, DAC enabled, Line in, Bypass off, mic unmuted
+- X"08", X"10",
+- -- Digital path, Unmute, HP filter enabled
+- X"0A", X"00",
+- -- Power down mic, clkout and xtal osc
+- X"0C", X"62",
+- -- Format 16-bit I2S, no bit inversion or phase changes
+- X"0E", X"02",
+- -- Sampling control, 8 kHz USB mode (MCLK = 250fs * 6)
+- X"10", X"0D",
+- -- Activate
+- X"12", X"01"
+- );
+--- Number of bursts (i.e. total number of registers)
+-constant burst_length : positive := 2;
+--- Number of bytes to transfer per burst
+-constant num_bursts : positive := (init_regs'length / burst_length);
+-
+-type state_t is (Idle, Start, Data, Ack, Stop, Pause, Done);
+-signal state : state_t;
+-signal phase : std_logic_vector(1 downto 0);
+-subtype nbit_t is integer range 0 to 7;
+-signal nbit : nbit_t;
+-subtype nbyte_t is integer range 0 to burst_length; -- +1 for address byte
+-signal nbyte : nbyte_t;
+-subtype thisbyte_t is integer range 0 to init_regs'length; -- +1 for "done"
+-signal thisbyte : thisbyte_t;
+-subtype retries_t is integer range 0 to num_retries;
+-signal retries : retries_t;
+-
+-signal clken : std_logic;
+-signal divider : std_logic_vector(log2_divider-1 downto 0);
+-signal shiftreg : std_logic_vector(7 downto 0);
+-signal scl_out : std_logic;
+-signal sda_out : std_logic;
+-signal nak : std_logic;
+-begin
+- -- Create open-drain outputs for I2C bus
+- I2C_SCL <= '0' when scl_out = '0' else 'Z';
+- I2C_SDA <= '0' when sda_out = '0' else 'Z';
+- -- Status outputs are driven both ways
+- IS_DONE <= '1' when state = Done else '0';
+- IS_ERROR <= nak;
+-
+- -- Generate clock enable for desired bus speed
+- clken <= AND_REDUCE(divider);
+- process(nRESET,CLK)
+- begin
+- if nRESET = '0' then
+- divider <= (others => '0');
+- elsif falling_edge(CLK) then
+- divider <= divider + '1';
+- end if;
+- end process;
+-
+- -- The I2C loader process
+- process(nRESET,CLK)
+- begin
+- if nRESET = '0' then
+- scl_out <= '1';
+- sda_out <= '1';
+- state <= Idle;
+- phase <= "00";
+- nbit <= 0;
+- nbyte <= 0;
+- thisbyte <= 0;
+- shiftreg <= (others => '0');
+- nak <= '0'; -- No error
+- retries <= num_retries;
+- elsif rising_edge(CLK) and clken = '1' then
+- -- Next phase by default
+- phase <= phase + 1;
+-
+- -- STATE: IDLE
+- if state = Idle then
+- -- Start loading the device registers straight away
+- -- A 'GO' bit could be polled here if required
+- state <= Start;
+- phase <= "00";
+- scl_out <= '1';
+- sda_out <= '1';
+-
+- -- STATE: START
+- elsif state = Start then
+- -- Generate START condition
+- case phase is
+- when "00" =>
+- -- Drop SDA first
+- sda_out <= '0';
+- when "10" =>
+- -- Then drop SCL
+- scl_out <= '0';
+- when "11" =>
+- -- Advance to next state
+- -- Shift register loaded with device slave address
+- state <= Data;
+- nbit <= 7;
+- shiftreg <= std_logic_vector(to_unsigned(device_address,7)) & '0'; -- writing
+- nbyte <= burst_length;
+- when others =>
+- null;
+- end case;
+-
+- -- STATE: DATA
+- elsif state = Data then
+- -- Generate data
+- case phase is
+- when "00" =>
+- -- Drop SCL
+- scl_out <= '0';
+- when "01" =>
+- -- Output data and shift (MSb first)
+- sda_out <= shiftreg(7);
+- shiftreg <= shiftreg(6 downto 0) & '0';
+- when "10" =>
+- -- Raise SCL
+- scl_out <= '1';
+- when "11" =>
+- -- Next bit or advance to next state when done
+- if nbit = 0 then
+- state <= Ack;
+- else
+- nbit <= nbit - 1;
+- end if;
+- when others =>
+- null;
+- end case;
+-
+- -- STATE: ACK
+- elsif state = Ack then
+- -- Generate ACK clock and check for error condition
+- case phase is
+- when "00" =>
+- -- Drop SCL
+- scl_out <= '0';
+- when "01" =>
+- -- Float data
+- sda_out <= '1';
+- when "10" =>
+- -- Sample ack bit
+- nak <= I2C_SDA;
+- if I2C_SDA = '1' then
+- -- Error
+- nbyte <= 0; -- Close this burst and skip remaining registers
+- thisbyte <= init_regs'length;
+- else
+- -- Hold ACK to avoid spurious stops - this seems to fix a
+- -- problem with the Wolfson codec which releases the ACK
+- -- right on the falling edge of the clock pulse. It looks like
+- -- the device interprets this is a STOP condition and then fails
+- -- to acknowledge the next byte. We can avoid this by holding the
+- -- ACK condition for a little longer.
+- sda_out <= '0';
+- end if;
+- -- Raise SCL
+- scl_out <= '1';
+- when "11" =>
+- -- Advance to next state
+- if nbyte = 0 then
+- -- No more bytes in this burst - generate a STOP
+- state <= Stop;
+- else
+- -- Generate next byte
+- state <= Data;
+- nbit <= 7;
+- shiftreg <= init_regs(thisbyte);
+- nbyte <= nbyte - 1;
+- thisbyte <= thisbyte + 1;
+- end if;
+- when others =>
+- null;
+- end case;
+-
+- -- STATE: STOP
+- elsif state = Stop then
+- -- Generate STOP condition
+- case phase is
+- when "00" =>
+- -- Drop SCL first
+- scl_out <= '0';
+- when "01" =>
+- -- Drop SDA
+- sda_out <= '0';
+- when "10" =>
+- -- Raise SCL
+- scl_out <= '1';
+- when "11" =>
+- if thisbyte = init_regs'length then
+- -- All registers done, advance to finished state. This will
+- -- bring SDA high while SCL is still high, completing the STOP
+- -- condition
+- state <= Done;
+- else
+- -- Load the next register after a short delay
+- state <= Pause;
+- end if;
+- when others =>
+- null;
+- end case;
+-
+- -- STATE: PAUSE
+- elsif state = Pause then
+- -- Delay for one cycle of 'phase' then start the next burst
+- scl_out <= '1';
+- sda_out <= '1';
+- if phase = "11" then
+- state <= Start;
+- end if;
+-
+- -- STATE: DONE
+- else
+- -- Finished
+- scl_out <= '1';
+- sda_out <= '1';
+-
+- if nak = '1' and retries > 0 then
+- -- We can retry in the event of a NAK in case the
+- -- slave got out of sync for some reason
+- retries <= retries - 1;
+- state <= Idle;
+- end if;
+- end if;
+- end if;
+- end process;
+-end i2c_loader_arch;
+-
++-- ZX Spectrum for Altera DE1
++--
++-- Copyright (c) 2009-2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.STD_LOGIC_ARITH.ALL;
++use IEEE.STD_LOGIC_UNSIGNED.ALL;
++use IEEE.STD_LOGIC_MISC.ALL; -- for AND_REDUCE
++use IEEE.NUMERIC_STD.ALL;
++
++entity i2c_loader is
++generic (
++ -- Address of slave to be loaded
++ device_address : integer := 16#1a#;
++ -- Number of retries to allow before stopping
++ num_retries : integer := 0;
++ -- Length of clock divider in bits. Resulting bus frequency is
++ -- CLK/2^(log2_divider + 2)
++ log2_divider : integer := 6
++);
++
++port (
++ CLK : in std_logic;
++ nRESET : in std_logic;
++
++ I2C_SCL : inout std_logic;
++ I2C_SDA : inout std_logic;
++
++ IS_DONE : out std_logic;
++ IS_ERROR : out std_logic
++ );
++end i2c_loader;
++
++architecture i2c_loader_arch of i2c_loader is
++type regs is array(0 to 19) of std_logic_vector(7 downto 0);
++constant init_regs : regs := (
++ -- Left line in, 0dB, unmute
++ X"00", X"17",
++ -- Right line in, 0dB, unmute
++ X"02", X"17",
++ -- Left headphone out, 0dB
++ X"04", X"79",
++ -- Right headphone out, 0dB
++ X"06", X"79",
++ -- Audio path, DAC enabled, Line in, Bypass off, mic unmuted
++ X"08", X"10",
++ -- Digital path, Unmute, HP filter enabled
++ X"0A", X"00",
++ -- Power down mic, clkout and xtal osc
++ X"0C", X"62",
++ -- Format 16-bit I2S, no bit inversion or phase changes
++ X"0E", X"02",
++ -- Sampling control, 8 kHz USB mode (MCLK = 250fs * 6)
++ X"10", X"0D",
++ -- Activate
++ X"12", X"01"
++ );
++-- Number of bursts (i.e. total number of registers)
++constant burst_length : positive := 2;
++-- Number of bytes to transfer per burst
++constant num_bursts : positive := (init_regs'length / burst_length);
++
++type state_t is (Idle, Start, Data, Ack, Stop, Pause, Done);
++signal state : state_t;
++signal phase : std_logic_vector(1 downto 0);
++subtype nbit_t is integer range 0 to 7;
++signal nbit : nbit_t;
++subtype nbyte_t is integer range 0 to burst_length; -- +1 for address byte
++signal nbyte : nbyte_t;
++subtype thisbyte_t is integer range 0 to init_regs'length; -- +1 for "done"
++signal thisbyte : thisbyte_t;
++subtype retries_t is integer range 0 to num_retries;
++signal retries : retries_t;
++
++signal clken : std_logic;
++signal divider : std_logic_vector(log2_divider-1 downto 0);
++signal shiftreg : std_logic_vector(7 downto 0);
++signal scl_out : std_logic;
++signal sda_out : std_logic;
++signal nak : std_logic;
++begin
++ -- Create open-drain outputs for I2C bus
++ I2C_SCL <= '0' when scl_out = '0' else 'Z';
++ I2C_SDA <= '0' when sda_out = '0' else 'Z';
++ -- Status outputs are driven both ways
++ IS_DONE <= '1' when state = Done else '0';
++ IS_ERROR <= nak;
++
++ -- Generate clock enable for desired bus speed
++ clken <= AND_REDUCE(divider);
++ process(nRESET,CLK)
++ begin
++ if nRESET = '0' then
++ divider <= (others => '0');
++ elsif falling_edge(CLK) then
++ divider <= divider + '1';
++ end if;
++ end process;
++
++ -- The I2C loader process
++ process(nRESET,CLK)
++ begin
++ if nRESET = '0' then
++ scl_out <= '1';
++ sda_out <= '1';
++ state <= Idle;
++ phase <= "00";
++ nbit <= 0;
++ nbyte <= 0;
++ thisbyte <= 0;
++ shiftreg <= (others => '0');
++ nak <= '0'; -- No error
++ retries <= num_retries;
++ elsif rising_edge(CLK) and clken = '1' then
++ -- Next phase by default
++ phase <= phase + 1;
++
++ -- STATE: IDLE
++ if state = Idle then
++ -- Start loading the device registers straight away
++ -- A 'GO' bit could be polled here if required
++ state <= Start;
++ phase <= "00";
++ scl_out <= '1';
++ sda_out <= '1';
++
++ -- STATE: START
++ elsif state = Start then
++ -- Generate START condition
++ case phase is
++ when "00" =>
++ -- Drop SDA first
++ sda_out <= '0';
++ when "10" =>
++ -- Then drop SCL
++ scl_out <= '0';
++ when "11" =>
++ -- Advance to next state
++ -- Shift register loaded with device slave address
++ state <= Data;
++ nbit <= 7;
++ shiftreg <= std_logic_vector(to_unsigned(device_address,7)) & '0'; -- writing
++ nbyte <= burst_length;
++ when others =>
++ null;
++ end case;
++
++ -- STATE: DATA
++ elsif state = Data then
++ -- Generate data
++ case phase is
++ when "00" =>
++ -- Drop SCL
++ scl_out <= '0';
++ when "01" =>
++ -- Output data and shift (MSb first)
++ sda_out <= shiftreg(7);
++ shiftreg <= shiftreg(6 downto 0) & '0';
++ when "10" =>
++ -- Raise SCL
++ scl_out <= '1';
++ when "11" =>
++ -- Next bit or advance to next state when done
++ if nbit = 0 then
++ state <= Ack;
++ else
++ nbit <= nbit - 1;
++ end if;
++ when others =>
++ null;
++ end case;
++
++ -- STATE: ACK
++ elsif state = Ack then
++ -- Generate ACK clock and check for error condition
++ case phase is
++ when "00" =>
++ -- Drop SCL
++ scl_out <= '0';
++ when "01" =>
++ -- Float data
++ sda_out <= '1';
++ when "10" =>
++ -- Sample ack bit
++ nak <= I2C_SDA;
++ if I2C_SDA = '1' then
++ -- Error
++ nbyte <= 0; -- Close this burst and skip remaining registers
++ thisbyte <= init_regs'length;
++ else
++ -- Hold ACK to avoid spurious stops - this seems to fix a
++ -- problem with the Wolfson codec which releases the ACK
++ -- right on the falling edge of the clock pulse. It looks like
++ -- the device interprets this is a STOP condition and then fails
++ -- to acknowledge the next byte. We can avoid this by holding the
++ -- ACK condition for a little longer.
++ sda_out <= '0';
++ end if;
++ -- Raise SCL
++ scl_out <= '1';
++ when "11" =>
++ -- Advance to next state
++ if nbyte = 0 then
++ -- No more bytes in this burst - generate a STOP
++ state <= Stop;
++ else
++ -- Generate next byte
++ state <= Data;
++ nbit <= 7;
++ shiftreg <= init_regs(thisbyte);
++ nbyte <= nbyte - 1;
++ thisbyte <= thisbyte + 1;
++ end if;
++ when others =>
++ null;
++ end case;
++
++ -- STATE: STOP
++ elsif state = Stop then
++ -- Generate STOP condition
++ case phase is
++ when "00" =>
++ -- Drop SCL first
++ scl_out <= '0';
++ when "01" =>
++ -- Drop SDA
++ sda_out <= '0';
++ when "10" =>
++ -- Raise SCL
++ scl_out <= '1';
++ when "11" =>
++ if thisbyte = init_regs'length then
++ -- All registers done, advance to finished state. This will
++ -- bring SDA high while SCL is still high, completing the STOP
++ -- condition
++ state <= Done;
++ else
++ -- Load the next register after a short delay
++ state <= Pause;
++ end if;
++ when others =>
++ null;
++ end case;
++
++ -- STATE: PAUSE
++ elsif state = Pause then
++ -- Delay for one cycle of 'phase' then start the next burst
++ scl_out <= '1';
++ sda_out <= '1';
++ if phase = "11" then
++ state <= Start;
++ end if;
++
++ -- STATE: DONE
++ else
++ -- Finished
++ scl_out <= '1';
++ sda_out <= '1';
++
++ if nak = '1' and retries > 0 then
++ -- We can retry in the event of a NAK in case the
++ -- slave got out of sync for some reason
++ retries <= retries - 1;
++ state <= Idle;
++ end if;
++ end if;
++ end if;
++ end process;
++end i2c_loader_arch;
++
+diff --git a/i2s_intf.vhd b/i2s_intf.vhd
+index e15ce2c..49b6efb 100644
+--- a/i2s_intf.vhd
++++ b/i2s_intf.vhd
+@@ -1,37 +1,37 @@
+ -- ZX Spectrum for Altera DE1
+ --
+--- Copyright (c) 2009-2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- Copyright (c) 2009-2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ -- POSSIBILITY OF SUCH DAMAGE.
+ --
+
+diff --git a/keyboard.vhd b/keyboard.vhd
+index c0b8603..cba4054 100644
+--- a/keyboard.vhd
++++ b/keyboard.vhd
+@@ -1,294 +1,294 @@
+--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- BBC keyboard implementation with interface to PS/2
+---
+--- (C) 2011 Mike Stirling
+---
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity keyboard is
+-port (
+- CLOCK : in std_logic;
+- nRESET : in std_logic;
+- CLKEN_1MHZ : in std_logic;
+-
+- -- PS/2 interface
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
+-
+- -- If 1 then column is incremented automatically at
+- -- 1 MHz rate
+- AUTOSCAN : in std_logic;
+-
+- COLUMN : in std_logic_vector(3 downto 0);
+- ROW : in std_logic_vector(2 downto 0);
+-
+- -- 1 when currently selected key is down (AUTOSCAN disabled)
+- KEYPRESS : out std_logic;
+- -- 1 when any key is down (except row 0)
+- INT : out std_logic;
+- -- BREAK key output - 1 when pressed
+- BREAK_OUT : out std_logic;
+-
+- -- DIP switch inputs
+- DIP_SWITCH : in std_logic_vector(7 downto 0)
+- );
+-end entity;
+-
+-architecture rtl of keyboard is
+-
+--- PS/2 interface
+-component ps2_intf is
+-generic (filter_length : positive := 8);
+-port(
+- CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- -- PS/2 interface (could be bi-dir)
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
+-
+- -- Byte-wide data interface - only valid for one clock
+- -- so must be latched externally if required
+- DATA : out std_logic_vector(7 downto 0);
+- VALID : out std_logic;
+- ERROR : out std_logic
+- );
+-end component;
+-
+--- Interface to PS/2 block
+-signal keyb_data : std_logic_vector(7 downto 0);
+-signal keyb_valid : std_logic;
+-signal keyb_error : std_logic;
+-
+--- Internal signals
+-type key_matrix is array(0 to 15) of std_logic_vector(7 downto 0);
+-signal keys : key_matrix;
+-signal col : unsigned(3 downto 0);
+-signal release : std_logic;
+-signal extended : std_logic;
+-begin
+-
+- ps2 : ps2_intf port map (
+- CLOCK, nRESET,
+- PS2_CLK, PS2_DATA,
+- keyb_data, keyb_valid, keyb_error
+- );
+-
+- -- Column counts automatically when AUTOSCAN is enabled, otherwise
+- -- value is loaded from external input
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- col <= (others => '0');
+- elsif rising_edge(CLOCK) then
+- if AUTOSCAN = '0' then
+- -- If autoscan disabled then transfer current COLUMN to counter
+- -- immediately (don't wait for next 1 MHz cycle)
+- col <= unsigned(COLUMN);
+- elsif CLKEN_1MHZ = '1' then
+- -- Otherwise increment the counter once per 1 MHz tick
+- col <= col + 1;
+- end if;
+- end if;
+- end process;
+-
+- -- Generate interrupt if any key in currently scanned column is pressed
+- -- (apart from in row 0). Output selected key status if autoscan disabled.
+- process(keys,col,ROW,AUTOSCAN)
+- variable k : std_logic_vector(7 downto 0);
+- begin
+- -- Shortcut to current key column
+- k := keys(to_integer(col));
+-
+- -- Interrupt if any key pressed in rows 1 to 7.
+- INT <= k(7) or k(6) or k(5) or k(4) or k(3) or k(2) or k(1);
+-
+- -- Determine which key is pressed
+- -- Inhibit output during auto-scan
+- if AUTOSCAN = '0' then
+- KEYPRESS <= k(to_integer(unsigned(ROW)));
+- else
+- KEYPRESS <= '0';
+- end if;
+- end process;
+-
+- -- Decode PS/2 data
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- release <= '0';
+- extended <= '0';
+-
+- BREAK_OUT <= '0';
+-
+- keys(0) <= (others => '0');
+- keys(1) <= (others => '0');
+- keys(2) <= (others => '0');
+- keys(3) <= (others => '0');
+- keys(4) <= (others => '0');
+- keys(5) <= (others => '0');
+- keys(6) <= (others => '0');
+- keys(7) <= (others => '0');
+- keys(8) <= (others => '0');
+- keys(9) <= (others => '0');
+- -- These non-existent rows are used in the BBC master
+- keys(10) <= (others => '0');
+- keys(11) <= (others => '0');
+- keys(12) <= (others => '0');
+- keys(13) <= (others => '0');
+- keys(14) <= (others => '0');
+- keys(15) <= (others => '0');
+- elsif rising_edge(CLOCK) then
+- -- Copy DIP switches through to row 0
+- keys(2)(0) <= DIP_SWITCH(7);
+- keys(3)(0) <= DIP_SWITCH(6);
+- keys(4)(0) <= DIP_SWITCH(5);
+- keys(5)(0) <= DIP_SWITCH(4);
+- keys(6)(0) <= DIP_SWITCH(3);
+- keys(7)(0) <= DIP_SWITCH(2);
+- keys(8)(0) <= DIP_SWITCH(1);
+- keys(9)(0) <= DIP_SWITCH(0);
+-
+- if keyb_valid = '1' then
+- -- Decode keyboard input
+- if keyb_data = X"e0" then
+- -- Extended key code follows
+- extended <= '1';
+- elsif keyb_data = X"f0" then
+- -- Release code follows
+- release <= '1';
+- else
+- -- Cancel extended/release flags for next time
+- release <= '0';
+- extended <= '0';
+-
+- -- Decode scan codes
+- case keyb_data is
+- when X"12" => keys(0)(0) <= not release; -- Left SHIFT
+- when X"59" => keys(0)(0) <= not release; -- Right SHIFT
+- when X"15" => keys(0)(1) <= not release; -- Q
+- when X"09" => keys(0)(2) <= not release; -- F10 (F0)
+- when X"16" => keys(0)(3) <= not release; -- 1
+- when X"58" => keys(0)(4) <= not release; -- CAPS LOCK
+- when X"11" => keys(0)(5) <= not release; -- LEFT ALT (SHIFT LOCK)
+- when X"0D" => keys(0)(6) <= not release; -- TAB
+- when X"76" => keys(0)(7) <= not release; -- ESCAPE
+- when X"14" => keys(1)(0) <= not release; -- LEFT/RIGHT CTRL (CTRL)
+- when X"26" => keys(1)(1) <= not release; -- 3
+- when X"1D" => keys(1)(2) <= not release; -- W
+- when X"1E" => keys(1)(3) <= not release; -- 2
+- when X"1C" => keys(1)(4) <= not release; -- A
+- when X"1B" => keys(1)(5) <= not release; -- S
+- when X"1A" => keys(1)(6) <= not release; -- Z
+- when X"05" => keys(1)(7) <= not release; -- F1
+- when X"25" => keys(2)(1) <= not release; -- 4
+- when X"24" => keys(2)(2) <= not release; -- E
+- when X"23" => keys(2)(3) <= not release; -- D
+- when X"22" => keys(2)(4) <= not release; -- X
+- when X"21" => keys(2)(5) <= not release; -- C
+- when X"29" => keys(2)(6) <= not release; -- SPACE
+- when X"06" => keys(2)(7) <= not release; -- F2
+- when X"2E" => keys(3)(1) <= not release; -- 5
+- when X"2C" => keys(3)(2) <= not release; -- T
+- when X"2D" => keys(3)(3) <= not release; -- R
+- when X"2B" => keys(3)(4) <= not release; -- F
+- when X"34" => keys(3)(5) <= not release; -- G
+- when X"2A" => keys(3)(6) <= not release; -- V
+- when X"04" => keys(3)(7) <= not release; -- F3
+- when X"0C" => keys(4)(1) <= not release; -- F4
+- when X"3D" => keys(4)(2) <= not release; -- 7
+- when X"36" => keys(4)(3) <= not release; -- 6
+- when X"35" => keys(4)(4) <= not release; -- Y
+- when X"33" => keys(4)(5) <= not release; -- H
+- when X"32" => keys(4)(6) <= not release; -- B
+- when X"03" => keys(4)(7) <= not release; -- F5
+- when X"3E" => keys(5)(1) <= not release; -- 8
+- when X"43" => keys(5)(2) <= not release; -- I
+- when X"3C" => keys(5)(3) <= not release; -- U
+- when X"3B" => keys(5)(4) <= not release; -- J
+- when X"31" => keys(5)(5) <= not release; -- N
+- when X"3A" => keys(5)(6) <= not release; -- M
+- when X"0B" => keys(5)(7) <= not release; -- F6
+- when X"83" => keys(6)(1) <= not release; -- F7
+- when X"46" => keys(6)(2) <= not release; -- 9
+- when X"44" => keys(6)(3) <= not release; -- O
+- when X"42" => keys(6)(4) <= not release; -- K
+- when X"4B" => keys(6)(5) <= not release; -- L
+- when X"41" => keys(6)(6) <= not release; -- ,
+- when X"0A" => keys(6)(7) <= not release; -- F8
+- when X"4E" => keys(7)(1) <= not release; -- -
+- when X"45" => keys(7)(2) <= not release; -- 0
+- when X"4D" => keys(7)(3) <= not release; -- P
+- when X"0E" => keys(7)(4) <= not release; -- ` (@)
+- when X"4C" => keys(7)(5) <= not release; -- ;
+- when X"49" => keys(7)(6) <= not release; -- .
+- when X"01" => keys(7)(7) <= not release; -- F9
+- when X"55" => keys(8)(1) <= not release; -- = (^)
+- when X"5D" => keys(8)(2) <= not release; -- # (_)
+- when X"54" => keys(8)(3) <= not release; -- [
+- when X"52" => keys(8)(4) <= not release; -- '
+- when X"5B" => keys(8)(5) <= not release; -- ]
+- when X"4A" => keys(8)(6) <= not release; -- /
+- when X"61" => keys(8)(7) <= not release; -- \
+- when X"6B" => keys(9)(1) <= not release; -- LEFT
+- when X"72" => keys(9)(2) <= not release; -- DOWN
+- when X"75" => keys(9)(3) <= not release; -- UP
+- when X"5A" => keys(9)(4) <= not release; -- RETURN
+- when X"66" => keys(9)(5) <= not release; -- BACKSPACE (DELETE)
+- when X"69" => keys(9)(6) <= not release; -- END (COPY)
+- when X"74" => keys(9)(7) <= not release; -- RIGHT
+-
+- -- F12 is used for the BREAK key, which in the real BBC asserts
+- -- reset. Here we pass this out to the top level which may
+- -- optionally OR it in to the system reset
+- when X"07" => BREAK_OUT <= not release; -- F12 (BREAK)
+-
+- when others => null;
+- end case;
+-
+- end if;
+- end if;
+- end if;
+- end process;
+-
+-end architecture;
+-
+-
++-- BBC Micro for Altera DE1
++--
++-- Copyright (c) 2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++-- BBC keyboard implementation with interface to PS/2
++--
++-- (C) 2011 Mike Stirling
++--
++
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.NUMERIC_STD.ALL;
++
++entity keyboard is
++port (
++ CLOCK : in std_logic;
++ nRESET : in std_logic;
++ CLKEN_1MHZ : in std_logic;
++
++ -- PS/2 interface
++ PS2_CLK : in std_logic;
++ PS2_DATA : in std_logic;
++
++ -- If 1 then column is incremented automatically at
++ -- 1 MHz rate
++ AUTOSCAN : in std_logic;
++
++ COLUMN : in std_logic_vector(3 downto 0);
++ ROW : in std_logic_vector(2 downto 0);
++
++ -- 1 when currently selected key is down (AUTOSCAN disabled)
++ KEYPRESS : out std_logic;
++ -- 1 when any key is down (except row 0)
++ INT : out std_logic;
++ -- BREAK key output - 1 when pressed
++ BREAK_OUT : out std_logic;
++
++ -- DIP switch inputs
++ DIP_SWITCH : in std_logic_vector(7 downto 0)
++ );
++end entity;
++
++architecture rtl of keyboard is
++
++-- PS/2 interface
++component ps2_intf is
++generic (filter_length : positive := 8);
++port(
++ CLK : in std_logic;
++ nRESET : in std_logic;
++
++ -- PS/2 interface (could be bi-dir)
++ PS2_CLK : in std_logic;
++ PS2_DATA : in std_logic;
++
++ -- Byte-wide data interface - only valid for one clock
++ -- so must be latched externally if required
++ DATA : out std_logic_vector(7 downto 0);
++ VALID : out std_logic;
++ ERROR : out std_logic
++ );
++end component;
++
++-- Interface to PS/2 block
++signal keyb_data : std_logic_vector(7 downto 0);
++signal keyb_valid : std_logic;
++signal keyb_error : std_logic;
++
++-- Internal signals
++type key_matrix is array(0 to 15) of std_logic_vector(7 downto 0);
++signal keys : key_matrix;
++signal col : unsigned(3 downto 0);
++signal release : std_logic;
++signal extended : std_logic;
++begin
++
++ ps2 : ps2_intf port map (
++ CLOCK, nRESET,
++ PS2_CLK, PS2_DATA,
++ keyb_data, keyb_valid, keyb_error
++ );
++
++ -- Column counts automatically when AUTOSCAN is enabled, otherwise
++ -- value is loaded from external input
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ col <= (others => '0');
++ elsif rising_edge(CLOCK) then
++ if AUTOSCAN = '0' then
++ -- If autoscan disabled then transfer current COLUMN to counter
++ -- immediately (don't wait for next 1 MHz cycle)
++ col <= unsigned(COLUMN);
++ elsif CLKEN_1MHZ = '1' then
++ -- Otherwise increment the counter once per 1 MHz tick
++ col <= col + 1;
++ end if;
++ end if;
++ end process;
++
++ -- Generate interrupt if any key in currently scanned column is pressed
++ -- (apart from in row 0). Output selected key status if autoscan disabled.
++ process(keys,col,ROW,AUTOSCAN)
++ variable k : std_logic_vector(7 downto 0);
++ begin
++ -- Shortcut to current key column
++ k := keys(to_integer(col));
++
++ -- Interrupt if any key pressed in rows 1 to 7.
++ INT <= k(7) or k(6) or k(5) or k(4) or k(3) or k(2) or k(1);
++
++ -- Determine which key is pressed
++ -- Inhibit output during auto-scan
++ if AUTOSCAN = '0' then
++ KEYPRESS <= k(to_integer(unsigned(ROW)));
++ else
++ KEYPRESS <= '0';
++ end if;
++ end process;
++
++ -- Decode PS/2 data
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ release <= '0';
++ extended <= '0';
++
++ BREAK_OUT <= '0';
++
++ keys(0) <= (others => '0');
++ keys(1) <= (others => '0');
++ keys(2) <= (others => '0');
++ keys(3) <= (others => '0');
++ keys(4) <= (others => '0');
++ keys(5) <= (others => '0');
++ keys(6) <= (others => '0');
++ keys(7) <= (others => '0');
++ keys(8) <= (others => '0');
++ keys(9) <= (others => '0');
++ -- These non-existent rows are used in the BBC master
++ keys(10) <= (others => '0');
++ keys(11) <= (others => '0');
++ keys(12) <= (others => '0');
++ keys(13) <= (others => '0');
++ keys(14) <= (others => '0');
++ keys(15) <= (others => '0');
++ elsif rising_edge(CLOCK) then
++ -- Copy DIP switches through to row 0
++ keys(2)(0) <= DIP_SWITCH(7);
++ keys(3)(0) <= DIP_SWITCH(6);
++ keys(4)(0) <= DIP_SWITCH(5);
++ keys(5)(0) <= DIP_SWITCH(4);
++ keys(6)(0) <= DIP_SWITCH(3);
++ keys(7)(0) <= DIP_SWITCH(2);
++ keys(8)(0) <= DIP_SWITCH(1);
++ keys(9)(0) <= DIP_SWITCH(0);
++
++ if keyb_valid = '1' then
++ -- Decode keyboard input
++ if keyb_data = X"e0" then
++ -- Extended key code follows
++ extended <= '1';
++ elsif keyb_data = X"f0" then
++ -- Release code follows
++ release <= '1';
++ else
++ -- Cancel extended/release flags for next time
++ release <= '0';
++ extended <= '0';
++
++ -- Decode scan codes
++ case keyb_data is
++ when X"12" => keys(0)(0) <= not release; -- Left SHIFT
++ when X"59" => keys(0)(0) <= not release; -- Right SHIFT
++ when X"15" => keys(0)(1) <= not release; -- Q
++ when X"09" => keys(0)(2) <= not release; -- F10 (F0)
++ when X"16" => keys(0)(3) <= not release; -- 1
++ when X"58" => keys(0)(4) <= not release; -- CAPS LOCK
++ when X"11" => keys(0)(5) <= not release; -- LEFT ALT (SHIFT LOCK)
++ when X"0D" => keys(0)(6) <= not release; -- TAB
++ when X"76" => keys(0)(7) <= not release; -- ESCAPE
++ when X"14" => keys(1)(0) <= not release; -- LEFT/RIGHT CTRL (CTRL)
++ when X"26" => keys(1)(1) <= not release; -- 3
++ when X"1D" => keys(1)(2) <= not release; -- W
++ when X"1E" => keys(1)(3) <= not release; -- 2
++ when X"1C" => keys(1)(4) <= not release; -- A
++ when X"1B" => keys(1)(5) <= not release; -- S
++ when X"1A" => keys(1)(6) <= not release; -- Z
++ when X"05" => keys(1)(7) <= not release; -- F1
++ when X"25" => keys(2)(1) <= not release; -- 4
++ when X"24" => keys(2)(2) <= not release; -- E
++ when X"23" => keys(2)(3) <= not release; -- D
++ when X"22" => keys(2)(4) <= not release; -- X
++ when X"21" => keys(2)(5) <= not release; -- C
++ when X"29" => keys(2)(6) <= not release; -- SPACE
++ when X"06" => keys(2)(7) <= not release; -- F2
++ when X"2E" => keys(3)(1) <= not release; -- 5
++ when X"2C" => keys(3)(2) <= not release; -- T
++ when X"2D" => keys(3)(3) <= not release; -- R
++ when X"2B" => keys(3)(4) <= not release; -- F
++ when X"34" => keys(3)(5) <= not release; -- G
++ when X"2A" => keys(3)(6) <= not release; -- V
++ when X"04" => keys(3)(7) <= not release; -- F3
++ when X"0C" => keys(4)(1) <= not release; -- F4
++ when X"3D" => keys(4)(2) <= not release; -- 7
++ when X"36" => keys(4)(3) <= not release; -- 6
++ when X"35" => keys(4)(4) <= not release; -- Y
++ when X"33" => keys(4)(5) <= not release; -- H
++ when X"32" => keys(4)(6) <= not release; -- B
++ when X"03" => keys(4)(7) <= not release; -- F5
++ when X"3E" => keys(5)(1) <= not release; -- 8
++ when X"43" => keys(5)(2) <= not release; -- I
++ when X"3C" => keys(5)(3) <= not release; -- U
++ when X"3B" => keys(5)(4) <= not release; -- J
++ when X"31" => keys(5)(5) <= not release; -- N
++ when X"3A" => keys(5)(6) <= not release; -- M
++ when X"0B" => keys(5)(7) <= not release; -- F6
++ when X"83" => keys(6)(1) <= not release; -- F7
++ when X"46" => keys(6)(2) <= not release; -- 9
++ when X"44" => keys(6)(3) <= not release; -- O
++ when X"42" => keys(6)(4) <= not release; -- K
++ when X"4B" => keys(6)(5) <= not release; -- L
++ when X"41" => keys(6)(6) <= not release; -- ,
++ when X"0A" => keys(6)(7) <= not release; -- F8
++ when X"4E" => keys(7)(1) <= not release; -- -
++ when X"45" => keys(7)(2) <= not release; -- 0
++ when X"4D" => keys(7)(3) <= not release; -- P
++ when X"0E" => keys(7)(4) <= not release; -- ` (@)
++ when X"4C" => keys(7)(5) <= not release; -- ;
++ when X"49" => keys(7)(6) <= not release; -- .
++ when X"01" => keys(7)(7) <= not release; -- F9
++ when X"55" => keys(8)(1) <= not release; -- = (^)
++ when X"5D" => keys(8)(2) <= not release; -- # (_)
++ when X"54" => keys(8)(3) <= not release; -- [
++ when X"52" => keys(8)(4) <= not release; -- '
++ when X"5B" => keys(8)(5) <= not release; -- ]
++ when X"4A" => keys(8)(6) <= not release; -- /
++ when X"61" => keys(8)(7) <= not release; -- \
++ when X"6B" => keys(9)(1) <= not release; -- LEFT
++ when X"72" => keys(9)(2) <= not release; -- DOWN
++ when X"75" => keys(9)(3) <= not release; -- UP
++ when X"5A" => keys(9)(4) <= not release; -- RETURN
++ when X"66" => keys(9)(5) <= not release; -- BACKSPACE (DELETE)
++ when X"69" => keys(9)(6) <= not release; -- END (COPY)
++ when X"74" => keys(9)(7) <= not release; -- RIGHT
++
++ -- F12 is used for the BREAK key, which in the real BBC asserts
++ -- reset. Here we pass this out to the top level which may
++ -- optionally OR it in to the system reset
++ when X"07" => BREAK_OUT <= not release; -- F12 (BREAK)
++
++ when others => null;
++ end case;
++
++ end if;
++ end if;
++ end if;
++ end process;
++
++end architecture;
++
++
+diff --git a/m6522.vhd b/m6522.vhd
+index e01ed10..5c0d341 100644
+--- a/m6522.vhd
++++ b/m6522.vhd
+@@ -1,886 +1,886 @@
+---
+--- A simulation model of VIC20 hardware
+--- Copyright (c) MikeJ - March 2003
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- You are responsible for any legal issues arising from your use of this code.
+---
+--- The latest version of this file can be found at: www.fpgaarcade.com
+---
+--- Email vic20@fpgaarcade.com
+---
+---
+--- Revision list
+---
+--- version 002 fix from Mark McDougall, untested
+--- version 001 initial release
+--- not very sure about the shift register, documentation is a bit light.
+-
+-library ieee ;
+- use ieee.std_logic_1164.all ;
+- use ieee.std_logic_unsigned.all;
+- use ieee.numeric_std.all;
+-
+---library UNISIM;
+--- use UNISIM.Vcomponents.all;
+-
+-entity M6522 is
+- port (
+-
+- I_RS : in std_logic_vector(3 downto 0);
+- I_DATA : in std_logic_vector(7 downto 0);
+- O_DATA : out std_logic_vector(7 downto 0);
+- O_DATA_OE_L : out std_logic;
+-
+- I_RW_L : in std_logic;
+- I_CS1 : in std_logic;
+- I_CS2_L : in std_logic;
+-
+- O_IRQ_L : out std_logic; -- note, not open drain
+- -- port a
+- I_CA1 : in std_logic;
+- I_CA2 : in std_logic;
+- O_CA2 : out std_logic;
+- O_CA2_OE_L : out std_logic;
+-
+- I_PA : in std_logic_vector(7 downto 0);
+- O_PA : out std_logic_vector(7 downto 0);
+- O_PA_OE_L : out std_logic_vector(7 downto 0);
+-
+- -- port b
+- I_CB1 : in std_logic;
+- O_CB1 : out std_logic;
+- O_CB1_OE_L : out std_logic;
+-
+- I_CB2 : in std_logic;
+- O_CB2 : out std_logic;
+- O_CB2_OE_L : out std_logic;
+-
+- I_PB : in std_logic_vector(7 downto 0);
+- O_PB : out std_logic_vector(7 downto 0);
+- O_PB_OE_L : out std_logic_vector(7 downto 0);
+-
+- I_P2_H : in std_logic; -- high for phase 2 clock ____----__
+- RESET_L : in std_logic;
+- ENA_4 : in std_logic; -- clk enable
+- CLK : in std_logic
+- );
+-end;
+-
+-architecture RTL of M6522 is
+-
+- signal phase : std_logic_vector(1 downto 0);
+- signal p2_h_t1 : std_logic;
+- signal cs : std_logic;
+-
+- -- registers
+- signal r_ddra : std_logic_vector(7 downto 0);
+- signal r_ora : std_logic_vector(7 downto 0);
+- signal r_ira : std_logic_vector(7 downto 0);
+-
+- signal r_ddrb : std_logic_vector(7 downto 0);
+- signal r_orb : std_logic_vector(7 downto 0);
+- signal r_irb : std_logic_vector(7 downto 0);
+-
+- signal r_t1l_l : std_logic_vector(7 downto 0);
+- signal r_t1l_h : std_logic_vector(7 downto 0);
+- signal r_t2l_l : std_logic_vector(7 downto 0);
+- signal r_t2l_h : std_logic_vector(7 downto 0); -- not in real chip
+- signal r_sr : std_logic_vector(7 downto 0);
+- signal r_acr : std_logic_vector(7 downto 0);
+- signal r_pcr : std_logic_vector(7 downto 0);
+- signal r_ifr : std_logic_vector(7 downto 0);
+- signal r_ier : std_logic_vector(6 downto 0);
+-
+- signal sr_write_ena : boolean;
+- signal sr_read_ena : boolean;
+- signal ifr_write_ena : boolean;
+- signal ier_write_ena : boolean;
+- signal clear_irq : std_logic_vector(7 downto 0);
+- signal load_data : std_logic_vector(7 downto 0);
+-
+- -- timer 1
+- signal t1c : std_logic_vector(15 downto 0);
+- signal t1c_active : boolean;
+- signal t1c_done : boolean;
+- signal t1_w_reset_int : boolean;
+- signal t1_r_reset_int : boolean;
+- signal t1_load_counter : boolean;
+- signal t1_reload_counter : boolean;
+- signal t1_toggle : std_logic;
+- signal t1_irq : std_logic := '0';
+-
+- -- timer 2
+- signal t2c : std_logic_vector(15 downto 0);
+- signal t2c_active : boolean;
+- signal t2c_done : boolean;
+- signal t2_pb6 : std_logic;
+- signal t2_pb6_t1 : std_logic;
+- signal t2_w_reset_int : boolean;
+- signal t2_r_reset_int : boolean;
+- signal t2_load_counter : boolean;
+- signal t2_reload_counter : boolean;
+- signal t2_irq : std_logic := '0';
+- signal t2_sr_ena : boolean;
+-
+- -- shift reg
+- signal sr_cnt : std_logic_vector(3 downto 0);
+- signal sr_cb1_oe_l : std_logic;
+- signal sr_cb1_out : std_logic;
+- signal sr_drive_cb2 : std_logic;
+- signal sr_strobe : std_logic;
+- signal sr_strobe_t1 : std_logic;
+- signal sr_strobe_falling : boolean;
+- signal sr_strobe_rising : boolean;
+- signal sr_irq : std_logic;
+- signal sr_out : std_logic;
+- signal sr_off_delay : std_logic;
+-
+- -- io
+- signal w_orb_hs : std_logic;
+- signal w_ora_hs : std_logic;
+- signal r_irb_hs : std_logic;
+- signal r_ira_hs : std_logic;
+-
+- signal ca_hs_sr : std_logic;
+- signal ca_hs_pulse : std_logic;
+- signal cb_hs_sr : std_logic;
+- signal cb_hs_pulse : std_logic;
+-
+- signal cb1_in_mux : std_logic;
+- signal ca1_ip_reg : std_logic;
+- signal cb1_ip_reg : std_logic;
+- signal ca1_int : boolean;
+- signal cb1_int : boolean;
+- signal ca1_irq : std_logic;
+- signal cb1_irq : std_logic;
+-
+- signal ca2_ip_reg : std_logic;
+- signal cb2_ip_reg : std_logic;
+- signal ca2_int : boolean;
+- signal cb2_int : boolean;
+- signal ca2_irq : std_logic;
+- signal cb2_irq : std_logic;
+-
+- signal final_irq : std_logic;
+-begin
+- p_phase : process
+- begin
+- -- internal clock phase
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- p2_h_t1 <= I_P2_H;
+- if (p2_h_t1 = '0') and (I_P2_H = '1') then
+- phase <= "11";
+- else
+- phase <= phase + "1";
+- end if;
+- end if;
+- end process;
+-
+- p_cs : process(I_CS1, I_CS2_L, I_P2_H)
+- begin
+- cs <= '0';
+- if (I_CS1 = '1') and (I_CS2_L = '0') and (I_P2_H = '1') then
+- cs <= '1';
+- end if;
+- end process;
+-
+- -- peripheral control reg (pcr)
+- -- 0 ca1 interrupt control (0 +ve edge, 1 -ve edge)
+- -- 3..1 ca2 operation
+- -- 000 input -ve edge
+- -- 001 independend interrupt input -ve edge
+- -- 010 input +ve edge
+- -- 011 independend interrupt input +ve edge
+- -- 100 handshake output
+- -- 101 pulse output
+- -- 110 low output
+- -- 111 high output
+- -- 7..4 as 3..0 for cb1,cb2
+-
+- -- auxiliary control reg (acr)
+- -- 0 input latch PA (0 disable, 1 enable)
+- -- 1 input latch PB (0 disable, 1 enable)
+- -- 4..2 shift reg control
+- -- 000 disable
+- -- 001 shift in using t2
+- -- 010 shift in using o2
+- -- 011 shift in using ext clk
+- -- 100 shift out free running t2 rate
+- -- 101 shift out using t2
+- -- 101 shift out using o2
+- -- 101 shift out using ext clk
+- -- 5 t2 timer control (0 timed interrupt, 1 count down with pulses on pb6)
+- -- 7..6 t1 timer control
+- -- 00 timed interrupt each time t1 is loaded pb7 disable
+- -- 01 continuous interrupts pb7 disable
+- -- 00 timed interrupt each time t1 is loaded pb7 one shot output
+- -- 01 continuous interrupts pb7 square wave output
+- --
+-
+- p_write_reg_reset : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- r_ora <= x"00"; r_orb <= x"00";
+- r_ddra <= x"00"; r_ddrb <= x"00";
+- r_acr <= x"00"; r_pcr <= x"00";
+-
+- w_orb_hs <= '0';
+- w_ora_hs <= '0';
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- w_orb_hs <= '0';
+- w_ora_hs <= '0';
+- if (cs = '1') and (I_RW_L = '0') then
+- case I_RS is
+- when x"0" => r_orb <= I_DATA; w_orb_hs <= '1';
+- when x"1" => r_ora <= I_DATA; w_ora_hs <= '1';
+- when x"2" => r_ddrb <= I_DATA;
+- when x"3" => r_ddra <= I_DATA;
+-
+- when x"B" => r_acr <= I_DATA;
+- when x"C" => r_pcr <= I_DATA;
+- when x"F" => r_ora <= I_DATA;
+-
+- when others => null;
+- end case;
+- end if;
+-
+- if (r_acr(7) = '1') and (t1_toggle = '1') then
+- r_orb(7) <= not r_orb(7); -- toggle
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- p_write_reg : process
+- begin
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- t1_w_reset_int <= false;
+- t1_load_counter <= false;
+-
+- t2_w_reset_int <= false;
+- t2_load_counter <= false;
+-
+- load_data <= x"00";
+- sr_write_ena <= false;
+- ifr_write_ena <= false;
+- ier_write_ena <= false;
+-
+- if (cs = '1') and (I_RW_L = '0') then
+- load_data <= I_DATA;
+- case I_RS is
+- when x"4" => r_t1l_l <= I_DATA;
+- when x"5" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
+- t1_load_counter <= true;
+-
+- when x"6" => r_t1l_l <= I_DATA;
+- when x"7" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
+-
+- when x"8" => r_t2l_l <= I_DATA;
+- when x"9" => r_t2l_h <= I_DATA; t2_w_reset_int <= true;
+- t2_load_counter <= true;
+-
+- when x"A" => sr_write_ena <= true;
+- when x"D" => ifr_write_ena <= true;
+- when x"E" => ier_write_ena <= true;
+-
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end process;
+-
+- p_oe : process(cs, I_RW_L)
+- begin
+- O_DATA_OE_L <= '1';
+- if (cs = '1') and (I_RW_L = '1') then
+- O_DATA_OE_L <= '0';
+- end if;
+- end process;
+-
+- p_read : process
+- begin
+- wait until rising_edge(CLK);
+-
+- if ENA_4 = '1' then
+- t1_r_reset_int <= false;
+- t2_r_reset_int <= false;
+- sr_read_ena <= false;
+- r_irb_hs <= '0';
+- r_ira_hs <= '0';
+-
+- if (cs = '1') and (I_RW_L = '1') then
+- case I_RS is
+- --when x"0" => O_DATA <= r_irb; r_irb_hs <= '1';
+- -- fix from Mark McDougall, untested
+- when x"0" => O_DATA <= (r_irb and not r_ddrb) or (r_orb and r_ddrb); r_irb_hs <= '1';
+- when x"1" => O_DATA <= r_ira; r_ira_hs <= '1';
+- when x"2" => O_DATA <= r_ddrb;
+- when x"3" => O_DATA <= r_ddra;
+- when x"4" => O_DATA <= t1c( 7 downto 0); t1_r_reset_int <= true;
+- when x"5" => O_DATA <= t1c(15 downto 8);
+- when x"6" => O_DATA <= r_t1l_l;
+- when x"7" => O_DATA <= r_t1l_h;
+- when x"8" => O_DATA <= t2c( 7 downto 0); t2_r_reset_int <= true;
+- when x"9" => O_DATA <= t2c(15 downto 8);
+- when x"A" => O_DATA <= r_sr; sr_read_ena <= true;
+- when x"B" => O_DATA <= r_acr;
+- when x"C" => O_DATA <= r_pcr;
+- when x"D" => O_DATA <= r_ifr;
+- when x"E" => O_DATA <= ('0' & r_ier);
+- when x"F" => O_DATA <= r_ira;
+- when others => null;
+- end case;
+- end if;
+- end if;
+-
+- end process;
+- --
+- -- IO
+- --
+- p_ca1_cb1_sel : process(sr_cb1_oe_l, sr_cb1_out, I_CB1)
+- begin
+- -- if the shift register is enabled, cb1 may be an output
+- -- in this case, we should listen to the CB1_OUT for the interrupt
+- if (sr_cb1_oe_l = '1') then
+- cb1_in_mux <= I_CB1;
+- else
+- cb1_in_mux <= sr_cb1_out;
+- end if;
+- end process;
+-
+- p_ca1_cb1_int : process(r_pcr, ca1_ip_reg, I_CA1, cb1_ip_reg, cb1_in_mux)
+- begin
+- if (r_pcr(0) = '0') then -- ca1 control
+- -- negative edge
+- ca1_int <= (ca1_ip_reg = '1') and (I_CA1 = '0');
+- else
+- -- positive edge
+- ca1_int <= (ca1_ip_reg = '0') and (I_CA1 = '1');
+- end if;
+-
+- if (r_pcr(4) = '0') then -- cb1 control
+- -- negative edge
+- cb1_int <= (cb1_ip_reg = '1') and (cb1_in_mux = '0');
+- else
+- -- positive edge
+- cb1_int <= (cb1_ip_reg = '0') and (cb1_in_mux = '1');
+- end if;
+- end process;
+-
+- p_ca2_cb2_int : process(r_pcr, ca2_ip_reg, I_CA2, cb2_ip_reg, I_CB2)
+- begin
+- ca2_int <= false;
+- if (r_pcr(3) = '0') then -- ca2 input
+- if (r_pcr(2) = '0') then -- ca2 edge
+- -- negative edge
+- ca2_int <= (ca2_ip_reg = '1') and (I_CA2 = '0');
+- else
+- -- positive edge
+- ca2_int <= (ca2_ip_reg = '0') and (I_CA2 = '1');
+- end if;
+- end if;
+-
+- cb2_int <= false;
+- if (r_pcr(7) = '0') then -- cb2 input
+- if (r_pcr(6) = '0') then -- cb2 edge
+- -- negative edge
+- cb2_int <= (cb2_ip_reg = '1') and (I_CB2 = '0');
+- else
+- -- positive edge
+- cb2_int <= (cb2_ip_reg = '0') and (I_CB2 = '1');
+- end if;
+- end if;
+- end process;
+-
+- p_ca2_cb2 : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- O_CA2 <= '0';
+- O_CA2_OE_L <= '1';
+- O_CB2 <= '0';
+- O_CB2_OE_L <= '1';
+-
+- ca_hs_sr <= '0';
+- ca_hs_pulse <= '0';
+- cb_hs_sr <= '0';
+- cb_hs_pulse <= '0';
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- -- ca
+- if (phase = "00") and ((w_ora_hs = '1') or (r_ira_hs = '1')) then
+- ca_hs_sr <= '1';
+- elsif ca1_int then
+- ca_hs_sr <= '0';
+- end if;
+-
+- if (phase = "00") then
+- ca_hs_pulse <= w_ora_hs or r_ira_hs;
+- end if;
+-
+- O_CA2_OE_L <= not r_pcr(3); -- ca2 output
+- case r_pcr(3 downto 1) is
+- when "000" => O_CA2 <= '0'; -- input
+- when "001" => O_CA2 <= '0'; -- input
+- when "010" => O_CA2 <= '0'; -- input
+- when "011" => O_CA2 <= '0'; -- input
+- when "100" => O_CA2 <= not (ca_hs_sr); -- handshake
+- when "101" => O_CA2 <= not (ca_hs_pulse); -- pulse
+- when "110" => O_CA2 <= '0'; -- low
+- when "111" => O_CA2 <= '1'; -- high
+- when others => null;
+- end case;
+-
+- -- cb
+- if (phase = "00") and (w_orb_hs = '1') then
+- cb_hs_sr <= '1';
+- elsif cb1_int then
+- cb_hs_sr <= '0';
+- end if;
+-
+- if (phase = "00") then
+- cb_hs_pulse <= w_orb_hs;
+- end if;
+-
+- O_CB2_OE_L <= not (r_pcr(7) or sr_drive_cb2); -- cb2 output or serial
+- if (sr_drive_cb2 = '1') then -- serial output
+- O_CB2 <= sr_out;
+- else
+- case r_pcr(7 downto 5) is
+- when "000" => O_CB2 <= '0'; -- input
+- when "001" => O_CB2 <= '0'; -- input
+- when "010" => O_CB2 <= '0'; -- input
+- when "011" => O_CB2 <= '0'; -- input
+- when "100" => O_CB2 <= not (cb_hs_sr); -- handshake
+- when "101" => O_CB2 <= not (cb_hs_pulse); -- pulse
+- when "110" => O_CB2 <= '0'; -- low
+- when "111" => O_CB2 <= '1'; -- high
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end if;
+- end process;
+- O_CB1 <= sr_cb1_out;
+- O_CB1_OE_L <= sr_cb1_oe_l;
+-
+- p_ca_cb_irq : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- ca1_irq <= '0';
+- ca2_irq <= '0';
+- cb1_irq <= '0';
+- cb2_irq <= '0';
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- -- not pretty
+- if ca1_int then
+- ca1_irq <= '1';
+- elsif (r_ira_hs = '1') or (w_ora_hs = '1') or (clear_irq(1) = '1') then
+- ca1_irq <= '0';
+- end if;
+-
+- if ca2_int then
+- ca2_irq <= '1';
+- else
+- if (((r_ira_hs = '1') or (w_ora_hs = '1')) and (r_pcr(1) = '0')) or
+- (clear_irq(0) = '1') then
+- ca2_irq <= '0';
+- end if;
+- end if;
+-
+- if cb1_int then
+- cb1_irq <= '1';
+- elsif (r_irb_hs = '1') or (w_orb_hs = '1') or (clear_irq(4) = '1') then
+- cb1_irq <= '0';
+- end if;
+-
+- if cb2_int then
+- cb2_irq <= '1';
+- else
+- if (((r_irb_hs = '1') or (w_orb_hs = '1')) and (r_pcr(5) = '0')) or
+- (clear_irq(3) = '1') then
+- cb2_irq <= '0';
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- p_input_reg : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- ca1_ip_reg <= '0';
+- cb1_ip_reg <= '0';
+-
+- ca2_ip_reg <= '0';
+- cb2_ip_reg <= '0';
+-
+- r_ira <= x"00";
+- r_irb <= x"00";
+-
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- -- we have a fast clock, so we can have input registers
+- ca1_ip_reg <= I_CA1;
+- cb1_ip_reg <= cb1_in_mux;
+-
+- ca2_ip_reg <= I_CA2;
+- cb2_ip_reg <= I_CB2;
+-
+- if (r_acr(0) = '0') then
+- r_ira <= I_PA;
+- else -- enable latching
+- if ca1_int then
+- r_ira <= I_PA;
+- end if;
+- end if;
+-
+- if (r_acr(1) = '0') then
+- r_irb <= I_PB;
+- else -- enable latching
+- if cb1_int then
+- r_irb <= I_PB;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+-
+- p_buffers : process(r_ddra, r_ora, r_ddrb, r_acr, r_orb)
+- begin
+- -- data direction reg (ddr) 0 = input, 1 = output
+- O_PA <= r_ora;
+- O_PA_OE_L <= not r_ddra;
+-
+- if (r_acr(7) = '1') then -- not clear if r_ddrb(7) must be 1 as well
+- O_PB_OE_L(7) <= '0'; -- an output if under t1 control
+- else
+- O_PB_OE_L(7) <= not (r_ddrb(7));
+- end if;
+-
+- O_PB_OE_L(6 downto 0) <= not r_ddrb(6 downto 0);
+- O_PB(7 downto 0) <= r_orb(7 downto 0);
+-
+- end process;
+- --
+- -- Timer 1
+- --
+- p_timer1_done : process(t1c,phase,r_acr)
+- variable done : boolean;
+- begin
+- done := (t1c = x"0000");
+- t1c_done <= done and (phase = "11");
+- --if (phase = "11") then
+- t1_reload_counter <= done and (r_acr(6) = '1');
+- --end if;
+- end process;
+-
+- p_timer1 : process
+- begin
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- if t1_load_counter or (t1_reload_counter and phase = "11") then
+- t1c( 7 downto 0) <= r_t1l_l;
+- t1c(15 downto 8) <= r_t1l_h;
+- elsif (phase="11") then
+- t1c <= t1c - "1";
+- end if;
+-
+- if t1_load_counter or t1_reload_counter then
+- t1c_active <= true;
+- elsif t1c_done then
+- t1c_active <= false;
+- end if;
+- if RESET_L = '0' then
+- t1c_active <= false;
+- end if;
+-
+- t1_toggle <= '0';
+- if t1c_active and t1c_done then
+- t1_toggle <= '1';
+- t1_irq <= '1';
+- elsif RESET_L = '0' or t1_w_reset_int or t1_r_reset_int or (clear_irq(6) = '1') then
+- t1_irq <= '0';
+- end if;
+- end if;
+- end process;
+- --
+- -- Timer2
+- --
+- p_timer2_pb6_input : process
+- begin
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- if (phase = "01") then -- leading edge p2_h
+- t2_pb6 <= I_PB(6);
+- t2_pb6_t1 <= t2_pb6;
+- end if;
+- end if;
+- end process;
+-
+- p_timer2_done : process(t2c,phase)
+- variable done : boolean;
+- begin
+- done := (t2c = x"0000");
+- t2c_done <= done and (phase = "11");
+- --if (phase = "11") then
+- t2_reload_counter <= done;
+- --end if;
+- end process;
+-
+- p_timer2 : process
+- variable ena : boolean;
+- begin
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- if (r_acr(5) = '0') then
+- ena := true;
+- else
+- ena := (t2_pb6_t1 = '1') and (t2_pb6 = '0'); -- falling edge
+- end if;
+-
+- if t2_load_counter or (t2_reload_counter and phase = "11") then
+- -- not sure if t2c_reload should be here. Does timer2 just continue to
+- -- count down, or is it reloaded ? Reloaded makes more sense if using
+- -- it to generate a clock for the shift register.
+- t2c( 7 downto 0) <= r_t2l_l;
+- t2c(15 downto 8) <= r_t2l_h;
+- else
+- if (phase="11") and ena then -- or count mode
+- t2c <= t2c - "1";
+- end if;
+- end if;
+-
+- t2_sr_ena <= (t2c(7 downto 0) = x"00") and (phase = "11");
+-
+- if t2_load_counter then
+- t2c_active <= true;
+- elsif t2c_done then
+- t2c_active <= false;
+- end if;
+- if RESET_L = '0' then
+- t2c_active <= false;
+- end if;
+-
+- if t2c_active and t2c_done then
+- t2_irq <= '1';
+- elsif RESET_L = '0' or t2_w_reset_int or t2_r_reset_int or (clear_irq(5) = '1') then
+- t2_irq <= '0';
+- end if;
+- end if;
+- end process;
+- --
+- -- Shift Register
+- --
+- p_sr : process(RESET_L, CLK)
+- variable dir_out : std_logic;
+- variable ena : std_logic;
+- variable cb1_op : std_logic;
+- variable cb1_ip : std_logic;
+- variable use_t2 : std_logic;
+- variable free_run : std_logic;
+- variable sr_count_ena : boolean;
+- begin
+- if (RESET_L = '0') then
+- r_sr <= x"00";
+- sr_drive_cb2 <= '0';
+- sr_cb1_oe_l <= '1';
+- sr_cb1_out <= '0';
+- sr_strobe <= '1';
+- sr_cnt <= "0000";
+- sr_irq <= '0';
+- sr_out <= '1';
+- sr_off_delay <= '0';
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- -- decode mode
+- dir_out := r_acr(4); -- output on cb2
+- cb1_op := '0';
+- cb1_ip := '0';
+- use_t2 := '0';
+- free_run := '0';
+-
+- case r_acr(4 downto 2) is
+- when "000" => ena := '0'; cb1_ip := '1';
+- when "001" => ena := '1'; cb1_op := '1'; use_t2 := '1';
+- when "010" => ena := '1'; cb1_op := '1';
+- when "011" => ena := '1'; cb1_ip := '1';
+- when "100" => ena := '1'; use_t2 := '1'; free_run := '1';
+- when "101" => ena := '1'; cb1_op := '1'; use_t2 := '1';
+- when "110" => ena := '1';
+- when "111" => ena := '1'; cb1_ip := '1';
+- when others => null;
+- end case;
+-
+- -- clock select
+- -- 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
+- if (cb1_ip = '1') then
+- sr_strobe <= I_CB1;
+- else
+- if (sr_cnt(3) = '0') and (free_run = '0') then
+- sr_strobe <= '1';
+- else
+- if ((use_t2 = '1') and t2_sr_ena) or
+- ((use_t2 = '0') and (phase = "00")) then
+- sr_strobe <= not sr_strobe;
+- end if;
+- end if;
+- end if;
+-
+- -- latch on rising edge, shift on falling edge
+- if sr_write_ena then
+- r_sr <= load_data;
+- else
+- if (dir_out = '0') then
+- -- input
+- if (sr_cnt(3) = '1') or (cb1_ip = '1') then
+- if sr_strobe_rising then
+- r_sr <= r_sr(6 downto 0) & I_CB2;
+- end if;
+- end if;
+- sr_out <= '1';
+- else
+- -- output
+- if (sr_cnt(3) = '1') or (sr_off_delay = '1') or (cb1_ip = '1') or (free_run = '1') then
+- if sr_strobe_falling then
+- r_sr(7 downto 1) <= r_sr(6 downto 0);
+- r_sr(0) <= r_sr(7);
+- sr_out <= r_sr(7);
+- end if;
+- else
+- sr_out <= '1';
+- end if;
+- end if;
+- end if;
+-
+- sr_count_ena := sr_strobe_rising;
+-
+- if sr_write_ena or sr_read_ena then
+- -- some documentation says sr bit in IFR must be set as well ?
+- sr_cnt <= "1000";
+- elsif sr_count_ena and (sr_cnt(3) = '1') then
+- sr_cnt <= sr_cnt + "1";
+- end if;
+-
+- if (phase = "00") then
+- sr_off_delay <= sr_cnt(3); -- give some hold time when shifting out
+- end if;
+-
+- if sr_count_ena and (sr_cnt = "1111") and (ena = '1') and (free_run = '0') then
+- sr_irq <= '1';
+- elsif sr_write_ena or sr_read_ena or (clear_irq(2) = '1') then
+- sr_irq <= '0';
+- end if;
+-
+- -- assign ops
+- sr_drive_cb2 <= dir_out;
+- sr_cb1_oe_l <= not cb1_op;
+- sr_cb1_out <= sr_strobe;
+- end if;
+- end if;
+- end process;
+-
+- p_sr_strobe_rise_fall : process
+- begin
+- wait until rising_edge(CLK);
+- if (ENA_4 = '1') then
+- sr_strobe_t1 <= sr_strobe;
+- sr_strobe_rising <= (sr_strobe_t1 = '0') and (sr_strobe = '1');
+- sr_strobe_falling <= (sr_strobe_t1 = '1') and (sr_strobe = '0');
+- end if;
+- end process;
+- --
+- -- Interrupts
+- --
+- p_ier : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- r_ier <= "0000000";
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- if ier_write_ena then
+- if (load_data(7) = '1') then
+- -- set
+- r_ier <= r_ier or load_data(6 downto 0);
+- else
+- -- clear
+- r_ier <= r_ier and not load_data(6 downto 0);
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- p_ifr : process(t1_irq, t2_irq, final_irq, ca1_irq, ca2_irq, sr_irq,
+- cb1_irq, cb2_irq)
+- begin
+- r_ifr(7) <= final_irq;
+- r_ifr(6) <= t1_irq;
+- r_ifr(5) <= t2_irq;
+- r_ifr(4) <= cb1_irq;
+- r_ifr(3) <= cb2_irq;
+- r_ifr(2) <= sr_irq;
+- r_ifr(1) <= ca1_irq;
+- r_ifr(0) <= ca2_irq;
+-
+- O_IRQ_L <= not final_irq;
+- end process;
+-
+- p_irq : process(RESET_L, CLK)
+- begin
+- if (RESET_L = '0') then
+- final_irq <= '0';
+- elsif rising_edge(CLK) then
+- if (ENA_4 = '1') then
+- if ((r_ifr(6 downto 0) and r_ier(6 downto 0)) = "0000000") then
+- final_irq <= '0'; -- no interrupts
+- else
+- final_irq <= '1';
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- p_clear_irq : process(ifr_write_ena, load_data)
+- begin
+- clear_irq <= x"00";
+- if ifr_write_ena then
+- clear_irq <= load_data;
+- end if;
+- end process;
+-
+-end architecture RTL;
++--
++-- A simulation model of VIC20 hardware
++-- Copyright (c) MikeJ - March 2003
++--
++-- All rights reserved
++--
++-- Redistribution and use in source and synthezised forms, with or without
++-- modification, are permitted provided that the following conditions are met:
++--
++-- Redistributions of source code must retain the above copyright notice,
++-- this list of conditions and the following disclaimer.
++--
++-- Redistributions in synthesized form must reproduce the above copyright
++-- notice, this list of conditions and the following disclaimer in the
++-- documentation and/or other materials provided with the distribution.
++--
++-- Neither the name of the author nor the names of other contributors may
++-- be used to endorse or promote products derived from this software without
++-- specific prior written permission.
++--
++-- THIS CODE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++-- You are responsible for any legal issues arising from your use of this code.
++--
++-- The latest version of this file can be found at: www.fpgaarcade.com
++--
++-- Email vic20@fpgaarcade.com
++--
++--
++-- Revision list
++--
++-- version 002 fix from Mark McDougall, untested
++-- version 001 initial release
++-- not very sure about the shift register, documentation is a bit light.
++
++library ieee ;
++ use ieee.std_logic_1164.all ;
++ use ieee.std_logic_unsigned.all;
++ use ieee.numeric_std.all;
++
++--library UNISIM;
++-- use UNISIM.Vcomponents.all;
++
++entity M6522 is
++ port (
++
++ I_RS : in std_logic_vector(3 downto 0);
++ I_DATA : in std_logic_vector(7 downto 0);
++ O_DATA : out std_logic_vector(7 downto 0);
++ O_DATA_OE_L : out std_logic;
++
++ I_RW_L : in std_logic;
++ I_CS1 : in std_logic;
++ I_CS2_L : in std_logic;
++
++ O_IRQ_L : out std_logic; -- note, not open drain
++ -- port a
++ I_CA1 : in std_logic;
++ I_CA2 : in std_logic;
++ O_CA2 : out std_logic;
++ O_CA2_OE_L : out std_logic;
++
++ I_PA : in std_logic_vector(7 downto 0);
++ O_PA : out std_logic_vector(7 downto 0);
++ O_PA_OE_L : out std_logic_vector(7 downto 0);
++
++ -- port b
++ I_CB1 : in std_logic;
++ O_CB1 : out std_logic;
++ O_CB1_OE_L : out std_logic;
++
++ I_CB2 : in std_logic;
++ O_CB2 : out std_logic;
++ O_CB2_OE_L : out std_logic;
++
++ I_PB : in std_logic_vector(7 downto 0);
++ O_PB : out std_logic_vector(7 downto 0);
++ O_PB_OE_L : out std_logic_vector(7 downto 0);
++
++ I_P2_H : in std_logic; -- high for phase 2 clock ____----__
++ RESET_L : in std_logic;
++ ENA_4 : in std_logic; -- clk enable
++ CLK : in std_logic
++ );
++end;
++
++architecture RTL of M6522 is
++
++ signal phase : std_logic_vector(1 downto 0);
++ signal p2_h_t1 : std_logic;
++ signal cs : std_logic;
++
++ -- registers
++ signal r_ddra : std_logic_vector(7 downto 0);
++ signal r_ora : std_logic_vector(7 downto 0);
++ signal r_ira : std_logic_vector(7 downto 0);
++
++ signal r_ddrb : std_logic_vector(7 downto 0);
++ signal r_orb : std_logic_vector(7 downto 0);
++ signal r_irb : std_logic_vector(7 downto 0);
++
++ signal r_t1l_l : std_logic_vector(7 downto 0);
++ signal r_t1l_h : std_logic_vector(7 downto 0);
++ signal r_t2l_l : std_logic_vector(7 downto 0);
++ signal r_t2l_h : std_logic_vector(7 downto 0); -- not in real chip
++ signal r_sr : std_logic_vector(7 downto 0);
++ signal r_acr : std_logic_vector(7 downto 0);
++ signal r_pcr : std_logic_vector(7 downto 0);
++ signal r_ifr : std_logic_vector(7 downto 0);
++ signal r_ier : std_logic_vector(6 downto 0);
++
++ signal sr_write_ena : boolean;
++ signal sr_read_ena : boolean;
++ signal ifr_write_ena : boolean;
++ signal ier_write_ena : boolean;
++ signal clear_irq : std_logic_vector(7 downto 0);
++ signal load_data : std_logic_vector(7 downto 0);
++
++ -- timer 1
++ signal t1c : std_logic_vector(15 downto 0);
++ signal t1c_active : boolean;
++ signal t1c_done : boolean;
++ signal t1_w_reset_int : boolean;
++ signal t1_r_reset_int : boolean;
++ signal t1_load_counter : boolean;
++ signal t1_reload_counter : boolean;
++ signal t1_toggle : std_logic;
++ signal t1_irq : std_logic := '0';
++
++ -- timer 2
++ signal t2c : std_logic_vector(15 downto 0);
++ signal t2c_active : boolean;
++ signal t2c_done : boolean;
++ signal t2_pb6 : std_logic;
++ signal t2_pb6_t1 : std_logic;
++ signal t2_w_reset_int : boolean;
++ signal t2_r_reset_int : boolean;
++ signal t2_load_counter : boolean;
++ signal t2_reload_counter : boolean;
++ signal t2_irq : std_logic := '0';
++ signal t2_sr_ena : boolean;
++
++ -- shift reg
++ signal sr_cnt : std_logic_vector(3 downto 0);
++ signal sr_cb1_oe_l : std_logic;
++ signal sr_cb1_out : std_logic;
++ signal sr_drive_cb2 : std_logic;
++ signal sr_strobe : std_logic;
++ signal sr_strobe_t1 : std_logic;
++ signal sr_strobe_falling : boolean;
++ signal sr_strobe_rising : boolean;
++ signal sr_irq : std_logic;
++ signal sr_out : std_logic;
++ signal sr_off_delay : std_logic;
++
++ -- io
++ signal w_orb_hs : std_logic;
++ signal w_ora_hs : std_logic;
++ signal r_irb_hs : std_logic;
++ signal r_ira_hs : std_logic;
++
++ signal ca_hs_sr : std_logic;
++ signal ca_hs_pulse : std_logic;
++ signal cb_hs_sr : std_logic;
++ signal cb_hs_pulse : std_logic;
++
++ signal cb1_in_mux : std_logic;
++ signal ca1_ip_reg : std_logic;
++ signal cb1_ip_reg : std_logic;
++ signal ca1_int : boolean;
++ signal cb1_int : boolean;
++ signal ca1_irq : std_logic;
++ signal cb1_irq : std_logic;
++
++ signal ca2_ip_reg : std_logic;
++ signal cb2_ip_reg : std_logic;
++ signal ca2_int : boolean;
++ signal cb2_int : boolean;
++ signal ca2_irq : std_logic;
++ signal cb2_irq : std_logic;
++
++ signal final_irq : std_logic;
++begin
++ p_phase : process
++ begin
++ -- internal clock phase
++ wait until rising_edge(CLK);
++ if (ENA_4 = '1') then
++ p2_h_t1 <= I_P2_H;
++ if (p2_h_t1 = '0') and (I_P2_H = '1') then
++ phase <= "11";
++ else
++ phase <= phase + "1";
++ end if;
++ end if;
++ end process;
++
++ p_cs : process(I_CS1, I_CS2_L, I_P2_H)
++ begin
++ cs <= '0';
++ if (I_CS1 = '1') and (I_CS2_L = '0') and (I_P2_H = '1') then
++ cs <= '1';
++ end if;
++ end process;
++
++ -- peripheral control reg (pcr)
++ -- 0 ca1 interrupt control (0 +ve edge, 1 -ve edge)
++ -- 3..1 ca2 operation
++ -- 000 input -ve edge
++ -- 001 independend interrupt input -ve edge
++ -- 010 input +ve edge
++ -- 011 independend interrupt input +ve edge
++ -- 100 handshake output
++ -- 101 pulse output
++ -- 110 low output
++ -- 111 high output
++ -- 7..4 as 3..0 for cb1,cb2
++
++ -- auxiliary control reg (acr)
++ -- 0 input latch PA (0 disable, 1 enable)
++ -- 1 input latch PB (0 disable, 1 enable)
++ -- 4..2 shift reg control
++ -- 000 disable
++ -- 001 shift in using t2
++ -- 010 shift in using o2
++ -- 011 shift in using ext clk
++ -- 100 shift out free running t2 rate
++ -- 101 shift out using t2
++ -- 101 shift out using o2
++ -- 101 shift out using ext clk
++ -- 5 t2 timer control (0 timed interrupt, 1 count down with pulses on pb6)
++ -- 7..6 t1 timer control
++ -- 00 timed interrupt each time t1 is loaded pb7 disable
++ -- 01 continuous interrupts pb7 disable
++ -- 00 timed interrupt each time t1 is loaded pb7 one shot output
++ -- 01 continuous interrupts pb7 square wave output
++ --
++
++ p_write_reg_reset : process(RESET_L, CLK)
++ begin
++ if (RESET_L = '0') then
++ r_ora <= x"00"; r_orb <= x"00";
++ r_ddra <= x"00"; r_ddrb <= x"00";
++ r_acr <= x"00"; r_pcr <= x"00";
++
++ w_orb_hs <= '0';
++ w_ora_hs <= '0';
++ elsif rising_edge(CLK) then
++ if (ENA_4 = '1') then
++ w_orb_hs <= '0';
++ w_ora_hs <= '0';
++ if (cs = '1') and (I_RW_L = '0') then
++ case I_RS is
++ when x"0" => r_orb <= I_DATA; w_orb_hs <= '1';
++ when x"1" => r_ora <= I_DATA; w_ora_hs <= '1';
++ when x"2" => r_ddrb <= I_DATA;
++ when x"3" => r_ddra <= I_DATA;
++
++ when x"B" => r_acr <= I_DATA;
++ when x"C" => r_pcr <= I_DATA;
++ when x"F" => r_ora <= I_DATA;
++
++ when others => null;
++ end case;
++ end if;
++
++ if (r_acr(7) = '1') and (t1_toggle = '1') then
++ r_orb(7) <= not r_orb(7); -- toggle
++ end if;
++ end if;
++ end if;
++ end process;
++
++ p_write_reg : process
++ begin
++ wait until rising_edge(CLK);
++ if (ENA_4 = '1') then
++ t1_w_reset_int <= false;
++ t1_load_counter <= false;
++
++ t2_w_reset_int <= false;
++ t2_load_counter <= false;
++
++ load_data <= x"00";
++ sr_write_ena <= false;
++ ifr_write_ena <= false;
++ ier_write_ena <= false;
++
++ if (cs = '1') and (I_RW_L = '0') then
++ load_data <= I_DATA;
++ case I_RS is
++ when x"4" => r_t1l_l <= I_DATA;
++ when x"5" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
++ t1_load_counter <= true;
++
++ when x"6" => r_t1l_l <= I_DATA;
++ when x"7" => r_t1l_h <= I_DATA; t1_w_reset_int <= true;
++
++ when x"8" => r_t2l_l <= I_DATA;
++ when x"9" => r_t2l_h <= I_DATA; t2_w_reset_int <= true;
++ t2_load_counter <= true;
++
++ when x"A" => sr_write_ena <= true;
++ when x"D" => ifr_write_ena <= true;
++ when x"E" => ier_write_ena <= true;
++
++ when others => null;
++ end case;
++ end if;
++ end if;
++ end process;
++
++ p_oe : process(cs, I_RW_L)
++ begin
++ O_DATA_OE_L <= '1';
++ if (cs = '1') and (I_RW_L = '1') then
++ O_DATA_OE_L <= '0';
++ end if;
++ end process;
++
++ p_read : process
++ begin
++ wait until rising_edge(CLK);
++
++ if ENA_4 = '1' then
++ t1_r_reset_int <= false;
++ t2_r_reset_int <= false;
++ sr_read_ena <= false;
++ r_irb_hs <= '0';
++ r_ira_hs <= '0';
++
++ if (cs = '1') and (I_RW_L = '1') then
++ case I_RS is
++ --when x"0" => O_DATA <= r_irb; r_irb_hs <= '1';
++ -- fix from Mark McDougall, untested
++ when x"0" => O_DATA <= (r_irb and not r_ddrb) or (r_orb and r_ddrb); r_irb_hs <= '1';
++ when x"1" => O_DATA <= r_ira; r_ira_hs <= '1';
++ when x"2" => O_DATA <= r_ddrb;
++ when x"3" => O_DATA <= r_ddra;
++ when x"4" => O_DATA <= t1c( 7 downto 0); t1_r_reset_int <= true;
++ when x"5" => O_DATA <= t1c(15 downto 8);
++ when x"6" => O_DATA <= r_t1l_l;
++ when x"7" => O_DATA <= r_t1l_h;
++ when x"8" => O_DATA <= t2c( 7 downto 0); t2_r_reset_int <= true;
++ when x"9" => O_DATA <= t2c(15 downto 8);
++ when x"A" => O_DATA <= r_sr; sr_read_ena <= true;
++ when x"B" => O_DATA <= r_acr;
++ when x"C" => O_DATA <= r_pcr;
++ when x"D" => O_DATA <= r_ifr;
++ when x"E" => O_DATA <= ('0' & r_ier);
++ when x"F" => O_DATA <= r_ira;
++ when others => null;
++ end case;
++ end if;
++ end if;
++
++ end process;
++ --
++ -- IO
++ --
++ p_ca1_cb1_sel : process(sr_cb1_oe_l, sr_cb1_out, I_CB1)
++ begin
++ -- if the shift register is enabled, cb1 may be an output
++ -- in this case, we should listen to the CB1_OUT for the interrupt
++ if (sr_cb1_oe_l = '1') then
++ cb1_in_mux <= I_CB1;
++ else
++ cb1_in_mux <= sr_cb1_out;
++ end if;
++ end process;
++
++ p_ca1_cb1_int : process(r_pcr, ca1_ip_reg, I_CA1, cb1_ip_reg, cb1_in_mux)
++ begin
++ if (r_pcr(0) = '0') then -- ca1 control
++ -- negative edge
++ ca1_int <= (ca1_ip_reg = '1') and (I_CA1 = '0');
++ else
++ -- positive edge
++ ca1_int <= (ca1_ip_reg = '0') and (I_CA1 = '1');
++ end if;
++
++ if (r_pcr(4) = '0') then -- cb1 control
++ -- negative edge
++ cb1_int <= (cb1_ip_reg = '1') and (cb1_in_mux = '0');
++ else
++ -- positive edge
++ cb1_int <= (cb1_ip_reg = '0') and (cb1_in_mux = '1');
++ end if;
++ end process;
++
++ p_ca2_cb2_int : process(r_pcr, ca2_ip_reg, I_CA2, cb2_ip_reg, I_CB2)
++ begin
++ ca2_int <= false;
++ if (r_pcr(3) = '0') then -- ca2 input
++ if (r_pcr(2) = '0') then -- ca2 edge
++ -- negative edge
++ ca2_int <= (ca2_ip_reg = '1') and (I_CA2 = '0');
++ else
++ -- positive edge
++ ca2_int <= (ca2_ip_reg = '0') and (I_CA2 = '1');
++ end if;
++ end if;
++
++ cb2_int <= false;
++ if (r_pcr(7) = '0') then -- cb2 input
++ if (r_pcr(6) = '0') then -- cb2 edge
++ -- negative edge
++ cb2_int <= (cb2_ip_reg = '1') and (I_CB2 = '0');
++ else
++ -- positive edge
++ cb2_int <= (cb2_ip_reg = '0') and (I_CB2 = '1');
++ end if;
++ end if;
++ end process;
++
++ p_ca2_cb2 : process(RESET_L, CLK)
++ begin
++ if (RESET_L = '0') then
++ O_CA2 <= '0';
++ O_CA2_OE_L <= '1';
++ O_CB2 <= '0';
++ O_CB2_OE_L <= '1';
++
++ ca_hs_sr <= '0';
++ ca_hs_pulse <= '0';
++ cb_hs_sr <= '0';
++ cb_hs_pulse <= '0';
++ elsif rising_edge(CLK) then
++ if (ENA_4 = '1') then
++ -- ca
++ if (phase = "00") and ((w_ora_hs = '1') or (r_ira_hs = '1')) then
++ ca_hs_sr <= '1';
++ elsif ca1_int then
++ ca_hs_sr <= '0';
++ end if;
++
++ if (phase = "00") then
++ ca_hs_pulse <= w_ora_hs or r_ira_hs;
++ end if;
++
++ O_CA2_OE_L <= not r_pcr(3); -- ca2 output
++ case r_pcr(3 downto 1) is
++ when "000" => O_CA2 <= '0'; -- input
++ when "001" => O_CA2 <= '0'; -- input
++ when "010" => O_CA2 <= '0'; -- input
++ when "011" => O_CA2 <= '0'; -- input
++ when "100" => O_CA2 <= not (ca_hs_sr); -- handshake
++ when "101" => O_CA2 <= not (ca_hs_pulse); -- pulse
++ when "110" => O_CA2 <= '0'; -- low
++ when "111" => O_CA2 <= '1'; -- high
++ when others => null;
++ end case;
++
++ -- cb
++ if (phase = "00") and (w_orb_hs = '1') then
++ cb_hs_sr <= '1';
++ elsif cb1_int then
++ cb_hs_sr <= '0';
++ end if;
++
++ if (phase = "00") then
++ cb_hs_pulse <= w_orb_hs;
++ end if;
++
++ O_CB2_OE_L <= not (r_pcr(7) or sr_drive_cb2); -- cb2 output or serial
++ if (sr_drive_cb2 = '1') then -- serial output
++ O_CB2 <= sr_out;
++ else
++ case r_pcr(7 downto 5) is
++ when "000" => O_CB2 <= '0'; -- input
++ when "001" => O_CB2 <= '0'; -- input
++ when "010" => O_CB2 <= '0'; -- input
++ when "011" => O_CB2 <= '0'; -- input
++ when "100" => O_CB2 <= not (cb_hs_sr); -- handshake
++ when "101" => O_CB2 <= not (cb_hs_pulse); -- pulse
++ when "110" => O_CB2 <= '0'; -- low
++ when "111" => O_CB2 <= '1'; -- high
++ when others => null;
++ end case;
++ end if;
++ end if;
++ end if;
++ end process;
++ O_CB1 <= sr_cb1_out;
++ O_CB1_OE_L <= sr_cb1_oe_l;
++
++ p_ca_cb_irq : process(RESET_L, CLK)
++ begin
++ if (RESET_L = '0') then
++ ca1_irq <= '0';
++ ca2_irq <= '0';
++ cb1_irq <= '0';
++ cb2_irq <= '0';
++ elsif rising_edge(CLK) then
++ if (ENA_4 = '1') then
++ -- not pretty
++ if ca1_int then
++ ca1_irq <= '1';
++ elsif (r_ira_hs = '1') or (w_ora_hs = '1') or (clear_irq(1) = '1') then
++ ca1_irq <= '0';
++ end if;
++
++ if ca2_int then
++ ca2_irq <= '1';
++ else
++ if (((r_ira_hs = '1') or (w_ora_hs = '1')) and (r_pcr(1) = '0')) or
++ (clear_irq(0) = '1') then
++ ca2_irq <= '0';
++ end if;
++ end if;
++
++ if cb1_int then
++ cb1_irq <= '1';
++ elsif (r_irb_hs = '1') or (w_orb_hs = '1') or (clear_irq(4) = '1') then
++ cb1_irq <= '0';
++ end if;
++
++ if cb2_int then
++ cb2_irq <= '1';
++ else
++ if (((r_irb_hs = '1') or (w_orb_hs = '1')) and (r_pcr(5) = '0')) or
++ (clear_irq(3) = '1') then
++ cb2_irq <= '0';
++ end if;
++ end if;
++ end if;
++ end if;
++ end process;
++
++ p_input_reg : process(RESET_L, CLK)
++ begin
++ if (RESET_L = '0') then
++ ca1_ip_reg <= '0';
++ cb1_ip_reg <= '0';
++
++ ca2_ip_reg <= '0';
++ cb2_ip_reg <= '0';
++
++ r_ira <= x"00";
++ r_irb <= x"00";
++
++ elsif rising_edge(CLK) then
++ if (ENA_4 = '1') then
++ -- we have a fast clock, so we can have input registers
++ ca1_ip_reg <= I_CA1;
++ cb1_ip_reg <= cb1_in_mux;
++
++ ca2_ip_reg <= I_CA2;
++ cb2_ip_reg <= I_CB2;
++
++ if (r_acr(0) = '0') then
++ r_ira <= I_PA;
++ else -- enable latching
++ if ca1_int then
++ r_ira <= I_PA;
++ end if;
++ end if;
++
++ if (r_acr(1) = '0') then
++ r_irb <= I_PB;
++ else -- enable latching
++ if cb1_int then
++ r_irb <= I_PB;
++ end if;
++ end if;
++ end if;
++ end if;
++ end process;
++
++
++ p_buffers : process(r_ddra, r_ora, r_ddrb, r_acr, r_orb)
++ begin
++ -- data direction reg (ddr) 0 = input, 1 = output
++ O_PA <= r_ora;
++ O_PA_OE_L <= not r_ddra;
++
++ if (r_acr(7) = '1') then -- not clear if r_ddrb(7) must be 1 as well
++ O_PB_OE_L(7) <= '0'; -- an output if under t1 control
++ else
++ O_PB_OE_L(7) <= not (r_ddrb(7));
++ end if;
++
++ O_PB_OE_L(6 downto 0) <= not r_ddrb(6 downto 0);
++ O_PB(7 downto 0) <= r_orb(7 downto 0);
++
++ end process;
++ --
++ -- Timer 1
++ --
++ p_timer1_done : process(t1c,phase,r_acr)
++ variable done : boolean;
++ begin
++ done := (t1c = x"0000");
++ t1c_done <= done and (phase = "11");
++ --if (phase = "11") then
++ t1_reload_counter <= done and (r_acr(6) = '1');
++ --end if;
++ end process;
++
++ p_timer1 : process
++ begin
++ wait until rising_edge(CLK);
++ if (ENA_4 = '1') then
++ if t1_load_counter or (t1_reload_counter and phase = "11") then
++ t1c( 7 downto 0) <= r_t1l_l;
++ t1c(15 downto 8) <= r_t1l_h;
++ elsif (phase="11") then
++ t1c <= t1c - "1";
++ end if;
++
++ if t1_load_counter or t1_reload_counter then
++ t1c_active <= true;
++ elsif t1c_done then
++ t1c_active <= false;
++ end if;
++ if RESET_L = '0' then
++ t1c_active <= false;
++ end if;
++
++ t1_toggle <= '0';
++ if t1c_active and t1c_done then
++ t1_toggle <= '1';
++ t1_irq <= '1';
++ elsif RESET_L = '0' or t1_w_reset_int or t1_r_reset_int or (clear_irq(6) = '1') then
++ t1_irq <= '0';
++ end if;
++ end if;
++ end process;
++ --
++ -- Timer2
++ --
++ p_timer2_pb6_input : process
++ begin
++ wait until rising_edge(CLK);
++ if (ENA_4 = '1') then
++ if (phase = "01") then -- leading edge p2_h
++ t2_pb6 <= I_PB(6);
++ t2_pb6_t1 <= t2_pb6;
++ end if;
++ end if;
++ end process;
++
++ p_timer2_done : process(t2c,phase)
++ variable done : boolean;
++ begin
++ done := (t2c = x"0000");
++ t2c_done <= done and (phase = "11");
++ --if (phase = "11") then
++ t2_reload_counter <= done;
++ --end if;
++ end process;
++
++ p_timer2 : process
++ variable ena : boolean;
++ begin
++ wait until rising_edge(CLK);
++ if (ENA_4 = '1') then
++ if (r_acr(5) = '0') then
++ ena := true;
++ else
++ ena := (t2_pb6_t1 = '1') and (t2_pb6 = '0'); -- falling edge
++ end if;
++
++ if t2_load_counter or (t2_reload_counter and phase = "11") then
++ -- not sure if t2c_reload should be here. Does timer2 just continue to
++ -- count down, or is it reloaded ? Reloaded makes more sense if using
++ -- it to generate a clock for the shift register.
++ t2c( 7 downto 0) <= r_t2l_l;
++ t2c(15 downto 8) <= r_t2l_h;
++ else
++ if (phase="11") and ena then -- or count mode
++ t2c <= t2c - "1";
++ end if;
++ end if;
++
++ t2_sr_ena <= (t2c(7 downto 0) = x"00") and (phase = "11");
++
++ if t2_load_counter then
++ t2c_active <= true;
++ elsif t2c_done then
++ t2c_active <= false;
++ end if;
++ if RESET_L = '0' then
++ t2c_active <= false;
++ end if;
++
++ if t2c_active and t2c_done then
++ t2_irq <= '1';
++ elsif RESET_L = '0' or t2_w_reset_int or t2_r_reset_int or (clear_irq(5) = '1') then
++ t2_irq <= '0';
++ end if;
++ end if;
++ end process;
++ --
++ -- Shift Register
++ --
++ p_sr : process(RESET_L, CLK)
++ variable dir_out : std_logic;
++ variable ena : std_logic;
++ variable cb1_op : std_logic;
++ variable cb1_ip : std_logic;
++ variable use_t2 : std_logic;
++ variable free_run : std_logic;
++ variable sr_count_ena : boolean;
++ begin
++ if (RESET_L = '0') then
++ r_sr <= x"00";
++ sr_drive_cb2 <= '0';
++ sr_cb1_oe_l <= '1';
++ sr_cb1_out <= '0';
++ sr_strobe <= '1';
++ sr_cnt <= "0000";
++ sr_irq <= '0';
++ sr_out <= '1';
++ sr_off_delay <= '0';
++ elsif rising_edge(CLK) then
++ if (ENA_4 = '1') then
++ -- decode mode
++ dir_out := r_acr(4); -- output on cb2
++ cb1_op := '0';
++ cb1_ip := '0';
++ use_t2 := '0';
++ free_run := '0';
++
++ case r_acr(4 downto 2) is
++ when "000" => ena := '0'; cb1_ip := '1';
++ when "001" => ena := '1'; cb1_op := '1'; use_t2 := '1';
++ when "010" => ena := '1'; cb1_op := '1';
++ when "011" => ena := '1'; cb1_ip := '1';
++ when "100" => ena := '1'; use_t2 := '1'; free_run := '1';
++ when "101" => ena := '1'; cb1_op := '1'; use_t2 := '1';
++ when "110" => ena := '1';
++ when "111" => ena := '1'; cb1_ip := '1';
++ when others => null;
++ end case;
++
++ -- clock select
++ -- 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
++ if (cb1_ip = '1') then
++ sr_strobe <= I_CB1;
++ else
++ if (sr_cnt(3) = '0') and (free_run = '0') then
++ sr_strobe <= '1';
++ else
++ if ((use_t2 = '1') and t2_sr_ena) or
++ ((use_t2 = '0') and (phase = "00")) then
++ sr_strobe <= not sr_strobe;
++ end if;
++ end if;
++ end if;
++
++ -- latch on rising edge, shift on falling edge
++ if sr_write_ena then
++ r_sr <= load_data;
++ else
++ if (dir_out = '0') then
++ -- input
++ if (sr_cnt(3) = '1') or (cb1_ip = '1') then
++ if sr_strobe_rising then
++ r_sr <= r_sr(6 downto 0) & I_CB2;
++ end if;
++ end if;
++ sr_out <= '1';
++ else
++ -- output
++ if (sr_cnt(3) = '1') or (sr_off_delay = '1') or (cb1_ip = '1') or (free_run = '1') then
++ if sr_strobe_falling then
++ r_sr(7 downto 1) <= r_sr(6 downto 0);
++ r_sr(0) <= r_sr(7);
++ sr_out <= r_sr(7);
++ end if;
++ else
++ sr_out <= '1';
++ end if;
++ end if;
++ end if;
++
++ sr_count_ena := sr_strobe_rising;
++
++ if sr_write_ena or sr_read_ena then
++ -- some documentation says sr bit in IFR must be set as well ?
++ sr_cnt <= "1000";
++ elsif sr_count_ena and (sr_cnt(3) = '1') then
++ sr_cnt <= sr_cnt + "1";
++ end if;
++
++ if (phase = "00") then
++ sr_off_delay <= sr_cnt(3); -- give some hold time when shifting out
++ end if;
++
++ if sr_count_ena and (sr_cnt = "1111") and (ena = '1') and (free_run = '0') then
++ sr_irq <= '1';
++ elsif sr_write_ena or sr_read_ena or (clear_irq(2) = '1') then
++ sr_irq <= '0';
++ end if;
++
++ -- assign ops
++ sr_drive_cb2 <= dir_out;
++ sr_cb1_oe_l <= not cb1_op;
++ sr_cb1_out <= sr_strobe;
++ end if;
++ end if;
++ end process;
++
++ p_sr_strobe_rise_fall : process
++ begin
++ wait until rising_edge(CLK);
++ if (ENA_4 = '1') then
++ sr_strobe_t1 <= sr_strobe;
++ sr_strobe_rising <= (sr_strobe_t1 = '0') and (sr_strobe = '1');
++ sr_strobe_falling <= (sr_strobe_t1 = '1') and (sr_strobe = '0');
++ end if;
++ end process;
++ --
++ -- Interrupts
++ --
++ p_ier : process(RESET_L, CLK)
++ begin
++ if (RESET_L = '0') then
++ r_ier <= "0000000";
++ elsif rising_edge(CLK) then
++ if (ENA_4 = '1') then
++ if ier_write_ena then
++ if (load_data(7) = '1') then
++ -- set
++ r_ier <= r_ier or load_data(6 downto 0);
++ else
++ -- clear
++ r_ier <= r_ier and not load_data(6 downto 0);
++ end if;
++ end if;
++ end if;
++ end if;
++ end process;
++
++ p_ifr : process(t1_irq, t2_irq, final_irq, ca1_irq, ca2_irq, sr_irq,
++ cb1_irq, cb2_irq)
++ begin
++ r_ifr(7) <= final_irq;
++ r_ifr(6) <= t1_irq;
++ r_ifr(5) <= t2_irq;
++ r_ifr(4) <= cb1_irq;
++ r_ifr(3) <= cb2_irq;
++ r_ifr(2) <= sr_irq;
++ r_ifr(1) <= ca1_irq;
++ r_ifr(0) <= ca2_irq;
++
++ O_IRQ_L <= not final_irq;
++ end process;
++
++ p_irq : process(RESET_L, CLK)
++ begin
++ if (RESET_L = '0') then
++ final_irq <= '0';
++ elsif rising_edge(CLK) then
++ if (ENA_4 = '1') then
++ if ((r_ifr(6 downto 0) and r_ier(6 downto 0)) = "0000000") then
++ final_irq <= '0'; -- no interrupts
++ else
++ final_irq <= '1';
++ end if;
++ end if;
++ end if;
++ end process;
++
++ p_clear_irq : process(ifr_write_ena, load_data)
++ begin
++ clear_irq <= x"00";
++ if ifr_write_ena then
++ clear_irq <= load_data;
++ end if;
++ end process;
++
++end architecture RTL;
+diff --git a/m6522_tb.vhd b/m6522_tb.vhd
+index 3e4262d..30307d2 100644
+--- a/m6522_tb.vhd
++++ b/m6522_tb.vhd
+@@ -1,378 +1,378 @@
+--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+-
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity m6522_tb is
+-end entity;
+-
+-architecture tb of m6522_tb is
+-
+-component M6522 is
+- port (
+-
+- I_RS : in std_logic_vector(3 downto 0);
+- I_DATA : in std_logic_vector(7 downto 0);
+- O_DATA : out std_logic_vector(7 downto 0);
+- O_DATA_OE_L : out std_logic;
+-
+- I_RW_L : in std_logic;
+- I_CS1 : in std_logic;
+- I_CS2_L : in std_logic;
+-
+- O_IRQ_L : out std_logic; -- note, not open drain
+- -- port a
+- I_CA1 : in std_logic;
+- I_CA2 : in std_logic;
+- O_CA2 : out std_logic;
+- O_CA2_OE_L : out std_logic;
+-
+- I_PA : in std_logic_vector(7 downto 0);
+- O_PA : out std_logic_vector(7 downto 0);
+- O_PA_OE_L : out std_logic_vector(7 downto 0);
+-
+- -- port b
+- I_CB1 : in std_logic;
+- O_CB1 : out std_logic;
+- O_CB1_OE_L : out std_logic;
+-
+- I_CB2 : in std_logic;
+- O_CB2 : out std_logic;
+- O_CB2_OE_L : out std_logic;
+-
+- I_PB : in std_logic_vector(7 downto 0);
+- O_PB : out std_logic_vector(7 downto 0);
+- O_PB_OE_L : out std_logic_vector(7 downto 0);
+-
+- I_P2_H : in std_logic; -- high for phase 2 clock ____----__
+- RESET_L : in std_logic;
+- ENA_4 : in std_logic; -- clk enable
+- CLK : in std_logic
+- );
+-end component;
+-
+-signal rs : std_logic_vector(3 downto 0) := "0000";
+-signal di : std_logic_vector(7 downto 0) := "00000000";
+-signal do : std_logic_vector(7 downto 0);
+-signal n_d_oe : std_logic;
+-signal r_nw : std_logic := '1';
+-signal cs1 : std_logic := '0';
+-signal n_cs2 : std_logic := '0';
+-signal n_irq : std_logic;
+-signal ca1_in : std_logic := '0';
+-signal ca2_in : std_logic := '0';
+-signal ca2_out : std_logic;
+-signal n_ca2_oe : std_logic;
+-signal pa_in : std_logic_vector(7 downto 0) := "00000000";
+-signal pa_out : std_logic_vector(7 downto 0);
+-signal n_pa_oe : std_logic_vector(7 downto 0);
+-signal cb1_in : std_logic := '0';
+-signal cb1_out : std_logic;
+-signal n_cb1_oe : std_logic;
+-signal cb2_in : std_logic := '0';
+-signal cb2_out : std_logic;
+-signal n_cb2_oe : std_logic;
+-signal pb_in : std_logic_vector(7 downto 0) := "00000000";
+-signal pb_out : std_logic_vector(7 downto 0);
+-signal n_pb_oe : std_logic_vector(7 downto 0);
+-
+-signal phase2 : std_logic := '0';
+-signal n_reset : std_logic := '0';
+-signal clken : std_logic := '0';
+-signal clock : std_logic := '0';
+-
+-begin
+-
+- uut: m6522 port map (
+- rs, di, do, n_d_oe,
+- r_nw, cs1, n_cs2, n_irq,
+- ca1_in, ca2_in, ca2_out, n_ca2_oe,
+- pa_in, pa_out, n_pa_oe,
+- cb1_in, cb1_out, n_cb1_oe,
+- cb2_in, cb2_out, n_cb2_oe,
+- pb_in, pb_out, n_pb_oe,
+- phase2, n_reset, clken, clock
+- );
+-
+- clock <= not clock after 125 ns; -- 4x 1 MHz
+- phase2 <= not phase2 after 500 ns;
+- clken <= '1'; -- all cycles enabled
+-
+- process
+- begin
+- wait for 1 us;
+- -- Release reset
+- n_reset <= '1';
+- end process;
+-
+- process
+-
+- procedure reg_write(
+- a : in std_logic_vector(3 downto 0);
+- d : in std_logic_vector(7 downto 0)) is
+- begin
+- wait until falling_edge(phase2);
+- rs <= a;
+- di <= d;
+- cs1 <= '1';
+- r_nw <= '0';
+- wait until falling_edge(phase2);
+- cs1 <= '0';
+- r_nw <= '1';
+- end procedure;
+-
+- procedure reg_read(
+- a : in std_logic_vector(3 downto 0)) is
+- begin
+- wait until falling_edge(phase2);
+- rs <= a;
+- cs1 <= '1';
+- r_nw <= '1';
+- wait until falling_edge(phase2);
+- cs1 <= '0';
+- end procedure;
+-
+- begin
+- wait for 2 us;
+-
+- -- Set port A and B to output
+- reg_write("0010","11111111");
+- reg_write("0011","11111111");
+-
+- -- Write to port B
+- reg_write("0000","10101010");
+- -- Write to port B
+- reg_write("0000","01010101");
+- -- Write to port A (no handshake)
+- reg_write("1111","10101010");
+- -- Write to port A (with handshake)
+- reg_write("0001","01010101");
+-
+- -- Set port A and B to input
+- reg_write("0010","00000000");
+- reg_write("0011","00000000");
+-
+- -- Apply input stimuli and read from ports
+- pa_in <= "10101010";
+- pb_in <= "01010101";
+- reg_read("0000");
+- reg_read("0001");
+-
+- -- Test CA1 interrupt
+- ca1_in <= '0';
+- reg_write("1100","00000001"); -- PCR - interrupt on rising edge
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","10000010"); -- Enable CA1 interrupt
+- ca1_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0001"); -- Should clear interrupt
+- wait for 2 us;
+- reg_write("1100","00000000"); -- PCR - interrupt on falling edge
+- ca1_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_write("1101","00000010"); -- Should clear interrupt
+- wait for 2 us;
+- reg_write("1110","00000010"); -- Disable CA1 interrupt
+-
+- -- Test CB1 interrupt
+- cb1_in <= '0';
+- reg_write("1100","00010000"); -- PCR - interrupt on rising edge
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","10010000"); -- Enable CB1 interrupt
+- cb1_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0000"); -- Should clear interrupt
+- wait for 2 us;
+- reg_write("1100","00000000"); -- PCR - interrupt on falling edge
+- cb1_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_write("1101","00010000"); -- Should clear interrupt
+- wait for 2 us;
+- reg_write("1110","00010000"); -- Disable CA1 interrupt
+-
+- -- Test CA2 interrupt modes
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","10000001"); -- Enable CA2 interrupt
+- -- mode 2 (+ve edge, clear on read/write)
+- reg_write("1100","00000100"); -- PCR
+- ca2_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("1111"); -- Should not clear interrupt
+- reg_read("0001"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 0 (-ve edge, clear on read/write)
+- reg_write("1100","00000000"); -- PCR
+- ca2_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("1111"); -- Should not clear interrupt
+- reg_read("0001"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 3 (+ve edge, don't clear on read/write)
+- reg_write("1100","00000110");
+- ca2_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("1111"); -- Should not clear interrupt
+- reg_read("0001"); -- Should not clear interrupt
+- reg_write("1101","00000001"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 1 (-ve edge, don't clear on read/write)
+- reg_write("1100","00000010");
+- ca2_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("1111"); -- Should not clear interrupt
+- reg_read("0001"); -- Should not clear interrupt
+- reg_write("1101","00000001"); -- Should clear interrupt
+- wait for 2 us;
+-
+- -- Test CA2 output modes
+- -- mode 4 (set low on read/write of ORA, set high on CA1 interrupt edge)
+- reg_write("1100","00001000");
+- -- mode 5 (set low for 1 cycle on read/write ORA)
+- reg_write("1100","00001010");
+- -- mode 6 (held low)
+- reg_write("1100","00001100");
+- -- mode 7 (held high)
+- reg_write("1100","00001110");
+-
+- -- Test CB2 interrupt modes
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","10001000"); -- Enable CB2 interrupt
+- -- mode 2 (+ve edge, clear on read/write)
+- reg_write("1100","01000000"); -- PCR
+- cb2_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0000"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 0 (-ve edge, clear on read/write)
+- reg_write("1100","00000000"); -- PCR
+- cb2_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0000"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 3 (+ve edge, don't clear on read/write)
+- reg_write("1100","01100000");
+- cb2_in <= '1'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0000"); -- Should not clear interrupt
+- reg_write("1101","00001000"); -- Should clear interrupt
+- wait for 2 us;
+- -- mode 1 (-ve edge, don't clear on read/write)
+- reg_write("1100","00100000");
+- cb2_in <= '0'; -- Trigger event
+- wait for 2 us;
+- reg_read("1101");
+- reg_read("0000"); -- Should not clear interrupt
+- reg_write("1101","00001000"); -- Should clear interrupt
+- wait for 2 us;
+-
+- -- Test CB2 output modes
+- -- mode 4 (set low on read/write of ORA, set high on CA1 interrupt edge)
+- reg_write("1100","10000000");
+- -- mode 5 (set low for 1 cycle on read/write ORA)
+- reg_write("1100","10100000");
+- -- mode 6 (held low)
+- reg_write("1100","11000000");
+- -- mode 7 (held high)
+- reg_write("1100","11100000");
+-
+- -- Timer 1 timeout
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","11000000"); -- Enable timer 1 interrupt
+- -- Count to 16
+- reg_write("0100","00010000");
+- reg_write("0101","00000000");
+- wait for 50 us;
+- -- Count to 16
+- reg_write("0100","00010000");
+- reg_write("0101","00000000"); -- Should clear interrupt
+- wait for 50 us;
+- reg_read("0100"); -- Should clear interrupt
+-
+- -- Timer 2 timeout
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1110","10100000"); -- Enable timer 2 interrupt
+- -- Count to 16
+- reg_write("1000","00010000");
+- reg_write("1001","00000000");
+- wait for 50 us;
+- -- Count to 16
+- reg_write("1000","00010000");
+- reg_write("1001","00000000"); -- Should clear interrupt
+- wait for 50 us;
+- reg_read("1000"); -- Should clear interrupt
+-
+- -- Timer 2 test similar to BBC usage (speech interrupt)
+- -- PB6 high
+- pb_in(6) <= '1';
+- reg_write("1101","01111111"); -- Clear interrupts
+- reg_write("1110","01111111"); -- Disable all interrupts
+- reg_write("1011","00100000"); -- Timer 2 PB6 counter mode
+- reg_write("1000","00000001"); -- Start at 1
+- reg_write("1001","00000000");
+- reg_write("1110","10100000"); -- Enable timer 2 interrupt
+- wait for 5 us;
+- -- Generate falling edge
+- pb_in(6) <= '0';
+- wait for 5 us;
+- -- Clear interrupt
+- reg_write("1101","00100000");
+- -- Zero timer high byte
+- reg_write("1001","00000000");
+-
+- wait;
+- end process;
+-
+-end architecture;
++-- BBC Micro for Altera DE1
++--
++-- Copyright (c) 2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.NUMERIC_STD.ALL;
++
++entity m6522_tb is
++end entity;
++
++architecture tb of m6522_tb is
++
++component M6522 is
++ port (
++
++ I_RS : in std_logic_vector(3 downto 0);
++ I_DATA : in std_logic_vector(7 downto 0);
++ O_DATA : out std_logic_vector(7 downto 0);
++ O_DATA_OE_L : out std_logic;
++
++ I_RW_L : in std_logic;
++ I_CS1 : in std_logic;
++ I_CS2_L : in std_logic;
++
++ O_IRQ_L : out std_logic; -- note, not open drain
++ -- port a
++ I_CA1 : in std_logic;
++ I_CA2 : in std_logic;
++ O_CA2 : out std_logic;
++ O_CA2_OE_L : out std_logic;
++
++ I_PA : in std_logic_vector(7 downto 0);
++ O_PA : out std_logic_vector(7 downto 0);
++ O_PA_OE_L : out std_logic_vector(7 downto 0);
++
++ -- port b
++ I_CB1 : in std_logic;
++ O_CB1 : out std_logic;
++ O_CB1_OE_L : out std_logic;
++
++ I_CB2 : in std_logic;
++ O_CB2 : out std_logic;
++ O_CB2_OE_L : out std_logic;
++
++ I_PB : in std_logic_vector(7 downto 0);
++ O_PB : out std_logic_vector(7 downto 0);
++ O_PB_OE_L : out std_logic_vector(7 downto 0);
++
++ I_P2_H : in std_logic; -- high for phase 2 clock ____----__
++ RESET_L : in std_logic;
++ ENA_4 : in std_logic; -- clk enable
++ CLK : in std_logic
++ );
++end component;
++
++signal rs : std_logic_vector(3 downto 0) := "0000";
++signal di : std_logic_vector(7 downto 0) := "00000000";
++signal do : std_logic_vector(7 downto 0);
++signal n_d_oe : std_logic;
++signal r_nw : std_logic := '1';
++signal cs1 : std_logic := '0';
++signal n_cs2 : std_logic := '0';
++signal n_irq : std_logic;
++signal ca1_in : std_logic := '0';
++signal ca2_in : std_logic := '0';
++signal ca2_out : std_logic;
++signal n_ca2_oe : std_logic;
++signal pa_in : std_logic_vector(7 downto 0) := "00000000";
++signal pa_out : std_logic_vector(7 downto 0);
++signal n_pa_oe : std_logic_vector(7 downto 0);
++signal cb1_in : std_logic := '0';
++signal cb1_out : std_logic;
++signal n_cb1_oe : std_logic;
++signal cb2_in : std_logic := '0';
++signal cb2_out : std_logic;
++signal n_cb2_oe : std_logic;
++signal pb_in : std_logic_vector(7 downto 0) := "00000000";
++signal pb_out : std_logic_vector(7 downto 0);
++signal n_pb_oe : std_logic_vector(7 downto 0);
++
++signal phase2 : std_logic := '0';
++signal n_reset : std_logic := '0';
++signal clken : std_logic := '0';
++signal clock : std_logic := '0';
++
++begin
++
++ uut: m6522 port map (
++ rs, di, do, n_d_oe,
++ r_nw, cs1, n_cs2, n_irq,
++ ca1_in, ca2_in, ca2_out, n_ca2_oe,
++ pa_in, pa_out, n_pa_oe,
++ cb1_in, cb1_out, n_cb1_oe,
++ cb2_in, cb2_out, n_cb2_oe,
++ pb_in, pb_out, n_pb_oe,
++ phase2, n_reset, clken, clock
++ );
++
++ clock <= not clock after 125 ns; -- 4x 1 MHz
++ phase2 <= not phase2 after 500 ns;
++ clken <= '1'; -- all cycles enabled
++
++ process
++ begin
++ wait for 1 us;
++ -- Release reset
++ n_reset <= '1';
++ end process;
++
++ process
++
++ procedure reg_write(
++ a : in std_logic_vector(3 downto 0);
++ d : in std_logic_vector(7 downto 0)) is
++ begin
++ wait until falling_edge(phase2);
++ rs <= a;
++ di <= d;
++ cs1 <= '1';
++ r_nw <= '0';
++ wait until falling_edge(phase2);
++ cs1 <= '0';
++ r_nw <= '1';
++ end procedure;
++
++ procedure reg_read(
++ a : in std_logic_vector(3 downto 0)) is
++ begin
++ wait until falling_edge(phase2);
++ rs <= a;
++ cs1 <= '1';
++ r_nw <= '1';
++ wait until falling_edge(phase2);
++ cs1 <= '0';
++ end procedure;
++
++ begin
++ wait for 2 us;
++
++ -- Set port A and B to output
++ reg_write("0010","11111111");
++ reg_write("0011","11111111");
++
++ -- Write to port B
++ reg_write("0000","10101010");
++ -- Write to port B
++ reg_write("0000","01010101");
++ -- Write to port A (no handshake)
++ reg_write("1111","10101010");
++ -- Write to port A (with handshake)
++ reg_write("0001","01010101");
++
++ -- Set port A and B to input
++ reg_write("0010","00000000");
++ reg_write("0011","00000000");
++
++ -- Apply input stimuli and read from ports
++ pa_in <= "10101010";
++ pb_in <= "01010101";
++ reg_read("0000");
++ reg_read("0001");
++
++ -- Test CA1 interrupt
++ ca1_in <= '0';
++ reg_write("1100","00000001"); -- PCR - interrupt on rising edge
++ reg_write("1101","01111111"); -- Clear interrupts
++ reg_write("1110","01111111"); -- Disable all interrupts
++ reg_write("1110","10000010"); -- Enable CA1 interrupt
++ ca1_in <= '1'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_read("0001"); -- Should clear interrupt
++ wait for 2 us;
++ reg_write("1100","00000000"); -- PCR - interrupt on falling edge
++ ca1_in <= '0'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_write("1101","00000010"); -- Should clear interrupt
++ wait for 2 us;
++ reg_write("1110","00000010"); -- Disable CA1 interrupt
++
++ -- Test CB1 interrupt
++ cb1_in <= '0';
++ reg_write("1100","00010000"); -- PCR - interrupt on rising edge
++ reg_write("1101","01111111"); -- Clear interrupts
++ reg_write("1110","01111111"); -- Disable all interrupts
++ reg_write("1110","10010000"); -- Enable CB1 interrupt
++ cb1_in <= '1'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_read("0000"); -- Should clear interrupt
++ wait for 2 us;
++ reg_write("1100","00000000"); -- PCR - interrupt on falling edge
++ cb1_in <= '0'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_write("1101","00010000"); -- Should clear interrupt
++ wait for 2 us;
++ reg_write("1110","00010000"); -- Disable CA1 interrupt
++
++ -- Test CA2 interrupt modes
++ reg_write("1101","01111111"); -- Clear interrupts
++ reg_write("1110","01111111"); -- Disable all interrupts
++ reg_write("1110","10000001"); -- Enable CA2 interrupt
++ -- mode 2 (+ve edge, clear on read/write)
++ reg_write("1100","00000100"); -- PCR
++ ca2_in <= '1'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_read("1111"); -- Should not clear interrupt
++ reg_read("0001"); -- Should clear interrupt
++ wait for 2 us;
++ -- mode 0 (-ve edge, clear on read/write)
++ reg_write("1100","00000000"); -- PCR
++ ca2_in <= '0'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_read("1111"); -- Should not clear interrupt
++ reg_read("0001"); -- Should clear interrupt
++ wait for 2 us;
++ -- mode 3 (+ve edge, don't clear on read/write)
++ reg_write("1100","00000110");
++ ca2_in <= '1'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_read("1111"); -- Should not clear interrupt
++ reg_read("0001"); -- Should not clear interrupt
++ reg_write("1101","00000001"); -- Should clear interrupt
++ wait for 2 us;
++ -- mode 1 (-ve edge, don't clear on read/write)
++ reg_write("1100","00000010");
++ ca2_in <= '0'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_read("1111"); -- Should not clear interrupt
++ reg_read("0001"); -- Should not clear interrupt
++ reg_write("1101","00000001"); -- Should clear interrupt
++ wait for 2 us;
++
++ -- Test CA2 output modes
++ -- mode 4 (set low on read/write of ORA, set high on CA1 interrupt edge)
++ reg_write("1100","00001000");
++ -- mode 5 (set low for 1 cycle on read/write ORA)
++ reg_write("1100","00001010");
++ -- mode 6 (held low)
++ reg_write("1100","00001100");
++ -- mode 7 (held high)
++ reg_write("1100","00001110");
++
++ -- Test CB2 interrupt modes
++ reg_write("1101","01111111"); -- Clear interrupts
++ reg_write("1110","01111111"); -- Disable all interrupts
++ reg_write("1110","10001000"); -- Enable CB2 interrupt
++ -- mode 2 (+ve edge, clear on read/write)
++ reg_write("1100","01000000"); -- PCR
++ cb2_in <= '1'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_read("0000"); -- Should clear interrupt
++ wait for 2 us;
++ -- mode 0 (-ve edge, clear on read/write)
++ reg_write("1100","00000000"); -- PCR
++ cb2_in <= '0'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_read("0000"); -- Should clear interrupt
++ wait for 2 us;
++ -- mode 3 (+ve edge, don't clear on read/write)
++ reg_write("1100","01100000");
++ cb2_in <= '1'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_read("0000"); -- Should not clear interrupt
++ reg_write("1101","00001000"); -- Should clear interrupt
++ wait for 2 us;
++ -- mode 1 (-ve edge, don't clear on read/write)
++ reg_write("1100","00100000");
++ cb2_in <= '0'; -- Trigger event
++ wait for 2 us;
++ reg_read("1101");
++ reg_read("0000"); -- Should not clear interrupt
++ reg_write("1101","00001000"); -- Should clear interrupt
++ wait for 2 us;
++
++ -- Test CB2 output modes
++ -- mode 4 (set low on read/write of ORA, set high on CA1 interrupt edge)
++ reg_write("1100","10000000");
++ -- mode 5 (set low for 1 cycle on read/write ORA)
++ reg_write("1100","10100000");
++ -- mode 6 (held low)
++ reg_write("1100","11000000");
++ -- mode 7 (held high)
++ reg_write("1100","11100000");
++
++ -- Timer 1 timeout
++ reg_write("1101","01111111"); -- Clear interrupts
++ reg_write("1110","01111111"); -- Disable all interrupts
++ reg_write("1110","11000000"); -- Enable timer 1 interrupt
++ -- Count to 16
++ reg_write("0100","00010000");
++ reg_write("0101","00000000");
++ wait for 50 us;
++ -- Count to 16
++ reg_write("0100","00010000");
++ reg_write("0101","00000000"); -- Should clear interrupt
++ wait for 50 us;
++ reg_read("0100"); -- Should clear interrupt
++
++ -- Timer 2 timeout
++ reg_write("1101","01111111"); -- Clear interrupts
++ reg_write("1110","01111111"); -- Disable all interrupts
++ reg_write("1110","10100000"); -- Enable timer 2 interrupt
++ -- Count to 16
++ reg_write("1000","00010000");
++ reg_write("1001","00000000");
++ wait for 50 us;
++ -- Count to 16
++ reg_write("1000","00010000");
++ reg_write("1001","00000000"); -- Should clear interrupt
++ wait for 50 us;
++ reg_read("1000"); -- Should clear interrupt
++
++ -- Timer 2 test similar to BBC usage (speech interrupt)
++ -- PB6 high
++ pb_in(6) <= '1';
++ reg_write("1101","01111111"); -- Clear interrupts
++ reg_write("1110","01111111"); -- Disable all interrupts
++ reg_write("1011","00100000"); -- Timer 2 PB6 counter mode
++ reg_write("1000","00000001"); -- Start at 1
++ reg_write("1001","00000000");
++ reg_write("1110","10100000"); -- Enable timer 2 interrupt
++ wait for 5 us;
++ -- Generate falling edge
++ pb_in(6) <= '0';
++ wait for 5 us;
++ -- Clear interrupt
++ reg_write("1101","00100000");
++ -- Zero timer high byte
++ reg_write("1001","00000000");
++
++ wait;
++ end process;
++
++end architecture;
+diff --git a/mc6845.vhd b/mc6845.vhd
+index 31208ea..c102501 100644
+--- a/mc6845.vhd
++++ b/mc6845.vhd
+@@ -1,481 +1,481 @@
+--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- MC6845 CRTC
+---
+--- Synchronous implementation for FPGA
+---
+--- (C) 2011 Mike Stirling
+---
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity mc6845 is
+-port (
+- CLOCK : in std_logic;
+- CLKEN : in std_logic;
+- nRESET : in std_logic;
+-
+- -- Bus interface
+- ENABLE : in std_logic;
+- R_nW : in std_logic;
+- RS : in std_logic;
+- DI : in std_logic_vector(7 downto 0);
+- DO : out std_logic_vector(7 downto 0);
+-
+- -- Display interface
+- VSYNC : out std_logic;
+- HSYNC : out std_logic;
+- DE : out std_logic;
+- CURSOR : out std_logic;
+- LPSTB : in std_logic;
+-
+- -- Memory interface
+- MA : out std_logic_vector(13 downto 0);
+- RA : out std_logic_vector(4 downto 0)
+- );
+-end entity;
+-
+-architecture rtl of mc6845 is
+-
+--- Host-accessible registers
+-signal addr_reg : std_logic_vector(4 downto 0); -- Currently addressed register
+--- These are write-only
+-signal r00_h_total : unsigned(7 downto 0); -- Horizontal total, chars
+-signal r01_h_displayed : unsigned(7 downto 0); -- Horizontal active, chars
+-signal r02_h_sync_pos : unsigned(7 downto 0); -- Horizontal sync position, chars
+-signal r03_v_sync_width : unsigned(3 downto 0); -- Vertical sync width, scan lines (0=16 lines)
+-signal r03_h_sync_width : unsigned(3 downto 0); -- Horizontal sync width, chars (0=no sync)
+-signal r04_v_total : unsigned(6 downto 0); -- Vertical total, character rows
+-signal r05_v_total_adj : unsigned(4 downto 0); -- Vertical offset, scan lines
+-signal r06_v_displayed : unsigned(6 downto 0); -- Vertical active, character rows
+-signal r07_v_sync_pos : unsigned(6 downto 0); -- Vertical sync position, character rows
+-signal r08_interlace : std_logic_vector(1 downto 0);
+-signal r09_max_scan_line_addr : unsigned(4 downto 0);
+-signal r10_cursor_mode : std_logic_vector(1 downto 0);
+-signal r10_cursor_start : unsigned(4 downto 0); -- Cursor start, scan lines
+-signal r11_cursor_end : unsigned(4 downto 0); -- Cursor end, scan lines
+-signal r12_start_addr_h : unsigned(5 downto 0);
+-signal r13_start_addr_l : unsigned(7 downto 0);
+--- These are read/write
+-signal r14_cursor_h : unsigned(5 downto 0);
+-signal r15_cursor_l : unsigned(7 downto 0);
+--- These are read-only
+-signal r16_light_pen_h : unsigned(5 downto 0);
+-signal r17_light_pen_l : unsigned(7 downto 0);
+-
+-
+--- Timing generation
+--- Horizontal counter counts position on line
+-signal h_counter : unsigned(7 downto 0);
+--- HSYNC counter counts duration of sync pulse
+-signal h_sync_counter : unsigned(3 downto 0);
+--- Row counter counts current character row
+-signal row_counter : unsigned(6 downto 0);
+--- Line counter counts current line within each character row
+-signal line_counter : unsigned(4 downto 0);
+--- VSYNC counter counts duration of sync pulse
+-signal v_sync_counter : unsigned(3 downto 0);
+--- Field counter counts number of complete fields for cursor flash
+-signal field_counter : unsigned(5 downto 0);
+-
+--- Internal signals
+-signal h_sync_start : std_logic;
+-signal h_half_way : std_logic;
+-signal h_display : std_logic;
+-signal hs : std_logic;
+-signal v_display : std_logic;
+-signal vs : std_logic;
+-signal odd_field : std_logic;
+-signal ma_i : unsigned(13 downto 0);
+-signal ma_row_start : unsigned(13 downto 0); -- Start address of current character row
+-signal cursor_i : std_logic;
+-signal lpstb_i : std_logic;
+-
+-
+-begin
+- HSYNC <= hs; -- External HSYNC driven directly from internal signal
++-- BBC Micro for Altera DE1
++--
++-- Copyright (c) 2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++-- MC6845 CRTC
++--
++-- Synchronous implementation for FPGA
++--
++-- (C) 2011 Mike Stirling
++--
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.NUMERIC_STD.ALL;
++
++entity mc6845 is
++port (
++ CLOCK : in std_logic;
++ CLKEN : in std_logic;
++ nRESET : in std_logic;
++
++ -- Bus interface
++ ENABLE : in std_logic;
++ R_nW : in std_logic;
++ RS : in std_logic;
++ DI : in std_logic_vector(7 downto 0);
++ DO : out std_logic_vector(7 downto 0);
++
++ -- Display interface
++ VSYNC : out std_logic;
++ HSYNC : out std_logic;
++ DE : out std_logic;
++ CURSOR : out std_logic;
++ LPSTB : in std_logic;
++
++ -- Memory interface
++ MA : out std_logic_vector(13 downto 0);
++ RA : out std_logic_vector(4 downto 0)
++ );
++end entity;
++
++architecture rtl of mc6845 is
++
++-- Host-accessible registers
++signal addr_reg : std_logic_vector(4 downto 0); -- Currently addressed register
++-- These are write-only
++signal r00_h_total : unsigned(7 downto 0); -- Horizontal total, chars
++signal r01_h_displayed : unsigned(7 downto 0); -- Horizontal active, chars
++signal r02_h_sync_pos : unsigned(7 downto 0); -- Horizontal sync position, chars
++signal r03_v_sync_width : unsigned(3 downto 0); -- Vertical sync width, scan lines (0=16 lines)
++signal r03_h_sync_width : unsigned(3 downto 0); -- Horizontal sync width, chars (0=no sync)
++signal r04_v_total : unsigned(6 downto 0); -- Vertical total, character rows
++signal r05_v_total_adj : unsigned(4 downto 0); -- Vertical offset, scan lines
++signal r06_v_displayed : unsigned(6 downto 0); -- Vertical active, character rows
++signal r07_v_sync_pos : unsigned(6 downto 0); -- Vertical sync position, character rows
++signal r08_interlace : std_logic_vector(1 downto 0);
++signal r09_max_scan_line_addr : unsigned(4 downto 0);
++signal r10_cursor_mode : std_logic_vector(1 downto 0);
++signal r10_cursor_start : unsigned(4 downto 0); -- Cursor start, scan lines
++signal r11_cursor_end : unsigned(4 downto 0); -- Cursor end, scan lines
++signal r12_start_addr_h : unsigned(5 downto 0);
++signal r13_start_addr_l : unsigned(7 downto 0);
++-- These are read/write
++signal r14_cursor_h : unsigned(5 downto 0);
++signal r15_cursor_l : unsigned(7 downto 0);
++-- These are read-only
++signal r16_light_pen_h : unsigned(5 downto 0);
++signal r17_light_pen_l : unsigned(7 downto 0);
++
++
++-- Timing generation
++-- Horizontal counter counts position on line
++signal h_counter : unsigned(7 downto 0);
++-- HSYNC counter counts duration of sync pulse
++signal h_sync_counter : unsigned(3 downto 0);
++-- Row counter counts current character row
++signal row_counter : unsigned(6 downto 0);
++-- Line counter counts current line within each character row
++signal line_counter : unsigned(4 downto 0);
++-- VSYNC counter counts duration of sync pulse
++signal v_sync_counter : unsigned(3 downto 0);
++-- Field counter counts number of complete fields for cursor flash
++signal field_counter : unsigned(5 downto 0);
++
++-- Internal signals
++signal h_sync_start : std_logic;
++signal h_half_way : std_logic;
++signal h_display : std_logic;
++signal hs : std_logic;
++signal v_display : std_logic;
++signal vs : std_logic;
++signal odd_field : std_logic;
++signal ma_i : unsigned(13 downto 0);
++signal ma_row_start : unsigned(13 downto 0); -- Start address of current character row
++signal cursor_i : std_logic;
++signal lpstb_i : std_logic;
++
++
++begin
++ HSYNC <= hs; -- External HSYNC driven directly from internal signal
+ VSYNC <= vs; -- External VSYNC driven directly from internal signal
+- DE <= h_display and v_display;
+-
+- -- Cursor output generated combinatorially from the internal signal in
+- -- accordance with the currently selected cursor mode
+- CURSOR <= cursor_i when r10_cursor_mode = "00" else
+- '0' when r10_cursor_mode = "01" else
+- (cursor_i and field_counter(4)) when r10_cursor_mode = "10" else
+- (cursor_i and field_counter(5));
+-
+- -- Synchronous register access. Enabled on every clock.
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- -- Reset registers to defaults
+- addr_reg <= (others => '0');
+- r00_h_total <= (others => '0');
+- r01_h_displayed <= (others => '0');
+- r02_h_sync_pos <= (others => '0');
+- r03_v_sync_width <= (others => '0');
+- r03_h_sync_width <= (others => '0');
+- r04_v_total <= (others => '0');
+- r05_v_total_adj <= (others => '0');
+- r06_v_displayed <= (others => '0');
+- r07_v_sync_pos <= (others => '0');
+- r08_interlace <= (others => '0');
+- r09_max_scan_line_addr <= (others => '0');
+- r10_cursor_mode <= (others => '0');
+- r10_cursor_start <= (others => '0');
+- r11_cursor_end <= (others => '0');
+- r12_start_addr_h <= (others => '0');
+- r13_start_addr_l <= (others => '0');
+- r14_cursor_h <= (others => '0');
+- r15_cursor_l <= (others => '0');
+-
+- DO <= (others => '0');
+- elsif rising_edge(CLOCK) then
+- if ENABLE = '1' then
+- if R_nW = '1' then
+- -- Read
+- case addr_reg is
+- when "01110" =>
+- DO <= "00" & std_logic_vector(r14_cursor_h);
+- when "01111" =>
+- DO <= std_logic_vector(r15_cursor_l);
+- when "10000" =>
+- DO <= "00" & std_logic_vector(r16_light_pen_h);
+- when "10001" =>
+- DO <= std_logic_vector(r17_light_pen_l);
+- when others =>
+- DO <= (others => '0');
+- end case;
+- else
+- -- Write
+- if RS = '0' then
+- addr_reg <= DI(4 downto 0);
+- else
+- case addr_reg is
+- when "00000" =>
+- r00_h_total <= unsigned(DI);
+- when "00001" =>
+- r01_h_displayed <= unsigned(DI);
+- when "00010" =>
+- r02_h_sync_pos <= unsigned(DI);
+- when "00011" =>
+- r03_v_sync_width <= unsigned(DI(7 downto 4));
+- r03_h_sync_width <= unsigned(DI(3 downto 0));
+- when "00100" =>
+- r04_v_total <= unsigned(DI(6 downto 0));
+- when "00101" =>
+- r05_v_total_adj <= unsigned(DI(4 downto 0));
+- when "00110" =>
+- r06_v_displayed <= unsigned(DI(6 downto 0));
+- when "00111" =>
+- r07_v_sync_pos <= unsigned(DI(6 downto 0));
+- when "01000" =>
+- r08_interlace <= DI(1 downto 0);
+- when "01001" =>
+- r09_max_scan_line_addr <= unsigned(DI(4 downto 0));
+- when "01010" =>
+- r10_cursor_mode <= DI(6 downto 5);
+- r10_cursor_start <= unsigned(DI(4 downto 0));
+- when "01011" =>
+- r11_cursor_end <= unsigned(DI(4 downto 0));
+- when "01100" =>
+- r12_start_addr_h <= unsigned(DI(5 downto 0));
+- when "01101" =>
+- r13_start_addr_l <= unsigned(DI(7 downto 0));
+- when "01110" =>
+- r14_cursor_h <= unsigned(DI(5 downto 0));
+- when "01111" =>
+- r15_cursor_l <= unsigned(DI(7 downto 0));
+- when others =>
+- null;
+- end case;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process; -- registers
+-
+- -- Horizontal, vertical and address counters
+- process(CLOCK,nRESET)
+- variable ma_row_start : unsigned(13 downto 0);
+- variable max_scan_line : unsigned(4 downto 0);
+- begin
+- if nRESET = '0' then
+- -- H
+- h_counter <= (others => '0');
+-
+- -- V
+- line_counter <= (others => '0');
+- row_counter <= (others => '0');
+- odd_field <= '0';
+-
+- -- Fields (cursor flash)
+- field_counter <= (others => '0');
+-
+- -- Addressing
+- ma_row_start := (others => '0');
+- ma_i <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN='1' then
+- -- Horizontal counter increments on each clock, wrapping at
+- -- h_total
+- if h_counter = r00_h_total then
+- -- h_total reached
+- h_counter <= (others => '0');
+-
+- -- In interlace sync + video mode mask off the LSb of the
+- -- max scan line address
+- if r08_interlace = "11" then
+- max_scan_line := r09_max_scan_line_addr(4 downto 1) & "0";
+- else
+- max_scan_line := r09_max_scan_line_addr;
+- end if;
+-
+- -- Scan line counter increments, wrapping at max_scan_line_addr
+- if line_counter = max_scan_line then
+- -- Next character row
+- -- FIXME: No support for v_total_adj yet
+- line_counter <= (others => '0');
+- if row_counter = r04_v_total then
+- -- If in interlace mode we toggle to the opposite field.
+- -- Save on some logic by doing this here rather than at the
+- -- end of v_total_adj - it shouldn't make any difference to the
+- -- output
+- if r08_interlace(0) = '1' then
+- odd_field <= not odd_field;
+- else
+- odd_field <= '0';
+- end if;
+-
+- -- Address is loaded from start address register at the top of
+- -- each field and the row counter is reset
+- ma_row_start := r12_start_addr_h & r13_start_addr_l;
+- row_counter <= (others => '0');
+-
+- -- Increment field counter
+- field_counter <= field_counter + 1;
+- else
+- -- On all other character rows within the field the row start address is
+- -- increased by h_displayed and the row counter is incremented
+- ma_row_start := ma_row_start + r01_h_displayed;
+- row_counter <= row_counter + 1;
+- end if;
+- else
+- -- Next scan line. Count in twos in interlaced sync+video mode
+- if r08_interlace = "11" then
+- line_counter <= line_counter + 2;
+- line_counter(0) <= '0'; -- Force to even
+- else
+- line_counter <= line_counter + 1;
+- end if;
+- end if;
+-
+- -- Memory address preset to row start at the beginning of each
+- -- scan line
+- ma_i <= ma_row_start;
+- else
+- -- Increment horizontal counter
+- h_counter <= h_counter + 1;
+- -- Increment memory address
+- ma_i <= ma_i + 1;
+- end if;
+- end if;
+- end process;
+-
+- -- Signals to mark hsync and half way points for generating
+- -- vsync in even and odd fields
+- process(h_counter)
+- begin
+- h_sync_start <= '0';
+- h_half_way <= '0';
+-
+- if h_counter = r02_h_sync_pos then
+- h_sync_start <= '1';
+- end if;
+- if h_counter = "0" & r02_h_sync_pos(7 downto 1) then
+- h_half_way <= '1';
+- end if;
+- end process;
+-
+- -- Video timing and sync counters
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- -- H
+- h_display <= '0';
+- hs <= '0';
+- h_sync_counter <= (others => '0');
+-
+- -- V
+- v_display <= '0';
+- vs <= '0';
+- v_sync_counter <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Horizontal active video
+- if h_counter = 0 then
+- -- Start of active video
+- h_display <= '1';
+- end if;
+- if h_counter = r01_h_displayed then
+- -- End of active video
+- h_display <= '0';
+- end if;
+-
+- -- Horizontal sync
+- if h_sync_start = '1' or hs = '1' then
+- -- In horizontal sync
+- hs <= '1';
+- h_sync_counter <= h_sync_counter + 1;
+- else
+- h_sync_counter <= (others => '0');
+- end if;
+- if h_sync_counter = r03_h_sync_width then
+- -- Terminate hsync after h_sync_width (0 means no hsync so this
+- -- can immediately override the setting above)
+- hs <= '0';
+- end if;
+-
+- -- Vertical active video
+- if row_counter = 0 then
+- -- Start of active video
+- v_display <= '1';
+- end if;
+- if row_counter = r06_v_displayed then
+- -- End of active video
+- v_display <= '0';
+- end if;
+-
+- -- Vertical sync occurs either at the same time as the horizontal sync (even fields)
+- -- or half a line later (odd fields)
+- if (odd_field = '0' and h_sync_start = '1') or (odd_field = '1' and h_half_way = '1') then
+- if (row_counter = r07_v_sync_pos and line_counter = 0) or vs = '1' then
+- -- In vertical sync
+- vs <= '1';
+- v_sync_counter <= v_sync_counter + 1;
+- else
+- v_sync_counter <= (others => '0');
+- end if;
+- if v_sync_counter = r03_v_sync_width and vs = '1' then
+- -- Terminate vsync after v_sync_width (0 means 16 lines so this is
+- -- masked by 'vs' to ensure a full turn of the counter in this case)
+- vs <= '0';
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- -- Address generation
+- process(CLOCK,nRESET)
+- variable slv_line : std_logic_vector(4 downto 0);
+- begin
+- if nRESET = '0' then
+- RA <= (others => '0');
+- MA <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- slv_line := std_logic_vector(line_counter);
+-
+- -- Character row address is just the scan line counter delayed by
+- -- one clock to line up with the syncs.
+- if r08_interlace = "11" then
+- -- In interlace sync and video mode the LSb is determined by the
+- -- field number. The line counter counts up in 2s in this case.
+- RA <= slv_line(4 downto 1) & (slv_line(0) or odd_field);
+- else
+- RA <= slv_line;
+- end if;
+- -- Internal memory address delayed by one cycle as well
+- MA <= std_logic_vector(ma_i);
+- end if;
+- end process;
+-
+- -- Cursor control
+- process(CLOCK,nRESET)
+- variable cursor_line : std_logic;
+- begin
+- -- Internal cursor enable signal delayed by 1 clock to line up
+- -- with address outputs
+- if nRESET = '0' then
+- cursor_i <= '0';
+- cursor_line := '0';
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- if h_display = '1' and v_display = '1' and ma_i = r14_cursor_h & r15_cursor_l then
+- if line_counter = 0 then
+- -- Suppress wrap around if last line is > max scan line
+- cursor_line := '0';
+- end if;
+- if line_counter = r10_cursor_start then
+- -- First cursor scanline
+- cursor_line := '1';
+- end if;
+-
+- -- Cursor output is asserted within the current cursor character
+- -- on the selected lines only
+- cursor_i <= cursor_line;
+-
+- if line_counter = r11_cursor_end then
+- -- Last cursor scanline
+- cursor_line := '0';
+- end if;
+- else
+- -- Cursor is off in all character positions apart from the
+- -- selected one
+- cursor_i <= '0';
+- end if;
+- end if;
+- end process;
+-
+- -- Light pen capture
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- lpstb_i <= '0';
+- r16_light_pen_h <= (others => '0');
+- r17_light_pen_l <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Register light-pen strobe input
+- lpstb_i <= LPSTB;
+-
+- if LPSTB = '1' and lpstb_i = '0' then
+- -- Capture address on rising edge
+- r16_light_pen_h <= ma_i(13 downto 8);
+- r17_light_pen_l <= ma_i(7 downto 0);
+- end if;
+- end if;
+- end process;
+-end architecture;
+-
+-
++ DE <= h_display and v_display;
++
++ -- Cursor output generated combinatorially from the internal signal in
++ -- accordance with the currently selected cursor mode
++ CURSOR <= cursor_i when r10_cursor_mode = "00" else
++ '0' when r10_cursor_mode = "01" else
++ (cursor_i and field_counter(4)) when r10_cursor_mode = "10" else
++ (cursor_i and field_counter(5));
++
++ -- Synchronous register access. Enabled on every clock.
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ -- Reset registers to defaults
++ addr_reg <= (others => '0');
++ r00_h_total <= (others => '0');
++ r01_h_displayed <= (others => '0');
++ r02_h_sync_pos <= (others => '0');
++ r03_v_sync_width <= (others => '0');
++ r03_h_sync_width <= (others => '0');
++ r04_v_total <= (others => '0');
++ r05_v_total_adj <= (others => '0');
++ r06_v_displayed <= (others => '0');
++ r07_v_sync_pos <= (others => '0');
++ r08_interlace <= (others => '0');
++ r09_max_scan_line_addr <= (others => '0');
++ r10_cursor_mode <= (others => '0');
++ r10_cursor_start <= (others => '0');
++ r11_cursor_end <= (others => '0');
++ r12_start_addr_h <= (others => '0');
++ r13_start_addr_l <= (others => '0');
++ r14_cursor_h <= (others => '0');
++ r15_cursor_l <= (others => '0');
++
++ DO <= (others => '0');
++ elsif rising_edge(CLOCK) then
++ if ENABLE = '1' then
++ if R_nW = '1' then
++ -- Read
++ case addr_reg is
++ when "01110" =>
++ DO <= "00" & std_logic_vector(r14_cursor_h);
++ when "01111" =>
++ DO <= std_logic_vector(r15_cursor_l);
++ when "10000" =>
++ DO <= "00" & std_logic_vector(r16_light_pen_h);
++ when "10001" =>
++ DO <= std_logic_vector(r17_light_pen_l);
++ when others =>
++ DO <= (others => '0');
++ end case;
++ else
++ -- Write
++ if RS = '0' then
++ addr_reg <= DI(4 downto 0);
++ else
++ case addr_reg is
++ when "00000" =>
++ r00_h_total <= unsigned(DI);
++ when "00001" =>
++ r01_h_displayed <= unsigned(DI);
++ when "00010" =>
++ r02_h_sync_pos <= unsigned(DI);
++ when "00011" =>
++ r03_v_sync_width <= unsigned(DI(7 downto 4));
++ r03_h_sync_width <= unsigned(DI(3 downto 0));
++ when "00100" =>
++ r04_v_total <= unsigned(DI(6 downto 0));
++ when "00101" =>
++ r05_v_total_adj <= unsigned(DI(4 downto 0));
++ when "00110" =>
++ r06_v_displayed <= unsigned(DI(6 downto 0));
++ when "00111" =>
++ r07_v_sync_pos <= unsigned(DI(6 downto 0));
++ when "01000" =>
++ r08_interlace <= DI(1 downto 0);
++ when "01001" =>
++ r09_max_scan_line_addr <= unsigned(DI(4 downto 0));
++ when "01010" =>
++ r10_cursor_mode <= DI(6 downto 5);
++ r10_cursor_start <= unsigned(DI(4 downto 0));
++ when "01011" =>
++ r11_cursor_end <= unsigned(DI(4 downto 0));
++ when "01100" =>
++ r12_start_addr_h <= unsigned(DI(5 downto 0));
++ when "01101" =>
++ r13_start_addr_l <= unsigned(DI(7 downto 0));
++ when "01110" =>
++ r14_cursor_h <= unsigned(DI(5 downto 0));
++ when "01111" =>
++ r15_cursor_l <= unsigned(DI(7 downto 0));
++ when others =>
++ null;
++ end case;
++ end if;
++ end if;
++ end if;
++ end if;
++ end process; -- registers
++
++ -- Horizontal, vertical and address counters
++ process(CLOCK,nRESET)
++ variable ma_row_start : unsigned(13 downto 0);
++ variable max_scan_line : unsigned(4 downto 0);
++ begin
++ if nRESET = '0' then
++ -- H
++ h_counter <= (others => '0');
++
++ -- V
++ line_counter <= (others => '0');
++ row_counter <= (others => '0');
++ odd_field <= '0';
++
++ -- Fields (cursor flash)
++ field_counter <= (others => '0');
++
++ -- Addressing
++ ma_row_start := (others => '0');
++ ma_i <= (others => '0');
++ elsif rising_edge(CLOCK) and CLKEN='1' then
++ -- Horizontal counter increments on each clock, wrapping at
++ -- h_total
++ if h_counter = r00_h_total then
++ -- h_total reached
++ h_counter <= (others => '0');
++
++ -- In interlace sync + video mode mask off the LSb of the
++ -- max scan line address
++ if r08_interlace = "11" then
++ max_scan_line := r09_max_scan_line_addr(4 downto 1) & "0";
++ else
++ max_scan_line := r09_max_scan_line_addr;
++ end if;
++
++ -- Scan line counter increments, wrapping at max_scan_line_addr
++ if line_counter = max_scan_line then
++ -- Next character row
++ -- FIXME: No support for v_total_adj yet
++ line_counter <= (others => '0');
++ if row_counter = r04_v_total then
++ -- If in interlace mode we toggle to the opposite field.
++ -- Save on some logic by doing this here rather than at the
++ -- end of v_total_adj - it shouldn't make any difference to the
++ -- output
++ if r08_interlace(0) = '1' then
++ odd_field <= not odd_field;
++ else
++ odd_field <= '0';
++ end if;
++
++ -- Address is loaded from start address register at the top of
++ -- each field and the row counter is reset
++ ma_row_start := r12_start_addr_h & r13_start_addr_l;
++ row_counter <= (others => '0');
++
++ -- Increment field counter
++ field_counter <= field_counter + 1;
++ else
++ -- On all other character rows within the field the row start address is
++ -- increased by h_displayed and the row counter is incremented
++ ma_row_start := ma_row_start + r01_h_displayed;
++ row_counter <= row_counter + 1;
++ end if;
++ else
++ -- Next scan line. Count in twos in interlaced sync+video mode
++ if r08_interlace = "11" then
++ line_counter <= line_counter + 2;
++ line_counter(0) <= '0'; -- Force to even
++ else
++ line_counter <= line_counter + 1;
++ end if;
++ end if;
++
++ -- Memory address preset to row start at the beginning of each
++ -- scan line
++ ma_i <= ma_row_start;
++ else
++ -- Increment horizontal counter
++ h_counter <= h_counter + 1;
++ -- Increment memory address
++ ma_i <= ma_i + 1;
++ end if;
++ end if;
++ end process;
++
++ -- Signals to mark hsync and half way points for generating
++ -- vsync in even and odd fields
++ process(h_counter)
++ begin
++ h_sync_start <= '0';
++ h_half_way <= '0';
++
++ if h_counter = r02_h_sync_pos then
++ h_sync_start <= '1';
++ end if;
++ if h_counter = "0" & r02_h_sync_pos(7 downto 1) then
++ h_half_way <= '1';
++ end if;
++ end process;
++
++ -- Video timing and sync counters
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ -- H
++ h_display <= '0';
++ hs <= '0';
++ h_sync_counter <= (others => '0');
++
++ -- V
++ v_display <= '0';
++ vs <= '0';
++ v_sync_counter <= (others => '0');
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ -- Horizontal active video
++ if h_counter = 0 then
++ -- Start of active video
++ h_display <= '1';
++ end if;
++ if h_counter = r01_h_displayed then
++ -- End of active video
++ h_display <= '0';
++ end if;
++
++ -- Horizontal sync
++ if h_sync_start = '1' or hs = '1' then
++ -- In horizontal sync
++ hs <= '1';
++ h_sync_counter <= h_sync_counter + 1;
++ else
++ h_sync_counter <= (others => '0');
++ end if;
++ if h_sync_counter = r03_h_sync_width then
++ -- Terminate hsync after h_sync_width (0 means no hsync so this
++ -- can immediately override the setting above)
++ hs <= '0';
++ end if;
++
++ -- Vertical active video
++ if row_counter = 0 then
++ -- Start of active video
++ v_display <= '1';
++ end if;
++ if row_counter = r06_v_displayed then
++ -- End of active video
++ v_display <= '0';
++ end if;
++
++ -- Vertical sync occurs either at the same time as the horizontal sync (even fields)
++ -- or half a line later (odd fields)
++ if (odd_field = '0' and h_sync_start = '1') or (odd_field = '1' and h_half_way = '1') then
++ if (row_counter = r07_v_sync_pos and line_counter = 0) or vs = '1' then
++ -- In vertical sync
++ vs <= '1';
++ v_sync_counter <= v_sync_counter + 1;
++ else
++ v_sync_counter <= (others => '0');
++ end if;
++ if v_sync_counter = r03_v_sync_width and vs = '1' then
++ -- Terminate vsync after v_sync_width (0 means 16 lines so this is
++ -- masked by 'vs' to ensure a full turn of the counter in this case)
++ vs <= '0';
++ end if;
++ end if;
++ end if;
++ end process;
++
++ -- Address generation
++ process(CLOCK,nRESET)
++ variable slv_line : std_logic_vector(4 downto 0);
++ begin
++ if nRESET = '0' then
++ RA <= (others => '0');
++ MA <= (others => '0');
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ slv_line := std_logic_vector(line_counter);
++
++ -- Character row address is just the scan line counter delayed by
++ -- one clock to line up with the syncs.
++ if r08_interlace = "11" then
++ -- In interlace sync and video mode the LSb is determined by the
++ -- field number. The line counter counts up in 2s in this case.
++ RA <= slv_line(4 downto 1) & (slv_line(0) or odd_field);
++ else
++ RA <= slv_line;
++ end if;
++ -- Internal memory address delayed by one cycle as well
++ MA <= std_logic_vector(ma_i);
++ end if;
++ end process;
++
++ -- Cursor control
++ process(CLOCK,nRESET)
++ variable cursor_line : std_logic;
++ begin
++ -- Internal cursor enable signal delayed by 1 clock to line up
++ -- with address outputs
++ if nRESET = '0' then
++ cursor_i <= '0';
++ cursor_line := '0';
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ if h_display = '1' and v_display = '1' and ma_i = r14_cursor_h & r15_cursor_l then
++ if line_counter = 0 then
++ -- Suppress wrap around if last line is > max scan line
++ cursor_line := '0';
++ end if;
++ if line_counter = r10_cursor_start then
++ -- First cursor scanline
++ cursor_line := '1';
++ end if;
++
++ -- Cursor output is asserted within the current cursor character
++ -- on the selected lines only
++ cursor_i <= cursor_line;
++
++ if line_counter = r11_cursor_end then
++ -- Last cursor scanline
++ cursor_line := '0';
++ end if;
++ else
++ -- Cursor is off in all character positions apart from the
++ -- selected one
++ cursor_i <= '0';
++ end if;
++ end if;
++ end process;
++
++ -- Light pen capture
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ lpstb_i <= '0';
++ r16_light_pen_h <= (others => '0');
++ r17_light_pen_l <= (others => '0');
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ -- Register light-pen strobe input
++ lpstb_i <= LPSTB;
++
++ if LPSTB = '1' and lpstb_i = '0' then
++ -- Capture address on rising edge
++ r16_light_pen_h <= ma_i(13 downto 8);
++ r17_light_pen_l <= ma_i(7 downto 0);
++ end if;
++ end if;
++ end process;
++end architecture;
++
++
+diff --git a/pll32.ppf b/pll32.ppf
+index 1ba6b2c..71486cf 100644
+--- a/pll32.ppf
++++ b/pll32.ppf
+@@ -1,11 +1,11 @@
+-<?xml version="1.0" encoding="UTF-8" ?>
+-<!DOCTYPE pinplan>
+-<pinplan intended_family="Cyclone II" variation_name="pll32" megafunction_name="ALTPLL" specifies="all_ports">
+-<global>
+-<pin name="areset" direction="input" scope="external" />
+-<pin name="inclk0" direction="input" scope="external" source="clock" />
+-<pin name="c0" direction="output" scope="external" source="clock" />
+-<pin name="locked" direction="output" scope="external" />
+-
+-</global>
+-</pinplan>
++<?xml version="1.0" encoding="UTF-8" ?>
++<!DOCTYPE pinplan>
++<pinplan intended_family="Cyclone II" variation_name="pll32" megafunction_name="ALTPLL" specifies="all_ports">
++<global>
++<pin name="areset" direction="input" scope="external" />
++<pin name="inclk0" direction="input" scope="external" source="clock" />
++<pin name="c0" direction="output" scope="external" source="clock" />
++<pin name="locked" direction="output" scope="external" />
++
++</global>
++</pinplan>
+diff --git a/pll32.qip b/pll32.qip
+index f78bd93..e82abed 100644
+--- a/pll32.qip
++++ b/pll32.qip
+@@ -1,4 +1,4 @@
+-set_global_assignment -name IP_TOOL_NAME "ALTPLL"
+-set_global_assignment -name IP_TOOL_VERSION "9.1"
+-set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "pll32.vhd"]
+-set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll32.ppf"]
++set_global_assignment -name IP_TOOL_NAME "ALTPLL"
++set_global_assignment -name IP_TOOL_VERSION "9.1"
++set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "pll32.vhd"]
++set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll32.ppf"]
+diff --git a/pll32.vhd b/pll32.vhd
+index 43df1aa..ab53700 100644
+--- a/pll32.vhd
++++ b/pll32.vhd
+@@ -1,365 +1,365 @@
+--- megafunction wizard: %ALTPLL%
+--- GENERATION: STANDARD
+--- VERSION: WM1.0
+--- MODULE: altpll
+-
+--- ============================================================
+--- File Name: pll32.vhd
+--- Megafunction Name(s):
+--- altpll
+---
+--- Simulation Library Files(s):
+--- altera_mf
+--- ============================================================
+--- ************************************************************
+--- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+---
+--- 9.1 Build 222 10/21/2009 SJ Web Edition
+--- ************************************************************
+-
+-
+---Copyright (C) 1991-2009 Altera Corporation
+---Your use of Altera Corporation's design tools, logic functions
+---and other software and tools, and its AMPP partner logic
+---functions, and any output files from any of the foregoing
+---(including device programming or simulation files), and any
+---associated documentation or information are expressly subject
+---to the terms and conditions of the Altera Program License
+---Subscription Agreement, Altera MegaCore Function License
+---Agreement, or other applicable license agreement, including,
+---without limitation, that your use is for the sole purpose of
+---programming logic devices manufactured by Altera and sold by
+---Altera or its authorized distributors. Please refer to the
+---applicable agreement for further details.
+-
+-
+-LIBRARY ieee;
+-USE ieee.std_logic_1164.all;
+-
+-LIBRARY altera_mf;
+-USE altera_mf.all;
+-
+-ENTITY pll32 IS
+- PORT
+- (
+- areset : IN STD_LOGIC := '0';
+- inclk0 : IN STD_LOGIC := '0';
+- c0 : OUT STD_LOGIC ;
+- locked : OUT STD_LOGIC
+- );
+-END pll32;
+-
+-
+-ARCHITECTURE SYN OF pll32 IS
+-
+- SIGNAL sub_wire0 : STD_LOGIC_VECTOR (5 DOWNTO 0);
+- SIGNAL sub_wire1 : STD_LOGIC ;
+- SIGNAL sub_wire2 : STD_LOGIC ;
+- SIGNAL sub_wire3 : STD_LOGIC ;
+- SIGNAL sub_wire4 : STD_LOGIC_VECTOR (1 DOWNTO 0);
+- SIGNAL sub_wire5_bv : BIT_VECTOR (0 DOWNTO 0);
+- SIGNAL sub_wire5 : STD_LOGIC_VECTOR (0 DOWNTO 0);
+-
+-
+-
+- COMPONENT altpll
+- GENERIC (
+- clk0_divide_by : NATURAL;
+- clk0_duty_cycle : NATURAL;
+- clk0_multiply_by : NATURAL;
+- clk0_phase_shift : STRING;
+- compensate_clock : STRING;
+- gate_lock_signal : STRING;
+- inclk0_input_frequency : NATURAL;
+- intended_device_family : STRING;
+- invalid_lock_multiplier : NATURAL;
+- lpm_hint : STRING;
+- lpm_type : STRING;
+- operation_mode : STRING;
+- port_activeclock : STRING;
+- port_areset : STRING;
+- port_clkbad0 : STRING;
+- port_clkbad1 : STRING;
+- port_clkloss : STRING;
+- port_clkswitch : STRING;
+- port_configupdate : STRING;
+- port_fbin : STRING;
+- port_inclk0 : STRING;
+- port_inclk1 : STRING;
+- port_locked : STRING;
+- port_pfdena : STRING;
+- port_phasecounterselect : STRING;
+- port_phasedone : STRING;
+- port_phasestep : STRING;
+- port_phaseupdown : STRING;
+- port_pllena : STRING;
+- port_scanaclr : STRING;
+- port_scanclk : STRING;
+- port_scanclkena : STRING;
+- port_scandata : STRING;
+- port_scandataout : STRING;
+- port_scandone : STRING;
+- port_scanread : STRING;
+- port_scanwrite : STRING;
+- port_clk0 : STRING;
+- port_clk1 : STRING;
+- port_clk2 : STRING;
+- port_clk3 : STRING;
+- port_clk4 : STRING;
+- port_clk5 : STRING;
+- port_clkena0 : STRING;
+- port_clkena1 : STRING;
+- port_clkena2 : STRING;
+- port_clkena3 : STRING;
+- port_clkena4 : STRING;
+- port_clkena5 : STRING;
+- port_extclk0 : STRING;
+- port_extclk1 : STRING;
+- port_extclk2 : STRING;
+- port_extclk3 : STRING;
+- valid_lock_multiplier : NATURAL
+- );
+- PORT (
+- inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
+- locked : OUT STD_LOGIC ;
+- areset : IN STD_LOGIC ;
+- clk : OUT STD_LOGIC_VECTOR (5 DOWNTO 0)
+- );
+- END COMPONENT;
+-
+-BEGIN
+- sub_wire5_bv(0 DOWNTO 0) <= "0";
+- sub_wire5 <= To_stdlogicvector(sub_wire5_bv);
+- sub_wire1 <= sub_wire0(0);
+- c0 <= sub_wire1;
+- locked <= sub_wire2;
+- sub_wire3 <= inclk0;
+- sub_wire4 <= sub_wire5(0 DOWNTO 0) & sub_wire3;
+-
+- altpll_component : altpll
+- GENERIC MAP (
+- clk0_divide_by => 3,
+- clk0_duty_cycle => 50,
+- clk0_multiply_by => 4,
+- clk0_phase_shift => "0",
+- compensate_clock => "CLK0",
+- gate_lock_signal => "NO",
+- inclk0_input_frequency => 41666,
+- intended_device_family => "Cyclone II",
+- invalid_lock_multiplier => 5,
+- lpm_hint => "CBX_MODULE_PREFIX=pll32",
+- lpm_type => "altpll",
+- operation_mode => "NORMAL",
+- port_activeclock => "PORT_UNUSED",
+- port_areset => "PORT_USED",
+- port_clkbad0 => "PORT_UNUSED",
+- port_clkbad1 => "PORT_UNUSED",
+- port_clkloss => "PORT_UNUSED",
+- port_clkswitch => "PORT_UNUSED",
+- port_configupdate => "PORT_UNUSED",
+- port_fbin => "PORT_UNUSED",
+- port_inclk0 => "PORT_USED",
+- port_inclk1 => "PORT_UNUSED",
+- port_locked => "PORT_USED",
+- port_pfdena => "PORT_UNUSED",
+- port_phasecounterselect => "PORT_UNUSED",
+- port_phasedone => "PORT_UNUSED",
+- port_phasestep => "PORT_UNUSED",
+- port_phaseupdown => "PORT_UNUSED",
+- port_pllena => "PORT_UNUSED",
+- port_scanaclr => "PORT_UNUSED",
+- port_scanclk => "PORT_UNUSED",
+- port_scanclkena => "PORT_UNUSED",
+- port_scandata => "PORT_UNUSED",
+- port_scandataout => "PORT_UNUSED",
+- port_scandone => "PORT_UNUSED",
+- port_scanread => "PORT_UNUSED",
+- port_scanwrite => "PORT_UNUSED",
+- port_clk0 => "PORT_USED",
+- port_clk1 => "PORT_UNUSED",
+- port_clk2 => "PORT_UNUSED",
+- port_clk3 => "PORT_UNUSED",
+- port_clk4 => "PORT_UNUSED",
+- port_clk5 => "PORT_UNUSED",
+- port_clkena0 => "PORT_UNUSED",
+- port_clkena1 => "PORT_UNUSED",
+- port_clkena2 => "PORT_UNUSED",
+- port_clkena3 => "PORT_UNUSED",
+- port_clkena4 => "PORT_UNUSED",
+- port_clkena5 => "PORT_UNUSED",
+- port_extclk0 => "PORT_UNUSED",
+- port_extclk1 => "PORT_UNUSED",
+- port_extclk2 => "PORT_UNUSED",
+- port_extclk3 => "PORT_UNUSED",
+- valid_lock_multiplier => 1
+- )
+- PORT MAP (
+- inclk => sub_wire4,
+- areset => areset,
+- clk => sub_wire0,
+- locked => sub_wire2
+- );
+-
+-
+-
+-END SYN;
+-
+--- ============================================================
+--- CNX file retrieval info
+--- ============================================================
+--- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
+--- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
+--- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0"
+--- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
+--- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
+--- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
+--- Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0"
+--- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
+--- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
+--- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
+--- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "1"
+--- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
+--- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
+--- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
+--- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
+--- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0"
+--- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7"
+--- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
+--- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
+--- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "32.000000"
+--- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
+--- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
+--- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
+--- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "1"
+--- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
+--- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
+--- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
+--- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "24.000"
+--- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
+--- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
+--- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
+--- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
+--- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
+--- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+--- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
+--- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
+--- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
+--- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "312.000"
+--- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
+--- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
+--- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
+--- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
+--- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
+--- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
+--- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "32.00000000"
+--- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
+--- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
+--- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "0"
+--- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
+--- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
+--- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
+--- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
+--- Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
+--- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
+--- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
+--- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
+--- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
+--- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
+--- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll32.mif"
+--- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
+--- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0"
+--- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
+--- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
+--- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
+--- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
+--- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
+--- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
+--- Retrieval info: PRIVATE: SPREAD_USE STRING "0"
+--- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
+--- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
+--- Retrieval info: PRIVATE: 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_CLKENA0 STRING "0"
+--- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
+--- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
+--- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+--- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "3"
+--- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
+--- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "4"
+--- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
+--- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
+--- Retrieval info: CONSTANT: GATE_LOCK_SIGNAL STRING "NO"
+--- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "41666"
+--- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+--- Retrieval info: CONSTANT: INVALID_LOCK_MULTIPLIER NUMERIC "5"
+--- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
+--- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
+--- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"
+--- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
+--- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
+--- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
+--- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
+--- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED"
+--- 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: VALID_LOCK_MULTIPLIER NUMERIC "1"
+--- Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT_CLK_EXT VCC "@clk[5..0]"
+--- Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT_CLK_EXT VCC "@extclk[3..0]"
+--- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]"
+--- Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
+--- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
+--- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
+--- Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
+--- Retrieval info: CONNECT: locked 0 0 0 0 @locked 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: @inclk 0 0 1 1 GND 0 0 0 0
+--- Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.vhd TRUE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.ppf TRUE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.inc FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.cmp FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.bsf FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL pll32_inst.vhd FALSE
+--- Retrieval info: LIB_FILE: altera_mf
+--- Retrieval info: CBX_MODULE_PREFIX: ON
++-- megafunction wizard: %ALTPLL%
++-- GENERATION: STANDARD
++-- VERSION: WM1.0
++-- MODULE: altpll
++
++-- ============================================================
++-- File Name: pll32.vhd
++-- Megafunction Name(s):
++-- altpll
++--
++-- Simulation Library Files(s):
++-- altera_mf
++-- ============================================================
++-- ************************************************************
++-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
++--
++-- 9.1 Build 222 10/21/2009 SJ Web Edition
++-- ************************************************************
++
++
++--Copyright (C) 1991-2009 Altera Corporation
++--Your use of Altera Corporation's design tools, logic functions
++--and other software and tools, and its AMPP partner logic
++--functions, and any output files from any of the foregoing
++--(including device programming or simulation files), and any
++--associated documentation or information are expressly subject
++--to the terms and conditions of the Altera Program License
++--Subscription Agreement, Altera MegaCore Function License
++--Agreement, or other applicable license agreement, including,
++--without limitation, that your use is for the sole purpose of
++--programming logic devices manufactured by Altera and sold by
++--Altera or its authorized distributors. Please refer to the
++--applicable agreement for further details.
++
++
++LIBRARY ieee;
++USE ieee.std_logic_1164.all;
++
++LIBRARY altera_mf;
++USE altera_mf.all;
++
++ENTITY pll32 IS
++ PORT
++ (
++ areset : IN STD_LOGIC := '0';
++ inclk0 : IN STD_LOGIC := '0';
++ c0 : OUT STD_LOGIC ;
++ locked : OUT STD_LOGIC
++ );
++END pll32;
++
++
++ARCHITECTURE SYN OF pll32 IS
++
++ SIGNAL sub_wire0 : STD_LOGIC_VECTOR (5 DOWNTO 0);
++ SIGNAL sub_wire1 : STD_LOGIC ;
++ SIGNAL sub_wire2 : STD_LOGIC ;
++ SIGNAL sub_wire3 : STD_LOGIC ;
++ SIGNAL sub_wire4 : STD_LOGIC_VECTOR (1 DOWNTO 0);
++ SIGNAL sub_wire5_bv : BIT_VECTOR (0 DOWNTO 0);
++ SIGNAL sub_wire5 : STD_LOGIC_VECTOR (0 DOWNTO 0);
++
++
++
++ COMPONENT altpll
++ GENERIC (
++ clk0_divide_by : NATURAL;
++ clk0_duty_cycle : NATURAL;
++ clk0_multiply_by : NATURAL;
++ clk0_phase_shift : STRING;
++ compensate_clock : STRING;
++ gate_lock_signal : STRING;
++ inclk0_input_frequency : NATURAL;
++ intended_device_family : STRING;
++ invalid_lock_multiplier : NATURAL;
++ lpm_hint : STRING;
++ lpm_type : STRING;
++ operation_mode : STRING;
++ port_activeclock : STRING;
++ port_areset : STRING;
++ port_clkbad0 : STRING;
++ port_clkbad1 : STRING;
++ port_clkloss : STRING;
++ port_clkswitch : STRING;
++ port_configupdate : STRING;
++ port_fbin : STRING;
++ port_inclk0 : STRING;
++ port_inclk1 : STRING;
++ port_locked : STRING;
++ port_pfdena : STRING;
++ port_phasecounterselect : STRING;
++ port_phasedone : STRING;
++ port_phasestep : STRING;
++ port_phaseupdown : STRING;
++ port_pllena : STRING;
++ port_scanaclr : STRING;
++ port_scanclk : STRING;
++ port_scanclkena : STRING;
++ port_scandata : STRING;
++ port_scandataout : STRING;
++ port_scandone : STRING;
++ port_scanread : STRING;
++ port_scanwrite : STRING;
++ port_clk0 : STRING;
++ port_clk1 : STRING;
++ port_clk2 : STRING;
++ port_clk3 : STRING;
++ port_clk4 : STRING;
++ port_clk5 : STRING;
++ port_clkena0 : STRING;
++ port_clkena1 : STRING;
++ port_clkena2 : STRING;
++ port_clkena3 : STRING;
++ port_clkena4 : STRING;
++ port_clkena5 : STRING;
++ port_extclk0 : STRING;
++ port_extclk1 : STRING;
++ port_extclk2 : STRING;
++ port_extclk3 : STRING;
++ valid_lock_multiplier : NATURAL
++ );
++ PORT (
++ inclk : IN STD_LOGIC_VECTOR (1 DOWNTO 0);
++ locked : OUT STD_LOGIC ;
++ areset : IN STD_LOGIC ;
++ clk : OUT STD_LOGIC_VECTOR (5 DOWNTO 0)
++ );
++ END COMPONENT;
++
++BEGIN
++ sub_wire5_bv(0 DOWNTO 0) <= "0";
++ sub_wire5 <= To_stdlogicvector(sub_wire5_bv);
++ sub_wire1 <= sub_wire0(0);
++ c0 <= sub_wire1;
++ locked <= sub_wire2;
++ sub_wire3 <= inclk0;
++ sub_wire4 <= sub_wire5(0 DOWNTO 0) & sub_wire3;
++
++ altpll_component : altpll
++ GENERIC MAP (
++ clk0_divide_by => 3,
++ clk0_duty_cycle => 50,
++ clk0_multiply_by => 4,
++ clk0_phase_shift => "0",
++ compensate_clock => "CLK0",
++ gate_lock_signal => "NO",
++ inclk0_input_frequency => 41666,
++ intended_device_family => "Cyclone II",
++ invalid_lock_multiplier => 5,
++ lpm_hint => "CBX_MODULE_PREFIX=pll32",
++ lpm_type => "altpll",
++ operation_mode => "NORMAL",
++ port_activeclock => "PORT_UNUSED",
++ port_areset => "PORT_USED",
++ port_clkbad0 => "PORT_UNUSED",
++ port_clkbad1 => "PORT_UNUSED",
++ port_clkloss => "PORT_UNUSED",
++ port_clkswitch => "PORT_UNUSED",
++ port_configupdate => "PORT_UNUSED",
++ port_fbin => "PORT_UNUSED",
++ port_inclk0 => "PORT_USED",
++ port_inclk1 => "PORT_UNUSED",
++ port_locked => "PORT_USED",
++ port_pfdena => "PORT_UNUSED",
++ port_phasecounterselect => "PORT_UNUSED",
++ port_phasedone => "PORT_UNUSED",
++ port_phasestep => "PORT_UNUSED",
++ port_phaseupdown => "PORT_UNUSED",
++ port_pllena => "PORT_UNUSED",
++ port_scanaclr => "PORT_UNUSED",
++ port_scanclk => "PORT_UNUSED",
++ port_scanclkena => "PORT_UNUSED",
++ port_scandata => "PORT_UNUSED",
++ port_scandataout => "PORT_UNUSED",
++ port_scandone => "PORT_UNUSED",
++ port_scanread => "PORT_UNUSED",
++ port_scanwrite => "PORT_UNUSED",
++ port_clk0 => "PORT_USED",
++ port_clk1 => "PORT_UNUSED",
++ port_clk2 => "PORT_UNUSED",
++ port_clk3 => "PORT_UNUSED",
++ port_clk4 => "PORT_UNUSED",
++ port_clk5 => "PORT_UNUSED",
++ port_clkena0 => "PORT_UNUSED",
++ port_clkena1 => "PORT_UNUSED",
++ port_clkena2 => "PORT_UNUSED",
++ port_clkena3 => "PORT_UNUSED",
++ port_clkena4 => "PORT_UNUSED",
++ port_clkena5 => "PORT_UNUSED",
++ port_extclk0 => "PORT_UNUSED",
++ port_extclk1 => "PORT_UNUSED",
++ port_extclk2 => "PORT_UNUSED",
++ port_extclk3 => "PORT_UNUSED",
++ valid_lock_multiplier => 1
++ )
++ PORT MAP (
++ inclk => sub_wire4,
++ areset => areset,
++ clk => sub_wire0,
++ locked => sub_wire2
++ );
++
++
++
++END SYN;
++
++-- ============================================================
++-- CNX file retrieval info
++-- ============================================================
++-- Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
++-- Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
++-- Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "0"
++-- Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
++-- Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
++-- Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
++-- Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0"
++-- Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
++-- Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
++-- Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
++-- Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "1"
++-- Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
++-- Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
++-- Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
++-- Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
++-- Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "e0"
++-- Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7"
++-- Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
++-- Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
++-- Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "32.000000"
++-- Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
++-- Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
++-- Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
++-- Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "1"
++-- Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
++-- Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
++-- Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
++-- Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "24.000"
++-- Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
++-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
++-- Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
++-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
++-- Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
++-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
++-- Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
++-- Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
++-- Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
++-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "312.000"
++-- Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
++-- Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
++-- Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
++-- Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
++-- Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
++-- Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
++-- Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "32.00000000"
++-- Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
++-- Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
++-- Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "0"
++-- Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
++-- Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
++-- Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
++-- Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
++-- Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
++-- Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
++-- Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
++-- Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0"
++-- Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
++-- Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
++-- Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
++-- Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
++-- Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
++-- Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
++-- Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
++-- Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll32.mif"
++-- Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
++-- Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0"
++-- Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
++-- Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
++-- Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
++-- Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
++-- Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
++-- Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
++-- Retrieval info: PRIVATE: SPREAD_USE STRING "0"
++-- Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
++-- Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
++-- Retrieval info: PRIVATE: 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_CLKENA0 STRING "0"
++-- Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
++-- Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
++-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
++-- Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "3"
++-- Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
++-- Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "4"
++-- Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
++-- Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
++-- Retrieval info: CONSTANT: GATE_LOCK_SIGNAL STRING "NO"
++-- Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "41666"
++-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
++-- Retrieval info: CONSTANT: INVALID_LOCK_MULTIPLIER NUMERIC "5"
++-- Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
++-- Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
++-- Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"
++-- Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
++-- Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
++-- Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
++-- Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
++-- Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED"
++-- 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: VALID_LOCK_MULTIPLIER NUMERIC "1"
++-- Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT_CLK_EXT VCC "@clk[5..0]"
++-- Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT_CLK_EXT VCC "@extclk[3..0]"
++-- Retrieval info: USED_PORT: @inclk 0 0 2 0 INPUT_CLK_EXT VCC "@inclk[1..0]"
++-- Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
++-- Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
++-- Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
++-- Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
++-- Retrieval info: CONNECT: locked 0 0 0 0 @locked 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: @inclk 0 0 1 1 GND 0 0 0 0
++-- Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0
++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.vhd TRUE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.ppf TRUE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.inc FALSE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.cmp FALSE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32.bsf FALSE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL pll32_inst.vhd FALSE
++-- Retrieval info: LIB_FILE: altera_mf
++-- Retrieval info: CBX_MODULE_PREFIX: ON
+diff --git a/ps2_intf.vhd b/ps2_intf.vhd
+index dc8440f..015a7d0 100644
+--- a/ps2_intf.vhd
++++ b/ps2_intf.vhd
+@@ -1,157 +1,157 @@
+--- ZX Spectrum for Altera DE1
+---
+--- Copyright (c) 2009-2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+-
+--- PS/2 interface (input only)
+--- Based loosely on ps2_ctrl.vhd (c) ALSE. http://www.alse-fr.com
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+--- This is input-only for the time being
+-entity ps2_intf is
+-generic (filter_length : positive := 8);
+-port(
+- CLK : in std_logic;
+- nRESET : in std_logic;
+-
+- -- PS/2 interface (could be bi-dir)
+- PS2_CLK : in std_logic;
+- PS2_DATA : in std_logic;
+-
+- -- Byte-wide data interface - only valid for one clock
+- -- so must be latched externally if required
+- DATA : out std_logic_vector(7 downto 0);
+- VALID : out std_logic;
+- ERROR : out std_logic
+- );
+-end ps2_intf;
+-
+-architecture ps2_intf_arch of ps2_intf is
+-subtype filter_t is std_logic_vector(filter_length-1 downto 0);
+-signal clk_filter : filter_t;
+-
+-signal ps2_clk_in : std_logic;
+-signal ps2_dat_in : std_logic;
+--- Goes high when a clock falling edge is detected
+-signal clk_edge : std_logic;
+-signal bit_count : unsigned (3 downto 0);
+-signal shiftreg : std_logic_vector(8 downto 0);
+-signal parity : std_logic;
+-begin
+- -- Register input signals
+- process(nRESET,CLK)
+- begin
+- if nRESET = '0' then
+- ps2_clk_in <= '1';
+- ps2_dat_in <= '1';
+- clk_filter <= (others => '1');
+- clk_edge <= '0';
+- elsif rising_edge(CLK) then
+- -- Register inputs (and filter clock)
+- ps2_dat_in <= PS2_DATA;
+- clk_filter <= PS2_CLK & clk_filter(clk_filter'high downto 1);
+- clk_edge <= '0';
+-
+- if clk_filter = filter_t'(others => '1') then
+- -- Filtered clock is high
+- ps2_clk_in <= '1';
+- elsif clk_filter = filter_t'(others => '0') then
+- -- Filter clock is low, check for edge
+- if ps2_clk_in = '1' then
+- clk_edge <= '1';
+- end if;
+- ps2_clk_in <= '0';
+- end if;
+- end if;
+- end process;
+-
+- -- Shift in keyboard data
+- process(nRESET,CLK)
+- begin
+- if nRESET = '0' then
+- bit_count <= (others => '0');
+- shiftreg <= (others => '0');
+- parity <= '0';
+- DATA <= (others => '0');
+- VALID <= '0';
+- ERROR <= '0';
+- elsif rising_edge(CLK) then
+- -- Clear flags
+- VALID <= '0';
+- ERROR <= '0';
+-
+- if clk_edge = '1' then
+- -- We have a new bit from the keyboard for processing
+- if bit_count = 0 then
+- -- Idle state, check for start bit (0) only and don't
+- -- start counting bits until we get it
+-
+- parity <= '0';
+-
+- if ps2_dat_in = '0' then
+- -- This is a start bit
+- bit_count <= bit_count + 1;
+- end if;
+- else
+- -- Running. 8-bit data comes in LSb first followed by
+- -- a single stop bit (1)
+- if bit_count < 10 then
+- -- Shift in data and parity (9 bits)
+- bit_count <= bit_count + 1;
+- shiftreg <= ps2_dat_in & shiftreg(shiftreg'high downto 1);
+- parity <= parity xor ps2_dat_in; -- Calculate parity
+- elsif ps2_dat_in = '1' then
+- -- Valid stop bit received
+- bit_count <= (others => '0'); -- back to idle
+- if parity = '1' then
+- -- Parity correct, submit data to host
+- DATA <= shiftreg(7 downto 0);
+- VALID <= '1';
+- else
+- -- Error
+- ERROR <= '1';
+- end if;
+- else
+- -- Invalid stop bit
+- bit_count <= (others => '0'); -- back to idle
+- ERROR <= '1';
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-end ps2_intf_arch;
++-- ZX Spectrum for Altera DE1
++--
++-- Copyright (c) 2009-2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++
++-- PS/2 interface (input only)
++-- Based loosely on ps2_ctrl.vhd (c) ALSE. http://www.alse-fr.com
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.NUMERIC_STD.ALL;
++
++-- This is input-only for the time being
++entity ps2_intf is
++generic (filter_length : positive := 8);
++port(
++ CLK : in std_logic;
++ nRESET : in std_logic;
++
++ -- PS/2 interface (could be bi-dir)
++ PS2_CLK : in std_logic;
++ PS2_DATA : in std_logic;
++
++ -- Byte-wide data interface - only valid for one clock
++ -- so must be latched externally if required
++ DATA : out std_logic_vector(7 downto 0);
++ VALID : out std_logic;
++ ERROR : out std_logic
++ );
++end ps2_intf;
++
++architecture ps2_intf_arch of ps2_intf is
++subtype filter_t is std_logic_vector(filter_length-1 downto 0);
++signal clk_filter : filter_t;
++
++signal ps2_clk_in : std_logic;
++signal ps2_dat_in : std_logic;
++-- Goes high when a clock falling edge is detected
++signal clk_edge : std_logic;
++signal bit_count : unsigned (3 downto 0);
++signal shiftreg : std_logic_vector(8 downto 0);
++signal parity : std_logic;
++begin
++ -- Register input signals
++ process(nRESET,CLK)
++ begin
++ if nRESET = '0' then
++ ps2_clk_in <= '1';
++ ps2_dat_in <= '1';
++ clk_filter <= (others => '1');
++ clk_edge <= '0';
++ elsif rising_edge(CLK) then
++ -- Register inputs (and filter clock)
++ ps2_dat_in <= PS2_DATA;
++ clk_filter <= PS2_CLK & clk_filter(clk_filter'high downto 1);
++ clk_edge <= '0';
++
++ if clk_filter = filter_t'(others => '1') then
++ -- Filtered clock is high
++ ps2_clk_in <= '1';
++ elsif clk_filter = filter_t'(others => '0') then
++ -- Filter clock is low, check for edge
++ if ps2_clk_in = '1' then
++ clk_edge <= '1';
++ end if;
++ ps2_clk_in <= '0';
++ end if;
++ end if;
++ end process;
++
++ -- Shift in keyboard data
++ process(nRESET,CLK)
++ begin
++ if nRESET = '0' then
++ bit_count <= (others => '0');
++ shiftreg <= (others => '0');
++ parity <= '0';
++ DATA <= (others => '0');
++ VALID <= '0';
++ ERROR <= '0';
++ elsif rising_edge(CLK) then
++ -- Clear flags
++ VALID <= '0';
++ ERROR <= '0';
++
++ if clk_edge = '1' then
++ -- We have a new bit from the keyboard for processing
++ if bit_count = 0 then
++ -- Idle state, check for start bit (0) only and don't
++ -- start counting bits until we get it
++
++ parity <= '0';
++
++ if ps2_dat_in = '0' then
++ -- This is a start bit
++ bit_count <= bit_count + 1;
++ end if;
++ else
++ -- Running. 8-bit data comes in LSb first followed by
++ -- a single stop bit (1)
++ if bit_count < 10 then
++ -- Shift in data and parity (9 bits)
++ bit_count <= bit_count + 1;
++ shiftreg <= ps2_dat_in & shiftreg(shiftreg'high downto 1);
++ parity <= parity xor ps2_dat_in; -- Calculate parity
++ elsif ps2_dat_in = '1' then
++ -- Valid stop bit received
++ bit_count <= (others => '0'); -- back to idle
++ if parity = '1' then
++ -- Parity correct, submit data to host
++ DATA <= shiftreg(7 downto 0);
++ VALID <= '1';
++ else
++ -- Error
++ ERROR <= '1';
++ end if;
++ else
++ -- Invalid stop bit
++ bit_count <= (others => '0'); -- back to idle
++ ERROR <= '1';
++ end if;
++ end if;
++ end if;
++ end if;
++ end process;
++end ps2_intf_arch;
+diff --git a/saa5050.vhd b/saa5050.vhd
+index 57dd999..f198aa8 100644
+--- a/saa5050.vhd
++++ b/saa5050.vhd
+@@ -1,391 +1,391 @@
+--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- SAA5050 teletext generator
+---
+--- Synchronous implementation for FPGA. Certain TV-specific functions are
+--- not implemented. e.g.
+---
+--- No /SI pin - 'TEXT' mode is permanently enabled
+--- No remote control features (/DATA, DLIM)
+--- No large character support
+--- No support for box overlay (BLAN, PO, DE)
+--- No character rounding, although this may be added
+---
+--- FIXME: Hold graphics not supported - this needs to be added
+---
+--- (C) 2011 Mike Stirling
+---
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity saa5050 is
+-port (
+- CLOCK : in std_logic;
+- -- 6 MHz dot clock enable
+- CLKEN : in std_logic;
+- -- Async reset
+- nRESET : in std_logic;
+-
+- -- Character data input (in the bus clock domain)
+- DI_CLOCK : in std_logic;
+- DI_CLKEN : in std_logic;
+- DI : in std_logic_vector(6 downto 0);
+-
+- -- Timing inputs
+- -- General line reset (not used)
+- GLR : in std_logic; -- /HSYNC
+- -- Data entry window - high during VSYNC.
+- -- Resets ROM row counter and drives 'flash' signal
+- DEW : in std_logic; -- VSYNC
+- -- Character rounding select - high during even field
+- CRS : in std_logic; -- FIELD
+- -- Load output shift register enable - high during active video
+- LOSE : in std_logic; -- DE
+-
+- -- Video out
+- R : out std_logic;
+- G : out std_logic;
+- B : out std_logic;
+- Y : out std_logic
+- );
+-end entity;
+-
+-architecture rtl of saa5050 is
+-
+-component saa5050_rom IS
+- PORT
+- (
+- address : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
+- clock : IN STD_LOGIC ;
+- q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
+- );
+-end component;
+-
+--- Register inputs in the bus clock domain
+-signal di_r : std_logic_vector(6 downto 0);
+-signal dew_r : std_logic;
+-signal lose_r : std_logic;
+--- Data input registered in the pixel clock domain
+-signal code : std_logic_vector(6 downto 0);
+-signal line_addr : unsigned(3 downto 0);
+-signal rom_address : std_logic_vector(11 downto 0);
+-signal rom_data : std_logic_vector(7 downto 0);
+-
+--- Delayed display enable derived from LOSE by delaying for one character
+-signal disp_enable : std_logic;
+--- Latched timing signals for detection of falling edges
+-signal dew_latch : std_logic;
+-signal lose_latch : std_logic;
+-signal disp_enable_latch : std_logic;
+-
+--- Row and column addressing is handled externally. We just need to
+--- keep track of which of the 10 lines we are on within the character...
+-signal line_counter : unsigned(3 downto 0);
+--- ... and which of the 6 pixels we are on within each line
+-signal pixel_counter : unsigned(2 downto 0);
+--- We also need to count frames to implement the flash feature.
+--- The datasheet says this is 0.75 Hz with a 3:1 on/off ratio, so it
+--- is probably a /64 counter, which gives us 0.78 Hz
+-signal flash_counter : unsigned(5 downto 0);
+--- Output shift register
+-signal shift_reg : std_logic_vector(5 downto 0);
+-
+--- Flash mask
+-signal flash : std_logic;
+-
+--- Current display state
+--- Foreground colour (B2, G1, R0)
+-signal fg : std_logic_vector(2 downto 0);
+--- Background colour (B2, G1, R0)
+-signal bg : std_logic_vector(2 downto 0);
+-signal conceal : std_logic;
+-signal gfx : std_logic;
+-signal gfx_sep : std_logic;
+-signal gfx_hold : std_logic;
+-signal is_flash : std_logic;
+-signal double_high : std_logic;
+--- Set in first row of double height
+-signal double_high1 : std_logic;
+--- Set in second row of double height
+-signal double_high2 : std_logic;
+-
+-begin
+- char_rom: saa5050_rom port map (
+- rom_address,
+- CLOCK,
+- rom_data
+- );
+-
+- -- Generate flash signal for 3:1 ratio
+- flash <= flash_counter(5) and flash_counter(4);
+-
+- -- Sync inputs
+- process(DI_CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- di_r <= (others => '0');
+- dew_r <= '0';
+- lose_r <= '0';
+- elsif rising_edge(DI_CLOCK) and DI_CLKEN = '1' then
+- di_r <= DI;
+- dew_r <= DEW;
+- lose_r <= LOSE;
+- end if;
+- end process;
+-
+- -- Register data into pixel clock domain
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- code <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- code <= di_r;
+- end if;
+- end process;
+-
+- -- Generate character rom address in pixel clock domain
+- -- This is done combinatorially since all the inputs are already
+- -- registered and the address is re-registered by the ROM
+- line_addr <= line_counter when double_high = '0' else
+- ("0" & line_counter(3 downto 1)) when double_high2 = '0' else
+- ("0" & line_counter(3 downto 1)) + 5;
+- rom_address <= (others => '0') when (double_high = '0' and double_high2 = '1') else
+- gfx & code & std_logic_vector(line_addr);
+-
+- -- Character row and pixel counters
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- dew_latch <= '0';
+- lose_latch <= '0';
+- disp_enable <= '0';
+- disp_enable_latch <= '0';
+- double_high1 <= '0';
+- double_high2 <= '0';
+- line_counter <= (others => '0');
+- pixel_counter <= (others => '0');
+- flash_counter <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Register syncs for edge detection
+- dew_latch <= dew_r;
+- lose_latch <= lose_r;
+- disp_enable_latch <= disp_enable;
+-
+- -- When first entering double-height mode start on top row
+- if double_high = '1' and double_high1 = '0' and double_high2 = '0' then
+- double_high1 <= '1';
+- end if;
+-
+- -- Count pixels between 0 and 5
+- if pixel_counter = 5 then
+- -- Start of next character and delayed display enable
+- pixel_counter <= (others => '0');
+- disp_enable <= lose_latch;
+- else
+- pixel_counter <= pixel_counter + 1;
+- end if;
+-
+- -- Rising edge of LOSE is the start of the active line
+- if lose_r = '1' and lose_latch = '0' then
+- -- Reset pixel counter - small offset to make the output
+- -- line up with the cursor from the video ULA
+- pixel_counter <= "011";
+- end if;
+-
+- -- Count frames on end of VSYNC (falling edge of DEW)
+- if dew_r = '0' and dew_latch = '1' then
+- flash_counter <= flash_counter + 1;
+- end if;
+-
+- if dew_r = '1' then
+- -- Reset line counter and double height state during VSYNC
+- line_counter <= (others => '0');
+- double_high1 <= '0';
+- double_high2 <= '0';
+- else
+- -- Count lines on end of active video (falling edge of disp_enable)
+- if disp_enable = '0' and disp_enable_latch = '1' then
+- if line_counter = 9 then
+- line_counter <= (others => '0');
+-
+- -- Keep track of which row we are on for double-height
+- -- The double_high flag can be cleared before the end of a row, but if
+- -- double height characters are used anywhere on a row then the double_high1
+- -- flag will be set and remain set until the next row. This is used
+- -- to determine that the bottom half of the characters should be shown if
+- -- double_high is set once again on the row below.
+- double_high1 <= '0';
+- double_high2 <= double_high1;
+- else
+- line_counter <= line_counter + 1;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- -- Shift register
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- shift_reg <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- if disp_enable = '1' and pixel_counter = 0 then
+- -- Load the shift register with the ROM bit pattern
+- -- at the start of each character while disp_enable is asserted.
+- shift_reg <= rom_data(5 downto 0);
+-
+- -- If bit 7 of the ROM data is set then this is a graphics
+- -- character and separated/hold graphics modes apply.
+- -- We don't just assume this to be the case if gfx=1 because
+- -- these modes don't apply to caps even in graphics mode
+- if rom_data(7) = '1' then
+- -- Apply a mask for separated graphics mode
+- if gfx_sep = '1' then
+- shift_reg(5) <= '0';
+- shift_reg(2) <= '0';
+- if line_counter = 2 or line_counter = 6 or line_counter = 9 then
+- shift_reg <= (others => '0');
+- end if;
+- end if;
+- end if;
+- else
+- -- Pump the shift register
+- shift_reg <= shift_reg(4 downto 0) & "0";
+- end if;
+- end if;
+- end process;
+-
+- -- Control character handling
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- fg <= (others => '1');
+- bg <= (others => '0');
+- conceal <= '0';
+- gfx <= '0';
+- gfx_sep <= '0';
+- gfx_hold <= '0';
+- is_flash <= '0';
+- double_high <= '0';
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- if disp_enable = '0' then
+- -- Reset to start of line defaults
+- fg <= (others => '1');
+- bg <= (others => '0');
+- conceal <= '0';
+- gfx <= '0';
+- gfx_sep <= '0';
+- gfx_hold <= '0';
+- is_flash <= '0';
+- double_high <= '0';
+- elsif pixel_counter = 0 then
+- -- Latch new control codes at the start of each character
+- if code(6 downto 5) = "00" then
+- if code(3) = '0' then
+- -- Colour and graphics setting clears conceal mode
+- conceal <= '0';
+-
+- -- Select graphics or alpha mode
+- gfx <= code(4);
+-
+- -- 0 would be black but is not allowed so has no effect,
+- -- otherwise set the colour
+- if code(2 downto 0) /= "000" then
+- fg <= code(2 downto 0);
+- end if;
+- else
+- case code(4 downto 0) is
+- -- FLASH
+- when "01000" => is_flash <= '1';
+- -- STEADY
+- when "01001" => is_flash <= '0';
+- -- NORMAL HEIGHT
+- when "01100" => double_high <= '0';
+- -- DOUBLE HEIGHT
+- when "01101" => double_high <= '1';
+- -- CONCEAL
+- when "11000" => conceal <= '1';
+- -- CONTIGUOUS GFX
+- when "11001" => gfx_sep <= '0';
+- -- SEPARATED GFX
+- when "11010" => gfx_sep <= '1';
+- -- BLACK BACKGROUND
+- when "11100" => bg <= (others => '0');
+- -- NEW BACKGROUND
+- when "11101" => bg <= fg;
+- -- HOLD GFX
+- when "11110" => gfx_hold <= '1';
+- -- RELEASE GFX
+- when "11111" => gfx_hold <= '0';
+-
+- when others => null;
+- end case;
+- end if;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- -- Output
+- process(CLOCK,nRESET)
+- variable pixel : std_logic;
+- begin
+- pixel := shift_reg(5) and not ((flash and is_flash) or conceal);
+-
+- if nRESET = '0' then
+- R <= '0';
+- G <= '0';
+- B <= '0';
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Generate mono output
+- Y <= pixel;
+-
+- -- Generate colour output
+- if pixel = '1' then
+- R <= fg(0);
+- G <= fg(1);
+- B <= fg(2);
+- else
+- R <= bg(0);
+- G <= bg(1);
+- B <= bg(2);
+- end if;
+- end if;
+- end process;
+-end architecture;
++-- BBC Micro for Altera DE1
++--
++-- Copyright (c) 2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++-- SAA5050 teletext generator
++--
++-- Synchronous implementation for FPGA. Certain TV-specific functions are
++-- not implemented. e.g.
++--
++-- No /SI pin - 'TEXT' mode is permanently enabled
++-- No remote control features (/DATA, DLIM)
++-- No large character support
++-- No support for box overlay (BLAN, PO, DE)
++-- No character rounding, although this may be added
++--
++-- FIXME: Hold graphics not supported - this needs to be added
++--
++-- (C) 2011 Mike Stirling
++--
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.NUMERIC_STD.ALL;
++
++entity saa5050 is
++port (
++ CLOCK : in std_logic;
++ -- 6 MHz dot clock enable
++ CLKEN : in std_logic;
++ -- Async reset
++ nRESET : in std_logic;
++
++ -- Character data input (in the bus clock domain)
++ DI_CLOCK : in std_logic;
++ DI_CLKEN : in std_logic;
++ DI : in std_logic_vector(6 downto 0);
++
++ -- Timing inputs
++ -- General line reset (not used)
++ GLR : in std_logic; -- /HSYNC
++ -- Data entry window - high during VSYNC.
++ -- Resets ROM row counter and drives 'flash' signal
++ DEW : in std_logic; -- VSYNC
++ -- Character rounding select - high during even field
++ CRS : in std_logic; -- FIELD
++ -- Load output shift register enable - high during active video
++ LOSE : in std_logic; -- DE
++
++ -- Video out
++ R : out std_logic;
++ G : out std_logic;
++ B : out std_logic;
++ Y : out std_logic
++ );
++end entity;
++
++architecture rtl of saa5050 is
++
++component saa5050_rom IS
++ PORT
++ (
++ address : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
++ clock : IN STD_LOGIC ;
++ q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
++ );
++end component;
++
++-- Register inputs in the bus clock domain
++signal di_r : std_logic_vector(6 downto 0);
++signal dew_r : std_logic;
++signal lose_r : std_logic;
++-- Data input registered in the pixel clock domain
++signal code : std_logic_vector(6 downto 0);
++signal line_addr : unsigned(3 downto 0);
++signal rom_address : std_logic_vector(11 downto 0);
++signal rom_data : std_logic_vector(7 downto 0);
++
++-- Delayed display enable derived from LOSE by delaying for one character
++signal disp_enable : std_logic;
++-- Latched timing signals for detection of falling edges
++signal dew_latch : std_logic;
++signal lose_latch : std_logic;
++signal disp_enable_latch : std_logic;
++
++-- Row and column addressing is handled externally. We just need to
++-- keep track of which of the 10 lines we are on within the character...
++signal line_counter : unsigned(3 downto 0);
++-- ... and which of the 6 pixels we are on within each line
++signal pixel_counter : unsigned(2 downto 0);
++-- We also need to count frames to implement the flash feature.
++-- The datasheet says this is 0.75 Hz with a 3:1 on/off ratio, so it
++-- is probably a /64 counter, which gives us 0.78 Hz
++signal flash_counter : unsigned(5 downto 0);
++-- Output shift register
++signal shift_reg : std_logic_vector(5 downto 0);
++
++-- Flash mask
++signal flash : std_logic;
++
++-- Current display state
++-- Foreground colour (B2, G1, R0)
++signal fg : std_logic_vector(2 downto 0);
++-- Background colour (B2, G1, R0)
++signal bg : std_logic_vector(2 downto 0);
++signal conceal : std_logic;
++signal gfx : std_logic;
++signal gfx_sep : std_logic;
++signal gfx_hold : std_logic;
++signal is_flash : std_logic;
++signal double_high : std_logic;
++-- Set in first row of double height
++signal double_high1 : std_logic;
++-- Set in second row of double height
++signal double_high2 : std_logic;
++
++begin
++ char_rom: saa5050_rom port map (
++ rom_address,
++ CLOCK,
++ rom_data
++ );
++
++ -- Generate flash signal for 3:1 ratio
++ flash <= flash_counter(5) and flash_counter(4);
++
++ -- Sync inputs
++ process(DI_CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ di_r <= (others => '0');
++ dew_r <= '0';
++ lose_r <= '0';
++ elsif rising_edge(DI_CLOCK) and DI_CLKEN = '1' then
++ di_r <= DI;
++ dew_r <= DEW;
++ lose_r <= LOSE;
++ end if;
++ end process;
++
++ -- Register data into pixel clock domain
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ code <= (others => '0');
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ code <= di_r;
++ end if;
++ end process;
++
++ -- Generate character rom address in pixel clock domain
++ -- This is done combinatorially since all the inputs are already
++ -- registered and the address is re-registered by the ROM
++ line_addr <= line_counter when double_high = '0' else
++ ("0" & line_counter(3 downto 1)) when double_high2 = '0' else
++ ("0" & line_counter(3 downto 1)) + 5;
++ rom_address <= (others => '0') when (double_high = '0' and double_high2 = '1') else
++ gfx & code & std_logic_vector(line_addr);
++
++ -- Character row and pixel counters
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ dew_latch <= '0';
++ lose_latch <= '0';
++ disp_enable <= '0';
++ disp_enable_latch <= '0';
++ double_high1 <= '0';
++ double_high2 <= '0';
++ line_counter <= (others => '0');
++ pixel_counter <= (others => '0');
++ flash_counter <= (others => '0');
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ -- Register syncs for edge detection
++ dew_latch <= dew_r;
++ lose_latch <= lose_r;
++ disp_enable_latch <= disp_enable;
++
++ -- When first entering double-height mode start on top row
++ if double_high = '1' and double_high1 = '0' and double_high2 = '0' then
++ double_high1 <= '1';
++ end if;
++
++ -- Count pixels between 0 and 5
++ if pixel_counter = 5 then
++ -- Start of next character and delayed display enable
++ pixel_counter <= (others => '0');
++ disp_enable <= lose_latch;
++ else
++ pixel_counter <= pixel_counter + 1;
++ end if;
++
++ -- Rising edge of LOSE is the start of the active line
++ if lose_r = '1' and lose_latch = '0' then
++ -- Reset pixel counter - small offset to make the output
++ -- line up with the cursor from the video ULA
++ pixel_counter <= "011";
++ end if;
++
++ -- Count frames on end of VSYNC (falling edge of DEW)
++ if dew_r = '0' and dew_latch = '1' then
++ flash_counter <= flash_counter + 1;
++ end if;
++
++ if dew_r = '1' then
++ -- Reset line counter and double height state during VSYNC
++ line_counter <= (others => '0');
++ double_high1 <= '0';
++ double_high2 <= '0';
++ else
++ -- Count lines on end of active video (falling edge of disp_enable)
++ if disp_enable = '0' and disp_enable_latch = '1' then
++ if line_counter = 9 then
++ line_counter <= (others => '0');
++
++ -- Keep track of which row we are on for double-height
++ -- The double_high flag can be cleared before the end of a row, but if
++ -- double height characters are used anywhere on a row then the double_high1
++ -- flag will be set and remain set until the next row. This is used
++ -- to determine that the bottom half of the characters should be shown if
++ -- double_high is set once again on the row below.
++ double_high1 <= '0';
++ double_high2 <= double_high1;
++ else
++ line_counter <= line_counter + 1;
++ end if;
++ end if;
++ end if;
++ end if;
++ end process;
++
++ -- Shift register
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ shift_reg <= (others => '0');
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ if disp_enable = '1' and pixel_counter = 0 then
++ -- Load the shift register with the ROM bit pattern
++ -- at the start of each character while disp_enable is asserted.
++ shift_reg <= rom_data(5 downto 0);
++
++ -- If bit 7 of the ROM data is set then this is a graphics
++ -- character and separated/hold graphics modes apply.
++ -- We don't just assume this to be the case if gfx=1 because
++ -- these modes don't apply to caps even in graphics mode
++ if rom_data(7) = '1' then
++ -- Apply a mask for separated graphics mode
++ if gfx_sep = '1' then
++ shift_reg(5) <= '0';
++ shift_reg(2) <= '0';
++ if line_counter = 2 or line_counter = 6 or line_counter = 9 then
++ shift_reg <= (others => '0');
++ end if;
++ end if;
++ end if;
++ else
++ -- Pump the shift register
++ shift_reg <= shift_reg(4 downto 0) & "0";
++ end if;
++ end if;
++ end process;
++
++ -- Control character handling
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ fg <= (others => '1');
++ bg <= (others => '0');
++ conceal <= '0';
++ gfx <= '0';
++ gfx_sep <= '0';
++ gfx_hold <= '0';
++ is_flash <= '0';
++ double_high <= '0';
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ if disp_enable = '0' then
++ -- Reset to start of line defaults
++ fg <= (others => '1');
++ bg <= (others => '0');
++ conceal <= '0';
++ gfx <= '0';
++ gfx_sep <= '0';
++ gfx_hold <= '0';
++ is_flash <= '0';
++ double_high <= '0';
++ elsif pixel_counter = 0 then
++ -- Latch new control codes at the start of each character
++ if code(6 downto 5) = "00" then
++ if code(3) = '0' then
++ -- Colour and graphics setting clears conceal mode
++ conceal <= '0';
++
++ -- Select graphics or alpha mode
++ gfx <= code(4);
++
++ -- 0 would be black but is not allowed so has no effect,
++ -- otherwise set the colour
++ if code(2 downto 0) /= "000" then
++ fg <= code(2 downto 0);
++ end if;
++ else
++ case code(4 downto 0) is
++ -- FLASH
++ when "01000" => is_flash <= '1';
++ -- STEADY
++ when "01001" => is_flash <= '0';
++ -- NORMAL HEIGHT
++ when "01100" => double_high <= '0';
++ -- DOUBLE HEIGHT
++ when "01101" => double_high <= '1';
++ -- CONCEAL
++ when "11000" => conceal <= '1';
++ -- CONTIGUOUS GFX
++ when "11001" => gfx_sep <= '0';
++ -- SEPARATED GFX
++ when "11010" => gfx_sep <= '1';
++ -- BLACK BACKGROUND
++ when "11100" => bg <= (others => '0');
++ -- NEW BACKGROUND
++ when "11101" => bg <= fg;
++ -- HOLD GFX
++ when "11110" => gfx_hold <= '1';
++ -- RELEASE GFX
++ when "11111" => gfx_hold <= '0';
++
++ when others => null;
++ end case;
++ end if;
++ end if;
++ end if;
++ end if;
++ end process;
++
++ -- Output
++ process(CLOCK,nRESET)
++ variable pixel : std_logic;
++ begin
++ pixel := shift_reg(5) and not ((flash and is_flash) or conceal);
++
++ if nRESET = '0' then
++ R <= '0';
++ G <= '0';
++ B <= '0';
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ -- Generate mono output
++ Y <= pixel;
++
++ -- Generate colour output
++ if pixel = '1' then
++ R <= fg(0);
++ G <= fg(1);
++ B <= fg(2);
++ else
++ R <= bg(0);
++ G <= bg(1);
++ B <= bg(2);
++ end if;
++ end if;
++ end process;
++end architecture;
+diff --git a/saa5050_rom.qip b/saa5050_rom.qip
+index e9513f7..be776f1 100644
+--- a/saa5050_rom.qip
++++ b/saa5050_rom.qip
+@@ -1,3 +1,3 @@
+-set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT"
+-set_global_assignment -name IP_TOOL_VERSION "9.1"
+-set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "saa5050_rom.vhd"]
++set_global_assignment -name IP_TOOL_NAME "ROM: 1-PORT"
++set_global_assignment -name IP_TOOL_VERSION "9.1"
++set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "saa5050_rom.vhd"]
+diff --git a/saa5050_rom.vhd b/saa5050_rom.vhd
+index 7541c0b..e1c702d 100644
+--- a/saa5050_rom.vhd
++++ b/saa5050_rom.vhd
+@@ -1,168 +1,168 @@
+--- megafunction wizard: %ROM: 1-PORT%
+--- GENERATION: STANDARD
+--- VERSION: WM1.0
+--- MODULE: altsyncram
+-
+--- ============================================================
+--- File Name: saa5050_rom.vhd
+--- Megafunction Name(s):
+--- altsyncram
+---
+--- Simulation Library Files(s):
+--- altera_mf
+--- ============================================================
+--- ************************************************************
+--- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+---
+--- 9.1 Build 222 10/21/2009 SJ Web Edition
+--- ************************************************************
+-
+-
+---Copyright (C) 1991-2009 Altera Corporation
+---Your use of Altera Corporation's design tools, logic functions
+---and other software and tools, and its AMPP partner logic
+---functions, and any output files from any of the foregoing
+---(including device programming or simulation files), and any
+---associated documentation or information are expressly subject
+---to the terms and conditions of the Altera Program License
+---Subscription Agreement, Altera MegaCore Function License
+---Agreement, or other applicable license agreement, including,
+---without limitation, that your use is for the sole purpose of
+---programming logic devices manufactured by Altera and sold by
+---Altera or its authorized distributors. Please refer to the
+---applicable agreement for further details.
+-
+-
+-LIBRARY ieee;
+-USE ieee.std_logic_1164.all;
+-
+-LIBRARY altera_mf;
+-USE altera_mf.all;
+-
+-ENTITY saa5050_rom IS
+- PORT
+- (
+- address : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
+- clock : IN STD_LOGIC ;
+- q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
+- );
+-END saa5050_rom;
+-
+-
+-ARCHITECTURE SYN OF saa5050_rom IS
+-
+- SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
+-
+-
+-
+- COMPONENT altsyncram
+- GENERIC (
+- clock_enable_input_a : STRING;
+- clock_enable_output_a : STRING;
+- init_file : STRING;
+- intended_device_family : STRING;
+- lpm_hint : STRING;
+- lpm_type : STRING;
+- numwords_a : NATURAL;
+- operation_mode : STRING;
+- outdata_aclr_a : STRING;
+- outdata_reg_a : STRING;
+- widthad_a : NATURAL;
+- width_a : NATURAL;
+- width_byteena_a : NATURAL
+- );
+- PORT (
+- clock0 : IN STD_LOGIC ;
+- address_a : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
+- q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
+- );
+- END COMPONENT;
+-
+-BEGIN
+- q <= sub_wire0(7 DOWNTO 0);
+-
+- altsyncram_component : altsyncram
+- GENERIC MAP (
+- clock_enable_input_a => "BYPASS",
+- clock_enable_output_a => "BYPASS",
+- init_file => "./roms/saa5050/saa5050.hex",
+- intended_device_family => "Cyclone II",
+- lpm_hint => "ENABLE_RUNTIME_MOD=NO",
+- lpm_type => "altsyncram",
+- numwords_a => 4096,
+- operation_mode => "ROM",
+- outdata_aclr_a => "NONE",
+- outdata_reg_a => "UNREGISTERED",
+- widthad_a => 12,
+- width_a => 8,
+- width_byteena_a => 1
+- )
+- PORT MAP (
+- clock0 => clock,
+- address_a => address,
+- q_a => sub_wire0
+- );
+-
+-
+-
+-END SYN;
+-
+--- ============================================================
+--- CNX file retrieval info
+--- ============================================================
+--- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
+--- Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
+--- Retrieval info: PRIVATE: AclrByte NUMERIC "0"
+--- Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
+--- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
+--- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
+--- Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
+--- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
+--- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
+--- Retrieval info: PRIVATE: Clken NUMERIC "0"
+--- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
+--- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
+--- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
+--- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+--- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
+--- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
+--- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
+--- Retrieval info: PRIVATE: MIFfilename STRING "./roms/saa5050/saa5050.hex"
+--- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096"
+--- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
+--- Retrieval info: PRIVATE: RegAddr NUMERIC "1"
+--- Retrieval info: PRIVATE: RegOutput NUMERIC "0"
+--- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
+--- Retrieval info: PRIVATE: SingleClock NUMERIC "1"
+--- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
+--- Retrieval info: PRIVATE: WidthAddr NUMERIC "12"
+--- Retrieval info: PRIVATE: WidthData NUMERIC "8"
+--- Retrieval info: PRIVATE: rden NUMERIC "0"
+--- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
+--- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
+--- Retrieval info: CONSTANT: INIT_FILE STRING "./roms/saa5050/saa5050.hex"
+--- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+--- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
+--- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
+--- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096"
+--- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
+--- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
+--- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
+--- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12"
+--- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
+--- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
+--- Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL address[11..0]
+--- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
+--- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0]
+--- Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 0
+--- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
+--- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
+--- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.vhd TRUE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.inc FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.cmp FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.bsf FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_inst.vhd FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_waveforms.html FALSE
+--- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_wave*.jpg FALSE
+--- Retrieval info: LIB_FILE: altera_mf
++-- megafunction wizard: %ROM: 1-PORT%
++-- GENERATION: STANDARD
++-- VERSION: WM1.0
++-- MODULE: altsyncram
++
++-- ============================================================
++-- File Name: saa5050_rom.vhd
++-- Megafunction Name(s):
++-- altsyncram
++--
++-- Simulation Library Files(s):
++-- altera_mf
++-- ============================================================
++-- ************************************************************
++-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
++--
++-- 9.1 Build 222 10/21/2009 SJ Web Edition
++-- ************************************************************
++
++
++--Copyright (C) 1991-2009 Altera Corporation
++--Your use of Altera Corporation's design tools, logic functions
++--and other software and tools, and its AMPP partner logic
++--functions, and any output files from any of the foregoing
++--(including device programming or simulation files), and any
++--associated documentation or information are expressly subject
++--to the terms and conditions of the Altera Program License
++--Subscription Agreement, Altera MegaCore Function License
++--Agreement, or other applicable license agreement, including,
++--without limitation, that your use is for the sole purpose of
++--programming logic devices manufactured by Altera and sold by
++--Altera or its authorized distributors. Please refer to the
++--applicable agreement for further details.
++
++
++LIBRARY ieee;
++USE ieee.std_logic_1164.all;
++
++LIBRARY altera_mf;
++USE altera_mf.all;
++
++ENTITY saa5050_rom IS
++ PORT
++ (
++ address : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
++ clock : IN STD_LOGIC ;
++ q : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
++ );
++END saa5050_rom;
++
++
++ARCHITECTURE SYN OF saa5050_rom IS
++
++ SIGNAL sub_wire0 : STD_LOGIC_VECTOR (7 DOWNTO 0);
++
++
++
++ COMPONENT altsyncram
++ GENERIC (
++ clock_enable_input_a : STRING;
++ clock_enable_output_a : STRING;
++ init_file : STRING;
++ intended_device_family : STRING;
++ lpm_hint : STRING;
++ lpm_type : STRING;
++ numwords_a : NATURAL;
++ operation_mode : STRING;
++ outdata_aclr_a : STRING;
++ outdata_reg_a : STRING;
++ widthad_a : NATURAL;
++ width_a : NATURAL;
++ width_byteena_a : NATURAL
++ );
++ PORT (
++ clock0 : IN STD_LOGIC ;
++ address_a : IN STD_LOGIC_VECTOR (11 DOWNTO 0);
++ q_a : OUT STD_LOGIC_VECTOR (7 DOWNTO 0)
++ );
++ END COMPONENT;
++
++BEGIN
++ q <= sub_wire0(7 DOWNTO 0);
++
++ altsyncram_component : altsyncram
++ GENERIC MAP (
++ clock_enable_input_a => "BYPASS",
++ clock_enable_output_a => "BYPASS",
++ init_file => "./roms/saa5050/saa5050.hex",
++ intended_device_family => "Cyclone II",
++ lpm_hint => "ENABLE_RUNTIME_MOD=NO",
++ lpm_type => "altsyncram",
++ numwords_a => 4096,
++ operation_mode => "ROM",
++ outdata_aclr_a => "NONE",
++ outdata_reg_a => "UNREGISTERED",
++ widthad_a => 12,
++ width_a => 8,
++ width_byteena_a => 1
++ )
++ PORT MAP (
++ clock0 => clock,
++ address_a => address,
++ q_a => sub_wire0
++ );
++
++
++
++END SYN;
++
++-- ============================================================
++-- CNX file retrieval info
++-- ============================================================
++-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
++-- Retrieval info: PRIVATE: AclrAddr NUMERIC "0"
++-- Retrieval info: PRIVATE: AclrByte NUMERIC "0"
++-- Retrieval info: PRIVATE: AclrOutput NUMERIC "0"
++-- Retrieval info: PRIVATE: BYTE_ENABLE NUMERIC "0"
++-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "8"
++-- Retrieval info: PRIVATE: BlankMemory NUMERIC "0"
++-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "0"
++-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "0"
++-- Retrieval info: PRIVATE: Clken NUMERIC "0"
++-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
++-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_A"
++-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "0"
++-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
++-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
++-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
++-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
++-- Retrieval info: PRIVATE: MIFfilename STRING "./roms/saa5050/saa5050.hex"
++-- Retrieval info: PRIVATE: NUMWORDS_A NUMERIC "4096"
++-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
++-- Retrieval info: PRIVATE: RegAddr NUMERIC "1"
++-- Retrieval info: PRIVATE: RegOutput NUMERIC "0"
++-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
++-- Retrieval info: PRIVATE: SingleClock NUMERIC "1"
++-- Retrieval info: PRIVATE: UseDQRAM NUMERIC "0"
++-- Retrieval info: PRIVATE: WidthAddr NUMERIC "12"
++-- Retrieval info: PRIVATE: WidthData NUMERIC "8"
++-- Retrieval info: PRIVATE: rden NUMERIC "0"
++-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "BYPASS"
++-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
++-- Retrieval info: CONSTANT: INIT_FILE STRING "./roms/saa5050/saa5050.hex"
++-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
++-- Retrieval info: CONSTANT: LPM_HINT STRING "ENABLE_RUNTIME_MOD=NO"
++-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
++-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "4096"
++-- Retrieval info: CONSTANT: OPERATION_MODE STRING "ROM"
++-- Retrieval info: CONSTANT: OUTDATA_ACLR_A STRING "NONE"
++-- Retrieval info: CONSTANT: OUTDATA_REG_A STRING "UNREGISTERED"
++-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "12"
++-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "8"
++-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
++-- Retrieval info: USED_PORT: address 0 0 12 0 INPUT NODEFVAL address[11..0]
++-- Retrieval info: USED_PORT: clock 0 0 0 0 INPUT NODEFVAL clock
++-- Retrieval info: USED_PORT: q 0 0 8 0 OUTPUT NODEFVAL q[7..0]
++-- Retrieval info: CONNECT: @address_a 0 0 12 0 address 0 0 12 0
++-- Retrieval info: CONNECT: q 0 0 8 0 @q_a 0 0 8 0
++-- Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
++-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.vhd TRUE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.inc FALSE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.cmp FALSE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom.bsf FALSE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_inst.vhd FALSE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_waveforms.html FALSE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL saa5050_rom_wave*.jpg FALSE
++-- Retrieval info: LIB_FILE: altera_mf
+diff --git a/seg7.vhd b/seg7.vhd
+index a61e679..566b1f6 100644
+--- a/seg7.vhd
++++ b/seg7.vhd
+@@ -1,68 +1,68 @@
+--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2009-2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+-
+-library ieee;
+-use ieee.std_logic_1164.all;
+-
+--- Convert BCD to 7-segment display characters
+-entity seg7 is
+-port (
+- D : in std_logic_vector(3 downto 0);
+- Q : out std_logic_vector(6 downto 0)
+-);
+-end seg7;
+-
+-architecture seg7_arch of seg7 is
+-begin
+- Q <= "1000000" when D = "0000" else
+- "1111001" when D = "0001" else
+- "0100100" when D = "0010" else
+- "0110000" when D = "0011" else
+- "0011001" when D = "0100" else
+- "0010010" when D = "0101" else
+- "0000010" when D = "0110" else
+- "1111000" when D = "0111" else
+- "0000000" when D = "1000" else
+- "0010000" when D = "1001" else
+- "0001000" when D = "1010" else
+- "0000011" when D = "1011" else
+- "1000110" when D = "1100" else
+- "0100001" when D = "1101" else
+- "0000110" when D = "1110" else
+- "0001110";
+-end seg7_arch;
+-
++-- BBC Micro for Altera DE1
++--
++-- Copyright (c) 2009-2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++
++library ieee;
++use ieee.std_logic_1164.all;
++
++-- Convert BCD to 7-segment display characters
++entity seg7 is
++port (
++ D : in std_logic_vector(3 downto 0);
++ Q : out std_logic_vector(6 downto 0)
++);
++end seg7;
++
++architecture seg7_arch of seg7 is
++begin
++ Q <= "1000000" when D = "0000" else
++ "1111001" when D = "0001" else
++ "0100100" when D = "0010" else
++ "0110000" when D = "0011" else
++ "0011001" when D = "0100" else
++ "0010010" when D = "0101" else
++ "0000010" when D = "0110" else
++ "1111000" when D = "0111" else
++ "0000000" when D = "1000" else
++ "0010000" when D = "1001" else
++ "0001000" when D = "1010" else
++ "0000011" when D = "1011" else
++ "1000110" when D = "1100" else
++ "0100001" when D = "1101" else
++ "0000110" when D = "1110" else
++ "0001110";
++end seg7_arch;
++
+diff --git a/sn76489-1.0/sn76489_top.vhd b/sn76489-1.0/sn76489_top.vhd
+index 277f601..deb8170 100644
+--- a/sn76489-1.0/sn76489_top.vhd
++++ b/sn76489-1.0/sn76489_top.vhd
+@@ -196,15 +196,15 @@ begin
+ noise_o => noise_s
+ );
+
+-
++
+ -- Register output
+- process(clock_i)
+- begin
+- if res_n_i = '0' then
+- aout_o <= (others => '0');
+- elsif rising_edge(clock_i) then
+- aout_o <= tone1_s + tone2_s + tone3_s + noise_s;
+- end if;
+- end process;
++ process(clock_i)
++ begin
++ if res_n_i = '0' then
++ aout_o <= (others => '0');
++ elsif rising_edge(clock_i) then
++ aout_o <= tone1_s + tone2_s + tone3_s + noise_s;
++ end if;
++ end process;
+
+ end struct;
+diff --git a/vidproc.vhd b/vidproc.vhd
+index 6d5f91f..25f3d75 100644
+--- a/vidproc.vhd
++++ b/vidproc.vhd
+@@ -1,279 +1,279 @@
+--- BBC Micro for Altera DE1
+---
+--- Copyright (c) 2011 Mike Stirling
+---
+--- 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 agreement from the author.
+---
+--- * License is granted for non-commercial use only. A fee may not be charged
+--- for redistributions as source code or in synthesized/hardware form without
+--- specific prior written agreement from the author.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- BBC Micro "VIDPROC" Video ULA
+---
+--- Synchronous implementation for FPGA
+---
+--- (C) 2011 Mike Stirling
+---
+-library IEEE;
+-use IEEE.STD_LOGIC_1164.ALL;
+-use IEEE.NUMERIC_STD.ALL;
+-
+-entity vidproc is
+-port (
+- CLOCK : in std_logic;
+- -- Clock enable qualifies display cycles (interleaved with CPU cycles)
+- CLKEN : in std_logic;
+- nRESET : in std_logic;
+-
+- -- Clock enable output to CRTC
+- CLKEN_CRTC : out std_logic;
+-
+- -- Bus interface
+- ENABLE : in std_logic;
+- A0 : in std_logic;
+- -- CPU data bus (for register writes)
+- DI_CPU : in std_logic_vector(7 downto 0);
+- -- Display RAM data bus (for display data fetch)
+- DI_RAM : in std_logic_vector(7 downto 0);
+-
+- -- Control interface
+- nINVERT : in std_logic;
+- DISEN : in std_logic;
+- CURSOR : in std_logic;
+-
+- -- Video in (teletext mode)
+- R_IN : in std_logic;
+- G_IN : in std_logic;
+- B_IN : in std_logic;
+-
+- -- Video out
+- R : out std_logic;
+- G : out std_logic;
+- B : out std_logic
+- );
+-end entity;
+-
+-architecture rtl of vidproc is
+--- Write-only registers
+-signal r0_cursor0 : std_logic;
+-signal r0_cursor1 : std_logic;
+-signal r0_cursor2 : std_logic;
+-signal r0_crtc_2mhz : std_logic;
+-signal r0_pixel_rate : std_logic_vector(1 downto 0);
+-signal r0_teletext : std_logic;
+-signal r0_flash : std_logic;
+-
+-type palette_t is array(0 to 15) of std_logic_vector(3 downto 0);
+-signal palette : palette_t;
+-
+--- Pixel shift register
+-signal shiftreg : std_logic_vector(7 downto 0);
+--- Delayed display enable
+-signal delayed_disen : std_logic;
+-
+--- Internal clock enable generation
+-signal clken_pixel : std_logic;
+-signal clken_fetch : std_logic;
+-signal clken_counter : unsigned(3 downto 0);
+-
+--- Cursor generation - can span up to 32 pixels
+--- Segments 0 and 1 are 8 pixels wide
+--- Segment 2 is 16 pixels wide
+-signal cursor_invert : std_logic;
+-signal cursor_active : std_logic;
+-signal cursor_counter : unsigned(1 downto 0);
+-
+-begin
+- -- Synchronous register access, enabled on every clock
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- r0_cursor0 <= '0';
+- r0_cursor1 <= '0';
+- r0_cursor2 <= '0';
+- r0_crtc_2mhz <= '0';
+- r0_pixel_rate <= "00";
+- r0_teletext <= '0';
+- r0_flash <= '0';
+-
+- for colour in 0 to 15 loop
+- palette(colour) <= (others => '0');
+- end loop;
+- elsif rising_edge(CLOCK) then
+- if ENABLE = '1' then
+- if A0 = '0' then
+- -- Access control register
+- r0_cursor0 <= DI_CPU(7);
+- r0_cursor1 <= DI_CPU(6);
+- r0_cursor2 <= DI_CPU(5);
+- r0_crtc_2mhz <= DI_CPU(4);
+- r0_pixel_rate <= DI_CPU(3 downto 2);
+- r0_teletext <= DI_CPU(1);
+- r0_flash <= DI_CPU(0);
+- else
+- -- Access palette register
+- palette(to_integer(unsigned(DI_CPU(7 downto 4)))) <= DI_CPU(3 downto 0);
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- -- Clock enable generation.
+- -- Pixel clock can be divided by 1,2,4 or 8 depending on the value
+- -- programmed at r0_pixel_rate
+- -- 00 = /8, 01 = /4, 10 = /2, 11 = /1
+- clken_pixel <=
+- CLKEN when r0_pixel_rate = "11" else
+- (CLKEN and not clken_counter(0)) when r0_pixel_rate = "10" else
+- (CLKEN and not (clken_counter(0) or clken_counter(1))) when r0_pixel_rate = "01" else
+- (CLKEN and not (clken_counter(0) or clken_counter(1) or clken_counter(2)));
+- -- The CRT controller is always enabled in the 15th cycle, so that the result
+- -- is ready for latching into the shift register in cycle 0. If 2 MHz mode is
+- -- selected then the CRTC is also enabled in the 7th cycle
+- CLKEN_CRTC <= CLKEN and
+- clken_counter(0) and clken_counter(1) and clken_counter(2) and
+- (clken_counter(3) or r0_crtc_2mhz);
+- -- The result is fetched from the CRTC in cycle 0 and also cycle 8 if 2 MHz
+- -- mode is selected. This is used for reloading the shift register as well as
+- -- counting cursor pixels
+- clken_fetch <= CLKEN and not (clken_counter(0) or clken_counter(1) or clken_counter(2) or
+- (clken_counter(3) and not r0_crtc_2mhz));
+-
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- clken_counter <= (others => '0');
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Increment internal cycle counter during each video clock
+- clken_counter <= clken_counter + 1;
+- end if;
+- end process;
+-
+- -- Fetch control
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- shiftreg <= (others => '0');
+- elsif rising_edge(CLOCK) and clken_pixel = '1' then
+- if clken_fetch = '1' then
+- -- Fetch next byte from RAM into shift register. This always occurs in
+- -- cycle 0, and also in cycle 8 if the CRTC is clocked at double rate.
+- shiftreg <= DI_RAM;
+- else
+- -- Clock shift register and input '1' at LSB
+- shiftreg <= shiftreg(6 downto 0) & "1";
+- end if;
+- end if;
+- end process;
+-
+- -- Cursor generation
+- cursor_invert <= cursor_active and
+- ((r0_cursor0 and not (cursor_counter(0) or cursor_counter(1))) or
+- (r0_cursor1 and cursor_counter(0) and not cursor_counter(1)) or
+- (r0_cursor2 and cursor_counter(1)));
+- process(CLOCK,nRESET)
+- begin
+- if nRESET = '0' then
+- cursor_active <= '0';
+- cursor_counter <= (others => '0');
+- elsif rising_edge(CLOCK) and clken_fetch = '1' then
+- if CURSOR = '1' or cursor_active = '1' then
+- -- Latch cursor
+- cursor_active <= '1';
+-
+- -- Reset on counter wrap
+- if cursor_counter = "11" then
+- cursor_active <= '0';
+- end if;
+-
+- -- Increment counter
+- if cursor_active = '0' then
+- -- Reset
+- cursor_counter <= (others => '0');
+- else
+- -- Increment
+- cursor_counter <= cursor_counter + 1;
+- end if;
+- end if;
+- end if;
+- end process;
+-
+- -- Pixel generation
+- -- The new shift register contents are loaded during
+- -- cycle 0 (and 8) but will not be read here until the next cycle.
+- -- By running this process on every single video tick instead of at
+- -- the pixel rate we ensure that the resulting delay is minimal and
+- -- constant (running this at the pixel rate would cause
+- -- the display to move slightly depending on which mode was selected).
+- process(CLOCK,nRESET)
+- variable palette_a : std_logic_vector(3 downto 0);
+- variable dot_val : std_logic_vector(3 downto 0);
+- variable red_val : std_logic;
+- variable green_val : std_logic;
+- variable blue_val : std_logic;
+- begin
+- if nRESET = '0' then
+- R <= '0';
+- G <= '0';
+- B <= '0';
+- delayed_disen <= '0';
+- elsif rising_edge(CLOCK) and CLKEN = '1' then
+- -- Look up dot value in the palette. Bits are as follows:
+- -- bit 3 - FLASH
+- -- bit 2 - Not BLUE
+- -- bit 1 - Not GREEN
+- -- bit 0 - Not RED
+- palette_a := shiftreg(7) & shiftreg(5) & shiftreg(3) & shiftreg(1);
+- dot_val := palette(to_integer(unsigned(palette_a)));
+-
+- -- Apply flash inversion if required
+- red_val := (dot_val(3) and r0_flash) xor not dot_val(0);
+- green_val := (dot_val(3) and r0_flash) xor not dot_val(1);
+- blue_val := (dot_val(3) and r0_flash) xor not dot_val(2);
+-
+- -- To output
+- -- FIXME: INVERT option
+- if r0_teletext = '0' then
+- -- Cursor can extend outside the bounds of the screen, so
+- -- it is not affected by DISEN
+- R <= (red_val and delayed_disen) xor cursor_invert;
+- G <= (green_val and delayed_disen) xor cursor_invert;
+- B <= (blue_val and delayed_disen) xor cursor_invert;
+- else
+- R <= R_IN xor cursor_invert;
+- G <= G_IN xor cursor_invert;
+- B <= B_IN xor cursor_invert;
+- end if;
+-
+- -- Display enable signal delayed by one clock
+- delayed_disen <= DISEN;
+- end if;
+- end process;
+-end architecture;
+-
++-- BBC Micro for Altera DE1
++--
++-- Copyright (c) 2011 Mike Stirling
++--
++-- 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 agreement from the author.
++--
++-- * License is granted for non-commercial use only. A fee may not be charged
++-- for redistributions as source code or in synthesized/hardware form without
++-- specific prior written agreement from the author.
++--
++-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
++-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
++-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
++-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
++-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
++-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
++-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
++-- POSSIBILITY OF SUCH DAMAGE.
++--
++-- BBC Micro "VIDPROC" Video ULA
++--
++-- Synchronous implementation for FPGA
++--
++-- (C) 2011 Mike Stirling
++--
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.NUMERIC_STD.ALL;
++
++entity vidproc is
++port (
++ CLOCK : in std_logic;
++ -- Clock enable qualifies display cycles (interleaved with CPU cycles)
++ CLKEN : in std_logic;
++ nRESET : in std_logic;
++
++ -- Clock enable output to CRTC
++ CLKEN_CRTC : out std_logic;
++
++ -- Bus interface
++ ENABLE : in std_logic;
++ A0 : in std_logic;
++ -- CPU data bus (for register writes)
++ DI_CPU : in std_logic_vector(7 downto 0);
++ -- Display RAM data bus (for display data fetch)
++ DI_RAM : in std_logic_vector(7 downto 0);
++
++ -- Control interface
++ nINVERT : in std_logic;
++ DISEN : in std_logic;
++ CURSOR : in std_logic;
++
++ -- Video in (teletext mode)
++ R_IN : in std_logic;
++ G_IN : in std_logic;
++ B_IN : in std_logic;
++
++ -- Video out
++ R : out std_logic;
++ G : out std_logic;
++ B : out std_logic
++ );
++end entity;
++
++architecture rtl of vidproc is
++-- Write-only registers
++signal r0_cursor0 : std_logic;
++signal r0_cursor1 : std_logic;
++signal r0_cursor2 : std_logic;
++signal r0_crtc_2mhz : std_logic;
++signal r0_pixel_rate : std_logic_vector(1 downto 0);
++signal r0_teletext : std_logic;
++signal r0_flash : std_logic;
++
++type palette_t is array(0 to 15) of std_logic_vector(3 downto 0);
++signal palette : palette_t;
++
++-- Pixel shift register
++signal shiftreg : std_logic_vector(7 downto 0);
++-- Delayed display enable
++signal delayed_disen : std_logic;
++
++-- Internal clock enable generation
++signal clken_pixel : std_logic;
++signal clken_fetch : std_logic;
++signal clken_counter : unsigned(3 downto 0);
++
++-- Cursor generation - can span up to 32 pixels
++-- Segments 0 and 1 are 8 pixels wide
++-- Segment 2 is 16 pixels wide
++signal cursor_invert : std_logic;
++signal cursor_active : std_logic;
++signal cursor_counter : unsigned(1 downto 0);
++
++begin
++ -- Synchronous register access, enabled on every clock
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ r0_cursor0 <= '0';
++ r0_cursor1 <= '0';
++ r0_cursor2 <= '0';
++ r0_crtc_2mhz <= '0';
++ r0_pixel_rate <= "00";
++ r0_teletext <= '0';
++ r0_flash <= '0';
++
++ for colour in 0 to 15 loop
++ palette(colour) <= (others => '0');
++ end loop;
++ elsif rising_edge(CLOCK) then
++ if ENABLE = '1' then
++ if A0 = '0' then
++ -- Access control register
++ r0_cursor0 <= DI_CPU(7);
++ r0_cursor1 <= DI_CPU(6);
++ r0_cursor2 <= DI_CPU(5);
++ r0_crtc_2mhz <= DI_CPU(4);
++ r0_pixel_rate <= DI_CPU(3 downto 2);
++ r0_teletext <= DI_CPU(1);
++ r0_flash <= DI_CPU(0);
++ else
++ -- Access palette register
++ palette(to_integer(unsigned(DI_CPU(7 downto 4)))) <= DI_CPU(3 downto 0);
++ end if;
++ end if;
++ end if;
++ end process;
++
++ -- Clock enable generation.
++ -- Pixel clock can be divided by 1,2,4 or 8 depending on the value
++ -- programmed at r0_pixel_rate
++ -- 00 = /8, 01 = /4, 10 = /2, 11 = /1
++ clken_pixel <=
++ CLKEN when r0_pixel_rate = "11" else
++ (CLKEN and not clken_counter(0)) when r0_pixel_rate = "10" else
++ (CLKEN and not (clken_counter(0) or clken_counter(1))) when r0_pixel_rate = "01" else
++ (CLKEN and not (clken_counter(0) or clken_counter(1) or clken_counter(2)));
++ -- The CRT controller is always enabled in the 15th cycle, so that the result
++ -- is ready for latching into the shift register in cycle 0. If 2 MHz mode is
++ -- selected then the CRTC is also enabled in the 7th cycle
++ CLKEN_CRTC <= CLKEN and
++ clken_counter(0) and clken_counter(1) and clken_counter(2) and
++ (clken_counter(3) or r0_crtc_2mhz);
++ -- The result is fetched from the CRTC in cycle 0 and also cycle 8 if 2 MHz
++ -- mode is selected. This is used for reloading the shift register as well as
++ -- counting cursor pixels
++ clken_fetch <= CLKEN and not (clken_counter(0) or clken_counter(1) or clken_counter(2) or
++ (clken_counter(3) and not r0_crtc_2mhz));
++
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ clken_counter <= (others => '0');
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ -- Increment internal cycle counter during each video clock
++ clken_counter <= clken_counter + 1;
++ end if;
++ end process;
++
++ -- Fetch control
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ shiftreg <= (others => '0');
++ elsif rising_edge(CLOCK) and clken_pixel = '1' then
++ if clken_fetch = '1' then
++ -- Fetch next byte from RAM into shift register. This always occurs in
++ -- cycle 0, and also in cycle 8 if the CRTC is clocked at double rate.
++ shiftreg <= DI_RAM;
++ else
++ -- Clock shift register and input '1' at LSB
++ shiftreg <= shiftreg(6 downto 0) & "1";
++ end if;
++ end if;
++ end process;
++
++ -- Cursor generation
++ cursor_invert <= cursor_active and
++ ((r0_cursor0 and not (cursor_counter(0) or cursor_counter(1))) or
++ (r0_cursor1 and cursor_counter(0) and not cursor_counter(1)) or
++ (r0_cursor2 and cursor_counter(1)));
++ process(CLOCK,nRESET)
++ begin
++ if nRESET = '0' then
++ cursor_active <= '0';
++ cursor_counter <= (others => '0');
++ elsif rising_edge(CLOCK) and clken_fetch = '1' then
++ if CURSOR = '1' or cursor_active = '1' then
++ -- Latch cursor
++ cursor_active <= '1';
++
++ -- Reset on counter wrap
++ if cursor_counter = "11" then
++ cursor_active <= '0';
++ end if;
++
++ -- Increment counter
++ if cursor_active = '0' then
++ -- Reset
++ cursor_counter <= (others => '0');
++ else
++ -- Increment
++ cursor_counter <= cursor_counter + 1;
++ end if;
++ end if;
++ end if;
++ end process;
++
++ -- Pixel generation
++ -- The new shift register contents are loaded during
++ -- cycle 0 (and 8) but will not be read here until the next cycle.
++ -- By running this process on every single video tick instead of at
++ -- the pixel rate we ensure that the resulting delay is minimal and
++ -- constant (running this at the pixel rate would cause
++ -- the display to move slightly depending on which mode was selected).
++ process(CLOCK,nRESET)
++ variable palette_a : std_logic_vector(3 downto 0);
++ variable dot_val : std_logic_vector(3 downto 0);
++ variable red_val : std_logic;
++ variable green_val : std_logic;
++ variable blue_val : std_logic;
++ begin
++ if nRESET = '0' then
++ R <= '0';
++ G <= '0';
++ B <= '0';
++ delayed_disen <= '0';
++ elsif rising_edge(CLOCK) and CLKEN = '1' then
++ -- Look up dot value in the palette. Bits are as follows:
++ -- bit 3 - FLASH
++ -- bit 2 - Not BLUE
++ -- bit 1 - Not GREEN
++ -- bit 0 - Not RED
++ palette_a := shiftreg(7) & shiftreg(5) & shiftreg(3) & shiftreg(1);
++ dot_val := palette(to_integer(unsigned(palette_a)));
++
++ -- Apply flash inversion if required
++ red_val := (dot_val(3) and r0_flash) xor not dot_val(0);
++ green_val := (dot_val(3) and r0_flash) xor not dot_val(1);
++ blue_val := (dot_val(3) and r0_flash) xor not dot_val(2);
++
++ -- To output
++ -- FIXME: INVERT option
++ if r0_teletext = '0' then
++ -- Cursor can extend outside the bounds of the screen, so
++ -- it is not affected by DISEN
++ R <= (red_val and delayed_disen) xor cursor_invert;
++ G <= (green_val and delayed_disen) xor cursor_invert;
++ B <= (blue_val and delayed_disen) xor cursor_invert;
++ else
++ R <= R_IN xor cursor_invert;
++ G <= G_IN xor cursor_invert;
++ B <= B_IN xor cursor_invert;
++ end if;
++
++ -- Display enable signal delayed by one clock
++ delayed_disen <= DISEN;
++ end if;
++ end process;
++end architecture;
++
diff --git a/de1/fpga-bbc-pq/master/missing-process-sensitivity.patch b/de1/fpga-bbc-pq/master/missing-process-sensitivity.patch
new file mode 100644
index 0000000..994998a
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/missing-process-sensitivity.patch
@@ -0,0 +1,234 @@
+diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd
+index 194f93a..25b3b43 100644
+--- a/bbc_micro_de1.vhd
++++ b/bbc_micro_de1.vhd
+@@ -1012,7 +1012,7 @@ begin
+ end if;
+ end process;
+
+- cycle_stretch: process(clock,reset_n)
++ cycle_stretch: process(clock,reset_n,mhz2_clken)
+ begin
+ if reset_n = '0' then
+ cpu_cycle_mask <= '0';
+@@ -1170,7 +1170,7 @@ begin
+ video_data <= SRAM_DQ(7 downto 0);
+
+ -- Synchronous outputs to SRAM
+- process(clock,reset_n)
++ process(clock,reset_n,ram_enable,cpu_r_nw)
+ variable ram_write : std_logic;
+ begin
+ ram_write := ram_enable and not cpu_r_nw;
+@@ -1290,9 +1290,10 @@ begin
+ SD_nCS <= '0'; -- CS
+ user_via_cb2_in <= SD_MISO; -- SDI
+ user_via_pb_in <= user_via_pb_out;
++
+
+ -- ROM select latch
+- process(clock,reset_n)
++ process(clock,reset_n,romsel_enable)
+ begin
+ if reset_n = '0' then
+ romsel <= (others => '0');
+@@ -1313,7 +1314,7 @@ begin
+ shift_lock_led_n <= ic32(7);
+
+
+- process(clock,reset_n)
++ process(clock,reset_n,sys_via_pb_out)
+ variable bit_num : integer;
+ begin
+ bit_num := to_integer(unsigned(sys_via_pb_out(2 downto 0)));
+diff --git a/debugger.vhd b/debugger.vhd
+index a7a9d7d..5431b47 100644
+--- a/debugger.vhd
++++ b/debugger.vhd
+@@ -213,7 +213,7 @@ begin
+ end process;
+
+ -- Set watchpoint address
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,mode)
+ begin
+ if nRESET = '0' then
+ watchpoint <= (others => '1');
+@@ -232,7 +232,7 @@ begin
+ end process;
+
+ -- Set breakpoint address
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,mode)
+ begin
+ if nRESET = '0' then
+ breakpoint <= (others => '1');
+diff --git a/i2c_loader.vhd b/i2c_loader.vhd
+index e0a7115..5152c7b 100644
+--- a/i2c_loader.vhd
++++ b/i2c_loader.vhd
+@@ -132,7 +132,7 @@ begin
+ end process;
+
+ -- The I2C loader process
+- process(nRESET,CLK)
++ process(nRESET,CLK,clken)
+ begin
+ if nRESET = '0' then
+ scl_out <= '1';
+diff --git a/mc6845.vhd b/mc6845.vhd
+index c102501..c28152d 100644
+--- a/mc6845.vhd
++++ b/mc6845.vhd
+@@ -231,7 +231,7 @@ begin
+ end process; -- registers
+
+ -- Horizontal, vertical and address counters
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ variable ma_row_start : unsigned(13 downto 0);
+ variable max_scan_line : unsigned(4 downto 0);
+ begin
+@@ -318,7 +318,7 @@ begin
+
+ -- Signals to mark hsync and half way points for generating
+ -- vsync in even and odd fields
+- process(h_counter)
++ process(h_counter,r02_h_sync_pos)
+ begin
+ h_sync_start <= '0';
+ h_half_way <= '0';
+@@ -332,7 +332,7 @@ begin
+ end process;
+
+ -- Video timing and sync counters
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ begin
+ if nRESET = '0' then
+ -- H
+@@ -399,7 +399,7 @@ begin
+ end process;
+
+ -- Address generation
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ variable slv_line : std_logic_vector(4 downto 0);
+ begin
+ if nRESET = '0' then
+@@ -423,7 +423,7 @@ begin
+ end process;
+
+ -- Cursor control
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ variable cursor_line : std_logic;
+ begin
+ -- Internal cursor enable signal delayed by 1 clock to line up
+@@ -459,7 +459,7 @@ begin
+ end process;
+
+ -- Light pen capture
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ begin
+ if nRESET = '0' then
+ lpstb_i <= '0';
+diff --git a/saa5050.vhd b/saa5050.vhd
+index 573aaa3..d082339 100644
+--- a/saa5050.vhd
++++ b/saa5050.vhd
+@@ -155,7 +155,7 @@ begin
+ flash <= flash_counter(5) and flash_counter(4);
+
+ -- Sync inputs
+- process(DI_CLOCK,nRESET)
++ process(DI_CLOCK,nRESET,DI_CLKEN)
+ begin
+ if nRESET = '0' then
+ di_r <= (others => '0');
+@@ -169,7 +169,7 @@ begin
+ end process;
+
+ -- Register data into pixel clock domain
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ begin
+ if nRESET = '0' then
+ code <= (others => '0');
+@@ -188,7 +188,7 @@ begin
+ gfx & code & std_logic_vector(line_addr);
+
+ -- Character row and pixel counters
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ begin
+ if nRESET = '0' then
+ dew_latch <= '0';
+@@ -260,7 +260,7 @@ begin
+ end process;
+
+ -- Shift register
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ begin
+ if nRESET = '0' then
+ shift_reg <= (others => '0');
+@@ -292,7 +292,7 @@ begin
+ end process;
+
+ -- Control character handling
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ begin
+ if nRESET = '0' then
+ fg <= (others => '1');
+@@ -363,7 +363,7 @@ begin
+ end process;
+
+ -- Output
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN,shift_reg,flash,conceal,is_flash)
+ variable pixel : std_logic;
+ begin
+ pixel := shift_reg(5) and not ((flash and is_flash) or conceal);
+diff --git a/vidproc.vhd b/vidproc.vhd
+index 25f3d75..e53bb46 100644
+--- a/vidproc.vhd
++++ b/vidproc.vhd
+@@ -165,7 +165,7 @@ begin
+ clken_fetch <= CLKEN and not (clken_counter(0) or clken_counter(1) or clken_counter(2) or
+ (clken_counter(3) and not r0_crtc_2mhz));
+
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ begin
+ if nRESET = '0' then
+ clken_counter <= (others => '0');
+@@ -176,7 +176,7 @@ begin
+ end process;
+
+ -- Fetch control
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,clken_pixel)
+ begin
+ if nRESET = '0' then
+ shiftreg <= (others => '0');
+@@ -197,7 +197,7 @@ begin
+ ((r0_cursor0 and not (cursor_counter(0) or cursor_counter(1))) or
+ (r0_cursor1 and cursor_counter(0) and not cursor_counter(1)) or
+ (r0_cursor2 and cursor_counter(1)));
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,clken_fetch)
+ begin
+ if nRESET = '0' then
+ cursor_active <= '0';
+@@ -231,7 +231,7 @@ begin
+ -- the pixel rate we ensure that the resulting delay is minimal and
+ -- constant (running this at the pixel rate would cause
+ -- the display to move slightly depending on which mode was selected).
+- process(CLOCK,nRESET)
++ process(CLOCK,nRESET,CLKEN)
+ variable palette_a : std_logic_vector(3 downto 0);
+ variable dot_val : std_logic_vector(3 downto 0);
+ variable red_val : std_logic;
diff --git a/de1/fpga-bbc-pq/master/other-floating-pins.patch b/de1/fpga-bbc-pq/master/other-floating-pins.patch
new file mode 100644
index 0000000..2eb6ee7
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/other-floating-pins.patch
@@ -0,0 +1,57 @@
+diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd
+index fa7b2e8..991fb40 100644
+--- a/bbc_micro_de1.vhd
++++ b/bbc_micro_de1.vhd
+@@ -781,6 +781,8 @@ begin
+ LEDR(2) -- WATCHPOINT
+ );
+
++ debug_aux <= (others => '0');
++
+ -- 6502 CPU
+ cpu : T65 port map (
+ cpu_mode,
+@@ -929,7 +931,10 @@ begin
+ mhz4_clken,
+ clock
+ );
+-
++
++ user_via_ca2_in <='0';
++ user_via_pa_in <=(others => '0');
++
+ --LEDG(0) <= not PS2_CLK;
+ --LEDG(1) <= not PS2_DAT;
+
+@@ -972,6 +977,12 @@ begin
+ LEDR(5), -- IS_DONE
+ LEDR(4) -- IS_ERROR
+ );
++ AUD_ADCLRCK <= '1';
++
++ UART_TXD <= '0';
++ DRAM_ADDR <= (others => '1');
++ LEDR(9 downto 6) <= (others => '0');
++ sys_via_pb_in(3 downto 0) <= (others => '1');
+
+ -- Asynchronous reset
+ -- PLL is reset by external reset switch
+@@ -1123,6 +1134,8 @@ begin
+ end case;
+ end if;
+ end process;
++
++ FL_DQ <= (others =>'Z');
+
+ -- CPU data bus mux and interrupts
+ cpu_di <=
+@@ -1325,5 +1338,9 @@ begin
+
+ GPIO_0(0) <= not (crtc_hsync xor crtc_vsync);
+ GPIO_0(1) <= crtc_de;
++ GPIO_0(2) <= ld_vsync;
++ GPIO_0(3) <= ld_hsync;
++ GPIO_0(35 downto 4) <= (others => '0');
++ GPIO_1 <= (others => '0');
+
+ end architecture;
diff --git a/de1/fpga-bbc-pq/master/other.patch b/de1/fpga-bbc-pq/master/other.patch
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/other.patch
diff --git a/de1/fpga-bbc-pq/master/saa5050-fixes.patch b/de1/fpga-bbc-pq/master/saa5050-fixes.patch
new file mode 100644
index 0000000..060f2f6
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/saa5050-fixes.patch
@@ -0,0 +1,13 @@
+diff --git a/saa5050.vhd b/saa5050.vhd
+index f198aa8..573aaa3 100644
+--- a/saa5050.vhd
++++ b/saa5050.vhd
+@@ -274,7 +274,7 @@ begin
+ -- character and separated/hold graphics modes apply.
+ -- We don't just assume this to be the case if gfx=1 because
+ -- these modes don't apply to caps even in graphics mode
+- if rom_data(7) = '1' then
++ if rom_data(7) = '1' and rom_data(6)='0' then
+ -- Apply a mask for separated graphics mode
+ if gfx_sep = '1' then
+ shift_reg(5) <= '0';
diff --git a/de1/fpga-bbc-pq/master/saa5050-rom.patch b/de1/fpga-bbc-pq/master/saa5050-rom.patch
new file mode 100644
index 0000000..b676e51
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/saa5050-rom.patch
@@ -0,0 +1,472 @@
+diff --git a/roms/saa5050/genrom.c b/roms/saa5050/genrom.c
+new file mode 100644
+index 0000000..9d93bb3
+--- /dev/null
++++ b/roms/saa5050/genrom.c
+@@ -0,0 +1,180 @@
++#include <stdint.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++
++// Characters on a 5x9 matrix. This is padded up to 16 rows when the
++// ROM is generated
++static uint8_t saa5050_charset[] = {
++ 0,0,0,0,0,0,0,0,0,
++ 4,4,4,4,4,0,4,0,0,
++ 10,10,10,0,0,0,0,0,0,
++ 6,9,8,28,8,8,31,0,0,
++ 14,21,20,14,5,21,14,0,0,
++ 24,25,2,4,8,19,3,0,0,
++ 8,20,20,8,21,18,13,0,0,
++ 4,4,4,0,0,0,0,0,0,
++
++ 2,4,8,8,8,4,2,0,0,
++ 8,4,2,2,2,4,8,0,0,
++ 4,21,14,4,14,21,4,0,0,
++ 0,4,4,31,4,4,0,0,0,
++ 0,0,0,0,0,4,4,8,0,
++ 0,0,0,14,0,0,0,0,0,
++ 0,0,0,0,0,0,4,0,0,
++ 0,1,2,4,8,16,0,0,0,
++
++ 4,10,17,17,17,10,4,0,0,
++ 4,12,4,4,4,4,14,0,0,
++ 14,17,1,6,8,16,31,0,0,
++ 31,1,2,6,1,17,14,0,0,
++ 2,6,10,18,31,2,2,0,0,
++ 31,16,30,1,1,17,14,0,0,
++ 6,8,16,30,17,17,14,0,0,
++ 31,1,2,4,8,8,8,0,0,
++
++ 14,17,17,14,17,17,14,0,0,
++ 14,17,17,15,1,2,12,0,0,
++ 0,0,4,0,0,0,4,0,0,
++ 0,0,4,0,0,4,4,8,0,
++ 2,4,8,16,8,4,2,0,0,
++ 0,0,31,0,31,0,0,0,0,
++ 8,4,2,1,2,4,8,0,0,
++ 14,17,2,4,4,0,4,0,0,
++
++ 14,17,23,21,23,16,14,0,0,
++ 4,10,17,17,31,17,17,0,0,
++ 30,17,17,30,17,17,30,0,0,
++ 14,17,16,16,16,17,14,0,0,
++ 30,17,17,17,17,17,30,0,0,
++ 31,16,16,30,16,16,31,0,0,
++ 31,16,16,30,16,16,16,0,0,
++ 14,17,16,16,19,17,15,0,0,
++
++ 17,17,17,31,17,17,17,0,0,
++ 14,4,4,4,4,4,14,0,0,
++ 1,1,1,1,1,17,14,0,0,
++ 17,18,20,24,20,18,17,0,0,
++ 16,16,16,16,16,16,31,0,0,
++ 17,27,21,21,17,17,17,0,0,
++ 17,17,25,21,19,17,17,0,0,
++ 14,17,17,17,17,17,14,0,0,
++
++ 30,17,17,30,16,16,16,0,0,
++ 14,17,17,17,21,18,13,0,0,
++ 30,17,17,30,20,18,17,0,0,
++ 14,17,16,14,1,17,14,0,0,
++ 31,4,4,4,4,4,4,0,0,
++ 17,17,17,17,17,17,14,0,0,
++ 17,17,17,10,10,4,4,0,0,
++ 17,17,17,21,21,21,10,0,0,
++
++ 17,17,10,4,10,17,17,0,0,
++ 17,17,10,4,4,4,4,0,0,
++ 31,1,2,4,8,16,31,0,0,
++ 0,4,8,31,8,4,0,0,0,
++ 16,16,16,16,22,1,2,4,7,
++ 0,4,2,31,2,4,0,0,0,
++ 0,4,14,21,4,4,0,0,0,
++ 10,10,31,10,31,10,10,0,0,
++
++ 0,0,0,31,0,0,0,0,0,
++ 0,0,14,1,15,17,15,0,0,
++ 16,16,30,17,17,17,30,0,0,
++ 0,0,15,16,16,16,15,0,0,
++ 1,1,15,17,17,17,15,0,0,
++ 0,0,14,17,31,16,14,0,0,
++ 2,4,4,14,4,4,4,0,0,
++ 0,0,15,17,17,17,15,1,14,
++
++ 16,16,30,17,17,17,17,0,0,
++ 4,0,12,4,4,4,14,0,0,
++ 4,0,4,4,4,4,4,4,8,
++ 8,8,9,10,12,10,9,0,0,
++ 12,4,4,4,4,4,14,0,0,
++ 0,0,26,21,21,21,21,0,0,
++ 0,0,30,17,17,17,17,0,0,
++ 0,0,14,17,17,17,14,0,0,
++
++ 0,0,30,17,17,17,30,16,16,
++ 0,0,15,17,17,17,15,1,1,
++ 0,0,11,12,8,8,8,0,0,
++ 0,0,15,16,14,1,30,0,0,
++ 4,4,14,4,4,4,2,0,0,
++ 0,0,17,17,17,17,15,0,0,
++ 0,0,17,17,10,10,4,0,0,
++ 0,0,17,17,21,21,10,0,0,
++
++ 0,0,17,10,4,10,17,0,0,
++ 0,0,17,17,17,17,15,1,14,
++ 0,0,31,2,4,8,31,0,0,
++ 8,8,8,8,9,3,5,7,1,
++ 10,10,10,10,10,10,10,0,0,
++ 24,4,24,4,25,3,5,7,1,
++ 0,4,0,31,0,4,0,0,0,
++ 31,31,31,31,31,31,31,0,0,
++};
++
++/* Generates 6x10 teletext graphics symbol according to specified code */
++void gen_gfx(char code,char *base)
++{
++ char *c;
++ int r;
++
++ for (r = 0, c = base; r < 10; r++, c++) {
++ /* Set unused bit 7 to 1 to flag these characters as graphics (the
++ * implementation uses this to determine whether hold and separated
++ * modes should be applied */
++ *c = 128;
++ if (r < 3) {
++ // 1 2
++ if (code & 1) *c += 56;
++ if (code & 2) *c += 7;
++ } else if (r < 7) {
++ // 4 8
++ if (code & 4) *c += 56;
++ if (code & 8) *c += 7;
++ } else {
++ // 16 64
++ if (code & 16) *c += 56;
++ if (code & 64) *c += 7;
++ }
++ }
++}
++
++int main(void) {
++ char *outbuf;
++ int ch,row;
++
++ outbuf = malloc(256 * 16);
++ if (outbuf == NULL) {
++ fprintf(stderr,"Out of memory\n");
++ return 1;
++ }
++
++ /* Unused locations are blank (all zero) */
++ memset(outbuf,0,256 * 16);
++
++ /* Copy character bitmaps to locations 32-127 and 160-255 */
++ for (ch = 0; ch < 96; ch++) {
++ for (row = 0; row < 9; row++) {
++ outbuf[16 * (32 + ch) + row + 1] = saa5050_charset[9 * ch + row];
++ outbuf[16 * (160 + ch) + row + 1] = saa5050_charset[9 * ch + row];
++ }
++ }
++
++ /* Generate graphics in locations 160-191 and 224-255 */
++ for (ch = 160; ch < 192; ch++) {
++ gen_gfx(ch,&outbuf[16 * ch]);
++ }
++ for (ch = 224; ch < 256; ch++) {
++ gen_gfx(ch,&outbuf[16 * ch]);
++ }
++
++ /* Write to stdout */
++ fwrite(outbuf,256 * 16,1,stdout);
++
++ free(outbuf);
++ return 0;
++}
++
+diff --git a/roms/saa5050/saa5050.hex b/roms/saa5050/saa5050.hex
+new file mode 100644
+index 0000000..f696b00
+--- /dev/null
++++ b/roms/saa5050/saa5050.hex
+@@ -0,0 +1,257 @@
++:1000000000000000000000000000000000000000F0
++:1000100000000000000000000000000000000000E0
++:1000200000000000000000000000000000000000D0
++:1000300000000000000000000000000000000000C0
++:1000400000000000000000000000000000000000B0
++:1000500000000000000000000000000000000000A0
++:100060000000000000000000000000000000000090
++:100070000000000000000000000000000000000080
++:100080000000000000000000000000000000000070
++:100090000000000000000000000000000000000060
++:1000A0000000000000000000000000000000000050
++:1000B0000000000000000000000000000000000040
++:1000C0000000000000000000000000000000000030
++:1000D0000000000000000000000000000000000020
++:1000E0000000000000000000000000000000000010
++:1000F0000000000000000000000000000000000000
++:1001000000000000000000000000000000000000EF
++:1001100000000000000000000000000000000000DF
++:1001200000000000000000000000000000000000CF
++:1001300000000000000000000000000000000000BF
++:1001400000000000000000000000000000000000AF
++:10015000000000000000000000000000000000009F
++:10016000000000000000000000000000000000008F
++:10017000000000000000000000000000000000007F
++:10018000000000000000000000000000000000006F
++:10019000000000000000000000000000000000005F
++:1001A000000000000000000000000000000000004F
++:1001B000000000000000000000000000000000003F
++:1001C000000000000000000000000000000000002F
++:1001D000000000000000000000000000000000001F
++:1001E000000000000000000000000000000000000F
++:1001F00000000000000000000000000000000000FF
++:1002000000000000000000000000000000000000EE
++:1002100000040404040400040000000000000000C6
++:10022000000A0A0A000000000000000000000000B0
++:10023000000609081C08081F00000000000000005C
++:10024000000E15140E05150E000000000000000041
++:100250000018190204081303000000000000000049
++:10026000000814140815120D000000000000000022
++:100270000004040400000000000000000000000072
++:10028000000204080808040200000000000000004A
++:100290000008040202020408000000000000000040
++:1002A0000004150E040E15040000000000000000FC
++:1002B000000004041F04040000000000000000000F
++:1002C000000000000000040408000000000000001E
++:1002D000000000000E000000000000000000000010
++:1002E000000000000000000400000000000000000A
++:1002F00000000102040810000000000000000000DF
++:1003000000040A1111110A0400000000000000009E
++:1003100000040C040404040E0000000000000000AF
++:10032000000E11010608101F000000000000000070
++:10033000001F01020601110E000000000000000075
++:100340000002060A121F0202000000000000000066
++:10035000001F101E0101110E00000000000000002F
++:10036000000608101E11110E000000000000000021
++:10037000001F01020408080800000000000000003F
++:10038000000E11110E11110E0000000000000000FF
++:10039000000E11110F01020C00000000000000000F
++:1003A0000000000400000004000000000000000045
++:1003B0000000000400000404080000000000000029
++:1003C0000002040810080402000000000000000001
++:1003D0000000001F001F00000000000000000000DF
++:1003E00000080402010204080000000000000000F0
++:1003F000000E1102040400040000000000000000D0
++:10040000000E11171517100E00000000000000006C
++:1004100000040A11111F111100000000000000006B
++:10042000001E11111E11111E00000000000000002E
++:10043000000E11101010110E00000000000000004E
++:10044000001E11111111111E00000000000000001B
++:10045000001F10101E10101F000000000000000000
++:10046000001F10101E1010100000000000000000FF
++:10047000000E11101013110F00000000000000000A
++:10048000001111111F1111110000000000000000E7
++:10049000000E04040404040E00000000000000002C
++:1004A000000101010101110E000000000000000028
++:1004B00000111214181412110000000000000000B6
++:1004C000001010101010101F0000000000000000AD
++:1004D00000111B1515111111000000000000000093
++:1004E0000011111915131111000000000000000087
++:1004F000000E11111111110E00000000000000008B
++:10050000001E11111E10101000000000000000005D
++:10051000000E11111115120D000000000000000066
++:10052000001E11111E141211000000000000000036
++:10053000000E11100E01110E00000000000000005E
++:10054000001F040404040404000000000000000074
++:10055000001111111111110E000000000000000027
++:10056000001111110A0A040400000000000000003C
++:10057000001111111515150A0000000000000000FF
++:100580000011110A040A111100000000000000000F
++:100590000011110A0404040400000000000000001F
++:1005A000001F01020408101F0000000000000000EE
++:1005B000000004081F080400000000000000000004
++:1005C00000101010101601020407000000000000C7
++:1005D000000004021F0204000000000000000000F0
++:1005E0000000040E150404000000000000000000DC
++:1005F000000A0A1F0A1F0A0A00000000000000008B
++:10060000000000001F0000000000000000000000CB
++:100610000000000E010F110F00000000000000009C
++:100620000010101E1111111E00000000000000003B
++:100630000000000F1010100F00000000000000006C
++:100640000001010F1111110F000000000000000057
++:100650000000000E111F100E00000000000000003E
++:10066000000204040E040404000000000000000066
++:100670000000000F1111110F010E0000000000001A
++:100680000010101E111111110000000000000000E8
++:100690000004000C0404040E000000000000000030
++:1006A0000004000404040404040800000000000026
++:1006B000000808090A0C0A090000000000000000F8
++:1006C000000C04040404040E0000000000000000FC
++:1006D0000000001A151515150000000000000000AC
++:1006E0000000001E111111110000000000000000A8
++:1006F0000000000E1111110E0000000000000000AB
++:100700000000001E1111111E10100000000000005A
++:100710000000000F1111110F010100000000000086
++:100720000000000B0C08080800000000000000009A
++:100730000000000F100E011E00000000000000006D
++:100740000004040E04040402000000000000000085
++:10075000000000111111110F000000000000000046
++:1007600000000011110A0A0400000000000000004F
++:10077000000000111115150A000000000000000023
++:10078000000000110A040A1100000000000000002F
++:10079000000000111111110F010E000000000000F7
++:1007A0000000001F0204081F0000000000000000FD
++:1007B0000008080808090305070100000000000000
++:1007C000000A0A0A0A0A0A0A0000000000000000E3
++:1007D00000180418041903050701000000000000B8
++:1007E000000004001F0004000000000000000000E2
++:1007F000001F1F1F1F1F1F1F000000000000000020
++:1008000000000000000000000000000000000000E8
++:1008100000000000000000000000000000000000D8
++:1008200000000000000000000000000000000000C8
++:1008300000000000000000000000000000000000B8
++:1008400000000000000000000000000000000000A8
++:100850000000000000000000000000000000000098
++:100860000000000000000000000000000000000088
++:100870000000000000000000000000000000000078
++:100880000000000000000000000000000000000068
++:100890000000000000000000000000000000000058
++:1008A0000000000000000000000000000000000048
++:1008B0000000000000000000000000000000000038
++:1008C0000000000000000000000000000000000028
++:1008D0000000000000000000000000000000000018
++:1008E0000000000000000000000000000000000008
++:1008F00000000000000000000000000000000000F8
++:1009000000000000000000000000000000000000E7
++:1009100000000000000000000000000000000000D7
++:1009200000000000000000000000000000000000C7
++:1009300000000000000000000000000000000000B7
++:1009400000000000000000000000000000000000A7
++:100950000000000000000000000000000000000097
++:100960000000000000000000000000000000000087
++:100970000000000000000000000000000000000077
++:100980000000000000000000000000000000000067
++:100990000000000000000000000000000000000057
++:1009A0000000000000000000000000000000000047
++:1009B0000000000000000000000000000000000037
++:1009C0000000000000000000000000000000000027
++:1009D0000000000000000000000000000000000017
++:1009E0000000000000000000000000000000000007
++:1009F00000000000000000000000000000000000F7
++:100A000080808080808080808080000000000000E6
++:100A1000B8B8B8808080808080800000000000002E
++:100A200087878780808080808080000000000000B1
++:100A3000BFBFBF80808080808080000000000000F9
++:100A4000808080B8B8B8B8808080000000000000C6
++:100A5000B8B8B8B8B8B8B88080800000000000000E
++:100A6000878787B8B8B8B880808000000000000091
++:100A7000BFBFBFB8B8B8B8808080000000000000D9
++:100A8000808080878787878080800000000000004A
++:100A9000B8B8B88787878780808000000000000092
++:100AA0008787878787878780808000000000000015
++:100AB000BFBFBF878787878080800000000000005D
++:100AC000808080BFBFBFBF8080800000000000002A
++:100AD000B8B8B8BFBFBFBF80808000000000000072
++:100AE000878787BFBFBFBF808080000000000000F5
++:100AF000BFBFBFBFBFBFBF8080800000000000003D
++:100B000080808080808080B8B8B80000000000003D
++:100B1000B8B8B880808080B8B8B800000000000085
++:100B200087878780808080B8B8B800000000000008
++:100B3000BFBFBF80808080B8B8B800000000000050
++:100B4000808080B8B8B8B8B8B8B80000000000001D
++:100B5000B8B8B8B8B8B8B8B8B8B800000000000065
++:100B6000878787B8B8B8B8B8B8B8000000000000E8
++:100B7000BFBFBFB8B8B8B8B8B8B800000000000030
++:100B800080808087878787B8B8B8000000000000A1
++:100B9000B8B8B887878787B8B8B8000000000000E9
++:100BA00087878787878787B8B8B80000000000006C
++:100BB000BFBFBF87878787B8B8B8000000000000B4
++:100BC000808080BFBFBFBFB8B8B800000000000081
++:100BD000B8B8B8BFBFBFBFB8B8B8000000000000C9
++:100BE000878787BFBFBFBFB8B8B80000000000004C
++:100BF000BFBFBFBFBFBFBFB8B8B800000000000094
++:100C0000000E11171517100E000000000000000064
++:100C100000040A11111F1111000000000000000063
++:100C2000001E11111E11111E000000000000000026
++:100C3000000E11101010110E000000000000000046
++:100C4000001E11111111111E000000000000000013
++:100C5000001F10101E10101F0000000000000000F8
++:100C6000001F10101E1010100000000000000000F7
++:100C7000000E11101013110F000000000000000002
++:100C8000001111111F1111110000000000000000DF
++:100C9000000E04040404040E000000000000000024
++:100CA000000101010101110E000000000000000020
++:100CB00000111214181412110000000000000000AE
++:100CC000001010101010101F0000000000000000A5
++:100CD00000111B151511111100000000000000008B
++:100CE000001111191513111100000000000000007F
++:100CF000000E11111111110E000000000000000083
++:100D0000001E11111E101010000000000000000055
++:100D1000000E11111115120D00000000000000005E
++:100D2000001E11111E14121100000000000000002E
++:100D3000000E11100E01110E000000000000000056
++:100D4000001F04040404040400000000000000006C
++:100D5000001111111111110E00000000000000001F
++:100D6000001111110A0A0404000000000000000034
++:100D7000001111111515150A0000000000000000F7
++:100D80000011110A040A1111000000000000000007
++:100D90000011110A04040404000000000000000017
++:100DA000001F01020408101F0000000000000000E6
++:100DB000000004081F0804000000000000000000FC
++:100DC00000101010101601020407000000000000BF
++:100DD000000004021F0204000000000000000000E8
++:100DE0000000040E150404000000000000000000D4
++:100DF000000A0A1F0A1F0A0A000000000000000083
++:100E000080808080808080878787000000000000CD
++:100E1000B8B8B88080808087878700000000000015
++:100E20008787878080808087878700000000000098
++:100E3000BFBFBF80808080878787000000000000E0
++:100E4000808080B8B8B8B8878787000000000000AD
++:100E5000B8B8B8B8B8B8B8878787000000000000F5
++:100E6000878787B8B8B8B887878700000000000078
++:100E7000BFBFBFB8B8B8B8878787000000000000C0
++:100E80008080808787878787878700000000000031
++:100E9000B8B8B88787878787878700000000000079
++:100EA00087878787878787878787000000000000FC
++:100EB000BFBFBF8787878787878700000000000044
++:100EC000808080BFBFBFBF87878700000000000011
++:100ED000B8B8B8BFBFBFBF87878700000000000059
++:100EE000878787BFBFBFBF878787000000000000DC
++:100EF000BFBFBFBFBFBFBF87878700000000000024
++:100F000080808080808080BFBFBF00000000000024
++:100F1000B8B8B880808080BFBFBF0000000000006C
++:100F200087878780808080BFBFBF000000000000EF
++:100F3000BFBFBF80808080BFBFBF00000000000037
++:100F4000808080B8B8B8B8BFBFBF00000000000004
++:100F5000B8B8B8B8B8B8B8BFBFBF0000000000004C
++:100F6000878787B8B8B8B8BFBFBF000000000000CF
++:100F7000BFBFBFB8B8B8B8BFBFBF00000000000017
++:100F800080808087878787BFBFBF00000000000088
++:100F9000B8B8B887878787BFBFBF000000000000D0
++:100FA00087878787878787BFBFBF00000000000053
++:100FB000BFBFBF87878787BFBFBF0000000000009B
++:100FC000808080BFBFBFBFBFBFBF00000000000068
++:100FD000B8B8B8BFBFBFBFBFBFBF000000000000B0
++:100FE000878787BFBFBFBFBFBFBF00000000000033
++:100FF000BFBFBFBFBFBFBFBFBFBF0000000000007B
++:00000001FF
+diff --git a/roms/saa5050/saa5050.rom b/roms/saa5050/saa5050.rom
+new file mode 100644
+index 0000000000000000000000000000000000000000..71565e3cf7af216396dab97af8326a10b103347b
+GIT binary patch
+literal 4096
+zcmeHIZI;?F40N(y)}++LfV<H4;j8XHuEamC)|oiyqgPl2@8R)iWJy*+2rqkez;qze
+zLX@3pnq<wzW}E(|)MPK$Q+}^m@cA;vbbJ$>PN!54KLs<oHF&2KN7=%9#Gc?-bIjFf
+zVr>6~2q79l2%3yWkyRKFeO4H!Qp%+9<Bko`5V;JSG;6(W7&k*ve%wrlHfsKDz7Cd$
+z_*#rV^sHDC$RI5buph>q@F)&z&2L$odRdL_UkD8!HE=vpHgXx={pRvnKWD9n{b;3#
+zKa%HHa4z#an|eUPlyCEVoo&AstPQ9BSoRVRVjQREWwzh+f1sK3%HecA9n>G$z_jA>
+zr&b%UluJF@_#kb+SsVgLKInh3^Ge>Hhy1h62g67c{Sw~hi|Lv?Uu)H8io=JN8$G;@
+z|1vM8z7SJOdR$=jzi`7J&j@jBqu~Re9)qW;;iKn6rp;So<Y8~_2iJ#^^nOFw<3zo`
+z0p1wd=jr&(rI~rcwDC#}zxWT&iR<yT{uuZGK3PsX+o1!W(stTSTZy+kuEsxv-{@}@
+zK7?gL4dxAN{LW(p#G~go2>!9N&nxTCgZ87Br_X-~oB-R8WdI}^d3*oB9014j6`&d7
+zI?ekQxuose`^Pgsyq{^JKgV;t7#<C5_Vv-aiT`Wytvm1~*4uEu-`AavZ?~JnkH^Dd
+z07$42y~EHu486k;!i8su-eCfm@X$L90$a>U^bW(>VFH-=V?jesqIbBTt$f!i?pl^4
+zdIDI-(090E=pBZh^@u+f4imtHhu&f6vBj8jzQb^Km;fgJcw4{z|G)A7KZhNLF_HOk
+z7=*)^9ftuhOPpEJI}F0%K6~m9JzQv_?{LK{5FUERLys-)iQZul4imt{pT)qiC3=V9
+u=r9}|24H<w?=bWZ!_i^r;ldo{e1{2O!eiku^w^?_zQYxFt@0}={{H|=Yq~)I
+
+literal 0
+HcmV?d00001
+
diff --git a/de1/fpga-bbc-pq/master/scan-rate-converter.patch b/de1/fpga-bbc-pq/master/scan-rate-converter.patch
new file mode 100644
index 0000000..8ec3840
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/scan-rate-converter.patch
@@ -0,0 +1,457 @@
+commit 5fe74b3778ec4f58f628a6f140af1e9fa9a08eac
+Author: root <root@lab.panaceas.james.local>
+Date: Fri Oct 18 11:08:40 2013 +0100
+
+ with_line_doubler
+
+diff --git a/bbc_micro_de1.vhd b/bbc_micro_de1.vhd
+index e109c36..d78fe69 100644
+--- a/bbc_micro_de1.vhd
++++ b/bbc_micro_de1.vhd
+@@ -279,6 +279,30 @@ port (
+ );
+ end component;
+
++
++component line_doubler is
++port (
++ CLOCK : in std_logic;
++ -- Clock enable qualifies display cycles (interleaved with CPU cycles)
++ CLKEN : in std_logic;
++ nRESET : in std_logic;
++
++ -- Video in (teletext mode)
++ R_IN : in std_logic;
++ G_IN : in std_logic;
++ B_IN : in std_logic;
++ HS_IN : in std_logic;
++ VS_IN : in std_logic;
++
++ -- Video out
++ R_OUT : out std_logic;
++ G_OUT : out std_logic;
++ B_OUT : out std_logic;
++ HS_OUT : out std_logic;
++ VS_OUT : out std_logic
++ );
++end component;
++
+ --------------------------------
+ -- SAA5050 Teletext Generator
+ --------------------------------
+@@ -610,6 +634,13 @@ signal r_out : std_logic;
+ signal g_out : std_logic;
+ signal b_out : std_logic;
+
++-- line doubler signals
++signal ld_r_out : std_logic;
++signal ld_g_out : std_logic;
++signal ld_b_out : std_logic;
++signal ld_hsync : std_logic;
++signal ld_vsync : std_logic;
++
+ -- SAA5050 signals
+ signal ttxt_glr : std_logic;
+ signal ttxt_dew : std_logic;
+@@ -801,6 +832,16 @@ begin
+ r_out, g_out, b_out
+ );
+
++ ld : line_doubler port map (
++ clock,
++ vid_clken,
++ reset_n,
++ r_out, g_out, b_out,
++ crtc_hsync,crtc_vsync,
++ ld_r_out,ld_g_out,ld_b_out,
++ ld_hsync, ld_vsync
++ );
++
+ teletext : saa5050 port map (
+ CLOCK_24(0), -- This runs at 6 MHz, which we can't derive from the 32 MHz clock
+ ttxt_clken,
+@@ -1182,12 +1223,16 @@ begin
+ ttxt_crs <= not crtc_ra(0);
+ ttxt_lose <= crtc_de;
+
++
++ -- line doubler
++
++
+ -- CRTC drives video out (CSYNC on HSYNC output, VSYNC high)
+- VGA_HS <= not (crtc_hsync xor crtc_vsync);
+- VGA_VS <= '1';
+- VGA_R <= r_out & r_out & r_out & r_out;
+- VGA_G <= g_out & g_out & g_out & g_out;
+- VGA_B <= b_out & b_out & b_out & b_out;
++ VGA_HS <= ld_hsync;
++ VGA_VS <= ld_vsync;
++ VGA_R <= (others => ld_r_out);
++ VGA_G <= (others => ld_g_out);
++ VGA_B <= (others => ld_b_out);
+
+ -- Connections to System VIA
+ -- ADC
+diff --git a/line_buffer.qip b/line_buffer.qip
+new file mode 100644
+index 0000000..5a031a0
+--- /dev/null
++++ b/line_buffer.qip
+@@ -0,0 +1,5 @@
++set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT"
++set_global_assignment -name IP_TOOL_VERSION "13.0"
++set_global_assignment -name VHDL_FILE [file join $::quartus(qip_path) "line_buffer.vhd"]
++set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "line_buffer.bsf"]
++set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "line_buffer.cmp"]
+diff --git a/line_buffer.vhd b/line_buffer.vhd
+new file mode 100644
+index 0000000..5ca9fca
+--- /dev/null
++++ b/line_buffer.vhd
+@@ -0,0 +1,242 @@
++-- megafunction wizard: %RAM: 2-PORT%
++-- GENERATION: STANDARD
++-- VERSION: WM1.0
++-- MODULE: altsyncram
++
++-- ============================================================
++-- File Name: line_buffer.vhd
++-- Megafunction Name(s):
++-- altsyncram
++--
++-- Simulation Library Files(s):
++-- altera_mf
++-- ============================================================
++-- ************************************************************
++-- THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
++--
++-- 13.0.1 Build 232 06/12/2013 SP 1 SJ Web Edition
++-- ************************************************************
++
++
++--Copyright (C) 1991-2013 Altera Corporation
++--Your use of Altera Corporation's design tools, logic functions
++--and other software and tools, and its AMPP partner logic
++--functions, and any output files from any of the foregoing
++--(including device programming or simulation files), and any
++--associated documentation or information are expressly subject
++--to the terms and conditions of the Altera Program License
++--Subscription Agreement, Altera MegaCore Function License
++--Agreement, or other applicable license agreement, including,
++--without limitation, that your use is for the sole purpose of
++--programming logic devices manufactured by Altera and sold by
++--Altera or its authorized distributors. Please refer to the
++--applicable agreement for further details.
++
++
++LIBRARY ieee;
++USE ieee.std_logic_1164.all;
++
++LIBRARY altera_mf;
++USE altera_mf.all;
++
++ENTITY line_buffer IS
++ PORT
++ (
++ data : IN STD_LOGIC_VECTOR (3 DOWNTO 0);
++ rdaddress : IN STD_LOGIC_VECTOR (9 DOWNTO 0);
++ rdclock : IN STD_LOGIC ;
++ rdclocken : IN STD_LOGIC := '1';
++ wraddress : IN STD_LOGIC_VECTOR (9 DOWNTO 0);
++ wrclock : IN STD_LOGIC := '1';
++ wrclocken : IN STD_LOGIC := '1';
++ wren : IN STD_LOGIC := '0';
++ q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
++ );
++END line_buffer;
++
++
++ARCHITECTURE SYN OF line_buffer IS
++
++ SIGNAL sub_wire0 : STD_LOGIC_VECTOR (3 DOWNTO 0);
++
++
++
++ COMPONENT altsyncram
++ GENERIC (
++ address_reg_b : STRING;
++ clock_enable_input_a : STRING;
++ clock_enable_input_b : STRING;
++ clock_enable_output_a : STRING;
++ clock_enable_output_b : STRING;
++ intended_device_family : STRING;
++ lpm_type : STRING;
++ numwords_a : NATURAL;
++ numwords_b : NATURAL;
++ operation_mode : STRING;
++ outdata_aclr_b : STRING;
++ outdata_reg_b : STRING;
++ power_up_uninitialized : STRING;
++ widthad_a : NATURAL;
++ widthad_b : NATURAL;
++ width_a : NATURAL;
++ width_b : NATURAL;
++ width_byteena_a : NATURAL
++ );
++ PORT (
++ clock0 : IN STD_LOGIC ;
++ clocken1 : IN STD_LOGIC ;
++ wren_a : IN STD_LOGIC ;
++ address_b : IN STD_LOGIC_VECTOR (9 DOWNTO 0);
++ clock1 : IN STD_LOGIC ;
++ clocken0 : IN STD_LOGIC ;
++ address_a : IN STD_LOGIC_VECTOR (9 DOWNTO 0);
++ data_a : IN STD_LOGIC_VECTOR (3 DOWNTO 0);
++ q_b : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
++ );
++ END COMPONENT;
++
++BEGIN
++ q <= sub_wire0(3 DOWNTO 0);
++
++ altsyncram_component : altsyncram
++ GENERIC MAP (
++ address_reg_b => "CLOCK1",
++ clock_enable_input_a => "NORMAL",
++ clock_enable_input_b => "NORMAL",
++ clock_enable_output_a => "BYPASS",
++ clock_enable_output_b => "NORMAL",
++ intended_device_family => "Cyclone II",
++ lpm_type => "altsyncram",
++ numwords_a => 1024,
++ numwords_b => 1024,
++ operation_mode => "DUAL_PORT",
++ outdata_aclr_b => "NONE",
++ outdata_reg_b => "CLOCK1",
++ power_up_uninitialized => "TRUE",
++ widthad_a => 10,
++ widthad_b => 10,
++ width_a => 4,
++ width_b => 4,
++ width_byteena_a => 1
++ )
++ PORT MAP (
++ clock0 => wrclock,
++ clocken1 => rdclocken,
++ wren_a => wren,
++ address_b => rdaddress,
++ clock1 => rdclock,
++ clocken0 => wrclocken,
++ address_a => wraddress,
++ data_a => data,
++ q_b => sub_wire0
++ );
++
++
++
++END SYN;
++
++-- ============================================================
++-- CNX file retrieval info
++-- ============================================================
++-- Retrieval info: PRIVATE: ADDRESSSTALL_A NUMERIC "0"
++-- Retrieval info: PRIVATE: ADDRESSSTALL_B NUMERIC "0"
++-- Retrieval info: PRIVATE: BYTEENA_ACLR_A NUMERIC "0"
++-- Retrieval info: PRIVATE: BYTEENA_ACLR_B NUMERIC "0"
++-- Retrieval info: PRIVATE: BYTE_ENABLE_A NUMERIC "0"
++-- Retrieval info: PRIVATE: BYTE_ENABLE_B NUMERIC "0"
++-- Retrieval info: PRIVATE: BYTE_SIZE NUMERIC "1"
++-- Retrieval info: PRIVATE: BlankMemory NUMERIC "1"
++-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_A NUMERIC "1"
++-- Retrieval info: PRIVATE: CLOCK_ENABLE_INPUT_B NUMERIC "1"
++-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_A NUMERIC "1"
++-- Retrieval info: PRIVATE: CLOCK_ENABLE_OUTPUT_B NUMERIC "1"
++-- Retrieval info: PRIVATE: CLRdata NUMERIC "0"
++-- Retrieval info: PRIVATE: CLRq NUMERIC "0"
++-- Retrieval info: PRIVATE: CLRrdaddress NUMERIC "0"
++-- Retrieval info: PRIVATE: CLRrren NUMERIC "0"
++-- Retrieval info: PRIVATE: CLRwraddress NUMERIC "0"
++-- Retrieval info: PRIVATE: CLRwren NUMERIC "0"
++-- Retrieval info: PRIVATE: Clock NUMERIC "1"
++-- Retrieval info: PRIVATE: Clock_A NUMERIC "0"
++-- Retrieval info: PRIVATE: Clock_B NUMERIC "0"
++-- Retrieval info: PRIVATE: IMPLEMENT_IN_LES NUMERIC "0"
++-- Retrieval info: PRIVATE: INDATA_ACLR_B NUMERIC "0"
++-- Retrieval info: PRIVATE: INDATA_REG_B NUMERIC "0"
++-- Retrieval info: PRIVATE: INIT_FILE_LAYOUT STRING "PORT_B"
++-- Retrieval info: PRIVATE: INIT_TO_SIM_X NUMERIC "1"
++-- Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
++-- Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
++-- Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
++-- Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
++-- Retrieval info: PRIVATE: MEMSIZE NUMERIC "4096"
++-- Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0"
++-- Retrieval info: PRIVATE: MIFfilename STRING ""
++-- Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "2"
++-- Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "0"
++-- Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "1"
++-- Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
++-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_MIXED_PORTS NUMERIC "2"
++-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_A NUMERIC "3"
++-- Retrieval info: PRIVATE: READ_DURING_WRITE_MODE_PORT_B NUMERIC "3"
++-- Retrieval info: PRIVATE: REGdata NUMERIC "1"
++-- Retrieval info: PRIVATE: REGq NUMERIC "0"
++-- Retrieval info: PRIVATE: REGrdaddress NUMERIC "1"
++-- Retrieval info: PRIVATE: REGrren NUMERIC "1"
++-- Retrieval info: PRIVATE: REGwraddress NUMERIC "1"
++-- Retrieval info: PRIVATE: REGwren NUMERIC "1"
++-- Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
++-- Retrieval info: PRIVATE: USE_DIFF_CLKEN NUMERIC "0"
++-- Retrieval info: PRIVATE: UseDPRAM NUMERIC "1"
++-- Retrieval info: PRIVATE: VarWidth NUMERIC "0"
++-- Retrieval info: PRIVATE: WIDTH_READ_A NUMERIC "4"
++-- Retrieval info: PRIVATE: WIDTH_READ_B NUMERIC "4"
++-- Retrieval info: PRIVATE: WIDTH_WRITE_A NUMERIC "4"
++-- Retrieval info: PRIVATE: WIDTH_WRITE_B NUMERIC "4"
++-- Retrieval info: PRIVATE: WRADDR_ACLR_B NUMERIC "0"
++-- Retrieval info: PRIVATE: WRADDR_REG_B NUMERIC "0"
++-- Retrieval info: PRIVATE: WRCTRL_ACLR_B NUMERIC "0"
++-- Retrieval info: PRIVATE: enable NUMERIC "1"
++-- Retrieval info: PRIVATE: rden NUMERIC "0"
++-- Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
++-- Retrieval info: CONSTANT: ADDRESS_REG_B STRING "CLOCK1"
++-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_A STRING "NORMAL"
++-- Retrieval info: CONSTANT: CLOCK_ENABLE_INPUT_B STRING "NORMAL"
++-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_A STRING "BYPASS"
++-- Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "NORMAL"
++-- Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
++-- Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
++-- Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "1024"
++-- Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "1024"
++-- Retrieval info: CONSTANT: OPERATION_MODE STRING "DUAL_PORT"
++-- Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "NONE"
++-- Retrieval info: CONSTANT: OUTDATA_REG_B STRING "CLOCK1"
++-- Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "TRUE"
++-- Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "10"
++-- Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "10"
++-- Retrieval info: CONSTANT: WIDTH_A NUMERIC "4"
++-- Retrieval info: CONSTANT: WIDTH_B NUMERIC "4"
++-- Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "1"
++-- Retrieval info: USED_PORT: data 0 0 4 0 INPUT NODEFVAL "data[3..0]"
++-- Retrieval info: USED_PORT: q 0 0 4 0 OUTPUT NODEFVAL "q[3..0]"
++-- Retrieval info: USED_PORT: rdaddress 0 0 10 0 INPUT NODEFVAL "rdaddress[9..0]"
++-- Retrieval info: USED_PORT: rdclock 0 0 0 0 INPUT NODEFVAL "rdclock"
++-- Retrieval info: USED_PORT: rdclocken 0 0 0 0 INPUT VCC "rdclocken"
++-- Retrieval info: USED_PORT: wraddress 0 0 10 0 INPUT NODEFVAL "wraddress[9..0]"
++-- Retrieval info: USED_PORT: wrclock 0 0 0 0 INPUT VCC "wrclock"
++-- Retrieval info: USED_PORT: wrclocken 0 0 0 0 INPUT VCC "wrclocken"
++-- Retrieval info: USED_PORT: wren 0 0 0 0 INPUT GND "wren"
++-- Retrieval info: CONNECT: @address_a 0 0 10 0 wraddress 0 0 10 0
++-- Retrieval info: CONNECT: @address_b 0 0 10 0 rdaddress 0 0 10 0
++-- Retrieval info: CONNECT: @clock0 0 0 0 0 wrclock 0 0 0 0
++-- Retrieval info: CONNECT: @clock1 0 0 0 0 rdclock 0 0 0 0
++-- Retrieval info: CONNECT: @clocken0 0 0 0 0 wrclocken 0 0 0 0
++-- Retrieval info: CONNECT: @clocken1 0 0 0 0 rdclocken 0 0 0 0
++-- Retrieval info: CONNECT: @data_a 0 0 4 0 data 0 0 4 0
++-- Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
++-- Retrieval info: CONNECT: q 0 0 4 0 @q_b 0 0 4 0
++-- Retrieval info: GEN_FILE: TYPE_NORMAL line_buffer.vhd TRUE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL line_buffer.inc FALSE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL line_buffer.cmp TRUE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL line_buffer.bsf TRUE
++-- Retrieval info: GEN_FILE: TYPE_NORMAL line_buffer_inst.vhd FALSE
++-- Retrieval info: LIB_FILE: altera_mf
+diff --git a/line_doubler.vhd b/line_doubler.vhd
+new file mode 100644
+index 0000000..4c444c1
+--- /dev/null
++++ b/line_doubler.vhd
+@@ -0,0 +1,98 @@
++library IEEE;
++use IEEE.STD_LOGIC_1164.ALL;
++use IEEE.NUMERIC_STD.ALL;
++
++entity line_doubler is
++port (
++ CLOCK : in std_logic;
++ -- Clock enable qualifies display cycles (interleaved with CPU cycles)
++ CLKEN : in std_logic;
++ nRESET : in std_logic;
++
++ -- Video in (teletext mode)
++ R_IN : in std_logic;
++ G_IN : in std_logic;
++ B_IN : in std_logic;
++ HS_IN : in std_logic;
++ VS_IN : in std_logic;
++
++ -- Video out
++ R_OUT : out std_logic;
++ G_OUT : out std_logic;
++ B_OUT : out std_logic;
++ HS_OUT : out std_logic;
++ VS_OUT : out std_logic
++ );
++end entity;
++
++architecture rtl of line_doubler is
++
++component line_buffer is
++ PORT
++ (
++ data : IN STD_LOGIC_VECTOR (3 DOWNTO 0);
++ rdaddress : IN STD_LOGIC_VECTOR (9 DOWNTO 0);
++ rdclock : IN STD_LOGIC ;
++ rdclocken : IN STD_LOGIC := '1';
++ wraddress : IN STD_LOGIC_VECTOR (9 DOWNTO 0);
++ wrclock : IN STD_LOGIC := '1';
++ wrclocken : IN STD_LOGIC := '1';
++ wren : IN STD_LOGIC := '0';
++ q : OUT STD_LOGIC_VECTOR (3 DOWNTO 0)
++ );
++END component;
++
++signal out_addr : std_logic_vector(9 downto 0);
++signal in_addr : std_logic_vector(9 downto 0);
++
++signal in_data : std_logic_vector(3 downto 0);
++signal out_data : std_logic_vector(3 downto 0);
++signal old_hs: std_logic;
++
++begin
++
++ in_data(3) <= HS_IN;
++ in_data(2) <= R_IN;
++ in_data(1) <= G_IN;
++ in_data(0) <= B_IN;
++
++ line_buffer_inst : line_buffer PORT MAP (
++ wrclock => CLOCK,
++ wrclocken => CLKEN,
++ wren => '1',
++ data => in_data,
++ wraddress => in_addr,
++
++ rdclock => CLOCK,
++ rdclocken => '1',
++ q => out_data,
++ rdaddress => out_addr
++ );
++
++ HS_OUT <= out_data(3);
++ R_OUT <= out_data(2);
++ G_OUT <= out_data(1);
++ B_OUT <= out_data(0);
++ VS_OUT <= VS_IN;
++
++ process(CLOCK,CLKEN,nRESET,HS_IN,in_addr,out_addr)
++ begin
++ if nRESET = '0' then
++ in_addr <= (others => '0');
++ out_addr <= (others => '0');
++ elsif rising_edge(CLOCK) then
++ old_hs <= HS_IN;
++
++ if old_hs ='0' and HS_IN='1' then
++ in_addr <= (others => '0');
++ out_addr <= (others => '0');
++ else
++ out_addr <= std_logic_vector(unsigned(out_addr) +1 );
++ if CLKEN = '1' then
++ in_addr <= std_logic_vector(unsigned(in_addr) +1 );
++ end if;
++ end if;
++ end if;
++ end process;
++end architecture;
++
diff --git a/de1/fpga-bbc-pq/master/series b/de1/fpga-bbc-pq/master/series
new file mode 100644
index 0000000..8219dc3
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/series
@@ -0,0 +1,16 @@
+line-endings.patch
+gitignore.patch
+build-system.patch
+saa5050-rom.patch
+saa5050-fixes.patch
+scan-rate-converter.patch
+cpu-core-fixes.patch
+sn76489-fixes.patch
+audio-16bit-48k.patch
+keyboard.patch
+keyboard-fixes.patch
+dram-floating-pins.patch
+other-floating-pins.patch
+missing-process-sensitivity.patch
+fix-warnings.patch
+endstop
diff --git a/de1/fpga-bbc-pq/master/sn76489-fixes.patch b/de1/fpga-bbc-pq/master/sn76489-fixes.patch
new file mode 100644
index 0000000..6566582
--- /dev/null
+++ b/de1/fpga-bbc-pq/master/sn76489-fixes.patch
@@ -0,0 +1,634 @@
+diff --git a/sn76489-1.0/sn76489_comp_pack-p.vhd b/sn76489-1.0/sn76489_comp_pack-p.vhd
+index 06b12c8..c5fcc90 100644
+--- a/sn76489-1.0/sn76489_comp_pack-p.vhd
++++ b/sn76489-1.0/sn76489_comp_pack-p.vhd
+@@ -27,9 +27,11 @@ package sn76489_comp_pack is
+ clock_i : in std_logic;
+ clk_en_i : in boolean;
+ res_n_i : in std_logic;
+- we_i : in boolean;
++ we_i : in std_logic;
+ d_i : in std_logic_vector(0 to 7);
+- r2_i : in std_logic;
++ addr_i : in std_logic_vector(0 to 1);
++ rst_a_i : in std_logic_vector(0 to 3);
++ rst_cnt_i: in std_logic_vector(0 to 9);
+ ff_o : out std_logic;
+ tone_o : out signed(0 to 7)
+ );
+@@ -40,31 +42,14 @@ package sn76489_comp_pack is
+ clock_i : in std_logic;
+ clk_en_i : in boolean;
+ res_n_i : in std_logic;
+- we_i : in boolean;
++ we_i : in std_logic;
+ d_i : in std_logic_vector(0 to 7);
+- r2_i : in std_logic;
++ addr_i : in std_logic_vector(0 to 1);
+ tone3_ff_i : in std_logic;
+ noise_o : out signed(0 to 7)
+ );
+ end component;
+
+- component sn76489_latch_ctrl
+- port (
+- clock_i : in std_logic;
+- clk_en_i : in boolean;
+- res_n_i : in std_logic;
+- ce_n_i : in std_logic;
+- we_n_i : in std_logic;
+- d_i : in std_logic_vector(0 to 7);
+- ready_o : out std_logic;
+- tone1_we_o : out boolean;
+- tone2_we_o : out boolean;
+- tone3_we_o : out boolean;
+- noise_we_o : out boolean;
+- r2_o : out std_logic
+- );
+- end component;
+-
+ component sn76489_clock_div
+ generic (
+ clock_div_16_g : integer := 1
+diff --git a/sn76489-1.0/sn76489_latch_ctrl-c.vhd b/sn76489-1.0/sn76489_latch_ctrl-c.vhd
+deleted file mode 100644
+index abc09e0..0000000
+--- a/sn76489-1.0/sn76489_latch_ctrl-c.vhd
++++ /dev/null
+@@ -1,14 +0,0 @@
+--------------------------------------------------------------------------------
+---
+--- Synthesizable model of TI's SN76489AN.
+---
+--- $Id: sn76489_latch_ctrl-c.vhd,v 1.2 2005/10/10 22:12:38 arnim Exp $
+---
+--------------------------------------------------------------------------------
+-
+-configuration sn76489_latch_ctrl_rtl_c0 of sn76489_latch_ctrl is
+-
+- for rtl
+- end for;
+-
+-end sn76489_latch_ctrl_rtl_c0;
+diff --git a/sn76489-1.0/sn76489_latch_ctrl.vhd b/sn76489-1.0/sn76489_latch_ctrl.vhd
+deleted file mode 100644
+index 789720c..0000000
+--- a/sn76489-1.0/sn76489_latch_ctrl.vhd
++++ /dev/null
+@@ -1,138 +0,0 @@
+--------------------------------------------------------------------------------
+---
+--- Synthesizable model of TI's SN76489AN.
+---
+--- $Id: sn76489_latch_ctrl.vhd,v 1.6 2006/02/27 20:30:10 arnim Exp $
+---
+--- Latch Control Unit
+---
+--------------------------------------------------------------------------------
+---
+--- Copyright (c) 2005, 2006, Arnim Laeuger (arnim.laeuger@gmx.net)
+---
+--- All rights reserved
+---
+--- Redistribution and use in source and synthezised forms, with or without
+--- modification, are permitted provided that the following conditions are met:
+---
+--- Redistributions of source code must retain the above copyright notice,
+--- this list of conditions and the following disclaimer.
+---
+--- Redistributions in synthesized form must reproduce the above copyright
+--- notice, this list of conditions and the following disclaimer in the
+--- documentation and/or other materials provided with the distribution.
+---
+--- Neither the name of the author nor the names of other contributors may
+--- be used to endorse or promote products derived from this software without
+--- specific prior written permission.
+---
+--- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+--- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+--- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+--- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
+--- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+--- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+--- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+--- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+--- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+--- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+--- POSSIBILITY OF SUCH DAMAGE.
+---
+--- Please report bugs to the author, but before you do so, please
+--- make sure that this is not a derivative work and that
+--- you have the latest version of this file.
+---
+--------------------------------------------------------------------------------
+-
+-library ieee;
+-use ieee.std_logic_1164.all;
+-
+-entity sn76489_latch_ctrl is
+-
+- port (
+- clock_i : in std_logic;
+- clk_en_i : in boolean;
+- res_n_i : in std_logic;
+- ce_n_i : in std_logic;
+- we_n_i : in std_logic;
+- d_i : in std_logic_vector(0 to 7);
+- ready_o : out std_logic;
+- tone1_we_o : out boolean;
+- tone2_we_o : out boolean;
+- tone3_we_o : out boolean;
+- noise_we_o : out boolean;
+- r2_o : out std_logic
+- );
+-
+-end sn76489_latch_ctrl;
+-
+-
+-library ieee;
+-use ieee.numeric_std.all;
+-
+-architecture rtl of sn76489_latch_ctrl is
+-
+- signal reg_q : std_logic_vector(0 to 2);
+- signal we_q : boolean;
+- signal ready_q : std_logic;
+-
+-begin
+-
+- -----------------------------------------------------------------------------
+- -- Process seq
+- --
+- -- Purpose:
+- -- Implements the sequential elements.
+- --
+- seq: process (clock_i, res_n_i)
+- begin
+- if res_n_i = '0' then
+- reg_q <= (others => '0');
+- we_q <= false;
+- ready_q <= '0';
+-
+- elsif clock_i'event and clock_i = '1' then
+- -- READY Flag Output ----------------------------------------------------
+- if ready_q = '0' and we_q then
+- if clk_en_i then
+- -- assert READY when write access happened
+- ready_q <= '1';
+- end if;
+- elsif ce_n_i = '1' then
+- -- deassert READY when access has finished
+- ready_q <= '0';
+- end if;
+-
+- -- Register Selection ---------------------------------------------------
+- if ce_n_i = '0' and we_n_i = '0' then
+- if clk_en_i then
+- if d_i(0) = '1' then
+- reg_q <= d_i(1 to 3);
+- end if;
+- we_q <= true;
+- end if;
+- else
+- we_q <= false;
+- end if;
+-
+- end if;
+- end process seq;
+- --
+- -----------------------------------------------------------------------------
+-
+-
+- -----------------------------------------------------------------------------
+- -- Output mapping
+- -----------------------------------------------------------------------------
+- tone1_we_o <= reg_q(0 to 1) = "00" and we_q;
+- tone2_we_o <= reg_q(0 to 1) = "01" and we_q;
+- tone3_we_o <= reg_q(0 to 1) = "10" and we_q;
+- noise_we_o <= reg_q(0 to 1) = "11" and we_q;
+-
+- r2_o <= reg_q(2);
+-
+- ready_o <= ready_q
+- when ce_n_i = '0' else
+- '1';
+-
+-end rtl;
+diff --git a/sn76489-1.0/sn76489_noise.vhd b/sn76489-1.0/sn76489_noise.vhd
+index 8b2ee0e..035adab 100644
+--- a/sn76489-1.0/sn76489_noise.vhd
++++ b/sn76489-1.0/sn76489_noise.vhd
+@@ -54,9 +54,9 @@ entity sn76489_noise is
+ clock_i : in std_logic;
+ clk_en_i : in boolean;
+ res_n_i : in std_logic;
+- we_i : in boolean;
++ we_i : in std_logic;
+ d_i : in std_logic_vector(0 to 7);
+- r2_i : in std_logic;
++ addr_i : in std_logic_vector(0 to 1);
+ tone3_ff_i : in std_logic;
+ noise_o : out signed(0 to 7)
+ );
+@@ -68,6 +68,9 @@ use work.sn76489_comp_pack.sn76489_attenuator;
+
+ architecture rtl of sn76489_noise is
+
++ signal selected : std_logic;
++ signal write_cr : std_logic;
++
+ signal nf_q : std_logic_vector(0 to 1);
+ signal fb_q : std_logic;
+ signal a_q : std_logic_vector(0 to 3);
+@@ -78,12 +81,13 @@ architecture rtl of sn76489_noise is
+ shift_source_q : std_logic;
+ signal shift_rise_edge_s : boolean;
+
+- signal lfsr_q : std_logic_vector(0 to 15);
++ signal lfsr_q : std_logic_vector(0 to 7);
+
+ signal freq_s : signed(0 to 1);
+
+ begin
+
++
+ -----------------------------------------------------------------------------
+ -- Process cpu_regs
+ --
+@@ -96,22 +100,25 @@ begin
+ nf_q <= (others => '0');
+ fb_q <= '0';
+ a_q <= (others => '1');
+-
+- elsif clock_i'event and clock_i = '1' then
+- if clk_en_i and we_i then
+- if r2_i = '0' then
+- -- access to control register
+- -- both access types can write to the control register!
+- nf_q <= d_i(6 to 7);
+- fb_q <= d_i(5);
+-
+- else
+- -- access to attenuator register
+- -- both access types can write to the attenuator register!
+- a_q <= d_i(4 to 7);
+-
++ elsif rising_edge(clock_i) and we_i = '1' then
++ if d_i(0) = '1' then
++ if d_i(1 to 2) = addr_i then
++ if d_i(3) = '0' then
++ selected<='1';
++ nf_q <= d_i(6 to 7);
++ fb_q <= d_i(5);
++ else
++ selected <='0';
++ a_q <= d_i(4 to 7);
++ end if;
++ else
++ selected <='0';
++ end if;
++ elsif selected = '1' then
++ selected<='0';
++ nf_q <= d_i(6 to 7);
++ fb_q <= d_i(5);
+ end if;
+- end if;
+ end if;
+ end process cpu_regs;
+ --
+@@ -130,8 +137,7 @@ begin
+ freq_cnt_q <= (others => '0');
+ freq_ff_q <= '0';
+
+- elsif clock_i'event and clock_i = '1' then
+- if clk_en_i then
++ elsif rising_edge(clock_i) and clk_en_i then
+ if freq_cnt_q = 0 then
+ -- reload frequency counter according to NF setting
+ case nf_q is
+@@ -152,8 +158,6 @@ begin
+ freq_cnt_q <= freq_cnt_q - 1;
+
+ end if;
+-
+- end if;
+ end if;
+ end process freq_gen;
+ --
+@@ -191,6 +195,8 @@ begin
+ shift_rise_edge_s <= shift_source_q = '0' and shift_source_s = '1';
+
+
++ write_cr <= '1' when ((we_i='1') and (((d_i(0) = '1') and (d_i(1 to 2) = addr_i) and (d_i(3) = '0')) or (selected='1'))) else '0';
++
+ -----------------------------------------------------------------------------
+ -- Process lfsr
+ --
+@@ -219,15 +225,15 @@ begin
+ return parity_v;
+ end;
+
++
+ begin
+ if res_n_i = '0' then
+ -- reset LFSR to "0000000000000001"
+ lfsr_q <= (others => '0');
+ lfsr_q(lfsr_q'right) <= '1';
+
+- elsif clock_i'event and clock_i = '1' then
+- if clk_en_i then
+- if we_i and r2_i = '0' then
++ elsif rising_edge(clock_i) and clk_en_i then
++ if write_cr='1' then
+ -- write to noise register
+ -- -> reset LFSR
+ lfsr_q <= (others => '0');
+@@ -253,7 +259,6 @@ begin
+
+ end if;
+
+- end if;
+ end if;
+ end process lfsr;
+ --
+diff --git a/sn76489-1.0/sn76489_tone.vhd b/sn76489-1.0/sn76489_tone.vhd
+index b71af8b..f1b6885 100644
+--- a/sn76489-1.0/sn76489_tone.vhd
++++ b/sn76489-1.0/sn76489_tone.vhd
+@@ -54,9 +54,11 @@ entity sn76489_tone is
+ clock_i : in std_logic;
+ clk_en_i : in boolean;
+ res_n_i : in std_logic;
+- we_i : in boolean;
++ we_i : in std_logic;
+ d_i : in std_logic_vector(0 to 7);
+- r2_i : in std_logic;
++ addr_i : in std_logic_vector(0 to 1);
++ rst_a_i : in std_logic_vector(0 to 3);
++ rst_cnt_i: in std_logic_vector(0 to 9);
+ ff_o : out std_logic;
+ tone_o : out signed(0 to 7)
+ );
+@@ -68,6 +70,7 @@ use work.sn76489_comp_pack.sn76489_attenuator;
+
+ architecture rtl of sn76489_tone is
+
++ signal selected : std_logic;
+ signal f_q : std_logic_vector(0 to 9);
+ signal a_q : std_logic_vector(0 to 3);
+ signal freq_cnt_q : unsigned(0 to 9);
+@@ -75,6 +78,7 @@ architecture rtl of sn76489_tone is
+
+ signal freq_s : signed(0 to 1);
+
++
+ function all_zero(a : in std_logic_vector) return boolean is
+ variable result_v : boolean;
+ begin
+@@ -91,6 +95,8 @@ architecture rtl of sn76489_tone is
+
+ begin
+
++
++
+ -----------------------------------------------------------------------------
+ -- Process cpu_regs
+ --
+@@ -99,27 +105,28 @@ begin
+ --
+ cpu_regs: process (clock_i, res_n_i)
+ begin
+- if res_n_i = '0' then
+- f_q <= (others => '0');
+- a_q <= (others => '1');
+-
+- elsif clock_i'event and clock_i = '1' then
+- if clk_en_i and we_i then
+- if r2_i = '0' then
+- -- access to frequency register
+- if d_i(0) = '0' then
+- f_q(0 to 5) <= d_i(2 to 7);
+- else
+- f_q(6 to 9) <= d_i(4 to 7);
+- end if;
+-
+- else
+- -- access to attenuator register
+- -- both access types can write to the attenuator register!
+- a_q <= d_i(4 to 7);
+
++ if res_n_i = '0' then
++ f_q <= (others => '1');
++ a_q <= rst_a_i;
++ selected <='0';
++ elsif rising_edge(clock_i) and we_i = '1' then
++ if d_i(0) = '1' then
++ if d_i(1 to 2) = addr_i then
++ if d_i(3) = '0' then
++ selected<='1';
++ f_q(6 to 9) <= d_i(4 to 7);
++ else
++ selected <='0';
++ a_q <= d_i(4 to 7);
++ end if;
++ else
++ selected <='0';
++ end if;
++ elsif selected = '1' then
++ selected<='0';
++ f_q(0 to 5) <= d_i(2 to 7);
+ end if;
+- end if;
+ end if;
+ end process cpu_regs;
+ --
+@@ -135,17 +142,19 @@ begin
+ freq_gen: process (clock_i, res_n_i)
+ begin
+ if res_n_i = '0' then
+- freq_cnt_q <= (others => '0');
++ freq_cnt_q <= unsigned(rst_cnt_i);
+ freq_ff_q <= '0';
+
+- elsif clock_i'event and clock_i = '1' then
+- if clk_en_i then
+- if freq_cnt_q = 0 then
++ elsif rising_edge(clock_i) and clk_en_i then
++ if we_i='1' and selected = '1' then
++ freq_cnt_q <= (others => '0');
++ freq_ff_q <= '1';
++ elsif freq_cnt_q = 0 then
+ -- update counter from frequency register
+- freq_cnt_q <= unsigned(f_q);
++ freq_cnt_q <= unsigned(f_q)-to_unsigned(1,10);
+
+ -- and toggle the frequency flip-flop if enabled
+- if not all_zero(f_q) then
++ if unsigned(f_q) > to_unsigned(1,10) then
+ freq_ff_q <= not freq_ff_q;
+ else
+ -- if frequency setting is 0, then keep flip-flop at +1
+@@ -157,7 +166,6 @@ begin
+ freq_cnt_q <= freq_cnt_q - 1;
+
+ end if;
+- end if;
+ end if;
+ end process freq_gen;
+ --
+diff --git a/sn76489-1.0/sn76489_top-c.vhd b/sn76489-1.0/sn76489_top-c.vhd
+index 8f709b9..55f3dfb 100644
+--- a/sn76489-1.0/sn76489_top-c.vhd
++++ b/sn76489-1.0/sn76489_top-c.vhd
+@@ -14,10 +14,6 @@ configuration sn76489_top_struct_c0 of sn76489_top is
+ use configuration work.sn76489_clock_div_rtl_c0;
+ end for;
+
+- for latch_ctrl_b : sn76489_latch_ctrl
+- use configuration work.sn76489_latch_ctrl_rtl_c0;
+- end for;
+-
+ for all : sn76489_tone
+ use configuration work.sn76489_tone_rtl_c0;
+ end for;
+diff --git a/sn76489-1.0/sn76489_top.vhd b/sn76489-1.0/sn76489_top.vhd
+index deb8170..2f6a01c 100644
+--- a/sn76489-1.0/sn76489_top.vhd
++++ b/sn76489-1.0/sn76489_top.vhd
+@@ -86,19 +86,17 @@ architecture struct of sn76489_top is
+
+ signal clk_en_s : boolean;
+
+- signal tone1_we_s,
+- tone2_we_s,
+- tone3_we_s,
+- noise_we_s : boolean;
+- signal r2_s : std_logic;
+-
+ signal tone1_s,
+ tone2_s,
+ tone3_s,
+- noise_s : signed(0 to 7);
++ noise_s : signed(0 to 15);
+
+ signal tone3_ff_s : std_logic;
+
++ signal dl : std_logic_vector(0 to 9);
++
++ signal we : std_logic;
++
+ begin
+
+ -----------------------------------------------------------------------------
+@@ -116,26 +114,6 @@ begin
+ );
+
+
+- -----------------------------------------------------------------------------
+- -- Latch Control = CPU Interface
+- -----------------------------------------------------------------------------
+- latch_ctrl_b : sn76489_latch_ctrl
+- port map (
+- clock_i => clock_i,
+- clk_en_i => clk_en_s,
+- res_n_i => res_n_i,
+- ce_n_i => ce_n_i,
+- we_n_i => we_n_i,
+- d_i => d_i,
+- ready_o => ready_o,
+- tone1_we_o => tone1_we_s,
+- tone2_we_o => tone2_we_s,
+- tone3_we_o => tone3_we_s,
+- noise_we_o => noise_we_s,
+- r2_o => r2_s
+- );
+-
+-
+ -----------------------------------------------------------------------------
+ -- Tone Channel 1
+ -----------------------------------------------------------------------------
+@@ -144,9 +122,11 @@ begin
+ clock_i => clock_i,
+ clk_en_i => clk_en_s,
+ res_n_i => res_n_i,
+- we_i => tone1_we_s,
++ we_i => we,
+ d_i => d_i,
+- r2_i => r2_s,
++ addr_i => "00",
++ rst_a_i => "0000",
++ rst_cnt_i=> "0000000000",
+ ff_o => open,
+ tone_o => tone1_s
+ );
+@@ -159,9 +139,11 @@ begin
+ clock_i => clock_i,
+ clk_en_i => clk_en_s,
+ res_n_i => res_n_i,
+- we_i => tone2_we_s,
++ we_i => we,
+ d_i => d_i,
+- r2_i => r2_s,
++ addr_i => "01",
++ rst_a_i => "1000",
++ rst_cnt_i=> "0000110100",
+ ff_o => open,
+ tone_o => tone2_s
+ );
+@@ -174,9 +156,11 @@ begin
+ clock_i => clock_i,
+ clk_en_i => clk_en_s,
+ res_n_i => res_n_i,
+- we_i => tone3_we_s,
++ we_i => we,
+ d_i => d_i,
+- r2_i => r2_s,
++ addr_i => "10",
++ rst_a_i => "1000",
++ rst_cnt_i=> "1100110100",
+ ff_o => tone3_ff_s,
+ tone_o => tone3_s
+ );
+@@ -189,14 +173,16 @@ begin
+ clock_i => clock_i,
+ clk_en_i => clk_en_s,
+ res_n_i => res_n_i,
+- we_i => noise_we_s,
++ we_i => we,
+ d_i => d_i,
+- r2_i => r2_s,
++ addr_i => "11",
+ tone3_ff_i => tone3_ff_s,
+ noise_o => noise_s
+ );
+
+
++ we<= not(ce_n_i or we_n_i) when clk_en_s else '0';
++
+ -- Register output
+ process(clock_i)
+ begin
+@@ -207,4 +193,23 @@ begin
+ end if;
+ end process;
+
++ process(clock_i)
++ begin
++ if res_n_i = '0' then
++ dl<=(others => '0');
++ elsif rising_edge(clock_i) then
++ if ce_n_i = '0' and we_n_i = '0' then
++ if d_i(0)='1' then
++ if d_i(3)='0' then
++ dl(6 to 9) <= d_i(4 to 7);
++ end if;
++ else
++ dl(0 to 5) <= d_i(2 to 7);
++ end if;
++ end if;
++ end if;
++ end process;
++
++
++ ready_o <= '1';
+ end struct;
diff --git a/de1/fpga-flash-nor/Makefile b/de1/fpga-flash-nor/Makefile
new file mode 100644
index 0000000..e542f8f
--- /dev/null
+++ b/de1/fpga-flash-nor/Makefile
@@ -0,0 +1,63 @@
+PROJ=de1flash
+
+SRCS=$(wildcard *.vhd *.v *.qsf *.qpf )
+SOF=${PROJ}.sof
+
+ROMSRC=../../roms
+
+default: do_flash
+
+
+do_flash: rom_image.stamp
+
+rom_image.stamp:rom_image.rom load_sof.stamp
+ ./quartus_wrap quartus_stp -t de1flash.tcl write rom_image.rom@0x20000
+ touch $@
+
+
+os.rom:${ROMSRC}/os12.rom
+ cp $< $@
+rom0.rom:${ROMSRC}/empty.rom
+ cp $< $@
+rom1.rom:${ROMSRC}/empty.rom
+ cp $< $@
+rom2.rom:${ROMSRC}/supermmc.rom
+ cp $< $@
+rom3.rom:${ROMSRC}/basic2.rom
+ cp $< $@
+
+rom_image.rom:os.rom rom0.rom rom1.rom rom2.rom rom3.rom
+ cat rom0.rom rom1.rom rom2.rom rom3.rom ${ROMSRC}/empty.rom ${ROMSRC}/empty.rom ${ROMSRC}/empty.rom os.rom > $@ || /bin/rm -f $@
+
+sta.stamp:asm.stamp
+ ./quartus_wrap quartus_sta ${PROJ} -c ${PROJ}
+ touch $@
+
+asm.stamp:fit.stamp
+ ./quartus_wrap quartus_asm --read_settings_files=off --write_settings_files=off ${PROJ} -c ${PROJ}
+ touch $@
+
+${SOF}:asm.stamp
+
+fit.stamp: ans.stamp
+ ./quartus_wrap quartus_fit --read_settings_files=off --write_settings_files=off ${PROJ} -c ${PROJ}
+ touch $@
+
+ans.stamp: source.stamp
+ ./quartus_wrap quartus_map --read_settings_files=on --write_settings_files=off ${PROJ} -c ${PROJ}
+ touch $@
+
+source.stamp:${SRCS}
+ touch source.stamp
+
+load_sof.stamp: ${SOF}
+ ./quartus_wrap quartus_pgm -m JTAG -o "p;${SOF}" -c 1
+ #touch $@
+
+clean:
+ /bin/rm -rf db incremental_db
+ /bin/rm -f *.stamp ${SOF} *.rpt *.html *.summary *.pin *.jdi *.qws *.pof *.done *.rom
+
+
+
+
diff --git a/de1/fpga-flash-nor/crc32_d8.v b/de1/fpga-flash-nor/crc32_d8.v
new file mode 100644
index 0000000..4721eb5
--- /dev/null
+++ b/de1/fpga-flash-nor/crc32_d8.v
@@ -0,0 +1,96 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2011 H. Peter Anvin - All Rights Reserved
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall
+// be included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// -----------------------------------------------------------------------
+
+////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 1999-2008 Easics NV.
+// This source file may be used and distributed without restriction
+// provided that this copyright statement is not removed from the file
+// and that any derivative work contains the original copyright notice
+// and the associated disclaimer.
+//
+// THIS SOURCE FILE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS
+// OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+// WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Purpose : synthesizable CRC function
+// * polynomial: (0 1 2 4 5 7 8 10 11 12 16 22 23 26 32)
+// * data width: 8
+//
+// Info : tools@easics.be
+// http://www.easics.com
+////////////////////////////////////////////////////////////////////////////////
+
+module crc_32_d8 (
+ input [ 7:0] data,
+ input [31:0] in,
+ output [31:0] out
+ );
+
+ // Note the bit ordering and the polarity of the inputs and outputs...
+ wire [0: 7] d = data;
+ wire [0:31] c = ~in;
+ reg [0:31] newcrc;
+
+ assign out = ~newcrc;
+
+ always @(d, c)
+ begin
+ newcrc[0] = d[6] ^ d[0] ^ c[24] ^ c[30];
+ newcrc[1] = d[7] ^ d[6] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[30] ^ c[31];
+ newcrc[2] = d[7] ^ d[6] ^ d[2] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[26] ^ c[30] ^ c[31];
+ newcrc[3] = d[7] ^ d[3] ^ d[2] ^ d[1] ^ c[25] ^ c[26] ^ c[27] ^ c[31];
+ newcrc[4] = d[6] ^ d[4] ^ d[3] ^ d[2] ^ d[0] ^ c[24] ^ c[26] ^ c[27] ^ c[28] ^ c[30];
+ newcrc[5] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[24] ^ c[25] ^ c[27] ^ c[28] ^ c[29] ^ c[30] ^ c[31];
+ newcrc[6] = d[7] ^ d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1] ^ c[25] ^ c[26] ^ c[28] ^ c[29] ^ c[30] ^ c[31];
+ newcrc[7] = d[7] ^ d[5] ^ d[3] ^ d[2] ^ d[0] ^ c[24] ^ c[26] ^ c[27] ^ c[29] ^ c[31];
+ newcrc[8] = d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[0] ^ c[24] ^ c[25] ^ c[27] ^ c[28];
+ newcrc[9] = d[5] ^ d[4] ^ d[2] ^ d[1] ^ c[1] ^ c[25] ^ c[26] ^ c[28] ^ c[29];
+ newcrc[10] = d[5] ^ d[3] ^ d[2] ^ d[0] ^ c[2] ^ c[24] ^ c[26] ^ c[27] ^ c[29];
+ newcrc[11] = d[4] ^ d[3] ^ d[1] ^ d[0] ^ c[3] ^ c[24] ^ c[25] ^ c[27] ^ c[28];
+ newcrc[12] = d[6] ^ d[5] ^ d[4] ^ d[2] ^ d[1] ^ d[0] ^ c[4] ^ c[24] ^ c[25] ^ c[26] ^ c[28] ^ c[29] ^ c[30];
+ newcrc[13] = d[7] ^ d[6] ^ d[5] ^ d[3] ^ d[2] ^ d[1] ^ c[5] ^ c[25] ^ c[26] ^ c[27] ^ c[29] ^ c[30] ^ c[31];
+ newcrc[14] = d[7] ^ d[6] ^ d[4] ^ d[3] ^ d[2] ^ c[6] ^ c[26] ^ c[27] ^ c[28] ^ c[30] ^ c[31];
+ newcrc[15] = d[7] ^ d[5] ^ d[4] ^ d[3] ^ c[7] ^ c[27] ^ c[28] ^ c[29] ^ c[31];
+ newcrc[16] = d[5] ^ d[4] ^ d[0] ^ c[8] ^ c[24] ^ c[28] ^ c[29];
+ newcrc[17] = d[6] ^ d[5] ^ d[1] ^ c[9] ^ c[25] ^ c[29] ^ c[30];
+ newcrc[18] = d[7] ^ d[6] ^ d[2] ^ c[10] ^ c[26] ^ c[30] ^ c[31];
+ newcrc[19] = d[7] ^ d[3] ^ c[11] ^ c[27] ^ c[31];
+ newcrc[20] = d[4] ^ c[12] ^ c[28];
+ newcrc[21] = d[5] ^ c[13] ^ c[29];
+ newcrc[22] = d[0] ^ c[14] ^ c[24];
+ newcrc[23] = d[6] ^ d[1] ^ d[0] ^ c[15] ^ c[24] ^ c[25] ^ c[30];
+ newcrc[24] = d[7] ^ d[2] ^ d[1] ^ c[16] ^ c[25] ^ c[26] ^ c[31];
+ newcrc[25] = d[3] ^ d[2] ^ c[17] ^ c[26] ^ c[27];
+ newcrc[26] = d[6] ^ d[4] ^ d[3] ^ d[0] ^ c[18] ^ c[24] ^ c[27] ^ c[28] ^ c[30];
+ newcrc[27] = d[7] ^ d[5] ^ d[4] ^ d[1] ^ c[19] ^ c[25] ^ c[28] ^ c[29] ^ c[31];
+ newcrc[28] = d[6] ^ d[5] ^ d[2] ^ c[20] ^ c[26] ^ c[29] ^ c[30];
+ newcrc[29] = d[7] ^ d[6] ^ d[3] ^ c[21] ^ c[27] ^ c[30] ^ c[31];
+ newcrc[30] = d[7] ^ d[4] ^ c[22] ^ c[28] ^ c[31];
+ newcrc[31] = d[5] ^ c[23] ^ c[29];
+ end // always @ (d, c)
+
+endmodule // crc_32_d8
diff --git a/de1/fpga-flash-nor/de1flash.fit.smsg b/de1/fpga-flash-nor/de1flash.fit.smsg
new file mode 100644
index 0000000..7121cbb
--- /dev/null
+++ b/de1/fpga-flash-nor/de1flash.fit.smsg
@@ -0,0 +1,8 @@
+Extra Info (176273): Performing register packing on registers with non-logic cell location assignments
+Extra Info (176274): Completed register packing on registers with non-logic cell location assignments
+Extra Info (176236): Started Fast Input/Output/OE register processing
+Extra Info (176237): Finished Fast Input/Output/OE register processing
+Extra Info (176238): Start inferring scan chains for DSP blocks
+Extra Info (176239): Inferring scan chains for DSP blocks is complete
+Extra Info (176248): Moving registers into I/O cells, Multiplier Blocks, and RAM blocks to improve timing and density
+Extra Info (176249): Finished moving registers into I/O cells, Multiplier Blocks, and RAM blocks
diff --git a/de1/fpga-flash-nor/de1flash.map.smsg b/de1/fpga-flash-nor/de1flash.map.smsg
new file mode 100644
index 0000000..93f31b5
--- /dev/null
+++ b/de1/fpga-flash-nor/de1flash.map.smsg
@@ -0,0 +1,2 @@
+Warning (10273): Verilog HDL warning at de1flash.v(463): extended using "x" or "z"
+Warning (10273): Verilog HDL warning at de1flash.v(466): extended using "x" or "z"
diff --git a/de1/fpga-flash-nor/de1flash.qpf b/de1/fpga-flash-nor/de1flash.qpf
new file mode 100644
index 0000000..6c4d9ae
--- /dev/null
+++ b/de1/fpga-flash-nor/de1flash.qpf
@@ -0,0 +1,30 @@
+# -------------------------------------------------------------------------- #
+#
+# Copyright (C) 1991-2011 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
+# Version 11.0 Build 157 04/27/2011 SJ Web Edition
+# Date created = 15:03:51 May 30, 2011
+#
+# -------------------------------------------------------------------------- #
+
+QUARTUS_VERSION = "11.0"
+DATE = "15:03:51 May 30, 2011"
+
+# Revisions
+
+PROJECT_REVISION = "de1flash"
diff --git a/de1/fpga-flash-nor/de1flash.qsf b/de1/fpga-flash-nor/de1flash.qsf
new file mode 100644
index 0000000..eb43225
--- /dev/null
+++ b/de1/fpga-flash-nor/de1flash.qsf
@@ -0,0 +1,348 @@
+# -------------------------------------------------------------------------- #
+#
+# Copyright (C) 1991-2011 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
+# Version 11.0 Build 157 04/27/2011 SJ Web Edition
+# Date created = 15:03:51 May 30, 2011
+#
+# -------------------------------------------------------------------------- #
+#
+# Notes:
+#
+# 1) The default values for assignments are stored in the file:
+# de1flash_assignment_defaults.qdf
+# If this file doesn't exist, see file:
+# assignment_defaults.qdf
+#
+# 2) Altera recommends that you do not modify this file. This
+# file is updated automatically by the Quartus II software
+# and any changes you make may be lost or overwritten.
+#
+# -------------------------------------------------------------------------- #
+
+
+set_global_assignment -name FAMILY "Cyclone II"
+set_global_assignment -name DEVICE EP2C20F484C7
+set_global_assignment -name TOP_LEVEL_ENTITY de1flash
+set_global_assignment -name ORIGINAL_QUARTUS_VERSION 11.0
+set_global_assignment -name PROJECT_CREATION_TIME_DATE "15:03:51 MAY 30, 2011"
+set_global_assignment -name LAST_QUARTUS_VERSION "13.0 SP1"
+set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
+set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
+set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
+set_location_assignment PIN_A13 -to gpio_0[0]
+set_location_assignment PIN_B13 -to gpio_0[1]
+set_location_assignment PIN_A14 -to gpio_0[2]
+set_location_assignment PIN_B14 -to gpio_0[3]
+set_location_assignment PIN_A15 -to gpio_0[4]
+set_location_assignment PIN_B15 -to gpio_0[5]
+set_location_assignment PIN_A16 -to gpio_0[6]
+set_location_assignment PIN_B16 -to gpio_0[7]
+set_location_assignment PIN_A17 -to gpio_0[8]
+set_location_assignment PIN_B17 -to gpio_0[9]
+set_location_assignment PIN_A18 -to gpio_0[10]
+set_location_assignment PIN_B18 -to gpio_0[11]
+set_location_assignment PIN_A19 -to gpio_0[12]
+set_location_assignment PIN_B19 -to gpio_0[13]
+set_location_assignment PIN_A20 -to gpio_0[14]
+set_location_assignment PIN_B20 -to gpio_0[15]
+set_location_assignment PIN_C21 -to gpio_0[16]
+set_location_assignment PIN_C22 -to gpio_0[17]
+set_location_assignment PIN_D21 -to gpio_0[18]
+set_location_assignment PIN_D22 -to gpio_0[19]
+set_location_assignment PIN_E21 -to gpio_0[20]
+set_location_assignment PIN_E22 -to gpio_0[21]
+set_location_assignment PIN_F21 -to gpio_0[22]
+set_location_assignment PIN_F22 -to gpio_0[23]
+set_location_assignment PIN_G21 -to gpio_0[24]
+set_location_assignment PIN_G22 -to gpio_0[25]
+set_location_assignment PIN_J21 -to gpio_0[26]
+set_location_assignment PIN_J22 -to gpio_0[27]
+set_location_assignment PIN_K21 -to gpio_0[28]
+set_location_assignment PIN_K22 -to gpio_0[29]
+set_location_assignment PIN_J19 -to gpio_0[30]
+set_location_assignment PIN_J20 -to gpio_0[31]
+set_location_assignment PIN_J18 -to gpio_0[32]
+set_location_assignment PIN_K20 -to gpio_0[33]
+set_location_assignment PIN_L19 -to gpio_0[34]
+set_location_assignment PIN_L18 -to gpio_0[35]
+set_location_assignment PIN_H12 -to gpio_1[0]
+set_location_assignment PIN_H13 -to gpio_1[1]
+set_location_assignment PIN_H14 -to gpio_1[2]
+set_location_assignment PIN_G15 -to gpio_1[3]
+set_location_assignment PIN_E14 -to gpio_1[4]
+set_location_assignment PIN_E15 -to gpio_1[5]
+set_location_assignment PIN_F15 -to gpio_1[6]
+set_location_assignment PIN_G16 -to gpio_1[7]
+set_location_assignment PIN_F12 -to gpio_1[8]
+set_location_assignment PIN_F13 -to gpio_1[9]
+set_location_assignment PIN_C14 -to gpio_1[10]
+set_location_assignment PIN_D14 -to gpio_1[11]
+set_location_assignment PIN_D15 -to gpio_1[12]
+set_location_assignment PIN_D16 -to gpio_1[13]
+set_location_assignment PIN_C17 -to gpio_1[14]
+set_location_assignment PIN_C18 -to gpio_1[15]
+set_location_assignment PIN_C19 -to gpio_1[16]
+set_location_assignment PIN_C20 -to gpio_1[17]
+set_location_assignment PIN_D19 -to gpio_1[18]
+set_location_assignment PIN_D20 -to gpio_1[19]
+set_location_assignment PIN_E20 -to gpio_1[20]
+set_location_assignment PIN_F20 -to gpio_1[21]
+set_location_assignment PIN_E19 -to gpio_1[22]
+set_location_assignment PIN_E18 -to gpio_1[23]
+set_location_assignment PIN_G20 -to gpio_1[24]
+set_location_assignment PIN_G18 -to gpio_1[25]
+set_location_assignment PIN_G17 -to gpio_1[26]
+set_location_assignment PIN_H17 -to gpio_1[27]
+set_location_assignment PIN_J15 -to gpio_1[28]
+set_location_assignment PIN_H18 -to gpio_1[29]
+set_location_assignment PIN_N22 -to gpio_1[30]
+set_location_assignment PIN_N21 -to gpio_1[31]
+set_location_assignment PIN_P15 -to gpio_1[32]
+set_location_assignment PIN_N15 -to gpio_1[33]
+set_location_assignment PIN_P17 -to gpio_1[34]
+set_location_assignment PIN_P18 -to gpio_1[35]
+set_location_assignment PIN_L22 -to sw[0]
+set_location_assignment PIN_L21 -to sw[1]
+set_location_assignment PIN_M22 -to sw[2]
+set_location_assignment PIN_V12 -to sw[3]
+set_location_assignment PIN_W12 -to sw[4]
+set_location_assignment PIN_U12 -to sw[5]
+set_location_assignment PIN_U11 -to sw[6]
+set_location_assignment PIN_M2 -to sw[7]
+set_location_assignment PIN_M1 -to sw[8]
+set_location_assignment PIN_L2 -to sw[9]
+set_location_assignment PIN_J2 -to s7_0[0]
+set_location_assignment PIN_J1 -to s7_0[1]
+set_location_assignment PIN_H2 -to s7_0[2]
+set_location_assignment PIN_H1 -to s7_0[3]
+set_location_assignment PIN_F2 -to s7_0[4]
+set_location_assignment PIN_F1 -to s7_0[5]
+set_location_assignment PIN_E2 -to s7_0[6]
+set_location_assignment PIN_E1 -to s7_1[0]
+set_location_assignment PIN_H6 -to s7_1[1]
+set_location_assignment PIN_H5 -to s7_1[2]
+set_location_assignment PIN_H4 -to s7_1[3]
+set_location_assignment PIN_G3 -to s7_1[4]
+set_location_assignment PIN_D2 -to s7_1[5]
+set_location_assignment PIN_D1 -to s7_1[6]
+set_location_assignment PIN_G5 -to s7_2[0]
+set_location_assignment PIN_G6 -to s7_2[1]
+set_location_assignment PIN_C2 -to s7_2[2]
+set_location_assignment PIN_C1 -to s7_2[3]
+set_location_assignment PIN_E3 -to s7_2[4]
+set_location_assignment PIN_E4 -to s7_2[5]
+set_location_assignment PIN_D3 -to s7_2[6]
+set_location_assignment PIN_F4 -to s7_3[0]
+set_location_assignment PIN_D5 -to s7_3[1]
+set_location_assignment PIN_D6 -to s7_3[2]
+set_location_assignment PIN_J4 -to s7_3[3]
+set_location_assignment PIN_L8 -to s7_3[4]
+set_location_assignment PIN_F3 -to s7_3[5]
+set_location_assignment PIN_D4 -to s7_3[6]
+set_location_assignment PIN_R22 -to key_n[0]
+set_location_assignment PIN_R21 -to key_n[1]
+set_location_assignment PIN_T22 -to key_n[2]
+set_location_assignment PIN_T21 -to key_n[3]
+set_location_assignment PIN_R20 -to ledr[0]
+set_location_assignment PIN_R19 -to ledr[1]
+set_location_assignment PIN_U19 -to ledr[2]
+set_location_assignment PIN_Y19 -to ledr[3]
+set_location_assignment PIN_T18 -to ledr[4]
+set_location_assignment PIN_V19 -to ledr[5]
+set_location_assignment PIN_Y18 -to ledr[6]
+set_location_assignment PIN_U18 -to ledr[7]
+set_location_assignment PIN_R18 -to ledr[8]
+set_location_assignment PIN_R17 -to ledr[9]
+set_location_assignment PIN_U22 -to ledg[0]
+set_location_assignment PIN_U21 -to ledg[1]
+set_location_assignment PIN_V22 -to ledg[2]
+set_location_assignment PIN_V21 -to ledg[3]
+set_location_assignment PIN_W22 -to ledg[4]
+set_location_assignment PIN_W21 -to ledg[5]
+set_location_assignment PIN_Y22 -to ledg[6]
+set_location_assignment PIN_Y21 -to ledg[7]
+set_location_assignment PIN_D12 -to clock_27[0]
+set_location_assignment PIN_E12 -to clock_27[1]
+set_location_assignment PIN_B12 -to clock_24[0]
+set_location_assignment PIN_A12 -to clock_24[1]
+set_location_assignment PIN_L1 -to clock_50
+set_location_assignment PIN_M21 -to ext_clock
+set_location_assignment PIN_H15 -to ps2_clk
+set_location_assignment PIN_J14 -to ps2_dat
+set_location_assignment PIN_F14 -to uart_rxd
+set_location_assignment PIN_G12 -to uart_txd
+set_location_assignment PIN_E8 -to tdi
+set_location_assignment PIN_D8 -to tcs
+set_location_assignment PIN_C7 -to tck
+set_location_assignment PIN_D7 -to tdo
+set_location_assignment PIN_D9 -to vga_r[0]
+set_location_assignment PIN_C9 -to vga_r[1]
+set_location_assignment PIN_A7 -to vga_r[2]
+set_location_assignment PIN_B7 -to vga_r[3]
+set_location_assignment PIN_B8 -to vga_g[0]
+set_location_assignment PIN_C10 -to vga_g[1]
+set_location_assignment PIN_B9 -to vga_g[2]
+set_location_assignment PIN_A8 -to vga_g[3]
+set_location_assignment PIN_A9 -to vga_b[0]
+set_location_assignment PIN_D11 -to vga_b[1]
+set_location_assignment PIN_A10 -to vga_b[2]
+set_location_assignment PIN_B10 -to vga_b[3]
+set_location_assignment PIN_A11 -to vga_hs
+set_location_assignment PIN_B11 -to vga_vs
+set_location_assignment PIN_A3 -to i2c_scl
+set_location_assignment PIN_B3 -to i2c_sda
+set_location_assignment PIN_A6 -to aud_adclrck
+set_location_assignment PIN_B6 -to aud_adcdat
+set_location_assignment PIN_A5 -to aud_daclrck
+set_location_assignment PIN_B5 -to aud_dacdat
+set_location_assignment PIN_B4 -to aud_xck
+set_location_assignment PIN_A4 -to aud_bclk
+set_location_assignment PIN_W4 -to dram_a[0]
+set_location_assignment PIN_W5 -to dram_a[1]
+set_location_assignment PIN_Y3 -to dram_a[2]
+set_location_assignment PIN_Y4 -to dram_a[3]
+set_location_assignment PIN_R6 -to dram_a[4]
+set_location_assignment PIN_R5 -to dram_a[5]
+set_location_assignment PIN_P6 -to dram_a[6]
+set_location_assignment PIN_P5 -to dram_a[7]
+set_location_assignment PIN_P3 -to dram_a[8]
+set_location_assignment PIN_N4 -to dram_a[9]
+set_location_assignment PIN_W3 -to dram_a[10]
+set_location_assignment PIN_N6 -to dram_a[11]
+set_location_assignment PIN_U3 -to dram_ba[0]
+set_location_assignment PIN_V4 -to dram_ba[1]
+set_location_assignment PIN_T3 -to dram_cas_n
+set_location_assignment PIN_N3 -to dram_cke
+set_location_assignment PIN_U4 -to dram_clk
+set_location_assignment PIN_T6 -to dram_cs_n
+set_location_assignment PIN_U1 -to dram_dq[0]
+set_location_assignment PIN_U2 -to dram_dq[1]
+set_location_assignment PIN_V1 -to dram_dq[2]
+set_location_assignment PIN_V2 -to dram_dq[3]
+set_location_assignment PIN_W1 -to dram_dq[4]
+set_location_assignment PIN_W2 -to dram_dq[5]
+set_location_assignment PIN_Y1 -to dram_dq[6]
+set_location_assignment PIN_Y2 -to dram_dq[7]
+set_location_assignment PIN_N1 -to dram_dq[8]
+set_location_assignment PIN_N2 -to dram_dq[9]
+set_location_assignment PIN_P1 -to dram_dq[10]
+set_location_assignment PIN_P2 -to dram_dq[11]
+set_location_assignment PIN_R1 -to dram_dq[12]
+set_location_assignment PIN_R2 -to dram_dq[13]
+set_location_assignment PIN_T1 -to dram_dq[14]
+set_location_assignment PIN_T2 -to dram_dq[15]
+set_location_assignment PIN_R7 -to dram_dqm[0]
+set_location_assignment PIN_T5 -to dram_ras_n
+set_location_assignment PIN_M5 -to dram_dqm[1]
+set_location_assignment PIN_R8 -to dram_we_n
+set_location_assignment PIN_AB20 -to fl_a[0]
+set_location_assignment PIN_AA14 -to fl_a[1]
+set_location_assignment PIN_Y16 -to fl_a[2]
+set_location_assignment PIN_R15 -to fl_a[3]
+set_location_assignment PIN_T15 -to fl_a[4]
+set_location_assignment PIN_U15 -to fl_a[5]
+set_location_assignment PIN_V15 -to fl_a[6]
+set_location_assignment PIN_W15 -to fl_a[7]
+set_location_assignment PIN_R14 -to fl_a[8]
+set_location_assignment PIN_Y13 -to fl_a[9]
+set_location_assignment PIN_R12 -to fl_a[10]
+set_location_assignment PIN_T12 -to fl_a[11]
+set_location_assignment PIN_AB14 -to fl_a[12]
+set_location_assignment PIN_AA13 -to fl_a[13]
+set_location_assignment PIN_AB13 -to fl_a[14]
+set_location_assignment PIN_AA12 -to fl_a[15]
+set_location_assignment PIN_AB12 -to fl_a[16]
+set_location_assignment PIN_AA20 -to fl_a[17]
+set_location_assignment PIN_U14 -to fl_a[18]
+set_location_assignment PIN_V14 -to fl_a[19]
+set_location_assignment PIN_U13 -to fl_a[20]
+set_location_assignment PIN_R13 -to fl_a[21]
+set_location_assignment PIN_AB16 -to fl_dq[0]
+set_location_assignment PIN_AA16 -to fl_dq[1]
+set_location_assignment PIN_AB17 -to fl_dq[2]
+set_location_assignment PIN_AA17 -to fl_dq[3]
+set_location_assignment PIN_AB18 -to fl_dq[4]
+set_location_assignment PIN_AA18 -to fl_dq[5]
+set_location_assignment PIN_AB19 -to fl_dq[6]
+set_location_assignment PIN_AA19 -to fl_dq[7]
+set_location_assignment PIN_AA15 -to fl_oe_n
+set_location_assignment PIN_W14 -to fl_rst_n
+set_location_assignment PIN_Y14 -to fl_we_n
+set_location_assignment PIN_AB15 -to fl_ce_n
+set_location_assignment PIN_AA3 -to sram_a[0]
+set_location_assignment PIN_AB3 -to sram_a[1]
+set_location_assignment PIN_AA4 -to sram_a[2]
+set_location_assignment PIN_AB4 -to sram_a[3]
+set_location_assignment PIN_AA5 -to sram_a[4]
+set_location_assignment PIN_AB10 -to sram_a[5]
+set_location_assignment PIN_AA11 -to sram_a[6]
+set_location_assignment PIN_AB11 -to sram_a[7]
+set_location_assignment PIN_V11 -to sram_a[8]
+set_location_assignment PIN_W11 -to sram_a[9]
+set_location_assignment PIN_R11 -to sram_a[10]
+set_location_assignment PIN_T11 -to sram_a[11]
+set_location_assignment PIN_Y10 -to sram_a[12]
+set_location_assignment PIN_U10 -to sram_a[13]
+set_location_assignment PIN_R10 -to sram_a[14]
+set_location_assignment PIN_T7 -to sram_a[15]
+set_location_assignment PIN_Y6 -to sram_a[16]
+set_location_assignment PIN_Y5 -to sram_a[17]
+set_location_assignment PIN_AB5 -to sram_ce_n
+set_location_assignment PIN_AA6 -to sram_dq[0]
+set_location_assignment PIN_AB6 -to sram_dq[1]
+set_location_assignment PIN_AA7 -to sram_dq[2]
+set_location_assignment PIN_AB7 -to sram_dq[3]
+set_location_assignment PIN_AA8 -to sram_dq[4]
+set_location_assignment PIN_AB8 -to sram_dq[5]
+set_location_assignment PIN_AA9 -to sram_dq[6]
+set_location_assignment PIN_AB9 -to sram_dq[7]
+set_location_assignment PIN_Y9 -to sram_dq[8]
+set_location_assignment PIN_W9 -to sram_dq[9]
+set_location_assignment PIN_V9 -to sram_dq[10]
+set_location_assignment PIN_U9 -to sram_dq[11]
+set_location_assignment PIN_R9 -to sram_dq[12]
+set_location_assignment PIN_W8 -to sram_dq[13]
+set_location_assignment PIN_V8 -to sram_dq[14]
+set_location_assignment PIN_U8 -to sram_dq[15]
+set_location_assignment PIN_Y7 -to sram_be_n[0]
+set_location_assignment PIN_T8 -to sram_oe_n
+set_location_assignment PIN_W7 -to sram_be_n[1]
+set_location_assignment PIN_AA10 -to sram_we_n
+set_location_assignment PIN_V20 -to sd_clk
+set_location_assignment PIN_Y20 -to sd_cmd
+set_location_assignment PIN_W20 -to sd_dat0
+set_location_assignment PIN_U20 -to sd_dat3
+
+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 USE_CONFIGURATION_DEVICE ON
+set_global_assignment -name RESERVE_ALL_UNUSED_PINS "AS INPUT TRI-STATED WITH WEAK PULL-UP"
+set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
+set_global_assignment -name RESERVE_ASDO_AFTER_CONFIGURATION "USE AS REGULAR IO"
+set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "NO HEAT SINK WITH STILL AIR"
+set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
+set_global_assignment -name VERILOG_FILE crc32_d8.v
+set_global_assignment -name VERILOG_FILE hexled.v
+set_global_assignment -name VERILOG_FILE de1flash.v
+set_global_assignment -name QIP_FILE vjtag_mega.qip
+set_global_assignment -name SDC_FILE de1flash.sdc
+set_global_assignment -name QIP_FILE pll.qip
+set_global_assignment -name QIP_FILE fl_fifo.qip
+set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file
diff --git a/de1/fpga-flash-nor/de1flash.tcl b/de1/fpga-flash-nor/de1flash.tcl
new file mode 100644
index 0000000..5556e3b
--- /dev/null
+++ b/de1/fpga-flash-nor/de1flash.tcl
@@ -0,0 +1,423 @@
+## -----------------------------------------------------------------------
+##
+## Copyright 2011 H. Peter Anvin - All Rights Reserved
+##
+## Permission is hereby granted, free of charge, to any person
+## obtaining a copy of this software and associated documentation
+## files (the "Software"), to deal in the Software without
+## restriction, including without limitation the rights to use,
+## copy, modify, merge, publish, distribute, sublicense, and/or
+## sell copies of the Software, and to permit persons to whom
+## the Software is furnished to do so, subject to the following
+## conditions:
+##
+## The above copyright notice and this permission notice shall
+## be included in all copies or substantial portions of the Software.
+##
+## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+## OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+## HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+## WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+## FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+## OTHER DEALINGS IN THE SOFTWARE.
+##
+## -----------------------------------------------------------------------
+
+# Virtual JTAG instance index
+set fl_instance 0
+# Current IR value
+set fl_current_ir -1
+# Known space in the write FIFO
+set fl_free_space 0
+
+# Device parameters which really should come from reading the CFI data
+set fl_device_size 0x400000
+proc fl_sector_size addr {
+ expr ($addr < 65536) ? 8192 : 65536
+}
+
+proc select_ir new_ir {
+ global fl_instance fl_current_ir
+ if { $new_ir != $fl_current_ir } {
+ device_virtual_ir_shift -instance_index $fl_instance \
+ -ir_value $new_ir -no_captured_ir_value
+ set fl_current_ir $new_ir
+ }
+}
+
+# Send a command (given as a 72-bit hex string)
+proc fl_send cmd {
+ global fl_instance fl_free_space
+
+ while { $fl_free_space < 1 } {
+ # Poll the free space register until nonzero
+ select_ir 2
+ scan [device_virtual_dr_shift -instance_index $fl_instance \
+ -length 8 -value_in_hex] "%x" fl_free_space
+ }
+
+ select_ir 3
+ device_virtual_dr_shift -instance_index $fl_instance \
+ -dr_value $cmd -length 72 -value_in_hex -no_captured_dr_value
+ incr fl_free_space -1
+}
+
+# Receive a reply (returned as a 72-bit hex string)
+proc fl_recv {} {
+ global fl_instance
+
+ set status 0
+
+ select_ir 1
+ while { ($status & 0x80) == 0 } {
+ set v [device_virtual_dr_shift -instance_index $fl_instance \
+ -length 72 -value_in_hex]
+ scan $v "%2x" status
+ }
+ return $v
+}
+
+# Receive bulk data (returned as a binary string)
+proc fl_recv_bulk bytes {
+ global fl_instance
+
+ select_ir 1
+
+ set qwords [expr ($bytes + 7) >> 3]
+ set outdata ""
+
+ while { $qwords } {
+ set d [device_virtual_dr_shift -instance_index $fl_instance \
+ -length [expr $qwords * 72] -value_in_hex]
+
+ # The LSW is the first transaction, so we need to process
+ # the returned string backwards
+ for { set n [expr $qwords - 1] } { $n >= 0 } { incr n -1 } {
+ set ix [expr $n * 18]
+ set di [string range $d $ix [expr $ix + 17]]
+ scan $di "%2x%2x%2x%2x%2x%2x%2x%2x%2x" st d7 d6 d5 d4 d3 d2 d1 d0
+ if { $st & 0x80 } {
+ set bd [binary format cccccccc $d0 $d1 $d2 $d3 $d4 $d5 $d6 $d7]
+ set nbytes 8
+ if { $bytes < 8 } {
+ set bd [string range $bd 0 [expr $bytes - 1]]
+ set nbytes $bytes
+ }
+ append outdata $bd
+ incr qwords -1
+ set bytes [expr $bytes - $nbytes]
+ } else {
+ # puts "Dropping non-data: $di"
+ }
+ }
+ }
+ return $outdata
+}
+
+# Reset state machine
+proc fl_reset {} {
+ global fl_instance
+
+ puts -nonewline "Issuing reset... "
+
+ select_ir 5
+ device_virtual_dr_shift -instance_index $fl_instance \
+ -dr_value 1 -length 1 -no_captured_dr_value
+
+ select_ir 4
+ set rdy 0
+ while { !$rdy } {
+ set rdy [device_virtual_dr_shift -instance_index $fl_instance -length 1]
+ }
+
+ puts "done."
+}
+
+# Sector erase
+proc fl_erase addr {
+ set secsize [fl_sector_size $addr]
+ set secaddr [expr $addr & ~($secsize - 1)]
+
+ puts -nonewline [format "Erasing sector at 0x%x(0x%x)... " $secaddr $secsize]
+
+ # Blank check the sector before erasing
+ fl_send [format "50%08X%08X" $secaddr $secsize]
+ set zc [fl_recv]
+ set ze [format "\[89ABCDEF\]5%08XFFFFFFFF" [expr $secaddr + $secsize]]
+
+ if { ![string match $ze $zc] } {
+ # puts "\nNot blank, expected $ze got $zc"
+
+ fl_send 81AAAAAAAA000000AA
+ fl_send 815555555500000055
+ fl_send 81AAAAAAAA00000080
+ fl_send 81AAAAAAAA000000AA
+ fl_send 815555555500000055
+ fl_send [format "81%08X00000030" $secaddr]
+
+ set read_cmd [format "D0%08X%08X" $secaddr 8]
+
+ set done 0
+ while { !$done } {
+ fl_send $read_cmd
+ set v [fl_recv]
+ set done [string match {[89ABCDEF]DFFFFFFFFFFFFFFFF} $v]
+ }
+ puts "done."
+ } else {
+ puts "already blank."
+ }
+}
+
+# Read file
+proc fl_read_file { file addr size } {
+ set f [open $file {WRONLY CREAT TRUNC BINARY}]
+
+ puts -nonewline [format "Reading file %s@0x%x,0x%x... " $file $addr $size]
+
+ # This is an arbitrary tunable, but at least for Quartus 11 is doesn't
+ # seem to get any better with a larger block size...
+ set max_block 4096
+
+ # Read data
+ set left $size
+ fl_send [format "D0%08X%08X" $addr $size]
+ while { $left > 0 } {
+ set blk [expr ($left < $max_block) ? $left : $max_block]
+ puts -nonewline $f [fl_recv_bulk $blk]
+ set left [expr $left - $blk]
+ }
+
+ close $f
+ puts "done."
+}
+
+# Write file (without erase)
+proc fl_write_file { file addr size } {
+ set f [open $file {RDONLY BINARY}]
+
+ puts -nonewline [format "Writing file %s@0x%x,0x%x... " $file $addr $size]
+
+ # Write data
+ set left $size
+ fl_send [format "D0%08X%08X" $addr 0]
+ while { $left > 0 } {
+ set blk [expr ($left < 8) ? $left : 8]
+ set d [read $f $blk]
+ append d [string repeat "\xff" [expr 8 - $blk]]
+ binary scan $d H2H2H2H2H2H2H2H2 d0 d1 d2 d3 d4 d5 d6 d7
+ fl_send [format "B%X%s%s%s%s%s%s%s%s" $blk $d7 $d6 $d5 $d4 $d3 $d2 $d1 $d0]
+ set left [expr $left - $blk]
+ }
+
+ # Synchronize
+ puts -nonewline "syncing... "
+ fl_send 6000000000AEAEAEAE
+ set v [fl_recv]
+ if { [string match $v [format "\[89ABCDEF\]6%08XAEAEAEAE" [expr $addr + $size]]] } {
+ puts "error!"
+ } else {
+ puts "done."
+ }
+
+ close $f
+}
+
+# Checksum (CRC32) a region
+proc fl_crc32_file { file addr size } {
+ fl_send [format "70%08X%08X" $addr $size]
+ set v [fl_recv]
+ scan $v "%1x%1x%8x%8x" ctr type end crc
+ if { $type != 7 || $end != $addr + $size } {
+ puts "$file: checksumming failure"
+ } else {
+ puts [format "%08x %s@0x%x,0x%x" $crc $file $addr $size]
+ }
+}
+
+# Parse a list of filespecs
+proc fl_parse_files { mode files } {
+ global fl_device_size
+
+ set last_address 0
+ set file_list {}
+
+ foreach file $files {
+ regexp {^(.*?)(\@([0-9a-fA-FxX]+|)(,([0-9a-fA-FxX]+)|)|)$} $file \
+ junk0 filename junk1 address junk2 len
+ if { [string equal $address ""] } {
+ set address $last_address
+ }
+ if { [string equal $len ""] } {
+ switch $mode {
+ read
+ {
+ set len [expr $fl_device_size - $address]
+ }
+ write
+ {
+ if { [string equal $filename ""] } {
+ set len [expr $fl_device_size - $address]
+ } else {
+ set len [file size $filename]
+ }
+ }
+ }
+ }
+ lappend file_list [list $filename $address $len]
+ }
+
+ return $file_list
+}
+
+# Produce a list of erase blocks from a filespec list
+proc fl_get_eraseblocks flist {
+ set erase_list {}
+
+ foreach fspec $flist {
+ set addr [lindex $fspec 1]
+ set len [lindex $fspec 2]
+
+ set end [expr $addr + $len]
+
+ while { $addr < $end } {
+ set secsize [fl_sector_size $addr]
+ set secaddr [expr $addr & ~($secsize - 1)]
+
+ lappend erase_list $secaddr
+ set addr [expr $secaddr + $secsize]
+ }
+ }
+
+ return [lsort -integer -unique $erase_list]
+}
+
+# Erase per filespec
+proc fl_erase_files flist {
+ foreach eb [fl_get_eraseblocks $flist] {
+ fl_erase $eb
+ }
+}
+
+# Read per filespec
+proc fl_read_files flist {
+ foreach fspec $flist {
+ set file [lindex $fspec 0]
+ set addr [lindex $fspec 1]
+ set len [lindex $fspec 2]
+
+ if { ![string equal $file ""] } {
+ fl_read_file $file $addr $len
+ }
+ }
+}
+
+# Write per filespec
+proc fl_write_files flist {
+ foreach fspec $flist {
+ set file [lindex $fspec 0]
+ set addr [lindex $fspec 1]
+ set len [lindex $fspec 2]
+
+ if { ![string equal $file ""] } {
+ fl_write_file $file $addr $len
+ }
+ }
+}
+
+# Checksum per filespec
+proc fl_crc32_files flist {
+ foreach fspec $flist {
+ set file [lindex $fspec 0]
+ set addr [lindex $fspec 1]
+ set len [lindex $fspec 2]
+
+ fl_crc32_file $file $addr $len
+ }
+}
+
+# ---------------------------------------------------------------------------
+# Start of main program
+# ---------------------------------------------------------------------------
+
+if {$argc < 1} {
+ error "Usage: quartus_stp -t de1flash.tcl command [filespec...]"
+}
+
+set fl_cmd [lindex $argv 0]
+set fl_fspec [lrange $argv 1 end]
+
+# List all available programming hardwares, and select the USBBlaster.
+# (Note: this example assumes only one USBBlaster connected.)
+#puts "Programming Hardwares:"
+#foreach hardware_name [get_hardware_names] {
+# puts $hardware_name
+# if { [string match "USB-Blaster*" $hardware_name] } {
+# set usbblaster_name $hardware_name
+# }
+#}
+
+set hardwares [get_hardware_names]
+set usbblaster_name [lindex $hardwares 0]
+
+puts "\nUsing programming cable \{$usbblaster_name\}.\n";
+
+# List all devices on the chain, and select the first device on the
+# chain.
+puts "\nDevices on the JTAG chain:"
+foreach device_name [get_device_names -hardware_name $usbblaster_name] {
+ puts $device_name
+ if { [string match "@1*" $device_name] } {
+ set test_device $device_name
+ }
+}
+puts "\nSelecting device: \{$test_device\}.\n";
+
+# Open device
+open_device -hardware_name $usbblaster_name -device_name $test_device
+
+device_lock -timeout 120000
+
+fl_reset
+
+switch $fl_cmd {
+ write
+ {
+ set fspec [fl_parse_files write $fl_fspec]
+ fl_erase_files $fspec
+ fl_write_files $fspec
+ }
+ writeonly
+ {
+ set fspec [fl_parse_files write $fl_fspec]
+ fl_write_files $fspec
+ }
+ erase
+ {
+ set fspec [fl_parse_files write $fl_fspec]
+ fl_erase_files $fspec
+ }
+ read
+ {
+ set fspec [fl_parse_files read $fl_fspec]
+ fl_read_files $fspec
+ }
+ crc32
+ {
+ set fspec [fl_parse_files write $fl_fspec]
+ fl_crc32_files $fspec
+ }
+ eraseall
+ {
+ fl_erase_files [list [list "" 0 $fl_device_size]]
+ }
+ default
+ {
+ error "Unknown de1flash command"
+ }
+}
+
+device_unlock
+close_device
diff --git a/de1/fpga-flash-nor/de1flash.v b/de1/fpga-flash-nor/de1flash.v
new file mode 100644
index 0000000..57cd5ec
--- /dev/null
+++ b/de1/fpga-flash-nor/de1flash.v
@@ -0,0 +1,893 @@
+// -----------------------------------------------------------------------
+//
+// Copyright 2003-2011 H. Peter Anvin - All Rights Reserved
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom
+// the Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall
+// be included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+// -----------------------------------------------------------------------
+
+//
+// de1flash.v
+//
+// Top-level module template for the Terasic DE1/Altera Cyclone II
+// Starter Board virtual JTAG programmer module
+//
+module de1flash (
+ input clock_50, // 50 MHz clock
+ input [1:0] clock_24, // 24 MHz clock (on two pins)
+ input [1:0] clock_27, // 27 MHz clock (on two pins)
+ input ext_clock, // External clock input
+
+ inout ps2_clk, // PS/2 keyboard clock
+ inout ps2_dat, // PS/2 keyboard data
+
+ output [9:0] ledr, // Red LEDs
+ output [7:0] ledg, // Green LEDs
+ output [6:0] s7_0, // 7-segment LEDs
+ output [6:0] s7_1, // 7-segment LEDs
+ output [6:0] s7_2, // 7-segment LEDs
+ output [6:0] s7_3, // 7-segment LEDs
+
+ input [3:0] key_n, // Pushbutton switches
+ input [9:0] sw, // Slide switches
+
+ output fl_rst_n, // Flash ROM RST#
+ output fl_ce_n, // Flash ROM CE#
+ output fl_oe_n, // Flash ROM OE#
+ output fl_we_n, // Flash ROM WE#
+ output [21:0] fl_a, // Flash ROM address bus
+ inout [7:0] fl_dq, // Flash ROM data bus
+
+ output [1:0] dram_ba, // SDRAM bank selects
+ output dram_ras_n, // SDRAM RAS#
+ output dram_cas_n, // SDRAM CAS#
+ output dram_cke, // SDRAM clock enable
+ output dram_clk, // SDRAM clock
+ output dram_cs_n, // SDRAM CS#
+ output dram_we_n, // SDRAM WE#
+ output [1:0] dram_dqm, // SDRAM DQM (per byte)
+ output [11:0] dram_a, // SDRAM address bus
+ inout [15:0] dram_dq, // SDRAM data bus
+
+ output sram_ce_n, // SRAM CE#
+ output sram_oe_n, // SRAM OE#
+ output sram_we_n, // SRAM WE#
+ output [1:0] sram_be_n, // SRAM UB#, LB#
+ output [17:0] sram_a, // SRAM address bus
+ inout [15:0] sram_dq, // SRAM data bus
+
+ output sd_clk, // SD card clock
+ inout sd_cmd, // SD card DI/MOSI/CMD
+ inout sd_dat0, // SD card SO/MISO/DAT0
+ inout sd_dat3, // SD card CS#/CD/DAT3
+
+ output uart_txd, // RS232 port TxD
+ input uart_rxd, // RS232 port RxD
+
+ output [3:0] vga_r, // VGA red
+ output [3:0] vga_g, // VGA green
+ output [3:0] vga_b, // VGA blue
+ output vga_hs, // VGA horz sync
+ output vga_vs, // VGA vert sync
+
+ output aud_xck, // Audio master clock
+ output aud_bclk, // Audio bitclock
+ output aud_dacdat, // Audio DAC data
+ output aud_daclrck, // Audio DAC framing
+ input aud_adcdat, // Audio ADC data
+ output aud_adclrck, // Audio ADC framing
+
+ inout i2c_scl, // I2C SCK line
+ inout i2c_sda, // I2C SDA line
+
+ inout [35:0] gpio_0, // GPIO headers
+ inout [35:0] gpio_1 // GPIO headers
+ );
+
+ wire fl_reset_n;
+
+ reg tdo;
+ wire [3:0] ir_in;
+ wire tck, tdi, v_sdr, v_cdr, v_uir, v_udr;
+
+ reg [71:0] jtag_wr_data;
+ reg [71:0] jtag_rd_data;
+ reg jtag_rd_valid;
+ reg [ 6:0] jtag_data_ctr;
+ wire [71:0] jtag_rd_q;
+ wire [ 7:0] jtag_wr_used;
+ reg [ 7:0] jtag_wr_free;
+ wire jtag_rd_empty;
+ reg jtag_bypass;
+ reg jtag_reset = 1'b0;
+
+ assign ledg[3:0] = ir_in;
+ assign ledg[7:4] = { v_udr, v_sdr, v_cdr, v_uir };
+
+ reg jtag_wr_wrq = 1'b0; // FIFO write strobe
+ reg jtag_rd_rrq = 1'b0; // FIFO read strobe
+
+ parameter cmd_read_fifo = 4'b0001;
+ parameter cmd_free_space = 4'b0010;
+ parameter cmd_write_fifo = 4'b0011;
+ parameter cmd_check_ready = 4'b0100;
+ parameter cmd_reset = 4'b0101;
+
+ // Shift registers and TDI input
+ always @(posedge tck)
+ begin
+ jtag_wr_wrq <= 1'b0;
+ jtag_rd_rrq <= 1'b0;
+ jtag_reset <= 1'b0;
+
+ if (v_udr)
+ begin
+ case (ir_in)
+ cmd_write_fifo:
+ jtag_wr_wrq <= 1'b1;
+ endcase // case(ir_in)
+ end // if (v_udr)
+ else if (v_cdr)
+ begin
+ case (ir_in)
+ cmd_read_fifo:
+ begin
+ jtag_rd_data <= { ~jtag_rd_empty, jtag_rd_q[70:0] };
+ jtag_rd_valid <= ~jtag_rd_empty;
+ jtag_data_ctr <= 7'd71;
+ end
+ cmd_free_space:
+ begin
+ jtag_wr_free <= ~jtag_wr_used;
+ end
+ endcase // case(ir_in)
+ end
+ else if (v_sdr)
+ begin
+ jtag_bypass <= tdi;
+
+ case (ir_in)
+ cmd_read_fifo:
+ begin
+ if ( jtag_data_ctr == 7'd2 )
+ begin
+ jtag_rd_rrq <= jtag_rd_valid;
+ jtag_rd_valid <= 1'b0;
+ end
+
+ if ( ~|jtag_data_ctr )
+ begin
+ jtag_rd_data <= { ~jtag_rd_empty, jtag_rd_q[70:0] };
+ jtag_rd_valid <= ~jtag_rd_empty;
+ jtag_data_ctr <= 7'd71;
+ end
+ else
+ begin
+ jtag_rd_data <= { tdi, jtag_rd_data[71:1] };
+ jtag_data_ctr <= jtag_data_ctr - 1'b1;
+ end
+ end // case: cmd_read_fifo
+ cmd_free_space:
+ jtag_wr_free <= { tdi, jtag_wr_free[ 7:1] };
+ cmd_write_fifo:
+ jtag_wr_data <= { tdi, jtag_wr_data[71:1] };
+ cmd_reset:
+ jtag_reset <= tdi;
+ endcase // case(ir_in)
+ end // if (v_sdr)
+ end
+
+ reg [2:0] jtag_ready = 3'b000;
+
+ always @(posedge tck)
+ jtag_ready <= { jtag_ready[1:0], fl_reset_n };
+
+ // TDO output MUX
+ always @ (*)
+ begin
+ case (ir_in)
+ cmd_read_fifo:
+ tdo <= jtag_rd_data[0];
+ cmd_free_space:
+ tdo <= jtag_wr_free[0];
+ cmd_write_fifo:
+ tdo <= jtag_wr_data[0];
+ cmd_reset:
+ tdo <= 1'b0; // Always read as zero
+ cmd_check_ready:
+ tdo <= jtag_ready[2];
+ default:
+ tdo <= jtag_bypass;
+ endcase // case(ir_in)
+ end // always @ (*)
+
+ vjtag_mega vjtag_mega_1
+ (
+ .ir_out ( ),
+ .tdo ( tdo ),
+ .ir_in ( ir_in ),
+ .tck ( tck ),
+ .tdi ( tdi ),
+ .virtual_state_cdr ( v_cdr ),
+ .virtual_state_cir ( ),
+ .virtual_state_e1dr ( v_udr ),
+ .virtual_state_e2dr ( ),
+ .virtual_state_pdr ( ),
+ .virtual_state_sdr ( v_sdr ),
+ .virtual_state_udr ( ),
+ .virtual_state_uir ( v_uir )
+ );
+
+ // ------------------------------------------------------------------
+ // Flash clock PLL and reset logic
+ // ------------------------------------------------------------------
+
+ wire pll_locked;
+ wire fl_clk;
+
+ pll pll (
+ .areset ( jtag_reset ),
+ .inclk0 ( clock_50 ),
+ .c0 ( fl_clk ), // 20 MHz
+ .locked ( pll_locked )
+ );
+
+ assign fl_reset_n = pll_locked;
+
+ // ------------------------------------------------------------------
+ // Write FIFO (JTAG -> programmer)
+ // ------------------------------------------------------------------
+
+ wire [71: 0] prog_wr_q;
+ wire prog_wr_rrq;
+ wire prog_wr_empty;
+
+ fl_fifo fl_wr_fifo
+ (
+ .aclr ( ~fl_reset_n ),
+
+ .wrclk ( tck ),
+ .data ( jtag_wr_data ),
+ .wrreq ( jtag_wr_wrq ),
+ .wrusedw ( jtag_wr_used ),
+ .wrfull ( ),
+
+ .rdclk ( fl_clk ),
+ .q ( prog_wr_q ),
+ .rdreq ( prog_wr_rrq ),
+ .rdempty ( prog_wr_empty )
+ );
+
+ // ------------------------------------------------------------------
+ // Read FIFO (programmer -> JTAG)
+ // ------------------------------------------------------------------
+
+ wire [71:0] prog_rd_data;
+ wire prog_rd_wrq;
+ wire prog_rd_full;
+
+ fl_fifo fl_rd_fifo
+ (
+ .aclr ( ~fl_reset_n ),
+
+ .wrclk ( fl_clk ),
+ .data ( prog_rd_data ),
+ .wrreq ( prog_rd_wrq ),
+ .wrusedw ( ),
+ .wrfull ( prog_rd_full ),
+
+ .rdclk ( tck ),
+ .q ( jtag_rd_q ),
+ .rdreq ( jtag_rd_rrq ),
+ .rdempty ( jtag_rd_empty )
+ );
+
+ // ------------------------------------------------------------------
+ // Flash state machine
+ // This is clocked at 20 MHz (50 ns); one clock cycle for each
+ // rising or falling edge
+ // ------------------------------------------------------------------
+
+ reg [63:0] fl_data; // Data shift register
+ reg [31:0] fl_bytectr; // Byte counter
+ reg [ 2:0] fl_rbctr; // Read bytes in shift register
+ reg [ 3:0] fl_rbcmd; // Command code
+ reg [31:0] fl_addr;
+
+ reg fl_ce_q;
+ reg fl_oe_q;
+ reg fl_we_q;
+ reg [31:0] fl_a_q;
+ reg [ 7:0] fl_d_q;
+ reg fl_d_en;
+
+ assign fl_rst_n = fl_reset_n;
+ assign fl_ce_n = ~fl_ce_q;
+ assign fl_oe_n = ~fl_oe_q;
+ assign fl_we_n = ~fl_we_q;
+ assign fl_a = fl_a_q[21:0];
+ assign fl_dq = fl_d_en ? fl_d_q : 8'hzz;
+
+ reg [4:0] prog_state;
+ parameter pst_idle = 5'h00;
+ parameter pst_delay = 5'h01;
+ parameter pst_status = 5'h02;
+ parameter pst_read0 = 5'h04;
+ parameter pst_read1 = 5'h05;
+ parameter pst_read2 = 5'h06;
+ parameter pst_readpad = 5'h07;
+ parameter pst_write0 = 5'h08;
+ parameter pst_write1 = 5'h09;
+ parameter pst_zchk0 = 5'h0A;
+ parameter pst_zchk1 = 5'h0B;
+ parameter pst_zchk2 = 5'h0C;
+ parameter pst_crc0 = 5'h0D;
+ parameter pst_crc1 = 5'h0E;
+ parameter pst_crc2 = 5'h0F;
+ parameter pst_program0 = 5'h10;
+ parameter pst_program1 = 5'h11;
+ parameter pst_program2 = 5'h12;
+ parameter pst_program3 = 5'h13;
+ parameter pst_program4 = 5'h14;
+ parameter pst_program5 = 5'h15;
+ parameter pst_program6 = 5'h16;
+ parameter pst_program7 = 5'h17;
+ parameter pst_program8 = 5'h18;
+ parameter pst_program9 = 5'h19;
+ parameter pst_program10 = 5'h1A;
+ parameter pst_program11 = 5'h1B;
+ parameter pst_program12 = 5'h1C;
+ parameter pst_program13 = 5'h1D;
+ parameter pst_program14 = 5'h1E;
+
+ reg rd_ack;
+
+ reg [7:0] pgm_data;
+ reg [7:0] tst_data;
+
+ // Debugging... registering these is "free" since there are
+ // registers in the I/O buffers, and deconstrains the design
+ reg [9:0] ledr_q;
+ assign ledr = ledr_q;
+
+ always @(posedge fl_clk or negedge fl_reset_n)
+ if (~fl_reset_n)
+ begin
+ ledr_q <= ~10'b0;
+ end
+ else
+ begin
+ ledr_q[0] <= prog_rd_full;
+ ledr_q[1] <= fl_ce_q;
+ ledr_q[2] <= fl_oe_q;
+ ledr_q[3] <= fl_we_q;
+ ledr_q[4] <= fl_d_en;
+ ledr_q[9:5] <= prog_state;
+ end
+
+ reg [6:0] s7_0_q;
+ reg [6:0] s7_1_q;
+ reg [6:0] s7_2_q;
+ reg [6:0] s7_3_q;
+
+ wire [6:0] s7_0_w;
+ wire [6:0] s7_1_w;
+ wire [6:0] s7_2_w;
+ wire [6:0] s7_3_w;
+
+ assign s7_0 = s7_0_q;
+ assign s7_1 = s7_1_q;
+ assign s7_2 = s7_2_q;
+ assign s7_3 = s7_3_q;
+
+ hexled hexled0 ( .value (fl_addr[11: 8]), .s7 (s7_0_w) );
+ hexled hexled1 ( .value (fl_addr[15:12]), .s7 (s7_1_w) );
+ hexled hexled2 ( .value (fl_addr[19:16]), .s7 (s7_2_w) );
+ hexled hexled3 ( .value (fl_addr[23:20]), .s7 (s7_3_w) );
+
+ reg [2:0] rd_cnt;
+
+ always @(posedge fl_clk or negedge fl_reset_n)
+ if (~fl_reset_n)
+ begin
+ s7_0_q <= ~7'b1000000;
+ s7_1_q <= ~7'b1000000;
+ s7_2_q <= ~7'b1000000;
+ s7_3_q <= ~7'b1000000;
+ end
+ else
+ begin
+ s7_0_q <= s7_0_w;
+ s7_1_q <= s7_1_w;
+ s7_2_q <= s7_2_w;
+ s7_3_q <= s7_3_w;
+ end
+
+ assign prog_wr_rrq = ~prog_wr_empty & (prog_state == pst_idle);
+ assign prog_rd_wrq = rd_ack;
+ assign prog_rd_data = { 1'b1, rd_cnt, fl_rbcmd, fl_data };
+
+ always @(negedge fl_reset_n or posedge fl_clk)
+ if (~fl_reset_n)
+ rd_cnt <= 3'b000;
+ else
+ rd_cnt <= rd_cnt + rd_ack;
+
+ wire bump_addr =
+ (prog_state == pst_read2) |
+ (prog_state == pst_zchk2) |
+ (prog_state == pst_crc2) |
+ (prog_state == pst_write1) |
+ ((prog_state == pst_program3) & ~|(tst_data & ~fl_data[7:0])) |
+ ((prog_state == pst_program14) & (tst_data == pgm_data));
+
+ wire [31:0] tst_crc;
+ crc_32_d8 crcgen
+ (
+ .data ( tst_data ),
+ .in ( fl_data[31:0] ),
+ .out ( tst_crc )
+ );
+ reg bump_crc;
+
+ always @(negedge fl_reset_n or posedge fl_clk)
+ if (~fl_reset_n)
+ begin
+ fl_ce_q <= 1'b0;
+ fl_oe_q <= 1'b0;
+ fl_we_q <= 1'b0;
+ fl_addr <= 32'h0;
+ fl_a_q <= 32'h0;
+ fl_d_q <= 8'h0;
+ fl_d_en <= 1'b0;
+
+ fl_data <= 64'bx;
+ fl_bytectr <= 32'h0;
+ fl_rbctr <= 3'h0;
+ fl_rbcmd <= 4'bx;
+
+ prog_state <= pst_idle;
+ rd_ack <= 1'b0;
+ bump_crc <= 1'b0;
+
+ pgm_data <= 8'hxx;
+ tst_data <= 8'hff;
+ end
+ else
+ begin
+ fl_ce_q <= 1'b0;
+ fl_oe_q <= 1'b0;
+ fl_we_q <= 1'b0;
+ fl_d_en <= 1'b0;
+
+ rd_ack <= 1'b0;
+ bump_crc <= 1'b0;
+
+ fl_addr <= fl_addr + bump_addr;
+
+ case ( prog_state )
+ pst_idle:
+ begin
+ fl_rbctr <= 3'h0;
+ fl_rbcmd <= prog_wr_q[71:68];
+ tst_data <= 8'hff;
+
+ if ( ~prog_wr_empty )
+ casez ( prog_wr_q[71:68] )
+ 4'b0010: // Delay command
+ begin
+ fl_bytectr <= prog_wr_q[31:0];
+ prog_state <= pst_delay;
+ end
+ 4'b0101: // Zero check
+ begin
+ fl_addr <= prog_wr_q[63:32];
+ fl_bytectr <= prog_wr_q[31:0];
+ prog_state <= pst_zchk0;
+ end
+ 4'b0110: // Read back address, token
+ begin
+ fl_data <= { fl_addr, prog_wr_q[31:0] };
+ prog_state <= pst_status;
+ end
+ 4'b0111: // CRC32
+ begin
+ fl_addr <= prog_wr_q[63:32];
+ fl_bytectr <= prog_wr_q[31:0];
+ fl_data[63:32] <= 32'hxxxxxxxx;
+ fl_data[31: 0] <= 32'h00000000;
+ prog_state <= pst_crc0;
+ end
+ 4'b100z: // Write bytes command
+ begin
+ fl_data <= prog_wr_q[63:0];
+ if ( prog_wr_q[68] )
+ fl_addr <= prog_wr_q[63:32];
+ prog_state <= pst_write0;
+ end
+ 4'b1011: // Program bytes command
+ begin
+ fl_bytectr <= { 28'b0, prog_wr_q[67:64] };
+ fl_data <= prog_wr_q[63:0];
+ prog_state <= pst_program0;
+ end
+ 4'b1101: // Set address register/read command
+ begin
+ fl_addr <= prog_wr_q[63:32];
+ fl_bytectr <= prog_wr_q[31:0];
+ prog_state <= pst_read0;
+ end
+ endcase // case( prog_wr_q[71:69] )
+ end // case: pst_idle
+
+ pst_delay:
+ begin
+ if ( |fl_bytectr )
+ fl_bytectr <= fl_bytectr - 1'b1;
+ else
+ prog_state <= pst_idle;
+ end
+
+ pst_status:
+ begin
+ if ( ~prog_rd_full )
+ begin
+ rd_ack <= 1'b1;
+ prog_state <= pst_idle;
+ end
+ end
+
+ pst_read0: // Read initial state
+ begin
+ fl_a_q <= fl_addr;
+ if ( |fl_bytectr )
+ begin
+ if ( ~prog_rd_full )
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_read1;
+ end
+ end
+ else if ( |fl_rbctr )
+ begin
+ if ( ~prog_rd_full )
+ prog_state <= pst_readpad;
+ end
+ else
+ prog_state <= pst_idle;
+ end // case: pst_read0
+
+ pst_read1: // Read output waveform #1
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_read2;
+ end
+
+ pst_read2:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_data <= { fl_dq, fl_data[63:8] };
+ rd_ack <= &fl_rbctr;
+ fl_bytectr <= fl_bytectr - 1'b1;
+ fl_rbctr <= fl_rbctr + 1'b1;
+ prog_state <= pst_read0;
+ end
+
+ pst_readpad:
+ begin
+ fl_data <= { 8'hFF, fl_data[63:8] };
+ rd_ack <= &fl_rbctr;
+ fl_rbctr <= fl_rbctr + 1'b1;
+ prog_state <= pst_read0;
+ end
+
+ pst_zchk0: // Zero check
+ begin
+ fl_a_q <= fl_addr;
+ if ( (&tst_data) & (|fl_bytectr) )
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ fl_data[63:32] <= 32'hxxxxxxxx;
+ fl_data[31: 0] <= 32'hxxxxxxxx;
+ prog_state <= pst_zchk1;
+ end
+ else if ( ~prog_rd_full )
+ begin
+ fl_data[63:32] <= fl_addr;
+ fl_data[31: 8] <= 24'hffffff;
+ fl_data[ 7: 0] <= tst_data;
+ rd_ack <= 1'b1;
+ prog_state <= pst_idle;
+ end // else: !if( |fl_bytectr )
+ end // case: pst_zchk0
+
+ pst_zchk1:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_zchk2;
+ end
+
+ pst_zchk2:
+ begin
+ fl_ce_q <= 1'b1;
+ tst_data <= fl_dq;
+ fl_bytectr <= fl_bytectr - 1'b1;
+ prog_state <= pst_zchk0;
+ end
+
+ pst_crc0: // CRC32
+ begin
+ fl_a_q <= fl_addr;
+ if ( bump_crc )
+ fl_data[31: 0] <= tst_crc;
+ if ( |fl_bytectr )
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ fl_data[63:32] <= 32'hxxxxxxxx;
+ prog_state <= pst_crc1;
+ end
+ else if ( ~prog_rd_full )
+ begin
+ fl_data[63:32] <= fl_addr;
+ rd_ack <= 1'b1;
+ prog_state <= pst_idle;
+ end // else: !if( |fl_bytectr )
+ end // case: pst_crc0
+
+ pst_crc1:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_crc2;
+ end
+
+ pst_crc2:
+ begin
+ fl_ce_q <= 1'b1;
+ tst_data <= fl_dq;
+ fl_bytectr <= fl_bytectr - 1'b1;
+ bump_crc <= 1'b1;
+ prog_state <= pst_crc0;
+ end
+
+ pst_write0:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_we_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ fl_d_q <= fl_data[7:0];
+ fl_a_q <= fl_data[63:32];
+ prog_state <= pst_write1;
+ end
+
+ pst_write1:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ prog_state <= pst_idle;
+ end
+
+ // Programming algorithm: read individual bytes to avoid
+ // hanging the flash chip due to zero bits
+ pst_program0:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ fl_a_q <= fl_addr;
+ prog_state <= pst_program1;
+ end
+
+ pst_program1:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_program2;
+ end
+
+ pst_program2:
+ begin
+ fl_ce_q <= 1'b1;
+ tst_data <= fl_dq;
+ prog_state <= pst_program3;
+ fl_bytectr <= fl_bytectr - 1'b1;
+ end
+
+ pst_program3:
+ begin
+ fl_ce_q <= 1'b1;
+ pgm_data <= tst_data & fl_data[7:0];
+ fl_data <= { 8'hFF, fl_data[63:8] };
+
+ if ( |(tst_data & ~fl_data[7:0]) )
+ begin
+ fl_we_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ fl_d_q <= 8'hAA;
+ fl_a_q <= 32'hAAAA_AAAA;
+ prog_state <= pst_program4;
+ end
+ else
+ begin
+ if ( |fl_bytectr )
+ prog_state <= pst_program0;
+ else
+ prog_state <= pst_idle;
+ end
+ end // case: pst_program3
+
+ pst_program4:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ prog_state <= pst_program5;
+ end
+
+ pst_program5:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_we_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ fl_d_q <= 8'h55;
+ fl_a_q <= 32'h5555_5555;
+ prog_state <= pst_program6;
+ end
+
+ pst_program6:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ prog_state <= pst_program7;
+ end
+
+ pst_program7:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_we_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ fl_d_q <= 8'hA0;
+ fl_a_q <= 32'hAAAA_AAAA;
+ prog_state <= pst_program8;
+ end
+
+ pst_program8:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ prog_state <= pst_program9;
+ end
+
+ pst_program9:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_we_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ fl_d_q <= pgm_data;
+ fl_a_q <= fl_addr;
+ prog_state <= pst_program10;
+ end
+
+ pst_program10:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_d_en <= 1'b1;
+ prog_state <= pst_program11;
+ end
+
+ pst_program11:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_program12;
+ end
+
+ pst_program12:
+ begin
+ fl_ce_q <= 1'b1;
+ fl_oe_q <= 1'b1;
+ prog_state <= pst_program13;
+ end
+
+ pst_program13:
+ begin
+ fl_ce_q <= 1'b1;
+ tst_data <= fl_dq;
+ prog_state <= pst_program14;
+ end
+
+ pst_program14:
+ begin
+ fl_ce_q <= 1'b1;
+ if ( tst_data != pgm_data )
+ prog_state <= pst_program11;
+ else if ( |fl_bytectr )
+ prog_state <= pst_program0;
+ else
+ prog_state <= pst_idle;
+ end
+ endcase // case( prog_state )
+ end
+
+ // ------------------------------------------------------------------
+ // Unused hardware ports
+ // ------------------------------------------------------------------
+
+ // PS/2 port
+ assign ps2_clk = 1'bz;
+ assign ps2_dat = 1'bz;
+
+ // SDRAM
+ assign dram_ba = 2'b11;
+ assign dram_ras_n = 1'b1;
+ assign dram_cas_n = 1'b1;
+ assign dram_cke = 1'b1;
+ assign dram_clk = 1'b1;
+ assign dram_cs_n = 1'b1;
+ assign dram_we_n = 1'b1;
+ assign dram_dqm = 2'b11;
+ assign dram_a = ~12'b0;
+ assign dram_dq = 16'hzzzz;
+
+ // SRAM
+ assign sram_ce_n = 1'b1;
+ assign sram_oe_n = 1'b1;
+ assign sram_we_n = 1'b1;
+ assign sram_be_n = 2'b11;
+ assign sram_a = ~18'b0;
+ assign sram_dq = 16'hzzzz;
+
+ // SD card
+ assign sd_clk = 1'b1;
+ assign sd_cmd = 1'bz;
+ assign sd_dat0 = 1'bz;
+ assign sd_dat3 = 1'bz;
+
+ // RS232
+ assign uart_txd = 1'b1;
+
+ // Video
+ assign vga_r = 4'b0;
+ assign vga_g = 4'b0;
+ assign vga_b = 4'b0;
+ assign vga_hs = 1'b0;
+ assign vga_vs = 1'b0;
+
+ // Audio I2S
+ assign aud_xck = 1'b1;
+ assign aud_bclk = 1'b1;
+ assign aud_dacdat = 1'b1;
+ assign aud_daclrck = 1'b1;
+ assign aud_adclrck = 1'b1;
+
+ // Audio I2C
+ assign i2c_scl = 1'bz;
+ assign i2c_sda = 1'bz;
+
+ // GPIO
+ assign gpio_0 = 36'hz_zzzz_zzzz;
+ assign gpio_1 = 36'hz_zzzz_zzzz;
+
+endmodule // de1flash
diff --git a/de1/fpga-flash-nor/fl_fifo.qip b/de1/fpga-flash-nor/fl_fifo.qip
new file mode 100644
index 0000000..7981a70
--- /dev/null
+++ b/de1/fpga-flash-nor/fl_fifo.qip
@@ -0,0 +1,4 @@
+set_global_assignment -name IP_TOOL_NAME "FIFO"
+set_global_assignment -name IP_TOOL_VERSION "11.0"
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "fl_fifo.v"]
+set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "fl_fifo_bb.v"]
diff --git a/de1/fpga-flash-nor/fl_fifo.v b/de1/fpga-flash-nor/fl_fifo.v
new file mode 100644
index 0000000..c16e687
--- /dev/null
+++ b/de1/fpga-flash-nor/fl_fifo.v
@@ -0,0 +1,185 @@
+// megafunction wizard: %FIFO%
+// GENERATION: STANDARD
+// VERSION: WM1.0
+// MODULE: dcfifo
+
+// ============================================================
+// File Name: fl_fifo.v
+// Megafunction Name(s):
+// dcfifo
+//
+// Simulation Library Files(s):
+// altera_mf
+// ============================================================
+// ************************************************************
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+//
+// 11.0 Build 157 04/27/2011 SJ Web Edition
+// ************************************************************
+
+
+//Copyright (C) 1991-2011 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 fl_fifo (
+ aclr,
+ data,
+ rdclk,
+ rdreq,
+ wrclk,
+ wrreq,
+ q,
+ rdempty,
+ wrfull,
+ wrusedw);
+
+ input aclr;
+ input [71:0] data;
+ input rdclk;
+ input rdreq;
+ input wrclk;
+ input wrreq;
+ output [71:0] q;
+ output rdempty;
+ output wrfull;
+ output [7:0] wrusedw;
+`ifndef ALTERA_RESERVED_QIS
+// synopsys translate_off
+`endif
+ tri0 aclr;
+`ifndef ALTERA_RESERVED_QIS
+// synopsys translate_on
+`endif
+
+ wire sub_wire0;
+ wire [71:0] sub_wire1;
+ wire sub_wire2;
+ wire [7:0] sub_wire3;
+ wire wrfull = sub_wire0;
+ wire [71:0] q = sub_wire1[71:0];
+ wire rdempty = sub_wire2;
+ wire [7:0] wrusedw = sub_wire3[7:0];
+
+ dcfifo dcfifo_component (
+ .rdclk (rdclk),
+ .wrclk (wrclk),
+ .wrreq (wrreq),
+ .aclr (aclr),
+ .data (data),
+ .rdreq (rdreq),
+ .wrfull (sub_wire0),
+ .q (sub_wire1),
+ .rdempty (sub_wire2),
+ .wrusedw (sub_wire3),
+ .rdfull (),
+ .rdusedw (),
+ .wrempty ());
+ defparam
+ dcfifo_component.intended_device_family = "Cyclone II",
+ dcfifo_component.lpm_hint = "MAXIMIZE_SPEED=5,",
+ dcfifo_component.lpm_numwords = 256,
+ dcfifo_component.lpm_showahead = "ON",
+ dcfifo_component.lpm_type = "dcfifo",
+ dcfifo_component.lpm_width = 72,
+ dcfifo_component.lpm_widthu = 8,
+ dcfifo_component.overflow_checking = "ON",
+ dcfifo_component.rdsync_delaypipe = 5,
+ dcfifo_component.underflow_checking = "ON",
+ dcfifo_component.use_eab = "ON",
+ dcfifo_component.write_aclr_synch = "ON",
+ dcfifo_component.wrsync_delaypipe = 5;
+
+
+endmodule
+
+// ============================================================
+// CNX file retrieval info
+// ============================================================
+// Retrieval info: PRIVATE: AlmostEmpty NUMERIC "0"
+// Retrieval info: PRIVATE: AlmostEmptyThr NUMERIC "-1"
+// Retrieval info: PRIVATE: AlmostFull NUMERIC "0"
+// Retrieval info: PRIVATE: AlmostFullThr NUMERIC "-1"
+// Retrieval info: PRIVATE: CLOCKS_ARE_SYNCHRONIZED NUMERIC "0"
+// Retrieval info: PRIVATE: Clock NUMERIC "4"
+// Retrieval info: PRIVATE: Depth NUMERIC "256"
+// Retrieval info: PRIVATE: Empty NUMERIC "1"
+// Retrieval info: PRIVATE: Full NUMERIC "1"
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+// Retrieval info: PRIVATE: LE_BasedFIFO NUMERIC "0"
+// Retrieval info: PRIVATE: LegacyRREQ NUMERIC "0"
+// Retrieval info: PRIVATE: MAX_DEPTH_BY_9 NUMERIC "0"
+// Retrieval info: PRIVATE: OVERFLOW_CHECKING NUMERIC "0"
+// Retrieval info: PRIVATE: Optimize NUMERIC "2"
+// Retrieval info: PRIVATE: RAM_BLOCK_TYPE NUMERIC "0"
+// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
+// Retrieval info: PRIVATE: UNDERFLOW_CHECKING NUMERIC "0"
+// Retrieval info: PRIVATE: UsedW NUMERIC "1"
+// Retrieval info: PRIVATE: Width NUMERIC "72"
+// Retrieval info: PRIVATE: dc_aclr NUMERIC "1"
+// Retrieval info: PRIVATE: diff_widths NUMERIC "0"
+// Retrieval info: PRIVATE: msb_usedw NUMERIC "0"
+// Retrieval info: PRIVATE: output_width NUMERIC "72"
+// Retrieval info: PRIVATE: rsEmpty NUMERIC "1"
+// Retrieval info: PRIVATE: rsFull NUMERIC "0"
+// Retrieval info: PRIVATE: rsUsedW NUMERIC "0"
+// Retrieval info: PRIVATE: sc_aclr NUMERIC "0"
+// Retrieval info: PRIVATE: sc_sclr NUMERIC "0"
+// Retrieval info: PRIVATE: wsEmpty NUMERIC "0"
+// Retrieval info: PRIVATE: wsFull NUMERIC "1"
+// Retrieval info: PRIVATE: wsUsedW NUMERIC "1"
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+// Retrieval info: CONSTANT: LPM_HINT STRING "MAXIMIZE_SPEED=5,"
+// Retrieval info: CONSTANT: LPM_NUMWORDS NUMERIC "256"
+// Retrieval info: CONSTANT: LPM_SHOWAHEAD STRING "ON"
+// Retrieval info: CONSTANT: LPM_TYPE STRING "dcfifo"
+// Retrieval info: CONSTANT: LPM_WIDTH NUMERIC "72"
+// Retrieval info: CONSTANT: LPM_WIDTHU NUMERIC "8"
+// Retrieval info: CONSTANT: OVERFLOW_CHECKING STRING "ON"
+// Retrieval info: CONSTANT: RDSYNC_DELAYPIPE NUMERIC "5"
+// Retrieval info: CONSTANT: UNDERFLOW_CHECKING STRING "ON"
+// Retrieval info: CONSTANT: USE_EAB STRING "ON"
+// Retrieval info: CONSTANT: WRITE_ACLR_SYNCH STRING "ON"
+// Retrieval info: CONSTANT: WRSYNC_DELAYPIPE NUMERIC "5"
+// Retrieval info: USED_PORT: aclr 0 0 0 0 INPUT GND "aclr"
+// Retrieval info: USED_PORT: data 0 0 72 0 INPUT NODEFVAL "data[71..0]"
+// Retrieval info: USED_PORT: q 0 0 72 0 OUTPUT NODEFVAL "q[71..0]"
+// Retrieval info: USED_PORT: rdclk 0 0 0 0 INPUT NODEFVAL "rdclk"
+// Retrieval info: USED_PORT: rdempty 0 0 0 0 OUTPUT NODEFVAL "rdempty"
+// Retrieval info: USED_PORT: rdreq 0 0 0 0 INPUT NODEFVAL "rdreq"
+// Retrieval info: USED_PORT: wrclk 0 0 0 0 INPUT NODEFVAL "wrclk"
+// Retrieval info: USED_PORT: wrfull 0 0 0 0 OUTPUT NODEFVAL "wrfull"
+// Retrieval info: USED_PORT: wrreq 0 0 0 0 INPUT NODEFVAL "wrreq"
+// Retrieval info: USED_PORT: wrusedw 0 0 8 0 OUTPUT NODEFVAL "wrusedw[7..0]"
+// Retrieval info: CONNECT: @aclr 0 0 0 0 aclr 0 0 0 0
+// Retrieval info: CONNECT: @data 0 0 72 0 data 0 0 72 0
+// Retrieval info: CONNECT: @rdclk 0 0 0 0 rdclk 0 0 0 0
+// Retrieval info: CONNECT: @rdreq 0 0 0 0 rdreq 0 0 0 0
+// Retrieval info: CONNECT: @wrclk 0 0 0 0 wrclk 0 0 0 0
+// Retrieval info: CONNECT: @wrreq 0 0 0 0 wrreq 0 0 0 0
+// Retrieval info: CONNECT: q 0 0 72 0 @q 0 0 72 0
+// Retrieval info: CONNECT: rdempty 0 0 0 0 @rdempty 0 0 0 0
+// Retrieval info: CONNECT: wrfull 0 0 0 0 @wrfull 0 0 0 0
+// Retrieval info: CONNECT: wrusedw 0 0 8 0 @wrusedw 0 0 8 0
+// Retrieval info: GEN_FILE: TYPE_NORMAL fl_fifo.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fl_fifo.inc FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fl_fifo.cmp FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fl_fifo.bsf FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fl_fifo_inst.v FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL fl_fifo_bb.v TRUE
+// Retrieval info: LIB_FILE: altera_mf
diff --git a/de1/fpga-flash-nor/hexled.v b/de1/fpga-flash-nor/hexled.v
new file mode 100644
index 0000000..1c25a59
--- /dev/null
+++ b/de1/fpga-flash-nor/hexled.v
@@ -0,0 +1,72 @@
+module hexled (
+ value,
+ s7
+ );
+
+ input [3:0] value;
+ output [6:0] s7;
+ reg [6:0] s7;
+
+ always @( value )
+ begin
+ case ( value )
+ 4'h0: s7 = ~7'b0111111;
+ 4'h1: s7 = ~7'b0000110;
+ 4'h2: s7 = ~7'b1011011;
+ 4'h3: s7 = ~7'b1001111;
+ 4'h4: s7 = ~7'b1100110;
+ 4'h5: s7 = ~7'b1101101;
+ 4'h6: s7 = ~7'b1111101;
+ 4'h7: s7 = ~7'b0000111;
+ 4'h8: s7 = ~7'b1111111;
+ 4'h9: s7 = ~7'b1101111;
+ 4'hA: s7 = ~7'b1110111;
+ 4'hB: s7 = ~7'b1111100;
+ 4'hC: s7 = ~7'b0111001;
+ 4'hD: s7 = ~7'b1011110;
+ 4'hE: s7 = ~7'b1111001;
+ 4'hF: s7 = ~7'b1110001;
+ endcase
+ end
+endmodule // hexled
+
+module hexledx (
+ value,
+ blank,
+ minus,
+ s7
+ );
+
+ input [3:0] value;
+ input blank;
+ input minus;
+ output [6:0] s7;
+ reg [6:0] s7;
+
+ always @( value or blank or minus )
+ begin
+ if ( blank )
+ s7 = ~7'b0000000;
+ else if ( minus )
+ s7 = ~7'b1000000;
+ else case ( value )
+ 4'h0: s7 = ~7'b0111111;
+ 4'h1: s7 = ~7'b0000110;
+ 4'h2: s7 = ~7'b1011011;
+ 4'h3: s7 = ~7'b1001111;
+ 4'h4: s7 = ~7'b1100110;
+ 4'h5: s7 = ~7'b1101101;
+ 4'h6: s7 = ~7'b1111101;
+ 4'h7: s7 = ~7'b0000111;
+ 4'h8: s7 = ~7'b1111111;
+ 4'h9: s7 = ~7'b1101111;
+ 4'hA: s7 = ~7'b1110111;
+ 4'hB: s7 = ~7'b1111100;
+ 4'hC: s7 = ~7'b0111001;
+ 4'hD: s7 = ~7'b1011110;
+ 4'hE: s7 = ~7'b1111001;
+ 4'hF: s7 = ~7'b1110001;
+ endcase
+ end
+endmodule // hexledx
+
diff --git a/de1/fpga-flash-nor/pll.qip b/de1/fpga-flash-nor/pll.qip
new file mode 100644
index 0000000..39950ff
--- /dev/null
+++ b/de1/fpga-flash-nor/pll.qip
@@ -0,0 +1,5 @@
+set_global_assignment -name IP_TOOL_NAME "ALTPLL"
+set_global_assignment -name IP_TOOL_VERSION "11.0"
+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_bb.v"]
+set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"]
diff --git a/de1/fpga-flash-nor/pll.v b/de1/fpga-flash-nor/pll.v
new file mode 100644
index 0000000..93ce8a4
--- /dev/null
+++ b/de1/fpga-flash-nor/pll.v
@@ -0,0 +1,323 @@
+// 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!
+//
+// 11.0 Build 157 04/27/2011 SJ Web Edition
+// ************************************************************
+
+
+//Copyright (C) 1991-2011 Altera Corporation
+//Your use of Altera Corporation's design tools, logic functions
+//and other software and tools, and its AMPP partner logic
+//functions, and any output files from any of the foregoing
+//(including device programming or simulation files), and any
+//associated documentation or information are expressly subject
+//to the terms and conditions of the Altera Program License
+//Subscription Agreement, Altera MegaCore Function License
+//Agreement, or other applicable license agreement, including,
+//without limitation, that your use is for the sole purpose of
+//programming logic devices manufactured by Altera and sold by
+//Altera or its authorized distributors. Please refer to the
+//applicable agreement for further details.
+
+
+// synopsys translate_off
+`timescale 1 ps / 1 ps
+// synopsys translate_on
+module pll (
+ areset,
+ inclk0,
+ c0,
+ locked);
+
+ input areset;
+ input inclk0;
+ output c0;
+ output locked;
+`ifndef ALTERA_RESERVED_QIS
+// synopsys translate_off
+`endif
+ tri0 areset;
+`ifndef ALTERA_RESERVED_QIS
+// synopsys translate_on
+`endif
+
+ wire sub_wire0;
+ wire [5:0] sub_wire1;
+ wire [0:0] sub_wire5 = 1'h0;
+ wire locked = sub_wire0;
+ wire [0:0] sub_wire2 = sub_wire1[0:0];
+ wire c0 = sub_wire2;
+ wire sub_wire3 = inclk0;
+ wire [1:0] sub_wire4 = {sub_wire5, sub_wire3};
+
+ altpll altpll_component (
+ .areset (areset),
+ .inclk (sub_wire4),
+ .locked (sub_wire0),
+ .clk (sub_wire1),
+ .activeclock (),
+ .clkbad (),
+ .clkena ({6{1'b1}}),
+ .clkloss (),
+ .clkswitch (1'b0),
+ .configupdate (1'b0),
+ .enable0 (),
+ .enable1 (),
+ .extclk (),
+ .extclkena ({4{1'b1}}),
+ .fbin (1'b1),
+ .fbmimicbidir (),
+ .fbout (),
+ .fref (),
+ .icdrclk (),
+ .pfdena (1'b1),
+ .phasecounterselect ({4{1'b1}}),
+ .phasedone (),
+ .phasestep (1'b1),
+ .phaseupdown (1'b1),
+ .pllena (1'b1),
+ .scanaclr (1'b0),
+ .scanclk (1'b0),
+ .scanclkena (1'b1),
+ .scandata (1'b0),
+ .scandataout (),
+ .scandone (),
+ .scanread (1'b0),
+ .scanwrite (1'b0),
+ .sclkout0 (),
+ .sclkout1 (),
+ .vcooverrange (),
+ .vcounderrange ());
+ defparam
+ altpll_component.clk0_divide_by = 5,
+ altpll_component.clk0_duty_cycle = 50,
+ altpll_component.clk0_multiply_by = 2,
+ altpll_component.clk0_phase_shift = "0",
+ altpll_component.compensate_clock = "CLK0",
+ altpll_component.gate_lock_counter = 1048575,
+ altpll_component.gate_lock_signal = "YES",
+ altpll_component.inclk0_input_frequency = 20000,
+ altpll_component.intended_device_family = "Cyclone II",
+ altpll_component.invalid_lock_multiplier = 5,
+ altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
+ altpll_component.lpm_type = "altpll",
+ altpll_component.operation_mode = "NORMAL",
+ altpll_component.port_activeclock = "PORT_UNUSED",
+ altpll_component.port_areset = "PORT_USED",
+ altpll_component.port_clkbad0 = "PORT_UNUSED",
+ altpll_component.port_clkbad1 = "PORT_UNUSED",
+ altpll_component.port_clkloss = "PORT_UNUSED",
+ altpll_component.port_clkswitch = "PORT_UNUSED",
+ altpll_component.port_configupdate = "PORT_UNUSED",
+ altpll_component.port_fbin = "PORT_UNUSED",
+ altpll_component.port_inclk0 = "PORT_USED",
+ altpll_component.port_inclk1 = "PORT_UNUSED",
+ altpll_component.port_locked = "PORT_USED",
+ altpll_component.port_pfdena = "PORT_UNUSED",
+ altpll_component.port_phasecounterselect = "PORT_UNUSED",
+ altpll_component.port_phasedone = "PORT_UNUSED",
+ altpll_component.port_phasestep = "PORT_UNUSED",
+ altpll_component.port_phaseupdown = "PORT_UNUSED",
+ altpll_component.port_pllena = "PORT_UNUSED",
+ altpll_component.port_scanaclr = "PORT_UNUSED",
+ altpll_component.port_scanclk = "PORT_UNUSED",
+ altpll_component.port_scanclkena = "PORT_UNUSED",
+ altpll_component.port_scandata = "PORT_UNUSED",
+ altpll_component.port_scandataout = "PORT_UNUSED",
+ altpll_component.port_scandone = "PORT_UNUSED",
+ altpll_component.port_scanread = "PORT_UNUSED",
+ altpll_component.port_scanwrite = "PORT_UNUSED",
+ altpll_component.port_clk0 = "PORT_USED",
+ altpll_component.port_clk1 = "PORT_UNUSED",
+ 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.valid_lock_multiplier = 1;
+
+
+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 "0"
+// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
+// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
+// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
+// Retrieval info: PRIVATE: BANDWIDTH_USE_CUSTOM STRING "0"
+// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
+// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
+// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
+// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "1"
+// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
+// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
+// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
+// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
+// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
+// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "7"
+// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
+// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
+// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "20.000000"
+// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
+// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
+// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
+// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "1"
+// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "1"
+// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
+// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
+// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "50.000"
+// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
+// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
+// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
+// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
+// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
+// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
+// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
+// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
+// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
+// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
+// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
+// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
+// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "1"
+// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
+// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "20.00000000"
+// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
+// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
+// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "0"
+// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
+// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
+// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
+// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
+// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
+// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "1"
+// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
+// Retrieval info: PRIVATE: PLL_ENA_CHECK STRING "0"
+// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
+// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
+// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
+// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
+// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
+// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
+// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
+// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
+// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
+// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "0"
+// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
+// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
+// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
+// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
+// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
+// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
+// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
+// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
+// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
+// Retrieval info: PRIVATE: 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_CLKENA0 STRING "0"
+// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
+// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "5"
+// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
+// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "2"
+// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
+// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
+// Retrieval info: CONSTANT: GATE_LOCK_COUNTER NUMERIC "1048575"
+// Retrieval info: CONSTANT: GATE_LOCK_SIGNAL STRING "YES"
+// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "20000"
+// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+// Retrieval info: CONSTANT: INVALID_LOCK_MULTIPLIER NUMERIC "5"
+// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
+// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
+// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_USED"
+// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
+// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
+// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
+// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
+// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_UNUSED"
+// 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: VALID_LOCK_MULTIPLIER NUMERIC "1"
+// Retrieval info: USED_PORT: @clk 0 0 6 0 OUTPUT_CLK_EXT VCC "@clk[5..0]"
+// Retrieval info: USED_PORT: @extclk 0 0 4 0 OUTPUT_CLK_EXT VCC "@extclk[3..0]"
+// Retrieval info: USED_PORT: areset 0 0 0 0 INPUT GND "areset"
+// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
+// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
+// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
+// Retrieval info: CONNECT: @areset 0 0 0 0 areset 0 0 0 0
+// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
+// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
+// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
+// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v TRUE
+// Retrieval info: LIB_FILE: altera_mf
+// Retrieval info: CBX_MODULE_PREFIX: ON
diff --git a/de1/fpga-flash-nor/protocol.txt b/de1/fpga-flash-nor/protocol.txt
new file mode 100644
index 0000000..d7a1968
--- /dev/null
+++ b/de1/fpga-flash-nor/protocol.txt
@@ -0,0 +1,64 @@
+Virtual IR register (4 bits):
+
+0 - bypass
+1 - read fifo
+2 - write fifo space query
+3 - write fifo
+4 - read ready (single bit)
+5 - write reset flag (single bit; write 1 then 0)
+F - bypass
+
+Virtual DR register 1:
+
+READ FIFO
+
+72 bits:
+-binary- -------hex-------
+VNNNCCCC DDDDDDD DDDDDDDDD - V = valid
+ - N = sequence counter
+ - C = top 4 bits of command
+
+Read transactions can be streamed by shifting out a multiple of 72 bits.
+
+Virtual DR register 2:
+
+Reads the amount of space in the write FIFO as an 8-bit number.
+
+
+Virtual DR register 3:
+
+WRITE FIFO
+
+72 bits:
+-binary- -------hex-------
+
+000XXXXX XXXXXXXX XXXXXXXX - noop
+
+0010XXXX XXXXXXXX CCCCCCCC - delay for C cycles @ 20 MHz
+
+0101XXXX AAAAAAAA CCCCCCCC - zero check
+ Returns last address read in [63:32]
+ Returns last datum 1's extended in [31:0] - FFFFFFFF on success
+
+0110XXXX XXXXXXXX TTTTTTTT - read back address register, token
+ Returns address register in [63:32]
+ Returns token in [31:0]
+
+0111XXXX AAAAAAAA CCCCCCCC - compute CRC32
+ Returns last address read in [63:32]
+ Returns Ethernet CRC32 of the region in [31:0]
+
+100SEEEE AAAAAAAA DDDDDDDD - write cycle (address, data)
+ address register set to A if S=1
+ E is byte enables; for a byte flash
+ E should be set to 0001
+
+1011CCCC DDDDDDDD DDDDDDDD - program bytes (C = byte count)
+
+1101XXXX AAAAAAAA CCCCCCCC - set address register to A
+ read C bytes (pad output to 64 bits)
+ if C=0 no read is done
+
+111XXXXX XXXXXXXX XXXXXXXX - noop
+
+For vestigial writes the data should be right-justified (LSB valid)
diff --git a/de1/fpga-flash-nor/quartus_wrap b/de1/fpga-flash-nor/quartus_wrap
new file mode 100755
index 0000000..e818413
--- /dev/null
+++ b/de1/fpga-flash-nor/quartus_wrap
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+AD=/software/apps/altera/quartus_ii_13.0sp1
+if [ $(uname -m ) == "x86_64" ]; then
+ LL=linux64
+else
+ LL=linux
+fi
+QUARTUS_ROOTDIR="${AD}/quartus"
+PATH="${AD}/quartus/bin:${AD}/quartus/sopc_builder/bin:${AD}/nios2eds/sdk2/bin:${AD}/nios2eds/bin:${AD}/nios2eds/bin/gnu/H-i686-pc-linux-gnu/bin:${PATH}"
+LD_LIBRARY_PATH="${AD}/quartus/${LL}:/software/apps/altera/libcompat/32:/software/apps/altera/libcompat/64:${LD_LIBRARY_PATH}"
+
+export LD_LIBRARY_PATH PATH QUARTUS_ROOTDIR
+
+"$@"
diff --git a/de1/fpga-flash-nor/vjtag_mega.qip b/de1/fpga-flash-nor/vjtag_mega.qip
new file mode 100644
index 0000000..9bff0d2
--- /dev/null
+++ b/de1/fpga-flash-nor/vjtag_mega.qip
@@ -0,0 +1,6 @@
+set_global_assignment -name IP_TOOL_NAME "Virtual JTAG"
+set_global_assignment -name IP_TOOL_VERSION "11.0"
+set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "vjtag_mega.v"]
+set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "vjtag_mega.bsf"]
+set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "vjtag_mega_inst.v"]
+set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "vjtag_mega_bb.v"]
diff --git a/de1/fpga-flash-nor/vjtag_mega.v b/de1/fpga-flash-nor/vjtag_mega.v
new file mode 100644
index 0000000..844c24d
--- /dev/null
+++ b/de1/fpga-flash-nor/vjtag_mega.v
@@ -0,0 +1,181 @@
+// megafunction wizard: %Virtual JTAG%
+// GENERATION: STANDARD
+// VERSION: WM1.0
+// MODULE: sld_virtual_jtag
+
+// ============================================================
+// File Name: vjtag_mega.v
+// Megafunction Name(s):
+// sld_virtual_jtag
+//
+// Simulation Library Files(s):
+// altera_mf
+// ============================================================
+// ************************************************************
+// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
+//
+// 11.0 Build 157 04/27/2011 SJ Web Edition
+// ************************************************************
+
+
+//Copyright (C) 1991-2011 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 vjtag_mega (
+ ir_out,
+ tdo,
+ ir_in,
+ tck,
+ tdi,
+ virtual_state_cdr,
+ virtual_state_cir,
+ virtual_state_e1dr,
+ virtual_state_e2dr,
+ virtual_state_pdr,
+ virtual_state_sdr,
+ virtual_state_udr,
+ virtual_state_uir);
+
+ input [3:0] ir_out;
+ input tdo;
+ output [3:0] ir_in;
+ output tck;
+ output tdi;
+ output virtual_state_cdr;
+ output virtual_state_cir;
+ output virtual_state_e1dr;
+ output virtual_state_e2dr;
+ output virtual_state_pdr;
+ output virtual_state_sdr;
+ output virtual_state_udr;
+ output virtual_state_uir;
+
+ wire sub_wire0;
+ wire sub_wire1;
+ wire [3:0] sub_wire2;
+ wire sub_wire3;
+ wire sub_wire4;
+ wire sub_wire5;
+ wire sub_wire6;
+ wire sub_wire7;
+ wire sub_wire8;
+ wire sub_wire9;
+ wire sub_wire10;
+ wire virtual_state_cir = sub_wire0;
+ wire virtual_state_pdr = sub_wire1;
+ wire [3:0] ir_in = sub_wire2[3:0];
+ wire tdi = sub_wire3;
+ wire virtual_state_udr = sub_wire4;
+ wire tck = sub_wire5;
+ wire virtual_state_e1dr = sub_wire6;
+ wire virtual_state_uir = sub_wire7;
+ wire virtual_state_cdr = sub_wire8;
+ wire virtual_state_e2dr = sub_wire9;
+ wire virtual_state_sdr = sub_wire10;
+
+ sld_virtual_jtag sld_virtual_jtag_component (
+ .ir_out (ir_out),
+ .tdo (tdo),
+ .virtual_state_cir (sub_wire0),
+ .virtual_state_pdr (sub_wire1),
+ .ir_in (sub_wire2),
+ .tdi (sub_wire3),
+ .virtual_state_udr (sub_wire4),
+ .tck (sub_wire5),
+ .virtual_state_e1dr (sub_wire6),
+ .virtual_state_uir (sub_wire7),
+ .virtual_state_cdr (sub_wire8),
+ .virtual_state_e2dr (sub_wire9),
+ .virtual_state_sdr (sub_wire10)
+ // synopsys translate_off
+ ,
+ .jtag_state_cdr (),
+ .jtag_state_cir (),
+ .jtag_state_e1dr (),
+ .jtag_state_e1ir (),
+ .jtag_state_e2dr (),
+ .jtag_state_e2ir (),
+ .jtag_state_pdr (),
+ .jtag_state_pir (),
+ .jtag_state_rti (),
+ .jtag_state_sdr (),
+ .jtag_state_sdrs (),
+ .jtag_state_sir (),
+ .jtag_state_sirs (),
+ .jtag_state_tlr (),
+ .jtag_state_udr (),
+ .jtag_state_uir (),
+ .tms ()
+ // synopsys translate_on
+ );
+ defparam
+ sld_virtual_jtag_component.sld_auto_instance_index = "YES",
+ sld_virtual_jtag_component.sld_instance_index = 0,
+ sld_virtual_jtag_component.sld_ir_width = 4,
+ sld_virtual_jtag_component.sld_sim_action = "",
+ sld_virtual_jtag_component.sld_sim_n_scan = 0,
+ sld_virtual_jtag_component.sld_sim_total_length = 0;
+
+
+endmodule
+
+// ============================================================
+// CNX file retrieval info
+// ============================================================
+// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone II"
+// Retrieval info: PRIVATE: show_jtag_state STRING "0"
+// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
+// Retrieval info: CONSTANT: SLD_AUTO_INSTANCE_INDEX STRING "YES"
+// Retrieval info: CONSTANT: SLD_INSTANCE_INDEX NUMERIC "0"
+// Retrieval info: CONSTANT: SLD_IR_WIDTH NUMERIC "4"
+// Retrieval info: CONSTANT: SLD_SIM_ACTION STRING ""
+// Retrieval info: CONSTANT: SLD_SIM_N_SCAN NUMERIC "0"
+// Retrieval info: CONSTANT: SLD_SIM_TOTAL_LENGTH NUMERIC "0"
+// Retrieval info: USED_PORT: ir_in 0 0 4 0 OUTPUT NODEFVAL "ir_in[3..0]"
+// Retrieval info: USED_PORT: ir_out 0 0 4 0 INPUT NODEFVAL "ir_out[3..0]"
+// Retrieval info: USED_PORT: tck 0 0 0 0 OUTPUT NODEFVAL "tck"
+// Retrieval info: USED_PORT: tdi 0 0 0 0 OUTPUT NODEFVAL "tdi"
+// Retrieval info: USED_PORT: tdo 0 0 0 0 INPUT NODEFVAL "tdo"
+// Retrieval info: USED_PORT: virtual_state_cdr 0 0 0 0 OUTPUT NODEFVAL "virtual_state_cdr"
+// Retrieval info: USED_PORT: virtual_state_cir 0 0 0 0 OUTPUT NODEFVAL "virtual_state_cir"
+// Retrieval info: USED_PORT: virtual_state_e1dr 0 0 0 0 OUTPUT NODEFVAL "virtual_state_e1dr"
+// Retrieval info: USED_PORT: virtual_state_e2dr 0 0 0 0 OUTPUT NODEFVAL "virtual_state_e2dr"
+// Retrieval info: USED_PORT: virtual_state_pdr 0 0 0 0 OUTPUT NODEFVAL "virtual_state_pdr"
+// Retrieval info: USED_PORT: virtual_state_sdr 0 0 0 0 OUTPUT NODEFVAL "virtual_state_sdr"
+// Retrieval info: USED_PORT: virtual_state_udr 0 0 0 0 OUTPUT NODEFVAL "virtual_state_udr"
+// Retrieval info: USED_PORT: virtual_state_uir 0 0 0 0 OUTPUT NODEFVAL "virtual_state_uir"
+// Retrieval info: CONNECT: @ir_out 0 0 4 0 ir_out 0 0 4 0
+// Retrieval info: CONNECT: @tdo 0 0 0 0 tdo 0 0 0 0
+// Retrieval info: CONNECT: ir_in 0 0 4 0 @ir_in 0 0 4 0
+// Retrieval info: CONNECT: tck 0 0 0 0 @tck 0 0 0 0
+// Retrieval info: CONNECT: tdi 0 0 0 0 @tdi 0 0 0 0
+// Retrieval info: CONNECT: virtual_state_cdr 0 0 0 0 @virtual_state_cdr 0 0 0 0
+// Retrieval info: CONNECT: virtual_state_cir 0 0 0 0 @virtual_state_cir 0 0 0 0
+// Retrieval info: CONNECT: virtual_state_e1dr 0 0 0 0 @virtual_state_e1dr 0 0 0 0
+// Retrieval info: CONNECT: virtual_state_e2dr 0 0 0 0 @virtual_state_e2dr 0 0 0 0
+// Retrieval info: CONNECT: virtual_state_pdr 0 0 0 0 @virtual_state_pdr 0 0 0 0
+// Retrieval info: CONNECT: virtual_state_sdr 0 0 0 0 @virtual_state_sdr 0 0 0 0
+// Retrieval info: CONNECT: virtual_state_udr 0 0 0 0 @virtual_state_udr 0 0 0 0
+// Retrieval info: CONNECT: virtual_state_uir 0 0 0 0 @virtual_state_uir 0 0 0 0
+// Retrieval info: GEN_FILE: TYPE_NORMAL vjtag_mega.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL vjtag_mega.inc FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL vjtag_mega.cmp FALSE
+// Retrieval info: GEN_FILE: TYPE_NORMAL vjtag_mega.bsf TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL vjtag_mega_inst.v TRUE
+// Retrieval info: GEN_FILE: TYPE_NORMAL vjtag_mega_bb.v TRUE
+// Retrieval info: LIB_FILE: altera_mf