1 |
2 |
scottnortm |
--------------------------------------------------------------------------------
|
2 |
3 |
scottnortm |
-- File: quad_decoder.vhd
|
3 |
|
|
-- Desc: HDL implementation of a quadrature decoder with a Wishbone bus
|
4 |
|
|
-- interface. See the "quad_decoder" datasheet for more information.
|
5 |
|
|
-- Date: Initiated October, 2009
|
6 |
|
|
-- Auth: Scott Nortman, COPYRIGHT 2009 Bridge Electronic Design LLC
|
7 |
|
|
-- scott.nortman@gmail.com
|
8 |
|
|
--
|
9 |
|
|
-- NOTE: If you find this file useful / helpful, please let me know :)
|
10 |
|
|
--
|
11 |
2 |
scottnortm |
--------------------------------------------------------------------------------
|
12 |
|
|
--
|
13 |
3 |
scottnortm |
-- REVISION INFORMATION
|
14 |
2 |
scottnortm |
--
|
15 |
3 |
scottnortm |
-- Current Version: 1.0.0
|
16 |
2 |
scottnortm |
--
|
17 |
3 |
scottnortm |
-- Nov. 2009
|
18 |
|
|
-- 1)Initial beta release, upload to OpenCores.org.
|
19 |
|
|
-- 2)Tested HDL implementation with in a Xilinx Spartan 3 AN FPGA, with
|
20 |
|
|
-- a softcore processor, the Tasking TSK3000. Emulated a quadrature
|
21 |
|
|
-- encoder for initial verification.
|
22 |
2 |
scottnortm |
--
|
23 |
3 |
scottnortm |
-- July, 2010
|
24 |
|
|
-- 1)Release version v1.0.0
|
25 |
|
|
-- 2)Changes from prior release:
|
26 |
|
|
-- a) Bit 3 of the Quadrature Control Register (offset 0x00) is now changed
|
27 |
|
|
-- functions, to enable / disable of the Index Zero Count function. When
|
28 |
|
|
-- the bit is 0, an index event does not affect the count. When the bit is
|
29 |
|
|
-- 1, and index events are permitted, the internal quadrature count is set
|
30 |
|
|
-- to 0.
|
31 |
|
|
-- b) Added control bit 13, Index Read Count Bit. When set to 0, no count
|
32 |
|
|
-- is latched. When set to 1, and index events are permitted, the internal
|
33 |
|
|
-- quadrature count is automatically latched to the QRW (offset 0x08)
|
34 |
|
|
-- register when an index event is true. This is VERY useful for detection
|
35 |
|
|
-- of missed encoder counts, as you can assume that the delta counts in
|
36 |
|
|
-- between each index event is fixed, so any deviation from the expected
|
37 |
|
|
-- amount indicates that there were missed encoder counts.
|
38 |
|
|
-- 3)Tested the FPGA implementation with a real encoder, verified proper
|
39 |
|
|
-- operation with count frequencies up to 1.3MHz (50MHz system clock)
|
40 |
|
|
-- This test used an instrumented motor driver, with a hardware qudrature
|
41 |
|
|
-- decoder in parallel with this encoder module. This module did not miss
|
42 |
|
|
-- any counts with a 2048 quad counts / rev encoder running at 40e3 rpm.
|
43 |
|
|
-- 4) Fixed a minor bug with the QCR_PLCT bit and the QCR_INZC bit; under
|
44 |
|
|
-- a specific condition that both the PLCT bit and the INZC bit were asserted
|
45 |
|
|
-- at the same clock cycle, the PLCT would have been executed while the INZC
|
46 |
|
|
-- event would have been missed.
|
47 |
|
|
-- 5) Added an additional feature: Quadrature Count Compare Match Event;
|
48 |
|
|
-- when the CCME bit is set in the QCR register, and the quadrature count
|
49 |
|
|
-- matches the QRW register, a signal is asserted and the status bit of the
|
50 |
|
|
-- QSR register is set. This event can also generate an interrupt.
|
51 |
2 |
scottnortm |
--
|
52 |
|
|
-------------------------------------------------------------------------------
|
53 |
|
|
|
54 |
|
|
library ieee;
|
55 |
|
|
use ieee.std_logic_1164.all;
|
56 |
|
|
use ieee.std_logic_unsigned.all;
|
57 |
|
|
|
58 |
|
|
entity quad_decoder is
|
59 |
|
|
--Configurable quadrature counter width; default is 32 bits
|
60 |
|
|
generic( QUAD_COUNT_WIDTH : integer := 32 );
|
61 |
|
|
port( --Wishbone bus signals
|
62 |
|
|
wb_clk_i : in std_logic;
|
63 |
|
|
wb_rst_i : in std_logic;
|
64 |
|
|
wb_stb_i : in std_logic;
|
65 |
|
|
wb_cyc_i : in std_logic;
|
66 |
|
|
wb_ack_o : out std_logic;
|
67 |
|
|
--wb_adr_i : in std_logic_vector(3 downto 0);
|
68 |
3 |
scottnortm |
wb_adr_i : in std_logic_vector(1 downto 0); --assumes 32 bit alignment
|
69 |
2 |
scottnortm |
wb_dat_o : out std_logic_vector(31 downto 0);
|
70 |
|
|
wb_dat_i : in std_logic_vector(31 downto 0);
|
71 |
|
|
wb_we_i : in std_logic;
|
72 |
|
|
--Quadrature inputs
|
73 |
|
|
quad_cha_i : in std_logic; --Qudrature channel A
|
74 |
|
|
quad_chb_i : in std_logic; --Quadrature channel B
|
75 |
|
|
quad_idx_i : in std_logic; --Quadrature index
|
76 |
|
|
quad_lat_i : in std_logic; --Quadrature latch cnt input
|
77 |
|
|
quad_irq_o : out std_logic --Quadrature IRQ out
|
78 |
|
|
);
|
79 |
|
|
end quad_decoder;
|
80 |
|
|
|
81 |
|
|
architecture quad_decoder_rtl of quad_decoder is
|
82 |
|
|
|
83 |
|
|
--Register and bit definitions
|
84 |
|
|
-----------------------------------------------------------------------------
|
85 |
|
|
-- Quadrature Control Register, QCR, offset 0x00
|
86 |
|
|
--
|
87 |
3 |
scottnortm |
-- Bit 0: Enable Counting, ECNT
|
88 |
2 |
scottnortm |
-- 0 -> Quadrature counting disabled
|
89 |
|
|
-- 1 -> Quadrature counting enabled
|
90 |
|
|
-- Bit 1: Set Count Direction, CTDR
|
91 |
|
|
-- 0 -> Counts positive when A leads B
|
92 |
|
|
-- 1 -> Counts negative when A leads B
|
93 |
|
|
-- Bit 2: Index Enable Bit, INEN
|
94 |
|
|
-- 0 -> Index input disabled
|
95 |
|
|
-- 1 -> Index input enabled
|
96 |
3 |
scottnortm |
-- Bit 3: Index Zero Count Bit, INZC
|
97 |
2 |
scottnortm |
-- 0 -> Internal count not affected.
|
98 |
3 |
scottnortm |
-- 1 -> Zero internal quad_count when quad_index is asserted.
|
99 |
2 |
scottnortm |
-- Bit 4: Index Interrupt Enable, INIE
|
100 |
|
|
-- 0 -> Index interrupt request disabled
|
101 |
|
|
-- 1 -> Index interrupt request enabled
|
102 |
|
|
-- Bit 5: Pre Load Count register, PLCT
|
103 |
|
|
-- 0 -> No action.
|
104 |
|
|
-- 1 -> Load value currently in pre load reg into count reg, auto clear
|
105 |
|
|
-- Bit 6: Underflow Interrupt Enable, UNIE
|
106 |
|
|
-- 0 -> Underflow event will not trigger an interrupt.
|
107 |
|
|
-- 1 -> Underflow event will trigger an interrupt
|
108 |
|
|
-- Bit 7: Overflow Interrupt Enable, OVIE
|
109 |
|
|
-- 0 -> Overflow event will not trigger an interrupt
|
110 |
|
|
-- 1 -> Overflow event will trigger an interrupt
|
111 |
|
|
-- Bit 8: Quadrature Count Latch, QLAT
|
112 |
|
|
-- 0 -> No action.
|
113 |
|
|
-- 1 -> Latch and store quad count in QRW register, auto cleared
|
114 |
|
|
-- Bit 9: Index Channel A configuration, ICHA
|
115 |
|
|
-- 0 -> Index asserted when quadrature channel A logic low
|
116 |
|
|
-- 1 -> Index asserted when quadrature channel A logic high
|
117 |
|
|
-- Bit 10: Index Channel B configuration, ICHB
|
118 |
|
|
-- 0 -> Index asserted when quadrature channel B logic low
|
119 |
|
|
-- 1 -> Index asserted when quadrature channel B logic high
|
120 |
|
|
-- Bit 11: Index Level configuration, IDXL
|
121 |
|
|
-- 0 -> Index asserted when quadature index is logic low
|
122 |
|
|
-- 1 -> Index asserted when quadrature index is logic high
|
123 |
|
|
-- Bit 12: Quadrature Error Interrupt enable, QEIE
|
124 |
|
|
-- 0 -> Quadrature Error Interrupt disabled
|
125 |
|
|
-- 1 -> Quadrature Error Interrupt enabled
|
126 |
3 |
scottnortm |
-- Bit 13: Index Read Count Bit, INRC
|
127 |
|
|
-- 0 -> Quadrature Read / Write register not affected.
|
128 |
|
|
-- 1 -> Read the value of the quad. count to the QRW reg, when index event is true.
|
129 |
|
|
-- Bit 14: Count Compare Match Enable, CCME
|
130 |
|
|
-- 0 -> No compare match event may occur.
|
131 |
|
|
-- 1 -> Compare match event asserted when enabled and QRW == quad_count
|
132 |
|
|
-- Bit 15: Compare Match Interrupt Enable, CMIE
|
133 |
|
|
-- 0 -> No interrupt generated when a compare match event is asserted.
|
134 |
|
|
-- 1 -> An external interrupt will be generated when the compare event is asserted.
|
135 |
|
|
-- Bits 31:16 -> Reserved, must always be written to 0
|
136 |
2 |
scottnortm |
--
|
137 |
|
|
-----------------------------------------------------------------------------
|
138 |
3 |
scottnortm |
constant QCR_ECNT : integer := 0;
|
139 |
|
|
constant QCR_CTDR : integer := 1;
|
140 |
|
|
constant QCR_INEN : integer := 2;
|
141 |
|
|
constant QCR_INZC : integer := 3;
|
142 |
|
|
constant QCR_INIE : integer := 4;
|
143 |
|
|
constant QCR_PLCT : integer := 5;
|
144 |
|
|
constant QCR_UNIE : integer := 6;
|
145 |
|
|
constant QCR_OVIE : integer := 7;
|
146 |
|
|
constant QCR_QLAT : integer := 8;
|
147 |
|
|
constant QCR_ICHA : integer := 9;
|
148 |
|
|
constant QCR_ICHB : integer := 10;
|
149 |
|
|
constant QCR_IDXL : integer := 11;
|
150 |
|
|
constant QCR_QEIE : integer := 12;
|
151 |
|
|
constant QCR_INRC : integer := 13;
|
152 |
|
|
constant QCR_CCME : integer := 14;
|
153 |
|
|
constant QCR_CMIE : integer := 15;
|
154 |
|
|
constant QCR_BITS : integer := 16; --Number of bits used in QCR register
|
155 |
2 |
scottnortm |
signal qcr_reg : std_logic_vector(QCR_BITS-1 downto 0); --QCR register
|
156 |
3 |
scottnortm |
constant QCR_ADDR : std_logic_vector(1 downto 0) := "00";
|
157 |
2 |
scottnortm |
|
158 |
|
|
----------------------------------------------------------------------------
|
159 |
|
|
-- Quadrature Status Register, QSR, offset 0x04
|
160 |
|
|
-- Note: User clears set bits by writing a 1 to the correspoding register
|
161 |
|
|
-- bit.
|
162 |
|
|
-- Bit 0: Quadrature decoder error status, QERR, auto set, user cleared
|
163 |
|
|
-- 0 -> No error
|
164 |
|
|
-- 1 -> Illegal state transition detected
|
165 |
|
|
-- Bit 1: Counter Overflow, CTOV, auto set, user cleared
|
166 |
|
|
-- 0 -> No overflow detected
|
167 |
|
|
-- 1 -> Counter overflow from 0xFFFF to 0x0000
|
168 |
|
|
-- Bit 2: Counter Underflow, CTUN, auto set, user cleared
|
169 |
|
|
-- 0 -> No underflow detected
|
170 |
|
|
-- 1 -> Counter underflow from 0x0000 to 0xFFFF
|
171 |
|
|
-- Bit 3: Index event, INEV, auto set, user cleared
|
172 |
|
|
-- 0 -> Index event has not occurred
|
173 |
|
|
-- 1 -> Index event occured, interrupt requested if INIE set
|
174 |
3 |
scottnortm |
-- Bit 4: Count Compare Match Event, CCME, auto set, user cleared
|
175 |
|
|
-- 0 -> Compare match event has not occurred
|
176 |
|
|
-- 1- > Compare match event occurred, interrupt genetated if enabled
|
177 |
|
|
-- Bits 31:5 -> Reserved, will always read 0
|
178 |
2 |
scottnortm |
----------------------------------------------------------------------------
|
179 |
3 |
scottnortm |
constant QSR_QERR : integer := 0;
|
180 |
|
|
constant QSR_CTOV : integer := 1;
|
181 |
|
|
constant QSR_CTUN : integer := 2;
|
182 |
|
|
constant QSR_INEV : integer := 3;
|
183 |
|
|
constant QSR_CCME : integer := 4;
|
184 |
|
|
constant QSR_BITS : integer := 5; -- Num bits in QSR reg
|
185 |
|
|
signal qsr_reg : std_logic_vector(QSR_BITS-1 downto 0); --QSR register
|
186 |
|
|
constant QSR_ADDR : std_logic_vector(1 downto 0) := "01";
|
187 |
2 |
scottnortm |
|
188 |
|
|
--Signals indicating status information for the QSR process
|
189 |
|
|
signal quad_error : std_logic;
|
190 |
|
|
signal quad_ovflw : std_logic;
|
191 |
|
|
signal quad_unflw : std_logic;
|
192 |
|
|
signal quad_index : std_logic;
|
193 |
3 |
scottnortm |
signal quad_index_d : std_logic;
|
194 |
|
|
signal quad_index_d2: std_logic;
|
195 |
|
|
signal quad_comp : std_logic;
|
196 |
2 |
scottnortm |
|
197 |
|
|
----------------------------------------------------------------------------
|
198 |
|
|
-- Quadrature Count Read / Write Register, QRW, offset 0x08
|
199 |
|
|
-- Note: The actual quadrature count value must be latched prior to
|
200 |
|
|
-- reading from this register. This may be triggered two ways:
|
201 |
|
|
-- 1) Writing a '1' to the QCR, bit 9 quadrature count latch
|
202 |
|
|
-- (QLAT), -or-
|
203 |
|
|
-- 2) Asserting the external syncronous input quad_lat_i.
|
204 |
|
|
-- Once either event occurs, the quadrature count value will be
|
205 |
|
|
-- copied to the QCT register.
|
206 |
|
|
--
|
207 |
|
|
-- This register is also used to hold the pre-load count value.
|
208 |
|
|
-- After writing to this register, the pre-load value is
|
209 |
|
|
-- transferred to the quadrature count register by writing a '1'
|
210 |
3 |
scottnortm |
-- to bit location 5, quadrature pre-load count (PLCT) of the
|
211 |
2 |
scottnortm |
-- quadrature control register (QCR) offset 0x00.
|
212 |
|
|
----------------------------------------------------------------------------
|
213 |
|
|
signal qrw_reg : std_logic_vector(QUAD_COUNT_WIDTH-1 downto 0);
|
214 |
3 |
scottnortm |
constant QRW_ADDR : std_logic_vector(1 downto 0) := "10";
|
215 |
2 |
scottnortm |
|
216 |
|
|
--Actual quadrature counter register, extra bit for over/underflow detect
|
217 |
|
|
signal quad_count : std_logic_vector(QUAD_COUNT_WIDTH downto 0);
|
218 |
|
|
|
219 |
|
|
--Input buffers / filters for quadrature signals
|
220 |
|
|
signal quad_cha_buf: std_logic_vector(3 downto 0);
|
221 |
|
|
signal quad_chb_buf: std_logic_vector(3 downto 0);
|
222 |
|
|
signal quad_idx_buf: std_logic_vector(3 downto 0);
|
223 |
|
|
signal quad_cha_flt: std_logic;
|
224 |
|
|
signal quad_chb_flt: std_logic;
|
225 |
|
|
signal quad_idx_flt: std_logic;
|
226 |
|
|
signal quad_cha_j : std_logic;
|
227 |
|
|
signal quad_cha_k : std_logic;
|
228 |
|
|
signal quad_chb_j : std_logic;
|
229 |
|
|
signal quad_chb_k : std_logic;
|
230 |
|
|
signal quad_idx_j : std_logic;
|
231 |
|
|
signal quad_idx_k : std_logic;
|
232 |
|
|
|
233 |
3 |
scottnortm |
signal quad_lat_flt : std_logic;
|
234 |
|
|
signal quad_lat_q : std_logic;
|
235 |
|
|
signal quad_lat_m : std_logic;
|
236 |
2 |
scottnortm |
|
237 |
|
|
--Quadrature 4X decoding state machine signals
|
238 |
|
|
signal quad_st_new : std_logic_vector(1 downto 0);
|
239 |
|
|
signal quad_st_old : std_logic_vector(1 downto 0);
|
240 |
|
|
signal quad_trans : std_logic;
|
241 |
|
|
signal quad_dir : std_logic;
|
242 |
|
|
-- State constants for 4x quad decoding, CH B is MSB, CH A is LSB
|
243 |
|
|
constant QUAD_STATE_0: std_logic_vector(1 downto 0) := "00";
|
244 |
|
|
constant QUAD_STATE_1: std_logic_vector(1 downto 0) := "01";
|
245 |
|
|
constant QUAD_STATE_2: std_logic_vector(1 downto 0) := "11";
|
246 |
|
|
constant QUAD_STATE_3: std_logic_vector(1 downto 0) := "10";
|
247 |
3 |
scottnortm |
|
248 |
|
|
--Wishbone internal signals
|
249 |
|
|
signal wb_request : std_logic;
|
250 |
|
|
signal wb_write : std_logic;
|
251 |
|
|
|
252 |
2 |
scottnortm |
--Signal for single clock delay of ack out
|
253 |
3 |
scottnortm |
signal ack_dly : std_logic;
|
254 |
|
|
|
255 |
2 |
scottnortm |
--Internal irq signal
|
256 |
|
|
signal quad_irq_int: std_logic;
|
257 |
|
|
|
258 |
3 |
scottnortm |
-- Internal signal to latch quad count on index assertion
|
259 |
|
|
signal qcnt_idx_latch : std_logic;
|
260 |
|
|
|
261 |
2 |
scottnortm |
----------------------------------------------------------------------------
|
262 |
|
|
--Start of RTL
|
263 |
|
|
----------------------------------------------------------------------------
|
264 |
|
|
begin
|
265 |
3 |
scottnortm |
|
266 |
|
|
--Assign internal signal to external signal
|
267 |
2 |
scottnortm |
quad_irq_o <= quad_irq_int;
|
268 |
|
|
|
269 |
|
|
-- Handle wishbone ack generation / internal write signals
|
270 |
|
|
wb_request <= wb_stb_i and wb_cyc_i;
|
271 |
|
|
wb_write <= wb_request and wb_we_i;
|
272 |
3 |
scottnortm |
wb_ack_o <= ack_dly;
|
273 |
|
|
|
274 |
|
|
-----------------------------------------------------------------------
|
275 |
|
|
-- Process: qck_dly_proc( wb_clk_i )
|
276 |
|
|
-- Desc: Generates the wishbone ack signal after a single clock
|
277 |
|
|
-- delay. This insures that the internal read / write
|
278 |
|
|
-- operations have completed before acknowledging the
|
279 |
|
|
-- master device.
|
280 |
|
|
-- Signals: wb_clk_i
|
281 |
|
|
-- ack_dly
|
282 |
|
|
-- wb_rst_i
|
283 |
|
|
-- Notes: Verified using the Wishbone bus of the TSK3000 from
|
284 |
|
|
-- Altium Designer.
|
285 |
|
|
-----------------------------------------------------------------------
|
286 |
2 |
scottnortm |
ack_dly_proc: process( wb_clk_i ) begin
|
287 |
|
|
if rising_edge( wb_clk_i ) then
|
288 |
|
|
if wb_rst_i = '1' then
|
289 |
|
|
ack_dly <= '0';
|
290 |
|
|
elsif wb_request = '1' then
|
291 |
|
|
ack_dly <= '1';
|
292 |
|
|
end if;
|
293 |
|
|
if ack_dly = '1' then
|
294 |
|
|
ack_dly <= '0';
|
295 |
|
|
end if;
|
296 |
|
|
end if;
|
297 |
|
|
end process ack_dly_proc;
|
298 |
|
|
|
299 |
|
|
-----------------------------------------------------------------------
|
300 |
|
|
-- Process: qcr_reg_wr_proc( wb_clk_i )
|
301 |
|
|
-- Desc: Handles writing of the Quadrature Control Regsiter
|
302 |
|
|
-- signal, address offset 0x00.
|
303 |
|
|
-- Signals: qcr_reg, quadrature control register
|
304 |
|
|
-- wb_rst_i, external reset input
|
305 |
|
|
-- wb_write, internal write enable signal
|
306 |
|
|
-- wb_adr_i, wishbone address inputs
|
307 |
|
|
-- wb_dat_i, wishbone data inputs
|
308 |
|
|
-- Notes: See comments above for more info re the qcr_reg
|
309 |
|
|
-----------------------------------------------------------------------
|
310 |
|
|
qcr_reg_wr_proc: process( wb_clk_i ) begin
|
311 |
|
|
if rising_edge( wb_clk_i ) then
|
312 |
|
|
if wb_rst_i = '1' then
|
313 |
|
|
qcr_reg <= (others => '0');
|
314 |
3 |
scottnortm |
elsif wb_write = '1' and wb_adr_i = QCR_ADDR then
|
315 |
2 |
scottnortm |
qcr_reg <= wb_dat_i(QCR_BITS-1 downto 0);
|
316 |
|
|
end if;
|
317 |
|
|
--See if PLCT asserted, should be auto-cleared
|
318 |
|
|
if qcr_reg(QCR_PLCT) = '1' then
|
319 |
|
|
qcr_reg(QCR_PLCT) <= '0';
|
320 |
|
|
end if;
|
321 |
|
|
--See if QLAT asserted, should be auto-cleared
|
322 |
|
|
if qcr_reg(QCR_QLAT) = '1' then
|
323 |
|
|
qcr_reg(QCR_QLAT) <= '0';
|
324 |
|
|
end if;
|
325 |
|
|
end if;
|
326 |
|
|
end process qcr_reg_wr_proc;
|
327 |
|
|
|
328 |
|
|
-----------------------------------------------------------------------
|
329 |
|
|
-- Process: qsr_reg_wr_proc( wb_clk_i )
|
330 |
3 |
scottnortm |
-- Desc: Handles writing of the Quadrature Status Register, QSR,
|
331 |
2 |
scottnortm |
-- offset 0x04.
|
332 |
|
|
-- Signals: quad_error, internal error status signal
|
333 |
|
|
-- quad_ovflw, internal counter overflow signal
|
334 |
|
|
-- quad_unflw, internal counter underflow signal
|
335 |
|
|
-- quad_index, internl index event signal
|
336 |
|
|
-- wb_rst_i, external reset input
|
337 |
|
|
-- wb_write, internal write enable signal
|
338 |
|
|
-- wb_adr_i, wishbone address inputs
|
339 |
|
|
-- wb_dat_i, wishbone data inputs
|
340 |
|
|
-- Notes: All of these bits are set automatically based on the
|
341 |
|
|
-- states of the internal signals. Once set, the user must
|
342 |
|
|
-- write a '1' to the corresponding bit location to clear it.
|
343 |
|
|
-- See the comments above for more information.
|
344 |
|
|
-----------------------------------------------------------------------
|
345 |
|
|
qsr_reg_wr_proc: process( wb_clk_i ) begin
|
346 |
|
|
if rising_edge( wb_clk_i ) then
|
347 |
|
|
if wb_rst_i = '1' then
|
348 |
|
|
qsr_reg <= (others => '0');
|
349 |
|
|
else
|
350 |
|
|
--Set qsr_reg bit from signal quad_error
|
351 |
3 |
scottnortm |
if quad_error = '1' and qcr_reg(QCR_ECNT) = '1' then
|
352 |
2 |
scottnortm |
qsr_reg(QSR_QERR) <= '1';
|
353 |
3 |
scottnortm |
elsif wb_write = '1' and wb_adr_i = QSR_ADDR and qsr_reg(QSR_QERR) = '1' and wb_dat_i(QSR_QERR) = '1' then
|
354 |
2 |
scottnortm |
qsr_reg(QSR_QERR) <= '0';
|
355 |
|
|
end if;
|
356 |
|
|
--Set qsr_reg bit rom signal quad_ovflw
|
357 |
3 |
scottnortm |
if quad_ovflw = '1' then
|
358 |
2 |
scottnortm |
qsr_reg(QSR_CTOV) <= '1';
|
359 |
3 |
scottnortm |
elsif wb_write = '1' and wb_adr_i = QSR_ADDR and qsr_reg(QSR_CTOV) = '1' and wb_dat_i(QSR_CTOV) = '1' then
|
360 |
2 |
scottnortm |
qsr_reg(QSR_CTOV) <= '0';
|
361 |
|
|
end if;
|
362 |
|
|
--Set qsr_reg bit from signal quad_unflw
|
363 |
3 |
scottnortm |
if quad_unflw = '1' then
|
364 |
2 |
scottnortm |
qsr_reg(QSR_CTUN) <= '1';
|
365 |
3 |
scottnortm |
elsif wb_write = '1' and wb_adr_i = QSR_ADDR and qsr_reg(QSR_CTUN) = '1' and wb_dat_i(QSR_CTUN) = '1' then
|
366 |
2 |
scottnortm |
qsr_reg(QSR_CTUN) <= '0';
|
367 |
|
|
end if;
|
368 |
|
|
--Set qsr_reg bit from signal quad_index
|
369 |
3 |
scottnortm |
if quad_index = '1' then
|
370 |
2 |
scottnortm |
qsr_reg(QSR_INEV) <= '1';
|
371 |
3 |
scottnortm |
elsif wb_write = '1' and wb_adr_i = QSR_ADDR and qsr_reg(QSR_INEV) = '1' and wb_dat_i(QSR_INEV) = '1' then
|
372 |
2 |
scottnortm |
qsr_reg(QSR_INEV) <= '0';
|
373 |
|
|
end if;
|
374 |
3 |
scottnortm |
--check quadrature compare bit
|
375 |
|
|
if quad_comp = '1' then
|
376 |
|
|
qsr_reg(QSR_CCME) <= '1';
|
377 |
|
|
elsif wb_write = '1' and wb_adr_i = QSR_ADDR and qsr_reg(QSR_CCME) = '1' and wb_dat_i(QSR_CCME) = '1' then
|
378 |
|
|
qsr_reg(QSR_CCME) <= '0';
|
379 |
|
|
end if;
|
380 |
2 |
scottnortm |
end if;
|
381 |
|
|
end if;
|
382 |
|
|
end process qsr_reg_wr_proc;
|
383 |
3 |
scottnortm |
|
384 |
2 |
scottnortm |
-----------------------------------------------------------------------
|
385 |
|
|
-- Process: qrw_reg_wr_proc( wb_clk_i )
|
386 |
|
|
-- Desc: Handles writing to the Quadrature Read / Write Register,
|
387 |
|
|
-- offset 0x08.
|
388 |
3 |
scottnortm |
-- Signals: wb_rst, reset signal
|
389 |
|
|
-- QLAT bit of QCR reg, Quadrature latch
|
390 |
|
|
-- quad_lat_flt, filtered external quadrature latch signal
|
391 |
|
|
-- Notes: Use of this register is required to access the
|
392 |
|
|
-- quadrature count.
|
393 |
2 |
scottnortm |
-----------------------------------------------------------------------
|
394 |
|
|
qrw_reg_wr_proc: process( wb_clk_i ) begin
|
395 |
|
|
if rising_edge( wb_clk_i ) then
|
396 |
|
|
if wb_rst_i = '1' then
|
397 |
|
|
qrw_reg <= (others =>'0');
|
398 |
3 |
scottnortm |
elsif wb_write = '1' and wb_adr_i = QRW_ADDR then
|
399 |
2 |
scottnortm |
qrw_reg <= wb_dat_i;
|
400 |
3 |
scottnortm |
elsif qcr_reg(QCR_QLAT) = '1' or quad_lat_flt = '1' or (qcr_reg(QCR_INRC) = '1' and quad_index = '1') then
|
401 |
2 |
scottnortm |
qrw_reg <= quad_count(QUAD_COUNT_WIDTH-1 downto 0);
|
402 |
3 |
scottnortm |
end if;
|
403 |
2 |
scottnortm |
end if;
|
404 |
|
|
end process qrw_reg_wr_proc;
|
405 |
3 |
scottnortm |
|
406 |
2 |
scottnortm |
-----------------------------------------------------------------------
|
407 |
|
|
-- Process: quad_regs_rd_proc( wb_clk_i )
|
408 |
|
|
-- Desc: Handles reading of all of the registers.
|
409 |
3 |
scottnortm |
-- Signals: wb_adr_i, Wishbone address input
|
410 |
|
|
-- qcr_reg, Quadrature control register
|
411 |
|
|
-- qsr_reg, Quadrature status register
|
412 |
|
|
-- qrw_reg, Quadrature read/write register
|
413 |
|
|
-- Notes: None.
|
414 |
2 |
scottnortm |
-----------------------------------------------------------------------
|
415 |
3 |
scottnortm |
quad_regs_rd_proc: process( wb_adr_i, qcr_reg, qsr_reg, qrw_reg ) begin
|
416 |
|
|
case wb_adr_i is
|
417 |
|
|
when QCR_ADDR =>
|
418 |
|
|
wb_dat_o(QCR_BITS-1 downto 0) <= qcr_reg;
|
419 |
|
|
wb_dat_o(31 downto QCR_BITS) <= (others => '0');
|
420 |
|
|
when QSR_ADDR =>
|
421 |
|
|
wb_dat_o(QSR_BITS-1 downto 0) <= qsr_reg;
|
422 |
|
|
wb_dat_o(31 downto QSR_BITS) <= (others => '0');
|
423 |
|
|
when QRW_ADDR =>
|
424 |
|
|
wb_dat_o(QUAD_COUNT_WIDTH-1 downto 0) <= qrw_reg;
|
425 |
|
|
when others =>
|
426 |
|
|
wb_dat_o <= (others => '0' );
|
427 |
|
|
end case;
|
428 |
2 |
scottnortm |
end process quad_regs_rd_proc;
|
429 |
3 |
scottnortm |
|
430 |
|
|
-----------------------------------------------------------------------
|
431 |
|
|
-- Process: quad_lat_m_proc( wb_clk_i )
|
432 |
|
|
-- Desc: Rising edge detect for input quad_lat_i
|
433 |
|
|
-- Signals: quad_lat_i, external quadratire latch input
|
434 |
|
|
-- quad_lat_m, metastable quadature latch signal
|
435 |
|
|
-- Note: This is an asynchronous signal; the metastable
|
436 |
|
|
-- output is later latched to a synchronized internal
|
437 |
|
|
-- signal for other module processes.
|
438 |
|
|
-----------------------------------------------------------------------
|
439 |
|
|
quad_lat_m_proc : process( quad_lat_i ) begin
|
440 |
|
|
if rising_edge( quad_lat_i ) then
|
441 |
|
|
if wb_rst_i = '1' then
|
442 |
|
|
quad_lat_m <= '0';
|
443 |
|
|
else
|
444 |
|
|
quad_lat_m <= '1';
|
445 |
|
|
end if;
|
446 |
|
|
|
447 |
|
|
if quad_lat_m = '1' then
|
448 |
|
|
quad_lat_m <= '0';
|
449 |
|
|
end if;
|
450 |
|
|
end if;
|
451 |
|
|
end process quad_lat_m_proc;
|
452 |
|
|
|
453 |
|
|
-----------------------------------------------------------------------
|
454 |
|
|
-- Process: quad_lat_proc
|
455 |
|
|
-- Desc: Metastable filter for quad_lat_i, sets internal signal
|
456 |
|
|
-- Signals: quad_lat_m, metastable latch signal
|
457 |
|
|
-- quad_lat_q, stable latched signal
|
458 |
|
|
-- quad_lat_flt, filtered signal used by other processe
|
459 |
|
|
-- Note: Due to the filtering, there is a delay of 4 clk cycles
|
460 |
|
|
-- from assertion of the signal until asserting internal
|
461 |
|
|
-- processes.
|
462 |
|
|
-----------------------------------------------------------------------
|
463 |
2 |
scottnortm |
quad_lat_proc: process( wb_clk_i) begin
|
464 |
|
|
if rising_edge( wb_clk_i ) then
|
465 |
|
|
if wb_rst_i = '1' then
|
466 |
|
|
quad_lat_flt <= '0';
|
467 |
3 |
scottnortm |
quad_lat_q <= '0';
|
468 |
2 |
scottnortm |
else
|
469 |
3 |
scottnortm |
if quad_lat_m = '1' then
|
470 |
|
|
quad_lat_q <= '1';
|
471 |
|
|
end if;
|
472 |
|
|
if quad_lat_q = '1' then
|
473 |
|
|
quad_lat_q <= '0';
|
474 |
|
|
quad_lat_flt <= '1';
|
475 |
|
|
end if;
|
476 |
2 |
scottnortm |
if quad_lat_flt = '1' then
|
477 |
|
|
quad_lat_flt <= '0';
|
478 |
|
|
end if;
|
479 |
|
|
end if;
|
480 |
|
|
end if;
|
481 |
|
|
end process quad_lat_proc;
|
482 |
|
|
|
483 |
|
|
--Combinatorial logic for JK flip flop filters
|
484 |
|
|
quad_cha_j <= quad_cha_buf(3) and quad_cha_buf(2) and quad_cha_buf(1);
|
485 |
|
|
quad_cha_k <= not( quad_cha_buf(3) or quad_cha_buf(2) or quad_cha_buf(1) );
|
486 |
|
|
quad_chb_j <= quad_chb_buf(3) and quad_chb_buf(2) and quad_chb_buf(1);
|
487 |
|
|
quad_chb_k <= not( quad_chb_buf(3) or quad_chb_buf(2) or quad_chb_buf(1) );
|
488 |
|
|
quad_idx_j <= quad_idx_buf(3) and quad_idx_buf(2) and quad_idx_buf(1);
|
489 |
|
|
quad_idx_k <= not( quad_idx_buf(3) or quad_idx_buf(2) or quad_idx_buf(1) );
|
490 |
3 |
scottnortm |
|
491 |
|
|
-----------------------------------------------------------------------
|
492 |
|
|
-- Process: quad_filt_proc
|
493 |
|
|
-- Desc: Digital filters for the quadrature inputs. This is
|
494 |
|
|
-- implemented with serial shift registers on all inputs;
|
495 |
|
|
-- similar to the digital filters of the HCTL-2016. See
|
496 |
|
|
-- that datasheet for more information.
|
497 |
|
|
-- Signals: quad_cha_i, external input
|
498 |
|
|
-- quad_chb_i, external input
|
499 |
|
|
-- quad_idx_i, external input
|
500 |
|
|
-- quad_cha_buf, input buffer for filtering
|
501 |
|
|
-- quad_chb_buf, input buffer for filtering
|
502 |
|
|
-- quad_cha_flt, filtered cha signal
|
503 |
|
|
-- quad_chb_flt, filtered chb signal
|
504 |
|
|
-- quad_cha_j, j signal for jk FF
|
505 |
|
|
-- quad_cha_k, k signal for jk FF
|
506 |
|
|
-- Note: Upon reset, all buffers are filled with the values
|
507 |
|
|
-- present on the input pins.
|
508 |
|
|
-----------------------------------------------------------------------
|
509 |
2 |
scottnortm |
quad_filt_proc: process( wb_clk_i ) begin
|
510 |
|
|
if rising_edge( wb_clk_i ) then
|
511 |
|
|
if wb_rst_i = '1' then
|
512 |
|
|
quad_cha_buf <= ( quad_cha_i & quad_cha_i & quad_cha_i & quad_cha_i );
|
513 |
|
|
quad_chb_buf <= ( quad_chb_i & quad_chb_i & quad_chb_i & quad_chb_i );
|
514 |
|
|
quad_idx_buf <= ( quad_idx_i & quad_idx_i & quad_idx_i & quad_idx_i );
|
515 |
|
|
quad_cha_flt <= quad_cha_i;
|
516 |
|
|
quad_chb_flt <= quad_chb_i;
|
517 |
|
|
quad_idx_flt <= quad_idx_i;
|
518 |
|
|
else
|
519 |
|
|
--sample inputs, place into shift registers
|
520 |
|
|
quad_cha_buf <= ( quad_cha_buf(2) & quad_cha_buf(1) & quad_cha_buf(0) & quad_cha_i );
|
521 |
|
|
quad_chb_buf <= ( quad_chb_buf(2) & quad_chb_buf(1) & quad_chb_buf(0) & quad_chb_i );
|
522 |
|
|
quad_idx_buf <= ( quad_idx_buf(2) & quad_idx_buf(1) & quad_idx_buf(0) & quad_idx_i );
|
523 |
|
|
|
524 |
|
|
-- JK flip flop filters
|
525 |
|
|
if quad_cha_j = '1' then
|
526 |
|
|
quad_cha_flt <= '1';
|
527 |
|
|
end if;
|
528 |
|
|
if quad_cha_k = '1' then
|
529 |
|
|
quad_cha_flt <= '0';
|
530 |
|
|
end if;
|
531 |
|
|
if quad_chb_j = '1' then
|
532 |
|
|
quad_chb_flt <= '1';
|
533 |
|
|
end if;
|
534 |
|
|
if quad_chb_k = '1' then
|
535 |
|
|
quad_chb_flt <= '0';
|
536 |
|
|
end if;
|
537 |
|
|
if quad_idx_j = '1' then
|
538 |
|
|
quad_idx_flt <= '1';
|
539 |
|
|
end if;
|
540 |
|
|
if quad_idx_k = '1' then
|
541 |
|
|
quad_idx_flt <= '0';
|
542 |
3 |
scottnortm |
end if;
|
543 |
2 |
scottnortm |
end if;
|
544 |
|
|
end if;
|
545 |
|
|
end process quad_filt_proc;
|
546 |
|
|
|
547 |
|
|
-----------------------------------------------------------------------
|
548 |
3 |
scottnortm |
-- Process: quad_state_proc
|
549 |
|
|
-- Desc: Reads filtered values quad_cha_flt, quad_chb_flt and
|
550 |
|
|
-- asserts the quad_trans and quad_dir signals.
|
551 |
|
|
-- Signals: quad_st_old
|
552 |
|
|
-- quad_st_new
|
553 |
|
|
-- quad_trans
|
554 |
|
|
-- quad_dir
|
555 |
|
|
-- quad_error
|
556 |
|
|
-- Notes: See the datasheet for more info.
|
557 |
|
|
-----------------------------------------------------------------------
|
558 |
2 |
scottnortm |
quad_state_proc: process( wb_clk_i ) begin
|
559 |
|
|
if rising_edge( wb_clk_i ) then
|
560 |
|
|
if wb_rst_i = '1' then
|
561 |
|
|
quad_st_old <= (quad_chb_i & quad_cha_i);
|
562 |
|
|
quad_st_new <= (quad_chb_i & quad_cha_i);
|
563 |
|
|
quad_trans <= '0';
|
564 |
|
|
quad_dir <= '0';
|
565 |
|
|
quad_error <= '0';
|
566 |
3 |
scottnortm |
else
|
567 |
2 |
scottnortm |
quad_st_new <= (quad_chb_flt & quad_cha_flt);
|
568 |
|
|
quad_st_old <= quad_st_new;
|
569 |
3 |
scottnortm |
--state machine enabled if counting
|
570 |
|
|
if qcr_reg(QCR_ECNT) = '1' then
|
571 |
|
|
case quad_st_new is
|
572 |
|
|
when QUAD_STATE_0 => --"00"
|
573 |
|
|
case quad_st_old is
|
574 |
|
|
when QUAD_STATE_0 =>
|
575 |
|
|
quad_trans <= '0';
|
576 |
|
|
when QUAD_STATE_3 => --"10" -- dflt positive direction
|
577 |
|
|
if qcr_reg(QCR_CTDR) = '1' then
|
578 |
|
|
quad_trans <= '1';
|
579 |
|
|
quad_dir <= '0';
|
580 |
|
|
else
|
581 |
|
|
quad_trans <= '1';
|
582 |
|
|
quad_dir <= '1';
|
583 |
|
|
end if;
|
584 |
|
|
when QUAD_STATE_1 => --"01" -- dflt negative direction
|
585 |
|
|
if qcr_reg(QCR_CTDR) = '1' then
|
586 |
|
|
quad_trans <= '1';
|
587 |
|
|
quad_dir <= '1';
|
588 |
|
|
else
|
589 |
|
|
quad_trans <= '1';
|
590 |
|
|
quad_dir <= '0';
|
591 |
|
|
end if;
|
592 |
|
|
when others =>
|
593 |
|
|
quad_error <= '1';
|
594 |
|
|
quad_trans <= '0';
|
595 |
|
|
end case; --quad_st_old
|
596 |
2 |
scottnortm |
|
597 |
3 |
scottnortm |
when QUAD_STATE_1 => --"01"
|
598 |
|
|
case quad_st_old is
|
599 |
|
|
when QUAD_STATE_1 =>
|
600 |
|
|
quad_trans <= '0';
|
601 |
|
|
when QUAD_STATE_0 => --"10" -- dflt positive direction
|
602 |
|
|
if qcr_reg(QCR_CTDR) = '1' then
|
603 |
|
|
quad_trans <= '1';
|
604 |
|
|
quad_dir <= '0';
|
605 |
|
|
else
|
606 |
|
|
quad_trans <= '1';
|
607 |
|
|
quad_dir <= '1';
|
608 |
|
|
end if;
|
609 |
|
|
when QUAD_STATE_2 => --"01" -- dflt negative direction
|
610 |
|
|
if qcr_reg(QCR_CTDR) = '1' then
|
611 |
|
|
quad_trans <= '1';
|
612 |
|
|
quad_dir <= '1';
|
613 |
|
|
else
|
614 |
|
|
quad_trans <= '1';
|
615 |
|
|
quad_dir <= '0';
|
616 |
|
|
end if;
|
617 |
|
|
when others =>
|
618 |
|
|
quad_error <= '1';
|
619 |
|
|
quad_trans <= '0';
|
620 |
|
|
end case; --quad_st_old
|
621 |
2 |
scottnortm |
|
622 |
3 |
scottnortm |
when QUAD_STATE_2 => --"11"
|
623 |
|
|
case quad_st_old is
|
624 |
|
|
when QUAD_STATE_2 =>
|
625 |
|
|
quad_trans <= '0';
|
626 |
|
|
when QUAD_STATE_1 => --"10" -- dflt positive direction
|
627 |
|
|
if qcr_reg(QCR_CTDR) = '1' then
|
628 |
|
|
quad_trans <= '1';
|
629 |
|
|
quad_dir <= '0';
|
630 |
|
|
else
|
631 |
|
|
quad_trans <= '1';
|
632 |
|
|
quad_dir <= '1';
|
633 |
|
|
end if;
|
634 |
|
|
when QUAD_STATE_3 => --"01" -- dflt negative direction
|
635 |
|
|
if qcr_reg(QCR_CTDR) = '1' then
|
636 |
|
|
quad_trans <= '1';
|
637 |
|
|
quad_dir <= '1';
|
638 |
|
|
else
|
639 |
|
|
quad_trans <= '1';
|
640 |
|
|
quad_dir <= '0';
|
641 |
|
|
end if;
|
642 |
|
|
when others =>
|
643 |
|
|
quad_error <= '1';
|
644 |
|
|
quad_trans <= '0';
|
645 |
|
|
end case; --quad_st_old
|
646 |
2 |
scottnortm |
|
647 |
3 |
scottnortm |
when QUAD_STATE_3 => --"10"
|
648 |
|
|
case quad_st_old is
|
649 |
|
|
when QUAD_STATE_3 =>
|
650 |
|
|
quad_trans <= '0';
|
651 |
|
|
when QUAD_STATE_2 => --"10" -- dflt positive direction
|
652 |
|
|
if qcr_reg(QCR_CTDR) = '1' then
|
653 |
|
|
quad_trans <= '1';
|
654 |
|
|
quad_dir <= '0';
|
655 |
|
|
else
|
656 |
|
|
quad_trans <= '1';
|
657 |
|
|
quad_dir <= '1';
|
658 |
|
|
end if;
|
659 |
|
|
when QUAD_STATE_0 => --"01" -- dflt negative direction
|
660 |
|
|
if qcr_reg(QCR_CTDR) = '1' then
|
661 |
|
|
quad_trans <= '1';
|
662 |
|
|
quad_dir <= '1';
|
663 |
|
|
else
|
664 |
|
|
quad_trans <= '1';
|
665 |
|
|
quad_dir <= '0';
|
666 |
|
|
end if;
|
667 |
|
|
when others =>
|
668 |
|
|
quad_error <= '1';
|
669 |
|
|
quad_trans <= '0';
|
670 |
|
|
end case; --quad_st_old
|
671 |
2 |
scottnortm |
|
672 |
3 |
scottnortm |
when others =>
|
673 |
|
|
quad_error <= '1';
|
674 |
|
|
quad_trans <= '0';
|
675 |
|
|
end case; --quad_st_new
|
676 |
|
|
|
677 |
|
|
end if;
|
678 |
|
|
|
679 |
2 |
scottnortm |
if quad_trans = '1' then
|
680 |
|
|
quad_trans <= '0';
|
681 |
|
|
end if;
|
682 |
3 |
scottnortm |
|
683 |
2 |
scottnortm |
if quad_dir = '1' then
|
684 |
|
|
quad_dir <= '0';
|
685 |
|
|
end if;
|
686 |
3 |
scottnortm |
|
687 |
2 |
scottnortm |
if quad_error = '1' then
|
688 |
|
|
quad_error <= '0';
|
689 |
|
|
end if;
|
690 |
|
|
end if;
|
691 |
|
|
end if;
|
692 |
|
|
end process quad_state_proc;
|
693 |
3 |
scottnortm |
|
694 |
2 |
scottnortm |
-----------------------------------------------------------------------
|
695 |
|
|
-- Process: quad_count_proc( wb_clk_i )
|
696 |
3 |
scottnortm |
-- Desc: Handles writing to the quad_count register.
|
697 |
2 |
scottnortm |
-- First, pre-load events are handled; this may be triggered
|
698 |
|
|
-- by writing a '1' to the qcr_reg QCR_PLCT bit location, or
|
699 |
|
|
-- by an index_event assertion. Next, count events may be
|
700 |
3 |
scottnortm |
-- triggered by an assertion of the 'quad_trans' signal,
|
701 |
2 |
scottnortm |
-- which causes the quad_count value to increment or
|
702 |
|
|
-- decrement by one, based on the quad_dir signal.
|
703 |
3 |
scottnortm |
-- With each change on the count value, the counter is
|
704 |
|
|
-- checked for over/underflow. If either is detected, the
|
705 |
2 |
scottnortm |
-- corresponding signal is asserted for one clock cycle.
|
706 |
|
|
-- Signals: quad_count, QUAD_COUNT_WIDTH+1 bit length, holds the actual
|
707 |
|
|
-- 4x quadrature counts. The extra bit (i.e., as compared
|
708 |
|
|
-- to the user register qrw_reg) is for over / underflow
|
709 |
|
|
-- detection. 2's complement integer.
|
710 |
|
|
-- quad_ovflw, single bit signal indicating an overflow event
|
711 |
|
|
-- has occurred; asserted one clock cycle then cleared.
|
712 |
|
|
-- quad_unflw, single bit signal indicating that an underflow
|
713 |
|
|
-- event occured; asserted one clock cycle then cleared.
|
714 |
|
|
-- Note: See the comments for the qcr_reg register for more info
|
715 |
|
|
-- regarding the index event control bits.
|
716 |
|
|
-----------------------------------------------------------------------
|
717 |
|
|
quad_count_proc: process( wb_clk_i ) begin
|
718 |
|
|
if rising_edge( wb_clk_i ) then
|
719 |
|
|
--Reset event
|
720 |
|
|
if wb_rst_i = '1' then
|
721 |
|
|
quad_count <= (others =>'0');
|
722 |
|
|
quad_ovflw <= '0';
|
723 |
|
|
quad_unflw <= '0';
|
724 |
3 |
scottnortm |
else
|
725 |
2 |
scottnortm |
--Pre-load count event; either from qcr_reg or index event
|
726 |
3 |
scottnortm |
if qcr_reg(QCR_PLCT) = '1' then
|
727 |
|
|
quad_count(QUAD_COUNT_WIDTH-1 downto 0) <= qrw_reg;
|
728 |
|
|
quad_count(QUAD_COUNT_WIDTH) <= '0';
|
729 |
|
|
end if;
|
730 |
|
|
if (quad_index = '1' and qcr_reg(QCR_INZC) = '1') then
|
731 |
|
|
quad_count <= (others =>'0');
|
732 |
|
|
end if;
|
733 |
|
|
if quad_trans = '1' then
|
734 |
2 |
scottnortm |
if quad_dir = '1' then
|
735 |
|
|
quad_count <= quad_count + 1;
|
736 |
|
|
else
|
737 |
|
|
quad_count <= quad_count - 1;
|
738 |
|
|
end if;
|
739 |
|
|
end if;
|
740 |
|
|
--check for over/under flow
|
741 |
|
|
if quad_count(QUAD_COUNT_WIDTH) = '1' then
|
742 |
|
|
--reset overflow bit
|
743 |
|
|
quad_count(QUAD_COUNT_WIDTH) <= '0';
|
744 |
|
|
--Check MSB-1 to see if it is under or over flow
|
745 |
|
|
if quad_count(QUAD_COUNT_WIDTH-1) = '1' then
|
746 |
|
|
quad_unflw <= '1';
|
747 |
|
|
else
|
748 |
|
|
quad_ovflw <= '1';
|
749 |
|
|
end if;
|
750 |
|
|
end if;
|
751 |
|
|
end if;
|
752 |
3 |
scottnortm |
--reset signals
|
753 |
|
|
if quad_ovflw = '1' then
|
754 |
|
|
quad_ovflw <= '0';
|
755 |
|
|
end if;
|
756 |
|
|
if quad_unflw = '1' then
|
757 |
|
|
quad_unflw <= '0';
|
758 |
|
|
end if;
|
759 |
2 |
scottnortm |
end if;
|
760 |
|
|
end process quad_count_proc;
|
761 |
|
|
|
762 |
|
|
-----------------------------------------------------------------------
|
763 |
3 |
scottnortm |
-- Preocess: quad_comp_proc( wb_clk_i )
|
764 |
|
|
-- Desc: Monitors the quad_count and the qwr_reg to assert the
|
765 |
|
|
-- the quad_comp signal.
|
766 |
|
|
-- Signals: wb_clk_i
|
767 |
|
|
-- wb_rst_i
|
768 |
|
|
-- quad_comp
|
769 |
|
|
-- Note: When enabled, the quad_comp signal will get asserted
|
770 |
|
|
-- every time the quad_count is latched into the qrw reg.
|
771 |
|
|
-----------------------------------------------------------------------
|
772 |
|
|
quad_comp_proc : process( wb_clk_i ) begin
|
773 |
|
|
if rising_edge( wb_clk_i ) then
|
774 |
|
|
if wb_rst_i = '1' then
|
775 |
|
|
quad_comp <= '0';
|
776 |
|
|
elsif (quad_count(QUAD_COUNT_WIDTH-1 downto 0) = qrw_reg) and qcr_reg(QCR_CCME) = '1' and qsr_reg(QSR_CCME) = '0' then
|
777 |
|
|
quad_comp <= '1';
|
778 |
|
|
end if;
|
779 |
|
|
if quad_comp = '1' then
|
780 |
|
|
quad_comp <= '0';
|
781 |
|
|
end if;
|
782 |
|
|
end if;
|
783 |
|
|
end process quad_comp_proc;
|
784 |
|
|
|
785 |
|
|
-----------------------------------------------------------------------
|
786 |
2 |
scottnortm |
-- Process: quad_index_proc( wb_clk_i )
|
787 |
3 |
scottnortm |
-- Desc: Controls the internal quad_index signal. This signal is
|
788 |
2 |
scottnortm |
-- asserted to indicated the occurance of an index event.
|
789 |
3 |
scottnortm |
-- Signals: quad_index
|
790 |
|
|
-- quad_cha_flt
|
791 |
|
|
-- quad_chb_flt
|
792 |
|
|
-- quad_index
|
793 |
|
|
-- Note: None.
|
794 |
2 |
scottnortm |
-----------------------------------------------------------------------
|
795 |
|
|
quad_index_proc : process( wb_clk_i ) begin
|
796 |
|
|
if rising_edge( wb_clk_i ) then
|
797 |
|
|
if wb_rst_i = '1' then
|
798 |
|
|
quad_index <= '0';
|
799 |
3 |
scottnortm |
elsif qcr_reg(QCR_INEN) = '1'
|
800 |
|
|
and qcr_reg(QCR_ECNT) = '1'
|
801 |
|
|
and qcr_reg(QCR_ICHA) = quad_cha_flt
|
802 |
|
|
and qcr_reg(QCR_ICHB) = quad_chb_flt
|
803 |
|
|
and qcr_reg(QCR_IDXL) = quad_idx_flt then
|
804 |
|
|
quad_index_d <= '1';
|
805 |
2 |
scottnortm |
end if;
|
806 |
3 |
scottnortm |
if quad_index_d = '1' then
|
807 |
|
|
quad_index_d <= '0';
|
808 |
|
|
quad_index_d2<= '1';
|
809 |
|
|
end if;
|
810 |
|
|
if quad_index_d2 ='1' then
|
811 |
|
|
quad_index_d2 <= '0';
|
812 |
|
|
quad_index <= '1';
|
813 |
|
|
end if;
|
814 |
2 |
scottnortm |
if quad_index = '1' then
|
815 |
|
|
quad_index <= '0';
|
816 |
|
|
end if;
|
817 |
|
|
end if;
|
818 |
|
|
end process quad_index_proc;
|
819 |
3 |
scottnortm |
|
820 |
|
|
-----------------------------------------------------------------------
|
821 |
|
|
-- Process: quad_irq_proc
|
822 |
|
|
-- Desc: Handles writing to the internal signal quad_irq_int.
|
823 |
|
|
-- This process checks to see if a valid interrupt signal
|
824 |
|
|
-- is asserted along with the corresponding enable bit; if
|
825 |
|
|
-- so, the external interrupt is asserted.
|
826 |
|
|
-- Signals: quad_irq_int
|
827 |
|
|
-- quad_error
|
828 |
|
|
-- quad_ovflw
|
829 |
|
|
-- quad_unflw
|
830 |
|
|
-- quad_index
|
831 |
|
|
-- quad_comp
|
832 |
|
|
-- Note: The external interrupt is cleared after assertion when
|
833 |
|
|
-- all status bits are cleared in the QSR register.
|
834 |
|
|
--
|
835 |
|
|
-----------------------------------------------------------------------
|
836 |
2 |
scottnortm |
quad_irq_proc: process( wb_clk_i ) begin
|
837 |
|
|
if rising_edge( wb_clk_i ) then
|
838 |
|
|
if wb_rst_i = '1' then
|
839 |
|
|
quad_irq_int <= '0';
|
840 |
|
|
elsif ( quad_error = '1' and qcr_reg(QCR_QEIE) = '1' )
|
841 |
3 |
scottnortm |
or ( quad_ovflw = '1' and qcr_reg(QCR_OVIE) = '1' )
|
842 |
|
|
or ( quad_unflw = '1' and qcr_reg(QCR_UNIE) = '1' )
|
843 |
|
|
or ( quad_index = '1' and qcr_reg(QCR_INIE) = '1' )
|
844 |
|
|
or ( quad_comp = '1' and qcr_reg(QCR_CMIE) = '1' ) then
|
845 |
2 |
scottnortm |
quad_irq_int <= '1';
|
846 |
3 |
scottnortm |
elsif quad_irq_int = '1' and
|
847 |
2 |
scottnortm |
not( ( qsr_reg(QSR_QERR) = '1' and qcr_reg(QCR_QEIE) = '1' )
|
848 |
3 |
scottnortm |
or ( qsr_reg(QSR_CTOV) = '1' and qcr_reg(QCR_OVIE) = '1' )
|
849 |
|
|
or ( qsr_reg(QSR_CTUN) = '1' and qcr_reg(QCR_UNIE) = '1' )
|
850 |
|
|
or ( qsr_reg(QSR_INEV) = '1' and qcr_reg(QCR_INIE) = '1' )
|
851 |
|
|
or ( qsr_reg(QSR_CCME) = '1' and qcr_reg(QCR_CMIE) = '1' ) ) then
|
852 |
2 |
scottnortm |
quad_irq_int <= '0';
|
853 |
|
|
end if;
|
854 |
|
|
end if;
|
855 |
|
|
end process quad_irq_proc;
|
856 |
|
|
|
857 |
|
|
end architecture quad_decoder_rtl;
|