diff options
author | root <root@ka-ata-killa.ourano.james.local> | 2021-02-24 23:45:58 +0000 |
---|---|---|
committer | root <root@ka-ata-killa.ourano.james.local> | 2021-02-24 23:45:58 +0000 |
commit | 1575d4f53805f177474b5bb96daebede9b2dfb73 (patch) | |
tree | 91f6819f7280088bb9344fae7dbef8c43a0a04c0 /de1/fpga-bbc-pq | |
download | base-1575d4f53805f177474b5bb96daebede9b2dfb73.tar.gz base-1575d4f53805f177474b5bb96daebede9b2dfb73.tar.bz2 base-1575d4f53805f177474b5bb96daebede9b2dfb73.zip |
Diffstat (limited to 'de1/fpga-bbc-pq')
19 files changed, 24676 insertions, 0 deletions
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; |