Verilog

COPYRIGHT ISSUES

I must insist that any copyright material submitted for inclusion
include the GPL license notice as shown in the rest of the source.

And this of course brings up the issue of copyright status of test
programs sent as bug reports. Basically, I presume when sample code is
sent as part of a bug report that you are granting me license
to redistribute it
(properly attributed, of course) in a test suite or other forum. In
particular,
code that might reveal trade secrets and intellectual property should
not
be sent to me. If you are reporting a problem you are
encountering
in such code, try making a contrived example that does the trick. Just
realize
that I signed no non-disclosure agreements, so am not bound to
non-disclosure.

Еще ускоряемся

К сожалению, современные системы уже настолько сложны, что данного ускорения бывает недостаточно, в этом случае приходится прибегать к распараллеливанию. Многопоточных Verilog симуляторов, насколько я знаю, пока не изобрели, поэтому придется в рукопашную.
В SystemVerilog введен новый механизм для обращения к внешним программным модулям – Direct Programming Interface (DPI). Т.к. этот механизм проще, по сравнению с другими двумя, будем использовать его.

В начале модуля, где мы хотим вызвать внешнюю функцию нужно вставить строчку import.
import «DPI-C» function int some_funct(input string file_name, input int in, output real out);
Далее можно в Verilog ее использовать обычным образом, например, так:

Как правильно скомпилировать и где лежат библиотеки описано в документации на симулятор.
Далее приведу пример программы, работающей в несколько потоков

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

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

An Example Edit

This sample:

# This is a comment in a command file.
# The -y statement declares a library
# search directory
-y $(PROJ_LIBRARY)/prims
#
# This plusarg tells the compiler that
# files in libraries may have .v or .vl
# extensions.
+libext+.v+.vl
#
main.v // This is a source file
#
# This is a file name with blanks.
C:/Project Directory/file name.vl

is a command file that demonstrates the major
syntactic elements of command files. It demonstrates the
use of comments, variables, plusargs and file names. It
contains a lot of information about the hypothetical
project, and suggests that command files can be used to
describe the project as a whole fairly concisely.

The syntax of command files is rich enough that they
can be used to document and control the assembly and
compilation of large Verilog programs. It is not unusual
to have command files that are hundreds of lines long,
although judicious use of libraries can lead to very
short command files even for large designs. It is also
practical to have different command files that pull
together combinations of sources and compiler arguments
to make different designs from the same Verilog source
files.

Проектирование низкого уровня

Чтобы увидеть, как с помощью Verilog спроектировать нашего арбитра, давайте вернемся к нашей машине состояний- теперь мы займемся разработкой низкого уровня. Мы рассмотрим как на черный ящик с предыдущей диаграммы, влияют наши входы.

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

Модули

Мы должны будем немного прерваться, и рассказать о модулях Verilog. Если Вы смотрите на блок схему арбитра на первом рисунке, то увидим, что модуль имеет имя («арбитр») и порты ввода/вывода (req_0, req_1, gnt_0, и gnt_1).

Так как Verilog — HDL (язык описания аппаратных средств — используемый для концептуального проектирования интегральных схем), то он должен иметь такое средство как модули. В Verilog мы называем наш «черный ящик» модулем. Module — зарезервированное слово в рамках языка, используется, для описания объектов с входами, выходами и внутренней логикой работы; модули — грубые эквиваленты функций с возвращаемым результатом на других языках программирования.

Compiling VPI Modules Edit

To compile and link a VPI module for use with Icarus Verilog,
you must compile all the source files of a module as if you
were compiling for a DLL or shared object. With gcc under
Linux, this means compiling with the «-fpic» flag. The
module is then linked together with the vpi library like
so:

% gcc -c -fpic hello.c
% gcc -shared -o hello.vpi hello.o -lvpi

This assumes that the «vpi_user.h header file and the
libvpi.a library file are installed on your system so that
gcc may find them. This is normally the case under Linux
and UNIX systems. An easier, the preferred method that
works on all supported systems is to use the single command:

% iverilog-vpi hello.c

The «iverilog-vpi» command takes as command arguments the
source files for your VPI module, compiles them with proper
compiler flags, and links them into a vpi module with any
system specific libraries and linker flags that are required.
This simple command makes the «hello.vpi» module with
minimum fuss.

Представление аналоговых сигналов

Для представления аналоговых сигналов хорошо подходит тип с плавающей точкой. В System Verilog это типы shortreal (эквивалентен float в С) и real. Необходимо отметить, что это типы данных с памятью. Значение в них обновляется только в момент присваивания, т.е. это тип аналогичный reg, но в котором запомненное значение представляется не 0 или 1, а напряжением или током, представленном, в свою очередь, в виде числа с плавающей точкой.
Теперь, нам очень нужен тип аналогичный wire, который обновляется непрерывно, а не только в момент записи. Надо сказать, что в System Verilog такого типа нет. Ходят слухи, что при обсуждении стандарта, было некое движение, дабы вставить в него этот функционал, но оно не реализовалось ни во что конкретное. Тем не менее, если вы используете симулятор ncsim, то в нем есть модификатор var, который делает из типа real и других типов аналог wire. Пример:

Если ваш симулятор не поддерживает var, то можно сделать так:

Запись менее удобная, тем не менее вполне рабочая.

How To Send Patches

Icarus Verilog Developer Guide

Next best is context diffs as emitted by diff from GNU diffutils. 
Human
beings can read such things, and they are resilient to changing
originals. A good set of flags to diff are «diff -cNB».  With
such diffs, I can
look at the changes you are offering and probably tell at a glance that
they
are plausible. Then I can use patch(1) to apply them. Or I can apply
them
by hand.

I find replacement files particularly inconvenient. Replacement
files do
not clearly highlight what they change, and they are particularly
difficult to merge with local changes to the file. Please, if your
changes are restricted to a single file, it is easy for you to use the
diff command on that file, and diffs of this form are infinitely easier
for me to accept, approve and
apply. If you just send me a replacement file, I’ll probably send it back to you to make a patch.

Now that you have the perfect patch, please tell me what
this patch
is supposed to accomplish, and if appropriate include a test program
that
demonstrates the efficacy of the patch. (If I have no idea what the
patch
is for, I will ask for clarification before applying it.) The test
program
may well find its way into the regression test suite, so include
copyright
notices.

Конструкция always (Always Block)

Ключевое слово: always

Блок always означает, что действие выполняется непрерывно, пока процесс моделирования не будет остановлен директивой $finish или $stop.

Директива $finish на самом деле определяет симуляцию, в то время как директива $stop — паузы. Ниже приведен пример формирования тактового импульса с использованием конструкции always. Заметим, что, вообще говоря, для этих целей удобнее использовать циклы.

module pulse;reg clock;initial clock = 1’b0; // запуск тактаalways #10 clock = ~clock; // тактinitial #5000 $finish // конец моделированияendmodule

Пример проектирования последовательностного устройства: двоичный счетчик

Рассмотрим пример проектирования двоичного счетчика, который считает от 0 до 12, по достижении 12 сбрасывается в 0 и начинает счет заново.

Рассмотрим описание на вентильном уровне.

// 4-bit binary countermodule counter4_bit(q, d, increment, load_data, global_reset, clock);output q;input d;input load_data, global_reset, clock, increment;wire t1, t2, t3; // internal wireswire see12, reset; // internal wireset_ff etff0(q, d, increment, load_data, reset, clock);et_ff etff1(q, d, t1, load_data, reset, clock);et_ff etff2(q, d, t2, load_data, reset, clock);et_ff etff3(q, d, t3, load_data, reset, clock);and a1(t1, increment, q);and a2(t2, t1, q);and a3(t3, t2, q);recog12 r1(see12, q); // счетor or1(reset, see12, global_reset); // сбросendmodule // counter4_bitmodule et_ff(q, data, toggle, load_data, reset, clock);output q;input data, toggle, load_data, reset, clock;wire m1, m2;mux mux0(m1, ~q, q, toggle);mux mux1(m2, data, m1, load_data);dff dff0(q, m2, reset, clock);endmodule // et_ffmodule mux(out, in1, in2, cntrl);output out;input in1, in2, cntrl;assign out = cntrl? in1: in2;endmodule // muxmodule dff(q, data, reset, clock);output q;input data, reset, clock;reg q;always @(posedge clock) // at every clock edge, if reset is 1, q isif (reset == 1)q = 0;else q = data;endmodulemodule recog12(flag, in);input in;output flag;assign flag = (in == 4’b1100)? 1: 0;endmodule // recog12module stumulus;wire q;reg d;reg load_data, global_reset, clk, increment;counter4_bit mod1 (q, d, increment, load_data, global_reset, clk);initial beginglobal_reset = 0;clk = 0;increment = 0;load_data = 0;d = 4’b0100;#10 global_reset = 1;#20 global_reset = 0;#20 load_data = 1;#20 load_data = 0;#20 increment = 1;#200 global_reset = 1;#20 global_reset = 0;#50 load_data = 1;#20 load_data = 0;#10 increment = 0;#20 $finish;end // initial beginalways #5 clk = ~clk;always #10 $display ($time,» %b %b %b %d -> %b %d»,increment, load_data, global_reset, d, q, q);endmodule // stumulusПроанализируем этот пример более подробно.module counter4_bit(q, d, increment, load_data, global_reset, clock);output q;input d;input load_data, global_reset, clock, increment;wire t1, t2, t3; // internal wireswire see12, reset; // internal wires

Как нам уже известно, первые строки модуля содержат его имя и объявление портов. Выход счетчика q, все остальные входные сигналы — t1, t2, t3, see12 и reset объявлены как внутренние цепи, подключенные ко входам, соответствующим субмодулям проекта.

et_ff etff0(q, d, increment, load_data, reset, clock);et_ff etff1(q, d, t1, load_data, reset, clock);et_ff etff2(q, d, t2, load_data, reset, clock);et_ff etff3(q, d, t3, load_data, reset, clock);

В этом фрагменте кода мы определяем четыре счетных триггера с разрешением (Enable/Toggle flip flops):

and a1(t1, increment, q);and a2(t2, t1, q);and a3(t3, t2, q);

Сигнал увеличения счетчика, (increment signal) объединяется по И с выходом последнего триггера для переноса сигнала счета на следующий триггер:

recog12 r1(see12, q);or or1(reset, see12, global_reset);

Каждый раз, когда выход q изменяется, переменная see12 модифицируется по достижении 12 и внутренний сигнал сброса обеспечит сброс счетчика на очередном такте. Далее рассмотрим поведенческую модель нашего счетчика.

Variable Substitution Edit

The syntax «$(name)» is a variable reference, and may be
used anywhere within filenames or directory names. The
contents of the variable are read from the environment and
substituted in place of the variable reference. In Windows,
these environment variables are the very same variables
that are set through the
Control Panel->System dialog box,
and in UNIX these variables are environment variables as
exported by your shell.

Variables are useful for giving command files some
installation independence. For example, one can import a
vendor library with the line:

-y $(VENDOR)/verilog/library

in the command file, and the next programmer will be able
to use this command file without editing it to point to the
location of VENDOR on his machine. Note the use of forward
slashes as a directory separator. This works even under
Windows, so always use forward slashes in file paths
and Windows and UNIX users will be able to share command
files.

Строки

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

  • n печатать текст с новой строки. Аналогично применению клавиши RETURN.
  • Символ табуляции t. Эквивалентно тому, что происходит при нажатии на клавишу табуляции.
  • Применение двух символов является эквивалентом применения символа «».
  • « является символом «.
  • ddd — символ ASCII, определяющий цифру. (В этой записи использовано от одной до трех восьмеричных цифр.)
  • %% — это печать знака %.

В примере 14 показаны правильная и неправильная формы записи строки.

A Worked Example Edit

Let us try a complete, working example. Place the C
code that follows into the file hello.c:

# include  <vpi_user.h>

static int hello_compiletf(char*user_data)
{
      return 0;
}

static int hello_calltf(char*user_data)
{
      vpi_printf("Hello, World!\n");
      return 0;
}

void hello_register()
{
      s_vpi_systf_data tf_data;

      tf_data.type      = vpiSysTask;
      tf_data.tfname    = "$hello";
      tf_data.calltf    = hello_calltf;
      tf_data.compiletf = hello_compiletf;
      tf_data.sizetf    = 0;
      tf_data.user_data = 0;
      vpi_register_systf(&tf_data);
}

void (*vlog_startup_routines[])() = {
    hello_register,
    0
};

and place the Verilog code that follows into hello.v:

module main;
initial $hello;
endmodule

Next, compile and execute the code with these steps:

% iverilog-vpi hello.c
% iverilog -ohello.vvp hello.v
% vvp -M. -mhello hello.vvp
Hello, World!

The compile and link in this example are conveniently
combined into the «iverilog-vpi» command. The «iverilog»
command then compiles the «hello.v» Verilog source file
to the «hello.vvp» program. Next, the «vvp» command
demonstrates the use of the «-M» and «-m» flags to specify
a vpi module search directory and vpi module name.
Specifically, they tell the «vvp» command where to find
the module we just compiled.

The «vvp» command, when executed as above, loads the
«hello.vpi» module that it finds in the current working
directory. When the module is loaded, the vlog_startup_routines table is scanned, and the
«hello_register» function is executed. The «hello_register»
function in turn tells «vvp» about the system tasks that
are included in this module.

After the modules are all loaded, the «hello.vvp» design
file is loaded and its call to the «$hello» system task
is matched up to the version declared by the module. While
«vvp» compiles the «hello.vvp» source, any calls to «$hello»
are referred to the «compiletf» function. This function is
called at compile time and can be used to check
parameters to system tasks or function. It can be left empty
like this, or left out completely. The «compiletf» function
can help performance by collecting parameter checks in
compile time, so they do not need to be done each time the
system task is run, thus potentially saving execution time
overall.

When the run-time executes the call to the hello system
task, the «hello_calltf» function is invoked in the loaded
module, and thus the output is generated. The «calltf»
function is called at run time when the Verilog code
actually executes the system task. This is where the active
code of the task belongs.

Код модуля «арбитр»

Если Вы посмотрите на блок арбитра, то увидите, что есть стрелки, (приходящие для входов и уходящие для выходов). В Verilog, после того, как мы объявили имя модуля и названия портов, мы можем определить направление каждого порта. (примечание: В Verilog 2001 мы можем определить порты и направления порта в объявлении модуля), пример показан ниже.

Verilog Code:
  1. module arbiter (
  2. // Два слэша создают строку комментария.
  3. clock , // clock
  4. reset , // Active high, syn reset
  5. req_0 , // Request 0
  6. req_1 , // Request 1
  7. gnt_0 , // Grant 0
  8. gnt_1 // Grant 1
  9. );
  10. //————-Входящие порты——————————
  11. // Примечание : все команды заканчиваются точкой с запятой
  12. input clock ;
  13. input reset ;
  14. input req_0 ;
  15. input req_1 ;
  16. //————-Выходящие порты—————————-
  17. output gnt_0 ;
  18. output gnt_1 ;

Здесь у нас представлено только два типа портов, входящие и выходящие. В реальной жизни у нас также могут быть двунаправленные порты. Verilog позволяет нам определять двунаправленные порты директивой «inout».

Install

Now you can install Pyverilog using setup.py script:

Tools

This software includes various tools for Verilog HDL design.

  • vparser: Code parser to generate AST (Abstract Syntax Tree) from source codes of Verilog HDL.
  • dataflow: Dataflow analyzer with an optimizer to remove redundant expressions and some dataflow handling tools.
  • controlflow: Control-flow analyzer with condition analyzer that identify when a signal is activated.
  • ast_code_generator: Verilog HDL code generator from AST.

Getting Started

First, please prepare a Verilog HDL source file as below. The file name is ‘test.v’.
This sample design adds the input value internally whtn the enable signal is asserted. Then is outputs its partial value to the LED.

module top
  (
   input CLK, 
   input RST,
   input enable,
   input  value,
   output  led
  );
  reg  count;
  reg  state;
  assign led = count;
  always @(posedge CLK) begin
    if(RST) begin
      count <= ;
      state <= ;
    end else begin
      if(state == ) begin
        if(enable) state <= 1;
      end else if(state == 1) begin
        state <= 2;
      end else if(state == 2) begin
        count <= count + value;
        state <= ;
      end
    end
  end
endmodule

Case

Case инструкция используется, когда надо проверить одну переменную на множество условий. Это похоже на декодер адреса, где вход — адрес и он должен быть проверен на все возможные адреса, которые могут потребоваться. Вместо того, чтобы использовать многократно вложенный if, где в каждом условии проверяется одно состояние, мы используем case с единственным аргументом: это подобно оператору switch в языке C ++.

Конструкция Case начинается  с зарезервированного слова case а заканчивается endcase (Verilog не использует скобки, чтобы разграничить блоки программы). Далее идет список состоящий из совпадающего значение, и через двоеточие выполняемого при совпадении действия. В конце каждого действия- точка с запятой. Также неплохой идеей является использование действия по умолчанию. Так же как автомат конечных состояний, Verilog попадает в неопределенное состояние при неучтенном значении. Введение действия по умолчанию, защищает нас от такой ситуации.

Verilog Code:
  1. case(address)
  2. $display («Сейчас 11:40 вечера»);
  3. 1 $display («Я чувствую себя сонным»);
  4. 2 $display («Побыстрее бы закончить это руководство»);
  5. default $display («Я должен его закончить»);
  6. endcase

Пусть address равняется 3, значит я должен закончить это описание.

Примечание: Общей чертой конструкций if-else и Case является то, что если вы не охватываете все случаи (отсутствие else у if-else и default у case) то это приводит к синтезу защелки.

FreeBSD Edit

Icarus Verilog can be used without a problem on FreeBSD-based systems. It is very simple to
install and get it working. The fastest way is to use FreeBSD Ports collection.

FreeBSD Ports Edit

Installation (as root—unless you’ve done some customization):

% # cd /usr/ports/cad/iverilog && make install clean

Now, you should be able to use «iverilog». If you use csh(1) shell, remember to type:

% rehash

In case of having no /usr/ports directory, you’ll have to fetch it by yourself.
The easiest way is to copy /usr/share/examples/cvsup/ports-supfile to some other location:

% cp /usr/share/examples/cvsup/ports-supfile ~/csup-ports

Edit this file to change «CHANGE_THIS.FreeBSD.org» to appropriate FreeBSD mirror, and start
downloading:

# csup -L 2 ~/csup-ports

Настройка проекта под Visual Studio Code

В качестве проекта возьмём counter.v и counter_tb.v из прошлой статьи «Запускаем ModelSim с Quartus Prime и без«, чего будет более чем достаточно.

Приведу их ещё раз. counter.v :

`timescale 1ns/1ns

module counter (
input wire reset,
input wire clk,
input wire wdata,
input wire wr,
output reg data
);
always @ (posedge clk or posedge reset)
if (reset)
data <= 8'h00;
else
if(wr)
data <= wdata;
else
data <= data + 8'h01;

endmodule

counter_tb.v :

`timescale 1ns/1ns
`include "counter.v"
module counter_tb();

reg reset, clk, wr;
reg wdata;
wire  data_cnt;

counter DUT(reset, clk, wdata, wr, data_cnt);

always
#10 clk = ~clk;

initial begin
clk = 0;
reset = 0;
wdata = 8'h00;
wr = 1'b0;

#10 reset = 1;
#5 reset = 0;
#50;

end

initial begin
#400 $stop;
end

initial
begin
$dumpfile("out.vcd");
$dumpvars(0,DUT);
end

initial
$monitor($stime,, reset,, clk,,, wdata,, wr,, data_cnt);

endmodule

Итак, открываем корневую папку проекта, в которой и находятся файлы counter.v и counter_tb.v:

Редактор теперь показывает открытую папку TEST и файлы в ней:

Далее необходимо создать задачи компиляции и симуляции проекта (точнее Test Bench). Переходим в меню по пункту Terminal -> Configure Tasks, откроется следующий диалог:

Потом:

Создаём файл .vscode\Tasks.json из шаблона Others (нижний пункт). Собственно, после создания файла он должен открыться в редакторе — копируем туда следующий текст:

{
    "version": "2.0.0",
    "tasks": 
}

Сохраняем. Это создание двух команд, первая — для компиляции, вторая — для отображения результатов симуляции.

Закрываем редактор, чтобы он подхватил изменения файла .vscode\Tasks.json при следующем запуске.

Примечание: Можно еще хоткеи настроить для задач, но это уже оставлю на вашу любознательность. 😉

Реализация на уровне логических вентилей (Gate Level Implementation)

Рассмотрим пример реализации нашего мультиплексора 4 в 1 на уровне логических вентилей.

Рассмотрим этот пример построчно.

Первая строка представляет собой описание модуля. Ключевое слово module используется вместе с именем модуля, по которому осуществляется ссылка на модуль. В скобках приведен список портов модуля (port list), причем вначале перечисляются выходы, затем входы. Каждая строка завершается точкой с запятой — это, как известно, характерно для многих языков высокого уровня.

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

В данной строке определяются внутренние цепи, осуществляющие объединение узлов мультиплексора. Как видим, понятия цепи в Verilog и сигнала в VHDL очень схожи:

В этих строчках описываются вентили НЕ с входами cntrl1 и cntrl2 и выходами notcntrl1 и notcntrl2 соответственно. Следует помнить, что в описании портов вентиля всегда вначале идут выходы, затем входы:

Аналогично описываются и вентили И и ИЛИ

Конец модуля завершается ключевым словом endmodule.

Возможно, вам также будет интересно

Все статьи цикла: Краткий курс HDL. Часть 1. Введение Краткий курс HDL. Часть 2.1. Описание языка Verilog Краткий курс HDL. Часть 2.2. Описание языка Verilog Краткий курс HDL. Часть 2.3. Описание языка Краткий курс HDL. Часть 3. О написании кода «вообще»… Краткий курс HDL. Часть 4. Расположение шаблонов текстовых файлов в программных инструментах различных фирм-производителей

Влияние различных факторов, в том числе и климатических, вынуждает производителей радиоэлектронной аппаратуры и вычислительной техники применять различные защитные материалы для печатной платы. Радиоэлектронная аппаратура работает не всегда в комфортных условиях. Температура и влажность воздуха в зависимости от времени суток, времени года и месторасположения изменяются в широком диапазоне. Увеличение влажности воздуха, а в предельных случаях и

Стыковочные системы (Docking systems) — это набор разъемов различных типов, объединенных в одном корпусе или на одном модуле и применяемых для различных приложений. В промышленности стыковочные системы играют большую роль, и чаще всего здесь используются разъемы для передачи сигнальных импульсов, энергии, высокочастотных и мультимедийных сигналов. Попросту говоря, стыковочные системы — это ограниченно управляемые соединители, которые стыкуются в автоматическом режиме. В статье описывается несколько примеров стыковочных систем, которые были реализованы компанией ODU.

Summary Edit

Given the above description of the command file format, the
following is a list of the special records with their meaning.

+libdir+dir-path Edit

Declare library directory paths. The dir path may be a single
directory, or a list of directories. The directories are searched
in order that they are listed.

+libdir-nocase+dir-path Edit

This is the same as «+libdir+», but when searching «nocase»
libraries for module files, case will not be taken as significant.
This is useful when the library is on a case insensitive file
system.

+libext+suffix-string Edit

Declare the suffix strings to use when searching library directories
for Verilog files. The compiler may test a list of suffix strings to
support a variety of naming conventions.

-y dir-path Edit

This is like «+libdir+» but each line takes only one path. Like
«+libdir+» there can be multiple «-y» records to declare multiple
library directories. This is similar to the «-y» flag on the iverilog
command line.

-v file-name or -l file-name Edit

This declares a library file. A library file is just like any other
Verilog source file, except that modules declared within it are
not implicitly possible root modules.

NOTE: The «-l» alias is new as of 2 October 2016. It will become available in releases and snapshots made after that date.

+incdir+include-dir-path Edit

Declare a directory or list of directories to search for files
included by the «include» compiler directive. The directories
are searched in order. This is similar to the «-I» flag on the
iverilog command line.

+define+name=value Edit

Define the preprocessor symbol «name» to have the string value «value».
If the value (and the «=») are omitted, then it is assumed to be the
string «1». This is similar to the «-D» on the iverilog command line.

+timescale+units/precision Edit

Define the default timescale. This is the timescale that is used if
there is no other timescale directive in the Verilog source. The compiler
default default is «+timescale+1s/1s», which this
command file setting can change. The format of the units/precision
is the same as that for the timescale directive in the verilog source.

+toupper-filename Edit

This token causes file names after this in the command file to be
translated to uppercase. this helps with situations where a directory
has passed through a DOS machine (or a FAT file system) and in
the process the file names become munged. This is not meant to
be used in general, but only in emergencies.

+parameter+name=value Edit

This token causes the compiler to override a parameter value for a
top-level module. For example, if the module main has the parameter
WIDTH, set the width like this «+parameter+main.WIDTH=5». Note the
use of the complete hierarchical name. This currently only works for parameters defined in root (top level) modules and a defparam may override the command file value.

+vhdl-work+path Edit

When compiling VHDL, this token allows control over the directory to use
for holding working package declarations. For example, «+vhdl-work+workdir»
will cause the directory «workdir» to be used as a directory for holding
working working copies of package headers.

Preprocessor Flags Edit

These flags control the behavior of the preprocessor.
They are similar to flags for the typical «C» compiler,
so C programmers will find them familiar.

-E Edit

This flag is special in that it tells the compiler to only
run the preprocessor. This is useful for example as a way to
resolve preprocessing for other tools. For example, this
command:

% iverilog -E -ofoo.v -DKEY=10 src1.v src2.v

runs the preprocessor on the source files src1.v and src2.v
and produces the single output file foo.v that has all the
preprocessing (including header includes and ifdefs)
processed.

-D<macro> Edit

Assign a value to the macro name. The format of this flag
is one of:

-Dkey=value
-Dkey

The key is defined to have the given value. If no value
is given, then it is assumed to be «1». The above examples
are the same as these defines in Verilog source:

`define key value
`define key

-I<path> Edit

Append directory <path> to list of directories searched for Verilog include files. The -I switch may be used many times to specify several directories to search, the directories are searched in the order they appear on the command line.

Сложение знакового и беззнакового числа

Доверить компилятору управление знаковым разрядом – это хорошая идея. Используя тип строить выражения на основе знаковой арифметики стало удобно, но проблема может прийти откуда ее совсем не ждали. А если нам понадобится сложить знаковое и беззнаковое число? Если следовать логике приведенных выше правил, при сложении знакового и беззнакового чисел результат будет беззнаковым.

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

– возвращаемое значение знаковое,

– возвращаемое значение беззнаковое.

Попробуем переписать модуль из предыдущего примера, где мы пытались операнд A сделать беззнаковым, с использованием функции . Если мы просто применим функцию к операнду A, то это будет эквивалентно объявлению A как , и все значения больше 4’b0111 (‘d7) окажутся отрицательными, так как старший бит будет равен единице. Чтобы этого не произошло, вручную дополним старший бит нулем:

 module adder (
input			3	A,
input	signed		3	B,
output		 	4	Sum
);
	assign Sum = $signed({1'b0, A}) + B;
endmodule

Рисунок 3 –  RTL сумматора. A – беззнаковый, B – знаковый

Как видно из RTL, старший бит операнда A всегда равен нулю, а операнд B остался знаковым. Операнд A может принимать только положительные значения в соответствии со своей разрядностью: от 0 и до 15, а операнд B может быть от -8 до 7. Так как разрядность выхода так и осталась 5 бит, диапазон значений Sum: от -16 и до 15. Потому, несмотря на то, что такой сумматор корректно работает, может возникнуть переполнение, если результат должен получиться более 15.

Загрузим в ПЛИС, помимо уже привычных нам примеров (-3+1 и -3+3) добавим еще несколько, чтобы продемонстрировать новые свойства.

Таблица 4 – Исследование сумматора
B
знаковый
A
беззнаковый
Sum
знаковый
Комментарии
1101 (-3) 0001 (1) 11110 (-2) Числа из предыдущих примеров. Ничем не примечательны. Работает корректно.
1101 (-3) 0011 (3) 00000 (0) То же.
1101 (-3) 1000 (8) 00101 (5) A превышает максимальное допустимое положительное число для знакового типа разрядностью 4. Результат корректен.
0111 (7) 1000 (8) 01111 (15) B – максимальное допустимое положительное число. Sum принял максимально допустимое значение. Результат корректен.
0111 (7) 1001 (9) 10000 (-16) При сложении двух положительных чисел получили отрицательное. Переполнение!

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

module adder (
input		3	A,
input	signed	3	B,
output	signed	4	Sum,
output			overflow
);
	wire sign;	
	assign {sign, Sum} = $signed({1'b0, A}) + B;
	assign overflow = sign^Sum4;
 
endmodule

Рисунок 4 – RTL cумматора с флагом переполнения

Установка Visual Studio Code

 для вашей ОС, в моём случае я скачал версию для Windows x64, ZIP архив (версия 1.27.1). Распаковываем\устанавливаем и запускаем, нас встречает главное окно редактора (да, да, это не полноценная IDE, как Visual Studio, а именно легкий редактор кода с возможностью кастомизации расширениями практически до уровня IDE) со стартовой страницей:

Произведём минимальные настройки для удобства. Открываем настройки Visual Studio Code:

В строке поиска вводим «theme» и переключаем на более приятную тему для вас (в моём случае это «Default Light+«):

Далее в строке поиска вводим «titleBarStyle» и переключаем параметр Title Bar Style на «custom«:

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

И последнее, в строке поиска вводим «minimap» и, собственно, отключаем её отображение:

Миникарта — это вот что:

Справа сверху отображается представление файла в мини-превью, иногда это удобно, иногда это место лучше освободить от этого превью (к примеру, открываете вертикально 2-3 файла, и это превью уже ощутимо кушает место) — тут кому как удобнее. 🙂

Итак, перезапускаем редактор и видим следующие визуальные изменения:

Итог

  • While, if-else, case(switch) операторы такие же как и в языке Си.
  • If-else и case операторы требуют описания всех вариантов.
  • Цикл for такой же, как в C, но не поддерживает операторы ++ и —.
  • Repeat такой же, как и цикл for, но без увеличения переменной.

Объявление переменных

В цифровом синтезе существует два типа элементов, комбинационные и последовательные. Конечно, мы знаем, что это такое. Но остается вопрос: «Как мы можем моделировать это в Verilog?». Verilog предоставляет два способа моделирования комбинационной логики и только один путь к моделированию последовательной логики.

  • Комбинаторные элементы могут быть смоделированы с помощью блоков «assign» и «always».
  • Последовательные элементы могут быть смоделированы только с использованием блокаа «always».
  • Существует третий блок операторов, который используется только при написании тестов: Начальное объявление.
Оцените статью
Рейтинг автора
5
Материал подготовил
Андрей Измаилов
Наш эксперт
Написано статей
116
Добавить комментарий