Compare commits

...

10 Commits

Author SHA1 Message Date
RuigeLee
d53d1dbe9b * 上下行清硬件错误的条件增加为**上**行接收到isK28_0
* 从站发生硬件错误时,软件先写`clr`寄存器预解锁,其后上行方向接收到K28_0完成正式解锁
* 预解锁需要在K28_0之前,两者在同一拍到达将只会产生预解锁效果
2026-07-31 16:48:27 +08:00
RuigeLee
f2f2c306fe 从站的控制码传输机制 2026-07-30 15:59:07 +08:00
RuigeLee
4de049c05c 主站的ctrlWord 2026-07-30 14:51:22 +08:00
RuigeLee
3d446383e6 * PRE改为K28_0 //0x1C
* SDF改为K28_3 //0x7C

* CDR_OUT CDR_IN补充状态state_ctrl
* 编码的isCtrl在idle转preamble,preamble处最后一个,state_ctrl有效
* CDR_OUT补充对外寄存器输入ctrlWord
* CDR_IN对齐直接看decoder的控制字组合
* CDR_IN的控制字由补充状态机STATE_CTRL过滤后输出
* PRE SDF的控制字在包末尾将允许重复使用
2026-07-29 16:30:31 +08:00
RuigeLee
43369d87f7 增加控制码3个必选,3个可选 2026-07-28 17:28:49 +08:00
RuigeLee
6622bf1c73 增加在wsl1中对sbt2.0的支持 2026-07-28 16:10:01 +08:00
RuigeLee
db2e84c7f5 移除4b5b特性,只使用8b10b特性 2026-07-28 16:09:20 +08:00
259a4ab2af 更新fpga的顶层文件 2026-05-29 08:55:50 +08:00
39986b7039 增加resource代码,将spi多合一 2026-05-28 19:18:58 +08:00
RuigeLee
19cc932896 专利,文档 2026-05-12 17:31:36 +08:00
18 changed files with 1547 additions and 348 deletions

View File

@@ -22,7 +22,7 @@ endif
shin: shin:
rm -f ./generated/shin/* rm -f ./generated/shin/*
rm -f ./generated/SimCDR/* rm -f ./generated/SimCDR/*
sbt "test:runMain test.testShinModule" sbt --jvm-client "Test/runMain test.testShinModule"
testShin_vl: testShin_vl:
python3 ./tb/shinTest/gen_pkt.py ${SPI_TYPE} ${TRANS_CODE} ${CDR_TYPE} python3 ./tb/shinTest/gen_pkt.py ${SPI_TYPE} ${TRANS_CODE} ${CDR_TYPE}

19
doc/spec/SPI.md Normal file
View File

@@ -0,0 +1,19 @@
# SPI特性
## 同步采样SPI/QSPI
同步采样SPI通过使用系统驱动的时钟将输入的spi/QSPI信号全部当作异步数据信号通过观测CSN以及其余信号和SCK的关系采样SPI/QSPI的输入并给出输出
使用这种方法允许的QSPI传输速度会受到限制使用慢模式时允许的SCK速率为无穷小到1/2主时钟频率当使用快模式时允许的SCK速度为1/2主时钟频率到1倍主时钟频率
## 异步采样SPI/QSPI
异步采样设计的SPI/QSPI端直接使用SCK作为敏感源因此允许更高的传输速度但是SPI数据测和主时钟域需要精确地进行跨时钟域处理

113
doc/spec/SlaveParser.md Normal file
View File

@@ -0,0 +1,113 @@
# SlaveParser
----------------------------
以下为用户区域
---------------------------
* 该模块例化在`MstSlvSwith`模块内,负责从站接收功能实现
* 内部例化了两个`SlaveRecParser``downRecParser``upRecParser`)和两个`SlaveSendGen``downSendGen``upSendGen`
## 接口
* `downIn``Decoupled`封装的axis格式的lvds下行串行数据输入
* `downOut``Decoupled`封装的axis格式的lvds下行串行数据输出
* `upIn``Decoupled`封装的axis格式的lvds上行串行数据输入
* `upOut``Decoupled`封装的axis格式的lvds上行串行数据输出
* `sram_w`接入到4个`SmUnit`的SRAM写接口
* `sram_r`接入到4个`SmUnit`的SRAM读接口
* `dSMenq`接入到4个`SmUnit`的下行写入压栈Bool信号
* `uSMdeq`接入到4个`SmUnit`的上行读出弹出Bool信号
* `localDevIndex`输出本地设备的索引16bits
* `isDevOnRight`表示设备的“右边”下行方向下一级是否还有设备2bits实际只使用了1bits
* `isDevOnRightModify`表示设备的“右边”(下行方向下一级)是否改变过
* `indexOfRightDev`表示设备的“右边”(下行方向下一级)设备的索引号
* `mstDeltaTimeStamp`输出32bits的时间戳信息
* `slvDeltaTime`输出32bits的时间戳信息
* `deltaFinal`输出64bits的时间戳信息
* `isLoop`是否回环Bool
* `cReg`以结构体输入通用寄存器组
* `sReg`以结构体输入从站寄存器组
* `lvds`一个类似sram的访问接口用于允许从lvds总线的访问读写寄存器区域
* `intHWTrig`输出两个Bool硬件中断信号
* `intHWClr`输入两个Bool硬件清除中断信号
* `downRecStat`输出下行接收方向信息
* `upRecStat`输出上行接收方向信息
---------------------------------------------------------
## 主报文转发处理
* 下行发送模块`downSendGen`的帧头请求`frameReq`来自于下行接收`downRecParser`的报文头同步握手,同时`frameInfo`会被更改为本地设备的索引号`lcalDevIndex`
* 上行发送模块`upSendGen`的帧头请求`frameReq`
- 上行接收`upRecParser`的报文头同步握手,此时`frameStyle`需要为普通包`FRAME_STYLE_COMMON`,转发完全相同的上行接收报文头
- 下行接收到的是嗅探包而进入`isAckProbe`状态,发送(回复)嗅探包,`frameLenAim`为0`frameStyle``FRAME_STYLE_PROBE``frameInfo``localDevIndex`
## 子报文处理
* 子报文接收在上、下行各有2个位宽8bits深度20的FIFO`downRecFifo`/`upRecFifo`,以乒乓方式工作,子报文负载信息先进入`RecFifo`,再由发送模块`SendGen`发送
* 子报文接收在上、下行各有2组寄存器分别保存子报文头子报文尾信息以乒乓方式工作发送模块发送时从寄存器中提取和修改信息
## 索引特质
* 当子报文的`operator``SUBMSG_OPERATOR_INDEX`,为索引模式,从站按顺序更新自己的索引
* 更新索引时
- 本设备索引`localDevIndex`更新为子报文尾工作计数`workCnt`加1
- 下行转发的`workCnt`计数也加1`localDevIndex`
- 右边(下行方向)设备索引`indexOfRightDev`
+ 当是最后一个设备记录为0
+ 不是最后一个设备,更新为子报文尾工作计数`workCnt`计数加2
## 读写特质
* 写操作发生在下行阶段
* 读操作发生在上行阶段
* 单独读(和/或)写操作是否执行需要根据子报文头的报文类型`style`进行判定
- 当为顺序索引`SeqIndex`,只需要子报文头的设备索引`devIndex`匹配上本设备的索引`localDevIndex`,则需要进行操作
- 当为逻辑索引`LgcIndex`, 则需要进一步根据EBMMU的配置进行判定
* 广播读(和/或)写操作则均会被执行
* 如果从站对该子报文进行了操作,则转发到下一级从站时,子报文的工作计数`workCnt`需要加1
* lvds的写操作根据地址可以访问
- 寄存器
- SMUnit0
- SMUnit2
- SMUnit4
- SMUnit6
* lvds的写操作根据地址可以访问
- 寄存器
- SMUnit1
- SMUnit3
- SMUnit5
- SMUnit7
* 当lvds的读、写操作到特定地址时触发SMUnit对应的写压入或者读弹出操作
### ebmmu
## 同步特质
## 嗅探特质
##
---------------------------------------
以下是大模型补充区域
---------------------------------------

147
doc/spec/SlaveRecParser.md Normal file
View File

@@ -0,0 +1,147 @@
# SlaveRecParser
----------------------------
以下为用户区域
---------------------------
* 从站接收解析器使用状态机将输入的数据流解析获取到帧头子报文头负载数据子报文尾CRC校验等部分
* `SlaveRecParser``SlaveParser`模块中例化2个分别解析上行和下行方向接收到的数据
## 接口
* `rec`数据流输入接口以axis协议传输
* `data``decoupledIO`握手协议下的8bits数据传输将负载数据传输到下一级逻辑
* `stateNext` 组合逻辑输出下一拍状态机状态输出
* `stateCurr` 当前状态机状态寄存器输出
* `frameReq`以``validIO`握手协议输出帧头的信息,完整帧头信息以结构体打包
* `subMsgHeadReq`以``validIO`握手协议输出子报文头的信息,完整子报文头信息以结构体打包
* `subMsgTailReq`以``validIO`握手协议输出子报文尾的信息,完整子报文尾信息以结构体打包
* `isError` 输出Bool下的错误状态当状态机进入错误状态则为真
* `stat`输出传输状态
- `isHeaderError `帧头错误
- `isSubHeaderError`子报文头错误
- `isPayloadError `负载错误
- `isSubTailError `子报文尾错误
- `isCRCError `CRC错误
- `isFinish `传输正确完成
- `isRecByteAck `接收到一个字节
* `flush`软件复位
---------------------------------------
## 状态机
状态机有如下状态
* `STATE_IDLE`空闲
* `STATE_HEADER`解析帧头
* `STATE_SUBMSG_HEADER`解析子报文头
* `STATE_PAYLOAD_DATA`解析负载
* `STATE_SUBMSG_TAIL`解析子报文尾
* `STATE_CRC`CRC校验
* `STATE_ERROR`传输错误
* 上电复位或者软件复位后,状态机应该处在空闲状态
*`STATE_IDLE`
- 当输入的`rec``valid`从0跳1则进入`STATE_HEADER`
- 其余状况保持
*`STATE_HEADER`
-`rec`fire时`tlast`为1传输结束进入`STATE_ERROR`状态
-`rec`fire`tlast`为0接收帧头长度到达34byte判断解析的帧类型
+ 如果为常规包`FRAME_STYLE_COMMON`,进入解析子报文头`STATE_SUBMSG_HEADER`,此时为***时刻1***
+ 如果为探测包`FRAME_STYLE_PROBE`进入CRC校验`STATE_CRC`,此时为***时刻1***
+ 以上均不是则是错误,进入`STATE_ERROR`
- 其余状况保持
*`STATE_SUBMSG_HEADER`
-`rec`fire时`tlast`为1传输结束进入`STATE_ERROR`状态
-`rec`fire`tlast`为0接收子报文头长度到达56byte进入解析负载`STATE_PAYLOAD_DATA`,此时为***时刻2***
- 其余状况保持
*`STATE_PAYLOAD_DATA`
-`rec`fire时`tlast`为1传输结束或者`data`端口上溢出`isDataRejErr`valid为1而ready为0进入`STATE_ERROR`状态
-`rec`fire`tlast`为0接收子报文长度到达子报文头信息标示的长度-1进入子报文尾解析`STATE_SUBMSG_TAIL`
- 其余状况保持
*`STATE_SUBMSG_TAIL`
-`rec`fire时`tlast`为1传输结束进入`STATE_ERROR`状态
-`rec`fire`tlast`为0接收子报文尾长度到达12byte
+ 若已接受帧长度到达帧头标示的长度-1进入`STATE_CRC`,此时为***时刻3***
+ 若未达到,进入`STATE_SUBMSG_HEADER`接收下一个子报文,此时为***时刻3***
- 其余状况保持
*`STATE_CRC`
-`rec`fire时`tlast`为1传输结束
+ 传输长度达到34byte且CRC校验通过返回`STATE_IDLE`,解析正确完成
+ 否则,进入`STATE_ERROR`长度不一致或者CRC校验失败
- 其余状况保持
*`STATE_ERROR`
- 保持`STATE_ERROR`,只能通过软复位或者全局复位清除错误
--------------------------------------
## 帧结构
* 帧头4byte
- frameLenAim12bits帧长度目标
- Null2bits 留空
- frameStyle 2bits 包类型
+ `FRAME_STYLE_COMMON` 普通包 0
+ `FRAME_STYLE_PROBE` 嗅探包 1
- frameInfo 16bits其它信息
* 子报文头 6byte
- devIndex (14bits) 子报文中设备索引
- style (2bits) 子报文类型
+ SeqIndex 0 顺序索引
+ LgcIndex 2 逻辑索引
- address (16bits) 子报文地址
- operator (4bits) 子报文命令类型
+ `SUBMSG_OPERATOR_UNIREAD ` 单独读 0
+ `SUBMSG_OPERATOR_UNIWRITE ` 单独写 1
+ `SUBMSG_OPERATOR_UNIRDWR ` 单独读写 2
+ `SUBMSG_OPERATOR_SYNCA ` 时间同步操作A 0xa
+ `SUBMSG_OPERATOR_INDEX ` 索引 0xb
+ `SUBMSG_OPERATOR_SYNCC ` 时间同步操作C 0xc
+ `SUBMSG_OPERATOR_BOARDREAD ` 广播读 0xd
+ `SUBMSG_OPERATOR_BOARDWRITE` 广播写 0xe
+ `SUBMSG_OPERATOR_BOARDRDWR ` 广播读写 0xf
- length (12bits) 子报文负载长度
* 子报文尾 2byte
- 包含`workCnt`工作计数
-------------------------------------------
## 信息交换
* 在***时刻1***,`frameReq``valid`为高,将帧头信息使用结构体传输到`SlaveParser`模块
* 在***时刻2***`subMsgHeadReq``valid`为高,将子报文头信息使用结构体传输到`SlaveParser`模块
* 在***时刻3***`subMsgTailReq``valid`为高,将子报文尾信息使用结构体传输到`SlaveParser`模块
*`STATE_PAYLOAD_DATA`状态,`data``valid`始终为高,将负载数据传输到`SlaveParser`模块
- `SlaveParser`模块需要保证`data``ready``valid`为高是也为高,否则触发上溢出`isDataRejErr`
-----------------------
## CRC
* `SlaveRecParser`内部例化一个CRC32的8比特输入模块
*`rec`fire时且状态机处于`STATE_HEADER` `STATE_SUBMSG_HEADER` `STATE_PAYLOAD_DATA` `STATE_SUBMSG_TAIL`时,将数据输入模块进行计算
* 当状态机处于`STATE_IDLE`或者软件复位时清空CRC模块状态
* 当接收的最后4byte和CRC模块计算值匹配时CRC通过
---------------------------------------
以下是大模型补充区域
---------------------------------------

52
doc/spec/SmUnit.md Normal file
View File

@@ -0,0 +1,52 @@
# SMUnit
---------------------------------------------
以下是用户区域
---------------------------------------------
SMUnit本质是一个SRAM队列FIFO的维护模块
## 接口
对外接口包括:
* sram对外写接口
* sram对外读接口
* enq 输入Bool 压栈
* deq 输入Bool 弹出
* SRAM对内接口接入实际例化的多个SRAM
* cnt 输出当前fifo内有多少个数据
* flush 输入软件复位整个SMUnit
* isComf 输入Bool确认正式写入
* isAbrt 输入Bool放弃写入
-----------------------------------------
## 指针
* FIFO内部除了常见的读指针`rPtr`和写指针`wPtr`,额外增加了一个提交指针`cPtr`
* 提交指针是为了在系统错误写入时进行撤销而设计的当eb01从站接收数据过程中有可能收到了部分数据进而写入fifo并进行压栈但是本次传输并没有完全完成例如后续数据错误crc校验失败。这时我们需要回滚fifo的状态抛弃掉之前写入的数据
-------------------------
* 三个指针的位宽比fifo实际需要位宽多1bits用于指示空满`log2Ceil(depth)+1`
* 当读指针`rPtr`和提交指针`cPtr`相等时fifo为空
* 当读指针`rPtr`和写指针`wPtr`最高位不同其余比特相同fifo为满
* 复位或者使用`flush`软复位时,所有指针归零
*`enq`时且fifo不为满写指针加1
*`isAbrt`了,写指针`wPtr`回退到提交指针`cPtr`的位置
* **对于写指针`wPtr`,当`enq``isAbrt`同时到来,`enq`的优先级更高,对整个大系统工作功能会不会产生问题需要测,或者系统正常运行时不会发生这种情况**
*`deq`且fifo不为空读指针加1
*`isComf`时提交指针`cPtr`前进到写指针`wPtr`的位置
* 根据写指针`wPtr`的有效比特位的值sram对外写接口连接到内部实际例化特定SRAM的写接口其余未指向的接口保持为0不活动或者悬空
* 根据读指针`rPtr`的有效比特位的值sram对外读接口连接到内部实际例化特定SRAM的读接口其余未指向的接口保持为0不活动或者悬空
---------------------------------------
以下是大模型补充区域
---------------------------------------

View File

@@ -0,0 +1,64 @@
# 物理层优化
----------------------------
以下为用户区域
---------------------------
## 8b10b模块
* 停用4b5b特性
- 删除选择寄存器器 h4c寄存器不再有效
- 8b10b编码解码模块改为cdrout cdrin中例化
* 增加部分控制码
- 所有控制码都有极性
- 控制码有对应原始码
- 额外增加一条控制线
- 控制线由发送状态机控制
- 解码不需要极性控制
* 增加6个控制码
- 同时将`in(4,0)b11100".U``isCtrl`时映射为 `"b001111".U(6.W), "b110000".U(6.W)`
- 3个必选 `in(7,5)`保持不变
val isK28_0 = Output(Bool()) //0x1c
val isK28_3 = Output(Bool()) //0x7c
val isK28_4 = Output(Bool()) //0x9c
- 3个备选使用宏定义控制 `in(7,5)`平衡但需要增加翻转
* val isK28_1 = Output(Bool()) //0x3c IS_ENABLE_K28_1
* val isK28_2 = Output(Bool()) //0x5c IS_ENABLE_K28_2
* val isK28_6 = Output(Bool()) //0xdc IS_ENABLE_K28_6
* PRE改为K28_0 //0x1C
* SDF改为K28_3 //0x7C
* CDR_OUT CDR_IN补充状态state_ctrl
* 编码的isCtrl在idle转preamblepreamble处最后一个state_ctrl有效
* CDR_OUT补充对外寄存器输入ctrlWord
* CDR_IN对齐直接看decoder的控制字组合
* CDR_IN的控制字由补充状态机STATE_CTRL过滤后输出
* PRE SDF的控制字在包末尾将允许重复使用
* 主站寄存器增加"h600"指向CDR_OUT的ctrlWord
* 从站SlaveParse层增加两个`ctrlWordRelay`寄存器,
- 下行relay只看下行输入的6个`isK`布尔信号直接转译8bit原始码
- 上行relay在`isProbeAck`跳变状态直接拷贝下行寄存器信息其它条件看上行输入的6个`isK`布尔信号直接转译8bit原始码
* 上下行清硬件错误的条件增加为**上**行接收到`isK28_0`
* 从站发生硬件错误时,软件先写`clr`寄存器预解锁其后上行方向接收到K28_0完成正式解锁
* 预解锁需要在K28_0之前两者在同一拍到达将只会产生预解锁效果
---------------------------------------
以下是大模型补充区域
---------------------------------------

View File

@@ -0,0 +1,490 @@
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/05/13 11:43:33
// Design Name:
// Module Name: FPGATop
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
//bacon base project
module FPGATop(
input clkin,
input resetIn,
input dDatIn_p,
input dDatIn_n,
output dDatOut_p,
output dDatOut_n,
input uDatIn_p,
input uDatIn_n,
output uDatOut_p,
output uDatOut_n,
// input dDatIn,
// output dDatOut,
// input uDatIn,
// output uDatOut,
output sync0,
output sync1,
input latch0,
input latch1,
//input spi_sck,
//input spi_mosi,
//output spi_miso,
//input spi_csn,
(* keep="true" *)input io_qspi_sck,
(* keep="true" *)inout [3:0] io_qspi_data,
(* keep="true" *)input io_qspi_csn,
output interrupt,
output [3:0] io_led,
output [11:0] testIO
);
(* keep="true" *) wire [15:0] multiCLK;
(* keep="true" *) wire [3:0] div4CLK;
//assign testIO = multiCLK;
wire reset;
wire dDatIn;
wire dDatOut;
wire uDatIn;
wire uDatOut;
wire spi_sck;
wire spi_mosi;
wire spi_miso;
wire spi_csn;
//wire clkin_bufg;
// BUFG BUFG_inst (
// .O(clkin_bufg), // 1-bit output: Clock output
// .I(clkin) // 1-bit input: Clock input
// );
//clk_wiz_0 i_clk_0
// (
// .clk_out1(multiCLK[0]),
// .clk_out2(multiCLK[1]),
// .clk_out3(multiCLK[2]),
// .clk_out4(multiCLK[3]),
// .clk_out5(multiCLK[4]),
// .clk_in1(clkin_bufg)
// );
//clk_wiz_1 i_clk_1
// (
// .clk_out1(multiCLK[5]),
// .clk_out2(multiCLK[6]),
// .clk_out3(multiCLK[7]),
// .clk_out4(multiCLK[8]),
// .clk_out5(multiCLK[9]),
// .clk_in1(clkin_bufg)
// );
//clk_wiz_2 i_clk_2
// (
// .clk_out1(multiCLK[10]),
// .clk_out2(multiCLK[11]),
// .clk_out3(multiCLK[12]),
// .clk_out4(multiCLK[13]),
// .clk_out5(multiCLK[14]),
// .clk_out6(multiCLK[15]),
// .clk_in1(clkin_bufg)
// );
(* keep="true" *) wire clk320M;
clk_wiz_3 i_clk_3
(
.clk_out1(clk320M),
// .clk_out2(multiCLK[1]),
// .clk_out3(multiCLK[2]),
// .clk_out4(multiCLK[3]),
// .clk_out5(multiCLK[4]),
// .clk_out6(multiCLK[5]),
.locked(),
.clk_in1(clkin)
);
reg [3:0] phaseCnt;
(* keep="true" *) reg [15:0] phaseClk;
generate
for( genvar i = 0; i < 16; i = i+1 ) begin
BUFG BUFG_inst (
.O(multiCLK[i]), // 1-bit output: Clock output
.I(phaseClk[i]) // 1-bit input: Clock input
);
end
endgenerate
always @( posedge clk320M )begin
phaseCnt <= phaseCnt + 4'd1;
if( phaseCnt == 0 ) begin
phaseClk[0] <= 1;
phaseClk[8] <= 0;
end
if( phaseCnt == 1 ) begin
phaseClk[1] <= 1;
phaseClk[9] <= 0;
end
if( phaseCnt == 2 ) begin
phaseClk[2] <= 1;
phaseClk[10] <= 0;
end
if( phaseCnt == 3 ) begin
phaseClk[3] <= 1;
phaseClk[11] <= 0;
end
if( phaseCnt == 4 ) begin
phaseClk[4] <= 1;
phaseClk[12] <= 0;
end
if( phaseCnt == 5 ) begin
phaseClk[5] <= 1;
phaseClk[13] <= 0;
end
if( phaseCnt == 6 ) begin
phaseClk[6] <= 1;
phaseClk[14] <= 0;
end
if( phaseCnt == 7 ) begin
phaseClk[7] <= 1;
phaseClk[15] <= 0;
end
if( phaseCnt == 8 ) begin
phaseClk[8] <= 1;
phaseClk[0] <= 0;
end
if( phaseCnt == 9 ) begin
phaseClk[9] <= 1;
phaseClk[1] <= 0;
end
if( phaseCnt == 10 ) begin
phaseClk[10] <= 1;
phaseClk[2] <= 0;
end
if( phaseCnt == 11 ) begin
phaseClk[11] <= 1;
phaseClk[3] <= 0;
end
if( phaseCnt == 12 ) begin
phaseClk[12] <= 1;
phaseClk[4] <= 0;
end
if( phaseCnt == 13 ) begin
phaseClk[13] <= 1;
phaseClk[5] <= 0;
end
if( phaseCnt == 14 ) begin
phaseClk[14] <= 1;
phaseClk[6] <= 0;
end
if( phaseCnt == 15 ) begin
phaseClk[15] <= 1;
phaseClk[7] <= 0;
end
end
reg [1:0] div4phCnt;
(* keep="true" *) reg [3:0] div4phClk;
generate
for( genvar i = 0; i < 4; i = i+1 ) begin
BUFG BUFG_div4_inst (
.O(div4CLK[i]), // 1-bit output: Clock output
.I(div4phClk[i]) // 1-bit input: Clock input
);
end
endgenerate
always @( posedge clk320M )begin
div4phCnt <= div4phCnt + 2'd1;
if( div4phCnt == 0 ) begin
div4phClk[0] <= 1;
div4phClk[2] <= 0;
end
if( div4phCnt == 1 ) begin
div4phClk[1] <= 1;
div4phClk[3] <= 0;
end
if( div4phCnt == 2 ) begin
div4phClk[2] <= 1;
div4phClk[0] <= 0;
end
if( div4phCnt == 3 ) begin
div4phClk[3] <= 1;
div4phClk[1] <= 0;
end
end
proc_sys_reset_0 i_proc_sys_reset(
.slowest_sync_clk(multiCLK[0]),
.ext_reset_in(resetIn),
.aux_reset_in(1'b0),
.mb_debug_sys_rst(1'b0),
.dcm_locked(1'b1),
.mb_reset(),
.bus_struct_reset(),
.peripheral_reset(reset),
.interconnect_aresetn(),
.peripheral_aresetn()
);
//assign reset = resetIn;
wire iqspi_sck;
wire [3:0] iqspi_mosi;
wire [3:0] iqspi_miso;
wire iqspi_isDirIn;
wire iqspi_cs;
wire oqspi_sck;
wire [3:0] oqspi_mosi;
wire [3:0] oqspi_miso;
wire oqspi_isDirIn;
wire oqspi_cs;
wire aqspi_sck;
wire [3:0] aqspi_mosi;
wire [3:0] aqspi_miso;
wire aqspi_isDirIn;
wire aqspi_cs;
wire vqspi_sck;
wire [3:0] vqspi_mosi;
wire [3:0] vqspi_miso;
wire vqspi_isDirIn;
wire vqspi_cs;
wire bqspi_sck;
wire [3:0] bqspi_mosi;
wire [3:0] bqspi_miso;
wire bqspi_isDirIn;
wire bqspi_cs;
//wire qspi_sck;
wire [3:0] qspi_mosi;
wire [3:0] qspi_miso;
wire [3:0] isDirIn;
//wire qspi_cs;
wire [2:0] spi_sel;
wire isSoftReset;
wire [7:0] led;
ShinTop i_ShinTop(
.clock(multiCLK[0]),
.reset(reset | isSoftReset),
.io_dDatIn(dDatIn),
.io_dDatOut(dDatOut),
.io_uDatIn(uDatIn),
.io_uDatOut(uDatOut),
.io_multiCLK_0(multiCLK[0]),
.io_multiCLK_1(multiCLK[1]),
.io_multiCLK_2(multiCLK[2]),
.io_multiCLK_3(multiCLK[3]),
.io_multiCLK_4(multiCLK[4]),
.io_multiCLK_5(multiCLK[5]),
.io_multiCLK_6(multiCLK[6]),
.io_multiCLK_7(multiCLK[7]),
.io_multiCLK_8(multiCLK[8]),
.io_multiCLK_9(multiCLK[9]),
.io_multiCLK_10(multiCLK[10]),
.io_multiCLK_11(multiCLK[11]),
.io_multiCLK_12(multiCLK[12]),
.io_multiCLK_13(multiCLK[13]),
.io_multiCLK_14(multiCLK[14]),
.io_multiCLK_15(multiCLK[15]),
.io_multiCLKDiv4_0(div4CLK[0]),
.io_multiCLKDiv4_1(div4CLK[1]),
.io_multiCLKDiv4_2(div4CLK[2]),
.io_multiCLKDiv4_3(div4CLK[3]),
.io_iqspi_sck(iqspi_sck),
.io_iqspi_mosi(iqspi_mosi),
.io_iqspi_miso(iqspi_miso),
.io_iqspi_isDirIn(iqspi_isDirIn),
.io_iqspi_csn(iqspi_cs),
.io_aqspi_sck(aqspi_sck),
.io_aqspi_mosi(aqspi_mosi),
.io_aqspi_miso(aqspi_miso),
.io_aqspi_isDirIn(aqspi_isDirIn),
.io_aqspi_csn(aqspi_cs),
.io_vqspi_sck(vqspi_sck),
.io_vqspi_mosi(vqspi_mosi),
.io_vqspi_miso(vqspi_miso),
.io_vqspi_isDirIn(vqspi_isDirIn),
.io_vqspi_csn(vqspi_cs),
.io_bqspi_sck(bqspi_sck),
.io_bqspi_mosi(bqspi_mosi),
.io_bqspi_miso(bqspi_miso),
.io_bqspi_isDirIn(bqspi_isDirIn),
.io_bqspi_csn(bqspi_cs),
.io_ospi_sck(spi_sck),
.io_ospi_mosi(spi_mosi),
.io_ospi_miso(spi_miso),
.io_ospi_csn(spi_csn),
.io_oqspi_sck(oqspi_sck),
.io_oqspi_mosi(oqspi_mosi),
.io_oqspi_miso(oqspi_miso),
.io_oqspi_isDirIn(oqspi_isDirIn),
.io_oqspi_csn(oqspi_cs),
.io_spiSel(spi_sel),
.io_iSync_0(sync0),
.io_iSync_1(sync1),
.io_iSync_2(),
.io_iSync_3(),
.io_isSoftReset(isSoftReset),
//.io_ledTest(led),
.io_interrupt(interrupt),
.io_latchPin_0(latch0),
.io_latchPin_1(latch1),
//.io_testIO(testIO),
.io_hwSerial(48'h4c5850303031)
);
reg [2:0] spi_sel_post;
always @(posedge multiCLK[0]) begin
if (reset | isSoftReset) begin
spi_sel_post <= 3'b001;
end else if( io_qspi_csn ) begin
spi_sel_post <= spi_sel;
end
end
assign io_led = led[5:2];
assign testIO = 12'hfff;
assign iqspi_sck = (spi_sel_post == 3'b000)? io_qspi_sck : 1'b0;
assign spi_sck = (spi_sel_post == 3'b001)? io_qspi_sck : 1'b0;
assign oqspi_sck = (spi_sel_post == 3'b010)? io_qspi_sck : 1'b0;
assign aqspi_sck = (spi_sel_post == 3'b011)? io_qspi_sck : 1'b0;
assign vqspi_sck = (spi_sel_post == 3'b100)? io_qspi_sck : 1'b0;
assign bqspi_sck = (spi_sel_post == 3'b101)? io_qspi_sck : 1'b0;
assign iqspi_mosi = (spi_sel_post == 3'b000)? qspi_mosi : 4'b0;
assign spi_mosi = (spi_sel_post == 3'b001)? qspi_mosi[0] : 4'b0;
assign oqspi_mosi = (spi_sel_post == 3'b010)? qspi_mosi : 4'b0;
assign aqspi_mosi = (spi_sel_post == 3'b011)? qspi_mosi : 4'b0;
assign vqspi_mosi = (spi_sel_post == 3'b100)? qspi_mosi : 4'b0;
assign bqspi_mosi = (spi_sel_post == 3'b101)? qspi_mosi : 4'b0;
assign qspi_miso = (spi_sel_post == 3'b000)? iqspi_miso :
(spi_sel_post == 3'b001)? {2'b0, spi_miso, 1'b0} :
(spi_sel_post == 3'b010)? oqspi_miso :
(spi_sel_post == 3'b011)? aqspi_miso :
(spi_sel_post == 3'b100)? vqspi_miso : bqspi_miso;
assign iqspi_cs = (spi_sel_post == 3'b000)? io_qspi_csn : 1'b1;
assign spi_csn = (spi_sel_post == 3'b001)? io_qspi_csn : 1'b1;
assign oqspi_cs = (spi_sel_post == 3'b010)? io_qspi_csn : 1'b1;
assign aqspi_cs = (spi_sel_post == 3'b011)? io_qspi_csn : 1'b1;
assign vqspi_cs = (spi_sel_post == 3'b100)? io_qspi_csn : 1'b1;
assign bqspi_cs = (spi_sel_post == 3'b101)? io_qspi_csn : 1'b1;
assign isDirIn = (spi_sel_post == 3'b000)? {iqspi_isDirIn, iqspi_isDirIn, iqspi_isDirIn, iqspi_isDirIn} :
(spi_sel_post == 3'b001)? {2'b11, 1'b0, 1'b1} :
(spi_sel_post == 3'b010)? {oqspi_isDirIn, oqspi_isDirIn, oqspi_isDirIn, oqspi_isDirIn} :
(spi_sel_post == 3'b011)? {aqspi_isDirIn, aqspi_isDirIn, aqspi_isDirIn, aqspi_isDirIn} :
(spi_sel_post == 3'b100)? {vqspi_isDirIn, vqspi_isDirIn, vqspi_isDirIn, vqspi_isDirIn} :
{bqspi_isDirIn, bqspi_isDirIn, bqspi_isDirIn, bqspi_isDirIn};
IOBUF QSPI_D0_inst (
.O(qspi_mosi[0]), // Buffer output
.IO(io_qspi_data[0]), // Buffer inout port (connect directly to top-level port)
.I(qspi_miso[0]), // Buffer input
.T(isDirIn[0]) // 3-state enable input, high=input, low=output
);
IOBUF QSPI_D1_inst (
.O(qspi_mosi[1]), // Buffer output
.IO(io_qspi_data[1]), // Buffer inout port (connect directly to top-level port)
.I(qspi_miso[1]), // Buffer input
.T(isDirIn[1]) // 3-state enable input, high=input, low=output
);
IOBUF QSPI_D2_inst (
.O(qspi_mosi[2]), // Buffer output
.IO(io_qspi_data[2]), // Buffer inout port (connect directly to top-level port)
.I(qspi_miso[2]), // Buffer input
.T(isDirIn[2]) // 3-state enable input, high=input, low=output
);
IOBUF QSPI_D3_inst (
.O(qspi_mosi[3]), // Buffer output
.IO(io_qspi_data[3]), // Buffer inout port (connect directly to top-level port)
.I(qspi_miso[3]), // Buffer input
.T(isDirIn[3]) // 3-state enable input, high=input, low=output
);
IBUFDS i_dDatIn (
.O(dDatIn), // Buffer output
.I(dDatIn_p), // Diff_p buffer input (connect directly to top-level port)
.IB(dDatIn_n) // Diff_n buffer input (connect directly to top-level port)
);
IBUFDS i_uDatIn (
.O(uDatIn), // Buffer output
.I(uDatIn_p), // Diff_p buffer input (connect directly to top-level port)
.IB(uDatIn_n) // Diff_n buffer input (connect directly to top-level port)
);
OBUFDS i_dDatOut (
.O(dDatOut_p), // Diff_p output (connect directly to top-level port)
.OB(dDatOut_n), // Diff_n output (connect directly to top-level port)
.I(dDatOut) // Buffer input
);
OBUFDS i_uDatOut (
.O(uDatOut_p), // Diff_p output (connect directly to top-level port)
.OB(uDatOut_n), // Diff_n output (connect directly to top-level port)
.I(uDatOut) // Buffer input
);
endmodule

View File

@@ -0,0 +1,103 @@
set_property -dict {PACKAGE_PIN H4 IOSTANDARD LVCMOS33} [get_ports clkin]
#CPUPC8
set_property -dict {PACKAGE_PIN P1 IOSTANDARD LVCMOS33} [get_ports resetIn]
#set_property -dict {PACKAGE_PIN P20 IOSTANDARD LVCMOS33} [get_ports mosi]
#set_property -dict {PACKAGE_PIN T20 IOSTANDARD LVCMOS33} [get_ports miso]
#set_property -dict {PACKAGE_PIN W21 IOSTANDARD LVCMOS33} [get_ports sck]
#set_property -dict {PACKAGE_PIN W22 IOSTANDARD LVCMOS33} [get_ports csn]
set_property -dict {PACKAGE_PIN F16 IOSTANDARD TMDS_33} [get_ports dDatOut_p]
set_property -dict {PACKAGE_PIN E16 IOSTANDARD TMDS_33} [get_ports dDatIn_p]
set_property -dict {PACKAGE_PIN E13 IOSTANDARD TMDS_33} [get_ports uDatOut_p]
set_property -dict {PACKAGE_PIN F13 IOSTANDARD TMDS_33} [get_ports uDatIn_p]
set_property -dict {IOSTANDARD TMDS_33} [get_ports dDatOut_n]
set_property -dict {IOSTANDARD TMDS_33} [get_ports dDatIn_n]
set_property -dict {IOSTANDARD TMDS_33} [get_ports uDatOut_n]
set_property -dict {IOSTANDARD TMDS_33} [get_ports uDatIn_n]
#set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports dDatOut]
#set_property -dict {PACKAGE_PIN E16 IOSTANDARD LVCMOS33} [get_ports dDatIn]
#set_property -dict {PACKAGE_PIN E13 IOSTANDARD LVCMOS33} [get_ports uDatOut]
#set_property -dict {PACKAGE_PIN F13 IOSTANDARD LVCMOS33} [get_ports uDatIn]
#set_property -dict {PACKAGE_PIN U15 IOSTANDARD LVCMOS33} [get_ports sync0]
set_property -dict {PACKAGE_PIN G1 IOSTANDARD LVCMOS33} [get_ports sync0]
set_property -dict {PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports sync1]
set_property -dict {PACKAGE_PIN Y11 IOSTANDARD LVCMOS33} [get_ports latch0]
set_property -dict {PACKAGE_PIN Y12 IOSTANDARD LVCMOS33} [get_ports latch1]
#CPU PC7
set_property -dict {PACKAGE_PIN P5 IOSTANDARD LVCMOS33} [get_ports interrupt]
#set_property -dict {PACKAGE_PIN V22 IOSTANDARD LVCMOS33} [get_ports io_iqspi_sck]
#set_property -dict {PACKAGE_PIN T21 IOSTANDARD LVCMOS33} [get_ports {io_iqspi_data[0]}]
#set_property -dict {PACKAGE_PIN U21 IOSTANDARD LVCMOS33} [get_ports {io_iqspi_data[1]}]
#set_property -dict {PACKAGE_PIN P19 IOSTANDARD LVCMOS33} [get_ports {io_iqspi_data[2]}]
#set_property -dict {PACKAGE_PIN R19 IOSTANDARD LVCMOS33} [get_ports {io_iqspi_data[3]}]
#set_property -dict {PACKAGE_PIN U22 IOSTANDARD LVCMOS33} [get_ports io_iqspi_csn]
set_property -dict {PACKAGE_PIN V22 IOSTANDARD LVCMOS33} [get_ports io_qspi_sck]
set_property -dict {PACKAGE_PIN T21 IOSTANDARD LVCMOS33} [get_ports {io_qspi_data[0]}]
set_property -dict {PACKAGE_PIN U21 IOSTANDARD LVCMOS33} [get_ports {io_qspi_data[1]}]
set_property -dict {PACKAGE_PIN P19 IOSTANDARD LVCMOS33} [get_ports {io_qspi_data[2]}]
set_property -dict {PACKAGE_PIN R19 IOSTANDARD LVCMOS33} [get_ports {io_qspi_data[3]}]
set_property -dict {PACKAGE_PIN U22 IOSTANDARD LVCMOS33} [get_ports io_qspi_csn]
set_property -dict {PACKAGE_PIN P2 IOSTANDARD LVCMOS33} [get_ports {io_led[0]}]
set_property -dict {PACKAGE_PIN N2 IOSTANDARD LVCMOS33} [get_ports {io_led[1]}]
set_property -dict {PACKAGE_PIN M6 IOSTANDARD LVCMOS33} [get_ports {io_led[2]}]
set_property -dict {PACKAGE_PIN M5 IOSTANDARD LVCMOS33} [get_ports {io_led[3]}]
set_property -dict {PACKAGE_PIN E19 IOSTANDARD LVCMOS33} [get_ports {testIO[0]}]
set_property -dict {PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports {testIO[1]}]
set_property -dict {PACKAGE_PIN D20 IOSTANDARD LVCMOS33} [get_ports {testIO[2]}]
set_property -dict {PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {testIO[3]}]
set_property -dict {PACKAGE_PIN D17 IOSTANDARD LVCMOS33} [get_ports {testIO[4]}]
set_property -dict {PACKAGE_PIN C17 IOSTANDARD LVCMOS33} [get_ports {testIO[5]}]
set_property -dict {PACKAGE_PIN B15 IOSTANDARD LVCMOS33} [get_ports {testIO[6]}]
set_property -dict {PACKAGE_PIN B16 IOSTANDARD LVCMOS33} [get_ports {testIO[7]}]
set_property -dict {PACKAGE_PIN A15 IOSTANDARD LVCMOS33} [get_ports {testIO[8]}]
set_property -dict {PACKAGE_PIN A16 IOSTANDARD LVCMOS33} [get_ports {testIO[9]}]
set_property -dict {PACKAGE_PIN D14 IOSTANDARD LVCMOS33} [get_ports {testIO[10]}]
set_property -dict {PACKAGE_PIN D15 IOSTANDARD LVCMOS33} [get_ports {testIO[11]}]
#set_property -dict {PACKAGE_PIN A13 IOSTANDARD LVCMOS33} [get_ports {testIO[12]}]
#set_property -dict {PACKAGE_PIN A14 IOSTANDARD LVCMOS33} [get_ports {testIO[13]}]
#set_property -dict {PACKAGE_PIN C13 IOSTANDARD LVCMOS33} [get_ports {testIO[14]}]
#set_property -dict {PACKAGE_PIN B13 IOSTANDARD LVCMOS33} [get_ports {testIO[15]}]
create_clock -period 50.000 -name multi0 -waveform {0.000 25.000} [get_nets {multiCLK[0]}]
create_clock -period 50.000 -name multi1 -waveform {3.125 28.125} [get_nets {multiCLK[1]}]
create_clock -period 50.000 -name multi2 -waveform {6.250 31.250} [get_nets {multiCLK[2]}]
create_clock -period 50.000 -name multi3 -waveform {9.375 34.375} [get_nets {multiCLK[3]}]
create_clock -period 50.000 -name multi4 -waveform {12.500 37.500} [get_nets {multiCLK[4]}]
create_clock -period 50.000 -name multi5 -waveform {15.625 40.625} [get_nets {multiCLK[5]}]
create_clock -period 50.000 -name multi6 -waveform {18.750 43.750} [get_nets {multiCLK[6]}]
create_clock -period 50.000 -name multi7 -waveform {21.875 46.875} [get_nets {multiCLK[7]}]
create_clock -period 50.000 -name multi8 -waveform {25.000 50.000} [get_nets {multiCLK[8]}]
create_clock -period 50.000 -name multi9 -waveform {28.125 53.125} [get_nets {multiCLK[9]}]
create_clock -period 50.000 -name multi10 -waveform {31.250 56.250} [get_nets {multiCLK[10]}]
create_clock -period 50.000 -name multi11 -waveform {34.375 59.375} [get_nets {multiCLK[11]}]
create_clock -period 50.000 -name multi12 -waveform {37.500 62.500} [get_nets {multiCLK[12]}]
create_clock -period 50.000 -name multi13 -waveform {40.625 65.625} [get_nets {multiCLK[13]}]
create_clock -period 50.000 -name multi14 -waveform {43.750 68.750} [get_nets {multiCLK[14]}]
create_clock -period 50.000 -name multi15 -waveform {46.875 71.875} [get_nets {multiCLK[15]}]
create_clock -period 50.000 -name qspiclk -waveform {0.000 25.000} [get_nets {i_ShinTop/aqspi_sck i_ShinTop/bqspi_sck}]
#set_clock_groups -name async -asynchronous -group [list [get_clocks -regexp .*multi.*] [get_clocks [list sys_clk [get_clocks -of_objects [get_pins i_clk_3/inst/mmcm_adv_inst/CLKOUT0]] [get_clocks -of_objects [get_pins i_clk_3/inst/mmcm_adv_inst/CLKFBOUT]]]]] -group [get_clocks qspiclk]
#set_max_delay -datapath_only -from [get_cells -hier -filter {CLOCK_NAME == qspiclk}] -to [get_cells -hier -filter {CLOCK_NAME == multi0}] 50.000
#set_max_delay -datapath_only -from [get_cells -hier -filter {CLOCK_NAME == multi0}] -to [get_cells -hier -filter {CLOCK_NAME == qspiclk}] 50.000
set_max_delay -datapath_only -from [get_clocks qspiclk] -to [get_clocks multi0] 50.000
set_max_delay -datapath_only -from [get_clocks multi0] -to [get_clocks qspiclk] 50.000

View File

@@ -165,24 +165,30 @@ class CDRInMultiSample(clkNum: Int) extends Module with RequireAsyncReset{
class CDRInAxisIO extends Bundle{ class CDRInAxisIO extends Bundle{
val axis = Decoupled(new AXIS_Bundle(8)) val axis = Decoupled(new AXIS_Bundle(8))
val decode = Flipped(new Decode_Bundle)
val syncSerDat = Input(Bool()) val syncSerDat = Input(Bool())
val flush = Input(Bool()) val flush = Input(Bool())
val isK28_0 = Output(Bool()) //0x1c
val isK28_3 = Output(Bool()) //0x7c
val isK28_4 = Output(Bool()) //0x9c
val isK28_1 = Output(Bool()) //0x3c
val isK28_2 = Output(Bool()) //0x5c
val isK28_6 = Output(Bool()) //0xdc
} }
class CDRInAxis extends Module with RequireAsyncReset{ class CDRInAxis extends Module with RequireAsyncReset{
val io: CDRInAxisIO = IO(new CDRInAxisIO) val io: CDRInAxisIO = IO(new CDRInAxisIO)
io.decode.dataIn := 0.U
def HeaderByte: Int = 4
val ETH_PRE = "h68".U(8.W) def HeaderByte: Int = 4
val ETH_SFD = "h25".U(8.W)
val STATE_IDLE = 0.U val STATE_IDLE = 0.U
val STATE_HEADER = 1.U val STATE_HEADER = 1.U
val STATE_PAYLOAD = 2.U val STATE_PAYLOAD = 2.U
val STATE_CTRL = 3.U
val stateNext = Wire(UInt(2.W)) val stateNext = Wire(UInt(2.W))
val stateCurr = RegNext( stateNext, STATE_IDLE ) val stateCurr = RegNext( stateNext, STATE_IDLE )
@@ -190,6 +196,7 @@ class CDRInAxis extends Module with RequireAsyncReset{
val bitCnt = RegInit(0.U(4.W)) val bitCnt = RegInit(0.U(4.W))
val byteCnt = RegInit(0.U((12+1).W)) val byteCnt = RegInit(0.U((12+1).W))
val decoder = Module(new b8b10Decode)
val checkSFD = RegInit( 0.U(10.W) ) val checkSFD = RegInit( 0.U(10.W) )
when( io.flush ){ when( io.flush ){
@@ -198,10 +205,10 @@ class CDRInAxis extends Module with RequireAsyncReset{
checkSFD := Cat( checkSFD(8,0), io.syncSerDat ) checkSFD := Cat( checkSFD(8,0), io.syncSerDat )
} }
io.decode.dataIn := checkSFD(9,0) decoder.io.dataIn := checkSFD(9,0)
val shiftData = io.decode.dataOut val shiftData = decoder.io.dataOut
val shiftData10Next = ShiftRegister( shiftData, 10, 0.U(8.W), true.B ) val shiftData10NextIsK28_0 = ShiftRegister( decoder.io.isK28_6, 10, false.B, true.B )
val isPreAndSfd = ( shiftData10NextIsK28_0 && decoder.io.isK28_3 )
val payloadLen = RegInit(0.U(12.W)) val payloadLen = RegInit(0.U(12.W))
when( io.flush ){ when( io.flush ){
@@ -215,17 +222,19 @@ class CDRInAxis extends Module with RequireAsyncReset{
stateNext := stateNext :=
Mux( io.flush, STATE_IDLE, Mux( io.flush, STATE_IDLE,
Mux1H(Seq( Mux1H(Seq(
(stateCurr === STATE_IDLE) -> ( Mux( shiftData10Next === ETH_PRE && shiftData === ETH_SFD , STATE_HEADER, STATE_IDLE )), //IDLE (stateCurr === STATE_IDLE) -> ( Mux( isPreAndSfd , STATE_HEADER, STATE_IDLE )), //IDLE
(stateCurr === STATE_HEADER) -> ( Mux( (byteCnt === (HeaderByte-1).U) & (bitCnt === 9.U), STATE_PAYLOAD, STATE_HEADER ) ), (stateCurr === STATE_HEADER) -> ( Mux( (byteCnt === (HeaderByte-1).U) & (bitCnt === 9.U), STATE_PAYLOAD, STATE_HEADER ) ),
(stateCurr === STATE_PAYLOAD) -> ( Mux( (byteCnt === (payloadLen + (4 - 1).U) ) & (bitCnt === 9.U), STATE_IDLE, STATE_PAYLOAD )), // PAYLOAD (stateCurr === STATE_PAYLOAD) -> ( Mux( (byteCnt === (payloadLen + (4 - 1).U) ) & (bitCnt === 9.U), STATE_CTRL, STATE_PAYLOAD )), // PAYLOAD +CRC
)) //crc (stateCurr === STATE_CTRL) -> STATE_IDLE
))
) )
when( stateCurr === STATE_IDLE & ( shiftData10Next === ETH_PRE && shiftData === ETH_SFD ) ){ //first align when( stateCurr === STATE_IDLE & isPreAndSfd ){ //first align
bitCnt := 0.U bitCnt := 0.U
} .otherwise{ } .otherwise{
when( bitCnt === 9.U ){ when( bitCnt === 9.U ){
@@ -237,7 +246,7 @@ class CDRInAxis extends Module with RequireAsyncReset{
when( io.flush ){ when( io.flush ){
byteCnt := 0.U byteCnt := 0.U
} .elsewhen( stateCurr === STATE_IDLE & ( shiftData10Next === ETH_PRE && shiftData === ETH_SFD ) ){ //first align } .elsewhen( stateCurr === STATE_IDLE & isPreAndSfd ){ //first align
byteCnt := 0.U byteCnt := 0.U
} .elsewhen( bitCnt === 9.U ){ } .elsewhen( bitCnt === 9.U ){
when( stateCurr === STATE_HEADER ){ when( stateCurr === STATE_HEADER ){
@@ -279,6 +288,15 @@ class CDRInAxis extends Module with RequireAsyncReset{
axis_tlast := (stateCurr === STATE_PAYLOAD & stateNext === STATE_IDLE) axis_tlast := (stateCurr === STATE_PAYLOAD & stateNext === STATE_IDLE)
} }
io.isK28_0 := decoder.io.isK28_0 & (stateCurr === STATE_CTRL) //0x1c
io.isK28_3 := decoder.io.isK28_3 & (stateCurr === STATE_CTRL) //0x7c
io.isK28_4 := decoder.io.isK28_4 & (stateCurr === STATE_CTRL) //0x9c
io.isK28_1 := decoder.io.isK28_1 & (stateCurr === STATE_CTRL) //0x3c
io.isK28_2 := decoder.io.isK28_2 & (stateCurr === STATE_CTRL) //0x5c
io.isK28_6 := decoder.io.isK28_6 & (stateCurr === STATE_CTRL) //0xdc
} }
@@ -381,4 +399,5 @@ class CDRInOriSample extends Module with RequireAsyncReset{
io.syncSerDat := asyncSerDat io.syncSerDat := asyncSerDat
} }

View File

@@ -15,9 +15,8 @@ class AXIS_Bundle(dw: Int) extends Bundle{
//work in 100MHZ //work in 100MHZ
class CDROutIO extends Bundle{ class CDROutIO extends Bundle{
val axis = Flipped(Decoupled(new AXIS_Bundle(8))) val axis = Flipped(Decoupled(new AXIS_Bundle(8)))
val encode = Flipped(new Encode_Bundle)
val serDat = Output(Bool()) val serDat = Output(Bool())
val ctrlWord = Input(UInt(8.W))
val flush = Input(Bool()) val flush = Input(Bool())
@@ -34,9 +33,10 @@ class CDROut extends Module with RequireAsyncReset{
def STATE_IDLE = 0.U def STATE_IDLE = 0.U
def STATE_PREAMBLE = 1.U def STATE_PREAMBLE = 1.U
def STATE_PAYLOAD = 2.U def STATE_PAYLOAD = 2.U
def STATE_CTRL = 3.U
val ETH_PRE = "h68".U(8.W) val ETH_PRE = "h1c".U(8.W) //K28_0
val ETH_SFD = "h25".U(8.W) val ETH_SFD = "h7c".U(8.W) //K28_3
val stateNext = Wire(UInt(2.W)) val stateNext = Wire(UInt(2.W))
val stateCurr = RegNext( stateNext, 0.U ) val stateCurr = RegNext( stateNext, 0.U )
@@ -45,16 +45,21 @@ class CDROut extends Module with RequireAsyncReset{
val bitCnt = RegInit(0.U(4.W)) val bitCnt = RegInit(0.U(4.W))
val byteCnt = RegInit(0.U(3.W)) //payload dont need to count val byteCnt = RegInit(0.U(3.W)) //payload dont need to count
val encoder = Module(new b8b10Encode)
val shiftData = RegInit(0.U(10.W)) val shiftData = RegInit(0.U(10.W))
io.encode.isEnable := false.B //组合逻辑 encoder.io.isEnable := false.B //组合逻辑
io.encode.dataIn := 0.U //组合逻辑 encoder.io.isCtrl := false.B //组合逻辑
encoder.io.dataIn := 0.U //组合逻辑
stateNext := stateNext :=
Mux( io.flush, STATE_IDLE, Mux( io.flush, STATE_IDLE,
Mux1H(Seq( Mux1H(Seq(
(stateCurr === STATE_IDLE) -> ( Mux( io.axis.valid, STATE_PREAMBLE, STATE_IDLE )), (stateCurr === STATE_IDLE) -> ( Mux( io.axis.valid, STATE_PREAMBLE, STATE_IDLE )),
(stateCurr === STATE_PREAMBLE) -> ( Mux( (byteCnt === (PRE_NUM-1).U) & (bitCnt === 9.U), Mux( io.axis.valid, STATE_PAYLOAD, STATE_IDLE), STATE_PREAMBLE )), (stateCurr === STATE_PREAMBLE) -> ( Mux( (byteCnt === (PRE_NUM-1).U) & (bitCnt === 9.U), Mux( io.axis.valid, STATE_PAYLOAD, STATE_IDLE), STATE_PREAMBLE )),
(stateCurr === STATE_PAYLOAD) -> ( Mux( (io.axis.fire & io.axis.bits.tlast) | (~io.axis.valid & io.axis.ready), STATE_IDLE, STATE_PAYLOAD ) ), (stateCurr === STATE_PAYLOAD) -> ( Mux( (io.axis.fire & io.axis.bits.tlast) | (~io.axis.valid & io.axis.ready), STATE_CTRL, STATE_PAYLOAD ) ),
(stateCurr === STATE_CTRL) -> STATE_IDLE,
)) ))
) )
io.serDat := shiftData.extract(9) io.serDat := shiftData.extract(9)
@@ -73,24 +78,32 @@ class CDROut extends Module with RequireAsyncReset{
when( io.flush ){ when( io.flush ){
shiftData := 0.U shiftData := 0.U
} .elsewhen( stateCurr === STATE_IDLE & stateNext === STATE_PREAMBLE){ //PRE } .elsewhen( stateCurr === STATE_IDLE & stateNext === STATE_PREAMBLE){ //PRE
shiftData := io.encode.dataOut shiftData := encoder.io.dataOut
io.encode.dataIn := ETH_PRE //组合逻辑 encoder.io.isEnable := true.B //组合逻辑
io.encode.isEnable := true.B //组合逻辑 encoder.io.isCtrl := true.B
encoder.io.dataIn := ETH_PRE //组合逻辑
} .otherwise{ } .otherwise{
when( bitCnt =/= 9.U ){ when( bitCnt =/= 9.U ){
shiftData := shiftData << 1 shiftData := shiftData << 1
} .otherwise{ //bitCnt === 9.U } .otherwise{ //bitCnt === 9.U
when( stateCurr === STATE_PREAMBLE ){ when( stateCurr === STATE_PREAMBLE ){
shiftData := io.encode.dataOut shiftData := encoder.io.dataOut
io.encode.dataIn := MuxCase( ETH_PRE, Array( encoder.io.isEnable := true.B
encoder.io.isCtrl := byteCnt =/= (PRE_NUM-1).U //组合逻辑
encoder.io.dataIn := MuxCase( ETH_PRE, Array(
( byteCnt === (PRE_NUM-2).U ) -> ETH_SFD, ( byteCnt === (PRE_NUM-2).U ) -> ETH_SFD,
( byteCnt === (PRE_NUM-1).U ) -> io.axis.bits.tdata, ( byteCnt === (PRE_NUM-1).U ) -> io.axis.bits.tdata,
)) //组合逻辑 )) //组合逻辑
io.encode.isEnable := true.B //组合逻辑
} .elsewhen( stateCurr === STATE_PAYLOAD ){ } .elsewhen( stateCurr === STATE_PAYLOAD ){
io.encode.dataIn := io.axis.bits.tdata //组合逻辑 shiftData := encoder.io.dataOut
shiftData := io.encode.dataOut encoder.io.isEnable := true.B //组合逻辑
io.encode.isEnable := true.B //组合逻辑 encoder.io.isCtrl := false.B //组合逻辑
encoder.io.dataIn := io.axis.bits.tdata //组合逻辑
} .elsewhen( stateCurr === STATE_CTRL ){
shiftData := encoder.io.dataOut
encoder.io.isEnable := true.B //组合逻辑
encoder.io.isCtrl := true.B //组合逻辑
encoder.io.dataIn := io.ctrlWord //组合逻辑
} }
} }
} }

View File

@@ -45,7 +45,6 @@ class CommonRegisterBundle extends Bundle{
val uniCode = UInt(64.W) val uniCode = UInt(64.W)
val dwupEx = Bool() val dwupEx = Bool()
val b8b4Sel = Bool()
val cdrParam = UInt(8.W) val cdrParam = UInt(8.W)
@@ -115,6 +114,8 @@ class MasterRegisterBundle extends Bundle{
val isRecCRCErr = UInt(4.W) val isRecCRCErr = UInt(4.W)
val rplTimeStampTx = UInt(16.W) val rplTimeStampTx = UInt(16.W)
val timeStampOffset = UInt(64.W) val timeStampOffset = UInt(64.W)
val ctrlWord = UInt(8.W)
} }
@@ -285,7 +286,6 @@ abstract class InterfaceBase extends Module with RequireAsyncReset{
Seq( Seq(
(addr === "h4a".U ) -> cReg.dwupEx, (addr === "h4a".U ) -> cReg.dwupEx,
(addr === "h4c".U ) -> cReg.b8b4Sel,
(addr === "h4e".U ) -> cReg.cdrParam, (addr === "h4e".U ) -> cReg.cdrParam,
(addr === "h70".U ) -> cReg.intEnable(7,0), (addr === "h70".U ) -> cReg.intEnable(7,0),
@@ -521,6 +521,9 @@ abstract class InterfaceBase extends Module with RequireAsyncReset{
( 0 until 8 ).map{ i => ( 0 until 8 ).map{ i =>
( addr === ("h540".U(16.W) + i.U) ) -> cReg.event.lvdsSMTimeStampDeq( 8*i+7, 8*i+0 ) ( addr === ("h540".U(16.W) + i.U) ) -> cReg.event.lvdsSMTimeStampDeq( 8*i+7, 8*i+0 )
} ++ } ++
Seq(
(addr === "h600".U(16.W)) -> mReg.ctrlWord,
) ++
Seq() Seq()
) )
@@ -625,6 +628,8 @@ trait InterfaceMCUop{ this: InterfaceBase =>
mReg.txSM := RegEnable( dataw(2,1), 0.U(2.W), isEnW & addrw === "h20".U ) mReg.txSM := RegEnable( dataw(2,1), 0.U(2.W), isEnW & addrw === "h20".U )
mReg.rxSM := RegEnable( dataw(4,3), 0.U(2.W), isEnW & addrw === "h20".U ) mReg.rxSM := RegEnable( dataw(4,3), 0.U(2.W), isEnW & addrw === "h20".U )
mReg.ctrlWord := RegEnable( dataw(7,0), "h1c".U(8.W), isEnW & addrw === "h600".U )
val mReg_isRecCRCErr = RegInit(0.U(4.W)) val mReg_isRecCRCErr = RegInit(0.U(4.W))
mReg.isRecCRCErr := mReg_isRecCRCErr mReg.isRecCRCErr := mReg_isRecCRCErr
when( isEnW & addrw === "h22".U(16.W) ){ when( isEnW & addrw === "h22".U(16.W) ){
@@ -1049,9 +1054,6 @@ trait InterfaceSystem{ this: InterfaceBase =>
val dwupExTemp = RegEnable(dataw, 0.U(8.W), isEnW & addrw === "h4a".U ) val dwupExTemp = RegEnable(dataw, 0.U(8.W), isEnW & addrw === "h4a".U )
cReg.dwupEx := RegEnable(dwupExTemp, 0.U(8.W), isEnW & addrw === "h4b".U & dataw === "h58".U ) cReg.dwupEx := RegEnable(dwupExTemp, 0.U(8.W), isEnW & addrw === "h4b".U & dataw === "h58".U )
val b8b4SelTemp = RegEnable(dataw, 0.U(8.W), isEnW & addrw === "h4c".U )
cReg.b8b4Sel := RegEnable(b8b4SelTemp, 0.U(8.W), isEnW & addrw === "h4d".U & dataw === "h59".U )
val cdrParamTemp = RegEnable(dataw, 0.U(8.W), isEnW & addrw === "h4e".U ) val cdrParamTemp = RegEnable(dataw, 0.U(8.W), isEnW & addrw === "h4e".U )
cReg.cdrParam := RegEnable(cdrParamTemp, 0.U(8.W), isEnW & addrw === "h4f".U & dataw === "h60".U ) cReg.cdrParam := RegEnable(cdrParamTemp, 0.U(8.W), isEnW & addrw === "h4f".U & dataw === "h60".U )

View File

@@ -54,16 +54,6 @@ abstract class MstSlvSwitchBase extends Module with RequireAsyncReset{
val slaveParser = Module(new SlaveParser ) val slaveParser = Module(new SlaveParser )
val masterParser = Module(new MasterParser) val masterParser = Module(new MasterParser)
val b4b5DownEncoder = Module(new b4b5DualEncode)
val b4b5DownDecoder = Module(new b4b5DualDecode)
val b4b5UpEncoder = Module(new b4b5DualEncode)
val b4b5UpDecoder = Module(new b4b5DualDecode)
val b8b10DownEncoder = Module(new b8b10Encode)
val b8b10DownDecoder = Module(new b8b10Decode)
val b8b10UpEncoder = Module(new b8b10Encode)
val b8b10UpDecoder = Module(new b8b10Decode)
val interface = Module(new Interface) val interface = Module(new Interface)
val downInSerDat = Wire(Bool()) val downInSerDat = Wire(Bool())
@@ -211,9 +201,6 @@ abstract class MstSlvSwitchBase extends Module with RequireAsyncReset{
} }
} }
//default //default
{ {
smUnit(0).io.sram_w := 0.U.asTypeOf(new SRAM2kWRIO) smUnit(0).io.sram_w := 0.U.asTypeOf(new SRAM2kWRIO)
@@ -255,6 +242,9 @@ abstract class MstSlvSwitchBase extends Module with RequireAsyncReset{
upCDROut.io.axis.valid := false.B upCDROut.io.axis.valid := false.B
upCDROut.io.axis.bits := 0.U.asTypeOf(new AXIS_Bundle(8)) upCDROut.io.axis.bits := 0.U.asTypeOf(new AXIS_Bundle(8))
downCDROut.io.ctrlWord := 0.U
upCDROut.io.ctrlWord := 0.U
interface.io.mstDeltaTime := 0.U interface.io.mstDeltaTime := 0.U
interface.io.slvDeltaTime := 0.U interface.io.slvDeltaTime := 0.U
@@ -277,6 +267,20 @@ abstract class MstSlvSwitchBase extends Module with RequireAsyncReset{
interface.io.downRecStat := 0.U.asTypeOf(new Stat_IO_Bundle) interface.io.downRecStat := 0.U.asTypeOf(new Stat_IO_Bundle)
interface.io.upRecStat := 0.U.asTypeOf(new Stat_IO_Bundle) interface.io.upRecStat := 0.U.asTypeOf(new Stat_IO_Bundle)
slaveParser.io.downCtrlWordIsK28_0 := false.B
slaveParser.io.downCtrlWordIsK28_3 := false.B
slaveParser.io.downCtrlWordIsK28_4 := false.B
slaveParser.io.downCtrlWordIsK28_1 := false.B
slaveParser.io.downCtrlWordIsK28_2 := false.B
slaveParser.io.downCtrlWordIsK28_6 := false.B
slaveParser.io.upCtrlWordIsK28_0 := false.B
slaveParser.io.upCtrlWordIsK28_3 := false.B
slaveParser.io.upCtrlWordIsK28_4 := false.B
slaveParser.io.upCtrlWordIsK28_1 := false.B
slaveParser.io.upCtrlWordIsK28_2 := false.B
slaveParser.io.upCtrlWordIsK28_6 := false.B
} }
} }
@@ -335,6 +339,9 @@ trait MstSlvSwitchMaster{ this: MstSlvSwitchBase =>
interface.io.downRecStat := 0.U.asTypeOf(new Stat_IO_Bundle) interface.io.downRecStat := 0.U.asTypeOf(new Stat_IO_Bundle)
interface.io.upRecStat := masterParser.io.upRecStat interface.io.upRecStat := masterParser.io.upRecStat
downCDROut.io.ctrlWord := interface.io.mReg.ctrlWord
upCDROut.io.ctrlWord := interface.io.mReg.ctrlWord
} }
masterParser.io.req := interface.io.txReq.valid masterParser.io.req := interface.io.txReq.valid
@@ -409,14 +416,47 @@ trait MstSlvSwitchSlave{ this: MstSlvSwitchBase =>
interface.io.downRecStat := slaveParser.io.downRecStat interface.io.downRecStat := slaveParser.io.downRecStat
interface.io.upRecStat := slaveParser.io.upRecStat interface.io.upRecStat := slaveParser.io.upRecStat
downCDROut.io.ctrlWord := slaveParser.io.downCtrlWordRelay
upCDROut.io.ctrlWord := slaveParser.io.upCtrlWordRelay
slaveParser.io.downCtrlWordIsK28_0 := downCDRInAxis.io.isK28_0
slaveParser.io.downCtrlWordIsK28_3 := downCDRInAxis.io.isK28_3
slaveParser.io.downCtrlWordIsK28_4 := downCDRInAxis.io.isK28_4
slaveParser.io.downCtrlWordIsK28_1 := downCDRInAxis.io.isK28_1
slaveParser.io.downCtrlWordIsK28_2 := downCDRInAxis.io.isK28_2
slaveParser.io.downCtrlWordIsK28_6 := downCDRInAxis.io.isK28_6
slaveParser.io.upCtrlWordIsK28_0 := upCDRInAxis.io.isK28_0
slaveParser.io.upCtrlWordIsK28_3 := upCDRInAxis.io.isK28_3
slaveParser.io.upCtrlWordIsK28_4 := upCDRInAxis.io.isK28_4
slaveParser.io.upCtrlWordIsK28_1 := upCDRInAxis.io.isK28_1
slaveParser.io.upCtrlWordIsK28_2 := upCDRInAxis.io.isK28_2
slaveParser.io.upCtrlWordIsK28_6 := upCDRInAxis.io.isK28_6
} }
slaveParser.io.intHWClr(0) := interface.io.intHWTrig(0) & interface.io.intHWClr(0) val intHWClr = for( _ <- 0 until 2) yield Wire(Bool())
slaveParser.io.intHWClr(1) := interface.io.intHWTrig(1) & interface.io.intHWClr(1) val intHWClrCMDRev = for( _ <- 0 until 2) yield RegInit(false.B)
downCDRInAxis.io.flush := RegNext( interface.io.intHWTrig(0) & interface.io.intHWClr(0), false.B )
upCDRInAxis.io.flush := RegNext( interface.io.intHWTrig(1) & interface.io.intHWClr(1), false.B ) for( i <- 0 until 2 ){
downCDROut.io.flush := RegNext( interface.io.intHWTrig(0) & interface.io.intHWClr(0), false.B ) when( interface.io.intHWTrig(i) & interface.io.intHWClr(i) ){
upCDROut.io.flush := RegNext( interface.io.intHWTrig(1) & interface.io.intHWClr(1), false.B ) intHWClrCMDRev(i) := true.B
} .elsewhen( upCDRInAxis.io.isK28_0 ){
intHWClrCMDRev(i) := false.B
}
intHWClr(i) := intHWClrCMDRev(i) & upCDRInAxis.io.isK28_0
}
slaveParser.io.intHWClr(0) := intHWClr(0)
slaveParser.io.intHWClr(1) := intHWClr(1)
downCDRInAxis.io.flush := RegNext( intHWClr(0), false.B )
upCDRInAxis.io.flush := RegNext( intHWClr(1), false.B )
downCDROut.io.flush := RegNext( intHWClr(0), false.B )
upCDROut.io.flush := RegNext( intHWClr(1), false.B )
interface.io.lvds <> slaveParser.io.lvds interface.io.lvds <> slaveParser.io.lvds
@@ -573,36 +613,6 @@ trait MstSlvSwitchDataPath{ this: MstSlvSwitchBase =>
} }
} }
trait MstSlvSwitchB8B4{ this: MstSlvSwitchBase =>
val isUsing8b10b = ~interface.io.cReg.b8b4Sel.extract(0)
when( isUsing8b10b ){
b8b10DownEncoder.io <> downCDROut.io.encode
b8b10DownDecoder.io <> downCDRInAxis.io.decode
b8b10UpEncoder.io <> upCDROut.io.encode
b8b10UpDecoder.io <> upCDRInAxis.io.decode
b4b5DownEncoder.io.isEnable := false.B
b4b5DownEncoder.io.dataIn := 0.U
b4b5DownDecoder.io.dataIn := 0.U
b4b5UpEncoder.io.isEnable := false.B
b4b5UpEncoder.io.dataIn := 0.U
b4b5UpDecoder.io.dataIn := 0.U
} .otherwise{
b4b5DownEncoder.io <> downCDROut.io.encode
b4b5DownDecoder.io <> downCDRInAxis.io.decode
b4b5UpEncoder.io <> upCDROut.io.encode
b4b5UpDecoder.io <> upCDRInAxis.io.decode
b8b10DownEncoder.io.isEnable := false.B
b8b10DownEncoder.io.dataIn := 0.U
b8b10DownDecoder.io.dataIn := 0.U
b8b10UpEncoder.io.isEnable := false.B
b8b10UpEncoder.io.dataIn := 0.U
b8b10UpDecoder.io.dataIn := 0.U
}
}
trait MstSlvSwitchCDRIn{ this: MstSlvSwitchBase => trait MstSlvSwitchCDRIn{ this: MstSlvSwitchBase =>
val cdrSelB = interface.io.cReg.cdrParam === 1.U val cdrSelB = interface.io.cReg.cdrParam === 1.U
val cdrSelC = interface.io.cReg.cdrParam === 2.U val cdrSelC = interface.io.cReg.cdrParam === 2.U
@@ -649,7 +659,6 @@ with MstSlvSwitchMaster
with MstSlvSwitchSlave with MstSlvSwitchSlave
with MstSlvSwitchWatchDog with MstSlvSwitchWatchDog
with MstSlvSwitchDataPath with MstSlvSwitchDataPath
with MstSlvSwitchB8B4
with MstSlvSwitchCDRIn{ with MstSlvSwitchCDRIn{

View File

@@ -66,6 +66,23 @@ class SlaveParserIO extends Bundle{
val downRecStat = Output(new Stat_IO_Bundle) val downRecStat = Output(new Stat_IO_Bundle)
val upRecStat = Output(new Stat_IO_Bundle) val upRecStat = Output(new Stat_IO_Bundle)
val downCtrlWordRelay = Output( UInt(8.W) )
val upCtrlWordRelay = Output( UInt(8.W) )
val downCtrlWordIsK28_0 = Input(Bool()) //0x1c
val downCtrlWordIsK28_3 = Input(Bool()) //0x7c
val downCtrlWordIsK28_4 = Input(Bool()) //0x9c
val downCtrlWordIsK28_1 = Input(Bool()) //0x3c
val downCtrlWordIsK28_2 = Input(Bool()) //0x5c
val downCtrlWordIsK28_6 = Input(Bool()) //0xdc
val upCtrlWordIsK28_0 = Input(Bool()) //0x1c
val upCtrlWordIsK28_3 = Input(Bool()) //0x7c
val upCtrlWordIsK28_4 = Input(Bool()) //0x9c
val upCtrlWordIsK28_1 = Input(Bool()) //0x3c
val upCtrlWordIsK28_2 = Input(Bool()) //0x5c
val upCtrlWordIsK28_6 = Input(Bool()) //0xdc
} }
abstract class SlaveParserBase extends Module with RequireAsyncReset{ abstract class SlaveParserBase extends Module with RequireAsyncReset{
@@ -116,7 +133,8 @@ abstract class SlaveParserBase extends Module with RequireAsyncReset{
val localDevIndex = RegInit(0.U(14.W)); io.localDevIndex := localDevIndex //当前设备索引 val localDevIndex = RegInit(0.U(14.W)); io.localDevIndex := localDevIndex //当前设备索引
val downCtrlWordRelay = RegInit("h1c".U); io.downCtrlWordRelay := downCtrlWordRelay
val upCtrlWordRelay = RegInit("h1c".U); io.upCtrlWordRelay := upCtrlWordRelay
@@ -1020,6 +1038,44 @@ trait SlaveParserProbe{ this: SlaveParserBase =>
} }
trait SlaveParserCtrlWord{ this: SlaveParserBase =>
val downCtrlWordRelay = Output( UInt(8.W) )
val upCtrlWordRelay = Output( UInt(8.W) )
when( io.downCtrlWordIsK28_0 ){
downCtrlWordRelay := "h1c".U
} .elsewhen( io.downCtrlWordIsK28_3 ){
downCtrlWordRelay := "h7c".U
} .elsewhen( io.downCtrlWordIsK28_4 ){
downCtrlWordRelay := "h9c".U
} .elsewhen( io.downCtrlWordIsK28_1 ){
downCtrlWordRelay := "h3c".U
} .elsewhen( io.downCtrlWordIsK28_2 ){
downCtrlWordRelay := "h5c".U
} .elsewhen( io.downCtrlWordIsK28_6 ){
downCtrlWordRelay := "hdc".U
}
when( ~RegNext(isAckProbe,false.B) & isAckProbe ){
upCtrlWordRelay := downCtrlWordRelay
} .elsewhen( io.upCtrlWordIsK28_0 ) {
upCtrlWordRelay := "h1c".U
} .elsewhen( io.upCtrlWordIsK28_3 ) {
upCtrlWordRelay := "h7c".U
} .elsewhen( io.upCtrlWordIsK28_4 ) {
upCtrlWordRelay := "h9c".U
} .elsewhen( io.upCtrlWordIsK28_1 ) {
upCtrlWordRelay := "h3c".U
} .elsewhen( io.upCtrlWordIsK28_2 ) {
upCtrlWordRelay := "h5c".U
} .elsewhen( io.upCtrlWordIsK28_6 ) {
upCtrlWordRelay := "hdc".U
}
}
class SlaveParser extends SlaveParserBase class SlaveParser extends SlaveParserBase
with SlaveParserIndex with SlaveParserIndex
with SlaveParserRW with SlaveParserRW

View File

@@ -6,15 +6,32 @@ import chisel3.util._
class Encode_Bundle extends Bundle{ class Encode_Bundle extends Bundle{
val dataIn = Input(UInt(8.W)) val dataIn = Input(UInt(8.W))
val isEnable = Input(Bool()) val isEnable = Input(Bool())
val isCtrl = Input(Bool())
val dataOut = Output(UInt(10.W)) val dataOut = Output(UInt(10.W))
} }
class Decode_Bundle extends Bundle{ class Decode_Bundle extends Bundle{
val dataIn = Input(UInt(10.W)) val dataIn = Input(UInt(10.W))
val dataOut = Output(UInt(8.W)) val dataOut = Output(UInt(8.W))
val isK28_0 = Output(Bool()) //0x1c
val isK28_3 = Output(Bool()) //0x7c
val isK28_4 = Output(Bool()) //0x9c
val isK28_1 = Output(Bool()) //0x3c
val isK28_2 = Output(Bool()) //0x5c
val isK28_6 = Output(Bool()) //0xdc
} }
class b8b10Encode extends Module with RequireAsyncReset{ trait b8b10Config{ this: RawModule =>
val IS_ENABLE_K28_1 = false
val IS_ENABLE_K28_2 = false
val IS_ENABLE_K28_6 = false
}
class b8b10Encode extends Module with RequireAsyncReset with b8b10Config{
val io = IO(new Encode_Bundle) val io = IO(new Encode_Bundle)
val rdTest = IO(Output(Bool())) //测试使用 val rdTest = IO(Output(Bool())) //测试使用
@@ -51,7 +68,8 @@ class b8b10Encode extends Module with RequireAsyncReset{
(io.dataIn(4,0) === "b11001".U) -> "b100110".U(6.W), (io.dataIn(4,0) === "b11001".U) -> "b100110".U(6.W),
(io.dataIn(4,0) === "b11010".U) -> "b010110".U(6.W), (io.dataIn(4,0) === "b11010".U) -> "b010110".U(6.W),
(io.dataIn(4,0) === "b11011".U) -> Mux( ~rd, "b110110".U(6.W), "b001001".U(6.W) ), (io.dataIn(4,0) === "b11011".U) -> Mux( ~rd, "b110110".U(6.W), "b001001".U(6.W) ),
(io.dataIn(4,0) === "b11100".U) -> "b001110".U(6.W), (io.dataIn(4,0) === "b11100".U & ~io.isCtrl) -> "b001110".U(6.W),
(io.dataIn(4,0) === "b11100".U & io.isCtrl) -> Mux( ~rd, "b001111".U(6.W), "b110000".U(6.W) ),
(io.dataIn(4,0) === "b11101".U) -> Mux( ~rd, "b101110".U(6.W), "b010001".U(6.W) ), (io.dataIn(4,0) === "b11101".U) -> Mux( ~rd, "b101110".U(6.W), "b010001".U(6.W) ),
(io.dataIn(4,0) === "b11110".U) -> Mux( ~rd, "b011110".U(6.W), "b100001".U(6.W) ), (io.dataIn(4,0) === "b11110".U) -> Mux( ~rd, "b011110".U(6.W), "b100001".U(6.W) ),
(io.dataIn(4,0) === "b11111".U) -> Mux( ~rd, "b101011".U(6.W), "b010100".U(6.W) ) (io.dataIn(4,0) === "b11111".U) -> Mux( ~rd, "b101011".U(6.W), "b010100".U(6.W) )
@@ -87,20 +105,35 @@ class b8b10Encode extends Module with RequireAsyncReset{
(io.dataIn(4,0) === "b11001".U) -> rd, (io.dataIn(4,0) === "b11001".U) -> rd,
(io.dataIn(4,0) === "b11010".U) -> rd, (io.dataIn(4,0) === "b11010".U) -> rd,
(io.dataIn(4,0) === "b11011".U) -> ~rd, (io.dataIn(4,0) === "b11011".U) -> ~rd,
(io.dataIn(4,0) === "b11100".U) -> rd, (io.dataIn(4,0) === "b11100".U & ~io.isCtrl) -> rd,
(io.dataIn(4,0) === "b11100".U & io.isCtrl) -> ~rd,
(io.dataIn(4,0) === "b11101".U) -> ~rd, (io.dataIn(4,0) === "b11101".U) -> ~rd,
(io.dataIn(4,0) === "b11110".U) -> ~rd, (io.dataIn(4,0) === "b11110".U) -> ~rd,
(io.dataIn(4,0) === "b11111".U) -> ~rd, (io.dataIn(4,0) === "b11111".U) -> ~rd,
)) ))
val b3b4LookUp = Mux1H(Seq( val b3b4LookUp = Mux1H(Seq(
(io.dataIn(7,5) === "b000".U) -> Mux( ~b5b6RD, "b1011".U(4.W), "b0100".U(4.W) ), (io.dataIn(7,5) === "b000".U) -> Mux( ~b5b6RD, "b1011".U(4.W), "b0100".U(4.W) ),//控制位与否保持相同情况
(io.dataIn(7,5) === "b001".U) -> "b1001".U(4.W),
(io.dataIn(7,5) === "b010".U) -> "b0101".U(4.W), (io.dataIn(7,5) === "b001".U) -> Mux( (if(IS_ENABLE_K28_1) {~io.isCtrl} else { true.B }),
(io.dataIn(7,5) === "b011".U) -> Mux( ~b5b6RD, "b1100".U(4.W), "b0011".U(4.W) ), "b1001".U(4.W),
(io.dataIn(7,5) === "b100".U) -> Mux( ~b5b6RD, "b1101".U(4.W), "b0010".U(4.W) ), Mux( ~b5b6RD, "b0110".U(4.W), "b1001".U(4.W) ), //控制位
),
(io.dataIn(7,5) === "b010".U) -> Mux( (if(IS_ENABLE_K28_2) {~io.isCtrl} else { true.B }),
"b0101".U(4.W),
Mux( ~b5b6RD, "b1010".U(4.W), "b0101".U(4.W)), //控制位
),
(io.dataIn(7,5) === "b011".U) -> Mux( ~b5b6RD, "b1100".U(4.W), "b0011".U(4.W) ),//控制位与否保持相同情况
(io.dataIn(7,5) === "b100".U) -> Mux( ~b5b6RD, "b1101".U(4.W), "b0010".U(4.W) ),//控制位与否保持相同情况
(io.dataIn(7,5) === "b101".U) -> "b1010".U(4.W), (io.dataIn(7,5) === "b101".U) -> "b1010".U(4.W),
(io.dataIn(7,5) === "b110".U) -> "b0110".U(4.W),
(io.dataIn(7,5) === "b110".U) -> Mux( (if(IS_ENABLE_K28_6) {~io.isCtrl} else { true.B }),
"b0110".U(4.W),
Mux( ~b5b6RD, "b1001".U(4.W), "b0110".U(4.W)), //控制位
),
(io.dataIn(7,5) === "b111".U) -> MuxCase( Mux( ~b5b6RD, "b1110".U(4.W), "b0001".U(4.W) ), Array( (io.dataIn(7,5) === "b111".U) -> MuxCase( Mux( ~b5b6RD, "b1110".U(4.W), "b0001".U(4.W) ), Array(
((io.dataIn(4,0) === 17.U || io.dataIn(4,0) === 18.U || io.dataIn(4,0) === 20.U) & ~b5b6RD) -> "b0111".U(4.W), // 17, 18, 20 are special cases ((io.dataIn(4,0) === 17.U || io.dataIn(4,0) === 18.U || io.dataIn(4,0) === 20.U) & ~b5b6RD) -> "b0111".U(4.W), // 17, 18, 20 are special cases
((io.dataIn(4,0) === 11.U || io.dataIn(4,0) === 13.U || io.dataIn(4,0) === 14.U) & b5b6RD) -> "b1000".U(4.W), // 11, 13, 14 are special cases ((io.dataIn(4,0) === 11.U || io.dataIn(4,0) === 13.U || io.dataIn(4,0) === 14.U) & b5b6RD) -> "b1000".U(4.W), // 11, 13, 14 are special cases
@@ -131,10 +164,11 @@ class b8b10Encode extends Module with RequireAsyncReset{
} }
} }
class b8b10Decode extends Module with RequireAsyncReset{ class b8b10Decode extends Module with RequireAsyncReset with b8b10Config{
val io = IO(new Decode_Bundle) val io = IO(new Decode_Bundle)
@@ -189,4 +223,11 @@ class b8b10Decode extends Module with RequireAsyncReset{
io.dataOut := Cat(b3b4LookUp, b5b6LookUp) io.dataOut := Cat(b3b4LookUp, b5b6LookUp)
io.isK28_0 := (io.dataIn === "b0011110100".U) || (io.dataIn === "b1100001011".U)
io.isK28_1 := (if(IS_ENABLE_K28_1) { (io.dataIn === "b0011111001".U) || (io.dataIn === "b1100000110".U) } else { false.B })
io.isK28_2 := (if(IS_ENABLE_K28_2) { (io.dataIn === "b0011110101".U) || (io.dataIn === "b1100001010".U) } else { false.B })
io.isK28_3 := (io.dataIn === "b0011110011".U) || (io.dataIn === "b1100001100".U)
io.isK28_4 := (io.dataIn === "b0011110010".U) || (io.dataIn === "b1100001101".U)
io.isK28_6 := (if(IS_ENABLE_K28_6) { (io.dataIn === "b0011110110".U) || (io.dataIn === "b1100001001".U) } else { false.B })
} }

View File

@@ -16,8 +16,8 @@ object testShinModule extends App {
ChiselGeneratorAnnotation(() => { new ShinTop }), ChiselGeneratorAnnotation(() => { new ShinTop }),
)) ))
(new chisel3.stage.ChiselStage).execute( Array("--target-dir", "generated/SimCDR/", "-e", "verilog" ) ++ args, Seq( // (new chisel3.stage.ChiselStage).execute( Array("--target-dir", "generated/SimCDR/", "-e", "verilog" ) ++ args, Seq(
ChiselGeneratorAnnotation(() => { new SimCDR }), // ChiselGeneratorAnnotation(() => { new SimCDR }),
)) // ))
} }

71
专利交底书.md Normal file
View File

@@ -0,0 +1,71 @@
# 专利交底书
-----------------------------------------
## CDR串行采样还原模块设计
在无时钟串行采样的需求下使用16相位时钟对串行输入信号进行过采样
1. 串行输入信号分别使用16个相位时钟进行采样为防止亚稳态16个相位都是使用移位寄存器打两拍后使用
2. 对采样后的信号在各自相位时钟下再采样8次重新排序后即可获得相当于在16倍时钟下的8*16个采样点
3. 毛刺滤波为了防止潜在的采样毛刺认为连续3个采样点中2个以上为1则中间的采样点才为1.
4. 在主时钟下当CDR在解锁状态时监控中间部分的采样点当发现跳变时进入上锁状态将相位指针`arbCali`指向跳变点。
5. 每个主时钟的下的采样值为`arbCali` + 8相半个时钟周期
### 时钟频率容错
由于在硬件上不能保证发送方和接收方电路板上时钟源频率的完全一致,在长时间数据传输过程中,采样点有可能向正/负方向偏移,因此设计上需要有足够的裕量保证在最坏的频率偏差下完成最长的一次传输
6. 每16个周期有机会检查一次跳变沿的偏移当跳变沿向前或者向后移动时相应地`arbCali`加1或者减1.这样可以保证采样点不会跳变
7. 采样点足够多,可以保证完成一次完整的传输解锁前,采样指针不会移出采样范围
8. 传输数据使用8b10b编码可以增加传输数据的跳变增加跳变沿偏移时被检测到的机会
9. 传输完成后数据线长时间处于0值状态CDR解锁。下次传输上锁时采样指针重新重新初始化到采样点的中间位置
----------------------------------------------
## 内存单元队列
* 内存单元队列是一个使用FIFO形式组织的SRAM功能单元其内部包含读指针写指针提交指针。
* 写操作根据写指针进行写入指定的SRAM块
* 读操作根据读指针进行从指定SRAM块中读出
* 当传输完整完成,提交指针移动到写指针位置,当传输没有成功完成,写指针恢复到提交指针位置
----------------------------------------------------
## 从站的数据接收、转发、处理
数据包分常规包和嗅碳包,
传输分为下行方向和上行方向,系统的物理连接方式为主站-从站1- 从站2-从站3-... 从主站发出,向远离主站的远端从站方向传输的为下行方向。相反的,从远端从站向靠近主站方向传输的方向为上行方向
### 嗅探包
1. 首个嗅碳包由主站主动发出
2. 每个从站在接收到下行方向的嗅探包时
(1) 将该嗅探包下行转发给下一级从站
(2) 用嗅碳包上行回复上一级设备表示自己的存在
3. 当从站向下行方向发送嗅碳包后进行计时,若超时没有接收到上行的嗅碳包回复,则认为是最后一级从站而闭合其下行发送链路和上行接收链路
### 常规包
常规包用于完成主要系统功能,常规包传输时,包含大量不同长度的子包,每个子包含对单个或者多个从站的同步控制,数据读和(或)写等功能
#### 系统同步
由于主站和各个从站的上电(复位)时刻不一致,总线传输延迟不一致。为了将所有从站的时间同步到和主站一致,需要使用系统同步功能。主站将向所有从站下发:
1. 主站发送同步子包的本地时间
2. 主站完成一次数据传输所需要的时间
每个从站依据:
1. 上一次传输的下行发送时刻
2. 上一次传输的上行接收时刻
3. 从站本地时间
根据公式
`recoTimeStamp = io.timeStamp + mstTimeStamp - downTimeStamp + (mstDeltaTimeStamp - (upTimeStamp - downTimeStamp)) >> 1`
将本地时间校准到和主站时间一致
#### 从站读写操作
#### 物理地址和逻辑地址控制