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

Подсчитать кол-во единиц в слове

Попробовал на сумматорах, синтезатор выдает 14 уровней логики, и задержку 20.2ns то есть в район. Spartan3, VHDL, ISE.

Затем поставил на входе сумматоров 8 ROM на 256x4, а затем три уровня сумматоров , выдало 13 уровней логики и 16.5ns

После подумал, а если все сделать на ROM в четыре уровня, 8ROM 256x4 затем 4ROM 256x5 затем 2 ROM 1024x6 и наконец 1ROM 4096x7

В результате синтезатор выдал 5 уровней логики и 10.5 ns, это на Spartan3 (-5)

Вполне возможно на быстрой версии Cyclone такой вариант получится на 125MHz, расход на все в районе 8Кb.

Проверьте, может ошибаюсь, но должно получиться по моему.

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


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

Спасибо, воспользовался поводом запустить quartus.

 

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

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

 

Вопросов по большой счету есть только два:

- можно ли задачу обойти двумя-тремя тактами, другой микросхемой или меньшим количеством разрядов ?

- сколько входных битов можно обработать одним LAB-ом ?

 

Второй вопрос вызван тоже двумя вопросами, но поменьше:

- как засунуть в один LAB два асинхронных двухбитных сумматора с входом carry_in и выходом carry_out ?

- можно ли в принципе заставить quartus забить LAB как хочется автору и использовать carry chains ?

 

Без этого больше 120MHz (slow model 85C) не выходит никак, quartus тупит со страшной силой, наверное только терпеливое тыкание его мордой в LogicLock может помочь.

 

Суть подхода такова:

- Определяю как действовать на первой стадии. В cyclone3 LUT 4-х входовой, однако, если пытаться подсчитывать количество единиц на 4 входах, то потребуется 3 LUT-а и соотношение количества информации на входе первой стадии и на выходе будет 4/3, так как количество битов с '1' может быть от 0 до 4, что в двоичной записи требует 3 бита. Если использовать LUT3, то для 3-х входов понадобится только 2 LUT-а, для вариантов 0..3 нужно только два бита, то есть соотношение 3/2, что немного лучше первого варианта. Хотя, на все 64-бита в первом случае получится 48 бит, во втором 44.

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

Можно надеяться, что 12 входов одного LAB-а превратятся в 8 сигналов. Займет это преобрахование 8 LUT-ов.

 

- На вторую стадию напрашивается сложение пары двойки битов. Так как сумматор 0..3+0..3 может дать в результате от 0 до 6, остается одно свободное состояние. Эту ситуацию можно исправить, если на вход CARRY сумматора подать еще один исходный сигнал. Каждый сумматор займет 2 LUT-а, старший бит суммы является CARRY_OUT. Мне это сделать пока не удалось, не умею я готовить quartus. Если получится, то к 12 входам добавится еще 2, а на выходе будут те же 2 раза по 3 бита. Займет вторая стадия 4 LUT-а с их CARRY-цепочками. Суммарное соотношение входной информации к выходной заметно улучшится.

 

- Третья стадия имеет полное право поместиться в оставшиеся 4 LUT-а данного LAB-а, хотя мне кажется, что и трёх должно хватить. Итого, на входе 14 битов, на выходе 4 бита содержащих количество единиц.

 

Чтобы этим хозяйством можно было сосчитать 64(70)-бит, понадобится 5 таких блоков и сумматор 5 раз по 4 бита на 4-ом уровне, он и поест все время.

 

Вопрос: как же в исходном тексте в этом quartus-е управлять низкоуровневым синтезом, размещением внутри LAB-а, относительно соседних LAB-ов? Есть ли механизмы для создания макросов, вроде xilinx-овых RLOC? Неужели снова LogicLoc и констрейны?!

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

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

 

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


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

ВСЕМ СПАСИБО! Теперь надобно решить, либо хитрить и считать все-таки на 125 МГц, либо логику переделывать. Поже все-таки логику переделывать. Судя по Вашим оценкам экспертов, если и будет на 125МГц работать, то с натягом, сильным, и ресурсов это как-то много займет. А мне как-то не нравится, когда с натягом работает. Я спокоен только когда 1,5 кратный запас :biggrin: .

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


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

Судя по Вашим оценкам экспертов, если и будет на 125МГц работать, то с натягом, сильным, и ресурсов это как-то много займет. А мне как-то не нравится, когда с натягом работает. Я спокоен только когда 1,5 кратный запас :biggrin: .

Вам же дали ссылки. Первая ссылка немного о другом, там поиск лидирующей единицы, а вторая как раз в тему. Там много вариантов.

alexPec, уважаемый des00 был как всегда точен, тем было несколько, ищутся легко, вот пара на вскидку:

Сумма единиц

Есть ли стандартная функция

Я из интереса проделал аналогичный эксперимент с CycloneIII. На медленной модели при 85С получилась частота 143,5МГц. По-моему, достаточный запас. И сама схема занимает всего 119 логических элементов (не учитывая входные регистры, без которых не посчитать тактовую частоту).

module cnt64(clk,rst,din,cnt);

input clk,rst;
input  [63:0] din;
output reg [6:0] cnt;

reg [63:0] dreg;
reg [6:0] comb_cnt;

wire [2:0] s[15:0];
reg [3:0] s0[7:0];
reg [4:0] s1[3:0];
reg [5:0] s2[1:0];

//ones in four bits
function [2:0] cnt8;
input [3:0] din;
integer i;
begin
	cnt8=0;
	for(i=0; i<=3; i=i+1) if (din[i]) cnt8=cnt8+1;
end
endfunction

//registers
always @(posedge clk or negedge rst) begin
	if (!rst) 
	begin
		cnt<=0; dreg<=0;
	end
	else 
	begin
		cnt<=comb_cnt; dreg<=din;
	end
end

//adder tree
always @(*)
begin
	//first level
	s0[0]=s[0]+s[1]; s0[1]=s[2]+s[3]; s0[2]=s[4]+s[5]; s0[3]=s[6]+s[7];
	s0[4]=s[8]+s[9]; s0[5]=s[10]+s[11]; s0[6]=s[12]+s[13]; s0[7]=s[14]+s[15];
	//second level
	s1[0]=s0[0]+s0[1]; s1[1]=s0[2]+s0[3]; s1[2]=s0[4]+s0[5]; s1[3]=s0[6]+s0[7];
	//third level
	s2[0]=s1[0]+s1[1]; s2[1]=s1[2]+s1[3];
	//fourth level
	comb_cnt=s2[0]+s2[1];
end

//preadders
genvar j;
generate
	for(j=0; j<=15; j=j+1) 
	begin : os
		assign s[j]=cnt8(dreg[j*4+:4]);
	end
endgenerate

endmodule

P.S. При включении Fitter effort = Standard получается 156МГц, а при задействовании входных переносов в дереве сумматоров (как предложено в указанной выше теме) и избавления, таким образом, от одного сумматора первого уровня, комбинаторика получается еще на 7 элементов меньше и частота поднимается до 159МГц. Можно и дальше оптимизировать и искать варианты, но требования и так выполняются с запасом.

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


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

...Я из интереса проделал аналогичный эксперимент с CycloneIII. На медленной модели при 85С получилась частота 143,5МГц. По-моему, достаточный запас... 

 

Так Вы проверяете на C6, а автор просил на С8.  :)

 

 

 

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


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

Так Вы проверяете на C6, а автор просил на С8.  :)

Вроде как сначала были неопровергнутые сомнения, что получится и на быстрой градации. :) На 6 и 7 градации получается. На EP3C5 даже на 8 градации модификация с разбросом 8 бит из 64-х по входам переноса в дереве сумматоров укладывается в 125МГц. Можно и дальше поколдовать с архитектурой и попробовать выжать на больших микросхемах. Но разница в стоимости между 7 и 8 градацией меня в данном случае не мотивирует. :)

 

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

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


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

Все что я выше написал про реализацию на ROM оказалось полной чушью, прошу прощения у автора топика. Но зато попробовал изменить код представленный Sergey'F

 

Загнал вышеприведенный код суммирования на Verilog, вот что выдал Synplify 9.6 (установки по умолчанию, я в нем не слишком пока ориентируюсь)

EP3C5, FC256, -6
                  Requested     Estimated     Requested     Estimated                Clock        Clock                
Starting Clock     Frequency     Frequency     Period        Period        Slack      Type         Group                
------------------------------------------------------------------------------------------------------------------------
cnt64|clk          160.6 MHz     136.5 MHz     6.227         7.325         -1.099     inferred     Autoconstr_clkgroup_0
================================================================================

 

То есть на -6 выдает частоту 136.5 MHz

 

А затем я решил, просуммировать 64 единицы и выкинуть все массивы из кода вообще. В результате получились вот такие результаты (установки те же)

EP3C5, FC256, -8   Requested     Estimated     Requested     Estimated                Clock        Clock                
Starting Clock     Frequency     Frequency     Period        Period        Slack      Type         Group                
------------------------------------------------------------------------------------------------------------------------
top|clk            178.7 MHz     151.9 MHz     5.596         6.584         -0.988     inferred     Autoconstr_clkgroup_0
===========================================================================

EP3C5, FC256, -6   Requested     Estimated     Requested     Estimated                Clock        Clock                
Starting Clock     Frequency     Frequency     Period        Period        Slack      Type         Group                
------------------------------------------------------------------------------------------------------------------------
top|clk            237.7 MHz     202.1 MHz     4.206         4.949         -0.742     inferred     Autoconstr_clkgroup_0
===========================================================================

 

На версии -8 влезаем в 150MHz, а на -6 можно работать до 200MHz

 

Вот код на VHDL

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity top is
	port	(  clk,rst : in std_logic;
				di : in std_logic_vector(63 downto 0);
				q : out std_logic_vector(6 downto 0)
				);
end top;
architecture rtl of top is
component add2 is 
  port ( d : in std_logic_vector(63 downto 0);
  	    q : out std_logic_vector(6 downto 0));
end component;					  
signal sdat : std_logic_vector (6 downto 0);--sdat_array;
signal dreq : std_logic_vector (63 downto 0);

begin
ADD_21: add2 port map( d=>dreq, q=>sdat);

process(clk)
begin
if(clk='1' and clk'event) then
if(rst = '1') then
 dreq <= (others=>'0');
 q <= (others=>'0');
else
 dreq <= di;
 q <= sdat;--comb_cnt;
end if; 
end if; 
end process;

end rtl;


-- add 4-to-cnt8  preadder 
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity add2 is 
   port ( d : in std_logic_vector(63 downto 0);
		  q : out std_logic_vector(6 downto 0));
end add2;					  
architecture rtl of add2 is
begin
q <= conv_std_logic_vector(
		conv_integer(d(63)) + conv_integer(d(62)) + conv_integer(d(61)) + conv_integer(d(60)) +
		conv_integer(d(59)) + conv_integer(d(58)) + conv_integer(d(57)) + conv_integer(d(56)) +
		conv_integer(d(55)) + conv_integer(d(54)) + conv_integer(d(53)) + conv_integer(d(52)) +
		conv_integer(d(51)) + conv_integer(d(50)) + conv_integer(d(49)) + conv_integer(d(48)) +
		conv_integer(d(47)) + conv_integer(d(46)) + conv_integer(d(45)) + conv_integer(d(44)) +
		conv_integer(d(43)) + conv_integer(d(42)) + conv_integer(d(41)) + conv_integer(d(40)) +
		conv_integer(d(39)) + conv_integer(d(38)) + conv_integer(d(37)) + conv_integer(d(36)) +
		conv_integer(d(35)) + conv_integer(d(34)) + conv_integer(d(33)) + conv_integer(d(32)) +
		conv_integer(d(31)) + conv_integer(d(30)) + conv_integer(d(29)) + conv_integer(d(28)) +
		conv_integer(d(27)) + conv_integer(d(26)) + conv_integer(d(25)) + conv_integer(d(24)) +
		conv_integer(d(23)) + conv_integer(d(22)) + conv_integer(d(21)) + conv_integer(d(20)) +
		conv_integer(d(19)) + conv_integer(d(18)) + conv_integer(d(17)) + conv_integer(d(16)) +
		conv_integer(d(15)) + conv_integer(d(14)) + conv_integer(d(13)) + conv_integer(d(12)) +
		conv_integer(d(11)) + conv_integer(d(10)) + conv_integer(d(9)) + conv_integer(d(8)) +
		conv_integer(d(7)) + conv_integer(d(6)) + conv_integer(d(5)) + conv_integer(d(4)) +
		conv_integer(d(3)) + conv_integer(d(2)) + conv_integer(d(1)) + conv_integer(d(0)),7);
end rtl;

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


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

А что говорит TimeQuest после размещения и разводки?

Уверен, что на этой задаче Synplify выдает желаемое за действительное, половину времени сожрет интерконнект.

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


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

У меня нет Квартуса и возможности пока поставить нет. Согласен, Synplify тут возможно горячится.

В ISE на Spartan3 лучшие результаты показывает дизайн где в preadder первые 4 бита вот так, как выше через конверсию целых чисел, а затем массивы.

Для Cyclone надо смотреть, но путь оптимизации мне например ясен, подменять массивы сумматорами с входа по 4 или 8 или 16 бит, а остальное массивами.

Какой из них покажет лучшие результаты тот и брать. Как поставлю Квартус, выложу свои результаты.

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


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

А что говорит TimeQuest после размещения и разводки?

Уверен, что на этой задаче Synplify выдает желаемое за действительное, половину времени сожрет интерконнект.

 

Если этот код скомпилить в Quartus'е, то для C8 получаем 78 МГц.  :laughing:

 

 

 

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


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

Задача далеко за рамками обычного промышленного синтеза.

Без учета архитектуры ячейки и интерконнекта получить результаты немногим лучше 100MHz трудно.

Без использования архитектуро-зависимых примитивов больше 119 MHz получить не выходит, хотя есть ощущение,

что quartus просто дурачится и можно сделать лучше.

Описывать обычным языком VHDL или verilog и надеяться на хороший синтез не приходится, так как должен получиться вполне конкретный результат, а синтезатор не говорит, что именно программист сделал не так и почему синтезировалось так, а не эдак. Например, quartus сообщает, что проигнорировал буфер carry_sum, lut_output или cascade, но не говорит почему.

 

Главное, как я считаю, заставить один LAB обрабатывать побольше входных сигналов, так как быстрый интерконнект LAB-а очень полезен, а забитый под завязку LAB по определению быстрее нескольких полупустых.

Научите меня контролировать размещение LUT-ов в LAB-е и принудительно соединять LUT-ы через carry цепочки.

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

У Зайлингс в таких случаях задача решается применением низкоуровневых примитивов и атрибутов RLOC для указания относительного размещения ячеек.

И хотя я сердцем больше люблю Альтеру, работаю чаще с Зайлингс. Так вот синтезатор последнего XST не пытается игнорировать мои команды, а если они противоречат возможностям микросхемы, то их не игнорирует, а останавливает синтез с внятным сообщением.

 

Мои изыскания закончились следующим:

 

1) для кодирования количества единиц на N входах нужно log2(N+1) бит, так как считать нужно с нуля до N.

Казалось бы, чем больше входов у LUT-а, тем выгоднее, но 4-х входовые LUT-ы оказываются совсем некудышными. 3 LUT-а на 4 входа и из 8-ми состояний только 5 полезных. Если применить 3-х входовые LUT-ы, то потребуется 2 LUT-а на 3 входа. А если учесть, что один 4-х входовой LUT в арифметическом режиме превращается в 2 LUT3, то и совсем интересно выходит. Все хорошо, если не учесть, что один из выходов - это CARRY ведущий вниз и только второй выход идет на быстрый интерконнект LAB-а и наружу.

 

2) Ну и замечательно, пусть один из выходов будет carry_out, его мы можем использовать в качестве carry_in младшего бита сумматора. Второй выход LUT-ов нижнего уровня подать на второй бит этого сумматора. Итого, получается 3 LUT-а на 5 входов. Не очень густо, но лучше, чем на 4. Старший бит результата выходит на carry, что с одной стороны плохо, а с другой полезно. Если ниже расположен младший бит сумматора следующего уровня, то полезно.

 

3) Выходы сумматоров первого уровня попадают на сумматоры второго уровня, у которых тоже есть пустой вход carry_in. На него можно подать дополнительный входной сигнал. То есть, если на нижнем уровне суммируется 5 сигналов, то на следующем 5+5+1=11. На втором уровне 11+11+1=23, и т.д.

 

В общем, идею можно развить, вылизать и реализовать, но это требует усилий, в основном по борьбе с синтезатором и mapper-ом. Кстати, подозреваю, что использование synplify или другого синтезатора поможет для получения netlist с необходимыми буферами.

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


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

Задача далеко за рамками обычного промышленного синтеза.

Без учета архитектуры ячейки и интерконнекта получить результаты немногим лучше 100MHz трудно.

Ну это уже не смешно. Извините, Вы то, что я выше написал, читали?

 

Повторюсь:

QII 9.1, Таймквест, медленная модель, 85С. На любом Cyclone III градации 6 и 7, что я пробовал, укладывается в 125МГц. Код с разбрасыванием 8 бит из 64 по входам дерева сумматоров приводить не буду - это тривиально. Он ненамного быстрее того, что я привел. Самое быстрое, что я получил на нем - 159МГц.

 

Это не значит, что нельзя сделать лучше - просто дальше нет интереса идти. И никаких LogicLock, архитектурно зависимых примитивов и т.д.. Чем и хороша Altera по сравнению с некоторыми другими производителями. :)

 

По поводу идей:

Четырехвходовые LUT на первом уровне как раз очень подходят. В отличие от предлагаемых Вами трехвходовых, они уменьшают глубину дерева сумматоров на один уровень и сами обрабатывают 4 бита в один слой логики, без переносов, которые, хоть и быстрые, но вносят задержку. Замечу, что синтезатор все синтезирует как написано без всяких примитивов - на первом уровне под каждую группу из 4 бит по 3 LUT, а далее складываем 16 (в случае с разбросом 8 бит - 14) таких сумм на 4 уровнях сумматоров. Кстати, если не разбрасывать, он очень четко делает первый уровень в нормальном режиме, а все следующие с цепями переноса.

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


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

У меня за мои суммарные час попыток на С8 выжать 125 МГц так и не удалось. :)

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


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

У меня за мои суммарные час попыток на С8 выжать 125 МГц так и не удалось. :)

Вот проект :). Компилировался в 9.1 без SP.

cnt64.zip

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


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

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

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

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

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

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

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

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

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

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