I have two combinational blocks, fnA.vhd and fnB.vhd. I have a higher level of hierarchy, test.vhd, which instantiates these two functions, and also infers a clocked register, each with an input mux. There it a top-level port, contrlAnotB, that drives the control inputs to all three muxes.
If input port contrlAnotB = 1, then the output of fnA will drive the input to fnB, but the output of fnB is not allowed to drive the input to fnA (rather, the register output stateReg does.) So, when contrlAnotB = 1, there can be no combinational loop.
If input port contrlAnotB = 0, then the output of fnB drives the input to fnA, but the output of fnA is not allowed to drive the input to fnB (rather, it is driven by stateReg.) So when contrlAnotB = 0, there can be no combinational loop.
Synplicity finds lots of combinational paths of type fnA -> fnB -> fnA, and also fnB -> fnA -fnB, even though I know there is no value of contrlAnotB which would allow these paths.
How can I resolve this? There are lots of cases where one may want to execute two functions, in either order, and register the result. (This instance is extracted from a block encryptor/decryptor. If encrypting, the steps are executed in one order, if decrypting, then the reverse.) I'd like to use define_false_path to disallow consideration of these paths, but can't find a syntax that will work (as there are no registers, top-level ports, or black boxes in the combinational loops it is seeing.)
Any advice or suggestions would be greatly appreciated. Thanks -
View attachment testForOutside.txt
- - - Updated - - -
-- So, I tried to attach the source files, but somehow failed. I will just paste test.vhd below.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity test is
port (clk : in std_logic;
reset : in std_logic;
loadState : in std_logic;
byteIn : in std_logic_vector(7 downto 0);
contrlAnotB : in std_logic;
outRequest : in std_logic;
outByte : out std_logic_vector(7 downto 0)
);
end test;
architecture rtl of test is
-- component declarations
component fnA
port (x : in std_logic_vector(7 downto 0);
y : out std_logic_vector(7 downto 0));
end component fnA;
component fnB
port (x : in std_logic_vector(7 downto 0);
y : out std_logic_vector(7 downto 0));
end component fnB;
attribute syn_hier : string;
-- attribute syn_hier of rtl: architecture is "Hard";
attribute syn_hier of rtl: architecture is "Firm";
-- main data path
signal Ain : std_logic_vector(7 downto 0);
signal Aout : std_logic_vector(7 downto 0);
signal Bin : std_logic_vector(7 downto 0);
signal Bout : std_logic_vector(7 downto 0);
signal stateIn : std_logic_vector(7 downto 0);
signal stateReg : std_logic_vector(7 downto 0);
begin
aInMux_proc : process (contrlAnotB, Bout,
stateReg)
begin
if (contrlAnotB = '1') then -- A first, then B
Ain <= stateReg(7 downto 0) ;
else -- first B, then A
Ain <= Bout;
end if;
end process aInMux_proc;
-- Here is A
fnA_0 : fnA port map(
x => Ain,
y => Aout
);
bInMux_proc : process (contrlAnotB, Aout,
stateReg)
begin
if (contrlAnotB = '1') then -- A first, then B
Bin <= Aout;
else -- first B, then A
Bin <= stateReg(7 downto 0) ;
end if;
end process bInMux_proc;
-- Here is B
fnB_0 : fnB port map(
x => Bin,
y => Bout
);
stateRegMux_proc : process (contrlAnotB, Aout, Bout,
byteIn, loadState)
begin
if (loadState = '1') then
stateIn <= byteIn;
else
if (contrlAnotB = '1') then -- A first, then B
stateIn <= Bout;
else -- first B, then A
stateIn <= Aout;
end if;
end if;
end process stateRegMux_proc;
stateReg_proc : process (clk, reset)
begin
if (reset = '1') then
stateReg <= (others => '0');
elsif (rising_edge(clk)) then
stateReg <= stateIn;
end if;
end process stateReg_proc;
outMux_proc : process (stateReg, outRequest)
begin
if (outRequest = '1') then
outByte <= stateReg;
else
outByte <= (others => '0');
end if;
end process outMux_proc;
end rtl;
- - - Updated - - -
-- My apologies for how this reads, somehow the formatting removed all the white space.