VHDL에서 signed와 unsigned는 데이터 버스에 산술 연산을 수행하게 해주는 특수 비트 벡터입니다. std_logic_vector가 시그널 라우팅엔 이상적이지만 계산엔 부적합한 반면, 이 타입들은 컴파일러에 의해 숫자값으로 해석됩니다.
std_logic_vector를 더하려 하면 No feasible entries for infix operator "+" 컴파일 에러가 납니다. 도구가 원시 비트 패턴을 숫자로 어떻게 다룰지 판단 못 하기 때문입니다.
Basic VHDL Tutorials 시리즈의 일부.
산술을 가능하게 하려면 벡터를 signed나 unsigned로 선언하세요:
signal <name> : signed(<N-1> downto 0) := <initial_value>; signal <name> : unsigned(<N-1> downto 0) := <initial_value>;
범위는 to나 downto 둘 다 가능하지만 downto 0이 가장 일반적입니다. 초기값은 선택 사항이며 생략 시 모든 비트가 'U'로 기본 설정됩니다.
전통적 integer 대신 signed/unsigned를 선호하는 이유? 디지털 설계자는 비트 폭을 정밀하게 제어해야 할 때가 많습니다. 이 벡터 타입은 오버플로 시 랩어라운드(wrap around)하지만 integer는 한계 초과 시 런타임 에러를 냅니다. 게다가 벡터는 'U', 'X' 같은 메타값을 포함해 설계 버그를 조기 발견하는 데 도움이 됩니다.
비디오 시연
동반 비디오에서 signed와 unsigned 시그널이 어떻게 비슷하게 동작하고 어디서 갈리는지 탐구합니다.
샘플 코드
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T12_SignedUnsignedTb is end entity; architecture sim of T12_SignedUnsignedTb is signal UnsCnt : unsigned(7 downto 0) := (others => '0'); signal SigCnt : signed(7 downto 0) := (others => '0'); signal Uns4 : unsigned(3 downto 0) := "1000"; signal Sig4 : signed(3 downto 0) := "1000"; signal Uns8 : unsigned(7 downto 0) := (others => '0'); signal Sig8 : signed(7 downto 0) := (others => '0'); begin process is begin wait for 10 ns; -- Wrapping counter UnsCnt <= UnsCnt + 1; SigCnt <= SigCnt + 1; -- Adding signals Uns8 <= Uns8 + Uns4; Sig8 <= Sig8 + Sig4; end process; end architecture;
파형 분석
ModelSim 파형, 주요 이벤트 확대로 모든 값 16진수로 표시:
카운터 예제에서 UnsCnt와 SigCnt 모두 0에서 시작해 FF(10진수 255)까지 증가 후 0으로 랩어라운드—동일한 랩어라운드 동작 시연.
4비트 시그널 Uns4와 Sig4 모두 이진 1000을 가지며, 부호 없는 경우 10진수 8, 부호 있는 경우 -8(2의 보수)입니다.
이 4비트 숫자를 8비트 누산기에 더할 때 부호 확장이 작용합니다. 부호 없는 수는 0으로 패딩, 부호 있는 수는 부호 비트로 패딩. 결과적으로 Uns8은 8 증가, Sig8은 8 감소합니다.