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

Накапливающий сумматор, введение латентности

Добрый день всем. Создаю один проект на больших скоростях и мне там необходимо складывать и накапливать большие значения (разрядность вектора более 50).  Естественно проседает быстродействие и необходимо ввести латентность на сумматоре (хотя бы 2). На вход сумматора подаётся значения, которые изменяют по линейному закону с каким-то произвольным коэффициентом. Например входные данные могут быть 1,2,3,4,5 и т.д. А на выходе соответственно получаем 1,3,6,10,15. 

Схема классическая: выход сумматора падает на вход регистра, а его выход на второй вход сумматора. Регистр может инициировать любым значением перед началом работы. Классический аккумулятор!

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

У кого-нибудь есть мысли, как увеличить быстродействие??

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


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

 

49 минут назад, mixa7109 сказал:

У кого-нибудь есть мысли, как увеличить быстродействие??

Вот так:

Acc.png.6058a2313e3f140247d2ce37b48f59ba.png

 

+ Retiming

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


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

4 hours ago, Самурай said:

 

Вот так:

Acc.png.6058a2313e3f140247d2ce37b48f59ba.png

 

+ Retiming

либо ваш вход, дециматор(счетный триггер) и обычный аккумулятор на выходе + мультицикл)

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


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

10 часов назад, Самурай сказал:

 

Вот так:

Acc.png.6058a2313e3f140247d2ce37b48f59ba.png

 

+ Retiming

Вот описал схему.

n_reset_adder <= miStart and n_reset;
    
    add_sub1: lpm_add_sub
    generic map 
        (
            lpm_direction     => "UNUSED",
            lpm_representation => data_type,
            lpm_width        => WIDTH_RG
        )
    port map
        (
            clock        => clk,
            clken        => miValid,
            aclr        =>    not n_reset_adder,
            add_sub  => miType,
            dataa        => data_reg,
            datab        => wire_dataB(0),
            result    => wire_out(0)
        );
        
        process(clk, n_reset)
        begin
            if n_reset = '0' then
            elsif rising_edge(clk) then
                wire_dataB(0) <= data_reg;
                wire_dataB(2) <= wire_out(1);
                wire_dataB(2) <= wire_dataB(1);
            end if;
        end process;
    
    add_sub2: lpm_add_sub
    generic map 
        (
            lpm_direction     => "UNUSED",
            lpm_representation => data_type,
            lpm_width        => WIDTH_RG
        )
    port map
        (
            clock        => clk,
            clken        => miValid,
            aclr        =>    not n_reset_adder,
            add_sub  => miType,
            dataa        => wire_out(0),
            datab        => wire_dataB(2),
            result    => wire_out(1)
        );
        
        moData <= wire_out(1);

    data_reg(WIDTH_DATA - 1 downto 0) <= miData;

Результат не сходится с ожиданием, что я не так делаю? 

image.thumb.png.8fe44655dbb9929a79af4142ddb66d1c.png

А вот схема из квартуса

image.thumb.png.f5a10907c57a634e8aabeb964eb2f305.png

 

Изменено пользователем mixa7109

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


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

Приветствую!

11 hours ago, mixa7109 said:

У кого-нибудь есть мысли, как увеличить быстродействие??

Вариантов  несколько:

Первый  считать  двумя  сумматорами  отдельно четные и нечетные отсчеты, что в купе с multicycle констрейнами  сделает виртуальную частоту  счета в 2 раза ниже,

Второй  - "разделить"  сумматор pipeline регистрами  на несколько стадий (по N/2  бит) с регистром в цепи переноса между ними что уменьшит  критическую длину  логики сумматора. 

 

Удачи! Rob. 

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


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

4 минуты назад, RobFPGA сказал:

Приветствую!

Вариантов  несколько:

Первый  считать  двумя  сумматорами  отдельно четные и нечетные отсчеты, что в купе с multicycle констрейнами  сделает виртуальную частоту  счета в 2 раза ниже,

Второй  - "разделить"  сумматор pipeline регистрами  на несколько стадий (по N/2  бит) с регистром в цепи переноса между ними что уменьшит  критическую длину  логики сумматора. 

 

Удачи! Rob. 

Можно поподробнее про первый вариант? Пытался его реализовать, но на выходные получалось опять же не то

, что надо

Изменено пользователем mixa7109

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


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

32 минуты назад, mixa7109 сказал:

Результат не сходится с ожиданием, что я не так делаю? 

process(clk, n_reset)
        begin
            if n_reset = '0' then
            elsif rising_edge(clk) then
                wire_dataB(0) <= data_reg;
                wire_dataB(2) <= wire_out(1); -- Должно быть так: wire_dataB(1) <= wire_out(1);  
                wire_dataB(2) <= wire_dataB(1);
            end if;
        end process;

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


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

Только что, Самурай сказал:

process(clk, n_reset)
        begin
            if n_reset = '0' then
            elsif rising_edge(clk) then
                wire_dataB(0) <= data_reg;
                wire_dataB(2) <= wire_out(1); -- Должно быть так: wire_dataB(1) <= wire_out(1);  
                wire_dataB(2) <= wire_dataB(1);
            end if;
        end process;

Я этот момент исправил, я когда построил rtl схему, увидел, что не так, а вот поправить в сообщении забыл. Вообщем, там так, как "должно быть так"

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


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

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

Я этот момент исправил, я когда построил rtl схему, увидел, что не так, а вот поправить в сообщении забыл. Вообщем, там так, как "должно быть так"

Тогда подозреваю, что Вам надо добавить в секцию generic map для lpm_add_sub вот такую строчку:

LPM_PIPELINE => 0,

Изменено пользователем Самурай

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


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

Приветствую!

38 minutes ago, mixa7109 said:

Можно поподробнее про первый вариант? Пытался его реализовать, но на выходные получалось опять же не, что надо

Делите поток на четные/нечетные отсчеты, задерживаете четные на 1 такт,  получаете  2 потока  с вдвое меньшей частотой  обновления,  накапливаете в 2 сумматорах,  выход с которых тоже суммируете.

Но  в вашем случае думаю проще  второй вариант  c pipeline сумматора. И обновления суммы каждый  такт, и  головной боли с констрейнами не будет.

Spoiler

assign  {din_h, din_l} = din;

assign sum = {sum_h1, sum_l1};

always_ff @(posedge clk) begin
  clear0 <= clear;

  if (clear) begin
    {cy0, sum_l0} <= '0;
    din_h0        <= '0;
  end
  else begin
    {cy0, sum_l0} <= sum_l0 + din_l;
    din_h0        <= din_h;
  end

  if (clear0) begin
    sum_l1 <= '0;
    sum_h1 <= '0;
  end
  else begin
    sum_l1 <= sum_l0;
    sum_h1 <= sum_h1 + din_h0 + cy0;
  end
end

 

Удачи! Rob.      

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


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

2 часа назад, RobFPGA сказал:

Приветствую!

Делите поток на четные/нечетные отсчеты, задерживаете четные на 1 такт,  получаете  2 потока  с вдвое меньшей частотой  обновления,  накапливаете в 2 сумматорах,  выход с которых тоже суммируете.

Но  в вашем случае думаю проще  второй вариант  c pipeline сумматора. И обновления суммы каждый  такт, и  головной боли с констрейнами не будет.

  Скрыть содержимое


assign  {din_h, din_l} = din;

assign sum = {sum_h1, sum_l1};

always_ff @(posedge clk) begin
  clear0 <= clear;

  if (clear) begin
    {cy0, sum_l0} <= '0;
    din_h0        <= '0;
  end
  else begin
    {cy0, sum_l0} <= sum_l0 + din_l;
    din_h0        <= din_h;
  end

  if (clear0) begin
    sum_l1 <= '0;
    sum_h1 <= '0;
  end
  else begin
    sum_l1 <= sum_l0;
    sum_h1 <= sum_h1 + din_h0 + cy0;
  end
end

 

Удачи! Rob.      

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

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


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

Наверное, имеется ввиду загрузить в чётный аккумулятор ноль, в нечётный А, затем суммировать каждый с 2А и чередовать выходы.

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


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

Приветствую!

3 hours ago, mixa7109 said:

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

Ко второму варианту:

sum.jpg

 

Успехов! Rob. 

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


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

Вообщем вот такая упрощенная схемы вышла у меня.
Если кому-то интересна реализация этой схемы на vhdl пишите)

adder.jpg

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


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

Приветствую!

Just now, mixa7109 said:

Вообщем вот такая упрощенная схемы вышла у меня.
Если кому-то интересна реализация этой схемы на vhdl пишите)

Выход cout тоже должен  проходит через регистр  иначе эта схема смысла не имеет. 

 

Удачи! Rob.

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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