如何删除 vhdl 中的闩锁和 RTL_ROM 的用途?

how to remove the latch in vhdl and purpose of RTL_ROM?

下面的代码是一个简单的16位加法器(只用了一个四位加法器)。我试着避开所有的闩锁。但是我无法移除图像中突出显示的闩锁(sum_16_temp)。任何人都可以帮助我避免这种闩锁。如果有人能帮助我理解 RTL_ROMnext_state_i 的目的,我将不胜感激。 =13=]

    library IEEE;
    use IEEE.STD_LOGIC_1164.ALL;

    entity sixteen_bit_adder is
        Port ( a_16 : in STD_LOGIC_VECTOR (15 downto 0);
               b_16 : in STD_LOGIC_VECTOR (15 downto 0);
               carry_in_16 : in STD_LOGIC;
               clk : in std_logic;
               reset_16 : in std_logic;
               done_addition : out std_logic;
               sum_16 : out STD_LOGIC_VECTOR (15 downto 0);
               carry_out_16 : out STD_LOGIC);

    end sixteen_bit_adder;

    architecture structural of sixteen_bit_adder is

                              ------------------signal declaration------------------
    signal sum_16_temp      : STD_LOGIC_VECTOR (15 downto 0):=x"0000";      -- temporary register for sum
    signal carry_out_temp   : std_logic;                           -- temporary register for carry
    type state_type is (s0,s1,s2,s3,s4);                              -- states;
    signal next_state,state: state_type;
    signal a_4,b_4,sum_4: STD_LOGIC_VECTOR (3 downto 0):=x"0";           -- temp for 4 bit component inputs
    signal carry_in_4,carry_out_4,done_temp: std_logic:='0'; 
                               -------end of signal declaration-------

                               ------component declaration-------------

    component  four_bit_adder is
        Port ( a : in STD_LOGIC_VECTOR (3 downto 0);
               b : in STD_LOGIC_VECTOR (3 downto 0);
               carry_in : in STD_LOGIC;
               sum_4 : out STD_LOGIC_VECTOR (3 downto 0);
               carry_out : out STD_LOGIC);
    end component four_bit_adder;
                                ------end of component declaraton--------

    begin

    four_bit_adder1: four_bit_adder port map(a_4, b_4, carry_in_4, sum_4, carry_out_4);
    flopping_process:  process(reset_16,clk)
                               begin
                                    if reset_16 ='1' then
                                        sum_16          <=   x"0000";
                                        carry_out_16    <=   '0';
                                        state           <=   s0;
                                        done_addition   <=   '0';
                                    elsif rising_edge(clk) then
                                        sum_16          <=   sum_16_temp;
                                        carry_out_16    <=   carry_out_temp;
                                        state           <=   next_state;
                                        done_addition   <=   done_temp;

                                    end if;
                       end process;

    State_machine:     process(state,reset_16)
                                begin
                                if reset_16 ='0' then
                                      case state is
                                            when s0 =>

                                                 a_4             <=   a_16(3 downto 0);
                                                 b_4             <=   b_16(3 downto 0);
                                                 carry_in_4      <=   carry_in_16; 
                                                 next_state      <=   s1;
                                                 sum_16_temp(3 downto 0)     <=   sum_4;
                                                 carry_out_temp    <=   carry_out_4;
                                                 done_temp   <=   '0';

                                            when s1 =>
                                                 a_4             <=   a_16(7 downto 4);
                                                 b_4             <=   b_16(7 downto 4);
                                                 carry_in_4      <=   carry_out_4;
                                                 sum_16_temp(3 downto 0)     <=   sum_4;
                                                 next_state      <=   s2;
                                                 carry_out_temp    <=   carry_out_4;
                                                 done_temp   <=   '0';
                                            when s2 =>
                                                 a_4             <=   a_16(11 downto 8);
                                                 b_4             <=   b_16(11 downto 8);
                                                 carry_in_4      <=   carry_out_4;
                                                 sum_16_temp(7 downto 4)    <=   sum_4;
                                                 next_state      <=   s3;
                                                 carry_out_temp    <=   carry_out_4;
                                                 done_temp   <=   '0';
                                           when s3 =>
                                                 a_4             <=   a_16(15 downto 12);
                                                 b_4             <=   b_16(15 downto 12);
                                                 carry_in_4      <=   carry_out_4;
                                                 sum_16_temp(11 downto 8)    <=   sum_4;
                                                 next_state      <=   s4;
                                                 carry_out_temp    <=   carry_out_4;
                                                 done_temp   <=   '0';
                                           when others =>
                                                 a_4             <=   a_16(15 downto 12);
                                                 b_4             <=   b_16(15 downto 12);
                                                 carry_in_4      <=   carry_out_4;
                                                 sum_16_temp(15 downto 12)    <=   sum_4;
                                                 carry_out_temp    <=   carry_out_4;
                                                 done_temp   <=   '1';
                                                 next_state      <=   s4;

                                            end case;
                                else
                                             a_4             <=   x"0";
                                             b_4             <=   x"0";
                                             carry_in_4      <=   '0';
                                             sum_16_temp     <=   x"0000";
                                             carry_out_temp  <=   '0';
                                             done_temp   <=   '0';
                                             next_state      <=   s0;
                                end if;
                       end process;

    end structural;

我不愿意回答没有 MCVE 的问题。没有办法知道是否还有其他问题。

library ieee;
use ieee.std_logic_1164.all;

entity sixteen_bit_adder is
    port ( 
        a_16:           in  std_logic_vector (15 downto 0);
        b_16:           in  std_logic_vector (15 downto 0);
        carry_in_16:    in  std_logic;
        clk:            in  std_logic;
        reset_16:       in  std_logic;
        done_addition:  out std_logic;
        sum_16:         out std_logic_vector (15 downto 0);
        carry_out_16:   out std_logic
    );
end entity sixteen_bit_adder;

architecture structural of sixteen_bit_adder is

    -- signal sum_16_temp:       std_logic_vector (15 downto 0) := x"0000";
    signal carry_out_temp:    std_logic;
    type state_type is (s0,s1,s2,s3,s4);
    signal next_state, state: state_type;
    signal a_4, b_4, sum_4:   std_logic_vector (3 downto 0) := x"0";
    signal carry_in_4,
           carry_out_4,
           done_temp:         std_logic := '0'; 


    component  four_bit_adder is
        port ( 
            a:         in  std_logic_vector (3 downto 0);
            b:         in  std_logic_vector (3 downto 0);
            carry_in:  in  std_logic;
            sum_4:     out std_logic_vector (3 downto 0);
            carry_out: out std_logic
        );
    end component four_bit_adder;

begin

four_bit_adder1: 
    four_bit_adder 
        port map (a_4, b_4, carry_in_4, sum_4, carry_out_4);

flopping_process:  
    process (reset_16, clk)
    begin
        if reset_16 = '1' then
            sum_16          <=   x"0000";
            carry_out_16    <=   '0';
            state           <=   s0;
            done_addition   <=   '0';
        elsif rising_edge(clk) then
            case state is
                when s0 =>
                    sum_16(3 downto 0) <= sum_4;
                when s1 =>
                    sum_16(7 downto 4) <= sum_4;
                when s2 =>
                    sum_16(11 downto 8) <= sum_4;
                when s3 =>
                    sum_16(15 downto 12) <= sum_4;
                when others =>
            end case;
            -- sum_16          <=   sum_16_temp;
            carry_out_16    <=   carry_out_temp;
            state           <=   next_state;
            done_addition   <=   done_temp;
        end if;
    end process;

state_machine:
    process (state, reset_16, a_16, b_16, carry_in_16, carry_in_4)
    begin
        if reset_16 = '0' then
            case state is
                when s0 =>
                     a_4             <=   a_16(3 downto 0);
                     b_4             <=   b_16(3 downto 0);
                     carry_in_4      <=   carry_in_16; 
                     next_state      <=   s1;
                     -- sum_16_temp(3 downto 0)     <=   sum_4;
                     carry_out_temp    <=   carry_out_4;
                     done_temp   <=   '0';
                when s1 =>
                     a_4             <=   a_16(7 downto 4);
                     b_4             <=   b_16(7 downto 4);
                     carry_in_4      <=   carry_out_4;
                     -- sum_16_temp(3 downto 0)     <=   sum_4;
                     next_state      <=   s2;
                     carry_out_temp    <=   carry_out_4;
                     done_temp   <=   '0';
                when s2 =>
                     a_4             <=   a_16(11 downto 8);
                     b_4             <=   b_16(11 downto 8);
                     carry_in_4      <=   carry_out_4;
                     -- sum_16_temp(7 downto 4)    <=   sum_4;
                     next_state      <=   s3;
                     carry_out_temp    <=   carry_out_4;
                     done_temp   <=   '0';
               when s3 =>
                     a_4             <=   a_16(15 downto 12);
                     b_4             <=   b_16(15 downto 12);
                     carry_in_4      <=   carry_out_4;
                     -- sum_16_temp(11 downto 8)    <=   sum_4;
                     next_state      <=   s4;
                     carry_out_temp    <=   carry_out_4;
                     done_temp   <=   '0';
               when others =>
                     a_4             <=   a_16(15 downto 12);
                     b_4             <=   b_16(15 downto 12);
                     carry_in_4      <=   carry_out_4;
                     -- sum_16_temp(15 downto 12)    <=   sum_4;
                     carry_out_temp    <=   carry_out_4;
                     done_temp   <=   '1';
                     next_state      <=   s4;
              end case;
        else
            a_4             <=   x"0";
            b_4             <=   x"0";
            carry_in_4      <=   '0';
            -- sum_16_temp     <=   x"0000";
            carry_out_temp  <=   '0';
            done_temp   <=   '0';
            next_state      <=   s0;
        end if;
    end process;

end architecture structural;

这通过根据状态将加法器 (sum_4) 的输出分配给 sum_16 的半字节来消除 sum_16_temp。

图中锁存器的 RTL_ROM 输入为您要消除的当前锁存器提供了相同的 nybble 转向。

您在此答案分析中修改的代码。如果没有 four_bit_adder 的实体和体系结构对,也没有应用刺激的方法来确保功能,答案只会解决您要删除的闩锁。

这个答案中的代码确实进行了分析,但没有更多的内容无法详细说明或模拟。

仔细检查后发现您的设计规范存在其他问题

严格来说组合过程敏感性列表:

state_machine:
        process (state, reset_16)

还应包含所有输入。这通常不会产生合成伪影,但会影响模拟结果(输出延迟,直到敏感列表中的事件和信号丢失 'glitches')。

大多数综合软件忽略敏感度列表,而您在问题中展示了映射结果。

将在信号分配右侧的表达式中找到的信号添加到灵敏度列表:

    state_machine:
        process (state, reset_16, a_16, b_16, carry_in_16, carry_in_4)

揭示了一个设计问题。在状态 s1、s2、s3 和 s4 中,您有:

                     carry_in_4      <=   carry_out_4;

没有寄存器保存前一个 nybble 进位值的好处。这不会模拟并且应该至少在综合过程中给你一个警告。将进位附加到 4 位加法器的进位提供了一个反馈循环,有可能提供不同的结果。这可以描述为张弛振荡器。

导入和执行反馈的解决方案很微妙,表明您的设计规范尚未完成。

所以我进行了更改以正确支持进位,同时修复了敏感度列表:

architecture structural of sixteen_bit_adder is

    -- signal sum_16_temp:       std_logic_vector (15 downto 0) := x"0000";
    signal carry_out_temp:    std_logic;
    type state_type is (s0,s1,s2,s3,s4);
    signal next_state, state: state_type;
    signal a_4, b_4, sum_4:   std_logic_vector (3 downto 0) := x"0";
    signal carry_in_4,
           carry_out_4,
           done_temp:         std_logic := '0';


    component  four_bit_adder is
        port ( 
            a:         in  std_logic_vector (3 downto 0);
            b:         in  std_logic_vector (3 downto 0);
            carry_in:  in  std_logic;
            sum_4:     out std_logic_vector (3 downto 0);
            carry_out: out std_logic
        );
    end component four_bit_adder;

begin

four_bit_adder1: 
    four_bit_adder 
        port map (a_4, b_4, carry_in_4, sum_4, carry_out_4);

flopping_process:  
    process (reset_16, clk)
    begin
        if reset_16 = '1' then
            sum_16          <=   x"0000";
            carry_out_16    <=   '0';
            state           <=   s0;
            done_addition   <=   '0';
        elsif rising_edge(clk) then
            case state is
                when s0 =>
                    sum_16(3 downto 0) <= sum_4;

                when s1 =>
                    sum_16(7 downto 4) <= sum_4;
                when s2 =>
                    sum_16(11 downto 8) <= sum_4;
                when s3 =>
                    sum_16(15 downto 12) <= sum_4;
                when others =>
            end case;
            -- sum_16          <=   sum_16_temp;
            carry_out_16    <=   carry_out_temp;
            state           <=   next_state;
            done_addition   <=   done_temp;
        end if;
    end process;

state_machine:
    process (state,reset_16, a_16, b_16, carry_in_16)
    begin
        if reset_16 = '0' then
            case state is
                when s0 =>
                     a_4             <=   a_16(3 downto 0);
                     b_4             <=   b_16(3 downto 0);
                     carry_in_4      <=   carry_in_16; 
                     next_state      <=   s1;
                     -- sum_16_temp(3 downto 0)     <=   sum_4;
                     carry_out_temp    <=   carry_out_4;
                     done_temp   <=   '0';
                when s1 =>
                     a_4             <=   a_16(7 downto 4);
                     b_4             <=   b_16(7 downto 4);
                     carry_in_4      <=   carry_out_4;
                     -- sum_16_temp(3 downto 0)     <=   sum_4;
                     next_state      <=   s2;
                     carry_out_temp    <=   carry_out_4;
                     done_temp   <=   '0';
                when s2 =>
                     a_4             <=   a_16(11 downto 8);
                     b_4             <=   b_16(11 downto 8);
                     carry_in_4      <=   carry_out_4;
                     -- sum_16_temp(7 downto 4)    <=   sum_4;
                     next_state      <=   s3;
                     carry_out_temp    <=   carry_out_4;
                     done_temp   <=   '0';
               when s3 =>
                     a_4             <=   a_16(15 downto 12);
                     b_4             <=   b_16(15 downto 12);
                     carry_in_4      <=   carry_out_4;
                     -- sum_16_temp(11 downto 8)    <=   sum_4;
                     next_state      <=   s4;
                     carry_out_temp    <=   carry_out_4;
                     done_temp   <=   '0';
               when others =>
                     a_4             <=   a_16(15 downto 12);
                     b_4             <=   b_16(15 downto 12);
                     carry_in_4      <=   carry_out_4;
                     -- sum_16_temp(15 downto 12)    <=   sum_4;
                     carry_out_temp    <=   carry_out_4;
                     done_temp   <=   '1';
                     next_state      <=   s4;
              end case;
        else
            a_4             <=   x"0";
            b_4             <=   x"0";
            carry_in_4      <=   '0';
            -- sum_16_temp     <=   x"0000";
            carry_out_temp  <=   '0';
            done_temp   <=   '0';
            next_state      <=   s0;
        end if;
    end process;

end architecture structural;

模拟了一个四位加法器:

图书馆 ieee;

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

entity  four_bit_adder is
    port ( 
        a:         in  std_logic_vector (3 downto 0);
        b:         in  std_logic_vector (3 downto 0);
        carry_in:  in  std_logic;
        sum_4:     out std_logic_vector (3 downto 0);
        carry_out: out std_logic
    );
end entity four_bit_adder;

architecture foo of four_bit_adder is
    signal sum:   std_logic_vector (5 downto 0);
begin
    sum <= std_logic_vector (
            unsigned ("0" & a & carry_in) + unsigned (b & carry_in)
           );
    carry_out <= sum(5);
    sum_4 <= sum(4 downto 1);
end architecture;

和一个测试平台:

library ieee;
use ieee.std_logic_1164.all;

entity sixteen_bit_adder_tb is
end entity;

architecture foo of sixteen_bit_adder_tb is
    signal a_16:           std_logic_vector (15 downto 0) := (others => '0');
    signal b_16:           std_logic_vector (15 downto 0) := (others => '0');
    signal carry_in_16:    std_logic := '0';
    signal clk:            std_logic := '0';
    signal reset_16:       std_logic := '1';
    signal done_addition:  std_logic;
    signal sum_16:         std_logic_vector (15 downto 0);
    signal carry_out_16:   std_logic;
begin
DUT:
    entity work.sixteen_bit_adder
        port map (
            a_16 => a_16,
            b_16 => b_16,
            carry_in_16 => carry_in_16,
            clk => clk,
            reset_16 => reset_16,
            done_addition => done_addition,
            sum_16 => sum_16,
            carry_out_16 => carry_out_16
        );
CLOCK:
    process
    begin
        wait for 5 ns;
        clk <= not clk;
        if now > 140 ns then
            wait;
        end if;
    end process;
STIMLI:
    process
    begin
        wait for 20 ns;
        a_16 <= x"0043";
        b_16 <= x"FFFE";  -- one's complement of 1
        carry_in_16 <= '1';  -- plus one is the two's complement
        reset_16 <= '0';
        wait until done_addition = '1';
        wait until rising_edge (clk);
        reset_16 <= '1';
        wait until rising_edge (clk);
        a_16 <= x"1234";
        b_16 <= x"4567";
        carry_in_16 <= '0';
        reset_16 <= '0';
        wait;

    end process;
end architecture;

并得到:

看起来有用的东西。

(请注意,这并不是一个详尽的测试,应该构建一组输入值对,用于选择性地测试跨 nybbles 的进位输入)。