Компиляция даты и времени в FPGA

Могу ли я использовать в VHDL нечто похожее на C-Sourcecode-Macros __DATE__ и __TIME__  сделать время компиляции доступным в FPGA как своего рода штамп времени версии?

В качестве → > new-comer < < для VHDL Я хочу изменить следующий существующий код, который помещает дату с жесткой кодировкой в ​​регистр FPGA. Я всегда должен помнить об изменении значений перед компиляцией. Было бы проще, если это будет сделано автоматически. Могу ли я также включать часы/минуты/секунды?

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;

ENTITY Datum2 IS
   PORT
   (
        Day         :OUT std_logic_vector(4 downto 0);
        Month       :OUT std_logic_vector(3 downto 0);
        Year        :OUT std_logic_vector(4 downto 0)
   );
END Datum2 ;

ARCHITECTURE rtl OF Datum2 IS

BEGIN
--  "08.08.0013"
    Day   <= conv_std_logic_vector(8, 5);
    Month <= conv_std_logic_vector(8, 4);
    Year  <= conv_std_logic_vector(13, 5);
END ARCHITECTURE rtl;

Ответ 1

Текущая дата и время не доступны напрямую в VHDL, но решение предлагается ниже.

EDITED 2013-08-10: Добавлено описание для автоматической генерации Altera Quartus II Tcl.

Один из способов сделать дату и время доступными - использовать автоматически созданный пакет VHDL, как показано ниже:

library ieee;
use ieee.std_logic_1164.all;

package datetime is
  -- Date information
  constant YEAR_INT  : integer                       := 2013;
  constant YEAR_HEX  : std_logic_vector(15 downto 0) := X"2013";
  constant MONTH_INT : integer                       := 08;
  constant MONTH_HEX : std_logic_vector(7 downto 0)  := X"08";
  constant DAY_INT   : integer                       := 09;
  constant DAY_HEX   : std_logic_vector(7 downto 0)  := X"09";
  constant DATE_HEX  : std_logic_vector(31 downto 0) := YEAR_HEX & MONTH_HEX & DAY_HEX;
  -- Time information
  constant HOUR_INT   : integer                       := 13;
  constant HOUR_HEX   : std_logic_vector(7 downto 0)  := X"13";
  constant MINUTE_INT : integer                       := 06;
  constant MINUTE_HEX : std_logic_vector(7 downto 0)  := X"06";
  constant SECOND_INT : integer                       := 29;
  constant SECOND_HEX : std_logic_vector(7 downto 0)  := X"29";
  constant TIME_HEX   : std_logic_vector(31 downto 0) := X"00" & HOUR_HEX & MINUTE_HEX & SECOND_HEX;
  -- Miscellaneous information
  constant EPOCH_INT  : integer := 1376046389;  -- Seconds since 1970-01-01_00:00:00
end package;

Этот пакет VHDL может быть создан с помощью сценария Tcl следующим образом:

# Make datetime.vhd package from Tcl script

# Current date, time, and seconds since epoch
# Array index                                            0  1  2  3  4  5  6
set datetime_arr [clock format [clock seconds] -format {%Y %m %d %H %M %S %s}]

# Write VHDL package
set filename datetime.vhd
set file [open $filename w]
puts $file "library ieee;"
puts $file "use ieee.std_logic_1164.all;"
puts $file ""
puts $file "package datetime is"
puts $file "  -- Date information"
puts $file "  constant YEAR_INT  : integer                       := [lindex $datetime_arr 0];"
puts $file "  constant YEAR_HEX  : std_logic_vector(15 downto 0) := X\"[lindex $datetime_arr 0]\";"
puts $file "  constant MONTH_INT : integer                       := [lindex $datetime_arr 1];"
puts $file "  constant MONTH_HEX : std_logic_vector(7 downto 0)  := X\"[lindex $datetime_arr 1]\";"
puts $file "  constant DAY_INT   : integer                       := [lindex $datetime_arr 2];"
puts $file "  constant DAY_HEX   : std_logic_vector(7 downto 0)  := X\"[lindex $datetime_arr 2]\";"
puts $file "  constant DATE_HEX  : std_logic_vector(31 downto 0) := YEAR_HEX & MONTH_HEX & DAY_HEX;"
puts $file "  -- Time information"
puts $file "  constant HOUR_INT   : integer                       := [lindex $datetime_arr 3];"
puts $file "  constant HOUR_HEX   : std_logic_vector(7 downto 0)  := X\"[lindex $datetime_arr 3]\";"
puts $file "  constant MINUTE_INT : integer                       := [lindex $datetime_arr 4];"
puts $file "  constant MINUTE_HEX : std_logic_vector(7 downto 0)  := X\"[lindex $datetime_arr 4]\";"
puts $file "  constant SECOND_INT : integer                       := [lindex $datetime_arr 5];"
puts $file "  constant SECOND_HEX : std_logic_vector(7 downto 0)  := X\"[lindex $datetime_arr 5]\";"
puts $file "  constant TIME_HEX   : std_logic_vector(31 downto 0) := X\"00\" & HOUR_HEX & MINUTE_HEX & SECOND_HEX;"
puts $file "  -- Miscellaneous information"
puts $file "  constant EPOCH_INT  : integer := [lindex $datetime_arr 6];  -- Seconds since 1970-01-01_00:00:00"
puts $file "end package;"
close $file

В Altera Quartus II можно запустить этот сценарий перед синтезом, в результате чего может быть создан пакет datetime. Это делается в файле .qsf с помощью строки ниже, где скрипт называется "make_datetime.tcl":

set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:make_datetime.tcl"

Более подробное описание этой функции Quartus II можно найти в Quartus II Tcl Пример: автоматическое выполнение сценария.

Затем модуль Datum2 может использовать такой пакет:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

entity Datum2 is
  port(
    Day   : out std_logic_vector(4 downto 0);
    Month : out std_logic_vector(3 downto 0);
    Year  : out std_logic_vector(4 downto 0));
end Datum2;


library work;
use work.datetime;

architecture rtl of Datum2 is
begin
  Day   <= conv_std_logic_vector(datetime.day_int, 5);
  Month <= conv_std_logic_vector(datetime.month_int, 4);
  Year  <= conv_std_logic_vector(datetime.year_int mod 100, 5);
end architecture rtl;

После синтеза в Quartus II программа просмотра RTL отображает выходные данные модуля, как показано ниже:

enter image description here

Ранее описанные альтернативные решения - создать пакет VHDL с помощью сценария Bash, например:

# Make datetime.vhd package from shell script

# Current date, time, and seconds since epoch
# Array index           0  1  2  3  4  5  6
datetime_arr=($(date +"%Y %m %d %H %M %S %s"))

# Write VHDL package
filename="datetime.vhd"
echo "library ieee;" > $filename
echo "use ieee.std_logic_1164.all;" >> $filename
echo "" >> $filename
echo "package datetime is" >> $filename
echo "  -- Date information" >> $filename
echo "  constant YEAR_INT  : integer                       := ${datetime_arr[0]};" >> $filename
echo "  constant YEAR_HEX  : std_logic_vector(15 downto 0) := X\"${datetime_arr[0]}\";" >> $filename
echo "  constant MONTH_INT : integer                       := ${datetime_arr[1]};" >> $filename
echo "  constant MONTH_HEX : std_logic_vector(7 downto 0)  := X\"${datetime_arr[1]}\";" >> $filename
echo "  constant DAY_INT   : integer                       := ${datetime_arr[2]};" >> $filename
echo "  constant DAY_HEX   : std_logic_vector(7 downto 0)  := X\"${datetime_arr[2]}\";" >> $filename
echo "  constant DATE_HEX  : std_logic_vector(31 downto 0) := YEAR_HEX & MONTH_HEX & DAY_HEX;" >> $filename
echo "  -- Time information" >> $filename
echo "  constant HOUR_INT   : integer                       := ${datetime_arr[3]};" >> $filename
echo "  constant HOUR_HEX   : std_logic_vector(7 downto 0)  := X\"${datetime_arr[3]}\";" >> $filename
echo "  constant MINUTE_INT : integer                       := ${datetime_arr[4]};" >> $filename
echo "  constant MINUTE_HEX : std_logic_vector(7 downto 0)  := X\"${datetime_arr[4]}\";" >> $filename
echo "  constant SECOND_INT : integer                       := ${datetime_arr[5]};" >> $filename
echo "  constant SECOND_HEX : std_logic_vector(7 downto 0)  := X\"${datetime_arr[5]}\";" >> $filename
echo "  constant TIME_HEX   : std_logic_vector(31 downto 0) := X\"00\" & HOUR_HEX & MINUTE_HEX & SECOND_HEX;" >> $filename
echo "  -- Miscellaneous information" >> $filename
echo "  constant EPOCH_INT  : integer := ${datetime_arr[6]};  -- Seconds since 1970-01-01_00:00:00" >> $filename
echo "end package;" >> $filename

Для независимости от платформы можно использовать такой скрипт Python 3.x, как этот:

# Make datetime.vhd package from Python 3.x script

# Get date and time
import datetime
import time
now = datetime.datetime.now()
now_epoch_sec = int(time.time())

# Write VHDL package
file = open('datetime.vhd', 'wt')
file.write('library ieee;\n')
file.write('use ieee.std_logic_1164.all;\n')
file.write('\n')
file.write('package datetime is\n')
file.write('  -- Date information\n')
file.write('  constant YEAR_INT  : integer                       := {};\n'.format(now.strftime('%Y')))
file.write('  constant YEAR_HEX  : std_logic_vector(15 downto 0) := X\"{}\";\n'.format(now.strftime('%Y')))
file.write('  constant MONTH_INT : integer                       := {};\n'.format(now.strftime('%m')))
file.write('  constant MONTH_HEX : std_logic_vector(7 downto 0)  := X\"{}\";\n'.format(now.strftime('%m')))
file.write('  constant DAY_INT   : integer                       := {};\n'.format(now.strftime('%d')))
file.write('  constant DAY_HEX   : std_logic_vector(7 downto 0)  := X\"{}\";\n'.format(now.strftime('%d')))
file.write('  constant DATE_HEX  : std_logic_vector(31 downto 0) := YEAR_HEX & MONTH_HEX & DAY_HEX;\n')
file.write('  -- Time information\n')
file.write('  constant HOUR_INT   : integer                       := {};\n'.format(now.strftime('%H')))
file.write('  constant HOUR_HEX   : std_logic_vector(7 downto 0)  := X\"{}\";\n'.format(now.strftime('%H')))
file.write('  constant MINUTE_INT : integer                       := {};\n'.format(now.strftime('%M')))
file.write('  constant MINUTE_HEX : std_logic_vector(7 downto 0)  := X\"{}\";\n'.format(now.strftime('%M')))
file.write('  constant SECOND_INT : integer                       := {};\n'.format(now.strftime('%S')))
file.write('  constant SECOND_HEX : std_logic_vector(7 downto 0)  := X\"{}\";\n'.format(now.strftime('%S')))
file.write('  constant TIME_HEX   : std_logic_vector(31 downto 0) := X\"00\" & HOUR_HEX & MINUTE_HEX & SECOND_HEX;\n')
file.write('  -- Miscellaneous information\n')
file.write('  constant EPOCH_INT  : integer := {};  -- Seconds since 1970-01-01_00:00:00\n'.format(now_epoch_sec))
file.write('end package;\n')
file.close()

Для представления даты и времени в 32-битных значениях регистра модуль может быть таким:

library ieee;
use ieee.std_logic_1164.all;
entity tb is
end entity;

library work;
use work.datetime;
architecture sim of tb is
  signal date_hex : std_logic_vector(31 downto 0);
  signal time_hex : std_logic_vector(31 downto 0);
begin
  date_hex <= datetime.DATE_HEX;
  time_hex <= datetime.TIME_HEX;
  process is begin wait; end process;
end architecture;

Форма волны показана ниже.

enter image description here

Подход сценариев Bash или Python требует интеграции в поток сборки для автоматической генерации пакетов.

РЕДАКТИРОВАНИЕ 2016-08-08 с обновлением Дэмиена: описание вызова сценария, отличного от Tcl, из Altera Quartus.

Чтобы интегрировать скрипт bash (в Linux), создайте скрипт-обертку Tcl, который вызывает скрипт bash как часть процесса. В этом примере есть каталог "scripts", в котором есть скрипт "call_bash.tcl" и "make_datetime.sh", который выполняет реальную работу:

# Useful if the script is in a subdirectory
proc getScriptDirectory {} {
    set dispScriptFile [file normalize [info script]]
    set scriptFolder [file dirname $dispScriptFile]
    return $scriptFolder
}

set scriptDir [getScriptDirectory]

# Call the bash script which does the real work
exec $scriptDir/make_datetime_vhdl.sh

# Add a message the Altera workflow
post_message -type info "Created datetime.vhd"

Интеграция в процесс сборки Altera может быть достигнута путем добавления следующего в файл qsf:

set_global_assignment -name PRE_FLOW_SCRIPT_FILE "quartus_sh:scripts/call_bash.tcl"

Ответ 2

Я использую 64-битную константу std_logic_vector.

У меня есть TCL script, который запускается непосредственно перед синтезом, чтобы закодировать текущее время в константе в пакете, который затем включается в FPGA, поэтому его можно считать каким-то образом.

Там неавтогенерированная версия того же пакета, который я использую в симуляциях, - это не изменяется, поэтому мне не нужно обновлять тесты.

Ответ 3

Вам не нужно выписывать полный код каждый раз, когда метка времени обновляется. В Quartus вы можете использовать TCL для установки генераторов верхнего уровня перед компиляцией:

Передайте дженерикам до объекта timestamp:

entity top is
generic (day, month, year : integer);
end entity top;

architecture struct of top is
begin
timestamp_inst : entity work.timestamp generic map(day, month, year);
end architecture struct;

И затем используйте preflow- script для установки дженериков:

set_parameter -name day $someday
set_parameter -name year $someyear
# etc

Я успешно использовал этот подход как с отметками времени, так и с версией git, идентификатором сборки. Мне удобно преобразовать его в массив слов, а затем получить доступ к ПЗУ. Просто используйте свое воображение.