FPGA实现ws2812b显示

WS2812B-LED工作时序如下:
数据的0/1用不同占空比的pwm表示
在这里插入图片描述
0码和1码以及复位时间如上图所示。
在这里插入图片描述
RGB888总共24位,每位0/1输出,一个88led灯,一个总周期需要连续发64个24位数据,再复位一段时间重新下一个轮回。
在这里插入图片描述
数据高位先发,本程序为0为最先发的23为最后发的。
在这里插入图片描述
设计思路:
ws2812b led灯工作前需要复位,所以我们设置一个状态RESET来进行复位操作,拉低dq_out300us,然后设置一个发送数据状态WR_BIT,我们需要发送64
24bit的数据在一个周期里面,每24bit代表一个灯的颜色状态,所以我们定义两个计数器
一个记录bit发送数量:bit_cnt
一个记录发送的24bit的个数:rbg_data
具体代码如下:

/*================================================
Filename           : ws2812b
AutDATAor             : xq
Description        : ws2812b模块驱动
Date               : 2023年8月11日09:50:48
Email              : 1617784441@qq.com
Company            :
================================================*/
module ws2812b_ctrl(
   input                       sys_clk     , //时钟信号 50MDATAz
   input                       sys_rst_n   , //复位信号,低有效

   output       reg            dq_out//
);
//参数定义
parameter IDLE      = 2'd0       ;
parameter RESET     = 2'd1       ;
parameter WR_BIT    = 2'd2       ;
parameter BIT_MAX   = 5'd23     ;
parameter TIME_1S = 26'd4999_9999;
parameter RESET_MAX = 14'd14_999 ;//300US

parameter GREEN       = 24'b00000000_00000000_01010000 ;
parameter RED         = 24'b01010000_00000000_00000000 ;
parameter WHITE       = 24'hFFFFFF ;
parameter LIGHT_CORAL = 24'h30D5C8;
parameter SEASHELL    = 24'h7AB8CC;
parameter COFFEE      = 24'h4D3900 ;


parameter H = 64'b1100001111000011110000111111111111111111110000111100001111000011;
parameter A = 64'b0000000000000000000110000011110001100110111111111100001111000011;
parameter B = 64'b0000000011111111100000011000000111111111100000011000000111111111;
parameter C = 64'b0000000001111110110000111100000011000000110000110111111000000000;
parameter D = 64'b0000000011111110110000111100001111000011110000111111111000000000;
parameter E = 64'b0000000011111111110000001100000011111111110000001100000011111111;
parameter F = 64'b0000000011111111110000001100000011111111110000001100000011000000;
//信号定义
reg [25:0] cnt_1s;
wire [63:0] DATA;
reg [6:0]  cnt_max;
reg [13:0] cnt_num ;
reg [6:0]  rgb_led ;
reg [4:0 ] bit_cnt ;
reg [1:0]  state_c ;
reg [1:0]  state_n ;
reg [2:0]  cnt_data;
reg [23:0]  color_data;
reg [7:0]  address;
//逻辑组成
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        cnt_1s <= 26'd0;
    end
    else if(cnt_1s==TIME_1S)begin
        cnt_1s <= 26'd0;
    end
    else begin
        cnt_1s <= cnt_1s + 1'd1;
    end
end
ram_256x8	ram_256x8_inst (
	.aclr ( ~sys_rst_n ),
	.address ( address ),
	.clock ( sys_clk ),
	.data (  ),
	.rden ( 1'b1 ),
	.wren ( 1'b0 ),
	.q ( DATA )
	);
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        address <= 8'd0;
    end
    else if(cnt_1s==TIME_1S&&address==59)begin
        address <= 8'd0;
    end
    else if(cnt_1s==TIME_1S)begin
        address <= address+1'b1;
    end
    else begin
        address <= address;
    end
end
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        cnt_data <= 3'd0;
    end
    else if(cnt_1s==TIME_1S&&cnt_data==5)begin
        cnt_data <= 3'd0;
    end
    else if(cnt_1s==TIME_1S)begin
        cnt_data <= cnt_data+1'd1;
    end
    else begin
        cnt_data <= cnt_data;
    end
end
always @(*) begin
    if(!sys_rst_n)begin
        color_data=24'd0;
    end
    else begin
        case (cnt_data)
            0:begin color_data=GREEN      ;end
            1:begin color_data=RED        ;end
            2:begin color_data=WHITE      ;end
            3:begin color_data=LIGHT_CORAL;end
            4:begin color_data=SEASHELL   ;end
            5:begin color_data=COFFEE     ;end
            default: ;
        endcase
    end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        state_c <= IDLE;
    end
    else begin
        state_c <= state_n;
    end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        cnt_max <= 7'd0;
    end
    else if(color_data[bit_cnt]==1&&DATA[rgb_led])begin
        cnt_max <= 7'd74;
    end
    else if(color_data[bit_cnt]==0&&DATA[rgb_led])begin
        cnt_max <= 7'd49;
    end
    else if(DATA[rgb_led]==0)begin
        cnt_max <= 7'd49;
    end
    else begin
        cnt_max <= 7'd0;
    end
end

always @(*) begin
    case (state_c)
        IDLE:begin
            state_n = RESET;
        end 
        RESET:begin
            if(cnt_num==RESET_MAX)begin
                state_n = WR_BIT;
            end
            else begin
                state_n = RESET;
            end
        end
        WR_BIT:begin
            if(rgb_led==7'd63&&bit_cnt==BIT_MAX&&cnt_num==cnt_max)begin
                state_n = IDLE;
            end
            else begin
                state_n = WR_BIT;
            end
        end
        default: state_n = IDLE;
    endcase
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        cnt_num <= 14'd0;
    end
    else if(state_c==RESET&&cnt_num==RESET_MAX)begin
        cnt_num <= 14'd0;
    end
    else if(state_c==WR_BIT&&cnt_num==cnt_max)begin
        cnt_num <= 14'd0;
    end
    else if(state_c==RESET||state_c==WR_BIT)begin
        cnt_num <=cnt_num+1'd1;
    end
    else begin
        cnt_num <= 14'd0;
    end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        bit_cnt <= 5'd0;
    end
    else if(state_c==WR_BIT&&bit_cnt==BIT_MAX&&cnt_num==cnt_max)begin
        bit_cnt <= 5'd0;
    end
    else if(state_c==WR_BIT&&cnt_num==cnt_max)begin
        bit_cnt <= bit_cnt + 1'd1;
    end
    else begin
        bit_cnt <= bit_cnt;
    end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        rgb_led <= 7'd0;
    end
    else if(state_c==WR_BIT&&bit_cnt==BIT_MAX&&cnt_num==cnt_max&&rgb_led==7'd63)begin
        rgb_led <= 7'd0;
    end
    else if(state_c==WR_BIT&&bit_cnt==BIT_MAX&&cnt_num==cnt_max)begin
        rgb_led <= rgb_led + 1'd1;
    end
    else begin
        rgb_led <= rgb_led;
    end
end


always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        dq_out <= 1'b0;
    end
    case (state_c)
        IDLE  :begin dq_out<=1'b0;end
        RESET :begin dq_out<=1'b0;end
        WR_BIT:begin
        if(color_data[bit_cnt]==1&&DATA[rgb_led])begin
            if(cnt_num<38)begin
                dq_out <= 1'b1;
            end
            else begin
                dq_out <= 1'b0;
            end
        end
        else if(color_data[bit_cnt]==0&&DATA[rgb_led])begin
            if(cnt_num<15)begin
                dq_out <= 1'b1;
            end
            else begin
                dq_out <= 1'b0;
            end
        end
        else if(DATA[rgb_led]==0)begin
            if(cnt_num<15)begin
                dq_out <= 1'b1;
            end
            else begin
                dq_out <= 1'b0;
            end
        end
        end
        default: dq_out <= 1'b0;
    endcase
end

endmodule

ram是256x64规模的ram,存的64位宽数据上的每一位都可以决定一个LED的两灭 例如data[0]=1则 第一个led灯亮 若data[0]=0则 led灯灭
也可以不要ram 稍微修改一下就好了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值