You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
4.4 KiB
Verilog

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
);
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) ? (((bit == 0 && cnt_0 < T0H) ? 1'b1 : 1'b0) | ((bit == 1 && cnt_1 < T1H) ? 1'b1 : 1'b0)): 1'b0;
endmodule