From 67f204e10e99bba30a6bb55f7e7b59194cd2c58b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Mon, 17 Sep 2018 14:56:19 +0200 Subject: [PATCH] library: Add perfect shuffle module The perfect shuffle is a common operation in data processing. Add a shared module that implements this operation. Having this in a shared module rather than open-coding every instance makes sure that there are clear and well defined semantics associated with the operation that are the same each time. This should ease review, maintenance and understanding of the code. The perfect shuffle splits the input vector into NUM_GROUPS groups and then each group in WORDS_PER_GROUP. The output vector consists of WORDS_PER_GROUP groups and each group has NUM_GROUPS words. The data is remapped, so that the i-th word of the j-th word in the output vector is the j-th word of the i-th group of the input vector. The inverse operation of the perfect shuffle is the perfect shuffle with both parameters swapped. I.e. [perfect_suffle B A [perfect_shuffle A B data]] == data Examples: NUM_GROUPS = 2, WORDS_PER_GROUP = 4 [A B C D a b c d] => [A a B b C c D d] NUM_GROUPS = 4, WORDS_PER_GROUP = 2 [A a B b C c D d] => [A B C D a b c d] NUM_GROUPS = 3, WORDS_PER_GROUP = 2 [A B a b 1 2] => [A a 1 B b 2] Signed-off-by: Lars-Peter Clausen --- library/common/ad_perfect_shuffle.v | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 library/common/ad_perfect_shuffle.v diff --git a/library/common/ad_perfect_shuffle.v b/library/common/ad_perfect_shuffle.v new file mode 100644 index 000000000..c04276515 --- /dev/null +++ b/library/common/ad_perfect_shuffle.v @@ -0,0 +1,68 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2018 (c) Analog Devices, Inc. All rights reserved. +// +// Each core or library found in this collection may have its own licensing terms. +// The user should keep this in in mind while exploring these cores. +// +// Redistribution and use in source and binary forms, +// with or without modification of this file, are permitted under the terms of either +// (at the option of the user): +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory, or at: +// https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html +// +// OR +// +// 2. An ADI specific BSD license as noted in the top level directory, or on-line at: +// https://github.com/analogdevicesinc/hdl/blob/dev/LICENSE +// +// *************************************************************************** +// *************************************************************************** + +`timescale 1ns/100ps + +module ad_perfect_shuffle #( + parameter NUM_GROUPS = 2, + parameter WORDS_PER_GROUP = 2, + parameter WORD_WIDTH = 8 +) ( + input [NUM_GROUPS*WORDS_PER_GROUP*WORD_WIDTH-1:0] data_in, + output [NUM_GROUPS*WORDS_PER_GROUP*WORD_WIDTH-1:0] data_out +); + /* + * Performs the perfect shuffle operation. + * + * The perfect shuffle splits the input vector into NUM_GROUPS groups and then + * each group in WORDS_PER_GROUP. The output vector consists of WORDS_PER_GROUP + * groups and each group has NUM_GROUPS words. The data is remapped, so that + * the i-th word of the j-th word in the output vector is the j-th word of the + * i-th group of the input vector. + + * The inverse operation of the perfect shuffle is the perfect shuffle with + * both parameters swapped. + * I.e. [perfect_suffle B A [perfect_shuffle A B data]] == data + * + * Examples: + * NUM_GROUPS = 2, WORDS_PER_GROUP = 4 + * [A B C D a b c d] => [A a B b C c D d] + * NUM_GROUPS = 4, WORDS_PER_GROUP = 2 + * [A a B b C c D d] => [A B C D a b c d] + * NUM_GROUPS = 3, WORDS_PER_GROUP = 2 + * [A B a b 1 2] => [A a 1 B b 2] + */ + generate + genvar i; + genvar j; + for (i = 0; i < NUM_GROUPS; i = i + 1) begin: shuffle_outer + for (j = 0; j < WORDS_PER_GROUP; j = j + 1) begin: shuffle_inner + localparam src_lsb = (j + i * WORDS_PER_GROUP) * WORD_WIDTH; + localparam dst_lsb = (i + j * NUM_GROUPS) * WORD_WIDTH; + + assign data_out[dst_lsb+:WORD_WIDTH] = data_in[src_lsb+:WORD_WIDTH]; + end + end + endgenerate + +endmodule