How can I calculate elements in one vector? - vhdl

I'm new at VHDL code, and I'm trying to figure out, how is the easiest way to calculate elements in STD_LOGIC_VECTOR.
so how my ports look like:
Port ( D : in STD_LOGIC_VECTOR (width-1 downto 0); -- data input
parity : out STD_LOGIC -- parity bit
);
so I want to do something like this (code in c)
int helper = 0;
for (int i = 0; i < width; i++) {
if (D[i] == 1) {
helper++;
}
}
if (helper % 2 == 0) {
parity = 1;
}
if im not enought clear sorry for that, i can probably answer your question, if there will be.

Probably the best way to do this in VHDL is with xor_reduce from ieee.std_logic_misc. Addition modulo 2 is exactly the same as XOR, and xor_reduce XORs all of the inputs together, giving you the addition modulo 2 of your input bits. This would look like:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.xor_reduce;
entity PARITY_GEN is
generic (width : integer := 8);
port( D: in std_logic_vector(width-1 downto 0);
parity: out std_logic
);
end PARITY_GEN;
architecture bhv of PARITY_GEN is
begin
process(D)
begin
parity <= xor_reduce(D);
end process;
end bhv;
If you don't want to include xor_reduce, you could do the same just using xor:
library ieee;
use ieee.std_logic_1164.all;
entity PARITY_GEN is
generic (width : integer := 8);
port( D: in std_logic_vector(width-1 downto 0);
parity: out std_logic
);
end PARITY_GEN;
architecture bhv of PARITY_GEN is
begin
process(D)
variable temp:std_logic_vector(width-1 downto 0);
begin
temp(0) := D(0);
loop:for i in 1 to width-1 generate
temp(i) := temp(i-1) xor D(i);
end generate;
parity <= temp(width-1);
end process;
end bhv;

Related

Why does this Full Adder Function not work VHDL

Library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity ALU is
port( A: in STD_LOGIC_VECTOR(7 downto 0);
B: in STD_LOGIC_VECTOR(7 downto 0);
C: in STD_LOGIC_VECTOR(3 downto 0);
Result: out STD_LOGIC_VECTOR(7 downto 0));
end ALU;
architecture arch of ALU is
----------------- SUM------------------------------------------------
function SUM (X:STD_LOGIC; Y:STD_LOGIC;CIN :STD_LOGIC) return STD_LOGIC is
variable Res: STD_LOGIC;
begin
Res:= X XOR Y XOR CIN;
return Res;
end SUM;
function Carry(X:STD_LOGIC; Y:STD_LOGIC;CIN :STD_LOGIC) return STD_LOGIC is
variable Res: STD_LOGIC;
begin
Res:=(X AND Y) OR (CIN AND X) OR (CIN AND Y);
return Res;
end Carry;
------------------------------------------------------------------
function Adder(A:STD_LOGIC_VECTOR;B :STD_LOGIC_VECTOR) return STD_LOGIC_VECTOR is
variable Res: STD_LOGIC_VECTOR(0 to 7);
variable Car: STD_LOGIC_VECTOR(0 to 8);
begin
Car(0):='0';
for i in 0 to 7 loop
Res(i):=SUM(A(i),B(i),Car(i));
Car(i+1):= Carry(A(i),B(i),Car(i));
end loop;
return Res;
end Adder;
begin
Result <= Adder("00110010","00000010");
end arch;
Hello I am a bit confused on why this full adder function does not work. I have tried multiple times to fix it however it does not give the correct output.
I am unsure where the errors are in the sum or carry or adder function. I do not know what to do to ensure it works. I also do not want to make a different component for a full adder.

Vhdl, is there a way, to use modulo on larger than 64 bits unsigned?

I've got two 115bits unsigned vectors. I have to do some mod calculations on them, but Quartus shows those errors.
Error: In lpm_divide megafunction, LPM_WIDTHN must be less than or equals to 64
Error: In lpm_divide megafunction, LPM_WIDTHD must be less than or equal to 64
Error: Can't elaborate inferred hierarchy "lpm_divide:Mod0"
I fully understand, that numbers are too large to perform mod. Is there a way/library/any idea how to solve this problem? I would love to avoid using any "substracting loop", and be as simple as possible. VHDL is not my world, and after academic project I will abandon it with pleasure :P
Application has to calculate modulo inversion. As far as I am not master from VHDL, I've tried doing it using fast powering + mod alghoritm. Application can sucks, it just has to work :d
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use IEEE.std_logic_unsigned.all;
library altera;
use altera.altera_primitives_components.all;
entity inwersja is
port(
a: in unsigned(114 downto 0);
clk: in std_logic;
start: in std_logic;
reset: in std_logic;
c: out unsigned(114 downto 0);
ready: out std_logic);
end inwersja;
architecture i1 of inwersja is
begin
process(clk)
variable tempOutput : unsigned(114 downto 0) := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
variable temp : unsigned (114 downto 0):= a;
variable modul: unsigned(114 downto 0) := "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101011";
variable power: unsigned(114 downto 0) := "1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101001";
variable counter: integer := 0;
begin
if reset='1' then
tempOutput := "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001";
ready <= '0';
elsif clk'event and clk='1' then
if start='0' then
ready<='0';
else
if (counter < 115) then
if (power(counter) /= '0') then
tempOutput := (tempOutput * temp) mod modul;
end if;
temp := (temp * temp) mod modul;
counter := counter + 1;
elsif (counter = 115) then
ready <= '1';
end if;
end if;
end if;
c <= tempOutput;
end process;
end i1;

Implementing Overflow Checking in 4-bit Adder/Subtractor (VHDL)

I am rather new (3 weeks) to VHDL, and I am having a problem in my latest assignment, which involves implementing overflow checking in a simple 4-bit adder:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity add_sub_4bit is
Port ( a : in STD_LOGIC_VECTOR(3 downto 0);
b : inout STD_LOGIC_VECTOR(3 downto 0);
sel: in STD_LOGIC );
--sum : inout STD_LOGIC_VECTOR(3 downto 0)
end add_sub_4bit;
architecture Behavioral of add_sub_4bit is
signal localflow : STD_LOGIC;
signal localsum : STD_LOGIC_VECTOR (3 downto 0);
begin
localsum <= a + b when sel = '1'
else
a - b;
process(a,b,localsum) begin
if a(3) = '0' AND b(3) = '0' AND localsum(3) = '1' then
localflow <= '1';
elsif a(3) = '1' AND b(3) = '1' AND localsum(3) = '0' then
localflow <='1';
else
localflow <='0';
end if;
end process;
end Behavioral;
Now, the test cases are as such:
A=5, B=-3, giving 0 to sel adds them, 1 subtracts.
A=6, B=2, working much the same.
Now, given that the numbers are signed, of course, they are two's complement numbers, so is the result. However, I can only detect overflow in a case of adding 6 (0110) and 2 (0010), giving out -8 (1000), which is obviously an overflow case in 4-bit. But, when doing 5 -(-3), the result is much the same, 1000, but since I have given numbers of two different signs, I cannot detect overflow using my method.
My teacher has suggested that we change the sign of B depending on the value of sel - I tried something like making b <= b+"1000" based on that but that didn't help, and I don't know of other ways, being very new to the language. What can I do to get a proper program? Thank you.
Firstly:
use IEEE.STD_LOGIC_UNSIGNED.ALL;
Don't do that. Especially if you want the numbers to be signed. Normal to use is:
use IEEE.numeric_std.all;
After that, you should cast the std_logic_vector to the wanted data type, e.g. 'signed', for the correct arithmetic.
Secondly, don't use inout. VHDL is not so good with bidirectional assignments. Either use in or out.
So combining the above, you could do (n.b. not the best code):
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity add_sub_4bit is
Port (
a : in STD_LOGIC_VECTOR(3 downto 0);
b : in STD_LOGIC_VECTOR(3 downto 0);
sel: in STD_LOGIC;
sum : out STD_LOGIC_VECTOR(3 downto 0);
overflow : out std_logic
);
end add_sub_4bit;
architecture Behavioral of add_sub_4bit is
signal localflow : STD_LOGIC;
signal locala, localb, localsum : signed(4 downto 0); -- one bit more then input
signal sumout : std_logic_vector(4 downto 0);
begin
locala <= resize(signed(a), 5);
localb <= resize(signed(b), 5);
localsum <= locala + localb when sel = '1' else locala - localb;
-- overflow occurs when bit 3 is not equal to the sign bit(4)
localflow <= '1' when localsum(3) /= localsum(4) else '0';
-- convert outputs
sumout <= std_logic_vector(localsum);
--outputs
sum <= sumout(4)&sumout(2 downto 0);
overflow <= localflow;
end Behavioral;
You can test this using a testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity add_sub_4bit_tb is
end add_sub_4bit_tb;
architecture Behavioral of add_sub_4bit_tb is
signal sel : std_logic_vector(0 downto 0);
signal a, b, sum : std_logic_vector(3 downto 0);
begin
uut: entity work.add_sub_4bit
port map (a, b, sel(0), sum);
test: process
begin
for sel_o in 0 to 1 loop
sel <= std_logic_vector(to_signed(sel_o, 1));
for a_o in -8 to 7 loop
a <= std_logic_vector(to_signed(a_o, 4));
for b_o in -8 to 7 loop
b <= std_logic_vector(to_signed(b_o, 4));
wait for 1 ns;
end loop;
end loop;
end loop;
wait;
end process;
end Behavioral;

How to use the Xilinx Division IP Core

I am writing code in VHDL to be synthesised onto a XilinX FPGA. I typically use GHDL to simulate my testbenches. I need to make use of the XilinX division core in order to divide by a variable however I am not sure how to do this as there appear to be no examples in the XilinX documentation. Do I have to use the XilinX software to generate the VHDL component for the divider? Or does XilinX implicitly understand that divider means using the IP core? If my 2nd statement is true how would I go about simulating this with GHDL or would I have to use a XilinX simulation tool? I could really do with a minimal example of using the XilinX divider core to implement division by a variable e.g. something like this:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
entity DividingExample is
port (
clk : in std_logic;
reset : in std_logic;
InputSignal : in std_logic_vector(15 downto 0);
OutputSignal : out std_logic_vector(15 downto 0)
);
end DividingExample;
architecture behaviour of DividingExample is
-- declarations
signal numerator : integer;
begin
-- behaviour
process(clk)
begin
if(rising_edge(clk)) then
if(reset = '1') then
-- reset values
numerator <= 1000;
else
-- calculate value to be output
OutputSignal <= numerator/to_integer(signed(InputSignal))
end if;
end if;
end process;
end behaviour;
This example code obviously doesn't work as division (the '/' operator) is not defined for the integer datatype. How might I go about this?
I ended up writing my own division code, which was significantly quicker and easier to implement than using XilinX's IP Core. I used the binary division algorithm detailed here and wrote the following VHDL code for a signed 32 bit division:
function Divide(N : signed(31 downto 0); D : signed(31 downto 0)) return signed is
variable Q : signed(31 downto 0) := to_signed(0, 32);
variable R : signed(31 downto 0) := to_signed(0, 32);
variable l : line;
constant N_Abs : signed(31 downto 0) := abs(N);
constant D_Abs : signed(31 downto 0) := abs(D);
begin
-- behaviour
for i in N_Abs'high downto 0 loop
R := shift_left(R, 1);
R(0) := N_Abs(i);
if R >= D_Abs then
R := R - D;
Q(i) := '1';
end if;
end loop;
if ((N < 0 and D > 0) or (N > 0 and D < 0)) then
return -Q;
else
return Q;
end if;
end function;

VHDL Counter ones errors

I already done the code, and it can work, However, when I try to write the test bench, I got some troubles on that. The input x sets up as 8 bits, and x: IN BIT_VECTOR (N -1 DOWNTO 0).
When I write the test bench I connot enter the bits number.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_unsigned.all;
ENTITY Count_ones IS
GENERIC (N: INTEGER := 8); -- number of bits
PORT ( x: IN BIT_VECTOR (N -1 DOWNTO 0); y: OUT NATURAL RANGE 0 TO N);
END ENTITY ;
architecture Behavioral of Count_ones is
TYPE count is Array (N DOWNTO 1) OF Natural;
signal a : count;
begin
a(0) <= 1 when (x(0) = '1')
else
0;
gen: FOR i IN N-1 DOWNTO 0
GENERATE
a(i+1) <= (a(i)+1) when (x(i)='0')
else
a(i);
END GENERATE;
y <= a(N-1);
end Behavioral;
The Test Bench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
ENTITY Count_ones_TB IS
END Count_ones_TB;
ARCHITECTURE behavior OF Count_ones_TB IS
COMPONENT Count_ones
PORT(
x : IN std_logic_vector(7 downto 0);
y : OUT std_logic_vector(0 to 3)
);
END COMPONENT;
--Inputs
signal x : std_logic_vector(7 downto 0) := (others => '0');
--Outputs
signal y : std_logic_vector(0 to 3);
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Count_ones PORT MAP (
x => x,
y => y
);
stim_proc: process
begin
x <= "00010101";
wait for 100 ns;
x <= "00001001";
wait for 100 ns;
x <= "11111111101"
wait for 100ns;
-- insert stimulus here
wait;
end process;
END;
The error is
Entity port x does not match with type std_logic_vector of component port
Entity port y does not match with type std_logic_vector of component port
Please help me, I real cannot figure out the way to solve that.
The answer to your specific question is that the types of the ports in the entity, the ports in the component and the types of the signals must match. Here is a link to your code with those errors and many more corrected.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_unsigned.all;
ENTITY Count_ones IS
GENERIC (N: INTEGER := 8); -- number of bits
PORT ( x: IN BIT_VECTOR (N -1 DOWNTO 0); y: OUT NATURAL RANGE 0 TO N);
END ENTITY ;
architecture Behavioral of Count_ones is
TYPE count is Array (N DOWNTO 0) OF Natural;
signal a : count;
begin
a(0) <= 1 when (x(0) = '1')
else
0;
gen: FOR i IN N-1 DOWNTO 0
GENERATE
a(i+1) <= (a(i)+1) when (x(i)='0')
else
a(i);
END GENERATE;
y <= a(N-1);
end Behavioral;
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.all;
ENTITY Count_ones_TB IS
END Count_ones_TB;
ARCHITECTURE behavior OF Count_ones_TB IS
COMPONENT Count_ones
GENERIC (N: INTEGER := 8); -- number of bits
PORT ( x: IN BIT_VECTOR (N -1 DOWNTO 0);
y: OUT NATURAL RANGE 0 TO N);
END COMPONENT;
--Inputs
signal x : BIT_VECTOR(7 downto 0) := (others => '0');
--Outputs
signal y : natural;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Count_ones PORT MAP (
x => x,
y => y
);
stim_proc: process
begin
x <= "00010101";
wait for 100 ns;
x <= "00001001";
wait for 100 ns;
x <= "11111101";
wait for 100ns;
-- insert stimulus here
wait;
end process;
END;
However I must point out that you are a long way from achieving your goal of trying to count the number of ones.
Because of that:
My corrections to your code are not the only correct answer. In
fact, my corrections are not even a good answer. I have simply made
the minimum corrections to make your code compile and run. You need
to think very carefully what type all the ports and signals in your
design should be.
My corrections will not make your code work, i.e. count the number of
ones.

Resources