1 |
2 |
franksdeve |
library ieee;
|
2 |
|
|
use ieee.std_logic_1164.all;
|
3 |
|
|
|
4 |
|
|
-- c2003 Franks Development, LLC
|
5 |
|
|
-- http://www.franks-development.com
|
6 |
|
|
-- !This source is distributed under the terms & conditions specified at opencores.org
|
7 |
|
|
|
8 |
|
|
--How we 'talk' to the outside world:
|
9 |
|
|
entity QuadratureDecoderPorts is
|
10 |
|
|
port (
|
11 |
6 |
franksdeve |
clock : in std_logic;
|
12 |
|
|
QuadA : in std_logic;
|
13 |
|
|
QuadB : in std_logic;
|
14 |
|
|
Direction : out std_logic;
|
15 |
|
|
CountEnable : out std_logic
|
16 |
2 |
franksdeve |
);
|
17 |
|
|
end QuadratureDecoderPorts;
|
18 |
|
|
|
19 |
|
|
--What we 'do':
|
20 |
|
|
architecture QuadratureDecoder of QuadratureDecoderPorts is
|
21 |
|
|
|
22 |
|
|
--local 'variables' or 'registers'
|
23 |
|
|
|
24 |
|
|
--this runs our state machine: where are we in the decoding process?
|
25 |
|
|
--the following constants describe each state
|
26 |
|
|
--note that every possible state is not listed. the unused states
|
27 |
|
|
--are physically unreachable in a functioning quadratre device, given that the
|
28 |
|
|
--clock is fast enough to 'catch' each transition on the quadrature inputs
|
29 |
|
|
--LR means left-right, RL = left-right. Of course the two are reversed
|
30 |
|
|
--if the two quadratre inputs are switched.
|
31 |
|
|
signal state : std_logic_vector(3 downto 0);
|
32 |
|
|
constant Wait0 : std_logic_vector(3 downto 0) := "0000";
|
33 |
|
|
constant Wait1 : std_logic_vector(3 downto 0) := "0001";
|
34 |
|
|
constant Count0 : std_logic_vector(3 downto 0) := "0010";
|
35 |
|
|
constant Count1 : std_logic_vector(3 downto 0) := "0011";
|
36 |
|
|
constant LR1 : std_logic_vector(3 downto 0) := "1001";
|
37 |
|
|
constant LR2 : std_logic_vector(3 downto 0) := "1101";
|
38 |
|
|
constant LR3 : std_logic_vector(3 downto 0) := "0101";
|
39 |
|
|
constant RL1 : std_logic_vector(3 downto 0) := "0100";
|
40 |
|
|
constant RL2 : std_logic_vector(3 downto 0) := "1100";
|
41 |
|
|
constant RL3 : std_logic_vector(3 downto 0) := "1000";
|
42 |
|
|
|
43 |
|
|
--this is a temp where the two quadrature inputs are stored
|
44 |
|
|
signal Quad : std_logic_vector(1 downto 0);
|
45 |
|
|
|
46 |
|
|
--as a single quadrature count is made up of several states, and the decoder
|
47 |
|
|
--can remain in a given state indefinately (if the quadrature input
|
48 |
|
|
--device is not 'moving'), so we need these 'gate-ing' variables
|
49 |
|
|
--to keep us from counting on every clock when we sit idle in the
|
50 |
|
|
--'count' state; thusly, we just count on the first clock
|
51 |
|
|
--upon entering a 'count' state.
|
52 |
|
|
signal counted : std_logic;
|
53 |
|
|
signal counting : std_logic;
|
54 |
|
|
|
55 |
|
|
begin --architecture QuadratureDecoder
|
56 |
|
|
|
57 |
|
|
process (clock)
|
58 |
|
|
|
59 |
|
|
begin --(clock)
|
60 |
|
|
|
61 |
|
|
if ( (clock'event) and (clock = '1') ) then --every rising edge
|
62 |
|
|
|
63 |
|
|
--convert inputs from asynch to synch by assigning once on each rising edge of clock
|
64 |
|
|
Quad(0) <= QuadA;
|
65 |
|
|
Quad(1) <= QuadB;
|
66 |
|
|
|
67 |
|
|
--we are not going to be counting on this clock by default
|
68 |
|
|
CountEnable <= '0';
|
69 |
|
|
|
70 |
|
|
--we are not in a 'count' state
|
71 |
|
|
if (Counting = '0') then
|
72 |
|
|
|
73 |
|
|
Counted <= '0'; --haven't counted when not in count state
|
74 |
|
|
CountEnable <= '0'; --are not outputing a count either
|
75 |
|
|
|
76 |
|
|
end if;
|
77 |
|
|
|
78 |
|
|
--we are in a count state
|
79 |
|
|
if (Counting = '1') then
|
80 |
|
|
|
81 |
|
|
if (Counted = '1') then --note that this is covered by default, but is included for clarity.
|
82 |
|
|
CountEnable <= '0'; --already counted this one, don't output a count
|
83 |
|
|
end if;
|
84 |
|
|
|
85 |
|
|
if (Counted = '0') then --we haven't counted it already
|
86 |
|
|
Counted <= '1'; --make sure we dont count it again on next clock
|
87 |
|
|
CountEnable <= '1'; --output a count!
|
88 |
|
|
end if;
|
89 |
|
|
|
90 |
|
|
end if;
|
91 |
|
|
|
92 |
|
|
-- run our state machine
|
93 |
|
|
-- the state transitions are governed by the nature of reality -
|
94 |
|
|
-- vis-a-vis this is what quadratre is.
|
95 |
|
|
-- the '--?' are the physically un-reachable states.
|
96 |
|
|
-- note that it is imperative that the clock be at least (4 I recal)
|
97 |
|
|
-- times faster than the maximum transition rate on each quadratre
|
98 |
|
|
-- input, or else transitions will occur in between clocks, corrupting
|
99 |
|
|
-- the state of the decoder. Put differently, the quadratre device must
|
100 |
|
|
-- physically remain in each state for at least a single clock
|
101 |
|
|
-- or state changes will not be 'captured' and decoder output will be bogus.
|
102 |
|
|
-- which is substancially the case with any clock-based logic.
|
103 |
|
|
-- the difference is that a normal glitch is any change in input which
|
104 |
|
|
-- has duration less than a single clock, but in quadrature, as single
|
105 |
|
|
-- transition of the actual device cases 4 transitions in the state,
|
106 |
|
|
-- by design of the quadrature encoding process.
|
107 |
|
|
case state is
|
108 |
|
|
|
109 |
|
|
when Wait0 =>
|
110 |
|
|
if (Quad = "00") then state <= Wait0; end if;
|
111 |
|
|
if (Quad = "01") then state <= RL1; end if;
|
112 |
|
|
if (Quad = "10") then state <= LR1; end if;
|
113 |
|
|
if (Quad = "11") then state <= Wait0; end if; --?
|
114 |
|
|
Counting <= '0';
|
115 |
|
|
|
116 |
|
|
when Wait1 =>
|
117 |
|
|
if (Quad = "00") then state <= Wait0; end if;
|
118 |
|
|
if (Quad = "01") then state <= RL1; end if;
|
119 |
|
|
if (Quad = "10") then state <= LR1; end if;
|
120 |
|
|
if (Quad = "11") then state <= Wait0; end if; --?
|
121 |
|
|
Counting <= '0';
|
122 |
|
|
|
123 |
|
|
when Count0 =>
|
124 |
|
|
if (Quad = "00") then state <= Wait0; end if;
|
125 |
|
|
if (Quad = "01") then state <= RL1; end if;
|
126 |
|
|
if (Quad = "10") then state <= LR1; end if;
|
127 |
|
|
if (Quad = "11") then state <= Count0; end if; --?
|
128 |
|
|
Counting <= '1';
|
129 |
|
|
|
130 |
|
|
when Count1 =>
|
131 |
|
|
if (Quad = "00") then state <= Wait0; end if;
|
132 |
|
|
if (Quad = "01") then state <= RL1; end if;
|
133 |
|
|
if (Quad = "10") then state <= LR1; end if;
|
134 |
|
|
if (Quad = "11") then state <= Count0; end if; --?
|
135 |
|
|
Counting <= '1';
|
136 |
|
|
|
137 |
|
|
when LR1 =>
|
138 |
|
|
if (Quad = "00") then state <= Wait0; end if;
|
139 |
|
|
if (Quad = "01") then state <= LR1; end if; --?
|
140 |
|
|
if (Quad = "10") then state <= LR1; end if;
|
141 |
|
|
if (Quad = "11") then state <= LR2; end if;
|
142 |
|
|
Direction <= '0';
|
143 |
|
|
Counting <= '0';
|
144 |
|
|
|
145 |
|
|
when LR2 =>
|
146 |
|
|
if (Quad = "00") then state <= LR2; end if; --?
|
147 |
|
|
if (Quad = "01") then state <= LR3; end if;
|
148 |
|
|
if (Quad = "10") then state <= LR1; end if;
|
149 |
|
|
if (Quad = "11") then state <= LR2; end if; --?
|
150 |
|
|
Direction <= '0';
|
151 |
|
|
Counting <= '0';
|
152 |
|
|
|
153 |
|
|
when LR3 =>
|
154 |
|
|
if (Quad = "00") then state <= Count0; end if;
|
155 |
|
|
if (Quad = "01") then state <= LR3; end if;
|
156 |
|
|
if (Quad = "10") then state <= LR3; end if; --?
|
157 |
|
|
if (Quad = "11") then state <= LR2; end if;
|
158 |
|
|
Direction <= '0';
|
159 |
|
|
Counting <= '0';
|
160 |
|
|
|
161 |
|
|
when RL1 =>
|
162 |
|
|
if (Quad = "00") then state <= Wait0; end if;
|
163 |
|
|
if (Quad = "01") then state <= RL1; end if;
|
164 |
|
|
if (Quad = "10") then state <= RL1; end if; --?
|
165 |
|
|
if (Quad = "11") then state <= RL2; end if;
|
166 |
|
|
Direction <= '1';
|
167 |
|
|
Counting <= '0';
|
168 |
|
|
|
169 |
|
|
when RL2 =>
|
170 |
|
|
if (Quad = "00") then state <= RL2; end if; --?
|
171 |
|
|
if (Quad = "01") then state <= RL1; end if;
|
172 |
|
|
if (Quad = "10") then state <= RL3; end if;
|
173 |
|
|
if (Quad = "11") then state <= RL2; end if; --?
|
174 |
|
|
Direction <= '1';
|
175 |
|
|
Counting <= '0';
|
176 |
|
|
|
177 |
|
|
when RL3 =>
|
178 |
|
|
if (Quad = "00") then state <= Count0; end if;
|
179 |
|
|
if (Quad = "01") then state <= RL3; end if; --?
|
180 |
|
|
if (Quad = "10") then state <= RL3; end if;
|
181 |
|
|
if (Quad = "11") then state <= RL2; end if;
|
182 |
|
|
Direction <= '1';
|
183 |
|
|
Counting <= '0';
|
184 |
|
|
|
185 |
|
|
when others => state <= Wait0; -- undefined state; just go back to wait so we don't get stuck here...
|
186 |
|
|
|
187 |
|
|
end case; --state
|
188 |
|
|
|
189 |
|
|
end if; --clock'event
|
190 |
|
|
|
191 |
|
|
end process; --(clock)
|
192 |
|
|
|
193 |
|
|
end QuadratureDecoder;
|
194 |
|
|
|
195 |
|
|
|
196 |
|
|
|