logic operations on multidimensional arrays in verilog - arrays

I have a multidimensional array as below.
reg [3:0] varname [`KEY-1:0];
I want to check if atleast one element in the array is equivalent to 4'b1111 or 4'b1110
What is the easiest and best way we can do this?

If 'KEY is small and constant that you know, then it is better to use simple logic for each row (example for i-th row)
if((varname[i] && 4'b1111) || (varname[i] && 4'b1110) )
If 'KEY is variable or quite large number then it is better to use different method, i would try using
output reg equivalent_detected;
reg counter;
initial
begin
equivalent_detected = 1'b0;
counter = 0;
end
always#(posedge clk)
begin
if((varname[counter] && 4'b1111) || (varname[counter] && 4'b1110) )
equivalent_detected <= 1'b1;
counter <= counter + 1;
end // end of always block
You can use the above codes in your module
If you use equivalent_detected as your output then whenever you get 1 it means you detected 4'b1111 or 4'b1110.
You can further improve this code and make it better, I just wanted to give you some idea.

Related

accessing boundaries of array without duplicating lots of code

When I try to compile my code using -fcheck=all I get a runtime error since it seems I step out of bounds of my array dimension size. It comes from the part of my code shown below. I think it is because my loops over i,j only run from -ny to ny, -nx to nx but I try to use points at i+1,j+1,i-1,j-1 which takes me out of bounds in my arrays. When the loop over j starts at -ny, it needs j-1, so it immediately takes me out of bounds since I'm trying to access -ny-1. Similarly when j=ny, i=-nx,nx.
My question is, how can I fix this problem efficiently using minimal code?
I need the array grad(1,i,j) correctly defined on the boundary, and it needs to be defined exactly as on the right hand side of the equality below, I just don't know an efficient way of doing this. I can explicitly define grad(1,nx,j), grad(1,-nx,j), etc, separately and only loop over i=-nx+1,nx-1,j=-ny+1,ny-1 but this causes lots of duplicated code and I have many of these arrays so I don't think this is the logical/efficient approach. If I do this, I just end up with hundreds of lines of duplicated code that makes it very hard to debug. Thanks.
integer :: i,j
integer, parameter :: nx = 50, ny = 50
complex, dimension (3,-nx:nx,-ny:ny) :: grad,psi
real, parameter :: h = 0.1
do j = -ny,ny
do i = -nx,nx
psi(1,i,j) = sin(i*h)+sin(j*h)
psi(2,i,j) = sin(i*h)+sin(j*h)
psi(3,i,j) = sin(i*h)+sin(j*h)
end do
end do
do j = -ny,ny
do i = -nx,nx
grad(1,i,j) = (psi(1,i+1,j)+psi(1,i-1,j)+psi(1,i,j+1)+psi(1,i,j-1)-4*psi(1,i,j))/h**2 &
- (psi(2,i+1,j)-psi(2,i,j))*psi(1,i,j)/h &
- (psi(3,i,j+1)-psi(3,i,j))*psi(1,i,j)/h &
- psi(2,i,j)*(psi(1,i+1,j)-psi(1,i,j))/h &
- psi(3,i,j)*(psi(1,i,j+1)-psi(1,i,j))/h
end do
end do
If I was to do this directly for grad(1,nx,j), grad(1,-nx,j), it would be given by
do j = -ny+1,ny-1
grad(1,nx,j) = (psi(1,nx,j)+psi(1,nx-2,j)+psi(1,nx,j+1)+psi(1,nx,j-1)-2*psi(1,nx-1,j)-2*psi(1,nx,j))/h**2 &
- (psi(2,nx,j)-psi(2,nx-1,j))*psi(1,nx,j)/h &
- (psi(3,nx,j+1)-psi(3,nx,j))*psi(1,nx,j)/h &
- psi(2,nx,j)*(psi(1,nx,j)-psi(1,nx-1,j))/h &
- psi(3,nx,j)*(psi(1,nx,j+1)-psi(1,nx,j))/h
grad(1,-nx,j) = (psi(1,-nx+2,j)+psi(1,-nx,j)+psi(1,-nx,j+1)+psi(1,-nx,j-1)-2*psi(1,-nx+1,j)-2*psi(1,-nx,j))/h**2 &
- (psi(2,-nx+1,j)-psi(2,-nx,j))*psi(1,-nx,j)/h &
- (psi(3,-nx,j+1)-psi(3,-nx,j))*psi(1,-nx,j)/h &
- psi(2,-nx,j)*(psi(1,-nx+1,j)-psi(1,-nx,j))/h &
- psi(3,-nx,j)*(psi(1,-nx,j+1)-psi(1,-nx,j))/h
end do
One possible way for you could be using an additional index variable for the boundaries, modified from the original index to avoid getting out-of-bounds. I mean something like this:
do j = -ny,ny
jj = max(min(j, ny-1), -ny+1)
do i = -nx,nx
ii = max(min(i, nx-1), -nx+1)
grad(1,i,j) = (psi(1,ii+1,j)+psi(1,ii-1,j)+psi(1,i,jj+1)+psi(1,i,jj-1)-4*psi(1,i,j))/h**2 &
- (psi(2,ii+1,j)-psi(2,ii,j))*psi(1,i,j)/h &
- (psi(3,i,jj+1)-psi(3,i,jj))*psi(1,i,j)/h &
- psi(2,i,j)*(psi(1,ii+1,j)-psi(1,ii,j))/h &
- psi(3,i,j)*(psi(1,i,jj+1)-psi(1,i,jj))/h
end do
end do
It's hard for me to write a proper code because it seems you trimmed part of the original expression in the code you presented in the question, but I hope you understand the idea and apply it correctly for your logic.
Opinions:
Even though this is what you are asking for (as far as I understand), I would not recommend doing this before profiling and checking if assigning the boundary conditions manually after a whole array operation wouldn't be more efficient, instead. Maybe those extra calculations on the indices on each iteration could impact on performance (arguably less than if conditionals or function calls). Using "ghost cells", as suggested by #evets, could be even more performant. You should profile and compare.
I'd recommend you declaring your arrays as dimension(-nx:nx,-ny:ny,3) instead. Fortran stores arrays in column-major order and, as you are accessing values on the neighborhood of the "x" and "y", they would be non-contiguous memory locations for a fixed "other" dimension is the leftest, and that could mean less cache-hits.
In somewhat pseudo-code, you can do
do j = -ny, ny
if (j == -ny) then
p1jm1 = XXXXX ! Some boundary condition
else
p1jm1 = psi(1,i,j-1)
end if
if (j == ny) then
p1jp1 = YYYYY ! Some other boundary condition
else
p1jp1 = psi(1,i,j+1)
end if
do i = -nx, ny
grad(1,i,j) = ... term involving p1jm1 ... term involving p1jp1 ...
...
end do
end do
The j-loop isn't bad in that you are adding 2*2*ny conditionals. The inner i-loop is adding 2*2*nx conditionals for each j iteration (or 2*2*ny * 2*2*nx conditional). Note, you need a temporary for each psi with the triplet indices are unique, ie., psi(1,i,j+1), psi(1,i,j-1), and psi(3,i,j+1).

Increment a for loop by 3 then by 1 using matlab

I am working on MATLAB code right now, and I want to increament y by 3 then by 1 and so on.
Here is the code if anyone could help, it would be appreciated.
for y=1:2:9
for x=9:-1:1
A(x,y)=1
if x==1 && y~=9
%y=y+1
for x= 1:9
A(x,y)=1
end
end
end
end
You first make a vector of the indexes you want to visit and then loop over the vector.
idx = [1,2,5]; %and so on
for ct = 1:length(idx)
A(x,y(idx(ct)))=1
end
You can specify a predefined vector or even matrix to be used in for loop; not necessary to use range index.
I am not completely certain how your question is reflected in your code. However, if you want to alternately increment y with 1 and 3, I would make a standard for-loop and then update y inside. Something like:
n = 100;
for i = 1:n
y = y + 2*mod(i,2)+1;
display(y) %Do things
end

Array output in verilog

I'm working on a school homework and I'm finding difficulties in outputing an array with values of 1.I used this code,but the simulator keeps filling the signal bar with X
integer index = 0;
initial
begin
for(index=0;index<=7;index = index+1)
begin
data_out[index]<=1;
end
end
endmodule
data_out is declared as output reg [7:0]data_out
Can anyone suggest me anything?
It works now , as i've used wire[7:0] data_out_test and always block. Thank you for your answers
Ok,and next . I have a descending order counter by the posedge clock and another variable suma_de_1 whose value is 12.The counters stars from 31 to 0 and i have the following if condition
`integer index = 0;
always#(posedge clock) begin
for(index=0;index<=31;index = index+1)
begin
if(count > suma_de_1)
data_out[index]<=2'b00;
else data_out[index]<=1;
end end`
check this out to see the result waveform
at that point count becomes smaller than suma_de_1 but it creates another array . I want it to complete the previous array who was full of 0 until then.
Hope I'm clear enough. I want the output in one array,not two

Function to encoding input characters in MATLAB

I want to create a function that encrypts the input sentence. This encryption will replace the first letter of each word with the next letter in the ASCII table, and the second letter with the next, ....
So basically, the resulting output for abc def should be bcd efg. However, when I run my function, the space will also be replaced, i.e. output will be bcd!efg. Why is this so? Thanks.
Below is what I have written:
function out = encrypt(input)
ascii_encode=double(input);
line={ascii_encode};
counter=0;
for a=1:length(line)
if line{a}==32
counter=0;
else
counter=counter+1;
line{a}=line{a}+counter;
end
line{a}=char(line{a});
end
out=line;
end
You should be careful handling cells.
Try line{a} , line(a) , line(1){a}, to understand how they work.
The code should be like this,
function out = encrypt(input)
ascii_encode = double(input);
line = {ascii_encode};
for a = 1 : length(line{1})
if line{1}(a) == 32
continue;
end
line{1}(a) = line{1}(a) + 1;
end
line{1} = char(line{1});
out = line{1};
end
And there is no need for counter, you just have to jump when if is true.
Kamtal's answer is perfectly right. You assign your input to a cell and then you were not accessing an index in the cell value (which is still a char array), but the full cell value.
Follow Kamtal answer if you still want to use cells type, and look at the cell documentation.
Note that you could also benefit by Matlab vectorization capabilities, and simplify your function by:
function out = encrypt(input)
charToKeep = ( input==' ' ) ; %// save position of character to keep
out = char(input+1) ; %// apply the modification on the full string
out(charToKeep) = ' ' ; %// replace the character we saved in their initial position
end

How to use 'Last attribute on multidimensional arrays in Ada?

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 :-)

Resources