实验四序列发生器
南昌大学实验报告
学生姓名: 学 号: 专业班级:中兴101班
实验类型:□验证 □综合 ■设计 □创新 实验日期:2012、11、16 成绩:
实验四 序列信号发生器与检测器设计
一、实验目的
1、学习VHDL文本输入法 2、学习有限状态机的设计
3、利用状态机实现串行序列的输出与序列的检测 4、继续学习优化设计
二.实验内容与要求
1. 设计序列发生器,完成序列为0111010011011010的序列生成器 2.用有限状态机设计序列检测器,实现串行序列11010的检测器 3. 若检测到符合要求的序列,则输出显示位为“1”,否则为“0” 4. 对检测到的次数计数
5.整个工程采用顶层文件+底层模块的原理图或文本的设计思路
三、实验仪器
PC机、Quartus II软件、EDA实验箱
四、实验思路
1. 设计序列发生器
基本思想为一个信号CQ1计数,给另一个信号CO(代表序列的每一位)赋值的方法:
先设定端口CQ1用于产生序列时计数,因为序列共16位,因此端口CQ1为标准逻辑矢量,位宽为4,设另一个端口M代表序列的每一位,CQ1每计一个数,就给M赋一个值,这样产生一个16位的序列。由于端口不能参与相关运算,因此在结构体中我分别定义了信号CQ1(标准逻辑矢量,位宽4),信号Q与相应的端口CQ1 CO对应,在进程中参与相应的运算,在程序的最后再用端口接收信号: CO<=Q;
在进程中我采用case – when 语句,如当CQ1为“0000”的时候,给另一信号Q赋‘0’,当CQ1为“0001”时,为Q赋‘1’以此类推,且让CQ1产生循环,即可源源不断的产生所需序列了,如下表 CQ1 Q CQ1 Q 0000 0 1000 1 0001 1 1001 1 0010 1 1010 0 0011 1 1011 1 0100 0 1100 1 0101 1 1101 0 0110 0 1110 1 0111 0 1111 0 2. 序列检测器
序列检测器设计的关键在于正确码的收到必须是连续的,这就要求检测器必须记住前一次的正确码及序列,直到在连续的检测中收到的每一位码都与实验要求相同。在此,必须利用状态转移图。
电路需要分别不间断记忆:初始状态、1、11、110、1101、11010共六种状态,状态转移如图:
1
1 1 0 1 0 S0 S1 S2 S3 S4 S5 0 0 1 1 1
若检测到“11010”序列,则输出信号N为1,定义VARIABLE X:STD_LOGIC_VECTOR (3 DOWNTO 0)进行计数,最后把变量X赋给输出SS,在数码管上显示检测到序列“11010”的次数。
3.时钟脉冲的选择
数码管显示的扫描时钟需要很快的速度,因此采用1KHz频率的时钟;而序列发生器,为了能够人眼识别亮灭,则我选择采用2000分频之后得到的0.5Hz频率
五.原理图输入法设计(程序来源:基本上独立完成) 1. 建立文件夹
建立自己的文件夹(目录),如c:\\myeda,进入Windows操作系统 Quartus II不能识别中文,文件及文件夹名不能用中文。 2. 原理图设计输入
打开Quartus II,选菜单File→New,选择“Device Design File->Block Diagram->Schematic File”项。点击“OK”,在主界面中将打开 “Block Editor”窗口。
(1) 分频器模块:(实体名为DIV)
本设计使用的FPGA开发板中使用的芯片是Cyclone II EP2C35F672C8,使用的是10kHz的时钟脉冲输入,根据电路的具体设计需要,对其进行分频设计。
如图1所示为系统的分频模块,其中模块Clockout管脚输出为0.5hz的时钟脉冲,得出序列发生器和序列检测器模块正常工作的时钟信号,在Clockin管脚输出为一个1khz的时钟脉冲,作用与动态扫描模块的正常工作。
输入管脚:Clockin为1khz脉冲输入; 输出管脚:Clockout为0.5hz脉冲输出;
ParameterValueN2000fenpinClockinClockOutinst5 图1 --时间:2012年11月10号 --版本:7.2
--功能:分频器(2000分频)
2
分频模块DIV源代码div.vhd如下:
-------分频程序,从1KHZ中得到0.5HZ的计数频率,2000分频---------- LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL; --这3个程序包足发应付大部分的VHDL程序设计 USE IEEE.STD_LOGIC_Arith.ALL; USE IEEE.STD_LOGIC_Unsigned.ALL;
ENTITY DIV IS
GENERIC(N:Integer:=20000);--此处定义了一个默认值N=10000,即电路为10000分频电路; Port(Clockin:IN STD_LOGIC;
ClockOut:OUT STD_LOGIC); END;
ARCHITECTURE Devider OF DIV IS
SIGNAL Counter:Integer RANGE 0 TO N-1; SIGNAL Temp1:STD_LOGIC; --信号的声明在结构体内,进程外部 BEGIN PROCESS(Clockin) BEGIN
IF RISING_EDGE(Clockin) THEN IF Counter=N-1 THEN counter<=0; Temp1<=Not Temp1; ELSE Counter<=Counter+1; IF Counter=(N/2-1) THEN Temp1<=NOT Temp1; END IF; END IF; END IF; END PROCESS; ClockOut<=Temp1; END;
(2) 序列发生器模块:(实体名为C_OUT) 序列发生器模块如图2所示,其中 : 输入管脚: CLK为0.5hz的时钟脉冲; RST为复位信号;
输出管脚:CO序列发生器设计时用于计数,实现模16计数,以产生16位的序列
C_OUTCLKCORSTinst 3
图2
--时间:2012年11月10号 --版本:7.2
--功能:产生一个十六位的指定序列
-----------------C_OUT------------------------------------------------------------------ LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;--为了重载 ENTITY C_OUT IS
PORT (CLK,RST:IN STD_LOGIC;--定义时钟和复位信号
CO :OUT STD_LOGIC ); --序列发生器设计时用于计数,实现模16计数,以产生16位的序列
END C_OUT;
---------------------------------------------------------------------------------------- ARCHITECTURE behav OF C_OUT IS
SIGNAL CQ1:STD_LOGIC_VECTOR(3 DOWNTO 0);--定义信号进行计数.实现模16计数,对应依次产生序列的位0到位15; SIGNAL Q: STD_LOGIC; BEGIN
PROCESS(CLK,RST,Q) BEGIN
IF RST='1' THEN CQ1<=\"0000\"; Q<='0'; --如果复位,则计数器清0,M也清0 ELSIF CLK'EVENT AND CLK='1' THEN
CQ1<=CQ1+1; --时钟上升沿到来,Q开始计数,产生序列 CASE CQ1 IS
WHEN \"0000\" =>Q<='0'; WHEN \"0001\" =>Q<='1'; WHEN \"0010\" =>Q<='1'; WHEN \"0011\" =>Q<='1'; WHEN \"0100\" =>Q<='0'; WHEN \"0101\" =>Q<='1'; WHEN \"0110\" =>Q<='0'; WHEN \"0111\" =>Q<='0'; WHEN \"1000\" =>Q<='1'; WHEN \"1001\" =>Q<='1'; WHEN \"1010\" =>Q<='0'; WHEN \"1011\" =>Q<='1'; WHEN \"1100\" =>Q<='1'; WHEN \"1101\" =>Q<='0'; WHEN \"1110\" =>Q<='1'; WHEN \"1111\" =>Q<='0'; END CASE; END IF;
END PROCESS;--序列发生器到此结束
4
CO<=Q; END behav;
(3)序列检测模块:(实体名为SCHK) 序列检测模块如图3所示,其中 : 输入管脚: CLK为0.5hz的时钟脉冲;
EN为使能端,为1才正常工作; M为显示当前产生的位;
输出管脚:N为显示满足序列要求时,产生‘1’,即为标志位。
SCHKCLKENMinstN 图3
--时间:2012年11月10号 --版本:7.2
--功能:检测指定的序列
---------- SCHK ------------------------------------------------------------------------------ LIBRARY IEEE ;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;--为了重载 ENTITY SCHK IS
PORT(CLK,EN,M : IN STD_LOGIC; -- EN为使能端,为1才正常工作;M为显示当前产生的位 N : OUT STD_LOGIC); -N为显示满足序列要求时,产生‘1’,即为标志位 END SCHK;
---------------------------------------------------------------------------------------- ARCHITECTURE behav OF SCHK IS
TYPE STATE IS(S0,S1,S2,S3,S4,S5);---状态机的定义,5个状态 SIGNAL S:STATE;
SIGNAL A1,A2,A3,A4,A5:STD_LOGIC; --SIGNAL Q : INTEGER RANGE 0 TO 5 ;
--SIGNAL D : STD_LOGIC_VECTOR(4 DOWNTO 0); SIGNAL N1:STD_LOGIC; BEGIN
PROCESS(CLK,S,N1,EN) ---序列检测器进程 BEGIN
IF EN='0' THEN S<=S0; N1<='0';
A5<='0';A4<='0';A3<='0';A2<='0';A1<='0'; ELSIF CLK'EVENT AND CLK='0' THEN
5
N1<='0'; CASE S IS
WHEN S0 => if M='1' then S<=S1;else S<=S0;end if; WHEN S1 => if M='1' then S<=S2;else S<=S0;end if; WHEN S2 => if M='0' then S<=S3;else S<=S2;end if; WHEN S3 => if M='1' then S<=S4;else S<=S0;end if;
WHEN S4 => if M='0' then S<=S5; ----生成一个11010序列 N1<='1'; else S<=S2;
end if;--11011010里有一个,同时计数 WHEN others=> S<=S0; END CASE;
A5<=A4;---移位输出显示在led上以便观看 A4<=A3; A3<=A2; A2<=A1;
A1<=M;--将最近生产的序列赋给最前端的A1位 end if;
N<=N1;--显示检测到11010,检测到时它为高电平,它所对应二极管亮,否则二极管灭 END PROCESS; END behav ;
(4)16进制计数模块(实体名:COUNT) 16进制计数模块如图4所示,其中 :
输入管脚: CLK为检测到一个序列产生一个脉冲; RST为计数复位信号; EN为使能端;
输出管脚:Q [3..0]为计数的个位;
COUNT计数达到15时,产生标志信号
COUNTCLKQ[3..0]RSTCOUTENinst 图4
--时间:2012年11月10号 --版本:7.2
--功能:16进制计数模块
------------- COUNT ----------------------------------------------- LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY COUNT IS
6
PORT (CLK,RST,EN :IN STD_LOGIC;
Q:OUT STD_LOGIC_VECTOR(3 DOWNTO 0); COUT: OUT STD_LOGIC ); END ENTITY COUNT;
---------------------------------------------------------------------------------------- ARCHITECTURE ONE OF COUNT IS BEGIN
PROCESS(CLK,EN,RST)
VARIABLE CQI:STD_LOGIC_VECTOR(3 DOWNTO 0); BEGIN
IF RST='1' THEN CQI:= (OTHERS=>'0'); ELSIF CLK'EVENT AND CLK='1' THEN IF EN='1' THEN IF CQI<15 THEN CQI:=CQI+1; ELSE CQI:=\"0000\"; END IF; END IF; END IF;
IF CQI=15 THEN COUT<='1'; ELSE COUT<='0'; END IF; Q<=CQI;
END PROCESS COUNT; END ARCHITECTURE ONE;
(5)数码管显示模块(实体名:scan_led) 数码管显示模块如图5所示,其中 : 输入管脚: CLK为1khz的时钟脉冲;
data1[3..0]为要显示的数的个位; data2[3..0] 为要显示的数的十位; 输出管脚:
scan数码管显示码
choose数码管位选信号
scan_ledclkscan[6..0]data1[3..0]choose[2..0]data2[3..0]inst7 图5
--时间:2012年11月10号 --版本:7.2
--功能: 将计数结果在数码管显示
7
--------------- scan_led --------------------------------- LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY scan_led IS
PORT(clk : IN STD_LOGIC; data1,data2
: IN STD_LOGIC_VECTOR(3 DOWNTO 0);
scan : OUT STD_LOGIC_VECTOR(6 DOWNTO 0);-- scan数码管显示码
choose: OUT STD_LOGIC_VECTOR(2 DOWNTO 0));-- choose数码管位选信号END ENTITY;
ARCHITECTURE one OF scan_led IS
SIGNAL cout8:STD_LOGIC_VECTOR(2 DOWNTO 0); SIGNAL A :STD_LOGIC_VECTOR(3 DOWNTO 0); BEGIN
P1:PROCESS(cout8)—片选 BEGIN
CASE cout8 IS
WHEN \"000\" => choose <= \"000\"; A <= data1; WHEN \"001\" => choose <= \"001\"; A <= data2; WHEN \"010\" => choose <= \"010\"; A <= \"0000\"; WHEN \"011\" => choose <= \"011\"; A <= \"0000\"; WHEN \"100\" => choose <= \"100\"; A <= \"0000\"; WHEN \"101\" => choose <= \"101\"; A <= \"0000\"; WHEN \"110\" => choose <= \"110\"; A <= \"0000\" ; WHEN \"111\" => choose <= \"111\"; A <= \"0000\"; WHEN OTHERS => NULL; END CASE; END PROCESS P1; P2:PROCESS(clk) BEGIN
IF clk'EVENT AND clk ='1' THEN cout8 <= cout8+1; END IF;
END PROCESS P2; P3:PROCESS(A)—译码 BEGIN CASE A IS WHEN \"0000\"=> scan <=\"0111111\"; --0 WHEN \"0001\"=> scan <=\"0000110\"; --1 WHEN \"0010\"=> scan <=\"1011011\"; --2 WHEN \"0011\"=> scan <=\"1001111\"; --3 WHEN \"0100\"=> scan <=\"1100110\"; --4 WHEN \"0101\"=> scan <=\"1101101\"; --5 WHEN \"0110\"=> scan <=\"1111101\"; --6
8
WHEN \"0111\"=> scan <=\"0000111\"; --7 WHEN \"1000\"=> scan <=\"1111111\"; --8 WHEN \"1001\"=> scan <=\"1101111\"; --9 WHEN \"1010\"=> scan <=\"1110111\"; --A WHEN \"1011\"=> scan <=\"1111100\"; --B WHEN \"1100\"=> scan <=\"0111001\"; --C WHEN \"1101\"=> scan <=\"1011110\"; --D WHEN \"1110\"=> scan <=\"1111001\"; --E WHEN \"1111\"=> scan <=\"1110001\"; --F WHEN OTHERS=> NULL; END CASE; END PROCESS P3; END;
2.包装元件入库。
编译通过后,单击File→Create Default Symbol,当前文件变成了一个包装好的自己的单一元件,并被放置在工程路径指定的目录中以备后用。 3.保存各个模块的原理图 单击File→Save as„按扭,出现对话框,选择自己的目录(如c:\\myeda),合适名称保存刚才输入的原理图,原理图的扩展名为.bdf。 4.设置工程文件(Project) 以EXP4为工程名命名 5. 选择目标器件 6. 放置元件
7. 添加连线
将以上各器件连接成实验原理图如下:
图6 原理图设计
8. 编译(Compiler)
单击→Quartus II Compiler,跳出Compiler窗口,此编译器的功能包括网表文件的提取、设计文件的排错、逻辑综合、逻辑分配、适配(结构综合)、时序仿真文件提取和编程下载文件装配等。单击Start,开始编译!如果发现有错,排除错误后再次编译。 7. 仿真,测试项目的正确性(仅对计数模块进行仿真测试) 1)建立新的波形激励文件 2)在波形编辑器窗口添加节点
9
3)通过Edit->End Time 来设定仿真结束时间为1ms 4)在CLOCK窗口中设置clk的时钟周期为10ns 时间设置如下:
5)点击save保存,输入波形如下:
6) 通过Tools下的Simulator Tools项进行仿真,然后观察输出波形。 仿真波形以及分析如下: 初步检验:
10
对上述问题进行调整
对序列发生器的考察: 当使能端EN=1,RST=0时产生序列“0111010011011010”
对检测器进行考察:
11
当产生一个“11010”时,N增1,
对序列发生器清零端进行考察:
当RST=0时,序列输出端CO=0,不产生序列,且计数器保持原始计数
对计数器的考察:
12
当计数到达15时,count=1,且从零开始计数
对计数清零端进行考察:
当RST1=1时,脉冲仍然正常产生,但是计数清零,为0时,重新计数
对状态图的考察
13
由上可知,仿真结果与要求一致!
六、引脚锁定和编程下载 1.Assignments-.>device->
引脚锁定,参照下载实验板1K100的引脚号说明书,选择适当的引脚
2.引脚锁定后,保存,必须重新进行一次全程编译,编译通过后才能编程下载。 3、编程下载,用下载线将计算机并口和试验箱上的JTAG口接起来,接通电源。 选择Tools—>Programmer菜单,打开programmer窗口。 在mode中选中JTAG,将Program/Configure下的笑方框选中
4在开始编程之前,必须正确设置编程硬件。点击“Hardware Setup”按钮,打开硬件设置口。 点击“Add Hardware”打开硬件添加窗口,在“Hardware type”下拉框中选择“ByteBlasterMV or ByteBlaster II”,“Port”下拉框中选择“LPT1”,点击OK按钮确认,关闭Hardware Setup窗口,完成硬件设置。
5、点击“Start”按钮,开始编程下载
图(14)下载成功
14
七、硬件测试结果
(1)序列发生器测试结果,实验中产生了序列0111010011011010 CQ1 Q CQ1 Q 0000 0 1000 1 0001 1 1001 1 0010 1 1010 0 0011 1 1011 1 0100 0 1100 1 0101 1 1101 0 0110 0 1110 1 0111 0 1111 0 而且产生的原理即为:看到的现象即为Q连接的数码管从0到15计数时,co连接的二极管会依次出现:
灭、亮、亮、亮、灭、亮、灭、灭、亮、亮、灭、亮、亮、灭、亮、灭 即产生了序列0111010011011010 (2)序列检测器测试结果
当产生的序列为11010时,与N相连的led灯亮,其余时刻灭。即说明检测到一个目标序列。 在一组序列中,在检测的序列0111010011011010中检测到两个11010,N所连接的LED亮了两次,Q计数到2,与分析结果相符合。 (3)计数器的测试结果
当led灯亮一次时,数码管以模16进行计数,通过数码管可以知道检测到多少个目标序列。 (4)使能端、复位键的测试结果
当拨下计数清零端时,数码管重新计数;当拨下序列发生清零端时,重新产生序列。
综上,实验现象与软件仿真以及程序分析的结果一致,可知实验很成功! 八、试验心得
通过本次实验我更加熟悉状态机的使用,还有移位显示输出的设计,加深了我对序列信号检测器基本原理的理解,并对状态机的使用环境和方法有了进一步的了解,掌握了用状态机设计模块的基本方法和思路。然而在设计时也遇到了一些问题,刚开始状态转换没设置好,结果导致状态转换出了问题,使得无论输入是否为有效序列,输出检测计数错误的问题,后经仔细排查,终于将问题解决。
本次实验的目的在于学习一般有限状态机的设计。状态机包括时序逻辑部分(存储部分)和组合逻辑部分(控制部分),其内部和输出经过一可预测的状态序列。因此设计状态机一般先根据具体问题明确控制输入、条件转换,再画出状态图,做出状态列表。利用VHDL设计状态机一般包括时序进程和组合进程两个主要部分常常使用CASE语句,条件的转换则可用CASE中的IF语句。
通过此次实验,我对设计所用到的软件有了更加深刻地了解,这对我们以后的工作和学习的帮助都很有用处。在以后的学习中应该多多的注意实践知识的训练和积累。在以后的学习生活中要不断的开拓自己的动手能力,不断的训练自己的动手能力。
感谢老师一直细心地提问,使我明白了一些知识上的漏洞! 九、参考资料
《EDA技术实用教程》 潘松 黄继业 《EDA实验指导书》 丁杰 朱启标
15
因篇幅问题不能全部显示,请点此查看更多更全内容