Search code examples
eventsprocessvhdlclocksynthesis

Why is this not synthesizable? (does not hold its value under NOT(clock-edge))


I'm a software engineer (JAVA/C++) and not an electrical engineer so you can imagine that VHDL is thoroughly confusing to me because I have little idea what the synthesizer is trying to do behind the scenes. And it's telling me it can't synthesize what I believe to be a very simple architecture. (in fact it's doing it for several entities I have so I suspect I am misunderstanding some fundamental concept and repeating the architectural mistake in multiple places.)

Why does this not synthesize... (ERROR - controller.vhd(63): statement is not synthesizable since it does not hold its value under NOT(clock-edge) condition. VHDL-1242 Done: error code 2)

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY controller IS
    PORT (
        ack: out STD_LOGIC := '0';
        data_request: in STD_LOGIC
    );
END controller;

ARCHITECTURE logic OF controller IS
BEGIN
    PROCESS (data_request)
    BEGIN
        if (rising_edge(data_request)) then
            -- other logic will be added here
            ack <= '1';
        elsif (falling_edge(data_request)) then
            -- other logic will be added here too
            ack<='0';
        end if;
    END PROCESS;
END logic;

(Yes, I am fully aware that the "logic" of the process could be replaced by ack <= data_request; but my vhdl source is actually much more complex than this but I have distilled it down to the simplest subset that throws the error. please, don't suggest replacing the process with a different structure/concurrent statement.)

Basically, when the data_request line transitions to high the ack output should be driven high; on the falling edge it should be changed to driven low. (and In each case I want a whole bunch of other stuff to change as well, hence I need the process instead of a concurrent statement, the ack change it just to signal a top-level entity that a request has been completed.)

What is "not holding its value"? What "clock" is it talking about when it says "NOT(clock-edge)"?

I would love an explanation of how to fix this (without changing the structure) and an explanation of what I trying to ask the synthesizer to do and why the synthesizer can't accomplish the goal.


Solution

  • The problem is your signal ack is set on rising edge and falling edge only. The synthesis will try to make your component working in the real world, with physics constraints. In other word you must manage the case there is no events. In your case you just have to add a else statement in your if, like the following way :

    architecture logic of controller is
    
    signal ack_s : std_logic := '0';
    
    begin
        process(data_request)
        begin
            if (rising_edge(data_request)) then
                -- other logic will be added here
                ack_s <= '1';
            elsif (falling_edge(data_request)) then
                -- other logic will be added here too
                ack_s <= '0';
            else then
                ack_s <= ack_s;
            end if;
        end process;
    
        ack <= ack_s;    -- You map the output on the internal signal
    
    end architecture logic;
    

    This way your signal is always mapped to a value. If you try to draw the schematics you will get the point. Also you must use a signal because you can't to the ack <= ack; when ack is an output. As a tip I recommend you to always have an else statement every time you do a if block because on a circuit in the real world you always need a default behavior.