Function result not locally static in case expression

Discussion in 'VHDL' started by a s, Nov 28, 2011.

  1. a s

    a s Guest

    Hello,

    I wrote the following helper function to decode a chip select for
    addressing a particular register in custom processor peripherals.

    function CE_decode(CE_bit,CE_width : integer) return
    std_logic_vector is
    variable v_tmp : std_logic_vector(0 to CE_width-1) := (others =>
    '0');
    begin
    v_tmp(CE_bit) := '1';
    return v_tmp;
    end function CE_decode;

    The problem is that Xilinx XST returns a warning:
    WARNING:HDLParsers:817 Choice CE_decode is not a locally static
    expression.

    I confirmed that the warning is actually redundant but I would still
    like to get rid of it.

    I am using the function in a context like this:

    C_NUM_REG : integer := 4;

    p_slv_reg_write : process(Bus2IP_Clk) is
    begin
    if rising_edge(Bus2IP_Clk) then
    case slv_reg_write_sel is
    when CE_decode(0, C_NUM_REG) =>
    slv_reg0 <= Bus2IP_Data;
    when CE_decode(1, C_NUM_REG) =>
    slv_reg1 <= Bus2IP_Data;
    when CE_decode(2, C_NUM_REG) =>
    slv_reg2 <= Bus2IP_Data;
    when CE_decode(3, C_NUM_REG) =>
    slv_reg3 <= Bus2IP_Data;
    when others => null;
    end case;
    end if;
    end process p_slv_reg_write;

    Instead of using the CE_decode function I can of course just write a
    static expression,
    but this gets hard to maintain and needs modification each time the
    number of registers
    in the peripheral changes. And it is hard to spot a mistake if there
    are 32 registers
    which CE is actually being decoded, e.g.
    "00000000000000000010000000000000".

    Can somebody please suggest how to work around the warning or suggest
    a better way
    in place of CE_decode function?

    Thank you!
     
    a s, Nov 28, 2011
    #1
    1. Advertisements

  2. You could use if-constructs like this:

    p_slv_reg_write : process(Bus2IP_Clk) is
    begin
    if rising_edge(Bus2IP_Clk) then
    if slv_reg_write_sel = CE_decode(0, C_NUM_REG) then
    slv_reg0 <= Bus2IP_Data;
    end if;
    if slv_reg_write_sel = CE_decode(1, C_NUM_REG) then
    slv_reg1 <= Bus2IP_Data;
    end if;
    if slv_reg_write_sel = CE_decode(2, C_NUM_REG) then
    slv_reg2 <= Bus2IP_Data;
    end if;
    if slv_reg_write_sel = CE_decode(3, C_NUM_REG) then
    slv_reg3 <= Bus2IP_Data;
    end if;
    end if;
    end process p_slv_reg_write;

    Note that 'elsif' has intentionally not been used to avoid priority
    decoders and because CE_decode() already guarantees non-overlapping
    conditions.

    If you put slv_regX into an array, you can even use a for loop instead
    of explicitly writing all those if's.

    Enrik
     
    Enrik Berkhan, Nov 28, 2011
    #2
    1. Advertisements

  3. a s

    Bart Fox Guest

    Can somebody please suggest how to work around the warning or suggest
    Try to define and use some constants:

    constant ce_slv_reg0_c : std_logic_vector := CE_decode(0, C_NUM_REG);
    constant ce_slv_reg1_c : std_logic_vector := CE_decode(1, C_NUM_REG);
    constant ce_slv_reg2_c : std_logic_vector := CE_decode(2, C_NUM_REG);
    constant ce_slv_reg3_c : std_logic_vector := CE_decode(3, C_NUM_REG);

    They should be static enough for VHDL.

    regards,
    Bart
     
    Bart Fox, Nov 28, 2011
    #3
  4. a s

    valtih1978 Guest


    Normally, breaking vec := (CE_BIT => '1', others => '0') into your code
    solves the problem. I would first ensure that args are constants:

    constant CE_bit,CE_width : integer
     
    valtih1978, Nov 28, 2011
    #4
  5. ....
    .... and using it as
    Bart Fox has one good solution : use the CE_Decode function to create
    your static expressions (constants) ... but another way is to realise the
    purpose of the case statement is to evaluate once, and simply compare
    against a static list (effectively a list of constants.

    So another way is to write a new function

    subtype reg_addr is natural range 0 to C_NUM_REG;
    -- Use a subtype here so synthesis doesn't use 32-bit arithmetic!

    function select_reg(selector : ) return reg_addr is
    -- a simple exercise...

    case select_reg(slv_reg_write_sel) is
    when 0 => slv_reg0 <= Bus2IP_Data;
    when 1 => slv_reg1 <= Bus2IP_Data;
    when 2 => slv_reg2 <= Bus2IP_Data;
    when 3 => slv_reg3 <= Bus2IP_Data;
    when others => null;
    end case;

    -- Brian
     
    Brian Drummond, Nov 28, 2011
    #5
  6. a s

    a s Guest

    Thank you all! These suggestions above are all very interesting.

    I decided to go with Brian's suggestions and implemented the
    following function. I checked it in simulation and synthesis
    and the function passed without warnings. Anyway, I would
    appreciate to receive a comment if someone spots a weak point.

    function select_reg(selector : std_logic_vector;
    C_NUM_REG : integer)
    return natural is
    subtype reg_addr_t is natural range 0 to C_NUM_REG-1;
    variable reg_addr : reg_addr_t := 0;
    begin
    for i in 0 to C_NUM_REG-1 loop
    if selector(i) = '1' then
    reg_addr := i;
    exit;
    end if;
    end loop;
    return reg_addr;
    end function select_reg;

    Thanks again!
     
    a s, Nov 29, 2011
    #6
  7. a s

    Andy Guest

    Why are you passing c_num_reg to the function? The 'range attribute
    from the selector argument will give you what you want:

    function select_reg(selector : std_logic_vector) return natural is
    variable reg_addr : natural range selector'range;
    begin
    for i in selector'range loop
    if selector(i) = '1' then
    reg_addr := i;
    exit;
    end if;
    end loop;
    return reg_addr;
    end function select_reg;

    Note that the function returns the same value whether no bits or set
    or selector'low is set. May not be a problem in your application.

    If you need to encode only a slice of a vector, then call the function
    with the slice instead of the whole vector.

    Andy
     
    Andy, Nov 29, 2011
    #7
  8. Selects are a stubborn problem.
    My last looked something like:

    type cs_t is (ram, rom, led, keys, io);
    type cs_bits_t is array (cs_t) of std_ulogic;
    type cs_bytes_t is array (cs_t) of byte_t;
    signal cs_s : cs_t;
    signal cs_bits_s : cs_bits_t;
    signal rdy_bits_s : cs_bits_t;
    signal data_bytes_s : cs_bytes_t;
    -- some limits record
    -- some table of adr limit records:
    type cs_table_t is array (cs_t) of cs_limits_t;
    function cs_all return cs_bits_t is ...for loop for all selects
    cs_s <= cs_now(cs_bits_s);
    d <= data_bytes_s(cs_s);


    -- Mike Treseler
     
    Mike Treseler, Nov 30, 2011
    #8
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.