Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > VHDL > Division with ieee.numeric_std

Reply
Thread Tools

Division with ieee.numeric_std

 
 
Gabriel Schuster
Guest
Posts: n/a
 
      09-21-2006
Hi everybody,

I've got a little problem with the division module (part of a
microcontroller alu) in my current project: I found a nice code sample
in the www implementing a similar module.
Originally ieee.std_logic_arith was used to create it, which I strictly
avoid in my project so I rewrote the divider module using
ieee.numeric_std... but unfortunately it doesn't work so far.

I think there's something wrong in the assignments / conversion between
std_logic_vector and unsigned. I'd appreciate any help, because I'm used
to work with std_logic_arith and I think I'll have more of these
conversion problems in the near future.
How is this conversion done the right way???

Here are the sources of the two divider modules. I also got two
testbenches, which I can add.

Thanks
Gabriel

=====================WORKING====================== ===================
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

entity divider is

generic (DWIDTH : integer := ;

port (dvdnd_i : in std_logic_vector(DWIDTH-1 downto 0); -- Dividend
dvsor_i : in std_logic_vector(DWIDTH-1 downto 0); -- Divisor
qutnt_o : out std_logic_vector(DWIDTH-1 downto 0); --
Quotient
rmndr_o : out std_logic_vector(DWIDTH-1 downto 0);
ov_o : out std_logic); -- Remainder

end divider;

architecture rtl of divider is
begin -- rtl

ov_o <= '1' when dvsor_i = "00000000" else '0';

-- purpose: Divide dvdnd_i through dvsor_i and deliver the result to
qutnt_o
-- and the remainder to rmndr_o.
-- type : combinational
-- inputs : dvdnd_i, dvsor_i
-- outputs: qutnt_o, rmndr_o
p_divide: process (dvdnd_i, dvsor_i)

variable v_actl_dvdnd : unsigned(DWIDTH-1 downto 0);
variable v_dffrnc : unsigned(DWIDTH-1 downto 0);
variable v_qutnt : unsigned(DWIDTH-1 downto 0);

begin -- process p_divide

v_actl_dvdnd := unsigned(dvdnd_i);

for i in DWIDTH-1 downto 0 loop
-- If the divisor can be subtracted from this part of the
dividend, then
-- the corresponding bit of the quotient has to be 1, otherwise 0.
if conv_std_logic_vector(v_actl_dvdnd(DWIDTH-1 downto i),DWIDTH) >=
dvsor_i then
-- Divisor can be subtracted
v_qutnt(i) := '1';
v_dffrnc := conv_unsigned(v_actl_dvdnd(DWIDTH-1 downto i),DWIDTH)
- unsigned(dvsor_i);
-- As long as this is not the last step of calculation, shift the
-- intermediate result.
if i /= 0 then
v_actl_dvdnd(DWIDTH-1 downto i) := v_dffrnc(DWIDTH-1-i downto 0);
v_actl_dvdnd(i-1) := dvdnd_i(i-1);
end if;
else
-- Divisor is greater than this part of the dividend.
v_qutnt(i) := '0';
v_dffrnc := conv_unsigned(v_actl_dvdnd(DWIDTH-1 downto i),DWIDTH);
end if;
end loop; -- i

rmndr_o <= std_logic_vector(v_dffrnc);
qutnt_o <= std_logic_vector(v_qutnt);

end process p_divide;

end rtl;


=============================NOT WORKING=============================
-- remark:
-- this is the numeric_std version
-- it's possible to simulate the other one with ghdl using --ieee=synopsis
-- but several people suggested to switch to the "real" ieee-stuff
--

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity alu_div is
port (
op1_i : in std_logic_vector(7 downto 0); -- dividend
op2_i : in std_logic_vector(7 downto 0); -- divisor
resa_o : out std_logic_vector(7 downto 0); -- result
resb_o : out std_logic_vector(7 downto 0); -- remainder
ov_o : out std_logic
);
end alu_div;

architecture rtl of alu_div is
begin

ov_o <= '1' when (op2_i="00000000") else '0';

p_divide: process (op1_i,op2_i)
variable v_result : unsigned(7 downto 0);
variable v_remainder : unsigned(7 downto 0);
variable v_tmp : unsigned(7 downto 0);
begin
v_tmp := unsigned(op1_i);
for i in 7 downto 0 loop
if (std_logic_vector(v_tmp(7 downto i)) >= op2_i) then
v_result(i) := '1';
v_remainder := unsigned(v_tmp(7 downto i)) - unsigned(op2_i);
if (i /= 0) then
v_tmp(7 downto i) := v_remainder(7-i downto 0);
v_tmp(i-1) := op1_i(i-1);
end if;
else
v_result(i) := '0';
v_remainder := "00000000";
v_remainder(7-i downto 0) := unsigned(v_tmp(7 downto i));
--v_remainder := to_unsigned(to_integer(v_tmp(7 downto i)),;
end if;
end loop; -- i

resa_o <= std_logic_vector(v_result);
resb_o <= std_logic_vector(v_remainder);

end process p_divide;

end rtl;
 
Reply With Quote
 
 
 
 
Gabriel Schuster
Guest
Posts: n/a
 
      09-21-2006
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
library std;
use std.textio.all;


entity tb_divider is
generic (DWIDTH : integer := ;
end tb_divider;

architecture behave of tb_divider is

function printb (bv : in std_logic_vector) return string is
alias bv_norm : std_logic_vector(1 to bv'length) is bv;
variable result : string(1 to bv'length);
begin
for index in bv_norm'range loop
if bv_norm(index) = '0' then
result(index) := '0';
else
result(index) := '1';
end if;
end loop;
return result;
end printb;

component divider
port (dvdnd_i : in std_logic_vector(DWIDTH-1 downto 0); -- Dividend
dvsor_i : in std_logic_vector(DWIDTH-1 downto 0); -- Divisor
qutnt_o : out std_logic_vector(DWIDTH-1 downto 0); --
Quotient
rmndr_o : out std_logic_vector(DWIDTH-1 downto 0);
ov_o : out std_logic); -- Remainder
end component divider;

signal op1_i : std_logic_vector(7 downto 0) := "00000000";
signal op2_i : std_logic_vector(7 downto 0) := "00000000";
signal resa_o : std_logic_vector(7 downto 0);
signal resb_o : std_logic_vector(7 downto 0);
signal ov_o : std_logic;

begin

uut: divider
port map (
dvdnd_i => op1_i,
dvsor_i => op2_i,
qutnt_o => resa_o,
rmndr_o => resb_o,
ov_o => ov_o
);

p_testbench: process
variable l : line;
begin
for i in 0 to 255 loop
for j in 0 to 255 loop
op1_i <= conv_std_logic_vector(i,;
op2_i <= conv_std_logic_vector(j,;
wait for 10 ns;
write(l,string'("OP1 :"));
write(l,printb(op1_i));
write(l,string'(" / OP2 :"));
write(l,printb(op2_i));
writeline(output,l);
write(l,string'("RESA:"));
write(l,printb(resa_o));
write(l,string'(" / RESB:"));
write(l,printb(resb_o));
write(l,string'(" / OV:"));
if (ov_o = '1') then
write(l,string'("1"));
else
write(l,string'("0"));
end if;
writeline(output,l);
if (op2_i = "00000000") then
assert (ov_o = '1')
report "ERROR: DIV BY Zero - OV-Assignment"
severity failure;
else
assert (ov_o = '0')
report "ERROR: DIV - OV-Assignment"
severity failure;
assert (resa_o = conv_std_logic_vector(i/j,)
report "ERROR: DIV - RESA-Assignment"
severity failure;
assert (resb_o = conv_std_logic_vector(i rem j,)
report "ERROR: DIV - RESB-Assignment"
severity failure;
end if;
end loop;
end loop;
assert false
report "Simulation successfully finished."
severity note;
wait;
end process p_testbench;

end behave;
 
Reply With Quote
 
 
 
 
Gabriel Schuster
Guest
Posts: n/a
 
      09-21-2006
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
library std;
use std.textio.all;


entity tb_alu_div is
end tb_alu_div;

architecture behave of tb_alu_div is

function printb (bv : in std_logic_vector) return string is
alias bv_norm : std_logic_vector(1 to bv'length) is bv;
variable result : string(1 to bv'length);
begin
for index in bv_norm'range loop
if bv_norm(index) = '0' then
result(index) := '0';
else
result(index) := '1';
end if;
end loop;
return result;
end printb;

component alu_div
port (
op1_i : in std_logic_vector(7 downto 0); -- dividend
op2_i : in std_logic_vector(7 downto 0); -- divisor
resa_o : out std_logic_vector(7 downto 0); -- result
resb_o : out std_logic_vector(7 downto 0); -- remainder
ov_o : out std_logic
);
end component alu_div;

signal op1_i : std_logic_vector(7 downto 0) := "00000000";
signal op2_i : std_logic_vector(7 downto 0) := "00000000";
signal resa_o : std_logic_vector(7 downto 0);
signal resb_o : std_logic_vector(7 downto 0);
signal ov_o : std_logic;

begin

uut: alu_div
port map (
op1_i => op1_i,
op2_i => op2_i,
resa_o => resa_o,
resb_o => resb_o,
ov_o => ov_o
);

p_testbench: process
variable l : line;
variable v_16 : unsigned(15 downto 0);
begin
v_16 := "0000000000000000";
for i in 0 to 65535 loop
op1_i <= std_logic_vector(v_16(15 downto );
op2_i <= std_logic_vector(v_16(7 downto 0));
wait for 10 ns;
write(l,string'("OP1 :"));
write(l,printb(op1_i));
write(l,string'(" / OP2 :"));
write(l,printb(op2_i));
writeline(output,l);
write(l,string'("RESA:"));
write(l,printb(resa_o));
write(l,string'(" / RESB:"));
write(l,printb(resb_o));
write(l,string'(" / OV:"));
if (ov_o = '1') then
write(l,string'("1"));
else
write(l,string'("0"));
end if;
writeline(output,l);
if (op2_i = "00000000") then
assert (ov_o = '1')
report "ERROR: DIV BY Zero - OV-Assignment"
severity failure;
else
assert (ov_o = '0')
report "ERROR: DIV - OV-Assignment"
severity failure;
assert (resa_o = std_logic_vector(unsigned(op1_i) /
unsigned(op2_i)))
report "ERROR: DIV - RESA-Assignment"
severity failure;
assert (resb_o = std_logic_vector(unsigned(op1_i) rem
unsigned(op2_i)))
report "ERROR: DIV - RESB-Assignment"
severity failure;
end if;
v_16 := v_16 + 1;
end loop;
assert false
report "Simulation successfully finished."
severity note;
wait;
end process p_testbench;

end behave;
 
Reply With Quote
 
Andy
Guest
Posts: n/a
 
      09-21-2006
The following statement probably does not do what you want:

if (std_logic_vector(v_tmp(7 downto i)) >= op2_i) then

What you have is a comparison of two slvs, which iirc, is based on
length, not value(?).

You should convert op2_i to unsigned, and maybe have to resize() on
v_tmp, but you do not want to convert it to slv!

Be careful what you ask for, because the compiler will give you exactly
that!

Andy

 
Reply With Quote
 
Gabriel Schuster
Guest
Posts: n/a
 
      09-22-2006
Thanks a lot!!!
I've changed it to

if (to_integer(v_tmp(7 downto i)) >= to_integer(unsigned(op2_i))) then

and it works perfectly!!!

Andy wrote:
> The following statement probably does not do what you want:
>
> if (std_logic_vector(v_tmp(7 downto i)) >= op2_i) then
>
> What you have is a comparison of two slvs, which iirc, is based on
> length, not value(?).
>
> You should convert op2_i to unsigned, and maybe have to resize() on
> v_tmp, but you do not want to convert it to slv!
>
> Be careful what you ask for, because the compiler will give you exactly
> that!
>
> Andy
>

 
Reply With Quote
 
Nicolas Matringe
Guest
Posts: n/a
 
      09-22-2006
Gabriel Schuster a écrit :
> Thanks a lot!!!
> I've changed it to
>
> if (to_integer(v_tmp(7 downto i)) >= to_integer(unsigned(op2_i))) then


You can drop the conversions
if (v_tmp(7 downto i) >= unsigned(op2_i)) then

Nicolas
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
division by 7 without using division operator krypto.wizard@gmail.com C Programming 94 02-09-2007 06:57 AM
SRT DIvision, Square root and reciprocal square root alghazo@siu.edu VHDL 0 05-27-2004 06:23 AM
polynomial division remainder Manfred Balik VHDL 5 05-18-2004 02:37 AM
FLOATING POINT DIVISION sunwij VHDL 3 12-29-2003 04:44 AM
will Synposys Design Compiler support division by two's power and integer rounding? walala VHDL 12 09-14-2003 03:49 PM



Advertisments