Jump to content
    

verilog из наглядного i<=i+1 счетчика синтезировать быстрый

Добрый день

Осваиваю плисоводство, на плате MaxII EPM570T100, соответственно quartus 13.0sp1 webedition.

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

//input bit_cntmax, word_cntmax

if (bit_cnt < bit_cntmax) bit_cnt <= bit_cnt + 1;
else bit_cnt <= 0;

if (bit_cnt == bit_cntmax) begin
    if (word_cnt < word_cntmax) word_cnt <= word_cnt + 1;
    else word_cnt <= 0;
end

if (bit_cnt == bit_cntmax && word_cnt == word_cntmax) begin
    if (msg_cnt < MSG_LENGTH) msg_cnt <= msg_cnt + 1;
    else msg_cnt <= 0;
end
        
//output sig = f(bit_cnt, word_cnt, msg_cnt)   

Привычно глазам, в симуляторе тикает как надо, но в железе не успевает.

Можно ли как-то объяснить синтезатору, что тут нужно делать именно счетчики, а не регистры+сумматор+компаратор? Или смириться и привыкать вставлять мегафункции?

 

 

Share this post


Link to post
Share on other sites

19 минут назад, AltairNsk сказал:

Добрый день

Осваиваю плисоводство, на плате MaxII EPM570T100, соответственно quartus 13.0sp1 webedition.

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


//input bit_cntmax, word_cntmax

if (bit_cnt < bit_cntmax) bit_cnt <= bit_cnt + 1;
else bit_cnt <= 0;

if (bit_cnt == bit_cntmax) begin
    if (word_cnt < word_cntmax) word_cnt <= word_cnt + 1;
    else word_cnt <= 0;
end

if (bit_cnt == bit_cntmax && word_cnt == word_cntmax) begin
    if (msg_cnt < MSG_LENGTH) msg_cnt <= msg_cnt + 1;
    else msg_cnt <= 0;
end
        
//output sig = f(bit_cnt, word_cnt, msg_cnt)   

Привычно глазам, в симуляторе тикает как надо, но в железе не успевает.

Можно ли как-то объяснить синтезатору, что тут нужно делать именно счетчики, а не регистры+сумматор+компаратор? Или смириться и привыкать вставлять мегафункции?

 

 

А счетчик это и есть регистр + сумматор. Компаратор ставится когда идет проверка на максимальное значение. Например счетчик считает от 0 до 12.

							if (cnt = 12) then                  -- Когда счетчик досчитал до конца это сравнение и есть компаратор
								cnt <= (others => '0');        
							else
								cnt <= cnt + "1";               -- Иначе продолжим считать  - это и есть сумматор
							end if;

Хотие быстрый счетчик? 

1. Используйте счетчик, который считает от 0 до 2**n -1, который обнуляется переполнением.

			if (rising_edge(clk)) then      
				cnt <= cnt + "1";   
			end if; 

2. Каскадируйте счетчики: например вместо счетчика считающего от 0 до 1023 вы делаете 2 счетчика считающих от 0 до 511.

Первый счетчик на 511 такте выдает сигнал (сигнал выход регистра) разрешающий работу второму счетчику.

			if (rising_edge(clk)) then      
				cnt <= cnt + "1";   
				if cnt = 511 then
					carry <= '1';
				else
					carry <= '0';
				end if;
			end if; 

Второй счетчик работает по сигналу разрешения первого счетчика вы формируете сигнал разрешения работы на регистре.


			if (rising_edge(clk)) then      
				if carry = '1' then
					cnt <= cnt + "1";   
				end if;
			end if; 

3. Атрибуты синтеза при правильном их применении могут творить чудеса:

library altera;
use altera.altera_syn_attributes.all;
...
...
architecture rtl of top is
attribute direct_enable of carry : signal is true;
...
...

 

Share this post


Link to post
Share on other sites

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

Вывод  -если хотите получить именно аппаратные счетчики - вначале расслабьте частоту, и вы их увидите. А когда увидите, постарайтесь переписать дизайн (или просто по другому расставить выводы), чтобы тул и на высокой частоте продолжал их использовать.

Share this post


Link to post
Share on other sites

3 минуты назад, Aleх сказал:

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

Вывод  -если хотите получить именно аппаратные счетчики - вначале расслабьте частоту, и вы их увидите. А когда увидите, постарайтесь переписать дизайн (или просто по другому расставить выводы), чтобы тул и на высокой частоте продолжал их использовать.

Разве в MaxII EPM570T100 есть примитивы готовых счетчиков ?

Share this post


Link to post
Share on other sites

24 минуты назад, AltairNsk сказал:

Привычно глазам, в симуляторе тикает как надо, но в железе не успевает.

На самом деле, есть еще кое-что, что Вы нам не сообщили.

1. Разрядность счетчиков? При большой разрядности и высоким требованиям к частоте, компилятор попытается сделать счетчик с синхронным переносом, а для этого требуется много ресурсов. Хотя Вы можете вручную написать счетчик с параллельным переносом. И тогда все это увидите.

2. Если величины для сравнения: bit_cntmax и word_cntmax заданы не параметрами, а в регистрах, то это тоже жрет много ресурсов при большой разрядности счетчиков.

 

И еще мне не понятно вот это:

if (bit_cnt < bit_cntmax) bit_cnt <= bit_cnt + 1;
else bit_cnt <= 0;

Если bit_cnt < bit_cntmax не выполняется, то это значит, что bit_cnt == bit_cntmax. Тогда по "else bit_cnt <= 0;" Итак счетчик обнулился..

А как тогда будет выполняться следующая строка:

if (bit_cnt == bit_cntmax) begin

Share this post


Link to post
Share on other sites

9 минут назад, iosifk сказал:

А как тогда будет выполняться следующая строка:

Запросто. bit_cntmax — это максималньое значение счётчика.

47 минут назад, AltairNsk сказал:

Добрый день

Осваиваю плисоводство, на плате MaxII EPM570T100, соответственно quartus 13.0sp1 webedition.

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


//input bit_cntmax, word_cntmax

if (bit_cnt < bit_cntmax) bit_cnt <= bit_cnt + 1;
else bit_cnt <= 0;

if (bit_cnt == bit_cntmax) begin
    if (word_cnt < word_cntmax) word_cnt <= word_cnt + 1;
    else word_cnt <= 0;
end

if (bit_cnt == bit_cntmax && word_cnt == word_cntmax) begin
    if (msg_cnt < MSG_LENGTH) msg_cnt <= msg_cnt + 1;
    else msg_cnt <= 0;
end
        
//output sig = f(bit_cnt, word_cnt, msg_cnt)   

Если ваши *_cntmax не меняются в процессе счёта, ну то есть задали *_cntmax, запустили счёт, досчитали, задали новые, то замените сравнени "меньше" на "не равно". При счёте с шагом 1 вы через эти значения не перескочите.

 

40 минут назад, Flip-fl0p сказал:

А счетчик это и есть регистр + сумматор. Компаратор ставится когда идет проверка на максимальное значение.

Ну гругря да, в RTL так и выглядит. Но вообще говоря синтез счётчиков делается немного по-другому: с таблицами переходов, диаграммами Вейча или картами Карно и т. п.: https://radioaktiv.ru/publ/lessons/digitall/132-publ_70.html. Понятно, что сейчас всё это делает синтезатор с учётом того, какие примитивы есть в целевой ПЛИС.

 

Share this post


Link to post
Share on other sites

3 минуты назад, andrew_b сказал:

Запросто. bit_cntmax — это максималньое значение счётчика.

Еще раз медленно...

Если (bit_cnt < bit_cntmax), то это выполняется, то счетчик инкрементируется. Так?

А если не выполняется т.е. это значит, что bit_cnt == bit_cntmax , то срабатывает "else bit_cnt <= 0;" И все... Больше нигде не будет выполняться условие того, что bit_cnt == bit_cntmax. А это и значит, что следующий "if (bit_cnt == bit_cntmax) begin" никогда не выполнится.

Share this post


Link to post
Share on other sites

10 minutes ago, iosifk said:

Еще раз медленно...

...

А это и значит, что следующий "if (bit_cnt == bit_cntmax) begin" никогда не выполнится.

Это шутка такая? :biggrin:

Share this post


Link to post
Share on other sites

22 минуты назад, andrew_b сказал:

Запросто. bit_cntmax — это максималньое значение счётчика.

 

Ну гругря да, в RTL так и выглядит. Но вообще говоря синтез счётчиков делается немного по-другому: с таблицами переходов, диаграммами Вейча или картами Карно и т. п.: https://radioaktiv.ru/publ/lessons/digitall/132-publ_70.html. Понятно, что сейчас всё это делает синтезатор с учётом того, какие примитивы есть в целевой ПЛИС.

 

Ну естественно в цифровой схемотехнике все так и делается. Даже у нас Лабораторные были в университете про синтез счетчиков, с различными видами переносов. Там много различных методик построения счетчиков есть. Но применительно к ПЛИС - синтезатор лепит счетчики из того что есть. А это регистры + лут.

Share this post


Link to post
Share on other sites

21 minutes ago, iosifk said:

На самом деле, есть еще кое-что, что Вы нам не сообщили.

bit_cnt[11:0], word_cnt[3:0], msg_cnt[6:0]; *_cntmax - регистры, значения загружаются перед счетом

 

39 minutes ago, iosifk said:

Если bit_cnt < bit_cntmax не выполняется, то это значит, что bit_cnt == bit_cntmax. Тогда по "else bit_cnt <= 0;" Итак счетчик обнулился..

А как тогда будет выполняться следующая строка:


if (bit_cnt == bit_cntmax) begin

как-то так

always @(posedge clk, posedge rst) begin
	if (rst) begin
  		bit_cnt <= 0;
  	end
    else begin
		if (bit_cnt < bit_cntmax) bit_cnt <= bit_cnt + 1; 
		else bit_cnt <= 0;
	end
end

 

36 minutes ago, iosifk said:

Хотя Вы можете вручную написать счетчик с параллельным переносом.

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

7 minutes ago, Flip-fl0p said:

Но применительно к ПЛИС - синтезатор лепит счетчики из того что есть. А это регистры + лут.

Поглядел что делает megawizard plugin. Похоже, вяжет цепочку LABов по канонам счетчикостроения и оно тикает, если cnt_en. Когда q==bit_cntmax, дёрнуть sclr. От сумматора избавляюсь, верно?

 

Share this post


Link to post
Share on other sites

1 hour ago, AltairNsk said:

Привычно глазам, в симуляторе тикает как надо, но в железе не успевает.

А частота то какая? И спид-грейд девайса тоже важен.

Share this post


Link to post
Share on other sites

1 час назад, AltairNsk сказал:

но в железе не успевает.

А о какой частоте идет речь?

Share this post


Link to post
Share on other sites

6 minutes ago, blackfin said:

А частота то какая? И спид-грейд девайса тоже важен.

100 МГц, EPM570T100C5

Share this post


Link to post
Share on other sites

12 minutes ago, AltairNsk said:

100 МГц, EPM570T100C5 

Не удивительно.

 

Попробуйте так:

reg bit_cnt_fire = 0;

always @(posedge ...) begin
  
if (bit_cnt < bit_cntmax) bit_cnt <= bit_cnt + 1;
else bit_cnt <= 0;

bit_cnt_fire <= (bit_cnt == bit_cntmax - 1);

if (bit_cnt_fire) begin
    if (word_cnt < word_cntmax) word_cnt <= word_cnt + 1;
    else word_cnt <= 0;
end

if (bit_cnt_fire && word_cnt == word_cntmax) begin
    if (msg_cnt < MSG_LENGTH) msg_cnt <= msg_cnt + 1;
    else msg_cnt <= 0;
end

end

 

Share this post


Link to post
Share on other sites

57 минут назад, AltairNsk сказал:

*_cntmax - регистры, значения загружаются перед счетом

Если вам нужно считать до разных значений, то для времянок будет лучше сделать счетчик считающий вниз.

Сравнение будет всегда с нулем (или единицей), а загружаться счетчик должен вашим *_cntmax-1 (или *_cntmax).

Сравнение с нулем в структуре ПЛИС реализуется на схемах ускоренного переноса и будет работать существенно быстрее многоразрядного компаратора с произвольным значением.

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...