산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> VHDL

TEXTIO를 사용하여 파일에서 RAM을 초기화하는 방법

블록 RAM을 초기 값으로 채우는 편리한 방법은 ASCII 파일에서 2진 또는 16진 리터럴을 읽는 것입니다. 이것은 VHDL에서 ROM(읽기 전용 메모리)을 만드는 좋은 방법이기도 합니다. 결국 RAM과 ROM은 FPGA에서 같은 것이고 ROM은 읽기만 하는 RAM입니다.

이 기사 전체의 예에서는 다음 상수와 RAM 유형이 VHDL 파일의 선언적 영역의 시작 부분에 선언되었다고 가정합니다.

constant ram_depth : natural := 256;
constant ram_width : natural := 32;

type ram_type is array (0 to ram_depth - 1)
  of std_logic_vector(ram_width - 1 downto 0);

이 블로그 게시물은 VHDL에서 TEXTIO 라이브러리를 사용하는 방법에 대한 시리즈의 일부입니다. 여기에서 다른 기사를 읽으십시오:

TEXTIO를 사용하여 테스트벤치에서 읽은 자극 파일

TEXTIO를 사용하여 읽은 BMP 파일 비트맵 이미지

READLINE, LINE, HREAD, OREAD 및 BREAD

VHDL에서 외부 파일을 읽고 쓰는 데 필요한 하위 프로그램 및 유형은 TEXTIO에 있습니다. 패키지. 이 패키지는 std의 일부입니다. 도서관. 표준 라이브러리는 항상 로드됩니다. 따라서 library를 사용하여 명시적으로 가져올 필요가 없습니다. 키워드.

TEXTIO를 사용하면 됩니다. 다음과 같이 VHDL 파일의 헤더에 패키지:

use std.textio.all;

한 줄의 텍스트가 메모리 슬롯에 해당하는 ASCII 파일에 RAM 데이터를 저장합니다. 한 줄의 텍스트를 읽으려면 READLINE를 사용합니다. TEXTIO의 절차 패키지. 이 절차는 상수 입력으로 파일 이름과 inout로 구문 분석된 텍스트 줄의 두 인수를 사용합니다. 변하기 쉬운. READLINE의 프로토타입 선언 절차 및 LINE VHDL 표준 사양에서 가져온 유형은 다음과 같습니다.

procedure READLINE (file F: TEXT; L: inout LINE);

type LINE is access STRING; -- A LINE is a pointer
                            -- to a STRING value.

LINE의 클래스이지만 매개변수가 READLINE의 프로토타입 선언에 명시적으로 지정되지 않았습니다. , inout의 기본 클래스이기 때문에 변수입니다. 매개변수. LINE type은 단순히 문자열에 대한 액세스 유형이며 동적으로 할당된 문자열 개체에 대한 포인터입니다.

VHDL-2008은 OREAD을 정의합니다. , HREADBREAD LINE에서 8진수, 16진수 및 2진수 값을 추출하는 절차 물체. 8진수 및 16진수 값을 읽는 방법은 매우 유사하며 8진수 값은 16진수의 하위 집합일 뿐입니다. 편의상 이 기사에서는 8진수 읽기를 건너뛰고 텍스트 파일에서 16진수 및 2진수 값을 읽는 방법에 중점을 둘 것입니다.

아래 코드는 우리와 관련된 절차의 정의를 보여주며, VHDL-2008 이상 버전에서만 사용할 수 있습니다. OREADHREAD 프로시저는 지원되는 각 출력 유형에 대해 두 가지 오버로드된 특징이 있습니다. 선택적 GOOD 출력은 읽기 오류를 감지하는 데 사용할 수 있지만 대부분의 도구는 이 출력의 사용 여부에 관계없이 오류 또는 경고를 생성합니다.

procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR;
                                 GOOD : out BOOLEAN);
procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);

procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR;
                                  GOOD : out BOOLEAN);
procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);

alias BREAD is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
alias BREAD is READ [LINE, STD_ULOGIC_VECTOR];
TEXTIO 라이브러리의 입력 절차 정의를 보려면 여기를 클릭하십시오.
procedure READLINE (file F: TEXT; L: inout LINE);

procedure READ (L: inout LINE; VALUE: out BIT;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out BIT);

procedure READ (L: inout LINE; VALUE: out BIT_VECTOR;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out BIT_VECTOR);

procedure READ (L: inout LINE; VALUE: out BOOLEAN;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out BOOLEAN);

procedure READ (L: inout LINE; VALUE: out CHARACTER;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out CHARACTER);

procedure READ (L: inout LINE; VALUE: out INTEGER;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out INTEGER);

procedure READ (L: inout LINE; VALUE: out REAL;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out REAL);

procedure READ (L: inout LINE; VALUE: out STRING;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out STRING);

procedure READ (L: inout LINE; VALUE: out TIME;
                               GOOD: out BOOLEAN);
procedure READ (L: inout LINE; VALUE: out TIME);

procedure SREAD (L: inout LINE; VALUE: out STRING;
                                STRLEN: out NATURAL);
alias STRING_READ is SREAD [LINE, STRING, NATURAL];

alias BREAD is READ [LINE, BIT_VECTOR, BOOLEAN];
alias BREAD is READ [LINE, BIT_VECTOR];
alias BINARY_READ is READ [LINE, BIT_VECTOR, BOOLEAN];
alias BINARY_READ is READ [LINE, BIT_VECTOR];

procedure OREAD (L: inout LINE; VALUE: out BIT_VECTOR;
                                GOOD: out BOOLEAN);
procedure OREAD (L: inout LINE; VALUE: out BIT_VECTOR);
alias OCTAL_READ is OREAD [LINE, BIT_VECTOR, BOOLEAN];
alias OCTAL_READ is OREAD [LINE, BIT_VECTOR];

procedure HREAD (L: inout LINE; VALUE: out BIT_VECTOR;
                                GOOD: out BOOLEAN);
procedure HREAD (L: inout LINE; VALUE: out BIT_VECTOR);
alias HEX_READ is HREAD [LINE, BIT_VECTOR, BOOLEAN];
alias HEX_READ is HREAD [LINE, BIT_VECTOR];
std_logic_1164 라이브러리
procedure READ (L : inout LINE; VALUE : out STD_ULOGIC; GOOD : out BOOLEAN);
procedure READ (L : inout LINE; VALUE : out STD_ULOGIC);

procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN);
procedure READ (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);

alias BREAD is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
alias BREAD is READ [LINE, STD_ULOGIC_VECTOR];
alias BINARY_READ is READ [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
alias BINARY_READ is READ [LINE, STD_ULOGIC_VECTOR];

procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN);
procedure OREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);
alias OCTAL_READ is OREAD [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
alias OCTAL_READ is OREAD [LINE, STD_ULOGIC_VECTOR];

procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR; GOOD : out BOOLEAN);
procedure HREAD (L : inout LINE; VALUE : out STD_ULOGIC_VECTOR);
alias HEX_READ is HREAD [LINE, STD_ULOGIC_VECTOR, BOOLEAN];
alias HEX_READ is HREAD [LINE, STD_ULOGIC_VECTOR];
의 입력 프로시저 정의를 보려면 여기를 클릭하십시오.

파일에서 16진수 값 읽기

16진수는 2개의 16진수 문자가 1바이트, 8비트로 직접 변환되기 때문에 RAM 내용을 설명하는 데 편리한 형식입니다. 모든 문자는 니블(1/2바이트)을 설명하고 텍스트 파일의 각 행은 하나의 RAM 슬롯의 내용을 설명합니다. 아래 목록은 ram_content_hex.txt에서 발췌한 내용을 보여줍니다. 파일. 16진수로 1부터 256까지의 예시 값으로 채워져 있습니다.

12–255256 00000001 00000002 ... 000000FF 00000100

텍스트 파일에서 데이터를 로드하기 위해 ram_type 아래에 선언된 불순한 함수를 사용합니다. , 그러나 RAM 신호 선언 위에 있습니다. 아래 코드는 init_ram_hex를 보여줍니다. 텍스트 파일에서 데이터를 읽고 ram_type로 반환하는 함수 개체.

impure function init_ram_hex return ram_type is
  file text_file : text open read_mode is "ram_content_hex.txt";
  variable text_line : line;
  variable ram_content : ram_type;
begin
  for i in 0 to ram_depth - 1 loop
    readline(text_file, text_line);
    hread(text_line, ram_content(i));
  end loop;

  return ram_content;
end function;

readline for 루프 내부의 프로시저는 한 번에 한 줄의 텍스트를 읽고 text_line에 할당합니다. 변하기 쉬운. 이 개체는 line 유형입니다. , 동적으로 할당된 문자열에 대한 포인터인 문자열 개체에 대한 액세스 유형입니다. 다음 줄에서 hread 프로시저는 line에서 문자열을 읽습니다. 개체를 만들고 std_ulogic_vector로 변환합니다. . 이 유형은 std_logic_vector에 직접 할당할 수 있습니다. 각 RAM 셀이 구성되어 있습니다.

마지막으로 init_ram_hex을 호출하는 동안 RAM 신호를 선언합니다. 초기 값을 제공하는 함수:

signal ram_hex : ram_type := init_ram_hex;

VHDL-2002 및 VHDL-93의 HREAD

안타깝게도 HREAD 절차는 VHDL-2008에서만 사용할 수 있습니다. VHDL의 모든 이전 버전에서 표준 READ 대신 절차를 사용해야 합니다. READ 프로시저가 다양한 출력 유형으로 오버로드되지만 16진수 값을 읽는 옵션이 없습니다.

16진수 ASCII 문자를 VHDL std_logic_vector로 변환하는 사용자 지정 알고리즘을 작성해 보겠습니다. . 먼저 text_line에서 문자를 하나씩 읽어야 합니다. 그런 다음 해당 값을 디코딩하고 RAM 슬롯 벡터의 올바른 슬라이스에 할당합니다. 아래 코드는 init_ram_hex의 동등한 구현을 보여줍니다. 레거시 VHDL 버전에서도 작동하는 기능입니다.

impure function init_ram_hex return ram_type is
  file text_file : text open read_mode is "ram_content_hex.txt";
  variable text_line : line;
  variable ram_content : ram_type;
  variable c : character;
  variable offset : integer;
  variable hex_val : std_logic_vector(3 downto 0);
begin
  for i in 0 to ram_depth - 1 loop
    readline(text_file, text_line);

    offset := 0;

    while offset < ram_content(i)'high loop
      read(text_line, c);

      case c is
        when '0' => hex_val := "0000";
        when '1' => hex_val := "0001";
        when '2' => hex_val := "0010";
        when '3' => hex_val := "0011";
        when '4' => hex_val := "0100";
        when '5' => hex_val := "0101";
        when '6' => hex_val := "0110";
        when '7' => hex_val := "0111";
        when '8' => hex_val := "1000";
        when '9' => hex_val := "1001";
        when 'A' | 'a' => hex_val := "1010";
        when 'B' | 'b' => hex_val := "1011";
        when 'C' | 'c' => hex_val := "1100";
        when 'D' | 'd' => hex_val := "1101";
        when 'E' | 'e' => hex_val := "1110";
        when 'F' | 'f' => hex_val := "1111";

        when others =>
          hex_val := "XXXX";
          assert false report "Found non-hex character '" & c & "'";
      end case;

      ram_content(i)(ram_content(i)'high - offset
        downto ram_content(i)'high - offset - 3) := hex_val;
      offset := offset + 4;

    end loop;
  end loop;

  return ram_content;
end function;

알고리즘은 모든 문자를 확인하면서 모든 라인을 통과하여 올바른 이진 값으로 변환합니다. 0x0-0xF 범위에 없는 문자가 발생하면 when others에서 어설션 실패가 발생합니다. 나뭇가지. offset 변수는 디코딩된 값을 할당할 각 메모리 셀 내의 슬라이스 위치를 제어합니다.

맞춤 hread init_ram_hex 안에 코딩하는 대신 절차 기능? 그러면 init_ram_hex을 변경할 필요가 없습니다. 기능이 전혀 없으면 사용자 정의 hread를 사용하기만 하면 됩니다. 누락된 표준 대신 절차.

그것은 대부분의 시뮬레이터와 Lattice iCEcube2와 같은 일부 신디사이저에서 작동하지만 Xilinx Vivado에서는 합성되지 않습니다. 아래 오류 메시지는 문제가 무엇인지 명확하게 설명합니다.

비바도에서:
[Synth 8-27] 'line' 유형의 프로시저 인수는 지원되지 않습니다 [init_ram_tb.vhd:15]

HREAD 프로시저의 대체 구현을 보려면 여기를 클릭하십시오.
procedure hread(l: inout line; value: out std_logic_vector) is
  variable c : character;
  variable ok : boolean;
  variable i : integer := 0;
  variable hex_val : std_logic_vector(3 downto 0);
begin
  while i < value'high loop
    read(l, c);
  
    case c is
      when '0' => hex_val := "0000";
      when '1' => hex_val := "0001";
      when '2' => hex_val := "0010";
      when '3' => hex_val := "0011";
      when '4' => hex_val := "0100";
      when '5' => hex_val := "0101";
      when '6' => hex_val := "0110";
      when '7' => hex_val := "0111";
      when '8' => hex_val := "1000";
      when '9' => hex_val := "1001";
      when 'A' | 'a' => hex_val := "1010";
      when 'B' | 'b' => hex_val := "1011";
      when 'C' | 'c' => hex_val := "1100";
      when 'D' | 'd' => hex_val := "1101";
      when 'E' | 'e' => hex_val := "1110";
      when 'F' | 'f' => hex_val := "1111";
  
      when others =>
        hex_val := "XXXX";
        assert false report "Found non-hex character '" & c & "'";
    end case;
  
    value(value'high - i downto value'high - i - 3) := hex_val;
    i := i + 4;
  end loop;
end procedure;

파일에서 바이너리 값 읽기

RAM 너비가 8의 배수가 아닌 경우 RAM 값을 16진수 문자 대신 이진 리터럴로 저장할 수 있습니다. 아래 목록은 이전과 동일한 내용을 표시하지만 문자 01 .

12–255256 00000000000000000000000000000001 00000000000000000000000000000010 ... 00000000000000000000000011111111 00000000000000000000000100000000

아래에 표시된 알고리즘은 파일에서 이진 값을 읽기 위한 것입니다. 16진수를 읽는 것과 비슷하지만 VHDL-2008에서는 BREAD를 사용해야 합니다. HREAD 대신 프로시저 호출 . 하나의 ASCII 문자를 단일 std_ulogic로 변환합니다. 암시적으로 std_logic로 변환되는 값 .

impure function init_ram_bin return ram_type is
  file text_file : text open read_mode is "ram_content_bin.txt";
  variable text_line : line;
  variable ram_content : ram_type;
begin
  for i in 0 to ram_depth - 1 loop
    readline(text_file, text_line);
    bread(text_line, ram_content(i));
  end loop;

  return ram_content;
end function;

마지막으로 아래 코드와 같이 새로운 불순 함수를 호출하여 RAM 신호를 초기화합니다.

signal ram_bin : ram_type := init_ram_bin;

VHDL-2002 및 VHDL-93의 빵

READ을 호출하여 코드를 레거시 VHDL 버전으로 쉽게 이식할 수 있습니다. BREAD 대신 . 아래 VHDL 표준에서 발췌한 내용은 READ의 프로토타입을 보여줍니다. 사용에 관심이 있습니다.

procedure READ (L: inout LINE; VALUE: out BIT);

READ std_ulogic를 출력하는 절차 VHDL-2008 이전에는 존재하지 않았으므로 bit을 사용해야 합니다. TEXTIO 버전 도서관. 다행히 이 유형은 std_logic로 쉽게 변환할 수 있습니다. 표준 To_StdLogicVector 사용 기능.

init_ram_bin 구현 아래 그림은 VHDL-2002 및 VHDL-93에서 작동합니다.

impure function init_ram_bin return ram_type is
  file text_file : text open read_mode is "ram_content_bin.txt";
  variable text_line : line;
  variable ram_content : ram_type;
  variable bv : bit_vector(ram_content(0)'range);
begin
  for i in 0 to ram_depth - 1 loop
    readline(text_file, text_line);
    read(text_line, bv);
    ram_content(i) := To_StdLogicVector(bv);
  end loop;

  return ram_content;
end function;

IEEE std_logic_1164 라이브러리의 백포트

레거시 VHDL 버전에 대한 코드를 변경하는 대안은 std_logic_1164_additions 타사 패키지를 사용하는 것입니다. 이 라이브러리를 다운로드하여 프로젝트에 추가하면 VHDL-2002 및 VHDL-93에서도 새 절차를 사용할 수 있습니다. 물론 더 많은 것을 가져올 것이고 코드는 항상 이 패키지에 의존하게 될 것입니다.


VHDL

  1. 부식으로부터 알루미늄을 보호하는 방법
  2. 금속 원소와 비금속 원소의 차이점
  3. AWS를 사용하여 CloudFormation 템플릿을 만드는 방법
  4. 클라우드 컴퓨팅은 기존 컴퓨팅과 어떻게 다른가요?
  5. C 프로그래밍에서 주석을 작성하는 방법
  6. Java BufferedReader:예제를 사용하여 Java에서 파일을 읽는 방법
  7. Python Average:Python에서 목록의 AVERAGE를 찾는 방법
  8. 마이크로미터란? | 마이크로미터를 읽는 방법
  9. 정보 모델을 사용하여 OPC UA 클라이언트에서 기능 블록을 호출하는 방법
  10. CNC 청사진을 읽는 방법