표준 Verilog 기본 요소(nand, not 등)가 복잡한 로직을 표현하기에 항상 쉽거나 충분하지 않을 수 있습니다. UDP 또는 사용자 정의 기본 요소(user-defined primitives)라고 하는 새로운 기본 요소들을 정의하여 조합 또는 순차 로직을 모델링할 수 있습니다.
모든 UDP는 정확히 하나의 출력을 가지며 0, 1, X 중 하나일 수 있고 Z는 절대 될 수 없습니다(지원 안 함). Z 값을 가진 입력은 X로 처리됩니다.
Verilog UDP 기호
Verilog 사용자 정의 기본 요소는 module 정의와 같은 레벨에 작성할 수 있지만, module과 endmodule 사이에는 절대 쓸 수 없습니다. 여러 입력 포트를 가질 수 있지만 항상 하나의 출력 포트만 가지며, 양방향 포트는 유효하지 않습니다. 모든 포트 신호는 스칼라여야 하므로 1비트 폭이어야 합니다.
하드웨어 동작은 기본 요소 상태 테이블로 기술되며, 입력의 다양한 가능한 조합과 해당 출력이 table과 endtable 안에 나열됩니다. 입력과 출력 신호 값은 다음 기호로 표시됩니다.
기호
설명
0
논리 0
1
논리 1
x
알 수 없음, 논리 0 또는 1일 수 있음. 순차 UDP의 입력/출력 또는 현재 상태에 사용 가능
?
논리 0, 1, 또는 x. UDP 출력에는 사용할 수 없음
-
변화 없음, UDP 출력에서만 허용
ab
a에서 b로의 값 변화, a 또는 b는 0, 1, 또는 x
*
??와 동일, 입력 값의 모든 변화를 나타냄
r
01과 동일, 입력의 상승 에지
f
10과 동일, 입력의 하강 에지
p
입력의 잠재적 양의 에지: 0->1, 0->x, 또는 x->1
n
입력의 잠재적 하강 에지: 1->0, x->0, 1->x
조합 UDP 예제
// 출력은 포트 리스트에서 항상 첫 번째 신호여야 함
primitive mux (out, sel, a, b);
output out;
input sel, a, b;
table
// sel a b out
0 1 ? : 1;
0 0 ? : 0;
1 ? 0 : 0;
1 ? 1 : 1;
x 0 0 : 0;
x 1 1 : 1;
endtable
endprimitive
?는 해당 신호가 0, 1, 또는 x일 수 있으며 최종 출력 결정에 영향을 주지 않음을 나타냅니다.
아래 테스트벤치 모듈은 UDP를 인스턴스화하고 입력 자극을 가합니다.
module tb;
reg sel, a, b;
reg [2:0] dly;
wire out;
integer i;
// UDP 인스턴스화 - UDP는 포트 이름 연결로 인스턴스화할 수 없음에 유의
mux u_mux ( out, sel, a, b);
initial begin
a <= 0; b <= 0;
$monitor("[T=%0t] a=%0b b=%0b sel=%0b out=%0b", $time, a, b, sel, out);
// a, b, sel을 서로 다른 랜덤 지연 후 구동
for (i = 0; i < 10; i = i + 1) begin
dly = $random; #(dly) a <= $random;
dly = $random; #(dly) b <= $random;
dly = $random; #(dly) sel <= $random;
end
end
endmodule
module tb;
reg clk, d;
reg [1:0] dly;
wire q;
integer i;
d_latch u_latch (q, clk, d);
always #10 clk = ~clk;
initial begin
clk = 0;
$monitor ("[T=%0t] clk=%0b d=%0b q=%0b", $time, clk, d, q);
#10; // X 효과 보기 위해
for (i = 0; i < 50; i = i+1) begin
dly = $random; #(dly) d <= $random;
end
#20 $finish;
end
endmodule