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