module registro_serie
#(
	parameter WIDTH=16,
	parameter REGISTER_NUMBER=21
)
(
	input 												clk,rst,
	input		[WIDTH-1:0]								new_data,
	input													move,
	input 												save,
	output	[REGISTER_NUMBER*WIDTH-1:0]		registro,
	output	[4:0]										id
);

function integer clog2;
input integer value;
begin 
value = value-1;
for (clog2=0; value>0; clog2=clog2+1)
value = value>>1;
end 
endfunction

//Declaración de señales
reg [REGISTER_NUMBER*WIDTH-1:0] registro_reg,registro_next;
reg [4:0] i_reg,i_next;
//Registro de filas
genvar i;
generate
for (i=0;i<=REGISTER_NUMBER-1;i=i+1) begin :generate_registros
	always@(posedge rst, posedge clk)
	if (rst)
		registro_reg[WIDTH*(i+1)-1:WIDTH*i] <= 3'b000;
	else
		registro_reg[WIDTH*(i+1)-1:WIDTH*i] <= registro_next[WIDTH*(i+1)-1:WIDTH*i];
	end
endgenerate

generate
for (i=1;i<=REGISTER_NUMBER-1;i=i+1) begin :generate_registro_next
	always@(*)
	begin
	if (move)
		registro_next[WIDTH*(i+1)-1:WIDTH*(i)]= registro_reg[WIDTH*i-1:WIDTH*(i-1)];
	else
		registro_next[WIDTH*(i+1)-1:WIDTH*(i)]= registro_reg[WIDTH*(i+1)-1:WIDTH*(i)];
	end
end
endgenerate

always@(*)
begin
if	(save)
	registro_next[WIDTH-1:0]=new_data;
else if (move)
	registro_next[WIDTH-1:0]=registro_reg[WIDTH*REGISTER_NUMBER-1:WIDTH*(REGISTER_NUMBER-1)];
else
	registro_next[WIDTH-1:0]=registro_reg[WIDTH-1:0];
end

assign registro=registro_reg;

always@(posedge rst,posedge clk)
begin
if (rst)
	i_reg=5'h00;
else
	i_reg=i_next;
end

always@(*)
begin
i_next=i_reg;
if (move)
begin
	if (i_reg==REGISTER_NUMBER-1)
	begin
		i_next=5'h00;
	end
	else
	begin
		i_next=i_reg+1'b1;
	end
end
else
begin
	i_next=i_reg;
end
end

assign id = i_reg;

endmodule
