From cedac9ece9eb113691d614d480256de7b7b65332 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Sun, 3 Jul 2016 17:30:01 +0200 Subject: Add testcase for bug24065 --- testsuite/gna/bug24065/cic_up.vhd | 201 ++++++++++++++++++++++++++++++++++++ testsuite/gna/bug24065/testsuite.sh | 9 ++ 2 files changed, 210 insertions(+) create mode 100644 testsuite/gna/bug24065/cic_up.vhd create mode 100755 testsuite/gna/bug24065/testsuite.sh diff --git a/testsuite/gna/bug24065/cic_up.vhd b/testsuite/gna/bug24065/cic_up.vhd new file mode 100644 index 000000000..a07c48396 --- /dev/null +++ b/testsuite/gna/bug24065/cic_up.vhd @@ -0,0 +1,201 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +entity cic_up is + generic( + num_bits : natural := 16; -- How many bits in our incoming data? + num_stages : natural := 3; -- How many stages in the CIC? (N) + resamp : natural := 32; -- By what factor are we changing our data rate? (R) + diff_dly : natural := 1; -- The differential delay (M) + out_rate : natural := 8); -- Number of clocks per output sample + -- Must be a power of two + port( + clk_i : in std_logic; + rst_i : in std_logic; + -- Input ports + data_i : in std_logic_vector(num_bits-1 downto 0); + valid_i : in std_logic; + -- Output samples + data_o : out std_logic_vector; + valid_o : out std_logic); +end entity cic_up; + +architecture behavior of cic_up is + ----------------------------------------------------------------------------- + -- Functions + ----------------------------------------------------------------------------- + function log(b,n: positive) return natural is + variable temp : natural := 1; + variable answer : natural := 0; + begin + while temp < n loop + answer := answer + 1; + temp := temp * b; + end loop; + return answer; + end function log; + + ----------------------------------------------------------------------------- + function signed_add(l,r: std_logic_vector) return std_logic_vector is + variable resized_r : signed(r'high+1 downto r'low); + begin + resized_r := resize(signed(r), r'length+1); + return std_logic_vector(signed(l) + resized_r); + end function signed_add; + + ----------------------------------------------------------------------------- + function signed_sub(l,r: std_logic_vector) return std_logic_vector is + variable resized_r : signed(r'high+1 downto r'low); + begin + resized_r := resize(signed(r), r'length+1); + return std_logic_vector(signed(l) - resized_r); + end function signed_sub; + + ----------------------------------------------------------------------------- + impure function input_bits return natural is + variable a, b, c : integer; + begin + a := (num_bits + 1); + b := (num_stages - 2)*(log(2,resamp)); + c := (num_stages - 1)*(log(2,diff_dly)); + return a + b + c; + end function input_bits; + + ----------------------------------------------------------------------------- + impure function output_bits return natural is + variable a, b, c : integer; + begin + a := (num_bits + 0); + b := (num_stages - 1)*(log(2,resamp)); + c := (num_stages - 0)*(log(2,diff_dly)); + return a + b + c; + end function output_bits; + + ----------------------------------------------------------------------------- + -- Types, subtypes, and constants + ----------------------------------------------------------------------------- + -- Bit growth constants + constant direction : string := "up"; + subtype int_i_range is natural range input_bits-1 downto 0; + subtype int_o_range is natural range output_bits-1 downto 0; + subtype comb_sum_range is natural range num_bits downto 0; + subtype count_range is natural range log(2,out_rate)-1 downto 0; + -- Array type for differential delay + subtype word is std_logic_vector(num_bits-1 downto 0); + type comb_reg_type is array (integer range <>) of word; + ----------------------------------------------------------------------------- + -- Signals + ----------------------------------------------------------------------------- + signal comb_reg : comb_reg_type(0 to diff_dly-1) := (others => (others => '0')); + signal comb_sum : std_logic_vector(comb_sum_range):= (others => '0'); + signal int_in : std_logic_vector(int_i_range); + signal int_sum : signed (int_o_range) := (others => '0'); + signal int_en : std_logic; + signal count : unsigned(count_range) := (others => '0'); + signal c_dly : std_logic; +begin + ----------------------------------------------------------------------------- + -- Map outputs + ----------------------------------------------------------------------------- + data_o <= std_logic_vector(int_sum); + + ----------------------------------------------------------------------------- + -- Comb (derivative) section + ----------------------------------------------------------------------------- + comb_proc : process(clk_i) + begin + if rising_edge(clk_i) then + -- Comb registers + if rst_i = '1' then + comb_reg <= (others => (others => '0')); + comb_sum <= (others => '0'); + elsif valid_i = '1' then + comb_reg <= data_i & comb_reg(0 to comb_reg'high-1); + comb_sum <= signed_sub(data_i, comb_reg(comb_reg'high)); + end if; + end if; + end process comb_proc; + + ----------------------------------------------------------------------------- + -- Integrator section + ----------------------------------------------------------------------------- + int_proc : process(clk_i) + begin + if rising_edge(clk_i) then + -- Integrator registers + if rst_i = '1' then + int_sum <= (others => '0'); + else + if num_stages = 1 then + -- The connection between the ints and the combs is determined + -- by the generic out_rate. This is indirectly controlled by + -- the top bit in count, which counts to out_rate. + if out_rate = 1 then + valid_o <= '1'; + else + valid_o <= count(count'left) and not c_dly; + end if; + + -- The size of the first integrator register could be a different + -- size from the last stage of the combs. This should make up + -- that difference. + if valid_i = '1' then + int_sum <= resize(int_sum + signed(comb_sum), int_sum'length); + end if; + + -- Every other stage of the integrators is controlled by the enable + -- signal of the previous stage + elsif int_en = '1' then + int_sum <= int_sum + signed(int_in); + valid_o <= '1'; + else + valid_o <= '0'; + end if; + end if; + end if; + end process int_proc; + + ----------------------------------------------------------------------------- + -- Recursive instantiation and termination + ----------------------------------------------------------------------------- + cic_gen : if num_stages > 1 generate + begin + cic_inst : entity work.cic_up + generic map( + num_bits => num_bits+1, + num_stages => num_stages-1, + diff_dly => diff_dly, + resamp => resamp, + out_rate => out_rate) + port map( + clk_i => clk_i, + rst_i => rst_i, + -- Input ports + data_i => comb_sum, + valid_i => valid_i, + -- Output samples + data_o => int_in, + valid_o => int_en); + end generate cic_gen; + + valid_gen : if num_stages = 1 generate + begin + vary_valid_o : if out_rate /= 1 generate + begin + valid_o_proc : process(clk_i) + begin + if rising_edge(clk_i) then + if rst_i = '1' then + count <= (others => '0'); + c_dly <= '0'; + else + count <= count + 1; + c_dly <= count(count'left); + end if; + end if; + end process valid_o_proc; + end generate vary_valid_o; + end generate valid_gen; + +end architecture behavior; diff --git a/testsuite/gna/bug24065/testsuite.sh b/testsuite/gna/bug24065/testsuite.sh new file mode 100755 index 000000000..d2a092883 --- /dev/null +++ b/testsuite/gna/bug24065/testsuite.sh @@ -0,0 +1,9 @@ +#! /bin/sh + +. ../../testenv.sh + +analyze cic_up.vhd + +clean + +echo "Test successful" -- cgit v1.2.3