diff --git a/src/main/scala/backBoard/shin/README.md b/src/main/scala/backBoard/shin/README.md index eb83275..7cca836 100644 --- a/src/main/scala/backBoard/shin/README.md +++ b/src/main/scala/backBoard/shin/README.md @@ -3,17 +3,17 @@ ## ShinTop 顶层模块 ### 例化模块 - * slaveParser 从站解析模块 - * masterParser 主站解析模块 +* slaveParser 从站解析模块 +* masterParser 主站解析模块 - * downCDRIn 下行CDR接收模块 - * upCDRIn 上行CDR接收模块 - * downCDROut 下行CDR发送模块 - * upCDROut 上行CDR发送模块 +* downCDRIn 下行CDR接收模块 +* upCDRIn 上行CDR接收模块 +* downCDROut 下行CDR发送模块 +* upCDROut 上行CDR发送模块 - * interface 寄存器逻辑控制模块 +* interface 寄存器逻辑控制模块 - * sram 分别为8个SM例化4个或2个2k SRAM用于sram FIFO +* sram 分别为8个SM例化4个或2个2k SRAM用于sram FIFO ``` val sram = Seq( @@ -34,58 +34,113 @@ ### 例化模块 #### SlaveRecParser 接收解析器 - * downRecParser 下行接收解析器 - * upRecParser 上行接收解析器 +* downRecParser 下行接收解析器 +* upRecParser 上行接收解析器 + +##### 输入输出 +* rec 输入来自CDRIn模块的axis格式原始数据 +* data 输出解析后的子报文负载 +* stateCurr 用于辅助上级SlaveParser模块 +* frameReq 输出解析的帧头给上级SlaveParser模块 +* subMsgReq 输出解析的子报文头给上级SlaveParser模块 +* resp 清模块的STATE_ERROR状态 +* isError 输出模块的错误信息触发中断 + ##### 状态机 - * 0:STATE_IDLE 空闲 - * 1:STATE_HEADER 包头 - * 2:STATE_SUBMSG_HEADER 子报文头 - * 3:STATE_PAYLOAD_DATA 子报文数据 - * 4:STATE_CRC CRC校验 - * 5:STATE_ERROR 错误状态 - * 6:STATE_WAIT 等待状态 +**(测试点:应该覆盖所有状态和跳转条件)** +* 0:STATE_IDLE 空闲 +* 1:STATE_HEADER 包头 +* 2:STATE_SUBMSG_HEADER 子报文头 +* 3:STATE_PAYLOAD_DATA 子报文数据 +* 4:STATE_CRC CRC校验 +* 5:STATE_ERROR 错误状态 + + ##### 逻辑及行为 - * STATE_IDLE 在空闲态,等待接收CDR解析后的axis格式数据,当valid从低跳高,进入STATE_HEADER,否则一直保持在STATE_IDLE - * STATE_HEADER - - 等待axis的fire`io.rec.fire`,否则保持STATE_HEADER,无动作 - - 检查tlast不应该出现`io.rec.bits.tlast`,否则进入STATE_ERROR **(测试点)** - - 检查长度计数到达4-1,否则保持STATE_HEADER - + 将包头信息装填入`frameHeader`寄存器 - - 长度计数到达4-1的同时检查`frameHeader.frameStyle` - + 常规包 FRAME_STYLE_COMMON 则进入 STATE_SUBMSG_HEADER - + 嗅探包 FRAME_STYLE_PROBE 则进入 STATE_CRC - + 其它则进入STATE_ERROR **(测试点:会不会影响xxSendGen的行为)** - + 使用`io.frameReq`通知上层模块SlaveParser接收包的到来 - - * STATE_SUBMSG_HEADER - - 等待axis的fire`io.rec.fire`,否则保持STATE_SUBMSG_HEADER,无动作 - - 检查tlast不应该出现`io.rec.bits.tlast`,否则进入STATE_ERROR **(测试点)** - - 检查长度计数到达7-1,否则保持STATE_SUBMSG_HEADER - + 将子报文头信息装填入`subMsgHeader`寄存器 - - 长度计数到达7-1时,进入STATE_PAYLOAD_DATA - + 使用`io.subMsgReq`通知上层模块SlaveParser子报文的到来 +* STATE_IDLE 在空闲态,等待接收CDR解析后的axis格式数据,当valid从低跳高,进入STATE_HEADER,否则一直保持在STATE_IDLE +* STATE_HEADER + - 等待axis的fire`io.rec.fire`,否则保持STATE_HEADER,无动作 + - 检查tlast不应该出现`io.rec.bits.tlast`,否则进入STATE_ERROR **(测试点)** + - 检查长度计数到达4-1,否则保持STATE_HEADER + + 将包头信息装填入`frameHeader`寄存器 + - 长度计数到达4-1的同时检查`frameHeader.frameStyle` + + 常规包 FRAME_STYLE_COMMON 则进入 STATE_SUBMSG_HEADER + + 嗅探包 FRAME_STYLE_PROBE 则进入 STATE_CRC + + 其它则进入STATE_ERROR **(测试点:会不会影响xxSendGen的行为)** + + 使用`io.frameReq`通知上层模块SlaveParser接收包的到来 - * STATE_PAYLOAD_DATA - - 等待axis的fire`io.rec.fire`,否则保持STATE_PAYLOAD_DATA,无动作 - - 检查tlast不应该出现`io.rec.bits.tlast`,否则进入STATE_ERROR **(测试点)** - - 检查io.data的数据流是否被外部fifo拒绝`isDataRejErr`,若fifo上溢出进入STATE_ERROR **(测试点)** - - 检查子报文长度计数`frameLenCnt`是否到达子报文头说明长度-1 `subMsgHeader.length - 1.U` - + 未到达,保持STATE_PAYLOAD_DATA - + 已到达,进一步检查帧长度`frameLenCnt`是否达到总报文头说明长度-1 `frameHeader.frameLenAim - 1.U` - * 未到达,进入STATE_SUBMSG_HEADER处理下一个子报文 - * 已到达,进入STATE_CRC做最后CRC校验 - + 将子报文负载数据通过io.data传输给上层SlaveParser存入down/up RecFifo 的pingpong缓冲区,准备用于发送转发 - * STATE_CRC - - 等待axis的fire`io.rec.fire`和`io.rec.bits.tlast`,否则保持STATE_CRC **(测试点:超长时间tlast不到来)** - - 等待长度计数等于4-1时刻,同时检查`isCrcPass`,若检查通过,回到STATE_IDLE,否则到STATE_ERROR **(测试点:tlast在计数4-1之前到来;tlast在计数4-1之后到来)** - * STATE_ERROR - - 在该状态`io.isError`保持为高,持续触发interface中的 下行/上行 接收错误中断 - - 当interface写清对应中断时,通过`io.resp`让状态机回到STATE_IDLE +* STATE_SUBMSG_HEADER + - 等待axis的fire`io.rec.fire`,否则保持STATE_SUBMSG_HEADER,无动作 + - 检查tlast不应该出现`io.rec.bits.tlast`,否则进入STATE_ERROR **(测试点)** + - 检查长度计数到达7-1,否则保持STATE_SUBMSG_HEADER + + 将子报文头信息装填入`subMsgHeader`寄存器 + - 长度计数到达7-1时,进入STATE_PAYLOAD_DATA + + 使用`io.subMsgReq`通知上层模块SlaveParser子报文的到来 + +* STATE_PAYLOAD_DATA + - 等待axis的fire`io.rec.fire`,否则保持STATE_PAYLOAD_DATA,无动作 + - 检查tlast不应该出现`io.rec.bits.tlast`,否则进入STATE_ERROR **(测试点)** + - 检查io.data的数据流是否被外部fifo拒绝`isDataRejErr`,若fifo上溢出进入STATE_ERROR **(测试点)** + - 检查子报文长度计数`frameLenCnt`是否到达子报文头说明长度-1 `subMsgHeader.length - 1.U` + + 未到达,保持STATE_PAYLOAD_DATA + + 已到达,进一步检查帧长度`frameLenCnt`是否达到总报文头说明长度-1 `frameHeader.frameLenAim - 1.U` + * 未到达,进入STATE_SUBMSG_HEADER处理下一个子报文 + * 已到达,进入STATE_CRC做最后CRC校验 + + 将子报文负载数据通过io.data传输给上层SlaveParser存入down/up-RecFifo 的pingpong缓冲区的enq,准备用于发送转发 +* STATE_CRC + - 等待axis的fire`io.rec.fire`和`io.rec.bits.tlast`,否则保持STATE_CRC **(测试点:超长时间tlast不到来)** + - 等待长度计数等于4-1时刻,同时检查`isCrcPass`,若检查通过,回到STATE_IDLE,否则到STATE_ERROR **(测试点:tlast在计数4-1之前到来;tlast在计数4-1之后到来)** +* STATE_ERROR + - 在该状态`io.isError`保持为高,持续触发interface中的 下行/上行 接收错误中断 + - 当interface写清对应中断时,通过`io.resp`让状态机回到STATE_IDLE #### 发送生成器 - * downSendGen 下行发送生成器 - * upSendGen 上行发送生成器 +* downSendGen 下行发送生成器 +* upSendGen 上行发送生成器 + +##### 输入输出 +* data 连接上级模块SlaveParser down/up-RecFifo 的pingpong缓冲区的deq,准备用于发送转发 +* frameReq 连接上级模块SlaveParser请求的帧头结构体 +* subMsgReq 连接上级模块SlaveParser请求的子报文结构体 +* send 输出axis格式的发送输出数据到CDRout模块 +* stateCurr 输出内部状态机状态给上级模块SlaveParser辅助判断(无意义) + +##### 状态机 +**(测试点:应该覆盖所有状态和跳转条件)** +* 0.U: STATE_IDLE 空闲 +* 1.U: STATE_FRAME_HEADER 发送帧头 +* 2.U: STATE_SUBMSG_HEADER 发送子报文头 +* 3.U: STATE_SUBMSG_DATA 发送子报文负载 +* 4.U: STATE_CRC 发送CRC校验 +* 5.U: STATE_WAIT 等待 + +##### 逻辑及行为 +* STATE_IDLE + - 等待帧头请求和确认`io.frameReq.fire`的到来,进入STATE_FRAME_HEADER状态,否则保持STATE_IDLE等待 +* STATE_FRAME_HEADER + - 等待axis的fire`io.send.fire`,否则保持STATE_FRAME_HEADER,无动作 + - 等待发送计数到达4-1(帧头发送完成) + + 如果为常规包`frameInfo.frameStyle === FRAME_STYLE_COMMON`, + * 子报文头请求已经到来,进入STATE_SUBMSG_HEADER发送子报文头 + * 子报文头请求没有到来,进入STATE_WAIT等待子报文头 **(测试点:确认等待期间,CDRout数据不会下溢)** + + 如果不为常规包(一般为嗅探包),进入STATE_CRC **(测试点: 如果既不是常规包,又不是嗅探包是否会出错)** +* STATE_SUBMSG_HEADER + - 等待axis的fire`io.send.fire`,否则保持STATE_SUBMSG_HEADER,无动作 + - 等待发送计数到达8-1(子报文头发送完成),进入STATE_SUBMSG_DATA +* STATE_SUBMSG_DATA + - 等待axis的fire`io.send.fire`,否则保持STATE_SUBMSG_DATA,无动作 + - 等待发送计数到达`subMsgInfoSel.length-1.U`(子报文负载发送完成) + + 若同时总负载长度计数`frameLenCnt`到达帧头请求长度`frameInfo.frameLenAim -1.U`,进入CRC + + 若还有子报文 + * 子报文头请求已经到来,进入STATE_SUBMSG_HEADER发送子报文头 + * 子报文头请求没有到来,进入STATE_WAIT等待子报文头 **(测试点:确认等待期间,CDRout数据不会下溢)** +* STATE_CRC + - 等待axis的fire`io.send.fire`,否则保持STATE_CRC,无动作 + - 当计数到达4-1,进入STATE_IDLE,否则保持STATE_CRC +* STATE_WAIT + - 当子报文头请求到来`io.subMsgReq.valid`,返回STATE_SUBMSG_HEADER继续处理,否则在STATE_WAIT **(测试点:是否会产生长时间等待情形而导致流水线溢出)** + diff --git a/src/main/scala/backBoard/shin/SlaveRecParser.scala b/src/main/scala/backBoard/shin/SlaveRecParser.scala index 689e5de..f18a86b 100644 --- a/src/main/scala/backBoard/shin/SlaveRecParser.scala +++ b/src/main/scala/backBoard/shin/SlaveRecParser.scala @@ -4,12 +4,20 @@ import chisel3._ import chisel3.util._ +/** + * @param rec 输入来自CDRIn模块的axis格式原始数据 + * @param data 输出解析后的子报文负载 + * @param stateCurr 用于辅助上级SlaveParser模块 + * @param frameReq 输出解析的帧头给上级SlaveParser模块 + * @param subMsgReq 输出解析的子报文头给上级SlaveParser模块 + * @param resp 清模块的STATE_ERROR状态 + * @param isError 输出模块的错误信息触发中断 + */ class SlaveRecParserIO extends Bundle{ val rec = Flipped( Decoupled(new AXIS_Bundle(8)) ) val data = Decoupled(UInt(8.W)) - val stateNext = Output(UInt(4.W)) val stateCurr = Output(UInt(4.W)) val frameReq = Valid( new FrameHeader ) @@ -34,7 +42,7 @@ class SlaveRecParser extends Module{ val STATE_ERROR = 5.U // - val stateNext = Wire(UInt(4.W)); io.stateNext := stateNext + val stateNext = Wire(UInt(4.W)) val stateCurr = RegNext(stateNext, STATE_IDLE); io.stateCurr := stateCurr io.isError := stateCurr === STATE_ERROR diff --git a/src/main/scala/backBoard/shin/SlaveSendGen.scala b/src/main/scala/backBoard/shin/SlaveSendGen.scala index 65fc363..96f6f82 100644 --- a/src/main/scala/backBoard/shin/SlaveSendGen.scala +++ b/src/main/scala/backBoard/shin/SlaveSendGen.scala @@ -8,18 +8,21 @@ class SubMsgTxInfo extends SubMsgHeader{ val source = UInt(2.W) } - +/** + * @param data 连接上级模块SlaveParser down/up-RecFifo 的pingpong缓冲区的deq,准备用于发送转发 + * @param frameReq 连接上级模块SlaveParser请求的帧头结构体 + * @param subMsgReq 连接上级模块SlaveParser请求的子报文结构体 + * @param send 输出axis格式的发送输出数据到CDRout模块 + * @param stateCurr 输出内部状态机状态给上级模块SlaveParser辅助判断(无意义) + */ class SlaveSendGenIO extends Bundle{ val data = Vec(2, Flipped( Decoupled(UInt(8.W)) ) ) - - val frameReq = Flipped(Decoupled( new FrameHeader )) val subMsgReq = Flipped(Decoupled( new SubMsgTxInfo )) val send = Decoupled(new AXIS_Bundle(8)) - val isError = Output(Bool()) val stateCurr = Output(UInt(3.W)) } @@ -40,15 +43,12 @@ class SlaveSendGen extends Module{ val STATE_SUBMSG_HEADER = 2.U val STATE_SUBMSG_DATA = 3.U val STATE_CRC = 4.U //CRC校验 - //val STATE_ERROR = 5.U - val STATE_WAIT = 6.U + val STATE_WAIT = 5.U val stateNext = Wire(UInt(3.W)) val stateCurr = RegNext(stateNext, STATE_IDLE); io.stateCurr := stateCurr - io.isError := false.B//stateCurr === STATE_ERROR - crc.io.isEnable := io.send.fire & ( stateCurr === STATE_FRAME_HEADER | stateCurr === STATE_SUBMSG_HEADER | @@ -128,7 +128,6 @@ class SlaveSendGen extends Module{ STATE_SUBMSG_DATA ), STATE_SUBMSG_DATA ), (stateCurr === STATE_CRC) -> Mux( io.send.fire, Mux( lengthCnt === (4-1).U, STATE_IDLE, STATE_CRC ), STATE_CRC), - // (stateCurr === STATE_ERROR) -> Mux( io.send.fire, STATE_IDLE, STATE_ERROR), (stateCurr === STATE_WAIT) -> Mux( io.subMsgReq.valid, STATE_SUBMSG_HEADER, STATE_WAIT), ))