Verilog : For loop inside an always - verilog

I am trying to implement a module that use a for loop inside a always block
We are using an array of 0 & 1 in order to record the number of signal received during a certain time.
Unfortunatly we received that kind of error :
ERROR:Xst:2636 - "Tourniquet.v" line 54: Loop has iterated 10000 times. Use "set -loop_iteration_limit XX" to iterate more.
It seems that the for loop isn't allowed inside a always block (The n doesn't seems to reset).
I have looked at various website and forum but don't have found any solutions.
Here is my code :
module Tourniquet(
input t0,
input mvt,
input clk,
output init
);
reg initialisation;
reg [0:99] memoire;
reg count = 0;
reg compteur = 0;
reg n;
assign init = initialisation;
always #(posedge clk)
begin
if (count==99)
begin
if (mvt)
begin
memoire[count]=1;
count=0;
end
else
begin
memoire[count]=0;
count=0;
end
end
else
begin
if (mvt)
begin
memoire[count]=1;
count = count + 1;
end
else
begin
memoire[count]=0;
count = count + 1;
end
end
end
always #(posedge clk)
begin
initialisation = 0;
for (n=0; n<99; n=n+1) compteur = compteur + memoire[n];
if (compteur>10) initialisation = 1;
compteur = 0;
end
endmodule
I can't find the solution nor be sure of what is the problem, any tips or help is welcomed.
Thank you very much !

You need the loop to iterate 100 times. For that, you need atleast 8 bit counter variable.
But here, n is declared as reg n, a single bit counter variable. So, n+1 gives 1 and doing n+1 again gives 0.
So, the condition of for loop for which n<100 is always satisfied. And the for loop never terminates.
This is the main reason your for loop iterates many many times.
Generally integer datatype is used for these kind of counters. integer is similar to 32 bit reg. Declare n as integer n or reg [7:0] n to have proper increment of counter and proper termination of loop.

Further to #sharvil111's answer, I see all these are single bits:
reg initialisation;
reg count = 0;
reg compteur = 0;
reg n;
An N bit reg in Verilog is normally declared, eg:
reg [N-1:0] n;
where N is some number (constant). And I see this is a 100-bit number:
reg [0:99] memoire;
Obviously, I don't know your design intent, but I suspect you wanted an array of N-bit numbers:
reg [N-1:0] memoire [0:99];
where N is again some number (constant).

Related

How to write verilog testbench to loop through a n bit input n times

I am writing a testbench to loop through a 16 bit Data input I have where it will go through each bit and change the value from a 0 to a 1, for example the first iteration would be 10000...00, second would be 010000...00, 001000...00, and so on. Here is what I have right now.
module testbench();
//inputs
reg [15:0] Data = 0;
//outputs
wire [15:0] Errors;
OLS uut (
.Data (Data),
.Errors (Errors)
);
integer k = 0;
initial
begin
Data = 0;
for(k = 0; k<16; k=k+1)
begin
Data[k] = 1;
if(k>0)
begin
Data[k-1] = 0;
end
end
end
endmodule
I am unsure if I have made a mistake with my testbench or if this is expected behavior, but I can't tell how I am supposed to see the expected output in each iteration. I have tried to use console outputs to keep track of where I am in the loop and if I am resetting the previous bit to 0 after I am done with that one.
I expect to get 0 in the 'Errors' output in every iteration, so basically I need help to verify my code does what I want it to do, and also how to read the graphical output of the simulation.
The loop in the post unrolls in 0 time.
Some delay is needed to create a waveform.
Also need a $finish, otherwise the testbench runs forever.
Like this:
module testbench();
//inputs
reg [15:0] Data = 0;
integer k = 0;
initial
begin
#100;
end
initial
begin
Data = 0;
for(k = 0; k<16; k=k+1)
begin
Data[k] = 1;
if(k>0)
begin
Data[k-1] = 0;
end
#5; // delay here
end
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule

How to assign variable pins to a port in verilog?

I have a 32-bit input port pins and a 32-bit input enable pin_en, and want to generate a 16-bit output selected by the enables. I wrote verilog like this, but seems there are some errors.
How can I fix it or any other way to achive? Thanks!
ps: No more than 16 pins selected by en, but maybe less.
input [31:0] pins;
input [31:0] pin_en;
output [15:0] actual_pins;
generate
genvar i;
localparam cnt = 0;
for(i = 0; (i < 'd32) & (cnt < 'd16); i = i + 'd1) begin : b1
if(pin_en[i]) begin
assign actual_pins[i] = pins[cnt];
cnt = cnt + 'd1;
end
end
if(cnt < 16)
assign actual_pins[16 : cnt] = 'b0;
endgenerate
I think that there are several errors in you code:
in generate blocks you cannot do any generation, based on the actual values of variables. The blocks are for the constant expressions only which could be resolved at compilation time, not at the run time. Also, you cannot modify anything in the generated blocks besides genvars. Paremeters (localparams) cannot be modified, so the cnt = cnt + 1 is just illegal there.
you messed up actual_pins and pins. by logic there should be actual_pins[cnt];
you use binary & operator, but you should have used logical && instead.
So, all your code should have been implemented in a run-time constructs, i.e., always blocks. You also need a trigger which will cause the always block to be evaluated. I created a small example where the always block is to be triggered by a clock.
module top (
input clk,
input [31:0] pins,
input [31:0] pin_en,
output reg [15:0] actual_pins
);
always #(posedge clk) begin
int cnt = 0;
int i;
for(i = 0; (i < 'd32) && (cnt < 'd16); i = i + 'd1) begin
if(pin_en[i]) begin
actual_pins[cnt] = pins[i];
cnt = cnt + 'd1;
end
end
for(; cnt < 16; cnt = cnt + 1)
actual_pins[j] = 1'b0;
end
endmodule

Verilog test bench for loop(priority, problem with value)

For i=0 and j=0 this code makes my a,b,cin and s signals to be xxxxxxxx.
For i=0 and j=1 my a,b,cin and s are all 00000000.Which should be the result for my adder for i=0 j=0 cin =0. Whats wrong? I am sure my adder module is correct.
http://prntscr.com/lpngel
http://prntscr.com/lpngih (...and so on)
Most of the trouble came at first with the for loops and began when some of the values werent printed and then after i added begin end in each loop i saw the full loop result whith the above problem^^^^^.Still dont know how it worked but it did
module test_cla4_n;
reg [7:0] a,b;
reg cin;
wire [7:0] s;
wire cout;
integer i;
integer j;
integer cv;
cla4_n#(.n(8)) UUT
(.a(a), .b(b),
.cin(cin),
.s(s), .cout(cout));
initial
begin
for(cv=0;cv<=1;cv=cv+1)
begin
for (i=0;i<6;i=i+1)
begin
for (j=0;j<6;j=j+1)
begin
#100 a = j; b = i; cin = cv;
end
end
end
end
initial
begin
$monitor($time, ,"a=%9b, b=%9b, cin=%b, sum=%9b", a, b, cin, s);
end
endmodule
Whether you put the #100 delay before or after the assignments does not matter as long as you understand how the delay works w.r.t. the loop.
The only place begin/end is required anywhere in the code you show is with the innermost for(j=0; ` loop.
All 4-state variables and nets in verilog are initialized with 'x'. Therefore, before you drive something in your simulation, all signals will remain 'x'.
In your test bench you use #100 delay in your loop. In your expression it means that all the assignments which follow #100 will happen only after 100 verilog simulation cycles (or whatever you set with 'timescale'). But before it all your values will remain 'x'.
Now when #100 triggers in you will have the following:
#100
a = j; <-- 0
b = i; <-- 0
cin = cv; <-- 0
j = j + 1; <-- 1 << from the loop
You end up with a = 0, b = 0, c = 0, and j will change to '1'.
Now your simulation will kick in and calculate the results for the above. You can continue this train of thoughts for the rest of simulation.
In order for all those statement to happen in side the loop after #100, yes you need to put begin/end around them. Otherwise only the first statement will be evaluated in the innermost loop. This is similar to any programming language.
for (j=0;j<6;j=j+1)
begin
#100 // wait here for 100 simulation ticks
a = j;
b = i;
cin = cv;
end

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.

Synthesizable Verilog modular shift register

I'm doing a LOTTT of pipelining with varying width signals and wanted a SYNTHESIZEABLE module wherein i could pass 2 parameters : 1) number of pipes (L) and 2) width of signal (W).
That way i just have to instantiate the module and pass 2 values which is so much simple and robust than typing loads and loads of signal propagation via dummy registers...prone to errors and et all.
I have HALF written the verilog code , kindly request you to correct me if i am wrong.
I AM FACING COMPILE ERROR ... SEE COMMENTS
*****************************************************************
PARTIAL VERILOG CODE FOR SERIAL IN SERIAL OUT SHIFT REGISTER WITH
1) Varying number of shifts / stages : L
2) Varying number of signal / register width : W
*****************************************************************
module SISO (clk, rst, Serial_in, Serial_out); // sIn -> [0|1|2|3|...|L-1] -> sOut
parameter L = 60; // Number of stages
parameter W = 60; // Width of Serial_in / Serial_out
input clk,rst;
input reg Serial_in;
output reg Serial_out;
// reg [L-1:0][W-1:0] R;
reg [L-1:0] R; // Declare a register which is L bit long
always #(posedge clk or posedge rst)
begin
if (rst) // Reset = active high
//**********************
begin
R[0] <= 'b0; // Exceptional case : feeding input to pipe
Serial_out <= 'b0; // Exceptional case : vomiting output from pipe
genvar j;
for(j = 1; j<= L; j=j+1) // Ensuring ALL registers are reset when rst = 1
begin : rst_regs // Block name = reset_the_registers
R[L] <= 'b0; // Verilog automatically assumes destination width # just using 'b0
end
end
else
//**********************
begin
generate
genvar i;
for(i = 1; i< L; i=i+1)
begin : declare_reg
R[0] <= Serial_in; // <---- COMPILE ERROR POINTED HERE
R[L] <= R[L-1];
Serial_out <= R[L-1];
end
endgenerate;
end
//**********************
endmodule
//**********************
Why so complicated? The following code would be much simpler and easier to understand:
module SISO #(
parameter L = 60, // Number of stages (1 = this is a simple FF)
parameter W = 60 // Width of Serial_in / Serial_out
) (
input clk, rst,
input [W-1:0] Serial_in,
output [W-1:0] Serial_out
);
reg [L*W-1:0] shreg;
always #(posedge clk) begin
if (rst)
shreg <= 0;
else
shreg <= {shreg, Serial_in};
end
assign Serial_out = shreg[L*W-1:(L-1)*W];
endmodule
However, looking at your code there are the following problems:
You declare Serial_in as input reg. This is not possible, an input cannot be a reg.
You are using generate..endgenerate within an always block. A generate block is a module item and cannot be used in an always block. Simply remove the generate and endgenerate statements and declare i as integer.
Obviously Serial_in and Serial_out must be declared as vectors of size [W-1:0].
You are using R as a memory. Declare it as such: reg [W-1:0] R [0:L-1].
You are not using i in you for loop. Obviously you meant to chain all the elements of R together, but you are just accessing the 0th, (L-1)th and Lth element. (Obviously the Lth element is nonexisting, this array would be going from 0 to L-1.
I'm now stopping writing this list because, I'm sorry, I think there really is not much to gain by improving the code you have posted..

Resources