Simulation Constant

B

Brad Smallridge

Hello,

What I would like to do is this:

if( sim=true ) then
constant mem_size : integer := 128;
else
constant mem_size : integer := 2**18;
end if;

But, of course, VHDL doesn't let me
use "if" in the declaration part before
the "begin" keyword. What's a way to do
this?

Brad Smallridge
AiVision
 
D

Daniel Koethe

Hello Brad,
a solution is to provide this costant mem_size with a generic signal.
For Synthesis set the defaul value to 2**18 and overide this generic in
the modelsim simulation.

ENTITY ram_block IS
GENERIC (
mem_size : positive := 2**18
);
PORT (
....
);

Modelsim:
vsim -g/top/ram_block/mem_size=128 top

Second you can a workaround. Define two constants sim_true and sim_false
as integer instead of one boolean and change your code to:

sim=true -> sim_true=1, sim_false=0
sim=false -> sim_true=0, sim_false=1

constant mem_size : integer := 128*sim_true+sim_false*2**18;

Daniel
 
J

Jim Lewis

Brad,
I do a variation of the 2nd method for counters in one of my designs:

entity ClkPrescale is
generic (
SCALE_FACTOR : integer := 0 -- value 1 runs Pulse1ms faster 10,000 faster
) ;
port (
Clk : In std_logic ;
nReset : In std_logic ;

. . .

Pulse1ms : Out std_logic
);
end ClkPrescale ;

architecture RTL of ClkPrescale is

constant CLOCK_FREQ : integer := 50E6 ; -- 50 MHz
constant Pulse1MS_FREQ : integer := 1E3 ; -- 1 KHz
constant CNT_1MS_INIT : integer := CLOCK_FREQ/(Pulse1MS_FREQ * (1+9999*SCALE_FACTOR));
constant CNT_1MS_WIDTH : integer := 16 ;


In your case, simplifying by using a single integer generic:
constant mem_size : integer := 2**7 * (sim_false*2**18) ;
-- or
constant mem_size : integer := 2**7 * ((1 - sim_true)*2**18) ;

I haven't checked Synopsys lately, but in the past they only
supported integer generics. So I have always limited myself
to only integer generics anyway.

Cheers,
Jim
 
K

kennheinrich

Brad,
I do a variation of the 2nd method for counters in one of my designs:

entity ClkPrescale is
generic (
SCALE_FACTOR : integer := 0 -- value 1 runs Pulse1ms faster 10,000 faster
) ;
port (
Clk : In std_logic ;
nReset : In std_logic ;

. . .

Pulse1ms : Out std_logic
);
end ClkPrescale ;

architecture RTL of ClkPrescale is

constant CLOCK_FREQ : integer := 50E6 ; -- 50 MHz
constant Pulse1MS_FREQ : integer := 1E3 ; -- 1 KHz
constant CNT_1MS_INIT : integer := CLOCK_FREQ/(Pulse1MS_FREQ * (1+9999*SCALE_FACTOR));
constant CNT_1MS_WIDTH : integer := 16 ;

In your case, simplifying by using a single integer generic:
constant mem_size : integer := 2**7 * (sim_false*2**18) ;
-- or
constant mem_size : integer := 2**7 * ((1 - sim_true)*2**18) ;

I haven't checked Synopsys lately, but in the past they only
supported integer generics. So I have always limited myself
to only integer generics anyway.

Cheers,
Jim

In the general case, you can probably also try something based on
classical mathematics and curve-fitting through polynomials: with
generic values g in the set {1,2,3,...,N} that you want to yield a
value V(g) in {V1,V2,V3,...,VN} you can write an expression :

constant k : integer
:= ((V1)* (g-2)*(g-3)...(g-N) / ((1-2)*(1-3)*(1-4)...(1-N)) +
(V2)*(g-1)* (g-3)...(g-N) / ((2-1)*(2-3)*(2-4)...(2-N) +
... +
(VN)*(g-1)...(g-(N-1) / ((N-1)*(N-2)* ... *(N-
(N-1)) ) );

I.e. the idea is that for any given term in the sum, only one term is
ever non-zero, because if you have the "wrong: value of g, one of the
factors will be zero. But if you have the "right" value of g in your
term, all the stuff on the denominator cancels out the (G-k) terms,
leaving you with Vk.

Caveat: I've never tried this myself in VHDL, but for small values of
N, and some attention to precision and overflow, it might just be
crazy enough to work :) You might need to cast most of the operands
to real, as well, to avoid errors due to using integer division.

All of the operators (+,*,/) must be the implicit operators (not
overloaded) so that the initializer is still technically static.

An obvious improvement is to try to use an ordinary VHDL function f
(which might use 'if' and 'case' statements) to map g to V(g), and
initialize the constant with f(g). But I think means that the
initializer is no longer a static expression and most synthesizers
will complain, although you might be might get lucky and wind up with
tool-dependent non-portable code :-( In the past I've seen Tool #1
gallantly accept fancy initializers that another Tool #2 later
complained about.

Apologies in advance if I messed up some of the subscripts above -- do
what I meant, not what I said!

- Kenn
 
P

Paul Uiterlinden

Brad said:
Hello,

What I would like to do is this:

if( sim=true ) then
constant mem_size : integer := 128;
else
constant mem_size : integer := 2**18;
end if;

But, of course, VHDL doesn't let me
use "if" in the declaration part before
the "begin" keyword. What's a way to do
this?

Use a function.

function get_mem_size (sim: boolean) return natural is
begin
if sim then
return 2**7;
else
return 2**18;
end if;
end function get_mem_size;

constant mem_size : integer := get_mem_size(sim);
 
B

Brian Drummond

Hello,

What I would like to do is this:

if( sim=true ) then
constant mem_size : integer := 128;
else
constant mem_size : integer := 2**18;
end if;

But, of course, VHDL doesn't let me
use "if" in the declaration part before
the "begin" keyword. What's a way to do
this?

As Paul said, use a function (and pass a boolean "sim" constant, true or false,
to the function.

But you don't need to declare a "sim" constant. (You can, and it works, but it
needs maintenance, or one day you WILL synthesise for 128 words of memory!)
You can use pragmas to distinguish automatically between synthesis and
simulation, e.g.

function get_mem_size (sim: boolean) return natural is
variable size : integer := 2**18;
begin
--pragma synthesis off
size := 128;
--pragma synthesis on
return size;
end if;
end function get_mem_size;

Or use a similar function to return the "sim" boolean constant and plug it into
the other approaches.

- Brian
 
B

Brad Smallridge

Use a function.

function get_mem_size (sim: boolean) return natural is
begin
if sim then
return 2**7;
else
return 2**18;
end if;
end function get_mem_size;

constant mem_size : integer := get_mem_size(sim);


Thanks Paul,

That looks like the cleanest albeit verbose.

Another post said something about Synopsys only passing integer
generics. I don't use Synopsys but I would like my code to be
portable. Does anyone know about this?

There was also the issue of synthesis and simulation detection.
I can pass generics from the testbench to the top module which
could override the default synthesis generics, right? But suppose,
I want to run a Xilinx ISE Waveform?

Brad Smallridge
AiVision
 
A

Andy

Thanks Paul,

That looks like the cleanest albeit verbose.

Another post said something about Synopsys only passing integer
generics. I don't use Synopsys but I would like my code to be
portable. Does anyone know about this?

There was also the issue of synthesis and simulation detection.
I can pass generics from the testbench to the top module which
could override the default synthesis generics, right? But suppose,
I want to run a Xilinx ISE Waveform?

Brad Smallridge
AiVision

You can also define an constant array, with a boolean index (two
elements) that works the same way as the function call. Index the
array with the sim generic to get the value you want.

type size_array is array (boolean) of integer;
constant size : size_array := (true => 128, false => 2**18);

constant memsize : integer := size(sim);

If the array is an array of records, then you can have a whole set of
named values defined uniformly based on the value of sim.

Andy
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,808
Messages
2,569,684
Members
45,438
Latest member
greenleaf

Latest Threads

Top