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

Subversion Repositories neopixel_fpga

[/] [neopixel_fpga/] [trunk/] [rtl/] [ws2812_ctl.v] - Rev 3

Compare with Previous | Blame | View Log

/*
 *  FpgaNeoPixel - A spi to ws2812 machine
 *
 *  Copyright (C) 2020  Hirosh Dabui <hirosh@dabui.de>
 *
 *  Permission to use, copy, modify, and/or distribute this software for any
 *  purpose with or without fee is hereby granted, provided that the above
 *  copyright notice and this permission notice appear in all copies.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 */
`include "simple_spi_slave.v"
`include "ram_sync.v"
`include "ws2812_sequence.v"
 
module ws2812_ctl(clk, resetn, dout, sck,
                  mosi, miso, cs, ready);
input clk;
input resetn;
output dout;
 
input cs;
input sck;
input mosi;
output miso;
output reg ready;
 
reg [9:0] ram_addr;
reg [9:0] rx_word_counter;
reg [23:0] ram_din;
wire [23:0] ram_dout;
reg  ram_we = 0;
 
reg [23:0] din;
reg enable = 0;
wire done;
 
wire spi_done;
reg [23:0] spi_rx_data;
wire [31:0] rx_data;
 
// fifo write states
localparam SYSTEM_CLOCK_FREQ = 12_000_000;
localparam S_RESET                = 0;
localparam S_WAIT4_SPI_DATA       = 1;
localparam S_STORE_FIFO_DATA      = 2;
localparam S_PREPARE_FIFO         = 3;
 
// fifo read and burst states
localparam S_CHECK4_FIFO_DATA     = 4;
localparam S_GET_FIFO_DATA        = 5;
localparam S_BURST_WS2812_SEQ     = 6;
localparam S_SEQ_DONE             = 7;
 
reg [2:0] state = S_RESET;
 
spi_slave spi_slave_i(.resetn(resetn), .clk(clk), .sck(sck),
                      .mosi(mosi), .miso(miso), .cs(cs),
                      .done(spi_done), .rx_data(rx_data));
 
ram_sync #(.ADDRESS_LINES(1024), .DATA_WIDTH(24))
                ram_sync_i(.clk(clk), .addr(ram_addr),
                  .din(ram_din), .dout(ram_dout), .we(ram_we));
 
ws2812_sequence #(.SYSTEM_CLOCK_FREQ(SYSTEM_CLOCK_FREQ))
                ws2812_sequence_i(.clk(clk),
                  .din(din),
                  .resetn(resetn),
                  .enable(enable),
                  .dout(dout),
                  .done(done)
                );
 
always @(posedge clk)
  ready <= ~( &(~ram_addr) && state == S_WAIT4_SPI_DATA);
 
always @(posedge clk) begin
  if (~resetn) begin
    state <= S_RESET;
  end else begin
    case (state)
 
      S_RESET: begin
        enable <= 0;
        rx_word_counter <= 0;
        ram_addr <= 0;
        ram_we <= 0;
        spi_rx_data <= 0;
        state <= S_WAIT4_SPI_DATA;
      end
 
      S_WAIT4_SPI_DATA: begin
        if (spi_done) begin
          spi_rx_data <= rx_data[23:0];
          if (rx_data == 32'h dead_beaf) begin
            rx_word_counter <= ram_addr;
            ram_addr <= 0;
            state <= S_CHECK4_FIFO_DATA;
          end else begin
            state <= S_STORE_FIFO_DATA;
          end
        end else
          state <= S_WAIT4_SPI_DATA;
      end
 
      S_STORE_FIFO_DATA: begin
        ram_we <= 1;
        ram_din <= spi_rx_data;
        state <= S_PREPARE_FIFO;
      end
 
      S_PREPARE_FIFO: begin
        ram_we <= 0;
        ram_addr <= ram_addr + 1;
        state <= S_WAIT4_SPI_DATA;
      end
 
      S_CHECK4_FIFO_DATA: begin
        ram_we <= 0;
        enable <= 0;
        if (ram_addr == (rx_word_counter)) begin
          spi_rx_data <= 0;
          rx_word_counter <= 0;
          ram_addr <= 0;
          ram_we <= 0;
          state <= S_WAIT4_SPI_DATA;
        end else
          state <= S_GET_FIFO_DATA;
      end
 
      S_GET_FIFO_DATA: begin
        din <= ram_dout;
        state <= S_BURST_WS2812_SEQ;
      end
 
      S_BURST_WS2812_SEQ: begin
        enable <= 1;
        state <= S_SEQ_DONE;
      end
 
      S_SEQ_DONE: begin
          enable <= 0;
        if (done) begin
         ram_addr <= ram_addr + 1;
          state <= S_CHECK4_FIFO_DATA;
        end else
          state <= S_SEQ_DONE;
      end
 
    default: begin
        state <= S_RESET;
      end
    endcase
  end end
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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