Search code examples
vhdlsimulationxilinxlookup-tablesvivado

Timing simulation in Vivado giving an error


I am trying to implement and simulate ring oscillators in Xilinx Vivado with the LUT6 primitive. When running the Behavioral Simulation it runs fine, and I can see the signal switch every 5 ns due to my added delay. For doing the Power Simulation I need to be able to run the Timing Simulation. Both the Post-Synthesis and Post-Implementation timing simulations produce the result X indicating an error.

I have tried the ring oscillator from this answer as well, and I have the same issue where the Behavioral Simulation works, but the Timing Simulation doesn't. The constraints file should allow ring oscillators. The target language in Vivado is Verilog as Timing Simulation only works on that.

RO_LUT_I0.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
library UNISIM;
use UNISIM.VComponents.all;

entity RO_LUT_I0 is
    Port (
        EndAND    : out STD_LOGIC
    );
end RO_LUT_I0;

architecture rtl of RO_LUT_I0 is
    --amount of ROs
    constant size : integer := 2;
    
    --input signal for specific LUT
    signal I0 : std_logic_vector(0 to size - 1) := (others => '0');
    --output signal
    signal O : std_logic_vector(0 to size - 1);
    
    
    --connect inputs to ground
    signal I1 : std_logic := '0';
    signal I2 : std_logic := '0';
    signal I3 : std_logic := '0';
    signal I4 : std_logic := '0';
    signal I5 : std_logic := '0';

begin
    --instantiation LUT
    gen_LUT6: for i in 0 to size - 1 generate
        LUT6_inst : LUT6
        generic map (
           INIT => X"0000000000000001") -- Only when every input is 0, produce 1. Otherwise produce 0.
        port map (
           O => O(i),  -- LUT general output
           I0 => I0(i),   -- LUT input
           I1 => I1,   -- LUT input
           I2 => I2,   -- LUT input
           I3 => I3,   -- LUT input
           I4 => I4,   -- LUT input
           I5 => I5    -- LUT input
        );
    end generate gen_LUT6;
-- End of LUT6_inst instantiation


    --Create RO and combine into END gate
    process(O)
        variable TempAND : std_logic;
    begin
        --set output as input to create RO
            I0 <= O after 1 ns;
        
        --combine all 
        TempAND := '1';
        for i in 0 to size - 1 loop
            TempAND := TempAND and O(i);
        end loop;
       
        EndAND <= TempAND;
    end process;

end rtl;

RO_LUT_I0_TB.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity RO_LUT_I0_TB is
end RO_LUT_I0_TB;

architecture sim of RO_LUT_I0_TB is
    signal EndAND   : STD_LOGIC := 'U';
    
begin
    --DUT
    i_RO_LUT_I0 : entity work.RO_LUT_I0(rtl) port map(
    EndAND      => EndAND);


    process is
    begin
        wait;
    end process;

end architecture;

RO_LUT_constr.xdc

set_property IOSTANDARD LVCMOS33 [get_ports EndAND]
set_property PACKAGE_PIN A2 [get_ports EndAND]

#Don't touch LUTS
set_property DONT_TOUCH TRUE [get_cells *LUT6*]

# Allow combinatorial loops for all nets
set_property ALLOW_COMBINATORIAL_LOOPS true [get_nets]

set_property SEVERITY {Warning}  [get_drc_checks LUTLP-1]
set_property SEVERITY {Warning} [get_drc_checks NSTD-1]

Solution

  • TL;DR: this isn't a ring oscillator, and you can't synthesise 'after 1ns'. You should read your log files.

    There's too much here for a simple SO question. I think (correct me if I'm wrong) that you're instantiating 2 LUTs, each of which is an inverter. Each input is driven from its own output after a delay which is "after 1ns". The two inverters aren't conencted to each other. The module output in the AND of the two inverter outputs. Correct?

    1. Dump the 'after 1ns'. The delay must be provided by gate delays; that's what makes it a 'ring oscillator'.
    2. Connect the two inverters to each other to make the 'ring'. Tip: your generate must include i+1, i-1, whatever, to connect to the next element. You also have to handle the end condition to wrap around the whole thing.
    3. You're expecting the initialisation of input elements to somehow 'prime' the ring so that it has a value to start for. This will work for a behavioural simulation, but will it work for synthesis? Maybe, maybe not. You'll need to check. If you get Xs you'll need to inject a reset value somehow.
    4. etc. Don't assign an initial value to a signal which is an output, and so on.
    5. You can't run a behavioural simulation of a ring oscillator; it'll just hang up. You're presumably trying to 'fix' this with your 'after 1ns', but you'll need to be smarter. I would just not bother with the behavioural sim, since it tells you nothing.