可编程FPGA数字系统设计实验指导书 - 图文

更新时间:2024-05-08 03:56:01 阅读量: 综合文库 文档下载

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

可编程FPGA

数字系统设计实验指导

西安电子科技大学

空间科学与技术学院编制

目录

第一部分 课程简介 ......................................................................................................................... 3 一.课程简介 ................................................................................................................................................ 3 二.实验项目及学时安排............................................................................................................................. 3 第二部分 实验基础知识 ................................................................................................................... 4 一.实验的基本过程 ....................................................................................................................................... 4 二.实验中操作规范和常见故障检查方法.................................................................................................... 4 三、DE2-115型数字系统综合实验平台简介 .............................................................................................. 5 四、Quartus ii 10.0在本实验中的使用 .....................................................................................................11 第三部分 Verilog HDL语言设计实验 ............................................................................................... 17 实验一 简单的组合逻辑和时序逻辑的设计 ........................................................................................... 17 实验二 复杂时序逻辑电路的设计 ........................................................................................................... 20 实验三 函数和任务的应用设计 ................................................................................................................. 24 实验四 有限状态机(FSM)的设计 ......................................................................................................... 28 实验五 基于模块多层次引用的结构化电路设计 ..................................................................................... 32 第四部分 综合实验: ......................................................................................................................... 36 实验一:8位十进制频率计设计 ............................................................................................................... 36 实验二:出租车自动计费器....................................................................................................................... 36 实验三:正弦波信号发生器....................................................................................................................... 37

第一部分 课程简介

一.课程简介

本课程是电子工程和计算机科学等的选修专业课。Verilog HDL程序设计是电子信息类专业学生在学习完数字电子技术后的选修专业课程,主要内容是学习利用Verilog HDL进行数字逻辑电路和系统的开发和设计。

通过对该课程的学习,学生应该掌握Verilog HDL的词法、语法、句法,可综合程序的编写,仿真及测试程序的编写,一般数字逻辑的实现,复杂数字逻辑和算法的实现,并能够初步的利用Verilog HDL进行时序及逻辑系统的设计,并对寄存器传输级(RTL)上的设计方法掌握和理解。

Verilog HDL语言设计是一门理论与实践联系紧密的课程,所以本课程安排5个实验,以帮助学生掌握Verilog HDL程序设计技术,提高学生分析问题和解决问题的能力,并通过实验培养学生的创新意识。

本实验课的基本要求如下:

1.学会用Verilog HDL语言编写数字电路和系统的程序,通过上机实习加深对课堂所学知识的理解;

2.上机前应按照要求把实验内容准备好,即编好程序及需要改变的参数,能预计出可能出现的结果;

3.观察实验结果,得出结论; 4.实验结束时提交实验报告。

二.实验项目及学时安排

序号 1 2 3 4 5

项目 简单的组合逻辑和时序逻辑的设计 复杂时序逻辑电路的设计 函数和任务的应用设计 有限状态机(FSM)的设计 基于模块多层次引用的结构化电路设计 学时 验证 4 4 4 4 4 实验性质 综合 设计 √ √ √ √ √ 3

第二部分 实验基础知识

一.实验的基本过程

实验的基本过程,应包括:1,熟悉实验平台;2,确定实验内容;3,选定最佳的实验方法和实验线路;4,拟出较好的实验步骤、进行仿真和调试、最后写出完整的实验报告。

在利用Verilog HDL进行数字系统设计实验时,充分掌握和正确利用Verilog语言独有的特点和规律,可以收到事半功倍的效果,对于完成每一个实验,应做好实验预习、实验记录和实验报告等环节。 (一) 实验预习

认真预习是做好实验的关键。预习好坏,不仅关系到实验能否顺利进行,而且直接影响实验效果。预习应按本教材的实验预习要求进行,在每次实验前首先要认真复习有关实验的基本原理,对如何着手实验做到心中有数,通过预习还应做好实验前的准备。 (二) 实验记录

实验记录是实验过程中获得的第一手资料。测试过程中所测试的数据和波形必须和理论基本一致,所以记录必须清楚、合理、正确,若不正确,则要现场及时重复测试,找出原因。 (三) 实验报告

实验报告是培养学生科学实验的总结能力和分析思维能力的有效手段,也是一项重要的基本功训练,它能很好地巩固实验成果,加深对基本理论的认识和理解,从而进一步扩大知识面。

实验报告是一份技术总结,要求文字简洁,内容清楚,图表工整。报告内容应包括实验目的、实验内容和结果、实验使用仪器和元器件以及分析讨论等,其中实验内容和结果是报告的主要部分,它应包括实际完成的全部实验,并且要按实验任务逐个书写,每个实验任务应有如下内容:

1.实验课题的方框图、逻辑图、状态图,真值表以及文字说明等,对于设计性课题,还应有整个设计过程和关键的设计技巧说明。

2.实验结果分析、讨论及结论,对讨论的范围,没有严格要求,一般应对重要的实验现象、结论加以讨论,以便进一步加深理解,此外,对实验中的异常现象,可作一些简要说明,实验中有何收获,可谈一些心得体会。

二.实验中操作规范和常见故障检查方法

实验中操作的正确与否对实验结果影响甚大。因此,实验者需要注意按以下规程进行。 1.搭接实验电路前,应对仪器设备进行必要的检查校准,对所用集成电路进行功能测试。

4

2.搭接电路时,应遵循正确的布线原则和操作步骤(即要按照先接线后通电,做完后,先断电再拆线的步骤)。

3.掌握科学的调试方法,有效地分析并检查故障,以确保电路工作稳定可靠。 4.仔细观察实验现象,完整准确地记录实验数据并与理论值进行比较分析。

5.实验完毕,经指导教师同意后,可关断电源拆除连线,整理好放在实验箱内,并将实验台清理干净、摆放整洁。

三、DE2-115型数字系统综合实验平台简介

DE2-115型数字系统综合实验平台是以FPGA芯片数数主的可进行数字逻辑、微机原理、接口技术等数字技术的课程实验。本实验通过所需完成数字逻辑的器件配置图来配置FPGA核心芯片完成相关的逻辑功能。

1、DE2-115型FPGA综合实验平台介绍 FPGA核心芯片“

C7N”,配置方式有TJAG和AS模式两种,配置

控制芯片为EPCS64,使用USB Blaster进行在线配置。系统上电后不断进行自检。

2、本实验中涉及主要引脚

(1)拨动开关(SW)与FPGA引脚对应关系

5

(2)按钮开关(KEY)与FPGA引脚对应关系

(3)LED指示灯与FPGA引脚对应关系

6

(4)数码管与FPGA引脚对应关系

7

3、DE2-115下载器连接与配置

8

(1)配置Cyclone IV E FPGA芯片

在Quartus II 软件使用简介中,我们已经介绍了如何从PC 下载一个硬件电路到DE2-115 开发板。这份使用说明书可以在DE2-115 系统光盘里面的DE2_115_tutorials 目录下面找到。用户应该首先仔细阅读这份说明书,而把以下的介绍作为简短的参考。 DE2-115 开发板包含一个存储有Cyclone IV E FPGA 芯片配置数据的串行配置芯片。每次开发板上电的时候,芯片里面的配置数据会自动从配置芯片加载到FPGA 芯片。使用Quartus II软件,用户可以随时重新配置FPGA,并可以改变存储在非易失性串行存储器芯片(EPCS)里面的数据。下面分述两种不同的配置方式:

1)JTAG 编程:这种下载方式-名字起源于IEEE 标准,联合测试行动组-会把配置数据直接加载到Cyclone IV E FPGA 芯片。FPGA 芯片会保持这些配置信息直到芯片掉电。

2)AS 编程:这种下载方式被叫称作串行主动编程,它会下载配置数据到Altera EPCS64 芯片。它将配置数据保存在非易失性器件中,即使DE2-115 开发板掉电,数据也不会丢失。在每次开发板上电的时候,EPCS64 芯片里面的数据会自动加载到Cyclone IV E FPGA 芯片。

(2)DE2-115 开发板上的JTAG 链

当使用JTAG 接口配置FPGA 芯片的时候,DE2-115 上的JTAG 链必须形成一个回路,这样Quartus II 软件才可以正确检测到JTAG 链上的FPGA/CPLD 器件。给出了DE2-115 开发板上的JTAG 链。短接JP3 上的第一、二引脚会旁路HSMC 接头的JTAG信号,直接在DE2-115 上形成JTAG 回路,这样只有DE2-115上的FPGA 器件(Cyclone IV E)才可以被Quartus II 软件检测到。如果用户想通过HSMC 接头包含其它的FPGA器件或者包含FPGA器件的界面,短路JP3 的第二、三脚,从而使能HSMC接头上的JTAG 链。

以下是关于JTAG 和AS 编程的操作步骤。对于这两种方式,DE2-115 开发板均通过USB

电缆连接到PC 主机。通过这种连接,主机将开发板当做一个Altera USB-Blaster

设备。在主机上安装USB-Blaster 驱动的步骤在说明书“Getting Started with Altera’s DE2-115 Board”(tut_initialDE2-115.pdf)中有详细描述。这份说明书可以在DE2-115 的系统光盘中找到。

(3)使用JTAG 模式配置FPGA

给出了JTAG 编程模式的设定信息。执行以下步骤,以将配置数据下载到Cyclone IV E FPGA:

??确保DE2-115 已经正确连接好电源

??将RUN/PROG 拨动开关(SW19)放置在RUN 位置

??将附带的USB 电缆连接到DE2-115 开发板的USB-Blaster 电路上。

??现在可以通过Quartus II 编程器选择合适的以.sof 为扩展名的配置数据来配置DE2-115 的FPGA 芯片了

9

(4)使用AS 模式配置EPCS64 芯片

图 4-5 给出了AS 配置模式的设定。执行以下步骤,以将配置数据下载到EPCS64 芯片:

??确保DE2-115 已经连接好电源

??连接附带的USB 电缆到DE2-115 的USB-Blaster 接口 ??将RUN/PROG 拨动开关(SW19)放置在PROG 位置

??现在可以通过Quartus II 编程器通过选择以.pof 位扩展名的配置文件来编程EPCS64 器件了 ??编程结束后,将RUN/PROG 开关拨回RUN 位置,关闭然后打开DE2-115 的电源开关。

通过这次重启,FPGA 将从EPCS64 器件读取新的配置数据

(5)拨动开关与按钮开关的使用

DE2-115 提供了四个按钮开关,如图4-6所示。每个按钮开关都通过一个施密特触发器进行了去抖动处理,如图4-7所示。四个施密特触发器的输出信号,分别为KEY0,KEY1,KEY2,KEY3,直接连接到了Cyclone IV E FPGA。当按钮没有被按下的时候,它的输出是高电平,按下去则给出一个低电平。得益于去抖动电路,这些按钮开关适合用来给内部电路提供(模拟的)时钟或者复位信号。

1 0

DE2-115 开发板上还有18 个拨动开关(参考图4-8)。这些开关没有去抖动电路,它们可以作为对电平敏感的电路的输入数据。每个开关都直接连接到Cyclone IV E FPGA。

当拨动开关在DOWN 位置(靠近开发板边缘)的时候,输出为低电平,当在UP 位置时,输出为高电平。

Cyclone IV E FPGA 到拨动开关间的详细引脚连接信息请参考表见前面引脚对应表格。

(6)LED指示灯的使用

DE2-115 开发板共有27 个直接由FPGA 控制的LED。18 个红色的LED 位于18 个拨动开关

的正上方,8 个绿色LED 可以在按钮开关的上方找到(第九个LED 位于七段数码管的中间)。 每一个LED 都由Cyclone IV E FPGA 的一个引脚直接驱动,其输出高电平则点亮LED,输出低电平LED 熄灭。图 4-9 给出了LED 和Cyclone IV E FPGA 之间的连接示意图。

四、Quartus ii 10.0在本实验中的使用

1. 新建一个文件夹FPGA,再启动QuratusII 2. 启动后界面

11

3. 点

新建工程,出现以下界面

4. 在出现的界面里第一行上选择新建的FPGA文件夹,第二行上输入myHDL,点finish完成后出现

如下界面

1 2

5. 再新建文件,选择“Verilog HDL File”

6. 出现编辑界面

7.

文本文件编辑器里,键入上述语句. Click Save. 这样就完成了Verilog HDL的输入。

1 3

8. 重新命名各信号引脚。双击某信号引脚(输入或输出),出现界面后修改信号引脚名称。再按“

进行预编译,检查是否有错。 9. 在主菜单点“Assignments”,下拉菜单中选“Device…”,在出现的界面中,“Family”选择“cyclone

IV E”,在下面列表中选与实验板FPGA主芯片对应的芯片名称,如“EP4CE115F29C7”,点“OK”确定

10. 点“

”选对应器件引脚。在出现的界面上选与实验板上对应的引脚与原理图输入输出引脚对

应。引脚输入输出对应开关和指示灯见DE2-115实验板使用手册。

1 4

11. 重新按“

”编译,编译时有“%”指示。

12. 连接实验板(USB),查看设备管理中有无“USB-Blaster”连接

13. 按主界面中图标“

”,在出现的界面中查看下载器件是否连接,编译后的文件是否在上面。

1 5

14. 在上面界面上点“(等待一段时间或重) 15. 运行实验板,看逻辑变化

”将编译后的文件“XX.sof”下载到实验板中,看下载指示条

1 6

第三部分 Verilog HDL语言设计实验

实验一 简单的组合逻辑和时序逻辑的设计 一、实验目的

1、掌握基本组合逻辑电路的实现方法,掌握连续赋值语句和条件赋值语句的使用方法; 2、掌握基本时序逻辑电路的实现,掌握always语句的使用方法。

二、实验原理、内容及步骤

1、简单组合逻辑设计

描述组合逻辑电路通常利用assign连续赋值语句的数据流方式。连续赋值语句将值赋给线网(连续赋值不能为寄存器赋值)。连续赋值语句只要在右端表达式的操作数上有事件(事件为值的变化)发生时,表达式即被计算,如果结果值有变化,新结果就赋给左边的线网。

连续赋值的目标类型如下:1) 标量线网;2) 向量线网;3) 向量的常数型位选择;4) 向量的常数型部分选择;5) 上述类型的任意的拼接运算结果。

组合逻辑设计示例:可综合的数据比较器。它的功能是比较数据a与数据b,如果两个数据相同,则给出结果1,否则给出结果0。描述组合逻辑时常使用assign结构。注意equal=(a==b)?1:0,这是一种在组合逻辑实现分支判断时常使用的格式。

模块源代码:

//--------------- compare.v ----------------- module compare(equal,a,b);

input a,b; output equal;

assign equal=(a==b)?1:0; //a等于b时,equal输出为1;a不等于b时, //equal输出为0。 endmodule

测试模块用于检测模块设计得正确与否,它给出模块的输入信号,观察模块的内部信号和输出信号,如果发现结果与预期的有所偏差,则要对设计模块进行修改。

测试模块源代码:

`timescale 1ns/1ns //定义时间单位。

`include \包含模块文件。在有的仿真调试环境中并不需要此语句。 //而需要从调试环境的菜单中键入有关模块文件的路径和名称 module comparetest; reg a,b; wire equal;

initial //initial常用于仿真时信号的给出。 begin a=0; b=0;

#100 a=0; b=1;

1 7

#100 a=1; b=1; #100 a=1; b=0;

#100 $stop; //系统任务,暂停仿真以便观察仿真波形。 end

compare compare1(.equal(equal),.a(a),.b(b)); //调用模块。 endmodule

2、简单时序逻辑设计

在Verilog HDL中,相对于组合逻辑电路,时序逻辑电路也有规定的表述方式。在可综合的Verilog HDL模型,我们通常使用always块和 @(posedge clk)或 @(negedge clk)的结构来表述时序逻辑。

时序逻辑设计示例:可综合的1/2分频器模型。 // half_clk.v:

module half_clk(reset,clk_in,clk_out);

input clk_in,reset; output clk_out; reg clk_out;

always @(posedge clk_in) begin if(!reset) clk_out=0; else

clk_out=~clk_out;

end endmodule

在always块中,被赋值的信号都必须定义为reg型,这是由时序逻辑电路的特点所决定的。对于reg型数据,如果未对它进行赋值,仿真工具会认为它是不定态。为了能正确地观察到仿真结果,在可综合风格的模块中我们通常定义一个复位信号reset,当reset为低电平时,对电路中的寄存器进行复位。

测试模块的源代码:

//------------------- clk_Top.v ----------------------------- `timescale 1ns/100ps `define clk_cycle 50 module clk_Top.v

reg clk,reset; wire clk_out;

always #`clk_cycle clk = ~clk; initial

begin

clk = 0; reset = 1; #100 reset = 0; #100 reset = 1; #10000 $stop; end

half_clk half_clk(.reset(reset),.clk_in(clk),.clk_out(clk_out)); endmodule

1 8

3、组合逻辑及时序设计题

1. 设计一个字节(8位)比较器。要求:比较两个字节的大小,如a[7:0]大于 b[7:0],则点亮

LEDR0,否则点亮LEDR1;用DE2开发板上的switches SW17-0作为输入,用LED和7-segment displays显示为16进制。 2.作clk_in的二分频clk_out,要求输出与上例的输出正好反相。编写测试模块,给出测试波形。

三、实验报告要求

1、简要描述Verilog HDL中实现组合逻辑和时序逻辑的不同语法结构;

2、实验报告应包括Modelsim环境下仿真得到的波形和QuatusII环境下综合得到RTL级电路图; 3、实验报告应附硬件仿真的波形或显示的照片。

1 9

实验二 复杂时序逻辑电路的设计 一、实验目的

1、掌握条件语句if…else在复杂时序逻辑设计中的应用; 2、掌握阻塞赋值与非阻塞赋值的概念和区别,掌握阻塞赋值的使用情况。

二、实验原理、内容及步骤

1.条件语句在Verilog HDL中的使用

与常用的高级程序语言一样,为了描述较为复杂的时序关系,Verilog HDL提供了条件语句供分支判断时使用。在可综合风格的Verilog HDL模型中常用的条件语句有if…else和case…endcase两种结构,用法和C程序语言中类似。两者相较,if…else用于不很复杂的分支关系,实际编写可综合风格的模块、特别是用状态机构成的模块时,更常用的是case…endcase风格的代码。 条件语句示例:可综合风格的分频器。它的功能是将10M的时钟分频为500K的时钟。基本原理与1/2分频器是一样的,但是需要定义一个计数器,以便准确获得1/20分频。

模块源代码:

// --------------- fdivision.v ----------------------------- module fdivision(RESET,F10M,F500K);

input F10M,RESET; output F500K; reg F500K; reg [7:0]j;

always @(posedge F10M) if(!RESET) //低电平复位。 begin F500K <= 0; j <= 0; end else begin if(j==19) //对计数器进行判断,以确定F500K信号是否反转。 begin j <= 0; F500K <= ~F500K; end else j <= j+1; end endmodule

测试模块源代码:

//--------------- fdivision_Top.v ------------------------

2 0

`timescale 1ns/100ps `define clk_cycle 50 module division_Top;

reg F10M_clk,RESET; wire F500K_clk; always

#`clk_cycle F10M_clk = ~ F10M_clk; initial

begin

RESET=1; F10M=0;

#100 RESET=0; #100 RESET=1; #10000 $stop;

end

fdivision fdivision (.RESET(RESET),.F10M(F10M_clk),.F500K(F500K_clk)); endmodule

2.设计时序逻辑时采用阻塞赋值与非阻塞赋值的区别

非阻塞赋值语句(<=)右端表达式计算完后并不立即赋值给左端,而是同时启动下一条语句继续执行,而阻塞赋值语句(=)在每个右端表达式计算完成后立即赋值给左端变量。非阻塞赋值不能用于assign语句中,而只能用于对寄存器型变量进行赋值,只能在intial和always等过程过程块中。阻塞赋值既能用于assign语句,也能用于intial和always等过程赋值中。对于时序逻辑的描述和建模,应尽量使用非阻塞赋值方式。若在同一个always过程块中描述时序和组合逻辑混合电路时也最好使用非阻塞赋值方式。

在always块中,阻塞赋值可以理解为赋值语句是顺序执行的,而非阻塞赋值可以理解为赋值语句是并发执行的。实际的时序逻辑设计中,一般的情况下非阻塞赋值语句被更多地使用,有时为了在同一周期实现相互关联的操作,也使用了阻塞赋值语句。

可综合设计中阻塞赋值和非阻塞赋值设计要点:

1)非阻塞赋值不能用于assign持续赋值中,一般只出现在initial和always等过程块中,对reg型变量进行赋值;

2)当用always块来描述组合逻辑时,既可以用阻塞赋值,也可以用非阻塞赋值。但在同一个过程块中,最好不要同时用阻塞赋值和非阻塞赋值;

3)在向函数funtion的返回值赋值时,应使用阻塞赋值;

4)不能在一个以上的always过程块中对同一个变量赋值,这样会引起冲突,在综合时会报错;

5)在一个模块中,严禁对同一个变量既进行阻塞赋值,又进行非阻塞赋值,这样会在综合时报错;

6)对时序逻辑的描述和建模,应尽量使用非阻塞赋值方式,此外,若在同一个always过程块中描述时序和组合逻辑混合电路时,最好使用非阻塞赋值方式。

阻塞赋值与非阻塞赋值示例:分别采用阻塞赋值语句和非阻塞赋值语句的两个看上去非常相似的两个模块blocking.v和non_blocking.v来阐明两者之间的区别。 模块源代码:

// ------------- blocking.v --------------- module blocking(clk,a,b,c); output [3:0] b,c;

2 1

input [3:0] a; input clk; reg [3:0] b,c; always @(posedge clk) begin b = a; c = b; $display(\ end

endmodule

//------------- non_blocking.v ------------------- module non_blocking(clk,a,b,c);

output [3:0] b,c;

input [3:0] a; input clk; reg [3:0] b,c; always @(posedge clk) begin b <= a; c <= b; $display(\ end endmodule

测试模块源代码:

//------------- compareTop.v ----------------------------- `timescale 1ns/100ps `include \

`include \module compareTop;

wire [3:0] b1,c1,b2,c2;

reg [3:0] a; reg clk; initial begin clk = 0; forever #50 clk = ~clk; end initial begin a = 4'h3; $display(\ # 100 a = 4'h7; $display(\ # 100 a = 4'hf; $display(\ # 100 a = 4'ha;

2 2

$display(\ # 100 a = 4'h2; $display(\ # 100 $display(\ $stop; end non_blocking non_blocking(clk,a,b2,c2); blocking blocking(clk,a,b1,c1);

endmodule

3,设计题

1,10M的时钟,设计一个单周期形状如下的周期波形。

20μs 10μs 20μs

三、实验报告要求

1、简要描述Verilog HDL中条件语句的使用,阻塞性赋值和非阻塞性赋值的区别和使用要点; 2、实验报告应包括Modelsim环境下仿真得到的波形和QuatusII环境下综合得到RTL级电路图; 3、实验报告应附硬件仿真的波形或显示的照片。

2 3

实验三 函数和任务的应用设计 一 、实验目的

1、掌握函数在模块设计中的使用;

2、掌握任务在结构化Verilog HDL设计中的应用。

二、实验原理、内容及步骤

1、 函数在模块设计中的使用

函数可以在模块不同位置执行共同代码。函数只能返回一个值,它不能包含任何时延或时序控制(必须立即执行),并且它不能调用其它的任务。

函数必须带有至少一个输入,在函数中允许没有输出或输入输出说明。函数可以调用其它的函数。

函数说明部分可以在模块说明中的任何位置出现,函数的输入是由输入说明指定。如果函数说明部分中没有指定函数取值范围,则其缺省的函数值为1位二进制数。函数定义在函数内部隐式地声明一个寄存器变量,该寄存器变量与函数同名并且取值范围相同。函数通过在函数定义中显式地对该寄存器赋值来返回函数值。对这一寄存器的赋值必须出现在函数定义中。

函数调用是表达式的一部分。与任务相似,函数定义中声明的所有局部寄存器都是静态的,即函数中的局部寄存器在函数的多个调用之间保持它们的值。

下例是函数调用的一个简单示范,采用同步时钟触发运算的执行,每个clk时钟周期都会执行一次运算。并且在测试模块中,通过调用系统任务$display在时钟的下降沿显示每次计算的结果。

模块源代码:

module tryfunct(clk,n,result,reset); output[31:0] result; input[3:0] n; input reset,clk; reg[31:0] result; always @(posedge clk) //clk的上沿触发同步运算。

begin

if(!reset) //reset为低时复位。 result<=0; else begin result <= n * factorial(n)/((n*2)+1); end end function [31:0] factorial; //函数定义。 input [3:0] operand; reg [3:0] index; begin factorial = operand ? 1 : 0;

2 4

for(index = 2; index <= operand; index = index + 1) factorial = index * factorial; end endfunction endmodule

测试模块源代码: `include \`timescale 1ns/100ps `define clk_cycle 50 module tryfuctTop;

reg[3:0] n,i; reg reset,clk; wire[31:0] result; initial

begin n=0; reset=1; clk=0; #100 reset=0; #100 reset=1; for(i=0;i<=15;i=i+1) begin #200 n=i; end #100 $stop; end

always #`clk_cycle clk=~clk;

tryfunct tryfunct(.clk(clk),.n(n),.result(result),.reset(reset)); endmodule

上例中函数factorial(n)实际上就是阶乘运算。必须提醒大家注意的是,在实际的设计中,我们不希望设计中的运算过于复杂,以免在综合后带来不可预测的后果。经常的情况是,我们把复杂的运算分成几个步骤,分别在不同的时钟周期完成。

2、 任务在结构化设计中的应用

一个任务就像一个过程,它可以从描述的不同位置执行共同的代码段。共同的代码段用任务定义编写成任务,这样它就能够从设计描述的不同位置通过任务调用被调用。任务可以包含时序控制,即时延控制,并且任务也能调用其它任务和函数。

任务可以没有或有一个或多个参数。值通过参数传入和传出任务。除输入参数外(参数从任务中接收值),任务还能带有输出参数(从任务中返回值)和输入输出参数。任务的定义在模块说明部分中编写。

任务调用:

? 一个任务由任务调用语句调用。任务调用语句给出传入任务的参数值和接收结果的变

量值;

? 任务调用语句是过程性语句,可以在always 语句或initial 语句中使用;

? 任务调用语句中参数列表必须与任务定义中的输入、输出和输入输出参数说明的顺序

匹配。此外,参数要按值传递,不能按地址传递;

2 5

? 任务能够包含定时控制,任务可在被调用后再经过一定时延才返回值;

? 任务调用语句是过程性语句,所以任务调用中的输出和输入输出参数必须是寄存器类

型的;

? 任务可以带有时序控制,或等待特定事件的发生。但是,输出参数的值直到任务退出

时才传递给调用参数。

实例应用:利用task和电平敏感的always块设计比较后重组信号的组合逻辑。可以看到,利用task非常方便地实现了数据之间的交换,如果要用函数实现相同的功能是非常复杂的;另外,task也避免了直接用一般语句来描述所引起的不易理解和综合时产生冗余逻辑等问题。

模块源代码:

//----------------- sort4.v ------------------ module sort4(ra,rb,rc,rd,a,b,c,d); output[3:0] ra,rb,rc,rd; input[3:0] a,b,c,d; reg[3:0] ra,rb,rc,rd; reg[3:0] va,vb,vc,vd; always @ (a or b or c or d) begin {va,vb,vc,vd}={a,b,c,d}; sort2(va,vc); //va 与vc互换。 sort2(vb,vd); //vb 与vd互换。 sort2(va,vb); //va 与vb互换。 sort2(vc,vd); //vc 与vd互换。 sort2(vb,vc); //vb 与vc互换。 {ra,rb,rc,rd}={va,vb,vc,vd}; end task sort2; inout[3:0] x,y; reg[3:0] tmp; if(x>y) begin tmp=x; //x与y变量的内容互换,要求顺序执行,所以采用阻塞赋值方式。 x=y; y=tmp; end endtask

endmodule

值得注意的是task中的变量定义与模块中的变量定义不尽相同,它们并不受输入输出类型的限制。如此例,x与y对于task sort2来说虽然是inout型,但实际上它们对应的是always块中变量,都是reg型变量。

测试模块源代码: `timescale 1ns/100ps `include \module task_Top;

reg[3:0] a,b,c,d;

wire[3:0] ra,rb,rc,rd;

2 6

initial begin a=0;b=0;c=0;d=0;

repeat(5) begin

#100 a ={$random}; b ={$random}; c ={$random}; d ={$random};

end #100 $stop;

sort4 sort4 (.a(a),.b(b),.c(c),.d(d), .ra(ra),.rb(rb),.rc(rc),.rd(rd));

endmodule

3,设计

1,设计一个带控制端的逻辑运算电路,分别完成正整数的平方、立方和阶乘的运算。编写测试模块,并给出仿真波形。

2,设计一个模块,通过任务完成3个8位2进制输入数据的冒泡排序。要求:时钟触发任务的执行,每个时钟周期完成一次数据交换的操作。

三、实验报告要求

1、简要描述Verilog HDL中任务和函数的区别和使用要点;

2、实验报告应包括Modelsim环境下仿真得到的波形和QuatusII环境下综合得到RTL级电路图; 3、实验报告应附硬件仿真的波形或显示的照片。

2 7

实验四 有限状态机(FSM)的设计 一 、实验目的

1、了解FSM的应用范围和两种类型的不同特点; 2、掌握FSM的电路结构和设计要点。

二、实验原理、内容及步骤

1、 FSM相关概念和设计要点

FSM适合于设计数字系统的控制模块。用Verilog HDL的case/if-else等语句能很好地描述基于状态机的设计。状态机可以认为是组合逻辑和时序逻辑的特殊组合。时序逻辑部分用于存贮状态,组合电路用于状态译码和产生输出信号。状态机的下一个状态不仅与输入信号有关,还与状态寄存器当前所处的状态有关。

状态机分为Mealy和Moore两种类型,前者的输出只是当前状态的函数,也就是状态的转换与输入信号无关,后者的输出则是当前状态和当前输入的函数,即状态的转换与输入信号有关。

状态机的表示方法:状态图、状态表和流程图。 状态机设计要点

? 一般采用同步时序方式,在时钟信号的触发下完成状态转移;

? 起始状态是指电路复位后所处的状态,选择一个合理的起始状态将使整个系统简洁、高效,

有的综合器会自动为状态机的设计选择一个最佳的起始状态; ? 状态编码的方式主要有二进制编码、格雷编码和一位热码编码等:

? 二进制编码(Binary State Machine):采用普通的二进制数代表每个状态,如4个状

态state0/state1/state2/state3对应编码为00/01/10/11。这种编码的缺点是相邻状态的转换有可能有多个比特发生变化(如01->10),瞬变次数多,容易产生毛刺,引起逻辑错误;

? 格雷编码(Gray Code State Machine): 4个状态state0/state1/state2/state3对应编

码为00/01/11/10即为格雷编码方式。格雷码节省逻辑单元,而且在状态的顺序转换中相邻状态每次只有一个比特发生变化,这样减少了瞬变的次数,也减少了产生毛刺和一些暂态的可能。

? 一位热码编码(One-Hot State Machine Encoding):采用n位来编码具有n个状态的

状态机 。如4个状态state0/state1/state2/state3对应编码为1000/0100/0010/0001。采用一位热码编码,虽然多用了触发器,但可以有效节省和简化组合电路。对于寄存器数量多而门逻辑相对缺乏的FPGA来说,采用一位热码编码可以有效地提高电路地速度和可靠性,也有利于提高器件资源的利用率。因此,对于FPGA器件,建议采用这种编码方式。采用这种编码会出现一些多余的状态,即一些无效的状态,需要增加default分支项,以便这些状态下能自动回到起始状态。

? 状态编码的定义可以用parameter或者`define语句。建议采用前者。尽量采用同步电路设

计;

`define state0 2’b00 //不要加分号 `define state1 2’b01 …. case (state)

`state0: …; //不能少“`”

2 8

….

? 状态转换一般使用case/casex/casez描述。Case语句比if-else语句更清晰明了。此外,

case语句的最后不要忘了default分支语句以避免锁存器的产生。 2、状态机设计实例

功能是检测一个5位二进制序列“10010”。考虑到序列重叠的可能,有限状态机共提供8个状态(包括初始状态IDLE)。

模块源代码: //seqdet.v

module seqdet(x,z,clk,rst,state);

input x,clk,rst; output z;

output[2:0] state; reg[2:0] state; wire z;

parameter IDLE='d0, A='d1, B='d2,C='d3, D='d4,E='d5, F='d6,G='d7;

assign z = ( state==E && x==0 )? 1 : 0; //当x=0时,状态已变为E, //状态为D时,x仍为1。因此

//输出为1的条件为( state==E && x==0 )。

always @(posedge clk)

if(!rst) begin state <= IDLE; end else casex(state) IDLE : if(x==1)

begin

state <= A; end A: if(x==0) begin state <= B; end B: if(x==0) begin state <= C; end else begin state <= F; end C: if(x==1) begin state <= D; end

2 9

else begin state <= G; end D: if(x==0) begin state <= E; end else begin state <= A; end E: if(x==0) begin state <= C; end else begin state <= A; end F: if(x==1) begin state <= A; end else begin state <= B; end G: if(x==1) begin state <= F; end default:state=IDLE; //缺省状态为初始状态。 endcase

endmodule

测试模块源代码:

//------------------ seqdet.v ------------------- `timescale 1ns/1ns `include \module seqdet_Top; reg clk,rst; reg[23:0] data; wire[2:0] state; wire z,x; assign x=data[23];

3 0

always #10 clk = ~clk; always @(posedge clk)

data={data[22:0],data[23]}; initial begin clk=0; rst=1; #2 rst=0; #30 rst=1; data ='b1100_1001_0000_1001_0100; #500 $stop; end seqdet m(x,z,clk,rst,state);

endmodule

3,设计题

设计一个串行数据检测器。要求是:连续4个或4个以上的1时输出为1,其他输入情况下为0。编写测试模块并给出仿真波形。

四、实验报告要求

1、简要描述Verilog HDL中状态机的相关概念和设计要点;

2、实验报告应包括Modelsim环境下仿真得到的波形和QuatusII环境下综合得到RTL级电路图; 3、实验报告应附硬件仿真的波形或显示的照片。

3 1

实验五 基于模块多层次引用的结构化电路设计 一 、实验目的

1、了解复杂电路与系统的“top-down”设计思想; 2、掌握简单多层次电路的描述方法。

二、实验原理、内容及步骤

1、多层次结构电路的设计

复杂数字系统可采用“top-down”的方法进行设计:首先把系统分为几个模块,每个模块在分为几个子模块,依次类推,知道易于实现为止。

这种“top-down”的方法能够把复杂的设计分为许多简单的设计来实现,同时也适合于多人进行合作开发。

多层次结构电路的描述既可以采用文本方式,也可以采用图形和文本混合设计的方式。 被调用模块的指定方式:1)文件复制方式;2)使用`include语句;3)库管理方式。 2、 设计实例分析

这个实例的功能是将并行数据转化为串行数据送交外部电路编码,并将解码后得到的串行数据转化为并行数据交由CPU处理。显而易见,这实际上是两个独立的逻辑功能,分别设计为独立的模块,然后再合并为一个模块显得目的明确、层次清晰。

模块源代码

// ---------------- p_to_s.v --------------------------------- module p_to_s(D_in,T0,data,SEND,ESC,ADD_100); output D_in,T0; // D_in是串行输出,T0是移位时钟并给 // CPU中断,以确定何时给出下个数据。 input [7:0] data; //并行输入的数据。 input SEND,ESC,ADD_100; //SEND、ESC共同决定是否进行并到串 //的数据转化。ADD_100决定何时置数。 wire D_in,T0; reg [7:0] DATA_Q,DATA_Q_buf; assign T0 = ! (SEND & ESC); //形成移位时钟。. assign D_in = DATA_Q[7]; //给出串行数据。 always @(posedge T0 or negedge ADD_100) //ADD_100下沿置数,T0上沿移位。 begin if(!ADD_100) DATA_Q = data; else begin DATA_Q_buf = DATA_Q<<1; //DATA_Q_buf作为中介,以令综合器 DATA_Q = DATA_Q_buf; //能辨明。 end end

3 2

endmodule

在p_to_s.v中,由于移位运算虽然可综合,但是不是简单的RTL级描述,直接用DATA_Q<=DATA_Q<<1的写法在综合时会令综合器产生误解。另外,在该设计中,由于时钟T0的频率较低,所以没有象以往那样采用低电平置数,而是采用ADD_100的下降沿置数。

//--------------------- s_to_p.v ---------------------------

module s_to_p(T1, data, D_out,DSC,TAKE,ADD_101);

output T1; //给CPU中断,以确定CPU何时取转化 //得到的并行数据。 output [7:0] data;

input D_out, DSC, TAKE, ADD_101; //D_out提供输入串行数据。DSC、TAKE //共同决定何时取数。 wire [7:0] data;

wire T1,clk2;

reg [7:0] data_latch, data_latch_buf;

assign clk2 = DSC & TAKE ; //提供移位时钟。 assign T1 = !clk2;

assign data = (!ADD_101) ? data_latch : 8'bz; always @(posedge clk2) begin

data_latch_buf = data_latch << 1; //data_latch_buf作缓冲 data_latch = data_latch_buf; //,以令综合器能辩明。 data_latch[0] = D_out; end

endmodule

将上面的两个模块合并起来的sys.v的源代码: //------------------- sys.v --------------------------- `include \`include \

module sys(D_in,T0,T1, data, D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101); input D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101; inout [7:0] data; output D_in,T0,T1; p_to_s

p_to_s(.D_in(D_in),.T0(T0),.data(data),.SEND(SEND),.ESC(ESC),.ADD_100(ADD_100)); s_to_p

s_to_p(.T1(T1),.data(data),.D_out(D_out),.DSC(DSC),.TAKE(TAKE),.ADD_101(ADD_101)); endmodule

测试模块源代码:

//-------------Top test file for sys.v ------------------ `timescale 1ns/100ps `include \module Top; reg D_out,SEND,ESC,DSC,TAKE,ADD_100,ADD_101; reg[7:0] data_buf; wire [7:0] data;

3 3

wire clk2; assign data = (ADD_101) ? data_buf : 8'bz;

//data在sys中是inout型变量,ADD_101 //控制data是作为输入还是进行输出。 assign clk2 =DSC && TAKE; initial begin SEND = 0; ESC = 0; DSC = 1; TAKE = 1; ADD_100 = 1; ADD_101 = 1; end initial begin data_buf = 8'b10000001; #90 ADD_100 = 0; #100 ADD_100 = 1; end always begin #50; SEND = ~SEND; ESC = ~ESC; end initial begin #1500 ; SEND = 0; ESC = 0; DSC = 1; TAKE = 1; ADD_100 = 1; ADD_101 = 1; D_out = 0; #1150 ADD_101 = 0; #100 ADD_101 =1; #100 $stop; end always begin #50 ; DSC = ~DSC; TAKE = ~TAKE; end

3

4

always @(negedge clk2) D_out = ~D_out;

sys sys(.D_in(D_in),.T0(T0),.T1(T1),.data(data),.D_out(D_out),

.ADD_101(ADD_101), .SEND(SEND),.ESC(ESC),.DSC(DSC),

.TAKE(TAKE),.ADD_100(ADD_100)); endmodule

3,设计题

1、设计一个序列发生器。要求根据输入的8位并行数据输出串行数据,如果输入数据在0—127之间则输出一位0,如果输入数据在128—255之间则输出一位1,同步时钟触发;并且和范例8的序列检测器搭接,形成一个封闭系统。编写测试模块,并给出仿真波形。

四、实验报告要求

1、简要描述Verilog HDL中基于模块多层次引用的结构化电路设计要点;

2、实验报告应包括Modelsim环境下仿真得到的波形和QuatusII环境下综合得到RTL级电路图; 3、实验报告应附硬件仿真的波形或显示的照片。

3 5

第四部分 综合实验:

实验一:8位十进制频率计设计

设计任务:

(1) 设计一个频率计,对周期信号进行测量,并在数码管上显示结果。 (2) 输出数码管共8个,结果用十进制表示。 (3) 数码管驱动采用静态显示方式。

(4) 能在软件中正确仿真,在实验板上完成系统的运行。 设计原理: (1)、设计原理

根据频率的定义和频率测量的基本原理,测定信号的频率必须有一个脉宽为1s的输入信号脉冲计数允许的信号;1s计数结束后,计数值被锁存入锁存器,计数器清零,为下一测频计数周期做好准备。测频控制信号可以由一个独立的发生器来产生。 (2)、总体架构

实验二:出租车自动计费器

设计任务

计费包括起步价、行车里程计费两部分,用四位数码管显示金额,最大值为9999元,最小计价单元为 1元,行程 3公里内,起步费为8元,超过3公里,以每公里1元计费。用两位数码管显示总里程,最大为99公里。 设计原理

该设计问题自顶向下可分为分频模块、计量模块、计费模块、控制模块、译码和动态扫描显示模块。 (1)分频模块对频率为240Hz的输入脉冲进行分频,得到的频率为10Hz频率。该模块产生频率信号用于计费, 10HZ信号为1元的计费控制。

(2)计量控制模块是出租车自动计费器系统的主体部分,该模块主要完成计价功能、计程功能,同时产生行程 3公里外的使能控制信号en0。其中计价功能主要完成的任务是:行程 3公里内,起步费为8元;3公里外以每公里1.元计费,

(3)计程功能主要完成的任务是:计算乘客所行驶的公里数。计程器的量程为99公里,满量程自动归零。

3 6

(4)译码显示模块经过4位BCD码译码器、计程数据(2位BCD码)动态选择输出。其中计费数据送入显示译码模块进行译码,十元、元为单位对应的数码管上显示,最大显示为99元;计程数据送入显示译码模块进行译码,最后送至以公里为单位的数码管上显示,最大显示为99公里。

实验三:正弦波信号发生器

设计任务:

自己设计一个正弦波信号发生器,相关参数自己设定。正弦波信号通过板载DAC输出。 设计原理

(1) 定制ROM存储sin波形数据; (2) 计数器产生地址信号;

(3) 利用系统配置的WM8731L进行输出。

实验报告要求

交出下载工程文件并来实验室验证,包括实验原理、程序设计、程序分析、仿真分析、硬件测试和详细实验步骤记录。

3 7

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

Top