Eworm001 发表于 2019-2-20 20:36:35

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)
    }

}
}

xiaocat85 发表于 2019-2-20 22:40:27

赶时髦,用上Chisel了,赞一个
页: [1]
查看完整版本: Chisel Uart 接收并发送