From 52dcf10d59b88b026adab0f5d9f127bfac18b36a Mon Sep 17 00:00:00 2001 From: Adam Izraelevitz Date: Fri, 21 Aug 2020 14:40:05 -0700 Subject: Move multi-clock to explanations (#1561) --- docs/src/explanations/multi-clock.md | 98 ++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/src/explanations/multi-clock.md (limited to 'docs/src/explanations/multi-clock.md') diff --git a/docs/src/explanations/multi-clock.md b/docs/src/explanations/multi-clock.md new file mode 100644 index 00000000..6e9afd5a --- /dev/null +++ b/docs/src/explanations/multi-clock.md @@ -0,0 +1,98 @@ +--- +layout: docs +title: "Multiple Clock Domains" +section: "chisel3" +--- +Chisel 3 supports multiple clock domains as follows. + +Note that in order to cross clock domains safely, you will need appropriate synchronization logic (such as an asynchronous FIFO). You can use the [AsyncQueue library](https://github.com/ucb-bar/asyncqueue) to do this easily. + +```scala mdoc:silent:reset +import chisel3._ + +class MultiClockModule extends Module { + val io = IO(new Bundle { + val clockB = Input(Clock()) + val resetB = Input(Bool()) + val stuff = Input(Bool()) + }) + + // This register is clocked against the module clock. + val regClock = RegNext(io.stuff) + + withClockAndReset (io.clockB, io.resetB) { + // In this withClock scope, all synchronous elements are clocked against io.clockB. + // Reset for flops in this domain is using the explicitly provided reset io.resetB. + + // This register is clocked against io.clockB. + val regClockB = RegNext(io.stuff) + } + + // This register is also clocked against the module clock. + val regClock2 = RegNext(io.stuff) +} +``` + +You can also instantiate modules in another clock domain: + +```scala mdoc:silent:reset +import chisel3._ + +class ChildModule extends Module { + val io = IO(new Bundle{ + val in = Input(Bool()) + }) +} +class MultiClockModule extends Module { + val io = IO(new Bundle { + val clockB = Input(Clock()) + val resetB = Input(Bool()) + val stuff = Input(Bool()) + }) + val clockB_child = withClockAndReset(io.clockB, io.resetB) { Module(new ChildModule) } + clockB_child.io.in := io.stuff +} +``` + +If you only want to connect your clock to a new clock domain and use the regular implicit reset signal, you can use `withClock(clock)` instead of `withClockAndReset`. + +```scala mdoc:silent:reset +import chisel3._ + +class MultiClockModule extends Module { + val io = IO(new Bundle { + val clockB = Input(Clock()) + val stuff = Input(Bool()) + }) + + // This register is clocked against the module clock. + val regClock = RegNext(io.stuff) + + withClock (io.clockB) { + // In this withClock scope, all synchronous elements are clocked against io.clockB. + + // This register is clocked against io.clockB, but uses implict reset from the parent context. + val regClockB = RegNext(io.stuff) + } + + // This register is also clocked against the module clock. + val regClock2 = RegNext(io.stuff) +} + +// Instantiate module in another clock domain with implicit reset. +class MultiClockModule2 extends Module { + val io = IO(new Bundle { + val clockB = Input(Clock()) + val stuff = Input(Bool()) + }) + val clockB_child = withClock(io.clockB) { Module(new ChildModule) } + clockB_child.io.in := io.stuff +} + +class ChildModule extends Module { + val io = IO(new Bundle{ + val in = Input(Bool()) + }) +} + +``` -- cgit v1.2.3