CSE 341 Verilog HDL An Introduction Hardware Specification Languages Verilog Similar syntax to C Commonly used in Industry (USA & Japan) VHDL Similar syntax to ADA Commonly used in Government Contract Work Academia Europe Structural vs. Behavioral Structural Shows primitive components and how they are connected Modules are defined as a collection of interconnected gates and other previously defined modules Modules are built up to make more complex modules The design describes the structure of the circuit Behavioral Shows functional steps of how the outputs are computed Abstract description of how the circuit works Does not include any indication of structure (implementation) details Useful early in design process Allows designer to get a sense of circuit’s characteristics before embarking on design process After functionality is well defined, structural design may follow Synthesis Tools Generate implementation based on the behavioral specification Overview System is described as a set of modules consisting of: Interface Declares nets & registers which comprise the two (2) fundamental data types in Verilog Nets Used to connect structures (eg. - gates) Need to be driven Reg Data storage element Retain value until overwritten by another value Don’t need to be driven Description Defines structure Modules Instantiating modules can help make code easier to write, modify, read, and debug Examples Carry Lookahead Adder Partial Full Adder Carry Lookahead Unit Barrel Shifter 7-Segment Display Decoder Basic Module Format module name; Interface Description endmodule Modules Structure module modulename(port list); parameters port declarations (input or output) wire declarations reg declarations submodule instantiations … text body … endmodule Instantiations modulename instance_name(port list); Datatypes Net Wire Register Reg Static Storage Element Parameters Parameters Used to define constants in modules Examples parameter and_delay=2, or_delay=1; and #and_delay (f,a,b); Primitive Structural Modules Define the structure of the module Form the module’s body Format gate #n (output, inputs) Note: The integral delay (#n ) may be neglected If omitted, delay = 0 Gates and or nand not xor Identifiers Names given to hardware objects Wires (busses) Registers Memories Modules Alphanumeric May Include: _ $ May NOT Start With: Number $ Numbers Syntax Sized Size’Format Number Size Number of digits Format (Base) h (Hexadecimal) d (Decimal) Default o (Octal) b (Binary) Number Number specified Unsized ’Format Number Numbers Examples 4’b1011 8’hfe902a30 2’d37 Same as 37 (default) 4’h a729 ‘d 62923 8’b 1101zzzz 16’h x The Full Adder Consider a Full Adder The Full Adder Basic Module module fulladder() ; wire w1, w2, w3, w4, s, cout; reg a, b, c; xor g1(w1, a, b), g2(s, w1, c); and g3(w2, c, b), g4(w3, c, a), g5(w4, a, b); or g6(cout, w2, w3, w4); --> Simulation <-endmodule Simulation The simulation is an event-driven, timeordered depiction of the circuit’s behavior under the prescribed specifications. Structure initial begin Simulation end Simulation Some Useful Simulation Commands $monitor(“format”, variable list); Displays the specified entities when the values change Modelled after C’s printf Extra commas add spaces in the output Format %b bit %d decimal %h hexadecimal $display (“format”, variable list); Similar to monitor, but displays variable list in the format specified whenever it is encountered Simulation Some Useful Simulation Commands $time Keeps track of simulator’s time Used to maintain current time by simulator The simulation will display the time when an event occurs Referenced by $time Specification of Units ‘timescale units / least significant digit to be printed Example ‘timescale 10 ns / 100 ps Units of 10 ns are used, printing out to no more precision than 100 ps Simulation Some Useful Simulation Commands Integral Delay #n Delays action by n time units (as defined by the timescale) In other words… n time units after the current time, the described event will take place May also be used for setting module & gate delays Example will follow Simulation A bit in the simulation may take one of four values: 1 (true) 0 (false) X (unknown) Z (High Impedance) The Full Adder Basic Module module fulladder() ; wire w1, w2, w3, w4, s, cout; reg a, b, c; xor g1(w1, a, b), g2(s, w1, c); and g3(w2, c, b), g4(w3, c, a), g5(w4, a, b); or g6(cout, w2, w3, w4); initial begin $monitor($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); $display($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); #10 a=0; b=0; c=0; #10 a=1; #10 b=1; #10 c=1; a=0; #10 a=1; #10 // Required for iverilog to show final values $display($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); end endmodule Simulation Timescale Compiler Directive Preceded by ` Note, this is not an apostrophe `timescale reference_time_unit / time_precision The Full Adder Basic Module `timescale 1ns/1ns module fulladder() ; wire w1, w2, w3, w4, s, cout; reg a, b, c; xor g1(w1, a, b), g2(s, w1, c); and g3(w2, c, b), g4(w3, c, a), g5(w4, a, b); or g6(cout, w2, w3, w4); initial begin $monitor($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); $display($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); #10 a=0; b=0; c=0; #10 a=1; #10 b=1; #10 c=1; a=0; #10 a=1; #10 // Required for iverilog to show final values $display($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); end endmodule Simulation Other Common Directives Define Defines constants or macros Structure `define name definition; Example `define delay 1 Include Allows for multiple source file use Not needed in Xilinx Structure `include filename Example `include multiplexors.v Full Adder Functional Simulation Text Output # # # # # # # 0 10 20 30 40 50 60 a=x, a=0, a=1, a=1, a=0, a=1, a=1, Waveform b=x, b=0, b=0, b=1, b=1, b=1, b=1, c=x, c=0, c=0, c=0, c=1, c=1, c=1, s=x, s=0, s=1, s=0, s=0, s=1, s=1, cout=x cout=0 cout=0 cout=1 cout=1 cout=1 cout=1 Full Adder Under Unit Delay Model Basic Module `timescale 1ns/1ns module fulladder() ; wire w1, w2, w3, w4, s, cout; reg a, b, c; xor #1 g1(w1, a, b), g2(s, w1, c); and #1 g3(w2, c, b), g4(w3, c, a), g5(w4, a, b); or #1 g6(cout, w2, w3, w4); initial begin $monitor($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); $display($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); #10 a=0; b=0; c=0; #10 a=1; #10 b=1; #10 c=1; a=0; #10 a=1; #10 // Required for iverilog to show final values $display($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); end endmodule Full Adder Under Unit Delay Model Basic Module `timescale 1ns/1ns module fulladder() ; wire w1, w2, w3, w4, s, cout; reg a, b, c; xor #1 g1(w1, a, b), g2(s, w1, c); and #1 g3(w2, c, b), g4(w3, c, a), g5(w4, a, b); or #1 g6(cout, w2, w3, w4); initial begin $monitor($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); $display($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); #10 a=0; b=0; c=0; #10 a=1; #10 b=1; #10 c=1; a=0; #10 a=1; #10 // Required for iverilog to show final values $display($time,,,, "a=%b, b=%b, c=%b, s=%b, cout=%b",a,b,c,s,cout); end endmodule Full Adder Unit Delay Simulation Text Output # # # # # # # # # # # # # 0 10 12 20 22 30 32 40 41 42 50 52 60 a=x, a=0, a=0, a=1, a=1, a=1, a=1, a=0, a=0, a=0, a=1, a=1, a=1, Waveform b=x, b=0, b=0, b=0, b=0, b=1, b=1, b=1, b=1, b=1, b=1, b=1, b=1, c=x, c=0, c=0, c=0, c=0, c=0, c=0, c=1, c=1, c=1, c=1, c=1, c=1, s=x, s=x, s=0, s=0, s=1, s=1, s=0, s=0, s=1, s=0, s=0, s=1, s=1, cout=x cout=x cout=0 cout=0 cout=0 cout=0 cout=1 cout=1 cout=1 cout=1 cout=1 cout=1 cout=1 Comments Single Line Comments Comment preceded by // Example or #1 // OR gate with a g6(cout, w2, w3, w4); delay of one time unit Multiple Line Comments Comment encapsulated by /* and */ Example and #1 g1(e, a, b); /* In this circuit, the output of the AND gate is an input to the OR gate */ or #1 g2(f, c, e); Creating Ports Port names are known only inside the module Declarations Input Output Bidirectional Full Adder Module fulladder a s b c cout Creating Ports in the Full Adder `timescale 1ns/1ns module fulladder(a,b,c,s,cout); input a,b,c; output s,cout; xor #1 g1(w1, a, b), g2(s, w1, c); and #1 g3(w2, c, b), g4(w3, c, a), g5(w4, a, b); or #1 g6(cout, w2, w3, w4); endmodule Creating Ports in the Full Adder `timescale 1ns/1ns module fulladder(a,b,c,s,cout); input a,b,c; output s,cout; xor #1 g1(w1, a, b), g2(s, w1, c); and #1 g3(w2, c, b), g4(w3, c, a), g5(w4, a, b); or #1 g6(cout, w2, w3, w4); endmodule Instantiation Modules can be instantiated to complete a design 4-bit Ripple Carry Adder fulladder fulladder fulladder fulladder a a a a s b c s b cout c s b cout c s b cout c cout Vectors Scalar A single bit net or reg Vector A multiple bit net or reg Advantage Vectors make for a more natural way of scaling up a design Example Consider the 4-bit adder Using scalars: A3 A2 A1 A0 + B3 B2 B1 B0 + Cin = Cout S3 S2 S1 S0 Using vectors: A + B + Cin = Cout, S A[3:0] + B[3:0] + Cin = Cout, S[3:0] Vectors Details wire and reg may be declared as multibit [expression_1 : expression_2] Note: Left expression is MSB, right is LSB Expression must be constant, but may contain constants operators parameters Vectors Concatenation A bitvector can be created by concatenating scalar carriers and/or bitvectors Example reg sum[3:0] reg cout [cout,sum] Replication n{bitvector} Replicates the bitvector n times. Example 4{b’1001} results in 1001100110011001 Creating the 4-bit Adder `timescale 1ns/1ns module fulladder(a,b,c,s,cout); input a,b,c; output s,cout; xor #1 g1(w1, a, b), g2(s, w1, c); and #1 g3(w2, c, b), g4(w3, c, a), g5(w4, a, b); or #1 g6(cout, w2, w3, w4); endmodule module fourBitAdder(x,y,s,cout,cin); input [3:0] x,y; output [3:0] s; input cin; output cout; wire c[3:0]; fulladder fulladder fulladder fulladder endmodule f0 f1 f2 f3 (x[0],y[0],cin,s[0],c[0]); (x[1],y[1],c[0],s[1],c[1]); (x[2],y[2],c[1],s[2],c[2]); (x[3],y[3],c[2],s[3],cout); Creating the 4-bit Adder `timescale 1ns/1ns module fulladder(a,b,c,s,cout); input a,b,c; output s,cout; xor #1 g1(w1, a, b), g2(s, w1, c); and #1 g3(w2, c, b), g4(w3, c, a), g5(w4, a, b); or #1 g6(cout, w2, w3, w4); endmodule module fourBitAdder(x,y,s,cout,cin); input [3:0] x,y; output [3:0] s; input cin; output cout; wire [3:0] c; fulladder fulladder fulladder fulladder endmodule f0 f1 f2 f3 (x[0],y[0],cin,s[0],c[0]); (x[1],y[1],c[0],s[1],c[1]); (x[2],y[2],c[1],s[2],c[2]); (x[3],y[3],c[2],s[3],cout); Creating a Testbench Provides for efficient testing of circuit Process Create a module dedicated for testing Instantiate Test Module Circuit to be Tested Wire the modules together Note that initial assignments in blocks must always be made to registers Testbench for the 4-bit Adder `timescale 1ns/1ns module testbench(); wire [3:0] x,y,s; wire cin,cout; testAdder test (x,y,s,cout,cin); fourBitAdder adder (x,y,s,cout,cin); endmodule module testAdder(a,b,s,cout,cin); input [3:0] s; input cout; output [3:0] a,b; output cin; reg [3:0] a,b; reg cin; initial begin $monitor($time,,"a=%d, b=%d, c=%b, $display($time,,"a=%d, b=%d, c=%b, #20 a=2; b=3; cin=0; #20 a=1; b=7; cin=0; #20 // Required for iverilog $display($time,,"a=%d, b=%d, c=%b, s=%d, cout=%b",a,b,cin,s,cout); s=%d, cout=%b",a,b,cin,s,cout); to show final values s=%d, cout=%b",a,b,cin,s,cout); end endmodule // Don’t forget to include the fourBitAdder and fulladder modules 4-bit Adder Unit Delay Simulation Text Output # # # # # # # # # # 0 20 22 23 40 42 43 45 47 60 a= a= a= a= a= a= a= a= a= a= x, 2, 2, 2, 1, 1, 1, 1, 1, 1, b= b= b= b= b= b= b= b= b= b= Waveform x, 3, 3, 3, 7, 7, 7, 7, 7, 7, c=x, c=0, c=0, c=0, c=0, c=0, c=0, c=0, c=0, c=0, s= x, s= x, s= X, s= 5, s= 5, s= 2, s=12, s= 0, s= 8, s= 8, cout=x cout=x cout=0 cout=0 cout=0 cout=0 cout=0 cout=0 cout=0 cout=0 Icarus Verilog iverilog Available on the CSE systems Using iverilog Enter source code using any editor Save using .v exention Compile iverilog -t vvp filename.v -o out_filename Note that neglecting to specify the output filename (-o out_filename), iverilog will output to a.out. View Results vpp out filename Example Simulate the following circuit using Verilog HDL. a b x c y f Example a module eg_function(); x reg a,b,c; b wire f; ckt inst1(f,a,b,c); y c initial begin $monitor($time,"a =%b, b=%b, c=%b, f=%b",a,b,c,f); $display($time,"a =%b, b=%b, c=%b, f=%b",a,b,c,f); #0 a=0; b=0; c=0; #10 a=1; b=1; c=0; #10 a=1; b=1; c=1; #10 // Required for iverilog to show final values $display($time,"a =%b, b=%b, c=%b, f=%b",a,b,c,f); end endmodule module ckt(f,a,b,c); parameter delay=1; output f; input a,b,c; wire x,y; and #delay (x,a,b); or #delay (y,b,c); xor #delay (f,x,y); endmodule f