Is there a more concise way to write the assign for this wire in Verilog? - verilog

Just trying to create a wire finished that is true iff data == dataNew for all registers and indexes. The only way I can come up with is using a bunch of finishedAgg wires as intermediate values; I'd love to get rid of them but I can't figure out how to. Seems like there has to be an easier way than this!
reg[24:0] data[0:24];
reg[24:0] dataNew[0:24];
wire finished;
genvar i;
generate
wire finishedAgg[-1:24];
assign finishedAgg[-1] = 1;
for (i=0; i<25; i=i+1) begin :b1
assign finishedAgg[i] = finishedAgg[i-1] & (data[i]==dataNew[i]);
end
assign finished = finishedAgg[24];
endgenerate

Here's my cut at it:
reg [24:0] finishAgg;
wire finished;
always #(*)
for (int i=0; i<25; i=i+1) begin :b1
finishedAgg[i] = (data[i]==dataNew[i]);
end : b1
assign finished = &finishedAgg;
It's not too much shorter than your version, but it doesn't need a generate block. I've declared i in-loop Systemverilog-style, and I'm using a reduction-AND to make the finished signal.

Related

Will temp variable in always_comb create latch

I have following code snippet where a temp variable is used to count number of 1s in an array:
// count the number 1s in array
logic [5:0] count_v; //temp
always_comb begin
count_v = arr[0];
if (valid) begin
for (int i=1; i<=31; i++) begin
count_v = arr[i] + count_v;
end
end
final_count = count_v;
end
Will this logic create a latch for count_v ? Is synthesis tool smart enough to properly synthesize this logic? I am struggling to find any coding recommendation for these kind of scenarios.
Another example:
logic temp; // temp variable
always_comb begin
temp = 0;
for (int i=0; i<32; i++) begin
if (i>=start) begin
out_data[temp*8 +: 8] = in_data[i*8 +: 8];
temp = temp + 1'b1;
end
end
end
For any always block with deterministic initial assignment, it will not generate latch except logic loop.
Sorry Eddy Yau, we seem to have some discussions going on regarding your post.
Here is some example code:
module latch_or_not (
input cond,
input [3:0] v_in,
output reg latch,
output reg [2:0] comb1,
output reg [2:0] comb2
);
reg [2:0] temp;
reg [2:0] comb_loop;
// Make a latch
always #( * )
if (cond)
latch = v_in[0];
always #( * )
begin : aw1
integer i;
for (i=0; i<4; i=i+1)
comb_loop = comb_loop + v_in[i];
comb2 = comb_loop;
end
always #( * )
begin : aw2
integer i;
temp = 7;
for (i=0; i<4; i=i+1)
temp = temp - v_in[i];
comb1 = temp;
end
endmodule
This is what came out if it according to the Xilinx Vivado tool after elaboration:
The 'latch' output is obvious. You will also notice that temp is not present in the end result.
The 'comb_loop' is not a latch but even worse: it is a combinatorial loop. The output of the logic goes back to the input. A definitely NO-NO!
General rule: if you read a variable before writing to it, then your code implies memory of some sort. In this case, both the simulator and synthesiser have to implement storage of a previous value, so a synthesiser will give you a register or latch. Both your examples write to the temporary before reading it, so no storage is implied.
Does it synthesisie? Try it and see. I've seen lots of this sort of thing in production code, and it works (with the synths I've used), but I don't do it myself. I would try it, see what logic is created, and use that to decide whether you need to think more about it. Counting set bits is easy without a loop, but the count loop will almost certainly work with your synth. The second example may be more problematical.

verilog compile error - "variable not constant"

Why am I getting error "q is not constant"?
module prv(
input [7:0]x,
input [7:0]y,
output [49:0]z
);
wire [24:0]q;
assign z=1;
genvar k;
for (k=50; k<0; k=k-1)
begin
wire [25:0]a;
assign a=0;
assign q= x;
genvar i;
for(i=0; i<8; i=i+1)
begin
if(q[0]==1)
begin
assign a=a+z;
end
assign {a,q}={a,q}>>1;
end
assign z={a[24:0],q};
end
endmodule
I'm afraid that you are trying to use Verilog the wrong way. q is a wire, not a variable (a reg) so it cannot be assigned with a value that includes itself, because that would cause a combinational loop. You are using the assign statement as if it were a regular variable assignment statement and it's not.
Declare a and q as reg, not wire. i and k don't need to be genvars variables, unless you are trying to generate logic by replicating multiple times a piece of code (description). For for loops that need to behave as regular loops (simulation only) use integer variables.
Besides, behavioral code must be enclosed in a block, let it be combinational, sequential, or initial.
A revised (but I cannot make guarantees about its workings) version of your module would be something like this:
module prv(
input wire [7:0] x,
input wire [7:0] y,
output reg [49:0] z
);
reg [24:0] q;
reg [25:0] a;
integer i,k;
initial begin
z = 1;
for (k=50; k<0; k=k-1) begin
a = 0;
q = x;
for (i=0; i<8; i=i+1) begin
if (q[0] == 1) begin
a = a + z;
end
{a,q} = {a,q}>>1;
end
z = {a[24:0],q};
end
endmodule

How to dynamically reverse the bit position in verilog?

wire [9:0] data_reg;
reg [3:0] Reverse_Count = 8; //This register is derived in logic and I need to use it in following logic in order to reverse the bit position.
assign data_reg[9:0] = 10'h88; // Data Register
genvar i;
for (i=0; i< Reverse_Count; i=i+1)
assign IReg_swiz[i] = IReg[Reverse_Count - 1 -i];
This is generating syntax error. May I know how to do this in verilog
If you'd have Reverse_Count as constant, your task boils down to just wire mix-up, which is essentially free in HDL.
In your case, the task can be nicely reduced to first mirroring wide data and then shifting by Reverse_Count to get LBS bit on its position, which itself is done just by a row of N-to-1 multiplexers.
integer i;
reg [9:0] reversed;
wire [9:0] result;
// mirror bits in wide 10-bit value
always #*
for(i=0;i<10;i=i+1)
reversed[i] = data_reg[9-i];
// settle LSB on its place
assign result = reversed>>(10-Reverse_Count);
Reverse_Count is not a constant, ie it is not a parameter or localparam.
This means that the generate statement you would be creating and destroying hardware as required, this is not allowed in verilog as it would not be possible in hardware.
The Bus that your reversing should have a fixed width at compile time, it should be possible to declare Reverse_Count as a parameter.
Since the value of Reverse_Count dunamic, you cannot use a generate statement. You can use an always block with for-loop. To be synthesizable, the for-loop needs able to static unroll. To decide which bits reverse, use an if condition to compare the indexing value and Reverse_Count
Example:
parameter MAX = 10;
reg [MAX-1:0] IReg_swiz;
integer i;
always #* begin
for (i=0; i < MAX ; i=i+1) begin
if (i < Reverse_Count) begin
IReg_swiz[i] = IReg[Reverse_Count - 1 -i];
end
else begin
// All bits need to be assigned or complex latching logic will be inferred.
IReg_swiz[i] = IReg[i]; // Other values okay depending on your requirements.
end
end
end

Verilog HDL syntax error near text "for"; expecting "endmodule"

So I just got around to learning verilog and I was implementing a basic binary adder in it.
From my limited understanding of verilog, the following should add two 16-bit values.
module ADD(X, Y, Z);
input[15:0] X;
input[15:0] Y;
output Z[15:0];
wire C[15:0];
assign C[0] = 0;
integer i;
for(i=1; i<16; i=i+1) begin
assign C[i]=(X[i-1]&Y[i-1])|(X[i-1]&C[i-1])|(Y[i-1]&C[i-1]);
end
for(i=0; i<16; i=i+1) begin
assign Z[i]=X[i]^Y[i]^C[i];
end
endmodule
However, I get an error when I try to synthesize the above.
Error (10170): Verilog HDL syntax error at add.v(10) near text "for"; expecting "endmodule"
I'm not sure what is wrong with the code. Any help is appreciated!
The for-loop is used outside of an always block, so i needs to be a genvar instead of an integer. Also, you probably want Z and C to declared an packed arrays instead of unpacked, mo the [15:0] to the other side.
output [15:0] Z; // make as packed bits
wire [15:0] C;
assign C[0] = 0;
genvar i; // not integer
generate // Required for IEEE 1364-2001, optional for *-2005 and SystemVerilog
for(i=1; i<16; i=i+1) begin
assign C[i]=(X[i-1]&Y[i-1])|(X[i-1]&C[i-1])|(Y[i-1]&C[i-1]);
end
for(i=0; i<16; i=i+1) begin
assign Z[i]=X[i]^Y[i]^C[i];
end
endgenerate // must be matched with a generate
Alternative solution 1: use an always block
output reg[15:0] Z; // make as reg
reg [15:0] C;
integer i; // integer OK
always #* begin
for(i=1; i<16; i=i+1) begin
if (i==0) C[i] = 1'b0;
else C[i]=(X[i-1]&Y[i-1])|(X[i-1]&C[i-1])|(Y[i-1]&C[i-1]);
Z[i]=X[i]^Y[i]^C[i];
end
end
Alternative solution 2: bit-wise assignment
output [15:0] Z;
wire [15:0] C = { (X&Y)|(X&C)|(Y&C) , 1'b0 };
assign Z = X^Y^C;
Alternative solution 3: behavioral assignment
output [15:0] Z;
assign Z = X+Y;
Working examples here
Change the definition of i from integer to genvar.
Notice that for loops can be used either in an always block or in a generate block. The latter is implicitly the context that you are using it in your code. In generate blocks, the loop variable should be of type genvar.
More info in IEEE Std 1800-2012

How to represent assign logic array in Verilog generate block?

I have difficulties in representing a simple assignment with generate block.
My intention is
assign bus = disp[0] | disp[1] | disp[2] ...;
The following code does not work. How can I fix it? Such accumulation related assignments does not appear in the Verilog mannual. Thanks in advance for any advice.
genvar varx;
for (varx = 0; varx < `N; varx = varx + 1) begin
if (varx == 0) assign bus = disp[0];
else assign bus = bus | disp[varx];
end
That is an incorrect usage of generate and assign.
generates should not be used that liberally in Verilog and their use should be something special like extending a module for parametrization etc.
If it can be statically unrolled (as per your usage here) then a plain for loop could have been used. Generates would typically be used for parametrizing module instantiations;
assign should be once per wire and constantly drives the right hand side expression on to that wire.
Your code looks like you are simply trying to OR the disp bus, this can be achieved with an OR reduction operator:
wire bus;
assign bus = |disp ;
Update1
disp is actually defined as a memory and we are not trying to calculate a single bit or reduction. Here a for loop can be used to calculate the OR.
logic [3:0] data [5:0];
logic [3:0] or_data;
integer i;
always #* begin
or_data = 4'b0;
for(i=0; i<6; i=i+1) begin
or_data = or_data | data[i] ;
end
end
Simple Simulation:
logic [3:0] data [5:0];
logic [3:0] or_data;
integer i;
initial begin
for(i=0; i<6; i=i+1) begin
data[i] = i*2;
end
#1ns;
for(i=0; i<6; i=i+1) begin
$displayb(data[i]);
end
or_data = 4'b0;
for(i=0; i<6; i=i+1) begin
or_data = or_data | data[i] ;
end
#1ns;
$displayb(or_data);
end

Resources