Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: DDS
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Работаем с ПЛИС, области применения, выбор
kkosik
Вообщем, в продолжение темы многоразрядного накопительного сумматора...

Удалось-таки его написать, но при моделировании с учетом задержек в кристалле (после place&route) оказалось, что при суммировании числа (1111... + A) происходит огроменная задержка (т.е. старшие разряды числа долго-долго перекидываются в 0000...).
Суммируем по фронту испульса, а значение из таблицы синусов в соответствии с 10 старшими разрядами суммы выдается по срезу. Т.о. задержка суммирования "залазит" на срез. Из-за этого на выход по таблице синусов отчего-то выдается значение, которого в этой таблице в принципе нет!!
Тактовая частота 40 МГц, плис Actel apa300.

Кто что может посоветовать? wacko.gif
TRILLER
Я бы вам посоветовал сделать всю схему только по фронту.
kkosik
Боюсь, что все организованные процессы по фронту могут вызвать "гонки и состязания"...
Timmy
Цитата(kkosik @ Sep 28 2012, 13:59) *
Боюсь, что все организованные процессы по фронту могут вызвать "гонки и состязания"...

Срочно начинайте изучать принципы синхронного дизайна.
bogaev_roman
Цитата(kkosik @ Sep 28 2012, 11:03) *
Удалось-таки его написать, но при моделировании с учетом задержек в кристалле (после place&route) оказалось, что при суммировании числа (1111... + A) происходит огроменная задержка (т.е. старшие разряды числа долго-долго перекидываются в 0000...).
Тактовая частота 40 МГц, плис Actel apa300.

Если работаете и по фронту и по срезу, то анализ реально ведется по 80МГц. Эта огроменная задержка возникает из-за большого кол-во CELL или IC от одного CELL в другой?
Bad0512
Цитата(kkosik @ Sep 28 2012, 14:03) *
Вообщем, в продолжение темы многоразрядного накопительного сумматора...

Удалось-таки его написать, но при моделировании с учетом задержек в кристалле (после place&route) оказалось, что при суммировании числа (1111... + A) происходит огроменная задержка (т.е. старшие разряды числа долго-долго перекидываются в 0000...).
Суммируем по фронту испульса, а значение из таблицы синусов в соответствии с 10 старшими разрядами суммы выдается по срезу. Т.о. задержка суммирования "залазит" на срез. Из-за этого на выход по таблице синусов отчего-то выдается значение, которого в этой таблице в принципе нет!!
Тактовая частота 40 МГц, плис Actel apa300.

Кто что может посоветовать? wacko.gif

На 40 МГц даже 40-разрядный сумматор будет работать без проблем. Сдаётся мне, что вы сумматор этот криво описываете. В общем, код - в студию!
Serhiy_UA
Есть такой прием с конвейеризацией.
Вместо одного длинного сумматора используют три но покороче: один для сложений младшей части и два других для старшей.
Младшая часть суммируется как обычно, и в регистре записываются младшая сумма и бит переноса из младшей части.
Два других сумматора также суммируют старшие части, но один +1 в младшем разряде, а другой без неё.
Результаты всех сумматоров записываются в регистрах. Это есть первое звено конвейера.
Во втором звене используется многоразрядный коммутатор 2 а 1, на входы которого подаются разряды регистров от сумматоров старших частей. А управляется коммутатор с регистра бита переноса. Выход коммутатора и регистр младшей суммы и составляют полный результат.
Вот такая вот конвейеризация, здесь можно получить большую частоту суммирования, но есть некая транспортная задержка конвейера…

Этот прием описан в доке от Xilinx, найти пока не могу....

Применял это прием при суммировании нескольких чисел, с конвейером.
yes
Цитата(Bad0512 @ Sep 28 2012, 15:06) *
На 40 МГц даже 40-разрядный сумматор будет работать без проблем. Сдаётся мне, что вы сумматор этот криво описываете. В общем, код - в студию!


с проазиками дело имели? это не ксайлинсы sm.gif

автору:

если накопительный сумматор, то часто (зависит от приложения) его можно описать в виде нескольких коротких сумматоров с защелкиванием CARRY-ей между секциями

как-то так
always @(posedge clk)
begin
sum[39:20] <= sum[39:20] + adder[39:20] + co;
{co,sum[19:0]} <= {1'b0,sum[19:0]} + adder[19:0];
end

ну и так далее, при необходимости можно резать не на 2 а на 3,4,5 и т.д.

----------------

об этом, наверно, Serhiy_UA написал, я просто начал писать до его ответа sm.gif
нет, там наверно, чуть другое.

в моем примере, для разгрузки суматора (если нужны не отдельно старшие биты и каждый такт) нужно конвеер - задержка младший части на такт (регистр), ну и для многоступенчатого суматора - пирамида регистров. если в поток сумирования можно 0 вставлять, то конвеер на выходе не нужен, ну и т.д. - зависит от приложения
kkosik
Цитата
На 40 МГц даже 40-разрядный сумматор будет работать без проблем. Сдаётся мне, что вы сумматор этот криво описываете. В общем, код - в студию!

Я даже попробовал сделать 2 сумматора.
1) "обычный", складываем два unsigned
Код
entity adder_simple is
  port(
       DataA : in std_logic_vector(31 downto 0);
       Aclr : in std_logic;
       Clock : in std_logic;
       Sum : out std_logic_vector(39 downto 0);
       Cout : out std_logic);
end adder_simple;

architecture behavioral of adder_simple is

  signal DataA_unsigned : UNSIGNED(39 downto 0);
  signal SumAPlusB_unsigned : UNSIGNED(39 downto 0);
  signal SumOut_unsigned : UNSIGNED(39 downto 0);

begin
  DataA_unsigned <= resize(UNSIGNED(DataA),40);

  process (DataA_unsigned, SumOut_unsigned)
    variable sumAux_unsigned : UNSIGNED(40 downto 0);

  begin
    sumAux_unsigned := ('0' & DataA_unsigned) + ('0' & SumOut_unsigned);
    SumAPlusB_unsigned <= sumAux_unsigned(39 downto 0);
    Cout <= not(std_logic(sumAux_unsigned (40)));
  end process;

  process (AClr, Clock)
  begin
    if (Aclr = '1') then
       SumOut_unsigned <= TO_UNSIGNED(0, 40);
    elsif (Clock'event and Clock = '1')then
         SumOut_unsigned <= SumAPlusB_unsigned;
    end if;
  end process;

  Sum <= std_logic_vector(SumOut_unsigned(39 downto 0));

end behavioral;


2) с ускоренным переносом. За основу взят код ускоренного сумматора из книжки VHDL: Справочное пособие по основам языка:
Код
entity adder_fast is
  port(
       DataA : in std_logic_vector(31 downto 0);
       Aclr : in std_logic;
       Clock : in std_logic;
       Sum : out std_logic_vector(39 downto 0);
       carry_out : out std_logic);
end adder_fast;

architecture behavioral of adder_fast is


    signal h_sum : unsigned(39 downto 0);
    signal carry_generate : unsigned(39 downto 0);
    signal carry_propogate : unsigned(39 downto 0);
    signal carry_in_internal : unsigned(39 downto 1);

    signal sumout : unsigned(39 downto 0);

    signal dataA_unsigned : unsigned(39 downto 0);

begin
    
    dataA_unsigned <= resize(UNSIGNED(DataA),40);
    h_sum <= dataA_unsigned xor sumout;
    carry_generate <= dataA_unsigned and sumout;
    carry_propogate <= dataA_unsigned or sumout;

    process(carry_generate,carry_propogate,carry_in_internal)
        begin
            carry_in_internal(1) <= carry_generate(0);
      
            inst: for i in 1 to 38 loop
                carry_in_internal(i+1) <= carry_generate(i) or (carry_propogate(i) and carry_in_internal(i));
                end loop;

            carry_out <= carry_generate(39) or (carry_propogate(39) and carry_in_internal(39));
        end process;
    
    process(AClr, Clock)
        begin
            if(Aclr = '1') then
                sumout <= TO_UNSIGNED(0, 40);
                elsif (Clock'event and Clock = '1')then
                    sumout(0) <= h_sum(0) xor '0';
                    sumout(39 downto 1) <= h_sum(39 downto 1) xor carry_in_internal(39 downto 1);
            end if;
        end process;
    
    Sum <= std_logic_vector(sumout);
end behavioral;


Позже выложу графики из modelsim.

Цитата
always @(posedge clk)
begin
sum[39:20] <= sum[39:20] + adder[39:20] + co;
{co,sum[19:0]} <= {1'b0,sum[19:0]} + adder[19:0];
end

эммм, я vhdl учу. verilog воспринимаю пока что с трудом... Не могли бы переконвертировать? суть, в принципе, ясна. но вот эти {} ???
yes
Цитата(kkosik @ Sep 28 2012, 18:14) *
эммм, я vhdl учу. verilog воспринимаю пока что с трудом... Не могли бы переконвертировать? суть, в принципе, ясна. но вот эти {} ???


в VHDL это
co & sum
по моему тоже может быть lvalue, ну или в скобочках

то есть вектор на 1 битик длинее

или добавьте еще один разряд
kkosik
Это сумматор №1. Собственно, "обычный" сумматор. Из-за наличия задержки такой, на работе попросили что-нибудь придумать, чтобы быстрее суммировал...

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


Цитата
в моем примере, для разгрузки суматора (если нужны не отдельно старшие биты и каждый такт)

Как раз нужно суммировать число в 32 разряда и 40-разрядное число, а на выход только старшие 10 разрядов!
bogaev_roman
Я так понимаю, что и Serhiy_UA и yes предложили Вам обычную конвейерную реализацию сумматора http://www.masters.donntu.edu.ua/2012/fknt...l/ACIT_2012.htm
рис.1 Он будет работать быстрее, но имеет латентность. Чем больше уровней - тем быстрее, но и латентность выше. Соответственно, если у Вас есть обратная связь, то данный вариант наврядли подойдет.
des00
Цитата(bogaev_roman @ Sep 28 2012, 09:27) *
Соответственно, если у Вас есть обратная связь, то данный вариант наврядли подойдет.

да в DDS ке обратная связь обычно не замыкается через счетчик частоты, так что пойдет.
Bad0512
Цитата(yes @ Sep 28 2012, 21:11) *
с проазиками дело имели? это не ксайлинсы sm.gif


Не имел. Решил потренироваться. Вот код (всё сделано "втупую", без хитростей с переносами) :
Код
module adder
(
    input    logic    [31:0]        data,
    input    logic                reset,
    input    logic                clk,
    output    logic    [39:0]        sum,
    output    logic                cout
);


always_ff@(posedge clk)
if(reset)    begin
    sum <= '0;
    cout <= '0;
    end
else
    {cout,sum} <= sum + data;

endmodule


Собрал всё это в синплифае. Вот кусок репорта синплифая касательно быстродействия :

Performance Summary
*******************


Worst slack in design: -2.195

Requested Estimated Requested Estimated Clock Clock
Starting Clock Frequency Frequency Period Period Slack Type Group
------------------------------------------------------------------------------------------------------------------------
adder|clk 80.4 MHz 68.3 MHz 12.437 14.631 -2.195 inferred Autoconstr_clkgroup_0
================================================================================
========================================

Ну то есть по оценкам Синплифая этот сумматор будет работать на 68 МГц. Может конечно Синплифай малость и привирает в сторону оптимизма, но не думаю что очень сильно.
Вывод : на 40МГц даже Проасик сможет суммировать 40 битные числа. И никаких танцев с бубном.

Автору топика : уберите из вашего дизайна работу по двум фронтам.О безусловном вреде этого писали на этом форуме неоднократно.
Мой сорец написан на SV, но сути это не меняет, он делает то же что и ваш код, только сброс у меня синхронный(почему синхронный? - почитайте Кена Чапмена, у него есть хорошая статья на эту тему).



bogaev_roman
to Bad0512 я так понял со слов ТС, что данные от результата суммирования дальще обрабатываются по срезу, т.е. реально надо отталкиваться от удвоенной частоты - 80МГц. Теории DDS не помню, но вроде есть стандартная схема, где подсчет идет по фронту, а анализ по срезу.
Bad0512
Цитата(bogaev_roman @ Sep 29 2012, 01:15) *
to Bad0512 я так понял со слов ТС, что данные от результата суммирования дальще обрабатываются по срезу, т.е. реально надо отталкиваться от удвоенной частоты - 80МГц. Теории DDS не помню, но вроде есть стандартная схема, где подсчет идет по фронту, а анализ по срезу.

Вот именно от этой "стандартности" я и предлагаю автору уйти. Такая схема (работа по двум фронтам) в два раза ухудшает времянку. Кроме того, она имеет и ещё много разных недостатков, неоднократно описанных на этом форуме. Кроме того, честно говоря, не вижу смысла экономить пол-такта в подобном дизайне - все процессы последовательные, никаких обратных связей. К чему этот геморрой с двумя фронтами?
Timmy
Проблема вашего сумматора по первому варианту в том, что перенос вы подаёте прямо на выход без защёлкивания в регистре, очевидно, он используется в логике где-то дальше, и даёт критический путь, в который уже вошло всё время суммирования.
Serhiy_UA
Цитата(Serhiy_UA @ Sep 28 2012, 14:56) *
Этот прием описан в доке от Xilinx, найти пока не могу....

Все же нашел... Это было у Альтеры в stx_cookbook.pdf, что в приложении. См., стр.2-9.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.