SOPC综合实验报告

发布时间:2015-12-15 16:16:05   来源:文档文库   
字号:

基于SOPC的数字钟设计

院: 计控学院

级: 计本121

号: 2012021001

名: 钟济强

指导老师: 张浩鹏

一、
设计概述

Nios II DE2开发板的LCD显示电子钟的日期和时间,LCD分两行显示,第一行显示年月日,第二行显示时分秒。用输入按钮BUTTON来控制LCD行修改,通过Nios II IDE进行软件设计。

二、 设计要求

1.掌握Nios II系统的设计和使用方法;

2.学习通过Nios II IDE进行软件设计的方法;

3.实现在液晶屏上显示时间和日期,并可以对其进行设置。

三、 实验环境

DE2 开发板

QuartusII 7.2

SOPC Builder 7.2

NiosII IDE 7.2

四、 设计方案(总体设计、软件设计、硬件设计

1. 总体设计要实现以下两个功能:

(1). 在液晶屏上显示时间,日期

(2). 对时间、日期能够进行设置

建立新工程clock

2. 硬件系统组成设计

根据系统要实现的功能和开发板配置,需要用到的DE2开发板上的外围器件有:

LCD:电子钟显示屏幕

按钮:电子钟设置功能键

CFI Flash存储器:存储软、硬件程序

SDRAM存储器:程序运行时将其导入SDRAM

根据所用到的外设和器件特性,在SOPC Builder中建立系统要添加的模块包括:NiosII CPU定时器,按键PIOLCD 外部存储器总线(Avalon三态桥),外部SDRAM控制器,外部Flash接口。

打开SOPC Buider,系统名称为sopc_clock

加入SDRAM组件

加入Flash Memory 组件

加入外部存储器总线(Avalon三态桥)

加入按键PIO

加入LCD

加入NiosII CPU定时器,选择标准型的

元件添加完后,要为每个外设分配及地址和中断请求优先级(IRQ),在System中选择Auto-Assign Base AddressAuto-Assign IRQs命令,这两个命令可分别简单分配外设基地址和中断优先级。然后生成Nios II系统。

然后生成顶层文件,将Nios II系统模块加入到顶层文件中,如图所示原理图

进行引脚锁定,并编译,然后进行硬件下载

3.软件系统设计

要实现系统所需的功能,大量的工作应该集中在软件设计和优化上。电子钟的软件功能主要分为显示、设置和时间算法三大部分。

显示部分的功能包括:显示时间(小时:分钟:秒)和 显示日期(年--日)

设置部分的功能包括:设置小时,设置分钟,设置年份,设置月份,设置日期和退出设置。

设置部分的程序主要用在对按键的响应。在编写程序前要对DE2开发板上的四个按键BUTTON功能进行如下分配:

(1). 主菜单

BUTTON0:设置选择键,可依次选择设置时、分、秒和年、月、日

BUTTON1:显示日期键

BUTTON2:显示时间键

(2). 子菜单(即进入对某个选项设置后的按键功能):

BUTTON1:选项数字增加

BUTTON2:选项数字减少

BUTTON3:退出对选项的设置,返回主菜单

时间算法部分的功能包括:时间累加和确定每个月的最大天数,使年、月、日能正确累加

五、 软件代码

1count_binary.c的代码:

#include "count_binary.h"

//程序每秒钟检测一次按钮的状态,对日期和时间进行设置

#include "alt_types.h"

#include

#include

#include

#include "system.h"

#include "sys/alt_irq.h"

#include "altera_avalon_pio_regs.h"

#include "lcd.h"

volatile int edge_capture;

void LCD_Init()

{

//LCD初始化

lcd_write_cmd(LCD_BASE,0x38);

usleep(2000);

lcd_write_cmd(LCD_BASE,0x0C);

usleep(2000);

lcd_write_cmd(LCD_BASE,0x01);

usleep(2000);

lcd_write_cmd(LCD_BASE,0x06);

usleep(2000);

lcd_write_cmd(LCD_BASE,0x80);

usleep(2000);

}

void LCD_Show_Text(char* Text)

{

//LCD输出格式

int i;

for(i=0;i

{

lcd_write_data(LCD_BASE,Text[i]);

usleep(2000);

}

}

void LCD_Line1()

{

//LCD写命令

lcd_write_cmd(LCD_BASE,0x80);

usleep(2000);

}

void LCD_Line2()

{

//LCD写命令

lcd_write_cmd(LCD_BASE,0xC0);

usleep(2000);

}

static void handle_button_interrupts(void* context,alt_u32 id)

{

volatile int* edge_capture_ptr=(volatile int*) context;

/*存储按钮的值到边沿捕获寄存器*/

*edge_capture_ptr=IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE);

/*复位边沿捕获寄存器*/

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE,0);

}

/*初始化button_pio*/

static void init_button_pio()

{

void* edge_capture_ptr=(void*)&edge_capture;

/*开放全部4个按钮的中断*/

IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTON_PIO_BASE,0xf);

/*复位边沿捕获寄存器*/

IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTON_PIO_BASE,0x0);

/*登记中断源*/

alt_irq_register(BUTTON_PIO_IRQ,edge_capture_ptr,handle_button_interrupts);

}

void delay(unsigned int x)

{

while(x--);

}

int check_month(int month)

{

//如果是135781012月,则每月31天,程序返回1

if((month==1)||(month==3)||(month==5)||(month==7)||(month==8)||(month==10)||(month==12))

return 1;

//如果是46911月,则每月是30天,程序返回0

if((month==4)||(month==6)||(month==9)||(month==11))

return 0;

//如果是2月,程序返回2,具体多少天还要根据年的判断来决定

if(month==2)

return 2;

}

/*

闰年的计算方法:公元纪年的年数可以被四整数,即为闰年

100整除而不能被400整除为平年;被100整除也可被400整除的为闰年

2000年时闰年,而1900年不是

*/

int check_year(int year)

{

if(((year%400)==0)||(((year%4)==0)&&((year%100)!=0)))

return 1;

//是闰年,返回1

else return 0;

//不是闰年,返回0

}

int main(void)

{

int screen=0;//共有两行,一行显示年月日,一行显示时间

int pos=0;//每行都有三个位置,第一行是年月日,第二行是时分秒

int year,month,day,hour,minute,second;

unsigned long sum;//sum要设置为长整型变量,不然会溢出

char date[16];

char time[16];

int year1=6;

int year2=0;

int year3=0;

int year4=2;

int month1=1;

int month2=0;

int day1=1;

int day2=0;

int hour4,hour3,hour2,hour1,minute2,minute1,second2,second1;

unsigned int screenflag;

hour=0;minute=0;second=0;year=2006;month=1;day=1;

//年月日时分秒初始化

init_button_pio();

LCD_Init();

while(1)

{

if(pos>=3)

pos=0;//共有三个位置012,超过了2要马上清0

if(screen>=2)

screen=0;//共有两行01,超过了1要马上清0

//na_LED8->np_piodata=1<用一个LED指示当前调整的位置

if(screen==0)

screenflag=8;

else screenflag=0;

//IOWR_ALTERA_AVALON_PIO_DATA(LED_GREEN_BASE,(1<

usleep(1000000);//等待1秒的定时时间

if(second<59) second++;

else

{

second=0;

if(minute<59) minute++;

else

{

minute=0;

if(hour<23) hour++;

else

{

hour=0;

if(day<30) day++;

else

{

day=1;

if(month<12) month++;

else

{

month=1;

if(year<9999) year++;

else year=2005;

}

}

}

}

}

switch(edge_capture)//检测按钮

{

case 0x08:pos=pos+1;break;//改变调整位置

/*

对数据进行加减操作的CASEcase 0x02case 0x04

根据当前调整位置,判断当前屏显示的是年、月、日还是时分、秒

然后决定是对年月日进行加减还是对分时秒进行加减

*/

case 0x02://对当前位置上的数据执行减操作

if(pos==0)

{

if(screen==0)

{

if(day>1)day--;

else

{

if(check_month(month)==0)day=30;

if(check_month(month)==1)day=31;

if(check_month(month)==2)

{

if(check_year(year))day=29;

else day=28;

}

}

}

if(screen==1)

{

if(second>0)second--;

else second=59;

}

}

if(pos==1)

{

if(screen==0)

{

if(month>1)month--;

else month=12;

}

if(screen==1)

{

if(minute>0)minute--;

else minute=59;

}

}

if(pos==2)

{

if(screen==0)

{

if(year>0)year--;

else year=2005;

}

if(screen==1)

{

if(hour>0)hour--;

else hour=23;

}

}

break;

case 0x04://对当前位置上的数据执行加操作

if(pos==0)

{

if(screen==0)

{

if(check_month(month)==0){if(day<30)day++;else day=1;}

if(check_month(month)==1){if(day<31)day++;else day=1;}

if(check_month(month)==2)

{

if(check_year(year)){if(day<29)day++;else day=1;}

else {if(day<28)day++;else day=1;}

}

}

if(screen==1)

{

if(second<59)second++;

else second=0;

}

}

if(pos==1)

{

if(screen==0)

{

if(month<12)month++;

else month=1;

}

if(screen==1)

{

if(minute<59)minute++;

else minute=0;

}

}

if(pos==2)

{

if(screen==0)

{

if(year<9999)year++;

else year=2005;

}

if(screen==1)

{

if(hour<23)hour++;

else hour=0;

}

}

break;

case 0x01:screen++;break;//换屏

}

edge_capture=0;

{

year4=year/1000;year3=(year-year4*1000)/100;

year2=(year-year4*1000-year3*100)/10;year1=year%10;

month2=month/10;month1=month%10;

day2=day/10;day1=day%10;

LCD_Line1();

date[0]=year4+0x30;date[1]=year3+0x30;

date[2]=year2+0x30;date[3]=year1+0x30;

date[4]=' ';date[5]=' ';

date[6]=month2+0x30;date[7]=month1+0x30;

date[8]=' ';date[9]=' ';

date[10]=day2+0x30;date[11]=day1+0x30;

date[12]=' ';date[13]=' ';

date[14]=' ';date[15]=' ';

LCD_Show_Text(date);

}

{

hour4=0;hour3=0;

hour2=hour/10;hour1=hour%10;

minute2=minute/10;minute1=minute%10;

second2=second/10;second1=second%10;

time[0]=' ';time[1]=' ';

time[2]=hour2+0x30;time[3]=hour1+0x30;

time[4]=' ';time[5]=' ';

time[6]=minute2+0x30;time[7]=minute1+0x30;

time[8]=' ';time[9]=' ';

time[10]=second2+0x30;time[11]=second1+0x30;

time[12]=' ';time[13]=' ';

time[14]=' ';time[15]=' ';

LCD_Line2();

LCD_Show_Text(time);

}

}

}

2lcd.h的代码:

#ifndef _LCD_H_

#define _LCD_H_

//LCD Module 16*2

#define lcd_write_cmd(base,data) IOWR(base,0,data)

#define lcd_read_cmd(base) IORD(base,1)

#define lcd_write_data(base,data) IOWR(base,2,data)

#define lcd_read_data(base) IORD(base,3)

//----------------------------------------------------------------------

void LCD_Init();

void LCD_Show_Text(char* Text);

void LCD_Line2();

void LCD_Test();

//----------------------------------------------------------------------

#endif

六、 实验分析和实验结果

用输入按钮BUTTON[0]可以控制LCD行修改,同时让NiosII DE2开发板上的绿色发光二极管LEDG3的亮灭来表示。用输入按钮BUTTON[3]可以控制日期和时间的修改,BUTTON[1]BUTTON[2]输入按钮可以减少和增加显示的数字。

实验中开始时SDRAMBIDIR端口的命名错误导致引脚锁定未成功,此端口的名称应为DRAM_DQ[15..0]。此外,三态桥的设置被改变了,需要重新设置,回到Quartus II中,在assignments中选择settingsDevice->Device and Pin Options->Unused Pins,改为As input tri-stated

七、 总结

通过这12周的SOPC技术综合设计实践的学习,我学会了Quartus II

SOPC BuiderNios II DE2 的使用,并通过这些软件可以进行简单的实验操作,强化了我的动手能力,并通过这几次实验更加了解SOPC的设计与应用。在实验中,遇到了各种各样的问题,首先是自己进行检查,查不出来再由老师同学进行检查和讲解,提高了自己解决问题的能力,并且熟悉了整个实验的流程及具体的操作。我觉得这门课程很有意思,实验中是把各个部分的操作整合在一起,形成一个系统,做实验时要有整体感,一旦出现问题整体的重新进行设置和编译,比如如果添加组建时出现错误,要重新添加,重新生成模块,重新倒入模块,重新编译顶层文件,是一个整体的过程。

八、 附录

参考《SOPC技术与应用》,编著:江国强,机械工业出版社。

参考《SOPC技术综合设计实践实验指南》,编著:邱德惠。

思考题

1. 何谓SOC

SOCSystem On a Chip)称为片上系统,它是指将一个完整产品的功能集成在一个芯片上或芯片组上。SOC中可以包括微处理器CPU、数字信号处理器DSP、存储器(ROMRAMFlash等)、总线和总线控制器、外围设备接口等,还可以包括数模混合电路(放大器、比较器、A/DD/A转换器、锁相环等),甚至传感器、微机电和微光电单元。

2. 何谓SOPC

SOPCSystem On a Programmable Chip)称为可编程片上系统,它是基于可编程逻辑器件(FPGACPLD)可重构的SOCSOPC集成了硬核或软核CPUDSP、锁相环(PLL)、存储器、I/O接口及可编程逻辑,可以灵活高效地解决SOC方案,而且设计周期短,设计成本低,一般只需要一台配有SOPC开发软件的PC和一台SOPC实验开发系统(或开发板),就可以进行SOPC的设计与开发。

3. 何谓IP核?

IPIntellectual Property)是知识产权的简称。集成电路IP是指经过预先设计、预先验证、符合产业界普遍认同的设计规范和设计标准,并具有相对独立并可以重复利用的电路模块或子系统,如CPU、运算器、存储器、放大器等。集成电路IP模块具有知识含量高、占用芯片面积小、运行速度快、功耗低、工艺容差性大等特点,可重复用于SOCSOPC或复杂ASIC设计中。

4. 何谓嵌入式系统,嵌入式系统的CPU核可以分为哪两种类型?

嵌入式系统是指嵌入到对象体系中的专用计算机系统,包括硬件和软件两大部分。硬件包括处理器、存储器、输入输出接口和外部设备等,软件包括系统软件和应用软件。

基于SOPC的嵌入式系统结构主要包括嵌入式微处理器(CPU核)、定时器(Timer)、嵌入式锁相环(PLL)、嵌入式数字信号处理器(DSP)及其他IP模块等部分。

嵌入式系统的CPU核可以分为硬核和软核。

5. 简述CPU软核的特点。

软核通常以可综合的HDL提供,因此具有较高的灵活性,并与具体的实现工艺无关,其主要缺点是缺乏对时序、面积和功耗的预见性。由于软核是以源代码的形式提供,尽管源代码可以采用加密方法,但其知识产权保护问题不容忽视。

6. 简述HAL的用途及基于HAL的外围设备的编程方法。

HAL作为支持Nios II处理器系统的软件包,为用户的嵌入式系统上的外围设备提供了与之相匹配的接口程序。用户不用自己建立或复制HAL文件,也不需要编辑HAL中的任何源代码,使用时只需要在C/C++源程序中指明代表这些接口程序的库函数包含的头文件即可。

在一个基于Nios IISOPC系统上,外围设备包括通用异步串口UART、发光二极管LED、七段数码管、按钮、LCD、存储器、定时器、鼠标、VGA等。在应用软件的开发中,对于按钮、发光二极管LED、七段数码管等通用输入输出设备的编程比较简单,而对于通用异步串口UARTLCDVGA等字符模式外围设备的编程就比较复杂。

为了方便用户对字符模式外围设备的编程,HAL支持标准输入、标准输出和标准错误函数,允许在程序中调用stdio.h中的I/O函数来完成对这些设备的访问,也支持字符模式外围设备的通用访问。

7. 简述SOPC的设计流程。

SOPC硬件开发流程

a) 创建Quartus II工程

b) 创建Nios II系统模块

c) 配置Nios II系统

d) Nios II系统模块、LPM和用户自定义模块连接起来

e) 编译、引脚分配、编程下载

SOPC软件开发流程

Nios II程序包括一个应用工程、可选的库工程和一个板支持包工程(自动生成)。将Nios II程序编译成一个能在Nios II处理器上运行的.elf文件。

1. 新建Nios II C/C++应用工程与系统库工程

为新的Nios II工程命名、选择目标硬件(硬件系统的PTF文件,IDE根据该文件来建立系统库)、选择新工程的模板、建立C的源文件与头文件(注意一定要加上后缀名.c)、创建新的系统库(为硬件提供相应驱动)

注意:工程文件夹要建在D盘根目录下(其中D盘装有Quartus II软件)

2. 编译与设置工程

对工程进行编译projectbuild project,编译成功后,在工程下面会出现一个Binaries目录,其中有一个可执行文件.elf

3. 运行与调试程序

4. 编译整个项目

软件设计完成并调试成功后,可以在Quartus II中将整个项目进行编译,将硬件配置信息和软件初始化信息编译在一起,并固化到EPCS1芯片中。

8. 简述AVALON总线的特点。

Avalon总线是一种相对简单的总线结构,主要用于片内处理器与外设的连接,构成SOPC系统。Avalon总线拥有多种传输模式,以适应不同外设的要求。Avalon总线支持多总线的主外设,并允许在单总线外设之间传输多个数据单元,在构建SOPC系统时拥有极大的灵活性。

9. System.h系统描述文件包含了哪些NIOS II系统的硬件信息?

·处理器配置

·外设列表

·存储器配置

·定制指令宏

·处理器复位和异常地址

·代码段位置

10. 基于altera公司的SOPC系统如何实现上电自动加载程序?

1) SOPC Builder中,将CPUReset Vector设为cfi_flash

2) 下载硬件时,先将DE2板上液晶左边的开关扳到prog,在下载器窗口中Mode选项选择Active Serial Programing选项,然后单击Add File按钮,选择FlashTest.pof文件,勾选全部选项,点击start按钮即开始下载。下载结束后将上述开关扳回run。以后上电之后就自动将硬件加载到FPGA中,可以直接运行软件。

3) 下载软件时,选择Tool->Flash Programmer,点击Program Flash就可以将程序烧入Flash

本文来源:https://www.2haoxitong.net/k/doc/97d0ef16c1c708a1294a4472.html

《SOPC综合实验报告.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式