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, nd , mean, standard_deviation; integer degree_of_freedom, k_stage; initial begin seed=1; start=0; nd =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, nd ) ; 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):
|
||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||
|