/ 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;