内存映射UART
简介
此示例将采用先前 示例 中实现的 UartCtrl
组件来创建内存映射UART控制器。
规范
该实现将基于带有RX FIFO的APB3总线。
这是寄存器映射表:
名称 |
类型 |
访问 |
地址 |
描述 |
---|---|---|---|---|
clockDivider |
UInt |
RW |
0 |
设置UartCtrl时钟分频器 |
frame |
UartCtrlFrameConfig |
RW |
4 |
设置数据长度、奇偶校验和停止位配置 |
writeCmd |
位 |
W |
8 |
向UartCtrl发送写命令 |
writeBusy |
Bool |
R |
8 |
当可以发送新的writeCmd时,位0 => 0 |
read |
Bool / Bits |
R |
12 |
位7到0 => rx payload
位31 => rx payload valid
|
实现
此实现将使用Apb3SlaveFactory工具。它允许您使用良好的语法定义APB3从端。您可以在 这里 找到该工具的文档。
首先,我们只需要定义控制器要使用的 Apb3Config
。它在Scala object中被定义为一个函数,以便能够从任何地方获取它。
object Apb3UartCtrl {
def getApb3Config = Apb3Config(
addressWidth = 4,
dataWidth = 32
)
}
然后我们可以定义一个 Apb3UartCtrl
组件,该组件实例化了一个 UartCtrl
并在它和APB3总线之间创建内存映射逻辑:
case class Apb3UartCtrl(uartCtrlConfig: UartCtrlGenerics, rxFifoDepth: Int) extends Component {
val io = new Bundle {
val bus = slave(Apb3(Apb3UartCtrl.getApb3Config))
val uart = master(Uart())
}
// Instantiate an simple uart controller
val uartCtrl = new UartCtrl(uartCtrlConfig)
io.uart <> uartCtrl.io.uart
// Create an instance of the Apb3SlaveFactory that will then be used as a slave factory drived by io.bus
val busCtrl = Apb3SlaveFactory(io.bus)
// Ask the busCtrl to create a readable/writable register at the address 0
// and drive uartCtrl.io.config.clockDivider with this register
busCtrl.driveAndRead(uartCtrl.io.config.clockDivider,address = 0)
// Do the same thing than above but for uartCtrl.io.config.frame at the address 4
busCtrl.driveAndRead(uartCtrl.io.config.frame,address = 4)
// Ask the busCtrl to create a writable Flow[Bits] (valid/payload) at the address 8.
// Then convert it into a stream and connect it to the uartCtrl.io.write by using an register stage (>->)
busCtrl.createAndDriveFlow(Bits(uartCtrlConfig.dataWidthMax bits),address = 8).toStream >-> uartCtrl.io.write
// To avoid losing writes commands between the Flow to Stream transformation just above,
// make the occupancy of the uartCtrl.io.write readable at address 8
busCtrl.read(uartCtrl.io.write.valid,address = 8)
// Take uartCtrl.io.read, convert it into a Stream, then connect it to the input of a FIFO of 64 elements
// Then make the output of the FIFO readable at the address 12 by using a non blocking protocol
// (Bit 7 downto 0 => read data <br> Bit 31 => read data valid )
busCtrl.readStreamNonBlocking(uartCtrl.io.read.queue(rxFifoDepth),
address = 12, validBitOffset = 31, payloadBitOffset = 0)
}
重要
是的,仅此而已。它同样是可综合的。
Apb3SlaveFactory工具不是硬编码到SpinalHDL编译器中的东西。它是使用SpinalHDL常规的硬件描述语法实现的。