From 83f00f9ff3752db98a6c9f13256674b26bd95b7a Mon Sep 17 00:00:00 2001 From: pavel Date: Fri, 7 Aug 2026 17:46:11 +0300 Subject: [PATCH] driver WS2812b moved to the other module --- omdazz_WS2812b.qsf | 7 +- omdazz_WS2812b.v | 187 ++++++++++++++++++++++++--------------------- top.v | 15 ++++ 3 files changed, 119 insertions(+), 90 deletions(-) create mode 100644 top.v diff --git a/omdazz_WS2812b.qsf b/omdazz_WS2812b.qsf index a451a04..979fa47 100644 --- a/omdazz_WS2812b.qsf +++ b/omdazz_WS2812b.qsf @@ -61,5 +61,8 @@ set_instance_assignment -name IO_STANDARD "3.3-V LVTTL" -to WS2812 set_location_assignment PIN_23 -to CLOCK_50 set_location_assignment PIN_31 -to D_INP[4] set_location_assignment PIN_42 -to WS2812 -set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top -set_global_assignment -name CDF_FILE output_files/Chain1.cdf \ No newline at end of file +set_global_assignment -name CDF_FILE output_files/Chain1.cdf +set_global_assignment -name CDF_FILE output_files/Chain3.cdf +set_global_assignment -name CDF_FILE output_files/Chain5.cdf +set_global_assignment -name VERILOG_FILE top.v +set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top \ No newline at end of file diff --git a/omdazz_WS2812b.v b/omdazz_WS2812b.v index 7c38d63..109b884 100644 --- a/omdazz_WS2812b.v +++ b/omdazz_WS2812b.v @@ -1,100 +1,111 @@ -module omdazz_WS2812b( - input CLOCK_50, - input [4:4] D_INP, // 3 (ADCHub1), 4 (ADCHub2) - используются - output reg WS2812 // output interface to WS2812 +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 ); -parameter WS2812_NUM = 10 - 1 ; // number of WS2812 LEDs (1, counting from 0) -parameter WS2812_WIDTH = 24 ; // WS2812 data bit width -parameter CLK_FRE = 50_000_000; -parameter F_SCALE = 50 / 27; // conversion factor from 27 MHz to 50 MHz + 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 -parameter DELAY_1_HIGH = (CLK_FRE / 1_000_000 * 85 / 100 * F_SCALE) - 1; -parameter DELAY_1_LOW = (CLK_FRE / 1_000_000 * 40 / 100 * F_SCALE) - 1; -parameter DELAY_0_HIGH = (CLK_FRE / 1_000_000 * 40 / 100 * F_SCALE) - 1; -parameter DELAY_0_LOW = (CLK_FRE / 1_000_000 * 85 / 100 * F_SCALE) - 1; -parameter DELAY_RESET = (CLK_FRE / 10 * F_SCALE) - 1; + localparam RESET = 2'd0; + localparam DATA_SEND = 2'd1; + localparam BIT_SEND_HIGH = 2'd2; + localparam BIT_SEND_LOW = 2'd3; -parameter RESET = 0; // state machine declaration -parameter DATA_SEND = 1; -parameter BIT_SEND_HIGH = 2; -parameter BIT_SEND_LOW = 3; + reg [1:0] state = RESET; + reg [8:0] bit_send = 0; + reg [8:0] data_send = 0; + reg [31:0] clk_count = 0; -reg [ 1:0] state = 0; // synthesis preserve // main state machine control -reg [ 8:0] bit_send = 0; // amount of bits sent // increase it for larger LED strips/matrix -reg [ 8:0] data_send = 0; // amount of data words sent // increase it for larger LED strips/matrix -reg [31:0] clk_count = 0; // delay control -reg [23:0] WS2812_data = 24'd1; // WS2812 color data + // Формат WS2812: обычно GRB, отправка старшим битом вперёд + reg [23:0] WS2812_data = 24'h000001; -always@(posedge CLOCK_50) - case (state) - RESET:begin - WS2812 <= 0; + always @(posedge CLOCK_50) begin + case (state) - if (clk_count < DELAY_RESET) - clk_count <= clk_count + 1; - else begin - clk_count <= 0; - WS2812_data <= {WS2812_data[22:0],WS2812_data[23]};// color shifting for cyclic - state <= DATA_SEND; - end - end + RESET: begin + WS2812 <= 1'b0; - DATA_SEND: - 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// if (bit_send == WS2812_WIDTH) - data_send <= data_send + 1; - bit_send <= 0; - state <= BIT_SEND_HIGH; - end - - BIT_SEND_HIGH:begin - WS2812 <= 1; + 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 - if (WS2812_data[bit_send]) - if (clk_count < DELAY_1_HIGH) - clk_count <= clk_count + 1; - else begin - clk_count <= 0; - state <= BIT_SEND_LOW; - end - else - if (clk_count < DELAY_0_HIGH) - clk_count <= clk_count + 1; - else begin - clk_count <= 0; - state <= BIT_SEND_LOW; - 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_LOW:begin - WS2812 <= 0; + BIT_SEND_HIGH: begin + WS2812 <= 1'b1; - if (WS2812_data[bit_send]) - if (clk_count < DELAY_1_LOW) - clk_count <= clk_count + 1; - else begin - clk_count <= 0; + 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 <= bit_send + 1; - state <= DATA_SEND; - end - else - if (clk_count < DELAY_0_LOW) - clk_count <= clk_count + 1; - else begin - clk_count <= 0; - - bit_send <= bit_send + 1; - state <= DATA_SEND; - end - end - endcase -endmodule + 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 \ No newline at end of file diff --git a/top.v b/top.v new file mode 100644 index 0000000..491b265 --- /dev/null +++ b/top.v @@ -0,0 +1,15 @@ +module top( + input wire CLOCK_50, + input wire [4:4] D_INP, + output wire WS2812_OUT +); + + omdazz_WS2812b #( + .WS2812_NUM(10 - 1), + .CLK_FRE(50_000_000) + ) u_ws2812 ( + .CLOCK_50(CLOCK_50), + .WS2812 (WS2812_OUT) + ); + +endmodule \ No newline at end of file