文档内容:对一个以特定时序传送的协议,在接收端对其进行检测并进行判断,传输正确存储否则丢弃。
一、 协议信息
协议时序图如下:
相应的协议规定如下:
A:在CS低有效期间,信源在CLK上升沿发送数据,信宿在CLK的下降沿接受数据,连续的两个字节之间CLK保持低至少2个CLK周期;
B:连续两个片选信号有效之间,片选无效高电平的保持时间大于10个CLK周期;
C:CLK信号时钟频率为2.5MHz;
D:在CS低有效期间,信源连续发送数据大小为188byte;
E:第一个字节应该为0x47。
设计思路:根据上述规定设定多个条件,条件满足将串并变换之后的并行数据存入RAM,否则丢弃,这可以通过RAM上的使能信号实现。同时采用两个RAM,用以实现一个在读取的时候另外一个依然可以存储的乒乓操作。
二、 模块设计
由上述协议信息分析可得,在工程设计的时候需要进行一下模块的设计:
A:边沿检测,处理时候需要去检测CS和CLK的上下升沿来进行相应的处理;
B:串并变换模块,因为输出的是串行数据,而检测存储时都是以8bit处理的;
C:头字节的检测,需要为0x47;
D:时钟周期的检测,需要8个连续的CLK并且相邻byte要间隔至少2个CLK;
E:字节个数的检测,需要188个byte。
1、边沿检测
对输出的CS信号CLK信号的边沿进行检测,统计CLK的边沿实现对周期的统计进而在达到某一个特定值的时候进行处理,比如可用于指示1个byte传输结束等。
对边沿的检测可以通过将输入信号存储一个周期再输出取反与最新一周期的数据想与,上升沿和下降沿的检测正好相反。相应的RTL图如下所示:
从两个图中可以看到,一个是经D触发器取反和输出数据想与,一个是经D触发器和输入信号取法想与。那么通过这样的操作是如何实现对上升沿和下降沿的检测的呢。
工作流程如下:
(1)D触发器经过时钟CLK的触发,输出signal_i信号,保存了t0时刻的信号;
(2)同时signal_i信号通过与非门输出信号,保留了当前时刻t1的触发信号;
(3)对应上面两图,经过与门输出信号分两种情况,如下:
A)只有t0时刻为低,且t1时刻为高时,与门输出为高,此时为上升沿;
B)只有t0时刻为高,且t1时刻为低时,与门输出为高,此时为下降沿。
程序如下所示:
DET_POSEDGE_EN可用于选择上升沿或者下降沿,相应的对CS和CLK的边沿检测如下所示:
边沿检测模块生成了三个变量用于别的模块的处理,即变量CLK_pdge&CLK_ndge&CS_ndge
2、串并变换模块
串并变换通过对CLK周期的统计,且将串行数据放入一个并行变量中,在统计到8个CLK周期时,即一个byte传输结束的时候,将此事的串行变量输出,即为第一个byte串并变换的结果。
同时串行变量在CS为低开始时,应置0;在CLK上升沿输入一个串行数据到并行变量。
统计部分和并行存储变量如下:
从程序中可以看到每产生一个CLK的上升沿,将CNT加1;每输入一个数据DATA,就将其赋给并行变量P_Reg。赋值之后就是什么时候取得问题了,同时我们还需要生成一个并行时钟用于驱动并行数据,程序如下:
程序中可以看到,在CNT为7即产生了8个上升沿之后将并行变量P_Reg中的数据赋给Data_P用于输出,同时生成一个并行时钟CLK_P。
3、头字节检测
3、4、5这三个模块都是为了确定正在传输的帧是否有效,是否需要将该帧存入RAM中,三个模块分别生成信号,相与最终赋给RAM信号的写使能端。
头字节检测,有两个分点需要去检测,一个是第一个字节,一个是是否为0x47。所以类似第二点中,一个是周期的统计,还有一个是对串行数据串并变化看第一个byte是否为0x47。相应程序如下:
有了条件的统计,接下来就需要对条件进行判断,如下:
程序中可以看到,当两个条件都满足的时候,条件Premble_Enable_Reg置1,即头字节为0x47这个条件已经满足了。还有个问题就是我们需要将这个使能变量输出,因为它需要在下一个188byte都一直保持着有效,这样才能实现对已经存储下来的一帧数据进行持续的读取。可以通过在CS的上升沿即一帧传输结束之后,将Premble_Enable_Reg赋给最终的使能信号Premble_Enable,这样就可以实现在下一帧满足可读条件的时候,读使能一直有效
4、时钟周期检测
时钟周期的检测主要用于检测在一个byte内有均匀的8个CLK周期,且相邻的byte之间至少间隔两个CLK周期。CLK周期由条件知为2.5MHz,我们使用50MHz的系统时钟去对其进行采样。系统时钟为CLK的20倍,所以在对CLK和系统时钟CLK-Sys计数的时候可以通过对二者计数周期的对比判断是否一个byte是否通过连续的8个CLK传输的,同样可以检测相邻的byte之间是否间隔2个CLK以上。
首先对两个时钟的统计如下:
CNT在下一个byte开始时候清0,CNT_Sys在一个byte传输完毕后清0。下面就需要判断在8*20=160个CLK_Sys周期内是否含有8个CLK了,程序如下:
在规定的8个CLK时间的最后1个CLK的后半个周期(即CNT_Sys的值在149和159之间)含有8个CLK,则说明1个byte内含有均匀的8个CLK。这时置CLK_Enable_REG_8为1。我们发现,只要每个byte都是均匀传送的,CLK_Enable_REG_8就一直为1,所以只要产生错误,CLK_Enable_REG_8会置0,即产生一个下降沿。
判断两个byte之间的间隔至少大于2个CLK,可以利用CLK_Sys统计有效byte加byte间隔这个长的时间内,依然只包括8个CLK周期即可。程序如下:
上面的149加上至少两个CLK周期即40个CLK_Sys,得189个CLK_Sys周期依然只含有8个CLK,则CLK_Enable_REG_10为1.同变量CLK_Enable_REG_8一样,只要发生错误就会产生一个下降沿。
对上述的两个变量进行边沿检测,如下:
产生变量CLK_Enable_REG_8_ndge和CLK_Enable_REG_10_ndge。通过判断这两个变量是否产生,来给使能信号赋值,如下:
由程序中可得,当不产生下降沿时,使能信号保持为1,即有效。最后将这个变量再CS的上升沿即188byte传输完毕的时候赋给最终的使能信号CLK_Timing_Enable。如下:
5、字节个数检测
字节个数的检测在4部分已有的情况下,只用检测CLK的周期是否为8*188即可,所有有程序如下:
含有8*188个CLK时,使能信号Byte188_Enable置1.
6、数据存储和有效信息读取
在通过上述几个小节的处理之后得到多个使能信号,如Premble_Enable、CLK_Timing_Enable、Byte188_Enable等,这些信号共同构成了读写RAM的控制使能。
输入此部分的数据为经过串并变换之后的并行数据和并行时钟,在时钟的上升沿进行数据的存储与读取。所以,首先需要检测并行时钟信号的上升沿,如下:
存储部分,采用两个RAM做乒乓操作,当一个读时,另外一个写。如下:
通过对RAM的写使能信号以及地址线的控制实现对读写的操作,在每个CS为低周期都有一个RAM在写,而是否读取信号需要根据前面所描述的三个信号是否有效来判断,有效说明数据没有发生传输错误,是正确的可以进行读取,否则不读。
首先需要对CS为低周期进行统计:
接下来根据Cnt_CS进行RAM的读写操作。
首先复位信号有效时复位
在并行时钟CLK_P的上升沿触发操作,首先是CS第一个周期。此时对RAM1进行写操作,写使能置1;地址线增加;将输入信号Data_P赋给Din_1。RAM2根据之前的三个条件,若均满足即都为1时,对RAM2读操作,写使能置0,即读取;地址线增加,输入信号为0,将RAM2的输出Dout_2赋给模块的数据输出RAM_OUT。而当三个使能条件不满足的时候,不对RAM2进行读操作。
同样的,在CS为1的时候对上述的操作正好相反,即对RAM1读,对RAM2写。
7、同步处理
其实在进行上述的诸多操作之前首先需要进行的一个操作时同步处理,因为接口的时钟CLK是外部提供的,系统时钟CLK_Sys和CLK是不同步的,需要进行同步处理,通过D触发器实现。对CS、CLK、DATA均做下处理,如下所示:
三、 工程整体RTL图
上述诸多模块的连接如下: