clocked process and sensitivity list

Discussion in 'VHDL' started by alb, May 3, 2013.

  1. alb

    alb Guest

    Hi everyone (geez has been a long time since my last post...),

    I'm looking at a piece of code that I would feel embarrassed to post
    here and when I synthesize it I get a warning about 'Feedback mux
    created for signal...'. Any insight on the type of warning?

    I am also puzzled about the style used in the code which goes along
    these lines:

    process (clr, rst, foo, bar, foobar)
    if rst = '1' then
    -- a bunch of assignments
    elsif foo = '1' then
    -- another bunch of assignments
    elsif bar = '1' then
    -- another bloody bunch of assignments
    elsif (bar = '0') and (foo = '1') and (foobar = '1') then
    -- another insane bunch of assignments

    elsif rising_edge(clk) then
    case mysterious_signal is
    when '1' =>
    foobar <= '0';
    mysterious_signal <= '0';
    -- gibberish

    when '0' =>
    -- some more gibberish
    end case;
    end if;
    end process; -- thanks GOD!!!

    Except for the readability issues, there's something deeper I'd like to
    understand; when there's an asynchronous set and reset I would
    definitely need to have both signals in the sensitivity list otherwise
    the pre-synthesis simulation would never trigger the process
    assignments. But why synthesis does not need them?

    Moreover the 'foobar' signal in the above snippet is truly not needed in
    the sensitivity list since an event should be scheduled for it to change
    at next delta cycle. Am I wrong?

    There's a possibility that my questions are badly formulated!! But I'm
    trying to figure out what the heck stroke the designer's mind when he
    wrote this...

    alb, May 3, 2013
    1. Advertisements

  2. [..]

    First I assume the clr in sensitivity list should be clk.
    In fact the designer wrote a bunch of logic in the asynchronous
    (re)set path of the FF. I see no wrong on a formal point(depending on
    conntent of the "bunch of assignments" there could still be trouble),
    but I guess that usual synthesis tools accept only

    if resetcondition = true then
    elsif rising_edge(Clk) then
    end if

    Depending on content of the commented lines, you could have logic that
    is hard to implement in a technology that contains no FF with both set
    and reset. This would lead to creation of latch with a lot surrounding
    stuff to emulate FF with async set and reset. The warning is for me
    first hint that some latch or even worse is instantiated. I think you
    need to analyse for all signals in (re)set whats happing.
    A good example of what is sometimes desired on first glance, but not
    synthesiseable by any tool:

    if reset = '1' than
    FF <= Inputsignal;
    elsif ....

    best regards

    Thomas Stanka, May 3, 2013
    1. Advertisements

  3. alb

    Andy Guest

    First things first. A "feedback mux generated" message almost always indicates an issue with asynchronous resets.

    In your code, if any of those reset conditions trigger, the elsif rising_edge(clk) section does not execute (nor do the other reset sections execute).Therefore the synthesis tool has to add a feedback mux for those registersnot reset by all reset conditions. The feedback mux is controlled by the reset conditions (oops, they're asynchronous!) so that the register does notupdate on rising clock edges while any of the reset conditions is true.

    If you really want to have non-reset and reset registers in the same process, then you should use an "if rising_edge(clk)" section first, with a matching end if, and then a separate if statement (NOT elsif!) afterwards for EACH reset input condition.

    Note that using multiple, partial asynchronous resets can cause strange problems, if circuitry that is not reset is using outputs from other asynchronously reset circuitry, since those outputs can be reset at any time relative to the clock. For this reason, asynchronous resets should generally only be used for general initialization, and not for functional logic purposes. Consider other ways to accomplish what the multiple asynchronous resets aretrying to do.

    As for the sensitivity list issues, generating an event is not the same as triggering a process. A process has to be sensitive to the signal in order for an event on that signal to cause the process to re-execute.

    Synthesis tools started out ignoring sensitivity lists, and have continued to do so to this day, much to my chagrin. At least they warn you when they find a sensitivity list problem that would cause a mismatch between the code's simulated behavior and that of the resulting hardware.

    Andy, May 3, 2013
  4. Hi alb!

    foobar is needed in the sensitivity list: it is a Flipflop written in
    the rising_edge(clk) part and furthermore it is used as async. reset/set
    for the "another insane bunch of assignments"-branch.

    Therefore it may be that foobar is a signal, that triggers it's own
    reset. But I guess the designer of this code was aware of this and did
    pay attention to it.

    But let's come back to the "feedback mux"-problem: foobar is used as
    input for the reset/set conditions. Therefore if the "another insane
    bunch of assignments"-branch gets active, then the
    "rising_edge(clk)"-part should not be reached. For this purpose
    synthesis tools may infer a data multiplexer. Let's have a look at some
    synthesizable code:

    if (reset_n='0') then
    dout(1) <= '0';
    dout(0) <= '0';
    elsif (set_n='0') then
    dout(1) <= '1';
    --dout(0) <= '1';
    elsif rising_edge(clk) then
    dout(1) <= din(1);
    dout(0) <= din(0);
    end if;
    end process;

    As can be seen, dout(0) does not have a set-Input, but if set_n gets
    active, then dout(0) must not change. Therefore synthesis builds the
    following logic for the "rising_edge(clk)"-part :
    "if set_n='0' then dout(0)<=dout(0); else dout(0)<=din(0);"

    Please note that all this depends on your synthesis tool and the target

    Ralf Hildebrandt, May 6, 2013
  5. Hi Thomas!

    This synthesizes "well" to a Flipflop with reset and set input and some
    logic in front of that.

    set_input gets active, if reset='1' and Inputsignal='1'
    reset_input gets active, if reset='1' and Inputsignal='0'

    This works fine as long as Inputsignal does not change around the time
    when reset gets inactive.

    This is not code that is accepted as good code, may cause trouble with
    synthesis and ATPG tools and so on, but it is synthesizable and works.

    Ralf Hildebrandt, May 6, 2013
  6. alb

    alb Guest

    Hi Andy,

    I believe that 'almost' in your statement is referred to the variability
    of the various synthesis tools' implementation.
    meaning that if a signal is not set for *all* sets and resets, the
    synthesis needs to 'remember' the state of the not-assigned signal to
    maintain its state. Sorry if I needed to reformulate it, but I guess is
    part of my 'learning process'!
    got your point.
    This is the direction towards which I'm willing to go. The code (as I
    sarcastically described) has been put together with patches after
    patches up to a point where 'it works', but I've been asked to review
    the code and pin point any suspicious part which might cause problems.

    The fun part of it is the total absence of specs and a very primitive
    verification plan in place... but that's another issue.
    Meaning that every signal the process depends on (i.e. resets/sets and
    clock) should be in the sensitivity list. Correct?
    That is unfortunate and allows proliferating bad habits as well. I often
    see designers rushing to the synthesis phase (or even the FPGA
    programming) without paying too much of attention to pre-synth simulations.
    alb, May 7, 2013
  7. alb

    alb Guest

    Hi Ralf,

    Uhm, I guess you are right. Indeed I guess I was also right that
    'foobar' is scheduled for a change in the next delta cycle, but if the
    process is not sensitive to it (with the sensitivity list) than it will
    not trigger. Is this a correct statement?
    Well, I've raised this question also. Indeed I did not even receive a
    strong opinion on why the resets/sets should really be asynchronous...
    that is crystal clear. In the even of a reset_n/set_n and clk happening
    at the same time both will have an event schedule for the same
    delta-cycle and to prevent the clk branch to trigger there should be
    some logic 'around' it, hence the feedback mux.
    [OT] This is indeed very unfortunate. When we will have a common
    agreement by synthesis tool vendors on 'how a synthesis tool should
    behave'. Is there any standard they need to obey? I apologize but I got
    a bit 'infected' by the *nix world where platforms aim to comply to
    POSIX standards and code can be - to a large extent - portable.
    alb, May 7, 2013
  8. alb

    Andy Guest


    My use of "almost always" instead of "always" is just being cautious. I have never had a case where it was not caused by a missing assignment in a process with a preceding asynchronous reset clause. But I have not written every possible combination of code yet, nor have I used every synthesis tool.

    Anytime a description has to remember a previously (in simulation time) stored value, there is some type of storage or storage modification involved in the implementation. This fundamental behavioral aspect of synthesis is atthe root of how/why latches, registers and clock enables are inferred, andholds true whether you use signals or variables for your data. But that's another subject...

    I feel your pain. The absence of specifications for what the code is actually required to do (NOT how it has to or does do it) creates problems whenever the code must be changed. An effective testbench is not possible withouta good specification. Otherwise, the testbench can only test what you think the code is supposed to do, which must be extracted from what the code actually does.

    All causal signals must be in the sensitivity list. Non-causal signals should not be in the sensitivity list. In a combinatorial process, every signalread is causal. In a clocked process, only the clock and if present, asynchronous reset(s) are causal.

    Andy, May 7, 2013
  9. alb

    rickman Guest

    I'm not following the issue here. I can't see why any extra logic would
    need to be asserted. The clocked process infers a register for each bit
    assigned in the edge triggered section. Are the async assigned bits
    *not* assigned in the edge triggered section?

    What am I missing?
    rickman, May 7, 2013
  10. Hi alb!

    This is correct for simulation. Most synthesis tools don't care for the
    sensitivity list and "generate their depending on the code".

    It depends on the target library, because it has to include flipflops
    with async. set and reset. An for these flipflops in the synthesis model
    there must be a specification what to do is set and reset are activated
    together. (This will in most cases not happen, but the synthesis tool
    has to be aware of it.)

    And then it depends on the synthesis tool, how it solves the given
    problem. It is not some kind of "incompatibility" but more a problem of
    choosing one solution.

    Ralf Hildebrandt, May 8, 2013
  11. alb

    Andy Guest


    In the typical pattern for clocked logic with asynchronous reset:

    if reset then
    -- asynchronous reset/preset assignments to registers
    eslif rising_edge(clk) then
    -- synchronous assignments to registers
    end if;

    The elsif keeps the synchronous section from executing while reset is active.

    Thus, even if a register is not reset, the register does not keep updating on clock edges while reset is active. In order to correctly implement that behavior in the circuit, a feedback mux (clock enable) is used to retain the previously stored value in the register on every clock edge while reset is active. That feedback mux is extra logic, whether it is in the form of a built-in clock enable or not.

    Andy, May 9, 2013
  12. alb

    rickman Guest

    That's what I'm not clear on. I don't see why *anything* is needed to
    keep the register in reset as long as the reset is asserted. That's
    what the reset does, it holds the FF in reset. I've never seen a
    feedback mux added to a FF to implement a reset. Or are you referring
    to the internal logic of the FF?

    I looked and I couldn't find a transistor based model of a D FF with set
    and reset inputs.
    rickman, May 10, 2013
  13. alb

    Jan Decaluwe Guest

    The feedback mux is needed if you *forget* to reset the register
    in the 'if reset' clause. In that case, HDL semantics dictate
    that the register should keep its previous value during reset,
    hence the feedback mux.

    Jan Decaluwe, May 10, 2013
  14. alb

    GaborSzakacs Guest

    I've found that Symplify is very good at warning you about
    forgetting the reset terms in this case. You get a warning
    about feedback mux, followed by "Did you forget..."

    I wish XST did that instead of all the useless warnings it
    GaborSzakacs, May 10, 2013
  15. alb

    rickman Guest

    I'm not sure that is really needed. If the reset clause is missing an
    assignment doesn't it become a clock enable? When the reset is asserted
    the clock does not work and the output is held. Still no need for a
    feedback mux...
    rickman, May 10, 2013
  16. alb

    Andy Guest


    We are in complete agreement, but saying the same thing in different ways.

    The feedback mux IS A CLOCK ENABLE. If the target architecture supports built-in clock enables on registers, then one will be used to implement the feedback mux.

    It may be that at the time during processing when the need for a feedback mux is determined, it may not be known whether the target architecture supports built-in clock enables, thus the message indicates a feedback mux.

    Andy, May 13, 2013
  17. alb

    celine Guest

    Le vendredi 10 mai 2013 11:45:56 UTC+2, Jan Decaluwe a écrit :
    Hi all,
    Your discussion rises a lot of questions in my head on whether I usually doright or not.
    For simple FSMs I usually use a one process description, and when I have some signals that I am sure that are assigned in a state before use I don't reset them. I do this because I work with Xilinx technology and I understoodthat not resetting these signals gives more freedom to the tool:
    from Spartan 6 CLB User Guide : "To maximize design flexibility and utilization, use the GSR and avoid local initialization signals."

    For instance it gives this kind of process:
    --! @brief Receiver Finite State Machine
    --! @Details The module detects the frame header according to the frame forming protocol, receives the data and check the CRC
    p_rx_fsm : process (clk, rst)
    constant DFL_NULL : unsigned(rx_ctr_dfl'length-1 downto 0) := (others=> '0');
    variable frx_sr : std_logic_vector((maximum(maximum(ADR_L, CRC_L), maximum(CMD_L, DFL_L))*FW_L)-1 downto 0); --!
    if (rst = RST_ALVL) then
    frx_fsm <= FRX_IDLE;
    -- no reset required for frx_dat_cnt
    elsif (rising_edge(clk)) then
    case frx_fsm is
    when FRX_IDLE =>
    if (f_rx_wr = '1' and f_rx_d = rx_ctr_sof) then
    frx_fsm <= FRX_DFL;
    end if;
    when FRX_DFL =>
    if (f_rx_wr = '1') then
    frx_fsm <= FRX_DAT;
    frx_dat_cnt <= unsigned(frx_sr(DFL_L*FW_L-1 downto 0))-1;
    end if;
    when FRX_DAT =>
    if (f_rx_wr = '1') then
    if (frx_dat_cnt = DFL_NULL) then
    frx_fsm <= FRX_EOF;
    frx_fsm <= FRX_DAT;
    frx_dat_cnt <= frx_dat_cnt - 1;
    end if;
    end if;
    when FRX_EOF =>
    if (f_rx_wr = '1') then
    frx_fsm <= FRX_IDLE;
    end if;
    when others =>
    frx_fsm <= FRX_IDLE;
    end case;
    end if;
    end process p_rx_fsm;

    I synthesized it on a Spartan 6 and looked in FPGA Editor what the frx_dat_cnt FF looked like and I saw that no SR pin was used.
    I then wrote the above process in two different processes, one for the FSM state in a (clk, rst) process and another for the frx_dat_cnt signal with clk only process.
    Both methods gave me exactly the same diagram in FPGA Editor.

    So here is my question: is it just an XST interpretation of the VHDL or is it valid in all cases ?
    In other words can the code above lead to the same "feedback mux" warning in another synthesizer ?
    celine, May 22, 2013
  18. alb

    Andy Guest

    OK, you implied that both code versions generated the same circuit with respect to set/reset, but you did not say whether they had exactly the same clock enable (feedback mux) logic for the counter. Did they?

    The reason I ask is that many years ago, Synopsys FPGA Compiler II (may it rest in peace) did not give warnings about feedback muxes, because it did not insert them!

    Synplify, as far as I know (I've been using it for at least 15 years) has always implemented the feedback mux (and issued warnings) in order to createhardware that behaved like the RTL, even while reset was asserted and the clock was still running.

    I have no idea whether XST inserts feedback muxes or not, or if it does, whether it issues warnings for them. Any tool that does not insert feedback muxes (usually implemented using the clock enable input on the flip-flop) inthis situation is broken.

    As to whether all registers should be reset, there are many design techniques that will work. There are fewer of them that are easily verifiable and are not mistake-prone.

    If you reset all registers, it is fairly easy to find out if you missed one(look for register primitives that do not have reset inputs). Verifying that all non-reset registers are initialized otherwise is more difficult to verify, and more prone to mistakes.

    When I worked with PALs, we designed state machines that handled asynchronous inputs without separately synchronizing them by controlling the state mapping and ensuring that only one register bit changed in response to that asynchronous input. It worked really well, and saved registers in PALs with very few registers available. I would not recommend using the same technique in FPGAs because it is much harder to verify, much more mistake-prone, and using an extra register or two to explicily synchronize an input before the state machine reads it is no big deal in an FPGA, they have lots of registers.

    Also, IIRC, Xilinx FPGAs cannot merge multiple registers into the same CLB (or slice?) that have different reset or clock signals. This means that youare better off resetting all registers to allow maximum freedom in mappingthem to CLBs and slices during P&R.

    Andy, May 22, 2013
  19. alb

    celine Guest

    Le mercredi 22 mai 2013 20:53:25 UTC+2, Andy a écrit :
    In the case of only one process, the CE pin is directly driven by f_rx_wr alone, but in the equation of the D pin I see my asynchronous reset.
    In the case of two separated processes, one with clk an rst, the other withclk only, the D pin has a complicated equation where I don't see my asynchronous reset, and the CE pin has also a complicated equation where the asynchronous reset doesn't appear.

    And if I add the initialization on reset of frx_dat_cnt in the one process above, the SR pin is now driven by my asynchronous reset, the CE pin simplyby f_rx_wr, and the D pin has an equation not so much complicated.
    I'll go with this one.

    In fact I used to systematically initialize all my registers on an externalreset for ten years until I had to design an FPGA with multiple digital filters in a virtex 6 at a quite high speed (240MHz) and I found that the reset line exploded the timing constraints.
    So I changed my reset strategy to initialize only the signals that needed it.
    Seems that I have gone a little too far this way...

    You're right about the fact that Xilinx FPGAs cannot merge multiple registers into the same CLB if they have different control signals (clock, reset but I think also clock enable), but I can not find what is the best for the placer:
    avoiding local initialization or having all signals with the same controls.
    I understood that the need to avoid local initialization was statistical: if you have a big design the Xilinx placer will fit it more easily if a goodpart of your registers are not initialized because some of the FF resources don't have SR pin at all. I hope I'm not mistaken.
    In the case of my little FSM though I think I should initialize all the registers in my process.
    celine, May 23, 2013
  20. alb

    Andy Guest

    It sounds like you are seeing the logic of the feedback mux in the single process version where you don't reset all registers.

    There is an easy way to infer different registers with different types of reset (or no reset) from a single process, without feedback muxes.

    The key is to code it such that the reset (whatever kind) has priority overclocked logic, but is not exlusive of the clocked logic. Here is an example pattern for defining registers with asynchronous, synchronous, or no reset, all in one process, with no feedback muxes"

    process (arst, clk) is
    if rising_edge(clk) then
    -- synchronous assignments and control statements here
    if srst = '1' then
    -- synchronous reset assignments here
    end if; -- srst
    end if; -- clk
    if arst = '1' then
    -- asynchronous reset assignments here
    end if; -- arst
    -- don't assign non-reset registers in either reset region
    end process;

    The reset assignments override the effects of the synchronous asssignments,but they do not keep the latter from executing. Thus registers that are not reset are not overridden by reset either, and behave as if there were no reset at all (and therefore need no feedback mux).

    I should note that having asynchronously reset registers feeding other registers that are not held in reset can cause problems with unsynchronized inputs to the non-reset registers. This can be very hard to detect and diagnose without gate level simulation and lots of variation in the onset of the asynchronous reset relative to the clock.

    All asynchronous reset control signals should be synchronized to each clockdomain for their deasserting edge only. This makes sure that all asynchronously reset registers come out of reset on the same clock edge. You also need to ensure that the STA tool is checking timing on that path.

    Finally, WRT timing on a heavily used asynchronous (or synchronous) reset signal, you can pipeline the reset (you are synchronizing the deasserting edge aren't you?!), and P&R on some tools can replicate the last pipeline stage(s), creating a "reset tree" to ease timing. If the replication is performed in synthesis, I don't know whether the P&R tool will be able to swap loads between the replicated registers to match a given placement, and you cartainly don't want the synthesis register allocations to drive placement. Of course, physical synthesis tools will handle this latter issue automatically.

    Andy, May 23, 2013
    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.