亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> VHDL

VHDL 中的有符号与无符号

所有数字设计师都必须了解 FPGA 或 ASIC 内部的数学原理。第一步是了解有符号和无符号信号类型是如何工作的。 numeric_std 中存在有符号和无符号类型 包,它是 ieee 库的一部分。需要注意的是,还有一个包文件经常被用来进行数学运算:std_logic_arith .但是,std_logic_arith 不是官方 ieee 支持的包文件,不建议在数字设计中使用。

定义为 signed 类型的信号 意味着工具将此信号解释为正面或负面。定义为 unsigned 类型的信号 意味着信号只会是积极的。在内部,FPGA 将使用 Two's Complement 表示。例如,一个 3 位的信号可以根据下表来解释:

位 无符号值 签名值 011 3 3 010 2 2 001 1 1 000 0 0 111 7 -1 110 6 -2 101 5 -3 100 4 -4

你还迷茫吗?你应该是,这不直观!让我们看一个希望能把事情弄清楚的例子。下面的文件测试了有符号无符号的工作原理。需要理解的是信号是否定义为有符号或无符号不是 影响实际二进制数学的执行方式。

例如:对于两个有符号向量 10001 + 00010,答案仍然是 10011,但它是 解释 的结果是不同的。
对于未签名的情况,答案 (10011) 代表 19。
对于已签名的情况,答案 (10011) 表示 -13。

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


entity signed_unsigned is
  port (
    i_rst_l : in std_logic;
    i_clk   : in std_logic;
    i_a     : in std_logic_vector(4 downto 0);
    i_b     : in std_logic_vector(4 downto 0)
    );
end signed_unsigned;

architecture behave of signed_unsigned is
  signal rs_SUM_RESULT : signed(4 downto 0)   := (others => '0');
  signal ru_SUM_RESULT : unsigned(4 downto 0) := (others => '0');
  signal rs_SUB_RESULT : signed(4 downto 0)   := (others => '0');
  signal ru_SUB_RESULT : unsigned(4 downto 0) := (others => '0');
        
begin

  -- Purpose: Add two numbers.  Does both the signed and unsigned
  -- addition for demonstration.  This process is synthesizable.
  p_SUM : process (i_clk, i_rst_l)
  begin 
    if i_rst_l = '0' then             -- asynchronous reset (active low)
      rs_SUM_RESULT <= (others => '0');
      ru_SUM_RESULT <= (others => '0');
    elsif rising_edge(i_clk) then
      
      ru_SUM_RESULT <= unsigned(i_a) + unsigned(i_b);
      rs_SUM_RESULT <= signed(i_a) + signed(i_b);
    
    end if;
      
  end process p_SUM;

  
  -- Purpose: Subtract two numbers.  Does both the signed and unsigned
  -- subtraction for demonstration.  This process is synthesizable.
  p_SUB : process (i_clk, i_rst_l)
  begin 
    if i_rst_l = '0' then             -- asynchronous reset (active low)
      rs_SUB_RESULT <= (others => '0');
      ru_SUB_RESULT <= (others => '0');
    elsif rising_edge(i_clk) then
          
      ru_SUB_RESULT <= unsigned(i_a) - unsigned(i_b);
      rs_SUB_RESULT <= signed(i_a) - signed(i_b);
    
    end if;
      
  end process p_SUB;

end behave;

测试台:

library ieee;
use ieee.std_logic_1164.all;

entity example_signed_unsigned_tb is
end example_signed_unsigned_tb;

architecture behave of example_signed_unsigned_tb is

  --Registers
  signal r_CLK   : std_logic                    := '0';
  signal r_RST_L : std_logic                    := '0';
  signal r_A     : natural                      := 0;
  signal r_B     : natural                      := 0;
  signal r_A_SLV : std_logic_vector(4 downto 0) := (others => '0');
  signal r_B_SLV : std_logic_vector(4 downto 0) := (others => '0');

  constant c_CLK_PERIOD : time := 10 ns;

  component example_signed_unsigned is
    port (
      i_rst_l        : in  std_logic;
      i_clk          : in  std_logic;
      i_a            : in  std_logic_vector(4 downto 0);
      i_b            : in  std_logic_vector(4 downto 0)
      );
  end component example_signed_unsigned;

begin
  
  i_DUT: example_signed_unsigned
    port map (
     i_rst_l          => r_RST_L,
     i_clk            => r_CLK,
     i_a              => r_A_SLV,
     i_b              => r_B_SLV
     );

  
  clk_gen : process is
  begin
    r_CLK <= '0' after c_CLK_PERIOD/2, '1' after c_CLK_PERIOD;
    wait for c_CLK_PERIOD;
  end process clk_gen;


  process
  begin
    
    r_RST_L <= '0';
    wait for 20 ns;
    r_RST_L <= '1';
    wait for 20 ns;

    r_A_SLV <= "01001";
    r_B_SLV <= "00110";   
    wait for 20 ns;

    r_A_SLV <= "10001";
    r_B_SLV <= "00110";
    wait for 20 ns;

    r_A_SLV <= "10001";
    r_B_SLV <= "00001";
    wait for 20 ns;

    r_A_SLV <= "10001";
    r_B_SLV <= "00010";
    wait for 20 ns;
    
    r_A_SLV <= "11111";
    r_B_SLV <= "00001";
    wait for 20 ns;

    r_A_SLV <= "00000";
    r_B_SLV <= "00001";
    wait for 20 ns;    
    wait;
    
  end process;

end behave;

Modelsim仿真波输出值以十六进制显示

Modelsim 模拟波输出值以十进制显示

比较上面的两个modelsim截图。在第一个你可以看到 results 以十六进制表示时,数学函数的数量完全相同。这是解释 的结果是不同的。这可以通过查看底部屏幕截图来看到。当 Modelsim 以十进制显示结果时,它会将其中的一些解释为负数。使用有符号和无符号类型时,您必须非常小心!希望你能更好地理解这个话题。我觉得这是许多数字设计师都在努力解决的一个领域,所以如果有什么你不完全理解的东西,请通过侧边栏上的联系链接给我发电子邮件,我会尽量把它说得更清楚。


最受欢迎的 Nandland 页面

VHDL

  1. 教程 - VHDL 简介
  2. VHDL 转换示例
  3. 过程语句 - VHDL 示例
  4. 记录 - VHDL 示例
  5. 变量 - VHDL 示例
  6. 当前信号系统
  7. 交通信号
  8. LoRa 本地化
  9. 使用 PSL 在 VHDL 中进行形式化验证
  10. 如何在 VHDL 中创建字符串列表
  11. 如何在 VHDL 测试平台中停止仿真
  12. 信号完整性和 PCB