The inside keyword checks whether a given value lies within a range or set of values specified using the inside phrase. It can be used inside if and other conditional statements, in addition to being used directly as a constraint.

10 min read | Intermediate Level

What You'll Learn

  • The syntax for inside, using both explicit value lists and ranges
  • How inside works identically inside conditional statements and inside constraints
  • How to invert inside to exclude a range instead of restricting to it
  • A practical memory-partitioning example using inside to keep a randomized address within a specific region

Syntax


 inside {}

// Inverted "inside"
!( inside {})

For example:


m_var inside {4, 7, 9} 	// Check if m_var is either 4, 7, or 9
m_var inside {[10:100]} 	// Check if m_var is between 10 and 100 inclusive

When Used in Conditional Statements

Here, inside is used both in a ternary operator and an if/else statement. flag is set to 1 if the randomized value of m_data lies within 4 to 9 (inclusive); otherwise it's set to 0. The if/else block uses the same check to print a matching message:


module tb;
	bit [3:0] 	m_data;
	bit 		flag;

	initial begin
		for (int i = 0; i < 10; i++) begin
			m_data = $random;

			// Used in a ternary operator
			flag = m_data inside {[4:9]} ? 1 : 0;

			// Used with "if-else" operators
			if (m_data inside {[4:9]})
				$display ("m_data=%0d INSIDE [4:9], flag=%0d", m_data, flag);
			else
				$display ("m_data=%0d outside [4:9], flag=%0d", m_data, flag);

		end
	end
endmodule

Output

Output
ncsim> run
m_data=4 INSIDE [4:9], flag=1
m_data=1 outside [4:9], flag=0
m_data=9 INSIDE [4:9], flag=1
m_data=3 outside [4:9], flag=0
m_data=13 outside [4:9], flag=0
m_data=13 outside [4:9], flag=0
m_data=5 INSIDE [4:9], flag=1
m_data=2 outside [4:9], flag=0
m_data=1 outside [4:9], flag=0
m_data=13 outside [4:9], flag=0
ncsim: *W,RNQUIE: Simulation is complete.

Every row is consistent: flag is 1 exactly when m_data falls between 4 and 9, and 0 otherwise — including the boundary values 4 and 9 themselves, both correctly counted as inside the range.

Quick Check

Q: Would m_data inside {[4:9]} be true for m_data = 9?

Show Answer

Yes. A range written as [4:9] is inclusive on both ends — 4 and 9 are both valid members of the range, not just the values strictly between them.

Used in Constraints

The inside operator is quite useful in constraints, making code shorter and more readable:


class ABC;
	rand bit [3:0] 	m_var;

	// Constrain m_var to be either 3,4,5,6 or 7
	constraint c_var { m_var inside {[3:7]}; }
endclass

module tb;
	initial begin
		ABC abc = new();
		repeat (5) begin
			abc.randomize();
			$display("abc.m_var = %0d", abc.m_var);
		end

	end
endmodule

Output

Output
ncsim> run
abc.m_var = 7
abc.m_var = 6
abc.m_var = 6
abc.m_var = 3
abc.m_var = 4
ncsim: *W,RNQUIE: Simulation is complete.

Every value of m_var falls inside the given range, [3:7].

Inverted inside

The opposite of what inside checks for can be achieved by placing ! in front of it — applicable to both constraints and conditional statements. This example is the same as the one above, except the constraint has been tweaked to reflect an inverted inside:


class ABC;
	rand bit [3:0] 	m_var;

	// Inverted inside: Constrain m_var to be outside 3 to 7
	constraint c_var { !(m_var inside {[3:7]}); }
endclass

module tb;
	initial begin
		ABC abc = new();
		repeat (5) begin
			abc.randomize();
			$display("abc.m_var = %0d", abc.m_var);
		end

	end
endmodule

Output

Output
ncsim> run
abc.m_var = 1
abc.m_var = 12
abc.m_var = 0
abc.m_var = 14
abc.m_var = 10
ncsim: *W,RNQUIE: Simulation is complete.

Every value of m_var this time falls outside the range [3:7] — exactly the opposite of the previous example, since the constraint now explicitly excludes that range instead of restricting to it.

Quick Check

Q: With this inverted constraint, could abc.m_var ever randomize to exactly 5?

Show Answer

No. 5 falls inside [3:7], and the constraint explicitly requires m_var to be outside that range — 5 is one of the values this constraint rules out entirely.

Practical Example

Say a memory is located between address 0x4000 and 0x5FFF, partitioned into two halves — one for instructions, one for data. To randomize an address that's guaranteed to fall within the data half of memory, inside is a natural fit:


class Data;
	rand bit [15:0] 	m_addr;

	constraint c_addr 	{ m_addr inside {[16'h5000:16'h5fff]}; }
endclass

module tb;
	initial begin
		Data data = new();
		repeat (5) begin
			data.randomize();
			$display ("addr = 0x%0h", data.m_addr);
		end
	end
endmodule

Output

Output
ncsim> run
addr = 0x58ef
addr = 0x563f
addr = 0x5612
addr = 0x5249
addr = 0x5cee
ncsim: *W,RNQUIE: Simulation is complete.

Every generated address falls between 0x5000 and 0x5FFF — squarely within the data region, never straying into the instruction half of memory.

Where Is This Used?

inside is the standard way to express both "must be one of these specific values" (like a small set of legal opcodes) and "must fall within this range" (like a valid address window) without writing out a long chain of || comparisons. Its inverted form is equally common for explicitly carving out reserved or illegal ranges a randomized value must never land on.

Common Beginner Mistakes

Mistake #1: Assuming a range is exclusive of its endpoints

As the first example shows, [4:9] includes both 4 and 9 themselves. Why? It's easy to assume a range excludes its boundary values by default — inside ranges are always inclusive on both ends unless the values themselves are written to exclude them.

Mistake #2: Forgetting where the ! belongs in an inverted inside

The negation wraps the entire expression: !(m_var inside {[3:7]}), not m_var !inside {[3:7]}. Why? inside itself has no built-in negated form — the ! operator negates the whole boolean result of the inside check.

Mistake #3: Confusing a value list with a range

{4, 7, 9} matches only those three exact values; {[4:9]} matches every value from 4 through 9. Why? The square brackets specifically signal a contiguous range — mixing up the two syntaxes silently changes which values are actually considered legal.

Mistake #4: Assuming inside only works inside a constraint block

As the conditional-statement example shows, inside works identically in an if, a ternary operator, or any other boolean expression — not just inside a constraint block. Why? It's a general-purpose membership operator, and constraints are simply one common place it gets used.

Practice Exercise

Challenge: Constrain an Address Outside a Reserved Region

A device has address space 0x0000 to 0xFFFF, with 0x8000–0x80FF reserved for internal use. Write a constraint on a rand bit [15:0] addr that keeps randomized addresses out of the reserved region.

Hint

Use the inverted form of inside, the same way this article's own "Inverted inside" section excludes a range rather than restricting to one.

Solution

class DeviceAddr;
  rand bit [15:0] addr;

  constraint c_addr { !(addr inside {[16'h8000:16'h80FF]}); }
endclass

This allows any address in the full 16-bit space except the reserved 0x8000–0x80FF window — the same inverted-inside pattern used earlier in this article, just applied to a realistic reserved-address scenario.

Summary

In this tutorial, you learned:

  • inside checks whether a value matches an explicit list of values or falls within an inclusive range
  • It works identically inside conditional statements (if, ternary) and inside constraint blocks
  • Wrapping the entire expression in !(...) inverts the check, excluding a range instead of restricting to it
  • A value-list ({4, 7, 9}) and a range ({[4:9]}) use similar-looking syntax but mean very different things
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5