VHDL 中的有符号与无符号
所有数字设计师都必须了解 FPGA 或 ASIC 内部的数学原理。第一步是了解有符号和无符号信号类型是如何工作的。 numeric_std 中存在有符号和无符号类型 包,它是 ieee 库的一部分。需要注意的是,还有一个包文件经常被用来进行数学运算:std_logic_arith .但是,std_logic_arith 不是官方 ieee 支持的包文件,不建议在数字设计中使用。
定义为 signed 类型的信号 意味着工具将此信号解释为正面或负面。定义为 unsigned 类型的信号 意味着信号只会是积极的。在内部,FPGA 将使用 Two's Complement 表示。例如,一个 3 位的信号可以根据下表来解释:
你还迷茫吗?你应该是,这不直观!让我们看一个希望能把事情弄清楚的例子。下面的文件测试了有符号无符号的工作原理。需要理解的是信号是否定义为有符号或无符号不是 影响实际二进制数学的执行方式。
例如:对于两个有符号向量 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 以十进制显示结果时,它会将其中的一些解释为负数。使用有符号和无符号类型时,您必须非常小心!希望你能更好地理解这个话题。我觉得这是许多数字设计师都在努力解决的一个领域,所以如果有什么你不完全理解的东西,请通过侧边栏上的联系链接给我发电子邮件,我会尽量把它说得更清楚。
VHDL