Here is my code :
variable input: array(0 to 3, 0 to 3) of unsigned(7 downto 0);
variable outt: array(0 to 3, 0 to 175) of unsigned(7 downto 0);
for i in 0 to 3 loop
outt(0,i) :=input(0,i);
outt(1,i) :=input(1,i);
outt(2,i) :=input(2,i);
outt(3,i) :=input(3,i);
end loop;
Is there a better way to do this?I mean an efficient code to copy all of input array in a part of the larger outt array ?
As a rule of thumb for loops in VHDL are unrolled, as the purpose of a loop is to synthesize multiple copies of hardware described in the loop body. The control logic does not appear in the synthesized hardware.
For that reason, a more compact way to write multiple assignments is to do two nested loops.
for i in 0 to 3 loop
for j in 0 to 3 loop
out(i,j) := in(i,j); // there will be 16 wires / flipflops synthesized
end loop;
end loop;
Try
outt(0 to 3, 0 to 3) := input;
For maximum flexibility, you can use nested loops and attributes to cope with changes in the size of i:
for i in i'range(1) loop
for j in i'range(2) loop
outt(i,j) := input(i,j);
end loop;
end loop;
Related
I am doing some undergraduate research that involved some VHDL coding, something i have virtually no experience with. I am running into some issues and hoping for some help:
I need to read in a signal (array of "std_logic_vectors"), and perform a logical shift on it. My thought was to concatenate an array of 0's with an array that contains the relevant portion of the input. Here is what i've done:
Library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use work.SignalGen.all;
entity Shifter is
Port ( xsig_in : in SignalGen;
shift : in integer;
clk : in STD_LOGIC;
x_out1 : out SignalGen;
x_out2 : out SignalGen);
end Shifter;
architecture Behavioral of Shifter is
type x_in_type is array (0 to (1024-shift) of std_logic_vector;
type zeroes_type is array(0 to shift) of std_logic_vector;
signal x_shifted: SignalGen;
signal x_in : x_in_type := xsig_in(1024 downto shift); -- This is line 37
signal zeroes : zeroes_type := (others => (others => '0'));
begin
process(clk)
begin
x_shifted <= zeroes & x_in; -- This is line 49
end process;
end Behavioral;
Its important to know what type SignalGen is, so here is my declaraion:
type SignalGen is array (0 to 1024) of STD_LOGIC_VECTOR(15 downto 0);
So as you can see, I've created a type "zeroes_type", which is the length of the desired shift. It is used to generate a signal "zeroes" filled with zeroes. Also x_in is of type x_in_type, which is the length of the input signal minus the shift amount, and is initialized to be the signal minus the values shifted out.
When i try to concatenate them together, I get these errors:
Line 37: Indexed name is not a x_in_type
Line 49: found '0' definitions of operator "&", cannot determine exact overloaded matching definition for "&"
The line numbers are included in comments in the code posting. I've been tinkering with this segment for hours now and nothing i've tried to do can fix it.
If anyone can shed some light on the matter, or give me a better way to do what I am trying to do, I would be extremely appreciative! Thanks!
I think you were a long way from where you needed to be. This will not be an efficient implementation in terms of area: you will have 16,000+ flip-flops. However, this solution ought to be closer to where you need to be:
Library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.SignalGen.ALL;
entity Shifter is
Port ( xsig_in : in SignalGen;
shift : in integer;
clk : in STD_LOGIC;
x_out1 : out SignalGen;
x_out2 : out SignalGen);
end Shifter;
architecture Behavioral of Shifter is
begin
process(clk)
variable V : SignalGen;
begin
if rising_edge(clk) then
V := xsig_in;
for I in 1 to xsig_in'RIGHT loop
if I <= shift then
V := "0000000000000000" & V(0 to xsig_in'RIGHT-1);
end if;
end loop;
x_out1 <= V;
end if;
end process;
end Behavioral;
http://www.edaplayground.com/x/8AQ
Variables, loops and concatenation are often useful when doing shifting as you can see in my example. You can jump out of the loop (using exit) when you're finished shifting, but my experience you might get slightly more logic doing that, ie:
if I <= shift then
V := "0000000000000000" & V(0 to xsig_in'RIGHT-1);
else
exit;
end if;
There are many errors in your code. Whilst, I'm sure you will learn something from me just posting the answer, here are some explanations about the errors you are seeing:
type x_in_type is array (0 to (1024-shift)) of std_logic_vector;
You were missing a right hand parenthesis and this line relies on you using VHDL 2008, because the inner dimension is unconstrained. But even then, you cannot define a type based on a non-static quantity (shift), anyway.
signal x_in : x_in_type := xsig_in(1024 downto shift);
With you array constrained as it is, you need to skip over the outer dimension to constrain the inner one. In VHDL 2008 you can skip over a constrained dimension like this:
signal x_in : x_in_type := xsig_in(open)(1024 downto shift);
I have done some searching about how to detect a loop in topological sort, I also finish the coding for the finding a loop, and here is the code:
--print the sort message
IF Kn = 0 THEN
Put("The sorting is complete!!");
RETURN;
ELSE
Put("The Sorting is not complete, loops occur!!");
FOR K IN 1 .. NA LOOP
SortStructure(K).Count:= 0;
END LOOP;
END IF;
-- Find the loop
for K in 1 .. NA loop
P := SortStructure(K).Top;
SortStructure(K).Top := ITN(0);
--when count = 0 and top /= 0, the loop occur
while P /= ITN(0) and then SortStructure(SortElement'Pos(P.suc)).count= 0 loop
SortStructure(SortElement'Pos(P.suc)).count:= k;
IF P /= Itn(0) THEN
P := P.Next;
END IF;
END LOOP;
END LOOP;
--use K determine a part of the loop
K:=1;
WHILE Sortstructure(K).Count= 0 LOOP
K:= K+1;
END LOOP;
--Mark the loop
LOOP
Sortstructure(K).Top := ITN(1);
K:= Sortstructure(K).Count;
EXIT WHEN SortStructure(K).Top /= ITN(0);
END LOOP;
--Print the loop
Put_Line("The loop is: ");
WHILE SortStructure(K).Top /= ITN(0) LOOP
--SortElement'Val(K) will return the value of K, make this also work for Enumeration
Put(SortElement'Val(K));
Put(", ");
SortStructure(K).Top := ITN(0);
K:= SortStructure(K).Count;
END LOOP;
Put(SortElement'Val(K));
New_Line;
This code starts from printing the message if there is a loop occurred, then mark the beginning of the loop and the end of the loop then print it. It works well for detect single loop, but how to make this can detect multiple loops and print them?
For example:Given the relations (format "Pre < Suc"):
1<2, 2<3, 3<1 (one loop), 1<4, 4<3 (second loop).
Any ideas would be appreciated.
I am not sure if topological sorting will help you detecting all cycles. It definitely helps you in testing whether the graph is acyclic or not.
Why you do not simply run DFS over the graph and look for back edges. Every time you encounter a back edge, you print the cycle path. The printing task is kind of tricky but I believe is doable ( see this )
I would think , you would go like All path problem. If topological sort is what you want to do for detecting multiple cycles, whenever you detect a cycle, add the current stack to a list and continue with next available node , and go up the edge recursively.
I am trying to use the 'Last attribute with a 2D array in Ada, but I can't seem to find the correct syntax to do so.
I know that if I have a 1D array/vector I can use A'last or A'last(n) where n is the nth dimension. But if I do the following
type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
for i in 0..tempTable'last(1) loop
for j in 0..tempTable'last(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
end temp;
I get the following compile time error:
Storage_Error stack overflow (or erroneous memory access)
So what am I doing wrong?
I am using GNAT Pro 6.4.1 on Linux.
I'd be very surprised if you got a compile-time Storage_Error on that code.
I've grabbed a copy of your code and modified it as follows; it compiles without error using GNAT (gcc-4.4):
procedure Array_2D is
type UnconstrainedArray_2D is array (Integer range <>, Integer range <>) of Integer;
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
for i in 0..tempTable'last(1) loop
for j in 0..tempTable'last(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
return 42; -- added this
end temp;
begin
null;
end Array_2D;
(Note that I had to add the missing return statement in temp.)
Your syntax for the 'Last attribute (not "command") is correct, but since Ada arrays can have arbitrary lower and upper bounds, it's better to use the 'Range attribute instead:
for i in tempTable'Range(1) loop
for j in tempTable'Range(2) loop
tempTable(i, j) := Table(i,j);
end loop;
end loop;
As for the Storage_Error exception, that could easily happen at run time (not compile time) if you call your temp function with a very large value for tempIn. Remember that it has to allocate enough space to hold tempIn**2 Integer objects. Presumably you've also created another UnconstrainedArray_2D object to be passed in as the Table parameter.
It's conceivable that the compiler itself could die with a Storage_Error exception, but I don't see anything in your code that might cause that.
Show us a complete (but small) program that demonstrates the problem you're having, along with the exact (copy-and-pasted) error message. Please distinguish clearly between compile-time and run-time errors.
Your tempTable might have a range of 0..tempIn, but you don't know what range your Table has.. They could be of different length, too.
You would have to check that the length is the same and then use relative indices, like this:
function temp(tempIn : in Integer;
Table : in UnconstrainedArray_2D) return Integer is
tempTable : UnconstrainedArray_2D(0..tempIn, 0..tempIn);
begin
if tempTable'Length (1) /= Table'Length (1) or else
tempTable'Length (2) /= Table'Length (2)
then
raise Constraint_Error; -- or something else
end if;
for i in 0 .. tempTable'Length (1) - 1 loop
for j in 0 .. tempTable'Length (2) - 1 loop
tempTable(tempTable'First (1) + i, tempTable'First (2) + j) :=
Table(Table'First (1) + i, Table'First (2) + j);
end loop;
end loop;
end temp;
that way it is ensured that both tables are same length and all indices are valid.
If your tempTable is allowed to be smaller than Table, simply adjust the length check to >. The indices would still be valid.
I don't see an actual value for tempIn set. If the value for tempIn coming into the function temp has not been properly initialized or explicitly set, then the value in tempIn could be anything and probably not something you would like.
I was thinking of a default value. (probably shouldn't post when I am not feeling well :-)
Is there any programming language that has a do-until loop?
Example:
do
{
<statements>
}
until (<condition>);
which is basically equivalent to:
do
{
<statements>
}
while (<negated condition>);
NOTE: I'm looking for post-test loops.
Ruby has until.
i=0
begin
puts i
i += 1
end until i==5
VBA!
Do-Until-Loop
Do-Loop-Until
Although I think quite a number of people here would doubt if it is a real language at all, but well, BASIC is how Microsoft started (quite weak argument for many, I know)...
It is possible in VB.Net
bExitFromLoop = False
Do
'Executes the following Statement
Loop Until bExitFromLoop
It is also possible in SDF-P on BS2000 (Fujitsu/Siemens Operating System)
/ DECLARE-VARIABLE A
/ DECLARE-VARIABLE SWITCH-1(TYPE=*BOOLEAN)
/ SET-VARIABLE A = 5
/ SET-VARIABLE SWITCH-1 = ON
/ REPEAT
/ A = A + 10
/ IF (A > 50)
/ SET-VARIABLE SWITCH-1 = OFF
/ END-IF
/ UNTIL (SWITCH-1 = OFF)
/ SHOW-VARIABLE A
A = 55
Is is also possible is C or C++ using a macro that define until
Example (definition):
#define until(cond) while(!(##cond))
Example (utilisation):
int i = 0;
do {
cout << i << "\n";
i++;
} until(i == 5);
In VB we can find something like:
Reponse = InputBox("Please Enter Pwd")
Do Until Reponse = "Bob-pwr148" ...
Eiffel offers you an until loop.
from
x := 1
until
x > 100
loop
...
end
There is also an "across" loop as well. Both are very powerful and expressive.
The design of this loop has more to offer. There are two more parts to its grammar that will help us resolve two important "correctness" problems.
Endless loop protection.
Iteration failure detection.
Endless Loop Protection
Let's modify our loop code a little by adding a loop variant.
from
x := 1
v := 1_000
until
x > 100
variant
v
loop
...
v := v - 1
end
The loop variant is (essentially) a count-down variable, but not just any old variable. By using the variant keyword, we are telling the compiler to pay attention to v. Specifically, the compiler is going to generate code that watchdogs the v variable for two conditions:
Does v decrease with each iteration of the loop (are we counting down). It does no good to try and use a count-down variable if it is (in fact) not counting down, right? If the loop variant is not counting down (decreasing by any amount), then we throw an exception.
Does v ever reach a condition of less than zero? If so, then we throw an exception.
Both of these work together through the compiler and variant variable to detect when and if our iterating loop fails to iterate or iterates too many times.
In the example above, our code is communicating to us a story that it expects to iterate zero to 1_000 times, but not more. If it is more, then we stop the loop, which leaves us to wonder: Do we really have cases were we iterate more than 1_000 times, or is there something wrong that our condition is failing to become True?
Loop Invariant
Now that we know what a loop variant is, we need to understand what a loop invariant is.
The invariant is a set of one or more Boolean conditions that must hold True after each iteration through the loop. Why do we want these?
Imagine you have 1_000_000 iterations and one of them fails. You don't have time to walk through each iteration, examining it to see it is okay or not. So, you create a set of one or more conditions that are tested upon completion of each iteration. If the one or all of the conditions fail, then you know precisely which iteration (and its deterministic state) is causing the problem!
The loop invariant might look something like:
from
x := 1
y := 0
v := 1_000
invariant
y = x - 1
until
x > 100
variant
v
loop
...
x := x + 1
y := y + 1
v := v - 1
end
In the example above, y is trailing x by 1. We expect that after each iteration, y will always be x - 1. So, we create a loop invariant using the invariant keyword that states our Boolean assertion. If y fails to be x - 1, the loop will immediately throw an exception and let us know precisely which iteration has failed to keep the assertion True.
CONCLUSION
Our loop is now quite tight and secure—well guarded against failure (bugs, errors).
Below is a piece of code shown and doubts are regarding the implementation of loops
C := character'last; --'// SO code colorizer hack
I := 1;
K : loop
Done := C = character'first; --'
Count2 := I;
Exit K when Done;
C := character'pred(c); --'
I := I + 1;
end loop K;
Can anyone please tell me what does 'K' stands for.I guess its not a variable.How does 'K' control the execution of the loop?
K is the name of the loop. The end loop and Exit statements refer to that name, to make it clear what loop is being exited.
The Ada Reference Manual calls it a "loop_statement_identifier".
As noted, K is the loop's label. It allows you to identify a particular loop to aid readability, and also to selectively exit a specific loop from a set of nested enclosing ones (i.e. being a "goto"...shhh! :-)
Here's a contrived example (not compiled checked):
S : Unbounded_String;
F : File_Type;
Done_With_Line : Boolean := False;
All_Done : Boolean := False;
begin
Open(F, In_File, "data_file.dat");
File_Processor:
while not End_Of_File(F) loop
S := Get_Line(F);
Data_Processor:
for I in 1 .. Length(S) loop
Process_A_Character
(Data_Char => Element(S, I), -- Mode in
Line_Done => Done_With_Line, -- Mode out
Finished => All_Done); -- Mode out
-- If completely done, leave the outermost (file processing) loop
exit File_Processor when All_Done;
-- If just done with this line of data, go on to the next one.
exit Data_Processor when Done_With_Line;
end loop;
end loop File_Processor;
Close(F);
end;
K is essentially the name of the loop. The exit k tells the code to stop looping and go to the next statement after loop k ends.
You usually don't need to name loops, as you can just say exit and it will exit the enclosing loop. However, if you have a loop nested inside another loop, and you'd like to exit not the one immediately around the exit statement, but the outermost one, then doing something like this may be required.
K is a label that names the loop. Wow, it has been a long time since I've seen any Ada...