fpga项目: ws2812灯 - minichao9901/TangNano-20k-Zynq-7020 GitHub Wiki
1) ws2812灯简介
https://blog.csdn.net/zhuoqingjoking97298/article/details/120871808
2)画时序图
代码实现思路:
- 采用状态机+2个计数器作为核心
- 由start_pulse启动
- out用纯组合逻辑实现
3)代码
代码结构
代码
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/12/08 23:37:12
// Design Name:
// Module Name: ws2812_top
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ws2812_top(
input clk,
input rst,
output led
);
assign rst_n=~rst;
wire [23:0] po_data;
gen_color_data gen_color_data_inst (
.clk (clk),
.rst_n (rst_n),
.po_start_pulse (po_start_pulse),
.po_data (po_data)
);
ws2812 ws2812_inst (
.clk (clk),
.pi_start_pulse (po_start_pulse),
.rst_n (rst_n),
.pi_color (po_data),
.out (led)
);
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/12/08 22:35:15
// Design Name:
// Module Name: ws2812
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module ws2812(
input clk,
input rst_n,
input pi_start_pulse,
input [23:0] pi_color, //g[7:0],r[7:0],b[7:0]
output reg out
);
parameter FCLK=27_000_000;
parameter T0H=11; //0.4us
parameter T0L=23; //0.85us
parameter T1H=23; //0.85us
parameter T1L=11; //0.4us
parameter TRESET=1350; //50us
parameter IDLE=2'b01;
parameter DATA=2'b10;
reg [5:0] baud_cnt;
reg [4:0] bit_cnt;
reg [1:0] state;
//baud_cnt
always @(posedge clk or negedge rst_n)
if(rst_n==0)
baud_cnt<=0;
else if(pi_start_pulse)
baud_cnt<=0;
else if(baud_cnt==33)
baud_cnt<=0;
else if(state==DATA)
baud_cnt<=baud_cnt+1;
//bit_cnt
always @(posedge clk or negedge rst_n)
if(rst_n==0)
bit_cnt<=23;
else if(pi_start_pulse)
bit_cnt<=23;
else if(baud_cnt==33 && bit_cnt==0)
bit_cnt<=23;
else if(baud_cnt==33)
bit_cnt<=bit_cnt-1;
//state
always @(posedge clk or negedge rst_n)
if(rst_n==0)
state<=IDLE;
else
case(state)
IDLE: if(pi_start_pulse)
state<=DATA;
DATA: if(baud_cnt==33 && bit_cnt==0)
state<=IDLE;
endcase
//out
always @(*) begin
if(rst_n==0)
out=0;
else if(state==IDLE)
out=0;
else if(state==DATA) begin
if(pi_color[bit_cnt]==0)
out=(baud_cnt<T0H)? 1:0;
else
out=(baud_cnt<T1H)? 1:0;
end
end
endmodule
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/12/08 23:30:09
// Design Name:
// Module Name: gen_color_data
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module gen_color_data(
input clk,
input rst_n,
output reg po_start_pulse,
output reg [23:0] po_data
);
parameter FCLK=27_000_000;
parameter DLY_MS=FCLK/2; //0.5ms
parameter EVENT_MAX=7; //实际状态数是EVENT_MAX-1,看波形EVENT_MAX这个状态只出现了1个cycle
parameter RED=24'h00ff00;
parameter GREEN=24'hff0000;
parameter BLUE=24'h0000ff;
parameter CYAN=GREEN+BLUE;
parameter YELLOW=RED+GREEN;
parameter MAGENTA=RED+BLUE;
reg [24:0] timer;
reg [5:0] event_t;
reg timer_flag;
wire [5:0] event_o;
always @(posedge clk or negedge rst_n)
if(rst_n==0)
timer<=0;
else if(timer==DLY_MS-1)
timer<=0;
else
timer<=timer+1;
always @(posedge clk or negedge rst_n)
if(rst_n==0)
timer_flag<=0;
else if(timer==DLY_MS-2)
timer_flag<=1;
else
timer_flag<=0;
always @(posedge clk or negedge rst_n)
if(rst_n==0)
event_t<=1; //注意复位值是1,这样方便event_o的使用
else if(event_t==EVENT_MAX)
event_t<=1; //注意复位值是1,这样方便event_o的使用
else if(timer_flag)
event_t<=event_t+1;
assign event_o=timer_flag? event_t: 0; //generate counter-value pulse
always @(posedge clk or negedge rst_n)
if(rst_n==0) begin
po_start_pulse<=0;
po_data<=0;
end
else if(event_o)
case(event_o)
1: send_data(RED);
2: send_data(GREEN);
3: send_data(BLUE);
4: send_data(CYAN);
5: send_data(YELLOW);
6: send_data(MAGENTA);
endcase
else
po_start_pulse<=0;
task send_data;
input [23:0] datax;
begin
po_start_pulse<=1;
po_data<=datax;
end
endtask
endmodule
4) tang nano-20k引脚约束
IO_LOC "clk" 4;
IO_LOC "rst" 88;
IO_LOC "led" 79;
5) 测试波形
输出6种颜色,每种颜色间隔0.5s
6) 仿真tb
我们看到,event_o=7的状态只停留了1个cycle,就切换到了event_o=1