实验三序列发生器与序列检测器实验报告.docx

上传人:b****7 文档编号:10381211 上传时间:2023-02-10 格式:DOCX 页数:19 大小:236.50KB
下载 相关 举报
实验三序列发生器与序列检测器实验报告.docx_第1页
第1页 / 共19页
实验三序列发生器与序列检测器实验报告.docx_第2页
第2页 / 共19页
实验三序列发生器与序列检测器实验报告.docx_第3页
第3页 / 共19页
实验三序列发生器与序列检测器实验报告.docx_第4页
第4页 / 共19页
实验三序列发生器与序列检测器实验报告.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

实验三序列发生器与序列检测器实验报告.docx

《实验三序列发生器与序列检测器实验报告.docx》由会员分享,可在线阅读,更多相关《实验三序列发生器与序列检测器实验报告.docx(19页珍藏版)》请在冰豆网上搜索。

实验三序列发生器与序列检测器实验报告.docx

实验三序列发生器与序列检测器实验报告

南昌大学实验报告

姓名:

学号:

6100210173专业班级:

中兴通信101

实验类型:

验证□综合■设计□创新□实验日期:

2012、11、16

实验四序列信号发生器与检测器设计

一、实验目的

1、.学习VHDL文本输入法

2、学习有限状态机的设计

3、设计序列信号发生器和检测器

二.实验内容与要求

1.设计序列发生器,完成序列为0111010011011010的序列生成器

2.用有限状态机设计序列检测器,实现串行序列11010的检测器

3.若检测到符合要求的序列,则输出显示位为“1”,否则为“0”

4.对检测到的次数计数

三.设计思路

1.设计分频器因为最终要把待检测序列的检测次数在数码管上显示出,所以必须设计一个分频器,将起始频率作为数码管的扫描频率,而将分频后的频率作为序列发生器的移位频率,所以在程序中设置10KHZ进行分频分成1HZ脉冲(10KHZ的扫描频率是为了让数码管的动态显示更加清晰)

2.设计序列发生器

在这次的设计序列发生器时没有用状态转移的方法来来形成一个16位的序列,而是通过直接设计一串16位的序列,通过对最高位的输出与并置来形成一串循环的16位序列,这样设计简单方便,易于操作与控制,也减少了在状态转移产生的误差,其主要的核心程序为:

architecturebhvofp2is

signalbs:

std_logic_vector(15downto0):

="0111010011011010";

begin

xlout<=bs(15);

process(clk1hz)

begin

if(clk1hz'eventandclk1hz='1')then

bs<=bs(14downto0)&bs(15);

先将序列最高位输出至序列检测器中,然后在一个脉冲作用下,将此时最高位变成最低位,其余14位不变,使序列循环移动,最终形成一个16位循环序列。

3.设计序列检测器

基本思想是采用有限状态机设计,通过状态的转移来实现被检测序列的的检测,首先设定6个状态S0S1S2S3S4S5通过这6个状态的转移情况来检测出11010这个序列。

但因为序列发生器发生的序列不断循环过程中也会出现一些类似11010的特殊序列,则在状态转移中则需要通过一些状态的变换来检测出里面包含的11010序列,如下文所讲的两种特殊情形便是我们序列发生器产生序列中出现的特殊序列:

(1)在序列发生器产生序列不断循环过程中出现该序列1110100,此序列中也有一个要检测到的序列但在状态转移过程需要注意:

1110100

S0S1S2S2S3S4S5S0

即当S2状态转移到S3状态时,如果此时序列值为1,则只需转移到状态本身S2而不需要转移至S0,这样即可节约转移时间也可提高检测效率,之后的状态按正常转移并且最后从状态S5回到S0。

(2)在序列发生器产生序列不断循环过程中出现该序列110110100,此序列中也有一个要检测到的序列但是在状态团转移时同样需要注意:

110110100

S0S1S2S3S4S2S3S4S5S0

即当状态S4转移到S5状态时,如果此时序列值为1,则需要将状态转移至S2状态,从S2状态重新开始检测,而不需要转移至S0,之后其它状态正常转移并且最后由S5状态转移至S0状态。

从上面的流程图可以看出所有的回路在检测完一次序列后在下一次没有该序列时会流向初始状态S0,而当两个或多个被检测序列连续在一起时,状态S5会跳过状态S0直接转移至状态S1完成序列的的检测,直到检测完后再次回到初始状态S0,并且为了避免上面所讲的两种特殊序列在状态转移都进行了改进,在状态S2至状态S3时若序列值为1则返回自身,消除第一种特殊情况下序列的检测问题,在状态S4至状态S5时若序列值为1返回到状态S2,消除第二种特殊情况对1101016序列的检测。

3、此外在设计序列检测器时,为了使实验现象更明显,更好的观测序列的的移动与检测情况我使用了5个LED分别来显示最新产生的五个序列位,分别输出到端口ledag(4),ledag(3),ledag

(2),ledag

(1),ledag(0)实现程序语句如下

if(clk1hz'eventandclk1hz='1')then

ledag(4)<=ledag(3);---移位输出显示在led上以便观看

ledag(3)<=ledag

(2);

ledag

(2)<=ledag

(1);

ledag

(1)<=ledag(0);

ledag(0)<=xlout;--将最近生产的序列赋给最前端的ledge(0)位

endif;

4、设计计数器模块

因为序列发生器产生的序列不断地循环,待检测序列11010的个数很多,则在程序中设计计数模块,当序列检测器模块检测完一次待检测序列11010时产生一次下降沿,而计数器模块通过该下降沿进行计数自动加一,因为用两个数码管来表示待检测序列的个数,所以计数模块取上限为99即用数码管译码模块将计数值在数码管表示出来时最多能计99检测序列之后清零重新计数,这样设计之后比通过LED的亮灭来统计被检测序列的个数更加具体直观。

四、实验程序(程序来源于自己编写)

--总的设计模块如图所示:

--分频器模块

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

entityp1is

rt(clk:

instd_logic;

clk1hz:

outstd_logic--分频的频率1HZ的输出端口

);

endp1;

architecturebehaveofp1is

SignalClk_Count1:

std_logic_vector(13downto0);

begin

process(clk)--将10KHZ的频率分频成1HZ

begin

if(Clk'eventandClk='1')then

if(Clk_Count1<10000)then

Clk_Count1<=Clk_Count1+1;--在小于10000时,自动加1

else

Clk_Count1<="00000000000001";--超过10000后返回1

endif;

endif;

endprocess;

Clk1Hz<=Clk_Count1(13);--将Clk_Count1的第14位赋给Clk1Hz

endbehave;

--序列发生器模块

libraryieee;

useieee.std_logic_1164.all;

entityp2is

port

(clk1hz:

instd_logic;--定义输入端口此时频率为1HZ

xlout:

outstd_logic--输出序列发生器产生的序列端口

);

endentity;

architecturebhvofp2is

signalbs:

std_logic_vector(15downto0):

="0111010011011010";

begin

xlout<=bs(15);--将bs的第16位值赋给xlout

process(clk1hz)

begin

if(clk1hz'eventandclk1hz='1')then

bs<=bs(14downto0)&bs(15);--前15位保持不变,将bs的第16位并到最前来形成序列的循环

endif;

endprocess;

endbhv;

 

--序列检测器模块

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

entityp3is

port

(clr:

instd_logic;--清零端口

clk1hz:

instd_logic;--输入信号频率

xlout:

instd_logic;--输入序列

result:

outstd_logic

);

endentity;

architecturebhvofp3is

typestate_valueis(s0,s1,s2,s3,s4,s5);--定义6个状态

signalstate:

state_value;

signaldclk:

std_logic;

begin

result<=dclk;

process(clr,clk1hz)

begin

if(clr='0')thenstate<=s0;dclk<='0';--检测输入序列“11010”由左开始

elsif(clk1hz'eventandclk1hz='0')then

casestateis

whens0=>ifxlout='1'then--序列值为1S0转态S1,若序列值为0,返回自身

state<=s1;

elsestate<=s0;

endif;

whens1=>ifxlout='1'then

state<=s2;

elsestate<=s0;

endif;

whens2=>ifxlout='0'then--序列值为1,S2转向自身,序列值为0,转向S3

state<=s3;

elsestate<=s2;

endif;

whens3=>ifxlout='1'then

state<=s4;

elsestate<=s0;

endif;

whens4=>ifxlout='0'then--序列值为0,S4转向S5,输出端为1

state<=s5;dclk<='1';

elsestate<=s2;--若此时序列值为1,S4转向S2

endif;

whens5=>ifxlout='0'then--序列值1,S5转移至S1,若为0,转向S0

state<=s0;

elsestate<=s1;

endif;

dclk<='0';

whenothers=>state<=s0;--其它状态都将返回初始状态

endcase;

endif;

endprocess;

endbhv;

--100计数模块

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

entityp5is

port

(result:

instd_logic;--前面序列检测模块中检测到序列后产生的跳变信号

d6,d7:

outstd_logic_vector(3downto0)--定义十位个位数值

);

endentity;

architecturebehaveofp5is

signalcnt0,cnt1:

std_logic_vector(3downto0):

="0000";--初始化

begin

process(result)

begin

if(result'eventandresult='0')then

if(cnt0="1001"andcnt1="1001")then--设置计数上限为99

cnt0<="0000";cnt1<="0000";

elsif(cnt0="1001")then--BCD码的调整

cnt0<="0000";

cnt1<=cnt1+1;--接受跳变信号后自动加1计数

elsecnt0<=cnt0+1;

endif;

endif;

endprocess;

d6<=cnt1;d7<=cnt0;

endbehave;

--数码管译码模块

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

entityp6is

port(clk:

instd_logic;--扫描频率10KHZ的输入端口

sel0,sel1,sel2:

bufferstd_logic;--数码管的位选信号

sg:

outstd_logic_vector(6downto0);--数码管的段选

sel:

outstd_logic_vector(7downto0);

d6,d7:

instd_logic_vector(3downto0)--计数模块中个位十位的数值

);

endp6;

architecturebehaveofp6is

signalcnt:

std_logic_vector(1downto0);

signalA:

std_logic_vector(3downto0);

begin

process(clk)

begin

ifclk'eventandclk='1'then

ifcnt<"01"thencnt<=cnt+1;

elsecnt<=(others=>'0');

endif;

endif;

sel(0)<=sel0;

sel

(1)<=sel1;

sel

(2)<=sel2;

casecntis

when"00"=>sel2<='1';sel1<='1';sel0<='1';A<=d7;--选择数码管的位置

when"01"=>sel2<='1';sel1<='1';sel0<='0';A<=d6;

whenothers=>null;

endcase;

endprocess;

process(A)

begin

caseAis

when"0000"=>sg<="0111111";--数码管显示值为0时的译码值

when"0001"=>sg<="0000110";

when"0010"=>sg<="1011011";

when"0011"=>sg<="1001111";

when"0100"=>sg<="1100110";

when"0101"=>sg<="1101101";

when"0110"=>sg<="1111101";

when"0111"=>sg<="0000111";

when"1000"=>sg<="1111111";

when"1001"=>sg<="1101111";

whenothers=>null;

endcase;

endprocess;

endbehave;

--显示序列移动模块

libraryieee;

useieee.std_logic_1164.all;

useieee.std_logic_unsigned.all;

entityp4is

port(clk1hz:

instd_logic;--分频后的频率输入端口

xlout:

instd_logic;--序列发生器产生的序列

ledag:

bufferstd_logic_vector(4downto0)--5位序列值的输出口

);

endp4;

architecturebehaveofp4is

begin

process(clk1hz)

begin

if(clk1hz'eventandclk1hz='1')then

ledag(4)<=ledag(3);--序列值向左移动

ledag(3)<=ledag

(2);

ledag

(2)<=ledag

(1);

ledag

(1)<=ledag(0);

ledag(0)<=xlout;--将最近生产的序列赋给最前端的ledge(0)位

endif;

endprocess;

endbehave;

四.实验步骤

1.建立工程项目

2.在VHDL编辑窗口下写好程序,并保存

3、进行全编译,没有错误。

显示出状态机如图所示:

完全符合前面的设计思想,说明了程序的正确性。

4再新建波形仿真文件,引入端口,设置输入

5、

接下来就是波形仿真了,点击

,时序仿真,结果如下图所示

 

五、仿真波形分析

结合仿真图和图上的注释对设计的模块进行功能的检测。

由于序列产生的是0111010011011010,而要检测的序列是11010,因此,当检测到一个序列时,须经7或9的移位脉冲才能检测到下一个序列,根据第一个仿真图,可看出仿真是正确的。

由于总体的仿真正确了,所以对细节的仿真,例如:

序列是如何在移位脉冲的输入下输出的:

每检测到一个11010序列,数码管的具体输出是多少等,就不一一作分析了。

六、硬件测试

1.Assignments-.>device->

引脚锁定,参照下载实验板引脚号说明书,选择适当的引脚

2.引脚锁定后,保存,必须重新进行一次全程编译,编译通过后才能编程下载。

3.编程下载,用下载线将计算机并口和试验箱上的JTAG口接起来,接通电源。

选择Tools—>Programmer菜单,打开programmer窗口。

在mode中选中JTAG,将Program/Configure下的方框选中

4在开始编程之前,必须正确设置编程硬件。

点击“HardwareSetup”按钮,打开硬件设置口。

点击“AddHardware”打开硬件添加窗口,在“Hardwaretype”下拉框中选择“USB”,点击OK按钮确认,关闭HardwareSetup窗口,完成硬件设置。

5、点击“Start”按钮,开始编程下载

然后就可以根据实验要就进行检测,看是否能产生正确的序列,是不是在正确的状态计数等等功能。

七、硬件测试结果

(1)序列发生器测试结果,实验中产生了序列0111010011011010

而且产生的原理即为通过预先设计的一个序列0111010011011010,然后通过把最高位移至最低位后与其余不变的15位相并接形成一个新的序列,然后循环往复,便可循环的产生该序列例如:

第一步为0111010*********

第二次为1110100110110100

第三次为1101001101101001

第四次为1010*********1

为010*********1等等

然后继续循环相并即产生了序列0111010011011010

每一次的最高位都会输出到LED中显示,然后通过循环次数,不断地向右推进,例如上面所写的:

LED显示的是01110即灭、亮、亮、亮、灭,第五次的最高位0就是最近新产生的,而该LED就显示在锁定的ledag(4),ledag(3),ledag

(2),ledag

(1),

ledag(0)五个LED管中并且一一对应产生的序列值。

(2)序列检测器测试结果

当ledag(4),ledag(3),ledag

(2),ledag

(1),ledag(0)连接的二极管为亮、亮、灭、亮、灭时,数码管显示的数值会自动加一,说明检测到了一次待检测的序列11010。

原理上在一组序列中,在检测的序列0111010011011010中有两个11010,数码管应计数到2,但因为序列是循环的产生的,所以待检测的序列便可不断的产生,在每检测到一次待检测序列后数码管上会自动的加一直至到计数器设置的上限99后自动清零,而在实际操作中正如分析结果一样,每当五个二极管为亮、亮、灭、亮、灭时,数码管便自动加一,最终加到99然后清零。

理论与结果相匹配,所以实验成功。

八、实验心得体会

1、序列发生器模块:

开始使用状态机的方法去设计的,经老师提点发现用状态机做的话会增加FPGA的布线,所以改进了方法,利用循环移位的思想进行设计。

对应的程序是:

bs<=bs(14downto0)&bs(15);从而妥善的解决了该问题,说明了设计思想是有优劣之分的,同一个问题,可以有许多解决方法,但一定会有一个相对比较好的办法,因此需多思多实践。

然后将最高位不断地输出到设定的五个LED二极管中,通过移动位置,便可清楚的看到序列产生的过程。

当五个LED二极管出现亮、亮、灭、亮、灭时,数码管计数值加一,完成一次对待检测序列的检测。

2、序列显示移动模块:

正是因为增加了该模块,所以在上面所讲的序列发生器模块产生的序列便可以通过移动位置在LED二极管中显示出来,其原理就是通过将次高位的值赋给高位的值来实现位置的移动显示的。

但需要注意的是最后一位即ledag(0)是最新产生的序列值。

在序列发生器产生序列不断循环过程中出现该序列1110100,此序列中也有一个要检测到的序列但在状态转移过程需要注意:

即当S2状态转移到S3状态时,如果此时序列值为1,则只需转移到状态本身S2而不需要转移至S0,这样即可节约转移时间也可提高检测效率,之后的状态按正常转移并且最后从状态S5回到S0。

这在设计的过程中要非常注意,一旦设计出错了,设计结果将得不到意想的。

由于软件中可看到状态图,所以最好相比对一下,确保设计的的正确性。

九、参考资料

《EDA技术实用教程》潘松黄继业

《EDA实验指导书》丁杰朱启标

..

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 学习总结

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1