Chisel Uart 接收并发送
本帖最后由 Eworm001 于 2019-2-20 20:35 编辑Uart.scala
import chisel3._
import chisel3.util._
class UartRx extends Module {
val io = IO(new Bundle {
val rx = Input(Bool())
val d = Output(UInt(8.W))
val rdy = Output(Bool())
val clrRdy = Input(Bool())
})
val samStamp = RegInit(0.U(4.W))
//rx Debounce
val samBits = RegInit("hf".U)
samBits := Cat(samBits(2, 0), io.rx)
val rxDly0 = RegInit(true.B)
when(samBits.andR) {rxDly0 := true.B}
.elsewhen(samBits.orR) {rxDly0 := false.B}
val rxDly1 = RegNext(rxDly0, true.B)
val start = rxDly1 && (!rxDly0)
val samCnt = RegInit(0.U(4.W))
val bitCnt = RegInit(0.U(3.W))
val baudReq = (samCnt === 8.U)
val s_idle :: s_start :: s_data :: s_stop ::s_fend:: Nil = Enum(5)
val state = RegInit(s_idle)
switch(state) {
is(s_idle) {when(start) {state := s_start}}
is(s_start) {when(baudReq) {state := s_data}}
is(s_data){when(baudReq && (bitCnt === 7.U)) {state := s_stop}}
is(s_stop) {when(baudReq) {state := s_fend}}
is(s_fend){when(rxDly1){state := s_idle}}
}
when(state === s_idle) {samCnt := 0.U}
.otherwise {samCnt := samCnt + 1.U}
val tmp = RegInit(0.U(8.W))
when(state =/= s_data){bitCnt := 0.U}
.elsewhen(baudReq) {
tmp := Cat(rxDly1,tmp(7,1))
bitCnt := bitCnt + 1.U
}
val rdy_reg = RegInit(false.B)
val d_reg = RegInit(0.U(8.W))
when(io.clrRdy) {rdy_reg := false.B}
.elsewhen((state === s_fend)&&(!rdy_reg)){
d_reg := tmp
rdy_reg := true.B
}
io.d := d_reg
io.rdy := rdy_reg
}
class UartTx extends Module {
val io = IO(new Bundle {
var req = Input(Bool())
var d = Input(UInt(8.W))
val tx = Output(Bool())
val busy = Output(Bool())
})
//body
val tx_reg = RegInit(true.B)
val bsy_reg = RegInit(false.B)
val samCnt = RegInit(0.U(4.W))
val bitCnt = RegInit(0.U(4.W))
val baudReq = (samCnt === 15.U)
val s_idle :: s_start :: s_data :: s_stop ::s_fend :: Nil = Enum(5)
val state = RegInit(s_idle)
switch(state) {
is(s_idle) {when(io.req) {state := s_start}}
is(s_start) {when(baudReq) {state := s_data}}
is(s_data) {when(baudReq && (bitCnt === 7.U)) {state := s_stop}}
is(s_stop) {when(baudReq) {state := s_fend}}
is(s_fend){when(baudReq) {state := s_idle}}
}
when(state === s_idle) {samCnt := 0.U}
.otherwise {samCnt := samCnt + 1.U}
when(state =/= s_data) {bitCnt := 0.U}
.elsewhen(baudReq) {bitCnt := bitCnt + 1.U}
when(state === s_start) {tx_reg := false.B}
.elsewhen(state === s_data) {tx_reg := io.d(bitCnt)}
.elsewhen(state === s_stop) {tx_reg := true.B}
.otherwise {tx_reg := true.B}
when(state === s_idle) {bsy_reg := false.B}
.otherwise {bsy_reg := true.B}
io.tx := tx_reg
io.busy := bsy_reg
}
class UartCtl extends Module {
val io = IO(new Bundle {
val rxd = Input(UInt(8.W))
val rxrdy = Input(Bool())
val rxclrrdy = Output(Bool())
val txd = Output(UInt(8.W))
val txreq = Output(Bool())
val txbsy = Input(Bool())
})
//body
val txReq_reg = RegInit(false.B)
val rxClrRdy_reg = RegInit(false.B)
val txd_reg = RegInit(0.U(8.W))
val s_0 :: s_1 :: s_2:: s_3 ::s_4:: Nil = Enum(5)
val state = RegInit(s_0)
switch(state){
is(s_0){
when(io.rxrdy) {
txd_reg := io.rxd
rxClrRdy_reg := true.B
state := s_1
}
}
is(s_1){
rxClrRdy_reg := false.B
state := s_0
}
}
val txState = RegInit(s_0)
switch(txState) {
is(s_0) {
when(rxClrRdy_reg) {
txReq_reg := true.B
txState := s_1
}
}
is(s_1) {
when(io.txbsy) {
txReq_reg := false.B
txState := s_2
}
}
is(s_2) {
when(!io.txbsy) {
txState := s_0
}
}
}
io.rxclrrdy := rxClrRdy_reg
io.txd := txd_reg
io.txreq := txReq_reg
}
class UartTop extends Module {
val io = IO(new Bundle {
val rx = Input(Bool())
val tx = Output(Bool())
})
//body
val rx = Module(new UartRx)
val tx = Module(new UartTx)
val ctl = Module(new UartCtl)
io.tx := tx.io.tx
ctl.io.txbsy := tx.io.busy
tx.io.d := ctl.io.txd
tx.io.req := ctl.io.txreq
rx.io.rx := io.rx
rx.io.clrRdy := ctl.io.rxrdy
ctl.io.rxd := rx.io.d
ctl.io.rxrdy := rx.io.rdy
rx.io.clrRdy := ctl.io.rxclrrdy
}
UartTest.scala
class UartTopTest(c:UartTop) extendsPeekPokeTester(c){
poke(c.io.rx,true)
step(200)
for (i <- 0 to 255) {
//printf(p"Step $i")
//a Byte
var d =i
poke(c.io.rx, false)
step(16)
for(j <- 0 to 7){
poke(c.io.rx, d&0x01)
step(16)
d = (d>>1)
}
poke(c.io.rx, true)
step(16)
step(100)
}
}
object AuxSinkTopTester {
def main(args: Array): Unit = {
val margs = Array("--tr-write-vcd")
Driver.execute(margs, () => new UartTop) {
c => new UartTopTest(c)
}
}
}
赶时髦,用上Chisel了,赞一个
页:
[1]