How does recursion work in Verilog? - recursion

I was supposed to apply recursion in Verilog . The code which I have designed doesn't show any error. Please have a look at my code where the task (splitt00) is recursively called. Does Verilog support recursion and how can I implement a recursive logic?
task split00;
input [0:n-1] a;
input [0:n-1] b;
input [0:n-1] num0;
output [0:2*n-1] s;
reg [0:n-1] a0,b0,u0,v0,w0,s0,s1,a1,b1,a2,b2,u1,w1,v1;
reg [0:n-1] num00;
begin
num00=num0;
if(num00==2)
begin
u0=(a/10)*(b/10);
w0=(a%10)*(b%10);
if (((a%10-a/10)*(b%10-b/10))<0)
begin
v0=((a%10-a/10)*(b%10-b/10))*-1;
s=u0*100+(u0+w0+v0)*10+w0;
end
else
begin
v0=((a%10-a/10)*(b%10-b/10));
s=u0*100+(u0+w0-v0)*10+w0;
end
end
else
begin
a0=a/(10**(num00/2));
b0=a%(10**(num00/2));
a1=b/(10**(num00/2));
b1=b%(10**(num00/2));
split00(a0,a1,num00/2,u1);
split00(b0,b1,num00/2,w1);
if((a1-a0)<0 && (b1-b0)>0)
begin
a2=a0-a1;
b2=b1-b0;
split00(a2,b2,num00/2,v1);
s=u1*(10**num0)+(u1+v1+w1)*(10**(num0/2))+w1;
end
else if((a1-a0)>0 && (b1-b0)<0)
begin
a2=a1-a0;
b2=b0-b1;
split00(a2,b2,num00/2,v1);
s=u1*(10**num0)+(u1+v1+w1)*(10**(num0/2))+w1;
end
else if((a1-a0)<0 && (b1-b0)<0)
begin
a2=a0-a1;
b2=b0-b1;
split00(a2,b2,num00/2,v1);
s=u1*(10**num0)+(u1-v1+w1)*(10**(num0/2))+w1;
end
else
begin
a2=a1-a0;
b2=b1-b0;
split00(a2,b2,num00/2,v1);
s=u1*(10**num0)+(u1-v1+w1)*(10**(num0/2))+w1;
end
end
end
endtask

What you have coded here is Verilog-1995, which does not support recursion. The arguments to your task, and all the local variables inside it are static variables, which means there is only one copy of them for all entries into the task. Verilog-2001 added automatic tasks and functions, which changes the lifetime so that each entry creates a new copy of those variables. The way you would code that is by adding the automatic keyword.
task automatic split00(
input [0:n-1] a,
input [0:n-1] b,
input [0:n-1] num0,
output [0:2*n-1] s);
In SystemVerilog, I would use a function instead of a task for any routine that is combinational logic, and change the keyword reg to logic
function automatic void split00(
input [0:n-1] a,
input [0:n-1] b,
input [0:n-1] num0,
output [0:2*n-1] s);
logic [0:n-1] a0,b0,u0,v0,w0,s0,s1,a1,b1,a2,b2,u1,w1,v1;
logic [0:n-1] num00;
In order to synthesize a recursive function, you have the same coding restrictions as any loop. The synthesis tool needs to unroll the recursion into a fixed number of entries of the function. It does this by in-lining the function in to the body of code that made the call to the function.

Related

Progress 4GL In-line functions / Multi-line statement

Description:
I am Writing/Editing a LinqToProgress query engine. So far simple functions within progress is simple to replicate, such as "A" >= "B" or Lookup(A, B) > 1, simple one liners that give boolean conditions. However to implement more advance function or custom functions I will need to be able to write multiline statements that can be plugged into conditions, meaning the inline function should be able to give a boolean result when you use DISP ( myFunc ) in the ABL ScratchPad (Using Eclipse) or similar programs.
Issue:
I need to convert the code between the //Start Here and //End Here to an inline boolean result.
DEF VAR i AS INT NO-UNDO.
DEF VAR LIST AS CHAR NO-UNDO INIT "one,two,three,four".
DEF VAR LIST2 AS CHAR NO-UNDO INIT "one,three,five".
DISP(
// Start Here
DO i=1 TO NUM-ENTRIES(LIST):
IF LOOKUP(ENTRY(i, LIST),LIST2) > 0 THEN RETURN TRUE.
END.
RETURN FALSE.
// End Here
)
Currently the code throws an error.
White space after colon ends statement. I tried looking for solutions on multiline statements/inline functions but so far found nothing.
Constraints:
Everything written needs to be contained within the Disp function.
I can't use previously created functions.
You should introduce a method or function that contains your code block. The ABL does not support statements and blocks as an expression.

Creating plsql function for Factorial program

When I call the function using select statement
[select fact(5) from dual;]
I get output as 1.Can you guys please help me from the below code
create or replace function fact(num in number)
return number
Is
res_fact number:=1;
begin
for i in 1..5 loop
res_fact:=res_fact*i;
dbms_output.put_line(res_fact);
-- dbms_output.put_line('Factorial of '||num||' = '||res_fact);
return res_fact;
end loop;
dbms_output.put_line(res_fact);
end;
res_fact=res_fact*i;
as i call function i used to get the factorial of that input number
res_fact=5*4*3*2*1;
res_fact=120
Make this code "return res_fact;" out of loop you code will run, But above code work for only 5.
Two issues....
Firstly you need to move your return statement outside of your loop. As you now have it it will return on the first pass through the loop.
Secondly you are ignoring your input parameter and always going to get factorial of 5 rather than what is passed in (once you move your return statement.
See code below
create or replace function fact(num in number)
return number
Is
res_fact number:=1;
begin
for i in 1..num loop
res_fact:=res_fact*i;
end loop;
dbms_output.put_line('Factorial of '||num||' = '||res_fact);
return res_fact;
end;

Starting tasks again

I recently started Ada programming and now I'm stuck.
I created a program with multiple tasks. The main-task is managing incoming communication and as a consequence starts working-tasks or transfers data to the working-tasks.
The working-tasks are all of the same kind but with different identifiers.
They do their work and should finish after that. For example:
task body Access_Protected is
begin
accept Start(foo: in Integer; foo2: out Integer)
do something
end Start;
while Go_loop loop
select
accept Quit do
Go_loop := false;
end Quit;
or
accept Insert(foo3: in Integer)
do something
if something = 0 then
Go_loop := false;
end if;
end Insert;
or delay 2.0;
end select;
end loop;
end Access_Protected;
I understand that the working-task should be terminated when the Go_loop is finished. Am I right?
It works to start the task one time but when the main-task tries to restart the working-task by calling the Start procedure, nothing happens.
Can someone please tell me which point I am missing.
A task and subprogram are somewhat related in that when the body is completed the construct ends, this is to say that the construct ends with it's appropriate end; in the case of a procedure control returns to the caller, in the case of a function the exception PROGRAM_ERROR is raised, and in the case of a task the controlling "thread" terminates.
What's happening in your particular problem, it seems, boils down to the following:
Package Example is
Task Type Message_Task is
Entry Execute;
End Message_Task;
End Example;
Package Body Example is
Task Body Message_Task is
Use Ada.Text_IO;
Begin
accept Execute do
Put_Line( "Rendezvous!" );
end Execute;
delay 0.2; -- Stub delay.
Put_Line( "Finishing Task." );
-- Task Ends Here.
End Message_Task;
End Example;
--...
Test : Example.Message_Task;
--...
Test.Execute;
-- Test.Execute can't be accepted here because it can only accept "Execute"
-- the one time, as per the body's definition.
The reason that this really is like your problem is because, likewise once you say "X.Start(1,2)" another call to Start doesn't reset the position of the task's execution back up to that accept.
If you wanted the task to "stay alive" for further processing you could do one of two options.
Option 1 -- set up a 'protocol':
Package Example is
Task Type Message_Task is
Entry Initialization;
Entry Execute;
Entry Quit;
End Message_Task;
End Example;
Package Body Example is
Task Body Message_Task is
Use Ada.Text_IO;
Has_quit : Boolean := False;
Begin
Main:
loop
select
accept Initialization do
null;
end Initialization;
accept Execute do
null;
end Execute;
or
accept Quit do
Has_Quit := True;
end Quit;
end select;
Exit Main when Has_Quit;
end loop Main;
End Message_Task;
End Example;
Option 2 -- Allow termination.
Package Example is
Task Type Message_Task is
Entry Initialization;
Entry Execute;
End Message_Task;
End Example;
Package Body Example is
Task Body Message_Task is
Use Ada.Text_IO;
Has_quit : Boolean := False;
Begin
accept Initialization do
null;
end Initialization;
Main:
loop
select
accept Execute do
null;
end Execute;
or
terminate;
end select;
end loop Main;
End Message_Task;
End Example;
The subtle difference is Option 2 gets rid of the Quit entry, allowing the task to 'rest' on the terminate alternative while Option 1 is more explicit in control (and required in some cases), but requiring that Initialization & Execute be called in pairs.
A task only runs until it reaches the end of its main sequence of statements (ignoring various technicalities).
If you want a task to do something, and then pause until it receives an external trigger, you should put a loop around the statements you have in the task body.

Ada actual for "S" must be a variable

So here is a piece of my body file. I am getting the error "words.adb:75:42: actual for "S" must be a variable".
procedure Remove_Character(S : in out Ustring; C : in Character; Successful : out Boolean) is
begin
for I in 1..length(S) loop
if Element(S, I) = C then
Delete(S, I, I);
Successful := true;
return;
end if;
end loop;
Successful := false;
end Remove_Character;
function Is_Subset(Subset : Ustring; S : Ustring) return Boolean is
Could_Remove : Boolean;
begin
for I in 1..length(Subset) loop
Remove_Character(S , Element(Subset, I), Could_Remove);
if Could_Remove = false then
return false;
end if;
end loop;
return True;
end Is_Subset;
I understand where my error is coming from. Remove_Character uses S : in out Ustring while function Is_Subset uses S : in Ustring.
My question is how do I change the variable from Remove_Character into only an in Ustring?
Sorry if this is a tad jumbled, I'm fairly new to both programming and the site.
You can't, at least not directly.
I don't know what a UString is, but I presume the Delete procedure modifies it. If you changed the declaration of S in Remove_Character to S: in Ustring, you'd presumably get an error on the call to Delete.
The simplest approach I can think of would be to make a copy of S in Is_Subset:
Copy_Of_S: UString := S;
and then pass the (modifiable) copy to Remove_Character.
By "simplest", I mean it makes the smallest change to your existing code. But you should probably consider reorganizing it. Determining whether one UString is a subset of another by modifying one of the strings doesn't seem like the best approach; I'm sure there's a more efficient way to do it.
A minor and irrelevant point: this:
if Could_Remove = false then
is better written as:
if not Could_Remove then

Recursion in Verilog within an Always block

I have a verilog code where I wish to use recursion. However, whenever I try this in an always block, it gives an error saying is not a task.
Is there any way I can implement a module in an always block? Also is there anyway I can use recursion within the always block?
You can write recursive modules using a generate block:
module unary_and
#(parameter WIDTH = 32)
(input [WIDTH-1:0] in_and,
output out_and)
generate
if(WIDTH == 1) begin
assign out_and = in_and;
end
else if(WIDTH == 2) begin
assign out_and = in_and[0] & in_and[1];
end
else begin
unary_and #(.WIDTH (WIDTH/2))
unary_and_low
(.in_and (in_and[WIDTH/2-1:0]),
.out_and (out_and_low));
unary_and #(.WIDTH (WIDTH - WIDTH/2))
unary_and_high
(.in_and (in_and[WIDTH-1:WIDTH/2]),
.out_and (out_and_high));
assign out_and = out_and_low & out_and_high;
end
endgenerate
endmodule
This is from Recursive and Iterative designs in Verilog where you can find other solutions as well. You can check out Recursive Modules too.
Maybe you should also take a look at these questions and answers:
Could we have generate inside an always block?
Verilog generate/genvar in an always block

Resources