Objective
- Understand the Verilog language syntax.
Understand the constructs used to model the behavior of digital systems.1. Lexical Conventions
Whitespace (space, tab, newline): Ignored in Verilog except when separating tokens. Not ignored in strings. Comments - Single Line (//) - Multiple line (/* */) Operators
Operator Type Operator Symbol Operation Performed Number of Operands Arithmetic *
/
+
-
%multiply
divide
add
subtract
modulus 2
2
2
2
2 Logical!
&&
||logical negation
logical and
logical or1
2
2Relational >
<
>=
<=greater than
less than
greater than or equal
less than or equal
2
2
2
2Equality ==
!=
===
!==equality
inequality
case equality
case inequality2
2
2
2Bitwise ~
&
|
^
^~ or ~^bitwise negation
bitwise and
bitwise or
bitwise xor
bitwise xnor1
2
2
2
2Reduction &
~&
|
~|
^
^~ or ~^reduction and
reduction nand
reduction or
reduction nor
reduction xor
reduction xnor1
1
1
1
1
1Shift >>
<<Right shift
Left shift2
2Concatenation
Replication{ }
{ \d{ } }Concatenation
Replicationany
anyConditional ?: Conditional 3
Number Specification
- Sized Numbers
<size>'<base_format> <number>
<size> is a decimal number and specifies the number of bits in the number
<base_format> is one of [dD] - decimal, [hH] - hex, [bB] - binary, [oO] - octal.
<number> is a string of characters representing legal number types for the specified base format ([0-9] for decimal, [0-9,a-f,A-F] for hex, [0-1] for binary, [0-7] for octal.
- Unsized numbers
Numbers specified without the <base_format> specification are decimal numbers by default. Numbers that are written without a <size> specification have simulator-specified number of bits (that must be at least, and usually is, 32 bits - which we will assume for this course).- Values - 0, 1, x (unknown), z (high impedance)
An x or z sets 1 bit in the binary case, three bits in the octal case and four bits in the hexadecimal case. If the most significant represented bit of a number is 0, x, or z, then the number is automatically extended to fill the most significant bits with that value. If the most significant represented bit is a 1, then the number is 0 extended.- Negative numbers
Negative numbers can be specified by putting a minus sign before the size for a constant number. It is illegal to have a minus sign between <base_format> and <number>.
123
32 bit decimal 'h7C4 32 bit hex 'o765 32 bit octal 4'b11 4 bit binary 3'b10x 3 bit binary 9'bx10 9 bit binary, x-extended 5'd3 5 bit decimal -4'b11 4 bit binary two's complement of 0011 == 1101.
Thepart may not contain a sign. Any sign must go on the front.
- Identifiers
Identifiers are names given to objects so that they can be referenced in the design. Identifiers are made up of alphanumeric characters, the underscore, and the dollar sign ($). Identifiers are case sensitive and cannot start with a number or the dollar sign. The dollar sign is reserved as the first character for system tasks.
An identifier can be "escaped" using the backslash '\' and ends with whitespace. Using escaped identifiers, any printable ASCII character can be used in the identifier. Escaped identifiers are commonly used by verilog netlist generators.2. Data Types
- Nets (note that net is not a keyword) - Nets represent connections between hardware elements. As in hardware, nets have values continuously driven on them by the outputs of the devices that they are connected to. Typically, nets are declared as type wire. Undefined variables default to 1 bit wires. If a net has no driver, it will default to 'X'. Other types of nets are wand, wor, tri, triand, trior ...
- Registers - Registers are data storage elements that retain their value until another value is placed on them. Despite the poor choice of names, remember that registers are not equivalent to the hardware flip-flop. In Verilog, a register simply holds a value - the main difference between the Verilog register and the hardware flip-flops is that the flip-flop is synchronous. The register can be set at any time. Furthermore, registers do not need a driver. They can be set anywhere in the simulation from other registers, from the value of wires, or from constants. The default value for an unassigned register is 'X'.
- Vectors (this applies to wires as well)
vectors are declared as [highbit : lowbit] or [lowbit : highbit], but the leftmost number is always the most significant bit of the vector (remember when extending).
When referencing a vector, range indices must be constants - bit indices can be variables.
Declaration Reference Commentreg bus[7:0] bus[4:0] The 5 least significant bits of bus. wire addends[4:2] addends[3:2] The 2 least significant bits of addends wire addends[2:4] addends[2:3] The two most significant bits of addends reg value [5:0] value[var:1] Illegal - indices must be constant reg value [5:0] value [n] The n'th bit of value where n is a register or net.
- Integer - Be warned that a reg variable is unsigned and that an integer variable is a signed 32-bit integer (more technically, at least a 32 bit integer - the bitsize is implementation specific, but must be at least 32 bits). This has important consequences when you subtract. Integers are very useful in testbenches or when representing variables that don't get synthesized (like loop counters). This insures that you have enough room for any data that you want to put into the integer.
- Real - Real numbers are not synthesizable They are used almost exclusively in testbenches.
- Time - Time variables are again, implementation specific, but are usually 64 bits in size. They are used to mark simulation time. The system function $time returns the current simulation time.
- Arrays/Memories - Arrays are allowed for reg, integer, and time data types. Multidimensional arrays are not permitted in verilog.
Memories are specified as vectors of registers. For example, MyMem is 1K words each 32-bits.
reg [31:0] MyMem [0:1023]The notation MyMem[0] references the zeroth word of memory. The array index for memory (register vector) may be a register. Notice that one can not reference a memory at the bit-level in Verilog HDL. If you want a specific range of bits in a word of memory, you must first transfer the data in the word to a temporary register.
- Strings - Technically speaking, the string is not a separate data type in verilog. Strings are stored in register vectors, and each character takes 8 bits (1 byte). Strings are typically declared as a register vector that is 8 times the size of the expected string; e.g.
reg string [8*strlen : 1] mystring;Whenever you see the above vector notation (8*var:1) in a reg declaration, that reg is almost certainly a string.
- Parameters - Verilog allows a module to define parameters. These parameters can be used as constants within the module. When a module is instantiated, it can be instantiated with unique parameters, so that a generic counter module can be implemented with a parameter, and then specific instantiations can specify the parameter. Notice that a parameter is considered as a constant inside the Verilog module. It can thus be used in a vector range index
3. Continuous Assignments
A continuous assignment is the most basic statement in dataflow modeling. Using a continuous assignment, a value can be driven onto a net.
- The assign statement
- assign <drive_strength> <delay> <list_of_assignments>;
- The left hand side must always be of type net. (It can be a scalar, vector, or concatenation).
- Continuous assignments are always active and change whenever the right-hand-side operands change.
- The right-hand-side operands can be registers or nets or function calls (vectors or scalars or concatenations are allowed).
Delay values can be specified for assignments in terms of time units. assign out = i1 & i2; assign addr[15:0] = addr1_bits[15:0] ^ addr2_bits[15:0]; assign (c_out, sump3:0]} = a[3:0] + b[3:0] + c_in;- Implicit Continuous Assignment - rather than declaring a wire and then doing a continuous assignment, the two statements can be done together.
wire out = in1 & in2;- Assignment Delay
assign #10 out = in1 & in2;- Implicit continuous assignment delay
wire #10 out = in1 & in2;4. Behavioral Modeling
- The Process Model - The essence of the behavioral model is the process. It can be thought of as an independent thread of control.
The initial block
Initial blocks are set to execute at time 0 of the simulation. They proceed sequentially through the block, terminating on the final statement of the block.- The always block
The always block continuously executes it's block, never exiting or stopping. A behavioral model can contain one or more always statements.- Block suspension
Block processing can be suspended when an event statement (@) or a delay statement (#) is encountered, or, potentially when a wait statement is executed.- If - Else
In an if statement, the else is paired with the nearest, unfinished if statement. Begin-end pairs can be used to avoid confusion.
The ?: conditional operator can be used when one of the two values is to be selected for assignment.- Loops
- Repeat
integer count; initial begin count = 0; repeat (128) begin $display("Count = %d", count); count = count + 1; end end- For
integer count; initial begin for (count = 0; count < 128; count = count + 1) //notice the 3rd term $display("Count = %d", count); end end- While
integer count; initial begin while (count < 128) begin $display("Count = %d", count); count = count + 1; end end- Forever
reg clock; initial begin clock = 1'b0; forever #10 clock = ~clock; end- Breaking out of loops
- Named loops
- Disable statement
- Case Statements
reg ready; case (ready) 1'bz: $display ("ready is high impedance"); 1'bx: $display ("ready is unknown"); default: $display ("ready is %b", ready); endcase- Casez and Casex - Casez allows z values to be treated as don't-care values, Casex allows both z and x values to be treated as don't care values.
r = 8'bx1x0x1x0; casex(r) 8'b001100xx: statement1; 8'b1100xx00: statement2; 8'b00xx0011: statement3; 8'bxx001100: statement4; endcase- Tasks and Functions - Verilog functions and tasks are similar to software functions and tasks except that the source for the function/task must be included inside a module, rather than outside of it. For functions and tasks that find use in multiple modules, this is normally done by putting the function/task in a separate file and including the function/task in the module via the `include directive.
- Tasks
- Called from a statement.
- Parameters passed to and from the tasks - these are not like ports to a module
module mark1Task; reg [15:0] m [0:8191]; // 8192 x 16 bit memory reg [12:0] pc; // 13 bit program counter reg [12:0] acc; // 13 bit accumulator reg ck; // a clock signal always begin: executeInstructions reg [15:0] ir; // 16 bit instruction register @(posedge ck) ir = m [pc]; @(posedge ck) case (ir [15:13]) // other case expressions as before 3'b111 : multiply (acc, m [ir [12:0]]); endcase pc = pc + 1; end task multiply; inout [12:0] a; input [15:0] b; begin: serialMult reg [5:0] mcnd, mpy;//multiplicand and multiplier reg [12:0] prod;//product mpy = b[5:0]; mcnd = a[5:0]; prod = 0; repeat (6) begin if (mpy[0]) prod = prod + {mcnd, 6'b000000}; prod = prod >> 1; mpy = mpy >> 1; end a = prod; // note that a is not an inout port (wire data type) end endtask endmodule- Functions
- Called from within an expression.
- Returns a value to an expression.
- Has one output (the function name) and at least one input.
- May not include event (@) or delay (#) statements, or , to say it another way, a function must execute in one simulation time unit.
module mark1Fun; reg [15:0] m [0:8191]; // 8192 x 16 bit memory reg [12:0] pc; // 13 bit program counter reg [12:0] acc; // 13 bit accumulator reg ck; // a clock signal always begin: executeInstructions reg [15:0] ir; // 16 bit instruction register @(posedge ck) ir = m [pc]; @(posedge ck) case (ir [15:13]) //case expressions, as before 3'b111: acc = multiply(acc, m [ir [12:0]]); endcase pc = pc + 1; end function [12:0] multiply; input [12:0] a; input [15:0] b; begin: serialMult reg [5:0] mcnd, mpy; mpy = b[5:0]; mcnd = a[5:0]; multiply = 0; repeat (6) begin if (mpy[0]) multiply = multiply + {mcnd, 6'b000000}; multiply = multiply >> 1; mpy = mpy >> 1; end end endfunction endmodule- Scope and Hierarchical Names - The '.' is the hierarchical delimeter.Verilog allows forward referencing (referring to the item before it has been defined) on modules, tasks, functions, and named blocks. It does not allow forward referencing for register and net accesses.
module top; reg r; //hierarchical name is top.r wire w; // hierarchical name is top.w b instance1(); always begin: y reg q; //hierarchical name is top.y.q end task t; begin: c //hierarchical name is top.t.c reg q; //hierarchical name is top.t.c.q disable y; // OK end endtask endmodule module bl reg s; //hierarchical name is top.instance1.s always begin t; //OK disable y; //OK disable c; //Nope, c is not known disable t.c; //OK s = 1; //OK r = 1; //Nope, r is not known top.r = 1; //OK t.c.q = 1; //OK y.q = 1; //OK, a different q than t.c.q end endmodule
Last updated Mon, 21 Sep 1998 12:53:09 GMT