打印
[VHDL]

玩转VHDL015-高速信号的比特同步

[复制链接]
982|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
ucx|  楼主 | 2018-1-29 12:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
高速信号的比特同步
数字通信中,比特同步是一切工作的开始。对于10Mbps左右或以下的低速信号,可以采用数字锁相环的方法实现比特同步,这在很多书籍中可以查到方法的介绍。那么对于几十兆、上百兆甚至到200M的高速信号(比如常用的155Mbps)如何实现比特同步呢?有人可能会想到使用Altera的ALTGX或者XILINX的RocketIO,这种方法主要是利用FPGA的引脚专用资源实现比特同步,常用在300M~3G的比特速率信号的同步。本文介绍的方法是用FGPA的通用IO资源,利用数字逻辑实现比特同步,再利用锁相环的动态相位配置恢复低抖动的线路时钟信号。在很多应用场合,线路时钟信号是不需要恢复的,只要保证能正确读取线路比特信息即可。那么,利用锁相环的动态相位配置恢复低抖动的线路时钟信号这一步是可以省略的。
利用锁相环的动态相位配置恢复低抖动的线路时钟信号,这里称作时钟平滑技术。时钟的平滑,在低速信号场合同样需要。比如接收2M(或64K)信号,当设备设为从钟模式,需要从接收的信号频率中选取一路,用作系统时钟。有时系统时钟需要倍频处理,而利用数字锁相技术恢复的时钟抖动较大无法进入FPGA的PLL模块。如果采用时钟平滑技术,把恢复的2M平滑出抖动在100ps以下的8M时钟,那么再用PLL倍频成32M或64M就很方便了。时钟平滑和比特同步虽通常一起使用,但时钟平滑又独立于比特同步,所以在放在下一帖单独介绍时钟平滑过程。本帖着力讨论高速信号的比特同步。
比特同步原理
为行文方便,假设线路信号flow的比特率为100Mbps。用PLL产生一个150M(100×1.5 = 150M)低抖动本地时钟信号clk150M。低抖动的时钟的产生方式是选取PLL为无补偿模式”with no compensation”。用clk150M的下沿和上沿分别读取flow获得smp,则相当于用300M时钟采样100M的flow。
通常情况下,smp的比特数是flow比特数的三倍。即如果flow= 0100则smp = 000111000000,考虑到flow的相位抖动和不同源问题,一个比特的flow也可能被读取为2~4个比特。那么 smp的可能值为000111000000、00111000000、0000111000000、00011000000或者000110000000、000111100000……等等情况。
判决为1的方法是: smp从0变1开始数1,当数到第二个1时判决收到flow第一个1,以后每增加三个1判决flow增加一个1。也就是说smp中2~4个1判决为flow的一个1、5~7个1判决为flow的两个1、8~10个1判决为flow的三个1...,以此类推。
判决为0的方法是从smp由1变0开始数0,其他情况类似。
按照上述方法从列出的smp值中均可正确判断出收到了flow四个比特且值为0100,那么我们可以说完成了flow的比特同步和判决。
比特同步实现过程
实现代码如下
1.      function sum_ones(vCur,vIn   : std_vector) return std_vector is
                   variable v                   : std_vector(0 to 3);
                   variable q                            : std_vector(0 to1);
         begin
5.               v := vCur& vIn;
                   case v is
                   when"0001"|"0101"| "1001"| "1101"|"1011"=>         q := "01";
                   when"0011"|"1111"|"0110" =>                                          q :="10";
                   when"0111"                      =>                                                    q:= "11";
10.             when others                       =>                                                    q:= "00";
                   end case;
                   return q;
         end;
         Signal nEdge,h_b,h_en                                : std_logic;
15.   Signal P2B,pCnt,nCnt                                   : std_vector(0to 1);
16.   Process(clk150M) begin
                   iffalling_edge(clk150M) then
                            nEdge<= flow;
                   end if;
20.             if rising_edge(clk150M)then
                            P2B<= nEdge & flow;      
                            pCnt<= sum_ones(pCnt, P2B);
                            nCnt<= sum_ones(nCnt, not P2B);
                            LoadValue(h_b,pCnt(0), pCnt(0) or nCnt(0));
25.                      h_en<= pCnt(0) or nCnt(0);
                   end if;
         End process;
行1到行13定义的函数sum_ones完成1计数功能,在讲述22行之后再详述。
行18:下降沿读取flow到nEdge
行21:上升沿读取flow,合并nEdge获得并行的两个比特smp值P2B。
行22:pCnt作用是对P2B中连续1的模3计数。每当pCnt(0)=’1’则表示收到flow中的一个’1’。
行7:when"0001"|"0101"| "1001" | "1101" |"1011"=>q := "01";中"0001"表示当前1的个数为0("00")收到的P2B="01",那么当前时钟周期收到P2B后1的个数由0变为1,那么返回值为1,即"01"。"0101"| "1001" | "1101"均表示收到了P2B="01",smp中有0到1的变化,重新开始计数,所以返回值均为"01"。"1011"中前面余下的1的个数为"10"(两个),P2B="11"中1的个数是两个,那么模3后余下的1的个数是一个,所以也返回"01"。
行8:when"0011"|"1111"|"0110"=>q := "10";中0+2、3+2、1+1模3后均为2,所以返回"10",
行9:表示1+2=3返回”11”
行10:对其他情况均返回0。对于”1010”或”1110”也返回0是因为新增加的一个1(P2B = ”10”)不足以使flow增加一个1,所以同样返回0,pCnt恢复到重新等待0到1的变化状态。
行23:nCnt是对P2B中的0计数,等效于对P2B取反然后1计数。
行25:pCnt(0)=’1’或nCnt(0)=’1’表示收到了flow的一个比特,用h_en指示。
行24:pCnt(0)=’1’表示收到一个比特的1,nCnt(0)=’1’表示收到一个比特的0。这个比特的值锁存在h_b中。
经过第24和25行获得的h_en和h_b,分别用作使能和数据。h_en携带者flow的时钟信息,h_b为flow的比特判决值。即实现了比特同步。
本模块已实际应用于155.52Mbps的STM-1比特同步,实测未见异常。

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

ucx

29

主题

89

帖子

5

粉丝