diff options
Diffstat (limited to 'testsuite/gna/issue1655')
-rw-r--r-- | testsuite/gna/issue1655/absenc_master.vhdl | 607 | ||||
-rw-r--r-- | testsuite/gna/issue1655/absenc_master_endat.vhdl | 314 | ||||
-rw-r--r-- | testsuite/gna/issue1655/absenc_pkg.vhdl | 776 | ||||
-rw-r--r-- | testsuite/gna/issue1655/absenc_utils.vhdl | 239 | ||||
-rw-r--r-- | testsuite/gna/issue1655/endat_tb.vhdl | 130 | ||||
-rw-r--r-- | testsuite/gna/issue1655/repro.vhdl | 24 | ||||
-rw-r--r-- | testsuite/gna/issue1655/repro1.vhdl | 25 | ||||
-rwxr-xr-x | testsuite/gna/issue1655/testsuite.sh | 16 |
8 files changed, 2131 insertions, 0 deletions
diff --git a/testsuite/gna/issue1655/absenc_master.vhdl b/testsuite/gna/issue1655/absenc_master.vhdl new file mode 100644 index 000000000..3fa3fee12 --- /dev/null +++ b/testsuite/gna/issue1655/absenc_master.vhdl @@ -0,0 +1,607 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +library work; + + +entity master is + +generic +( + CLK_FREQ: integer; + ENABLE_ENDAT: boolean; + ENABLE_BISS: boolean; + ENABLE_SSI: boolean +); +port +( + -- local clock + clk: in std_logic; + rst: in std_logic; + + -- generated clock for slave + -- fdiv divides CLK_FREQ + ma_fdiv: in unsigned; + ma_clk: out std_logic; + + -- master out, slave in + mosi: out std_logic; + miso: in std_logic; + + -- gate to drive output (1 to drive it) + gate: out std_logic; + + -- data from slave, and data length + data: out std_logic_vector; + len: in unsigned; + + -- encoder type + enc_type: in integer; + + -- ssi specific control registers + ssi_flags: in std_logic_vector; + ssi_delay_fdiv: in unsigned +); + +end entity; + + +architecture absenc_master_rtl of master is + +constant DATA_LEN: integer := data'length; + +-- +-- conversion pipeline + +type conv_state_t is +( + CONV_WAIT_LATCH, + CONV_LSB_TO_MSB, + CONV_GRAY_TO_BIN, + CONV_EXTEND_SIGN, + CONV_DONE +); + +constant CONV_ERR: conv_state_t := CONV_WAIT_LATCH; + +signal curr_state: conv_state_t; +signal next_state: conv_state_t; + +signal latched_data: std_logic_vector(data'range); +signal msb_data: std_logic_vector(data'range); +signal bin_data: std_logic_vector(data'range); +signal signed_data: std_logic_vector(data'range); +signal conv_data: std_logic_vector(data'range); +signal len_mask: std_logic_vector(data'range); + +-- +-- enable conversion stages + +signal gray_to_bin_en: std_logic; +signal lsb_to_msb_en: std_logic; + +-- +-- timeout counter + +constant TM_MAX: integer := work.absenc_pkg.us_to_count + (work.absenc_pkg.MAX_TM_US, CLK_FREQ, integer'high); + +constant TM_LEN: integer := + work.absenc_pkg.integer_length(TM_MAX); + +constant DEFAULT_TM_TOP: integer := work.absenc_pkg.us_to_count + (work.absenc_pkg.MASTER_DEFAULT_TM_US, CLK_FREQ, TM_LEN); + +signal tm_val: unsigned(TM_LEN - 1 downto 0); +signal tm_top: unsigned(tm_val'range); +signal tm_match: std_logic; + +-- +-- general counter + +signal count_val: + unsigned(work.absenc_pkg.integer_length(DATA_LEN) - 1 downto 0); +signal count_top: unsigned(count_val'range); +signal count_top_latched: unsigned(count_val'range); +signal count_rst: std_logic; +signal count_match: std_logic; + +-- +-- serial in, parallel out (SIPO) register + +signal sipo_val: std_logic_vector(DATA_LEN - 1 downto 0); +signal sipo_latch_redge: std_logic; +signal sipo_latch_pre: std_logic; +signal sipo_latch: std_logic; + +-- +-- master clock + +signal ma_clk_rst_en: std_logic; +signal ma_clk_rst_val: std_logic; + +signal ma_clk_val: std_logic; + +signal ma_half_fdiv: unsigned(ma_fdiv'length - 1 downto 0); +signal ma_half_count: unsigned(ma_half_fdiv'length - 1 downto 0); +signal ma_half_match: std_logic; + +-- +-- master clock rising falling edges + +signal ma_clk_redge: std_logic; +signal ma_clk_fedge: std_logic; +signal ma_clk_edge: std_logic; + +-- +-- encoder multiplexed signal +-- +-- the mux size depends on ENABLE_xxx generics. the idea is to eliminate +-- unneeded FPGA logic by instantiating only modules enabled by the generics. +-- to do so, we have functions that translate from ENC_TYPE_xxx to ENC_MUX_xxx +-- and vice versa. ENC_TYPE_xxx represent all the possible encoders, while +-- ENC_MUX_xxx represent an encoder index in the mux, if enabled by generics. + +subtype tm_val_t is unsigned(tm_val'range); +type tm_val_array_t is array(integer range<>) of tm_val_t; + +subtype count_val_t is unsigned(count_val'range); +type count_val_array_t is array(integer range<>) of count_val_t; + +constant enc_mux_to_type: work.absenc_pkg.enc_type_array_t := + work.absenc_pkg.gen_enc_mux_to_type(ENABLE_ENDAT, ENABLE_BISS, ENABLE_SSI); + +constant ENC_MUX_COUNT: integer := + work.absenc_pkg.get_enc_mux_count(ENABLE_ENDAT, ENABLE_BISS, ENABLE_SSI); + +constant ENC_MUX_ENDAT: integer := + work.absenc_pkg.get_enc_mux_endat(ENABLE_ENDAT, ENABLE_BISS, ENABLE_SSI); + +constant ENC_MUX_BISS: integer := + work.absenc_pkg.get_enc_mux_biss(ENABLE_ENDAT, ENABLE_BISS, ENABLE_SSI); + +constant ENC_MUX_SSI: integer := + work.absenc_pkg.get_enc_mux_ssi(ENABLE_ENDAT, ENABLE_BISS, ENABLE_SSI); + +signal ma_clk_edge_mux: std_logic_vector(ENC_MUX_COUNT - 1 downto 0); +signal ma_clk_rst_en_mux: std_logic_vector(ENC_MUX_COUNT - 1 downto 0); +signal ma_clk_rst_val_mux: std_logic_vector(ENC_MUX_COUNT - 1 downto 0); +signal mosi_mux: std_logic_vector(ENC_MUX_COUNT - 1 downto 0); +signal gate_mux: std_logic_vector(ENC_MUX_COUNT - 1 downto 0); +signal tm_top_mux: tm_val_array_t(ENC_MUX_COUNT - 1 downto 0); +signal count_rst_mux: std_logic_vector(ENC_MUX_COUNT - 1 downto 0); +signal count_top_mux: count_val_array_t(ENC_MUX_COUNT - 1 downto 0); +signal sipo_latch_mux: std_logic_vector(ENC_MUX_COUNT - 1 downto 0); +signal gray_to_bin_en_mux: std_logic_vector(ENC_MUX_COUNT - 1 downto 0); +signal lsb_to_msb_en_mux: std_logic_vector(ENC_MUX_COUNT - 1 downto 0); + + +begin + + +-- +-- assert lengths to reduce generated logic +-- ie. counter and comparator sizes + +assert (ma_fdiv'length <= 16) +report "ma_fdiv'length too large" severity failure; + + +-- +-- master clock generation +-- master clock frequency is clk divided by ma_fdiv +-- generate edges using a counter from ma_fdiv/2 to 0 + +ma_half_fdiv <= ma_fdiv srl 1; +ma_half_match <= '1' when ma_half_count = 1 else '0'; + +process +begin + wait until rising_edge(clk); + + if ((rst or ma_clk_rst_en or ma_half_match) = '1') then + ma_half_count <= ma_half_fdiv; + else + ma_half_count <= ma_half_count - 1; + end if; + +end process; + + +process +begin + wait until rising_edge(clk); + + if ((rst or ma_clk_rst_en) = '1') then + ma_clk_val <= ma_clk_rst_val; + else + ma_clk_val <= ma_clk_val xor ma_half_match; + end if; + +end process; + +ma_clk <= ma_clk_val; + + +-- +-- master clock edges + +process +begin + wait until rising_edge(clk); + ma_clk_redge <= ma_half_match and (not ma_clk_val); +end process; + +process +begin + wait until rising_edge(clk); + ma_clk_fedge <= ma_half_match and ma_clk_val; +end process; + + +-- +-- timeout counter +-- tm_val decrement from tm_top to 0 +-- tm_val reloaded at ma_clk_edge + +process +begin + wait until rising_edge(clk); + + tm_match <= '0'; + + if ((rst or ma_clk_edge) = '1') then + tm_val <= tm_top; + elsif (tm_val = 0) then + tm_val <= tm_top; + tm_match <= '1'; + else + tm_val <= tm_val - 1; + end if; + +end process; + + +-- +-- general purpose counter +-- monotically incrementing +-- increment every master edge +-- starts from 1 + +process +begin + + wait until rising_edge(clk); + + if (count_rst = '1') then + count_val <= to_unsigned(integer(1), count_val'length); + elsif (ma_clk_edge = '1') then + count_val <= count_val + 1; + end if; + +end process; + + +-- +-- general purpose counter comparator +-- count_match set to one when count_val = count_top + +process +begin + + wait until rising_edge(clk); + + if (count_rst = '1') then + count_top_latched <= count_top; + end if; + +end process; + +count_match <= '1' when (count_val = count_top_latched) else '0'; + + +-- +-- sipo register + +process +begin + + wait until rising_edge(clk); + + if (ma_clk_edge = '1') then + sipo_val <= sipo_val(sipo_val'length - 2 downto 0) & miso; + end if; + +end process; + + +-- +-- sipo_latch edge detector +-- ma_clk_redge is not used as ma_clk may be disabled. +-- instead, clk is used for detecting sipo_latch edges + +process +begin + wait until rising_edge(clk); + sipo_latch_pre <= sipo_latch; +end process; + +sipo_latch_redge <= (not sipo_latch_pre) and sipo_latch; + + +-- +-- data conversion pipeline. ordering: +-- data from slave (latched at sipo_latch redge from sipo_val) +-- lsb_to_msb +-- gray_to_bin +-- extend_sign +-- latched to data +-- bin_to_sfixed (implemented in top) + +process +begin + wait until rising_edge(clk); + + if (rst = '1') then + curr_state <= CONV_WAIT_LATCH; + else + curr_state <= next_state; + end if; + +end process; + + +process(curr_state, sipo_latch_redge) +begin + + next_state <= curr_state; + + case curr_state is + + when CONV_WAIT_LATCH => + if (sipo_latch_redge = '1') then + next_state <= CONV_LSB_TO_MSB; + end if; + + when CONV_LSB_TO_MSB => + next_state <= CONV_GRAY_TO_BIN; + + when CONV_GRAY_TO_BIN => + next_state <= CONV_EXTEND_SIGN; + + when CONV_EXTEND_SIGN => + next_state <= CONV_DONE; + + when CONV_DONE => + next_state <= CONV_WAIT_LATCH; + + when others => + next_state <= CONV_ERR; + + end case; + +end process; + + +process +begin + wait until rising_edge(clk); + + latched_data <= latched_data; + conv_data <= conv_data; + + case curr_state is + + when CONV_WAIT_LATCH => + latched_data <= sipo_val and len_mask; + + when CONV_LSB_TO_MSB => + + when CONV_EXTEND_SIGN => + + when CONV_DONE => + conv_data <= signed_data; + + when others => + + end case; + +end process; + +data <= conv_data; + + +len_to_mask: work.absenc_pkg.len_to_mask +port map +( + len => len, + mask => len_mask +); + + +lsb_to_msb: work.absenc_pkg.lsb_to_msb +port map +( + en => lsb_to_msb_en, + data_len => len, + lsb_data => latched_data, + msb_data => msb_data +); + + +gray_to_bin: work.absenc_pkg.gray_to_bin +port map +( + en => gray_to_bin_en, + gray_data => msb_data, + bin_data => bin_data +); + + +extend_sign: work.absenc_pkg.extend_sign +port map +( + data_len => len, + data_in => bin_data, + data_out => signed_data, + len_mask => len_mask +); + + +-- +-- encoder master implementations + +gen_endat: if ENABLE_ENDAT = TRUE generate +master_endat: work.absenc_pkg.master_endat +generic map +( + CLK_FREQ => CLK_FREQ +) +port map +( + clk => clk, + rst => rst, + ma_clk_fedge => ma_clk_fedge, + ma_clk_redge => ma_clk_redge, + ma_clk_edge => ma_clk_edge_mux(ENC_MUX_ENDAT), + ma_clk_rst_en => ma_clk_rst_en_mux(ENC_MUX_ENDAT), + ma_clk_rst_val => ma_clk_rst_val_mux(ENC_MUX_ENDAT), + mosi => mosi_mux(ENC_MUX_ENDAT), + miso => miso, + gate => gate_mux(ENC_MUX_ENDAT), + len => len, + tm_match => tm_match, + tm_top => tm_top_mux(ENC_MUX_ENDAT), + count_top => count_top_mux(ENC_MUX_ENDAT), + count_match => count_match, + count_rst => count_rst_mux(ENC_MUX_ENDAT), + sipo_val => sipo_val, + sipo_latch => sipo_latch_mux(ENC_MUX_ENDAT), + gray_to_bin_en => gray_to_bin_en_mux(ENC_MUX_ENDAT), + lsb_to_msb_en => lsb_to_msb_en_mux(ENC_MUX_ENDAT) +); +end generate gen_endat; + + +gen_biss: if ENABLE_BISS = TRUE generate +master_biss: work.absenc_pkg.master_biss +generic map +( + CLK_FREQ => CLK_FREQ +) +port map +( + clk => clk, + rst => rst, + ma_clk_fedge => ma_clk_fedge, + ma_clk_redge => ma_clk_redge, + ma_clk_edge => ma_clk_edge_mux(ENC_MUX_BISS), + ma_clk_rst_en => ma_clk_rst_en_mux(ENC_MUX_BISS), + ma_clk_rst_val => ma_clk_rst_val_mux(ENC_MUX_BISS), + mosi => mosi_mux(ENC_MUX_BISS), + miso => miso, + gate => gate_mux(ENC_MUX_BISS), + len => len, + tm_match => tm_match, + tm_top => tm_top_mux(ENC_MUX_BISS), + count_top => count_top_mux(ENC_MUX_BISS), + count_match => count_match, + count_rst => count_rst_mux(ENC_MUX_BISS), + sipo_val => sipo_val, + sipo_latch => sipo_latch_mux(ENC_MUX_BISS), + gray_to_bin_en => gray_to_bin_en_mux(ENC_MUX_BISS), + lsb_to_msb_en => lsb_to_msb_en_mux(ENC_MUX_BISS) +); +end generate gen_biss; + + +gen_ssi: if ENABLE_SSI = TRUE generate +master_ssi: work.absenc_pkg.master_ssi +generic map +( + CLK_FREQ => CLK_FREQ +) +port map +( + clk => clk, + rst => rst, + ma_clk_fedge => ma_clk_fedge, + ma_clk_redge => ma_clk_redge, + ma_clk_edge => ma_clk_edge_mux(ENC_MUX_SSI), + ma_clk_rst_en => ma_clk_rst_en_mux(ENC_MUX_SSI), + ma_clk_rst_val => ma_clk_rst_val_mux(ENC_MUX_SSI), + mosi => mosi_mux(ENC_MUX_SSI), + miso => miso, + gate => gate_mux(ENC_MUX_SSI), + len => len, + tm_match => tm_match, + tm_top => tm_top_mux(ENC_MUX_SSI), + count_top => count_top_mux(ENC_MUX_SSI), + count_match => count_match, + count_rst => count_rst_mux(ENC_MUX_SSI), + sipo_val => sipo_val, + sipo_latch => sipo_latch_mux(ENC_MUX_SSI), + gray_to_bin_en => gray_to_bin_en_mux(ENC_MUX_SSI), + lsb_to_msb_en => lsb_to_msb_en_mux(ENC_MUX_SSI), + ssi_flags => ssi_flags, + ssi_delay_fdiv => ssi_delay_fdiv +); +end generate gen_ssi; + + +-- +-- enc_type multiplexer + +process +( + enc_type, + ma_clk_edge_mux, + ma_clk_rst_en_mux, + ma_clk_rst_val_mux, + mosi_mux, + gate_mux, + tm_top_mux, + count_rst_mux, + count_top_mux, + sipo_latch_mux, + gray_to_bin_en_mux, + lsb_to_msb_en_mux +) + +begin + + ma_clk_edge <= ma_clk_redge; + ma_clk_rst_en <= '0'; + ma_clk_rst_val <= '1'; + mosi <= '0'; + gate <= '0'; + tm_top <= to_unsigned(DEFAULT_TM_TOP, tm_top'length); + count_rst <= '0'; + count_top <= (others => '0'); + sipo_latch <= '0'; + gray_to_bin_en <= '0'; + lsb_to_msb_en <= '0'; + + for i in 0 to ENC_MUX_COUNT - 1 loop + if enc_mux_to_type(i) = enc_type then + ma_clk_edge <= ma_clk_edge_mux(i); + ma_clk_rst_en <= ma_clk_rst_en_mux(i); + ma_clk_rst_val <= ma_clk_rst_val_mux(i); + mosi <= mosi_mux(i); + gate <= gate_mux(i); + tm_top <= tm_top_mux(i); + count_rst <= count_rst_mux(i); + count_top <= count_top_mux(i); + sipo_latch <= sipo_latch_mux(i); + gray_to_bin_en <= gray_to_bin_en_mux(i); + lsb_to_msb_en <= lsb_to_msb_en_mux(i); + end if; + end loop; + +end process; + + +end absenc_master_rtl; diff --git a/testsuite/gna/issue1655/absenc_master_endat.vhdl b/testsuite/gna/issue1655/absenc_master_endat.vhdl new file mode 100644 index 000000000..2d0daf141 --- /dev/null +++ b/testsuite/gna/issue1655/absenc_master_endat.vhdl @@ -0,0 +1,314 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + +library work; + + +entity master_endat is + +generic +( + CLK_FREQ: integer +); +port +( + -- local clock + clk: in std_logic; + rst: in std_logic; + + -- master clock edges + ma_clk_fedge: in std_logic; + ma_clk_redge: in std_logic; + + -- the edge we are interested in + ma_clk_edge: out std_logic; + + -- master clock reset + -- if ma_clk_rst_en, use ma_clk_rst_level + ma_clk_rst_en: out std_logic; + ma_clk_rst_val: out std_logic; + + -- master out, slave in + mosi: out std_logic; + miso: in std_logic; + + -- gate to drive output (1 to drive it) + gate: out std_logic; + + -- desired data length + len: in unsigned; + + -- timeout counter + tm_match: in std_logic; + tm_top: out unsigned; + + -- general purpose counter + count_top: out unsigned; + count_match: in std_logic; + count_rst: out std_logic; + + -- sipo register + sipo_val: in std_logic_vector; + sipo_latch: out std_logic; + + -- enable data conversion stages + gray_to_bin_en: out std_logic; + lsb_to_msb_en: out std_logic +); + +end entity; + + +architecture absenc_master_endat_rtl of master_endat is + + +-- +-- default timeout value. standard says: 10 to 30 us + +constant TM_VAL: integer := work.absenc_pkg.us_to_count + (work.absenc_pkg.MASTER_DEFAULT_TM_US, CLK_FREQ, tm_top'length); + + +-- +-- main state machine + +type endat_state_t is +( + ENDAT_INIT, + + ENDAT_T0, + ENDAT_T1, + ENDAT_MODE, + ENDAT_T3, + ENDAT_T4, + + ENDAT_T5, + + ENDAT_START, + ENDAT_F1, + ENDAT_DATA, + + ENDAT_CRC5_FIRST, + ENDAT_CRC5_CONT, + + ENDAT_DONE +); + +constant ENDAT_TMOUT: endat_state_t := ENDAT_DONE; +constant ENDAT_ERR: endat_state_t := ENDAT_DONE; + +signal curr_state: endat_state_t; +signal next_state: endat_state_t; + + +-- +-- right shifted parallel in, serial out register +-- loaded values are in reverse order + +constant piso_ini: std_logic_vector := "111000"; +signal piso_val: std_logic_vector(piso_ini'length - 1 downto 0); +signal piso_load: std_logic; + + +begin + + +-- +-- state automaton + +process +begin + wait until rising_edge(clk); + + if (rst = '1') then + curr_state <= ENDAT_TMOUT; + elsif ((tm_match or ma_clk_fedge) = '1') then + curr_state <= next_state; + end if; + +end process; + + +process(curr_state, count_match, tm_match, miso) +begin + + next_state <= curr_state; + + case curr_state is + + when ENDAT_INIT => + next_state <= ENDAT_T0; + + when ENDAT_T0 => + next_state <= ENDAT_T1; + + when ENDAT_T1 => + next_state <= ENDAT_MODE; + + when ENDAT_MODE => + if (count_match = '1') then + next_state <= ENDAT_T3; + end if; + + when ENDAT_T3 => + next_state <= ENDAT_T4; + + when ENDAT_T4 => + next_state <= ENDAT_T5; + + when ENDAT_T5 => + next_state <= ENDAT_START; + + when ENDAT_START => + if (miso = '1') then + next_state <= ENDAT_F1; + elsif (tm_match = '1') then + next_state <= ENDAT_TMOUT; + end if; + + when ENDAT_F1 => + next_state <= ENDAT_DATA; + + when ENDAT_DATA => + if (count_match = '1') then + next_state <= ENDAT_CRC5_FIRST; + end if; + + when ENDAT_CRC5_FIRST => + next_state <= ENDAT_CRC5_CONT; + + when ENDAT_CRC5_CONT => + if (count_match = '1') then + next_state <= ENDAT_DONE; + end if; + + when ENDAT_DONE => + -- wait for at least one timeout + next_state <= ENDAT_INIT; + + when others => + next_state <= ENDAT_ERR; + + end case; + +end process; + + +process +begin + + wait until rising_edge(clk); + + ma_clk_rst_en <= '0'; + count_top <= (count_top'range => '0'); + count_rst <= '0'; + sipo_latch <= '0'; + gate <= '0'; + mosi <= '0'; + piso_load <= '0'; + + case curr_state is + + when ENDAT_INIT => + gate <= '1'; + + when ENDAT_T0 => + gate <= '1'; + + when ENDAT_T1 => + piso_load <= '1'; + gate <= '1'; + count_top <= to_unsigned(6, count_top'length); + count_rst <= '1'; + + when ENDAT_MODE => + mosi <= piso_val(0); + gate <= '1'; + + when ENDAT_T3 => + mosi <= '0'; + gate <= '1'; + + when ENDAT_T4 => + mosi <= '0'; + gate <= '1'; + + when ENDAT_T5 => + + when ENDAT_START => + + when ENDAT_F1 => + count_top <= len(count_top'range); + count_rst <= '1'; + + when ENDAT_DATA => + -- sent LSb first + + when ENDAT_CRC5_FIRST => + count_top <= to_unsigned(integer(5 - 1), count_top'length); + count_rst <= '1'; + sipo_latch <= '1'; + + when ENDAT_CRC5_CONT => + + when ENDAT_DONE => + ma_clk_rst_en <= '1'; + + when others => + + end case; + +end process; + + +-- +-- right shifted piso register +-- set at falling edge, sample by slave at redge + +process +begin + wait until rising_edge(clk); + + if (piso_load = '1') then + piso_val <= piso_ini; + elsif (ma_clk_fedge = '1') then + piso_val <= '0' & piso_val(piso_val'length - 1 downto 1); + end if; + +end process; + + +-- +-- clock reset or idle value + +ma_clk_rst_val <= '1'; + + +-- +-- timeout + +tm_top <= to_unsigned(TM_VAL, tm_top'length); + + +-- +-- gray to binary disabled + +gray_to_bin_en <= '0'; + + +-- +-- lsb to msb enabled + +lsb_to_msb_en <= '1'; + + +-- +-- use falling edge + +ma_clk_edge <= ma_clk_fedge; + + +end architecture; diff --git a/testsuite/gna/issue1655/absenc_pkg.vhdl b/testsuite/gna/issue1655/absenc_pkg.vhdl new file mode 100644 index 000000000..e5a439746 --- /dev/null +++ b/testsuite/gna/issue1655/absenc_pkg.vhdl @@ -0,0 +1,776 @@ +-- +-- package for absolute encoder slave and master +-- supported formats: ENDAT, BISS, SSI +-- +-- there is a bunch of code here. a typical user is +-- interested in the following 2 components: +-- absenc_pkg.slave +-- absenc_pkg.master +-- +-- refer to sim/common/main.vhd for usage. + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; +use ieee.math_real.all; + + +package absenc_pkg is + + +-- +-- encoder type identifiers + +constant ENC_TYPE_ENDAT: integer := 0; +constant ENC_TYPE_BISS: integer := 1; +constant ENC_TYPE_SSI: integer := 2; +constant ENC_TYPE_COUNT: integer := 3; + + +-- +-- encoder positions in mux + +function get_enc_mux_endat +( + enable_endat: boolean; + enable_biss: boolean; + enable_ssi: boolean +) +return integer; + + +function get_enc_mux_biss +( + enable_endat: boolean; + enable_biss: boolean; + enable_ssi: boolean +) +return integer; + + +function get_enc_mux_ssi +( + enable_endat: boolean; + enable_biss: boolean; + enable_ssi: boolean +) +return integer; + + +-- +-- count enabled encoders + +function get_enc_mux_count +( + enable_endat: boolean; + enable_biss: boolean; + enable_ssi: boolean +) +return integer; + + +-- +-- mux position to encoder type + +type enc_type_array_t is array(ENC_TYPE_COUNT - 1 downto 0) of integer; + +function gen_enc_mux_to_type +( + enable_endat: boolean; + enable_biss: boolean; + enable_ssi: boolean +) +return enc_type_array_t; + + +-- +-- compute integer length + +function integer_length +( + i: integer +) +return integer; + + +-- +-- microsecond to counter clocked by freq + +function us_to_count +( + us: integer; + freq: integer; + len: integer +) +return integer; + + +-- +-- default timeout us +-- conditions the lowset and highest ma_clk + +constant MAX_TM_US: integer := 100; +constant MASTER_DEFAULT_TM_US: integer := 60; +constant SLAVE_DEFAULT_TM_US: integer := 20; + + +-- +-- default ssi related values +-- no spy mode +-- binary coding +-- no special terminating pattern +-- no delay + +constant SSI_DEFAULT_FLAGS: std_logic_vector := "00000"; +constant SSI_DEFAULT_DELAY_FDIV: unsigned(0 downto 0) := to_unsigned(0, 1); + + +-- +-- encoder slave interface + +component slave +generic +( + -- local clock frequency + CLK_FREQ: integer; + + -- enable a specific implementation, or all by default + -- disabling unneeded implementations optimizes resources + ENABLE_ENDAT: boolean := TRUE; + ENABLE_BISS: boolean := TRUE; + ENABLE_SSI: boolean := TRUE +); +port +( + -- local clock and reset + clk: in std_logic; + rst: in std_logic; + + -- clock from master + ma_clk: in std_logic; + + -- master in, slave out + miso: out std_logic; + mosi: in std_logic; + + -- gate to drive output (1 to drive it). used in PEPU + -- first versions, set to open if not used. + gate: out std_logic; + + -- data sent to master. typically the position + -- important: use the smallest possible width, as + -- this is used to derive other resource sizes + data: in std_logic_vector; + + -- data length. typically the encoder resolution + -- important: use the smallest possible width, as + -- this is used to derive other resource sizes + len: in unsigned; + + -- the selected encoder type + enc_type: in integer; + + -- ssi specific flags + -- set to work.absenc_pkg.SSI_DEFAULT_FLAGS if unused + -- ssi_flags<0>: unused + -- ssi_flags<1>: 0 or 1 for binary or gray data coding + -- ssi_flags<2>: '.S' terminating pattern + -- ssi_flags<3>: 'ES' terminating pattern + -- ssi_flags<4>: 'OS' terminating pattern + ssi_flags: in std_logic_vector +); +end component; + + +component slave_endat +generic +( + CLK_FREQ: integer +); +port +( + -- local clock + clk: in std_logic; + rst: in std_logic; + + -- master clock edges + ma_clk_redge: in std_logic; + ma_clk_fedge: in std_logic; + + -- the edge we are interested in + ma_clk_edge: out std_logic; + + -- master in, slave out + miso: out std_logic; + mosi: in std_logic; + + -- gate to drive output (1 to drive it) + gate: out std_logic; + + -- actual data to send and length + data: in std_logic_vector; + len: in unsigned; + + -- timeout counter + tm_match: in std_logic; + tm_top: out unsigned; + + -- general purpose counter + count_top: out unsigned; + count_match: in std_logic; + count_rst: out std_logic; + + -- piso register + piso_rval: in std_logic_vector; + piso_lval: in std_logic_vector; + piso_ini: out std_logic_vector; + piso_load: out std_logic +); +end component; + + +component slave_biss +generic +( + CLK_FREQ: integer +); +port +( + -- local clock + clk: in std_logic; + rst: in std_logic; + + -- master clock edges + ma_clk_redge: in std_logic; + ma_clk_fedge: in std_logic; + + -- the edge we are interested in + ma_clk_edge: out std_logic; + + -- master in, slave out + miso: out std_logic; + mosi: in std_logic; + + -- gate to drive output (1 to drive it) + gate: out std_logic; + + -- actual data to send and length + data: in std_logic_vector; + len: in unsigned; + + -- timeout counter + tm_match: in std_logic; + tm_top: out unsigned; + + -- general purpose counter + count_top: out unsigned; + count_match: in std_logic; + count_rst: out std_logic; + + -- piso register + piso_rval: in std_logic_vector; + piso_lval: in std_logic_vector; + piso_ini: out std_logic_vector; + piso_load: out std_logic +); +end component; + + +component slave_ssi +generic +( + CLK_FREQ: integer +); +port +( + -- local clock + clk: in std_logic; + rst: in std_logic; + + -- master clock edges + ma_clk_redge: in std_logic; + ma_clk_fedge: in std_logic; + + -- the edge we are interested in + ma_clk_edge: out std_logic; + + -- master in, slave out + miso: out std_logic; + mosi: in std_logic; + + -- gate to drive output (1 to drive it) + gate: out std_logic; + + -- actual data to send and length + data: in std_logic_vector; + len: in unsigned; + + -- timeout counter + tm_match: in std_logic; + tm_top: out unsigned; + + -- general purpose counter + count_top: out unsigned; + count_match: in std_logic; + count_rst: out std_logic; + + -- piso register + piso_rval: in std_logic_vector; + piso_lval: in std_logic_vector; + piso_ini: out std_logic_vector; + piso_load: out std_logic; + + -- refer to absenc_pkg.slave for comments + ssi_flags: in std_logic_vector +); +end component; + + +-- +-- encoder master interface + +component master +generic +( + -- local clock frequency + CLK_FREQ: integer; + + -- enable a specific implementation, or all by default + -- disabling unneeded implementations optimizes resources + ENABLE_ENDAT: boolean := TRUE; + ENABLE_BISS: boolean := FALSE; + ENABLE_SSI: boolean := FALSE +); +port +( + -- local clock and reset + clk: in std_logic; + rst: in std_logic; + + -- ma_clk is the clock signal generated by the master + -- to the slave. its frequency is CLK_FREQ / ma_fdiv + ma_fdiv: in unsigned; + ma_clk: out std_logic; + + -- master out, slave in + mosi: out std_logic; + miso: in std_logic; + + -- gate to drive output (1 to drive it). used in PEPU + -- first versions, set to open if not used. + gate: out std_logic; + + -- data received from slave. typically the position + -- important: use the smallest possible width, as + -- this is used to derive other resource sizes + data: out std_logic_vector; + + -- data length. typically the encoder resolution + -- important: use the smallest possible width, as + -- this is used to derive other resource sizes + len: in unsigned; + + -- the selected encoder type + enc_type: in integer; + + -- ssi specific flags + -- set to work.absenc_pkg.SSI_DEFAULT_FLAGS if unused + -- ssi_flags<0>: ssi spy mode (ie. master without clock) + -- ssi_flags<1>: 0 or 1 for binary or gray data coding + -- ssi_flags<2>: '.S' terminating pattern + -- ssi_flags<3>: 'ES' terminating pattern + -- ssi_flags<4>: 'OS' terminating pattern + ssi_flags: in std_logic_vector; + + -- ssi frame delay. divides CLK_FREQ + -- set to work.absenc_pkg.SSI_DEFAULT_DELAY_FDIV if unsued + ssi_delay_fdiv: in unsigned +); +end component; + + +component master_endat +generic +( + CLK_FREQ: integer +); +port +( + -- local clock + clk: in std_logic; + rst: in std_logic; + + -- master clock edges + ma_clk_fedge: in std_logic; + ma_clk_redge: in std_logic; + + -- the edge we are interested in + ma_clk_edge: out std_logic; + + -- master clock reset + -- if ma_clk_rst_en, use ma_clk_rst_level + ma_clk_rst_en: out std_logic; + ma_clk_rst_val: out std_logic; + + -- master out, slave in + mosi: out std_logic; + miso: in std_logic; + + -- gate to drive output (1 to drive it) + gate: out std_logic; + + -- desired data length + len: in unsigned; + + -- timeout counter + tm_match: in std_logic; + tm_top: out unsigned; + + -- general purpose counter + count_top: out unsigned; + count_match: in std_logic; + count_rst: out std_logic; + + -- sipo register + sipo_val: in std_logic_vector; + sipo_latch: out std_logic; + + -- enable data conversion stages + gray_to_bin_en: out std_logic; + lsb_to_msb_en: out std_logic +); +end component; + + +component master_biss +generic +( + CLK_FREQ: integer +); +port +( + -- local clock + clk: in std_logic; + rst: in std_logic; + + -- master clock edges + ma_clk_fedge: in std_logic; + ma_clk_redge: in std_logic; + + -- the edge we are interested in + ma_clk_edge: out std_logic; + + -- master clock reset + -- if ma_clk_rst_en, use ma_clk_rst_level + ma_clk_rst_en: out std_logic; + ma_clk_rst_val: out std_logic; + + -- master out, slave in + mosi: out std_logic; + miso: in std_logic; + + -- gate to drive output (1 to drive it) + gate: out std_logic; + + -- desired data length + len: in unsigned; + + -- timeout counter + tm_match: in std_logic; + tm_top: out unsigned; + + -- general purpose counter + count_top: out unsigned; + count_match: in std_logic; + count_rst: out std_logic; + + -- sipo register + sipo_val: in std_logic_vector; + sipo_latch: out std_logic; + + -- enable data conversion stages + gray_to_bin_en: out std_logic; + lsb_to_msb_en: out std_logic +); +end component; + + +component master_ssi +generic +( + CLK_FREQ: integer +); +port +( + -- local clock + clk: in std_logic; + rst: in std_logic; + + -- master clock edges + ma_clk_fedge: in std_logic; + ma_clk_redge: in std_logic; + + -- the edge we are interested in + ma_clk_edge: out std_logic; + + -- master clock reset + -- if ma_clk_rst_en, use ma_clk_rst_level + ma_clk_rst_en: out std_logic; + ma_clk_rst_val: out std_logic; + + -- master out, slave in + mosi: out std_logic; + miso: in std_logic; + + -- gate to drive output (1 to drive it) + gate: out std_logic; + + -- desired data length + len: in unsigned; + + -- timeout counter + tm_match: in std_logic; + tm_top: out unsigned; + + -- general purpose counter + count_top: out unsigned; + count_match: in std_logic; + count_rst: out std_logic; + + -- sipo register + sipo_val: in std_logic_vector; + sipo_latch: out std_logic; + + -- enable data conversion stages + gray_to_bin_en: out std_logic; + lsb_to_msb_en: out std_logic; + + -- refer to absenc_pkg.master for comments + ssi_flags: in std_logic_vector; + ssi_delay_fdiv: in unsigned +); +end component; + + +component reader_hssl is +generic +( + CLK_FREQ: integer +); +port +( + -- local clock + clk: in std_logic; + rst: in std_logic; + + -- sender clock + sclk: in std_logic; + + -- sender out, reader in + sori: in std_logic; + + -- actual data to send and length + data: out std_logic_vector; + + -- configuration + len: in unsigned; + tm_gap: in unsigned +); + +end component; + + +-- +-- utilities + +component len_to_mask +port +( + len: in unsigned; + mask: out std_logic_vector +); +end component; + + +component lsb_to_msb +port +( + en: in std_logic; + data_len: in unsigned; + lsb_data: in std_logic_vector; + msb_data: out std_logic_vector +); +end component; + + +component bin_to_gray +port +( + en: in std_logic; + bin_data: in std_logic_vector; + gray_data: out std_logic_vector +); +end component; + + +component gray_to_bin +port +( + en: in std_logic; + gray_data: in std_logic_vector; + bin_data: out std_logic_vector +); +end component; + + +component extend_sign +port +( + data_len: in unsigned; + data_in: in std_logic_vector; + data_out: out std_logic_vector; + len_mask: in std_logic_vector +); +end component; + + +end package absenc_pkg; + + +package body absenc_pkg is + +-- +-- encoder positions in mux + +function get_enc_mux_endat +( + enable_endat: boolean; + enable_biss: boolean; + enable_ssi: boolean +) +return integer is +begin + return 0; +end get_enc_mux_endat; + + +function get_enc_mux_biss +( + enable_endat: boolean; + enable_biss: boolean; + enable_ssi: boolean +) +return integer is + variable i: integer; +begin + i := 0; + if enable_endat = TRUE then i := i + 1; end if; + return i; +end get_enc_mux_biss; + + +function get_enc_mux_ssi +( + enable_endat: boolean; + enable_biss: boolean; + enable_ssi: boolean +) +return integer is + variable i: integer; +begin + i := 0; + if enable_endat = TRUE then i := i + 1; end if; + if enable_biss = TRUE then i := i + 1; end if; + return i; +end get_enc_mux_ssi; + + +-- +-- count enabled encoders + +function get_enc_mux_count +( + enable_endat: boolean; + enable_biss: boolean; + enable_ssi: boolean +) +return integer is + variable n: integer; +begin + n := 0; + if enable_endat = TRUE then n := n + 1; end if; + if enable_biss = TRUE then n := n + 1; end if; + if enable_ssi = TRUE then n := n + 1; end if; + return n; +end get_enc_mux_count; + + +-- +-- mux position to encoder type + +function gen_enc_mux_to_type +( + enable_endat: boolean; + enable_biss: boolean; + enable_ssi: boolean +) +return enc_type_array_t is + variable a: enc_type_array_t; + variable i: integer; +begin + + i := 0; + + if enable_endat = TRUE then + a(i) := ENC_TYPE_ENDAT; + i := i + 1; + end if; + + if enable_biss = TRUE then + a(i) := ENC_TYPE_BISS; + i := i + 1; + end if; + + if enable_ssi = TRUE then + a(i) := ENC_TYPE_SSI; + i := i + 1; + end if; + + return a; +end gen_enc_mux_to_type; + + +-- +-- compute integer length + +function integer_length +( + i: integer +) +return integer is +begin + return integer(ceil(log2(real(i)))); +end integer_length; + + +-- +-- microsecond to counter clocked by freq + +function us_to_count +( + us: integer; + freq: integer; + len: integer +) +return integer is + variable count: integer; +begin + count := integer(ceil(real(us) * real(freq) / 1000000.0)); + assert (integer_length(count) <= len) report "tm too high" severity failure; + return count; +end us_to_count; + + +end package body absenc_pkg; diff --git a/testsuite/gna/issue1655/absenc_utils.vhdl b/testsuite/gna/issue1655/absenc_utils.vhdl new file mode 100644 index 000000000..92d881b38 --- /dev/null +++ b/testsuite/gna/issue1655/absenc_utils.vhdl @@ -0,0 +1,239 @@ +-- +-- create a mask with all length bit set + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + + +entity len_to_mask is +port +( + len: in unsigned; + mask: out std_logic_vector +); +end entity; + +architecture len_to_mask_rtl of len_to_mask is + +constant size: integer := mask'length; + +begin + +-- +-- result in a mask such as: +-- mask(mask'length - 1 downto len) = '0'; +-- mask(len - 1 downto 0) = '1'; + +process(len) +begin + for i in 2 to size loop + if i = to_integer(len) then + mask(size - 1 downto i) <= (others => '0'); + mask(i - 1 downto 0) <= (others => '1'); + end if; + end loop; +end process; + +end len_to_mask_rtl; + + +-- +-- lsb to msb conversion + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + + +entity lsb_to_msb is +port +( + en: in std_logic; + data_len: in unsigned; + lsb_data: in std_logic_vector; + msb_data: out std_logic_vector +); +end entity; + +architecture lsb_to_msb_rtl of lsb_to_msb is + +constant size: integer := lsb_data'length; + +begin + +-- +-- lsb_data: uuuuLxxxxM +-- msb_data: uuuuMxxxxL +-- where u undefined, x 0 or 1 + +process(en, lsb_data) +begin + + if (en = '1') then + + for i in 1 to size loop + if i = to_integer(data_len) then + msb_data(msb_data'length - 1 downto i) <= (others => '0'); + for j in 0 to (i - 1) loop + msb_data(j) <= lsb_data(i - 1 - j); + end loop; + exit ; + end if; + end loop; + + else + + msb_data <= lsb_data; + + end if; + +end process; + +end lsb_to_msb_rtl; + + +-- +-- binary to gray conversion + + +library ieee; +use ieee.std_logic_1164.all; + + +entity bin_to_gray is +port +( + -- enable conversion + en: in std_logic; + bin_data: in std_logic_vector; + gray_data: out std_logic_vector +); +end entity; + +architecture bin_to_gray_rtl of bin_to_gray is + +constant size: integer := bin_data'length; + +begin + +assert (bin_data'length = gray_data'length) +report "size differs" severity failure; + +process(en, bin_data) is +begin + if en = '1' then + for j in 0 to (size - 2) loop + gray_data(j) <= bin_data(j) xor bin_data(j + 1); + end loop; + gray_data(size - 1) <= bin_data(size - 1); + else + gray_data <= bin_data; + end if; +end process; + +end bin_to_gray_rtl; + + +-- +-- gray to binary conversion + + +library ieee; +use ieee.std_logic_1164.all; + + +entity gray_to_bin is +port +( + -- enable conversion + en: in std_logic; + gray_data: in std_logic_vector; + bin_data: out std_logic_vector +); +end entity; + +architecture gray_to_bin_rtl of gray_to_bin is + +constant size: integer := bin_data'length; + +signal tmp_data: std_logic_vector(bin_data'range); + +begin + +assert (bin_data'length = gray_data'length) +report "size differs" severity failure; + +process(en, gray_data, tmp_data) is +begin + if (en = '1') then + for j in 0 to (size - 2) loop + tmp_data(j) <= gray_data(j) xor tmp_data(j + 1); + end loop; + tmp_data(size - 1) <= gray_data(size - 1); + bin_data <= tmp_data; + else + bin_data <= gray_data; + end if; +end process; + +end gray_to_bin_rtl; + + +-- +-- extend sign + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.std_logic_unsigned.all; +use ieee.numeric_std.all; + + +entity extend_sign is +port +( + data_len: in unsigned; + data_in: in std_logic_vector; + data_out: out std_logic_vector; + len_mask: in std_logic_vector +); +end entity; + +architecture extend_sign_rtl of extend_sign is + +constant size: integer := data_in'length; +signal is_signed: std_logic; + +begin + +process(data_in, data_len) +begin + -- fixme: modelsim fails without this check + -- synthesis translate_off + is_signed <= '0'; + if data_len > 0 then + -- synthesis translate_on + + is_signed <= data_in(to_integer(data_len) - 1); + + -- synthesis translate_off + end if; + -- synthesis translate_on + +end process; + +process(is_signed, data_in) +begin + if (is_signed = '1') then + data_out <= data_in or not len_mask; + else + data_out <= data_in; + end if; +end process; + +end extend_sign_rtl; diff --git a/testsuite/gna/issue1655/endat_tb.vhdl b/testsuite/gna/issue1655/endat_tb.vhdl new file mode 100644 index 000000000..ecf4a1932 --- /dev/null +++ b/testsuite/gna/issue1655/endat_tb.vhdl @@ -0,0 +1,130 @@ +library IEEE; +use IEEE.std_logic_1164.all; +use IEEE.numeric_std.all; + +library work; + + +entity ENDAT_TB is +end ENDAT_TB; + + +architecture BEHAVIORAL of ENDAT_TB is + + -- Component declaration + component master + port ( -- local clock + clk: in std_logic; + rst: in std_logic; + + -- generated clock for slave + -- fdiv divides CLK_FREQ + ma_fdiv: in unsigned; + ma_clk: out std_logic; + + -- master out, slave in + mosi: out std_logic; + miso: in std_logic; + + -- gate to drive output (1 to drive it) + gate: out std_logic; + + -- data from slave, and data length + data: out std_logic_vector; + len: in unsigned; + + -- encoder type + enc_type: in integer; + + -- ssi specific control registers + ssi_flags: in std_logic_vector; + ssi_delay_fdiv: in unsigned + ); end component; + +-- Configuration +for u_master: master use entity work.master(absenc_master_rtl); + +-- Clock period +constant period: time := 10 ns; + +-- Signals +signal clk, rst, ma_clk, mosi, miso, gate, down, up: std_logic; +signal cnt_out: std_logic_vector (3 downto 0); +signal ma_fdiv, ssi_delay_fdiv, len: unsigned(31 downto 0); +signal enc_type: integer; +signal data, ssi_flags: std_logic_vector(31 downto 0); + +begin + + -- Instantiate counter... + u_master : master port map ( + clk => clk, + rst => rst, + + ma_fdiv => ma_fdiv, + ma_clk => ma_clk, + + mosi => mosi, + miso => miso, + + gate => gate, + + data => data, + len => len, + + enc_type => enc_type, + + ssi_flags => ssi_flags, + ssi_delay_fdiv => ssi_delay_fdiv + + ); + + -- Process for applying patterns + process + + -- Helper to perform one clock cycle... + procedure run_cycle is + begin + clk <= '0'; + wait for period / 2; + clk <= '1'; + wait for period / 2; + end procedure; + + begin + + -- Reset counter... + --down <= '1'; up <= '1'; + --run_cycle; + --assert cnt_out = "0000" report "Reset does not work"; + + -- Count up and keep state... + -- for n in 1 to 20 loop + -- down <= '0'; up <= '1'; + -- run_cycle; + -- assert cnt_out = std_logic_vector (to_unsigned (n mod 16, 4)) report "Counting up does not work"; + -- down <= '0'; up <= '0'; + -- run_cycle; + -- assert cnt_out = std_logic_vector (to_unsigned (n mod 16, 4)) report "Keeping the state does not work"; + -- end loop; + + -- Count down and keep state... + -- down <= '1'; up <= '1'; + -- run_cycle; + -- for n in 15 downto integer(-5) loop + -- down <= '1'; up <= '0'; + -- run_cycle; + -- assert cnt_out = std_logic_vector (to_unsigned (n mod 16, 4)) report "Counting down does not work"; + -- down <= '0'; up <= '0'; + -- run_cycle; + -- assert cnt_out = std_logic_vector (to_unsigned (n mod 16, 4)) report "Keeping the state does not work"; + -- end loop; + + -- Print a note & finish simulation... + -- assert false report "Simulation finished" severity note; + -- wait; + + end process; + +end BEHAVIORAL; + diff --git a/testsuite/gna/issue1655/repro.vhdl b/testsuite/gna/issue1655/repro.vhdl new file mode 100644 index 000000000..d8d2be2b6 --- /dev/null +++ b/testsuite/gna/issue1655/repro.vhdl @@ -0,0 +1,24 @@ +entity repro_ch is + generic (v : natural); + port (i : bit); +end; + +architecture behav of repro_ch is +begin + assert v > 5; +end; + +entity repro is +end; + +architecture behav of repro is + component comp is + port (i : bit); + end component; + + signal s : bit; + + for inst : comp use entity work.repro_ch(behav); +begin + inst: comp port map (i => s); +end; diff --git a/testsuite/gna/issue1655/repro1.vhdl b/testsuite/gna/issue1655/repro1.vhdl new file mode 100644 index 000000000..c33e1f52d --- /dev/null +++ b/testsuite/gna/issue1655/repro1.vhdl @@ -0,0 +1,25 @@ +entity repro1_ch is + generic (v : natural); + port (i : bit); +end; + +architecture behav of repro1_ch is +begin + assert v > 5; +end; + +entity repro1 is +end; + +architecture behav of repro1 is + component comp is + generic (v : natural); + port (i : bit); + end component; + + signal s : bit; + + for inst : comp use entity work.repro1_ch(behav); +begin + inst: comp port map (i => s); +end; diff --git a/testsuite/gna/issue1655/testsuite.sh b/testsuite/gna/issue1655/testsuite.sh new file mode 100755 index 000000000..b977e14e1 --- /dev/null +++ b/testsuite/gna/issue1655/testsuite.sh @@ -0,0 +1,16 @@ +#! /bin/sh + +. ../../testenv.sh + +GHDL_STD_FLAGS=-fsynopsys +analyze absenc_pkg.vhdl absenc_utils.vhdl absenc_master.vhdl absenc_master_endat.vhdl endat_tb.vhdl +elab_failure endat_tb + +analyze repro.vhdl +elab_failure repro + +analyze_failure repro1.vhdl + +clean + +echo "Test successful" |