From a031686763982de66a11cf61884a116262419cee Mon Sep 17 00:00:00 2001 From: mwachs5 Date: Fri, 16 Sep 2016 13:50:09 -0700 Subject: [PATCH] util: Do BlackBox Async Set/Reset Registers more properly (#305) * util: Do Set/Reset Async Registers more properly The way BlackBox "init" registers were coded before was not really kosher verilog for most synthesis tools. Also, the enable logic wasn't really pushed down into the flop. This change is more explicit about set/reset flops, again this is only a 'temporary' problem that would go away with parameterizable blackboxes (or general async reset support). * Tabs, not spaces, in Makefiles * util: Fix typos in Async BB Reg Comments --- src/main/scala/uncore/util/BlackBoxRegs.scala | 49 +++++++++++-------- vsim/Makefrag | 7 +-- vsrc/AsyncResetReg.v | 21 +++----- vsrc/AsyncSetReg.v | 47 ++++++++++++++++++ 4 files changed, 88 insertions(+), 36 deletions(-) create mode 100644 vsrc/AsyncSetReg.v diff --git a/src/main/scala/uncore/util/BlackBoxRegs.scala b/src/main/scala/uncore/util/BlackBoxRegs.scala index 51af290f..439adab0 100644 --- a/src/main/scala/uncore/util/BlackBoxRegs.scala +++ b/src/main/scala/uncore/util/BlackBoxRegs.scala @@ -5,13 +5,17 @@ import Chisel._ import cde.{Parameters} /** This black-boxes an Async Reset - * Reg. + * (or Set) + * Register. * * Because Chisel doesn't support * parameterized black boxes, * we unfortunately have to * instantiate a number of these. * + * We also have to hard-code the set/ + * reset behavior. + * * Do not confuse an asynchronous * reset signal with an asynchronously * reset reg. You should still @@ -22,29 +26,26 @@ import cde.{Parameters} * @param q Data Output * @param clk Clock Input * @param rst Reset Input + * @param en Write Enable Input * - * @param init Value to write at Reset. - * This is a constant, - * but this construction - * will likely make backend flows - * and lint tools unhappy. - * */ -class AsyncResetReg extends BlackBox { +abstract class AbstractBBReg extends BlackBox { val io = new Bundle { val d = Bool(INPUT) val q = Bool(OUTPUT) + val en = Bool(INPUT) val clk = Clock(INPUT) val rst = Bool(INPUT) - - val init = Bool(INPUT) } } +class AsyncResetReg extends AbstractBBReg +class AsyncSetReg extends AbstractBBReg + class SimpleRegIO(val w: Int) extends Bundle{ val d = UInt(INPUT, width = w) @@ -60,30 +61,38 @@ class AsyncResetRegVec(val w: Int, val init: BigInt) extends Module { val bb_d = Mux(io.en, io.d, io.q) - val async_regs = List.fill(w)(Module (new AsyncResetReg)) + val async_regs: List[AbstractBBReg] = List.tabulate(w)( + i => Module ( + if (((init >> i) % 2) > 0) + new AsyncSetReg + else + new AsyncResetReg) + ) io.q := async_regs.map(_.io.q).asUInt for ((reg, idx) <- async_regs.zipWithIndex) { reg.io.clk := clock reg.io.rst := reset - reg.io.init := Bool(((init >> idx) & 1) == 1) - reg.io.d := bb_d(idx) + reg.io.d := bb_d(idx) + reg.io.en := io.en } } object AsyncResetReg { - def apply(d: Bool, clk: Clock, rst: Bool, init: Bool): Bool = { - val reg = Module(new AsyncResetReg) + def apply(d: Bool, clk: Clock, rst: Bool, init: Boolean): Bool = { + val reg: AbstractBBReg = + if (init) Module (new AsyncSetReg) + else Module(new AsyncResetReg) reg.io.d := d reg.io.clk := clk reg.io.rst := rst - reg.io.init := init + reg.io.en := Bool(true) reg.io.q } - def apply(d: Bool, clk: Clock, rst: Bool): Bool = apply(d, clk, rst, Bool(false)) + def apply(d: Bool, clk: Clock, rst: Bool): Bool = apply(d, clk, rst, false) def apply(updateData: UInt, resetData: BigInt, enable: Bool): UInt = { val w = updateData.getWidth max resetData.bitLength @@ -93,9 +102,9 @@ object AsyncResetReg { reg.io.q } - def apply(updateData: UInt, resetData: BigInt): UInt = apply(updateData, resetData, Bool(true)) + def apply(updateData: UInt, resetData: BigInt): UInt = apply(updateData, resetData, enable=Bool(true)) - def apply(updateData: UInt, enable: Bool): UInt = apply(updateData, BigInt(0), enable) + def apply(updateData: UInt, enable: Bool): UInt = apply(updateData, resetData=BigInt(0), enable) - def apply(updateData: UInt): UInt = apply(updateData, BigInt(0), Bool(true)) + def apply(updateData: UInt): UInt = apply(updateData, resetData=BigInt(0), enable=Bool(true)) } diff --git a/vsim/Makefrag b/vsim/Makefrag index ba537d85..ed8e3bbf 100644 --- a/vsim/Makefrag +++ b/vsim/Makefrag @@ -8,10 +8,11 @@ bb_vsrcs = $(base_dir)/vsrc/DebugTransportModuleJtag.v \ $(base_dir)/vsrc/jtag_vpi.v \ $(base_dir)/vsrc/AsyncMailbox.v \ $(base_dir)/vsrc/AsyncResetReg.v \ + $(base_dir)/vsrc/AsyncSetReg.v \ $(base_dir)/vsrc/ClockDivider.v \ - $(base_dir)/vsrc/ClockToSignal.v \ - $(base_dir)/vsrc/SignalToClock.v \ - + $(base_dir)/vsrc/ClockToSignal.v \ + $(base_dir)/vsrc/SignalToClock.v \ + sim_vsrcs = \ $(generated_dir)/$(MODEL).$(CONFIG).v \ diff --git a/vsrc/AsyncResetReg.v b/vsrc/AsyncResetReg.v index 3adf16b1..4775f6c6 100644 --- a/vsrc/AsyncResetReg.v +++ b/vsrc/AsyncResetReg.v @@ -8,6 +8,8 @@ * we unfortunately have to * instantiate a number of these. * + * We also have to hard-code the set/reset. + * * Do not confuse an asynchronous * reset signal with an asynchronously * reset reg. You should still @@ -18,32 +20,25 @@ * @param q Data Output * @param clk Clock Input * @param rst Reset Input + * @param en Write Enable Input * - * @param init Value to write at Reset. - * This is a constant, - * but this construction - * will likely make backend flows - * and lint tools unhappy. - * */ module AsyncResetReg ( input d, output reg q, + input en, input clk, - input rst, - - input init); - + input rst); + always @(posedge clk or posedge rst) begin if (rst) begin - q <= init; - end else begin + q <= 1'b0; + end else if (en) begin q <= d; end - end diff --git a/vsrc/AsyncSetReg.v b/vsrc/AsyncSetReg.v new file mode 100644 index 00000000..ffafdab3 --- /dev/null +++ b/vsrc/AsyncSetReg.v @@ -0,0 +1,47 @@ + + +/** This black-boxes an Async Set + * Reg. + * + * Because Chisel doesn't support + * parameterized black boxes, + * we unfortunately have to + * instantiate a number of these. + * + * We also have to hard-code the set/reset. + * + * Do not confuse an asynchronous + * reset signal with an asynchronously + * reset reg. You should still + * properly synchronize your reset + * deassertion. + * + * @param d Data input + * @param q Data Output + * @param clk Clock Input + * @param rst Reset Input + * @param en Write Enable Input + * + */ + +module AsyncSetReg ( + input d, + output reg q, + input en, + + input clk, + input rst); + + always @(posedge clk or posedge rst) begin + + if (rst) begin + q <= 1'b1; + end else if (en) begin + q <= d; + end + + end + + +endmodule // AsyncSetReg +