FPGA课程设计(拨码控制流水灯)

2023-10-11 14:30

本文主要是介绍FPGA课程设计(拨码控制流水灯),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基本要求:以十赫兹的频率,点亮实验开发板上的发光二极管,显示过程中各个点亮的发光二极管的亮度呈现出明暗变化,形似呼吸。开关0 向下系统复位,灯全灭。开关0向上,LED呈现呼吸状显示。(利用pwm)

扩展部分:

分组显示两组不同渐变周期的呼吸灯,Key0控制LED4~LED0显示, KEY1 控制LED9~LED5显示,渐变周期由开关1~开关9输入,同时数码管分别显示2组呼吸灯对应周期数。

module  led
(
//数据的输入input   wire            sys_clk     ,input   wire            sys_rst_n   ,  input   wire    [9:0]   sw_in       ,  input   wire            key_in1     ,  input   wire            key_in2     , //led的输出output  wire   [9:0]   led_out      ,//前三个数码管显示频率output  wire    [6:0]   ge1         ,output  wire    [6:0]   shi1        ,output  wire    [6:0]   bai1        ,//后三个数码管显示频率output  wire  [6:0]   ge2         ,output  wire  [6:0]   shi2        ,output  wire  [6:0]   bai2     );wire    [8:0]     data_in1         ;
wire    [8:0]     data_in2         ;
wire    [10: 0]   bcd1              ;
wire    [10: 0]   bcd2              ;//key1和key2 控制输入的频率
ctrl ctrl_inst
(.sys_clk   (sys_clk)  ,.sys_rst_n (sys_rst_n)  ,  .sw_in     (sw_in)  ,  .key_in1   (key_in1)  ,  .key_in2   (key_in2)  ,.data_in1  (data_in1) ,.data_in2  (data_in2) );//开关输入的二进制数,转换为BCD码用于数码管显示
binTobcd binTobcd_inst1
( .bin (data_in1),   // binary.bcd (bcd1)
);binTobcd binTobcd_inst2
( .bin (data_in2),   // binary.bcd (bcd2)
);//led的输出breath_led breath_led_inst1
(.sys_clk     (sys_clk  ),.sys_rst_n   (sys_rst_n),.data      (data_in1),.led_out     (led_out[4:0]  )
);breath_led breath_led_inst2
(.sys_clk     (sys_clk  ),.sys_rst_n   (sys_rst_n),.data      (data_in2),.led_out     (led_out[9:5]  )
);//数码管显示seg seg_int1
(.sys_clk   (sys_clk)  ,.sys_rst_n (sys_rst_n)  ,.sw0       (sw_in[0])  ,.bcd       (bcd1)  ,.ge        (ge1) ,.shi       (shi1) ,.bai       (bai1) 
);seg seg_int2
(.sys_clk   (sys_clk)  ,.sys_rst_n (sys_rst_n)  ,.sw0       (sw_in[0])  ,.bcd       (bcd2)  ,.ge        (ge2) ,.shi       (shi2) ,.bai       (bai2) 
);module  breath_led(input   wire          sys_clk     , //系统时钟50Mhzinput   wire          sys_rst_n   , //key3全局复位input   wire   [8:0]  data        ,//获得控制权寄存的数据output  reg    [4:0]  led_out  //led的输出
);reg     [9:0]   cnt_1s  ;
reg     [9:0]   cnt_1ms ;
reg     [5:0]   cnt_1us ;
reg             cnt_en  ;//PWM脉宽调制呼吸流水,的几个参数来调制,和改变频率
parameter   CNT_1US_MAX = 6'd49 ;
parameter   CNT_1MS_MAX = 10'd999;
parameter   CNT_1S_MAX  = 10'd999 ;//cnt_1us:1us计数器
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_1us <=  6'd0;else    if(cnt_1us == CNT_1US_MAX)cnt_1us <=  6'd0;elsecnt_1us <=  cnt_1us + 6'd1;//cnt_1ms:1ms计数器
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_1ms <=  10'd0;else    if((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))cnt_1ms <=  10'd0;else    if(cnt_1us == CNT_1US_MAX)cnt_1ms <=  cnt_1ms + 10'd1;elsecnt_1ms <=  cnt_1ms;//cnt_1s:1s计数器以及用1S来作为基础,通过1/data来获得新的频率让led的闪亮
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_1s  <=  10'd0;else    if(data == 9'd0)cnt_1s  <=  10'd0;else    if((cnt_1s == CNT_1S_MAX / data) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))cnt_1s  <=  10'd0;else    if((cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))cnt_1s  <=  cnt_1s + 10'd1;elsecnt_1s  <=  cnt_1s;//cnt_1s:1s计数器以及用1S来作为基础,通过1/data来获得新的频率让led的闪亮的使能信号
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)cnt_en  <=  1'b0;else    if(data == 9'd0)cnt_en  <=  1'b0;else    if((cnt_1s == CNT_1S_MAX / data) && (cnt_1ms == CNT_1MS_MAX) && (cnt_1us == CNT_1US_MAX))cnt_en  <=  ~cnt_en;elsecnt_en  <=  cnt_en;//利用PWM脉宽调制呼吸流水
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)led_out <=  5'b00000;else    if(data == 9'd0)led_out <=  5'b00000;else    if(((cnt_en == 1'b0) && (cnt_1ms <= cnt_1s)) || ((cnt_en == 1'b1) && (cnt_1ms > cnt_1s)))led_out <=  5'b00000;elseled_out <=  5'b11111;endmodulemodule  ctrl
(input   wire            sys_clk     ,//输入50mhz的时钟信号input   wire            sys_rst_n   ,  //复位信号input   wire    [9:0]   sw_in       , //拨码开关input   wire            key_in1     , // 按键控制input   wire            key_in2     ,//按键控制output  reg    [8:0]     data_in1   ,//输出的数据output  reg    [8:0]     data_in2    //输出的数据);reg              begin_reg        ;//开始的标志,开始时10hz的频率
reg              sw0_reg          ;//sw[0]的延时一拍
reg              key_in1_reg      ;//按键1控制后面的数据
reg              key_in2_reg      ;  //按键2控制前面的数据wire             sw0_flag          ; //SW[0]拨动了的标志信号//最开SW0拨上去就赋值给数据初始值10hz,按下按键后跳转
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)sw0_reg <= 1'd0;elsesw0_reg <= sw_in[0];assign  sw0_flag = ((sw_in[0])&&(~ sw0_reg));always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)begin_reg <= 1'd0;else    if(key_in1 == 1'd0 ||key_in2 == 1'd0)begin_reg <= 1'd0;else    if(sw0_flag == 1'd1)begin_reg <= ~ begin_reg;elsebegin_reg <=  begin_reg;// 按下按键获得对前后数据的控制权
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)key_in1_reg <= 1'd0;else    if(sw_in[0] == 1'd0)key_in1_reg <= 1'd0;else    if(key_in2 == 1'd0)key_in1_reg <= 1'd0;        else    if(sw_in[0] == 1'd1 && key_in1 == 1'd0)key_in1_reg <= 1'd1;elsekey_in1_reg <= key_in1_reg;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)key_in2_reg <= 1'd0;else    if(sw_in[0] == 1'd0)key_in2_reg <= 1'd0;else    if(key_in1 == 1'd0)key_in2_reg <= 1'd0;else    if(sw_in[0] == 1'd1 && key_in2 == 1'd0)key_in2_reg <= 1'd1;elsekey_in2_reg <= key_in2_reg;//把数据传输给寄存器
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)data_in1 <= 9'd0;else    if(sw_in[0] == 1'd0)data_in1 <= 9'd0;else    if(sw_in[0] == 1'd1 && begin_reg == 1'd1)data_in1 <= 9'd10;else    if(key_in1_reg == 1'd1)data_in1 <= sw_in[9:1] ;elsedata_in1 <= data_in1;always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)data_in2 <= 9'd0;else    if(sw_in[0] == 1'd0)data_in2 <= 9'd0;else    if(sw_in[0] == 1'd1 && begin_reg == 1'd1)data_in2 <= 9'd10;else    if(key_in2_reg == 1'd1)data_in2 <= sw_in[9:1] ;elsedata_in2 <= data_in2;endmodulemodule  seg
(input   wire            sys_clk     ,//系统时钟50Mhzinput   wire            sys_rst_n   ,//key3全局复位input   wire            sw0         ,//sw0的拨码输入input   wire    [10:0]  bcd         ,//转换后的BCd码output  reg    [6:0]    ge         ,//个位的输出output  reg    [6:0]    shi        ,//十位的输出output  reg    [6:0]    bai        //百位的输出
);//个位的输出
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)ge <= 7'b1_111_111;else    if(sw0 == 1'd0)ge <= 7'b1_111_111;else    case(bcd[3:0])
4'b0000:ge <= 7'b1_000_000;
4'b0001:   ge <= 7'b1_111_001;
4'b0010:   ge <= 7'b0_100_100;
4'b0011:   ge <= 7'b0_110_000;
4'b0100:   ge <= 7'b0_011_001;
4'b0101:   ge <= 7'b0_010_010;
4'b0110:   ge <= 7'b0_000_010;
4'b0111:   ge <= 7'b1_111_000;
4'b1000:   ge <= 7'b0_000_000;
4'b1001:   ge <= 7'b0_010_000;
default:    ge <= 7'b1_000_000;
endcase//十位的输出
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)shi <= 7'b1_111_111;else    if(sw0 == 1'd0)shi <= 7'b1_111_111;else    case(bcd[7:4])
4'b0000:shi <= 7'b1_000_000;
4'b0001:shi <= 7'b1_111_001;
4'b0010:shi <= 7'b0_100_100;
4'b0011:shi <= 7'b0_110_000;
4'b0100:shi <= 7'b0_011_001;
4'b0101:shi <= 7'b0_010_010;
4'b0110:shi <= 7'b0_000_010;
4'b0111:shi <= 7'b1_111_000;
4'b1000:shi <= 7'b0_000_000;
4'b1001:shi <= 7'b0_010_000;
default:    shi <= 7'b1_000_000;
endcase//百位的输出
always@(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n == 1'b0)bai <= 7'b1_111_111;else    if(sw0 == 1'd0)bai <= 7'b1_111_111;else    case(bcd[10:8])
3'b000:bai <= 7'b1_000_000;
3'b001:     bai <= 7'b1_111_001;
3'b010:     bai <= 7'b0_100_100;
3'b011:     bai <= 7'b0_110_000;
3'b100:     bai <= 7'b0_011_001;
3'b101:     bai <= 7'b0_010_010;
3'b110:     bai <= 7'b0_000_010;
3'b111:     bai <= 7'b1_111_000;
/* 4'b1000: shi <= 7'b0_000_000;
4'b1001:    shi <= 7'b0_010_000; */
default:    bai <= 7'b1_000_000;
endcaseendmodulemodule binTobcd(input	[8:0]	bin,//二进制数output	[10:0]	bcd//BCD码);reg [3:0] ones;
reg [3:0] tens;
reg [2:0] hundreds;
integer i;//移3进位的算法
always @(*) beginones 		= 4'd0;tens 		= 4'd0;hundreds 	= 3'd0;for(i = 8; i >= 0; i = i - 1) beginif (ones >= 4'd5) 		ones = ones + 4'd3;if (tens >= 4'd5) 		tens = tens + 4'd3;if (hundreds >= 4'd5)	hundreds = hundreds + 4'd3;hundreds = {hundreds[1:0],tens[3]};tens	 = {tens[2:0],ones[3]};ones	 = {ones[2:0],bin[i]};endend	assign bcd = {hundreds, tens, ones};endmodule

测试代码:

`timescale 1ns/1ns //时间参数
module tb_led();reg            sys_clk     ;//模拟时钟信号
reg            sys_rst_n   ; //模拟复位信号
reg    [9:0]   sw_in       ; //模拟拨码
reg            key_in1     ; //模拟按键
reg            key_in2     ;//模拟按键wire    [9:0]led_out      ;//模拟灯的输出wire   [6:0] ge1         ;
wire   [6:0] shi1        ;
wire  [6:0]  bai1        ;wire   [6:0] ge2         ;
wire   [6:0] shi2        ;
wire  [6:0]  bai2     ;//模拟输入
initialbeginsys_clk = 1'b1;//开始的赋值sys_rst_n <= 1'b0;sw_in <= 10'd0;key_in1 <= 1'b1;key_in2 <= 1'b1;#20sys_rst_n <= 1'b1;//复位#5_000_00sw_in[0] <= 1'b1;//SW0拨上#1_000_000_000key_in1 <= 1'b0;//按下按键key0#200key_in1 <= 1'b1;#200    sw_in[9:1] <= 9'b0_0000_0001;//拨码输入1hz#1_000_000_000sw_in[9:1] <= 9'b1_0001_0001;//等1s拨码输入频率#1_000_000_000sw_in[9:1] <= 9'b1_1011_0001;//等1s拨码输入频率#5000key_in2 <= 1'b0;//按下key1#200key_in2 <= 1'b1;#500_000_000key_in1 <= 1'b0;//等0.5s,按下key0#200key_in1 <= 1'b1;#1_000_000_000sw_in[9:1] <= 9'b0_0000_0000;//等1s拨码输入频率#1_000_000_000sw_in[9:1] <= 9'b0_0000_0001;//等1s拨码输入频率#1_000_000_000sw_in[0] <= 1'b0;//等1s拨码sw0拨下endalways #10 sys_clk = ~sys_clk;//时钟生成//调用模块
led led_inst
(.sys_clk   (sys_clk)  ,.sys_rst_n (sys_rst_n)  ,  .sw_in     (sw_in)  ,  .key_in1   (key_in1)  ,  .key_in2   (key_in2)  , .led_out   (led_out)   ,.ge1       (ge1)  ,.shi1      (shi1)  ,.bai1      (bai1)  ,.ge2       (ge2)  ,.shi2      (shi2)  ,.bai2      (bai2));
endmodule

这篇关于FPGA课程设计(拨码控制流水灯)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/188686

相关文章

Python实现局域网远程控制电脑

《Python实现局域网远程控制电脑》这篇文章主要为大家详细介绍了如何利用Python编写一个工具,可以实现远程控制局域网电脑关机,重启,注销等功能,感兴趣的小伙伴可以参考一下... 目录1.简介2. 运行效果3. 1.0版本相关源码服务端server.py客户端client.py4. 2.0版本相关源码1

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

控制反转 的种类

之前对控制反转的定义和解释都不是很清晰。最近翻书发现在《Pro Spring 5》(免费电子版在文章最后)有一段非常不错的解释。记录一下,有道翻译贴出来方便查看。如有请直接跳过中文,看后面的原文。 控制反转的类型 控制反转的类型您可能想知道为什么有两种类型的IoC,以及为什么这些类型被进一步划分为不同的实现。这个问题似乎没有明确的答案;当然,不同的类型提供了一定程度的灵活性,但

深入解析秒杀业务中的核心问题 —— 从并发控制到事务管理

深入解析秒杀业务中的核心问题 —— 从并发控制到事务管理 秒杀系统是应对高并发、高压力下的典型业务场景,涉及到并发控制、库存管理、事务管理等多个关键技术点。本文将深入剖析秒杀商品业务中常见的几个核心问题,包括 AOP 事务管理、同步锁机制、乐观锁、CAS 操作,以及用户限购策略。通过这些技术的结合,确保秒杀系统在高并发场景下的稳定性和一致性。 1. AOP 代理对象与事务管理 在秒杀商品

PostgreSQL中的多版本并发控制(MVCC)深入解析

引言 PostgreSQL作为一款强大的开源关系数据库管理系统,以其高性能、高可靠性和丰富的功能特性而广受欢迎。在并发控制方面,PostgreSQL采用了多版本并发控制(MVCC)机制,该机制为数据库提供了高效的数据访问和更新能力,同时保证了数据的一致性和隔离性。本文将深入解析PostgreSQL中的MVCC功能,探讨其工作原理、使用场景,并通过具体SQL示例来展示其在实际应用中的表现。 一、

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b

【电机控制】数字滤波算法(持续更新)

文章目录 前言1. 数字低通滤波 前言 各种数字滤波原理,离散化公式及代码。 1. 数字低通滤波 滤波器公式 一阶低通滤波器的输出 y [ n ] y[n] y[n] 可以通过以下公式计算得到: y [ n ] = α x [ n ] + ( 1 − α ) y [ n − 1 ] y[n] = \alpha x[n] + (1 - \alpha) y[n-1]

物联网之流水LED灯、正常流水灯、反复流水灯、移动流水灯

MENU 硬件电路设计软件程序设计正常流水LED灯反复流水LED灯移动流水LED灯 硬件电路设计 材料名称数量直插式LED1kΩ电阻杜邦线(跳线)若干面包板1 每一个LED的正极与开发板一个GPIO引脚相连,并串联一个电阻,负极接GND。 当然也可以选择只使用一个电阻。 软件程序设计 正常流水LED灯 因为要用到多个GPIO引脚,所以最好把所有的GPI

OpenStack离线Train版安装系列—3控制节点-Keystone认证服务组件

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版

OpenStack离线Train版安装系列—1控制节点-环境准备

本系列文章包含从OpenStack离线源制作到完成OpenStack安装的全部过程。 在本系列教程中使用的OpenStack的安装版本为第20个版本Train(简称T版本),2020年5月13日,OpenStack社区发布了第21个版本Ussuri(简称U版本)。 OpenStack部署系列文章 OpenStack Victoria版 安装部署系列教程 OpenStack Ussuri版