/ qcountersfp.vhd
qcountersfp.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 qcounterp 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  		probe: in std_logic;
 87  		filterrate: in std_logic;
 88  		clk: in std_logic
 89  	);
 90  end qcounterp;
 91  
 92  architecture behavioral of qcounterp is
 93  
 94  signal count: std_logic_vector (15 downto 0);
 95  signal up: std_logic;
 96  signal down: std_logic;
 97  signal countlatch: std_logic_vector (15 downto 0);
 98  signal timestamplatch: std_logic_vector (15 downto 0);
 99  signal quadadel: std_logic;
100  signal quada1: std_logic;
101  signal quada2: std_logic;
102  signal quadacnt: std_logic_vector (3 downto 0);
103  signal quadafilt: std_logic;
104  signal quadbdel: std_logic;
105  signal quadb1: std_logic;
106  signal quadb2: std_logic;
107  signal quadbcnt: std_logic_vector (3 downto 0);
108  signal quadbfilt: std_logic;
109  signal indexdel: std_logic;
110  signal index1: std_logic;
111  signal index2: std_logic;
112  signal indexdet: std_logic;
113  signal indexcnt: std_logic_vector (3 downto 0);
114  signal indexfilt: std_logic;
115  signal probedel: std_logic;
116  signal probe1: std_logic;
117  signal probe2: std_logic;
118  signal probedet: std_logic;
119  signal probecnt: std_logic_vector (3 downto 0);
120  signal probefilt: std_logic;
121  signal qcountup: std_logic; 
122  signal qcountdown: std_logic;
123  signal udcountup: std_logic; 
124  signal udcountdown: std_logic;
125  signal clearonindex: std_logic;	-- ccr register bits...
126  signal latchonindex:std_logic;
127  signal latchonprobe:std_logic;
128  signal justonce: std_logic;
129  signal abgateindex: std_logic;
130  signal indexsrc: std_logic;
131  signal quadfilter: std_logic;
132  signal countermode: std_logic;
133  signal quaderror: std_logic;
134  signal indexpol: std_logic;
135  signal probepol: std_logic;
136  signal fixedindexmask: std_logic;
137  signal indexmaskpol: std_logic;
138  signal useindexmask: std_logic;
139  signal abmaskpol: std_logic;
140  signal flimit: std_logic_vector(3 downto 0);
141  
142  
143  begin
144  	aqcounter: process 	(clk,abgateindex, indexpol, indexdel, abmaskpol,
145  	                      quadadel, quadbdel, indexmaskpol, indexmask,
146  								 quadfilter, countermode, quada2,
147  								 quada1, quadb2, quadb1, index1, index2,
148  								 useindexmask, readcount, timestamplatch, count,
149  								 readccr, countlatch, quaderror, justonce,
150  								 clearonindex, latchonindex, latchonprobe)
151  
152  	begin
153  		-- new index logic 02/09/2006 PCW
154  				
155  		if abgateindex = '0' then	 		-- not gated by A,B
156  			if indexpol = '1' then
157  				indexsrc	<= indexdel;
158  			else
159  				indexsrc <= not indexdel;
160  			end if;
161  		else									-- gated by A,B
162  			if indexpol = '1' then										  		-- normal index
163  				if abmaskpol = '1' then 
164  					indexsrc <=	quadadel and quadbdel and indexdel;					-- enable by A,B high
165  				else
166  					indexsrc <= (not (quadadel or quadbdel)) and indexdel;		-- enable by A,B low
167  				end if;
168  			else																		-- inverted index
169  				if abmaskpol = '1' then 
170  					indexsrc <=	quadadel and quadbdel and (not indexdel);			-- enable by A,B high
171  				else
172  					indexsrc <= (not (quadadel or quadbdel)) and (not indexdel);-- enable by A,B low
173  				end if;
174  			end if;
175  		end if;
176  
177  
178  		if indexmaskpol = '1' then
179  			fixedindexmask <= indexmask;
180  		else
181  			fixedindexmask <= not indexmask;
182  		end if;
183  
184  		if quadfilter = '1' then
185  			flimit <= "1111";
186  		else
187  			flimit <= "0011";
188  		end if;		
189  		if countermode = '0' and (  
190  		(quada2 = '0' and quada1 = '1' and quadb2 = '0' and quadb1 = '0')  or
191  		(quada2 = '0' and quada1 = '0' and quadb2 = '1' and quadb1 = '0')  or
192  		(quada2 = '1' and quada1 = '1' and quadb2 = '0' and quadb1 = '1')  or
193  		(quada2 = '1' and quada1 = '0' and quadb2 = '1' and quadb1 = '1')) then		   
194  			qcountup <= '1';
195  		else 
196  			qcountup <= '0';
197  		end if;			
198  
199  		if (countermode = '1' and 
200  		quadb2 = '1' and quada2 = '0' and quada1 = '1') then  -- up down mode: count up on rising edge of A when B is high
201  			udcountup <= '1';
202  		else
203  			udcountup <= '0';
204  		end if;
205  			
206  		if countermode = '0' and ( 
207  		(quada2 = '0' and quada1 = '0' and quadb2 = '0' and quadb1 = '1')  or
208  		(quada2 = '0' and quada1 = '1' and quadb2 = '1' and quadb1 = '1')  or
209  		(quada2 = '1' and quada1 = '0' and quadb2 = '0' and quadb1 = '0')  or
210  		(quada2 = '1' and quada1 = '1' and quadb2 = '1' and quadb1 = '0')) then
211  			qcountdown <= '1';
212  		else
213  			qcountdown <= '0';
214  		end if;		
215  	
216  		if (countermode = '1' and  
217  		quadb2 = '0' and quada2 = '0' and quada1 = '1') then
218  			udcountdown <= '1';
219  		else
220  		   udcountdown <= '0';
221  		end if;		
222  
223  		if rising_edge(clk) then
224  			
225  
226  			quadadel <= quada;			
227  			quada1 <= quadafilt;
228  			quada2 <= quada1;	
229  
230  			quadbdel <= quadb;
231  			quadb1 <= quadbfilt;			
232  			quadb2 <= quadb1;	
233  
234  			indexdel <= index;
235  			index1 <= indexfilt;			
236  			index2 <= index1;	
237  
238  			probedel <= probe;
239  			probe1 <= probefilt;			
240  			probe2 <= probe1;	
241  
242  			
243  			if filterrate = '1' then 
244  			
245  				-- deadended counter for A input filter --
246  				if (quadadel = '1') and (quadacnt < flimit) then 
247  					quadacnt <= quadacnt + 1;
248  				end if;
249  				if (quadadel = '0') and (quadacnt /= 0) then 
250  					quadacnt <= quadacnt -1;
251  				end if;
252  				if quadacnt >= flimit then
253  					quadafilt<= '1';
254  				end if;
255  				if quadacnt = 0 then
256  					quadafilt<= '0';
257  				end if;
258  				
259  				-- deadended counter for A input filter --
260  				if (quadbdel = '1') and (quadbcnt < flimit ) then 
261  					quadbcnt <= quadbcnt + 1;
262  				end if;
263  				if (quadbdel = '0') and (quadbcnt /= 0) then 
264  					quadbcnt <= quadbcnt -1;
265  				end if;
266  				if quadbcnt >= flimit then
267  					quadbfilt<= '1';
268  				end if;
269  				if quadbcnt = 0 then
270  					quadbfilt <= '0';
271  				end if;	
272  
273  				-- deadended counter for index input filter --
274  				if (indexsrc = '1') and (indexcnt < flimit ) then 
275  					indexcnt <= indexcnt + 1;
276  				end if;
277  				if (indexsrc = '0') and (indexcnt /= 0) then 
278  					indexcnt <= indexcnt -1;
279  				end if;
280  				if indexcnt >= flimit then
281  					indexfilt<= '1';
282  				end if;
283  				if indexcnt = 0 then
284  					indexfilt<= '0';
285  				end if;		
286  
287  				-- deadended counter for probe filter --				
288  				if (probedel = '1') and (probecnt < flimit ) then 
289  					probecnt <= probecnt + 1;
290  				end if;
291  				if (probedel = '0') and (probecnt /= 0) then 
292  					probecnt <= probecnt -1;
293  				end if;
294  				if probecnt >= flimit then
295  					probefilt<= '1';
296  				end if;
297  				if probecnt = 0 then
298  					probefilt<= '0';
299  				end if;						
300  			end if;
301  			
302  
303  
304  			if	countermode = '0' and (
305  			(quada2 = '0' and quada1 = '1' and quadb2 = '0' and quadb1 = '1')  or	  -- any time both a,b change at same time
306  			(quada2 = '1' and quada1 = '0' and quadb2 = '1' and quadb1 = '0')  or	  -- indicates a quadrature count error
307  			(quada2 = '0' and quada1 = '1' and quadb2 = '1' and quadb1 = '0')  or
308  			(quada2 = '1' and quada1 = '0' and quadb2 = '0' and quadb1 = '1')) then
309  			 	quaderror <= '1';
310  			end if;
311  
312  			if up /= down then
313  				timestamplatch <= timestamp;	 		-- time stamp whenever we count
314  				if up = '1' then 
315  					count <= count + 1; 
316  				else
317  					count <= count - 1;
318  				end if;
319  			end if;	
320  
321  			if (countclear = '1') or ((clearonindex = '1') and (indexdet = '1')) then -- rising edge of conditioned index	
322  				count <= x"0000";
323  				if justonce = '1' then
324  					clearonindex <= '0';
325  				end if;
326  			end if;		
327  
328  			if ((latchonindex = '1') and (indexdet = '1') ) then	-- rising edge of conditioned index
329  				countlatch <= count;
330  				if justonce = '1' then
331  					latchonindex <= '0';
332  				end if;		
333  			end if;
334  
335  			-- latchonprobe has priority on latched count
336  			if ((latchonprobe = '1') and (probedet = '1') ) then	-- rising edge of conditioned probe
337  				countlatch <= count;
338  				if justonce = '1' then
339  					latchonprobe <= '0';
340  				end if;		
341  			end if;
342  
343  			if loadccr = '1' then	
344  				quaderror <= ibus(15);
345  				abmaskpol <= ibus(14);
346  			   latchonprobe <= ibus(13);
347  				probepol <= ibus(12);
348  				quadfilter <= ibus(11);
349  				countermode <= ibus(10);
350  				useindexmask <= ibus(9);
351  				indexmaskpol <= ibus(8);
352  				abgateindex <= ibus(7);
353  				justonce <= ibus(6);
354  				clearonindex <= ibus(5);
355  				latchonindex <= ibus(4);
356  				indexpol <= ibus(3);
357  			end if;
358  		end if; --(clock edge)
359  
360  		if (index1 = '1') and (index2 = '0') and ((fixedindexmask = '1') or (useindexmask = '0')) then
361  			indexdet <= '1';
362  		else
363  			indexdet <= '0';
364  		end if;
365   
366        -- probedet changed 10/09 so that changing probepol dynamically will not generate a latch event
367  		if ((probe1 = '1') and (probe2 = '0') and (probepol = '1')) 		-- rising edge
368        or ((probe1 = '0') and (probe2 = '1') and (probepol = '0'))	then 	-- falling edge
369  			probedet <= '1';
370  		else
371  			probedet <= '0';
372  		end if;
373  
374  		if (qcountup = '1' or udcountup = '1' ) then
375  			up <= '1';
376  		else
377  		  	up <= '0';
378  		end if;
379     
380  		if (qcountdown = '1' or udcountdown = '1' ) then
381  			down <= '1';
382  		else
383  		  	down <= '0';
384  		end if;	 
385  			
386  		obus <= (others => 'Z');
387  	
388  		if	 (readcount = '1') then
389  			obus(31 downto 16) <= timestamplatch;
390  			obus(15 downto 0) <= count;
391  		end if;		
392  		if (readccr = '1') then
393  				obus(31 downto 16) <= countlatch;
394  				obus(15) <= quaderror;
395  				obus(14) <= abmaskpol;		
396  				obus(13) <= latchonprobe;
397  				obus(12) <= probepol;
398  				obus(11) <= quadfilter;
399  				obus(10) <= countermode;
400  				obus(9) <= useindexmask; 
401  				obus(8) <= indexmaskpol;
402  				obus(7) <= abgateindex;	
403  				obus(6) <= justonce;							
404  				obus(5) <= clearonindex;
405  				obus(4) <= latchonindex;
406  				obus(3) <= indexpol;
407  				obus(2) <= index1;
408  				obus(1) <= quadb1;
409  				obus(0) <= quada1;
410  		end if;
411  	end process;
412  end behavioral;