添加和移位倍增器

时间:2016-06-07 22:15:37

标签: vhdl quartus

我正在尝试“添加和移位乘法器(顺序)”并且我在最终模拟中遇到问题,输出上的值总是错误的。我使用状态机逻辑来制作部分和的控制块。

当我制作1 x 1输出错误时(所有产品出错):

Output Error on VWF File

所有被乘数和乘数输入都会出现此错误。

我使用以下代码来计算总和:

 library IEEE;
 use IEEE.std_logic_1164.all;

 entity adder_8bits is 
 port (
     cin: in STD_LOGIC;
     a,b: in STD_LOGIC_VECTOR(7 DOWNTO 0);
     s: out STD_LOGIC_VECTOR(8 DOWNTO 0)
 );
 end adder_8bits;

 architecture arch_1 of adder_8bits is 
 begin 
     process(a,b,cin)
     variable soma:std_logic_vector(8 downto 0);
     variable c:std_logic; 
     begin
          c := cin;
          for i in 0 to 7 loop
                soma(i) := a(i) xor b(i) xor c;
                c := (a(i) and b(i)) or ((a(i) xor b(i)) and c);
          end loop;
          s(7 downto 0) <= soma(7 downto 0);
          s(8) <= c;
      end process;
end arch_1;

8位加法器,用于对部分结果求和。

 library IEEE;
 use IEEE.std_logic_1164.all;
 use IEEE.numeric_std.all;

 entity sum_register is 
 port (
     i_DIN   : in UNSIGNED(8 DOWNTO 0);
     i_LOAD  : in STD_LOGIC;
     i_CLEAR : in STD_LOGIC;
     i_SHIFT : in STD_LOGIC;
     i_CLK : in STD_ULOGIC;
     o_DOUT  : buffer UNSIGNED(15 downto 0)
 );
 end sum_register;


 architecture arch_1 of sum_register is 
 begin
     process(i_CLK)
     begin
     IF rising_edge(i_CLK) THEN
        IF (i_CLEAR = '1') THEN
            o_DOUT <= "0000000000000000";
        ELSIF (i_LOAD = '1') THEN
            o_DOUT(15 downto 7) <= i_DIN;
        ELSIF (i_SHIFT = '1') THEN
            IF (i_DIN(8) = '1') THEN
              o_DOUT <= o_DOUT SRL 1;
            END IF;
        END IF;
      END IF;
      end process;
end arch_1;

一个和寄存器,用于获取实际的和值,并在另一个和之前移位。

LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.std_logic_unsigned.ALL;
use IEEE.std_logic_arith.ALL;

ENTITY controller IS
  PORT (
        i_CLK     : IN STD_ULOGIC;
        i_START   : IN  STD_LOGIC; 
        i_MLTPLR  : IN STD_LOGIC_VECTOR(7 downto 0);
        o_MDLD    : OUT STD_LOGIC; 
        o_MRLD    : OUT STD_LOGIC;  
        o_RSLD    : OUT STD_LOGIC;
        o_RSCLR   : OUT STD_LOGIC;
        o_RSSHR   : OUT STD_LOGIC
      );     
END controller;

ARCHITECTURE arch_1 OF controller IS
  TYPE state_type IS (s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18);
  SIGNAL stateT : state_type;
BEGIN
  PROCESS(i_CLK)
  BEGIN
  IF rising_edge(i_CLK) THEN
      IF (i_START = '0') THEN
        stateT <= s0;
      ELSE
        CASE stateT IS
          when s0 => if (i_START = '1') then 
                         stateT <= s1; 
                     end if;
          when s1 =>  stateT <= s2;          
          when s2 => if (i_MLTPLR(0) = '1') then
                         stateT <= s3;
                     else
                         stateT <= s4;
                     end if;
          when s3 => stateT <= s4;                    
          when s4 => if (i_MLTPLR(1) = '1') then
                         stateT <= s5;
                     else
                         stateT <= s6;
                     end if;
          when s5 => stateT <= s6;
          when s6 => if (i_MLTPLR(2) = '1') then
                         stateT <= s7;
                     else
                         stateT <= s8;
                     end if;
          when s7 => stateT <= s8;
          when s8 => if (i_MLTPLR(3) = '1') then
                         stateT <= s9;
                     else
                         stateT <= s10;
                     end if;
          when s9 => stateT <= s10;
          when s10 => if (i_MLTPLR(4) = '1') then
                         stateT <= s11;
                     else
                         stateT <= s12;
                     end if;
          when s11 => stateT <= s12;
          when s12 => if (i_MLTPLR(5) = '1') then
                         stateT <= s13;
                     else
                         stateT <= s14;
                     end if;  
          when s13 => stateT <= s14; 
          when s14 => if (i_MLTPLR(6) = '1') then
                         stateT <= s15;
                     else
                         stateT <= s16;
                     end if;  
          when s15 => stateT <= s16; 
          when s16 => if (i_MLTPLR(7) = '1') then
                         stateT <= s17;
                     else
                         stateT <= s18;
                     end if;           
          when s17 => stateT <= s18; 
          when s18 => stateT <= s0;    
        END CASE;
      END IF;
    END IF;
  END PROCESS;

  o_MDLD <= '1' when (stateT = s1) else '0';  
  o_MRLD <= '1' when (stateT = s1) else '0';  
  o_RSCLR <= '1' when (stateT = s1) else '0';
  o_RSLD  <= '1' when (stateT = s3 or stateT = s5 or 
                       stateT = s7 or stateT = s9 or 
                       stateT = s11 or stateT = s13 or 
                       stateT = s15 or stateT = s17) else '0';    
  o_RSSHR <= '1' when (stateT = s4 or stateT = s6 or 
                       stateT = s8 or stateT = s10 or 
                       stateT = s12 or stateT = s14 or 
                       stateT = s16 or stateT = s18) else '0'; 

END arch_1;

状态机控制器,用于控制来自de sum寄存器的输入信号。

我使用BDF文件连接所有块,与下面的原理图的唯一区别是加法器块中有一个进位输入。 所有块的时钟都在同一个引脚上。

Controller simulation

任何人都知道导致此错误的原因是什么?

2 个答案:

答案 0 :(得分:1)

问题出在sum_register,我将加法器的进位发送到和寄存器,所以这会导致输出出错,我只是从发送到和寄存器的字节中取出进位。 / p>

 s <= soma;
来自加法器的

和变量soma变为8位:

variable soma:std_logic_vector(7 downto 0);

总和寄存器被更改为仅从加法器接收8位:

architecture arch_1 of sum_register is 
 begin
     process(i_CLK)
     begin
     IF rising_edge(i_CLK) THEN
        IF (i_CLEAR = '1') THEN
            o_DOUT <= "0000000000000000";
        ELSIF (i_LOAD = '1') THEN
            o_DOUT(15 downto 8) <= i_DIN;
        ELSIF (i_SHIFT = '1') THEN
              o_DOUT <= o_DOUT SRL 1;

        END IF;
      END IF;
      end process;
end arch_1;

通过这些更改,模拟就可以了!

答案 1 :(得分:0)

实施答案时:

architecture arch_1 of sum_register is 
 begin
     process(i_CLK)
     begin
     IF rising_edge(i_CLK) THEN
        IF (i_CLEAR = '1') THEN
            o_DOUT <= "0000000000000000";
        ELSIF (i_LOAD = '1') THEN
            o_DOUT(15 downto 8) <= i_DIN;
        ELSIF (i_SHIFT = '1') THEN
              o_DOUT <= o_DOUT SRL 1;

        END IF;
      END IF;
      end process;
end arch_1;

当你乘以255 x 255时会发生什么?

你的产品是1(如果这是一个有符号的乘法,你指定无符号乘数和被乘数,这是正确的,正确的答案是65025(&#34; 1111111000000001&#34;)。因为你有单独的负载和换档操作你需要保存丢弃的进位并在转入时使用它。而且因为你可以有连续的乘数位,而且需要清除它后面的进位。移位指令(默认为预期符号,对于无符号乘法是&#39; 0&#39;。

您可以使用原始的9位路径为adder_8bits求和并保存进位:

architecture foo of sum_register is
    signal carry: std_logic;
begin
    process (i_clk)
    begin
        if rising_edge(i_clk) then
            if i_clear = '1' then
                o_dout <= (others => '0');
                carry <= '0';
            elsif i_load = '1' then
                o_dout(15 downto 8) <= i_din (7 downto 0);
                carry <= i_din(8);
            elsif i_shift = '1' then
                o_dout <= carry & o_dout(15 downto 1);
                carry <= '0';  -- expected sign for multiply result
            end if;
        end if;
    end process;
end architecture;

请注意,它在消耗时已被清除,需要先前的加载来插入进位=&#39; 1&#39;。

如果你有两个加载和移位负载和一个加载指令而不是加载指令和移位指令,这个设计可能会消失。它需要从Moore状态机切换到Mealy状态机并减少状态数。

你是一个控制器,一个摩尔状态机可以遍历16个状态,它们都可以移动和加载一个乘法器&#34; 11111111&#34;,一个Mealy机器可以在8个状态下进行移位 - 和 - sum_register中的加载和移位操作。

sum_register看起来像:

architecture fum of sum_register is

begin
    process (i_clk)
    begin
        if rising_edge(i_clk) then
            if i_clear = '1' then
                o_dout <= (others => '0');
            elsif i_load_shift = '1' then
                o_dout(15 downto 7) <= i_din & o_dout (6 downto 1); 
            elsif i_shift = '1' then
                o_dout <= '0' & o_dout(15 downto 1); -- '0' expected result sign
            end if;
        end if;
    end process;
end architecture;

来自adder_8bits的9位总和。注意,i_load信号被重命名为i_load_shift,并且控制器状态机需要重新编写为Mealy机器,发出i_load_shift =&#39; 1&#39;或者i_shift =&#39; 1&#39;而另一个&#39; 0&#39;取决于评估的乘数位是否为&#39; 1&#39;或者是&#39; 0&#39;。

请注意,即使您将乘数,被乘数和乘积声明为无符号,此处仍有大量提示如何签名乘法。