- •Contents
- •Instantiating a Module
- •Specifying Time Units
- •Resetting Compiler Directives
- •Declaring Nets
- •Declaring Registers
- •Example: Declaring registers
- •Declaring and Using Integers
- •Declaring and Using Reals
- •Declaring and Using Strings
- •Declaring Vectors
- •Declaring Arrays
- •Declaring and Loading Memories
- •Using Operators
- •Modeling Your Hardware (Gate-Level)
- •Instantiating Gates
- •Specifying Drive Strengths
- •Specifying Gate Delays
- •Assigning Values to Registers (Procedural Assignments)
- •Specifying Intra-Assignment Timing Controls
- •Disabling Named Blocks and Tasks
- •Controlling Timing with Delays
- •Controlling Timing with Event Controls
- •Declaring and Triggering Named Events
- •Overriding Procedural Assignments on Registers
Verilog-XL Modeling Style Guide |
|
|
Modeling Your Hardware |
|
|
Example: Declaring arays |
|
module test_fixture; |
// See Step 1 |
integer index; |
|
time trigger_time [0:99]; |
// See Step 2 |
reg q; |
|
... |
|
initial index=0; |
|
always @(posedge q) begin
trigger_time[index] = $time; // See Step 3 index = index + 1;
end
...
endmodule // text_fixture
1.In this example, the integer index is a single variable to be used as a counter and index into an array.
2.Array index declarations appear after the variable name and take the form
[start_index:end_index].
There are 100 time variables, called trigger_time[0], trigger_time[1] ...
trigger_time[99].
3.Access the individual elements of an array by following the array name with an element index: array_name[index_expr]. Unlike vectors, you cannot operate on the entire array as a single entity.
Each time q has a positive edge, Verilog-XL stores the current simulation time in one of the trigger_time array variables. Verilog-XL then increments index
Declaring and Loading Memories
You can declare memories by combining vector and array specifications on registers (reg).
You access the individual elements, or “words”, of the memory by specifying a single array index—you cannot operate on the entire memory as a single entity. You can load a memory either by manually assigning a value to each word, or by using system tasks to read memory values from files or strings.
The example shows how you declare a 256x16-bit memory. It also shows how to load values into the memory by direct assignment and by reading a memory file. “See Step n” comments in the example correspond to descriptive steps that follow the example.
Example: Declaring and loading memories
module memory;
reg [15:0] mem [255:0]; // See Step 1
...
January 2001 |
20 |
Product Version 3.2 |
Verilog-XL Modeling Style Guide
Modeling Your Hardware
task memory_clear; integer i;
for (i=0;i<255;i=i+1)
mem[i] = 0; // See Step 2 endtask // memory_clear
task memory_load;
$readmemh("mem.dat", mem); // See Step 3 endtask // memory_load
...
endmodule // memory
/* mem.dat -- intializes the 256x16 memory for the memory module */
//See Step 4
1122
F447
de00 ZZZZ xx11 45_ee @FE 0000 0000
//End of Memory Pattern
1.Declare a memory by specifying an array of reg variables. Without a vector specification, the memory consists of 1-bit words (n x 1 memory). A vector specification declares the number of bits in each word, while the array specifies the number of words.
This memory is a 256 (word) x 16 (bit) memory.
2.Access the individual words of a memory as you access the individual elements of an array; follow the memory name with an index. You cannot operate on the entire memory as a single entity.
The memory_clear task uses a for loop to initialize each word in the memory to 0 (clears the memory).
3.Load the values for a memory from a file with the $readmemh (hex data) or
$readmemb (binary data) system tasks. The first argument is the file name. The second is the name of the memory. Optional third and fourth arguments specify the start and
finish address for the memory load. You can also load memories with values specified as Verilog HDL strings with the $sreadmemb and $sreadmemh system tasks.
Verilog-XL loads the mem memory with the contents of the mem.dat file.
4.Create memory files as you would any ASCII file. The file must only contain white space, comments (both // and /* */), the binary or hexadecimal values that Verilog-XL loads into the memory, and address specifications. Do not specify length or base formats. Separate each value with either white space or a comment. Verilog-XL loads values starting at the beginning of the memory (left-hand address of the memory declaration) unless you specify a starting-address with the $readmem system task or specify addresses within the memory file.
January 2001 |
21 |
Product Version 3.2 |
Verilog-XL Modeling Style Guide
Modeling Your Hardware
5.You can specify unknown (X), high impedence (Z), and the underscore formatting character (_) which breaks up long numbers for better readability.
6.You can specify addresses within the memory file by using the “at” sign (@) followed by a hexadecimal address specification. Verilog-XL loads subsequent values into memory starting from this memory address. If you specify a starting-address with the $readmem system task, Verilog-XL ignores addresses specified in the memory file. Verilog-XL loads the last two memory addresses with 0000.
Defining and Overriding Parameters
You can specify a parameter to define constants within a local module. To override parameters in one module from another module, you can use a defparam statement or module instance parameter value assignments (#). Parameters differ from macros (‘define, +define+) in that macros are global (affect all modules), and parameters are local to a module.
The example shows how you can use parameters within a module and modify values from another module.
“See Step n” comments in the example correspond to descriptive steps that follow the example.
Example: Defining and overriding parameters
module MYAND (result, a, b); |
// See Step 1 |
parameter size=8, delay=6 |
|
output [size-1:0] result; |
// See Step 2 |
input [size-1:0] a, b; |
|
wire [size-1:0] #delay result = a & b; |
|
endmodule // MYAND |
|
module MYOR (result, a, b); |
// See Step 3 |
parameter size=8, delay=6; |
|
output [size-1:0] result; |
|
input [size-1:0] a, b; |
|
wire [size-1:0] #delay result = a | b; |
|
endmodule // MYOR |
|
module my_design; |
|
reg[7:0] in1, in2; |
|
reg [3:0] in3, in4; |
|
wire [7:0] q1,q2; |
|
wire [3:0] q3,q4; |
|
MYAND and1 (q1, in1, in2); |
|
// See Step 4 |
|
MYAND #(10,5) and2 (q3, in3, in4); // override |
|||
MYOR or1 (q2, in1, in2), or2 (q4, in3, in4); |
|
|
|
defparam |
|
// |
See Step 5 |
and1.delay = 3, |
// override MYAND |
delay spec |
|
and2.delay = 5, |
// override MYAND |
delay spe |
January 2001 |
22 |
Product Version 3.2 |
|
|
Verilog-XL Modeling Style Guide |
|
|
Modeling Your Hardware |
|
|
|
and2.size = 4, |
// override MYAND size spec |
|
or2.size = 4; |
// override MYOR size spec |
|
initial |
|
|
begin |
|
|
in1 = |
8’b11001100; |
|
in2 = |
8’b11110000; |
|
in3 = |
4’b1100; |
|
in4 = |
4’b1111; |
|
end |
|
|
... |
|
|
endmodule |
// my_design |
|
1.Define parameters with the parameter keyword followed by one or more assignments.
This module has two parameters describing the size of the registers (8) and the continuous assignment delay (6).
2.Use parameters anywhere in the module in which the parameters are defined. Unlike macros, which must be preceded by a back tick ( ‘ ), you do not need a character indicating that the variable is a parameter.
The size parameter is used to define the register and wire sizes, and the delay parameter appears in the continuous assignment.
3.Because parameters are local to a module, you can use the same parameter names in other modules that are part of the same design. This differs from macro behavior.
Both the MYAND and MYOR modules each have different parameters of the same name called size and delay.
4.Override the parameters of a module instance by placement of new values. Parameters cannot be skipped; all of the parameters must be respecified.
The top-level module instantiates two MYAND modules two MYOR modules. In the second MYAND instantiation, the value 10 overrides the size parameter, and the value 5 overrides the delay parameter.
5.Override the parameters of a module instance with the defparam statement. You must provide the full hierarchical name to access the parameter. If you do not explicitly override a parameter, Verilog-XL uses the parameter values as defined in the original module definition.
Using Operators
You can create simple or complex expressions using Verilog HDL operators. Verilog HDL operators fall into the following classes: arithmetic, relational, logical, bitwise, reduction, shift, conditional, and concatenation. Operators accept one, two, or three operands depending on whether the operator is unary, binary, or ternary, respectively.
January 2001 |
23 |
Product Version 3.2 |
Verilog-XL Modeling Style Guide
Modeling Your Hardware
The following example shows several types of operations. “See Step n” comments in the example correspond to descriptive steps that follow the example.
Example: Using Operators
module operators; |
|
|
parameter |
param = 4; |
|
integer int, result; |
|
|
reg [3:0] |
reg1, reg2, reg3; |
|
reg [7:0] |
big_reg; |
|
initial begin |
|
|
int = |
5; reg1 = 4’b1001; reg2 = 4’b1100; |
|
end |
|
|
initial begin |
|
|
// 1. |
Arithmetic operation |
|
result = param + int + 3; |
// result = 12 |
|
// 2. |
Relational operation |
|
result = param == integer; |
// result = 0 |
|
// 3. |
Logical operation |
|
result = param && reg2; |
// result = 1 |
|
// 4. |
Bitwise operation |
|
reg3 = reg1 & reg2; |
// reg3 = 4’b1000 |
|
// 5. |
Reduction operation |
|
reg3 = & reg1; |
// reg3 = 4’b0000 |
|
// 6. |
Conditional operation |
|
reg3 = param ? 4’b1111 : 4’b0000; |
// reg3 = 4’b1111 |
|
// 7. |
Concatenation operation |
|
big_reg = {reg1, reg2}; |
// big_reg = 8’b10011100 |
|
// 8. |
Shift operation |
|
big_reg = big_reg >> param; |
// big_reg = 4’b00001001 |
|
/* 9. |
Use parentheses to override operator precedence |
|
|
or to make complex expressions more readable. */ |
|
result = param + (reg1 && reg2); |
// result = 5 |
|
end |
|
|
endmodule |
// operators |
|
Performing Timing Checks
You can verify that critical events within your design occur within given time limits by performing timing checks. Verilog-XL provides system tasks to perform different types of timing checks. In your model, you must place these system tasks in specify blocks.
The following example shows a gate-level flip-flop module with setup and hold timing checks. A test fixture provides stimulus that violates the setup and hold constraints. A run of VerilogXL illustrates the error messages created for timing violations. “See Step n” comments in the example correspond to descriptive steps that follow the example.
Example: Performing Timing Checks
module flop (data,clock,clear,q,qb); input data, clock, clear;
output q, qb;
nand #10 nd1 (a, data, clock, clear), nd2 (b, ndata, clock),
nd4 (d, c, b, clear), nd5 (e, c, nclock),
January 2001 |
24 |
Product Version 3.2 |
Verilog-XL Modeling Style Guide
Modeling Your Hardware
|
nd6 (f, d, nclock), |
|
|
nd8 (qb, q, f, clear); |
|
nand #9 nd3 (c, a, d), |
|
|
|
nd7 (q, e, qb); |
|
not #10 iv1 (ndata, data), |
|
|
specify |
iv2 (nclock, clock); |
// See Step 1 |
|
||
|
specparam tSU = 10, tHD = 2; |
// See Step 2 |
|
$setuphold(posedge clock &&& clear, |
// See Step 3 |
|
data, tSU, tHD); |
// See Step 4 |
endspecify |
||
endmodule // flop |
// See Step 5 |
|
module time_flop; |
||
reg clk, clr, data; |
|
|
wire q, qb; |
|
|
flop f1 |
(data, clk, clr, q, qb); |
|
always #50 clk = ~clk; |
|
|
initial |
|
|
begin |
clr = 1; clk = 0; data = 0; |
|
|
|
|
#100 |
data = 1; |
// See Step 6 |
#49 |
data = 0; |
|
#102 |
data = 1; |
// See Step 7 |
#49 |
clr = 0; |
// See Step 8 |
#49 |
data = 0; |
|
#100 |
$finish; |
|
end |
|
|
endmodule // time_flop
// See Step 9
% verilog time_flop.v flop.v
...
Compiling source file "time_flop.v" Compiling source file "flop.v" Highest level modules:
time_flop
"flop.v", 20: Timing violation in time_flop.f1
$setup( data:149, posedge clock &&& clear:150, 10 ); "flop.v", 20: Timing violation in time_flop.f1
$hold( posedge clock &&& clear:250, data:251, 2 ); L18 "time_flop.v": $finish at simulation time 451
69 simulation events + 61 accelerated events + 42 timing check events CPU time: 1.3 secs to compile + 0.2 secs to link + 0.1 secs in simulation
1.Create a specify block. All timing checks must be in a specify block.
2.Use specparam to assign parameter names to timing values. Doing so lets you easily change these values if they appear in many places.
This example defines two timing constraints: setup time (tSU) and hold time (tHD). The names are arbitrary.
3.Use any combination of timing-check system tasks.
The $setuphold system task provides a quick way for specifying the $setup and $hold system tasks. The data signal must be stable 10 (tSU) units before and 2 (tHD)
January 2001 |
25 |
Product Version 3.2 |
Verilog-XL Modeling Style Guide
Modeling Your Hardware
units after the positive edge of clock (only when clear is not active). &&&
signalname means that the timing check is performed only when the signal is true.
4.End the specify block with the endspecify keyword.
5.Create a test fixture to verify that the timing checks you defined in your model work as expected.
The file test_flop.v instantiates a single flop, defines a clock cycle of 100 time units, and applies a stimulus that violates the setup and hold constraints verifying that the timing checks work as expected.
6.Specify an input change that violates the setup requirement.
In this case, data changes 1 time unit before the positive edge of the clock, which violates the10-unit setup constraint set in the specparam.
7.Specify an input change that violates the hold requirement.
In this case, data changes 1 time unit after the positive edge of the clock, which violates the 2-unit hold constraint.
This change of data would violate the setup constraint except that clear is currently enabled, so Verilog-XL ignores the violation.
8.Check that your $setuphold reference signal works as expected.
This change of data would violate the setup constraint except that clr is currently enabled, so Verilog-XL ignores the violation.
9.Invoke Verilog-XL on your test fixture and model and confirm that you have the $setuphold violations you expected. If you invoke Verilog-XL with the
+notimingchecks command-line option, Verilog-XL ignores all timing checks. There is one setup violation and one hold violation, as expected.
Defining Module Path Delays
You can define delays between inputs and outputs of your module, called module path delays. You typically use either distributed (#) or path delays—not both. However, Verilog-XL can handle both types of delays for a single module and chooses the larger delays.
The following example shows how you define module path delays and define a timing check based on those delays.
“See Step n” comments in the example correspond to descriptive steps that follow the example.
January 2001 |
26 |
Product Version 3.2 |
|
Verilog-XL Modeling Style Guide |
|
|
Modeling Your Hardware |
|
|
|
|
Example: Defining module path delays |
|
|
‘delay_mode_path |
// See Step 1 |
|
module flop |
(data, clock, clear, q, qb); |
|
input data, |
clock, clear; |
|
output q, qb; |
|
|
nand |
nd1 (a, data, clock, clear), |
|
|
nd2 (b, ndata, clock), |
|
|
nd4 (d, c, b, clear), |
|
|
nd5 (e, c, nclock), |
|
|
nd6 (f, d, nclock), |
|
|
nd8 (qb, q, f, clear); |
|
nand |
nd3 (c, a, d), |
|
|
nd7 (q, e, qb); |
|
not |
iv1 (ndata, data), |
|
specify |
iv2 (nclock, clock); |
// See Step 2 |
|
||
specparam tSU = 10, tHD = 2; |
// See Step 3 |
|
specparam tRise_clk_q = 4:5:6, |
|
|
|
tFall_clk_q = 6:7:8; |
|
specparam |
tRise_clr = 3:4:5, |
|
|
|
|
|
tFall_clr = 4:5:6; |
|
|
(clock |
=> |
q) = (tRise_clk_q, |
tFall_clk_q); |
// See Step 4 |
(clock |
=> |
qb) = (tRise_clk_q+1, tFall_clk_q+1); |
||
(clear |
*> |
q, qb) = (tRise_clr, tFall_clr); |
// See Step 5 |
|
// See Step 6 |
|
|
|
|
$setuphold(posedge clock &&& |
clear,data, tSU, |
tHD); |
||
endspecify |
|
|
|
// See Step 7 |
endmodule // flop |
|
|
1.By default, Verilog-XL monitors both path and distributed delays and chooses the larger. To explicitly select path delay mode, use either the ‘delay_mode_path compiler directive in a design, or the +delay_mode_path plus option on the command line.
2.Begin a specify block with the specify keyword. Module path delays must be defined in a specify block.
3.Use specparams to assign names to timing and path delay values. Doing so lets you change these values easily if they appear in many places. The names are arbitrary. As with distributed delays, you can specify single or min:typ:max delays.
This example defines setup and hold timing constraint specparams, as well as rise and fall time parameters for clk and clr.
4.Define your module paths and assign them path delays. The path source must be an input net and the path destination must be an output or inout net. You can define bit-to-bit (parallel) connections with the => operator and bit-to-vector connections with the *> operator.
These statements define rise and fall delays for the paths from clock to q.
5.You can also use *> to define multiple paths in a single statement.
The rise and fall times for the paths from clear to both q and qb are defined in the same statement.
January 2001 |
27 |
Product Version 3.2 |
Verilog-XL Modeling Style Guide
Modeling Your Hardware
6.Use any combination of timing-check system tasks.
The $setuphold system task provides a quick way for specifying the $setup and $hold system tasks. The data signal must be stable 10 (tSU) units before and 2 (tHD) units after the positive edge of the clock (only when clear is not active).
7.End a specify block with the endspecify keyword.
January 2001 |
28 |
Product Version 3.2 |