|
import chisel3._
import chisel3.util._
class UartIO extends DecoupledIO(UInt(8.W)) { //具有valid,ready,bits的Bundle
override def cloneType: UartIO.this.type = new UartIO().asInstanceOf[this.type]
}
/**
* 没有缓冲区的只有valid/ready控制信号的TX
* @param frequency 频率
* @param baudRate 波特率
*/
class Tx(frequency:Int,baudRate:Int) extends Module {
val io = IO(new Bundle {
val txd = Output(UInt(1.W)) //串口的txd线
val deq = Flipped(new UartIO)
})
val BIT_CNT = ((frequency + baudRate / 2) / baudRate -1).asUInt() //按baudRate速率传一bit所需要的时钟周期数据,也就是波特率分频计数器值
val shiftReg = RegInit(0x7ff.U) //2047 共11bit
val cntReg = RegInit(0.U(20.W))
val bitsReg = RegInit(0.U(4.W))
io.deq.ready := (cntReg === 0.U) && (bitsReg === 0.U)
io.txd := shiftReg(0) //取寄存器shiftReg的第0位
when(cntReg === 0.U) {
cntReg := BIT_CNT
when(bitsReg =/= 0.U) {
val shift = shiftReg >> 1
shiftReg := Cat(1.U,shift(9,0))
bitsReg := bitsReg - 1.U
} .otherwise {
when(io.deq.valid) { //收到数据有效valid
shiftReg := Cat(Cat(3.U,io.deq.bits),0.U) // two stop bits, data, one start bit
bitsReg := 11.U
} .otherwise {
shiftReg := 0x7ff.U
}
}
}.otherwise {
cntReg := cntReg - 1.U
}
}
//带有valid/ready的单个字节缓冲区
class Buffer extends Module {
val io = IO(new Bundle {
val enq = Flipped(new UartIO)
val deq = new UartIO
})
val empty :: full :: Nil = Enum(2)
val stateReg = RegInit(empty)
val dataReg = RegInit(0.U(8.W))
when(stateReg === empty){ //empty状态
when(io.enq.valid) { //enq的上游master发来valid数据有效指示
dataReg := io.enq.bits //用寄存器dataReg接收数据
stateReg := full
}
}.otherwise { //full状态
when(io.deq.ready) { //deq的下游slave发出了ready信号表示已经准备好接收数据
stateReg := empty //状态迁回到empty
}
}
io.deq.bits := dataReg
io.enq.ready := stateReg === empty //空就给enq的上游master发出ready信号
io.deq.valid := stateReg === full //满就给deq的下游slave发出valid数据有效
}
class BufferedTx(frequency:Int,baudRate:Int) extends Module {
val io = IO(new Bundle {
val txd = Output(UInt(1.W))
val deq = Flipped(new UartIO)
})
val tx = Module(new Tx(frequency,baudRate))
val buf = Module(new Buffer)
buf.io.enq <> io.deq //父子模块级连 input连input,output连output 父输出值:=子输出值 子输入值:=父输入值
tx.io.deq <> buf.io.deq //
//在chisel中如果上下级模块连,左右两边都是output或input类型,则下面语法不正确:
//in.txt := tx.io.txd,特别是当书写到tx.io.之后IDE不会提示有txd
//只有用整体连接,比如下面:
io.txd <> tx.io.txd //父子级连,output连output
}
|
|