Эмулятор логических схем – Нужен хороший и понятный онлайн/оффлайн симулятор простых электрических схем (аналоговых и цифровых)?

проект снова жив / Habr

TKGate ( tkgate.org ) — это симулятор цифровых схем на базе Verilog с открытым исходным кодом. Он работает в ОС Linux. Симулятор написан на связке C и Tk/Tcl. Автором проекта является Jeffery P. Hansen (неактивен). Сейчас разработкой занимается наш соотечественник Андрей Скворцов. На прошлой неделе после шестилетнего (!) перерыва в разработке вышла новая версия симулятора TKGate-2.0. Вот так выглядит TKGate:

Под катом более подробный разбор TKGate.

История и основные возможности


Я использовал TKGate приблизительно в 2005-2006 году, и у меня о нём остались самые положительные воспоминания. Потом около 2009 года разработка проекта прекратилась, и у меня не было проектов с цифровой электроникой, которую нужно было моделировать. С этого времени я данный симулятор не видел и думал, что проект умер. Теперь, к счастью, нашёлся разработчик, который поднял этот проект из мёртвых. Теперь рассмотрим подробнее этот симулятор. Ключевые возможности симулятора следующие:
  • Интерактивное моделирование цифровых схем
  • Доступные типы компонентов: логические элементы, триггеры, регистры, счётчики, дешифраторы, мультиплексоры, ОЗУ, ПЗУ, АЛУ, ключи на МОП-транзисторе, имитаторы входных сигналов, светодиоды, семисегментыне индикаторы, шкалы, генераторы синхросигналов.
  • Использование пользовательских скриптов Verilog.

Схемный файл представляет собой обычный скрипт Verilog, в комментариях которого содержатся данные о расположении компонентов и проводов. Этот код Verilog, например, можно потом передавать в САПР для синтеза ПЛИС.

Графический интерфейс TKGate написан на Tk/Tcl и поэтому для тех, кто привык к современным KDE и Gnome выглядит несколько старомодно. Тем не менее это нисколько не вредит функционалу программы.

Установка


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

Предыдущая версия TKGate-1.8 есть в репозитории Debian, и чтобы его установить достаточно выполнить команду:

apt-get install tkgate

Готовых пакетов для последней версии пока нет, поэтому её нужно собирать самим. Требуются следующие зависимости:

Можно либо скачать архив с исходниками с официального сайта или склонировать репозиторий проекта на Bitbucket:

hg clone https://bitbucket.org/starling13/tkgate

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

./configure
make
make install

Если склонировали репозиторий, то последовательность сборки сложнее:

./configure
aclocal
automake
make 
make install

Можно make install заменить на checkinstall, который соберёт пакет для вашего дистрибутива.

Настройка


После установки, нужно настроить библиотеки, загружаемые при запуске программы. Можно загружать все библиотеки или некоторые из них. Для этого нажимаем в главном меню Инструменты->Настройки и затем в появившемся диалоге Библиотеки->Автозагрузка. Выбираем библиотеки, загружаемые при старте. В частности программа содержит библиотеку ИМС 74-й серии (ТТЛ и ТТЛШ). На этом настройка завершена.

Динамически загружать библиотеки можно щёлкнув правой кнопкой на пункте Библиотеки в дереве проекта в левой части окна программы и выбрав в контекстном меню пункт Менеджер библиотек.

Работа с программой


Рассмотрим небольшой пример. Промоделируем элемент 2И-НЕ. Для этого создаём новый файл: Файл->Создать.

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

Теперь нужно добавить компоненты. Компоненты добавляются через контекстное меню,
вызываемое по правому щелчку мыши на поле схемы. Выбираем Компоненты->Вентиль->И-НЕ. Ко входам вентиля нужно подключить переключатели, которые будут подавать на них лог.0 или лог.1, а к выходу светодиод, чтобы контролировать состояние вентиля 2И-НЕ. Переключатели выбираем снова через контекстное меню Компоненты->Ввод/вывод->Переключатель. Светодиод находится там же: Компоненты->Ввод/вывод->Светодиод. Теперь соединяем всё проводами. Должна получиться вот такая схема:

Теперь схему можно моделировать. Для этого переходим на вкладку Симуляция. Становится активным меню Симуляция. Теперь запускаем моделирование: Симуляция->Пуск. Моделирование является полностью интерактивным, в отличие от например моделирования цифровых схем в Qucs. Подход к моделированию в TKGate напоминает Multisim или Proteus. Во время моделирования можно вручную изменять состояние переключателей и т.п. и смотреть отклик схемы. В нашей схеме если пощёлкать по переключателям, то увидим, что состояние выхода логического элемента изменяется в зависимости от состояния входов согласно таблице истинности элемента 2И-НЕ. Чтобы остановить симуляцию, нужно вызвать команду Симуляция->Закончить симуляцию. Результат моделирования представлен на рисунке:

Более сложные схемы могут включать в себя ИМС средней степени интеграции, модули Verilog, ОЗУ и ПЗУ.

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

Пишем эмулятор простых логических схем

Сегодня мы реализуем программу для симуляции логических схем.

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

  • триггер
  • ячейка памяти
  • и многие другие (все те, что имеют обратную связь)

но для написания простого сумматора — самое то!

Для простоты реализации писать будем на Python. Забегу вперёд и скажу, что наша базовая реализация займёт не больше 100 строчек кода. Можно и меньше, но мы за этим не будем гнаться.

Давайте определим что нам будет нужно чтобы эмулировать работу самого простого элемента?

  1. Он должен иметь входы/выходы
  2. Иметь возможность получать сигнал на вход и отдавать на выходе
  3. Выполнять некое преобразование между входным и выходным сигналом

Для определенность возьмём элемент NAND. В привычных для многих функциях он будет выглядеть так:

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

Напишем каркас для нашего элемента.

class ElementNAND:
    def __init__(self):
        # у NAND два входа
        self.input = [0, 0]
        # и один выход
        self.output = [0]

    def execute(self):
        # X NAND Y = NOT (X AND Y) = (NOT X) or (NOT Y)
        # см. законы де Моргана
        self.output[0] = (not self.input[0]) % 2 or (not self.input[1]) % 2
        # и выбирай любое из условий :)
        # self.output[0] = (not (self.input[0] and self.input[1])) % 2
        """
        для удобства отображения input и output содержат числа, а не булевый тип
        и поэтому нужно брать остаток от деления!
        """

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

from itertools import product

""" ... место для класса ElementNAND ... """

a = ElementNAND()
for signal in product(range(2), repeat=2):
    a.input = list(signal)
    a.execute()
    print('{} NAND {} = {}'.format(*a.input, a.output[0]))

Запустим и посмотрим на результат

0 NAND 0 = 1
0 NAND 1 = 1
1 NAND 0 = 1
1 NAND 1 = 0

Отлично, результат соответствует таблице истинности!

Теперь обобщим наши действия, т.е. введём ещё пару правил:

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

Что же это значит для нас?

Только то, что нужно будет:

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

Начнём по порядку

class Element:
    """
        input_w  -- количество входных проводов
        output_w -- количество выходных проводов
        type     -- тип элемента ('составной' или 'NAND')
    """
    def __init__(self, input_w, output_w, type='составной'):
        # инициализируем нулями массивы входов и выходов
        self.input = [0] * input_w
        self.output = [0] * output_w
        # указываем тип элемента
        self.type = type
        # создаём список для внутренних элементов
        self.elements = []
        # создаём список соединяющих проводов
        self.wires = []

Наверное нужно остановится на списках elements и wires.

elements будет содержать объекты Element к которым можно будет обращаться по индексу, а wires будет содержать все связи входных и выходных проводов между элементами.

Пойдём дальше и добавим функции для работы с элементами и проводами

def push_element(self, element):
    # проталкиваем элемент в список
    self.elements.append(element)
    # и возвращаем его номер в списке
    return len(self.elements) - 1

def connect_wire(self, wire_a, wire_b):
    # добавляем провод в список
    self.wires.append((wire_a, wire_b))

Вроде всё просто! Да?

А теперь самое главное, функция execute.

def execute(self):
    # если элемент NAND, то считаем по формуле
    if self.type == 'NAND':
        """ наш прошлый код """
        # X NAND Y = NOT (X AND Y) = (NOT X) or (NOT Y)
        # см. законы де Моргана
        self.output[0] = (not self.input[0]) % 2 or (not self.input[1]) % 2
        # и выбирай любое из условий :)
        # self.output[0] = (not (self.input[0] and self.input[1])) % 2
    # иначе, если элемент составной:
    elif self.type == 'составной':
        """ ... некоторый код ... """

Остановимся на данном моменте и подумаем…

В голову сразу приходит несколько вопросов:

  1. Как исполнять код для вложенных элементов?
  2. Как идентифицировать входные и выходные провода?
  3. Как вообще различить внутренние и внешние провода?

На 2 и 3 вопрос можно ответить сразу:

  • ввести in_self и out_self – для входов и выходов данного элемента
  • и in и out – для внутренних элементов

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

element.connect_wire(('in_self', 0), ('in', e_id, 0))

где element – имя самого элемента, ('in_self', 0) – нулевой вход у этого элемента, а ('in', e_id, 0) – вход у внутреннего элемента e_id на нулевом проводе

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

Я думаю вы уже поняли каким путём мы пойдём 🙂

elif self.type == 'составной':
    """
    идём по всем проводам, где
        from_e -- начало провода
          to_e -- конец провода
    """
    for from_e, to_e in self.wires:
        # если from_e -- вход у элемента
        if from_e[0] == 'in_self':
            wire = from_e[1]
            # запоминаем установленных вход во временную переменную
            result = self.input[wire]
        # если from_e -- выход у внутреннего элемента
        elif from_e[0] == 'out':
            # вытаскиваем номер элемента и провод из from_e
            idN, wire = from_e[1:]
            # и запоминаем установленных выход во временную переменную
            result = self.elements[idN].output[wire]
        # если to_e -- вход внутреннего элемента
        if to_e[0] == 'in':
            # вытаскиваем номер элемента и провод
            idN, wire = to_e[1:]
            # устанавливаем значение сигнала на проводе используя ту самую переменную
            self.elements[idN].input[wire] = result
            # и выполняем код внутри элемента
            self.elements[idN].execute()
        # если to_e -- выход у самого элемента
        elif to_e[0] == 'out_self':
            wire = to_e[1]
            # то просто записываем результат на его выход
            self.output[wire] = result

Вот и всё! Конечно код не супер идеальный и скорее всего с ошибкой в логике исполнения, но он работает 🙂

И для миниатюрного симулятора логики этого будет достаточно!

Полный листинг кода

class Element:
    """
        input_w  -- количество входных проводов
        output_w -- количество выходных проводов
        type     -- тип элемента ('составной' или 'NAND')
    """
    def __init__(self, input_w, output_w, type='составной'):
        # инициализируем нулями массивы входов и выходов
        self.input = [0] * input_w
        self.output = [0] * output_w
        # указываем тип элемента
        self.type = type
        # создаём список для внутренних элементов
        self.elements = []
        # создаём список соединяющих проводов
        self.wires = []

    def push_element(self, element):
        # проталкиваем элемент в список
        self.elements.append(element)
        # и возвращаем его номер в списке
        return len(self.elements) - 1

    def connect_wire(self, wire_a, wire_b):
        # добавляем провод в список
        self.wires.append((wire_a, wire_b))

    def execute(self):
        # если элемент NAND, то считаем по формуле
        if self.type == 'NAND':
            # X NAND Y = NOT (X AND Y) = (NOT X) or (NOT Y)
            # см. законы де Моргана
            self.output[0] = (not self.input[0]) % 2 or (not self.input[1]) % 2
            # и выбирай любое из условий :)
            # self.output[0] = (not (self.input[0] and self.input[1])) % 2
        # иначе, если элемент составной:
        elif self.type == 'составной':
            """
            идём по всем проводам, где
                from_e -- начало провода
                  to_e -- конец провода
            """
            for from_e, to_e in self.wires:
                # если from_e -- вход у элемента
                if from_e[0] == 'in_self':
                    wire = from_e[1]
                    # запоминаем установленных вход во временную переменную
                    result = self.input[wire]
                # если from_e -- выход у внутреннего элемента
                elif from_e[0] == 'out':
                    # вытаскиваем номер элемента и провод из from_e
                    idN, wire = from_e[1:]
                    # и запоминаем установленных выход во временную переменную
                    result = self.elements[idN].output[wire]
                # если to_e -- вход внутреннего элемента
                if to_e[0] == 'in':
                    # вытаскиваем номер элемента и провод
                    idN, wire = to_e[1:]
                    # устанавливаем значение сигнала на проводе используя ту самую переменную
                    self.elements[idN].input[wire] = result
                    # и выполняем код внутри элемента
                    self.elements[idN].execute()
                # если to_e -- выход у самого элемента
                elif to_e[0] == 'out_self':
                    wire = to_e[1]
                    # то просто записываем результат на его выход
                    self.output[wire] = result

Если мы честно хотим реализовать сумматор используя класс Element, то для начала нам нужно создать ещё несколько логических элементов.

Реализовывать мы его будем через два полусумматора, а также нам будут нужны ещё и следующие элементы:

Элемент NOT

Элемент NOT достаточно легко будет реализовать, нужно всего лишь подать один и тот же сигнал на обе ноги NAND.

NOT X = X NAND X = NOT (X AND X) = NOT X

Реализуем в коде

# нам нужен новый объект, а не ссылка
from copy import deepcopy

""" ... код ... """

# создадим элемент NAND (два входа и один выход)
nand_e = Element(2, 1, type='NAND')
# создадим элемент NOT (вход и выход)
not_e = Element(1, 1)
# добавим элемент внутрь и получим его id
nand_id = not_e.push_element(deepcopy(nand_e))

# соединяем нулевой вход элемента NOT и нулевой вход у NAND
not_e.connect_wire(('in_self', 0), ('in', nand_id, 0))
# соединяем нулевой вход элемента NOT и первый вход у NAND
not_e.connect_wire(('in_self', 0), ('in', nand_id, 1))
# соединяем выходы
not_e.connect_wire(('out', nand_id, 0), ('out_self', 0))

# + можно сделать проверку на корректность результатов
not_e.input[0] = 0
not_e.execute()
assert(not_e.output[0] == 1)
not_e.input[0] = 1
not_e.execute()
assert(not_e.output[0] == 0)

Элемент AND

Элемент AND реализуем через только что написанный NOT и опять же NAND.

X AND Y = NOT (X NAND Y) = X AND Y

Пишем код

from itertools import product

""" ... код ... """

# создадим элемент AND (два входа и один выход)
and_e = Element(2, 1)
# добавим NOT и NAND
not_id_1 = and_e.push_element(deepcopy(not_e))
nand_id_1 = and_e.push_element(deepcopy(nand_e))

# теперь соединяем провода
# B = X NAND Y
and_e.connect_wire(('in_self', 0), ('in', nand_id_1, 0))
and_e.connect_wire(('in_self', 1), ('in', nand_id_1, 1))
# A = NOT B
and_e.connect_wire(('out', nand_id_1, 0), ('in', not_id_1, 0))
# result = A
and_e.connect_wire(('out', not_id_1, 0), ('out_self', 0))

# и делаем проверку
for signal in product(range(2), repeat=2):
    and_e.input = list(signal)
    and_e.execute()
    prof = signal[0] and signal[1]
    assert(and_e.output[0] == prof)

Элемент OR

Элемент OR реализуем используя три NAND.

X OR Y = (X NAND X) NAND (Y NAND Y)

Реализуя следующим кодом

# создаём элемент OR (два входа и один выход)
or_e = Element(2, 1)
# добавляем нужные элементы
nand_id_1 = or_e.push_element(deepcopy(nand_e))
nand_id_2 = or_e.push_element(deepcopy(nand_e))
nand_id_3 = or_e.push_element(deepcopy(nand_e))

# и соединяем провода
# A = X NAND X
or_e.connect_wire(('in_self', 0), ('in', nand_id_1, 0))
or_e.connect_wire(('in_self', 0), ('in', nand_id_1, 1))
# B = Y NAND Y
or_e.connect_wire(('in_self', 1), ('in', nand_id_2, 0))
or_e.connect_wire(('in_self', 1), ('in', nand_id_2, 1))
# C = A NAND B
or_e.connect_wire(('out', nand_id_1, 0), ('in', nand_id_3, 0))
or_e.connect_wire(('out', nand_id_2, 0), ('in', nand_id_3, 1))
# result = C
or_e.connect_wire(('out', nand_id_3, 0), ('out_self', 0))

# и делаем проверку
for signal in product(range(2), repeat=2):
    or_e.input = list(signal)
    or_e.execute()
    prof = signal[0] or signal[1]
    assert(or_e.output[0] == prof)

Элемент XOR

Элемент XOR реализуем используя NAND, AND и OR.

X XOR Y = (X NAND Y) AND (X OR Y)

Реализация будет следующая

# создаем элемент XOR (два входа и один выход)
xor_e = Element(2, 1)
# добавляем элементы
nand_id = xor_e.push_element(deepcopy(nand_e))
or_id = xor_e.push_element(deepcopy(or_e))
and_id = xor_e.push_element(deepcopy(and_e))

# и соединяем провода
# A = X NAND Y
xor_e.connect_wire(('in_self', 0), ('in', nand_id, 0))
xor_e.connect_wire(('in_self', 1), ('in', nand_id, 1))
# B = X OR Y
xor_e.connect_wire(('in_self', 0), ('in', or_id, 0))
xor_e.connect_wire(('in_self', 1), ('in', or_id, 1))
# C = A AND B
xor_e.connect_wire(('out', nand_id, 0), ('in', and_id, 0))
xor_e.connect_wire(('out', or_id, 0), ('in', and_id, 1))
# result = C
xor_e.connect_wire(('out', and_id, 0), ('out_self', 0))

# и делаем проверку
for signal in product(range(2), repeat=2):
    xor_e.input = list(signal)
    xor_e.execute()
    prof = signal[0] ^ signal[1]
    assert(xor_e.output[0] == prof)

Полусумматор

Настало время написать полусумматор. Для этого нам понадобятся два элемента: XOR и AND.

Таблица истинности полусумматора выглядит следующим образом

где X и Y – входы, а S и C – сумма и бит переноса, и они определяются следующими выражениями

Напишем его реализацию

# создаём полусумматор (два входа и два выхода)
hadd_e = Element(2, 2)
# добавляем в него XOR и AND
xor_id = hadd_e.push_element(deepcopy(xor_e))
and_id = hadd_e.push_element(deepcopy(and_e))

# и соединяем провода
# S = X XOR Y
hadd_e.connect_wire(('in_self', 0), ('in', xor_id, 0))
hadd_e.connect_wire(('in_self', 1), ('in', xor_id, 1))
# result[0] = S
hadd_e.connect_wire(('out', xor_id, 0), ('out_self', 0))
# C = X AND Y
hadd_e.connect_wire(('in_self', 0), ('in', and_id, 0))
hadd_e.connect_wire(('in_self', 1), ('in', and_id, 1))
# result[1] = C
hadd_e.connect_wire(('out', and_id, 0), ('out_self', 1))

# и делаем проверку
for signal in product(range(2), repeat=2):
    hadd_e.input = list(signal)
    hadd_e.execute()
    prof = [signal[0] ^ signal[1], signal[0] and signal[1]]
    assert(hadd_e.output == prof)

Сумматор

Наконец-то мы подошли к самому сумматору!

Для его реализации нам понадобятся два полусумматора и элемент OR.

Таблица истинности следующая

XYZSC
00000
10010
01010
11001
00110
10101
01101
11111

где X и Y – входы, Z – входной бит переноса, S – выходная сумма, C – выходной бит переноса.

Давайте же наконец напишем его

# создаём сумматор (три входа и два выхода)
add_e = Element(3, 2)
# добавляем элементы
ha_id_1 = add_e.push_element(deepcopy(hadd_e))
ha_id_2 = add_e.push_element(deepcopy(hadd_e))
or_id = add_e.push_element(deepcopy(or_e))

# и соединяем провода
# я думаю вы сможете найти схему полного сумматора на двух полусумматорах
# и разобраться в этом коде!
add_e.connect_wire(('in_self', 0), ('in', ha_id_1, 0))
add_e.connect_wire(('in_self', 1), ('in', ha_id_1, 1))
add_e.connect_wire(('in_self', 2), ('in', ha_id_2, 1))
add_e.connect_wire(('out', ha_id_1, 0), ('in', ha_id_2, 0))
add_e.connect_wire(('out', ha_id_1, 1), ('in', or_id, 0))
add_e.connect_wire(('out', ha_id_2, 1), ('in', or_id, 1))
add_e.connect_wire(('out', ha_id_2, 0), ('out_self', 0))
add_e.connect_wire(('out', or_id, 0), ('out_self', 1))

# делаем финальную проверку по таблице истинности
table = [
#    X  Y  Z  S  C
    [0, 0, 0, 0, 0],
    [1, 0, 0, 1, 0],
    [0, 1, 0, 1, 0],
    [1, 1, 0, 0, 1],
    [0, 0, 1, 1, 0],
    [1, 0, 1, 0, 1],
    [0, 1, 1, 0, 1],
    [1, 1, 1, 1, 1]
]
for x, y, z, s, c in table:
    add_e.input = [x, y, z]
    add_e.execute()
    assert(add_e.output == [s, c])

Полный листинг представлен ниже

from itertools import product
from copy import deepcopy


class Element:
    """
        input_w  -- количество входных проводов
        output_w -- количество выходных проводов
        type     -- тип элемента ('составной' или 'NAND')
    """
    def __init__(self, input_w, output_w, type='составной'):
        # инициализируем нулями массивы входов и выходов
        self.input = [0] * input_w
        self.output = [0] * output_w
        # указываем тип элемента
        self.type = type
        # создаём список для внутренних элементов
        self.elements = []
        # создаём список соединяющих проводов
        self.wires = []

    def push_element(self, element):
        # проталкиваем элемент в список
        self.elements.append(element)
        # и возвращаем его номер в списке
        return len(self.elements) - 1

    def connect_wire(self, wire_a, wire_b):
        # добавляем провод в список
        self.wires.append((wire_a, wire_b))

    def execute(self):
        # если элемент NAND, то считаем по формуле
        if self.type == 'NAND':
            # X NAND Y = NOT (X AND Y) = (NOT X) or (NOT Y)
            # см. законы де Моргана
            self.output[0] = (not self.input[0]) % 2 or (not self.input[1]) % 2
            # и выбирай любое из условий :)
            # self.output[0] = (not (self.input[0] and self.input[1])) % 2
        # иначе, если элемент составной:
        elif self.type == 'составной':
            

Qucs — open-source САПР для моделирования электронных схем / Habr

В настоящее время существует не так уж и много open-source САПР. Тем не менее, среди САПР для электроники (EDA) есть весьма достойные продукты. Этот пост будет посвящён моделировщику электронных схем с открытым исходным кодом Qucs. Qucs написан на С++ с использованием фреймворка Qt4. Qucs является кроссплатформенным и выпущен для ОС Linux, Windows и MacOS.

Разработку данной САПР начали в 2004 году немцы Michael Margraf и Stefan Jahn (в настоящее время не активны). Сейчас Qucs разрабатывается интернациональной командой, в которую вхожу и я. Руководителями проекта являются Frans Schreuder и Guilherme Torri. Под катом будет рассказано о ключевых возможностях нашего моделировщика схем, его преимуществах и недостатках по сравнению с аналогами.

Главное окно программы показано на скриншоте. Там смоделирован резонансный усилитель на полевом транзисторе и получены осциллограммы напряжения на входе и выходе и также АЧХ.

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

Формат схемного файла Qucs основан на XML и к нему поставляется документация. Поэтому схема Qucs может быть легко сгенерирована сторонними программами. Это позволяет создавать ПО для синтеза схем, которое является расширением Qucs. Проприетарное ПО как правило использует бинарные форматы.

Перечислим основные компоненты, имеющиеся в Qucs:

  1. Пассивные RCL-компоненты
  2. Диоды
  3. Биполярные транзисторы
  4. Полевые транзисторы (JFET, MOSFET, MESFET и СВЧ-транзисторы)
  5. Идеальные ОУ
  6. Коаксиальные и микрополосковые линии
  7. Библиотечные компоненты: транзисторы, диоды и микросхемы
  8. Файловые компоненты: подсхемы, spice-подсхемы, компоненты Verilog

Библиотека компонентов использует собственный формат, основанный на XML. Но можно импортировать существующие библиотеки компонентов, основанные на Spice (приводятся в даташитах на электронные компоненты).

Поддерживаются следующие виды моделирования:

  1. Моделирование рабочей точки на постоянном токе
  2. Моделирование в частотной области на переменном токе
  3. Моделирование переходного процесса во временной области
  4. Моделирование S-параметров
  5. Параметрический анализ

Результаты моделирования можно экспортировать в Octave/Matlab и выполнить там постобработку данных.

Qucs основан на вновь разработанном движке схемотехнического моделирования. Отличительной особенностью этого движка является встроенная возможность моделирования S-параметров и КСВ, что важно для анализа ВЧ-схем. Qucs может пересчитывать S-параметры в Y- и Z-параметры.

На скриншотах показан пример моделирования S-параметров широкополосного усилителя высокой частоты.

Итак, отличительной особенностью Qucs является возможность анализа комплексных частотных характеристик (КЧХ), построение графиков на комплексной плоскости и диаграмм Смита, анализ комплексных сопротивлений и S-параметров. Эти возможности отсутствуют в проприетарных системах MicroCAP и MultiSim, и здесь Qucs даже превосходит коммерческое ПО и позволяет получить недостижимые для симуляторов электронных схем, основанных на Spice результаты.

Недостатком Qucs является малое количество библиотечных компонентов. Но этот недостаток не является препятствием к использованию, так как Qucs совместим с форматом Spice в котором приводятся модели электронных компонентов в даташитах. Также моделировщик работает медленнее, чем аналогичные Spice-совместимые моделировщики (например MicroCAP (проприетарный) или Ngspice (open-source)).

В настоящее время мы работаем над возможностью предоставления пользователю выбора движка для моделирования схемы. Можно будет использовать встроенный движок Qucs, Ngspice (spice-совместимый консольный моделировщик, похожий на PSpice) или Xyce (моделировщик с поддержкой параллельных вычислений через OpenMPI )

Теперь рассмотрим перечень нововведений в недавнем релизе Qucs 0.0.18 перспективных направлений в разработке Qucs:

  1. Улучшена совместимость с Verilog
  2. Продолжается портирование интерфейса на Qt4
  3. Реализован список недавних открытых документов в главном меню.
  4. Реализован экспорт графиков, схем в растровые и векторные форматы: PNG, JPEG, PDF, EPS, SVG, PDF+LaTeX. Эта функция полезна при подготовке статей и отчётов, содержащих результаты моделирования
  5. Возможность открытия документа схемы из будущей версии программы.
  6. Исправлены баги, связанные с зависанием моделировщика при определённых условиях.
  7. Ведётся разработка системы синтеза активных фильтров для Qucs (ожидается в версии 0.0.19)
  8. Ведётся разработка сопряжения с прочими open-source движками для моделирования электронных схем (Ngspice, Xyce, Gnucap). В последующих версиях будет добавлена возможность выбора движка для моделирования схемы.

Можно заключить, что несмотря на свои недостатки Qucs представляет собой весьма достойную альтернативу проприетарным САПР для моделирования электронных схем.

Ресурсы по Qucs:

Сайт проекта: qucs.sourceforge.net
Репозиторий на Github: github.com/Qucs/qucs
Библиотека отечественных компонентов для Qucs: github.com/ra3xdh/qucs-rus-complib

Игра «Жизнь» на логических элементах / Habr

Заранее предупрежу: довольно много картинок.

В данной статье речь пойдёт о реализации игры «Жизнь» на логических элементах в симуляторе «Atanua».

Игра «Жизнь» является, пожалуй, одним из самых узнаваемых клеточных автоматов. Про неё написано не одна статья, в том числе и на Хабрахабре. Когда-то тоже заинтересовался ей, но как-то надолго не хватило.

Напомню, что такое «Жизнь»:Имеется некоторая матрица из клеток, которая зовётся «вселенной» (в идеале бесконечная). На каждой итерации (называемые «днями») любая клетка может быть «живой» или «мёртвой», причём её состояние зависит от предыдущей итерации по следующим правилам:
  • Клетка оживает, если в её окрестности имеются 3 живые клетки.
  • Клетка продолжает жить, если в ёе окрестности живы 2 или 3 клетки.
  • В иных случаях клетка умирает.

Окрестностью клетки считаются 8 окружающих её клеток (см. двумерная окрестность Мура порядка 1).

Подробнее о «Жизне» можно узнать в Википедии.


Позже услышал где-то, что современные компьютеры имеют ограничение в скорости вызванное, в том числе и наличием некоторого канала связи между памятью и вычислительным ядром. В качестве решения предлагалось собрать считающую память. Я уже точно не помню, то ли я сам вспомнил про «Жизнь», то ли она упоминалась в той статье, но я захотел смоделировать её в логической схеме (если быть точным, то в матрице одинаковых схем). Почему именно «Жизнь»? Основными причинами были её распространённость и известность, а также тот факт, что «вселенные» в ней полны по Тьюрингу, что позволяет производить на ней любые вычисления и решать разнообразные задачи. Получается, на основе данного клеточного автомата можно создать компьютер.

В качестве инструмента был выбран симулятор Atanua (официальный сайт), так как довольно лёгкий в освоении и отображает состояние всех линий. В конечном итоге получилось следующее:

Схема одной ячейки

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

Для более подробного рассмотрения левый верхний угол:

Кнопка «r» используется для сброса схемы. Кнопки, подписанные как «0», используются для установки ячейки в живое состояние. Хочу заметить, сброс повторным нажатием пока не реализован. 3 нижних заземления используются как ограничители схемы, чтобы не появлялось разнообразных артефактов. В Atanua провод может иметь 4 состояния:

  • тёмно-зелёный: лог. 0;
  • светло-зелёный: лог. 1;
  • красный: не правильно подключён;
  • белый: не подключён (неопределённое состояние).

При этом, если на вход логического элемента подано неопределённое состояние, то некоторые могут распознать его как 0, а некоторые как 1. Для этого и были поставлены ограничители в виде установки неиспользуемых выводов в 0.

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

Теперь поподробнее о схеме ячейки. Из-за проблем с качеством скриншотов, я буду давать рисунки отдельных узлов.

Регистр


На рисунке выше представлен 2-х разрядный зацикленный сдвиговый регистр на D триггерах, который выступает в роли памяти. С ним связан один не хороший момент, который мне ещё предстоит поправить: во время работы схема как бы мигает, так как в активном состоянии (когда в данный регистр записана информация, то есть в состоянии живой клетки) триггеры обмениваются между собой 0 и 1 и получается, что на выходе F (выход на индикацию состояния, на светодиод например) имеем то 0, то 1 (это заметно на видео в конце статьи). RST – это вход сброса. SET – вход установки ячейки в состояние живой клетки. Как уже упоминалось, сброс отдельной ячейки пока не предусмотрен. Слева сверху подходит тактовый сигнал. О соседних двух проводах далее.

Блок проверки


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

Сумматоры


Пожалуй, самой большой и противоречивой частью схемы являются параллельно-последовательно подключенные сумматоры. Реализовав его, я решил проблему проверки необходимых условий «в лоб», просуммировав все входы A0-A7 от соседних ячеек и проверив результат на соответствие условиям. В данном случае суммируются сначала входы A0+A1+A2, A5+A6+A7, потом результат второй суммы выводы A3 и A4 и так далее. В конечном итоге получилось в конечном итоге 6 сумматоров и 1 полусумматор. Стоит отметить один из сумматоров можно также заменить на полусумматор, т.к. один из его входов не используется. Зачем я сделал один заземлённый вход (слева снизу тёмно-зелёный уходящий за пределы рисунка) – не помню. Изначально хотел её упростить при помощи ДНФ или КНФ, но решать карту Карно 16×16 желания пока не возникает. Так что не исключаю, того момента, что этот модуль может иметь альтернативный вид.

C – это вход таковой частоты, к схеме сумматоров отношения не имеет, идёт к регистру. Про Init я писал выше – рудимент от прошлого варианта.

Итог


Я не считаю игру «Жизнь» достойным клеточным автоматом для реализации считающей памяти, так как «программа» для такого компьютера займёт довольно много места и сложна в реализации. Но всё же схема позволяет по мечтать о микросхеме с реализацией ячеек этой игры. Думаю это было бы довольно интересно, увидеть аппаратную реализацию данного клеточного автомата. Причём я имею ввиду не микроконтроллеры с программой, а исключительно на ячейках из логических элементов.

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

Напоследок несколько видео с работой:

Планер:

Малый корабль:

Уместился и пентадекатлон:

Файлы с проектом на Google Drive.

Некоторое пояснение по содержимому:

live.atanua — ячейка;
LiveFieldM.atanua — матрица;
LiveField.atanua — небольшой элемент матрицы (8×8) из которых создавался LiveFieldM. Края не заземлены.

Для обнаружения сложить в одну папку. Если не поможет, отредактируйте файлы в любом текстовом редакторе (по структуре, обычные XML).

Logisim

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

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

Программа Logisim имеет обширную библиотеку. Среди основных элементов можно отметить: блок логических элементов (управляемый инвертор и буфер, НЕ, ИЛИ, И, четность и нечетность и т.д.), элементы проводки (разветвитель, датчик, контакт, согласующий резистор, передаточный вентиль, тоннель и т.д.), элементы ввода/вывода (кнопка, клавиатура, джойстик, светодиод, семисегментный индикатор, терминал, светодиодная матрица и т.д.), набор мультиплексоров, блок арифметических операций (сумматор, множитель, вычитатель, делитель, компаратор, отрицатель и т.д.), элементы памяти (триггеры, регистры, ОЗУ и ПЗУ, счетчики, генераторы случайных чисел и т.д.). Приложение также позволяет рисовать вертикальные/горизонтальные проводники и осуществляет их автоматическое подключение к элементам схем.

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

Одной из важнейших возможностей программы Logisim является создание подсхем с целью повторного применения уже спроектированных частей, а также для упрощения процесса отладки. Приложение включает небольшой редактор векторной графики, способный менять внешний вид и расположение контактов подсхем при их добавлении в другие схемы. Еще один модуль – «Комбинационный анализ» – позволяет преобразовывать данные между логическими выражениями, логическими схемами и таблицами истинности, давая возможность конвертировать информацию во всех направлениях. Все провода в программе Logisim имеют один из семи цветов, несущих информацию об их назначении. Провода можно собирать в пучки с назначением порядка входа в пучок. Кроме того поддерживается: создание на языке Java пользовательских библиотек компонентов, привязка любого инструмента к определённой комбинации клавиш, вывод полной статистики по количеству и типам компонентов, содержащихся в схеме. Необходимо отметить, что программа Logisim не дает возможности работать с аналоговыми элементами.

Программа Logisim была разработана преподавателем Hendrix College, профессором Карлом Берчем (США, штат Арканзас, город Конуэй). Перевод на русский язык был выполнен Ильей Лиловым. Данный инструмент моделирования логических схем впервые появился в 2001 году, и с тех пор регулярно обновляется и дополняется.

Приложение Logisim является свободным программным обеспечением (лицензия GNU GPL). Софт включает в себя: справку по элементам библиотеки, полное руководство пользователя и краткое пособие для начинающих.

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

Для работы рассматриваемого конструктора схем необходимо наличие пакета Java Runtime Environment (5 версии или более поздней). Программа Logisim является кроссплатформенным программным обеспечением и работоспособна на операционных системах: Microsoft Windows (поддерживаются все последние версии), MacOS, Linux и Solaris. Дистрибутив приложения содержит один исполняемый файл, не требующий установки.

Распространение программы: бесплатная.

Официальный сайт Logisim: http://cburch.com

Форматы файлов Logisim: CIRC

Скачать Logisim

Обсуждение программы на форуме

Программная разработка: «Конструктор логических схем»

1. Введение

Современная электронная вычислительная машина - это сложнейший комплекс устройств, восхищающий своим технологическим совершенством и разнообразием физических принципов работы. Различные устройства машины представляют собой комбинацию большого числа элементов-кирпичиков. Элементы компьютера выполняют хранение, преобразование и передачу двоичных переменных, а также ряд вспомогательных функций: задержку сигнала во времени, формирование сигнала с определенными физическими характеристиками и т. п. Для представления и обработки информации используются различные физические явления и процессы, например электрический ток или магнитный поток. Наличие или отсутствие электрического тока, уровня напряжения различной величины или полярности, величины магнитного потока и т. д. рассматриваются как сигналы. В техническом отношении передача и преобразование дискретной информации реализуется наиболее просто, если различать только два уровня сигнала, соответствующие символам 0 и 1, или понятиям истинности ДА или НЕТ. Различные конструкции элементов могут давать лишь разные технические реализации, гарантирующие распознавание двух таких состояний.

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

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

Так же как и для математической задачи, решение любой логической задачи имеет свою “технологию”. Она составляется из простейших операций, похожих на сложение и умножение. Принято считать, что значение истинности высказывания равно единице, если оно истинно, и равно нулю, если оно ложно. Если условно обозначить различные высказывания буквами A, B и т. д., то в общем виде запись A = 1 означает, что высказывание А истинно, а B = 0 означает, что высказывание B ложно. То, что значение истинности может принимать два значения — 0 и 1, хорошо согласуется с двоичной системой счисления и с работой двухпозиционных элементов, используемых в ЭВМ. Например, в ЭВМ истинность высказывания может быть передана сигналом положительного электрического напряжения, что условно соответствует сигналу 1, а ложность — сигналом отрицательного напряжения или отсутствием вообще какого-либо сигнала. Это условно соответствует сигналу 0.

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

2. Базовые логические элементы

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

3. Постановка задачи.

Создать конструктор и тестер логических схем для внедрения в учебный процесс предмета ОИВТ.

а) Техническое задание.

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

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

4. Назначение пакета (версия DOS)

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

а) Назначение программы “Конструктор логических схем”.

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

Команды главного меню.

РЕДАКТИРОВАНИЕ:

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

ЗАПИСЬ НА ДИСК:

В верхнем правом углу предлагается ввести имя файла (без расширения, расширение .sav присваивается автоматически), в котором будет записана текущая схема. Если нажать клавишу “Esc”, то схема не будет записана, и управление перейдет главному меню. После нажатия клавиши “Enter” схема будет записана на диск, и управление перейдет главному меню. Если в текущей директории будет обнаружен файл, имеющий такое же имя, то будет выдано сообщение об этом и предложено переписать файл. При нажатии на клавишу “Enter” файл будет переписан. Если будет нажата любая другая клавиша, то схема не будет записана.

ЧТЕНИЕ С ДИСКА:

Появляется меню файлов с сохраненными схемами. В верхнем правом углу отображается имя текущего файла. На рабочем поле отображается схема, записанная в текущем файле. В меню имя текущего файла имеет зеленый цвет. Выбор файла в меню осуществляется клавишами передвижения курсора. После нажатия клавиши “Enter” схема, записанная в файле, останется на рабочем поле и текущим станет главное меню. Если вместо клавиши “Enter” нажать клавишу “Delete”, то файл будет удален с диска. Если нажать клавишу “Esc”, то текущим станет главное меню, а на рабочее поле вернется схема, бывшая на нем до запуска команды “ЧТЕНИЕ С ДИСКА”. Также прочитать файл с сохраненной схемой можно, нажав клавишу “Tab”. В верхнем правом углу появится курсор. После ввода с клавиатуры имени файла, он будет прочитан. Если во время ввода повторно нажать клавишу “Tab”, то текущим снова станет меню файлов.

СОЗДАНИЕ ВАРИАНТОВ:

Появляется меню выбора вариантов. Выбор варианта осуществляется клавишами передвижения курсора (всего 28 вариантов).

После нажатия клавиши “Enter” появится список из пяти файлов. Для того чтобы записать в вариант другой файл, нужно клавишами передвижения курсора сделать текущим файл, вместо которого предполагается записать другой файл.

Затем нужно нажать клавишу “Enter”. Появится меню, идентичное меню “ЧТЕНИЯ С ДИСКА”. После выбора нужного файла, вновь появится список варианта. Если сделанные изменения устраивают, нужно нажать клавишу “Esc”. На экране появится меню выбора варианта. Если нужные варианты отредактированы, нажимается клавиша “Esc” и текущим станет главное меню.

КОНТРОЛЬ:

В левой части рабочего поля появляется светлый зеленый прямоугольник, перемещая который по вертикали клавишами передвижения курсора, можно клавишей “Пробел” изменять сигналы, подаваемые на схему. В правой части рабочего поля отображаются сигналы, выходящие из схемы. При нажатии на клавиши “Enter” или “Esc” текущим станет главное меню.

ОЧИСТКА:

  • Очищается рабочее поле.
  • ВЫХОД:
  • Выход из программы.

б) Назначение программы “Тест по логическим схемам”.

Программа “Тест по логическим схемам” предназначена для тестирования учащихся по знанию работы простейших логических схем, основанных на базовых логических элементах. По внешнему виду программа схожа с “Конструктором логических схем”.

Команды главного меню.

ТЕСТИРОВАНИЕ ПО ВАРИАНТАМ:

Появляется меню выбора вариантов. После выбора варианта на рабочем поле появляется первая схема. Сигналы, присутствующие на входе схемы, расставляются случайно. В правой части рабочего поля появляется светлый зеленый прямоугольник, перемещая его по вертикали клавишами передвижения курсора, можно клавишей “Пробел” изменять сигналы, которые по мнению тестируемого должны присутствовать на выходе схемы. Затем нужно нажать клавишу “Enter” и на рабочем поле появится следующая схема.

После окончания теста в поле подсказок будет выведено количество набранных баллов. Каждый правильный ответ — 1 балл. Затем, после нажатия любой клавиши, будет задан вопрос “Тестировать еще раз?”. Если нажать клавишу “Enter”, то тестирование будет повторено. Если нажать любую другую клавишу, текущим станет главное меню.

ТЕСТИРОВАНИЕ БЕЗ ВАРИАНТОВ:

Файлы со схемами выбираются случайно. Тестирование проходит аналогично тестированию по вариантам.

ВКЛЮЧИТЬ (ОТКЛЮЧИТЬ) ВЫВОД НА ПРИНТЕР:

Включает (отключает) вывод на принтер. Вначале вывод на принтер отключен.

ВЫХОД:

Выход из программы.

5. Перспективы развития (пакет под WINDOWS)

В следующих версиях пакета сделаны следующие дополнения:

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

— увеличенное рабочее поле

— возможность управления мышью

— поддержка работы в локальной сети

— вывод схем на принтер

— сохранение схем в файлах в графическом виде

— более дружелюбный и удобный интерфейс

— красочная графика

— возможность настройки программы по вкусу пользователя

Версия для WINDOWS

Все это было реализовано в версии 1.00 для OS WINDOWS

1. Построение логической схемы…осуществляется выбором из библиотеки элементов соответствующего соединения и расстановкой его на рабочем поле.

2. Настройка вида программы по вкусу пользователя…

3. Построение сложных реальных схем. Пример – дешифратор

4. Вызов справочной информации

5. Вызов библиотеки логических схем…

6. Сохранение логической схемы в формате BITMAP

7. Тестирование и многое другое…

Литература.

  1. М.Г. Мнеян “Физические принципы работы ЭВМ”, 1987 г.

Конструктор логических схем.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *