How to generate a synthesizable pseudo random generator from 1 to 52 System Verilog - system-verilog

Could someone explain how to create a pseudo number generator that has a range of 1 to 51 and can have its value placed within something like the for loop. This has to be in System Verilog and synthesizable. I have read about some CRC and LFSRs but was not quite sure how to modify them to fit it within the specified values I needed (1-52) and how to fit it within a for loop as most examples took up an entire module.
Thank you for your time.
initial begin
for(int i = 0; i < 52; i++) begin
int j = // insert PSEUDO RANDOM NUM GEN 0 to 51
if(array[j] == 0)begin
i = i-1;
continue;
end
else
array2[i] = array[j];
array[j] = 0;
end
end
(array and array2 both have 52 values of bit size 4)

I don't know what is your application, but what you could do is to generate numbers in the modular ring mod 53 (53 is a prime number). Since you did not mention any other requirement I will take the simplest generator I could imagine, that can be performed without multiplications and will generate numbers, 1 <= n < 52.
function [5:0] next_item(input logic [5:0] v);
if(v < 26) begin
next_item = (v << 1); // 2 * v % 53 = 2 * v
end
else if(v > 26) begin
// (2 * v) % 53 = (2 * v - 52 - 1) % 53 = 2 * (v - 26) - 1
next_item = (((v - 26) << 2) - 1);
end
else begin
// v = 26, you want to exclude 2 * v % 53 = 52, so we skip it
// by applying the next item again, and it will be
next_item = 51;
end
endfunction
And you could use it like this
parameter SEED = 20; // any number 1 <= N < 52 you like
initial begin
int j = SEED;
for(int i = 0; i < 52; i++) begin
if(array[j-1] == 0)begin
i = i-1;
continue;
end
else begin
array2[i] = array[k];
end
j = next_item(j);
end

Related

Matlab Prime number list checker

Ok so I have been having a go at creating a prime number checker. I have been successful in making it work for a specific number. The code is here.
#To test if number is prime
prompt = input("number to test if prime: ");
n = prompt;
i = 2; #start of mod test
t = floor(sqrt(n));
counter = 0;
tic
for i = 2:t
if mod(n,i) == 0
disp('n is not prime')
break
else
counter = (counter + 1);
end
end
if counter == t-1
disp('n is prime')
end
toc
I then tried to make a program which would test a range of numbers. It's been successful for n=10, but when I go higher than that it doesn't seem to pick up the primes. I'm not sure where I'm going wrong.
#Want to test numbers 2:n if they're prime
prompt = input("max number to test: ");
n = prompt;
l = 2; #start of mod test
counter = 0;
tic
for i = 2:n #cycle to test 2 up to n
t = floor(sqrt(i)) #Only need to test up to root of number
for l = 2:t
if mod(i,l) == 0
break
else
counter = (counter + 1);
end
end
if counter == t-1 # if tested up to the root of the number, it must be prime
prime = sprintf('%d is prime', round(i));
disp(prime)
counter = 0;
end
end
toc
Any help in getting it to work for larger values would be greatly appreciated and also any ways to make the code more efficient. The top program can test 982451653 in 0.268 seconds on my laptop.
Just a way to linearize your algorithm:
n = 997 %test number
t1 = n./([2,3:2:n/2]);
t2 = t1 - round(t1);
res = sum(t2 == 0); %can n be divided ?
if res == 0
fprintf('%s','prime');
else
fprintf('%s','not prime');
end
I got help on the issue and found that 'counter' was constantly re-setting and needed to be moved up. Fixed code is here
#Want to test numbers 2:n if they're prime
prompt = input("max number to test: ");
n = prompt;
l = 2; #start of mod test
counter = 0;
tic
for i = 2:n #cycle to test 2 up to n
t = floor(sqrt(i)); #Only need to test up to root of number
counter = 0;
for l = 2:t
if mod(i,l) == 0
break
else
counter = (counter + 1);
end
end
if counter == t-1; # if tested up to the root of the number, it must be prime
prime = sprintf('%d is prime', round(i));
disp(prime)
end
end
toc

Only allow fixed number of random points in each tile

Following up on a previous question, I have code that I think should limit the number of randomly generated points in each quadrant of the total tile; however, it is not working.
n = 4;
used = [];
k = 0;
a1_count = 0;
a2_count = 0;
a3_count = 0;
a4_count = 0;
min = 1;
max = 1;
while k<n
x = rand*2;
y = rand*2;
notvalid = 0;
if (0 <= x) && (x <= 1) && (0 <= y) && (y <= 1)
a1_count = a1_count + 1;
end
if (1 < x) && (x <= 2) && (0 <= y) && (y <= 1)
a2_count = a2_count + 1;
end
if (0 <= x) && (x <= 1) && (1 < y) && (y <= 2)
a3_count = a3_count + 1;
end
if (1 < x) && (x <= 2) && (1 < y) && (y <= 2)
a4_count = a4_count + 1;
end
%%%
if (min <= a1_count) && (a1_count <= max) && (min <= a2_count) && (a2_count <= max)...
&& (min <= a3_count) && (a3_count <= max) && (min <= a4_count) && (a4_count <= max)
notvalid=1;
end
if notvalid
continue
end
used(end+1,:) = [x;y];
k = k+1;
end
I wish to generate 4 random points, and have one in each quadrant of the total area. To do this, I have a maximum and minimum number of points in each quadrant (in this case 1), and an if statement to check that the count for each tile falls within the min and max. If it doesn't, then notvalid = 0 and the loop should begin again. This function doesn't seem to work however, as the loop finishes with 4 points total and is completely random (all the counts should = 1).
Can anyone spot where I'm going wrong?
I may be missing something, but the easiest approach would probably be something like
Select N random numbers within the x/y range of the first grid cell
Repeat for all grid cells
Here is some basic code that should create N random x/y points per grid cell
% Define the grid (for demonstration purposes)
dx = 1; dy = 1;
xrange = 0:dx:2;
yrange = 0:dy:2;
% Number of points per cell
N = 1;
[lowerx, lowery] = meshgrid(xrange(1:end-1), yrange(1:end-1));
% Store all those random numbers in a cell
data = cell(size(lowerx));
for k = 1:numel(lowerx);
% Generate 4 random points within the x/y range
xcoord = (rand(N, 1) * dx) + lowerx(k);
ycoord = (rand(N, 1) * dy) + lowery(k);
data{k} = [xcoord, ycoord];
end
disp(data)
data =
[1x2 double] [1x2 double]
[1x2 double] [1x2 double]
EDIT
To address your question directly using the code that you have provided, the logic in the code in your question is a little wonky. I have rewritten your while loop to be a little clearer so we can talk through it.
while k < n
x = rand * 2;
y = rand * 2;
if y >= 0 && y < 1
if x >= 0 && x < 1
a1_count = a1_count + 1;
else
a2_count = a2_count + 1;
end
else
if x >= 0 && x < 1
a3_count = a3_count + 1;
else
a4_count = a4_count + 1;
end
end
counts = [a1_count, a2_count, a3_count, a4_count];
notValid = all(counts >= minimum) && all(counts <= maximum);
if notValid
continue;
end
used(end+1,:) = [x;y];
k = k+1;
end
So the biggest thing is your notValid check. If you actually look at what you're checking (that all your *_count variables are within the pre-specified limits), I believe that if all of those conditions are true, then the current point is valid; however you state just the opposite.
Then you basically say, that if the current x y is valid, then add it to the used list. Well this logic is fine except that you define validity backwards as I stated before.
Ok so that aside, let's look at when you think that a point is not valid. Well, then you (correctly) go to the next iteration, but you never decrement the *_count variable. So say you had 1 point in quadrant 1 already and the second iteration through the loop it's in quadrant 1 again. Well you'd add 1 to a1_count and then see that it isn't valid (a1_count exceeds max) and go to the next loop, but a1_count stays at 2 despite really only having 1 because you just rejected it.
Now, all of that aside. Let's consider the first time through your loop and look at your validity check. Since you only add one point. Your validity check can never pass (if implemented correctly) because all *_count variables except the one that was just incremented will be less than the min.
So I think what happened is you probably did the validity check correctly at first, ended up with an infite while loop, and then negated that check, didn't get an infinite loop, but as a result got an incorrect solution.
The solution that you are getting currently, is literally the first 4 times through the while loop due to the incorrect logic.
If you really like your current approach, we can clean up the code to be correct.
n = 4;
used = zeros(0,2);
minimum = 1;
maximum = 1;
counts = [0 0 0 0];
while true
x = rand * 2;
y = rand * 2;
if y >= 0 && y < 1
if x >= 0 && x < 1
quadrant = 1;
else
quadrant = 2;
end
else
if x >= 0 && x < 1
quadrant = 3;
else
quadrant = 4;
end
end
% Check to see if we can even add this point
if counts(quadrant) + 1 > maximum
continue;
end
counts(quadrant) = counts(quadrant) + 1;
used = cat(1, used, [x, y]);
isComplete = all(counts >= minimum & counts <= maximum) && ...
size(used, 1) == n;
if isComplete
break
end
end

Smallest integer greater than or equal to harmonic series of input

I'm working on the following problem:
I realize my code is a bit off, but I want to create a for loop that will determine whether or not the integer x (the input value) is at least less than or equal to the sum of a harmonic series.
Here is what I have so far:
function n =one_per_n(x)
if x > 10000
n = -1;
end
total = 0;
i = 0;
for i = 1:10000
if x >= total
n = ceil(total);
else
total = (1/i) + total;
end
end
I've added my attempt at a while loop. I realize it's wrong, but any help would be appreciated.
function n =one_per_n(x)
if x > 10000
n = -1;
end
total = 0;
i = 0;
for i = 1:10000
while total <= x
total = (1/i) + total;
end
end
n = total;
you don't need to use some loops:
function n = one_per_n(x)
lim = min(10000,exp(x));
value = cumsum(1./(1:lim));
n = find(value >= x,1);
if isempty(n)
n = -1;
end
A while loop is a better option in this case I think
function [total, n] = one_per_n(x)
% This is a good initial check, good work
if x > 10000
n = -1;
return;
end
% Initialize the variables
total = 0;
n = 0;
% While not finished
while (total < x)
% Number of terms
n = n + 1;
total = total + 1/n;
end
end

matlab: convert a string of hex values to a decimal value?

I wrote functions to convert 100,000 hex strings to values, but it takes 10 seconds to perform on the whole array. Does Matlab have a function to do this, so that it is faster, ... ie: less than 1 second for the array?
function x = hexstring2dec(s)
[m n] = size(s);
x = zeros(1, m);
for i = 1 : m
for j = n : -1 : 1
x(i) = x(i) + hexchar2dec(s(i, j)) * 16 ^ (n - j);
end
end
function x = hexchar2dec(c)
if c >= 48 && c <= 57
x = c - 48;
elseif c >= 65 && c <= 70
x = c - 55;
elseif c >= 97 && c <= 102
x = c - 87;
end
Try using hex2dec. It should be faster much faster than looping over each character.
shoelzer's answer is obviously the best.
However, if you want to do the conversion by yourself, then you might find this useful:
Assuming s is a char matrix: all hex numbers are of the same length (zero padded if necessary) and each row has a single number. Then
ds = double( upper(s) ); % convert to double
sel = ds >= double('A'); % select A-F
ds( sel ) = ds( sel ) - double('A') + 10; % convert to 10 - 15
ds(~sel) = ds(~sel) - double('0'); % convert 0-9
% do the sum through vector product
v = 16.^( (size(s,2)-1):-1:0 );
x = s * v(:);

Matlab error : Subscript indices must either be real positive integers or logicals

I have the following error in MATLAB:
??? Subscript indices must either be real positive integers or
logicals.
Error in ==> Lloyd_Max at 74 D(w_count) = mean((x -
centers(xq)).^2);
This is my code :
function [ xq,centers,D ] = Lloyd_Max( x,N,min_value,max_value )
%LLOYD_MAX Summary of this function goes here
% Detailed explanation goes here
x = x';
temp = (max_value - min_value)/2^N;
count=1;
for j=0:temp:((max_value - min_value)-temp),
centers(count) = (j + j + temp )/2;
count = count + 1;
end
for i=1:length(centers),
k(i) = centers(i);
end
w_count = 0;
while((w_count < 2) || (D(w_count) - D(w_count - 1) > 1e-6))
w_count = w_count + 1;
count1 = 2;
for i=2:(count-1),
T(i) = (k(i-1) + k(i))/2;
count1 = count1 +1 ;
end
T(1) = min_value;
T(count1) = max_value;
index = 1;
for j=2:count1,
tempc = 0;
tempk = 0;
for k=1:10000,
if(x(k) >= T(j-1) && x(k) < T(j))
tempk = tempk + x(k);
tempc = tempc + 1;
end
end
k(index) = tempk;
k_count(index) = tempc;
index = index + 1;
end
for i=1:length(k),
k(i) = k(i)/k_count(i);
end
for i=1:10000,
if (x(i) > max_value)
xq(i) = max_value;
elseif (x(i) < min_value)
xq(i) = min_value;
else
xq(i) = x(i);
end
end
for i=1:10000,
cnt = 1;
for l=2:count1,
if(xq(i) > T(l-1) && xq(i) <= T(l))
xq(i) = cnt;
end
cnt = cnt +1 ;
end
end
D(w_count) = mean((x - centers(xq)).^2);
end
end
and i call it and have these inputs :
M = 10000
t=(randn(M,1)+sqrt(-1)*randn(M,1))./sqrt(2);
A= abs(t).^2;
[xq,centers,D] = Lloyd_Max( A,2,0,4 );
I tried to comment the while and the D, Results :
I got the xq and the centers all normal, xq in the 1-4 range, centers 1-4 indexes and 0.5-3.5 range.
I dont know whats going wrong here...Please help me.
Thank in advance!
MYSTERY SOVLED!
Thank you all guys for your help!
I just putted out of the while the for loop :
for i=1:10000,
if (x(i) > max_value)
xq(i) = max_value;
elseif (x(i) < min_value)
xq(i) = min_value;
else
xq(i) = x(i);
end
end
and it worked like charm.... this loop was initilizing the array again. Sorry for that. Thank you again!
There is an assignment xq(i) = x(i) somewhere in the middle of your function, but you pass A as x from outside where you calculate A from t which is sampled by randn, so you can't promise xq is an integer.
I'm not sure exactly what you are aiming to do, but your vector xq does not contain integers, it contains doubles. If you want to use a vector of indices as you do with centers(xq), all elements of the vector need to be integers.
Upon a little inspection, it looks like xq are x values, you should find some way to map them to the integer of the closest cell to which they belong (i'm guessing 'centers' represents centers of cells?)