Pregunta

As an academic exercise, I am designing a shift register with certain constraints, one of which is that I have to make use of a given amount of d-type flipflops (the quantity of which comes from a generic).

How can I make the width of the input bus vary with the amount of flip flops I have?

This was the original plan (with for-loops, using i as an incrementing value), but we were not able to use a for loop inside a process!

 else --SHIFT LEFT
 if (CTRL = "10") then


 internalInputBus (i+1) <= internalOutputBus(i);
 internalInputBus (0) <= SHIFT_IN;

 else --SHIFT RIGHT
 if (CTRL = "01")  then
 internalInputBus (i) <= internalOutputBus(i+1);
 internalInputBus (n-1) <= SHIFT_IN; --use interesting test length thing
¿Fue útil?

Solución

Because you specify i+1 for left shift and i-1 for right shift we can adduce that you're expressing the range as little endian (downto).

The size of the 'register' can assigned via a generic, used to match the port size and any internal array value size.

signal internalInputBus: std_logic_vector (REGSIZE-1 downto 0);

In your process statement, where shifting left

internalInputBus <= internalInputBus(REGSIZE-2 downto 0) & right_shift_input;

Using the concatenation operator on the right most REGSIZE-1 bits and shift input.

When shifting right

internalInputBus <= left_shift_input & internalInputBus(REGSIZE-1 downto 1);

I've seen people use a single shift input before, but have never found an application where it makes sense myself. Without internal tristate signals there is an implied multiplexer somewhere.

Loop statements are allowed sequential statements inside a process statement. I'd imagine you were having trouble with end boundaries. Seeking a solution would lead you to an analog of using concatenation operators.

The left and right boundaries of the two concatenation operator examples above would lead you to how to use a loop not traversing all of the elements along with an additional assignment operator to cover all the elements of the target array.

-- LEFT
for i in REGSIZE-2 downto 0 loop
    internalInputBus(i+1) <= internalInputBus(i);
end loop;

internalInputBus(0) <= right_shift_input;

and

-- RIGHT
for i in REGIZE-1 downto 1 loop
    internalInputBus(i-1) <= internalInputBus(i);
end loop;
internalInputBus(REGSIZE-1) <= left_shift_input;

These are simply done off the top of my head. Caveat Emptor.

Note that signal assignments without intervening waits (as in a loop statement) can read the current value of a value you've just scheduled for update. If you were using a variable target instead you'd want to reverse the order to prevent overwriting the next value being evaluated. (In this case in the -- RIGHT example, for i in 1 to REGIZE-1 loop).

Otros consejos

You can write a shifter in one line. I've renamed your signals i and o to save typing and make the fundamental point clearer (I think it does anyway!):

i <= o(o'high-1 downto 0) & SHIFT_IN;

This takes the signal o, chops off the highest bit, and puts the new bit on the "low" end, resulting in a left-shift.

Similarly, for a right-shift, drop the lowest bit and put the new bit on the "high" end:

i <= SHIFT_IN & o(o'high downto 1);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top