• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Functional Verification
  3. System Verilog: always @( * ) is not working, but explicit...

Stats

  • Locked Locked
  • Replies 5
  • Subscribers 66
  • Views 12320
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

System Verilog: always @( * ) is not working, but explicit declaration always @( s1, s1, s3) is working

HoWei
HoWei over 2 years ago

In my code I am using the following sensitivity list declaration.

Problem: This code never enters the always @( * )  block - thus the supply check always fails (supplyOk=0):

//checking supply
`ifdef SUPPLYCHKOFF
   logic supplyOk = 1;
`else
  logic supplyOk = 0;
  always @( * ) begin
    $display("TIO MUX GATE always block was triggered");
    //range check
    if( VSS inside {[minGND : maxGND]}) supplyOk = 1;
    else supplyOk = 0;
end
`endif

BUT when the sensitivity list includes the explicit inputs, then it is working as expected and sets "supplyOk=1":

//checking supply
`ifdef SUPPLYCHKOFF
   logic supplyOk = 1;
`else
  logic supplyOk = 0;
  always @( ATB_TG_EN, ATB_TG_EN_B, VSS, TG_in ) begin
     $display("TIO MUX GATE always block was triggered");
    //range check
    if( VSS inside {[minGND : maxGND]}) supplyOk = 1;
    else supplyOk = 0;
end
`endif 

Does anyone have an explanation for this behavior ?

I am using  ICADVM20.10.310 with XCELIUM22.09.002.

This supply-check code snippet is used in many other models and working there perfectly fine. Only in this model, it does not - and I do not find the reason.

I would like to attach the complete model file, but did not find a way to do it in this forum. 

  • Cancel
  • HoWei
    HoWei over 2 years ago

    Could the problem be, that I do have multiple "always @( * )" blocks inside this module ?

    Because I do have another condition and 'ifdef condition in the functional part of the module - below is the complete module code.

    This code uses 'ifdef conditions to allow SV-RNM-bidirectional nets to be run in XCELIUM as well as in Synopsys VCS (just FYI):

    //systemVerilog HDL for "CROCODILE", "atb_tiomux_tgate" "systemVerilog"

    import CONTI_SV_PACKAGE::*;

    `ifdef XCELIUM
    import cds_rnm_pkg::*; //for Cadence tool-chain
    `elsif VCS
    import snps_msv_nettype_pkg::*;//for Synopsys tool-chain
    `endif

    `define T wreal4state //nettype to resolve net value

    module atb_tiomux_tgate ( TG_out, VSS, ATB_TG_EN, ATB_TG_EN_B, TG_in );

    inout `T TG_in;
    input logic ATB_TG_EN;
    inout `T TG_out;
    input logic ATB_TG_EN_B;
    input `T VSS;

    //checking supply
    `ifdef SUPPLYCHKOFF
    logic supplyOk = 1;
    `else
    logic supplyOk = 0;
    //always @( ATB_TG_EN, ATB_TG_EN_B, VSS, TG_in ) begin
    always @( * ) begin
    $display("TIO MUX GATE always block was triggered");
    //range check
    if( VSS inside {[minGND : maxGND]}) supplyOk = 1;
    else supplyOk = 0;
    end
    `endif

    //internal control logic
    bit control;
    assign control = ( (ATB_TG_EN && ~ATB_TG_EN_B) === 1'b1 && supplyOk==1 ) ? 1'b1 : 1'b0; //case comparison resolves to 0 if 'X or 'Z


    `ifdef XCELIUM
    //internal nets to store the external resolved value
    `T TG_in_i = `wrealZState; //this initial value is essential for proper function
    `T TG_out_i = `wrealZState;

    // bidirectional functionality
    assign TG_in = ( control==1'b1) ? TG_out_i : `wrealZState ;
    assign TG_out = ( control==1'b1) ? TG_in_i : `wrealZState ;

    //on a change, check the sense the external driver status
    always @( * ) begin
    $cged(TG_in, TG_in_i); //store outside resolved value on internal net
    $cged(TG_out, TG_out_i);
    end

    `elsif VCS
    tranif1(TG_in, TG_out, control);
    `endif


    endmodule

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • StephenH
    StephenH over 2 years ago in reply to HoWei

    Since you seem to be using SystemVerilog, please replace the always @(*) with always_comb. The semantics of the always @(*) are not well defined and can cause incompatible resutls where different vendors have implemented the feature differently due to differing interpretations of the spec. always_comb is much more precisely specified in the SV standard and should be more portable.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • HoWei
    HoWei over 2 years ago in reply to StephenH

    Thanks Stephen for this hint - I will have a look and try to understand and use this is future in system verilog.

    BUT the real issue is that I missunderstood the "always @ (*)" functionality.

    So far (in my short verilog modelling career) had the understanding that the "*" means "ALL INPUTS IN THE MODULE"  - but it acutally means "ALL INPUTS INSIDE THE ALWAYS BLOCK" - which is a completely different functionality.

    I now changed my code which will assign the "supplyOk" continously as combinatorial logic - do you see any issues with such a implementation - compared to the above approach with "always..." :

    module atb_tiomux_tgate ( TG_out, VSS, ATB_TG_EN, ATB_TG_EN_B, TG_in );

    inout `T TG_in;
    input logic ATB_TG_EN;
    inout `T TG_out;
    input logic ATB_TG_EN_B;
    input `T VSS;

    //checking supply
    `ifdef SUPPLYCHKOFF
       logic supplyOk = 1;
    `else
       logic supplyOk;
       assign supplyOk = VSS inside {[minGND : maxGND]};
    `endif

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • tpylant
    tpylant over 2 years ago in reply to HoWei

    Yes, your new understanding is correct -- the always @(*) or always_comb refers to all signals on the RHS of expressions inside the always procedural block. The big difference between @(*) and comb is that always_comb executes at time 0 regardless of the signal values whereas always@(*) waits until there is a signal change before executing for the first time.

    The code changes you made should provide the simplest solution for the functionality that you want.

    Tim

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • HoWei
    HoWei over 2 years ago in reply to tpylant

    Thanks for confirmation.

    As I try to understand the differences between "always_comb / _latch /_ff" I think the differences among those functions are only relevant when the code will be synthesized - and it will give error if it cannot be synthesized as declared by either _comb / _ff or _latch.

    In my case, I am doing AMS modelling and verification/testbenches only an do not care about synthesizability of the module.  Thus can I still use the "always  @*" function and by that avoid any error which might be caused due to non-synthesizability ?

    Or does would this cause other issues ?

    I indeed see the advantage of the initial execution of the new "always_comb/latch/ff" function.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information