1
0

Merge pull request #265 from ucb-bar/black_box_regs

Make it possible to have Async Reset Flops
This commit is contained in:
mwachs5 2016-09-09 13:54:04 -07:00 committed by GitHub
commit 8273ca1ae7
6 changed files with 185 additions and 38 deletions

View File

@ -0,0 +1,37 @@
// See LICENSE for license details.
package uncore.tilelink2
import Chisel._
case class ExampleParams(num: Int, address: BigInt)
trait ExampleBundle
{
val params: ExampleParams
val gpio = UInt(width = params.num)
}
trait ExampleModule extends HasRegMap
{
val params: ExampleParams
val io: ExampleBundle
val interrupts: Vec[Bool]
val state = RegInit(UInt(0))
val pending = RegInit(UInt(0xf, width = 4))
io.gpio := state
interrupts := pending.toBools
regmap(
0 -> Seq(
RegField(params.num, state)),
1 -> Seq(
RegField.w1ToClear(4, pending, state)))
}
// Create a concrete TL2 version of the abstract Example slave
class TLExample(p: ExampleParams) extends TLRegisterRouter(p.address, 4)(
new TLRegBundle(p, _) with ExampleBundle)(
new TLRegModule(p, _, _) with ExampleModule)

View File

@ -1,37 +0,0 @@
// See LICENSE for license details.
package uncore.tilelink2
import Chisel._
case class GPIOParams(num: Int, address: BigInt)
trait GPIOBundle
{
val params: GPIOParams
val gpio = UInt(width = params.num)
}
trait GPIOModule extends HasRegMap
{
val params: GPIOParams
val io: GPIOBundle
val interrupts: Vec[Bool]
val state = RegInit(UInt(0))
val pending = RegInit(UInt(0xf, width = 4))
io.gpio := state
interrupts := pending.toBools
regmap(
0 -> Seq(
RegField(params.num, state)),
1 -> Seq(
RegField.w1ToClear(4, pending, state)))
}
// Create a concrete TL2 version of the abstract GPIO slave
class TLGPIO(p: GPIOParams) extends TLRegisterRouter(p.address, 4)(
new TLRegBundle(p, _) with GPIOBundle)(
new TLRegModule(p, _, _) with GPIOModule)

View File

@ -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

View 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)
}
}

View File

@ -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 \

51
vsrc/AsyncResetReg.v Normal file
View 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