Size of arithmetic operation result in Verilog - verilog

I am making a signed comparator in Verilog. Here is the code:
module signedComparator(a0, a1, a2, b0, b1, b2, G, E, L);
input a0, a1, a2, b0, b1, b2;
output reg G, E, L;
always#(a0 or a1 or a2 or b0 or b1 or b2)
begin
if(a2 == 0 && b2 == 0) //both a and b >= 0
begin
L <= {a1,a0} < {b1,b0};
G <= {a1,a0} > {b1,b0};
E <= {a1,a0} == {b1,b0};
end
else if(a2 == 1 && b2 == 0) //a negative, b >= 0
begin
L <= 1;
G <= 0;
E <= 0;
end
else if(a2 == 0 && b2 == 1) //a >= 0, b negative
begin
L <= 0;
G <= 1;
E <= 0;
end
else //both a and b negative
begin
L <= (~{a1,a0} + 1) > (~{b1,b0} + 1);
G <= (~{a1,a0} + 1) < (~{b1,b0} + 1);
E <= (~{a1,a0} + 1) == (~{b1,b0} + 1);
end
end
endmodule
I am wondering, when adding vectors, what is the length of the intermediate result? I am concerned about the last case (L <= (~{a1,a0} + 1) > (~{b1,b0} + 1);). When adding 1 to ~{a1,a0}, is the result three bits in length for the comparison, or will {1,1} + 1 = {0,0}? Is there documentation somewhere for what the data type of intermediate results in verilog will be? This is hard to search for since I don't yet know the proper terminology.

I'm assuming this is for synthesis and have a few comments about your code. You seem to be using individual bits as inputs to the module and then using concatenation to make vectors later on. You can avoid this by declaring ports as signed vectors and doing a comparison directly.
input signed [2:0] a,b;
...
if(a == b)
...
else if(a > b)
...
else
...
Also, you are using non-blocking assignments to model combinational logic. These will work in the code you posted but really shouldn't be used in this manner. They work much better modeling synchronous logic via a clocked process. There's a good paper that summarizes a good coding style for synthesis.
I am wondering, when adding vectors, what is the length of the intermediate result?
The spec has a table for this as it depends on the operands and context.
An integer : Unsized constants are at least 32-bits
{a,b} : sizeof(a) + sizeof(b)
~{a} : sizeof(a)
a + b : max(sizeof(a),sizeof(b))
Thus your comparison operands will both be (at least) 32-bits. You can explicitly assign a constant size by using a tick before the value.
4'b1 // 0001 Binary 1
4'd1 // 0001 Decimal 1
4'd8 // 1000 Decimal 8
1'b1 // 1 Binary 1
'b1 // The same as 1, tick here only specifies dec/oct/bin format
Is there documentation somewhere for what the data type of
intermediate results in verilog will be?
By far the best resource I've found for details like this is the spec itself, IEEE 1364.

Related

How to sample covergroup at the occurence of a certain sequence?

module testbench;
bit [2:0] A;
bit [2:0] data[];
int i;
bit [2:0] b;
covergroup cov_grp;
c1 : coverpoint A {
bins b1 = {0,1,2};
bins b2 = {3,4,5};
bins b3 = {6,7};}
endgroup
sequence seq;
(b == 'd7);
endsequence
initial
begin
cov_grp cov_ins = new();
data = new[10];
for(i=0;i<8;i++)
begin
data[i] = $random;
A = data[i];
assert property #(seq) cov_ins.sample();
end
end
endmodule
I want to sample for the covergroup instance cov_ins when sequence seq occurs.
When b = 'd7 it should sample
...............................................................................................................................................................................................................................................................................................................
Just as your covergroup needs an event to trigger sampling, a sequence needs an event to know when to sample and evaluate the expression b = 'd7 (BTW, your testbench never sets b).
And it's not clear from your testcase why you even need to be using a sequence that is a simple Boolean expression. You could just write:
if (b == 'd7) cov_ins.sample();
But assuming your sequence is more complex, then you need a clock in your sequence and need to write something like
sequence seq;
#(posedge clk) (b == 'd7)[->1]; // when b transitions to 'b7
endsequence
covergroup cov_grp #seq; // instead of calling sample()
c1 : coverpoint A {
bins b1 = {0,1,2};
bins b2 = {3,4,5};
bins b3 = {6,7};}
endgroup

Clean way to truncate result of addition or subtraction

When I do addition or subtraction in Verilog, some compilers emit warning.
// code example
logic [9 : 0] a, b, c;
always_ff #(posedge clk) begin
b <= a + 1;
c <= a - 1;
end
// warning example
Warning (13469): Verilog HDL assignment warning at xxx.sv(xxx): truncated value with size 11 to match size of target (10) File: xxx.sv Line: xxx
Warning (13469): Verilog HDL assignment warning at xxx.sv(xxx): truncated value with size 32 to match size of target (10) File: xxx.sv Line: xxx
I want to find clean way to remove these warnings. I tried two methods:
// method 1
b <= (a + 1)[9 : 0];
// method 2
logic [10 : 0] d;
d <= a + 1;
b <= d[9 : 0];
I thought the first method would compile, but it was invalid syntax in verilog.
Second method works, but it is too verbose and dirty.
Is there any other clean ways?
From IEEE Std 1364-2001.
Page 73:
Table 29—Bit lengths resulting from self-determined expressions:
Unsized constant number = Same as integer
Page 45:
NOTE Implementations may limit the maximum size of an integer variable, but they shall at least be 32 bits.
So the warnings you see come from trying to operate one unsized numeric constant (32 bits at least) with a sized variable (10 bits), so the synthesizer warns about the result may overflow.
So, just make sure all your operands have the same size:
Instead of:
// code example
logic [9 : 0] a, b, c;
always_ff #(posedge clk) begin
b <= a + 1;
c <= a - 1;
end
Do:
// code example
logic [9 : 0] a, b, c;
always_ff #(posedge clk) begin
b <= a + 10'd1;
c <= a - 10'd1;
end
1 id a 32-bit value. As a result the width of the expression is 32.
The way around is to use a sized value of '1', i.e.
b <= a + 1'b1;
c <= b - 1'b1;
This can potentially give you an 11-bit result. Carryon bit will be lost. At this point you can do some other tricks. I guess this is the most common one. Use a carry on bit.
logic con;
logic[9:0] a,b;
...
{con, a} <= b + 1'b1;
You can use a temp variable, as in your example.
In general, verilog standard does allow free truncation or extension of operand widths and no warning is required. Definitely in this case you can ignore the warning or turn it off. I have not seen simulators which would warn about it. Just certain rule in linting tools.
Use curley concatination braces
b <= {a + 1}[9 : 0];
or change the constant size (which defaults to 32-bits)
b <= a + 10'd1;

Verilog error : A reference to a wire or reg is not allowed in a constant expression

I'm new to Verilog and I would really appreciate it if someone could help me out with this error:
output reg [0:image_width][image_height:0] result
....
integer i, j, imageX, imageY, x, y, kernelX, kernelY;
....
#(negedge ACLK)
for(x = 0; x < image_width; x++) begin
for(y = 0; y < image_height; y++)
begin
//multiply every value of the filter with corresponding image pixel
for(kernelX = 0; kernelX < kernel_width; kernelX++) begin
for(kernelY = 0; kernelY < kernel_height; kernelY++)
begin
imageX = (x - kernel_width / 2 + kernelX + image_width) % image_width;
imageY = (y - kernel_height / 2 + kernelY + image_height) % image_height;
// ignore input samples which are out of bound
if( imageY >= 0 && imageY < image_height && imageX >= 0 && imageX < image_width )
//ERROR HERE!!!
result[x][y] += image[imageX][imageY] * kernel[kernelX][kernelY];
end
end
end
end
end
The error I get is:
error: A reference to a wire or reg ('x') is not allowed in a constant expression.
error: Array index expressions must be constant here.
error: A reference to a wire or reg ('imageX') is not allowed in a constant expression.
error: Array index expressions must be constant here.
error: A reference to a wire or reg ('kernelX') is not allowed in a constant expression.
error: Array index expressions must be constant here.
Could somebody tell me what I'm doing wrong? Thank you!
This line is the problem:
result[x][y] += image[imageX][imageY] * kernel[kernelX][kernelY];
Indexing into arrays is only allowed for constant expressions. You are not allowed to use variables in vector indexes. Remember that you're working with an HDL: you're dictating physical connections in hardware. Having a variable in the index implies the ability to dynamically rewire the circuit. This SO question has some rough workarounds that may work for you. However, you should really try to refactor your algorithm to avoid the need to use the variable indexing in the first place.
By the way, you should be using non-blocking assignments instead of the blocking assignments you currently have. Your code is in a clocked block, so blocking combinational logic should be avoided:
imageX <= (x - kernel_width / 2 + kernelX + image_width) % image_width;
imageY <= (y - kernel_height / 2 + kernelY + image_height) % image_height;
// ignore input samples which are out of bound
if( imageY >= 0 && imageY < image_height && imageX >= 0 && imageX < image_width )
result[x][y] <= result[x][y] + image[imageX][imageY] * kernel[kernelX][kernelY];
#(negedge ACLK);
^
I'm pretty sure that semicolon doesn't belong there. As written, the for loops are all outside the always block.
Additionally, your image array currently only has one bit per pixel. Is this intentional? Whether it is or not, I would recommend that you reconsider this architecture; filtering an image of any significant size in a single clock cycle is not going to synthesize very well.

Sum of Values based on bits enabled Verilog

I am new to Verilog, I was trying to write a simple code but I am not sure how to do it in a expert way.
I have a 12 bit register "data", each bit of that register have a specific value. e.g.
Bit 0 = 12;
Bit 1 = 16;
Bit 2 = 33;
......
Bit 11 = 180;
Now if any bit of "data" register is 1 then the result should be the sum of all value that coresponds to that bit value. e.g.
data = 12'b100000000101
result = 225 (180+33+12)
Right now i am checking each bit of data, if it is 1 then i register that corresponding value and add it to previous registered value. This method takes number of cycles.
How can i do it in a fast way in verilog.
thank you
It depends on what you mean by "fast". Presumably you mean time, but remember that time=cycles/frequency - reducing the number of cycles will often reduce the maximum frequency your circuit can operate at.
For example, here's a circuit that does the entire add in one cycle:
always#(*) begin
tempsum = 0;
tempsum = tempsum + (data[0]? 12:0);
tempsum = tempsum + (data[1]? 16:0);
tempsum = tempsum + (data[2]? 33:0);
//...
end
always#(posedge clock)
result <= tempsum;
If you synthesized this circuit, you'd see a long chain of adders. In could calculate the result in a single cycle, but would have a long critical path, and therefore have a lower fMax. Whether this would be "faster" is impossible to know until you synthesize it (there are too many factors to guess).
A better multi-cycle approach could be to use a tree, i.e.:
reg [31:0] sum [29:0];
always # (posedge clock) begin
// level 0
sum[0] <= (data[0]? 12:0) + (data[1]? 16:0);
sum[1] <= (data[2]? 33:0) + (data[3]? 40:0);
// ...
sum[15] <= (data[30]? 160:0) + (data[31]? 180:0);
// level 1
sum[16] <= sum [0] + sum [1];
sum[17] <= sum [2] + sum [3];
// ...
sum[23] <= sum [14] + sum [15];
// level 2
sum[24] <= sum [16] + sum [17];
sum[25] <= sum [18] + sum [19];
// ...
// level 3
sum[28] <= sum [24] + sum [25];
sum[29] <= sum [26] + sum [27];
result <= sum [28] + sum [29];
end
All that said, ultimately the "fastest" approach will also depend on the other requirements of your system, what you're implementing it on, etc.
you can try something like below :-
reg [15:0] sum;
always #(*)begin
for (i=0;i<12;i++)begin
if (data[i])
sum = sum+Bit[i];
end //for
end //always
assign finalSum = |data ? finalSum: 'h0;

FSM: next state precedence

When being in a state "a1" how can I show that the next arrows will have a precedence over each other, without having an overhead of extra states?
Full example:
We are at a1 state and signals x && y are asserted: we go to state b1
If that condition is not asserted but x && z is asserted then we go to state b2
If the above conditions are not asserted but x is asserted then we go to state b3
Visual concept:
In the above "FSM" we can't see that x && y is checked before the other two.
Code snippet:
always_comb begin
case (states)
a1: begin
if (x && y)
next_state = b1;
else if (x && z)
next_state = b2;
else if (x)
next_state = b3;
else
next_state = a1;
end
endcase
end
Since you tagged the question with SystemVerilog, I just wanted to mention an alternative way of describing your next state logic:
always_comb begin
case (states)
a1:
priority casez ({x,y,z})
3'b11?: next_state = b1; // x && y
3'b1?1: next_state = b2; // x && z
3'b1??: next_state = b3; // x
default: next_state = a1;
endcase
endcase
end
Also, the commonly used state diagram does not specify priority, so you need to completely specify the transition conditions as in xbug's answer. But I don't see why you can't extend this notation, for example, mark each arc with labels 1, 2, 3, and 4, where lower numbers indicate higher priority.
Ideally, you'd need to cover all the possible combinations of input events in each state to get a proper DFA (deterministic FSM).
However, you can get away by fully specifying the triggers in terms of input signals, and let your HDL default to "no transition". In that case:
transition from a1 to b1 may be triggered by x && y && !z
transition from a1 to b2 may be triggered by x && !y && z
transition from a1 to b3 may be triggered by x && !y && !z
(with ! denoting logical 'not').
With an alphabet of 3 symbols (your three input signals), you get 2^3 = 8 possible combinations in every state. Ask yourself: in your current design, what happens if all of x, y and z get asserted ? You need to be specific about that.
EDIT
Let me be more specific.
Let's consider A, B, C, ... H as events, each representing one possible combination of input signals, such as:
x y z
A 0 0 0
B 0 0 1
C 0 1 0
D 0 1 1
E 1 0 0
F 1 0 1
G 1 1 0
H 1 1 1
Then try to express your transitions in terms of A, B, C, ... H. If you can, the resulting FSM is suitable to your task. If you can't, you should probably rethink your logic.

Resources