Lecture 2
• User Defined Primitive (UDP)
• `timescale directive
• IO
• Modules
• Parameters
• Combinational Logic
4.1 Introduction
• Digital systems consist of combinational and sequential circuits
– Combinational
• Operation specified logically by a set of Boolean functions
Outputs are a continuous function of inputs
– Sequential
• Outputs a function of inputs and state of storage elements
User Defined Primitive (UDP) – The keywords and, or, etc. are defined by the system
and thus are system primitives
– The user can create additional primitives by defining them in tabular format • Scoped by table, endtable keywords
– Declared with primitive … endprimitive
– The current IEEE 1364 standard provides for
multiple-inputs/outputs UDPs but multiple outputs are not common
– The output terminal must be first in the terminal list
– All UDP terminals are scalar
– No bidirectional inout terminals allowed
The high impedance value (z) cannot be specified
UDPs
• Example from av16_svt16_composite_gate_verilog.v:
– Note: the //D0 D1… comment line is just a comment line
The table column order is determined by the input order
primitive mux2_UDP0_SVT16(Q, D0, D1, SEL1); output Q; input D0, D1, SEL1; table // D0 D1 SEL1 : Q 1 ? 0 : 1; ? 1 1 : 1; 0 ? 0 : 0; ? 0 1 : 0; 0 0 ? : 0; 1 1 ? : 1; endtable endprimitive
D0
D1
Q
SEL1
0
1
UDPs
primitive d_edge_ff(q, clock, data); output q; reg q; input clock, data; table // obtain output on rising edge of clock // clock data q q+ (01) 0 : ? : 0 ; (01) 1 : ? : 1 ; (0?) 1 : 1 : 1 ; (0?) 0 : 0 : 0 ; // ignore negative edge of clock (?0) ? : ? : - ; // ignore data changes on steady clock ? (??) : ? : - ; endtable endprimitive
timescale • A “`” (grave accent) indicates a compiler directive • `timescale 1ns/1ps
– Specifies the time unit and time precision • time unit
– 1ns indicates a time unit of 1ns – #10 will have a delay of 10nS
• time precision – Indicates the degree of accuracy, i.e. how delay values are rounded
• Valid time units are s, ms, us, ns, ps, fs • Only 1, 10 , or 100 are valid integers for specifying unit and precision
– Must be specified before and outside module definition • The first line of a module is the `timescale compiler directive if required,
otherwise an optional comment
– Module without timescale directive will inherent timescale from calling module
– Verilog simulates with the smallest time precision unit specified for a given module
– Make time precision no smaller than necessary
Other compiler directives • `include “filename”
– Inserts the contents of a specified file into a file in which it was called. The file name should be given in quotation marks (") and it can be given using full or relative path.
• `ifdef, `else, and `endif – These directives can be used to decide which lines of Verilog code should be
included for the compilation
– Used with `define or +define command line option
• `protect, `endprotect – Encrypts code to new file, compile with the +protect command line option
– After compilation, the new file has regions marked `protected, unprotected
– +autoprotect command line option protects all modules • Used for libraries, etc.
`ifdef NO_SLAVE … `else … `endif
`include “Chip.vh”
Module ports
• input, output, inout – Keyword that declare ports of a module or task – input and inout are of type wire – output can be of type reg, wire, wor, or tri
• Default is wire
– Direction relative to module – Enhanced with Verilog 2001 – Scalar port:
input clk;
– Vector port: output [7:0] data;
Module ports // Verilog 1995 example:
module ports1995 ( read, write, dataIn, addr, dataOut); input read, write; input [7:0] dataIn; input [3:0] addr; output [7:0] dataOut; wire read, write; wire [7:0] dataIn; wire [3:0] addr; reg [7:0] dataOut; … endmodule
// Verilog 2001 example: module ports2001 ( input wire read, write, input wire [7:0] dataIn, input wire [3:0] addr, output reg [7:0] dataOut ); … endmodule
Verilog Port Definition
• Can specify port connections implicitly or explicitly when instantiating modules – Implicit (order dependent)
– Explicit
– Safer to use explicit
module module_name(port_name, port_name, …) …
endmodule
module module_name(.port_name1(signal_nam1e), .port_name2(signal_name2), …); … endmodule
Modules • Modules is the basic unit of hierarchy in a design
– Designs would be flat w/o modules • Unwieldy for larger designs • Need a way to separate design from test bench
• Module consists of: – Boundaries (module, endmodule) – Port List: input(s), output(s), and inout(s) – parameter values (if any) into module – Behavioral code – module #(parameters) module_name (port list);
• A module should be contained within one file – Multiple files can reside with file but should be avoided – File name should have “.v” suffix
• Can be a single element (i.e. behavioral code) or collection of lower level modules with interconnect.
• Module name should match file name • Nomenclature
– Declaration: A Verilog module is declared – Instantiation: Once a Verilog module is declared it may be instantiated within a design (other
modules)
• All but top level module in a hierarchy have ports module top_tb(); … endmodule
Modules • Hello world example:
// Example of "Hello World" program in Verilog module hello_world; initial begin $display(“Hello World”); end endmodule
Parameters • A constant value declared within the module structure
• Local in scope
• May be overridden at instantiation time using the defparam statement
– If overriding value is not specified, default parameter values are used
• When one parameter depends on another, if the first one is changed, the second one will be updated automatically
• Verilog 2001 added ‘localparam’ which protects the localparam from modification by
defparam statements or module instance parameter value assignments.
• See “New Verilog-2001 Techniques for Creating Parameterized Models (or Down With `define and Death of a defparam!)” by C. Cummings
module paraDemo; parameter foo = 0; endmodule // Verilog 1995 module paraOverride; paraDemo #(5) u_paraDemo(); endmodule // Verilog 2001 module paraOverride; paraDemo #(parameter foo=5) u_paraDemo(); endmodule
module paraDemo; parameter foo = 0; endmodule module paraDefparam; defparam u_paraDemo.foo = 5; paraDemo u_paraDemo(); endmodule
Combinational Circuits
• Combinational circuits consist of an interconnect of logic gates, configured to perform a given function
– For n inputs, there are 2n possible combinations
• Each output function is expressed in terms of the n inputs
Combinational Module `timescale 1ns/10ps // HDL Example 3.1 // Verilog model of circuit of Figure 3.35 // IEEE 1364-1995 Syntax module gateLevel(A, B, C, D, E); output D, E; input A, B, C; // Declare internal wires wire w1; /* Instantiate Gates Format is: type optName(output, input1, input2, …) */ and G1(w1, A, B); // Optional gate instance name not (E, C); // w/o opt. gate instance name or G3(D, w1, E); endmodule
Combinational Logic
• Dataflow Modeling
`timescale 1ns/10ps module simpleCircuit(A, B, C, D, E); output D, E; input A, B, C; wire w1; and G1(w1, A, B); not G2(E, C); or G3(D, w1, E); endmodule
`timescale 1ns/10ps module booleanCircuit(A, B, C, D, E); output D, E; input A, B, C; wire E, D; assign E = !C; assign D = (A && B) || E; endmodule
Blocking statements More on this later
Combinational Logic
• Conditional Operator:
– The conditional operator take three operands:
• condition ? true_expression : false_expression;
• The condition is evaluated – If the result is logic 1, the true_expression is evaluated and
used to assign a value to the left hand side of the equation
– If the result is logic 0, the false_expression is evaluated and used to assign a value to the left hand side of the equation
// Dataflow description of // two-to-one multiplexer module mux_2x1_df ( output m_out, input A, B, select ); wire m_out; assign m_out = select ? A : B; endmodule
Conditional operator can be used for tri-state buffer modeling. assign data_out = (enable) ? data_reg : 8'bz; Conditional operator can be nested assign out = sel[1] ? (sel[0] ? In3: in2) : (sel[0] ? In1 : in0);
Combinational Logic
• Half Adder – Dataflow Style
// Half Adder module halfAdder ( output wire S, C, input x, y ); assign S = x ^ y; assign C = x && y; endmodule
Combinational Logic • Full Adder
module fullAdder ( output S, C, input wire x, y, z ); wire S0, C0, C1;
halfAdder ha0( .x(x), .y(y), .S(S0), .C(C0) ); halfAdder ha1( .x(S0), .y(z), .S(S), .C(C1) ); or (C, C0, C1); endmodule
// Half Adder module halfAdder ( output wire S, C, input x, y ); assign S = x ^ y; assign C = x && y; endmodule
// Dataflow coding module full_adder (Sum, Cout, A, B, Cin); input A, B, Cin; output Sum, Cout;
wire Sum, Cout;
assign Sum = Cin ^ (A ^ B); assign Cout = Cin * (A ^ B) + A*B; endmodule
& or
Combinational Logic
• Death Adder
Combinational Logic /* module ripple_carry_4_bit_adder(Sum, C4, A, B, C0); // Verilog 1995 output [3:0] Sum; output C4; input [3:0] A, B; input C0; */ module ripple_carry_4_bit_adder (output [3:0] Sum, output C4, input [3:0] A, B, input C0); // Verilog 2001, 2005 wire C1, C2, C3; // Instantiate chain of full adders full_adder FA0(Sum[0], C1, A[0], B[0], C0), FA1(Sum[1], C2, A[1], B[1], C1), FA2(Sum[2], C3, A[2], B[2], C2), FA3(Sum[3], C4, A[3], B[3], C3); endmodule
Question: What is critical path for ripple carry adder below?
Answer: The carry value depends on all previous carries
Trivia: Charles Babbage first recognized the carry delay issue and devised anticipating carriage mechanisms for his mechanical computers IBM filed first look –ahead carry patent in 1957
Combinational Logic
// Mux with three-state output module triMux( output m_out; input A, B, select; tri m_out ); bufif1(m_out, A, select); bufif0(mout_B, select); endmodule
case/casex/casez statement
// Example 1 reg a; case (a) 1'b0 : statement1; // Executes if variable ‘a’ is 1’b0 1'b1 : statement2; // Executes if variable ‘a’ is 1’b1 1'bx : statement3; // Executes if variable ‘a’ is 1’bx 1'bz : statement4; // Executes if variable ‘a’ is 1’bz or 1’b? endcase
// Example 3 // casex treats x, z, and ? as don’t care values // Per C. Cummings, don’t use casex for synthesizable code reg a; casex (a) 1'b0 : statement1; // Executes if variable ‘a’ is 1’b0 or 1’bz or 1’bx or 1’b? 1'b1 : statement2; // Executes if variable ‘a’ is 1’b1 1'bx : statement3; // Never executes 1'bz : statement4; // Never executes endcase
// Example 2 // casez treats z and ? as don’t care values reg a; casez (a) 1'b0 : statement1; // Executes if variable ‘a’ is 1’b0 or 1’bz or 1’b? 1'b1 : statement2; // Executes if variable ‘a’ is 1’b1 1'bx : statement3; // Executes if variable ‘a’ is 1’bx 1'bz : statement4; // Never executes endcase
• The case statement can appear only within structured procedures, i.e. always, initial, function or task
• Unlike other high level languages, the Verilog case statement includes implied break statements
• Verilog case item statements must be enclosed between the keywords "begin" and "end" if more than one statement is to be executed for a selected case item
case statements
• default case: – An optional case to indicate what actions to perform if
none of the defined case items match the case expression – Good coding style to place the default last, though not
required by the Verilog LRM – If a case statement does not include a case default and if it
is not possible to find a binary case expression that matches any of the defined case items, the case statement is not "full." • Verilog does not require case statements to be “full” • If case statement not “full” and no default case, latch inferred
– Generates ELAB-311 Warning (DEFAULT branch of CASE statement cannot be reached.) during synthesis if case statement fully defined
case statements
• //synopsys “full_case”
– No change in the Verilog simulation for the case statement as Verilog comment
– Synopsys interprets the "full_case" directive to mean that if a case statement is not "full" that the outputs are "don't care's" for all unspecified case items.
– Ignored if default case is included (redundant)
– Can cause simulation/synthesis mis-match
case statements • //synopsys “parallel_case”
– A "parallel" case statement is a case statement in which it is only possible to match a case expression to one and only one case item. If it is possible to find a case expression that would match more than one case item, the matching case items are called "overlapping" case items and the case statement is not "parallel.“ • Implies an if(), else if(), else if()… structure, i.e priority
encoder
– parallel_case directs synthesis to implement parallel logic rather than a priority scheme for all case item expressions • Implies simple OR structure
parallel_case
• With the parallel_case pragma, that is equivalent to:
out <= (state[0] & in1) | (state[1] & in2) ;
• Without the parallel case pragma, extra logic is required to handle the condition when both state[0] and [1] are asserted:
out <= (state[0] & in1) | (state[1] & ! state[0] & in2) ;
// parallel_case not needed when cases not variables case (state) 4'b0001: begin end 4'b0010: begin end 4'b0100: begin end 4'b1000: begin endcase
case (1'b1) // synthesis parallel_case state[0]: out <= in1 ; state[1]: out <=in2 ; endcase
Combinational Logic
// Behavioral description of four-to-one multiplexer module mux_4x1_beh ( output reg m_out, input in_0, in_1, in_2, in_3, input [1:0] select ); always @(in_0, in_1, in_2, in_3, select) case(select) 1’d0: m_out = in_0; 1’d1: m_out = in_1; 1’d2: m_out = in_2; 1’d3: m_out = in_3; endcase endmodule
The sensitivity list consists of one or more signals. When at least one of these signals changes, the always block executes through to the end keyword.
Decision Trees Post synthesis implementation will differ based on coding style
Priority Decision Tree
Parallel Decision Tree
// Gate Level description of two-to-four decoder module decoder_2x4_gates (D, A, B, enable); output [0:3] D; input A, B; input enable; wire A_not, B_not, enable_not; not G1 (A_not, A), G2 (B_not, B), G3 (enable_not, enable); nand G1 (D[0], A_not, B_not, enable_not), G2 (D[1], A_not, B, enable_not), G3 (D[2], A, B_not, enable_not), G3 (D[3], A, B, enable_not); endmodule
// Dataflow description of two-to-four decoder module decoder_2x4_df ( output [0:3] D, input A, B, enable ); assign D[0] = !((!A) && (!B) && (!enable)), D[1] = !((!A) && B && (!enable)), D[2] = !(A && B && (!enable)), D[3] = !(A && B && (!enable)); endmodule
Combinational Logic
Combinational Logic
// Dataflow description of four-bit comparator module magCompare ( output A_lt_B, A_eq_B, A_gt_B, input [3:0] A, B ); assign A_lt_B = (A<B); assign A_GT_B = (A > B); assign A_eq_B = (A == B); endmodule