OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 945|回复: 0

[XILINX] 正点原子 Zynq7000 xc7z010clg400-1 触摸流水灯 flow_touch_led 课后拓展题 分享

[复制链接]

1

主题

3

帖子

0

精华

新手上路

积分
37
金钱
37
注册时间
2023-10-14
在线时间
4 小时
发表于 2023-11-22 21:51:03 | 显示全部楼层 |阅读模式
本帖最后由 huochangling 于 2023-11-22 21:59 编辑

我是正在学习FPGA的新手小白,目前在B站正在跟着 QinQZ 的最新的真人出镜FPGA视频学习。本次分享是因为我跟着视频学到了触摸按键点灯,学到最后 QinQZ大大 提出了一个拓展训练:
通过触摸按键控制流水灯的运行,开发板上电时开发板上的LED灯实现流水灯效果,当按下触摸按键时,流水灯效果暂停,松开时保持此效果;当再次按下时,流水灯继续玉兴,松开时保持此效果。
先将思路分享如下:
1、通过加入一个输入端口:touch_key,还是利用视频中的打两拍,捕获 上升沿 的方式,表示触摸按键被按下。
2、在捕获 上升沿 后,做一个标志位,通过定义一个标志位 led_run_flag 的状态去控制 计数器 的计数的暂停和继续 从而达到控制流水灯状态。具体原理是每次检测到(touch_key)上升沿时,改变led_run_flag 的状态。
例如  led_run_flag =1'b0 的时候表示流水灯暂停运行
        led_run_flag =1'b1 的时候表示流水灯开始运行。


代码分享:module flow_touch_led(
    input               sys_clk,
    input               sys_rst_n,
    input               touch_key,
    output  reg[1:0]    led
);
//设置打两拍
    reg      
   touch_key_d0;
    reg         touch_key_d1;
    wire        post_touch_key;//声明捕获上升沿

    reg         led_run_flag;   //定义标志位决定计数器是否工作,该标志位由捕获post_touch_key的上升沿决定

//定义25位计数器
    reg [24:0]  cnt;
//定义一个外部参数,便于修改
    parameter CNT_MAX = 25'd25000000;//在仿真时25'd25为计时500ns

//post_touch_key是组合逻辑,因此使用assign语句
//采集上升沿
assign post_touch_key =  ~touch_key_d1 & touch_key_d0;


//打两拍操作,在always语句中实现
always @ (posedge sys_clk or negedge sys_rst_n)begin
    if(!sys_rst_n)begin
        touch_key_d0 <= 1'b0;
        touch_key_d1 <= 1'b0;
    end
    else begin
        touch_key_d0 <= touch_key;
        touch_key_d1 <= touch_key_d0;//实现打两拍的操作
    end
end


//由post_touch_key控制标志位 led_run_flag 是否取反 从而控制计数器 继续or暂停计数
always @ (posedge sys_clk or negedge sys_rst_n)begin
    if(!sys_rst_n)
        led_run_flag <= 1'b0;//板子复位信号有效时,给led_run_flag默认为1'b0
    else if(post_touch_key == 1'b1)//当捕获到上升沿时,标志位进行取反(因为该标志位为 1bit,直接取反即可)
        led_run_flag <= ~led_run_flag;
    else                            //当没有捕获到上升沿时,标志位保持不变
        led_run_flag <= led_run_flag;
end


//计数器由led_run_flag的状态决定,计时0.5s
always @ (posedge sys_clk or negedge sys_rst_n)begin
    if(!sys_rst_n)
        cnt <= 25'd0;
    else if(led_run_flag == 1'b1 & cnt < CNT_MAX)begin  //led_run_flag的状态和cnt计数状态 相与为真的情况下  进行如下操作
        if(cnt == CNT_MAX -25'd1)   //如果计数器计数到了CNT_MAX -25'd1,那么就应该给其复位为25'd1
            cnt <= 25'd1;
        else                        //否则计数器正常进行累加计数
            cnt <= cnt + 25'd1;
    end
    else
        cnt <= cnt;
end

//实现流水灯的移位操作
always @ (posedge sys_clk or negedge sys_rst_n)begin
    if(!sys_rst_n)
        led <= 2'b10;
    else if(cnt == CNT_MAX - 25'd1)
        led <= {led[0],led[1]};
    else
        led <= led;
end
endmodule







仿真例化:
`timescale  1ns/1ns     //声明:  仿真单位 / 仿真精度
module tb_flow_touch_led();

parameter CLK_PERIOD = 20;

    reg          sys_clk;    //时钟周期为20ns,每隔10ns翻转一次即可
    reg          sys_rst_n;
    reg          touch_key;
    wire [1:0]   led;


initial begin       //赋初始值
    sys_clk   <= 1'b0;
    sys_rst_n <= 1'b0;
    touch_key <= 1'b0;
    #200
    sys_rst_n <= 1'b1;
    #1000       //延迟1000ns后,触摸按键被按下
    touch_key <=1'b1;//触摸按键被按下后变为高电平1
    #2000       //延迟2000ns后,松开触摸按键
    touch_key <=1'b0;//触摸按键被松开后变为低电平0

//重复按下触摸按键和松开触摸按键的操作

    #1000       //延迟1000ns后,触摸按键被按下
    touch_key <=1'b1;//触摸按键被按下后变为高电平1
    #2000       //延迟2000ns后,松开触摸按键
    touch_key <=1'b0;//触摸按键被松开后变为低电平0  

//重复按下触摸按键和松开触摸按键的操作

    #1000       //延迟1000ns后,触摸按键被按下
    touch_key <=1'b1;//触摸按键被按下后变为高电平1
end

always #(CLK_PERIOD/2)  sys_clk = ~sys_clk;      //周期为20ns,除以2即为:每隔10ns翻转一次


flow_touch_led   u_flow_touch_led
(
    .sys_clk       (sys_clk  ),
    .sys_rst_n     (sys_rst_n),
    .touch_key     (touch_key),
    .led           (led      )

);
endmodule









正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 17:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表