Im trying to get the maximum of an input vector. Im assuming all inputs are unsigned and that it should work on a range of bitwidths and array lengths.
I have to keep the parameters and input and output logic the way they are. Here is what I have, but I get a syntax error at the if statement:
module max
#(parameter int bW=16,
parameter int eC=8)
(input logic [bW-1:0] a[eC-1:0],
output logic [bW-1:0] z);
logic i=0;
always #* begin
for (i=0; i<size; i++) {
if(a[i] >z)
z = a[i];
}
end
endmodule
Maybe using a case statement would be better? I dont know. Any help would be nice!
Two simple problems.
You used brackets {/} instead of begin/end to wrap your looping statement. No need to wrap a single statement anyways.
You defined i as a single bit. use an int.
You'll also want to use a default for the initial value, then compute max from there.
For example:
module max
#(parameter int bW=16,
parameter int eC=8)
(input logic [bW-1:0] a[eC-1:0],
output logic [bW-1:0] z);
always #(*) begin
// defaults
z = 0;
for (int i=0; i<size; i++) begin
if (a[i] > z)
z = a[i];
end
end
endmodule
In addition to the other comments, I believe the for comparison value should be 'eC', not 'size'. This compiles for me (with the sverilog flag of course):
module max #(
parameter int bW = 16,
parameter int eC = 8
)
(
input logic [bW-1:0] a [eC-1:0],
output logic [bW-1:0] z
);
always #* begin
z = a[0];
for (int i=1; i<eC; i++) begin
if(a[i] > z) begin
z = a[i];
end
end
end
endmodule
Related
I am trying to figure out, how to use an unsigned char type of a variable inside a for loop, while not "breaking" out of range for unsigned char, which can vary form 0 to 255.
main(void) {
TRISC = 0;
LATC = 0;
unsigned char j;
for (j = 0; j <= 255 ; j++){
LATC = j;
__delay_ms(1000);
}
return;
}
This is code in C, where PIC is programmed. "TRISC = 0" means setting port C as an output and "LATC" is referring to port C itself. Basically I want to assign values from including 0 to 255 to this port. But if I try to compile this, the compiler (xc8) returns following two warnings:
I cannot quite understand what these two are saying, but I assume it has to do something with variable j exceeding the limit value of unsigned char, that is 255 (in last iteration j = 256, which is not allowed/defined).
However, this code gets compiled and works as meant. But I still want to write and understand a code that assigns port C the value of 255 without entering "prohibited" range of values.
*P.S. I would use any other variable type than unsigned char or char, however to ports in PICs only these two types can be applied directly (without conversion).
j <= 255 is always true if j is only 8 Bit wide.
This version should work:
main(void) {
TRISC = 0;
LATC = 0;
int j;
for (j = 0; j <= 255 ; j++){
LATC = (unsigned char)j;
__delay_ms(1000);
}
return;
}
First, in microcontroller firmware, you should not return from main(). Your main() should include some kind of endless loop.
j <= 255 is always true for a uint8_t variable. Because j can't be 256. Adding 1 to j when it's 255, makes it 0, not 256.
As others have suggested, using an 16-bit integer, signed or unsigned, is the easiest and the cleanest way. However, in performance sensitive loops you may prefer to stick with 8 bit loop counters as these are the fastest ones for a 8-bit PIC microcontroller.
This particular one-time loop can be written as:
uint8_t j = 0;
do {
LATC = j++;
__delay_ms(1000);
} while (j != 0);
I'm a bit embarrassed as I thought this would be easy to write.
A fixed-width one-hot encoder would be easy to write with a case statement. But I'm wracking my brain trying to write a parameterized N-bit one-hot encoder. So far, I have:
module onehot_enc #(
parameter WIDTH
) (
input logic [WIDTH-1:0] in,
input logic [$clog2(WIDTH-1:0] out
);
genvar i;
generate
for(i = 0; i < WIDTH; i++) begin
assign out |= in[i] ? i : 0;
end
endgenerate
endmodule
But apparently "|=" is not an operator.
Anyone have any suggestions on writing this? It seemed so simple to do in my head...
You definitely need a loop for it. No generate block should be used here. The encider can be implemented within an always block.
Because you used 'logic' in your example, I assumed that system verilog syntax is ok here. So, please add the 'system verilog' tag.
In the following example the loop runs through the whole set of iterations without any 'break' to make it synthesizable. So, in this case the last '1' wins. The first out=0 statement assigns the default value of '0' to 'out'. It also makes the code combinational. Otherwise it would be a latch.
module onehot_enc #(
parameter WIDTH = 1
) (
input logic [WIDTH-1:0] in,
output logic [$clog2(WIDTH)-1:0] out
);
always_comb begin
out = 0;
for (int i = 0; i < WIDTH; i++) begin
if (in[i])
out = i;
end
end
endmodule
This only works if your one-hot is truly one-hot, but it doesn't try to priorty-encode the inputs, so it synthesizes smaller.
// one-hot to binary encode
function binary_type_t to_binary_f(vector_type_t v);
to_binary_f = '0;
for (int i=0; i<$bits(binary_type_t); i++) begin
for (int j=0; j<$bits(vector_type_t); j++) to_binary_f[i] |= (j%(2**(i+1)) >= 2**i) ? v[j] : '0;
end
endfunction
I'm attempting to using a for loop to count the repeated leading bit in a 32-bit number. For this, I am doing:
input[31:0] A;
output reg result;
Integer i;
for (i = 31; i > -1; i = i - 1) begin
if (A[i] == 0) begin
result = result + 1;
end
else if (A[i] == 1) begin
i = -1;
end
end
However, when I synthesize the program, I receive a warning saying that the program does not converge. Am I using the for loop wrong? Before this I used i >= 0 and even used a while instead but it doesn't change the outcome. I would appreciate any help. Should I set result to 0 before running the loop?
A[i] == 1 makes number of iterations non-deterministic and causes synthesis to fail. The way around it is letting the loop to unroll till the end and use a conditional variable to handle your calculations. Something like the following:
input[31:0] A;
output reg result;
Integer i;
reg flag;
flag = 0;
for (i = 31; i > -1; i = i - 1) begin
if (flag == 0 && A[i] == 0) begin
result = result + 1;
end
else if (A[i] == 1) begin
flag = 1;
end
end
I assume that it was some type of a flop logic, since in any case this would produce state elements. So, you need to use correct nbas for result and flag.
For synthesis for loops must converge during COMPILE time. Your condition of A[i]==1 can not be determined at compile time so the loops goes from 32 to 2^31-1 before it ends.
Verilog is an HDL, which in many aspects is totally different from standard computer languages.
Problem: I have N elements of X bits each, and have them concatenated into 1 vector and now I want to unpack them into a matrix M[N][X] using for loops. For example,
input [N*X-1:0]VECTOR;
integer i;
reg [X-1:0]M[N-1:0];
always#(*) begin
for(i=0; i<N; i=i+1) begin
M[i] = VECTOR[(X*(i+1)-1):(X*i)];
end
end
However, the above code gives me the following error:
Error (10734): Verilog HDL error at FILE.v(line_number): i is not a
constant
A few corrections:
input [N*X-1:0] VECTOR; // move range to the other side
integer i;
reg [X-1:0] M [0:N-1]; // Give proper range with X
always #* begin // always block for comb logic
for(i=0; i<N; i=i+1) begin // not i=i++
M[i] = VECTOR[X*i +: X]; // vector slicing
end
end
Refer to previously answered questions to explain +: vector slicing:
Indexing vectors and arrays with +:
What is +: and -:?
How to change the sign of int using bitwise operators? Obviously we can use x*=-1 or x/=-1. Is there any fastest way of doing this?
I did a small test as below. Just for curiosity...
public class ChangeSign {
public static void main(String[] args) {
int x = 198347;
int LOOP = 1000000;
int y;
long start = System.nanoTime();
for (int i = 0; i < LOOP; i++) {
y = (~x) + 1;
}
long mid1 = System.nanoTime();
for (int i = 0; i < LOOP; i++) {
y = -x;
}
long mid2 = System.nanoTime();
for (int i = 0; i < LOOP; i++) {
y = x * -1;
}
long mid3 = System.nanoTime();
for (int i = 0; i < LOOP; i++) {
y = x / -1;
}
long end = System.nanoTime();
System.out.println(mid1 - start);
System.out.println(mid2 - mid1);
System.out.println(mid3 - mid2);
System.out.println(end - mid3);
}
}
Output is almost similar to :
2200211
835772
1255797
4651923
The speed difference between non-floating point (e.g. int math) addition/multiplication and bitwise operations is less than negligible on almost all machines.
There is no general way to turn an n-bit signed integer into its negative equivalent using only bitwise operations, as the negation operation looks like x = (~x) + 1, which requires one addition. However, assuming the signed integer is 32 bit you can probably write a bitwise equation to do this calculation. Note: do not do this.
The most common, readable way to negate a number is x = -x.
Java uses Complement Two representation. In order to change a sign, it means you must do a bitwise negation (it would be equivalent to xor with FFFF) and add 1.
x = ~x + 1;
I am almost sure that -x is, if anything, faster than that.
Solution using high level language
Questions like these are popular in interviews and competitive programming world .
I landed here researching more solution for negation of a number without using - or + operator .
For this :
complement a number using ~ operator
Then add 1 to the number obtained in step 1 using Half adder logic :
int addNumbers(int x, int y) {
if(y==0) return x; // carry is 0 return
addNumbers(x^y,(x&y)<<1); }
Here x^y performs addition of bits and x&y handles carry operation