I'm trying to output the result of some multiplications and adders. As far as I can tell I've coded everything correctly (system compiles, seems consistent with examples I've seen) but it doesn't output the values of any assigned/calculated variables. Clearly there is something wrong or missing.
I've pasted my code below:
module multiplier_4x4(
logic [1:0] a,b,
output logic [3:0] c,
logic [3:0] p,
input logic cin = 0,
output logic cout = 0
);
assign a = 2'b11;
assign b = 2'b11;
assign c[0] = a[0] & b[0];
fulladder FA1(a[1]&b[0], a[0]&b[1], 1'b0, c[1], p[0]);
fulladder FA2(b[1]&a[1], 1'b0, cin, c[2], p[1]);
assign c[3] = p[1];
initial begin
$display("Output %d", c[1]);
$display("Output %d", c);
$display("Output %d", a);
$display("Output %d", a[0]);
$display("Output %d", 1'b1);
end
endmodule
module fulladder(input logic a, b, cin,
output logic s, cout);
wire p, g;
assign p = a ^ b;
assign g = a & b;
assign s = p ^ cin;
assign cout = g | (p & cin);
endmodule
The display lines output the following (in order of appearance):
x
x
x
x
1
I would have expected the x values to represent actual numbers/variables. Where did I go wrong?
The simulation in the post does nothing because it was running for 0 time.
Make this change so that it runs for at least a single time step before displaying the results:
initial begin
#1;
$display("Output %d", c[1]);
$display("Output %d", c);
$display("Output %d", a);
$display("Output %d", a[0]);
$display("Output %d", 1'b1);
end
Produces:
# Output 0
# Output 5
# Output 3
# Output 1
# Output 1
Related
I have been trying to implement Montogomery Modular Reduction in Verilog and encountered an error while doing so. Attaching the code below-
module MMM ( a , b , c , y ) ;
// Parameters
//
parameter N = 32 ; // Default value of N
// Inputs
//
input [N-1:0] a ; // N-bit input a
input [N-1:0] b ; // N-bit input b
input [N-1:0] c ; // N-bit input c
// Outputs
//
output [N-1:0] y ; // N-bit output y
// Internal nets
//
wire [N-1:0] q ; // N-bit q array
//wire [N+1:0] t [0:N-1] ; // (N+2)-bit temporary iteration variable t, bus array of N
wire [N+1:0] s ; //
// Initial value of S
//
assign s[0] = 0 ;
// Iteration
//
genvar i ;
generate
for ( i = 0 ; i <= N-1 ; i = i + 1 )
begin : iterate
assign q[i] = (s[i] + a[i] * b) % 2;
assign s[i+1] = (s[i] + q[i] * c + a[i] * b) / 2;
if (s[N] >= c)
assign y = s[N] - c ;
else
assign y = s[N] ;
end // iterate
endgenerate
//assign MMM[a, b, c] = y;
endmodule
The error- The generate if condition must be a constant expression.
Any help would be great.
Thanks
The problem is that if inside a generate must be decidable at compilation time, you are using a signal as a condition of the if block. I understand that what you mean is to create a mux with that expression in the selector, but the compiler don't.
you could wrap the iterate logic in a procedural always block and then you would be able to use the if statement.
Also, the assignment to y should be outside the iterate block, otherwise it will have multiple drivers.
Fixing these two problems you have
module MMM ( a , b , c , y ) ;
// Parameters
//
parameter N = 32 ; // Default value of N
// Inputs
//
input [N-1:0] a ; // N-bit input a
input [N-1:0] b ; // N-bit input b
input [N-1:0] c ; // N-bit input c
// Outputs
//
output [N-1:0] y ; // N-bit output y
// Internal nets
//
wire [N-1:0] q ; // N-bit q array
//wire [N+1:0] t [0:N-1] ; // (N+2)-bit temporary iteration variable t, bus array of N
wire [N+1:0] s ; //
// Initial value of S
//
assign s[0] = 0 ;
// Iteration
//
genvar i ;
generate
for ( i = 0 ; i <= N-1 ; i = i + 1 )
begin : iterate
assign q[i] = (s[i] + a[i] * b) % 2;
assign s[i+1] = (s[i] + q[i] * c + a[i] * b) / 2;
end // iterate
endgenerate
assign y = s[N] >= c ? s[N] - c : s[N];
//assign MMM[a, b, c] = y;
endmodule
Disclaimer: Maybe there are more errors, I did not notice.
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
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
2 questions
in the system verilog 2012 reference guide there is a reference to coding a sequential logic in an always_comb, is this possible since there is no clocking reference for an always_comb block - as seen here -> [sequential logic in always_comb]
while using system verilog assertion in Synopsys Verdi, is it possible that the green arrow(indicating the asserted property is satisfied) to be fired half or once clock cycle later, after the property being satisfied
Thanks :D
Regarding question 1. non-blocking assignments don't necessarily imply sequential behavior. Blocking/non-blocking assignments are a simulation construct. Let's look at a small example to understand it better:
module some_gate(
input logic a,
input logic b,
output logic c,
output logic d
);
// c is 'a or b'
// d is 'a and c'
endmodule
We have two input signals and two output signals. We want to model a composite gate.
In classical Verilog style, we would write the following:
always #(a or b) begin
c = a || b;
d = a && c;
end
This means, whenever a or b changes, compute the values of c and of d. Because we used a blocking assignment for c, the value we computed here gets "propagated" to the computation of d. This essentially means that we've chained the logic described by d to come after the logic for c.
We can test this using a little testbench:
module test;
logic a, b, c, d;
some_gate dut(.*);
always #(a or b or c or d)
$display("[%0d] a = %b, b = %b, c = %b, d = %b", $time(), a, b, c, d);
initial begin
#1 a = 1;
#1 b = 1;
#1 a = 0;
#1 $finish();
end
endmodule
If we simulate this, we'll get:
[1] a = 1, b = x, c = x, d = x
[1] a = 1, b = x, c = 1, d = 1
[2] a = 1, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 0
This is because the display process triggers once for each change of the variables. a gets changed from x to 1, but c haven't been updated yet. Then c and d get updated in the same time step. Later on, we change b, but this doesn't trigger any changes on c or d. Then, we change a again and later in the same time slice, d gets updated.
It's a bit redundant to have to specify the sensitivity list, since if we know that we want combinatorial logic, we should re-trigger the process whenever something on the right hand side of an assignment changes. This is what always_comb is for.
We can re-write our code using always_comb, by just getting rid of the sensitivity list:
always_comb begin
c = a || b;
d = a && c;
end
Running this code will lead to the same prints:
[1] a = 1, b = x, c = x, d = x
[1] a = 1, b = x, c = 1, d = 1
[2] a = 1, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 0
Now comes the interesting part. We can model the exact same circuit using always_comb and non-blocking assignments:
always_comb begin
c <= a || b;
d <= a && c;
end
Running this code, though, will produce slightly different prints:
[1] a = 1, b = x, c = x, d = x
[1] a = 1, b = x, c = 1, d = x
[1] a = 1, b = x, c = 1, d = 1
[2] a = 1, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 1
[3] a = 0, b = 1, c = 1, d = 0
Notice that in the first time step we have 3 prints, instead of one. Let's look closer at what happens here. First, we change a, but c and d haven't been updated yet. Second, c gets updated, but d stays the same. This is because of the non-blocking assignment on c, leading to d "seeing" the "old" value of c. Third, after c was officially updated, the tool schedules an update on d and we see the last print for the first time step. The rest is the same as in the previous cases.
Remember from a previous paragraph that always_comb re-triggers whenever something on the right hand side of an assignment changes. The trick here is that this always_comb actually behaves like:
always #(a or b or c) begin
c <= a || b;
d <= a && c;
end
This is non-standard Verilog, but would still model the same logic. Notice that c has been explicitly added to the sensitivity list. If we omit this, then we'd be describing a latch. This style is discouraged, because it's easy to get wrong (i.e. forget to add intermediate logic nodes to the sensitivity list).
The key takeaway point here is that blocking or non-blocking assignments don't either describe sequential or combinatorial logic. It's the entire context (i.e. the sensitivity lists that determine when they get executed) that controls what logic circuit gets inferred from the code.
The full code example is available on EDAPlayground.
Regarding question 2. this is tool specific and this isn't the forum for this. You should ask this on the vendor's website.
I just downloaded Cula and I want to use it's implemented functions for solving system of linear equation I looked into Examples Directory and I saw below code but it's very confusing when they want to obtain X solution of A*X=B they just copy B in X and since A is identity diagonal matrix so the answer IS, "B" and in this line of code nothing happens
status = culaSgesv(N, NRHS, A, N, IPIV, X, N);
(changing X to B didn't help!)
would you please tell me whats going on? Please tell me how can I get the answer "X" from this?
if anyone need any further information please just tell me.
#ifdef CULA_PREMIUM
void culaDoubleExample()
{
#ifdef NDEBUG
int N = 4096;
#else
int N = 780;
#endif
int NRHS = 1;
int i;
culaStatus status;
culaDouble* A = NULL;
culaDouble* B = NULL;
culaDouble* X = NULL;
culaInt* IPIV = NULL;
culaDouble one = 1.0;
culaDouble thresh = 1e-6;
culaDouble diff;
printf("-------------------\n");
printf(" DGESV\n");
printf("-------------------\n");
printf("Allocating Matrices\n");
A = (culaDouble*)malloc(N*N*sizeof(culaDouble));
B = (culaDouble*)malloc(N*sizeof(culaDouble));
X = (culaDouble*)malloc(N*sizeof(culaDouble));
IPIV = (culaInt*)malloc(N*sizeof(culaInt));
if(!A || !B || !IPIV)
exit(EXIT_FAILURE);
printf("Initializing CULA\n");
status = culaInitialize();
checkStatus(status);
// Set A to the identity matrix
memset(A, 0, N*N*sizeof(culaDouble));
for(i = 0; i < N; ++i)
A[i*N+i] = one;
// Set B to a random matrix (see note at top)
for(i = 0; i < N; ++i)
B[i] = (culaDouble)rand();
memcpy(X, B, N*sizeof(culaDouble));
memset(IPIV, 0, N*sizeof(culaInt));
printf("Calling culaDgesv\n");
DWORD dw1 = GetTickCount();
status = culaDgesv(N, NRHS, A, N, IPIV, X, N);
DWORD dw2 = GetTickCount();
cout<<"Time difference is "<<(dw2-dw1)<<" milliSeconds"<<endl;
if(status == culaInsufficientComputeCapability)
{
printf("No Double precision support available, skipping example\n");
free(A);
free(B);
free(IPIV);
culaShutdown();
return;
}
checkStatus(status);
printf("Verifying Result\n");
for(i = 0; i < N; ++i)
{
diff = X[i] - B[i];
if(diff < 0.0)
diff = -diff;
if(diff > thresh)
printf("Result check failed: i=%d X[i]=%f B[i]=%f", i, X[i], B[i]);
}
printf("Shutting down CULA\n\n");
culaShutdown();
free(A);
free(B);
free(IPIV);
}
You mention Sgesv but the sample code you have shown is for Dgesv. Nevertheless, the answer is the same.
According to the Netlib LAPACK reference, the B matrix of RHS vectors is passed to the function as the 6th parameter:
[in,out] B
B is DOUBLE PRECISION array, dimension (LDB,NRHS)
On entry, the N-by-NRHS matrix of right hand side matrix B.
On exit, if INFO = 0, the N-by-NRHS solution matrix X.
And the X matrix is returned in the same parameter location. So B when passed to the function contains the NxNRHS right-hand-side vectors, and the same parameter returns the X result.
In the code you have shown, they are actually passing a variable called X and after the result is returned (in the same variable X) they are comparing it against a variable named B which is perhaps confusing, but the concept is the same.
Since the A matrix in the example is the identity matrix, the correct solution of Ax = b is x=b
For the general case, you should pass your B matrix of RHS vectors in the 6th parameter location. Upon completion of the function, the result (X) will be returned in the same parameter.