diff options
Diffstat (limited to 'testsuite/gna')
-rw-r--r-- | testsuite/gna/bug24065/cic_up.vhd | 201 | ||||
-rwxr-xr-x | testsuite/gna/bug24065/testsuite.sh | 9 |
2 files changed, 210 insertions, 0 deletions
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" |