移位溢出错误?超高密度语言

Overflow error in shift? VHDL

我正在尝试将千克转换为 Lib,为此我使用移位器进行转换(由于输出的表示形式不是小数,我会出现一个小错误),我发现正确的函数和值来进行转换,当我这样说时,我的意思是我的移位值是正确的,如果有人想要转换函数,请在下面的评论中告诉我。

我的问题是:当我输入大于 130 KG 的值时,转换出错,小值则 130 KG 工作正常。我正在使用 16 位输入(千克输入)和 16 位输出(LB 输出)。

出现这个错误的时候,我第一时间以为是加法器溢出错误,但是所有加法器都没有进位,所以不可能是加法器溢出。我试图在值(32 位)中使用更大的表示,但错误仍然出现。由于这个原因,我删除了执行输出。

代码下方:

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

entity shift_register is
port (
    i_DIN : in unsigned (15 downto 0);
    o_DOUT0 : out unsigned (15 downto 0);
    o_DOUT1 : out unsigned (15 downto 0);
    o_DOUT2 : out unsigned (15 downto 0);
    o_DOUT3 : out unsigned (15 downto 0)); 
end shift_register;

architecture arch_1 of shift_register is
begin
    o_DOUT0 <= i_DIN SLL 9;
    o_DOUT1 <= i_DIN SLL 5;
    o_DOUT2 <= i_DIN SLL 2;
    o_DOUT3 <= i_DIN SLL 1;
end arch_1;

在这部分,我对转换工作进行了 4 次必要的转换,在此之后我得到 4 个值输出并求和为 2 个半加器。

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

entity half_adder is
port (
    i_DIN0 : in unsigned(15 downto 0); -- data input
    i_DIN1 : in unsigned(15 downto 0); -- data input
    o_DOUT : out unsigned(16 downto 0)); -- data output
end half_adder;


architecture arch_1 of half_adder is
begin
process(i_DIN0,i_DIN1)
     variable soma:unsigned(15 downto 0);
     variable c:std_logic; 
     begin
          c :='0';
          for i in 0 to 15 loop
                soma(i) := i_DIN0(i) xor i_DIN1(i) xor c;
                c := (i_DIN0(i) and i_DIN1(i)) or ((i_DIN0(i) xor i_DIN1(i)) and c);
          end loop;
          o_DOUT(15 downto 0)<= soma(15 downto 0);
          o_DOUT(16) <= c;
      end process;
end arch_1;

我将有 2 个输出,每个半加器 1 个,这 2 个输出我加到一个全加器中以获得最终的移位值,2 个半加器的进位在每个输出的最后一位连接.

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

entity full_adder is
port (
    i_DIN0 : in unsigned(16 downto 0); 
    i_DIN1 : in unsigned(16 downto 0); 
    o_DOUT : out unsigned(16 downto 0)); 
end full_adder;

architecture arch_1 of full_adder is
begin
     process(i_DIN0,i_DIN1)
     variable soma:unsigned(16 downto 0);
     variable c:std_logic; 
     begin
          c := '0';
          for i in 0 to 16 loop
                soma(i) := i_DIN0(i) xor i_DIN1(i) xor c;
                c := (i_DIN0(i) and i_DIN1(i)) or ((i_DIN0(i) xor i_DIN1(i)) and c);
          end loop;
          o_DOUT <= soma;
      end process;
end arch_1;

这里我没有将全加器的进位连接到输出的最后一位,因为我想在总和溢出时显示进位。

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

entity div_register is
port (
    i_DIN : in unsigned (16 downto 0);
    o_DOUT : out unsigned (16 downto 0)); 
end div_register;

architecture arch_1 of div_register is
begin
    o_DOUT <= i_DIN SRL 8;
end arch_1;

最后我将4个初始移位的总和除以得到转换后的值。

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity kg_to_lb is
port (
    i_INPUTKG : in  unsigned(15 downto 0); -- data input
    o_OUTLB : out unsigned(16 downto 0)); -- data output
end kg_to_lb;


architecture arch_1 of kg_to_lb is

component full_adder is
    port (
    i_DIN0 : in unsigned(16 downto 0); 
    i_DIN1 : in unsigned(16 downto 0); 
    o_DOUT : out unsigned(16 downto 0)); -- data output
end component;

component half_adder is 
port (
    i_DIN0 : in unsigned(15 downto 0); -- data input
    i_DIN1 : in unsigned(15 downto 0); -- data input
    o_DOUT : out unsigned(16 downto 0)); -- data output
end component;  

component shift_register is 
port (
    i_DIN : in unsigned (15 downto 0);
    o_DOUT0 : out unsigned (15 downto 0);
    o_DOUT1 : out unsigned (15 downto 0);
    o_DOUT2 : out unsigned (15 downto 0);
    o_DOUT3 : out unsigned (15 downto 0)); -- data output
end component; 

component div_register is 
port (
    i_DIN : in unsigned (16 downto 0);
    o_DOUT : out unsigned (16 downto 0)); -- data output
end component; 



signal w_OUT0 : unsigned(15 downto 0);
signal w_OUT1 : unsigned(15 downto 0);
signal w_OUT2 : unsigned(15 downto 0);
signal w_OUT3 : unsigned(15 downto 0);
signal w_OUT4 : unsigned(16 downto 0);
signal w_OUT5 : unsigned(16 downto 0);
signal w_OUT6 : unsigned(16 downto 0);
signal w_OUT7 : unsigned(16 downto 0);

begin 

u_0: shift_register port map (
                 i_DIN => i_INPUTKG,
                 o_DOUT0 => w_OUT0,
                 o_DOUT1 => w_OUT1,
                 o_DOUT2 => w_OUT2,
                 o_DOUT3 => w_OUT3
                  );

u_1: half_adder port map (
                 i_DIN0 => w_OUT0,
                 i_DIN1 => w_OUT1,
                 o_DOUT => w_OUT4
                  );

u_2: half_adder port map (
                 i_DIN0 => w_OUT2,
                 i_DIN1 => w_OUT3,
                 o_DOUT => w_OUT5
                  );

u_3: full_adder port map (
                 i_DIN0 => w_OUT4,
                 i_DIN1 => w_OUT5,
                 o_DOUT => w_OUT6
                 );

u_4: div_register port map (
                 i_DIN => w_OUT6,
                 o_DOUT => w_OUT7
                 );

o_OUTLB <= w_OUT7;

end arch_1;

这是我的主文件,我在其中完成了所有这些,基本上我使用的是与下图相同的架构,唯一的区别是偏移,因为我在转换函数中使用了另一个值,但是换个图还是报错

以下正确转换:

就像我之前说的,由于忽略了小数部分,所以会出现错误。当我输入大于 130KG 的值时,转换出错:

注意:在我的模拟中,我没有从全加器中取出进位,因为我已经模拟了这个,并且在模拟中没有出现进位(溢出错误),因此我认为错误是在轮班中。

有人知道这是什么吗?

错误出在内部寄存器宽度上,当我移位逻辑 9 时,对于大于 8 位的值,de 输出保持为 0,因为移位太大,解决方案是使用更大的寄存器(32 位在这种情况)。