打印

求32位/16位除法器verilog程序

[复制链接]
10608|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
adoiny2010|  楼主 | 2012-5-25 09:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
沙发
Backkom80| | 2012-5-25 13:10 | 只看该作者
有IP的

使用特权

评论回复
板凳
drentsi| | 2012-5-25 18:26 | 只看该作者

使用特权

评论回复
地板
GoldSunMonkey| | 2012-5-26 18:16 | 只看该作者
:)除法如果是常数比较好搞定~

使用特权

评论回复
5
gkb986| | 2012-5-26 22:26 | 只看该作者
除法一直是个难题
https://bbs.21ic.com/viewthread.php?tid=315124&highlight=%2Bdrentsi
drentsi 发表于 2012-5-25 18:26

貌似很难啊!
最快就是查表了,大不了搞个大容量存储器!

使用特权

评论回复
6
李冬发| | 2012-6-3 07:14 | 只看该作者
移位减也是很快的

使用特权

评论回复
7
GoldSunMonkey| | 2012-6-3 16:38 | 只看该作者
移位减也是很快的
李冬发 发表于 2012-6-3 07:14
但是必须是除数是常数

使用特权

评论回复
8
drentsi| | 2012-6-3 17:34 | 只看该作者
但是必须是除数是常数
GoldSunMonkey 发表于 2012-6-3 16:38

可以不是常数,移位减的速度够快,但是需要很多个clock,综合起来,速度还是太慢。
32位除以16位,移位减需要33个clock,在virtex-5中,可以跑到300MHz,但整体延时110ns,难以实用

使用特权

评论回复
9
李冬发| | 2012-6-3 20:48 | 只看该作者
32个移位和减可以同时完成的,不需要很多个clock。

使用特权

评论回复
10
drentsi| | 2012-6-3 22:06 | 只看该作者
我试过,一个clock也可以完成的,logic level =512,延时约200ns

使用特权

评论回复
11
李冬发| | 2012-6-4 01:56 | 只看该作者
logic level =512?
不是你的移位就用了32 level了吧?

使用特权

评论回复
12
GoldSunMonkey| | 2012-6-4 22:25 | 只看该作者
可以不是常数,移位减的速度够快,但是需要很多个clock,综合起来,速度还是太慢。
32位除以16位,移位减需要33个clock,在virtex-5中,可以跑到300MHz,但整体延时110ns,难以实用 ...
drentsi 发表于 2012-6-3 17:34

我对非常数非常感兴趣,有兄弟给我一个例子,感受一下。

使用特权

评论回复
13
drentsi| | 2012-6-5 19:37 | 只看该作者
logic level =512 和延时好像记错了,我把代码贴下来,自己研究一下
单周期除法,来自网上的代码改装的,data_width为参数,16表示32bit除以16bit,可以改成其它值


library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;



entity SDIV_UNIT is
        generic(data_width:integer:=16);
        port (
                CLK: in std_logic;
                DIVIDEND: in STD_LOGIC_VECTOR (data_width*2 - 1 downto 0);
                DIVISOR: in STD_LOGIC_VECTOR (data_width - 1 downto 0);
                DIV_RESULT: out STD_LOGIC_VECTOR (data_width*2 downto 0)
        );
end SDIV_UNIT;

architecture RTL of SDIV_UNIT is




function div1(A: STD_LOGIC_VECTOR; B: STD_LOGIC_VECTOR; Q: STD_LOGIC_VECTOR; EXT: STD_LOGIC)
         return STD_LOGIC_VECTOR is
variable S : STD_LOGIC_VECTOR(A'length downto 0);
variable REST : STD_LOGIC_VECTOR(A'length - 1 downto 0);
variable QN : STD_LOGIC_VECTOR(Q'length downto 0);

begin
  S := EXT & A - B;

  QN := Q & (not S(S'high));
  if S(S'high) = '1' then
    REST := A;
  else
    REST := S(S'high - 1 downto 0);
  end if;
  return QN & REST;
end div1; --function div1

function div(A: STD_LOGIC_VECTOR;
             B: STD_LOGIC_VECTOR;
             Q: STD_LOGIC_VECTOR;
             EXT: STD_LOGIC)
         return STD_LOGIC_VECTOR is

variable R : STD_LOGIC_VECTOR(A'length - 2 downto 0);
variable RESIDUAL : STD_LOGIC_VECTOR(A'length - 1 downto 0);
variable QN : STD_LOGIC_VECTOR(Q'length downto 0);
variable S : STD_LOGIC_VECTOR(B'length + Q'length downto 0);


begin
  S := div1(A(A'high downto A'high - B'high), B, Q, EXT);
  QN := S(S'high downto B'high + 1);

  if A'length > B'length then
    R := S(B'high - 1 downto 0) & A(A'high - B'high - 1 downto 0);
    return DIV(R, B, QN, S(B'high));    -- save MSB '1' in the rest for future sum
  else
    RESIDUAL := S(B'high downto 0);
    return QN(QN'high - 1 downto 0) & RESIDUAL;  -- delete initial '0'
  end if;
end div;


function division(DIVIDEND: STD_LOGIC_VECTOR;
                  DIVISOR: STD_LOGIC_VECTOR)
         return STD_LOGIC_VECTOR is

variable B : STD_LOGIC_VECTOR(DIVISOR'length - 1 downto 0);
variable A : STD_LOGIC_VECTOR(DIVIDEND'length - 1 downto 0);
variable QUOTIENT, REMAINDER : STD_LOGIC_VECTOR(DIVISOR'length - 1 downto 0);
variable VECT : STD_LOGIC_VECTOR(DIVIDEND'length downto 0);
variable QI : STD_LOGIC_VECTOR(0 downto 0);
variable OVFL : STD_LOGIC;

begin
  A := DIVIDEND;                                     -- it is necessary to avoid errors during synthesis!!!!
  B := DIVISOR;
  QI := (others =>'0');

  VECT := div(A, B, QI, '0');

  QUOTIENT := VECT(VECT'high - 1 downto B'high + 1);
  REMAINDER := VECT(B'high downto 0);
  OVFL := VECT(VECT'high );
return OVFL & QUOTIENT & REMAINDER;
-- return VECT;

end division;



signal A_REG: std_logic_vector(data_width*2 - 1 downto 0);
signal B_REG: std_logic_vector(data_width - 1 downto 0);
signal RD_REG: std_logic_vector(data_width*2 downto 0);

begin

process(CLK)
begin
if CLK'event and CLK = '1' then
   A_REG <= DIVIDEND;
   B_REG <= DIVISOR;

  RD_REG <= DIVISION(A_REG, B_REG);

end if;

end process;

DIV_RESULT<=RD_REG;

使用特权

评论回复
14
GoldSunMonkey| | 2012-6-5 21:43 | 只看该作者
logic level =512 和延时好像记错了,我把代码贴下来,自己研究一下
单周期除法,来自网上的代码改装的,data_width为参数,16表示32bit除以16bit,可以改成其它值


library IEEE;
use IEEE.std_logic_1164.all;
us ...
drentsi 发表于 2012-6-5 19:37
先谢谢啦。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

0

主题

8

帖子

0

粉丝