VHDL
블록 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 파일 비트맵 이미지
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
을 정의합니다. , HREAD
및 BREAD
LINE
에서 8진수, 16진수 및 2진수 값을 추출하는 절차 물체. 8진수 및 16진수 값을 읽는 방법은 매우 유사하며 8진수 값은 16진수의 하위 집합일 뿐입니다. 편의상 이 기사에서는 8진수 읽기를 건너뛰고 텍스트 파일에서 16진수 및 2진수 값을 읽는 방법에 중점을 둘 것입니다.
아래 코드는 우리와 관련된 절차의 정의를 보여주며, VHDL-2008 이상 버전에서만 사용할 수 있습니다. OREAD
및 HREAD
프로시저는 지원되는 각 출력 유형에 대해 두 가지 오버로드된 특징이 있습니다. 선택적 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진수는 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;
안타깝게도 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]
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진수 문자 대신 이진 리터럴로 저장할 수 있습니다. 아래 목록은 이전과 동일한 내용을 표시하지만 문자 0
및 1
.
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;
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;
레거시 VHDL 버전에 대한 코드를 변경하는 대안은 std_logic_1164_additions 타사 패키지를 사용하는 것입니다. 이 라이브러리를 다운로드하여 프로젝트에 추가하면 VHDL-2002 및 VHDL-93에서도 새 절차를 사용할 수 있습니다. 물론 더 많은 것을 가져올 것이고 코드는 항상 이 패키지에 의존하게 될 것입니다.
VHDL
모든 훌륭한 제품은 아이디어에서 시작됩니다. 연구원, 엔지니어 및 제조업체는 모두 해당 아이디어를 사용하는 사람들의 삶을 개선하는 실행 가능한 제품으로 변환하는 데 한 역할을 합니다. 디자인에서 제작, 제품 출시까지의 단계를 통해 제품을 이동하는 것은 많은 요소가 관련된 복잡한 프로세스입니다. 각 아이디어는 성공적인 신제품의 궁극적인 대량 생산으로 이어지는 점진적인 단계를 거칩니다. 1. 프로토타입 디자인 제조 공정의 첫 번째 단계는 실용적인 디자인을 찾는 것입니다. 일반적으로 해당 분야와 신제품으로 해결하고자 하는 문제에 대한
마스크 COVID-19의 확산에 대한 첫 번째 방어선, 감염원의 흡입 및 전염을 방지하기 위해 설계된 간단한 장치는 전 세계 수십억 명의 삶에 영향을 미쳤습니다. 전 세계적인 유행병이 시작된 이래 안면 마스크의 사용은 필수였고 많은 경우에 의무였지만, 그들이 한 모든 좋은 일에도 불구하고 마스크의 제거는 더 즉각적인 조치를 위해 대체로 무시되어 온 기념비적인 생태학적 도전을 나타냅니다. 우려 사항 . 매달 전 세계적으로 약 1,290억 개의 호흡보호구가 사용된 것으로 추정되며, 대부분은 일회용으로 설계되었습니다. 마스크가 분해되