How range overflow affects the simulation and synthesis? - verilog

module dut ( a,b_out,array,c);
input [2:0] a;
input [3:0] array;
input c;
output reg b_out;
always#( a or c or array) begin
if(c)
b_out = 1'b0;
else
b_out = array[a];
end
endmodule
There is a possible range overflow in the above RTL, how it exactly affects the simulation and synthesis?

When a > 3 and !c then b_out will be undef in simulation because an out-of bounds access to a vector returns undef (i.e. 1'bx). See 5.2.1 in IEEE Std 1364-2005:
A part-select of any type that addresses a range of bits that are
completely out of the address bounds of the net, reg, integer, time
variable, or parameter or a part-select that is x or z shall yield the
value x when read and shall have no effect on the data stored when
written. Part-selects that are partially out of range shall, when
read, return x for the bits that are out of range and shall, when
written, only affect the bits that are in range.
In synthesis this don't care will be transformed into whatever the synthesis tool deems the most efficient. Very likely that means that only the bottom two bits of a are used in array[a], i.e. it is identical to array[a[1:0]]. But there is no guarantee for that whatsoever and it would be equally correct to create a circuit that for example always returns 1 or 0 when a[2] is high.

Related

Determine whether a binary number is of power of two in verilog code

I am trying to determine whether a binary number is of power of two (in other words, is it of one-hot encoding).
I found a method to do so, but it is for integer.
Could anyone help to transform the method for usage with binary number in verilog ?
There's nothing wrong with your codeā€”it's limitations of the tool you are using.
Verilator requires code with inputs and outputs so it can be stimulated and results displayed.
It also doesn't like performing logical operators on multi-bit operands.
module is_power_of_two(output reg f);
reg [7:0];
initial begin
#1 v = 8'b11110000;
#1;
end
always #(*) f = v != 0 && !((v & v - 1) != 0);
endmodule

Is there a mandate for the variable to be of data type "integer" for arithmetic operations "+" and "-"?

Following is the code for finding factorial of a number. If I declare "i" as "register", the output (z) remains 1, irrespective of the input. If it is declared as "integer", I get the proper result. Why is it so? Please explain.
module Factorial_calc(n, z);
input [5:0] n;
output reg [64:0] z;
reg i;
// integer i;
always #(n)
begin
i=0;
z=1;
while(i<n)
begin
i=i+1;
z=i*z;
end
end
endmodule
Because your integer is 32 bits wide and your reg is only one bit wide. Your simulation should not finish for most values of n, let alone produce a result.
HDL is not like any other programming language. Beware that even if your code simulates it does not mean it will work in hardware. In your case it will not synthesize. You value of n is undefined at compile time.
Last be not least do NOT use x or z for variables, They are too easily confused with 'x or 'z.

Multi dimensional array value assignment in verilog

The verilog below code as you see uses a multi-dimensional register array for storing the data.
parameter DSIZE = 8;
parameter ASIZE = 4;
input [DSIZE-1:0] wdata;
input wclk,wen;
reg [ASIZE:0] wptr;
parameter MEMDEPTH = 1<<ASIZE;
reg [DSIZE-1:0] ex_mem [0:MEMDEPTH-1];
always #(posedge wclk)
if (wen)
ex_mem[wptr[ASIZE-1:0]] <= wdata;
I do not properly understand what happens in the last assignment statement in which ex_mem is assigned the value in wdata. What does the part in the brackets (wptr[ASIZE-1:0]) associated with ex_mem return and to what location of ex_mem does wdata get stored into?
In the code, ex_mem is a memory that has 16 (MEMDEPTH) slots. Each slot has 8 (DSIZE) bits. 16 slots can be addressed by 4 (ASIZE) bits, but wptr is a 5-bit signal for some reason, so its most significant bit (MSB) is not used for addressing the memory.
ex_mem[wptr[ASIZE-1:0]] <= wdata;
Since wptr[ASIZE-1:0] is a 4-bit signal (for ASIZE=4), the assignment above may write to a slot between ex_mem[0] and ex_mem[15].
'wptr' is just a one-dimensional register.
So, first of all verilog extracts an index to ex_mem from the 'wptr' thing. It uses this range to do so: ASIZE-1:0.
If ASIZE is 4, as in your example, it can sample values from 0 to 15 from there. For example,
reg [4:0] wptr = 0x1B;
wptr[3:0] will give you 'B' (11).
Now this index value will be applied to the ex_mem array to write your data.

How to use the input's values in "always" definiton in Verilog

I got the problem with using the input's value in Verilog.
I write:
module reg_vector (INPUT, ICLK, IENBL, NR, OUT);
parameter k = 6;
parameter n = 3;
input [(8*k)-1:0] INPUT;
input ICLK;
input IENBL;
input [n-1:0] NR;
reg [n-1:0] temp;
output reg [7:0] OUT;
always# (temp, posedge ICLK)
begin
if (IENBL)
begin
OUT = INPUT[temp*8 : temp*8+8];
end
end
endmodule
But got the error:
Error (10734): Verilog HDL error at reg_vector.v(25): temp is not a
constant
How should I fix it?
Thank you)
INPUT[temp*8 : temp*8+8] does not work because the : range syntax requires both sides to be a constant.
What you want is to use the +: array slicing: INPUT[temp*8 +: 8]
The left hand side of +: allows variables and represents the starting index. The right hand side is the width and must be a constant. For more on +: see Indexing vectors and arrays with +:
Other issues:
Remove temp from the sensitivity list.
temp needs to be assigned to something
OUT should be assigned with non-blocking (<=) not blocking (=) since it is sequential logic.
always #(posedge ICLK) // no temp in sensitivity list
begin
if (IENBL)
begin
OUT <= INPUT[temp*8 +: 8]; // non-blocking and +:
end
end
Even if your vector is always 1 byte wide, the tool understands it as a variable size and it does not know how to deal with it. (you also inverted the indexes temp*8 and temp*8+8 in the vector selection)
Another way to do it is to use the shift operator
OUT = INPUT >> (temp*8);
This should work as OUT will take the lower 8bits of the shifting by 8*temp of INPUT

how to nullify register in system verilog

How do I nullify a register in SystemVerilog if I do not know the size?
For example, if I have:
reg [DATA_WIDTH-1:0] data_stack;
with some parameter DATA_WIDTH given to the module. Is it possible to assign a zero to the register data_stack?
Note that it is sufficient to initialize a similar reg to zero as then I can simply perform a bitwise and between the two and nullify data_stack.
The IEEE Std 1800-2009 is the golden reference. The following sets all bits to 0:
data_stack = '0;
Refer to the section "Integer literal constants".
An unsized single-bit value can be specified by preceding the
single-bit value with an apostrophe ( ' ), but without the base
specifier. All bits of the unsized value shall be set to the value of
the specified bit. In a self-determined context, an unsized single-bit
value shall have a width of 1 bit, and the value shall be treated as
unsigned.
If I understand your question, you want to know how to generate a zero value with the same width as data_stack?
In that case, use the replication operator:
data_stack = {DATA_WIDTH{1'b0}};
This generates DATA_WIDTH number of zeros.
I think your searches would yield better results if you searched for initialising registers, instead of nullify.
If this is a testbench variable then just :
initial begin
data_stack = {DATA_WIDTH{1'b0}};
end
If it is to be used in a flip-flop you need to reset it:
always #(posedge clk or negedge reset_n) begin
if (~reset_n) begin
data_stack <= {DATA_WIDTH{1'b0}};
end
else begin
//<=nextvalue;
end
end

Resources