diff options
-rw-r--r-- | neopixel.v | 83 |
1 files changed, 27 insertions, 56 deletions
@@ -41,11 +41,14 @@ module neopixel ( output reg [31:0] npout ); + // Code assumes pulse0 < pulse1 + parameter pulse0 = 8; + parameter pulse1 = 20; + // Pipeline stages: // A - generate address for config/status RAM // B - generate address for SRAM, advance staus RAM - // D - process and latch output - // E - pulse shaping + // pulse shaping (delay line for data) reg g_enable; // Global enable, latched on word boundaries @@ -53,8 +56,6 @@ module neopixel ( // 32 channels x 24 bits reg [9:0] a_ctr; reg [9:0] b_ctr; - reg [9:0] d_ctr; - reg [9:0] e_ctr; wire [9:0] a_ctr_p1 = a_ctr + 1'b1; @@ -63,8 +64,6 @@ module neopixel ( begin a_ctr <= 10'd0; b_ctr <= 10'd1; - d_ctr <= 10'd2; - e_ctr <= 10'd3; g_enable <= 1'b0; end else @@ -81,8 +80,6 @@ module neopixel ( end b_ctr <= a_ctr; - d_ctr <= b_ctr; - e_ctr <= d_ctr; end // else: !if(~rst_n) // A stage, counter fed to RAMs @@ -132,9 +129,6 @@ module neopixel ( wire [7:0] b_stat_pctr = b_stat_q[23:16]; wire [8:0] b_stat_cctr = b_stat_q[32:24]; - // Output: are we in chain reset? - reg b_in_rst; - // Channel is enabled if plen > 0 or global disable wire b_ena = |b_conf_plen & g_enable; @@ -174,63 +168,40 @@ module neopixel ( end // else: !if( ~b_ena ) end // always @ (*) - always @(negedge rst_n or posedge clk) - if (~rst_n) - b_in_rst <= 1'b1; - else - b_in_rst <= ~b_ena | b_stat_cctr[8]; + // Output: are we in chain reset? + wire b_in_rst = ~b_ena | b_stat_cctr[8]; // b_ctr[7:5] is inverted as bit order is bigendian assign ram_a = { b_stat_addr, ~b_ctr[7:5] }; - // D stage, data out from SRAM, parallel out - reg [31:0] d_in_rst; - reg [31:0] d_data; - - reg [1:0] pulse; - - always @(negedge rst_n or posedge clk) - if (~rst_n) - begin - d_in_rst <= ~32'b0; - d_data <= 32'bx; - pulse <= 2'b0; - end - else - begin - d_in_rst[d_ctr[4:0]] <= b_in_rst; - d_data[d_ctr[4:0]] <= ram_q; - pulse[0] <= (d_ctr[4:0] < 5'd8); - pulse[1] <= (d_ctr[4:0] < 5'd20); - end - - // E stage, pulse generation (all channels loaded in parallel) + // Pulse generation. We can start the pulse even before the data + // arrives from SRAM, as we will already know if we are in reset! - reg [31:0] e_in_rst; - reg [31:0] e_data; - - always @(negedge rst_n or posedge clk) - if (~rst_n) - begin - e_in_rst <= ~32'b0; - e_data <= 32'bx; - end - else if (&e_ctr[4:0]) - begin - // Parallel load of all channels - e_in_rst <= d_in_rst; - e_data <= d_data; - end + // Shift register to delay data for pulse generation + reg [pulse0-2:0] data_q; + always @(posedge clk) + data_q <= { ram_q, data_q[pulse0-2:1] }; + // Output pulse generation genvar i; generate for (i = 0; i < 32; i = i + 1) begin: gen_npout always @(negedge rst_n or posedge clk) - if (~rst_n) + if ( ~rst_n ) npout[i] <= 1'b0; else - npout[i] <= ~e_in_rst[i] & pulse[e_data[i]]; - end + begin + case ( b_ctr[4:0] ) + (i & 5'h1f): + npout[i] <= ~b_in_rst; + ((i+pulse0) & 5'h1f): + npout[i] <= npout[i] & data_q[0]; + ((i+pulse1) & 5'h1f): + npout[i] <= 1'b0; + endcase // case ( b_ctr[4:0] ) + end // else: !if( ~rst_n ) + end // block: gen_npout endgenerate + endmodule // neopixel |