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 +