
module mux41 #(parameter N=6)(
    input [1:0] sel,
    input [N-1:0] IN0,IN1,IN2,IN3,

	 output reg [N-1:0] z
    );

always @*
	case (sel)
		0: z=IN0;
		1: z=IN1;
		2: z=IN2;
		3: z=IN3;
	endcase
	
endmodule

module dec2a4_en(
    input en,
    input [1:0] d,
    output reg [3:0] w
    );
	 
	 always @* begin
	 w=0;
	 if (en==0)
	 w[d]=1;
	 end

endmodule

module registro_w_busin_busout #(parameter N=4,valorinicial=0)(
//module registro_w_busin_busout (

    input [N-1:0] Din,
    input w,
	 input ck,
    output [N-1:0] Dout
    );
//parameter N=4;

reg [N-1:0] q;

initial
q = valorinicial;

always @(posedge ck)
	if (w)
	q<=Din;
assign Dout = q;

endmodule

module problema9 #(parameter M=8)(
    input [1:0] s,
    input en,
    input [1:0] d,
	 input ck
    );
//descripcion estructural

wire [M-1:0] out[0:3];
wire [M-1:0] mux_out;
wire [3:0] w;

mux41 #(.N(M)) mimux (.sel(s),.IN3(out[3]),.IN2(out[2]),.IN1(out[1]),.IN0(out[0]),.z(mux_out));
dec2a4_en midec (.d(d),.en(en),.w(w));
registro_w_busin_busout #(.N(M),.valorinicial(10)) regA (.Din(mux_out),.w(w[0]),.ck(ck),.Dout(out[0]));
registro_w_busin_busout #(.N(M),.valorinicial(20)) regB (.Din(mux_out),.w(w[1]),.ck(ck),.Dout(out[1]));
registro_w_busin_busout #(.N(M),.valorinicial(30)) regC (.Din(mux_out),.w(w[2]),.ck(ck),.Dout(out[2]));
registro_w_busin_busout #(.N(M),.valorinicial(40)) regD (.Din(mux_out),.w(w[3]),.ck(ck),.Dout(out[3]));

endmodule



module problema9 #(parameter M=8)(
    input [1:0] s,
    input en,
    input [1:0] d,
	 input ck
    );
reg [M-1:0] REG[3:0]; //definición de los cuatro registros
	always @(posedge ck)
	if (en==0)
		REG[d]<=REG[s];
	initial
		begin
			REG[0]=10;
			REG[1]=20;
			REG[2]=30;
			REG[3]=40;
		end
endmodule


`timescale 1ns / 1ps


module problema9_tb;

	// Inputs
	reg [1:0] s;
	reg en;
	reg [1:0] d;
	reg ck;

	// Instantiate the Unit Under Test (UUT)
	problema9 uut (
		.s(s), 
		.en(en), 
		.d(d), 
		.ck(ck)
	);

	always begin
	#10;
	ck = ~ck;
	end
	
	initial begin
		// Initialize Inputs
		s = 0;
		en = 0;
		d = 0;
		ck = 1;

		// Wait 10 ns for global reset to finish
		#10;
		d=3;
		
		@(negedge ck);
		en= 1; s=3;
		
		@(negedge ck);
		en=0; d=0; s=1;
		
		@(negedge ck);
		d=1; s=2;
		
		@(negedge ck);
		en= 1; d=0; s=0;
		
		@(negedge ck);
		en= 0; d=2; s=3;
		
		@(negedge ck);
		$finish;
		
		// Add stimulus here

	end
      
endmodule

