WS2812B————动/静态显示

一,系统架构

在这里插入图片描述

二,芯片介绍

1.管脚说明

在这里插入图片描述

2.数据传输时间

在这里插入图片描述

3.时序波形

在这里插入图片描述

4.数据传输方法

在这里插入图片描述

5.常用电路连接

在这里插入图片描述

三,代码展示及说明

  1. 驱动模块
    在驱动模块首先选择使用状态机,其中包括,空闲状态,复位清空状态,和读数据状态,其中空闲状态是向fifo中写入数据,复位清空状态是清空ws2812b中的数据,读数据状态是讲fifo中存的数据依次读到ws2812b中,以这样的流程来达到对ws2812b的控制,以下是我的驱动代码:
/**************************************功能介绍***********************************
Date	: 
Author	: WZY.
Version	: 
Description: 这是项目的逻辑状态机模块
*********************************************************************************///---------<模块及端口声名>------------------------------------------------------
module state( input 	wire				clk		,input 	wire				rst_n	,input   wire    [23:0]      data_in ,input   wire                fifo_wr_vld,output  reg                 ws2812b_io ,output  wire                ready
);								 
//---------<参数定义>--------------------------------------------------------- //状态机参数定义parameter IDLE = 3'b001,//空闲状态RST  = 3'b010,//复位状态DATA = 3'b100;//数据传输状态    //---------<内部信号定义>-----------------------------------------------------reg 	[2:0]	cstate      ;//现态
reg	    [2:0]	nstate      ;//次态
wire            idle2rst    ;
wire            rst2data    ;
wire            data2idle   ;//fifoIP核参数定义
wire    [23:0]  fifo_wr_data;
wire    [23:0]  fifo_rd_data;
wire            empty       ;
wire            full        ;
wire            fifo_rd_req ;
wire            fifo_wr_req ;//复位参数定义
reg			[14:0]	cnt_rst	   	;
wire				add_cnt_rst	;
wire				end_cnt_rst	;//数据传输参数定义
reg			[5:0]	cnt_cyc	   	;
wire				add_cnt_cyc	;
wire				end_cnt_cyc	;reg			[4:0]	cnt_bit	   	;
wire				add_cnt_bit	;
wire				end_cnt_bit	;reg			[5:0]	cnt_num	   	;
wire				add_cnt_num	;
wire				end_cnt_num	;//****************************************************************
//                  状态机
//****************************************************************//第一段:时序逻辑描述状态转移
always @(posedge clk or negedge rst_n)begin if(!rst_n)begincstate <= IDLE;end else begin cstate <= nstate;end 
end//第二段:组合逻辑描述状态转移规律和状态转移条件
always @(*) begincase(cstate)IDLE  : beginif (idle2rst) beginnstate = RST;endelse beginnstate = cstate;endendRST   : beginif (rst2data) beginnstate = DATA;endelse beginnstate = cstate;endendDATA : beginif (data2idle) beginnstate = IDLE;endelse beginnstate = cstate;endenddefault : nstate = IDLE;endcase
end
assign idle2rst  = cstate == IDLE && fifo_wr_vld;//当检测到读使能时由空闲状态转换到复位状态
assign rst2data  = cstate == RST  && end_cnt_rst;//当复位完成后转到数据输入状态
assign data2idle = cstate == DATA && end_cnt_num;//当数据输入完成后返回空闲状态           
//第三段:描述输出,时序逻辑或组合逻辑皆可//****************************************************************
//                      IP核FIFO读取
//****************************************************************           
fifo_test	fifo_test_inst (.aclr ( ~rst_n ),.clock ( clk ),.data ( fifo_wr_data ),.rdreq ( fifo_rd_req ),.wrreq ( fifo_wr_req),.empty ( empty ),.full ( full ),.q ( fifo_rd_data ),.usedw (  ));       assign fifo_wr_data = {data_in[15:8],data_in[23:16],data_in[7:0]} ;//RGB->GRB
assign fifo_wr_req = fifo_wr_vld&&~full;//当检测到写使能并且不为满时拉高
assign fifo_rd_req = end_cnt_bit&& ~empty;//每次读取计时到一个数据后并且不为空时读出一个数据//****************************************************************
//                  复位计时
//****************************************************************    always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_rst <= 15'd0;end else if(add_cnt_rst)begin if(end_cnt_rst)begin cnt_rst <= 15'd0;endelse begin cnt_rst <= cnt_rst + 1'b1;end end
end assign add_cnt_rst = cstate == RST;
assign end_cnt_rst = add_cnt_rst && cnt_rst == 400_000/20 - 1;//****************************************************************
//                      数据传输计时
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_cyc <= 6'd0;end else if(add_cnt_cyc)begin if(end_cnt_cyc)begin cnt_cyc <= 6'd0;endelse begin cnt_cyc <= cnt_cyc + 1'b1;end end
end assign add_cnt_cyc = cstate == DATA;
assign end_cnt_cyc = add_cnt_cyc && cnt_cyc == 1200/20 - 1;always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_bit <= 5'd0;end else if(add_cnt_bit)begin if(end_cnt_bit)begin cnt_bit <= 5'd0;endelse begin cnt_bit <= cnt_bit + 1'b1;end end
end assign add_cnt_bit = end_cnt_cyc;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 24-1;always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_num <= 6'd0;end else if(add_cnt_num)begin if(end_cnt_num)begin cnt_num <= 6'd0;endelse begin cnt_num <= cnt_num + 1'b1;end end
end assign add_cnt_num = end_cnt_bit;
assign end_cnt_num = add_cnt_num && cnt_num == 64-1;
//****************************************************************
//                      用户接口
//****************************************************************always @(posedge clk or negedge rst_n) begincase (cstate)IDLE : ws2812b_io = 0;RST  : ws2812b_io = 0;DATA : beginif (fifo_rd_data[23-cnt_bit] == 1) beginws2812b_io = (cnt_cyc <30)?1:0;endelse  beginws2812b_io = (cnt_cyc<15)?1:0;endenddefault: ws2812b_io = 0;endcase
end//****************************************************************
//                      ready控制
//****************************************************************
assign ready = cstate == IDLE;
endmodule
  1. 数据传输
    接下来是数据选择传输模块,这个模块同样使用到了ip核以及状态机,通过三个状态,空闲状态,读数据状态,以及延迟状态,其中空闲状态下,等待驱动模块准备完成跳转到读数据状态,在读数据状态下根据三个计数器即横坐标,纵坐标还有偏移坐标来作为ROM的地址,依次向外读出数据,同时驱动模块向fifo中写入数据,当读取完64个数据后跳转到等待状态,延迟500ms后再次回到IDLE状态并且偏移坐标+1,以此循环就可以达到动态显示,下面是代码展示:
/**************************************************************
@File    :   ws2812_control2.v
@Time    :   2023/08/14 10:04:56
@Author  :   WangHaodong 
@EditTool:   VS Code 
@Font    :   UTF-8 
@Function:   显示一张图片
**************************************************************/
module ws2812_control(input               clk             ,input               rst_n           ,output      [23:0]  pix_data        ,output              pix_data_vld    ,input               ready                   //可以接收图像数据了
);parameter   IDLE    =   0,DATA     =   1,DELAY     =   2;reg     [2:0]   state   ;reg	[5:0] cnt_x;wire		  add_x_cnt,end_x_cnt;	reg	[4:0] cnt_y;wire		  add_y_cnt,end_y_cnt;	reg			[24:0]	cnt_delay	   	;wire				add_cnt_delay	;wire				end_cnt_delay	;reg			[5:0]	cnt_offset	   	;wire				add_cnt_offset	;wire				end_cnt_offset	;localparam	RED     =   24'hFF0000,   //红色ORANGE  =   24'hFF8000,   //橙色YELLOW  =   24'hFFFF00,   //黄色GREEN   =   24'h00FF00,   //绿色CYAN    =   24'h00FFFF,   //青色BLUE    =   24'h0000FF,   //蓝色PURPPLE =   24'h8000FF,   //紫色BLACK   =   24'h000000,   //黑色WHITE   =   24'hFFFFFF,   //白色GRAY    =   24'hC0C0C0;	  //灰色
parameter   MAX_500S =  24_999_999;wire        rom_rd_req      ;wire        rom_rd_data_vld ;reg         rom_rd_req_r1   ;reg         rom_rd_req_r2   ;/**************************************************************状态机
**************************************************************/always@(posedge clk or negedge rst_n)if(!rst_n)state <= IDLE;else case(state)IDLE		:	if(ready)state <=DATA;DATA		:	if(end_y_cnt)state <=DELAY;DELAY       :   if (end_cnt_delay) state <= IDLE;default :	state <= IDLE;endcase
//****************************************************************
//                  延时计数器
//****************************************************************always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_delay <= 'd0;end else if(add_cnt_delay)begin if(end_cnt_delay)begin cnt_delay <= 'd0;endelse begin cnt_delay <= cnt_delay + 1'b1;end endelse begincnt_delay <= 0;end
end assign add_cnt_delay = state == DELAY;
assign end_cnt_delay = add_cnt_delay && cnt_delay == MAX_500S;/**************************************************************图像数据个数计数器
**************************************************************/       
//横坐标always@(posedge clk or negedge rst_n)	if(!rst_n)								cnt_x <= 'd0;						else    if(add_x_cnt) begin				if(end_x_cnt)						cnt_x <= 'd0;  				else									cnt_x <= cnt_x + 1'b1;		end											assign add_x_cnt = state == DATA;assign end_x_cnt = add_x_cnt && cnt_x == 8 - 1;//纵坐标always@(posedge clk or negedge rst_n)	if(!rst_n)								cnt_y <= 'd0;						else    if(add_y_cnt) begin				if(end_y_cnt)						cnt_y <= 'd0;  				else									cnt_y <= cnt_y + 1'b1;		end											assign add_y_cnt = end_x_cnt;assign end_y_cnt = add_y_cnt && cnt_y == 8 - 1;//偏移量  always @(posedge clk or negedge rst_n)begin if(!rst_n)begincnt_offset <= 'd0;end else if(add_cnt_offset)begin if(end_cnt_offset)begin cnt_offset <= 'd0;endelse begin cnt_offset <= cnt_offset + 1'b1;end endend assign add_cnt_offset = end_cnt_delay;assign end_cnt_offset = add_cnt_offset && cnt_offset == 31;wire[4:0]  num_x;assign num_x = (cnt_x+cnt_offset)%32;//避免超出32的坐标限制//存放了一张图片rom	rom_inst (.aclr       ( ~rst_n ),.address    (  cnt_y*32+num_x ),.clock      ( clk ),.rden       (rom_rd_req),.q          (pix_data));assign rom_rd_req = state == DATA;always@(posedge clk or negedge rst_n)if(!rst_n) beginrom_rd_req_r1 <= 0;rom_rd_req_r2 <= 0;endelse beginrom_rd_req_r1 <= rom_rd_req;rom_rd_req_r2 <= rom_rd_req_r1;endassign rom_rd_data_vld = rom_rd_req_r2;assign pix_data_vld = rom_rd_data_vld;//打两拍使得读出数据和fifo中写入数据同步endmodule

3.仿真演示

仿真代码:

`timescale 1ns/1nsmodule state_tb();//激励信号定义 reg				 clk  	;reg				 rst_n	;
//输出信号定义	 wire                    ws2812b_io ;//时钟周期参数定义	parameter		CYCLE = 20; defparam        top_inst.ws2812_control_inst.MAX_500S = 10*CYCLE;  //模块例化top top_inst(.clk            (clk),.rst_n          (rst_n),.ws2812b_io     (ws2812b_io)
);	//产生时钟initial 		 clk = 1'b1;always #(CYCLE/2)  clk = ~ clk;//产生激励initial  begin rst_n = 1'b1;#(CYCLE*2);rst_n = 1'b0;#(CYCLE*20);rst_n = 1'b1;#(CYCLE*1000000);$stop;endendmodule 

仿真结果展示:
在这里插入图片描述

4.结果演示

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

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

相关文章

怎么把图片表格转换成word表格?几个步骤达成

在处理文档时&#xff0c;图片表格的转换是一个常见的需求。而手动输入表格是非常耗时的&#xff0c;因此&#xff0c;使用文本识别软件来自动转换图片表格可以大大提高工作效率。在本文中&#xff0c;我们将介绍如何使用OCR文字识别技术来将图片表格转换为Word表格。 OCR文字识…

15.3 【Linux】循环执行的例行性工作调度

相对于 at 是仅执行一次的工作&#xff0c;循环执行的例行性工作调度则是由 cron &#xff08;crond&#xff09; 这个系统服务来控制的。刚刚谈过 Linux 系统上面原本就有非常多的例行性工作&#xff0c;因此这个系统服务是默认启动的。另外&#xff0c; 由于使用者自己也可以…

栈和队列--受限制的线性表

目录 和队列的定义和特点 1.1栈的定义和特点、 1.2队列的定义和特点 1.3栈和队列的应用 2.栈的表示和操作的实现 2.1栈的类型定义 2.2顺序栈的表示和实现 2.2.1初始化 2.2.2入栈 2.2.3出栈 2.2.4取栈顶元素 2.3链栈的表示和实现 2.2.1初始化 2.2.2入栈 2.2.3出栈…

Java-运算符和控制语句(下)(基于c语言的补充)

输出到控制台 System.out.println(msg); // 输出一个字符串, 带换行 System.out.print(msg); // 输出一个字符串, 不带换行 System.out.printf(format, msg); // 格式化输出 从键盘输入 使用 Scanner 读取字符串/整数/浮点数 首先需要导入util包 自动导入util包 这里把回车看…

如何选择最佳的文件传输协议?(FTP、TFTP、Raysync)

在数字化时代&#xff0c;通过互联网传输文件是一项常见的任务。因此&#xff0c;选择适合您企业需求的文件传输协议非常重要。 文件传输协议是发送方和接收方之间的一套规则和信息。它的作用就像网络两端都能理解的一种语言&#xff0c;使得数据可以正确输出并带有正确的文件…

【高频面试题】JVM篇

文章目录 一、JVM组成1.什么是程序计数器2.什么是Java堆&#xff1f;3.能不能介绍一下方法区(元空间&#xff09;4.你听过直接内存吗5.什么是虚拟机栈6.垃圾回收是否涉及栈内存&#xff1f;7.栈内存分配越大越好吗&#xff1f;8.方法内的局部变量是否线程安全&#xff1f;9.什么…

NIO 非阻塞式IO

NIO Java NIO 基本介绍 Java NIO 全称 Java non-blocking IO&#xff0c;是指 JDK 提供的新 API。从 JDK1.4 开始&#xff0c;Java 提供了一系列改进的输入/输出的新特性&#xff0c;被统称为 NIO&#xff08;即 NewIO&#xff09;&#xff0c;是同步非阻塞的。NIO 相关类都被…

netty学习分享 二

操作系统IO模型与实现原理 阻塞IO 模型 应用程序调用一个IO函数&#xff0c;导致应用程序阻塞&#xff0c;等待数据准备好。如果数据没有准备好&#xff0c;一直等待….数据准备好了&#xff0c;从内核拷贝到用户空间,IO函数返回成功指示。 当调用recv()函数时&#xff0c;系…

釉面陶瓷器皿SOR/2016-175标准上架亚马逊加拿大站

亲爱的釉面陶瓷器皿和玻璃器皿制造商和卖家&#xff0c;亚马逊加拿大站将执行SOR/2016-175法规。这是一份新的法规&#xff0c;规定了含有铅和镉的釉面陶瓷器和玻璃器皿需要满足的要求。让我们一起来看一看&#xff0c;为什么要实行SOR/2016-175法规&#xff1f;这是一个保护消…

使用SpringAop切面编程通过Spel表达式实现Controller权限控制

目录 参考一、概念SpEL表达式 二、开发引入包定义注解定义切面定义用户上下文 三、测试新建Service在方法上注解新建Service在类上注解运行 参考 SpringBoot&#xff1a;SpEL让复杂权限控制变得很简单 一、概念 对于在Springboot中&#xff0c;利用自定义注解切面来实现接口…

opencv实战项目 手势识别-手势音量控制(opencv)

本项目是使用了谷歌开源的框架mediapipe&#xff0c;里面有非常多的模型提供给我们使用&#xff0c;例如面部检测&#xff0c;身体检测&#xff0c;手部检测等。 手势识别系列文章 1.opencv实现手部追踪&#xff08;定位手部关键点&#xff09; 2.opencv实战项目 实现手势跟踪…

Jay17 2023.8.12日报

8.12 今天做了2题&#xff0c;CTFshow 红包挑战8&#xff08;PHP create_function()&#xff09;和BUU [RoarCTF 2019]Easy Java&#xff08;web.xml泄露&#xff09;。 此外一直在打NepCTF&#xff0c;出了一题&#xff08;ez_java_checkin&#xff09;简单了解了java中shri…

Kafka消息队列学习(一)

文章目录 概述核心概念生产者示例同步 / 异步发送消息生产者参数配置ack-确认机制retries - 重试次数compression_type - 消息压缩类型 分区机制分区策略 消费者消息有序性提交和偏移量偏移量提交方式手动提交 高可用设计 SpringBoot集成Kafka基本使用传递对象消息 概述 核心概…

HTTP之cookie基础学习

目录 Cookie 什么是Cookie Cookie分类 Cookie版本 Cookie工作原理 Cookie详解 创建cookie cookie编码 cookie过期时间选项 Cookie流程 Cookie使用 会话管理 个性化信息 记录用户的行为 Cookie属性 domain选项 path选项 secure选项 cookie…

香港大学余涛组推出开源XLANG Agent!支持三种Agent模式

作者 |小戏、ZenMoore 一个新的未来又逐渐开始从理论走向现实走到我们身边了。 语言的意义在于使用&#xff0c;而从 ChatGPT 以来这些大规模语言模型的意义&#xff0c;也必然绝不止于 Chat&#xff0c;在四个月前&#xff0c;我们介绍了清华大学关于工具学习的综述《清华发布…

Python-OpenCV中的图像处理-图像特征

Python-OpenCV中的图像处理-图像特征 图像特征Harris角点检测亚像素级精度的角点检测Shi-Tomasi角点检测SIFT(Scale-Invariant Feature Transfrom)SURF(Speeded-Up Robust Features) 图像特征 特征理解特征检测特征描述 Harris角点检测 cv2.cornerHarris(img, blockSize, ks…

海格里斯HEGERLS四向穿梭车仓储解决方案在电子商务行业中的应用

随着现代物流&#xff0c;尤其是智能化物流的飞速发展&#xff0c;河北沃克金属制品有限公司看到了智能物流领域背后的巨大价值和市场空间&#xff0c;深知物流与供应链对企业发展的重要性。于是&#xff0c;引进了先进的高科技智能技术—HEGERLS四向穿梭车技术&#xff0c;并迅…

自制手写机器人

写字机器人模拟在画图板上写字效果 写了一套写字机器人代码&#xff0c;有多种字体可供选择&#xff0c;需要的朋友私信获取代码和软件

Spring5学习笔记— 工厂高级特性

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Spring专栏 ✨特色专栏&#xff1a; M…

创建型模式-原型模式

文章目录 一、原型模式1. 概述2. 结构3. 实现4. 案例1.5 使用场景1.6 扩展&#xff08;深克隆&#xff09; 一、原型模式 1. 概述 用一个已经创建的实例作为原型&#xff0c;通过复制该原型对象来创建一个和原型对象相同的新对象。 2. 结构 原型模式包含如下角色&#xff1a; …