Well, so far (in previous blogs) I have managed to get the board power up and detected by Vivado hardware manager, but that's only part of the way there. Whilst I can upload a bitstream to the FPGA I need to know how to upload a useful bitstream. The simplest "Hello World" for FPGAs is to take a clock signal and slow it down to blink an LED as a visible frequency. To do this you need to know what pins a clock and an LED are connected to.
Schematic reverse engineering
There are a number of ways to reverse engineer the schematic. I'm going to explain a few as they may be useful for your own reverse engineering adventures even if they didn't work for me.
Visual inspection
If you're lucky enough to have a simple double-sided board and reasonably consumer-friendly components then sometimes you can see the PCB traces you need. Unfortunately this board has at least 4 layers and a thick matt black solder mask. Not a chance of gleaning anything visually - even with a microscope.
Continuity testing
Sometimes this is easier than visual inspection anyway. Simply use a multi-meter with an audible beep for continuity testing. It's unlikely that the voltage applied by the meter to the (obviously) powered off device will cause any damage. If you have one that reacts quickly then sometimes you can attach one probe to a test point and drag along the pins of an IC. This obviously works best when you can get to the pins. Something like SOIC, TTTSOP or QFP is reasonably easy. QFN is harder but possible. Bear in mind that if pins are connected via transistors, buffers, etc. then this may not always work.
Oh dear. The Artix-7 device on this board is BGA, so no pins are within reach of a probe. Sometimes you get lucky and there are lots of vias under the BGA. Even tented vias can be probed with a sharp enough tip. No such luck here. Not a via in sight under the IC.
Desoldering
If I really want to know where the solder balls connected I could remove the device. I don't have the skills or equipment to reball a 484-ball FPGA with any chance of success. I could buy a second sacrificial device and desolder than knowing it would never work again. Unfortunately my post on EEVBlog seemed to cause some interest in the device. The really cheap ones (mostly in the US) had been snapped up. There were fewer around and they seemed to be around the £50+ point now. Considering this was a "try to snap up a bargain" project, it didn't seem worth it.
Heavy duty bit-bashing
I know I can load a bitstream. What if I set all the pins I could to an output and play around with them. I had heard of others creating hundreds of UARTs and having each one "shout" out a unique value. Then I just probe pins with a scope and serial decoder and see what they say. Genius! Unfortunately I don't even have a clock input that would be required to do this. I could always set a group of pins high at once and just slowly eliminate them as I go. It would work, but it sounds painfully slow.
JTAG boundary scan
Many of us think of JTAG as a device programming protocol, but that's not really it's original purpose. JTAG (Joint Test Action Group) was conceived as a way to test PCBs without needing a huge bed of nails jig. It is possible to control the pins of a JTAG compatible device and set them high/low independently of the device inside. I've never used JTAG this way but it sounds perfect.
A breakthrough
Before i could start on the JTAG boundary scan, I had a breakthrough. Remember earlier when I said earlier that the interest on EEVBlog had a downside of driving up prices? Well, it also had the benefit if having more eyes on the device. Someone spotted an uncannily similar crowd-funded device called the NiteFury on Crowd Supply. A bit of digging on other forums and it seems that they are indeed the same device. It seems likely they were developed in parallel rather than one ripping off the other. There seem to be minor differences with the location of the connectors but that seems to be all I've found.
Luckily the NiteFury does have some documentation and a schematic. This saved me a lot of time and also solved some issues I probably wouldn't have been able to - how to determine what clocks were available and where they went.
This bit of luck meant that not only would it be possible to use the SQRL Acorn - my £35 investment had netted me an open source development board that went for $329 on Crowd Supply. I can't actually find any info on whether this actually shipped to backers. Considering the fiasco surrounding the SQRL Acorn it may not have. However, I haven't seen anyone complaining about the NiteFury either.
Blinky lives!
So, armed with this new information I thought the first thing to do would be to use the clocks to blink some LEDs. There are 3 available clocks - a 90Mhz single-ended EMC clock, a 100Mhz differential clock from PCIe, and a 200Mhz clock for the DDR. With the board still not connected to a PCIe slot, I connected the 90Mhz and 200Mhz up and blinked an LED off each at 1Hz. Here are the Verilog and constraints file I used.
blinky.v
module blinky( input emc_clk, input ddr_clk_p, input ddr_clk_n, output led_a1, output led_a2, output led_a3, output led_a4 ); reg[31:0] count200; wire clk200; reg blink200; // IO buffer for differential clock input IBUFDS ibuf200 (.I(ddr_clk_p), .IB(ddr_clk_n), .O(clk200)); always @ (posedge clk200) begin if (count200 == 100000000-1) begin count200 <= 0; blink200 <= ~blink200; end else begin count200 <= count200+1; end end reg[31:0] count90; reg blink90; always @ (posedge emc_clk) begin if (count90 == 45000000-1) begin count90 <= 0; blink90 <= ~blink90; end else begin count90 <= count90+1; end end assign led_a1 = blink200; assign led_a2 = blink90; assign led_a3 = 1; //off assign led_a4 = 1; //off endmodule
sqrl-acorn.xdc
#2.5V 200MHz differential clock from X1 (intended for DDR) set_property PACKAGE_PIN J19 [get_ports ddr_clk_p] set_property IOSTANDARD LVDS_25 [get_ports ddr_clk_p] set_property PACKAGE_PIN H19 [get_ports ddr_clk_n] set_property IOSTANDARD LVDS_25 [get_ports ddr_clk_n] #3.3V 90MHz single-ended clock from U10 set_property PACKAGE_PIN V22 [get_ports emc_clk] set_property IOSTANDARD LVCMOS33 [get_ports emc_clk] set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets emc_clk_IBUF] #3.3V LEDs (active low) set_property PACKAGE_PIN G3 [get_ports led_a1] set_property IOSTANDARD LVCMOS33 [get_ports led_a1] set_property PULLUP true [get_ports led_a1] set_property DRIVE 8 [get_ports led_a1] set_property PACKAGE_PIN H3 [get_ports led_a2] set_property IOSTANDARD LVCMOS33 [get_ports led_a2] set_property PULLUP true [get_ports led_a2] set_property DRIVE 8 [get_ports led_a2] set_property PACKAGE_PIN G4 [get_ports {led_a3}] set_property IOSTANDARD LVCMOS33 [get_ports {led_a3}] set_property PULLUP true [get_ports {led_a3}] set_property DRIVE 8 [get_ports {led_a3}] set_property PACKAGE_PIN H4 [get_ports {led_a4}] set_property IOSTANDARD LVCMOS33 [get_ports {led_a4}] set_property PULLUP true [get_ports {led_a4}] set_property DRIVE 8 [get_ports {led_a4}]
So - did it work? Hell yes! I'm not sure I've ever been so pleased to see two LEDs flashing. Whilst I still want to do more with the board I think I can call this a success. I've got a nice small Artix-7 development board that I can now program to do something more useful than its original purpose.
I will be putting it into a PCIe slot soon. My main PC doesn't have room for that large heatsink and I've been sorting out an old PC to use. Once it's in there it may be a little more awkward to use too. Also, what were they thinking saying it could go in an M.2 slot of a laptop! If it needs a heatsink like that then it would probably start a fire crammed in there.
Top Comments