`timescale 1ns/1ps

module top ();

  wire [1:0] lBusA;
  wire [1:0] lBusB;
  wire [1:0] rBusA;
  wire [1:0] rBusB;
  wire [1:0] lrBusA;
  wire [1:0] lrBusB;

  //logic
  lDriver driver1(lBusA[0]);
  lDriver driver2(lBusA[1]);
  lPad pad1(lBusA[0],lBusB[0]);
  lPad pad2(lBusA[1],lBusB[1]);

  //real
  rDriver driver3(rBusA[0]);
  rDriver driver4(rBusA[1]);
  rPad pad3(rBusA[0],rBusB[0]);
  rPad pad4(rBusA[1],rBusB[1]);

  //real/logic mix
  lDriver driver5(lrBusA[0]);
  rDriver driver6(lrBusA[1]);
  lPad pad5(lrBusA[0],lrBusB[0]);
  rPad pad6(lrBusA[1],lrBusB[1]);  

  obsBlock obs1 (
    .obs_lBus(lBusB),
    .obs_rBus(rBusB),
    .obs_lrBus(lrBusB)
  );

endmodule

module rDriver (
  output real r
);
  real rVal;
  assign r = rVal;
  initial begin
    rVal = 0.0;
    #5
    rVal = 1.2;
    #5
    rVal = 2.4;
  end
endmodule

module rPad (
 input  real rIn,
 output real rOut
);
  assign rOut = rIn * 2.0;
  always @(rIn) $display("[pad] Real: %e [%e]\n",rIn,$time);
endmodule

module lDriver (
  output logic l
);
  initial begin
    l <= 1'b0;
    #5
    l <= 1'b1;
    #15
    l <= 1'b0;
  end
endmodule

module lPad (
  input  logic lIn,
  output logic lOut
);
  assign lOut = ~lIn;
  always @(lIn) $display("[pad] Logic: %b [%e]\n",lIn,$time);
endmodule

module obsBlock (
  input [1:0] obs_lBus,
  input [1:0] obs_rBus,
  input [1:0] obs_lrBus
);
  lMod mod1(obs_lBus[0]);
  lMod mod2(obs_lBus[1]);

  rMod mod3(obs_rBus[0]);
  //Mixed I/O
  rMod mod4(obs_rBus[1]);
  lMod mod5(obs_rBus[1]);

  //Mixed bus
  lMod mod6(obs_lrBus[0]);
  rMod mod7(obs_lrBus[1]);

endmodule

module rMod (
 input real r
);
  always @(r) $display("[mod] Real: %e [%e]\n",r,$time);
endmodule

module lMod (
  input logic l
);
  always @(l) $display("[mod] Logic: %b [%e]\n",l,$time);
endmodule
