// Demo 2: Generalize the depth of the pipeline using generate statements

// A parameterized module that adds N to inputs 32-bit input
// Same as in demo 1.
module AddN#(
  parameter N = 1
)(
  input  wire[31:0] x,
  output wire[31:0] y
);

  assign y = x + N;

endmodule

// A parameterized module that instantiates K adders in series
module Pipeline#(
  parameter K = 8
)(
  input  wire[31:0] x,
  output wire[31:0] y
);

  genvar i;
  for (i = 1; i <= K; i = i + 1) begin : Adders
    wire[31:0] xi;
    if (i == 1) 
      AddN#(i) adder(x, xi);
    else
      AddN#(i) adder(Adders[i-1].xi, xi);
  end

  assign y = Adders[K].xi;

endmodule

// Program input
// Same as in demo 1
reg[31:0] v0 = 0;

// Instantiate a pipeline with 10 adders
wire[31:0] v10;
Pipeline#(10) pipeline(v0, v10);

// Things to try:
// 1. Print out the value of v10: should be sum_i=1:10 = 55
// 2. Change the value of v0 and print out the value of v10: should be v0 + 55

// Talking points:
// 1. Cascade emits a warning about being unable to resolve Adders[K].xi --- what's it's problem?
// 2. Instead of printing out v10, try printing pipeline.Adders[10].genblk1.adder.y --- where does this name come from?
