1
0
mirror of https://github.com/mist-devel/mist-board.git synced 2026-01-28 04:37:12 +00:00

Added QL source code

This commit is contained in:
Till Harbaum
2015-08-13 10:04:11 +02:00
parent dfb90b679b
commit c0bebae163
21 changed files with 8000 additions and 0 deletions

918
cores/ql/TG68K_ALU.vhd Normal file
View File

@@ -0,0 +1,918 @@
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- --
-- Copyright (c) 2009-2011 Tobias Gubener --
-- Subdesign fAMpIGA by TobiFlex --
-- --
-- This source file is free software: you can redistribute it and/or modify --
-- it under the terms of the GNU General Public License as published --
-- by the Free Software Foundation, either version 3 of the License, or --
-- (at your option) any later version. --
-- --
-- This source file is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --
-- GNU General Public License for more details. --
-- --
-- You should have received a copy of the GNU General Public License --
-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
-- --
------------------------------------------------------------------------------
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use IEEE.numeric_std.all;
use work.TG68K_Pack.all;
entity TG68K_ALU is
generic(
MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
DIV_Mode : integer := 0 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
);
port(clk : in std_logic;
Reset : in std_logic;
clkena_lw : in std_logic:='1';
execOPC : in bit;
exe_condition : in std_logic;
exec_tas : in std_logic;
long_start : in bit;
movem_presub : in bit;
set_stop : in bit;
Z_error : in bit;
rot_bits : in std_logic_vector(1 downto 0);
exec : in bit_vector(lastOpcBit downto 0);
OP1out : in std_logic_vector(31 downto 0);
OP2out : in std_logic_vector(31 downto 0);
reg_QA : in std_logic_vector(31 downto 0);
reg_QB : in std_logic_vector(31 downto 0);
opcode : in std_logic_vector(15 downto 0);
datatype : in std_logic_vector(1 downto 0);
exe_opcode : in std_logic_vector(15 downto 0);
exe_datatype : in std_logic_vector(1 downto 0);
sndOPC : in std_logic_vector(15 downto 0);
last_data_read : in std_logic_vector(15 downto 0);
data_read : in std_logic_vector(15 downto 0);
FlagsSR : in std_logic_vector(7 downto 0);
micro_state : in micro_states;
bf_ext_in : in std_logic_vector(7 downto 0);
bf_ext_out : out std_logic_vector(7 downto 0);
bf_shift : in std_logic_vector(5 downto 0);
bf_width : in std_logic_vector(5 downto 0);
bf_loffset : in std_logic_vector(4 downto 0);
set_V_Flag : buffer bit;
Flags : buffer std_logic_vector(7 downto 0);
c_out : buffer std_logic_vector(2 downto 0);
addsub_q : buffer std_logic_vector(31 downto 0);
ALUout : out std_logic_vector(31 downto 0)
);
end TG68K_ALU;
architecture logic of TG68K_ALU is
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
-- ALU and more
-----------------------------------------------------------------------------
-----------------------------------------------------------------------------
signal OP1in : std_logic_vector(31 downto 0);
signal addsub_a : std_logic_vector(31 downto 0);
signal addsub_b : std_logic_vector(31 downto 0);
signal notaddsub_b : std_logic_vector(33 downto 0);
signal add_result : std_logic_vector(33 downto 0);
signal addsub_ofl : std_logic_vector(2 downto 0);
signal opaddsub : bit;
signal c_in : std_logic_vector(3 downto 0);
signal flag_z : std_logic_vector(2 downto 0);
signal set_Flags : std_logic_vector(3 downto 0); --NZVC
signal CCRin : std_logic_vector(7 downto 0);
signal niba_l : std_logic_vector(5 downto 0);
signal niba_h : std_logic_vector(5 downto 0);
signal niba_lc : std_logic;
signal niba_hc : std_logic;
signal bcda_lc : std_logic;
signal bcda_hc : std_logic;
signal nibs_l : std_logic_vector(5 downto 0);
signal nibs_h : std_logic_vector(5 downto 0);
signal nibs_lc : std_logic;
signal nibs_hc : std_logic;
signal bcd_a : std_logic_vector(8 downto 0);
signal bcd_s : std_logic_vector(8 downto 0);
signal result_mulu : std_logic_vector(63 downto 0);
signal result_div : std_logic_vector(63 downto 0);
signal set_mV_Flag : std_logic;
signal V_Flag : bit;
signal rot_rot : std_logic;
signal rot_lsb : std_logic;
signal rot_msb : std_logic;
signal rot_X : std_logic;
signal rot_C : std_logic;
signal rot_out : std_logic_vector(31 downto 0);
signal asl_VFlag : std_logic;
signal bit_bits : std_logic_vector(1 downto 0);
signal bit_number : std_logic_vector(4 downto 0);
signal bits_out : std_logic_vector(31 downto 0);
signal one_bit_in : std_logic;
signal bchg : std_logic;
signal bset : std_logic;
signal mulu_sign : std_logic;
signal mulu_signext : std_logic_vector(16 downto 0);
signal muls_msb : std_logic;
signal mulu_reg : std_logic_vector(63 downto 0);
signal FAsign : std_logic;
signal faktorA : std_logic_vector(31 downto 0);
signal faktorB : std_logic_vector(31 downto 0);
signal div_reg : std_logic_vector(63 downto 0);
signal div_quot : std_logic_vector(63 downto 0);
signal div_ovl : std_logic;
signal div_neg : std_logic;
signal div_bit : std_logic;
signal div_sub : std_logic_vector(32 downto 0);
signal div_over : std_logic_vector(32 downto 0);
signal nozero : std_logic;
signal div_qsign : std_logic;
signal divisor : std_logic_vector(63 downto 0);
signal divs : std_logic;
signal signedOP : std_logic;
signal OP1_sign : std_logic;
signal OP2_sign : std_logic;
signal OP2outext : std_logic_vector(15 downto 0);
signal in_offset : std_logic_vector(5 downto 0);
-- signal in_width : std_logic_vector(5 downto 0);
signal datareg : std_logic_vector(31 downto 0);
signal insert : std_logic_vector(31 downto 0);
-- signal bf_result : std_logic_vector(31 downto 0);
-- signal bf_offset : std_logic_vector(5 downto 0);
-- signal bf_width : std_logic_vector(5 downto 0);
-- signal bf_firstbit : std_logic_vector(5 downto 0);
signal bf_datareg : std_logic_vector(31 downto 0);
-- signal bf_out : std_logic_vector(31 downto 0);
signal result : std_logic_vector(39 downto 0);
signal result_tmp : std_logic_vector(39 downto 0);
signal sign : std_logic_vector(31 downto 0);
signal bf_set1 : std_logic_vector(39 downto 0);
signal inmux0 : std_logic_vector(39 downto 0);
signal inmux1 : std_logic_vector(39 downto 0);
signal inmux2 : std_logic_vector(39 downto 0);
signal inmux3 : std_logic_vector(31 downto 0);
signal copymux0 : std_logic_vector(39 downto 0);
signal copymux1 : std_logic_vector(39 downto 0);
signal copymux2 : std_logic_vector(39 downto 0);
signal copymux3 : std_logic_vector(31 downto 0);
signal bf_set2 : std_logic_vector(31 downto 0);
-- signal bf_set3 : std_logic_vector(31 downto 0);
signal shift : std_logic_vector(39 downto 0);
signal copy : std_logic_vector(39 downto 0);
-- signal offset : std_logic_vector(5 downto 0);
-- signal width : std_logic_vector(5 downto 0);
signal bf_firstbit : std_logic_vector(5 downto 0);
signal mux : std_logic_vector(3 downto 0);
signal bitnr : std_logic_vector(4 downto 0);
signal mask : std_logic_vector(31 downto 0);
signal bf_bset : std_logic;
signal bf_NFlag : std_logic;
signal bf_bchg : std_logic;
signal bf_ins : std_logic;
signal bf_exts : std_logic;
signal bf_fffo : std_logic;
signal bf_d32 : std_logic;
signal bf_s32 : std_logic;
signal index : std_logic_vector(4 downto 0);
-- signal i : integer range 0 to 31;
-- signal i : integer range 0 to 31;
-- signal i : std_logic_vector(5 downto 0);
BEGIN
-----------------------------------------------------------------------------
-- set OP1in
-----------------------------------------------------------------------------
PROCESS (OP2out, reg_QB, opcode, OP1out, OP1in, exe_datatype, addsub_q, execOPC, exec,
bcd_a, bcd_s, result_mulu, result_div, exe_condition, bf_shift,
Flags, FlagsSR, bits_out, exec_tas, rot_out, exe_opcode, result, bf_fffo, bf_firstbit, bf_datareg)
BEGIN
ALUout <= OP1in;
ALUout(7) <= OP1in(7) OR exec_tas;
IF exec(opcBFwb)='1' THEN
ALUout <= result(31 downto 0);
IF bf_fffo='1' THEN
ALUout <= (OTHERS =>'0');
ALUout(5 downto 0) <= bf_firstbit + bf_shift;
END IF;
END IF;
OP1in <= addsub_q;
IF exec(opcABCD)='1' THEN
OP1in(7 downto 0) <= bcd_a(7 downto 0);
ELSIF exec(opcSBCD)='1' THEN
OP1in(7 downto 0) <= bcd_s(7 downto 0);
ELSIF exec(opcMULU)='1' AND MUL_Mode/=3 THEN
IF exec(write_lowlong)='1' AND (MUL_Mode=1 OR MUL_Mode=2) THEN
OP1in <= result_mulu(31 downto 0);
ELSE
OP1in <= result_mulu(63 downto 32);
END IF;
ELSIF exec(opcDIVU)='1' AND DIV_Mode/=3 THEN
IF exe_opcode(15)='1' OR DIV_Mode=0 THEN
-- IF exe_opcode(15)='1' THEN
OP1in <= result_div(47 downto 32)&result_div(15 downto 0);
ELSE --64bit
IF exec(write_reminder)='1' THEN
OP1in <= result_div(63 downto 32);
ELSE
OP1in <= result_div(31 downto 0);
END IF;
END IF;
ELSIF exec(opcOR)='1' THEN
OP1in <= OP2out OR OP1out;
ELSIF exec(opcAND)='1' THEN
OP1in <= OP2out AND OP1out;
ELSIF exec(opcScc)='1' THEN
OP1in(7 downto 0) <= (others=>exe_condition);
ELSIF exec(opcEOR)='1' THEN
OP1in <= OP2out XOR OP1out;
ELSIF exec(opcMOVE)='1' OR exec(exg)='1' THEN
-- OP1in <= OP2out(31 downto 8)&(OP2out(7)OR exec_tas)&OP2out(6 downto 0);
OP1in <= OP2out;
ELSIF exec(opcROT)='1' THEN
OP1in <= rot_out;
ELSIF exec(opcSWAP)='1' THEN
OP1in <= OP1out(15 downto 0)& OP1out(31 downto 16);
ELSIF exec(opcBITS)='1' THEN
OP1in <= bits_out;
ELSIF exec(opcBF)='1' THEN
OP1in <= bf_datareg;
ELSIF exec(opcMOVESR)='1' THEN
OP1in(7 downto 0) <= Flags;
IF exe_datatype="00" THEN
OP1in(15 downto 8) <= "00000000";
ELSE
OP1in(15 downto 8) <= FlagsSR;
END IF;
END IF;
END PROCESS;
-----------------------------------------------------------------------------
-- addsub
-----------------------------------------------------------------------------
PROCESS (OP1out, OP2out, execOPC, datatype, Flags, long_start, movem_presub, exe_datatype, exec, addsub_a, addsub_b, opaddsub,
notaddsub_b, add_result, c_in, sndOPC)
BEGIN
addsub_a <= OP1out;
IF exec(get_bfoffset)='1' THEN
IF sndOPC(11)='1' THEN
addsub_a <= OP1out(31)&OP1out(31)&OP1out(31)&OP1out(31 downto 3);
ELSE
addsub_a <= "000000000000000000000000000000"&sndOPC(10 downto 9);
END IF;
END IF;
IF exec(subidx)='1' THEN
opaddsub <= '1';
ELSE
opaddsub <= '0';
END IF;
c_in(0) <='0';
addsub_b <= OP2out;
IF execOPC='0' AND exec(OP2out_one)='0' AND exec(get_bfoffset)='0'THEN
IF long_start='0' AND datatype="00" AND exec(use_SP)='0' THEN
addsub_b <= "00000000000000000000000000000001";
ELSIF long_start='0' AND exe_datatype="10" AND (exec(presub) OR exec(postadd) OR movem_presub)='1' THEN
IF exec(movem_action)='1' THEN
addsub_b <= "00000000000000000000000000000110";
ELSE
addsub_b <= "00000000000000000000000000000100";
END IF;
ELSE
addsub_b <= "00000000000000000000000000000010";
END IF;
ELSE
IF (exec(use_XZFlag)='1' AND Flags(4)='1') OR exec(opcCHK)='1' THEN
c_in(0) <= '1';
END IF;
opaddsub <= exec(addsub);
END IF;
IF opaddsub='0' OR long_start='1' THEN --ADD
notaddsub_b <= '0'&addsub_b&c_in(0);
ELSE --SUB
notaddsub_b <= NOT ('0'&addsub_b&c_in(0));
END IF;
add_result <= (('0'&addsub_a&notaddsub_b(0))+notaddsub_b);
c_in(1) <= add_result(9) XOR addsub_a(8) XOR addsub_b(8);
c_in(2) <= add_result(17) XOR addsub_a(16) XOR addsub_b(16);
c_in(3) <= add_result(33);
addsub_q <= add_result(32 downto 1);
addsub_ofl(0) <= (c_in(1) XOR add_result(8) XOR addsub_a(7) XOR addsub_b(7)); --V Byte
addsub_ofl(1) <= (c_in(2) XOR add_result(16) XOR addsub_a(15) XOR addsub_b(15)); --V Word
addsub_ofl(2) <= (c_in(3) XOR add_result(32) XOR addsub_a(31) XOR addsub_b(31)); --V Long
c_out <= c_in(3 downto 1);
END PROCESS;
------------------------------------------------------------------------------
--ALU
------------------------------------------------------------------------------
PROCESS (OP1out, OP2out, niba_hc, niba_h, niba_l, niba_lc, nibs_hc, nibs_h, nibs_l, nibs_lc, Flags)
BEGIN
--BCD_ARITH-------------------------------------------------------------------
--ADC
bcd_a <= niba_hc&(niba_h(4 downto 1)+('0',niba_hc,niba_hc,'0'))&(niba_l(4 downto 1)+('0',niba_lc,niba_lc,'0'));
niba_l <= ('0'&OP1out(3 downto 0)&'1') + ('0'&OP2out(3 downto 0)&Flags(4));
niba_lc <= niba_l(5) OR (niba_l(4) AND niba_l(3)) OR (niba_l(4) AND niba_l(2));
niba_h <= ('0'&OP1out(7 downto 4)&'1') + ('0'&OP2out(7 downto 4)&niba_lc);
niba_hc <= niba_h(5) OR (niba_h(4) AND niba_h(3)) OR (niba_h(4) AND niba_h(2));
--SBC
bcd_s <= nibs_hc&(nibs_h(4 downto 1)-('0',nibs_hc,nibs_hc,'0'))&(nibs_l(4 downto 1)-('0',nibs_lc,nibs_lc,'0'));
nibs_l <= ('0'&OP1out(3 downto 0)&'0') - ('0'&OP2out(3 downto 0)&Flags(4));
nibs_lc <= nibs_l(5);
nibs_h <= ('0'&OP1out(7 downto 4)&'0') - ('0'&OP2out(7 downto 4)&nibs_lc);
nibs_hc <= nibs_h(5);
END PROCESS;
-----------------------------------------------------------------------------
-- Bits
-----------------------------------------------------------------------------
PROCESS (clk, exe_opcode, OP1out, OP2out, one_bit_in, bchg, bset, bit_Number, sndOPC)
BEGIN
IF rising_edge(clk) THEN
IF clkena_lw = '1' THEN
bchg <= '0';
bset <= '0';
CASE opcode(7 downto 6) IS
WHEN "01" => --bchg
bchg <= '1';
WHEN "11" => --bset
bset <= '1';
WHEN OTHERS => NULL;
END CASE;
END IF;
END IF;
IF exe_opcode(8)='0' THEN
IF exe_opcode(5 downto 4)="00" THEN
bit_number <= sndOPC(4 downto 0);
ELSE
bit_number <= "00"&sndOPC(2 downto 0);
END IF;
ELSE
IF exe_opcode(5 downto 4)="00" THEN
bit_number <= reg_QB(4 downto 0);
ELSE
bit_number <= "00"&reg_QB(2 downto 0);
END IF;
END IF;
one_bit_in <= OP1out(to_integer(unsigned(bit_Number)));
bits_out <= OP1out;
bits_out(to_integer(unsigned(bit_Number))) <= (bchg AND NOT one_bit_in) OR bset ;
END PROCESS;
-----------------------------------------------------------------------------
-- Bit Field
-----------------------------------------------------------------------------
PROCESS (clk, mux, mask, bitnr, bf_ins, bf_bchg, bf_bset, bf_exts, bf_shift, inmux0, inmux1, inmux2, inmux3, bf_set2, OP1out, OP2out, result_tmp, bf_ext_in,
shift, datareg, bf_NFlag, result, reg_QB, sign, bf_d32, bf_s32, copy, bf_loffset, copymux0, copymux1, copymux2, copymux3, bf_width)
BEGIN
IF rising_edge(clk) THEN
IF clkena_lw = '1' THEN
bf_bset <= '0';
bf_bchg <= '0';
bf_ins <= '0';
bf_exts <= '0';
bf_fffo <= '0';
bf_d32 <= '0';
bf_s32 <= '0';
CASE opcode(10 downto 8) IS
WHEN "010" => bf_bchg <= '1'; --BFCHG
WHEN "011" => bf_exts <= '1'; --BFEXTS
-- WHEN "100" => insert <= (OTHERS =>'0'); --BFCLR
WHEN "101" => bf_fffo <= '1'; --BFFFO
WHEN "110" => bf_bset <= '1'; --BFSET
WHEN "111" => bf_ins <= '1'; --BFINS
bf_s32 <= '1';
WHEN OTHERS => NULL;
END CASE;
IF opcode(4 downto 3)="00" THEN
bf_d32 <= '1';
END IF;
bf_ext_out <= result(39 downto 32);
END IF;
END IF;
shift <= bf_ext_in&OP2out;
IF bf_s32='1' THEN
shift(39 downto 32) <= OP2out(7 downto 0);
END IF;
IF bf_shift(0)='1' THEN
inmux0 <= shift(0)&shift(39 downto 1);
ELSE
inmux0 <= shift;
END IF;
IF bf_shift(1)='1' THEN
inmux1 <= inmux0(1 downto 0)&inmux0(39 downto 2);
ELSE
inmux1 <= inmux0;
END IF;
IF bf_shift(2)='1' THEN
inmux2 <= inmux1(3 downto 0)&inmux1(39 downto 4);
ELSE
inmux2 <= inmux1;
END IF;
IF bf_shift(3)='1' THEN
inmux3 <= inmux2(7 downto 0)&inmux2(31 downto 8);
ELSE
inmux3 <= inmux2(31 downto 0);
END IF;
IF bf_shift(4)='1' THEN
bf_set2(31 downto 0) <= inmux3(15 downto 0)&inmux3(31 downto 16);
ELSE
bf_set2(31 downto 0) <= inmux3;
END IF;
IF bf_loffset(4)='1' THEN
copymux3 <= sign(15 downto 0)&sign(31 downto 16);
ELSE
copymux3 <= sign;
END IF;
IF bf_loffset(3)='1' THEN
copymux2(31 downto 0) <= copymux3(23 downto 0)&copymux3(31 downto 24);
ELSE
copymux2(31 downto 0) <= copymux3;
END IF;
IF bf_d32='1' THEN
copymux2(39 downto 32) <= copymux3(7 downto 0);
ELSE
copymux2(39 downto 32) <= "11111111";
END IF;
IF bf_loffset(2)='1' THEN
copymux1 <= copymux2(35 downto 0)&copymux2(39 downto 36);
ELSE
copymux1 <= copymux2;
END IF;
IF bf_loffset(1)='1' THEN
copymux0 <= copymux1(37 downto 0)&copymux1(39 downto 38);
ELSE
copymux0 <= copymux1;
END IF;
IF bf_loffset(0)='1' THEN
copy <= copymux0(38 downto 0)&copymux0(39);
ELSE
copy <= copymux0;
END IF;
result_tmp <= bf_ext_in&OP1out;
IF bf_ins='1' THEN
datareg <= reg_QB;
ELSE
datareg <= bf_set2;
END IF;
IF bf_ins='1' THEN
result(31 downto 0) <= bf_set2;
result(39 downto 32) <= bf_set2(7 downto 0);
ELSIF bf_bchg='1' THEN
result(31 downto 0) <= NOT OP1out;
result(39 downto 32) <= NOT bf_ext_in;
ELSE
result <= (OTHERS => '0');
END IF;
IF bf_bset='1' THEN
result <= (OTHERS => '1');
END IF;
sign <= (OTHERS => '0');
bf_NFlag <= datareg(to_integer(unsigned(bf_width)));
FOR i in 0 to 31 LOOP
IF i>bf_width(4 downto 0) THEN
datareg(i) <= '0';
sign(i) <= '1';
END IF;
END LOOP;
FOR i in 0 to 39 LOOP
IF copy(i)='1' THEN
result(i) <= result_tmp(i);
END IF;
END LOOP;
IF bf_exts='1' AND bf_NFlag='1' THEN
bf_datareg <= datareg OR sign;
ELSE
bf_datareg <= datareg;
END IF;
-- bf_datareg <= copy(31 downto 0);
-- result(31 downto 0)<=datareg;
--BFFFO
mask <= datareg;
bf_firstbit <= '0'&bitnr;
bitnr <= "11111";
IF mask(31 downto 28)="0000" THEN
IF mask(27 downto 24)="0000" THEN
IF mask(23 downto 20)="0000" THEN
IF mask(19 downto 16)="0000" THEN
bitnr(4) <= '0';
IF mask(15 downto 12)="0000" THEN
IF mask(11 downto 8)="0000" THEN
bitnr(3) <= '0';
IF mask(7 downto 4)="0000" THEN
bitnr(2) <= '0';
mux <= mask(3 downto 0);
ELSE
mux <= mask(7 downto 4);
END IF;
ELSE
mux <= mask(11 downto 8);
bitnr(2) <= '0';
END IF;
ELSE
mux <= mask(15 downto 12);
END IF;
ELSE
mux <= mask(19 downto 16);
bitnr(3) <= '0';
bitnr(2) <= '0';
END IF;
ELSE
mux <= mask(23 downto 20);
bitnr(3) <= '0';
END IF;
ELSE
mux <= mask(27 downto 24);
bitnr(2) <= '0';
END IF;
ELSE
mux <= mask(31 downto 28);
END IF;
IF mux(3 downto 2)="00" THEN
bitnr(1) <= '0';
IF mux(1)='0' THEN
bitnr(0) <= '0';
END IF;
ELSE
IF mux(3)='0' THEN
bitnr(0) <= '0';
END IF;
END IF;
END PROCESS;
-----------------------------------------------------------------------------
-- Rotation
-----------------------------------------------------------------------------
PROCESS (exe_opcode, OP1out, Flags, rot_bits, rot_msb, rot_lsb, rot_rot, exec)
BEGIN
CASE exe_opcode(7 downto 6) IS
WHEN "00" => --Byte
rot_rot <= OP1out(7);
WHEN "01"|"11" => --Word
rot_rot <= OP1out(15);
WHEN "10" => --Long
rot_rot <= OP1out(31);
WHEN OTHERS => NULL;
END CASE;
CASE rot_bits IS
WHEN "00" => --ASL, ASR
rot_lsb <= '0';
rot_msb <= rot_rot;
WHEN "01" => --LSL, LSR
rot_lsb <= '0';
rot_msb <= '0';
WHEN "10" => --ROXL, ROXR
rot_lsb <= Flags(4);
rot_msb <= Flags(4);
WHEN "11" => --ROL, ROR
rot_lsb <= rot_rot;
rot_msb <= OP1out(0);
WHEN OTHERS => NULL;
END CASE;
IF exec(rot_nop)='1' THEN
rot_out <= OP1out;
rot_X <= Flags(4);
IF rot_bits="10" THEN --ROXL, ROXR
rot_C <= Flags(4);
ELSE
rot_C <= '0';
END IF;
ELSE
IF exe_opcode(8)='1' THEN --left
rot_out <= OP1out(30 downto 0)&rot_lsb;
rot_X <= rot_rot;
rot_C <= rot_rot;
ELSE --right
rot_X <= OP1out(0);
rot_C <= OP1out(0);
rot_out <= rot_msb&OP1out(31 downto 1);
CASE exe_opcode(7 downto 6) IS
WHEN "00" => --Byte
rot_out(7) <= rot_msb;
WHEN "01"|"11" => --Word
rot_out(15) <= rot_msb;
WHEN OTHERS => NULL;
END CASE;
END IF;
END IF;
END PROCESS;
------------------------------------------------------------------------------
--CCR op
------------------------------------------------------------------------------
PROCESS (clk, Reset, exe_opcode, exe_datatype, Flags, last_data_read, OP2out, flag_z, OP1IN, c_out, addsub_ofl,
bcd_s, bcd_a, exec)
BEGIN
IF exec(andiSR)='1' THEN
CCRin <= Flags AND last_data_read(7 downto 0);
ELSIF exec(eoriSR)='1' THEN
CCRin <= Flags XOR last_data_read(7 downto 0);
ELSIF exec(oriSR)='1' THEN
CCRin <= Flags OR last_data_read(7 downto 0);
ELSE
CCRin <= OP2out(7 downto 0);
END IF;
------------------------------------------------------------------------------
--Flags
------------------------------------------------------------------------------
flag_z <= "000";
IF exec(use_XZFlag)='1' AND flags(2)='0' THEN
flag_z <= "000";
ELSIF OP1in(7 downto 0)="00000000" THEN
flag_z(0) <= '1';
IF OP1in(15 downto 8)="00000000" THEN
flag_z(1) <= '1';
IF OP1in(31 downto 16)="0000000000000000" THEN
flag_z(2) <= '1';
END IF;
END IF;
END IF;
-- --Flags NZVC
IF exe_datatype="00" THEN --Byte
set_flags <= OP1IN(7)&flag_z(0)&addsub_ofl(0)&c_out(0);
IF exec(opcABCD)='1' THEN
set_flags(0) <= bcd_a(8);
ELSIF exec(opcSBCD)='1' THEN
set_flags(0) <= bcd_s(8);
END IF;
ELSIF exe_datatype="10" OR exec(opcCPMAW)='1' THEN --Long
set_flags <= OP1IN(31)&flag_z(2)&addsub_ofl(2)&c_out(2);
ELSE --Word
set_flags <= OP1IN(15)&flag_z(1)&addsub_ofl(1)&c_out(1);
END IF;
IF rising_edge(clk) THEN
IF clkena_lw = '1' THEN
IF exec(directSR)='1' OR set_stop='1' THEN
Flags(7 downto 0) <= data_read(7 downto 0);
END IF;
IF exec(directCCR)='1' THEN
Flags(7 downto 0) <= data_read(7 downto 0);
END IF;
IF exec(opcROT)='1' THEN
asl_VFlag <= ((set_flags(3) XOR rot_rot) OR asl_VFlag);
ELSE
asl_VFlag <= '0';
END IF;
IF exec(to_CCR)='1' THEN
Flags(7 downto 0) <= CCRin(7 downto 0); --CCR
ELSIF Z_error='1' THEN
IF exe_opcode(8)='0' THEN
Flags(3 downto 0) <= reg_QA(31)&"000";
ELSE
Flags(3 downto 0) <= "0100";
END IF;
ELSIF exec(no_Flags)='0' THEN
IF exec(opcADD)='1' THEN
Flags(4) <= set_flags(0);
ELSIF exec(opcROT)='1' AND rot_bits/="11" AND exec(rot_nop)='0' THEN
Flags(4) <= rot_X;
END IF;
IF (exec(opcADD) OR exec(opcCMP))='1' THEN
Flags(3 downto 0) <= set_flags;
ELSIF exec(opcDIVU)='1' AND DIV_Mode/=3 THEN
IF V_Flag='1' THEN
Flags(3 downto 0) <= "1010";
ELSE
Flags(3 downto 0) <= OP1IN(15)&flag_z(1)&"00";
END IF;
ELSIF exec(write_reminder)='1' AND MUL_Mode/=3 THEN -- z-flag MULU.l
Flags(3) <= set_flags(3);
Flags(2) <= set_flags(2) AND Flags(2);
Flags(1) <= '0';
Flags(0) <= '0';
ELSIF exec(write_lowlong)='1' AND (MUL_Mode=1 OR MUL_Mode=2) THEN -- flag MULU.l
Flags(3) <= set_flags(3);
Flags(2) <= set_flags(2);
Flags(1) <= set_mV_Flag; --V
Flags(0) <= '0';
ELSIF exec(opcOR)='1' OR exec(opcAND)='1' OR exec(opcEOR)='1' OR exec(opcMOVE)='1' OR exec(opcMOVEQ)='1' OR exec(opcSWAP)='1' OR exec(opcBF)='1' OR (exec(opcMULU)='1' AND MUL_Mode/=3) THEN
Flags(1 downto 0) <= "00";
Flags(3 downto 2) <= set_flags(3 downto 2);
IF exec(opcBF)='1' THEN
Flags(3) <= bf_NFlag;
END IF;
ELSIF exec(opcROT)='1' THEN
Flags(3 downto 2) <= set_flags(3 downto 2);
Flags(0) <= rot_C;
IF rot_bits="00" AND ((set_flags(3) XOR rot_rot) OR asl_VFlag)='1' THEN --ASL/ASR
Flags(1) <= '1';
ELSE
Flags(1) <= '0';
END IF;
ELSIF exec(opcBITS)='1' THEN
Flags(2) <= NOT one_bit_in;
ELSIF exec(opcCHK)='1' THEN
IF exe_datatype="01" THEN --Word
Flags(3) <= OP1out(15);
ELSE
Flags(3) <= OP1out(31);
END IF;
IF OP1out(15 downto 0)=X"0000" AND (exe_datatype="01" OR OP1out(31 downto 16)=X"0000") THEN
Flags(2) <='1';
ELSE
Flags(2) <='0';
END IF;
Flags(1 downto 0) <= "00";
END IF;
END IF;
END IF;
Flags(7 downto 5) <= "000";
END IF;
END PROCESS;
-------------------------------------------------------------------------------
---- MULU/MULS
-------------------------------------------------------------------------------
PROCESS (exe_opcode, OP2out, muls_msb, mulu_reg, FAsign, mulu_sign, reg_QA, faktorB, result_mulu, signedOP)
BEGIN
IF (signedOP='1' AND faktorB(31)='1') OR FAsign='1' THEN
muls_msb <= mulu_reg(63);
ELSE
muls_msb <= '0';
END IF;
IF signedOP='1' AND faktorB(31)='1' THEN
mulu_sign <= '1';
ELSE
mulu_sign <= '0';
END IF;
IF MUL_Mode=0 THEN -- 16 Bit
result_mulu(63 downto 32) <= muls_msb&mulu_reg(63 downto 33);
result_mulu(15 downto 0) <= 'X'&mulu_reg(15 downto 1);
IF mulu_reg(0)='1' THEN
IF FAsign='1' THEN
result_mulu(63 downto 47) <= (muls_msb&mulu_reg(63 downto 48)-(mulu_sign&faktorB(31 downto 16)));
ELSE
result_mulu(63 downto 47) <= (muls_msb&mulu_reg(63 downto 48)+(mulu_sign&faktorB(31 downto 16)));
END IF;
END IF;
ELSE -- 32 Bit
result_mulu <= muls_msb&mulu_reg(63 downto 1);
IF mulu_reg(0)='1' THEN
IF FAsign='1' THEN
result_mulu(63 downto 31) <= (muls_msb&mulu_reg(63 downto 32)-(mulu_sign&faktorB));
ELSE
result_mulu(63 downto 31) <= (muls_msb&mulu_reg(63 downto 32)+(mulu_sign&faktorB));
END IF;
END IF;
END IF;
IF exe_opcode(15)='1' OR MUL_Mode=0 THEN
faktorB(31 downto 16) <= OP2out(15 downto 0);
faktorB(15 downto 0) <= (OTHERS=>'0');
ELSE
faktorB <= OP2out;
END IF;
IF (result_mulu(63 downto 32)=X"00000000" AND (signedOP='0' OR result_mulu(31)='0')) OR
(result_mulu(63 downto 32)=X"FFFFFFFF" AND signedOP='1' AND result_mulu(31)='1') THEN
set_mV_Flag <= '0';
ELSE
set_mV_Flag <= '1';
END IF;
END PROCESS;
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF clkena_lw='1' THEN
IF micro_state=mul1 THEN
mulu_reg(63 downto 32) <= (OTHERS=>'0');
IF divs='1' AND ((exe_opcode(15)='1' AND reg_QA(15)='1') OR (exe_opcode(15)='0' AND reg_QA(31)='1')) THEN --MULS Neg faktor
FAsign <= '1';
mulu_reg(31 downto 0) <= 0-reg_QA;
ELSE
FAsign <= '0';
mulu_reg(31 downto 0) <= reg_QA;
END IF;
ELSIF exec(opcMULU)='0' THEN
mulu_reg <= result_mulu;
END IF;
END IF;
END IF;
END PROCESS;
-------------------------------------------------------------------------------
---- DIVU/DIVS
-------------------------------------------------------------------------------
PROCESS (execOPC, OP1out, OP2out, div_reg, div_neg, div_bit, div_sub, div_quot, OP1_sign, div_over, result_div, reg_QA, opcode, sndOPC, divs, exe_opcode, reg_QB,
signedOP, nozero, div_qsign, OP2outext)
BEGIN
divs <= (opcode(15) AND opcode(8)) OR (NOT opcode(15) AND sndOPC(11));
divisor(15 downto 0) <= (OTHERS=> '0');
divisor(63 downto 32) <= (OTHERS=> divs AND reg_QA(31));
IF exe_opcode(15)='1' OR DIV_Mode=0 THEN
divisor(47 downto 16) <= reg_QA;
ELSE
divisor(31 downto 0) <= reg_QA;
IF exe_opcode(14)='1' AND sndOPC(10)='1' THEN
divisor(63 downto 32) <= reg_QB;
END IF;
END IF;
IF signedOP='1' OR opcode(15)='0' THEN
OP2outext <= OP2out(31 downto 16);
ELSE
OP2outext <= (OTHERS=> '0');
END IF;
IF signedOP='1' AND OP2out(31) ='1' THEN
div_sub <= (div_reg(63 downto 31))+('1'&OP2out(31 downto 0));
ELSE
div_sub <= (div_reg(63 downto 31))-('0'&OP2outext(15 downto 0)&OP2out(15 downto 0));
END IF;
IF DIV_Mode=0 THEN
div_bit <= div_sub(16);
ELSE
div_bit <= div_sub(32);
END IF;
IF div_bit='1' THEN
div_quot(63 downto 32) <= div_reg(62 downto 31);
ELSE
div_quot(63 downto 32) <= div_sub(31 downto 0);
END IF;
div_quot(31 downto 0) <= div_reg(30 downto 0)&NOT div_bit;
IF ((nozero='1' AND signedOP='1' AND (OP2out(31) XOR OP1_sign XOR div_neg XOR div_qsign)='1' ) --Overflow DIVS
OR (signedOP='0' AND div_over(32)='0')) AND DIV_Mode/=3 THEN --Overflow DIVU
set_V_Flag <= '1';
ELSE
set_V_Flag <= '0';
END IF;
END PROCESS;
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF clkena_lw='1' THEN
V_Flag <= set_V_Flag;
signedOP <= divs;
IF micro_state=div1 THEN
nozero <= '0';
IF divs='1' AND divisor(63)='1' THEN -- Neg divisor
OP1_sign <= '1';
div_reg <= 0-divisor;
ELSE
OP1_sign <= '0';
div_reg <= divisor;
END IF;
ELSE
div_reg <= div_quot;
nozero <= NOT div_bit OR nozero;
END IF;
IF micro_state=div2 THEN
div_qsign <= NOT div_bit;
div_neg <= signedOP AND (OP2out(31) XOR OP1_sign);
IF DIV_Mode=0 THEN
div_over(32 downto 16) <= ('0'&div_reg(47 downto 32))-('0'&OP2out(15 downto 0));
ELSE
div_over <= ('0'&div_reg(63 downto 32))-('0'&OP2out);
END IF;
END IF;
IF exec(write_reminder)='0' THEN
-- IF exec_DIVU='0' THEN
IF div_neg='1' THEN
result_div(31 downto 0) <= 0-div_quot(31 downto 0);
ELSE
result_div(31 downto 0) <= div_quot(31 downto 0);
END IF;
IF OP1_sign='1' THEN
result_div(63 downto 32) <= 0-div_quot(63 downto 32);
ELSE
result_div(63 downto 32) <= div_quot(63 downto 32);
END IF;
END IF;
END IF;
END IF;
END PROCESS;
END;

165
cores/ql/TG68K_Pack.vhd Normal file
View File

@@ -0,0 +1,165 @@
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- --
-- Copyright (c) 2009-2013 Tobias Gubener --
-- Subdesign fAMpIGA by TobiFlex --
-- --
-- This source file is free software: you can redistribute it and/or modify --
-- it under the terms of the GNU General Public License as published --
-- by the Free Software Foundation, either version 3 of the License, or --
-- (at your option) any later version. --
-- --
-- This source file is distributed in the hope that it will be useful, --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --
-- GNU General Public License for more details. --
-- --
-- You should have received a copy of the GNU General Public License --
-- along with this program. If not, see <http://www.gnu.org/licenses/>. --
-- --
------------------------------------------------------------------------------
------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
package TG68K_Pack is
type micro_states is (idle, nop, ld_nn, st_nn, ld_dAn1, ld_AnXn1, ld_AnXn2, st_dAn1, ld_AnXnbd1, ld_AnXnbd2, ld_AnXnbd3,
ld_229_1, ld_229_2, ld_229_3, ld_229_4, st_229_1, st_229_2, st_229_3, st_229_4,
st_AnXn1, st_AnXn2, bra1, bsr1, bsr2, nopnop, dbcc1, movem1, movem2, movem3,
andi, op_AxAy, cmpm, link1, link2, unlink1, unlink2, int1, int2, int3, int4, rte1, rte2, rte3, trap0, trap1, trap2, trap3,
trap4, trap5, trap6, movec1, movep1, movep2, movep3, movep4, movep5, rota1, bf1,
mul1, mul2, mul_end1, mul_end2, div1, div2, div3, div4, div_end1, div_end2);
constant opcMOVE : integer := 0; --
constant opcMOVEQ : integer := 1; --
constant opcMOVESR : integer := 2; --
constant opcADD : integer := 3; --
constant opcADDQ : integer := 4; --
constant opcOR : integer := 5; --
constant opcAND : integer := 6; --
constant opcEOR : integer := 7; --
constant opcCMP : integer := 8; --
constant opcROT : integer := 9; --
constant opcCPMAW : integer := 10;
constant opcEXT : integer := 11; --
constant opcABCD : integer := 12; --
constant opcSBCD : integer := 13; --
constant opcBITS : integer := 14; --
constant opcSWAP : integer := 15; --
constant opcScc : integer := 16; --
constant andiSR : integer := 17; --
constant eoriSR : integer := 18; --
constant oriSR : integer := 19; --
constant opcMULU : integer := 20; --
constant opcDIVU : integer := 21; --
constant dispouter : integer := 22; --
constant rot_nop : integer := 23; --
constant ld_rot_cnt : integer := 24; --
constant writePC_add : integer := 25; --
constant ea_data_OP1 : integer := 26; --
constant ea_data_OP2 : integer := 27; --
constant use_XZFlag : integer := 28; --
constant get_bfoffset : integer := 29; --
constant save_memaddr : integer := 30; --
constant opcCHK : integer := 31; --
constant movec_rd : integer := 32; --
constant movec_wr : integer := 33; --
constant Regwrena : integer := 34; --
constant update_FC : integer := 35; --
constant linksp : integer := 36; --
constant movepl : integer := 37; --
constant update_ld : integer := 38; --
constant OP1addr : integer := 39; --
constant write_reg : integer := 40; --
constant changeMode : integer := 41; --
constant ea_build : integer := 42; --
constant trap_chk : integer := 43; --
constant store_ea_data : integer := 44; --
constant addrlong : integer := 45; --
constant postadd : integer := 46; --
constant presub : integer := 47; --
constant subidx : integer := 48; --
constant no_Flags : integer := 49; --
constant use_SP : integer := 50; --
constant to_CCR : integer := 51; --
constant to_SR : integer := 52; --
constant OP2out_one : integer := 53; --
constant OP1out_zero : integer := 54; --
constant mem_addsub : integer := 55; --
constant addsub : integer := 56; --
constant directPC : integer := 57; --
constant direct_delta : integer := 58; --
constant directSR : integer := 59; --
constant directCCR : integer := 60; --
constant exg : integer := 61; --
constant get_ea_now : integer := 62; --
constant ea_to_pc : integer := 63; --
constant hold_dwr : integer := 64; --
constant to_USP : integer := 65; --
constant from_USP : integer := 66; --
constant write_lowlong : integer := 67; --
constant write_reminder : integer := 68; --
constant movem_action : integer := 69; --
constant briefext : integer := 70; --
constant get_2ndOPC : integer := 71; --
constant mem_byte : integer := 72; --
constant longaktion : integer := 73; --
constant opcRESET : integer := 74; --
constant opcBF : integer := 75; --
constant opcBFwb : integer := 76; --
constant s2nd_hbits : integer := 77; --
-- constant : integer := 75; --
-- constant : integer := 76; --
-- constant : integer := 7; --
-- constant : integer := 7; --
-- constant : integer := 7; --
constant lastOpcBit : integer := 77;
component TG68K_ALU
generic(
MUL_Mode : integer := 0; --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no MUL,
DIV_Mode : integer := 0 --0=>16Bit, 1=>32Bit, 2=>switchable with CPU(1), 3=>no DIV,
);
port(
clk : in std_logic;
Reset : in std_logic;
clkena_lw : in std_logic:='1';
execOPC : in bit;
exe_condition : in std_logic;
exec_tas : in std_logic;
long_start : in bit;
movem_presub : in bit;
set_stop : in bit;
Z_error : in bit;
rot_bits : in std_logic_vector(1 downto 0);
exec : in bit_vector(lastOpcBit downto 0);
OP1out : in std_logic_vector(31 downto 0);
OP2out : in std_logic_vector(31 downto 0);
reg_QA : in std_logic_vector(31 downto 0);
reg_QB : in std_logic_vector(31 downto 0);
opcode : in std_logic_vector(15 downto 0);
datatype : in std_logic_vector(1 downto 0);
exe_opcode : in std_logic_vector(15 downto 0);
exe_datatype : in std_logic_vector(1 downto 0);
sndOPC : in std_logic_vector(15 downto 0);
last_data_read : in std_logic_vector(15 downto 0);
data_read : in std_logic_vector(15 downto 0);
FlagsSR : in std_logic_vector(7 downto 0);
micro_state : in micro_states;
bf_ext_in : in std_logic_vector(7 downto 0);
bf_ext_out : out std_logic_vector(7 downto 0);
bf_shift : in std_logic_vector(5 downto 0);
bf_width : in std_logic_vector(5 downto 0);
bf_loffset : in std_logic_vector(4 downto 0);
set_V_Flag : buffer bit;
Flags : buffer std_logic_vector(7 downto 0);
c_out : buffer std_logic_vector(2 downto 0);
addsub_q : buffer std_logic_vector(31 downto 0);
ALUout : out std_logic_vector(31 downto 0)
);
end component;
end;

File diff suppressed because it is too large Load Diff

120
cores/ql/data_io.v Normal file
View File

@@ -0,0 +1,120 @@
//
// data_io.v
//
// io controller writable ram for the MiST board
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module data_io (
// io controller spi interface
input sck,
input ss,
input sdi,
output downloading, // signal indicating an active download
output reg [4:0] index, // menu index used to upload the file
// external ram interface
input clk,
output reg wr,
output reg [24:0] addr,
output reg [15:0] data
);
// *********************************************************************************
// spi client
// *********************************************************************************
// this core supports only the display related OSD commands
// of the minimig
reg [14:0] sbuf;
reg [7:0] cmd;
reg [4:0] cnt;
reg rclk;
reg [24:0] laddr;
reg [15:0] ldata;
localparam UIO_FILE_TX = 8'h53;
localparam UIO_FILE_TX_DAT = 8'h54;
localparam UIO_FILE_INDEX = 8'h55;
assign downloading = downloading_reg;
reg downloading_reg = 1'b0;
// data_io has its own SPI interface to the io controller
always@(posedge sck, posedge ss) begin
if(ss == 1'b1)
cnt <= 5'd0;
else begin
rclk <= 1'b0;
// don't shift in last bit. It is evaluated directly
// when writing to ram
if(cnt != 23)
sbuf <= { sbuf[13:0], sdi};
// count 0-7 8-15 16-23 8-15 16-23 ...
if(cnt < 23) cnt <= cnt + 4'd1;
else cnt <= 4'd8;
// finished command byte
if(cnt == 7)
cmd <= {sbuf[6:0], sdi};
// prepare/end transmission
if((cmd == UIO_FILE_TX) && (cnt == 15)) begin
// prepare
if(sdi) begin
// download rom to address 0, microdrive image to 16MB+
if(index == 0) laddr <= 25'h0 - 25'd1;
else laddr <= 25'h800000 - 25'd1;
downloading_reg <= 1'b1;
end else
downloading_reg <= 1'b0;
end
// command 0x54: UIO_FILE_TX
if((cmd == UIO_FILE_TX_DAT) && (cnt == 23)) begin
ldata <= {sbuf, sdi};
laddr <= laddr + 1;
rclk <= 1'b1;
end
// expose file (menu) index
if((cmd == UIO_FILE_INDEX) && (cnt == 15))
index <= {sbuf[3:0], sdi};
end
end
reg rclkD, rclkD2;
always@(posedge clk) begin
// bring all signals from spi clock domain into local clock domain
rclkD <= rclk;
rclkD2 <= rclkD;
wr <= 1'b0;
if(rclkD && !rclkD2) begin
addr <= laddr;
data <= ldata;
wr <= 1'b1;
end
end
endmodule

131
cores/ql/ipc.v Normal file
View File

@@ -0,0 +1,131 @@
//
// ipc.v
//
// Sinclair QL for the MiST
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module ipc (
input reset,
input clk_bus,
input ipc_bit_strobe,
input ipc_bit,
output reg ipc_reply_bit,
output ipc_busy,
input ps2_kbd_clk,
input ps2_kbd_data
);
assign ipc_busy = 1'b0;
// ---------------------------------------------------------------------------------
// -------------------------------------- KBD --------------------------------------
// ---------------------------------------------------------------------------------
reg key_strobe;
wire [8:0] key;
wire key_available, key_pressed;
keyboard keyboard (
.reset ( reset ),
.clk ( clk_bus ),
.ps2_clk ( ps2_kbd_clk ),
.ps2_data ( ps2_kbd_data ),
.keycode_available ( key_available ),
.keycode ( key ),
.strobe ( key_strobe ),
.pressed ( key_pressed )
);
// ---------------------------------------------------------------------------------
// ----------------------------------- simple IPC ----------------------------------
// ---------------------------------------------------------------------------------
reg [15:0] ipc_reply;
reg [3:0] ipc_unexpected /* synthesis noprune */;
reg [7:0] ipc_reply_len;
reg [3:0] ipc_cmd;
reg [31:0] ipc_len /* synthesis noprune */;
always @(posedge ipc_bit_strobe or posedge reset) begin
if(reset) begin
ipc_len <= 32'd0;
ipc_reply_len <= 8'h00;
ipc_reply <= 8'h00;
ipc_reply_bit <= 1'b0;
ipc_unexpected <= 4'h0;
key_strobe <= 1'b0;
end else begin
key_strobe <= 1'b0;
if(ipc_reply_len == 0) begin
ipc_cmd <= { ipc_cmd[2:0], ipc_bit};
ipc_len <= ipc_len + 32'd1;
// last bit of a 4 bit command being written?
if(ipc_len[1:0] == 2'b11) begin
case({ ipc_cmd[2:0], ipc_bit })
// request status
1: begin
// send 8 bit ipc status reply, bit 0 -> 1=kbd data available
ipc_reply_len <= 8'd8;
ipc_reply_bit <= 1'b0;
ipc_reply <= { 7'b0000000, key_available, 8'h00 };
end
// keyboard
// nibble: PNNN N = chars in buffer, P = last key still pressed
// N*(
// nibble: ctrl/alt/shift
// byte: keycode
// )
8: begin
if(key_available) begin
// currently we can only report one key at once ...
ipc_reply_len <= 8'd16;
ipc_reply_bit <= 1'b0;
ipc_reply <= { 1'b0, 3'd1, 1'b0, key[8:6], 2'b00, key[5:0]};
key_strobe <= 1'b1;
end else begin
// no key to report
ipc_reply_len <= 8'd4;
ipc_reply_bit <= 1'b0;
ipc_reply <= { 1'b0, 3'd0, 12'h000};
end
end
default: begin
if(ipc_unexpected == 0)
ipc_unexpected <= { ipc_cmd[2:0], ipc_bit };
end
endcase;
end
end else begin
// sending reply: shift it out through the ipc_reply_bit register
ipc_reply_len <= ipc_reply_len - 8'd1;
ipc_reply_bit <= ipc_reply[15];
ipc_reply <= { ipc_reply[14:0], 1'b0 };
end
end
end
endmodule

231
cores/ql/keyboard.v Normal file
View File

@@ -0,0 +1,231 @@
//
// keyboard.v
//
// Sinclair QL for the MiST
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module keyboard (
input clk,
input reset,
// ps2 interface
input ps2_clk,
input ps2_data,
output keycode_available,
output [8:0] keycode,
input strobe,
output reg pressed
);
// F1 ESC 1 2 3 4 5 6 7 8 9 0 - = £ \
// F2 TAB Q W E R T Y U I O P [ ]
// F3 CAPS A S D F G H J K L ; ' ENTER
// F4 SHIFT Z X C V B N M , . / SHIFT
// F5 CTRL LEFT RIGHT SPACE UP DOWN ALT
// buffer to hold up to 8 keys
reg [2:0] modifier;
reg [2:0] key_rptr, key_wptr;
reg [8:0] key_fifo [7:0];
// read from fifo
assign keycode_available = key_rptr != key_wptr;
assign keycode = key_fifo[key_rptr];
always @(posedge strobe or posedge reset) begin
if(reset) key_rptr <= 3'd0;
else key_rptr <= key_rptr + 3'd1;
end
// the top most bit is set when the new value is written and cleared
// shortly after when the value itself is stable
always @(negedge ql_key[9] or posedge reset) begin
if(reset)
key_wptr <= 3'd0;
else begin
if(ql_key[8:6] == 3'b000)
key_fifo[key_wptr] <= { modifier, ql_key[5:0] };
else
key_fifo[key_wptr] <= ql_key[8:0];
key_wptr <= key_wptr + 3'd1;
end
end
wire released = reset || key_released;
always @(negedge ql_key[9] or posedge released) begin
if(released) pressed <= 1'b0;
else pressed <= 1'b1;
end
wire [7:0] byte;
wire valid;
wire error;
reg key_released;
reg key_extended;
reg [9:0] ql_key;
always @(posedge clk) begin
if(reset) begin
ql_key <= 10'b0;
key_released <= 1'b0;
key_extended <= 1'b0;
modifier <= 3'b000;
end else begin
ql_key[9] <= 1'b0;
// ps2 decoder has received a valid byte
if(valid) begin
if(byte == 8'he0)
// extended key code
key_extended <= 1'b1;
else if(byte == 8'hf0)
// release code
key_released <= 1'b1;
else begin
key_extended <= 1'b0;
key_released <= 1'b0;
// SHIFT
if((byte == 8'h12) || (byte == 8'h59))
modifier[2] <= !key_released;
// CTRL
if(byte == 8'h14)
modifier[1] <= !key_released;
// ALT
if(byte == 8'h11)
modifier[0] <= !key_released;
// only key down events are enqueued
if(!key_released) begin
case(byte)
// function keys
8'h05: ql_key <= {1'b1, 3'b000, 6'd57}; // F1
8'h06: ql_key <= {1'b1, 3'b000, 6'd59}; // F2
8'h04: ql_key <= {1'b1, 3'b000, 6'd60}; // F3
8'h0c: ql_key <= {1'b1, 3'b000, 6'd56}; // F4
8'h03: ql_key <= {1'b1, 3'b000, 6'd61}; // F5
// cursor keys
8'h75: ql_key <= {1'b1, 3'b000, 6'd50}; // Up
8'h72: ql_key <= {1'b1, 3'b000, 6'd55}; // Down
8'h6b: ql_key <= {1'b1, 3'b000, 6'd49}; // Left
8'h74: ql_key <= {1'b1, 3'b000, 6'd52}; // Right
8'h1c: ql_key <= {1'b1, 3'b000, 6'd28}; // a
8'h32: ql_key <= {1'b1, 3'b000, 6'd44}; // b
8'h21: ql_key <= {1'b1, 3'b000, 6'd43}; // c
8'h23: ql_key <= {1'b1, 3'b000, 6'd30}; // d
8'h24: ql_key <= {1'b1, 3'b000, 6'd12}; // e
8'h2b: ql_key <= {1'b1, 3'b000, 6'd36}; // f
8'h34: ql_key <= {1'b1, 3'b000, 6'd38}; // g
8'h33: ql_key <= {1'b1, 3'b000, 6'd26}; // h
8'h43: ql_key <= {1'b1, 3'b000, 6'd18}; // i
8'h3b: ql_key <= {1'b1, 3'b000, 6'd31}; // j
8'h42: ql_key <= {1'b1, 3'b000, 6'd34}; // k
8'h4b: ql_key <= {1'b1, 3'b000, 6'd24}; // l
8'h3a: ql_key <= {1'b1, 3'b000, 6'd46}; // m
8'h31: ql_key <= {1'b1, 3'b000, 6'd06}; // n
8'h44: ql_key <= {1'b1, 3'b000, 6'd23}; // o
8'h4d: ql_key <= {1'b1, 3'b000, 6'd29}; // p
8'h15: ql_key <= {1'b1, 3'b000, 6'd11}; // q
8'h2d: ql_key <= {1'b1, 3'b000, 6'd20}; // r
8'h1b: ql_key <= {1'b1, 3'b000, 6'd35}; // s
8'h2c: ql_key <= {1'b1, 3'b000, 6'd14}; // t
8'h3c: ql_key <= {1'b1, 3'b000, 6'd15}; // u
8'h2a: ql_key <= {1'b1, 3'b000, 6'd04}; // v
8'h1d: ql_key <= {1'b1, 3'b000, 6'd17}; // w
8'h22: ql_key <= {1'b1, 3'b000, 6'd03}; // x
8'h35: ql_key <= {1'b1, 3'b000, 6'd22}; // y
8'h1a: ql_key <= {1'b1, 3'b000, 6'd41}; // z
8'h45: ql_key <= {1'b1, 3'b000, 6'd13}; // 0
8'h16: ql_key <= {1'b1, 3'b000, 6'd27}; // 1
8'h1e: ql_key <= {1'b1, 3'b000, 6'd09}; // 2
8'h26: ql_key <= {1'b1, 3'b000, 6'd25}; // 3
8'h25: ql_key <= {1'b1, 3'b000, 6'd62}; // 4
8'h2e: ql_key <= {1'b1, 3'b000, 6'd58}; // 5
8'h36: ql_key <= {1'b1, 3'b000, 6'd10}; // 6
8'h3d: ql_key <= {1'b1, 3'b000, 6'd63}; // 7
8'h3e: ql_key <= {1'b1, 3'b000, 6'd08}; // 8
8'h46: ql_key <= {1'b1, 3'b000, 6'd16}; // 9
8'h5a: ql_key <= {1'b1, 3'b000, 6'd48}; // RET
8'h29: ql_key <= {1'b1, 3'b000, 6'd54}; // SPACE
8'h0d: ql_key <= {1'b1, 3'b000, 6'd19}; // TAB
8'h76: ql_key <= {1'b1, 3'b000, 6'd51}; // ESC
8'h58: ql_key <= {1'b1, 3'b000, 6'd33}; // CAPS
8'h4e: ql_key <= {1'b1, 3'b000, 6'd21}; // -
8'h55: ql_key <= {1'b1, 3'b000, 6'd37}; // =
8'h61: ql_key <= {1'b1, 3'b000, 6'd45}; // Pound
8'h5d: ql_key <= {1'b1, 3'b000, 6'd53}; // \
8'h54: ql_key <= {1'b1, 3'b000, 6'd32}; // [
8'h5b: ql_key <= {1'b1, 3'b000, 6'd40}; // ]
8'h4c: ql_key <= {1'b1, 3'b000, 6'd39}; // ;
8'h52: ql_key <= {1'b1, 3'b000, 6'd47}; // '
8'h41: ql_key <= {1'b1, 3'b000, 6'd07}; // ,
8'h49: ql_key <= {1'b1, 3'b000, 6'd42}; // .
8'h4a: ql_key <= {1'b1, 3'b000, 6'd05}; // /
// special keys that include modifier
8'h66: ql_key <= {1'b1, 3'b010, 6'd49}; // Backspace -> CTRL+LEFT
8'h71: ql_key <= {1'b1, 3'b010, 6'd52}; // Delete -> CTRL+RIGHT
8'h7d: ql_key <= {1'b1, 3'b100, 6'd50}; // PageUp -> SHIFT+UP
8'h7a: ql_key <= {1'b1, 3'b100, 6'd55}; // PageDown -> SHIFT+DOWN
8'h6c: ql_key <= {1'b1, 3'b001, 6'd49}; // Home -> ALT+LEFT
8'h69: ql_key <= {1'b1, 3'b001, 6'd52}; // End -> ALT+RIGHT
8'h0b: ql_key <= {1'b1, 3'b100, 6'd57}; // F6 -> SHIFT+F1
8'h83: ql_key <= {1'b1, 3'b100, 6'd59}; // F7 -> SHIFT+F2
8'h0a: ql_key <= {1'b1, 3'b100, 6'd60}; // F8 -> SHIFT+F3
8'h01: ql_key <= {1'b1, 3'b100, 6'd56}; // F9 -> SHIFT+F4
8'h09: ql_key <= {1'b1, 3'b100, 6'd61}; // F10 -> SHIFT+F5
endcase
end
end
end
end
end
// the ps2 decoder has been taken from the zx spectrum core
ps2_intf ps2_keyboard (
.CLK ( clk ),
.nRESET ( !reset ),
// PS/2 interface
.PS2_CLK ( ps2_clk ),
.PS2_DATA ( ps2_data ),
// Byte-wide data interface - only valid for one clock
// so must be latched externally if required
.DATA ( byte ),
.VALID ( valid ),
.ERROR ( error )
);
endmodule

195
cores/ql/mdv.v Normal file
View File

@@ -0,0 +1,195 @@
//
// mdv.v - Microdrive
//
// Sinclair QL for the MiST
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module mdv (
input clk, // 21mhz clock
input reset,
input sel,
// control bits
output gap,
output tx_empty,
output rx_ready,
output [7:0] dout,
// ram interface to read image
input download,
input [24:0] dl_addr,
input mem_ena,
input mem_cycle,
input mem_clk,
output reg mem_read,
output reg [24:0] mem_addr,
input [15:0] mem_din
);
localparam BASE_ADDR = 25'h800000;
// a gap is permanently present if no mdv is inserted or if
// there's a gap on the inserted one. This is the signal that triggers
// the irq and can be seen by the cpu
assign gap = (!mdv_present) || mdv_gap /* synthesis keep */;
// the mdv_rx_ready flag must be quite short as the CPU never waist for it to end
wire mdv_valid = (mdv_bit_cnt[2:0] == 2);
assign rx_ready = mdv_present && mdv_data_valid && mdv_valid /* synthesis keep */;
assign tx_empty = 1'b0;
// microdrive implementation works with images which are uploaded by the user into
// the part of ram which is unavailable to the 68k CPU (>16MB). It is then continously
// replayed from there at 200kbit/s
reg [7:0] mdv_sector /* synthesis noprune */;
reg [24:0] mdv_end /* synthesis noprune */;
// determine mdv image size after download
always @(negedge download or posedge reset) begin
if(reset) mdv_end <= BASE_ADDR;
else mdv_end <= dl_addr;
end
// the microdrive at 200kbit/s reads a bit every 8.3us and needs a new word
// every 80us. video hsync comes every 64us. A new word can thus be read in
// the hsync phase while video isn't accessing ram and the next word will not
// be needed before the next hsync
// gaps are 2800/3400 us which is 35 words at 200kbit/s
assign dout = mdv_bit_cnt[3]?mdv_data[7:0]:mdv_data[15:8];
// data is valid at the end of the video cycle while mem_read is active
reg [15:0] mdv_din /* synthesis noprune */;
always @(negedge mem_cycle)
if(mem_read) mdv_din <= mem_din;
// activate memory read for the next full video cycle after mdv_required
always @(negedge mem_clk) begin
// mdv memory enable signal from zx8301 to give mdv emulation ram access
if(!mem_cycle)
mem_read <= mdv_rd_wait && mem_ena;
end
// wait for next hsync to service request
reg mdv_rd_wait /* synthesis noprune */;
wire mdv_rd_ack = mem_read;
always @(posedge mdv_next_word or posedge mdv_rd_ack) begin
if(mdv_rd_ack) mdv_rd_wait <= 1'b0;
else mdv_rd_wait <= 1'b1;
end
// a microdrive image is present if at least one word is in the buffer
wire mdv_present = sel && (mdv_end != BASE_ADDR);
reg mdv_next_word /* synthesis noprune */;
reg [3:0] mdv_bit_cnt /* synthesis noprune */;
// also generate gap timing
reg [9:0] mdv_gap_cnt /* synthesis noprune */;
reg mdv_gap_state /* synthesis noprune */;
reg mdv_gap_active /* synthesis noprune */;
reg [15:0] mdv_data;
reg mdv_data_valid;
reg mdv_gap;
always @(posedge mdv_clk) begin
mdv_next_word <= 1'b0;
mdv_bit_cnt <= mdv_bit_cnt + 4'd1;
if(mdv_bit_cnt == 15) begin
mdv_data <= mdv_din;
mdv_data_valid <= !mdv_gap_active &&
// don't generate data_valid for first 12 bytes (preamble)
(mdv_gap_cnt > 5) &&
// and also not for the sector internal preamble
!(mdv_gap_state && (mdv_gap_cnt > 7) && (mdv_gap_cnt < 12));
mdv_next_word <= 1'b1;
// reset counters when address is out of range
if((mem_addr > mdv_end)||(mem_addr < 25'h800000)) begin
mem_addr <= BASE_ADDR;
// assume we start at the end of a post-sector/pre-header gap
mdv_gap_cnt <= 10'd0; // count bytes until gap
mdv_gap_state <= 1'b1; // toggle header + data gap
mdv_gap_active <= 1'b1; // gap atm
mdv_sector <= 8'd0;
mdv_gap <= 1'b1;
end else begin
mdv_gap_cnt <= mdv_gap_cnt + 10'd1;
if(mdv_gap_active) begin
// stop sending gap after 35 words = 70 bytes = 2800us
if(mdv_gap_cnt == 34) begin
mdv_gap_cnt <= 10'd0; // restart counter until next gap
mdv_gap_active <= 1'b0; // no gap anymore
mdv_gap_state <= !mdv_gap_state; // toggle gap/data
mdv_gap <= 1'b0;
end
end else begin
mem_addr <= mem_addr + 25'd1;
if((!mdv_gap_state) && (mdv_gap_cnt == 13)) begin
// done reading 14 words header data
mdv_gap_cnt <= 10'd0; // restart counter for gap
mdv_gap_active <= 1'b1; // now comes a gap
mdv_gap <= 1'b1;
end else if(mdv_gap_state && (mdv_gap_cnt == 328)) begin
// done reading 330 words sector data
mdv_gap_cnt <= 10'd0; // restart counter for gap
mdv_gap_active <= 1'b1; // now comes a gap
mdv_gap <= 1'b1;
// The sectors on cartridges are written in descending order
// The images seem to contain them in ascending order. So we
// have to replay them backwards for better performance
if(mem_addr == BASE_ADDR + 343 - 1)
mem_addr <= mdv_end - 343 + 1;
else
mem_addr <= mem_addr - 2*343 + 1;
mdv_sector <= mdv_sector + 8'd1;
end
end
end
end
end
// microdrive clock runs at 200khz
// -> new word required every 80us
localparam mdv_clk_scaler = 21000000/(2*200000)-1;
reg mdv_clk;
reg [7:0] mdv_clk_cnt;
always @(posedge clk) begin
if(mdv_clk_cnt == mdv_clk_scaler) begin
mdv_clk_cnt <= 8'd0;
mdv_clk <= !mdv_clk;
end else
mdv_clk_cnt <= mdv_clk_cnt + 8'd1;
end
endmodule

204
cores/ql/osd.v Normal file
View File

@@ -0,0 +1,204 @@
//
// osd.v
//
// A simple OSD implementation. Can be hooked up between a cores
// VGA output and the physical VGA pins
//
// Sinclair QL for the MiST
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module osd (
// OSDs pixel clock, should be synchronous to cores pixel clock to
// avoid jitter.
input pclk,
// SPI interface
input sck,
input ss,
input sdi,
// VGA signals coming from core
input [5:0] red_in,
input [5:0] green_in,
input [5:0] blue_in,
input hs_in,
input vs_in,
// VGA signals going to video connector
output [5:0] red_out,
output [5:0] green_out,
output [5:0] blue_out,
output hs_out,
output vs_out
);
parameter OSD_X_OFFSET = 10'd0;
parameter OSD_Y_OFFSET = 10'd0;
parameter OSD_COLOR = 3'd0;
localparam OSD_WIDTH = 10'd256;
localparam OSD_HEIGHT = 10'd128;
// *********************************************************************************
// spi client
// *********************************************************************************
// this core supports only the display related OSD commands
// of the minimig
reg [7:0] sbuf;
reg [7:0] cmd;
reg [4:0] cnt;
reg [10:0] bcnt;
reg osd_enable;
reg [7:0] osd_buffer [2047:0]; // the OSD buffer itself
// the OSD has its own SPI interface to the io controller
always@(posedge sck, posedge ss) begin
if(ss == 1'b1) begin
cnt <= 5'd0;
bcnt <= 11'd0;
end else begin
sbuf <= { sbuf[6:0], sdi};
// 0:7 is command, rest payload
if(cnt < 15)
cnt <= cnt + 4'd1;
else
cnt <= 4'd8;
if(cnt == 7) begin
cmd <= {sbuf[6:0], sdi};
// lower three command bits are line address
bcnt <= { sbuf[1:0], sdi, 8'h00};
// command 0x40: OSDCMDENABLE, OSDCMDDISABLE
if(sbuf[6:3] == 4'b0100)
osd_enable <= sdi;
end
// command 0x20: OSDCMDWRITE
if((cmd[7:3] == 5'b00100) && (cnt == 15)) begin
osd_buffer[bcnt] <= {sbuf[6:0], sdi};
bcnt <= bcnt + 11'd1;
end
end
end
// *********************************************************************************
// video timing and sync polarity anaylsis
// *********************************************************************************
// horizontal counter
reg [9:0] h_cnt;
reg hsD, hsD2;
reg [9:0] hs_low, hs_high;
wire hs_pol = hs_high < hs_low;
wire [9:0] h_dsp_width = hs_pol?hs_low:hs_high;
wire [9:0] h_dsp_ctr = { 1'b0, h_dsp_width[9:1] };
always @(posedge pclk) begin
// bring hsync into local clock domain
hsD <= hs_in;
hsD2 <= hsD;
// falling edge of hs_in
if(!hsD && hsD2) begin
h_cnt <= 10'd0;
hs_high <= h_cnt;
end
// rising edge of hs_in
else if(hsD && !hsD2) begin
h_cnt <= 10'd0;
hs_low <= h_cnt;
end
else
h_cnt <= h_cnt + 10'd1;
end
// vertical counter
reg [9:0] v_cnt;
reg vsD, vsD2;
reg [9:0] vs_low, vs_high;
wire vs_pol = vs_high < vs_low;
wire [9:0] v_dsp_width = vs_pol?vs_low:vs_high;
wire [9:0] v_dsp_ctr = { 1'b0, v_dsp_width[9:1] };
always @(posedge hs_in) begin
// bring vsync into local clock domain
vsD <= vs_in;
vsD2 <= vsD;
// falling edge of vs_in
if(!vsD && vsD2) begin
v_cnt <= 10'd0;
vs_high <= v_cnt;
end
// rising edge of vs_in
else if(vsD && !vsD2) begin
v_cnt <= 10'd0;
vs_low <= v_cnt;
end
else
v_cnt <= v_cnt + 10'd1;
end
// area in which OSD is being displayed
wire [9:0] h_osd_start = h_dsp_ctr + OSD_X_OFFSET - (OSD_WIDTH >> 1);
wire [9:0] h_osd_end = h_dsp_ctr + OSD_X_OFFSET + (OSD_WIDTH >> 1) - 1;
wire [9:0] v_osd_start = v_dsp_ctr + OSD_Y_OFFSET - (OSD_HEIGHT >> 1);
wire [9:0] v_osd_end = v_dsp_ctr + OSD_Y_OFFSET + (OSD_HEIGHT >> 1) - 1;
reg h_osd_active, v_osd_active;
always @(posedge pclk) begin
if(hs_in != hs_pol) begin
if(h_cnt == h_osd_start) h_osd_active <= 1'b1;
if(h_cnt == h_osd_end) h_osd_active <= 1'b0;
end
if(vs_in != vs_pol) begin
if(v_cnt == v_osd_start) v_osd_active <= 1'b1;
if(v_cnt == v_osd_end) v_osd_active <= 1'b0;
end
end
wire osd_de = osd_enable && h_osd_active && v_osd_active;
wire [7:0] osd_hcnt = h_cnt - h_osd_start + 7'd1; // one pixel offset for osd_byte register
wire [6:0] osd_vcnt = v_cnt - v_osd_start;
wire osd_pixel = osd_byte[osd_vcnt[3:1]];
reg [7:0] osd_byte;
always @(posedge pclk)
osd_byte <= osd_buffer[{osd_vcnt[6:4], osd_hcnt}];
wire [2:0] osd_color = OSD_COLOR;
assign red_out = !osd_de?red_in: {osd_pixel, osd_pixel, osd_color[2], red_in[5:3] };
assign green_out = !osd_de?green_in:{osd_pixel, osd_pixel, osd_color[1], green_in[5:3]};
assign blue_out = !osd_de?blue_in: {osd_pixel, osd_pixel, osd_color[0], blue_in[5:3] };
assign hs_out = hs_in;
assign vs_out = vs_in;
endmodule

4
cores/ql/pll.qip Normal file
View File

@@ -0,0 +1,4 @@
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
set_global_assignment -name IP_TOOL_VERSION "13.1"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll.ppf"]

337
cores/ql/pll.v Normal file
View File

@@ -0,0 +1,337 @@
// megafunction wizard: %ALTPLL%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altpll
// ============================================================
// File Name: pll.v
// Megafunction Name(s):
// altpll
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 13.1.4 Build 182 03/12/2014 SJ Web Edition
// ************************************************************
//Copyright (C) 1991-2014 Altera Corporation
//Your use of Altera Corporation's design tools, logic functions
//and other software and tools, and its AMPP partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Altera Program License
//Subscription Agreement, Altera MegaCore Function License
//Agreement, or other applicable license agreement, including,
//without limitation, that your use is for the sole purpose of
//programming logic devices manufactured by Altera and sold by
//Altera or its authorized distributors. Please refer to the
//applicable agreement for further details.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll (
inclk0,
c0,
c1,
locked);
input inclk0;
output c0;
output c1;
output locked;
wire [4:0] sub_wire0;
wire sub_wire2;
wire [0:0] sub_wire6 = 1'h0;
wire [0:0] sub_wire3 = sub_wire0[0:0];
wire [1:1] sub_wire1 = sub_wire0[1:1];
wire c1 = sub_wire1;
wire locked = sub_wire2;
wire c0 = sub_wire3;
wire sub_wire4 = inclk0;
wire [1:0] sub_wire5 = {sub_wire6, sub_wire4};
altpll altpll_component (
.inclk (sub_wire5),
.clk (sub_wire0),
.locked (sub_wire2),
.activeclock (),
.areset (1'b0),
.clkbad (),
.clkena ({6{1'b1}}),
.clkloss (),
.clkswitch (1'b0),
.configupdate (1'b0),
.enable0 (),
.enable1 (),
.extclk (),
.extclkena ({4{1'b1}}),
.fbin (1'b1),
.fbmimicbidir (),
.fbout (),
.fref (),
.icdrclk (),
.pfdena (1'b1),
.phasecounterselect ({4{1'b1}}),
.phasedone (),
.phasestep (1'b1),
.phaseupdown (1'b1),
.pllena (1'b1),
.scanaclr (1'b0),
.scanclk (1'b0),
.scanclkena (1'b1),
.scandata (1'b0),
.scandataout (),
.scandone (),
.scanread (1'b0),
.scanwrite (1'b0),
.sclkout0 (),
.sclkout1 (),
.vcooverrange (),
.vcounderrange ());
defparam
altpll_component.bandwidth_type = "AUTO",
altpll_component.clk0_divide_by = 9,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 7,
altpll_component.clk0_phase_shift = "0",
altpll_component.clk1_divide_by = 9,
altpll_component.clk1_duty_cycle = 50,
altpll_component.clk1_multiply_by = 7,
altpll_component.clk1_phase_shift = "-5000",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 37037,
altpll_component.intended_device_family = "Cyclone III",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "NORMAL",
altpll_component.pll_type = "AUTO",
altpll_component.port_activeclock = "PORT_UNUSED",
altpll_component.port_areset = "PORT_UNUSED",
altpll_component.port_clkbad0 = "PORT_UNUSED",
altpll_component.port_clkbad1 = "PORT_UNUSED",
altpll_component.port_clkloss = "PORT_UNUSED",
altpll_component.port_clkswitch = "PORT_UNUSED",
altpll_component.port_configupdate = "PORT_UNUSED",
altpll_component.port_fbin = "PORT_UNUSED",
altpll_component.port_inclk0 = "PORT_USED",
altpll_component.port_inclk1 = "PORT_UNUSED",
altpll_component.port_locked = "PORT_USED",
altpll_component.port_pfdena = "PORT_UNUSED",
altpll_component.port_phasecounterselect = "PORT_UNUSED",
altpll_component.port_phasedone = "PORT_UNUSED",
altpll_component.port_phasestep = "PORT_UNUSED",
altpll_component.port_phaseupdown = "PORT_UNUSED",
altpll_component.port_pllena = "PORT_UNUSED",
altpll_component.port_scanaclr = "PORT_UNUSED",
altpll_component.port_scanclk = "PORT_UNUSED",
altpll_component.port_scanclkena = "PORT_UNUSED",
altpll_component.port_scandata = "PORT_UNUSED",
altpll_component.port_scandataout = "PORT_UNUSED",
altpll_component.port_scandone = "PORT_UNUSED",
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_USED",
altpll_component.port_clk2 = "PORT_UNUSED",
altpll_component.port_clk3 = "PORT_UNUSED",
altpll_component.port_clk4 = "PORT_UNUSED",
altpll_component.port_clk5 = "PORT_UNUSED",
altpll_component.port_clkena0 = "PORT_UNUSED",
altpll_component.port_clkena1 = "PORT_UNUSED",
altpll_component.port_clkena2 = "PORT_UNUSED",
altpll_component.port_clkena3 = "PORT_UNUSED",
altpll_component.port_clkena4 = "PORT_UNUSED",
altpll_component.port_clkena5 = "PORT_UNUSED",
altpll_component.port_extclk0 = "PORT_UNUSED",
altpll_component.port_extclk1 = "PORT_UNUSED",
altpll_component.port_extclk2 = "PORT_UNUSED",
altpll_component.port_extclk3 = "PORT_UNUSED",
altpll_component.self_reset_on_loss_lock = "OFF",
altpll_component.width_clock = 5;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "9"
// Retrieval info: PRIVATE: DIV_FACTOR1 NUMERIC "9"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: DUTY_CYCLE1 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "21.000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE1 STRING "21.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 "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "27.000"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "1"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT1 STRING "ps"
// Retrieval info: PRIVATE: MIG_DEVICE_SPEED_GRADE STRING "Any"
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MIRROR_CLK1 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "7"
// Retrieval info: PRIVATE: MULT_FACTOR1 NUMERIC "7"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "21.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ1 STRING "21.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE1 STRING "0"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT1 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT1 STRING "-5000.00000000"
// Retrieval info: PRIVATE: PHASE_SHIFT_STEP_ENABLED_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: PHASE_SHIFT_UNIT1 STRING "ps"
// Retrieval info: PRIVATE: PLL_ADVANCED_PARAM_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_ARESET_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll.mif"
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: STICKY_CLK1 STRING "1"
// Retrieval info: PRIVATE: SWITCHOVER_COUNT_EDIT NUMERIC "1"
// Retrieval info: PRIVATE: SWITCHOVER_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SYNTH_WRAPPER_GEN_POSTFIX STRING "0"
// Retrieval info: PRIVATE: USE_CLK0 STRING "1"
// Retrieval info: PRIVATE: USE_CLK1 STRING "1"
// Retrieval info: PRIVATE: USE_CLKENA0 STRING "0"
// Retrieval info: PRIVATE: USE_CLKENA1 STRING "0"
// Retrieval info: PRIVATE: USE_MIL_SPEED_GRADE NUMERIC "0"
// Retrieval info: PRIVATE: ZERO_DELAY_RADIO STRING "0"
// Retrieval info: LIBRARY: altera_mf altera_mf.altera_mf_components.all
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "9"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "7"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: CLK1_DIVIDE_BY NUMERIC "9"
// Retrieval info: CONSTANT: CLK1_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK1_MULTIPLY_BY NUMERIC "7"
// Retrieval info: CONSTANT: CLK1_PHASE_SHIFT STRING "-5000"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "37037"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk2 STRING "PORT_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: SELF_RESET_ON_LOSS_LOCK STRING "OFF"
// Retrieval info: CONSTANT: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: c1 0 0 0 0 OUTPUT_CLK_EXT VCC "c1"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: USED_PORT: locked 0 0 0 0 OUTPUT GND "locked"
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: CONNECT: c1 0 0 0 0 @clk 0 0 1 1
// Retrieval info: CONNECT: locked 0 0 0 0 @locked 0 0 0 0
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf
// Retrieval info: CBX_MODULE_PREFIX: ON

4
cores/ql/pll_rtc.qip Normal file
View File

@@ -0,0 +1,4 @@
set_global_assignment -name IP_TOOL_NAME "ALTPLL"
set_global_assignment -name IP_TOOL_VERSION "13.1"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "pll_rtc.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "pll_rtc.ppf"]

301
cores/ql/pll_rtc.v Normal file
View File

@@ -0,0 +1,301 @@
// megafunction wizard: %ALTPLL%
// GENERATION: STANDARD
// VERSION: WM1.0
// MODULE: altpll
// ============================================================
// File Name: pll_rtc.v
// Megafunction Name(s):
// altpll
//
// Simulation Library Files(s):
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
//
// 13.1.4 Build 182 03/12/2014 SJ Web Edition
// ************************************************************
//Copyright (C) 1991-2014 Altera Corporation
//Your use of Altera Corporation's design tools, logic functions
//and other software and tools, and its AMPP partner logic
//functions, and any output files from any of the foregoing
//(including device programming or simulation files), and any
//associated documentation or information are expressly subject
//to the terms and conditions of the Altera Program License
//Subscription Agreement, Altera MegaCore Function License
//Agreement, or other applicable license agreement, including,
//without limitation, that your use is for the sole purpose of
//programming logic devices manufactured by Altera and sold by
//Altera or its authorized distributors. Please refer to the
//applicable agreement for further details.
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module pll_rtc (
inclk0,
c0);
input inclk0;
output c0;
wire [4:0] sub_wire0;
wire [0:0] sub_wire4 = 1'h0;
wire [0:0] sub_wire1 = sub_wire0[0:0];
wire c0 = sub_wire1;
wire sub_wire2 = inclk0;
wire [1:0] sub_wire3 = {sub_wire4, sub_wire2};
altpll altpll_component (
.inclk (sub_wire3),
.clk (sub_wire0),
.activeclock (),
.areset (1'b0),
.clkbad (),
.clkena ({6{1'b1}}),
.clkloss (),
.clkswitch (1'b0),
.configupdate (1'b0),
.enable0 (),
.enable1 (),
.extclk (),
.extclkena ({4{1'b1}}),
.fbin (1'b1),
.fbmimicbidir (),
.fbout (),
.fref (),
.icdrclk (),
.locked (),
.pfdena (1'b1),
.phasecounterselect ({4{1'b1}}),
.phasedone (),
.phasestep (1'b1),
.phaseupdown (1'b1),
.pllena (1'b1),
.scanaclr (1'b0),
.scanclk (1'b0),
.scanclkena (1'b1),
.scandata (1'b0),
.scandataout (),
.scandone (),
.scanread (1'b0),
.scanwrite (1'b0),
.sclkout0 (),
.sclkout1 (),
.vcooverrange (),
.vcounderrange ());
defparam
altpll_component.bandwidth_type = "AUTO",
altpll_component.clk0_divide_by = 328125,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 1024,
altpll_component.clk0_phase_shift = "0",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 47619,
altpll_component.intended_device_family = "Cyclone III",
altpll_component.lpm_hint = "CBX_MODULE_PREFIX=pll_rtc",
altpll_component.lpm_type = "altpll",
altpll_component.operation_mode = "NORMAL",
altpll_component.pll_type = "AUTO",
altpll_component.port_activeclock = "PORT_UNUSED",
altpll_component.port_areset = "PORT_UNUSED",
altpll_component.port_clkbad0 = "PORT_UNUSED",
altpll_component.port_clkbad1 = "PORT_UNUSED",
altpll_component.port_clkloss = "PORT_UNUSED",
altpll_component.port_clkswitch = "PORT_UNUSED",
altpll_component.port_configupdate = "PORT_UNUSED",
altpll_component.port_fbin = "PORT_UNUSED",
altpll_component.port_inclk0 = "PORT_USED",
altpll_component.port_inclk1 = "PORT_UNUSED",
altpll_component.port_locked = "PORT_UNUSED",
altpll_component.port_pfdena = "PORT_UNUSED",
altpll_component.port_phasecounterselect = "PORT_UNUSED",
altpll_component.port_phasedone = "PORT_UNUSED",
altpll_component.port_phasestep = "PORT_UNUSED",
altpll_component.port_phaseupdown = "PORT_UNUSED",
altpll_component.port_pllena = "PORT_UNUSED",
altpll_component.port_scanaclr = "PORT_UNUSED",
altpll_component.port_scanclk = "PORT_UNUSED",
altpll_component.port_scanclkena = "PORT_UNUSED",
altpll_component.port_scandata = "PORT_UNUSED",
altpll_component.port_scandataout = "PORT_UNUSED",
altpll_component.port_scandone = "PORT_UNUSED",
altpll_component.port_scanread = "PORT_UNUSED",
altpll_component.port_scanwrite = "PORT_UNUSED",
altpll_component.port_clk0 = "PORT_USED",
altpll_component.port_clk1 = "PORT_UNUSED",
altpll_component.port_clk2 = "PORT_UNUSED",
altpll_component.port_clk3 = "PORT_UNUSED",
altpll_component.port_clk4 = "PORT_UNUSED",
altpll_component.port_clk5 = "PORT_UNUSED",
altpll_component.port_clkena0 = "PORT_UNUSED",
altpll_component.port_clkena1 = "PORT_UNUSED",
altpll_component.port_clkena2 = "PORT_UNUSED",
altpll_component.port_clkena3 = "PORT_UNUSED",
altpll_component.port_clkena4 = "PORT_UNUSED",
altpll_component.port_clkena5 = "PORT_UNUSED",
altpll_component.port_extclk0 = "PORT_UNUSED",
altpll_component.port_extclk1 = "PORT_UNUSED",
altpll_component.port_extclk2 = "PORT_UNUSED",
altpll_component.port_extclk3 = "PORT_UNUSED",
altpll_component.width_clock = 5;
endmodule
// ============================================================
// CNX file retrieval info
// ============================================================
// Retrieval info: PRIVATE: ACTIVECLK_CHECK STRING "0"
// Retrieval info: PRIVATE: BANDWIDTH STRING "1.000"
// Retrieval info: PRIVATE: BANDWIDTH_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_FREQ_UNIT STRING "MHz"
// Retrieval info: PRIVATE: BANDWIDTH_PRESET STRING "Low"
// Retrieval info: PRIVATE: BANDWIDTH_USE_AUTO STRING "1"
// Retrieval info: PRIVATE: BANDWIDTH_USE_PRESET STRING "0"
// Retrieval info: PRIVATE: CLKBAD_SWITCHOVER_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKLOSS_CHECK STRING "0"
// Retrieval info: PRIVATE: CLKSWITCH_CHECK STRING "0"
// Retrieval info: PRIVATE: CNX_NO_COMPENSATE_RADIO STRING "0"
// Retrieval info: PRIVATE: CREATE_CLKBAD_CHECK STRING "0"
// Retrieval info: PRIVATE: CREATE_INCLK1_CHECK STRING "0"
// Retrieval info: PRIVATE: CUR_DEDICATED_CLK STRING "c0"
// Retrieval info: PRIVATE: CUR_FBIN_CLK STRING "c0"
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "1"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "0.065536"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: GLOCKED_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: GLOCKED_MODE_CHECK STRING "0"
// Retrieval info: PRIVATE: GLOCK_COUNTER_EDIT NUMERIC "1048575"
// Retrieval info: PRIVATE: HAS_MANUAL_SWITCHOVER STRING "1"
// Retrieval info: PRIVATE: INCLK0_FREQ_EDIT STRING "21.000"
// Retrieval info: PRIVATE: INCLK0_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT STRING "100.000"
// Retrieval info: PRIVATE: INCLK1_FREQ_EDIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_CHANGED STRING "1"
// Retrieval info: PRIVATE: INCLK1_FREQ_UNIT_COMBO STRING "MHz"
// Retrieval info: PRIVATE: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: PRIVATE: INT_FEEDBACK__MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: LOCKED_OUTPUT_CHECK STRING "0"
// Retrieval info: PRIVATE: LONG_SCAN_RADIO STRING "1"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE STRING "Not Available"
// Retrieval info: PRIVATE: LVDS_MODE_DATA_RATE_DIRTY NUMERIC "0"
// Retrieval info: PRIVATE: LVDS_PHASE_SHIFT_UNIT0 STRING "deg"
// Retrieval info: PRIVATE: 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 "0.06553600"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: PHASE_RECONFIG_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: PHASE_SHIFT0 STRING "0.00000000"
// Retrieval info: PRIVATE: PHASE_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 "0"
// Retrieval info: PRIVATE: PLL_AUTOPLL_CHECK NUMERIC "1"
// Retrieval info: PRIVATE: PLL_ENHPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FASTPLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_FBMIMIC_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_LVDS_PLL_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PLL_PFDENA_CHECK STRING "0"
// Retrieval info: PRIVATE: PLL_TARGET_HARCOPY_CHECK NUMERIC "0"
// Retrieval info: PRIVATE: PRIMARY_CLK_COMBO STRING "inclk0"
// Retrieval info: PRIVATE: RECONFIG_FILE STRING "pll_rtc.mif"
// Retrieval info: PRIVATE: SACN_INPUTS_CHECK STRING "0"
// Retrieval info: PRIVATE: SCAN_FEATURE_ENABLED STRING "1"
// Retrieval info: PRIVATE: SELF_RESET_LOCK_LOSS STRING "0"
// Retrieval info: PRIVATE: SHORT_SCAN_RADIO STRING "0"
// Retrieval info: PRIVATE: SPREAD_FEATURE_ENABLED STRING "0"
// Retrieval info: PRIVATE: SPREAD_FREQ STRING "50.000"
// Retrieval info: PRIVATE: SPREAD_FREQ_UNIT STRING "KHz"
// Retrieval info: PRIVATE: SPREAD_PERCENT STRING "0.500"
// Retrieval info: PRIVATE: SPREAD_USE STRING "0"
// Retrieval info: PRIVATE: SRC_SYNCH_COMP_RADIO STRING "0"
// Retrieval info: PRIVATE: STICKY_CLK0 STRING "1"
// Retrieval info: PRIVATE: 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: BANDWIDTH_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "328125"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "1024"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "47619"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "Cyclone III"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altpll"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "NORMAL"
// Retrieval info: CONSTANT: PLL_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: PORT_ACTIVECLOCK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_ARESET STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD0 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKBAD1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKLOSS STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CLKSWITCH STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_CONFIGUPDATE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_FBIN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_INCLK0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_INCLK1 STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_LOCKED STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PFDENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASECOUNTERSELECT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASESTEP STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PHASEUPDOWN STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_PLLENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANACLR STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLK STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANCLKENA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATA STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDATAOUT STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANDONE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANREAD STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_SCANWRITE STRING "PORT_UNUSED"
// Retrieval info: CONSTANT: PORT_clk0 STRING "PORT_USED"
// Retrieval info: CONSTANT: PORT_clk1 STRING "PORT_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: WIDTH_CLOCK NUMERIC "5"
// Retrieval info: USED_PORT: @clk 0 0 5 0 OUTPUT_CLK_EXT VCC "@clk[4..0]"
// Retrieval info: USED_PORT: c0 0 0 0 0 OUTPUT_CLK_EXT VCC "c0"
// Retrieval info: USED_PORT: inclk0 0 0 0 0 INPUT_CLK_EXT GND "inclk0"
// Retrieval info: CONNECT: @inclk 0 0 1 1 GND 0 0 0 0
// Retrieval info: CONNECT: @inclk 0 0 1 0 inclk0 0 0 0 0
// Retrieval info: CONNECT: c0 0 0 0 0 @clk 0 0 1 0
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_rtc.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_rtc.ppf TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_rtc.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_rtc.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_rtc.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_rtc_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_rtc_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf
// Retrieval info: CBX_MODULE_PREFIX: ON

158
cores/ql/ps2_intf.vhd Executable file
View File

@@ -0,0 +1,158 @@
-- 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.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.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;

30
cores/ql/ql.qpf Normal file
View File

@@ -0,0 +1,30 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2010 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 10.1 Build 153 11/29/2010 SJ Full Version
# Date created = 11:11:11 June 13, 2011
#
# -------------------------------------------------------------------------- #
QUARTUS_VERSION = "10.1"
DATE = "11:11:11 June 13, 2011"
# Revisions
PROJECT_REVISION = "ql"

395
cores/ql/ql.qsf Normal file
View File

@@ -0,0 +1,395 @@
# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2011 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus II
# Version 11.0 Build 157 04/27/2011 SJ Full Version
# Date created = 17:14:01 April 10, 2012
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# led_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 III"
set_global_assignment -name DEVICE EP3C25E144C8
set_global_assignment -name TOP_LEVEL_ENTITY ql
set_global_assignment -name ORIGINAL_QUARTUS_VERSION 11.0
set_global_assignment -name PROJECT_CREATION_TIME_DATE "17:14:01 APRIL 10, 2012"
set_global_assignment -name LAST_QUARTUS_VERSION 13.1
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name DEVICE_FILTER_PACKAGE "ANY QFP"
set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 8
set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 1
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_global_assignment -name USE_CONFIGURATION_DEVICE OFF
set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF
set_global_assignment -name RESERVE_ALL_UNUSED_PINS_WEAK_PULLUP "AS INPUT TRI-STATED"
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise
set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise
set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall
set_global_assignment -name CYCLONEIII_CONFIGURATION_SCHEME "PASSIVE SERIAL"
set_global_assignment -name GENERATE_RBF_FILE ON
set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_location_assignment PIN_7 -to LED
set_location_assignment PIN_22 -to CLOCK_50[0]
set_location_assignment PIN_23 -to CLOCK_50[1]
set_location_assignment PIN_128 -to CLOCK_32[0]
set_location_assignment PIN_129 -to CLOCK_32[1]
set_location_assignment PIN_54 -to CLOCK_27[0]
set_location_assignment PIN_55 -to CLOCK_27[1]
set_location_assignment PIN_144 -to VGA_R[5]
set_location_assignment PIN_143 -to VGA_R[4]
set_location_assignment PIN_142 -to VGA_R[3]
set_location_assignment PIN_141 -to VGA_R[2]
set_location_assignment PIN_137 -to VGA_R[1]
set_location_assignment PIN_135 -to VGA_R[0]
set_location_assignment PIN_133 -to VGA_B[5]
set_location_assignment PIN_132 -to VGA_B[4]
set_location_assignment PIN_125 -to VGA_B[3]
set_location_assignment PIN_121 -to VGA_B[2]
set_location_assignment PIN_120 -to VGA_B[1]
set_location_assignment PIN_115 -to VGA_B[0]
set_location_assignment PIN_114 -to VGA_G[5]
set_location_assignment PIN_113 -to VGA_G[4]
set_location_assignment PIN_112 -to VGA_G[3]
set_location_assignment PIN_111 -to VGA_G[2]
set_location_assignment PIN_110 -to VGA_G[1]
set_location_assignment PIN_106 -to VGA_G[0]
set_location_assignment PIN_136 -to VGA_VS
set_location_assignment PIN_119 -to VGA_HS
set_location_assignment PIN_65 -to AUDIO_L
set_location_assignment PIN_80 -to AUDIO_R
set_location_assignment PIN_46 -to UART_TX
set_location_assignment PIN_31 -to UART_RX
set_location_assignment PIN_105 -to SPI_DO
set_location_assignment PIN_88 -to SPI_DI
set_location_assignment PIN_126 -to SPI_SCK
set_location_assignment PIN_127 -to SPI_SS2
set_location_assignment PIN_91 -to SPI_SS3
set_location_assignment PIN_90 -to SPI_SS4
set_location_assignment PIN_13 -to CONF_DATA0
set_location_assignment PIN_49 -to SDRAM_A[0]
set_location_assignment PIN_44 -to SDRAM_A[1]
set_location_assignment PIN_42 -to SDRAM_A[2]
set_location_assignment PIN_39 -to SDRAM_A[3]
set_location_assignment PIN_4 -to SDRAM_A[4]
set_location_assignment PIN_6 -to SDRAM_A[5]
set_location_assignment PIN_8 -to SDRAM_A[6]
set_location_assignment PIN_10 -to SDRAM_A[7]
set_location_assignment PIN_11 -to SDRAM_A[8]
set_location_assignment PIN_28 -to SDRAM_A[9]
set_location_assignment PIN_50 -to SDRAM_A[10]
set_location_assignment PIN_30 -to SDRAM_A[11]
set_location_assignment PIN_32 -to SDRAM_A[12]
set_location_assignment PIN_83 -to SDRAM_DQ[0]
set_location_assignment PIN_79 -to SDRAM_DQ[1]
set_location_assignment PIN_77 -to SDRAM_DQ[2]
set_location_assignment PIN_76 -to SDRAM_DQ[3]
set_location_assignment PIN_72 -to SDRAM_DQ[4]
set_location_assignment PIN_71 -to SDRAM_DQ[5]
set_location_assignment PIN_69 -to SDRAM_DQ[6]
set_location_assignment PIN_68 -to SDRAM_DQ[7]
set_location_assignment PIN_86 -to SDRAM_DQ[8]
set_location_assignment PIN_87 -to SDRAM_DQ[9]
set_location_assignment PIN_98 -to SDRAM_DQ[10]
set_location_assignment PIN_99 -to SDRAM_DQ[11]
set_location_assignment PIN_100 -to SDRAM_DQ[12]
set_location_assignment PIN_101 -to SDRAM_DQ[13]
set_location_assignment PIN_103 -to SDRAM_DQ[14]
set_location_assignment PIN_104 -to SDRAM_DQ[15]
set_location_assignment PIN_58 -to SDRAM_BA[0]
set_location_assignment PIN_51 -to SDRAM_BA[1]
set_location_assignment PIN_85 -to SDRAM_DQMH
set_location_assignment PIN_67 -to SDRAM_DQML
set_location_assignment PIN_60 -to SDRAM_nRAS
set_location_assignment PIN_64 -to SDRAM_nCAS
set_location_assignment PIN_66 -to SDRAM_nWE
set_location_assignment PIN_59 -to SDRAM_nCS
set_location_assignment PIN_33 -to SDRAM_CKE
set_location_assignment PIN_43 -to SDRAM_CLK
set_global_assignment -name ENABLE_SIGNALTAP ON
set_global_assignment -name USE_SIGNALTAP_FILE stp1.stp
set_global_assignment -name CYCLONEII_RESERVE_NCEO_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA0_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DATA1_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_FLASH_NCE_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name RESERVE_DCLK_AFTER_CONFIGURATION "USE AS REGULAR IO"
set_global_assignment -name OPTIMIZE_HOLD_TIMING "ALL PATHS"
set_global_assignment -name OPTIMIZE_MULTI_CORNER_TIMING ON
set_global_assignment -name FITTER_EFFORT "FAST FIT"
set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW"
set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)"
set_instance_assignment -name CURRENT_STRENGTH_NEW "MAXIMUM CURRENT" -to VGA_*
set_global_assignment -name SLD_NODE_CREATOR_ID 110 -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_ENTITY_NAME sld_signaltap -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_RAM_BLOCK_TYPE=AUTO" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_NODE_INFO=805334528" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_POWER_UP_TRIGGER=0" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_STORAGE_QUALIFIER_INVERSION_MASK_LENGTH=0" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_ATTRIBUTE_MEM_MODE=OFF" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_STATE_FLOW_USE_GENERATED=0" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_STATE_BITS=11" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_BUFFER_FULL_STOP=1" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_CURRENT_RESOURCE_WIDTH=1" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_TRIGGER_LEVEL=1" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_TRIGGER_IN_ENABLED=0" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_ADVANCED_TRIGGER_ENTITY=basic,1," -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_TRIGGER_LEVEL_PIPELINE=1" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_ENABLE_ADVANCED_TRIGGER=0" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_SEGMENT_SIZE=256" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_SAMPLE_DEPTH=256" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[0] -to "TG68KdotC_Kernel:tg68k|IPL[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[1] -to "TG68KdotC_Kernel:tg68k|IPL[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[2] -to "TG68KdotC_Kernel:tg68k|IPL[2]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[3] -to "TG68KdotC_Kernel:tg68k|Reset" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[4] -to "TG68KdotC_Kernel:tg68k|addr[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[5] -to "TG68KdotC_Kernel:tg68k|addr[10]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[6] -to "TG68KdotC_Kernel:tg68k|addr[11]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[7] -to "TG68KdotC_Kernel:tg68k|addr[12]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[8] -to "TG68KdotC_Kernel:tg68k|addr[13]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[9] -to "TG68KdotC_Kernel:tg68k|addr[14]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[10] -to "TG68KdotC_Kernel:tg68k|addr[15]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[11] -to "TG68KdotC_Kernel:tg68k|addr[16]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[12] -to "TG68KdotC_Kernel:tg68k|addr[17]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[13] -to "TG68KdotC_Kernel:tg68k|addr[18]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[14] -to "TG68KdotC_Kernel:tg68k|addr[19]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[15] -to "TG68KdotC_Kernel:tg68k|addr[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[16] -to "TG68KdotC_Kernel:tg68k|addr[20]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[17] -to "TG68KdotC_Kernel:tg68k|addr[21]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[18] -to "TG68KdotC_Kernel:tg68k|addr[22]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[19] -to "TG68KdotC_Kernel:tg68k|addr[23]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[20] -to "TG68KdotC_Kernel:tg68k|addr[24]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[21] -to "TG68KdotC_Kernel:tg68k|addr[25]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[22] -to "TG68KdotC_Kernel:tg68k|addr[26]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[23] -to "TG68KdotC_Kernel:tg68k|addr[27]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[24] -to "TG68KdotC_Kernel:tg68k|addr[28]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[25] -to "TG68KdotC_Kernel:tg68k|addr[29]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[26] -to "TG68KdotC_Kernel:tg68k|addr[2]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[27] -to "TG68KdotC_Kernel:tg68k|addr[30]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[28] -to "TG68KdotC_Kernel:tg68k|addr[31]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[29] -to "TG68KdotC_Kernel:tg68k|addr[3]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[30] -to "TG68KdotC_Kernel:tg68k|addr[4]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[31] -to "TG68KdotC_Kernel:tg68k|addr[5]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[32] -to "TG68KdotC_Kernel:tg68k|addr[6]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[33] -to "TG68KdotC_Kernel:tg68k|addr[7]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[34] -to "TG68KdotC_Kernel:tg68k|addr[8]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[35] -to "TG68KdotC_Kernel:tg68k|addr[9]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[36] -to "TG68KdotC_Kernel:tg68k|busstate[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[37] -to "TG68KdotC_Kernel:tg68k|busstate[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[38] -to "TG68KdotC_Kernel:tg68k|clk" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[39] -to "TG68KdotC_Kernel:tg68k|clkena_in" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[40] -to "TG68KdotC_Kernel:tg68k|data_in[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[41] -to "TG68KdotC_Kernel:tg68k|data_in[10]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[42] -to "TG68KdotC_Kernel:tg68k|data_in[11]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[43] -to "TG68KdotC_Kernel:tg68k|data_in[12]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[44] -to "TG68KdotC_Kernel:tg68k|data_in[13]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[45] -to "TG68KdotC_Kernel:tg68k|data_in[14]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[46] -to "TG68KdotC_Kernel:tg68k|data_in[15]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[47] -to "TG68KdotC_Kernel:tg68k|data_in[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[48] -to "TG68KdotC_Kernel:tg68k|data_in[2]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[49] -to "TG68KdotC_Kernel:tg68k|data_in[3]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[50] -to "TG68KdotC_Kernel:tg68k|data_in[4]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[51] -to "TG68KdotC_Kernel:tg68k|data_in[5]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[52] -to "TG68KdotC_Kernel:tg68k|data_in[6]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[53] -to "TG68KdotC_Kernel:tg68k|data_in[7]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[54] -to "TG68KdotC_Kernel:tg68k|data_in[8]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[55] -to "TG68KdotC_Kernel:tg68k|data_in[9]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[56] -to "TG68KdotC_Kernel:tg68k|data_write[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[57] -to "TG68KdotC_Kernel:tg68k|data_write[10]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[58] -to "TG68KdotC_Kernel:tg68k|data_write[11]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[59] -to "TG68KdotC_Kernel:tg68k|data_write[12]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[60] -to "TG68KdotC_Kernel:tg68k|data_write[13]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[61] -to "TG68KdotC_Kernel:tg68k|data_write[14]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[62] -to "TG68KdotC_Kernel:tg68k|data_write[15]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[63] -to "TG68KdotC_Kernel:tg68k|data_write[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[64] -to "TG68KdotC_Kernel:tg68k|data_write[2]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[65] -to "TG68KdotC_Kernel:tg68k|data_write[3]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[66] -to "TG68KdotC_Kernel:tg68k|data_write[4]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[67] -to "TG68KdotC_Kernel:tg68k|data_write[5]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[68] -to "TG68KdotC_Kernel:tg68k|data_write[6]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[69] -to "TG68KdotC_Kernel:tg68k|data_write[7]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[70] -to "TG68KdotC_Kernel:tg68k|data_write[8]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[71] -to "TG68KdotC_Kernel:tg68k|data_write[9]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[72] -to "TG68KdotC_Kernel:tg68k|exe_opcode[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[73] -to "TG68KdotC_Kernel:tg68k|exe_opcode[10]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[74] -to "TG68KdotC_Kernel:tg68k|exe_opcode[11]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[75] -to "TG68KdotC_Kernel:tg68k|exe_opcode[12]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[76] -to "TG68KdotC_Kernel:tg68k|exe_opcode[13]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[77] -to "TG68KdotC_Kernel:tg68k|exe_opcode[14]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[78] -to "TG68KdotC_Kernel:tg68k|exe_opcode[15]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[79] -to "TG68KdotC_Kernel:tg68k|exe_opcode[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[80] -to "TG68KdotC_Kernel:tg68k|exe_opcode[2]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[81] -to "TG68KdotC_Kernel:tg68k|exe_opcode[3]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[82] -to "TG68KdotC_Kernel:tg68k|exe_opcode[4]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[83] -to "TG68KdotC_Kernel:tg68k|exe_opcode[5]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[84] -to "TG68KdotC_Kernel:tg68k|exe_opcode[6]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[85] -to "TG68KdotC_Kernel:tg68k|exe_opcode[7]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[86] -to "TG68KdotC_Kernel:tg68k|exe_opcode[8]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[87] -to "TG68KdotC_Kernel:tg68k|exe_opcode[9]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[88] -to "TG68KdotC_Kernel:tg68k|nLDS" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[89] -to "TG68KdotC_Kernel:tg68k|nReset" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[90] -to "TG68KdotC_Kernel:tg68k|nUDS" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[91] -to "TG68KdotC_Kernel:tg68k|nWr" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[0] -to "TG68KdotC_Kernel:tg68k|IPL[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[1] -to "TG68KdotC_Kernel:tg68k|IPL[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[2] -to "TG68KdotC_Kernel:tg68k|IPL[2]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[3] -to "TG68KdotC_Kernel:tg68k|Reset" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[4] -to "TG68KdotC_Kernel:tg68k|addr[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[5] -to "TG68KdotC_Kernel:tg68k|addr[10]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[6] -to "TG68KdotC_Kernel:tg68k|addr[11]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[7] -to "TG68KdotC_Kernel:tg68k|addr[12]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[8] -to "TG68KdotC_Kernel:tg68k|addr[13]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[9] -to "TG68KdotC_Kernel:tg68k|addr[14]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[10] -to "TG68KdotC_Kernel:tg68k|addr[15]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[11] -to "TG68KdotC_Kernel:tg68k|addr[16]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[12] -to "TG68KdotC_Kernel:tg68k|addr[17]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[13] -to "TG68KdotC_Kernel:tg68k|addr[18]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[14] -to "TG68KdotC_Kernel:tg68k|addr[19]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[15] -to "TG68KdotC_Kernel:tg68k|addr[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[16] -to "TG68KdotC_Kernel:tg68k|addr[20]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[17] -to "TG68KdotC_Kernel:tg68k|addr[21]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[18] -to "TG68KdotC_Kernel:tg68k|addr[22]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[19] -to "TG68KdotC_Kernel:tg68k|addr[23]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[20] -to "TG68KdotC_Kernel:tg68k|addr[24]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[21] -to "TG68KdotC_Kernel:tg68k|addr[25]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[22] -to "TG68KdotC_Kernel:tg68k|addr[26]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[23] -to "TG68KdotC_Kernel:tg68k|addr[27]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[24] -to "TG68KdotC_Kernel:tg68k|addr[28]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[25] -to "TG68KdotC_Kernel:tg68k|addr[29]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[26] -to "TG68KdotC_Kernel:tg68k|addr[2]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[27] -to "TG68KdotC_Kernel:tg68k|addr[30]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[28] -to "TG68KdotC_Kernel:tg68k|addr[31]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[29] -to "TG68KdotC_Kernel:tg68k|addr[3]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[30] -to "TG68KdotC_Kernel:tg68k|addr[4]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[31] -to "TG68KdotC_Kernel:tg68k|addr[5]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[32] -to "TG68KdotC_Kernel:tg68k|addr[6]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[33] -to "TG68KdotC_Kernel:tg68k|addr[7]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[34] -to "TG68KdotC_Kernel:tg68k|addr[8]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[35] -to "TG68KdotC_Kernel:tg68k|addr[9]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[36] -to "TG68KdotC_Kernel:tg68k|busstate[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[37] -to "TG68KdotC_Kernel:tg68k|busstate[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[38] -to "TG68KdotC_Kernel:tg68k|clk" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[39] -to "TG68KdotC_Kernel:tg68k|clkena_in" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[40] -to "TG68KdotC_Kernel:tg68k|data_in[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[41] -to "TG68KdotC_Kernel:tg68k|data_in[10]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[42] -to "TG68KdotC_Kernel:tg68k|data_in[11]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[43] -to "TG68KdotC_Kernel:tg68k|data_in[12]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[44] -to "TG68KdotC_Kernel:tg68k|data_in[13]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[45] -to "TG68KdotC_Kernel:tg68k|data_in[14]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[46] -to "TG68KdotC_Kernel:tg68k|data_in[15]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[47] -to "TG68KdotC_Kernel:tg68k|data_in[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[48] -to "TG68KdotC_Kernel:tg68k|data_in[2]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[49] -to "TG68KdotC_Kernel:tg68k|data_in[3]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[50] -to "TG68KdotC_Kernel:tg68k|data_in[4]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[51] -to "TG68KdotC_Kernel:tg68k|data_in[5]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[52] -to "TG68KdotC_Kernel:tg68k|data_in[6]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[53] -to "TG68KdotC_Kernel:tg68k|data_in[7]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[54] -to "TG68KdotC_Kernel:tg68k|data_in[8]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[55] -to "TG68KdotC_Kernel:tg68k|data_in[9]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[56] -to "TG68KdotC_Kernel:tg68k|data_write[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[57] -to "TG68KdotC_Kernel:tg68k|data_write[10]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[58] -to "TG68KdotC_Kernel:tg68k|data_write[11]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[59] -to "TG68KdotC_Kernel:tg68k|data_write[12]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[60] -to "TG68KdotC_Kernel:tg68k|data_write[13]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[61] -to "TG68KdotC_Kernel:tg68k|data_write[14]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[62] -to "TG68KdotC_Kernel:tg68k|data_write[15]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[63] -to "TG68KdotC_Kernel:tg68k|data_write[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[64] -to "TG68KdotC_Kernel:tg68k|data_write[2]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[65] -to "TG68KdotC_Kernel:tg68k|data_write[3]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[66] -to "TG68KdotC_Kernel:tg68k|data_write[4]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[67] -to "TG68KdotC_Kernel:tg68k|data_write[5]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[68] -to "TG68KdotC_Kernel:tg68k|data_write[6]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[69] -to "TG68KdotC_Kernel:tg68k|data_write[7]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[70] -to "TG68KdotC_Kernel:tg68k|data_write[8]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[71] -to "TG68KdotC_Kernel:tg68k|data_write[9]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[72] -to "TG68KdotC_Kernel:tg68k|exe_opcode[0]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[73] -to "TG68KdotC_Kernel:tg68k|exe_opcode[10]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[74] -to "TG68KdotC_Kernel:tg68k|exe_opcode[11]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[75] -to "TG68KdotC_Kernel:tg68k|exe_opcode[12]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[76] -to "TG68KdotC_Kernel:tg68k|exe_opcode[13]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[77] -to "TG68KdotC_Kernel:tg68k|exe_opcode[14]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[78] -to "TG68KdotC_Kernel:tg68k|exe_opcode[15]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[79] -to "TG68KdotC_Kernel:tg68k|exe_opcode[1]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[80] -to "TG68KdotC_Kernel:tg68k|exe_opcode[2]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[81] -to "TG68KdotC_Kernel:tg68k|exe_opcode[3]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[82] -to "TG68KdotC_Kernel:tg68k|exe_opcode[4]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[83] -to "TG68KdotC_Kernel:tg68k|exe_opcode[5]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[84] -to "TG68KdotC_Kernel:tg68k|exe_opcode[6]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[85] -to "TG68KdotC_Kernel:tg68k|exe_opcode[7]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[86] -to "TG68KdotC_Kernel:tg68k|exe_opcode[8]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[87] -to "TG68KdotC_Kernel:tg68k|exe_opcode[9]" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[88] -to "TG68KdotC_Kernel:tg68k|nLDS" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[89] -to "TG68KdotC_Kernel:tg68k|nReset" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[90] -to "TG68KdotC_Kernel:tg68k|nUDS" -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[91] -to "TG68KdotC_Kernel:tg68k|nWr" -section_id auto_signaltap_0
set_global_assignment -name VERILOG_FILE zx8301.v
set_global_assignment -name VHDL_FILE ps2_intf.vhd
set_global_assignment -name VERILOG_FILE keyboard.v
set_global_assignment -name VHDL_FILE TG68KdotC_Kernel.vhd
set_global_assignment -name VHDL_FILE TG68K_Pack.vhd
set_global_assignment -name VHDL_FILE TG68K_ALU.vhd
set_global_assignment -name VERILOG_FILE data_io.v
set_global_assignment -name VERILOG_FILE sdram.v
set_global_assignment -name VERILOG_FILE osd.v
set_global_assignment -name VERILOG_FILE user_io.v
set_global_assignment -name QIP_FILE pll.qip
set_global_assignment -name VERILOG_FILE ql.v
set_global_assignment -name SIGNALTAP_FILE stp1.stp
set_global_assignment -name QIP_FILE pll_rtc.qip
set_global_assignment -name VERILOG_FILE mdv.v
set_global_assignment -name VERILOG_FILE zx8302.v
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[92] -to cpu_enable -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[93] -to cpu_mem -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[94] -to cpu_rd -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[95] -to cpu_wr -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_trigger_in[96] -to video_cycle_rd -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[92] -to cpu_enable -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[93] -to cpu_mem -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[94] -to cpu_rd -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[95] -to cpu_wr -section_id auto_signaltap_0
set_instance_assignment -name CONNECT_TO_SLD_NODE_ENTITY_PORT acq_data_in[96] -to video_cycle_rd -section_id auto_signaltap_0
set_global_assignment -name VERILOG_FILE ipc.v
set_instance_assignment -name POST_FIT_CONNECT_TO_SLD_NODE_ENTITY_PORT acq_clk -to clk5 -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_DATA_BITS=97" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_TRIGGER_BITS=97" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_INVERSION_MASK=0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_INVERSION_MASK_LENGTH=313" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_NODE_CRC_LOWORD=20891" -section_id auto_signaltap_0
set_global_assignment -name SLD_NODE_PARAMETER_ASSIGNMENT "SLD_NODE_CRC_HIWORD=32699" -section_id auto_signaltap_0
set_global_assignment -name SLD_FILE db/stp1_auto_stripped.stp
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top

413
cores/ql/ql.v Normal file
View File

@@ -0,0 +1,413 @@
//
// ql.v - Sinclair QL for the MiST
//
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module ql (
input [1:0] CLOCK_27,
// LED outputs
output LED, // LED Yellow
// SDRAM interface
inout [15:0] SDRAM_DQ, // SDRAM Data bus 16 Bits
output [12:0] SDRAM_A, // SDRAM Address bus 13 Bits
output SDRAM_DQML, // SDRAM Low-byte Data Mask
output SDRAM_DQMH, // SDRAM High-byte Data Mask
output SDRAM_nWE, // SDRAM Write Enable
output SDRAM_nCAS, // SDRAM Column Address Strobe
output SDRAM_nRAS, // SDRAM Row Address Strobe
output SDRAM_nCS, // SDRAM Chip Select
output [1:0] SDRAM_BA, // SDRAM Bank Address
output SDRAM_CLK, // SDRAM Clock
output SDRAM_CKE, // SDRAM Clock Enable
// SPI interface to arm io controller
output SPI_DO,
input SPI_DI,
input SPI_SCK,
input SPI_SS2,
input SPI_SS3,
input SPI_SS4,
input CONF_DATA0,
output AUDIO_L, // sigma-delta DAC output left
output AUDIO_R, // sigma-delta DAC output right
output VGA_HS,
output VGA_VS,
output [5:0] VGA_R,
output [5:0] VGA_G,
output [5:0] VGA_B
);
// the configuration string is returned to the io controller to allow
// it to control the menu on the OSD
parameter CONF_STR = {
"QL;;",
"F1,MDV;",
"O2,RAM,128k,640k;",
"O3,Video mode,PAL,NTSC;",
"O4,Scanlines,Off,On;",
"T5,Reset"
};
parameter CONF_STR_LEN = 4+7+17+23+20+8;
// the status register is controlled by the on screen display (OSD)
wire [7:0] status;
wire tv15khz;
wire [1:0] buttons;
wire ps2_kbd_clk, ps2_kbd_data;
// generate ps2_clock
wire ps2_clock = ps2_clk_div[6]; // ~20khz
reg [6:0] ps2_clk_div;
always @(posedge clk2)
ps2_clk_div <= ps2_clk_div + 7'd1;
// include user_io module for arm controller communication
user_io #(.STRLEN(CONF_STR_LEN)) user_io (
.conf_str ( CONF_STR ),
.SPI_CLK ( SPI_SCK ),
.SPI_SS_IO ( CONF_DATA0 ),
.SPI_MISO ( SPI_DO ),
.SPI_MOSI ( SPI_DI ),
.scandoubler_disable ( tv15khz ),
.buttons ( buttons ),
// ps2 interface
.ps2_clk ( ps2_clock ),
.ps2_kbd_clk ( ps2_kbd_clk ),
.ps2_kbd_data ( ps2_kbd_data ),
.status ( status )
);
// csync for tv15khz
// QLs vsync is positive, QLs hsync is negative
wire vga_csync = !(!vga_hsync ^ vga_vsync);
wire vga_hsync, vga_vsync;
// TV SCART has csync on hsync pin and "high" on vsync pin
assign VGA_VS = tv15khz?1'b1:vga_vsync;
assign VGA_HS = tv15khz?vga_csync:vga_hsync;
// tv15hkz has half the pixel rate
wire osd_clk = tv15khz?clk10:clk21;
// include the on screen display
osd #(12,0,5) osd (
.pclk ( osd_clk ),
// spi for OSD
.sdi ( SPI_DI ),
.sck ( SPI_SCK ),
.ss ( SPI_SS3 ),
.red_in ( video_r ),
.green_in ( video_g ),
.blue_in ( video_b ),
.hs_in ( video_hs ),
.vs_in ( video_vs ),
.red_out ( VGA_R ),
.green_out ( VGA_G ),
.blue_out ( VGA_B ),
.hs_out ( vga_hsync ),
.vs_out ( vga_vsync )
);
// SDRAM control signals
assign SDRAM_CKE = 1'b1;
// CPU and data_io share the same bus cycle. Thus the CPU cannot run while
// (ROM) data is being downloaded which wouldn't make any sense, anyway
// during ROM download data_io writes the ram. Otherwise the CPU
wire [24:0] sys_addr = dio_download?dio_addr[24:0]:{ 6'b000000, cpu_addr[19:1]};
wire [1:0] sys_ds = dio_download?2'b11:~cpu_ds;
wire [15:0] sys_dout = dio_download?dio_data:cpu_dout;
wire sys_wr = dio_download?dio_write:(cpu_wr && cpu_ram);
wire sys_oe = dio_download?1'b0:(cpu_rd && cpu_mem);
// microdrive emulation and video share the video cycle time slot
wire [24:0] video_cycle_addr = mdv_read?mdv_addr:{6'd0, video_addr};
wire video_cycle_rd = mdv_read?1'b1:video_rd;
// video and CPU/data_io time share the sdram bus
wire [24:0] sdram_addr = video_cycle?video_cycle_addr:sys_addr;
wire sdram_wr = video_cycle?1'b0:sys_wr;
wire sdram_oe = video_cycle?video_cycle_rd:sys_oe;
wire [1:0] sdram_ds = video_cycle?2'b11:sys_ds;
wire [15:0] sdram_dout;
wire [15:0] sdram_din = sys_dout;
sdram sdram (
// interface to the MT48LC16M16 chip
.sd_data ( SDRAM_DQ ),
.sd_addr ( SDRAM_A ),
.sd_dqm ( {SDRAM_DQMH, SDRAM_DQML} ),
.sd_cs ( SDRAM_nCS ),
.sd_ba ( SDRAM_BA ),
.sd_we ( SDRAM_nWE ),
.sd_ras ( SDRAM_nRAS ),
.sd_cas ( SDRAM_nCAS ),
// system interface
.clk ( clk21 ),
.clkref ( clk2 ),
.init ( !pll_locked ),
// cpu interface
.din ( sdram_din ),
.addr ( sdram_addr ),
.we ( sdram_wr ),
.oe ( sdram_oe ),
.ds ( sdram_ds ),
.dout ( sdram_dout )
);
// ---------------------------------------------------------------------------------
// ------------------------------------- data io -----------------------------------
// ---------------------------------------------------------------------------------
wire dio_download;
wire [4:0] dio_index;
wire [24:0] dio_addr;
wire [15:0] dio_data;
wire dio_write;
// include ROM download helper
// this receives a byte stream from the arm io controller via spi and
// writes it into sdram
data_io data_io (
// io controller spi interface
.sck ( SPI_SCK ),
.ss ( SPI_SS2 ),
.sdi ( SPI_DI ),
.downloading ( dio_download ), // signal indicating an active rom download
.index ( dio_index ),
// external ram interface
.clk ( cpu_cycle ),
.wr ( dio_write ),
.addr ( dio_addr ),
.data ( dio_data )
);
// ---------------------------------------------------------------------------------
// -------------------------------------- video ------------------------------------
// ---------------------------------------------------------------------------------
wire [5:0] video_r, video_g, video_b;
wire video_hs, video_vs;
wire [18:0] video_addr;
wire video_rd;
// the zx8301 has only one write-only register at $18063
wire zx8301_cs = cpu_cycle && cpu_io &&
({cpu_addr[6:5], cpu_addr[1]} == 3'b111)&& cpu_wr && !cpu_ds[0];
zx8301 zx8301 (
.reset ( reset ),
.clk_vga ( clk21 ),
.clk_video ( clk10 ),
.video_cycle ( video_cycle ),
.ntsc ( status[3] ),
.scandoubler ( !tv15khz ),
.scanlines ( status[4] ),
.clk_bus ( clk2 ),
.cpu_cs ( zx8301_cs ),
.cpu_data ( cpu_dout[7:0] ),
.mdv_men ( mdv_men ),
.addr ( video_addr ),
.din ( sdram_dout ),
.rd ( video_rd ),
.hs ( video_hs ),
.vs ( video_vs ),
.r ( video_r ),
.g ( video_g ),
.b ( video_b )
);
// ---------------------------------------------------------------------------------
// -------------------------------------- reset ------------------------------------
// ---------------------------------------------------------------------------------
wire rom_download = dio_download && (dio_index == 0);
reg [11:0] reset_cnt;
wire reset = (reset_cnt != 0);
always @(posedge clk2) begin
if(buttons[1] || status[0] || status[5] || !pll_locked || rom_download)
reset_cnt <= 12'hfff;
else if(reset_cnt != 0)
reset_cnt <= reset_cnt - 1;
end
// ---------------------------------------------------------------------------------
// --------------------------------------- IO --------------------------------------
// ---------------------------------------------------------------------------------
wire zx8302_sel = cpu_cycle && cpu_io && !cpu_addr[6];
wire [1:0] zx8302_addr = {cpu_addr[5], cpu_addr[1]};
wire [15:0] zx8302_dout;
wire mdv_download = (dio_index == 1) && dio_download;
wire mdv_men;
wire mdv_read;
wire [24:0] mdv_addr;
zx8302 zx8302 (
.reset ( reset ),
.init ( !pll_locked ),
.clk ( clk21 ),
.ipl ( cpu_ipl ),
.led ( LED ),
// CPU connection
.clk_bus ( clk2 ),
.cpu_sel ( zx8302_sel ),
.cpu_wr ( cpu_wr ),
.cpu_addr ( zx8302_addr ),
.cpu_ds ( cpu_ds ),
.cpu_din ( cpu_dout ),
.cpu_dout ( zx8302_dout ),
.ps2_kbd_clk ( ps2_kbd_clk ),
.ps2_kbd_data ( ps2_kbd_data ),
.vs ( video_vs ),
// microdrive sdram interface
.mdv_addr ( mdv_addr ),
.mdv_din ( sdram_dout ),
.mdv_read ( mdv_read ),
.mdv_men ( mdv_men ),
.video_cycle ( video_cycle ),
.mdv_download ( mdv_download ),
.mdv_dl_addr ( dio_addr )
);
// ---------------------------------------------------------------------------------
// -------------------------------------- CPU --------------------------------------
// ---------------------------------------------------------------------------------
// address decoding
wire cpu_io = ({cpu_addr[19:14], 2'b00} == 8'h18); // internal IO $18000-$1bffff
wire cpu_bram = (cpu_addr[19:17] == 3'b001); // 128k RAM at $20000
wire cpu_xram = status[2] && ((cpu_addr[19:18] == 2'b01) ||
(cpu_addr[19:18] == 2'b10)); // 512k RAM at $40000 if enabled
wire cpu_ram = cpu_bram || cpu_xram; // any RAM
wire cpu_rom = (cpu_addr[19:16] == 4'h0); // 64k ROM at $0
wire cpu_mem = cpu_ram || cpu_rom; // any memory mapped to sdram
wire [15:0] io_dout = cpu_addr[6]?16'h0000:zx8302_dout;
// demultiplex the various data sources
wire [15:0] cpu_din =
cpu_mem?sdram_dout:
cpu_io?io_dout:
16'hffff;
wire [31:0] cpu_addr;
wire [1:0] cpu_ds;
wire [15:0] cpu_dout;
wire [2:0] cpu_ipl;
wire cpu_rw;
wire [1:0] cpu_busstate;
wire cpu_rd = (cpu_busstate == 2'b00) || (cpu_busstate == 2'b10);
wire cpu_wr = (cpu_busstate == 2'b11) && !cpu_rw;
wire cpu_idle = (cpu_busstate == 2'b01);
reg cpu_enable;
always @(negedge clk2)
cpu_enable <= (cpu_cycle && !dio_download) || cpu_idle;
TG68KdotC_Kernel #(0,0,0,0,0,0) tg68k (
.clk ( clk2 ),
.nReset ( ~reset ),
.clkena_in ( cpu_enable ),
.data_in ( cpu_din ),
.IPL ( cpu_ipl ),
.IPL_autovector ( 1'b1 ),
.berr ( 1'b0 ),
.clr_berr ( 1'b0 ),
.CPU ( 2'b00 ), // 00=68000
.addr ( cpu_addr ),
.data_write ( cpu_dout ),
.nUDS ( cpu_ds[1] ),
.nLDS ( cpu_ds[0] ),
.nWr ( cpu_rw ),
.busstate ( cpu_busstate ), // 00-> fetch code 10->read data 11->write data 01->no memaccess
.nResetOut ( ),
.FC ( )
);
// -------------------------------------------------------------------------
// -------------------------- clock generation -----------------------------
// -------------------------------------------------------------------------
reg clk10; // 10.5 MHz QL pixel clock
wire clk21;
always @(posedge clk21)
clk10 <= !clk10;
reg clk5; // 5.25 MHz CPU clock
always @(posedge clk10)
clk5 <= !clk5;
reg clk2; // 2.625 MHz bus clock
always @(posedge clk5)
clk2 <= !clk2;
// CPU and Video share the bus
reg video_cycle;
wire cpu_cycle = !video_cycle;
always @(posedge clk2)
video_cycle <= !video_cycle;
wire pll_locked;
// A PLL to derive the system clock from the MiSTs 27MHz
pll pll (
.inclk0( CLOCK_27[0] ),
.c0( clk21 ), // 21.000 MHz
.c1( SDRAM_CLK ), // 21.000 MHz phase shifted
.locked( pll_locked )
);
endmodule

6
cores/ql/readme.md Normal file
View File

@@ -0,0 +1,6 @@
QL for MIST
===========
This is an implementation of the Sinclair QL for the MIST board.
It's based on the TG68K CPU core.

150
cores/ql/sdram.v Normal file
View File

@@ -0,0 +1,150 @@
//
// sdram.v
//
// sdram controller implementation for the MiST board
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module sdram (
// interface to the MT48LC16M16 chip
inout [15:0] sd_data, // 16 bit bidirectional data bus
output reg [12:0] sd_addr, // 13 bit multiplexed address bus
output reg [1:0] sd_dqm, // two byte masks
output reg[1:0] sd_ba, // two banks
output sd_cs, // a single chip select
output sd_we, // write enable
output sd_ras, // row address select
output sd_cas, // columns address select
// cpu/chipset interface
input init, // init signal after FPGA config to initialize RAM
input clk, // sdram is accessed at up to 128MHz
input clkref, // reference clock to sync to
input [15:0] din, // data input from chipset/cpu
output [15:0] dout, // data output to chipset/cpu
input [24:0] addr, // 25 bit word address
input [1:0] ds, // data strobe for hi/low byte
input oe, // cpu/chipset requests read
input we // cpu/chipset requests write
);
// no burst configured
localparam RASCAS_DELAY = 3'd3; // tRCD>=20ns -> 2 cycles@64MHz
localparam BURST_LENGTH = 3'b000; // 000=none, 001=2, 010=4, 011=8
localparam ACCESS_TYPE = 1'b0; // 0=sequential, 1=interleaved
localparam CAS_LATENCY = 3'd3; // 2/3 allowed
localparam OP_MODE = 2'b00; // only 00 (standard operation) allowed
localparam NO_WRITE_BURST = 1'b1; // 0= write burst enabled, 1=only single access write
localparam MODE = { 3'b000, NO_WRITE_BURST, OP_MODE, CAS_LATENCY, ACCESS_TYPE, BURST_LENGTH};
// ---------------------------------------------------------------------
// ------------------------ cycle state machine ------------------------
// ---------------------------------------------------------------------
localparam STATE_IDLE = 3'd0; // first state in cycle
localparam STATE_CMD_START = 3'd1; // state in which a new command can be started
localparam STATE_CMD_CONT = STATE_CMD_START + RASCAS_DELAY - 3'd1; // 4 command can be continued
localparam STATE_LAST = 3'd7; // last state in cycle
reg [2:0] q /* synthesis noprune */;
always @(posedge clk) begin
// 32Mhz counter synchronous to 4 Mhz clock
// force counter to pass state 5->6 exactly after the rising edge of clkref
// since clkref is two clocks early
if(((q == 7) && ( clkref == 0)) ||
((q == 0) && ( clkref == 1)) ||
((q != 7) && (q != 0)))
q <= q + 3'd1;
end
// ---------------------------------------------------------------------
// --------------------------- startup/reset ---------------------------
// ---------------------------------------------------------------------
// wait 1ms (32 clkref cycles) after FPGA config is done before going
// into normal operation. Initialize the ram in the last 16 reset cycles (cycles 15-0)
reg [4:0] reset;
always @(posedge clk) begin
if(init) reset <= 5'h1f;
else if((q == STATE_LAST) && (reset != 0))
reset <= reset - 5'd1;
end
// ---------------------------------------------------------------------
// ------------------ generate ram control signals ---------------------
// ---------------------------------------------------------------------
// all possible commands
localparam CMD_INHIBIT = 4'b1111;
localparam CMD_NOP = 4'b0111;
localparam CMD_ACTIVE = 4'b0011;
localparam CMD_READ = 4'b0101;
localparam CMD_WRITE = 4'b0100;
localparam CMD_BURST_TERMINATE = 4'b0110;
localparam CMD_PRECHARGE = 4'b0010;
localparam CMD_AUTO_REFRESH = 4'b0001;
localparam CMD_LOAD_MODE = 4'b0000;
reg [3:0] sd_cmd; // current command sent to sd ram
// drive control signals according to current command
assign sd_cs = sd_cmd[3];
assign sd_ras = sd_cmd[2];
assign sd_cas = sd_cmd[1];
assign sd_we = sd_cmd[0];
assign sd_data = we?din:16'bZZZZZZZZZZZZZZZZ;
assign dout = sd_data;
always @(posedge clk) begin
sd_cmd <= CMD_INHIBIT;
if(reset != 0) begin
sd_ba <= 2'b00;
sd_dqm <= 2'b00;
if(reset == 13) sd_addr <= 13'b0010000000000;
else sd_addr <= MODE;
if(q == STATE_IDLE) begin
if(reset == 13) sd_cmd <= CMD_PRECHARGE;
if(reset == 2) sd_cmd <= CMD_LOAD_MODE;
end
end else begin
if(q <= STATE_CMD_START) begin
sd_addr <= addr[20:8];
sd_ba <= addr[22:21];
sd_dqm <= { !ds[1], !ds[0] };
end else
sd_addr <= { 4'b0010, addr[23], addr[7:0]};
if(q == STATE_IDLE) begin
if(we || oe) sd_cmd <= CMD_ACTIVE;
else sd_cmd <= CMD_AUTO_REFRESH;
end else if(q == STATE_CMD_CONT) begin
if(we) sd_cmd <= CMD_WRITE;
else if(oe) sd_cmd <= CMD_READ;
end
end
end
endmodule

418
cores/ql/user_io.v Normal file
View File

@@ -0,0 +1,418 @@
//
// user_io.v - interface to MIST arm io controller
//
// Sinclair QL for the MiST
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// parameter STRLEN and the actual length of conf_str have to match
module user_io #(parameter STRLEN=0) (
input [(8*STRLEN)-1:0] conf_str,
input SPI_CLK,
input SPI_SS_IO,
output reg SPI_MISO,
input SPI_MOSI,
output reg [7:0] joystick_0,
output reg [7:0] joystick_1,
output reg [15:0] joystick_analog_0,
output reg [15:0] joystick_analog_1,
output [1:0] buttons,
output [1:0] switches,
output scandoubler_disable,
output reg [7:0] status,
// connection to sd card emulation
input [31:0] sd_lba,
input sd_rd,
input sd_wr,
output reg sd_ack,
input sd_conf,
input sd_sdhc,
output [7:0] sd_dout, // valid on rising edge of sd_dout_strobe
output reg sd_dout_strobe,
input [7:0] sd_din,
output reg sd_din_strobe,
output reg sd_change,
// ps2 keyboard emulation
input ps2_clk, // 12-16khz provided by core
output ps2_kbd_clk,
output reg ps2_kbd_data,
output ps2_mouse_clk,
output reg ps2_mouse_data,
// serial com port
input [7:0] serial_data,
input serial_strobe
);
reg [6:0] sbuf;
reg [7:0] cmd;
reg [2:0] bit_cnt; // counts bits 0-7 0-7 ...
reg [7:0] byte_cnt; // counts bytes
reg [5:0] joystick0;
reg [5:0] joystick1;
reg [7:0] but_sw;
reg [2:0] stick_idx;
assign buttons = but_sw[1:0];
assign switches = but_sw[3:2];
assign scandoubler_disable = but_sw[4];
assign sd_dout = { sbuf, SPI_MOSI};
// this variant of user_io is for 8 bit cores (type == a4) only
wire [7:0] core_type = 8'ha4;
// command byte read by the io controller
wire [7:0] sd_cmd = { 4'h5, sd_conf, sd_sdhc, sd_wr, sd_rd };
// filter spi clock. the 8 bit gate delay is ~2.5ns in total
wire [7:0] spi_sck_D = { spi_sck_D[6:0], SPI_CLK } /* synthesis keep */;
wire spi_sck = (spi_sck && spi_sck_D != 8'h00) || (!spi_sck && spi_sck_D == 8'hff);
// drive MISO only when transmitting core id
always@(negedge spi_sck or posedge SPI_SS_IO) begin
if(SPI_SS_IO == 1) begin
SPI_MISO <= 1'bZ;
end else begin
// first byte returned is always core type, further bytes are
// command dependent
if(byte_cnt == 0) begin
SPI_MISO <= core_type[~bit_cnt];
end else begin
// reading serial fifo
if(cmd == 8'h1b) begin
// send alternating flag byte and data
if(byte_cnt[0]) SPI_MISO <= serial_out_status[~bit_cnt];
else SPI_MISO <= serial_out_byte[~bit_cnt];
end
// reading config string
else if(cmd == 8'h14) begin
// returning a byte from string
if(byte_cnt < STRLEN + 1)
SPI_MISO <= conf_str[{STRLEN - byte_cnt,~bit_cnt}];
else
SPI_MISO <= 1'b0;
end
// reading sd card status
else if(cmd == 8'h16) begin
if(byte_cnt == 1)
SPI_MISO <= sd_cmd[~bit_cnt];
else if((byte_cnt >= 2) && (byte_cnt < 6))
SPI_MISO <= sd_lba[{5-byte_cnt, ~bit_cnt}];
else
SPI_MISO <= 1'b0;
end
// reading sd card write data
else if(cmd == 8'h18)
SPI_MISO <= sd_din[~bit_cnt];
else
SPI_MISO <= 1'b0;
end
end
end
// ---------------- PS2 ---------------------
// 8 byte fifos to store ps2 bytes
localparam PS2_FIFO_BITS = 3;
// keyboard
reg [7:0] ps2_kbd_fifo [(2**PS2_FIFO_BITS)-1:0];
reg [PS2_FIFO_BITS-1:0] ps2_kbd_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_kbd_rptr;
// ps2 transmitter state machine
reg [3:0] ps2_kbd_tx_state;
reg [7:0] ps2_kbd_tx_byte;
reg ps2_kbd_parity;
assign ps2_kbd_clk = ps2_clk || (ps2_kbd_tx_state == 0);
// ps2 transmitter
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
reg ps2_kbd_r_inc;
always@(posedge ps2_clk) begin
ps2_kbd_r_inc <= 1'b0;
if(ps2_kbd_r_inc)
ps2_kbd_rptr <= ps2_kbd_rptr + 1;
// transmitter is idle?
if(ps2_kbd_tx_state == 0) begin
// data in fifo present?
if(ps2_kbd_wptr != ps2_kbd_rptr) begin
// load tx register from fifo
ps2_kbd_tx_byte <= ps2_kbd_fifo[ps2_kbd_rptr];
ps2_kbd_r_inc <= 1'b1;
// reset parity
ps2_kbd_parity <= 1'b1;
// start transmitter
ps2_kbd_tx_state <= 4'd1;
// put start bit on data line
ps2_kbd_data <= 1'b0; // start bit is 0
end
end else begin
// transmission of 8 data bits
if((ps2_kbd_tx_state >= 1)&&(ps2_kbd_tx_state < 9)) begin
ps2_kbd_data <= ps2_kbd_tx_byte[0]; // data bits
ps2_kbd_tx_byte[6:0] <= ps2_kbd_tx_byte[7:1]; // shift down
if(ps2_kbd_tx_byte[0])
ps2_kbd_parity <= !ps2_kbd_parity;
end
// transmission of parity
if(ps2_kbd_tx_state == 9)
ps2_kbd_data <= ps2_kbd_parity;
// transmission of stop bit
if(ps2_kbd_tx_state == 10)
ps2_kbd_data <= 1'b1; // stop bit is 1
// advance state machine
if(ps2_kbd_tx_state < 11)
ps2_kbd_tx_state <= ps2_kbd_tx_state + 4'd1;
else
ps2_kbd_tx_state <= 4'd0;
end
end
// mouse
reg [7:0] ps2_mouse_fifo [(2**PS2_FIFO_BITS)-1:0];
reg [PS2_FIFO_BITS-1:0] ps2_mouse_wptr;
reg [PS2_FIFO_BITS-1:0] ps2_mouse_rptr;
// ps2 transmitter state machine
reg [3:0] ps2_mouse_tx_state;
reg [7:0] ps2_mouse_tx_byte;
reg ps2_mouse_parity;
assign ps2_mouse_clk = ps2_clk || (ps2_mouse_tx_state == 0);
// ps2 transmitter
// Takes a byte from the FIFO and sends it in a ps2 compliant serial format.
reg ps2_mouse_r_inc;
always@(posedge ps2_clk) begin
ps2_mouse_r_inc <= 1'b0;
if(ps2_mouse_r_inc)
ps2_mouse_rptr <= ps2_mouse_rptr + 1;
// transmitter is idle?
if(ps2_mouse_tx_state == 0) begin
// data in fifo present?
if(ps2_mouse_wptr != ps2_mouse_rptr) begin
// load tx register from fifo
ps2_mouse_tx_byte <= ps2_mouse_fifo[ps2_mouse_rptr];
ps2_mouse_r_inc <= 1'b1;
// reset parity
ps2_mouse_parity <= 1'b1;
// start transmitter
ps2_mouse_tx_state <= 4'd1;
// put start bit on data line
ps2_mouse_data <= 1'b0; // start bit is 0
end
end else begin
// transmission of 8 data bits
if((ps2_mouse_tx_state >= 1)&&(ps2_mouse_tx_state < 9)) begin
ps2_mouse_data <= ps2_mouse_tx_byte[0]; // data bits
ps2_mouse_tx_byte[6:0] <= ps2_mouse_tx_byte[7:1]; // shift down
if(ps2_mouse_tx_byte[0])
ps2_mouse_parity <= !ps2_mouse_parity;
end
// transmission of parity
if(ps2_mouse_tx_state == 9)
ps2_mouse_data <= ps2_mouse_parity;
// transmission of stop bit
if(ps2_mouse_tx_state == 10)
ps2_mouse_data <= 1'b1; // stop bit is 1
// advance state machine
if(ps2_mouse_tx_state < 11)
ps2_mouse_tx_state <= ps2_mouse_tx_state + 4'd1;
else
ps2_mouse_tx_state <= 4'd0;
end
end
// fifo to receive serial data from core to be forwarded to io controller
// 16 byte fifo to store serial bytes
localparam SERIAL_OUT_FIFO_BITS = 6;
reg [7:0] serial_out_fifo [(2**SERIAL_OUT_FIFO_BITS)-1:0];
reg [SERIAL_OUT_FIFO_BITS-1:0] serial_out_wptr;
reg [SERIAL_OUT_FIFO_BITS-1:0] serial_out_rptr;
wire serial_out_data_available = serial_out_wptr != serial_out_rptr;
wire [7:0] serial_out_byte = serial_out_fifo[serial_out_rptr] /* synthesis keep */;
wire [7:0] serial_out_status = { 7'b1000000, serial_out_data_available};
// status[0] is reset signal from io controller and is thus used to flush
// the fifo
always @(posedge serial_strobe or posedge status[0]) begin
if(status[0] == 1) begin
serial_out_wptr <= 0;
end else begin
serial_out_fifo[serial_out_wptr] <= serial_data;
serial_out_wptr <= serial_out_wptr + 1;
end
end
always@(negedge spi_sck or posedge status[0]) begin
if(status[0] == 1) begin
serial_out_rptr <= 0;
end else begin
if((byte_cnt != 0) && (cmd == 8'h1b)) begin
// read last bit -> advance read pointer
if((bit_cnt == 7) && !byte_cnt[0] && serial_out_data_available)
serial_out_rptr <= serial_out_rptr + 1;
end
end
end
// SPI receiver
always@(posedge spi_sck or posedge SPI_SS_IO) begin
if(SPI_SS_IO == 1) begin
bit_cnt <= 3'd0;
byte_cnt <= 8'd0;
sd_ack <= 1'b0;
sd_dout_strobe <= 1'b0;
sd_din_strobe <= 1'b0;
sd_change <= 1'b0;
end else begin
sd_dout_strobe <= 1'b0;
sd_din_strobe <= 1'b0;
if(bit_cnt != 7)
sbuf[6:0] <= { sbuf[5:0], SPI_MOSI };
bit_cnt <= bit_cnt + 3'd1;
if((bit_cnt == 7)&&(byte_cnt != 8'd255))
byte_cnt <= byte_cnt + 8'd1;
// finished reading command byte
if(bit_cnt == 7) begin
if(byte_cnt == 0) begin
cmd <= { sbuf, SPI_MOSI};
// fetch first byte when sectore FPGA->IO command has been seen
if({ sbuf, SPI_MOSI} == 8'h18)
sd_din_strobe <= 1'b1;
if(({ sbuf, SPI_MOSI} == 8'h17) || ({ sbuf, SPI_MOSI} == 8'h18))
sd_ack <= 1'b1;
end else begin
// buttons and switches
if(cmd == 8'h01)
but_sw <= { sbuf, SPI_MOSI };
if(cmd == 8'h02)
joystick_0 <= { sbuf, SPI_MOSI };
if(cmd == 8'h03)
joystick_1 <= { sbuf, SPI_MOSI };
if(cmd == 8'h04) begin
// store incoming ps2 mouse bytes
ps2_mouse_fifo[ps2_mouse_wptr] <= { sbuf, SPI_MOSI };
ps2_mouse_wptr <= ps2_mouse_wptr + 1;
end
if(cmd == 8'h05) begin
// store incoming ps2 keyboard bytes
ps2_kbd_fifo[ps2_kbd_wptr] <= { sbuf, SPI_MOSI };
ps2_kbd_wptr <= ps2_kbd_wptr + 1;
end
if(cmd == 8'h15)
status <= { sbuf[6:0], SPI_MOSI };
// send sector IO -> FPGA
if(cmd == 8'h17) begin
// flag that download begins
sd_dout_strobe <= 1'b1;
end
// send sector FPGA -> IO
if(cmd == 8'h18)
sd_din_strobe <= 1'b1;
// send SD config IO -> FPGA
if(cmd == 8'h19) begin
// flag that download begins
// sd card knows data is config if sd_dout_strobe is asserted
// with sd_ack still being inactive (low)
sd_dout_strobe <= 1'b1;
end
// joystick analog
if(cmd == 8'h1a) begin
// first byte is joystick indes
if(byte_cnt == 1)
stick_idx <= { sbuf[1:0], SPI_MOSI };
else if(byte_cnt == 2) begin
// second byte is x axis
if(stick_idx == 0)
joystick_analog_0[15:8] <= { sbuf, SPI_MOSI };
else if(stick_idx == 1)
joystick_analog_1[15:8] <= { sbuf, SPI_MOSI };
end else if(byte_cnt == 3) begin
// third byte is y axis
if(stick_idx == 0)
joystick_analog_0[7:0] <= { sbuf, SPI_MOSI };
else if(stick_idx == 1)
joystick_analog_1[7:0] <= { sbuf, SPI_MOSI };
end
end
// set sd card status. The fact that this register is being
// set by the arm controller indicates a possible disk change
if(cmd == 8'h1c)
sd_change <= 1'b1;
end
end
end
end
endmodule

345
cores/ql/zx8301.v Normal file
View File

@@ -0,0 +1,345 @@
//
// zx8301.v
//
// ZX8301 ULA for Sinclair QL for the MiST
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module zx8301 (
input reset,
// clock
input clk_vga, // 21 Mhz VGA pixel clock
input clk_video, // 10.5 MHz QL pixel clock
input video_cycle,
// config options
input ntsc,
input scandoubler,
input scanlines,
// CPU interface to access $18063
input clk_bus,
input cpu_cs,
input [7:0] cpu_data,
// sdram interface
output reg [18:0] addr,
output rd,
input [15:0] din,
// signal telling mdv emulation that it may use the video
output reg mdv_men,
// VIDEO output
output hs,
output reg vs,
output [5:0] r,
output [5:0] g,
output [5:0] b
);
assign rd = me;
/* ----------------------------------------------------------------- */
/* -------------------------- CPU register ------------------------- */
/* ----------------------------------------------------------------- */
// [6] -> NTSC?
wire membase = mc_stat[7]; // 0 = $20000, 1 = $28000
wire mode = mc_stat[3]; // 0 = 512*256*2bpp, 1=256*256*4bpp
wire blank = mc_stat[1]; // 0 = normal video, 1 = blanked video
reg [7:0] mc_stat;
always @(negedge clk_bus) begin
if(reset)
mc_stat <= 8'h00;
else if(cpu_cs)
mc_stat <= cpu_data;
end
/* ----------------------------------------------------------------- */
/* ---------------------- video timing values ---------------------- */
/* ----------------------------------------------------------------- */
// PAL video parameters
parameter H = 512; // width of visible area
//parameter PAL_HFP = 112; // unused time before hsync
//parameter PAL_HSW = 96; // width of hsync
//parameter PAL_HBP = 176; // unused time after hsync
//// PAL total: 896
//parameter NTSC_HFP = 112; // unused time before hsync
//parameter NTSC_HSW = 88; // width of hsync
//parameter NTSC_HBP = 176; // unused time after hsync
//// NTSC total: 888
parameter PAL_HFP = 34; // unused time before hsync
parameter PAL_HSW = 72; // width of hsync
parameter PAL_HBP = 54; // unused time after hsync
// PAL total: 672
parameter NTSC_HFP = 34; // unused time before hsync
parameter NTSC_HSW = 64; // width of hsync
parameter NTSC_HBP = 54; // unused time after hsync
// NTSC total: 664
parameter V = 256; // height of visible area
parameter PAL_VFP = 15; // unused time before vsync
parameter PAL_VSW = 6; // width of vsync
parameter PAL_VBP = 35; // unused time after vsync
// PAL total: 312
parameter NTSC_VFP = 2; // unused time before vsync
parameter NTSC_VSW = 2; // width of vsync
parameter NTSC_VBP = 2; // unused time after vsync
// NTSC total: 262
// both counters count from the begin of the visibla area
reg [9:0] h_cnt; // horizontal pixel counter
reg [9:0] sd_h_cnt; // scandoubler horizontal pixel counter
reg [9:0] v_cnt; // vertical pixel counter
// swtich between ntsc and pal values
wire [9:0] hfp = ntsc?NTSC_HFP:PAL_HFP;
wire [9:0] hsw = ntsc?NTSC_HSW:PAL_HSW;
wire [9:0] hbp = ntsc?NTSC_HBP:PAL_HBP;
wire [9:0] vfp = ntsc?NTSC_VFP:PAL_VFP;
wire [9:0] vsw = ntsc?NTSC_VSW:PAL_VSW;
wire [9:0] vbp = ntsc?NTSC_VBP:PAL_VBP;
// QL colors
localparam BLACK = 3'b000;
localparam BLUE = 3'b001;
localparam GREEN = 3'b010;
localparam CYAN = 3'b011;
localparam RED = 3'b100;
localparam MAGENTA = 3'b101;
localparam YELLOW = 3'b110;
localparam WHITE = 3'b111;
/* ----------------------------------------------------------------- */
/* ------------------------ VGA scandoubler ------------------------ */
/* ----------------------------------------------------------------- */
// scan doubler buffer can hold two lines
reg [2:0] sd_buffer [1023:0];
reg sd_scanline;
reg sd_toggle;
// the scandoubler alternates between two buffers
// one is being written while the other one is being output
always @(posedge clk_video)
if(h_cnt == H+hfp+hsw+hbp-1)
sd_toggle = !sd_toggle;
// scandoubler horizontal pixel counter
always@(posedge clk_vga) begin
// synchronize to
if((!clk_video && (h_cnt==H+hfp+hsw+hbp-1)) ||
(sd_h_cnt==H+hfp+hsw+hbp-1)) sd_h_cnt <= 0;
else sd_h_cnt <= sd_h_cnt + 1;
// generate negative hsync signal
if(sd_h_cnt == H+hfp) sd_hs <= 1'b0;
if(sd_h_cnt == H+hfp+hsw) begin
sd_hs <= 1'b1;
sd_scanline <= !sd_scanline;
end
if(v_cnt == V+vfp+vsw+vbp-1)
sd_scanline <= 1'b0;
end
// write to scandoubler buffer at QL pixel clock
always @(posedge clk_video) begin
if(h_cnt < H) begin
if(v_cnt < V)
sd_buffer[{sd_toggle, h_cnt[8:0]}] <= mode?pixel_color_4bpp:pixel_color_2bpp;
else
sd_buffer[{sd_toggle, h_cnt[8:0]}] <= 3'b000;
end
end
// read from scandoubler buffer at twice QL pixel clock
reg [2:0] sd_pixel;
reg [2:0] sd_buffer_out;
always @(posedge clk_vga) begin
sd_buffer_out <= sd_buffer[{~sd_toggle, sd_h_cnt[8:0]}];
if((sd_h_cnt > 1) && (sd_h_cnt <= H)) sd_pixel <= sd_buffer_out;
else sd_pixel <= 3'b000;
end
// sd_pixel <= (sd_h_cnt < H)?sd_buffer[{~sd_toggle, sd_h_cnt[8:0]}]:3'b000;
// sd_buffer_out <= sd_buffer[{~sd_toggle, sd_h_cnt[8:0]}];
/* ----------------------------------------------------------------- */
/* -------------------- video timing generation -------------------- */
/* ----------------------------------------------------------------- */
// toggle between scandoubler hsync and ql hsync
reg sd_hs, ql_hs;
assign hs = scandoubler?sd_hs:ql_hs;
reg video_cycleD;
reg [2:0] video_cycle_cnt;
// mode 8 supports hardware flashing
reg flash_state;
reg [5:0] flash_cnt;
always @(posedge vs) begin
if(flash_cnt == 25) begin
flash_cnt <= 6'd0;
flash_state <= !flash_state;
end else
flash_cnt <= flash_cnt + 6'd1;
end
// horizontal pixel counter
always@(posedge clk_video) begin
// video cycle counter runs at pixel clock and
// synchronous to video_cycle
video_cycleD <= video_cycle;
if(video_cycle && !video_cycleD)
video_cycle_cnt <= 3'd0;
else
video_cycle_cnt <= video_cycle_cnt + 3'd1;
// make sure h counter runs synchronous to bus_cycle
if(h_cnt==H+hfp+hsw+hbp-1) begin
if(video_cycle_cnt == 6)
h_cnt <= 0;
end else
h_cnt <= h_cnt + 1;
// generate negative hsync signal
if(h_cnt == H+hfp) ql_hs <= 1'b0;
if(h_cnt == H+hfp+hsw) ql_hs <= 1'b1;
end
// veritical pixel counter
always@(posedge clk_video) begin
// the vertical counter is processed at the begin of each hsync
if(h_cnt == H+hfp) begin
if(v_cnt==V+vfp+vsw+vbp-1) v_cnt <= 0;
else v_cnt <= v_cnt + 1;
// generate positive vsync signal
if(v_cnt == V+vfp) vs <= 1'b1;
if(v_cnt == V+vfp+vsw) vs <= 1'b0;
end
end
reg [15:0] video_din;
reg [15:0] video_word;
reg [2:0] ql_pixel;
always @(negedge video_cycle)
video_din <= din;
// memory enable is 16 pixels ahead of display
reg meV, me;
always@(posedge clk_video) begin
// the verical "memory enable" changes
if(h_cnt == H+hfp+hsw+hbp-1-9) begin
if(v_cnt == 0) meV <= 1'b1;
if(v_cnt == V) meV <= 1'b0;
end
if(meV) begin
if(h_cnt == H+hfp+hsw+hbp-1-8) me <= 1'b1;
if(h_cnt == H-1-8) me <= 1'b0;
end
// mdv emulation may use the video bus cycle to read
// data whenever video is not using the bus
if(h_cnt == H-1) mdv_men <= 1'b1;
if(h_cnt == H+31) mdv_men <= 1'b0;
end
// 2BPP: G0,G1,G2,G3,G4,G5,G6,G7 R0,R1,R2,R3,R4,R5,R6,R7
wire [1:0] pixel_code_2bpp = {video_word[15], video_word[7]};
wire [2:0] pixel_color_2bpp =
(pixel_code_2bpp == 0)?BLACK: // 0=black
(pixel_code_2bpp == 1)?RED: // 1=red
(pixel_code_2bpp == 2)?GREEN: // 2=green
WHITE; // 3=white
// 4BPP: G0,F0,G1,F1,G2,F2,G3,F3 R0,B0,R1,B1,R2,B2,R3,B3
wire [2:0] pixel_code_4bpp = {video_word[15], video_word[7:6]};
wire pixel_flash_toggle = video_word[14];
wire [2:0] pixel_color_4bpp =
(flash_reg && flash_state)?flash_col: // flash to saved color
(pixel_code_4bpp == 0)?BLACK: // 0=black
(pixel_code_4bpp == 1)?BLUE: // 1=blue
(pixel_code_4bpp == 2)?RED: // 2=red
(pixel_code_4bpp == 3)?MAGENTA: // 3=magenta
(pixel_code_4bpp == 4)?GREEN: // 4=green
(pixel_code_4bpp == 5)?CYAN: // 5=cyan
(pixel_code_4bpp == 6)?YELLOW: // 6=yellow
WHITE; // 7=white
reg flash_reg;
reg [2:0] flash_col;
always@(posedge clk_video) begin
if(h_cnt == H+1)
flash_reg <= 1'b0; // reset flash state at the begin of each line
if((v_cnt == V+1) && (h_cnt == H+1))
addr <= membase?19'h14000:19'h10000; // word! address
if((me)&&(h_cnt[2:0] == 3'b111)) begin
addr <= addr + 19'd1;
video_word <= video_din;
end else begin
if(mode) begin
// 4bpp: shift rgbf every second pixel clock
if(h_cnt[0])
video_word <= { video_word[13:8], 2'b00, video_word[5:0], 2'b00 };
end else
// 2bpp, shift green byte and red byte up one pixel
video_word <= { video_word[14:8], 1'b0, video_word[6:0], 1'b0 };
end
// visible area?
if((v_cnt < V) && (h_cnt < H)) begin
if(mode) begin
ql_pixel <= pixel_color_4bpp;
// change state of flash_reg if flasg bit in current pixel is set
// do this in the second half of the pixel so it's valid afterwards for the
// next pixels. the current pixel directly honours pixel_flash_toggle
if(h_cnt[0] && pixel_flash_toggle) begin
flash_reg <= !flash_reg;
flash_col <= pixel_color_4bpp;
end
end else
ql_pixel <= pixel_color_2bpp;
end else
// black pixel outside active area
ql_pixel <= 4'h0;
end
wire [2:0] pixel = blank?3'b000:scandoubler?sd_pixel:ql_pixel;
// the current line is a scanline if the scandoubler is being used, if
// scanlines are emnabled and if it's a scanline
wire is_scanline = scandoubler && scanlines && sd_scanline;
assign r = {(is_scanline?1'b0:pixel[2]), {5{pixel[2]}}};
assign g = {(is_scanline?1'b0:pixel[1]), {5{pixel[1]}}};
assign b = {(is_scanline?1'b0:pixel[0]), {5{pixel[0]}}};
endmodule

244
cores/ql/zx8302.v Normal file
View File

@@ -0,0 +1,244 @@
//
// zx8302.v
//
// ZX8302 for Sinclair QL for the MiST
// https://github.com/mist-devel
//
// Copyright (c) 2015 Till Harbaum <till@harbaum.org>
//
// This source file is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This source file is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
module zx8302 (
input clk, // 21 mhz
input reset,
input init,
// interrupts
output [2:0] ipl,
// sdram interface for microdrive emulation
output [24:0] mdv_addr,
input [15:0] mdv_din,
output mdv_read,
input mdv_men,
input video_cycle,
// interface to watch MDV cartridge upload
input [24:0] mdv_dl_addr,
input mdv_download,
output led,
// vertical synv
input vs,
input ps2_kbd_clk,
input ps2_kbd_data,
// bus interface
input clk_bus,
input cpu_sel,
input cpu_wr,
input [1:0] cpu_addr, // a[5,1]
input [1:0] cpu_ds,
input [15:0] cpu_din,
output [15:0] cpu_dout
);
// ---------------------------------------------------------------------------------
// ----------------------------- CPU register write --------------------------------
// ---------------------------------------------------------------------------------
reg [7:0] mctrl;
reg ipc_bit_strobe;
wire ipc_reply_bit;
// cpu is writing io registers
always @(negedge clk_bus) begin
irq_ack <= 5'd0;
ipc_bit_strobe <= 1'b0;
// cpu writes to 0x18XXX area
if(cpu_sel && cpu_wr) begin
// even addresses have lds=0 and use the lower 8 data bus bits
if(!cpu_ds[1]) begin
// cpu writes microdrive control register
if(cpu_addr == 2'b10)
mctrl <= cpu_din[15:8];
end
// odd addresses have lds=0 and use the lower 8 data bus bits
if(!cpu_ds[0]) begin
// 18003 - IPCWR
// (host sends a single bit to ipc)
if(cpu_addr == 2'b01) begin
// data is ----XEDS
// S = start bit (should be 0)
// D = data bit (0/1)
// E = stop bit (should be 1)
// X = extra stopbit (should be 1)
// QL will always write 11D0 here with one exception: At startup it sends
// one single bit through the start bit by writing 0001. Thus we ignore
// anything which doesn't match the 11D0 pattern
if((cpu_din[3:2]== 2'b11)&&(cpu_din[0]==1'b0))
ipc_bit_strobe <= 1'b1;
end
// cpu writes interrupt register
if(cpu_addr == 2'b10) begin
irq_mask <= cpu_din[7:5];
irq_ack <= cpu_din[4:0];
end
end
end
end
// ---------------------------------------------------------------------------------
// ----------------------------- CPU register read ---------------------------------
// ---------------------------------------------------------------------------------
// status register read
// bit 0 Network port
// bit 1 Transmit buffer full
// bit 2 Receive buffer full
// bit 3 Microdrive GAP
// bit 4 SER1 DTR
// bit 5 SER2 CTS
// bit 6 IPC busy
// bit 7 COMDATA
wire [7:0] io_status = { ipc_reply_bit, ipc_busy, 2'b00,
mdv_gap, mdv_rx_ready, mdv_tx_empty, 1'b0 };
assign cpu_dout =
// 18000/18001 and 18002/18003
(cpu_addr == 2'b00)?rtc[46:31]:
(cpu_addr == 2'b01)?rtc[30:15]:
// 18020/18021 and 18022/18023
(cpu_addr == 2'b10)?{io_status, irq_pending}:
(cpu_addr == 2'b11)?{mdv_byte, mdv_byte}:
16'h0000;
// ---------------------------------------------------------------------------------
// -------------------------------------- IPC --------------------------------------
// ---------------------------------------------------------------------------------
ipc ipc (
.reset ( reset ),
.clk_bus ( clk_bus ),
.ipc_bit_strobe ( ipc_bit_strobe ),
.ipc_bit ( cpu_din[1] ),
.ipc_reply_bit ( ipc_reply_bit ),
.ipc_busy ( ipc_busy ),
.ps2_kbd_clk ( ps2_kbd_clk ),
.ps2_kbd_data ( ps2_kbd_data )
);
// ---------------------------------------------------------------------------------
// -------------------------------------- IRQs -------------------------------------
// ---------------------------------------------------------------------------------
wire [7:0] irq_pending = {1'b0, (mdv_sel == 0), clk64k,
1'b0, vsync_irq, 1'b0, 1'b0, gap_irq };
reg [2:0] irq_mask;
reg [4:0] irq_ack;
// any pending irq raises ipl to 2
assign ipl = (irq_pending[4:0] == 0)?3'b111:3'b101;
// vsync irq is set whenever vsync rises
reg vsync_irq;
wire vsync_irq_reset = reset || irq_ack[3];
always @(posedge vs or posedge vsync_irq_reset) begin
if(vsync_irq_reset) vsync_irq <= 1'b0;
else vsync_irq <= 1'b1;
end
// toggling the mask will also trigger irqs ...
wire gap_irq_in = mdv_gap && irq_mask[0];
reg gap_irq;
wire gap_irq_reset = reset || irq_ack[0];
always @(posedge gap_irq_in or posedge gap_irq_reset) begin
if(gap_irq_reset) gap_irq <= 1'b0;
else gap_irq <= 1'b1;
end
// ---------------------------------------------------------------------------------
// ----------------------------------- microdrive ----------------------------------
// ---------------------------------------------------------------------------------
wire mdv_gap;
wire mdv_tx_empty;
wire mdv_rx_ready;
wire [7:0] mdv_byte;
assign led = !mdv_sel[0];
mdv mdv (
.clk ( clk ),
.reset ( init ),
.sel ( mdv_sel[0] ),
// control bits
.gap ( mdv_gap ),
.tx_empty ( mdv_tx_empty ),
.rx_ready ( mdv_rx_ready ),
.dout ( mdv_byte ),
.download ( mdv_download ),
.dl_addr ( mdv_dl_addr ),
// ram interface to read image
.mem_ena ( mdv_men ),
.mem_cycle( video_cycle ),
.mem_clk ( clk_bus ),
.mem_addr ( mdv_addr ),
.mem_read ( mdv_read ),
.mem_din ( mdv_din )
);
// the microdrive control register mctrl generates the drive selection
reg [7:0] mdv_sel;
always @(negedge mctrl[1])
mdv_sel <= { mdv_sel[6:0], mctrl[0] };
// ---------------------------------------------------------------------------------
// -------------------------------------- RTC --------------------------------------
// ---------------------------------------------------------------------------------
// PLL for the real time clock (rtc)
reg [46:0] rtc;
always @(posedge clk64k)
rtc <= rtc + 47'd1;
wire clk64k;
pll_rtc pll_rtc (
.inclk0(clk),
.c0(clk64k) // 65536Hz
);
endmodule