Vengin 0 21 декабря, 2018 Опубликовано 21 декабря, 2018 · Жалоба Симулирую FIFO корку Vivado и что-то никак не удаётся получить ожидаемого поведения. Не совпадают результаты симуляции с тем, что описано в даташите (в частости latency выходных сигналов), и с тем, что ожидаешь увидеть. Когда много лет назад приходилось работать с FIFO ядром в ISE, не припомню таких трудностей. Совсем запутался, надеюсь коллективный разум поможет. Итак вводные: Vivado v2017.4 (64-bit), корка fifo_generator_v13_2_1. Генерим простейшее FIFO: Native (без AXI), Common Clock Block-RAM, 8x16, Standard Read Mode (т.е. не First Word Fall Through), без выходных регистров: Как видим, ожидаемая задержка чтения (данных) должна быть 1 такт. А задержка остальных выходных сигналов указывается в даташите (“Ch. 3: Designing with the Core” -> Latency -> Non-Built-in FIFOs: Common Clock and Standard Read Mode Implementations) : Т.е. вроде все остальные выходные сигналы в домене чтения (кроме prog_empty) должны иметь задержу 0 тактов. Хотя лично для меня это звучит странно, т.к. в моём понимании это сигналы «синхронные» (т.е. выходят с неких внутренних регистров ядра), и должны быть задержаны хотя бы на 1 такт. И эти догадки подтверждаются синтезом корки (на схематике выходные «статусные» выходят с регистров. В моём понимании это задержка минимум в 1 такт (или больше, в зависимости от общего количества регистров в каскаде). Уже это вызывает вопросы. Xilinx в даташите на FIFO описывает, как определяется Latency: Тут стоит сказать, что ИМХО такое изображение диаграмм (т.е. не как в function simulation, («синхронное, такт-в-такт»), а как в timing simulation (более «реалистичное» с учётом таких задержек, как setup/hold)) не только не помогает понять логику работы для функциональной симуляции, но скорее больше мешает, ухудшает восприятие и приводит к потенциальным ошибкам. По мне так эта диаграмма больше похожа на latency=1, а не 0. Так вот генерим в Vivado тестбенч для нашего простенького FIFO (правым кликом на IP-Core –> “Open IP Example Design…”). В сгенеренном Vivado тестбенче «имитируются» вышеупомянутые timing задержки, т.е на VHDL используются конструкции вида “… after XX ns”. Таким способом «задержаны» синхронный сброс (srst), входные сигналы записи/чтения (wr_en/rd_en) и входные данные записи (din). В данном случае период клока симуляции 200ns, задержки after = 50ns. И что же мы имеем в симуляции. Вот так выглядит запись в FIFO: А так чтение из FIFO: Сначала я долго не мог понять, что за 0.1ns на выходных сигналах (диаграмма чтения, 3-ий курсор, сигналы empty/data_count обновляются при T=16300.1ns). Покопавшись в даташите и инете, вроде пришёл к выводу, что так явно «имитируются» delta delay симуляции (и/или задержки синхронных сигналов в железе). В даташите (Ch. 4: Design Flow Steps -> Simulation -> Behavioral Model): И на форуме Xilinx: тыц (100 ps delay for Block Memory Generator 6.3) и тыц (BRAM output delay). Т.е. вроде эти 100ps должны быть «более наглядными» (если сравнивать с delta delay, которая в симуляции стремится к нулю), показывая, что «in hardware, it should never assume that synchronous data is available instantaneously with the active clock edge». Переварив всё это, я прихожу к выводу, что: На диаграмме записи задержка сигналов статуса чтения (empty, data_count) по отношению к wr_en вроде как 0 тактов (соответствует значениям в таблице 3-14). Хотя (как уже писалось раньше), эти сигналы вроде как выходят с регистров, и должны иметь задержку минимум 1 такт. На диаграмме чтения задержка сигнала данных (dout) по отношению к сигналу rd_en мне непонятна (получается ещё меньше, чем 0 тактов, т.к. нет 100ps, а исходя из вышеупомянутых параметров FIFO latency=1). При этом если сконфигурировать FIFO с выходным регистром (Embedded или Fabric в поле Output Register), то ожидаемая задержка latency=2 такта, а на диаграмме выход dout «свдигается» на всё те же 100ps (т.е. выравнивается со «статусными» выходными сигналами, что вроде как по описанию Xilinx соответствует задержке 0 тактов, а не 2). Но больше всего мне непонятно, как такие выходные сигналы (с задержкой на 100ps) «стыковать» с остальной частью логики, которая описана естественно без такого рода задержек, как просто «функциональная» схема или «синхронный» дизайн на логическом уровне. Т.е. елсли в проекте стыковать это FIFO ядро, на уровне функциональной симуляции, его входные управляющие сигналы (wr_en, wr_data) не будут иметь «имитируемую» задержку 'after XX ns'. Т.е к примеру диаграмма записи будет выглядеть так: Получается, что с точки зрения остальной «функциональной логики», выходные статусные сигналы empty и data_count будут иметь latency=2. Т.е. любой синхронный процесс «защёлкнет» значение empty/data_count после двух клоков от сигнала wr_en (в момент T=16500ns), т.к. после одного клока (T=16300ns) сигнал ещё не обновился из-за этих 100ps. В то же время у асинхронных процессов эти 100ps будут вызывать glitch-и, и тоже приводить к ошибкам. В конечном итоге, основые вопросы такие. Как работать в «функциональной» симуляции с таким ядром? И почему выходные задержки latency не соответствуют значениям указанным в datasheet? Понимаю, что решение должно быть, но мне оно пока не ясно. Извиняюсь, что так много букв получилось, но не знаю как всё это описать покороче. И это лишь простейший вариант конфигурации FIFO. А что уж будет, если надо использовать скажем разные клоковые домены, в режиме First-Word-Fall-Through, разные Aspect Ratios и т.п. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 17 21 декабря, 2018 Опубликовано 21 декабря, 2018 · Жалоба . Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 35 21 декабря, 2018 Опубликовано 21 декабря, 2018 · Жалоба Приветствую! Не вижу на симуляции никаких проблем. Вы что с чем сравнивает? И как считаете latency, На диаграмме я вижу при записи latency=1 так как статус обновляется на следующем фронте а не одновременно с сигналом wr_en. IMHO хотя закладываться в дизайне на фиксированную latency write->read пусть даже для синхронного FIFO не есть хорошая практика. Для нормального режима (не FWFT) статус и данные чтения тоже меняются на следующем фронте clk перед котором сигнал rd_en=1. Вот вам и read latecy=1. На задержку в 100 ps при functional стимуляции можно и не обращать внимания (конечно если сами чего то не намудрили в RTL коде с задержками) Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 21 декабря, 2018 Опубликовано 21 декабря, 2018 · Жалоба 26 минут назад, RobFPGA сказал: Вы что с чем сравниваете? И как считаете latency, На диаграмме я вижу при записи latency=1 так как статус обновляется на следующем фронте а не одновременно с сигналом wr_en. IMHO хотя закладываться в дизайне на фиксированную latency write->read пусть даже для синхронного FIFO не есть хорошая практика. Ну я уж даже не знаю, как ещё более подробно описать, чем в 1-ом сообщении. Мне тоже кажется, что скажем задержка при записи должна быть 1 такт. Но то, как это описывается в даташите xilinx вроде должно быть latency=0. Но ведь если задержка 1 такст, то она не соответствует описываемой в даташите (по табичке 3-14 =0 тактов) 26 минут назад, RobFPGA сказал: IMHO хотя закладываться в дизайне на фиксированную latency write->read пусть даже для синхронного FIFO не есть хорошая практика. Не совсем понял этого высказывания. Что есть "не фиксированная" latency? Она что, для одних и тех же параметров ядра может быть разной? Нужно например инициировать сигнал чтения в зависимости от наполняемости FIFO (т.е. произвольного значения сигнала data_count). И делать это нужно как можно быстрее (т.е. вариант с подождать пару лишних тактов для надёжности не подходит). 26 минут назад, RobFPGA сказал: Не вижу на симуляции никаких проблем. На задержку в 100 ps при functional стимуляции можно и не обращать внимания (конечно если сами чего то не намудрили в RTL коде с задержками) А я бы сказал, что наоборот, сплошные проблемы. Просто тупо не работает. Как описывалось рньше, из-за этих 100ps синхронная логика "думает", что сигналы приходят на 1 такт позже, асинхронная начинает "сбоить" и расходится с синхронной. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 35 21 декабря, 2018 Опубликовано 21 декабря, 2018 · Жалоба Приветствую! Тут наверно просто недоразумения какие-то связанные с определением как latency считается. Quote Note: Latency is defined as the number of clock edges after a read or write operation occur before the signal is updated. Example: if latency is 0, that means that the signal is updated at the clock edge in which the operation occurred, as shown in Figure 3-40 in which wr_ack is getting updated in which wr_en is hig 52 minutes ago, Vengin said: Не совсем понял этого высказывания. Что есть "не фиксированная" latency? Она что, для одних и тех же параметров ядра может быть разной? Нужно например инициировать сигнал чтения в зависимости от наполняемости FIFO (т.е. произвольного значения сигнала data_count). И делать это нужно как можно быстрее (т.е. вариант с подождать пару лишних тактов для надёжности не подходит). Я всегда стараюсь делать так чтобы wr_* домен и rd_* домен независим даже если и синхронное FIFO. То есть так чтобы можно было заменить синхронное FIFO на асинхронное ничего не переделывая. Соответственно rd_домен не знает какая latency между wr_ena и rd_empty, rd_data_count, .... Поэтому и проблем нет - увидел фиксированное/какое-либо число на rd_data_count - значит гарантированно можно делать фиксированное/какое-либо число циклов чтения. 52 minutes ago, Vengin said: А я бы сказал, что наоборот, сплошные проблемы. Просто тупо не работает. Как описывалось рньше, из-за этих 100ps синхронная логика "думает", что сигналы приходят на 1 такт позже, асинхронная начинает "сбоить" и расходится с синхронной. Для functional симуляции этого не должно быть так как неважно когда изменится выходной сигнал после фронта клока - через 0ps задержки или через 100ps. Защелкиваются те значения которые были за -1 дельта цикл перед фронтом клока. Если у вас все ломается - значит либо глючит сим (отсюда и эта необходимость лепить в коде (особенно старом) эти задержки на минимальный шаг времени) - либо у вас где то в коде есть еще задержки на цепи клока. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 22 декабря, 2018 Опубликовано 22 декабря, 2018 · Жалоба 15 часов назад, RobFPGA сказал: Я всегда стараюсь делать так чтобы wr_* домен и rd_* домен независим даже если и синхронное FIFO. То есть так чтобы можно было заменить синхронное FIFO на асинхронное ничего не переделывая. Соответственно rd_домен не знает какая latency между wr_ena и rd_empty, rd_data_count, .... Поэтому и проблем нет - увидел фиксированное/какое-либо число на rd_data_count - значит гарантированно можно делать фиксированное/какое-либо число циклов чтения. Звучит логично, надо будет принять на вооружение. Правда не совсем понятно, как, скажем, поступать для Common Clock FIFO с общим сигналом data_count. Ведь в данном случае нет отедльных rd_data_count и wr_data_count для каждого клокового домена, т.к. клок общий. Искусственно создавать такие идентичные сигналы с "прицелом на асинхронное FIFO"? 15 часов назад, RobFPGA сказал: Для functional симуляции этого не должно быть так как неважно когда изменится выходной сигнал после фронта клока - через 0ps задержки или через 100ps. Защелкиваются те значения которые были за -1 дельта цикл перед фронтом клока. Если у вас все ломается - значит либо глючит сим (отсюда и эта необходимость лепить в коде (особенно старом) эти задержки на минимальный шаг времени) - либо у вас где то в коде есть еще задержки на цепи клока. Согласен, для симуляции не важно, на сколько сигнал задержан. Если изменения произошли после фронта клока - то и защёлкиваться они будут на следующем клоке. Т.к. визуально эти 100ps заметить крайне сложно (поначалу я их просто не видел), это и приводит к ощущению, что данные защёлкиваются не на том клоке. Мне например по прежнему не понятно, почему для функциональной модели для задержки сигнала на 1 такт xilinx где-то использует эти 100ps (а где-то вроде полноценный такт). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 22 декабря, 2018 Опубликовано 22 декабря, 2018 · Жалоба И всё-таки мне совершенно непонятно как работать с ядром. Вот для примера остановлюсь только на одном случае. Это диаграмма записи из первого сообщения, сгенерированного Vivado тестбенча с "искусственной" задержкой входных сигналов (wr_en, din) "after 50 ns": Насколько я понимаю, задержка между wr_en и data_count будет 1 такт. Т.е. синхронная логика "видит" значение сигнала wr_en на такте клока T=16300ns, а новое значение data_count=0x1 на следующем клоке T=16500ns. А теперь возьмём это ядро, и из Vivado тестбенча с "искусственными" задержками вставим в "реальный" проект. Входные сигналы wr_en, din и прочие контролируются синхронной логикой, и в функциональной симуляции не имеют никаких "искусственных" задержек "after XX ns". Тем не менее, т.к. ядро по прежнему выходные сигналы задерживает на 100ps получается что latency увеличивается. Т.е. получается, что (с точки зрения синхронной логики) задержка между wr_en и data_count будет 2 такта! Т.е. синхронная логика "видит" значение сигнала wr_en на такте клока T=16100ns, а новое значение data_count=0x1 по преженму клоке T=16500ns, т.е. через 2 такта. Обясните пожалуйста, где я не прав, или как это всё понимать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrew_b 17 22 декабря, 2018 Опубликовано 22 декабря, 2018 · Жалоба Где-то я читал, что cycle accuracy являются только empty и full. Всякие счётчики, торчащие из FIFO, особенно асинхронного, такими не являются, у них может быть произвольная (хоть и небольшая) задержка. В общем-то, так оно и есть. И это понятно. Чтобы передать счётчик из одного домена в другой, требуется несколько тактов. Жить это не мешает. Ну будет счётчик обновляться чуть позже, ну начнёте вы чуть позже читать из FIFO. Ну и что? В большинстве случаев это допустимо. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 22 декабря, 2018 Опубликовано 22 декабря, 2018 · Жалоба Я описал лишь один случай, но это применимо абсолютно ко всем выходным статусным сигналам FIFO (в том числе full и empty - они точно также задержаны на 100ps). Так что проблема не исчезает, если просто "закрыть на глаза". Тем более, что описываемый случай касается синхронного FIFO. И ни о каких передачах в другой домен речи не идёт. И ещё я упоминал, что стоит задача читать как можно раньше, чуть позже не вариант. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 35 22 декабря, 2018 Опубликовано 22 декабря, 2018 · Жалоба Приветствую! 4 hours ago, Vengin said: Насколько я понимаю, задержка между wr_en и data_count будет 1 такт. Т.е. синхронная логика "видит" значение сигнала wr_en на такте клока T=16300ns, а новое значение data_count=0x1 на следующем клоке T=16500ns. А теперь возьмём это ядро, и из Vivado тестбенча с "искусственными" задержками вставим в "реальный" проект. Входные сигналы wr_en, din и прочие контролируются синхронной логикой, и в функциональной симуляции не имеют никаких "искусственных" задержек "after XX ns". Тем не менее, т.к. ядро по прежнему выходные сигналы задерживает на 100ps получается что latency увеличивается. Т.е. получается, что (с точки зрения синхронной логики) задержка между wr_en и data_count будет 2 такта! Т.е. синхронная логика "видит" значение сигнала wr_en на такте клока T=16100ns, а новое значение data_count=0x1 по преженму клоке T=16500ns, т.е. через 2 такта. Обясните пожалуйста, где я не прав, или как это всё понимать. Что на первой картинке что на второй запись в FIFO происходит в момент 16300 (происходит запись байта 0x1B). Соответственно меняется значение статуса и счетчика по фронту этого такта. То что на второй картинке wr_en появился с задержкой 0 сразу после фронта 16100 не значит что запись будет на этом фронте - сигнал ведь появился не перед ним а после него! Поэтому вы можете двигать задержку wr_en и/или wr_data после такта 16100 от 0 до 200ns-1*delta а результат на симе будет один и тот же - запись по фронту 16300. Ну и опять же для functional - в синхронной схеме latency считается не от момента когда сигнал изменил значение (например wr_en в 16100+(0..50ns)) а от такта в котором этот сигнал привел к смене состояния в дизайне (запись в 16300) и до такта в котором это событие изменило состояние соответствующего выхода (data_count+1 в 16300). Отсюда у вас некоторая неоднозначность определения layency для разных событий Для простого синхронного FIFO wr_count и rd_count можно считать равными data_count. Но только для простого - для FWFT это уже не так. 15 minutes ago, Vengin said: Я описал лишь один случай, но это применимо абсолютно ко всем выходным статусным сигналам FIFO (в том числе full и empty - они точно также задержаны на 100ps). Так что проблема не исчезает, если просто "закрыть на глаза". И ещё я упоминал, что стоит задача читать как можно раньше, чуть позже не вариант. Читать быстрее чем данные будут доступны на чтение из FIFO вы не сможете. А наличие возможности чтения видно только на сигналах статуса rd_* домена. Поэтому для вашего случая простого синхронного FIFO вы сможете получить первые данные на выходе на следцущем такте после такта записи (такте 16500) не ранее. Тут нет проблемы. Вам надо просто разобраться аккуратно. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 35 22 декабря, 2018 Опубликовано 22 декабря, 2018 · Жалоба Приветствую! 1 hour ago, andrew_b said: Где-то я читал, что cycle accuracy являются только empty и full. Всякие счётчики, торчащие из FIFO, особенно асинхронного, такими не являются, у них может быть произвольная (хоть и небольшая) задержка. В общем-то, так оно и есть. И это понятно. Чтобы передать счётчик из одного домена в другой, требуется несколько тактов. Жить это не мешает. Ну будет счётчик обновляться чуть позже, ну начнёте вы чуть позже читать из FIFO. Ну и что? В большинстве случаев это допустимо. В правильном асинхронном FIFO сигналы статуса wr_* и rd_* домена синхротроны с соответствующим клоком и гарантируют корректную работу своего домена. Например rd_cout показывает сколько слов можно гарантированно прочитать начиная с текущего такта. При этом этот счетчик должен уменьшатся на 1 при каждом чтении. А вот увеличиваться на 1..N с непредсказуемой cycle latency после операций записи. Но опять же синхронно с rd_clk. Почти тоже и для wr_count увеличение на 1 при каждой записи, уменьшения на 1..N с непредсказуемой cycle latency после операций чтения. Для синхронного FIFO эта cycle latency фиксирована НО она зависит от реализации FIFO. Поэтому я и говорил что закладываться на это в дизайне не есть хорошо. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 22 декабря, 2018 Опубликовано 22 декабря, 2018 · Жалоба 21 минуту назад, RobFPGA сказал: Что на первой картинке что на второй запись в FIFO происходит в момент 16300 (происходит запись байта 0x1B). Хм, действительно во 2-ом случае запись в момент T=16300ns, хотя я был уверен что на такт раньше, при T=16100. Пойду разбираться. Но при всё при этом, мне не понятно, почему при чтении из FIFO выходные данные не имеют эту задержку 100ps: Тут значение 0x1B появляется в момент 20300ns. Это для FIFO без выходных регистров. Ведь сама BRAM память синхронна и её выход должен быть с задержкой хотя бы в 1 такт (как это и указано в параметрах). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RobFPGA 35 22 декабря, 2018 Опубликовано 22 декабря, 2018 · Жалоба Приветствую! 11 minutes ago, Vengin said: Хм, действительно во 2-ом случае запись в момент T=16300ns, хотя я был уверен что на такт раньше, при T=16100. Пойду разбираться. Но при всё при этом, мне не понятно, почему при чтении из FIFO выходные данные не имеют эту задержку 100ps: .. Тут значение 0x1B появляется в момент 20300ns. Это для FIFO без выходных регистров. Ведь сама BRAM память синхронна и её выход должен быть с задержкой хотя бы в 1 такт (как это и указано в параметрах). Опять же все корректно - перед тактом 20300 rd_addr чтения уже был на входах BRAM. При активном rd_ena по такту 20300 защелкнулись данные на выходе BRAM (вход en* на bram) а rd_addr увеличился на 1. Удачи! Rob. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 22 декабря, 2018 Опубликовано 22 декабря, 2018 · Жалоба Действительно логично... Благодарю за "разжевывание". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Vengin 0 22 декабря, 2018 Опубликовано 22 декабря, 2018 · Жалоба Ну вот, как только кажется, что появилась ясность, и всё начало становиться на свои места, появляются новые затыки. Вот диаграмма чтения Common Clock FIFO 32x1024 Standard, без выходных регистров (т.е. выходная задержка 1 такт): Задержка между rd_en и dout как и ожидается =1 такт. Переконфигурировал FIFO и добавил выходной регистр (Output Registers = Embedded Registers). Ожидается, что задержка выходных данных увеличится на 1 такт, и будет составлять 2 такта (о чём и говорится в Summary на корку "Read latency = 2"). Однако в симуляции поджидает неприятный сюрприз: Как видим значение на выходе dout появляется через 2 такта + 100ps, т.е. 3 такта для синхронной логики. Как же так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться