SR Flip Flop

N

Nirav

Hello Everybody,

I'm the student of Electronics and Communication Engineering and
finding a problem in implementing SR Flip flop on VHDL Platform, using
Quartus 7.1 tool. Please help me out.

I've made a few programs for that but in all those I'm finding same or
other Problem or not perfect output, Can you please let me know where
I'm making this mistake ??

1st Program :

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity RSFF_NRK is
port(s,r,clk : in BIT ; q,qbar : buffer BIT);
end RSFF_NRK;

architecture RSFF_NRK_ARC of RSFF_NRK is
begin

process(clk)
begin

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

if( r = '1' and s = '0' ) then

q <= r nor qsbar;
qs <= r nor qsbar;

qbar <= s nor qs;
qsbar <= s nor qs;

elsif(s= '1' and r = '0') then

qbar <= s nor qs;
qsbar <= s nor qs;

q <= r nor qsbar;
qs <= r nor qsbar;


elsif(s = '1' and r = '1') then

q <= '1';
qbar <= '1';

end if;

end if;

end process;

end RSFF_NRK_ARC;

Here the program runs well but its RTL schematic shows a very large
circuit instead of having only 2 gates.

2nd Program :

library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity RSFF_NRK is
port(ip : in std_logic_vector (1 downto 0); clk : in BIT ; q,qbar :
out BIT);
signal qs,qsbar : BIT;
signal sel : INTEGER;
end RSFF_NRK;

architecture RSFF_NRK_ARC of RSFF_NRK is
begin

p:process(clk,ip)
begin

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


case ip is

when "00" => sel <= 0;
when "01" => sel <= 1;
when "10" => sel <= 2;
when "11" => sel <= 3;

end case;

if(sel = 1) then

q <= ip[0] nor qsbar;
qs <=ip[0] nor qsbar;

qbar <=ip[1] nor qs;
qsbar <=ip[1] nor qs;

elsif(sel=2) then

qbar <=ip[1] nor qs;
qsbar <=ip[1] nor qs;

q <=ip[0] nor qsbar;
qs <=ip[0] nor qsbar;

elsif(sel=3) then

q <= ip[1] ;
qbar <= ip[0] ;

end if;


end if;

end process;

end RSFF_NRK_ARC;

Here, I've made the program but ip[_] is not being supported, always
at this point I'm given an error report.

3rd Program :


library IEEE;
use IEEE.STD_LOGIC_1164.all;

entity RSFF_NRK is
port(s,r,clk : in BIT ; q,qbar : out BIT);
end RSFF_NRK;

architecture RSFF_NRK_ARC of RSFF_NRK is
begin

process(clk)
begin

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

if( r = '1' and s = '0' ) then
q <= s;
qbar <= r;
elsif(s= '1' and r = '0') then
qbar <= r;
q <= s;
elsif(s = '1' and r = '1') then

q <= s;
qbar <= r;

end if;

end if;

end process;

end RSFF_NRK_ARC;

Here program works well but circuit becomes much a complex.

Please point out my error or let me have an alternate solution.

Nirav
 
B

beckjer

In program 1, (common problem in all 3 programs) add an 'else'
statement to complete all the transistions. Leaving off the else
clause can make for some large and messy circuits. A simple fix is:
if your_happy = '1' AND youknowit = '1' then
clapYourHands; -- proc call :p
else
null;
end if;

Null is a wonderful statement. It's great for creating sections you
want to go back to (an inherant comment - of I'm not done yet) or
closing if then else groups.

In program 2 I see that you are combining std_logic_vector with bit
for operations. Try defining all the entity names with std_logic
instead of bit. That or you will need to convert the bit (or
std_logic_vector) for the nor operation to work properly.


In program 3 it looks like you always have:
q <= s; qbar <= r;

I would change the structure to
if r = '1' or s = '1' then
q <= s;
qbar <= r;
else --you are missing the final 'else' keyword. This can make for
rather large circuits.
null;
end if;
 
J

jens

Null is a wonderful statement. It's great for creating sections you
want to go back to (an inherant comment - of I'm not done yet) or
closing if then else groups.

I guess I fail to see the point of adding two lines of code to every
if statement to tell it to do nothing, it'll do nothing just fine on
it its own. The suggestion of converting everything to std_logic is a
good one.

To answer the original question...

Every signal assigned in a clocked process will create a flip-flip, so
the first two examples will create 4 flip-flops, one each for q, qs,
qbar and qsbar. Also, the outputs of some of those flip-flops will
feed into the inputs of other flip-flops, which will delay signals in
a way you didn't intend. Using variables instead of signals could
have change the behavior, but would still be needlessly complex. The
third one is better with only two flip-flops (q and qbar). The key to
create one SR flip-flop is to create only one flip-flop for q and
derive qbar from q. Also, the logic is more complex than it needs to
be, as it handles the illegal case separately and also assign outputs
to input values rather than constants. As is usually the case, look
for a simpler answer rather than a more complicated answer. Try
something like this:

process( clk )
begin
if ( r = '1' ) then -- R wins in the illegal case of RS=11
q <= '0';
elsif ( s = '1' ) then
q <= '1';
end if;
end process;

qbar <= not q;
 
J

jens

Null is a wonderful statement. It's great for creating sections you
want to go back to (an inherant comment - of I'm not done yet) or
closing if then else groups.

I guess I fail to see the point of adding two lines of code to every
if statement to tell it to do nothing, it'll do nothing just fine on
it its own. The suggestion of converting everything to std_logic is a
good one.

To answer the original question...

Every signal assigned in a clocked process will create a flip-flip, so
the first two examples will create 4 flip-flops, one each for q, qs,
qbar and qsbar. Also, the outputs of some of those flip-flops will
feed into the inputs of other flip-flops, which will delay signals in
a way you didn't intend. Using variables instead of signals could
have changed the behavior, but would still be needlessly complex. The
third one is better with only two flip-flops (q and qbar). The key to
create one SR flip-flop is to create only one flip-flop for q and
derive qbar from q. Also, the logic is more complex than it needs to
be, as it handles the illegal case separately and also assign outputs
to input values rather than constants. As is usually the case, look
for a simpler answer rather than a more complicated answer. Try
something like this:

process( clk )
begin

if ( r = '1' ) then -- R wins in the illegal case of RS=11
q <= '0';
elsif ( s = '1' ) then
q <= '1';
end if;
end process;

qbar <= not q;
 
J

jens

Null is a wonderful statement. It's great for creating sections you
want to go back to (an inherant comment - of I'm not done yet) or
closing if then else groups.

I guess I fail to see the point of adding two lines of code to every
if statement to tell it to do nothing, it'll do nothing just fine on
it its own. The suggestion of converting everything to std_logic is a
good one.

To answer the original question...

Every signal assigned in a clocked process will create a flip-flip, so
the first two examples will create 4 flip-flops, one each for q, qs,
qbar and qsbar. Also, the outputs of some of those flip-flops will
feed into the inputs of other flip-flops, which will delay signals in
a way you didn't intend. Using variables instead of signals could
have changed the behavior, but would still be needlessly complex. The
third one is better with only two flip-flops (q and qbar). The key to
create one SR flip-flop is to create only one flip-flop for q and
derive qbar from q. Also, the logic is more complex than it needs to
be, as it handles the illegal case separately and also assign outputs
to input values rather than constants. As is usually the case, look
for a simpler answer rather than a more complicated answer. Try
something like this:

process(clk)
begin
if rising_edge(clk) then
if r = '1' then -- R wins in the illegal case of RS=11
q <= '0';
elsif s = '1' then
q <= '1';
end if;
end if;
end process;

qbar <= not q;
 
A

Andy

Null is a wonderful statement. It's great for creating sections you
want to go back to (an inherant comment - of I'm not done yet) or
closing if then else groups.

Your comments about NULL completing an if-else statement got my
attention.

Are you trying to avoid latches, by any chance?

In clocked processes, if-then statements (without else) can result in
clock enables, but not latches.

Latches are caused by combinatorial processes that execute, but, under
some circumstances do not assign a signal that is assigned under
other circumstances. When the signal is not assigned, it is forced to
"remember" its previous state, and a latch is inferred to do that. The
common (and I believe outdated) admonition to always have an 'else'
with every 'if-(elsif)-then' statement to avoid latches in
combinatorial processes is not a reliable way to avoid latches.

There are many more effective approaches to avoiding latches. First,
avoid combinatorial processes, and you won't have any latches.

If you have to use a combinatorial process (you probably really don't
but if you think you have to), then provide default assignments to
every signal driven by the process, right up front in the process,
before any if/case/loop/etc. statements. By assigning everything a
default value in one place, it makes it easier to review/audit the
code, and verify that no latches will be produced. Then you don't have
to worry about whether every if has an else (and contains all the
assignments in needs), etc.

For example, rather than write:

if condition = '1' then
a <= b;
else
a <= '0';
end if;

you could re-write it as:

a <= '0'; -- default
if condition = '1' then
a <= b;
end if;

Of course, the advantages become more clear as the number of signals
and conditions grows.

Andy
 
B

beckjer

I guess I fail to see the point of adding two lines of code to every
if statement to tell it to do nothing, it'll do nothing just fine on
it its own. The suggestion of converting everything to std_logic is a
good one.
I meant closing case statements, not if statements (which would make
it a useless comment). Not enough coffee the other day I guess.
 
A

Andy

I meant closing case statements, not if statements (which would make
it a useless comment). Not enough coffee the other day I guess.

Oh,... nevermind.
Disregard my comments regarding latch avoidance.

Andy
 
P

Paul Uiterlinden

beckjer said:
I meant closing case statements, not if statements (which would make
it a useless comment). Not enough coffee the other day I guess.

Also there NULL makes no sense, in my opinion. A choice is allowed to be
empty. Something along these lines is valid VHDL:

case my_enum is
when => e_plus
a := b + c;
when => e_min
a := b - c;
when others =>
-- Do nothing (no NULL needed here)
end case;
 
J

Jonathan Bromley

Something along these lines is valid VHDL:

case my_enum is
when e_plus => -- JB fixed minor syntax error
a := b + c;
when e_min =>
a := b - c;
when others =>
-- Do nothing (no NULL needed here)
end case;

Agreed, but... when I write control structures
I typically write the WHOLE control structure
and then start filling in the bodies. This
prevents me from making silly nesting errors.
So I might write:

case my_enum is
when e_plus =>
when e_min =>
when others =>
end case;

and then start adding code to each branch.

A completely empty branch is a good clue that I
forgot to do something. Consequently, I generally
prefer to put an explicit "null;" in branches that
I *intended* to be empty, to distinguish them from
branches that I didn't get around to completing yet.

Users of the kind of highly automated text editor
that makes my brain explode will doubtless tell me
there's a better way to write code... :)
--
Jonathan Bromley, Consultant

DOULOS - Developing Design Know-how
VHDL * Verilog * SystemC * e * Perl * Tcl/Tk * Project Services

Doulos Ltd., 22 Market Place, Ringwood, BH24 1AW, UK
(e-mail address removed)
http://www.MYCOMPANY.com

The contents of this message may contain personal views which
are not the views of Doulos Ltd., unless specifically stated.
 
P

Paul Uiterlinden

Jonathan said:
Agreed, but... when I write control structures
I typically write the WHOLE control structure
and then start filling in the bodies. This
prevents me from making silly nesting errors.
So I might write:

case my_enum is
when e_plus =>
when e_min =>
when others =>
end case;

and then start adding code to each branch.

A completely empty branch is a good clue that I
forgot to do something. Consequently, I generally
prefer to put an explicit "null;" in branches that
I *intended* to be empty, to distinguish them from
branches that I didn't get around to completing yet.

Sounds sensible. I guess I'm just used to put "-- Do nothing" where you
put "null;". No real difference.

And talking about "when others =>": in behavioral code I avoid using it all
together. When I later add a member to the enumeration type, the compiler
nicely puts it to my attention that I should add a choice to the case
statement.
Users of the kind of highly automated text editor
that makes my brain explode will doubtless tell me
there's a better way to write code... :)

Naaaah...
 
K

KJ

Sounds sensible. I guess I'm just used to put "-- Do nothing" where you
put "null;". No real difference.

And talking about "when others =>": in behavioral code I avoid using it all
together. When I later add a member to the enumeration type, the compiler
nicely puts it to my attention that I should add a choice to the case
statement.
That's why I find it better to have something like the following as
the default...

when others =>
assert FALSE report "OOPS! Unexpected value" severity ERROR;

It's the wordiest of the bunch but also throws a sim exception when
you add an enumeration member and don't update all of the places where
you use it or, like Jon mentioned, you haven't gotten around to coding
it yet.

KJ
 
P

Paul Uiterlinden

KJ said:
That's why I find it better to have something like the following as
the default...

when others =>
assert FALSE report "OOPS! Unexpected value" severity ERROR;

Still, this work only in _simulation_, and you have to hit the condition. By
not using the others choice at all, the error is already caught during
_analysis_. That's what I like about not using the "when others". For
synthesisable code however, the "when others" is needed most of the time,
so I agree with your solution.
 
A

Andy

Still, this work only in _simulation_, and you have to hit the condition. By
not using the others choice at all, the error is already caught during
_analysis_. That's what I like about not using the "when others". For
synthesisable code however, the "when others" is needed most of the time,
so I agree with your solution.

Does any synthesis vendor interpret "when others =>", even if not
reachable formally (i.e. all enumerated values are covered), as
instructions for what to do in the case of an unused digital code? It
would be nice to be able to use it to specify recovery from illegal
states, but that is probably a whole 'nother can of worms.

Andy
 
K

KJ

Paul Uiterlinden said:
Still, this work only in _simulation_, and you have to hit the condition.
By
not using the others choice at all, the error is already caught during
_analysis_. That's what I like about not using the "when others". For
synthesisable code however, the "when others" is needed most of the time,
so I agree with your solution.

When I was first posting it, I was thinking more along the lines of the
situation that Jonathon was describing which was more for a placeholder for
code that hasn't been written yet. Probably a better 'report' string for me
to have put down would've been something like "This code hasn't been written
yet" and use that type of assertion wherever needed (i.e. in other case
values, 'if/elsif' statement branches, etc).

Having said though, and after reading your post and Andy's reply got me to
wondering again how is synthesis handling 'when others' now-a-daze. Back ~8
years or so ago, whatever tool it was that I was using treated 'when others'
a bit more seriously in that if the synthesizer turned an eight state
enumeration into an 8 flip flop one hot that 'when others' would pick up the
248 uncoded (and supposedly not reachable) states. At the time it seemed to
be a perfectly reasonable thing to do in response to the 'when others' in
order to force recovery from an illegal state...and if there was no 'when
others' that no logic would be added to cover those conditions.

Flash forward to modern tools and that no longer seems to be the case (as
Andy queried). Now it takes a compiler option (at least with Quartus) to
get an output that can only occur in 'illegal' states to be anything other
than '0' which seems reasonable too and somewhat user controllable. But now
there would seem to be no reason to code the 'when others' path explicitly
since it will either get optomized away or handled by coding of each of the
enumerated cases (depending on how the compiler setting is set). I haven't
tried it yet with Synplify or ISE yet to see how to handle things there.

Given all that I agree that your approach of simply coding all the
enumerations and leaving out the 'when others' is the better approach since
the compiler catches the problem earlier on and controlling how the
synthesis operation generates logic has been moved to a compiler setting
(not sure I 'like' that, but one needs to work with the tools).

By the way, now that we each agree with the others approach....at the end of
your post you said "For synthesisable code however, the "when others" is
needed most of the time...", what tool and settings are you using that
caused you to say that 'when others' is usually needed for synthesizable
code?

KJ
 
P

Paul Uiterlinden

Andy said:
Does any synthesis vendor interpret "when others =>", even if not
reachable formally (i.e. all enumerated values are covered), as
instructions for what to do in the case of an unused digital code? It
would be nice to be able to use it to specify recovery from illegal
states, but that is probably a whole 'nother can of worms.

As far as I know (I do not know much about synthesis, so somebody correct me
if I'm talking nonsense) this is exactly the reason why the "others" choice
must be used in synthesis.

When you have an enumeration type with three members, and all these members
are covered in a case statement (in an FSM, for example), the "others"
choice is not needed in VHDL.

However, for storing the FSM state there will be two flip-flops (assuming
binary encoding), giving four possible states. If for some reason the FSM
gets in the fourth (unused) state, it will be stuck forever without
the "when others" choice.

If the "when others" choice is present (with an assignment to one of the
three vailid states), it will be honored by the synthesis tool and the FSM
will recover. As far as I know this is at least valid for Quartus.

Another approach would be to make sure that the enumeration type for the
states of an FSM contains 2**N states.
 
M

Mike Treseler

Yes it is.
VHDL makes no assumption about how the enum is encoded,
so such countermeasures are left to synthesis,
and synthesis assumes that the hardware works.
If any flop can change state at any time,
there is really nothing that synthesis can do
to fix this up.
I use "when others =>" for a valid transition.

Paul said:
Another approach would be to make sure that the enumeration type for the
states of an FSM contains 2**N states.

This assumes that I have made a synthesis
setting for binary encoding.

If flops can flop at random,
state machines won't be the
only problem in the design.

-- Mike Treseler
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top