How to cope with the error of the following piece of system verilog code? - system-verilog

schematic
I would like to write system verilog code to implement this schematic (using 3 2:4 decoder and 64 3-input and gate to achieve a 6:64 decoder), and the following is my piece of code:
module Ex4( input logic [5:0] D,
output logic [63:0] y
);
genvar i;
genvar j;
genvar k;
integer n = 0;
logic [3:0] y1, y2, y3;
dec2 d1(D[1:0], y1);
dec2 d2(D[3:2], y2);
dec2 d3(D[5:4], y3);
generate
begin
for(i = 0; i < 3; i = i + 1) begin:flp1
for (j = 0; j < 3; j = j + 1) begin:flp2
for(k = 0; k < 3; k = k + 1) begin:flp3
and3_new a_n(y1[i], y2[j], y3[k], y[n]);
n=n+1; // error message comes from this line
end
end
end
end
endgenerate
endmodule
Note: "dec2" and "and3_new" are two modules written in advance with no problems
However, I got the following error during compilation, can anybody give me some hint? Thank you.
Error (10170): Verilog HDL syntax error at Ex4.sv(22) near text: "=";
expecting ".", or "(". Check for and fix any syntax errors that appear
immediately before or at the specified keyword. The Intel FPGA
Knowledge Database contains many articles with specific details on
how to resolve this error. Visit the Knowledge Database at
https://www.altera.com/support/support-resources/knowledge-
base/search.html and search for this specific error message number.

You can't put a procedural assignment statement in that position. Instead of [n], use [i*16+j*4+k]. You can also do
module Ex4( input logic [5:0] D,
output logic [63:0] y
);
logic [3:0] y1, y2, y3;
dec2 d1(D[1:0], y1);
dec2 d2(D[3:2], y2);
dec2 d3(D[5:4], y3);
for(genvar i = 0; i < 4; i++) begin:flp1
for (genvar j = 0; j < 4; j++) begin:flp2
for(genvar k = 0; k < 4; k = k + 1) begin:flp3
parameter n = i*16+j*4+k;
and3_new a_n(y1[i], y2[j], y3[k], y[n]);
end :flp3
end : flp2
end : flp1
endmodule

Related

Bit slicing with variable width in SystemVerilog

I am trying to access certain sections of an array using the +: operator however getting the infamous [variable] is not a constant error. The only problem is, the width I would like the get from the array is changing as well.
This is the loop I have:
logic [N-1:0] a;
logic [2**N-2:0] b;
for (i = 0; i < N; i++)
a[i] = b[(2**i)-1 +: 2**i] == {(2**i){1'b1}};
In other words, if N = 4, I want this loop to do this:
a[0] = b[0:0] == 1'b1;
a[1] = b[2:1] == 2'b11;
a[2] = b[6:3] == 4'b1111;
a[3] = b[14:7] == 8'b11111111;
Logically, I'm pretty certain that the loop I provided works however SystemVerilog doesn't allow non-constants to be used for setting the width (after the a:).
How can I utilize the +: operator when my starting index and width are both dependent on a non-constant variable? or is there another way of doing this considering that N can be a large number.
Thanks!
EDIT:
This can be done with shifts, here is a working code:
for (i = 0; i < N; i++)
a[i] <= ((b >> (2**i)-1) << ((2**N) - (2**i) - 1)) ==
{(2**N-1){1'b1}} << ((2**N) - (2**i) - 1);
You cannot use +: with variable widths. It is actually just a short-hand for shifts and masks. For example, something like the following should work in your case:
logic [N-1:0] a;
logic [2**N-2:0] b;
always_comb begin
for (int i = 0; i < N; i++) begin
logic [2**N-2:0] tmpb, tmp1;
tmpb = b >> ((2**i)+1);
tmp1 = ((2**N)'(1) << (2**i)) - 1;
a[i] = (tmpb & tmp1) == 0;
end
end
you just need to figure out exact numbers of shifts and widths.
You can use a combination of '+:` operator with a mask
parameter N = 8; localparam N2 = 2**(N-1);
logic [N-1:0] a;
logic [2**N-1:0] b;
initial begin
b ={8'b000001,4'b1111,2'b01,1'b1};
for (int i = 0; i < N; i++)
a[i] = (b[(2**i)-1 +: N2] | ~N2'((1 << 2**i)- 1)) == '1;
$displayb(a,,b);
end
You can use +: provided that the right hand side is a constant or genvar.
logic [N-1:0] a;
logic [2**N-2:0] b;
for (genvar i = 0; i < N; i++) begin : gen_a
assign a[i] = b[(2**i)-1 +: 2**i] == {(2**i){1'b1}};
end
Note that this for-loop is a generate-for-loop which is not within a procedural block (ie begin-end)

Integrating over a constant function

I am trying to integrate over a constant function in MATLAB 2017a, but I am stuck. First of all when I integrate using the following script, I get the right output. So the script works for a x0 which depends on t.
function E=sol(n,k)
x0 = #(t) t^(2);
j = 0;
E = zeros(n,1);
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
E(j+1,1) = subs(sprintf('x%d',j+1))
j = j+1;
end
end
Where function po(j,k) is as follows,
function A_j = po(j,k) % Adomian polynomials
if j >0
x = sym('x',[1 j]);
syms p; % Assinging a symbolic variable for p
syms x0;
S = x0+ sum(p.^(1:j) .* x) ; % Sum of p*x up to order j
Q =f(S,k); % Taking the k-th power of S, i.e.
A_nc = diff(Q,p,j)/factorial(j); % Taking the j-th order derivative
A_j = subs(A_nc,p,0) ; % Filling in p=0
else
syms x0;
S = x0;
A_j =f(S,k); % Taking the k-th power of S,
end
end
And where f(x,k) is,
function F = f(x,k) % Nonlinear function of k power
F = x^k ;
end
Now when I cal sol(n,k) it does work. But when I try to change my x0 function in sol(n,k) in a constant function like,
function E=solcon(n,k)
x0 = #(t) 2.*ones(size(t));
j = 0;
E = zeros(n,1);
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
E(j+1,1) = subs(sprintf('x%d',j+1))
j = j+1;
end
end
It does not work, As you can see I added *ones(size(t)); just to make it a function of t. But unfortunately it still doesn't work when I call,
K = matlabFunction(subs(po(j,k))) ;
I get,
#()4.0
And then I get an error when I call,
eval(sprintf('x%d = integral(K,0,1);',j+1))
Could anyone help me out trying to integrate over a constant?
The error I get when I call solcon(10,2) is
Error using symengine>#()4.0
Too many input arguments.
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 132)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 75)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 88)
Q = integralCalc(fun,a,b,opstruct);
Error in solcon1 (line 7)
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
EDIT 2
I used the following script,
function E=solcon(n,k)
x0 = #(t) 2.*ones(size(t));
j = 0;
E = zeros(n,1);
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
fstr= func2str(K)
if fstr(3) == ')';
x{j+1} = K*(1-0)
else x{j+1} = integral(K,0,1)
end
E(j+1,1) = subs(x{j+1},1);
j = j+1
end
end
But the following error occurs,
Undefined operator '*' for input arguments of type 'function_handle'.
Error in solcone1 (line 9)
x{j+1} = K*(1-0);
I am going to ignore the terrible choice of using eval, especially when you can do
x{j+1} = integral(K,0,1);
Read more on why dynamic variables and eval are terrible
Your problem is that matlabFunction is a smartass. When it detects that your function does not have any dependency to x, it gives you a function with empty input arguments #()4.0. As you see, integral does not like that.
A way of solving the problem is detecting this before calling integral. You could check if it has input arguments, and if it does not, then evaluate the integral "by hand"
...
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
fstr=func2str(K);
if fstr(3)==')'
x{j+1}=K()*(1-0); % evaluate the integral yourself
else
x{j+1} = integral(K,0,1);
end
E(j+1,1) = subs(x{j+1});
j = j+1;
end
...
The problem is considerably more difficult that I though I was. Either rewrite the entire thing, or using eval:
...
while j < n+1 ;
K = matlabFunction(subs(po(j,k))) ;
fstr=func2str(K);
if j==0
eval(sprintf('x%d = K()*(1-0);;',j+1)) ;
else
eval(sprintf('x%d = integral(K,0,1);',j+1)) ;
end
E(j+1,1) = subs(sprintf('x%d',j+1));
j = j+1;
end
...

Modeling skewed delay for combinational logic

I need help to model a block with different delays for various input-output paths?
input A;
input [3:0] B, C;
output [3:0] Y;
Y = B xor C if A = 1 else Y = 0
with A->Y delay of 10us when posedge A (rise delay) and 5us when negedge A(fall delay)
and B,C - > Y delay is 1us (applicable only if A = 1)
For my case, I might need to use procedural way and assign statements might not suit.
Here is something that worked best for me.
`timescale 1us/1ns
module xor_w_enabled(input A, input B, input C, output Y);
wire A_delayed;
wire B_xor_C_delayed;
assign #1 B_xor_C_delayed = B^C;
assign #(10,5) A_delayed = A;
assign Y = (A_delayed == 1) ? B_xor_C_delayed : 0;
endmodule
Please let me know if I'm missing anything.
For non-synthesizable models you can use #delay constructs combined with `timescale to model delays. something like the following code
`timescale 1us/1us
module delayModule(A,B,C,Y);
input A;
input [3:0] B, C; // this should probably be output
output [3:0] Y;
reg [3:0] tmpb, tmpy;
always #(posedge A)
#10us tmpb <= 1;
always #(negedge A)
#5us tmpb <= 0;
always #* begin
if (A == 1)
#1us tmpy =(B^C);
end
assign B = tmpb;
assign Y = tmpy;
endmodule // delayModule

Plotting bisect method in matlab

So I had a problem in which I needed to find roots using the bisect method:
Function:
function [ c,k ] = bisect(f,a,b,tol)
k=0;
while b-a > tol
c=(a+b)/2;
if sign(f(c)) == sign(f(b))
b=c;
else
a=c;
end
k=k+1;
end
Script:
f = #(x) (((1800).*log((160000)./(160000 - (x.*2600))) - (9.812).*x)./750) - 1;
a = 10;
b = 50;
tol = 1e-4;
[root, iter] = bisect(f,a,b,tol);
fprintf(' iterations = %i root = %15.10e ' ,iter, root);
This works perfectly, now I need to use an embedded function in Matlab to find the value of c for different values of q (in the above example q is a fixed number 2600) from 2000 to 3000 in increments of 10 and plot x vs q. In order to do this I have the following script:
function myFunction
h = 10;
a = 10;
b = 50;
tol = 1e-4;
function y = f(x)
y = (((1800).*log((160000)./(160000 - (x.*q))) - (9.812).*x)./750) - 1;
end
for q = (2000:h:3000)
k=0;
while b-a > tol
c=(a+b)/2;
if sign(f(c)) == sign(f(b))
b=c;
cArray(q) = c;
else
a=c;
cArray(q) = c;
end
k=k+1;
end
end
plot(q,cArray)
end
This code has no errors but when I run it there is no graph. Can someone please help me with this issue? I don't even know if my code to find c vs q is correct.
Major issues with your myFunction code:
The endpoints a,b should be reset within the for loop, so that the root search begins anew.
Using q as index in cArray(q) results in a too-large array filled with zeros for indices below 2000. You need an index variable to keep track of that array. (I used j below)
plot(q,cArray) should be plot(2000:h:3000,cArray), because q is not an array, it's a scalar.
Minor issues:
You never used k
You assign to cArray(q) within the while loop; this only needs to be done once the loop has ran.
Corrected function:
function myFunction
h = 10;
tol = 1e-4;
function y = f(x)
y = (((1800).*log((160000)./(160000 - (x.*q))) - (9.812).*x)./750) - 1;
end
j = 0;
for q = 2000:h:3000
a = 10;
b = 50;
while b-a > tol
c=(a+b)/2;
if sign(f(c)) == sign(f(b))
b=c;
else
a=c;
end
end
j=j+1;
cArray(j)=c;
end
plot(2000:h:3000,cArray)
end
and its output:

Cannot execute *quick sort* script in matlab (from Engineering Computation with matlab book - Smith)

The script lies on page 438 of the book, 2nd edition. Here it is:
function a = quicksort(a, from, to)
clear, clc, close all
if (from < to)
[a p] = partition(a, from, to);
a = quicksort(a, from, p);
a = quicksort(a, p+1, to);
end
function [a lower] = partition(from,to)
pivot = a(from); i = from - 1; j = to + 1;
while (i<j)
i = i + 1;
while lt(a(i),pivot)
i = i + 1;
end
j = j - 1;
while gt(a(j), pivot)
j = j - 1;
end
if (i<j)
temp = a(i);
a(i) = a(j);
a(j) = temp;
end
end
lower = j;
a
I fail to execute the script to see the result and I keep receiving the following error (even if I modify the inputs):
??? Error using ==> quicksort>partition
Too many input arguments.
Error in ==> quicksort at 9
[a p] = partition(a, from, to);
Can someone please help me? I'm very interested in these Matlab sorting techniques. Thanks.
You should never call clear all, clc, close all inside a function. You shouldn't even call it from inside a script, in my opinion.
Also, the call to partition has too many input arguments, as the error says. In fact, the function partition should be defined as partition(a, from, to), instead of partition(from,to).