How to make while loop, with no definite bounds, synthesizable? - while-loop

I have this part of code which is not synthesizable because the number of times the loop will execute is not definite. I am a beginner with VHDL, how can I convert it to a synthesizable form?
Note: I tried doing it with for loop too, along with break statement, but it is still not synthesizable due to the break statement.
The code below is to calculate the value of ee such that the greatest common divisor of ee and Phi is 1.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity gcd11 is
Port ( ee : out integer;
Phi : in integer);
--gc : out integer);
end gcd11;
architecture Behavioral of gcd11 is
signal rem1,dd,dv,gc,temp: integer;
begin
process(temp,Phi,rem1,dd,dv,gc)
begin
gc<=2;
temp<=1;
while(gc/=1) loop
temp<=temp+1;
rem1<=1;
if (temp<Phi)then
dd<=Phi;
dv<=temp;
elsif(temp>=Phi) then
dd<=temp;
dv<=Phi;
end if;
while(rem1/=0) loop
rem1<= dd mod dv;
dd<=dv;
gc<=dv;
dv<=rem1;
end loop;
end loop;
ee<=temp;
end process;
end Behavioral;

First of all I would start with reading a book on VHDL as hardware design is very different from software design.
Next to that 3 main this that will not allow you to synthesis:
loops:
It's important to understand that a VHDL loop will not iterate like a software loop but is unfolded during synthesis and the resulting logic (all iterations) will run as parallel hardware blocks
Meaning that if you have a for loop that will run 8 times the circuit described will be instantiated 8 times. The follwing loop will create 8 parallel "AND" gates each taking 1 bit input from bus A and 1 bit from signal B.
for I in 0 to 7 loop
Z(I) <= A(I) and B;
end loop;
This means that at the moment you start the logic synthesis the amount of loops needs to be know as hardware can not be added/removed after synthesis.
mod:
Modulo function are in general not suited for synthisis. Only if your operands (inputs) are fixed (synthisis can calculate the output upfront) or you you have an statement that resembles the code below your synthesizer will allow it.(mod with a power of 2)
z <= y mod 2**x
signal declartion:
In VHDL that need to be synthezised you need to tell the tool how "large" (read: how many bits) a signal is. It is common practice to not use a blunt integer declaration but to use either a std_logic_vector type of an integer of a given range.
signal x : std_logic_vector(31 downto 0);
signal y : integer range 1 to 31;

Related

VHDL How to define integer range based on result from procedures declaration

I want to make my integer type signal range depend on output of some procedure i.e. something like this
procedure blah( signal A : in std_logic_vector(0 to 1); signal B : inout integer)
Begin
Case A is
When "00" => B <= 215;
When "01" => B <= 300;
When others => B <= 105;
end case;
End;
Next I want to use output from this procedure to define signal range of say type integer
Blah(A,myrange);
Signal myint: inout integer range 0 to myrange/23;
The difficulity is I can not use procedure in declaration of architecture, is there any way to define variable range for integer or is there a way to define integer range within architecture part after begin statement
As explained in the comments you cannot have a variable range for integer type. VHDL is a Hardware Description Language. On a pure hardware point of view, what would an integer type with variable range mean? Suppose you use the myint signal as an input of an adder. If its type changes during the lifetime of your hardware, it means that you have some dynamic silicon too. Some transistors would appear suddenly when the type range increases, and they would vanish when the type range decreases. It does not really make sense, does it?
So, if you understand this constraint, you must also understand that there is no need for varying signals to define your type. What you need is plain constant values that can be computed statically at the beginning of the simulation or logic synthesis. Two possibilities here:
First case: this A input that you use to compute the range is really an input of your design that can change during the lifetime of your hardware (switches of your board, for instance). Then, you must dimension your type to the worst case (300/23), such that it is always sufficient, even when A takes the worst case value "01":
signal myint: integer range 0 to 300 / 23;
Note: there is no mode specification for internal signal declarations, no inout. Internal signals can always be assigned and read. It is entity ports, for instance, that have a mode (in, out...) constraining how they can be used.
Second case: this A value is constant during the lifetime of your hardware. To make the point very clear, it means that if you decide to program an FPGA or to manufacture an Integrated Circuit (IC) with your design, you will fix the value of A before programming the FPGA or manufacturing the IC and the hardware will work only with this value. No way to change it afterwards without re-programming the FPGA or manufacturing another IC.
Then, if you are in this case, it would be much better to declare it as a generic parameter than as an input port or an internal signal. This is exactly what generic parameters are intended for. And, as explained in the comments, you cannot use a procedure here, but you can use a function. As your procedure has only one output, a function also does the job:
entity foo is
generic(A: std_logic_vector(0 to 1));
port(...);
end entity foo;
architecture rtl of foo is
function blah(val: in std_logic_vector(0 to 1)) return integer is
begin
case val is
when "00" => return 215;
when "01" => return 300;
when others => return 105;
end case;
end function blah;
signal myint: integer range 0 to blah(A) / 23;
If you really also need this procedure during operations (for a completely different purpose than declaring types), you can even use the function to define the procedure:
procedure blah(signal A: in std_logic_vector(0 to 1); signal B: out integer) is
begin
B <= blah(A);
end procedure blah;
Note that I changed the mode of B to out instead of inout because... it is only used as an output by your procedure, never as an input.

VHDL decimation(?) of data in specific way

My VHDL code doesn't behave as i expected.
What i want: i have 32 bit input data stream, and decimated 32 bit data output in some specific order.
Let's say each 32 bit data split into two 16 bit data.
first case: every second 16 bit of 32 bit data present on output;
second case: every fourth 16 bit of 32 bit data present on output;
third case fourth 16 bit of 32 bit data present on output
and so on.
Like in the picture:pic1
Here is first case of implementation:
process (CLK_IN, RST_IN)
begin
if (RST_IN = '1') then
rx_data_half_a <= (others => '0');
elsif rising_edge(CLK_IN) then
rx_data_half_a <= DATA_IN(15 downto 0);
end if;
end process;
process (CLK_IN, RST_IN)
begin
if (RST_IN = '1') then
rx_data_half_a0 <= (others => '0');
rx_data_half_a1 <= (others => '0');
elsif rising_edge(CLK_IN) then
rx_data_half_a0 <= rx_data_half_a;
rx_data_half_a1 <= rx_data_half_a0;
rx_data_half_a2 <= rx_data_half_a1;
DATA_OUT <= rx_data_half_a0 & rx_data_half_a;
end if;
end process;
And the testbench is looking like that:
sim
Instead of 00002222 44446666 ...
I get: 00002222 22224444 44446666 ...
I already do this job using memory (just counting specific addresses) but i dont' want to use it. I think there's much easiest way to implement this.
It is possible to do with registers without reducing the frequency?
Can you give me some advise?
You need a minimal state machine (eg: a counter) to track the input and update the data registers at the appropriate time. You logic is running every clock cycle and has no idea it needs to "skip" any of the incoming samples.
Since you are decimating, it is not possible to do this in registers or in memory without "reducing the frequency" in that you will have half (or 1/4 or whatever your decimation ratio is set to) as many output elements as input elements. If you use a memory you could burst at the full rate for a while, but you will still have to pause periodically and "re-fill" the buffer.

bubble sort in vhdl

Can anyone help me in writing VHDL code for bubble sort given an array of data as input?
I have declared in_array as input which contains 15 array elements. i want to bubble sort them in descending order.
in_array is input array.
sorted_array is out put array.
in_array_sig is signal of type in_array
I am facing problem with statements inside process
Below is my code:
architecture behav of Bubblesort is
signal in_array_sig : bubble;
signal temp : std_logic_vector(3 downto 0);
signal i : integer := 0;
begin
in_array_sig <= in_array;
proc1 : process(clk, reset)
begin
if reset = '0' then
if (clk'event and clk = '1') then
while (i <= 15) loop
if (in_array_sig(i) < in_array_sig(i + 1)) then
temp <= in_array_sig(i);
in_array_sig(i) <= in_array_sig(i + 1);
in_array_sig(i + 1) <= temp;
end if;
i <= i + 1;
end loop;
end if;
end if;
end process;
sorted_array <= in_array_sig;
end behav;
I am beginner in VHDL coding. Kindly help me with this.
The lack of a Minimal Complete and Verifiable example makes it hard to provide an answer about all the the things stopping your code from bubble sorting accurately. These can be described in the order you'd encounter them troubleshooting.
proc1 : process(clk, reset)
begin
if reset = '0' then
if (clk'event and clk = '1') then
while (i <= 15) loop
if (in_array_sig(i) < in_array_sig(i + 1)) then
temp <= in_array_sig(i);
in_array_sig(i) <= in_array_sig(i + 1);
in_array_sig(i + 1) <= temp;
end if;
i <= i + 1;
end loop;
end if;
end if;
end process;
Before starting note that the clock is gated with reset. You could qualify assignments with reset making it an enable instead.
Problems
The first thing we'd find producing an MCVe and a testbench is that the process never suspends. This is caused by the condition in the while loop depending on i and i a signal being updated within the process. i shouldn't be a signal here (and alternatively you could use a for loop here).
This also points out that temp is a signal and suffers the same problem, you can't use the 'new' value of temp until the process has suspended and resumed. Signals are scheduled for update, a signal assignment without a waveform element containing an after clause have an implicit after clause with zero delay. Signal updates do no occur while any process scheduled to resume has yet to resume and subsequently suspend. This allows the semblance of concurrency for signals who's assignments are found in sequential statements (a concurrent statement has an equivalent process containing equivalent sequential statements). So neither i nor temp can update during execution of a processes sequence of statements and both want to be variables.
We'd also get bitten using a signal for in_array_sig. As you increment i the previously indexed in_array_sig(i + 1) becomes the next loop iteration's in_array_sig(i). Without an intervening process suspend and resume the original value is available. in_array_sig wants to be a variable as well.
If we were to fix all these we'd also likely note that i is not initialized (this would be taken care of in a for loop iteration scheme) and we might also find that we get a bound error in a line using an (i + 1) index for in_array_sig. It's not clear without the author of the question providing an MCVe whether the array size is 16 (numbered 0 to 15) or 17. If the former i = 15 + 1 would be out of the index range for the undisclosed array type for in_array, in_array_sig, and sorted_array.
If we were to insure the index range is met noting that we only need 1 fewer tests and swaps than the number of elements in an array we'd find that what the process isn't a complete bubble sort. We would see the largest binary value of in_array_sig end up as the right most element of sorted_array. However the order of the remaining elements isn't guaranteed.
To perform a complete bubble sort we need another loop nesting the first one. Also the now 'inner' for loop can have a decreasing number of elements to traverse because each iteration leaves a largest remaining element rightmost until the order is assured to be complete.
Fixes
Fixing the above would give us something that looks like this:
architecture foo of bubblesort is
use ieee.numeric_std.all;
begin
BSORT:
process (clk)
variable temp: std_logic_vector (3 downto 0);
variable var_array: bubble;
begin
var_array := in_array;
if rising_edge(clk) then
for j in bubble'LEFT to bubble'RIGHT - 1 loop
for i in bubble'LEFT to bubble'RIGHT - 1 - j loop
if unsigned(var_array(i)) > unsigned(var_array(i + 1)) then
temp := var_array(i);
var_array(i) := var_array(i + 1);
var_array(i + 1) := temp;
end if;
end loop;
end loop;
sorted_array <= var_array;
end if;
end process;
end architecture foo;
Note the loop iteration schemes are described in terms of type bubble bounds, the outer is one shorter than the length and the inner is one shorter for each iteration. Also note the sorted_array assignment is moved into the process where the in_array_sig variable replacement var_array is visible.
Also of note is the use of the unsigned greater than operator. The ">" for std_logic_vector allows meta-values and 'H' and 'L' values to distort relational comparison while the operator for unsigned is arithmetic.
Results
Throw in package and entity declarations:
library ieee;
use ieee.std_logic_1164.all;
package array_type is
type bubble is array (0 to 15) of std_logic_vector(3 downto 0);
end package;
library ieee;
use ieee.std_logic_1164.all;
use work.array_type.all;
entity bubblesort is
port (
signal clk: in std_logic;
signal reset: in std_logic;
signal in_array: in bubble;
signal sorted_array: out bubble
);
end entity;
along with a testbench:
library ieee;
use ieee.std_logic_1164.all;
use work.array_type.all;
entity bubblesort_tb is
end entity;
architecture fum of bubblesort_tb is
signal clk: std_logic := '0';
signal reset: std_logic := '0';
signal in_array: bubble :=
(x"F", x"E", x"D", x"C", x"B", x"A", x"9", x"8",
x"7", x"6", x"5", x"4", x"3", x"2", x"1", x"0");
signal sorted_array: bubble;
begin
DUT:
entity work.bubblesort(foo)
port map (
clk => clk,
reset => reset,
in_array => in_array,
sorted_array => sorted_array
);
CLOCK:
process
begin
wait for 10 ns;
clk <= not clk;
if now > 30 ns then
wait;
end if;
end process;
end architecture;
and we get:
something that works.
The reset as enable has not been included in process BSORT in architecture and can be added in, inside the if statement with a clock edge condition.
And about here we get to Matthew Taylor's point in a comment about describing hardware.
Depending on the synthesis tool the process may or may not be realizable as hardware. If not you'd need intermediary variables holding the array portions used in each successive iteration of the inner loop.
There's also the issue of how much you can do in a clock cycle. Worst case there is a delay depth comprised of fifteen element comparisons and fifteen 2:2 selectors conditionally swapping element pairs.
If you were to pick a clock speed that was incompatible with the synthesized delay you'd need to re-architect the implementation from a software loop emulation to something operating across successive clocks.
That could be as simple as allowing more clock periods by using that enable to determine when the bubble sort is valid for loading into the sorted_array register. It could be more complex also allowing different and better performing sorting methods or a modification to bubble sort to say detect no more swaps can be necessary.

Combinational Logic Timing

I am currently trying to implement a data path, which calculates the following, in one clock cycle.
Takes input A and B and add them.
Shift the result of addition, one bit to right. (Dividing by 2)
Subtract the shifted result from another input C.
The behavioral architecture of the entity is simply shown below.
signal sum_out : std_logic_vector (7 downto 0);
signal shift_out : std_logic_vector (7 downto 0);
process (clock, data_in_a, data_in_b, data_in_c)
begin
if clock'event and clock = '1' then
sum_out <= std_logic_vector(unsigned(data_in_a) + unsigned(data_in_b));
shift_out <= '0' & sum_out(7 downto 1);
data_out <= std_logic_vector(unsigned(data_in_c) - unsigned(shift_out));
end if;
end process;
When I simulate the above code, I do get the result I expect to get. However, I get the result, after 3 clock cycles, instead 1 as I wish. The simulation wave form is shown below.
I am not yet familiar with implementing designs with timing concerns. I was wondering, if there are ways to achieve above calculations, in one clock cycle. If there are, how can I implement them?
Do do this with signals simply register only the last element in the chain (data_out). This analyzes, I didn't write a test bench to verify simulation.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity signal_single_clock is
port (
signal clock: in std_logic;
signal data_in_a: in std_logic_vector(7 downto 0);
signal data_in_b: in std_logic_vector(7 downto 0);
signal data_in_c: in std_logic_vector(7 downto 0);
signal data_out: out std_logic_vector(7 downto 0)
);
end entity;
architecture behave of signal_single_clock is
signal sum_out : std_logic_vector (7 downto 0);
signal shift_out : std_logic_vector (7 downto 0);
begin
sum_out <= std_logic_vector(unsigned(data_in_a) + unsigned(data_in_b));
shift_out <= '0' & sum_out(7 downto 1);
single_reg:
process (clock)
begin
if clock'event and clock = '1' then
data_out <= std_logic_vector(unsigned(data_in_c) - unsigned(shift_out));
end if;
end process;
end architecture;
When you assign a new value to a signal inside a process, this new value will be available only after the process finishes execution. Therefore, anytime you read the signal's value you will be using the original value from when the process started executing.
On the other hand, assignments to varibles take place immediately, and the new value can be used in the subsequent statements if you wish.
So, to solve you problem, simply implement sum_out, shift_out, and data_out using variables, instead of signals. Then simply copy the value of data_out to an output port of your entity.
Without using variables:
sum <= in_a + in_b;
process (clock)
begin
if rising_edge(clock) then
data_out <= in_c - ('0' & sum(7 downto 1));
end if;
end process;
All declarations except clock are unsigned(7 downto 0); why make it more complicated than that?
The original, pipelined to 3 cycles, will probably work at higher clock rates.
EDIT following comment:
I wanted to demonstrate that VHDL doesn't really have to be that verbose.
However there seem to be a lot of people "teaching" VHDL who are focussing on trivial elements and missing the big picture entirely, so I'll say a little bit about that.
VHDL is a strongly typed language, to prevent mistakes that creep in when types are mistaken for each other and (e.g.) you add two large numbers and get a negative result.
It does NOT follow from that, that you need type conversions all over the place.
Indeed, if you need a lot of type conversions, it's a sign that your design is probably wrong, and it's time to rethink that instead of ploughing ahead down the wrong path.
Code - in ANY language - should be as clean and simple as possible.
Otherwise it's hard to read, and there are probably bugs in it.
The big difference between a C-like language and VHDL is this:
In C, using the correct data types you can write sum = in_a + in_b;
and it will work. Using the wrong data types you can also write sum = in_a + in_b;
and it will compile just fine; what it actually does is another matter! The bugs are hidden : it is up to you to determine the correct types, and if you get it wrong there is very little you can do except keep on testing.
in VHDL, using the right types you can write sum <= in_a + in_b;
and using the wrong types, the compiler forces you to write something like sum <= std_logic_vector(unsigned(in_a) + unsigned(in_b)); which is damn ugly, but will (probably: see note 1) still work correctly.
So to answer the question : how do I decide to use unsigned or std_logic_vector?
I see that I need three inputs and an output. I could just make them std_logic_vectorbut I stop and ask: what do they represent?
Numbers.
Can they be negative? Not according to my reading of the specification (your question).
So, unsigned numbers... (Note 1)
Do I need non-arithmetic operations on them? Yes there's a shift.(Note 2)
So, numeric_std.unsigned which is related to std_logic_vector instead of natural which is just an integer.
Now you can't avoid type conversions altogether. Coding standards may impose restrictions such as "all top level ports must be std_logic_vector" and you must implement the external entity specification you are asked to; intermediate signals for type conversions are sometimes cleaner than the alternatives, e.g. in_a <= unsigned(data_in_a);
Or if you are getting instructions, characters and the numbers above from the same memory, for example, you might decide the memory contents must be std_logic_vector because it doesn't just contain numbers. But pick the correct place to convert type and you will find maybe 90% of the type conversions disappear. Take that as a design guideline.
(Note 1 : but what happens if C < (A+B)/2 ? Should data_out be signed? Even thinking along these lines has surfaced a likely bug that std_logic_vector left hidden...
The right answer depends on unknowns including the purpose of data_out : if it is really supposed to be unsigned, e.g. a memory address, you may want to flag an error instead of making it signed)
(Note 2 : there isn't a synthesis tool left alive that won't translate
signal a : natural; ... x <= a/2 into a shift right, so natural would also work, unless there were other reasons to choose unsigned. A lot of people seem to still be taught that integers aren't synthesisable, and that's just wrong.)

signal vs variable

VHDL provides two major object types to hold data, namel signal and variable, but I can't find anywhere that is clear on when to use one data-type over the other. Can anyone shed some light on their strengths/limitations/scope/synthesis/situations in which using one would be better than the other?
Signals can be used to communicate values between processes. Variables cannot. There are shared variables which can in older compilers, but you really are asking for problems (with race conditions) if you do that - unless you use protected types which are a bit like classes. Then they are same to use for communication, but not (as far as I know) synthesisable.
This fundamental restriction on communication comes from the way updates on signals and variables work.
The big distinction comes because variables update immediately they are assigned to (with the := operator). Signals have an update scheduled when assigned to (with the <= operator) but the value that anyone sees when they read the signal will not change until some time passes.
(Aside: That amount of time could be as small as a delta cycle, which is the smallest amount of time in a VHDL simuator - no "real" time passes. Something like wait for 0 ps; causes the simulator to wait for the next delta cycle before continuing.)
If you need the same logic to feed into multiple flipflops a variable is a good way of factoring that logic into a single point, rather than copying/pasting code.
In terms of logic, within a clocked process, signals always infer a flipflop. Variables can be used for both combinatorial logic and inferring a flipflop. Sometimes both for the same variable. Some think this confusing, personally, I think it's fine:
process (clk)
variable something : std_logic;
if rising_edge(clk) then
if reset = '1' then
something := '0';
else
output_b <= something or input c; -- using the previous clock's value of 'something' infers a register
something := input_a and input_b; -- comb. logic for a new value
output_a <= something or input_c; -- which is used immediately, not registered here
end if;
end if;
end process;
One thing to watch using variables is that because if they are read after they are written, no register output is used, you can get long chains of logic which can lead to missing your fmax target
One thing to watch using signals (in clocked processes) is that they always infer a register, and hence leads to latency.
As others have said signals get updated with their new value at the end of the time slice, but variables are updated immediately.
// inside some process
// varA = sigA = 0. sigB = 2
varA := sigB + 1; // varA is now 3
sigC <= varA + 1; // sigC will be 4
sigA <= sigB + 1; // sigA will be 3
sigD <= sigA + 1; // sigD will be 1 (original sigA + 1)
For hardware design, I use variables very infrequently. It's normally when I'm hacking in some feature that really needs the code to be re-factored, but I'm on a deadline. I avoid them because I find the mental model of working with signals and variables too different to live nicely in one piece of code. That's not to say it can't be done, but I think most RTL engineers avoid mixing... and you can't avoid signals.
Other points:
Signals have entity scoping. Variables are local to the process.
Both synthesize