/ qcountersf.vhd
qcountersf.vhd
  1  library IEEE;
  2  use IEEE.std_logic_1164.ALL;
  3  use IEEE.std_logic_ARITH.ALL;
  4  use IEEE.std_logic_UNSIGNED.ALL;
  5  --
  6  -- Copyright (C) 2007, Peter C. Wallace, Mesa Electronics
  7  -- http://www.mesanet.com
  8  --
  9  -- This program is is licensed under a disjunctive dual license giving you
 10  -- the choice of one of the two following sets of free software/open source
 11  -- licensing terms:
 12  --
 13  --    * GNU General Public License (GPL), version 2.0 or later
 14  --    * 3-clause BSD License
 15  -- 
 16  --
 17  -- The GNU GPL License:
 18  -- 
 19  --     This program is free software; you can redistribute it and/or modify
 20  --     it under the terms of the GNU General Public License as published by
 21  --     the Free Software Foundation; either version 2 of the License, or
 22  --     (at your option) any later version.
 23  -- 
 24  --     This program is distributed in the hope that it will be useful,
 25  --     but WITHOUT ANY WARRANTY; without even the implied warranty of
 26  --     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 27  --     GNU General Public License for more details.
 28  -- 
 29  --     You should have received a copy of the GNU General Public License
 30  --     along with this program; if not, write to the Free Software
 31  --     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 32  -- 
 33  -- 
 34  -- The 3-clause BSD License:
 35  -- 
 36  --     Redistribution and use in source and binary forms, with or without
 37  --     modification, are permitted provided that the following conditions
 38  --     are met:
 39  -- 
 40  --         * Redistributions of source code must retain the above copyright
 41  --           notice, this list of conditions and the following disclaimer.
 42  -- 
 43  --         * Redistributions in binary form must reproduce the above
 44  --           copyright notice, this list of conditions and the following
 45  --           disclaimer in the documentation and/or other materials
 46  --           provided with the distribution.
 47  -- 
 48  --         * Neither the name of Mesa Electronics nor the names of its
 49  --           contributors may be used to endorse or promote products
 50  --           derived from this software without specific prior written
 51  --           permission.
 52  -- 
 53  -- 
 54  -- Disclaimer:
 55  -- 
 56  --     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 57  --     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 58  --     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 59  --     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 60  --     COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 61  --     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 62  --     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 63  --     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 64  --     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 65  --     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 66  --     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 67  --     POSSIBILITY OF SUCH DAMAGE.
 68  -- 
 69  
 70  entity qcounter is
 71     generic (
 72  		buswidth : integer := 32
 73  		);
 74     port ( 
 75  		obus: out std_logic_vector (buswidth-1 downto 0);
 76  		ibus: in std_logic_vector (buswidth-1 downto 0);
 77  		quada: in std_logic;
 78  		quadb: in std_logic;
 79  		index: in std_logic;
 80  		loadccr: in std_logic;
 81  		readccr: in std_logic;
 82  		readcount: in std_logic;
 83  		countclear: in std_logic;
 84  		timestamp: in std_logic_vector (15 downto 0);
 85  		indexmask: in std_logic;
 86  		filterrate: in std_logic;
 87  		clk: in std_logic
 88  	);
 89  end qcounter;
 90  
 91  architecture behavioral of qcounter is
 92  
 93  signal count: std_logic_vector (15 downto 0);
 94  signal up: std_logic;
 95  signal down: std_logic;
 96  signal countlatch: std_logic_vector (15 downto 0);
 97  signal timestamplatch: std_logic_vector (15 downto 0);
 98  signal quadadel: std_logic;
 99  signal quada1: std_logic;
100  signal quada2: std_logic;
101  signal quadacnt: std_logic_vector (3 downto 0);
102  signal quadafilt: std_logic;
103  signal quadbdel: std_logic;
104  signal quadb1: std_logic;
105  signal quadb2: std_logic;
106  signal quadbcnt: std_logic_vector (3 downto 0);
107  signal quadbfilt: std_logic;
108  signal indexdel: std_logic;
109  signal index1: std_logic;
110  signal index2: std_logic;
111  signal indexdet: std_logic;
112  signal indexcnt: std_logic_vector (3 downto 0);
113  signal indexfilt: std_logic;
114  signal qcountup: std_logic; 
115  signal qcountdown: std_logic;
116  signal udcountup: std_logic; 
117  signal udcountdown: std_logic;
118  signal doclear: std_logic;
119  signal clearonindex: std_logic;	-- ccr register bits...
120  signal latchonindex:std_logic;
121  signal justonce: std_logic;
122  signal abgateindex: std_logic;
123  signal indexsrc: std_logic;
124  signal quadfilter: std_logic;
125  signal countermode: std_logic;
126  signal quaderror: std_logic;
127  signal indexpol: std_logic;
128  signal fixedindexmask: std_logic;
129  signal indexmaskpol: std_logic;
130  signal useindexmask: std_logic;
131  signal abmaskpol: std_logic;
132  signal flimit: std_logic_vector(3 downto 0);
133  
134  
135  begin
136  	aqcounter: process 	(clk,abgateindex, indexpol, indexdel, abmaskpol,
137  	                      quadadel, quadbdel, indexmaskpol, indexmask,
138  								 quadfilter, countermode, doclear, quada2,
139  								 quada1, quadb2, quadb1, index1, index2,
140  								 useindexmask, readcount, timestamplatch, count,
141  								 readccr, countlatch, quaderror, justonce, qcountdown,
142  								 clearonindex, latchonindex, fixedindexmask, qcountup,
143  								 udcountup,udcountdown)
144  
145  	begin
146  		-- new index logic 02/09/2006 PCW
147  		
148  		if abgateindex = '0' then	 		-- not gated by A,B
149  			if indexpol = '1' then
150  				indexsrc	<= indexdel;
151  			else
152  				indexsrc <= not indexdel;
153  			end if;
154  		else									-- gated by A,B
155  			if indexpol = '1' then										  		-- normal index
156  				if abmaskpol = '1' then 
157  					indexsrc <=	quadadel and quadbdel and indexdel;					-- enable by A,B high
158  				else
159  					indexsrc <= (not (quadadel or quadbdel)) and indexdel;		-- enable by A,B low
160  				end if;
161  			else																		-- inverted index
162  				if abmaskpol = '1' then 
163  					indexsrc <=	quadadel and quadbdel and (not indexdel);			-- enable by A,B high
164  				else
165  					indexsrc <= (not (quadadel or quadbdel)) and (not indexdel);-- enable by A,B low
166  				end if;
167  			end if;
168  		end if;
169  
170  		if indexmaskpol = '1' then
171  			fixedindexmask <= indexmask;
172  		else
173  			fixedindexmask <= not indexmask;
174  		end if;
175  
176  		if quadfilter = '1' then
177  			flimit <= "1111";
178  		else
179  			flimit <= "0011";
180  		end if;		
181  		if countermode = '0' and doclear = '0' and (  
182  		(quada2 = '0' and quada1 = '1' and quadb2 = '0' and quadb1 = '0')  or
183  		(quada2 = '0' and quada1 = '0' and quadb2 = '1' and quadb1 = '0')  or
184  		(quada2 = '1' and quada1 = '1' and quadb2 = '0' and quadb1 = '1')  or
185  		(quada2 = '1' and quada1 = '0' and quadb2 = '1' and quadb1 = '1')) then		   
186  			qcountup <= '1';
187  		else 
188  			qcountup <= '0';
189  		end if;			
190  
191  		if (countermode = '1' and doclear = '0' and 
192  		quadb2 = '1' and quada2 = '0' and quada1 = '1') then  -- up down mode: count up on rising edge of A when B is high
193  			udcountup <= '1';
194  		else
195  			udcountup <= '0';
196  		end if;
197  			
198  		if countermode = '0' and doclear = '0' and ( 
199  		(quada2 = '0' and quada1 = '0' and quadb2 = '0' and quadb1 = '1')  or
200  		(quada2 = '0' and quada1 = '1' and quadb2 = '1' and quadb1 = '1')  or
201  		(quada2 = '1' and quada1 = '0' and quadb2 = '0' and quadb1 = '0')  or
202  		(quada2 = '1' and quada1 = '1' and quadb2 = '1' and quadb1 = '0')) then
203  			qcountdown <= '1';
204  		else
205  			qcountdown <= '0';
206  		end if;		
207  	
208  		if (countermode = '1' and doclear = '0' and  
209  		quadb2 = '0' and quada2 = '0' and quada1 = '1') then
210  			udcountdown <= '1';
211  		else
212  		   udcountdown <= '0';
213  		end if;		
214  
215  		if rising_edge(clk) then
216  			
217  
218  			quadadel <= quada;			
219  			quada1 <= quadafilt;
220  			quada2 <= quada1;	
221  
222  			quadbdel <= quadb;
223  			quadb1 <= quadbfilt;			
224  			quadb2 <= quadb1;	
225  
226  			indexdel <= index;
227  			index1 <= indexfilt;			
228  			index2 <= index1;	
229  
230  			
231  			if filterrate = '1' then 
232  			
233  				-- deadended counter for A input filter --
234  				if (quadadel = '1') and (quadacnt < flimit) then 
235  					quadacnt <= quadacnt + 1;
236  				end if;
237  				if (quadadel = '0') and (quadacnt /= 0) then 
238  					quadacnt <= quadacnt -1;
239  				end if;
240  				if quadacnt >= flimit then
241  					quadafilt<= '1';
242  				end if;
243  				if quadacnt = 0 then
244  					quadafilt<= '0';
245  				end if;
246  				
247  				-- deadended counter for A input filter --
248  				if (quadbdel = '1') and (quadbcnt < flimit ) then 
249  					quadbcnt <= quadbcnt + 1;
250  				end if;
251  				if (quadbdel = '0') and (quadbcnt /= 0) then 
252  					quadbcnt <= quadbcnt -1;
253  				end if;
254  				if quadbcnt >= flimit then
255  					quadbfilt<= '1';
256  				end if;
257  				if quadbcnt = 0 then
258  					quadbfilt <= '0';
259  				end if;	
260  
261  				-- deadended counter for index input filter --
262  				if (indexsrc = '1') and (indexcnt < flimit ) then 
263  					indexcnt <= indexcnt + 1;
264  				end if;
265  				if (indexsrc = '0') and (indexcnt /= 0) then 
266  					indexcnt <= indexcnt -1;
267  				end if;
268  				if indexcnt >= flimit then
269  					indexfilt<= '1';
270  				end if;
271  				if indexcnt = 0 then
272  					indexfilt<= '0';
273  				end if;					
274  			end if;
275  			
276  			if (countclear = '1')  or 
277  			((clearonindex = '1') and (indexdet = '1')) then -- rising edge of conditioned index	
278  				doclear <= '1';
279  				if justonce = '1' then
280  					clearonindex <= '0';
281  				end if;
282  			else
283  				doclear <= '0';
284  			end if;		
285  
286  			if ((latchonindex = '1') and (indexdet = '1') ) then	-- rising edge of conditioned index
287  				countlatch <= count;
288  				if justonce = '1' then
289  					latchonindex <= '0';
290  				end if;		
291  			end if;
292  
293  
294  			if	countermode = '0' and (
295  			(quada2 = '0' and quada1 = '1' and quadb2 = '0' and quadb1 = '1')  or	  -- any time both a,b change at same time
296  			(quada2 = '1' and quada1 = '0' and quadb2 = '1' and quadb1 = '0')  or	  -- indicates a quadrature count error
297  			(quada2 = '0' and quada1 = '1' and quadb2 = '1' and quadb1 = '0')  or
298  			(quada2 = '1' and quada1 = '0' and quadb2 = '0' and quadb1 = '1')) then
299  			 	quaderror <= '1';
300  			end if;
301  
302  			if up /= down then
303  				timestamplatch <= timestamp;	 		-- time stamp whenever we count
304  				if up = '1' then 
305  					count <= count + 1; 
306  				else
307  					count <= count - 1;
308  				end if;
309  			end if;	
310  
311  			if doclear = '1' then
312  				count <= x"0000";
313  			end if;
314  
315  			if loadccr = '1' then	
316  				quaderror <= ibus(15);
317  				abmaskpol <= ibus(14);
318  				-- latchonprobe (bit 13);
319  				-- probepol (bit 12);
320  				quadfilter <= ibus(11);
321  				countermode <= ibus(10);
322  				useindexmask <= ibus(9);
323  				indexmaskpol <= ibus(8);
324  				abgateindex <= ibus(7);
325  				justonce <= ibus(6);
326  				clearonindex <= ibus(5);
327  				latchonindex <= ibus(4);
328  				indexpol <= ibus(3);
329  			end if;
330  		end if; --(clock edge)
331  
332  		if (index1 = '1') and (index2 = '0') and ((fixedindexmask = '1') or (useindexmask = '0')) then
333  			indexdet <= '1';
334  		else
335  			indexdet <= '0';
336  		end if;
337  
338  		if (qcountup = '1' or udcountup = '1' ) and doclear = '0' then
339  			up <= '1';
340  		else
341  		  	up <= '0';
342  		end if;
343     
344  		if (qcountdown = '1' or udcountdown = '1' ) and doclear = '0'  then
345  			down <= '1';
346  		else
347  		  	down <= '0';
348  		end if;	 
349  			
350  		obus <= (others => 'Z');
351  	
352  		if	 (readcount = '1') then
353  			obus(31 downto 16) <= timestamplatch;
354  			obus(15 downto 0) <= count;
355  		end if;		
356  		if (readccr = '1') then
357  				obus(31 downto 16) <= countlatch;
358  				obus(15) <= quaderror;
359  				obus(14) <= abmaskpol;		
360  				obus(11) <= quadfilter;
361  				obus(10) <= countermode;
362  				obus(9) <= useindexmask; 
363  				obus(8) <= indexmaskpol;
364  				obus(7) <= abgateindex;	
365  				obus(6) <= justonce;							
366  				obus(5) <= clearonindex;
367  				obus(4) <= latchonindex;
368  				obus(3) <= indexpol;
369  				obus(2) <= index1;
370  				obus(1) <= quadb1;
371  				obus(0) <= quada1;
372  		end if;
373  	end process;
374  end behavioral;