Testbench: Debuggen per Konsole

Assert Statment
Führen einen Vergleich aus. Stimmt der Vergleich, so passiert nichts. Nur wenn der Vergleich falsch ist, dann wird der Report ausgegeben.

ASSERT (s_midi = "010110") REPORT "Midi-value wrong" SEVERITY NOTE;

Es gibt vier Levels von severity reports: NOTE, WARNING, ERROR, FAILURE.
Das letzte Level (failure) bricht die Simulation ab.

Ist das Testing textbasiert, so steht oft auf der rechten Seite der eingelesene Wert, den das Signal haben soll (aus Textfile):

ASSERT (s_midi = note_1) REPORT "Note 1 falsch" SEVERITY WARNING;

 

Asserts als Passed-Points
Will man nur wissen, ob die Simulation an einer gewissen Stelle durchgekommen ist, wird Assert false  (= immer ausgeben) für die Kommandoausgabe gebraucht.

ASSERT false REPORT "Read in finished" SEVERITY NOTE;

Textbasierte Testbench  Passed-Point
Falls die textio-Bibliothek eingebunden und  variable line_out: Line; definiert wurde, kann man mit der Funktion write()  Text auf die Konsole schreiben.

write(line_out, string'("Read in finished."));
writeline(OUTPUT, line_out);

Der Text muss (leider) zuerst in den Zeilenbuffer Line gespeichert werden, und dann per OUTPUT  der Konsole übergeben. Die Definition dieser Varialblen steht in der Datei std_logic_textio.vhd.

std_logic_textio.vhd

Die Vollversion:

use STD.textio.all;
library IEEE;
use IEEE.std_logic_1164.all;

package STD_LOGIC_TEXTIO is
--synopsys synthesis_off
	-- Read and Write procedures for STD_ULOGIC and STD_ULOGIC_VECTOR
	procedure READ(L:inout LINE; VALUE:out STD_ULOGIC);
	procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD: out BOOLEAN);
	procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR);
	procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN);
	procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0);
	procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0);

	-- Read and Write procedures for STD_LOGIC_VECTOR
	procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR);
	procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN);
	procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0);

	--
	-- Read and Write procedures for Hex and Octal values.
	-- The values appear in the file as a series of characters
	-- between 0-F (Hex), or 0-7 (Octal) respectively.
	--

	-- Hex
	procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR);
	procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN);
	procedure HWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0);
	procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR);
	procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN);
	procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0);

	-- Octal
	procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR);
	procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN);
	procedure OWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0);
	procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR);
	procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN);
	procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0);

	
--synopsys synthesis_on
end STD_LOGIC_TEXTIO;

package body STD_LOGIC_TEXTIO is
--synopsys synthesis_off

	-- Type and constant definitions used to map STD_ULOGIC values 
	-- into/from character values.

	type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', ERROR);
	type char_indexed_by_MVL9 is array (STD_ULOGIC) of character;
	type MVL9_indexed_by_char is array (character) of STD_ULOGIC;
	type MVL9plus_indexed_by_char is array (character) of MVL9plus;

	constant MVL9_to_char: char_indexed_by_MVL9 := "UX01ZWLH-";
	constant char_to_MVL9: MVL9_indexed_by_char := 
		('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
		 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U');
	constant char_to_MVL9plus: MVL9plus_indexed_by_char := 
		('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z',
		 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => ERROR);


	-- Overloaded procedures.

	procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD:out BOOLEAN) is
		variable c: character;
		variable readOk: BOOLEAN;
	begin
		loop					-- skip white space
			read(l,c,readOk);		-- but also exit on a bad read
			exit when ((readOk = FALSE) or ((c /= ' ') and (c /= CR) and (c /= HT)));
		end loop;

		if (readOk = FALSE) then
			good := FALSE;
		else
		    if (char_to_MVL9plus(c) = ERROR) then
			value := 'U';
			good := FALSE;
		     else
			value := char_to_MVL9(c);
			good := TRUE;
		    end if;
		end if;
	end READ;

	procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD:out BOOLEAN) is
		variable m:  STD_ULOGIC;
		variable c:  character;
		variable s:  string(1 to value'length-1);
		variable mv: STD_ULOGIC_VECTOR(0 to value'length-1);
		constant allU: STD_ULOGIC_VECTOR(0 to value'length-1)
		 				:= (others => 'U');
                variable readOk: BOOLEAN;

	begin
		loop					-- skip white space
			read(l,c,readOk);
			exit when ((readOk = FALSE) or ((c /= ' ') and (c /= CR) and (c /= HT)));
		end loop;
 
-- Bail out if there was a bad read
                if (readOk = FALSE) then
                        good := FALSE;
			return;
                end if;

		if (char_to_MVL9plus(c) = ERROR) then
			value := allU;
			good := FALSE;
			return;
		end if;

		read(l, s, readOk);
-- Bail out if there was a bad read
                if (readOk = FALSE) then
                        good := FALSE;
                        return;
                end if;

	    	for i in 1 to value'length-1 loop
			if (char_to_MVL9plus(s(i)) = ERROR) then
				value := allU;
				good := FALSE;
			    	return;
			end if;
		end loop;

		mv(0) := char_to_MVL9(c);
	    	for i in 1 to value'length-1 loop
			mv(i) := char_to_MVL9(s(i));
	    	end loop;
		value := mv;
		good := TRUE;
	end READ;
	
	procedure READ(L:inout LINE; VALUE:out STD_ULOGIC) is
		variable c: character;
	begin
		loop					-- skip white space
			read(l,c);
			exit when ((c /= ' ') and (c /= CR) and (c /= HT));
		end loop;

		if (char_to_MVL9plus(c) = ERROR) then
			value := 'U';
			assert FALSE report "READ(STD_ULOGIC) Error: Character '" &
					c & "' read, expected STD_ULOGIC literal.";
		else
			value := char_to_MVL9(c);
		end if;
	end READ;

	procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is
		variable m: STD_ULOGIC;
		variable c: character;
		variable s: string(1 to value'length-1);
		variable mv: STD_ULOGIC_VECTOR(0 to value'length-1);
		constant allU: STD_ULOGIC_VECTOR(0 to value'length-1)
				 := (others => 'U');
	begin
		loop					 -- skip white space
			read(l,c);
			exit when ((c /= ' ') and (c /= CR) and (c /= HT));
		end loop;

		if (char_to_MVL9plus(c) = ERROR) then
			value := allU;
			assert FALSE report
				"READ(STD_ULOGIC_VECTOR) Error: Character '" & 
					c & "' read, expected STD_ULOGIC literal.";
			return;
		end if;

		read(l, s);
	    	for i in 1 to value'length-1 loop
			if (char_to_MVL9plus(s(i)) = ERROR) then
			    value := allU;
			    assert FALSE report 
				"READ(STD_ULOGIC_VECTOR) Error: Character '" &
					s(i) & "' read, expected STD_ULOGIC literal.";
			    return;
			end if;
		end loop;

		mv(0) := char_to_MVL9(c);
	    	for i in 1 to value'length-1 loop
			mv(i) := char_to_MVL9(s(i));
	    	end loop;
		value := mv;
	end READ;

	procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is
	begin
		write(l, MVL9_to_char(value), justified, field);
	end WRITE;
	

	procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is
		variable s: string(1 to value'length);
		variable m: STD_ULOGIC_VECTOR(1 to value'length) := value;
	begin
	    	for i in 1 to value'length loop
			s(i) := MVL9_to_char(m(i));
		end loop;
		write(l, s, justified, field);
	end WRITE;

	-- Read and Write procedures for STD_LOGIC_VECTOR
	procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is
		variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0);
	begin
		READ(L, tmp);
		VALUE := STD_LOGIC_VECTOR(tmp);
	end READ;

	procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is
		variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0);
	begin
		READ(L, tmp, GOOD);
		VALUE := STD_LOGIC_VECTOR(tmp);
	end READ;

	procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is
	begin
		WRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD);
	end WRITE;


	--
	-- Hex Read and Write procedures.
	--

	--
	-- Hex, and Octal Read and Write procedures for BIT_VECTOR
	--  (these procedures are not exported, they are only used
	--   by the STD_ULOGIC hex/octal reads and writes below.
	--
	--

	procedure Char2QuadBits(C: Character; 
				RESULT: out std_ulogic_vector(3 downto 0);
				GOOD: out Boolean;
				ISSUE_ERROR: in Boolean) is
	begin
		case c is
			when '0' => result :=  x"0"; good := TRUE;
			when '1' => result :=  x"1"; good := TRUE;
			when '2' => result :=  x"2"; good := TRUE;
			when '3' => result :=  x"3"; good := TRUE;
			when '4' => result :=  x"4"; good := TRUE;
			when '5' => result :=  x"5"; good := TRUE;
			when '6' => result :=  x"6"; good := TRUE;
			when '7' => result :=  x"7"; good := TRUE;
			when '8' => result :=  x"8"; good := TRUE;
			when '9' => result :=  x"9"; good := TRUE;
			when 'A' => result :=  x"A"; good := TRUE;
			when 'B' => result :=  x"B"; good := TRUE;
			when 'C' => result :=  x"C"; good := TRUE;
			when 'D' => result :=  x"D"; good := TRUE;
			when 'E' => result :=  x"E"; good := TRUE;
			when 'F' => result :=  x"F"; good := TRUE;
			when 'Z' => result(0) :=  'Z'; result(1) :=  'Z'; result(2) :=  'Z'; result(3) :=  'Z'; good := TRUE;
			when 'X' => result(0) :=  'X'; result(1) :=  'X'; result(2) :=  'X'; result(3) :=  'X'; good := TRUE;
 
			when 'a' => result :=  x"A"; good := TRUE;
			when 'b' => result :=  x"B"; good := TRUE;
			when 'c' => result :=  x"C"; good := TRUE;
			when 'd' => result :=  x"D"; good := TRUE;
			when 'e' => result :=  x"E"; good := TRUE;
			when 'f' => result :=  x"F"; good := TRUE;
			when others =>
			   if ISSUE_ERROR then 
				   assert FALSE report
					"HREAD Error: Read a '" & c &
					   "', expected a Hex character (0-F).";
			   end if;
			   good := FALSE;
		end case;
	end;

	procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR)  is
		variable ok: boolean;
		variable c:  character;
		constant ne: integer := value'length/4;
		variable bv: std_ulogic_vector(0 to value'length-1);
		variable s:  string(1 to ne-1);
	begin
		if value'length mod 4 /= 0 then
			assert FALSE report 
				"HREAD Error: Trying to read vector " &
				   "with an odd (non multiple of 4) length";
			return;
		end if;

		loop					-- skip white space
			read(l,c);
			exit when ((c /= ' ') and (c /= CR) and (c /= HT));
		end loop;

		Char2QuadBits(c, bv(0 to 3), ok, TRUE);
		if not ok then 
			return;
		end if;

		read(L, s, ok);
		if not ok then
			assert FALSE 
				report "HREAD Error: Failed to read the STRING";
			return;
		end if;

		for i in 1 to ne-1 loop
			Char2QuadBits(s(i), bv(4*i to 4*i+3), ok, TRUE);
			if not ok then
				return;
			end if;
		end loop;
		value := bv;
	end HREAD; 

	procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR;GOOD: out BOOLEAN) is
		variable ok: boolean;
		variable c:  character;
		constant ne: integer := value'length/4;
		variable bv: std_ulogic_vector(0 to value'length-1);
		variable s:  string(1 to ne-1);
	begin
		if value'length mod 4 /= 0 then
			good := FALSE;
			return;
		end if;

		loop					-- skip white space
			read(l,c);
			exit when ((c /= ' ') and (c /= CR) and (c /= HT));
		end loop;

		Char2QuadBits(c, bv(0 to 3), ok, FALSE);
		if not ok then 
			good := FALSE;
			return;
		end if;

		read(L, s, ok);
		if not ok then
			good := FALSE;
			return;
		end if;

		for i in 1 to ne-1 loop
			Char2QuadBits(s(i), bv(4*i to 4*i+3), ok, FALSE);
			if not ok then
				good := FALSE;
				return;
			end if;
		end loop;
		good := TRUE;
		value := bv;
	end HREAD; 

	procedure HWRITE(L:inout LINE; VALUE:in std_ulogic_vector;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is
		variable quad: std_ulogic_vector(0 to 3);
		constant ne:   integer := value'length/4;
		variable bv:   std_ulogic_vector(0 to value'length-1) := value;
		variable s:    string(1 to ne);
	begin
		if value'length mod 4 /= 0 then
			assert FALSE report 
				"HWRITE Error: Trying to read vector " &
				   "with an odd (non multiple of 4) length";
			return;
		end if;

		for i in 0 to ne-1 loop
			quad := To_X01Z(bv(4*i to 4*i+3));
			case quad is
				when x"0" => s(i+1) := '0';
				when x"1" => s(i+1) := '1';
				when x"2" => s(i+1) := '2';
				when x"3" => s(i+1) := '3';
				when x"4" => s(i+1) := '4';
				when x"5" => s(i+1) := '5';
				when x"6" => s(i+1) := '6';
				when x"7" => s(i+1) := '7';
				when x"8" => s(i+1) := '8';
				when x"9" => s(i+1) := '9';
				when x"A" => s(i+1) := 'A';
				when x"B" => s(i+1) := 'B';
				when x"C" => s(i+1) := 'C';
				when x"D" => s(i+1) := 'D';
				when x"E" => s(i+1) := 'E';
				when x"F" => s(i+1) := 'F';
				when others =>  
					if (quad = "ZZZZ") then
					   s(i+1) := 'Z';
					else
					   s(i+1) := 'X';
					end if;
			end case;
		end loop;
		write(L, s, JUSTIFIED, FIELD);
	end HWRITE; 

	procedure Char2TriBits(C: Character; 
				RESULT: out bit_vector(2 downto 0);
				GOOD: out Boolean;
				ISSUE_ERROR: in Boolean) is
	begin
		case c is
			when '0' => result :=  o"0"; good := TRUE;
			when '1' => result :=  o"1"; good := TRUE;
			when '2' => result :=  o"2"; good := TRUE;
			when '3' => result :=  o"3"; good := TRUE;
			when '4' => result :=  o"4"; good := TRUE;
			when '5' => result :=  o"5"; good := TRUE;
			when '6' => result :=  o"6"; good := TRUE;
			when '7' => result :=  o"7"; good := TRUE;
			when others =>
			   if ISSUE_ERROR then 
				   assert FALSE report
					"OREAD Error: Read a '" & c &
					"', expected an Octal character (0-7).";
			   end if;
			   good := FALSE;
		end case;
	end;

	procedure OREAD(L:inout LINE; VALUE:out BIT_VECTOR)  is
		variable c: character;
		variable ok: boolean;
		constant ne: integer := value'length/3;
		variable bv: bit_vector(0 to value'length-1);
		variable s: string(1 to ne-1);
	begin
		if value'length mod 3 /= 0 then
			assert FALSE report 
				"OREAD Error: Trying to read vector " &
				   "with an odd (non multiple of 3) length";
			return;
		end if;

		loop					-- skip white space
			read(l,c);
			exit when ((c /= ' ') and (c /= CR) and (c /= HT));
		end loop;

		Char2TriBits(c, bv(0 to 2), ok, TRUE);
		if not ok then 
			return;
		end if;

		read(L, s, ok);
		if not ok then
			assert FALSE 
				report "OREAD Error: Failed to read the STRING";
			return;
		end if;

		for i in 1 to ne-1 loop
			Char2TriBits(s(i), bv(3*i to 3*i+2), ok, TRUE);
			if not ok then
				return;
			end if;
		end loop;
		value := bv;
	end OREAD; 

	procedure OREAD(L:inout LINE; VALUE:out BIT_VECTOR;GOOD: out BOOLEAN) is
		variable ok: boolean;
		variable c:  character;
		constant ne: integer := value'length/3;
		variable bv: bit_vector(0 to value'length-1);
		variable s:  string(1 to ne-1);
	begin
		if value'length mod 3 /= 0 then
			good := FALSE;
			return;
		end if;

		loop					-- skip white space
			read(l,c);
			exit when ((c /= ' ') and (c /= CR) and (c /= HT));
		end loop;

		Char2TriBits(c, bv(0 to 2), ok, FALSE);
		if not ok then 
			good := FALSE;
			return;
		end if;

		read(L, s, ok);
		if not ok then
			good := FALSE;
			return;
		end if;

		for i in 1 to ne-1 loop
			Char2TriBits(s(i), bv(3*i to 3*i+2), ok, FALSE);
			if not ok then
				good := FALSE;
				return;
			end if;
		end loop;
		good := TRUE;
		value := bv;
	end OREAD; 


	procedure OWRITE(L:inout LINE; VALUE:in std_ulogic_vector;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is
		variable tri: std_ulogic_vector(0 to 2);
		constant ne:  integer := value'length/3;
		variable bv:  std_ulogic_vector(0 to value'length-1) := value;
		variable s:   string(1 to ne);
	begin
		if value'length mod 3 /= 0 then
			assert FALSE report 
				"OWRITE Error: Trying to read vector " &
				   "with an odd (non multiple of 3) length";
			return;
		end if;

		for i in 0 to ne-1 loop
			tri := To_X01Z(bv(3*i to 3*i+2));
			case tri is
				when o"0" => s(i+1) := '0';
				when o"1" => s(i+1) := '1';
				when o"2" => s(i+1) := '2';
				when o"3" => s(i+1) := '3';
				when o"4" => s(i+1) := '4';
				when o"5" => s(i+1) := '5';
				when o"6" => s(i+1) := '6';
				when o"7" => s(i+1) := '7';
				when others =>  
					if (tri = "ZZZ") then
					   s(i+1) := 'Z';
					else
					   s(i+1) := 'X';
					end if;
			end case;
		end loop;
		write(L, s, JUSTIFIED, FIELD);
	end OWRITE; 

	-- Hex Read and Write procedures for STD_LOGIC_VECTOR
	procedure HREAD(L:inout LINE; VALUE:out BIT_VECTOR;GOOD:out BOOLEAN) is
		variable tmp: std_ulogic_vector(VALUE'length-1 downto 0);
	begin
		HREAD(L, tmp, GOOD);
		VALUE := To_BitVector(tmp);
	end HREAD;
	
	procedure HREAD(L:inout LINE; VALUE:out BIT_VECTOR) is
		variable tmp: std_ulogic_vector(VALUE'length-1 downto 0);
	begin
		HREAD(L, tmp);
		VALUE := To_BitVector(tmp);
	end HREAD;

	-- Hex Read and Write procedures for STD_LOGIC_VECTOR

	procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is
		variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0);
	begin
		HREAD(L, tmp);
		VALUE := STD_LOGIC_VECTOR(tmp);
	end HREAD;

	procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is
		variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0);
	begin
		HREAD(L, tmp, GOOD);
		VALUE := STD_LOGIC_VECTOR(tmp);
	end HREAD;

	procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is
	begin
		HWRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD);
	end HWRITE;


	-- Octal Read and Write procedures for STD_ULOGIC_VECTOR
	procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR;GOOD:out BOOLEAN) is
		variable tmp: bit_vector(VALUE'length-1 downto 0);
	begin
		OREAD(L, tmp, GOOD);
		VALUE := To_X01(tmp);
	end OREAD;
	
	procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is
		variable tmp: bit_vector(VALUE'length-1 downto 0);
	begin
		OREAD(L, tmp);
		VALUE := To_X01(tmp);
	end OREAD;

	-- Octal Read and Write procedures for STD_LOGIC_VECTOR

	procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is
		variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0);
	begin
		OREAD(L, tmp);
		VALUE := STD_LOGIC_VECTOR(tmp);
	end OREAD;

	procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is
		variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0);
	begin
		OREAD(L, tmp, GOOD);
		VALUE := STD_LOGIC_VECTOR(tmp);
	end OREAD;

	procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR;
			JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is
	begin
		OWRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD);
	end OWRITE;


--synopsys synthesis_on
end STD_LOGIC_TEXTIO;

Sie muss mit vcim 2002 kompiliert werden.

VHDL: natural, unsigned, integer

Operiert man mit Indexes, Adressen, etc. so ist dies am einfachsten mit dez. Zahlen:12 + 100 = 112;
Das selbe gilt auch für die Zähler.
VHDL hat dafür 3 Types: integer, unsigned, natural .

 

  1. Integer
signal addr:        integer range 0 to 15;
addr <= to_integer(value_a);

Adresse kann Werte von  0, 1, 2, … 15 annehmen.

cnt: integer range 0 to 3;

Der Zähler zählt 0, 1, 2, 3 und beginnt wieder bei 0.
.

2. Unsigned

-- 5 Werte
signal count:       unsigned(4 downto 0); 
signal value_a:     unsigned(15 downto 0);
signal  value_b:     unsigned(15 downto 0);

Der Zähler kann die Werte 4, 3, 2, 1, und 0 annahmen. Er besitzt 5 Zustände.

value_b <= to_unsigned(max_value,  4); ????? not shure

.

3. Natural

CONSTANT    max_value:        natural := 200;
signal      s_reg_index:      natural;
signal      s_next_reg_indes: natural;
s_next_reg_index := s_reg_index + 1;

Zuweisung braucht ein : vor dem =   line_cnt := line_cnt + 1;     reset := 1;

VHDL: AND, &, +

Was ist der Unterschied dieser Zeichen?

&: vektor zusammensetzen

s_midi <= s_tone_on & s_note_value & s_velocity;

– geht nur für std_logic;
.

AND: logisch zusammenzählen
Das AND folgt der Logik des Gatters AND:
Nur zwei ‚1‘ geben eine ‚1‘, alles andere gibt eine ‚0‘;

s_result = s_enable and s_bit_input;

– geht nur für std_logic;
– ist üblich für Signal-Logik und Takt-Logik

if (strobe_i = '1' and clk_intern = '0') then
.      // do

.
+: normal zählen

– geht nur für unsigned, integer, natural

signal index:  integer range 0 to 15  := 0;
signal offset: integer range 0 to 255 := 100;

index  <=  to_integer(s_midi(7 downto 4));
new_index = index + 4;

addr <= index + offset;

– ist bei Zählern üblich

next_cnt <= cnt + 1;

..

Signale zusammensetzen

In VHDL ist es üblich, vor dem Senden von Daten mehrere Informationen (Signale) in einen grossen Vektor zusammenzubauen.
Beim Empfangen wird dann der grosse Vektor wieder in seine Einzelteile zerlegt.

1. Einzelne Signalgrössen

signal s_tone_on:  std_logic;
signal s_note_value: std_logic_vector(7 downto 0);
signal s_velocity: std_logic_vector(7 downto 0);

signal s_midi: std_logic_vector(16 dowonto 0);


2. Addition  zu Vektor

// Vektor für innerhalb Entity bilden

s_midi <= s_tone_on & s_note_value & s_velocity;

// oder direkt beim Port

GPIO_0 <= s_tone_on & s_note_value & s_velocity;

Man kann auch nur Teile des Vektors addieren.

VHDL Bits aus Vektor extrahieren

Oft ist ein Vektor aus mehreren Informationen zusammengesetzt (vgl midi_in).

entity a is
port( midi_in: in std_logic_vector(16 downto 0);
      data:    out std_logic_vector(7 downto 0)
    );

Braucht man nun nur einen Bit-Abschnitt so geschieht dies so:

1. Signal von der gewünschten Bit-Breite definieren

signal s_tone_on:  std_logic;
signal s_note_value: std_logic_vector(7 downto 0);
signal s_velocity: std_logic_vector(7 downto 0);

2. Vektor bitweise zuweisten

s_tone_on <= midi_in(16);
s_note_value <= midi_in(15 downto 8);
s_velocity <= midi_in(7 downto 0);

….

VHDL speicher, buffer, register

Inputdaten müssen teilweise abgelegt werden. Wie wird dies in VHDL umgesetzt?

  • man kann per IP RAM anschliessen und dort per Adresse die Daten hineinschreiben.
  • Das VHDL-eigene Speicherprinzip sind jedoch die Flip- Flops. Alle Daten die gespeichert werden sollen, werden in (Vektoren) von Flip-Flops abgelegtff_speicher
    Signale führen Wert in und aus dem Flip-Flop

    -- input
    signal s_next_value: std_logic_vector(7 downto 0);
    -- gespeichert
    signal s_current_value: std_logic_vector(7downto0);
-- input in ff-signal ablegen
s_next_value <= input;

-- input speichern
input_register: process (all)
begin
.    if (reset = '1') then
.        s_current_value <= (others => '0');
.    elsif (clk'event) and (clk = '1') then
.        -- ausgang ff  erhält  eingang ff
.        s_current_value <= s_next_value; 
.  end if; 
end process;

 

speicher_mit_enable

Normalerweise wird das Inputsignal nicht asynchron an den Eingang des Flip-Flops gelegt. Oft entscheidet ein enable_signal, wann die Daten vor den Eingang gelegt werden sollen. (Dies geschieht mit einem Multiplexer.)

-- input speichern
input_register: process (all)
begin
.    if (reset = '1') then
.        s_current_value <= (others => '0');
.    elsif (clk'event) and (clk = '1') then
.        -- ausgang ff  erhält  eingang ff
.        s_current_value <= s_next_value; 

.        if (s_enable = '1') then
           s_next_value <= input;
        else
           s_nex_value <= s_current_value;
        end if;
.  end if; 
end process;

Git detached HEAD

Ein alter commit wurde heruntergeladen. Nun ist der Head losgelöst.

temporären Branch erstellen

git checkout -b develop2

Dadurch wird der losgelöste HEAD an den neuen Branch gebunden!
Als Überblick ev.  git diff master develop2 .

Branch Master zufügen
Danach normal weitergehen (mit diesem Branch),
oder den Branch zum Mater oder anderen Branch einbinden.

git branch -f master develop2
git checkout master
git branch -d develop2

Pointer C++: Wert auslesen

struct ImageInt16 {
.        short data[100]
};


Objekt bilden
2 Bilder werden abgelegt. Inhaltstruktur ist identisch. Der Typ der Speichervariable nicht.

ImageInt16     bild_1;          // enthält Wert
ImageInt16*    bild_2;          // enthält Speicherort, an dem Wert liegt


Variable auslesen

int result_1, result_2;

result_1 = bild_1.data[0];    
result_2 = bild_2->data[1];       // Objektreferenz
  //oder
result_2 = (*bild_2).data[1];    // Dereferenziert
.                                // Wert des Objekts

Der ersten zwei Wert aus dem Array wurden übergeben.
..