这是西安电子科技大学2019级数字电路课程实践项目之一,在此将自己的实践过程和实验报告整理发布,以供日后回顾。
一组发光LED,在控制系统的控制下按照设定的顺序和时间来发亮和熄灭,这样就能形成一定的视觉效果。如果通过设计,实现LED灯依次点亮,那么就形成流水灯。
本实验的内容就是设计这样的控制系统,实现12位流水灯,并进行仿真及下载到电路板验证。
流水灯的关键设计
-
状态及其变化
状态
需要存储当前的状态,12个灯中有一个是亮的,定义12个触发器构成的12位寄存器ledtemp保存当前的状态。时钟
流水灯的流转时间设置为半秒钟(500ms/2Hz)比较合适,系统的唯一时钟来源是由电路板上的有源晶振所产生的时钟连接到FPGA,是50MHz的时钟clk,因此需做25,000,000分频。状态变化
将寄存器ledtemp的初始值设置为12'b0000_0000_0001,divclk的每个上升边沿,对ledtemp进行向左移位,当移到12'b1000_0000_0000之后,再次移位应移为12'b0000_0000_0001。
分频设计
要进行25,000,000分频,采用计数器的方式。当计数值达到12,500,000时令divclk翻转,这样divclk的一个周期就是25,000,000个clk时钟周期。
需要一个寄存器变量存储计数值,12,500,000的十六进制是BEBC20为24位,因此需要设计24位以上的寄存器保存计数值。
0-> 12,500,000->0-> 12,500,000->0-> 12,500,000约束文件设计
需要定义一个时钟输入,12个数码管输出。
实践过程
创建vivado项目
- 创建新项目
- 选择项目类型
- 选择开发板,我们的开发板芯片型号是xc7a35tftg256
- 最后选择Finish,完成工程的创建。
工程文件的创建与编写
- 创建Verilog文件
- 通过Add Sources添加新Verilog文件;
- 选择文件类型为Design Sources;
- 点击Create File;
- 选择文件类型并命名;
点击Finish即可(没有显示的步骤均点击OK/YES即可),在建立好的Verilog文件中添加如下代码:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2020/12/15 17:16:49
// Design Name:
// Module Name: LED_Test_1
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module LED_Test_1(
input SysCLK,
output [11:0] LED
);
reg [11:0] LEDReg = 12'b000000000001;
reg [31:0] ClkDiv = 0;
reg LEDPos;
initial LEDPos = 1;
assign LED = LEDReg;
//定义分频参数值
parameter Div = 12500000;
always @(posedge SysCLK) begin
if (ClkDiv == Div) begin
ClkDiv <= 0;
//时序电路通过有限状态机来实现
if(LEDPos) begin
case (LEDReg)
12'b000000000001: LEDReg <= 12'b000000000010;
12'b000000000010: LEDReg <= 12'b000000000100;
12'b000000000100: LEDReg <= 12'b000000001000;
12'b000000001000: LEDReg <= 12'b000000010000;
12'b000000010000: LEDReg <= 12'b000000100000;
12'b000000100000: LEDReg <= 12'b000001000000;
12'b000001000000: LEDReg <= 12'b000010000000;
12'b000010000000: LEDReg <= 12'b000100000000;
12'b000100000000: LEDReg <= 12'b001000000000;
12'b001000000000: LEDReg <= 12'b010000000000;
12'b010000000000: LEDReg <= 12'b100000000000;
12'b100000000000: LEDPos <= 1'b0;
endcase
end else begin
case (LEDReg)
12'b100000000000: LEDReg <= 12'b010000000000;
12'b010000000000: LEDReg <= 12'b001000000000;
12'b001000000000: LEDReg <= 12'b000100000000;
12'b000100000000: LEDReg <= 12'b000010000000;
12'b000010000000: LEDReg <= 12'b000001000000;
12'b000001000000: LEDReg <= 12'b000000100000;
12'b000000100000: LEDReg <= 12'b000000010000;
12'b000000010000: LEDReg <= 12'b000000001000;
12'b000000001000: LEDReg <= 12'b000000000100;
12'b000000000100: LEDReg <= 12'b000000000010;
12'b000000000010: LEDReg <= 12'b000000000001;
12'b000000000001: LEDPos <= 1'b1;
endcase
end
end else begin
ClkDiv <= ClkDiv + 1'b1;
end
end
endmodule
- 创建并编写Constraints(约束)文件
约束文件是定义管脚功能及其电平等属性的文件,可以将Verilog文件中的输入输出映射到开发板的不同管脚上。
创建约束文件有两种方法,这里仅展示其中一种,即通过编写代码来获得约束文件。
通过编写代码创建约束文件的具体操作方式与创建Verilog的步骤类似,只需在选择文件类型时选择创建约束文件即可,这里不再写出其全部过程。
- 通过Add Sources添加新Verilog文件;
- 打开约束文件,在其中添加如下代码:
//设置输入输出对应管脚
set_property PACKAGE_PIN D4 [get_ports SysCLK]
set_property PACKAGE_PIN P9 [get_ports {LED[0]}]
set_property PACKAGE_PIN R8 [get_ports {LED[1]}]
set_property PACKAGE_PIN R7 [get_ports {LED[2]}]
set_property PACKAGE_PIN T5 [get_ports {LED[3]}]
set_property PACKAGE_PIN N6 [get_ports {LED[4]}]
set_property PACKAGE_PIN T4 [get_ports {LED[5]}]
set_property PACKAGE_PIN T3 [get_ports {LED[6]}]
set_property PACKAGE_PIN T2 [get_ports {LED[7]}]
set_property PACKAGE_PIN R1 [get_ports {LED[8]}]
set_property PACKAGE_PIN G5 [get_ports {LED[9]}]
set_property PACKAGE_PIN H3 [get_ports {LED[10]}]
set_property PACKAGE_PIN E3 [get_ports {LED[11]}]
//设置管脚电平
set_property IOSTANDARD LVCMOS33 [get_ports SysCLK]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {LED[11]}]
至此,工程所需代码全部编写完成。
综合工程的源文件
编写完全部文件后我们需要对工程文件进行综合,步骤如下:
- 点击Run Synthsis综合工程的源文件;
- 按照默认设置运行即可,开始运行后软件界面右上角会显示运行状态,等待综合结束即可;
- 完成综合。
实现综合设计网表
- 完成综合后,选择Run Implementation,点击OK,实现综合设计网表;
- 按照默认设置运行即可,开始运行后软件界面右上角会显示运行状态,等待运行结束即可;
- Implementation完成。
生成比特流文件
- Implementation完成后,选择Generate Bitstream生成比特流文件,按照默认设置运行即可,开始运行后软件界面右上角会显示运行状态,等待运行结束即可;
- 比特流文件生成完成,这里点击Open Hardware Manager来准备硬件的连接与烧录。
硬件的连接与烧录
生成比特流文件结束后,我们需要将其烧录到开发板上,具体步骤如下:
- 用USB连接线将开发板连接到电脑上,在Hardware窗口中点击Auto Connect;
- 此时Hardware窗口应显示如下:
- 右击开发板,将其打开;
- 点击Program Device进行烧录,烧录完成后流水灯即可正常运行。