Verilog Intro: Part 1
Hardware Description Languages A Hardware Description Language (HDL) is a language used to describe a digital system, for example, a computer or a component of a computer. A digital system can be described at several levels: – Register Transfer Level (RTL): registers and the transfers of information between registers. – Gate level: logical gates and flip-flops – Switch level: wires, resistors and transistors Two Major HDLs in Industry – VHDL (Mostly in Europe) – Verilog HDL (Mostly in USA)
Verilog HDL vs. VHDL VHDL “V” is short for Very High Speed Integrated Circuits. Designed for and sponsored by US Department of Defense. Designed by committee ( ). Syntax based on Ada programming language. Was made an IEEE Standard in Verilog HDL Was introduced in 1985 by Gateway Design System Corporation, now a part of Cadence Design Systems, Inc.'s Systems Division. Was made an IEEE Standard in 1995 (IEEE 1364) Syntax based on C programming language.
Design Methodology
Identifiers An identifier is composed of a space-free sequence of uppercase and lowercase letters from alphabet, digits (0,1,….9), underscore (_), and the $ symbol. Verilog is a case sensitive language. – c_out_bar and C_OUT_BAR are two different identifiers The name of a variable may not begin with a digit or $, and may be up to 1,024 characters long. – e.g. clock_, state_3
Comments There are two kinds of comments: single line and multiline. A single-line comment begins with two forward slashes (//) A multiline comment begins with the pair of characters /* and terminate with the characters */ Example: – // This is a single-line comments – /* This is a multiline comments more comments here …………………………………. */
Numbers Numbers are specified using the following form size: a decimal number specifies the size of the number in bits. base format: is the character ’ followed by one of the following characters – b for binary, d for decimal, o for octal, h for hexadecimal number: The number of binary bits the number is comprised of. Not the number of hex or decimal digits. Default is 32 bits.
Numbers Example: x = 347 // decimal number x = 4 ’ b101 // 4- bit binary number 0101 x = 6 ’ o12 // 6-bit octal number x = 16 ’ h87f7 // 16-bit hex number h87f7 x = 2 ’b x = 2 ’ d83 String in double quotes “ this is an introduction ”
Operators Bitwise Operators ~ NOT & AND | OR ^ XOR ~^ XNOR Logical Operators !, &&, | | Relational Operators ==, !=, >=,, < Reduction Operators (Unary) &, ~&, |, ~|, ^, ~^
Operators Arithmetic Operators +, -, *, /, % Concatenation & Replication Operators {identifier_1, identifier_2, …} {n{identifier}} – Examples: {REG_IN[6:0],Serial_in} {8{1’b0}}
Value Logic System Data type for signals Bits (value on a wire) – 0, 1 – x unknown value Vectors of bits (parallel wires or registers) – A[3:0] is a vector of 4 bits: A[3], A[2], A[1], A[0] – Concatenating bits/vectors into a vector B[7:0] = {A[3], A[3], A[3], A[3], A[3:0]}; B[7:0] = {4{A[3]}, A[3:0]};
Data Types: Constants A constant is declared with the keyword parameter in a statement assigning a name and a value to the constant The value of a constant is fixed during simulation. Examples: – parameter HIGH_INDEX= 31; // integer – parameter BYTE_SIZE = 8;
Data Types: Variables Two basic families of data types for variables: Nets and Registers Net variables – e.g. wire – Variable used simply to connect components together – Usually corresponds to a wire in the circuit. Register variables – e.g. reg – Variable used to store data as part of a behavioral description – Like variables in ordinary procedural languages Note: – reg should only be used with always and initial blocks – The reg variables store the last value that was procedurally assigned to them whereas the wire variables represent physical connections between structural entities such as gates.
Continuous Assignment A continuous assignment statement is declared with the keyword assign, followed by a net(e.g. type wire) variable, an assignment operator(=), and an expression. assign corresponds to a connection. Target is never a reg variable. – assign A = B | (C & ~D); // not the use of ~ not ! – assign B[3:0] = 4'b01XX; – assign C[15:0] = 16'h00ff; //(MSB:LSB) – assign {Cout, S[3:0]} = A[3:0] + B[3:0] + Cin;
Procedural Assignment Procedural assignments have the form = where the must be a register or memory. e.g. reg enable, d; enable = 0; d = 0;
Primitives No declaration required (predefined) ; Can only be instantiated Example: and a1 (C, A, B); //instance name – Usually better to provide instance name for debugging. Example: or o1 (SET, ~A, C ), o2(N, ABC,SET ); Example: and #(10) a2(o, i1, i2); // name + delay
Program Structure: Modules Any digital system is a set of modules. Modules may run concurrently, but usually there is one top level module to specify a closed system containing both test data and hardware models. The top level module invokes instances of other modules. A module is never called, it is instantiated. Modules can be specified behaviorally or structurally (or a combination of the two). A behavioral specification defines the behavior of a digital system using traditional programming language constructs (e. g.,if else, assignment statements). A structural specification expresses the behavior of a digital system (module) as a hierarchical interconnection of submodules.
The Structure of a Module The structure of a module is the following: module ( ); endmodule is an identifier that uniquely names the module. is a list of input, output and inout ports which are used to connect to other modules. specifies data objects as registers, memories & wires as wells as procedural constructs such as functions & tasks. may be – initial constructs, – always constructs, – continuous assignments or – instances of modules.
Module ports Module name Verilog keywords Taste of Verilog (Structural) module HalfAdder(sum, c_out, a, b ); inputa, b; outputsum, c_out; wire c_out_bar; xor g1(sum, a, b); nand g2(c_out_bar, a, b); not g3(c_out, c_out_bar); endmodule Declaration of port modes Declaration of internal signal Instantiation of primitive gates c_out a b sum c_out_bar
module HalfAdder(sum, c_out, a, b ); inputa, b; outputsum, c_out; assign {c_out, sum} = a + b; endmodule Taste of Verilog (Behavioral)
Test Bench module ; // Data type declaration // Instantiate module ( call the module that is going to be tested) // Apply the stimulus // Display results endmodule
Test Bench Example module HalfAdder_tb; // Test bench to test half adder reg A, B; wire s, cOut; HalfAdder dut( s, cOut, A, B ); // instantiate the half adder initial begin // apply the stimulus, test data A = 1'b0; B = 1'b0; #100 A = 1'b1; // delay one simulation cycle, then change A=>1. #100 B = 1'b1; #100 A = 1'b0; end initial #500 $finish; initial begin // setup monitoring //$monitor("Time=%d A=%b B=%b s=%b cOut=%b", $time, A, B, s, cOut); end endmodule