1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > FPGA | 按键 拨码开关控制流水灯实验(附完整代码)

FPGA | 按键 拨码开关控制流水灯实验(附完整代码)

时间:2023-03-23 04:56:43

相关推荐

FPGA | 按键 拨码开关控制流水灯实验(附完整代码)

FPGA 课程设计,果断选择最简单的花式点灯

实验要求

一、设计一个8路流水灯控制电路二、有多种变化方式:1)自左向右逐次点亮,或自右向左逐次点亮,到终点后在从头开始;2)自左向右逐次熄灭,或自右向左逐次熄灭,到终点后再从头开始;3)按一定间隔(自定义)逐次点亮;4)灯工作时间可调;三、设置复位键,独立流水灯工作模式控制键,独立流水灯速度键;四、时钟信号为开发板上时源。完成任务1)-4)的得分不超过65分,有扩展到内容酌情增加得分。

OK,虽然看起来很复杂,但拆分一下要求的话核心是以下几点:

基础流水灯 *、方向控制键 **、速度控制键 **、复位键 ***(*代表优先级)

实验平台

对于流水灯实验,都不需要开发板选型,随便抄起手边现有的板子就直接开始,这里我用的是安路科技的 EF2L45BG256_MINI_DEV3 开发板,原理图如下。我这里LED是低电平点亮,按键按下去是"0",按键释放是"1",拨码开关拨上ON 是"0",拨到OFF 是"1"。

学校里常用的应该是Xilinx或者Altera的板子,但其实影响不大,不同板子只需要对照原理图修改部分代码(LED是低电平点亮还是高电平点亮、按键按下是0还是1)以及管脚约束文件就可以。

设计思路

按键检测

按键开关和拨码开关不同,需要你一直按着才能保持,一旦松手就检测不到’'0"了,这里我为了达到和拨码开关一样的效果(按一下之后就可以松手了),当然你如果想一直按着按键保持流水灯点亮可以忽略这一部分。

因为按下后弹起会有一个从"0"到"1"的上升沿,通过检测这个上升沿就可以判断按键是否被按下后又弹起:

reg key1_d0,key2_d0,key3_d0;reg key1_out,key2_out,key3_out; // 检测按键是否弹起assign key1_up = key[0] & ~key1_d0;assign key2_up = key[1] & ~key2_d0;assign key3_up = key[2] & ~key3_d0;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginkey1_d0 <= 1'b1; key2_d0 <= 1'b1;key2_d0 <= 1'b1;endelse beginkey1_d0 <= key[0]; key2_d0 <= key[1];key3_d0 <= key[2];endend // 每次检测到按键弹起,令对应的key_out取反,即开/关状态切换always@(posedge clk or negedge rst_n) beginif(!rst_n)beginkey1_out <= 0;key2_out <= 0;key3_out <= 0;endelse if(key1_up) key1_out <= ~key1_out;else if(key2_up) key2_out <= ~key2_out;else if(key3_up) key3_out <= ~key3_out;end

流水灯控制

这一部分基本都是大同小异的,先设置一个计数器,再设置一个状态控制,当计数到一定值(可以通过设置这个值来改变速度)的时候令状态+1,之后再根据按键选择状态即可:

// 控制流水灯方向always @ (posedge clk or negedge rst_n) beginif(!rst_n)direction <= 1'd0; else if(!switch[0])direction <= 1'd1;elsedirection <= 1'd0;end // key3控制流水灯速度always @(posedge clk or negedge rst_n) beginif (!rst_n)speed <= 25'd24_999_999;else if(key3_out) speed <= 25'd4_999_999;elsespeed <= 25'd24_999_999;end// 计数器,控制流水灯速度always @ (posedge clk or negedge rst_n) beginif(!rst_n)cnt <= 25'd0; else if(cnt < speed)cnt<=cnt+1;elsecnt<=0;end // 控制流水灯状态always @(posedge clk or negedge rst_n) beginif (!rst_n)led_control <= 3'b000;else if(cnt == speed) led_control <= led_control + 1'b1;elseled_control <= led_control;end

完整代码

module key_led(inputclk , inputrst_n, input [1:0] switch, // switch[0]:控制方向 switch[1]:控制间隔点亮input [2:0] key, // key[0]/key[1]:流水灯点亮/熄灭 key[2]:控制速度output reg [7:0] led );reg key1_d0,key2_d0,key3_d0;reg key1_out,key2_out,key3_out; reg direction;reg [24:0] cnt;reg [2:0] led_control; reg [24:0] speed;// 按键弹起wire key1_up,key2_up,key3_up;// 检测按键是否弹起assign key1_up = key[0] & ~key1_d0;assign key2_up = key[1] & ~key2_d0;assign key3_up = key[2] & ~key3_d0;always@(posedge clk or negedge rst_n)beginif(!rst_n)beginkey1_d0 <= 1'b1; key2_d0 <= 1'b1;key2_d0 <= 1'b1;endelse beginkey1_d0 <= key[0];key2_d0 <= key[1];key3_d0 <= key[2];endend always@(posedge clk or negedge rst_n) beginif(!rst_n)beginkey1_out <= 0;key2_out <= 0;key3_out <= 0;endelse if(key1_up) key1_out <= ~key1_out;else if(key2_up) key2_out <= ~key2_out;else if(key3_up) key3_out <= ~key3_out;end// 用拨码开关控制流水灯方向always @ (posedge clk or negedge rst_n) beginif(!rst_n)direction <= 1'd0; else if(!switch[0])direction <= 1'd1;elsedirection <= 1'd0;end // key3控制流水灯速度,时钟25M,24_999_999=1s always @(posedge clk or negedge rst_n) beginif (!rst_n)speed <= 25'd24_999_999;else if(key3_out) speed <= 25'd4_999_999;elsespeed <= 25'd24_999_999;end// 计数器,控制流水灯速度always @ (posedge clk or negedge rst_n) beginif(!rst_n)cnt <= 25'd0; else if(cnt < speed)cnt<=cnt+1;elsecnt<=0;end // 控制流水灯状态always @(posedge clk or negedge rst_n) beginif (!rst_n)led_control <= 3'b000;else if(cnt == speed) led_control <= led_control + 1'b1;elseled_control <= led_control;endalways @(posedge clk or negedge rst_n) beginif(!rst_n) beginled<=8'b0000_0000;endelse if(key1_out & direction & switch[1]) // 从左向右点亮case (led_control)3'b000 : led<=8'b1111_1110;3'b001 : led<=8'b1111_1101;3'b010 : led<=8'b1111_1011;3'b011 : led<=8'b1111_0111;3'b100 : led<=8'b1110_1111;3'b101 : led<=8'b1101_1111;3'b110 : led<=8'b1011_1111;3'b111 : led<=8'b0111_1111;default : led<=8'b1111_1111;endcaseelse if (key1_out & !direction & switch[1]) // 从右向左点亮 case (led_control)3'b000 : led<=8'b0111_1111;3'b001 : led<=8'b1011_1111;3'b010 : led<=8'b1101_1111;3'b011 : led<=8'b1110_1111;3'b100 : led<=8'b1111_0111;3'b101 : led<=8'b1111_1011;3'b110 : led<=8'b1111_1101;3'b111 : led<=8'b1111_1110;default : led<=8'b1111_1111;endcaseelse if (key2_out & direction & switch[1]) // 从左向右熄灭case (led_control) 3'b000 : led<=8'b0000_0000;3'b001 : led<=8'b0000_0001;3'b010 : led<=8'b0000_0011;3'b011 : led<=8'b0000_0111;3'b100 : led<=8'b0000_1111;3'b101 : led<=8'b0001_1111;3'b110 : led<=8'b0011_1111;3'b111 : led<=8'b0111_1111;default : led<=8'b1111_1111;endcase else if (key2_out & !direction & switch[1]) // 从右向左熄灭case (led_control) 3'b000 : led<=8'b0000_0000;3'b001 : led<=8'b1000_0000;3'b010 : led<=8'b1100_0000;3'b011 : led<=8'b1110_0000;3'b100 : led<=8'b1111_0000;3'b101 : led<=8'b1111_1000;3'b110 : led<=8'b1111_1100;3'b111 : led<=8'b1111_1110;default : led<=8'b1111_1111;endcase else if (key2_out & direction & !(switch[1])) // 从左向右间隔熄灭case (led_control) 3'b000 : led<=8'b0000_0000;3'b001 : led<=8'b0000_0001;3'b010 : led<=8'b0000_0101;3'b011 : led<=8'b0001_0101;3'b100 : led<=8'b0101_0101;3'b101 : led<=8'b0000_0001;3'b110 : led<=8'b0000_0101;3'b111 : led<=8'b0001_0101;default : led<=8'b0101_0101;endcase else if (key2_out & !direction & !(switch[1])) // 从右向左间隔熄灭case (led_control) 3'b000 : led<=8'b0000_0000;3'b001 : led<=8'b0100_0000;3'b010 : led<=8'b0101_0000;3'b011 : led<=8'b0101_0100;3'b100 : led<=8'b0101_0101;3'b101 : led<=8'b0100_0000;3'b110 : led<=8'b0101_0000;3'b111 : led<=8'b0101_0100;default : led<=8'b0101_0101;endcase else if (key1_out & direction & !(switch[1])) // 从左向右间隔点亮case (led_control) 3'b000 : led<=8'b1111_1110;3'b001 : led<=8'b1111_0111;3'b010 : led<=8'b1011_1111;3'b011 : led<=8'b1111_1110;3'b100 : led<=8'b1111_0111;3'b101 : led<=8'b1011_1111;3'b110 : led<=8'b1111_1110;3'b111 : led<=8'b0111_0111;default : led<=8'b1011_1111;endcase else if (key1_out & !direction & !(switch[1])) // 从右向左间隔点亮case (led_control) 3'b000 : led<=8'b0111_1111;3'b001 : led<=8'b1110_1111;3'b010 : led<=8'b1111_1101;3'b011 : led<=8'b1011_1111;3'b100 : led<=8'b1111_0111;3'b101 : led<=8'b1111_1110;3'b110 : led<=8'b1101_1111;3'b111 : led<=8'b0111_1011;default : led<=8'b0111_1111;endcaseelse led<=8'b1111_1111; endendmodule

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。