How to use the Xilinx Division IP Core - vhdl

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;

Related

VHDL: big slv array slicing indexed by integer (big mux)

I want to slice a std_logic_vector in VHDL obtaining parts of it of fixed dimensions.
The general problem is:
din N*M bits
dout M bits
sel clog2(N) bits
Expected behaviour in an example (pseudocode): input 16 bit, want to slice it in 4 subvectors of 4bit each.
signal in: std_logic_vector(N*M-1 downto 0);
signal sel: integer;
-- with sel = 0
output <= in(N-1:0);
--with sel = 1 output <= in(2N-1:N)
-- with sel = 2
output <= in(3N-1:2N)
.....
--with sel = M-1
output <= in(M*N-1:(M-1)N)
I know a couples of way to do this, but I don't know which one is the best practice and give the best results in synthesis.
the entity
din: in std_logic_vector(15 downto 0);
dout: out std_logic_vector(3 downto 0);
sel: in std_logic_vecotor(1 downto 0)
CASE STATEMENT
case sel is
when "00" => dout <= din(3:0);
when "01" => dout <= din(7:4);
when "10" => dout <= din(11:8);
when "11" => dout <= din(15:12);
when others => ....`
It clearly implement a mux, but it's not generic at all and If the input gets big it's really hard to write and to codecover.
INTEGER INDEXING
sel_int <= to_integer(unsigned(sel));
dout <= din(4*(sel_int+1) - 1 downto 4*sel_int);
Extremely easy to write and to mantain, BUT it can have problems when the input is not a power of 2. For example, if I want to slice a 24bit vector in chunks of 4, what happen when the integer conversion of sel brings to the index 7?
A STRANGE TRADEOFF
sel_int <= to_integer(unsigned(sel));
for i in 0 to 4 generate
din_slice(i) <= din(4*(i+1)-1 downto 4*i);
end generate dout <= din_slice(sel_int);
I'm searching a solution that is general enough to be used with various input/output relationships and safe enough to be synthesized consistently everytime.
The Case statement is the only one with the Others case (that feels really safe), the other solutions rely on the slv to integer conversion and indexing that feels really comfortable but not so reliable.
Which solution would you use?
practical usecase
I have a 250bit std_logic_vector and I need to select 10 contigous bits inside of it starting from a certain point from 0 to 239. How can I do that in a way that is good for synthesis?
There is another option that is accepted by tools that allow VHDL 2008 (which includes Vivado and Prime Pro). You can use an unconstrained 2d type from a package:
type slv_array_t is array(natural range <>) of std_logic_vector; --vhdl 2008 unconstrained array type
then you can simply select which port you want. And it is as generic as you like.
library ieee;
use ieee.std_logic_1164.all;
use work.my_pkg.all;
entity mux is
generic (
N : natural;
M : natural
);
port (
sel : in natural;
ip : in slv_array_t (N-1 downto 0)(M-1 downto 0);
op : out std_logic_vector (M-1 downto 0);
);
end entity;
architecture rtl of mux is
begin
op <= ip(sel);
end architecture;
First you must extend the incoming data to be sure to have always as much bits as you need for connecting all multiplexer inputs (see the code below, process p_extend).
This will not create any logic at synthesis.
Second you must convert the resulting vector into an array, which you can access later by an index (see the code below, process p_create_array).
Again this will not create any logic at synthesis.
At last you must access this array by the select input signal (see the code below, process p_mux).
library ieee;
use ieee.std_logic_1164.all;
entity mux is
generic (
g_data_width : natural := 250;
g_slice_width : natural := 10;
g_sel_width : natural := 5;
g_start_point : natural := 27
);
port (
d_i : in std_logic_vector(g_data_width-1 downto 0);
sel_i : in std_logic_vector(g_sel_width-1 downto 0);
d_o : out std_logic_vector(g_slice_width-1 downto 0)
);
end entity mux;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
architecture struct of mux is
signal data : std_logic_vector(g_slice_width * 2**g_sel_width-1 downto 0);
type t_std_logic_slice_array is array (natural range <>) of std_logic_vector(g_slice_width-1 downto 0);
signal mux_in : t_std_logic_slice_array (2**g_sel_width-1 downto 0);
begin
p_extend: process(d_i)
begin
for i in 0 to g_slice_width * 2**g_sel_width-1 loop
if i+g_start_point<g_data_width then
data(i) <= d_i(i+g_start_point);
else
data(i) <= '0';
end if;
end loop;
end process;
p_create_array: process (data)
begin
for i in 0 to 2**g_sel_width-1 loop
mux_in(i) <= data((i+1)*g_slice_width-1 downto i*g_slice_width);
end loop;
end process;
p_mux: d_o <= mux_in(to_integer(unsigned(sel_i)));
end architecture;

Can't normally see result in wave (Modesim)

I have code designed for Vivid software. How I can translate this code into ModelSIM? In vivado, I should get the following values, but in modelsim I get completely different ones.
This is noise generator. Successful in adding pseudorandom noise sequence to our sine wave, but now we are trying to add Gaussian noise. The code and the simulation results for ADDITION OF PSEUDORANDOM NOISE SEQUENCE TO SINE WAVE IS GIVEN BELOW:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; --try to use this library as much as possible.
entity sine_wave is
generic ( width : integer := 4 );
port (clk :in std_logic;
random_num : out std_logic_vector (width-1 downto 0);
data_out : out STD_LOGIC_VECTOR(7 downto 0)
);
end sine_wave;
architecture Behavioral of sine_wave is
signal data_out1,rand_temp1,noisy_signal : integer;
signal noisy_signal1 : STD_LOGIC_VECTOR(7 downto 0);
signal i : integer range 0 to 29:=0;
--type memory_type is array (0 to 29) of integer;
type memory_type is array (0 to 29) of std_logic_vector(7 downto 0);
--ROM for storing the sine values generated by MATLAB.
signal sine : memory_type := ("01001101","01011101","01101100","01111010","10000111","10010000","10010111","10011010","10011010");
--hi
begin
process(clk)
variable rand_temp : std_logic_vector(width-1 downto 0):=(width-1 => '1',others => '0');
variable temp : std_logic := '0';
begin
--to check the rising edge of the clock signal
if(rising_edge(clk)) then
temp := rand_temp(width-1) xor rand_temp(width-2);
rand_temp(width-1 downto 1) := rand_temp(width-2 downto 0);
rand_temp(0) := temp;
--data_out <= sine(i);
i <= i+ 1;
if(i = 29) then
i <= 0;
end if;
end if;
data_out <= sine(i);
data_out1<=to_integer(unsigned(sine(i)));
random_num <= rand_temp;
rand_temp1<=to_integer(unsigned(rand_temp));
noisy_signal<=data_out1+rand_temp1;
noisy_signal1<= std_logic_vector(to_signed(noisy_signal,8));
end process;
end Behavioral;
Vivado
ModelSIM

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;

Shift unit in VHDL

As part of an alu design for a FPGA course I need to build a Shift unit capable of doing left shift and right arithmetic shift.
I wrote some VHDL code, simulated it in ModelSim and it worked fine. The next step was to compile it for an FPGA (ALTERA DE1). Now all the other operations of the ALU works fine but not the shift unit. For opcodes related to shift the output stays equals to the input.
entity Shift is
generic (
N : integer := 8 );
port (
A,B:in std_logic_vector(N-1 downto 0);
OP: in std_logic_vector(2 downto 0);
Enable: in std_logic;
shiftedA:out std_logic_vector(N-1 downto 0));
end Shift;
architecture rtl of Shift is
begin
shift_process: process (Enable,op,A,B)
variable TempVec : std_logic_vector(N-1 downto 0) ;--:= (others => '0');
variable inVector : std_logic_vector(N-1 downto 0);
variable bitNum : Integer;
begin
inVector:=A;
TempVec:=A;
bitNum := conv_integer(B);
test <= "00000000";
if Enable = '1' then
if OP = "100" then
for i in 1 to bitNum loop
TempVec := TempVec(N-2 downto 0) & "0";
end loop ;
elsif OP = "101" then
for j in 1 to bitNum loop
TempVec := A(N-1) & TempVec(N-1 downto 1);
end loop;
else
TempVec := (others => '0');
end if;
else
TempVec := (others => '0');
end if;
shiftedA <= TempVec;
end process;
end rtl;
What am I doing wrong?
Loops, like for i in 1 to bitNum loop are unrolled in synthesis for implementation as a circuit, but in this case the end condition for the loop is dependent on data, since bitNum is conv_integer(B), so conversion into hardware is a problem. Simulators can handle such constructions, since they do not convert into a circuit.
There is probably a synthesis warning telling this, so check the warnings, since some are actually relevant.
Telling more will spoil a good exercise... ;-)

VHDL n-bit barrel shifter

I have a 32 bit barrel shifter using behavior architecture. Now I need to convert it to an n-bit shifter. The problem that I'm facing is that there is some kind of restriction to the for loop that I have to put a constant as sentinel value.
Following is my Code
library IEEE;
use IEEE.std_logic_1164.all;
Entity bshift is -- barrel shifter
port (left : in std_logic; -- '1' for left, '0' for right
logical : in std_logic; -- '1' for logical, '0' for arithmetic
shift : in std_logic_vector(4 downto 0); -- shift count
input : in std_logic_vector (31 downto 0);
output : out std_logic_vector (31 downto 0) );
end entity bshift;
architecture behavior of bshift is
function to_integer(sig : std_logic_vector) return integer is
variable num : integer := 0; -- descending sig as integer
begin
for i in sig'range loop
if sig(i)='1' then
num := num*2+1;
else
num := num*2;
end if;
end loop; -- i
return num;
end function to_integer;
begin -- behavior
shft32: process(left, logical, input, shift)
variable shft : integer;
variable out_right_arithmetic : std_logic_vector(31 downto 0);
variable out_right_logical : std_logic_vector(31 downto 0);
variable out_left_logical : std_logic_vector(31 downto 0);
begin
shft := to_integer(shift);
if logical = '0' then
out_right_arithmetic := (31 downto 32-shft => input(31)) &
input(31 downto shft);
output <= out_right_arithmetic after 250 ps;
else
if left = '1' then
out_left_logical := input(31-shft downto 0) &
(shft-1 downto 0 => '0');
output <= out_left_logical after 250 ps;
else
out_right_logical := (31 downto 32-shft => '0') &
input(31 downto shft);
output <= out_right_logical after 250 ps;
end if;
end if;
end process shft32;
end architecture behavior; -- of bshift
any help will be appreciated
Your code is not a barrel shifter implementation, because a barrel shift is a mux-tree.
If you have a 32 bit BarrelShifter module, you will need a 5 bit Shift input, wherein every bit position i enables a 2^i shift operation.
So for example shift = 5d -> 00101b enables a mux in stage 1 to shift for 1 bit and a mux in stage 3 to shift 4 bits. All other mux stages are set to pass through (shift(i) = 0).
I also would not advice to mix up basic shifting with shift modes (arithmetic, logic, rotate) and directions (left, right).
arithmetic and logic is only different in the shift-in value
shift right can be done by a conversion => shiftright = reverse(shiftleft(reverse(input), n)
An open source implementation can be found here:
https://github.com/VLSI-EDA/PoC/blob/master/src/arith/arith_shifter_barrel.vhdl

Resources