11.13 Other Verilog FeaturesThis section covers some of the more advanced Verilog features. System tasks and functions are defined as part of the IEEE Verilog standard [Verilog LRM14]. 11.13.1 Display TasksThe following code illustrates the display system tasks [Verilog LRM 14.1]:
module test_display; // display system tasks:
initial begin ("string, variables, or expression");
/* format specifications work like printf in C:
%d=decimal %b=binary %s=string %h=hex %o=octal
%c=character %m=hierarchical name %v=strength %t=time format
%e=scientific %f=decimal %g=shortest
examples: %d uses default width %0d uses minimum width
%7.3g uses 7 spaces with 3 digits after decimal point */
// , , print in b, h, o formats
// , , also have b, h, o versions
("write"); // as , but without newline at end of line
("strobe"); // as , values at end of simulation cycle
(v); // disp. @change of v (except v= ,,)
; ; // toggle monitor mode on/off
end endmodule
11.13.2 File I/O TasksThe following example illustrates the file I/O system tasks [Verilog LRM 14.2]:
module file_1; integer f1, ch; initial begin f1 = ("f1.out");
if(f1==0) (2); if(f1==2)("f1 open");
ch = f1|1; (ch,"Hello"); (f1); end endmodule
> vlog file_1.v
> vsim -c file_1
# Loading work.file_1
VSIM 1> run 10
# f1 open
# Hello
VSIM 2> q
> more f1.out
Hello
>
The The file I/O tasks
mem.dat
@2 1010_1111 @4 0101_1111 1010_1111 // @address in hex
x1x1_zzzz 1111_0000 /* x or z is OK */
module load; reg [7:0] mem[0:7]; integer i; initial begin
("mem.dat", mem, 1, 6); // start_address=1, end_address=6
for (i= 0; i<8; i=i+1) ("mem[%0d] %b", i, mem[i]);
end endmodule
> vsim -c load
# Loading work.load
VSIM 1> run 10
# ** Warning: (memory mem) file mem.dat line 2:
# More patterns than index range (hex 1:6)
# Time: 0 ns Iteration: 0 Instance:/
# mem[0] xxxxxxxx
# mem[1] xxxxxxxx
# mem[2] 10101111
# mem[3] xxxxxxxx
# mem[4] 01011111
# mem[5] 10101111
# mem[6] x1x1zzzz
# mem[7] xxxxxxxx
VSIM 2> q
>
11.13.3 Timescale, Simulation, and Timing-Check TasksThere are two timescale
tasks, // timescale tasks: module a; initial (b.c1); endmodule module b; c c1 (); endmodule `timescale 10 ns / 1 fs module c_dat; endmodule `timescale 1 ms / 1 ns module Ttime; initial (-9, 5, " ns", 10); endmodule /* [ ( 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 */ The simulation control
tasks are and module test_simulation_control; // simulation control system tasks: initial begin ; // enter interactive mode (default parameter 1) (2); // graceful exit with optional parameter as follows: // 0 = nothing 1 = time and location 2 = time, location, and statistics end endmodule The timing-check tasks [Verilog LRM 14.5] are used in specify blocks. The following code and comments illustrate the definitions and use of timing-check system tasks. The arguments to the tasks are defined and explained in Table 11.11.
module timing_checks (data, clock, clock_1,clock_2); input data,clock,clock_1,clock_2; reg tSU,tH,tHIGH,tP,tSK,tR; specify // timing check system tasks: /* (data_event, reference_event, limit [, notifier]); violation = (T_reference_event)-(T_data_event) < limit */ (data, posedge clock, tSU); /* (reference_event, data_event, limit [, notifier]); violation = (time_of_data_event)-(time_of_reference_event) < limit */ (posedge clock, data, tH); /* (reference_event, data_event, setup_limit, hold_limit [, notifier]); parameter_restriction = setup_limit + hold_limit > 0 */ (posedge clock, data, tSU, tH); /* (reference_event, limit, threshold [, notifier]); violation = threshold < (T_data_event) - (T_reference_event) < limit reference_event = edge data_event = opposite_edge_of_reference_event */ (posedge clock, tHIGH); /* (reference_event, limit [, notifier]); violation = (T_data_event) - (T_reference_event) < limit reference_event = edge data_event = same_edge_of_reference event */ (posedge clock, tP); /* (reference_event, data_event, limit [, notifier]); violation = (T_data_event) - (T_reference_event) > limit */ (posedge clock_1, posedge clock_2, tSK); /* (reference_event, data_event, limit, [, notifier]); violation = (T_data_event) - (T_reference_event) < limit */ (posedge clock, posedge clock_2, tR); /* (reference_event, data_event, start_edge_offset, end_edge_offset [, notifier]); reference_event = posedge | negedge violation = change while reference high (posedge)/low (negedge) +ve start_edge_offset moves start of window later +ve end_edge_offset moves end of window later */ (posedge clock, data, 0, 0); endspecify endmodule You can use edge specifiers as parameters for the timing-check events (except for the reference event in ):
edge_control_specifier ::= edge [edge_descriptor {, edge_descriptor}]
edge_descriptor ::= 01 | 0x | 10 | 1x | x0 | x1
For example, Here is a D flip-flop model that uses timing checks and a notifier register. The register, notifier, is changed when a timing-check task detects a violation and the last entry in the table then sets the flip-flop output to unknown. primitive dff_udp(q, clock, data, notifier); output q; reg q; input clock, data, notifier; table // clock data notifier:state: q r 0 ? : ? : 0 ; r 1 ? : ? : 1 ; n ? ? : ? : - ; ? * ? : ? : - ; ? ? * : ? : x ; endtable // notifier endprimitive `timescale 100 fs / 1 fs module dff(q, clock, data); output q; input clock, data; reg notifier; dff_udp(q1, clock, data, notifier); buf(q, q1); specify specparam tSU = 5, tH = 1, tPW = 20, tPLH = 4:5:6, tPHL = 4:5:6; (clock *> q) = (tPLH, tPHL); (data, posedge clock, tSU, notifier); // setup: data to clock (posedge clock, data, tH, notifier); // hold: clock to data (posedge clock, tPW, notifier); // clock: period endspecify endmodule 11.13.4 PLA TasksThe PLA modeling
tasks model two-level logic [Verilog LRM 14.6]. As an example, the following
b1 = a1 & a2; b2 = a3 & a4 & a5 ; b3 = a5 & a6 & a7; The following module loads
a PLA model for the equations above (in AND logic) using the array format
(the array format allows only
array.dat
1100000
0011100
0000111
module pla_1 (a1,a2,a3,a4,a5,a6,a7,b1,b2,b3);
input a1, a2, a3, a4, a5, a6, a7 ; output b1, b2, b3;
reg [1:7] mem[1:3]; reg b1, b2, b3;
initial begin
("array.dat", mem);
#1; b1=1; b2=1; b3=1;
(mem,{a1,a2,a3,a4,a5,a6,a7},{b1,b2,b3});
end
initial ("%4g",,,b1,,b2,,b3);
endmodule
The next example illustrates
the use of the plane format, which allows
b1 = a1 & !a2; b2 = a3; b3 = !a1 & !a3; b4 = 1;
module pla_2; reg [1:3] a, mem[1:4]; reg [1:4] b;
initial begin
(mem,{a[1],a[2],a[3]},{b[1],b[2],b[3],b[4]});
mem[1] = 3'b10?; mem[2] = 3'b??1; mem[3] = 3'b0?0; mem[4] = 3'b???;
#10 a = 3'b111; #10 (a, " -> ", b);
#10 a = 3'b000; #10 (a, " -> ", b);
#10 a = 3'bxxx; #10 (a, " -> ", b);
#10 a = 3'b101; #10 (a, " -> ", b);
end endmodule
111 -> 0101
000 -> 0011
xxx -> xxx1
101 -> 1101
11.13.5 Stochastic Analysis TasksThe stochastic analysis tasks model queues [Verilog LRM 14.7]. Each of the tasks return a status as shown in Table 11.12.
The following module illustrates the interface and parameters for these tasks: module stochastic; initial begin // stochastic analysis system tasks: /* (q_id, q_type, max_length, status) ; q_id is an integer that uniquely identifies the queue q_type 1=FIFO 2=LIFO max_length is an integer defining the maximum number of entries */ (q_id, q_type, max_length, status) ; /* (q_id, job_id, inform_id, status) ; job_id = integer input inform_id = user-defined integer input for queue entry */ (q_id, job_id, inform_id, status) ; /* (q_id, job_id, inform_id, status) ; */ (q_id, job_id, inform_id, status) ; /* (q_id, status) ; status = 0 = queue is not full, status = 1 = queue full */ (q_id, status) ; /* (q_id, q_stat_code, q_stat_value, status) ; q_stat_code is input request as follows: 1=current queue length 2=mean inter-arrival time 3=max. queue length 4=shortest wait time ever 5=longest wait time for jobs still in queue 6=ave. wait time in queue q_stat_value is output containing requested value */ (q_id, q_stat_code, q_stat_value, status) ; end endmodule 11.13.6 Simulation Time FunctionsThe simulation time functions return the time as follows [Verilog LRM 14.8]: module test_time; initial begin // simulation time system functions: ; // returns 64-bit integer scaled to timescale unit of invoking module ; // returns 32-bit integer scaled to timescale unit of invoking module ; // returns real scaled to timescale unit of invoking module end endmodule 11.13.7 Conversion FunctionsThe conversion functions for reals handle real numbers [Verilog LRM 14.9]:
module test_convert; // conversion functions for reals:
integer i; real r; reg [63:0] bits;
initial begin #1 r=256;#1 i = (r);
#1; r = (2 * i) ; #1 bits = (2.0 * r) ;
#1; r = (bits) ; end
initial ("%3f",,,i,,r,,bits); /*
converts reals to integers w/truncation e.g. 123.45 -> 123
converts integers to reals e.g. 123 -> 123.0
converts reals to 64-bit vector
converts bit pattern to real
Real numbers in these functions conform to IEEE Std 754. Conversion rounds to the nearest valid number. */
endmodule
# 0.000000 x 0 x
# 1.000000 x 256 x
# 2.000000 256 256 x
# 3.000000 256 512 x
# 4.000000 256 512 4652218415073722368
# 5.000000 256 1024 4652218415073722368
Here is an example using the conversion functions in port connections:
module test_real;wire [63:0]a; driver d (a); receiver r (a);
initial ("%3g",,,a,,d.r1,,r.r2); endmodule
module driver (real_net);
output real_net; real r1; wire [64:1] real_net = (r1);
initial #1 r1 = 123.456; endmodule
module receiver (real_net);
input real_net; wire [64:1] real_net; real r2;
initial assign r2 = (real_net);
endmodule
# 0 0 0 0
# 1 4638387860618067575 123.456 123.456
11.13.8 Probability Distribution FunctionsThe probability distribution functions are as follows [Verilog LRM 14.10]:
module probability; // probability distribution functions:
/* [ ( seed ) ] returns random 32-bit signed integer
seed = register, integer, or time */
reg [23:0] r1,r2; integer r3,r4,r5,r6,r7,r8,r9;
integer seed, start, \end , mean, standard_deviation;
integer degree_of_freedom, k_stage;
initial begin seed=1; start=0; \end =6; mean=5;
standard_deviation=2; degree_of_freedom=2; k_stage=1; #1;
r1 = % 60; // random -59 to 59
r2 = % 60; // positive value 0-59
r3= (seed, start, \end ) ;
r4= (seed, mean, standard_deviation) ;
r5= (seed, mean) ;
r6= (seed, mean) ;
r7= (seed, degree_of_freedom) ;
r8= (seed, degree_of_freedom) ;
r9= (seed, k_stage, mean) ; end
initial #2 ("%3f",,,r1,,r2,,r3,,r4,,r5);
initial begin #3; ("%3f",,,r6,,r7,,r8,,r9); end
/* All parameters are integer values.
Each function returns a pseudo-random number
e.g. returns uniformly distributed random numbers
mean, degree_of_freedom, k_stage
(exponential, poisson, chi-square, t, erlang) > 0.
seed = inout integer initialized by user, updated by function
start, end () = integer bounding return values */
endmodule
2.000000 8 57 0 4 9
3.000000 7 3 0 2
11.13.9 Programming Language InterfaceThe C language Programming Language Interface ( PLI) allows you to access the internal Verilog data structure [Verilog LRM17-23, A-E]. For example, you can use the PLI to implement the following extensions to a Verilog simulator:
There are three generations of PLI routines (see Appendix B for an example):
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||