3
\$\begingroup\$

Is it possible to generate different set of constants in a vhdl preamble using a kind of "if generate statement"?

For example I was trying:

library ieee; use ieee.std_logic_1164.all;

entity my_entity is
   generic(flag : integer);
   port(x : in std_logic_vector(31 downto 0);
        y : out std_logic_vector(31 downto 0));
end entity my_entity;

architecture arch of my_entity is

   flag_true : if flag /= 0 generate
      constant K1 : integer := 32;
   end generate flag_true;

   flag_false : if flag = 0 generate
      constant K2 : integer 32;
   end generate flag_false;

begin

   flag_true_conc : if flag /= 0 generate
      y(K1 - 1 downto 0) <= not x(K1 - 1 downto 0);
   end generate flag_true_conc;

   flag_false_conc : if flag = 0 generate
      y(K2 - 1 downto 0) <= x(K2 - 2 downto 0) & x(K2 - 1);
   end generate flag_false_conc;

end architecture arch; 

But when I run the ncvhdl for the syntax check it returns me loads of errors:

ncvhdl: 14.20-s029: (c) Copyright 1995-2016 Cadence Design Systems, Inc.
architecture arch of my_entity is
                                  |
ncvhdl_p: *E,EXPBEG (entity_test.vhd,10|34): expecting the reserved word 'BEGIN' [1.2].
      constant K1 : integer := 32;
                                   |
ncvhdl_p: *E,EXPBEG (entity_test.vhd,13|35): expecting the reserved word 'BEGIN' [9.7].
      constant K2 : integer 32;
                            |
ncvhdl_p: *E,EXPSMI (entity_test.vhd,17|28): expecting a semicolon (';') [4.3.1.1].
      constant K2 : integer 32;
                                |
ncvhdl_p: *E,EXPBEG (entity_test.vhd,17|32): expecting the reserved word 'BEGIN' [9.7].
   end generate flag_false;
                            |
ncvhdl_p: *E,EXPEND (entity_test.vhd,18|28): expecting the reserved word 'END' [1.2].

I don't think except for the if generate in the preamble I've done something weird.

Assuming I made you understand what I'm trying to achieve is it possible to do that?

(You have to imagine the situation where in the preamble I want to generate different set of constants based on some kind of flag or condition).

\$\endgroup\$
1
  • \$\begingroup\$ A generate statement is elaborated into a block statement (IEEE Std 1076-2008 14.5.3) and is a separate declarative region (12.1) - the constants wouldn't be visible outside their scope (12.2). VHDL syntax is specified in an Extended Backus Naur Form and semantics specified by the standard's descriptive text. If you can't trace what you want to do through the BNF (Appendix C Syntax summary) it's not possible without regard to semantic restriction. VHDL is a formal notation. \$\endgroup\$
    – user8352
    Commented Jun 2, 2016 at 10:04

3 Answers 3

4
\$\begingroup\$

You can't put statements in (formally there is no "preamble" so) the declarative region.

However you can wrap statements and their associated declarations in a block statement. This keeps the declarations and their statements closely scoped together, avoiding bugs where statements are associated with the wrong declarations (which would be possible in your example.

So do that :

architecture arch of my_entity is
-- declarative region

begin
-- concurrent statement region

   flag_true : if flag /= 0 generate
      -- a block statement
      true_block : block
         constant K1 : integer := 32;
      begin
         y(K1 - 1 downto 0) <= not x(K1 - 1 downto 0);
      end;
   end generate flag_true;

end architecture arch; 

And an observation :

if /=0 means true there is probably something very wrong with the design : you have true booleans in VHDL, you don't have to obscure the meaning so you can do everything with an integer. Then you can write

if flag generate ...
\$\endgroup\$
1
  • \$\begingroup\$ Never used block statements before, I'm having a look. About the observation, it was just a minimal example it's not an actual design. \$\endgroup\$ Commented Jun 2, 2016 at 10:11
2
\$\begingroup\$

I would recommend using a function for initializing constants. So this:

flag_true : if flag /= 0 generate
  constant K1 : integer := 32;
end generate flag_true;

...could be turned into this:

function flag_true(flag : integer) return integer
is begin
    if flag /= 0 then
        return 32;
    else
        return 0; -- Or some other default
    end if;
end function;

constant K1 : integer := flag_true(flag);
\$\endgroup\$
1
  • \$\begingroup\$ This may need to be declared in a package, since I don't think you can declare a function in the preamble to an entity. \$\endgroup\$ Commented Sep 12, 2019 at 23:22
0
\$\begingroup\$

I would have added this as a comment to Brian's answer, but I wanted to include code and make it readable.

With generate statements, you don't need a block statement. Starting in VHDL-1993, generate statements can have declarative regions. For example:

architecture arch of my_entity is
-- declarative region

begin
-- concurrent statement region

   flag_true : if flag /= 0 generate
      -- declarative region (scope limited to generate)
      constant K1 : integer := 32;
   begin
      y(K1 - 1 downto 0) <= not x(K1 - 1 downto 0);
   end generate flag_true;

end architecture arch;

Indeed, Brian's example requires VHDL '93 or later with the use of end architecture .... From The Designer's Guide to VHDL:

In VHDL-87, the keyword entity may not be included at the end of an entity declaration, and the keyword architecture may not be included at the end of an architecture body.

And based on the OP, the fact that they are using end entity ... and end architecure ..., they can use the generate declarative region.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.