Язык AHDL

         

Оператор If Then против оператора Case


Операторы If Then и  Case

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

Но между ними существует важное различие:

¨    В операторе If Then можно использовать любые виды булевых выражений. Каждое выражение, следующее за IF или  ELSIF областями, может быть несвязанно с другими выражениями в операторе. В операторе Case, напротив, только одно булево выражение сравнивается с константой в каждой WHEN области.

¨    Использование ELSIF предложения может привести к логике, которая слишком сложна для компилятора, так как каждое следующее друг за другом предложение ELSIF должно еще проверять, ложность предыдущих IF/ELSIF предложений. Следующий пример показывает как компилятор интерпретирует оператор If Then. Если a и b сложные выражения, тогда инверсия этих выражений даст, возможно, даже более сложные выражения.

Оператор If Then         Интерпретация компилятора

IF a THEN                     IF a THEN

            c = d;                c = d;

                                    END IF;

ELSIF b THEN               IF !a & b THEN

            c = e;                c = e;

                                    END IF;

ELSE                            IF !a & !b THEN

            c = f;                 c = f;

END IF;                         END IF;



Оператор Include


Оператор Include позволяет импортировать текст из файла с расширением .inc в текущий файл. Следующий пример демонстрирует использование оператора Include:

INCLUDE "const.inc";

Оператор Include имеет следующие характеристики:

¨    Оператор Include начинается с ключевого слова INCLUDE, за которым следует имя подключаемого .inc-файла, заключенного в двойные кавычки.

¨    Если явно не указывать расширение подключаемого файла, то компилятор по умолчанию предполагает, что файл имеет расширение .inc.

¨    Оператор Include заканчивается символом (;).

¨    На этапе компиляции осуществляется замена оператора Include содержимым .inc-файла. В примере, показанном выше, файл const.inc заменяет текст INCLUDE “const.inc”;

Оператор Include часто используется для подключения прототипов функций для файлов более низкого уровня иерархии по отношению к данному текстовому файлу проекта (TDF). Для использования мега- и макрофункций необходимо сначала определить их логику функционирования в соответствующем файле проекта. Затем необходимо использовать оператор Function Prototype для определения портов функции. В качестве альтернативного варианта, можно использовать оператор Include для подключения прототипа функции, хранящегося в соответствующем файле с расширением .inc. Затем можно осуществить объявление объекта (Instance Declaration) или подставляемую ссылку (in-line reference) для экземпляра логической функции.

Можно автоматически создать файл с расширением .inc, содержащий прототип функции для текущего файла проекта, с помощью команды Create Default Include File меню File.

На этапе компиляции текстового файла проекта, компилятор осуществляет поиск файлов с расширением .inc в следующей последовательности:

1.   Сначала осуществляется поиск в директории данного проекта

2.   Просматриваются пользовательские библиотеки указанные командой User Libraries




меню Options.

3.   Просматриваются директории \maxplus2\max2lib\mega_lpm и \maxplus2\max2inc, созданные во время инсталляции.

После изменений, внесенных в  текстовый файл проекта (TDF), в котором осуществляется подключение файлов с расширением .inc, можно использовать команду Project Save&Check меню File  или  осуществить полную перекомпиляцию проекта для обновления  дерева иерархии проекта, выводимого в окне отображения иерархии проекта.

При использовании оператора Include необходимо соблюдать следующие правила:

¨    Имя файла, приведенного в операторе Include, не  должно содержать пути.

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

¨    Oператор Include должен быть расположен за пределами других разделов  языка AHDL.

¨    Оператор Include может использоваться произвольное количество раз в рамках одного текстового файла проекта (TDF).

Файлы с расширением .inc должны удовлетворять следующим соглашениям:

¨    Полные имена этих файлов должны иметь расширение .inc.

¨    Файлы с расширением .inc могут содержать лишь следующие операторы:

·     Function Prototype

·     Define

·     Parameters

·     Constant

Вложенность при использовании файлов с расширением .inc недопустима.

Файлы с расширением .inc не должны содержать секцию Subdesign.


Оператор Options


Оператор Options предназначен для определения значения опции BIT0, указывающего в отношении группы, является ли бит с наименьшим номером битом с наибольшим весом (MSB - Most Significant Bit), битом с наименьшим весом (LSB - Least Significant Bit) или с весом, зависящим от места  расположения индекса данного бита при описании группы. Использование данной опции позволяет избежать генерации сообщений  предупредительного характера, если бит с наименьшим номером в группе используется не в качестве бита с наименьшим весом, что предполагается по умолчанию. При описании группы с размерностью, определенной  диапазоном чисел, левое число представленного диапазона (заметим, что оно может быть и наименьшим и наибольшим в данном диапазоне)  всегда представляет собой индекс бита с наибольшим весом (MSB - Most Significant Bit); соответственно правое число представленного диапазона (заметим также, что оно может быть и наименьшим и наибольшим числом указанного диапазона) всегда представляет собой индекс бита с наименьшим весом (LSB - Least Significant Bit). Если упомянутый диапазон чисел представлен в возрастающем порядке и при этом не установлена опция BIT0=MSB, то будет сгенерировано предупреждающее сообщение .Если использована опция BIT0=MSB и упомянутый диапазон представлен в убывающем порядке, то также  будет сформировано предупреждающее сообщение. При установке опции BIT0=ANY можно определять размерности групп  диапазонами чисел, представленных как в возрастающем, так и в убывающем порядке без генерации предупреждающих сообщений.

Оператор Options начинается ключевым словом OPTIONS, за которым следует опция BIT0 и ее установка. Оператор Options заканчивается символом (;).

Следующий пример демонстрирует использование оператора Options:

OPTIONS BIT0 = MSB;

В данном примере бит с наименьшим номером в группе определен как бит, имеющий наибольший вес (MSB).Другими возможными вариантами являются  LSB - наименьший вес и ANY - вес, зависящий от расположения бита с наименьшим номером при описании группы.

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



Оператор Parameters


Оператор Parameters позволяет определять один и более параметров, управляющих экземпляром[M2]  (an instance) параметрической мега- или макрофункции. Следующий пример демонстрирует использование оператора Parameters:

PARAMETERS

(

   FILENAME = "myfile.mif", -- optional default value follows "=" sign

   WIDTH,

   AD_WIDTH = 8,

   NUMWORDS = 2^AD_WIDTH

);

При использовании оператора Parameters необходимо соблюдать следующие правила:

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

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

¨    Имена параметров могут представлять собой либо имена, определенные пользователем, либо имена, предопределенные фирмой Altera .

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

¨    Оператор Parameters заканчивается символом (;).

¨    После того, как параметр был определен, он может использоваться во всем текстовом файле проекта.

¨    Параметр может быть использован лишь после того, как он был определен.

¨    Имена параметров должны быть уникальными.

¨    Имя параметра не должно содержать пробелов. Для разделения слов и лучшего восприятия необходимо пользоваться символом подчеркивания.

¨    Оператор Parameters может использоваться произвольное количество раз в рамках одного текстового файла проекта.




¨    Oператор Parameters должен быть расположен за пределами других разделов  языка AHDL.

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

¨    Использование круговых ссылок недопустимо. Следующий пример демонстрирует использование недопустимой круговой ссылки:

PARAMETERS

(

   FOO = BAR;

   BAR = FOO;

);

На этапе компиляции текстового файла проекта, компилятор осуществляет поиск значений параметров в следующей последовательности:

1.   Производится анализ экземпляра (an instance)

логической функции. Например, в текстовом файле проекта, в объекте (an instance), созданном путем объявления объекта (Instance Declaration)

или подставляемой ссылкой (in-line reference), можно определить те параметры, которые будут использоваться, а также в необязательном порядке определить  их значения. В графическом файле проекта (GDF - Graphic Design File) можно выбрать символ и, используя команду Edit Ports/Parameters

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

2.   Производится анализ экземпляра логической функции более высокого уровня иерархии. Значения параметров экземпляра

логической функции более высокого уровня иерархии распространяются на подфункции данной логической функции, если экземпляры

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

3.   Производится анализ глобальных значений параметров проекта по умолчанию, определенных командой Global Project Parameters из меню Assign. Эти  значения хранятся в файле установок и конфигурации  (Assignment&Configuration file - .acf) проекта.

4.   Просматриваются необязательные значения по умолчанию, указываемые в разделе Parameters текстового файла проекта (TDF), или с помощью примитива PARAM в графическом файле проекта, описывающем логическую функцию. Эти значения по умолчанию используются только в том файле, в котором они приводятся и не распространяются на подпроекты, входящие в данный проект.


Оператор Title


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

TITLE "Display Controller";

При использовании оператора Title необходимо соблюдать следующие правила:

¨    Оператор Title начинается с ключевого слова TITLE, за которым следует текстовая строка -заголовок, заключенная в двойные кавычки. Оператор заканчивается символом ‘;’ (точка с запятой).

¨    Если оператор Title используется в текстовом файле проекта, то  использованный заголовок помещается  в  начало файла отчета (Report File). В показанном выше примере, заголовок Display Controller помещается в файл отчета.

¨    Заголовок может содержать до 255 символов, кроме того в нем не должны использоваться символы конца строки (end-of-line) и конца файла (end-of-file). Для использования кавычек в заголовке необходимо использовать пары двойных кавычек. Пример:

TITLE """EPM5130"" Display Controller";

¨    В одном текстовом файле проекта может использоваться не более одного оператора Title.

¨    Oператор Title должен быть расположен за пределами других разделов  языка AHDL.



Оператор Truth Table


Оператор Truth Table используется для определения комбинационной логики или для определения поведения автоматов. В таблицах истинности, используемых в AHDL каждая строка таблицы состоит из комбинации входных значений и соответствующих этой комбинации выходных значений. Эти выходные значения могут использоваться как обратные связи для определения переходов автоматов из одного состояния в другое, а также его выходов.

Следующий пример демонстрирует использование оператора Truth Table:

TABLE

a0,        f[4..1].q   => f[4..1].d,     control;

0,         B"0000"  =>  B"0001",     1;

0,         B"0100"  =>  B"0010",     0;

1,         B"0XXX"  =>  B"0100",    0;

X,         B"1111"  =>  B"0101",     1;

END TABLE;

Оператор Truth Table имеет следующие характеристики:

¨    Заголовок таблицы истинности состоит из ключевого слова TABLE, за которым следует разделенный запятыми список входов, символ (=>) и разделенный запятыми список выходов таблицы. Заголовок таблицы истинности заканчивается символом (;).

¨    Входы таблицы истинности являются булевскими выражениями; выходы являются переменными. В примере, показанном выше, входными сигналами являются a0 и f[4..1].q; выходными сигналами являются f[4..1] и control.

Тело таблицы истинности состоит из одного или более компонентов, каждый из которых представляет одну или более строку и заканчивается символом (;).

Каждый компонент состоит из разделенного запятыми списка входов и разделенного запятыми списка выходов. Входы и выходы разделены символом (=>).

Каждый сигнал имеет однозначное соответствие с значениями в каждом компоненте тела таблицы истинности. Таким образом, первый компонент в примере, показанном выше, определяет, что когда a0 имеет  значение 0, а f[4..1].q имеет значение B”0000”, то f[4..1].d примет значение B”0001”,

а сигнал control примет значение 1.




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

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

Описание таблицы истинности заканчивается ключевыми словами END TABLE, за которыми следует символ (;).

В отношении описания таблицы истинности необходимо соблюдать следующие правила:

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

¨    Нет необходимости оговаривать в таблице истинности все возможные комбинации входных сигналов. Можно использовать символ “X” для определения того, что выходное значение не зависит от входного. Следующий пример определяет, что, если a0 имеет высокий уровень и f4  имеет низкий уровень, то логические уровни  остальных входов не имеют значения. Таким образом, можно указать лишь общую часть нескольких комбинаций входных сигналов, а для всех остальных использовать символ “X”:

TABLE

a0,        f[4..1].q  =>  f[4..1].d,     control;

0,         B"0000"  =>  B"0001",     1;

0,         B"0100"  =>  B"0010",     0;

1,         B"0XXX"  =>  B"0100",    0;

X,         B"1111"  =>  B"0101",     1;

END TABLE;

¨    Количество разделенных запятыми элементов таблицы истинности должно в точности соответствовать количеству элементов в заголовке таблицы истинности. В противном случае в отношении выходных сигналов используются значения по умолчанию.

¨    При использовании символа “X” для определения нескольких комбинаций значений входных сигналов необходимо внимательно следить за тем, чтобы определяемое таким образом подмножество комбинаций не перекрывалось ни с каким другим подмножеством в пределах данной таблицы истинности.В противном случае возможны непредсказуемые результаты.


Описание объектов


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

При необходимости реализации объекта мега- или макрофункции надо убедиться в существовании соответствующего ей файла с описанием ее логического функционирования. Затем используется оператор Function Prototype для описания портов и параметров функции и производится реализация функции посредством подставляемой ссылки или объявления объекта.

Для экземпляра примитива также используется подставляемая ссылка или объявления объекта. Однако, в отличие от мега- и макрофункций,  логика функционирования примитива предопределена, поэтому нет необходимости определять логику функционирования примитива в отдельном текстовом файле проекта. В большинстве случаев нет необходимости использовать оператор Function Prototype.

При использовании процедуры объявления объекта в разделе описания переменных производится описание переменной типа <primitive>,  <megafunction> или <macrofunction>. Для параметрических мега- и макрофункций объявление включает список параметров, используемых объектом и в необязательном порядке, значения этих параметров. После определения переменной порты объекта функции можно использовать с применением следующего формата:

<имя экземпляра>.<имя порта>

Например, если необходимо использовать в данном файле проекта функции adder и compare, нужно выполнить следующие описания экземпляров в разделе описания переменных:

VARIABLE

            comp  : compare;

            adder : lpm_add_sub WITH (LPM_WIDTH = 8);

Переменные comp и adder являются объектами функций compare и  lpm_add_sub, имеющих следующие входы и выходы:

a[3..0], b[3..0]                : INPUT;            -- входы компаратора




less, equal, greater       :OUTPUT;--выходы компаратора
a[8..1], b[8..1]                : INPUT; -- входы сумматора
sum[8..1]                       : OUTPUT;--выходы сумматора
Таким образом, в секции Logic можно использовать следующие порты переменных comp и adder:
comp.a[], comp.b[], comp.less, comp.equal, comp.greater
adder.dataa[], adder.datab[], adder.result[]
Эти порты могут использоваться в любом операторе также как и узлы.
Поскольку все примитивы имеют только один выход можно использовать имя примитива без указания имени его выходного порта (например, без .q или .out) в правой части выражений. Аналогично, если примитив имеет лишь один вход (т.е. все примитивы за исключением примитивов JKFF, JKFFE, SRFF и SRFFE), то можно использовать имя примитива без указания имени его входного порта в левой части выражений (т.е., без .d, .t или .in).
На этапе  компиляции компилятор осуществляет поиск значений параметров мега- и макрофункций в порядке, описанном в разделе “Оператор Parameters”.

Описание узлов


AHDL поддерживает два типа узлов : NODE и TRI_STATE_NODE.

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

И NODE и TRI_STATE_NODE схожи с типами портов INPUT, OUTPUT и BIDIR, описываемых в разделе Subsection, в том, что и те и другие представляют проводники, по которым распространяются сигналы.

Þ   В файле с расширением .fit для текущего проекта могут иметь место имена, сгенерированные компилятором и имеющие в своем составе знак тильда (~). Если производится обратная аннотация  присоединений, осуществленных в файле с расширением .fit, то эти имена появятся в файле установок  и конфигурации  (.acf). Символ тильды зарезервирован исключительно для имен генерируемых компилятором; использовать их для обозначения выводов, узлов и групп (шин) запрещено.

Следующий пример демонстрирует процедуру определения узла:

SUBDESIGN node_ex

(

            a, oe        : INPUT;

            b             : OUTPUT;

            c             : BIDIR;

)

VARIABLE

            b : NODE;

            t : TRI_STATE_NODE;

BEGIN

            b = a;               

            out = b  % следовательно out = a %

            t = TRI(a, oe);

            t = c;     % t есть шина c и a %

END;

NODE и TRI_STATE_NODE отличаются тем, что  многократное присваивание значений  этим объектам дает различные результаты:

¨    Многократные присваивания узлам типа NODE объединяют сигналы в соответствии с функцией монтажное И или монтажное ИЛИ. Значения переменных по умолчанию, определенные в операторах Default детерминируют поведение: значение по умолчанию VCC предопределяет выполнение функции монтажное И  над несколькими значениями, присваиваемыми к данному узлу; соответственно значение по умолчанию GND предопределяет выполнение функции монтажное ИЛИ.

¨    Если только одна переменная присвоена узлу типа TRI_STATE_NODE , то он ведет себя также как  и  узел типа NODE .

Следующие примитивы и сигналы могут быть подключены к узлам типа TRI_STATE_NODE:

¨    Примитивы TRI.

¨    Порты типа INPUT файла проекта с файлами проекта более высокого уровня иерархии.

¨    Порты типа OUTPUT и BIDIR файла проекта с файлом проекта более низкого уровня иерархии.

¨    Порты типа BIDIR данного файла проекта.

¨    Другие узлы типа TRI_STATE_NODE данного файла проекта.



Определение шин


Шина, которая может включать до 256 членов (битов), трактуется как коллекция узлов и работает как одно целое. Имя шины можно определить с помощью имени с одним диапазоном, имени с двумя  диапазонами или именем в последовательном формате.

В булевых уравнениях шина может приравниваться булеву выражению, другой шине, единственному узлу, VCC, GND, 1 или 0. В каждом из этих случаев  значение шины различно. Оператор Options

можно использовать для определения того, каким будет самый младший бит: наиболее значимым битом(MSB) или наименее значимым битом(LSB) или каким-либо другим.

Как только шина определена, скобки [ ] являются коротким способом определения всего диапазона. Например, a[4..1] можно также указать как a[]; b[5..4][3..2] можно представить  как b[][].

Файл group1.tdf,  приведенный ниже, демонстрирует булевы выражения, которые определяют несколько шин.

OPTIONS BIT0 = MSB;

CONSTANT MAX_WIDTH = 1+2+3-3-1;

% MAX_WIDTH = 2 %

SUBDESIGN group1

(

a[1..2], use_exp_in[1+2-2..MAX_WIDTH] : INPUT;

d[1..2],use_exp_out[1+2*2-4..MAX_WIDTH] : OUTPUT;

dual_range[5..4][3..2] : OUTPUT;

)

BEGIN

   d[] = a[] + B"10";

   use_exp_out[] = use_exp_in[];

   dual_range[][] = VCC;

END;

В этом примере оператор Options

используется для определения того, что самый правый бит шины будет MSB, а десятичная 1 прибавляется к шине a[]. Если ко входу a[] прикладывается 00, то результатом этой программы будет d[] == 1. Шины use_exp_in[] и use_exp_out[] показывают как константы и арифметические выражения можно использовать для ограничения диапазонов шин.

Следующие примеры иллюстрируют использование шин:

¨    Когда шина приравнивается к другой шине того же самого размера, то каждый член справа приравнивается каждому члену слева в соответствующей позиции.

¨    Когда шина приравнивается к VCC или GND, все биты шины соединяются с этим значением.

¨    Когда шина приравнивается к 1, только наименее значимый бит шины соединяется со значением VCC. Остальные биты шины соединяются с GND.

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

a[4..1] = b[2..1] правильно.

В этом уравнении биты отображаются следующим образом:

a4 = b2

a3 = b1

a2 = b2

a1 = b1



Подставляемая ссылка для реализации логической функции (In-Line Logic Function Reference)


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

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

Для реализации объекта примитива также используется подставляемая ссылка или производится описание в разделе объявления объектов. Однако в отличие от мега - и макрофункций логика функционирования примитивов предопределена, то есть нет необходимости определять логику функционирования примитива в отдельном файле проекта. В большинстве случаев нет необходимости использовать оператор Function Prototype для определения прототипа функции.

Следующие примеры демонстрируют прототипы функций compare

и lpm_add _sub. Функция compare  имеет входные порты a[3..0] и b[3..0], а также выходные порты less, equal, greater; функция lpm_add_sub имеет входные порты dataa[LPM_WIDTH-1..0], cin и add_sub, а также выходные порты result[LPM_WIDTH-1..0], cout и overflow.

FUNCTION compare (a[3..0], b[3..0])

            RETURNS (less, equal, greater);

FUNCTION lpm_add_sub (cin, dataa[LPM_WIDTH-1..0], datab[LPM_WIDTH-1..0],  add_sub)

            WITH (LPM_WIDTH, LPM_REPRESENTATION)

            RETURNS (result[LPM_WIDTH-1..0], cout, overflow);

Подставляемые ссылки  (in-line logic function references) для функций compare и lpm_add_sub

указываются в правой части показанного ниже выражения:

(clockwise, , counterclockwise) = compare(position[], target[]);

sum[] = lpm_add_sub (.datab[] = b[], .dataa[] = a[])

   WITH (LPM_WIDTH = 8)

   RETURNS (.result[]);

Подставляемая ссылка для логической функции имеет следующие характеристики:




¨    За именем функции справа от символа равенства (=) следует заключенный в круглые скобки список сигналов, содержащий символические имена, десятичные числа или группы разделенные между собой запятыми. Все эти компоненты описывают входные порты функции.

¨    В списке сигналов имена портов могут иметь позиционное соответствие, либо соответствие по имени:

*    В примере, показанном выше и демонстрирующем использование функции compare, имена переменных position[] и target[] имеют позиционное соответствие портам a[3..0] и b[3..0]. При использовании позиционного соответствия можно применять запятые для резервирования места под выходы, не подсоединяемые к конкретным переменным. В функции compare выход equal не подключается к переменным, поэтому необходимо использовать запятую для резервирования его места в правой части выражения.

*    В примере, показанном выше и демонстрирующем использование функции lpm_add_sub, входы .datab[] и .dataa[] соединяются соответственно с переменными b[] и a[] путем установления соответствия по имени. Соответствие между переменными и портами устанавливается посредством использования символа (=).

1.   Имена портов должны иметь следующий формат .<имя порта> как в правой, так и в левой  части подставляемой ссылки, использующей способ установления соответствия портов переменным по имени.

2.   Установление соответствия портов переменным по имени возможно лишь в правой части подставляемой ссылки. В левой части подставляемой ссылки всегда используется позиционное соответствие.

¨    В параметризируемой функции, за ключевым словом WITH и списком имен параметров следует список входных портов. Этот список заключается в круглые скобки, а имена параметров разделяются запятыми. Декларируются лишь те параметры, которые используются объектом; значения параметров отделяются от имен параметров посредством символа равенства. В примере, показанном выше и демонстрирующим использование функции lpm_add_sub, параметру LPM_WIDTH присвоено значение 8.



Если какому- либо параметру не присвоено никакого значения, то компилятор осуществляет поиск значений для этих параметров в том порядке, который описан в разделе “Оператор Parameters”.

¨    В левой части подставляемой ссылки выходы функции ставятся в соответствие переменным. В примере, показанном выше и демонстрирующем использование функции compare выходы less и greater поставлены в соответствие переменным clockwise и counterclockwise с использованием позиционного соответствия. Подобным же образом в примере для функции lpm_add_sub выходы result[]

поставлены в соответствие группе sum[]

с использованием позиционного соответствия.

¨    Значения переменных, которые определены где-либо в разделе Logic, являются значениями связанными с соответствующими им входами и выходами. В примере, показанном выше для функции compare,  значения position[]

и target[] являются значениями, подаваемыми на соответствующие входы функции compare. Значения выходных портов less и greater связаны с clockwise и counterwise, соответственно. Эти переменные могут быть использованы в других выражениях раздела Logic.


Порты


Порт - это вход или выход логической функции. Порт может находится в двух местах:

·     Порт, который является входом или выходом текущего файла, объявляется в разделе Subdesign.

·     Порт, который является входом или выходом экземпляра примитива или файла разработки более  низкого уровня, используется в разделе Logic.

Порты текущего файла

Порт, который является входом или выходом текущего файла объявляется в следующем формате в разделе Subdesign:

<имя порта>: <тип порта> [ = <значение по умолчанию> ]

Доступны следующие типы портов:

INPUT               MACHINE INPUT

OUTPUT                       MACHINE OUTPUT

BIDIR

Когда текстовой файл проекта является старшим в иерархии, имя порта синонимично с именем вывода. Дополнительное значение порта по умолчанию, которое может быть или VCC или GND, можно определить для типов портов INPUT и BIDIR. Это значение используется только если слева порт не подсоединен, когда экземпляр TDF применяется в файле разработки более высокого уровня.

Например:

SUBDESIGN top

(

foo, bar, clk1, clk2, c[4..0][6..0] : INPUT = VCC;

a0, a1, a2, a3, a4                       : OUTPUT;

b[7..0]                                       : BIDIR;

)

Вы можете импортировать и экспортировать конечные автоматы между TDF и другими файлами разработки, описывая входы и выходы как MACHINE INPUT или MACHINE OUTPUT в разделе Subdesign. Прототип функции, который представляет файл, должен указывать, какие порты принадлежат конечному автомату. MACHINE INPUT и MACHINE OUTPUT можно использовать только в файлах более низкого уровня в иерархии проекта.

Порты экземпляров

Порт, который является входом или выходом экземпляра логической функции присоединяется в разделе Logic. Для соединения логической функции с другими частями TDF, Вы вставляете экземпляр функции с помощью подставляемой ссылки, объявления Instance или конечного автомата с помощью State Machine и затем используете порты функции в разделе Logic.




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

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

В следующем примере D триггер объявляется как переменная reg в разделе Variable, а затем используется в разделе Logic:

VARIABLE

            reg : DFF;

BEGIN

            reg.clk = clk

            reg.d   = d

            out     = reg.q

END;

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

<имя экземпляра>.<имя порта>

<имя экземпляра> - это имя функции, данное пользователем. <имя порта> идентично с именем порта, который объявляется как вход или выход файла в разделе Subdesign TDF файла более низкого уровня или имя вывода в файле разработки другого типа. <имя порта> синонимично с именем порта символа (pinstub),  который представляет экземпляр файла разработки в GDF.

Все функции, поставляемые Altera, имеют предопределенные имена портов (pinstub), которые показываются в прототипе функции. Наиболее используемые имена портов примитивов показаны в следующей таблице:

Имя порта        Описание

.q                     Выход триггера или защелки

.d                     Вход данных триггера или защелки

.t          Вход T триггера

.j          J вход JK триггера

.k         K вход JK триггера

.s         Вход установки SR триггера

.r          Вход очистки SR триггера

.clk       Тактовый вход триггера

.ena     Вход разрешения тактирования триггера, разрешения фиксации защелки разрешения конечного автомата

.prn      Активный низкий вход предустановки триггера

.clrn     Активный низкий вход очистки триггера

.reset   Активный высокий вход сброса конечного автомата

.oe       Вход разрешения выхода  TRI примитива

.in        Первичный вход CARRY, CASCADE, EXP, TRI, OPNDRN, SOFT, GLOBAL, и LCELL примитивов

.out      Выход TRI, OPNDRN, SOFT, GLOBAL, и LCELL примитивов


Последовательностная логика


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



Примитивы


MAX+PLUS II обеспечивает большое многообразие примитивных функций для разработки схем. Так как AHDL и VHDL логические операторы, порты и некоторые операторы замещают примитивы в AHDL и VHDL файлах, то примитивы  являются подмножеством их, доступных для GDF файлов, как показано ниже.

Примитив - один из основных функциональных блоков, применяющийся для проектирования схем с помощью программы MAX+PLUS II. Примитивы используются в графических файлах (.gdf), текстовых файлах (.tdf), и VHDL файлах (.vhd). 

Символы примитивов для графического редактора поставляются в директории \maxplus2\max2lib\prim, созданной во время инсталляции.

Прототипы функций встроены в программу MAX+PLUS II.

            Примитивные массивы

Примитивный массив - это примитив, который представляет несколько идентичных примитивов. Вы можете использовать примитивные массивы для создания более компактных GDF или  OrCAD Schematic файлов путем ввода единственного примитива, который экстрактор списков связей компилятора переведет в несколько примитивов.

Вы можете создать примитивный массив двумя способами:

·     Если все порты символа (pinstub) примитива соединяются с шинами, состоящими из n членов, примитив переводится в массив n индивидуальных примитивов. Каждый индивидуальный узел шины соединяется с соответствующим портом символа каждого индивидуального примитива в массиве. Например,

В этом примере примитивный массив создается при соединении трех шин A[0..2], B[0..2], и C[0..2] с двумя выводами INPUT, выводом OUTPUT и вентилем AND2.

Во время обработки компилятор переводит этот примитивный массив в 6 выводов INPUT, 3 вывода OUTPUT и 3 вентиля AND2 следующим образом:

Один AND2 вентиль соединяется с узлами A0, B0, и C0.

Один AND2 вентиль соединяется с узлами A1, B1, и C1.

Один AND2 вентиль соединяется с узлами A2, B2, и C2.

Входные выводы A0, A1, и A2 соединяются с узлами A0, A1, и A2, соответственно.

Входные выводы В0, В1, и В2 соединяются с узлами В0, В1, и В2, соответственно.




Выходные выводы С0, С1, и С2 соединяются с узлами С0, С1, и С2, соответственно.

Примитивы выводов INPUT, INPUTC, OUTPUT, OUTPUTC, BIDIR, или BIDIRC, которым даны шинные имена переводятся в массив примитивов. Вы не можете использовать перечислимое имя шины для обозначения примитива вывода.

·     Если некоторые порты символа примитива соединяются с шинами с n членами, а некоторые с одиночными узлами, примитив переводится в массив n примитивов. В этом случае каждый индивидуальный узел шины соединяется с соответствующим портов символа каждого примитива в массиве, а каждый узел, который не является частью шины, соединяется с тем же самым портом символа каждого примитива. Например,



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

·     Одиночный узел, который соединяется с примитивным массивом.

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



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

Проба

- уникальное имя, связанное с любым узлом, например, вход или выход примитива, мегафункции или макрофункции, которое можно использовать вместо полного иерархического имени узла в любом месте MAX+PLUS II. Таким образом пробное имя обеспечивает быструю идентификацию узла.

Не используемые входы примитивов, мегафункций и макрофункций

К не подсоединенным входным портам примитива, мегафункции, символов макрофункций и экземпляров применяются следующие правила.

·     Не используемые входы примитивов триггеров имеют следующие значения по умолчанию:



CLRN:   VCC (неактивный)

PRN:     VCC (неактивный)

ENA:     VCC (активный)

·     Требуются входы data и Clock в триггеры и входы data и ENA в защелки.

·     Неиспользуемый вход OE буфера TRI по умолчанию имеет значение VCC (активный).

·     В файлах графического редактора неиспользуемые входы логических примитивов должны соединяться с VCC или GND.

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

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

Примитивы буферов

CARRY             OPNDRN

CASCADE         SOFT

EXP                  TRI

GLOBAL (SCLK)            WIRE (только GDF)

LCELL (MCELL)

Примитивы триггеров и защелок

DFF      SRFF

DFFE    SRFFE

JKFF    TFF

JKFFE  TFFE

LATCH

Примитивы/Порты входов и выходов

BIDIR или INOUT                      BIDIRC (только GDF)

INPUT или IN               INPUTC (только GDF)

OUTPUT или OUT        OUTPUTC(толькоGDF)

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

AND                              NOR

BAND (только GDF)      NOT

BNAND (только GDF)   OR

BNOR (только GDF)     VCC (только GDF)

BOR (только GDF)       XNOR

GND (только GDF)       XOR

NAND

            Другие примитивы (только GDF)

CONSTANT

PARAM

Title Block

Прототипы функций для примитивов в TDF файлах не нужны. Однако Вы можете переопределить порядок вызова входов примитива, вводя оператор Function Prototype в Ваш TDF.


Приоритеты булевых операторов и компараторов


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

Приоритет:

Оператор/Компаратор:

1

- (минус)

1

! (НЕ)

2

+ (сложение)

2

- (вычитание)

3

== (равно)

3

!= (не равно)

3

< (меньше чем)

3

<= (меньше чем или равно)

3

> (больше чем)

3

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

4

& (И)

4

!& (И-НЕ)

5

$ (Исключающее ИЛИ)

5

!$ (Исключающее ИЛИ-НЕ)

6

# (ИЛИ)

6

!# (ИЛИ-НЕ)



Присваивание состояний


Бит состояния - это выход триггера, который используется конечным автоматом для запоминания однобитного значения. В большинстве случаев Вы должны разрешить компилятору MAX+PLUS II присвоить биты состояния и значения для минимизации требующихся логических ресурсов: логический синтезатор автоматически минимизирует количество необходимых битов состояния, оптимизируя как использование устройства так и производительность.

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

Команда Global Project Logic Synthesis (меню Assign) включает опцию One-Hot State Machine Encoding (позиционное кодирование состояний), которая автоматически реализует этот тип кодирования для проекта. Кроме того, компилятор автоматически реализует позиционное кодирование для устройств FLEX 6000, FLEX 8000, и FLEX 10K, несмотря на то, включена или нет эта опция. Если Вы точно назначили биты состояния, в добавление к использованию автоматического позиционного кодирования, логика Вашего проекта может быть реализована неэффективно.

Файл stepper.tdf, приведенный ниже, реализует контроллер шагового двигателя.

SUBDESIGN stepper

(

   clk, reset   : INPUT;

   ccw, cw      : INPUT;

   phase[3..0]  : OUTPUT;

)

VARIABLE

   ss: MACHINE OF BITS (phase[3..0])

      WITH STATES  (

         s0 = B"0001",

         s1 = B"0010",

         s2 = B"0100",

         s3 = B"1000");

BEGIN

   ss.clk   = clk;

   ss.reset = reset;

   TABLE

      ss,   ccw,   cw   =>   ss;

      s0,   1,      x   =>   s3;

      s0,   x,      1   =>   s1;

      s1,   1,      x   =>   s0;

      s1,   x,      1   =>   s2;

      s2,   1,      x   =>   s1;

      s2,   x,      1   =>   s3;

      s3,   1,      x   =>   s2;

      s3,   x,      1   =>   s0;

   END TABLE;

END;

В этом примере выходы phase[3..0], объявленные в разделе Subdesign, также объявлены как биты конечного автомата ss в объявлении конечного автомата. Заметьте, что ccw и cw никогда не должны одновременно равняться 1 в одной и той же таблице. AHDL предполагает, что только одно условие в таблице истинности является истинным в одно и тоже время, следовательно, перекрытие комбинаций битов может привести к непредсказуемым результатам.



Раздел Logic


Раздел Logic определяет логическое функционирование текстового файла проекта (TDF) и является собственно его телом. В этом разделе могут быть многократно использованы следующие операторы и разделы:

¨    Булевские выражения.

¨    Управляющие булевские выражения.

¨    Оператор Case.

¨    Оператор Defaults.

¨    Оператор If Then.

¨    Оператор If Generate

¨    Оператор If Generate

¨    Оператор таблицы истинности

Þ   Раздел Logic может также содержать оператор Assert.

Раздел Logic заключается в ключевые слова BEGIN и END. За ключевым словом END следует символ (;), заканчивающий раздел. Если используется оператор Defaults, то он должен предшествовать всем другим операторам в этом разделе.

AHDL является параллельным языком. Компилятор анализирует поведенческую модель, описанную в разделе Logic, параллельно. Выражения, осуществляющие множественные присваивания объекту, имеющему тип NODE  или переменной, объединяются в соответствии с функцией монтажное ИЛИ.



Раздел Subdesign


Раздел Subdesign определяет входные, выходные и двунаправленные порты данного проекта.

Следующий пример демонстрирует использование раздела Subdesign:

SUBDESIGN top

(

            foo, bar, clk1, clk2        : INPUT = VCC;

            a0, a1, a2, a3, a4           : OUTPUT;

            b[7..0]                           : BIDIR;

)

Раздел Subdesign имеет следующие характеристики:

¨    За ключевым словом SUBDESIGN следует имя подпроекта. Имя подпроекта  должно совпадать с именем текстового файла проекта. В данном примере подпроект имеет имя top.

¨    Список сигналов заключается в круглые скобки.

¨    Сигналы представляются символическими именами  с определением их типа (например, INPUT)

¨    Имена сигналов отделяются друг от друга запятыми .За именами следует двоеточие, далее тип сигналов и символ (;).

¨    Возможными типами портов являются : INPUT, OUTPUT, BIDIR, MACHINE INPUT или MACHINE OUTPUT.В примере, показанном выше, сигналы foo, bar, clk1 и clk2, а сигналы a0, a1, a2, a3 и a4 являются выходами. Шина b[7..0] является двунаправленной.

¨    Ключевые слова MACHINE INPUT и MACHINE OUTPUT используются для импорта и экспорта конечных автоматов между текстовыми файлами проектов и другими файлами проектов. Однако типы портов MACHINE INPUT и MACHINE OUTPUT не могут использоваться в текстовых файлах проектов верхнего уровня.

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

В файле высшего уровня иерархии порты, имеющие тип INPUT, OUTPUT или BIDIR являются выводами устройства. В файлах более низких уровней иерархии все типы портов являются точками входа и выхода данного файла, но не устройства в целом.



Раздел Variable


Необязательный раздел Variable используется для описания и/или генерации переменных, используемых в разделе Logic. Переменные языка AHDL сходны с переменными, используемыми в языках высокого уровня; они используются для определения внутренней логики.

Следующий пример демонстрирует использование раздела Variable:

VARIABLE

            a, b, c   : NODE;

            temp                 : halfadd;

            ts_node            : TRI_STATE_NODE;

            IF DEVICE_FAMILY == "FLEX8000" GENERATE

                        8kadder            : flex_adder;

                        d, e                  : NODE;

            ELSE GENERATE

                        7kadder            : pterm_adder;

                        f, g                   : NODE;

            END GENERATE;

Раздел Variable может включать следующие операторы и конструкции:

¨    Описание объектов.

¨    Описание узлов.

¨    Описание регистров.

¨    Описание конечных автоматов.

¨    Описание псевдоимен конечных автоматов.

Þ      Раздел Variable может также содержать операторы If Generate, которые могут быть использованы для генерирования объектов, узлов, регистров, конечных автоматов,  и псевдоимен конечных автоматов.

Þ      Раздел Variable имеет следующие характеристики:

¨    Раздел начинается с ключевого слова VARIABLE.

¨    Определенные пользователем символические имена переменных отделяются друг от друга запятыми, а от соответствующего им типа символом двоеточия. Допустимыми типами переменных являются: NODE,  TRI_STATE_NODE, <primitive>, <megafunction>, <macrofunction> или <state machine declaration>. В примере, показанном выше, внутренними переменными являются a, b и c, имеющие тип NODE; temp является экземпляром макрофункции halfadd; и tsnode является объектом типа TRI_STATE_NODE.

¨    Каждая строка определения переменных заканчивается символом (;).

Þ      В файле с расширением .fit для текущего проекта могут иметь место имена, сгенерированные компилятором и имеющие в своем составе знак тильда (~). Если производится обратная аннотация  присоединений, осуществленных в файле с расширением .fit, то эти имена появятся в файле установок  и конфигурации  (.acf).Символ тильды зарезервирован исключительно для имен генерируемых компилятором; использовать их для обозначения выводов, узлов и групп (шин) запрещено.



Реализация булевых выражений и уравнений


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

Файл boole1.tdf,  приведенный ниже, демонстрирует два простых булевых выражения, представляющие два логических вентиля.

SUBDESIGN boole1

(

   a0, a1, b  : INPUT;

   out1, out2 : OUTPUT;

)

BEGIN

   out1 = a1 & !a0;

   out2 = out1 # b;

END;

В этом файле выход out1 является логическим И входов а1 и инверсии а0, а выход out2 логическим ИЛИ out1 и b. Порядок следования их в файле не важен.



Реализация двунаправленных выводов


MAX+PLUS II позволяет конфигурировать выводы I/O как двунаправленные. Двунаправленные выводы можно определить с помощью порта BIDIR, который соединяется с выходом примитива TRI. Сигнал между выводом и примитивом TRI является двунаправленным и может использоваться для управления другой логикой проекта.

Файлы bus_reg2.tdf и bus_reg3.tdf,  приведенные ниже, оба реализуют регистр, который фиксирует значение, обнаруженное на тристабильной шине. Также они могут выдавать запомненное значение обратно на шину. Один файл реализует DFF и TRI функции с помощью ссылок на логические функции. Другой файл использует объявления Register

и Instance, соответственно, в разделе Variable.

SUBDESIGN bus_reg2                 SUBDESIGN bus_reg3

(                                          (

clk : INPUT;                           clk : INPUT;

oe  : INPUT;                           oe  : INPUT;

io  : BIDIR;                             io  : BIDIR;

)                                          )

VARIABLE                             VARIABLE

   dff_out : NODE;                      my_dff  : DFF;

                                                   my_tri  : TRI;

BEGIN                                       BEGIN

   dff_out = DFF(io, clk, ,);             my_dff.d = io;

   io = TRI(dff_out, oe);                  my_dff.clk = clk;

                                                 my_tri.in = my_dff.q;

END;                                          my_tri.oe = oe;

                                                 io = my_tri.out;

                                                 END;

Двунаправленный сигнал io, управляемый примитивом TRI, используется в качестве входа d триггера D (DFF).

Также Вы можете присоединить двунаправленный вывод из TDF файла нижнего уровня к выводу верхнего уровня. Двунаправленный выходной порт подпроекта должен соединяться с двунаправленным выводом с верхнего уровня иерархии. Прототип Function для TDF файла нижнего уровня должен включать двунаправленный вывод в предложении RETURNS. Файл bidir1.tdf, приведенный ниже, включает четыре экземпляра функции bus_reg2, упомянутой выше.

FUNCTION bus_reg2 (clk, oe)

RETURNS (io);

SUBDESIGN bidir1

(

   clk, oe  : INPUT;

   io[3..0] : BIDIR;

)

BEGIN

   io0 = bus_reg2(clk, oe);

   io1 = bus_reg2(clk, oe);

   io2 = bus_reg2(clk, oe);

   io3 = bus_reg2(clk, oe);

END;



Реализация иерархических проектов


TDF файлы, написанные на языке AHDL, можно смешивать с другими файлами в проектную иерархию. Файлы низкого уровня могут быть или файлами, поставляемыми Altera-ой, или мега и макрофункциями, определенными пользователем.



Реализация конечных автоматов


Вы можете создать конечный автомат, объявив его имя, состояния и, дополнительно, биты конечного автомата в объявлении конечного автомата в разделе Variable.

Файл simple.tdf, приведенный ниже, обладает такой же функциональностью как D триггер (DFF).

SUBDESIGN simple

(

   clk, reset, d : INPUT;

   q             : OUTPUT;

)

VARIABLE

   ss: MACHINE WITH STATES (s0, s1);

BEGIN

   ss.clk = clk;

   ss.reset = reset;

   CASE ss IS

      WHEN s0 =>

         q = GND;

         IF d THEN

            ss = s1;

         END IF;

      WHEN s1 =>

         q = VCC;

         IF !d THEN

            ss = s0;

         END IF;

   END CASE;

END;

В файле simple.tdf конечный автомат с именем ss объявлен в разделе Variable. Состояния автомата определены как s0 и s1, а биты состояния не объявлены.

Переходы конечного автомата определяют условия изменения к новому состоянию. Вы должны условно присвоить состояния в пределах одной поведенческой конструкции для определения переходов конечного автомата. Для этой цели рекомендуются операторы Case или Table. Например, в simple.tdf переходы из каждого состояния определяются в предложениях WHEN оператора Case.

Вы можете также определить выходное значение для состояния с помощью оператора If Then или Case. В операторах Case эти присваивания выполняются в предложениях WHEN. Например, в simple.tdf выход q присваивается GND, когда конечный автомат ss находится в состоянии s0 и VCC, когда автомат находится в состоянии s1.

Выходные значения можно также определить в таблицах истинности как описано в пункте 1.2.7.3 Присваивание состояний.



Реализация LCELL & SOFT примитивов


Вы можете ограничить размер (масштаб) логического синтеза путем изменения переменных NODE на SOFT

и LCELL примитивы. NODE переменные и  LCELL примитивы обеспечивают наибольшее управление всем логическим синтезом. SOFT

примитивы не предусмотрены для управления всем логическим синтезом.

NODE

переменные, объявленные с помощью объявления Node в разделе Variable налагают несколько ограничений на логический синтез. Во время синтеза логический синтезатор заменяет каждый экземпляр переменной NODE логикой, которая представляет переменную. Затем он минимизирует логику для подгонки в одну  логическую ячейку. Обычно этот метод дает самую большую скорость, но может приводить к слишком сложной логике.

SOFT

буферы обеспечивают больший контроль по использованию ресурсов, чем NODE  переменные. Логический синтезатор выбирает, когда заместить экземпляры SOFT

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

LCELL

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

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

MAX+PLUS II обеспечивает несколько логических опций, которые автоматически вставляют или удаляют SOFT

и LCELL буферы в соответствующих местах проекта.

Следующая иллюстрация демонстрирует два варианта TDF файла: один реализуется с помощью NODE

переменных, а другой с SOFT примитивами. В nodevar переменная odd_parity объявлена как NODE и затем ей присвоено значение булева выражения d0 $ d1 $ ... $ d8. В softbuf компилятор замещает некоторые SOFT примитивы на LCELL примитивы во время обработки для улучшения использования устройства.

TDF с NODE переменными:    TDF с SOFT примитивами:

SUBDESIGN nodevar                SUBDESIGN softbuf

(                                               (

)                                               )

VARIABLE                                 VARIABLE

odd_parity : NODE;                   odd_parity : NODE;

BEGIN                                      BEGIN

odd_parity =                             odd_parity =

d0 $ d1 $ d2$                            SOFT(d0 $ d1 $ d2) $

d3 $ d4 $ d5$                            SOFT(d3 $ d4 $ d5) $

d6 $ d7 $ d8;                            SOFT(d6 $ d7 $ d8);

END;                                         END;



Реализация логики с активными низкими уровнями


Активный низкий сигнал становится активным, когда его значение равно GND. Активные низкие сигналы могут быть полезны при управлении памятью, периферийными устройствами и микропроцессорными кристаллами.

Файл daisy.tdf,  приведенный ниже, является модулем схемы арбитра по методу дейзи-цепочки. Он принимает запросы на доступ к шине от самого себя и от следующего модуля в цепочке. Доступ к шине предоставляется модулю с наивысшим приоритетом, запросившим его.

SUBDESIGN daisy

(

/local_request   : INPUT;

/local_grant      : OUTPUT;

/request_in       : INPUT;            % от младшего приоритета %

/request_out     : OUTPUT; % к старшему приоритету %

/grant_in          : INPUT;            % от старшего приоритета %

/grant_out         : OUTPUT;% к младшему приоритету %

)

BEGIN

            DEFAULTS

/local_grant = VCC;% активные низкие выходы %

/request_out=VCC;

%должны быть равны по умолчанию %

/grant_out = VCC;         % VCC  %

            END DEFAULTS;

            IF /request_in == GND # /local_request == GND THEN

/request_out = GND;

            END IF;

            IF /grant_in == GND THEN

                        IF /local_request == GND THEN

                                    /local_grant = GND;

                        ELSIF /request_in == GND THEN

                                    /grant_out = GND;

                        END IF;

            END IF;

END;

 

Все сигналы в этом файле активные низкие. Altera рекомендует, чтобы Вы выбирали схему именования узлов, ясно указывающую имена активных низких сигналов, например, начальное "n" или слеш  (/).

Операторы If Then

используются для определения активности модулей,  т.е. равен ли сигнал GND. Если сигнал активный, то активизируются уравнения, следующие за соответствующим оператором If Then.



Реализация RAM & ROM


MAX+PLUS II (и AHDL) снабжены несколькими LPM и мегафункциями, которые позволяют Вам реализовать RAM и ROM в устройствах MAX+PLUS II. Универсальная, масштабируемая природа каждой из этих функций гарантирует, что Вы можете использовать их для реализации любых поддерживаемых типов RAM или ROM в MAX+PLUS II.

Altera не рекомендует создавать заказные логические функции для реализации памяти. Вы должны использовать поставляемые Altera функции во всех случаях, где Вы хотите реализовать RAM или ROM.

Можно использовать следующие мегафункции для реализации RAM и ROM в MAX+PLUS II:

Имя

Описание

lpm_ram_dq  

Синхронная или асинхронная память с раздельными портами ввода вывода

lpm_ram_io   

Синхронная или асинхронная память с единственным портов I/O

lpm_rom        

Синхронная или асинхронная память только для считывания

csdpram

Двухпортовая память

csfifo

Буфер FIFO

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



Реализация тристабильных шин


Примитивы TRI, которые управляют портами OUTPUT или BIDIR, имеют вход разрешения выхода (Output Enable), который переводит выход в высокоимпедансное состояние.

Вы можете создать тристабильную шину путем соединения примитивов TRI и портов OUTPUT или BIDIR вместе с помощью узла TRI_STATE_NODE типа. Схема управления должна обеспечивать разрешение не более одного выхода в одно и тоже время.

Файл tri_bus.tdf, приведенный ниже, реализует тристабильную шину, используя узел TRI_STATE_NODE типа, созданный в объявлении Node.

SUBDESIGN tri_bus

(

   in[3..1], oe[3..1] : INPUT;

   out1               : OUTPUT;

)

VARIABLE

   tnode : TRI_STATE_NODE;

BEGIN

   tnode = TRI(in1, oe1);

   tnode = TRI(in2, oe2);

   tnode = TRI(in3, oe3);

   out1 = tnode;

END;

В этом примере несколько присваиваний узлу tnode, связывают сигналы вместе. Для реализации тристабильной шины требуется тип TRI_STATE_NODE, вместо типа NODE: для типа NODE сигналы связываются вместе с помощью проводного И или проводного ИЛИ, тогда как для типа TRI_STATE_NODE сигналы соединяются с тем же самым узлом. Однако, если только одна переменная присваивается узлу TRI_STATE_NODE, то она трактуется как переменная обычного типа NODE.



Реализация условной логики


Операторы If Then и Case

идеально подходят для реализации условной логики. Операторы If Then

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

Условную логику, реализуемую с помощью операторов If Then и Case, не следует путать с логикой, создаваемой условно оператором If Generate. Эта логика не обязательно является условной.



Шины


Символьные имена и порты одного и того же типа можно объявить и использовать как шины в булевых выражениях и уравнениях.

Шина, которая может содержать до 256 членов (или битов), рассматривается как коллекция узлов и действует как одно целое.

Одиночные узлы и константы GND и VCC можно дублировать для создания шин.

Шины можно объявить с помощью следующих трех способов:

1.   Имя шины состоит из символьного имени или имени порта, за которым следует указание поддиапазона, заключенного в скобки, т.е. a[4..1]. Имя вместе с самым длинным числом в диапазоне может содержать до 32 символов. Например,

Имя q[MAX..0] правильно, если константа MAX была описана выше в операторе Constant.

После определения шины скобки [] являются коротким способом описания всего диапазона. Например,

a [4..1] можно указать как a[].

b [6..0][3..2] можно указать как b[][].

2.   Имя шины состоит из символьного имени или имени порта, за которым следует указание поддиапазонов, заключенных в скобки, т.е. d[6..0][2..0]. Имя вместе с самым длинным числом в диапазоне может содержать до 32 символов. К индивидуальному узлу в шине можно обратиться как name[y][z] или namey_z, где y и z числа в диапазоне шины.

3.   Последовательное имя шины состоит из списка символьных имен, портов или чисел, разделенных запятыми и заключенных в скобки, например, (a, b, c).

Эта нотация полезна для определения имен портов. Например,

Входные порты переменной reg типа DFF можно записать как reg.(d, clk, clrn, prn).

Ниже приведены две совокупности примеров, демонстрирующие две шины, описанные с помощью различной нотации:

b[5..0]

(b5, b4, b3, b2, b1, b0)

b[]

b[log2(256)..1+2-1]

b[2^8..3 mod 1]

b[2*8..8 div 2]



Символы


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

Символ

Функция

_        (подчеркивание)           

Идентификаторы, описанные пользователем и используемые как допустимые символы в символьных именах.

-           (тире)

/           (прямой слеш)

--          (два тире)       

Начинает однострочный комментарий в VHDL стиле

%         (процент)

Ограничивает комментарий в AHDL стиле

( )         (круглые скобки)

Ограничивают и определяют последовательные имена шин. Например,

            шина (a, b, c) состоит из узлов a, b, и c.

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

Дополнительно, ограничивает входы и выходы таблиц истинности в операторах Truth Table.

Заключают биты и состояния объявлений State Machine.

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

Ограничивают определения параметров в операторах Parameters, объявлениях Instance и параметрические имена в операторах Function Prototype и в подставляемых ссылках.

Дополнительно, ограничивают условие в операторе Assert.

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

[ ]         (скобки)

Ограничивают диапазон шины

'...'        (кавычки)

Ограничивают символьные имена

"..."       (двойные кавычки)

Ограничивают строки в операторах Title, Parameters, Assert.

Ограничивают имена файлов в операторах Include.

Ограничивают цифры в недесятичных числах

.           (точка)

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

Отделяет расширения от имен файлов.

..          (эллипс)

Отделяет старший бит от младшего.

;           (точка с запятой)

Оканчивает операторы и разделы AHDL.

,           (запятая)

Отделяет символьные имена от типов в объявлениях.

=          (равно)

Присваивает входам значения по умолчанию GND и VCC в разделе Subdesign.

Присваивает значения опциям в операторе Options.

Присваивает значения по умолчанию параметрам в операторе Parameters или в подставляемой ссылке.

Присваивает значения состояниям конечного автомата.

Присваивает значения булевым уравнениям.

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

=>         (стрелка)

Отделяет входы от выходов в операторах Truth Table.

Отделяет WHEN предложения от булевых выражений в операторах Case.

+          (плюс)

Оператор сложения

-           (минус)

Оператор вычитания

==         (два знака равенства)

Оператор эквивалентности строк или чисел

!           (восклицательный знак)

Оператор НЕ

!=         (знак восклицание равно)

Оператор неравенства

>          (больше чем)

Компаратор больше чем

>=         (больше или равно)

Компаратор больше чем или равно

<          (меньше чем)

Компаратор меньше чем

<=         (меньше или равно)

Компаратор меньше чем или равно

&          (амперсант)    

Оператор И

!&         (восклицание амперсант)

Оператор И-НЕ

$          (знак доллара)

Оператор Исключающее - ИЛИ

!$         (восклицание доллар)

Оператор Исключающее - ИЛИ - НЕ

#          (знак фунта)   

Оператор ИЛИ

!#         (восклицание фунт)   

Оператор ИЛИ-НЕ

?          (вопрос)

Тернарный оператор. Он использует следующий формат:

<выражение 1> ? < выражение 2> : < выражение 3>

Если первое выражение не ноль (истина), то вычисляется второе выражение и результат возвращается тернарному выражению. В противном случае возвращается значение третьего выражения.



Создание дешифраторов


В AHDL  для создания дешифратора Вы можете использовать или оператор Truth Table или lpm_compare или  lpm_decode функции.

Файл 7segment.tdf,  приведенный ниже, является дешифратором для комбинации светоизлучающих диодов (LED). LED отображают шестнадцатеричные числа.

SUBDESIGN 7segment

(

i[3..0]                : INPUT;

a, b, c, d, e, f, g            : OUTPUT;

)

BEGIN

   TABLE

      i[3..0]  => a, b, c, d, e, f, g;

      H"0"    => 1, 1, 1, 1, 1, 1, 0;

      H"1"    => 0, 1, 1, 0, 0, 0, 0;

      H"2"    => 1, 1, 0, 1, 1, 0, 1;

      H"3"    => 1, 1, 1, 1, 0, 0, 1;

      H"4"    => 0, 1, 1, 0, 0, 1, 1;

      H"5"    => 1, 0, 1, 1, 0, 1, 1;

      H"6"    => 1, 0, 1, 1, 1, 1, 1;

      H"7"    => 1, 1, 1, 0, 0, 0, 0;

      H"8"    => 1, 1, 1, 1, 1, 1, 1;

      H"9"    => 1, 1, 1, 1, 0, 1, 1;

      H"A"    => 1, 1, 1, 0, 1, 1, 1;

      H"B"    => 0, 0, 1, 1, 1, 1, 1;

      H"C"    => 1, 0, 0, 1, 1, 1, 0;

      H"D"    => 0, 1, 1, 1, 1, 0, 1;

      H"E"    => 1, 0, 0, 1, 1, 1, 1;

      H"F"    => 1, 0, 0, 0, 1, 1, 1;

   END TABLE;

END;

В этом примере выходной  набор для всех 16 возможных  входных наборов i[3..0] описан в операторе Truth Table

Файл decode3.tdf,  приведенный ниже, является дешифратором адреса для реализации 16-битной микропроцессорной системы.

SUBDESIGN decode3

(

addr[15..0], m/io         : INPUT;

rom, ram, print, sp[2..1] : OUTPUT;

)

BEGIN

   TABLE

      m/io, addr[15..0]                    => rom, ram,  print,    sp[];

      1,    B"00XXXXXXXXXXXXXX"              => 1,    0,       0,         B"00";

      1,    B"100XXXXXXXXXXXXX"               => 0,    1,       0,         B"00";

      0,    B"0000001010101110"      => 0,    0,       1,         B"00";




      0,    B"0000001011011110"      => 0,    0,       0,         B"01";

      0,    B"0000001101110000"      => 0,    0,       0,         B"10";

   END TABLE;

END;

В этом примере существуют тысячи входных наборов и описывать их все в операторе Truth Table

непрактично. Вместо этого Вы можете использовать логический уровень Х для указания того, что выход не зависит от соответствующего входа. Например, в первой строчке оператора TABLE выход  rom должен быть высоким для всех 16,384 входных наборов addr[15..0], начинающихся с 00. Следовательно Вам необходимо точно определить только общую часть входного набора, а для остальных входов использовать символ Х.

При использовании символов Х  Вы должны гарантировать отсутствие наложений между битовыми комбинациями в таблице истинности. Язык AHDL предполагает что одновременно только одно условие в таблице истинности может быть истинно.

Файл decode4.tdf, приведенный ниже, использует функцию lpm_decode для получения такой же функциональности как и файл decode1.tdf.

INCLUDE "lpm_decode.inc";

SUBDESIGN decode4

(

address[15..0]   : INPUT;

chip_enable      : OUTPUT;

)

BEGIN

chip_enable = lpm_decode(.data[]=address[])

WITH (LPM_WIDTH=16, LPM_DECODES=2^10)

      RETURNS (.eq[H"0370"]);

END;


Создание счетчиков


Счетчики можно определить с помощью D триггеров (DFF и DFFE) и операторов If Then или с помощью функции lpm_counter.

Файл ahdlcnt.tdf, приведенный ниже, реализует 16-битный суммирующий счетчик с загрузкой, который можно сбросить в ноль.

SUBDESIGN ahdlcnt

(

   clk, load, ena, clr, d[15..0] : INPUT;

   q[15..0]                      : OUTPUT;

)

VARIABLE

   count[15..0]                  : DFF;

BEGIN

   count[].clk = clk;

   count[].clrn = !clr;

   IF load THEN

      count[].d = d[];

   ELSIF ena THEN

      count[].d = count[].q + 1;

   ELSE

      count[].d = count[].q;

   END IF;

   q[] = count[];

END;

В этом файле в разделе Variable

объявляется 16 триггеров с имена count0 по count15. Оператор If Then

определяет значение, которое загружается в триггеры на возрастающем фронте Clock.

Файл lpm_cnt.tdf, приведенный ниже, использует функцию lpm_counter для реализации той же функциональности, что и файл ahdlcnt.tdf.

INCLUDE "lpm_counter.inc";

SUBDESIGN lpm_cnt

(

   clk, load, ena, clr, d[15..0] : INPUT;

   q[15..0]                      : OUTPUT;

)

VARIABLE

   my_cntr: lpm_counter WITH (LPM_WIDTH=16);

BEGIN

   my_cntr.clock  = clk;

   my_cntr.aload  = load;

   my_cntr.cnt_en = ena;

   my_cntr.aclr   = clr;

   my_cntr.data[] = d[];

   q[] = my_cntr.q[];

END;



Создание текстового выходного файла


Вы можете создать один или больше текстовых выходных файлов проекта (Text Design Output Files (.tdo)), которые содержат AHDL эквивалент полностью оптимизированной логики для устройства, применяющегося в проекте. Кроме того Компилятор создает также один или больше выходных файлов назначения и конфигурации (Assignment & Configuration Output Files (.aco)).

Вы можете сохранить TDO файл как текстовой файл проекта, отредактировать его, определить его как проект с помощью команд меню File: Project Name

или Project Set Project to Current File

и перекомпилировать проект (Вы должны также сохранить ACO файл как файл Assignment & Configuration File если Вы хотите сохранить распределения для устройства).

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

Для создания TDO файла для проекта:

1.   Включите опцию Generate AHDL TDO File в команде меню Processing.

2.   Для начала компиляции выберите кнопку Start в окне компилятора или одну из команд в меню File: Project Save & Compile или  Project Save, Compile & Simulate в любом из приложений MAX+PLUS II.



Строковые и символьные имена


В AHDL существует три типа имен:

A.            Символьные имена являются идентификаторами, описываемыми пользователем. Они используются для объявления следующих частей TDF:

1.             Внутренних и внешних узлов и шин

2.             Констант

3.             Переменных конечных автоматов, битов состояний и имен состояний

4.             Экземпляров

5.             Параметров

6.             Сегментов памяти

7.             Оценочных функций

8.             Именованных операторов

B.            Имена подпроектов - это имена, которые пользователь определил для файлов проекта более низкого уровня. Имя подпроекта должно совпадать с именем TDF файла.

C.            Имена портов - это символьные имена, идентифицирующие входы или выходы логической функции.

Компилятор генерирует имена содержащие символ тильда (~), которые могут появляться в файле подгонки (Fit File) проекта. При использовании обратной аннотации [M1] эти имена появятся и в ACF файле проекта. Символ тильда зарезервирован только для имен, генерируемых компилятором и Вы не можете использовать его в Ваших собственных именах выводов, узлов и шин.

Для трех типов имен доступны два вида представления: с использованием кавычек и без них. Строковые имена заключаются в одиночные кавычки ('), а символьные имена без них.

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



Структура проекта


Этот раздел описывает структуру проекта на языке AHDL. Разделы и операторы языка AHDL описываются в том порядке, в котором они следуют в текстовом файле проекта (TDF - Text Design File).

¨    Обзор

¨    Оператор Title

¨    Оператор Parameters

¨    Оператор Include

¨    Оператор Constant

¨    Оператор Define

¨    Оператор Function Prototype

¨    Оператор Options

¨    Оператор Assert

¨    Раздел Subdesign

¨    Раздел Variable

Раздел Logic



Управляющие булевские выражения


Управляющие булевские выражения используются в разделе Logic для определения значений сигналов Clock, Reset и Clock Enable в конечных автоматах.

Следующий пример демонстрирует использование управляющих булевских выражений:

ss.clk = clk1;

ss.reset = a & b;

ss.ena = clk1ena;

Управляющие булевские выражения имеют следующие характеристики:

¨    Значения сигналов Clock, Reset и Clock Enable для всякого конечного автомата могут быть определены с использованием следующего формата: <имя конечного автомата>.<имя порта>.В примере, показанном выше, значения этих входов определены для конечного автомата с именем ss.

¨    Имя конечного автомата, определенное на этапе его объявления, может быть использовано  в управляющих булевских выражениях.

¨    Тактирующему сигналу <имя конечного автомата>.clk должно быть присвоено значение.

¨    Если в качестве начального значения конечного автомата выбрано ненулевое значение, то  должен использоваться сигнал начальной установки <имя конечного автомата>.reset; в противном случае использование этого сигнала необязательно.

¨    Использовать тактирующий сигнал <имя конечного автомата>.ena  необязательно.

¨    Каждое выражение заканчивается символом (;).



Установка сигналов Clock, Reset & Enable


Сигналы Clock, Reset, и Clock Enable управляют триггерами регистра состояний конечного автомата. Эти сигналы определяются с помощью булевых уравнений управления в разделе Logic.

В файле simple.tdf, приведенном ниже, Clock конечного автомата управляется входом clk. Сигнал асинхронного сброса конечного автомата Reset управляется сигналом reset, который является активным высоким. В этом файле проекта объявление входа ena в разделе Subdesign

и булева уравнения ss.ena = ena в разделе Logic подсоединяет сигнал Clock Enable.

SUBDESIGN simple

(

   clk, reset, ena, d : INPUT;

   q                  : OUTPUT;

)

VARIABLE

   ss: MACHINE WITH STATES (s0, s1);

BEGIN

   ss.clk = clk;

   ss.reset = reset;

   ss.ena = ena;

   CASE ss IS

      WHEN s0 =>

         q = GND;

         IF d THEN

            ss = s1;

         END IF;

      WHEN s1 =>

         q = VCC;

         IF !d THEN

            ss = s0;

         END IF;

   END CASE;

END;



Вставка шаблонов AHDL


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

Для вставки шаблона AHDL в текущую позицию ввода:

1.   Откройте диалоговое окно AHDL Template

с помощью команды меню Template.

2.   Выберите имя в окне Template Section.

3.   Нажмите OK.

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



Встроенные оценочные функции


В AHDL встроены следующие предопределенные оценочные функции, которые не нужно определять в операторах Define:

¨    USED, которую можно использовать для контроля того, использовался ли порт, например, в операторе If Generate или Parameters. USED принимает имя порта в качестве входа и возвращает значение FALSE, если порт не используется.

¨    CEIL, которая возвращает наименьшее целое число большее вещественного числа. Хотя эта операция применима ко всем арифметическим выражениям, она имеет смысл только для LOG2 и DIV, в которых результат может быть вещественным.

¨    FLOOR, которая возвращает наибольшее целое число меньшее вещественного числа. Хотя эта операция применима ко всем арифметическим выражениям, она имеет смысл только для LOG2 и DIV, в которых результат может быть вещественным.

Примеры

CEIL(LOG2(255)) = 8

FLOOR(LOG2(255)) = 7

Использованный статус протестирован  в операторе Assert:

USED(aconst) == # 0 USED(AVALUE)   



язык описания аппаратуры фирмы Altera)


AHDL
( язык описания аппаратуры фирмы Altera) является высокоуровневым, модульным языком, полностью интегрированным в систему MAX+PLUS II. Он особенно хорошо подходит для проектирования сложной комбинационной логики, шин, конечных автоматов, таблиц истинности и параметрической логики. Вы можете использовать текстовой редактор системы MAX+PLUS II или любой другой для создания текстовых файлов проектов (AHDL Text Design Files (.tdf)). Затем Вы можете откомпилировать TDF файлы для получения выходных файлов, пригодных для последующего моделирования, временного анализа и программирования устройства. Кроме того компилятор системы MAX+PLUS II может создавать текстовые файлы экспортирования (AHDL Text Design Export Files (.tdx)) и текстовые выходные файлы (Text Design Output Files (.tdo)), которые можно сохранить как TDF файлы и повторно использовать в качестве файлов проекта.
Как  работает AHDL?
Операторы и элементы AHDL являются мощным, многогранным и легким в использовании  средством. Вы можете создавать весь иерархический проект с помощью AHDL или смешивать TDF файлы с другими типами файлов в один проект.
Хотя Вы можете воспользоваться любым текстовым редактором для создания TDF файлов, но только текстовой редактор системы MAX+PLUS II дает Вам возможность воспользоваться его преимуществами, когда Вы вводите, компилируете и отлаживаете Ваш AHDL проект.
AHDL проект легко вставить в иерархию проекта. В текстовом редакторе Вы можете автоматически создавать символ, представляющий TDF файл и вводить его в графический файл проекта (Graphic Design File (.gdf)). Аналогичным образом Вы можете объединять заказные функции и свыше 300 мегафункций и макрофункций, поставляемых Альтерой, включая функции библиотеки параметрических модулей (LPM), в  любой TDF файл.
Вы можете использовать команды меню Assign или Assignment & Configuration File (.acf) для создания ресурса и выбора устройства. Вы можете также проверить синтаксис и выполнить полную компиляцию для отладки и прогона Вашего проекта. Любые появляющиеся ошибки автоматически локализуются процессором сообщений (Message Processor ) и выделяются в окне текстового редактора.

Выход из некорректных состояний


Логика, созданная для конечного автомата компилятором MAX+PLUS II, будет вести себя так, как Вы описали в файле TDF. Тем не менее проекты  конечных автоматов, которые точно объявляют биты состояния, и которые не используют позиционного кодирования, часто допускают значения битов состояния, которые не связаны с действительными состояниями. Эти не присвоенные значения называются не корректными состояниями. Проект, который вводит некорректные состояния, например, в результате нарушений времени предустановки и удержания, может приводить к неверным выходам. Хотя Altera рекомендует, чтобы входы конечного автомата удовлетворяли всем временным требованиям, Вы можете заставить конечный автомат принудительно вернуться из некорректного состояния в известное состояние с помощью оператора Case.

Для возвращения из некорректных состояний в проектах не использующих FLEX устройств, или проектов не использующих опцию позиционного кодирования, Вы должны назвать все некорректные состояния автомата. Предложение WHEN OTHERS в операторе Case, которое принуждает выполнить каждый переход из некорректного состояния в известное состояние, применяется только к состояниям, которые объявлены, но не упоминаются в предложении WHEN. Предложение WHEN OTHERS может форсировать принудительные переходы, только если все некорректные состояния объявлены в объявлении конечного автомата.

Для n-битного конечного автомата, существует 2n возможных состояний. Если Вы объявили n бит Вы должны продолжать добавлять имена фиктивных состояний до тех пор, пока количество состояний не достигнет степени 2. Файл recover.tdf, приведенный ниже, содержит автомат, который может возвращаться из некорректных состояний.

SUBDESIGN recover

(

   clk : INPUT;

   go  : INPUT;

   ok  : OUTPUT;

)

VARIABLE

   sequence : MACHINE

            OF BITS (q[2..0])

            WITH STATES (  

               idle,

               one,

               two,

               three,

               four,

               illegal1,   

               illegal2,   

               illegal3);

BEGIN

   sequence.clk = clk;

   CASE sequence IS

      WHEN idle =>

         IF go THEN

            sequence = one;

         END IF;

      WHEN one =>

         sequence = two;

      WHEN two =>

         sequence = three;

      WHEN three =>

         sequence = four;

      WHEN OTHERS =>

         sequence = idle;

   END CASE;

   ok = (sequence == four);

END;

Этот пример содержит 3 бита: q2, q1, и q0. Следовательно существует 8 состояний. Так как объявлено только 5 состояний, были добавлены 3 фиктивных состояния.



Зарезервированные идентификаторы


Ниже приведен список всех зарезервированных идентификаторов:

CARRY

JKFFE

SRFFE

CASCADE

JKFF

SRFF

CEIL

LATCH

TFFE

DFFE

LCELL

TFF

DFF

MCELL

TRI

EXP

MEMORY

USED

FLOOR

OPENDRN

WIRE

GLOBAL

SOFT

X



Зарезервированные слова


Зарезервированные ключевые слова используются для управления операторами AHDL, а также для предопределенных констант GND и VCC.

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

Altera рекомендует вводить все ключевые слова с заглавных букв для удобства чтения.

Для получения контекстно-зависимой помощи по ключевому слову сначала убедитесь, что TDF файл сохранен с расширением .tdf. Затем откройте файл в окне текстового редактора и нажмите Shift+F1 и щелкните кнопкой 1 на нем или выберите кнопку контекстно-зависимой помощи на панели инструментов.

Ниже приведен список всех зарезервированных ключевых слов:

AND

FUNCTION

OUTPUT

ASSERT

GENERATE

PARAMETERS

BEGIN

GND

REPORT

BIDIR

HELP_ID

RETURNS

BITS

IF

SEGMENTS

BURIED

INCLUDE

SEVERITY

CASE

INPUT

STATES

CLIQUE

IS

SUBDESIGN

CONNECTED_PINS

LOG2

TABLE

CONSTANT

MACHINE

THEN

DEFAULTS

MOD

TITLE

DEFINE

NAND

TO

DESIGN

NODE

TRI_STATE_NODE

DEVICE

NOR

VARIABLE

DIV

NOT

VCC

ELSE

OF

WHEN

ELSIF

OPTIONS

WITH

END

OR

XNOR

FOR

OTHERS

XOR