Blog

Thoughts on IC development, EDA, and hardware design languages.

EDA Tool Developer Series: Always blocks don’t have sensitivity lists!

Posted by: Brad Quinton | Posted on: December 16th, 2014 | 11 Comments

Share on LinkedIn24Share on Facebook0Tweet about this on Twitter0Share on Google+0Email this to someone

Everyone knows how a SystemVerilog always block works, right? Always blocks contain sensitivity lists that describe when they should be executed. We all write our RTL that way. Common sense, right? Actually, it’s not true. In fact, always blocks, and the other SystemVerilog processes (initial, always, always_comb, always_latch, and always_ff) are not, in fact, connected to the sensitivity list. The sensitivity list is actually connected to a sequential statement or a compound sequential statement that follows. A bit surprising. Let’s take a look…

Consider the classic flip-flop:

always @(posedge clk)
begin
q <= d;
end

Written like this, it really feels like that sensitivity list is a part of the always. And if you have ever tried to write your own Verilog or SystemVerilog parser, you have likely tried to key off or the “always @(” to orient yourself. But, a careful read of the SystemVeriog language reference manual (LRM) tells us otherwise. @ is actually an event control operator. And the event control operator defines the behavior of a sequential statement. So, actually this flip-flop would be more accurately written as follows:

always
@(posedge clk) begin
q <= d;
end

And in fact could also be written as follows:

always
begin
@(posedge clk) q <= d;
end

In the example above, the event control operator is acting on the statement d <= q. Of course, I would not recommend you write your Verilog or SystemVerilog this way! Not only would it be easy to add another statement and break the design, but you would have to be sure that all the EDA tools in your flow have been carefully written with this subtlety in mind!

In fact, because this assumption is so common, even in our Invio platform, we have an attribute named sensitivity_list on our process objects (which actually references the sensitivity list on the statement that follows). So when you want to print the sensitivity lists of all processes in your design you can simply do the following:

for p in get_processes(flags=HIER):
for expr in p.sensitivity_list:
print expr.orig_text

But, for completeness (and correctness!) we also provide a sensitivity_list attribute for all statements (with begin/end blocks just being a special case of a statement), so the following will also give you the information you need from your Verilog or SystemVerilog design:

for p in get_processes(flags=HIER):
for stmt in get_statements(p):
for expr in stmt.sensitivity_list:
print expr.orig_text

I have to admit, even though I have been building EDA tools and designing with Verilog and SystemVerilog for over 15 years, I had never really understood this until we were defining our Invio API…

So the question is: Have you ever run into this problem when you are writing your own internal EDA tools? Or, run into this with an EDA Vendor tool? Let us know. And, also, feel free to request things you might like to see in future posts for our reoccurring EDA Tool Developer Series. We love to hear about all the cool scripts and tools that people have built or, even better, are trying to build.

4-Ways-to-Build-Best-in-Class

Share on LinkedIn24Share on Facebook0Tweet about this on Twitter0Share on Google+0Email this to someone

Comments (11)


  1. Carl DeSalvo - Reply
    December 17, 2014

    Brad,

    I loved your positioning statement at the end of this posting. Basically you don’t know what you don’t know so you should use Invio to help you build your EDA tools correctly – the first time.

    I don’t understand the nuances in the subtleties of your examples above. Maybe we can go through it together when you have the time.

    Thanks, Carl

    • Brad Quinton - Reply
      December 18, 2014

      Thanks Carl. This is a bit of a subtle point, but I think your take away is just right: let you Platform, in this case Invio, take care of the details so you can focus on the value-add.

  2. Naveen Kumar - Reply
    December 18, 2014

    Brad, Section 4.3 in SV 1800-2012 LRM says that even procedural assignment is a process. How does tool identify this from always,initial… processes?

    • Brad Quinton - Reply
      December 18, 2014

      Wow. Thanks for the detailed question @Naveen. You are correct. A procedural assignment is identified as a process in the SystemVerilog language reference manual (LRM), and Invio does indeed identify procedural assignments (as an InvioObject statement type) and we allow you to access the sensitivity_list attribute for them.

      Of course, the complexity of procedural assignments is in the dynamic execution. I can see that there are potentially a few good uses of procedural assignments, but a lot of potential of confusion as well! But, that’s probably a topic for another blog post…

  3. Vincent Wang - Reply
    December 22, 2014

    Thanks for the information. Very interesting, I’ve never noted about this. However, sometime we need to balance efficient and readability. We also need to watch the compatibility. Therefor, we usually keep conservative from unusual coding style.

  4. Roberto - Reply
    December 23, 2014

    About 20 Y ago i wrote a raw translator from Verilog to C api calling a board simulator device.
    Now that work is somewere inside /dev/null….

    However I remember that at that time I sorted out a solution:
    Because my goal was a model for an event driven simulator, all I needed was to focus on the @ and # as “entry point” or “re-entry” point for the simulator C-translated model.

    Back to the allways block:
    If you think about Simulation (also behavioural simulation) you should just focus on “wait event” statements (@ and #).

    If you focus on Synthesizable construct you can “require” a more stringent usage of always blocks and think as “always block with sensitivity list”

    Using @(….) inside an always block is not a good
    pracrice, and shoud be used only for
    non synthesizable blocks (e.g. behavioural simulation).

    Because of this “policy” is better to change


    always
    begin
    ...
    @(...)
    ...
    end

    To an equivalent “initial .. forever” block:


    initial
    begin
    ...
    forever
    begin
    ...
    @(...)
    ...
    end
    end

    Using this distinction helps also on understanding what already written here by other contributors, e.g. that the @ (and #) are referred to the next statement that can also be a null one (the semicolon!)

    • Brad Quinton - Reply
      December 23, 2014

      That is a good suggestion. It definitely reads cleaner with the “initial .. forever” style for behavioral code.

      Your point about the null statement being a valid statement is also a great point (and maybe a blog post in itself), I sure that many people don’t realize that when they write:


      @(posedge clk);

      That they are really conditioning at the null statement!

  5. Shalom Bresticker - Reply
    January 7, 2015

    always_comb and always_latch may not have sensitivity lists because they are not allowed to have event controls.

    • Brad Quinton - Reply
      January 7, 2015

      This is an excellent point — always_comb (and always_latch) were added to SystemVerilog to more accurately reflect the designers intent when writing sequential procedures. The LRM has an extensive list documenting what elements in these procedures contribute to the implicit sensitivity list that controls the procedure timing. This list includes the idea of traversing functions that are called by the sequential procedure to determine what the function output depends. And, as you say, a corollary of this is that the always_comb forbids any statements that can block or that have event controls. Interestingly, SystemVerilog has some dark corners. For instance, it is actually possible to subvert this intent in an always_comb block by using a task call that does block (or consumes time in some other way).

  6. Pingback: Do always_latch and always_ff bring any real value? - Invionics

  7. Pingback: EDA Tool Developers Series: What The Flop? ... Part 2 - Invionics

Leave a Comment