ZYNQ 7020 学习记录-2呼吸灯(模块化)

系列文章目录

1.点灯
2.呼吸灯(模块化)



前言

由于研究生课题组所需学习ZYNQ,以下是本人自学ZYNQ的学习记录,所用板卡为:基于 XILINX ZYNQ7000 开发平台的开发板(型号:AX7021B) 2022 款。
在这里插入图片描述

一、模块实例化

模块化,相当于将一个模块当作一个函数,使用在另一个模块中,代码就可以显得有序、不冗余。
示例如下:
加法模块

module add(
    input   num1,    //子模块输入1
    input   num2,    //子模块输入2
    output  add		//子模块输出     
    );
    
assign led = key;
    
endmodule

顶层模块

module top_add(
    input   wire [10:0] a,    		//顶层模块输入1
    input   wire [10:0] b,    		//顶层模块输入2
    output  wire [10:0] sum   //顶层模块输出     
    );
    
add u_add(
	.num1(a),
	.num2(b),
	.add(sum)
);
    
endmodule

二、呼吸灯

1.原理解释

代码如下(示例):

// 呼吸灯由两个部分组成
// 一个是由亮到暗的过程,一个是由暗到亮的过程
// 我们是在固定的频率下通过调整“高电平”的占空比来调控led灯的亮度    ;定义一个LED灯高占空比递增/递减信号inc_dec_flag
// LED灯的亮度由亮到暗变化,就是LED灯信号的高占空比开始递减        inc_dec_flag=1'b1
// LED灯的亮度由暗到亮变化,就是LED灯信号的高占空比开始递增        inc_dec_flag=1'b0
// 系统时钟周期为20ns(50MHz)
// 计时2us=100*20ns——100个周期;从0开始到99     计时4us=200*20ns——200个周期;从0开始到199
// 计时2ms=1000*2us——1000个周期;从0开始到999   计时4ms=1000*4us——1000个周期;从0开始到999
// 计时2s=1000*2ms——1000个周期;从0开始到999    计时4s=1000*4ms——1000个周期;从0开始到999
// 故在2ms从0到999计数时,此时2s计数器进1,故2ms计数值小于等于2s计数器的个数从1到1000在逐渐增多,且每次以2us增加
// 可以定义在2ms小于等于2s计数器值时,给led高电平(变亮)

2.按键消抖模块

// 按键消抖
// 原理:滤除按键值保持时间小于20ms的信号
// 在按键被按下或者被释放时导致按键值产生变化时,从20ms开始倒计时,
// 如果倒计时结束后,按键值仍然保持不变,则认为是一次有效的按键事件。
// 否则,认为是一次无效的按键事件。
// 有效的按键事件会被传递到下一个模块,无效的按键事件会被忽略。
// 该模块的输入为按键信号,输出为有效的按键事件。
// 系统时钟为50MHz,时钟周期为20ns。

module keydebounce (
    input clk, // 系统时钟
    input rst, // 复位信号

    output reg rst_filter
);

parameter CNT_MAX = 20'd1000000;//消抖时间20ms

reg [19:0] cnt;
reg key_d0;//将按键信号延迟一个时钟周期
reg key_d1;//将按键信号延迟两个时钟周期

// 按键信号的延迟
always @(posedge clk ) begin
    key_d0 <= rst;
    key_d1 <= key_d0;
end

// 按键消抖计数器——计时20ms
always @(posedge clk ) begin
    if(key_d1 != key_d0) //按键状态发生变化
        cnt <= CNT_MAX; // 开始计时
    else begin  //按键状态保持不变
        if(cnt > 20'd0) //计数器开始递减
            cnt <= cnt - 1'b1;
        else
            cnt <= 20'd0; //计数器归零
    end
end
// 按键有效输出
always @(posedge clk ) begin
    if(cnt == 20'd1) //计数器归零,按键有效
        rst_filter <= key_d1;
    else //计数器未归零,按键无效
        rst_filter <= rst_filter;
end
    
endmodule

3.呼吸灯模块

module breath_led (
    input clk,
    input rst,

    output reg led
    
);

parameter CNT_2US_MAX = 7'd100;
parameter CNT_2MS_MAX = 10'd1000;
parameter CNT_2S_MAX = 10'd1000;

reg[8:0] cnt_2us;
reg[9:0] cnt_2ms;
reg[9:0] cnt_2s;
reg inc_dec_flag;    

//计数2us
always@(posedge clk or negedge rst)begin
    if(!rst)
        cnt_2us <= 7'b0;
    else if(cnt_2us == (CNT_2US_MAX-7'b1))
        cnt_2us <= 7'b0;
    else
        cnt_2us <= cnt_2us + 7'b1; 
end

//计数2ms
always@(posedge clk or negedge rst)begin
    if(!rst)
        cnt_2ms <= 10'b0;
    else if(cnt_2ms == (CNT_2MS_MAX-10'b1) && cnt_2us == (CNT_2US_MAX-7'b1))
        cnt_2ms <= 10'b0;
    else if(cnt_2us == (CNT_2US_MAX-7'b1))
        cnt_2ms <= cnt_2ms + 10'b1;
    else
        cnt_2ms <= cnt_2ms;
end

//计数2s
always@(posedge clk or negedge rst)begin
    if(!rst)
        cnt_2s <= 10'b0;
    else if(cnt_2s == (CNT_2S_MAX-10'b1) && cnt_2ms == (CNT_2MS_MAX-7'b1) && cnt_2us == (CNT_2US_MAX-7'b1))
        cnt_2s <= 10'b0;
    else if(cnt_2us == (CNT_2US_MAX-7'b1) && cnt_2ms == (CNT_2MS_MAX-7'b1))
        cnt_2s <= cnt_2s + 10'b1;
    else
        cnt_2s <= cnt_2s;
end

// LED灯的亮度由亮到暗变化,就是LED灯信号的高占空比开始递减        inc_dec_flag=1'b1
// LED灯的亮度由暗到亮变化,就是LED灯信号的高占空比开始递增        inc_dec_flag=1'b0
    
always@(posedge clk or negedge rst)begin
    if(!rst)
        inc_dec_flag <= 1'b0;
    else if(cnt_2s == (CNT_2S_MAX-10'b1) && cnt_2ms == (CNT_2MS_MAX-7'b1) && cnt_2us == (CNT_2US_MAX-7'b1))
        inc_dec_flag <= ~inc_dec_flag;
    else
        inc_dec_flag <= inc_dec_flag;
end

    
// 定义在2ms小于等于2s计数器值时,给led高电平(变亮)
always@(posedge clk or negedge rst)begin
    if(!rst)
        led <= 1'b1;//led灯初始状态为高电平,本项目的灯低电平点亮
    else if((inc_dec_flag == 1'b1 && cnt_2ms >= cnt_2s) || (inc_dec_flag == 1'b0 && cnt_2ms <= cnt_2s))
        led <= 1'b0;
    else
        led <= 1'b1;
end
    
endmodule

4.顶层模块

//将呼吸灯模块通过例化到顶层
module top_breath_led(
    input clk,
    input rst,

    output  led1,    //2s
    output  led2    //4s
);

wire rst_filter; // 按键消抖后的值

// 实例化按键消抖模块
keydebounce u_keydebounce (
    .clk(clk),
    .rst(rst),
    .rst_filter(rst_filter)
);

// 实例化呼吸灯模块
// 2s
breath_led #(
    .CNT_2US_MAX(7'd100),
    .CNT_2MS_MAX(10'd1000),
    .CNT_2S_MAX(10'd1000)
) u_breath_led1(
    .clk(clk),
    .rst(rst_filter),
    .led(led1)
);

// 4s
breath_led #(
    .CNT_2US_MAX(8'd200),
    .CNT_2MS_MAX(10'd1000),
    .CNT_2S_MAX(10'd1000)
) u_breath_led2(
    .clk(clk),
    .rst(rst_filter),
    .led(led2)
);

endmodule

5.上板验证

IO定义如下,其中LED1为实图中的绿色灯( Y19),LED2为红色灯(AA19),时钟接口为Y9,rst为用户按键2(A17)
在这里插入图片描述
在这里插入图片描述
具体扩展版引脚分配图如下:
在这里插入图片描述
如图可视,频率不一致的呼吸效果:
在这里插入图片描述

总结

以上就是今天要讲的内容,本文仅仅简单介绍了XILINX ZYNQ7020的使用,如有任何问题请发送邮件至:zelinliu@nuaa.edu.cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值