Introduce
Verilog에서는 다양한 행위 수준의 타이밍 제어구조를 사용할 수 있다.
- 지연 기반 타이밍 제어(delay-based timing control)
- 사건 기반 타이밍 제어(event-based timing control)
- 준위-구동 타이밍 제어(level-sensitive timing control)
지연 기반 타이밍 제어
수식문 안에서 지연 기반 타이밍 제어는 문장을 만나고 그것이 수행되는 사이의 시간 지연을 지정한다. 지연은 기호 #에 의해서 지정된다. 절차적 할당을 위한 지연에는 3가지 형태가 있다.
- 정규 지연 제어
- 내부 할당 지연 제어
- 제로 지연 제어
정규지연 제어
절차적 할당의 왼쪽에 0값이 아닌 지연이 지정될때 사용한다. 사용법은 다음과 같다.
parameter latency = 20;
parameter delta = 2;
// 레지스터 변수 정의
reg x, y, z, p, q;
initial begin
x = 0; // 지연 제어가 없다.
#10 y = 1; // 숫자를 가지고 지연 제어를 한다.
#latency z = 0; // 식별자를 가지고 지연 제어를 한다.
#(latency + delta) p = 1; // 수식을 가지고 지연 제어.
#y x = x +1; // 식별자를 가지고 지연 제어를 한다. y의 값을 가진다.
#(4:5:6) q = 0; // 최소, 전형, 최대 지연값.
end
내부 할당 지연 제어
지연 제어를 할당의 왼쪽에 지정하는 대신에, 할당 연산자의 오른쪽에 지연을 할당할 수 있다. 이러한 지연 지정은 수행의 흐름을 다른 방식으로 바꾼다. 다음의 예는 내부 할당 지연과 정규 지연의 대조를 보여준다.
// 레지스터 변수 정의
reg x, y, z, p, q;
// 내부 할당 지연
initial begin
x = 0; z = 0;
y = #5 x + z; // x와 z의 값을 단위시간 0에 취해서, x+z를 계산한뒤 5단위 시간을 기다린 후에 y에 값을 할당
end
// 임시 변수와 정규 지연 제어를 사용한 같은 방법
initial begin
x = 0; z = 0;
temp_xz = x + z;
#5 y = temp_xz;
end
정규할당지연에서는 단지 해당 문장을 만난 뒤 특정 단위 시간 후 수행되는 반면에 내부 할당 지연 제어는 현재 시간에 x+z의 값을 취해서 임시 변수에 저장한다. 비록 x와 z가 0과 5사이에 변한다고 해도 단위 시간 5에 할당되는 값은 변하지 않는다.
제로 지연 제어
다른 always-initial 블록 안의 절차적 할당은 같은 시뮬레이션 기간에 수행한다. 다른 always-initial블록 안의 이 문장의 수행 순서는 무작위이다. 제로 지연 제어는 다른 모든 문장이 이 시뮬레이션 기간에 실행된 후 이 문장이 마지막으로 수행되게 하는 방법이다. (경쟁 상태를 없애기 위해서 사용된다.) 사용법은 다음과 같다.
initial begin
x = 0;
y = 0;
end
initial begin
#0 x = 1; // 제로 지연 제어
#0 y = 1;
end
두번째 initial 블록이 마지막에 수행된다. 그래서 단위시간 0의 끝에서 x,y는 1의 값을 가진다. 하지만 실제로 #0을 사용하는것은 추천하지 않는다.
사건 기반 타이밍 제어
사건(event)는 레지스터 또는 넷의 값 변화를 의미한다. 사건은 문장 또는 문장의 블록 구동을 위해 사용될 수 있다. 사건 기반 타이밍 제어는 4가지 형태가 있다.
- 정규 사건 제어
- 명명된 사건 제어
- 사건 OR 제어
- 준위-구동 타이밍 제어
정규 사건 제어
@ 기호는 사건 제어를 지정하는데 사용된다. 문장은 신호값 또는 신호값의 양 또는 음으로 변할때 수행된다. 다음 예제는 키워드 posedge는 클럭이 상승시에 사용된다.
@(clock) q = d; // q = d는 신호 클럭이 별할 때마다 수행.
@(posedge clock) q = d; // q = d는 신호 클럭이 상승 변환을 할 때마다 수행.
q = @(posedge clock) d; // 클럭의 상승 엣지에서 현재 d의 값을 구하고 q로 할당.
명명된 사건 제어
Verilog는 사건을 선언하는 것을 제공하고 그 사건이 일어나는 경우 구동되고 인정된다. 사건은 어떤 데이터도 가지고 있을 수 없다. 명명된 사건은 키워드 event에 의해 선언되고, ->에 의해 구동된다. 사건의 구동은 @기호에 의해 인정된다.
// 데이터의 마지막 패킷이 도착한 후에 데이터 버파가 데이터에 저장되는 얘제
event received_data ; // received_data라는 사건을 정의.
always @(posedge clock) begin
if(last_data_packet) // 만약 마지막 데이터 패킷이면
-> received_data; // 사건 received_data를 구동한다.
end
always @(received_data) begin // 사건 received_data가 구동되기를 기다린다.
// 사건이 구동되면 데이터 버퍼의 받은 모든 데이터를 버퍼를 연결연산자{}를 통해 저장한다.
data_buf = {data_pkt[0],data_pkt[1]};
end
사건 OR 제어
때때로 여러 신호와 사건 중 하나의 신호라도 변하면, 문장이나 문장 블록이 실행될 수 있다. 이것은 사건이나 신호의 OR로 표현한다. OR로 표현된 사건이나 신호의 목록을 감지목록(senseitivity list)라 한다. 다음은 키워드 or가 여러 개의 구동을 지정하는데 사용된다.
// 비동기 리셋을 가진 준위-구동 래치
always @(rest or clock or d) begin
if(reset) q = 1'b0;
else if(clock) q = d;
end
조합 논리 블록의 입력 변수가 매우 많으면 감지 목록들을 쓰기가 매우 복잡해 진다. 게다가, 입력 변수의 값을 잘못 입력하면, 예상치못한 오류를 일으킬 수 있다. 이 문제를 해결하기 위해 Verilog HDL은 두개의 특별한 기호를 도입한다. @*, @(*)
두 기호 모두 동일한 동작을 한다. 이 특별한 기호 뒤에 따라오는 명령문 그룹에서 어떠한 신호의 변화도 감지해낸다.
// 조합 논리 블록은 복잡한 입력에 or 연산자를 사용한다.
// 이런 방식은 실수를 하기 쉽다.
always @(a or b or c or d or e or f) begin
out1 = a ? b : c;
out2 = d ? e : f;
end
// 위 방법을 대신해서 @(*)기호를 사용할 수 있다.
always @(*) begin
out1 = a ? b : c;
out2 = d ? e : f;
end
준위 - 구동 타이밍 제어
사건 제어는 신호값이 바뀌거나 사건이 구동되기를 기다린다는 것을 볼 수 있었다. @기호는 엣지-구동 제어를 제공한다. Verilog는 문장 또는 문장의 블록이 수행괴기 전, 특정 상태가 참이 되기를 기다리는 준위-구동 타이밍 제어를 제공한다. 키우더 wait는 준위-구동 제어를 위해 쓰인다.
always
wait (count_enable) #20 count = count +1 ;
위의 예에서 count_enable의 값은 연속적으로 모니터 된다. 만약 count_enable이 0이면, 문장이 수행되지않고, 1이면 cout = count +1은 20 단위시간 후 수행된다. 즉, count_enable이 1값을 유지하면, 매 20단위시간마다 count값이 증가한다.
'UVM & RTL > Verilog HDL' 카테고리의 다른 글
[Verilog HDL] CH7 루프 (0) | 2022.06.14 |
---|---|
[Verilog HDL] CH7 조건문, 다중분기 (0) | 2022.06.14 |
[Verilog HDL] CH7 구조적 프로시저 & 절차적 할당 (0) | 2022.06.14 |
[Verilog HDL] CH6 연산자 (0) | 2022.06.14 |
[Verilog HDL] CH6 dataflow 모델링 (0) | 2022.06.14 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!