【发布时间】:2016-02-26 14:12:44
【问题描述】:
假设module_a 中有register_a,它需要链接到module_b。 register_a 是否应该单独声明并分配给module_a 的输出:
reg register_a;
assign output_a = register_a;
或者我们应该在模块声明中使用 reg 内联声明 output_a 并在代码中使用它?
【问题讨论】:
假设module_a 中有register_a,它需要链接到module_b。 register_a 是否应该单独声明并分配给module_a 的输出:
reg register_a;
assign output_a = register_a;
或者我们应该在模块声明中使用 reg 内联声明 output_a 并在代码中使用它?
【问题讨论】:
我想你是在问以下之间的区别:
module my_dff (output reg q, input clk, d); //None Blocking style
always @(posedge clk) begin
q <= d;
end
endmodule
对
module my_dff (output q, input clk, d);
reg reg_q;
assign q = reg_q; // Blocking style
always @(posedge clk) begin
reg_q <= d;
end
endmodule
两者之间没有功能上的区别。这主要是一种编码偏好。有很多模拟器不强制输入和输出的方向,所以如果意外有两个模块驱动同一个网络,那些模拟器 X 可以将 X 传播到带有output reg 的寄存器。这是一种罕见的情况,大多数模拟器(尤其是主流模拟器)都没有这个问题。
我个人更喜欢output reg,主要是因为它的代码行数更少。
无论输出类型如何声明,当您实例化模块时,输出需要连接到网络类型(例如wire),而不是reg。输入可以是任何一种类型。
module fifo(output out, input clk, in);
wire q0;
reg q1;
my_dff dff0 ( q0, clk, in );
always @(posedge clk) begin
q1 <= q0;
end
my_dff dff1 ( out, clk, q1 );
endmodule
【讨论】:
我假设您正在寻找这样的东西:
module module_b (...);
....
module_a foo (.output_a(some_wire),
...);
endmodule
如果是这种情况,那就没关系 - 两个版本都会产生相同的结果电路。
第一种方法确实有一些优点,即您可以根据需要对输出进行门控(类似于assign output_a = valid ? register_a : 0;),并且如果为您定义了接口(例如例如,预设引脚映射)。
如果您不尝试执行上述操作,那么这可能不是真的。
【讨论】:
我读到应该始终注册输出。也就是说module_a有一个名为output_a的输出。这是一种行为与顺序的代码风格。确实,您可以通过任何一种方式创建相同的硬件,但我认为您的问题的答案是您应该将输出声明为 reg。
所以模块声明应该是这样的:
module module_a (output reg output_a);
....
output_a <= "some value"
endmodule
【讨论】:
reg)。不必注册每个模块的输出。然而,更重要的是,verilog reg 不是触发器。因此,如果您确实认为是这种情况,请放弃这个想法。
reg 是 Verilog 变量(相对于 wire 是一个网络)。 reg 就像任何其他语言中的变量一样:分配给它的最后一个值就是它拥有的值。您可以使用reg 来推断组合逻辑或顺序逻辑。