EDA实验

更新时间:2023-12-31 16:01:01 阅读量: 教育文库 文档下载

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

实验一 应用QuartusII 完成完成LED 的驱动的驱动

一、实验目的

通过此实验让学生逐步了解、熟悉和掌握FPGA 开发软件QuartusII 的使用方法及Verilog HDL 的编程 方法。 2、实验内容

实验平台 (EP2C5 核心板)上有 8个发光二极管 ,其中一个发光二极管的硬件原理图如图 1.1 所示,其他的发光二极管原理图与此类似。

本实验的内容是点亮EDA-MK-01模块上的4个发光二极管。 3、 实验原理

FPGA 器件同单片机一样,为用户提供了许多灵活独立的输入/输出 I/O 口。FPGA 每个 I/O 口可以配置为输入、输出、双向 I/O、集电极开路和三态门等各种组态。作为输出口时,FPGA 的 I/O 口可以吸入最大为 24mA 的电流,可以直接驱动发光二极管 LED 等器件。所以只要正确分配并锁定引脚后,在相应的引脚上输出低电平“0”,就可以实现点亮该发光二极管的功能。 4、实验步骤

1)使用QuartusII建立工程

每个开发过程开始时都应建立一个 QuartusII 工程,QuartusII 是以工程的方式对设计过程进行管理,QuartusII工程中存放创建FPGA配置文件需要的所有设置和设计文件。

(1)打开QuartusII软件并建立工程

选择开始>>程序>>Altera>>QuartusII 7.2 >> QuartusII 7.2 打开QuartusII 7.2 软件,软件界面如图 1.2 所示。

在图 1.2 中选择 File>>New Project Wizard 来新建一项工程,注意不要把 New 误认为 New Project

Wizard?。新建工程向导对话框如图 1.3所示。

在如图 1.3 所示的新建工程向导说明对话框中可以了解在新建工程的过程中我们要完成哪些工作,这

些工作包括:

a) 指定项目目录、名称和顶层实体。 b) 指定项目设计文件。

c) 指定该设计的Altera器件系列。 d) 指定该项目的其它EDA工具。 e) 项目信息报告。

在图 1.3 中单击Next进入图 1.4所示的新建工程路径、名称、顶层实体指定对话框。

任何一项设计都是一项工程(project),必须首先为此工程建立一个放置与此工程相关的所有文件的文件夹,此文件夹将被QuartusII默认为工作库(Work Library)。一般,不同的设计项目最好放在不同的文件夹中,而同一工程的所有文件都必须放在同一文件夹中。

不要将文件夹设在计算机已有的安装目录中,更不要将工程文件直接放在安装目录中。文件夹所在路径名和文件夹中不能用中文,不能用空格,不能用括号,可以用下划线,最好也不要以数字开头。

图 1.4 第一栏用于指定工程所在的工作库文件夹;第二栏用于指定工程名,工程名可以取任何名字,也可以直接用顶层文件的实体名作为工程名(建议使用);第三栏用于指定顶层文件的实体名。注意:工程名与顶层文件的实体名应同名。

接着单击Next进入图 1.5所示的添加文件对话框。

由于是新建工程,暂无输入文件,所以直接单击 Next,进入图 1.6 所示的指定目标器件对话框。这里我们选择的是 EP2C5-2C8 核心板上CycloneII系列 EP2C5Q208C8。

在图 1.6 右边的过滤器栏(Filters)中,设计者可以通过指定封装、引脚数以及器件速度等级来加快器件查找的速度。

指定完器件后,单击 Next进入图 1.7所示的指定 EDA 工具对话框。

本实验利用 QuartusII 的集成环境进行开发,不使用任何 EDA 工具,因此这里不作任何改动。图 1.7中单击 Next进入图 1.8 所示的工程信息报告对话框。从工程信息报告对话框,设计者可以看到工程文件配置信息报告。单击 Finish,完成新建工程的建立。

需要注意的是,建立工程后,还可以根据设计中的实际情况对工程进行重新设置,可选择Assignments>>Setting 进行设置,也可以选择工具栏上的 按钮。

(2)建立源程序文件

如图 1.9 所示,选择 File>>New打开新建文件对话框如图 1.10 所示。

图1.10 新建Verilog HDL File

在如图 1.10 所示的新建文件对话框中选择 Verilog HDL File,按 OK建立一个空的文本文件,后缀名为.v。如图 1.11所示,选择 File>>Save As打开将 Verilog文件存盘的对话框,如图1.12 所示。

图1.11 Verilog HDL File编辑框

图1.12 保存Verilog文件

(3) 编译文件

点击Processing/Start Compilation对源文件进行编译,如果通过将会出现类似图1.13所示的信息。

图1.13 编译信息

(4)分配 FPGA 引脚

要执行 FPGA 引脚的分配,可按下面步骤进行:

a. 选择Assignments>>Assignment Editor打开引脚分配对话框如图1.14所示。 b. 在 CateGory下拉菜单中选择Pin。 c. 在 To 栏中,输入各引脚名称,在 Location 下拉选择相应的引脚,也可以在Location 下输入引脚号(如Pin_32)来快速定位。

d. 选择 File>>Save来保存分配,然后关闭Assignment Editor。

图1.14 引脚分配

(5)器件和引脚的其他位置

单击Assignments/Device,在出现的对话框中点击Device and Pin Options。在Device and Pin Options对话框中选择 Configuration 标签页按图 1.15 所示设置,即采用串行配置器件 EPCS1 的主动配置方式。在 Device&Pin Options 对话框中选择 Unused Pins标签页进行没有使用引脚的设置,按照图 1.16所示将未使用引脚设置为高阻输入,这样上电后 FPGA 的所有不使用引脚后将进入高阻抗状态。

图1.15 Configuration 配置

图1.16未用引脚配置

2)下载硬件设计到目标 FPGA 成功编译硬件系统后,将产生 logic.sof 的 FPGA 配置文件输出。本步骤简单介绍将 SOF 文件下载到目标 FPGA 器件的步骤。

A、 通过并口 BlasterII下载电缆连接实验平台JTAG口和主计算机,接通实验平台电源。 B、 在QuartusⅡ软件中选择 Tools>>Programmer。打开编程器窗口并自动打开配置文

件(logic.sof),如图 1.17所示。如果没有自动打开配置文件,则需要自己添加需要编程的配置文件。

C、 确保编程器窗口左上角的 Hardware Steup栏中硬件已经安装。 D、 确保 Program/Configure中的方框选中。 E、 单击 START开始使用配置文件对 FPGA进行配置,Progress栏显示配置进度。 5)观察 LED 的状态

观察实验平台上的发光二极管H1。看是否与设计相符。

图1.17编程窗口

将配置文件下载到 FPGA中,掉电后 FPGA中的配置数据将丢失。 5、电路连接 引脚分配

PIN_74 -to led\\[0\\] PIN_72 -to led\\[1\\] PIN_69 -to led\\[2\\] PIN_68 -to led\\[3\\] PIN_67 -to led\\[4\\] PIN_64 -to led\\[5\\] PIN_63 -to led\\[6\\] PIN_61 -to led\\[7\\] 5、实验参考程序

module led_test(led);//模块名LED_TEST.v output [7:0]led;//定义输出端口 assign

led = 8'b10101010;//输出0xaa endmodule

实验二 流水灯

1、 实验目的

通过此实验进一步熟悉和掌握FPGA开发软件的使用方法及VERILOG HDL的编程方法,学习简单时序电路的设计和硬件测试。 2、 实验内容

建立可用于控制LED流水灯的简单硬件电路,要求在EDA实验箱上实现LED1-LED8发光二极管流水灯显示。

实验内容(1)新建工程及源程序文件ledwater.v,然后按实验一的方法实现流水灯设计。 实验内容(2)通过图形设计文件实现流水灯

A:通过ledwater.v文件创建相应的模块符号文件ledwater.bsf(在Project Navigator窗口中,点击Files标签,然后右击ledwater.v文件,选择Create Symbol Files for Current File,即可生成对应的图形符号文件)。 B: 新建图形设计文件ledwater.bsf并保存

步骤1:点击File/NEW,出现新建对话框如图2.1所示。按图示进行选择。然后点击OK并出现图2.2所示的图形编辑框。

图2.1 新建对话框

图2.2图形设计文件编辑框

步骤2:在编辑框的空白处双击,将symbol对话框中library:project下的ledwater模块放在图形设计文件编辑框中,加入输出输入引脚,最后的总电路图如图2.3所示。

图2.3 总体图形设计文件图

步骤3:将ledwater.bsf设为顶层实体(在Project Navigator窗口中,点击Files标签,然后右击ledwater.bsf文件,选择Set as Top-level Entity)。

步骤4:编译文件,分配引脚,下载程序到实验箱。 3、 电路连接

(1)PIN_130 -to clk PIN_74 -to led\\[0\\]

PIN_72 -to led\\[1\\] PIN_69 -to led\\[2\\] PIN_68 -to led\\[3\\] PIN_67 -to led\\[4\\] PIN_64 -to led\\[5\\] PIN_63 -to led\\[6\\] PIN_61 -to led\\[7\\]

(2)将EDA-MK-01模块跳线帽设置为LED1-LED8和KEY0-KEY7端。 (3)确保数字信号源的X12中CLOCK0的短路帽处于4HZ位置。 4、实验程序

module led_water(led,clk);

input clk;//clock0,采用数字信号源 output [7:0]led; reg [8:0]led_r;

assign led = led_r[7:0];

always @(posedge clk) begin

led_r <= led_r << 1;

if(led_r == 9'd0)

led_r <= 9'b111111111; end

endmodule

实验三 一位全加器测试

1、实验目的

通过此实验让用户逐步了解、熟悉和掌握 FPGA 开发软件 QuartusⅡ的使用方法及 Verilog HDL 的编程方法。学习用 Verilog HDL 语言以不同方式描述1 位全加器及电路设计的仿真和硬件测试。 2、实验内容

通过实验箱EDA-MK-01模块上的开关S1-S3输入信号,分别为 A、B和Cin,并通过LED1-LED3 指示相应的状态。输出 Sum和 Cout 通过LED7和LED8 指示(灯亮表示输入或输出为“1”)。 3、实验步骤

1)启动 QuartusⅡ建立一个空白工程,然后命名为fulladd.qpf。

2)新建 Verilog HDL 源程序文件 fulladd.v,输入程序代码并保存(进行综合编译,若在编译过程中发现错误,则找出并更正错误,直至编译成功为止。然后再生成图形符号文件 fulladd.qpf(在Project Navigator窗口中,点击Files标签,然后右击fulladd.v文件,选择Create Symbol Files for Current File,即可生成对应的图形符号文件)。

3)新建图形设计文件命名为 top.bdf 并保存(点击File/New,出现图3.1,按图示选择再点击OK,便出现图形文件编辑框)。模块图如图3.2所示,因为实验平台上的 LED 发光二级管是低电平亮,所以在每个输入口都加了反相器。

4)选择目标器件并对相应的引脚进行锁定,在这里所选择的器件为 Altera 公司 CycloneII 系列的EP2C5Q208C8 芯片,将未使用的引脚设置为三态输入(一定要设置,否则可能会损坏芯片)。

5)将 top.bdf设置为顶层实体。对该工程文件进行全程编译处理,若在编译过程中发现错误,则找出并更正错误,直至编译成功为止。

6)最后把程序下载到 FPGA 器件中。按下S1-S3,观察发光二极管 LED1-LED3,LED7,LED8的状态。

图3.1 新建图形文件

图3.2 顶层模块原理图

4、 电路连接(引脚分配)

PIN_74 -to A PIN_72 -to B PIN_69 -to CIN PIN_63 -to SUM PIN_61 -to COUT PIN_86 -to SW1 PIN_84 -to SW2 PIN_82 -to SW3

5、 实验程序

module fulladd(a,b,cin,sum,cout); input a,b,cin; output sum,cout; assign {cout,sum} = a + b +cin; endmodule

//1位加器 //输入端口 //输出端口

实验四 8位十进制频率计

1、实验目的

设计 8位十进制频率计,学习较复杂的数字系统设计方法。学习VerilogHDL编程例化语句的使用。 2、实验内容

在实验平台上实现 8位十进制频率计的设计。被测信号从 CLOCK0(数字信号时钟源)输入,经过检测后测得的频率值用数码管 1~8 显示。 3、实验原理

根据频率的定义和频率测量的基本原理,测定信号的频率必须有一个脉宽为1 秒的输入信号脉冲计数允许的信号;1 秒计数结束后,计数值锁入锁存器,并为下一测频计数周期作准备的计数器清零。计数器在这里是由 8 个十进制计数器级连组成,如下图所示是频率计的计数结构图,从图中可以看出十进制模块之间是由进位链级连而成的。

4、 电路连接 (1) 将EDA-MK-01模块跳线帽设置为SEG_a—SEG_dp和COM0—COM7端。 (2) 确保数字信号源的X12的短路帽处于ON位置。 (3) 引脚分配

PIN_23 -to clk

PIN_130 -to clock0 PIN_74 -to seg\\[0\\] PIN_72 -to seg\\[1\\] PIN_69 -to seg\\[2\\] PIN_68 -to seg\\[3\\] PIN_67 -to seg\\[4\\] PIN_64 -to seg\\[5\\] PIN_63 -to seg\\[6\\] PIN_61 -to seg\\[7\\] PIN_86 -to dig\\[0\\] PIN_84 -to dig\\[1\\] PIN_82 -to dig\\[2\\] PIN_81 -to dig\\[3\\] PIN_80 -to dig\\[4\\] PIN_77 -to dig\\[5\\] PIN_76 -to dig\\[6\\] PIN_75 -to dig\\[7\\]

5、 实验程序

(1) scan_led.v

module scan_led(clk_1k,d,dig,seg); //模块名scan_led input clk_1k; //输入时钟

input[31:0] d; output[7:0] dig; output[7:0] seg;

reg[7:0] seg_r; reg[7:0] dig_r; reg[3:0] disp_dat; reg[2:0]count;

assign dig = dig_r; assign seg = seg_r;

always @(posedge clk_1k) begin

count <= count + 1'b1; end

always @(posedge clk_1k) begin

case(count) 3'd0:disp_dat = d[31:28]; 3'd1:disp_dat = d[27:24]; 3'd2:disp_dat = d[23:20]; 3'd3:disp_dat = d[19:16]; 3'd4:disp_dat = d[15:12]; 3'd5:disp_dat = d[11:8]; 3'd6:disp_dat = d[7:4]; 3'd7:disp_dat = d[3:0]; endcase

case(count) 3'd0:dig_r = 8'b01111111; 3'd1:dig_r = 8'b10111111; 3'd2:dig_r = 8'b11011111; 3'd3:dig_r = 8'b11101111; 3'd4:dig_r = 8'b11110111; 3'd5:dig_r = 8'b11111011; 3'd6:dig_r = 8'b11111101; 3'd7:dig_r = 8'b11111110; endcase end

always @(disp_dat) begin

case(disp_dat)

//输入要显示的数据 //数码管选择输出引脚 //数码管段输出引脚 //定义数码管输出寄存器 //定义数码管选择输出寄存器 //定义显示数据寄存器 //定义计数寄存器 //输出数码管选择

//输出数码管译码结果

//定义上升沿触发进程

//选择扫描显示数据

//第一个数码管 //第二个数码管 //第三个数码管 //第四个数码管 //第五个数码管 //第六个数码管 //第七个数码管 //第八个数码管 //选择数码管显示位 //选择第一个数码管显示 //选择第二个数码管显示 //选择第三个数码管显示 //选择第四个数码管显示 //选择第五个数码管显示 //选择第六个数码管显示 //选择第七个数码管显示

//选择第八个数码管显示

//七段译码

4'h0:seg_r = 8'hc0; 4'h1:seg_r = 8'hf9; 4'h2:seg_r = 8'ha4; 4'h3:seg_r = 8'hb0; 4'h4:seg_r = 8'h99; 4'h5:seg_r = 8'h92; 4'h6:seg_r = 8'h82; 4'h7:seg_r = 8'hf8; 4'h8:seg_r = 8'h80; 4'h9:seg_r = 8'h90; 4'ha:seg_r = 8'h88; 4'hb:seg_r = 8'h83; 4'hc:seg_r = 8'hc6; 4'hd:seg_r = 8'ha1; 4'he:seg_r = 8'h86; 4'hf:seg_r = 8'h8e; endcase end

endmodule

(2) freqtest.v(设为顶层实体)

module freqtest(clk,clock0,dig,seg); input clk; input clock0;

output[7:0] dig; output[7:0] seg;

//显示0 //显示1 //显示2 //显示3 //显示4 //显示5 //显示6 //显示7 //显示8 //显示9 //显示a //显示b //显示c //显示d //显示e //显示f

//系统时钟 //被测信号输入

//数码管选择输出引脚 //数码管段输出引脚 //时钟分频计数器 //频率测量结果寄存器 //脉冲计数寄存器 //1Hz闸门信号 //数码管扫描显示时钟

reg[25:0] counter; reg[31:0] freq_result; wire[31:0] pre_freq; reg rst;

wire divide_clk; wire clk_scan; wire cout1,cout2,cout3,cout4,cout5,cout6,cout7;

assign clk_scan = counter[15];

//时钟分频进程:分出1Hz基准信号 always @(posedge clk) begin

if (divide_clk)

counter <= 26'd0; else

//动态扫描时钟

counter <= counter + 1'b1; end

assign divide_clk = (counter >= 26'd50000000);

//锁存测量值进程

always @(posedge clk) begin

if(divide_clk) freq_result <= pre_freq; end

//产生计数器复位信号

always @(posedge clk) begin

if(divide_clk) rst <= 1'b1; else rst <= 1'b0; end

//8位十进制计数模块:由8个十进制计数模块构成

cnt10 u1(.clock(clock0),.rst(rst),.cin(1'b1),.cout(cout1),.dout(pre_freq[3:0])); cnt10 u2(.clock(clock0),.rst(rst),.cin(cout1),.cout(cout2),.dout(pre_freq[7:4])); cnt10 u3(.clock(clock0),.rst(rst),.cin(cout2),.cout(cout3),.dout(pre_freq[11:8])); cnt10 u4(.clock(clock0),.rst(rst),.cin(cout3),.cout(cout4),.dout(pre_freq[15:12])); cnt10 u5(.clock(clock0),.rst(rst),.cin(cout4),.cout(cout5),.dout(pre_freq[19:16])); cnt10 u6(.clock(clock0),.rst(rst),.cin(cout5),.cout(cout6),.dout(pre_freq[23:20])); cnt10 u7(.clock(clock0),.rst(rst),.cin(cout6),.cout(cout7),.dout(pre_freq[27:24])); cnt10 u8(.clock(clock0),.rst(rst),.cin(cout7),.cout(),.dout(pre_freq[31:28]));

//数码管显示模块

scan_led u9(.clk_1k(clk_scan),.d(freq_result),.dig(dig),.seg(seg));

endmodule

(3)count10.v

module cnt10(clock,rst,cin,cout,dout); //10进制计数器 input clock; //计数时钟 input cin; //进位输入 input rst; //复位信号 output cout; //进位输出 output[3:0] dout; //计数输出 reg[3:0] counter; //寄存器

assign dout = counter;

assign cout = cin && (counter >= 4'd9); //进位输出

always @(posedge clock or posedge rst) begin if(rst) counter <= 4'd0; else if(cin) begin if(cout) counter <= 4'd0; else counter <= counter + 1'b1; end end

endmodule

//计数器复位 //进位输入

实验五 硬件电子琴

1、 实验目的

学习利用蜂鸣器和按键设计硬件电子琴 2、实验内容

在实验箱上实现一个简易电子琴。 3、实验原理

实验平台上有 1个蜂鸣器报警单元。其硬件原理图如下图 所示。可以看出为了增加 I/O 口的驱动能力,在此采用了 PNP型三极管,这样只要在 BEEP上输入一定频率的脉冲,蜂鸣器就会发出音乐。

4、电路连接

(1)将EDA-MK-01模块跳线帽设置为LED1-LED8和KEY0-KEY7端,S1-S8作为按键。 (2)引脚分配

PIN_23 -to clk PIN_107 -to fout PIN_86 -to key\\[0\\] PIN_84 -to key\\[1\\] PIN_82 -to key\\[2\\] PIN_81 -to key\\[3\\] PIN_80 -to key\\[4\\] PIN_77 -to key\\[5\\] PIN_76 -to key\\[6\\] PIN_75 -to key\\[7\\] PIN_74 -to led\\[0\\] PIN_72 -to led\\[1\\] PIN_69 -to led\\[2\\] PIN_68 -to led\\[3\\] PIN_67 -to led\\[4\\] PIN_64 -to led\\[5\\] PIN_63 -to led\\[6\\]

PIN_61 -to led\\[7\\]

5、实验程序

module beep1(clk,key,fout,led); input clk; input[7:0]key; output fout; output[7:0]led;

reg beep_r; reg[15:0]count,count_end; reg[7:0]key_r;

always@(posedge clk) begin

//模块名称beep //系统时钟50MHz //按键输入 //蜂鸣器输出端 //LED输出

//寄存器

count <= count + 1'b1; //计数器加1

if((count == count_end)&(!(count_end == 16'hffff))) begin

count <= 16'h0; beep_r <= !beep_r; end end

always @(key) begin

//计数器清零 //取反输出信号

key_r = key; case(key_r) 8'b11111110:count_end = 16'hba9d; 8'b11111101:count_end = 16'ha647; 8'b11111011:count_end = 16'h941f; 8'b11110111:count_end = 16'h8bce; 8'b11101111:count_end = 16'h7c8f; 8'b11011111:count_end = 16'h6ef9; 8'b10111111:count_end = 16'h62dc; 8'b01111110:count_end = 16'h5d68; 8'b01111101:count_end = 16'h5322; 8'b01111011:count_end = 16'h4a10; 8'b01110111:count_end = 16'h45e8; 8'b01101111:count_end = 16'h3e47; 8'b01011111:count_end = 16'h377c; 8'b00111111:count_end = 16'h316f; default:count_end = 16'hffff; endcase end

//取键值

//中音1的分频系数值 //中音2的分频系数值 //中音3的分频系数值 //中音4的分频系数值 //中音5的分频系数值 //中音6的分频系数值 //中音7的分频系数值 //高音1的分频系数值 //高音2的分频系数值 //高音3的分频系数值 //高音4的分频系数值 //高音5的分频系数值 //高音6的分频系数值 //高音7的分频系数值

assign fout =beep_r; assign led =key_r; endmodule

//输出音乐 //输出按键状态

实验六 硬件乐曲自动演奏电路

1、实验目的

学习利用 7节硬件电子琴的原理设计硬件演奏电路。 2、实验内容

在实验平台上的实现《天长地久》乐曲的演奏。 3、实验原理

硬件电路和乐曲演奏的原理同第十三节硬件电子琴相同。在程序中设置了一个状态机,每 250ms改变一个状态(乐曲的每个一个节拍),组成乐曲的每个音符的频率值(音调)相对应于状态机的每一个状态。只要让状态机的状态按顺序转换,就可以自动播放音乐了。 4、电路连接 PIN_23 -to clk

PIN_107 -to beep

6、 实验程序

module song(clk,beep); //模块名称song input clk; //系统时钟48MHz output beep; //蜂鸣器输出端

reg beep_r; //寄存器 reg[7:0] state; //乐谱状态机 reg[15:0]count,count_end; reg[23:0]count1;

//乐谱参数:D=F/2K (D:参数,F:时钟频率,K:音高频率) parameter L_5 = 16'd63776, //低音5 L_6 = 16'd56818, //低音6 M_1 = 16'd47774, //中音1 M_2 = 16'd42567, //中音2 M_3 = 16'd37919, //中音3 M_5 = 16'd31888, //中音5 M_6 = 16'd28409, //中音6 H_1 = 16'd23912; //高音1 parameter TIME = 10000000; //控制每一个音的长短(250ms) assign beep = beep_r; //输出音乐

always@(posedge clk) begin

count <= count + 1'b1; //计数器加1 if(count == count_end) begin count <= 16'h0; //计数器清零 beep_r <= !beep_r; //输出取反 end

end

always @(posedge clk) begin

if(count1 < TIME) //一个节拍250mS count1 = count1 + 1'b1; else begin count1 = 24'd0; if(state == 8'd147) state = 8'd0; else state = state + 1'b1; case(state) 8'd0,8'd1: count_end = L_5;//低音\持续2个节拍 8'd2,8'd3,8'd4,8'd5,8'd6,8'd7,8'd8: count_end = M_1;//中音\持续7个节拍 8'd9,8'd10:count_end = M_3;//中音\持续2个节拍 8'd11,8'd12,8'd13,8'd14: count_end = M_2; 8'd15: count_end = M_1; 8'd16,8'd17: count_end = M_2; 8'd18,8'd19: count_end = M_3; 8'd20,8'd21,8'd22,8'd23,8'd24: count_end = M_1; 8'd25,8'd26: count_end = M_3; 8'd27,8'd28: count_end = M_5; 8'd29,8'd30,8'd31,8'd32,8'd33:count_end = M_6; 8'd34,8'd35,8'd36,8'd37,8'd38: count_end = M_6; 8'd39,8'd40,8'd41,8'd42: count_end = M_5; 8'd43,8'd44,8'd45: count_end = M_3; 8'd46,8'd47: count_end = M_1; 8'd48,8'd49,8'd50,8'd51: count_end = M_2; 8'd52: count_end = M_1; 8'd53,8'd54: count_end = M_2; 8'd55,8'd56: count_end = M_3; 8'd57,8'd58,8'd59,8'd60: count_end = M_1; 8'd61,8'd62,8'd63: count_end = L_6; 8'd64,8'd65: count_end = M_5; 8'd66,8'd67,8'd68,8'd69: count_end = M_1; 8'd70,8'd71,8'd72,8'd73: count_end = M_1; 8'd74,8'd75: count_end = M_6; 8'd76,8'd77,8'd78,8'd79: count_end = M_5; 8'd80,8'd81,8'd82: count_end = M_3; 8'd83,8'd84: count_end = M_1;

8'd85,8'd86,8'd87,8'd88: count_end = M_2; 8'd89: count_end = M_1; 8'd90,8'd91: count_end = M_2; 8'd92,8'd93: count_end = M_6; 8'd94,8'd95,8'd96,8'd97: count_end = M_5; 8'd98,8'd99,8'd100: count_end = M_3; 8'd101,8'd102: count_end = M_5; 8'd103,8'd104,8'd105,8'd106: count_end = M_6; 8'd107,8'd108,8'd109,8'd110: count_end = M_6; 8'd111,8'd112: count_end = H_1; 8'd113,8'd114,8'd115,8'd116: count_end = M_5; 8'd117,8'd118,8'd119: count_end = M_3; 8'd120,8'd121: count_end = M_1; 8'd122,8'd123,8'd124,8'd125: count_end = M_2; 8'd126: count_end = M_1; 8'd127,8'd128: count_end = M_2; 8'd129,8'd130: count_end = M_3; 8'd131,8'd132,8'd133,8'd134: count_end = M_1; 8'd135,8'd136,8'd137: count_end = L_6; 8'd138,8'd139: count_end = M_5; 8'd140,8'd141,8'd142,8'd143: count_end = M_1; 8'd144,8'd145,8'd146,8'd147: count_end = M_1; default:count_end = 16'h0; endcase end end

endmodule

实验七 交通灯控制器

1、实验目的

学习交通灯控制器的设计,学习简单状态机的设计和硬件测试。 2、实验内容

本实验的内容是设计一个简易的交通灯控制器,要求能实现红黄绿三种灯的控制并通过数码管显示倒计时时间,整个设计在实验平台上实现。 3、实验原理

本实验的设计的交通灯控制器要求实现对A,B 两个方向的红,绿,黄三种灯的控制,并能实现时间显示的到计时。因此每个方向的灯可用一个状态机实现,状态的跳转顺序为灯-绿灯-黄灯-红灯(另一个的状态应为绿-黄-红-绿),同时设计一个计时器,来记录每种灯的道计时时间。最后将交通灯的状态信息输出,至数码管显示模块和交通灯模块。注意一个方向的绿灯时间应和另一个方向的红黄灯时间总和相等。 4、电路连接

(1)将EDA-MK-01模块跳线帽设置为SEG_a—SEG_dp和COM0—COM7端。 (2)引脚分配

PIN_23 -to clk PIN_4 -to rst_n PIN_34 -to lampa\\[0\\] PIN_37 -to lampa\\[1\\] PIN_35 -to lampa\\[2\\] PIN_108 -to lampb\\[0\\] PIN_117 -to lampb\\[1\\] PIN_39 -to lampb\\[2\\] PIN_74 -to seg\\[0\\] PIN_72 -to seg\\[1\\] PIN_69 -to seg\\[2\\] PIN_68 -to seg\\[3\\] PIN_67 -to seg\\[4\\] PIN_64 -to seg\\[5\\] PIN_63 -to seg\\[6\\] PIN_61 -to seg\\[7\\] PIN_86 -to dig\\[0\\] PIN_84 -to dig\\[1\\] PIN_82 -to dig\\[2\\] PIN_81 -to dig\\[3\\] PIN_80 -to dig\\[4\\] PIN_77 -to dig\\[5\\] PIN_76 -to dig\\[6\\] PIN_75 -to dig\\[7\\]

5、实验程序

(1) traffic.v

module traffic(clock,rst_n,clken,lampa,lampb,acount,bcount); input clock;

input rst_n; input clken; output [2:0] lampa; output [2:0] lampb; output [7:0] acount; output [7:0] bcount;

reg[2:0] lampa,lampb; reg[7:0] numa,numb; reg tempa,tempb; reg[2:0] StateA,StateB;

parameter ared =8'h30, //30秒 ayellow =8'h5, //5秒 agreen =8'h15, //15秒 bred =8'h20, //20秒 byellow =8'h5, //5秒 bgreen =8'h25; //25秒

assign acount=numa; assign bcount=numb;

//控制A方向的三种灯

always @(posedge clock or negedge rst_n) begin

if(!rst_n) begin StateA <= 3'h0; lampa <= 3'b011; tempa <= 1'b0; end

else if(clken) begin if(!tempa) begin tempa <= 1'b1; //防重进入标志 case(StateA) //控制亮灯的顺序 0: begin numa <= agreen; lampa <= 3'b011; StateA <= 1; end 1: begin numa <= ayellow; lampa <= 3'b101; StateA <= 2; end 2: begin numa <= ared; lampa <= 3'b110; StateA <= 0; end

default: endcase end else

lampa <= 3'b110;

begin //倒计时 if(numa>1) if(numa[3:0]==0) begin numa[3:0]<=4'h9; numa[7:4]<=numa[7:4]-4'h1; end else numa[3:0]<=numa[3:0]-4'h1; if (numa==2) tempa<=1'b0; end end end

//控制B方向的三种灯

always @(posedge clock or negedge rst_n) begin

if(!rst_n) begin lampb<=3'b110; StateB<=3'h0; tempb<=1'b0; end

else if (clken) begin

if(!tempb) begin tempb<=1'b1; //防重进入标志 case (StateB) //控制亮灯的顺序 0: begin numb<=bred; lampb<=3'b110; StateB<=1; end 1: begin numb<=bgreen; lampb<=3'b011; StateB<=2; end 2: begin numb<=byellow; lampb<=3'b101; StateB<=0; end default: lampb<=3'b110; endcase end else begin //倒计时

if(numb>1) if(numb[3:0]==0) begin numb[3:0]<=4'h9; numb[7:4]<=numb[7:4]-4'h1; end else numb[3:0]<=numb[3:0]-4'h1; if(numb==2) tempb <= 1'b0; end end end

endmodule

(2) traffic_test.v

module traffic_test(clock,clken,rst_n,acount,bcount,seg,dig);

input clock; input rst_n; output clken;

input [7:0] acount; input [7:0] bcount; output [7:0] seg; output [7:0] dig; //I/O寄存器 reg[7:0]seg; reg[7:0]dig;

//系统时钟(50MHz)

//内部寄存器 reg[25:0]clk_cnt; reg[16:0]count; reg[1:0] cnt; reg[3:0]disp_dat; wire div_clk;

//产生1Hz时钟使能信号 always @(posedge clock) begin if(clken) clk_cnt <= 26'h0; else clk_cnt <= clk_cnt + 26'h1; end

assign clken = (clk_cnt >= 26'd49999999);

//时钟分频进程,用于数码管扫描显示 always @(posedge clock) begin

count <= count + 1'b1; end

assign div_clk = &count;

//数码管扫描显示部分

always @(posedge clock) begin

if(div_clk) cnt <= cnt + 1'b1; end

always @(posedge clock) begin

if(div_clk) begin case(cnt) 2'd0:disp_dat <= acount[7:4]; 2'd1:disp_dat <= acount[3:0]; 2'd2:disp_dat <= bcount[7:4]; 2'd3:disp_dat <= bcount[3:0]; endcase case(cnt) 2'd0:dig <= 8'b01111111; 2'd1:dig <= 8'b10111111; 2'd2:dig <= 8'b11110111; 2'd3:dig <= 8'b11111011; endcase end end

always @(disp_dat) begin

case(disp_dat) 4'h0:seg = 8'hc0; //显示0 4'h1:seg = 8'hf9; //显示1 4'h2:seg = 8'ha4; //显示2 4'h3:seg = 8'hb0; //显示3 4'h4:seg = 8'h99; //显示4 4'h5:seg = 8'h92; //显示5 4'h6:seg = 8'h82; //显示6 4'h7:seg = 8'hf8; //显示7

4'h8:seg = 8'h80; //显示8 4'h9:seg = 8'h90; //显示9 4'ha:seg = 8'h88; //显示a 4'hb:seg = 8'h83; //显示b 4'hc:seg = 8'hc6; //显示c 4'hd:seg = 8'ha1; //显示d 4'he:seg = 8'h86; //显示e 4'hf:seg = 8'h8e; //显示f endcase end

endmodule

(3) traffic_top.v(顶层文件)

module traffic_top(clk,rst_n,seg,dig,lampa,lampb); input clk; input rst_n; output [2:0] lampa; output [2:0] lampb; output [7:0] seg; output [7:0] dig;

wire clken;

wire [7:0] acount; wire [7:0] bcount;

traffic traffic( .clock(clk), .rst_n(rst_n), .clken(clken), .lampa(lampa), .lampb(lampb), .acount(acount), .bcount(bcount) );

traffic_test traffic_test( .clock(clk), .clken(clken), .rst_n(rst_n), .acount(acount), .bcount(bcount), .seg(seg),

//系统时钟(48MHz) //复位信号,低电平有效

.dig(dig) );

Endmodule

实验八 数字时钟

1、实验目的

学习数字时钟的硬件设计。 2、实验内容

在实验平台上完成一个可以计时的数字时钟,其显示时间范围是 00:00:00~23:59:59,且该时钟具有暂停计时和清零等功能。 3 、实验原理

一个完整的时钟应由 3 部分组成:秒脉冲发生电路、计数显示部分和时钟调整部分。一个时钟的准确与否主要取决秒脉冲的精确度。为了保证计时准确我们对系统时钟 50MHZ 进行了 50000000 分频,从而得到 1HZ 的秒脉冲。至于显示部分与 LED 数码管原理相同,而校时电路用户可以自由发挥,如定义 3 个键keystart、keymon 和 keyadd,分别用于控制时钟的计时开始、调整功能选择和加 1 处理,从而完成对现 在时间的调整。本实验的较时电路在此仅仅完成了暂停、清零等基本功能。 4、电路连接

(1)将EDA-MK-01模块跳线帽设置为SEG_a—SEG_dp和COM0—COM7端。

(2) 用实验仪提供的 8PIN 数据线将 IO 口三和四(J33和J34)分别与数码管的

J28、J27相连接。 (3)引脚分配 PIN_23 -to clk PIN_120 -to key\\[0\\] PIN_119 -to key\\[1\\] PIN_74 -to seg\\[0\\] PIN_72 -to seg\\[1\\] PIN_69 -to seg\\[2\\] PIN_68 -to seg\\[3\\] t PIN_67 -to seg\\[4\\] PIN_64 -to seg\\[5\\] PIN_63 -to seg\\[6\\] PIN_61 -to seg\\[7\\] PIN_86 -to dig\\[0\\] PIN_84 -to dig\\[1\\] PIN_82 -to dig\\[2\\] PIN_81 -to dig\\[3\\] PIN_80 -to dig\\[4\\] PIN_77 -to dig\\[5\\] PIN_76 -to dig\\[6\\] PIN_75 -to dig\\[7\\]

(4) 把程序下载到 FPGA 器件中。观察数码管的显示状态。按下按键 K3、K2 观察数

字钟上的时间有什么变化。

5、实验程序

module clock(clk,key,dig,seg); input clk; input[1:0] key; output[7:0] dig;

output[7:0] seg;

reg[7:0] seg_r; reg[7:0] dig_r; reg[3:0] disp_dat; reg[24:0]count; reg[23:0]hour; reg sec,keyen; reg[1:0]dout1,dout2,dout3; wire[1:0]key_done;

assign dig = dig_r; assign seg = seg_r;

//秒信号产生部分

always @(posedge clk) begin count = count + 1'b1; if(count == 25'd25000000) begin count = 25'd0; sec = ~sec; end end

//按键消抖处理部分

assign key_done = (dout1 | dout2 | dout3);

always @(posedge count[17]) begin dout1 <= key; dout2 <= dout1; dout3 <= dout2; end

always @(negedge key_done[0]) begin keyen = ~keyen; end

//数码管动态扫描显示部分 always @(posedge clk) begin case(count[17:15])

3'd0:disp_dat = hour[3:0]; 3'd1:disp_dat = hour[7:4]; 3'd2:disp_dat = 4'ha; 3'd3:disp_dat = hour[11:8]; 3'd4:disp_dat = hour[15:12]; 3'd5:disp_dat = 4'ha; 3'd6:disp_dat = hour[19:16]; 3'd7:disp_dat = hour[23:20]; endcase

case(count[17:15])

//秒个位 //秒十位 //显示\ //分个位 //分十位 //显示\//时个位 //时十位

//选择第一个数码管显示 //选择第二个数码管显示 //选择第三个数码管显示 //选择第四个数码管显示 //选择第五个数码管显示 //选择第六个数码管显示 //选择第七个数码管显示 //选择第八个数码管显示

3'd0:dig_r = 8'b11111110; 3'd1:dig_r = 8'b11111101; 3'd2:dig_r = 8'b11111011; 3'd3:dig_r = 8'b11110111; 3'd4:dig_r = 8'b11101111; 3'd5:dig_r = 8'b11011111; 3'd6:dig_r = 8'b10111111; 3'd7:dig_r = 8'b01111111; endcase end

always @(posedge clk) begin case(disp_dat)

4'h0:seg_r = 8'hc0; //显示0 4'h1:seg_r = 8'hf9; //显示1 4'h2:seg_r = 8'ha4; //显示2 4'h3:seg_r = 8'hb0; //显示3 4'h4:seg_r = 8'h99; //显示4 4'h5:seg_r = 8'h92; //显示5 4'h6:seg_r = 8'h82; //显示6 4'h7:seg_r = 8'hf8; //显示7 4'h8:seg_r = 8'h80; //显示8 4'h9:seg_r = 8'h90; //显示9 4'ha:seg_r = 8'hbf; //显示- default:seg_r = 8'hff; //不显示 endcase if((count[17:15]== 3'd2)&sec) seg_r = 8'hff; end

//计时处理部分

always @(negedge sec or negedge key_done[1])//计时处理 begin

if(!key_done[1]) begin hour = 24'h0; end

else if(!keyen) begin hour[3:0] = hour[3:0] + 1'b1; if(hour[3:0] == 4'ha) begin hour[3:0] = 4'h0;

//是清零键吗? //是,则清零

//秒加1

hour[7:4] = hour[7:4] + 1'b1; //秒的十位加一 if(hour[7:4] == 4'h6) begin hour[7:4] = 4'h0;

hour[11:8] = hour[11:8] + 1'b1;//分个位加一 if(hour[11:8] == 4'ha) begin hour[11:8] = 4'h0; hour[15:12] = hour[15:12] + 1'b1;//分十位加一 if(hour[15:12] == 4'h6) begin hour[15:12] = 4'h0;

hour[19:16] = hour[19:16] + 1'b1;//时个位加一

if(hour[19:16] == 4'ha) begin hour[19:16] = 4'h0; hour[23:20] = hour[23:20] + 1'b1;//时十位加一 end if(hour[23:16] == 8'h24) hour[23:16] = 8'h0; end end end end end end

endmodule

实验九 利用PWM实现DAC 转换

1、实验目的

学习使用 PWM 进行 DAC 转换,了解 PWM-DAC 电压转换的原理。 2、实验内容

本实验的内容是设计一个PWM信号产生模块,并通过外部低通滤波电路将PWM信号转换为直流信号,硬件原理图如图所示,PWM占空比对应的值由数码管 LED5~LED8显示,并由 K3、K2、RESET控制。

3、电路连接

(1)将EDA-MK-01模块跳线帽设置为SEG_a—SEG_dp和COM0—COM7端。 (2)引脚分配

#key0,key1,KEY2分别为2C5核心板的K1,K2,K3 PIN_23 -to clk

PIN_4 -to key\\[2\\] PIN_120 -to key\\[1\\] PIN_119 -to key\\[0\\] PIN_96 -to pwm_out PIN_74 -to seg\\[0\\] PIN_72 -to seg\\[1\\] PIN_69 -to seg\\[2\\] PIN_68 -to seg\\[3\\] PIN_67 -to seg\\[4\\] PIN_64 -to seg\\[5\\] PIN_63 -to seg\\[6\\] PIN_61 -to seg\\[7\\] PIN_86 -to dig\\[0\\] PIN_84 -to dig\\[1\\] PIN_82 -to dig\\[2\\] PIN_81 -to dig\\[3\\] PIN_80 -to dig\\[4\\] PIN_77 -to dig\\[5\\] PIN_76 -to dig\\[6\\] PIN_75 -to dig\\[7\\]

5、实验程序

(1)pwm_logic.v

module pwm_logic(clock,pwm_enable,reset_n,clock_divide,duty_cycle,pwm_out);

input clock; input [31:0] clock_divide; input [31:0] duty_cycle; input pwm_enable; input reset_n; output pwm_out; reg [31:0] counter; reg pwm_out; //输入时钟,用于PWM分频

//时钟分频值 //占空比周期值 //使能信号 //信号信号 //PWM输出 //PWM内部计数器

//PWM计数进程

always @(posedge clock or negedge reset_n) begin

if (~reset_n) begin counter <= 32'd0; end

else if(pwm_enable) begin if (counter >= clock_divide) counter <= 32'd0; else counter <= counter + 1'b1; end end

//PWM比较进程

always @(posedge clock or negedge reset_n) begin

if (~reset_n) begin pwm_out <= 0; end else begin if (pwm_enable & (counter <= duty_cycle)) pwm_out <= 1'b1; else pwm_out <= 1'b0; end end

endmodule

(2)pwm_dac.v(顶层实体)

module pwm_dac(clk,reset_n,seg,dig,key,pwm_out); input clk; input reset_n;

output [7:0] seg;

output [7:0] dig; input [2:0] key;

output pwm_out;

wire [15:0] duty_cycle;

pwm_logic U1( .clock(clk),

.pwm_enable(1'b1), .reset_n(reset_n), .clock_divide(32'hfff),

.duty_cycle({16'd0,duty_cycle}), .pwm_out(pwm_out) );

key_led U2( .clock(clk),

.key({4'b1111,key,1'b1}), .led(),

.hex(duty_cycle), .bin(), .seg(seg), .dig(dig), .ledin(4'd0), .data(16'd0) );

endmodule (3)key_led.v

module key_led(clock,key,led,hex,bin,seg,dig,ledin,data); input clock; //系统时钟(50MHz) input [7:0] key; //按键输入(KEY1~KEY8) output [7:0] led; //LED输出(LED1~LED8) output [15:0] hex; //4位16进制数输出(在数码管1~4显示) output [3:0] bin; //4位2进制数输出(在LED1~LED4显示) output [7:0] seg; //数码管段码输出 output [7:0] dig; //数码管位码输出 input [3:0] ledin; //LED显示输入(在LED5~LED8显示) input [15:0] data; //数码管显示输出(在数码管5~8显示)

reg [15:0] hex_r; reg [3:0] bin_r; reg [7:0] seg_r; reg [7:0] dig_r;

reg reg reg reg

[16:0] count; [7:0] dout1,dout2,dout3,buff; [2:0] cnt3; [3:0] disp_dat;

//时钟分频计数器 //消抖寄存器

//数码管扫描计数器 //数码管扫描显存 //分频时钟,用于消抖和扫描 //按键消抖输出

wire div_clk; wire [7:0] key_edge;

//信号输出

assign hex = hex_r; assign bin = bin_r; assign seg = seg_r; assign dig = dig_r;

assign led = ~{ledin,bin_r};

//时钟分频部分

always @(posedge clock) begin

if (div_clk) count <= 17'd0; else count <= count + 1'b1; end

assign div_clk = (count > 17'd125000);

//按键消抖部分

always @(posedge clock) begin if(div_clk) begin dout1 <= key; dout2 <= dout1; dout3 <= dout2; end end

//按键边沿检测部分 always @(posedge clock) begin

buff <= dout1 | dout2 | dout3; end

assign key_edge = ~(dout1 | dout2 | dout3) & buff;

//4位16进制数输出部分 always @(posedge clock) begin

if(key_edge[0]) hex_r[15:12] <= hex_r[15:12] + 1'b1; end

always @(posedge clock) begin

if(key_edge[1]) hex_r[11:8] <= hex_r[11:8] + 1'b1; end

always @(posedge clock)

begin

if(key_edge[2]) hex_r[7:4] <= hex_r[7:4] + 1'b1; end

always @(posedge clock) begin

if(key_edge[3]) hex_r[3:0] <= hex_r[3:0] + 1'b1; end

//4位2进制数输出部分

always @(posedge clock)

begin

if(key_edge[4]) bin_r[0] <= ~bin_r[0]; end

always @(posedge clock) begin

if(key_edge[5]) bin_r[1] <= ~bin_r[1]; end

always @(posedge clock) begin

if(key_edge[6]) bin_r[2] <= ~bin_r[2]; end

//按键1

//按键2

//按键3

//按键4

//按键5

//按键6

//按键7

always @(posedge clock) //按键8 begin

if(key_edge[7]) bin_r[3] <= ~bin_r[3]; end

//数码管扫描显示部分

always @(posedge clock) //定义上升沿触发进程 begin if(div_clk) cnt3 <= cnt3 + 1'b1; end

always @(posedge clock) begin if(div_clk) begin case(cnt3) //选择扫描显示数据 3'd0:disp_dat = hex_r[15:12]; //第一个数码管 3'd1:disp_dat = hex_r[11:8]; //第二个数码管 3'd2:disp_dat = hex_r[7:4]; //第三个数码管 3'd3:disp_dat = hex_r[3:0]; //第四个数码管 3'd4:disp_dat = data[15:12]; //第五个数码管 3'd5:disp_dat = data[11:8]; //第六个数码管 3'd6:disp_dat = data[7:4]; //第七个数码管 3'd7:disp_dat = data[3:0]; //第八个数码管 endcase case(cnt3) //选择数码管显示位 3'd0:dig_r = 8'b01111111; //选择第一个数码管显示 3'd1:dig_r = 8'b10111111; //选择第二个数码管显示 3'd2:dig_r = 8'b11011111; //选择第三个数码管显示 3'd3:dig_r = 8'b11101111; //选择第四个数码管显示 3'd4:dig_r = 8'b11110111; //选择第五个数码管显示 3'd5:dig_r = 8'b11111011; //选择第六个数码管显示 3'd6:dig_r = 8'b11111101; //选择第七个数码管显示 3'd7:dig_r = 8'b11111110; //选择第八个数码管显示 endcase end end

always @(disp_dat) begin

case(disp_dat) //七段译码

4'h0:seg_r = 8'hc0; 4'h1:seg_r = 8'hf9; 4'h2:seg_r = 8'ha4; 4'h3:seg_r = 8'hb0; 4'h4:seg_r = 8'h99; 4'h5:seg_r = 8'h92; 4'h6:seg_r = 8'h82; 4'h7:seg_r = 8'hf8; 4'h8:seg_r = 8'h80; 4'h9:seg_r = 8'h90; 4'ha:seg_r = 8'h88; 4'hb:seg_r = 8'h83; 4'hc:seg_r = 8'hc6; 4'hd:seg_r = 8'ha1; 4'he:seg_r = 8'h86; 4'hf:seg_r = 8'h8e; endcase end

endmodule

//显示0 //显示1 //显示2 //显示3 //显示4 //显示5 //显示6 //显示7 //显示8 //显示9 //显示a //显示b //显示c //显示d //显示e //显示f

实验十 直流电机控制

1、实验目的

学习使用PWM对直流电机进行调速控制,掌握PWM控制的工作原理 2、实验内容

实验箱上有一个直流电机MG2,控制端DJ_A,DJ_B与FPGA相连。

本实验的内容是设计使用高低电平来控制直流电机的正反转,停止与启动等操作。 把程序下载到FPGA中,按KEY3,观察直流电机的转动状态。 3、电路连接 PIN_119 -to key PIN_32 -to led

PIN_201 -to moto_a PIN_203 -to moto_b

4、实验程序

module moto_test(clk,key,led,moto_a,moto_b); input clk; input key; output led; output moto_a; output moto_b;

reg moto_a_r; reg moto_b_r;

reg [23:0] count;

reg dir; reg dout1,dout2,dout3,buff; wire key_edge;

reg speed_clk; wire div_clk;

//时钟分频部分

always @(posedge clk) begin count = count + 1'b1; if(count == 24'd16000000) begin count = 24'd0; speed_clk = ~ speed_clk; end end

//系统输入时钟 //按键输入 //LED指示输出

//控制直流电机输出

//时钟分频计数器

//电机旋转方向控制 //消抖寄存器 //按键消抖输出

//电机转动速度控制 //消抖动时钟

assign div_clk = (count[15:0] == 16'hffff); //assign speed_clk = (count >= 24'hffffff);

//按键消抖部分

always @(posedge clk) begin if(div_clk) begin dout1 <= key; dout2 <= dout1; dout3 <= dout2; end end

//按键边沿检测部分 always @(posedge clk) begin buff <= dout1 | dout2 | dout3; end

assign key_edge = ~(dout1 | dout2 | dout3) & buff;

//按键操作部分

always @(posedge clk) //按键1 begin if(key_edge) dir <= ~dir; end

assign led = ~dir; //输出LED指示 assign moto_a = moto_a_r; //输出模块选择 assign moto_b = moto_b_r;

always @(posedge speed_clk) //电机正/反转控制 begin if(dir == 1'b1) begin moto_a_r <= 1'b0 ; moto_b_r <= 1'b1 ; end else begin moto_a_r <= 1'b1 ;

moto_b_r <= 1'b0 ; end end

endmodule

实验十一 步进电机细分驱动控制

1、 实验目的

学习使用FPGA实现步进电机的驱动和细分控制,了解步进电机细分控制的原理 2、 实验内容

本实验使用PWM方法来控制步进电机细分旋转,用KEY2控制正反转,KEY3控制正常运行及细分运行。 3、 电路连接

PIN_23 -to clk PIN_120 -to key\\[0\\] PIN_119 -to key\\[1\\] PIN_74 -to led\\[0\\] PIN_72 -to led\\[1\\]

PIN_200 -to pwm_out\\[0\\] PIN_199 -to pwm_out\\[1\\] PIN_198 -to pwm_out\\[2\\] PIN_197 -to pwm_out\\[3\\] 4、 实验程序

module step_moto(clk,key,led,pwm_out); input clk; input[1:0] key; output[1:0]led; output[3:0] pwm_out; reg[3:0] pwm_out_r; reg[3:0] p_out_r;

reg [23:0] count;

reg [3:0] pwm_count; reg[3:0]cnt4; reg[15:0]duty_cycle; reg dir; reg mode; reg[1:0]dout1,dout2,dout3,buff;

wire[1:0]key_edge; wire pwm_clk; wire speed_clk; wire div_clk;

//时钟分频部分

always @(posedge clk) begin

count <= count + 1'b1; end

assign pwm_clk = (count[6:0] == 7'h7f);

//系统输入时钟 //按键输入 //LED指示输出 //PWM输出

//时钟分频计数器

//PWM内部计数器 //电机步进时序计数器 //PWM占空比控制 //电机旋转方向控制 //电机控制模式 //消抖寄存器

//按键消抖输出 //PWM计数时钟 //电机转动速度控制

//消抖动时钟

assign div_clk = (count[15:0] == 16'hffff); assign speed_clk = (count >= 24'hffffff);

//按键消抖部分

always @(posedge clk) begin if(div_clk) begin dout1 <= key; dout2 <= dout1; dout3 <= dout2; end end

//按键边沿检测部分 always @(posedge clk) begin

buff <= dout1 | dout2 | dout3; end

assign key_edge = ~(dout1 | dout2 | dout3) & buff; //按键操作部分

always @(posedge clk) //按键1 begin

if(key_edge[0]) dir <= ~dir; end

always @(posedge clk) //按键2 begin

if(key_edge[1]) mode <= ~mode; end

assign led = ~{mode,dir}; //输出LED指示 assign pwm_out = mode ? ~pwm_out_r : p_out_r; //输出模块选择(细分/正常)

always @(posedge clk) //电机正/反转控制 begin

if(speed_clk) begin if(dir == 1'b1) cnt4 <= cnt4 + 1'b1; else

cnt4 <= cnt4 - 1'b1;

end end

always @(posedge clk) begin

if(pwm_clk) pwm_count <= pwm_count + 1'b1; end

always @(posedge clk) begin

if (pwm_count[3:0] < duty_cycle[15:12]) pwm_out_r[3] <= 1'b1; else pwm_out_r[3] <= 1'b0; end

always @(posedge clk) begin

if (pwm_count[3:0] < duty_cycle[11:8])

pwm_out_r[2] <= 1'b1; else pwm_out_r[2] <= 1'b0; end

always @(posedge clk) begin

if (pwm_count[3:0] < duty_cycle[7:4]) pwm_out_r[1] <= 1'b1; else pwm_out_r[1] <= 1'b0; end

always @(posedge clk) begin

if (pwm_count[3:0] < duty_cycle[3:0]) pwm_out_r[0] <= 1'b1; else pwm_out_r[0] <= 1'b0; end

always @(posedge clk) begin

//PWM波计数器

//PWM A通道

//PWM B通道

//PWM C通道

//PWM D通道

//步进电机控制时序

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

Top