How to use a rotary encoder with the XuLA2 and the Spartan-6 FPGA.

Another real world example: I'm checking if the Xess Rotary Encoder library works with the encoder I use in a GaN half-bridge design.

TL;DR: yes it works

Xess has a plug-in board with a rotary encoder. I'm not using that module (called a StickIt!) - but I'm using the sample project that comes with it.




Hat Shield Cape Wing. All names were taken except the coolest one.

StickIt!s are tiny modules that work togethet with the XuLa.

A XuLA board is small. Still it manages to expose loads of FPGA pins. Plug the XuLA in a breadboard and you have access to them.

Alternatively,  you can go StickIt!.


To start using the StickIt! modules, there's a motherboard. You dock the XuLA onto it and the signals become available in a few ways:

  • as a Raspberry Pi Hat (it can be used as a Hat or you can plug hats onto it. Your call).
  • as StickIt! ports where you can you can plug StickIt! modules into. The motherboard can host three modules.


In this blog I'm attaching the rotary encoder contacts to StickIt! port PM1. I just use patch cables to make the connections between my GaN PCB and that connector.

If you don't have the motherboard, you can make the connections directly to the XuLA2. I've pasted the xref tables you need to find out the correct pins.


This is the schematic of my rotary encoder. It's identical to the Xess module - except that I've added debounce capacitors.




The encoder is a Panasonic EVQ-VVD00203B Square SMD Encoder.

That's not the same model as the one on the Xess board but it works the same. This one doesn't have a push-button built in.



I'm plugging it into the PM1 of the motherboard. The power comes from the XuLA board, so you have to populate the XuLA PWR jumper and remove all others.

On this image you can see where you have to insert the jumper wires coming from the encoder.

Pin 6, VCC, goes to the 3V3 of the encoder circuit.

Pin 5, GND, to the circuit's GND

Pin 1, DO, to one of the encoder's switch contacts

Pin 2, D2, to the other switch contact.

The table also shows the channel numbers. Use these if you work without the motherboard. They represent the XuLA2 pins.




In this table you can find the mapping between the channel number and the FPGA signal.

You'll use that to define the pins in your project's constraint file.

For the pins that I've used, this is the constraint info.


# PM1 connections for rotary encoder module.
net rotEncA_i   loc=r7;
net rotEncB_i   loc=r16;


Update your project's .ucf file to reflect that.



I haven't changed a single line of code. I just went trough the typical FPGA build steps and generated the bitfile.


> xsload --fpga rotaryencodertest.bit
Success: Bitstream in rotaryencodertest.bit downloaded to FPGA on XuLA2-LX25!


Then I used the Python test script that's part of the project. It checks the (defined in the VHDL project)  register that holds the accumulated value, and prints it to the command line.

To start the test, execute this command:




Rotate the encoder like a madman and see the results on your command prompt:


If you don't have a rotary encoder, break open an old mouse. The scroll wheel is often an encoder.


XuLA2 FPGA - First Impressions of the Development Tools
XuLA2 FPGA - SD Card Read and Write
XuLA2 FPGA - Rotary Encoder and VHDL
XuLA2 FPGA - PWM with Dead Band in VHDL
XuLA2 FPGA - Up the Clock
XuLA2 FPGA - Utility to Generate Pin Assignments