赞
踩
LED,又 名 发光 二极管 。 LED灯工作电流很小(有的仅零点几毫安即可发光) 抗冲击和抗震性能好,可靠性高,寿命长 。由于 这些优点, LED灯 被 广泛用 在 仪器 仪表中作指示灯 、 液晶屏背光源 等 诸多领域 。
发光二极管与普通二极管一样具有单向导电性。 给 它 加上 阳极 正向电压后 ,通过 5mA左右 的电流就可以 使 二极管发光 。 通过 二极管 的 电流 越大, 发出 的光 亮度 越强 。不 过 我们一般将 电流限定在 3~20mA之间 ,否则电流过大就会烧坏二极管。
本节实验任务 是使 ALINX 7020底板上的 PL LED1和 PL LED2以固定的频率交替闪烁。
老规矩,这种依然是以原理图为依托
我们可以根据原理图的连线关系确定 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灯熄灭。
其中,计数器对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 ”重新加载文件,并保存文件
接下来我们不妨小试牛刀,利用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
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 。
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同时闪烁。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。