ZYNQ 7020 学习记录-2呼吸灯(模块化)
系列文章目录
1.点灯
2.呼吸灯(模块化)
文章目录
- 系列文章目录
- 前言
- 一、模块实例化
- 二、呼吸灯
- 1.原理解释
- 2.按键消抖模块
- 3.呼吸灯模块
- 4.顶层模块
- 5.上板验证
- 总结
前言
由于研究生课题组所需学习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