spinal.lib.graphic.vga.BmbVgaCtrl.scala Maven / Gradle / Ivy
The newest version!
package spinal.lib.graphic.vga
import spinal.core._
import spinal.core.fiber._
import spinal.lib.bus.amba3.apb.{Apb3, Apb3SlaveFactory}
import spinal.lib.bus.amba4.axi.Axi4ReadOnly
import spinal.lib.bus.bmb.{Bmb, BmbAccessCapabilities, BmbAccessParameter, BmbImplicitPeripheralDecoder, BmbInterconnectGenerator, BmbParameter, BmbSlaveFactory}
import spinal.lib.bus.bsb.{Bsb, BsbInterconnectGenerator, BsbParameter}
import spinal.lib.graphic.{Rgb, RgbConfig, VideoDma}
import spinal.lib.generator._
import spinal.lib._
import spinal.lib.bus.misc.SizeMapping
import spinal.lib.com.uart.BmbUartCtrl
import spinal.lib.graphic.hdmi.VgaToHdmiEcp5
object BmbVgaCtrl{
def getBmbCapabilities(accessSource : BmbAccessCapabilities) = BmbSlaveFactory.getBmbCapabilities(
accessSource,
addressWidth = addressWidth,
dataWidth = 32
)
def addressWidth = 8
}
case class BmbVgaCtrlParameter(rgbConfig: RgbConfig,
timingsWidth: Int = 12){
}
case class BmbVgaCtrl(p : BmbVgaCtrlParameter,
ctrlParameter : BmbParameter,
inputParameter : BsbParameter,
vgaCd : ClockDomain) extends Component{
val io = new Bundle{
// val input = slave(Stream(Fragment(Rgb(p.rgbConfig))))
val input = slave(Bsb(inputParameter))
val ctrl = slave(Bmb(ctrlParameter))
val vga = master(Vga(p.rgbConfig))
}
val ctrl = BmbSlaveFactory(io.ctrl)
val run = ctrl.createReadAndWrite(Bool(),0x00) init(False)
val vga = new ClockingArea(vgaCd) {
val input = io.input.toStreamFragment(omitMask = true) //TODO
val resized = Stream(Fragment(Bits(16 bits)))
StreamFragmentWidthAdapter(input, resized)
val adapted = Stream(Fragment(Rgb(p.rgbConfig)))
adapted.arbitrationFrom(resized)
adapted.last := resized.last
adapted.r := U(resized.fragment(15-p.rgbConfig.rWidth+1, p.rgbConfig.rWidth bits))
adapted.g := U(resized.fragment(10-p.rgbConfig.gWidth+1, p.rgbConfig.gWidth bits))
adapted.b := U(resized.fragment( 4-p.rgbConfig.bWidth+1, p.rgbConfig.bWidth bits))
val run = BufferCC(BmbVgaCtrl.this.run)
val ctrl = VgaCtrl(p.rgbConfig, p.timingsWidth)
ctrl.feedWith(adapted, resync = run.rise)
io.input.ready setWhen(!run) //Flush
ctrl.io.softReset := !run
ctrl.io.vga <> io.vga
}
vga.ctrl.io.timings.driveFrom(ctrl, 0x40)
vga.ctrl.io.timings.addTag(crossClockDomain)
}
case class BmbVgaCtrlGenerator(ctrlOffset : Handle[BigInt] = Unset)
(implicit val interconnect: BmbInterconnectGenerator, val bsbInterconnect : BsbInterconnectGenerator, decoder : BmbImplicitPeripheralDecoder = null) extends Area{
val ctrl = Handle(logic.io.ctrl)
val input = Handle(logic.io.input)
val output = Handle(logic.io.vga)
val parameter = Handle[BmbVgaCtrlParameter]
val vgaCd = Handle[ClockDomain]
val logic : Handle[BmbVgaCtrl] = Handle(BmbVgaCtrl(
p = parameter,
ctrlParameter = accessRequirements.toBmbParameter(),
inputParameter = BsbParameter(
byteCount = is.byteCount,
sourceWidth = is.sourceWidth,
sinkWidth = is.sinkWidth,
withMask = is.withMask
),
vgaCd = vgaCd
))
val accessSource = Handle[BmbAccessCapabilities]
val accessRequirements = Handle[BmbAccessParameter]
interconnect.addSlave(
accessSource = accessSource,
accessCapabilities = accessSource.derivate(BmbVgaCtrl.getBmbCapabilities),
accessRequirements = accessRequirements,
bus = ctrl,
mapping = ctrlOffset.derivate(SizeMapping(_, 1 << BmbVgaCtrl.addressWidth))
)
if(decoder != null) interconnect.addConnection(decoder.bus, ctrl)
val is = vgaCd on bsbInterconnect.addSlave(input)
is.sinkWidth.load(0)
def withRegisterPhy(withColorEn : Boolean) = output.produce{
val reg = out(vgaCd.get(Reg(Vga(output.rgbConfig, false))))
reg.assignSomeByName(output)
when(!output.colorEn){
reg.color.clear()
}
reg
}
def withHdmiEcp5(hdmiCd : Handle[ClockDomain]) = output produce new Area{
val bridge = VgaToHdmiEcp5(vgaCd, hdmiCd)
bridge.io.vga << output
val gpdi_dp, gpdi_dn = out Bits(4 bits)
gpdi_dp := bridge.io.gpdi_dp
gpdi_dn := bridge.io.gpdi_dn
}
}