Skip to content

Add FPGA steppers peripheral - #2

Merged
hydra merged 27 commits into
masterfrom
fpga-steppers-10
Jul 27, 2026
Merged

Add FPGA steppers peripheral#2
hydra merged 27 commits into
masterfrom
fpga-steppers-10

Conversation

@hydra

@hydra hydra commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

The peripheral manages 2 banks of 4 stepper outputs (step/dir) signals.

They are split into two banks because of the hardware on the MakerPnPControl board has 2 sockets, one bank per socket.

Step signals are generated as follows:

  • configuring the bank pulse width.
  • compute a set of ramp segments for a motor using the MCU.
  • send the ramp segments to the FPGA.
  • start the sequence.
  • optionally poll for status and read motor position or stop individual motors.

Since the FPGA used on the MakerPnPControl board is cheap and has no DSP/math functions, there is no floating point math at all on the FPGA, the MCU does it. MCUs are better for this anyway. It also means that regardless of the stepper system, the MCU controls the motion calculation and the FPGA executes the motion, uninterrupted by MCU concerns, such as interrupts or task management, the result is a step-accurate jitter free solution.

The units the FPGA works in is a 'step', so there is no drift-over-time concerns in the hardware. The MCU just needs to calculate the amount of steps. The MCU can use encoder feedback to make correction, but that is out-of-scope of the hardware implementation in this PR.

Many human attempts were created prior to this version, all ultimately failed, various reasons:

  • plan s-curves math on FPGA - send position and limit sequence to FPGA from MCU = high LC usage, step drift error
  • switching to a ramp based solution using a position = simpler, but LC issues
  • per-bank peripheral = high LC usage
  • shared common code = failed FPGA placement and high usage.
  • various refactoring attempts = high LC usage, pain and failure.

In the end, the lessons learned and human written test-benches and skeleton code from previous attempts were use to prompt AI (Claude) into making an implementation that works, and has a lower LC usage than this lowly human was able to achieve.

Example s-curve that was calculated in the testbench by capturing the step/dir pulses over time:
image

captured_scurve.csv

Here's the communication log for the s-curve test, see steppers_motion_tb.v.

[PLAN] 17 segments, 100 steps total:
[BUS_WRITE] address: 0004, value: 00000011
  segment 0: SP=50 DM=10 n=1 DECREASING      MOVE
[BUS_WRITE] address: 0010, value: 01000001
[BUS_WRITE] address: 0014, value: 0032000a
  segment 1: SP=40 DM=10 n=2 DECREASING      MOVE
[BUS_WRITE] address: 0010, value: 01000002
[BUS_WRITE] address: 0014, value: 0028000a
  segment 2: SP=20 DM=2 n=3 DECREASING      MOVE
[BUS_WRITE] address: 0010, value: 01000003
[BUS_WRITE] address: 0014, value: 00140002
  segment 3: SP=13 DM=0 n=4 DECREASING      MOVE
[BUS_WRITE] address: 0010, value: 01000004
[BUS_WRITE] address: 0014, value: 000d0000
  segment 4: SP=10 DM=0 n=6 DECREASING      MOVE
[BUS_WRITE] address: 0010, value: 01000006
[BUS_WRITE] address: 0014, value: 000a0000
  segment 5: SP=8 DM=0 n=7 DECREASING      MOVE
[BUS_WRITE] address: 0010, value: 01000007
[BUS_WRITE] address: 0014, value: 00080000
  segment 6: SP=7 DM=0 n=8 DECREASING      MOVE
[BUS_WRITE] address: 0010, value: 01000008
[BUS_WRITE] address: 0014, value: 00070000
  segment 7: SP=6 DM=0 n=9 DECREASING      MOVE
[BUS_WRITE] address: 0010, value: 01000009
[BUS_WRITE] address: 0014, value: 00060000
  segment 8: SP=5 DM=0 n=20 DECREASING      MOVE
[BUS_WRITE] address: 0010, value: 01000014
[BUS_WRITE] address: 0014, value: 00050000
  segment 9: SP=5 DM=0 n=9 INCREASING      MOVE
[BUS_WRITE] address: 0010, value: 09000009
[BUS_WRITE] address: 0014, value: 00050000
  segment 10: SP=6 DM=0 n=8 INCREASING      MOVE
[BUS_WRITE] address: 0010, value: 09000008
[BUS_WRITE] address: 0014, value: 00060000
  segment 11: SP=7 DM=0 n=7 INCREASING      MOVE
[BUS_WRITE] address: 0010, value: 09000007
[BUS_WRITE] address: 0014, value: 00070000
  segment 12: SP=8 DM=0 n=6 INCREASING      MOVE
[BUS_WRITE] address: 0010, value: 09000006
[BUS_WRITE] address: 0014, value: 00080000
  segment 13: SP=10 DM=0 n=4 INCREASING      MOVE
[BUS_WRITE] address: 0010, value: 09000004
[BUS_WRITE] address: 0014, value: 000a0000
  segment 14: SP=13 DM=2 n=3 INCREASING      MOVE
[BUS_WRITE] address: 0010, value: 09000003
[BUS_WRITE] address: 0014, value: 000d0002
  segment 15: SP=20 DM=10 n=2 INCREASING      MOVE
[BUS_WRITE] address: 0010, value: 09000002
[BUS_WRITE] address: 0014, value: 0014000a
  segment 16: SP=40 DM=10 n=1 INCREASING MOVE_HALT
[BUS_WRITE] address: 0010, value: 0a000001
[BUS_WRITE] address: 0014, value: 0028000a
[CTRL] Issuing Start Strobe to Core 0...
[BUS_WRITE] address: 0000, value: 00000100
``

Humans and AI can do clean-up and bug fixing as required in the future. 

@hydra
hydra force-pushed the fpga-steppers-10 branch from 39a35e0 to ad6c7e0 Compare July 27, 2026 12:34
@hydra
hydra merged commit 62b3306 into master Jul 27, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant