OpenCores
URL https://opencores.org/ocsvn/quadraturecount/quadraturecount/trunk

Subversion Repositories quadraturecount

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/trunk/QuadratureDecoder.vhd
0,0 → 1,196
library ieee;
use ieee.std_logic_1164.all;
 
-- c2003 Franks Development, LLC
-- http://www.franks-development.com
-- !This source is distributed under the terms & conditions specified at opencores.org
 
--How we 'talk' to the outside world:
entity QuadratureDecoderPorts is
port (
clock : in std_logic;
QuadA : in std_logic;
QuadB : in std_logic;
Direction : out std_logic;
CountEnable : out std_logic
);
end QuadratureDecoderPorts;
 
--What we 'do':
architecture QuadratureDecoder of QuadratureDecoderPorts is
 
--local 'variables' or 'registers'
 
--this runs our state machine: where are we in the decoding process?
--the following constants describe each state
--note that every possible state is not listed. the unused states
--are physically unreachable in a functioning quadratre device, given that the
--clock is fast enough to 'catch' each transition on the quadrature inputs
--LR means left-right, RL = left-right. Of course the two are reversed
--if the two quadratre inputs are switched.
signal state : std_logic_vector(3 downto 0);
constant Wait0 : std_logic_vector(3 downto 0) := "0000";
constant Wait1 : std_logic_vector(3 downto 0) := "0001";
constant Count0 : std_logic_vector(3 downto 0) := "0010";
constant Count1 : std_logic_vector(3 downto 0) := "0011";
constant LR1 : std_logic_vector(3 downto 0) := "1001";
constant LR2 : std_logic_vector(3 downto 0) := "1101";
constant LR3 : std_logic_vector(3 downto 0) := "0101";
constant RL1 : std_logic_vector(3 downto 0) := "0100";
constant RL2 : std_logic_vector(3 downto 0) := "1100";
constant RL3 : std_logic_vector(3 downto 0) := "1000";
--this is a temp where the two quadrature inputs are stored
signal Quad : std_logic_vector(1 downto 0);
 
--as a single quadrature count is made up of several states, and the decoder
--can remain in a given state indefinately (if the quadrature input
--device is not 'moving'), so we need these 'gate-ing' variables
--to keep us from counting on every clock when we sit idle in the
--'count' state; thusly, we just count on the first clock
--upon entering a 'count' state.
signal counted : std_logic;
signal counting : std_logic;
 
begin --architecture QuadratureDecoder
 
process (clock)
begin --(clock)
 
if ( (clock'event) and (clock = '1') ) then --every rising edge
 
--convert inputs from asynch to synch by assigning once on each rising edge of clock
Quad(0) <= QuadA;
Quad(1) <= QuadB;
--we are not going to be counting on this clock by default
CountEnable <= '0';
 
--we are not in a 'count' state
if (Counting = '0') then
 
Counted <= '0'; --haven't counted when not in count state
CountEnable <= '0'; --are not outputing a count either
 
end if;
 
--we are in a count state
if (Counting = '1') then
 
if (Counted = '1') then --note that this is covered by default, but is included for clarity.
CountEnable <= '0'; --already counted this one, don't output a count
end if;
 
if (Counted = '0') then --we haven't counted it already
Counted <= '1'; --make sure we dont count it again on next clock
CountEnable <= '1'; --output a count!
end if;
 
end if;
 
-- run our state machine
-- the state transitions are governed by the nature of reality -
-- vis-a-vis this is what quadratre is.
-- the '--?' are the physically un-reachable states.
-- note that it is imperative that the clock be at least (4 I recal)
-- times faster than the maximum transition rate on each quadratre
-- input, or else transitions will occur in between clocks, corrupting
-- the state of the decoder. Put differently, the quadratre device must
-- physically remain in each state for at least a single clock
-- or state changes will not be 'captured' and decoder output will be bogus.
-- which is substancially the case with any clock-based logic.
-- the difference is that a normal glitch is any change in input which
-- has duration less than a single clock, but in quadrature, as single
-- transition of the actual device cases 4 transitions in the state,
-- by design of the quadrature encoding process.
case state is
 
when Wait0 =>
if (Quad = "00") then state <= Wait0; end if;
if (Quad = "01") then state <= RL1; end if;
if (Quad = "10") then state <= LR1; end if;
if (Quad = "11") then state <= Wait0; end if; --?
Counting <= '0';
when Wait1 =>
if (Quad = "00") then state <= Wait0; end if;
if (Quad = "01") then state <= RL1; end if;
if (Quad = "10") then state <= LR1; end if;
if (Quad = "11") then state <= Wait0; end if; --?
Counting <= '0';
when Count0 =>
if (Quad = "00") then state <= Wait0; end if;
if (Quad = "01") then state <= RL1; end if;
if (Quad = "10") then state <= LR1; end if;
if (Quad = "11") then state <= Count0; end if; --?
Counting <= '1';
when Count1 =>
if (Quad = "00") then state <= Wait0; end if;
if (Quad = "01") then state <= RL1; end if;
if (Quad = "10") then state <= LR1; end if;
if (Quad = "11") then state <= Count0; end if; --?
Counting <= '1';
when LR1 =>
if (Quad = "00") then state <= Wait0; end if;
if (Quad = "01") then state <= LR1; end if; --?
if (Quad = "10") then state <= LR1; end if;
if (Quad = "11") then state <= LR2; end if;
Direction <= '0';
Counting <= '0';
when LR2 =>
if (Quad = "00") then state <= LR2; end if; --?
if (Quad = "01") then state <= LR3; end if;
if (Quad = "10") then state <= LR1; end if;
if (Quad = "11") then state <= LR2; end if; --?
Direction <= '0';
Counting <= '0';
when LR3 =>
if (Quad = "00") then state <= Count0; end if;
if (Quad = "01") then state <= LR3; end if;
if (Quad = "10") then state <= LR3; end if; --?
if (Quad = "11") then state <= LR2; end if;
Direction <= '0';
Counting <= '0';
when RL1 =>
if (Quad = "00") then state <= Wait0; end if;
if (Quad = "01") then state <= RL1; end if;
if (Quad = "10") then state <= RL1; end if; --?
if (Quad = "11") then state <= RL2; end if;
Direction <= '1';
Counting <= '0';
when RL2 =>
if (Quad = "00") then state <= RL2; end if; --?
if (Quad = "01") then state <= RL1; end if;
if (Quad = "10") then state <= RL3; end if;
if (Quad = "11") then state <= RL2; end if; --?
Direction <= '1';
Counting <= '0';
when RL3 =>
if (Quad = "00") then state <= Count0; end if;
if (Quad = "01") then state <= RL3; end if; --?
if (Quad = "10") then state <= RL3; end if;
if (Quad = "11") then state <= RL2; end if;
Direction <= '1';
Counting <= '0';
when others => state <= Wait0; -- undefined state; just go back to wait so we don't get stuck here...
 
end case; --state
end if; --clock'event
 
end process; --(clock)
end QuadratureDecoder;
 
 
 
/trunk/Quadrature.npl Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
trunk/Quadrature.npl Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: trunk/QuadratureCounter.vhd =================================================================== --- trunk/QuadratureCounter.vhd (nonexistent) +++ trunk/QuadratureCounter.vhd (revision 2) @@ -0,0 +1,100 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.STD_LOGIC_ARITH.ALL; +use IEEE.STD_LOGIC_SIGNED.ALL; + +-- c2003 Franks Development, LLC +-- http://www.franks-development.com +-- !This source is distributed under the terms & conditions specified at opencores.org + +--resource or companion to this code: + -- Xilinx Application note 12 - "Quadrature Phase Decoder" - xapp012.pdf + -- no longer appears on xilinx website (to best of my knowledge), perhaps it has been superceeded? + +--this code was origonally intended for use on Xilinx XPLA3 'coolrunner' CPLD devices +--origonally compiled/synthesized with Xilinx 'Webpack' 5.2 software + +--How we 'talk' to the outside world: +entity QuadratureCounterPorts is + Port ( clock : in std_logic; --system clock, i.e. 10MHz oscillator + QuadA : in std_logic; --first input from quadrature device (i.e. optical disk encoder) + QuadB : in std_logic; --second input from quadrature device (i.e. optical disk encoder) + CounterValue : out std_logic_vector(15 downto 0) --just an example debuggin output + ); +end QuadratureCounterPorts; + +--What we 'do': +architecture QuadratureCounter of QuadratureCounterPorts is + + -- local 'variables' or 'registers' + + --This is the counter for how many quadrature ticks have gone past. + --the size of this counter is dependant on how far you need to count + --it was origonally used with a circular disk encoder having 2048 ticks/revolution + --thus this 16-bit count could hold 2^15 ticks in either direction, or a total + --of 32768/2048 = 16 revolutions in either direction. if the disk + --was turned more than 16 times in a given direction, the counter overflows + --and the origonal location is lost. If you had a linear instead of + --circular encoder that physically could not move more than 2048 ticks, + --then Count would only need to be 11 downto 0, and you could count + --2048 ticks in either direction, regardless of the position of the + --encoder at system bootup. + signal Count : std_logic_vector(15 downto 0); + + --this is the signal from the quadrature logic that it is time to change + --the value of the counter on this clock signal (either + or -) + signal CountEnable : std_logic; + + --should we increment or decrement count? + signal CountDirection : std_logic; + + --where all the 'work' is done: quadraturedecoder.vhd + component QuadratureDecoderPorts + Port ( + clock : in std_logic; + QuadA : in std_logic; + QuadB : in std_logic; + CountDirection : out std_logic; + CountEnable : out std_logic + ); + end component; + + begin --architecture QuadratureCounter + + --instanciate the decoder + iQuadratureDecoder: QuadratureDecoderPorts + port map ( + clock => clock, + QuadA => QuadA, + QuadB => QuadB, + CountDirection => CountDirection, + CountEnable => CountEnable + ); + + + -- do our actual work every clock cycle + process(clock) + begin + + --keep track of the counter + if ( (clock'event) and (clock = '1') ) then + + if (CountEnable = '1') then + + if (CountDirection = '1') then Count <= Count + "0000000000000001"; end if; + if (CountDirection = '0') then Count <= Count - "0000000000000001"; end if; + + end if; + + end if; --clock'event + + --!!!!!!!!!!!INSERT SOMETHING USEFULL HERE!!!!!!!!!!! + --This is where you do actual work based on the value of the counter + --for instance, I will just output the value of the counter + --led's on an output like this are very useful - you can see the top + --bits light when moved backwards from initial position (count goes negative) + CounterValue <= Count; + + end process; --(clock) + +end QuadratureCounter;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.