Jump to content
    

Синтез задержек большой величины (5ms, 10ms, 50ms, 200ms и более) с использованием минимума ресурсов

Про 25МГц, честно говоря,  не понял.  У меня их нет. Модуль с W5500, типа такого

https://iarduino.ru/shop/Expansion-payments/setevoy-modul-w5500-tsr-ip-ethernet.html

подключается по SPI к FPGA.

    //интерфейс с W5500
    output     W5500_MOSI    ,
    input       W5500_MISO    ,
    output     W5500_SCK    ,
    output     W5500_SSEL
    //output    W5500_RST    ,

Ну от прерываний там еще пин есть. И все вроде.

По поводу нужности задержек - этот топик как раз и появился по причине того, что реализовать все задержки малыми ресурсами я не смог придумать как, а загонять под их реализацию кучу логики, учитывая что это, не конечный проект, а просто интерфейс для передачи данных, который хотелось бы потом вставлять куда потребуется, в том числе и, возможно, во всякую, совсем мелочь, мелочь, короче так [censored] LE пока рука не поднимаются, так и пользуюсь пока одной задержкой 10ms типа soft reset, хотя можно и без нее, только тогда желаемый mac адрес немного портится, что не критично.

 

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

Накидал вот такой код

module FPGA_TOP #(
		parameter CLK_IN_HZ 		= 50_000_000
)(
	input 		clk			,		//Clock 50MHz
	input 		rst_n			,		//RESET
	input [1:0]	State			,

	output reg 	tick_200ms	,
	output reg 	tick_50ms	,
	output reg 	tick_10ms


);



`ifdef SMOLL_RESURSES


//--------------------------------------
assign zad200 = (State == 2'b11);
//--------------------------------------
reg _zad200;
always @(posedge clk)
	_zad200 <= zad200;

wire load_cnt_200ms;
assign load_cnt_200ms = ~_zad200 & zad200;


//--------------------------------------
assign zad50 = (State == 2'b10);
//--------------------------------------
reg _zad50;
always @(posedge clk)
	_zad50 <= zad50;

wire load_cnt_50ms;
assign load_cnt_50ms = ~_zad50 & zad50;


//--------------------------------------
assign zad10 = (State == 2'b01);
//--------------------------------------
reg _zad10;
always @(posedge clk)
	_zad10 <= zad10;

wire load_cnt_10ms;
assign load_cnt_10ms = ~_zad10 & zad10;


	
	
	localparam 	PARAM_ZAD_200MS = 200;
	localparam					CUR_CNT_200MS = CLK_IN_HZ/1000*PARAM_ZAD_200MS;			// величина счетчика, соответсвующая требуемой задержке
	localparam							 CNT_WH = $clog2(CUR_CNT_200MS);						// сширина счечика, сколько разрядов нужно, чтобы сформировать требуемую задержку
	localparam [CNT_WH:0] INIT_CNT_200MS  = (1<<CNT_WH) - CUR_CNT_200MS + 1;		// (1<<CNT_WH) = 2^CNT_WH = MAX_CNT = 2^19 = 524_288 

	localparam 	PARAM_ZAD_50MS = 50;
	localparam	  			  CUR_CNT_50MS = CLK_IN_HZ/1000*PARAM_ZAD_50MS;				// величина счетчика, соответсвующая требуемой задержке
	localparam [CNT_WH:0] INIT_CNT_50MS = (1<<CNT_WH) - CUR_CNT_50MS + 1;			// (1<<CNT_WH) = 2^CNT_WH = MAX_CNT = 2^19 = 524_288 

	localparam 	PARAM_ZAD_10MS = 10;
	localparam					CUR_CNT_10MS = CLK_IN_HZ/1000*PARAM_ZAD_10MS;			// величина счетчика, соответсвующая требуемой задержке
	localparam [CNT_WH:0] INIT_CNT_10MS  = (1<<CNT_WH) - CUR_CNT_10MS + 1;			// (1<<CNT_WH) = 2^CNT_WH = MAX_CNT = 2^19 = 524_288 



reg [CNT_WH-1:0] cnt;

always @(posedge clk or negedge rst_n)
if (!rst_n) begin

	cnt 			<=  'd0;
	tick_200ms 	<= 1'b0;
	tick_50ms 	<= 1'b0;
	tick_10ms 	<= 1'b0;

end else begin

	case(State)
		2'b11:	begin

						if(load_cnt_200ms)
							{tick_200ms, cnt} <= INIT_CNT_200MS;
						else
							if (tick_200ms)
								tick_200ms <= 1'b0;
							else
								{tick_200ms, cnt} <= {tick_200ms, cnt} + 1'b1;
					 
					end
					
		2'b10:	begin
		
						if(load_cnt_50ms)
							{tick_50ms, cnt} <= INIT_CNT_50MS;
						else
							if (tick_50ms)
								tick_50ms <= 1'b0;
							else
								{tick_50ms, cnt} <= {tick_50ms, cnt} + 1'b1;
							
					end
		2'b01:	begin
		
						if(load_cnt_10ms)
							{tick_10ms, cnt} <= INIT_CNT_10MS;
						else
						
							if (tick_10ms)
								tick_10ms <= 1'b0;
							else
								{tick_10ms, cnt} <= {tick_10ms, cnt} + 1'b1;
					
					end
		default:		begin 
							cnt 			<= 'd0;
						end
	endcase

end









`else





//Счетчик задержки 200 мс
reg [23:0] Delay200_1;
always @(posedge clk or negedge rst_n)
	if (!rst_n) begin	
		Delay200_1 <= 24'd0;
		tick_200ms <= 1'b0;
	end else 
		if (State == 2'b11)	
			Delay200_1 <= Delay200_1 + 1'b1;
		else begin
			if(Delay200_1 == 24'd10000000) begin
				Delay200_1 <= 24'd0;
				tick_200ms <= 1'b1;
			end else
				tick_200ms <= 1'b0;
			
		end

//Счетчик задержки 50 мс
reg [23:0] Delay50_1;
always @(posedge clk or negedge rst_n)
	if (!rst_n) begin	
		Delay50_1 <= 24'd0;
		tick_50ms <= 1'b0;
	end else 
		if (State == 2'b10)	
			Delay50_1 <= Delay50_1 + 1'b1;
		else begin
			if(Delay50_1 == 24'd2500000) begin
				Delay50_1 <= 24'd0;
				tick_50ms <= 1'b1;
			end else
				tick_50ms <= 1'b0;
			
		end
	
//Счетчик задержки 10 мс
reg [23:0] Delay10_1;
always @(posedge clk or negedge rst_n)
	if (!rst_n) begin	
		Delay10_1 <= 24'd0;
		tick_10ms <= 1'b0;
	end else 
		if (State == 2'b01)		
			Delay10_1 <= Delay10_1 + 1'b1;
		else begin
			if(Delay10_1 == 24'd500000) begin	
				Delay10_1 <= 24'd0;
				tick_10ms <= 1'b1;
			end else
				tick_10ms <= 1'b0;
			
		end
	
`endif


endmodule

Реализация в лоб: Total logic elements - 105, Total registrs - 75

мои попытки:        Total logic elements - 162, Total registrs - 30

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

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

 

Share this post


Link to post
Share on other sites

1 hour ago, tems-ya said:

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

В конечном продукте, помимо интерфейса могут быть события:

  • регулярное событие №0 каждые 10мс
  • регулярное событие №1 и событие №2 с разницей между ними  20мс.

Может проще на маленькой ПЛИС блок задержек сделать отдельным общим модулем для всех остальных? А сейчас организовать к нему выводы.

 

Share this post


Link to post
Share on other sites

2 часа назад, tems-ya сказал:

остался только вариант с памятью

Вообще-то, первый вариант — снаружи навесить генератор, на логическом элементе и RC или часовом кварце, либо жабоудушенный, на входах/выходах ПЛИС, и если сейчас тоже вдруг выяснится, что речь изначально была не о голой ПЛИС, а об ещё одной демоплате, то он как раз годится.

Share this post


Link to post
Share on other sites

Внутренний генератор, внешний генератор,  доп. маленькая FPGA только для задержек, ... можно ещё и внешние таймеры на 555 прилепить или даже песочные часы с фотоэлементом и моторчиком чтобы оные переворачивать ...  

Чего только не нагородишь  если нет чёткого понимания "А что же нужно?" ... 

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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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...