【问题标题】:How can I add two std_logic_vectors that have been concatenated in VHDL?如何添加已在 VHDL 中连接的两个 std_logic_vector?
【发布时间】:2018-02-07 06:50:29
【问题描述】:

我正在使用一组特定的函数来开发 ALU。我认为如果我使用额外的位来存储进位,加法和位移部分会容易得多。我正在尝试将一个额外的位连接到两个 8 位长的“std_logic_vector”。额外的位将保留加法中的进位。

但是,当我在一些调试后运行模拟时,它看起来不像我用来给 s_a 和 s_b 他们的值的行在做任何事情。如果我要取出默认值,它们就会变成空的。

我确定这个错误很愚蠢,我不熟悉串联在 vhdl 中的工作原理,也许有更好的方法来存储执行,任何帮助将不胜感激。

代码:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity ALU is
    Port ( 
            A       : in std_logic_vector(7 downto 0);
            B       : in std_logic_vector(7 downto 0);
            SEL     : in std_logic_vector(3 downto 0);
            Cin     : in std_logic;
            Result  : out std_logic_vector(7 downto 0);
            C       : out std_logic;
            Z       : out std_logic);

end ALU;

architecture Behavioral of ALU is

signal s_result: unsigned(8 downto 0) := "000000000";
signal s_cin: unsigned(8 downto 0) := "000000000";
signal s_a: unsigned(8 downto 0) := "000000000";
signal s_b: unsigned(8 downto 0) := "000000000";
signal s_exempt: std_logic := '0';

begin

s1: process(A, B, SEL, CIN)
    begin

        s_a <= ('0' & unsigned(A));
        s_b <= ('0' & unsigned(B));
        s_cin(0) <= Cin;
        s_exempt <= '0';

        case SEL is
          when "0000" =>   
            s_result <= s_a + s_b;
            C <= s_result(8);
          when "0001" =>                    --ADDc Add with carry
            s_result <= s_a + s_b + s_cin;
            C <= s_result(8);
          when "0010" =>                    --SUB
            if(s_a > s_b) then
                s_result <= s_a - s_b;
                C <= '0';
            else
                s_result <= s_b - s_a;
                C <= '1';
            end if;
          when "0011" =>                    --SUBc Subtract with carry

            if(s_a > (s_b + s_cin)) then
              s_result <= s_a - s_b - s_cin;
              C <= '0';
            else
              s_result <= s_b - s_a - s_cin;
              C <= '1';
            end if;
          when "0100" =>                    --CMP  Compare both values              
            if(s_a > s_b) then
                C <= '0';
                Z <= '0';  
            elsif(s_a = s_b) then
                Z <= '1';
                C <= '0';         
            else
                C <= '1';
                Z <= '1';
            end if;
            s_exempt <= '1';     
          when "0101" =>                    --AND
            s_result <= s_a AND s_b;
            C <= '0';
          when "0110" => Z<= '1';           --OR
            s_result <= s_a OR s_b;
            C <= '0';
          when "0111" =>                    --EXOR
            s_result <= s_a XOR s_b;
            C <= '0';
          when "1000" =>                    --TEST, comparator, flag change ONLY
            if((s_a AND s_b) = "000000000") 
                then
                    C <= '0';
                    Z <= '1';
            else
                C <= '0';
                Z <= '0';
            end if;
          when "1001" =>                    --LSL Left shift
            s_result <= s_a sll 1;
            C <= s_result(8);
          when "1010" =>                    --LSR RIght shift
            C <= s_a(0);
            s_result <= s_a srl 1;
          when "1011" => Z<= '1';           --ROL Rotate Left
            s_result <= s_a sll 1;
            C <= s_result(8);
            s_result(0) <= s_result(8);
          when "1100" => Z<= '1';           --ROR Rotate Right
            C <= s_a(0);
            s_result <= s_a srl 1;
            s_result(0) <= s_a(0);
          when "1101" =>                    --ASR Arithemetic Roation
            C <= s_a(0);
            s_result <= s_a srl 1;
            s_result(8) <= s_a(7);
          when "1110" =>                    --MOV Moves data into result
            s_result <= s_b;
            s_exempt <= '1';
          when others => 
            s_result <= "000000000";
            s_exempt <= '1';
            Z <= '0';
            C <= '0';
        end case;

        if(s_exempt = '0') -- Checks Result for 0 if hasn't been found
            then 
                 if(s_result(7 downto 0) = "00000000") 
                    then 
                        Z <= '1';
                 else Z <= '0';
                 end if;
        end if;

       Result <= std_logic_vector(s_result(7 downto 0)); 

    end process; 

end Behavioral;

测试台:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity simulation is
end simulation;

architecture Behavioral of simulation is

    COMPONENT ALU
        Port ( 
               A         : in std_logic_vector(7 downto 0);
               B         : in std_logic_vector(7 downto 0);
               SEL        : in std_logic_vector(3 downto 0);
               Cin        : in std_logic;
               Result    : out std_logic_vector(7 downto 0);
               C         : out std_logic;
               Z        : out std_logic
          );
    END COMPONENT;

    signal A : std_logic_vector(7 downto 0) := "00000000";
    signal B : std_logic_vector(7 downto 0) := "00000000";
    signal SEL : std_logic_vector(3 downto 0) := "0000";
    signal Cin : std_logic;
    signal Result : std_logic_vector(7 downto 0) := "00000000";
    signal C: std_logic := '0';
    signal Z: std_logic := '0';

    begin

        uut: ALU PORT MAP (
            A => A,
            B => B,
            SEL => SEL,
            Cin => Cin,
            Result => Result,
            C => C,
            Z => Z
        );

        stim_proc: process
        begin
            A <= "00000001";
            B <= "00100001";
            SEL <= "0000";
            Cin <= '1';
            wait for 10ns;
            wait;
        end process;
end Behavioral;

【问题讨论】:

    标签: vhdl hardware xilinx hdl


    【解决方案1】:

    在 VHDL 进程中分配的任何信号在进程挂起之前都不会更新。因此,例如,此行中 s_result 的值:

    s_result <= s_a + s_b + s_cin;
    

    在执行此行时不会更新:

    C <= s_result(8);
    

    您需要了解delta 延迟,一旦发现,您将需要重写代码。

    VHDL 是一种硬件 描述语言。您正在设计硬件,而不是编写软件。例如,您对所有信号的初始化不会在硬件中实现,这意味着您的模拟可能与您的硬件表现不同:

    signal s_result: unsigned(8 downto 0) := "000000000";
    signal s_cin: unsigned(8 downto 0) := "000000000";
    signal s_a: unsigned(8 downto 0) := "000000000";
    signal s_b: unsigned(8 downto 0) := "000000000";
    signal s_exempt: std_logic := '0';
    

    【讨论】:

    • 也许使用:= (others =&gt; '0'); 初始化为零。
    • “完全重写代码”可能就像将 s_a、s_b 分配移到进程外一样简单(尽管 C、Z 标志的生成也会出现类似的问题)
    • @BrianDrummond 我打算建议简单地将 s_a、s_b 分配移到流程之外,但标志生成的东西更难改变。
    • 除了s_a和s_b之外,还有s_cin、s_result和s_exempt。所有指望立即更新,都可能是在进程 s1 中声明的变量,并且会被夸大为完全重写。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多