tvShushtov 0 13 сентября, 2023 Опубликовано 13 сентября, 2023 · Жалоба Обнаружили с коллегами любопытный баг, когда писали код spi-slave устройства для GW2A. Для отладки код был упрощен до минимума и фактически превратился в одиночный триггер (см. картинку). RST, CLK, DIN – входные порты, на которых формируется сигнал, согласно временной диаграмме ниже. Для теста я формирую их с помощью другой отладочной платы с ПЛИС. DOUT – защелкнутый триггером сигнал DIN. MUST – то, что должно было быть защелкнуто на триггере. Если хотите пробовать повторить багу, то я оставлю оба кода источника и приемника под спойлером. Спойлер library ieee; use ieee.std_logic_1164.all; entity main is port ( RST : in std_logic; CLK : in std_logic; DIN : in std_logic; clk_la : out std_logic; dout_la : out std_logic ); end entity; architecture rtl of main is signal DOUT : std_logic; begin -- тестовый триггер process (RST, CLK) begin if RST = '1' then DOUT <= '0'; elsif rising_edge(CLK) then DOUT <= DIN; end if; end process; --clk_la <= CLK; --!!!!!! dout_la <= DOUT; end architecture; Спойлер library ieee; use ieee.std_logic_1164.all; entity gen_sig is port ( clk : in std_logic; rst : in std_logic; test_rst : out std_logic; test_clk : out std_logic; test_data : out std_logic ); end gen_sig; architecture rtl of gen_sig is constant MAX_CNT_CLK : integer := 49; signal cnt_clk : integer range 0 to MAX_CNT_CLK := 0; begin TEST_PROC : process (clk, rst) begin if rst = '1' then test_rst <= '1'; test_clk <= '0'; test_data <= '0'; cnt_clk <= 0; elsif rising_edge(clk) then test_data <= '1'; if cnt_clk = MAX_CNT_CLK then cnt_clk <= 0; test_rst <= '0'; if test_rst = '0' then test_clk <= not test_clk; end if; else cnt_clk <= cnt_clk + 1; end if; end if; end process TEST_PROC; end rtl; Проблема выглядит следующим образом: После перезагрузки (power on/off) платы (или после перепрошивки ПЛИС) данные, которые приходятся на первый защелкивающий фронт триггера, не поступают на его выход (это событие помечено на временной диаграмме стрелкой 1-?->2). Все последующие защелкивания происходят корректно (например, стрелка 3-ok->4). Вот так эта проблема выглядит в GAO: Для всех, кроме первой, итераций схема функционирует корректно вплоть до выключения питания/перепрошивки. Чтобы исключить из рассмотрения GAO, выходной сигнал был выведен на пин и подключен к логическому анализатору вместе в входными RST и CLK. Картина оказалась аналогичной. Уточню, как выглядит схематик синтезированного кода, также посмотрим на то, какие ресурсы задействовал компилятор. Собирал я все на нескольких версиях софта. Самый последний тест был на Gowin EDA 1.9.9 (build 65859). Спойлер Самый простой способ, который позволяет вернуть «адекватную» работоспособность триггеру, это проброс входного сигнала CLK на выходной пин (раскомментировать строчку "clk_la <= CLK" в коде). Совершенно непонятно по какой причине в этом случае баг пропадает. Чтобы докопаться до источника проблемы, было произведено множество манипуляций со схемой. Я уберу все их под спойлер, оставлю только самое важное. Спойлер Менял пины двойного назначения на обычные. Не помогло Попробовал инвертировать клок перед подачей на триггер. Не помогло Сделал триггер без асинхронного сброса. Не помогло Вывел клок на глобальную линию через BUFG компонент. Не помогло Добавил дополнительный триггер на те же входы. Fanout=2. Не помогло Пробую подключить клок насильно через DQCE. Не помогло + теперь не помогает подключение выхода DQCE на выходной порт. Решающим оказалось предположение копать в сторону работы glitch-free механизма DCS. Стоит отметить, что на репортах не задействуется ни DQCE, ни DCS. Что за DQCE и DCS под спойлером. Спойлер Оба элемента являются частью системы распределения клоков по ПЛИС Gowin Arora. DQCE (Dynamic Quadrant Clock Enable) предоставляет возможность управлять сигналом enable выбранной тактовой частоты для квадранта. DCS (dynamic clock selector) же позволяет переключаться между разными клоками. Подробнее можно прочитать в UG286 Был добавлен блок DCS из доступных ip, в настройках которого можно управлять glitchless mode. После сборки получили такие результаты: glitchless mode = false -> работает нормально glitchless mode = true -> работает ненормально Самой показательной оказалась сборка с добавлением DCS в код так, чтобы можно было управлять glitchless mode со свича на плате. Если будете пробовать, код компонента под стойлером. Спойлер component DCS generic ( DCS_MODE : string := "RISING" ); port ( CLK0 : in std_logic; CLK1 : in std_logic; CLK2 : in std_logic; CLK3 : in std_logic; CLKSEL : in std_logic_vector(3 downto 0); SELFORCE : in std_logic; CLKOUT : out std_logic ); end component; dcs_2 : DCS port map( CLK0 => test_in_clk, CLK1 => '0', CLK2 => '0', CLK3 => '0', CLKSEL => "0001", SELFORCE => SW1, -- переключатель на плате CLKOUT => clk_mod ); В итоге, есть два вышеописанных способа решить проблему, если вы вдруг столкнетесь с таким поведением. Хоть и удалось локализовать проблему, но непонятно, почему прокидывание CLK на пин, не задействует glitch-free. Есть ли у кого какие мысли? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 13 сентября, 2023 Опубликовано 13 сентября, 2023 · Жалоба Говина у меня конечно нет, но ЕМНП, все такие штуки делаются через AND-OR мульиплексор, в управлении которого стоит синхронизатор в домен. И он требует двух тактов частоты, чтобы перещелкнуться. А некоторые ещё требуют наличия всех тактовых частот для переключения. А вот почему он у вас включается по умолчанию, да, интересный вопрос. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tvShushtov 0 13 сентября, 2023 Опубликовано 13 сентября, 2023 · Жалоба Да пусть он включается... можно было бы это запомнить. Но вот почем он иногда отключается, а так же почему он не пишет в репортах, что задействовал DCS? Напрягает неопределенность. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
des00 25 14 сентября, 2023 Опубликовано 14 сентября, 2023 · Жалоба 9 hours ago, tvShushtov said: Да пусть он включается... можно было бы это запомнить. Но вот почем он иногда отключается, а так же почему он не пишет в репортах, что задействовал DCS? Напрягает неопределенность. я бы рыл в сторону документов по разводке тактовых на чипе. Мое вангование: тактовая там разводится через специальные блоки контроля доступа к глобальным линиями, на которые авторы считали что gated clock никогда не будут использоваться (т.е. тактовые всегда есть), поэтому он всегда включен и лишний такт проблемы не представляет. Но когда вы пробрасываете тактовую через порты, софт либо не делает это через глобальную разводку либо включается режим что сигнал может быть любым, в том числе gated clock, а в этом случае, включенние этого блока приведет к не корректной работе) Но багофича интересная, да, не делая асинхронный SPI, на нее сложно наткнуться) А про логи, ну судя по темам на форуме, говин много что не пишет) дело времени. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 215 14 сентября, 2023 Опубликовано 14 сентября, 2023 · Жалоба В 13.09.2023 в 19:55, tvShushtov сказал: Да пусть он включается... можно было бы это запомнить. Но вот почем он иногда отключается, а так же почему он не пишет в репортах, что задействовал DCS? Напрягает неопределенность. Нетлист после PnR смотрели? Он там есть или нет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tvShushtov 0 15 сентября, 2023 Опубликовано 15 сентября, 2023 · Жалоба 14 часов назад, makc сказал: Нетлист после PnR смотрели? Он там есть или нет? Не знаю, как посмотреть PnR нетлист... Поделитесь знаниями - все перерыл, не нашел. Смотрел пост-синтез нетлист - там DCS нет. Привожу два нетлиста для сравнения. Вот нетлист начального проекта: Спойлер module main_2 ( RST, CLK, DIN, clk_la, dout_la ) ; input RST; input CLK; input DIN; output clk_la; output dout_la; wire RST_d; wire CLK_d; wire DIN_d; wire dout_la_d; wire VCC; wire GND; IBUF RST_ibuf ( .O(RST_d), .I(RST) ); IBUF CLK_ibuf ( .O(CLK_d), .I(CLK) ); IBUF DIN_ibuf ( .O(DIN_d), .I(DIN) ); TBUF clk_la_s0 ( .O(clk_la), .I(GND), .OEN(VCC) ); OBUF dout_la_obuf ( .O(dout_la), .I(dout_la_d) ); DFFC DOUT_s0 ( .Q(dout_la_d), .D(DIN_d), .CLK(CLK_d), .CLEAR(RST_d) ); VCC VCC_cZ ( .V(VCC) ); GND GND_cZ ( .G(GND) ); GSR GSR ( .GSRI(VCC) ); endmodule Вот нетлист с добавленным руками DSC: Спойлер module main ( RST, CLK, DIN, clk_la, dout_la ) ; input RST; input CLK; input DIN; output clk_la; output dout_la; wire RST_d; wire CLK_d; wire DIN_d; wire dout_la_d; wire clk_mod; wire VCC; wire GND; IBUF RST_ibuf ( .O(RST_d), .I(RST) ); IBUF CLK_ibuf ( .O(CLK_d), .I(CLK) ); IBUF DIN_ibuf ( .O(DIN_d), .I(DIN) ); TBUF clk_la_s0 ( .O(clk_la), .I(GND), .OEN(VCC) ); OBUF dout_la_obuf ( .O(dout_la), .I(dout_la_d) ); DFFC DOUT_s0 ( .Q(dout_la_d), .D(DIN_d), .CLK(clk_mod), .CLEAR(RST_d) ); DCS dcs_2 ( .CLKOUT(clk_mod), .CLK0(CLK_d), .CLK1(GND), .CLK2(GND), .CLK3(GND), .CLKSEL({GND,GND,GND,VCC}), .SELFORCE(GND) ); defparam dcs_2.DCS_MODE="RISING"; VCC VCC_cZ ( .V(VCC) ); GND GND_cZ ( .G(GND) ); GSR GSR ( .GSRI(VCC) ); endmodule Так же посмотрел анализ путей клока в тайминг репортах - там тоже нет упоминания DSC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 215 15 сентября, 2023 Опубликовано 15 сентября, 2023 · Жалоба 31 минуту назад, tvShushtov сказал: Не знаю, как посмотреть PnR нетлист... Поделитесь знаниями - все перерыл, не нашел. 31 минуту назад, tvShushtov сказал: Смотрел пост-синтез нетлист - там DCS нет. Привожу два нетлиста для сравнения. Там этого обычно не видно, т.к. на фазе мэппинга происходит трансформация нетлиста и добавление служебных элементов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tvShushtov 0 18 сентября, 2023 Опубликовано 18 сентября, 2023 · Жалоба В 15.09.2023 в 15:17, makc сказал: Там этого обычно не видно, т.к. на фазе мэппинга происходит трансформация нетлиста и добавление служебных элементов. Для симуляции файл генерировал - там DSC тоже нет. Смотрел даже VHDL и Verilog на всякий. Спойлер module main_2( RST, CLK, DIN, clk_la, dout_la ); input RST; input CLK; input DIN; output clk_la; output dout_la; wire CLK; wire CLK_d; wire DIN; wire DIN_d; wire GND; wire RST; wire RST_d; wire VCC; wire clk_la; wire dout_la; wire dout_la_d; VCC VCC_cZ ( .V(VCC) ); GND GND_cZ ( .G(GND) ); GSR GSR ( .GSRI(VCC) ); IBUF RST_ibuf ( .I(RST), .O(RST_d) ); IBUF CLK_ibuf ( .I(CLK), .O(CLK_d) ); IBUF DIN_ibuf ( .I(DIN), .O(DIN_d) ); TBUF clk_la_s0 ( .I(GND), .OEN(VCC), .O(clk_la) ); OBUF dout_la_obuf ( .I(dout_la_d), .O(dout_la) ); DFFC DOUT_s0 ( .D(DIN_d), .CLK(CLK_d), .CLEAR(RST_d), .Q(dout_la_d) ); defparam DOUT_s0.INIT=1'b0; endmodule Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tvShushtov 0 25 сентября, 2023 Опубликовано 25 сентября, 2023 · Жалоба Последний вопрос по этой теме (дальше наверное можно закрывать): есть ли у кого на форуме контакт с техподдержкой gowin? Есть ли возможность заслать багрепорт? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
makc 215 25 сентября, 2023 Опубликовано 25 сентября, 2023 · Жалоба 14 минут назад, tvShushtov сказал: Последний вопрос по этой теме (дальше наверное можно закрывать): есть ли у кого на форуме контакт с техподдержкой gowin? Есть ли возможность заслать багрепорт? Может быть у @StewartLittle есть такая возможность. Приглашаем его в тему. 🙂 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
StewartLittle 45 25 сентября, 2023 Опубликовано 25 сентября, 2023 · Жалоба В 25.09.2023 в 13:15, makc сказал: Может быть у @StewartLittle есть такая возможность. Приглашаем его в тему. 🙂 Увы... У Gowin европейская штаб-кавартира находится в Великобритании, так что... На все попытки прямого обращения в китайский саппорт следует отсылка в Лондон. И тем не менее, можно попробовать! Засылайте максимально подробный баг репорт в личку. А там уж как получится. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
longest 0 9 мая Опубликовано 9 мая · Жалоба Столкнулся видимо с этим же глюком, когда отлаживал QSPI slave. Я тоже так и не понял, что принципиально меняется в нетлисте или RTL описание после проброса CLK на выход. Клок QSPI_CLK у меня подключен к обычной ноге плис. Судя по отчету он пробрасывается в линюю глобального клока. Думал попробовать поиграть с этим. Прописал в файле cst: CLOCK_LOC "QSPI_CLK" LOCAL_CLOCK; но это ни как не повлияло на репорт. Клок так и остался глобальным. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Builder 1 15 мая Опубликовано 15 мая · Жалоба А я кажется в каком-то видео слышал про этот глюк и говорили как избавится, если верно запомнил - нужно отключить модууль переключения клока. Попробую поискать видео, а вообще, это не автор делал доклад? UP: нашел: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tvShushtov 0 16 мая Опубликовано 16 мая · Жалоба В 09.05.2024 в 23:12, longest сказал: Клок так и остался глобальным. У вас получилось побороть проблему "костыльным способом" или нужна помощь? Так же интересно, какой версией САПР вы пользовались? 15 часов назад, Builder сказал: вообще, это не автор делал доклад? Да, информация по этой проблеме вошла в доклад моего коллеги Ивана =)) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
longest 0 16 мая Опубликовано 16 мая · Жалоба 8 hours ago, tvShushtov said: У вас получилось побороть проблему "костыльным способом" или нужна помощь? Так же интересно, какой версией САПР вы пользовались? Я просто перед началом работы делаю "пустую" передачу данных. Проблема проявлялась на Gowin_V1.9.8.10 и на Gowin_V1.9.9.02_x64. В следующей ревизии платы заведу QSPI_CLK на ножку GCLKT, как это сделано для GBE ETH_RX_CLK. За одно ожидаю и по времянкам лучшую ситуацию. Хотя вот в DK_START_GW2AR-LV18EQ144PC8I7 гигабитные клоки RXC заведены куда попало и ничего. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться