VCS仿真中为何部分变量允许多驱动而其他变量报错?
pass_val works but rollover_n triggers a driver conflict in VCS? Great question! Let's break down why you're seeing this confusing discrepancy between pass_val and rollover_n in your Verilog code when simulating with VCS.
Core Verilog Rule to Remember
First, let's get the basics straight: logic-type variables cannot be driven by multiple independent procedural blocks (separate always blocks). Variables hold a single value at any time, so having two distinct blocks trying to set their value creates an ambiguous conflict—there's no built-in rule for which assignment takes precedence. This is exactly what the "illegal combination of procedural drivers" error is flagging.
Why pass_val didn't trigger the error (for now)
Looking at your code, the assignment to pass_val in the second always block (@(pass_val,compare,rollover_n)) is conditional: it only sets pass_val = 0 when pass_val > compare. When this condition isn't met, the block doesn't touch pass_val at all.
Some simulators like VCS might be lenient here if they can't definitively prove that both blocks will ever drive pass_val simultaneously. However, this is not valid synthesizable Verilog, and you're lucky it didn't break—you could easily hit race conditions or unexpected behavior in more complex scenarios. The always_comb block unconditionally sets pass_val every time it runs, while the second block only modifies it in one branch; the simulator might not flag this immediately, but it's a ticking time bomb.
Why rollover_n throws the error
Unlike pass_val, rollover_n has unambiguous conflicting drivers:
- In the
always_combblock: every code path assigns a value torollover_n(either1or0via theif/elsestatement—assumingseqnum_rollover_nwas a typo forrollover_n). - In the second
alwaysblock: wheneverrollover_nis high, the block sets it to0. Even if the condition isn't met, the block has the potential to driverollover_n, creating a clear conflict with thealways_combblock's continuous assignments.
VCS's compiler correctly catches this definite conflict—two separate procedural blocks both can drive rollover_n, which violates Verilog's variable driving rules.
How to fix this
You need to refactor your code so each variable is driven by only one procedural block. Here are practical approaches:
- Merge logic into a single block: Combine the bit-slicing/comparison logic and arbitration logic into one
always_combblock. This eliminates conflicting drivers entirely, as all assignments topass_valandrollover_nlive in the same block. - Restructure driver responsibilities: Instead of having the arbitration block modify
rollover_n, have it set a control signal (likeclear_rollover) that thealways_combblock uses to updaterollover_n. This keeps all assignments torollover_nwithin thealways_combblock. - Use wire-type with continuous assignment (if needed): If you must keep separate blocks, change
rollover_nto awireand use a continuous assignment with priority (e.g.,assign rollover_n = arbitration_clear ? 0 : (pass_val == 0 && |enable) ? 1 : 0;). This resolves the conflict by explicitly defining which driver takes precedence.
内容的提问来源于stack exchange,提问作者TheSprintingEngineer

