Перейти к содержанию
    

Обконстрейнить асинхронный EMIF

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

 

Дано: DSP имени TI и FPGA имени Xilinx, соединённые шиной EMIF. EMIF асинхронный. Временные диаграммы чтения в приаттаченном рисунке.post-1757-1418366208_thumb.png

 

В FPGA имееется много регистров, формируемых в общем случае на разных клоках. Их надо читать процессором. То есть получается такой большой многоразрядный мультиплексор:

process (EMIFA, D0, D1, D2)
begin
       -- для простоты тут регистра только три, реально их много больше
       case EMIFA is
              when A0 => D <= D0;
              when A1 => D <= D1;
              when A2 => D <= D2;
              when others => D <= (others => '0');
       end case;

       EMIFD <= D when (EMIFCE = '0' and EMIFOE = '0') else (others => 'Z');
end;

 

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

# DSP read strobe: setup: 2 * 6 ns, strobe: 4 * 6 ns, hold: 2 * 6 ns

TIMEGRP DSP_EMIFD_GRP = PADS(EMIFD(*));

NET U00/D0(*) TPSYNC = UU0_D0;
TIMESPEC TS_UU0_D0 = FROM UU0_D0 TO DSP_EMIFD_GRP 30 ns;
# 30 нс -- это меньше чем setup+hold=36 нс.

Но видимо, этого недостаточно. Наверное, надо как-то учесть и EMIFA, и EMIFCE, и EMIFOE.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А у Вас-то он синхронный? То есть, все это выставляется по какому-то клоку, и данные принимается по этому же клоку?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В FPGA имееется много регистров, формируемых в общем случае на разных клоках. Их надо читать процессором. То есть получается такой большой многоразрядный мультиплексор:

 

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

Но видимо, этого недостаточно. Наверное, надо как-то учесть и EMIFA, и EMIFCE, и EMIFOE.

 

FPGA и процесор асинхронны.

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

 

Ну и как обконстрейнить.

время регистр-пин FPGA не критично (регистр устанавливается, выдаётся прерывание, пока отреагирует процесор...), но лутше таки задать максимальное значение, чтобы оно было под контролем (а вдруг процесор такой быстрый).

Обычно всё что относится к внешним пинам констрейнится через виртуальные клоки.

 

А вот время срабатывания мультиплексора (процесор шина адреса\RD - PCB задержка - FPGA пины - FPGA шина адреса - FPGA декодер - FPGA пины - PCB задержка - процесор шина данных)

нужно задать как set_maх_delay -from FPGA пин -though FPGA декодер -to FPGA пины , чтобы данные гарантировано приходили в ожидаемое процесором время.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А у Вас-то он синхронный? То есть, все это выставляется по какому-то клоку, и данные принимается по этому же клоку?

Регистры, которые надо читать, сидят в трёх клоковых доменах с некратными частотатми. Переносить их в один домен мне кажется несколько некрасивым. Кроме того, максимальная частота внутри ПЛИС примерно 65 МГц. Если работу с EMIF "привязать" к ней, то надо увеличивать setup/strobe/hold у EMIF и таким образом несколько его затормозить, чего не хотелось бы.

 

Для избежания чтения данных в момент их изменения, процесор должен получить сигнал готовности данных - например после обновления регистра FPGA выставляет запрос прерывания и держит данные, пока процесор не прочитает их.
А если таких регистров много, десяток-другой? На всех прерывания не напасёшься.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Дано: DSP имени TI и FPGA имени Xilinx, соединённые шиной EMIF. EMIF асинхронный. Временные диаграммы чтения в приаттаченном рисунке.post-1757-1418366208_thumb.png

 

В FPGA имееется много регистров, формируемых в общем случае на разных клоках. Их надо читать процессором. То есть получается такой большой многоразрядный мультиплексор:

process (EMIFA, D0, D1, D2)
begin
       -- для простоты тут регистра только три, реально их много больше
       case EMIFA is
              when A0 => D <= D0;
              when A1 => D <= D1;
              when A2 => D <= D2;
              when others => D <= (others => '0');
       end case;

       EMIFD <= D when (EMIFCE = '0' and EMIFOE = '0') else (others => 'Z');
end;

 

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

# DSP read strobe: setup: 2 * 6 ns, strobe: 4 * 6 ns, hold: 2 * 6 ns

TIMEGRP DSP_EMIFD_GRP = PADS(EMIFD(*));

NET U00/D0(*) TPSYNC = UU0_D0;
TIMESPEC TS_UU0_D0 = FROM UU0_D0 TO DSP_EMIFD_GRP 30 ns;
# 30 нс -- это меньше чем setup+hold=36 нс.

Но видимо, этого недостаточно. Наверное, надо как-то учесть и EMIFA, и EMIFCE, и EMIFOE.

а почему Вы не хотите сделать EMIF и подключить к одному порту двупортовой памяти/фифо? Со вторым портом Вы работаете на своей частоте...

возможно еще выделить дополнительно еще пару пинов для обмена готовности данных у FPGA и DSP...

Таким образом, блок работы EMIF работает в своем тактовом домене и данные Вы забираете практически без задержек...

Чем память хороша, тем что Вы можете забирать нужные типы данных по соответствующим адресам, например

сигнал готовности:

"00" данные забирать с 0 адреса по 127 адрес

"01" данные забирать с 128 адреса по 156 адрес

"10" данные забирать с 157 адреса по 200 адрес

"11" данные забирать с 158 адреса по 256 адрес

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Регистры, которые надо читать, сидят в трёх клоковых доменах с некратными частотатми. Переносить их в один домен мне кажется несколько некрасивым. Кроме того, максимальная частота внутри ПЛИС примерно 65 МГц. Если работу с EMIF "привязать" к ней, то надо увеличивать setup/strobe/hold у EMIF и таким образом несколько его затормозить, чего не хотелось бы.

 

В таком случае, так:

1) Во всех трех доменах нужны синхронизаторы по два триггера на каждый из входных сигналов.

2) Для всех входных сигналов (адрес, данные, т.п.) во всех доменах указать set_input_delay так, чтобы Tsu у FPGA было бы меньше, чем период клока EMIF-а за минусом максимального Tco этих сигналов у EMIF и некоего маленького запаса.

3) Адрес и управление анализировать ТОЛЬКО когда EMIFOE с выхода синхронизатора стал активен. При этом, при таком set_input_delay, как описано в 2) есть 100% гарантия валидности адреса и остальных сигналов управления, так как они реально активизируются раньше, чем OE.

4) данные выдавать на выход, соответственно, на следующем клоке после анализа адреса. Для них установить какое-то определенное Tco.

 

Ну и EMIF запрограммировать так, чтобы гарантировать такую длительность OE, чтобы оно прошло через синхронизаторы во всех трех доменах (2.5 клока самого медленного домена), плюс еще 1 клок самого медленного домена на выдачу данных, плюс Tco из п.4)

 

Это вариант №1. синхронный внутри FPGA. Еще есть вариант №2, если внутри FPGA сделать асинхронную дешифрацию адреса и асинхронные флаги чтения. Но этот вариант не всегда реализуем, но более эффективен по скорости. Там все придется констрейнить через set_max_delay и set_min_delay.

 

В варианте номер 2 - строится асинхронный дешифратор адреса и мультиплексор с регистров ядра FPGA на выход данных. сигнал OE управляет непосредственно тристейтами выходных буферов. Все констрейнится через set_max_delay от входов адресов и CS-ов и до выхода данных, на какое то условное значение, физически реализуемое в проекте. И, соответственно этому настраивается EMIF.

Флаги, что произошло чтение соотв. регистра, реализуются с использованием сигнала OE (заднего его фронта) как клока, и сигналов дешифрации адреса, как разрешения установки флага. при этом задаются констрейны типа set_input_delay для адресов и CS-ов относительно OE. Эти флаги пропускаются в ядро FPGA через синхронизаторы из двух триггеров, и сбрасываются из ядра асинхронно, импульсами длиной в 1 клок соотв. клок-домена. Эти же флаги используются как сигнал READY EMIF-а, чтобы растянуть цикл, если он задумает читать данное раньше, чем ядро фпга его обновило (то есть, пока флаг в единице).

READY формируется асинхронно пропусканием соответствующих флагов согласно адресу читаемого регистра, и констрейнится так же, как данные.

Эти флаги нужны только таким регистрам, которые передают данные, которые же передают статусы, или являются управляющими (то есть, и пишутся только через EMIF, используя его же WE как клок), флагов и READY не требуют. Это вариант предпочтителен и по скорости, и по area, но многие имеют перед ним предрассудки - комплекс боязни асинхронных схем. На всякий случай, для READY можно описать еще и set_output_delay относительно клока OE.

 

Если вариант 2 непонятен из описания словами, могу нарисовать его на верилоге.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а почему Вы не хотите сделать EMIF и подключить к одному порту двупортовой памяти/фифо? Со вторым портом Вы работаете на своей частоте...

возможно еще выделить дополнительно еще пару пинов для обмена готовности данных у FPGA и DSP...

Таким образом, блок работы EMIF работает в своем тактовом домене и данные Вы забираете практически без задержек...

Немного не понял. Вы предлагаете вместо россыпи регистров использовать банк памяти? А как тогда их писать? Со стороны FPGA регистры обновляются независимо друг от друга. А у памяти вход один.

 

SM, благзаин. Надо обдумать.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Немного не понял. Вы предлагаете вместо россыпи регистров использовать банк памяти? А как тогда их писать? Со стороны FPGA регистры обновляются независимо друг от друга. А у памяти вход один.

Знаю, что геморно (извиняюсь за слово), но в FPGA значения регистров, нужно будет последовательно записывать в память по нужным адресам. Создать типа паралельно-последовательного устройства, которое забирет с паралельных регистров (учитывая все переходы из разных тактовых доменов) данные и запишет последовательно по нужным адресам в память...

Запись/чтение в/из память/памяти можно сделать на более высокой частоте - для повышения быстродействия...

Как-то так....

 

PS Можно попробовать увеличить двупортовую память в два раза и сделать типа двойной буферизации, т.е. пока например процессор считывает информацию, FPGA записывает новую информацию и наоборот... Быстродейстаие должно увеличиться....

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Дано: DSP имени TI и FPGA имени Xilinx, соединённые шиной EMIF. EMIF асинхронный. Временные диаграммы чтения в приаттаченном рисунке.post-1757-1418366208_thumb.png

 

В FPGA имееется много регистров, формируемых в общем случае на разных клоках. Их надо читать процессором. То есть получается такой большой многоразрядный мультиплексор:

process (EMIFA, D0, D1, D2)
begin
       -- для простоты тут регистра только три, реально их много больше
       case EMIFA is
              when A0 => D <= D0;
              when A1 => D <= D1;
              when A2 => D <= D2;
              when others => D <= (others => '0');
       end case;

       EMIFD <= D when (EMIFCE = '0' and EMIFOE = '0') else (others => 'Z');
end;

 

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

# DSP read strobe: setup: 2 * 6 ns, strobe: 4 * 6 ns, hold: 2 * 6 ns

TIMEGRP DSP_EMIFD_GRP = PADS(EMIFD(*));

NET U00/D0(*) TPSYNC = UU0_D0;
TIMESPEC TS_UU0_D0 = FROM UU0_D0 TO DSP_EMIFD_GRP 30 ns;
# 30 нс -- это меньше чем setup+hold=36 нс.

Но видимо, этого недостаточно. Наверное, надо как-то учесть и EMIFA, и EMIFCE, и EMIFOE.

Как бы я сделал :

1. Перетащил все выходы регистров в один домен. Тут важно убедиться что данные из регистров не изменятся "частично" вследствие того, что фронты чтения и записи асинхронны и могут совпасть. В некоторых случаях на эту ситуацию можно вообще забить (например если мы точно знаем, что писать в регистры новые данные в момент чтения точно никто не будет). Тут всё зависит от логики работы. Это всё очень похоже на классический mailbox.

2. Офигенных размеров выходной мультиплексор сделал бы обязательно синхронным, если не укладываемся в тайминги ввиду конских размеров мультиплексора - добавил бы мультициклы в это место.

3. В вашем EMIF интерфейсе наверняка должен быть сигнальчик RDY, позволяющий на некоторое время "затянуть" цикл чтения из "тормозных" слейвов. Можно тянуть цикл до тех пор, пока наш конский синхронный мультиплексор не выплюнет наружу данные, можно даже малость перестраховаться.

4. Ну и понятно, что фактически ваш асинхронный интерфейс превращается в синхронный. Кстати, если клоки от TI каким-то образом вдруг окажутся в ПЛИС - это может сильно облегчить жизнь.(мы же понимаем, что асинхронных интерфейсов на самом деле не существует, просто кто-то забыл или просто не захотел по какой-то причине тащить наружу клок).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще, вдогонку.

 

В Вашем, конкретном примере, есть

FROM UU0_D0 TO DSP_EMIFD_GRP 30 ns;

 

А он, в принципе то, и не особо нужен (хотя, и не мешает). Этот путь, даже если опутать дорожками всю FPGA изнутри, будет выдержан всегда, так как, Вы же наверняка не читаете данное, пока не прочитали, что данное готово, или ОНО не запросило прерывание. А когда оно его запросило, то по этому пути уже все дошло куда следует десять раз.

 

А вот основного - FROM EMIFA TO DSP_EMIFD_GRP XXXX ns; нету! Именно этот путь отвечает за настройку EMIF-а.

ну и FROM EMIFCE TO DSP_EMIFD_GRP XXXX ns; и FROM EMIFOE TO DSP_EMIFD_GRP XXXX ns;

 

причем самый критичный, это последний. И по ним еще и MIN пути надо задать, чтобы HOLD TIME выдержать (Особенно, EMIFOE->EMIFD)! Наверняка там какое-то неотрицательное значение имеется в доке на EMIF. Причем, если MAX пути можно растянуть настройкой емифа, то MIN путь - соблюдать из даташит необходимо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Помнится мне, что EMIF, на самом деле, не вполне асинхронная весч. Снаружи он асинхронный, но внутри он по клокам (не помню каким, зависит от камня) работает, и вся времянка у него к этим клокам привязана.
Разумеется. Клок этот 1/6 ГГц. Только в даташите никаких привязок к этому клоку нет.

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

Ну собсно в итоге я так и сделал: перенёс всё внутри на самый высокий из имеющихся клоков, раздвинул "корыта" OE и WE и вроде как всё заработало.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Только в даташите никаких привязок к этому клоку нет.

Ну это, не совсем, так. Можно перевести режим Вашего CE, например в SBSRAM, и уже получить вполне себе синхронный интерфейс.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всем привет.

Посмотрев на автомат ТС мне представилась следующая возможная конструкция этого-же автомата:

package x_types is

type x_array is array (0 to NUM_REGISTERS) of integer;
    
end x_types;

----------------------------

entity xxx is
port
(
    ...
    a        : in x_array; -- каждый элемент массива подключается к своему источнику данных (к своему тактовому домену)
    ...
);
end xxx;

----------------------------

EMIFD        <= a(EMIFA);

Это всё, конечно же, на вскидку, без проработки мелочей.

Но хотелось бы услышать мнение знатоков: возможна ли такая конструкция мультиплексора (возможно и не асинхронная)? Или же это полная ...?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Всем привет.

Посмотрев на автомат ТС мне представилась следующая возможная конструкция этого-же автомата:

package x_types is

type x_array is array (0 to NUM_REGISTERS) of integer;
    
end x_types;

----------------------------

entity xxx is
port
(
    ...
    a        : in x_array; -- каждый элемент массива подключается к своему источнику данных (к своему тактовому домену)
    ...
);
end xxx;

----------------------------

EMIFD        <= a(EMIFA);

Это всё, конечно же, на вскидку, без проработки мелочей.

Но хотелось бы услышать мнение знатоков: возможна ли такая конструкция мультиплексора (возможно и не асинхронная)? Или же это полная ...?

Возможна и такая реализация, все зависит от Вашей фантазии и уровня знаний/опыта, но тут "мелочи" решают все. Главное, что в итоге - описание в ПЛИС работает или нет и удовлетворяет заданным/желаемым характеристикам работы... Я к чему, например одно описание будет работать на 40 МГц, чуть по другому описанная схема работает уже на 200 МГц, но функционально выполняют то, что необходимо/нужно для одной и той же ПЛИС.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...