aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTristan Gingold <tgingold@free.fr>2014-01-01 08:30:17 +0100
committerTristan Gingold <tgingold@free.fr>2014-01-01 08:30:17 +0100
commit876d38444585710c6e9cbe609a56f907d963842f (patch)
tree8f6b8d7c510764007aeb54937f60ef8394e4cfdf
parent98ef692fe333e01f4e7127e6dee719b1aa7621b5 (diff)
downloadghdl-876d38444585710c6e9cbe609a56f907d963842f.tar.gz
ghdl-876d38444585710c6e9cbe609a56f907d963842f.tar.bz2
ghdl-876d38444585710c6e9cbe609a56f907d963842f.zip
Add bug17309
-rw-r--r--testsuite/gna/bug17309/makefile120
-rw-r--r--testsuite/gna/bug17309/master_testbench3.vhdl366
-rw-r--r--testsuite/gna/bug17309/polyamplib.vhdl1860
-rwxr-xr-xtestsuite/gna/bug17309/testsuite.sh10
4 files changed, 2356 insertions, 0 deletions
diff --git a/testsuite/gna/bug17309/makefile b/testsuite/gna/bug17309/makefile
new file mode 100644
index 000000000..6914cb717
--- /dev/null
+++ b/testsuite/gna/bug17309/makefile
@@ -0,0 +1,120 @@
+# Builds the library file "polyamplib", and a lot of testbenches.
+
+.SUFFIXES :
+.SUFFIXES : .o .vhdl
+
+AN_OPTS = --workdir=work
+ANTB_OPTS = --workdir=work --ieee=synopsys
+EL_OPTS = --workdir=work --ieee=synopsys
+
+OPTIONS=--ieee=synopsys
+
+#TB3REQ = command_decoder.o
+
+# General rule that don't recognize the working directory
+#.vhdl.o :
+# ghdl -a ${AN_OPTS} $<
+
+
+# Add testbenches to run here
+tests: prio_resolv2_tb.vcd active_input_tb.vcd one_of_n_encoder_tb.vcd master_state_machine_tb.vcd
+
+.PHONY: tests
+
+.PHONY: clean
+clean:
+ ghdl --clean ${AN_OPTS}
+
+work/polyamplib.o : polyamplib.vhdl
+ ghdl -a ${AN_OPTS} polyamplib.vhdl
+
+ad_interface_tb.vcd: ad_interface_tb.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} ad_interface_tb.vhdl
+ ghdl -e ${EL_OPTS} ad_interface_tb
+ ghdl -r ${EL_OPTS} ad_interface_tb --vcd=ad_interface_tb.vcd
+
+prio_resolv2_tb.vcd: prio_resolv2_tb.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} prio_resolv2_tb.vhdl
+ ghdl -e ${EL_OPTS} prio_resolv2_tb
+ ghdl -r ${EL_OPTS} prio_resolv2_tb --vcd=prio_resolv2_tb.vcd
+
+active_input_tb.vcd: active_input_tb.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} active_input_tb.vhdl
+ ghdl -e ${EL_OPTS} active_input_tb
+ ghdl -r ${EL_OPTS} active_input_tb --vcd=active_input_tb.vcd
+
+one_of_n_encoder_tb.vcd: one_of_n_encoder_tb.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} one_of_n_encoder_tb.vhdl
+ ghdl -e ${EL_OPTS} one_of_n_encoder_tb
+ ghdl -r ${EL_OPTS} one_of_n_encoder_tb --vcd=one_of_n_encoder_tb.vcd
+
+master_state_machine_tb.vcd: master_state_machine_tb.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} master_state_machine_tb.vhdl
+ ghdl -e ${EL_OPTS} master_state_machine_tb
+ ghdl -r ${EL_OPTS} master_state_machine_tb --vcd=master_state_machine_tb.vcd
+
+fifo_memory_tb.vcd: fifo_memory_tb.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} fifo_memory_tb.vhdl
+ ghdl -e ${EL_OPTS} fifo_memory_tb
+ ghdl -r ${EL_OPTS} fifo_memory_tb --vcd=fifo_memory_tb.vcd
+
+fifo_ft_memory_tb.vcd: fifo_ft_memory_tb.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} fifo_ft_memory_tb.vhdl
+ ghdl -e ${EL_OPTS} fifo_ft_memory_tb
+ ghdl -r ${EL_OPTS} fifo_ft_memory_tb --vcd=fifo_ft_memory_tb.vcd
+
+#ads1271_model.o: ads1271_model.vhdl
+# ghdl -a ${ANTB_OPTS} ads1271_model.vhdl
+#
+#command_decoder.o : command_decoder.vhdl
+# ghdl -a ${AN_OPTS} command_decoder.vhdl
+
+ad_interface2_tb.vcd: ad_interface2_tb.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} ad_interface2_tb.vhdl
+ ghdl -e ${EL_OPTS} ad_interface2_tb
+ ghdl -r ${EL_OPTS} ad_interface2_tb --vcd=ad_interface2_tb.vcd
+
+testguarded.vcd: testguarded.vhdl
+ ghdl -a ${ANTB_OPTS} testguarded.vhdl
+ ghdl -e ${EL_OPTS} testguarded
+ ghdl -r ${EL_OPTS} testguarded --vcd=testguarded.vcd
+
+sr_piso_tb.vcd: sr_piso_tb.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} sr_piso_tb.vhdl
+ ghdl -e ${EL_OPTS} sr_piso_tb
+ ghdl -r ${EL_OPTS} sr_piso_tb --vcd=sr_piso_tb.vcd
+
+spi_slave_tb1.vcd: spi_slave_tb1.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} spi_slave_tb1.vhdl
+ ghdl -e ${EL_OPTS} spi_slave_tb1
+ ghdl -r ${EL_OPTS} spi_slave_tb1 --vcd=spi_slave_tb1.vcd
+
+spi_slave_burst_tb.vcd: spi_slave_burst_tb.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} spi_slave_burst_tb.vhdl
+ ghdl -e ${EL_OPTS} spi_slave_burst_tb
+ ghdl -r ${EL_OPTS} spi_slave_burst_tb --vcd=spi_slave_burst_tb.vcd
+
+master_testbench.vcd: master_testbench.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} master_testbench.vhdl
+ ghdl -e ${EL_OPTS} master_testbench
+ ghdl -r ${EL_OPTS} master_testbench --vcd=master_testbench.vcd
+
+master_testbench2.vcd: master_testbench2.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} master_testbench2.vhdl
+ ghdl -e ${EL_OPTS} master_testbench2
+ ghdl -r ${EL_OPTS} master_testbench2 --vcd=master_testbench2.vcd
+
+master_testbench3.vcd: master_testbench3.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} master_testbench3.vhdl
+ ghdl -e ${EL_OPTS} master_testbench3
+ ghdl -r ${EL_OPTS} master_testbench3 --vcd=master_testbench3.vcd
+
+fast_edge_detect.vcd: fast_edge_detect.vhdl work/polyamplib.o
+ ghdl -a ${ANTB_OPTS} fast_edge_detect.vhdl
+ ghdl -e ${EL_OPTS} fast_edge_detect
+ ghdl -r ${EL_OPTS} fast_edge_detect --vcd=fast_edge_detect.vcd
+srff_tb.vcd: srff.vhdl
+ ghdl -a ${ANTB_OPTS} srff.vhdl
+ ghdl -e ${EL_OPTS} srff_tb
+ ghdl -r ${EL_OPTS} srff_tb --vcd=srff_tb.vcd
+
diff --git a/testsuite/gna/bug17309/master_testbench3.vhdl b/testsuite/gna/bug17309/master_testbench3.vhdl
new file mode 100644
index 000000000..c485af5f5
--- /dev/null
+++ b/testsuite/gna/bug17309/master_testbench3.vhdl
@@ -0,0 +1,366 @@
+-------------------------------------------------------------------------------
+-- Master testbench version 3
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+entity master_testbench3 is
+ -- Nada !
+end master_testbench3;
+
+
+use work.polyamplib.all;
+
+architecture master_testbench3_arch of master_testbench3 is
+
+ shared variable running : boolean := true; -- Run testbench when true
+
+ -- Global signals
+ signal fastclk : std_logic := '0';
+ signal resync : std_logic := '0';
+ signal adc_data_0 : std_logic_vector(23 downto 0); -- Bus from AD-interface
+ signal adc_data_1 : std_logic_vector(23 downto 0); -- to mux
+ signal fifo_write : std_logic;
+ signal fifo_input : std_logic_vector(31 downto 0);
+ signal fifo_output : std_logic_vector(31 downto 0);
+ signal id_code : unsigned(3 downto 0);
+ signal id_code_i : unsigned(3 downto 0);
+ signal fifo_isempty : std_logic;
+ signal fifo_meter : unsigned(7 downto 0);
+ signal fifo_half_full : std_logic := '0';
+ signal enable_adcvalues : std_logic := '0'; -- Enable automatic emission of values
+ signal not_enable_adcvalues : std_logic;
+
+ -- Clocks
+ signal clk24M : std_logic := '0';
+ signal clk4M : std_logic := '0';
+ signal clk2M : std_logic := '0';
+
+
+ -- Channel 0
+ signal advalue_0 : signed(23 downto 0) := to_signed(192, 24); --Input to ADC
+ signal adclk_0 : std_logic;
+ signal ad_ser_data_0 : std_logic;
+ signal n_drdy_0 : std_logic;
+ signal n_sync_0 : std_logic;
+ signal adi_busy_0 : std_logic;
+
+ -- Channel 1
+ signal advalue_1 : signed(23 downto 0) := to_signed(193, 24);
+ signal adclk_1 : std_logic;
+ signal ad_ser_data_1 : std_logic;
+ signal n_drdy_1 : std_logic;
+ signal n_sync_1 : std_logic;
+ signal adi_busy_1 : std_logic;
+
+ -- Spi interface
+ signal addr_data : std_logic_vector(31 downto 0); -- Received command/data
+ signal exec_cmd : std_logic := '0';
+ signal fifo_read : std_logic := '0';
+ signal start_adcs : std_logic := '0';
+ signal stop_adcs : std_logic := '0';
+ signal mosi : std_logic := '0';
+ signal miso : std_logic;
+ signal sck : std_logic := '1';
+ signal en_adc : std_logic := '1'; -- Active low
+ signal en_incl : std_logic := '1'; -- Active low
+ signal incl_miso : std_logic := '0';
+ signal incl_mosi : std_logic;
+ signal incl_sck : std_logic;
+ signal incl_ena : std_logic;
+
+ -- Simulation
+ signal data_to_spi : std_logic_vector(31 downto 0);
+ signal data_from_spi : std_logic_vector(31 downto 0);
+ signal start : std_logic := '0';
+ signal spim_busy : std_logic := '0';
+ signal signal_running : std_logic := '1';
+
+
+begin -- master_testbench3_arch
+
+
+ -----------------------------------------------------------------------------
+ -- Component instantiations
+ -----------------------------------------------------------------------------
+
+ adc0 : ads1271_model port map (
+ analog_in => advalue_0,
+ clk => adclk_0,
+ sclk => adclk_0,
+ n_sync => n_sync_0,
+ din => '0',
+ dout => ad_ser_data_0,
+ n_drdy => n_drdy_0);
+
+ adc1 : ads1271_model port map (
+ analog_in => advalue_1,
+ clk => adclk_1,
+ sclk => adclk_1,
+ n_sync => n_sync_1,
+ din => '0',
+ dout => ad_ser_data_1,
+ n_drdy => n_drdy_1);
+
+ adi0 : interface_ads1271 port map (
+ fastclk => fastclk,
+ adclk => adclk_0,
+ resync => resync,
+ ser_data => ad_ser_data_0,
+ n_drdy => n_drdy_0,
+ data_out => adc_data_0,
+ nsync => n_sync_0,
+ busy => adi_busy_0);
+
+ adi1 : interface_ads1271 port map (
+ fastclk => fastclk,
+ adclk => adclk_1,
+ resync => resync,
+ ser_data => ad_ser_data_1,
+ n_drdy => n_drdy_1,
+ data_out => adc_data_1,
+ nsync => n_sync_1,
+ busy => adi_busy_1);
+
+ msm : master_state_machine port map (
+ fastclk => fastclk,
+ enable_lo8 => enable_adcvalues,
+ busy_n_vec(0) => adi_busy_0,
+ busy_n_vec(1) => adi_busy_1,
+ busy_n_vec(11 downto 2) => "1111111110", -- Not used in testbench
+ id_code => id_code,
+ fifo_write => fifo_write);
+
+ adck0 : clockmux port map (
+ clk24M => clk24M,
+ clk4M => clk4M,
+ clk2M => clk2M,
+ clk1M => '0',
+ clk512k => '0',
+ clk256k => '0',
+ clk128k => '0',
+ sel => "110", -- 24 MHz clock => 48 ksa/s
+ clkout => adclk_0);
+
+ adck1 : clockmux port map (
+ clk24M => clk24M,
+ clk4M => clk4M,
+ clk2M => clk2M,
+ clk1M => '0',
+ clk512k => '0',
+ clk256k => '0',
+ clk128k => '0',
+ sel => "100", -- 2 MHz clock => 4 ksa/s
+ clkout => adclk_1);
+
+ fifo : fifo_ft_memory port map (
+ clock => fastclk,
+ sclr => not_enable_adcvalues, -- fifo_sclr @@@@@@@@@@
+ datain => fifo_input,
+ wrreq => fifo_write,
+ rdreq => fifo_read,
+ dataout => fifo_output,
+ empty => fifo_isempty,
+ meter => fifo_meter);
+
+ sync : sync_logic_2 port map (
+ start_adcs => start_adcs,
+ stop_adcs => stop_adcs,
+ reset => '0',
+ hwsync => '0',
+ fastclk => fastclk,
+ enable_adcvalues => enable_adcvalues);
+
+ spis : spi_slave_burst port map (
+ fastclk => fastclk,
+ spi_tx => fifo_output,
+ spi_rx => addr_data,
+-- spi_op => spi_op,
+ exec_cmd => exec_cmd,
+ fifo_read => fifo_read,
+ mosi => mosi,
+ miso => miso,
+ sck => sck,
+ en_adc => en_adc,
+ en_incl => en_incl,
+ incl_miso => incl_miso,
+ incl_mosi => incl_mosi,
+ incl_sck => incl_sck,
+ incl_ena => incl_ena);
+
+ cmd : command_decoder port map (
+ addr_data => addr_data,
+ decode => exec_cmd,
+ fastclk => fastclk,
+ resync_adc => resync,
+ start_adcs => start_adcs,
+ stop_adcs => stop_adcs);
+-- empty_fifo => fifo_sclr); -- fifo_sclr / open
+
+ spim : spi_master port map (
+ miso => miso,
+ mosi => mosi,
+ sck => sck,
+ en_adval => en_adc,
+ en_incl => en_incl,
+ data_to_spi => data_to_spi,
+ data_from_spi => data_from_spi,
+ start => start,
+ busy => spim_busy,
+ running => signal_running);
+
+
+ -----------------------------------------------------------------------------
+ -- Here comes the code
+ -----------------------------------------------------------------------------
+
+ id_code_i <= id_code + 1; -- Skip NULL command/address
+ fifo_half_full <= fifo_meter(6); -- >= 64
+ not_enable_adcvalues <= not enable_adcvalues;
+
+ with id_code select
+ fifo_input(23 downto 0) <=
+ adc_data_0 when "0000",
+ adc_data_1 when "0001",
+ "000000000000000000000000" when others;
+ fifo_input(27 downto 24) <= "0000" when fifo_isempty = '1' else std_logic_vector(id_code_i);
+ fifo_input(31 downto 28) <= "0000";
+
+
+ -----------------------------------------------------------------------------
+
+ fetch_data : process
+ begin -- process fetch_data
+ data_to_spi <= "00000001000000000000000000000100"; -- sel_adclk0
+ wait for 2500 ns;
+ start <= '1';
+ wait until spim_busy = '1';
+ start <= '0';
+ wait until spim_busy = '0';
+ wait for 1 us;
+
+ data_to_spi <= "00000010000000000000000000000100"; -- sel_adclk1
+ wait for 7 us;
+ start <= '1';
+ wait until spim_busy = '1';
+ start <= '0';
+ wait until spim_busy = '0';
+ wait for 1 us;
+
+-- data_to_spi <= "00000000000000000000000000000000"; -- Null command
+ data_to_spi <= "00001001000000000000000000000000"; -- resync
+-- wait for 15 us;
+ wait for 1 us;
+ start <= '1';
+ wait until spim_busy = '1';
+ start <= '0';
+ wait until spim_busy = '0';
+ wait for 1 us;
+
+ data_to_spi <= "00001011000000000000000000000000"; -- Start AD-conv.
+-- wait for 15 us;
+ wait for 1 us;
+ start <= '1';
+ wait until spim_busy = '1';
+ start <= '0';
+ wait until spim_busy = '0';
+ wait for 1 us;
+
+ for j in 1 to 250 loop
+ data_to_spi <= "00000000000000000000000000000000"; -- Null command
+-- wait for 15 us;
+ wait for 2 us;
+ start <= '1';
+ wait until spim_busy = '1';
+ start <= '0';
+ wait until spim_busy = '0';
+ wait for 1 us;
+ end loop; -- j
+
+ wait for 2000 us;
+
+ for j in 1 to 250 loop
+ data_to_spi <= "00000000000000000000000000000000"; -- Null command
+-- wait for 15 us;
+ wait for 2 us;
+ start <= '1';
+ wait until spim_busy = '1';
+ start <= '0';
+ wait until spim_busy = '0';
+ wait for 1 us;
+ end loop; -- j
+
+ wait;
+ end process fetch_data;
+
+ -----------------------------------------------------------------------------
+
+ main_timing : process
+ begin -- process main_timing
+ wait for 6 ms; -- Run during this time
+ signal_running <= '0';
+ running := false;
+ wait;
+ end process main_timing;
+
+ -----------------------------------------------------------------------------
+
+ osc_fastclk : process
+ begin -- process osc_fastclk
+ while running = true loop
+ fastclk <= '0';
+ wait for 10173 ps;
+ fastclk <= '1';
+ wait for 10173 ps;
+ end loop;
+ wait for 10 ns;
+ wait;
+ end process osc_fastclk;
+
+ -----------------------------------------------------------------------------
+
+ osc24M : process
+ begin -- process osc24M
+ while running = true loop
+ clk24M <= '0';
+ wait for 20345 ps;
+ clk24M <= '1';
+ wait for 20345 ps;
+ end loop;
+ wait for 10 ns;
+ wait;
+ end process osc24M;
+
+ -----------------------------------------------------------------------------
+
+ osc4M : process
+ begin -- process osc4M
+ while running = true loop
+ clk4M <= '0';
+ wait for 122 ns;
+ clk4M <= '1';
+ wait for 122 ns;
+ end loop;
+ wait for 10 ns;
+ wait;
+ end process osc4M;
+
+ -----------------------------------------------------------------------------
+
+ osc2M : process
+ begin -- process osc2M
+ while running = true loop
+ clk2M <= '0';
+ wait for 244 ns;
+ clk2M <= '1';
+ wait for 244 ns;
+ end loop;
+ wait for 10 ns;
+ wait;
+ end process osc2M;
+
+
+end master_testbench3_arch;
diff --git a/testsuite/gna/bug17309/polyamplib.vhdl b/testsuite/gna/bug17309/polyamplib.vhdl
new file mode 100644
index 000000000..4793cd560
--- /dev/null
+++ b/testsuite/gna/bug17309/polyamplib.vhdl
@@ -0,0 +1,1860 @@
+-----------------------------------------------------------------------------
+-- Polyamp vhdl function library
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+package polyamplib is
+
+ component interface_ads1271
+ port (
+ fastclk : in std_logic; -- Fast clock
+ adclk : in std_logic; -- A/D converter clock
+ resync : in std_logic; -- Clock change; resync
+ ser_data : in std_logic; -- Serial data in
+ n_drdy : in std_logic; -- Data is ready, active low
+ data_out : out std_logic_vector(23 downto 0); -- Parallell data out
+ nsync : out std_logic; -- Synchronize (restart) A/D conv.
+ busy : out std_logic; -- Busy reading serial data
+ g_sclk : out std_logic); -- Gated SPI clock, FOR SIMULATION ONLY
+ end component;
+
+ component priority_resolver2 is
+ port (
+ inp : in std_logic_vector(11 downto 0);
+ prio : out unsigned(3 downto 0); -- Output highest signal
+ active : out std_logic); -- High when any input is active
+ end component;
+
+ component one_of_n_encoder is
+ port (
+ number : in unsigned(3 downto 0);
+ enable : in std_logic;
+ single_out : out std_logic_vector(11 downto 0)); -- Only a single wire is active at a time
+ end component;
+
+ component active_input is
+ port (
+ fastclk : in std_logic; -- Main clock
+ enable : in std_logic; -- Enable signal
+ busy_n : in std_logic; -- Busy input signal, active low
+ clear : in std_logic; -- Clear the corresponding flip-flop
+ active_out : out std_logic); -- Active output
+ end component;
+
+ component master_state_machine is
+ port (
+ fastclk : in std_logic := '0'; -- Main clock
+ enable_lo8 : in std_logic; -- Enable the 8 low inputs
+ busy_n_vec : in std_logic_vector(11 downto 0); -- Busy inputs
+ id_code : inout unsigned(3 downto 0); -- Id code output
+ fifo_write : out std_logic); -- Save to fifo
+ end component;
+
+ component fifo_memory is
+ generic (
+ fifo_size : natural := 100);
+ port (
+ clock : in std_logic;
+ sclr : in std_logic;
+ datain : in std_logic_vector(31 downto 0);
+ wrreq : in std_logic;
+ rdreq : in std_logic;
+ dataout : out std_logic_vector(31 downto 0);
+ full : out std_logic;
+ empty : out std_logic;
+ meter : out unsigned(7 downto 0));
+ end component;
+
+ component fifo_ft_memory is
+ generic (
+ fifo_size : natural := 100);
+ port (
+ clock : in std_logic;
+ sclr : in std_logic;
+ datain : in std_logic_vector(31 downto 0);
+ wrreq : in std_logic;
+ rdreq : in std_logic;
+ dataout : out std_logic_vector(31 downto 0);
+ full : out std_logic;
+ empty : out std_logic;
+ meter : out unsigned(7 downto 0));
+ end component;
+
+ component ads1271_model is
+ port (
+ analog_in : in signed(23 downto 0); -- Analog input signal
+ clk : in std_logic; -- Conversion clock
+ sclk : in std_logic; -- SPI clock
+ n_sync : in std_logic; -- Input sync signal, active low
+ din : in std_logic; -- Serial data in
+ dout : out std_logic; -- Serial data out
+ n_drdy : out std_logic); -- Data ready, active low
+ end component;
+
+ component sr_sipo is
+ generic (
+ LENGTH : positive := 8; --! Shift register length
+ EDGE : natural := 1; --! Active edge; 1=positive, 0=negative
+ DIR : natural := 1); --! Direction; 1=left, 0=right
+ port (
+ clk : in std_logic; --! Clock input
+ ser_in : in std_logic; --! Serial input data
+ par_out : out std_logic_vector(1 to LENGTH)); --! Parallel output data
+ end component;
+
+ component sr_piso is
+ generic (
+ LENGTH : positive := 8; --! Shift register length
+ EDGE : natural := 1; --! Active edge; 1=positive, 0=negative
+ DIR : natural := 1); --! Direction; 1=left, 0=right
+ port (
+ clk : in std_logic; --! Clock input
+ load : in std_logic; --! Load on next clock
+ par_in : in std_logic_vector(1 to LENGTH); --! Parallel input data
+ ser_in : in std_logic; --! Serial input data
+ ser_out : out std_logic); --! Serial output data
+ end component;
+
+ component sr_piso_s is
+ generic (
+ LENGTH : positive := 8; --! Shift register length
+ DIR : natural := 1); --! Direction; 1=left, 0=right
+ port (
+ fastclk : in std_logic; --! Synchronous clock
+ clk_en : in std_logic; --! Clock enable input
+ load_en : in std_logic; --! Load enable input
+ par_in : in std_logic_vector(1 to LENGTH); --! Parallel input data
+ ser_in : in std_logic; --! Serial input data
+ ser_out : out std_logic); --! Serial output data
+ end component;
+
+ component spi_slave is
+ port (
+ -- Main controls
+ fastclk : in std_logic;
+ spi_tx : in std_logic_vector(31 downto 0); -- Data to be sent
+ spi_rx : out std_logic_vector(31 downto 0); -- Data to be received
+ spi_op : out std_logic; -- Read/Write status/data/command
+
+ -- Slave port, connected to CPU
+ mosi : in std_logic;
+ miso : out std_logic;
+ sck : in std_logic; -- SPI clock
+ en_adc : in std_logic; -- Active low, enable ADC
+ en_incl : in std_logic; -- Active low, enable inclinometer
+
+ -- Master port, connected to inclinometer
+ incl_miso : in std_logic;
+ incl_mosi : out std_logic;
+ incl_sck : out std_logic;
+ incl_ena : out std_logic); -- Active low, enable inclinometer
+ end component;
+
+ component command_decoder is
+ port (
+ addr_data : in std_logic_vector(31 downto 0); -- Input address/data
+ decode : in std_logic; -- Single cycle decode pulse
+ fastclk : in std_logic; -- Master clock (not used for now)
+ sel_nulcmd : out std_logic; -- NULL command (no operation)
+ sel_adclk0 : out std_logic; -- Select sampling clock, ad0.
+ sel_adclk1 : out std_logic; -- Select sampling clock, ad1.
+ sel_adclk2 : out std_logic; -- Select sampling clock, ad2.
+ sel_adclk3 : out std_logic; -- Select sampling clock, ad3.
+ sel_adclk4 : out std_logic; -- Select sampling clock, ad4.
+ sel_adclk5 : out std_logic; -- Select sampling clock, ad5.
+ sel_adclk6 : out std_logic; -- Select sampling clock, ad6.
+ sel_adclk7 : out std_logic; -- Select sampling clock, ad7.
+ resync_adc : out std_logic; -- Resynchronize all ADC's
+ write_ctrl : out std_logic; -- Write to control-signal register
+ start_adcs : out std_logic; -- Start AD-conversion
+ stop_adcs : out std_logic); -- Stop AD-conversion
+ end component;
+
+ component clockmux is
+ port (
+ clk24M : in std_logic; -- Input clocks, 24 576 000
+ clk4M : in std_logic; -- 4 096 000
+ clk2M : in std_logic; -- 2 048 000
+ clk1M : in std_logic; -- 1 024 000
+ clk512k : in std_logic; -- 512 000
+ clk256k : in std_logic; -- 256 000
+ clk128k : in std_logic; -- 128 000
+ sel : in unsigned(2 downto 0); -- Mux select input
+ clkout : out std_logic); -- Output clock
+ end component;
+
+ component spi_master is
+ port (
+ -- Hardware ports
+ miso : in std_logic;
+ mosi : out std_logic;
+ sck : inout std_logic;
+ en_adval : out std_logic := '1';
+ en_incl : out std_logic := '1';
+
+ -- Simulation ports
+ data_to_spi : in std_logic_vector(31 downto 0);
+ data_from_spi : out std_logic_vector(31 downto 0);
+ start : in std_logic;
+ busy : out std_logic := '0';
+ running : in std_logic);
+ end component;
+
+ component spi_slave_burst is
+ port (
+ -- Main controls
+ fastclk : in std_logic;
+ spi_tx : in std_logic_vector(31 downto 0); -- Data to be sent
+ spi_rx : out std_logic_vector(31 downto 0); -- Data to be received
+ exec_cmd : out std_logic; -- Write command/data
+ fifo_read : out std_logic; -- Read status/data
+
+ -- Slave port, connected to CPU
+ mosi : in std_logic;
+ miso : out std_logic;
+ sck : in std_logic; -- SPI clock
+ en_adc : in std_logic; -- Active low, enable ADC
+ en_incl : in std_logic; -- Active low, enable inclinometer
+
+ -- Master port, connected to inclinometer
+ incl_miso : in std_logic;
+ incl_mosi : out std_logic;
+ incl_sck : out std_logic;
+ incl_ena : out std_logic); -- Active low, enable inclinometer
+ end component;
+
+ component sync_logic_2 is
+ port (
+ start_adcs : in std_logic; -- Start command
+ stop_adcs : in std_logic; -- Stop command
+ reset : in std_logic; -- Active high
+ hwsync : in std_logic; -- Hardware sync
+ fastclk : in std_logic; -- Master clock
+ enable_adcvalues : out std_logic); -- Enable reception of values
+ end component;
+
+end polyamplib;
+
+
+-----------------------------------------------------------------------------
+-- Shift register for adc_interface, spi_interface etc.
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+--! General serial input, parallell output shift register
+
+--! The shift register length is generic, from 2 and up. It can trigger on
+--! positive or negative edges, and the shift direction can be choosen as well.
+entity sr_sipo is
+ generic (
+ LENGTH : positive := 8; --! Shift register length
+ EDGE : natural := 1; --! Active edge; 1=positive, 0=negative
+ DIR : natural := 1); --! Direction; 1=left, 0=right
+ port (
+ clk : in std_logic; --! Clock input
+ ser_in : in std_logic; --! Serial input data
+ par_out : out std_logic_vector(1 to LENGTH)); --! Parallel output data
+end sr_sipo;
+
+architecture sr_arch of sr_sipo is
+
+ signal my_sr : std_logic_vector(1 to LENGTH);
+
+begin -- sr_arch
+
+ posedge_right : if (EDGE = 1) and (DIR = 1) generate
+ shift : process(clk)
+
+ begin
+ if clk'event and clk = '1' then -- Positive clock edge
+ my_sr(1 to LENGTH) <= (my_sr(2 to LENGTH) & ser_in);
+ end if;
+ end process shift;
+ end generate posedge_right;
+
+ posedge_left : if (EDGE = 1) and (DIR /= 1) generate
+ shift : process(clk)
+
+ begin
+ if clk'event and clk = '1' then -- Positive clock edge
+ my_sr(1 to LENGTH) <= (ser_in & my_sr(1 to LENGTH-1));
+ end if;
+ end process shift;
+ end generate posedge_left;
+
+ negedge_right : if (EDGE /= 1) and (DIR = 1) generate
+ shift : process(clk)
+
+ begin
+ if clk'event and clk = '0' then -- Negative clock edge
+ my_sr(1 to LENGTH) <= (my_sr(2 to LENGTH) & ser_in);
+ end if;
+ end process shift;
+ end generate negedge_right;
+
+ negedge_left : if (EDGE /= 1) and (DIR /= 1) generate
+ shift : process(clk)
+
+ begin
+ if clk'event and clk = '0' then -- Negative clock edge
+ my_sr(1 to LENGTH) <= (ser_in & my_sr(1 to LENGTH-1));
+ end if;
+ end process shift;
+ end generate negedge_left;
+
+ par_out <= my_sr(1 to LENGTH) after 2 ns;
+
+end sr_arch;
+
+
+
+
+
+-----------------------------------------------------------------------------
+-- Shift register for spi_interface
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+--! General parallell input, serial output shift register
+
+--! The shift register length is generic, from 2 and up. It can trigger on
+--! positive or negative edges, and the shift direction can be choosen as well.
+
+entity sr_piso is
+ generic (
+ LENGTH : positive := 8; --! Shift register length
+ EDGE : natural := 1; --! Active edge; 1=positive, 0=negative
+ DIR : natural := 1); --! Direction; 1=left, 0=right
+ port (
+ clk : in std_logic; --! Clock input
+ load : in std_logic; --! Load on next clock
+ par_in : in std_logic_vector(1 to LENGTH); --! Parallel input data
+ ser_in : in std_logic; --! Serial input data
+ ser_out : out std_logic); --! Serial output data
+end sr_piso;
+
+architecture sr_arch of sr_piso is
+
+ signal my_sr : std_logic_vector(1 to LENGTH);
+
+begin -- sr_arch
+
+ shift_left : if DIR = 1 generate
+ ser_out <= my_sr(1) after 2 ns;
+ end generate shift_left;
+
+ shift_right : if DIR /= 1 generate
+ ser_out <= my_sr(LENGTH) after 2 ns;
+ end generate shift_right;
+
+ posedge_left : if (EDGE = 1) and (DIR = 1) generate
+ shift : process(clk)
+
+ begin
+ if clk'event and clk = '1' then -- Positive clock edge
+ if load = '1' then
+ my_sr <= par_in;
+ else
+ my_sr(1 to (LENGTH-1)) <= my_sr(2 to LENGTH);
+ my_sr(LENGTH) <= ser_in;
+ end if;
+ end if;
+ end process shift;
+ end generate posedge_left;
+
+ posedge_right : if (EDGE = 1) and (DIR /= 1) generate
+ shift : process(clk)
+
+ begin
+ if clk'event and clk = '1' then -- Positive clock edge
+ if load = '1' then
+ my_sr <= par_in;
+ else
+ my_sr(2 to LENGTH) <= my_sr(1 to LENGTH-1);
+ my_sr(1) <= ser_in;
+ end if;
+ end if;
+ end process shift;
+ end generate posedge_right;
+
+ negedge_left : if (EDGE /= 1) and (DIR = 1) generate
+ shift : process(clk)
+
+ begin
+ if clk'event and clk = '0' then -- Negative clock edge
+ if load = '1' then
+ my_sr <= par_in;
+ else
+ my_sr(1 to (LENGTH-1)) <= my_sr(2 to LENGTH);
+ my_sr(LENGTH) <= ser_in;
+ end if;
+ end if;
+ end process shift;
+ end generate negedge_left;
+
+ negedge_right : if (EDGE /= 1) and (DIR /= 1) generate
+ shift : process(clk)
+
+ begin
+ if clk'event and clk = '0' then -- Negative clock edge
+ if load = '1' then
+ my_sr <= par_in;
+ else
+ my_sr(2 to LENGTH) <= my_sr(1 to LENGTH-1);
+ my_sr(1) <= ser_in;
+ end if;
+ end if;
+ end process shift;
+ end generate negedge_right;
+
+end sr_arch;
+
+
+
+
+-----------------------------------------------------------------------------
+-- Synchronously clocked shift register for spi_interface
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+--! Synchronously clocked parallell input, serial output shift register
+
+--! The shift register length is generic, from 2 and up.
+--! The shift direction can be choosen.
+
+entity sr_piso_s is
+ generic (
+ LENGTH : positive := 8; --! Shift register length
+ DIR : natural := 1); --! Direction; 1=left, 0=right
+ port (
+ fastclk : in std_logic; --! Synchronous clock
+ clk_en : in std_logic; --! Clock enable input
+ load_en : in std_logic; --! Load enable input
+ par_in : in std_logic_vector(1 to LENGTH); --! Parallel input data
+ ser_in : in std_logic; --! Serial input data
+ ser_out : out std_logic); --! Serial output data
+end sr_piso_s;
+
+
+architecture ar_piso_s_arch of sr_piso_s is
+
+ signal my_sr : std_logic_vector(1 to LENGTH);
+
+begin -- ar_piso_s_arch
+
+ shift_left_out : if DIR = 1 generate
+ ser_out <= my_sr(1) after 2 ns;
+ end generate shift_left_out;
+
+ shift_right_out : if DIR /= 1 generate
+ ser_out <= my_sr(LENGTH) after 2 ns;
+ end generate shift_right_out;
+
+ shift_left : if (DIR = 1) generate
+ shift : process(fastclk)
+
+ begin
+ if rising_edge(fastclk) then -- Positive clock edge
+ if load_en = '1' then
+ my_sr <= par_in;
+ elsif clk_en = '1' then
+ my_sr(1 to (LENGTH-1)) <= my_sr(2 to LENGTH);
+ my_sr(LENGTH) <= ser_in;
+ end if;
+ end if;
+ end process shift;
+ end generate shift_left;
+
+ shift_right : if (DIR /= 1) generate
+ shift : process(fastclk)
+
+ begin
+ if rising_edge(fastclk) then -- Positive clock edge
+ if load_en = '1' then
+ my_sr <= par_in;
+ elsif clk_en = '1' then
+ my_sr(2 to LENGTH) <= my_sr(1 to LENGTH-1);
+ my_sr(1) <= ser_in;
+ end if;
+ end if;
+ end process shift;
+ end generate shift_right;
+
+
+end ar_piso_s_arch;
+
+
+
+
+
+
+-----------------------------------------------------------------------------
+-- The adc_interface
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity interface_ads1271 is
+
+ port (
+ fastclk : in std_logic; -- Fast clock
+ adclk : in std_logic; -- A/D converter clock
+ resync : in std_logic; -- Clock change; resync
+ ser_data : in std_logic; -- Serial data in
+ n_drdy : in std_logic; -- Data is ready, active low
+ data_out : out std_logic_vector(23 downto 0); -- Parallell data out
+ nsync : out std_logic := '1'; -- Synchronize (restart) A/D conv.
+ busy : out std_logic; -- Busy reading serial data
+ g_sclk : out std_logic); -- Gated SPI clock, FOR SIMULATION ONLY
+
+end interface_ads1271;
+
+
+architecture interface_ads1271_arch of interface_ads1271 is
+
+ type state_type is (idle, counting, freeze);
+ signal state : state_type := idle; -- Controlling state machine
+ signal unlatch_data : std_logic_vector(23 downto 0) := (others => '0'); -- From shift register
+ signal bitcounter : unsigned(4 downto 0) := to_unsigned(0, 5); -- Range 0..31
+ signal g_sclk_enable : std_logic := '0';
+
+ type rsync_sm_type is (rs_idle, rs_clo1, rs_chi, rs_clo2);
+ signal rsync_sm : rsync_sm_type := rs_idle;
+
+ component sr_sipo is
+ generic (
+ LENGTH : positive; --! Shift register length
+ EDGE : natural; --! Active edge; 1=positive, 0=negative
+ DIR : natural); --! Direction; 1=left, 0=right
+ port (
+ clk : in std_logic; --! Clock input
+ ser_in : in std_logic; --! Serial input data
+ par_out : out std_logic_vector(1 to LENGTH)); --! Parallel output data
+ end component;
+
+
+begin -- interface_ads1271_arch
+
+ sr1 : sr_sipo generic map (
+ LENGTH => 24,
+ EDGE => 1,
+ DIR => 1)
+ port map (
+ clk => adclk,
+ ser_in => ser_data,
+ par_out => unlatch_data);
+
+
+-- Static interconnects
+ g_sclk <= g_sclk_enable and adclk;
+
+
+
+-- purpose: Freeze output data
+-- type : sequential
+-- inputs : adclk, n_drdy
+
+ freeze_proc : process (adclk)
+ begin -- process freeze_proc
+ if rising_edge(adclk) then -- rising clock edge
+ case state is
+ when idle => if n_drdy = '0' then
+ busy <= '1';
+ state <= counting;
+ bitcounter <= to_unsigned(23, 5);
+ g_sclk_enable <= '1';
+ else
+ busy <= '0';
+ end if;
+ when counting => busy <= '1';
+ if bitcounter > 0 then
+ bitcounter <= bitcounter - 1;
+ else
+ state <= freeze;
+ data_out <= unlatch_data;
+ g_sclk_enable <= '0';
+ end if;
+ when freeze => busy <= '0';
+ if n_drdy = '1' then
+ state <= idle;
+ end if;
+ when others => state <= idle; busy <= '0';
+ end case;
+ end if;
+ end process freeze_proc;
+
+
+
+-- purpose: Handle resyncronization of A/D converters
+-- Keep nsync low for at least one adclk cycle
+-- type : sequential
+-- inputs : fastclk, adclk, resync
+-- outputs: nsync
+ resync_proc : process (fastclk)
+ begin -- process resync_proc
+ if rising_edge(fastclk) then -- rising clock edge
+ nsync <= '0';
+ case rsync_sm is
+ when rs_idle => if resync = '1' then
+ rsync_sm <= rs_clo1;
+ else
+ nsync <= '1';
+ end if;
+ when rs_clo1 => if adclk = '0' then
+ rsync_sm <= rs_chi;
+ end if;
+ when rs_chi => if adclk = '1' then
+ rsync_sm <= rs_clo2;
+ end if;
+ when rs_clo2 => if adclk = '0' then
+ rsync_sm <= rs_idle;
+ end if;
+ when others => rsync_sm <= rs_idle;
+ nsync <= '1';
+ end case;
+end if;
+end process resync_proc;
+
+end interface_ads1271_arch;
+
+
+
+
+-----------------------------------------------------------------------------
+-- The priority_resolver2
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity priority_resolver2 is
+ port (
+ inp : in std_logic_vector(11 downto 0); -- Active low inputs
+ prio : out unsigned(3 downto 0); -- Output highest signal
+ active : out std_logic); -- High when any input is active
+end priority_resolver2;
+
+
+architecture priority_resolver2_arch of priority_resolver2 is
+
+begin -- priority_resolver2_arch
+
+ -- Any input active ???
+ active <= inp(0) or inp(1) or inp(2) or inp(3) or inp(4) or inp(5) or
+ inp(6) or inp(7) or inp(8) or inp(9) or inp(10) or inp(11) after 1 ns;
+
+ -- purpose: Priority resolver
+ -- type : combinational
+ -- inputs : inp
+ -- outputs: prio, active
+ mainloop : process (inp)
+ begin -- process mainloop
+ if inp(11) = '1' then
+ prio <= to_unsigned(11, 4) after 1 ns;
+ elsif inp(10) = '1' then
+ prio <= to_unsigned(10, 4) after 1 ns;
+ elsif inp(9) = '1' then
+ prio <= to_unsigned(9, 4) after 1 ns;
+ elsif inp(8) = '1' then
+ prio <= to_unsigned(8, 4) after 1 ns;
+ elsif inp(7) = '1' then
+ prio <= to_unsigned(7, 4) after 1 ns;
+ elsif inp(6) = '1' then
+ prio <= to_unsigned(6, 4) after 1 ns;
+ elsif inp(5) = '1' then
+ prio <= to_unsigned(5, 4) after 1 ns;
+ elsif inp(4) = '1' then
+ prio <= to_unsigned(4, 4) after 1 ns;
+ elsif inp(3) = '1' then
+ prio <= to_unsigned(3, 4) after 1 ns;
+ elsif inp(2) = '1' then
+ prio <= to_unsigned(2, 4) after 1 ns;
+ elsif inp(1) = '1' then
+ prio <= to_unsigned(1, 4) after 1 ns;
+ else
+ prio <= to_unsigned(0, 4) after 1 ns;
+ end if;
+ end process mainloop;
+
+end priority_resolver2_arch;
+
+
+
+
+-----------------------------------------------------------------------------
+-- The active_input state machine
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity active_input is
+ port (
+ fastclk : in std_logic; -- Main clock
+ enable : in std_logic; -- Enable signal
+ busy_n : in std_logic; -- Busy input signal, active low
+ clear : in std_logic; -- Clear the corresponding flip-flop
+ active_out : out std_logic); -- Active output
+end active_input;
+
+
+architecture active_input_arch of active_input is
+
+ type input_state_type is (i_idle, i_active, i_decay);
+ signal i_state : input_state_type := i_idle;
+ signal temp_active_out : std_logic := '0'; -- Temporary signal'
+
+
+begin -- active_input_arch
+
+ -- Static delayed connex
+ active_out <= temp_active_out after 1 ns;
+
+
+ -- purpose: Input state machine
+ -- type : sequential
+ -- inputs : fastclk, fastclk, busy_n, clear
+ -- outputs: temp_active_out
+ input_active : process (fastclk)
+
+ begin -- process input_active
+ if rising_edge(fastclk) then -- rising clock edge
+ temp_active_out <= '0';
+ case i_state is
+ when i_idle => if (busy_n = '0') and (enable = '1') then
+ temp_active_out <= '1';
+ i_state <= i_active;
+ end if;
+
+ when i_active => if clear = '0' then
+ temp_active_out <= '1';
+ else
+ i_state <= i_decay;
+ end if;
+
+ when i_decay => if busy_n = '1' then
+ i_state <= i_idle;
+ end if;
+
+ when others => i_state <= i_idle;
+ end case;
+
+ end if;
+ end process input_active;
+end active_input_arch;
+
+
+
+
+
+
+-----------------------------------------------------------------------------
+-- The one_of_n_encoder
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity one_of_n_encoder is
+
+ port (
+ number : in unsigned(3 downto 0);
+ enable : in std_logic;
+ single_out : out std_logic_vector(11 downto 0)); -- Only a single wire is active at a time
+
+end one_of_n_encoder;
+
+
+
+architecture one_of_n_encoder_arch of one_of_n_encoder is
+
+ type out_table_type is array (0 to 15) of std_logic_vector(11 downto 0);
+ constant out_table : out_table_type :=
+ ("000000000001",
+ "000000000010",
+ "000000000100",
+ "000000001000",
+ "000000010000",
+ "000000100000",
+ "000001000000",
+ "000010000000",
+ "000100000000",
+ "001000000000",
+ "010000000000",
+ "100000000000",
+ "000000000000",
+ "000000000000",
+ "000000000000",
+ "000000000000");
+
+begin -- one_of_n_encoder_arch
+
+ -- purpose: Translate unsigned number into a signle output
+ -- type : sequential
+ -- inputs : number, number, enable
+ -- outputs: single_out
+ xlate : process (number, enable)
+ begin -- process xlate
+ if enable = '1' then
+ single_out <= out_table(to_integer(number)) after 1 ns;
+ else
+ single_out <= "000000000000" after 1 ns;
+ end if;
+
+ end process xlate;
+
+end one_of_n_encoder_arch;
+
+
+
+
+
+
+
+
+-----------------------------------------------------------------------------
+-- The master_state_machine
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.polyamplib.all;
+
+entity master_state_machine is
+
+ port (
+
+ fastclk : in std_logic := '0'; -- Main clock
+ enable_lo8 : in std_logic; -- Enable the 8 low inputs
+ busy_n_vec : in std_logic_vector(11 downto 0); -- Busy inputs
+ id_code : inout unsigned(3 downto 0); -- Id code output
+ fifo_write : out std_logic); -- Save to fifo
+
+end master_state_machine;
+
+
+
+architecture master_state_machine_arch of master_state_machine is
+
+ signal active_data : std_logic_vector(11 downto 0);
+ signal clear_vec : std_logic_vector(11 downto 0);
+ signal any_active : std_logic := '0'; -- Is any input active ???
+ signal clear_enable : std_logic := '0'; -- Clear the current active input flip-flop
+ signal temp_clear_en : std_logic := '0';
+ signal priority : unsigned(3 downto 0);
+
+ type master_state_type is (m_idle, m_latch, m_clear, m_decay);
+ signal m_state : master_state_type := m_idle;
+
+
+
+begin -- master_state_machine_arch
+
+ -- The first 8 are controlled by the enable_lo8 signal
+ gen1 : for i in 0 to 7 generate
+ inp_sm : active_input port map (
+ fastclk => fastclk,
+ enable => enable_lo8,
+ busy_n => busy_n_vec(i),
+ clear => clear_vec(i),
+ active_out => active_data(i));
+ end generate gen1;
+
+ -- The other inputs are always enabled
+ gen2 : for i in 8 to 11 generate
+ inp_sm : active_input port map (
+ fastclk => fastclk,
+ enable => '1',
+ busy_n => busy_n_vec(i),
+ clear => clear_vec(i),
+ active_out => active_data(i));
+ end generate gen2;
+
+ resolve : priority_resolver2 port map (
+ inp => active_data,
+ prio => priority,
+ active => any_active);
+
+ encode : one_of_n_encoder port map (
+ number => id_code,
+ enable => clear_enable,
+ single_out => clear_vec);
+
+
+ clear_enable <= temp_clear_en after 1 ns; -- After some delay
+ fifo_write <= clear_enable; -- Same-same
+
+
+ -- purpose: Master state machine
+ -- type : sequential
+ -- inputs : fastclk, s0..s11,c0..c11
+ -- outputs: fifo_write, data_id
+ master_loop : process (fastclk)
+
+ begin -- process master_loop
+
+ if rising_edge(fastclk) then -- rising clock edge
+ temp_clear_en <= '0';
+ case m_state is
+ when m_idle => if any_active = '1' then
+ id_code <= priority after 1 ns;
+ m_state <= m_latch;
+ end if;
+
+ when m_latch =>
+ temp_clear_en <= '1';
+ m_state <= m_clear;
+
+ when m_clear =>
+ m_state <= m_decay;
+
+ when m_decay =>
+ if any_active = '1' then
+ id_code <= priority after 1 ns;
+ m_state <= m_latch;
+ else
+ m_state <= m_idle;
+ end if;
+
+ when others => m_state <= m_idle;
+ end case;
+ end if;
+
+ end process master_loop;
+
+end master_state_machine_arch;
+
+
+
+
+
+-----------------------------------------------------------------------------
+-- The fifo_memory
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+--use work.polyamplib.all;
+
+entity fifo_memory is
+ generic (
+ fifo_size : natural := 100);
+ port (
+ clock : in std_logic;
+ sclr : in std_logic;
+ datain : in std_logic_vector(31 downto 0);
+ wrreq : in std_logic;
+ rdreq : in std_logic;
+ dataout : out std_logic_vector(31 downto 0);
+ full : out std_logic;
+ empty : out std_logic;
+ meter : out unsigned(7 downto 0));
+end fifo_memory;
+
+
+
+architecture fifo_memory_arch of fifo_memory is
+
+begin -- fifo_memory_arch
+
+ -- purpose: Fifo memory simulator
+ -- type : sequential
+ -- inputs : clock, datain, wrreq, rdreq, clock
+ -- outputs: dataout, full, empty
+ fifo_mem : process (clock)
+
+ subtype word is std_logic_vector(31 downto 0);
+ type memory_area is array(0 to fifo_size) of word;
+ variable fifo : memory_area; -- The fifo memory area
+
+ variable head_ix : natural := 0; -- Write data to this address
+ variable tail_ix : natural := 0; -- Read data from this address
+ variable test_ix : natural := 0; -- Used for test of overflow/underflow
+
+ begin -- process fifo
+ if rising_edge(clock) then -- rising clock edge
+
+ -- Synchronous clear
+ if sclr = '1' then
+ head_ix := 0;
+ tail_ix := 0;
+ elsif wrreq = '1' then -- Fifo write op's
+ test_ix := head_ix + 1;
+ if test_ix > fifo_size then
+ test_ix := 0;
+ end if;
+ -- Writing to full fifo discards the last value
+ if test_ix /= tail_ix then -- NOT full
+ fifo(head_ix) := datain; -- Write data
+ head_ix := test_ix; -- And adjust the pointer
+ end if;
+ end if;
+
+ -- Reading empty fifo returns the last value
+ if (rdreq = '1') and (head_ix /= tail_ix) then
+ dataout <= fifo(tail_ix) after 1 ns;
+ tail_ix := tail_ix + 1;
+ if tail_ix > fifo_size then
+ tail_ix := 0;
+ end if;
+ end if;
+
+ -- Fifo empty signal
+ if head_ix = tail_ix then
+ empty <= '1' after 1 ns;
+ else
+ empty <= '0' after 1 ns;
+ end if;
+
+ -- Fifo full signal
+ if (tail_ix = (head_ix+1)) or ((tail_ix = 0) and (head_ix = fifo_size)) then
+ full <= '1' after 1 ns;
+ else
+ full <= '0' after 1 ns;
+ end if;
+
+ -- Fifo fill meter operations
+ if head_ix >= tail_ix then
+ meter <= to_unsigned(head_ix - tail_ix, 8);
+ else
+ meter <= to_unsigned(fifo_size + 1 + head_ix - tail_ix, 8);
+ end if;
+
+ end if;
+ end process fifo_mem;
+
+end fifo_memory_arch;
+
+
+
+
+
+
+-----------------------------------------------------------------------------
+-- The fifo_ft_memory
+-----------------------------------------------------------------------------
+
+-- Fallthrough fifo memory model
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+--use work.polyamplib.all;
+
+entity fifo_ft_memory is
+ generic (
+ fifo_size : natural := 100);
+ port (
+ clock : in std_logic;
+ sclr : in std_logic;
+ datain : in std_logic_vector(31 downto 0);
+ wrreq : in std_logic;
+ rdreq : in std_logic;
+ dataout : out std_logic_vector(31 downto 0);
+ full : out std_logic;
+ empty : out std_logic;
+ meter : out unsigned(7 downto 0));
+end fifo_ft_memory;
+
+
+
+architecture fifo_ft_memory_arch of fifo_ft_memory is
+
+begin -- fifo_ft_memory_arch
+
+ -- purpose: Fifo memory simulator
+ -- type : sequential
+ -- inputs : clock, datain, wrreq, rdreq, clock
+ -- outputs: dataout, full, empty
+ fifo_mem : process (clock)
+
+ subtype word is std_logic_vector(31 downto 0);
+ type memory_area is array(0 to fifo_size) of word;
+ variable fifo : memory_area; -- The fifo memory area
+
+ variable head_ix : natural := 0; -- Write data to this address
+ variable tail_ix : natural := 0; -- Read data from this address
+ variable test_ix : natural := 0; -- Used for test of overflow/underflow
+
+ begin -- process fifo
+ if rising_edge(clock) then -- rising clock edge
+
+ -- Synchronous clear
+ if sclr = '1' then
+ head_ix := 0;
+ tail_ix := 0;
+ else
+ -- Write to fifo
+ if wrreq = '1' then -- Fifo write op's
+ test_ix := head_ix + 1;
+ if test_ix > fifo_size then
+ test_ix := 0;
+ end if;
+
+ -- Fifo is empty
+ if head_ix = tail_ix then
+ dataout <= datain; -- Let data fall-through
+ fifo(head_ix) := datain; -- Write data
+ head_ix := test_ix; -- And adjust the pointer
+ elsif test_ix /= tail_ix then -- NOT full
+ fifo(head_ix) := datain; -- Write data
+ head_ix := test_ix; -- And adjust the pointer
+ end if;
+ end if;
+
+ -- Reading empty fifo returns the last value
+ if (rdreq = '1') and (head_ix /= tail_ix) then
+ tail_ix := tail_ix + 1;
+ if tail_ix > fifo_size then
+ tail_ix := 0;
+ end if;
+ if tail_ix /= head_ix then
+ dataout <= fifo(tail_ix) after 1 ns;
+ end if;
+ end if;
+ end if;
+
+
+ -- Fifo empty signal
+ if head_ix = tail_ix then
+ empty <= '1' after 1 ns;
+ else
+ empty <= '0' after 1 ns;
+ end if;
+
+ -- Fifo full signal
+ if (tail_ix = (head_ix+1)) or ((tail_ix = 0) and (head_ix = fifo_size)) then
+ full <= '1' after 1 ns;
+ else
+ full <= '0' after 1 ns;
+ end if;
+
+ -- Fifo fill meter operations
+ if head_ix >= tail_ix then
+ meter <= to_unsigned(head_ix - tail_ix, 8);
+ else
+ meter <= to_unsigned(fifo_size + 1 + head_ix - tail_ix, 8);
+ end if;
+
+ end if;
+ end process fifo_mem;
+
+end fifo_ft_memory_arch;
+
+
+
+
+
+
+-----------------------------------------------------------------------------
+-- VHDL model of A/D-converter Texas ADS1271
+-----------------------------------------------------------------------------
+
+-- NOTE! This is a model for simulation only. It is not
+-- coded to be synthezised.
+
+-- SPI interface format, 512 clock cycles/conversion
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+entity ads1271_model is
+ port (
+ analog_in : in signed(23 downto 0); -- Analog input signal
+ clk : in std_logic; -- Conversion clock
+ sclk : in std_logic; -- SPI clock
+ n_sync : in std_logic; -- Input sync signal, active low
+ din : in std_logic; -- Serial data in
+ dout : out std_logic; -- Serial data out
+ n_drdy : out std_logic := '1'); -- Data ready, active low
+end ads1271_model;
+
+
+
+architecture ads1271_model_arch of ads1271_model is
+
+ signal analog_data : signed(23 downto 0) := to_signed(0, 24);
+ shared variable conv_timer : integer := 2; -- Data conversion rate
+ shared variable sdata_counter : integer := -1; -- Controls dout bits
+ signal din_mem : std_logic := '0'; -- 'din' memory
+ signal drdy_ff : std_logic;
+ signal clk_del : std_logic := '0'; -- Delayed clk signal
+ signal sclk_del : std_logic := '0'; -- Delayed sclk signal
+ signal ct_is_one : std_logic; -- Locally generated sync
+ signal ct_is_zero : std_logic; -- Locally generated sync
+
+
+begin -- ads1271_model_arch
+
+ n_drdy <= drdy_ff or ct_is_one after 8 ns;
+ sclk_del <= sclk after 2 ns;
+ clk_del <= clk after 1 ns;
+
+
+ -- purpose: Data conversion circuitry
+ -- type : sequential
+ -- inputs : clk_del
+ -- outputs: dout, ct_is_one
+ convert : process (clk_del)
+ begin -- process convert
+ if falling_edge(clk_del) then -- falling clock edge
+ ct_is_one <= '0';
+ ct_is_zero <= '0';
+ if n_sync = '0' then
+ conv_timer := (128*512); -- Reloading the FIR takes a while
+ ct_is_one <= '1';
+ else
+ conv_timer := conv_timer - 1;
+ if conv_timer <= 0 then -- Conversion rate number
+ conv_timer := 512;
+ sdata_counter := 23; -- MSBit comes first
+ ct_is_zero <= '1';
+ end if; -- conv_timer <= 0
+ if conv_timer = 1 then
+ ct_is_one <= '1';
+ end if; -- conv_timer = 1
+ if conv_timer = 512 then
+ analog_data <= analog_in; -- Data sampling, data av. after 512 clock's
+ end if; -- conv_timer = 512
+ end if; -- n_sync = '0'
+ end if; -- falling_edge(clk_del)
+
+ end process convert;
+
+
+
+ -- purpose: Serial data interface control
+ -- type : sequential
+ -- inputs : sclk_del
+ -- outputs: dout
+ dataout : process (sclk_del)
+
+ begin -- process dataout
+ if sclk_del'event then
+ if sclk_del = '0' then -- falling clock edge
+ if sdata_counter >= 0 then
+ dout <= 'X' after 5 ns;
+ dout <= analog_data(sdata_counter) after 12 ns;
+ sdata_counter := sdata_counter - 1;
+ else
+ dout <= 'X' after 5 ns;
+ dout <= din_mem after 12 ns;
+ end if;
+ else
+ -- rising clock edge samples din
+ din_mem <= din;
+ end if;
+ end if;
+ end process dataout;
+
+
+
+ -- purpose: Controls the drdy_ff signal
+ -- type : sequential
+ -- inputs : sclk_del, ct_is_zero
+ -- outputs: drdy_ff
+ readyctl : process (sclk_del, ct_is_zero)
+ begin -- process readyctl
+ if ct_is_zero = '1' then -- asynchronous reset (active high)
+ drdy_ff <= '0';
+ elsif falling_edge(sclk_del) then -- falling clock edge
+ drdy_ff <= '1';
+ end if;
+ end process readyctl;
+
+end ads1271_model_arch;
+
+
+
+
+
+-----------------------------------------------------------------------------
+-- SPI slave with secondary spi master port
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.polyamplib.all;
+
+
+entity spi_slave is
+
+ port (
+ -- Main controls
+ fastclk : in std_logic;
+ spi_tx : in std_logic_vector(31 downto 0); -- Data to be sent
+ spi_rx : out std_logic_vector(31 downto 0); -- Data to be received
+ spi_op : out std_logic; -- Read/Write status/data/command
+
+ -- Slave port, connected to CPU
+ mosi : in std_logic;
+ miso : out std_logic;
+ sck : in std_logic; -- SPI clock
+ en_adc : in std_logic; -- Active low, enable ADC
+ en_incl : in std_logic; -- Active low, enable inclinometer
+
+ -- Master port, connected to inclinometer
+ incl_miso : in std_logic;
+ incl_mosi : out std_logic;
+ incl_sck : out std_logic;
+ incl_ena : out std_logic); -- Active low, enable inclinometer
+end spi_slave;
+
+
+
+architecture spi_slave_arch of spi_slave is
+
+ type state_type is (idle, load, shift, relax);
+ signal state : state_type := idle; -- Controlling state machine
+
+ signal enable_inclinometer : std_logic := '0';
+ signal enable_adc : std_logic := '0';
+ signal adc_miso : std_logic;
+ signal adc_load : std_logic := '0';
+-- signal g_miso : std_logic register := '0'; -- guarded miso signal
+ signal adc_sck : std_logic;
+ signal tx_sck : std_logic;
+ signal delayed_adc_sck : std_logic; -- Delayed, for edge detection
+
+
+begin -- spi_slave_arch
+
+ -- Transmit shift register
+ tx_sr : sr_piso_s generic map (
+ LENGTH => 32,
+ DIR => 1) -- Shift left => MSB first
+ port map (
+ fastclk => fastclk,
+ clk_en => tx_sck,
+ load_en => adc_load,
+ par_in => spi_tx,
+ ser_in => '0',
+ ser_out => adc_miso);
+
+ -- Receive shift register
+ rx_sr : sr_sipo generic map (
+ LENGTH => 32,
+ EDGE => 1, -- Positive edge
+ DIR => 1) -- Shift left => MSB first
+ port map (
+ clk => adc_sck,
+ ser_in => mosi,
+ par_out => spi_rx);
+
+
+ -- Passthru signals
+ incl_sck <= sck after 1 ns;
+ incl_mosi <= mosi after 1 ns;
+ incl_ena <= not enable_inclinometer after 1 ns; -- Active low output
+
+ -- Enable and clock
+ enable_inclinometer <= not en_incl and en_adc after 1 ns;
+ enable_adc <= not en_adc after 1 ns;
+ adc_sck <= sck or en_adc after 1 ns; -- Clock is driven high at inactive state
+ tx_sck <= (not adc_sck) and delayed_adc_sck after 1 ns; -- sck negative edge trigger
+
+ -- Output data
+-- miso <= g_miso;
+
+
+ -- purpose: ADC controls miso
+-- talkto_adc : block (enable_adc = '1')
+-- begin -- block talkto_adc
+-- g_miso <= guarded adc_miso;
+-- end block talkto_adc;
+
+
+ -- purpose: Inclinometer controls miso
+-- talkto_incl : block (enable_inclinometer = '1')
+-- begin -- block talkto_incl
+-- g_miso <= guarded incl_miso;
+-- end block talkto_incl;
+
+
+ -- Instead of the guarded assignments above
+ miso <= adc_miso when enable_inclinometer = '0' else incl_miso;
+
+
+ -- purpose: SPI slave controller state machine
+ -- type : sequential
+ -- inputs : fastclk, enable_adc
+ -- outputs: adc_load
+ input_active : process (fastclk)
+
+ begin -- process input_active
+ if rising_edge(fastclk) then -- rising clock edge
+ delayed_adc_sck <= adc_sck;
+ adc_load <= '1' after 1 ns;
+ spi_op <= '0' after 1 ns;
+ case state is
+ when idle => if enable_adc = '1' then
+ state <= load;
+ end if;
+
+ when load => state <= shift;
+
+ when shift => adc_load <= '0' after 1 ns;
+ if enable_adc = '0' then
+ state <= relax;
+ spi_op <= '1' after 1 ns;
+ end if;
+
+ when relax => state <= idle;
+
+ when others => state <= idle;
+ end case;
+ end if;
+ end process input_active;
+
+end spi_slave_arch;
+
+
+
+
+-----------------------------------------------------------------------------
+-- SPI slave with burst capabilities and with secondary spi master port
+-- NOTE! Spi mode 2
+-----------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.polyamplib.all;
+
+
+entity spi_slave_burst is
+
+ port (
+ -- Main controls
+ fastclk : in std_logic;
+ spi_tx : in std_logic_vector(31 downto 0); -- Data to be sent
+ spi_rx : out std_logic_vector(31 downto 0); -- Data to be received
+ exec_cmd : out std_logic; -- Write command/data
+ fifo_read : out std_logic; -- Read status/data
+
+ -- Slave port, connected to CPU
+ mosi : in std_logic;
+ miso : out std_logic;
+ sck : in std_logic; -- SPI clock
+ en_adc : in std_logic; -- Active low, enable ADC
+ en_incl : in std_logic; -- Active low, enable inclinometer
+
+ -- Master port, connected to inclinometer
+ incl_miso : in std_logic;
+ incl_mosi : out std_logic;
+ incl_sck : out std_logic;
+ incl_ena : out std_logic); -- Active low, enable inclinometer
+end spi_slave_burst;
+
+
+
+architecture spi_slave_burst_arch of spi_slave_burst is
+
+-- type state_type is (idle, load, shift, relax);
+-- signal state : state_type := idle; -- Controlling state machine
+
+ signal bitcounter : unsigned(4 downto 0) := to_unsigned(0, 5); -- Range 0..31
+ signal enable_inclinometer : std_logic := '0';
+ signal enable_adc : std_logic := '0';
+ signal adc_miso : std_logic;
+ signal clk_tx_sr : std_logic := '0';
+ signal load_tx_sr : std_logic := '0';
+
+ signal sck_r1 : std_logic; -- Delayed, for edge detection
+ signal sck_r2 : std_logic; -- Delayed, for edge detection
+ signal sck_negedge : std_logic; -- Negative edge
+ signal sck_posedge : std_logic; -- Positive edge
+ signal enable_adc_r1 : std_logic; -- Delayed, for edge detection
+ signal enable_adc_r2 : std_logic; -- Delayed, for edge detection
+ signal enable_adc_negedge : std_logic; -- Negative edge
+
+ signal bitcounter_zero : std_logic;
+ signal bitcounter_one : std_logic;
+ signal exec_ff : std_logic := '0'; -- Enable the execute signal
+ signal load_ff : std_logic := '0'; -- Enable the load signal
+
+
+begin -- spi_slave_burst_arch
+
+ -- Transmit shift register
+ tx_sr : sr_piso_s generic map (
+ LENGTH => 32,
+ DIR => 1) -- Shift left => MSB first
+ port map (
+ fastclk => fastclk,
+ clk_en => clk_tx_sr,
+ load_en => load_tx_sr,
+ par_in => spi_tx,
+ ser_in => '0',
+ ser_out => adc_miso);
+
+ -- Receive shift register
+ rx_sr : sr_sipo generic map (
+ LENGTH => 32,
+ EDGE => 1, -- Positive edge
+ DIR => 1) -- Shift left => MSB first
+ port map (
+ clk => sck_negedge,
+ ser_in => mosi,
+ par_out => spi_rx);
+
+
+ -- Passthru signals
+ incl_sck <= sck after 1 ns;
+ incl_mosi <= mosi after 1 ns;
+ incl_ena <= not enable_inclinometer after 1 ns; -- Active low output
+
+ -- Enable and clock
+ enable_inclinometer <= not en_incl and en_adc after 1 ns;
+ enable_adc <= not en_adc after 1 ns;
+
+ sck_posedge <= sck_r1 and (not sck_r2) after 1 ns; -- sck Positive edge
+ sck_negedge <= sck_r2 and (not sck_r1) after 1 ns; -- sck Negative edge
+
+ enable_adc_negedge <= enable_adc_r1 and (not enable_adc_r2) after 1 ns;
+ fifo_read <= sck_posedge and bitcounter_one after 1 ns;
+ load_tx_sr <= enable_adc_negedge or
+ (sck_negedge and bitcounter_zero and (not load_ff)) after 1 ns;
+ exec_cmd <= bitcounter_zero and exec_ff and sck_posedge after 1 ns;
+ clk_tx_sr <= sck_posedge or enable_adc_negedge after 1 ns;
+
+ -- Instead of the guarded assignments above
+ miso <= adc_miso when enable_inclinometer = '0' else incl_miso after 1 ns;
+
+
+ -- purpose: SPI slave controller state machine
+ -- type : sequential
+ -- inputs : fastclk, sck, enable_adc, bitcounter, load_tx_sr
+ -- outputs: sck_r1, sck_r2, enable_adc_r1, enable_adc_r2, bitcounter
+ input_active : process (fastclk)
+
+ begin -- process input_active
+ if rising_edge(fastclk) then -- rising clock edge
+ sck_r2 <= sck_r1 after 1 ns;
+ sck_r1 <= sck after 1 ns;
+
+ enable_adc_r2 <= enable_adc_r1 after 1 ns;
+ enable_adc_r1 <= enable_adc after 1 ns;
+
+ if enable_adc_negedge = '1' then
+ bitcounter <= to_unsigned(0, 5) after 1 ns;
+ else if sck_negedge = '1' then
+ bitcounter <= bitcounter + 1 after 1 ns;
+ end if;
+ end if;
+
+ if bitcounter = 0 then
+ bitcounter_zero <= '1' after 1 ns;
+ else
+ bitcounter_zero <= '0' after 1 ns;
+ end if;
+
+ if bitcounter = 1 then
+ bitcounter_one <= '1' after 1 ns;
+ else
+ bitcounter_one <= '0' after 1 ns;
+ end if;
+
+ if enable_adc = '0' then
+ exec_ff <= '0' after 1 ns;
+ elsif bitcounter = 2 then
+ exec_ff <= '1' after 1 ns;
+ end if;
+
+ if load_tx_sr = '1' then
+ load_ff <= '1' after 1 ns;
+ elsif bitcounter = 2 then
+ load_ff <= '0' after 1 ns;
+ end if;
+
+ end if;
+ end process input_active;
+
+end spi_slave_burst_arch;
+
+
+
+
+
+----------------------------------------------------------------------
+-- Command decoder function
+----------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+entity command_decoder is
+ port (
+ addr_data : in std_logic_vector(31 downto 0); -- Input address/data
+ decode : in std_logic; -- Single cycle decode pulse
+ fastclk : in std_logic; -- Master clock (not used for now)
+ sel_nulcmd : out std_logic; -- NULL command (no operation)
+ sel_adclk0 : out std_logic; -- Select sampling clock, ad0.
+ sel_adclk1 : out std_logic; -- Select sampling clock, ad1.
+ sel_adclk2 : out std_logic; -- Select sampling clock, ad2.
+ sel_adclk3 : out std_logic; -- Select sampling clock, ad3.
+ sel_adclk4 : out std_logic; -- Select sampling clock, ad4.
+ sel_adclk5 : out std_logic; -- Select sampling clock, ad5.
+ sel_adclk6 : out std_logic; -- Select sampling clock, ad6.
+ sel_adclk7 : out std_logic; -- Select sampling clock, ad7.
+ resync_adc : out std_logic; -- Resynchronize all ADC's
+ write_ctrl : out std_logic; -- Write to control-signal register
+ start_adcs : out std_logic; -- Start AD-conversion
+ stop_adcs : out std_logic); -- Stop AD-conversion
+end command_decoder;
+
+
+architecture command_decoder_arch of command_decoder is
+
+begin -- command_decoder_arch
+
+ sel_nulcmd <= '1' when (addr_data(27 downto 24) = "0000") and decode = '1' else '0';
+ sel_adclk0 <= '1' when (addr_data(27 downto 24) = "0001") and decode = '1' else '0';
+ sel_adclk1 <= '1' when (addr_data(27 downto 24) = "0010") and decode = '1' else '0';
+ sel_adclk2 <= '1' when (addr_data(27 downto 24) = "0011") and decode = '1' else '0';
+ sel_adclk3 <= '1' when (addr_data(27 downto 24) = "0100") and decode = '1' else '0';
+ sel_adclk4 <= '1' when (addr_data(27 downto 24) = "0101") and decode = '1' else '0';
+ sel_adclk5 <= '1' when (addr_data(27 downto 24) = "0110") and decode = '1' else '0';
+ sel_adclk6 <= '1' when (addr_data(27 downto 24) = "0111") and decode = '1' else '0';
+ sel_adclk7 <= '1' when (addr_data(27 downto 24) = "1000") and decode = '1' else '0';
+ resync_adc <= '1' when (addr_data(27 downto 24) = "1001") and decode = '1' else '0';
+ write_ctrl <= '1' when (addr_data(27 downto 24) = "1010") and decode = '1' else '0';
+ start_adcs <= '1' when (addr_data(27 downto 24) = "1011") and decode = '1' else '0';
+ stop_adcs <= '1' when (addr_data(27 downto 24) = "1100") and decode = '1' else '0';
+
+end command_decoder_arch;
+
+
+
+
+----------------------------------------------------------------------
+-- ADC clock multiplexer function
+----------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity clockmux is
+ port (
+ clk24M : in std_logic; -- Input clocks, 24 576 000
+ clk4M : in std_logic; -- 4 096 000
+ clk2M : in std_logic; -- 2 048 000
+ clk1M : in std_logic; -- 1 024 000
+ clk512k : in std_logic; -- 512 000
+ clk256k : in std_logic; -- 256 000
+ clk128k : in std_logic; -- 128 000
+ sel : in unsigned(2 downto 0); -- Mux select input
+ clkout : out std_logic); -- Output clock
+end clockmux;
+
+
+architecture clockmux_arch of clockmux is
+
+begin -- clockmux_arch
+
+ with sel select
+ clkout <=
+ clk128k when "000",
+ clk256k when "001",
+ clk512k when "010",
+ clk1M when "011",
+ clk2M when "100",
+ clk4M when "101",
+ clk24M when "110",
+ clk24M when others;
+
+end clockmux_arch;
+
+
+
+
+-------------------------------------------------------------------------------
+-- SPI master for simulation and test (no synth.)
+-------------------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+
+entity spi_master is
+ port (
+ -- Hardware ports
+ miso : in std_logic;
+ mosi : out std_logic;
+ sck : inout std_logic := '0';
+ en_adval : out std_logic := '1';
+ en_incl : out std_logic := '1';
+
+ -- Simulation ports
+ data_to_spi : in std_logic_vector(31 downto 0);
+ data_from_spi : out std_logic_vector(31 downto 0);
+ start : in std_logic;
+ busy : out std_logic := '0';
+ running : in std_logic);
+end spi_master;
+
+
+architecture spi_master_arch of spi_master is
+
+ type state_type is (idle, load, shift);
+ signal state : state_type := idle;
+ signal start_mem : std_logic := '0';
+
+
+begin -- spi_master_arch
+
+
+ -----------------------------------------------------------------------------
+
+ -- Assume that data_to_spi is defined before this process is triggered
+ spi_rxtx : process (sck)
+
+ variable bit_index : integer := 0;
+
+ begin -- process spi_rxtx
+ if sck'event then
+ if sck = '1' then -- rising clock edge
+ start_mem <= start;
+ case state is
+ when idle => if start = '1' and start_mem = '0' then -- Start rising
+ -- edge
+ en_adval <= '0' after 15 ns;
+ busy <= '1' after 2 ns;
+ state <= load;
+ bit_index := 31;
+ end if;
+
+ when load => data_from_spi(bit_index) <= miso;
+ state <= shift;
+
+ when shift => bit_index := bit_index - 1;
+ if bit_index < 0 then
+ state <= idle;
+ en_adval <= '1' after 15 ns;
+ busy <= '0' after 2 ns;
+ else
+ data_from_spi(bit_index) <= miso;
+ end if;
+ when others => state <= idle;
+ end case;
+ end if; -- sck = '1' else ...
+
+ if sck = '0' and (state = load or state = shift) then
+ mosi <= data_to_spi(bit_index) after 1 ns;
+ end if;
+
+ end if; -- sck'event
+ end process spi_rxtx;
+
+ -----------------------------------------------------------------------------
+
+ spi_clk : process
+ begin -- process spi_clk
+ while running = '1' loop
+ sck <= not sck;
+ wait for 50 ns;
+ end loop;
+ sck <= not sck;
+ wait for 50 ns;
+ sck <= not sck;
+ wait for 50 ns;
+ sck <= not sck;
+ wait for 50 ns;
+ sck <= not sck;
+ wait for 50 ns;
+ wait;
+ end process spi_clk;
+
+end spi_master_arch;
+
+
+
+----------------------------------------------------------------------
+-- Synchronization logic
+----------------------------------------------------------------------
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity sync_logic_2 is
+
+ port (
+ start_adcs : in std_logic; -- Start command
+ stop_adcs : in std_logic; -- Stop command
+ reset : in std_logic; -- Active high
+ hwsync : in std_logic; -- Hardware sync
+ fastclk : in std_logic; -- Master clock
+ enable_adcvalues : out std_logic); -- Enable reception of values
+
+end sync_logic_2;
+
+
+
+architecture sync_logic_2_arch of sync_logic_2 is
+
+ signal del_sync_1 : std_logic; -- 1'st delay
+ signal del_sync_2 : std_logic; -- 2'nd delay
+ signal sr_set : std_logic; -- Set input to SR-latch
+ signal sr : std_logic := '0'; -- sr Q output, entity output
+
+
+begin -- sync_logic_2_arch
+
+ enable_adcvalues <= sr;
+ sr_set <= (del_sync_1 and (not del_sync_2)) xor start_adcs;
+
+
+ -- purpose: Two D-latches and one SR-latch is controlled
+ -- type : sequential
+ -- inputs : fastclk, reset, start_adcs, stop_adcs, hwsync
+ -- outputs: sr
+ registered_logic : process (fastclk, reset)
+ begin -- process registered_logic
+ if reset = '1' then -- asynchronous reset
+ del_sync_1 <= '0' after 2 ns;
+ del_sync_2 <= '0' after 2 ns;
+ sr <= '0' after 2 ns;
+ elsif rising_edge(fastclk) then -- rising clock edge
+ del_sync_1 <= hwsync after 2 ns;
+ del_sync_2 <= del_sync_1 after 2 ns;
+ if stop_adcs = '1' then
+ sr <= '0' after 2 ns;
+ elsif sr_set = '1' then
+ sr <= '1' after 2 ns;
+ end if;
+
+ end if;
+ end process registered_logic;
+
+end sync_logic_2_arch;
diff --git a/testsuite/gna/bug17309/testsuite.sh b/testsuite/gna/bug17309/testsuite.sh
new file mode 100755
index 000000000..689896329
--- /dev/null
+++ b/testsuite/gna/bug17309/testsuite.sh
@@ -0,0 +1,10 @@
+#! /bin/sh
+
+. ../../testenv.sh
+
+analyze polyamplib.vhdl master_testbench3.vhdl
+elab_simulate master_testbench3 --stop-time=1ms
+
+clean
+
+echo "Test successful"