南昌大学实验报告学生姓名:学号:专业班级:中兴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”2.序列检测器序列检测器设计的关键在于正确码的收到必须是连续的,这就要求检测器必须记住前一次的正确码及序列,直到在连续的检测中收到的每一位码都与实验要求相同。
在此,必须利用状态转移图。
电路需要分别不间断记忆:初始状态、1、11、110、1101、11010共六种状态,状态转移如图:若检测到“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脉冲输出;--时间:2012年11月10号--版本:7.2--功能:分频器(2000分频)分频模块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 ISGENERIC(N:Integer:=20000);--此处定义了一个默认值N=10000,即电路为10000分频电路; Port(Clockin:IN STD_LOGIC;ClockOut:OUT STD_LOGIC);END;ARCHITECTURE Devider OF DIV ISSIGNAL Counter:Integer RANGE 0 TO N-1;SIGNAL Temp1:STD_LOGIC; --信号的声明在结构体内,进程外部BEGINPROCESS(Clockin)BEGINIF RISING_EDGE(Clockin) THENIF Counter=N-1 THENcounter<=0;Temp1<=Not Temp1;ELSECounter<=Counter+1;IF Counter=(N/2-1) THENTemp1<=NOT Temp1;END IF;END IF;END IF;END PROCESS;ClockOut<=Temp1;END;(2)序列发生器模块:(实体名为C_OUT)序列发生器模块如图2所示,其中:输入管脚: CLK为0.5hz的时钟脉冲;RST为复位信号;输出管脚:CO序列发生器设计时用于计数,实现模16计数,以产生16位的序列图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 ISPORT (CLK,RST:IN STD_LOGIC;--定义时钟和复位信号CO :OUT STD_LOGIC );--序列发生器设计时用于计数,实现模16计数,以产生16位的序列END C_OUT;----------------------------------------------------------------------------------------ARCHITECTURE behav OF C_OUT ISSIGNAL CQ1:STD_LOGIC_VECTOR(3 DOWNTO 0);--定义信号进行计数.实现模16计数,对应依次产生序列的位0到位15;SIGNAL Q: STD_LOGIC;BEGINPROCESS(CLK,RST,Q)BEGINIF RST='1' THEN CQ1<="0000"; Q<='0'; --如果复位,则计数器清0,M也清0 ELSIF CLK'EVENT AND CLK='1' THENCQ1<=CQ1+1; --时钟上升沿到来,Q开始计数,产生序列CASE CQ1 ISWHEN "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;--序列发生器到此结束CO<=Q;END behav;(3)序列检测模块:(实体名为SCHK)序列检测模块如图3所示,其中:输入管脚: CLK为0.5hz的时钟脉冲;EN为使能端,为1才正常工作;M为显示当前产生的位;输出管脚:N为显示满足序列要求时,产生‘1’,即为标志位。
图3--时间:2012年11月10号--版本:7.2--功能:检测指定的序列---------- SCHK ------------------------------------------------------------------------------LIBRARY IEEE ;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL;--为了重载ENTITY SCHK ISPORT(CLK,EN,M : IN STD_LOGIC; --EN为使能端,为1才正常工作;M为显示当前产生的位N : OUT STD_LOGIC); -N为显示满足序列要求时,产生‘1’,即为标志位END SCHK;----------------------------------------------------------------------------------------ARCHITECTURE behav OF SCHK ISTYPE 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;BEGINPROCESS(CLK,S,N1,EN) ---序列检测器进程BEGINIF EN='0' THENS<=S0; N1<='0';A5<='0';A4<='0';A3<='0';A2<='0';A1<='0';ELSIF CLK'EVENT AND CLK='0' THENN1<='0';CASE S ISWHEN 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时,产生标志信号图4--时间:2012年11月10号--版本:7.2--功能:16进制计数模块------------- COUNT -----------------------------------------------LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL;ENTITY COUNT ISPORT (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 ISBEGINPROCESS(CLK,EN,RST)V ARIABLE CQI:STD_LOGIC_VECTOR(3 DOWNTO 0);BEGINIF RST='1' THEN CQI:= (OTHERS=>'0');ELSIF CLK'EVENT AND CLK='1' THENIF EN='1' THENIF CQI<15 THENCQI:=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数码管位选信号图5--时间:2012年11月10号--版本:7.2--功能:将计数结果在数码管显示--------------- scan_led ---------------------------------LIBRARY IEEE;USE IEEE.STD_LOGIC_1164.ALL;USE IEEE.STD_LOGIC_UNSIGNED.ALL;ENTITY scan_led ISPORT(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 ISSIGNAL cout8:STD_LOGIC_VECTOR(2 DOWNTO 0);SIGNAL A :STD_LOGIC_VECTOR(3 DOWNTO 0);BEGINP1:PROCESS(cout8)—片选BEGINCASE cout8 ISWHEN "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)BEGINIF clk'EVENT AND clk ='1' THEN cout8 <= cout8+1;END IF;END PROCESS P2;P3:PROCESS(A)—译码BEGINCASE A ISWHEN "0000"=> scan <="0111111"; --0WHEN "0001"=> scan <="0000110"; --1WHEN "0010"=> scan <="1011011"; --2WHEN "0011"=> scan <="1001111"; --3WHEN "0100"=> scan <="1100110"; --4WHEN "0101"=> scan <="1101101"; --5WHEN "0110"=> scan <="1111101"; --6WHEN "0111"=> scan <="0000111"; --7WHEN "1000"=> scan <="1111111"; --8WHEN "1001"=> scan <="1101111"; --9WHEN "1010"=> scan <="1110111"; --AWHEN "1011"=> scan <="1111100"; --BWHEN "1100"=> scan <="0111001"; --CWHEN "1101"=> scan <="1011110"; --DWHEN "1110"=> scan <="1111001"; --EWHEN "1111"=> scan <="1110001"; --FWHEN OTHERS=> NULL;END CASE;END PROCESS P3;END;2.包装元件入库。