2016-06-07 120 views
1

我想要做一個「添加和移位乘法器(順序)」,我在最後的模擬上遇到問題,輸出中的值始終是錯誤的。我用狀態機邏輯來製作部分和的控制塊。VHDL添加和移位乘法器的邏輯仿真錯誤

當我做1×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; 

A 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; 

一個狀態機控制器,用於控制來自總和寄存器的輸入信號。

我正在使用一個BDF文件來連接所有塊,與下面的示意圖唯一的區別是在加法器塊中有一個進位輸入。 所有塊的時鐘位於同一個引腳。

Controller simulation

任何人有任何的想法是什麼原因造成這個錯誤?

+1

你的問題不是一個[最小,完整和可驗證的例子](http://stackoverflow.com/help/mcve),缺乏任何手段來複制(未說明)的錯誤。你的波形甚至不顯示狀態,你的控件也不顯示數據通路連接(o_MDLD,o_MRLD,o_RSLD,o_RSCLR,o_RSSHR)。 – user1155120

+0

我不能發佈任何更多的圖像,我相信錯誤不是在狀態機上,因爲當我模擬每個組件單獨所有他們正常工作,但是當我模擬他們集成錯誤出現時,我要把用你說的輸出波形。 – Mutante

+0

我添加了原始帖子user1155120上的控制器模擬屏幕截圖。我相信控制器塊可以正常工作。 – Mutante

回答

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會發生什麼?如果這是一個有符號乘法,你指定了無符號乘數和被乘數,其中正確答案是65025(「1111111000000001」)。因爲你有單獨的加載和移位操作,所以你需要以保存被丟棄的進位,並在換入時使用它。因爲可以有連續的乘數位爲'0',所以在用於移位指令後需要清除進位(缺省爲預期符號,即'0 '爲無符號乘法)。

你可以做到這一點與儲蓄進了adder_8bits和你原來的9位路徑:

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; 

注意,它清除食用時,需要前面的負載插話攜帶=「1」。

如果你有兩個加載和移位加載和一個加載指令而不是加載指令和移位指令,這個設計可能會消失。它需要從摩爾狀態機切換到Mealy狀態機,並減少狀態數。

您是控制器,摩爾狀態機可以遍歷16個狀態,既可以移位也可以加載「11111111」的乘數,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,並且控制器狀態機需要重寫爲發出i_load_shift ='1'或i_shift ='1'且另一個'0'的Mealy機器,具體取決於評估的乘數位是'1'或'0'。

注意這裏有很多提示,即使您將乘數,被乘數和乘積聲明爲無符號,如何對乘法進行標記。

1

問題出在sum_register中,我將加法器的執行位發送到總和寄存器,所以這使得輸出出錯,我只是從發送到總和寄存器的字節中取出進位。

s <= 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; 

利用這種變化仿真就OK了!

+0

這個答案不正確。當你乘以255×255會發生什麼?您的產品爲1,正確答案爲65025(「1111111000000001」)。這也強調了對[最小,完整和可驗證示例](http://stackoverflow.com/help/mcve)的需求。 – user1155120