better alternative on for loop verilog - for-loop

I am a newbie in verilog. I have been searching online and most of them suggest to not use for-loop in verilog coding. So is there a better alternative to replace for-loop?
The problem that I am facing now is that I need to perform 1 or 2 for-loop in a case statement. And I have been thinking of better alternatives but come up with none. It will be great if any one of you can shed some light on this.
Example of my code:
always #(*)
case (help)
4'd1: for (i=A; i<=20;i=i+B)
begin temp[i-1]=1; end
4'd2: for (i=A; i<=20;i=i+B)
begin temp[i-1]=1; B=B+1; end
4'd3: begin
for (i=A; i<=20;i=i+B)
begin temp[i-1]=1; B=B+1; end
for (i=A; i>=1;i=i-B)
begin temp[i-1]=1; B=B+1; end
end
default: temp = 0;

For-loops are fine in Verilog, but they need to able to static unroll if you plan on synthesizing. Static unroll means the loop is not depended on any external variables. For example for(i=0;i<10;i=i+1) is static. for(i=A; i<=20;i=i+B) is not static as it is a depends on the variables A and B.
You can make a loop static my moving the variables as a condition inside the for-loop. for(i=A; i<=20;i=i+B) becomes:
tmp_var = A;
for (i=0; i<=20;i=i+1) begin
if (i==tmp_var) begin
// ... your logic here ...
tmp_var = tmp_var+B;
end
end
Issues that need to be addressed beyond the scope of the question:
They way you are using B and temp is a little concerning.
B appears to be an input, but you are also incrementing it. For synthesis it is illegal to manipulate an input. If it is an input, then create a local variable with default value as B and you may change this value later in the within same always block. If it is not an input, then it is creating latching logic; which is not good and I will cover that next with temp.
temp is latching logic. Latching logic are troublesome because timing is critical; knowing when the latch is transparent or closed, and respecting the hold time requirements. The more complex the logic the harder it is to predict. In RTL one way latches are inferred is by incomplete assignments inside an combinational blocks (ie always #*). To resolve this, make sure every bit is assigned each pass of the combinational blocks. One way to safe guard this is to assign default values before staring your logic. Example:
always #(*) begin
temp = 0; // default to a constant
temp_B = B; // default to an input value
// ... your logic ...
end

Related

First assign and then reassign in if block as alternative to if-(else if)-else in Verilog

Is it better to first assign a value to a variable and then reassign in if block instead of using if-(else if)-else blocks where the assignment in if and else blocks are the same and the assignment in the else if block is a different assignment.
always #(*) begin
if condition1 begin
var = val1;
end
else if condition2 begin
var = val2;
end
else begin
var = val1;
end
end
vs
always #(*) begin
var = val1;
if condition2 begin
var = val2;
end
end
Given condition1 and condition2 are mutually exclusive, I am thinking that both of these blocks should synthesize the same logic and the choice of one over the other is purely aesthetic. Am I correct in thinking this or will one implementation synthesize differently from the other? If my thinking is correct, which method is preferred in the community?
Edit: Added mutually exclusive criteria after racraman's comment.
As for the general principle you're asking about: it doesn't matter which route you go. The synthesiser will be smart enough to work it out anyway. For simulation, it's possible that the option which carries out a default assignment first might execute more slowly (particularly if the assignment is a non-blocking one), but I wouldn't worry about it.
Personally, I prefer the second, because it's more obvious to the causual reader that you have covered your bases in terms of generating unwanted latches (in other words, you are always assigning to var).
Having said all that, your example is (in principle) very simple, and in this particular case it's obvious that a mux is required, and you probably don't need an always block at all, and should just use an assign with a ternary operator.
I say 'in principle' because you logic doesn't really make sense. You say your conditions are mutually exclusive, but what happens if neither condition is active? Do you actually need a latch to preserve the previous output? If not, why do you have two conditions at all?
While using always#(*) blocks you may end up inferring unintentional latches in your design.
For assignments of the type you have mentioned its better to go for ternary operators.
assign var = (cond1)?(val1):(cond2)?(val2):(val1);
//Assuming cond1 and cond2 are mutually exclusive
If cond1 and cond2 can occur at the same time then above assign can be changed as
assign var = (cond1 && cond2)?(val1):(cond1)?(val1):(cond2)?(val2):(val1);
//Assuming val1 when both cond1/2 are high

How does the pascal for loop work?

I've got a question related to the way the for loop works in Pascal:
Program example;
var i:integer;
Begin
i:=7;
for i:=1 to i do write(i);
End.
This piece of code outputs: 1234567.
I think that the compiler makes a secondary copy of the variable i, and then uses that one in the for loop.
Note that this is REQUIRED to work in Pascal according to the ISO7185 standard. The "end value" should be copied before the loop counter is modified.
https://github.com/Leporacanthicus/lacsap/blob/master/test/Basic/iso7185pat.pas#L761
In the for loop in Pascal we have variable called loop counter which controls the iterations of the loop, and this variable changes in each iteration of the loop, so it's that i which is declared here: i:=1 in your code.
The second is the variable declared above the loop which is called also i but it's a variable which is the final value for the loop.
Consider this:
Program example;
var i:integer;
var addr:^word;
Begin
i:=10;
for i:=1 to i do addr:=#i;
addr^ := addr^+1; { I add 1 to the last loop counter }
writeln(i); { This is final variable, I don't add anything to the final variable of the loop }
writeln(addr^); { This is value of the last loop counter index }
{ Both variables give us the same result }
{ Proposal: In my opinion, your guess about the copy is correct }
End.
As in comment in the code - in my opinion, pascal creates a copy of this variable.
Hope it will help!
If yes please let me know by voting up.
Regards!
The point here is the Pascal compiler will set the parameters for the for once, at the first execution. Then it sets a start point i:=1 and and end point 7 before doing anything with the control value, then starts the loop.
But I should point that this is bad practice in programming. Unless you are just making an academical or speculative question, I see no reason to "save" a variable name doing something like this.
It is interesting to notice too that this abuse of the control variable name may cause unpredictable results if this is done inside the loop.
As they use to say in those programs who show dangerous adventures, don't try to do this at home!

verilog compiler error: near “;”: syntax error

timescale 1ns/10ps
/* resource counter for nor gates
*/
module global_vars;
integer count;
endmodule
module my_nor(y, a, b);
output y;
input a, b;
global_vars gv;
/* at instantiation increment the resources used */
gv =gv +1;
/* add 2ns inherent delay */
nor #2 nor1(y,a,b);
endmodule
When I compile, there is one syntax error at global_vars gv;
I have no idea. Should I initial the gv?
In verilog you can not just do this:
gv = gv +1;
wire types need to use assign:
wire gv;
assign gv = a + b;
reg types can use initial, always #* or always #(posedge clk).
always #* begin
gv = a + b;
end
Your trying to use an instance like a variable, I am not sure what your trying to do with your global_vars, may be make a global variable but creating an instance would make it local not global. Here you would do just as well to make gv an integer rather than an instance.
Note
Wire assignment and always #* are combinatorial, is there is no time delay in the assignment, therefor the value can not be directly referenced to itself. For example
gv = gv + 1;
Is a combinatorial loop, when do you expect the +1 to happen. This is normally solved by making gv a flip-flop and updating its value on a clock edge:
always #(posedge clk) begin
gv <= gv + 1;
end
In this case you still need to set an initial value for gv. for FPGAs this can be done using an initial or an async reset for ASIC.
FPGA using initial:
initial begin
gv = 'b0;
end
always #(posedge clk) begin
gv <= gv + 1;
end
Or for ASIC using reset:
always #(posedge clk or negedge rst_n) begin
if (~rst_n) begin
gv <= 'b0;
end
else begin
gv <= gv + 1;
end
end
It looks like you are trying to embed a reference to a global variable within a synthesizable module so that you can count how many times that module has been instantiated. As #Morgan has already pointed out, you can't reference a module instantiate as a variable. But there is an even more fundamental problem -- you are trying to mix behavioral code (i.e. global variables) into synthesizable code and that just doesn't work.
Creating a synthesized module is really a two step process -- design and then coding. In the design phase, you figure out what kind of logic you are trying to create. You don't need to go down to the gate level, but you should be able to sketch out the function with clouds of combinatorial logic, registers, FIFOs, memories etc. Once you've gained some familiarity with the language, this may strictly be a mental process rather than something committed to paper, but you still need to think about the logic you are creating. Then once you have designed your circuit, you actually go write the code to implement your design.
Global variables do not exist in hardware. You can make a counter that is accessible by multiple modules, but but it would need some sort of arbitration process. But what you're trying to do is create a run-time counter that counts up the number of modules instantiated, for which there is no hardware analog. You could use 'define statements to instantiate a variable number of modules and have a signal from each module which is defined as '1' if the module is instantiated and '0' if it isn't and then count the number of '1's, but that is self defeating since you already had to define a macro telling you the number of modules before you instantiated them! In which case, you might as well just use the macro value directly and dispense with all the extra signals.

My sorting algorithm runtime errors

I developed the following sorting algorithm but there are some run time errors that I cant figure out. The program terminates when it comes to the part of filling the array. I'm still a beginner in ada so I couldn't figure out where the problem is...
With Ada.Text_IO;
With Ada.Integer_Text_IO;
Use Ada.Integer_Text_IO;
Use Ada.Text_IO;
Procedure sort is
n,i,x : Integer;
-- Max_Heapify Function...
Procedure Max_Heapify ( i, n : integer) is
j, Temp : Integer;
begin
Temp:=Int_Acc(i);
j:=2*i;
if Temp>Int_Acc(j) then
elsif Temp<=Int_Acc(j) then
Int_Acc(j/2):=Int_Acc(j);
j:=2*j;
end if;
end loop;
Int_Acc(j/2):=Temp;
end Max_Heapify;
begin
Get(n);
for i in MyArr'range loop
Put_Line("Enter Element " & Integer'Image(i));
Get(MyArr(i));
end loop;
end;
end sort;
Thanks in advance :)
Your Problem is that you are insisting on writing Ada code using c - Style programming paradigms.
Firstly:
The declarations:
Type Arr is array(1..20) of Integer;
Type int_access is access Arr;
MyArr : int_access;
Where you use Int_Acc : in out int_access as parameters to procedures are useless in Ada. You are trying to pass a pointer to an array in (which you are doing!), but you should just pass your Type Arr as in out - The Ada compiler knows to do this as a pointer!
Secondly:
I cannot see where you actually allocate any memory to MyArr. This is a possible source of your runtime error. (when you write to or index an array that does not exist, i would expect to have a problem!)
Thirdly:
You seem to be mixing fixed length arrays with variable length input. If N > 20, you will have a problem.
Fourthly:
Insulting the language is not the best way of getting help from those who like it.
NWS has nailed it : there is a pointer, but no array there.
But it's clear that you have learned C, which leaves you with a lot to learn about other languages including Ada. There really are better ways of doing many things, that aren't taught to C programmers because C doesn't allow them.
Allocating variable sized arrays without pointers, malloc and free for example...
Type Arr is array(positive range <>) of Integer; -- of any size
begin
Put_Line("Enter Number Of Elements Of Array");
Get(n);
declare -- now we know the size
My_Arr : Arr(1 .. n);
begin -- My_Arr is in scope until the end of this block
...
end;
end sort;
Using the type system better...
Bad programming :
for i in 1 .. n loop
Get(MyArr(i));
end loop;
HeapSort(MyArr,n);
for i in 1 .. n loop
Put_Line(Integer'Image(MyArr(i)));
end loop;
This is bad because it violates the DRY principle : loop bounds repeated, and something that hopefully represents the array size passed around as a separate parameter... a maintenance nightmare if you decide to rename n to something meaningful for example.
better programming : Use the type system. Recognise that merely declaring an array has declared a new subtype of integer, representing the index of the array. You can access it as My_Arr'range, and the high bound as My_Arr'last.
for i in My_Arr'range loop
Get(MyArr(i));
end loop;
HeapSort(MyArr);
for i in My_Arr'range loop
Put_Line(Integer'Image(MyArr(i)));
end loop;
And accidents such as redefining n after the array declaration can no longer generate buffer overflows.
NOTE: Heapsort now gets its range from the array. (Max_Heapify may still need a separate parameter to operate on subsets of the array)
Arguably best - if it makes the intent clearer - name the index datatype explicitly and use it...
declare -- now we know the size
subtype My_Range is positive range 1 .. n;
My_Arr : Arr(My_Range);
begin -- My_Arr is in scope until the end of this block
for i in My_Range loop ...
And lastly, which do you prefer; a Storage_Error exception immediately the bug occurs (writing to memory you forgot to allocate) or something odd happening much later because something scribbled across another variable?
EDIT
Having cleared up the major issues two more subtle ones remain...
If I compile the modified program (in Gnat 4.8) I get several warnings : one of them is important and tells you exactly what the problem is...
Most of the warnings stem from the fact that
for i in My_Arr'range loop
declares its own loop variable i which hides any existing in-scope declaration. So you can tidy up the code by removing the unnecessary declarations.
What remains is:
sort.adb:51:28: warning: loop range may be null
sort.adb:51:28: warning: bounds may be wrong way round
The for loop bounds are empty ranges, reversed...
1 .. 3 declares a subtype with 3 values
reverse 1 .. 3 declares the same subtype and iterates backwards over it.
But 3 .. 1 declares an EMPTY subtype (containing NO valid values) so iterating over it - either way round - does precisely nothing.
Hopefully that is the missing part of the puzzle. I'm not clear why one faulty loop gets this warning while the other (at line 38) doesn't...
if j<n **and then** Int_Acc(j+1)>Int_Acc(j) then
j:=j+1;
I think you want just 'and' instead of 'and then,' although I haven't looked at Ada code in years.
Did that compile?

Why do we use functions in VHDL

Functions are obviously less verbose to write than entities. But it implies many drawbacks, including:
No generic keyword equivalent
Only one output possible
It appears that functions can be called recursively. May it not be the case with entities? If so, is there any good reason to use functions except for aesthetic purposes?
Functions can't create hardware directly - they have to exist within an architecture to do so. There's nothing to stop you putting all your functionality into a function (or procedure) and then just calling that within a process though.
Regarding some of your other points:
With procedures you can have multiple inout or out parameters.
Entities can recurse... Consider:
entity recurse is
generic (
depth : integer := 1;
param : integer := 3);
port (
a : in integer;
b : out integer);
end entity recurse;
architecture a1 of recurse is
signal c : integer;
begin
c <= a + 1;
bottom: if depth = param generate
b <= a + 1;
end generate bottom;
mid:if depth /= param generate
recurse_1: entity work.recurse
generic map (
param => param,
depth => depth+1)
port map (
a => c,
b => b);
end generate mid;
end architecture a1;
Not very useful, but it synthesises and simulates just fine.
And finally, of course you only use functions for aesthetic purposes (assuming you include maintainability and readability into the definition of aesthetic, which most programming types do in my experience). You only use enumerated types, entities, records and a whole host of other language features for 'aesthetic purposes'. Even assembly mnemonics are aesthetic! Maybe should return to toggling DIP switches :)
Functions in vhdl make the code easy to maintain and read. generally architectures are very big and while debugging if something is not working you can easily find the problematic function and correct it and no need to analyse the entire architecture body.
in case of small codes it's useless but in more big machines it makes you better understand if you consider it function wise.
There is no rule for this so all comments are welcome.
in short : the advantage of functions are
overloading
operators definition
overloading of operators therefore
Better Structure of code
I can see why you are confused, another good question would be why there's both procedure and function. (VHDL seems quite inelegant sometimes!)
That being said, I use both procedures and functions all the time, although mostly in testbenches. For example, for a testbench for a firewall system I made a while back I wrote a procedure called pd_tb_send_udp_packet() that I use repeatedly in the main process, e.g.,
pd_tb_send_udp_packet("10.10.10.2", 1234, false);
pd_tb_send_udp_packet("10.10.10.1", 1234, true);
pd_tb_send_udp_packet("10.10.10.1", 1235, false);
pd_tb_send_udp_packet("ff02:100::1", 1234, false);
pd_tb_send_udp_packet("ff02:101::1", 1234, true);
This procedure generates a random UDP packet with the given addr/port and sends it to the firewall system, then tests whether it is forwarded or not based on the final boolean parameter. Here are the first lines of it, where I use functions from a library:
if f_atvtb_is_ipv6_addr(dest_ip_addr) then
v_ipv6 := true;
v_ipv6_addr := f_atvtb_ipv6_addr(dest_ip_addr);
else
v_ipv6 := false;
v_ipv4_addr := f_atvtb_ip_addr(dest_ip_addr);
end if;
The latter two return 128 and 32 bit std_logic_vectors from the string input, respectively.
While I could probably do all this without using procedures and functions somehow, it would definitely be a lot more messy.

Resources