Reputation: 501
I would like to crearte own implementation of insertion sort for learning purposes. As you may now, one of the steps reqiure shifting array elements to right by 1. The main difficulty here that the range of this operation has to be dynamic.
so if sort_reg is array from 0 to array_length, I need to acheive sort_reg(n)<=sort_reg(n-1), sort_reg(n-1)<=sort_reg(n-2) ... sort_reg(n-i+1)<=sort_reg(n-i); (n-m)>=i>=1, where m starting array index of the range, which would be shifted right by 1 from range ( m to n-1) to (m+1 to n).
The question is if it is possible to acheive this in one step, and then how?
Upvotes: 1
Views: 5533
Reputation: 3659
Yes, it is possible in one step. You must store the element in registers and than assign the new value for all array elements at the same rising edge.
Let's make a simple example with just two signals a and b of type std_logic
. Then this process would swap both elements at the rising edge of the clock
:
process(clock)
begin
if rising_edge(clock) then
a <= b;
b <= a;
end if;
end process;
This works, because the signals get there new values after the process has finished. Thus, in the assignment of b
the old value of a
(before the rising clock edge) is assigned.
Let's continue with your example. You didn't specify an specific array, so I take this one:
type array_type is array(0 to SIZE-1) of std_logic_vector(7 downto 0);
signal sort_reg : array_type;
Then the process can be written using a for loop.
EDIT: Within each iteration step, anif
statement can be used to check if an element should be actually shifted. The signals n
and m
should be of type unsigned
(prefered), or integer
with range 0 to SIZE-1.
EDIT 2: Example changed to rotation as indicated in comments.
-- value to insert in case of rotation
value_to_insert <= sort_reg(to_integer(n)); -- to_integer required if type of 'n' is unsigned
process(clock)
begin
if rising_edge(clock) then
-- This loop is unrolled by the synthesis tool.
for i in SIZE-1 downto 1 loop
-- shift elements [n-1:m] to [n:m+1]
if (i <= n) and (i >= m+1) then
sort_reg(i) <= sort_reg(i-1);
end if;
-- insert new value
if i = m then
sort_reg(i) <= value_to_insert;
end if;
end loop;
-- insert into position zero
if m = 0 then
sort_reg(0) <= value_to_insert;
end if;
end if;
end process;
Upvotes: 3
Reputation: 2073
How about this;
sort_reg <= sort_reg(1 to sort_reg'high) & sort_reg(0);
I'm assuming sort_reg
is a signal defined as;
signal sort_reg : some_array_type(0 to N);
In this case sort_reg'high
is an attribute that is equal to N
.
In vhdl &
is used as concatenation operators. It joins two vector/arrays together to form a single vector/array.
Above example shifts only by 1 item. If you want to shift by M
, you can use something like this;
sort_reg <= sort_reg(M to sort_reg'high) & sort_reg(0 to M-1);
Note that if you want to shift a signal (not assign it to a different signal) you should do it in a process as described by Martin.
Upvotes: 0