Electrical – verilog module inside an if-statement

verilog

I have to build a circuit of an arithmetic right shift operator in verilog and include it in a verilog code of a simple computer. I've written the code of the circuit with a module and it compiles without an error but when I try to include it in the code of the computer(it has to be in an if-statement) an error occurs: "error: syntax error, unexpected MODULE" is it possible to include a module in an if-statement?

 always @(alu_A or alu_B or aluop)
if      (aluop==0)    alu <= alu_A;
else if (aluop==1)    alu <= alu_A + alu_B;
else if (aluop==2)    alu <= alu_A - alu_B;
else if (aluop==3)    alu <= alu_A & alu_B;
else if (aluop==4)    alu <= alu_A ^ alu_B;
else if (aluop==5)    alu <= alu_A << alu_B[3:0];
//else if (aluop==6)    alu <= right_shift(alu_A, alu_B[3:0]);
else 
 begin
 module right_shift (alu_A,alu_B,alu);
input [15:0] alu_A;
input [3:0] alu_B;
output [15:0] alu;

this is a piece of the code: the comment is the old piece of code where right shift is done everything beneath are the changes i've done. I did not comment the whole code because it is very big

Best Answer

It is important to remember that with Verilog you are describing hardware, not writing software. Modules are instances of hardware. They can't be called and they don't return a value.

You can't instantiate a module conditionally within an if statements (*), and you definitely can't instantiate them within procedural blocks. If you consider what such a statement would describe it becomes clear as to why not. With a module instantiation within an if statement you are basically saying:

If signal is high, make some hardware appear; otherwise delete the hardware.

FPGAs can't work like that. All hardware is described and fixed at synthesis.

Instead what you need to do is instantiate your hardware (in this case right shift module) not within the if statement or procedural block. Connect the output of that module to a wire. Now your hardware is always present, regardless of the control signals. So how do you make use of it conditionally?

This is quite simple. Within the if statement you can use your wire. If a condition is met assign the wire to whatever signal you are controlling. Otherwise assign some other signal.

wire module_output_wire;
...
always @ (...) begin
    ...
    if (some_condition) begin
        some_signal <= module_output_wire;
    end else begin
        some_signal <= something_else;
    end
end
...
your_module (
    .whatever(module_output_wire)
);

The reason this now works is because rather than trying to infer transient hardware, you are now inferring a simple multiplexer. The inputs to the multiplexer are the module_output_wire and something_else, the select signal is some_condition, and the output of the multiplexer is some_signal. The hardware always exists, but you don't always need to use the output value.

As an alternative, you could make your right shift code a function. A function in Verilog can be called in the way you show on the commented out line in your code. In the case of the function you are inferring hardware that is always there and the output of the hardware is a wire (the return value of the function) which you can then use in an always block.


(*) With the exception of in Verilog 2001 Generate statements, but in that case the condition is known at compile time, it doesn't depend on the value of a signal.