Implementing a build counter in VHDL
Posted on September 16, 2021 in Hardware
I propose two codes to manage a build counter automatically.
The first one, which I have been using for years, is in VHDL. The second one, which I wrote recently, is in VHDL-2008.
Here is the first code, in 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; |
Here is now the VHDL-2008 version.
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
These source codes have only been tested with Xilinx tools. They might not be usable with other development toolchains. The main reason is that in VHDL, the reading/writing of files is present, basically, to be used during simulation. Reading test vectors, writing simulation report files... The Xilinx synthesizer allows to read and write files during the synthesis, with restrictions.
Translated with the help of www.DeepL.com/Translator (free version)