반응형

Verilog의 시스템 작업은 실제 회로와 연결되지 않은 모델에 추가 기능을 삽입하는 데 사용되는 작업입니다.

 

Verilog에는 세 가지 주요 시스템 작업 그룹이 있습니다.

(1) 텍스트 출력

(2) 파일 입출력

(3) 시뮬레이션 제어.

 

모든 시스템 작업은 $로 시작하며 시뮬레이션 중에만 사용됩니다. 이러한 작업은 합성기에 의해 무시되므로 실제 회로 모델에 포함될 수 있습니다. 모든 시스템 작업은 절차 블록 내에 있어야 합니다.

 

텍스트 출력

텍스트 출력 시스템 작업은 문자열과 변수 값을 시뮬레이션 도구의 콘솔이나 스크립트에 인쇄하는 데 사용됩니다. 구문은 인쇄할 텍스트 문자열을 나타내는 데 큰따옴표("")가 사용되는 ANSI C를 따릅니다. 문자열에는 변수 외에 표준 텍스트를 입력할 수 있습니다. 변수는 두 가지 방법으로 인쇄할 수 있습니다. 첫 번째는 시스템 작업 함수의 변수를 큰따옴표 외부에 간단히 나열하는 것입니다.

이 사용법에서 작업이 다른 기본 형식으로 사용되지 않는 한 인쇄되는 기본 형식은 10진수입니다. 변수를 인쇄하는 두 번째 방법은 텍스트 문자열 내에서입니다. 이 사용법에서는 값을 인쇄하는 형식을 나타내는 문자열에 고유한 코드가 삽입됩니다. 문자열 뒤에는 문자열 내의 코드에 위치적으로 해당하는 변수 이름의 쉼표로 구분된 목록이 나열됩니다. 다음은 가장 일반적으로 사용되는 텍스트 출력 시스템 작업입니다.

 

Task Description
$display() Print text string when statement is encountered and append a newline.
$displayb() Same as $display, but default format of any arguments is binary.
$displayo() Same as $display, but default format of any arguments is octal.
$displayh() Same as $display, but default format of any arguments is hexadecimal.
$write() Same as $display, but the string is printed without a newline.
$writeb() Same as $write, but default format of any arguments is binary.
$writeo() Same as $write, but default format of any arguments is octal.
$writeh() Same as $write, but default format of any arguments is hexadecimal.
$strobe() Same as $display, but printing occurs after all simulation events are executed.
$strobeb() Same as $strobe, but default format of any arguments is binary.
$strobeo() Same as $strobe, but default format of any arguments is octal.
$strobeh() Same as $strobe, but default format of any arguments is hexadecimal.
$monitor() Same as $display, but printing occurs when the value of an argument changes.
$monitorb() Same as $monitor, but default format of any arguments is binary.
$monitoro() Same as $monitor, but default format of any arguments is octal.
$monitorh() Same as $monitor, but default format of any arguments is hexadecimal.
$monitoron Begin tracking argument changes in subsequent $monitor tasks.
$monitoroff Stop tracking argument changes in subsequent $monitor tasks.

 

다음은 문자열 내에서 변수를 인쇄하기 위한 가장 일반적인 텍스트 형식화 코드 목록입니다.

Code Format
%b Binary values
%o Octal values
%d Decimal values
%h Hexadecimal values
%f Real values using decimal form
%e Real values using exponential form
%t Time values
%s Character strings
%m Hierarchical name of scope (no argument required when printing)
%l Configuration library binding (no argument required when printing)

 

이러한 코드의 형식 문자는 대소문자를 구분하지 않습니다(, %d %D는 동일함). 이러한 각 형식 지정 코드에는 선행 및 후행 숫자의 잘림에 대한 정보도 포함될 수 있습니다.

숫자가 잘리면 반올림됩니다. 서식 구문은 다음과 같습니다.

 

%<number_of_leading_digits>.<number_of_trailing_digits><format_code_letter>

 

텍스트 출력 시스템 작업과 함께 사용하기 위해 지원되는 문자열 형식화 및 문자 이스케이프 세트도 있습니다.

 

Code Description
\n Print a new line.
\t Print a tab.
\ Print a quote ().
\cr Print a backslash (\).
%% Print a percent sign (%)

 

다음은 일반적인 텍스트 출력 시스템 작업을 사용하는 일련의 예입니다. 이러한 예에서 A = 3(정수) B = 45.6789(실수)와 같이 두 개의 변수가 선언되고 초기화되었다고 가정합니다. Verilog 32비트 코드를 사용하여 정수 및 실수 유형을 나타냅니다.

 

$display("Hello World");
$display("A =
%b", A);

$display("A = %o", A);
$display("A =
%d", A);
$display("A =
%h", A);
$display("A =
%4.0b", A);

$display("B = %f", B);
$display("B =
%2.0f", B);
$display("B =
%2.1f", B);
$display("B =
%2.2f", B);
$display("B =
%e", B);
$display("B =
%1.0e", B);
$display("B =
%1.1e", B);
$display("B =
%2.2e", B);

$write("A is ", A, "\n");
$writeb("A is ", A, "\n");

$write("A is ", A, "\n");
$writeb("A is ", A, "\n");
// Will print: Hello World
// This will print: A =
0000000000000000000000000000011
// This will print: A =
00000000003
// This will print: A =
3
// This will print: A =
00000003
// This will print: A =
0011

// This will print: B = 45.678900
// This will print: B =
46
// This will print: B =
45.7
// This will print: B =
45.68
// This will print: B =
4.567890e+001
// This will print: B =
5e+001
// This will print: B =
4.6e+001
// This will print: B =
4.57e+001

// This will print: A is 3
// This will print: A is 00000000000000000000000000000011
// Will print: A is 00000000003
// Will print: A is 00000003

 

 

파일 입출력

파일 I/O 시스템 작업을 통해 Verilog 모듈은 파일이 ANSI C에서 처리되는 것과 동일한 방식으로 데이터 파일을 생성 및/또는 액세스할 수 있습니다. 이는 시뮬레이션 결과가 크고 반대로 파일에 저장해야 할 때 유용합니다. 파형 또는 스크립트 창에서 보기 이는 복잡한 자극 벡터를 외부 파일에서 읽어 테스트 중인 장치로 구동해야 하는 경우에도 유용합니다. Verilog는 다음 파일 I/O 시스템 작업 기능을 지원합니다.

 

Task Description
$fopen() Opens a file and returns a unique file descriptor.
$fclose() Closes the file associated with the descriptor.
$fdisplay() Same as $display but statements are directed to the file descriptor.
$fwrite() Same as $write but statements are directed to the file descriptor.
$fstrobe() Same as $strobe but statements are directed to the file descriptor.
$fmonitor() Same as $monitor but statements are directed to the file descriptor.
$readmemb() Read binary data from file and insert into previously defined memory array.
$readmemh() Read hexadecimal data from file and insert into previously defined memory array.

 

$fopen() 함수는 기존 파일을 만들고 열거나 엽니다. 열리는 각 파일에는 다른 I/O 기능에서 파일을 식별하는 데 사용되는 파일 설명자라는 고유 정수가 제공됩니다. $fopen을 처음 사용하기 전에 정수를 선언해야 합니다. 파일 이름 인수는 필수이며 큰따옴표 안에 제공됩니다. 기본적으로 파일은 쓰기 위해 열립니다. 파일 이름이 없으면 생성됩니다. 파일 이름이 있으면 덮어씁니다. 기존 파일 열기 및 파일 추가를 포함하여 파일 열기에 대한 특정 작업을 제공하는 선택적 file_type을 제공할 수 있습니다. 다음은 $fopen()에 대해 지원되는 코드입니다.

 

$fopen types Description
ror rb Open file for reading.
wor wb Create for writing.
aor ab Open for writing and append to the end of file.
r+or r+bor rb+ Open for update, reading or writing file.
w+or w+bor wb+ Create for update.
a+or a+bor ab+ Open or create for update, append to the end of file.

 

파일이 열리면 $fdisplay(), $fwrite(), $fstrobe() $fmonitor() 작업을 사용하여 파일에 데이터를 쓸 수 있습니다. 이러한 함수에는 두 개의 인수가 필요합니다. 첫 번째 인수는 파일 설명자이고 두 번째 인수는 기록할 정보입니다. 정보는 I/O 시스템 작업과 동일한 구문을 따릅니다.

 

다음 예제에서는 파일을 만들고 데이터를 쓰는 방법을 보여줍니다. 이 예제에서는 "Data_out.txt"라는 새 파일을 만들고 변수 A B의 값으로 두 줄의 텍스트를 작성합니다.

 

integer A = 3;
real B =
45.6789;
integer FILE_1;

initial
begin
  FILE_1 =
$fopen("Data_out.txt", "w");
  $fdisplay(FILE_1, "A is %d", A);
  $fdisplay(FILE_1, "B is %f", B);
  $fclose(FILE_1);
end

 

파일에서 데이터를 읽을 때 $readmemb() $readmemh() 함수를 사용할 수 있습니다. 이러한 작업을 수행하려면 파일 내용을 읽을 수 있는 스토리지 배열을 선언해야 합니다. 이러한 작업에는 두 개의 인수가 있습니다. 첫 번째는 파일 이름이고 두 번째 인수는 파일 내용을 저장할 스토리지 배열의 이름입니다.

 

다음 예는 파일의 내용을 "메모리"라는 스토리지 어레이로 읽는 방법을 보여줍니다. 파일에 각각 3비트 벡터가 포함된 8개의 줄이 있다고 가정합니다. 벡터는 000에서 시작하여 111로 증가하며 각 기호는 $readmemb() 작업을 사용하여 이진으로 해석됩니다. 스토리지 어레이 "메모리" reg 유형의 8 x 3 어레이로 선언됩니다. $readmemb() 작업은 파일의 각 줄을 "메모리" 내의 각 3비트 벡터 위치에 삽입합니다. 데이터가 저장되는 방식을 설명하기 위해 이 예제에는 저장 요소의 내용을 기록에 인쇄하는 두 번째 절차 블록도 포함되어 있습니다.

 

reg[2:0] memory[7:0];

initial
begin: Read_Block
  $readmemb("Data_in.txt", memory);
end

initial
begin: Print_Block

$display("printing memory %b", memory[0]);   // This will print “000”
$display("printing memory %b", memory[1]);   // This will print “001”
$display("printing memory %b", memory[2]);   // This will print “010”
$display("printing memory %b", memory[3]);   // This will print “011”
$display("printing memory %b", memory[4]);   // This will print “100”
$display("printing memory %b", memory[5]);   // This will print “101”
$display("printing memory %b", memory[6]);   // This will print “110”
$display("printing memory %b", memory[7]);   // This will print “111”

end

 

 

시뮬레이션 제어 및 모니터링

Verilog는 또한 일련의 시뮬레이션 제어 및 모니터링 작업을 제공합니다. 다음은 이 그룹에서 가장 일반적으로 사용되는 작업입니다.

Task Description
$finish() Finishes simulation and exits.
$stop() Halts the simulation and enters an interactive debug mode.
$time() Returns the current simulation time as a 64-bit vector.
$stime() Returns the current simulation time as a 32-bit integer.
$realtime() Returns the current simulation time as a 32-bit real number.
$timeformat() Controls the format used by the %t code in print statements.
The arguments are: (<unit>, <precision>, <suffix>, <min_field_width>)
where:
<unit>
0 = 1 s
-1 = 100 ms
-2 = 10 ms
-3 = 1 ms
-4 = 100 μs
-5 = 10 μs
-6 = 1 μs
-7 = 100 ns
-8 = 10 ns
-9 = 1 ns
-10 = 100 ps
-11 = 10ps
-12 = 1ps
-13 = 100fs
-14 = 10fs
-15 = 1fs
<precision> The number of decimal points to display.
<suffix> A string to be appended to time to indicate units.
<min_field_width> The minimum number of characters to display

 

다음은 이러한 작업을 사용할 수 있는 방법의 예를 보여줍니다.

initial
begin
  $timeformat (-9, 2, "ns", 10);
  $display("Stimulus starting at time: %t", $time);

 

#10 A_TB=0; B_TB=0; C_TB=0;
#10 A_TB=0; B_TB=0; C_TB=1;
#10 A_TB=0; B_TB=1; C_TB=0;
#10 A_TB=0; B_TB=1; C_TB=1;
#10 A_TB=1; B_TB=0; C_TB=0;
#10 A_TB=1; B_TB=0; C_TB=1;
#10 A_TB=1; B_TB=1; C_TB=0;
#10 A_TB=1; B_TB=1; C_TB=1;

 

$display("Simulation stopping at time: %t", $time);
end

 

이 예에서는 시뮬레이터 결과에 다음 명령문이 인쇄됩니다.

Stimulus starting at time: 0.00ns
Simulation stopping at time: 80.00ns

반응형
반응형

조건부 프로그래밍 구조

Verilog에서 절차 블록이 제공하는 보다 강력한 기능 중 하나는 if-else 결정, case 문 및 루프와 같은 조건부 프로그래밍 구성을 사용하는 기능입니다. 이러한 구성은 절차 블록 내에서만 사용할 수 있으며 조합 논리와 순차 논리를 모두 모델링하는 데 사용할 수 있습니다.

 

if-else

if-else 문은 부울 조건을 기반으로 조건부 신호를 할당하는 방법을 제공합니다. 문의 if 부분 다음에 TRUE로 평가되면 그 뒤에 나열된 신호 할당이 수행되도록 하는 부울 조건이 옵니다. 부울 조건이 FALSE로 평가되면 else 부분 뒤에 나열된 명령문이 실행됩니다. 여러 명령문이 if 또는 else 부분에서 실행되어야 하는 경우 명령문 그룹 키워드 begin/end를 사용해야 합니다. 하나의 명령문만 실행해야 하는 경우 명령문 그룹 키워드가 필요하지 않습니다. 문의 else 부분은 필요하지 않으며 생략하면 부울 조건이 FALSE로 평가될 때 할당이 수행되지 않습니다. if-else 문의 구문은 다음과 같습니다.

 

if (<boolean_condition>)
true_statement

else
false_statement

여러 true/false 문이 있는 if-else 문의 구문은 다음과 같습니다.
if (<boolean_condition>)
begin
  true_statement_1
  true_statement_2
end
else
begin
  false_statement_1
  false_statement_2
end

 

둘 이상의 부울 조건이 필요한 경우 이전 if 문의 else 절 내에 추가 if-else 문을 포함할 수 있습니다. 다음은 두 개의 부울 조건을 구현하는 if-else 문의 예를 보여줍니다.

 

if (<boolean_condition_1>)
true_statement_1

else if (<boolean_condition_2>)
true_statement_2

else
false_statement

 

if-else 문을 사용하여 조합 논리 회로의 동작을 설명하는 방법을 살펴보겠습니다.

조합 논리 회로는 출력이 입력의 순시 값에 의존하는 회로임을 상기하십시오. 이 동작은 회로에 대한 모든 입력을 always 블록의 감지 목록에 배치하고 블로킹 할당을 사용하여 모델링할 수 있습니다.

이 접근 방식을 사용하면 신호감지 목록의 입력이 변경되면 블로킹이 트리거되고 할당이 즉시 수행됩니다.

 

다음은 절차적 always 블록 내에서 if-else 문을 사용하여 3입력 조합 논리 회로를 모델링하는 방법을 보여줍니다.

 

 

case

케이스 문은 부울 조건을 기반으로 신호 할당을 모델링하는 또 다른 기술입니다.

if-else 문과 마찬가지로 case 문은 절차 블록 내에서만 사용할 수 있습니다. 명령문은 case 키워드로 시작하고 그 뒤에 괄호로 묶인 할당의 기반이 되는 입력 신호 이름이 옵니다. case 문은 괄호 안에 신호를 연결하여 여러 입력 신호 이름을 기반으로 할 수 있습니다. 그런 다음 해당 할당이 뒤따르는 일련의 입력 코드가 나열됩니다. 키워드 default는 명시적으로 나열되지 않은 입력 코드에 대해 원하는 신호 할당을 제공하는 데 사용할 수 있습니다. 여러 입력 조건에 동일한 지정문이 있는 경우 공간을 절약하기 위해 동일한 줄에 쉼표로 구분하여 나열할 수 있습니다. endcase 키워드는 case 문의 끝을 나타내는 데 사용됩니다. 다음은 case 문의 구문입니다.

 

case (<input_name>)
input_val_1
: statement_1
input_val_2
: statement_2
       :
input_val_n
: statement_n

default    : default_statement

endcase

 

 

다음은 절차 블록 내에서 case 문을 사용하여 3입력 조합 논리 회로를 모델링하는 방법을 보여줍니다. 이 예에서 입력은 스칼라이므로 입력 값이 3비트 벡터로 나열될 수 있도록 연결해야 합니다.

 

이 예에서는 세 가지 버전의 모델이 제공됩니다. 첫 번째는 모든 이진 입력 코드를 명시적으로 나열합니다. 이 접근 방식은 진리표 형식을 반영하기 때문에 더 읽기 쉽습니다. 두 번째 접근 방식은 하나의 출력에 해당하는 입력 코드만 나열하고 기본 절을 사용하여 다른 모든 입력 코드를 처리합니다. 세 번째 접근 방식은 쉼표로 구분된 계열을 사용하여 같은 줄에 동일한 할당을 가진 여러 입력 코드를 나열하는 방법을 보여줍니다.

 

 

if-else 문은 case 문 안에 포함될 수 있고 반대로 case 문은 if-else 문 안에 포함될 수 있습니다.

 

casez casex

Verilog는 입력 조건에서 don't care를 지원하는 두 개의 추가 case 문을 제공합니다. casez 문은 기호 ? Z는 상관 없음을 나타냅니다. casex 문은 X don't care로 해석하여 casez 문을 확장합니다. 입력 코드에 don't care를 사용하면 의도하지 않은 로직이 생기기 쉽기 때문에 casez casex 문을 사용할 때 주의가 필요하다.

 

forever 루프

Verilog 내의 루프는 반복 할당을 무한히 수행하는 메커니즘을 제공합니다. 이것은 클록 또는 기타 주기적 신호와 같은 자극을 생성하기 위한 테스트 벤치에서 유용합니다. 우리는 이미 always 블록 형태의 반복 구조를 다루었습니다. 항상 블록은 시작 조건이 있는 루프를 제공합니다. Verilog는 보다 정교한 동작을 모델링하기 위해 추가 루핑 구조를 제공합니다.

 

모든 루핑 구문은 절차 블록과 함께 있어야 합니다.

가장 간단한 루프 구성은 forever 루프입니다. 다른 조건부 프로그래밍 구성과 마찬가지로 여러 문이 forever 루프와 연결된 경우 문 그룹으로 묶어야 합니다. 하나의 명령문만 사용하는 경우 명령문 그룹이 필요하지 않습니다. 초기 블록 내의 forever 루프는 신호감지 루프가 없는 항상 루프와 동일한 동작을 제공합니다. forever 루프 내에서 시간 단계 이벤트 또는 지연을 제공하는 것이 중요합니다. 그렇지 않으면 시뮬레이션이 중단됩니다. 다음은 Verilog의 영원히 루프 구문입니다.

 

forever
begin
  statement_1
  statement_2
      :
  statement_n
end

 

10ns 단위의 주기로 클록 신호(CLK)를 생성하는 forever 루프의 다음 예를 고려하십시오. 이 예에서 forever 루프는 초기 블록 내에 포함됩니다. 이것은 시뮬레이션 시작 시 CLK의 초기 값이 0으로 설정되도록 합니다. forever 루프에 들어가면 무기한 실행됩니다. forever 키워드 뒤에 문이 하나만 있기 때문에 문 그룹(, 시작/종료)이 필요하지 않습니다.

 

initial
begin
  CLK
= 0;
  forever
    #10 CLK
= ~CLK;
end

 

while 루프

while 루프는 실행을 제어하는 부울 조건이 있는 루프 구조를 제공합니다. 루프는 부울 조건이 true로 평가되는 동안에만 실행됩니다. 다음은 Verilog while 루프의 구문입니다.

 

while (<boolean_condition>)
begin
  statement_1
  statement_2
     :
  statement_n
end

 

EN = 1인 동안 10ns 단위의 주기로 클록 신호(CLK)를 생성하는 루프의 이전 예를 구현해 보겠습니다. while 루프의 TRUE 부울 조건은 EN = 1입니다. EN = 0일 때 while 루프를 건너뜁니다. 루프가 비활성화되면 CLK는 마지막으로 할당된 값을 유지합니다.

 

initial
begin
  CLK =
0;
  while (EN ==
1)
  #10 CLK =
~CLK;
end

 

repeat 반복

repeat 루프는 고정된 횟수만큼 실행되는 루핑 구조를 제공합니다. 다음은 Verilog 반복 루프의 구문입니다.

 

repeat (<number_of_loops>)
begin
  statement_1
  statement_2
      :
  statement_n
end

 

10ns 단위의 주기로 클록 신호(CLK)를 생성하는 루프의 이전 예제를 구현해 보겠습니다. , 이번에는 반복 루프를 사용하여 10개의 클록 전환 또는 5개의 전체 CLK 주기만 생성할 것입니다.

 

initial
begin
  CLK
= 0;
  repeat (10)
    #10 CLK =
~CLK;
end

 

for 루프

for 루프는 내부 변수를 자동으로 업데이트할 수 있는 루프를 생성하는 기능을 제공합니다. for 루프 내의 루프 변수는 단계 할당에 따라 루프를 통해 매번 변경됩니다. 루프 변수의 시작 값은 초기 할당을 사용하여 제공됩니다. 루프 변수와 연결된 부울 조건이 TRUE인 한 루프가 실행됩니다. 다음은 Verilog for 루프의 구문입니다.

 

for (<initial_assignment>; <Boolean_condition>; <step_assignment>)
begin
  statement_1
  statement_2
      :
  statement_n
end

 

다음은 루프 변수를 이용하여 간단한 카운터를 생성하는 예이다. 루프 변수 i는 이 블록 이전에 정수로 선언되었습니다. 신호 Count도 정수 유형입니다. 루프 변수는 0에서 시작하여 루프를 통과할 때마다 1씩 증가합니다. 루프는 i < 15 또는 총 16배 동안 실행됩니다. For 루프를 사용하면 블록 내에서 신호 할당에 루프 변수를 사용할 수 있습니다.

 

initial
begin
  for (i
=0; i<15; i=i+1)
    #10 Count
= i;
end

 

disable

Verilog는 키워드 disable을 사용하여 루프를 중지하는 기능을 제공합니다. 비활성화 기능은 명명된 명령문 그룹에서만 작동합니다. 비활성화 기능은 일반적으로 특정 고정 시간 후 또는 제어 신호에 의해 트리거되는 if-else 또는 case 문과 같은 조건부 구성 내에서 사용됩니다.

클록 신호(CLK)를 생성하지만 인에이블(EN)이 어설션된 경우에만 발생하는 다음의 무한 루프 예를 고려하십시오. EN = 0일 때 루프가 비활성화되고 시뮬레이션이 종료됩니다.

 

initial
begin
  CLK
= 0;
  forever
    begin: loop_ex
    if (EN ==
1)
      #10 CLK =
~CLK;
    else
      disable loop_ex; // The group name to be disabled comes after the keyword
  end
end

 

 

반응형
반응형

절차적 블록 내에서 사용할 수 있는 두 가지 종류의 신호 할당, 블로킹(blocking) 및 논블로킹(non-blocking)이 있습니다.

 

블로킹 할당

블로킹 할당은 = 기호로 표시되며 각 명령문의 평가 및 할당은 즉시 수행됩니다. 블록 내의 각 할당은 병렬로 실행됩니다.

 

이 동작이 시스템에 대한 모든 입력을 포함하는 감지 목록과 결합될 때 이 접근 방식은 합성 가능한 조합 논리 회로를 모델링할 수 있습니다.

 

이 접근 방식은 절차 블록 외부의 연속 할당과 동일한 기능을 제공합니다. 설계자가 연속 할당 대신 블로킹 할당을 사용하는 이유는 Verilog 절차 블록 내에서 고급 프로그래밍 구성이 지원되기 때문입니다.

 

다음은 조합 논리 회로를 모델링하기 위해 절차 블록 내에서 블로킹 할당을 사용하는 방법을 보여줍니다.

 

 

논블로킹 할당

논블로킹 할당은 <= 기호로 표시됩니다. 논블로킹 할당을 사용할 때 대상 신호에 대한 할당은 절차 블록이 끝날 때까지 연기됩니다. 이렇게 하면 목록을 통해 중간 할당을 계단식으로 연결하지 않고도 할당이 블록에 나열된 순서대로 실행될 수 있습니다. 이 동작이 클록 신호의 차단을 트리거하는 것과 결합될 때 이 접근 방식은 합성 가능한 순차 논리 회로를 모델링할 수 있습니다.

 

다음은 논블로킹 할당을 사용하여 순차 논리 회로를 모델링하는 예를 보여줍니다.

 

 

블로킹 할당과 논블로킹 할당의 차이는 미묘하며 종종 Verilog를 처음 배울 때 파악하기 가장 어려운 개념 중 하나입니다. 혼란의 원인 중 하나는 단일 할당 또는 신호 상호 의존성이 없는 할당 목록을 포함할 때 블로킹 및 논블로킹 할당이 동일한 결과를 생성할 수 있다는 사실에서 비롯됩니다.

 

신호 상호 의존성은 할당의 대상(, 할당의 LHS에서)인 신호가 후속 명령문에서 인수(, 할당의 RHS에서)로 사용되는 경우를 나타냅니다.

 

다음은 블로킹 또는 논블로킹 할당이 사용되는지 여부에 관계없이 동일한 결과를 생성하는 두 가지 모델을 보여줍니다.

 

 

절차 블록 내의 명령문 목록에 신호 상호 의존성이 있는 경우 블로킹 및 논블로킹 할당은 다른 동작을 갖습니다.

 

다음은 신호 상호 의존성이 블로킹 할당과 논블로킹 할당 간에 어떻게 다른 동작을 유발하는지 보여줍니다. 이 예에서 모든 입력은 조합 논리를 모델링할 목적으로 신호감지 목록에 나열됩니다.

 

블로킹 대 논블로킹 할당을 사용할 때 다른 동작

이 예에는 신호의 상호 의존성이 있으며 모든 입력이 감지 목록에 나열됩니다. 신호감지 목록의 모든 입력을 나열함으로써 입력이 변경될 때마다 출력이 업데이트되도록 조합 논리를 모델링하는 것이 목적입니다.

 

 

두 경우 모두 명령문 1(n1에 대한 할당)은 동일한 결과를 생성합니다. 이는 할당이 입력 A B에만 의존하기 때문입니다. A B가 감지 목록에 나열되기 때문에 이들에 대한 변경은 블록을 트리거하고 현재 값은 n1에 대한 할당에 사용됩니다.

그러나 명령문 2(S에 대한 할당)는 신호의 상호 의존성을 포함하며 두 경우 모두 동일한 결과를 생성하지 않습니다.

블로킹 할당 사례(=): 블로킹 할당이 즉시 발생합니다. 이것은 명령문 1에서 n1에 대한 할당이 즉시 발생하고 명령문 2에서 n1의 업데이트된 값이 사용됨을 의미합니다. 민감도 목록의 모든 입력을 나열하는 것과 함께 사용되는 경우 이 접근 방식은 조합 논리를 성공적으로 모델링합니다.

 

논블로킹 할당 사례(<=): 논블로킹 할당은 절차 블록의 끝에서 발생합니다. 이것은 명령문 1 n1에 대한 할당이 명령문 2의 할당보다 먼저 발생하지 않음을 의미합니다. 명령문 2에서 사용된 n1의 값은 블록이 트리거될 때 n1의 값이 될 것이며 블록 내에 할당된 n1의 새로운 값이 아닙니다.  다시 말해서, 문장 2에서 사용된 n1의 값은 블록이 트리거된 "이전" 시간의 n1 또는 n1 "마지막" 값이 됩니다. 이것은 조합 논리를 모델링하지 않습니다.

 

 

다음은 신호의 상호 의존성이 블록 할당과 논블록 할당 간에 다른 동작을 일으키는 또 다른 경우를 보여줍니다. 이 예에서 절차 블록은 순차 논리의 두 단계를 모델링할 목적으로 클록 신호의 상승 에지에 의해 트리거됩니다.

 

 

 

이러한 절차적 할당의 동작은 혼란스러울 수 있지만 정확하고 합성 가능한 모델을 간단하게 만들 수 있는 두 가지 설계 지침이 있습니다.

1. 조합 논리를 모델링할 때 블로킹 할당을 사용하고 신호감지 목록에 모든 입력을 나열합니다.

2. 순차 논리를 모델링할 때 논블로킹 할당을 사용하고 신호감지 목록에 클록 및 리셋 라인(해당되는 경우)만 나열합니다.

 

명령문 그룹

명령문 그룹은 블록의 명령문이 처리되는 방식을 나타냅니다. Verilogbegin/end fork/join이라는 두 가지 유형의 명령문 그룹을 지원합니다.

begin/end를 사용할 때 그룹 내에 포함된 모든 명령문은 나열된 순서대로 평가됩니다.

fork/join을 사용할 때 그룹 내에 포함된 모든 명령문은 병렬로 평가됩니다.

procedural block 내에 하나의 statement만 있는 경우 statement group은 필요하지 않습니다.

절차 블록의 여러 명령문에는 명령문 그룹이 필요합니다. 명령문 그룹은 ":"가 앞에 오는 첫 번째 키워드 뒤에 추가되는 선택적 이름을 포함할 수 있습니다.

 

 

로컬변수

지역 변수는 절차 블록 내에서 선언할 수 있습니다. 명령문 그룹의 이름을 지정해야 하며 변수는 블록 외부에서 볼 수 없습니다. 변수는 변수 유형만 가능합니다.

 

initial
begin: stim_block  // it is required to name the block when declaring local variables
  integer i;       // local variables can only be of variable type
  I = 2;
end

반응형
반응형

VHDL의 조합 논리 회로 설계 및 동시 코딩

조합 논리 회로는 논리 연산자와 VHDL 문을 사용하여 구현할 수 있습니다. 논리 회로 구현에서 조건식을 사용할 수 있는 경우 VHDL when select가 구현에 사용됩니다. 조합 회로는 동시 코드를 통해 구현됩니다.

 

"when" "select"

VHDL when select는 동시 VHDL 코드에서 사용할 수 있습니다. 이러한 명령문은 순차, , 클록된 프로그램 단위에서 사용되지 않습니다.

 

조합 회로의 구현을 선택할 때 VHDL 문을 사용할 수 있습니다. 이러한 명령문은 논리 회로의 조건부 구현에 사용됩니다. when 문의 구문은 다음과 같습니다.

 

<signal object> <= <statement> when <condition> else

                         <statement> when <condition> else

                                           

                         <statement> when <condition> else

                         <statement>;

 

when select 문은 서로 유사합니다. 구현 구문만 다릅니다. select 문의 구문은 다음과 같습니다.

 

with <condition> select

<signal object> <= <statement> when <condition>,

                         <statement> when <condition>,

                                            

                         <statement> when others;

 

다음 예제는 논리 연산자를 사용하여 부울 함수 f(x, y, z) = x'y' + y'z를 구현합니다.

부울 함수 f(x, y, z) = x'y' + y'z는 다음을 사용하여 구현할 수 있습니다.

f <= (not(x) not(y)) 또는 (not(y) z)와 같은 논리 연산자

부울 함수 f(x, y, z) = x'y' + y'z를 구현하는 VHDL 프로그램은 다음과 같습니다.

 

entity f_function is
port
(

x, y, z: in bit;

f: out bit );
end entity;
architecture
logic_flow of f_function is
begin
  f<=(not(x) and not(y)) or (not(y) and z);
end architecture;

 

다음은 부울함수의 진리표를 보여주고 있습니다.

x y z f (x, y, z)
0 0 0 1
0 0 1 1
0 1 0 0
0 1 1 0
1 0 0 0
1 0 1 1
1 1 0 0
1 1 1 0

 

 

whenwith문을 사용하여 부울함수를 VHDL로 프로그램하면 다음과 같습니다.

 

f <= ‘1’ when(x = ‘0’ and y = ‘0’ and z = ‘0’) else

     ‘1’ when(x = ‘0’ and y = ‘0’ and z = ‘1’) else

‘1’ when(x = ‘1’ and y = ‘0’ and z = ‘1’) else

     ‘0’

 

with(x&y&z) select

f <= ‘1’ when “000”,

     ‘1’ when “001”,

     ‘1’ when “101”,

     ‘0’ when others;

 

아래 함수를 VHDL로 프로그램하면 다음과 같습니다.

entity fx_function is
port
( x: in integer;
     y: out integer range 0 to 4);
end entity;
architecture logic_flow of fx_function is
begin
with
x select
  y <= 2 when 1 | 2,
       4 when 3 to 6,
       0 when others;
end architecture;

 

Generate

VHDLgenerate는 동시 문입니다. 프로그램 세그먼트의 여러 인스턴스를 생성하는 데 사용됩니다. 생성 문에는 무조건 generate과 조건 generate라는 두 가지 다른 형식이 있습니다. 이 양식을 별도로 살펴보겠습니다.

 

무조건 generate

이름에서 알 수 있듯이 무조건 생성에는 조건부 부분이 없습니다. 구문은 다음과 같습니다.

 

Label : for parameter in number  -- range generate

[declarative part

begin]
Statements

end generate[Label] ;

 

Label의 사용은 generate 문에서 필수이며, 단어 begin generate 문에서 선언적 부분을 사용할 수 있는 경우에 사용됩니다.

 

다음은 generate문의 예제입니다.

Label 1 : for indx in 0 to 3 generate

             y(indx) <= x(indx) xor x(indx + 1)

       end generate;

 

위의 generate문을 다음과 같습니다.

y(0) <= x(0) xor x(1);

y(1) <= x(1) xor x(2);

y(2) <= x(2) xor x(3);

y(3) <= x(3) xor x(4);

 

다음 VHDL 문을 사용하여 벡터 x의 내용을 뒤집을 수 있습니다. 여기서 x, y8비트 벡터입니다.

 

entity reverse_vector is
port
( x_vec: in bit_vector(7 downto 0);
     y_rvec: out bit_vector(7 downto 0));
end entity;
architecture logic_flow of reverse_vector is
begin
reverse: for indx in 0 to 7 generate
          y_rvec(indx)<=x_vec(7-indx);
end generate;
end architecture;

 

조건 generate

조건 generate의 구문은 다음과 같습니다.

Label : if condition generate

           [declarative_part

       begin]

           Statement

       end generate[Label];

 

상수 양의 정수를 확인하고 짝수인지 홀수인지 감지하는 VHDL 문을 조건 generate로 작성하면 다음과 같습니다.

 

entity even_odd_detector is
port(
EvenFlag: out bit);
end entity;
architecture logic_flow of even_odd_detector is
constant
number: positive:=10001;   -- 31-bit positive integer
begin
  EvenDetector: if ((number mod 2)=0) generate
    EvenFlag<=1;
  end generate;

OddDetector: if ((number mod 2)=1) generate
EvenFlag<=0;

end generate;

end architecture;

 

반응형

+ Recent posts