omdazz_WS2812b/omdazz_WS2812b.v

111 lines
3.6 KiB
Verilog

module omdazz_WS2812b #(
parameter integer WS2812_NUM = 10 - 1,
parameter integer WS2812_WIDTH = 24,
parameter integer CLK_FRE = 50_000_000
)(
input wire CLOCK_50,
output reg WS2812
);
localparam integer DELAY_1_HIGH = 40 - 1; // 0.8 us @ 50 MHz
localparam integer DELAY_1_LOW = 22 - 1; // 0.45 us @ 50 MHz
localparam integer DELAY_0_HIGH = 20 - 1; // 0.4 us @ 50 MHz
localparam integer DELAY_0_LOW = 43 - 1; // 0.85 us @ 50 MHz
localparam integer DELAY_RESET = 3000 - 1; // 60 us @ 50 MHz
localparam RESET = 2'd0;
localparam DATA_SEND = 2'd1;
localparam BIT_SEND_HIGH = 2'd2;
localparam BIT_SEND_LOW = 2'd3;
reg [1:0] state = RESET;
reg [8:0] bit_send = 0;
reg [8:0] data_send = 0;
reg [31:0] clk_count = 0;
// Формат WS2812: обычно GRB, отправка старшим битом вперёд
reg [23:0] WS2812_data = 24'h000001;
always @(posedge CLOCK_50) begin
case (state)
RESET: begin
WS2812 <= 1'b0;
if (clk_count < DELAY_RESET)
clk_count <= clk_count + 1'b1;
else begin
clk_count <= 0;
// Смена цвета после передачи очередного кадра
WS2812_data <= {WS2812_data[22:0], WS2812_data[23]};
state <= DATA_SEND;
end
end
DATA_SEND: begin
if ((data_send == WS2812_NUM) &&
(bit_send == WS2812_WIDTH)) begin
data_send <= 0;
bit_send <= 0;
state <= RESET;
end
else if (bit_send < WS2812_WIDTH) begin
state <= BIT_SEND_HIGH;
end
else begin
data_send <= data_send + 1'b1;
bit_send <= 0;
state <= BIT_SEND_HIGH;
end
end
BIT_SEND_HIGH: begin
WS2812 <= 1'b1;
if (WS2812_data[WS2812_WIDTH - 1 - bit_send]) begin
if (clk_count < DELAY_1_HIGH)
clk_count <= clk_count + 1'b1;
else begin
clk_count <= 0;
state <= BIT_SEND_LOW;
end
end
else begin
if (clk_count < DELAY_0_HIGH)
clk_count <= clk_count + 1'b1;
else begin
clk_count <= 0;
state <= BIT_SEND_LOW;
end
end
end
BIT_SEND_LOW: begin
WS2812 <= 1'b0;
if (WS2812_data[WS2812_WIDTH - 1 - bit_send]) begin
if (clk_count < DELAY_1_LOW)
clk_count <= clk_count + 1'b1;
else begin
clk_count <= 0;
bit_send <= bit_send + 1'b1;
state <= DATA_SEND;
end
end
else begin
if (clk_count < DELAY_0_LOW)
clk_count <= clk_count + 1'b1;
else begin
clk_count <= 0;
bit_send <= bit_send + 1'b1;
state <= DATA_SEND;
end
end
end
default: state <= RESET;
endcase
end
endmodule