Back on vhdl.. and on processes..

M

Massi

Hi all.
Some time ago, i found on this ng a GIANT help for my vhdl problems, so i'm
here again to mess you all :)

I'm trying (again) to create a simple module, intended to do this function:

take in input a value, if this value is in a defined period output the
value, else take the value in the period adding or subtracting the period
value.

I had 2 way yo try: do everything as a finite state machine (ARG) -> many
work, many problems, bad code
The other way (i thought) was trying to do the module using simple
processes.
That's what i wanted to do: the first process (controlled by the clock)
works on the input value: if it's out of the period changes it, else simply
modify a local signal named "local_signal" (ie :p)
The second process is controlled by this local signal, and on the rising
edge of the signal generates the output.
Obviously, nothing works so the question is: is this a valid way, or it will
never work in this way?

Thank you very much!
Just to enjoy you, i post here my test code :)

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_signed.all;
use ieee.std_logic_arith.all;

entity Discretizer is
port(
BININ : in std_logic_vector(0 to 15);
BINOUT : out std_logic_vector(0 to 15)
);
end Discretizer;

architecture rrgen of Discretizer is

constant pi : std_logic_vector(0 to 15) := "0000001100100100";
constant duepi : std_logic_vector(0 to 15) := "0000011001001000";
constant pimezzi : std_logic_vector(0 to 15) := "0000000110010010";

signal clk: bit;
signal TEMP_BININ: SIGNED(BININ'range);
signal create_output: bit;

begin

TEMP_BININ <= SIGNED(BININ);

-- Data
data: process( CLK )
begin

if( create_output = '1' ) then
create_output <= '0';
end if;

if( signed(TEMP_BININ) < -signed(pi) ) then
TEMP_BININ <= TEMP_BININ + signed(duepi);
end if;

if( signed(TEMP_BININ) > signed(pi) ) then
TEMP_BININ <= TEMP_BININ - signed(duepi);
end if;

if( signed(TEMP_BININ) < signed(pi) and signed(TEMP_BININ)
> -signed(pi) ) then
create_output <= '1';
end if;

end process;

-- output register
output_register: process( create_output )
begin

if( create_output'event and create_output = '1' ) then
BINOUT <= std_logic_vector( TEMP_BININ );
end if;

end process;

end rrgen;
 
Joined
Aug 18, 2006
Messages
7
Reaction score
0
Hello,
a few points to note:

a) this problem looks purely combinational to me; if so, why do you want processes on the clk edge? its a waste of a flip flop

b)i dont seem to quite understand ur problem statement
here's how i interpret it:
given a,b, where

if (input > a AND input < b) return input
else
return (input + (b-a))?


if thats the case, in vhdl this is simple

output <= input when ((input>a)and(input<b)) else;
(input + (b-a));
 
B

backhus

Massi said:
Hi all.
Some time ago, i found on this ng a GIANT help for my vhdl problems, so i'm
here again to mess you all :)

I'm trying (again) to create a simple module, intended to do this function:

take in input a value, if this value is in a defined period output the
value, else take the value in the period adding or subtracting the period
value.

I had 2 way yo try: do everything as a finite state machine (ARG) -> many
work, many problems, bad code
The other way (i thought) was trying to do the module using simple
processes.
That's what i wanted to do: the first process (controlled by the clock)
works on the input value: if it's out of the period changes it, else simply
modify a local signal named "local_signal" (ie :p)
The second process is controlled by this local signal, and on the rising
edge of the signal generates the output.
Obviously, nothing works so the question is: is this a valid way, or it will
never work in this way?

Thank you very much!
Just to enjoy you, i post here my test code :)
Hi Massi,
and we really laughed a lot ;-)

Seems like you know some VHDL syntax, but have no clue what to do with it.
Have you ever tried to read the error messages you get? (Do you
understand them too?)

If your hardware should work you should design it like hardware:
Why is your clock not in the port list? Put it in there!
Why is CLK in the sensitivity list of your first process, when you never
use it there?
Why are you assigning values to creater_output at two IFs. This can be
done more clearly inside one IF. Use ELSE there.


Why do you use create_output to clock the second process?
Use Clock instead and make create_output as a clock_enable.


What you said about FSMs:
many work <= not true
many problems <= not true
bad code <= your fault

have a nice synthesis
Eilert
 
M

Massi

backhus said:
Hi Massi,
and we really laughed a lot ;-)

i'm happy of that :)
Seems like you know some VHDL syntax, but have no clue what to do
with it.

yes, basically that's the problem lol
Have you ever tried to read the error messages you get? (Do
you understand them too?)

mmm...
the module is compiled right, no errors..
Why is your clock not in the port list? Put it in there!

ops, thats a stupid error, i can do better :)
Why is CLK in the sensitivity list of your first process, when you
never use it there?

Ok, that's a problem. i thought that controlling a process with clock means
that every time the clock changes, che process is executed. Is this right?
so why need i to use the value of clock in the process?
Why are you assigning values to creater_output at two IFs. This can be
done more clearly inside one IF. Use ELSE there.

yes, that's true, the code now is written to be just clear :)
Why do you use create_output to clock the second process?
Use Clock instead and make create_output as a clock_enable.

Ok, i simply did not understand :)
Can you make me an example of that? thanks :)
What you said about FSMs:
many work <= not true

speak for you
many problems <= not true

speak for you
bad code <= your fault

de hi ho :)

basically, do you think i can do it in both ways?
thanks so much :)
 
B

Brian Drummond

Hi all.
Some time ago, i found on this ng a GIANT help for my vhdl problems, so i'm
here again to mess you all :)

Thank you very much!
Just to enjoy you, i post here my test code :)

You are fighting the type system all the way with this code ... why not
use it instead?
library IEEE;
use IEEE.std_logic_1164.all;
--use ieee.std_logic_signed.all;
--use ieee.std_logic_arith.all;
use ieee.numeric_std.all;

As a first step, use the standard library, not these non-standard ones.
It defines usedful signed and unsigned types.
entity Discretizer is
port(
BININ : in std_logic_vector(0 to 15);
BINOUT : out std_logic_vector(0 to 15)
);
end Discretizer;

Later you may decide these ports are better "signed" or "unsigned"
(unless this entity is your top-level design with ports brought out to
actual pins, in which case, std_logic_vector is best)
architecture rrgen of Discretizer is

constant pi : std_logic_vector(0 to 15) := "0000001100100100";
constant duepi : std_logic_vector(0 to 15) := "0000011001001000";
constant pimezzi : std_logic_vector(0 to 15) := "0000000110010010";

constant pi : signed(0 to 15) := "0000001100100100";
constant duepi : signed(pi'range) := pi(pi'low + 1 to pi'high) & '0';
constant pimezzi : signed(0 to 15) := '0' & pi(pi'low to pi'high - 1);

Since you are using pi as a signed quantity throughout, why not define
it as a signed type?
Also, since the latter constants are related to it, if you define them
from it, there is less room for errors to creep into their definition.
Further, using 'range, 'high and 'low attributes keeps the latter
correct even if you later change the size and value of pi because
youneed greater accuracy.

Incidentally I always use signed(15 downto 0), so there may be
inadvertent errors in the above...
signal clk: bit;
signal TEMP_BININ: SIGNED(BININ'range);
signal create_output: bit;

begin

TEMP_BININ <= SIGNED(BININ);

This is the ONLY necessary input type conversion - assuming BININ and
BINOUT remain std_logic_vector.
-- Data
data: process( CLK )
begin
if( signed(TEMP_BININ) < -signed(pi) ) then
TEMP_BININ <= TEMP_BININ + signed(duepi);
end if;

if( TEMP_BININ < -pi ) then TEMP_BININ <= TEMP_BININ + duepi ;

etc...
if( create_output'event and create_output = '1' ) then
BINOUT <= std_logic_vector( TEMP_BININ );

and this is the only necessary output type conversion ... as above.

Other problems, see other answers. But I hope this helps understand how
to use the types to make life simpler...

- Brian
 
J

jens

Just to enjoy you, i post here my test code :)

You Enjoy Myself! *
Ok, that's a problem. i thought that controlling a process with clock means
that every time the clock changes, che process is executed. Is this right?
Yes.

so why need i to use the value of clock in the process?

To determine what to do. Do you want to use the rising edge or falling
edge, or both? (If the answer is both, good luck finding hardware that
can support that). Do you want a flip-flop or a latch? (Usually you
want a flip-flop). Note the difference:

flip_flop: process(clk)
begin
if rising_edge(clk) then
q <= d;
end if;
end process flip_flop;

latch: process(gate,d)
begin
if gate = '1' then
q <= d;
end if;
end process latch;
Ok, i simply did not understand :)
Can you make me an example of that? thanks :)

flip_flop_enable: process(clk)
begin
if rising_edge(clk) then
if enable = '1' then
q <= d;
end if;
end if;
end process flip_flop_enable;


* sorry, couldn't resist a Phish reference in a VHDL newsgroup...
http://www.phish.net/faq/syem.html
 
M

Massi

jens said:
To determine what to do. Do you want to use the rising edge or
falling edge, or both? (If the answer is both, good luck finding
hardware that can support that).

ok ok
so it's enough for me the rising edge :)

Than, i used your precious info to "fix" the module: i used the rising edge
of clock in both processes, and the result is that.. nothing works like
before :)
it compiles.. yes.. but nothing else lol
The strange thing (for me, lol) is this: i thought that "sequential" code
BEFORE of processes had to be executed BEFORE OF PROCESSES
but that's definitely false.. dunno why..

Before of the code, i'm italian and i cannot read a page in which "UFFIZI"
is told "IUFFITZI" lol

here is the "fixed" (lol) code
What have i to do to get this piece of code working? :(

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_signed.all;
use ieee.std_logic_arith.all;

entity Discretizer is
port(
CLK : in std_logic;
BININ : in std_logic_vector(0 to 15);
BINOUT : out std_logic_vector(0 to 15)
);
end Discretizer;

architecture rrgen of Discretizer is

constant pi : std_logic_vector(0 to 15) := "0000001100100100";
constant duepi : std_logic_vector(0 to 15) := "0000011001001000";
constant pimezzi : std_logic_vector(0 to 15) := "0000000110010010";

signal TEMP_BININ: SIGNED(BININ'range);
signal create_output: std_logic;

begin

TEMP_BININ <= SIGNED(BININ);
create_output <= '0';

-- Data
data: process( CLK )
begin

if ( CLK'event and CLK = '1' ) then

if( signed(TEMP_BININ) < -signed(pi) ) then
TEMP_BININ <= TEMP_BININ + signed(duepi);
end if;

if( signed(TEMP_BININ) > signed(pi) ) then
TEMP_BININ <= TEMP_BININ - signed(duepi);
end if;

if( signed(TEMP_BININ) < signed(pi) and signed(TEMP_BININ)
> -signed(pi) ) then
create_output <= '1';
end if;

end if;

end process;

-- output register
output_register: process( CLK )
begin

if ( CLK'event and CLK = '1' ) then

if( create_output = '1' ) then
BINOUT <= std_logic_vector( TEMP_BININ );
end if;

end if;

end process;

end rrgen;
 
B

backhus

Massi said:
ok ok
so it's enough for me the rising edge :)

Than, i used your precious info to "fix" the module: i used the rising edge
of clock in both processes, and the result is that.. nothing works like
before :)
it compiles.. yes.. but nothing else lol
The strange thing (for me, lol) is this: i thought that "sequential" code
BEFORE of processes had to be executed BEFORE OF PROCESSES
but that's definitely false.. dunno why..

Before of the code, i'm italian and i cannot read a page in which "UFFIZI"
is told "IUFFITZI" lol

here is the "fixed" (lol) code
What have i to do to get this piece of code working? :(

Hi Massi,
well it starts getting better. At least the clocking is ok now.
But what did you do with the create_output signal...

In VHDL there is no Sequential Code before processes.
An assignment that is not inside a process is a concurrent assignment.
That means: This line of code is a process in itself. Just without the
begin-end stuff.

The same is it whith condithional assignments like
sig_a <= value1 when condition else value2;
etc.

Now, think for a moment that EVERY process is a electronic circuit.

Then your Assignment
create_output <= '0';
becomes a simple wire to Ground.

and since this wire is connected to the signal create output, which in
the first process is also used as the output of a flipflop (since it is
clocked there)...gues what happens...

The time your Flipflop goes to '1' = Vcc you have shortened your circuit
and ist's going up in flames creating nice smoke and smells. (OK, I'm
dramatizing a little, but this way it becomes more clear I hope.)

Simple Rule: Drive signals from one Proccess only!

like this:
....
if( signed(TEMP_BININ) < signed(pi) and signed(TEMP_BININ) -signed(pi) )
then
create_output <= '1';
else
create_output <= '0';
end if;
....

About Error Messages: Well, there may be warnings too!
And it depends on the tool you are using. A simulator looks for
different things than a synthesis tool.
You should either turn on the "synthesisis code check" in your
simulator (Modelsim has it, for instance) or use a real synthesis tool.
(e.g. XST gives you warnings about sensitivity lists despite the fact
that a synthesis tool doesn't care about it. Just to ceep synthesis and
simulation conform.)


have a nice simulation
Eilert
 
M

Massi

backhus said:
well it starts getting better.

don't bet on it :p
In VHDL there is no Sequential Code before processes.
An assignment that is not inside a process is a concurrent assignment.
That means: This line of code is a process in itself. Just without the
begin-end stuff.

That's why i like newsgroups. you learn always something new :)
Simple Rule: Drive signals from one Proccess only! like this:
...
if( signed(TEMP_BININ) < signed(pi) and signed(TEMP_BININ)
-signed(pi) ) then
create_output <= '1';
else
create_output <= '0';
end if;
...

That's ok and is not a problem.
Bue i have another problem. I have to work on the input signal, that
obviously i cannot edit, so i have to use a "temp" signal inside the module.
So how can i be sure that the assignment of the input signal to the temp
signal will be done BEFORE of other code?
have a nice simulation

Thaks, an you tell me if AT LEAST i am getting closer to the solution? :D

Because, as always, nothing works..

The (lol) code

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_signed.all;
use ieee.std_logic_arith.all;

entity Discretizer is
port(
read : in std_logic;
CLK : in std_logic;
BININ : in std_logic_vector(0 to 15);
BINOUT : out std_logic_vector(0 to 15)
);
end Discretizer;

architecture rrgen of Discretizer is

constant pi : std_logic_vector(0 to 15) := "0000001100100100";
constant duepi : std_logic_vector(0 to 15) := "0000011001001000";
constant pimezzi : std_logic_vector(0 to 15) := "0000000110010010";

signal TEMP_BININ: SIGNED(BININ'range);
signal create_output: std_logic;

begin

-- Data
data: process( CLK )
begin

if ( CLK'event and CLK = '1' ) then

if( read = '1' ) then
TEMP_BININ <= SIGNED( BININ );
end if;

if( signed(TEMP_BININ) < -signed(pi) or signed(TEMP_BININ) >
signed(pi) ) then
create_output <= '0';
if (signed(TEMP_BININ) < -signed(pi) ) then
TEMP_BININ <= TEMP_BININ + signed(duepi);
else
TEMP_BININ <= TEMP_BININ - signed(duepi);
end if;
else
create_output <= '1';
end if;

end if;

end process;

-- output register
output_register: process( CLK )
begin

if ( CLK'event and CLK = '1' ) then

if( create_output = '1' ) then
BINOUT <= std_logic_vector( TEMP_BININ );
end if;

end if;

end process;

end rrgen;
 
B

backhus

Hi Massi,
have you seen the Movie "What About Bob" with Bill Murray?
Well, then you would know what I mean when I say Babysteps. :)
But yes... you are geting closer.
Bue i have another problem. I have to work on the input signal, that
obviously i cannot edit, so i have to use a "temp" signal inside the module.
So how can i be sure that the assignment of the input signal to the temp
signal will be done BEFORE of other code?

Why is everyone (I mean you and lots of my students) always talking
about TEMP variables or signals???

If you change BININ and assign it to another Signal then it is just
that: Another signal. There's nothing temporary about it.

So, what did you do? You put in a validation signal called "read".
Good thing in the first place. Mark your valid data.
When the Data is Valid (read = '1') then you assign the std_logic_vector
to a signed signal.
But what happens, when read = '0'?
The rest of your circuit is working on the old (stored!) signed signal.

So what you want is to receive some data from time to time, check and
change it, and write it away.
and since you are doing the discretization on the same (not very
temporary) signal it changes from clock to clock and does nasty things
to your output. You have a feedback here!)

Now it's time to learn about (tadaa) PIPELINING.

A value that is written to TEMP_BININ should not be overwritten during
the Process, unless you know EXACTLY what you are doing. It's a very
mighty tool for those who know how to handle it.

If you change a Signal write it to another Signal. (If you like call it
TEMP_BINOUT).

Now you have a Pipeline: BININ -> TEMP_BININ -> TEMP_BINOUT -> BINOUT

It could be coded much nicer (each assignm,ent in it's own process) to
make things clearer, but anyway. This should work better.

If correct I can not say.


Thaks, an you tell me if AT LEAST i am getting closer to the solution? :D

Because, as always, nothing works..
Unless you get no fatal error theres always something happening in your
simulation. Look at it and you will see what causes it. Or at least you
can tell us what you see.


have a nice simulation
Eilert
 
J

jens

Bue i have another problem. I have to work on the input signal, that
obviously i cannot edit, so i have to use a "temp" signal inside the module.
So how can i be sure that the assignment of the input signal to the temp
signal will be done BEFORE of other code?

A few things...

Do you really need any temporary signals? Why not just assign the
output right in the comparison logic, compare directly to the input,
get rid of TEMP_BININ, get rid of create_output, and get rid of the 2nd
process?

Beware of thinking of things happening before others in a software-like
sequential sense, this is concurrent hardware here, but there are also
flip-flops delays involved. Any output signal of a clocked process
will not get assigned immediately, so even though that signal in the
process may appear to be used as in input in the same process right
after it's assigned, it's not- it's used on the next clock edge. Use
variables if you want to assign a value and use it immediately.
Familiarize yourself with the difference between signals and variables.
Also note there are two different ways to use variables, depending on
whether they're used before or after being assigned.

Simulate! Play with things and observe the results. Try something
like this:

if rising_edge(clk) then
a <= input;
b <= a;
c <= b;
output <= c;
end if;

Then swap the assignments around, change signals to variables, swap the
assignments around, etc. See what happens (in that example, there's a
huge difference between a, b, and c being signals or variables).

You might also want to verify that the BININ = +/- pi condition does
what you want it to do.

Also (as previously suggested), remove ieee.std_logic_signed.all and
ieee.std_logic_arith.all and replace with ieee.numeric_std.all.

Good luck!
 

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,774
Messages
2,569,596
Members
45,143
Latest member
DewittMill
Top