VHDL에서 "무관심"신호를 지정하려면 어떻게해야합니까?


11

Logic Design 과정에서는 Karnaugh 맵 또는 Quine–McCluskey 알고리즘 을 사용하여 로직 기능을 최소화 할 수 있다는 것을 모두 배웠습니다 . 또한 "Do n't Care" 값이 최소화 가능성을 증가 시킨다는 것도 알게되었습니다 .

예를 들어 레지스터 파일을 가져옵니다. write_addresswrite_data때 신호는별로 중요하지 않습니다 write_enable신호입니다 '0'. 따라서 이들 신호를 구동 하는 로직 (예 : 레지스터 파일 자체가 아님) 에서 더 많은 최적화를 허용하려면 "Do n't Care"값을 지정해야합니다 .

합성 툴에 가능한 최적화를위한 더 많은 공간을 허용하기 위해 VHDL에서 이러한 "Do n't Care"값을 지정하는 올바른 방법은 무엇입니까?


지금까지 나는 다음과 같은 것들이 적합하다고 생각했다. 그러나 각 접근법의 장단점이 무엇인지 확실하지 않습니다.

  • 단순히 신호를 할당하지 않습니다. 이것은 작동하는 것처럼 보입니다. 그러나 record레코드 상수를 완전히 지정해야하기 때문에 어떤 유형의 "아무것도 상수 없음"을 정의하려고 할 때 작동하지 않는 것으로 나타났습니다 (적어도 Modelsim이 나에게 알려줍니다).
  • std_logic_1164패키지는 값 정의 '-' -- Don't care를 들어 std_ulogic. 이것은 명시 적으로 "무관심"에 대한 의미 상 올바른 선택 인 것처럼 보이지만 관련이없는 VHDL-2008 case?구조를 제외하고는 어느 곳에서나 사용 된 적이 없습니다 .
  • Modelsim은 값 'X'을 사용하여 정의되지 않은 신호를 표시합니다. 그러나 합성 도구가 명시 적 'X'할당을 "무관심" 으로 이해하는지 확실 하지 않습니다.

설명을 위해 지나치게 단순화 된 코드 스 니펫이 '-'있습니다.

당신이 볼 수 있듯이, 신호는 control.reg_write_address3 개 가지 값을 가질 수 있습니다 "----", instruction(11 downto 8);그리고 instruction(3 downto 0);. 이제는 '-'"무관심"으로 해석되는 경우 2 입력 멀티플렉서로 이것을 합성 할 것으로 기대합니다 . (others => '0')대신을 사용 하여 신호를 초기화했다면 '-'도구는 3 입력 멀티플렉서를 대신 생성해야합니다.

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

package mytypes is
    type control_signals_t is record
        write_enable  : std_logic;
        write_address : std_ulogic_vector(3 downto 0);
        read_address  : std_ulogic_vector(3 downto 0);
    end record;

    -- All members of this constant must be fully specified.
    -- So it's not possible to simply not assign a value.
    constant CONTROL_NOP : control_signals_t := (
        write_enable  => '0',
        write_address => (others => '-'),
        read_address  => (others => '-')
    );
end package;

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

entity control_unit is
    port(
        instruction : in  std_ulogic_vector(15 downto 0);
        write_data  : out std_ulogic_vector(15 downto 0);
        ctrl        : out control_signals_t
    );
end entity;

architecture rtl of control_unit is
begin
    decode_instruction : process(instruction) is
    begin
        -- Set sensible default values that do nothing.
        -- Especially all "write_enable" signals should be '0'.
        -- Everything else is mostly irrelevant (don't care).
        ctrl       <= CONTROL_NOP;
        write_data <= (others => '-');

        if instruction(15 downto 12) = "1100" then
            -- Load 8 bit of data into the register file
            ctrl.write_enable  <= '1';
            write_data         <= std_ulogic_vector(resize(signed(instruction(7 downto 0)), 16));
            ctrl.write_address <= instruction(11 downto 8);
        elsif instruction(15 downto 8) = "11111001" then
            -- Load 4 bit of data into the register file
            write_data         <= std_ulogic_vector(resize(signed(instruction(7 downto 4)), 16));
            ctrl.write_address <= instruction(3 downto 0);
        elsif instruction(15 downto 8) = "10110101" then
            -- Read from the register file. Don't use the write signals at all.
            ctrl.read_address <= instruction(3 downto 0);
        end if;
    end process;
end architecture;

당신은 당신이 뭘 하려는지에 정교한 수 write_addresswrite_data? 어떤 최적화가 예상됩니까?
fru1tbat

나는 그 예가 내가 달성하고자하는 것을 더 명확하게하기를 바랍니다.
프리츠

답변:


9

좀 더 자세한 답변을 제공하기 위해 LRM 전문가에게 맡길 것이지만 요컨대 접근 방식이 유효해야합니다. 최근 버전의 Quartus로 빠른 테스트를 실행했으며 '-'예상 대로 처리 됩니다. 생성 된 로직이 줄어 듭니다. 출력이 기본값으로 설정되면 예상대로 '-'( 'X'그렇게 작동합니다). 나열된 접근법에 대한 자세한 내용 :

  • 신호를 할당하지 않는 것은 물론 래치를 원하지 않는 경우 실제로는 옵션이 아닙니다. 시간이 오래 걸리는 프로세스 인 경우 약간 더 나아지지만 필요하지 않은 곳에서는 계속 활성화 할 수 있습니다. 어쩌면 나는 여기에 당신의 의도를 잃어버린 것 같습니다.

  • '-'앞서 언급했듯이 의미 적 및 실제적인 이유로 아마도 가장 좋은 옵션 일 것입니다.

  • "정의되지 않음"의 의미에 따라 다릅니다. 'X'기술적으로 "알 수 없음"입니다. 'U'초기화되지 않은 신호에 대한 것으로 ModelSim "X"은 16 진 표현으로 표시합니다. 'X'그러나 위에서 언급했듯이 작동하는 것 같습니다.

또 다른 대안은 최적화를 직접 수행하고 한 사례가 명시 적으로 테스트되지 않도록 제거하는 것입니다.

if instruction(15 downto 8) = "11111001" then
  write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 4)), 16));
else
  write_data <= std_ulogic_vector(resize(signed(instruction(7 downto 0)), 16));
end if;

이것은 중요한 단점 (대부분 코드 선명도와 관련이 있음)을 가지고 있으며 아마도 더 이상적인 솔루션을 선택할 것입니다.

덧붙여서, 나는 '-'또한 다음과 같이 일반적으로 사용됩니다 std_match().

if std_match(instruction(15 downto 8), "1100----") then

그 시점에 아마도을 사용하는 것이 좋습니다 case?.


6

요컨대 합법적 인 VHDL이며 일반적으로 합성 도구에서 지원됩니다.

그러나 그것이 사용되는 것을 보는 것은 드문 일입니다. 왜 그런지 모르겠습니다. 귀하의 코드는 그것을 사용하는 것이 의미가있을 때의 좋은 예 인 것 같습니다.

그러나 알아야 할 한 가지 단점 이 있습니다. 합성시, 관심이없는 출력을 구동하는 기능 은 합성 실행 마다 다를 수 있습니다 . 이것은 합성을 덜 결정 론적으로 만듭니다. 신경 쓰지 않는 것으로 정의 된 출력을 실수로 사용하면 오류를 찾기가 더 어려워 질 수 있습니다.

도구 지원

최소한 다음 도구는 신경 쓰지 않고 최적화 가능성을 활용합니다.

  • Xilinx (참조 : "XST 사용자 안내서")
  • Altera (참조 : "권장 HDL 코딩 스타일")
  • 단순화 (참조 : "Synplify 참조 매뉴얼")

자일링스와 알테라는 취급 '-''X'같은 신 플리 파이는 또한 그와 취급, 상관 없어 'U''W'(약한)와 같은 상관 없어.


1
나는 그 단점에 대한 또 다른 적용을 받았다. 내 코드는 다음과 같기 때문에 코드는 시뮬레이션에서는 작동했지만 FPGA에서는 작동하지 않았습니다 if signal = '1' then a; else b; end if;. 불행하게도이 signal아니 었 1거나 0하지만 -. 따라서 시뮬레이션에서 else분기는 실행되었지만 하드웨어에서는 -이 것으로 나타났습니다 1. 따라서 실제 분기는 실행되었습니다.
Fritz

예, 비슷한 버그가 시뮬레이션을 통과했지만 대부분의 경우 'U'시뮬레이션의 시작 부분에서 공통으로 사용되는 else코드 블록이 있습니다. 'U'동시 부울 식의 동작과 비슷한 조건을 전파 할 수 있다면 좋을 것 입니다.
Carl

그 버그를 찾은 후에는 항상 다음과 같은 것을 작성했습니다 if signal = '1' then output <= '1'; elsif signal='0' then output <= '0'; else output <= '-'; end if;. 그리고 나는 모든 레지스터와 메모리에 다음을 추가 : assert not is_X(write_enable) report "we=" & str(A_write_enable) severity ERROR;if write_enable = '1' then assert not is_X(write_addr) report "write_addr=str(write_addr) severity ERROR; end if;. 에 대해서도 동일합니다 write_data. 함께하면 거의 모든 오류가 발생합니다.
프리츠

그 방법이지만, 너무 장황합니다. VHDL 언어로 이러한 가능성을 원합니다.
Carl

1
VHDL은 조금 장황하지만 VHDL 방식 일뿐입니다. : D 반면에, 그것은 또한 매우 명시 적이며, 등 뒤에서 "black magic"을하지 않습니다. 꽤 좋은 것을 발견합니다 (참조 : Python의 Zen "암시 적"은 암시 적입니다. ").
프리츠
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.