Mty 0 March 23 Posted March 23 · Report post 3 hours ago, blackfin said: Вот, держите: one_shot_pulse.txt detect_clock.txt rst_pulse.txt PS. В симуляторе не проверял, возможно, где-то ошибся.. Сами проверите.. PPS. Красоту не наводил.. Сами наведёте.. )) Ого, Огромное спасибо! Скачал, буду разбираться! Quote Share this post Link to post Share on other sites More sharing options...
Mty 0 March 24 Posted March 24 · Report post Спасибо всем за советы, переписал проект на стробы, и сделал что все синхронизируется одним клоком 50мгц. Сразу пропали предупреждения о нарушении тайминга в Time analyser! Но столкнулся с тем, что простой модуль отсчета паузы стал очень странно себя вести. Отдельно в тестбенче он работает, а в тестбенче всего проекта счетчик стоит на 0, и счет не происходит. Может кто посоветует, пол-дня не могу понять в чем дело. // Отсчет паузы 45us signal_in // Максимальное значение 45 // При появлении signal_in выставляется pause_reg // При снятии сигнала signal_in начинает отсчитываться пауза // pause_reg снимается в конце паузы. // Если в течении паузы пришел 2 раз signal_in - выдается pause_err_reg до сброса module Pause50 ( input wire clock, // 50MHz input wire strobe_1MHz, // Ширина строба 20нс начинается и заканчивается по фронту clock input wire reset, input wire signal_in, output reg pause_err_reg, output reg pause_reg ); reg [5:0] PauseCounter_reg; // 6bit = 64 reg signal_in_prev_reg; always @( posedge clock or posedge reset ) begin if( reset ) begin pause_reg <= 1'b0; PauseCounter_reg <= 6'b0; end else if( signal_in ) begin pause_reg <= 1'b1; PauseCounter_reg <= 6'b0; // перезапуск счетчика end else if( strobe_1MHz ) // ENA - здесь разрешение счета. Но регистр PauseCounter_reg всегда в 0 в составе проекта begin if( PauseCounter_reg < 6'd45 ) // Пока счетчик не переполнился PauseCounter_reg <= PauseCounter_reg + 1'b1; else pause_reg <= 1'b0; end end always @( posedge clock or posedge reset ) if( reset ) begin signal_in_prev_reg <= 1'b0; pause_err_reg <= 1'b0; end else begin signal_in_prev_reg <= signal_in; if( (signal_in & ~signal_in_prev_reg) && pause_reg ) // положительный перепад входн сигнала во время паузы pause_err_reg <= 1'b1; end endmodule Quote Share this post Link to post Share on other sites More sharing options...
andrew_b 23 March 24 Posted March 24 · Report post Если signal_in внешний асинхронный сигнал, то вы нарвались на метастабильность. Это классика. Для всех входных асинхронных сигналов надо делать CDC (clock domain crossing). В простейшем случае это цепочка из двух триггеров. Quote Share this post Link to post Share on other sites More sharing options...
sazh 9 March 24 Posted March 24 · Report post 1 час назад, Mty сказал: Спасибо всем за советы, переписал проект на стробы, и сделал что все синхронизируется одним клоком 50мгц. Сразу пропали предупреждения о нарушении тайминга в Time analyser! Но столкнулся с тем, что простой модуль отсчета паузы стал очень странно себя вести. Отдельно в тестбенче он работает, а в тестбенче всего проекта счетчик стоит на 0, и счет не происходит. Может кто посоветует, пол-дня не могу понять в чем дело. // Отсчет паузы 45us signal_in // Максимальное значение 45 // При появлении signal_in выставляется pause_reg // При снятии сигнала signal_in начинает отсчитываться пауза // pause_reg снимается в конце паузы. // Если в течении паузы пришел 2 раз signal_in - выдается pause_err_reg до сброса module Pause50 ( input wire clock, // 50MHz input wire strobe_1MHz, // Ширина строба 20нс начинается и заканчивается по фронту clock input wire reset, input wire signal_in, output reg pause_err_reg, output reg pause_reg ); reg [5:0] PauseCounter_reg; // 6bit = 64 reg signal_in_prev_reg; always @( posedge clock or posedge reset ) begin if( reset ) begin pause_reg <= 1'b0; PauseCounter_reg <= 6'b0; end else if( signal_in ) begin pause_reg <= 1'b1; PauseCounter_reg <= 6'b0; // перезапуск счетчика end else if( clock_1MHz ) // ENA - здесь разрешение счета. Но регистр PauseCounter_reg всегда в 0 в составе проекта begin if( PauseCounter_reg < 6'd45 ) // Пока счетчик не переполнился PauseCounter_reg <= PauseCounter_reg + 1'b1; else pause_reg <= 1'b0; end end always @( posedge clock or posedge reset ) if( reset ) begin signal_in_prev_reg <= 1'b0; pause_err_reg <= 1'b0; end else begin signal_in_prev_reg <= signal_in; if( (signal_in & ~signal_in_prev_reg) && pause_reg ) // положительный перепад входн сигнала во время паузы pause_err_reg <= 1'b1; end endmodule Проблема в логике мышления. signal in при таком подходе должен иметь признак. На раз два три рассчитайсь. Неужели простого сторожевого тамерс не достаточно. Quote Share this post Link to post Share on other sites More sharing options...
Freibier 18 March 24 Posted March 24 · Report post 1 час назад, Mty сказал: input wire strobe_1MHz, // Ширина строба 20нс начинается и заканчивается по фронту clock 1 час назад, Mty сказал: if( clock_1MHz ) // ENA - здесь разрешение счета. Но регистр PauseCounter_reg всегда в 0 в составе проекта что-то тут не то Quote Share this post Link to post Share on other sites More sharing options...
Mty 0 March 24 Posted March 24 · Report post 1 hour ago, andrew_b said: Если signal_in внешний асинхронный сигнал, то вы нарвались на метастабильность. Это классика. Он синхронный, с этим все ок вроде. Я не уверен что с временным стробом все ок. Его фронт совпадает с клоком и спад тоже. Т.е. во время фронта клока может быть нестабильность, или я не прав? 1 hour ago, Freibier said: что-то тут не то Блин, извиняюсь, Вы совершенно правы! Редактировал имя сигнала, чтобы было понятнее, и забыл поправить в этом месте. Поспешил, прошу прощения. Поправил в исходнном сообщении, теперь вот так if( strobe_1MHz ) // ENA - здесь разрешение счета. Но регистр PauseCounter_reg всегда в 0 в составе проекта 1 hour ago, sazh said: Проблема в логике мышления. signal in при таком подходе должен иметь признак. На раз два три рассчитайсь. Неужели простого сторожевого тамерс не достаточно. Не совсем понял, что за признак? Это синхронный сигнал из другого модуля. Да, согласен, пытаюсь выстроить логику мышления в стиле HDL. Quote Share this post Link to post Share on other sites More sharing options...
Raven 29 March 24 Posted March 24 · Report post 2 hours ago, Mty said: Спасибо всем за советы, переписал проект на стробы, и сделал что все синхронизируется одним клоком 50мгц. Сразу пропали предупреждения о нарушении тайминга в Time analyser! Но столкнулся с тем, что простой модуль отсчета паузы стал очень странно себя вести. Отдельно в тестбенче он работает, а в тестбенче всего проекта счетчик стоит на 0, и счет не происходит. Может кто посоветует, пол-дня не могу понять в чем дело. Как вы формируете Signal_in и strobe_1MHz? Ошибкой в приведенном коде, IMHO, является то, что вы, по сути, внешний сигнал (да еще, возможно, асинхронный), делаете состоянием FSM. Состояния машины должны быть местные, стабильные. Не удержался, немного переписал: Spoiler // Отсчет паузы 45us signal_in // Максимальное значение 45 // При появлении signal_in выставляется pause_reg // При снятии сигнала signal_in начинает отсчитываться пауза // pause_reg снимается в конце паузы. // Если в течении паузы пришел 2 раз signal_in - выдается pause_err_reg до сброса module Pause50 ( input wire clock, // 50MHz input wire strobe_1MHz, // Ширина строба 20нс начинается и заканчивается по фронту clock input wire reset, input wire signal_in, output reg pause_err_reg, output reg pause_reg ); reg [5:0] PauseCounter_reg; // 6bit = 64 reg signal_in_prev_reg; reg [1:0] signal_in_reg; wire signal_in_sync; // 2-stage Synchronizer for signal_in always @( posedge clock or posedge reset ) begin if ( reset ) begin signal_in_reg <= 2'b00; end else begin signal_in_reg[0] <= signal_in; signal_in_reg[1] <= signal_in_reg[0]; end end // signal_in_sync - synchronized version of the signal_in, use it within design instead of signal_in assign signal_in_sync = signal_in_reg[1]; always @( posedge clock or posedge reset ) begin if ( reset ) begin pause_reg <= 1'b0; PauseCounter_reg <= 6'b000000; end else begin if ( pause_reg == 1'b0 ) begin // FSM state : (pause_reg == 1'b0) - idle, waiting for input signal if ( signal_in_sync ) begin pause_reg <= 1'b1; // переключаемся в FSM state (pause_reg == 1'b1) PauseCounter_reg <= {6{1'b0}}; // и перезапуск счетчика end end else begin // FSM state : (pause_reg == 1'b1) - "pause", counting for (duration = 45 of strobe_1MHz pulses) if( strobe_1MHz ) begin // ENA - здесь разрешение счета. Но регистр PauseCounter_reg всегда в 0 в составе проекта if( PauseCounter_reg < 6'd45 ) begin // Пока счетчик не переполнился PauseCounter_reg <= PauseCounter_reg + 1'b1; end else begin pause_reg <= 1'b0; end end end end end always @( posedge clock or posedge reset ) if( reset ) begin signal_in_prev_reg <= 1'b0; pause_err_reg <= 1'b0; end else begin signal_in_prev_reg <= signal_in_sync; if( (signal_in_sync & ~signal_in_prev_reg) && pause_reg ) // положительный перепад входн сигнала во время паузы pause_err_reg <= 1'b1; end endmodule 1 Quote Share this post Link to post Share on other sites More sharing options...
sazh 9 March 24 Posted March 24 · Report post 1 час назад, Mty сказал: Не совсем понял, что за признак? Это синхронный сигнал из другого модуля. // При появлении signal_in выставляется pause_reg // При снятии сигнала signal_in начинает отсчитываться пауза // Если в течении паузы пришел 2 раз signal_in - выдается pause_err_reg до сброса По мне - это как себя своей рукой из болота вытащить. Язык тут не причем. Функционал скользкий. Чтоб поднять то, что Вам предлагают, без тестбенча не разобрать. Писать надо просто. Чтоб понятно было. Не надо сразу хвататься описать все в одном процессе. Просто пример. И я замолкаю. ct_div.zip Quote Share this post Link to post Share on other sites More sharing options...
Mty 0 March 24 Posted March 24 · Report post 5 hours ago, Raven said: Как вы формируете Signal_in и strobe_1MHz? Ошибкой в приведенном коде, IMHO, является то, что вы, по сути, внешний сигнал (да еще, возможно, асинхронный), делаете состоянием FSM. Состояния машины должны быть местные, стабильные. Не удержался, немного переписал: Reveal hidden contents // Отсчет паузы 45us signal_in // Максимальное значение 45 // При появлении signal_in выставляется pause_reg // При снятии сигнала signal_in начинает отсчитываться пауза // pause_reg снимается в конце паузы. // Если в течении паузы пришел 2 раз signal_in - выдается pause_err_reg до сброса module Pause50 ( input wire clock, // 50MHz input wire strobe_1MHz, // Ширина строба 20нс начинается и заканчивается по фронту clock input wire reset, input wire signal_in, output reg pause_err_reg, output reg pause_reg ); reg [5:0] PauseCounter_reg; // 6bit = 64 reg signal_in_prev_reg; reg [1:0] signal_in_reg; wire signal_in_sync; // 2-stage Synchronizer for signal_in always @( posedge clock or posedge reset ) begin if ( reset ) begin signal_in_reg <= 2'b00; end else begin signal_in_reg[0] <= signal_in; signal_in_reg[1] <= signal_in_reg[0]; end end // signal_in_sync - synchronized version of the signal_in, use it within design instead of signal_in assign signal_in_sync = signal_in_reg[1]; always @( posedge clock or posedge reset ) begin if ( reset ) begin pause_reg <= 1'b0; PauseCounter_reg <= 6'b000000; end else begin if ( pause_reg == 1'b0 ) begin // FSM state : (pause_reg == 1'b0) - idle, waiting for input signal if ( signal_in_sync ) begin pause_reg <= 1'b1; // переключаемся в FSM state (pause_reg == 1'b1) PauseCounter_reg <= {6{1'b0}}; // и перезапуск счетчика end end else begin // FSM state : (pause_reg == 1'b1) - "pause", counting for (duration = 45 of strobe_1MHz pulses) if( strobe_1MHz ) begin // ENA - здесь разрешение счета. Но регистр PauseCounter_reg всегда в 0 в составе проекта if( PauseCounter_reg < 6'd45 ) begin // Пока счетчик не переполнился PauseCounter_reg <= PauseCounter_reg + 1'b1; end else begin pause_reg <= 1'b0; end end end end end always @( posedge clock or posedge reset ) if( reset ) begin signal_in_prev_reg <= 1'b0; pause_err_reg <= 1'b0; end else begin signal_in_prev_reg <= signal_in_sync; if( (signal_in_sync & ~signal_in_prev_reg) && pause_reg ) // положительный перепад входн сигнала во время паузы pause_err_reg <= 1'b1; end endmodule О, спасибо, распечатаю, разберу листинг, мне очень интересен код опытных людей. По поводу signal_in - он полностью синхронный, я писал про это чуть выше. Формируется по основному клоку 50Mгц always @(posedge clock or posedge reset) begin if (reset) ... else if ( (current_state == CALC_OVERLAP_ANYDRV) || (current_state == STOP_PULSE) ) begin ........ AnyDrv4_reg <= prepare_AnyDrv4; // Далее этот сигнал AnyDrv4_reg соединяю с модулем паузы, входом signal_in Pause50 p50( .clock(clock_50MHz), .strobe_1MHz(clock_1MHz), .reset(reset), .signal_in(AnyDrv4_reg), .pause_reg( Pause50_now ), .pause_err_reg(Err_Pause50) ); Клок делается вот так - Spoiler Клок делается вот так - module ClockGen ( input wire clock_100MHz, // 100MHz output reg clock_50MHz, output reg clock_10MHz, output reg clock_1MHz ); reg [2:0] count_reg10M; // 3 bit = 8 /счет до 4 reg [3:0] count_reg1M; // 4 bit = 16 /счет до 9 reg raw_clock_50MHz; reg counter_10MHz_max; // регистры синхронного сброса reg counter_1MHz_max; // Генерация Clock 50 MHz always @(posedge clock_100MHz) begin raw_clock_50MHz <= ~raw_clock_50MHz; end // Генерация Clock 10 MHz always @(posedge raw_clock_50MHz) begin if( counter_10MHz_max ) count_reg10M <= 1'b0; else count_reg10M <= count_reg10M + 1'b1; counter_10MHz_max <= ( count_reg10M == 3'd3 ); // Делим на 5 - задаем константу 5-2 end // Генерация Clock 1 MHz always @(posedge raw_clock_50MHz) begin if( counter_10MHz_max ) begin if( counter_1MHz_max ) count_reg1M <= 1'b0; else count_reg1M <= count_reg1M + 1'b1; counter_1MHz_max <= ( count_reg1M == 4'd8 ); // Делим на 10 - задаем константу 10-2 end end // Фильтр выхода always @(posedge clock_100MHz) begin clock_50MHz <= raw_clock_50MHz; clock_10MHz <= counter_10MHz_max; clock_1MHz <= counter_1MHz_max & counter_10MHz_max; end endmodule Тут дело видимо не в signal_in, а в стробе strobe_1MHz Дело в том, что счетчик PauseCounter_reg не считает вообще, он всегда 0. А должен даже в отсутствии signal_in досчитать до 45 Quote Share this post Link to post Share on other sites More sharing options...
Freibier 18 March 24 Posted March 24 · Report post 31 минуту назад, Mty сказал: always @(posedge raw_clock_50MHz) Как я понял, синхронный проект вы делать принципиально не хотите? Quote Share this post Link to post Share on other sites More sharing options...
Mty 0 March 24 Posted March 24 · Report post 21 minutes ago, Freibier said: Как я понял, синхронный проект вы делать принципиально не хотите? Как раз хочу, внешний генератор я делю на 2, и в качестве основного клока я хочу использовать 50МГц. Хочу использовать только 50МГц и стробы 10мгц и 1мгц, как Вы советовали. Стробы шириной 20мкс выровнены по фронту клока 50. К сожалению забыл переименовать везде clock_1MHz -> strobe_1MHz возможно из за этого путаница. Сейчас займусь. Но у меня непонимание - почему строб у меня не работает как разрешение счетчика. Quote Share this post Link to post Share on other sites More sharing options...
Raven 29 March 24 Posted March 24 · Report post 59 minutes ago, Mty said: По поводу signal_in - он полностью синхронный, я писал про это чуть выше. Формируется по основному клоку 50Mгц Плохо. Каша имеет место быть. Возникает масса вопросов, вот самые первые: 1) если у вас основной приходящий клок - это clock (@50MHz), то откуда берется в ClockGen еще входной clock_100MHz? Может, лучше тогда его сделать основным? 2) вроде бы договорились, что вместо рядов клоков будем генерировать ряд стробов на частоте основного клока. Так у нас весь дизайн пока будет на одном клоке, что для начинающего лучше (а иногда - и для продолжающего тоже 🙂 ). А у вас - опять одни клоки генерируются из других, и потом еще применяются в остальном дизайне в смеси - так легко можно наворотить не пойми что... 3) Какой клок у вас приходит в чип извне? Или какие клоки - если их несколько? И который из них мы возьмем за основной, и на котором все и будем строить? 1 Quote Share this post Link to post Share on other sites More sharing options...
Mty 0 March 24 Posted March 24 · Report post 14 minutes ago, Raven said: Плохо. Каша имеет место быть. Возникает масса вопросов, вот самые первые: 1) если у вас основной приходящий клок - это clock (@50MHz), то откуда берется в ClockGen еще входной clock_100MHz? Может, лучше тогда его сделать основным? 2) вроде бы договорились, что вместо рядов клоков будем генерировать ряд стробов на частоте основного клока. Так у нас весь дизайн пока будет на одном клоке, что для начинающего лучше (а иногда - и для продолжающего тоже 🙂 ). А у вас - опять одни клоки генерируются из других, и потом еще применяются в остальном дизайне в смеси - так легко можно наворотить не пойми что... 3) Какой клок у вас приходит в чип извне? Или какие клоки - если их несколько? И который из них мы возьмем за основной, и на котором все и будем строить? Кажется заработало! Дело было в том, что в блоке init эмулятора я не проинициализировал clock_50MHz = 0; и он как то потом оживал из вспомогательного клока, который я зачем то сделал, но видимо криво. Ура, работает! Большое спасибо всем кто помогал! Касательно вопросов - 1) С внешнего генератора приходит 100Мгц. Я решил его поделить пополам, чтобы было проще с timing constrains и использовать 50. По быстродействию хватает и 50. 2) Я так и делаю со стробами, надо было переименовать clock_10MHz в strobe_10МГц, а я позабыл, прошу прощения что ввел в заблуждение. Сейчас займусь. 3) Извне 100МГц. Основной я решил сделать 50 пока, этого хватит. Quote Share this post Link to post Share on other sites More sharing options...
Freibier 18 March 24 Posted March 24 · Report post 26 минут назад, Mty сказал: Как раз хочу, внешний генератор я делю на 2, и в качестве основного клока я хочу использовать 50МГц. 1.Тогда клок 100МГц никуда, кроме одного единственного регистра делителя, поступать не должен. 2.Убедиться что сигнал 50МГц назначен как global_clock. А чем 100МГц не устраивает? 1 Quote Share this post Link to post Share on other sites More sharing options...
Mty 0 March 24 Posted March 24 · Report post 4 minutes ago, Freibier said: 1.Тогда клок 100МГц никуда, кроме одного единственного регистра делителя, поступать не должен. 2.Убедиться что сигнал 50МГц назначен как global_clock. А чем 100МГц не устраивает? 1. Сделано, спасибо 2. Сделаю При 100 мгц в timing analyser было куча красных slack. Сильно пугало. Сейчас осталось только 3 в Hold Clock - буду разбираться. А стробы strobe_10МГц strobe_1МГц надо прописывать в SDC файле как clock? Quote Share this post Link to post Share on other sites More sharing options...