我有一个浮点加法凿模块,我想使用它,它有几个阶段的管道。我想让它可以安装,这样我就可以将它放入一个管道中,该管道可能无法在任何给定时间消耗输出数据,因此我希望将部分计算的加法存储在模块中。
我最初希望我可以添加一个启用信号,然后将其添加为更新各种寄存器的另一个条件,但不幸的是,该模块包含许多形式为Reg(next=xxx)的语句。我很好奇,如果我只是把寄存器分配给它自己会发生什么,尽管它的输入已经通过next=xxx分配了,所以我做了一个测试模块,得到了一些(在我看来)奇怪的结果。
这是scala:
package Hello
import Chisel._
class Hello extends Module {
val io = new Bundle {
val in = UInt(INPUT, 8)
val en = Bool(INPUT)
val out = UInt(OUTPUT, 8)
}
val test_reg = Reg(next = io.in)
io.out := test_reg
when (!io.en) {
test_reg := test_reg
}
}
object Hello {
def main(args: Array[String]): Unit = {
}
}
这是生成的verilog:
module Hello(input clk,
input [7:0] io_in,
input io_en,
output[7:0] io_out
);
reg [7:0] test_reg;
wire[7:0] T0;
wire T1;
`ifndef SYNTHESIS
// synthesis translate_off
integer initvar;
initial begin
#0.002;
test_reg = {1{$random}};
end
// synthesis translate_on
`endif
assign io_out = test_reg;
assign T0 = T1 ? test_reg : io_in;
assign T1 = io_en ^ 1'h1;
always @(posedge clk) begin
if(T1) begin
test_reg <= test_reg;
end else begin
test_reg <= io_in;
end
end
endmodule
我感到奇怪的是,verilog似乎几乎以两种不同的方式实现了enable。它使用T1(!en)在test_reg和io_in之间进行多路复用,并标记输出T0。如果T0被无条件地作为test_reg的输入,我认为这将具有所需的功能。相反,T0被完全忽略,并且在if-else块中使用T1来选择寄存器是否应该更新。
最终,这个例子看起来仍然正确,但现在我有点害怕在更复杂的浮点单元中使用,如果它在简单的情况下表现得有点出乎意料的话。
有没有更优雅的方法来停止浮点加法模块的管道?我最初喜欢上面的方法,因为我可以在末尾添加一个when(!en)块,它只将所有状态的输出写入其输入。我认为另一种方法是用Reg()替换Reg(next=xxx)的任何实例,然后用when(en){Reg:=next}块更新寄存器。最终,我正在努力学习Chisel,所以我想知道最干净的方法是什么。
作为参考,我所说的浮点加法模块是:https://github.com/zhemao/chisel-float/blob/master/src/main/scala/FPAdd.scala
val test_reg = Reg(next = io.in)
io.out := test_reg
when (!io.en) {
test_reg := test_reg
}
我认为这是一种糟糕的编码实践——要么使用Reg(next=...)
,要么通过test_reg := ...
指定下一个值,但不要两者混合!首先,读者不清楚哪位作家应该优先(尽管答案是"最后一位作家获胜")。其次,当读者看到Reg(next=...)
时,他可能不希望看到代码中的其他地方覆盖了那个编写器。
写为:
val test_reg = Reg(io.in.clone())
when (io.en) {
test_reg := io.in
}
它仍然会生成一些未使用的信号,但代码的意图要清晰得多。
always @(posedge clk) begin
if(io_en) begin
test_reg <= io_in;
end
end
我从未使用过凿子,但我的猜测是:
when (io.en) {
test_reg := io.in
}
会产生这样的东西:
always @(posedge clk) begin
if(io_en) begin
test_reg <= io_in;
end
end
我认为这相当于你现在所拥有的,但可读性更强。