Search code examples
vhdlsimulationxilinx-ise

Constructing a 20kbit bit_vector data from 16bit unsigned_vector


I'm very new in VHDL and having a problem about assigning values I guess.

Let's say that I've a module that get an 16 bit input signal noisein_mono for every positive edge of the clock source. What I want is to construct a 20 Kbit long bit vector from this 16-bit inputs. So I'm gonna perform random number tests on it FIPS_140-2

The code I end up with is shown below:

-- Entity Decleration
entity MonoTestModule is

Port ( clk                  : in    STD_LOGIC;
       rst                  : in    STD_LOGIC;
       start                : in    STD_LOGIC;
       noisein_mono         : in    STD_LOGIC_VECTOR (15 downto 0);
       running_mono         : out   STD_LOGIC;
       tok_mono             : out   STD_LOGIC     
     );

end MonoTestModule;

architecture Behavioral of MonoTestModule is

-- Signal to communication between processes.
signal enable_20k_bit_stream : std_logic;                                                       

begin
process (rst, clk, start, noisein_mono)
    variable count : integer := 0;                                                                                      
    variable twnty_k_bit_stream : bit_vector(19999 to 0);                                   
    begin
        if(start = '1') then                                                                            
            if (rising_edge(clk)) then                                                      
                count := count + 1;                                                         
                twnty_k_bit_stream := twnty_k_bit_stream or to_bitvector(noisein_mono);
                twnty_k_bit_stream := twnty_k_bit_stream sll 16;
            end if;

            if (rst = '1') then                                                             
                count := 0;                                                                     
                enable_20k_bit_stream <= '0';                                                                           
            end if;

            -- if count is reached to 1250, 20kbit is constructed.
            if(count = 1250) then                                                                   
                enable_20k_bit_stream <= '1';
            else                                                                                            
                enable_20k_bit_stream <= '0';
            end if; 
    end if;
end process;

I'm using Xilinx ISE 14.7. The compiler pops up error says Line 52: Unequal length arguments for operator "or". How can I solve this problem?

My best regards.


Solution

  • In simulation this would be two different run-time errors.

    There's actually two bounds mismatch errors, one for the "or" on two array values:

                twnty_k_bit_stream := twnty_k_bit_stream or
                                      to_bitvector(noisein_mono);
    

    And one for the assignment to twnty_k_bit_stream where the length doesn't match following an implicit subtype conversion.

    And that's because

      variable twnty_k_bit_stream : bit_vector(19999 to 0);
    

    that to should be downto. When the direction is wrong you'll end up with a null range (an array with no elements).

    See IEEE Std 1076-2008 9.2.2 Logical operators, para 3:

    If both operands are one-dimensional arrays, the operands shall be arrays of the same length, the operation is performed on matching elements of the arrays, and the result is an array with the same index range as the left operand. If one operand is a scalar and the other operand is a one-dimensional array, the operation is performed on the scalar operand with each element of the array operand. The result is an array with the same index range as the array operand.

    So uneven length arrays don't work.

    Also see 10.6.2.1 (Variable assignment), paras 5 and 7:

    For the execution of a variable assignment whose target is a variable name, the variable name and the expression are first evaluated. A check is then made that the value of the expression belongs to the subtype of the variable, except in the case of a variable that is of a composite type (in which case the assignment involves a subtype conversion). Finally, each subelement of the variable that is not forced is updated with the corresponding subelement of the expression. A design is erroneous if it depends on the order of evaluation of the target and source expressions of an assignment statement.

    ...
    An error occurs if the aforementioned subtype checks fail.

    And that error occurs if there isn't a corresponding element in both the target and right hand side expression of the variable assignment.

    5.3.2.2 Index constrains and discrete ranges, para 4:

    An array constraint of the first form is compatible with the type if, and only if, the constraint defined by each discrete range is compatible with the corresponding index subtype and the array element constraint, if present, is compatible with the element subtype of the type. If any of the discrete ranges defines a null range, any array thus constrained is a null array, having no elements. An array value satisfies an index constraint if at each index position the array value and the index constraint have the same index range. (Note, however, that assignment and certain other operations on arrays involve an implicit subtype conversion.)

    Fix both those things:

    begin
        process (rst, clk) -- , start, noisein_mono)  -- not needed
            variable count:  integer := 0;
            variable twnty_k_bit_stream:  bit_vector(19999 downto 0); -- was to 
        begin
            if start = '1' then
                if rising_edge(clk) then
                    count := count + 1;
                    -- twnty_k_bit_stream := twnty_k_bit_stream or
                    --                       to_bitvector(noisein_mono);
                    -- twnty_k_bit_stream := twnty_k_bit_stream sll 16;
    
                    twnty_k_bit_stream (twnty_k_bit_stream'LEFT downto noisein_mono'LENGTH) :=
                        twnty_k_bit_stream (twnty_k_bit_stream'LEFT - noisein_mono'LENGTH downto 0);
                    twnty_k_bit_stream (noisein_mono'RANGE) :=
                                        to_bitvector(noisein_mono);
                end if;
    

    noting I also fixed the sensitivity list and we get something that doesn't have a bounds check error. Instead of using an "or" this shifts then writes the lower 16 bits with noisein_mono.

    Adding a testbench:

    library ieee;
    use ieee.std_logic_1164.all;
    use ieee.numeric_std.all;
    
    entity monoblahblah_tb is
    end entity;
    
    architecture foo of monoblahblah_tb is
        signal clk:           std_logic := '0';
        signal rst:           std_logic;
        signal start:         std_logic;
        signal noisein_mono:  std_logic_vector (15 downto 0);
    
        signal running_mono:  std_logic;
        signal tok_mono:      std_logic;
    begin
    DUT:
        entity work.monotestmodule
            port map (
                clk => clk,
                rst => rst,
                start => start,
                noisein_mono => noisein_mono,
                running_mono => running_mono,
                tok_mono => tok_mono
            );
    CLOCK:
        process
        begin
            wait for 5 ns;
            clk <= not clk;
            if now > 12680 ns then
                wait;
            end if;
        end process;
    STIMULI:
        process
        begin
            wait for 6 ns;
            rst <= '0';
            start <= '0';
            noisein_mono <= (others => '0');
            wait for 10 ns;
            rst <= '1';
            wait for 10 ns;
            rst <= '0';
            wait for 100 ns;
            start <= '1';
            for i in 0 to 1249 loop -- 20,000 / 16
                noisein_mono <= 
                    std_logic_vector(to_unsigned(i, noisein_mono'length)) 
                      xor
                    x"dead";
                wait for 10 ns;
            end loop;
            wait;
        end process;
    end architecture;
    

    And we get:

    monblahblah_tb.png

    And if I had thought about it I would have XOR'd different values in consecutively, these values are simply unique from 0 to 1249 as binary XOR'd with x"DEAD". (It seemed outré to write a random number generator for a simple testbench, considering the state of twnty_k_bit_stream isn't displayed. The purpose is to show there are no bounds check failures.)

    So there were two semantic errors detectable at run time (or synthesis) and an incorrect sensitivity list.