From 876d38444585710c6e9cbe609a56f907d963842f Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Wed, 1 Jan 2014 08:30:17 +0100 Subject: Add bug17309 --- testsuite/gna/bug17309/makefile | 120 ++ testsuite/gna/bug17309/master_testbench3.vhdl | 366 +++++ testsuite/gna/bug17309/polyamplib.vhdl | 1860 +++++++++++++++++++++++++ testsuite/gna/bug17309/testsuite.sh | 10 + 4 files changed, 2356 insertions(+) create mode 100644 testsuite/gna/bug17309/makefile create mode 100644 testsuite/gna/bug17309/master_testbench3.vhdl create mode 100644 testsuite/gna/bug17309/polyamplib.vhdl create mode 100755 testsuite/gna/bug17309/testsuite.sh 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" -- cgit v1.2.3