Uploaded by kurka2017

ТСМПС

advertisement
СОДЕРЖАНИЕ
Введение ................................................................................................................... 4
1 ТЕОРЕТИЧЕСКИЕ ОСНОВЫ РАБОТЫ УСТРОЙСТВА............................... 6
1.1 I²C..................................................................................................................... 6
1.2 Принцип подключения .................................................................................. 6
1.3 Принцип работы ............................................................................................. 7
1.3.1 Состояние старт и стоп .......................................................................... 7
1.3.2 Подтверждение ....................................................................................... 8
1.3.3 Синхронизация ....................................................................................... 8
1.4 Адресация в шине I²C .................................................................................... 9
1.5 Описание выводов ПЛИС и форматов данных ......................................... 11
2 VHDL-ОПИСАНИЕ МИКРОЭЛЕКТРОННОГО УСТРОЙСТВА ................ 13
3 ТЕСТИРОВАНИЕ РАБОТЫ МИКРОЭЛЕКТРОННОГО УСТРОЙСТВА.. 16
4 АППАРАТНАЯ РЕАЛИЗАЦИЯ МИКРОЭЛЕКТРОННОГО УСТРОЙСТВА
................................................................................................................................. 17
4.1 Обоснование выбора ПЛИС и микросхемы конфигурационного ПЗУ . 17
4.2 Использованные ресурсы ПЛИС ................................................................ 18
4.3 Оценка потребляемой устройством мощности ......................................... 22
Заключение ............................................................................................................ 23
Список используемых источников ...................................................................... 24
Приложение А - Реализация Master на языке VHDL ........................................ 25
Приложение Б - Тестирование Master на языке VHDL ..................................... 30
Приложение B - Реализация Slave на языке VHDL ........................................... 33
Приложение Г - Тестирование Slave на языке VHDL ....................................... 39
Приложение Г - Тестирование Master - Slave на языке C ................................. 48
Разработка безопасного микропроцессорного устройства
Изм. Лист
Разраб.
Руководит. .
Реценз.
Н. контр.
Утв.
№ докум.
Подпись Дата
Записка
пояснительная
Лит.
Лист
Листов
3
Кафедра
«ИУСиТ»
1
Введение
Системы автоматизированного проектирования (САПР) вычислительной
техники, как правило, имеют средства ввода и редактирования схем. Однако три
десятилетия назад при разработке СБИС начали отказываться от схемного
проектирования.
При разработке электрических схем этап проектирования средств
вычислительной техники – это работа, связанная с определёнными трудностями:
большими трудозатратами, контролем правильности и соответствия задуманному
проекту, необходимостью чёткого и ёмкого описания созданных схем, трудностями
с их сопровождением и модернизацией.
Язык «Very high speed integrated circuits Hardware Description Language»
(VHDL) был разработан в 1983 г. по заказу Министерства обороны США с целью
формального описания логических схем для всех этапов разработки электронных
систем, от модулей микросхем и до крупных вычислительных систем. Он является
стандартным языком с 1987 г. Стандартом 1993 г. закреплены многие его
усовершенствования. Наряду с языком Verilog он является базовым языком при
разработке аппаратуры современных вычислительных систем.
Преимущества VHDL перед схемным проектированием весьма значительны.
Это и универсальность, и надёжность, и портативность, и возможность
самодокументирования. Проекты, написанные на VHDL, предназначены для
исполнения в программируемой логической интегральной схеме (ПЛИС).
Размещение всего оборудования на одном кристалле является очень
выгодным, благодаря уменьшению общей стоимости, числа необходимых
микросхем, энергопотребления, повышению надёжности. Таким образом, на одном
кристалле размещается не только конкретное функциональное устройство,
например, центральный микропроцессор, но и другие, такие как АЦП, ОЗУ, ПЗУ,
блоки цифровой обработки сигналов, интерфейсные узлы и т.п., дополняющие его
до законченной системы блоков. Поэтому такое вычислительное устройство (ВУ)
принято называть «System On the Chip» (SOC) – системой на кристалле (СНК).
СНК это, как правило, заказная СБИС. Чтобы разработка СНК себя окупила,
необходимо реализовать десятки и сотни тысяч СБИС. Проект ВУ, реализованный
на ПЛИС, может быть выгодным при партиях в десятки и сотни экземпляров,
благодаря дешевизне разработки и производства. Разработка такого ВУ длится как
минимум в два раза быстрее, чем проектирование СБИС. Это обусловило бурное
распространение ПЛИС как элементной базы СНК.
В курсовой работе разработано специализированное микроэлектронное
устройство, реализующее алгоритм послеовательной передачи данных I2C.
В задачи курсовой работы входит: рассмотрение теоретических основ работы
алгоритма послеовательной передачи данных I2C, разработка алгоритма
функционирования устройства, описание алгоритма на языке VHDL, выбор
оптимального ПЛИС под заданные цели, синтез VHDL-описания и размещение
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
4
устройства на кристалле, а также тестирование разработанного микроэлектронного
устройства.
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
5
1 ТЕОРЕТИЧЕСКИЕ ОСНОВЫ РАБОТЫ УСТРОЙСТВА
1.1 I²C
I²C (IIC, англ. Inter-Integrated
Circuit) —
последовательная асимметричная шина для
связи
между интегральными
схемами внутри электронных приборов. Использует две двунаправленные линии
связи (SDA и SCL), применяется для соединения низкоскоростных периферийных
компонентов с процессорами и микроконтроллерами (например,
на материнских
платах, во встраиваемых системах, в мобильных телефонах).
1.2 Принцип подключения
Данные передаются по двум проводам — проводу данных и проводу тактов.
Есть ведущий (master) и ведомый (slave), такты генерирует master, ведомый лишь
«поддакивает» при приёме байта. Всего на одной двухпроводной шине может быть
до 127 устройств.
Рисунок 1 – Принцип подключения шины I2C
Пример схемотехники с одним главным микроконтроллером (μC Master) и
тремя
подчинёнными
(slave)
устройствами
(ADC — аналого-цифровой
преобразователь,
DAC — цифро-аналоговый
преобразователь и
второй
(подчиненный) микроконтроллер (μC Slave)), подтягивающими резисторами Rp.
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
6
1.3 Принцип работы
Рисунок 2 – Принцип работы шины I2C
I²C использует две двунаправленные линии, подтянутые к напряжению
питания и управляемые через открытый коллектор или открытый сток —
последовательная линия данных (SDA, англ. Serial DAta) и последовательная
линия тактирования (SCL, англ. Serial CLock). Стандартные напряжения +5 В или
+3,3 В, однако допускаются и другие.
Классическая адресация включает 7-битное адресное пространство с 16
зарезервированными адресами. Это означает, что разработчикам доступно до 112
свободных адресов для подключения периферии на одну шину.
Основной режим работы — 100 кбит/с; 10 кбит/с в режиме работы с
пониженной скоростью. Также немаловажно, что стандарт допускает приостановку
тактирования для работы с медленными устройствами.
1.3.1 Состояние старт и стоп
Процедура обмена начинается с того, что ведущий формирует состояние
СТАРТ: генерирует переход сигнала линии SDA из ВЫСОКОГО состояния в
НИЗКОЕ при ВЫСОКОМ уровне на линии SCL. Этот переход воспринимается
всеми устройствами, подключенными к шине, как признак начала процедуры
обмена. Генерация синхросигнала — это всегда обязанность ведущего; каждый
ведущий генерирует свой собственный сигнал синхронизации при пересылке
данных по шине. Процедура обмена завершается тем, что ведущий формирует
состояние СТОП — переход состояния линии SDA из НИЗКОГО состояния в
ВЫСОКОЕ при ВЫСОКОМ состоянии линии SCL. Состояния СТАРТ и СТОП
всегда вырабатываются ведущим. Считается, что шина занята после фиксации
состояния СТАРТ. Шина считается освободившейся через некоторое время после
фиксации состояния СТОП. При передаче посылок по шине I²C каждый ведущий
генерирует свой синхросигнал на линии SCL. После формирования состояния
СТАРТ ведущий опускает состояние линии SCL в НИЗКОЕ состояние и
выставляет на линию SDA старший бит первого байта сообщения. Количество байт
в сообщении не ограничено. Спецификация шины I²C разрешает изменения на
линии SDA только при НИЗКОМ уровне сигнала на линии SCL. Данные
действительны и должны оставаться стабильными только во время ВЫСОКОГО
состояния синхроимпульса. Для подтверждения приёма байта от ведущегопередатчика ведомым-приёмником в спецификации протокола обмена по шине I²C
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
7
вводится специальный бит подтверждения, выставляемый на шину SDA после
приёма 8 бит данных.
1.3.2 Подтверждение
Таким образом, передача 8 бит данных от передатчика к приёмнику
завершаются дополнительным циклом (формированием 9-го тактового импульса
линии SCL), при котором приёмник выставляет низкий уровень сигнала на линии
SDA, как признак успешного приёма байта.
Подтверждение при передаче данных обязательно, кроме случаев окончания
передачи ведомой стороной. Соответствующий импульс синхронизации
генерируется ведущим. Передатчик отпускает (переводит в ВЫСОКОЕ состояние)
линию SDA на время синхроимпульса подтверждения. Приёмник должен
удерживать линию SDA в течение ВЫСОКОГО состояния синхроимпульса
подтверждения в стабильном НИЗКОМ состоянии.
В том случае, когда ведомый-приёмник не может подтвердить свой адрес
(например, когда он выполняет в данный момент какие-либо функции реального
времени), линия данных должна быть оставлена в ВЫСОКОМ состоянии. После
этого ведущий может выдать состояние СТОП для прерывания пересылки данных.
Если в пересылке участвует ведущий-приёмник, то он должен сообщить об
окончании передачи ведомому-передатчику путём неподтверждения последнего
байта. Ведомый-передатчик должен освободить линию данных для того, чтобы
позволить ведущему выдать состояние СТОП или повторить состояние СТАРТ.
1.3.3 Синхронизация
Синхронизация выполняется с использованием подключения к линии SCL по
правилу монтажного И. Это означает, что ведущий не имеет монопольного права
на управление переходом линии SCL из НИЗКОГО состояния в ВЫСОКОЕ. В том
случае, когда ведомому необходимо дополнительное время на обработку
принятого бита, он имеет возможность удерживать линию SCL в низком состоянии
до момента готовности к приёму следующего бита. Таким образом, линия SCL
будет находиться в НИЗКОМ состоянии на протяжении самого длинного
НИЗКОГО периода синхросигналов.
Устройства с более коротким НИЗКИМ периодом будут входить в состояние
ожидания на время, пока не кончится длинный период. Когда у всех
задействованных устройств кончится НИЗКИЙ период синхросигнала, линия SCL
перейдет в ВЫСОКОЕ состояние. Все устройства начнут проходить ВЫСОКИЙ
период своих синхросигналов. Первое устройство, у которого кончится этот
период, снова установит линию SCL в НИЗКОЕ состояние. Таким образом,
НИЗКИЙ период синхролинии SCL определяется наидлиннейшим периодом
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
8
синхронизации из всех задействованных устройств, а ВЫСОКИЙ период
определяется самым коротким периодом синхронизации устройств.
Механизм синхронизации может быть использован приёмниками как средство
управления пересылкой данных на байтовом и битовом уровнях.
На уровне байта, если устройство может принимать байты данных с большой
скоростью, но требует определенное время для сохранения принятого байта или
подготовки к приёму следующего, то оно может удерживать линию SCL в
НИЗКОМ состоянии после приёма и подтверждения байта, переводя таким образом
передатчик в состояние ожидания.
На уровне битов устройство, такое, как микроконтроллер без встроенных
аппаратных цепей I²C или с ограниченными цепями, может замедлить частоту
синхроимпульсов путём продления их НИЗКОГО периода. Таким образом
скорость передачи любого ведущего адаптируется к скорости медленного
устройства.
1.4 Адресация в шине I²C
Каждое устройство, подключённое к шине, может быть программно
адресовано по уникальному адресу. Для выбора приёмника сообщения ведущий
использует уникальную адресную компоненту в формате посылки. При
использовании однотипных устройств ИС часто имеют дополнительный селектор
адреса, который может быть реализован как в виде дополнительных цифровых
входов селектора адреса, так и в виде аналогового входа. При этом адреса таких
однотипных устройств оказываются разнесены в адресном пространстве устройств,
подключенных к шине.
В обычном режиме используется 7-битная адресация.
Процедура адресации на шине I²C заключается в том, что первый байт после
сигнала СТАРТ определяет, какой ведомый адресуется ведущим для проведения
цикла обмена. Исключение составляет адрес «Общего вызова», который адресует
все устройства на шине. Когда используется этот адрес, все устройства в теории
должны послать сигнал подтверждения. Однако устройства, которые могут
обрабатывать «общий вызов», на практике встречаются редко.
Первые семь битов первого байта образуют адрес ведомого. Восьмой,
младший бит, определяет направление пересылки данных. «Ноль» означает, что
ведущий будет записывать информацию в выбранного ведомого. «Единица»
означает, что ведущий будет считывать информацию из ведомого.
После того, как адрес послан, каждое устройство в системе сравнивает первые
семь бит после сигнала СТАРТ со своим адресом. При совпадении устройство
полагает себя выбранным как ведомый-приёмник или как ведомый-передатчик, в
зависимости от бита направления.
Адрес ведомого может состоять из фиксированной и программируемой части.
Часто случается, что в системе будет несколько однотипных устройств (к примеру,
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
9
ИМС памяти, или драйверов светодиодных индикаторов), поэтому при помощи
программируемой части адреса становится возможным подключить к шине
максимально
возможное
количество
таких
устройств.
Количество
программируемых битов в адресе зависит от количества свободных выводов
микросхемы. Иногда используется один вывод с аналоговой установкой
программируемого диапазона адресов. При этом в зависимости от потенциала на
этом адресном выводе ИМС, возможно смещение адресного пространства драйвера
так, чтобы однотипные ИМС не конфликтовали между собой на общей шине.
Все специализированные ИМС, поддерживающие работу в стандарте шины
I²C, имеют набор фиксированных адресов, перечень которых указан
производителем в описаниях контроллеров.
Комбинация бит 11110ХХ адреса зарезервирована для 10-битной адресации.
Как следует из спецификации шины, допускаются как простые форматы
обмена, так и комбинированные, когда в промежутке от состояния СТАРТ до
состояния СТОП ведущий и ведомый могут выступать и как приёмник, и как
передатчик данных. Комбинированные форматы могут быть использованы,
например, для управления последовательной памятью.
Во время первого байта данных можно передавать адрес в памяти, который
записывается во внутренний регистр-защёлку. После повторения сигнала СТАРТа
и адреса ведомого выдаются данные из памяти. Все решения об авто-инкременте
или декременте адреса, к которому произошёл предыдущий доступ, принимаются
конструктором конкретного устройства. Поэтому в любом случае лучший способ
избежать неконтролируемой ситуации на шине перед использованием новой (или
ранее не используемой) ИМС — следует тщательно изучить её описание (datasheet
или reference manual), получив его с сайта производителя. Более того,
производители часто размещают рядом более подробные инструкции по
применению.
В любом случае по спецификации шины все разрабатываемые устройства
должны сбрасывать логику шины при получении сигнала СТАРТ или повторный
СТАРТ и подготавливаться к приёму адреса.
Тем не менее, основные проблемы с использованием I²C шины возникают
именно из-за того, что разработчики, «начинающие» работать с I²C шиной, не
учитывают того факта, что ведущий (часто — микропроцессор) не имеет
монопольного права ни на одну из линий шины.
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
10
1.5 Описание выводов ПЛИС и форматов данных
Рисунок 3 – Описание выводов ПЛИС
Таблица 1 – Описания портов
порт
CLK
ширина
1
Режим
in
RESET_N
1
in
ЕСА
1
in
addr
7
in
RW
1
in
data_wr
8
in
data_rd
8
out
занятый
1
out
Тип данных
стандартная
логика
стандартная
логика
стандартная
логика
Интерфейс
пользовательская
логика
пользовательская
логика
пользовательская
логика
стандартный
логический
вектор
стандартная
логика
стандартный
логический
вектор
стандартный
логический
вектор
стандартная
пользовательская
логика
Описание
Системные часы.
Асинхронный активный
сброс низкого уровня.
0: транзакция не
инициирована.
1: фиксирует в addr, rw и
data_wr, чтобы
инициировать
транзакцию. Если ena
имеет высокий уровень
при завершении
транзакции (то есть,
когда занятость
становится низкой),
тогда для продолжения
транзакции
фиксируются новый
адрес, команда чтения /
записи и данные.
Адрес целевого раба.
пользовательская
логика
пользовательская
логика
0: написать команду.
1: команда чтения.
Данные для передачи,
если rw = 0 (запись).
пользовательская
логика
Данные получены, если
rw = 1 (чтение).
пользовательская
0: ведущее устройство
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
11
логика
логика
ack_error
1
buffer
стандартная
логика
пользовательская
логика
SDA
1
INOUT
стандартная
логика
подчиненные
устройства
SCL
1
INOUT
стандартная
логика
подчиненные
устройства
I2C находится в режиме
ожидания, и данные
последнего чтения
доступны в data_rd.
1: команда
зафиксирована и
транзакция
выполняется.
0: нет подтвержденных
ошибок.
1: по крайней мере одна
ошибка подтверждения
произошла во время
транзакции. ack_error
очищается в начале
каждой транзакции.
Последовательная
линия передачи данных
шины I2C.
Последовательная
линия шины I2C.
Рисунок 4 – Описание выводов ПЛИС
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
12
2 VHDL-ОПИСАНИЕ МИКРОЭЛЕКТРОННОГО УСТРОЙСТВА
Мастер I2C использует конечный автомат, показанный на рисунке 5, для
реализации протокола шины I2C. После запуска компонент сразу переходит
в состояние готовности . В этом состоянии он ожидает, пока сигнал ena
не зафиксируется в команде. Начало состояние формирует условие запуска на
шине I2C, а команда состояние передает адрес и Rw команды к
шине. Затем состояние slv_ack1 захватывает
и
проверяет
подтверждение
ведомого. В зависимости от команды rw компонент затем переходит либо к записи
данных в подчиненное устройство ( состояние wr ), либо к получению данных от
подчиненного устройства ( состояние rd ). После завершения мастер захватывает и
проверяет
ответ
ведомого
(состояние slv_ack2 )
при
записи
или выдача собственного
ответа
( состояние mstr_ack )
при
чтении. Если сигнал ena фиксируется в другой команде, мастер немедленно
продолжает другую запись ( состояние wr ) или чтение ( состояние rd ), если
команда совпадает с предыдущей командой. Если он отличается от предыдущей
команды (то есть чтения после записи или записи после чтения или нового адреса
подчиненного
устройства),
то
мастер
выдает
повторный
запуск
( состояние запуска ) в соответствии со спецификацией I2C. Как только мастер
завершает чтение или запись, и сигнал ena не фиксируется в новой команде, мастер
генерирует
условие останова (состояние останова )
и
возвращается
в
готовое состояние.
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
13
Рисунок 5 – Главный конечный автомат I2C
Модуль Slave можно использовать через следующий интерфейс:
Рисунок 6 – Интерфейс модуля Slave
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
14
Когда значение read_req имеет высокое состояние, Slave извлекает
данные data_to_master в одном и том же тактовом цикле, поэтому обязательно
заранее установлены правильные данные. Когда data_valid становится в высокое
состояние, data_from_master предоставляет данные в том же тактовом цикле.
Slave игнорирует все главные команды, направленные на адреса, которые не
совпадают с MINION_ADDR. 7 битов MINION_ADDR обычно задаются в формате
старшего значащего бита (MSB) на стороне мастера. Например, 7-битный адрес
«0000011» соответствует десятичному 3 на Slave, на самом деле это 6 на главном,
потому что LSB никогда не отправляется.
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
15
3
ТЕСТИРОВАНИЕ
УСТРОЙСТВА
РАБОТЫ
МИКРОЭЛЕКТРОННОГО
Для тестирования Master необходимо задать адрес Slave и подать на вход
данных передаваемую информацию. Если Master свободен и Slave готов к приёму,
начнётся передача данных.
Рисунок 7 – Тестирование работы Master
Для тестирования Slave необходимо задать адрес Master и подать на вход
данных передаваемую информацию. Если шина данных SDA свободна, т.е.
находится в высокоомном состоянии и Master готов к приёму, начнётся передача
данных.
Рисунок 8 – Тестирование работы Slave
Для тестирования Master-Slave были промоделированы Master и Slave и
написана программа на языке C которая продемонстрирована в приложении Д.
Рисунок 9 – Тестирование Master-Slave
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
16
4 АППАРАТНАЯ
УСТРОЙСТВА
РЕАЛИЗАЦИЯ
МИКРОЭЛЕКТРОННОГО
4.1 Обоснование выбора ПЛИС и микросхемы конфигурационного
ПЗУ
Для реализации разработанного программного кода используем семейство
ПЛИС Spartan-6. Семейство специально разработана для использования в
электронных устройствах, рассчитанных на большие тиражи и невысокую
стоимость.
ПЛИС семейства Spartan-6 имеют емкость, достигающую 23 038 логических
ячеек и 184 304 системных вентилей (триггеров). Иерархическая система
элементов памяти выглядит следующим образом. Программа на ПЛИС семейства
Spartan-6 может быть построена на базе шестивходовых таблиц преобразования
(LUT-6 – Look-Up Table) конфигурируемых либо как 64-битное ОЗУ, либо как 64битный сдвиговый регистр; а также на встроенной блочной памяти, каждый блок
конфигурируется как синхронное двухпортовое ОЗУ ёмкостью 4,824 кбит. Также,
имеются быстрые интерфейсы PCI Express (1 примитив), GTP (8 примитивов) и
блоки аппаратных умножителей DSP48 Slice (180 примитивов), а также блок
управления и синтеза сигналов синхронизации (CMT).
Основные особенности семейства Spartan-6: технологический процесс 45 нм;
системная тактовая частота до 400 МГц; пониженное напряжение питания ядра –
1,2 В или 1,0 В; широкий диапазон напряжений блоков ввода-вывода – от 1,2 В до
3,3 В; программируемый ток выходных каскадов до 24 мА; поддержка 17
сигнальных стандартов ввода-вывода; 6 дифференциальных стандартов передачи
сигналов, включая LVDS; скорость 1050 Мбит/с по каждой дифференциальной
паре
контактов;
скорость
3,125
Гбит/с
для
приёмо-передатчиков;
программируемый импеданс; контроллер памяти DDR, DDR2, DDR3,
обеспечивающий полосу пропускания до 12,8 Гбит/с; блоки памяти емкостью 18
кбит, который можно сконфигурировать как два блока по 9 кбит.
Предусмотрена защита проекта от копирования, используется шифрование
конфигурационной последовательности по алгоритму AES.
Для заданных целей была выбрана микросхема XC6SLX9-3FTG256. Скорость
чипа (быстродействие логики) была выбрана максимально возможной для данного
кристалла (-3).
Для наших целей в соответствии с таблицей 3, в которой представлены
рекомендуемые фирмой производителем микросхемы памяти, было выбрано
Flash-ПЗУ S25FL008K с последовательным интерфейсом, которая также подходит
для используемой ПЛИС XC6SLX9-3FTG256.
В таблице 3 выделена строка с используемой микросхемой ПЛИС (XC6SLX9)
и микросхемой Flash-ПЗУ (S25FL008K).
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
17
Таблица 3 – Рекомендуемые типы Flash-ПЗУ
Наименование
ПЛИС
Емкость, Мбит
Flash-ПЗУ
XC6SLX4
S25FL008K
2,7
XC6SLX9
S25FL008K
2,7
XC6SLX16
S25FL008K
3,7
XC6SLX25
S25FL008K
6,4
XC6SLX45
S25FL016K
11,9
XC6SLX75
S25FL032P
19,6
XC6SLX100
S25FL032P
26,5
XC6SLX150
S25FL064P
33,8
XC6SLX25T
S25FL008K
6,4
XC6SLX45T
S25FL016K
11,9
XC6SLX75T
S25FL032P
19,6
XC6SLX100T
S25FL032P
26,5
XC6SLX150T
S25FL064P
33,8
4.2 Использованные ресурсы ПЛИС
Проект успешно синтезирован и размещен на кристалле XC6SLX9-3FTG256.
На рисунке 13 представлен отчет о синтезе, компиляции, разводке и расположении
на кристалле проектируемого устройства.
Рисунок 10 – Отчет о синтезе, компиляции, разводке и расположении на кристалле
проектируемого устройства
В результате, проект синтезировался и расположился на кристалле успешно
(ошибки и предупреждения отсутствуют). На рисунках 14 и 15 представлена
таблица используемых в ПЛИС ресурсов. Задействовано приблизительно 40-50%
внутренней логики ПЛИС.
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
18
Рисунок 11 – Таблица используемых в ПЛИС ресурсов (начало)
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
19
Рисунок 12 – Таблица используемых в ПЛИС ресурсов (продолжение)
На рисунке 16 представлено размещение устройства на кристалле ПЛИС
XC6SLX9-3FTG256. Визульное размещение устройства на кристалле произведено с
помощью встроенной в Xilinx ISE 14.5 утилиты «PlanAhead».
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
20
Рисунок 13 – Размещение устройства на кристалле
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
21
4.3 Оценка потребляемой устройством мощности
Произведена оценка электрических параметров системы, а именно
потребляемой устройством мощности, с помощью встроенной в Xilinx ISE 14.5
утилиты «XPower Analyzer».
На рисунке 17 показана сводная таблица энергопотребления всего ПЛИС.
Рисунок 14 – Таблица энергопотребления всего ПЛИС
В соответствии с рисунком 17, максимальная допустимая температура
окружающей среды для гарантированной работы ПЛИС составляет 84,3 °C, а
рекомендумая темпаратура – 25,5 °C. Эффективная температура для теплоотвода
составила 31,8 °C/Вт. Средняя мощность, потребляемая устройством, составляет
0,014 Вт, максимальная мощность – 0,023 Вт.
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
22
Заключение
В курсовой работе спроектировано специализированное микроэлектронное
устройство, реализующее последовательную шину передачи данных I2C. Данное
устройство может быть использовано как составная часть сложных систем
обработки информации.
Приведённые пояснения, блок-схемы алгоритмов и временные диаграммы
призваны сделать технический продукт максимально понятным для любого
специалиста, которому будет необходимо использовать кодер или его часть.
ПЛИС, выбранная для реализации последовательной шины передачи данных
I2C, является широкодоступной. Доступно также и программное обеспечение,
позволяющее легко проверить и при необходимости скорректировать реализацию
кодера. Поэтому не должно возникать никаких трудностей при использовании
продукта.
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
23
Список используемых источников
1 I2C [Электронный ресурс] / Материал из Википедии - свободной
энциклопедии. 2013 Режим доступа: http://ru.wikipedia.org/wiki/I2C.
2 Сеть Фейстеля [Электронный ресурс] / Материал из Википедии свободной энциклопедии., 2019 Режим доступа:
http://ru.wikipedia.org/wiki/Сеть_Фейстеля.
3 Шнайер Б. «Прикладная криптография», М.: Издательство Триумф, 2003 г.
4 Тарасов, И. Е. Разработка цифровых устройств на основе ПЛИС Xilinx с
применением языка VHDL / И. Е. Тарасов. – М.: Горячая линия – Телеком, 2005. –
252 с.
5 Суворова, Е.А. Проектирование цифровых устройств на VHDL / Е. А.
Суворова, Ю. Е. Шейнин. – СПб.: БХВ-Петербург, 2003 – 576 с.
6 Бочков К.А. Автоматика, телемеханика и связь на транспорте: Пособие по
оформлению дипломных проектов / К.А.Бочков, С.Н.Харлап, Серенков А.Г.,
Кондрачук В.Ф. – Гомель: БелГУТ, 2002. – 70 с.
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
24
Приложение А - Реализация Master на языке VHDL
----------------------------------------------------------------------------------- Company:
-- Engineer:
--- Create Date: 12:48:37 11/05/2019
-- Design Name:
-- Module Name: i2c_master - logic
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--- Dependencies:
--- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
----------------------------------------------------------------------------------library IEEE;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity i2c_master is
GENERIC(
input_clk : INTEGER := 50_000_000; --input clock speed from user logic in Hz
bus_clk : INTEGER := 400_000); --speed the i2c bus (scl) will run at in Hz
PORT(
clk : IN STD_LOGIC;
--system clock
reset_n : IN STD_LOGIC;
--active low reset
ena : IN STD_LOGIC;
--latch in command
addr : IN STD_LOGIC_VECTOR(6 DOWNTO 0); --address of target slave
rw
: IN STD_LOGIC;
--'0' is write, '1' is read
data_wr : IN STD_LOGIC_VECTOR(7 DOWNTO 0); --data to write to slave
busy : OUT STD_LOGIC;
--indicates transaction in progress
data_rd : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); --data read from slave
ack_error : BUFFER STD_LOGIC;
--flag if improper acknowledge from slave
sda : INOUT STD_LOGIC;
--serial data output of i2c bus
scl : INOUT STD_LOGIC);
--serial clock output of i2c bus
end i2c_master;
architecture logic of i2c_master is
CONSTANT divider : INTEGER := (input_clk/bus_clk)/4; --number of clocks in 1/4 cycle of scl
TYPE machine IS(ready, start, command, slv_ack1, wr, rd, slv_ack2, mstr_ack, stop); --needed states
SIGNAL state
: machine;
--state machine
SIGNAL data_clk : STD_LOGIC;
--data clock for sda
SIGNAL data_clk_prev : STD_LOGIC;
--data clock during previous system clock
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
25
SIGNAL scl_clk : STD_LOGIC;
--constantly running internal scl
SIGNAL scl_ena : STD_LOGIC := '0';
--enables internal scl to output
SIGNAL sda_int : STD_LOGIC := '1';
--internal sda
SIGNAL sda_ena_n : STD_LOGIC;
--enables internal sda to output
SIGNAL addr_rw : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in address and read/write
SIGNAL data_tx : STD_LOGIC_VECTOR(7 DOWNTO 0); --latched in data to write to slave
SIGNAL data_rx : STD_LOGIC_VECTOR(7 DOWNTO 0); --data received from slave
SIGNAL bit_cnt : INTEGER RANGE 0 TO 7 := 7; --tracks bit number in transaction
SIGNAL stretch : STD_LOGIC := '0';
--identifies if slave is stretching scl
begin
--generate the timing for the bus clock (scl_clk) and the data clock (data_clk)
PROCESS(clk, reset_n)
VARIABLE count : INTEGER RANGE 0 TO divider*4; --timing for clock generation
BEGIN
IF(reset_n = '0') THEN
--reset asserted
stretch <= '0';
count := 0;
ELSIF(clk'EVENT AND clk = '1') THEN
data_clk_prev <= data_clk;
--store previous value of data clock
IF(count = divider*4-1) THEN
--end of timing cycle
count := 0;
--reset timer
ELSIF(stretch = '0') THEN
--clock stretching from slave not detected
count := count + 1;
--continue clock generation timing
END IF;
CASE count IS
WHEN 0 TO divider-1 =>
--first 1/4 cycle of clocking
scl_clk <= '0';
data_clk <= '0';
WHEN divider TO divider*2-1 => --second 1/4 cycle of clocking
scl_clk <= '0';
data_clk <= '1';
WHEN divider*2 TO divider*3-1 => --third 1/4 cycle of clocking
scl_clk <= '1';
--release scl
IF(scl = '0') THEN
--detect if slave is stretching clock
stretch <= '1';
ELSE
stretch <= '0';
END IF;
data_clk <= '1';
WHEN OTHERS =>
--last 1/4 cycle of clocking
scl_clk <= '1';
data_clk <= '0';
END CASE;
END IF;
END PROCESS;
--state machine and writing to sda during scl low (data_clk rising edge)
PROCESS(clk, reset_n)
BEGIN
IF(reset_n = '0') THEN
--reset asserted
state <= ready;
--return to initial state
busy <= '1';
--indicate not available
scl_ena <= '0';
--sets scl high impedance
sda_int <= '1';
--sets sda high impedance
ack_error <= '0';
--clear acknowledge error flag
bit_cnt <= 7;
--restarts data bit counter
data_rd <= "00000000";
--clear data read port
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
26
ELSIF(clk'EVENT AND clk = '1') THEN
IF(data_clk = '1' AND data_clk_prev = '0') THEN --data clock rising edge
CASE state IS
WHEN ready =>
--idle state
IF(ena = '1') THEN
--transaction requested
busy <= '1';
--flag busy
addr_rw <= addr & rw;
--collect requested slave address and command
data_tx <= data_wr;
--collect requested data to write
state <= start;
--go to start bit
ELSE
--remain idle
busy <= '0';
--unflag busy
state <= ready;
--remain idle
END IF;
WHEN start =>
--start bit of transaction
busy <= '1';
--resume busy if continuous mode
sda_int <= addr_rw(bit_cnt); --set first address bit to bus
state <= command;
--go to command
WHEN command =>
--address and command byte of transaction
IF(bit_cnt = 0) THEN
--command transmit finished
sda_int <= '1';
--release sda for slave acknowledge
bit_cnt <= 7;
--reset bit counter for "byte" states
state <= slv_ack1;
--go to slave acknowledge (command)
ELSE
--next clock cycle of command state
bit_cnt <= bit_cnt - 1;
--keep track of transaction bits
sda_int <= addr_rw(bit_cnt-1); --write address/command bit to bus
state <= command;
--continue with command
END IF;
WHEN slv_ack1 =>
--slave acknowledge bit (command)
IF(addr_rw(0) = '0') THEN
--write command
sda_int <= data_tx(bit_cnt); --write first bit of data
state <= wr;
--go to write byte
ELSE
--read command
sda_int <= '1';
--release sda from incoming data
state <= rd;
--go to read byte
END IF;
WHEN wr =>
--write byte of transaction
busy <= '1';
--resume busy if continuous mode
IF(bit_cnt = 0) THEN
--write byte transmit finished
sda_int <= '1';
--release sda for slave acknowledge
bit_cnt <= 7;
--reset bit counter for "byte" states
state <= slv_ack2;
--go to slave acknowledge (write)
ELSE
--next clock cycle of write state
bit_cnt <= bit_cnt - 1;
--keep track of transaction bits
sda_int <= data_tx(bit_cnt-1); --write next bit to bus
state <= wr;
--continue writing
END IF;
WHEN rd =>
--read byte of transaction
busy <= '1';
--resume busy if continuous mode
IF(bit_cnt = 0) THEN
--read byte receive finished
IF(ena = '1' AND addr_rw = addr & rw) THEN --continuing with another read at same address
sda_int <= '0';
--acknowledge the byte has been received
ELSE
--stopping or continuing with a write
sda_int <= '1';
--send a no-acknowledge (before stop or repeated start)
END IF;
bit_cnt <= 7;
--reset bit counter for "byte" states
data_rd <= data_rx;
--output received data
state <= mstr_ack;
--go to master acknowledge
ELSE
--next clock cycle of read state
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
27
bit_cnt <= bit_cnt - 1;
--keep track of transaction bits
state <= rd;
--continue reading
END IF;
WHEN slv_ack2 =>
--slave acknowledge bit (write)
IF(ena = '1') THEN
--continue transaction
busy <= '0';
--continue is accepted
addr_rw <= addr & rw;
--collect requested slave address and command
data_tx <= data_wr;
--collect requested data to write
IF(addr_rw = addr & rw) THEN --continue transaction with another write
sda_int <= data_wr(bit_cnt); --write first bit of data
state <= wr;
--go to write byte
ELSE
--continue transaction with a read or new slave
state <= start;
--go to repeated start
END IF;
ELSE
--complete transaction
state <= stop;
--go to stop bit
END IF;
WHEN mstr_ack =>
--master acknowledge bit after a read
IF(ena = '1') THEN
--continue transaction
busy <= '0';
--continue is accepted and data received is available on bus
addr_rw <= addr & rw;
--collect requested slave address and command
data_tx <= data_wr;
--collect requested data to write
IF(addr_rw = addr & rw) THEN --continue transaction with another read
sda_int <= '1';
--release sda from incoming data
state <= rd;
--go to read byte
ELSE
--continue transaction with a write or new slave
state <= start;
--repeated start
END IF;
ELSE
--complete transaction
state <= stop;
--go to stop bit
END IF;
WHEN stop =>
--stop bit of transaction
busy <= '0';
--unflag busy
state <= ready;
--go to idle state
END CASE;
ELSIF(data_clk = '0' AND data_clk_prev = '1') THEN --data clock falling edge
CASE state IS
WHEN start =>
IF(scl_ena = '0') THEN
--starting new transaction
scl_ena <= '1';
--enable scl output
ack_error <= '0';
--reset acknowledge error output
END IF;
WHEN slv_ack1 =>
--receiving slave acknowledge (command)
IF(sda /= '0' OR ack_error = '1') THEN --no-acknowledge or previous no-acknowledge
ack_error <= '1';
--set error output if no-acknowledge
END IF;
WHEN rd =>
--receiving slave data
data_rx(bit_cnt) <= sda;
--receive current slave data bit
WHEN slv_ack2 =>
--receiving slave acknowledge (write)
IF(sda /= '0' OR ack_error = '1') THEN --no-acknowledge or previous no-acknowledge
ack_error <= '1';
--set error output if no-acknowledge
END IF;
WHEN stop =>
scl_ena <= '0';
--disable scl
WHEN OTHERS =>
NULL;
END CASE;
END IF;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
28
END IF;
END PROCESS;
--set sda output
WITH state SELECT
sda_ena_n <= data_clk_prev WHEN start, --generate start condition
NOT data_clk_prev WHEN stop, --generate stop condition
sda_int WHEN OTHERS;
--set to internal sda signal
--set scl and sda outputs
scl <= '0' WHEN (scl_ena = '1' AND scl_clk = '0') ELSE 'Z';
sda <= '0' WHEN sda_ena_n = '0' ELSE 'Z';
end logic;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
29
Приложение Б - Тестирование Master на языке VHDL
-------------------------------------------------------------------------------- Company:
-- Engineer:
--- Create Date:
13:22:34 11/11/2019
-- Design Name:
-- Module Name:
F:/ISE/I2CMaster/Master_test_bench.vhd
-- Project Name: I2CMaster
-- Target Device:
-- Tool versions:
-- Description:
--- VHDL Test Bench Created by ISE for module: i2c_master
--- Dependencies:
--- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--- Notes:
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test. Xilinx recommends
-- that these types always be used for the top-level I/O of a design in order
-- to guarantee that the testbench will bind correctly to the postimplementation
-- simulation model.
------------------------------------------------------------------------------LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY Master_test_bench IS
END Master_test_bench;
ARCHITECTURE behavior OF Master_test_bench IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT i2c_master
PORT(
clk : IN std_logic;
reset_n : IN std_logic;
ena : IN std_logic;
addr : IN std_logic_vector(6 downto 0);
rw : IN std_logic;
data_wr : IN std_logic_vector(7 downto 0);
busy : OUT std_logic;
data_rd : OUT std_logic_vector(7 downto 0);
ack_error : BUFFER std_logic;
sda : INOUT std_logic;
scl : INOUT std_logic
);
END COMPONENT;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
30
--Inputs
signal clk : std_logic := '0';
signal reset_n : std_logic := '0';
signal ena : std_logic := '0';
signal addr : std_logic_vector(6 downto 0) := (others => '0');
signal rw : std_logic := '0';
signal data_wr : std_logic_vector(7 downto 0) := (others => '0');
--BiDirs
signal sda : std_logic;
signal scl : std_logic;
--Outputs
signal busy : std_logic;
signal data_rd : std_logic_vector(7 downto 0);
signal ack_error : std_logic;
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: i2c_master PORT MAP (
clk => clk,
reset_n => reset_n,
ena => ena,
addr => addr,
rw => rw,
data_wr => data_wr,
busy => busy,
data_rd => data_rd,
ack_error => ack_error,
sda => sda,
scl => scl
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
wait for 100 ns;
addr <= "1010101";
data_wr <= "10011001";
ena <= '1';
reset_n <= '1';
rw <= '0';
wait for clk_period*10000;
--wait for clk_period*2;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
31
--code
wait;
end process;
END;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
32
Приложение B - Реализация Slave на языке VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-----------------------------------------------------------entity I2C_minion is
generic (
MINION_ADDR
: std_logic_vector(6 downto 0);
-- noisy SCL/SDA lines can confuse the minion
-- use low-pass filter to smooth the signal
-- (this might not be necessary!)
USE_INPUT_DEBOUNCING
: boolean := false;
-- play with different number of wait cycles
-- larger wait cycles increase the resource usage
DEBOUNCING_WAIT_CYCLES : integer := 4);
port (
scl
: inout std_logic;
sda
: inout std_logic;
clk
: in
std_logic;
rst
: in
std_logic;
-- User interface
read_req
: out
std_logic;
data_to_master
: in
std_logic_vector(7 downto 0);
data_valid
: out
std_logic;
data_from_master : out
std_logic_vector(7 downto 0));
end entity I2C_minion;
-----------------------------------------------------------architecture arch of I2C_minion is
type state_t is (idle, get_address_and_cmd,
answer_ack_start, write,
read, read_ack_start,
read_ack_got_rising, read_stop);
-- I2C state management
signal state_reg
: state_t
:= idle;
signal cmd_reg
: std_logic
:= '0';
signal bits_processed_reg : integer range 0 to 8 := 0;
signal continue_reg
: std_logic
:= '0';
signal
signal
signal
signal
scl_reg
sda_reg
scl_debounced
sda_debounced
:
:
:
:
signal
signal
signal
signal
scl_pre_internal
scl_internal
sda_pre_internal
sda_internal
std_logic
std_logic
std_logic
std_logic
-- Helpers to figure out
signal start_reg
:
signal stop_reg
:
signal scl_rising_reg :
signal scl_falling_reg :
:
:
:
:
:=
:=
:=
:=
std_logic
std_logic
std_logic
std_logic
'Z';
'Z';
'Z';
'Z';
:=
:=
:=
:=
next state
std_logic :=
std_logic :=
std_logic :=
std_logic :=
'Z';
'1';
'Z';
'1';
'0';
'0';
'0';
'0';
-- Address and data received from master
signal addr_reg
: std_logic_vector(6 downto 0) := (others =>
'0');
signal data_reg
: std_logic_vector(6 downto 0) := (others =>
'0');
signal data_from_master_reg : std_logic_vector(7 downto 0) := (others =>
'0');
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
33
signal scl_prev_reg
-- Minion writes on
signal scl_wen_reg
signal scl_o_reg
signal sda_prev_reg
-- Minion writes on
signal sda_wen_reg
signal sda_o_reg
: std_logic
scl
: std_logic
: std_logic
: std_logic
sda
: std_logic
: std_logic
:= 'Z';
:= '0';
:= '0';
:= 'Z';
-- unused for now
:= '0';
:= '0';
-- User interface
signal data_valid_reg
: std_logic
signal read_req_reg
: std_logic
signal data_to_master_reg : std_logic_vector(7
'0');
begin
:= '0';
:= '0';
downto 0) := (others
=>
debounce : if USE_INPUT_DEBOUNCING generate
-- debounce SCL and SDA
SCL_debounce : entity work.debounce
generic map (
WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES)
port map (
clk
=> clk,
signal_in => scl,
signal_out => scl_debounced);
-- it might not make sense to debounce SDA, since master
-- and minion can both write to it...
SDA_debounce : entity work.debounce
generic map (
WAIT_CYCLES => DEBOUNCING_WAIT_CYCLES)
port map (
clk
=> clk,
signal_in => sda,
signal_out => sda_debounced);
scl_pre_internal
<= scl_debounced;
sda_pre_internal <= sda_debounced;
end generate debounce;
dont_debounce : if (not USE_INPUT_DEBOUNCING) generate
process (clk) is
begin
if rising_edge(clk) then
scl_pre_internal
<= scl;
sda_pre_internal <= sda;
end if;
end process;
end generate dont_debounce;
scl_internal <= '0' when scl_pre_internal = '0' else '1';
sda_internal <= '0' when sda_pre_internal = '0' else '1';
process (clk) is
begin
if rising_edge(clk) then
-- Delay SCL and SDA by 1 clock cycle
scl_prev_reg
<= scl_internal;
sda_prev_reg
<= sda_internal;
-- Detect rising and falling SCL
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
34
scl_rising_reg <= '0';
if scl_prev_reg = '0' and scl_internal = '1' then
scl_rising_reg <= '1';
end if;
scl_falling_reg <= '0';
if scl_prev_reg = '1' and scl_internal = '0' then
scl_falling_reg <= '1';
end if;
-- Detect I2C START condition
start_reg <= '0';
stop_reg <= '0';
if scl_internal = '1' and scl_prev_reg = '1' and
sda_prev_reg = '1' and sda_internal = '0' then
start_reg <= '1';
stop_reg <= '0';
end if;
-- Detect I2C STOP condition
if scl_prev_reg = '1' and scl_internal = '1' and
sda_prev_reg = '0' and sda_internal = '1' then
start_reg <= '0';
stop_reg <= '1';
end if;
end if;
end process;
----------------------------------------------------------- I2C state machine
---------------------------------------------------------process (clk) is
begin
if rising_edge(clk) then
-- Default assignments
sda_o_reg
<= '0';
sda_wen_reg
<= '0';
-- User interface
data_valid_reg <= '0';
read_req_reg
<= '0';
case state_reg is
when idle =>
if start_reg = '1' then
state_reg
<= get_address_and_cmd;
bits_processed_reg <= 0;
end if;
when get_address_and_cmd =>
if scl_rising_reg = '1' then
if bits_processed_reg < 7 then
bits_processed_reg
<= bits_processed_reg + 1;
addr_reg(6-bits_processed_reg) <= sda_internal;
elsif bits_processed_reg = 7 then
bits_processed_reg <= bits_processed_reg + 1;
cmd_reg
<= sda_internal;
end if;
end if;
if bits_processed_reg = 8 and scl_falling_reg = '1' then
bits_processed_reg <= 0;
if addr_reg = MINION_ADDR then -- check req address
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
35
state_reg <= answer_ack_start;
if cmd_reg = '1' then -- issue read request
read_req_reg
<= '1';
data_to_master_reg <= data_to_master;
end if;
else
assert false
report ("I2C: target/minion address mismatch (data is being
sent to another minion).")
severity note;
state_reg <= idle;
end if;
end if;
----------------------------------------------------- I2C acknowledge to master
---------------------------------------------------when answer_ack_start =>
sda_wen_reg <= '1';
sda_o_reg
<= '0';
if scl_falling_reg = '1' then
if cmd_reg = '0' then
state_reg <= write;
else
state_reg <= read;
end if;
end if;
----------------------------------------------------- WRITE
---------------------------------------------------when write =>
if scl_rising_reg = '1' then
bits_processed_reg <= bits_processed_reg + 1;
if bits_processed_reg < 7 then
data_reg(6-bits_processed_reg) <= sda_internal;
else
data_from_master_reg <= data_reg & sda_internal;
data_valid_reg
<= '1';
end if;
end if;
if scl_falling_reg = '1' and bits_processed_reg = 8 then
state_reg
<= answer_ack_start;
bits_processed_reg <= 0;
end if;
----------------------------------------------------- READ: send data to master
---------------------------------------------------when read =>
sda_wen_reg <= '1';
if data_to_master_reg(7-bits_processed_reg) = '0' then
sda_o_reg <= '0';
else
sda_o_reg <= 'Z';
end if;
if scl_falling_reg = '1' then
if bits_processed_reg < 7 then
bits_processed_reg <= bits_processed_reg + 1;
elsif bits_processed_reg = 7 then
state_reg
<= read_ack_start;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
36
bits_processed_reg <= 0;
end if;
end if;
----------------------------------------------------- I2C read master acknowledge
---------------------------------------------------when read_ack_start =>
if scl_rising_reg = '1' then
state_reg <= read_ack_got_rising;
if sda_internal = '1' then -- nack = stop read
continue_reg <= '0';
else -- ack = continue read
continue_reg
<= '1';
read_req_reg
<= '1'; -- request reg byte
data_to_master_reg <= data_to_master;
end if;
end if;
when read_ack_got_rising =>
if scl_falling_reg = '1' then
if continue_reg = '1' then
if cmd_reg = '0' then
state_reg <= write;
else
state_reg <= read;
end if;
else
state_reg <= read_stop;
end if;
end if;
-- Wait for START or STOP to get out of this state
when read_stop =>
null;
-- Wait for START or STOP to get out of this state
when others =>
assert false
report ("I2C: error: ended in an impossible state.")
severity error;
state_reg <= idle;
end case;
--------------------------------------------------------- Reset counter and state on start/stop
-------------------------------------------------------if start_reg = '1' then
state_reg
<= get_address_and_cmd;
bits_processed_reg <= 0;
end if;
if stop_reg = '1' then
state_reg
<= idle;
bits_processed_reg <= 0;
end if;
if rst = '1' then
state_reg <= idle;
end if;
end if;
end process;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
37
----------------------------------------------------------- I2C interface
---------------------------------------------------------sda <= sda_o_reg when sda_wen_reg = '1' else
'Z';
scl <= scl_o_reg when scl_wen_reg = '1' else
'Z';
----------------------------------------------------------- User interface
----------------------------------------------------------- Master writes
data_valid
<= data_valid_reg;
data_from_master <= data_from_master_reg;
-- Master reads
read_req
<= read_req_reg;
end architecture arch;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
38
Приложение Г - Тестирование Slave на языке VHDL
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use std.textio.all;
use work.txt_util.all;
-----------------------------------------------------------------------entity I2C_minion_TB_001_ideal is
end I2C_minion_TB_001_ideal;
-----------------------------------------------------------------------architecture Testbench of I2C_minion_TB_001_ideal is
constant T
: time
:= 20 ns;
-- clk period
constant TH_I2C
: time
:= 100 ns; -- i2c clk quarter period(kbis)
constant T_MUL
: integer := 2; -- i2c clk quarter period(kbis)
constant T_HALF
: integer := (TH_I2C*T_MUL*2) / T;
-- i2c halfclk
period
constant T_QUARTER : integer := (TH_I2C*T_MUL) / T;
-- i2c quarterclk
period
signal
signal
signal
signal
signal
signal
'0');
signal
signal
signal
'0');
signal
signal
'0');
signal
'0');
clk
rst
scl
sda
:
:
:
:
std_logic
std_logic
std_logic
std_logic
:=
:=
:=
:=
'1';
'1';
'Z';
'Z';
state_dbg
received_data
: integer
:= 0;
: std_logic_vector(7 downto 0) := (others =>
ack
read_req
data_to_master
: std_logic
:= '0';
: std_logic
:= '0';
: std_logic_vector(7 downto 0) := (others =>
data_valid
data_from_master
: std_logic
:= '0';
: std_logic_vector(7 downto 0) := (others =>
data_from_master_reg : std_logic_vector(7 downto 0) := (others =>
shared variable seed1 : positive := 1000;
shared variable seed2 : positive := 2000;
-- simulation control
shared variable ENDSIM : boolean := false;
begin
---- Design Under Verification ----------------------------------------DUV : entity work.I2C_minion
generic map (
MINION_ADDR
=> "0000011",
USE_INPUT_DEBOUNCING => false)
port map (
-- I2C
scl
=> scl,
sda
=> sda,
-- default signals
clk
=> clk,
rst
=> rst,
-- user interface
read_req
=> read_req,
data_to_master
=> data_to_master,
data_valid
=> data_valid,
data_from_master => data_from_master);
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
39
---- DUT clock running forever ---------------------------process
begin
if ENDSIM = false then
clk <= '0';
wait for T/2;
clk <= '1';
wait for T/2;
else
wait;
end if;
end process;
---- Reset asserted for T/2 -----------------------------rst <= '1', '0' after T/2;
----------------------------------------------------------- Save data received from the master in a register
---------------------------------------------------------process (clk) is
begin
if rising_edge(clk) then
if data_valid = '1' then
data_from_master_reg <= data_from_master;
end if;
end if;
end process;
----- Test vector generation ------------------------------------------TESTS : process is
-- half clock
procedure i2c_wait_half_clock is
begin
for i in 0 to T_HALF loop
wait until rising_edge(clk);
end loop;
end procedure i2c_wait_half_clock;
-- quarter clock
procedure i2c_wait_quarter_clock is
begin
for i in 0 to T_QUARTER loop
wait until rising_edge(clk);
end loop;
end procedure i2c_wait_quarter_clock;
-- Write Bit
procedure i2c_send_bit (
constant a_bit : in std_logic) is
begin
scl <= '0';
if a_bit = '0' then
sda <= '0';
else
sda <= 'Z';
end if;
i2c_wait_quarter_clock;
scl <= 'Z';
i2c_wait_half_clock;
scl <= '0';
i2c_wait_quarter_clock;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
40
end procedure i2c_send_bit;
-- Read Bit
procedure i2c_receive_bit (
variable a_bit : out std_logic) is
begin
scl
<= '0';
sda
<= 'Z';
i2c_wait_quarter_clock;
scl
<= 'Z';
i2c_wait_quarter_clock;
if sda = '0' then
a_bit := '0';
else
a_bit := '1';
end if;
i2c_wait_quarter_clock;
scl
<= '0';
i2c_wait_quarter_clock;
end procedure i2c_receive_bit;
-- Write Byte
procedure i2c_send_byte (
constant a_byte : in std_logic_vector(7 downto 0)) is
begin
for i in 7 downto 0 loop
i2c_send_bit(a_byte(i));
end loop;
end procedure i2c_send_byte;
-- Address
procedure i2c_send_address (
constant address : in std_logic_vector(6 downto 0)) is
begin
for i in 6 downto 0 loop
i2c_send_bit(address(i));
end loop;
end procedure i2c_send_address;
-- Read Byte
procedure i2c_receive_byte (
signal a_byte : out std_logic_vector(7 downto 0)) is
variable a_bit : std_logic;
variable accu : std_logic_vector(7 downto 0) := (others => '0');
begin
for i in 7 downto 0 loop
i2c_receive_bit(a_bit);
accu(i) := a_bit;
end loop;
a_byte <= accu;
end procedure i2c_receive_byte;
-- START
procedure i2c_start is
begin
scl <= 'Z';
sda <= '0';
i2c_wait_half_clock;
scl <= 'Z';
i2c_wait_quarter_clock;
scl <= '0';
i2c_wait_quarter_clock;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
41
end procedure i2c_start;
-- STOP
procedure i2c_stop is
begin
scl <= '0';
sda <= '0';
i2c_wait_quarter_clock;
scl <= 'Z';
i2c_wait_quarter_clock;
sda <= 'Z';
i2c_wait_half_clock;
i2c_wait_half_clock;
end procedure i2c_stop;
-- send write
procedure i2c_set_write is
begin
i2c_send_bit('0');
end procedure i2c_set_write;
-- send read
procedure i2c_set_read is
begin
i2c_send_bit('1');
end procedure i2c_set_read;
-- read ACK
procedure i2c_read_ack (signal ack : out std_logic) is
begin
scl <= '0';
sda <= 'Z';
i2c_wait_quarter_clock;
scl <= 'Z';
if sda = '0' then
ack <= '1';
else
ack <= '0';
assert false report "No ACK received: expected '0'" severity note;
end if;
i2c_wait_half_clock;
scl <= '0';
i2c_wait_quarter_clock;
end procedure i2c_read_ack;
-- write NACK
procedure i2c_write_nack is
begin
scl <= '0';
sda <= 'Z';
i2c_wait_quarter_clock;
scl <= 'Z';
i2c_wait_half_clock;
scl <= '0';
i2c_wait_quarter_clock;
end procedure i2c_write_nack;
-- write ACK
procedure i2c_write_ack is
begin
scl <= '0';
sda <= '0';
i2c_wait_quarter_clock;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
42
scl <= 'Z';
i2c_wait_half_clock;
scl <= '0';
i2c_wait_quarter_clock;
end procedure i2c_write_ack;
-- write to I2C bus
procedure i2c_write (
constant address : in std_logic_vector(6 downto 0);
constant data
: in std_logic_vector(7 downto 0)) is
begin
state_dbg <= 0;
i2c_start;
state_dbg <= 1;
i2c_send_address(address);
state_dbg <= 2;
i2c_set_write;
state_dbg <= 3;
-- dummy read ACK--don't care, because we are testing
-- I2C minion
i2c_read_ack(ack);
if ack = '0' then
state_dbg <= 6;
i2c_stop;
ack
<= '0';
return;
end if;
state_dbg <= 4;
i2c_send_byte(data);
state_dbg <= 5;
i2c_read_ack(ack);
state_dbg <= 6;
i2c_stop;
end procedure i2c_write;
-- write to I2C bus
procedure i2c_quick_write (
constant address : in std_logic_vector(6 downto 0);
constant data
: in std_logic_vector(7 downto 0)) is
begin
state_dbg <= 0;
i2c_start;
state_dbg <= 1;
i2c_send_address(address);
state_dbg <= 2;
i2c_set_write;
state_dbg <= 3;
-- dummy read ACK--don't care, because we are testing
-- I2C minion
i2c_read_ack(ack);
if ack = '0' then
state_dbg <= 6;
i2c_stop;
ack
<= '0';
return;
end if;
state_dbg <= 4;
i2c_send_byte(data);
state_dbg <= 5;
i2c_read_ack(ack);
scl
<= '0';
sda
<= '0';
i2c_wait_quarter_clock;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
43
scl
<= 'Z';
sda
<= 'Z';
i2c_wait_quarter_clock;
end procedure i2c_quick_write;
-- read I2C bus
procedure i2c_write_bytes (
constant address
: in std_logic_vector(6 downto 0);
constant nof_bytes : in integer range 0 to 1023) is
variable data : std_logic_vector(7 downto 0) := (others => '0');
begin
state_dbg <= 0;
i2c_start;
state_dbg <= 1;
i2c_send_address(address);
state_dbg <= 2;
i2c_set_write;
state_dbg <= 3;
i2c_read_ack(ack);
if ack = '0' then
i2c_stop;
return;
end if;
ack <= '0';
for i in 0 to nof_bytes-1 loop
state_dbg <= 4;
i2c_send_byte(std_logic_vector(to_unsigned(i, 8)));
state_dbg <= 5;
i2c_read_ack(ack);
if ack = '0' then
i2c_stop;
return;
end if;
ack <= '0';
end loop;
state_dbg <= 6;
i2c_stop;
end procedure i2c_write_bytes;
-- read from I2C bus
procedure i2c_read (
constant address : in std_logic_vector(6 downto 0);
signal data
: out std_logic_vector(7 downto 0)) is
begin
state_dbg <= 0;
i2c_start;
state_dbg <= 1;
i2c_send_address(address);
state_dbg <= 2;
i2c_set_read;
state_dbg <= 3;
-- dummy read ACK--don't care, because we are testing
-- I2C minion
i2c_read_ack(ack);
if ack = '0' then
state_dbg <= 6;
i2c_stop;
return;
end if;
ack
<= '0';
state_dbg <= 4;
i2c_receive_byte(data);
state_dbg <= 5;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
44
i2c_write_nack;
state_dbg <= 6;
i2c_stop;
end procedure i2c_read;
-- read from I2C bus
procedure i2c_quick_read (
constant address : in std_logic_vector(6 downto 0);
signal data
: out std_logic_vector(7 downto 0)) is
begin
state_dbg <= 0;
i2c_start;
state_dbg <= 1;
i2c_send_address(address);
state_dbg <= 2;
i2c_set_read;
state_dbg <= 3;
-- dummy read ACK--don't care, because we are testing
-- I2C minion
i2c_read_ack(ack);
if ack = '0' then
state_dbg <= 6;
i2c_stop;
return;
end if;
ack
<= '0';
state_dbg <= 4;
i2c_receive_byte(data);
state_dbg <= 5;
i2c_write_nack;
scl
<= '0';
sda
<= '0';
i2c_wait_quarter_clock;
scl
<= 'Z';
sda
<= 'Z';
i2c_wait_quarter_clock;
end procedure i2c_quick_read;
-- read I2C bus
procedure i2c_read_bytes (
constant address
: in std_logic_vector(6
constant nof_bytes : in integer range 0 to
signal data
: out std_logic_vector(7
begin
state_dbg <= 0;
i2c_start;
state_dbg <= 1;
i2c_send_address(address);
state_dbg <= 2;
i2c_set_read;
state_dbg <= 3;
i2c_read_ack(ack);
if ack = '0' then
state_dbg <= 6;
i2c_stop;
return;
end if;
for i in 0 to nof_bytes-1 loop
-- dummy read ACK--don't care, because we
-- I2C minion
state_dbg <= 4;
i2c_receive_byte(data);
downto 0);
1023;
downto 0)) is
are testing
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
45
state_dbg <= 5;
if i < nof_bytes-1 then
i2c_write_ack;
else
i2c_write_nack;
end if;
end loop;
state_dbg <= 6;
i2c_stop;
end procedure i2c_read_bytes;
begin
print("");
print("------------------------------------------------------------");
print("----------------- I2C_minion_TB_001_ideal ------------------");
print("------------------------------------------------------------");
scl <= 'Z';
sda <= 'Z';
print("----------------- Testing a single write ------------------");
i2c_write("0000011", "11111111");
assert data_from_master_reg = "11111111"
report "test: 0 not passed"
severity warning;
print("----------------- Testing a single write ------------------");
i2c_write("0000011", "11111010");
assert data_from_master_reg = "11111010"
report "test: 0 not passed"
severity warning;
print("----------------- Testing repeated writes -----------------");
wait until rising_edge(clk);
for i in 0 to 127 loop
i2c_write("0000011", std_logic_vector(to_unsigned(i, 8)));
assert i = to_integer(unsigned(data_from_master_reg))
report "writing test: " & integer'image(i) & " not passed"
severity warning;
end loop;
print("----------------- Testing repeated reads ------------------");
for i in 0 to 127 loop
data_to_master <= std_logic_vector(to_unsigned(i, 8));
i2c_read("0000011", received_data);
assert i = to_integer(unsigned(received_data))
report "reading test: " & integer'image(i) & " not passed" & "test"
severity warning;
end loop;
--------------------------------------------------------- Quick read/write
-------------------------------------------------------print("----------------- Testing quick write --------------------");
i2c_quick_write("0000011", "10101010");
i2c_quick_write("0000011", "10101011");
i2c_quick_write("0000011", "10101111");
data_to_master <= std_logic_vector(to_unsigned(255, 8));
i2c_quick_read("0000011", received_data);
state_dbg
<= 6;
i2c_stop;
--------------------------------------------------------
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
46
-- Reads, writes from wrong minion addresses
-- this should cause some assertion notes (needs manual
-- confirmation)
-------------------------------------------------------print("----------------- Testing wrong addresses -----------------");
print("-> The following 3 tests should all fail");
print("[0] ---------------");
i2c_write_bytes("1000011", 100);
print("[1] ---------------");
i2c_read ("0101101", received_data);
print("[2] ---------------");
i2c_read_bytes ("0000010", 300, received_data);
wait until rising_edge(clk);
ENDSIM := true;
print("Simulation end...");
print("");
wait;
end process;
end Testbench;
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
47
Приложение Г - Тестирование Master - Slave на языке C
#include <Wire.h>
void setup()
{
Wire.begin();
// join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
while (!Serial.dtr()) {}
Serial.print("program begins");
Serial.println();
}
void loop()
{
byte c;
byte i;
i = 0;
while (true) {
Wire.beginTransmission(3);
Wire.write(i);
Wire.endTransmission();
delay(1);
Wire.requestFrom(3, 1);
// request 6 bytes from slave device #2
while(!Wire.available()) {}
c = Wire.read(); // receive a byte as character
Serial.print("Write: ");
Serial.print(i);
// print the characterc
Serial.print("; Read: ");
Serial.print(c);
// print the characterc
Serial.println();
i = i + 1;
if (i == 255) {
Serial.print("Press any key to repeat");
Serial.println();
while (!Serial.available()) {}
while (Serial.available())
Serial.read();
break;
}
delay(1);
}
}
Разработка безопасного микропроцессорного устройства
Изм. Лист
№ докум.
Подпись Дата
Лист
48
Download