module periodic_rd_ctrl #(parameter tCK = 2500, nCK_PER_CLK = 2, TCQ = 100, MAINT_PRESCALER_PERIOD = 200000) (
		input clk,
		input rst,
		
		input dfi_init_complete,
		input maint_prescaler_tick,
		
		input periodic_rd_ack, //NOTE: this also should be asserted for regular reads
		output periodic_rd_req
	);
	
	function integer clogb2 (input integer size); // ceiling logb2
    begin
      size = size - 1;
      for (clogb2=1; size>1; clogb2=clogb2+1)
            size = size >> 1;
    end
	endfunction // clogb2
	
	localparam tPRDI = 1_000_000;
	localparam PERIODIC_RD_TIMER_DIV = tPRDI/MAINT_PRESCALER_PERIOD;
	localparam PERIODIC_RD_TIMER_WIDTH = clogb2(PERIODIC_RD_TIMER_DIV + /*idle state*/ 1);
	localparam ONE = 1;
	 
	reg [PERIODIC_RD_TIMER_WIDTH-1:0] periodic_rd_timer_r, periodic_rd_timer;
	reg periodic_rd_request_r;
	 
	always @* begin
		periodic_rd_timer = periodic_rd_timer_r;
		
		if(~dfi_init_complete) begin
			periodic_rd_timer = {PERIODIC_RD_TIMER_WIDTH{1'b0}};
		end
		else if (periodic_rd_ack) begin
			periodic_rd_timer = PERIODIC_RD_TIMER_DIV[0+:PERIODIC_RD_TIMER_WIDTH];
		end
		else if (|periodic_rd_timer_r && maint_prescaler_tick) begin
			periodic_rd_timer = periodic_rd_timer_r - ONE[0+:PERIODIC_RD_TIMER_WIDTH];
		end
	end //always
	 
	wire periodic_rd_timer_one = maint_prescaler_tick && (periodic_rd_timer_r == ONE[0+:PERIODIC_RD_TIMER_WIDTH]);
	 
	wire periodic_rd_request = ~rst && (/*((PERIODIC_RD_TIMER_DIV != 0) && ~dfi_init_complete) ||*/
                      (~periodic_rd_ack && (periodic_rd_request_r || periodic_rd_timer_one)));
	 
	always @(posedge clk) begin
		periodic_rd_timer_r <= #TCQ periodic_rd_timer;
		periodic_rd_request_r <= #TCQ periodic_rd_request;
	end //always
	
	assign periodic_rd_req = periodic_rd_request_r;
	
endmodule