版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第7章“计算机组成原理”课程练习7.1一个简单的计算机系统7.2程序控制输入/输出7.3子程序与堆栈7.4轮询与中断7.5总线通信7.1一个简单的计算机系统7.1.1建立一个简单的计算机系统在本练习中,我们使用SOPCBuilder建立一个如图7.1所示的系统,这个系统由一个NiosⅡ/e处理器和一个片上存储器块组成,NiosⅡ/e处理器用来处理数据,存储器块用来保存指令和数据。请按照以下步骤实现如图7.1所示的NiosⅡ系统:
(1)新建一个QuartusⅡ工程,选择CycloneⅡEP2C35F672C6作为目标器件,这个器件是AlteraDE2平台上采用的器件。
(2)使用SOPCBuilder建立一个名为nios_system的系统,系统中包括以下部件:①带JTAGDebugModuleLevel1的NiosⅡ/e处理器。②RAM模式、32位宽、32K字节深度的On-ChipMemory。
(3)从System菜单中选择Auto-AssignBaseAddresses,自动分配系统中部件的基地址,得到如图7.1所示的系统。
(4)生成系统后退出SOPCBuidler并返回QuartusⅡ软件。
(5)在Verilog/VHDL模块中例化生成的NiosⅡ系统。
(6)分配引脚如下:①clk-PIN_N2(50MHz时钟输入)。②reset_n-PIN_G26(AlteraDE2平台上的按键KEY0)。
(7)编译QuartusⅡ工程。
(8)下载并配置DE2上的CycloneⅡ系列FPGA以实现生成的系统。使用这个系统前,还必须为处理器提供可供执行的程序,图7.1SOPCBuilder中的NiosII系统7.1.2对序列中出现的连续的1计数在数字计算机中,所有的数据都是按0和1的序列出现的。代码7.1所列的NiosⅡ汇编语言代码用以测试一串二进制数据中连续出现的1的最大长度。例如0x937a(1001001101111010)中最多有4个1连续出现(粗体部分)。代码7.1用于计算数据0x90abcdef中连续出现1的最大长度。代码7.1计算数据0x90abcdef中连续出现1的最大长度。.include"nios_macros.s".text.equTEST_NUM,0x90abcdef /*接受测试的数据*/.global_start_start:movia r7,TEST_NUM /*用r7初始化被测试的数据*/ mov r4,r7 /*将数据复制到r4*/STRING_COUNTER: mov r2,r0 /*初始化计数器*/STRING_COUNTER_LOOP: /*循环直至r4中没有1*/ beq r4,r0,END_STRING_COUNTER srli r5,r4,0x01 /*通过移位并将移位结果与自身相与来计算1的数量*/ and r4,r4,r5 addi r2,r2,0x0001 /*计数器加1*/ br STRING_COUNTER_LOOPEND_STRING_COUNTER: mov r16,r2 /*将结果保存在r16中*/END: br END /*程序结束*/.end请参照以下步骤编译并执行代码7.1:
(1)打开AlteraDebugClient,并用7.1.1小节中生成的系统及代码7.1所示的应用程序配置AlteraDebugClient。
(2)编译并装载该程序。
(3)单步执行完该程序,观察指令是如何改变处理器的寄存器值的,当程序执行结束之后,寄存器r16的值应该为4。
(4)将程序计数器(ProgramCounter)设为0x00000008,以此来跳过刚开始的两条指令重新执行程序。
(5)在地址0x28设置一个断点,这样程序执行完后会自动停止。
(6)将r7设为0xabcdef90,按F3(继续运行)重新运行程序,检验运行结果是否正确。7.1.3指令的组成与数据一样,指令也是由1和0组成的二进制序列。本练习主要考查指令是如何组成的。请参照以下步骤完成练习:
(1)在AlteraDebugClient中选择Actions>Load,重新装载程序,以清除7.1.2小节中对存储器内容的修改,重新执行一遍程序,结束后停下来。
(2)从Altera的网站上下载NiosⅡProcessorReferenceHandbook,光盘的Documents目录下也包含了这个手册,用该手册确定andr3, r7, r6和srar7, r7, r3两句代码的机器指令表示。
(3)使用AlteraDebugClient的memory-fill功能将这两个指令放在0和4的位置,我们会注意到在DebugClient的反汇编视图中看不到这些更新后的值。
(4)将程序计数器设为0x00000000,这个时候会发生什么呢?先想一想,然后再验证答案,先单步执行放在地址0和地址4的指令(查看是否已经生效),然后执行其他代码。
(5)使用memory-fill功能修改最后一个分支指令,使之指向程序的开始而不是本身,这样就不需要手工修改程序计数器了。
(6)返回程序,直至1的数量及被测试的数据变为常数。
(7)用指令srl47, r7, r3替代srar7, r7, r3,重复步骤(1)~(6),看看有什么区别。7.1.4子程序在大多数应用程序中,部分代码可能需要在一个程序中的不同位置被多次执行,这部分代码可以用子程序的形式实现。在程序的任何位置都可以通过call指令调用子程序,如果子程序以ret指令结尾,则在执行完毕后返回调用该子程序的位置。本练习建立一个子程序对连续的1计数,再调用这个子程序对一个给定数据中的1和0计数。请在7.1.2小节中代码的基础上进行如下修改:
(1)将对连续的1计数的程序作为一个子程序,在该子程序中用寄存器r4作为输入寄存器的接收输入,用寄存器r2保存计数结果作为子程序的输出。
(2)调用两次新建立的子程序,一次用来计算连续出现的1;另一次用来计算连续出现的0,计算连续的0时,先将输入数据取反,然后调用子程序进行计算。
(3)将连续出现的1的数量写入寄存器r16,而将连续出现的0的数量写入寄存器r17。7.1.5对交替出现的1和0计数我们有时需要计算一个序列中交替出现的1和0最多的字符串长度,例如二进制序列101101010001中有一个长度为6的交替出现1和0的字符串(粗体部分)。本练习使用7.1.4小节中建立的子程序来对交替出现的1和0计数,将计数结果保存在寄存器r18中,假设最后两位可以看做最长字节的一部分,例如1010有4个连续位交替出现的1和0。(提示:将数字左移一位或右移一位并与原始数据进行异或运算,看看会得到什么结果。)7.1.6C语言与汇编语言的比较使用C语言完成7.1.5小节中的练习。建立一个名为count_ones的函数用以对连续出现的1计数。从反汇编之后的代码中找到main函数及count_ones子程序,对照是否采用了同样的方式来编写汇编代码。分析编译器使用了哪些寄存器以及使用原因。7.2程序控制输入/输出本练习探讨为处理器提供输入/输出功能以及能够被软件控制的外设,将从软件和硬件两个角度来验证程序控制输入/输出操作,在AlteraDE2平台上使用PIO部件实现程序控制并行接口。本练习的背景知识可以参照本书部分相关内容,也可以从Altera网站上的IntroductiontotheAlteraNiosⅡ SoftProcessor及IntroductiontotheAlteraSOPCBuilder文档中获得,光盘的目录Documents中也提供了这些文档。其中IntroductiontotheAlteraSOPCBuidler有两个版本,一个是针对VHDL设计的,另一个是针对Verilog设计的。本练习中使用的PIO接口,是一个可以由SOPCBuilder生成的部件,用以提供输入/输出或双向数据传输。PIO提供的数据传输是1~32位的并行传输,传输数据位宽n及传输方向可以由使用者在SOPCBuilder中设定,PIO接口可以包含如表7.1所示的4个寄存器。每一个寄存器都是n位长,各寄存器的用途如下:
(1) Data(数据寄存器):用以保存PIO接口与NiosⅡ处理器之间传输的数据,SOPCBuilder可以根据要求用输入寄存器、输出寄存器或双向寄存器实现数据寄存器。
(2) Direction(方向寄存器):用以定义SOPCBuilder生成的双向寄存器的传输方向。
(3) Interrupt-mask(中断控制寄存器):用以控制连接在PIO接口上的输入口的中断使能。
(4) Edge-capture(边沿捕捉寄存器): 用以表明连接在PIO接口上的输入口何时发生逻辑电平的变化。并不是所有的寄存器都在每一个PIO接口模块中出现。如果不使用双向接口,则SOPCBuilder就不会生成方向寄存器;如果不使用输入接口,则不会生成中断控制寄存器和边沿捕捉寄存器。
PIO寄存器可以像处理器的存储器一样进行访问。可以将NiosⅡ处理器的任意一个低4位为0的地址分配给PIO接口(地址分配一般由SOPCBuilder自动完成),这个地址是数据寄存器Data的地址,其他3个寄存器的地址相对于数据寄存器Data分别有4、8和12个字节(1、2和3个双字)的偏移。关于PIO外设的更多信息请参考文档QuartusⅡ Version6.0HandbookVolume5:AlteraEmbeddedPeripherals(可从Altera网站或光盘的Doucuments目录中获得)中的相关内容。本练习的任务是用AlteraDE2平台上的波段开关输入一组带符号的8位数字,将这些数字相加并在LED和七段数码管上显示结果。7.2.1建立包含三个PIO接口部件的系统本练习使用8个波段开关SW7~SW0输入数字,使用绿色LED灯LEDG7~LEDG0显示由波段开关所定义的数字,使用16个红色LED灯LEDR15~LEDR0显示累加和。我们使用一个包含三个PIO接口的NiosⅡ系统完成该练习,其中一个PIO接口连接波段开关,为处理器提供数据;另外两个PIO接口分别连接到绿色和红色LED灯,作为输出接口,分别用来显示输入的数字以及累加和。请参照以下步骤在DE2平台上建立一个NiosⅡ系统并实现练习所需的硬件:
(1)新建一个NiosⅡ工程,选择DE2平台上的CycloneⅡEP2C35F672C6作为目标器件。
(2)使用SOPCBuilder生成所需的电路,系统名称为nios_system,这个系统由以下部件组成:①带JTAGDebugModuleLevel1的NiosII/s处理器,使用以下选项。● HardwareMultiply下拉菜单中的EmbeddedMultiplier(用硬件乘法器实现乘法)。●选中HardwareDivide(硬件除法器)。②RAM模式32K字节深度的片上存储器。③8位PIO输入接口电路。④8位PIO输出接口电路。⑤16位PIO输出接口电路。SOPCBuilder自动为三个PIO接口命名为pio_0、pio_1和pio_2,也可以根据PIO所做的具体工作修改名称,例如,可分别命名为new_number、green_LEDs和red_LEDs。
(3)使用System>Auto-AssignBaseAddresses菜单,自动为系统中的所有部件分配地址,结果为如图7.2所示的系统,看看各PIO模块的地址是如何分配的。
(4)在Verilog/VHDL文件中例化nios_system,并在Verilog/VHDL设计中对所需要的与DE2平台上开关和LED灯的连接进行定义。
(5)导入DE2_pin_assignment.csv中的引脚配置(可参考3.5.2小节),为设计分配引脚。
(6)编译QuartusⅡ工程。
(7)下载并配置DE2平台上的CycloneⅡ系列FPGA以实现所生成的系统。图7.2包含了三个PIO模块的NiosⅡ系统7.2.2用NiosⅡ汇编语言实现数据输入、累加及输出本练习用NiosⅡ汇编语言实现数据的输入、累加及输出,请参照以下步骤完成练习:
(1)用汇编语言编写一段程序,读取波段开关的内容,将相应的值在绿色LED上显示出来,将这个数字加到一个累加和上,并用红色LED显示累加结果。
(2)使用AlteraDebugClient软件编译并下载程序。
(3)单步执行程序并通过输入不同的数据来验证设计的正确性。注意,单步执行程序允许改变输入数据而不用担心程序会多次重复读取相同的数据。7.2.3用按键控制数据读取在本练习中,我们要为应用程序增加连续读取数据的功能,并通过一个按键启动数据读取。当在波段开关上输入新的数据后,通过按键通知处理器读取数据。本练习还需要监测控制电路的状态。通常使用一个状态标志(StatusFlag),首先将这个标志位清零,当I/O设备接口做好下一次数据传输的准备时,将状态标志位置1,传输结束后,重新把该标志位清零,这样,处理器可以通过轮询状态标志决定何时可以传输数据。在本练习中,I/O设备是波段开关,I/O接口是由SOPCBuilder生成的PIO电路,为了提供一个状态标志,我们可以生成一个特殊的带边沿捕捉功能的一位PIO电路。这个PIO与普通的PIO非常相似,寄存器分配与表7.1也一致。在目录altera_up_avalon_DE2_pio中定义了这个PIO,必须将这个定义导入到工程中来。该目录包含在光盘的目录\DE2_Computer_Organization\University_Program_IP_Cores中,也可以从Altera大学计划网站/up/pub/University_Program_IP_Cores/DE2_pio.zip上获得。请参照以下步骤完成练习:
(1)新建一个工程并实现一个与7.2.1小节中相同的系统。
(2)将altera_up_avalon_DE2_pio目录复制到工程目录中。打开SOPCBuidler,其中已经列出了已有的NiosⅡ子系统。为了能在SOPCBuilder中看到altera_up_avalon_DE2_pio,使用File>RefreshComponentList菜单刷新部件列表,此时在AvalonComponents>UniversityProgramDE2Board中将出现部件DE2_PIO。
(3)使用DE2_PIO生成一个状态标志部件,将这个部件配置成1位宽的输入口,在InputOptions中选择下降沿触发的SynchronouslyCapture。
(4)生成NiosⅡ子系统。
(5)针对完成的NiosⅡ系统修改Verilog/VHDL设计,使用按键KEY0作为状态标志PIO的输入(按键是低电平有效的)。
(6)分配引脚并编译工程。
(7)修改应用程序,当按键按下后接收一个新数据,并将Edge-capture寄存器的StatusFlag位置1,输入的数据累加之后,应用程序通过向Edge-capture寄存器中写入0来清除状态标志位。
(8)下载并运行编写的程序以验证其正确性,程序应该连续运行,且每次按下按键后加一个新的数字。7.2.4用七段数码管显示十六进制累加结果在前面的练习中用红色LED显示累加结果,本练习将对设计加以修改,除在红色LED上显示累加结果之外,同时在七段数码管HEX3~HEX0上用十六进制数显示累加结果。7.2.5将累加结果转换成十进制显示本练习在前面练习的基础上,用十进制数在七段数码管上显示累加结果,应用程序应能够完成所需的数制转换。注意:只有在7.2.1小节中选中HardwareDivide选项,才能使用div指令。7.3子程序与堆栈7.3.1建立一个NiosⅡ系统本练习中,我们将用到一个包含片上存储器块及JTAGUART模块的NiosⅡ系统,其中JTAGUART模块用以实现NiosⅡ处理器与主机之间的通信。请参照以下步骤实现这个系统:
(1)新建一个QuartusⅡ工程,选择CycloneⅡ EP2C35F673C6作为目标器件。
(2)使用SOPCBuilder建立一个名为nios_system的系统,该系统包含以下部件:①带JTAGDebugModuleLevel1的NiosⅡ/s处理器。②RAM模式32K字节深度的片上存储器模块。
(3)用System>Auto-AssignBaseAddresses菜单自动分配基地址,实现如图7.3所示的系统。图7.3用SOPCBuilder实现带jtag_debug_module的系统
(4)生成系统后,退出SOPCBuilder并返回QuartusⅡ软件。
(5)在Verilog/VHDL模块中例化所生成的NiosⅡ系统。
(6)分配引脚如下:①clk-PIN_N2作为50 MHz时钟输入。②reset_n-PIN_N25作为AlteraDE2平台上的按键SW0。
(7)编译QuartusⅡ工程。
(8)下载并配置DE2上的CycloneⅡ系列FPGA以实现生成的系统。7.3.2对32位正整数排序本练习的目标是对一系列32位正整数按降序排序。这些数据用文件的形式提供,文件的第一个32位数据表示数据列表的长度,其余为被排序的数据。请参照以下步骤用NiosⅡ汇编语言完成练习:
(1)编写一段汇编程序,对存储器中从LIST_FILE开始的数据文件中的数据进行排序。假设这个数据文件很大,没有足够的空间为排序后的数据提供单独的存储空间,因此排序过程要采用原位排序,即排序之后的数据列表和原始数据列表使用相同的存储空间。
(2)编译并用AlteraDebugClient下载程序。
(3)在存储器中手工建立一个数据列表,装载到内存中并运行程序。提示:包含数据列表的文件可以通过AlteraDebugClient装载到存储器中。7.3.3用子程序实现排序任务本练习中,我们使用子程序实现排序任务。为了使子程序更为通用,在进入子程序之前先将子程序使用的寄存器的内容保存到堆栈中,离开子程序之前再将这些内容写回寄存器。注意必须通过初始化堆栈指针sp(寄存器r27)建立堆栈,堆栈一般从高地址存储器位置开始向低地址方向增长。当有新的项目压入堆栈或堆栈中的内容弹出之后要动态地调整堆栈指针。为了保证堆栈由高地址向低地址增长,在新项目压入堆栈之前,堆栈指针先减4,项目从堆栈中弹出后,必须将堆栈指针再加4。请参照以下步骤修改7.3.2小节中的程序,完成练习:
(1)编写一个名为SORT的子程序,能够对存储器中任意位置任意数量的数据进行排序,假设数据列表的地址和数量通过如下寄存器传递给子程序:①参数size(排序数据的数量)由NiosⅡ寄存器r2给定。②列表中第一个项目的地址由寄存器r3的内容给定。
(2)编写一个主程序,初始化堆栈指针,将所需要的参数写入寄存器r2和r3,然后调用子程序SORT进行排序。同时将数据列表装载到存储器中的LIST_FILE处。
(3)编译并下载程序。
(4)建立一个示例数据列表,装载到存储器中并运行程序。7.3.4用堆栈向子程序传递参数修改7.3.3小节中的程序,用堆栈从主程序向子程序传递参数。编译、下载并运行程序。7.3.5用递归算法计算阶乘所有的NiosⅡ处理器都使用ra寄存器(r31)来保存子程序调用时的返回地址,在子程序中又会调用另外一个嵌套子程序,此时必须确保第一次子程序调用的返回地址不会被新写入ra的返回地址所覆盖。解决这个问题常用的办法是,先将第一次子程序调用的返回地址压入堆栈,第二个子程序返回时再将第一个子程序的返回地址重新写回ra。我们通过计算一个给定整数n的阶乘来探讨嵌套调用子程序的概念。整数n的阶乘由下式表示:n!=n(n-1)(n-2)×…×2×1也可以用下式递归计算:n!=n(n-1)!请注意:0!=1。请编写一个用递归算法计算n的阶乘的程序。程序中包括一个子程序FACTOR,该子程序重复调用自己,直至完成阶乘的计算。主程序通过堆栈将参数n传递给子程序。提示:由于子程序中要使用乘法指令mul,因此7.3.1小节中的系统一定要选择NiosII/s处理器,经济版NiosⅡ处理器NiosⅡ/e不能实现mul指令。编译、下载并运行程序,用不同的n验证其正确性。7.4轮 询 与 中 断本练习的目标是学习如何通过I/O设备发送和接收数据。可以用两种方法来获得I/O设备的状态:第一种方法称做轮询,处理器不断地查询I/O设备来确定是否可以发送数据或接收数据;第二种方法称做中断,由I/O设备主动向处理器表明已经提供了有效数据或可以接收处理器发送的数据。一个简单而且通用的处理器与I/O设备之间传输数据的方案是UART接口电路。UART接口电路置于处理器与外部I/O设备之间,每次处理一个8位字符。UART接口电路与处理器之间的数据传输是并行的,即使用一组连线一次完成一个字符的传输;而UART与I/O设备之间的数据传输采用串行传输,即每一次只传输一位字符。
SOPCBuilder可以为NiosⅡ系统提供一个名为JTAGUART的UART类型的接口电路。这个电路可以用来在DE2平台上的NiosⅡ处理器与计算机主机之间建立连接。图7.4是JTAGUART的原理框图,JTAGUART的一端连接到Avalon交换架构,另一端通过USB-Blaster连接到主机。JTAGUART中包括Data和Control等两个寄存器,NiosⅡ处理器可以按存储器地址的方式访问这两个寄存器,Control寄存器的地址比Data寄存器的地址高4个字节。JTAGUART中还包括两个FIFO作为存储缓冲,一个用来存储排队等候发送的数据,一个用来存储从主机传来的排队等候接收的数据。图7.5给出了寄存器的格式。图7.4JTAGUART原理框图图7.5JTAGUART的寄存器(a)数据寄存器(Data);(b)控制寄存器(Control)
Data寄存器中各字段的定义如下:
(1) b7~b0(DATA):8位字符型数据,处理器用Store操作可以将这个数据写入发送FIFO,用Load操作则将接收FIFO中的第一个数据写入Data寄存器。
(2) b15(RV,RVALID):表明DATA中是否包含能够被处理器读取的有效数据,如果DATA字段有效,则RV置1,否则RV置0。
(3) b31~b16(RAVAIL):表明此次读取之后,接收FIFO中还有多少有效数据等待读取。
Control寄存器中各字段的定义如下:
(1) b0(RE):如果置1则允许读中断。
(2) b1(WE):如果置1则允许写中断。
(3) b8(RI):如果置1则表明有未决的读中断,读取DATA中的数据可自动将RI清零。
(4) b9(WI):如果置1则表明有未决的写中断。
(5) b10(AC):如果置1则表明自从上次清零之后发生过JTAG活动(比如主机通过轮询来验证JTAG连接是否存在等),向AC写入1可以将AC清零。
(6) b31~b16(WSPACE):表明发送FIFO中剩余空间的数量。关于JTAGUART的更多信息请参考QuartusⅡVersion6.0HandbookVolume5:AlteraEmbeddedPeripherals的第5章。7.4.1建立一个包含计时器及JTAGUART的NiosⅡ系统用SOPCBuilder建立一个如图7.6所示的系统,该系统包含一个NiosⅡ/s处理器、一个JTAGUART、一个存储器块及一个计时器(IntervalTimer)。图7.6包含计时器及JTAGUART的系统请参照以下步骤实现该系统:
(1)新建一个QuartusⅡ工程,选择DE2平台上的CycloneⅡEP2C35F672C6作为目标器件。
(2)使用SOPCBuilder建立一个名为nios_system的系统,该系统包括以下部件:①带JTAGDebugModuleLevel1的NiosⅡ/s处理器。②RAM模式32K字节深度的片上存储器。③使用缺省设置的JTAGUART。④计时器(Other组中的IntervalTimer),如图7.7所示,定时器硬件选项中的PresetConfigurations选择Simpleperiadicinterrupt,TimeoutPeriod选择固定500 ms。图7.7计时器设置
(3)用System>Auto-AssignBaseAddresses菜单为NiosⅡ系统自动分配地址,得到如图7.8所示的系统。
(4)生成该系统后,退出SOPCBuidler并返回QuartusⅡ软件。
(5)在Verilog/VHDL顶层设计中例化生成的NiosⅡ系统。
(6)分配引脚如下:①clk-PIN_N2作为50 MHz时钟输入。②reset_n-PIN_G26作为AlteraDE2平台上的按键KEY0。
(7)编译QuartusⅡ工程。
(8)下载并配置DE2上的CycloneⅡ系列FPGA以实现生成的系统。图7.8用SOPCBuilder实现包含计时器及JTAGUART的系统7.4.2通过JTAGUART向主机发送字符
JTAGUART可以向AlteraDebugClient传送ASCII字符,AlteraDebugClient将接收到的ASCII字符显示在终端窗口中,当JTAGUART控制寄存器中的WSPACE字段为非零值时,JTAGUART可以接收处理器发送到AlteraDebugClient的字符。当处理器向AlteraDebugClient发送字符时,将轮询(连续读取)控制寄存器直至发送FIFO中有剩余的空间出现,一旦发送FIFO中有剩余的空间,处理器就可以将要发送的字符数据写入JTAGUART的Data寄存器中。编写一个NiosⅡ汇编语言程序,每隔500 ms在AlteraDebugClient的终端窗口中显示字符“Z”,请参照以下步骤建立并执行该程序:
(1)使用NiosⅡ汇编语言编写程序,循环读取JTAGUART的Control寄存器直至发送FIFO中有多余的空间出现。
(2)向Data寄存器中写入Z。
(3)使用AlteraDebugClient,编译并下载该汇编语言程序。
(4)单步执行这个程序,如果连续运行该程序,发送到AlteraDebugClient的字符会太多而导致终端窗口来不及处理接收到的字符。
(5)在汇编语言代码中,增加一个延迟循环,使处理器约每0.5 s向AlteraDebugClient发送一个字符。
(6)重新编译、装载并运行该程序。7.4.3用JTAGUART实现打字机功能
JTAGUART不仅可以向终端窗口写字符,还可以从终端窗口中接收ASCII字符,JTAGUART的Data寄存器的RVALID位(b15)表明DATA字段中是否包含接收到的有效数据,如果接收FIFO中还有更多的数据等待读取,则RAVAIL字段是一个非零值。编写一段程序实现一个类似打字机的任务,处理器读取JTAGUART从主机接收到的字符后,将这个字符在AlteraDebugClient的终端窗口上显示出来。使用轮询的方式判断JTAGUART是否接收到了有效数据。注意:必须将光标置于终端窗口中才能通过键盘向JTAGUART的接收端口写数据。7.4.4使用中断方式实现打字机功能使用轮询方式处理UART的数据接收时,要通过读取寄存器的值来确定UART的状态,这会产生额外的开销,因此效率较低,并显著地降低了程序的性能。如果使用中断方式,则让处理器在等待I/O设备传输数据时进行其他工作,可大大提高程序的性能。建立一个中断服务程序以读取JTAGUART从主机接收到的字符,将中断服务程序放在十六进制地址0x20处,这个地址是SOPCBuilder确定的异常处理程序(ExceptionHandler)缺省地址。将寄存器ea中的异常返回地址减4可以得到外部中断地址。代码7.2是用NiosⅡ汇编语言编写的终端服务程序的框架。代码7.2中断服务程序框架。.include“nios_macros.s”.text.org0x20 /*将中断服务程序放在相应地址*/ISR:rdctlet,ctl4 /*检查是否有外部中断发生*/beqet,r0,SKIP_EA_DECsubiea,ea,4 /*如果有外部中断发生,将ea减4以执行中断指令*/SKIP_EA_DEC: ...中断服务程序END_ISR:eret /*从异常处理程序中返回*/.global_start_start: /*程序起始位置*/ ...中断使能代码
...主程序代码LOOP: brLOOP /*无限循环*/.end可以用NiosⅡ控制寄存器ctl3(或叫做ienable寄存器)来单独打开中断。注意在7.4.1小节建立的系统中JTAGUART的中断被设为level0,这表明必须将ctl3的bit0置1才能打开JTAGUART的中断。请参照以下步骤完成练习:
(1)建立一个从JTAGUART读取字符的中断服务程序,注意中断服务程序必须放在存储器中0x20的位置,只有将相应的值写入JTAGUART的Control寄存器、NiosⅡ控制寄存器ctl0及ctl3,才能打开中断。
(2)在中断服务程序中使用轮询的方法将接收到的字符显示到主机上运行的AlteraDebugClient终端窗口中。
(3)编译、装载并运行程序。如果程序不能正常运行,则必须对程序进行调试以修正错误。AlteraDebugClient的单步调试特性允许使用者在每一条指令执行之后观察执行的程序流以及NiosⅡ的寄存器内容,这是一个很有效的调试工具。但单步执行会自动禁止中断,因此这种方法无法调试中断服务程序,对于含有中断的应用,可以通过设置断点来调试程序。另外还需要注意,执行中断服务程序时会自动禁止中断,中断服务程序结束后才能重新打开中断,因此,当有些应用需要使用嵌套中断时,必须在进入中断服务程序后重新打开中断。7.4.5计时器中断的使用本练习中,我们用中断方式读取JTAGUART从主机接收到的字符,并以500 ms的时间间隔将最后接收到的字符重复显示在AlteraDebugClient的终端窗口中。在7.4.2小节中我们用延时循环近似实现了这个时间间隔,现在改用计时器电路来实现500 ms的时间间隔。计时器每500 ms向处理器发送一次中断,处理器接收到这个中断后,通过JTAGUART向DebugClient终端窗口发送一个字符。计时器内部有一个计数器,将这个计数器设定为一个特定的初值,在每一个时钟周期内,计数器的值减1,当计数器的值为0时,会产生一个超时(Timeout)事件,计时器相应地产生一个中断而计数器的值被重新置于原来设定的值。与JTAGUART一样,计时器也有一组可以按存储器地址访问的16位寄存器,图7.9所示为Status寄存器(状态寄存器)和Control寄存器(控制寄存器)。状态寄存器(Status)的地址为计时器的基地址,控制寄存器(Control)的地址比Status寄存器的地址高4个字节。图7.9计时器的寄存器(a)状态寄存器(Status);(b)控制寄存器(Control)状态寄存器中各位的定义如下:
(1) b0(TO):超时位,当计时器中计数器的值为0时,该位自动置1,只有处理器向该位写入0才可以将该位清零。
(2) b1(RUN):当内部计数器运行时该位为1,否则该位为0,状态寄存器的写操作对此位无效。控制寄存器中各位的定义如下:
(1) b0(ITO):置为1时允许计时器中断。
(2) b1(CONT):用以确定计数器内部的寄存器到0后如何处理,如果CONT=1,计数器将自动重新装载,否则计数值到0后计数器将停止工作。
(3) b2(START):通过向这个寄存器写入1来启动计数器。
(4) b2(STOP):通过向这个寄存器写入1使计数器停止计数。关于计时器的更多信息请参考QuartusⅡ Version6.0HandbookVolume5:AlteraEmbeddedPeripherals的第12章。如图7.8所示,JTAGUART的中断连接在NiosⅡ处理器的中断线0上,而计时器连接在处理器的中断线1上,因此同时打开JTAGUART中断和计时器中断,需要将控制寄存器ctl3的b0和b1位都置1。控制寄存器ctl4(也叫做ipending寄存器)可以用来确定发生何种中断。如果一个外设的中断被寄存器ctl3所禁止,即使这个外设将其中断请求线置1也不能启动中断服务程序,且不会影响寄存器ctl4的值。请参照以下步骤完成练习:
(1)修改7.4.4中的程序,在主程序中打开JTAGUART和计时器中断,然后进入无限循环。
(2)修改中断服务程序来处理JTAGUART中断和计时器中断。
(3)为了启动这些中断,必须向JTAGUART的Control寄存器、计时器的Control寄存器和NiosⅡ的控制寄存器ctl0和ctl3写入相应的值。
(4)编译、下载并运行程序。7.5总线通信本练习学习如何使用总线进行通信。由SOPCBuilder生成的NiosⅡ系统设计中,NiosⅡ处理器通过Avalon交换架构与外设相连,外设需要通过SOPCBuilder的部件(Component)连接到Avalon交换架构上。为了研究总线通信,本练习不需要建立专用的SOPCBuilder部件,而是通过SOPC的部件Avalon至外部总线桥(AvalontoExternalBusBridge)与外部总线通信,设计者可以使用这个总线桥在QuartusⅡ软件中建立一个外设并连接到NiosⅡ系统。AvalontoExternalBusBridge建立了一个可以连接多个“从”设备的类似于总线的接口。图7.10为外部总线的信号及时序,所需要的信号如下:
(1) Address:k位地址信号(最多32位)。所要传输数据的地址按字节计算,自动与数据的尺寸对齐,对于32位数据,地址的低两位等于0,使用ByteEnable信号可以传输少于4字节的数据。
(2) BusEnable:1位总线使能信号。
(3) R/W:1位读写信号,1表示读传输,0表示写传输。
(4) ByteEnable:16、8、4、2或者1位字节使能信号,每一位表示能否对相应的字节进行读写,ByteEnable高电平有效。
(5) WriteData:128、64、32、16或8位写数据,在写传输中向外设传输的数据。
(6) Acknowledge:1位应答信号,外设通过应答信号表明数据传输结束。
(7) ReadData:128、64、32、16或8位读数据,在读传输中从外设读取的数据。
(8) IRQ:1位中断信号,外设用来中断NiosⅡ处理器的信号,中断信号是可选信号,没有在图中出现。图7.10Avalon至外部总线桥的信号(a)外部总线信号;(b)外部总线时序这个总线是一个同步总线,所有向外设传输的信号必须在时钟的上升沿被读取。将Address、R/W、ByteEnable以及可能的WriteData信号设置为合适的值,然后将BusEnable信号设置为1,可以发起一次传输。如果R/W信号为1,则表明传输是一个读操作,外设必须将ReadData设置为合适的值,并将Acknowledge信号置1。Acknowledge信号必须且只能保持一个时钟周期,ReadData信号在Acknowledge信号有效期间,必须保持不变。如果Acknowledge信号保持两个或两个以上的时钟周期,Avalon交换架构可能会认为这是另一次总线传输,因此Acknowledge信号只能保持一个时钟周期。如果R/W信号为0,则表明该传输是一个写操作,外设应该将WriteData线上的数据写入适当的位置。一旦外设完成了写传输,则必须将应答信号置1并保持一个时钟周期。7.5.1实现外部总线桥及七段数码管控制器图7.11为本练习中实现的系统,它可以由SOPCBuilder生成。该系统包括一个NiosⅡ/s处理器、一个JTAGUART、一个片上存储器块以及一个Avalon至外部总线桥。生成的系统如图7.12所示,从外设是一个由用户编写的Verilog/VHDL模块。Avalon至外部总线桥将NiosⅡ系统的Avalon交换架构与前文所述的外部总线连接起来,Avalon交换架构是SOPCBuilder所生成的系统中外设的主要互联网络。图7.11包含了外部总线接口的NiosⅡ系统原理图7.12包含了外部总线接口的NiosⅡ系统从外设包含四个16位寄存器以及用DE2平台上的七段数码管显示寄存器值的电路。这些寄存器可以按存储器地址来访问,因此NiosⅡ处理器可以直接将数据写入这些寄存器。为了帮助实现上述从外设,提供了三个Verilog/VHDL模块,其中的一个模块提供了完整的代码,另外两个模块只给出了代码的架构,本练习的一部分就是完成这两个模块的代码,这些模块分别如下:
(1) Lab5_Part1(提供了完整的代码)。
(2) Peripheral_on_External_Bus(提供了代码架构)。
(3) Seve_Segment_Display(提供了代码架构)。光盘的DE2_Computer_Organization目录中,压缩文件comporg_lab5_design_files.zip包含了以上文件,也可以从Altera的网站/up/pub/Laboratory_Exercises/Comp_Org/comporg_lab5_designfiles.zip上获得。生成如图7.12所示的系统之后,修改Verilog/VHDL模块Peripheral_on_External_Bus,将它连接到Avalon至外部总线桥的信号上,另外修改这个模块使之包含四个寄存器,将每一个寄存器映射为SOPCBuilder分配给地址的1/4,并使用七段数码管HEX3~HEX0显示这些寄存器的内容。由于每次只能在数码管上显示一个寄存器的内容,因此使用波段开关SW1和SW0来选择所要显示的寄存器。以上设置再加上SOPCBuilder生成的系统即可实现如图7.11所示的系统。为了使用外部总线桥,必须在启动SOPCBuilder软件之前,将目录altera_up_avalon_to_external_bus_bridge复制到工程目录中,这个目录可以从Altera大学计划/up/pub/university_Program_IP_Cores/avalon_to_external_bus_bridge.zip上获得。光盘的\DE2_Computer_Organization\University_Program_IP_Cores目录下也可以找到这个压缩文件。请按以下步骤实现所要求的系统:
(1)新建一个名为Lab5_Part1的QuartusⅡ工程,选择DE2平台上的CycloneⅡEP2C35F672C6作为目标器件。
(2)使用SOPCBuilder建立一个名为nios_system的系统,该系统包含以下部件:①带JTAGDebugModuleLevel1的NiosⅡ/s处理器。②RAM模式32 K字节深度的片上存储器。③采用缺省设置的JTAGUART。④Avalon至外部总线桥,选择数据宽度为16位,地址范围为512 K字节。选择这个参数是为了在7.5.2小节的练习中能方便地与SRAM连接。在SOPCBuilder窗口中,外部总线桥组件的位置为AvalonComponents>UniversityProgramDE2Board>AvalontoExternalBusBridge。注意:选择512 K字节的地址范围意味着实现的总线上共有k=19根地址线。
(3)将Avalon至外部总线桥连接到NiosⅡ的data_master端口而不是instruction_master端口,可以通过单击SOPCBuilder窗口中的连接路径来移除总线桥与instruction_master端口之间的连接。
(4)用System>Auto-AssignBaseAddress菜单自动分配地址空间,可以得到如图7.12所示的系统。
(5)生成系统后,退出SOPCBuilder并返回QuartusⅡ软件。
(6)将上面提到的四个Verilog/VHDL模块加入到QuartusⅡ工程中。
(7)检查给定的Verilog/VHDL模块Lab5_Part1是否正确地例化了生成的NiosⅡ系统。
(8)修改Verilog/VHDL模块Peri
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 26年中耳癌靶向临床原则解析
- 家装顾问招聘规划
- 职业生涯规划大纲
- 煤炭运输框架协议2026年
- Q-ZF 001-2023 化工设备安装工程施工质量验收标准
- 高考文化常识试题及答案
- 中学教师资格证教育知识与能力题库及解析
- 渔业技术淡水养鱼试卷及详解
- 财务分析师试题及答案
- 高等代数试题及详解
- 2026中国铁塔夏季校园招聘备考题库附答案详解(轻巧夺冠)
- 2026年软考高级系统架构设计师真题及答案解析
- 2026重庆新华书店有限公司招聘工作人员47名备考题库及参考答案详解一套
- 2025年软考《数据库系统工程师》考试试题及答案
- 2026年湖北省黄冈市八年级地理生物会考真题试卷(+答案)
- 2026年部编版新教材语文一年级下册第四单元检测题(有答案)
- 江西省省宜春市袁州区重点名校2026届中考数学模拟预测题含解析
- 舞蹈类创新创业
- 部编版(2024)七年级下册 第六单元 单元测试题(含答案)
- 2026年中煤科工(西安)智能成套装备科技有限公司招聘备考题库及完整答案详解1套
- 水法知识讲座课件
评论
0/150
提交评论