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.

206 lines
5.3 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 sys_clk ,//系统时钟50MHz
input sys_rst_n ,//系统复位,下降沿有效
input bit ,//data_cfg给的bit
input [3: 0] opcode ,
input [3: 0] data ,
input [1: 0] dev_id ,//设备地址
output reg [4: 0] bit_num ,//bit计数寄存器
output reg [6: 0] led_num ,//led计数寄存器
output reg [1: 0] frame ,//帧
output dout//点阵输出
);
parameter T0H = 4'd13,//0高电平时间
T0L = 5'd30,//0低电平时间
T1H = 5'd30,//1高电平时间
T1L = 5'd30,//1低电平时间
RST = 26'd5_000_000;//复位时间
parameter BIT = 5'd24,
LED = 7'd64;
reg [5: 0] cnt_0;//0bit计数寄存器
wire add_cnt_0;
wire end_cnt_0;
reg [5: 0] cnt_1;//1bit计数寄存器
wire add_cnt_1;
wire end_cnt_1;
reg [25: 0] cnt_rst;//复位计数寄存器
wire add_cnt_rst;
wire end_cnt_rst;
//bit计数寄存器
wire add_bit_num;
wire end_bit_num;
//led计数寄存器
wire add_led_num;
wire end_led_num;
reg rst_flag ;//复位标志
reg start_flag ;
//开始信号
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
start_flag <= 1'b0;
end
else if((dev_id == 2'd3) && (opcode == 4'b0001))begin
start_flag <= 1'b0;
end
else if((dev_id == 2'd3) && (opcode == 4'b0010))begin
start_flag <= 1'b1;
end
else begin
start_flag <= start_flag;
end
end
//bit0计数器设计
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)begin
cnt_0 <= 6'd0;
end
else if((dev_id == 2'd3) && (opcode == 4'b0001))begin
cnt_0 <= 6'd0;
end
else if(add_cnt_0)begin
if(end_cnt_0)begin
cnt_0 <= 6'd0;
end
else begin
cnt_0 <= cnt_0 + 1'd1;
end
end
else begin
cnt_0 <= cnt_0;
end
end
assign add_cnt_0 = start_flag && ~bit && ~rst_flag;
assign end_cnt_0 = add_cnt_0 && cnt_0 == T0H + T0L - 1'd1;
//bit1计数器设计
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
cnt_1 <= 6'd0;
end
else if((dev_id == 2'd3) && (opcode == 4'b0001))begin
cnt_1 <= 6'd0;
end
else if(add_cnt_1)begin
if(end_cnt_1)begin
cnt_1 <= 6'd0;
end
else begin
cnt_1 <= cnt_1 + 1'd1;
end
end
else begin
cnt_1 <= cnt_1;
end
end
assign add_cnt_1 = start_flag && bit && ~rst_flag;
assign end_cnt_1 = add_cnt_1 && cnt_1 == T1H + T1L - 1'd1;
//bit计数器设计
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
bit_num <= 5'd0;
end
else if((dev_id == 2'd3) && (opcode == 4'b0001))begin
bit_num <= 5'd0;
end
else if(add_bit_num)begin
if(end_bit_num)begin
bit_num <= 5'd0;
end
else begin
bit_num <= bit_num + 1'd1;
end
end
else begin
bit_num <= bit_num;
end
end
assign add_bit_num = end_cnt_0 || end_cnt_1;//0bit或者1bit结束bit计数器加1
assign end_bit_num = add_bit_num && bit_num == BIT - 1'd1;
//led计数器设计
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
led_num <= 7'd0;
end
else if((dev_id == 2'd3) && (opcode == 4'b0001))begin
led_num <= 7'd0;
end
else if(add_led_num)begin
if(end_led_num)begin
led_num <= 7'd0;
end
else begin
led_num <= led_num + 1'd1;
end
end
else begin
led_num <= led_num;
end
end
assign add_led_num = end_bit_num;
assign end_led_num = add_led_num && led_num == LED - 1'd1;
//rst_flag约束
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
rst_flag <= 1'b0;
end
else if(end_led_num)begin
rst_flag <= 1'b1;
end
else if(end_cnt_rst)begin
rst_flag <= 1'b0;
end
else begin
rst_flag <= rst_flag;
end
end
//复位计数器设计
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
cnt_rst <= 26'd0;
end
else if((dev_id == 2'd3) && (opcode == 4'b0001))begin
cnt_rst <= 26'd0;
end
else if(add_cnt_rst)begin
if(end_cnt_rst)begin
cnt_rst <= 26'd0;
end
else begin
cnt_rst <= cnt_rst + 1'd1;
end
end
else begin
cnt_rst <= cnt_rst;
end
end
assign add_cnt_rst = rst_flag;
assign end_cnt_rst = add_cnt_rst && cnt_rst == RST - 1'd1;
//frame约束
always @(posedge sys_clk or negedge sys_rst_n)begin
if(!sys_rst_n)begin
frame <= 2'd0;
end
else if((dev_id == 2'd3) && (opcode == 4'b0001))begin
frame <= 2'd0;
end
else if((frame == 2'd3) && (end_cnt_rst))begin
frame <= 2'd0;
end
else if(end_cnt_rst)begin
frame <= frame + 1'd1;
end
else begin
frame <= frame;
end
end
///////////////输出///////////////
assign dout = (rst_flag == 0) ? (((bit == 0 && cnt_0 < T0H) ? 1'b1 : 1'b0) | ((bit == 1 && cnt_1 < T1H) ? 1'b1 : 1'b0)): 1'b0;
endmodule