学习FPGA的一点心得
VHDL作业 1、写出消抖的程序,通过仿真或下载得出对应的波形,并分析。 FPGA对于输入的信号一般都要经过消抖处理,以消除干扰信号。对于两个设备之间的数据传输,这一点显得尤为重要。 消抖一般通过记录脉冲的个数,对输入信号的尖峰宽度进行限制,达不到预定的宽度,即认为是干扰,必须加以滤除,部分代码如下。因此,信号经过消抖去除干扰信号以后,必然产生延迟,延迟时间与系统晶振频率以及计数脉冲个数有关。 例如:设系统晶振为40MHz,消抖时间为4个CLK,一个脉冲时间为1/40M=25ns,所以信号延时为25*4=100ns,如图1所示。  图1 信号消抖示意图 代码示例: (a)延时4clk - process (gclk,rst) --群信号消抖
- begin
- if rst='1' then
- sig_out<='0';
- elsif gclk'event and gclk = '1' then
- sig_0 <= sig_in;
- sig_1 <= sig_0;
- sig_2 <= sig_1;
- sig_3 <= sig_2;
- if ((sig_3 = sig_2) and (sig_2 = sig_1) and (sig_1 = sig_0) and (sig_0 = sig_in)) then
- sig_out <= sig_3;
- end if;
- end if;
- end process;
复制代码
仿真结果如图2: 
图2消抖程序仿真图 (b) 延时4ms - process (gclk)
- begin
- if rst='1' then
- signal_out<='0';
- psignal<='0';
- ppsignal<='0';
- signal_cnt<=0;
- elsif (gclk='1') and (gclk'event) then
- ppsignal <= psignal;
- psignal <= signal_in;
- if psignal /= ppsignal then
- signal_cnt <= 0;
- else
- signal_cnt <= signal_cnt + 1;
- if signal_cnt > 159999 then ------消抖时间为4ms------
- --if signal_cnt > 99 then
- signal_out <= psignal;
- end if;
- end if;
- end if;
- 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串行发送
- process (pClock, pReset) --惯组信号源控制主进程
- begin
- if pReset = '1' then
- ch_ClearBusyFlag <= '1';
- ch_tx <= '1';
- ch_send_reg <= "0000000000000000000000000000000000000000";
- ch_st <= 0;
- ch_clock_fp <= 0;
- elsif (pClock='1') and (pClock'event) then
- if ch_st = 0 then --监测有无数据发送
- if (ch_s_busy_flag = '1') then
- ch_send_reg <= ch_send_buf; --读取要发送的数到寄存器
- ch_ClearBusyFlag <= '0'; --置忙标志清零
- ch_bit_counter <= 0;
- ch_clock_fp <= 0;
- ch_st <= 1;
- else
- ch_st <= 0;
- end if;
- elsif ch_st = 1 then --串行发送
- ch_clock_fp <= ch_clock_fp + 1; --0 - 57, 每位57个时钟,共12位,1起始,1停止,2空闲
- if ch_clock_fp = 1 then
- ch_tx <= ch_send_reg(39 - ch_bit_counter);
- elsif ch_clock_fp = 2 then
- if ch_bit_counter = 39 then
- ch_tx <= '1';
- ch_st <= 0; --跳转到监测busy标志,等待发送下一个数
- else
- ch_bit_counter <= ch_bit_counter + 1;
- end if;
- elsif ch_clock_fp = 3 then
- if ch_bit_counter = 5 then
- ch_ClearBusyFlag <= '1'; --忙标志清零结束,4个clk,希望前一进程不会监测丢失
- end if;
- end if;
- end if;
- end if;
- end process;
复制代码
(b) 422串行接收
******************************************************************
--命令接收主控制进程**异步接收,40位
仿真结果: 
图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)帧同步、路同步、码同步信号的产生
(b) PCM码接收
- process (f_mtb, rst, f_ztb)
- begin
- if rst = '1' or f_ztb='1' then
- q_state<=q0;
- f_data<="00000000";
- f_flag<='0';
- elsif f_mtb'event and f_mtb = '0' and f_ztb='0' then
- case q_state is
- when q0 =>
- f_data(7)<=not qun_afxd;
- f_flag<='0';
- q_state<=q1;
- when q1 =>
- f_data(6)<=not qun_afxd;
- q_state<=q2;
- when q2 =>
- f_data(5)<=not qun_afxd;
- q_state<=q3;
- when q3 =>
- f_data(4)<=not qun_afxd;
- q_state<=q4;
- when q4 =>
- f_data(3)<=not qun_afxd;
- q_state<=q5;
- when q5 =>
- f_data(2)<=not qun_afxd;
- q_state<=q6;
- when q6 =>
- f_data(1)<=not qun_afxd;
- q_state<=q7;
- when q7 =>
- f_data(0)<=not qun_afxd;
- f_flag<='1';
- q_state<=q0;
- when others =>
- q_state<=q0;
- end case;
-
- end if;
- end process ;
复制代码
(c) PCM码编帧
仿真结果: 

图15PCM通信的发送与接收仿真图
完整的Word格式文档51黑下载地址:
VHDL信号消抖.doc
(749.5 KB, 下载次数: 10)
|