Implémenter un BuildCounter en VHDL
Posté le 16 septembre 2021 dans Hardware
Je vous propose deux codes pour en gérer un automatiquement.
Le premier, que j'utilise depuis des années, est en VHDL. Le deuxième, que j'ai écrit récemment, est en VHDL-2008.
Voici le premier code, en VHDL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std.all; use std.textio.all; use IEEE.STD_LOGIC_TEXTIO.all; entity BuildCounter is Generic ( BUILD_COUNTER_SIZE : positive := 16 ); Port ( BuildCounter : out std_logic_vector(BUILD_COUNTER_SIZE-1 downto 0) ); end BuildCounter; architecture Behavioral of BuildCounter is constant FILE_NAME : string := "../../Sources/BuildCounter.txt"; -- Path relative to working directory impure function BuildCounterFromFile (BCFileName : in string) return std_logic_vector is FILE BCFile : text is in BCFileName; variable BCFileLine : line; variable BCounter : STD_LOGIC_VECTOR(BUILD_COUNTER_SIZE-1 downto 0); begin readline (BCFile, BCFileLine); read (BCFileLine, BCounter); report "File name : " & BCFileName; report "Build counter value : " & integer'Image(to_integer(unsigned(BCounter))); return BCounter; end function; constant BC : STD_LOGIC_VECTOR (BUILD_COUNTER_SIZE-1 downto 0) := BuildCounterFromFile(FILE_NAME); file BCFile : text; begin process variable file_status : file_open_status; variable BCFileLine : line; variable run : natural := 0; begin file_open(file_status, BCFile, FILE_NAME, write_mode); write(BCFileLine, std_logic_vector(unsigned(BC)+1)); writeline(BCFile, BCFileLine); file_close(BCFile); wait until run=1; end process; BuildCounter <= BC; end Behavioral; |
Voici maintenant la version VHDL-2008.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | library IEEE; use IEEE.STD_LOGIC_1164.ALL; use ieee.numeric_std.all; use std.textio.all; use IEEE.STD_LOGIC_TEXTIO.all; entity BuildCounter is Port ( Build_Counter : out std_logic_vector ); end BuildCounter; architecture Behavioral of BuildCounter is constant FILE_NAME : string := "../../Sources/BuildCounter.txt"; -- Path relative to working directory pure function str_to_natural (Str : in String) return Natural is variable Val : Natural := 0; variable FirstCharFound : Boolean := False; begin for i in Str'Range loop case Str(i) is when '0' => Val := Val * 10; Val := Val + 0; FirstCharFound := True; when '1' => Val := Val * 10; Val := Val + 1; FirstCharFound := True; when '2' => Val := Val * 10; Val := Val + 2; FirstCharFound := True; when '3' => Val := Val * 10; Val := Val + 3; FirstCharFound := True; when '4' => Val := Val * 10; Val := Val + 4; FirstCharFound := True; when '5' => Val := Val * 10; Val := Val + 5; FirstCharFound := True; when '6' => Val := Val * 10; Val := Val + 6; FirstCharFound := True; when '7' => Val := Val * 10; Val := Val + 7; FirstCharFound := True; when '8' => Val := Val * 10; Val := Val + 8; FirstCharFound := True; when '9' => Val := Val * 10; Val := Val + 9; FirstCharFound := True; when ' ' => if FirstCharFound then return Val; end if; when others => return Val; end case; end loop; return Val; end function; impure function BuildCounterFromFile (BC_FileName : in string) return Natural is File BC_File : text open read_mode is BC_FileName; variable FileLine : line; variable Counter : Natural; variable CounterStr : String (1 to 32); variable LineLength : Natural; begin report "Build counter file name : " & BC_FileName; readline (BC_File, FileLine); --file_close(BC_File); LineLength := FileLine'Length; CounterStr := (others => ' '); read (FileLine, CounterStr(1 to LineLength)); --Counter := Integer'Value(CounterStr(1 to LineLength)); Counter := str_to_natural(CounterStr(1 to LineLength)); report "Build counter value : " & Natural'Image(Counter); return Counter; end function; constant Counter : Natural := BuildCounterFromFile(FILE_NAME); constant CounterStr : String := Natural'Image(Counter + 1); File BC_File : text; begin process variable file_status : file_open_status; -- @suppress "variable file_status is never read" variable FileLine : line; begin file_open(file_status, BC_File, FILE_NAME, write_mode); write(FileLine, CounterStr); writeline(BC_File, FileLine); file_close(BC_File); wait; end process; Build_Counter <= std_logic_vector(to_unsigned(Counter, Build_Counter'Length)); end Behavioral; |
Note
Ces codes source n'ont été testés qu'avec les outils Xilinx. Il est fort probable qu'ils ne soient pas utilisables avec d'autres chaines de développement. La raison principale est qu'en VHDL, la lecture/écriture de fichiers est présente, à la base, pour être utilisée lors de la simulation. Lecture de vecteurs de test, écriture de fichiers de compte rendu de simulation... Le synthétiseur de Xilinx permet de lire et écrire des fichiers lors de la synthèse, avec des restrictions.