Kias
Kias

Reputation: 37

What is best way to call another module?

I'm confused about connection, I want to use ALU to call RippleCarry module, and I need to do branch without always block and Procedure Assignment.

I don't know what method is best. I see others have written in TestBench.v or ALU.v.

Here's my code.

ALU.v

module ALU( Signal, a, b, Output );
  input [31:0] a, b;
  input [5:0] Signal; 
 
  output [31:0] Output;
 
  //  write here ? or write into test bench?
  // if Signal is 6'd35, do RippleCarry.

  /*RippleCarry RC( .a(a), .b(b), .Sum(Output) ); */

endmodule

RippleCarray.v

module RippleCarry(
  input  [31:0] a, b,
  input Cin,
  output Cout,
  output [31:0] Sum
);
  

Upvotes: 0

Views: 4250

Answers (1)

Unn
Unn

Reputation: 5098

In verilog, modules are not called, but instantiated. Unlike traditional programming, verilog is a hardware descriptive language; meaning it is code describing hardware, not specifying instructions to be run by a cpu as you do in typically programming languages. Hardware doesn't materialize and dematerialize when signals take on different values; the control signals simply define which of many different data paths is connected between input and output.

In your case, you wouldnt write something like this:

module ALU(...)
  if (Signal == 6'd35) begin
    RippleCarry RC(...);
  end
endmodule

Since Signal is a control line that changes value as the hardware runs, this would imply the ripple carry adder exists when the Signal is 35 and disappears when it's not.

Instead, the adder should be instantiated, it exists in the design and it always there. The problem now is to direct it's output to the output of the ALU only when Signal is 35.

module ALU(input [5:0] Signal,
  input [31:0] a, b,
  output reg [31:0] Output); // Note, I made Output a reg so I can use always, it doesn't mean it's actually a register

  wire [31:0] rcOutput;

  // Instantiate the RC adder so it exists in the hardware
  RippleCarry RC(.a(a), .b(b), .Sum(rcOutput));

  // Direct the output of the RippleCarry adder to the output only when signal is 35, otherwise just leave it at 0.
  // Use switch here to make it easy to add more operations later
  always @(*) begin
    Output = 32'd0; // default

    case (Signal)
      6'd35: Output = rcOutput; // rc add
    endcase
  end
endmodule

Edit: I see now you want to do it without using always or assign, which doesn't change the fundamental design but makes it more obscure and less scalable, which is why I'm leaving the above as a reference. In the case we only have one op code for signal, we can simply implement the logic that compares signal to 35 and masks output if not equal in gates:

// Replace the always block with the below, though it's certainly not as nice, it's a possible implementation of that always block in gates
wire [5:0] SignalN;
wire SignalIs35;
not g1[5:0](SignalN, Signal);
// 35 is 100011 in binary, so see if Signal is that value
and g2(SignalIs35, Signal[5], SignalN[4], SignalN[3], SignalN[2], Signal[1], Signal[0]);
and g3[31:0](Output, rcOutput, {32{SignalIs35}});

Upvotes: 2

Related Questions