How to use the input's values in "always" definiton in Verilog - 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

Related

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.

Bit by bit comparison between two variables in Verilog

Currently, I am beginning to write the firmware by Verilog for one idea. It is comparing bit by bit between two variables and then using one binary counter to count the number of different bits.
For example:
I have two variables in verilog
A : 8'b00100001;
B : 8'b01000000;
Then I give the condition to compare bit by bit between two variables. If there is difference between 1 bit of A and 1 bit of B at same bit position, binary counter will count.
This is my verilog code:
module BERT_test(
input CLK,
input RST,
input [7:0] SIG_IN,
input [7:0] SIG_OUT,
output [7:0] NUM_ERR
);
integer i;
reg[7:0] sign_in;
reg[7:0] sign_out;
always #(posedge CLK) begin
sign_in[7:0] <= SIG_IN[7:0];
sign_out[7:0] <= SIG_OUT[7:0];
end
reg [15:0] bit_err;
// Combinational Logic
always #* begin
bit_err = 8'b0;
for (i=0;i<8;i=i+1) begin
if (sign_in[i] == sign_out[i]) begin
bit_err = bit_err + 8'b0;
end else begin
bit_err = bit_err + 8'b1;
end
end
assign NUM_ERR = bit_err;
end
endmodule
Then I had a mistake
Reference to vector wire 'NUM_ERR' is not a legal reg or variable lvalue
I do not know how to solve this problem. Are there any solutions for this problem or how I need to modify my firmware, please suggest me.
You are driving NUM_ERR (a net) from an always block. It is not permitted to drive nets from always blocks (or initial blocks). You need to move this line:
assign NUM_ERR = bit_err;
outside the always block.
You should not use an assign statement inside an always block. This is legal but is deprecated and means something weird. If you have included this line inside the always block by mistake, then indenting you code properly would have shown it up.
You have an assign WITHIN an always block. Move it outside.
Adding zero to bit error if the bits are the same is superfluous.
if (sign_in[i] != sign_out[i])
bit_err = bit_err + 8'b1;
Also bit error is 16 bits so it is not wrong to add 8'b1 but misleading.

How to change input signal to parameter in systemverilog?

I have an input logic sequence and I would like to convert it to a parameter in order to add it elsewhere in my program.
For example,
module myModule(input logic[7:0] SW, output logic[7:0] LEDR);
parameter shift = SW;
assign LEDR = SW[shift + 1: shift];
endmodule
I know that's not correct syntax, I just wanted to get the main idea.
Parameters are by definition compile time constants. That means you can not change their value based on an expression that can change over time.
What you can do is change the way you model so it does not require a parameter. For example , you could write your code as
module myModule(input logic[7:0] SW, output logic[7:0] LEDR);
assign LEDR = SW[SW +: 2];
endmodule
You cannot convert a variable to parameter. The value of the parameter will be locked after elaborations. A variable will not have a value until simulation.
Part-select (sometimes called range-slice) should do what you need. See
Indexing vectors and arrays with +: for more info.
Having SW slice itself does make sense since the resulting value would always be 0. Here is better example:
module myModule(input [8:0] IN, input [2:0] SW, output [1:0] LEDR);
assign LEDR = IN[SW +: 2];
endmodule

Verilog : Variable index is not supported in signal

I get an error saying 'Index is not supported in signal'. From what I can see the error is on the left hand side of the non-blocking assignment. Why does the code below give an error and is there a way to work around it?
...
parameter width = 32;
parameter size = 3;
input clk, reset;
input [width*size-1:0] A;
input [width*size-1:0] B;
output [width*size-1:0] result;
reg signed [width*size-1:0] partials;
reg signed [width-1:0] temp;
reg signed [width-1:0] currenta;
reg signed [width-1:0] currentb;
wire signed [width-1:0] temp1wire;
...
integer k = 0;
always # (posedge clk)
begin
currenta[width-1:0] <= A[width*k +: width];
k = k+1
currentb[width-1:0] <= B[width*k +: width];
partials[width*k +: width] <= temp1wire;
end
Add Add1(clk, temp1wire, currenta, currentb);
...
This code is part of a sequential block that does vector addition and saves the result at partials[width*k +: width].
I found this on the Xilinx forum:
"XST works fine with the indexed part-select operator "+:" if it is on the right-hand side (RHS) of the assignment. It also works fine when it is on the left-hand side (LHS) AND the starting index is a constant. Your case uses a variable as the starting index on the LHS and that what XST doesn't like although it's legal."
k needs to be clamped or wrapped around after reaching size-1.
Wrapping around can be done with the mod operator (%); example:k = (k+1)%size. % may not synthesize optimally (check your synthesizer), so a if-statement is a functional alternative if(k==SIZE-1) k = 0; else k=k+1;
Suggestions:
It is generally recommenced to keep parameters as uppercase, this way you can easily identity parameters form signal names. Putting a blocking assignment inside a sequential block is legal, but most design rules recommend separating combinational logic from sequential assignments. I would prefer writing your code like the following:
// $clog is IEEE1364-2005 ยง 17.11, some synthesizers support it, others don't
reg [$clog2(SIZE):0] k=0, next_k;
always #* begin
if (k==SIZE-1) begin
next_k = 0; // wrap around
// next_k = k; // clamp
end
else begin
next_k = k+1;
end
end
always # (posedge clk)
begin
currenta[WIDTH-1:0] <= A[WIDTH*k +: WIDTH];
currentb[WIDTH-1:0] <= A[WIDTH*next_k +: WIDTH];
partials[WIDTH*next_k +: WIDTH] <= temp1wire;
k <= next_k;
end

"<signal> is not a constant" error in if-statement

I am trying to write a simple module to output a 14-bit number based on the value of four input signals. My attempt is shown below.
module select_size(
input a,
input b,
input c,
input d,
output [13:0] size
);
if (a) begin
assign size = 14'h2222;
end
else begin
if (b) begin
assign size = 14'h1111;
end
else begin
if (c) begin
assign size = 14'h0777;
end
else begin
assign size = 14'h0333;
end
end
end
endmodule
Upon compilation, I receive the following error:
ERROR:HDLCompiler:44 - Line 67: c is not a constant
I don't understand why that particular if-statement isn't working if the other two preceding it are. I have tried changing the condition to
if (c == 1) begin
but to no avail.
Does anybody know how to solve this error? Thank you!
Two problems:
1) You need to put if statements inside an always block.
If you use verilog-2001, you can use
always #*
if ....
end
end
Otherwise specify all the inputs in the sensitivity list:
always #(a or b or c or d)
if ....
end
end
2) Constant assignments are not allowed inside if statements.
Remove the assign keyword from any statements inside the if block:
if (a) begin
size = 14'h2222;
end
You will also have to declare size as a reg type.
However my preference would be to rewrite the entire module with conditional operator, I find it much preferrable to read. This following module achieves the same result:
module select_size(
input a,
input b,
input c,
input d,
output [13:0] size
);
assign size = a ? 14'h2222 :
b ? 14'h1111 :
c ? 14'h0777 :
14'h0333 ;
endmodule
As #Tim has already answered, using reg types inside always blocks or wire with assign.
#Tim has also described the nested ternary assignments, while in the example are written very well, they are generally seen as bad practice. They imply a very long combinatorial path and can be hard to maintain. The combinatorial path may be optimised by synthesis which should imply a mux with optimised selection logic.
Easier to maintain code will have a lower cost of ownership, and as long as it does not lead to a larger synthesised design it is normally preferred.
My implementation would be to use a casez, (? are don't cares). I find the precedence of each value easier to see/debug.
module select_size(
input a,
input b,
input c,
input d,
output logic [13:0] size //logic (SystemVerilog) or reg type
);
always #* begin
casez ({a,b,c})
3'b1?? : size = 14'h2222 ;
3'b01? : size = 14'h1111 ;
3'b001 : size = 14'h0777 ;
3'b000 : size = 14'h0333 ;
default: size = 'bx ;
endcase
end
endmodule

Resources