Search code examples
vhdlvivado

Vivado VHDL: attribute 'stable not implemented


I am trying to detect when an oscillating signal stops oscillating. I thought the best approach would be to use the 'stable attribute. When I go to synthesis, it gives an error saying "attribute 'stable not implemented".

I use it only in the line clock_stable <= UART_TX'stable(20 ns);, which from what I read online is how I am supposed to use it. It's a predefined attribute, so I don't understand why it isn't being recognized? The source file properties show it is using VHDL_2008, and when I try to just use VHDL, it still gives the same error. Is there a package I am missing? Did I declare this wrong? Any insight helps, thanks!

Here is the code I am trying to synthesize, which is a bidirectional data signal, where the data bits can either be written (output on SDI port) or read (output on UART_RX port). When a burst of data is done being sent/received, UART_TX stops oscillating and is held high. It is possible it is incorrect- I am still testing it, but I am having a lot of difficulty getting the 'stable attribute to work. I am expecting to see a tristate buffer between UART_RX and SDI, where read_en controls the direction. Data will flow from UART_RX -> SDI most of the time, except when we are reading (MSB of Chip ID is 1), which will go from SDI -> UART_RX. I don't think all the specifics of the rest of the code are necessary for my issue; it is just all of the predefined attributed that Vivado is saying are not implemented.

library ieee;
use ieee.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.all;


entity top is
    port(
        CLK : in std_logic;

        UART_RX : inout std_logic;
        SDI : inout std_logic;

        UART_TX : in std_logic;
        SCK : out std_logic
        
        
        );
end entity;

architecture behav of top is

--Clock signals
signal clock : std_logic;


signal data_from_sys : std_logic;

--Data to be taken from SDI to UART_RX
signal data_from_device : std_logic;

--Clock signal from  UART_TX to SCK
signal sck_uarttx_sig : std_logic;

--Chip bits count
signal chip_b : integer := -1;

--Chip ID 
signal chip_ID : std_logic_vector(7 downto 0);

--Address bits count
signal address_b : integer := -1;

--Read enable: 0 for write, 1 for read
signal read_en : std_logic := '0';

--Clock stable boolean: True when SCK has been stable (end of a message)
signal clock_stable : boolean;


begin

    sck_uarttx_sig <= UART_TX;
    SCK <= sck_uarttx_sig;
    
    clock <= CLK;

    -- When read_en='1', SDI set to 'Z' to be able to read from it.
    SDI <= 'Z' when read_en='1' else data_from_sys;
    UART_RX <= 'Z' when read_en='0' else data_from_device;
    

    clock_stable <= UART_TX'stable(20 ns);
    

    process
    begin
        
        if(clock_stable) then
            read_en <= '0';
            chip_b <= -1;
            address_b <= -1;
        
        else
        
    
            if(falling_edge(sck_uarttx_sig)) then
                if(chip_b < 8) then
                    read_en <= '0';
                    --Record chip ID to know if R/W later
                    chip_ID <= UART_RX & chip_ID(7 downto 1);
                    chip_b<= chip_b + 1;
                    
                    data_from_sys <= UART_RX;
                    
                elsif(address_b < 8) then
                    read_en <= '0';
                    address_b <= address_b + 1;
                    
                    data_from_sys <= UART_RX;
                    
                    -- READ: If we are at last bit of address and the chip ID indicates read (MSB=1), 
                    -- set read enable high. Else, chip ID indicates write, set read enable low
                    if(address_b=7 and chip_ID(7)='1') then
                        read_en <= '1';
                    else
                        read_en <= '0';
                    end if;
                
                -- Chip ID and Address written already, write/read data
                else
                    if(read_en='1') then
                        data_from_device <= SDI;
                    else
                        data_from_sys <= UART_RX;
                    end if;
                end if;
            end if;
            
            
        end if;
    
    end process;
        
    
    
    

end behav;



Solution

  • VHDL is a hardware description language and as such defines elements to describe hardware behavior. In simple words it has different uses:

    1. Describe the behavior of hardware to be synthesized into actual hardware. This is of course limited to the possibilities of the target hardware.
    2. Describe the behavior of actual hardware. Since real parts have all kinds of timely effects (and more), more language elements can be used to model these effects.
    3. Describe the behavior of simulated hardware. Here you can use the full set of the language, as far as your simulator supports it.

    To my knowledge there is no part in any existing FPGA that could realize the attribute stable with user-supplied intervals.

    The same is true for a lot more elements of VHDL. For example, the assignment clause after is another one, and the file handling stuff.

    This means you cannot use such elements in your source to synthesize.

    Instead, invent some other way to detect the condition you're after.

    Just some quick ideas:

    • A timeout counter, which is reloaded with each (rising or falling, not both) edge of the watched clock. You will need another clock with a higher frequency.
    • An external analog part like a retriggerable mono stable multivibrator.