| `default_nettype none | |
| module ArrayOrReduction #( | |
| parameter SIZE = 16, WIDTH=32) ( | |
| // Flattened array | |
| input wire [(SIZE*WIDTH)-1:0] inputs, | |
| output wire [WIDTH-1:0] result | |
| ); | |
| // One option is to modify the code to use the flattened array, but probably | |
| // an easier option is to just insert a generate block to unflatten | |
| // everything. | |
| wire [WIDTH-1:0] __inputs[SIZE-1:0]; | |
| genvar index; | |
| generate | |
| for(index = 0; index < SIZE; index = index + 32'd1) begin : unflatten | |
| localparam START_BIT = index * WIDTH; | |
| assign __inputs[index] = inputs[START_BIT + WIDTH - 1:START_BIT]; | |
| end | |
| endgenerate | |
| // Recursively generate a pair-wise reduction | |
| generate | |
| if(SIZE <= 0) begin : error_case | |
| DoesNotExit foo(); | |
| end else if (SIZE == 1) begin : base_case_1 | |
| assign result = __inputs[0]; | |
| end else if(SIZE == 2) begin : base_case_2 | |
| assign result = __inputs[0] | __inputs[1]; | |
| end else begin : recursive_case | |
| wire [WIDTH-1:0] subResults [1:0]; | |
| // The array needs to be re-flattened here or alternatively, just use computation on the original array | |
| ArrayOrReduction #(.WIDTH(WIDTH), .SIZE(SIZE/2)) top(.inputs(inputs[(SIZE*WIDTH)-1:(SIZE*WIDTH)/2]), .result(subResults[1])); | |
| ArrayOrReduction #(.WIDTH(WIDTH), .SIZE(SIZE/2)) bot(.inputs(inputs[(SIZE * WIDTH)/2-1:0]), .result(subResults[0])); | |
| assign result = subResults[0] | subResults[1]; | |
| end | |
| endgenerate | |
| endmodule | |
| module Array #(parameter ELEMENTS=16, WIDTH=32)( | |
| input wire [$clog2(ELEMENTS)-1:0] index, | |
| input wire [WIDTH-1:0] element, | |
| // Flattened array | |
| output wire [(ELEMENTS*WIDTH)-1:0] array, | |
| input wire clock, clear, enable | |
| ); | |
| reg [WIDTH-1:0] __array[ELEMENTS-1:0]; | |
| genvar g_index; | |
| generate | |
| for(g_index = 0; g_index < ELEMENTS; g_index = g_index + 32'd1) begin : unflatten | |
| localparam START_BIT = g_index * WIDTH; | |
| assign array[START_BIT + WIDTH - 1:START_BIT] = __array[g_index]; | |
| end | |
| endgenerate | |
| localparam ZERO_ELEMENT = {WIDTH{1'b0}}; | |
| // I think this might synthesize correctly, but it is pretty gross. | |
| integer reset_index; | |
| always @(posedge clock) | |
| if(clear) begin | |
| for(reset_index = 0; reset_index < ELEMENTS; reset_index = reset_index + 32'd1) | |
| __array[reset_index] <= {ZERO_ELEMENT}; | |
| end else if(enable) | |
| __array[index] <= element; | |
| endmodule |