Jump to content

    

Счетчик на примитивах CARRY_SUM и DFFE

Хотел написать, что у меня сложилось впечатление, что Альтеровцы в Quartus намеренно душат семейства, не рекомендуемые к новым разработкам.

Но Stratix IV ??

Share this post


Link to post
Share on other sites
Приоритетность нарушаю? :unsure:

 

Ну накрутили. Снимаю шляпу.

module CountDownReload
#(parameter PERIOD = 16)
  (
  input Reset_n, Clock, Enable,
  output reg [WIDTH:0] Count
  );
  localparam WIDTH = clogb2(PERIOD);

function integer clogb2 (input [31:0] value);
if (value < 2)              clogb2 = 1;
else                 begin
value = value - 1;
for (clogb2 = 0; value > 0; clogb2 = clogb2 + 1)
value = value >> 1;
                     end
endfunction

  always @(negedge Reset_n, posedge Clock)
  if (!Reset_n)
       Count <= PERIOD-2;
  else
    if (Enable)
      if (Count[WIDTH])
        Count <= PERIOD-2;
      else 
        Count <= Count - 1'b1;
endmodule

Share this post


Link to post
Share on other sites
Приведите свой модуль.

 

как разберусь откуда берутся лишние плитки приведу %)

 

и вот опять старый мега баг квартуса, с неумением работать с сигналом sload %)

 

немного подрихтованный slon

module slon
(
    input            clk,
    input            rst,

    input            clk_en,
    input            cnt_en,

    input      [23:0] data,
    input             load,
                    
    output bit [23:0] cnt, 
    output bit cout, cout2    
);

bit [24:0] cnt_reg; 
wire [24:0] cnt_next = cnt_reg + 1'b1; 

always_ff @(posedge clk, posedge rst) begin
    if(rst) begin
        cnt_reg <= 0;
    end
    else begin
        if(clk_en) begin
        
            if(load) begin
                cnt_reg <= {1'b0, data};
            end
            else begin
                if(cnt_en) begin
                    cnt_reg <= cnt_next;
                end
            end
        end
    end
end

assign cnt = cnt_reg[23:0];
assign cout = cnt_reg[24];
assign cout2 = cnt_next[24];

endmodule

 

51 плитка, стоит убрать cout2 или sload 26 плиток. Несмотря на то, что согласно "Figure 2–3. Cyclone III Family Devices LEs in Arithmetic Mode" снять сигнал переноса с последнего сумматора можно легко, ква делает для cout2, при наличии сигнала sload, отдельный сумматор. Мозгов ему в этом "крайне сложном" деле не хватает %) С MWLPM_Counter такого эффекта нет

Share this post


Link to post
Share on other sites

UPD. Ну так и есть, немного хендмейда и те же 26 плиток на третьем сыклоне %)

 

wire [24:0] cnt_reg;
wire [24:0] cnt_next = cnt_reg + cnt_en;
wire [24:0] cnt_init = {1'b0, data};

genvar i;
generate
  for (i = 0; i < $size(cnt_reg); i++) begin : dff_gen
      dffeas
      dffeas
      (
        .clk    ( clk          ) ,
        .d      ( cnt_next [i] ) ,
        .ena    ( clk_en       ) ,
        .asdata ( cnt_init [i] ) ,
        .clrn   ( rst          ) ,
        .sload  ( load         ) ,
        .q      ( cnt_reg  [i] )
      );
  end
endgenerate

assign cnt = cnt_reg[23:0];
assign cout = cnt_reg[24];
assign cout2 = cnt_next[24];

 

Не любит ква сигнал sload, ох как не любит. Если мне память не изменяет, тянется это еще с 7 ой версии %)

Share this post


Link to post
Share on other sites
Ну накрутили. Снимаю шляпу.

Хотел, чтобы загрузка в ACEX шла нулем, согласно архитектуре.

Ваш пример работает в Cyclone III быстрее. Наверное, потому, что в Циклон загрузка идет единицей sload .

 

to des00

Посмотрите на картинку для последнего slon'а.

По-моему, все проблемы в сигнале cnt_en, который, вообще говоря, хрен знает зачем нужен. Есть же clk_en.

post-10362-1270803656_thumb.jpg

Share this post


Link to post
Share on other sites
Посмотрите на картинку для последнего slon'а.

я думал что вы уже поняли что квартусовскому RTL вьюверу не верю и им не пользуюсь. Только Technology mapper. %)

 

По-моему, все проблемы в сигнале cnt_en, который, вообще говоря, хрен знает зачем нужен. Есть же clk_en.

Ну почему, нужна вещь в некоторых применениях. Да и в мегафункции lpm_counter он был с ее основания %)

Share this post


Link to post
Share on other sites

Смотрю в картинку "Figure 2–5. Cyclone III Family Devices LEs in Arithmetic Mode" (у меня 2-5).

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

Левый нижний мультиплексор сообще нарисован по-идиотски, что выбирает, чем выбирает?

Дальше-то просто - sload, data3, clock, ena.

Т.е., возможно, это не глюк, а суровая реальность.

P.S. Впрочем, и без cnt_en результат тот же :(

 

Upd. Устройство ЛЭ лучше смотреть в Resource Property Editor (который выскакивает в Chip Planner) - там все видно, как надо.

День провозился с последним slon'ом, но так и не смог добиться того, что выдал des00 с использованием dffeas.

Хочется верить, что это не глюк, а какая-то логическая нестыковка между Verilog и Cyclone.

Вот и получается, что без примитивов перфект-качества не получить?

Share this post


Link to post
Share on other sites
Не могу представить, как можно сделать сумматор для счетчика, и обходной путь, когда cnt_en запрещает счет, и выход переноса для следующего разряда.

за счет цепей register bypass можно получить на тех же ресурсах комбинационный и регистровый выход сумматора. в lpm_counter cnt_en запрещает счет, но не запрещает формирование сигнала переноса.

Кодом его можно описать двояко :

1) как в приведенном мной коде (кстати в этом случае cout завязан на cnt_en)

2) сумматор сделать константным (развязав cout и cnt_en), но усложнив логику формирования сигнала ena типа так clk_ena & (sload | (~sload & cnt_en))

 

Upd. Устройство ЛЭ лучше смотреть в Resource Property Editor (который выскакивает в Chip Planner) - там все видно, как надо.

мне даташита хватает %)

 

Вот и получается, что без примитивов перфект-качества не получить?

вообще ква достаточно оптимально разводит, но вот сей эффект имеет место быть, когда я что-то делаю под альтеру, что должно использовать sload, я пишу два варианта и добавляю `ifdef __USE_ALTERA_MACRO__ %)

 

Хочется верить, что это не глюк, а какая-то логическая нестыковка между Verilog и Cyclone.

Вот за что мне нравиться форум, что ответы порой находятся сами собой. Читая ваш вопрос, случайно открыл даташит на второй сыклон и сравнил с третьим. Вуаля. Во втором сыклоне в арифметическом режиме нет register bypass. А ква не хватает ума что бы поставить последний LE в цепочке в нормальный режим (в котором register bypass есть). Ребята с альтеры сэкономили, архитектуру чипа улучшили, а вот маппер похоже оставили от второго сыклона. Индусы блин %(

post-3453-1270866083_thumb.png

post-3453-1270866089_thumb.png

Share this post


Link to post
Share on other sites

Приколы продолжаются.

"Хэндмэйд" des00 отказался укладываться в ACEX1K (Auto device selected by fitter), наверное, каналов не хватило?

Error: Cannot route source node "dff_gen[11].dffeas" of type logic cell to destination node "cnt[11]" of type I/O pin
Error: Cannot route source node "dff_gen[11].dffeas" of type logic cell to destination node "lpm_add_sub:Add0|addcore:adder|a_csnbuffer:result_node|cs_buffer[11]" of type logic cell
Error: Cannot route source node "dff_gen[24].dffeas" of type logic cell to destination node "cout" of type I/O pin
Error: Cannot route source node "dff_gen[24].dffeas" of type logic cell to destination node "lpm_add_sub:Add0|addcore:adder|unreg_res_node[24]" of type logic cell
Error: Cannot route source node "lpm_add_sub:Add0|addcore:adder|a_csnbuffer:result_node|cs_buffer[5]" of type logic cell to destination node "dff_gen[5].dffeas" of type logic cell
Error: Cannot route source node "lpm_add_sub:Add0|addcore:adder|a_csnbuffer:result_node|cs_buffer[7]" of type logic cell to destination node "dff_gen[7].dffeas" of type logic cell
Error: Can't find fit
Error: Quartus II Fitter was unsuccessful. 7 errors, 0 warnings

А в ACEX1K100 - влез.

 

Немного видоизмененный (и только с асинхронным выходом переноса) влез в удвоенное количество ЛЭ.

module  CounterDFFEAS
#(parameter    WIDTH = 24)
  (
  input    Reset_n,
  input    Clock,
  input    Enable,
  input    Load,
  input    [WIDTH-1:0] Data,
  output    [WIDTH-1:0] CntOut,
  output    POut
  );
  
  wire    [WIDTH-1:0] Count;
  wire    [WIDTH:0] Next = Count + 1;
  
  genvar i;
  generate
    for (i=0; i<WIDTH; i++)
    begin : ffc
      dffeas  dffeas
      (
      .d (Next[i]),
      .clk (Clock),
      .clrn (Reset_n),
      .ena (Enable),
      .asdata (Data[i]),
      .sload (Load),
      .q (Count[i])
      );
    end
  endgenerate

  assign  CntOut = Count;
  assign  POut = Next[WIDTH];
endmodule

И только MWLPM_Counter, как уже говорилось, упаковался компактно.

Еще одна особенность - если длина счетчика небольшая (смотрел для приведенного выше счетчика при длине 4 на Cyclone III), то цепи переноса из разряда в разряд не используются.

Share this post


Link to post
Share on other sites
Приколы продолжаются.

"Хэндмэйд" des00 отказался укладываться в ACEX1K (Auto device selected by fitter), наверное, каналов не хватило?

у меня 9.0сп2 собрал без каких либо проблем

 

а так,

wire [24:0] cnt_reg;
wire [24:0] cnt_next;
wire [24:0] carry_cnt;
wire [24:0] cnt_init = {1'b0, data};

genvar i;
generate
  for (i = 0; i < $size(cnt_reg); i++) begin : dff_gen

    carry_sum
    carry_sum
    (
      .sin  ( cnt_reg   [i]  ),
      .cin  ( (i == 0) ? 1'b1 : carry_cnt[i-1] ),
      .sout ( cnt_next  [i]  ),
      .cout ( carry_cnt [i]  )
    );

    dffeas
    dffeas
    (
      .clk    ( clk          ) ,
      .d      ( cnt_next [i] ) ,
      .ena    ( clk_en       ) ,
      .asdata ( cnt_init [i] ) ,
      .clrn   ( rst          ) ,
      .sload  ( load         ) ,
      .q      ( cnt_reg  [i] )
    );
  end
endgenerate

assign cnt = cnt_reg[23:0];
assign cout = cnt_reg[24];
assign cout2 = cnt_next[24];

даже уложился в 27 плиток для асекса (как MWLPM_Counter для него же), и в 1 у плитку для сыклонов %)

 

Еще одна особенность - если длина счетчика небольшая (смотрел для приведенного выше счетчика при длине 4 на Cyclone III), то цепи переноса из разряда в разряд не используются.

это не удивительно и достаточно очевидно %)

Share this post


Link to post
Share on other sites
у меня 9.0сп2 собрал без каких либо проблем

У меня 9.0 без СП, придется по-новее пошукать.

 

а так,...

...не работает, потому что нет сумматора. Об этом я уже писал в начале.

Я уже было обрадовался - вот оно!

Похоже, остался еще шаг до цели :)

 

это не удивительно и достаточно очевидно %)

Точно! Где можно обойтись параллельным выполнением операции, последовательное не нужно.

Share this post


Link to post
Share on other sites
...не работает, потому что нет сумматора. Об этом я уже писал в начале.

а так

    carry_sum
    carry_sum
    (
      .sin  ( cnt_reg   [i]  ),
      .cin  ( (i == 0) ? cnt_en : carry_cnt[i-1] ),
      .sout ( cnt_next  [i]  ),
      .cout ( carry_cnt [i]  )
    );

чем не сумматор %)))

 

ЗЫ. Те же 27 плиток %)

 

UPD. бугааа, повелся на поводу у людей, взято из файла altera_primitives.v

 

module carry_sum (sin, cin, sout, cout);
    input sin;
    input cin;
    output sout;
    output cout;

    assign sout = sin;
    assign cout = cin;
endmodule

это не сумматор, это всего лишь указание использовать быстрые цепи переноса

post-3453-1270971918_thumb.png

Share this post


Link to post
Share on other sites
это не сумматор, это всего лишь указание использовать быстрые цепи переноса

Ja-ja, naturlich! (как-то так :)

Меня терзает предчувствие, что не упакуется сумматор с триггерами даже если между ними и забить CARRY_SUM.

 

У ацекса одна судьба - пакет max+II

Все больше склоняюсь к этому. Уже проверил, где там у меня MAXPlus+II инсталлятор :)

Share this post


Link to post
Share on other sites
Ja-ja, naturlich! (как-то так :)

Меня терзает предчувствие, что не упакуется сумматор с триггерами даже если между ними и забить CARRY_SUM.

 

 

Все больше склоняюсь к этому. Уже проверил, где там у меня MAXPlus+II инсталлятор :)

 

так сумматор получили, теперь осталось только втолковать квартусу что все это ложиться в одну плитку в соответствии с режимом "Clearable Counter Mode" LE асекса указанного в даташите ACEX 1K Programmable Logic Device Family Data Sheet

wire [1:0]  sum [0 : 24];

wire cnt_en_wire = cnt_en; 

genvar i;
generate
  for (i = 0; i < $size(cnt_reg); i++) begin : dff_gen

    assign sum[i][0] = cnt_reg[i] ^ ((i == 0) ? cnt_en_wire : carry_cnt[i-1]);
    assign sum[i][1] = cnt_reg[i] & ((i == 0) ? cnt_en_wire : carry_cnt[i-1]);
    
    carry_sum
    carry_sum
    (
      .sin  ( sum[i][0]     ),
      .cin  ( sum[i][1]     ),
      .sout ( cnt_next  [i] ),
      .cout ( carry_cnt [i] )
    );

Share this post


Link to post
Share on other sites

Путем ковыряния даташита на асекс и квартуса у меня сложилось следующее понимание : альтеровцы как всегда всех ввели в заблуждение. Режим работы ячейки асекса Clearable Counter Mode

The clearable counter mode is similar to the up/down counter mode, but it supports a synchronous clear instead of the up/down control. The clear function is substituted for the cascade-in signal in the up/down counter mode. Two 3-input LUTs are used; one generates the counter data, and the other generates the fast carry bit. Synchronous loading is provided by a 2-to-1 multiplexer. The output of this multiplexer is AND ed with a synchronous clear signal.

квартусу недоступен, он слишком туп для этого. Он ставит лют в арифметический регистр и sload в такой LE уже не ложиться, (см даташит на асекс). Помимо этого добавление к вышеуказанному коду сигнала sclr раздувает код до 74 плиток, хотя по даташиту это должно лечь в аппаратный AND в LE.

 

Вывод : Надо пользовать в таких тяжелых случаях мегафункцию и не париться %)

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