Atom HDL

T

Tom

Hello,

Atom is a new high-level hardware description language embedded in
the functional language Haskell. Atom compiles circuit descriptions
in conditional term rewriting systems down to Verilog and VHDL
for IC simulation, verification, and synthesis.

Programming in Atom feels a lot like object oriented design because
module interfaces use methods, instead of just wires and bits.

We've used Atom successfully on several different "test" designs
including bus arbitration, packet routing, memory interfaces,
DSP, serial interface controllers, and error correction coding.
In fact, an early version of Atom compiled the 802.11an LDPC
codec posted to opencores.org.

The language is a bit in flux, and the documentation, tutorial,
and examples are pretty sparse. But if you're interested
in new ways to design hardware, and your not intimidated
by Haskell, give Atom a try. It's free.

http://funhdl.org/wiki/doku.php/atom

-Tom
 
T

tkvhdl

Hello,

Atom is a new high-level hardware description language embedded in
the functional language Haskell. Atom compiles circuit descriptions
in conditional term rewriting systems down to Verilog and VHDL
for IC simulation, verification, and synthesis.

Programming in Atom feels a lot like object oriented design because
module interfaces use methods, instead of just wires and bits.

We've used Atom successfully on several different "test" designs
including bus arbitration, packet routing, memory interfaces,
DSP, serial interface controllers, and error correction coding.
In fact, an early version of Atom compiled the 802.11an LDPC
codec posted to opencores.org.

The language is a bit in flux, and the documentation, tutorial,
and examples are pretty sparse. But if you're interested
in new ways to design hardware, and your not intimidated
by Haskell, give Atom a try. It's free.

http://funhdl.org/wiki/doku.php/atom

-Tom

Looks interesting, but very little info on the website.
How does this compare to Lava (Haskell), HDFS (F#) or i was going to
say confluence, (but it looks like confluence is becoming Atom)?
Has anyone outside of the developers tried any of these or have
opinions?
 
J

Jim Granville

Looks interesting, but very little info on the website.
How does this compare to Lava (Haskell), HDFS (F#) or i was going to
say confluence, (but it looks like confluence is becoming Atom)?
Has anyone outside of the developers tried any of these or have
opinions?

There is also this Python-derived flow :

http://myhdl.jandecaluwe.com/doku.php/start

How does Atom compare with that?
MyHDL is also a 'cross-compiler', that exports verilog code.

-jg
 
T

Tom

Looks interesting, but very little info on the website.
How does this compare to Lava (Haskell), HDFS (F#) or i was going to
say confluence, (but it looks like confluence is becoming Atom)?

Lava, HDFS, HDCaml, and Confluence use functional programing to
describe
the structure of a hardware circuit. In these languages, functions
are used
to assemble parametric hardware blocks from a collection of logic
primitives
(eg. gates, arithmetics, comparisons, registers, etc). Lava is step
above the
crowd in that it also gives the designer control of layout.

Even though these languages offer many benefits over Verilog and VHDL,
designers still must manually wire up every logic primitive in the
design.
Thus, one could argue they are still at the register transfer
abstraction level (RTL).

Atom is bit different. Designers still have to declare registers and
combinational
functions of these registers, but now Atom synthesizes control logic
to connect
the combinational functions to the register inputs for the next-state
calculations.
In a sense, the Atom compiler is now making design decisions that a
human has
to do today with any RTL HDL (Verilog, VHDL, Lava, HDFS, et al).

To address Jim's question in the following post:
There is also this Python-derived flow :
How does Atom compare with that?
MyHDL is also a 'cross-compiler', that exports verilog code.

I don't have experience with MyHDL, so my statements may need to be
qualified. From what
I gather, MyHDL very closely approximates the semantics of Verilog
(@always(clock.posedge)).
Therefore I suspect, in terms of synthesis, MyHDL is still at RTL.

Where MyHDL shines, is it's ability to simulate within it's host
language, Python.
If locked in a room with SystemVerilog and Python, I'd take Python any
day. If offered
OCaml or Haskell, I'll always reach for higher-order functional
languages.

-Tom
 
M

Mike Treseler

T

Tom

I think I disagree.
RTL++ anyway.

Have a look at this example.
source:http://myhdl.jandecaluwe.com/doku.php/cookbook:sinecomp

I would even say it's RTL# -- there's a ton of cool elaboration taking
place. But "yield clock.posedge" is still just an always block.

Here's how a cordic processor could look in Atom. Atom's strength is
control logic. So for clarity, I'll ignore the datapath details:

http://funhdl.org/wiki/doku.php/atom:tutorial:cordic

Unlike RTL, Atom's module interfaces are object-oriented. If an
external block wants to start a computation, it calls the loadData
method. When it wants the result, it calls getResult.

In addition, such interfaces support multiple consumers and
producers. If two blocks are trying to call loadData at the same
time, the Atom compiler will automatically handle the arbitration.

More importantly, the Atom compiler guarantees correctness across
module interfaces. If CORDIC is known to be correct on the inside,
there is nothing an external block can do to break it from the
outside.

-Tom
 
?

=?iso-8859-1?B?RWRtb25kIENvdOk=?=

Atom is a new high-level hardware description language embedded in
the functional language Haskell. Atom compiles circuit descriptions
in conditional term rewriting systems down to Verilog and VHDL
for IC simulation, verification, and synthesis.

I'll take a look...

Sounds a lot like Bluespec, what can you say about the differences
between the two?

Edmond
 
J

Jan Decaluwe

Tom said:
I don't have experience with MyHDL, so my statements may need to be
qualified. From what
I gather, MyHDL very closely approximates the semantics of Verilog
(@always(clock.posedge)).

VHDL semantics actually, where it really matters (i.e. a clear
separation between Signal objects and plain variables.)
Therefore I suspect, in terms of synthesis, MyHDL is still at RTL.

Where MyHDL shines, is it's ability to simulate within it's host
language, Python.
If locked in a room with SystemVerilog and Python, I'd take Python any
day. If offered
OCaml or Haskell, I'll always reach for higher-order functional
languages.

I believe that the usage of the term "RTL" creates a lot of confusion,
as I hope to clarify below.

The way I see it, there are two schools of thought in HDLs, depending
on the way they treat events and (hardware) registers:

* Type 1: explicit registers & implicit events
HDLs based on functional languages seem the be all of this type.

* Type 2: explicit events & implicit registers
This is the model of HDLs such as VHDL and Verilog (and MyHDL).
VHDL signals and variables, and Verilog regs, are all objects
that may become registers, or not, in hardware, depending on
how they are used in the code. Thus, registers are implicit.

Regarding the term RTL - Register Transfer Language - it seems clear
that it's appropriate terminology for type 1 languages. But how
could it be meaningful for type 2 languages - languages
without "register objects"?

It might even be argued that type 2 languages concentrate more
on hardware behavior instead of implementation, and therefore
should be considered "higher level".

More interestingly, there seems to be correlation between the
language type and the kind of semantics provided. Clearly,
all HDLs need concurrent statements - such as VHDL processes
and Verilog always blocks. However, type 1 languages seem
to stop there, while type 2 languages provide sequential
statements also (inside processes and always blocks).

So in my view, type 2 semantics is a superset of type 1.
Type 2 is more successful simply because it is more
powerful.

Jan
 
M

Mike Treseler

Jan said:
It might even be argued that type 2 languages concentrate more
on hardware behavior instead of implementation, and therefore
should be considered "higher level".

I agree. Inside a synchronous block/process of
a Type 2 RTL description, I can be as procedural
as I like. Synthesis will take care of the pesky
details of inferring the LUTs, registers,
and those wires to hook them up.

However, when it comes to wiring up blocks and modules,
my procedural inclinations are thwarted.
I'm ready for Type 3.

-- Mike Treseler
 
E

evilkidder

I believe that the usage of the term "RTL" creates a lot of confusion,
as I hope to clarify below.

The way I see it, there are two schools of thought in HDLs, depending
on the way they treat events and (hardware) registers:

* Type 1: explicit registers & implicit events
HDLs based on functional languages seem the be all of this type.

* Type 2: explicit events & implicit registers
This is the model of HDLs such as VHDL and Verilog (and MyHDL).
VHDL signals and variables, and Verilog regs, are all objects
that may become registers, or not, in hardware, depending on
how they are used in the code. Thus, registers are implicit.

Regarding the term RTL - Register Transfer Language - it seems clear
that it's appropriate terminology for type 1 languages. But how
could it be meaningful for type 2 languages - languages
without "register objects"?


I think it is. For hardware that is actually synthesizable, there are
really only two standard event models which are useful:

always @*
always @(posedge clock[, posedge reset])

Thus we still only really have combinatorial or registered logic. It
strikes me as more confusing than useful that "regs" or "signals" (or
"variables") can be both.

The one grey area is describing latches. In all my FPGA designs I
have never (intentionally) used them. In the one ASIC project I
worked on that did allow them, they had to be instantiated as a
library component which is easily supported by most HDLs.

It might even be argued that type 2 languages concentrate more
on hardware behavior instead of implementation, and therefore
should be considered "higher level".


What in particular do think makes it higher level? At the end of the
day we still only desribe one of two things - combinatorial logic or
registers. The only difference is in type 1 is it defined when the
"object" is created and in type 2 it is inferred from it's
environment. The later seems more clumsy to me.

More interestingly, there seems to be correlation between the
language type and the kind of semantics provided. Clearly,
all HDLs need concurrent statements - such as VHDL processes
and Verilog always blocks. However, type 1 languages seem
to stop there, while type 2 languages provide sequential
statements also (inside processes and always blocks).


I agree that the sequential style of coding is useful, however, it is
available in both HDCaml and HDFS. In fact the model provided there
is, in my opinion, more powerful than VHDL and Verilog (I dont know
about MyHDL) as the constructs can be manipulated programatically by
the host language.

The abstraction provided by atom is a whole different kettle of fish
which significantly changes the way you think about circuit design.
Of all the HDLs mentioned so far it's the only one I consider can
truly be called "higher level".

Please dont for a second consider this any sort of criticism of MyHDL
- it's a very good idea with a great implementation. For my part,
however, I prefer the functional programming approach - I just wish
more people agreed...

Cheers,

Andy.
 
J

Jan Decaluwe

For hardware that is actually synthesizable, there are
really only two standard event models which are useful:

always @*
always @(posedge clock[, posedge reset])

Thus we still only really have combinatorial or registered logic. It
strikes me as more confusing than useful that "regs" or "signals" (or
"variables") can be both.

I have two points to add to the confusion:

* the form "always @(posedge clock[, posedge reset])" is not just for
registered logic, but for combinatorial logic as well. With a few exceptions,
it's probably the only template that you really need.

* it's not just that one variable can be combinatorial and another registered;
to make things worse :) the *same* variable can be *both*!

For a practical example (in MyHDL) on how this can be useful, see:
http://myhdl.jandecaluwe.com/doku.php/cookbook:jc2

How to solve the confusion? Replace the "Think hardware" paradigm with
"Understand your compiler" (the compiler being the synthesis tool).
Similar to what good software engineers do, you have to understand what
type of coding styles are handled efficiently by the compiler, even if
at first you don't exactly understand how.

Once you do that the confusion disappears and a whole new world of
elegant coding solutions becomes available. And you even start to
understand how the compiler works - it's not *that* hard after all :)

Jan
 
T

Tom

I'll take a look...

Sounds a lot like Bluespec, what can you say about the differences
between the two?

Edmond

The ideas are the same, but Atom lags behind Bluespec on nearly every
front. Atom has:

- no support for multiple clock domains
- no assertions
- no input language support for SystemVerilog or SystemC
- incomprehensible HDL code generation
- minimal circuit optimization
- limited design capacity

If you are looking for a behavioral synthesis tool for professional
grade ASIC design, Bluespec is the best choice on the market. But if
you're a hobbyist without a CAD budget, Atom provides a glimpse of the
future of IC design.

-Tom

PS: This is just speculation, but Atom's rule scheduling may be
significantly different Bluespec -- I see no mention of it in the MIT
research papers. For those interested, Atom assigns a global, linear
priority to rules. To maximize rule concurrency, Atom prioritizes the
rules to minimize the number of lower priority rules that write data
read by higher priority rules. When a higher
priority rule writes data read by a lower priority rule, but not vice
versa, this forms a "sequentially composable" relationship, and
thus the two rules can execute in the same clock cycle. In this
framework, rule scheduling becomes equivalent to the Feedback Arc Set
problem (http://en.wikipedia.org/wiki/Feedback_arc_set), where an arc
is a data dependency between two rules.

Unfortunately, many of the arcs in a rule-data dependency graph are
irrelevant, since some rules can not be enabled at the same time. For
example, take an FSM, where the FSM is modeled with one rule for every
state:

stoplightController :: System ()
stoplightController = do

state <- reg "state" 2 0
let red = constant 2 0
yellow = constant 2 1
green = constant 2 2

rule "onRed" $ do
when (value state ==. red)
...
state <== green

rule "onGreen" $ do
when (value state ==. green)
...
state <== yellow

rule "onYellow" $ do
when (value state ==. yellow)
...
state <== red

For the stoplightController, the onRed, onGreen, and onYellow rules
will never be enabled at the same time. Therefore, any arcs between
these rules should be removed from the rule-data dependency graph
before optimizing the schedule. To find these mutually exclusive
rules, Atom analyzes the rule logic with it's own algorithms and with
the help of the MiniSat external SAT solver. There's no guarantee it
finds all mutually exclusive rules, but it does a pretty good job.
 
P

Paul Taylor

What in particular do think makes it higher level? At the end of the
day we still only desribe one of two things - combinatorial logic or
registers. The only difference is in type 1 is it defined when the
"object" is created and in type 2 it is inferred from it's
environment. The later seems more clumsy to me.

I would tend to agree. I have been working on a HDL (which is stalled
because some aspects of it don't scale well!) but explicitly declaring
registers is something that I like. From my stuff:

reg myRegister[%8]; # an eight bit register
reg myRegister[%8] = dataIn when load; # loadable register
reg myCounter[%8] = next; # 8-bit binary counter that just counts up
reg myCounter[%8] = { next when up; prev when dn; } # up/dn counter
gray myCounter = next; # gray counter that just counts up
johnson myCounter = { 0 when rst; next when up; } # guess what it does?
onehot myCounter = { async 0 when rst; next when up; } # ditto
shift reg myShReg[%8] = next when shft with myShReg[0] = serialIn; # ditto

Finally an example that creates two counters which are incremented in
different states of a state machine:

# the two counters
reg myCounterA[%4], myCounterB[%8] = { node up; next when up; }

# the state machine
reg myStateMachine[] = {
: myCounterA.up = 1; next;
: myCounterB.up = 1; prev;
}

Regards,

Paul.
 
P

Paul Taylor

On Sun, 06 May 2007 18:57:14 +0100, Paul Taylor wrote:

too hasty in posting....
gray myCounter = next; # gray counter that just counts up
johnson myCounter = { 0 when rst; next when up; } # guess what it does?
onehot myCounter = { async 0 when rst; next when up; } # ditto

should be as:

gray reg myCounter[%4] = next;
johnson reg myCounter[%4] = { 0 when rst; next when up; }
onehot reg myCounter[%4] = { async 0 when rst; next when up; }

gray, johnson, onehot provide context for the next and prev keywords
(amongst other things)

Regards,

Paul.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top