-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathWS2812.v
156 lines (130 loc) · 2.89 KB
/
WS2812.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// synopsys translate_off
`timescale 1 ns / 100 ps
// synopsys translate_on
module WS2812(iSIGNAL_CLOCK,iDATA_CLOCK,dR, dG, dB,oCTRL_OUT, LED_IDX, ext_reset);
input iSIGNAL_CLOCK;//100 MHz clock for signal timing
input iDATA_CLOCK;//clock driven by data input
input [7:0] dR, dG, dB;
input [8:0] LED_IDX;
input ext_reset;
output oCTRL_OUT;
//the following is times specified by the ws2812b datasheet
//units are in clock periods 10ns in this case
parameter T0H = 40;
parameter T1H = 80;
parameter T0L = 85;
parameter T1L = 45;
parameter TRS = 5100;
//signal declarations
wire [23:0] wRamData;
wire [23:0] wCDATA;
wire true;
//register declarations
reg wRCLK;
reg [8:0] read_address;
reg [8:0] ledCount;
reg [12:0] signal_timer;
reg [4:0] bit_counter;
reg [23:0] srCDATA;
reg rCTRL_OUT;
reg sig_reset;
reg [6:0] TH;
reg [6:0] TE;
//assignments
assign true=1;
assign oCTRL_OUT=rCTRL_OUT;
assign wRamData={dG,dR,dB};
RAM2P ram(
.data(wRamData),
.wraddress(LED_IDX),
.wrclock(iDATA_CLOCK),
.wren(true),
.rdaddress(read_address),
.rdclock(iSIGNAL_CLOCK),
.q(wCDATA)
);
/*
not 100% sure how to do this but the idea is that the higher the number
of LEDs indexed the larger the number of LEDs the program will loop through
this should give the fastest possible write rate Should probably impliment
a reset. basicaly this needs work
*/
always @(posedge iDATA_CLOCK or posedge ext_reset) //makes it so the led count only gets updated when data is entered
begin
if (ext_reset) begin
ledCount=0;
end
else begin
if (LED_IDX+1 > ledCount && LED_IDX)
begin
ledCount <= LED_IDX+1;
end
end
end
always @(posedge iSIGNAL_CLOCK or posedge ext_reset)
begin
if (ext_reset) begin
read_address=0;
bit_counter=0;
signal_timer=0;
rCTRL_OUT=0;
sig_reset=0;
end
else begin
if (signal_timer==0 && ~sig_reset)
begin
rCTRL_OUT<=1;
end
if (~sig_reset) begin
if (srCDATA[23])
begin
TH<=T1H;
TE<=T1H+T1L;
end
else
begin
TH<=T0H;
TE<=T0H+T0L;
end
rCTRL_OUT<=(signal_timer < TH)?1:0;//toggles control line
if (signal_timer >= TE)
begin
srCDATA<=srCDATA<<1;
if (bit_counter == 11) begin//change read address here
if (read_address >= ledCount) begin
read_address<=0;
end
else begin
read_address<=read_address+1;
end
end
if (bit_counter == 23)//read from ram output here
begin
bit_counter <= 0;
srCDATA <= wCDATA;
if (read_address == 0) begin// decide if need to enter reset mode here
sig_reset <= 1;
end
end
else
begin
bit_counter<=bit_counter+1;
end
end
end
if (sig_reset && signal_timer>TRS) begin// impliment reset timer
signal_timer <= 0;
sig_reset <= 0;
srCDATA <= wCDATA;
end
else begin
if (signal_timer >= TE) begin
signal_timer <= 0;
end
else begin
signal_timer <= signal_timer+1;
end
end
end
end
endmodule