I am writing one simple asynchronous sequence detector, but i am getting unusual result at one point. Code is working fine with "assign a8 = ((y2&&inp1&&~inp2)||(y1&&inp1)); " but if i replace above line with following lines in my code its not giving the correct result.
assign a6 = (y2&&inp1&&~inp2);
assign a5 = (y1&&inp1);
assign a8 = a6||a5;
Both are technically the same but i am not able to understand why output is not coming correct when i use above lines of code.
module Async_Design(inp1,inp2,outp);
input inp1,inp2;
output outp;
wire y1 ,y2;
/*assign a6 = (y2&&inp1&&~inp2);
assign a5 = (y1&&inp1);
assign a8 = (a6||a5);*/
/*Uncommenting the above section and commenting below
line is not giving correct result*/
assign a8 = ((y2&&inp1&&~inp2)||(y1&&inp1));
Delay D1(y1,a8);
nand(a1,y1,1'b1);
nand(a2,a1,inp1);
nand(a3,a2,1'b1);
nand(a4,a3,inp2);
nand(a5,a4,1'b1);
Delay D2(y2,a5);
assign outp = y1;
endmodule
module Delay(q,inp);
output q;
input inp;
reg q;
initial
begin
q=1'b0;
end
always #(*)
begin
q=((inp&&1'b1)||(inp&&1'b1));
end
endmodule
/***********************************************/
TEST BENCH
/***********************************************/
module Async_Design_Test;
reg inp1,inp2;
wire outp;
reg[15:0] sequence1;
reg[15:0] sequence2;
integer i;
Async_Design Async(inp1,inp2, outp);
initial
begin
sequence1 = 16'b 0101_1111_0111_1111;
sequence2 = 16'b 1010_1010_1110_1111;
for( i = 0; i <= 15; i = i+1)
begin
inp1 = sequence1[i];
inp2 = sequence2[i];
#6
$display( " Input1 = ", inp1, " Input2 = ", inp2, " Output = ", outp,);
end
end
endmodule
Can anyone help me to understand this behavior as i am new to HDL coding
Your code after change is not valid one. Why?
assign a5 = (y1&&inp1);
...
nand(a5,a4,1'b1);
What you're trying to do is drive a5 wire in two different places (btw your compiler should print an error like "can't resolve multiple constant drivers for net a5"). And it won't work, since you can drive a wire only in one place. If you change one of this lines, e.g.:
assign a6 = (y2&&inp1&&~inp2);
assign a7 = (y1&&inp1);
assign a8 = (a6||a7);
you'll get the same output as if you use assign a8 = ((y2&&inp1&&~inp2)||(y1&&inp1)).
PS Consider usage of & and | operators.
Related
I'm quite new with SystemVerilog, I-m trying to assign a value to a 2D array from another 2D array, but each time I compile this error appers:
Error: (vlog-13069) ../src/dadda tree/daddaTree.sv(75): near "[": syntax error, unexpected '['.
Here the code:
module daddaTree import globals ::*; (
input wire signed [24:0]PP[8],
output wire [31:0]C,
output wire [31:0]S );
// layers of the reduction tree
wire [31:0]l3[8];
wire [31:0]l2[5];
wire [20]Tout_l3;
// zero paffing of the inputs partial products
assign l3[0] = 8'b00000000 & PP[0];
assign l3[1] = 7'b0000000 & PP[1] & 1'b0;
assign l3[2] = 6'b000000 & PP[2] & 2'b00;
assign l3[3] = 5'b00000 & PP[3] & 3'b000;
assign l3[4] = 4'b0000 & PP[4] & 4'b0000;
assign l3[5] = 3'b000 & PP[5] & 5'b00000;
assign l3[6] = 2'b00 & PP[6] & 6'b000000;
assign l3[7] = 1'b0 & PP[7] & 7'b0000000; // MSB for carry of the layer
// bit with no compression
// [4:0]l2[0:4] = '{l3{[4:0][0:4]}}; ERRORS HERE
// assign l2[5][1:4] = l3[5][2:5];
// assign l2[6][2:4] = l3[6][3:6];
// assign l2[7][3:4] = l3[7][6:7];
endmodule
I can assign an entire raw of bit as assign l3[0] = 8'b00000000 & PP[0];, but when I have to assign a slice of an array to another the compiler givve me the above error.
I mean how can assign for example:
"l3 from column 0 to 4, from raw 0 to 4"
to
"l2 from column 0 to 4, from raw 0 to 4"
as an example bits [4:0] of column [0:4] of l2 should have as input bits [4:0] of column [0:4] of l3, that are zeros, or PP values received from another module, so unknwon values.
I can do the assignement manualy untill a certain point:
// bit without compression
assign l2[0][0] = l3[0][0]; // c0
assign l2[1][0] = l3[1][0]; // c1
assign l2[1][1] = l3[1][1];
assign l2[2][0] = l3[2][0]; // c2
assign l2[2][1] = l3[2][1];
assign l2[2][2] = l3[2][2];
assign l2[3][0] = l3[3][0]; // c3
assign l2[3][1] = l3[3][1];
assign l2[3][2] = l3[3][2];
assign l2[3][3] = l3[3][3];
assign l2[4][0] = l3[4][0]; // c4
assign l2[4][1] = l3[4][1];
assign l2[4][2] = l3[4][2];
assign l2[4][3] = l3[4][3];
assign l2[4][4] = l3[4][4];
assign l2[5][1] = l3[5][2]; // c5
assign l2[5][2] = l3[5][3];
assign l2[5][3] = l3[5][4];
assign l2[5][4] = l3[5][5];
but also in this case an error appears
Error (suppressible): ../src/dadda tree/daddaTree.sv(95): (vlog-2698) Index 5 into array dimension 1 of 'l2' is out of bounds.
Please someone can explain me how can I assign it?
Thanks
[4:0]l2[0:4] = '{l3{[4:0][0:4]}} -- what is it supposed to mean? No wonder that there is a syntax error. I guess, you wanted something like the following: assign l2[0:4][4:0] = l3[0:4][4:0] which is impossible, because you take a slice of the lower dimension here.
As for index out of bounds, l2 is declared as wire [31:0]l2[5]; where the outer index is [5], meaning [0:4]. So, when you tried to use index 5 it is out of bounds since the max is 4.
So, your only bet is to use generate for loops, for example (based on your manual code):
for(genvar i = 0; i <= 4; i++) begin: L1
for (genvar j = 0; j < i; j++) begin: L2
assign l2[i][j] = l3[i][j];
end
end
Or maybe like this:
for(genvar i = 0; i <= 4; i++) begin: L1
assign l2[i][i:0] = l3[i][i:0];
end
You have to figure out exact numbers.
I want to make a serial comparator using a dff with async reset base on with continuous assignment. but output will come in unknown (x) state I don't know why. I checked every wire and assigned each of them an expression
dff code (verilog):
module comparator (input a, input b, input reset, input clk, output [1:0] o);
wire q0_p, q0_n, q1_p, q1_n, d0, d1;
wire s0, r0, w01, w02, s1, r1, w11, w12;
assign d0 = (q1_n & q0_p) | (q0_p & ~a & b) | (q1_n & ~a & b);
assign d1 = (q1_p & q0_n) | (q0_n & a & ~b) | (q1_p & a & ~b);
assign w01 = ~(w02 & s0);
assign s0 = ~(w01 & reset & clk);
assign r0 = ~(s0 & clk & w02);
assign w02 = ~(r0 & d0 & reset);
assign q0_p = ~(s0 & q0_n);
assign q0_n = ~(q0_p & r0 & reset);
assign w11 = ~(w12 & s1);
assign s1 = ~(w11 & reset & clk);
assign r1 = ~(s1 & clk & w12);
assign w12 = ~(r1 & d1 & reset);
assign q1_p = ~(s1 & q1_n);
assign q1_n = ~(q1_p & r1 & reset);
assign o[0] = q0_p;
assign o[1] = q1_p;
endmodule
testbench:
module test();
reg a, b, reset, clk = 0;
wire [1:0] o;
comparator cmp(a, b, reset, clk, o);
always #1 clk <= ~clk;
initial begin
$monitor("%b %b %b", a, b, o);
reset = 0;
reset = 1;
// a = 1110, b = 1011
#1 a = 1; b = 1;
#1 a = 1; b = 0;
#1 a = 1; b = 1;
#1 a = 0; b = 1;
$finish();
end
endmodule
output:
1 1 xx
1 0 xx
1 1 xx
0 1 xx
if 'D' is in 'x' state, as soon as you deassert reset, the outputs will become 'x' again. You need to set a known value to 'D' before deassert. Also, you need a delay between assert and deassert of reset.
For example,
initial begin
$monitor("%b %b %b", a, b, o);
reset = 0;
#1
a = 0; b = 0;
reset = 1;
...
As you can see, it is non-trivial to debug simulation problems when trying to model a logic circuit with feedback at the gate level. You get unknowns (x) because you do not correctly initialize all the signals which need to be initialized.
Your testbench does not really drive the reset signal to 0 because you immediately drive it to 1 (both happen at time 0). You should add a delay between the 2 values. However, that will still be insufficient to initialize all the signals.
The solution is to use the appropriate model for your logic: behavioral level. This is trivial in Verilog. The common way to model a dff with an asynchronous active-low reset is:
always #(posedge clk or negedge nreset) begin
if (!nreset) begin
q <= 1'b0;
end else begin
q <= d;
end
end
The beauty of digital design and Verilog is that you can abstract away all the unnecessary details. The code above eliminates all the issues with properly initializing all your signals.
`timescale 1ns / 1ps
module Signadder(
input wire [3:0] a,
input wire [3:0] b,
output reg [3:0] sum
);
reg [2:0] mag_a, mag_b,mag_sum, max, min;
reg sign_a, sign_b, sign_sum;
always #*
begin
mag_a = [2:0]a;
mag_b = [2:0]b;
sign_a = [3]a;
sign_b = [3]b;
if(mag_a>mag_b)
begin
max = mag_a;
min = mag_b;
sign_sum = sign_a;
end
else
begin
max = mag_b;
min = mag_a;
sign_sum = sign_b;
end
if (sign_a == sign_b)
mag_sum = mag_a +mag_b;
else
mag_sum = max - min;
assign sum = {sign_sum,mag_sum};
end
endmodule
I describe a Sign_mag adder with Verilog, but I get these errors when I synthesize:
Line 35: Syntax error near "[".
Line 36: Syntax error near "[".
Line 33: a is not a task
Line 34: b is not a task
I can't find any syntax error in my Verilog code, and with "a is not a task", I fix it by use intermediate register :
reg [3:0] a1;
reg [3:0]b1;
a1 = a;
b1 = b;
But, it still does not work. I hope somebody has any idea why.
The syntax error is due to the following lines:
mag_a = [2:0]a;
mag_b = [2:0]b;
sign_a = [3]a;
sign_b = [3]b;
The signal name should be to the left of the square brackets:
mag_a = a[2:0];
mag_b = b[2:0];
sign_a = a[3];
sign_b = b[3];
In addition to that, you are not following good coding practices for synthesizable code.
You should not use the assign keyword inside an always block.
You have combinational feedback loops inside your always block. You should not read from and assign to the same signal. For example, mag_a:
mag_a = a[2:0];
max = mag_a;
I am working on a Module which changes it's constant values based on the input to calculate it's output.
Let me illustrate what I am looking for,
Let x be the input, y the output and a,b,c,d,e the set of constants.
Module performs something like the following operation:
y=(a*x)+(b*x)+(c*x)+(d*x)+(e*x); //separate adder and multiplier modules are used and this code itself is huge so just providing the idea.
Now I have used following method to choose the right value for the constants depending on the input: (Pseudo code)
module top (x,clk,y);
input clk;
input [31:0] x;
output [31:0] y;
if (x>=32'h08000000 && x<32'h0A000000) begin
localparam a = 32'h058B90C0;
localparam b = 32'h193C9F60;
localparam c = 32'h29AC1740;
localparam d = 32'hA48B9440;
localparam e = 32'h0B6392E0;
end else if (x>=32'h0A000000 && x<32'h0C000000) begin
localparam a = 32'h028A50C1;
localparam b = 32'hE98B489C;
localparam c = 32'h17402948;
localparam d = 32'h9440E45B;
localparam e = 32'h392E00AF;
end
y=(a*x)+(b*x)+(c*x)+(d*x)+(e*x); // Module that computes using any of the above mentioned constant sets
endmodule
I get the following errors:
(1) "Unable to bind parameter".
(2) "Cannot evaluate genvar conditional expression: ((x)G(32'000010000....00))&& so on......"
My question is:
My user will give the input through x, right constants will be chosen, my module will calculate and provide the output. Just providing the right constants to the module is enough. How shall I do it? Ideas through pseudo code will be helpful for me.
I had to look up where localparam is allowed. You can define a localparam after a begin : < label >.
I tried it and found that (at least in Vivado) it passed and worked.
always #( a )
if (a>=1)
begin : a_be_1
localparam P1 = 3;
c = P1;
end
else
begin : a_sm_1
localparam P1 = 5;
c = P1;
end
I have a 8-bit ALU unit in verilog that can do addition, invert, etc. This single unit is tested and performs correctly. When I combine 4 of these to make a bigger ALU every output is correct except when I choose the addition operation it comes out as
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx01010101, basically the first alu does the work right then the output from the second is xxxxxxxx as is the third and fourth. This is really frustrating!!
the 8 bit module( it would be nice to point if this model is behavioral or structural model i go for the former!)
module alu_8bit(
output reg [7:0] out,
output reg cout,g,e,
input [7:0] A,B,
input cin,
input [2:0] S
);
//used functions
parameter BUF_A = 3'b000;
parameter NOT_A = 3'b001;
parameter ADD = 3'b010;
parameter OR = 3'b011;
parameter AND = 3'b100;
parameter NOT_B = 3'b101;
parameter BUF_B = 3'b110;
parameter LOW = 3'b111;
always #(A or B or S) begin
//Comparator
g = A>B;
e = A==B;
//Other selective functions
case(S)
BUF_A: out = A;
NOT_A: out = ~A;
ADD: {cout,out} = A+B+cin;
OR: out = A | B;
AND: out = A & B;
NOT_B: out = ~B;
BUF_B: out = B;
LOW: out = {8{1'b0}};
endcase
end
endmodule
Here is the code of the bigger one:
module alu_32bit(
output [31:0] out,
output cout,g,e,
input [31:0] A,B,
input cin,
input [2:0] S
);
wire e1,e2,e3,e4;
wire g1,g2,g3,g4;
alu_8bit ALU1(out[7:0],cin2,g1,e1,A[7:0],B[7:0],cin,S);
alu_8bit ALU2(out[15:8],cin3,g2,e2,A[15:8],B[15:8],cin2,S);
alu_8bit ALU3(out[23:16],cin4,g3,e3,A[23:16],B[23:16],cin3,S);
alu_8bit ALU4(out[31:24],cout,g4,e4,A[31:24],B[31:24],cin4,S);
assign g = g4 | (e4 & g3) |(e4 & e3 & g2) | (e4& e3 & e2 & g1);
assign e = e4 & e3 & e2 & e1;
endmodule
Can any one give some help?! if you need more info just tell me.
Edited:
Waveform pic clearly input comes in correct but output not
The dataflow diagram shows that ALU1 output is just fine
Your sensitivity list for the main part of the ALU doesn't include cin.