Jump to content
    

Посоветуйте - как сделать цепочку из 2х делителей клока на 10 на verilog

3 hours ago, blackfin said:

Вот, держите:

one_shot_pulse.txt
detect_clock.txt
rst_pulse.txt

PS. В симуляторе не проверял, возможно, где-то ошибся.. Сами проверите..
PPS. Красоту не наводил.. Сами наведёте.. ))

Ого, Огромное спасибо!
Скачал, буду разбираться!

Share this post


Link to post
Share on other sites

Спасибо всем за советы, переписал проект на стробы, и сделал что все синхронизируется одним клоком 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

 

2025-03-24 15_43_25-RTL Viewer - C__intelFPGA_lite_Proj_DriverCtl1_MaxV_DriverCtl1_MaxV - DriverCtl1.png

Share this post


Link to post
Share on other sites

Если signal_in внешний асинхронный сигнал, то вы нарвались на метастабильность. Это классика.

Для всех входных асинхронных сигналов надо делать CDC (clock domain crossing). В простейшем случае это цепочка из двух триггеров.

Share this post


Link to post
Share on other sites

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

 

2025-03-24 15_43_25-RTL Viewer - C__intelFPGA_lite_Proj_DriverCtl1_MaxV_DriverCtl1_MaxV - DriverCtl1.png

Проблема в логике мышления.  signal in  при таком подходе должен иметь признак. На раз два три рассчитайсь.  Неужели простого сторожевого тамерс не достаточно.

Share this post


Link to post
Share on other sites

1 час назад, Mty сказал:
input  wire strobe_1MHz,  //  Ширина строба 20нс начинается и заканчивается по фронту clock
1 час назад, Mty сказал:
if( clock_1MHz ) // ENA - здесь разрешение счета. Но регистр PauseCounter_reg всегда в 0 в составе проекта

что-то тут не то

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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
 

 

Share this post


Link to post
Share on other sites

1 час назад, Mty сказал:

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

// При появлении signal_in выставляется pause_reg
// При снятии сигнала signal_in начинает отсчитываться пауза
// Если в течении паузы пришел 2 раз signal_in - выдается pause_err_reg до сброса

По мне - это как себя своей рукой из болота вытащить. Язык тут не причем. Функционал скользкий. 

Чтоб поднять то, что Вам предлагают, без тестбенча не разобрать.  Писать надо просто. Чтоб понятно было. Не надо сразу хвататься описать все в одном процессе. 

Просто пример. И я замолкаю.

ct_div.zip

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

31 минуту назад, Mty сказал:
always @(posedge raw_clock_50MHz)

Как я понял, синхронный проект вы делать принципиально не хотите?

Share this post


Link to post
Share on other sites

21 minutes ago, Freibier said:

Как я понял, синхронный проект вы делать принципиально не хотите?

Как раз хочу, внешний генератор я делю на 2, и в качестве основного клока я хочу использовать 50МГц.

Хочу использовать только 50МГц и стробы 10мгц и 1мгц, как Вы советовали. Стробы шириной 20мкс выровнены по фронту клока 50.
К сожалению забыл переименовать везде clock_1MHz -> strobe_1MHz возможно из за этого путаница. Сейчас займусь.

Но у меня непонимание - почему строб у меня не работает как разрешение счетчика.

Share this post


Link to post
Share on other sites

59 minutes ago, Mty said:

По поводу signal_in - он полностью синхронный, я писал про это чуть выше.
Формируется по основному клоку 50Mгц

Плохо. Каша имеет место быть. Возникает масса вопросов, вот самые первые:

1) если у вас основной приходящий клок - это clock (@50MHz), то откуда берется в ClockGen еще входной clock_100MHz? Может, лучше тогда его сделать основным?

2) вроде бы договорились, что вместо рядов клоков будем генерировать ряд стробов на частоте основного клока. Так у нас весь дизайн пока будет на одном клоке, что для начинающего лучше (а иногда - и для продолжающего тоже 🙂 ). А у вас - опять одни клоки генерируются из других, и потом еще применяются в остальном дизайне в смеси -  так легко можно наворотить не пойми что...

3) Какой клок у вас приходит в чип извне? Или какие клоки - если их несколько? И который из них мы возьмем за основной, и на котором все и будем строить?

Share this post


Link to post
Share on other sites

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 пока, этого хватит.

Share this post


Link to post
Share on other sites

26 минут назад, Mty сказал:

Как раз хочу, внешний генератор я делю на 2, и в качестве основного клока я хочу использовать 50МГц.

1.Тогда клок 100МГц никуда, кроме одного единственного регистра делителя, поступать не должен.

2.Убедиться что сигнал 50МГц назначен как global_clock.

А чем 100МГц не устраивает?

 

Share this post


Link to post
Share on other sites

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?

 

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