找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4629|回复: 0
收起左侧

学习FPGA信号消抖的一点心得 附源码

[复制链接]
ID:388050 发表于 2018-8-20 11:08 | 显示全部楼层 |阅读模式
学习FPGA的一点心得
VHDL作业
1、写出消抖的程序,通过仿真或下载得出对应的波形,并分析。

FPGA对于输入的信号一般都要经过消抖处理,以消除干扰信号。对于两个设备之间的数据传输,这一点显得尤为重要。

消抖一般通过记录脉冲的个数,对输入信号的尖峰宽度进行限制,达不到预定的宽度,即认为是干扰,必须加以滤除,部分代码如下。因此,信号经过消抖去除干扰信号以后,必然产生延迟,延迟时间与系统晶振频率以及计数脉冲个数有关。

例如:设系统晶振为40MHz,消抖时间为4个CLK,一个脉冲时间为1/40M=25ns,所以信号延时为25*4=100ns,如图1所示。

  

图1 信号消抖示意图

代码示例:

(a)延时4clk

  1.        process (gclk,rst)                                            --群信号消抖
  2.               begin                           
  3.                             if rst='1' then
  4.                                sig_out<='0';
  5.                             elsif gclk'event and gclk = '1' then
  6.                                           sig_0 <= sig_in;
  7.                                           sig_1 <= sig_0;
  8.                                           sig_2 <= sig_1;
  9.                                           sig_3 <= sig_2;
  10. if ((sig_3 = sig_2) and  (sig_2 = sig_1) and (sig_1 = sig_0) and (sig_0 = sig_in)) then   
  11.                                                         sig_out <=  sig_3;
  12.                                           end if;
  13.                             end if;
  14. end process;
复制代码


仿真结果如图2:

图2消抖程序仿真图

(b) 延时4ms

  1.               process (gclk)                                    
  2.               begin
  3.                    if rst='1'  then
  4.                                signal_out<='0';
  5.                                psignal<='0';
  6.                                ppsignal<='0';
  7.                                signal_cnt<=0;            
  8.                             elsif (gclk='1') and (gclk'event) then
  9.                                 ppsignal <= psignal;
  10.                                 psignal <= signal_in;
  11.                                 if psignal /= ppsignal then
  12.                                             signal_cnt <= 0;
  13.                                 else
  14.                                             signal_cnt <= signal_cnt + 1;
  15.                                             if signal_cnt > 159999 then              ------消抖时间为4ms------
  16.                                               --if signal_cnt > 99 then
  17.                                                         signal_out <= psignal;
  18.                                             end if;                             
  19.                                 end if;
  20.                    end if;
  21.               end process;
复制代码

仿真结果;

图3延时仿真图

2、测试在不同主频、分频下逻辑处理上的不同,并分析。
              分频器是数字系统设计中的基本电路,根据不同设计的需要,我们会遇到偶数分频、奇数分频、半整数分频等,有时要求等占空比,有时要求非等占空比。在同一个设计中有时要求多种形式的分频。通常由计数器或计数器的级联构成各种形式的偶数分频及非等占空比的奇数分频,实现较为简单。但对半整数分频及等占空比的奇数分频实现较为困难。本文利用VHDL硬件描述语言,可设计了一种能够满足上述各种要求的较为通用的分频器。

              现通过设计一个可以实现8.5分频,等占空比的17分频,2、4、8、16、32分频,及占空比为1∶8和4∶5的9分频等多种形式分频的分频器。分频器由带使能端的异或门、模N计数器和一个2分频器组成,本设计用D触发器来完成2分频的功能,实现方法是:将触发器的Q反输出端反馈回输入端D,将计数器的一个计数输出端作为D触发器的时钟输入端。各功能模块的VHDL语言实现如下。

1).模N计数器的实现

  一般设计中用到计数器时,我们可以调用lpm库中的计数器模块,也可以采用VHDL语言自己设计一个模N计数器。本设计采用VHDL语言设计一个最大模值为16的计数器。输入端口为:使能信号en,复位信号clr和时钟信号clk;输出端口为:qa、qb、qc、qd。其VHDL语言描述略。

 2).带使能控制的异或门的实现

  输入端为:xor_en:异或使能,a和b:异或输入;输出端为:c:异或输出。当xor_en为高电平时,c输出a和b的异或值。当xor_en为低电平时,c输出信号b。其VHDL语言略。

3).分频(触发器)的实现

  输入端为:时钟信号clk,输入信号d;输出端为:q:输出信号a,q1:输出信号a反。其VHDL语言略。

以下是几种分频器的分析:

偶数分频器

频最易于实现,欲实现占空比为50%的偶数N分频,一般来说有两种方案:,分频器的基础是计数器,设计分频偶数分N/2-1时,将输出电平进行一次翻转,同时给计数器一个复位信号,如此循环下去;二是当计数器输出为0到N/2-1时,时钟输出为0或1,计数器输出为N/2到N-1时,时钟输出为0或1,计数器输出为N/2到N-1时,时钟输出为0或1,计数器输出为N-1时,复位计数器,如此循环下去。

                                                                                    图4  偶数分频仿真结果图
                                                                                    图 5 偶数分频仿真结果图
奇数分频器

              实现非50%占空比的奇数分频,如占空比为20%、40%、60%、80%的5分频器,可以采用类似偶数分频的第二种方案;但如果实现占空比为50%的奇数分频,就不能使用偶数分频中所采用的方案了。

下面就以实现占空比40%的5分频分频器为例,说明非50%占空比的奇数分频器的实现。该分频器的实现对于我们实现50%占空比的分频器有一定的借鉴意义。一下是奇数分频仿真结果图。

                                                                      图6  占空比为40%的5分频仿真波形

半整数分频器

仅仅采用数字分频,不可能获得占空比为50%的N+0.5分频,我们只可以设计出占空比为(M+0.5)/(N+0.5)或者M/(N+0.5)的分频器,M小于N。这种半整数分频方法是对输入时钟进行操作,让计数器计数到某一个数值时,将输入时钟电平进行一次反转,这样,该计数值只保持了半个时钟周期,因此实现半整数分频。

              如上所述,占空比为50%的奇数分频可以帮助我们实现半整数分频,将占空比为50%的奇数分频与待分频时钟异或得到计数脉冲,下面的代码就是依靠占空比为50%的5分频实现2.5分频器的。仿真结果如图所示。

                                                                                    图7 2.5分频仿真波形

小数分频器

小数分频是通过可变分频和多次平均的方法实现的。例如要实现4.7分频,只要在10次分频中,做7次5分频,3次4分频就可以得到。再如要实现5.67分频,只要在100次分频中,做67 6分频,33次5分频即可。考虑到小数分频器要进行多次两种频率的分频,必须设法将两种分频均匀。表1以2.7分频为例,小数部分进行累加,如果大于等于10,则进行3分频,如果小于10,进行2分频。

              仿真波形如图 所示,我们可以清楚的看到2.7分频的实现。按照占空比的定义,该分频器的占空比应为10/27。

图8 2.7分频仿真波形

分数分频器

将小数分频的方法进行扩展,可以得到形如M*(L/N) 的分数分频的方法,例如,2*(7/13)等于分母的,进行分频,只要在13次分频中,进行7次3分频,6次2分频就可以得到。同样,为了将两种分频均匀,将分子部分累加,小于分母的,进行M分频,大于(M+1)分频。表2显示了2*(7/13) 的分频次序。

仿真波形如图11所示。显然,该分频器的占空比为13/33。

图9 33/13分频器仿真波形
积分分频器

积分分频器用于实现形如的分频,例如8/3分频。我们当然可以使用上面提到的分数分频的方法,但对于这种形式的分频,使用积分分频的方法综合往往占用更少的FPGA资源。

积分分频法基于下述原理:一个m位的二进制数字每次累加N,假定累加x次累加值最低m位回到0,同时超过次,那么,当前累加的数字应该是;每越过一次,最高位变化 2 次,所以,累加 x 次,最高位变化 2y次,得到分频的分频器,例如,取m为4,N为3,当累加16次时,累加值为48,最低m位变回到0,同时越过16三次,最高位变化6次,由此得到16/6=8/3分频的分频器。

分频仿真结果如图所示。

图10 积分分频仿真波形
3、写出异步串行通信的发送与接收程序,并分析。

异步串行数据传输具有设计简单、传输稳定等优点。其两个主要参数是波特率和数据位格式。数据位格式又称帧格式,一般包含一个起始位(逻辑0),一个终止位(逻辑1)以及校验位。在发送空闲时,总线一般处于逻辑1状态。这样当接收端检测到总线上由高到低的电平跳变,即认为是数据开始传输。波特率是用来约定通信双方的通信速率,一般通过对系统时钟进行分频来实现,RS-232协议中,常用的波特率有115200、9600等,RS-422与RS-232原理基本相同,只是在传输线路上,为了抗干扰,采用了差分方式。

在FPGA应用领域 ,串行数据传输一般采用422总线。通过对系统晶振分频,得到对应的波特率,比如对40MHz经行4分频,得到10MBit的传输速率。解码端会根据预先设定的波特率,对时钟进行分频,每隔相等时间读取总线上的一位数据。流程如下:在检测到起始位低电平之后,接收端(即解码端)每隔一位时间,采集总线上的电平,并写入移位寄存器中,直到将一帧数据全部接收,然后判断校验位,如果正确,则接收、编帧,否则,丢弃。

由于受温度等因素的影响,晶振会产生误差,串行数据在传输过程中,可能会受到干扰而产生毛刺。所以在一些对数据准确度要求比较高的场合,就得考虑串行数据传输的容错能力。对于这种情况,第一种方法通常会采取对总线上的一位分别采集三次,比较得到的三个电平,进而得到该位可信度更高的值,如图2所示;第二种方法则会将电平的采集点放在每一位的靠近中间的位置,通过计算晶振的最大误差,则可以计算出系统的最大容错能力。设晶振误差5%,频率为40MHz,1/40MHz=25ns,25*0.05=1.25ns,设波特率为4Mbit/s,所以对于40bit一帧的串行数据,累积误差最大会有1.25*40*4*50%=100ns,而比特位宽只有100ns,所以有可能会发生错位。

图11 多次采样减小误差示意图

部分代码如下

(a)422串行发送



  1. process (pClock, pReset)                 --惯组信号源控制主进程
  2.     begin
  3.         if pReset = '1' then
  4.             ch_ClearBusyFlag <= '1';
  5.             ch_tx <= '1';
  6.             ch_send_reg  <= "0000000000000000000000000000000000000000";
  7.             ch_st <= 0;
  8.             ch_clock_fp <= 0;
  9.         elsif (pClock='1') and (pClock'event) then
  10.             if    ch_st = 0 then    --监测有无数据发送                                                                          
  11.                 if (ch_s_busy_flag = '1') then
  12.            ch_send_reg  <= ch_send_buf;   --读取要发送的数到寄存器
  13.                     ch_ClearBusyFlag <= '0';  --置忙标志清零                       
  14.                     ch_bit_counter <= 0;
  15.                     ch_clock_fp <= 0;
  16.                     ch_st <= 1;
  17.                 else
  18.                     ch_st <= 0;
  19.                 end if;   
  20.             elsif  ch_st = 1 then     --串行发送                                    
  21.                 ch_clock_fp <= ch_clock_fp + 1;      --0 - 57, 每位57个时钟,共12位,1起始,1停止,2空闲
  22.                 if ch_clock_fp = 1 then
  23.                         ch_tx <= ch_send_reg(39 - ch_bit_counter);
  24.                 elsif ch_clock_fp = 2 then                  
  25.                     if ch_bit_counter = 39 then
  26.                         ch_tx <= '1';
  27.                         ch_st <= 0;                                        --跳转到监测busy标志,等待发送下一个数
  28.                     else
  29.                         ch_bit_counter <= ch_bit_counter + 1;
  30.                     end if;
  31.                 elsif ch_clock_fp = 3 then
  32.                                                         if   ch_bit_counter = 5 then                           
  33.                                                ch_ClearBusyFlag <= '1';                          --忙标志清零结束,4个clk,希望前一进程不会监测丢失
  34.                               end if;
  35.                                             end if;
  36.             end if;
  37.         end if;
  38.     end process;
复制代码


(b) 422串行接收
******************************************************************
--命令接收主控制进程**异步接收,40位

  1.     process (gClock_160, g_reset)      --flag=1 时,串并转换完成,
  2.     begin
  3.         if g_reset = '1' then
  4.             flag <= '1';
  5.         elsif (gClock_160='1') and (gClock_160'event) then
  6.             if cnt = 180 then  --161到180等待发送进程取走send_buf中的数去发送
  7.                 flag <= '1';               
  8.             elsif rx = '0'  then
  9.                 flag <= '0';
  10.             end if;
  11.         end if;
  12.     end process;
  13.     process (gClock_160, g_reset)            --160MHz采样40Mbps,每个位采样4个点,40个位cnt计数达到160
  14.     begin
  15.         if g_reset = '1' then
  16.             soft_reset <= '0';
  17.             cnt <= 0;
  18.            RcvBuf <= "0000000000000000000000000000000000000000";
  19.             tmp_data <= "0000000000000000000000000000000000000000";
  20.             REG_WR_PIPE_ADD <= "1111111111111111";
  21.             REG_ID <= "1111111100000001";
  22.                               led_show<='1';
  23.         elsif (gClock_160='1') and (gClock_160'event) then     
  24.                             -- led_show<= not led_show;
  25.             if flag = '1' then
  26.                 cnt <= 0;
  27.                 verify <= '0';
  28.             elsif flag = '0' then
  29.                 cnt <= cnt + 1;
  30.             end if;
  31.             if cnt =  1 then
  32.                 tmp_data(0)<=rx;
  33.             elsif cnt =  5 or cnt =  9 or cnt =  13 or cnt =  17 or
  34. cnt = 21 or cnt = 25 or cnt = 29 or cnt =  33 or cnt = 37 or  cnt = 41 or cnt = 45 or cnt = 49 or cnt = 53 or cnt =  57 or cnt = 61 or cnt = 65 or cnt = 69 or cnt = 73 or cnt = 77 or cnt = 81 or cnt = 85 or cnt = 89 or cnt = 93 or cnt = 97 or cnt = 101 or cnt =105 or cnt =109 or cnt =113 or cnt = 117 or cnt =121 or cnt =125 or cnt =129 or cnt =133 or cnt = 137 or cnt = 141 or cnt = 145 or cnt = 149 or cnt = 153 or cnt = 157 then               --先发高位
  35.                 verify <= verify xor rx;
  36.                 tmp_data(0)<=rx;
  37. for I in 1 to 39 loop
  38.                     tmp_data(I)<= tmp_data(I-1);
  39.                 end loop;
  40.             elsif (cnt = 160) and (tmp_data(39) = '0') and (tmp_data(1) = '1') and (tmp_data(0) = '1') then         --判断起始停止位
  41.                 RcvBuf <= tmp_data;
  42.              wr_ch_add <= CONV_INTEGER(REG_WR_PIPE_ADD(2 downto 0));
  43.                 FCA <= CONV_INTEGER(tmp_data(36 downto 29));
  44.                 CA <= CONV_INTEGER(tmp_data(31 downto 29));
  45.                 RW <= tmp_data(28);
  46.                 RA <= CONV_INTEGER(tmp_data(27 downto 21));
  47.                 CMD <= tmp_data(20 downto 5);
  48.             elsif (cnt = 161) and (verify = '0') and (RcvBuf(38) = not RcvBuf(4)) and (RcvBuf(37) = not RcvBuf(3)) then
  49.                             ---------------------■■■■接收数据测试用后删除-----------
  50.                                           RcvFlag_change  <= not RcvFlag_change;
  51.                                           RcvFlag              <=  RcvFlag_change;                                                        --接收数据翻转
  52.                                           testch              <=              tmp_data(31 downto 29);              --接收数据通道显示
  53.                             ---------------------■■■■------------------------------            
  54.                                           led_show<= not led_show;
  55.                                           if RcvBuf(38) = '0' then                                    --数据流,转发对应管道
  56.         if (CONV_INTEGER(REG_WR_PIPE_ADD) < 16) and (REG_WR_CH_BUSY(wr_ch_add) = '0') then
  57.                         send_buf(wr_ch_add) <= RcvBuf;   
  58.                         REG_WR_CH_BUSY(wr_ch_add) <= '1';                   --相应通道置忙,不允许再写入
  59.                     end if;
  60.                 elsif RcvBuf(38 downto 37) = "11" then                     
  61. --解析命令
  62.                     if FCA /= 255 then                                   --发送给16个通道的命令
  63.                 if (CA < 16) and (REG_WR_CH_BUSY(CA) = '0') then     --如果忙,将丢失此包,否则送给某个端口
  64.                             send_buf(CA) <= RcvBuf;        
  65.                             REG_WR_CH_BUSY(CA) <= '1';                      --置忙,不允许再写入,
  66.                         end if;
  67.                     else                                                    --发送给背板本身的命令
  68.                         if RW = '1' then
  69.                             case RA is
  70.                             --when 0 =>
  71.                             when 1 =>                                       --立即执行
  72.                    if CMD="0000000011000000" then    --reset
  73.                          soft_reset <= '1';      
  74.                                 end if;
  75. when 2 =>
  76.               REG_WR_PIPE_ADD <= CMD;
  77.   when 3 =>
  78.                 REG_RD_PIPE_ADD <= CMD;
  79. when others =>
  80.                  if (port_busy = '0') then
  81.             port_send_buf <= "010111111111" & RcvBuf(27 downto 21) & "111100000000111101011";    --失败
  82.                       port_busy <= '1';
  83.                           end if;
  84.                         end case;
  85.              else
  86.                   case RA is
  87.                       when 0 =>         -- read id
  88.                            if (port_busy = '0') then
  89.           port_send_buf <= "0101111111100000000" & REG_ID & "01011";
  90.                            port_busy <= '1';
  91.                              end if;
  92.                             --when 1 =>
  93.                         when 2 =>
  94.                           if (port_busy = '0') then
  95.   port_send_buf <= "0101111111100000010" & REG_WR_PIPE_ADD & "01011";
  96.                            port_busy <= '1';
  97.                              end if;
  98.                           when 3 =>
  99.                          if (port_busy = '0') then
  100.   port_send_buf <= "0101111111100000011" & REG_RD_PIPE_ADD & "01011";
  101.                           port_busy <= '1';
  102.                             end if;
  103.                          when 4 =>
  104.                       if (port_busy = '0') then
  105.    port_send_buf <= "0101111111100000100" & REG_WR_CH_BUSY & "01011";
  106.                         port_busy <= '1';
  107.                            end if;
  108.                         when others =>
  109.                      if (port_busy = '0') then
  110.    port_send_buf <= "010111111110" & RcvBuf(27 downto 21) & "111101010000101001011";                       --失败
  111.                          port_busy <= '1';
  112.                             end if;
  113.                             end case;
  114.                         end if;
  115.                        end if;
  116.                     --解析命令完成*****************************************************************
  117.                 end if;
  118.             elsif cnt < 160 then
  119.          REG_WR_CH_BUSY <= REG_WR_CH_BUSY and ("00000000" & ClearSndFlag_16ch);     --清除16个通道忙标志
  120.         port_busy <= port_busy and port_ClearBusyFlag;               --清除主通道忙标志
  121.             end if;
  122.         end if;
  123.     end process;
复制代码

仿真结果:

图12异步串行通信的发送与接收

4、写出PCM通信的发送与接收程序,并分析。

PCM脉冲编码调制是将模拟信号转换成二进制数字信号的编码过程。在无线遥测系统中,遥测采编器对多路模拟信号通过特定的顺序(帧结构)进行模数转换采样,然后再将采得的PCM码并串转换,串行送至无线发射机发射。地面站通过无线接收机接收。解码后的PCM码是一个由二进制数构成的串行序列。地面接收设备的主要任务是将串行PCM码中的数据解调出来,这就需要根据PCM码流中特定的同步码确定数据的起始位,在位信号变化时的上升沿(或下降沿)把PCM码流的位同步信号分离出来,再通过串行数据到并行数据的转换把数据并行输出。

    PCM码的串并转换分为三步,第一步是提取同步信号,第二步是提取帧同步信号,第三步是根据已得到的位同步和帧同步完成字同步和串并转换。

PCM码在发送以及接收(解码)过程中,都会用帧同步和码同步对PCM码进行同步,有些还会用到路同步信号,如图13所示。一般是PCM码接收端发送同步信号(即帧同步、码同步和路同步)。PCM码发送端根据接收到的同步信号输出PCM码,比如在码同步的上升沿或者下降沿给出数据,接收端则根据自己发出的同步信号接收PCM码。在实际数据传输过程中,考虑到信号的延时,一般发送端在码同步上升沿给出PCM数据,接收端在码同步下降沿读取PCM数据,而帧同步一般用作帧复位,路同步用作字节复位,如图14所示。

接收端接收到PCM数据后,一般要经过编帧,加上帧头、帧尾以及帧计数,然后上传给计算机。计算机则将数据解包,提取出有用的信息。

图13  PCM码接收发送过程中的信号示意图

图14 同步信号示意图

部分参考代码:

(a)帧同步、路同步、码同步信号的产生



  1.     process(gclk, rst)------ 分频得到码同步时钟,3.05008us x 2=6.10016us ,要求是6.1035us
  2.               begin
  3.                  if rst = '1' then
  4.                             gclk_cnt<=0;
  5.                             gclk_3us<='0';
  6.               elsif gclk'event and gclk = '1'  then
  7.                             if gclk_cnt>=60 then
  8.                                           gclk_cnt<=0;
  9.                                           gclk_3us<= not gclk_3us;
  10.                             else
  11.                                           gclk_cnt<=gclk_cnt+1;
  12.                             end if;
  13.      end if;  
  14. end process;
  15. process(gclk_3us, rst)                ----帧同步、码同步、路同步信号产生
  16.     begin
  17.               if rst='1' then
  18.                               f_ztb<='0';            
  19.                                   f_ltb<='1';
  20.                               f_mtb<='0';
  21.                               cnt2<=0;
  22.                               cnt1<=0;
  23.                               pcm_state<=pst0;                                                                                                               
  24.                 elsif  gclk_3us='1' and gclk_3us'event then   ----时钟频率为1/2码同步
  25.                             case pcm_state is
  26.               when pst0=>                                     ----ztb上升沿与mtb下降沿对齐,路同步延迟一个周期后,开始发送码同步
  27.                                               f_ztb<='1';
  28.                                             f_ltb<='0';
  29.                                             if cnt1=4 then
  30.                                                cnt1<=0;
  31.                              pcm_state<=pst1;            
  32.                                             else
  33.                                                         cnt1<=cnt1+1;
  34.                                                         pcm_state<=pst0;
  35.                                             end if;            
  36.                                           when pst1=>                           
  37.                                                    f_ztb<='0';
  38.                                              if cnt1=2 then
  39.                                       pcm_state<=pst2;
  40.                                                         cnt1<=0;
  41.                                              else
  42.                                                         cnt1<=cnt1+1;
  43.                                                         pcm_state<=pst1;
  44.                                              end if;
  45.                                           when pst2=>
  46.                                                    f_ltb<='1';
  47.                                              if cnt1=7 then
  48.                               pcm_state<=pst3;
  49.                                                 cnt1<=0;
  50.                                              else
  51.                                                 cnt1<=cnt1+1;
  52.                                                         pcm_state<=pst2;
  53.                                              end if;
  54.                                                                                       
  55.                                  when pst3=>
  56.                                                f_ltb<='0';
  57.                                                f_mtb<='1';                            -------1            
  58.                                                pcm_state<=pst4;
  59.                         when pst4=>
  60.                                                f_mtb<='0';
  61.                              pcm_state<=pst5;
  62.                                  when pst5=>            
  63.                                                f_mtb<='1';                            -------2
  64.                              pcm_state<=pst6;
  65.                                           when pst6=>
  66.                                                f_mtb<='0';
  67.                              pcm_state<=pst7;
  68.                                           when pst7=>                                         
  69.                                                f_mtb<='1';                            -------3
  70.                              pcm_state<=pst8;
  71.                                           when pst8=>            
  72.                                                f_mtb<='0';
  73.                              pcm_state<=pst9;
  74.                                           when pst9=>            
  75.                                                f_mtb<='1';                            ------4
  76.                              pcm_state<=pst10;
  77.                                           when pst10=>            
  78.                                                f_mtb<='0';
  79.                              pcm_state<=pst11;
  80.                                             when pst11=>            
  81.                                       f_ltb<='1';
  82.                                                f_mtb<='1';                    ------5
  83.                              pcm_state<=pst12;
  84.                                           when pst12=>
  85.                                                f_mtb<='0';
  86.                              pcm_state<=pst13;
  87.                                           when pst13=>
  88.                                                f_mtb<='1';                            ------6
  89.                              pcm_state<=pst14;
  90.                                           when pst14=>
  91.                                                f_mtb<='0';
  92.                              pcm_state<=pst15;
  93.                                           when pst15=>
  94.                                                f_mtb<='1';                            ------7
  95.                              pcm_state<=pst16;
  96.                                           when pst16=>
  97.                                                f_mtb<='0';
  98.                              pcm_state<=pst17;
  99.                                           when pst17=>
  100.                                                f_mtb<='1';                            ------8
  101.                              pcm_state<=pst18;
  102.                                           when pst18=>
  103.                                                f_mtb<='0';
  104.                              pcm_state<=pst19;
  105.                                           when pst19=>         --------f_mtb保持低,再产生3个周期的f_ltb
  106.                                       f_ltb<='0';                    ----------第2个f_ltb
  107.                                                         if cnt1=7 then
  108.                                                            cnt1<=0;
  109.                                                            pcm_state<=pst20;
  110.                                                         else
  111.                                                            cnt1<=cnt1+1;
  112.                                                            pcm_state<=pst19;
  113.                                                         end if;
  114.                                           when pst20=>                           
  115.                                       f_ltb<='1';
  116.                                                         if cnt1=7 then
  117.                                                            cnt1<=0;
  118.                                                            pcm_state<=pst21;
  119.                                                         else
  120.                                                            cnt1<=cnt1+1;
  121.                                                            pcm_state<=pst20;
  122.                                                         end if;
  123.                                           when pst21=>
  124.                                       f_ltb<='0';                                  -------第3个f_ltb
  125.                                                         if cnt1=7 then
  126.                                                            cnt1<=0;
  127.                                                            pcm_state<=pst22;
  128.                                                         else
  129.                                                           cnt1<=cnt1+1;
  130.                                                           pcm_state<=pst21;
  131.                                                         end if;
  132.                                           when pst22=>            
  133.                                       f_ltb<='1';
  134.                                                         if cnt1=7 then
  135.                                                            cnt1<=0;
  136.                                                            if cnt2=127 then                   ------循环128次,产生128路f_mtb
  137.                                                                          cnt2<=0;
  138.                                                                       pcm_state<=pst0;
  139.                                                            else
  140.                                                               cnt2<=cnt2+1;
  141.                                                                       pcm_state<=pst23;
  142.                                 end if;
  143.                                                         else
  144.                                                                       cnt1<=cnt1+1;
  145.                                                                       pcm_state<=pst22;
  146.                                                         end if;
  147.                                           when pst23=>            
  148.                                       f_ltb<='0';                                          --------第4个f_ltb
  149.                                                         if cnt1=7 then
  150.                                                            cnt1<=0;
  151.                                                            pcm_state<=pst24;
  152.                                                         else
  153.                                                            cnt1<=cnt1+1;
  154.                                                            pcm_state<=pst23;
  155.                                                         end if;
  156.                                           when pst24=>
  157.                                       f_ltb<='1';
  158.                                                         if cnt1=7 then
  159.                                                            cnt1<=0;     
  160.                                                      pcm_state<=pst3;
  161.                                                         else
  162.                                                            cnt1<=cnt1+1;
  163.                                                            pcm_state<=pst24;
  164.                                                         end if;
  165.                                when others =>
  166.                                      pcm_state<=pst0;
  167.                  end case;
  168.     end if;
  169.   end  process;
复制代码


(b) PCM码接收
  1.   process (f_mtb, rst, f_ztb)                                          
  2.     begin
  3.         if rst = '1' or f_ztb='1' then
  4.                               q_state<=q0;
  5.                               f_data<="00000000";
  6.                               f_flag<='0';                                                           
  7.          elsif f_mtb'event and f_mtb = '0' and f_ztb='0' then
  8.                                              case q_state  is
  9.                                               when q0 =>
  10.                                                 f_data(7)<=not qun_afxd;
  11.                                                         f_flag<='0';
  12.                                                         q_state<=q1;
  13.                             when q1 =>
  14.                                                 f_data(6)<=not qun_afxd;
  15.                                                         q_state<=q2;
  16.                                               when q2 =>
  17.                                                 f_data(5)<=not qun_afxd;
  18.                                                   q_state<=q3;
  19.                                               when q3 =>
  20.                                                 f_data(4)<=not qun_afxd;
  21.                                                         q_state<=q4;
  22.                                               when q4 =>
  23.                                                 f_data(3)<=not qun_afxd;
  24.                                                         q_state<=q5;
  25.                                               when q5 =>
  26.                                                 f_data(2)<=not qun_afxd;
  27.                                                         q_state<=q6;
  28.                                               when q6 =>
  29.                                                 f_data(1)<=not qun_afxd;
  30.                                                         q_state<=q7;
  31.                                               when q7 =>
  32.                                                 f_data(0)<=not qun_afxd;
  33.                                                         f_flag<='1';
  34.                                                         q_state<=q0;
  35.                                               when others =>
  36.                                                         q_state<=q0;
  37.                             end case;

  38.          end if;
  39.    end process ;
复制代码



(c) PCM码编帧
  1. process (gclk, rst)                            ---数据编帧,128 Byte群信号 + 2Byte转发信号(前11位,后5位为0) + 2Byte帧计数 + 2Byte帧标志
  2.     begin
  3.         if rst = '1' then
  4.                     fifo_data <= "00000000";
  5.                             b_state<=b0;
  6.                             z_cnt<=X"0000";
  7.                             cnt3<=0;
  8.                             f_flag_tmp<='0';
  9.          elsif gclk'event and gclk = '1' then
  10.                       case b_state is
  11.                                 when b0=>
  12.                                              f_flag_tmp<=f_flag;
  13.                                     if  f_flag_tmp='0' and f_flag='1' then
  14.                                        b_state<=b1;
  15.                                              else
  16.                                                 b_state<=b0;
  17.                                     end if;
  18.                                 when b1=>                                            
  19.                                             fifo_data<=f_data;
  20.                                             fifo_wr<='0';
  21.                                             b_state<=b2;
  22.               when b2 =>
  23.                                    if cnt4=10 then
  24.                                                cnt4<=0;
  25.                                                b_state<=b3;
  26.                  else
  27.                                                cnt4<=cnt4+1;
  28.                                                b_state<=b2;
  29.                  end if;
  30.               when b3=>
  31.                                             fifo_wr<='1';
  32.                                             b_state<=b41;            
  33.                                 when b41=>
  34.                                             if cnt3=127 then                                                      
  35.                                                             cnt3<=0;                                         
  36.                                                         b_state<=b4;
  37.                                             else                                                      
  38.                                                         cnt3<=cnt3+1;
  39.                                       b_state<=b0;
  40.                                             end if;                                                                                                
  41.               when b4 =>
  42.                                    fifo_data<= not zf1out & not zf2out  & not zf3out  & zf4out  & zf5out  & zf6out  & zf7out & zf8out;          --前8路转发信号
  43.                                             fifo_wr<='0';                   --前3路转发信号正端输入负端接地,由于通过管够接收,所以要取反            
  44.                                    b_state<=b5;                            --后8路信号负端输入正端接5V,所以不需要取反
  45.               when b5 =>
  46.                                    if cnt4=200 then
  47.                                                cnt4<=0;
  48.                                                b_state<=b6;
  49.                  else
  50.                                                cnt4<=cnt4+1;
  51.                                                b_state<=b5;
  52.                  end if;
  53.               when b6 =>
  54.                                    fifo_wr<='1';
  55.                              b_state<=b7;
  56.               when b7=>
  57.                                    b_state<=b8;
  58.               when b8=>
  59.                                    fifo_data<= zf9out & zf10out & zf11out  & "00000" ;                 --后3路转发信号
  60.                                             fifo_wr<='0';                                                                                                   
  61.                                    b_state<=b9;
  62.               when b9 =>
  63.                                    if cnt4=200 then
  64.                                                cnt4<=0;
  65.                                                b_state<=b10;
  66.                  else
  67.                                                cnt4<=cnt4+1;
  68.                                                b_state<=b9;
  69.                  end if;
  70.               when b10 =>
  71.                                    fifo_wr<='1';
  72.                               b_state<=b11;
  73.               when b11=>
  74.                                    b_state<=b12;
  75.               when b12=>
  76.                                    fifo_data<= z_cnt(15 downto 8) ;                                          --帧计数高字节
  77.                                             fifo_wr<='0';
  78.                                    b_state<=b13;
  79.               when b13 =>
  80.                                    if cnt4=200 then
  81.                                                cnt4<=0;
  82.                                                b_state<=b14;
  83.                  else
  84.                                                cnt4<=cnt4+1;
  85.                                                b_state<=b13;
  86.                  end if;
  87.               when b14 =>
  88.                                    fifo_wr<='1';
  89.                               b_state<=b15;
  90.                                 when b15=>
  91.                                    b_state<=b16;
  92.                                 when b16=>
  93.                                    fifo_data<= z_cnt(7 downto 0) ;
  94.                                             fifo_wr<='0';                                                                           --帧计数低字节
  95.                                    b_state<=b17;
  96.               when b17 =>
  97.                                    if cnt4=200 then
  98.                                                cnt4<=0;
  99.                                                b_state<=b18;
  100.                  else
  101.                                                cnt4<=cnt4+1;
  102.                                                b_state<=b17;
  103.                  end if;
  104.               when b18 =>
  105.                                    fifo_wr<='1';
  106.                                             z_cnt<=z_cnt+1;
  107.                               b_state<=b19;  
  108.                                 when b19=>
  109.                                    b_state<=b20;
  110.                                 when b20=>
  111.                                    fifo_data<= X"EB" ;                                                            --帧结束标志
  112.                                             fifo_wr<='0';
  113.                                    b_state<=b21;
  114.               when b21=>
  115.                                    if cnt4=200 then
  116.                                                cnt4<=0;
  117.                                                b_state<=b22;
  118.                  else
  119.                                                cnt4<=cnt4+1;
  120.                                                b_state<=b21;
  121.                  end if;
  122.               when b22=>
  123.                                    fifo_wr<='1';
  124.                               b_state<=b23;
  125.                                 when b23=>
  126.                                    b_state<=b24;
  127.                                 when b24=>                                                                                                      --帧结束标志
  128.                                    fifo_data<= X"90" ;
  129.                                             fifo_wr<='0';
  130.                                             b_state<=b25;
  131.                                 when b25 =>
  132.                  if cnt4=200 then
  133.                                                cnt4<=0;
  134.                                                b_state<=b26;
  135.                  else
  136.                                                cnt4<=cnt4+1;
  137.                                                b_state<=b25;
  138.                  end if;
  139.               when b26 =>
  140.                                    fifo_wr<='1';
  141.                               b_state<=b27;
  142.                                 when b27=>
  143.                                    b_state<=b0;
  144.                                 when others =>
  145.                                             b_state<=b0;
  146.              end case;
  147.            end if;
  148.      end process;
复制代码

仿真结果:

图15PCM通信的发送与接收仿真图


完整的Word格式文档51黑下载地址:
VHDL信号消抖.doc (749.5 KB, 下载次数: 10)

评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表