In complex testbenches, some variable declarations end up with a long data-type specification, or need to be used in multiple places throughout the code. A typedef gives a user-defined name to an existing data type, so that name can be reused everywhere afterward — avoiding the need to edit multiple places if the underlying type ever needs to change.

10 min read | Intermediate Level

What You'll Learn

  • How typedef creates a reusable name for a data type, useful for long or repeated type specifications
  • Why assigning a value wider than a typedef'd type still truncates, exactly as it would for any variable of that width
  • The difference between typedef (a new name for a type) and alias (multiple names for the same physical net)
  • Why alias only works on nets, never on variables

Typedef


// Normal declaration may turn out to be quite long
shortint unsigned  			my_data;
enum {RED, YELLOW, GREEN} 	e_light;
bit [7:0]  					my_byte;

// Declare an alias for this long definition
typedef shortint unsigned 			u_shorti;
typedef enum {RED, YELLOW, GREEN} 	e_light;
typedef bit [7:0]  					ubyte;

// Use these new data-types to create variables
u_shorti    my_data;
e_light     light1;
ubyte       my_byte;

Syntax


typedef data_type type_name [range];

Example


module tb;
  typedef shortint unsigned u_shorti;
  typedef enum {RED, YELLOW, GREEN} e_light;
  typedef bit [7:0] ubyte;

  initial begin
    u_shorti 	data = 32'hface_cafe;
    e_light 	light = GREEN;
    ubyte 		cnt = 8'hFF;
  
    $display ("light=%s data=0x%0h cnt=%0d", light.name(), data, cnt);
  end
endmodule

Output

Output
ncsim> run
light=GREEN data=0xcafe cnt=255
ncsim: *W,RNQUIE: Simulation is complete.

data shows 0xcafe, not the full 0xface_cafe that was assigned. u_shorti is typedef'd from shortint unsigned, which is only 16 bits wide — assigning a 32-bit literal to it truncates down to the lower 16 bits, exactly as it would for any ordinary 16-bit variable. A typedef only renames an existing type; it doesn't change any of that type's own behavior, including its width.

Quick Check

Q: Why does data end up as 0xcafe specifically, rather than being truncated to some other value?

Show Answer

Because truncation to a narrower width keeps the lower bits and discards the upper ones. 32'hface_cafe's lower 16 bits are cafe — that's exactly what survives once the value is forced into a 16-bit u_shorti.

Alias

An alias statement declares multiple names for the same physical net — it does not work on variables. Per IEEE 1800 §10.11 ("Net aliasing"): "Variables and hierarchical references cannot be used in alias statements." It's mainly used to model a bi-directional short-circuit connection, and can appear inside modules, interfaces, and generate blocks.


wire [7:0] data;
wire [7:0] mydata;
alias mydata = data; // "mydata" and "data" now name the same physical net

assign data = 8'hFF; // drives the shared net -- mydata reads back 8'hFF too

data and mydata are two names for the exact same physical net, so driving data is indistinguishable from driving mydata — unlike a variable, a wire is driven with a continuous assign (or force), not a plain procedural =.

Quick Check

Q: Could alias be used to give a second name to a logic variable driven procedurally inside an always block?

Show Answer

No. alias only works on nets — variables and hierarchical references are explicitly disallowed, per the IEEE 1800 citation above. A logic variable driven procedurally isn't a valid target for alias at all.

Where Is This Used?

typedef is commonly used in testbenches to give a project's own custom bit-widths — like a 21-bit address or a 4-bit opcode — a meaningful, consistent name used everywhere, so a later width change only requires editing one typedef line rather than hunting down every individual declaration. alias is far more specialized, mostly seen in low-level net modeling, such as bidirectional pad or pin connections, rather than everyday testbench code.

Common Beginner Mistakes

Mistake #1: Forgetting a typedef'd type can still be narrower than expected

As the u_shorti example shows, a typedef doesn't change the underlying type's width or behavior — only its name. Why? Assigning a wider value than the typedef'd type can hold still truncates silently, exactly as it would without the typedef at all.

Mistake #2: Trying to use alias on a variable instead of a net

As the second Quick Check shows, this is explicitly disallowed by the LRM. Why? alias exists specifically to name a physical net, not to create a second reference to a variable's storage — that's a different problem entirely, and not one alias solves.

Mistake #3: Assuming typedef and alias solve the same problem

They don't — typedef names a type, used to declare new variables; alias names an existing net, creating no new storage at all. Why? Confusing the two means reaching for the wrong construct: typedef can't connect two existing signals together, and alias can't be used to declare a new variable.

Mistake #4: Redeclaring the same typedef separately in every file that needs it

If the same custom type needs to be used across multiple files, repeating its typedef in each one risks the definitions silently drifting out of sync. Why? Declaring it once inside a shared package and importing it everywhere keeps every file working from the exact same definition.

Practice Exercise

Challenge: Predict a Truncation

Given typedef bit [11:0] u_addr; (a 12-bit type), what value would a variable of type u_addr hold if assigned 16'hABCD?

Hint

Truncation to a narrower width keeps the lower bits and discards the upper ones — the same pattern demonstrated in this article's own u_shorti example.

Solution

12'hBCD. 16'hABCD's lower 12 bits are BCD — the upper nibble (A) is discarded, since u_addr is only 12 bits wide, exactly the same truncation behavior shown for u_shorti in this article.

Summary

In this tutorial, you learned:

  • typedef gives a reusable name to an existing data type, useful for long specifications or types used repeatedly throughout a testbench
  • A typedef'd type keeps every behavior of its underlying type, including its width — assigning a wider value than it can hold still truncates silently
  • alias declares multiple names for the same physical net, and works only on nets — never on variables or hierarchical references
  • typedef and alias solve different problems: one names a type for declaring new variables, the other names an existing net with no new storage created
Did you find what you were looking for?

Quiz

Test Your Knowledge

1 of 5 Score: 0 / 5