归一化mac的发送接收buf
This commit is contained in:
@@ -24,7 +24,7 @@ class RxBuffBase extends Module{
|
|||||||
val isEnqPo = ~isEnqPi
|
val isEnqPo = ~isEnqPi
|
||||||
|
|
||||||
val isDeqPi = RegInit(true.B)
|
val isDeqPi = RegInit(true.B)
|
||||||
val isDeqPo = ~isEnqPi
|
val isDeqPo = ~isDeqPi
|
||||||
|
|
||||||
|
|
||||||
val buff = for( i <- 0 until 2 ) yield { Module(new Queue( new Mac_Stream_Bundle, 2048 )) }
|
val buff = for( i <- 0 until 2 ) yield { Module(new Queue( new Mac_Stream_Bundle, 2048 )) }
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import chisel3.util._
|
|||||||
|
|
||||||
import Switch._
|
import Switch._
|
||||||
|
|
||||||
import freechips.rocketchip.util._
|
|
||||||
|
|
||||||
|
|
||||||
class MII extends Bundle with MDIO{
|
class MII extends Bundle with MDIO{
|
||||||
// Tx
|
// Tx
|
||||||
@@ -433,22 +434,8 @@ val rxethmac = withClockAndReset(io.mii.mrx_clk_pad_i.asClock, io.asyncReset)( M
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
val wishbone = Module(new MacTileLink)
|
|
||||||
|
|
||||||
|
|
||||||
wishbone.io.RetryLimit := RetryLimit
|
|
||||||
wishbone.io.LateCollLatched := LateCollLatched
|
|
||||||
wishbone.io.DeferLatched := DeferLatched
|
|
||||||
wishbone.io.CarrierSenseLost := CarrierSenseLost
|
|
||||||
|
|
||||||
PerPacketCrcEn := wishbone.io.PerPacketCrcEn
|
|
||||||
|
|
||||||
wishbone.io.r_TxEn := r_TxEn
|
|
||||||
wishbone.io.r_RxEn := r_RxEn
|
|
||||||
TxB_IRQ := false.B
|
|
||||||
TxE_IRQ := false.B
|
|
||||||
RxB_IRQ := false.B
|
|
||||||
RxE_IRQ := false.B
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -513,35 +500,28 @@ val rxethmac = withClockAndReset(io.mii.mrx_clk_pad_i.asClock, io.asyncReset)( M
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
val macTileLinkTx = withClockAndReset( io.mii.mtx_clk_pad_i.asClock, io.asyncReset ) (Module(new MacTileLinkTx))
|
val macTileLinkTx = Module(new MacTileLinkTx)
|
||||||
|
|
||||||
|
|
||||||
val txReq_ToAsync = Wire(new AsyncBundle(new Mac_Stream_Bundle))
|
|
||||||
txReq_ToAsync <> ToAsyncBundle( wishbone.io.txReq )
|
|
||||||
withClockAndReset(io.mii.mtx_clk_pad_i.asClock, io.asyncReset) {
|
|
||||||
macTileLinkTx.io.txReq <> FromAsyncBundle( txReq_ToAsync )
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
withClockAndReset( io.mii.mtx_clk_pad_i.asClock, io.asyncReset ){
|
|
||||||
macTileLinkTx.io.BlockingTxStatusWrite_sync := ShiftRegister( wishbone.io.BlockingTxStatusWrite, 2, false.B, true.B)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
RstDeferLatched := macTileLinkTx.io.RstDeferLatched
|
RstDeferLatched := macTileLinkTx.io.RstDeferLatched
|
||||||
TxStartFrm := macTileLinkTx.io.TxStartFrm
|
TxStartFrm := macTileLinkTx.io.TxStartFrm
|
||||||
TxEndFrm := macTileLinkTx.io.TxEndFrm
|
TxEndFrm := macTileLinkTx.io.TxEndFrm
|
||||||
TxData := macTileLinkTx.io.TxData
|
TxData := macTileLinkTx.io.TxData
|
||||||
|
|
||||||
|
|
||||||
wishbone.io.TxUsedData := TxUsedData
|
|
||||||
macTileLinkTx.io.TxUsedData := TxUsedData
|
macTileLinkTx.io.TxUsedData := TxUsedData
|
||||||
|
|
||||||
macTileLinkTx.io.TxAbort := TxAbort
|
macTileLinkTx.io.TxAbort := TxAbort
|
||||||
macTileLinkTx.io.TxDone := TxDone
|
macTileLinkTx.io.TxDone := TxDone
|
||||||
|
|
||||||
wishbone.io.TxAbortSync := ShiftRegister( TxAbort, 2, false.B, true.B )
|
macTileLinkTx.io.RetryLimit := RetryLimit
|
||||||
wishbone.io.TxDoneSync := ShiftRegister( TxDone, 2, false.B, true.B )
|
macTileLinkTx.io.LateCollLatched := LateCollLatched
|
||||||
|
macTileLinkTx.io.DeferLatched := DeferLatched
|
||||||
|
macTileLinkTx.io.CarrierSenseLost := CarrierSenseLost
|
||||||
|
PerPacketCrcEn := macTileLinkTx.io.PerPacketCrcEn
|
||||||
|
|
||||||
|
macTileLinkTx.io.r_TxEn := r_TxEn
|
||||||
|
|
||||||
|
io.txDeq <> macTileLinkTx.io.txDeq
|
||||||
|
|
||||||
|
macTileLinkTx.io.MTxClk := io.mii.mtx_clk_pad_i
|
||||||
|
macTileLinkTx.io.asyncReset := io.asyncReset
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -554,63 +534,30 @@ val rxethmac = withClockAndReset(io.mii.mrx_clk_pad_i.asClock, io.asyncReset)( M
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val macTileLinkRx = Module(new MacTileLinkRx)
|
||||||
|
macTileLinkRx.io.DribbleNibble := DribbleNibble
|
||||||
|
macTileLinkRx.io.LatchedCrcError := LatchedCrcError
|
||||||
|
macTileLinkRx.io.RxLateCollision := RxLateCollision
|
||||||
|
macTileLinkRx.io.LoadRxStatus := LoadRxStatus
|
||||||
|
|
||||||
|
macTileLinkRx.io.RxData := RxData
|
||||||
|
macTileLinkRx.io.RxValid := RxValid
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val macTileLinkRx = withClockAndReset( io.mii.mrx_clk_pad_i.asClock, io.asyncReset ) ( Module(new MacTileLinkRx) )
|
|
||||||
|
|
||||||
|
|
||||||
val req_ToAsync = Wire(new AsyncBundle(new Mac_Stream_Bundle))
|
|
||||||
|
|
||||||
wishbone.io.rxReq <> FromAsyncBundle( req_ToAsync )
|
|
||||||
|
|
||||||
|
|
||||||
withClockAndReset(io.mii.mrx_clk_pad_i.asClock, io.asyncReset) {
|
|
||||||
req_ToAsync <> ToAsyncBundle( macTileLinkRx.io.rxReq )
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// wishbone.io.LatchedRxLength_rxclk := macTileLinkRx.io.LatchedRxLength
|
|
||||||
wishbone.io.RxStatusInLatched_rxclk := macTileLinkRx.io.RxStatusInLatched
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Busy Interrupt
|
|
||||||
val Busy_IRQ_sync = ShiftRegister(macTileLinkRx.io.Busy_IRQ_rck, 2, false.B, true.B)
|
|
||||||
Busy_IRQ := Busy_IRQ_sync & ~RegNext(Busy_IRQ_sync, false.B)
|
|
||||||
|
|
||||||
withClockAndReset( io.mii.mrx_clk_pad_i.asClock, io.asyncReset ) {
|
|
||||||
macTileLinkRx.io.Busy_IRQ_syncb := ShiftRegister( Busy_IRQ_sync, 2, false.B, true.B )
|
|
||||||
|
|
||||||
macTileLinkRx.io.RxReady := ShiftRegister( wishbone.io.RxReady, 2, false.B, true.B )
|
|
||||||
}
|
|
||||||
|
|
||||||
macTileLinkRx.io.RxData := RxData
|
|
||||||
macTileLinkRx.io.RxValid := RxValid
|
|
||||||
|
|
||||||
macTileLinkRx.io.RxStartFrm := RxStartFrm
|
macTileLinkRx.io.RxStartFrm := RxStartFrm
|
||||||
macTileLinkRx.io.RxEndFrm := RxEndFrm
|
macTileLinkRx.io.RxEndFrm := RxEndFrm
|
||||||
|
|
||||||
|
Busy_IRQ := macTileLinkRx.io.Busy_IRQ
|
||||||
|
|
||||||
// macTileLinkRx.io.RxLength := RxByteCnt
|
macTileLinkRx.io.r_RxEn := r_RxEn
|
||||||
macTileLinkRx.io.LoadRxStatus := LoadRxStatus
|
|
||||||
macTileLinkRx.io.RxStatusIn := Cat(false.B, false.B, false.B, false.B, DribbleNibble, false.B, false.B, LatchedCrcError, RxLateCollision)
|
|
||||||
|
|
||||||
wishbone.io.rxEnq <> io.rxEnq
|
macTileLinkRx.io.rxEnq <> io.rxEnq
|
||||||
wishbone.io.txDeq <> io.txDeq
|
|
||||||
|
|
||||||
|
macTileLinkRx.io.MRxClk := io.mii.mrx_clk_pad_i
|
||||||
|
macTileLinkRx.io.asyncReset := io.asyncReset
|
||||||
|
|
||||||
|
TxB_IRQ := false.B
|
||||||
|
TxE_IRQ := false.B
|
||||||
|
RxB_IRQ := false.B
|
||||||
|
RxE_IRQ := false.B
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package MAC
|
|||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
|
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
|
|
||||||
class Mac_Stream_Bundle extends Bundle{
|
class Mac_Stream_Bundle extends Bundle{
|
||||||
val data = UInt(8.W)
|
val data = UInt(8.W)
|
||||||
@@ -14,77 +16,216 @@ class Mac_Stream_Bundle extends Bundle{
|
|||||||
|
|
||||||
class MacTileLinkRxIO extends Bundle{
|
class MacTileLinkRxIO extends Bundle{
|
||||||
|
|
||||||
val rxReq = Decoupled(new Mac_Stream_Bundle)
|
|
||||||
|
|
||||||
// val LatchedRxLength = Output(UInt(16.W))
|
|
||||||
val RxStatusInLatched = Output( UInt(9.W) )
|
|
||||||
|
|
||||||
// val RxLength = Input(UInt(16.W))
|
|
||||||
val LoadRxStatus = Input(Bool())
|
val LoadRxStatus = Input(Bool())
|
||||||
val RxStatusIn = Input(UInt(9.W))
|
|
||||||
|
|
||||||
|
|
||||||
val Busy_IRQ_rck = Output(Bool())
|
|
||||||
val Busy_IRQ_syncb = Input(Bool())
|
|
||||||
|
|
||||||
val RxData = Input(UInt(8.W)) // Received data byte (from PHY)
|
val RxData = Input(UInt(8.W)) // Received data byte (from PHY)
|
||||||
val RxValid = Input(Bool())
|
val RxValid = Input(Bool())
|
||||||
val RxReady = Input(Bool())
|
|
||||||
val RxStartFrm = Input(Bool())
|
val RxStartFrm = Input(Bool())
|
||||||
val RxEndFrm = Input(Bool())
|
val RxEndFrm = Input(Bool())
|
||||||
|
|
||||||
|
val DribbleNibble = Input(Bool())
|
||||||
|
val LatchedCrcError = Input(Bool())
|
||||||
|
val RxLateCollision = Input(Bool())
|
||||||
|
|
||||||
|
val asyncReset = Input(AsyncReset())
|
||||||
|
val MRxClk = Input(Bool())
|
||||||
|
|
||||||
|
val Busy_IRQ = Output(Bool())
|
||||||
|
|
||||||
|
|
||||||
|
val r_RxEn = Input(Bool()) // Receive enable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val rxEnq = Decoupled(new Mac_Stream_Bundle)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class MacTileLinkRx extends Module with RequireAsyncReset{
|
class MacTileLinkRx extends Module{
|
||||||
val io = IO(new MacTileLinkRxIO)
|
val io = IO(new MacTileLinkRxIO)
|
||||||
|
|
||||||
|
val syncReqBundle = Wire(Decoupled(new Mac_Stream_Bundle))
|
||||||
|
val asyncReqBundle = Wire(Decoupled(new Mac_Stream_Bundle))
|
||||||
|
val req_ToAsync = Wire(new AsyncBundle(new Mac_Stream_Bundle))
|
||||||
|
|
||||||
val ShiftWillEnd = RegInit(false.B)
|
val rxReady = RegInit(false.B)
|
||||||
|
val rxReadyAsync = Wire(Bool())
|
||||||
val RxStatusInLatched = RegEnable(io.RxStatusIn, 0.U(9.W), io.LoadRxStatus); io.RxStatusInLatched := RxStatusInLatched
|
withClockAndReset( io.MRxClk.asClock, io.asyncReset ) {
|
||||||
|
rxReadyAsync := ShiftRegister( rxReady, 2, false.B, true.B )
|
||||||
when( io.LoadRxStatus ) {
|
|
||||||
when( io.RxStatusIn.extract(4) ) { printf("Warning! DribbleNibble!\n"); }
|
|
||||||
when( io.RxStatusIn.extract(1) ) { printf("Warning! LatchedCrcError!\n"); }
|
|
||||||
when( io.RxStatusIn.extract(0) ) { printf("Warning! RxLateCollision!\n"); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// val ShiftEnded_rck = RegInit(false.B); io.ShiftEnded_rck := ShiftEnded_rck
|
withClockAndReset(io.MRxClk.asClock, io.asyncReset){
|
||||||
val RxEnableWindow = RegInit(false.B)
|
|
||||||
|
|
||||||
val Busy_IRQ_rck = RegInit(false.B); io.Busy_IRQ_rck := Busy_IRQ_rck
|
|
||||||
|
|
||||||
|
when( io.LoadRxStatus ) {
|
||||||
// Indicating start of the reception process
|
when( io.DribbleNibble ) { printf("Warning! DribbleNibble!\n"); }
|
||||||
val SetWriteRxDataToFifo =
|
when( io.LatchedCrcError ) { printf("Warning! LatchedCrcError!\n"); }
|
||||||
io.RxValid & io.RxReady & (io.RxStartFrm | RxEnableWindow )
|
when( io.RxLateCollision ) { printf("Warning! RxLateCollision!\n"); }
|
||||||
|
|
||||||
|
|
||||||
// Generation of the end-of-frame signal
|
|
||||||
when(io.RxStartFrm){
|
|
||||||
RxEnableWindow := true.B
|
|
||||||
} .elsewhen(io.RxEndFrm ){
|
|
||||||
RxEnableWindow := false.B
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val RxEnableWindow = RegInit(false.B)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
when(io.RxValid & io.RxStartFrm & ~io.RxReady){
|
|
||||||
|
// Indicating start of the reception process
|
||||||
|
val SetWriteRxDataToFifo =
|
||||||
|
io.RxValid & rxReadyAsync & (io.RxStartFrm | RxEnableWindow )
|
||||||
|
|
||||||
|
|
||||||
|
// Generation of the end-of-frame signal
|
||||||
|
when(io.RxStartFrm){
|
||||||
|
RxEnableWindow := true.B
|
||||||
|
} .elsewhen(io.RxEndFrm ){
|
||||||
|
RxEnableWindow := false.B
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val rxFifo = Module(new Queue(new Mac_Stream_Bundle, 4))
|
||||||
|
rxFifo.io.enq.valid := SetWriteRxDataToFifo
|
||||||
|
rxFifo.io.enq.bits.data := io.RxData
|
||||||
|
rxFifo.io.enq.bits.isStart := io.RxStartFrm
|
||||||
|
rxFifo.io.enq.bits.isLast := io.RxEndFrm
|
||||||
|
assert( ~(rxFifo.io.enq.valid & ~rxFifo.io.enq.ready) )
|
||||||
|
|
||||||
|
asyncReqBundle <> rxFifo.io.deq
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
syncReqBundle <> FromAsyncBundle( req_ToAsync )
|
||||||
|
|
||||||
|
withClockAndReset(io.MRxClk.asClock, io.asyncReset) {
|
||||||
|
req_ToAsync <> ToAsyncBundle( asyncReqBundle )
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Busy Interrupt
|
||||||
|
val Busy_IRQ_rck = withClockAndReset(io.MRxClk.asClock, io.asyncReset) {RegInit(false.B)}
|
||||||
|
val Busy_IRQ_sync = ShiftRegister(Busy_IRQ_rck, 2, false.B, true.B)
|
||||||
|
|
||||||
|
|
||||||
|
io.Busy_IRQ := Busy_IRQ_sync & ~RegNext(Busy_IRQ_sync, false.B)
|
||||||
|
|
||||||
|
|
||||||
|
withClockAndReset( io.MRxClk.asClock, io.asyncReset ) {
|
||||||
|
val Busy_IRQ_syncb = ShiftRegister( Busy_IRQ_sync, 2, false.B, true.B )
|
||||||
|
|
||||||
|
when(io.RxValid & io.RxStartFrm & ~rxReadyAsync){
|
||||||
Busy_IRQ_rck := true.B
|
Busy_IRQ_rck := true.B
|
||||||
} .elsewhen(io.Busy_IRQ_syncb){
|
} .elsewhen(Busy_IRQ_syncb){
|
||||||
Busy_IRQ_rck := false.B
|
Busy_IRQ_rck := false.B
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
when(syncReqBundle.bits.isLast & syncReqBundle.fire ){
|
||||||
|
rxReady := false.B
|
||||||
|
} .elsewhen( io.r_RxEn & (io.rxEnq.ready) ){
|
||||||
|
rxReady := true.B
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
io.rxEnq.bits := syncReqBundle.bits
|
||||||
|
io.rxEnq.valid := syncReqBundle.valid
|
||||||
|
syncReqBundle.ready := io.rxEnq.ready
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
assert( ~(io.rxEnq.valid & ~io.rxEnq.ready), "Assert Failed, rx overrun!" )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val rxFifo = Module(new Queue(new Mac_Stream_Bundle, 4))
|
|
||||||
rxFifo.io.enq.valid := SetWriteRxDataToFifo
|
|
||||||
rxFifo.io.enq.bits.data := io.RxData
|
|
||||||
rxFifo.io.enq.bits.isStart := io.RxStartFrm
|
|
||||||
rxFifo.io.enq.bits.isLast := io.RxEndFrm
|
|
||||||
assert( ~(rxFifo.io.enq.valid & ~rxFifo.io.enq.ready) )
|
|
||||||
|
|
||||||
io.rxReq <> rxFifo.io.deq
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,17 +4,14 @@ import chisel3._
|
|||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
|
|
||||||
|
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
|
|
||||||
class MacTileLinkTxIO extends Bundle{
|
class MacTileLinkTxIO extends Bundle{
|
||||||
|
|
||||||
val txReq = Flipped(Decoupled(new Mac_Stream_Bundle))
|
|
||||||
// val txResp = Decoupled()
|
|
||||||
|
|
||||||
|
|
||||||
val RstDeferLatched = Output(Bool())
|
val RstDeferLatched = Output(Bool())
|
||||||
val BlockingTxStatusWrite_sync = Input(Bool())
|
|
||||||
|
|
||||||
val TxStartFrm = Output(Bool()) // Transmit packet start frame
|
val TxStartFrm = Output(Bool()) // Transmit packet start frame
|
||||||
val TxEndFrm = Output(Bool()) // Transmit packet end frame
|
val TxEndFrm = Output(Bool()) // Transmit packet end frame
|
||||||
@@ -24,62 +21,216 @@ class MacTileLinkTxIO extends Bundle{
|
|||||||
val TxAbort = Input(Bool()) // Transmit packet abort
|
val TxAbort = Input(Bool()) // Transmit packet abort
|
||||||
val TxDone = Input(Bool()) // Transmission ended
|
val TxDone = Input(Bool()) // Transmission ended
|
||||||
|
|
||||||
|
val MTxClk = Input(Bool())
|
||||||
|
val asyncReset = Input(AsyncReset())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Tx Status signals
|
||||||
|
val RetryLimit = Input(Bool()) // Retry limit reached (Retry Max value +1 attempts were made)
|
||||||
|
val LateCollLatched = Input(Bool()) // Late collision occured
|
||||||
|
val DeferLatched = Input(Bool()) // Defer indication (Frame was defered before sucessfully sent)
|
||||||
|
val CarrierSenseLost = Input(Bool()) // Carrier Sense was lost during the frame transmission
|
||||||
|
val PerPacketCrcEn = Output(Bool()) // Per packet crc enable
|
||||||
|
|
||||||
|
//Register
|
||||||
|
val r_TxEn = Input(Bool()) // Transmit enable
|
||||||
|
|
||||||
|
val txDeq = Flipped(Decoupled(new Mac_Stream_Bundle))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MacTileLinkTx extends Module with RequireAsyncReset{
|
class MacTileLinkTx extends Module{
|
||||||
val io = IO(new MacTileLinkTxIO)
|
val io = IO(new MacTileLinkTxIO)
|
||||||
|
|
||||||
|
val syncReqBundle = Wire(Decoupled(new Mac_Stream_Bundle))
|
||||||
|
val asyncReqBundle = Wire(Decoupled(new Mac_Stream_Bundle))
|
||||||
|
val txReq_ToAsync = Wire(new AsyncBundle(new Mac_Stream_Bundle))
|
||||||
|
|
||||||
|
|
||||||
io.RstDeferLatched := io.BlockingTxStatusWrite_sync & ~RegNext(io.BlockingTxStatusWrite_sync, false.B)
|
|
||||||
|
|
||||||
val TxStartFrm = RegInit(false.B); io.TxStartFrm := TxStartFrm
|
withClockAndReset( io.MTxClk.asClock, io.asyncReset ){
|
||||||
val TxEndFrm = RegInit(false.B); io.TxEndFrm := TxEndFrm
|
|
||||||
val TxData = RegInit(0.U(8.W)); io.TxData := TxData
|
|
||||||
val ReadTxDataFromFifo_tck = RegInit(false.B);
|
|
||||||
|
val TxStartFrm = RegInit(false.B); io.TxStartFrm := TxStartFrm
|
||||||
|
val TxEndFrm = RegInit(false.B); io.TxEndFrm := TxEndFrm
|
||||||
|
val TxData = RegInit(0.U(8.W)); io.TxData := TxData
|
||||||
|
|
||||||
|
// Generating delayed signals
|
||||||
|
val TxAbort_q = RegNext( io.TxAbort, false.B)
|
||||||
|
val TxUsedData_q = RegNext( io.TxUsedData, false.B)
|
||||||
|
|
||||||
|
// Changes for tx occur every second clock. Flop is used for this manner.
|
||||||
|
val Flop = RegInit(false.B)
|
||||||
|
when( io.TxDone | io.TxAbort){
|
||||||
|
Flop := false.B
|
||||||
|
} .elsewhen ( io.TxUsedData ){
|
||||||
|
Flop := ~Flop
|
||||||
|
}
|
||||||
|
|
||||||
|
when( asyncReqBundle.valid & asyncReqBundle.bits.isStart ){
|
||||||
|
TxStartFrm := true.B
|
||||||
|
} .elsewhen(TxUsedData_q | io.TxAbort & (~TxAbort_q) ){
|
||||||
|
TxStartFrm := false.B
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Tx end frame generation
|
||||||
|
when(Flop & TxEndFrm | io.TxAbort){
|
||||||
|
TxEndFrm := false.B
|
||||||
|
} .elsewhen( asyncReqBundle.fire & asyncReqBundle.bits.isLast ){
|
||||||
|
TxEndFrm := true.B
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
asyncReqBundle.ready :=
|
||||||
|
asyncReqBundle.valid & asyncReqBundle.bits.isStart & ~TxStartFrm |
|
||||||
|
io.TxUsedData & Flop & ~TxEndFrm |
|
||||||
|
TxStartFrm & io.TxUsedData & Flop
|
||||||
|
|
||||||
|
when( asyncReqBundle.fire ){
|
||||||
|
TxData := asyncReqBundle.bits.data
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
assert( ~(asyncReqBundle.ready & ~asyncReqBundle.valid) )
|
||||||
|
|
||||||
|
|
||||||
// Generating delayed signals
|
|
||||||
val TxAbort_q = RegNext( io.TxAbort, false.B)
|
|
||||||
val TxUsedData_q = RegNext( io.TxUsedData, false.B)
|
|
||||||
|
|
||||||
// Changes for tx occur every second clock. Flop is used for this manner.
|
|
||||||
val Flop = RegInit(false.B)
|
|
||||||
when( io.TxDone | io.TxAbort){
|
|
||||||
Flop := false.B
|
|
||||||
} .elsewhen ( io.TxUsedData ){
|
|
||||||
Flop := ~Flop
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
when( io.txReq.valid & io.txReq.bits.isStart ){
|
|
||||||
TxStartFrm := true.B
|
|
||||||
} .elsewhen(TxUsedData_q | io.TxAbort & (~TxAbort_q) ){
|
|
||||||
TxStartFrm := false.B
|
|
||||||
|
txReq_ToAsync <> ToAsyncBundle( syncReqBundle )
|
||||||
|
withClockAndReset(io.MTxClk.asClock, io.asyncReset) {
|
||||||
|
asyncReqBundle <> FromAsyncBundle( txReq_ToAsync )
|
||||||
|
}
|
||||||
|
|
||||||
|
val BlockingTxStatusWrite = RegInit(false.B)
|
||||||
|
|
||||||
|
withClockAndReset( io.MTxClk.asClock, io.asyncReset ){
|
||||||
|
val BlockingTxStatusWrite_sync = ShiftRegister( BlockingTxStatusWrite, 2, false.B, true.B)
|
||||||
|
io.RstDeferLatched := BlockingTxStatusWrite_sync & ~RegNext(BlockingTxStatusWrite_sync, false.B)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Tx end frame generation
|
val TxAbortSync = ShiftRegister( io.TxAbort, 2, false.B, true.B )
|
||||||
when(Flop & TxEndFrm | io.TxAbort){
|
val TxDoneSync = ShiftRegister( io.TxDone, 2, false.B, true.B )
|
||||||
TxEndFrm := false.B
|
|
||||||
} .elsewhen( io.txReq.fire & io.txReq.bits.isLast ){
|
|
||||||
TxEndFrm := true.B
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
val txDonePulse = TxDoneSync & ~RegNext(TxDoneSync, false.B)
|
||||||
|
val txAbortPulse = TxAbortSync & ~RegNext(TxAbortSync, false.B)
|
||||||
|
|
||||||
|
|
||||||
|
io.PerPacketCrcEn := false.B
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
when( txDonePulse | txAbortPulse ){
|
||||||
|
|
||||||
|
when(io.RetryLimit) {printf("Warning, io.RetryLimit\n")}
|
||||||
|
when(io.LateCollLatched) {printf("Warning, io.LateCollLatched\n")}
|
||||||
|
when(io.DeferLatched) {printf("Warning, io.DeferLatched\n")}
|
||||||
|
when(io.CarrierSenseLost) {printf("Warning, io.CarrierSenseLost\n")}
|
||||||
|
when(txAbortPulse) {printf("Warning, txAbortPulse\n")}
|
||||||
|
}
|
||||||
|
|
||||||
|
val killTrans = RegInit(false.B)
|
||||||
|
|
||||||
|
when( (io.txDeq.fire & io.txDeq.bits.isLast) | ~io.txDeq.valid ){
|
||||||
|
killTrans := false.B
|
||||||
|
} .elsewhen( txAbortPulse ){
|
||||||
|
killTrans := true.B
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
io.txReq.ready :=
|
|
||||||
io.txReq.valid & io.txReq.bits.isStart & ~TxStartFrm |
|
|
||||||
io.TxUsedData & Flop & ~TxEndFrm |
|
|
||||||
TxStartFrm & io.TxUsedData & Flop
|
|
||||||
|
|
||||||
when( io.txReq.fire ){
|
|
||||||
TxData := io.txReq.bits.data
|
|
||||||
|
val isTxEnable = RegInit(false.B)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
when( io.txDeq.fire & io.txDeq.bits.isLast & ~io.r_TxEn ){
|
||||||
|
isTxEnable := false.B
|
||||||
|
} .elsewhen( io.r_TxEn ){
|
||||||
|
isTxEnable := true.B
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
assert( ~(io.txReq.ready & ~io.txReq.valid) )
|
io.txDeq.ready := Mux( killTrans, true.B, isTxEnable & syncReqBundle.ready )
|
||||||
|
syncReqBundle.valid := Mux( killTrans, false.B, isTxEnable & io.txDeq.valid )
|
||||||
|
syncReqBundle.bits := io.txDeq.bits
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
when(~TxDoneSync & ~TxAbortSync){
|
||||||
|
BlockingTxStatusWrite := false.B
|
||||||
|
} .elsewhen(txDonePulse | txAbortPulse){
|
||||||
|
BlockingTxStatusWrite := true.B
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,38 +19,9 @@ abstract class MacTileLinkBase() extends Module{
|
|||||||
|
|
||||||
class MacTileLinkIO extends Bundle{
|
class MacTileLinkIO extends Bundle{
|
||||||
|
|
||||||
val r_RxEn = Input(Bool()) // Receive enable
|
|
||||||
|
|
||||||
val rxReq = Flipped(Decoupled(new Mac_Stream_Bundle))
|
|
||||||
|
|
||||||
val RxStatusInLatched_rxclk = Input(UInt(9.W))
|
|
||||||
val RxReady = Output(Bool())
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val txReq = Decoupled(new Mac_Stream_Bundle)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Tx Status signals
|
|
||||||
val RetryLimit = Input(Bool()) // Retry limit reached (Retry Max value +1 attempts were made)
|
|
||||||
val LateCollLatched = Input(Bool()) // Late collision occured
|
|
||||||
val DeferLatched = Input(Bool()) // Defer indication (Frame was defered before sucessfully sent)
|
|
||||||
val CarrierSenseLost = Input(Bool()) // Carrier Sense was lost during the frame transmission
|
|
||||||
val PerPacketCrcEn = Output(Bool()) // Per packet crc enable
|
|
||||||
|
|
||||||
//Register
|
|
||||||
val r_TxEn = Input(Bool()) // Transmit enable
|
|
||||||
val BlockingTxStatusWrite = Output(Bool())
|
|
||||||
val TxUsedData = Input(Bool()) // Transmit packet used data
|
|
||||||
|
|
||||||
val TxAbortSync = Input(Bool()) // Transmit packet abort
|
|
||||||
val TxDoneSync = Input(Bool()) // Transmission ended
|
|
||||||
|
|
||||||
|
|
||||||
val rxEnq = Decoupled(new Mac_Stream_Bundle)
|
|
||||||
val txDeq = Flipped(Decoupled(new Mac_Stream_Bundle))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -59,28 +30,6 @@ abstract class MacTileLinkBase() extends Module{
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
val RxReady = RegInit(false.B); io.RxReady := RxReady
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// RxReady generation
|
|
||||||
when(io.rxReq.bits.isLast & io.rxReq.fire ){
|
|
||||||
RxReady := false.B
|
|
||||||
} .elsewhen( io.r_RxEn & (io.rxEnq.ready) ){
|
|
||||||
RxReady := true.B
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
io.rxEnq.bits := io.rxReq.bits
|
|
||||||
io.rxEnq.valid := io.rxReq.valid
|
|
||||||
io.rxReq.ready := io.rxEnq.ready
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
assert( ~(io.rxEnq.valid & ~io.rxEnq.ready), "Assert Failed, rx overrun!" )
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -99,74 +48,6 @@ abstract class MacTileLinkBase() extends Module{
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
val txDonePulse = io.TxDoneSync & ~RegNext(io.TxDoneSync, false.B)
|
|
||||||
val txAbortPulse = io.TxAbortSync & ~RegNext(io.TxAbortSync, false.B)
|
|
||||||
|
|
||||||
|
|
||||||
io.PerPacketCrcEn := false.B
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
when( txDonePulse | txAbortPulse ){
|
|
||||||
|
|
||||||
when(io.RetryLimit) {printf("Warning, io.RetryLimit\n")}
|
|
||||||
when(io.LateCollLatched) {printf("Warning, io.LateCollLatched\n")}
|
|
||||||
when(io.DeferLatched) {printf("Warning, io.DeferLatched\n")}
|
|
||||||
when(io.CarrierSenseLost) {printf("Warning, io.CarrierSenseLost\n")}
|
|
||||||
when(txAbortPulse) {printf("Warning, txAbortPulse\n")}
|
|
||||||
}
|
|
||||||
|
|
||||||
val killTrans = RegInit(false.B)
|
|
||||||
|
|
||||||
when( (io.txDeq.fire & io.txDeq.bits.isLast) | ~io.txDeq.valid ){
|
|
||||||
killTrans := false.B
|
|
||||||
} .elsewhen( txAbortPulse ){
|
|
||||||
killTrans := true.B
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val isTxEnable = RegInit(false.B)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
when( io.txDeq.fire & io.txDeq.bits.isLast & ~io.r_TxEn ){
|
|
||||||
isTxEnable := false.B
|
|
||||||
} .elsewhen( io.r_TxEn ){
|
|
||||||
isTxEnable := true.B
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
io.txDeq.ready := Mux( killTrans, true.B, isTxEnable & io.txReq.ready )
|
|
||||||
io.txReq.valid := Mux( killTrans, false.B, isTxEnable & io.txDeq.valid )
|
|
||||||
io.txReq.bits := io.txDeq.bits
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
val BlockingTxStatusWrite = RegInit(false.B); io.BlockingTxStatusWrite := BlockingTxStatusWrite
|
|
||||||
|
|
||||||
when(~io.TxDoneSync & ~io.TxAbortSync){
|
|
||||||
BlockingTxStatusWrite := false.B
|
|
||||||
} .elsewhen(txDonePulse | txAbortPulse){
|
|
||||||
BlockingTxStatusWrite := true.B
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user