OpenCores
URL https://opencores.org/ocsvn/neopixel_fpga/neopixel_fpga/trunk

Subversion Repositories neopixel_fpga

[/] [neopixel_fpga/] [trunk/] [rtl/] [ws2812_sequence.v] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 splinedriv
/*
2
 *  FpgaNeoPixel - A spi to ws2812 machine
3
 *
4
 *  Copyright (C) 2020  Hirosh Dabui <hirosh@dabui.de>
5
 *
6
 *  Permission to use, copy, modify, and/or distribute this software for any
7
 *  purpose with or without fee is hereby granted, provided that the above
8
 *  copyright notice and this permission notice appear in all copies.
9
 *
10
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 *
18
 */
19
`ifndef WS2812_DATA_SEQUENCE_H
20
`define WS2812_DATA_SEQUENCE_H
21
module ws2812_sequence(clk, resetn, enable, din, dout, done);
22
  /*
23
   * e.g. 12 MHz = 83,33ns = 0.083us cycles
24
   *
25
   * 0,45 us => 450 ns
26
   *
27
   * T0H = 0,4 us = 400 ns ~ cycles * 5 = 416.65 ns
28
   * T0L = 0.85 us = 850 ns ~ cycles * 10 = 833.3 ns
29
   *
30
   * T0H + T0L = 1250 ns ~ 1249.95 ns
31
   *
32
   * T1H = 0.8us = 800 ns ~ cycles * 10 = 833.3 ns
33
   * T1L = 0.45us = 450 ns ~ cycles * 5 = 416.65 ns
34
   *
35
   * T0H + T0L = 1250 ns ~ 1249.95 ns
36
   *
37
   * RES above 50 us = 50000ns ~ cycles * 610 = 50831 ns
38
   * +/- 150 ns
39
   *
40
   * with 12 MHz = 1249.95 = +/- 0.05 ns
41
   *
42
   *  ______
43
   * | T0H  |__T0L___|
44
   *
45
   *  ______
46
   * | T1H  |__T1L___|
47
   *
48
   * |____Treset ____|
49
   *
50
   */
51
  localparam GRB_WIDTH = 24;
52
 
53
  parameter SYSTEM_CLOCK_FREQ = 12_000_000;
54
  parameter T0H_TIME = 0.4e-6; // 400 ns
55
  parameter T0L_TIME = 0.85e-6; // 850 ns
56
  localparam  CLK_HZ = $itor(SYSTEM_CLOCK_FREQ);
57
  localparam CLK_CYCLE = (1/CLK_HZ);
58
 
59
  localparam T0H_CYCLES = $rtoi((T0H_TIME)/CLK_CYCLE+0.5);//5;
60
  localparam T0L_CYCLES = $rtoi((T0L_TIME)/CLK_CYCLE+0.5);//10;
61
 
62
  localparam T1H_CYCLES = T0L_CYCLES;
63
  localparam T1L_CYCLES = T0H_CYCLES;
64
 
65
  localparam SEQUENCE_CYCLE = T0H_CYCLES + T0L_CYCLES;
66
 
67
  localparam TRESET_CYCLES = $rtoi((50e-6)/CLK_CYCLE+0.5);//610; // ~ 50us
68
 
69
  localparam CYCLE_BITS = $clog2(SEQUENCE_CYCLE);
70
 
71
  input clk;
72
  input resetn;
73
  input enable;
74
 
75
  /* |G7|...|G0|R7|...|R0|B7|..|B0| */
76
  input wire [GRB_WIDTH -1:0] din;
77
 
78
  output reg dout = 1'b0;
79
  output reg done = 1'b0;
80
 
81
  reg [GRB_WIDTH - 1:0] data_in = 0;
82
  reg [CYCLE_BITS-1:0] dout_cycle_cnt = 0;
83
  reg [$clog2(GRB_WIDTH-1):0] dout_bit_cycle_cnt = 0;
84
  reg dbit = 0;
85
 
86
 
87
  // states
88
  localparam S_RESET = 0;
89
  localparam S_IDLE = 1;
90
  localparam S_SEQUENCE_OUT = 2;
91
 
92
  localparam S_TXH_DATA_SEQUENCE = 3;
93
  localparam S_TXL_DATA_SEQUENCE = 4;
94
 
95
  reg [2:0] state = S_RESET;
96
 
97
  initial begin
98
    $display("CLK_HZ: ", CLK_HZ);
99
    $display("CLK_CYCLE: ", CLK_CYCLE);
100
    $display("T0H_CYCLES: ", T0H_CYCLES);
101
    $display("T0L_CYCLES: ", T0L_CYCLES);
102
    $display("SEQUENCE_CYCLE: ", SEQUENCE_CYCLE);
103
    $display("CYCLE_BITS: ", CYCLE_BITS);
104
    $display("$clog2(GRB_WIDTH): ", $clog2(GRB_WIDTH));
105
    $display("TRESET_CYCLES: ", TRESET_CYCLES);
106
  end
107
 
108
  always @(posedge clk) begin
109
    if (~resetn) begin
110
      done <= 0;
111
      dout <= 0;
112
      state <= S_RESET;
113
    end else begin
114
      case (state)
115
 
116
        S_RESET: begin
117
          state <= S_IDLE;
118
        end
119
 
120
        S_IDLE: begin
121
          done <= 0;
122
          dout_bit_cycle_cnt <= 0;
123
          dout_cycle_cnt <= 0;
124
          dout <= 0;
125
          if (enable) begin
126
            data_in <= din;
127
            state <= S_SEQUENCE_OUT;
128
          end else
129
            state <= S_IDLE;
130
        end
131
 
132
      S_SEQUENCE_OUT: begin
133
        dout_bit_cycle_cnt <= dout_bit_cycle_cnt + 1;
134
        if (dout_bit_cycle_cnt == GRB_WIDTH) begin
135
          done <= 1;
136
          state <= S_IDLE;
137
        end else begin
138
          dout_cycle_cnt <= 1;
139
          data_in <= {data_in[GRB_WIDTH -2: 0], 1'b0};
140
          dbit <= data_in[GRB_WIDTH -1];
141
          state <= S_TXH_DATA_SEQUENCE;
142
        end
143
      end
144
 
145
      S_TXH_DATA_SEQUENCE: begin
146
        dout_cycle_cnt <= dout_cycle_cnt + 1;
147
        if (dout_cycle_cnt < (dbit ? T1H_CYCLES[CYCLE_BITS-1:0] : T0H_CYCLES[CYCLE_BITS-1:0])) begin
148
          dout <= 1;
149
          state <= S_TXH_DATA_SEQUENCE;
150
        end
151
        else begin
152
          dout_cycle_cnt <= 1;
153
          state <= S_TXL_DATA_SEQUENCE;
154
        end
155
      end
156
 
157
      S_TXL_DATA_SEQUENCE: begin
158
        dout_cycle_cnt <= dout_cycle_cnt + 1;
159
        if ((dout_cycle_cnt < (dbit ? T1L_CYCLES[CYCLE_BITS-1:0] -1: T0L_CYCLES[CYCLE_BITS-1:0] -1))) begin
160
          dout <= 0;
161
          state <= S_TXL_DATA_SEQUENCE;
162
        end
163
        else
164
          state <= S_SEQUENCE_OUT;
165
      end
166
 
167
      // fall-through reset
168
      default: begin
169
        state <= S_RESET;
170
      end
171
    endcase
172
  end
173
end
174
 
175
endmodule
176
`endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.