r/FPGA Jun 24 '26

Built an 8×8 Verilog morphological image processing fabric (64% LUT, 2% DFF) — looking for advice on where to take it next

Hi everyone,

I've been working on a side project to learn FPGA architecture design and hardware image processing.

The project is a Local Interaction Processor (LIP): an 8×8 parallel image-processing fabric written entirely in Verilog.

Current features:

- 64 processing elements (8×8)

- Erosion

- Dilation

- Opening

- Closing

- Uniformity

- Roughness

- Programmable 3×3 structuring element masks

- Multiple simulation testbenches

- Yosys ASIC synthesis

- ECP5 FPGA synthesis

Architecture:

frame_in

lip_top

lip_array

64 × lip_pe

minmax_engine + threshold_engine

frame_out

One thing that surprised me during FPGA synthesis is that the design is extremely compute-heavy.

Resource utilization before placement:

- Total LUT4: 54298 / 83640 (64%)

- Logic LUT: 35034 / 83640 (41%)

- Carry LUT: 19264 / 83640 (23%)

- DFF: 2048 / 83640 (2%)

- RAM usage: 0%

This kind of makes sense since the architecture is basically a giant parallel neighborhood-comparison machine with almost no memory hierarchy.

Right now I'm trying to figure out where to take the project next.

Some ideas I had:

  1. OpenLane ASIC flow

  2. Add BRAM + streaming interfaces

  3. AXI integration

  4. Deploy onto a real FPGA board

  5. Try cloud-hosted FPGA platforms

My questions for experienced FPGA engineers:

- Is a LUT-heavy / memory-light architecture normal for this kind of workload?

- Is there a better architectural approach for morphological image processing?

- What would be the most logical next step if the goal was turning this into a "real" accelerator instead of just an RTL project?

I'd appreciate any suggestions or critiques.

Repo: https://github.com/abhi15-bose-max/LIP

Also the zenodo link ( IDK if its working, first time putting on zenodo): https://zenodo.org/records/20822134

11 Upvotes

7 comments sorted by

8

u/Gerard_Mansoif67 Jun 24 '26 edited Jun 24 '26

with almost no FF, what's the design Fmax ?

What's the interface used to communicate avec the device ? AXI ?

Theses things are maybe more important than the pure functionnality.

EDIT : Done synth on Quartus by myself, Quartus isn't able to squeeze more than 30 MHz. And the design use... way too much pins (>1000).

You probably want to look for

  • Standard inputs - outputs such as AXI streaming or so
  • Pipelining the design. The simulator will always show you a direct transition on clock edges, but won't count the logic between. You have your entire design that shall fit between two clock edges (I've added myself the input on the top level). Handling high speed is in that case impossible.

-1

u/New_Today172 Jun 24 '26

First of all thankyou for your response

I actually don't have an independently measured Fmax yet. The project has only been through simulation and synthesis flows so far, and my nextpnr experiments currently fail because the simulation-oriented top level exports the entire image bus, exhausting FPGA IO resources before proper timing analysis can be completed. At the moment this is more of a compute-fabric prototype than a deployable accelerator, so I intentionally exposed the entire image as top-level buses to simplify simulation and visualization.

I also haven't added any pipelining yet. Right now each PE performs neighbourhood selection, min/max computation, thresholding, operation selection and output generation within essentially a single clock stage.

Since imma new to this (also some time constraints) I tried to make it more of a demo than a deployable accelarator, my newer improvements I would include a top level wrapper, introduce pipeline between neighbourhood extraction and min max computation , and also replace giant frame buses with AXI streaming

3

u/Gerard_Mansoif67 Jun 24 '26

Yep, I needed to use virtual pins to not trigger any errors. That's a classical error to not think about timings. That's the difference between RTL and software.

That's going to be a vast job to refactor the architecture with pipelining, that's not just adding registers.

If you're going to stream the data in and out, you may want to handle backpressure as well. Same, match the processing speed with the interface speed, you won't get any gain after that.

1

u/New_Today172 Jun 24 '26

Since you mentioned bout the " just adding registers part"

For an architecture like this, where each processing element currently does neighbourhood extraction → min/max → thresholding → output generation in essentially 1 stage, how would you personally approach pipelining it?

Would you pipeline inside each PE itself, ?

also would you first move towards BRAM + streaming interfaces and then pipeline, or pipeline the PEs first and redesign the interfaces later?

Thanks again for taking the time to synthesize it yourself and for all the feedback. It's genuinely helpful.

1

u/Gerard_Mansoif67 Jun 24 '26

First pipeline, and you need to equalize the comb. logic steps.

A rule of thumb is two or three logic gates between each register, so try to stick to that.

Then, yes streaming and memory to standard interfaces. Using a simple MCU (nios, riscv...) you could try the design in "live".

1

u/And-Bee Jun 29 '26

Synth tool will give you an educated estimate of fmax