Skip to content

Commit

Permalink
MIITx added and tested
Browse files Browse the repository at this point in the history
  • Loading branch information
egk696 committed Mar 1, 2019
1 parent 0ce017a commit 2efde25
Show file tree
Hide file tree
Showing 16 changed files with 435 additions and 207 deletions.
78 changes: 42 additions & 36 deletions src/main/scala/ethcontroller/design/EthRxController.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// See README.md for license details.

package ethcontroller.design

import Chisel._
Expand All @@ -6,9 +8,11 @@ import ethcontroller.protocols.EthernetConstants
import ocp._

class EthRxController(numFrameBuffers: Int, timeStampWidth: Int) extends Module {
val io = new Bundle(){
val io = new Bundle() {
val ocp = new OcpCoreSlavePort(32, 32)
val ramPorts = Vec.fill(numFrameBuffers){new OcpCoreMasterPort(32, 32)}
val ramPorts = Vec.fill(numFrameBuffers) {
new OcpCoreMasterPort(32, 32)
}
val miiChannel = new MIIChannel().asInput()
val rtcTimestamp = UInt(INPUT, width = timeStampWidth)
}
Expand All @@ -31,24 +35,26 @@ class EthRxController(numFrameBuffers: Int, timeStampWidth: Int) extends Module
val wrRamIdReg = Reg(init = UInt(0, width = constRamIdWidth))
val rdRamIdReg = Reg(init = UInt(0, width = constRamIdWidth))
val byteCntReg = Reg(init = UInt(0, width = constRamAddrWidth))
val ramMasterRegs = Vec.fill(numFrameBuffers){Reg(new OcpCoreMasterSignals(constRamAddrWidth, 32))}
val ramMasterRegs = Vec.fill(numFrameBuffers) {
Reg(new OcpCoreMasterSignals(constRamAddrWidth, 32))
}
val dataReg = Reg(init = Bits(0, width = 32))
val respReg = Reg(init = OcpResp.NULL)

val rxEnReg = Reg(init = Bool(true))
val fifoCountReg = Reg(init = UInt(0, width = constRamIdWidth+1))
val fifoCountReg = Reg(init = UInt(0, width = constRamIdWidth + 1))
val fifoEmptyReg = Reg(init = Bool(true))
val fifoFullReg = Reg(init = Bool(false))
val fifoPopReg = Reg(init = Bool(false))
val macRxFilterReg = Reg(init = UInt(0, width = EthernetConstants.constEthMacLength))

val ethRxCtrlRegMap = Map(
"rxEn"->Map("Reg"->rxEnReg, "Addr"->Bits("h00")),
"fifoCount"->Map("Reg"->fifoCountReg, "Addr"->Bits("h01")),
"fifoEmpty"->Map("Reg"->fifoEmptyReg, "Addr"->Bits("h02")),
"fifoFull"->Map("Reg"->fifoFullReg, "Addr"->Bits("h03")),
"fifoPop"->Map("Reg"->fifoPopReg, "Addr"->Bits("h04")),
"macRxFilter"->Map("Reg"->macRxFilterReg, "Addr"->Bits("h05"))
"rxEn" -> Map("Reg" -> rxEnReg, "Addr" -> Bits("h00")),
"fifoCount" -> Map("Reg" -> fifoCountReg, "Addr" -> Bits("h01")),
"fifoEmpty" -> Map("Reg" -> fifoEmptyReg, "Addr" -> Bits("h02")),
"fifoFull" -> Map("Reg" -> fifoFullReg, "Addr" -> Bits("h03")),
"fifoPop" -> Map("Reg" -> fifoPopReg, "Addr" -> Bits("h04")),
"macRxFilter" -> Map("Reg" -> macRxFilterReg, "Addr" -> Bits("h05"))
)


Expand All @@ -64,20 +70,20 @@ class EthRxController(numFrameBuffers: Int, timeStampWidth: Int) extends Module
val ramWrSelOH = UIntToOH(wrRamIdReg)
val ramRdSelOH = UIntToOH(rdRamIdReg)

val ocpSelRam = Mux(ocpMasterReg.Addr(constRamAddrWidth-1) <= EthernetConstants.constEthFrameLength.U, true.B, false.B)
val ocpSelRam = Mux(ocpMasterReg.Addr(constRamAddrWidth - 1) <= EthernetConstants.constEthFrameLength.U, true.B, false.B)
val validRamPop = Mux(ethRxCtrlRegMap("fifoPop")("Reg") === true.B && !fifoFullReg, true.B, false.B)

val ethRamWrEn = Mux(ethByteDvReg && stateReg === stCollectPayload, true.B, false.B)
val ocpRamRdEn = Mux(ocpMasterReg.Cmd === OcpCmd.RD && ocpSelRam, true.B, false.B)

switch(stateReg) {
is(sWaitSFD) {
when(miiRx.io.ethSof && !fifoFullReg){
when(miiRx.io.ethSof && !fifoFullReg) {
stateReg := stCollectPayload
}
}
is(stCollectPayload) {
when(miiRx.io.ethEof){
when(miiRx.io.ethEof) {
stateReg := sWaitSFD
wrRamIdReg := wrRamIdReg + 1.U
fifoCountReg := fifoCountReg + 1.U
Expand All @@ -89,7 +95,7 @@ class EthRxController(numFrameBuffers: Int, timeStampWidth: Int) extends Module
byteCntReg := byteCntReg + 1.U
}

when(validRamPop){
when(validRamPop) {
rdRamIdReg := rdRamIdReg + 1.U
fifoCountReg := fifoCountReg - 1.U
}
Expand All @@ -99,52 +105,52 @@ class EthRxController(numFrameBuffers: Int, timeStampWidth: Int) extends Module
*/
ethRxCtrlRegMap("fifoPop")("Reg") := false.B
respReg := OcpResp.NULL
when(ocpSelRam){
when(ocpSelRam) {
dataReg := io.ramPorts(rdRamIdReg).S.Data
respReg := Mux(!fifoFullReg, io.ramPorts(rdRamIdReg).S.Resp, OcpResp.FAIL)
}.otherwise{
when(ocpMasterReg.Cmd === OcpCmd.RD){
}.otherwise {
when(ocpMasterReg.Cmd === OcpCmd.RD) {
respReg := OcpResp.DVA
when(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("rxEn")("Addr")){
when(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("rxEn")("Addr")) {
dataReg := ethRxCtrlRegMap("rxEn")("Reg")
}.elsewhen(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("fifoCount")("Addr")){
}.elsewhen(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("fifoCount")("Addr")) {
dataReg := ethRxCtrlRegMap("fifoCount")("Reg")
}.elsewhen(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("fifoEmpty")("Addr")){
}.elsewhen(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("fifoEmpty")("Addr")) {
dataReg := ethRxCtrlRegMap("fifoEmpty")("Reg")
}.elsewhen(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("fifoFull")("Addr")){
}.elsewhen(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("fifoFull")("Addr")) {
dataReg := ethRxCtrlRegMap("fifoFull")("Reg")
}.elsewhen(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("fifoPop")("Addr")){
}.elsewhen(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("fifoPop")("Addr")) {
dataReg := ethRxCtrlRegMap("fifoPop")("Reg")
}.elsewhen(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("macRxFilter")("Addr")){
}.elsewhen(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("macRxFilter")("Addr")) {
dataReg := ethRxCtrlRegMap("macRxFilter")("Reg")
}
}.elsewhen(ocpMasterReg.Cmd === OcpCmd.WR){
when(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("rxEn")("Addr")){
}.elsewhen(ocpMasterReg.Cmd === OcpCmd.WR) {
when(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("rxEn")("Addr")) {
ethRxCtrlRegMap("rxEn")("Reg") := orR(ocpMasterReg.Data)
respReg := OcpResp.DVA
}.elsewhen(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("fifoCount")("Addr")){
}.elsewhen(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("fifoCount")("Addr")) {
respReg := OcpResp.ERR
}.elsewhen(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("fifoEmpty")("Addr")){
}.elsewhen(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("fifoEmpty")("Addr")) {
respReg := OcpResp.ERR
}.elsewhen(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("fifoFull")("Addr")){
}.elsewhen(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("fifoFull")("Addr")) {
respReg := OcpResp.ERR
}.elsewhen(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("fifoPop")("Addr")){
}.elsewhen(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("fifoPop")("Addr")) {
ethRxCtrlRegMap("fifoPop")("Reg") := true.B //as long as you write something it is set to one which is automatically reset in the next clock cycle
respReg := OcpResp.DVA
}.elsewhen(ocpMasterReg.Addr(4,2) === ethRxCtrlRegMap("macRxFilter")("Addr")){
}.elsewhen(ocpMasterReg.Addr(4, 2) === ethRxCtrlRegMap("macRxFilter")("Addr")) {
ethRxCtrlRegMap("macRxFilter")("Reg") := ocpMasterReg.Data
respReg := OcpResp.DVA
}
}.otherwise{
}.otherwise {
respReg := OcpResp.NULL
}
}

/**
* Ram Master Control
*/
for(ramId <- 0 until numFrameBuffers){
ramMasterRegs(ramId).Addr := RegNext(Mux(ramWrSelOH(ramId) && ethRamWrEn, byteCntReg(constRamAddrWidth-1, 2), ocpMasterReg.Addr(constRamAddrWidth-1, 2)))
for (ramId <- 0 until numFrameBuffers) {
ramMasterRegs(ramId).Addr := RegNext(Mux(ramWrSelOH(ramId) && ethRamWrEn, byteCntReg(constRamAddrWidth - 1, 2), ocpMasterReg.Addr(constRamAddrWidth - 1, 2)))
ramMasterRegs(ramId).ByteEn := RegNext(Mux(ramWrSelOH(ramId) && ethRamWrEn, UIntToOH(byteCntReg(1, 0), width = 4), Mux(ocpRamRdEn, ocpMasterReg.ByteEn, Bits("b0000"))))
ramMasterRegs(ramId).Cmd := RegNext(Mux(ramWrSelOH(ramId) && ethRamWrEn, OcpCmd.WR, Mux(ocpRamRdEn, OcpCmd.RD, OcpCmd.IDLE)))
ramMasterRegs(ramId).Data := RegNext(ethByteReg)
Expand All @@ -157,12 +163,12 @@ class EthRxController(numFrameBuffers: Int, timeStampWidth: Int) extends Module
io.ocp.S.Resp := respReg
miiRx.io.miiChannel <> io.miiChannel
miiRx.io.rxEn := ethRxCtrlRegMap("rxEn")("Reg")
for(ramId <- 0 until numFrameBuffers){
for (ramId <- 0 until numFrameBuffers) {
io.ramPorts(ramId).M := ramMasterRegs(ramId)
}
}

object EthRxController extends App{
chiselMain(Array[String]("--backend", "v", "--targetDir", "generated/"+this.getClass.getSimpleName.dropRight(1)),
object EthRxController extends App {
chiselMain(Array[String]("--backend", "v", "--targetDir", "generated/" + this.getClass.getSimpleName.dropRight(1)),
() => Module(new EthRxController(2, 64)))
}
24 changes: 13 additions & 11 deletions src/main/scala/ethcontroller/design/MIIRx.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// See README.md for license details.

package ethcontroller.design

import Chisel._
import ethcontroller.interfaces.MIIChannel
import ethcontroller.protocols.EthernetConstants
import ethcontroller.utils.Deserializer

class MIIRx extends Module{
class MIIRx extends Module {
val io = new Bundle() {
val miiChannel = new MIIChannel().asInput()
val rxEn = Bool(INPUT)
Expand All @@ -26,14 +28,14 @@ class MIIRx extends Module{
/**
* Sampling clock and line of MII
*/
val miiClkReg = Reg(next=io.miiChannel.clk)
val miiClkReg2 = Reg(next=miiClkReg)
val miiDvReg = Reg(next=io.miiChannel.dv)
val miiDvReg2 = Reg(next=miiDvReg)
val miiDataReg = Reg(next=io.miiChannel.data)
val miiDataReg2 = Reg(next=miiDataReg)
val miiErrReg = Reg(next=io.miiChannel.err)
val miiErrReg2 = Reg(next=miiErrReg)
val miiClkReg = Reg(next = io.miiChannel.clk)
val miiClkReg2 = Reg(next = miiClkReg)
val miiDvReg = Reg(next = io.miiChannel.dv)
val miiDvReg2 = Reg(next = miiDvReg)
val miiDataReg = Reg(next = io.miiChannel.data)
val miiDataReg2 = Reg(next = miiDataReg)
val miiErrReg = Reg(next = io.miiChannel.err)
val miiErrReg2 = Reg(next = miiErrReg)

/**
* Flags
Expand Down Expand Up @@ -68,12 +70,12 @@ class MIIRx extends Module{
* Ethernet frame detection logic
*/
sofReg := false.B
when(regBuffer === EthernetConstants.constSFD && regBufferDv){
when(regBuffer === EthernetConstants.constSFD && regBufferDv) {
sofReg := true.B
}

eofReg := false.B
when(validPHYDataReg && ~validPHYData){
when(validPHYDataReg && ~validPHYData) {
eofReg := true.B
}

Expand Down
87 changes: 87 additions & 0 deletions src/main/scala/ethcontroller/design/MIITx.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package ethcontroller.design

import Chisel._
import ethcontroller.interfaces.MIIChannel
import ethcontroller.utils.Serializer

class MIITx extends Module {
val io = new Bundle() {
val miiChannel = new MIIChannel()
val startTx = Bool(INPUT)
val endTx = Bool(INPUT)
val busy = Bool(OUTPUT)
val macDataDv = Bool(INPUT)
val macData = Bits(INPUT, width = 64)
val phyErr = Bool(OUTPUT)
}

/**
* Registers and components
*/
val busyReg = Reg(init = false.B)
val startTxReg = Reg(init = false.B)

val serializeDataToByte = Module(new Serializer(false, 64, 8))
val serializeByteToNibble = Module(new Serializer(false, 8, 4))

/**
* Sampling clock and line of MII
*/
val miiClkReg = Reg(next = io.miiChannel.clk)
val miiClkReg2 = Reg(next = miiClkReg)
val miiErrReg = Reg(next = io.miiChannel.err)
val miiErrReg2 = Reg(next = miiErrReg)
val miiDataReg = Reg(init = UInt(0, width = 4))
val miiDvReg = Reg(init = false.B)

/**
* Flags
*/
val phyNA = io.miiChannel.col & ~io.miiChannel.crs
val phyError = phyNA || miiErrReg2
val fallingMIIEdge = ~miiClkReg & miiClkReg2 //we check the falling so that when the rising arrives on the next rising the data will be available to the PHY


/**
* Serialize Preamble to Byte
*/
serializeDataToByte.io.load := io.macDataDv
serializeDataToByte.io.shiftIn := io.macData
serializeDataToByte.io.en := ~serializeByteToNibble.io.dv

/**
* Serialize Output to Nibble
*/
serializeByteToNibble.io.load := serializeDataToByte.io.dv
serializeByteToNibble.io.shiftIn := serializeDataToByte.io.shiftOut
serializeByteToNibble.io.en := fallingMIIEdge

/**
* Interface control and automatic PREAMBLE/IFG injection
*/
when(io.startTx) {
busyReg := true.B
}.elsewhen(RegNext(serializeDataToByte.io.done) && RegNext(serializeByteToNibble.io.done)) {
busyReg := false.B
}

when(fallingMIIEdge) {
//(De-)Assert MII data valid
when(busyReg) {
miiDvReg := true.B
}.elsewhen(~busyReg) {
miiDvReg := false.B
}
//Data nibble
miiDataReg := serializeByteToNibble.io.shiftOut
}

/**
* I/O plumbing
*/
io.busy := serializeDataToByte.io.dv
io.phyErr := phyNA
io.miiChannel.data := miiDataReg
io.miiChannel.dv := miiDvReg

}
16 changes: 9 additions & 7 deletions src/main/scala/ethcontroller/interfaces/MIIChannel.scala
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
// See README.md for license details.

package ethcontroller.interfaces

import Chisel.{Bits, Bool, Bundle, INPUT}
import Chisel.{Bits, Bool, Bundle, INPUT, OUTPUT}

class MIIChannel extends Bundle{
class MIIChannel extends Bundle {
/** Clock from the PHY */
val clk = Bool(INPUT)
/** Received data valid */
val dv = Bool()
val dv = Bool(OUTPUT)
/** Received nibble data */
val data = Bits(width=4)
val data = Bits(OUTPUT,width = 4)
/** Signal could not be decoded to data */
val err = Bool()
val err = Bool(INPUT)
/** Carrier-sense signal */
val crs = Bool()
val crs = Bool(INPUT)
/** Collision detection signal */
val col = Bool()
val col = Bool(INPUT)
}
4 changes: 3 additions & 1 deletion src/main/scala/ethcontroller/interfaces/PHYChannel.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// See README.md for license details.

package ethcontroller.interfaces

import Chisel.{Bool, Bundle, INPUT, OUTPUT}

class PHYChannel extends Bundle{
class PHYChannel extends Bundle {
/** Management data clock to the PHY */
val mdc = Bool(OUTPUT)
/** Management output data */
Expand Down
11 changes: 6 additions & 5 deletions src/main/scala/ethcontroller/protocols/EthernetConstants.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,17 @@ object EthernetConstants {

// Constants
val constEthFrameLength = 1518 * 8 //bits
val constEthMacLength = 6*8 //bits
val constSFD = Bits("h55555555555555D5")
val constEthMacLength = 6 * 8 //bits
val constSFD = Bits("h55555555555555D5")
val constIFG = Bits("h0000000000000000")
val constVLANt1 = Bits("h8100")
val constVLANt2 = Bits("h88A8")
val constVLANt3 = Bits("h9100")
val constMPLSt1 = Bits("h8847")
val constMPLSt2 = Bits("h8848")
val constIPv4t = Bits("h0800")
val constIPv6t = Bits("h86DD")
val constPTP2t = Bits("h88F7")
val constIPv4t = Bits("h0800")
val constIPv6t = Bits("h86DD")
val constPTP2t = Bits("h88F7")
val constPTP4t1 = Bits("h013F")
val constPTP4t2 = Bits("h0140")
val constPTPGeneralPort = 319.U
Expand Down
Loading

0 comments on commit 2efde25

Please sign in to comment.