Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Счетчик на примитивах CARRY_SUM и DFFE
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Языки проектирования на ПЛИС (FPGA)
Страницы: 1, 2
ViKo
Quartus 9.0, Altera ACEX 1K. Пытаюсь создать счетчик, чтобы укладывался компактно в логические элементы. Для начала - фиксированного размера (с generate - свои проблемы). Как-то так:
Код
module CountPrim
#(parameter WIDTH = 4)
  (
  input Reset_n, Clock, Enable,
  output [WIDTH-1:0] Count,
  output POut
  );

  wire [WIDTH-1:0] Fb;    // feedback
  wire [WIDTH-1:0] Lt;    // look table
  wire [WIDTH-1:0] Cr;    // carry out

  CARRY_SUM Cy0 (.sin(Fb[0]), .cin(1),
        .sout(Lt[0]), .cout(Cr[0]));
  DFFE Ff0 (.d(Lt[0]), .clk(Clock),
        .clrn(Reset_n), .prn(1),
        .ena(Enable), .q(Fb[0]));

  CARRY_SUM Cy1 (.sin(Fb[1]), .cin(Cr[0]),
        .sout(Lt[1]), .cout(Cr[1]));
  DFFE Ff1 (.d(Lt[1]), .clk(Clock),
        .clrn(Reset_n), .prn(1),
        .ena(Enable), .q(Fb[1]));

  CARRY_SUM Cy2 (.sin(Fb[2]), .cin(Cr[1]),
        .sout(Lt[2]), .cout(Cr[2]));
  DFFE Ff2 (.d(Lt[2]), .clk(Clock),
        .clrn(Reset_n), .prn(1),
        .ena(Enable), .q(Fb[2]));

  CARRY_SUM Cy3 (.sin(Fb[3]), .cin(Cr[2]),
        .sout(Lt[3]), .cout(Cr[3]));
  DFFE Ff3 (.d(Lt[3]), .clk(Clock),
        .clrn(Reset_n), .prn(1),
        .ena(Enable), .q(Fb[3]));

  assign  Count = Fb;
  assign  POut = Cr[3];

endmodule

Но не получаю желаемого (см. картинку). Где-то промахнулся. Поможите, люди добрые!
Maverick
Цитата(ViKo @ Apr 6 2010, 15:09) *
Quartus 9.0, Altera ACEX 1K. Пытаюсь создать счетчик, чтобы укладывался компактно в логические элементы. Для начала - фиксированного размера (с generate - свои проблемы).
Но не получаю желаемого (см. картинку). Где-то промахнулся. Поможите, люди добрые!


чем Вас не устраивает такое описание

Код
   reg [<upper>:0] <reg_name>;
  
   always @(posedge <clock> or posedge <reset>)
      if (<reset>)
         <reg_name> <= 0;
      else if (<clock_enable>)
         <reg_name> <= <reg_name> + 1;


готового счетчика?
ViKo
Цитата(Maverick @ Apr 6 2010, 15:35) *
чем Вас не устраивает такое описание
...
готового счетчика?

Не устраивает тем, что Quartus не объединяет в одном логическом элементе сумматор и триггер, а раскидывает, как захочет. На MAX+II на AHDL у меня счетчики выстраивались в линейку, с цепями переноса длиной в 24 элемента.
Builder
Цитата(ViKo @ Apr 6 2010, 15:45) *
Не устраивает тем, что Quartus не объединяет в одном логическом элементе сумматор и триггер, а раскидывает, как захочет. На MAX+II на AHDL у меня счетчики выстраивались в линейку, с цепями переноса длиной в 24 элемента.
Какую версию квартуса используете? Квартус достаточно умный для того, что-б использовать мегафункции, если только там код не сильно хитрый и не завязано на что-то ещё. Если что-то не получается, по моему проще использовать LPM функцию сложения, врятли получится написать оптимальнее чем в ней, особенно для общего случая.
Kuzmi4
Цитата(ViKo @ Apr 6 2010, 15:45) *
..раскидывает, как захочет...

Если во времянку вложились - вам не всё равно где и почему он их так расставил ??
ViKo
Цитата(Kuzmi4 @ Apr 6 2010, 15:54) *
Если во времянку вложились - вам не всё равно где и почему он их так расставил ??

Предпочитаю идеальное решение. Жалко напрасно потраченных логических элементов.
dxp
Цитата(ViKo @ Apr 6 2010, 19:45) *
Не устраивает тем, что Quartus не объединяет в одном логическом элементе сумматор и триггер, а раскидывает, как захочет. На MAX+II на AHDL у меня счетчики выстраивались в линейку, с цепями переноса длиной в 24 элемента.

У вас счетчик по скорости не укладывается или вам просто хочется, чтобы фиттер размещал ячейки рядом и обязательно переносы делал через carry chain'ы?
ViKo
Цитата(dxp @ Apr 6 2010, 16:02) *
У вас счетчик по скорости не укладывается или вам просто хочется, чтобы фиттер размещал ячейки рядом и обязательно переносы делал через carry chain'ы?

...Просто хочется smile.gif...
Просто счетчиков будет некоторое количество... остальное уже сказал.
dxp
Цитата(ViKo @ Apr 6 2010, 19:57) *
Предпочитаю идеальное решение. Жалко напрасно потраченных логических элементов.

Перфекционизмом занимаетесь. smile.gif Просинтезируйте счетчик, который вам описали, и загляните в директорию db - с ненулевой вероятностью увидите там файл lpm_counter.tdf. smile.gif Который как раз весь из себя низкоуровневый и использует переносы "вручную".
iosifk
Цитата(ViKo @ Apr 6 2010, 17:06) *
Просто счетчиков будет некоторое количество... остальное уже сказал.

Самый главный вопрос: все счетчики считают одновременно и на максимальной для чипа частоте?
Т.е решение "в лоб"???
Или можно сделать один счетчик и успевать им считать в нескольких каналах?
Kuzmi4
2 ViKo
пройдитесь по форуму - помнится des00 и SM поднимали такой вопрос (только там есчё модуль был числа, а потом "плюс"). Не совсем то, что вам нужно, но сумматор там как раз таким вот хитроумным методом и был организован, и даже вроде бы через generate-ы.
dxp
Цитата(ViKo @ Apr 6 2010, 20:06) *
...Просто хочется smile.gif...
Просто счетчиков будет некоторое количество... остальное уже сказал.

Констрейнами зададите требования, синтезатор будет стараться выжимать скорость и/или размер.
ViKo
Счетчики разные, счетчиков - несколько (5-6), длинные.
Я могу написать Count = Count + 1, и все будет нормально.
Но хотелось бы получить конкретный ответ на свой вопрос. Что-то я напутал в CARRY_SUM.

Цитата(Kuzmi4 @ Apr 6 2010, 16:09) *
2 ViKo
пройдитесь по форуму - помнится des00 и SM поднимали такой вопрос (только там есчё модуль был числа, а потом "плюс"). Не совсем то, что вам нужно, но сумматор там как раз таким вот хитроумным методом и был организован, и даже вроде бы через generate-ы.

Смотрел, что-то видел. Но там не было CARRY_SUM.
Я понимаю так, что таблица истинности у него следующая:
Код
CI SI SO CO
0  0  0  0
0  1  1  0
1  0  1  0
1  1  0  1
Костян
Цитата(ViKo @ Apr 6 2010, 11:57) *
Предпочитаю идеальное решение. Жалко напрасно потраченных логических элементов.

а почему не берете в расчет зря потраченное время на это решение?

Цитата(ViKo @ Apr 6 2010, 12:20) *
Я понимаю так, что таблица истинности у него следующая:
Код
CI SI SO CO
0  0  0  0
0  1  1  0
1  0  1  0
1  1  0  1

похоже на правду, если хотите удостовериться - сделайте тестбенч и подайте на вход CI SI (всего лишь четыре варианта)
ViKo
Цитата(Костян @ Apr 6 2010, 16:45) *
а почему не берете в расчет зря потраченное время на это решение?

похоже на правду, если хотите удостовериться - сделайте тестбенч и подайте на вход CI SI (всего лишь четыре варианта)

По первому - один раз набив шишек, можно потом клепать счетчики сколь угодно раз. У меня есть нечто подобное на AHDL, мне нравится. Сразу видно на Floorplan - вот они, мои счетчики smile.gif
По второму - попробую.
sazh
Цитата(ViKo @ Apr 6 2010, 16:54) *
У меня есть нечто подобное на AHDL, мне нравится.


Попробуйте еще на макросах типа 74163 с трюковыми входами. Каскадировать можно до бесконечности. Еще круче будет.
ViKo
Цитата(sazh @ Apr 6 2010, 17:01) *
Попробуйте еще на макросах типа 74163 с трюковыми входами. Каскадировать можно до бесконечности. Еще круче будет.

Это - шутка?

Гляньте, какая таблица истинности вышла:
Код
CI SI SO CO
0  0  0  0
0  1  1  0
1  0  0  1
1  1  1  1

т.е., CO повторяет CI, SO повторяет SI
smile.gif smile.gif smile.gif
Builder
Цитата(ViKo @ Apr 6 2010, 17:13) *
Это - шутка?
Да, я думаю это была шутка.
Вы по моему занимаетесь пустой работой, главное - результат.
Т.е. описываете задачу, описываете сколько нужно по времянке и всё. Я тоже помню, что в старые времена красиво было смотреть как софт на раскладке рисовал цепочки переносов, видно было где счётчики. Но как-то последнее время на это уже не обращаешь внимание: временка и ресурсы устраивают и ладненько. А в последнее время как-то всёравно стало, как оно там, пока не прижмёт.

Да, что-то мне подсказывает, что такие примитивы как счётчик крайне редко получится сделать оптимальнее чем в LPM модулях сделано, времени потратите больше чем экономии будет, если будет экономия...
ViKo
Цитата(Builder @ Apr 6 2010, 18:42) *
Да, я думаю это была шутка.
Вы по моему занимаетесь пустой работой, главное - результат.

Я думаю, работа редко бывает впустую. Вот, мы узнали, что CARRY_SUM это просто два повторителя (наверное).
Счетчик, "выстроенный в шеренгу", имеет регулярную структуру, предсказуемое быстродействие, близкое к предельному, не зависимые от переукладки проекта.
С вашего позволения, я еще немного "потрахаюсь". Если будет результат, доложу.
des00
Цитата(ViKo @ Apr 6 2010, 07:24) *
Но не получаю желаемого (см. картинку). Где-то промахнулся. Поможите, люди добрые!

что то счетчиком не пахнет %) Нажмите для просмотра прикрепленного файла
тогда как в лоб Нажмите для просмотра прикрепленного файла
видно что ква использует lpm_counter для данной архитектуры
ViKo
Цитата(des00 @ Apr 7 2010, 14:14) *
что то счетчиком не пахнет %)

Не пахнет, потому что CARRY_SUM - это просто две цепи, одна ведет через мультиплексоры загрузки, синхронного сброса (зависит от архитектуры ПЛИС) к триггеру или еще куда подальше..., а вторая - цепь переноса, ведет ко входу переноса следующего ЛЭ. А не сумматор, как можно было бы подумать.
des00
Цитата(ViKo @ Apr 7 2010, 06:32) *
Не пахнет, потому что CARRY_SUM - это просто две цепи, одна ведет через мультиплексоры загрузки, синхронного сброса (зависит от архитектуры ПЛИС) к триггеру, а вторая - цепь переноса, ведет ко входу переноса следующего ЛЭ. А не сумматор, как можно было бы подумать.

а не пахнет потому что
1. это Technology Viewer:
2. вывод Pout не подключен к счетному выводу, как задумывалось, а сиди тупо на VCC
3. логика каждого бита порта Count не зависит от других битов, а зависит только от сигналов enable, reset_n, clock и своего собственного значения. Как ЭТО может быть счетчиком, в котором, при любом способе построения, старшие биты зависят от младших ?
bogaev_roman
Самый идеальный вариант - использовать мегафункцию, она специально заточена под структуру плисины.
При написании а ля counter<=counter+1 после синтеза квартус делает сумматор, который оптимизирует далее до счетчика и который проигрывает первоначальному варианту по быстродействию (немного, издержки фиттера).
Если делать на вентильном уровне, то квартус придет к тому же варианту что и с мегафункцией smile.gif (проверял на небольшой разрядности).
Если хотите, чтоб на флурплане было все в линеечку и максимально упаковано, то используйте мегафункцию (чтоб при фиттере в большом проекте не размазал, ограничте область).
ViKo
Объясняю, что хотел сделать. Вот образец на AHDL.
Для ACEX счетчик выстраивается ровненько, с цепями переноса из разряда в разряд и триггерами в тех же ЛЭ.
Для Cyclone - уже нет.
Хочу сделать подобное на Verilog.
Код
Title "Counter with Syncronous Reset";

%-- Library 2005 ViKo --------------------------
Counter with syncronous enable, load, reset
direction - increment (default) or decrement
carry-out - asyncronous, can be triggered outside

Нельзя использовать слишком много индивидуальных
загрузок и сбросов - не удастся разложить,
не хватит каналов, можно вылететь из-за ошибки.
Но можно использовать несколько сигналов для групп.

%-----------------------------------------------
Parameters
(
Wid = 8,        -- counter width
Dir = "up"        -- "down" or "up"
);

------------------------------------------------
Subdesign        ViKoCount
(
Clk        : input;    -- Clock
Ena        : input = Vcc;    -- Enable (input_pulse)
Dat[Wid-1..0]        : input = Gnd;    -- Data for load
nLd[Wid-1..0]        : input = Vcc;    -- /Load
nRes[Wid-1..0]        : input = Vcc;    -- /Reset
Q[Wid-1..0]        : output;    -- Outputs
P        : output;    -- Carry output
)

------------------------------------------------
Variable
Ct[Wid-1..0]    : dff;        -- Counter cells
Cy[Wid-1..0]    : carry;        -- Carry nodes

------------------------------------------------
Begin

Ct[].clk = Clk;
Ct0.d = ((Ct0 $ Ena) & nLd0 # Dat0 & !nLd0) & nRes0;
if Dir == "down" generate
    Cy0 = !Ct0; -- & nRes0;
    else generate
    Cy0 = Ct0; -- & nRes0;
    end generate;
for i in 1 to Wid-1 generate
Ct[i].d = ((Ct[i] $ (Cy[i-1] & Ena)) & nLd[i] # Dat[i] & !nLd[i]) & nRes[i];
if Dir == "down" generate
    Cy[i] = !Ct[i] & Cy[i-1]; -- & nRes[i];
    else generate
    Cy[i] = Ct[i] & Cy[i-1]; -- & nRes[i];
    end generate;
end generate;
Q[] = Ct[];
P = Cy[Wid-1];            -- Out with glitch
End;


Цитата(bogaev_roman @ Apr 7 2010, 14:39) *
Самый идеальный вариант - использовать мегафункцию, она специально заточена под структуру плисины.
...

Согласен. Попробую и это обязательно.


Вот такой код работает. Но это только "полуфабрикат".
Код
module CountPrim
#(parameter WIDTH = 4)
  (
  input Reset_n, Clock, Enable,
  output [WIDTH-1:0] Count,
  output POut,
  input Down
  );

  wire [WIDTH-1:0] Fb;    // feedback
  wire [WIDTH-1:0] Lt;    // lookUp table
  wire [WIDTH-1:0] Cr;    // carry out

  CARRY_SUM Cy0 (.sin(!Fb[0]), .cin(Fb[0] ^ Down),
        .sout(Lt[0]), .cout(Cr[0]));
  DFFE Ff0 (.d(Lt[0]), .clk(Clock),
        .clrn(Reset_n), .prn(1),
        .ena(Enable), .q(Fb[0]));

  CARRY_SUM Cy1 (.sin(Fb[1] ^ Cr[0]), .cin((Fb[1] ^ Down) & Cr[0] ),
        .sout(Lt[1]), .cout(Cr[1]));
  DFFE Ff1 (.d(Lt[1]), .clk(Clock),
        .clrn(Reset_n), .prn(1),
        .ena(Enable), .q(Fb[1]));

  CARRY_SUM Cy2 (.sin(Fb[2] ^ Cr[1]), .cin((Fb[2] ^ Down) & Cr[1]),
        .sout(Lt[2]), .cout(Cr[2]));
  DFFE Ff2 (.d(Lt[2]), .clk(Clock),
        .clrn(Reset_n), .prn(1),
        .ena(Enable), .q(Fb[2]));

  CARRY_SUM Cy3 (.sin(Fb[3] ^ Cr[2]), .cin((Fb[3] ^ Down) & Cr[2]),
        .sout(Lt[3]), .cout(Cr[3]));
  DFFE Ff3 (.d(Lt[3]), .clk(Clock),
        .clrn(Reset_n), .prn(1),
        .ena(Enable), .q(Fb[3]));

  assign  Count = Fb;
  assign  POut = Cr[3];

endmodule
ViKo
По совету участников обратился к мегафункции LPM_COUNTER, с помощью Визарда создал Verilog модуль, который можно вставлять в свой проект, причем, кое-что можно и менять, например, разрядность. Раскладывается, как положено, быстродействие отличное. Большего мне не надо.
Вот он какой, модуль.
Код
module MWLPM_Counter (
    aclr,
    clk_en,
    clock,
    cnt_en,
    data,
    sload,
    cout,
    q);

    input      aclr;
    input      clk_en;
    input      clock;
    input      cnt_en;
    input    [23:0]  data;
    input      sload;
    output      cout;
    output    [23:0]  q;

    wire  sub_wire0;
    wire [23:0] sub_wire1;
    wire  cout = sub_wire0;
    wire [23:0] q = sub_wire1[7:0];

    lpm_counter    lpm_counter_component (
                .sload (sload),
                .clk_en (clk_en),
                .aclr (aclr),
                .clock (clock),
                .data (data),
                .cnt_en (cnt_en),
                .cout (sub_wire0),
                .q (sub_wire1),
                .aload (1'b0),
                .aset (1'b0),
                .cin (1'b1),
                .eq (),
                .sclr (1'b0),
                .sset (1'b0),
                .updown (1'b1));
    defparam
        lpm_counter_component.lpm_direction = "UP",
        lpm_counter_component.lpm_port_updown = "PORT_UNUSED",
        lpm_counter_component.lpm_type = "LPM_COUNTER",
        lpm_counter_component.lpm_width = 24;


endmodule

Обращается к lpm_counter. А тот представляет собой AHDL файл, который, я, собственно, и пытался "изобрести".
Вывод такой - если хочешь качества - используй LPM, если все равно - пиши по-простому, на Verilog.
dxp
Цитата(ViKo @ Apr 7 2010, 20:51) *
Вывод такой - если хочешь качества - используй LPM, если все равно - пиши по-простому, на Verilog.

Код
module slon
(
    input            clk,                      
    output bit [63:0] cnt
);

always_ff @(posedge clk) begin
    cnt <= cnt + 1;
end

endmodule

Floorplan:
Нажмите для просмотра прикрепленного файла

Одна из ячеек (любая):
Нажмите для просмотра прикрепленного файла

Что я делаю не так?
Builder
Цитата(ViKo @ Apr 7 2010, 16:51) *
Обращается к lpm_counter. А тот представляет собой AHDL файл, который, я, собственно, и пытался "изобрести".
Вывод такой - если хочешь качества - используй LPM, если все равно - пиши по-простому, на Verilog.
Во-во, и более того, обычно достаточно просто написать: a=a+1; и квартус автоматически подключит LPM.
Единственный случай. который прихдит на ум, когда есть смысл попробовать ручками подключать, если сумматор по логике сложится с другой логике, и результат не ляжет на LPM. Но я например к таким экспериментам прихожу если не выполняются констрейны.
Так что не придумываете себе забот лишних, больше чем их есть.
sazh
Цитата(Builder @ Apr 8 2010, 09:28) *
Во-во, и более того, обычно достаточно просто написать: a=a+1; и квартус автоматически подключит LPM.


LPM counter он только на ацексе подключает. Последний квартус его уже не поддерживает.
У ацекса одна судьба - пакет max+II
ViKo
Цитата(sazh @ Apr 8 2010, 10:09) *
LPM counter он только на ацексе подключает. Последний квартус его уже не поддерживает.
У ацекса одна судьба - пакет max+II

Не знаю, как последний, а Quartus 9.0 тот модуль, что я показал, скушал.
des00
Цитата(dxp @ Apr 7 2010, 22:53) *
Что я делаю не так?


теперь еще добавить alcr, clk_ena, sload, cnt_en как в сабжевом примере и посмотреть. очень занятные вещи видятся для разных семейств (причины уже обсуждали на этом форуме) %)
ViKo
Ну, вот, к примеру.
Код
module CountDownReload
#(parameter PERIOD = 50000)
  (
  input Reset_n, Clock, Enable,
  output reg [WIDTH:0] Count
  );
  localparam WIDTH = NumBits(PERIOD-2);
  
  always @(negedge Reset_n, posedge Clock)
  if (!Reset_n)
    Count = 0;
  else
    if (Enable)
      if (Count[WIDTH])
        Count = Count - 1;
      else
        Count = (1 << WIDTH) | (PERIOD-2);
endmodule

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


А вот тот же код, разложенный в Cyclone III, 18 ЛЭ

Что сказать: Quartus + Cyclone = Сила!
Предыдущие семейства - в топку!
sazh
Цитата(ViKo @ Apr 8 2010, 11:47) *
Что сказать: Quartus + Cyclone = Сила!
Предыдущие семейства - в топку!


Добавлю, все на квартус 9.0. Ибо только он творит чудеса.
ViKo
Цитата(sazh @ Apr 8 2010, 11:58) *
Добавлю, все на квартус 9.0. Ибо только он творит чудеса.

Неужто 9.1 хуже?
Или, снова... шутка? Смайлик поставьте.
dxp
Цитата(des00 @ Apr 8 2010, 15:11) *
теперь еще добавить alcr, clk_ena, sload, cnt_en как в сабжевом примере и посмотреть. очень занятные вещи видятся для разных семейств (причины уже обсуждали на этом форуме) %)

Код
//------------------------------------------------------------------------------
module slon
(
    input            clk,
    input            rst,

    input            cnt_en,

    input      [63:0] data,
    input             load,
                    
    output bit [63:0] cnt
);

always_ff @(posedge clk, posedge rst) begin
    if(rst) begin
        cnt <= 0;
    end
    else begin
        if(cnt_en) begin
            if(load) begin
                cnt <= data;
            end
            else begin
                cnt <= cnt + 1;
            end
        end
    end
end

endmodule
//------------------------------------------------------------------------------

Нажмите для просмотра прикрепленного файла Нажмите для просмотра прикрепленного файла

P.S. EP2C8F256I8 @ Quartus II 9.0 Build 235 06/17/2009 SJ Full Version, Service Pack Installed: 2
ViKo
to dxp
Для ACEX попробуйте то же.

Сам попробовал smile.gif
Все ровненько, только я длину счетчика уменьшил до 32.
Значит, ваш пример недостаточно сложный.
des00
Цитата(dxp @ Apr 8 2010, 03:05) *
P.S. EP2C8F256I8 @ Quartus II 9.0 Build 235 06/17/2009 SJ Full Version, Service Pack Installed: 2

я не зря перечислил нужные сигналы, посмотрите для начала на таблицу истинности lpm_counter потом сравните со своим кодом %)
sazh
Цитата(ViKo @ Apr 8 2010, 12:01) *
Неужто 9.1 хуже?
Или, снова... шутка? Смайлик поставьте.


Error (10207): Verilog HDL error at CountDownReload.v(7): can't resolve reference to object "NumBits"
Где он описан?
Да и приоритетность нарушаете:
The signal order is the same for all Altera device families, although as noted
previously, not all device families provide every signal. The following priority order is
observed:
1. Asynchronous Clear, aclr—highest priority
2. Preset, pre
3. Asynchronous Load, aload
4. Enable, ena
5. Synchronous Clear, sclr
6. Synchronous Load, sload
7. Data In, data—lowest priority
ViKo
Цитата(sazh @ Apr 8 2010, 15:43) *
Error (10207): Verilog HDL error at CountDownReload.v(7): can't resolve reference to object "NumBits"
Где он описан?
Да и приоритетность нарушаете:
...

Это - функция, в другом месте была
Код
/*!
***********************************************************************
* @brief    Calculate Number-of-Bits for Number
* @details    Вычисляет количество разрядов для представления числа
* @param    Number - число
* @return    NumBits - количество двоичных разрядов
***********************************************************************/
function integer NumBits (input integer Number);
begin
  NumBits = 0;
  while (Number)
  begin
    NumBits++;
    Number >>= 1;
  end
end
endfunction

Приоритетность нарушаю? unsure.gif
dxp
Цитата(des00 @ Apr 8 2010, 18:56) *
я не зря перечислил нужные сигналы,

Цитата
теперь еще добавить alcr, clk_ena, sload, cnt_en

Код
module slon
(
    input            clk,
    input            rst,

    input            clk_en,
    input            cnt_en,

    input      [63:0] data,
    input             load,
                    
    output bit [63:0] cnt
);

always_ff @(posedge clk, posedge rst) begin
    if(rst) begin
        cnt <= 0;
    end
    else begin
        if(clk_en) begin
            if(load) begin
                cnt <= data;
            end
            else begin
                if(cnt_en) begin
                    cnt <= cnt + 1;
                end
            end
        end
    end
end

endmodule

Так?

Результат в смысле выстраивания счетчика в сгруппированном виде не изменился (скриншоты делать и слать лень).

Цитата(des00 @ Apr 8 2010, 18:56) *
посмотрите для начала на таблицу истинности lpm_counter потом сравните со своим кодом %)

lpm_counter может быть сконфигурирован очень разнообразно, начиная от первого моего примера и включая этот. Какую именно конфигурацию вы имеете в виду? И что в ней мешает синтезатору слепить счетчик в сгруппированных ячейках и с использованием быстрых переносов?
ViKo
Цитата(dxp @ Apr 8 2010, 16:05) *
Какую именно конфигурацию вы имеете в виду? И что в ней мешает синтезатору слепить счетчик в сгруппированных ячейках и с использованием быстрых переносов?

Если задействовать всё, что можно, в счетчике, то, может быть, "красивенько" уже не уложится.
Код
FUNCTION lpm_counter
                           (
                           -- INPUTS
                           data[LPM_WIDTH-1..0],
                           clock,
                           clk_en,
                           cnt_en,
                           updown,
                           cin,
                           aclr,
                           aset,
                           aconst,
                           aload,
                           sclr,
                           sset,
                           sconst,
                           sload
                           )

                           WITH
                           (
                           -- PARAMETERS
                           LPM_WIDTH,
                           LPM_DIRECTION,
                           LPM_MODULUS,
                           LPM_AVALUE,
                           LPM_SVALUE,
                           LPM_PORT_UPDOWN,
                           CARRY_CNT_EN,
                           LABWIDE_SCLR,
                           USE_NEW_VERSION
                           )

                           RETURNS
                           (
                           -- OUPUTS
                           q[LPM_WIDTH-1..0],
                           cout,
                           eq[15..0]%,
                           debug_out[6..0]%
                           );

Правда, я уже не совсем понимаю, зачем...
des00
Цитата(dxp @ Apr 8 2010, 08:05) *
Результат в смысле выстраивания счетчика в сгруппированном виде не изменился (скриншоты делать и слать лень).


пример Viko MWLPM_Counter в посте №25 дает 26 плиток для третьего сыклона, ваш пример slon подрихтованный по разрядности + выход cout дает 50 плиток для того же сыклона.
dxp
Цитата(ViKo @ Apr 8 2010, 20:39) *
Правда, я уже не совсем понимаю, зачем...

Тоже не представляю реальной задачи, где нужен такой счетчик.
ViKo
Цитата(des00 @ Apr 8 2010, 16:53) *
пример Viko MWLPM_Counter в посте №25 дает 26 плиток для третьего сыклона, ваш пример slon подрихтованный по разрядности + выход cout дает 50 плиток для того же сыклона.

Видимо, дело, в cout (которого нет у dxp). Потому что последний slon на 24 разряда дает те же 26 "плиток".
Приведите свой модуль.
Ой, нет - 24 "плитки", 26 было для ACEX.
des00
Цитата(ViKo @ Apr 8 2010, 09:14) *
Приведите свой модуль.

как разберусь откуда берутся лишние плитки приведу %)
bogaev_roman
Загнал следующий код в квартус 9.1 под stratix iv с установками по умолчанию.

Код
module test_counter
(
input clk,
input rst,
output reg [15:0] cnt_out
);

always @(posedge clk or posedge rst)
    if (rst) cnt_out<=16'd0;
        else cnt_out<=cnt_out+16'd1;

endmodule

Проект размазался на флурплане по трем лабам и занял 20 лог ячеек, при этом раскидался в произвольном порядке.
К сожалению, вставить картинку так и не смог smile3046.gif
При использовании мегафункции все получилось ровно и красиво.

Поменял далее на циклон второй - красивая картиночка - все как положено. Непонятно... cranky.gif
ViKo
Хотел написать, что у меня сложилось впечатление, что Альтеровцы в Quartus намеренно душат семейства, не рекомендуемые к новым разработкам.
Но Stratix IV ??
sazh
Цитата(ViKo @ Apr 8 2010, 16:01) *
Приоритетность нарушаю? unsure.gif


Ну накрутили. Снимаю шляпу.
Код
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
des00
Цитата(ViKo @ Apr 8 2010, 08:14) *
Приведите свой модуль.


Цитата(des00 @ Apr 8 2010, 08:20) *
как разберусь откуда берутся лишние плитки приведу %)


и вот опять старый мега баг квартуса, с неумением работать с сигналом 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 такого эффекта нет
des00
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 ой версии %)
ViKo
Цитата(sazh @ Apr 8 2010, 21:21) *
Ну накрутили. Снимаю шляпу.

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

to des00
Посмотрите на картинку для последнего slon'а.
По-моему, все проблемы в сигнале cnt_en, который, вообще говоря, хрен знает зачем нужен. Есть же clk_en.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.