The problem is an inconsistency I observed when I compared the result of the synthesis step to the result of the P&R step. The P&R inserts a combinatorial loop which is not present in the synthesis step. The tool flags then for the loop issue in the P&R trace report. I could make the problem disappear by resetting the variable properly but I haven't really grasped why the loop buffer is inserted.
I simplified the VHDL code in question for the purpose of this post. It is a legacy code that resets an internal variable to the value of an input pin, which I suspect to be a bug.
ENTITY InjectCtrl IS
PORT
(
Reset : in STD_LOGIC;
clk : in STD_LOGIC;
inject : in STD_LOGIC;
injector_opens : out STD_ULOGIC;
injector_closes : out STD_ULOGIC
);
END ENTITY;
architecture rtl of InjectCtrl is
begin
Process(Reset, clk)
Variable Delayed_Inject : STD_LOGIC;
Begin
if reset = '0' then
injector_opens <= '0';
injector_closes <= '0';
Delayed_Inject := '0';
Delayed_Inject := Inject; -- issue line
elsif rising_edge(clk) then
injector_opens <= '0';
injector_closes <= '0';
if (Delayed_Inject = '0') then
injector_opens <= '0';
injector_closes <= '1';
else
injector_opens <= '1';
injector_closes <= '0';
end if;
Delayed_Inject := Inject;
end if;
end Process;
end architecture;
The generated RTL diagram looks like this.
The diagram seems to be in line with what the code is specifying. The variable Delayed_Inject samples the value of the inject input every clock cycle, hence the flip-flop. However when the reset signal is de-asserted (reset = '0'), the variable is not set to '0', but instead to the value of the input signal inject. This explains why inject is routed through logic to the SET pin of the flip-flop. So at reset, if inject input is high, RESET pin is low and SET pin is high, which results in an output from the flip-flop being also high. Inversely, if inject is low, RESET pin is high and SET pin is low which gives a low output (D FF with set and reset pin).
The technology view diagrams looks a bit different from what I have expected.
First, notice the inference of two flip-flops for Delayed_Inject instead of one. But what is most interesting is the inference of a loop buffer that is routing the output of the LUT_3222 to itself. Where does that loop come from?
For reference, I am using Lattice Diamond with Synplify as synthesis tool of choice. The target FPGA is from the LFE5U family.


