YAOTU INSIGHTS

ws2812动态滚动显示图片

ws2812动态滚动显示图片
文章目录一.原理二.设计三.代码注本文续前文https://blog.csdn.net/weixin_67803687/article/details/132305311?spm1001.2014.3001.5502后一.原理基本原理和静态显示一致这里加入帧变换的概念如图所示第一帧为红色框显示第一个8 * 8的图像然后向右平移显示绿色框内的第二个8 * 8的图像…到最后显示紫色框内最后一个8 * 8的图像。可以设置帧与帧之间延时500ms在视觉上就得到了滚动的状态二.设计1.在静态基础上加入帧计数器2.加入一个状态在此状态计数500ms跳转到显示下一帧3.rom核中地址值的考量横坐标帧数取余32纵坐标乘324.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 25d25_000_000; parameter MAX_shifting 6d32; //---------内部信号定义----------------------------------------------------- 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 1d1; end end end assign add_cnt_shift cstate DONE; assign end_cnt_shift add_cnt_shift cnt_shift MAX_shifting - 1d1; //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 1d1; end end end assign add_cnt_500ms cstate WAIT; assign end_cnt_500ms add_cnt_500ms cnt_500ms MAX_500ms - 1d1; //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 1d1; 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 1d1; 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本项目完整代码详见https://download.csdn.net/download/weixin_67803687/88219021?spm1001.2014.3001.5501