Lesson 02: Verilog HDL
Verilog HDL is a Hardware Description Language (HDL). A Hardware Description Language is a language used to describe electronic systems and digital logic circuits. For example, a computer or a component of a computer. One may describe a digital system at several levels. For example, an HDL might describe the layout of the wires, resistors, and transistors on an Integrated Circuit (IC) chip, i. e., the switch level. Or, it might describe the logic gates and flip-flops in a digital system, i. e., the gate level. An even higher level describes the registers and the transfers of vectors of information between registers. This is called the Register Transfer Level (RTL). Verilog supports all of these levels. However, this course focuses on only the portions of Verilog which support the RTL level.
Verilog HDL originated in 1983 at Gateway Design Automation. Later, VHDL was developed under a contract from DARPA. Many people feel that Verilog is easier to learn and use than VHDL. The main reason is that Verilog is very similar to C and most electrical and computer engineers learn C in college, so Verilog HDL is more popular with them.
Table 1: Verilog and VHDL Compared
Parameters of Comparison | Verilog | VHDL |
---|---|---|
Introduced | in 1984 | in 1980 |
Data Type | Weakly typed | Strongly typed |
Language | Looks like C | Looks like Ads (Pascal) |
Alphabets | Case sensitive | Case insensitive |
Syntax | Terse | Verbose |
Developer | Design by a few | Design by committee |
Area of Use | Used all over | Mandated by government |
Difficulty of Learning | Easy to learn | Harder to learn |
Larger and Complex circuit | Easy to screw up | Holds your hand closely |
Identifiers are names given to modules, variables, and other elements of the language so that they can be referenced in the design. In the Verilog, identifiers have the following characteristics:
- It can be composed of letters (a ~ z, A ~ Z), numeric characters (0 ~ 9), and underscore (_).
- Must start with an alphabetic character or an underscore, not with a number.
- Identifiers are case-sensitive.
- It cannot be the same as Verilog keywords.
1.1 Logic Values
Verilog has four logic values:
- 0 - represents logic 0, false condition, connected to GND, number 0
- 1 - represents logic 1, true condition, connected to Vcc, number 1
- x - represents unknown logical value, or "don't care" logic value (Still logical 0 or 1)
- z - represents a hi-impedance state (used for tri-state buffer), floating wire, or undefined value
1.2 Numbers in Verilog
Verilog gives you several options for representing literal numbers. You can use binary, decimal, octal, or hexadecimal literals and specify their width in bits.
Numbers are represented in Verilog as follow:
<size>'<signed><radix>value // "< >" indicates optional part
- size
The number of binary bits the number is comprised of. (Not number of hex or decimal digital.)
Default is 32 bits - '
A separator, single quote - signed
Indicates if the value is signed. Either s or S can be used.
Default is unsigned - radix
Radix of the number
'b or 'B: binary
'h or 'H: hex
'o or 'O: octal
'd or 'D: decimal
Default is decimal - value
Possible values for "value" are dependent on the radixFormat Prefix Legal Characters binary 'b 0 1 x X z Z _ ? hexidecimal 'h 0~9 a~f A~F x X z Z _ ? octal 'o 0~7 x X z Z _ ? decimal 'd 0~9 _ - The underscore "_" is a separator used to improve readability. For example: 16'b0010_1010_1110_0101 is easily read as 16'h2AE5.
- The character "x" or "X" represents the unknown.
- The character "z" or "Z" represents high impedance.
- The character "?" same as Z (high impedance)
- The character "?" is also "don't care" to synthesis
If a number is without a prefix, the number is assumed to be 32 bits.
'hFF | ⇒ 0x0000_00FF hex, default 32 bit |
16'hFF | ⇒ 0x00FF hex, 16 bit |
140 | ⇒140 decimal, default 32 bit |
Bit Extend
Verilog extends <value> to fill given <size> working from LSB to MSB.
- if <size> is smaller than <value>
MSB's of value are truncated wirth warning. - If <size> is greater than <value>
MSB's of value are filled - 0-filling is done regardless of whether the MSB begins from 0 or 1
Left-most Bit Expansion Example 0 0 extend 8'b0100 => 8'b0000_0100 1 0 extend 8'b1011 => 8'b0000_1011 x X x or X extend 8'bx100 => 8'bxxxx_x100 z Z z or Z extend 8'bz100 => 8'bzzzz_z100
Signed Extension
If the MSB of the size is one and is signed, sign extension will occur.
reg [7:0] x1 = 4'shA; initial $displayb("x1 signed = \t", x1); reg [7:0] x2 = 5'shA; initial $displayb("x2 signed = \t", x2);
4'shA in binary is (1010)2's, and its sign bit (bit 3) is one indicating that the value is an negative number. When assign the value to a larger size, the sign bit will be extended to other high bits. So, x1 value will be (1111_1010)2's.
5'shA in binary is (0_1010)2, and its sign bit (bit 4) is zero. Wen assigns the value to a larger size, and the 0 will be filled to other high bits. x2 value will be (0000_1010)2.
When a value is assigned to a larger vector, the sign indication <s> will force sign extension when the MSB of the value is one. If a signed number such as 9'shA2, an 8-bit value in a 9-bit vector, is assigned to a larger vector, 9'shA2 will be converted to 9'sb0_1010_0010. The sign bit (bit 8) is zero, so the sign is not extended.
Some examples:
- reg [11:0] a = 8'shA2;
Number 0xA2, equal to (1010 0010)2's, is signed, and the sign bit (bit 7) is one, so it is a negative number. To produce the 12-bit result, its sign-extended with 1's. Thus, a = (1111_1010_0010)2's. - reg [11:0] b = 8'sh2A;
Signed number 0x2A, equal to (0010 1010)2, has sign bit (bit 7) is zero, it is positive, so to produce the 12-bit result, its sign-extended with 0's, thus, b = (0000_0010_1010)2. - reg [11:0] c = 'shA2;
c is the signed number A2, but its MSB (bit 31) is zero as its 32 bits long. So c = (0000_1010_0010)2, not sign extended. - reg [11:0] d = -8'shA2;
0xA2 is signed number, which equals to (1010 0010)2's, and its sign bit is one, so the vlaue is equal to -(0101_1110)2 = -94. The assignment will be d = -(-94) = 94 = 10'sb0000_0101_1110. - reg [11:0] e = -'shA2;
0xA2 is signed, unsized with sign bit (bit 31) zero. so it is a positive value: (0000_0000_0000_0000_0000_0000_1010_0010)2.
Take 2's complement of (-A2), we get: (1111_1111_1111_1111_1111_1111_0101_1110)2's. Assigning to 12-bit reg by sign extending: e = 12'sb1111_0101_1110.
Signed Number Calculations
If your application requires negative values, you need to handle signed numbers. The standard approach is two's complement, as with most software development. In the Verilog, declared victors are signed as follow:
reg [7:0] u; // unsigned (0 ... 255)
reg signed [7:0] s; // signed (-128 ... 127)
For literals, you can add the s prefix to the base:
reg signed [7:0] a = -8'sd25; // a value: -25 (signed)
reg signed [7:0] b = 8'sd64; // b value: +64 (signed)
Beware signed Logic!
Verilog treats variables as unsigned unless all variables in an expression are signed. The $signed operator can be used to force a variable to be signed if required.
The following testbench shows that can happen when you mix signed and unsigned variables in an expression:
module signed_tb (); logic [7:0] x, y; logic signed [7:0] x1, y1; logic signed [3:0] offset; always_comb begin x1 = x + offset; // AVOID! This probably won't work as expected! y1 = $signed(y) + offset; // ensure y is treated as signed end initial begin #10 $display("Coordinates (7,7):"); x = 8'd7; y = 8'd7; #10 $display("x : %b %d", x, x); $display("y : %b %d", y, y); #10 $display("With offset +4:"); offset = 4'sd4; #10 $display("x1: %b %d", x1, x1); $display("y1: %b %d", y1, y1); #10 $display("With offset -4:"); offset = -4'sd4; #10 $display("x1: %b %d *SURPRISE*", x1, x1); $display("y1: %b %d", y1, y1); end endmodule
The results as below:
Coordinates (7,7):
x : 00000111 7
y : 00000111 7
With offset +4:
x1: 00001011 11
y1: 00001011 11
With offset -4:
x1: 00010011 19 *SURPRISE*
y1: 00000011 3
Do not mix and match signed and unsigned variables in the same expression!