From fda4c2bd7696d79444b094cae2af6c9267f43534 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Thu, 8 Sep 2016 20:01:03 -0700 Subject: [PATCH] Add a way to create Async Reset Registers and a way to easily access them with TL2 --- .../scala/uncore/tilelink2/RegField.scala | 11 +++ src/main/scala/uncore/util/BlackBoxRegs.scala | 84 +++++++++++++++++++ vsim/Makefrag | 3 +- vsrc/AsyncResetReg.v | 51 +++++++++++ 4 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/main/scala/uncore/util/BlackBoxRegs.scala create mode 100644 vsrc/AsyncResetReg.v diff --git a/src/main/scala/uncore/tilelink2/RegField.scala b/src/main/scala/uncore/tilelink2/RegField.scala index 32a65c0d..d4b34743 100644 --- a/src/main/scala/uncore/tilelink2/RegField.scala +++ b/src/main/scala/uncore/tilelink2/RegField.scala @@ -4,6 +4,8 @@ package uncore.tilelink2 import Chisel._ +import uncore.util.{SimpleRegIO} + case class RegReadFn private(combinational: Boolean, fn: (Bool, Bool) => (Bool, Bool, UInt)) object RegReadFn { @@ -81,6 +83,15 @@ object RegField // Setting takes priority over clearing. def w1ToClear(n: Int, reg: UInt, set: UInt): RegField = RegField(n, reg, RegWriteFn((valid, data) => { reg := ~(~reg | Mux(valid, data, UInt(0))) | set; Bool(true) })) + + // This RegField wraps an explicit register + // (e.g. Black-Boxed Register) to create a R/W register. + def rwReg(n: Int, bb: SimpleRegIO) : RegField = + RegField(n, bb.q, RegWriteFn((valid, data) => { + bb.en := valid + bb.d := data + Bool(true) + })) } trait HasRegMap diff --git a/src/main/scala/uncore/util/BlackBoxRegs.scala b/src/main/scala/uncore/util/BlackBoxRegs.scala new file mode 100644 index 00000000..21fe09f0 --- /dev/null +++ b/src/main/scala/uncore/util/BlackBoxRegs.scala @@ -0,0 +1,84 @@ +package uncore.util + +import Chisel._ + +import cde.{Parameters} +import junctions.{ParameterizedBundle} + +/** This black-boxes an Async Reset + * Reg. + * + * Because Chisel doesn't support + * parameterized black boxes, + * we unfortunately have to + * instantiate a number of these. + * + * 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 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 { + + val io = new Bundle { + val d = Bool(INPUT) + val q = Bool(OUTPUT) + + val clk = Clock(INPUT) + val rst = Bool(INPUT) + + val init = Bool(INPUT) + } + +} + + +class SimpleRegIO(val w: Int)(implicit val p: Parameters) extends ParameterizedBundle()(p){ + + val d = UInt(INPUT, width = w) + val q = UInt(OUTPUT, width = w) + + val en = Bool(INPUT) + +} + +class AsyncResetRegVec(val w: Int, val init: Int)(implicit val p: Parameters) extends Module { + + val io = new SimpleRegIO(w)(p) + + val bb_q = Wire(UInt(width = w)) + val bb_d = Wire(UInt(width = w)) + + val init_val = Wire(UInt(width = w)) + init_val := UInt(init, width = w) + + val async_regs = List.fill(w)(Module (new AsyncResetReg)) + + bb_q := (async_regs.map(_.io.q)).asUInt() + bb_d := Mux(io.en , io.d , bb_q) + + io.q := bb_q + + + for ((reg, idx) <- async_regs.zipWithIndex) { + reg.io.clk := clock + reg.io.rst := reset + reg.io.init := init_val(idx) + reg.io.d := bb_d(idx) + } + +} diff --git a/vsim/Makefrag b/vsim/Makefrag index a2f5559d..3abb2b4e 100644 --- a/vsim/Makefrag +++ b/vsim/Makefrag @@ -6,7 +6,8 @@ bb_vsrcs = $(base_dir)/vsrc/DebugTransportModuleJtag.v \ $(base_dir)/vsrc/jtag_vpi.v \ - $(base_dir)/vsrc/AsyncMailbox.v + $(base_dir)/vsrc/AsyncMailbox.v \ + $(base_dir)/vsrc/AsyncResetReg.v sim_vsrcs = \ $(generated_dir)/$(MODEL).$(CONFIG).v \ diff --git a/vsrc/AsyncResetReg.v b/vsrc/AsyncResetReg.v new file mode 100644 index 00000000..3adf16b1 --- /dev/null +++ b/vsrc/AsyncResetReg.v @@ -0,0 +1,51 @@ + + +/** This black-boxes an Async Reset + * Reg. + * + * Because Chisel doesn't support + * parameterized black boxes, + * we unfortunately have to + * instantiate a number of these. + * + * 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 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 clk, + input rst, + + input init); + + always @(posedge clk or posedge rst) begin + + if (rst) begin + q <= init; + end else begin + q <= d; + end + + end + + +endmodule // AsyncResetReg +