verilog
Verilog에는 두 가지 유형의 타이밍 컨트롤이 있습니다 - 지연 및 이벤트 표현. 지연 제어는 시뮬레이터가 명령문을 만나는 시간과 실제로 실행하는 시간 사이에 지연을 추가하는 방법일 뿐입니다. 이벤트 표현 순 또는 변수의 값 변경이 될 수 있는 시뮬레이션 이벤트가 발생할 때까지 명령문이 지연되도록 허용합니다(암시적 이벤트 ) 또는 다른 프로시저에서 트리거되는 명시적으로 명명된 이벤트입니다.
시뮬레이션 시간은 다음 방법 중 하나로 앞당길 수 있습니다.
내부 지연을 갖도록 모델링된 게이트 및 네트도 시뮬레이션 시간을 앞당깁니다.
지연 표현식이 알 수 없거나 높은 임피던스 값으로 평가되면 지연이 0인 것으로 해석됩니다. 음수 값으로 평가되면 시간 변수와 동일한 크기의 2의 보수 부호 없는 정수로 해석됩니다.
`timescale 1ns/1ps
module tb;
reg [3:0] a, b;
initial begin
{a, b} <= 0;
$display ("T=%0t a=%0d b=%0d", $realtime, a, b);
#10;
a <= $random;
$display ("T=%0t a=%0d b=%0d", $realtime, a, b);
#10 b <= $random;
$display ("T=%0t a=%0d b=%0d", $realtime, a, b);
#(a) $display ("T=%0t After a delay of a=%0d units", $realtime, a);
#(a+b) $display ("T=%0t After a delay of a=%0d + b=%0d = %0d units", $realtime, a, b, a+b);
#((a+b)*10ps) $display ("T=%0t After a delay of %0d * 10ps", $realtime, a+b);
#(b-a) $display ("T=%0t Expr evaluates to a negative delay", $realtime);
#('h10) $display ("T=%0t Delay in hex", $realtime);
a = 'hX;
#(a) $display ("T=%0t Delay is unknown, taken as zero a=%h", $realtime, a);
a = 'hZ;
#(a) $display ("T=%0t Delay is in high impedance, taken as zero a=%h", $realtime, a);
#1ps $display ("T=%0t Delay of 10ps", $realtime);
end
endmodule
타임스케일의 정밀도는 1ps이므로 $realtime
입니다. 지연 표현식 (a+b)*10ps를 사용하여 문의 정밀도 값을 표시하는 데 필요합니다.
xcelium> run T=0 a=x b=x T=10000 a=0 b=0 T=20000 a=4 b=0 T=24000 After a delay of a=4 units T=29000 After a delay of a=4 + b=1 = 5 units T=29050 After a delay of 5 * 10ps T=42050 Expr evaluates to a negative delay T=58050 Delay in hex T=58050 Delay is unknown, taken as zero a=x T=58050 Delay is in high impedance, taken as zero a=z T=58051 Delay of 10ps xmsim: *W,RNQUIE: Simulation is complete.
네트 및 변수의 값 변경은 다른 절차적 명령문 실행을 트리거하는 동기화 이벤트로 사용될 수 있으며 암시적입니다. 이벤트. 이벤트는 0과 같은 변경 방향을 기반으로 할 수도 있으므로 negedge
이 됩니다. 1로 변경하면 posedge
이 됩니다. .
negedge
1에서 X, Z 또는 0으로, X 또는 Z에서 0으로의 전환이 있을 때입니다.posedge
0에서 X, Z 또는 1로, X 또는 Z에서 1로의 전환이 있을 때입니다.동일한 상태에서 동일한 상태로의 전환은 에지로 간주되지 않습니다. Posedge 또는 Negedge와 같은 에지 이벤트는 벡터 신호 또는 변수의 LSB에서만 감지할 수 있습니다. 표현식이 동일한 결과로 평가되면 이벤트로 간주될 수 없습니다.
module tb;
reg a, b;
initial begin
a <= 0;
#10 a <= 1;
#10 b <= 1;
#10 a <= 0;
#15 a <= 1;
end
// Start another procedural block that waits for an update to
// signals made in the above procedural block
initial begin
@(posedge a);
$display ("T=%0t Posedge of a detected for 0->1", $time);
@(posedge b);
$display ("T=%0t Posedge of b detected for X->1", $time);
end
initial begin
@(posedge (a + b)) $display ("T=%0t Posedge of a+b", $time);
@(a) $display ("T=%0t Change in a found", $time);
end
endmodule
시뮬레이션 로그 ncsim> run T=10 Posedge of a detected for 0->1 T=20 Posedge of b detected for X->1 T=30 Posedge of a+b T=45 Change in a found ncsim: *W,RNQUIE: Simulation is complete.
키워드 event
named를 선언하는 데 사용할 수 있습니다. 명시적으로 트리거될 수 있는 이벤트. event
데이터를 보유할 수 없고 지속 시간이 없으며 특정 시간에 발생하도록 만들 수 있습니다. 명명된 이벤트는 ->
에 의해 트리거됩니다. 명명된 이벤트 핸들 앞에 접두사로 연산자를 추가합니다. @
을 사용하여 명명된 이벤트를 기다릴 수 있습니다. 위에서 설명한 연산자입니다.
module tb;
event a_event;
event b_event[5];
initial begin
#20 -> a_event;
#30;
->a_event;
#50 ->a_event;
#10 ->b_event[3];
end
always @ (a_event) $display ("T=%0t [always] a_event is triggered", $time);
initial begin
#25;
@(a_event) $display ("T=%0t [initial] a_event is triggered", $time);
#10 @(b_event[3]) $display ("T=%0t [initial] b_event is triggered", $time);
end
endmodule
명명된 이벤트를 사용하여 동시에 실행 중인 둘 이상의 프로세스를 동기화할 수 있습니다. 예를 들어, always
블록 및 두 번째 initial
블록은 a_event에 의해 동기화됩니다. 이벤트는 크기가 5이고 인덱스 3이 트리거 및 대기 목적으로 사용되는 b_event의 경우와 같이 배열로 선언할 수 있습니다.
ncsim> run T=20 [always] a_event is triggered T=50 [always] a_event is triggered T=50 [initial] a_event is triggered T=100 [always] a_event is triggered T=110 [initial] b_event is triggered ncsim: *W,RNQUIE: Simulation is complete.
or
연산자는 나열된 이벤트 중 하나가 표현식에서 트리거될 때까지 기다리는 데 사용할 수 있습니다. 쉼표 ,
or
대신 사용할 수도 있습니다. 연산자.
module tb;
reg a, b;
initial begin
$monitor ("T=%0t a=%0d b=%0d", $time, a, b);
{a, b} <= 0;
#10 a <= 1;
#5 b <= 1;
#5 b <= 0;
end
// Use "or" between events
always @ (posedge a or posedge b)
$display ("T=%0t posedge of a or b found", $time);
// Use a comma between
always @ (posedge a, negedge b)
$display ("T=%0t posedge of a or negedge of b found", $time);
always @ (a, b)
$display ("T=%0t Any change on a or b", $time);
endmodule
시뮬레이션 로그 ncsim> run T=0 posedge of a or negedge of b found T=0 Any change on a or b T=0 a=0 b=0 T=10 posedge of a or b found T=10 posedge of a or negedge of b found T=10 Any change on a or b T=10 a=1 b=0 T=15 posedge of a or b found T=15 Any change on a or b T=15 a=1 b=1 T=20 posedge of a or negedge of b found T=20 Any change on a or b T=20 a=1 b=0 ncsim: *W,RNQUIE: Simulation is complete.
민감도 목록 또는 이벤트 표현 목록은 종종 RTL에서 많은 기능 오류의 일반적인 원인입니다. 이는 사용자가 절차 블록에 새 신호를 도입한 후 민감도 목록을 업데이트하는 것을 잊어버릴 수 있기 때문입니다.
module tb;
reg a, b, c, d;
reg x, y;
// Event expr/sensitivity list is formed by all the
// signals inside () after @ operator and in this case
// it is a, b, c or d
always @ (a, b, c, d) begin
x = a | b;
y = c ^ d;
end
initial begin
$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b x=%0b y=%0b", $time, a, b, c, d, x, y);
{a, b, c, d} <= 0;
#10 {a, b, c, d} <= $random;
#10 {a, b, c, d} <= $random;
#10 {a, b, c, d} <= $random;
end
endmodule
시뮬레이션 로그 ncsim> run T=0 a=0 b=0 c=0 d=0 x=0 y=0 T=10 a=0 b=1 c=0 d=0 x=1 y=0 T=20 a=0 b=0 c=0 d=1 x=0 y=1 T=30 a=1 b=0 c=0 d=1 x=1 y=1 ncsim: *W,RNQUIE: Simulation is complete.
사용자가 새로운 신호 e를 추가하고 z에 역을 캡처하기로 결정한 경우 e를 감도 목록에도 추가하는 데 특별한 주의를 기울여야 합니다.
module tb;
reg a, b, c, d, e;
reg x, y, z;
// Add "e" also into sensitivity list
always @ (a, b, c, d, e) begin
x = a | b;
y = c ^ d;
z = ~e;
end
initial begin
$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b e=%0b x=%0b y=%0b z=%0b",
$time, a, b, c, d, e, x, y, z);
{a, b, c, d, e} <= 0;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
end
endmodule
시뮬레이션 로그 ncsim> run T=0 a=0 b=0 c=0 d=0 e=0 x=0 y=0 z=1 T=10 a=0 b=0 c=1 d=0 e=0 x=0 y=1 z=1 T=20 a=0 b=0 c=0 d=0 e=1 x=0 y=0 z=0 T=30 a=0 b=1 c=0 d=0 e=1 x=1 y=0 z=0 ncsim: *W,RNQUIE: Simulation is complete.
Verilog는 이제 민감도 목록을 *
로 대체할 수 있습니다. 이는 아래와 같이 statemnt에서 읽는 모든 net과 변수를 추가하여 이러한 문제를 제거하는 편리한 약식입니다.
module tb;
reg a, b, c, d, e;
reg x, y, z;
// Use @* or @(*)
always @ * begin
x = a | b;
y = c ^ d;
z = ~e;
end
initial begin
$monitor ("T=%0t a=%0b b=%0b c=%0b d=%0b e=%0b x=%0b y=%0b z=%0b",
$time, a, b, c, d, e, x, y, z);
{a, b, c, d, e} <= 0;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
#10 {a, b, c, d, e} <= $random;
end
endmodule
시뮬레이션 로그 ncsim> run T=0 a=0 b=0 c=0 d=0 e=0 x=0 y=0 z=1 T=10 a=0 b=0 c=1 d=0 e=0 x=0 y=1 z=1 T=20 a=0 b=0 c=0 d=0 e=1 x=0 y=0 z=0 T=30 a=0 b=1 c=0 d=0 e=1 x=1 y=0 z=0 ncsim: *W,RNQUIE: Simulation is complete.
절차적 명령문 실행은 조건이 참이 될 때까지 지연될 수 있으며 wait
을 사용하여 수행할 수 있습니다. 키워드이며 레벨에 민감한 컨트롤입니다.
대기 문은 조건을 평가해야 하며 거짓이면 조건이 참이 될 때까지 그 뒤에 오는 절차 문을 차단된 상태로 유지해야 합니다.
module tb;
reg [3:0] ctr;
reg clk;
initial begin
{ctr, clk} <= 0;
wait (ctr);
$display ("T=%0t Counter reached non-zero value 0x%0h", $time, ctr);
wait (ctr == 4) $display ("T=%0t Counter reached 0x%0h", $time, ctr);
$finish;
end
always #10 clk = ~clk;
always @ (posedge clk)
ctr <= ctr + 1;
endmodule
시뮬레이션 로그 ncsim> run T=10 Counter reached non-zero value 0x1 T=70 Counter reached 0x4 T=90 Counter reached 0x5 T=170 Counter reached 0x9 Simulation complete via $finish(1) at time 170 NS + 1
verilog
매개변수는 다른 사양으로 모듈을 재사용할 수 있도록 하는 Verilog 구성입니다. 예를 들어, 4비트 가산기는 비트 수에 대한 값을 허용하도록 매개변수화될 수 있으며 모듈 인스턴스화 중에 새 매개변수 값이 전달될 수 있습니다. 따라서 N비트 가산기는 4비트, 8비트 또는 16비트 가산기가 될 수 있습니다. 함수 호출 중에 전달되는 함수에 대한 인수와 같습니다. parameter MSB = 7; // MSB is a parameter with a constant value 7 paramet
Verilog는 하드웨어 설명 언어이며 설계자가 RTL 설계를 시뮬레이션하여 논리 게이트로 변환할 필요가 없습니다. 시뮬레이션이 필요한 이유는 무엇입니까? 시뮬레이션은 RTL 코드가 의도한 대로 동작하는지 확인하기 위해 다른 시간에 다른 입력 자극을 설계에 적용하는 기술입니다. 기본적으로 시뮬레이션은 설계의 견고성을 검증하기 위해 잘 따라야 하는 기술입니다. 또한 가공된 칩이 실제 세계에서 사용되는 방식과 다양한 입력에 반응하는 방식과 유사합니다. 예를 들어, 위의 디자인은 출력 pe 보여진 바와 같이. 시뮬레이션을 통해