system verilog concatenation using values in a variable (type logic) - system-verilog

In system verilog, variables cannot be used as replication constants. Is there any other way to replicate. I need something like:
logic [7:0] value;
logic [4:0] full;
logic [4:0] data_len;
always_comb begin
N= full - data_len ;
output = {N{value}};
end
Thanks in advance.

Concatenations can only handle fixed width expressions. You can do this with a for-loop:
always_comb begin
N= full - data_len ;
output = '0;
for(int i = 0; i < N; i++)
output |= value << i * $bits(value);
end

Related

.sum() and .max() not included in Systemverilog?

Why does the error say sum/max "is not declared under this prefix"? I thought Systemverilog had these array reduction functions included. Do I need to add a library or something to use them?
Code below:
module compare_block (clk, result, data, led);
parameter taps = 50; //number of fir filter taps
parameter data_width = 8; //width of data input including sign bit
parameter coeff_width = 32; //width of coefficients including sign bit
parameter size = 4096;
input clk;
input [(data_width + coeff_width + $clog2(taps) - 1):0] result; //from filter
input [(data_width-1):0] data; //precalculated 1 Hz sine wave
output led;
reg [(data_width + coeff_width + $clog2(taps) - 1):0] filt_sig;
reg [(data_width-1):0] comp_sig;
reg [(data_width-1):0] ans_sig;
integer i;
integer ii;
integer sum_array;
integer array_avg;
always #(posedge clk)
begin
filt_sig [(data_width + coeff_width + $clog2(taps) - 1):0]<= result[(data_width + coeff_width + $clog2(taps) - 1):0];
comp_sig [(data_width-1):0]<= data[(data_width-1):0];
end
always #(*)
begin
for (i=0; i < size; i=i+1)
ans_sig[i] = filt_sig[i] - comp_sig[i];
end
assign sum = ans_sig.sum(); //with (int'(item))
assign array_avg = sum >> 'd12; //dividing by 4096 (size) to get mean of signal deviation
integer max_array = ans_sig.max();
integer error_val = 0.5*max_array;
always #(*)
begin
if (array_avg < error_val) begin
led <= 'b1;
end else begin
led <= 'b0;
end
end
endmodule
The array reduction methods are defined for unpacked arrays. Instead of sum(), you can use $countones(ans_sig). I'm not sure what you are trying to compute with max(). Maybe you meant to declare ans_sig as an unpacked array.

Iterate numbers within an fprintf

I have the following code in MATLAB. I want to iterate numbers 1, 2, and 3 sequentially in the filename(%d) section of the code such that if I turn on all tracks, each if statement will print filename(1), filename(2), filename(3). If I turn off B_track, A_track will print filename(1) and C_track will print filename(2). How can I iterate numbers within an fprintf so that filename(%d) prints out sequentially based on the tracks I turn on and off?
A_track = 1;
B_track = 0;
C_track = 1;
fid=fopen('test.txt','w');
if A_track ==1, i=1;
fprintf(fid,'\n\n');
fprintf(fid,[' filename(%d)=''test1'' \n'],i);
fprintf(fid,' idtrack(%d)=A_track \n',i);
end
if B_track ==1, i=2;
fprintf(fid,'\n\n');
fprintf(fid,[' filename(%d)=''test2'' \n'],i);
fprintf(fid,' idtrack(%d)=B_track \n',i);
end
if C_track ==1, i=3;
fprintf(fid,'\n\n');
fprintf(fid,[' filename(%d)=''test3'' \n'],i);
fprintf(fid,' idtrack(%d)=C_track \n',i);
end
fclose(fid);
I think this is what you intend to accomplish: i is set to 1 at the start, and for every item printed out, it is incremented by one. This way, no matter which tracks are on or off, the ones that are on will print with a sequential i.
A_track = 1;
B_track = 0;
C_track = 1;
fid = fopen('test.txt','w');
i = 1;
if A_track
fprintf(fid,'\n\n');
fprintf(fid,[' filename(%d)=''test1'' \n'],i);
fprintf(fid,' idtrack(%d)=A_track \n',i);
i = i+1;
end
if B_track
fprintf(fid,'\n\n');
fprintf(fid,[' filename(%d)=''test2'' \n'],i);
fprintf(fid,' idtrack(%d)=B_track \n',i);
i = i+1;
end
if C_track
fprintf(fid,'\n\n');
fprintf(fid,[' filename(%d)=''test3'' \n'],i);
fprintf(fid,' idtrack(%d)=C_track \n',i);
i = i+1;
end
fclose(fid);
I also changed your if A_track==1 to if A_track. I find this easier to read. You can use true and false values to define each of the track variables, if that makes more sense to you. But true and 1 are identical for all purposes.
For iteration of numbers the easiest trick is to use the mod() function.
You set the divider and that sets the size of the list you want to iterate over.
As mod() will return 0 you have to add 1 to it, as matlab indexes matrices starting at 1 and not 0. (most programming languages start at 0)
So let's say you have a for loop and you want to iterate over the numbers 1, 2 and 3. Then it would look something like this
for ii=0:10
nmbtoprint=mod(ii,3)+1;
fprintf(fid,[' filename=''test_%1'' \n'],nmbtoprint);
end
You don't need to use a for loop for every if statement as long as you have a general counter. For a general counter you can create any variable and just make sure that it updates (adds 1 wherever you need it to in the script).
i=1; %number at which you initiate your variable
if %check if true then do something
%run some piece of code
i=i+1; %increase the counter by 1
end
Also you can use a (cell) array.
idtoprint1=[0,1,10,100];
idtoprint2={'first','B','3rd'};
for ii=0:10
ida1=mod(ii,4)+1;
ida2=mod(ii,3)+1;
fprintf(fid,[' filename=''test_%i'' \n'],idtoprint1(ida1));
fprintf(fid,[' filename=''test_%s'' \n'],idtoprint2{ida2});
end

syntax error at "END LOOP;" part of WHILE loop in plpgsql

I am getting a syntax error when trying to define a function in plpgsql that I cannot explain. For some reason, this code will always fail with syntax error at or nor "LOOP":
CREATE OR REPLACE FUNCTION ST_Dilate(
in_geom GEOMETRY,
scale_factor FLOAT,
tol FLOAT DEFAULT 0.001,
guess FLOAT DEFAULT 1,
safety INTEGER DEFAULT 1000
)
RETURNS GEOMETRY AS
$$
DECLARE
step FLOAT = guess/2;
current_area FLOAT = ST_Area(ST_Buffer(in_geom, buff));
desired_area FLOAT = ST_Area(in_geom)*scale_factor;
dev FLOAT = (current_area-desired_area)/desired_area;
old_dev FLOAT;
safety_counter INTEGER = 0;
BEGIN
WHILE ABS(dev) > tol LOOP
IF safety_counter > safety THEN /* Can't find suitable distance after many iterations, terminate the function to prevent extreme hangs. */
RAISE NOTICE 'Could not find suitable buffer distance when dilating geom % after % iterations, NULL geometry returned instead. Consider adjusting "guess" parameter value or initial step size.', geom, safety;
RETURN NULL;
END IF;
safety_counter = safety_counter + 1;
/* Save the old deviation to be compared later to the new one later, calculate the current area and the new deviation from the desired area. */
old_dev = dev;
current_area = ST_Area(ST_Buffer(in_geom, guess));
dev = (current_area - desired_area) / desired_area;
IF dev < 0 THEN /* Current area is smaller than desired area, increase the buffer distance by the step. */
guess = guess + step;
ELSE IF dev > 0 THEN /* Current area is larger than desired area, decrease the buffer distance by the step. */
guess = guess - step;
ELSE /* Technically shouldn't ever happen because then ABS(dev) is indeed lesser than tol but here just in case. */
EXIT;
END IF;
IF dev * old_dev < 0 THEN /* Negative value indicates difference of sign, which means we just overestimated the area after underestimating it or vice versa, need to half the step. */
step = step * 0.5;
END IF;
END LOOP; /* syntax error here */
RETURN ST_Buffer(in_geom, guess);
END
$$
LANGUAGE plpgsql;
I don't see the syntax error at all. What is more confusing is that if I comment out this block:
IF safety_counter > safety THEN /* Can't find suitable distance after many iterations, terminate the function to prevent extreme hangs. */
RAISE NOTICE 'Could not find suitable buffer distance when dilating geom % after % iterations, NULL geometry returned instead. Consider adjusting "guess" parameter value or initial step size.', geom, safety;
RETURN NULL;
END IF;
safety_counter = safety_counter + 1;
the code executes once successfully, but then immediately fails with the same error the second time around.
I'm completely confused about this. I have commented out every block one at a time as well as individual lines trying to find the problem and I cannot find a syntax error anywhere, and yet it keeps complaining.
I'm on postgresql 9.6.
Use ELSIF if you want to get a single IF statement:
IF dev < 0 THEN /* Current area is smaller than desired area, increase the buffer distance by the step. */
guess = guess + step;
ELSIF dev > 0 THEN /* Current area is larger than desired area, decrease the buffer distance by the step. */
guess = guess - step;
ELSE /* Technically shouldn't ever happen because then ABS(dev) is indeed lesser than tol but here just in case. */
EXIT;
END IF;
Read in the documentation about Control Structures.
You are misssing END IF before END LOOP. See it simplified and intended:
IF dev < 0 THEN
guess = guess + step;
ELSE
IF dev > 0 THEN
guess = guess - step;
ELSE
EXIT;
END IF;
END IF; -- this is missing

Check Position with for loop, not enough input arguments - Matlab

I made a simple function that loops between the rows and columns of an array using for loops. The loop is part of a function named checktakentest (Since I'm testing this method atm). I keep getting the error that there aren't enough input arguments.
function [spotTaken] = checktakentest(tttArray)
for h = 1:3
if tttArray(h,j) == 1
%Is spot is taken, break loop
spotTaken = 1; break;
else
spotTaken = 0;
end
for j=1:3
if tttArray(h,j) == 1
spotTaken = 1; break;
else
spotTaken = 0;
end
end
end
I tried also defining h and j previously as follows
h = [1,2,3];
j = [1,2,3];
Note that tttArray is a global variable defined in another function and its array values change in that function. A spot taken is 1, empty is 0. What arguments should I pass to the function and how do I know which ones to pass since this has been a recurring problem for me? A simple explanation would be appreciated. Note that I call the function via
checktakentest(tttArray)
Just remove the first if clause - at that point you don't have j initialized to a value, so you can't use it, yet:
function [spotTaken] = checktakentest(tttArray)
for h = 1:3
for j=1:3
if tttArray(h,j) == 1
spotTaken = 1; break;
else
spotTaken = 0;
end
end
end
If you call your function like this: checktakentest(tttArray) with tttArray beeing a mxn-matrix with m>2 and n>2 you should not get an error.
If you call it like this: checktakentest you will get the error you described (not enough input arguments).

Storing the number of iterations of a nested loop in an array

I am relatively new to MATLAB and I am quite stuck in a specific problem.
I have an equation that I am trying to solve using a while loop. It works by guessing a certain parameter e_0 and filling it into the equation, until it converges. An example is found below, where the initial guessing value equals 100:
clear all
i=1;
e_0=100
e_1= e_0 + log(0.6) - log(exp(e_0)/(exp(e_0)+1))
while( i < 1e10 & abs((e_1 - e_0)) > 1e-12),
i = i + 1;
e_0=e_1;
e_1= e_0+log(0.6)-log(exp(e_0)/(exp(e_0)+1))
end
i
Now I would like the exact same procedure but then for multiple values of e_0 at the same time, e.g. 101, 102, 103 and so on, and count how many more iterations those will take. I reckon that I therefore need to put a for-loop for that. I thought something like this:
clear all
i=1;
for e_0 = 100:105
e_1= e_0+log(0.6)-log(exp(e_0)/(exp(e_0)+1))
while( i < 1e10 & abs((e_1 - e_0)) > 1e-12),
i = i + 1;
e_0=e_1;
e_1= e_0+log(0.6)-log(exp(e_0)/(exp(e_0)+1))
end
end
i
However, now all the iterations from the different guessing values are shown underneath each other, and I get a total of 1519 iterations. How can I for example store the number of iterations needed for every initial guessing value underneath each other into a variable?
I hope it is clear enough... Thank you!
How about this:
i = 0;
offset = 99;
for n = 1:6
e_0 = n + offset;
e_1 = e_0+log(0.6)-log(exp(e_0)/(exp(e_0)+1))
while( i < 1e10 & abs((e_1 - e_0)) > 1e-12),
i = i + 1;
This part needs to change to prevent e_0 to be redefined inside the loop:
e_1= e_1+log(0.6)-log(exp(e_1)/(exp(e_1)+1))
end
iterations(n)=i;
end
Note: it is not recommended to use i as a loop increment, since it redefines i used in complex numbers.