// See LICENSE for license details. package sifive.blocks.devices.terminal import Chisel._ import chisel3.core.{Input, Output} import chisel3.experimental.{Analog, MultiIOModule} import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp} import freechips.rocketchip.regmapper._ import freechips.rocketchip.subsystem.{BaseSubsystem} import freechips.rocketchip.tilelink._ import freechips.rocketchip.util.AsyncQueue import sifive.blocks.util.NonBlockingEnqueue case class TerminalParams ( address: BigInt ) class TerminalSysIO extends Bundle { val clk = Input(Clock()) val reset = Input(Bool()) } class TerminalDVIIO extends Bundle { val d = Output(Bits(12.W)) val clk_p = Output(Bits(1.W)) val clk_n = Output(Bits(1.W)) val hsync = Output(Bool()) val vsync = Output(Bool()) val de = Output(Bool()) val reset = Output(Bool()) val i2c_scl = Analog(1.W) val i2c_sda = Analog(1.W) } class Terminal extends BlackBox { val io = IO(new Bundle { val sys = new TerminalSysIO val dvi = new TerminalDVIIO val write_enable = Input(Bool()) val write_data = Input(UInt(8.W)) }) override def desiredName: String = "terminal" } trait TerminalRegBundle extends Bundle { val port_sys = new TerminalSysIO val port_dvi = new TerminalDVIIO } trait TerminalRegModule extends MultiIOModule with HasRegMap { val params: TerminalParams val io: TerminalRegBundle val term = Module(new Terminal) io.port_sys <> term.io.sys io.port_dvi <> term.io.dvi val crossing = Module(new AsyncQueue(UInt(8.W), depth=1, safe=false)) crossing.io.enq_clock := clock crossing.io.enq_reset := Bool(false) crossing.io.deq_clock := io.port_sys.clk crossing.io.deq_reset := Bool(false) // wire up dequeue to terminal io term.io.write_enable := crossing.io.deq.valid term.io.write_data := crossing.io.deq.bits crossing.io.deq.ready := Bool(true) // terminal can read at every cycle regmap( 0 -> NonBlockingEnqueue(crossing.io.enq) ) } class TLTerminal(w: Int, params: TerminalParams)(implicit p: Parameters) extends TLRegisterRouter ( params.address, "terminal", Seq("klemens,terminal0"), beatBytes = w )( new TLRegBundle(params, _) with TerminalRegBundle )( new TLRegModule(params, _, _) with TerminalRegModule ) //-- TerminalPeriphery case object PeripheryTerminalKey extends Field[TerminalParams] trait HasPeripheryTerminal { this: BaseSubsystem => val params = p(PeripheryTerminalKey) val terminal_name = Some("terminal_0") val terminal = LazyModule(new TLTerminal(pbus.beatBytes, params)) .suggestName(terminal_name) pbus.toVariableWidthSlave(terminal_name) { terminal.node } } trait HasPeripheryTerminalBundle { val terminal: TerminalSysIO val dvi: TerminalDVIIO } trait HasPeripheryTerminalModuleImp extends LazyModuleImp with HasPeripheryTerminalBundle { val outer: HasPeripheryTerminal val terminal = IO(new TerminalSysIO) val dvi = IO(new TerminalDVIIO) // right sides defined in TerminalRegBundle terminal <> outer.terminal.module.io.port_sys dvi <> outer.terminal.module.io.port_dvi }