В предыдущем посте мы дошли до схемы очень простого цифрового устройства. gnetlist показал нам кукиш и сейчас мы заставим его слушаться. Получив список соединений, будем подготавливать модели, управляемые событиями. Такими событиями могут быть тактовые сигналы часов, изменения логических состояний цифровых моделей, события от мостов типа аналог-цифра при смешанной симуляции, а также данные из файлов. Возможности симуляции ограничены только доступной вам памятью, которой в современных ПК и ноутбуках более, чем достаточно, для подобных целей.
Сначала разберемся с проблемой gnetlist. Почему он не хочет генерить нетлист? Ведь мы используем вполне законные префиксы для компонентов. Ответ можно усмотреть в диагностике, которую он выводит. Мы сделали наши символы доступными редактору gschem, но с gnetlist все обстоит по другому, он не может найти файлов. Вот что нам нужно, в принципе, сделать для решения проблем:
1. Поместить каталог с символами в каталог с системными библиотеками символов.
2. Подправить один из конфигурационных файлов.
3. Удалить ставший ненужным файл gschemrc из нашего рабочего каталога.
Вместо копирования каталога с символами в системный каталог, можно создать в последнем символьную ссылку на сам каталог. Это работает и это очень удобно. Мы можем править наши символы в любой момент, без прав админа. Но сначала эти права нам понадобятся (мы начинаем выполнять второй пункт). Запустим терминал и введем команду:
$ sudo scite /usr/share/gEDA/gafrc.d/geda-clib.scm
[sudo] password for ...:
Если у вас другой любимый редактор, gedit, например, или vim, указываете его. В файле, который открывается в редакторе, необходимо добавить строки, отмеченные номерами 18 и 19 на следующем снимке экрана:
Мы просто добавили данные для индексации моделей элементов, которая используется всеми утилитами пакета geda по стандартному соглашению разработчиков. Теперь gnetlist гарантированно увидит наш каталог, если он найдется по указанному пути. Сохраним данные и закроем редатор.
Теперь выполним вторую часть плана. Выполним еще одну команду:
$ sudo ln -s /usr/share/gEDA/sym /home/user/ваш-путь/symlib
В системном каталоге sym появится ссылка на каталог в домашнем каталоге пользователя user (это вы, разумеется, с поправкой на ваше имя в системе). Последняя команда также выполняется с административными привелегиями. После этого можно выйти из терминала.
И теперь можно удалить файл gschemrc из нашего рабочего каталога. Если нам когда-нибудь понадобится дополнительная конфигурация для gschem в каком-нибудь конкретном проекте, то мы будем знать, как это делается: просто создается файл gschemrc в рабочем каталоге. Пока он нам не нужен.
Таким способом можно добавить столько каталогов с компонентами, сколько вам нужно.
Теперь можно продолжать. Сейчас нам понадобится библиотека цифровых моделей. Опция XSPICE, скорее всего, была уже включена в компиляцию пакетов deb или rpm в репозиториях. Поэтому нам не придется компилировать ngspice из исходников. Поэтому мы можем использовать все кодовые модели: аналоговые, цифровые и мосты.
Даже для самой простой цифровой симуляции нам понадобятся "костыли" для привязки логических уровней к представляющим их напряжениям этих самых уровней. Иначе мы не сможем получить данные из цифровой симуляции. ngspice не может работать с абстрактными логическими величинами. Таким образом, цифровые модели - это лишь своеобразный способ "сжатия данных".
Поэтому мы немного расширим схемку из предыдущего поста, вот таким образом:
Элементы A5...7 это "ЦАП" для симулятора, эти самые костыли. Как разобраться с их графикой, вам уже известно. А инициализированы они так:
A/D: pinseq=1 pinnumber=1 pinlabel=A pintype=in; pinseq=2 pinnumber=2 pinlabel=D pintype=out; device=ADC; refdes=A?
D/A: pinseq=1 pinnumber=1 pinlabel=D pintype=in; pinseq=2 pinnumber=2 pinlabel=A pintype=out; device=DAC; refdes=A?
Разобравшись с назначением этих элементов, добавим новую библиотеку (digsim.lib):
*
* ==== библиотека цифровых моделей ====
*
* интерфейс аналог/цифр.
.model dac dac_bridge(
+ out_low = 0.7
+ out_high = 3.5
+ out_undef = 2.2
+ input_load = 5p
+ t_rise = 50n
+ t_fall = 20n )
* интерфейс цифр./аналог
.model adc adc_bridge(
+ in_low = 0.7
+ in_high = 3.5
+ t_rise = 50n
+ t_fall = 20n )
* резисторы подтяжки к земле и питанию
* они же низкий и высокий логич. уровни
.model pullup d_pullup(load = 20p)
.model pulldown d_pulldown(load = 20p)
* инвертор
.model not d_inverter(
+ rise_delay = 1n
+ fall_delay = 1n
+ input_load = 1p )
* элемент nИ-НЕ
.model nand d_nand(
+ rise_delay = 1n
+ fall_delay = 1n
+ input_load = 1p )
* элемент nИЛИ-НЕ
.model nor d_nor(
+ rise_delay = 1n
+ fall_delay = 1n
+ input_load = 1p )
* набор двоичных векторов (цифровых данных)
.model vector d_source(input_file = "data.txt")
Смысл параметров моделей очень простой. На примере самой первой: out_low - напряжение низкого уровня, которое было бы на реальном устройстве логики (ТТЛ 5В), out_high, как нетрудно догадаться, высокий уровень. out_undef - напряжение неопределенного уровня, когда имеется "звон", неприятная штука, связанная с неправильным проектированием логических схем. Остальные параметры. input_load - это емкостная нагрузка на цифровой пин элемента. t_rise и t_fall это понятно, время нарастания и спада уровня.
Параметры остальных моделей имеют аналогичный смысл. Собственно говоря, уже из названия видно, что это за параметры, а кто хотя бы не может свободно читать по-английски в наши времена, тот, ящетаю нихера ниграматный. Откуда же еще черпать информацию?
Разумеется, в нашей библиотеке не все модели XSPICE, но начало положено.
Файл для двоичного вектора с именем data.txt:
*время 0 1
0.0 0z 0z
0.1 0s 0s
0.2 1s 0s
0.3 0s 1s
0.4 1s 1s
0.5 0s 0s
Теперь можно запускать gnetlist и получать файл digsim.net Он показан ниже, но в отредактированном виде. Изменения не слишком велики, но очень важные:
. . . шапка
*vvvvvvvv Included SPICE model from digsim.lib vvvvvvvv
*
* ==== библиотека цифровых моделей ====
*
. . . содержание библиотеки (см. выше)
*^^^^^^^^ End of included SPICE model from digsim.lib ^^^^^^^^
*
*============== Begin SPICE netlist of main design ============
A7 [3] [c] dac
A6 [2] [a] dac
A5 [1] [b] dac
.INCLUDE digsim.lib
.tran 0.1s 0.5s
A2 [2 1] 3 nand
A1 [1 2] vector
.control
run
plot v(a) v(b)+5 v(c)+10
.endc
.end
Очень важные элементы в конце файла - квадратные скобки, пары квадратных скобок. Они ограничивают векоры, которые конечно, могут быть и единичными. Пин 3 элемента nand, с другой стороны, НЕ является вектором, это скаляр, как значение логической функции. В файле руководства по ngspice, который легко и погуглить, и пояндексить, все пины всех встроенных моделей описаны.
В секции .control симулятор запускается, и рисует три интересующих нас графика, а чтобы они не накладывались друг на друга и не было непонятной хуетени, мы слегка сдвигаем их вверх по оси ординат. Запускаем симулятор командой ngspice digsim.net и должна появиться диаграмма:
Мы разделили полсекунды на 5 частей при помощи data.txt. В каждой из этих частей "система" находится в своем состоянии. В первой части элемент A1 просто отключен - 0z - от логического элемента. Во второй части на входах элемента устанавливаются низкие урони. Дальше следим и записываем все в таблицу истинности элемента 2И-НЕ:
a b c
-----
x x 1
0 0 1
0 1 1
1 0 1
1 1 0
0 0 1
Как можно видеть, для конъюнкции с инверсией ошибок нет. Так же можно испытывать и все остальные логические функции. Основы цифровой симуляции при помощи ngspice заложены.
Теперь эту же схему постараемся развить в цифровую начинку таймера 555. Там стоит RS-триггер, имеющий входы R и S, один инверсный вход R, и два выхода, прямой и инверсный. Для тестирования нам понадобится вектор из трех бит. Мы можем просто сделать еще один элемент, подобный предыдущему, с четырьмя битами (бог любит троицу, но вычислительная техника любит двоицу и ее степени) и переписать файл data.txt Заодно поинтересуемся, что бывает с неподключенными пинами.
Возьмем даташит на таймер NE555 (у меня SE555, а он эквивалентный). Там есть его функциональная схема:
Ну что, быстро создать трехвходовый элемент 3И-НЕ, используя 2И-НЕ как шаблон, это же как два пальца...
Создадим новую схему:
Рамка из штрихованых линий просто ограничивает новую схему для наглядности. Один из пинов четырехбитового "источника" не присоединен ни к чему, что, вообще говоря, считается ошибкой. Но об этом немного ниже.
Новый файл data.txt с тестовыми векторами:
*время nR R S
* nR отключен
0.0 0z 0s 0s
0.1 0z 1s 0s
0.2 0z 0s 1s
0.3 0z 1s 1s
* nR низкий уровень
0.4 0s 0s 0s
0.5 0s 1s 0s
0.6 0s 0s 1s
0.7 0s 1s 1s
* nR высокий уровень
0.8 1s 0s 0s
0.9 1s 1s 0s
1.0 1s 0s 1s
1.1 1s 1s 1s
1.2 1s 0s 0s
Теперь создаем список соединений для новой схемы:
. . . шапка, содержимое библиотеки
*^^^^^^^^ End of included SPICE model from digsim.lib ^^^^^^^^
*
*============== Begin SPICE netlist of main design ============
A2 1 4 6 2 nand
A4 5 4 3 unconnected_pin-1 vector
A3 5 6 not
A9 2 Q dac
A8 1 nQ dac
A7 5 nR dac
A6 3 S dac
A5 4 R dac
.INCLUDE digsim.lib
.tran 0.1 1.2
A1 3 2 1 nand
.end
Этот список соединений сложнее предыдущего, и нуждается в важных пояснениях. То, что gnetlist пометил как неподключенный пин, следует обозначить как NULL, чтобы не возникало ошибки в симуляторе. В остальном достаточно правильно расставить квадратные скобки, чтобы обозначить векторы, и не захомутать в них скаляры. Скалярами являются значения логических функций и вход элемента НЕ. Остальное - векторы.
Неплохо было бы написать скрипт, которому gnetlist передает данные по конвейеру и который пишет готовый файл. Сам gnetlist под цифровую симуляцию не заточен, к сожалению. Но, прежде чем мы сможем написать такой скрипт, необходимо будет как следует формализовать правила, по которым он будет парсить входные строки. Это может оказаться не очень простым делом, либо будет связано неудобными ограничениями.
Пока перебьемся ручной правкой. Для наших текущих целей этого будет вполне достаточно:
*============== Begin SPICE netlist of main design ============
A2 [1 4 6] 2 nand
A4 [5 4 3] null vector
A3 5 6 not
A9 [2] [Q] dac
A8 [1] [nQ] dac
A7 [5] [nR] dac
A6 [3] [S] dac
A5 [4] [R] dac
.INCLUDE digsim.lib
.tran 0.1 1.2
A1 [3 2] 1 nand
.control
run
let nR=V(nR)
let R=V(R)+5
let S=V(s)+10
let Q=V(Q)+15
let nQ=V(nQ)+20
plot nR R S Q nQ
.endc
.end
Мы расставляем квадратные скобки в соответствии с имеющимися векторами и "отключаем" неиспользуемый пин. Секция .control поможет быстро нарисовать понятные графики.
Все готово к запуску. Запускаем:
Эта диаграмма не очень похожа на таблицу истинности. Чтобы привыкнуть к такому представлению, можно представить себе воображаемые нули и единицы на каждом такте. Повернем картинку, чтобы она выглядела в большей степени похожей на таблицу.
вход выход
------- -----
S R nR Q nQ
0 0 x 1 1
0 1 x 0 1
1 0 x 1 0
1 1 x 1 0
0 0 0 1 1
0 1 0 0 1
1 0 0 1 0
1 1 0 1 0
0 0 1 1 1
0 1 1 1 1
1 0 1 1 0
1 1 1 1 0
--------------
Так должна, по идее, вести себя логика в таймере 555. Правильно это или нет выяснится, если мы соберем таймер полностью и снова испытаем его, перебрав все сигналы на его входах. Окончательный ответ можно получить, взяв несколько микросхем и испытав их на простом стенде, который можно собрать на коленке: несколько резисторов, источник питания 5 В (заряжалка от мобильника или батарейка на 5-9 В), пара светодиодов.
Пост опять получился большим, поэтому окончательную сборку модели таймера мы оставим на следующий раз.
Дальше