This provides feedback to the programm if the last value was already printed to the terminal. If not, new values are ignored (unchanged).
116 lines
3.3 KiB
Scala
116 lines
3.3 KiB
Scala
// 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
|
|
}
|