《2022年通信与电子系统综合设计实验报告系.docx》由会员分享,可在线阅读,更多相关《2022年通信与电子系统综合设计实验报告系.docx(40页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、 通信与电子系统综合设计院系: 信息学院6系 姓名: 学号: 邮箱 手机: 2013年12月27日设计一 实现FPGA对CPLD外设的全部利用实验要求 编写CPLD程序控制其外设(LED,数码管,输入开关等),并全部提供给FPGA使用 编写CPLD与FPGA(XC2V2000)的接口电路,实现FPGA与CPLD外设的直接对应关系. 编写FPGA程序测试CPLD的全部外设实验说明1.硬件分析本次实验涉及的硬件包括:4个脉冲触发开关、8个拨码开关、8个7段数码管、32个LED发光二极管以及如图1.1所示的CPLD和FPGA芯片。0/1开关 8位脉冲开关 4位LED 32位数码管 8位Xilinx
2、CPLDXC95114XLXilinx FPGAXC2V2000图1.1 硬件连接图2.实验要求分析要求通过FPGA对CPLD的全部外设进行控制,如果不进行编码则需要4+8+32+16=60根连接线,而实际只有23条,在这种情况下,对于8位拨码开关,可以在CPLD中对进行并串转换,8位需要3位地址线,再用一位表示指定地址的拨码开关的状态,这样就可以用4位将8位拨码开关信号传输到FPGA,在FPGA中将4位表示拨码开关的信号进行串并转换,得到8位信号,然后用这8位信号控制8个7段数码管,用高4位信号表示段码,再用低四位实现功能控制,最多有16种。对于4个脉冲开关,可直接传输,在FPGA中,用这4
3、位信号实现对32位LED发光二极管进行控制;此外,8个7段数码管,需要3根地址线和4根数据线,32个LED发光二极管,需要5根地址线和1位状态位,状态位用来表示指定地址的LED的状态。通过上述分析,总共需要4+4+3+4+5+1=21根连接线,不超过实际的23条连接线,所以上述方案是可实现的。图1.2为FPGA控制CPLD外设的结构示意图。4位脉冲开关信号,4位拨码开关信号(先并串转换在串并转换)外设CPLDFPGALED控制信号(5位地址+1位状态)数码管控制信号(3位位选+4位段码)CPLD和外设连接图1.2 FPGA控制CPLD外设的结构示意图设计方案1. CPLD程序设计CPLD程序分
4、为以下几个功能模块:首先对八位拨码开关信号进行并串转换传输到FPGA中;对脉冲开关信号进行处理,每按一次脉冲开关,经过程序处理得到0或1传输到FPGA;对FPGA传输过来的5位LED地址、数码管3位位选信号和4位段码信号进行译码然后将译码之后的信号传输到外设。CPLD程序主要结构图如如1.3所示。图1.3 CPLD程序结构图a) 并串转换8位拨码开关信号进入CPLD后对其进行并串转换,转换后用4位信号表示,其中高3位表示拨码开关地址,最低位表示开关的状态。在程序模块,用一个3位计数器,每一次时钟上升沿到来时计数器加1,然后根据计数器的值进行选择转换,程序如下:process(clk,dip,c
5、ounter)beginif(clkevent and clk=1)thenif counter=111 thencounter=000;elsecounter dip_sw dip_sw dip_swdip_sw=111&dip(7);end case;end process;b) 脉冲开关信号处理每按一次脉冲开关,对其脉冲信号进行处理,得到1位信号0或1然后传输到FPGA。其处理的程序如下(4个脉冲开关处理过程一样):process(key1)variable K1 : std_logic;beginif key1event and key1=1 then K1:=not(K1);end
6、if;pul_sw1 led(0) led(1) led(30) led(31)=led_val;end case;end if;end process;d) 数码管位选和段码译码 FPGA传输过来的3位位选信号和4位段码信号,需要在CPLD中对其进行译码,然后直接传输到外设。其代码见附录中实验1的CPLD完整代码。2. FPGA程序设计在FPGA程序中,首先要对系统48MHz时钟进行两次分频得到10KHz和1Hz的时钟,其中10KHz时钟用于LED和数码管进程控制,1Hz时钟用于循环功能控制;其次要对CPLD传输过来的拨码开关的4位串行信号进行串并转换得到8位信号;LED驱动模块包括LED功
7、能控制进程、LED循环控制进程以及计数最大为32的计数器(在进程中指定LED的位置);数码管驱动模块包括数码管功能控制进程、数码管循环控制进程和一个32bit计数器。由于FPGA的VHDL代码较长,见附录中实验1的FPGA完整代码。图1.4为FPGA程序结构图。3位脉冲信号LED循环控制进程数码管进程控制模块数码管循环控制进程LED功能控制进程4位串行信号串并转换1Hz时钟计数器1Hz时钟10KHz时钟10KHz时钟32位计数器图1.4 FPGA程序结构图a) 时钟分频FPGA硬件系统接的时钟频率是48MHz,在程序中要对其进行分频。通过两次分频得到频率为10KHz和1Hz的时钟。10KHz主
8、要用于LED和数码管的动态扫描;1Hz的时钟用于LED和数码管的循环功能。b)LED功能控制模块 标号为pul_s1、pul_s2、pul_s3和pul_s4的用于对LED的控制。pul_s2和pul_s1组成2位二进制数用于表示LED实现何种功能;pul_s3用于计数值最大为32的计数器的触发控制,pul_s3每按下一次计数器计数值(LED_cnt)加1,用于指定LED的地址;pul_s4用于功能实现中子功能的选择。四个脉冲开发和LED功能的关系如表1.1。表1.1 四个脉冲开关与LED功能对应关系c)数码管功能控制模块拨码开关4位串行信号在FPGA中转换成8位并行信号dip(7 downt
9、o 0)后用于控制数码管功能实现。高四位dip(7 downto 4)用作功能状态位,可以实现16种功能,但在本程序中只设计了7种功能;低四位dip(3 downto 0)用于数码管段码控制;此外,数码管的其中两个功能是关于计数器counter的,8个数码管显示32位计数器加减计数,计数器每隔1秒加1或减1。dip(7 downto 0)与数码管的功能如表1.2所示。表1.2 dip与数码管功能的关系设计结果因为这个实验分为CPLD设计和FPGA设计,故实验程序仿真也分为两部分。1. CPLD仿真图1.5黄颜色部分是8位拨码开关信号并串转换的波形,每个时钟上升沿是转换其中一位,每完成一次转换需
10、要8个时钟周期;蓝颜色和淡粉色的部分分别是4位段码信号和3位位选信号的译码。图1.5 CPLD仿真波形1图1.6是LED地址译码过程,每个时钟上升沿到来时将led_value的值赋给指定地址的LED,每完成一次需要32个时钟周期。图1.6 CPLD仿真波形22. FPGA仿真图1.7是LED功能的仿真波形,包括全亮、全灭和循环移动的仿真波形。图1.7 LED功能仿真波形图1.8至图1.11是数码管各个功能的仿真波形,具体功能见图下方的标注。图1.8 数码管循环移动功能图1.9 数码管显示7(可设置)并循环移动图 1.10 数码管显示32位16进制计数器图1.11 数码管静态显示FDB75310
11、设计总结本次实验由于涉及到CPLD和FPGA的综合设计,所以花费的时间比较长。其中CPLD的设计较为简单,基本是并串转换和译码之类的;而FPGA的设计相对来说复杂很多,主要是其包含了LED和数码管各种功能的设计。在设计过程中,代码的设计看似逻辑正确,但在硬件上实现的时候结果却不是原本所期望的,比较深的感受是,一开始把LED和数码管循环控制的代码都放在LED、数码管功能控制进程中,但却不能实现循环功能,后来分别设计了一个LED和数码管的循环控制子进程,时钟选用1Hz,然后让其和主功能模块连接起来就达到预期的目标了。设计二 AD/DA控制及ChipScope使用实验要求 FPGA控制AD/DA双通
12、道最高速度下工作 学习ChipScope分析工具,并利用其观看AD或DA数字接口的数据实验说明本实验中用到的AD芯片AD9021和DA芯片AD9761都有两个通道(I通道和Q通道),用信号发生器产生两路不同(幅度、频率或波形不同)的信号分别接至AD9021的I通道和Q通道,AD9021的输出信号进入FPGA中经过相应处理传送到AD9761的输入端,经过AD9761数模转换处理之后得到两路模拟信号分别从I通道和Q通道输出,然后接至示波器的两个观测通道,观察波形。整个系统的硬件结构图如图2.1所示。I低通滤波器信号发生器1V直流偏置AD: AD9021Xilinx FPGAXC2V2000 -4
13、FG676Q低通滤波器1V直流偏置I示波器差分转单端DA: AD9761Q差分转单端图2.1 系统硬件结构图设计方案在设计之前,首先要了解模数转换芯片AD9021和数模转换芯片AD9761的参数和工作原理,之后才能做进一步的设计。1.AD9021与AD9761的简单介绍a)模数转换芯片AD9021AD9201 是一个双通道、10-bit CMOS 模数转换器(ADC),采样速度为20MSPS。 图2.2给出了AD9021的功能框图,包括 2个10-bit、20MSPS 的 ADC,2个输入缓存放大器,一个内部参考电压和复用的数字输出缓存器。图2.2 AD9021的功能框图AD9201 内部集成
14、了 2个ADC、2个模拟输入缓冲器、一个内部基准和基准缓冲器,以及一个输出复用器(multiplexer)。2个 ADC 分别用 I 通道和 Q 通道来表示,它们在输入时钟的上升沿同时对各自的输入信号进行采样。每个 ADC 都有自己的输出寄存器,寄存器的内容在输入时钟的上升沿更新。两个 ADC 寄存器中的结果是通过 SELECT 信号来进行选择的,从图 2.2 中可以看出,SELECT 为低电平时,选择 Q 通道输出;SELECT 为高电平时,选择 I通道输出。图2.3 AD9021时序图b)数模转换芯片AD9761AD9761 是一种双通道、高速、10-bit 的CMOS 数模转换器(DAC
15、),特别适用于包括 I 路和 Q 路数字信息处理的宽带通信应用场合(例如扩频通信)。AD9761 集成了两个 10-bit、40MSPS 的 DAC,两个2倍插值滤波器,一个参考电源和数字输入接口电路,如图2.4所示。该器件支持两个输入通道,每个通道的数据率为 20MSPS,经过两倍的插值,使得两个DAC同时输出最高达40 MSPS 的数据。图2.4 AD9761功能框图图2.5给出了AD9761 的工作时序图。在 DAC 的输入数据线 DB9DB0上,I 路和 Q 路数据交替输入。SELECT 为 I 路和 Q 路的选择信号,当 SELECT为高电平时,输入数据送 I 路的 DAC,当 SE
16、LECT 为低电平时,输入数据送 Q路的 DAC。WRITE 信号是写输入信号。DAC 的输入寄存器在 WRITE 的上升沿锁存数据。CLOCK 是时钟信号。两个 DAC 的输出都在 CLOCK 的上升沿更新,同时数字滤波器分别读取各自的输入寄存器。图 2.5 中,CLOCK的上升沿比WRITE 的上升沿延迟tCINV,但 CLOCK 和 WRITE 也可以连接在一起。图2.5 AD9761功能框图2.FPGA设计简单介绍完AD9021和AD9671的功能和时序后,就可以进一步进行FPGA设计。首先要考虑AD9021和AD9761的时钟问题,因为AD9201 是一个双通道、10-bit CMO
17、S 模数转换器(ADC),采样速度为20MSPS,所以可以采用频率为20Mhz的时钟, AD9021的SELECT的频率也为20MHz,每个ADC都有自己的输出寄存器,寄存器的内容在输入时钟的上升沿更新,两个ADC寄存器中的结果是通过 SELECT 信号来进行选择的,从图 2.3 中可以看出,SELECT为低电平时,选择 Q 通道输出;SELECT为高电平时,选择I通道输出。对于AD9761,时钟的频率可以选择为40MHz,因为AD9761集成了两个10bit、40MSPS的DAC,该器件支持两个输入通道,这样每个通道的数据率为20MSPS,经过两倍的插值,使得两个DAC同时输出最高达40MS
18、PS的数据,同时AD9761的SELECT的输入也选择为20MHz的时钟。由上述可知,在FPGA设计中需要用到频率分别为40MHz和20MHz的时钟,而FPGA选择的时钟频率为48MHz,需要对其分频或倍频。在FPGA中添加一个IP核用于生成40MHz的时钟,IP核的参数设置如图2.6所示。图2.6 时钟IP核的参数设置然后对生成的40MHz的时钟进行二分频便得到20MHz的时钟,其二分频代码如下。process(clk40Mhz)beginif clk40Mhzevent and clk40Mhz=1 then clk20Mhz=not(clk20Mhz);end if;end proces
19、s;FPGA中对于各种输入信号设置如下。ADC_CS = 0;ADC_SLEEP = 0;DAC_RST = 0;ADC_CLOCK=clk20Mhz;ADC_SELECT=clk20Mhz;DAC_CLOCK=clk40Mhz;DAC_WRITE=clk40Mhz;DAC=ADC;DAC_SELECT d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da db dc dd de df null;end case;elsif rd=0 thencase addr iswhen 0000= data data data data data data data data data da
20、ta data data data data data data null;end case;elsedata=ZZZZZZZZZZZZZZZZ;end if;else data=ZZZZZZZZZZZZZZZZ;end if; end process;2. DSP设计DSP通过EMIF接口对FPGA中的存储器进行访问。从硬件电路的连接关系可知,FPGA处于DSP的CE2空间,其首地址为0xA0000000.通过向改地址写入20位数据(低4位为地址,高16位为数据),可实现DSP向FPGA中存储器写入的操作。读数据时,先给出地址(低4位),然后再读出。首先要设置DSP相关寄存器,根据DSP中控
21、制寄存器的地址分配,对相应的控制寄存器作如下定义:#define EMIFA_GBLCTL 0X01800000 /EMIFA 全局控制#define EMIFA_CE2CTL 0X01800010 /EMIFA CE2空间控制寄存器#define EMIFA_CE2SCE 0X01800050 /EMIFA CE2辅助控制寄存器#define ADDRESS 0XA0000000 /选择CE2:0xA0000000 根据DSP EMIFA手册,在程序中可以对以上控制寄存器进行如下配置:*(volatile u32*)EMIFA_GBLCTL=(u32)0x00010020;/把clk2打开*
22、(volatile u32*)EMIFA_CE2CTL=(u32)0XFFFFFF13;/16位异步对应通信2*(volatile u32*)EMIFA_CE2SCE=(u32)0x00000002;写函数代码如下,每次向存储器中写入一个16bit数据,总共写16次,第一次写入0x00ff,然后每次写入的数据是前一个数据减去0x0010,这样写入存储器中的数据依次为:0x00ff、0x00ef、0x00df、0x00cf、0x00bf、0x00af、0x009f、0x008f、0x007f、0x006f、0x005f、0x004f、0x003f、0x002f、0x001f和0x000f,每写一
23、次数据要加一个适当的延时,以便进行下一次写数据。void WRITE()int i;unsigned short data=0x00ff;for(i=0;i16;i+)printf(%x ,data);*(volatile unsigned int short *)ADDRESS+i)=data;data=data-0x0010;delay(100000);printf(n);读函数代码如下,从首地址开始读数据,总共读16次。void READ()int i,temp;for(i=0;i IRAM .stack IRAM .bss IRAM .cinit IRAM .cio IRAM .con
24、st IRAM .data IRAM .switch IRAM .system IRAM .far IRAM进行程序设计时,首先要对SDRAM访问的几个相关寄存器进行配置,这些寄存器包括EMIFA全局控制器、CE0控制寄存器、CE0第二控制寄存器、SDRAM控制寄存器、SD刷新控制寄存器和SD扩展寄存器。根据DSP中控制寄存器的地址分配,对相应的控制寄存器作如下定义:#define EMIFA_GBLCTL 0X01800000 /EMIFA全局控制器#define EMIFA_CE0CTL 0X01800008 /CE0控制寄存器#define EMIFA_SDCTL 0X01800018
25、/SDRAM控制寄存器#define EMIFA_SDTIM 0X0180001C /SDRAM刷新控制寄存器#define EMIFA_SDEXT 0X01800020 /SDRAM扩展寄存器#define address 0x /选择CE0的首地址根据DSP EMIFA手册,在程序中可以对以上控制寄存器进行如下配置:*(volatile u32*)EMIFA_GBLCTL=(u32)0x00000020;*(volatile u32*)EMIFA_CE0CTL=(u32)0xFFFFFF33;*(volatile u32*)EMIFA_SDCTL =(u32)0x;*(volatile u
26、32*)EMIFA_SDTIM =(u32)0x00000446;*(volatile u32*)EMIFA_SDEXT =(u32)0x0005452B;因为已经对以上控制寄存器进行了命名,所以配置了这些控制寄存器之后,SDRAM 就可以像 DSP 内部存储器一样进行读写了。读写 SDRAM 时,可以采用指针,对某个具体地址进行赋值,然后再从相同的地址读出数据进行对比。SDRAM写函数每次把int型的变量i(32位)写入到地址(volatile u32 *)address + i中,总共写入32768个32位的数据,即1Mbit,这样的设计方便在读数据时对数据读写是否正确进行判断。SDRAM
27、写函数代码如下:SDRAM读函数执行时,每读一个数据都会对其进行判断,如果读写不正确,就让counter加1,程序结束后counter的值就是读写错误数据的总量。但在测试读速度时需要去掉读写判断代码,以保证测得的速度准确。SDRAM读函数代码如下:void Write_sdram() int i; for(i =0;i32768;i+) *(volatile u32 *)address + i) = i;void Read_sdram() int j,k; for(j =0;j32768;j+) k=*(volatile u32 *)address + j); /if(k!=j) /count
28、er+; 因为要测试SDRAM的访问速度,所以要测试读写花费的时间。具体设计如下:对SDRAM进行32位数据读写,程序中有SDRAM写函数和SDRAM读函数,每执行一次SDRAM写函数共写入1Mbit数据,每次写入32位,这样总共要写32768次;每执行一次SDRAM读函数就把这1Mbit数据读出来。main函数代码如下:void main() clock_t start,middle,stop; double wrt_time,rd_time; double wrt_rate_bit,rd_rate_bit; double wrt_rate_M,rd_rate_M; set_EMIFA(); start = clock(); Write_sdram(); middle = clock(); Read_sdram(); stop = clock(); wrt_time=(double)(middle-start)/CLOCKS_PER_SEC; rd_time=(double)(stop-middle)/CLOCKS_PER_SEC; wrt_rate_bit=1048576/wrt_time; rd_rate_bit=1048576/rd