I am trying to create a n-bit logical shift using generate function.
entity logical_shift_n is
generic(WIDTH : positive :=8);
port (A: in std_logic_vector(WIDTH-1 downto 0);
S: in std_logic_vector(log2(WIDTH)-1 downto 0);
D: out std_logic_vector(WIDTH-1 downto 0));
type two_dim is array (0 to log2(WIDTH)-1) of std_logic_vector(WIDTH-1 downto 0);
end logical_shift_n;
architecture behavioral of logical_shift_n is
component mux is
port(A,B : in std_logic_vector(WIDTH-1 downto 0);
S : in std_logic;
O : out std_logic_vector(WIDTH-1 downto 0));
end component;
signal D1 : two_dim :=(others=>(others=>'0'));
signal D0 : two_dim :=(others=>(others=>'0'));
signal Y : two_dim :=(others=>(others=>'0'));
begin
D0 <= A;
D1 <= A & '0';
reg: for i in 0 to log2(WIDTH)-1 generate
DC : mux
port map(
A => D0,
B => D1,
S => S(i),
O => Y
);
end generate;
D <= Y;
end behavioral;
The problem that I am facing is
I need to assign the first row of "D0" to "A" and first row of "D1" to "A & '0'" so that the first row of D0 contains the normal input A and first row of D1 contains the left shift of A by 1.
Then I want to iterate over the rows (using the generate function) such that the output coming from my first multiplexer acts as an input to the next multiplexer and the second multiplexer should have a normal input (which is equal to previous output) like the one before it then another input which should be the previous output shifted by 2. Similarly, for third multiplexer, one of the inputs to it should be previous output shifted by 4 (2^(n-1)). And so forth.
To provide a better idea, I have also created a diagram. Even though, this diagram is only for 8 bits (three multiplexers), I want to use a generate function to generalize it to n bits.
I created a two dimensional signal. But I am not sure how to initialize its first rows. Furthermore, I am not sure how to iterate over the rows such that cascading of the multiplexers happen and the left shift (by 2^n) also happens where n=0,1,2......n
There are some number of ways to create a generic or parameter controlled logical (left) shifter.
Here's one based on your question code:
And that produces:
noting the format of a report statement is VHDL tool implementation dependent.
The operative ideas changing your code include using the previous 'stage' Y as the unchanged input to a mux except for the first, which uses the unchanged A input. For the shifted input the function XSLL is purloined from the earliest release of IEEE package numeric_std, the package body where the declaration is not visible by use clause, which assigns an output slice based on the shift distance overwriting part of the output value which has an initial value of all '0's. The shift distance for D1(i) is 2 to the power of the S element for each stage except the first which derives from A instead. The Y output from the previous stage afterwards is used for the mux input not shifted and the D1(i) value is derived from the previous stage Y by shifting by the power of 2 to the distance.
The testbench is just a little something thrown together to demonstrate the code (with the independent implementation of mux) analyzes, elaborates and simulates without error.
There are two more ways in general, either recursive instantiation or recursive subprogram calls where a generic or parameter can define the number of 'stages' and is modified in subsequent instances or calls until no more shifts are required. These can eliminate the need for defining your own array type.
Here type two_dim is a single dimensional array type (it has one index) with an element type that is an array type (std_logic_vector).
A casual search reveals no source for a standard package log2 function returning an integer value. I threw in the encapsulating ceil function call on the off chance the length of A is not a power of two. If the shift distance exceeds WIDTH - 1 all '0's will be returned by function XSLL which is used here to encourage exploring preexisting packages.
An array value concatenated with a another array value or a value of it's subelement type ('0') has the length of the combined values which can cause issues during simulation or synthesis where the standard requires matching elements between the assignment target and the value expression and that isn't true with
Here you could also note the type of D1 is two_dim while the type of A is std_logic_vector, the types of the two arrays are not the same nor is one a subtype of the other. That issue is overcome by the assignment target D1(i) in the generate statements where type two_dim has an element type of std_logic_vector. This also provides insight as to why VHDL refers to two_dim as a single dimensional array type with an element type of std_logic_vector, where the element type is an array type (besides the lack of more than one index). Your 'rows' are elements of a value of type two_dim, while you can slice an element or index a subelement you need to index an element to refer to a value of std_logic_vector.
The semantics of VHDL are formal, that is the terms that are defined in the standard (in italics) are used in further semantic description. VHDL is a hard language to dip a toe in and the casual user resists the emersion effort while the standard will be revised at intervals shorter than the time to achieve mastery of the syntax and semantics.