Skip to content

Commit

Permalink
rtl: update to v4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
redchenjs committed Mar 13, 2021
1 parent 6aad598 commit cdee2f0
Show file tree
Hide file tree
Showing 38 changed files with 1,433 additions and 1,619 deletions.
83 changes: 37 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
WS281X Cube Controller
======================
NeoPixel LED Controller
=======================

WS281X Cube Controller based on MAX10 FPGA.
NeoPixel LED Controller based on MAX10 FPGA.

## Main Features

* 4-wire SPI interface
* High refresh rate (up to 500fps@8x8x8)
* 8 parallel output data lines (64 LEDs per line)
* Configurable waveform generator (T0H, T0L, T1H, T1L)
* Configurable LED serial connection sequence (address linked list)
* 4-wire SPI interface (SCLK, MOSI, CS, DC)
* High refresh rate (500fps@8x8x8, 125fps@16x16x16)
* 16 parallel output channels (up to 256 LEDs per channel)
* Each output channel has a programmable circular linked list
* Each output channel has a programmable waveform generator (T0H, T0L, T1H, T1L)

## Pinout

| Input Port | FPGA Pin | Output Port | FPGA Pin |
| ---------: | :------- | :--------------: | :------: |
| clk_i | PIN_J5 | ws281x_code_o[7] | PIN_R5 |
| rst_n_i | PIN_R9 | ws281x_code_o[6] | PIN_L7 |
| dc_i | PIN_P15 | ws281x_code_o[5] | PIN_P4 |
| spi_sclk_i | PIN_R14 | ws281x_code_o[4] | PIN_L6 |
| spi_mosi_i | PIN_P12 | ws281x_code_o[3] | PIN_R3 |
| spi_cs_n_i | PIN_R11 | ws281x_code_o[2] | PIN_M5 |
| - | | ws281x_code_o[1] | PIN_P3 |
| - | | ws281x_code_o[0] | PIN_M4 |
| Input Port | FPGA Pin | Output Port | FPGA Pin | Output Port | FPGA Pin |
| ---------: | :------- | :----------------: | :------: | :-----------------: | :------: |
| clk_i | PIN_J5 | neopixel_code_o[7] | PIN_R5 | neopixel_code_o[15] | PIN_C8 |
| rst_n_i | PIN_R9 | neopixel_code_o[6] | PIN_L7 | neopixel_code_o[14] | PIN_B7 |
| dc_i | PIN_P15 | neopixel_code_o[5] | PIN_P4 | neopixel_code_o[13] | PIN_D7 |
| spi_sclk_i | PIN_R14 | neopixel_code_o[4] | PIN_L6 | neopixel_code_o[12] | PIN_E7 |
| spi_mosi_i | PIN_P12 | neopixel_code_o[3] | PIN_R3 | neopixel_code_o[11] | PIN_B6 |
| spi_cs_n_i | PIN_R11 | neopixel_code_o[2] | PIN_M5 | neopixel_code_o[10] | PIN_A7 |
| - | | neopixel_code_o[1] | PIN_P3 | neopixel_code_o[9] | PIN_A5 |
| - | | neopixel_code_o[0] | PIN_M4 | neopixel_code_o[8] | PIN_B4 |

* SPI slave mode: MODE 0, CPOL=0, CPHA=0, MSB first
* SPI slave mode: F_MAX=33MHz, CPOL=0, CPHA=0, MSB first

## Commands

Expand All @@ -37,16 +37,15 @@ WS281X Cube Controller based on MAX10 FPGA.
| 2nd Param | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
| 3rd Param | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
| 4th Param | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
| 5th Param | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
| 6th Param | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |

* 1st Param: T0H time, range: 1-255, unit: 10 ns
* 2nd Param: T0L time, range: 1-255, unit: 10 ns
* 3rd Param: T1H time, range: 1-255, unit: 10 ns
* 4th Param: T1L time, range: 1-255, unit: 10 ns

Limits:

* T0H + T0L <= 257 = 2570 ns = 2.57 us
* T1H + T1L <= 257 = 2570 ns = 2.57 us
* 1st Param: T0H time (10 ns), range: 0 - 255
* 2nd Param: T0L time (10 ns), range: 0 - 255
* 3rd Param: T1H time (10 ns), range: 0 - 255
* 4th Param: T1L time (10 ns), range: 0 - 255
* 5th Param: channel length, range: 0 - 255
* 6th Param: channel count, range: 0 - 15

### ADDR_WR

Expand All @@ -57,15 +56,12 @@ Limits:
| ... | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
| Nth Param | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |

* 1st Param: 2nd LED address, range: 0-63
* 2nd Param: 3rd LED address, range: 0-63
* 3rd Param: 4th LED address, range: 0-63
* 1st Param: channel 0, the next pointer of the 1st color data, range: 0 - 255
* 2nd Param: channel 0, the next pointer of the 2nd color data, range: 0 - 255
* ...
* Nth Param: 1st LED address, range: 0-63

* N = 64
* Nth Param: ...

* These configurations will be applied to all 8 layers
* N_MAX = 256 x 16 = 4096

### DATA_WR

Expand All @@ -76,26 +72,21 @@ Limits:
| ... | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |
| Nth Param | 1 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | |

* 1st Param: 1st LED color byte 2, range: 0-255
* 2nd Param: 1st LED color byte 1, range: 0-255
* 3rd Param: 1st LED color byte 0, range: 0-255
* 4th Param: 2nd LED color byte 2, range: 0-255
* 5th Param: 2nd LED color byte 1, range: 0-255
* 6th Param: 2nd LED color byte 0, range: 0-255
* 1st Param: channel 0, the 1st color data, byte 2, range: 0 - 255
* 2nd Param: channel 0, the 1st color data, byte 1, range: 0 - 255
* 3rd Param: channel 0, the 1st color data, byte 0, range: 0 - 255
* 4th Param: channel 0, the 2nd color data, byte 2, range: 0 - 255
* ...
* Nth Param: ...

* N = 8 x 8 x 8 x 3 = 1536

* Layer data order: layer 7 first (layer 7 - layer 0)
* Color byte order: high byte first (byte 2 - byte 0)
* N_MAX = 256 x 16 x 3 = 12288

## Preparing

### Obtain the source

```
git clone https://github.com/redchenjs/ws281x_cube_controller_max10.git
git clone https://github.com/redchenjs/neopixel_led_controller_max10.git
```

### Update an existing repository
Expand Down
33 changes: 17 additions & 16 deletions ip/pll/pll.v
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// altpll
//
// Simulation Library Files(s):
//
// altera_mf
// ============================================================
// ************************************************************
// THIS IS A WIZARD-GENERATED FILE. DO NOT EDIT THIS FILE!
Expand Down Expand Up @@ -55,20 +55,20 @@ module pll (
// synopsys translate_on
`endif

wire [0:0] sub_wire2 = 1'h0;
wire [4:0] sub_wire3;
wire sub_wire5;
wire sub_wire0 = inclk0;
wire [1:0] sub_wire1 = {sub_wire2, sub_wire0};
wire [0:0] sub_wire4 = sub_wire3[0:0];
wire c0 = sub_wire4;
wire locked = sub_wire5;
wire [4:0] sub_wire0;
wire sub_wire2;
wire [0:0] sub_wire5 = 1'h0;
wire [0:0] sub_wire1 = sub_wire0[0:0];
wire c0 = sub_wire1;
wire locked = sub_wire2;
wire sub_wire3 = inclk0;
wire [1:0] sub_wire4 = {sub_wire5, sub_wire3};

altpll altpll_component (
.areset (areset),
.inclk (sub_wire1),
.clk (sub_wire3),
.locked (sub_wire5),
.inclk (sub_wire4),
.clk (sub_wire0),
.locked (sub_wire2),
.activeclock (),
.clkbad (),
.clkena ({6{1'b1}}),
Expand Down Expand Up @@ -106,7 +106,7 @@ module pll (
altpll_component.bandwidth_type = "AUTO",
altpll_component.clk0_divide_by = 3,
altpll_component.clk0_duty_cycle = 50,
altpll_component.clk0_multiply_by = 50,
altpll_component.clk0_multiply_by = 25,
altpll_component.clk0_phase_shift = "0",
altpll_component.compensate_clock = "CLK0",
altpll_component.inclk0_input_frequency = 83333,
Expand Down Expand Up @@ -183,7 +183,7 @@ endmodule
// Retrieval info: PRIVATE: DEVICE_SPEED_GRADE STRING "8"
// Retrieval info: PRIVATE: DIV_FACTOR0 NUMERIC "3"
// Retrieval info: PRIVATE: DUTY_CYCLE0 STRING "50.00000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "200.000000"
// Retrieval info: PRIVATE: EFF_OUTPUT_FREQ_VALUE0 STRING "100.000000"
// Retrieval info: PRIVATE: EXPLICIT_SWITCHOVER_COUNTER STRING "0"
// Retrieval info: PRIVATE: EXT_FEEDBACK_RADIO STRING "0"
// Retrieval info: PRIVATE: GLOCKED_COUNTER_EDIT_CHANGED STRING "1"
Expand All @@ -208,7 +208,7 @@ endmodule
// Retrieval info: PRIVATE: MIRROR_CLK0 STRING "0"
// Retrieval info: PRIVATE: MULT_FACTOR0 NUMERIC "50"
// Retrieval info: PRIVATE: NORMAL_MODE_RADIO STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "200.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ0 STRING "100.00000000"
// Retrieval info: PRIVATE: OUTPUT_FREQ_MODE0 STRING "1"
// Retrieval info: PRIVATE: OUTPUT_FREQ_UNIT0 STRING "MHz"
// Retrieval info: PRIVATE: PHASE_RECONFIG_FEATURE_ENABLED STRING "1"
Expand Down Expand Up @@ -253,7 +253,7 @@ endmodule
// Retrieval info: CONSTANT: BANDWIDTH_TYPE STRING "AUTO"
// Retrieval info: CONSTANT: CLK0_DIVIDE_BY NUMERIC "3"
// Retrieval info: CONSTANT: CLK0_DUTY_CYCLE NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "50"
// Retrieval info: CONSTANT: CLK0_MULTIPLY_BY NUMERIC "25"
// Retrieval info: CONSTANT: CLK0_PHASE_SHIFT STRING "0"
// Retrieval info: CONSTANT: COMPENSATE_CLOCK STRING "CLK0"
// Retrieval info: CONSTANT: INCLK0_INPUT_FREQUENCY NUMERIC "83333"
Expand Down Expand Up @@ -321,4 +321,5 @@ endmodule
// Retrieval info: GEN_FILE: TYPE_NORMAL pll.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL pll_bb.v FALSE
// Retrieval info: LIB_FILE: altera_mf
// Retrieval info: CBX_MODULE_PREFIX: ON
4 changes: 2 additions & 2 deletions ip/ram/ram64.qip → ip/ram/ram256.qip
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
set_global_assignment -name IP_TOOL_NAME "RAM: 2-PORT"
set_global_assignment -name IP_TOOL_VERSION "20.1"
set_global_assignment -name IP_GENERATED_DEVICE_FAMILY "{MAX 10}"
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "ram64.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "ram64_syn.v"]
set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) "ram256.v"]
set_global_assignment -name MISC_FILE [file join $::quartus(qip_path) "ram256_syn.v"]
50 changes: 25 additions & 25 deletions ip/ram/ram64.v → ip/ram/ram256.v
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// MODULE: altsyncram

// ============================================================
// File Name: ram64.v
// File Name: ram256.v
// Megafunction Name(s):
// altsyncram
//
Expand Down Expand Up @@ -37,7 +37,7 @@
// synopsys translate_off
`timescale 1 ps / 1 ps
// synopsys translate_on
module ram64 (
module ram256 (
aclr,
byteena_a,
clock,
Expand All @@ -52,9 +52,9 @@ module ram64 (
input [3:0] byteena_a;
input clock;
input [31:0] data;
input [5:0] rdaddress;
input [7:0] rdaddress;
input rden;
input [5:0] wraddress;
input [7:0] wraddress;
input wren;
output [31:0] q;
`ifndef ALTERA_RESERVED_QIS
Expand Down Expand Up @@ -105,16 +105,16 @@ module ram64 (
altsyncram_component.clock_enable_output_b = "BYPASS",
altsyncram_component.intended_device_family = "MAX 10",
altsyncram_component.lpm_type = "altsyncram",
altsyncram_component.numwords_a = 64,
altsyncram_component.numwords_b = 64,
altsyncram_component.numwords_a = 256,
altsyncram_component.numwords_b = 256,
altsyncram_component.operation_mode = "DUAL_PORT",
altsyncram_component.outdata_aclr_b = "CLEAR0",
altsyncram_component.outdata_reg_b = "UNREGISTERED",
altsyncram_component.power_up_uninitialized = "TRUE",
altsyncram_component.rdcontrol_reg_b = "CLOCK0",
altsyncram_component.read_during_write_mode_mixed_ports = "DONT_CARE",
altsyncram_component.widthad_a = 6,
altsyncram_component.widthad_b = 6,
altsyncram_component.widthad_a = 8,
altsyncram_component.widthad_b = 8,
altsyncram_component.width_a = 32,
altsyncram_component.width_b = 32,
altsyncram_component.width_byteena_a = 4;
Expand Down Expand Up @@ -155,9 +155,9 @@ endmodule
// Retrieval info: PRIVATE: JTAG_ENABLED NUMERIC "0"
// Retrieval info: PRIVATE: JTAG_ID STRING "NONE"
// Retrieval info: PRIVATE: MAXIMUM_DEPTH NUMERIC "0"
// Retrieval info: PRIVATE: MEMSIZE NUMERIC "2048"
// Retrieval info: PRIVATE: MEMSIZE NUMERIC "8192"
// Retrieval info: PRIVATE: MEM_IN_BITS NUMERIC "0"
// Retrieval info: PRIVATE: MIFfilename STRING "ram64.mif"
// Retrieval info: PRIVATE: MIFfilename STRING "ram256.mif"
// Retrieval info: PRIVATE: OPERATION_MODE NUMERIC "2"
// Retrieval info: PRIVATE: OUTDATA_ACLR_B NUMERIC "1"
// Retrieval info: PRIVATE: OUTDATA_REG_B NUMERIC "0"
Expand Down Expand Up @@ -193,16 +193,16 @@ endmodule
// Retrieval info: CONSTANT: CLOCK_ENABLE_OUTPUT_B STRING "BYPASS"
// Retrieval info: CONSTANT: INTENDED_DEVICE_FAMILY STRING "MAX 10"
// Retrieval info: CONSTANT: LPM_TYPE STRING "altsyncram"
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "64"
// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "64"
// Retrieval info: CONSTANT: NUMWORDS_A NUMERIC "256"
// Retrieval info: CONSTANT: NUMWORDS_B NUMERIC "256"
// Retrieval info: CONSTANT: OPERATION_MODE STRING "DUAL_PORT"
// Retrieval info: CONSTANT: OUTDATA_ACLR_B STRING "CLEAR0"
// Retrieval info: CONSTANT: OUTDATA_REG_B STRING "UNREGISTERED"
// Retrieval info: CONSTANT: POWER_UP_UNINITIALIZED STRING "TRUE"
// Retrieval info: CONSTANT: RDCONTROL_REG_B STRING "CLOCK0"
// Retrieval info: CONSTANT: READ_DURING_WRITE_MODE_MIXED_PORTS STRING "DONT_CARE"
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "6"
// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "6"
// Retrieval info: CONSTANT: WIDTHAD_A NUMERIC "8"
// Retrieval info: CONSTANT: WIDTHAD_B NUMERIC "8"
// Retrieval info: CONSTANT: WIDTH_A NUMERIC "32"
// Retrieval info: CONSTANT: WIDTH_B NUMERIC "32"
// Retrieval info: CONSTANT: WIDTH_BYTEENA_A NUMERIC "4"
Expand All @@ -211,24 +211,24 @@ endmodule
// Retrieval info: USED_PORT: clock 0 0 0 0 INPUT VCC "clock"
// Retrieval info: USED_PORT: data 0 0 32 0 INPUT NODEFVAL "data[31..0]"
// Retrieval info: USED_PORT: q 0 0 32 0 OUTPUT NODEFVAL "q[31..0]"
// Retrieval info: USED_PORT: rdaddress 0 0 6 0 INPUT NODEFVAL "rdaddress[5..0]"
// Retrieval info: USED_PORT: rdaddress 0 0 8 0 INPUT NODEFVAL "rdaddress[7..0]"
// Retrieval info: USED_PORT: rden 0 0 0 0 INPUT VCC "rden"
// Retrieval info: USED_PORT: wraddress 0 0 6 0 INPUT NODEFVAL "wraddress[5..0]"
// Retrieval info: USED_PORT: wraddress 0 0 8 0 INPUT NODEFVAL "wraddress[7..0]"
// Retrieval info: USED_PORT: wren 0 0 0 0 INPUT GND "wren"
// Retrieval info: CONNECT: @aclr0 0 0 0 0 aclr 0 0 0 0
// Retrieval info: CONNECT: @address_a 0 0 6 0 wraddress 0 0 6 0
// Retrieval info: CONNECT: @address_b 0 0 6 0 rdaddress 0 0 6 0
// Retrieval info: CONNECT: @address_a 0 0 8 0 wraddress 0 0 8 0
// Retrieval info: CONNECT: @address_b 0 0 8 0 rdaddress 0 0 8 0
// Retrieval info: CONNECT: @byteena_a 0 0 4 0 byteena_a 0 0 4 0
// Retrieval info: CONNECT: @clock0 0 0 0 0 clock 0 0 0 0
// Retrieval info: CONNECT: @data_a 0 0 32 0 data 0 0 32 0
// Retrieval info: CONNECT: @rden_b 0 0 0 0 rden 0 0 0 0
// Retrieval info: CONNECT: @wren_a 0 0 0 0 wren 0 0 0 0
// Retrieval info: CONNECT: q 0 0 32 0 @q_b 0 0 32 0
// Retrieval info: GEN_FILE: TYPE_NORMAL ram64.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram64.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram64.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram64.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram64_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram64_bb.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram64_syn.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram256.v TRUE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram256.inc FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram256.cmp FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram256.bsf FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram256_inst.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram256_bb.v FALSE
// Retrieval info: GEN_FILE: TYPE_NORMAL ram256_syn.v TRUE
// Retrieval info: LIB_FILE: altera_mf
Loading

0 comments on commit cdee2f0

Please sign in to comment.