Подписанный и неподписанный в VHDL
Все цифровые дизайнеры должны понимать, как математика работает внутри FPGA или ASIC. Первым шагом к этому является понимание того, как работают типы сигналов со знаком и без знака. Подписанные и неподписанные типы существуют в numeric_std. пакет, который является частью библиотеки ieee. Следует отметить, что есть еще один пакетный файл, который часто используется для выполнения математических операций:std_logic_arith. . Однако std_logic_arith не является официальным файлом пакета, поддерживаемым IEEE, и его не рекомендуется использовать в цифровых проектах.
Сигнал, определенный как тип signed означает, что инструменты интерпретируют этот сигнал как положительный или отрицательный. Сигнал, определенный как тип unsigned означает, что сигнал будет только положительным. Внутри ПЛИС будет использовать дополнение до двух. представление. Например, 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, показанный в DECIMAL
Сравните два скриншота modelim выше. В первом вы можете видеть, что результаты математических функций точно такие же, когда они представлены в шестнадцатеричном виде. Это интерпретация результатов, которые отличаются. В этом можно убедиться, взглянув на нижний скриншот. Когда Modelsim отображает результаты в десятичном виде, некоторые из них интерпретируются как отрицательные числа. При использовании подписанных и неподписанных типов вы должны быть очень осторожны! Надеюсь, вы немного лучше разбираетесь в этой теме. Я чувствую, что многие цифровые дизайнеры борются с этой областью, поэтому, если есть что-то, что вы не совсем понимаете, отправьте мне электронное письмо через ссылку «Контакты» на боковой панели, и я постараюсь сделать это яснее.
VHDL