VHDL을 작성할 때 SIGNALS 에 정수 (int) 대신 std_logic_vector (slv)를 사용하는 것이 좋습니다 . 반면에 제네릭, 정수 및 일부 변수에 int를 사용하면 유용 할 수 있습니다. int 유형의 신호를 선언하거나 정수의 범위를 지정해야하는 경우 간단히 수행 할 수 있습니다. 뭔가 잘못.
int의 문제점은 VHDL 프로그래머가 int의 내부 논리 표현이 무엇인지 알지 못하므로이를 활용할 수 없다는 것입니다. 예를 들어 1에서 10 범위의 정수를 정의하면 컴파일러가 해당 값을 어떻게 인코딩하는지 전혀 모릅니다. 잘만되면 그것은 4 비트로 인코딩 될 것이지만, 우리는 그 이상을 잘 모릅니다. FPGA 내부의 신호를 프로브 할 수 있으면 "0001"에서 "1010"으로 인코딩되거나 "0000"에서 "1001"로 인코딩 될 수 있습니다. 그것은 우리 인간에게는 절대적으로 의미가없는 방식으로 인코딩 될 수도 있습니다.
대신 int 대신 slv를 사용해야합니다. 왜냐하면 인코딩을 제어하고 개별 비트에 직접 액세스 할 수 있기 때문입니다. 나중에 볼 수 있듯이 직접 액세스하는 것이 중요합니다.
개별 비트에 액세스해야 할 때마다 int를 slv에 캐스트 할 수는 있지만 정말 지저분하고 빠릅니다. 그것은 두 세계의 최고 대신 두 세계의 최악을 얻는 것과 같습니다. 컴파일러는 최적화하기 어렵고 읽을 수없는 코드가 될 것입니다. 나는 이것을 권장하지 않습니다.
내가 말했듯이 slv를 사용하면 비트 인코딩을 제어하고 비트에 직접 액세스 할 수 있습니다. 그래서 당신은 이것으로 무엇을 할 수 있습니까? 몇 가지 예를 보여 드리겠습니다. 4,294,000,000 클럭마다 한 번씩 펄스를 출력해야한다고 가정 해 봅시다. int로 이것을 수행하는 방법은 다음과 같습니다.
signal count :integer range 0 to 4293999999; -- a 32 bit integer
process (clk)
begin
if rising_edge(clk) then
if count = 4293999999 then -- The important line!
count <= 0;
pulse <= '1';
else
count <= count + 1;
pulse <= '0';
end if;
end if;
end process;
그리고 slv를 사용하는 동일한 코드 :
use ieee.numeric_std.all;
signal count :std_logic_vector (32 downto 0); -- a 33 bit integer, one extra bit!
process (clk)
begin
if rising_edge(clk) then
if count(count'high)='1' then -- The important line!
count <= std_logic_vector(4293999999-1,count'length);
pulse <= '1';
else
count <= count - 1;
pulse <= '0';
end if;
end if;
end process;
이 코드의 대부분은 최소한 결과 논리의 크기와 속도의 관점에서 int와 slv간에 동일합니다. 물론 하나는 카운트 업하고 다른 하나는 카운트 다운하지만이 예제에서는 중요하지 않습니다.
차이점은 "중요한 선"에 있습니다.
int 예제를 사용하면 32 입력 비교기가됩니다. Xilinx Spartan-3이 사용하는 4 입력 LUT를 사용하려면 11 개의 LUT와 3 단계의 로직이 필요합니다. 일부 컴파일러는 이것을 캐리 체인을 사용하여 32 LUT에 해당하는 뺄셈으로 변환하지만 3 레벨의 논리보다 빠르게 실행될 수 있습니다.
slv 예제에서는 32 비트 비교가 없으므로 "제로 LUT, 제로 레벨 논리"입니다. 유일한 페널티는 카운터가 하나의 추가 비트라는 것입니다. 이 여분의 비트 비트에 대한 추가 타이밍이 모두 캐리 체인에 있기 때문에 "거의 0"추가 타이밍 지연이 있습니다.
물론 이것은 대부분의 사람들이 이런 식으로 32 비트 카운터를 사용하지 않기 때문에 극단적 인 예입니다. 더 작은 카운터에는 적용되지만 그 차이는 여전히 크지 만 덜 극적인 것입니다.
이것은 빠른 타이밍을 얻기 위해 int를 통해 slv를 사용하는 방법의 한 가지 예일뿐입니다. slv를 활용하는 다른 많은 방법이 있습니다. 약간의 상상력 만 있으면됩니다.
업데이트 : "if (count-1) <0"으로 int를 사용하는 것에 대한 Martin Thompson의 의견을 다루는 내용이 추가되었습니다.
(참고 : 나는 당신이 "if count <0"을 의미한다고 가정합니다. 왜냐하면 그것은 내 slv 버전과 더 동등하고 그 추가 빼기의 필요성을 제거하기 때문입니다.)
경우에 따라 의도 된 논리 구현이 생성 될 수 있지만 항상 작동하는 것은 아닙니다. 코드와 컴파일러가 int 값을 인코딩하는 방법에 따라 다릅니다.
컴파일러와 int 범위를 지정하는 방법에 따라 int 값이 0 인 경우 FPGA 로직으로 만들 때 "0000 ... 0000"의 비트 벡터로 인코딩되지 않을 수 있습니다. 변형이 작동하려면 "0000 ... 0000"으로 인코딩해야합니다.
예를 들어 int를 -5에서 +5의 범위로 정의한다고 가정 해 봅시다. 값 0은 "0000"과 같은 4 비트로, +5는 "0101", -5는 "1011"로 인코딩 될 것으로 예상합니다. 이것이 전형적인 2 보완 인코딩 체계입니다.
그러나 컴파일러가 twos-complement를 사용한다고 가정하지 마십시오. 드문 일이지만, 보완은 "더 나은"논리를 초래할 수 있습니다. 또는 컴파일러는 일종의 "바이어스 드"인코딩을 사용할 수 있습니다. 여기서 -5는 "0000", 0은 "0101", +5는 "1010"으로 인코딩됩니다.
int의 인코딩이 "정확한"경우 컴파일러는 캐리 비트로 수행 할 작업을 유추 할 수 있습니다. 그러나 그것이 틀렸다면 결과 논리는 끔찍할 것입니다.
이런 식으로 int를 사용하면 논리 크기와 속도가 합리적 일 수 있지만 보장 할 수는 없습니다. 다른 컴파일러 (예 : XST에서 시놉시스로)로 전환하거나 다른 FPGA 아키텍처로 전환하면 정확히 잘못된 일이 발생할 수 있습니다.
Unsigned / Signed vs. slv는 또 다른 논쟁입니다. VHDL에 많은 옵션을 제공 한 미국 정부위원회에 감사 할 수 있습니다. :) 모듈과 코어 사이의 인터페이스 표준이기 때문에 slv를 사용합니다. 그 외에도 시뮬레이션의 다른 경우에는 서명 / 서명되지 않은 것보다 slv를 사용하면 큰 이점이 없다고 생각합니다. 서명 / 서명되지 않은 신호가 삼중 신호를 지원하는지 확실하지 않습니다.