std_logic_vector signals in sensitivity list process

Discussion in 'VHDL' started by Steven Kauffmann, Dec 21, 2007.

  1. Hello all,

    I have some questions about how to use std_logic_vector signals in the
    sensitivity list of a process.

    First of all, is the sensitivity list like a comparator in hardware
    and does it continuously checks if the value changes? Or is the
    sensitivity list only important when simulating the design?

    If I use a std_logic_vector signal in the sensitivity list, are all
    the bits of this signal compared or is only one bit(MSB of LSB) used?

    Is there a difference between those two sensitivity lists?

    process(port_a(4 downto 0))
    -- do something
    end process

    process(port_a(3), port_a(2), port_a(1), port_a(0))
    -- do something
    end process


    Steven Kauffmann, Dec 21, 2007
    1. Advertisements

  2. Steven Kauffmann

    paragon.john Guest


    Sensitivity lists are relevant only in simulation. A synthesizer
    should warn you, however, if you have any signals missing from your
    sensitivity list, so as to let you know that you may have a simulation/
    synthesis mismatch.

    I believe your two examples would be dealt with in the same way, you
    could also just do the following...

    -- do something
    end process

    paragon.john, Dec 21, 2007
    1. Advertisements

  3. Yes, one has 5 bits and the other has 4 bits ;)

    Note that the use of asynchronous processes is usually optional.
    Using a synchronous process template eliminates concerns about
    sensitivity lists and many other things.
    sync_template : process(reset, clock) is
    -- declarations here
    if reset = '1' then
    elsif rising_edge(clock) then
    end if;
    end process sync_template;
    -- Mike Treseler
    Mike Treseler, Dec 22, 2007
  4. So this means that the process below is not working when it's
    implemented in hardware this because the sensitivity list is ignored
    and so the process will never be updated?

    -- do something
    end process;
    Steven Kauffmann, Dec 24, 2007
  5. Steven Kauffmann

    kennheinrich Guest

    Not quite. VHDL is fundamentally a simulation language, which, when
    written using certain common styles, allow it to be used as a source
    language for hardware synthesis. This code really could have two ways
    to interpret it: one in a simulation environment, which is exactly
    what the official language definition explains, and one interpretation
    as a hardware description, which is fuzzier. The idea behind using
    certain common coding styles is to make sure the behaviour of your
    code in simulation and synthesis are the same. That's what's meant by
    "synthesis/simulation mismatch".

    For simulation purposes, a process with a sensitivity list will run
    exactly once at initialization (although in no particular order w.r.t.
    other processes' initialization steps), and when the signal changes.
    If you specify the wrong sensitivity list by accident, your process
    won't respond as you expect (either ignoring events on the signal you
    wanted to use, or firing at apparently random other times).

    Generally, if you just want a process that responds asynchronously,
    immediately, to a set of signals, (like if you're writing a simple
    logic gate or an asynchronous memory read), you can skip the
    sensitivity list altogether and the compiler will figure out the right
    sensitivity list automatically, by looking at every signal that gets
    read in the process. You want to either specify every signal correctly
    or specify no signals at all in the sensitivity list. Otherwise
    there's a good chance that you messed up.

    Your question about "comparator in hardware" doesn't quite catch the
    idea. If you wanted to follow this analogy, think of a process as
    specifying some kind of piece of logic that might be a mixture of
    clocked and combinatorial. The sensitivity list defines those inputs
    which, if they have an event on them, may cause the output to change.
    This means that those signals are either directly connected to the
    circuit output through gates, or are used as clock input edges. (This
    is admittedly a sloppy analogy.)

    When you want to write something behind a clocked register (like a
    counter, state machine, etc), you typically _only_ specify the clock
    signal in the sensitivity list. Then you put the entire body of the
    process inside an "if rising_edge(clk)..." statement. The combination
    of these two things tells the synthesizer to generate the
    combinatorial logic specified inside the "if" statement, with a flop
    on each output signal you assign to. This again, is admittedly a
    sloppy description of the synthesis process :)

    If you write processes that don't follow one of these three styles
    (clocked, combinatorial with no sensitivity, or combinatorial with
    complete sensitivity), you're either doing the wrong thing (if you're
    a beginner) or are trying to do something fancy (if you're a more
    advanced user). If you're trying to be fancy as an advanced user,
    there's still a good chance you're wrong, at least the first few
    times :)

    And so as to make sure to answer your last question:

    blah blah...

    will run in simulation at initialization and when any subelement on
    port_a (or port_a in its entirety) changes. In hardware, as long as
    port_a is the only signal you look at inside your process, you should
    be generating a simple combinatorial function of port_a. If
    "blah_blah_bah" reads signals _other_ than port_a, or doesn't have the
    complete sensitivity list (as in the 4 vs 5 signal discrepancy Mike
    pointed out), you're most likely generating something which you didn't
    want, regardless of whether you're simulating or synthesizing.

    Hope this helps,

    - Kenn
    kennheinrich, Dec 24, 2007
  6. The way the sensitivity list is synthesized is going to dependon the tool
    being used. Aside from an extra bit in the sensitivity list the two would
    function the same. But synthesis could be completely different. In our
    synthesis tool the "sensitivity list" is completely ignored in some
    situations. We actually have a coding guide for our tool that states how
    the sensitivity list will be synthesized based on the code inside the block.

    Check to see if your synthesis tool has a coding guide for using sensitivity
    Dwayne Dilbeck, Jan 2, 2008
  7. Steven Kauffmann

    KJ Guest

    The only 'tool dependency' would be because the tool does not conform to the
    Well, they would likely synthesize to the exact same thing....but the
    synthesized result would differ from that of simulation because of the
    different signals in the sensitivity list. The 'correct' one would be the
    simulation result, the synthesized result would be wrong.
    Bragging about LRM non-compliance??
    I prefer the approved standards myself as opposed to a vendor's shortcuts.
    Check the LRM instead.

    I admit that I do prefer the usual synthesizer's ignoring of the sensitivity
    list and putting up a warning to indicate when I have an incomplete list or
    a signal that does not belong but that not being the standard, but I MUCH
    MORE strongly prefer simulation results to match synthesized results.

    But by not using processes other than clocked ones where 'clock' (or 'clock'
    and 'reset') is the extent of the sensitivity list means I normally don't
    even have to bother with this issue at all.

    Kevin Jennings
    KJ, Jan 2, 2008
  8. Bragging about LRM non-compliance??
    Uhm...NO....I hate non conformance, but that is a battle I lost a long time
    When ever we have non-conformance it is caused by one of three issues. 1)
    We screed up, 2) A competitor screwed up and we now have to match thier
    functionality, or 3) the customer requested we have an alterante path that
    is not compliant.

    The comment to check his vendors RTL style guide was to address items 2 and
    3. If his problem is due to item #1, then it has to be fixed. But cases 2
    and 3 are more common in my experience. Granted...My company will break LRM
    for any customer that waves enough money at us.(As will most EDA companies)
    It just drives me crazy when we make non-conformance a default option
    becuase a customer wants it.

    I have actually seen two seperate companies want LRM non conformance, but
    implemented differently. Niether wanted to use a command line switch to
    activate it. Both were holding up big money deals until they got thier
    enhancement. Nasty.
    Dwayne Dilbeck, Jan 3, 2008
  9. Steven Kauffmann

    Andy Guest

    Let's face it, the 800 lb gorilla (Synopsys) decided a long time ago
    that they were going to ignore sensitivity lists in synthesis, and
    everyone else followed suit, because customers (waiving money) wanted
    tools that work "just like Synopsys", instead of "just like the LRM".
    Ditto for std_logic_arith, etc.

    It really galls me that when we requested that Synopsys add a command
    line feature (like modelsim) to only compile certain design unit types
    found in the file(s) (i.e. only architectures, etc.). They replied
    that the LRM prohibited such a practice! One could argue that the LRM
    prohibits out of order compilation of units within one file (an ncsim
    and modelsim option), and I seriously doubt that interpretation was
    intended by the authors, but it says nothing requiring compiling every
    design unit in a file.

    Andy, Jan 3, 2008
  10. Bragging about LRM non-compliance??
    Uhm...NO....I hate non conformance, but that is a battle I lost a long time
    When ever we have non-conformance it is caused by one of three issues. 1)
    We screed up, 2) A competitor screwed up and we now have to match thier
    functionality, or 3) the customer requested we have an alterante path that
    is not compliant.

    The comment to check his vendors RTL style guide was to address items 2 and
    3. If his problem is due to item #1, then it has to be fixed. But cases 2
    and 3 are more common in my experience. Granted...My company will break LRM
    for any customer that waves enough money at us.(As will most EDA companies)
    It just drives me crazy when we make non-conformance a default option
    becuase a customer wants it.

    I have actually seen two seperate companies want LRM non conformance, but
    implemented differently. Niether wanted to use a command line switch to
    activate it. Both were holding up big money deals until they got thier
    enhancement. Nasty.
    Dwayne Dilbeck, Jan 3, 2008
  11. Yes I want to do something fancy, but it is not working and I think I
    know the problem after that I read your post. But I don't know a
    solution for it.

    As I already mentioned in my first post, I have to do something in a
    process when there is an event on a output port of an other component
    described in VHDL. That component is a complex algorithm and because I
    don't know how many clock pulses it need before its calculation is
    ready, I want to use an other process to check if there is an event on
    the output port. When there is an event, I know that the calculation
    of the algorithm is done.

    Because I thought that a sensitivity list wakes up a process when
    there's an event on the signals in its list. I write the following

    result_ready <= not(result_ready);
    end process;

    I thought that when the output of the complex algorithm changed, the
    result_ready signal would also change because of the sensitivity list.
    This is not working in hardware. The reason for that, I think, is that
    the signal output_complex_algorithm is not used in the process, only
    in the sensitivity list. The sensitivity list is not a comparator but
    these signals are directly connected with some logic as you said. But
    because I don't use the signals in the sensitivity list, it's not
    working. Is this correct what I'm saying?


    Steven Kauffmann, Jan 4, 2008
  12. Steven Kauffmann

    KJ Guest

    Then the other component should be generating an 'output_valid' signal
    to flag when the calculation is ready. This signal would be true on
    each and every clock cycle when there is some new output ready.
    'Events' don't synthesize well, because synthesis tools choose to
    ignore sensitivity lists. This makes the synthesized result different
    than from what you'll see in simulation. Other than to use a
    sensitivity list for looking for rising or falling edges of clock
    signals you shouldn't bother with them....but do pay attention to and
    fix any synthesis warnings that pop out about them (more on that
    Per the VHDL standard, what you've written is correct, the problem is
    that synthesis tools do not follow the standard when it comes to
    sensitivity lists. They basically ignore the sensitivity list and
    simply look at the rest of the code in the process. Given your code
    above, your synthesis tool should have generated a warning that signal
    'output_complex_algorithm' is not used in the process and will be
    ignored. That's the tools way of saying, I'm violating the language
    standard but at least I'm telling you about it. The reason it is
    ignoring it is because it does not get used anywhere in the process
    (other than in the sensitivity list...which the synthesis tool

    Now take a look at your process from the perspective of something that
    has blatantly chosen to ignore the sensitivity list and looks what's

    result_ready <= not(result_ready);

    This will generate a free running, uncontrollable oscillator if
    synthesized. Since it is also a combinatorial loop (i.e. feedback
    with no intervening flip flop) the synthesis tool should flag this as
    a 'warning' as well.

    The other type of warning you can get from synthesis tools in regards
    to sensitivity lists is an incomplete sensitivity list. In your
    process, the signal 'result_ready' was used within the process but was
    not in the sensitivity list. Again, the synthesis tool should
    generate a warning to that effect. It is doing this because it went
    off and determined what IT thinks your process SHOULD be sensitive to
    and found that you did not include a signal.

    Although the problem is technically with the synthesis tool for
    violating the language standard, you have to live with it and design
    around it lest you end up with hardware that doesn't work. Peruse the
    list of warnings from synthesis and make sure you really understand
    their implications. As you should be able to verify, the two types of
    warnings that I believe you'll find right now regarding the
    sensitivity list must be cleaned up because they represent ways that
    the synthesized result is completely different from simulation.
    Blaming the synthesis tool will get you nowhere, this behavior has
    been there for a looooong time (although don't interpret that to mean
    that if you run across other ways that synthesis differs from the
    language standard that you shouldn't open a service request, synthesis
    tools have lots of bugs).

    Synthesis tool 'warnings' can many times be design errors. The only
    thing that the synthesis tool considers as an 'error' is something
    that prevents it from generating an output file, anything else is a
    'warning'. Some examples:
    Violating specified timing requirements? 'Warning'.
    Completely change the logic by ignoring sensitivity list? 'Warning'
    I think so...get out the fine tooth comb and peruse the warnings that
    are no doubt present in the output of the synthesis tool and clean
    them all up and you'll be much closer to a working system.

    Kevin Jennings
    KJ, Jan 4, 2008
  13. Steven Kauffmann

    Andy Guest

    Kevin has given excellent advice. While I abhor the synthesis tools'
    ignorance of sensitivity lists, at least they do give you warnings
    that they cannot completely implement the list's effects. It is also
    interesting that they are perfectly willing to generate a latch, which
    is an artifact of the behavior due at least partially to the
    sensitivity list.

    If you try to think about what kind of hardware would be needed to
    implement an "event detector", such a thing would be very risky to
    design in an FPGA or ASIC without very explicit timing control, which
    is something that is generally best left to controlling clocks and
    paths between clocked registers.

    Besides, in the real implementation, how do you know that the
    circuit's output does not change until it magically has the right
    answer? Maybe it changes multiple times before settling on the right
    answer. What happens if the valid output is the same data twice in a
    row (there would be no change to the data, but it represents two valid
    pieces of data)? This is the reason you need to have that circuit
    either guarantee that output will be valid on specific clock cycles
    (usually a fixed cycle delay from the input, etc.), or it must give
    you a signal that says the data is or will be valid. Both are valid
    design techniques, and are universally used.

    Andy, Jan 4, 2008
  14. As KJ says, this is certainly valid VHDL and should do what you expect in

    But the trouble is that synthesis tools cannot generally translate VHDL into
    hardware (this is equally true for all the hardware-C efforts out there; any C
    or C++ construct capable of translation into hardware already has a VHDL
    equivalent.) Now some of these limitations are due to the current state of the
    synthesis tools (whether VHDL or other) but some are fundamental to what is
    achievable in hardware.

    The upshot is that, for synthesis, you need to "think hardware" first and
    foremost, and create something that WILL synthesise. Then and only then, worry
    about the sensitivity list to provide the simulator with information to make the
    simulation behaviour match the real hardware.

    Again as KJ says, the "clean" way in this case is for "complex_algorithm" to
    provide a data_valid signal.

    But assuming it cannot, (e.g. it's someone else's code) we have to find a way
    around the problem.

    Which is to detect and announce changes in the output from "complex_algorithm".

    Thinking hardware; you are right that a comparator is part of the solution. But
    we are detecting changes in the output; therefore comparing the output with an
    old copy of the output will work.

    You also said that "complex_algorithm" took an unknown number of clock pulses;
    implying it is a clocked component, so assume it produces at most one result per
    clock. (Two per clock is possible; let's not discuss that here!) Therefore we
    can use the same clock to clock a storage element for our "old copy".


    if rising_edge(clk) then
    old_output <= output_complex_algorithm;
    -- new_data_clocked <= new_data; -- ignore, but see below
    end if;
    end process;

    will store the current output until the next cycle, and present the previous
    output during this cycle. It only does anything when there is an event on "clk"
    therefore that is the only signal required in the sensitivity list.

    process (old_output, output_complex_algorithm)
    if old_output = output_complex_algorithm then
    new_data <= 0;
    new_data <= '1';
    end if;
    -- assuming new_data is of type std_logic, or simply
    -- new_data <= old_output /= output_complex_algorithm;
    -- if new_data is boolean;
    end process;

    The second process is unclocked; it will simply produce gates. It needs BOTH
    signals shown in its sensitivity list.

    It will synthesise correctly without them; however if you omit old_output, you
    will get incorrect SIMULATION results, because new_data will go '1' when new
    data comes in; however in the following cycle, when "old_output" updates, the
    simulator will not wake up the process to retract new_data. This is what the
    "missing signals in sensitivity list" synthesis warning is about.

    It can also be expressed as a single statement; this is simply shorthand for
    the above; the tools will work out the sensitivity list from the statement
    because what can be expressed in such a statement is strictly limited in scope.

    new_data <= old_output /= output_complex_algorithm; -- boolean
    -- or for std_logic
    new_data <= '0' when old_output = output_complex_algorithm else '1';

    Note that "new_data" would normally be stored in a register of its own, as
    commented out in the first process; in the current form it is present for less
    than a cycle; but guaranteed to be correct at the clock rising_edge, in the SAME
    CYCLE as the new input (which may or may not be important to you).

    If you want a stored "new_data" output (a clean signal, but one cycle late) you
    can combine both processes into one:

    if rising_edge(clk) then
    old_output <= output_complex_algorithm;
    new_data_clocked <= old_output /= output_complex_algorithm;
    end if;
    end process;

    and because you are only interested in the comparator output at the time of the
    clock edge, NO other signal is required in the sensitivity list. (Which is good
    synchronous design).

    The fact that it is one cycle late may not be of any importance to you; simply
    use "old_output" downstream instead of "output_complex_algorithm" and it is in
    the correct cycle; you have just added one cycle to your pipeline depth.

    Sorry if this is a bit pedantic, but I hope that the step by step approach makes
    it clear.

    - Brian
    Brian Drummond, Jan 4, 2008
  15. Steven Kauffmann

    kennheinrich Guest

    Watch out for one fine point though: a simple check of "output not
    equal to input" is not always equivalent to a "computation done" flag.
    For matching the behaviour of your simulation/sensitivity example
    given, it should work. But if you were, say pipelining some
    calculation, and *waiting* for the new result before going into some
    other stage of the pipeline, it could fail. If the earlier stage
    happened to produce the same result on different inputs, your data
    might be correct, the first computation would be complete, but your
    change-detect logic wouldn't fire and your next stage would be waiting
    forever. In some designs this might be OK; in others it's not.

    The unclocked process example that detects a change is also a very
    dangerous thing; it has the potential to produce glitches and timing

    I would strongly encourage you to add a "computation done" flag to
    your complex calculation block. And it goes without saying that this
    should be a synchronous (clocked) flag, just like the output of your
    complex block ought to be :)

    Brian's advice above to "think hardware" first is right on the money;
    a "done flag" is probably the first thought of most hardware guys.

    - Kenn
    kennheinrich, Jan 4, 2008
  16. Now this is true! Either for multiple computations producing the same result,
    or the computation outputting an intermediate result. I was taking the stated
    problem as the brief, but it's certainly worth asking if it's valid.
    Not "very dangerous" if it is used as I suggested - sampled on the clock edge.
    The design tools will either guarantee it is valid then, or report a timing
    error, as long as they are used correctly. (If you lie to them about the clock
    rate, for example, all bets are off!)

    But you are of course correct that other ways of using it - especially, using it
    as a clock signal itself - have their attendant dangers.

    - Brian
    Brian Drummond, Jan 5, 2008
  17. Steven Kauffmann

    kennheinrich Guest

    You're right; I mis-read your process.

    I'm sure this is all old hat to many. But for the benefit of the OP, I
    still think you want to add a done flag to the computation unit for
    real hardware. More specifically...

    There are still more ways the comparator/not equal approach can fail
    in the general case. Consider, for example, if the complex logic unit
    outputs a large result (say a record type) and not all of the outputs
    subelements change synchronously. Maybe one of the portions of the
    result is available a clock or two before the others. Then the
    comparator may falsely detect "done" when it's not really done, just
    in the middle of a partial result. Similarly if the output has don't
    care fields in some cases: say a hypothetical controller outputs a
    record which can indicate either a "reset" command with an ignored
    address, or a "read" command from a specified address. If the address
    (which was a don't care) changed spuriously (which conceivably is
    legal when the controller is outputting a "reset") it could trigger
    downstream action.

    Again, these would all be in keeping with the simulation semantics of
    the original code, but is not in general a robust way of achieving
    system synchronization.

    And I can almost guarantee simulation/synthesis mismatch if there are
    'X's in the complex output; in simulation, an 'X' will never equal a
    '0' but in hardware your gates only know '1' and '0'. So if your sim
    initializes the calculation output to 'X', then produces a '1', your
    comparator in simulation will detect a change. But if your *hardware*
    initializes to '0' and then you calculate a '0', your comparator won't
    fire. Mismatch!


    - Kenn
    kennheinrich, Jan 5, 2008
  18. KJ also wrote something about the synthesize warnings: incomplete
    sensitivity list and combinatorial loop.
    I receive the warning about the combinatorial loop but not about about
    the incomplete sensitivity list. During the place and route process I
    receive errors that the signal result_ready is going to be trimmed. If
    I turn off the option "trim unconnected signals" the error disappears.
    But I don't know if this is a good solution to solve the problem.
    As you already mentioned, a data_valid signal is the best solution but
    not always possible. Because the code of the complex algorithm is not
    written by myself, I prefer not to edit it.
    Like some others already mentioned, a comparator is not always a good
    idea because in some cases it won't see a change. In my design such
    cases are not ok. I have to see every change, even when the result of
    the output is the same as the previous one.

    But after reading this thread, I think I have to choose between two

    1) Adding a data valid signal (best solution but also requires the
    most effort because the code is not written myself).

    2) Using a comparator and keep in mind that this solution has some

    It's clear for me and is very useful.

    Thank you all
    Steven Kauffmann, Jan 7, 2008
  19. Any signal or variable that does not
    affect an output port is ignored for synthesis.
    If the signal "result_ready" is just used for debug,
    ignore the warning.
    Otherwise, use it to drive a handshake output port.
    I would write a testbench for the "complex" entity,
    make the addition, and verify that that everything
    still works. If I decide to use existing code,
    it becomes my responsibility to maintain it.
    It might not be more effort in the end.
    That code has bitten one, and may bite again.

    -- Mike Treseler
    Mike Treseler, Jan 7, 2008
  20. Steven Kauffmann

    neeraj2608 Guest

    I was wondering how the synthesis tool considers result_ready to be
    result_ready <= not (result_ready);
    mean that result_ready is actually connected somewhere (to the input
    of the inverter, in this case)?
    neeraj2608, Jan 9, 2008
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.