module control
#(
	parameter top=350*350,
	parameter endmember=21,
	parameter WIDTH=16
)
(
	input clk,rst,
	input req,
	input ack_mem,ack_NFNDR,
	input [(endmember-1)*WIDTH-1:0]data,
	
	output reg req_mem,new_pixel,init_NFINDR,
	output [16:0]position,
	output [16:0]memory_position,
	output [(endmember-1)*WIDTH-1:0]pixel,
	output ack
);

wire [16:0] cont_reg,cont_next,rand_reg,rand_next;
reg rst_counter,en_counter,rst_rand,en_rand,en_reg,sel_rand;
reg [(endmember-1)*WIDTH-1:0] register;
reg ack_reg,ack_next;
reg [3:0] state_reg,state_next;
wire [4:0] counter_rand;
localparam 	s_idle		=4'd0,
				s_rand_mem	=4'd1,
				s_rand_reg	=4'd2,
				s_rand_NFNDR=4'd3,
				s_rand_comp	=4'd4,
				s_cont_mem	=4'd5,
				s_cont_reg	=4'd6,
				s_cont_NFNDR=4'd7,
				s_cont_comp	=4'd8,
				s_ack			=4'd9;

always@(posedge clk,posedge rst)
begin
if(rst)
	state_reg <= 3'b000;
else
	state_reg <= state_next;
end

always@(*)
begin
req_mem=1'b0;
new_pixel=1'b0;
init_NFINDR=1'b0;
rst_counter=1'b0;
rst_rand=1'b0;
en_counter=1'b0;
en_rand=1'b0;
state_next= state_reg;
sel_rand=1'b0;
ack_next=1'b0;
en_reg=1'b0;
case(state_reg)
s_idle		:
begin
rst_rand=1'b1;
rst_counter=1'b1;
en_rand=1'b1;
en_counter=1'b1;
if (req)
	begin
	init_NFINDR=1'b1;
	state_next=s_rand_mem;
	end
end
s_rand_mem	:
begin
req_mem=1'b1;
sel_rand=1'b1;
if (ack_mem)
	state_next=s_rand_reg;
end
s_rand_reg	:
begin
	en_reg=1'b1;
	en_rand=1'b1;
	sel_rand=1'b1;
	state_next=s_rand_NFNDR;
end
s_rand_NFNDR:
begin
	req_mem=1'b1;
	new_pixel=1'b1;
	sel_rand=1'b1;
	if (ack_NFNDR)
		state_next=s_rand_comp;
end
s_rand_comp	:
begin
	req_mem=1'b1;
	sel_rand=1'b1;
	if (counter_rand==20)
		state_next=s_cont_mem;
	else
		state_next=s_rand_mem;
end
s_cont_mem	:
begin
req_mem=1'b1;
if (ack_mem)
	state_next=s_cont_reg;
end
s_cont_reg	:
begin
en_reg=1'b1;
en_counter=1'b1;
state_next=s_cont_NFNDR;
end
s_cont_NFNDR:
begin
req_mem=1'b1;
new_pixel=1'b1;
if (ack_NFNDR)
	state_next=s_cont_comp;
end
s_cont_comp	:
begin
req_mem=1'b1;
if (cont_reg==top-1)
	state_next=s_ack;
else
	state_next=s_cont_mem;
end
s_ack			:
begin
ack_next=1'b1;
if(req)
	state_next=state_reg;
else
	state_next=s_idle;
end
default:
begin
req_mem=1'b0;
new_pixel=1'b0;
init_NFINDR=1'b0;
rst_counter=1'b0;
rst_rand=1'b0;
en_counter=1'b0;
en_rand=1'b0;
state_next= state_reg;
sel_rand=1'b0;
end
endcase
end

counter #(.top(top)) stage_counter
(
	.clk(clk),
	.rst(rst),
	.rst_counter(rst_counter),
	.en_counter(en_counter),
	.cont_reg(cont_reg),
.cont_next(cont_next)
);

rand_counter #(.top(endmember-1)) stage_rand_counter
(
	.clk(clk),
	.rst(rst),
	.rst_rand(rst_rand),
	.en_rand(en_rand),
	.rand_reg(rand_reg),
	.rand_next(rand_next),
	.counter(counter_rand)
);

assign position=(sel_rand)?rand_reg:cont_reg;
assign memory_position=(sel_rand)?rand_next:cont_next;

always@(posedge clk,posedge rst)
begin
if (rst)
	register<=3'b000;
else if(en_reg)
	register<=data;
end

assign pixel=register;

always@(posedge clk,posedge rst)
begin
if (rst)
	ack_reg<=1'b0;
else
	ack_reg<=ack_next;
end

assign ack=ack_reg;

endmodule
