Beginner question on FIFO in "FPGA prototyping by VHDL examp

B

Bill

Guest
I am very new to FPGA programming. I'm using "FPGA Prototyping by
VHDL examples" to learn VHDL. I've gotten up to section 4.5.3 FIFO
buffer, and am having trouble understanding what might happen in the
code...

In the 'register file' section, array_reg(w_ptr_reg) is set to w_data.

In the fifo control section, w_ptr_reg is set to w_ptr_next.

Both events happen when clk'event and clk='1'.


Is there any guarantee as to which one happens first? How do I know
whether array_reg(???) will use w_ptr_reg as the index, or w_ptr_next?


If there is anyone who is working through this same book, I'd like to
start an email correspondence.

Bill
 
In article <8lf9g7dq02hfn7lmf5cnmjm4atidskuqte@4ax.com>,
Bill <bfmackin@nospam.mchsi.com> wrote:
I am very new to FPGA programming. I'm using "FPGA Prototyping by
VHDL examples" to learn VHDL. I've gotten up to section 4.5.3 FIFO
buffer, and am having trouble understanding what might happen in the
code...

In the 'register file' section, array_reg(w_ptr_reg) is set to w_data.

In the fifo control section, w_ptr_reg is set to w_ptr_next.

Both events happen when clk'event and clk='1'.


Is there any guarantee as to which one happens first? How do I know
whether array_reg(???) will use w_ptr_reg as the index, or w_ptr_next?
Well, I don't have the book, so I'm giving this advice blind - but -
you're not thinking hardware. What hardware does the VHDL represent?

There's no "first" in the above - they're happening at the same time - at
the postive edge of a clk.

Draw out what you think the hardware will look like. Sketch a few
timing diagrams. Under what timing conditions will things work
as intended?

If there is anyone who is working through this same book, I'd like to
start an email correspondence.
Just use this thread, so others can contribute too.

Regards,

Mark
 
Mark Curry <gtwrek@sonic.net> wrote:
In article <8lf9g7dq02hfn7lmf5cnmjm4atidskuqte@4ax.com>,
Bill <bfmackin@nospam.mchsi.com> wrote:
I am very new to FPGA programming. I'm using "FPGA Prototyping by
VHDL examples" to learn VHDL. I've gotten up to section 4.5.3 FIFO
buffer, and am having trouble understanding what might happen in the
code...
(snip)
Both events happen when clk'event and clk='1'.

Is there any guarantee as to which one happens first? How do I know
whether array_reg(???) will use w_ptr_reg as the index, or w_ptr_next?

Well, I don't have the book, so I'm giving this advice blind - but -
you're not thinking hardware. What hardware does the VHDL represent?

There's no "first" in the above - they're happening at the same time - at
the postive edge of a clk.
Also, note that the FIFO is usually built from a dual-port RAM,
so that it can write a new entry and read an old one at the same time.

Since you didn't mention it, I presume your FIFO doesn't have separate
read and write clocks, though that is also allowed.

-- glen
 
Don't confuse execution order with simulation time. Seqential
statements execute in sequential order, one after the other, without
consuming any simulation time (except a wait statement). Simulation
time only advances while the process is suspended (e.g. waiting for
the next clock edge, whether explicitly executing a wait statement, or
implicitly at the bottom of a process that has a sensitvity list).

If w_ptr_reg is a signal, its value is not actually updated until (in
execution order) the process suspends (to wait for another clock). So,
references to a signal, whether they occur before or after (in
execution order, not simulation time) the assignment to it, return the
non-updated value. This is different from how software code works in
typical programming languages.

If w_ptr_reg is a variable, it works just like software; the variable
is updated immediately upon execution of the assignment statement (or
procedure call, if it is an out or inout parameter). So references to
a variable occurring before (in execution order) the assignment will
return the non-updated value, but references to the variable occuring
after (in execution order) the assignment will return the updated
value.

Whether you use variables or signals, the synthesis tool will create
hardware (i.e. gates and registers) that mimics the simulation
behavior of the code. Whether that hardware is fits in the device or
meets timing constraints is a different issue. I find it works best
for me if I focus on coding the correct behavior, then worry about
what hardware it generates if it does not fit or meet timing. Of
course, with experience comes the knowledge of what types of behavior
take too much resources or won't meet timing! Because of my preference
and experience, I use more variables, saving signals for only inter-
process communications.

Andy
 
Andy <jonesandy@comcast.net> wrote:

Don't confuse execution order with simulation time. Seqential
statements execute in sequential order, one after the other, without
consuming any simulation time (except a wait statement). Simulation
time only advances while the process is suspended (e.g. waiting for
the next clock edge, whether explicitly executing a wait statement, or
implicitly at the bottom of a process that has a sensitvity list).
This is all true, but with a FIFO things get much more interesting.

Consider that the write data could come just before, at the same time
as (more likely in simulation than actual practice) or just after
the read cycle. The FIFO has to handle all three cases.
(If the FIFO is empty, you shouldn't even try reading, and if full
you shouldn't write.)

Some immediately pass data written to an empty FIFO to the output,
others don't.

If w_ptr_reg is a signal, its value is not actually updated until (in
execution order) the process suspends (to wait for another clock). So,
references to a signal, whether they occur before or after (in
execution order, not simulation time) the assignment to it, return the
non-updated value. This is different from how software code works in
typical programming languages.
I usually write mostly structural verilog (module references and
continuous assignment) but sometimes behavioral. When I do write
behavioral verilog, I try to order the statements such that the
result is the same as if they were executed sequentially.

(snip)
Whether you use variables or signals, the synthesis tool will create
hardware (i.e. gates and registers) that mimics the simulation
behavior of the code. Whether that hardware is fits in the device or
meets timing constraints is a different issue. I find it works best
for me if I focus on coding the correct behavior, then worry about
what hardware it generates if it does not fit or meet timing. Of
course, with experience comes the knowledge of what types of behavior
take too much resources or won't meet timing! Because of my preference
and experience, I use more variables, saving signals for only inter-
process communications.
Well, real hardware timing may result in hardware that works and a
simulation that doesn't, if you aren't careful with the way you
write the statements.

-- glen
 
I am very new to FPGA programming. I'm using "FPGA Prototyping by
VHDL examples" to learn VHDL. I've gotten up to section 4.5.3 FIFO
buffer, and am having trouble understanding what might happen in the
code...
[elided]

In real-world usage for Xilinx FPGAs, you do not write code that will b
synthesized into a FIFo. You use their CoreGen tool to generate a FIF
block, and instantiate that into the controlling logic.

However, what others have already said about the essentially simultaneou
nature of hardware versus the sequential programming paradigm holds true.


---------------------------------------
Posted through http://www.FPGARelated.com
 
On Jan 4, 6:44 pm, glen herrmannsfeldt <g...@ugcs.caltech.edu> wrote:
Andy <jonesa...@comcast.net> wrote:
Don't confuse execution order with simulation time. Seqential
statements execute in sequential order, one after the other, without
consuming any simulation time (except a wait statement). Simulation
time only advances while the process is suspended (e.g. waiting for
the next clock edge, whether explicitly executing a wait statement, or
implicitly at the bottom of a process that has a sensitvity list).

This is all true, but with a FIFO things get much more interesting.

Consider that the write data could come just before, at the same time
as (more likely in simulation than actual practice) or just after
the read cycle. The FIFO has to handle all three cases.
(If the FIFO is empty, you shouldn't even try reading, and if full
you shouldn't write.)

Some immediately pass data written to an empty FIFO to the output,
others don't.

If w_ptr_reg is a signal, its value is not actually updated until (in
execution order) the process suspends (to wait for another clock). So,
references to a signal, whether they occur before or after (in
execution order, not simulation time) the assignment to it, return the
non-updated value. This is different from how software code works in
typical programming languages.

I usually write mostly structural verilog (module references and
continuous assignment) but sometimes behavioral.  When I do write
behavioral verilog, I try to order the statements such that the
result is the same as if they were executed sequentially.

(snip)

Whether you use variables or signals, the synthesis tool will create
hardware (i.e. gates and registers) that mimics the simulation
behavior of the code. Whether that hardware is fits in the device or
meets timing constraints is a different issue. I find it works best
for me if I focus on coding the correct behavior, then worry about
what hardware it generates if it does not fit or meet timing. Of
course, with experience comes the knowledge of what types of behavior
take too much resources or won't meet timing! Because of my preference
and experience, I use more variables, saving signals for only inter-
process communications.

Well, real hardware timing may result in hardware that works and a
simulation that doesn't, if you aren't careful with the way you
write the statements.

-- glen
I missed an important detail. The OP does not mention whether both
assignment and reference are in the same process (I assumed they
were). If the signal assignment is in one process, another process
(clocked on the same edge of same clock signal) referencing the same
signal will not see the updated value until the next clock edge. All
VHDL processes scheduled to run in the same delta cycle must suspend
before any of their driven signals are updated. If two or more
processes are both sensitive to the same clock signal, then they will
run in the same delta cycle. The issues of (non-shared) variables'
update semantics affecting inter-process communication is completely
avoided in VHDL, by not allowing (non-shared) variables to be accessed
by multiple processes in the first place. Verilog's semantic parallel
to VHDL's signal/variable is the non-blocking/blocking assignment.
Unfortunately, verilog simulators are perfectly happy running code
that performs blocking assignments and accesses in different
"processes" (always blocks), even though the behavior is undefined/
erratic. This makes using these features riskier in Verilog (unless
you have a good linting tool, which is a must with Verilog, IMHO).

Things to look for if simulation behavior differs from the hardware:
Synthesis reported warnings/errors,
Static timing analysis (STA) reported warnings/errors,
Delta delay issues on clock signals (usually caused by assigning one
clock signal from another, then moving data between processes clocked
by both),
Incorrectly defined multi-cycle or false path constraints (and not
running full-timing simulations to verify them)
Testbench issues (incorrectly representing actual HW interface
counterparts),
Synthesis or simulator bug,
.... there are probably others.

In VHDL, with regard to variables, signals and orders of assignments
and references, the behavior of synchronous processes (and therefore
of the synthesized HW) is very well defined by the LRM, making
differences in their behavior (excepting the above) extremely rare in
my experience.

Andy
 
On Thu, 05 Jan 2012 10:40:08 -0600, RCIngham wrote:

I am very new to FPGA programming. I'm using "FPGA Prototyping by VHDL
examples" to learn VHDL. I've gotten up to section 4.5.3 FIFO buffer,
and am having trouble understanding what might happen in the code...

[elided]

In real-world usage for Xilinx FPGAs, you do not write code that will be
synthesized into a FIFo. You use their CoreGen tool to generate a FIFO
block, and instantiate that into the controlling logic.
Actually, in what passes for the real world here, I find a description
that makes the Xilinx tools make an effective use of FPGA resources.

This has more to do with my personal strong anti-"wizard" bias, and a
desire to write portable HDL. I suspect that if writing HDL took up a
bigger proportion of my professional life than the 2% or so that it does,
that my attitude might differ.

However, what others have already said about the essentially
simultaneous nature of hardware versus the sequential programming
paradigm holds true.
Yes. When you write software you should be thinking in the back of your
mind what the processor will be doing (and possibly what the compiler's
optimizer will do, first). When you write Verilog or VHDL you should be
thinking in the back of your mind what logic will be generated. I have
to admit that when I do this most of the blocks have "74HCxx" on them,
but you still want to devote part of your brain to thinking what actual
hardware will get used: it keeps you from doing really stupid things.

--
My liberal friends think I'm a conservative kook.
My conservative friends think I'm a liberal kook.
Why am I not happy that they have found common ground?

Tim Wescott, Communications, Control, Circuits & Software
http://www.wescottdesign.com
 
On Jan 5, 11:30 am, Tim Wescott <t...@seemywebsite.com> wrote:
Yes.  When you write software you should be thinking in the back of your
mind what the processor will be doing (and possibly what the compiler's
optimizer will do, first).  When you write Verilog or VHDL you should be
thinking in the back of your mind what logic will be generated.  I have
to admit that when I do this most of the blocks have "74HCxx" on them,
but you still want to devote part of your brain to thinking what actual
hardware will get used: it keeps you from doing really stupid things.
I write vhdl a lot more than 2% of the time, and I share your anti-
wizard approach for almost everything unless it is built-in HW that
can only be accessed by primitives, like PLL/DLL, some two-clock FIFOs
or that use two different data widths, etc. More often than not, I
need some little special behavior for my specific application that
precludes using the built-in stuff anyway, so I infer the RAM and roll
my own control. Dealing with data in arrays is so much easier anyway.

I found out a long time ago that thinking about and then coding
function and cycle-based behavior, rather than flops and gates, is
more productive for me. When I need the utmost in performance
(rarely), I normally use retiming, and it doesn't matter where/how I
coded the registers anyway. If I need to speed it up, I normally
approach it to see "what can I do ahead of time (in a previous clock
cycle)?", or "what can I delay (into the next clock cycle)?", while I
look for areas that I'm doing too much in one clock cycle. Unlike SW,
where you generally don't want to do something until and unless you
really need to, in HW it is almost the opposite. Do it just in case,
then use the results when you need them. This generally results in
less logic in the function, and therefore faster performance.

Andy
 

Welcome to EDABoard.com

Sponsor

Back
Top