加法和移位乘法器的VHDL逻辑模拟错误



我正在尝试执行"加法和移位乘法器(顺序)",但我在最终模拟中遇到了问题,输出值总是出错。我使用了一个状态机逻辑来制作部分和的控制块。

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

VWF文件输出错误

对于所有被乘数和乘法器输入,都会出现此错误。

我正在使用以下代码进行汇总:

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;

一种状态机控制器,用于控制来自求和寄存器的输入信号。

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

控制器模拟

有人知道是什么导致了这个错误吗?

实现您的答案时:

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乘以255会发生什么?

你的乘积是1(如果这是一个有符号的乘法,那么这是正确的,你指定了无符号乘法器和被乘数,其中正确的答案是65025("11111111000000001")。因为您有单独的加载和移位操作,所以您需要保存丢弃的进位,并在移入时使用它。因为您可以有连续的乘数位为"0",所以在移位指令中使用该进位后,您需要清除该进位(默认为所需的符号,对于无符号乘法,它是"0")。

您可以使用加法器_8位和的原始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;

请注意,它在消耗时被清除,需要前面的加载插入carry="1"。

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

你是控制器,Moore状态机可以遍历16个状态,包括移位和加载,乘数为"11111111",Mealy状态机可以在sum_register中进行移位、加载和移位操作,在8个状态下完成这一操作。

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;

对于来自加法器_ 8比特的9比特和。请注意,i_load信号被重命名为i_load_shift,并且控制器状态机需要被重写为Mealy机,根据评估的乘数位是"1"还是"0",发出i_load_sift="1"或i_shift='1'以及另一个"0"。

注意,这里有很多关于如何进行有符号乘法的提示,即使您将乘法器、被乘数和乘积声明为无符号。

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

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;

有了这些变化,模拟就可以了!

最新更新