![]() |
Constant conversion (natural to std_logic_vector)
I am in a situation where I have to increase an address bus width in
bit of re-usable code. In a package there is a list of constants which are used in the address decode constant abus_width : natural := 5; constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) := "00001"; constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) := "00010"; etc. I've now increased abus_width by 2 and now all the constant literals need updating because they are the wrong width. I thought I would try to work out a way of specifying the constants so that they would grow with abus_width so that if we ever had to do this again it would automatically work e.g. library ieee; use ieee.std_logic_arith.all; constant abus_width : natural := 7; constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) := conv_std_logic_vector(16#01#,abus_width); constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) := conv_std_logic_vector(16#02#,abus_width); However I now get the following warning "Case choice must be a locally static expression." in the Case statements which use these constants. But it IS locally static isnt it? It's a constant, it's in a package, that package is referenced... Anyone ever done anything like this before or got a better technique? Regards Alex Holland |
Re: Constant conversion (natural to std_logic_vector)
I cannot use VHDL 93's HEX literal ( X'"AA" ) because my bus is not a
multiple of 4-bits wide. |
Re: Constant conversion (natural to std_logic_vector)
a1_nocrap_exh@hotmail.com wrote:
> However I now get the following warning "Case choice must be a locally > static expression." in the Case statements which use these constants. > But it IS locally static isnt it? It's a constant, it's in a package, > that package is referenced... Sorry, that's the way it is. Use an if/elsif/elsif http://groups.google.com/groups/sear...c+short+answer -- Mike Treseler |
Re: Constant conversion (natural to std_logic_vector)
> Sorry, that's the way it is.
> Use an if/elsif/elsif > http://groups.google.com/groups/sear...c+short+answer Thanks for the link. But in this situation I am not doing anything fancy. These ARE constants. It should work. > A case expression is limited to operands that are scalar But they are scalar, that is my point. If I store my constants as naturals, and convert my std_logic_vector signal to integer EVERYTHING works e.g. constant REGISTER_A : natural := 1; constant REGISTER_B : natural :=2; case conv_integer(unsigned(addr)) is when REGISTER_A => when REGISTER_B => when OTHERS => end case; So I dont understand why I cannot store my constants as std_logic_vectors that are pre-converted from naturals? constant abus_width := 5; constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) := conv_std_logic_vector(16#01#, abus_width); constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) := conv_std_logic_vector(16#02#, abus_width); case addr is when REGISTER_A => when REGISTER_B => when OTHERS => end case; I would switch to storing them as naturals, but the code containing the case statement has already been to silicon, dont really want to change anything in that file if I can help it. I think I *will* find the syntax to make this warning go away. Anyone? Alex Holland |
Re: Constant conversion (natural to std_logic_vector)
You may find it easier if you use subtypes: e.g.
use ieee.numeric_std.all; .. . . . . subtype abus_type_t is std_logic_vector(7 downto 0); .. . . . . constant abus_sig_s : abus_type_t := std_logic_vector(to_unsigned(2, abus_type_t'length)); Then you only have to change the subtype dimensions in a single place if your bus gets resized Regards, Charles |
Re: Constant conversion (natural to std_logic_vector)
I am using subtypes in my code (not in my example) it doesnt help.
|
Re: Constant conversion (natural to std_logic_vector)
>use ieee.numeric_std.all;
> . . . . . > subtype abus_type_t is std_logic_vector(7 downto 0); > . . . . . > constant abus_sig_s : abus_type_t := > std_logic_vector(to_unsigned(2, abus_type_t'length)); > > Then you only have to change the subtype dimensions in a single place if > your bus gets resized Not that it matters but you dont have to use subtypes to only need to change dimensions in a single place, look at my example I posted earlier (or below), you change one constant "abus_width" and voila. constant abus_width : natural := 7; constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) := conv_std_logic_vector(16#01#,abus_width); constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) := conv_std_logic_vector(16#01#,abus_width); I've used std_logic_arith rather than numeric_std... I wonder if that helps? I doubt it. Charles, can you use a constant defined your way in a CASE statement? Alex Holland |
Re: Constant conversion (natural to std_logic_vector)
a1_nocrap_exh@hotmail.com wrote:
>>Sorry, that's the way it is. >>Use an if/elsif/elsif >>http://groups.google.com/groups/sear...c+short+answer > > Thanks for the link. But in this situation I am not doing anything > fancy. These ARE constants. It should work. It probably should, but it doesn't and this is a FAQ. -- Mike Treseler |
Re: Constant conversion (natural to std_logic_vector)
Alex,
a1_nocrap_exh@hotmail.com writes: > I thought I would try to work out a way of specifying the constants so > that they would grow with abus_width so that if we ever had to do this > again it would automatically work e.g. > > library ieee; > use ieee.std_logic_arith.all; > > constant abus_width : natural := 7; > constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) := > conv_std_logic_vector(16#01#,abus_width); > constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) := > conv_std_logic_vector(16#02#,abus_width); You can either extend your registers widths to a multiple of 4 and use the VHDL'93 syntax. In the case-statement you would have to extend the case-expression to the same width and be done. Chances are that Synthesis will strip the unused bits anyway. Or, as someone else already noted, you could use if-elsif*-else chains. Synthesis tools are also pretty good at generating the expected logic in cases like this. Alternatively you could assign the registers like this constant REGISTER_A : std_logic_vector(abus_width-1 downto 0) := (0 => '1', others => '0'); constant REGISTER_B : std_logic_vector(abus_width-1 downto 0) := (1 => '1', others => '0'); (Actually I am not absolutely sure that this last assignment works as expected. You'd have to try that yourself.) > But it IS locally static isnt it? It's a constant, it's in a package, > that package is referenced... Not quite. Locally static expressions must be fixed at compile time. Functions, such as `conv_std_logic_vector', defined in package bodies are not. You could compile a different package body for std_logic_arith with completely different function definitions and be screwed. Best regards, Marcus |
Re: Constant conversion (natural to std_logic_vector)
Hi Marcus,
Thanks for the reply, good suggestion for your alternative > > But it IS locally static isnt it? It's a constant, it's in a package, > > that package is referenced... > > Not quite. Locally static expressions must be fixed at compile > time. Functions, such as `conv_std_logic_vector', defined in package > bodies are not. You could compile a different package body for > std_logic_arith with completely different function definitions and be > screwed. Ah, yes now I understand. It ISNT the case statement which needs to resolve at compile time it's the WHEN operator. That is why I can define my constants as naturals and convert my case argument to an integer and it compiles fine e.g. constant REGISTER_A : natural := 1; constant REGISTER_B : natural := 2; case conv_integer(unsigned(addr)) is when REGISTER_A => when REGISTER_B => when OTHERS => end case; Makes sense now, dont like it, but it makes sense. Alex |
| All times are GMT. The time now is 08:33 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.