VHDL: unexpected END using functions - function

I'm trying to synthesize some code I've found which essentially converts an 8-bit binary to BCD. The code uses functions and I'm having an error of the following;
Line #: parse error, unexpected END
The following is the behavior part of my code;
architecture Behavioral of bintobcd is
function to_bcd ( bin : std_logic_vector(7 downto 0) ) return std_logic_vector is
variable i : integer:=0;
variable bcd : std_logic_vector(11 downto 0) := (others => '0');
variable bint : std_logic_vector(7 downto 0) := bin;
begin
for i in 0 to 7 loop -- repeating 8 times.
bcd(11 downto 1) := bcd(10 downto 0); --shifting the bits.
bcd(0) := bint(7);
bint(7 downto 1) := bint(6 downto 0);
bint(0) :='0';
if (i < 7 and bcd(3 downto 0) > "0100") then --add 3 if BCD digit is greater than 4.
bcd(3 downto 0) := bcd(3 downto 0) + "0011";
end if;
if (i < 7 and bcd(7 downto 4) > "0100") then --add 3 if BCD digit is greater than 4.
bcd(7 downto 4) := bcd(7 downto 4) + "0011";
end if;
if (i < 7 and bcd(11 downto 8) > "0100") then --add 3 if BCD digit is greater than 4.
bcd(11 downto 8) := bcd(11 downto 8) + "0011";
end if;
end loop;
return bcd;
end to_bcd;
end Behavioral;
The error points to my last line "end Behavioral". What am I doing wrong here?
Kind regards

The definition of an architecture is as follows:
architecture identifier of entity_name is
architecture_declarative_part
begin
architecture_statement_part
end optional(architecture) optional(architecture_simple_name) ;
Before you say end architecture, you need to say begin, and do the architecture statement part (which can be empty)

Related

Conversion of 8-bit binary number to decimal number for 7 segment decoder

I am currently a beginner programming to an FPGA board in VHDL using Quartus II. I need to convert an 8 bit number of type std_logic_vector to three separate 4 bit std_logic_vector variables so that i may display a decimal number on three 7 segment displays (the largest number in that will be dealt with is 254). currently i am using repeated subtraction division to handle this, however in compilation the while loop which i use is unable to resolve within 10000 iterations. the loop is shown below:
while (rmdr > "000000000") loop
while (rmdr > "000001001") loop
while (rmdr > "001100011") loop
dig2 := dig2 + '1';
rmdr := rmdr - "001100100";
end loop;
dig1 := dig1 + '1';
rmdr := rmdr - "000001010";
end loop;
dig0 := dig0 + '1';
rmdr := rmdr - "000000001";
end loop;
Any help or insight to this matter would be greatly appreciated.
I looks like you need `BCD converter.
Have a look at this website
8 bit binary to bcd convertor
function to_bcd ( bin : std_logic_vector(7 downto 0) ) return std_logic_vector is
variable i : integer:=0;
variable bcd : std_logic_vector(11 downto 0) := (others => '0');
variable bint : std_logic_vector(7 downto 0) := bin;
begin
for i in 0 to 7 loop -- repeating 8 times.
bcd(11 downto 1) := bcd(10 downto 0); --shifting the bits.
bcd(0) := bint(7);
bint(7 downto 1) := bint(6 downto 0);
bint(0) :='0';
if(i < 7 and bcd(3 downto 0) > "0100") then --add 3 if BCD digit is greater than 4.
bcd(3 downto 0) := bcd(3 downto 0) + "0011";
end if;
if(i < 7 and bcd(7 downto 4) > "0100") then --add 3 if BCD digit is greater than 4.
bcd(7 downto 4) := bcd(7 downto 4) + "0011";
end if;
if(i < 7 and bcd(11 downto 8) > "0100") then --add 3 if BCD digit is greater than 4.
bcd(11 downto 8) := bcd(11 downto 8) + "0011";
end if;
end loop;
return bcd;
end to_bcd;

Vhdl Multiplier usage too low

My design utilizes the Spartan 3E XC35100E device. I can use a total of 4 MUX. However, despite using 3 * signs and a FFT block (which also uses 3 MUX), the design summary specifies that I only use 1 MUX. Even when I use CLB logic in place of MUX for the FFT block, the design summary is the same.
Implementation and simulation are able to take place without any problems. So, why is the number of MUX I use so low? Any help would be greatly appreciated.
relevant libraries, port maps and signal declarations are excluded for brevity.
process (clk)
variable fsm : integer range 0 to 3:= 0;
variable i : integer range 0 to 127:= 0;
begin
if rising_edge(clk) then
if fsm = 0 then
tasiyici <= STD_LOGIC_VECTOR(to_signed(sample_1(i)* sample_2(i) , 16));
--sample1 and sample 2 are arrays with constant values
fsm := fsm +1;
elsif fsm = 1 then
wea_select <= '0';
wea_ram<= "1";
ram_write <= '0';
dina <= STD_LOGIC_VECTOR(tasiyici(15 downto 8));
mult_out<= STD_LOGIC_VECTOR(tasiyici(15 downto 8));
fsm := fsm +1;
elsif fsm = 2 then
address_write <= std_logic_vector(unsigned(addra) + 1);
wea_ram<= "0";
i := i+1 ;
if i=128 then
fsm:=3;
ram_write <= '1';
wea_select <= '1';
else
fsm := 0;
end if;
end if;
end if;
end process;
----FFT process---
process(clk)
variable fsm : integer range 0 to 7:= 0;
variable i : integer range 0 to 128;
variable counter : integer range 0 to 2:= 0;
variable j : integer range 0 to 512;
begin
if rising_edge(clk) then
if fsm = 0 then -- ram_write is control
if ram_write = '1' then
wea_fft <= "0";
fsm:= 1;
end if;
elsif fsm = 1 then --process start (pulse)
start <= '1';
fwd_inv_we <= '1';
fsm := fsm +1;
elsif fsm = 2 then
start <= '0';
fwd_inv_we <= '0';
fsm := fsm +1;
elsif fsm =3 then --128 cycle send data from douta to xn_re
if i= 128 then
fsm := fsm +1;
else
xn_re <= douta;
address_read <= std_logic_vector(unsigned(addra) + 1);
i:=i+1;
fsm := 3;
end if;
elsif fsm =4 then --all data sent. process complete
if done = '1' then --wait for done finish 3 clk cycle, then unload
if counter= 2 then
fsm := fsm +1;
else
counter := counter +1;
fsm :=4;
end if;
end if;
elsif fsm =5 then
counter := 0;
unload <= '1';
fsm := fsm +1;
fft_data_ready <= "1";
wea_fft<= "1";
elsif fsm =6 then --wait 512 clk cycle to read all outputs
unload <= '0';
wea_fft<= "0";
if dv = '1' then
fft_output <= std_logic_vector(signed(xk_re(15 downto 4))*signed(xk_re(15 downto 4))
+signed(xk_im(15 downto 4))*signed(xk_im(15 downto 4)));
if j=512 then
fsm:=fsm+1;
else
j:=j+1;
fsm:=6;
end if;
else
fsm:=6;
end if;
end if;
end if;
end process;
It seems like your design has simply been optimized.
You should check the RTL that is synthesized to check that your design has been synthesized the way that you wanted

VHDL internal signal to change output - not working?

I have this PC module, very simple (Code at the end). I first generate some input signal port_int and at the end of the process say pc_out <= port_int. My goal is to either increment or add or subtract from PC, depending on input signals.
In the simulation, the internal port_int signal works fine, but pc_out doesn't. Why is this happening? Look at the simulation:
Look how port_int changes as it should, while pc_out is late. Later in the simulation, pc_out gets even worse, changing irregularly, not even just being late.
What am I doing wrong? Is there another way to change pc_out? Bcoz you can't change out signals, and I've been told that inout is extremely bad practice..
Here's the code:
entity PC is
Port ( clk : in STD_LOGIC;
enable : in STD_LOGIC;
reset : in STD_LOGIC;
pc_out : out STD_LOGIC_VECTOR (3 downto 0);
data : in STD_LOGIC_VECTOR (3 downto 0); -- jump value
zero : in STD_LOGIC; -- jump condition
jmp_en : in STD_LOGIC; -- jump enable
jmp_dir : in STD_LOGIC; -- jump direction
ctrl_en : out STD_LOGIC); -- output signal
end PC;
architecture Behavioral of PC is
type state_type is (s0, s1, s2, s3);
signal reg_state, next_state : state_type;
signal port_int : std_logic_vector(3 downto 0);
begin
state_transition: process(clk, reset)
begin
if (reset = '1') then
reg_state <= s0;
elsif(rising_edge(clk)) then
reg_state <= next_state;
end if;
end process;
next_state_logic: process(reg_state, enable)
begin
case reg_state is
when s0 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
when s1 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
when s2 =>
next_state <= s3;
when s3 =>
if(enable = '1') then
next_state <= s2;
else
next_state <= s1;
end if;
end case;
end process;
output_logic: process(reg_state, zero, jmp_en, jmp_dir, data)
begin
case reg_state is
when s0 =>
pc_out <= "0000";
port_int <= "0000";
ctrl_en <= '0';
when s1 =>
ctrl_en <= '0';
when s2 =>
if(zero = '1' and jmp_en = '1' and jmp_dir = '1')then
port_int <= port_int + data; -- jump forward
elsif(zero = '1' and jmp_en = '1' and jmp_dir = '0')then
port_int <= port_int - data; -- jump backward
else -- nije ispunjen uslov skoka
port_int <= port_int + '1'; -- increment PC
end if;
pc_out <= port_int;
when s3 =>
ctrl_en <= '1';
end case;
end process;
end Behavioral;
EDIT:
When I import the module in a whole processor, this happens:
the same pc_out signal acts strangely, adn all the inputs are the same. I use the pc_out signal just in one place, to select memory.
Why isn't it behaving normally? What could have caused this?
The second process (output_logic: process), which computes the output values, has some problems.
First, recall that it implements a combinational circuit (therefore, memoryless), so equations like port_int <= port_int + data can only be computed if the value of port_int is stored somewhere. By the way, after fixing the code, you can drop the internal signal port_int and use pc_out directly.
Second, being this process a combinational circuit, its full truth table must be specified; otherwise, latches will be inferred. Note, for example, that only the value of ctrl_en is specified in state s1. You must either specify all output values (same list) in all states or, equivalently, you can make a list of output values before the case statements, so the compiler will use them as default values when the values are not explicitly declared.
If I understand what you're trying to do correctly, you just need a single statement outside the process blocks:
pc_out <= port_int;
Take all other statements assigning something to pc_out out of your design. I think you're getting tripped up by the <= operator, which waits until the next simulation delta to actually update the signal driver.

VHDL 4-bit binary divider

I am trying to make a binary divider to be part of a calculator using VHDL, I have written the code that I think should work but have been stuck for hours, can someone please help me.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity Div is
Port ( Ain : in STD_LOGIC_VECTOR (3 downto 0);
Bin : in STD_LOGIC_VECTOR (3 downto 0);
Q : out STD_LOGIC_VECTOR (3 downto 0);
R : out STD_LOGIC_VECTOR (3 downto 0));
end Div;
architecture Behavioral of Div is
Signal Atemp : Std_Logic_Vector (3 downto 0);
begin
Proc1: Process (Ain,Bin, Atemp)
variable cnt : STD_LOGIC_Vector(3 downto 0);
begin
if (Ain < Bin) then
cnt := "0000";
Atemp <= Ain;
elsif (Ain = Bin) then
cnt := "0001";
elsif (Ain > Bin) then
cnt := "0001";
Atemp <= (Ain - Bin);
while (Atemp >= Bin) loop
if(Atemp >=Bin) then
Atemp <= (Atemp - Bin);
cnt := cnt + "0001";
end if;
end loop;
end if;
Q <= cnt;
R <= Atemp;
end process Proc1;
end Behavioral;
In the iteration part of the divide process, when Ain > Bin, the assign
Atemp <= (Ain - Bin) is always performed, even if the iteration should be
completed. Process that assign to a signal also in the sensitivity list, is
hard to get right.
The code may be updated with Atemp as a variable instead, some other
simplifications with removal of unrequired code, and adding value for remainder
when Ain = Bin, resulting in architecture as:
architecture Behavioral of Div is
begin
Proc1 : process (Ain, Bin) is
variable cnt : std_logic_vector(3 downto 0);
variable Atemp : std_logic_vector(3 downto 0);
begin
if (Ain < Bin) then
cnt := "0000";
Atemp := Ain;
elsif (Ain = Bin) then
cnt := "0001";
Atemp := (others => '0'); -- Added to give correct remainder
elsif (Ain > Bin) then
cnt := "0001";
Atemp := (Ain - Bin);
while (Atemp >= Bin) loop
-- Removed trivial true if statement, since condition identical to condition in while
Atemp := (Atemp - Bin);
cnt := cnt + "0001";
end loop;
end if;
Q <= cnt;
R <= Atemp;
end process Proc1;
end Behavioral;
The inner process statements may actually be reduced to:
cnt := "0000";
Atemp := Ain;
while (Atemp >= Bin) loop
Atemp := (Atemp - Bin);
cnt := cnt + "0001";
end loop;
Q <= cnt;
R <= Atemp;
Whether this will synthesize to the required frequency with the unrolled
while is another question, that depends on the target frequency and
technology.
An alternative solution, given the short Ain and Bin, is to implement the
divider using a constant lookup table, with address as Ain & Bin and output
of Q & R. This will evaluate in fixed time, and synthesis is very likely to
reduce considerably if made as combinatorial logic.
Last comment is that you may also want to handle division by zero, when Bin
is zero.
To prevent mistakes, it is advisable to use explicitly the type unsigned or signed when implementing arithmetic circuits. The numeric_std package contains the following arithmetic operators for these types: +, -, *, /, abs, rem, mod.
Below is a suggested code (for unsigned division). Note that some lines in the arch can be eliminated, but were used to make the code more "didactic".
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity divider is
generic (size: natural := 4);
port (
A: in std_logic_vector(size-1 downto 0);
B: in std_logic_vector(size-1 downto 0);
Q: out std_logic_vector(size-1 downto 0);
R: out std_logic_vector(size-1 downto 0));
end entity;
architecture direct of divider is
signal Auns, Buns, Quns, Runs: unsigned(size-1 downto 0);
begin
--Convert inputs to unsigned:
Auns <= unsigned(A);
Buns <= unsigned(B);
--Do the division:
Quns <= Auns/Buns;
Runs <= Auns rem Buns; --Or: Runs <= Auns - resize(Quns*Buns, size);
--Covert results to std_logic_vector:
Q <= std_logic_vector(Quns);
R <= std_logic_vector(Runs);
end architecture

Synthesis warning in VHDL multiplier code

When I synthesize this 32-bit multiplier code, I do not get any errors, just warnings that my input is not used and is assigned but not used. My code is this:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity multiplier is
Port ( multiplicand : in STD_LOGIC_VECTOR(31 downto 0);
multiply : in STD_LOGIC_VECTOR(31 downto 0);
clk : in STD_LOGIC;
product : out STD_LOGIC_VECTOR(63 downto 0));
end multiplier;
architecture Behavioral of multiplier is
component adder32bit is
port(addone, addtwo : in STD_LOGIC_VECTOR(31 downto 0);
sum : out STD_LOGIC_VECTOR(31 downto 0);
cout : out STD_LOGIC);
end component;
signal tempsum : STD_LOGIC_VECTOR(31 downto 0);
signal preg : STD_LOGIC_VECTOR(63 downto 0);
signal start : STD_LOGIC := '1';
signal tempcout : STD_LOGIC;
signal counter : integer := 1;
begin
addN: adder32bit port map(multiplicand, preg(63 downto 32), tempsum, tempcout);
process(clk)
begin
if(rising_edge(clk)) then
if(start = '1') then
if(counter = 1) then
preg <= "00000000000000000000000000000000" & multiply;
end if;
if(preg(0) = '1') then
preg(63 downto 32) <= tempsum;
preg <= tempcout & preg(63 downto 1);
else
preg <= '0' & preg(63 downto 1);
end if;
counter <= counter + 1;
if(counter = 33) then
product <= preg;
start <= '0';
counter <= 1;
end if;
end if;
end if;
end process;
end Behavioral;
When I run the simulation, no matter what my two inputs are (multiplicand and multiply) the output will be like this: "0000...UUUUUUU"
Any suggestions as to what I should do here?
One way to initialise preginvolves just a minor change to your code...
if(counter = 1) then
preg <= "00000000000000000000000000000000" & multiply;
else
if(preg(0) = '1') then ...
end if;