Дизайн СБИС - Введение в Verilog

Verilog - это ЯЗЫК ОПИСАНИЯ АППАРАТНОГО ОБЕСПЕЧЕНИЯ (HDL). Это язык, используемый для описания цифровой системы, такой как сетевой коммутатор, микропроцессор, память или триггер. Это означает, что с помощью HDL мы можем описать любое цифровое оборудование на любом уровне. Проекты, описанные в HDL, не зависят от технологии, очень просты в разработке и отладке и обычно более полезны, чем схемы, особенно для больших схем.

Verilog поддерживает дизайн на многих уровнях абстракции. Основные три -

  • Поведенческий уровень
  • Уровень регистрации-передачи
  • Уровень ворот

Поведенческий уровень

Этот уровень описывает систему с помощью параллельных алгоритмов (поведенческих). Каждый алгоритм является последовательным, что означает, что он состоит из набора инструкций, которые выполняются одна за другой. Функции, задачи и блоки - это основные элементы. Нет никакого отношения к структурной реализации дизайна.

Регистр-Уровень передачи

Проекты, использующие уровень передачи регистров, определяют характеристики схемы, использующей операции и передачу данных между регистрами. Современное определение RTL-кода: «Любой синтезируемый код называется RTL-кодом».

Уровень ворот

На логическом уровне характеристики системы описываются логическими связями и их временными характеристиками. Все сигналы дискретные. Они могут иметь только определенные логические значения («0», «1», «X», «Z»). Используемые операции - это предопределенные логические примитивы (базовые вентили). Моделирование на уровне ворот может быть неправильной идеей для логического проектирования. Код уровня ворот генерируется с использованием таких инструментов, как инструменты синтеза, а его список соединений используется для моделирования уровня ворот и для бэкэнда.

Лексические токены

Исходные текстовые файлы на языке Verilog представляют собой поток лексических токенов. Токен состоит из одного или нескольких символов, и каждый отдельный символ находится ровно в одном токене.

Основные лексические токены, используемые Verilog HDL, аналогичны токенам в языке программирования C. Verilog чувствителен к регистру. Все ключевые слова в нижнем регистре.

Белое пространство

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

Символы пробела - это пустое пространство, табуляция, возврат каретки, новая строка и подача формы.

Комментарии

Есть две формы для представления комментариев

  • 1) Однострочные комментарии начинаются с токена // и заканчиваются возвратом каретки.

Пример: // это однострочный синтаксис

  • 2) Многострочные комментарии начинаются с токена / * и заканчиваются токеном * /

Пример: / * это многострочный синтаксис * /

Числа

Вы можете указать число в двоичном, восьмеричном, десятичном или шестнадцатеричном формате. Отрицательные числа представлены двумя дополнительными числами. Verilog позволяет использовать целые и действительные числа, а также числа со знаком и без знака.

Синтаксис задается - <размер> <радикс> <значение>

Размер или безразмерное число можно определить в <Size>, а <radix> определяет, является ли он двоичным, восьмеричным, шестнадцатеричным или десятичным.

Идентификаторы

Идентификатор - это имя, используемое для определения объекта, такого как функция, модуль или регистр. Идентификаторы должны начинаться с буквенного символа или символа подчеркивания. Ex. A_Z, a_z, _

Идентификаторы представляют собой комбинацию букв, цифр, символа подчеркивания и $. Они могут иметь длину до 1024 символов.

Операторы

Операторы - это специальные символы, используемые для задания условий или работы с переменными. Для выполнения операций с переменными используются один, два, а иногда и три символа.

Ex. >, +, ~, &! знак равно

Ключевые слова Verilog

Слова, которые имеют особое значение в Verilog, называются ключевыми словами Verilog. Например, assign, case, while, wire, reg, and, or, nand и module. Их не следует использовать в качестве идентификаторов. Ключевые слова Verilog также включают директивы компилятора, а также системные задачи и функции.

Моделирование на уровне ворот

Verilog имеет встроенные примитивы, такие как логические вентили, шлюзы передачи и переключатели. Они редко используются для проектных работ, но они используются в мире пост-синтеза для моделирования ячеек ASIC / FPGA.

Моделирование на уровне ворот демонстрирует два свойства:

Drive strength- Сила выходных ворот определяется силой привода. Выход будет самым сильным, если есть прямое соединение с источником. Сила уменьшается, если соединение осуществляется через проводящий транзистор, и меньше всего - через резистивный подтягивающий / понижающий резистор. Сила привода обычно не указывается, и в этом случае по умолчанию используются значения strong1 и strong0.

Delays- Если задержки не указаны, то у шлюзов нет задержек распространения; если указаны две задержки, то первая представляет задержку нарастания, а вторая - задержку спада; если указана только одна задержка, то и подъем, и спад равны. При синтезе задержки можно не учитывать.

Примитивы ворот

В Verilog используются основные логические элементы, использующие один выход и множество входов. GATE использует одно из ключевых слов - and, nand, or, nor, xor, xnor для использования в Verilog для числа N входов и 1 выхода.

Example:  
   Module gate() 
   Wire ot0; 
   Wire ot1; 
   Wire ot2; 
   
   Reg in0,in1,in2,in3; 
   Not U1(ot0,in0); 
   Xor U2(ot1,in1,in2,in3); 
   And U3(ot2, in2,in3,in0)

Примитивы шлюза передачи

Примитивы шлюза передачи включают как буферы, так и инверторы. У них один вход и один или несколько выходов. В синтаксисе создания экземпляра шлюза, показанном ниже, GATE означает ключевое слово buf или NOT gate.

Пример: Not, buf, bufif0, bufif1, notif0, notif1.

Not - n outout инвертор

Buf - n выходной буфер

Bufifo - трехсторонний буфер, активный низкий уровень включения

Bufif1 - трехсторонний буфер, активный высокий уровень включения

Notifo - трехступенчатый инвертор, активный низкий уровень разрешения

Notif1 - трехступенчатый инвертор, активный высокий уровень разрешения

Example:  
   Module gate() 
   Wire out0; 
   Wire out1; 
   
   Reg in0,in1;
   Not U1(out0,in0); 
   Buf U2(out0,in0);

Типы данных

Набор значений

Verilog состоит в основном из четырех основных ценностей. Все типы данных Verilog, которые используются в Verilog, хранят эти значения -

0 (логический ноль или ложное состояние)

1 (логическая единица, или истинное состояние)

x (неизвестное логическое значение)

z (состояние с высоким импедансом)

использование x и z для синтеза очень ограничено.

провод

Провод используется для обозначения физического провода в цепи и используется для соединения ворот или модулей. Значение провода можно только прочитать и не присвоить функции или блоку. Провод не может хранить значение, но всегда управляется оператором непрерывного присваивания или подключением провода к выходу элемента / модуля. Другие особые типы проводов:

Wand (wired-AND) - здесь значение Wand зависит от логического И всех подключенных к нему драйверов устройств.

Wor (wired-OR) - здесь значение Wor зависит от логического ИЛИ всех подключенных к нему драйверов устройств.

Tri (three-state) - здесь все драйверы, подключенные к tri, должны быть z, кроме одного (который определяет значение tri).

Example: 
   Wire [msb:lsb] wire_variable_list; 
   Wirec // simple wire 
   Wand d; 
   
   Assign d = a; // value of d is the logical AND of 
   Assign d = b; // a and b 
   Wire [9:0] A; // a cable (vector) of 10 wires. 
   
   Wand [msb:lsb] wand_variable_list; 
   Wor [msb:lsb] wor_variable_list; 
   Tri [msb:lsb] tri_variable_list;

регистр

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

Пример -

reg c; // одиночная 1-битная регистровая переменная

рег [5: 0] драгоценный камень; // 6-битный вектор;

рег [6: 0] д, д; // две 7-битные переменные

Вход, выход, вход

Эти ключевые слова используются для объявления портов ввода, вывода и двунаправленных портов задачи или модуля. Здесь входные и входные порты, которые относятся к проводному типу, а выходной порт сконфигурирован как провод, рег, палочка, работа или тройной тип. Всегда по умолчанию используется тип провода.

Example

Module sample(a, c, b, d);  
Input c;   // An input where wire is used. 

Output a, b;  // Two outputs where wire is used. 
Output [2:0] d;  /* A three-bit output. One must declare type in a separate statement. */ 
reg [1:0] a;  // The above ‘a’ port is for declaration in reg.

Целое число

Целые числа используются в переменных общего назначения. Они используются в основном в индикаторах циклов, константах и ​​параметрах. Они относятся к типу данных reg. Они хранят данные как числа со знаком, тогда как явно объявленные типы reg хранят их как данные без знака. Если целое число не определено во время компиляции, то размер по умолчанию будет 32 бита.

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

Example

Integer c;   // single 32-bit integer 
Assign a = 63;  // 63 defaults to a 7-bit variable.

Supply0, Supply1

Supply0 определяет провода, привязанные к логическому 0 (земля), а supply1 определяет провода, связанные с логической 1 (питание).

Example

supply0 logic_0_wires; 
supply0 gnd1;  // equivalent to a wire assigned as 0 

supply1 logic_1_wires; 
supply1 c, s;

Время

Время - это 64-битная величина, которая может использоваться вместе с системной задачей $ time для хранения времени моделирования. Время не поддерживается для синтеза и поэтому используется только для моделирования.

Example

time time_variable_list; 
time c; 
c = $time;   //c = current simulation time

Параметр

Параметр определяет константу, которая может быть установлена ​​при использовании модуля, что позволяет настраивать модуль в процессе создания экземпляра.

Example 
Parameter add = 3’b010, sub = 2’b11; 
Parameter n = 3; 
Parameter [2:0] param2 = 3’b110; 

reg [n-1:0] jam; /* A 3-bit register with length of n or above. */ 
always @(z) 
y = {{(add - sub){z}};  

if (z)
begin 
   state = param2[1];
else
   state = param2[2]; 
end

Операторы

Арифметические операторы

Эти операторы выполняют арифметические операции. + И - используются либо как унарные (x), либо как бинарные (z − y) операторы.

Операторы, которые включены в арифметические операции:

+ (сложение), - (вычитание), * (умножение), / (деление),% (модуль)

Example -

parameter v = 5;
reg[3:0] b, d, h, i, count; 
h = b + d; 
i = d - v; 
cnt = (cnt +1)%16; //Can count 0 thru 15.

Операторы отношения

Эти операторы сравнивают два операнда и возвращают результат в виде одного бита, 1 или 0.

Переменные Wire и reg положительны. Таким образом, (−3'd001) = = 3'd111 и (−3b001)> 3b110.

Операторы, которые включены в реляционную операцию:

  • == (равно)
  • != (Не равно)
  • > (больше чем)
  • > = (больше или равно)
  • <(меньше чем)
  • <= (меньше или равно)

Example

if (z = = y) c = 1; 
   else c = 0; // Compare in 2’s compliment; d>b 
reg [3:0] d,b; 

if (d[3]= = b[3]) d[2:0] > b[2:0]; 
   else b[3]; 
Equivalent Statement 
e = (z == y);

Битовые операторы

Побитовые операторы, выполняющие побитовое сравнение двух операндов.

Операторы, которые включены в побитовую операцию:

  • & (побитовое И)
  • | (побитовое ИЛИ)
  • ~ (побитовое НЕ)
  • ^ (побитовое исключающее ИЛИ)
  • ~ ^ или ^ ~ (побитовое исключающее ИЛИ)

Example

module and2 (d, b, c); 
input [1:0] d, b; 
output [1:0] c; 
assign c = d & b; 
end module

Логические операторы

Логические операторы - это побитовые операторы, которые используются только для однобитовых операндов. Они возвращают одно битовое значение, 0 или 1. Они могут работать с целыми числами или группой битов, выражениями и обрабатывать все ненулевые значения как 1. Логические операторы обычно используются в условных операторах, поскольку они работают с выражениями.

Операторы, которые включены в логическую операцию:

  • ! (логическое НЕ)
  • && (логическое И)
  • || (логическое ИЛИ)

Example

wire[7:0] a, b, c; // a, b and c are multibit variables. 
reg x; 

if ((a == b) && (c)) x = 1; //x = 1 if a equals b, and c is nonzero. 
   else x = !a; // x =0 if a is anything but zero.

Операторы редукции

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

Операторы, которые включены в операцию сокращения:

  • & (сокращение И)
  • | (уменьшение ИЛИ)
  • ~ & (сокращение NAND)
  • ~ | (сокращение NOR)
  • ^ (сокращение XOR)
  • ~ ^ или ^ ~ (сокращение XNOR)

Example

Module chk_zero (x, z); 

Input [2:0] x; 
Output z; 
Assign z = & x; // Reduction AND 
End module

Операторы смены

Операторы сдвига, которые сдвигают первый операнд на количество битов, указанное вторым операндом в синтаксисе. Вакантные должности заполняются нулями для обоих направлений, сдвигов влево и вправо (расширение знака не используется).

Операторы, которые включены в операцию Shift:

  • << (сдвиг влево)
  • >> (сдвиг вправо)

Example

Assign z = c << 3; /* z = c shifted left 3 bits;

Вакансии заполняются нулями * /

Оператор конкатенации

Оператор конкатенации объединяет два или более операнда для формирования большего вектора.

Оператор, включенный в операцию конкатенации, - {} (конкатенация)

Example

wire [1:0] a, h; wire [2:0] x; wire [3;0] y, Z; 
assign x = {1’b0, a}; // x[2] = 0, x[1] = a[1], x[0] = a[0] 
assign b = {a, h}; /* b[3] = a[1], b[2] = a[0], b[1] = h[1], 
b[0] = h[0] */ 
assign {cout, b} = x + Z; // Concatenation of a result

Оператор репликации

Оператор репликации создает несколько копий элемента.

Оператор, используемый в операции репликации, - {n {item}} (n-кратная репликация элемента)

Example

Wire [1:0] a, f; wire [4:0] x; 
Assign x = {2{1’f0}, a}; // Equivalent to x = {0,0,a } 
Assign y = {2{a}, 3{f}}; //Equivalent to y = {a,a,f,f} 
For synthesis, Synopsis did not like a zero replication.

For example:- 
Parameter l = 5, k = 5; 
Assign x = {(l-k){a}}

Условный оператор

Условный оператор синтезирует мультиплексор. Это тот же тип, что и в C / C ++, и вычисляет одно из двух выражений на основе условия.

Оператор, используемый в условной операции, -

(Состояние) ? (Результат, если условие истинно) -

(результат, если условие ложно)

Example

Assign x = (g) ? a : b; 
Assign x = (inc = = 2) ? x+1 : x-1; 
/* if (inc), x = x+1, else x = x-1 */

Операнды

Литералы

Литералы - это операнды с постоянным знаком, которые используются в выражениях Verilog. Два обычно используемых литерала Verilog:

  • String - Операнд строкового литерала - это одномерный массив символов, заключенный в двойные кавычки ("").

  • Numeric - Операнд постоянного числа указывается в виде двоичного, восьмеричного, десятичного или шестнадцатеричного числа.

Example

n - целое число, представляющее количество битов

F - один из четырех возможных базовых форматов -

b для двоичного, o для восьмеричного, d для десятичного, h для шестнадцатеричного.

“time is”  // string literal 
267        // 32-bit decimal number 
2’b01      // 2-bit binary 
20’hB36F   // 20-bit hexadecimal number 
‘062       // 32-bit octal number

Провода, регистры и параметры

Провода, регистры и параметры - это типы данных, используемые в качестве операндов в выражениях Verilog.

Выбор битов «x [2]» и выбор партии «x [4: 2]»

Выбор битов и выбор части используются для выбора одного и нескольких битов, соответственно, из провода, регистра или вектора параметров с использованием квадратных скобок «[]». Выборки по битам и выборки по частям также используются в качестве операндов в выражениях таким же образом, как и их основные объекты данных.

Example

reg [7:0] x, y; 
reg [3:0] z; 
reg a; 
a = x[7] & y[7];      // bit-selects 
z = x[7:4] + y[3:0];  // part-selects

Вызов функций

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

Example  
Assign x = y & z & chk_yz(z, y); // chk_yz is a function 

. . ./* Definition of the function */ 
Function chk_yz; // function definition 
Input z,y; 
chk_yz = y^z; 
End function

Модули

Объявление модуля

В Verilog основной объект проектирования - это модуль. Это указывает имя и список портов (аргументы). Следующие несколько строк определяют тип ввода / вывода (ввод, вывод или вывод) и ширину каждого порта. Ширина порта по умолчанию составляет всего 1 бит. Переменные порта должны быть объявлены wire, wand ,. . ., рег. Переменная порта по умолчанию - wire. Обычно входы являются проводными, потому что их данные фиксируются вне модуля. Выходы относятся к типу reg, если их сигналы хранятся внутри.

Example

module sub_add(add, in1, in2, out); 
input add; // defaults to wire 
input [7:0] in1, in2; wire in1, in2; 

output [7:0] out; reg out; 
... statements ... 
End module

Непрерывное присвоение

Непрерывное присвоение в модуле используется для присвоения значения проводу, которое является нормальным назначением, используемым вне всегда или начальных блоков. Это присвоение выполняется с помощью явного оператора присваивания или для присвоения значения проводу во время его объявления. Непрерывное присвоение непрерывно выполняется во время моделирования. Порядок операторов присваивания на это не влияет. Если вы сделаете какие-либо изменения в любом из сигналов правого входа, это изменит выходной сигнал левого края.

Example

Wire [1:0] x = 2’y01;   // assigned on declaration 
Assign y = c | d;       // using assign statement 
Assign d = a & b; 
/* the order of the assign statements does not matter. */

Экземпляры модуля

Объявления модулей - это шаблоны для создания реальных объектов. Модули создаются внутри других модулей, и каждый экземпляр создает один объект из этого шаблона. Исключением является модуль верхнего уровня, который является его собственным экземпляром. Порты модуля должны соответствовать тем, которые определены в шаблоне. Уточнено -

  • By name, используя точку «.template имя порта (имя провода, подключенного к порту)». Или же

  • By position, поместив порты в одно и то же место в списках портов как в шаблоне, так и в экземпляре.

Example

MODULE DEFINITION 
Module and4 (x, y, z); 
Input [3:0] x, y; 
Output [3:0] z; 
Assign z = x | y; 
End module