调用另一个模块的最佳方式是什么?
What is best way to call another module?
我对连接感到困惑,我想用ALU
调用RippleCarry
模块,我需要做分支而不总是阻塞和过程分配。
我不知道什么方法最好。我看到其他人写在 TestBench.v
或 ALU.v
.
这是我的代码。
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
);
在verilog中,模块不是被调用,而是被实例化。与传统编程不同,verilog 是一种硬件描述语言;这意味着它是描述硬件的代码,而不是像通常的编程语言那样通过 cpu 指定指令 运行。当信号采用不同的值时,硬件不会具体化和非具体化;控制信号简单地定义了输入和输出之间连接的许多不同数据路径中的哪一个。
在你的情况下,你不会写这样的东西:
module ALU(...)
if (Signal == 6'd35) begin
RippleCarry RC(...);
end
endmodule
由于 Signal
是一条控制线,随着硬件 运行s 的变化而改变值,这意味着纹波进位加法器在 Signal
为 35 时存在,而在不是时消失.
相反,应该实例化加法器,它存在于设计中并且始终存在。现在的问题是仅当 Signal
为 35 时才将其输出定向到 ALU 的输出。
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
编辑:我现在看到你想在不使用 always
或 assign
的情况下执行此操作,这不会改变基本设计,但会使其更加晦涩且可扩展性降低,这就是为什么我'留下以上作为参考。在我们只有一个信号操作码的情况下,我们可以简单地实现将信号与 35 进行比较的逻辑,如果在门中不相等则屏蔽输出:
// 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}});
我对连接感到困惑,我想用ALU
调用RippleCarry
模块,我需要做分支而不总是阻塞和过程分配。
我不知道什么方法最好。我看到其他人写在 TestBench.v
或 ALU.v
.
这是我的代码。
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
);
在verilog中,模块不是被调用,而是被实例化。与传统编程不同,verilog 是一种硬件描述语言;这意味着它是描述硬件的代码,而不是像通常的编程语言那样通过 cpu 指定指令 运行。当信号采用不同的值时,硬件不会具体化和非具体化;控制信号简单地定义了输入和输出之间连接的许多不同数据路径中的哪一个。
在你的情况下,你不会写这样的东西:
module ALU(...)
if (Signal == 6'd35) begin
RippleCarry RC(...);
end
endmodule
由于 Signal
是一条控制线,随着硬件 运行s 的变化而改变值,这意味着纹波进位加法器在 Signal
为 35 时存在,而在不是时消失.
相反,应该实例化加法器,它存在于设计中并且始终存在。现在的问题是仅当 Signal
为 35 时才将其输出定向到 ALU 的输出。
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
编辑:我现在看到你想在不使用 always
或 assign
的情况下执行此操作,这不会改变基本设计,但会使其更加晦涩且可扩展性降低,这就是为什么我'留下以上作为参考。在我们只有一个信号操作码的情况下,我们可以简单地实现将信号与 35 进行比较的逻辑,如果在门中不相等则屏蔽输出:
// 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}});