EBAZ4205 第二个工程 用ZYNQ的PL(FPGA)设计流水灯

工程1完整的介绍了一个工程从创建到编译综合,最终到程序运行的全过程,本工程在工程一的基础上进一步深化,以流水灯的形式同时点亮三个LED灯

1.原理图分析

EBAZ4205扩展板LED部分原理图

从上面电路图可以看出两个信息

1)三个LED灯的阴极接的GND, 则FPGA接LED的管脚输出为高电平,LED灯点亮,FPGA接LED的管脚输出为低电平 LED 熄灭 2)LED灯分别接到主芯片(PL)部分的E19,K17,H18三个管脚上

板子上共有4个按键,我们用板子中间的按键KEY3来充当复位按键的角色

EBAZ4205板子上时钟部分电路

时钟我们选择在EBAZ4205板子上焊接一个50MHZ的晶振, 该晶振时钟输出管脚接到FPGA的N18脚上

2.程序设计

LED的驱动方式有很多种

1)直驱方式,比较简单 如下

module LED(

    output LED1,
    output LED2
);
assign LED1=1'b0;
assign LED2=1'B1;

    
endmodule

这种方式相当于把LED的输出口直接通过assign 方式内部连接到 VCC,和GND上, 如上面代码中LED1连接到了GND,处于熄灭状态,LED2连接到了内部的VCC上 处于点亮状态

这个代码比较简单 所以不作展开

2) 接下来介绍一种用计数器来分别点亮3个LED灯来实现 流水灯的效果

由于我们板子上焊接的是一个50Mhz的晶振,所以每秒钟晶体振荡 50_000_000次,用计算器看50000000换算成二进制共占用26位,所以这里我们定义一个26bit 的寄存器作计数器用

reg [25:0]time_count; //[25:0]代表26bit

1秒钟计数器模块 接下来是编写一个完成的1秒钟计数器模块 parameter T1MS = 26’d50_000_000 ; //50M晶振时钟 reg [25:0]time_count; always@(posedge CLK or negedge RSTn) if(!RSTn)begin//当复位条件下,计数器赋初值0 time_count<=26’d0; end else begin//当不在复位条件下 if(time_count>=T1MS-1’b1)//如果计数器达到 50_000_000则代表一秒钟计数完成 time_count<=26’d0; else time_count<=time_count+1’b1;//其他情况下计数器自增 end

其中 parameter T1MS = 26’d50_000_000 ; 为定义一个常量,前面所说50M晶振下,1秒钟晶体震荡50_000_000次

always@(posedge CLK or negedge RSTn) 代表模块进入的两个条件,1是系统时钟的上升沿(posedge),另一种是复位信号的下降沿(negedge),也就当系统复位信号按下瞬间,时钟每次上升沿进入并执行always@块中的内容

复位条件下 if(!RSTn) 系统对计数器模块进行初始化0的操作

当系统不处于初始化情况,每个时钟上升沿 time_count 都自增1,当 time_count >= T1MS -1’b1时,即计数达到1秒钟的时间的时候, time_count 再次清零

LED灯切换模块

 reg [1:0]led_state;
    always@(posedge CLK or negedge RSTn)
        if(!RSTn)begin//当复位条件下,计数器赋初值0
    reg [1:0]led_state;
    always@(posedge CLK or negedge RSTn)
        if(!RSTn)begin//当复位条件下,计数器赋初值0
             led_state<=2'd0;
        end
        else begin
             if(time_count==T1MS-1'b1)begin
                if(led_state>=2'd2)led_state<=2'd0;
                else led_state<=led_state+1'b1;    
            end
        end    
      
      assign LED1= (led_state==2'd0)?1'b1:1'b0;
      assign LED2= (led_state==2'd1)?1'b1:1'b0;
      assign LED3= (led_state==2'd2)?1'b1:1'b0;

这里定义了一个2bit的led_state寄存器,用来控制当前灯的显示状态,从程序上可以看出,每当 time_count==T1MS-1’b1 时, led_state 在0-2反复循环自增。

led_state从0-2反复循环,每一种状态对应一个LED灯的显示,如 led_state =0时,LED1亮,当 led_state =1时LED2亮,当 led_state =3时LED=3亮。

工程完整代码如下

`timescale 1ns / 1ps
module LED(
    input  CLK,//时钟
    input  RSTn,//复位
    output LED1,
    output LED2,
    output LED3
    );
    
    parameter T1MS = 26'd50_000_000 ; //50M晶振时钟
    reg [25:0]time_count;
    always@(posedge CLK or negedge RSTn)
        if(!RSTn)begin//当复位条件下,计数器赋初值0
            time_count<=26'd0;
        end
        else begin//当不在复位条件下
            if(time_count>=T1MS-1'b1)//到达1秒钟
                time_count<=26'd0;
            else time_count<=time_count+1'b1;//其他情况下计数器自增
        end
        
    reg [1:0]led_state;
    always@(posedge CLK or negedge RSTn)
        if(!RSTn)begin//当复位条件下,计数器赋初值0
             led_state<=2'd0;
        end
        else begin
             if(time_count==T1MS-1'b1)begin//一秒钟
                if(led_state>=2'd2)led_state<=2'd0;//从0-2反复循环
                else led_state<=led_state+1'b1;//自增 
            end
        end    
      
      assign LED1= (led_state==2'd0)?1'b1:1'b0;
      assign LED2= (led_state==2'd1)?1'b1:1'b0;
      assign LED3= (led_state==2'd2)?1'b1:1'b0;
      
endmodule

项目的约束文件(管脚定义)

set_property IOSTANDARD LVCMOS33 [get_ports LED1]
set_property IOSTANDARD LVCMOS33 [get_ports LED2]
set_property IOSTANDARD LVCMOS33 [get_ports LED3]
set_property IOSTANDARD LVCMOS33 [get_ports CLK]
set_property IOSTANDARD LVCMOS33 [get_ports RSTn]
set_property PACKAGE_PIN H18 [get_ports LED1]
set_property PACKAGE_PIN K17 [get_ports LED2]
set_property PACKAGE_PIN E19 [get_ports LED3]
set_property PACKAGE_PIN N18 [get_ports CLK]
set_property PACKAGE_PIN U20 [get_ports RSTn]

create_clock -period 20.000 -name CLK -waveform {0.000 10.000} [get_ports CLK]

本项目约束文件也可以通过工程一的图形界面设置,自动生成

最后将程序进行编译综合,并用JTAG 口下载到板子上可以看到 转接板上3个灯依次按一秒钟的间隔频率闪烁

完整工程下载

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注