ЯЗЫК ОПИСАНИЯ ЛОГИЧЕСКИХ СХЕМ DSL
Язык высокого уровня Design Synthesis Language (DSL) предназначен для текстового описания цифровых устройств в САПР DesignLab фирмы MicroSim. В этом языке отсутствуют средства для описания временных задержек, поэтому его применение ограничено функциональным моделированием цифровой аппаратуры и синтезом программируемой логики.
DSL имеет средства для описания логических и арифметических выражений, таблиц истинности (Truth Tables) и конечных автоматов (State Machines). Кроме того, для создания моделей отдельных блоков имеются такие инструментальные средства, как процедуры и функции, операторы IF и CASE, макросы. Цифровые сигналы в языке SDL могут принимать четыре значения {0, 1, .X., .Z.}.
Мы будем знакомиться с основными особенностями языка DSL «оперативно», то есть изучать только то, что требуется в данный момент. Это наиболее эффективный подход к изучению компьютерных языков, он экономит время, хотя и оставляет «белые пятна».
ПРОЦЕДУРЫ И ФУНКЦИИ
Построим DSL-модель какого-нибудь простого логического элемента, например схемы 2И, назовём её AND2_DSL. На этом языке любая модель оформляется в виде процедуры или функции, как показано на рис.1.

Рис.1. DSL-модель логического элемента, выполняющего функцию 2И
Приведённый текст понятен любому человеку, мало-мальски знакомому с азами программирования. После ключевого слова PROCEDURE или FUNCTION следует имя модели, совпадающее с именем моделируемого элемента, а затем в круглых скобках перечисляются его входы и выходы.
Очевидно, что представление программной модели с помощью функции не универсально и пригодно лишь для элементов с одним выходом. В списке формальных параметров функции могут находиться только входные сигналы. Следовательно, ключевое слово INPUT теряет смысл и обычно опускается.
Кроме входов и выходов цифровые элементы иногда имеют двунаправленные контакты. В качестве примера можно назвать двунаправленные шинные драйверы. Для описания таких выводов в языке DSL применяется ключевое слово BIPUT. Но оно допустимо только в процедурах.
Именно процедуры являются главными строительными блоками проекта. В этом легко убедиться, если проделать простой эксперимент. Разместите в редакторе Schematics пакета DesignLab 8 простой иерархический блок с одним выходом, задайте ему какое-нибудь имя и тип DSL. Понизив уровень описания блока (раскрыв чёрный ящик), вы обнаружите, что редактор автоматически создал шаблон DSL-описания в виде процедуры. Он (редактор) не стал разбираться, что блок имеет один выход и, значит, может быть описан как функция.
По образу и подобию создадим DSL-модели для элементов 2ИЛИ (OR2_DSL) и НЕ (INVR_DSL). Они показаны на рис.2 и 3.

Рис.2. DSL-модель логического элемента, выполняющего функцию 2ИЛИ

Рис.3. DSL-модель логического элемента, выполняющего функцию НЕ
Как и в любом языке программирования одни процедуры могут вызывать другие процедуры, нельзя лишь ссылаться на самих себя. Все процедуры или функции должны быть определены внутри того файла, где они используются. Понятно, что описание процедуры должно предшествовать её вызову.
В качестве примера построим DSL-модель мультиплексора MUX2_DSL (рис.4, а). В нём используются элементы, для которых уже имеются соответствующие модели. Поэтому всё просто. Сначала декларируем нужные процедуры или функции, а затем вызываем их, заменяя формальные параметры IN1, IN2, OUT1 фактическими D0, D1, A, F1, F2, F3, Y (рис.4, б).
В теле процедуры MUX2_DSL объявлены три локальные переменные F1, F2, F3. В языке DSL они называются узлами (NODE - узел) или сигналами. Локальные узлы используются для имитации внутренних соединений в моделируемой схеме. В примере декларированы так называемые комбинационные узлы, то есть не тактируемые узлы, без синхронизации. Название говорит само за себя: такие узлы используются для описания комбинационных схем. Их значения обновляются в момент выполнения соответствующего оператора, не дожидаясь сигнала синхронизации. О тактируемых узлах мы поговорим позднее.

Рис. 4. Функциональная схема и DSL-модель мультиплексора MUX2_DSL
Кроме того, узлы могут быть физическими (PHYSICAL) или виртуальными (VIRTUAL). В процессе синтеза схем по его DSL-описанию оптимизатор создаёт физические узлы и может разрушать виртуальные. Удаляя виртуальные узлы (промежуточные переменные), оптимизатор сокращает систему логических уравнений в DSL-описании проекта.
Если в примере, показанном на рис.4, б, мы объявим:
PHYSICAL NODE F1; “ Физический узел F1
VIRTUAL NODE F2, F3; “ Виртуальные узлы F2 и F3
то оптимизатор может заменить три элемента DD1, DD2, DD3 одним элементом 2И-2ИЛИ-НЕ, реализующим ту же самую логическую функцию:
F1 = INVR_DSL (A);
Y = OR2_DSL (D0*F1, D1*A);
Как видно, теперь система логических уравнений сократилась вдвое, а узлов F2 и F3 нет и в помине. Обратите внимание, в качестве фактических параметров в функцию OR2_DSL подставлены выражения. Заметим, что и само значение, возвращаемое функцией, можно использовать в другом выражении, например:
Y = F1*OR2_DSL (D0*F1, D1*A);
БИБЛИОТЕЧНЫЕ ФАЙЛЫ. ДИРЕКТИВЫ USE И INCLUDE
Существует другой более изящный стиль, при котором процедуры декларируются в отдельном файле, называемом библиотечным. Этот файл компилируется программой PLSyn и может в дальнейшем подключаться к любому DSL-файлу, в котором используются библиотечные процедуры.
Создадим библиотечный файл LIB_DSL_PROC. dsl и запишем в него описания процедур AND2_DSL, OR2_DSL и INVR_DSL (рис.5, а). Модель мультиплексора напишем и сохраним в другом файле, например MUX2_DSL. dsl (рис.5, б). Чтобы получить доступ к библиотечным процедурам, сделаем ссылку на библиотечный файл LIB_DSL_PROC. dsl с помощью ключевого слова USE - использовать. Вслед за ним укажем имя нужного файла (без расширения), где хранятся требуемые процедуры. Имя файла следует заключить в одиночные кавычки (апострофы).

Рис.5. Использование необходимых процедур из библиотечного файла
Если библиотечный файл содержит много процедур, а нам нужны только некоторые из них, то их можно перечислить явным образом, отделив имя процедуры от имени файла точкой, то есть вот так:
USE 'LIB_DSL_PROC'.AND2_DSL;
USE 'LIB_DSLPROC'.OR2_DSL;
USE 'LIB_DSL_PROC'.INVR_DSL;
Впрочем, последнее делать не обязательно, в любом случае при ссылке на библиотечный файл все его процедуры и функции будут доступными, а компилятор выберет из них только те, которые применяются в текущем проекте.
Есть ещё один способ обеспечить доступ к нужным процедурам. Их можно просто включить в исходный DSL-файл, но не так, как это было сделано ранее (см. рис.5, б), а с помощью директивы INCLUDE.
В данном случае после ключевого слова INCLUDE надо назвать имя файла, где записаны нужные процедуры в исходном коде. В отличие от директивы USE, теперь надо указать расширение файла, например:
INCLUDE ‘LIB_DSL_PROC. dsl’;
Включаемые файлы могут, в свою очередь, содержать другие включаемые файлы. Текст включаемого файла вставляется целиком в то место, где стоит директива INCLUDE. Понятно, что все способы допускается использовать совместно, надо лишь следить за тем, чтобы описания одной и той же процедуры не повторялись в одном проекте несколько раз.
ЛОГИЧЕСКИЕ ОПЕРАТОРЫ
В рассмотренных примерах мы познакомились с тремя логическими операторами: И (IN1 * IN2), ИЛИ (IN1 + IN2) и НЕ (/ IN1). Всего в языке DSL их насчитывается десять. Они перечислены в табл.1. Там же указан приоритет и пример использования каждой логической операции. Операторы NOT, AND и OR дублируют соответствующие операторы /, *, +, но имеют меньший приоритет.
В правом столбце таблицы приведены имена элементов, реализующих названные функции. Для элементов INVR, AND2 и OR2 уже имеются соответствующие DSL-модели (см. рис. 1, 2, 3). Надеюсь, вам не составит труда написать аналогичные модели для отсутствующих элементов NAND2, NOR2, XOR, NXOR и включить их в библиотечные файлы LIB_DSL_FUNC. dsl и LIB_DSL_PROC. dsl.
Таблица 1
Оператор | Выполняемая функция | Приоритет | Пример | Элемент |
/ | Отрицание | 1 | /а | INVR |
* | Логическое И | 2 | a * b | AND2 |
/* | Логическое НЕ-И | 2 | a /* b | NAND2 |
+ | Логическое ИЛИ | 3 | a + b | OR2 |
/+ | Логическое НЕ-ИЛИ | 3 | a /+ b | NOR2 |
(+) | Исключающее ИЛИ | 3 | a (+) b | XOR |
/(+) | Отрицание Исключающего ИЛИ | 3 | a /(+) b | NXOR |
NOT | Логическое отрицание | 5 | NOT a | |
AND | Логическое И | 6 | a AND b | |
OR | Логическое ИЛИ | 7 | a OR b |
В языке DSL имеется возможность коротко записывать длинные выражения, содержащие многократно повторяющиеся логические операции. Например, выражение для элемента AND8:
OUT1 = IN8 * IN7 * IN6 * IN5 * IN4 * IN3 * IN2 * IN1;
можно записать гораздо короче:
OUT1 = * (IN8 .. IN1);
Такие короткие операторы называют ES-операторами (от английского названия Expression Shorthand (ES) Operators). Их полный перечень приведён в табл.2.
Таблица 2
ES-операторы | Приоритет | Пример | Эквивалентное написание |
* | 1 | *(A, B,E(+)F) | A*B*(E(+)F) |
+ | 1 | +(A, B,D*E) | A+B+(D*E) |
(+) | 1 | (+)(A, B,C) | A(+)B(+)C |
/* | 1 | /*(B, C,D) | /(B*C*D) |
/+ | 1 | /+(B, C,D) | /(B+C+D) |
/(+) | 1 | /(+)(B, C,D) | /(B(+)C(+)D) |
КОММЕНТАРИЙ
В процессе разработки DSL-программ нередко требуется добавить в исходный текст соответствующий комментарий. Он начинается с двойных кавычек и распространяется до конца строки. Например:
OUT1 = IN1 * IN2; “комментарий.
На рис.5 встречается несколько строк с таким комментарием. Если надо «закрыть комментарием» много строк, то приходится повторять кавычки неоднократно в начале каждой новой строки.
Данный способ становится неэффективным, когда надо временно исключить из текста большой фрагмент программы (а удалять жалко). В этом случае предпочтительнее заключить ненужный текст в так называемые COMP-скобки. Открывающая «скобка» COMP_OFF указывает компилятору игнорировать всё, что следует далее до тех пор, пока не встретится закрывающая «скобка» COMP_ON. На рис.6 показан пример использования COMP-скобок.

Рис.6. Использование ключевых слов COMP_OFF и COMP_ON для «выключения»
из программы фрагмента DSL-кода
Замечу, что число открывающих и закрывающих скобок совсем не обязано быть одинаковым. Ну а вложенные скобки просто не работают.
ПРАВИЛА НАПИСАНИЯ ИДЕНТИФИКАТОРОВ
В построенных ранее DSL-моделях мы неоднократно использовали различные идентификаторы, то есть имена сигналов, узлов, процедур и функций. Пришло время прояснить правила, которым они должны удовлетворять. Их не много:
§ Первый символ имени должен быть буквой (большой или маленькой) или подчеркиванием;
§ Последующие символы могут быть буквами, цифрами, знаком «доллар» или подчёркиванием. Имена не должны включать в себя пробелы. Рекомендуется использовать символ «подчёркивание» для разделения слов в длинных именах;
§ В языке DSL заглавные и прописные буквы не различаются и считаются одинаковыми. Тем не менее, зарезервированные слова принято писать большими буквами, а идентификаторы – маленькими;
§ На длину имени ограничений не накладывается;
§ В качестве имён нельзя использовать зарезервированные слова языка DSL, например CASE, INPUT, PROCEDURE, NODE и т. п. Список ключевых слов языка DSL довольно внушительный, он содержит около сотни слов (вместе с зарезервированными словами языка PIL). Полный список ключевых слов можно просмотреть в Help’e к программе PLSyn.
§ Не следует также называть процедуры именами логических символов, содержащихся в библиотечном файле dig_prim. slb, например BUF, INV, OR2, AND2, JKFF и т. п.
ФУНКЦИОНАЛЬНЫЕ DSL-МОДЕЛИ КОМБИНАЦИОННЫХ УСТРОЙСТВ
Рассмотренные выше модели мультиплексора MUX2_DSL (рис. 4, б и 5, б) строились на основе его структурного описания, приведённого на рис.4, а. Фактически функция мультиплексора реализовывалась косвенным образом, через функции входящих в него элементов. Мы знаем, что такие модели называются потоковыми (рис.4, б) или структурными (рис.5, б).
Если структура цифрового устройства нам не известна, то рассмотренные выше приёмы становятся недоступными. В такой ситуации придётся строить поведенческую модель на уровне чёрного ящика. Мы уже знаем, что в языке DSL есть для этих целей подходящие изобразительные средства.
Первое, что приходит в голову – описать работу мультиплексора булевским уравнением (рис.7, а). Так строятся аналитические модели.

Рис.7. Функциональные модели мультиплексора MUX2_DSL
Записав работу мультиплексора в форме алгоритма и используя, например, конструкцию «IF…THEN», можно получить алгоритмическую DSL-модель (рис.7, б).
На рис.7, в показана ещё одна реализация модели мультиплексора с помощью оператора CASE. В данном варианте проверяется значение сигнала A и в зависимости от того, чему оно равно, выполняется соответствующее присваивание: Y = D0 (когда A = 0) или Y = D1 (когда A = 1).
DSL - ШАБЛОНЫ
Здесь самое время отметить, что в САПР DesignLab 8 имеется встроенный текстовый редактор Text Editor, с помощью которого удобно создавать модели цифровых устройств на языке DSL. Удобство состоит в том, что он (редактор) имеет команду Insert/DSL Template…, которая позволяет вставлять в модель шаблоны DSL-кода. Это некоторые «заготовки», в которых надо лишь заменить формальные имена идентификаторов или выражений (expr) реальными и в предлагаемых местах (" statements go here) вставить желаемые операторы.
На рис.8, а приведён пример такого шаблона для конструкции CASE, а справа вы видите тот же самый текст после редактирования. Именно так был получен DSL-код на рис.7, в. Из него лишь удалены закомментированные строки.
Модель мультиплексора с конструкцией IF-THEN-ELSE (рис.7, б) получена аналогичным образом (рис.8, б). Обратите внимание на установку ELSIF expr THEN
" statements go here (в примере она закрыта комментарием). Её можно включать в оператор IF неограниченное число раз, в том числе и не разу.

Рис.8. Использование DSL-шаблонов (Template) в процессе проектирования
моделей цифровых устройств
Замечу, что DSL-шаблоны полезны не только на начальных этапах изучения языка, но и в дальнейшей работе: они ускоряют процесс создания модели и уменьшают количество ошибок в ней.
ОПЕРАТОР TRUTH_TABLE
В языке DSL есть ещё одна весьма любопытная и полезная конструкция – это оператор TRUTH_TABLE. Он позволяет записать программную модель в виде таблицы истинности. Отсюда и происходит название TRUTH_TABLE. Для разработчиков аппаратуры, далёких от программирования, такая форма описания модели выглядит особенно привлекательно. На рис.7, г показано, как с её помощью была построена модель мультиплексора MUX2_DSL.
Так как оператор TRUTH_TABLE довольно часто используется в практической работе, приведём ещё несколько вариантов его применения. На рис.9, а построена модель мультиплексора по полной таблице истинности. Слева от знака «::» перечислены все комбинации входных сигналов, а справа от него указаны значения, которые принимает выходной сигнал Y на этих наборах.
На рис.9, б таблицу удалось сократить благодаря «склеиванию» наборов, на которых выход не зависит от сигнала D1 (первые две строки) или от сигнала D0 (третья и четвёртая строки). На соответствующих позициях поставлено значение. X. (don't care), что переводится на русский язык как безразличное состояние. Другими словами, на позиции, где указано. X., может стоять любое допустимое значение (0 или 1), а реакция на выходе останется неизменной.

Рис.9. Варианты построения DSL-моделей с использованием оператора TRUTH_TABLE
Не следует путать безразличное состояние .X. в языке DSL с неизвестным значением X (Unknown - неизвестный) на временных диаграммах входных или выходных сигналов пакета DesignLab 8.
В первом случае значение определено, но от него ничего не зависит, во втором случае оно не определено (неизвестно). Возможно, вы забыли его задать или моделятор по каким-то причинам не сумел его вычислить.
Кстати, чтобы не возникало путаницы, в некоторых языках эти значения кодируются разными символами. Например, в языке VHDL это сделано так:
‘X’ – неизвестное значение;
‘-‘ безразличное значение.
Безразличное значение полезно при логическом синтезе схем, в процессе минимизации уравнений для не полностью определённых булевских функций.
Попробуйте в DSL-модели присвоить выходному сигналу значение. X., , записав, например, в теле процедуры оператор присваивания:
OUT1 = .X.;
Что вы предполагаете увидеть на выходе по окончании моделирования? Чаще всего студенты отвечают примерно так: что написал, то и собираюсь увидеть, то есть. X. Но ведь фраза OUT1 = .X.; говорит о том, что вам безразлично, каким будет значение выхода: 0 или 1. Фактически вы отдаёте решение на откуп компилятору, а он по умолчанию поставит 0.
Рассмотрим более реальную ситуацию. На рис.10, а показана карта Карно для элемента AND2. Поэкспериментируем немного с его DSL-моделью. Зададим безразличное значение. X. выходному сигналу OUT1 на входном наборе 01 (рис.10, б).
Компилятор «сообразит», что если вместо. X. подставить 1, то появляется возможность упростить логическое уравнение, склеив единицы по столбцу IN1. Промоделируйте работу элемента в этом режиме и вы увидите, что он действительно так и поступил: выход повторяет вход IN1.
Похожий результат получается, если значение. X. задать на входном наборе 10 (рис.10, в). Только теперь выход повторяет вход IN2.
В последнем эксперименте (рис.10, г) подстановка 1 вместо. X. не приводит к их «склеиванию», поэтому компилятор выставляет значение по умолчанию, то есть 0.

Рис.10. Безразличное значение на выходе OUT1 компилятор заменяет на 1 (или 0),
когда появляется возможность минимизировать логическое уравнение
Чтобы убедиться, что выход всё-таки может принимать значение X (Unknown), надо передать его через какой-нибудь входной сигнал. Например, записать
OUT1 = IN1;
и входному сигналу IN1 задать на временной диаграмме значение X. Впрочем, точно также выход отреагирует и на значение Z на входе IN1.
А вот выражение OUT1 = .Z.; сработает так, как вы от него и ждёте. На рис.9, в приведена модель инвертора, имеющего выход с тремя состояниями. При OE=0 данные передаются на выход (Y=/D), при OE=1 выход переключается в состояние высокого импеданса (Y=.Z.).
Сократить таблицу истинности можно ещё одним способом. Достаточно указать в ней только те наборы, на которых выходной сигнал равен 1 (или 0, если таких строк меньше). Затем с помощью ключевого слова ELSE надо объявить, какое значение должен иметь выход на всех других явно не названных комбинациях входных сигналов (рис.9, г).
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 |


