Синхронный системный интерфейс взаимодействия с периферийными блоками в объёме кристалла СБИС или ПЛИС. STI 1.0

в 9:16, , рубрики: asic, fpga, gpio, RTL, STI 1.0, внутренняя шина, интерфейс, интерфейсы, периферийный блок, ПЛИС, регистровый файл, системная шина, шина STI

В статье предложена организация взаимодействия функциональных блоков в объёме кристалла СБИС, а именно: процессорных ядер, контроллеров DMA и мостов системных шин с периферийными блоками, такими как: контроллеры GPIO, SPI, I2C, UART, таймеры и широтно-импульсные модуляторы – ШИМ. Рассмотрен набор сигналов и протокол обмена стыка простого исполнителя – локального системного интерфейса, реализующего взаимодействие перечисленных блоков кристалла. Приведены примеры синтезируемых моделей контроллера GPIO и регистрового файла, поддерживающие описанный интерфейс.

С момента освоения полупроводниковой промышленностью технологических процессов с нормами 0,18мкм и менее, позволивших достичь степени интеграции микросхем уровня «Система на Кристалле», появилось множество спецификаций на внутренние стыки функциональных блоков, реализуемых в таких микросхемах. В большинстве случаев эти стыки представлены синхронными системными шинами, такими как: AMBA APB, AHB, AXI, Wishbone, OCP [1, 2, 3, 4, 5, 6]. Предлагались также и оригинальные топологии, не имеющие ничего общего с шиной, например накристальные сети – NOC (Networks-On-Chip) [7].

Предметная область данной публикации ограничена построением связей функциональных блоков вычислительного устройства, не выходя за пределы кристалла СБИС или ПЛИС. Особенностью таких связей является отсутствие существенного ограничения числа сигнальных линий, задействованных в протоколе обмена. Эта особенность обусловлена тем, что в объёме кристалла введение дополнительного сигнала зачастую существенно упрощает логические схемы, занимающие транзисторные ресурсы, в то время как трассировочные ресурсы не являются настолько дефицитными. Также следует отметить, что некоторые сигналы, явно описанные в модели RTL-уровня, могут отсутствовать в синтезированной схеме и перечне связей на уровне технологических элементов вследствие оптимизации комбинационной логики.

Большинство существующих спецификаций внутрикристальных системных шин использует сложные протоколы, определяющие задержанные транзакции (Delayed Transactions), блочные передачи (Burst mode), чтение с предвыборкой (Prefetchable Read), остановы транзакций (Abort) и запросы повтора (Retry). Этот функционал требует поддержки со стороны всех агентов шины и приводит к значительному усложнению алгоритмов переключения управляющих автоматов, хотя во многих случаях не используется. В частности, он избыточен при организации доступа к медленным или простым периферийным блокам кристалла.

В некоторых спецификациях, например для шины Wishbone [5], не регламентирован принцип соединения агентов между собой, а определены только интерфейсы инициатора (Initiator) и исполнителя (Target).

Главное преимущество существующих интерфейсов заключается в широком ассортименте разработанных и верифицированных функциональных блоков (IP-ядер).

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

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

Стык простого исполнителя версии 1.0 – Simple Target Interface v.1.0 (далее – STI) представляет собой набор логических сигналов и протокол взаимодействия, обеспечивающий соединение нескольких функциональных блоков в объёме одного проекта конфигурации ПЛИС или кристалла СБИС (далее — проекта).

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

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

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

Способ взаимодействия по STI заключается в записи и чтении слов данных, доступных по определённым адресам в одном из адресных пространств процессора вычислительного устройства. Ширина слов определяется разрядностью трактов данных в выбранной для определённого сегмента STI реализации интерфейса и может составлять 8, 16, 32 или 64 бита.

Запись или чтение одного слова данных представляет собой цикл обмена по интерфейсу STI (далее – цикл).

Любой обмен данными по STI начинается единственным в сегменте блоком-инициатором обмена (далее – инициатор). Блоков-исполнителей обмена (далее – исполнителей), подключённых к общему сегменту STI может быть несколько. Максимальное количество исполнителей зависит от реализации проекта СБИС разработчиком, и не регламентировано данным протоколом. Тем не менее, по причинам оптимизации быстродействия, не рекомендуется подключать к одному сегменту STI более восьми исполнителей. При наличии на сегменте STI двух и более исполнителей коммутация данных в тракте чтения и переключение управляющих сигналов осуществляются связующими комбинационными схемами. Коммутация нескольких исполнителей производится на основании выбранного адресного пространства (команды STI), либо выбранного диапазона адресов в объёме общего адресного пространства.

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

Выбор адресного пространства закодирован в команде STI (S_CMD). Адрес в объёме выбранного адресного пространства передаётся от инициатора к исполнителю во всех циклах по тракту адреса (S_ADDR).

Ширина тракта адреса зависит от реализации проекта разработчиком, и не регламентирована данным протоколом. В некоторых функциональных блоках тракт адреса на стыке STI может отсутствовать, при условии доступа к исполнителю, использующему одну комбинацию из адресного пространства системы (один регистр для записи и/или один регистр для чтения).
Место интерфейса STI на примере кристалла СБИС класса «система на кристалле» (СнК) иллюстрирует структурная схема, приведённая на рис. 1. Связи, относящиеся к сегменту STI, выделены серой заливкой.

image
Рис. 1. Место интерфейса STI в объёме кристалла СБИС

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

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

Рассмотрим топологию связи агентов в объёме сегмента STI.

Взаимодействие по сегменту STI использует набор сигналов, приведённый в таблице 1.

Таблица 1.

8-р. тракты данных 16-р. тракты данных 32-р. тракты данных 64-р. тракты данных Инициатор Исполнитель
S_EX_REQ S_EX_REQ S_EX_REQ S_EX_REQ Выход запроса Вход запроса
S_ADDR[n-1:0] / S_ADDR_0 S_ADDR[n-1:1] / S_ADDR_1 S_ADDR[n-1:2] / S_ADDR_2 S_ADDR[n-1:3] / S_ADDR_3 Выход адреса Вход адреса
нет S_NBE[1:0] S_NBE[3:0] S_NBE[7:0] Выход разрешения байтов Вход разрешения байтов
S_CMD[2:0] S_CMD[2:0] S_CMD[2:0] S_CMD[2:0] Выход кода команды Вход кода команды
S_D_WR[7:0] S_D_WR[15:0] S_D_WR[31:0] S_D_WR[63:0] Выход данных для записи Вход данных для записи
S_EX_ACK S_EX_ACK S_EX_ACK S_EX_ACK Вход подтверждения Выход подтверждения
S_D_RD[7:0] S_D_RD[15:0] S_D_RD[31:0] S_D_RD[63:0] Вход данных чтения Выход данных чтения
CLK CLK CLK CLK Вход синхросигнала Вход синхросигнала
RST RST RST RST Вход системного сброса Вход системного сброса

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

Топология соединений логических сигналов в объёме одного сегмента STI показана на рис. 2. В рассматриваемом примере представлена коммутация двух исполнителей, а также организация входов и выходов исполнителей и инициатора. Коммутация исполнителей выполнена путём разделения адресных пространств на две равные части. Таким образом, при низком уровне старшего разряда адреса S_ADDR[n-1] выбирается исполнитель Target-A, а при высоком уровне – Target-B. В логику выбора исполнителей может быть также включён код команды для разделения не только по адресным комбинациям, но и по адресным пространствам.

image
Рис. 2. Топология соединений в сегменте STI

На топологию интерфейса инициатора стыка STI накладываются следующие ограничения:

  1. Выход адреса S_ADDR должен иметь источник в виде выхода регистра, синхронизируемого сигналом CLK. Таким образом, задержка по выходу S_ADDR от рабочего фронта синхросигнала равна выходной задержке триггера T-co (Clock-to-Output delay).
  2. Остальные выходные сигналы инициатора могут генерироваться комбинационными цепями, не реагирующими на входные сигналы S_EX_ACK и S_D_RD, либо регистрами.

На топологию интерфейса исполнителя стыка STI накладываются следующие ограничения:

  1. Выход подтверждения цикла S_EX_ACK должен иметь источник в виде выхода регистра, синхронизируемого сигналом CLK. Таким образом, задержка по выходу S_EX_ACK от рабочего фронта синхросигнала равна выходной задержке триггера T-co (Clock-to-Output delay). Для исполнителей, не вносящих такты ожидания в циклы обмена записи и циклы обмена чтения, допустимо формировать сигнал S_EX_ACK в виде константы высокого уровня.
  2. В отсутствие выходного регистра на шине S_D_RD управление мультиплексором в тракте чтения данных должно осуществляться либо выходом внутреннего регистра (синхронизируемого сигналом CLK) в объёме исполнителя, либо подмножеством входных разрядов шины адреса S_ADDR[n-1:k].

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

Связующие комбинационные схемы, обеспечивающие коммутацию нескольких исполнителей в рамках одного сегмента STI, представлены логическими вентилями «И» на цепях запроса S_EX_REQ а также мультиплексорами выходов исполнителей на общие входы инициатора. Пример построения связующей логики показан на рис. 2.

В синтезированной модели проекта определённые логические сигналы отдельно взятого сегмента STI могут отсутствовать в силу оптимизации комбинационной логики и переноса регистров через логические цепи. Результаты синтеза также зависят от пользовательских настроек, заданных в используемых разработчиком средствах проектирования (САПР).

Рассмотрим протокол взаимодействия агентов одного сегмента STI.

Все логические сигналы интерфейса STI кроме системных линий синхронизации CLK и начальной установки (сброса) RST должны удовлетворять требованиям синхронности относительно рабочего фронта синхросигнала CLK. Данным протоколом рабочий фронт полагается восходящим, при котором низкий уровень сменяется высоким.

Сигнал S_NBE переносит информацию об активных байтах, записываемых или считываемых в текущем цикле. Для 8-разрядного интерфейса STI данный сигнал не используется, ибо во всех циклах передаётся не более одного байта, который не может быть недействительным. Недействительному байту на 8-разрядном сегменте STI соответствует отсутствие цикла.
В 16-разрядном интерфейсе STI сигнал S_NBE имеет разрядность два бита. Низкий уровень S_NBE[0] сигнализирует о действительности данных в разрядах S_D_WR[7:0] или S_D_RD[7:0]. Низкий уровень S_NBE[1] сигнализирует о наличии действительных данных в разрядах S_D_WR[15:8] или S_D_RD[15:8]. Высокий уровень S_NBE[x] указывает на отсутствие данных в соответствующих разрядах. Таким образом, эти байты не должны быть записаны либо считаться считанными.

В 32-разрядном интерфейсе STI сигнал S_NBE имеет разрядность 4 бита. Два дополнительных разряда S_NBE[3:2] контролируют старшую половину шины данных. Низкий уровень S_NBE[2] сигнализирует о действительности данных в разрядах S_D_WR[23:16] или S_D_RD[23:16]. Низкий уровень S_NBE[3] сигнализирует о наличии действительных данных в разрядах S_D_WR[31:24] или S_D_RD[31:24]. Аналогичным способом биты S_NBE[7:4] управляют старшими байтами 64-разрядного интерфейса, причём бит-4 управляет байтом [39:32], бит-5 – байтом [47:40], бит-6 – байтом [55:48], а бит-7 – старшим байтом [63:56].

По линиям S_CMD[2:0] передаются команды, определяющие тип текущего цикла обмена. Команды STI перечислены в таблице 2.

Таблица 2.

S_CMD[2] S_CMD[1] S_CMD[0] Тип цикла
0 0 0 IO Write – Запись IO с ожиданием готовности конечного исполнителя (приёмника данных)
0 0 1 Memory Write – Запись в память с ожиданием готовности конечного исполнителя (приёмника данных)
0 1 0 Posted IO Write – Отложенная запись IO
0 1 1 Posted Memory Write – Отложенная запись в память
1 0 0 IO Read – Чтение IO (без предвыборки данных)
1 0 1 Memory Read – Чтение памяти (без предвыборки данных)
1 1 X Programm Memory Read – Чтение памяти программ (без предвыборки данных)

Интерфейс STI поддерживает три типа адресных пространств:

  1. Пространство портов ввода-вывода IO Space.
  2. Пространство памяти (или памяти данных) Memory Space.
  3. Пространство памяти программ (для архитектур процессоров с раздельной памятью программ и данных) Programm Memory Space.

Шина S_ADDR переносит адресную комбинацию любого из адресных пространств. В 8-разрядной версии STI младший разряд адреса имеет обозначение S_ADDR[0], в 16-разрядной – обозначается S_ADDR[1], в 32-разрядной версии младшим разрядом адреса является S_ADDR[2], а в 64-разрядной версии – S_ADDR[3]. Это обусловлено тем, что минимальной адресуемой величиной данных на стыке STI является байт, а в 16, 32 и 64-разрядных версиях младшие биты адреса S_ADDR[0], S_ADDR[1:0] и S_ADDR[2:0], соответственно, замещаются позиционным кодом выборки байтов: S_NBE[1:0], S_NBE[3:0] и S_NBE[7:0].

Шина S_D_WR переносит слова данных для записи и представляет собой тракт записи.

Шина S_D_RD переносит считанные слова данных и представляет собой тракт чтения.

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

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

Цикл обмена по стыку STI считается завершённым после фиксации по рабочему фронту синхросигнала факта одновременного наличия высокого уровня на линиях S_EX_REQ и S_EX_ACK.
Временная диаграмма, поясняющая цикл записи, показана на рис. 3.

image
Рис. 3. Пример временной диаграммы записи

Временная диаграмма, поясняющая цикл чтения, показана на рис. 4.

image
Рис. 4. Пример временной диаграммы чтения

Порядок изменения состояния сигналов по стыку STI регламентирован следующим набором правил.

Правило Ин-1.

Инициатор должен обеспечивать действительные значения сигналов S_ADDR, S_NBE, S_CMD во всех тактах, в которых активен запрос цикла (высокий уровень сигнала S_EX_REQ).

Правило Ин-2.

Инициатор должен обеспечивать действительные значения сигнала S_D_WR во всех тактах, в которых активен запрос цикла (высокий уровень сигнала S_EX_REQ) и на линиях S_CMD установлена комбинация любой команды записи.

Правило Ин-3.

Инициатор может изменять состояния сигналов S_ADDR, S_NBE, S_CMD, S_D_WR только в течение следующего такта после одновременной фиксации (по рабочему фронту синхросигнала) высокого уровня сигналов S_EX_REQ и S_EX_ACK а также при низком уровне сигнала S_EX_REQ.

Правило Ин-4.

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

Правило Исп-1.

Исполнитель должен обеспечивать действительные считанные значения данных на линиях S_D_RD при высоком уровне сигнала подтверждения цикла S_EX_ACK и наличии на линиях S_CMD комбинации любой команды чтения. (Исполнитель, выдающий высокий уровень сигнала подтверждения цикла S_EX_ACK с опережением, не дожидаясь высокого уровня сигнала запроса S_EX_REQ, должен обеспечить возможность чтения данных при смене входных комбинаций в течение одного такта до момента прихода ближайшего рабочего фронта синхросигнала.)

Правило Исп-2.

Исполнитель должен принимать и сохранять по рабочему фронту синхросигнала данные для записи с линий S_D_WR при высоком уровне сигнала подтверждения цикла S_EX_ACK, наличии высокого уровня на входе S_EX_REQ и наличии на линиях S_CMD комбинации любой команды записи. (Исполнитель, выдающий высокий уровень сигнала подтверждения цикла S_EX_ACK с опережением, не дожидаясь высокого уровня сигнала запроса S_EX_REQ, должен обеспечить возможность записи данных при смене входных комбинаций в течение одного такта до момента прихода ближайшего рабочего фронта синхросигнала.)

Правило Исп-3.

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

Правило Исп-4.

Исполнитель может изменять состояние сигналов на линиях S_D_RD только при одном из перечисленных условий:

  • после одновременной фиксации (по рабочему фронту синхросигнала) высокого уровня сигналов S_EX_REQ и S_EX_ACK,
  • непосредственно после смены состояния адреса S_ADDR, разрешения байтов S_NBE или кода команды S_CMD до момента прихода ближайшего рабочего фронта синхросигнала,
  • в тактах с низким уровнем сигнала S_EX_ACK,
  • одновременно (в одном такте) с установкой высокого уровня на выходе S_EX_ACK,
  • в тактах, с комбинациями кодов команд S_CMD, не соответствующих циклам чтения.

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

Исполнители со стыком STI, удовлетворяющие всем перечисленным выше правилам, могут быть основаны на простых схемных решениях, реализуемых в любой современной элементной базе.
Наиболее простым примером организации исполнителя STI может служить блок расширения ввода-вывода, реализующий дискретные входы-выходы общего назначения – GPIO (General Purpose Input-Output). Схема такого функционального блока показана на рис. 5.

image
Рис. 5. Функциональная схема блока расширения ввода-вывода

Данный блок позволяет побитно настроить 32 канала на ввод или на вывод логических сигналов. Для данных предусмотрены два 32-битных регистра: RG_O[31:0] и RG_I[31:0]. Для управления предназначен регистр RG_T[31:0], доступный для чтения и записи по базовому адресу (S_ADDR_2 = 0). Регистр RG_I[31:0] доступен для записи по адресу со смещением +1 (S_ADDR_2 = 1), регистр RG_O[31:0] доступен для чтения по адресу со смещением +1 (S_ADDR_2 = 1).
Запись в регистры осуществляется побайтно с учётом комбинации разрешения байтов S_NBE[3:0].
Ниже приведена синтезируемая модель рассмотренного блока расширения ввода-вывода, описанная на языке Verilog:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////
// Engineer:       FPGA-Mechanic
//
// Create Date:    11:12:38 07/24/2014
// Design Name:    STI Design
// Module Name:    MSTI_32b_GPIO_REG_V10 - 32-bit STI GPIO Expander
// Project Name:   Any
// Target Devices: FPGA
// Tool versions:  Xilinx DS 14.4
//
// Revision:       1.0 (24.07.2014)
// Revision        1.0 - File Created
//////////////////////////////////////////////////////////////////////////
module MSTI_32b_GPIO_REG_V10(
    input         CLK,
    input         RST,
    input         S_EX_REQ,
    input         S_ADDR_2,
    input  [3:0]  S_NBE,
    input  [2:0]  S_CMD,
    input  [31:0] S_D_WR,
    output        S_EX_ACK,
    output [31:0] S_D_RD,
    output [31:0] GP_O,
    output [31:0] GP_T,
    input  [31:0] GP_I
    );

// Internal signals declaration:
 wire IO_WR_CMD;
 reg  [31:0] RG_T, RG_O, RG_I;
//------------------------------------------
 assign IO_WR_CMD = ~S_CMD[0] & ~S_CMD[2] & S_EX_REQ;
//------------------------------------------
// Internal Data Registers:
 always @ (posedge CLK, posedge RST)
  if(RST)
   begin
    RG_T <= 32'hFFFFFFFF; // All Outputs Tri-Stated
    RG_O <= 32'h00000000;
    RG_I <= 32'h00000000;
   end
  else
   begin
    RG_I <= GP_I;
    if(~S_NBE[0] & ~S_ADDR_2 & IO_WR_CMD) RG_T[7:0]   <= S_D_WR[7:0];
    if(~S_NBE[1] & ~S_ADDR_2 & IO_WR_CMD) RG_T[15:8]  <= S_D_WR[15:8];
    if(~S_NBE[2] & ~S_ADDR_2 & IO_WR_CMD) RG_T[23:16] <= S_D_WR[23:16];
    if(~S_NBE[3] & ~S_ADDR_2 & IO_WR_CMD) RG_T[31:24] <= S_D_WR[31:24];
    if(~S_NBE[0] &  S_ADDR_2 & IO_WR_CMD) RG_O[7:0]   <= S_D_WR[7:0];
    if(~S_NBE[1] &  S_ADDR_2 & IO_WR_CMD) RG_O[15:8]  <= S_D_WR[15:8];
    if(~S_NBE[2] &  S_ADDR_2 & IO_WR_CMD) RG_O[23:16] <= S_D_WR[23:16];
    if(~S_NBE[3] &  S_ADDR_2 & IO_WR_CMD) RG_O[31:24] <= S_D_WR[31:24];
   end
//------------------------------------------
 assign S_EX_ACK = 1'b1;
//------------------------------------------
 assign GP_T = RG_T;
 assign GP_O = RG_O;
//------------------------------------------
 assign S_D_RD = S_ADDR_2 ? RG_I : RG_T;
//------------------------------------------
endmodule

Другой пример исполнителя представлен регистровым файлом ёмкостью 16 регистров с разрядностью 8 бит. Функциональная схема регистрового файла показана на рис. 6.
Каждый из шестнадцати регистров доступен для записи и чтения по стыку STI и имеет индивидуальный выходной сигнал RG_xQ[7:0], используемый на верхнем уровне иерархии проекта.

Функционально регистровый файл аналогичен четырём одноразрядным блокам распределённой памяти на основе табличных преобразователей LUT-4 архитектуры ПЛИС FPGA (например — примитивам RAM16X1D в библиотеке ПЛИС фирмы Xilinx).

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

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

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////
// Engineer:       FPGA-Mechanic
//
// Create Date:    11:40:08 07/24/2014
// Design Name:    STI Design
// Module Name:    MSTI_8b_16xREG_V10 - 16x8bit Register File 
//                                      in STI Memory Space
// Project Name:   Any
// Target Devices: FPGA
// Tool versions:  Xilinx DS 14.4
//
// Revision:       1.0 (24.07.2014)
// Revision 1.0 - File Created
//////////////////////////////////////////////////////////////////////////
module MSTI_8b_16xREG_V10(
    input         CLK,
    input         RST,
    input         S_EX_REQ,
    input  [3:0]  S_ADDR,
    //input  [1:0]  S_NBE,
    input  [2:0]  S_CMD,
    input  [7:0]  S_D_WR,
    output        S_EX_ACK,
    output reg
           [7:0]  S_D_RD,
    output [7:0]  RG_0Q,
    output [7:0]  RG_1Q,
    output [7:0]  RG_2Q,
    output [7:0]  RG_3Q,
    output [7:0]  RG_4Q,
    output [7:0]  RG_5Q,
    output [7:0]  RG_6Q,
    output [7:0]  RG_7Q,
    output [7:0]  RG_8Q,
    output [7:0]  RG_9Q,
    output [7:0]  RG_AQ,
    output [7:0]  RG_BQ,
    output [7:0]  RG_CQ,
    output [7:0]  RG_DQ,
    output [7:0]  RG_EQ,
    output [7:0]  RG_FQ
    );

// Internal signals declaration:
 wire M_WR_CMD;
 reg  [7:0] RG_0I, RG_1I, RG_2I, RG_3I, RG_4I, RG_5I, RG_6I, RG_7I;
 reg  [7:0] RG_8I, RG_9I, RG_AI, RG_BI, RG_CI, RG_DI, RG_EI, RG_FI;
//------------------------------------------
 assign M_WR_CMD = ~S_CMD[2] & S_CMD[0] & S_EX_REQ;
//------------------------------------------
// Internal Data Registers:
 always @ (posedge CLK, posedge RST)
  if(RST)
   begin
    RG_0I <= 8'h00; RG_1I <= 8'h00;
    RG_2I <= 8'h00; RG_3I <= 8'h00;
    RG_4I <= 8'h00; RG_5I <= 8'h00;
    RG_6I <= 8'h00; RG_7I <= 8'h00;
    RG_8I <= 8'h00; RG_9I <= 8'h00;
    RG_AI <= 8'h00; RG_BI <= 8'h00;
    RG_CI <= 8'h00; RG_DI <= 8'h00;
    RG_EI <= 8'h00; RG_FI <= 8'h00;
   end
  else
   begin
    if(M_WR_CMD)
    case(S_ADDR)
     4'h0 : RG_0I <= S_D_WR;
     4'h1 : RG_1I <= S_D_WR;
     4'h2 : RG_2I <= S_D_WR;
     4'h3 : RG_3I <= S_D_WR;
     4'h4 : RG_4I <= S_D_WR;
     4'h5 : RG_5I <= S_D_WR;
     4'h6 : RG_6I <= S_D_WR;
     4'h7 : RG_7I <= S_D_WR;
     4'h8 : RG_8I <= S_D_WR;
     4'h9 : RG_9I <= S_D_WR;
     4'hA : RG_AI <= S_D_WR;
     4'hB : RG_BI <= S_D_WR;
     4'hC : RG_CI <= S_D_WR;
     4'hD : RG_DI <= S_D_WR;
     4'hE : RG_EI <= S_D_WR;
     default: RG_FI <= S_D_WR;
    endcase
   end
//------------------------------------------
// Output MUX:
 always @ (S_ADDR,
           RG_0I, RG_1I, RG_2I, RG_3I, RG_4I, RG_5I, RG_6I, RG_7I,
           RG_8I, RG_9I, RG_AI, RG_BI, RG_CI, RG_DI, RG_EI, RG_FI)
  case(S_ADDR)
   4'h0 : S_D_RD <= RG_0I;
   4'h1 : S_D_RD <= RG_1I;
   4'h2 : S_D_RD <= RG_2I;
   4'h3 : S_D_RD <= RG_3I;
   4'h4 : S_D_RD <= RG_4I;
   4'h5 : S_D_RD <= RG_5I;
   4'h6 : S_D_RD <= RG_6I;
   4'h7 : S_D_RD <= RG_7I;
   4'h8 : S_D_RD <= RG_8I;
   4'h9 : S_D_RD <= RG_9I;
   4'hA : S_D_RD <= RG_AI;
   4'hB : S_D_RD <= RG_BI;
   4'hC : S_D_RD <= RG_CI;
   4'hD : S_D_RD <= RG_DI;
   4'hE : S_D_RD <= RG_EI;
   default: S_D_RD <= RG_FI;
  endcase
//------------------------------------------
 assign S_EX_ACK = 1'b1;
//------------------------------------------
// Regs Outputs:
 assign RG_0Q = RG_0I; assign RG_1Q = RG_1I;
 assign RG_2Q = RG_2I; assign RG_3Q = RG_3I;
 assign RG_4Q = RG_4I; assign RG_5Q = RG_5I;
 assign RG_6Q = RG_6I; assign RG_7Q = RG_7I;
 assign RG_8Q = RG_8I; assign RG_9Q = RG_9I;
 assign RG_AQ = RG_AI; assign RG_BQ = RG_BI;
 assign RG_CQ = RG_CI; assign RG_DQ = RG_DI;
 assign RG_EQ = RG_EI; assign RG_FQ = RG_FI;
//------------------------------------------
endmodule

Более компактно описать регистровый файл можно с помощью дух мерного массива:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////
// Engineer:       FPGA-Mechanic
//
// Create Date:    11:40:08 07/24/2014
// Design Name:    STI Design
// Module Name:    MSTI_8b_16xREG_V11 - 16x8bit Register File
//                                      in STI Memory Space
// Project Name:   Any
// Target Devices: FPGA
// Tool versions:  Xilinx DS 14.4
//
// Revision:       1.1 (24.07.2014) Array Coding
// Revision 1.0 - File Created
//////////////////////////////////////////////////////////////////////////
module MSTI_8b_16xREG_V11(
    input         CLK,
    input         RST,
    input         S_EX_REQ,
    input  [3:0]  S_ADDR,
    //input  [1:0]  S_NBE,
    input  [2:0]  S_CMD,
    input  [7:0]  S_D_WR,
    output        S_EX_ACK,
    output [7:0]  S_D_RD,
    output [7:0]  RG_0Q,
    output [7:0]  RG_1Q,
    output [7:0]  RG_2Q,
    output [7:0]  RG_3Q,
    output [7:0]  RG_4Q,
    output [7:0]  RG_5Q,
    output [7:0]  RG_6Q,
    output [7:0]  RG_7Q,
    output [7:0]  RG_8Q,
    output [7:0]  RG_9Q,
    output [7:0]  RG_AQ,
    output [7:0]  RG_BQ,
    output [7:0]  RG_CQ,
    output [7:0]  RG_DQ,
    output [7:0]  RG_EQ,
    output [7:0]  RG_FQ
    );

// Internal signals declaration:
 wire M_WR_CMD;
 reg  [7:0] RG_I [15:0]; // Array 16 x 8bit
//------------------------------------------
 assign M_WR_CMD = ~S_CMD[2] & S_CMD[0] & S_EX_REQ;
//------------------------------------------
// Internal Data Registers:
 always @ (posedge CLK, posedge RST)
  if(RST)
   begin
    RG_I[0] <= 8'h00; RG_I[1] <= 8'h00;
    RG_I[2] <= 8'h00; RG_I[3] <= 8'h00;
    RG_I[4] <= 8'h00; RG_I[5] <= 8'h00;
    RG_I[6] <= 8'h00; RG_I[7] <= 8'h00;
    RG_I[8] <= 8'h00; RG_I[9] <= 8'h00;
    RG_I[4'hA] <= 8'h00; RG_I[4'hB] <= 8'h00;
    RG_I[4'hC] <= 8'h00; RG_I[4'hD] <= 8'h00;
    RG_I[4'hE] <= 8'h00; RG_I[4'hF] <= 8'h00;
   end
  else
   if(M_WR_CMD)
    RG_I[S_ADDR] <= S_D_WR;
//------------------------------------------
// Output MUX:
 assign S_D_RD = RG_I[S_ADDR];
//------------------------------------------
 assign S_EX_ACK = 1'b1;
//------------------------------------------
// Regs Outputs:
 assign RG_0Q = RG_I[0]; assign RG_1Q = RG_I[1];
 assign RG_2Q = RG_I[2]; assign RG_3Q = RG_I[3];
 assign RG_4Q = RG_I[4]; assign RG_5Q = RG_I[5];
 assign RG_6Q = RG_I[6]; assign RG_7Q = RG_I[7];
 assign RG_8Q = RG_I[8]; assign RG_9Q = RG_I[9];
 assign RG_AQ = RG_I[4'hA]; assign RG_BQ = RG_I[4'hB];
 assign RG_CQ = RG_I[4'hC]; assign RG_DQ = RG_I[4'hD];
 assign RG_EQ = RG_I[4'hE]; assign RG_FQ = RG_I[4'hF];
//------------------------------------------
endmodule

image
Рис. 6. Функциональная схема регистрового файла

Третий пример исполнителя STI показывает вариант сопряжения с портами передачи и приёма данных DTP и DRP, описанными в статьях [8, 9, 10]. В этом примере возникла необходимость синтеза конечного автомата, управляющего сигналом подтверждения цикла S_EX_ACK и внутренними семафорами занятости регистров.

Для пересылки байтов в порт передачи данных DTP используется буферный регистр WR_DATA[7:0], занятость которого контролируется семафором WR_FULL.

Для приёма байтов из порта приёма данных DRP используется буферный регистр RD_DATA[7:0], занятость которого контролируется семафором RD_FULL.

Оба семафора построены на идентичных триггерах, работающих по графу, показанному в верхнем левом углу схемы (рис. 7). Вход установки S1 имеет более высокий приоритет по отношению ко входу сброса R2. Это позволяет осуществлять чтение из буферного регистра в одном такте с записью в этот регистр.

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

Остальные выходы автомата WR_SET и RD_CLEAR сформированы по схеме Мура (Moore FSM) комбинационными элементами.

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

Синтезируемая модель моста сопряжения с портами передачи и приёма данных, описанная на языке Verilog, приведена ниже:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////
// Engineer:       FPGA-Mechanic
//
// Create Date:    12:37:39 07/24/2014
// Design Name:    STI Design
// Module Name:    MSTI_8b_DTP_DRP_V10 8-bit STI to DTP & DRP Bridge
// Project Name:   Any
// Target Devices: FPGA
// Tool versions:  Xilinx DS 14.4
//
// Revision:       1.0 (24.07.2014)
// Revision 1.0 - File Created
//////////////////////////////////////////////////////////////////////////
module MSTI_8b_DTP_DRP_V10(
    input         CLK,
    input         RST,
    input         S_EX_REQ,
    //input         S_ADDR_0,
    //input  [1:0]  S_NBE,
    input  [2:0]  S_CMD,
    input  [7:0]  S_D_WR,
    output        S_EX_ACK,
    output [7:0]  S_D_RD,
    output        DTP_READY_T,
    output [7:0]  DTP_DATA_T,
    input         DTP_READY_R,
    input         DRP_READY_T,
    input  [7:0]  DRP_DATA_R,
    output        DRP_READY_R
    );

// Internal signals declaration:
 wire IOW_CMD, IOR_CMD;
 wire IOW_REQ, IOR_REQ;
 reg  [7:0] WR_DATA, RD_DATA;
 reg  WR_FULL, RD_FULL;
 reg  [1:0] FSM_STATE;
 wire WR_SET, RD_CLEAR;
//------------------------------------------
 assign IOW_CMD = ~S_CMD[0] & ~S_CMD[2];
 assign IOR_CMD = ~S_CMD[0] & ~S_CMD[1] & S_CMD[2];
 assign IOW_REQ = IOW_CMD & S_EX_REQ;
 assign IOR_REQ = IOR_CMD & S_EX_REQ;
//------------------------------------------
// Internal Data Registers:
 always @ (posedge CLK, posedge RST)
  if(RST)
   begin
    WR_DATA <= 8'h00;
    RD_DATA <= 8'h00;
   end
  else
   begin
    if(WR_SET) WR_DATA <= S_D_WR;
    if(~RD_FULL & DRP_READY_T)
     RD_DATA <= DRP_DATA_R;
   end
 assign S_D_RD = RD_DATA;
 assign DTP_DATA_T = WR_DATA;
//------------------------------------------
// Internal Data Semaphores:
 always @ (posedge CLK, posedge RST)
  if(RST)
   begin
    WR_FULL <= 1'b0;
    RD_FULL <= 1'b0;
   end
  else
   begin
    if(WR_SET) WR_FULL <= 1'b1;
    else if(DTP_READY_R) WR_FULL <= 1'b0;
    if(~RD_FULL & DRP_READY_T) RD_FULL <= 1'b1;
    else if(RD_CLEAR) RD_FULL <= 1'b0;
   end
 assign DTP_READY_T = WR_FULL;
 assign DRP_READY_R = ~RD_FULL;
//------------------------------------------
// Finite State Machine:
 always @ (posedge CLK, posedge RST)
  if(RST)
   FSM_STATE <= 2'd0;
  else
   begin
    case(FSM_STATE)

     2'd0 :
      if(IOW_REQ)
       if(WR_FULL) FSM_STATE <= 2'd2;
       else FSM_STATE <= 2'd1;
      else if(IOR_REQ)
       if(RD_FULL) FSM_STATE <= 2'd3;
       else FSM_STATE <= 2'd2;
      else FSM_STATE <= 2'd0;

     2'd1 : FSM_STATE <= 2'd0;

     2'd2 :
      if(IOW_REQ)
       if(WR_FULL) FSM_STATE <= 2'd2;
       else FSM_STATE <= 2'd1;
      else if(IOR_REQ)
       if(RD_FULL) FSM_STATE <= 2'd3;
       else FSM_STATE <= 2'd2;
      else FSM_STATE <= 2'd0;

     default: FSM_STATE <= 2'd0;

    endcase
   end
//------------------------------------------
// Moore Outputs
 assign WR_SET = ~FSM_STATE[1] & FSM_STATE[0];
 assign RD_CLEAR = &(FSM_STATE);
//------------------------------------------
 assign S_EX_ACK = FSM_STATE[0];
//------------------------------------------
endmodule

image
Рис. 7. Функциональная схема моста сопряжения стыка STI и портов передачи и приёма данных DTP и DRP

Выводы.

Стык простого исполнителя STI позволяет строить модели исполнителей для системных интерфейсов проекта конфигурации ПЛИС или кристалла СБИС, обеспечивающие большую пропускную способность, сочетающуюся с предельной простотой протокола взаимодействия.
Описанный интерфейс может найти применение в периферийных контроллерах кристалла, а также мостах сопряжения с классическими каналами обмена наподобие I2C, SPI, QSPI, SRAM, FLASH, Microwire и внешними системными шинами старого образца.

Литература:

1. AMBA APB Protocol. Version: 2.0. Specification. ARM IHI 0024C (ID041610) 2003-2010, ARM.
2. AMBA Specification Rev 2.0. ARM IHI 0011A. ARM Limited 1999.
3. AMBA AXI Protocol. Version: 2.0. Specification. ARM IHI 0022C (ID030510) 2003-2010, ARM.
4. AMBA 4 AXI4-Stream Protocol. Version: 1.0. Specification. ARM IHI 0051A (ID030510). 2010, ARM.
5. WISHBONE System-on-Chip (SoC) Interconnection Architecture for Portable IP Cores. 2010, OpenCores.
6. Open Core Protocol (OCP) Specification Release 2.1. 2005, OCP-IP Association.
7. RTL Hardware Design Using VHDL: Coding for Efficiency, Portability, and Scalability. By Pong P.Chu. John Wiley & Sons, Inc. 2006.
8. Борисенко Н. В. Подходы к организации унифицированного ряда синтезируемых моделей буферов FIFO, реализуемых в различных семействах программируемой логики. Часть 1. «Компоненты и технологии» №12.2012.
9. Борисенко Н. В. Схемы включения буферов FIFO с унифицированным интерфейсом в тракт данных между источником и приёмником информации. «Компоненты и технологии» №2.2013.
10. Борисенко Н. В. Организация синхронных буферов FIFO с унифицированным интерфейсом, построенных на регистрах общего назначения в объёме микросхем программируемой логики. «Компоненты и технологии» №8.2016.

Автор: Nikolay

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js