Problem writing quadrature decoder

With the proviso that such slow edges should NOT be fed into a FPGA. (they have tr/tf specs)

If you have a cpld with hysteresis pin option, (Atmel ATF15xxBE, Xilinx XC2Cxx, Lattice 40xxZE ) then you are ok.

-jg

Reply to
Jim Granville
Loading thread data ...

You can feed any FPGA with excessive transition-time signals, as long as you understand the consequences: The signal will pick up noise and thus create digital glitches as it moves through the threshold, and there will be some cross-current through the inverter, adding some power consumption, but never causing any damage. A slow-transitioning clock is an invitation to disaster, but a logic input usually causes no harm. And you can convert any 2 pins into a one-bit Schmitt input, just with 2 external resistors. Peter Alfke

Reply to
Peter Alfke

Let me try a conclusion after more than 70 postings:

Rotary (or linear) quadrature shaft encoder. After a lengthy exchange of ideas, we found that there are only two winning circuits. Both are equally simple and inexpensive, and both can be used from zero speed to multi-MHz speed. And none has cumulative errors.

Circuit A was presented by Peter Alfke, and it guarantees the suppression of all contact bounce and erratic contact behavior, completely isolating the position-indicating counter from such disturbances. The design pays for this with an angular or linear hysteresis (a.k.a. electronic backlash), that limits its resolution.

Circuit B was presented by John_H, and it guarantees the best possible resolution. This design pays for this with a possibly erratic foward/ backward oscillating content in the counter that indicates the shaft position.

Either design does the best possible job, and thus represents a perfect engineering compromise.

Peter Alfke

Reply to
Peter Alfke

Not if you count registers ;) With Xilinx tools, targeting a Xilinx CPLD, this used 8 more registers than the possible minimum.

...when used with a clean Quadrature signal.

This is actually a pre-filter, so it can be used with any 'standard' quadrature encoder. If you want Circuit A to not count on illegal states, use this line: rotary_event resolution. This design pays for this with a possibly erratic foward/

This is a more classic version, but with one packing twist : It uses the two counter LSBs as the follow-nodes, whilst that section of Circuit A uses two more registers. Circuit A also consumes registers for Event and Direction, and has more latency.

(in a fpga the higher register cost of Circuit A might not bother anyone)

There was another 'Circuit C', submitted by nospam, a more common 4 register vesion, but with illegal states properly handled. It is very easy to follow, as it tabulated the 16 states (8 as comments). [Cost is 2 more registers, than B.]

Below is a version of Circuit B, extended to a) Catch illegal states (for those who think that matters ) b) Does not count on illegal states. Instead, waits one click on POR

You can, of course, optionally add the Sticky-state filter of Circuit A to the front of B or C, if you want to reduce possible visual flicker.

Which I think covers all the bases, for everyone... :)

-jg

module whatCouldGoWrong ( input clk , input [1:0] quad , output reg [7:0] count , output OutByTwoErr );

// used for an asynchronous boundary crossing reg [1:0] rQuad; // change the quadrature input to binary wire [1:0] binQuad = {rQuad[1],^rQuad[1:0]}; // +1 is 0, -1 is 1, ±2 is init only wire dir = (binQuad - count[1:0]) >> 1; // Sense if out by Plus/Minus ONE - IF equal, or out by 2, ignore wire OutByOne = ( count[1:0]-binQuad == 2'b01 ) | ( binQuad-count[1:0] == 2'b01 );

// If out by 2 frequently, your CLK, and/or sensor need attention! // Can feed into an Error counter ( see some CAN Bus controllers ) assign OutByTwoErr = ( count[1:0]-binQuad == 2'b10 ) | ( binQuad-count[1:0] == 2'b10 ); always @(posedge clk) begin rQuad

Reply to
Jim Granville

Here's one way to hook up the processes:

formatting link
formatting link

-- Mike Treseler

Reply to
Mike Treseler

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.