Featured post

Top 5 books to refer for a VHDL beginner

VHDL (VHSIC-HDL, Very High-Speed Integrated Circuit Hardware Description Language) is a hardware description language used in electronic des...

Sunday, 9 September 2012

UDP State Table

Formal Definition

A UDP state table defines the behavior of UDP.

Simplified Syntax

table

  comb_input comb_input ... comb_input : output;

  seq_input seq_input ... seq_input : current_state : next_state;

endtable

Description

Each row of the state table defines the behavior of the UDP for a specific input combination. Each combination of inputs can be given only one time. It is illegal to define the same combination of inputs for different outputs.

The number of input values must match the number of UDP inputs in a port declaration.

The UDP state table for combinational and sequential UDPs is different. The combinational UDPs (Example 1) contain two fields: an input field and an output field. The sequential UDPs (Example 2) contain three fields: an input, a current state, and the next state (output) field.

The input field should contain a list of values (separated by white spaces), which should match the number of UDP input ports. The order of these ports is highly important. The first input port on the UDP port list matches the first input value in each row.

The rows of the state table can contain only 0, 1, unknown (x) value, and special characters. The high-impedance (z) value cannot be specified. The special characters are provided to increase readability of a description and to make it easier (Example 3).

Symbol

Interpretation

Comments

0

Logic 0

 

1

Logic 1

 

x

Unknown value

Not permitted in output field.

b

Substitute for 0 and 1

Not permitted in output field.

?

Substitute for 0, 1, and x

Not permitted in output field.

-

No change

Permitted only in output field of sequential UDPs.

(vw)

Transition from v to w value

Permitted only in input field of sequential UDPs. v and w can be 0, 1, x, b, and ?

*

Same as (??)

Any value change on input. Permitted only in input field of sequential UDPs.

r

Same as (01)

Rising edge on input. Permitted only in input field of sequential UDPs.

f

Same as (10)

Falling edge on input. Permitted only in input field of sequential UDPs.

p

Same as (01), (0x), (x1)

Positive edge on input. Permitted only in input field of sequential UDPs.

n

Same as (10), (1x), (x0)

Negative edge on input. Permitted only in input field of sequential UDPs.

Table 25: Summary of symbols

If some combinations of input signal values are not specified in a UDP state tables then the output value will be unknown (x).

Only one transition can appear in each row of sequential UDPs.

Examples

Example 1

primitive mux (o, i3, i2, i1, i0, a1, a0);

output o;
input i3, i2, i1, i0, a1, a0;
table
// i3 i2 i1 i0 a1 a0 : o;
0 ? ? ? 1 1 : 0;
1 ? ? ? 1 1 : 1;
? 0 ? ? 1 0 : 0;
? 1 ? ? 1 0 : 1;
? ? 0 ? 0 1 : 0;
? ? 1 ? 0 1 : 1;
? ? ? 0 0 0 : 0;
? ? ? 1 0 0 : 1;
endtable
endprimitive

If any address bit (a1, a0) is unknown, then the output value will be unknown (because there is no row which describes the output value for this combination of address signals).

If a1 = 0 and a0 = 0 then the signal from input i0 is driven to output (value of others inputs does not matter).

If a1 = 0 and a0 = 1 then signal from input i1 is driven to the output.

If a1 = 1 and a0 = 0 then signal from input i2 is driven to the output.

If a1 = 1 and a0 = 1 then signal from input i3 is driven to the output.

Example 2

primitive special_d_ff (q, clk, m, d, rst, set);
output q;
reg q;
input clk, m, d, rst, set;
table
// clk m d rst set : current : next;
// positive edge on clk and normal mode (m = 0)
(01) 0 0 0 0 : ? : 0 ; // line 1
(0x) 0 0 0 0 : ? : 0 ; // line 2
(x1) 0 0 0 0 : ? : 0 ; // line 3
(01) 0 1 0 0 : ? : 1 ; // line 4
(0x) 0 1 0 0 : ? : 1 ; // line 5
(x1) 0 1 0 0 : ? : 1 ; // line 6
// positive edge on clk and negation mode (m = 1)
p 1 ? 0 0 : 0 : 1 ; // line 7
p 1 ? 0 0 : 1 : 0 ; // line 8
// negative edge on clk and any mode (m = 0 or m = 1)
n ? ? 0 0 : ? : - ; // line 9
// reset
? ? ? 1 ? : ? : 0 ; // line 10
// preset
? ? ? 0 1 : ? : 1 ; // line 11
// any changes on inputs with no changes on clk
? * ? ? ? : ? : - ; // line 12
? ? * ? ? : ? : - ; // line 13
? ? ? * ? : ? : - ; // line 14
? ? ? ? * : ? : - ; // line 15
endtable
endprimitive

This is 'd' flip-flop with an additional input, which can convert it into a modulo 2 counter.

If m = 0 then this UDP works as a normal 'd' flip-flop (lines 1-6), but if m = 1 then it negates its current value (lines 7 and 8). If any falling edge occurs on the clk input, then it will not change the output (line 9). If rst is 1, then the output will go to 0 (line 10). If the rst is 0 and set is 1, then the output will go to 1 (line 11 - it means that rst has higher priority than set).

Any changes on the data input will not cause any changes on output (lines 12-15).

Example 3

primitive circuit_1 (o, i1, i2, i3);
output o;
input i1, i2, i3;
table
0 0 0 : 1 ;
0 0 1 : 1 ;
0 0 x : 1 ;
0 1 0 : 1 ;
0 1 1 : 1 ;
0 1 x : 1 ;
1 0 0 : 0 ;
1 0 1 : 0 ;
1 0 x : 0 ;
1 1 0 : 1 ;
1 1 1 : 1 ;
1 1 x : 1 ;
x 0 0 : 0 ;
x 0 1 : 0 ;
x 0 x : 0 ;
x 1 0 : 0 ;
x 1 1 : 0 ;
x 1 x : 0 ;
endtable
endprimitive
primitive circuit_2 (o, i1, i2, i3);
output o;
input i1, i2, i3;
table
0 ? ? : 1 ;
1 0 ? : 0 ;
1 1 ? : 1 ;
x b ? : 0 ;
endtable
endprimitive

'Circuit_1' and 'circit_2' are the same circuit, but the behavior of the 'circuit_1' was specified without special characters.

Important Notes

  • Each row of sequential UDPs can contain only one transition.
  • Special characters can make the UDP state table easier to read and write.
  • Any undefined combination of inputs will set the output to x value.

UDP Instantiation

Formal Definition

The UDP instantiation provides a means of using UDP in modules.

Simplified Syntax

udp_name (strengths) #(delays) instance_name[range] (list of ports);

Description

UDPs can be instantiated only within modules.

The name of an instance is optional (Example 1). A UDP instantiation can contain strength and delays declarations (Example 2). UDPs do not support high-impedance (z) values, therefore only two delays are permitted. Signals connected to input ports can be any net or reg data type. Only net data type variables can be connected to the output port. The strength declaration can contain only drive strength.

It is possible to specify an array of UDP instances by using a range (Example 3).

Examples

Example 1

primitive d_ff (q, clk, d);
...
endprimitive
d_ff (q, clk, d);

The name of an instance is optional.

Example 2

d_ff (weak1, strong0) #5 d1 (q, clk, d);

UDP instance with strength and delay declaration.

Example 3

wire [3:0] q;
reg [3:0] d;
reg clk;
d_ff flips[3:0] (q, clk, d);

Important Notes

· UDP instantiation can contain up to two delay values.


UDP Declaration

Formal Definition

User Defined Primitives (UDP) provide a means of expanding a set of built-in primitives.

Simplified Syntax

primitive udp_name ( port_list );

output output_port;

input list_of_imputs;

initial output_port = value;

table

  combinational_input_list : output_value;

  sequential_input_list : current_state : next_state;

endtable

endprimitive

Description

User Defined Primitives can describe both combinational (Example 1) and sequential (Example 2) circuits. The behavioral description is provided as a truth table.

The UDP declaration starts with the keyword primitive and ends with the keyword endprimitive. A port list, an output port declaration and input ports declaration are similar to their equivalents in a module declaration.

Port list

The port list contains a comma-separated list of primitive ports. There can be only one output port and several input ports. The inout ports are illegal. The first port on the list should be the output port. There are some restrictions concerning the number of input ports. The combinational UDPs list of ports should not contain more than 10 inputs, and the sequential UDPs port list should not contain more than 9 inputs. If the port list contains more inputs, then a warning will be issued. These restrictions are caused by illegibility of written UDPs.

Port declaration

Input and output port declarations should match the port list of the UDP they are enclosed in. If the described UDP is sequential, then reg declaration for output port should be provided. All ports of the UDP should be of scalar type (1-bit wide). Vectors are illegal.

Initial statement

Sequential UDPs can contain an initial statement for an output port. This statement begins with the keyword initial, followed by an assignment to the output port. Assigned values should be 1-bit wide and there must not be any delays.

State table

The state table starts with the keyword table and ends with the keyword endtable. The state tables for combinational and sequential UDPs are different. The state table is comprised of rows each of which ended with a the semicolon. Table row describes the behavior of UDP for a particular combination of inputs. The combinational UDPs have two fields separated by a colon. One field is for the inputs and one for the outputs. The sequential UDPs have three fields: one for the inputs, one for the current output state, and one for the next output state. If any combination of input signals, is not explicitly specified in the UDP declaration, the output value will be unknown (x). A particular combination of inputs can be specified only one time.

Examples

Example 1

primitive and_gate (o, in1, in2);
output o;
input in1, in2;
table
  // in1 in2 : o
  0 0 : 0;
  0 1 : 0;
  1 0 : 0;
  1 1 : 1;
endtable
endprimitive

Example of simple combinational UDP based on the and gate truth table.

Example 2

primitive d_ff (q, d, clk);
output q;
reg q;
input d, clk;
table
  // d clk : q : q+
  0 p : ? : 0;
  1 p : ? : 1;
  ? n : ? : -;
endtable
endprimitive

Example of sequential UDP based on a D flip-flop.

Important Notes

· UDP can have only one output.

· Inout ports are illegal.

· Combinational UDP should not have more than 10 inputs.

· Sequential UDP should not have more than 9 inputs.

· Vector declaration for UDP ports is illegal.


Timing Check Tasks


Formal Definition

Timing Check Tasks are for verification of timing properties of designs and for reporting timing violations.

Simplified Syntax

$setup (data_event, reference_event, limit[, notifier]) ;

$skew (reference_event, data_event, limit[,notifier]) ;

$hold (reference_event, data_event, limit[,notifier]) ;

$recovery (reference_event, data_event, limit, [notifier]) ;

$setuphold (reference_event, data_event, setup_limit, hold_limit, [notifier]) ;

$width (reference_event, limit, threshold [,notifier]) ;

$period (reference_event, limit[,notifier]) ;

$nochange (reference_event, data_event, start_edge_offset, end_edge_offset [,notifier]) ;

Description

Timing check tasks are invoked every time critical events occur within given time limits. See the table below with descriptions of all arguments:

Argument

Description

Type

Reference_event

The transition at a control signal that establishes the reference time for tracking timing violations on the data_event

Module input or inout that is scalar or vector net

Data_event

The signal change that initiates the timing check and is monitored for violations.

Module input or inout that is scalar or vector net

Limit

A time limit used to detect timing violations on the data_event

Constant expression or specparam

Threshold

The largest pulse width that is ignored by the timing check $width

Constant expression or specparam

Setup_limit

A time limit used to detect timing violations on the data_event for $setup.

Constant expression or specparam

Hold_limit

A time limit used to detect timing violations on the data_event for $hold.

Constant expression or specparam

Notifier

An optional argument that "notifies" the simulator when a timing violation occurs

Register

$setup checks setup time. When modeling synchronous circuits, flip-flops need time to force a correct value. Data cannot change within the setup time because flip-flops cannot detect the new value. If data changes within a given time limit, $setup reports a timing violation. If a data event and reference event occur at the same time there is no violation. The$setup first checks timing data then records a new data value. The formula to report a timing violation is as shown below:

(time of reference event) - (time of data event) < limit

Notice that the limit argument has to be a positive number.

$skew checks the following:

(time of data event) - (time of reference event) > limit

$skew can be used to check synchronicity of clocks inside a circuit. If different clocks are used in a design and are synchronized, $skew will report a timing violation when the active edge of one of them occurs outside the time limit allowed for the other clock to occur.

When the data event and the reference event occur at the same time, $skew will not report a timing violation.

$hold will report a timing violation if the following formula is true:

(time of data event) - (time of reference event) < limit

$hold simply checks that data is stable in the specified interval of time after the edge of the clock. In flip-flops, data should remain stable for a given time after the active edge of the clock to allow for propagation of data.

Also, a violation will be reported if the data event and the reference event occur at the same time.

$recovery responds when the following formula is true:

(time of data event) - (time of reference event) < limit

The 'reference_event' must be an edge-triggered event: posedge or negedge. A timing violation occurs if the time interval between an edge-triggered reference event and a data event exceeds the 'limit'. If a reference event and data event occur at the same time, a timing violation is reported. If a 'reference_event' argument is specified without edge specification, an error is reported.

$setuphold checks setup and hold timing violations. This task combines the functionality of $setup and $hold in one task. The following formula has to be applied:

setup_limit + hold_limit > 0

'reference_event' have to be one of the following:

  1. $hold lower bound event
  2. $setup upper bound event

'data_event' have to be one of the following:

  1. $hold upper bound event
  2. $setup lower bound event

In $width both limit and threshold have to be positive numbers. The 'reference_event' must be the edge specification, otherwise an error will be reported. The 'data_event' is not specified directly, but by default means 'reference_event' with opposite edge. A timing violation occurs with the following formula:

threshold < (time of data event) - (time of reference event) < limit

$width reports when width of the active-edge is too small. In FF case it is very important to ensure that the width of an active-edge is sufficient and FF will work properly.

The $period checks that a period of signal is sufficiently long. The reference_event has to be an edge specification. The data_event is not specified directly and by default, is the same as a reference_event. The $period reports a timing violation when the following formula comes true:

(time of data event) - (time of reference event) < limit

The $nochange checks if the data signal is stable in an interval of start_edge_offset and end_edge_offset. If the signal has changed, a timing violation is reported. The reference_event argument can be posedge or negedge but the edge control specifiers are disallowed.

Examples

Example 1

module setup (data1, data2, q);
input data1, data2;
output q;
and (q, data1, data2);
specify
specparam tsetup = 7, delay = 10 ;
(data1 => q) = 10 ;
$setup(data1, posedge data2, tsetup);
endspecify
endmodule

Example 2

module two_clocks (clk1, clk2, q);
input clk1, clk2;
output q;
specify
  specparam tskew = 7;
  $skew(posedge clk1, posedge clk2, tskew);
endspecify
endmodule

Example 3

module hold (data1, data2, q);
input data1, data2;
output q;
and (q, data1, data2);
specify
specparam thold = 7, delay = 10 ;
(data1 => q) = 10 ;
$hold(posedge data2, data1, thold);
endspecify
endmodule

Example 4

module recovery (in1, out1);
input in1 ;
output out1 ;
assign out1 = in1 ? 1'b1 : 1'bz ;
specify
  specparam trecovery = 10;
  $recovery(posedge in1, out1, trecovery);
endspecify
endmodule

Example 5

module setuphold (data1, data2, q);
input data1, data2;
output q;
and (q, data1, data2);
specify
specparam tsetup = 7,
thold = 7,
delay = 10 ;
(data1 => q) = 10 ;
$setuphold(posedge data2, data1, tsetup, thold);
endspecify
endmodule

Example 6

module width (data1, data2, q);
input data1, data2;
output q;
and (q, data1, data2);
specify
specparam twidth = 10,
delay = 10 ;
(data2 => q) = 10 ;
$width(posedge data2, twidth);
endspecify
endmodule

Example 7

module dff (clk, q);
input clk;
output q;
buf (q, clk);
specify
  specparam tperiod = 100 ;
  $period(posedge clk, tperiod);
endspecify
endmodule

Example 8

module nochange (data1, data2, q);
input data1, data2;
output q;
and (q, data1, data2);
specify
specparam tstart = -5,
tend = 5 ;
$nochange(posedge data2, data1, tstart, tend);
endspecify
endmodule

Important Notes

  • All timing check system tasks should be invoked within specify blocks.

Timescale System Tasks

Formal Definition

Timescale system tasks provide a means of setting and printing timescale information.

Simplified Syntax

$printtimescale [(hierarchical_path)] ;

$timeformat [(unit_number, precision, suffix, min_width )] ;

Description

The $printtimeformat system task is used when information about time units and precision is needed. An argument is optional. When the $printtimescale system task is invoked without an argument, the time unit and precision of the current modules are displayed. If an argument is specified, then the time unit and precision of the module specified is displayed in a hierarchical path. The following format is used to display this information:

Time scale of (module) is unit / precision

The $timeformat system task has double functionality.

First, when any delays are entered interactively, it specifies the time unit. Second, it specifies the %t format specification. These format specifications are used in $display, $fdisplay, $write, $fwrite, $strobe, $fstrobe and $monitor, $fmonitor system tasks.

The first argument of $timeformat system task should be an integer.

Unit

Time

Unit

Time

0

1 s

-8

10 ns

-1

100 ms

-9

1 ns

-2

10 ms

-10

100 ps

-3

1 ms

-11

10 ps

-4

100 us

-12

1 ps

-5

10 us

-13

100 fs

-6

1 us

-14

10 fs

-7

100 ns

-15

1 fs

Default argument values are given in the following table:

Argument

Value

Unit

The smallest time precision argument of all the `timescale compiler directives in the source description

Precision

0

Suffix

Null

Minimum width

20

Examples

Example 1

`timescale 1 ns / 100 ps
module a (y, a, b);
  output y;
  input a, b;
  assign y = a & b;
endmodule
`timescale 1 s / 10 fs
module top;
  wire y, a, b;
  a u(y, a, b);
  initial $printtimescale(top.u);
endmodule

Important Notes

  • The $timeformat system task specifies the %t format specification until the next `timescale compiler directive occurs.

initial $timeformat(-9, 5, " ns", 10);
/* $timeformat [ ( n, p, suffix , min_field_width ) ] ;
units = 1 second ** (-n), n = 0->15, e.g. for n = 9, units = ns
p = digits after decimal point for %t e.g. p = 5 gives 0.00000
suffix for %t (despite timescale directive)
min_field_width is number of character positions for %t */


Tasks

Formal Definition

Tasks provide a means of splitting code into small parts. Often tasks consist of frequently used functionalities.

Simplified Syntax

task identifier;

  parameter_declaration;

  input_declaration;

  output_declaration;

  inout_declaration;

  register_declaration;

  event_declaration;

  statement;

endtask

Description

Task definition begins with the keyword task and ends with the keyword endtask. A task should be followed by a task identifier and end with a semicolon. A task can contain a declaration of parameters, input arguments, output arguments, inout arguments, registers and events (these declarations are similar to module items declaration) but they are not required. Net declaration is illegal.

A task can contain zero or more behavioral statements, e.g. case statement, if statement. A begin-end block is required for bracketing multiple statements.

The task enabling statement should be made up of a task identifier and the list of comma-separated task arguments. The list of task arguments should be enclosed in parenthesis. If the task does not contain any argument declarations, then it should be enabled by specifying its identifier followed by a semicolon (Example 2).

The list of task enabling arguments should correspond exactly to the list of task arguments. If a task argument is declared as an input, then a corresponding argument of the task enabling statement can be any expression. If a task argument is declared as an output or an inout then the corresponding argument of the task enabling statement should be one of the following items:

  • Register data types
  • Memory references
  • Concatenations of registers or memory references
  • Bit-selects and part-selects of reg, integer and time registers

Only the last assignment to an output or an inout argument is passed to the corresponding task enabling arguments. If a task has assignments to global variables, then all changes of these variables are effective immediately.

Tasks can enable others tasks (Example 3) and functions. A task may be enabled several times in a module. If one task is enabled concurrently, then all registers and events declared in that task should be static, i.e., one variable for all instances.

A task can contain time-controlling statements. A task does not return a value by its name.

Examples

Example 1

task first_task;
  parameter size = 4;
  input a;
  integer a;
  inout [size-1:0] b;
  output c;
  reg [size-1:0] d;
  event e;
begin
  d = b;
  c = |d;
  b = ~b;
if (!a) -> e;
  end
endtask

This is an example of using parameters, input arguments, inout arguments, output arguments, registers and events within tasks. The 'a' argument is declared as an input and as an integer data type.

'First_task' can be enabled as follows:

integer x;
reg a, b, y;
reg [3:0] z;
reg [7:0] w;
first_task(x, z, y);
first_task(x, w[7:4], w[1]);
first_task(1, {a, b, w[3], x[0]}, y);

When being enabled, the first argument of the 'first_task' should be an integer data type expression, the second should be a 4-bit register expression, and the last argument should be 1-bit register expression.

Example 2

reg a, b;
task my_task; // task definition
begin
  a = 1'b1;
  b = 1'bx;
end
endtask
my_task; // task enabling

If 'my_task' is enabled then it will change the value of global variables 'a' and 'b'.

Example 3

task negation;
  inout data;
  data = ~data;
endtask
task my_nor;
  input a, b;
  output c;
  begin
  negation(a);
  negation(b);
  c = a & b;
  end
endtask

The 'my_nor' task enables negation tasks.

Important Notes

  • A task can contain time-controlling statements
  • A task does not return any value by its name

Structured Procedures

Formal Definition

Structured procedures provide a means of modeling blocks of procedural statements.

Simplified Syntax

always statement

initial statement

function

task

Description

Functions and tasks are described in the section: Task and Functions.

The initial statement (Example 1) is executed only during a simulation run. The always procedural block statement (Example 2) is executed continuously during simulation, i.e. when the flow of program reaches the last statement in the block, the flow continues with the first statement in the block.

The always statement should contain at least one procedural timing control because otherwise it may hang the simulation.

Module definition can contain more than one initial or always statement.

Care must be taken when same reg type variables are used in multiple procedural blocks, initial or always. This is because these blocks run in parallel and changing or assigning to one variable affects the same variable in another parallel block.

Examples

Example 1

initial out = 1'b0;
initial begin
  #10;
  a = 1'b0;
  #10;
  a = 1'b1;
  #10;
  a = 1'bz;
end

Example 2

always @(posedge clk)
q = d;
always #10 clk = ~clk;
initial clk = 0;
initial repeat(20)#\10 clk=~clk;

The first initial statement sets clk to 0 at time 0, and the second initial block toggles the clk 20 times every 10 time units.

Important Notes

· The always statement should contain at least one procedural timing control.