Reputation: 37
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
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