|
Introduction |
Verilog has built-in primitives like gates, transmission gates, and switches. This is a rather small number of primitives; if we need more complex primitives, then Verilog provides UDP, or simply User Defined Primitives. Using UDP we can model
| |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
We can include timing information along with these UDP to model complete ASIC library models.
| |||||||||||||||||||||||||||||
Syntax | |||||||||||||||||||||||||||||
UDP begins with reserve word primitive and ends withendprimitive. Ports/terminals of primitive should follow. This is similar to what we do for module definition. UDPs should be defined outside module and endmodule
| |||||||||||||||||||||||||||||
1 //This code shows how input/output ports 2 // and primitve is declared 3 primitive udp_syntax ( 4 a, // Port a 5 b, // Port b 6 c, // Port c 7 d // Port d 8 ); 9 output a; 10 input b,c,d; 11 12 // UDP function code here 13 14 endprimitiveYou could download file udp_syntax.v here | |||||||||||||||||||||||||||||
In the above code, udp_syntax is the primitive name, it contains ports a, b,c,d.
| |||||||||||||||||||||||||||||
The formal syntax of the UDP definition is as follows:
| |||||||||||||||||||||||||||||
<UDP>
::= primitive <name_of_UDP> ( <output_terminal_name>,
<input_terminal_name> <,<input_terminal_name>>* ) ;
<UDP_declaration>+
<UDP_initial_statement>?
<table_definition>
endprimitive
<name_of_UDP>
::= <IDENTIFIER>
<UDP_declaration>
::= <UDP_output_declaration>
||= <reg_declaration>
||= <UDP_input_declaration>
<UDP_output_declaration>
::= output <output_terminal _name>;
<reg_declaration>
::= reg <output_terminal_name> ;
<UDP_input_declaration>
::= input <input_terminal_name> <,<input_terminal_name>>* ;
<UDP_initial_statement>
::= initial <output_terminal_name> = <init_val> ;
<init_val>
::= 1'b0
||= 1'b1
||= 1'bx
||= 1
||= 0
<table_definition>
::= table
<table_entries>
endtable
<table_entries>
::= <combinational_entry>+
||= <sequential_entry>+
<combinational_entry>
::= <level_input_list> : <OUTPUT_SYMBOL> ;
<sequential_entry>
::= <input_list> : <state> : <next_state> ;
<input_list>
::= <level_input_list>
||= <edge_input_list>
<level_input_list>
::= <LEVEL_SYMBOL>+
<edge_input_list>
::= <LEVEL_SYMBOL>* <edge> <LEVEL_SYMBOL>*
<edge>
::= ( <LEVEL_SYMBOL> <LEVEL_SYMBOL> )
||= <EDGE_SYMBOL>
<state>
::= <LEVEL_SYMBOL>
<next_state>
::= <OUTPUT_SYMBOL>
||= -
| |||||||||||||||||||||||||||||
UDP ports rules | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
Body | |||||||||||||||||||||||||||||
Functionality of primitive (both combinational and sequential) is described inside a table, and it ends with reserved word 'endtable' as shown in the code below. For sequential UDP, we can use initial to assign an initial value to output.
| |||||||||||||||||||||||||||||
1 // This code shows how UDP body looks like 2 primitive udp_body ( 3 a, // Port a 4 b, // Port b 5 c // Port c 6 ); 7 output a; 8 input b,c; 9 10 // UDP function code here 11 // A = B | C; 12 table 13 // B C : A 14 ? 1 : 1; 15 1 ? : 1; 16 0 0 : 0; 17 endtable 18 19 endprimitiveYou could download file udp_body.v here | |||||||||||||||||||||||||||||
Note: An UDP cannot use 'z' in the input table
| |||||||||||||||||||||||||||||
TestBench to check the above UDP
| |||||||||||||||||||||||||||||
1 `include "udp_body.v" 2 module udp_body_tb(); 3 4 reg b,c; 5 wire a; 6 7 udp_body udp (a,b,c); 8 9 initial begin 10 $monitor(" B = %b C = %b A = %b",b,c,a); 11 b = 0; 12 c = 0; 13 #1 b = 1; 14 #1 b = 0; 15 #1 c = 1; 16 #1 b = 1'bx; 17 #1 c = 0; 18 #1 b = 1; 19 #1 c = 1'bx; 20 #1 b = 0; 21 #1 $finish; 22 end 23 24 endmoduleYou could download file udp_body_tb.v here | |||||||||||||||||||||||||||||
Simulator Output
| |||||||||||||||||||||||||||||
B = 0 C = 0 A = 0
B = 1 C = 0 A = 1
B = 0 C = 0 A = 0
B = 0 C = 1 A = 1
B = x C = 1 A = 1
B = x C = 0 A = x
B = 1 C = 0 A = 1
B = 1 C = x A = 1
B = 0 C = x A = x
| |||||||||||||||||||||||||||||
Table | |||||||||||||||||||||||||||||
Table is used for describing the function of UDP. Verilog reserved word table marks the start of table and reserved word endtablemarks the end of table.
| |||||||||||||||||||||||||||||
Each line inside a table is one condition; when an input changes, the input condition is matched and the output is evaluated to reflect the new change in input.
| |||||||||||||||||||||||||||||
Initial | |||||||||||||||||||||||||||||
Initial statement is used for initialization of sequential UDPs. This statement begins with the keyword 'initial'. The statement that follows must be an assignment statement that assigns a single bit literal value to the output terminal reg.
| |||||||||||||||||||||||||||||
1 primitive udp_initial (a,b,c); 2 output a; 3 input b,c; 4 reg a; 5 // a has value of 1 at start of sim 6 initial a = 1'b1; 7 8 table 9 // udp_initial behaviour 10 endtable 11 12 endprimitiveYou could download file udp_initial.v here | |||||||||||||||||||||||||||||
Symbols | |||||||||||||||||||||||||||||
UDP uses special symbols to describe functions like rising edge, don't care and so on. The table below shows the symbols that are used in UDPs:
| |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
沒有留言:
張貼留言