Jump to content
    

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

У меня есть нечто подобное на AHDL, мне нравится.

 

Попробуйте еще на макросах типа 74163 с трюковыми входами. Каскадировать можно до бесконечности. Еще круче будет.

Share this post


Link to post
Share on other sites

Попробуйте еще на макросах типа 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

:) :) :)

Share this post


Link to post
Share on other sites

Это - шутка?
Да, я думаю это была шутка.

Вы по моему занимаетесь пустой работой, главное - результат.

Т.е. описываете задачу, описываете сколько нужно по времянке и всё. Я тоже помню, что в старые времена красиво было смотреть как софт на раскладке рисовал цепочки переносов, видно было где счётчики. Но как-то последнее время на это уже не обращаешь внимание: временка и ресурсы устраивают и ладненько. А в последнее время как-то всёравно стало, как оно там, пока не прижмёт.

 

Да, что-то мне подсказывает, что такие примитивы как счётчик крайне редко получится сделать оптимальнее чем в LPM модулях сделано, времени потратите больше чем экономии будет, если будет экономия...

Share this post


Link to post
Share on other sites

Да, я думаю это была шутка.

Вы по моему занимаетесь пустой работой, главное - результат.

Я думаю, работа редко бывает впустую. Вот, мы узнали, что CARRY_SUM это просто два повторителя (наверное).

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

С вашего позволения, я еще немного "потрахаюсь". Если будет результат, доложу.

Share this post


Link to post
Share on other sites

Но не получаю желаемого (см. картинку). Где-то промахнулся. Поможите, люди добрые!

что то счетчиком не пахнет %) post-3453-1270637946_thumb.png

тогда как в лоб post-3453-1270637954_thumb.png

видно что ква использует lpm_counter для данной архитектуры

Share this post


Link to post
Share on other sites

что то счетчиком не пахнет %)

Не пахнет, потому что CARRY_SUM - это просто две цепи, одна ведет через мультиплексоры загрузки, синхронного сброса (зависит от архитектуры ПЛИС) к триггеру или еще куда подальше..., а вторая - цепь переноса, ведет ко входу переноса следующего ЛЭ. А не сумматор, как можно было бы подумать.

Share this post


Link to post
Share on other sites

Не пахнет, потому что CARRY_SUM - это просто две цепи, одна ведет через мультиплексоры загрузки, синхронного сброса (зависит от архитектуры ПЛИС) к триггеру, а вторая - цепь переноса, ведет ко входу переноса следующего ЛЭ. А не сумматор, как можно было бы подумать.

а не пахнет потому что

1. это Technology Viewer:

2. вывод Pout не подключен к счетному выводу, как задумывалось, а сиди тупо на VCC

3. логика каждого бита порта Count не зависит от других битов, а зависит только от сигналов enable, reset_n, clock и своего собственного значения. Как ЭТО может быть счетчиком, в котором, при любом способе построения, старшие биты зависят от младших ?

Share this post


Link to post
Share on other sites

Самый идеальный вариант - использовать мегафункцию, она специально заточена под структуру плисины.

При написании а ля counter<=counter+1 после синтеза квартус делает сумматор, который оптимизирует далее до счетчика и который проигрывает первоначальному варианту по быстродействию (немного, издержки фиттера).

Если делать на вентильном уровне, то квартус придет к тому же варианту что и с мегафункцией :) (проверял на небольшой разрядности).

Если хотите, чтоб на флурплане было все в линеечку и максимально упаковано, то используйте мегафункцию (чтоб при фиттере в большом проекте не размазал, ограничте область).

Share this post


Link to post
Share on other sites

Объясняю, что хотел сделать. Вот образец на 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;

 

Самый идеальный вариант - использовать мегафункцию, она специально заточена под структуру плисины.

...

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

 

 

Вот такой код работает. Но это только "полуфабрикат".

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

Share this post


Link to post
Share on other sites

По совету участников обратился к мегафункции 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.

Share this post


Link to post
Share on other sites

Вывод такой - если хочешь качества - используй LPM, если все равно - пиши по-простому, на Verilog.

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

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

endmodule

Floorplan:

post-1343-1270701399_thumb.png

 

Одна из ячеек (любая):

post-1343-1270701405_thumb.png

 

Что я делаю не так?

Share this post


Link to post
Share on other sites

Обращается к lpm_counter. А тот представляет собой AHDL файл, который, я, собственно, и пытался "изобрести".

Вывод такой - если хочешь качества - используй LPM, если все равно - пиши по-простому, на Verilog.

Во-во, и более того, обычно достаточно просто написать: a=a+1; и квартус автоматически подключит LPM.

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

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

Share this post


Link to post
Share on other sites

Во-во, и более того, обычно достаточно просто написать: a=a+1; и квартус автоматически подключит LPM.

 

LPM counter он только на ацексе подключает. Последний квартус его уже не поддерживает.

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

Share this post


Link to post
Share on other sites

LPM counter он только на ацексе подключает. Последний квартус его уже не поддерживает.

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

Не знаю, как последний, а Quartus 9.0 тот модуль, что я показал, скушал.

Share this post


Link to post
Share on other sites

Что я делаю не так?

 

теперь еще добавить alcr, clk_ena, sload, cnt_en как в сабжевом примере и посмотреть. очень занятные вещи видятся для разных семейств (причины уже обсуждали на этом форуме) %)

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...