Lattice ICE40UP FPGA中SB_RGBA_DRV原语VHDL实现P&R失败求助
I’ve run into this exact headache when working with ICE40UP’s RGB driver primitives in VHDL—let’s break down what’s happening and how to fix it:
The Root Cause
The SB_RGBA_DRV primitive is built to directly drive the FPGA’s dedicated RGB LED pins with no intermediate output buffers (like the automatic OBUF cells synthesizers add for regular IO ports). When your VHDL code is processed, the tool is inserting an OBUF between the primitive’s RGB2 output and your top-level LED2 port—this violates Lattice’s strict connection rules for this primitive.
Verilog examples usually work because the primitive binding is more explicit, so the tool skips auto-buffering when mapping directly to top ports. VHDL’s component declaration can sometimes trigger this unwanted auto-buffering behavior if not properly constrained.
Step-by-Step Fixes
1. Pin Constraints: Use Dedicated RGB Pins Only
First, double-check your .pcf pin constraint file. The SB_RGBA_DRV only works with the FPGA’s purpose-built RGB LED pins—regular IO pins won’t cut it. For example, on an ICE40UP5K-SG48, the RGB pins are typically:
set_io LED0 PF1 # Maps to RGB0 set_io LED1 PF2 # Maps to RGB1 set_io LED2 PF3 # Maps to RGB2
If you’re using a different package, reference your FPGA’s datasheet to find the correct dedicated RGB pin assignments. Using regular IO pins forces the synthesizer to insert an OBUF, which causes the error.
2. Add VHDL Attributes to Block Auto-Buffering
Even with correct pin constraints, tools like Yosys + nextpnr might still insert buffers for VHDL top-level ports. Add a dont_touch attribute to your top outputs to tell the tool to leave the direct connection intact:
Modify your entity declaration like this:
library ieee; use ieee.std_logic_1164.all; entity led is port ( LED0 : out std_logic; LED1 : out std_logic; LED2 : out std_logic ); -- Prevent synthesizer from adding intermediate buffers attribute dont_touch : boolean; attribute dont_touch of LED0 : signal is true; attribute dont_touch of LED1 : signal is true; attribute dont_touch of LED2 : signal is true; end entity led;
This locks in the direct link between SB_RGBA_DRV’s outputs and your top ports, skipping any unnecessary buffers.
3. Double-Check Your Component Declaration
Make sure your SB_RGBA_DRV component declaration matches Lattice’s official specs exactly. Your current code looks correct, but confirm generic and port names are case-sensitive where required (some tools are strict about this).
Test the Fix
After applying these changes, re-run synthesis and P&R. The "Illegal Connection" error should vanish, as the SB_RGBA_DRV outputs will now connect directly to the dedicated RGB pins without extra buffers.
内容的提问来源于stack exchange,提问作者N.Atema

