我正在實作一個脈沖寬度調制模塊來學習 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值初始化暫存器?
uj5u.com熱心網友回復:
在 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/芯片聯盟/chisel3/pull/2330。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/422309.html
標籤:
