diff --git a/src/main/scala/devices/terminal/Terminal.scala b/src/main/scala/devices/terminal/Terminal.scala new file mode 100644 index 0000000..e557fae --- /dev/null +++ b/src/main/scala/devices/terminal/Terminal.scala @@ -0,0 +1,112 @@ +// 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._ + + +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 writer_fn = (valid: Bool, data: UInt) => { + term.io.write_enable := valid + term.io.write_data := data + Bool(true) // terminal can read at every cycle + } + + regmap( + 0 -> Seq ( + RegField.w(8, writer_fn, RegFieldDesc( + "write", "Write an ASCII character to the terminal." + )) + ) + ) +} + +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 +}