ws2812动态滚动显示图片

一.原理

  • 基本原理和静态显示一致,这里加入帧变换的概念
    在这里插入图片描述

如图所示:第一帧为红色框,显示第一个8 * 8的图像,然后向右平移,显示绿色框内的第二个8 * 8的图像…到最后显示紫色框内最后一个8 * 8的图像。可以设置帧与帧之间延时500ms,在视觉上就得到了滚动的状态

二.设计

  • 1.在静态基础上加入帧计数器
    在这里插入图片描述

  • 2.加入一个状态,在此状态计数500ms,跳转到显示下一帧
    在这里插入图片描述

  • 3.rom核中地址值的考量,(横坐标+帧数)取余32+纵坐标乘32
    在这里插入图片描述

  • 4.rom核的数据深度需要调整,不然会溢出,影响最后显示
    在这里插入图片描述

三.代码

  • ws2812_drive.v不做修改,只修改ws2812_ctrl.v
/**************************************功能介绍***********************************
Date	: 2023年8月14日14:24:59
Author	: Alegg xy.
Version : 1.0
Description: 动态显示
*********************************************************************************/
    
//---------<模块及端口声名>------------------------------------------------------
module ws2812_ctrl3( 
    input				clk		,
    input				rst_n	,
    input				ready	,

    output		[23:0]	pix_data,
    output			    pix_data_vld	
);								 
//---------<参数定义>--------------------------------------------------------- 
    localparam  IDLE = 'd0,
                DATA = 'd1,
                DONE = 'd2,
                WAIT = 'd3;
    parameter   MAX_500ms = 25'd25_000_000;
    parameter   MAX_shifting = 6'd32;
//---------<内部信号定义>-----------------------------------------------------
    reg 	[2:0]	cstate     ;//现态
    reg	    [2:0]	nstate     ;//次态
    
    reg			[5:0]	cnt_x	   	;
    wire				add_cnt_x	;
    wire				end_cnt_x	;

    reg			[5:0]	cnt_y	   	;
    wire				add_cnt_y	;
    wire				end_cnt_y	;

    reg			[24:0]	cnt_500ms	   	;
    wire				add_cnt_500ms	;
    wire				end_cnt_500ms	;

    reg			[5:0]	cnt_shift	   	;
    wire				add_cnt_shift	;
    wire				end_cnt_shift	;
    
    //计偏移量
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_shift <= 'd0;
        end 
        else if(add_cnt_shift)begin 
            if(end_cnt_shift)begin 
                cnt_shift <= 'd0;
            end
            else begin 
                cnt_shift <= cnt_shift + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_shift = cstate == DONE;
    assign end_cnt_shift = add_cnt_shift && cnt_shift == MAX_shifting - 1'd1;
    
    //500ms计数器
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_500ms <= 'd0;
        end 
        else if(add_cnt_500ms)begin 
            if(end_cnt_500ms)begin 
                cnt_500ms <= 'd0;
            end
            else begin 
                cnt_500ms <= cnt_500ms + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_500ms = cstate == WAIT;
    assign end_cnt_500ms = add_cnt_500ms && cnt_500ms == MAX_500ms - 1'd1;
    

    //rom
    wire    rom_rd_data_vld;
    wire    rom_rd_req;
    reg     rom_rd_req_r1;//打一拍
    reg     rom_rd_req_r2;//打两拍
    
    //横坐标计数器
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_x <= 'd0;
        end 
        else if(add_cnt_x)begin 
            if(end_cnt_x)begin 
                cnt_x <= 'd0;
            end
            else begin 
                cnt_x <= cnt_x + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_x = cstate == DATA;
    assign end_cnt_x = add_cnt_x && cnt_x == 7;
    
    //纵坐标计数器
    always @(posedge clk or negedge rst_n)begin 
       if(!rst_n)begin
            cnt_y <= 'd0;
        end 
        else if(add_cnt_y)begin 
            if(end_cnt_y)begin 
                cnt_y <= 'd0;
            end
            else begin 
                cnt_y <= cnt_y + 1'd1;
            end 
        end
    end 
    
    assign add_cnt_y = end_cnt_x;
    assign end_cnt_y = add_cnt_y && cnt_y == 7;
    

    //第一段:时序逻辑描述状态转移
    always @(posedge clk or negedge rst_n)begin 
        if(!rst_n)begin
            cstate <= IDLE;
        end 
        else begin 
            cstate <= nstate;
        end 
    end
    
    //第二段:组合逻辑描述状态转移规律和状态转移条件
    always @(*) begin
        case(cstate)
            IDLE:begin
                if (ready) begin
                    nstate = DATA;
                end
                else begin
                    nstate = cstate;
                end
            end
            DATA:begin
                if (end_cnt_y) begin
                    nstate = DONE;
                end
                else begin
                    nstate = cstate;
                end
            end
            DONE:begin
                if (1) begin
                    nstate = WAIT;
                end
                else begin
                    nstate = cstate;
                end
            end
            WAIT :begin
                if (end_cnt_500ms) begin
                    nstate = IDLE;
                end
                else begin
                    nstate = cstate;
                end
            end
            default : nstate = IDLE;
        endcase
    end

    //rom例化            
    rom1	rom1_inst (
	    .aclr ( ~rst_n ),
	    .address ( (cnt_x + cnt_shift) % 32 + cnt_y * 32),
	    .clock ( clk ),
	    .rden ( rom_rd_req ),
	    .q ( pix_data )
	);

    //打两拍            
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            rom_rd_req_r1 <= 'd0;
            rom_rd_req_r2 <= 'd0;
        end
        else begin
            rom_rd_req_r1 <= rom_rd_req;
            rom_rd_req_r2 <= rom_rd_req_r1;
        end
    end            
    
    assign rom_rd_req = cstate == DATA;
    assign rom_rd_data_vld = rom_rd_req_r2;
    assign pix_data_vld = rom_rd_data_vld;
    
    
endmodule
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值