【FPGA实验1】FPGA点灯工程师养成记

news2024/11/17 1:54:55

对于FPGA几个与LED相关的实验(包括按键点灯、流水灯、呼吸灯等)的记录,方便日后查看。这世界上就又多了一个FPGA点灯工程师了😏

成为一个FPGA点灯工程师分三步:

        • 一、按键点灯
          • 1、按键点灯程序
          • 2、硬件实现
        • 二、流水灯
          • 1、流水灯程序
          • 2、仿真
          • 3、硬件实现
        • 三、呼吸灯
          • 1、先“吸”
          • 2、再“呼吸”
          • 3、最后大口地呼吸

一、按键点灯

按键点灯程序比较简单,就不搞仿真了,直接上机

1、按键点灯程序
module led(input wire key_1,
		output reg led_1);
						
 always@*
  led_1=!key_1;
 

endmodule

由程序得到的RTL图:

请添加图片描述

2、硬件实现

(1)引脚分配与接线
引脚分配如下,记得引脚分配后再编译一次,不然可能没有现象。

请添加图片描述

上述引脚分配对应的接线:JX22连接到JP5,JX5连接到JP1。
为什么要这样接线可以参考《【FPGA实验2】二进制转为格雷码》中的【三、实验箱实验】➡️【3、引脚分配】。

在这里插入图片描述

(2)实验现象

具体的实验现象可观看下方的视频😏

二、流水灯

学了点状态机的内容,决定用状态机来写一下这个流水灯的代码。
感谢正点原子的视频,用了一个很好理解的例子讲了状态机是怎么样的一个东西,并总结了写状态机主要有四个步骤(也称四段论):
(1)状态空间定义(定义各个状态)
(2)状态跳转(告诉FPGA:你要跳转。让FPGA知道在什么条件下,你要从现在状态跳转到下一个状态)
(3)下个状态的判断(告诉FPGA:你要怎么跳。给FPGA一个地图,判断现在的情况是什么,然后根据地图确定下一个要跳转的状态)
(4)各个状态下的动作(我理解为状态对应信息的输出)

1、流水灯程序
module WaterLED(input wire clk,
				input wire rst_n,
				output wire [7:0]led_data);
		
		//空间状态定义
		parameter S1=8'b10000000;
		parameter S2=8'b01000000;
		parameter S3=8'b00100000;
		parameter S4=8'b00010000;
		parameter S5=8'b00001000;
		parameter S6=8'b00000100;
		parameter S7=8'b00000010;
		parameter S8=8'b00000001;
		
		reg [7:0]current_state;
		reg[7:0]next_state;
		
		//状态跳转
		always @(posedge clk or negedge rst_n) begin
			if(! rst_n)   current_state<=S1;  //复位,从状态S1开始
			else current_state<=next_state; //不是复位的情况下,到达时钟的上升沿就转到下一个状态
		end
		
		//状态判断
		always @(current_state) begin
			case(current_state) 
				S1:next_state=S2;
				S2:next_state=S3;
				S3:next_state=S4;
				S4:next_state=S5;
				S5:next_state=S6;
				S6:next_state=S7;
				S7:next_state=S8;
				default:next_state=S1;
			endcase
		end
		
	//各个状态下的动作
	assign led_data=current_state;
	
endmodule

得到的RTL图如下:
在这里插入图片描述

2、仿真

流水灯的仿真程序如下:

`timescale 1ns/100ps
module tb_WaterLED;
	reg clk_1;
	reg rst_n_1;
	wire [7:0] led_data_1;
	parameter PERIOD=10;
	
	always #(PERIOD/2) clk_1=~clk_1;

	initial begin
		clk_1=0;
		#200  $stop;
	end
	
	task task_rst;
		begin 
		rst_n_1=0;
		repeat(2) @(negedge clk_1);//两个时钟负跳变之后
		rst_n_1=1;
		end
	endtask

	WaterLED WD_1(.clk(clk_1),.rst_n(rst_n_1),.led_data(led_data_1));
	
	initial begin
	task_rst;
	$display("task_rst ok!!!");
	end
	
	
	endmodule

【如何将仿真程序加入到工程中以及如何仿真可以看上一篇《【FPGA实验0】Quartus建立工程文件以及仿真》)】

仿真结果如下:
在两个时钟下降沿之后,复位线RST置高;之后随着每一个时钟上升沿的到来,开始状态的转换。

在这里插入图片描述

3、硬件实现

在实际的硬件实现中,需要注意两个点:

(1)时钟信号
在仿真中,两个状态之间的切换是在时钟信号的上升沿,因而,每个状态保持的时间是一个时钟信号周期(在上的仿真中,一个时钟信号的周期是10ns)。而如果在实际中要实现流水灯的效果,这样的间隔太小了,由于眼睛的暂存作用,我们看懂的现象是8个LED灯一直在同时亮着,没有流水灯的效果,因而我们必须将时钟周期改得大一点。
请添加图片描述

选择实验箱最大时钟12MHz(接线的话将左侧12M对应的时钟和右侧的任意一个引脚接起来即可),定义一个计数器,计数2400000个时钟周期,一个时钟频率为12MHz,一个时钟周期为83.33ns,2400000个时钟周期就是0.2秒。

	reg [23:0] counter;	
		
	//计数器对系统时钟计数,计时0.2秒
	always @(posedge clk or negedge rst_n) begin
	 if (!rst_n)
		  counter <= 24'd0;
	 else if (counter < 24'd2400_000)  //仿真的时候可以改为 24'd0000_0010,下同
		  counter <= counter + 1'b1;
	 else
		  counter <= 24'd0;
	end

同时,状态跳变部分增加一个条件,修改为:

//状态跳转
always @(posedge clk or negedge rst_n) begin
	if(! rst_n)   current_state<=S1;  //复位,从状态S1开始
	else if (counter==24'd2400_000) current_state<=next_state; //不是复位的情况下,到达时钟的上升沿就转到下一个状态
	else   ;
end

(2)复位键如何使用

复位键一开始需要置1(打到开的位置);
之后置0(下降沿产生出发条件;同时!rst=0,状态为初始状态S1);
完成复位后置1(使此刻的状态在触发之后能跳转到下一个状态)。

整个硬件实现的程序:

module WaterLED(input wire clk,
												input wire rst_n,
												output wire [7:0]led_data);
			
		
		//空间状态定义
		parameter S1=8'b10000000;
		parameter S2=8'b01000000;
		parameter S3=8'b00100000;
		parameter S4=8'b00010000;
		parameter S5=8'b00001000;
		parameter S6=8'b00000100;
		parameter S7=8'b00000010;
		parameter S8=8'b00000001;

		
		reg [7:0]current_state;
		reg[7:0]next_state;
		reg [23:0] counter;
		
	//计数器对系统时钟计数,计时0.2秒
		always @(posedge clk or negedge rst_n) begin
		 if (!rst_n)
			  counter <= 24'd0;
		 else if (counter < 24'd2400_000)  //仿真的时候可以改为 24'd0000_0010,下同
			  counter <= counter + 1'b1;
		 else
			  counter <= 24'd0;
		end
		
		//状态跳转
		always @(posedge clk or negedge rst_n) begin
			if(! rst_n)   current_state<=S1;  //复位,从状态S1开始
			else if (counter==24'd2400_000) current_state<=next_state; //不是复位的情况下,到达时钟的上升沿就转到下一个状态
			else   ;
		end
		
		//状态判断
		always @(current_state) begin
			case(current_state) 
				S1:next_state=S2;
				S2:next_state=S3;
				S3:next_state=S4;
				S4:next_state=S5;
				S5:next_state=S6;
				S6:next_state=S7;
				S7:next_state=S8;
				default:next_state=S1;
			endcase
		end
		
		//各个状态下的动作
	assign led_data=~current_state;//灯为0时亮起,为1时变暗
	
	
endmodule

对应的RTL图:
请添加图片描述

引脚分配与接线:
请添加图片描述

按之前的接线即可,key8为复位键。

上述引脚分配对应的接线:JX22连接到JP5,JX5连接到JP1。
为什么要这样接线可以参考《【FPGA实验2】二进制转为格雷码》中的【三、实验箱实验】➡️【3、引脚分配】。

时钟引脚:左侧的12M时钟引脚接到右侧任意一个引脚即可。总的接线图如下:

在这里插入图片描述

具体现象可以看文末的视频😏

三、呼吸灯

呼吸灯,就是灯的亮度由暗变亮再由亮变暗,像人的呼吸一样。

1、先“吸”

(1)代码

module PWM(           
			input wire clk,
			output wire[9:0] pwma,
			output wire pwmb);

	reg [3:0]counter1=0,counter2=0;
	reg [9:0]pwm_1=10'b0000_0000_00;
	reg[0:0] pwm_2;
	
	always@(posedge clk) begin

			if(counter2==4'd9)  begin
			
					if(counter1==4'd9)  begin
						counter1=0;
						pwm_1=10'b0000_0000_00;					
						end
					else  counter1=counter1+1;							
					pwm_1[counter1]=1;
					counter2=0;
				end
				
			else counter2=counter2+1;
			pwm_2=pwm_1[counter2];
	end
	
	assign pwma=pwm_1;
	assign pwmb=pwm_2;
		
endmodule

(2)仿真文件:

`timescale 1ns/100ps
module tb_PWM;
	
	reg clk;
	wire [9:0]pwma;
	wire [0:0]pwmb;
	parameter PERIOD=10;
	
	always #(PERIOD/2) clk=~clk;
	
	initial begin
		clk=0;
		# 3000 $stop;
		end
		
PWM PWM_1(.clk(clk),.pwma(pwma), .pwmb(pwmb));

endmodule

(3)仿真结果:
在这里插入图片描述

2、再“呼吸”

(1)代码

module PWM(
						input wire clk,
						output wire[9:0] pwma,
						output wire pwmb);

	reg [4:0]counter1=0;
	reg [3:0]counter2=0;
	reg [9:0]pwm_1=10'b0000_0000_00;
	reg[0:0] pwm_2;
	
	always@(posedge clk) begin

			if(counter2==4'd9)  begin
		
					if(counter1==5'd17)   counter1=0;
					else  counter1=counter1+1;	
					$display("counter1:   ",counter1);
					
					case(counter1)
						5'd0  : pwm_1=10'b0000_0000_01;
						5'd1  : pwm_1=10'b0000_0000_11;
						5'd2  : pwm_1=10'b0000_0001_11;
						5'd3  : pwm_1=10'b0000_0011_11;
						5'd4  : pwm_1=10'b0000_0111_11;
						5'd5  : pwm_1=10'b0000_1111_11;
						5'd6  : pwm_1=10'b0001_1111_11;
						5'd7  : pwm_1=10'b0011_1111_11;
						5'd8  : pwm_1=10'b0111_1111_11;
						5'd9  : pwm_1=10'b1111_1111_11;
						5'd10  : pwm_1=10'b0111_1111_11;
						5'd11  : pwm_1=10'b0011_1111_11;
						5'd12  : pwm_1=10'b0001_1111_11;
						5'd13  : pwm_1=10'b0000_1111_11;
						5'd14  : pwm_1=10'b0000_0111_11;
						5'd15  : pwm_1=10'b0000_0011_11;
						5'd16  : pwm_1=10'b0000_0001_11;
						5'd17  : pwm_1=10'b0000_0000_11;
					endcase
					$display("pwm_1:  ",pwm_1);
					counter2=0;
				end
				
			else counter2=counter2+1;
			pwm_2=pwm_1[counter2];
	end
	
	assign pwma=pwm_1;
	assign pwmb=pwm_2;
		
endmodule

(2)tb文件:

`timescale 1ns/100ps
module tb_PWM;
	
	reg clk;
	wire [9:0]pwma;
	wire [0:0]pwmb;
	parameter PERIOD=10;
	
	always #(PERIOD/2) clk=~clk;
	
	initial begin
		clk=0;
		# 3000 $stop;
		end
		
PWM PWM_1(.clk(clk),.pwma(pwma), .pwmb(pwmb));


endmodule

(3)仿真结果:

在这里插入图片描述

3、最后大口地呼吸

呼吸灯的硬件实现,和流水灯的硬件实现一样原理,如果每个亮度的时间跟仿真的时候一样的话,那我们是看不出亮度变化,所以在硬件实现的时候需要在每一个亮度延长一定的时间。具体的实现如下:

(1)代码:

module PWM(
						input wire clk,
						output wire led0,
						output wire led1,
						output wire led2,
						output wire led3,
						output wire led4,
						output wire led5,
						output wire led6,
						output wire led7
						);


	reg [4:0]counter1=0;
	reg [3:0]counter2=0;
	reg [9:0]pwm_1=10'b0000_0000_00;
	reg[0:0] pwm_2;
	reg [20:0] cnt_base;
	parameter T_6ms = 21'd2000_000;

 


	always @(posedge clk ) begin
		if(cnt_base < T_6ms - 1'b1)begin
			cnt_base <= cnt_base + 1'b1;
			pwm_2<=pwm_1[cnt_base%10];
		end
		
		else begin
			cnt_base <= 21'd0;
			if(counter1==5'd17)   counter1=0;
			else  counter1=counter1+1;	
			
			case(counter1)
				5'd0  : pwm_1=10'b0000_0000_01;
				5'd1  : pwm_1=10'b0000_0000_11;
				5'd2  : pwm_1=10'b0000_0001_11;
				5'd3  : pwm_1=10'b0000_0011_11;
				5'd4  : pwm_1=10'b0000_0111_11;
				5'd5  : pwm_1=10'b0000_1111_11;
				5'd6  : pwm_1=10'b0001_1111_11;
				5'd7  : pwm_1=10'b0011_1111_11;
				5'd8  : pwm_1=10'b0111_1111_11;
				5'd9  : pwm_1=10'b1111_1111_11;
				5'd10  : pwm_1=10'b0111_1111_11;
				5'd11  : pwm_1=10'b0011_1111_11;
				5'd12  : pwm_1=10'b0001_1111_11;
				5'd13  : pwm_1=10'b0000_1111_11;
				5'd14  : pwm_1=10'b0000_0111_11;
				5'd15  : pwm_1=10'b0000_0011_11;
				5'd16  : pwm_1=10'b0000_0001_11;
				5'd17  : pwm_1=10'b0000_0000_11;
			endcase
		end

	 end
	 
	 	assign led0=pwm_2;
		assign led1=pwm_2;
		assign led2=pwm_2;
		assign led3=pwm_2;
		assign led4=pwm_2;
		assign led5=pwm_2;
		assign led6=pwm_2;
		assign led7=pwm_2;
		
endmodule
		

(2)对应的RTL图:
请添加图片描述
(3)引脚分配与接线
请添加图片描述
接线同上流水灯的接线。

(4)实验现象:
具体实验现象可以看文末😏

FPGA点灯工程师养成记

Forever young,always tearful. 😏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419892.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue2-黑马(二)

目录&#xff1a; &#xff08;1&#xff09;vue2-基础-属性绑定 &#xff08;2&#xff09;vue2-事件绑定 &#xff08;3&#xff09;vue2-双向绑定 &#xff08;4&#xff09;vue2-计算属性 &#xff08;1&#xff09;vue2-基础-属性绑定 属性与js数据绑定&#xff1a; …

react-router原理

前端路由的原理 自己来监听URL的改变&#xff0c;改变url&#xff0c;渲染不同的组件(页面)&#xff0c;但是页面不要进行强制刷新&#xff08;a元素不行&#xff09;。 hash模式&#xff0c;localhost:3000/#/abc 优势就是兼容性更好&#xff0c;在老版IE中都可以运行缺点是…

DNS配置

TCP/IP提供了通过IP地址来连接到设备的功能&#xff0c;但对用户来讲&#xff0c;记住某台设备的IP地址是相当困难的&#xff0c;因此专门设计了一种字符串形式的主机命名机制&#xff0c;这些主机名与IP地址相对应。 在IP地址与主机名之间需要有一种转换和查询机制&#xff0c…

CANopen | 对象字典OD 06 - 创建对象字典变量,通过TPDO定时发送

文章目录一、前言二、实验目的三、对象字典OD四、TPDO1定时发送tx_Value变量一、前言 该笔记的程序: github 二、实验目的 CANopen从站有一个变量tx_Value&#xff0c;映射到TPDO1上。接着&#xff0c;CANopen从站每1S发送一次TPDO1&#xff0c;将tx_Value发送出去。 三、…

PasteSpider之文件同步软件的介绍

作为PasteSpider系统中的一大特色&#xff0c;那就是文件的差量同步和配置同步。能够实现对不同需求的良好实现。 在网站https://www.pastecode.cn/下载文件同步软件后&#xff0c;完全解压到自己的文件夹内&#xff0c;然后双击“SpiderSyncFile”,如下图&#xff1a; 打开登陆…

Nginx模板自动化

背景 在日常工作中&#xff0c;我们经常需要创建Nginx配置文件的模板&#xff0c;以便在不同的环境中快速部署和配置Nginx服务器。然而&#xff0c;这样的任务通常需要重复性高、耗时长&#xff0c;且容易出错。为了加快这些任务的完成&#xff0c;并提高工作效率&#xff0c;…

C/C++开发,认识opencv各模块

目录 一、opencv模块总述 二、opencv主要模块 2.1 opencv安装路径及内容 2.2 opencv模块头文件说明 2.3 成熟OpenCV主要模块 2.4 社区支持的opencv_contrib扩展主要模块 2.5 关于库文件的引用 一、opencv模块总述 opencv的主要能力在于图像处理&#xff0c;尤其是针对二维图…

字节8年测试经验,送给想要学习自动化测试的同学6条建议

我的职业生涯开始和大多数测试人一样&#xff0c;开始接触都是纯功能界面测试。那时候在一家电商公司做测试&#xff0c;做了有一段时间&#xff0c;熟悉产品的业务流程以及熟练测试工作流程规范之后&#xff0c;效率提高了&#xff0c;工作比较轻松&#xff0c;也得到了更好的…

QML控件--Dial

文章目录一、控件基本信息二、控件使用三、属性成员四、成员函数五、信号一、控件基本信息 Import Statement&#xff1a;import QtQuick.Controls 2.14 Since&#xff1a;Qt 5.7 Inherits&#xff1a;Control 二、控件使用 Dial&#xff1a;是一个旋钮控件&#xff1b; im…

【权限维持】黄金白银票据隐藏账户C2远控RustDeskGotoHTTP

文章目录内网域&单机版-权限维持-基于用户-隐藏用户内网域-权限维持-基于服务TGT-黄金白银票据黄金方法&#xff1a;白银方法&#xff1a;内网域-权限维持-基于软件-GotoHTTP&RustDesk—无需安装C2 GotoHTTPC2 RustDesk 推荐内网域&单机版-权限维持-基于用户-隐藏用…

Plist文件是什么?

plist 文件是一种用于存储应用程序配置信息的文件格式&#xff0c;其中包含应用程序的各种设置和数据。在过去&#xff0c;plist 文件通常是以.plist 格式存储的。然而&#xff0c;随着时间的推移&#xff0c;人们开始使用.plistx 格式来存储更复杂的数据结构和数据。如果您需要…

MySQL日期时间函数汇总、时间格式转换方法

MySQL日期时间函数汇总、时间格式转换方法时间函数日期时间格式转换date_format函数EXTRACT()DATE_ADD()DATE_SUB()DATEDIFF函数时间函数 函数描述NOW()返回当前的日期和时间CURDATE()返回当前的日期CURTIME()返回当前的时间DATE()返回日期或日期/时间表达式的日期部分HOUR()获…

【遗传算法、粒子群、改进遗传算法】基于智能算法的电力系统电网最优规划方案的研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【从零开始学Skynet】工具篇(一):Ubuntu16.04环境搭建

一、Ubuntu系统下载 为了初学者使用方便&#xff0c;我们下载的是Ubuntu16系统的桌面版本&#xff1a;下载地址 二、VirtualBox虚拟机下载 去Virtualbox官网下载:Downloads – Oracle VM VirtualBox 点击这里进行下载&#xff0c;下载完之后点击客户端进行安装&#xff0c;安装…

ros2-foxy windows下安装流程

1.系统要求 本手册安装环境为win10 x64 请确保已在系统路径中安装PowerShell。 请确保网络的通畅性 2.环境安装部分 安装Chocolatey 方案1&#xff1a; 复制以下命令行&#xff0c;使用管理员权限打开PowerShell&#xff0c;复制粘贴大法到PowerShell&#xff0c;安装好ch…

YC-A11(原创)基于springboot,vue网上商城

绪论 课题的开发背景 随着计算机和网络的快速发展&#xff0c;并且越来越普及&#xff0c;互联网日益成为人们收集信息常用渠道&#xff0c;电子商务开始流行&#xff0c;一种全新的理念不断形成并且快速发展&#xff0c;像国内电商巨头淘宝、京东、苏宁易购、唯品会等电商平台…

筑牢合规营销“防火墙”,助力四环医药实现合规营销管理能力全面进阶 | 案例研究

四环医药控股集团有限公司&#xff08;以下简称“四环医药”&#xff09;是一家集药品研发、生产和销售于一体的集团化医药企业&#xff0c;公司现拥有心脑血管疾病、肝病治疗、提高机体免疫机能、代谢及抗感染等多领域100品种。四环医药强大的营销体系及独特营销模式确保了自身…

会画画的海龟,Python Turtle库详解(27)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 欢迎和猫妹一起&#xff0c;趣味学Python。 今日主题 介绍下Python的turtle库&#xff0c;这是一个可以画画的库&#xff0c;非常适合小孩子在屏幕上画画。 先学习基础知…

Python入门教程+项目实战-9.4节: 字符串的格式化

目录 9.4.1 理解格式化 9.4.2 使用f-string进行格式化 9.4.3 使用格式化符号进行格式化 9.4.4 使用format方法进行格式化 9.4.5 知识要点 9.4.6 系统学习python 9.4.1 理解格式化 同学们比较熟悉的是磁盘格式化&#xff0c;将磁盘格式化以后&#xff0c;磁盘中的文件全部…

第10章_多线程

第10章_多线程 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 我们之前学习的程序在没有跳转语句的情况下&#xff0c;都是由上至下沿着一条路径依次执行。现在想要设计一个程序…