Using Claude Code to work with FPGAs

How I'm using AI agents for FPGA work

July 7, 202612 minutes

Using Claude Code to work with FPGAs

I’ve been working a lot lately with Claude Code. Since I started using it in February it has totally consumed me. I’m now quite confident that how-to blogs on FPGA design - at least the kind of blog posts that I used to write - will be more and more irrelevant as time goes by. In this post I’m just going to write about how I have been using Claude Code, and how it has changed the way that I work.

Example: The customer request

The other day, a customer reached out: “I bought the Opsero ABC FMC card and I’d like to use it with XYZ dev board. Do you have a ref design for that?”.

I don’t. But I do have one for another dev board and I know that Claude Code can easily port it to the new dev board. The setup takes me about 10 minutes, and the design is typically done and verified on hardware by Claude Code in a few hours time.

My workflow: I clone opsero-agent, I open Claude Code in that repo, then I say: “clone the ref design for ABC FMC card, add a dev branch to it and develop a new target design for XYZ dev board. i have connected the hardware that you need to test everything. you can commit and push to the dev branch when you have a clean build. let me know when its working on hw.”

Keep in mind, Claude Code is not starting from scratch on this ref design - although it probably would do fairly well if it was - it’s actually leveraging all of the existing Opsero ref designs to get the job done.

To explain opsero-agent. It’s a Git repo that contains information about all of the Opsero products and ref designs. It has scripts that can be used by agents for testing and debugging those designs, plus info for connecting to the FPGA Board Repository MCP server. It’s nothing complicated, just relevant information for Claude Code that is organized so that it can pull context on products and designs as it is needed. This is a repo that I have so far been keeping private as I build on it, but I plan to release a public version of it that Opsero customers or anyone can use.

What plan am I on?

This is an important question because the results that you get out of Claude Code will depend on what plan you are using and how you are using it. Also, some people are holding back from trying Claude Code because they hear that it is expensive. But it really depends on what you do with it.

I am using Claude Code Max 20x plan at the moment. So my company pays $200 USD per month for the subscription. I do not enable the option to pay for extra tokens when the limit is reached, and I do not use the API, so my expense is limited to $200 USD per month.

What is my token usage like?

My token usage has been highly dependent on the type of tasks that I’ve been giving to Claude Code. In all cases, I rarely hit the token limit.

For creating reference designs, debugging them, testing hardware and this kind of work, I find that the token usage is very low. If this was all that I did, I could be fine on the Max 5x plan. In these use cases, I am typically not using parallel agents - one agent working on the task is usually enough. I could probably have multiple agents working on different designs/fixes/problems in parallel, and that would make better use of my token allowance, but I find it difficult to context-switch so much and I prefer to keep my own brain focused on one thing at a time.

Where I tend to use a lot of tokens is in work that I have done for the FPGA Board Repository. For that, I often use multiple agents in parallel to do tasks that consume a lot of tokens. Why multiple agents? For context management. One example task: read the user guide for XYZ dev board and figure out if it has an FMC connector and if so, what are the supported VADJ voltages. And do this for a few hundred dev boards. Well if you give that task to a single agent, it would get through a few boards and its context window would already be pretty full. In reality, the agent would usually try to avoid that outcome - it would try to get the work done by doing greps on the userguides and looking for keywords instead of actually reading the text. That leads to poor (inaccurate) results, so the better solution is to create a skill for the task that a fresh agent (with an empty context window) could follow to get the task done on a single board, or maybe just a few. Then you use an orchestrator agent to coordinate the subagents to get the work done on all the hundreds of dev boards. Another token-heavy task is: look at an image of the board and work out exactly what connectors it has and their specific types.

When doing that high-token-usage work, I have reached the token limit a few times. But I try to stop before I get there, and my projects are small. People working on big projects, like at Uber or Amazon, would regularly go above the subscription quota, which is why they pay big token bills. For most people that read this blog, I think the subscription token quota is probably more than enough.

What is it good at?

It’s surprisingly good at lots of things. If you think that AI produces crap code, try Opus 4.8 and see if your opinion still holds.

  • Creating block designs in Tcl.
    It leverages all of the Vivado example designs so it’s surprisingly good to put together a complete block design from scratch. You can say “make me a Vivado project and a block design with the MRMAC IP for the VCK190 board connected to the on-board QSFP28 cage” and it will get that done in minutes.
  • Driving the AMD Xilinx tools.
    Since the tools can all be driven by Tcl or Python scripts, Claude Code does really well at driving them. I hardly ever open the GUI anymore.
  • Debugging designs and code.
    Load the bitstream over JTAG. Run the application and review the UART output. Not working? Fix the bugs in the code, rebuild, retest and repeat until its working.
  • Writing software.
    Standalone applications, Linux applications, drivers, you name it.

What about RTL? I don’t actually do much of that, so I wont comment on it. My guess is that if its not good at it now, it will get good at it soon enough.

Lessons I’ve found most useful

Don’t fill the context window

Learning to manage the context window effectively has been the most important thing that I’ve done to improve the results that I’ve been able to get from Claude Code.

Setup a context window monitor in the status bar, so that you always know how full the context window is. Whenever the context window gets too high, say above 60%, try to wrap up the current task and move to a new session. Results degrade with a full context window. Don’t get to the point of context compaction.

When I started managing the context window, I got much better at knowing when to use subagents and skills, and I got much better results. If you don’t manage the context window at all, you’ll often find agents cutting corners and getting poor results as a consequence. This is not because the agents are lazy, or that they are trying to save you tokens, its just because they are trying to conserve their context window and prevent context bloat. If you throw a big task at an agent, it’s going to make strategic shortcuts to get the job done without bloating its context window. If you instead give an agent a small job, it will do everything it was told because it knows that the task is small enough not to fill its context window. So the way to get the best results on big tasks is always to break the task into chunks that subagents can handle. Skills are a great way to define those tasks.

Set it up to be autonomous

In my case, most of my work involves testing physical hardware, and they are usually FPGA dev boards and FMC cards. I always try to setup the agent to be able to complete the whole task cycle, from design, to hardware validation. To do this, sometimes you only need to connect the JTAG and UART cables, but to test more complex hardware and software you sometimes need more.

For example, a lot of Opsero ref designs have a PetaLinux build that is setup to boot from SD card. Claude Code cannot reflash the SD card, physically plug it into the board and flip the power switch, so my setup and designs need to provide solutions to enable those steps.

For powering the board on and off, I like to use Shelly Plugs that are controlled over the WiFi network. They’re not expensive either. Digital Loggers has a multiple socket product with a cabled Ethernet connection and looks like a pretty good option. Whatever you use, you want Claude Code to be able to power cycle one or more boards independently.

For re-loading an SD card - I manually load the SD card once and connect the dev board’s Ethernet port to my network so that Claude Code can SSH into PetaLinux and re-write the SD card directly from PetaLinux. If you don’t need SD boot, there are cleaner options like TFTP boot where the board can boot directly off files that are on the network.

The idea is to create a setup that Claude Code has complete control of. Debug iterations can be many and can take hours. Rebuilds are slow. Take yourself out of the loop, and let Claude Code do the work autonomously. This has been a game changer for me and I have only scratched the surface on this in terms of how far I’ve taken it.

What if your design’s output is an image or video that gets displayed on a monitor? How could Claude Code validate that? Simplest solution is to connect a webcam to your computer, point it at the monitor and let Claude Code use it to take photos of the monitor and analyze them. A more precise solution would be to use a PiKVM V4 or JetKVM that will sit on the HDMI or DisplayPort line and allow Claude Code to take snapshots and pull images over the network. My point is that there is always a way to give Claude Code autonomy over your setup.

Use hooks

Before I started using hooks, I had little annoyances with Claude Code. It would repeatedly do things that I asked it not to do, or forget to do something that I asked it to do. For example “make sure you always source the AMD Xilinx tools before launching a build”. Then seconds later it would try to launch a build before sourcing the tools. That would fail, produce an error output and Claude Code would then source the tools. Why it behaves like this for some things, I have no idea, but the solution is to use hooks. Hooks can be used to trigger on certain commands that Claude Code is about to run, and they tell it to stop or to “source the tools first” or whatever the case might be.

Another useful hook to have is a dont-modify-generated-files hook. This will trigger when an agent tries to modify a generated file or any file that’s not version controlled. It just reminds the agent that it is modifying a generated file and that its work might get overwritten on the next build. Before using this hook, I’ve had instances where the agent fixed a problem only for the code to be lost because it wasn’t in a tracked file.

Expect Claude Code to make mistakes - try to prevent them or limit their damage by setting up hooks.

Work on Git branches

It took me a while to get comfortable letting Claude Code make git operations on my git repos. After many weeks managing git myself, I finally started letting Claude Code add, commit and push files to my git repos. It still does make mistakes, but I’ve found that you can limit the damage by doing two things: use hooks, and always work on branches.

With hooks you can setup reminders to prevent dumb git commands. For example, if an agent tries to do “git add -A”, I have a hook that will trigger and say “are you sure that there are no generated files in this add?”. That just forces the agent to stop and check what it has sweeped up into the staging area.

Then you can get into the habit of always working with git branches. If Claude Code ever commits generated files, private files, or just makes a mess of things, you can always clean-up the branch and eventually do a squash-merge to main, then delete the dev branch, erasing the messy history.

The future

I heard about chemistry labs using Claude Code and robots to autonomously run chemistry experiments. They are discovering all sorts of things and advancing science at a speed we couldn’t have dreamed of before.

In the hardware and FPGA space we can do similar things now. Setup all the hardware, tell the agent what you need the hardware to do and give it the tools to verify the results. I’ve been really inspired by the chemistry lab example to see what kind of amazing things I might be able to develop here in the office with all of the crazy high-performance hardware that I have available to me. No doubt I’ll be writing more about it in future posts.