Jump to content
    

счетчик задержки в Verilog

 

Вообще-то заводить "провод" с кнопки прямиком на управление синхронным счетчиком не очень хорошо - почитайте application notes про metastability. например Understanding Metastability in FPGAs Правильнее было бы подать сигналы с кнопок на простые триггеры и вот уже синхронными версиями этих сигналов управлять счетчиком.

 

Создавать задержанную на такт копию counter смысла нет - можно counter прямо "подать" на case. Лучше уж защелкнуть сигнал управления ЖКИ q

 

Кстати, у Вас в начале вроде говорилось про 2 кнопки, а в коде их уже 3. Что же нужно сделать на самом деле?

 

module new1
  (
    input btn,
    input clk,
    input btn2,
    input btn3,
    output reg [5:0] a,
    output reg [7:0] q
  );

reg [5:0] counter = 0;

reg btn_r;
reg btn_2r;
reg btn_3r;

always @(posedge clk)
begin
  btn_r   <=btn;
  btn_2r <=btn2;
  btn_3r <=btn3;
end


always @(posedge clk)
begin
  if     (btn_3r  == 1)   counter <=0;
  else if(btn_2r == 1)   counter <= counter;
  else if(btn_r   == 1)   counter <= counter + 1;
end

always @(posedge clk)
begin
    case(counter)    
    6'h00: q = 8'h3;//h2;    
    6'h01: q = 8'h2;//h8;
    
    ...

    endcase
end
  
endmodule

Share this post


Link to post
Share on other sites

Третья кнопка добавлена для сброса счетчика. При нажатии 1 кнопки происходит запуск счетчика, при нажатии второй остановка.

Share this post


Link to post
Share on other sites

Третья кнопка добавлена для сброса счетчика. При нажатии 1 кнопки происходит запуск счетчика, при нажатии второй остановка.

Если первая кнопка нажимается и сразу отпускается и потом через какое-то время нажимается и сразу отпускается вторая кнопка и нужно посчитать этот интервал, то ваш код работать не будет.

 

Сейчас логика работы вашего кода такова: после нажатия 1 кнопки счетчик считает до тех пор, пока она нажата. При ее отпускании счетчик остановится. Счетчик также остановится, если при нажатой 1 кнопке будет нажата 2-я. Далее, если первую не отпускать, то при отпускании 2 кнопки счетчик продолжит счет.

 

У Вас нет как такового запуска счетчика - есть просто разрешение на счет пока 1 кнопка остается нажатой и более приоритетный запрет счета, пока остается нажата 2 кнопка.

 

ну как скажете.

только указание не assign а то что под клоком

 

этот кусок

 

 

и этот кусок

 

 

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

 

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

 

Во-вторых, синтезатор это не последняя инстанция. Кроме того, результат синтеза сильно зависит от настроек стратегии. Я вот ваш код отдал Квартусу 13 версии - для него обе конструкции совершенно одинаковы. Нетлист получился абсолютно идентичный

 

post-7537-1383060227_thumb.jpg

 

Обратите внимание на инверсный ENA при том, что в коде if(CE_SIG == 1) - это потому, что синтезатор заметил, что в разных строчках используется одно и то же сравнение. И "пересинтезировал"

assign CE_SIG = (divider_b < div_val_b) ? 0: 1;

 

в

 

assign CE_SIG = (divider_b < div_val_b) ? 1: 0; заменив также if(CE_SIG == 1) на if(CE_SIG == 0)

 

Но самое главное, в том, что Fitter все равно не стал использовать ENA триггера и сделал так

 

post-7537-1383060503_thumb.jpg

 

Поэтому, выложите, пожалуйста результаты синтеза и результаты раскладки.

 

предлагаю для единообразия использовать такой код

 

module Test_CE
  (
    input clk,
    input [5:0] div_val_a,
    input [5:0] div_val_b,
    output reg mclk_ao,
    output reg mclk_bo
  );
  
reg [5:0] divider_a;  
reg [5:0] divider_b;  

reg mclk_a;
reg mclk_b;

wire CE_SIG;


always @(posedge clk)
begin
    if(divider_a < div_val_a)
       divider_a <= divider_a + 1;
    else
       begin
         divider_a <= 0;
         mclk_a <= ~mclk_a;
       end;
end

assign CE_SIG = (divider_b < div_val_b) ? 0: 1;


always @(posedge clk)
begin
    if(divider_b < div_val_b)
       divider_b <= divider_b + 1;
    else
       divider_b <= 0;

    if(CE_SIG == 1)
       mclk_b <= ~mclk_b;
end
                    
always @(posedge clk)
begin
  mclk_ao <= mclk_a;
  mclk_bo <= mclk_b;
end

                    
endmodule

Share this post


Link to post
Share on other sites

Если первая кнопка нажимается и сразу отпускается и потом через какое-то время нажимается и сразу отпускается вторая кнопка и нужно посчитать этот интервал, то ваш код работать не будет.

 

Сейчас логика работы вашего кода такова: после нажатия 1 кнопки счетчик считает до тех пор, пока она нажата. При ее отпускании счетчик остановится. Счетчик также остановится, если при нажатой 1 кнопке будет нажата 2-я. Далее, если первую не отпускать, то при отпускании 2 кнопки счетчик продолжит счет.

 

я использую не кнопки а переключатели на самой плате SW

Share this post


Link to post
Share on other sites

я использую не кнопки а переключатели на самой плате SW

Это не имеет никакого значения.

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

Share this post


Link to post
Share on other sites

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

 

Во-вторых, синтезатор это не последняя инстанция. Кроме того, результат синтеза сильно зависит от настроек стратегии. Я вот ваш код отдал Квартусу 13 версии - для него обе конструкции совершенно одинаковы. Нетлист получился абсолютно идентичный

 

мы далеко уходим от темы. В ксалинксовском синтезаторе со всеми стратегиями по умолчанию, с оптимизацией на скорость, он честно признался что из первой конструкции сделает gated clock, и попросил переписать используя на flip-flop сигнал CE, я переписал конструкцию на 2 вариант и она радостно захлопал в ладошки. Это все для спартана 6, возможно есть зависимость от архитектуры, даже вернее наверняка, так как синтезатор регулярно пишет послания про внимательность к клокам.

 

Опять же то что я делал, это не я придумал, почитал умные книжки и статьи, вот к примеру такую

http://www.sunburst-design.com/papers/Cumm...ston_Resets.pdf

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

 

П.С. к моему стыду я не настолько владею инструментом ISE чтобы выложить картинки что вы просите, если кто в 2 словах напишет где их взять, буду благодарен, а то может кто сразу их выложит, чтобы я не мучался:)

 

П.С.С то х66 смысл кодов один, результат работы один, а реализация в железе разная, и это надо учитывать, одни схемы будут быстрее, другие меньше току есть, третьи стабильнее масштабироваться и так далее...

Share this post


Link to post
Share on other sites

я использую не кнопки а переключатели на самой плате SW

 

Тогда понятно. Единственное, можно написать чуть компактнее

 

  if (btn_3r  == 1)   
    counter <=0;
  else if(btn_r   == 1 && btn_2r == 0)   
    counter <= counter + 1;

Share this post


Link to post
Share on other sites

В ксалинксовском синтезаторе со всеми стратегиями по умолчанию, с оптимизацией на скорость, он честно признался что из первой конструкции сделает gated clock, и попросил переписать используя на flip-flop сигнал CE, я переписал конструкцию на 2 вариант и она радостно захлопал в ладошки.

 

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

 

П.С. к моему стыду я не настолько владею инструментом ISE чтобы выложить картинки что вы просите, если кто в 2 словах напишет где их взять, буду благодарен, а то может кто сразу их выложит, чтобы я не мучался:)

 

П.С.С то х66 смысл кодов один, результат работы один, а реализация в железе разная, и это надо учитывать, одни схемы будут быстрее, другие меньше току есть, третьи стабильнее масштабироваться и так далее...

 

Скажите, пожалуйста, как Вы можете рассуждать о результатах синтеза, если Вы их даже не видели?

 

Как Вы смогли определить, что в первом варианте кода СЕ не используется, а во втором используется?

 

Share this post


Link to post
Share on other sites

Скажите, пожалуйста, как Вы можете рассуждать о результатах синтеза, если Вы их даже не видели?

 

Как Вы смогли определить, что в первом варианте кода СЕ не используется, а во втором используется?

 

я читал текст, я картинки не умею:).

 

об этом мне честно сказал синтезатор.

после первого когда он сказал

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

во молодец, так то лучше, теперь все хорошо, отсюда я заключил что он получил что хотел.

Вернее это даже не синтезатор, а на уровне имплементации вроде варнинги появлялись.

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

 

Я что-то не правильно трактовал?

Share this post


Link to post
Share on other sites

Приветствую Всех!=)

Ознакомившись со всеми мыслями по данной теме хочется заметить, что АВТОРУ ВОПРОСА нужно нарисовать функциональную!!!!!!!!!! схему того что он хочет. После этого уже определяться с языковыми конструкциями и тонкостями программирования. Просто люди хотят помочь, а суть разрабатываемого устройства понимают по своему. Вот такое мое предположение и предложение в одном лице=) А если я не прав, то попрошу автора все же нарисовать такую функц. схемку.....там ведь что-то простенькое

Share this post


Link to post
Share on other sites

я читал текст, я картинки не умею:).

 

об этом мне честно сказал синтезатор.

после первого когда он сказал

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

во молодец, так то лучше, теперь все хорошо, отсюда я заключил что он получил что хотел.

Вернее это даже не синтезатор, а на уровне имплементации вроде варнинги появлялись.

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

 

Я что-то не правильно трактовал?

 

Просинтезировал я в ISE - все то же самое, что и у Квартуса. ISE также не видит разницы между этими вариантами кода. У ISE также как и у Квартуса в RTL Sсhematic CE ипользуется для обеих вариантов, а Technology Schematic CE не использует тоже для обеих вариантов.

 

post-7537-1383131122_thumb.jpg

 

post-7537-1383131127_thumb.jpg

 

post-7537-1383131150_thumb.jpg

 

По вольному переводу сообщений ISE догадаться что у Вас на самом деле происходило я не могу.

 

Но на данный момент я вижу, что два варианта кода, которые для синтезатора не должны ничем отличаться - ничем и не отличаются. Что Quartus, что ISE, что Vivado дают совершенно идентичные результаты для обеих вариантов кода.

 

Share this post


Link to post
Share on other sites

наверное копнуть надо глубже.

 

схема такая

клок входной clk_pin

увеличивает счетчик, как только счетчик досчитывает до заданного числа

MCLK меняется на ~MCLK. Делитель частоты фактически.

далее сигнал MCLK и его инверсия идут на выходной DDR спартана 6 - это схема clock forwarding-а

у сигнала есть еще ресет

 

описание такое

 

  //делитель входного клока
    //MCLK = IN_CLK / 2 / (MCLK_DIVIDER + 1)
    //100 MHz -> ~16.7;
    parameter MCLK_DIVIDER = 2;
    integer CLKDivider = 0;
    
    //сигналы клока после делителя
    reg MCLK = 1'b0;
    wire INV_MCLK;
    assign INV_MCLK = ~MCLK;
    //боремся с Gated Clock
    wire ChangeCLKEnableSignal = (CLKDivider == MCLK_DIVIDER) ? 1 : 0; 
    
    //боремся с Gated Clock
    always @(posedge clk_pin)
        begin
            if(reset == 1)
                begin
                    CLKDivider <= 0;
                    MCLK <= 1'b0;
                end    
            else 
                begin
                    if(CLKDivider != MCLK_DIVIDER)
                        CLKDivider <= CLKDivider + 1;
                    else    
                        CLKDivider <= 0;
                    
                    if(ChangeCLKEnableSignal)
                        MCLK <= ~MCLK;
                end    
        end
        
    //схема форвардинга клока на основе ДДР  
  ODDR2 #(
      .DDR_ALIGNMENT("NONE"), // Sets output alignment to "NONE", "C0" or "C1" 
      .INIT(1'b0),    // Sets initial state of the Q output to 1'b0 or 1'b1
      .SRTYPE("SYNC") // Specifies "SYNC" or "ASYNC" set/reset
   ) clock_forward_inst (
      .Q(motor_st_mclk),     // 1-bit DDR output data
      .C0(MCLK),  // 1-bit clock input
      .C1(INV_MCLK), // 1-bit clock input
      .CE(1'b1),      // 1-bit clock enable input
      .D0(1'b1), // 1-bit data input (associated with C0)
      .D1(1'b0), // 1-bit data input (associated with C1)
      .R(reset),   // 1-bit reset input
      .S(1'b0)   // 1-bit set input
   );

 

 

 

посмотрел картинку, действительно стоит flip-flop и на сигнал CE идет этот разрешающий сигнал.

до этого было просто

 

begin
                    if(CLKDivider != MCLK_DIVIDER)
                        CLKDivider <= CLKDivider + 1;
                    else
                                            begin    
                        CLKDivider <= 0;
                            MCLK <= ~MCLK;
                                            end
                end

 

что порождало варнинг

Gated clock. Clock net MCLK is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.

 

за что купил, за то продал:)

 

Share this post


Link to post
Share on other sites

наверное копнуть надо глубже.

 

схема такая

клок входной clk_pin

увеличивает счетчик, как только счетчик досчитывает до заданного числа

MCLK меняется на ~MCLK. Делитель частоты фактически.

далее сигнал MCLK и его инверсия идут на выходной DDR спартана 6 - это схема clock forwarding-а

у сигнала есть еще ресет

 

 

 

посмотрел картинку, действительно стоит flip-flop и на сигнал CE идет этот разрешающий сигнал.

до этого было просто

 

 

что порождало варнинг

Gated clock. Clock net MCLK is sourced by a combinatorial pin. This is not good design practice. Use the CE pin to control the loading of data into the flip-flop.

 

за что купил, за то продал:)

 

 

Вот оно где шаманство-то зарыто!!!

 

Ни от какого gated clock Вы не избавились - он у Вас как был в обеих вариантах кода, так в обеих вариантах и остался!!!

 

Почему варнинг пропал? Уверен, когда Вы расскажите ВСЮ правду (также как сейчас выложили весь код вместе с истинным источником проблемы) и этому найдется объяснение.

 

Gated clock порождается строчкой

 

assign INV_MCLK = ~MCLK;

 

Эта строчка вставляет комбинаторную логику в виде логического "НЕ" между выходом триггера MCLK и входом ODDR2.C1. Именно это "НЕ" формирует gated clock. И это неизбежно. И CE тут вставлять просто некуда - у комбинаторной логики нет CE :), а CE на регистре MCLK к этому "НЕ" отношения не имеет.

 

Вот результат синтеза вашего кода (точнее фрагмент - чтобы было хорошо видно)

 

post-7537-1383148461_thumb.jpg

 

И результат раскладки по ячейкам ПЛИС (тоже фрагмент)

 

post-7537-1383147334_thumb.jpg

 

Обратите внимание, что после синтеза CE задействован, а после раскладки он не используется. Зато "НЕ" есть везде!

 

Выложите, плиз, ваши картинки.

 

Если Вы хотите действительно избавиться от gated clock надо ставить регистр и на MCLK и на INV_MCLK примерно так:

 

always @(posedge clk_pin)
begin
    if(reset == 1)
      begin
         CLKDivider <= 0;
         MCLK     <= 1'b0;
         INV_MCLK <= 1'b1;
      end    
    else 
      begin
         if(CLKDivider != MCLK_DIVIDER)
            CLKDivider <= CLKDivider + 1;
         else    
            CLKDivider <= 0;
                      
         if(ChangeCLKEnableSignal)
            begin
              MCLK     <= ~MCLK;
              INV_MCLK <=  MCLK;
            end    
      end
end

 

Разумеется INV_MCLK надо из wire "переделать" в reg.

 

 

Share this post


Link to post
Share on other sites

always @(posedge clk_pin)
begin
    if(reset == 1)
      begin
         CLKDivider <= 0;
         MCLK     <= 1'b0;
         INV_MCLK <= 1'b1;
      end    
    else 
      begin
         if(CLKDivider != MCLK_DIVIDER)
            CLKDivider <= CLKDivider + 1;
         else    
            CLKDivider <= 0;
                      
         if(ChangeCLKEnableSignal)
            begin
              MCLK     <= ~MCLK;
              INV_MCLK <=  MCLK;
            end    
      end
end

 

Разумеется INV_MCLK надо из wire "переделать" в reg.

 

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

 

я смотрел на картинку, у меня СЕ остался вроде задействован, хотя может не там смотрю. Обращаю внимание что варнинг у меня появлялся не после синтеза, а уже после раскладки, и там же исчез. У меня ПЛИС забита под завязку, так что там особо не разжируешь с раскладками, может потому раксладка и не меняется.

 

 

на самом деле я не то чтобы хочу избавится от гейтед клока, я просто поверил надписи, что так не хорошо, и надо по другому, сделал по другому, надпись исчезла. Значит либо сначала не было плохо, либо потом стало хорошо:)...

 

может надо как-то совсем из далека начинать. Чем это все грозит? тем что скважность сигнала будет не 50%, да вроде один инвертер ничтожно мало ее изменит...

 

поскольку я счастливый пользователь 64 битной винды 8, то делать картинки из ISE дается тяжело, но я вроде осилил

 

acf1aee5df018d2b3cce8f92d0cf7222.jpg

Share this post


Link to post
Share on other sites

на самом деле я не то чтобы хочу избавится от гейтед клока, я просто поверил надписи, что так не хорошо, и надо по другому, сделал по другому, надпись исчезла. Значит либо сначала не было плохо, либо потом стало хорошо:)...

 

может надо как-то совсем из далека начинать. Чем это все грозит? тем что скважность сигнала будет не 50%, да вроде один инвертер ничтожно мало ее изменит...

 

На приведенном рисунке CE используется только для MCLK, a INV_MCLK формируется обычным элементом НЕ. Кроме того, это RTL Schematic или Technology Schematic?

 

 

Будьте добры, покажите, пожалуйста, результаты синтеза, когда есть варнинг от которого Вы избавились.

 

 

Гейтед клок, сам по себе, это ни хорошо, ни плохо. К клоку есть очень важное требование - у него должен отсутствовать дребезг. Как только в цепи клока появляется комбинаторная логика - появляется опасность дребезга. Поэтому предупреждение может быть не о том, что "все плохо", а о том, что есть цепь где потенциально могут возникать проблемы. Примерно, как сообщение о том, что при присваивании урезается разрядность - потенциально могут быть проблемы, но синтезатор достоверно не может оценить есть ли они в данном конкретном случае или нет ( а разработчик знает, ну или должен знать :) ).

 

Есть 3 варианта комбинаторной логики, с разной степенью опасности - одновходовый элемент "НЕ" , двухвходовый элемент ("И","ИЛИ" и т.д.) и многовходовый элемент.

 

Одновходовый элемент он самый безопасный - он дребезг не вносит.

 

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

 

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

 

Второй фактор, который вносит комбинаторная логика - это смещение гейтированного клока по фазе от оригинала. В ПЛИС для клока предусмотрены отдельные "провода" и обеспечивается минимальная разница по времени прихода фронта на тактовые входы разных регистров (даже находящихся на большом удалении друг от друга). Исходя из этого, если прямой и инверсный клок формируется на отдельных регистрах, то на выходе этих регистров разница по фазе клоков минимальна и определяется разницей во времени прихода фронта исходного клока на каждый триггер. Дальнейшее расхождение зависит от того как эти сигналы будут проведены по ПЛИС во время P&R. Если инверсный клок формируется элементом "НЕ", то сдвиг по фазе (на выходе триггера и НЕ) будет гораздо больше. Но стоит ли об этом сдвиге беспокоиться - зависит от конкретного дизайна (для чего используются эти клоки и какие к ним требования).

 

Вообще в ПЛИС есть PLL (в том числе перенастраиваемые на лету) которые предназначены для формирования клоков с различными особенностями, в том числе и взаимными. Поэтому, если хотите качественный клок - пользуйтесь встроенными PLL.

 

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...