Syntax Errors
Helping you ‘register’ the same errors as the synthesiser. Haha.
Table of Contents
- Introduction
- Expecting a character or word
- Missing module name in instantiation
- Mismatched port width
- Connecting ports by name and order
- Object on the left hand side must be a variable type
- Cannot resolve multiple constant drivers
- Illegal assignment
- Top level not found
Introduction
Verilog syntax errors may seem cryptic, so it is important to understand what the compiler/synthesizer is trying to indicate. A syntax error thrown by Quartus Prime typically has the following format:
<file_name>.v(<line_number>) near text: “<random_word>”... Check for and fix any syntax errors that appear immediately before or at the specified keyword. Verilog HDL syntax error at
In your specific error, <file_name>
would be the name of the file wherein the error occurred, <line_number>
would indicate the line number of the error in <file_name>
, and <random_word>
would point out the specific location of the error within line <line_number>
.
Here are some typical errors you may encounter, along with fixes for the same. This is not a comprehensive list, but covers most common cases.
(Note that fixing one error may cause many more to appear—the compiler parses the file line by line so that is expected behavior.)
Expecting a character or word
One of the most common types of syntax errors is a missing character or word. For example, a missing semi colon would result in a error of the following form:
<file_name>.v(<line_number>) near text: “<random_word>”: expecting “;”. Verilog HDL syntax error at
Adding a ‘;
’ in <random_line> of <file_name> should fix the above error.
Similar errors can occur for missing closing brackets, endmodules etc. To fix such errors, identify where the missing character or word needs to be added.
Missing module name in instantiation
Verilog modules describe pieces of hardware. Hence, whenever instantiating a module (analogous to instantiating a software class in many ways), we need to specify an instance name.
For example, let’s review the code for a majority module MAJ with 3 inputs and 1 output.
module MAJ(a, b, c, m);
input a, b, c;
output m;
and a1(ab, a, b);
and a2(ac, a, c);
and a3(bc, b, c);
or o(m, ab, ac, bc);
endmodule
Each of the and
gates is a module, which has to be given a unique name so that the compiler knows how to distinguish them. When only 1 instance of a module is called in a program, some compilers do not throw an error. However, it is good practice to name every module instantiation regardless.
Name the module instance specified by the error message to resolve the error.
Mismatched Port Width
(10170): Verilog HDL syntax error at [file_name.v] line [line_number] near text: "[port_name]"; expecting "[expected_type]". Check that the port widths match between the module definition and the instantiation. Error
Whenever a module is declared, the widths of its ports are also described. For example, below is the description of the ports of a 4-bit carry-lookahead adder.
module CLA(
input [3:0] a, // 4-bit input a
input [3:0] b, // 4-bit input b
input cin, // Carry input
output [3:0] sum, // 4-bit sum output
output cout // Carry output
);
Ports a,
b
and sum
are each 4 bits wide , while cin
and cout
are each 1 bit wide. Hence, when CLA
is instantiated, the wires
reg [1:0] a;
reg [3:0] b;
reg cin;
wire [3:0] sum;
wire cout;
(.a(a),
CLA dut(b),
.b(cin),
.cin(sum),
.sum(cout)); .cout
The above instantiation would likely throw an error because a 2 bit register a
has been connected to a 4 bit wide port. Editing the code to reg [1:0] a;
should fix the error.
Sometimes, mismatched port widths only trigger warnings (typically if the connected element is larger than the port width, in which case the MSB of the element is usually taken). These can result in undesired behaviour and should be avoided as well.
Ensure declared port widths of modules match widths of connected nets.
Connecting Ports by Name and Order
Error: [file_name.v]: Line [line_number]: Cannot connect ports by both name and order in instantiation of '[module_name]'
Now, there are two broad ways of connecting ports when instantiating modules: by name, and by order. Consider the CLA module declared above. Here’s how one could instantiate it:
// By Name
(.b(y),
CLA dut1(x),
.a(bin),
.cin(bum),
.sum(dout));
.cout
// By Order
(x,
CLA dut2,
y,
bin,
bum); dout
When instantiating a module by name, we explicitly state which port each element is connected to. For example, in dut1
, x
and y
are explicitly connected to ports a
and b
respectively.
Whereas in dut2
, the connection is implicit—because ports a
, b
, cin
, sum
, and cout
were declared in that specific order, they are connected to x
, y
, bin
, bum
, and dout
, respectively.
Instantiating ports by name is better practice due to improved readability and less chance of making an error. Nevertheless, both are valid.
The issue arises when an instantiation uses both methods of connecting ports.
(x,
CLA dut1(y),
.b,
bin(bum),
.sum(dout)); .cout
This isn’t allowed because it creates a lot of ambiguity. Hence, the above error is thrown. Fixing the instantiation to connect ports by either name or order should resolve it.
Connect ports by either name or order—not both!
Object on the left hand side must be a variable type
(10028): [file_name.v](line_number): Object "[object_name]" on the left-hand side of assignment must be a variable type (reg, integer, time, real, etc.) Error
The object types we deal with in EECS 270 are reg
and wire
. A reg
is an object that can store its value across multiple ‘time steps’. It is not equivalent to a hardware register, but can be understood to have ‘memory’ of some form. A wire
, on the other hand, has no memory, and is constantly assigned a value. It gets this value by either being an output of a module, or on the LHS of an assign
statement.
This means a reg
can be assigned a value inside an always block (or task or function, but those are outside the scope of this course), while a wire
cannot. The reason—an always block contains code that is run whenever some variable(s) is/are changed.
@(*) begin
always= b * 4 + c;
a end
For example, the code in the above block will be executed whenever any value on the RHS (i.e. b
or c
) changes. This requires a
to retain its value, which it cannot do if it is a wire
.
Hence, in order to resolve the above error, the offending object should be modified to be declared as a reg
.
When assigning values to an object in an always
block, make sure it declared as a reg.
Cannot resolve multiple constant drivers
(10028): Can't resolve multiple constant drivers for net "[net_name]" at [file_name.v](line_number) Error
An object can only be assigned one value at any point in time.
Ensure net_name
is not assigned multiple values (either through assign statements or as the output of a module).
This also means a net can’t be assigned a value in more than 1 always
block.
// An interesting example:
// where are the multiple constant drivers in the following code?
module nand_270(A, B, C)
input [4:0] A, B;
output [4:0] C;
and [4:0] and1(ab, A, B);
not [4:0] not1(C, ab);
endmodule
/*
Hint: has ab been explicitly declared?
What happens to variables that are implicitly declared?
Ans: single bit wire ab is used to drive the output of all 5 'and1's. Not cool.
*/
Illegal Assignment
This means you have selected the wrong board to synthesise the program for. Selecting the correct one should resolve the error.
Top Level Not Found
Ensure the top level module name matches the name of the module you intend to have as the top level. The name of the file does not matter—only the module name does.