RegInit 仅在复位时初始化值
RegInit initializes value only on reset
我正在实现一个脉宽调制模块来学习chisel3。
模块代码为:
import chisel3._
import chisel3.util._
import chisel3.tester._
class Pwm(bitWidth: Int) extends Module {
val io = IO(new Bundle {
val duty = Input(UInt(bitWidth.W))
val period = Input(UInt(bitWidth.W))
val output = Output(Bool())
})
val context = RegInit(0.U(bitWidth.W))
val output = RegInit(false.B)
val sum = Wire(UInt(bitWidth.W + 1))
sum := context +& io.duty
when (sum >= io.period) {
context := sum - io.period
output := true.B
} otherwise {
context := sum
output := false.B
}
io.output := output
}
当我发出 verilog 时,我期望寄存器被初始化为它们的 RegInit
值:
val emit_args = Array("--emission-options=disableMemRandomization,disableRegisterRandomization");
chisel3.emitVerilog(new Pwm(8), emit_args)
但我得到了以下verilog代码:
module Pwm(
input clock,
input reset,
input [7:0] io_duty,
input [7:0] io_period,
output io_output
);
reg [7:0] context_; // @[Pwm.scala 12:26]
reg output_; // @[Pwm.scala 13:25]
wire [8:0] sum = context_ + io_duty; // @[Pwm.scala 15:20]
wire [8:0] _GEN_2 = {{1'd0}, io_period}; // @[Pwm.scala 17:15]
wire _T = sum >= _GEN_2; // @[Pwm.scala 17:15]
wire [8:0] _context_T_1 = sum - _GEN_2; // @[Pwm.scala 18:24]
wire [8:0] _GEN_0 = sum >= _GEN_2 ? _context_T_1 : sum; // @[Pwm.scala 17:29 18:17 21:17]
wire [8:0] _GEN_4 = reset ? 9'h0 : _GEN_0; // @[Pwm.scala 12:{26,26}]
assign io_output = output_; // @[Pwm.scala 25:15]
always @(posedge clock) begin
context_ <= _GEN_4[7:0]; // @[Pwm.scala 12:{26,26}]
if (reset) begin // @[Pwm.scala 13:25]
output_ <= 1'h0; // @[Pwm.scala 13:25]
end else begin
output_ <= _T;
end
end
endmodule
请注意,在代码中 context_
在重置为高电平时设置为 0,但不会以这种方式进行初始化。
是否有允许使用 RegInit
值初始化寄存器的发射参数?
在 Chisel 3 中,RegInit
指的是具有复位功能的寄存器。实验性支持将异步复位线视为“初始”线,但我想提醒的是,我不建议在典型的数字设计中使用它。
您可能已经知道,实际硬件并不普遍支持初始值。一些(但不是全部)FPGA 支持它们,而 ASIC 则完全不支持它们。因此,编写依赖于初始值的代码本质上是不可移植的,这与 Chisel 构建 可重用 硬件生成器的精神背道而驰。
也就是说,他们可以让某些设计更有效地使用某些 FPGA 上的资源,所以我们确实有办法做到这一点:
// RequireAsyncReset makes the implicit reset Async because the default is Sync (only for top-level module)
// Only AsyncReset can be emitted as an initial value
class Pwm(bitWidth: Int) extends Module with RequireAsyncReset {
val io = IO(new Bundle {
val duty = Input(UInt(bitWidth.W))
val period = Input(UInt(bitWidth.W))
val output = Output(Bool())
})
val context = RegInit(0.U(bitWidth.W))
val output = RegInit(false.B)
val sum = Wire(UInt(bitWidth.W + 1))
sum := context +& io.duty
when (sum >= io.period) {
context := sum - io.period
output := true.B
} otherwise {
context := sum
output := false.B
}
io.output := output
// Experimental API
annotate(new ChiselAnnotation {
def toFirrtl = firrtl.annotations.PresetAnnotation(reset.toTarget)
})
}
我已将您的设计调整为使用异步重置并使用实验性支持发出初始值。 (斯卡斯蒂:https://scastie.scala-lang.org/rQtHVUCZROul4i1uEjClPw)
这是使用 Chisel v3.5.0。最近修复了一个重要的错误(修复将在 v3.5.1 中发布),并且正在积极讨论如何在 Chisel 中直接公开此实验 API 而无需使用 FIRRTL 注释:https://github.com/chipsalliance/chisel3/pull/2330.
我正在实现一个脉宽调制模块来学习chisel3。
模块代码为:
import chisel3._
import chisel3.util._
import chisel3.tester._
class Pwm(bitWidth: Int) extends Module {
val io = IO(new Bundle {
val duty = Input(UInt(bitWidth.W))
val period = Input(UInt(bitWidth.W))
val output = Output(Bool())
})
val context = RegInit(0.U(bitWidth.W))
val output = RegInit(false.B)
val sum = Wire(UInt(bitWidth.W + 1))
sum := context +& io.duty
when (sum >= io.period) {
context := sum - io.period
output := true.B
} otherwise {
context := sum
output := false.B
}
io.output := output
}
当我发出 verilog 时,我期望寄存器被初始化为它们的 RegInit
值:
val emit_args = Array("--emission-options=disableMemRandomization,disableRegisterRandomization");
chisel3.emitVerilog(new Pwm(8), emit_args)
但我得到了以下verilog代码:
module Pwm(
input clock,
input reset,
input [7:0] io_duty,
input [7:0] io_period,
output io_output
);
reg [7:0] context_; // @[Pwm.scala 12:26]
reg output_; // @[Pwm.scala 13:25]
wire [8:0] sum = context_ + io_duty; // @[Pwm.scala 15:20]
wire [8:0] _GEN_2 = {{1'd0}, io_period}; // @[Pwm.scala 17:15]
wire _T = sum >= _GEN_2; // @[Pwm.scala 17:15]
wire [8:0] _context_T_1 = sum - _GEN_2; // @[Pwm.scala 18:24]
wire [8:0] _GEN_0 = sum >= _GEN_2 ? _context_T_1 : sum; // @[Pwm.scala 17:29 18:17 21:17]
wire [8:0] _GEN_4 = reset ? 9'h0 : _GEN_0; // @[Pwm.scala 12:{26,26}]
assign io_output = output_; // @[Pwm.scala 25:15]
always @(posedge clock) begin
context_ <= _GEN_4[7:0]; // @[Pwm.scala 12:{26,26}]
if (reset) begin // @[Pwm.scala 13:25]
output_ <= 1'h0; // @[Pwm.scala 13:25]
end else begin
output_ <= _T;
end
end
endmodule
请注意,在代码中 context_
在重置为高电平时设置为 0,但不会以这种方式进行初始化。
是否有允许使用 RegInit
值初始化寄存器的发射参数?
在 Chisel 3 中,RegInit
指的是具有复位功能的寄存器。实验性支持将异步复位线视为“初始”线,但我想提醒的是,我不建议在典型的数字设计中使用它。
您可能已经知道,实际硬件并不普遍支持初始值。一些(但不是全部)FPGA 支持它们,而 ASIC 则完全不支持它们。因此,编写依赖于初始值的代码本质上是不可移植的,这与 Chisel 构建 可重用 硬件生成器的精神背道而驰。
也就是说,他们可以让某些设计更有效地使用某些 FPGA 上的资源,所以我们确实有办法做到这一点:
// RequireAsyncReset makes the implicit reset Async because the default is Sync (only for top-level module)
// Only AsyncReset can be emitted as an initial value
class Pwm(bitWidth: Int) extends Module with RequireAsyncReset {
val io = IO(new Bundle {
val duty = Input(UInt(bitWidth.W))
val period = Input(UInt(bitWidth.W))
val output = Output(Bool())
})
val context = RegInit(0.U(bitWidth.W))
val output = RegInit(false.B)
val sum = Wire(UInt(bitWidth.W + 1))
sum := context +& io.duty
when (sum >= io.period) {
context := sum - io.period
output := true.B
} otherwise {
context := sum
output := false.B
}
io.output := output
// Experimental API
annotate(new ChiselAnnotation {
def toFirrtl = firrtl.annotations.PresetAnnotation(reset.toTarget)
})
}
我已将您的设计调整为使用异步重置并使用实验性支持发出初始值。 (斯卡斯蒂:https://scastie.scala-lang.org/rQtHVUCZROul4i1uEjClPw)
这是使用 Chisel v3.5.0。最近修复了一个重要的错误(修复将在 v3.5.1 中发布),并且正在积极讨论如何在 Chisel 中直接公开此实验 API 而无需使用 FIRRTL 注释:https://github.com/chipsalliance/chisel3/pull/2330.