// Realizacion de la Unidad de Datos del Multiplicador
// Rev: 3 (EdC-IC), apr 2021

/* Unidad de datos: Descripcion estructural
 * Se instancian e interconectan todos sus componentes 
 */
module u_datos(
 input [3:0] data, // Dato a
 input [3:0] datb, // Dato b
 input clk,wa,upcont,clsincr,
 input wd,wsumh,wsuml,shrsum,
 output [7:0] busc, // Bus de salida
 output cycont
);

 wire [3:0] busa;
 wire [3:0] busb;
 wire cable_and,q,cout;

 // Instancia del registro A
 reg_a A(.din(data),.cl(clsincr),
         .clk(clk),.w(wa),.dout(busa));
 // Instancia del sumador
 sumador_4 SUMADOR(.a(busa),.b(busc[7:4]),
                   .res(busb),.cout(cout));
 // Instancia del registro de desplazamiento para SUMH             
 reg_despl SUMH(.din(busb),.cl(clsincr),
                .w(wsumh),.clk(clk),.shr(shrsum),
                .sri(q),.dout(busc[7:4]));
 // Otra instancia del registro de desplazamiento para SUML
 reg_despl SUML(.din(datb),.cl(clsincr),
                .w(wsuml),.clk(clk),.shr(shrsum),
                .sri(busc[4]),.dout(busc[3:0]));
 // Instancia del biestable d           
 biestable_d BIESTABLE_D(.clk(clk),.cl(clsincr),.w(wd),
                       .d(cable_and),.q(q));
 // Instancia del contador
 cont_4 CONT_4(.clk(clk),.cl(clsincr),.cy(cycont),
               .up(upcont));
 // Una simple puerta and de 2 entradas               
 and P_AND(cable_and,busc[0],cout);

endmodule



// Registro A
module reg_a (
 input clk,cl,w,
 input [3:0] din,
 output reg [3:0] dout
 );
 
 always@(posedge clk)
  begin
    if(cl)
    dout <= 0;
   else if(w)
    dout <= din;
  end
endmodule

// Sumador de 4 bits
module sumador_4(
 input [3:0] a,
 input [3:0] b,
 output [3:0] res,
 output cout
 );
 assign {cout,res} = a + b;
endmodule

// Contador modulo 4
module cont_4(
 input clk,cl,up,
 output cy
 );
 
 reg [1:0] q;
 
 always@(posedge clk)
 begin
  if(cl)
    q <= 0;
  else if(up)
    q <= q + 1;
   end
 assign cy=&q; 
endmodule

// Registro de desplazamiento
module reg_despl(
 input clk,cl,shr,w,sri,
 input [3:0] din,
 output reg [3:0] dout);
 
 always@(posedge clk)
 begin
  if(cl)
   dout <= 0;
  else if(w)
   dout <= din;
  else if(shr)
   dout <= {sri,dout[3:1]};
 end
endmodule

// Biestable D para capturar el carry del sumador
module biestable_d(
 input clk,cl,d,w,
 output reg q);
 
 always @(posedge clk)
 begin
  if(cl)
   q <= 0;
  else if(w)
   q <= d;
  else
   q <= q;
 end
 
endmodule

