1
0

Compare commits

...

3 Commits

Author SHA1 Message Date
88f1cbe420 Use NonBlockingEnqueue for terminal writes
This provides feedback to the programm if the last value was already
printed to the terminal. If not, new values are ignored (unchanged).
2018-05-14 20:05:14 +02:00
48d8524c4a Move terminal into own clock domain using AsyncQueue 2018-04-30 22:50:39 +02:00
d7b9834d96 Add TLTerminal (write-only terminal TL slave) 2018-04-30 00:45:27 +02:00

View File

@ -0,0 +1,115 @@
// 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
}