Sefo 0 October 29, 2013 Posted October 29, 2013 · Report post Вообще-то заводить "провод" с кнопки прямиком на управление синхронным счетчиком не очень хорошо - почитайте 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 Quote Share this post Link to post Share on other sites More sharing options...
x66 0 October 29, 2013 Posted October 29, 2013 · Report post Третья кнопка добавлена для сброса счетчика. При нажатии 1 кнопки происходит запуск счетчика, при нажатии второй остановка. Quote Share this post Link to post Share on other sites More sharing options...
Sefo 0 October 29, 2013 Posted October 29, 2013 · Report post Третья кнопка добавлена для сброса счетчика. При нажатии 1 кнопки происходит запуск счетчика, при нажатии второй остановка. Если первая кнопка нажимается и сразу отпускается и потом через какое-то время нажимается и сразу отпускается вторая кнопка и нужно посчитать этот интервал, то ваш код работать не будет. Сейчас логика работы вашего кода такова: после нажатия 1 кнопки счетчик считает до тех пор, пока она нажата. При ее отпускании счетчик остановится. Счетчик также остановится, если при нажатой 1 кнопке будет нажата 2-я. Далее, если первую не отпускать, то при отпускании 2 кнопки счетчик продолжит счет. У Вас нет как такового запуска счетчика - есть просто разрешение на счет пока 1 кнопка остается нажатой и более приоритетный запрет счета, пока остается нажата 2 кнопка. ну как скажете. только указание не assign а то что под клоком этот кусок и этот кусок по смыслу делают одно и тоже, только в первом случае это гейтед клок, а во втором используется CE вход от флип флопа... уж не знаю что подсказывает синтезатору, мож он тоже новичок... Во-первых, и это пожалуй самое главное, Вы неправильно понимаете, что такое "гейтед клок" - даже если ваш синтезатор генерирует разный результат гейтед клок у Вас не получается ни в одном из вариантов т.к. MCLK в любом случае это выход триггера. Во-вторых, синтезатор это не последняя инстанция. Кроме того, результат синтеза сильно зависит от настроек стратегии. Я вот ваш код отдал Квартусу 13 версии - для него обе конструкции совершенно одинаковы. Нетлист получился абсолютно идентичный Обратите внимание на инверсный 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 триггера и сделал так Поэтому, выложите, пожалуйста результаты синтеза и результаты раскладки. предлагаю для единообразия использовать такой код 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 Quote Share this post Link to post Share on other sites More sharing options...
x66 0 October 29, 2013 Posted October 29, 2013 · Report post Если первая кнопка нажимается и сразу отпускается и потом через какое-то время нажимается и сразу отпускается вторая кнопка и нужно посчитать этот интервал, то ваш код работать не будет. Сейчас логика работы вашего кода такова: после нажатия 1 кнопки счетчик считает до тех пор, пока она нажата. При ее отпускании счетчик остановится. Счетчик также остановится, если при нажатой 1 кнопке будет нажата 2-я. Далее, если первую не отпускать, то при отпускании 2 кнопки счетчик продолжит счет. я использую не кнопки а переключатели на самой плате SW Quote Share this post Link to post Share on other sites More sharing options...
Александр77 1 October 29, 2013 Posted October 29, 2013 · Report post я использую не кнопки а переключатели на самой плате SW Это не имеет никакого значения. Если предполагается независимая параллельная работа, то для каждого коммутационного элемента (кнопка или тублер) нужно делать отдельные счетчики, заводить переменную для разрешения счета и устранять дребезг. Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 October 29, 2013 Posted October 29, 2013 · Report post Во-первых, и это пожалуй самое главное, Вы неправильно понимаете, что такое "гейтед клок" - даже если ваш синтезатор генерирует разный результат гейтед клок у Вас не получается ни в одном из вариантов т.к. MCLK в любом случае это выход триггера. Во-вторых, синтезатор это не последняя инстанция. Кроме того, результат синтеза сильно зависит от настроек стратегии. Я вот ваш код отдал Квартусу 13 версии - для него обе конструкции совершенно одинаковы. Нетлист получился абсолютно идентичный мы далеко уходим от темы. В ксалинксовском синтезаторе со всеми стратегиями по умолчанию, с оптимизацией на скорость, он честно признался что из первой конструкции сделает gated clock, и попросил переписать используя на flip-flop сигнал CE, я переписал конструкцию на 2 вариант и она радостно захлопал в ладошки. Это все для спартана 6, возможно есть зависимость от архитектуры, даже вернее наверняка, так как синтезатор регулярно пишет послания про внимательность к клокам. Опять же то что я делал, это не я придумал, почитал умные книжки и статьи, вот к примеру такую http://www.sunburst-design.com/papers/Cumm...ston_Resets.pdf сухой остаток как бы мне программисту не хотелось бы, но зависимость результата от написания еще очень сильна, во всяком случае у ксалинкса, в чем лично убедился. П.С. к моему стыду я не настолько владею инструментом ISE чтобы выложить картинки что вы просите, если кто в 2 словах напишет где их взять, буду благодарен, а то может кто сразу их выложит, чтобы я не мучался:) П.С.С то х66 смысл кодов один, результат работы один, а реализация в железе разная, и это надо учитывать, одни схемы будут быстрее, другие меньше току есть, третьи стабильнее масштабироваться и так далее... Quote Share this post Link to post Share on other sites More sharing options...
Sefo 0 October 29, 2013 Posted October 29, 2013 · Report post я использую не кнопки а переключатели на самой плате SW Тогда понятно. Единственное, можно написать чуть компактнее if (btn_3r == 1) counter <=0; else if(btn_r == 1 && btn_2r == 0) counter <= counter + 1; Quote Share this post Link to post Share on other sites More sharing options...
Sefo 0 October 30, 2013 Posted October 30, 2013 · Report post В ксалинксовском синтезаторе со всеми стратегиями по умолчанию, с оптимизацией на скорость, он честно признался что из первой конструкции сделает gated clock, и попросил переписать используя на flip-flop сигнал CE, я переписал конструкцию на 2 вариант и она радостно захлопал в ладошки. ... но зависимость результата от написания еще очень сильна, во всяком случае у ксалинкса, в чем лично убедился. П.С. к моему стыду я не настолько владею инструментом ISE чтобы выложить картинки что вы просите, если кто в 2 словах напишет где их взять, буду благодарен, а то может кто сразу их выложит, чтобы я не мучался:) П.С.С то х66 смысл кодов один, результат работы один, а реализация в железе разная, и это надо учитывать, одни схемы будут быстрее, другие меньше току есть, третьи стабильнее масштабироваться и так далее... Скажите, пожалуйста, как Вы можете рассуждать о результатах синтеза, если Вы их даже не видели? Как Вы смогли определить, что в первом варианте кода СЕ не используется, а во втором используется? Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 October 30, 2013 Posted October 30, 2013 · Report post Скажите, пожалуйста, как Вы можете рассуждать о результатах синтеза, если Вы их даже не видели? Как Вы смогли определить, что в первом варианте кода СЕ не используется, а во втором используется? я читал текст, я картинки не умею:). об этом мне честно сказал синтезатор. после первого когда он сказал гейтед клок, лучше напиши так чтобы я СЕ на флип-флопе использовал. Отсюда я заключил что он его не использует, я переписал код, как рекомендовали в инете, а именно использовал явное разрешение, и синтезатор написал во молодец, так то лучше, теперь все хорошо, отсюда я заключил что он получил что хотел. Вернее это даже не синтезатор, а на уровне имплементации вроде варнинги появлялись. ну и плюс там куча текста, чего он там с чем соединяет, какие примитивы использует. Я что-то не правильно трактовал? Quote Share this post Link to post Share on other sites More sharing options...
dima_spb 0 October 30, 2013 Posted October 30, 2013 · Report post Приветствую Всех!=) Ознакомившись со всеми мыслями по данной теме хочется заметить, что АВТОРУ ВОПРОСА нужно нарисовать функциональную!!!!!!!!!! схему того что он хочет. После этого уже определяться с языковыми конструкциями и тонкостями программирования. Просто люди хотят помочь, а суть разрабатываемого устройства понимают по своему. Вот такое мое предположение и предложение в одном лице=) А если я не прав, то попрошу автора все же нарисовать такую функц. схемку.....там ведь что-то простенькое Quote Share this post Link to post Share on other sites More sharing options...
Sefo 0 October 30, 2013 Posted October 30, 2013 · Report post я читал текст, я картинки не умею:). об этом мне честно сказал синтезатор. после первого когда он сказал гейтед клок, лучше напиши так чтобы я СЕ на флип-флопе использовал. Отсюда я заключил что он его не использует, я переписал код, как рекомендовали в инете, а именно использовал явное разрешение, и синтезатор написал во молодец, так то лучше, теперь все хорошо, отсюда я заключил что он получил что хотел. Вернее это даже не синтезатор, а на уровне имплементации вроде варнинги появлялись. ну и плюс там куча текста, чего он там с чем соединяет, какие примитивы использует. Я что-то не правильно трактовал? Просинтезировал я в ISE - все то же самое, что и у Квартуса. ISE также не видит разницы между этими вариантами кода. У ISE также как и у Квартуса в RTL Sсhematic CE ипользуется для обеих вариантов, а Technology Schematic CE не использует тоже для обеих вариантов. По вольному переводу сообщений ISE догадаться что у Вас на самом деле происходило я не могу. Но на данный момент я вижу, что два варианта кода, которые для синтезатора не должны ничем отличаться - ничем и не отличаются. Что Quartus, что ISE, что Vivado дают совершенно идентичные результаты для обеих вариантов кода. Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 October 30, 2013 Posted October 30, 2013 · Report post наверное копнуть надо глубже. схема такая клок входной 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. за что купил, за то продал:) Quote Share this post Link to post Share on other sites More sharing options...
Sefo 0 October 30, 2013 Posted October 30, 2013 · Report post наверное копнуть надо глубже. схема такая клок входной 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 к этому "НЕ" отношения не имеет. Вот результат синтеза вашего кода (точнее фрагмент - чтобы было хорошо видно) И результат раскладки по ячейкам ПЛИС (тоже фрагмент) Обратите внимание, что после синтеза 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. Quote Share this post Link to post Share on other sites More sharing options...
Golikov 0 October 30, 2013 Posted October 30, 2013 · Report post 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 дается тяжело, но я вроде осилил Quote Share this post Link to post Share on other sites More sharing options...
Sefo 0 November 1, 2013 Posted November 1, 2013 · Report post на самом деле я не то чтобы хочу избавится от гейтед клока, я просто поверил надписи, что так не хорошо, и надо по другому, сделал по другому, надпись исчезла. Значит либо сначала не было плохо, либо потом стало хорошо:)... может надо как-то совсем из далека начинать. Чем это все грозит? тем что скважность сигнала будет не 50%, да вроде один инвертер ничтожно мало ее изменит... На приведенном рисунке CE используется только для MCLK, a INV_MCLK формируется обычным элементом НЕ. Кроме того, это RTL Schematic или Technology Schematic? Будьте добры, покажите, пожалуйста, результаты синтеза, когда есть варнинг от которого Вы избавились. Гейтед клок, сам по себе, это ни хорошо, ни плохо. К клоку есть очень важное требование - у него должен отсутствовать дребезг. Как только в цепи клока появляется комбинаторная логика - появляется опасность дребезга. Поэтому предупреждение может быть не о том, что "все плохо", а о том, что есть цепь где потенциально могут возникать проблемы. Примерно, как сообщение о том, что при присваивании урезается разрядность - потенциально могут быть проблемы, но синтезатор достоверно не может оценить есть ли они в данном конкретном случае или нет ( а разработчик знает, ну или должен знать :) ). Есть 3 варианта комбинаторной логики, с разной степенью опасности - одновходовый элемент "НЕ" , двухвходовый элемент ("И","ИЛИ" и т.д.) и многовходовый элемент. Одновходовый элемент он самый безопасный - он дребезг не вносит. Двухвходовый элемент является потенциально опасным. Сигнал на разрешающем/запрещающем входе должен переключаться только в определенные безопасные моменты времени (отстоять от фронта и спада клока на какое-то время ) и обязательно быть согласованным с текущим уровнем клока. Например, если используется элемент И, то запрет/разрешение должны происходить только когда клок в низком уровне. Если используется ИЛИ, то наоборот - запрет/разрешение должны происходить только когда клок в высоком уровне. Многовходовые элементы очень опасны т.к. обеспечить отсутствие дребезга сложно. Даже если исключить одновременное переключение нескольких управляющих сигналов и гарантировать, что за период клока меняться будет только один из управляющих сигналов, то это все равно не гарантирует отсутствие дребезга. Второй фактор, который вносит комбинаторная логика - это смещение гейтированного клока по фазе от оригинала. В ПЛИС для клока предусмотрены отдельные "провода" и обеспечивается минимальная разница по времени прихода фронта на тактовые входы разных регистров (даже находящихся на большом удалении друг от друга). Исходя из этого, если прямой и инверсный клок формируется на отдельных регистрах, то на выходе этих регистров разница по фазе клоков минимальна и определяется разницей во времени прихода фронта исходного клока на каждый триггер. Дальнейшее расхождение зависит от того как эти сигналы будут проведены по ПЛИС во время P&R. Если инверсный клок формируется элементом "НЕ", то сдвиг по фазе (на выходе триггера и НЕ) будет гораздо больше. Но стоит ли об этом сдвиге беспокоиться - зависит от конкретного дизайна (для чего используются эти клоки и какие к ним требования). Вообще в ПЛИС есть PLL (в том числе перенастраиваемые на лету) которые предназначены для формирования клоков с различными особенностями, в том числе и взаимными. Поэтому, если хотите качественный клок - пользуйтесь встроенными PLL. Quote Share this post Link to post Share on other sites More sharing options...