首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >整数除以3的简单方法

整数除以3的简单方法
EN

Stack Overflow用户
提问于 2015-10-08 04:46:44
回答 4查看 6.1K关注 0票数 1

我正在做一个项目,就是在FPGA上制作一个简单的音乐播放器。它从PC上获取一个指定格式的音乐文件,并在循环中大声播放。

我们需要实现标准的音符长度,即,Quaver为半拍,Minim为2拍,等等。目前,我们有一个表,在不同的BPM值的时钟周期数的节拍长度。我们需要把它们乘以这些音符的长度,才能得到正确的时钟周期。唯一的问题是Tuplet,它是一个完整拍子的三分之一。

如果不实现一个完整的除法器电路,你有什么数学技巧可以把一个整数大约除以3吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-10-08 04:53:59

除以3等于乘以1/3 (=0.33333)。0.3333可以表示为两个或两个以上的加法(取决于所需的精度)(左)移位输入值。

代码语言:javascript
运行
复制
input*2^-a + input*2^-b + input*2^-c ...

只要为a,b,c,.找到合适的值.

这适用于(几乎)所有部门。

票数 6
EN

Stack Overflow用户

发布于 2015-10-08 14:33:35

下面是Hacker‘some’some中一些代码的VHDL翻译。它使用仅使用移位、加法和乘积的常量3除以无符号整数3(也可以简化为移位和加法)。

代码语言:javascript
运行
复制
-- q is quotient, d is dividend
q := (d srl 2) + (d srl 4); -- q = d*0.0101 (approx)
q := q + (q srl 4); -- q = d*0.01010101
q := q + (q srl 8);
q := q + (q srl 16);
r := resize(d - q * 3, 32); -- 0 <= r <= 15.
q := resize(q + (5 * (r + 1) srl 4), 32);
票数 1
EN

Stack Overflow用户

发布于 2017-09-22 10:33:01

如果长度为3的无符号值需要整数除以3 (x / 3)的确切结果,则可以使用截断整数操作。1/3的常量应该是长度LEN + 1,并且应该添加1。然后可以在以后使用截断。伪码为:

代码语言:javascript
运行
复制
C = 2 ** (LEN + 1) / 3 + 1
y = (x * C) / 2 ** (LEN + 1)

显示和测试所有值的算法的Python函数是:

代码语言:javascript
运行
复制
def div_by_3_test(LEN):
    DIVISOR = 3
    C = 2 ** (LEN + 1) // DIVISOR + 1
    for x in range(2 ** LEN):
        if (x * C) // 2 ** (LEN + 1) != x // DIVISOR: exit('Failed') 

实现此功能的VHDL模块如下:

代码语言:javascript
运行
复制
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity div_by_3 is
  generic(
    LEN : natural := 12);
  port(
    x_i   : in  std_logic_vector(LEN - 1 downto 0);
    y_o   : out std_logic_vector(LEN - 1 downto 0));
end entity;

architecture syn of div_by_3 is
  -- Constant to multiply, basically 1/3, but adding 1 to avoid error
  constant C : std_logic_vector(LEN - 1 + 1 downto 0) :=
    std_logic_vector(to_unsigned(2 ** (LEN + 1) / 3 + 1, LEN + 1));
  -- Intermediate, with length as 2 * LEN + 1
  signal t : std_logic_vector(2 * LEN + 1 - 1 downto 0);
begin
  -- Intermediate with full length result
  t <= std_logic_vector(unsigned(C) * unsigned(x_i));
  -- Result after truncation for division by LEN + 1
  y_o <= t(2 * LEN + 1 - 1 downto LEN + 1);
end architecture;

其优点是,仅使用一个LEN位数乘法,就可以在一个周期内将一个2 * LEN + 1位数除以3。

可以添加寄存器以允许高速设计的流水线。

请注意,对于任何除数都可以使用类似的方案,但是C的长度必须是LEN + ceil(log2(DIVISOR)),并相应地缩放C。关于数学基础,请参阅https://math.stackexchange.com/q/2444306/275980

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33006842

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档