module ws2812_ctrl( input wire sys_clk , input wire sys_rst_n , input wire bit , output wire dout , output reg [4: 0] cnt_bit , output reg [6: 0] cnt_led , output reg [1: 0] frame ); parameter T0H = 4'd15 ,//bit0的高电平 T0L = 6'd40 ,//bit0的低电平 T1H = 6'd40 ,//bit1的高电平 T1L = 6'd40 ,//bit1的低电平 RST = 28'd50_000_000 ;//64个led数据发完的复位信号时间,低电平0 wire add_frame;//每帧开始计数条件 wire end_frame;//帧计数结束条件 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 [27: 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 <= 28'd0; end else if(add_cnt_rst)begin if(end_cnt_rst)begin cnt_rst <= 28'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 //frame计数器设计 always @(posedge sys_clk or negedge sys_rst_n)begin if(!sys_rst_n)begin frame <= 2'd0; end else if(add_frame)begin if(end_frame)begin frame <= 2'd0; end else begin frame <= frame + 1'd1; end end else begin frame <= frame; end end assign add_frame = end_cnt_rst; assign end_frame = add_frame && frame == 2'd3; //dout输出逻辑 assign dout = (flag_rst == 0) ? (((bit == 0 && cnt_0 < T0H) ? 1'b1 : 1'b0) | ((bit == 1 && cnt_1 < T1H) ? 1'b1 : 1'b0)): 1'b0; endmodule