Following on from my work yesterday, I needed something to quickly reconfigure the edge triggering FPGA (i.e. to use it as a generic smartcard trigger, if without support for true ISO7816 pattern triggering). My solution was to stick a PMOD connector onto an ESP-01 and just bit-bang it over a clocked serial line:
Simply put, the ESP-01 stands up a temporary wireless access network and a webserver. For all the shit-talking Arduino gets, I’d sure as fuck rather spend 15 minutes writing this in Arduino with HL functions than 3 days trying to debug why DHCP isn’t working.
The webserver serves three endpoints:
- /, which displays a usage message
- /configure?io=X&clk=Y, configuring the IO edge count and clock edge count
- /program, which bit-bangs IO and CLK parameters to the FPGA
The ESP-FPGA communication is a simple fixed-length clocked signal, sampled on each rising edge of a dedicated clock line. It’s extremely slow, holding each signal for 40ms, but as a delay-tolerant configuration activity I don’t really care, an LED on the FPGA board is quickly repurposed to serve as a “programming indicator”.
A trivial Verilog state machine allows us to receive this incoming logic, and set the FPGA’s internal registers accordingly. For future reference and re-use:
always @(posedge prog_clk) begin if(prog_reset == 0) begin prog_shift <= 0; prog_wait_state <= 1; end else begin if(prog_wait_state == 1) begin if(prog_io == 1) begin IO_EDGE_TARGET <= 0; prog_state_io <= 1; prog_state_clk <= 0; end else begin CLK_EDGE_TARGET <= 0; prog_state_io <= 0; prog_state_clk <= 1; end prog_wait_state <= 0; end else begin if(prog_state_io == 1) // start shifting bits in begin IO_EDGE_TARGET <= IO_EDGE_TARGET + (prog_io << prog_shift); end else if(prog_state_clk == 1) begin CLK_EDGE_TARGET <= CLK_EDGE_TARGET + (prog_io << prog_shift); end prog_shift <= prog_shift + 1; end end end
For now, the ESP will always take 32-bit arguments and send the full 32-bits, but there is room for later optimisation.