Commit e854ab00 authored by Dimitris Lampridis's avatar Dimitris Lampridis

Merge branch 'proposed_master' into release/1.1.0

parents 0e1a96bf 66009259
......@@ -196,6 +196,8 @@ Directory [modules/wishbone](modules/wishbone) contains modules for wishbone.
- [wb_vic](modules/wishbone/wb_vic) is the vectored interrupt controller.
- [wb_ds182x_readout](modules/wishbone/wb_ds182x_readout) is a direct
interface to the digital thermometer.
- [wb_xc7_fw_update](modules/wishbone/wb_xc7_fw_update) is an SPI interface
to drive the xc7 bitstream spi flash (using the ht-flash tool).
* There are utilities to handle a wishbone bus:
- [wb_clock_crossing](modules/wishbone/wb_clock_crossing) handle clock domain
......
......@@ -24,6 +24,7 @@ files = [
"gc_prio_encoder.vhd",
"gc_word_packer.vhd",
"gc_i2c_slave.vhd",
"gc_simple_spi_master.vhd",
"gc_glitch_filt.vhd",
"gc_dyn_glitch_filt.vhd",
"gc_comparator.vhd",
......
......@@ -40,9 +40,10 @@ entity gc_pulse_synchronizer2 is
-- pulse input ready (clk_in_i domain). When HI, a pulse
-- coming to d_p_i will be correctly transferred to q_p_o.
d_ready_o : out std_logic;
-- last pulse input acknowledged. This is an alternative
-- status flag to d_ready_o for applications that work better
-- with a pulsed ACK instead of a "ready" flag.
-- last pulse input acknowledged (clk_in_i domain).
-- This is an alternative status flag to d_ready_o for
-- applications that work better with a pulsed ACK
-- instead of a "ready" flag.
d_ack_p_o : out std_logic;
-- pulse input (clk_in_i domain)
d_p_i : in std_logic;
......
-----------------------------------------------------------------------------
-- Title : SPI Bus Master
-- Project : Simple VME64x FMC Carrier (SVEC)
-------------------------------------------------------------------------------
-- File : gc_simple_spi_master.vhd
-- Author : Tomasz Wlostowski
-- Company : CERN
-- Created : 2011-08-24
-- Last update: 2013-01-25
-- Platform : FPGA-generic
-- Standard : VHDL'93
-------------------------------------------------------------------------------
-- Description: Just a simple SPI master (bus-less).
-------------------------------------------------------------------------------
--
-- Copyright (c) 2011-2013 CERN / BE-CO-HT
--
-- This source file is free software; you can redistribute it
-- and/or modify it under the terms of the GNU Lesser General
-- Public License as published by the Free Software Foundation;
-- either version 2.1 of the License, or (at your option) any
-- later version.
--
-- This source is distributed in the hope that it will be
-- useful, but WITHOUT ANY WARRANTY; without even the implied
-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-- PURPOSE. See the GNU Lesser General Public License for more
-- details.
--
-- You should have received a copy of the GNU Lesser General
-- Public License along with this source; if not, download it
-- from http://www.gnu.org/licenses/lgpl-2.1.html
--
-------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity gc_simple_spi_master is
generic(
-- clock division ratio (SCLK = clk_sys_i / (2 ** g_div_ratio_log2).
g_div_ratio_log2 : integer := 2;
-- number of data bits per transfer
g_num_data_bits : integer := 2);
port (
clk_sys_i : in std_logic;
rst_n_i : in std_logic;
-- state of the Chip select line (1 = CS active). External control
-- allows for multi-transfer commands (SPI master itself does not
-- control the state of spi_cs_n_o)
cs_i : in std_logic;
-- 1: start next transfer (using CPOL, DATA and SEL from the inputs below)
start_i : in std_logic;
-- Clock polarity: 1: slave clocks in the data on rising SCLK edge, 0: ...
-- on falling SCLK edge
cpol_i : in std_logic;
-- TX Data input
data_i : in std_logic_vector(g_num_data_bits - 1 downto 0);
-- 1: data_o contains the result of last read operation. Core is ready to initiate
-- another transfer.
ready_o : out std_logic;
-- data read from selected slave, valid when ready_o == 1.
data_o : out std_logic_vector(g_num_data_bits - 1 downto 0);
-- these are obvious
spi_cs_n_o : out std_logic;
spi_sclk_o : out std_logic;
spi_mosi_o : out std_logic;
spi_miso_i : in std_logic
);
end gc_simple_spi_master;
architecture behavioral of gc_simple_spi_master is
signal divider : unsigned(11 downto 0);
signal tick : std_logic;
signal sreg : std_logic_vector(g_num_data_bits-1 downto 0);
signal rx_sreg : std_logic_vector(g_num_data_bits-1 downto 0);
type t_state is (IDLE, TX_CS, TX_DAT1, TX_DAT2, TX_SCK1, TX_SCK2, TX_CS2, TX_GAP);
signal state : t_state;
signal sclk : std_logic;
signal counter : unsigned(4 downto 0);
begin -- rtl
-- Simple clock divder. Produces a 'tick' signal which defines the timing for
-- the main state machine transitions.
p_divide_spi_clock: process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
divider <= (others => '0');
else
if(start_i = '1' or tick = '1') then
divider <= (others => '0');
else
divider <= divider + 1;
end if;
end if;
end if;
end process;
tick <= divider(g_div_ratio_log2);
-- Main state machine. Executes SPI transfers
p_main_fsm: process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_n_i = '0' then
state <= IDLE;
sclk <= '0';
sreg <= (others => '0');
rx_sreg <= (others => '0');
spi_mosi_o <= '0';
counter <= (others => '0');
else
case state is
-- Waits for start of transfer command
when IDLE =>
sclk <= '0';
counter <= (others => '0');
if(start_i = '1') then
sreg <= data_i;
state <= TX_CS;
spi_mosi_o <= data_i(sreg'high);
end if;
-- Generates a gap between the externally asserted Chip Select and
-- the beginning of data transfer
when TX_CS =>
if tick = '1' then
state <= TX_DAT1;
end if;
-- Outputs subsequent bits to MOSI line.
when TX_DAT1 =>
if(tick = '1') then
spi_mosi_o <= sreg(sreg'high);
sreg <= sreg(sreg'high-1 downto 0) & '0';
state <= TX_SCK1;
end if;
-- Flips the SCLK (active edge)
when TX_SCK1 =>
if(tick = '1') then
sclk <= not sclk;
counter <= counter + 1;
state <= TX_DAT2;
end if;
-- Shifts in bits read from the slave
when TX_DAT2 =>
if(tick = '1') then
rx_sreg <= rx_sreg(rx_sreg'high-1 downto 0) & spi_miso_i;
state <= TX_SCK2;
end if;
-- Flips the SCLK (inactive edge). Checks if all bits have been
-- transferred.
when TX_SCK2 =>
if(tick = '1') then
sclk <= not sclk;
if(counter = g_num_data_bits) then
state <= TX_CS2;
else
state <= TX_DAT1;
end if;
end if;
-- Generates a gap for de-assertoin of CS line
when TX_CS2 =>
if(tick = '1') then
state <= TX_GAP;
data_o <= rx_sreg;
end if;
when TX_GAP =>
if (tick = '1') then
state <= IDLE;
end if;
end case;
end if;
end if;
end process;
ready_o <= '1' when (state = IDLE and start_i = '0') else '0';
-- SCLK polarity control
spi_sclk_o <= sclk xor cpol_i;
spi_cs_n_o <= not cs_i;
end behavioral;
......@@ -37,7 +37,7 @@ use work.gencores_pkg.all;
entity gc_sync_word_wr is
generic (
-- automatically write next word when not busy
-- Automatically write next word when not busy.
g_AUTO_WR : boolean := FALSE;
g_WIDTH : positive := 8);
port (
......@@ -47,16 +47,18 @@ entity gc_sync_word_wr is
-- Output clock and reset
clk_out_i : in std_logic;
rst_out_n_i : in std_logic;
-- Input data
-- Input data (from clk_in_i domain)
data_i : in std_logic_vector (g_WIDTH - 1 downto 0);
-- Input control and status
-- Input control (from clk_in_i domain)
-- wr_i is ignored if g_AUTO_WR is set
wr_i : in std_logic := '0';
-- Transfer in progress (clk_in_i domain).
busy_o : out std_logic;
-- Input wr_i has been used (clk_in_i domain).
ack_o : out std_logic;
-- Output data
data_o : out std_logic_vector (g_WIDTH - 1 downto 0);
-- Output status
-- Output status. Pulse set when the data has been transfered (clk_out_i domain).
wr_o : out std_logic);
end entity;
......
......@@ -45,8 +45,8 @@ entity generic_sync_fifo is
g_with_almost_full : boolean := false;
g_with_count : boolean := false; -- with words counter
g_almost_empty_threshold : integer; -- threshold for almost empty flag
g_almost_full_threshold : integer; -- threshold for almost full flag
g_almost_empty_threshold : integer := 0; -- threshold for almost empty flag
g_almost_full_threshold : integer := 0; -- threshold for almost full flag
g_register_flag_outputs : boolean := true
);
......
modules = { "local" : [
"wb_async_bridge",
"wb_axi4lite_bridge",
......@@ -30,6 +29,7 @@ modules = { "local" : [
"wb_indirect",
"wbgen2",
"wbgenplus",
"wb_xc7_fw_update",
]}
files = [
......
files = ["wb_xc7_fw_update_regs.vhd",
"xwb_xc7_fw_update.vhd",
]
memory-map:
bus: wb-32-be
name: wb_xc7_fw_update_regs
description: System Control Registers
x-hdl:
busgroup: True
children:
- reg:
name: far
width: 32
access: rw
comment: Flash Access Register
description: Provides direct access to the SPI flash memory containing the bitstream.
x-hdl:
type: wire
write-strobe: true
children:
- field:
name: data
range: 7-0
comment: SPI Data
description: Data to be written / read to/from the flash SPI controller.
- field:
name: xfer
range: 8
comment: SPI Start Transfer
description: "write 1: initiate an SPI transfer with an 8-bit data word taken from the DATA field. write 0: no effect"
- field:
name: ready
range: 9
comment: SPI Ready
description: "read 1: Core is ready to initiate another transfer. DATA field contains the data read during previous transaction. read 0: core is busy"
- field:
name: cs
range: 10
comment: SPI Chip Select
description: "write 1: Enable target SPI controller. write 0: Disable target SPI controller"
-- Do not edit. Generated on Tue May 19 11:16:59 2020 by tgingold
-- With Cheby 1.4.dev0 and these options:
-- -i wb_xc7_fw_update_regs.cheby --gen-hdl wb_xc7_fw_update_regs.vhd
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
entity wb_xc7_fw_update_regs is
port (
rst_n_i : in std_logic;
clk_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
-- Flash Access Register
-- SPI Data
far_data_i : in std_logic_vector(7 downto 0);
far_data_o : out std_logic_vector(7 downto 0);
-- SPI Start Transfer
far_xfer_i : in std_logic;
far_xfer_o : out std_logic;
-- SPI Ready
far_ready_i : in std_logic;
far_ready_o : out std_logic;
-- SPI Chip Select
far_cs_i : in std_logic;
far_cs_o : out std_logic;
far_wr_o : out std_logic
);
end wb_xc7_fw_update_regs;
architecture syn of wb_xc7_fw_update_regs is
signal rd_req_int : std_logic;
signal wr_req_int : std_logic;
signal rd_ack_int : std_logic;
signal wr_ack_int : std_logic;
signal wb_en : std_logic;
signal ack_int : std_logic;
signal wb_rip : std_logic;
signal wb_wip : std_logic;
signal far_wreq : std_logic;
signal rd_ack_d0 : std_logic;
signal rd_dat_d0 : std_logic_vector(31 downto 0);
signal wr_req_d0 : std_logic;
signal wr_dat_d0 : std_logic_vector(31 downto 0);
signal wr_sel_d0 : std_logic_vector(3 downto 0);
begin
-- WB decode signals
wb_en <= wb_i.cyc and wb_i.stb;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_rip <= '0';
else
wb_rip <= (wb_rip or (wb_en and not wb_i.we)) and not rd_ack_int;
end if;
end if;
end process;
rd_req_int <= (wb_en and not wb_i.we) and not wb_rip;
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
wb_wip <= '0';
else
wb_wip <= (wb_wip or (wb_en and wb_i.we)) and not wr_ack_int;
end if;
end if;
end process;
wr_req_int <= (wb_en and wb_i.we) and not wb_wip;
ack_int <= rd_ack_int or wr_ack_int;
wb_o.ack <= ack_int;
wb_o.stall <= not ack_int and wb_en;
wb_o.rty <= '0';
wb_o.err <= '0';
-- pipelining for wr-in+rd-out
process (clk_i) begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
rd_ack_int <= '0';
wr_req_d0 <= '0';
else
rd_ack_int <= rd_ack_d0;
wb_o.dat <= rd_dat_d0;
wr_req_d0 <= wr_req_int;
wr_dat_d0 <= wb_i.dat;
wr_sel_d0 <= wb_i.sel;
end if;
end if;
end process;
-- Register far
far_data_o <= wr_dat_d0(7 downto 0);
far_xfer_o <= wr_dat_d0(8);
far_ready_o <= wr_dat_d0(9);
far_cs_o <= wr_dat_d0(10);
far_wr_o <= far_wreq;
-- Process for write requests.
process (wr_req_d0) begin
far_wreq <= '0';
-- Reg far
far_wreq <= wr_req_d0;
wr_ack_int <= wr_req_d0;
end process;
-- Process for read requests.
process (rd_req_int, far_data_i, far_xfer_i, far_ready_i, far_cs_i) begin
-- By default ack read requests
rd_dat_d0 <= (others => 'X');
-- Reg far
rd_ack_d0 <= rd_req_int;
rd_dat_d0(7 downto 0) <= far_data_i;
rd_dat_d0(8) <= far_xfer_i;
rd_dat_d0(9) <= far_ready_i;
rd_dat_d0(10) <= far_cs_i;
rd_dat_d0(31 downto 11) <= (others => '0');
end process;
end syn;
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.all;
use work.wishbone_pkg.all;
entity xwb_xc7_fw_update is
port (
clk_i : in std_logic;
rst_n_i : in std_logic;
wb_i : in t_wishbone_slave_in;
wb_o : out t_wishbone_slave_out;
flash_cs_n_o : out std_logic;
flash_mosi_o : out std_logic;
flash_miso_i : in std_logic
);
end xwb_xc7_fw_update;
architecture rtl of xwb_xc7_fw_update is
signal far_data_in : std_logic_vector(7 downto 0);
signal far_data_out : std_logic_vector(7 downto 0);
signal far_xfer_out : std_logic;
signal far_ready_in : std_logic;
signal far_cs_out : std_logic;
signal far_wr_out : std_logic;
signal flash_spi_cs : std_logic;
signal flash_spi_start : std_logic;
signal flash_spi_wdata : std_logic_vector(7 downto 0);
signal flash_sclk : std_logic;
begin
inst_regs: entity work.wb_xc7_fw_update_regs
port map (
clk_i => clk_i,
rst_n_i => rst_n_i,
wb_i => wb_i,
wb_o => wb_o,
far_data_i => far_data_in,
far_data_o => far_data_out,
far_xfer_i => '0',
far_xfer_o => far_xfer_out,
far_ready_i => far_ready_in,
far_ready_o => open,
far_cs_i => '0',
far_cs_o => far_cs_out,
far_wr_o => far_wr_out
);
-- Need to capture cs and data_out, and need to delay start.
p_host_spi_registers : process(clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
flash_spi_start <= '0';
flash_spi_wdata <= (others => '0');
flash_spi_cs <= '0';
elsif far_wr_out = '1' then
flash_spi_wdata <= far_data_out;
flash_spi_start <= far_xfer_out;
flash_spi_cs <= far_cs_out;
else
-- Pulse for start.
flash_spi_start <= '0';
end if;
end if;
end process;
U_SPI_Master : entity work.gc_simple_spi_master
generic map (
g_div_ratio_log2 => 0,
g_num_data_bits => 8)
port map (
clk_sys_i => clk_i,
rst_n_i => rst_n_i,
cs_i => flash_spi_cs,
start_i => flash_spi_start,
cpol_i => '0',
data_i => flash_spi_wdata,
ready_o => far_ready_in,
data_o => far_data_in,
spi_cs_n_o => flash_cs_n_o,
spi_sclk_o => flash_sclk,
spi_mosi_o => flash_mosi_o,
spi_miso_i => flash_miso_i);
STARTUPE2_inst : STARTUPE2
generic map (
PROG_USR => "FALSE", -- Activate program event security feature. Requires encrypted bitstreams.
SIM_CCLK_FREQ => 0.0 -- Set the Configuration Clock Frequency(ns) for simulation.
)
port map (
CFGCLK => open, -- 1-bit output: Configuration main clock output
CFGMCLK => open, -- 1-bit output: Configuration internal oscillator clock output
EOS => open, -- 1-bit output: Active high output signal indicating the End Of Startup.
PREQ => open, -- 1-bit output: PROGRAM request to fabric output
CLK => '0', -- 1-bit input: User start-up clock input
GSR => '0', -- 1-bit input: Global Set/Reset input (GSR cannot be used for the port name)
GTS => '0', -- 1-bit input: Global 3-state input (GTS cannot be used for the port name)
KEYCLEARB => '0', -- 1-bit input: Clear AES Decrypter Key input from Battery-Backed RAM (BBRAM)
PACK => '0', -- 1-bit input: PROGRAM acknowledge input
USRCCLKO => flash_sclk, -- 1-bit input: User CCLK input
USRCCLKTS => '0', -- 1-bit input: User CCLK 3-state enable input
USRDONEO => '0', -- 1-bit input: User DONE pin output control
USRDONETS => '1' -- 1-bit input: User DONE 3-state enable output
);
end rtl;
......@@ -298,10 +298,14 @@ class CIWBMasterAccessor extends CWishboneAccessor;
endclass // CIWBMasterAccessor
CIWBMasterAccessor theAccessor;
initial
theAccessor = new;
function automatic CIWBMasterAccessor get_accessor();
automatic CIWBMasterAccessor tmp;
tmp = new;
return tmp;
return theAccessor;
endfunction // get_accessor
always@(posedge clk_i)
......
......@@ -9,12 +9,16 @@ virtual class CWishboneAccessor extends CBusAccessor;
protected wb_cycle_type_t m_cycle_type;
function new();
$display("NEW");
m_cycle_type = CLASSIC;
m_default_xfer_size = 4;
endfunction // new
virtual task set_mode(wb_cycle_type_t mode);
virtual task automatic set_mode(wb_cycle_type_t mode);
m_cycle_type = mode;
$display("SET MODE %d", mode );
endtask // set_mode
......@@ -29,18 +33,18 @@ virtual class CWishboneAccessor extends CBusAccessor;
// RANDOM - event occurs randomly with probability (prob)
// These two can be combined (random events occuring after a certain initial delay)
// DELAYED events can be repeated (rep_rate parameter)
virtual task add_event(wba_sim_event_t evt, wba_sim_behavior_t behv, int dly_start, real prob, int rep_rate);
virtual task automatic add_event(wba_sim_event_t evt, wba_sim_behavior_t behv, int dly_start, real prob, int rep_rate);
endtask // add_event
// [slave only] gets a cycle from the queue
virtual task get(ref wb_cycle_t xfer);
virtual task automatic get(ref wb_cycle_t xfer);
endtask // get
// [master only] executes a cycle and returns its result
virtual task put(ref wb_cycle_t xfer);
virtual task automatic put(ref wb_cycle_t xfer);
endtask // put
......@@ -49,7 +53,7 @@ virtual class CWishboneAccessor extends CBusAccessor;
endfunction // idle
// [master only] generic write(s), blocking
virtual task writem(uint64_t addr[], uint64_t data[], int size = 4, ref int result = _null);
virtual task automatic writem(uint64_t addr[], uint64_t data[], int size = 4, ref int result = _null);
wb_cycle_t cycle;
int i;
......@@ -74,11 +78,13 @@ virtual class CWishboneAccessor extends CBusAccessor;
endtask // write
// [master only] generic read(s), blocking
virtual task readm(uint64_t addr[], ref uint64_t data[],input int size = 4, ref int result = _null);
virtual task automatic readm(uint64_t addr[], ref uint64_t data[],input int size = 4, ref int result = _null);
wb_cycle_t cycle;
int i;
cycle.ctype = m_cycle_type;
$display("CYCLE CTYPE %d %d", cycle.ctype, m_cycle_type );
cycle.rw = 1'b0;
for(i=0;i < addr.size(); i++)
......@@ -99,7 +105,7 @@ virtual class CWishboneAccessor extends CBusAccessor;
endtask // readm
virtual task read(uint64_t addr, ref uint64_t data, input int size = 4, ref int result = _null);
virtual task automatic read(uint64_t addr, ref uint64_t data, input int size = 4, ref int result = _null);
uint64_t aa[], da[];
aa = new[1];
da = new[1];
......@@ -108,7 +114,7 @@ virtual class CWishboneAccessor extends CBusAccessor;
data = da[0];
endtask
virtual task write(uint64_t addr, uint64_t data, int size = 4, ref int result = _null);
virtual task automatic write(uint64_t addr, uint64_t data, int size = 4, ref int result = _null);
uint64_t aa[], da[];
aa = new[1];
da = new[1];
......
......@@ -24,10 +24,10 @@ virtual class CBusAccessor;
pure virtual task writem(uint64_t addr[], uint64_t data[], input int size, ref int result);
pure virtual task readm(uint64_t addr[], ref uint64_t data[], input int size, ref int result);
pure virtual task automatic writem(uint64_t addr[], uint64_t data[], input int size, ref int result);
pure virtual task automatic readm(uint64_t addr[], ref uint64_t data[], input int size, ref int result);
virtual task read(uint64_t addr, ref uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
virtual task automatic read(uint64_t addr, ref uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
int res;
uint64_t aa[1], da[];
......@@ -39,7 +39,7 @@ virtual class CBusAccessor;
endtask
virtual task write(uint64_t addr, uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
virtual task automatic write(uint64_t addr, uint64_t data, input int size = m_default_xfer_size, ref int result = _null);
uint64_t aa[1], da[1];
aa[0] = addr;
da[0] = data;
......
......@@ -3,11 +3,27 @@
with open("buildinfo_pkg.vhd", "w") as f:
import subprocess
import time
# Extract current commit id.
try:
commitid = subprocess.check_output(
["git", "log", "-1", "--format=%H"]).decode().strip()
except:
commitid = "unknown"
# Extract current tag + dirty indicator.
# It is not sure if the definition of dirty is stable across all git versions.
try:
tag = subprocess.check_output(
["git", "describe", "--dirty", "--always"]).decode().strip()
if tag.endswith('-dirty'):
dirty = '-dirty'
else:
dirty = ''
except:
tag = 'unknown'
dirty = "-??"
try:
userid = subprocess.check_output(
["git", "config", "--get", "user.name"]).decode().strip()
......@@ -27,7 +43,8 @@ with open("buildinfo_pkg.vhd", "w") as f:
f.write(" constant buildinfo : string :=\n")
f.write(' "buildinfo:1" & LF\n')
f.write(' & "module:{}" & LF\n'.format(top))
f.write(' & "commit:{}" & LF\n'.format(commitid))
f.write(' & "commit:{}" & LF\n'.format(commitid + dirty))
f.write(' & "tag:{}" & LF\n'.format(tag))
f.write(' & "syntool:{}" & LF\n'.format(tool))
f.write(' & "syndate:{}" & LF\n'.format(
time.strftime("%F, %H:%M %Z", time.localtime())))
......
# Script to generate the buildinfo_pkg.vhd file
# Local parameter: project
with open("sourceid_{}_pkg.vhd".format(project), "w") as f:
import subprocess
import time
# Extract current commit id.
try:
sourceid = subprocess.check_output(
["git", "log", "-1", "--format=%H"]).decode().strip()
sourceid = sourceid[0:32]
except:
commitid = 16 * "00"
# Extract current tag + dirty indicator.
# It is not sure if the definition of dirty is stable across all git versions.
try:
tag = subprocess.check_output(
["git", "describe", "--dirty", "--always"]).decode().strip()
dirty = tag.endswith('-dirty')
except:
dirty = True
if dirty:
# There is no room for a dirty flag, just erase half of the bytes, so
# that's obvious it's not a real sha1, and still leaves enough to
# find the sha1 in the project.
sourceid = sourceid[:16] + (16 * '0')
f.write("-- Sourceid for project {}\n".format(project))
f.write("--\n")
f.write("-- This file was automatically generated; do not edit\n")
f.write("\n")
f.write("library ieee;")
f.write("use ieee.std_logic_1164.all;")
f.write("\n")
f.write("package sourceid_{}_pkg is\n".format(project))
f.write(" constant sourceid : std_logic_vector(127 downto 0) :=\n")
f.write(' x"{}";\n'.format(sourceid))
f.write('end sourceid_{}_pkg;\n'.format(project))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment