ZYNQ从入门到秃头05 LED闪烁实验 && 按键控制LED实验Verilog(PL)
Posted “逛丢一只鞋”
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZYNQ从入门到秃头05 LED闪烁实验 && 按键控制LED实验Verilog(PL)相关的知识,希望对你有一定的参考价值。
文章目录
LED灯闪烁作为一个经典 的入门实验, 其 地位堪比 编程界的“ Hello World!!”。对于ZYNQ依然不例外
LED,又 名 发光 二极管 。 LED灯工作电流很小(有的仅零点几毫安即可发光) 抗冲击和抗震性能好,可靠性高,寿命长 。由于 这些优点, LED灯 被 广泛用 在 仪器 仪表中作指示灯 、 液晶屏背光源 等 诸多领域 。
发光二极管与普通二极管一样具有单向导电性。 给 它 加上 阳极 正向电压后 ,通过 5mA左右 的电流就可以 使 二极管发光 。 通过 二极管 的 电流 越大, 发出 的光 亮度 越强 。不 过 我们一般将 电流限定在 3~20mA之间 ,否则电流过大就会烧坏二极管。
本节实验任务 是使 ALINX 7020底板上的 PL LED1和 PL LED2以固定的频率交替闪烁。
LED闪烁实验Verilog(PL)
硬件设计
老规矩,这种依然是以原理图为依托
我们可以根据原理图的连线关系确定 LED 和 PL 管脚的绑定关系 。
原理图中以 PS_MIO 开头的 IO 都是 PS 端 IO ,不需要绑定,也不能绑定
PL_LED0和 PL_LED1的阴极通过 470 欧姆的电阻连到地( GND)上,阳极由 ZYNQ PL的 IO管脚控制, LED与地之间的电阻起到限流作用。
本实验中,系统时钟、按键复位以及两个LED端口的管脚 分配如下表所示,其中复位按键和两个LED位于底板上,时钟位于核心板上:
程序设计
由于发光二极管的 阳 极与 ZYNQ的 管脚 相连,只需要改变与 LED灯 相连的 ZYNQ管脚 的 电平, LED灯的 亮灭状态就会发生变化 。当ZYNQ管脚 为低 电平 时 LED灯 点亮 为高 电平 时, LED灯熄灭。
创建Verilog HDL文件
- 点击 Project Manager 下的 Add Sources 图标(或者使用快捷键 Alt+A
- 选择添加或创建设计源文件“ Add or create design sources 点击“ Next
- 选择创建文件“ Create File
- 文件名“ File name ”设置为 led ”,点击 OK
- 点击“ Finish 完成“ led.v ”文件添加
- 在弹出的模块定义“ Define Module 中可以指定“ led.v ”文件的模块名称 Modulename 这里默认不变为“ led ”,还可以指定一些端口,这里暂时不指定,点击 OK ”。
- 在弹出的对话框中选择“ Yes
- 双击“ led.v ”可以打开文件,然后编辑
编写Verilog
其中,计数器对50MHz时钟进行计数,从而达到计时的目的。
计数器在每次计时到 1秒之后清零,然后重新开始计数,计数的值用于控制 LED的显示状态。当计数器的值小于 0.5s时,就把 LED0点亮并把 LED1熄灭;每当计数器的值大于 0.5s时,就把 LED0熄灭并把 LED1点亮,以此实现两个 LED的交替闪烁。
module led_twinkle(
input sys_clk , //系统时钟
input sys_rst_n, //系统复位,低电平有效
output [1:0] led //LED灯
);
//reg define
reg [25:0] cnt ;
//*****************************************************
//** main code
//*****************************************************
//对计数器的值进行判断,以输出LED的状态
assign led = (cnt < 26'd2500_0000) ? 2'b01 : 2'b10 ;
//assign led = (cnt < 26'd5) ? 2'b01 : 2'b10 ; //仅用于仿真
//计数器在0~5000_000之间进行计数
always @ (posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)
cnt <= 26'd0;
else if(cnt < 26'd5000_0000)
// else if(cnt < 26'd10) //仅用于仿真
cnt <= cnt + 1'b1;
else
cnt <= 26'd0;
end
endmodule
endmodule
上述是一个简单的实现过程,控制两个灯闪烁
为了更加深入理解,下面 这个代码控制4个灯,然后交替闪烁
module led_flash(
input sys_clk, // 系统时钟
input sys_rst_n, // 系统复位,低电平有效
output reg [3 : 0] led
);
reg [31 : 0] cnt;
reg [3 : 0] led_flag;
//*********************************************************
//** main
//*********************************************************
// 计数器在0~5000_0000之间进行计数
always @ ( posedge sys_clk or negedge sys_rst_n ) begin
if( !sys_rst_n ) begin
cnt <= 32'd0;
led_flag <= 0;
end
else if(cnt < 32'd18_000_000) begin
cnt <= cnt + 1'b1;
led_flag <= 0;
end
else if(cnt >= 32'd18_000_000 && cnt < 32'd36_000_000) begin
cnt <= cnt + 1'b1;
led_flag <= 1;
end
else if(cnt >= 32'd36_000_000 && cnt < 32'd50_000_000) begin
cnt <= cnt + 1'b1;
led_flag <= 2;
end
else if(cnt >= 32'd50_000_000) begin
cnt <= 32'd0;
led_flag <= 0;
end
end
always @ (*) begin
case (led_flag)
4'd0 : led = 4'b1111;
4'd1 : led = 4'b1010;
4'd2 : led = 4'b0101;
default : led = 4'b1111;
endcase
end
endmodule
添加管脚约束
Vivado使用的约束文件格式为 xdc 文件。 xdc 文件里主要是完成管脚的约束 时钟的约束 ,以及组的约束。这里我们需要对 led.v 程序中的输入输出端口分配到 FPGA 的真实管脚上 。
添加时序约束
一个FPGA 设计除了管脚分配以外,还有一个重要的约束,那就是时序约束,这里通过向导方式演示如果进行一个时序约束。
-
点击“ Run Synthesis ”开始综合
-
弹出对话框点击“ OK
-
综合完成以后点击“ Cancel
-
点击“ Constraint s Wizard
-
在弹出的窗口中点击“ Next
-
时序约束向导分析出设计中的时钟,这里把“ sys_clk ”频率设置为 5 0Mhz ,然后点击“Skip to Finish ”结束时序约束向导。
这个时候 led.xdc 文件已经更新,点击“ Reload ”重新加载文件,并保存文件
生成BIT文件
- 编译的过程可以细分为综合、布局布线、生成 bit 文件等,这里我们直接点击“ GenerateBitstream 直接生成 bit 文件。
- 在弹出的对话框中可以选择任务数量,这里和 CPU 核心数有关,一般数字越大,编译越快,点击“ OK
- 编译中没有任何错误,编译完成,弹出一个对话框让我们选择后续操作, 可以选择Open Hardware Manger ”,当然,也可以选择 Cancel 我们这里选择 “ Cancel”,先不下载。
Vivado仿真
接下来我们不妨小试牛刀,利用Vivado 自带的 仿真工具来输出波形验证 流水灯程序 设计结果和我们的预想是否一致 注意:在生成 bit 文件之前也可以仿真 。 具体步骤如下:
1) 设置 Vivado 的仿真配置 右 击 SIMULATION 中 Simulation Settings 。
2) 在 Simulation Settings 窗口中进行如下图来配置,这里设置成 50ms (根据需要自行设定其它按默认设置,单击 OK 完成。
3) 添加 激励测试文件 ,点击 Project Manager 下的 Add Sources 图标 按下图设置后单击 Next
4) 点击 Create File 生成仿真激励文件 。
在弹出的对话框中输入激励文件的名字,这里我们输入名为tb_led_test。
5) 点击 Finish 按钮返回。
这里我们先不添加IO Ports ,点击 OK 。
在 Simulation Sources 目录下多了一个刚才添加的 vtf_led_test 文件。双击打开这个文件,可以看到里面只有 module 名的定义,其它都没有。
6) 接下去我们需要编写这个 tb_led_test.v 文件的内容。首先定义输入和输出信号,然后需要实例化 led_test 模块 让 led_test 程序作为本测试程序的一部分。再 添加复位和时钟的激励。完成后的 tb_led_test.v 文件如下:
`timescale 1ns / 1ps
//
// Module Name: tb_led_test
//
module tb_led_test;
// Inputs
reg sys_clk;
reg sys_rst_n ;
// Outputs
wire [3:0] led;
// Instantiate the Unit Under Test (UUT)
led_flash uut_led_flash (
.sys_clk(sys_clk),
.sys_rst_n(sys_rst_n),
.led(led)
);
initial begin
// Initialize Inputs
sys_clk = 0;
sys_rst_n = 0 ;
#1000 ;
sys_rst_n = 1;
end
//Create clock
always #10 sys_clk = ~ sys_clk;
endmodule
- 编写好后保存, tb_ led_test .v 自动 成了这个仿真 Hierarchy 的顶层了,它下面是设计文件led_test .v
- 点击 Run Simulation 按钮,再选择 Run Behavioral Simulation 。这里我们做一下行为级的仿真就可以了。
10.在 弹出 仿真界面 后 如下图,界面是仿真软件自动运行到仿真设置的 50ms 的波形。
由于LED[3 0] 在程序中设计的状态变化时间长,而仿真又比较耗时,在这里观测 timer[31:0] 计数器变化。把它放到 Wave 中观察 点击 Scope 界面下的 uut 再右键选择 Objects 界面下的 timer在弹出的下拉菜单里选择 Add Wave Window 。
11.点击如下标注的 Restart 按钮复位一下,再点击 Run All 按钮。(需要耐心!!!) 可以 看到仿真波形与设计相符。( 注意 :仿真的时间越长,仿真的波形文件占用的磁盘空间越大,波形文件在工程目录的 xx.sim 文件夹)
下载
编译工程并生成比特流.bit文件后,点击 Vivado左侧“ Flow Navigator”窗口最下面的 Open Hardware Manager”按钮如 下图所示 。
此时将Xilinx下载器一 端连 接 电脑, 另 一端 与 开发板上 的 JTAG下载 口连接,开发板 连接电源线
注意!一定要先把下载器的一端连接到了电脑、另一端连接了JTAG接口之后,再给开发板上电!否则,对开发板的 JTAG接口进行带电热插拔,有一定概率会损坏 JTAG接口!
开发板连接好电源线和下载器后,打开开发板电源开关,点击 Hardware”窗口中的 “Auto Connect”图标,如下图所示:
可以看到 JTAG 扫描到 arm 和 FPGA 内核
选择 xc 7z020 _1 ,右键 Program Device…
在弹出窗口中点击“ Program
下载完成以后,我们可以看到 4 颗 LED 开始每秒变化一次。到此为止 Vivado 简单流程体验完成。后面的章节会介绍如果把程序烧录到 Flash ,需要 PS 系统的配合才能完成,只有PL 的工程不能直接烧写 Flash 。
按键控制LED实验Verilog(PL)
硬件设计
AX7020开发板的 PL 部分板载了 4 个用户按键 (KEY1~KEY4), 按键的信号连接到 ZYNQ 的BANK34 和 BANK35 的 IO 上。 按键 都 为低电平有效 , 没有按下时,信号为高;按键按下时,信号为低。
程序设计
按键控制LED系统框图 如下图 所示:
计数器对 50MHz时钟进行计数,从而达到计时的目的。 计数器在每次计时到 0.5秒的时候,就改变 LED的显示状态,然后清零并重新开始计数。
然后根据两个按键(KEY0和 KEY1)的状态,在不同的 LED状态下,分别设置 LED的显示模式(是同时闪烁,或者交替闪烁)。
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/12/20 17:25:22
// Design Name:
// Module Name: led_key
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module led_key(
input sys_clk ,
input sys_rst_n ,
input [1 : 0] key ,
output reg [1 : 0] led
);
// reg define
reg [24 : 0] cnt;
reg led_ctrl;
//*****************************************************
//** main code
//*****************************************************
// 计数器 产生计时器
always @ (posedge sys_clk or negedge sys_rst_n) begin
if( !sys_rst_n )
cnt <= 25'd0;
else if( cnt <= 25'd5_000_000 )
cnt <= cnt + 1'b1;
else
cnt <= 25'd0;
end
//每隔100ms就更改LED闪烁状态
always @ (posedge sys_clk or negedge sys_rst_n) begin
if( !sys_rst_n )
led_ctrl <= 1'b0;
else if( cnt == 25'd5_000_000 )
led_ctrl <= ~led_ctrl;
end
//根据按键的状态以及LED的闪烁状态来赋值LED
always @ ( posedge sys_clk or negedge sys_rst_n ) begin
if( !sys_rst_n )
led <= 2'b11;
else case ( key )
//如果按键0按下,则两个LED交替闪烁
2'b10 :
if( led_ctrl == 1'b0 )
led <= 2'b01;
else
led <= 2'b10;
//如果按键1按下,则两个LED同时闪烁
2'b01 :
if( led_ctrl == 1'b0 )
led <= 2'b11;
else
led <= 2'b00;
//如果两个按键都未按下,则两个LED都保持点亮
2'b11 :
led <= 2'b00;
default: ;
endcase
end
endmodule
连接开发板的电源和下载器,并打开电源开关。在工程编译之后,将生成的bit文件下载到开发板中。下载完成之后,底板上 两个 PL LED处于 点亮状态。然后 按下 PL_KEY0,可以看到 两个 PL LED交替闪烁;按下 PL_KEY1,可以看到 两个 PL的 LED同时闪烁。
以上是关于ZYNQ从入门到秃头05 LED闪烁实验 && 按键控制LED实验Verilog(PL)的主要内容,如果未能解决你的问题,请参考以下文章
ZYNQ从入门到秃头10 DDS增强版实验ADDA测试(基于ALINX 7020 && AN108)
ZYNQ从入门到秃头07 FPGA 片内 RAM && ROM 读写测试实验
ZYNQ从入门到秃头07 FPGA 片内 RAM && ROM 读写测试实验
ZYNQ从入门到秃头10 DAC FIFO实验(AXI-stream FIFO IP核配置)