low-level vs. high-level

E

Evgeny Filatov

Guest
Hi,

I use graphical high-level tools to design DSP stuff and generate RTL
for it. It works for me, but I started to suspect that it is more
efficient to write RTL in HDL languages instead.

Is there any general rule of thumb for how much is sacrificed (in terms
of area / performance) by using high-level tools, as opposed to writing
RTL manually in VHDL/Verilog?

Regards,
Evgeny.
 
On 9/11/2015 2:18 PM, Evgeny Filatov wrote:
Hi,

I use graphical high-level tools to design DSP stuff and generate RTL
for it. It works for me, but I started to suspect that it is more
efficient to write RTL in HDL languages instead.

Is there any general rule of thumb for how much is sacrificed (in terms
of area / performance) by using high-level tools, as opposed to writing
RTL manually in VHDL/Verilog?

Regards,
Evgeny.

If you are using a good optimizing synthesis tool chain, the difference
may not be very large. I used some Mathcad generated RTL on a project,
and by the time the synthesis tool was done, it was as tight as I could
have gotten it by hand.

Regards,
BobH
 
Evgeny Filatov <e.v.filatov@ieee.org> wrote:

I use graphical high-level tools to design DSP stuff and generate RTL
for it. It works for me, but I started to suspect that it is more
efficient to write RTL in HDL languages instead.

I am not sure what there is in high-level tools.

If you mean schematic capture, I find it a lot of work for many
actual problems.

But it might be that some people are more visual than others,
and find it hard to read and understand HDL.

Is there any general rule of thumb for how much is sacrificed (in terms
of area / performance) by using high-level tools, as opposed to writing
RTL manually in VHDL/Verilog?

Most of the designs I work on are pretty low level, but if you write
the appropriate modules (or entities), you should be able to make it
look right in HDL. Write modules for high-level DSP blocks and wire
them up with HDL.

I write structural verilog, or more recently structural VHDL.

-- glen
 
On 9/11/2015 11:42 PM, glen herrmannsfeldt wrote:
Evgeny Filatov <e.v.filatov@ieee.org> wrote:

I use graphical high-level tools to design DSP stuff and generate RTL
for it. It works for me, but I started to suspect that it is more
efficient to write RTL in HDL languages instead.

I am not sure what there is in high-level tools.

If you mean schematic capture, I find it a lot of work for many
actual problems.

But it might be that some people are more visual than others,
and find it hard to read and understand HDL.

Is there any general rule of thumb for how much is sacrificed (in terms
of area / performance) by using high-level tools, as opposed to writing
RTL manually in VHDL/Verilog?

Most of the designs I work on are pretty low level, but if you write
the appropriate modules (or entities), you should be able to make it
look right in HDL. Write modules for high-level DSP blocks and wire
them up with HDL.

I write structural verilog, or more recently structural VHDL.

I'm not sure what you mean by that. Everyone writes structural HDL.
But they also write the code in the blocks that gets connected by the
structural HDL. Don't you? That is the hard part.

--

Rick
 
rickman <gnuarm@gmail.com> wrote:

(snip)

I write structural verilog, or more recently structural VHDL.

I'm not sure what you mean by that. Everyone writes structural HDL.
But they also write the code in the blocks that gets connected by the
structural HDL. Don't you? That is the hard part.

I write a very small part of my verilog in always blocks,
or vhdl in process blocks, and usually in leaf modules/entities.

As well as I know, not everyone does that.

The verilog books that I know make a bigger distinction between
behavioral and structural than the VHDL books, but both have it.

Many always/process blocks have one statement in them, though
sometimes two or three. A loadable counter with reset might go
in one.

-- glen
 
rickman <gnuarm@gmail.com> wrote:

(snip, I wrote0h)
I write structural verilog, or more recently structural VHDL.

I'm not sure what you mean by that. Everyone writes structural HDL.
But they also write the code in the blocks that gets connected by the
structural HDL. Don't you? That is the hard part.

I write a very small part of my verilog in always blocks,
or vhdl in process blocks, and usually in leaf modules/entities.

As well as I know, not everyone does that.

How else do people write their code?

Well, in verilog you can write combinatorial logic with either
continuous assignment not in an always block, or a behavioral
assignment (that is what the book nearby seems to call it) in
an always block. Two different ways to say the same thing.

The only way I make registers and latches in verilog is with
an always block. It might be that it can be done in VHDL without
a process block, but so far I use one, such that it looks similar
to the matching verilog.

The verilog books that I know make a bigger distinction between
behavioral and structural than the VHDL books, but both have it.

Many always/process blocks have one statement in them, though
sometimes two or three. A loadable counter with reset might go
in one.

Sure, the two are very different. Behavioral code requires thinking and
analysis. Structural code is just a matter of wiring together blocks.

I consider continuous assignment part of structural, though it might
have another name, and some logic goes in there.

I think maybe what you are saying is that you only write behavioral code
for very small logical functions and create more complex functions by
wiring them together. This would be analogous to designing a board
using SSI and MSI logic while others write behavioral modules more like
LSI and and VLSI, only using the structural code for the greatly reduced
interconnect.

Some can be written about the same either way. When I have a
choice between verilog continuous assignment and behavioral assignment,
I choose the former, others might choose the latter.

I usually put registers into their own module, even if that is the
only thing in the module.

One that I am working on now is exactly taking a design in SSI and
MSI and writing it in VHDL. The SSI (gates) go into assignment
statements with the appropriate logical operations. MSI (anything
more complicated than just gates) into a module. I can verify the
operation of the module once, and use it many times.

The main reason I can see for writing code using less structural and
more behavioral code is the greatly reduced code required. But then I'm
not sure it would be greatly reduced. I'm just familiar with
interconnecting larger blocks where structural code is a PITA because of
the verbosity. Each signal has to be declared in the higher module,
listed in the instantiation and declared as I/O in the lower module.
This can be so tedious that I have rather lengthy regular expressions I
keep in my code to automagically convert between them.

As far as I know, some people like the way it looks more like a
software (sequential) programming language.

Actually, I realize using structural code at the lower levels would be
*very* verbose because none of the higher level structural code is
reduced. So writing high and mid-level modules in structural code would
add lots of verbiage.

Well, for example, I might write a multiplexer in a module, nice
combinatorial logic with no registers, then use that module wherever
I need a multiplexer, instead of rewriting one each time.

Internally, that module will use either the verilog conditional
operator or VHDL WHEN operator. (Being use to C, I find the WHEN
syntax a little strange, but it doesn't take long to get used to.)

I suspect others will build a multiplexer using behavioral if
statements in either language.

OK, here is a multiplexer in VHDL:

library IEEE;
use IEEE.std_logic_1164.all;

entity N157 is
port (
Y : out std_logic_vector(3 downto 0);
A, B : in std_logic_vector(3 downto 0);
S, G: std_logic);
end entity N157;

architecture N157 of N157 is
begin
Y <= X"0" when G='1' else A when S='0' else B;
end architecture N157;

Once a process is defined, it can add another register with just three
rather simple lines of code. Declare the signal, initialize the signal
and assign the signal. Even creating a new process only adds two more
lines. Structural code for this requires at least as many lines of code
along with any generics and the common signals like reset and clocks.
Well, I count a lot of lines because I write in a spread out manner with
each I/O signal on it's own line. If you come from the Verilog world
your style may vary.

If it fits reasonably, I put a whole module/entity instatiation
on one line. I stay within 80 characters (for one, so that they print
nicely), so some will take more lines. Maybe that is from using
verilog first.

Still, I think the high and mid-level modules will become rather verbose
with structural code.

My early verilog was systolic arrays, with repeated blocks of fairly
simple code. The mid-level module fit on one or two pages, matching
fairly closely the register transfer logic that one might write.
Lower level were registers, adders, comparators, and multiplexers.
Top level instantiated some number of the unit cell in a linear array.

-- glen
 
Tim Wescott <tim@seemywebsite.com> wrote:
(snip)
Evgeny Filatov <e.v.filatov@ieee.org> wrote:

I use graphical high-level tools to design DSP stuff and generate RTL
for it. It works for me, but I started to suspect that it is more
efficient to write RTL in HDL languages instead.

I'm assuming he means that he draws up a block diagram in Simulink and
then pushes a button (well, maybe after lots of simulation and analysis).

But I'm just assuming.

I do remember using schematic drawing tools, but most often found
it took a lot of work drawing lines, making sure that they didn't
overlap what they weren't supposed to, and otherwise getting it right.

But I can write some lines of verilog or VHDL and not have to worry
about such lines overlapping. Match up signal names and everything
works the way it is supposed to.

But I suppose something like simulink isn't so bad. Generate the
VHDL or verilog, look at it, and see if it looks right.

-- glen
 
On 9/12/2015 9:33 AM, glen herrmannsfeldt wrote:
rickman <gnuarm@gmail.com> wrote:

(snip)

I write structural verilog, or more recently structural VHDL.

I'm not sure what you mean by that. Everyone writes structural HDL.
But they also write the code in the blocks that gets connected by the
structural HDL. Don't you? That is the hard part.

I write a very small part of my verilog in always blocks,
or vhdl in process blocks, and usually in leaf modules/entities.

As well as I know, not everyone does that.

How else do people write their code?


The verilog books that I know make a bigger distinction between
behavioral and structural than the VHDL books, but both have it.

Many always/process blocks have one statement in them, though
sometimes two or three. A loadable counter with reset might go
in one.

Sure, the two are very different. Behavioral code requires thinking and
analysis. Structural code is just a matter of wiring together blocks.

I think maybe what you are saying is that you only write behavioral code
for very small logical functions and create more complex functions by
wiring them together. This would be analogous to designing a board
using SSI and MSI logic while others write behavioral modules more like
LSI and and VLSI, only using the structural code for the greatly reduced
interconnect.

The main reason I can see for writing code using less structural and
more behavioral code is the greatly reduced code required. But then I'm
not sure it would be greatly reduced. I'm just familiar with
interconnecting larger blocks where structural code is a PITA because of
the verbosity. Each signal has to be declared in the higher module,
listed in the instantiation and declared as I/O in the lower module.
This can be so tedious that I have rather lengthy regular expressions I
keep in my code to automagically convert between them.

Actually, I realize using structural code at the lower levels would be
*very* verbose because none of the higher level structural code is
reduced. So writing high and mid-level modules in structural code would
add lots of verbiage.

Once a process is defined, it can add another register with just three
rather simple lines of code. Declare the signal, initialize the signal
and assign the signal. Even creating a new process only adds two more
lines. Structural code for this requires at least as many lines of code
along with any generics and the common signals like reset and clocks.
Well, I count a lot of lines because I write in a spread out manner with
each I/O signal on it's own line. If you come from the Verilog world
your style may vary.

Still, I think the high and mid-level modules will become rather verbose
with structural code.

--

Rick
 
On Sat, 12 Sep 2015 03:42:00 +0000, glen herrmannsfeldt wrote:

Evgeny Filatov <e.v.filatov@ieee.org> wrote:

I use graphical high-level tools to design DSP stuff and generate RTL
for it. It works for me, but I started to suspect that it is more
efficient to write RTL in HDL languages instead.
I'm assuming he means that he draws up a block diagram in Simulink and
then pushes a button (well, maybe after lots of simulation and analysis).

But I'm just assuming.

--
www.wescottdesign.com
 
On 9/12/2015 2:00 PM, glen herrmannsfeldt wrote:
rickman <gnuarm@gmail.com> wrote:

(snip, I wrote0h)
I write structural verilog, or more recently structural VHDL.

I'm not sure what you mean by that. Everyone writes structural HDL.
But they also write the code in the blocks that gets connected by the
structural HDL. Don't you? That is the hard part.

I write a very small part of my verilog in always blocks,
or vhdl in process blocks, and usually in leaf modules/entities.

As well as I know, not everyone does that.

How else do people write their code?

Well, in verilog you can write combinatorial logic with either
continuous assignment not in an always block, or a behavioral
assignment (that is what the book nearby seems to call it) in
an always block. Two different ways to say the same thing.

The only way I make registers and latches in verilog is with
an always block. It might be that it can be done in VHDL without
a process block, but so far I use one, such that it looks similar
to the matching verilog.

Yes, if you want, you can describe a FF in a continuous assignment in
VHDL, but it is very unconventional and not very malleable.

I'm not sure why you are drawing some of the distinctions you do. I
have never seen anyone consider continuous assignments to be
"structural" HDL. Rather complex logic can be defined that way although
I think most logic ends up in processes or the equivalent.


The verilog books that I know make a bigger distinction between
behavioral and structural than the VHDL books, but both have it.

Many always/process blocks have one statement in them, though
sometimes two or three. A loadable counter with reset might go
in one.

Sure, the two are very different. Behavioral code requires thinking and
analysis. Structural code is just a matter of wiring together blocks.

I consider continuous assignment part of structural, though it might
have another name, and some logic goes in there.

I only consider instantiations to be structural. Continuous assignments
have several logical constructs which will infer logic and are often
used that way. It is actually seldom that I use continuous assignments
for structure since the connections are made in the component
instantiations. Why would I want to connect two wires with an
assignment unless there was something very odd going on like one wire
into a module connected to two wires going out? I don't know I have
ever done that.


I think maybe what you are saying is that you only write behavioral code
for very small logical functions and create more complex functions by
wiring them together. This would be analogous to designing a board
using SSI and MSI logic while others write behavioral modules more like
LSI and and VLSI, only using the structural code for the greatly reduced
interconnect.

Some can be written about the same either way. When I have a
choice between verilog continuous assignment and behavioral assignment,
I choose the former, others might choose the latter.

Not sure why that matters. If it generates logic, it is not structural.
I think we have a *big* difference in definitions. Behavioral does
not imply any type of assignment to me. It is a method of designing
logic by describing how the logic works rather than describing how it is
constructed. Both concurrent and sequential coding is used for
behavioral design.

Purely structural design would use instantiation only without inference
by any statement type other than within the primitive units.

Of course my designs are never purely behavioral without use of module
instantiation. It is easier to test a design in pieces, then glue the
pieces together and test again. I think our disagreement is how far
down the modules are divided. My typical module size is a couple dozen
to a hundred or so lines. Although the really large ones are the top
level gluing it all together with structural code. One of my smaller
top level modules is over 600 lines of glue. Not hard to get right
using the tools that let me copy and paste with regular expression
conversions. Errors creep in when changes are made.


I usually put registers into their own module, even if that is the
only thing in the module.

One that I am working on now is exactly taking a design in SSI and
MSI and writing it in VHDL. The SSI (gates) go into assignment
statements with the appropriate logical operations. MSI (anything
more complicated than just gates) into a module. I can verify the
operation of the module once, and use it many times.

MSI is a very basic functional block. If you are using this very often
you likely are working at a very low level.

The point is that it is not rocket science to code a shift register or
counter. There is very little value in being able to say you have a
verified counter module. Not much different than saying you have a
verified multiplexor module which you say you do in continuous assignments.

In the end, using such MSI components can be as error prone as writing
them from scratch. I avoid most errors in behavioral code by pulling up
an existing file and copying an arbitrary process for a registered
function and then editing the code. It also reduces the tedium. Then I
can focus on the specifics of what this function needs to do other than
be a register.


The main reason I can see for writing code using less structural and
more behavioral code is the greatly reduced code required. But then I'm
not sure it would be greatly reduced. I'm just familiar with
interconnecting larger blocks where structural code is a PITA because of
the verbosity. Each signal has to be declared in the higher module,
listed in the instantiation and declared as I/O in the lower module.
This can be so tedious that I have rather lengthy regular expressions I
keep in my code to automagically convert between them.

As far as I know, some people like the way it looks more like a
software (sequential) programming language.

Not sure what you mean by this. Only the guts of processes, procedures
and functions look and feel like a sequential language. I think we may
be talking about different things because you include continuous
assignments as "structural".


Actually, I realize using structural code at the lower levels would be
*very* verbose because none of the higher level structural code is
reduced. So writing high and mid-level modules in structural code would
add lots of verbiage.

Well, for example, I might write a multiplexer in a module, nice
combinatorial logic with no registers, then use that module wherever
I need a multiplexer, instead of rewriting one each time.

Yeah, that is the level of design that should be like falling off a log.
It is a one liner in a continuous assignment, five lines in a process
with two of them being ELSE and END IF;

Here is an example...

SineAmpWord <= LUT_Data when ('0' = PhaseSign) else - LUT_Data;

--- or ---
if ('0' = PhaseSign) then
SineAmpWord <= LUT_Data;
else
SineAmpWord <= - LUT_Data;
end if;

A great reason for inferring this logic is because the tools may decide
to skip the mux and use an adder with one input being a N bit bus of the
control signal saving a bunch of logic. If I hardwired it as a mux it
would not be as efficient and coding it this way I don't have to think
about it. Then again the tools would likely optimize it either way. lol


Internally, that module will use either the verilog conditional
operator or VHDL WHEN operator. (Being use to C, I find the WHEN
syntax a little strange, but it doesn't take long to get used to.)

I suspect others will build a multiplexer using behavioral if
statements in either language.

OK, here is a multiplexer in VHDL:

library IEEE;
use IEEE.std_logic_1164.all;

entity N157 is
port (
Y : out std_logic_vector(3 downto 0);
A, B : in std_logic_vector(3 downto 0);
S, G: std_logic);
end entity N157;

architecture N157 of N157 is
begin
Y <= X"0" when G='1' else A when S='0' else B;
end architecture N157;

This is a terrible multiplexor module in VHDL. It is exactly 4 bits
wide when it could have been made N bits wide. Also it only works for
SLV data type when the example I use above will work for any types
available. BTW, what's with the name N157? Wouldn't it be better to
use something more descriptive? Otherwise, notice that all the work is
done in one line. Why go to all the trouble of the above when you only
need the one line?

Here is an example of a 5 to 1 mux by instantiation from a VHDL lecture.

--5:1 mux, 1 bit wide
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
LIBRARY adk;
USE adk.all;
ENTITY mux5_1_1wide IS
PORT(
a_input : IN STD_LOGIC; --input a
b_input : IN STD_LOGIC; --input b
c_input : IN STD_LOGIC; --input c
d_input : IN STD_LOGIC; --input d
e_input : IN STD_LOGIC; --input e
sel : IN STD_LOGIC_VECTOR(2 DOWNTO 0); --sel input
z_out : OUT STD_LOGIC --data out
);
END mux5_1_1wide;
ARCHITECTURE beh OF mux5_1_1wide IS
SIGNAL temp0, temp1, temp2, temp3 : STD_LOGIC;
COMPONENT mux21 PORT( a0,a1,s0 : IN STD_LOGIC;
y : OUT STD_LOGIC); END COMPONENT;
COMPONENT inv01 PORT( a : IN STD_LOGIC;
y : OUT STD_LOGIC); END COMPONENT;
BEGIN
U1 : mux21 PORT MAP(a0 => a_input,
a1 => b_input,
s0 => sel(0),
y => temp0);
U2 : mux21 PORT MAP(a0 => c_input,
a1 => d_input,
s0 => sel(0),
y => temp1);
U3 : mux21 PORT MAP(a0 => temp0,
a1 => temp1,
s0 => sel(1),
y => temp2);
U4 : mux21 PORT MAP(a0 => temp2,
a1 => e_input,
s0 => sel(2),
y => temp3);
U5 : inv01 PORT MAP(a => temp3,
y => z_out);
END beh;

Using behavioral descriptions.

--5:1 mux, 1 bit wide
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
LIBRARY adk;
USE adk.all;
ENTITY mux5_1_1wide IS
PORT(
a_input : IN STD_LOGIC; --input a
b_input : IN STD_LOGIC; --input b
c_input : IN STD_LOGIC; --input c
d_input : IN STD_LOGIC; --input d
e_input : IN STD_LOGIC; --input e
sel : IN STD_LOGIC_VECTOR(2 DOWNTO 0); --sel input
z_out : OUT STD_LOGIC --data out
);
END mux5_1_1wide;
ARCHITECTURE beh OF mux5_1_1wide IS
BEGIN
with sel select z_out <=
a_input when 0, -- count/2 = 1 for this choice
b_input when 1,
c_input when 2,
d_input when 3,
e_input when others;
END beh;

Which is simpler and more clear? If you were coding something more
complex, would you really want to code it by assembling pieces rather
than just describing what it does? I had to use the schematic produced
by synthesis to see what was done in the case of sel > 4 so I could code
the behavioral logic the same.


Once a process is defined, it can add another register with just three
rather simple lines of code. Declare the signal, initialize the signal
and assign the signal. Even creating a new process only adds two more
lines. Structural code for this requires at least as many lines of code
along with any generics and the common signals like reset and clocks.
Well, I count a lot of lines because I write in a spread out manner with
each I/O signal on it's own line. If you come from the Verilog world
your style may vary.

If it fits reasonably, I put a whole module/entity instatiation
on one line. I stay within 80 characters (for one, so that they print
nicely), so some will take more lines. Maybe that is from using
verilog first.

To do that you need to use positional association which is error prone.
Not a big deal for small entities, but harder to get right for large
ones with lots of I/O. I *always* use named association to prevent
difficult to find errors.


Still, I think the high and mid-level modules will become rather verbose
with structural code.

My early verilog was systolic arrays, with repeated blocks of fairly
simple code. The mid-level module fit on one or two pages, matching
fairly closely the register transfer logic that one might write.
Lower level were registers, adders, comparators, and multiplexers.
Top level instantiated some number of the unit cell in a linear array.

There will be some designs that suit instantiation well. I remember a
frequent poster here with a company specializing in high speed design in
Xilinx devices. He used hierarchical schematic design since it gave him
complete control over both the logic and placement via attributes
attached to the various symbols. When the rest of the world was moving
to HDL, he resisted until he was shown how he could do exactly the same
things in VHDL. He never looked back. Clearly structural HDL was the
way to go for him.

--

Rick
 
rickman <gnuarm@gmail.com> wrote:
(snip, I wrote)
I write structural verilog, or more recently structural VHDL.

I'm not sure what you mean by that. Everyone writes structural HDL.
But they also write the code in the blocks that gets connected by the
structural HDL. Don't you? That is the hard part.

(snip, I wrote)

Well, in verilog you can write combinatorial logic with either
continuous assignment not in an always block, or a behavioral
assignment (that is what the book nearby seems to call it) in
an always block. Two different ways to say the same thing.

The only way I make registers and latches in verilog is with
an always block. It might be that it can be done in VHDL without
a process block, but so far I use one, such that it looks similar
to the matching verilog.

Yes, if you want, you can describe a FF in a continuous assignment in
VHDL, but it is very unconventional and not very malleable.

I'm not sure why you are drawing some of the distinctions you do. I
have never seen anyone consider continuous assignments to be
"structural" HDL. Rather complex logic can be defined that way although
I think most logic ends up in processes or the equivalent.

OK, it seems that the book I have calls the continuous assignment
form data-flow model.

(snip)
Sure, the two are very different. Behavioral code requires thinking and
analysis. Structural code is just a matter of wiring together blocks.

I consider continuous assignment part of structural, though it might
have another name, and some logic goes in there.

I only consider instantiations to be structural. Continuous assignments
have several logical constructs which will infer logic and are often
used that way. It is actually seldom that I use continuous assignments
for structure since the connections are made in the component
instantiations. Why would I want to connect two wires with an
assignment unless there was something very odd going on like one wire
into a module connected to two wires going out? I don't know I have
ever done that.

A lot of my VHDL assignments are putting together or taking apart
vectors. It seems that VHDL feature is too new. So I have:

y29 <= (a, b, c, d);
-- instantiate entity using y29.

(snip)

Some can be written about the same either way. When I have a
choice between verilog continuous assignment and behavioral assignment,
I choose the former, others might choose the latter.

Not sure why that matters. If it generates logic, it is not structural.
I think we have a *big* difference in definitions. Behavioral does
not imply any type of assignment to me. It is a method of designing
logic by describing how the logic works rather than describing how it is
constructed. Both concurrent and sequential coding is used for
behavioral design.

Purely structural design would use instantiation only without inference
by any statement type other than within the primitive units.

I suppose, but structural plus continuous assignment takes too
long to write.

Of course my designs are never purely behavioral without use of module
instantiation. It is easier to test a design in pieces, then glue the
pieces together and test again. I think our disagreement is how far
down the modules are divided. My typical module size is a couple dozen
to a hundred or so lines. Although the really large ones are the top
level gluing it all together with structural code. One of my smaller
top level modules is over 600 lines of glue. Not hard to get right
using the tools that let me copy and paste with regular expression
conversions. Errors creep in when changes are made.

I suppose, but I do know people who write mostly behavioral,
with one big process block in each entity.

I usually put registers into their own module, even if that is the
only thing in the module.

One that I am working on now is exactly taking a design in SSI and
MSI and writing it in VHDL. The SSI (gates) go into assignment
statements with the appropriate logical operations. MSI (anything
more complicated than just gates) into a module. I can verify the
operation of the module once, and use it many times.

MSI is a very basic functional block. If you are using this very often
you likely are working at a very low level.

The point is that it is not rocket science to code a shift register or
counter. There is very little value in being able to say you have a
verified counter module. Not much different than saying you have a
verified multiplexor module which you say you do in continuous assignments.

If the design is already written in such blocks, it works well.

In the end, using such MSI components can be as error prone as writing
them from scratch. I avoid most errors in behavioral code by pulling up
an existing file and copying an arbitrary process for a registered
function and then editing the code. It also reduces the tedium. Then I
can focus on the specifics of what this function needs to do other than
be a register.

(snip)

As far as I know, some people like the way it looks more like a
software (sequential) programming language.

Not sure what you mean by this. Only the guts of processes, procedures
and functions look and feel like a sequential language. I think we may
be talking about different things because you include continuous
assignments as "structural".

OK, but continuous assignment isn't behavioral either.

Behavioral has its own assignment.

Actually, I realize using structural code at the lower levels would be
*very* verbose because none of the higher level structural code is
reduced. So writing high and mid-level modules in structural code would
add lots of verbiage.

Well, for example, I might write a multiplexer in a module, nice
combinatorial logic with no registers, then use that module wherever
I need a multiplexer, instead of rewriting one each time.

Yeah, that is the level of design that should be like falling off a log.
It is a one liner in a continuous assignment, five lines in a process
with two of them being ELSE and END IF;

Here is an example...

SineAmpWord <= LUT_Data when ('0' = PhaseSign) else - LUT_Data;

--- or ---
if ('0' = PhaseSign) then
SineAmpWord <= LUT_Data;
else
SineAmpWord <= - LUT_Data;
end if;

A great reason for inferring this logic is because the tools may decide
to skip the mux and use an adder with one input being a N bit bus of the
control signal saving a bunch of logic. If I hardwired it as a mux it
would not be as efficient and coding it this way I don't have to think
about it. Then again the tools would likely optimize it either way. lol

The tools are pretty good. Sometimes a small mistake and half the
logic gets optimized away.

Internally, that module will use either the verilog conditional
operator or VHDL WHEN operator. (Being use to C, I find the WHEN
syntax a little strange, but it doesn't take long to get used to.)

I suspect others will build a multiplexer using behavioral if
statements in either language.

OK, here is a multiplexer in VHDL:

library IEEE;
use IEEE.std_logic_1164.all;

entity N157 is
port (
Y : out std_logic_vector(3 downto 0);
A, B : in std_logic_vector(3 downto 0);
S, G: std_logic);
end entity N157;

architecture N157 of N157 is
begin
Y <= X"0" when G='1' else A when S='0' else B;
end architecture N157;

This is a terrible multiplexor module in VHDL. It is exactly 4 bits
wide when it could have been made N bits wide. Also it only works for
SLV data type when the example I use above will work for any types
available. BTW, what's with the name N157?

It is the logic of the 74157.

Wouldn't it be better to
use something more descriptive? Otherwise, notice that all the work is
done in one line. Why go to all the trouble of the above when you only
need the one line?

Here is an example of a 5 to 1 mux by instantiation from a VHDL lecture.

--5:1 mux, 1 bit wide
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
LIBRARY adk;
USE adk.all;
ENTITY mux5_1_1wide IS
PORT(
a_input : IN STD_LOGIC; --input a
b_input : IN STD_LOGIC; --input b
c_input : IN STD_LOGIC; --input c
d_input : IN STD_LOGIC; --input d
e_input : IN STD_LOGIC; --input e
sel : IN STD_LOGIC_VECTOR(2 DOWNTO 0); --sel input
z_out : OUT STD_LOGIC --data out
);
END mux5_1_1wide;
ARCHITECTURE beh OF mux5_1_1wide IS
SIGNAL temp0, temp1, temp2, temp3 : STD_LOGIC;
COMPONENT mux21 PORT( a0,a1,s0 : IN STD_LOGIC;
y : OUT STD_LOGIC); END COMPONENT;
COMPONENT inv01 PORT( a : IN STD_LOGIC;
y : OUT STD_LOGIC); END COMPONENT;
BEGIN
U1 : mux21 PORT MAP(a0 => a_input,
a1 => b_input,
s0 => sel(0),
y => temp0);
U2 : mux21 PORT MAP(a0 => c_input,
a1 => d_input,
s0 => sel(0),
y => temp1);
U3 : mux21 PORT MAP(a0 => temp0,
a1 => temp1,
s0 => sel(1),
y => temp2);
U4 : mux21 PORT MAP(a0 => temp2,
a1 => e_input,
s0 => sel(2),
y => temp3);
U5 : inv01 PORT MAP(a => temp3,
y => z_out);
END beh;

Using behavioral descriptions.

--5:1 mux, 1 bit wide
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
LIBRARY adk;
USE adk.all;
ENTITY mux5_1_1wide IS
PORT(
a_input : IN STD_LOGIC; --input a
b_input : IN STD_LOGIC; --input b
c_input : IN STD_LOGIC; --input c
d_input : IN STD_LOGIC; --input d
e_input : IN STD_LOGIC; --input e
sel : IN STD_LOGIC_VECTOR(2 DOWNTO 0); --sel input
z_out : OUT STD_LOGIC --data out
);
END mux5_1_1wide;
ARCHITECTURE beh OF mux5_1_1wide IS
BEGIN
with sel select z_out <=
a_input when 0, -- count/2 = 1 for this choice
b_input when 1,
c_input when 2,
d_input when 3,
e_input when others;
END beh;

Which is simpler and more clear?

If the logic is already written using such blocks, it is much easier
to write VHDL from those blocks, and then verify that they look
like the original design.

If you were coding something more
complex, would you really want to code it by assembling pieces rather
than just describing what it does? I had to use the schematic produced
by synthesis to see what was done in the case of sel > 4 so I could code
the behavioral logic the same.

Also, as well as I know it, that isn't behavioral.

For behavioral verilog it would look something like:

always @(*) begin
if (sel=0) then z_out <= a_input
else if (sel=1) then z_out <= b_input
else if (sel=2) then z_out <= c_input
else if (sel=3) then z_out <= d_input
else z_out <= e_input;
end

or I suppose the verilog case statement.

The non-behavioral verilog form is:

assign zout <= sel=0 ? a_input :
sel=1 ? b_input :
sel=2 ? c_input :
sel=3 ? d_input :
e_input :

(snip)

If it fits reasonably, I put a whole module/entity instatiation
on one line. I stay within 80 characters (for one, so that they print
nicely), so some will take more lines. Maybe that is from using
verilog first.

To do that you need to use positional association which is error prone.
Not a big deal for small entities, but harder to get right for large
ones with lots of I/O. I *always* use named association to prevent
difficult to find errors.

Still, I think the high and mid-level modules will become rather verbose
with structural code.

My early verilog was systolic arrays, with repeated blocks of fairly
simple code. The mid-level module fit on one or two pages, matching
fairly closely the register transfer logic that one might write.
Lower level were registers, adders, comparators, and multiplexers.
Top level instantiated some number of the unit cell in a linear array.

There will be some designs that suit instantiation well. I remember a
frequent poster here with a company specializing in high speed design in
Xilinx devices. He used hierarchical schematic design since it gave him
complete control over both the logic and placement via attributes
attached to the various symbols. When the rest of the world was moving
to HDL, he resisted until he was shown how he could do exactly the same
things in VHDL. He never looked back. Clearly structural HDL was the
way to go for him.

-- glen
 
On 9/13/2015 1:35 AM, glen herrmannsfeldt wrote:
rickman <gnuarm@gmail.com> wrote:
(snip, I wrote)
I write structural verilog, or more recently structural VHDL.

I'm not sure what you mean by that. Everyone writes structural HDL.
But they also write the code in the blocks that gets connected by the
structural HDL. Don't you? That is the hard part.

(snip, I wrote)

Well, in verilog you can write combinatorial logic with either
continuous assignment not in an always block, or a behavioral
assignment (that is what the book nearby seems to call it) in
an always block. Two different ways to say the same thing.

The only way I make registers and latches in verilog is with
an always block. It might be that it can be done in VHDL without
a process block, but so far I use one, such that it looks similar
to the matching verilog.

Yes, if you want, you can describe a FF in a continuous assignment in
VHDL, but it is very unconventional and not very malleable.

I'm not sure why you are drawing some of the distinctions you do. I
have never seen anyone consider continuous assignments to be
"structural" HDL. Rather complex logic can be defined that way although
I think most logic ends up in processes or the equivalent.

OK, it seems that the book I have calls the continuous assignment
form data-flow model.

"Data-flow" is a completely unrelated concept from my experience. I
have no idea what they mean by that. Verilog jargon perhaps? I am not
conversant in Verilog as much as VHDL where they are called concurrent
assignments.

There is no difference between a concurrent assignment and a process
with just one assignment and a sensitivity list with all input signals.
In general, a process can have many assignments including variable vs.
signals and the sensitivity list can include just a subset such as (clk,
rst) for a clocked process.

I looked up "Verilog data flow" and found no real definition of it and
found it used in different ways on each page. One page refers to
"structural data flow modelling" and "Behavioral data flow modelling".

I think the term "data flow" should be ignored in this context and just
"structural" and "behavioral" should be used.

In my book (the one in my head) "behavioral" includes any inference of
logic while "structural" is instantiated.

To muddy the waters a bit, I see the term "RTL" (register transfer
level) which is behavioral, but implies the level of abstraction does
not rise above describing specific registers and logic.


(snip)
Sure, the two are very different. Behavioral code requires thinking and
analysis. Structural code is just a matter of wiring together blocks.

I consider continuous assignment part of structural, though it might
have another name, and some logic goes in there.

I only consider instantiations to be structural. Continuous assignments
have several logical constructs which will infer logic and are often
used that way. It is actually seldom that I use continuous assignments
for structure since the connections are made in the component
instantiations. Why would I want to connect two wires with an
assignment unless there was something very odd going on like one wire
into a module connected to two wires going out? I don't know I have
ever done that.

A lot of my VHDL assignments are putting together or taking apart
vectors. It seems that VHDL feature is too new. So I have:

y29 <= (a, b, c, d);
-- instantiate entity using y29.

I am pretty sure you can use (a, b, c, d) in the component port map.
But there are some specific details on this and I haven't done much with
any HDL for a while so I've forgotten the finer points. (a, b, c, d) is
called and aggregate in VHDL.


Some can be written about the same either way. When I have a
choice between verilog continuous assignment and behavioral assignment,
I choose the former, others might choose the latter.

Not sure why that matters. If it generates logic, it is not structural.
I think we have a *big* difference in definitions. Behavioral does
not imply any type of assignment to me. It is a method of designing
logic by describing how the logic works rather than describing how it is
constructed. Both concurrent and sequential coding is used for
behavioral design.

Purely structural design would use instantiation only without inference
by any statement type other than within the primitive units.

I suppose, but structural plus continuous assignment takes too
long to write.

I don't follow. I thought you said that was what you do!


Of course my designs are never purely behavioral without use of module
instantiation. It is easier to test a design in pieces, then glue the
pieces together and test again. I think our disagreement is how far
down the modules are divided. My typical module size is a couple dozen
to a hundred or so lines. Although the really large ones are the top
level gluing it all together with structural code. One of my smaller
top level modules is over 600 lines of glue. Not hard to get right
using the tools that let me copy and paste with regular expression
conversions. Errors creep in when changes are made.

I suppose, but I do know people who write mostly behavioral,
with one big process block in each entity.

Yeah, I find one process per entity to be a bit awkward. I use multiple
processes to organize my thoughts. So each process will have a
functional purpose. Some small like a resynchronizer with just two FFs,
or some large with logic that is more than one register, but with
complex interaction which are awkward to break apart. Personal
preference. I just don't like very large processes so that it becomes
hard to see what is going on.


I usually put registers into their own module, even if that is the
only thing in the module.

One that I am working on now is exactly taking a design in SSI and
MSI and writing it in VHDL. The SSI (gates) go into assignment
statements with the appropriate logical operations. MSI (anything
more complicated than just gates) into a module. I can verify the
operation of the module once, and use it many times.

MSI is a very basic functional block. If you are using this very often
you likely are working at a very low level.

The point is that it is not rocket science to code a shift register or
counter. There is very little value in being able to say you have a
verified counter module. Not much different than saying you have a
verified multiplexor module which you say you do in continuous assignments.

If the design is already written in such blocks, it works well.

In the end, using such MSI components can be as error prone as writing
them from scratch. I avoid most errors in behavioral code by pulling up
an existing file and copying an arbitrary process for a registered
function and then editing the code. It also reduces the tedium. Then I
can focus on the specifics of what this function needs to do other than
be a register.

(snip)

As far as I know, some people like the way it looks more like a
software (sequential) programming language.

Not sure what you mean by this. Only the guts of processes, procedures
and functions look and feel like a sequential language. I think we may
be talking about different things because you include continuous
assignments as "structural".

OK, but continuous assignment isn't behavioral either.

Behavioral has its own assignment.

I don't know what this means. Behavioral isn't part of an HDL language.
It refers to how you write your code. By instantiating low level
primitives you are defining your design by the gates used (even if the
tools will optimize that as it sees fit). Behavioral means you describe
what the logic does. You can only do structural using instantiation.
If you use concurrent assignments or processes to do anything other than
connect wires you are inferring logic based on a description of what it
does, not the gates it is made of.


Actually, I realize using structural code at the lower levels would be
*very* verbose because none of the higher level structural code is
reduced. So writing high and mid-level modules in structural code would
add lots of verbiage.

Well, for example, I might write a multiplexer in a module, nice
combinatorial logic with no registers, then use that module wherever
I need a multiplexer, instead of rewriting one each time.

Yeah, that is the level of design that should be like falling off a log.
It is a one liner in a continuous assignment, five lines in a process
with two of them being ELSE and END IF;

Here is an example...

SineAmpWord <= LUT_Data when ('0' = PhaseSign) else - LUT_Data;

--- or ---
if ('0' = PhaseSign) then
SineAmpWord <= LUT_Data;
else
SineAmpWord <= - LUT_Data;
end if;

A great reason for inferring this logic is because the tools may decide
to skip the mux and use an adder with one input being a N bit bus of the
control signal saving a bunch of logic. If I hardwired it as a mux it
would not be as efficient and coding it this way I don't have to think
about it. Then again the tools would likely optimize it either way. lol

The tools are pretty good. Sometimes a small mistake and half the
logic gets optimized away.

Internally, that module will use either the verilog conditional
operator or VHDL WHEN operator. (Being use to C, I find the WHEN
syntax a little strange, but it doesn't take long to get used to.)

I suspect others will build a multiplexer using behavioral if
statements in either language.

OK, here is a multiplexer in VHDL:

library IEEE;
use IEEE.std_logic_1164.all;

entity N157 is
port (
Y : out std_logic_vector(3 downto 0);
A, B : in std_logic_vector(3 downto 0);
S, G: std_logic);
end entity N157;

architecture N157 of N157 is
begin
Y <= X"0" when G='1' else A when S='0' else B;
end architecture N157;

This is a terrible multiplexor module in VHDL. It is exactly 4 bits
wide when it could have been made N bits wide. Also it only works for
SLV data type when the example I use above will work for any types
available. BTW, what's with the name N157?

It is the logic of the 74157.

Wouldn't it be better to
use something more descriptive? Otherwise, notice that all the work is
done in one line. Why go to all the trouble of the above when you only
need the one line?

Here is an example of a 5 to 1 mux by instantiation from a VHDL lecture.

--5:1 mux, 1 bit wide
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
LIBRARY adk;
USE adk.all;
ENTITY mux5_1_1wide IS
PORT(
a_input : IN STD_LOGIC; --input a
b_input : IN STD_LOGIC; --input b
c_input : IN STD_LOGIC; --input c
d_input : IN STD_LOGIC; --input d
e_input : IN STD_LOGIC; --input e
sel : IN STD_LOGIC_VECTOR(2 DOWNTO 0); --sel input
z_out : OUT STD_LOGIC --data out
);
END mux5_1_1wide;
ARCHITECTURE beh OF mux5_1_1wide IS
SIGNAL temp0, temp1, temp2, temp3 : STD_LOGIC;
COMPONENT mux21 PORT( a0,a1,s0 : IN STD_LOGIC;
y : OUT STD_LOGIC); END COMPONENT;
COMPONENT inv01 PORT( a : IN STD_LOGIC;
y : OUT STD_LOGIC); END COMPONENT;
BEGIN
U1 : mux21 PORT MAP(a0 => a_input,
a1 => b_input,
s0 => sel(0),
y => temp0);
U2 : mux21 PORT MAP(a0 => c_input,
a1 => d_input,
s0 => sel(0),
y => temp1);
U3 : mux21 PORT MAP(a0 => temp0,
a1 => temp1,
s0 => sel(1),
y => temp2);
U4 : mux21 PORT MAP(a0 => temp2,
a1 => e_input,
s0 => sel(2),
y => temp3);
U5 : inv01 PORT MAP(a => temp3,
y => z_out);
END beh;

Using behavioral descriptions.

--5:1 mux, 1 bit wide
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
LIBRARY adk;
USE adk.all;
ENTITY mux5_1_1wide IS
PORT(
a_input : IN STD_LOGIC; --input a
b_input : IN STD_LOGIC; --input b
c_input : IN STD_LOGIC; --input c
d_input : IN STD_LOGIC; --input d
e_input : IN STD_LOGIC; --input e
sel : IN STD_LOGIC_VECTOR(2 DOWNTO 0); --sel input
z_out : OUT STD_LOGIC --data out
);
END mux5_1_1wide;
ARCHITECTURE beh OF mux5_1_1wide IS
BEGIN
with sel select z_out <=
a_input when 0, -- count/2 = 1 for this choice
b_input when 1,
c_input when 2,
d_input when 3,
e_input when others;
END beh;

Which is simpler and more clear?

If the logic is already written using such blocks, it is much easier
to write VHDL from those blocks, and then verify that they look
like the original design.

I don't understand. If the blocks were there, you don't need to write
anything. The above example illustrates how simpler behavioral code is
than structural code once you are working with higher levels of logic.
This is not even a very high level. Try structurally coding a UART with
full handshake controls and flags. A UART is a very simple IP block.
Then imagine coding a USB controller.


If you were coding something more
complex, would you really want to code it by assembling pieces rather
than just describing what it does? I had to use the schematic produced
by synthesis to see what was done in the case of sel > 4 so I could code
the behavioral logic the same.

Also, as well as I know it, that isn't behavioral.

For behavioral verilog it would look something like:

always @(*) begin
if (sel=0) then z_out <= a_input
else if (sel=1) then z_out <= b_input
else if (sel=2) then z_out <= c_input
else if (sel=3) then z_out <= d_input
else z_out <= e_input;
end

or I suppose the verilog case statement.

The non-behavioral verilog form is:

assign zout <= sel=0 ? a_input :
sel=1 ? b_input :
sel=2 ? c_input :
sel=3 ? d_input :
e_input :

Both of these are behavioral. You are describing how the circuit
behaves, not the gates used to implement it. The only difference is one
is continuous and the other is sequential.

Someone is giving you bad information. I hope this helps some.

--

Rick
 
rickman <gnuarm@gmail.com> wrote:

(snip, I wrote)

A lot of my VHDL assignments are putting together or taking apart
vectors. It seems that VHDL feature is too new. So I have:

y29 <= (a, b, c, d);
-- instantiate entity using y29.

I am pretty sure you can use (a, b, c, d) in the component port map.
But there are some specific details on this and I haven't done much with
any HDL for a while so I've forgotten the finer points. (a, b, c, d) is
called and aggregate in VHDL.

It seems that this changed over the years.

As for Xilinx ISE, it works in the port for some devices, but
not others. Doesn't make much sense, but they use a different VHDL
parser for Spartan 3E and for Spartan 6. One allows it, one doesn't.

Even newer in VHDL is the ability to do that in an output port.
(or the left side of an assignment) like you could do in verilog
for many years.

But if can get a little ugly if not done carefully.

-- glen
 
rickman <gnuarm@gmail.com> wrote:

(snip)

There is no difference between a concurrent assignment and a process
with just one assignment and a sensitivity list with all input signals.
In general, a process can have many assignments including variable vs.
signals and the sensitivity list can include just a subset such as (clk,
rst) for a clocked process.

(snip)

I suppose, but structural plus continuous assignment takes too
long to write.

I don't follow. I thought you said that was what you do!

I mean the name of it takes too long to write. That is why I call
it structural, even though it is more.

(snip, I wrote)

OK, but continuous assignment isn't behavioral either.

Behavioral has its own assignment.

I don't know what this means. Behavioral isn't part of an HDL language.
It refers to how you write your code. By instantiating low level
primitives you are defining your design by the gates used (even if the
tools will optimize that as it sees fit). Behavioral means you describe
what the logic does. You can only do structural using instantiation.
If you use concurrent assignments or processes to do anything other than
connect wires you are inferring logic based on a description of what it
does, not the gates it is made of.

Behavioral model is inside verilog always blocks, and VHDL process
blocks, and yes it describes what the logic does.

(snip, I wrote)

If the logic is already written using such blocks, it is much easier
to write VHDL from those blocks, and then verify that they look
like the original design.

I don't understand. If the blocks were there, you don't need to write
anything. The above example illustrates how simpler behavioral code is
than structural code once you are working with higher levels of logic.
This is not even a very high level. Try structurally coding a UART with
full handshake controls and flags. A UART is a very simple IP block.
Then imagine coding a USB controller.

I am converting an existing design, made with TTL and such, into VHDL.
By following the TTL MSI blocks, I can do that with minimal thinking
and minimal mistakes. I don't have to understand what the logic does,
just be sure that what I write does the same thing as the original.

(snip, I wrote)
For behavioral verilog it would look something like:

always @(*) begin
if (sel=0) then z_out <= a_input
else if (sel=1) then z_out <= b_input
else if (sel=2) then z_out <= c_input
else if (sel=3) then z_out <= d_input
else z_out <= e_input;
end

or I suppose the verilog case statement.

The non-behavioral verilog form is:

assign zout <= sel=0 ? a_input :
sel=1 ? b_input :
sel=2 ? c_input :
sel=3 ? d_input :
e_input :

Both of these are behavioral. You are describing how the circuit
behaves, not the gates used to implement it. The only difference is one
is continuous and the other is sequential.

Someone is giving you bad information. I hope this helps some.

Well, I pretty much learned verilog from the Thomas and Moorby book,
and if you claim that they are wrong, many people will disagree.

They don't make it so obvious, but early on they have an example
of a 16 bit counter in structural model, which does include a
continuous assignment to indicate when the counter is about to
overflow.

Later on, they have a behavioral model counter, which doesn't
use continuous assignment, but with all the logic inside an
always block. The actual block looks something like:

always
begin
@(negedge clock) #10 value = value + 1;
if(value==15)
begin
altFifteen=1;
fifteen=1;
end
else
begin
altFifteen=0;
fifteen=0;
end
end
endmodule

They call it behavioral model, and so do I.

Note, for example, that the assignment are not continuous,
but only done with the appropriate if condition.

Well, read chapter 1 of Thomas and Moorby, and see what you think
qualifies as behavioral, or not behavioral, logic.

-- glen
 
Evgeny Filatov <e.v.filatov@ieee.org> wrote:

(snip, I wrote)

I do remember using schematic drawing tools, but most often found
it took a lot of work drawing lines, making sure that they didn't
overlap what they weren't supposed to, and otherwise getting it right.

But I can write some lines of verilog or VHDL and not have to worry
about such lines overlapping. Match up signal names and everything
works the way it is supposed to.

(snip)

Tim is correct. An example (GPS C/A stuff):

http://tinyurl.com/nfmqjzm

I just suck at writing in VHDL/verilog. Should practice more.

OK, the tools are surprisingly good at doing what needs to be done.

If the problem is well described at the higher level, it is probably
fine.

If you need the highest speed, though, you might need to pipeline it,
and that might not be so easy from the high level representation.

If it is fast enough, and the high-level logic mostly does what
you want, you might not need to worry.

-- glen
 
On 12.09.2015 21:10, glen herrmannsfeldt wrote:
Tim Wescott <tim@seemywebsite.com> wrote:
(snip)
Evgeny Filatov <e.v.filatov@ieee.org> wrote:

I use graphical high-level tools to design DSP stuff and generate RTL
for it. It works for me, but I started to suspect that it is more
efficient to write RTL in HDL languages instead.

I'm assuming he means that he draws up a block diagram in Simulink and
then pushes a button (well, maybe after lots of simulation and analysis).

But I'm just assuming.

I do remember using schematic drawing tools, but most often found
it took a lot of work drawing lines, making sure that they didn't
overlap what they weren't supposed to, and otherwise getting it right.

But I can write some lines of verilog or VHDL and not have to worry
about such lines overlapping. Match up signal names and everything
works the way it is supposed to.

But I suppose something like simulink isn't so bad. Generate the
VHDL or verilog, look at it, and see if it looks right.

-- glen

Tim is correct. An example (GPS C/A stuff):

http://tinyurl.com/nfmqjzm

I just suck at writing in VHDL/verilog. Should practice more.

Regards,
Evgeny.
 
On 9/13/2015 5:34 PM, glen herrmannsfeldt wrote:
rickman <gnuarm@gmail.com> wrote:

(snip)

There is no difference between a concurrent assignment and a process
with just one assignment and a sensitivity list with all input signals.
In general, a process can have many assignments including variable vs.
signals and the sensitivity list can include just a subset such as (clk,
rst) for a clocked process.

(snip)

I suppose, but structural plus continuous assignment takes too
long to write.

I don't follow. I thought you said that was what you do!

I mean the name of it takes too long to write. That is why I call
it structural, even though it is more.

Ok, but that means our conversation has mostly been one large
misunderstanding...

I think what you mean is you don't use processes other than for
describing specific registers or something like that.


OK, but continuous assignment isn't behavioral either.

Behavioral has its own assignment.

I don't know what this means. Behavioral isn't part of an HDL language.
It refers to how you write your code. By instantiating low level
primitives you are defining your design by the gates used (even if the
tools will optimize that as it sees fit). Behavioral means you describe
what the logic does. You can only do structural using instantiation.
If you use concurrent assignments or processes to do anything other than
connect wires you are inferring logic based on a description of what it
does, not the gates it is made of.

Behavioral model is inside verilog always blocks, and VHDL process
blocks, and yes it describes what the logic does.

There is the core of our misunderstanding. No one else I have found
uses that definition of "behavioral".


If the logic is already written using such blocks, it is much easier
to write VHDL from those blocks, and then verify that they look
like the original design.

I don't understand. If the blocks were there, you don't need to write
anything. The above example illustrates how simpler behavioral code is
than structural code once you are working with higher levels of logic.
This is not even a very high level. Try structurally coding a UART with
full handshake controls and flags. A UART is a very simple IP block.
Then imagine coding a USB controller.

I am converting an existing design, made with TTL and such, into VHDL.
By following the TTL MSI blocks, I can do that with minimal thinking
and minimal mistakes. I don't have to understand what the logic does,
just be sure that what I write does the same thing as the original.

Sure, that is ideal for structural code. Duplicating something similar
to a schematic. But your definitions of the TTL components is most
likely to be behavioral. It is not too hard to design a 74x138 with
gates. The TI data sheet shows a schematic with 25 gates in it. Much
easier to do it with a simple with select statement inside an if as part
of a process.


For behavioral verilog it would look something like:

always @(*) begin
if (sel=0) then z_out <= a_input
else if (sel=1) then z_out <= b_input
else if (sel=2) then z_out <= c_input
else if (sel=3) then z_out <= d_input
else z_out <= e_input;
end

or I suppose the verilog case statement.

The non-behavioral verilog form is:

assign zout <= sel=0 ? a_input :
sel=1 ? b_input :
sel=2 ? c_input :
sel=3 ? d_input :
e_input :

Both of these are behavioral. You are describing how the circuit
behaves, not the gates used to implement it. The only difference is one
is continuous and the other is sequential.

Someone is giving you bad information. I hope this helps some.

Well, I pretty much learned verilog from the Thomas and Moorby book,
and if you claim that they are wrong, many people will disagree.

They don't make it so obvious, but early on they have an example
of a 16 bit counter in structural model, which does include a
continuous assignment to indicate when the counter is about to
overflow.

Later on, they have a behavioral model counter, which doesn't
use continuous assignment, but with all the logic inside an
always block. The actual block looks something like:

always
begin
@(negedge clock) #10 value = value + 1;
if(value==15)
begin
altFifteen=1;
fifteen=1;
end
else
begin
altFifteen=0;
fifteen=0;
end
end
endmodule

They call it behavioral model, and so do I.

Ok, but you really should read a bit more widely. You will find the
definition of "behavioral" has nothing to do with always blocks or
processes. It means the code is describing the behavior of the logic in
contrast to "structural" which is showing how blocks of logic are wired
together. "Continuous" assignments describe the behavior of the signal
they are assigned. They are equivalent to processes in all ways.


Note, for example, that the assignment are not continuous,
but only done with the appropriate if condition.

You are confusing "continuous" with non-behavioral. The assignments
work the same way regardless.

I can't speak for sure about Verilog, but I expect it works the same as
VHDL. "Continuous" assignments are the same as processes which have all
inputs to the assignment in the sensitivity list. This means the
process (or continuous assignment) does not run until one of the inputs
changes. Then the assignments are evaluated to produce an output which
may or may not have changed.

The fact that an IF is used in a process does not mean it is not
"continuous" in any mechanical sense. This is just a description of a
logic function. The signals in the IF statement are either assigned one
of two possible values (the THEN clause or the ELSE clause) or if no
assignment is included in one that infers a register or latch depending
on the outer logic (such as an IF clock or @(negedge clock)).

process (PhaseSign, LUT_Data) begin
if ('0' = PhaseSign) then
SineAmpWord <= LUT_Data;
else
SineAmpWord <= - LUT_Data;
end if;
end process;

This is exactly equivalent to this concurrent statement.

SineAmpWord <= LUT_Data when ('0' = PhaseSign) else - LUT_Data;

and to this Verilog always block I think...

always @ (in)
begin
if ('0' = PhaseSign) begin
SineAmpWord <= LUT_Data;
end else begin
SineAmpWord <= - LUT_Data;
end
end

or to this...

assign SineAmpWord <= ('0' = PhaseSign) ? LUT_Data : - LUT_Data;

There is no reason to distinguish between any of these functionally or
by thinking one runs "all the time" or any other meaning of the term
"continuous", even though some refer to it as if it truly were analyzed
"continuously".


Well, read chapter 1 of Thomas and Moorby, and see what you think
qualifies as behavioral, or not behavioral, logic.

I don't have that book. I have a few others on VHDL and none of them
say the term behavioral implies anything about the specifics of the
coding other than instantiation (structural) and inference (behavioral).
Try looking about the web. I am sure you will find tons of info on
this. I did and found a few Verilog references that use behavioral the
way you do, but they are not the majority.

I would say the terms structural and behavioral are not well or
certainly not consistently defined, so perhaps thy are poor terms to use.

--

Rick
 
On 9/13/2015 6:20 PM, Evgeny Filatov wrote:
On 12.09.2015 21:10, glen herrmannsfeldt wrote:
Tim Wescott <tim@seemywebsite.com> wrote:
(snip)
Evgeny Filatov <e.v.filatov@ieee.org> wrote:

I use graphical high-level tools to design DSP stuff and generate RTL
for it. It works for me, but I started to suspect that it is more
efficient to write RTL in HDL languages instead.

I'm assuming he means that he draws up a block diagram in Simulink and
then pushes a button (well, maybe after lots of simulation and
analysis).

But I'm just assuming.

I do remember using schematic drawing tools, but most often found
it took a lot of work drawing lines, making sure that they didn't
overlap what they weren't supposed to, and otherwise getting it right.

But I can write some lines of verilog or VHDL and not have to worry
about such lines overlapping. Match up signal names and everything
works the way it is supposed to.

But I suppose something like simulink isn't so bad. Generate the
VHDL or verilog, look at it, and see if it looks right.

-- glen



Tim is correct. An example (GPS C/A stuff):

http://tinyurl.com/nfmqjzm

I just suck at writing in VHDL/verilog. Should practice more.

Certainly VHDL can be verbose and it can present stumbling blocks to a
newbie. I came from a world of schematics, so it isn't hard to impress
me considering the huge improvement in productivity.

If I ever find a good Verilog book, I will get more proficient with it.

--

Rick
 
rickman wrote:

On 9/11/2015 11:42 PM, glen herrmannsfeldt wrote:

I write structural verilog, or more recently structural VHDL.

I'm not sure what you mean by that. Everyone writes structural HDL.
But they also write the code in the blocks that gets connected by the
structural HDL. Don't you? That is the hard part.
Well, at least in VHDL, there is structural and behavioral. Behavioral VHDL
looks like

a <= b or c;


where structural looks like defining sub-components and then linking signals
through their ports. So, you define 2-input OR gates, FF's and similar
basic devices, and then wire them together with signals.

Jon
 
On 9/14/2015 3:01 PM, Jon Elson wrote:
rickman wrote:

On 9/11/2015 11:42 PM, glen herrmannsfeldt wrote:

I write structural verilog, or more recently structural VHDL.

I'm not sure what you mean by that. Everyone writes structural HDL.
But they also write the code in the blocks that gets connected by the
structural HDL. Don't you? That is the hard part.

Well, at least in VHDL, there is structural and behavioral. Behavioral VHDL
looks like

a <= b or c;


where structural looks like defining sub-components and then linking signals
through their ports. So, you define 2-input OR gates, FF's and similar
basic devices, and then wire them together with signals.

The confusion seems to come from the fact that a small number of Verilog
texts and university materials use the terms for something other than
what most of us use them for. Seems some use "behavioral" for code
written in always blocks and "structural" for all other code.

Most references use the term "behavioral" as you seem to be using it,
for code that largely describes the behavior in code that is then used
to infer the logic to implement the behavior. Structural code would be
purely instantiating logic entities that exist.

What ever the case, I think Glen and I understand each other. Glen
doesn't like to use always blocks or processes and I am happy using them
while minimizing my use of instantiation.

--

Rick
 

Welcome to EDABoard.com

Sponsor

Back
Top