diff --git a/doc/ws2812时序图.vsdx b/doc/ws2812时序图.vsdx index e36b0a0..bd1cc23 100644 Binary files a/doc/ws2812时序图.vsdx and b/doc/ws2812时序图.vsdx differ diff --git a/doc/~$$ws2812时序图.~vsdx b/doc/~$$ws2812时序图.~vsdx deleted file mode 100644 index 0a1745d..0000000 Binary files a/doc/~$$ws2812时序图.~vsdx and /dev/null differ diff --git a/rtl/ws2812_ctrl.v b/rtl/ws2812_ctrl.v new file mode 100644 index 0000000..eb140c0 --- /dev/null +++ b/rtl/ws2812_ctrl.v @@ -0,0 +1,152 @@ +module ws2812_ctrl( + input wire sys_clk , + input wire sys_rst_n , + input wire bit , + + output wire dout +); +parameter T0H = 4'd15 ,//bit0的高电平 + T0L = 6'd40 ,//bit0的低电平 + T1H = 6'd40 ,//bit1的高电平 + T1L = 6'd40 ,//bit1的低电平 + RST = 14'd15000 ;//64个led数据发完的复位信号时间,低电平0 + +reg [5: 0] cnt_0;//bit0计数寄存器 +wire add_cnt0;//bit0开始计数条件 +wire end_cnt0;//bit0结束计数条件 + +reg [6: 0] cnt_1;//bit1计数寄存器 +wire add_cnt1;//bit1开始计数条件 +wire end_cnt1;//bit1结束计数条件 + +reg [4: 0] cnt_bit;//24个bit计数寄存器 +wire add_cnt_bit;//24bit计数器开始计数条件 +wire end_cnt_bit;//24bit计数器结束计数条件 + +reg [6: 0] cnt_led;//64个led计数寄存器 +wire add_cnt_led;//64个led计数器开始计数条件 +wire end_cnt_led;//64个led计数器结束计数条件 + +reg [13: 0] cnt_rst;//复位计数寄存器 +wire add_cnt_rst;//复位计数器开始计数条件 +wire end_cnt_rst;//复位计数器结束计数条件 + +reg flag_rst;//复位信号开始寄存器 +//bit0计数器设计 +always @(posedge sys_clk or negedge sys_rst_n) begin + if(!sys_rst_n)begin + cnt_0 <= 6'd0; + end + else if(add_cnt0)begin + if(end_cnt0)begin + cnt_0 <= 6'd0; + end + else begin + cnt_0 <= cnt_0 + 1'd1; + end + end + else begin + cnt_0 <= 6'd0; + end +end +assign add_cnt0 = ~bit && flag_rst == 0;//如果bit是0,并且复位计数器没有开启,则计数器开始计数 +assign end_cnt0 = add_cnt0 && (cnt_0 == T0H + T0L-1); + +//cnt_1计数器设计 +always @(posedge sys_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + cnt_1 <= 7'd0; + end + else if(add_cnt1)begin + if(end_cnt1)begin + cnt_1 <= 7'd0; + end + else begin + cnt_1 <= cnt_1 + 1'd1; + end + end + else begin + cnt_1 <= 7'd0; + end +end +assign add_cnt1 = bit && flag_rst == 0;//如果bit是1,并且复位计数器没有开启,则计数器开始计数 +assign end_cnt1 = add_cnt1 && (cnt_1 == T1H + T1L-1); + +//cnt_bit计数器设计 +always @(posedge sys_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + cnt_bit <= 5'd0; + end + else if(add_cnt_bit)begin + if(end_cnt_bit)begin + cnt_bit <= 5'd0; + end + else begin + cnt_bit <= cnt_bit + 1'd1; + end + end + else begin + cnt_bit <= cnt_bit;//其他时刻保持cnt_bit + end +end +assign add_cnt_bit = end_cnt0 || end_cnt1;//bit0或者bit1结束计数条件成立 +assign end_cnt_bit = add_cnt_bit && (cnt_bit == 5'd23);//24个bit结束计数条件成立 + +//cnt_led计数器设计 +always @(posedge sys_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + cnt_led <= 7'd0; + end + else if(add_cnt_led)begin + if(end_cnt_led)begin + cnt_led <= 7'd0; + end + else begin + cnt_led <= cnt_led + 1'd1; + end + end + else begin + cnt_led <= cnt_led; + end +end +assign add_cnt_led = end_cnt_bit; +assign end_cnt_led = add_cnt_led && (cnt_led == 7'd63); + +//cnt_rst计数器设计 +always @(posedge sys_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + cnt_rst <= 14'd0; + end + else if(add_cnt_rst)begin + if(end_cnt_rst)begin + cnt_rst <= 14'd0; + end + else begin + cnt_rst <= cnt_rst + 1'd1; + end + end + else begin + cnt_rst <= cnt_rst; + end +end +assign add_cnt_rst = flag_rst; +assign end_cnt_rst = add_cnt_rst && (cnt_rst == RST - 1); + +//flag_rst寄存器设计 +always @(posedge sys_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + flag_rst <= 1'b0;//初始化0,复位计数器关闭 + end + else if(end_cnt_led)begin//64个led数据发送完成,复位计数器打开 + flag_rst <= 1'b1; + end + else if(end_cnt_rst)begin//复位计数器结束,复位计数器关闭 + flag_rst <= 1'b0; + end + else begin + flag_rst <= flag_rst;//其他时刻保持flag_rst + end +end +//dout输出逻辑 +assign dout = (flag_rst == 0) ? ((cnt_0 < T0H ? 1'b0 : 1'b1) | (cnt_1 < T1H ? 1'b0 : 1'b1)): 1'b0; +endmodule \ No newline at end of file