ADS-B sync and manchester decoding in CPLD

Having put together my miniADSB I needed to extract the actual data from the Manchester encoded bit streams it produced*. Most of the guys out there do it inside the micro controller, like PIC, PICADSB or AVR, but it’s quite a burden for a chip clocked at some 10-20MHz to crunch an incoming 1MHz stream and still do some other useful stuff, not missing out too many incoming frames. Notable exceptions to that rule are guys doing it FPGA style, Mode-S Beast and miniADSBrx, but that’s heavy artillery, and I think a bit overdone.

*Caveat: AD8313, the last stage of miniADSB outputs signal between 0.7 and 1.1V that needs to be properly handled (filters, comparator) to produce useful digital signal. A post on this part will follow, as soon as I have the right solution for that part.

My idea was to join the simplicity of using a micro with the power of programmable gate arrays. In my application I want the micro to do some other work, and the CPLD should handle the simple repetitive task of looking for the ADS-B sync pattern (16 bits) and upon finding it, decode Manchester data that will follow, conveniently shifting it into the micro on the SPI bus. This way AVR is interrupted only when a new byte arrives on the SPI bus, and can handle all the other tasks meanwhile.

I’m no Verilog expert. Any patches to the code, especially improving readability and functional division are welcome. Being as it is, in beta, the code is expected to be improved upon.

This picture serves as a functional description (click to see the whole thing).

adsb2spi simulation


  • adsb_in – output from the comparator, incoming ADS-B signal
  • clk8x – 8MHz clock
  • rst – active low

Outputs (SPI signals):

  • MOSI – Master Output Slave Input, adsb2spi is the bus master, connect to MOSI on the micro.
    Like in the ADS-B signal, MSB first.
  • SCK – 1MHz clock generated by internal logic, sample data on rising edge
  • SS – Slave Select is generated for the duration of data transfer

It’s designed for Xilinx xc9536xl CPLD (I run it on xc9536xl-10VQ44) but will fit everything bigger (it won’t fit anything smaller, because that’s the smallest Xilinx’s CPLD ;).

Mind you, the code is still in beta and needs some work to be declared stable and fully operational. If you want to give it a try, I’ll be more than happy to hear about your thoughts/results.

You can get the code from svn repo at svn:// . The repository includes first and foremost the Verilog file with the actual code (adsb2spi.v), pin mappings that I used (User-Constrains File, adsb2spi.ucf), a testbench waveform I wrote for it (adsb2spi_tf.v) and a Makefile to run the testbench using icarus and display the results using gtkwave. If you just need the code, feel free to copy the adsb2spi.v file to your ISE environment or whatever else you use.

I contributed adsb2spi to the Hackerspace Global Grid’s github, ( ) at .