vak: (Улыбка)
Serge Vakulenko ([personal profile] vak) wrote2016-08-26 12:58 pm

Асинхронный арбитр

Столкнулся с необходимостью изобразить на FPGA асинхронный арбитр. Это такая схема, которая определяет, который из двух сигналов поступил раньше. Для ASIC задача решается так:

Выглядит как простая цифровая схема, но на самом деле здесь решается нетривиальная проблема фильтраци метастабильного состояния, аналоговая по своей сути. Об эту тему много копий сломано и научных статей написано. Для FPGA качественного решения не существует. В идеале изготовители FPGA должны бы закладывать в архитектуру чипа некоторое количество модулей-арбитров. Увы, в нынешних чипах от Xilinx и Altera их нет, поэтому приходится измышлять решения "на коленке". Пока думаю обойтись двумя вентилями NAND2, а в качестве фильтра метастабильности задействовать пару MUX7. По идее, всё это должно поместиться в один слайс. Еще можно попробовать вместо NAND2 использовать штатную RS-защелку типа FDCPE. У неё есть асинхронные входы для сброса и установки. Да и время выхода из метастабильного состояния должно получиться поменьше.

[identity profile] spamsink.livejournal.com 2016-08-26 08:28 pm (UTC)(link)
Какое у этой штуки определение на поведенческом уровне? Например, в виде UDP?

[identity profile] spamsink.livejournal.com 2016-08-26 09:11 pm (UTC)(link)
По идее, одного LUT6_2 с выходами, завернутыми на себя, должно хватить.

[identity profile] spamsink.livejournal.com 2016-08-26 09:52 pm (UTC)(link)
Насколько я понимаю, может быть, если разница во времени прихода входящих сигналов меньше, чем разница между временами фидбека двух выходов, но внутри одного слайса это должно быть на порядок меньше, чем произвольная разница между задержками во внешних соединениях.

Идея в том, чтобы как можно сильнее приблизиться к атомарной конструкции. Чем больше элементов, тем больше связей, и тем больше места/времени для осцилляции. А LUT6_2 с фидбеком, который гарантированно будет проведен внутри слайса - это "почти" атомарный элемент-арбитр.
Edited 2016-08-26 22:09 (UTC)

[identity profile] spamsink.livejournal.com 2016-08-26 10:18 pm (UTC)(link)
Как тебе вот это?
module MUTEX(input bit [1:0] in, output bit [1:0] out);
always @* casez ({int'(in), int'(out)})
{0, 'z}: out = 0;
{1, 'z}: out = 1;
{2, 'z}: out = 2;
{3, 1}: out = 1;
{3, 2}: out = 2;
{3, 0}: out = 1; // in[0] wins
{3, 3}: out = 1; // in[0] wins, I said!
endcase
endmodule

[identity profile] spamsink.livejournal.com 2016-08-27 12:55 am (UTC)(link)
Понятно, что если сначала меняется in[1], а потом почти мгновенно in[0] (пока out[0] еще не успел обернуться через фидбек), то на out[1] будет glitch. Трудность в том, что это невозможно отловить, добавляя буфера или инверторы, поскольку их задержка больше, чем задержка фидбека. Тут надежда на то, что вероятность такой разницы во времени минимальна.

[identity profile] spamsink.livejournal.com 2016-08-27 01:30 am (UTC)(link)
На вЫходе, ты имел в виду? MUXF7 не получится, потому что у них входы фиксированы.
Впрочем, если написать
{3, 0}: out = 1; // in[0] wins

{3, 3}: out = 2; // this means that in[1] came slightly earlier and it should win

то глитч будет не overlapping, а included, дальше можно будет написать
out_final[1] = out[1];
out_final[0] = out[0] & ~out[1];

Т.е. выйдет два LUT6_2, один из которых реально 4->2, а другой 2->2.

[identity profile] spamsink.livejournal.com 2016-08-27 02:26 am (UTC)(link)
А на Virtex7 они идут к выходам LUT6.

К выходам двух разных LUT6, а не одной LUT6_2.