Учебники

VLSI Design — Verilog Введение

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

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

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

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

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

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

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

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

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

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

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

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

Пустое пространство

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

Символами пробела являются Пробел, Вкладки, Возврат каретки, Новая строка и Форм подачи.

Комментарии

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

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

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

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

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

чисел

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

Синтаксис задается как — <size> <radix> <value>

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

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

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

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

операторы

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

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

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

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

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

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

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

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

Задержки — если задержки не указаны, то у ворот нет задержек распространения; если указаны две задержки, то первая представляет задержку нарастания, а вторая — задержку нарастания; если указана только одна задержка, то оба, подъем и спад равны. Задержки могут быть проигнорированы при синтезе.

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

Основные логические элементы используют один выход, а в Verilog используется множество входов. GATE использует одно из ключевых слов — и, nand, или, или, ни, 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

Нет — выходной инвертор

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 (логическая единица или истинное условие)

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

z (состояние высокого сопротивления)

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

провод

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

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

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

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

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 регистр переменного типа, который не может подразумевать физический регистр. В многобитовых регистрах данные хранятся в виде чисел без знака, а расширение знака не используется.

Пример —

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

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

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

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

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

пример

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 бита.

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

пример

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

Supply0, Supply1

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

пример

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

supply1 logic_1_wires; 
supply1 c, s;

Время

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

пример

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

параметр

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

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

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) операторы.

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

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

Пример

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.

Переменные проводов и регистров положительные. Таким образом (-3’d001) = = 3’d111 и (-3b001)> 3b110.

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

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

пример

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);

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

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

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

  • & (побитовое И)
  • | (BitwiseOR)
  • ~ (поразрядно НЕ)
  • ^ (побитовый XOR)
  • ~ ^ или ^ ~ (побитовый XNOR)

пример

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

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

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

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

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

пример

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)

пример

Module chk_zero (x, z); 

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

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

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

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

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

пример

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

Вакансии заполнены нулями * /

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

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

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

пример

wire [1:0] a, h; wire [2:0] x; wire [3;0] y, Z; 
assign x = {1b0, 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-кратная репликация элемента)

пример

Wire [1:0] a, f; wire [4:0] x; 
Assign x = {2{1f0}, 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 ++ и оценивает одно из двух выражений на основе условия.

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

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

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

пример

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 — Строковый литеральный операнд — это одномерный массив символов, заключенный в двойные кавычки («»).

  • Числовой — операнд с постоянным числом указывается в двоичном, восьмеричном, десятичном или шестнадцатеричном формате.

String — Строковый литеральный операнд — это одномерный массив символов, заключенный в двойные кавычки («»).

Числовой — операнд с постоянным числом указывается в двоичном, восьмеричном, десятичном или шестнадцатеричном формате.

пример

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

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

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

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

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

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

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

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

пример

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 ,. , ., рег. Переменная порта по умолчанию — проводная. Обычно входы являются проводными, потому что их данные защелкиваются вне модуля. Выходы имеют тип reg, если их сигналы хранятся внутри.

пример

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 

Непрерывное назначение

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

пример

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

Модульные реализации

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

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

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

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

По положению расположение портов в одном и том же месте в списках портов как шаблона, так и экземпляра.

пример