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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this