Add a way to create Async Reset Registers and a way to easily access them with TL2
This commit is contained in:
parent
c1eb1f12a2
commit
fda4c2bd76
@ -4,6 +4,8 @@ package uncore.tilelink2
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
|
||||||
|
import uncore.util.{SimpleRegIO}
|
||||||
|
|
||||||
case class RegReadFn private(combinational: Boolean, fn: (Bool, Bool) => (Bool, Bool, UInt))
|
case class RegReadFn private(combinational: Boolean, fn: (Bool, Bool) => (Bool, Bool, UInt))
|
||||||
object RegReadFn
|
object RegReadFn
|
||||||
{
|
{
|
||||||
@ -81,6 +83,15 @@ object RegField
|
|||||||
// Setting takes priority over clearing.
|
// Setting takes priority over clearing.
|
||||||
def w1ToClear(n: Int, reg: UInt, set: UInt): RegField =
|
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) }))
|
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
|
trait HasRegMap
|
||||||
|
84
src/main/scala/uncore/util/BlackBoxRegs.scala
Normal file
84
src/main/scala/uncore/util/BlackBoxRegs.scala
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -6,7 +6,8 @@
|
|||||||
|
|
||||||
bb_vsrcs = $(base_dir)/vsrc/DebugTransportModuleJtag.v \
|
bb_vsrcs = $(base_dir)/vsrc/DebugTransportModuleJtag.v \
|
||||||
$(base_dir)/vsrc/jtag_vpi.v \
|
$(base_dir)/vsrc/jtag_vpi.v \
|
||||||
$(base_dir)/vsrc/AsyncMailbox.v
|
$(base_dir)/vsrc/AsyncMailbox.v \
|
||||||
|
$(base_dir)/vsrc/AsyncResetReg.v
|
||||||
|
|
||||||
sim_vsrcs = \
|
sim_vsrcs = \
|
||||||
$(generated_dir)/$(MODEL).$(CONFIG).v \
|
$(generated_dir)/$(MODEL).$(CONFIG).v \
|
||||||
|
51
vsrc/AsyncResetReg.v
Normal file
51
vsrc/AsyncResetReg.v
Normal file
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user