Операторы блокирующего и неблокирующего присваивания



 

В языке Verilog существуют два типа операторов присвоения: блокирующее blocking(=) и неблокирующее nonblocking(<=).

Для того чтобы понять разницу между данными типами операторов присвоения, необходимо рассмотреть принцип работы Verilog симулятора. В реальном устройстве

(например – цифровой схеме), которая моделируется с помощью языка Verilog, события могут происходить одновременно – при изменении входного сигнала во всех элементах, связанных с ним, начинаются процессы. Они протекают одновременно и приводят к соответствующим изменениям выходных сигналов. Моделирующая программа не может выполнять события одновременно, она создает списки событий, которые будут выполняться

последовательно. Когда все события из списка выполнены, симулятор переходит к обработке

следующего временного шага – увеличивает текущее время моделирования на временной интервал (второй параметр в директиве `timescale) и выполняет обработку списка событий, которые должны произойти на данном шаге. Рассмотрим события происходящие«одновременно» – т.е. на одном временном шаге моделирования.

Допустим, имеется следующий набор команд:

 

 

1 2 3 always@(posedgeCLK)a=b;   always@(posedgeCLK)b=a;

 

 

В данном примере переменные а и b – одноразрядные регистры, к моменту появления положительного фронта тактового сигнала CLK хранящие значения а==0 и b==1. Какое же значение будут иметь эти переменные после выполнения операции присвоения? Это зависит от того, в какой последовательности операции присваивания попадут в список. То есть, поведение такой конструкции зависит от порядка следования операторов в программе. Это означает, что либо обе эти переменные будут равны 0, либо обе равны 1 (в нашем примере – 1). Операцияблокирующего присвоения (=) блокирует исполнение других последовательных операций до тех пор, пока она не будет выполнена. Использование операции блокирующего присвоения в параллельно исполняемых блоках нежелательно. Но если в блоке необходимо обеспечить последовательное выполнение операторов, следует использовать данный тип присвоения.

Следующий фрагмент программы гарантирует обнуление переменных a и b по переднему фронту сигнала CLK:

 

 

1 2 3 4 5 always@(posedgeCLK) begin a=0; b=a; end

 

Если в предыдущих примерах использовать оператор неблокирующего присвоения (<=), то поведение устройства изменится:

 

 

1 2 3 always@(posedgeCLK)a<=b;   always@(posedgeCLK)b<=a;

 

 

В данном случае в список событий, исполняемом на текущем временном шаге моделирования после изменения сигнала CLK, обе операции будут помещены как параллельно исполняемые, т.е. переменные a и b обменяются своими значениями. После прохождения переднего фронта сигнала CLK значения переменных будут следующими: а==1 b==0. Последовательность записи a<=b; b<=a; или b<=a; a<=b; в данном случае не имеет значения, т.к. события моделируются одновременно.

 

Системные функции языка Verilog

 

Язык Verilog предоставляет программисту специальные возможности для управления и анализа результатов моделирования. Эти возможности реализованы в виде системных функций симулятора. Следует помнить, что при синтезе системные функции игнорируются.

Благодаря наличию механизма PLI, обеспечивающего подключение исполняемой программы (написанной либо пользователем, либо третьей стороной) к тестовым файлам, число системных функций и задач, которые могут выполняться с их помощью, очень велико. Основное назначение системных функций – сбор и анализ информации, взаимодействие с операционной системой. Признаком системной функции является знак $. Перечислим наиболее популярные системные функции:

 

$finish– завершение процесса моделирования;

$stop– переход в интерактивный режим;

$display, $write– вывод данных в stdout (данные дублируются в файл протокола), поведение такой функции соответствует функции printf языка C (вывод форматированной строки с поддержкой дополнительных форматов, например, %b -бинарный), или процедуре write языка Паскаль с разделенными «,» аргументами. Функция $display завершает вывод строки командой «перевод строки»;

$monitor– отслеживает изменения аргументов и в конце каждого временного шага моделирования отображает текущие результаты (если были обнаружены изменения значений сигналов). Формат данной функции – как у $display;

$readmemb, $readmemh– обеспечивают считывание данных (в двоичном или шестнадцатеричном формате) из файла в память. Формат файла очень простой – в каждой строке указывается слово заданной разрядности, или указатель адреса (конструкция @<адрес загрузки>). Данную функцию удобно применять для моделирования ПЗУ;

$system– выполняет команду операционной системы (вызов функции языка С system()).

 

Для выполнения файловых операций используются функции $fopen, $fclose, $fwrite,$fmonitor. Они позволяют сохранять передаваемые данные в файлах. Функции $dumpfile,$dumpvars позволяют записывать изменения сигналов тестируемого модуля, всего проекта или его составных частей, в файле специального формата для дальнейшего анализа. Очень полезные и эффективные функции для обработки данных.

Функция $time– возвращает значение текущего времени моделирования.

Это небольшой перечень стандартных функций. Их полный список указан в документации к моделирующей программе.

 

Арифметические устройства

 

К арифметическим устройствам относятся преобразователи, выполняющие арифметические действия (сложение, вычитание, умножение) над входными данными.

На рисунке 1 представлена схема полного одноразрядного сумматора и его графическое изображение.

 

Рисунок 2. Схема полного одноразрядного сумматора и его графическое изображение.

 

Назначение сигналов сумматора следующее: a и b – входные сигналы (слагаемые), Сi –вход переноса, s– выходной сигнал (сумма), Со– выход переноса. Таблица истинности одноразрядного сумматора выглядит следующим образом:

Таблица истинности

a b Сi Со s
0 0 0 0 0
0 0 1 0 1
0 1 0 0 1
0 1 1 1 0
1 0 0 0 1
1 0 1 1 0
1 1 0 1 0
1 1 1 1 1

 

Для создания сумматоров большей разрядности используется каскадное соединение одноразрядных сумматоров. Например, на рисунке 2 показан полный четырехразрядный сумматор с последовательным переносом, состоящий из четырех одноразрядных сумматоров.

 

Рисунок 3. Полный четырехразрядный сумматор с последовательным переносом.

 

Пример выполнения операции умножения двух 4-разрядных чисел в двоичном виде показан на рисунке 3. На рисунке 4 показана структурная схема реализации такого перемножителя. Он состоит из логических элементов «И» и полных одноразрядных сумматоров (FA).

 

Рисунок 4.Операция умножения двух 4-разрядных чисел.

 

Рисунок 5.Структурная схема перемножителя двух 4-разрядных чисел.

 

Данные два компонента используются как базовые для создания различных арифметических или арифметико-логических устройств (АЛУ).

 

Порядок выполнения работы.

 

В лабораторной работе мы создадим проект, описывающий работу полного четырехразрядного сумматора, изображенного на рисунке 3. Для исходного модуля используется структурное описание. Для проверки сумматора создадим эталонную модель, использующую поведенческое описание, и тестовый файл (test-bench). Для этого:

1. Создайте новый проект в среде ModelSim.

2. Создайте исходный файл сумматора на структурном уровне:

 

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 module my_sum(Ain,Bin,Ci,Sout,Co);   input Ain,Bin,Ci;   output Sout,Co;   wire[3:0]Ain,Bin,Sout,C;   wire Ci,Co;   bitsum sum1(Ain[0],Bin[0],Sout[0],Ci,C[0]);   bitsum sum2(Ain[1],Bin[1],Sout[1],C[0],C[1]);   bitsum sum3(Ain[2],Bin[2],Sout[2],C[1],C[2]);   bitsum sum4(Ain[3],Bin[3],Sout[3],C[2],C[3]);   assignCo=C[3];   endmodule

 

Обратите внимание на подключение готовых модулей в данном файле.

3. Создайте исходный файл эталонного сумматора на поведенческом уровне:

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 module ref_sum(Ain,Bin,Ci,Sout,Co);   input Ain,Bin,Ci;   output Sout,Co;   wire[3:0]Sout,Ain,Bin;   reg[4:0]S;   always@(Ain,Bin,Ci)   S=Ain+Bin+Ci;   assign Sout=S[3:0];   assign Co=S[4];   endmodule

 

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 module bitsum(A,B,S,Cin,Cout);   inputA,B,Cin;   outputS,Cout;   wireA,B,S,Res;   wire c1,c2,Cin,Cout;   xor(Res,A,B);   and(c1,A,B);   xor(S,Cin,Res);   and(c2,Cin,Res);   or(Cout,c1,c2);   endmodule

 

 

4. Создайте тестовый файл для подачи входных сигналов и сравнения работы двух модулей:

 

 

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 module test_sum;// Top Level Testbench   wire Ci,cm,cr; wire[3:0]Ain,Bin; reg[3:0]Ain_r,Bin_r; regCi_r; wire[3:0]res_my,res_ref;   my_summy_block(Ain,Bin,Ci,res_my,cm);   ref_sumref_block(Ain,Bin,Ci,res_ref,cr);   initial begin $display("\t\t&nbsp;&nbsp;&nbsp;&nbsp; Time&nbsp;&nbsp;&nbsp;&nbsp; Ain Bin Cires_my cm res_refcr"); $monitor($time,,,,,Ain,,,,,Bin,,,,,Ci,,,,,res_my,,,,,,,,cm,,,,,,,res_ref,,,,,,,cr); #400 $finish; end   initial begin Ain_r=1; #50 Ain_r = 5; #50 Ain_r = 1; #50 Ain_r = 5; #50 Ain_r = 1; #50 Ain_r = 5; #50 Ain_r = 1; #50 Ain_r = 5; end   initial begin Bin_r=2; #100 Bin_r = 10; #100 Bin_r = 2; #100 Bin_r = 10; end   initial begin Ci_r=1'b0; #200 Ci_r = 1'b1; end   assign Ain=Ain_r;   assign Bin=Bin_r;   assign Ci=Ci_r;   endmodule

 

Обратите внимание на подключение модулей в данном файле и использование системных функций.

 

5. Скомпилируйте все программы. После успешной компиляции перейдите в режим моделирования. В качестве основного файла для моделирования укажите тестовый файл.

6. Отройте графическое окно и добавьте в него проверяемые сигналы. Запустите проект на моделирование. Ответьте НЕТна вопрос, хотите ли Вы закончить работу с симулятором. Проверьте полученные результаты:

 

7. Объясните полученный результат. Выйдите из режима моделирования.

Самостоятельная работа.

Спроектировать следующие арифметико-логические устройства (входные данные – восьмиразрядные):

Вариант 1.АЛУ с функциями: А+В, АxorВ, А-1, А-В.

Вариант 2.АЛУ с функциями: А+В, А*В, А-1, В.

Вариант 3.АЛУ с функциями: А+(А+В), А, А+1, А-В-1.

Вариант 4.АЛУ с функциями: not(А+В), not(А*В), А+В+1, (А + notВ)+1.

Вариант 5.АЛУ с функциями: АxorВ, А*В+(А+notВ), А, В.

Вариант 6: Спроектировать умножитель с накоплением (операция МАС).

 

Для проверки работы устройства создать тестовый файл.

 

ЛР6> Модернизация процессорного устройства

Статьи по теме

1. ЛР1> Реализация последовательного умножителя двух 8-разрядных чисел

2. ЛР2> Работа с блоками памяти в Quartus II

3. ЛР3 > Построение конечных автоматов

4. ЛР4> Арифметические устройства и перемножители

5. ЛР8 > Разработка простого процессорного модуля на Verilog

6. ЛР7> Специализированные модули. Реализация КИХ-фильтра

7. ЛР1> Разработка процессорного ядра NiosII и программного обеспечения для него


Дата добавления: 2018-04-04; просмотров: 1220; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!