Reputation: 6190
I am new at VHDL, and I am trying to do a Binary to BCD converter, I have serached on Internet and now I am trying to make my own to understand it and VHDL, here is my program:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Binary_to_BCD is
--generic(n: integer := 2);
Port ( data : in unsigned (7 downto 0);
bcdout : out unsigned (11 downto 0));
end Binary_to_BCD;
architecture Behavioral of Binary_to_BCD is
-- Inicio el proceso de conversion
begin
convert : process (data) is
variable i : integer := 0;
variable bin : unsigned (7 downto 0) := data;
variable bcd : unsigned (11 downto 0) := to_unsigned(0, 12);
begin
-- Repito por el numero de bits
for i in 0 to 7 loop
bcd := bcd sll 1; -- Desplazo un lugar a la izquierda el BCD
bcd(0) := bin(7); -- Ingreso el nuevo bit al BCD
bin := bin sll 1; -- Desplazo el bit que saque antes a la izquierda
-- Compruebo cada grupo de 4 bits del BCD, si se pasa de 4 le sumo 3
if(bcd(11 downto 8) > "0101") then
bcd(11 downto 8) := bcd(11 downto 8) + "0011";
end if;
if(bcd(7 downto 4) > "0101") then
bcd(7 downto 4) := bcd(7 downto 4) + "0011";
end if;
if(bcd(3 downto 0) > "0101") then
bcd(3 downto 0) := bcd(3 downto 0) + "0011";
end if;
end loop;
bcdout := bcd;
end process convert;
end Behavioral;
I get this error on line 66 which is bcdout := bcd;
:
Signal 'bcdout' bcdout is at left hand side of variable assignment statement.
After reading on the web and books I used unsigned
instead of std_logic_vector
because I need to rotate bits and arithmetic operations but still it doesn't synthesize.
Tried changing unsigned
to integer
and :=
to <=
but nothing works. It should be something very stupid but I don't realize. Thank you very much in advance.
Upvotes: 0
Views: 3926
Reputation:
The immediate problem is the incorrect use of variable assignment :=
instead of signal assignment <=
for the bcdout
signal - exactly as the error message and other answers point out.
However there is an underlying confusion about where you are in a VHDL process, that is not unusual when starting out - as revealed in the comments about functions.
A common approach to this confusion is to point out tht "VHDL is used for hardware design and not programming" that - while useful in some ways - can lead to artificially primitive and painfully low level uses of VHDL that are really holding it back.
Writing VHDL in a "software way" CAN work - and very well - however it does require a wider perspective on software AND hardware engineering than you can pick up through merely learning C.
The above code is probably synthesisable and will probably work - but it will almost certainly NOT do what you think it does. However a few small changes are in order rather than a completely different approach.
A couple of pointers may help :
the VHDL equivalent of a C function is a VHDL function.
the C equivalent of VHDL procedure is a void function.
(yes, C has procedures : it just calls them void functions to be contrary! :-)
the C equivalent of a VHDL process is ... a process. In other words, an entire C program as long as it doesn't use pthreads or fork/join.
And now you can see that VHDL is designed for parallel computation in a vastly more streamlined way than any dialect of C - processes are just building blocks, and signals are reliable forms of message passing or shared storage between processes.
So, within a process, you can (to a certain extent) think in software terms - but it is a HUGE mistake to think about "calling" a process as if it were a function. Apologies if you've seen this Q&A before but it will help understand the semantics of a VHDL process, and the use of signals between processes.
Now, as to the specific problems with your code:
1) It is asynchronous, i.e. unclocked. That means, guaranteeing how it responds to glitches on the input is ... difficult ... and knowing when the result is valid is harder than you need. Like uncontrolled use of global variables in C - not best practice!
So move to a clocked process for a safer, more analyzable design. This is also a step towards increasing its speed later. But for now, think of a VHDL clocked process as an event loop or perhaps an interrupt handler in C. It wakes up when told to, executes in (effectively) zero time, and sleep()s until next time.
convert : process (clk) is
variable bin : unsigned (7 downto 0);
...
begin
if rising_edge(clk) then
bin := data;
for i in 0 to 7 loop
...
end loop;
end if;
bcdout <= bcd;
end process convert;
2) the loops will be unrolled and generate a lot of hardware. This may not be a problem : it will deliver a result reasonably quickly (unlike the software equivalent!) There are ways to reduce the hardware use (state machines) or increase its speed (pipelining, link above) but they can wait for now...
3) This is actually the biggest problem with your original : your assignment of data
to bin
is actually a process variable initialisation not an assignment! It is only executed once, at t=0... And this is the most likely cause of any mis-operation you have seen.
The modified clocked example above assigns the latest data
value every time the process is woken : i.e. every clock cycle, and is thus more likely to do what you want.
4) Minor niggle : your declaration of "i" is redundant and actually hidden by a new implicit "i" created by the loop statement. This implicit declaration is both safer and better than an explicit one because it takes its type explicitly from the loop bounds. Imagine what might happen with for(int i; i<= 100000; i++)
when int
is a 16-bit type...
Upvotes: 2
Reputation: 1431
bcdout is a signal, and you are using the variable assignment operator := with it
replace line
bcdout := bcd;
with
bcdout <= bcd;
I've not tried to compile to see if there are any other problems, but that should answer your question.
Upvotes: 0
Reputation: 1789
Huh, strange. Have you tried making bcd a signal instead of a variable?
However, I think your main problem here is that you are trying to write VHDL in a "software" way, using a for loop and sequential logic. That is generally not the way you should write hardware descriptions. You should either use combinational logic, which involves concurrent assignment, or sequential logic, which involves doing things on the rising edge of the clock. It seems that what you are trying to implement is a combinational circuit. In that case, you should write separate concurrent assignments for each of your decimal digits. Take a look at http://www.csee.umbc.edu/portal/help/VHDL/concurrent.html for some examples of concurrent signal assignments. You will probably want to use either selected or conditional signal assignment.
Upvotes: 0