SOPC技术LED流水灯设计 - 图文

更新时间:2024-05-06 04:13:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Sopc_LED实验指导

一. 实验目的:

1. 掌握NIOS II软核的定制流程。 2. 掌握NIOS II的开发流程。

3. 熟识NIOS II IDE 开发环境的使用。 4. 掌握基本的软件的调试方法。

5. 掌握通过寄存器形式对硬件进行控制,可以更透彻地看清NIOS II 开发过程。

二. 实验内容: 1.PIO 模块的构建。

2.软件编程,通过寄存器形式对硬件进行控制。 3.下载程序并硬件调试。 4. 扩展实验:

程序功能通过SOPC建立的软核来运行程序 功 能:LED 显示控制。

通过PIO 直接控制8 个LED 产生流水灯效果

三. 实验简介:

这一节,我将给大家了解第一个与硬件有关的程序,虽然内容简单,却极具代表性。我将采用一种寄存器的操作方案,让大家感受到开发 NIOS跟单片机一样的简单,看透NIOS II开发的本质,尽量避免使用 NIOS II IDE提供的API,

这样做有很多好处。首先,有单片机开发经验的人应熟悉这种操作方案,其次,它是硬件试验部分的第一课,通过这个简单的实验,可以让你对单片机的操作有一个感官上的了解,可以说意义不同寻常。这一节,我也通过 LED 实验来带大家进入 NIOS II 的开发世界,感受 NIOS 的魅力所在,下面我们开始吧。

四. 实验内容: 1. 硬件开发

第一步,我们要在软核中加入PIO 模块。打开我们上一次建的Quartus 工程,如下图红圈所示

(如果你没保留上次的工程,需要按照上次指导书重新再做一个下面的。)

双击上图的hello_word后进入了SOPC BUILDER界面,如下图所示

点击下图所示红圈处 PIO(Parallel I/O)

点击后,如下图所示,红圈 1处是你需要的 PIO口的宽度,即你需要几个 IO口,这里面我设置为8,即我要控制8个LED,红圈2是选择输出方式,我选择为输出(Output)。

接下来,点击Finish,完成PIO模块的构建,然后将其改名为LED,如下图所示

接下来,需要自动分配一下基地址,上一次已经讲过,如下图所示

接下来,双击cpu,看下图红圈的地址为下图的。

点击finish。我们就要开始编译了,点击 Generate,耐心的等待编译的结束。

接着先保存一下吧,保存好以后,接下来,我们要对工程配置一下了,在左侧边框栏击右键点击hello_word,如下图所示

(双击Cyclone:EP1C12Q240C8也可以)

点击setting后,如下图所示,点击红圈处Device and Pin Options

点击后如下图所示,点击红圈处 unused Pins。

选中AS input tri-stated. 都修改好以后,点击确定,点击OK。 需要保存一下,点击save,开始编译。经过一段耐心的等徃,编译成功,如下图所示

完成了上面的工作,点击 Exit,会出现下面的界面,询问是否需要对 Hello_word 进行更新,点击“是(Y)”。

然后,会出现下面界面,点击OK

点击后,如下图:

如下图所示,可以看出,还有 LED 没有管脚相连,我们来建立一个输出管脚,并重命名

如果以后会出现下面情况,连线错位,这就需要我们手工来整理一下,将相应的管脚相连接。

最后的样子大家可以看到,如下图所示,我们将其命名为 LED[7..0],这是 quartus中总线的命名方式,大家要注意。

一切准备好了,我们需要给他进行引脚分配,按上次试验方式给他进行引脚分配。有不清楚的看上次的指导书和看以前的电子设计自动化实验指导书(附有管脚分配的word文档)。

下面,我们开始编译了,又是一次漫长的等待后,看到了下图红圈所示,说明编译成功。

2.软件开发:

首先打开NIOS II 9.0 IDE,把工程路径切换到上次做的quartu的工程里面去。File->Switch WorkSpace->Browse选中你d:projectname/hello_word的工程里面去。(如果你们没有,就新建了工程的,根据你quartus的工程路径,然后切换到那里去)。存储路径不能出现中文,否则会报错的。

如果你是用上次的工程文件,则会出现如下图红圈的

选中它,点击右键

出现了下图的,点击Delect

然后选第一个 点击yes

重复上面的方法删掉另一个文件,只留下(如图):

没有上次工程的,就要新建立一个软件工程,操作方案如下图所示,File->New->Project

点击后,会出现工程向导界面,如下图所示,选中红圈处的内容,Nios II C/C++ Application,

点击Next,会出现下图所示内容,

红圈2处是工程名,我将其修改为LED_test, 红圈 3 处是目标硬件文件,点击 Browse,找到我们上面生成的 NIOS 软核的位置,这个文件是以.ptf 为后缀的,如果大家跟我的地址一样的话,地址应该是在D:\\projectname\\hello_word.ptf。在

红圈1 处选中BlankProject,这个地方是空工程模块。 红圈 4,这个地方是改变工程所放位置的,如果不修改,软件工程的位置就在 Quartus工程目录下得software 下面,再这里不需要点击。 (按下图选择)

点击Next,这里不用修改,点击 Finish,完成工程向导.

在工程目录区中的LED_test项单击鼠标右键后,

点击红圈处的位置 System Library Properties

点击后,可看到下图所示界面,(按图选择)

按顺序来,红圈 1 处是标准输入(stdin)、标准输出(stdout)、标准错误(stderr)的位置区,我们在软核中构建了 JTAG UART,在此出现效果了吧,如果我们没有构建 JTAG UART,那么,这个地方就不会出现 jtag_uart 选项了。在所红圈 2 处,这个地方也不需要修改,不过有一个地方需要注意,就是Support C++,这个库相对Small C library要大,如果大家手中的板子没有FLASH, SDRAM这样大容量存储设备的话,选择Small C library,用FPGA 内部的SRAM,也可以跑些小程序。再说红圈3处,这个是一些有关内存的选项,默认就可以,不用修改。

点击后,我们看看是什么样子(如下图),这里有两个关键点,一个是红圈 1 处,这个地方时配置编译器的优化

级别,红圈 2 的地方是调试级别。编译器的优化级别会让你的生成的

代码更小,当要求也很高,你的代码如果不严谨,有可能优化以后不好用了,大家要注意。调试级别是你在编译过程中显示编译内容多少,级别越高显示内容的越多,建议将调试级别调到最高。

将上面设置好以后,点击Apply,然后点击 OK,回到主页面。

再添加一个c文件。如图所示:

点击后,出现如下图所示,并命名一个点****.c文件 ***** 代表你的c文件名,

点击finish。出现如下图

将下面程序复制上去,保存一下,在进行编译。 (下面的注释不能以文字开头,必须以 // 开头) #include \

#include \#include \int main (void) {

alt_u8 led = 0x02; // 0000 0010 alt_u8 dir = 0; // 0000 0000 volatile int i; while (1) {

//程序第一次执行的时候,第一个if语句和第二个if语句都不会执行的。

//当led变量的值在else 语句里面左移到1000 0000=0x80的时候,第一个if语句就满足执行的条件 //当第一个if语句执行第一次(第寄数)之后,dir的变量值就为1,就满足第二个if语句执行

//第二个语句执行的时候led变量值是从1000 0000 右移到0000 0001

if (led & 0x81) //led为1000 0000;或者是0000 0001的时候 这个If语句都会执行 {

dir = (dir ^ 0x01); //1 }

if (dir) //1 {

led = led >> 1; //LED右移动显示 led=1000 0000; } else {

led = led << 1; //LED左移动显示//000 0010 ; }

IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE, led); //赋值 i = 0;

while (i<100000) //延时 i++; } return 0; }

复制好后接着进行编译。

编译好以后,大家可以看到下面界面,红圈处说明了,编译完成。(无错误显示0 error)

③.运行 按下图点击

下载 选中helloword.sof文件

下载好后进行下面的操作

对于NIOS IDE提供了几种方法来验证,一种是直接硬件在线仿真,一种是软件仿真。我们先说第一种硬件在线仿真,很显然这种方案需要硬件配置,一块开发板,一个 仿真器(仿真器就是大家用的USB-BLASTER或者BYTE-BLASTER)。将仿真器与开发板的JTAG口相连。安装好以后,我们进行下面的操作,点击红圈处Nios II Hardware。

点击后,可以看观察栏的控制台(Console)。

说完第一种硬件在线仿真以后,我们再说说软件仿真。软件仿真不需要硬件,电脑单独运行即可,按下图所示操作,点击红圈处,Nios II Insruction Set Simulator。

点击(yes)

双击红圈处,设置断点

全速运行,

观察下面图的红圈。

可看到变化。

扩展实验程序:(花样流水灯) //////////////////////////////////////////////// //使用的是CPU内部内存

//NIOS II的工程路径最好不要有汉字和一些特殊字符,最好用英文

////////////////////////////////////////////////

#include \

#include \#include \

/* 流水灯花样,低电平点亮,注意调用时候用了取反操作 */ const alt_u32 LED_TBL[] = {

0x00, 0xFF, // 全部熄灭后,再全部点亮

0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, // 依次逐个点亮

0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, // 依次逐个

叠加

0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, // 依次逐个递减

0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81, // 两个靠拢后分开

0x81, 0xC3, 0xE7, 0xFF, 0xFF, 0xE7, 0xC3, 0x81 // 从两边叠加后递减 };

/******************************************************************** * 名 称:main()

* 功 能:控制LED 流水显示。

********************************************************************/ int main (void) { alt_u8 i; alt_u32 j; while (1) {

for (i=0; i<42; i++) { /* 流水灯花样显示 */

IOWR_ALTERA_AVALON_PIO_DATA(LED_BASE, ~LED_TBL[i]); j = 0;

while (j<100000) //延时 j++; } } return 0; }

接下来,我们总结一下这节内容。我们来对比一下寄存器操作方式不 API 之间有什么联系和异同,上面癿程序,如果用NIOS II IDE提供的API 来写,那么如下图所示

IOWR_ALTERA_AVALON_PIO

是一个宍,在

altera_avalon_pio_regs.h 中,其定义如下(大家可以按住 ctrl

键后,用鼠标点击进入定义所在的位置)

大家可以看到,它是一个 IOWR的宏,而IOWR的具体写法我就在此不详细说了(大家感兴趣的可以去 NIOS 的源码),反正就是对硬件地址的控制。我的做法就是绕过这个大圈子,直接去控制它的寄存器。 大家可能有点纳闷,我们的结构体中定的了四个变量,但却用了 DATA 一个,在这说明一下原因,首先是 DIRECTION。返个是 IO 的方向,就是说是输入还是输出,或者是双向的。因为在我们构建PIO 模块的构成中有了一个选项,如下图所示,红圈2,我们选择了输出(Output ports only),也就是我们在底局就已经固定了它的方向,所以在软件中就还需要在定义了。还有两个变量是涉及到中断时才会用到,所以在这个程序中也没有用到。

我要提醒大家一句,我虽然提倡大家用操作寄存器方式编程,但并不希望所有的程序都按这种方式来写,比如说对 flash 的操作,我们就可以使用 API 来写,因为 flash的操作相对复杂,而利用API可以径简单得几个语句就能完成,

没必要自己来写。

扩展数码管实验

一. 添加CPU

二. 添加on_chip的ram。 三. 添加 JTAG_UART

四. 添加三个PIO口为输出口,做为

位选输出。

五. 再添加8个PIO口为输出口,作

为段选输出。 注意的地方:

PIO的命名

位选的PIO命名为SMG_BIT 段选的PIO命名为SMG_SEG 实验程序:

//程序功能显示0到9的任意字符,动态显示。

//NIOS II工程路径不能有汉字 和特殊的字符

#include \#include \

//包含基本的IO寄存器信息 #include \ //Altera定义的数据类型 #include \ //延时函数

#define seg *(volatile unsigned char *) SMG_SEG_BASE //代表数码管的段码地址

#define bit *(volatile unsigned char *) SMG_BIT_BASE //代表数码管的位选地址

const alt_u8 duan[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

//共阳数码管的0到9的段码 0 1 2 3 4 5 6 7 8 9

void display()

{

alt_u8 i;

for(i=0;i<8;i++) {

bit = i ;

seg = ~duan[i]; 要显示的字符

usleep(500000); } }

int main(void) {

while(1) {

display(); }

return 0; }

//输出

本文来源:https://www.bwwdw.com/article/z4vg.html

Top