设为首页 加入收藏

TOP

基于FPGA的RGB灯WS2812B的控制器设计(一)
2023-07-23 13:25:07 】 浏览:128
Tags:基于 FPGA RGB WS2812B

这次设计一个RGB灯的控制器,该控制器具有如下特点:

  • 每个灯的颜色可调,亮灭可控
  • 可以设置参数来修改RGB的数目
     
    WS2812B的数据时序如下图所示:
     
    image
     
    image
     
    image
    (图片来源自网络、侵权删)
     
    为了方便设计我把T1H和T0L的时间值设为0.8us,为了稳定将RES设置为60us。
     
    设计的思路是,设置一个400ns的计时器,然后再设置一个计400ns次数的计时器(每计三次清零),然后1码就是前两个400us为高电平,第三个400us为低电平;0码也是同理。

一、设计的代码

1、单像素控制模块

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: GDUT
// Engineer: Lclone
// 
// Create Date: 2023/03/01 12:04:28
// Design Name: 
// Module Name: WS2812B_controller
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module WS2812B_controller(
        input        Clk,          //时钟信号
        input        Rst_n,        //复位信号
        input [23:0] Disp_Data,    //像素点的数据
        input        Data_valid,   //数据有效信号
        output reg  Send_done,    //单像素发送完成信号
        output reg   Data_out     //数据输出
    );
    
    parameter CNT_400NS = 20;   
    reg [4:0] cnt_400ns;          //40us计数器
    
    always @(posedge Clk or posedge Rst_n) begin
        if(Rst_n == 0)
            cnt_400ns <= 0;
        else if(cnt_400ns == CNT_400NS - 1)
            cnt_400ns <= 0;
        else
            cnt_400ns <= cnt_400ns + 1'b1;
    end
    
    reg [23:0] Disp_Data_reg; //数据寄存
    always @(posedge Clk or posedge Rst_n) begin
        if(Rst_n == 0)
            Disp_Data_reg <= 0;
        else if(Data_valid)
            Disp_Data_reg <= Disp_Data;
        else if(Send_done)
            Disp_Data_reg <= 0;
         else
            Disp_Data_reg <= Disp_Data_reg;
    end
    
    parameter NUM_400NS = 3;
    reg [1:0] num_400ns; //400ns段计数器,用来控制符号1和符号0的生成
    always @(posedge Clk or posedge Rst_n) begin
        if(Rst_n == 0)
            num_400ns <= 0;
        else if(num_400ns == NUM_400NS - 1 & cnt_400ns == CNT_400NS - 1)
            num_400ns <= 0;
        else if(cnt_400ns == CNT_400NS - 1)
            num_400ns <= num_400ns + 1'b1;
        else
            num_400ns <= num_400ns;
    end
    
    parameter BIT_CNT = 24;
    reg [4:0] bit_cnt; //位计数器
    always @(posedge Clk or posedge Rst_n) begin
        if(Rst_n == 0)
            bit_cnt <= 0;
        else if(bit_cnt == BIT_CNT - 1 & num_400ns == NUM_400NS - 1 & cnt_400ns == CNT_400NS - 1)
            bit_cnt <= 0;
        else if(num_400ns == NUM_400NS - 1 & cnt_400ns == CNT_400NS - 1)
            bit_cnt <= bit_cnt + 1'b1;
        else
            bit_cnt <= bit_cnt;
    end
    
    always @(posedge Clk or posedge Rst_n) begin
        if(Rst_n == 0)
            Send_done <= 0;
        else if(bit_cnt == BIT_CNT - 1 & num_400ns == NUM_400NS - 1 & cnt_400ns == CNT_400NS - 2)
            Send_done <= 1;
        else
            Send_done <= 0;
    end
    
    reg symbol_1;
    reg symbol_0;
    always @(*) begin // 这里将case = 2的情况提前到case = 0 ,是为了让模块不在工作的时候使输出为0;实际case情况串起来时也是满足要求的 
            case (num_400ns)
                0:begin
                    symbol_1 <= 0;
                    symbol_0 <= 0;
                end
                1:begin
                    symbol_1 <= 1;
                    symbol_0 <= 1;
                end
                2:begin
                    symbol_1 <= 1;
                    symbol_0 <= 0;
                end
                default:begin
                    symbol_1 <= 0;
                    symbol_0 <= 0;
                end
            endcase
    end
    
    always @(*) begin //数据传输,先传输高位
        case(bit_cnt)
            0: Data_out <= (Disp_Data_reg[23]) ?  symbol_1 : symbol_0;
            1: Data_out <= (Disp_Data_reg[22]) ?  symbol_1 : symbol_0;
            2: Data_out <= (Disp_Data_reg[21]) ?  symbol_1 : symbol_0;
            3: Data_out <= (Disp_Data_reg[20]) ?  symbol_1 : symbol_0;
            4: Data_out <= (Disp_Data_reg[19]) ?  symbol_1 : symbol_0;
            5: Data_out <= (Disp_Data_reg[18]) ?  symbol_1 : symbol_0;
            6: Data_out <= (Disp_Data_reg[17]) ?  symbol_1 : symbol_0;
            7: Data_out <= (Disp_Data_reg[16]) ?  symbol_1 : symbol_0;
            8: Data_out <= (Disp_Data_reg[15]) ?  symbol_1 : sym
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇【牛客】6 跨时钟域传输 下一篇【牛客】7 计数器&存储器&综合

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目