Loop Convergence - Verilog Synthesis - verilog

I am trying to successively subtract a particular number to get the last digit of the number (without division). For example when q=54, we get q=4 after the loop. Same goes for q=205, output is q=5.
if(q>10)
while(q>10)
begin
q=q-10;
end
The iteration should converge logically. However, I am getting an error:
"[Synth 8-3380] loop condition does not converge after 2000 iterations"
I checked the post - Use of For loop in always block. It says that the number of iterations in a loop must be fixed.
Then I tried to implement this loop with fixed iterations as well like below (just for checking if this atleast synthesizes):
if(q>10)
while(loopco<9)
begin
q=q-10;
loopco=loopco-1;
end
But the above does not work too. Getting the same error "[Synth 8-3380] loop condition does not converge after 2000 iterations". Logically, it should be 10 iterations as I had declared the value of loopco=8.
Any suggestions on how to implement the above functionality in verilog will be helpful.

That code can not be synthesized. For synthesis the loop has to have a compile time known number of iterations. Thus it has to know how many subtractions to make. In this case it can't.
Never forget that for synthesis you are converting a language to hardware. In this case the tool needs to generate the code for N subtractions but the value of N is not known.
You are already stating that you are trying to avoid division. That suggest to me you know the generic division operator can not be synthesized. Trying to work around that using repeated subtract will not work. You should have been suspicious: If it was the easy it would have been done by now.
You could build it yourself if you know the upper limit of q (which you do from the number of bits):
wire [5:0] q;
reg [3:0] rem;
always #( * )
if (q<6'd10)
rem = q;
else if (q<6'd20)
rem = q - 6'd10;
else if (q<6'd30)
rem = q - 6'd20;
etc.
else
rem = q - 6'd60;
Just noticed this link which pops up next to your question which shows it has been asked in the past:
How to NOT use while() loops in verilog (for synthesis)?

Related

Verilog - masking using 1 bit input

I have a situation I'm not sure what's the right syntax that exists which can solve it.
In my code I have
reg [N-1:0] bit_list;
and another variable n which counts how many bits I inserted into bit_list.
Occasionally and according to the input - I need to, during a single posedge, shift bit_list by 1 then change bit_list[N-n] to my input. My idea was I can do the following
bit_list<=bit_list<<1 || X
Where X should be replaced some N-1 long vector that has zeros in all bits except for N-n. The problem is I don't know to describe such a vector - Hence my question.
I'm sure my problem is simple enough to be solved in a variety of simple ways, so any solution to my problem will work.
Sorry if my question is noobish as I'm still new, help will be appriciated of course.
You can use a mask. (BTW || is logical-or, you want | a bitwise-or)
reg [N-1:0] mask;
mask = ({ {N{1'b0}},1'b0}) << n) - 1; // the concat is needed in case N > 32
bit_list<=((bit_list<<1) & ~mask) | (X & mask);

Using real parameter to determine counter sizes

I am trying to make my debounce code more modular by passing in parameters that are the frequency and the desired bounce time to eliminate button/switch bounce. This is how I approached it:
module debounceCounter
#(
parameter CLOCK_FREQUENCY_Hz = 50_000_000,
parameter BOUNCE_TIME_s = 0.003
)
(
input wire sysClk, reset,
input wire i_async,
output reg o_sync
);
/* include tasks/functions */
`include "clog2.v"
/* constants */
parameter [(clog2(BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz + 0.5) - 1) : 0]
MAX_COUNT = BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz;
Synthesis using Xilinx ISE 14.7 Throws this error:
Xst:850 - "../../rtl/verilog/debounceCounter.v" line0: Unsupported real
constant
How can I get around this issue so that I can determine the counter size and max count value based on parameters being passed in from code above this module in the heirarchy? A majority of my code has sizes of variables and such determined by frequency generics, so not being able to use methods like VHDL has proven to create problems in my designs.
Seems to work fine on Vivado 2016.3 (the oldest I have available). I think the problem is that 2014.7 is too old to support this. You didn't show the contents of the `include, but I'm assuming its the one from AR# 44586. If so, it should take and return integers and it will truncate the real floating point values for you. Floating point arithmetic is fine to use in Verilog/SystemVerilog testbenches and parameters.
How can I get around this issue so that I can determine the counter
size and max count value based on parameters being passed in from code
above this module in the heirarchy?
Update to a recent version. 2017.1 or 2017.3 are working good for me. I tested the following on 2016.3 and it also worked fine.
Try using SystemVerilog (.sv) which supports the $clog2() system function natively without the `include. Not sure when .sv started working, but probably needs 2015+.
Verify that your version of clog2 in the clog2.v header matches the following
NOTE: There is another pretty serious bug in the code you posted.
When you want to get the MSB required to hold a constant expression "x" the pattern should be $clog2((x)+1)-1. You have only added 0.5 instead of 1. This causes there to not be enough bits whenever the result of the floating point expression "x" falls between 2^n and (2^n + 0.5). For example, what you have erronously computes the constant as 17'h0 instead of 18'h4_0000 for the the frequency 87381333 but it still appears to work for your example at 50Mhz. Murphy's law says you will accidentally fall into this narrow bad range at the worst possible time, but never during testing :).
For reference, this is what I tested, with the `include expanded inline:
`timescale 1ns / 1ps
module debounceCounter
#(
//parameter CLOCK_FREQUENCY_Hz = 50_000_000,
parameter CLOCK_FREQUENCY_Hz = 87381333, // whoops
parameter BOUNCE_TIME_s = 0.003
)
(
input wire sysClk, reset,
input wire i_async,
output reg o_sync
);
/* include tasks/functions */
//`include "clog2.v"
function integer clog2;
input integer value;
begin
value = value-1;
for (clog2=0; value>0; clog2=clog2+1)
value = value>>1;
end
endfunction
/* constants */
//parameter [(clog2(BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz + 0.5) - 1) : 0] // <- BUG!!! 0.5 should 1
parameter [(clog2(BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz + 1) - 1) : 0]
MAX_COUNT = BOUNCE_TIME_s * CLOCK_FREQUENCY_Hz;
initial
$display("MAX_COUNT %d", MAX_COUNT);
endmodule
Type Real is not synthesizable. Draw/Create your design before you translate into/write HDL and you will realize this. Ask yourself, "What does a real synthesize to in gates?"
For those tools (e.g. Synplify) that do "support" Type Real, it is just a vendor interpretation, and as such is impossible to "support" since it is not defined as part of any HDL standard. The implication: If you had a simulator that interprets Type Real one way, and your synthesizer (likely) interprets it another way, you will get sim/syn mismatches. You may get away with them, depending on what you are trying to accomplish, but, it would still be considered poor design practice.
Behavioral code, for modeling and use in testbenches, as stated above, a different story as it is not synthesized.

Counting of different channels diverge and jumps

I'm trying to realize a counting module. My basic setup:
FPGA (Digilent's Arty with Xilinx Artix-35T) with two BNC cables attached to IO ports connected to a signal generator and via USB/UART to the PC for reading out. My signal generator produces with, say, 1 Hz some TTL signal.
I now want to count the amount of events in channel 1, in channel 2 and the coincidences of channels 1 and 2. While the basic principle works, I see channels 1 and 2 separate, even though they have the same input (via BNC-T connector). Also, sometimes one of the output channels jumps - in either direction, see figure.
The violet channel ("Channel 1") has a different slope than green ("Channel 2"). Also the coincidences make here two little lossy jumps.
My sequential counting code looks like
reg [15:0] coinciInt [(numCoincidences -1):0]; // internally store events
always #(posedge clk or posedge reset) // every time the clock rises...
begin
signalDelay <= signal; // delayed signal for not counting the same event twice
if(reset) // reset
begin
for(i=0;i<numCoincidences;i=i+1)
coinciInt[i] <= 16'b0;
end
else // No reset
begin
for(i=1;i<numCoincidences;i=i+1) // loop through all coincidence possibilities:
begin
if( ((signal & i) == i) && ((signalDelay & i) != i) ) // only if signal give coincidence, but did not give before, it's a coincidence
begin // "(signal & i) == i" means that "signal" is checked if bitmask of "i" is contained:
// ((0011 & 0010) == 0010) is true, since 0011 & 0010 = 0010 == 0010
coinciInt[i] <= coinciInt[i] + 1'b1; // the i-th coincidence triggered, store it
end
end
end
end // end of always
assign coinci = coinciInt; // the output variable is called coinci, so assign to this one
Please note that all events are in the register coinci - coincidences as well as 'single events'. Ideally, coinci[1] should store events of channel 1, coinci[2] these of channel 2 and coinci[3] coincidences between 1 and 2, since channels are labelled by 1,2,4,8,...,2^n and coincidences by the respective sum. coinci[0] is used for some kind of checksum, but that's off-topic now.
Are there any ideas for the missing counts? For the different slopes?
Thank you very much
Edit 1
#Brian Magnuson pointed to the meta stability issue. Using multi-buffered inputs solved the issue of diverging channels. That works nicely. Although I don't fully understand the reason for this, I also did not see any jumps in the coincidence channel so far. You probably save me a lot of time, thanks!
I would suspect a meta-stability problem. Your incoming pulses on ch1/ch2 are probably not synchronized with the system clock you are using. See here.
Because of this you are probably sometimes catching the counter updates 'mid-stride' so to speak which will cause unexpected behavior.
To fix this you can flop the inputs twice (called a dual-rank synchronizer) before feeding them into the rest of your logic. Usually multi-bit synchronization requires a bit more careful handling but in your case each bit can be treated independently.

Use of For loop in always block

I am writing a Verilog code for calculating the number of digits in a decimal number. In the code below I have initialised the value of c to be equal to a.
I was able to get the simulation results correctly but unable to syntesise and the error is due to 'c=a'. How can I get rid of the error ? Is there any other logic to calculate the number of digits ?
Error: [Synth 8-3380] loop condition does not converge after 2000 iterations
Code :-
module numdigits(a,b);
parameter n=100;
input [0:n-1] a;
output reg [0:n-1]b; //THIS MODULE COUNTS THE NUMBER OF DIGITS IN DECIMAL FORM
reg [0:n-1] d,c;
always #(*)
begin
d=0;
for(c=a;c>0;c=c/10)
begin
d=d+1;
end
b=d;
end
endmodule
In order for a for loop to be synthesisable, it must be static: that is, the maximum number of iterations round the loop must be fixed. It might seem that there is a maximum number of iterations of your loop, given that a has a fixed number of bits, but remember that your synthesiser doesn't simulate your code, so it cannot tell that.
You need to refactor your code; you need to write it in such a way so that the maximum number of loop iterations is fixed. In other words, the number of iterations of the loop must be fixed, but you can jump out early if you wish (using the disable statement).

verilog changing random seed

How do I change the seed for $urandom_range every time I am starting a new simulation. I tried so many things non worked.
always#(posedge tb_rd_clkh)
begin
$random(9);
tbo9_ready_toggle_q <= $urandom_range(0, 1);
end
You can change the seed using a flag like this:
irun -seed seed_number
Or you can use a random seed:
irun -seed random
I'm pretty sure every tool (Questa and VCS) has an option to do this. If you don't set a seed, it will default to 1.
Set the seed value by using the conventional way before accessing the range of random numbers using urandom_range
seed = 2;
void'($urandom(seed));
Here the above code snippet will set the seed value to 2 for uramdom_range too and every time you run, random number generator creates the same sequence as long as the seed is same, you can find a working example at the EDA-Playground
UPDATE:
For your question how to set seed for urandom_range insde always block? A more generalized way as per SV LRM IEEE 1800 - 2012 Section 18.13.3 srandom()
The srandom() method allows manually seeding the RNG of objects or
threads.
Thus by making use of it created a simplified self contained example to show how to set seed inside always block
module dut(input clk,output reg [31:0] out);
integer seed;
assign seed = 10;
always # (posedge clk)
begin
$srandom(seed);
out <= $urandom_range (10,1);
$display ("out = %d",out);
end
endmodule
You may want to try this out, the above example with tb can be found in the link.
Solution to your question
In your code snippet you have to change $random(9) to $srandom(9) were 9 is the seed value

Resources