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 <lars@metafoo.de>
main
Lars-Peter Clausen 2018-09-17 14:56:19 +02:00 committed by Lars-Peter Clausen
parent e7ea5dfa11
commit 67f204e10e
1 changed files with 68 additions and 0 deletions

View File

@ -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