From 1308680f7561f51094360fc27db89f773808cdb1 Mon Sep 17 00:00:00 2001 From: Megan Wachs Date: Wed, 14 Sep 2016 16:30:59 -0700 Subject: [PATCH] Add some async/clock utilities --- src/main/scala/junctions/crossing.scala | 41 ++++++++++++++ .../uncore/tilelink2/RegisterCrossing.scala | 54 +++++++++++++++++++ vsim/Makefrag | 3 ++ vsrc/ClockToSignal.v | 19 +++++++ vsrc/SignalToClock.v | 18 +++++++ 5 files changed, 135 insertions(+) create mode 100644 vsrc/ClockToSignal.v create mode 100644 vsrc/SignalToClock.v diff --git a/src/main/scala/junctions/crossing.scala b/src/main/scala/junctions/crossing.scala index 948c3a21..e803d950 100644 --- a/src/main/scala/junctions/crossing.scala +++ b/src/main/scala/junctions/crossing.scala @@ -50,3 +50,44 @@ object AsyncDecoupledFrom AsyncDecoupledCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync) } } + + +/** Because Chisel/FIRRTL does not allow us + * to directly assign clocks from Signals, + * we need this black box module. + * This may even be useful because some back-end + * flows like to have this sort of transition + * flagged with a special cell or module anyway. + */ + +class SignalToClock extends BlackBox { + val io = new Bundle { + val signal_in = Bool(INPUT) + val clock_out = Clock(OUTPUT) + } + + // io.clock_out := io.signal_in +} + +object SignalToClock { + def apply(signal: Bool): Clock = { + val s2c = Module(new SignalToClock) + s2c.io.signal_in := signal + s2c.io.clock_out + } +} + +class ClockToSignal extends BlackBox { + val io = new Bundle { + val clock_in = Clock(INPUT) + val signal_out = Bool(OUTPUT) + } +} + +object ClockToSignal { + def apply(clk: Clock): Bool = { + val c2s = Module(new ClockToSignal) + c2s.io.clock_in := clk + c2s.io.signal_out + } +} diff --git a/src/main/scala/uncore/tilelink2/RegisterCrossing.scala b/src/main/scala/uncore/tilelink2/RegisterCrossing.scala index cb66aca5..1a6ecd3f 100644 --- a/src/main/scala/uncore/tilelink2/RegisterCrossing.scala +++ b/src/main/scala/uncore/tilelink2/RegisterCrossing.scala @@ -4,6 +4,7 @@ package uncore.tilelink2 import Chisel._ import junctions._ +import uncore.util.{AsyncResetRegVec} // A very simple flow control state machine, run in the specified clock domain class BusyRegisterCrossing(clock: Clock, reset: Bool) @@ -130,3 +131,56 @@ class RegisterReadCrossing[T <: Data](gen: T, sync: Int = 3) extends Module { crossing.io.deq.ready := io.master_port.request.valid && !reg.io.busy crossing.io.enq.valid := Bool(true) } + +/** Wrapper to create an + * asynchronously reset + * slave register which + * can be both read + * and written using + * crossing FIFOs. + */ + +object AsyncRWSlaveRegField { + + def apply(slave_clock: Clock, + slave_reset: Bool, + width: Int, + init: Int, + master_allow: Bool = Bool(true), + slave_allow: Bool = Bool(true) + ): (UInt, RegField) = { + + val async_slave_reg = Module(new AsyncResetRegVec(width, init)) + async_slave_reg.reset := slave_reset + async_slave_reg.clock := slave_clock + + val wr_crossing = Module (new RegisterWriteCrossing(UInt(width = width))) + + val scope = Module (new AsyncScope()) + + wr_crossing.io.master_clock := scope.clock + wr_crossing.io.master_reset := scope.reset + wr_crossing.io.master_allow := master_allow + wr_crossing.io.slave_clock := slave_clock + wr_crossing.io.slave_reset := slave_reset + wr_crossing.io.slave_allow := slave_allow + + async_slave_reg.io.en := wr_crossing.io.slave_valid + async_slave_reg.io.d := wr_crossing.io.slave_register + + val rd_crossing = Module (new RegisterReadCrossing(UInt(width = width ))) + + rd_crossing.io.master_clock := scope.clock + rd_crossing.io.master_reset := scope.reset + rd_crossing.io.master_allow := master_allow + rd_crossing.io.slave_clock := slave_clock + rd_crossing.io.slave_reset := slave_reset + rd_crossing.io.slave_allow := slave_allow + + rd_crossing.io.slave_register := async_slave_reg.io.q + + (async_slave_reg.io.q, RegField(width, rd_crossing.io.master_port, wr_crossing.io.master_port)) + + } + +} diff --git a/vsim/Makefrag b/vsim/Makefrag index a0e1c3de..31ee449b 100644 --- a/vsim/Makefrag +++ b/vsim/Makefrag @@ -9,6 +9,9 @@ bb_vsrcs = $(base_dir)/vsrc/DebugTransportModuleJtag.v \ $(base_dir)/vsrc/AsyncMailbox.v \ $(base_dir)/vsrc/AsyncResetReg.v \ $(base_dir)/vsrc/ClockDivider.v \ + $(base_dir)/vsrc/ClockToSignal.v \ + $(base_dir)/vsrc/SignalToClock.v \ + sim_vsrcs = \ $(generated_dir)/$(MODEL).$(CONFIG).v \ diff --git a/vsrc/ClockToSignal.v b/vsrc/ClockToSignal.v new file mode 100644 index 00000000..db8b8b37 --- /dev/null +++ b/vsrc/ClockToSignal.v @@ -0,0 +1,19 @@ + +/* This blackbox is needed by + * Chisel in order to do type conversion. + * It may be useful for some synthesis flows + * as well which require special + * flagging on conversion from data to clock. + */ + + +module ClockToSignal( + output signal_out, + input clock_in + ); + + + assign signal_out = clock_in; + +endmodule // ClockToSignal + diff --git a/vsrc/SignalToClock.v b/vsrc/SignalToClock.v new file mode 100644 index 00000000..553bc580 --- /dev/null +++ b/vsrc/SignalToClock.v @@ -0,0 +1,18 @@ + +/* This blackbox is needed by + * Chisel in order to do type conversion. + * It may be useful for some synthesis flows + * as well which require special + * flagging on conversion from data to clock. + */ + + +module SignalToClock ( + output clock_out, + input signal_in + ); + + + assign clock_out = signal_in; + +endmodule // SignalToClock