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

Gowin. Баг с защелкиванием первых данных в Source Synchronous интерфейсе

Обнаружили с коллегами любопытный баг, когда писали код spi-slave устройства для GW2A. Для отладки код был упрощен до минимума и фактически превратился в одиночный триггер (см. картинку).

RST, CLK, DIN – входные порты, на которых формируется сигнал, согласно временной диаграмме ниже. Для теста я формирую их с помощью другой отладочной платы с ПЛИС. DOUT – защелкнутый триггером сигнал DIN. MUST – то, что должно было быть защелкнуто на триггере.

1.thumb.png.b3ec87a74db1b44823dd8e92cb999b25.png2.png.fcd81e196d1b0356c757fd305511a2ae.png

Если хотите пробовать повторить багу, то я оставлю оба кода источника и приемника под спойлером.

Спойлер
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:

3.png.5f9d69e4ec6631ee0e24aa1eb2de16d6.png

Для всех, кроме первой, итераций схема функционирует корректно вплоть до выключения питания/перепрошивки.

Чтобы исключить из рассмотрения GAO, выходной сигнал был выведен на пин и подключен к логическому анализатору вместе в входными RST и CLK. Картина оказалась аналогичной.

Уточню, как выглядит схематик синтезированного кода, также посмотрим на то, какие ресурсы задействовал компилятор. Собирал я все на нескольких версиях софта. Самый последний тест был на Gowin EDA 1.9.9 (build 65859).

Спойлер

4.thumb.png.8ba48137b9748ba07aa8e5d3c1034d8f.png
5.thumb.png.084b3416817c6b7ab681ae9269152e1d.png

Самый простой способ, который позволяет вернуть «адекватную» работоспособность триггеру, это проброс входного сигнала CLK на выходной пин (раскомментировать строчку "clk_la  <= CLK" в коде). Совершенно непонятно по какой причине в этом случае баг пропадает.

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

Спойлер
  1. Менял пины двойного назначения на обычные.
    Не помогло
  2. Попробовал инвертировать клок перед подачей на триггер.
    Не помогло
  3. Сделал триггер без асинхронного сброса.
    Не помогло
  4. Вывел клок на глобальную линию через BUFG компонент.
    Не помогло
  5. Добавил дополнительный триггер на те же входы. Fanout=2.
    Не помогло
  6. Пробую подключить клок насильно через DQCE.
    Не помогло + теперь не помогает подключение выхода DQCE на выходной порт.

Решающим оказалось предположение копать в сторону работы glitch-free механизма DCS. Стоит отметить, что на репортах не задействуется ни DQCE, ни DCS. Что за DQCE и DCS под спойлером.

Спойлер

Оба элемента являются частью системы распределения клоков по ПЛИС Gowin Arora. DQCE (Dynamic Quadrant Clock Enable) предоставляет возможность управлять сигналом enable выбранной тактовой частоты для квадранта. DCS (dynamic clock selector) же позволяет переключаться между разными клоками.
6.png.d33ec350ebd5d4c9516dde58d478f350.png
Подробнее можно прочитать в 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. Есть ли у кого какие мысли?

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


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

Говина у меня конечно нет, но ЕМНП, все такие штуки делаются через AND-OR мульиплексор, в управлении которого стоит синхронизатор в домен. И он требует двух тактов частоты, чтобы перещелкнуться. А некоторые ещё требуют наличия всех тактовых частот для переключения. 

А вот почему он у вас включается по умолчанию, да, интересный вопрос. 

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


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

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

Напрягает неопределенность.

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


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

9 hours ago, tvShushtov said:

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

Напрягает неопределенность.

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

Но багофича интересная, да, не делая асинхронный SPI, на нее сложно наткнуться)  А про логи, ну судя по темам на форуме, говин много что не пишет) дело времени. 

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


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

В 13.09.2023 в 19:55, tvShushtov сказал:

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

Напрягает неопределенность.

Нетлист после PnR смотрели? Он там есть или нет?

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


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

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.

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


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

31 минуту назад, tvShushtov сказал:

Не знаю, как посмотреть PnR нетлист... Поделитесь знаниями - все перерыл, не нашел.

image.thumb.png.d093d9aa21104826a6406b7fdd03012d.png

31 минуту назад, tvShushtov сказал:

Смотрел пост-синтез нетлист - там DCS нет. Привожу два нетлиста для сравнения.

Там этого обычно не видно, т.к. на фазе мэппинга происходит трансформация нетлиста и добавление служебных элементов.

 

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


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

В 15.09.2023 в 15:17, makc сказал:

image.thumb.png.d093d9aa21104826a6406b7fdd03012d.png

Там этого обычно не видно, т.к. на фазе мэппинга происходит трансформация нетлиста и добавление служебных элементов.

 

Для симуляции файл генерировал - там 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

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


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

Последний вопрос по этой теме (дальше наверное можно закрывать): есть ли у кого на форуме контакт с техподдержкой gowin? Есть ли возможность заслать багрепорт?

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


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

14 минут назад, tvShushtov сказал:

Последний вопрос по этой теме (дальше наверное можно закрывать): есть ли у кого на форуме контакт с техподдержкой gowin? Есть ли возможность заслать багрепорт?

Может быть у @StewartLittle есть такая возможность. Приглашаем его в тему. 🙂

 

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


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

В 25.09.2023 в 13:15, makc сказал:

Может быть у @StewartLittle есть такая возможность. Приглашаем его в тему. 🙂

Увы...

У Gowin европейская штаб-кавартира находится в Великобритании, так что...

На все попытки прямого обращения в китайский саппорт следует отсылка в Лондон.

 

И тем не менее, можно попробовать! Засылайте максимально подробный баг репорт в личку. А там уж как получится.

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


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

Столкнулся видимо с этим же глюком, когда отлаживал QSPI slave. Я тоже так и не понял, что принципиально меняется в нетлисте или RTL описание после проброса CLK на выход. Клок QSPI_CLK у меня подключен к обычной ноге плис. Судя по отчету он пробрасывается в линюю глобального клока. Думал попробовать поиграть с этим. Прописал в файле cst: CLOCK_LOC "QSPI_CLK" LOCAL_CLOCK; но это ни как не повлияло на репорт. Клок так и остался глобальным.

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


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

А я кажется в каком-то видео слышал про этот глюк и говорили как избавится, если верно запомнил - нужно отключить модууль переключения клока. Попробую поискать видео, а вообще, это не автор делал доклад?

UP: нашел: 

 

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


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

В 09.05.2024 в 23:12, longest сказал:

Клок так и остался глобальным.

У вас получилось побороть проблему "костыльным способом" или нужна помощь? Так же интересно, какой версией САПР вы пользовались?

15 часов назад, Builder сказал:

вообще, это не автор делал доклад?

Да, информация по этой проблеме вошла в доклад моего коллеги Ивана =))

 

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


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

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 заведены куда попало и ничего. 

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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