2016-09-17 142 views
-1

我正在试图做一个16bit到BCD转换。 我发现这个链接为8位,我试图将其转换为16位。 http://vhdlguru.blogspot.nl/2010/04/8-bit-binary-to-bcd-converter-double.html16bit到bcd转换

我不知道什么即时通讯做错了rpm_1000不断变化,rpm_100停留在4.有没有人有一个想法我做错了什么?

process (Hex_Display_Data) 
     variable i : integer:=0; 
     variable bcd : std_logic_vector(19 downto 0) := (others => '0'); 
     variable bint : std_logic_vector(15 downto 0) := Hex_Display_Data; 

    begin 
     for i in 0 to 15 loop -- repeating 16 times. 
     bcd(19 downto 1) := bcd(18 downto 0); --shifting the bits. 
     bcd(0) := bint(15); -- shift bit in 
     bint(15 downto 1) := bint(14 downto 0); --removing msb 
     bint(0) :='0'; -- adding a '0' 


     if(i < 15 and bcd(3 downto 0) > "0100") then --add 3 if BCD digit is greater than 4. 
     bcd(3 downto 0) := bcd(3 downto 0) + "0011"; 
     end if; 

     if(i < 15 and bcd(7 downto 4) > "0100") then --add 3 if BCD digit is greater than 4. 
     bcd(7 downto 4) := bcd(7 downto 4) + "0011"; 
     end if; 

     if(i < 15 and bcd(11 downto 8) > "0100") then --add 3 if BCD digit is greater than 4. 
     bcd(11 downto 8) := bcd(11 downto 8) + "0011"; 
     end if; 

     if(i < 15 and bcd(15 downto 12) > "0100") then --add 3 if BCD digit is greater than 4. 
     bcd(15 downto 12) := bcd(15 downto 12) + "0011"; 
     end if; 

    end loop; 

    rpm_1000 <= bcd(15 downto 12); 
    rpm_100  <= bcd(11 downto 8); 
    rpm_10  <= bcd(7 downto 4); 
    rpm_1  <= bcd(3 downto 0); 


end process ; 
+0

如果您需要帮助调试,您可能会发现包含[最小,完整和可验证示例](http://stackoverflow.com/help/mcve)会很有用。请注意,流程中有两个'i'变量,一个声明变量和一个内部声明区域中的循环常量(循环语句)。声明的变量'i'不被使用并且可以被删除。你的'vhdlguru'报告“[我认为我自己,仍然是VHDL的新手,如果你在我的帖子中发现任何错误,请原谅我...我不是vhdl中的大师](http://vhdlguru.blogspot.co .NZ/p /约-me.html)”。 – user1155120

回答

1

注4位BCD码可被完全包含在输入的未使用的bcd“位”(19 DOWNTO 16)14位(您Hex_Display_Data),并会得到所有的加3的不能因为发生一起合成过程中吃了高两位是'0'(不是> 4)。

如果你限制你的bcd值4十六进制数字,你的循环迭代到14位:

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

entity bin2bcd is 
    port ( 
     input:  in std_logic_vector (15 downto 0); 
     ones:  out std_logic_vector (3 downto 0); 
     tens:  out std_logic_vector (3 downto 0); 
     hundreds: out std_logic_vector (3 downto 0); 
     thousands: out std_logic_vector (3 downto 0) 
    ); 
end entity; 

architecture fum of bin2bcd is 
    alias Hex_Display_Data: std_logic_vector (15 downto 0) is input; 
    alias rpm_1: std_logic_vector (3 downto 0) is ones; 
    alias rpm_10: std_logic_vector (3 downto 0) is tens; 
    alias rpm_100: std_logic_vector (3 downto 0) is hundreds; 
    alias rpm_1000: std_logic_vector (3 downto 0) is thousands; 
begin 
    process (Hex_Display_Data) 
     type fourbits is array (3 downto 0) of std_logic_vector(3 downto 0); 
     -- variable i : integer := 0; -- NOT USED 
     -- variable bcd : std_logic_vector(15 downto 0) := (others => '0'); 
     variable bcd: std_logic_vector (15 downto 0); 
     -- variable bint : std_logic_vector(15 downto 0) := Hex_Display_Data; 
     variable bint: std_logic_vector (13 downto 0); -- SEE process body 
    begin 
     bcd := (others => '0');  -- ADDED for EVERY CONVERSION 
     bint := Hex_Display_Data (13 downto 0); -- ADDED for EVERY CONVERSION 

     for i in 0 to 13 loop 
      bcd(15 downto 1) := bcd(14 downto 0); 
      bcd(0) := bint(13); 
      bint(13 downto 1) := bint(12 downto 0); 
      bint(0) := '0'; 

      if i < 13 and bcd(3 downto 0) > "0100" then 
       bcd(3 downto 0) := 
        std_logic_vector (unsigned(bcd(3 downto 0)) + 3); 
      end if; 
      if i < 13 and bcd(7 downto 4) > "0100" then 
       bcd(7 downto 4) := 
        std_logic_vector(unsigned(bcd(7 downto 4)) + 3); 
      end if; 
      if i < 13 and bcd(11 downto 8) > "0100" then 
       bcd(11 downto 8) := 
        std_logic_vector(unsigned(bcd(11 downto 8)) + 3); 
      end if; 
      if i < 13 and bcd(15 downto 12) > "0100" then 
       bcd(11 downto 8) := 
        std_logic_vector(unsigned(bcd(15 downto 12)) + 3); 
      end if; 
     end loop; 

     (rpm_1000, rpm_100, rpm_10, rpm_1) <= 
        fourbits'(bcd (15 downto 12), bcd (11 downto 8), 
           bcd (7 downto 4), bcd (3 downto 0)); 
    end process ; 
end architecture; 

注意使用别名,使你的名字在现有的以其他方式兼容Minimal, Complete and Verifiable Example使用哪个你问题没有提供。

聚合信号分配也是从原来的,你的任务分配到个人数字应该工作得很好。

除了将转换限制为14位以及BCD数字的数量与输出的位数相匹配之外,还有两个变化。

bcdbint变量现在每次过程恢复时都会被清除(对更新Hex_Display_Data敏感)。这些可能导致您无法验证的错误。

多余的括号已被删除。

您没有提供上下文子句。显示的代码使用软件包numeric_std,而不是-2008 numeric_std_unsigned产品与使用IEEE授权软件包的早期版本的修订版兼容。

你会得到一些作品,可证明与测试平台:

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

entity bin2bcd_tb is 
end entity; 

architecture foo of bin2bcd_tb is 
    signal input:  std_logic_vector (15 downto 0) := (others => '0'); 
    signal ones:  std_logic_vector (3 downto 0); 
    signal tens:  std_logic_vector (3 downto 0); 
    signal hundreds: std_logic_vector (3 downto 0); 
    signal thousands: std_logic_vector (3 downto 0); 
begin 
DUT: 
    entity work.bin2bcd 
     port map (
      input => input, 
      ones => ones, 
      tens => tens, 
      hundreds => hundreds, 
      thousands => thousands 
     ); 
STIMULUS: 
    process 
    begin 
     for i in 0 to 1001 loop 
      wait for 20 ns; 
      input <= std_logic_vector(to_unsigned(9999 - i, 16)); 
     end loop; 
     wait for 20 ns; 
     wait; 
    end process; 
end architecture; 

其他一些经济刺激方案可用于在所有四个数字切换BCD数字滚动。

此测试平台提供的输入值开始于9999和1001递减次以显示所有四个数字转换:

bin2bcd_tb.png

我可以很容易地进行修改,以证明每个BCD数字的每一个过渡。

总之你遇到的错误似乎都来自于阐述变量在子程序的差异,其中bcdbint将是动态的阐述和初始化的每个函数调用,并在这个过程中,他们将只初始化一旦。

从探讨Xilinx公司的用户指南901 Vivado设计套件用户指南,合成(2015.3),第4章:VHDL支持,组合工艺,case语句,for循环语句,for循环出现合成得到支持和已经被报道在其他双面半透明问题上可以合成为合格。这个问题将支持重复赋值给顺序语句的重复序列中的变量,这应该得到支持。在stackoverflow中至少有一个其他的double dbsble问题,使用这样的for循环已经报告了成功的合成。

请注意,将处理的输入值限制为14位不会检测到较大二进制数(> 9999)的影响,您的进程无法提供仅4个BCD输出数字。您可以通过检查输入值是否大于9999(x“270F”)来处理该问题。

+3代表一个FPGA(4位输入,4位输出)中的1个LUT深度,根据转换后的数字的大小(范围为i),它们的深度分层数。允许通过ADD3进行转换传播的时间被可视化解释的速率所抵消。如果在毫秒范围内更新了Hex_Display_Data,您可能无法直观地看出差异。

0

运行循环16次将导致BCD寄存器的值,以由65536(MOD 100000)相乘,并加入到在二进制寄存器中的值。说值4000然后4000x65536产生44000 44000x65536产量84000. 84000x65536产量24000 24000x65536产量64000和64000x65536产量4000

为了使算法工作,必须通过清除BCD寄存器开始了。修复关于你的循环运行多少次的评论也不会有什么坏处。顺便说一下,二进制到BCD转换器的实际实现通常应该接受时钟输入,并为每个有效时钟边沿执行一个步骤。如果你的VHDL完全在模拟中运行,那么结果逻辑的复杂性就无关紧要,但是试图在真实硬件中一次完成所有的事情将会非常昂贵。相比之下,硬件可以简单地转换二进制数和BCD数的乘以二。请注意,如果您一次执行所有操作,输出的最高有效位将取决于输入的次低位,这意味着输入信号必须在一个步骤中传播所有逻辑。相比之下,如果每个时钟周期移位一位,则输出的每一位仅取决于输入的最多四位(因为每个数字在调整阶段之前将在0-9范围内,所以添加3永远不会导致执行)。

另外,“double dabble”算法要求在BCD移位之前执行之前的调整,但看起来好像代码正在执行之后的调整。进行调整后,如果有人看起来是 范围16..13,12..9,8..5和4..1而不是15..12等,那么可以进行调整。或者,可以指定值的位19..17应该是位18..16的值,位16..13的值应该是位15..12的值(如果小于5)或位15的值。 12,再加上三个(如果更大)等等。这样的公式将每个位的值设置在一个地方,这将使得更容易看到它应该如何被渲染成硬件。

+0

不是在这里清除? 变量bcd:std_logic_vector(19 downto 0):=(others =>'0'); – Dylan

+0

你描述的行为是没有被清除的症状。我不知道为什么它不会被清除,但我认为其他答案之一确定了一个可能的原因。 – supercat