377 lines
11 KiB
VHDL
Executable File
377 lines
11 KiB
VHDL
Executable File
library IEEE;
|
|
use IEEE.std_logic_1164.ALL;
|
|
use IEEE.std_logic_ARITH.ALL;
|
|
use IEEE.std_logic_UNSIGNED.ALL;
|
|
--
|
|
-- Copyright (C) 2007, Peter C. Wallace, Mesa Electronics
|
|
-- http://www.mesanet.com
|
|
--
|
|
-- This program is is licensed under a disjunctive dual license giving you
|
|
-- the choice of one of the two following sets of free software/open source
|
|
-- licensing terms:
|
|
--
|
|
-- * GNU General Public License (GPL), version 2.0 or later
|
|
-- * 3-clause BSD License
|
|
--
|
|
--
|
|
-- The GNU GPL License:
|
|
--
|
|
-- This program is free software; you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as published by
|
|
-- the Free Software Foundation; either version 2 of the License, or
|
|
-- (at your option) any later version.
|
|
--
|
|
-- This program is distributed in the hope that it will be useful,
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-- GNU General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License
|
|
-- along with this program; if not, write to the Free Software
|
|
-- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
--
|
|
--
|
|
-- The 3-clause BSD License:
|
|
--
|
|
-- Redistribution and use in source and binary 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 binary 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 Mesa Electronics nor the names of its
|
|
-- contributors may be used to endorse or promote products
|
|
-- derived from this software without specific prior written
|
|
-- permission.
|
|
--
|
|
--
|
|
-- Disclaimer:
|
|
--
|
|
-- 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
|
|
-- COPYRIGHT OWNER 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.
|
|
--
|
|
|
|
entity qcounter is
|
|
generic (
|
|
buswidth : integer := 32
|
|
);
|
|
port (
|
|
obus: out std_logic_vector (buswidth-1 downto 0);
|
|
ibus: in std_logic_vector (buswidth-1 downto 0);
|
|
quada: in std_logic;
|
|
quadb: in std_logic;
|
|
index: in std_logic;
|
|
loadccr: in std_logic;
|
|
readccr: in std_logic;
|
|
readcount: in std_logic;
|
|
countclear: in std_logic;
|
|
timestamp: in std_logic_vector (15 downto 0);
|
|
indexmask: in std_logic;
|
|
filterrate: in std_logic;
|
|
clk: in std_logic
|
|
);
|
|
end qcounter;
|
|
|
|
architecture behavioral of qcounter is
|
|
|
|
signal count: std_logic_vector (15 downto 0);
|
|
signal up: std_logic;
|
|
signal down: std_logic;
|
|
signal countlatch: std_logic_vector (15 downto 0);
|
|
signal timestamplatch: std_logic_vector (15 downto 0);
|
|
signal quadadel: std_logic;
|
|
signal quada1: std_logic;
|
|
signal quada2: std_logic;
|
|
signal quadacnt: std_logic_vector (3 downto 0);
|
|
signal quadafilt: std_logic;
|
|
signal quadbdel: std_logic;
|
|
signal quadb1: std_logic;
|
|
signal quadb2: std_logic;
|
|
signal quadbcnt: std_logic_vector (3 downto 0);
|
|
signal quadbfilt: std_logic;
|
|
signal indexdel: std_logic;
|
|
signal index1: std_logic;
|
|
signal index2: std_logic;
|
|
signal indexdet: std_logic;
|
|
signal indexcnt: std_logic_vector (3 downto 0);
|
|
signal indexfilt: std_logic;
|
|
signal qcountup: std_logic;
|
|
signal qcountdown: std_logic;
|
|
signal udcountup: std_logic;
|
|
signal udcountdown: std_logic;
|
|
signal doclear: std_logic;
|
|
signal clearonindex: std_logic; -- ccr register bits...
|
|
signal latchonindex:std_logic;
|
|
signal justonce: std_logic;
|
|
signal abgateindex: std_logic;
|
|
signal indexsrc: std_logic;
|
|
signal quadfilter: std_logic;
|
|
signal countermode: std_logic;
|
|
signal quaderror: std_logic;
|
|
signal indexpol: std_logic;
|
|
signal fixedindexmask: std_logic;
|
|
signal indexmaskpol: std_logic;
|
|
signal useindexmask: std_logic;
|
|
signal abmaskpol: std_logic;
|
|
signal flimit: std_logic_vector(3 downto 0);
|
|
|
|
|
|
begin
|
|
aqcounter: process (clk,abgateindex, indexpol, indexdel, abmaskpol,
|
|
quadadel, quadbdel, indexmaskpol, indexmask,
|
|
quadfilter, countermode, doclear, quada2,
|
|
quada1, quadb2, quadb1, index1, index2,
|
|
useindexmask, readcount, timestamplatch, count,
|
|
readccr, countlatch, quaderror, justonce, qcountdown,
|
|
clearonindex, latchonindex, fixedindexmask, qcountup,
|
|
udcountup,udcountdown)
|
|
|
|
begin
|
|
-- new index logic 02/09/2006 PCW
|
|
|
|
if abgateindex = '0' then -- not gated by A,B
|
|
if indexpol = '1' then
|
|
indexsrc <= indexdel;
|
|
else
|
|
indexsrc <= not indexdel;
|
|
end if;
|
|
else -- gated by A,B
|
|
if indexpol = '1' then -- normal index
|
|
if abmaskpol = '1' then
|
|
indexsrc <= quadadel and quadbdel and indexdel; -- enable by A,B high
|
|
else
|
|
indexsrc <= (not (quadadel or quadbdel)) and indexdel; -- enable by A,B low
|
|
end if;
|
|
else -- inverted index
|
|
if abmaskpol = '1' then
|
|
indexsrc <= quadadel and quadbdel and (not indexdel); -- enable by A,B high
|
|
else
|
|
indexsrc <= (not (quadadel or quadbdel)) and (not indexdel);-- enable by A,B low
|
|
end if;
|
|
end if;
|
|
end if;
|
|
|
|
if indexmaskpol = '1' then
|
|
fixedindexmask <= indexmask;
|
|
else
|
|
fixedindexmask <= not indexmask;
|
|
end if;
|
|
|
|
if quadfilter = '1' then
|
|
flimit <= "1111";
|
|
else
|
|
flimit <= "0011";
|
|
end if;
|
|
if countermode = '0' and doclear = '0' and (
|
|
(quada2 = '0' and quada1 = '1' and quadb2 = '0' and quadb1 = '0') or
|
|
(quada2 = '0' and quada1 = '0' and quadb2 = '1' and quadb1 = '0') or
|
|
(quada2 = '1' and quada1 = '1' and quadb2 = '0' and quadb1 = '1') or
|
|
(quada2 = '1' and quada1 = '0' and quadb2 = '1' and quadb1 = '1')) then
|
|
qcountup <= '1';
|
|
else
|
|
qcountup <= '0';
|
|
end if;
|
|
|
|
if (countermode = '1' and doclear = '0' and
|
|
quadb2 = '1' and quada2 = '0' and quada1 = '1') then -- up down mode: count up on rising edge of A when B is high
|
|
udcountup <= '1';
|
|
else
|
|
udcountup <= '0';
|
|
end if;
|
|
|
|
if countermode = '0' and doclear = '0' and (
|
|
(quada2 = '0' and quada1 = '0' and quadb2 = '0' and quadb1 = '1') or
|
|
(quada2 = '0' and quada1 = '1' and quadb2 = '1' and quadb1 = '1') or
|
|
(quada2 = '1' and quada1 = '0' and quadb2 = '0' and quadb1 = '0') or
|
|
(quada2 = '1' and quada1 = '1' and quadb2 = '1' and quadb1 = '0')) then
|
|
qcountdown <= '1';
|
|
else
|
|
qcountdown <= '0';
|
|
end if;
|
|
|
|
if (countermode = '1' and doclear = '0' and
|
|
quadb2 = '0' and quada2 = '0' and quada1 = '1') then
|
|
udcountdown <= '1';
|
|
else
|
|
udcountdown <= '0';
|
|
end if;
|
|
|
|
if rising_edge(clk) then
|
|
|
|
|
|
quadadel <= quada;
|
|
quada1 <= quadafilt;
|
|
quada2 <= quada1;
|
|
|
|
quadbdel <= quadb;
|
|
quadb1 <= quadbfilt;
|
|
quadb2 <= quadb1;
|
|
|
|
indexdel <= index;
|
|
index1 <= indexfilt;
|
|
index2 <= index1;
|
|
|
|
|
|
if filterrate = '1' then
|
|
|
|
-- deadended counter for A input filter --
|
|
if (quadadel = '1') and (quadacnt < flimit) then
|
|
quadacnt <= quadacnt + 1;
|
|
end if;
|
|
if (quadadel = '0') and (quadacnt /= 0) then
|
|
quadacnt <= quadacnt -1;
|
|
end if;
|
|
if quadacnt >= flimit then
|
|
quadafilt<= '1';
|
|
end if;
|
|
if quadacnt = 0 then
|
|
quadafilt<= '0';
|
|
end if;
|
|
|
|
-- deadended counter for A input filter --
|
|
if (quadbdel = '1') and (quadbcnt < flimit ) then
|
|
quadbcnt <= quadbcnt + 1;
|
|
end if;
|
|
if (quadbdel = '0') and (quadbcnt /= 0) then
|
|
quadbcnt <= quadbcnt -1;
|
|
end if;
|
|
if quadbcnt >= flimit then
|
|
quadbfilt<= '1';
|
|
end if;
|
|
if quadbcnt = 0 then
|
|
quadbfilt <= '0';
|
|
end if;
|
|
|
|
-- deadended counter for index input filter --
|
|
if (indexsrc = '1') and (indexcnt < flimit ) then
|
|
indexcnt <= indexcnt + 1;
|
|
end if;
|
|
if (indexsrc = '0') and (indexcnt /= 0) then
|
|
indexcnt <= indexcnt -1;
|
|
end if;
|
|
if indexcnt >= flimit then
|
|
indexfilt<= '1';
|
|
end if;
|
|
if indexcnt = 0 then
|
|
indexfilt<= '0';
|
|
end if;
|
|
end if;
|
|
|
|
if (countclear = '1') or
|
|
((clearonindex = '1') and (indexdet = '1')) then -- rising edge of conditioned index
|
|
doclear <= '1';
|
|
if justonce = '1' then
|
|
clearonindex <= '0';
|
|
end if;
|
|
else
|
|
doclear <= '0';
|
|
end if;
|
|
|
|
if ((latchonindex = '1') and (indexdet = '1') ) then -- rising edge of conditioned index
|
|
countlatch <= count;
|
|
if justonce = '1' then
|
|
latchonindex <= '0';
|
|
end if;
|
|
end if;
|
|
|
|
|
|
if countermode = '0' and (
|
|
(quada2 = '0' and quada1 = '1' and quadb2 = '0' and quadb1 = '1') or -- any time both a,b change at same time
|
|
(quada2 = '1' and quada1 = '0' and quadb2 = '1' and quadb1 = '0') or -- indicates a quadrature count error
|
|
(quada2 = '0' and quada1 = '1' and quadb2 = '1' and quadb1 = '0') or
|
|
(quada2 = '1' and quada1 = '0' and quadb2 = '0' and quadb1 = '1')) then
|
|
quaderror <= '1';
|
|
end if;
|
|
|
|
if up /= down then
|
|
timestamplatch <= timestamp; -- time stamp whenever we count
|
|
if up = '1' then
|
|
count <= count + 1;
|
|
else
|
|
count <= count - 1;
|
|
end if;
|
|
end if;
|
|
|
|
if doclear = '1' then
|
|
count <= x"0000";
|
|
end if;
|
|
|
|
if loadccr = '1' then
|
|
if ibus(15) = '1' then
|
|
quaderror <= '0';
|
|
end if;
|
|
abmaskpol <= ibus(14);
|
|
-- latchonprobe (bit 13);
|
|
-- probepol (bit 12);
|
|
quadfilter <= ibus(11);
|
|
countermode <= ibus(10);
|
|
useindexmask <= ibus(9);
|
|
indexmaskpol <= ibus(8);
|
|
abgateindex <= ibus(7);
|
|
justonce <= ibus(6);
|
|
clearonindex <= ibus(5);
|
|
latchonindex <= ibus(4);
|
|
indexpol <= ibus(3);
|
|
end if;
|
|
end if; --(clock edge)
|
|
|
|
if (index1 = '1') and (index2 = '0') and ((fixedindexmask = '1') or (useindexmask = '0')) then
|
|
indexdet <= '1';
|
|
else
|
|
indexdet <= '0';
|
|
end if;
|
|
|
|
if (qcountup = '1' or udcountup = '1' ) and doclear = '0' then
|
|
up <= '1';
|
|
else
|
|
up <= '0';
|
|
end if;
|
|
|
|
if (qcountdown = '1' or udcountdown = '1' ) and doclear = '0' then
|
|
down <= '1';
|
|
else
|
|
down <= '0';
|
|
end if;
|
|
|
|
obus <= (others => 'Z');
|
|
|
|
if (readcount = '1') then
|
|
obus(31 downto 16) <= timestamplatch;
|
|
obus(15 downto 0) <= count;
|
|
end if;
|
|
if (readccr = '1') then
|
|
obus(31 downto 16) <= countlatch;
|
|
obus(15) <= quaderror;
|
|
obus(14) <= abmaskpol;
|
|
obus(11) <= quadfilter;
|
|
obus(10) <= countermode;
|
|
obus(9) <= useindexmask;
|
|
obus(8) <= indexmaskpol;
|
|
obus(7) <= abgateindex;
|
|
obus(6) <= justonce;
|
|
obus(5) <= clearonindex;
|
|
obus(4) <= latchonindex;
|
|
obus(3) <= indexpol;
|
|
obus(2) <= index1;
|
|
obus(1) <= quadb1;
|
|
obus(0) <= quada1;
|
|
end if;
|
|
end process;
|
|
end behavioral;
|