High-level synthesis

On 25/03/2019 10:58, Svenn Are Bjerkem wrote:
On Sunday, March 24, 2019 at 11:01:05 PM UTC+1, Jan Coombs wrote:
On Sun, 24 Mar 2019 08:46:20 -0700 (PDT)
Svenn Are Bjerkem wrote:

On Sunday, March 24, 2019 at 8:31:34 AM UTC+1, Jan Coombs wrote:
On Sat, 23 Mar 2019 19:45:06 -0700 (PDT)
Kevin Neilson wrote:

"Hardware Construction Language": that's a good phrase. I write a lot of Matlab that generates Verilog. I wish I didn't have to, but that's the way it is.

Could you construct and simulate with MyHDL? The verilog
would then be just a simple export. [1]

Jan Coombs

I read on the myhdl discourse that there seems to be a problem with the myhdl owner not maintaining myhdl the way a proper project owner should. Care to comment on that?

Yes, this is a problem. The BDFL found time to consolidate
progress to a 0.10 release. The team look capable, but their
interests will likely diverge/fork if the leadership does not
improve.

What else combines the constructional power of the Python
ecosystem, with simulation speed equal to other free tools
[1], and spits out Verilog or VHDL?

The reason I don't write assembly these days is that gcc does the job for me *and* that there is a certain safety that gcc will not disappear because some leadership wanders off to more interesting projects. This has happened to "fast" tools in the past, and it will happen to "fast" tools in the future. When I decide to put a massive effort into learning something, I would like to know where I am heading. The current situation at myhdl is rocking my trust in it.

It is not that I am not willing to look into new ways of resolving my development and verification tasks. I am looking into both myhdl and cocotb[2] and I use ghdl as my simulator. cocotb managed to get their things together regarding the massive improvement in ghdl[3] on vhdl-2008, myhdl seem to still think iverilog is the only way to cosimulate in the FOSS world.

[2] http://potential.ventures/cocotb/
[3] https://github.com/ghdl/ghdl

Have you considered Spinal <https://github.com/SpinalHDL> ? It is a
high level HDL based on Scala.
 
On Monday, March 25, 2019 at 1:17:02 PM UTC-4, Rob Gaddi wrote:
On 3/23/19 9:21 PM, A.P.Richelieu wrote:
Den 2019-03-23 kl. 05:43, skrev A.P.Richelieu:
Den 2019-03-22 kl. 17:11, skrev Rob Gaddi:
On 3/21/19 9:37 PM, A.P.Richelieu wrote:
Den 2019-03-21 kl. 19:40, skrev Benjamin Couillard:
It's been about 3 years since I've done any *serious* FPGA work. I
used mostly VHDL or sometimes my own Matlab scripts to create
automated VHDL files.

I would like to know if anyone has used High-level synthesis
recetnly for *real* work and if so, would they recommend that
people learn it?




We are working on a system where we connect an FPGA and a CPU.
The FPGA will implement almost 20-30 peripherals.
The CPU will run Linux, and will need a driver for each type
of peripheral.

The Linux driver for each peripheral type will contain a main header
file, and a file describing the user interface (I.E: the peripheral
registers)

A register could look like:

typedef struct uart_mode_s {
     uint32_t    bits:4;
     uint32_t    parity:1;
     uint32_t    odd:1;
     uint32_t    encoding:2;
     uint32_t    baud:24;
} uart_mode_t;

I use the register header file as input to a Python program to
generate the register in VHDL. The Python program will generate a
package
containing the register with a std_logic_vector, and functions which
will convert to and from a "record" so I can use the high level view
of the register in VHDL.

If I change the C header file in the driver, then the VHDL code will
also change, due to dependencies in the build.

Plan to have another Python program which will take a CSV
file and use the contents to instantiate peripherals, and
to generate the interface to the processor, including the address
decoding. (Perhaps a JSON file will be better, though)

This allows me to adopt to changing requirements and save a lot of time
as well as keeping the driver and the peripheral in sync.

I know others that do it the same way.

AP

If you haven't gotten too deep into writing your own code yet, you
may want to check out a project I've been working on sporadically for
a while now.  https://github.com/NJDFan/register-maps

There's also a more standard format for describing registers,
IP-XACT, which like mine is XML-based.  I found it impossibly obtuse
to work with, but note it for the record.


Thank You,
I will have a look.
I was discussing this with the guy that has generated the FPGA
code for my current project, and he suggested an XML based
approach instead of C.
If I was going that route, to start from a description and
generate both C and VHDL, I would probably use a JSON format,
since they are so much easier to read.

In my mind the best way is to start off with the C driver.
If you like us are running Linux & U-Boot, then you
have an API for the driver, which needs to be followed.

The H/W implementation of all the peripherals I have seen basically
suck, and the C driver implementer has to overcome all the deficiencies
forced upon him/her by the chip designers.

The proper approach is to start with the API and then
figure out how to implement this in a driver in the most efficient way..

spi_xfer(peripheral SPI, uint8_t src, size_t size, enum spi_flags flags)
{
    SPI->START = flags;        // Activate CS on request
    strncpy(SPI->FIFO, src, size);
    SPI->STOP  = flags;        // Deactivate CS on request
}

Once I have the driver figured out, I already have the headers,
so I do not want to create XML to regenerate what I already have.

AP

Had a brief look at your stuff at

* https://github.com/NJDFan/register-maps

This is mainly to do address decoding, right?
Do you have any support for the actual fields inside the registers?
That is a primary function I would be looking for.

I can actually see the use of such tool for me,
if my C struct parser generates the XML (or JSON)
for an intermediate representation.

BR
AP

Yep. Registers can have fields of types signed, unsigned, or bits.
That generates VHDL records with named fields of types SIGNED, UNSIGNED,
and STD_LOGIC_VECTOR (or STD_LOGIC for single bit fields) and functions
to translate the records to/from a STD_LOGIC_VECTOR the size of the
read/write bus, as well as procedures to modify a structured register
from a write data bus that has byte enables.

If you use the high-level API (suitable for "I want to implement these
registers on flops", not for "I want to implement a large BRAM for
this.") you wind up with the entire thing in a
t_<component_name>_regfile, which is a record type where each register
(or register array) is a field. So you wind up using things like
regfile.ctl.enable to interface with your logic.

When creating a data structure like this, is there any real reason to use std_logic_vector rather than unsigned? I tend to use either signed or unsigned for all multibit data types rather than std_logic_vector just because it is easier to type and I've never found an issue.

--

Rick C.

- Get a 1,000 miles of free Supercharging
- Tesla referral code - https://ts.la/richard11209
 
On 3/25/19 3:12 PM, gnuarm.deletethisbit@gmail.com wrote:
On Monday, March 25, 2019 at 1:17:02 PM UTC-4, Rob Gaddi wrote:
On 3/23/19 9:21 PM, A.P.Richelieu wrote:
Den 2019-03-23 kl. 05:43, skrev A.P.Richelieu:
Den 2019-03-22 kl. 17:11, skrev Rob Gaddi:
On 3/21/19 9:37 PM, A.P.Richelieu wrote:
Den 2019-03-21 kl. 19:40, skrev Benjamin Couillard:
It's been about 3 years since I've done any *serious* FPGA work. I
used mostly VHDL or sometimes my own Matlab scripts to create
automated VHDL files.

I would like to know if anyone has used High-level synthesis
recetnly for *real* work and if so, would they recommend that
people learn it?




We are working on a system where we connect an FPGA and a CPU.
The FPGA will implement almost 20-30 peripherals.
The CPU will run Linux, and will need a driver for each type
of peripheral.

The Linux driver for each peripheral type will contain a main header
file, and a file describing the user interface (I.E: the peripheral
registers)

A register could look like:

typedef struct uart_mode_s {
     uint32_t    bits:4;
     uint32_t    parity:1;
     uint32_t    odd:1;
     uint32_t    encoding:2;
     uint32_t    baud:24;
} uart_mode_t;

I use the register header file as input to a Python program to
generate the register in VHDL. The Python program will generate a
package
containing the register with a std_logic_vector, and functions which
will convert to and from a "record" so I can use the high level view
of the register in VHDL.

If I change the C header file in the driver, then the VHDL code will
also change, due to dependencies in the build.

Plan to have another Python program which will take a CSV
file and use the contents to instantiate peripherals, and
to generate the interface to the processor, including the address
decoding. (Perhaps a JSON file will be better, though)

This allows me to adopt to changing requirements and save a lot of time
as well as keeping the driver and the peripheral in sync.

I know others that do it the same way.

AP

If you haven't gotten too deep into writing your own code yet, you
may want to check out a project I've been working on sporadically for
a while now.  https://github.com/NJDFan/register-maps

There's also a more standard format for describing registers,
IP-XACT, which like mine is XML-based.  I found it impossibly obtuse
to work with, but note it for the record.


Thank You,
I will have a look.
I was discussing this with the guy that has generated the FPGA
code for my current project, and he suggested an XML based
approach instead of C.
If I was going that route, to start from a description and
generate both C and VHDL, I would probably use a JSON format,
since they are so much easier to read.

In my mind the best way is to start off with the C driver.
If you like us are running Linux & U-Boot, then you
have an API for the driver, which needs to be followed.

The H/W implementation of all the peripherals I have seen basically
suck, and the C driver implementer has to overcome all the deficiencies
forced upon him/her by the chip designers.

The proper approach is to start with the API and then
figure out how to implement this in a driver in the most efficient way.

spi_xfer(peripheral SPI, uint8_t src, size_t size, enum spi_flags flags)
{
    SPI->START = flags;        // Activate CS on request
    strncpy(SPI->FIFO, src, size);
    SPI->STOP  = flags;        // Deactivate CS on request
}

Once I have the driver figured out, I already have the headers,
so I do not want to create XML to regenerate what I already have.

AP

Had a brief look at your stuff at

* https://github.com/NJDFan/register-maps

This is mainly to do address decoding, right?
Do you have any support for the actual fields inside the registers?
That is a primary function I would be looking for.

I can actually see the use of such tool for me,
if my C struct parser generates the XML (or JSON)
for an intermediate representation.

BR
AP

Yep. Registers can have fields of types signed, unsigned, or bits.
That generates VHDL records with named fields of types SIGNED, UNSIGNED,
and STD_LOGIC_VECTOR (or STD_LOGIC for single bit fields) and functions
to translate the records to/from a STD_LOGIC_VECTOR the size of the
read/write bus, as well as procedures to modify a structured register
from a write data bus that has byte enables.

If you use the high-level API (suitable for "I want to implement these
registers on flops", not for "I want to implement a large BRAM for
this.") you wind up with the entire thing in a
t_<component_name>_regfile, which is a record type where each register
(or register array) is a field. So you wind up using things like
regfile.ctl.enable to interface with your logic.

When creating a data structure like this, is there any real reason to use std_logic_vector rather than unsigned? I tend to use either signed or unsigned for all multibit data types rather than std_logic_vector just because it is easier to type and I've never found an issue.

Just the sake of strong typing. To my mind, a STD_LOGIC_VECTOR is a
thing that does not have a numerical interpretation, and as such can't
have arithmetic applied to it. An UNSIGNED has one and only one
numerical interpretation, and as such can't consist of multiple
bitfields doing different things. It's easier to verify the code if you
do it that way, but nothing really essential.

--
Rob Gaddi, Highland Technology -- www.highlandtechnology.com
Email address domain is currently out of order. See above to fix.
 
On Monday, March 25, 2019 at 6:22:25 PM UTC-4, Rob Gaddi wrote:
On 3/25/19 3:12 PM, gnuarm.deletethisbit@gmail.com wrote:
On Monday, March 25, 2019 at 1:17:02 PM UTC-4, Rob Gaddi wrote:
On 3/23/19 9:21 PM, A.P.Richelieu wrote:
Den 2019-03-23 kl. 05:43, skrev A.P.Richelieu:
Den 2019-03-22 kl. 17:11, skrev Rob Gaddi:
On 3/21/19 9:37 PM, A.P.Richelieu wrote:
Den 2019-03-21 kl. 19:40, skrev Benjamin Couillard:
It's been about 3 years since I've done any *serious* FPGA work. I
used mostly VHDL or sometimes my own Matlab scripts to create
automated VHDL files.

I would like to know if anyone has used High-level synthesis
recetnly for *real* work and if so, would they recommend that
people learn it?




We are working on a system where we connect an FPGA and a CPU.
The FPGA will implement almost 20-30 peripherals.
The CPU will run Linux, and will need a driver for each type
of peripheral.

The Linux driver for each peripheral type will contain a main header
file, and a file describing the user interface (I.E: the peripheral
registers)

A register could look like:

typedef struct uart_mode_s {
     uint32_t    bits:4;
     uint32_t    parity:1;
     uint32_t    odd:1;
     uint32_t    encoding:2;
     uint32_t    baud:24;
} uart_mode_t;

I use the register header file as input to a Python program to
generate the register in VHDL. The Python program will generate a
package
containing the register with a std_logic_vector, and functions which
will convert to and from a "record" so I can use the high level view
of the register in VHDL.

If I change the C header file in the driver, then the VHDL code will
also change, due to dependencies in the build.

Plan to have another Python program which will take a CSV
file and use the contents to instantiate peripherals, and
to generate the interface to the processor, including the address
decoding. (Perhaps a JSON file will be better, though)

This allows me to adopt to changing requirements and save a lot of time
as well as keeping the driver and the peripheral in sync.

I know others that do it the same way.

AP

If you haven't gotten too deep into writing your own code yet, you
may want to check out a project I've been working on sporadically for
a while now.  https://github.com/NJDFan/register-maps

There's also a more standard format for describing registers,
IP-XACT, which like mine is XML-based.  I found it impossibly obtuse
to work with, but note it for the record.


Thank You,
I will have a look.
I was discussing this with the guy that has generated the FPGA
code for my current project, and he suggested an XML based
approach instead of C.
If I was going that route, to start from a description and
generate both C and VHDL, I would probably use a JSON format,
since they are so much easier to read.

In my mind the best way is to start off with the C driver.
If you like us are running Linux & U-Boot, then you
have an API for the driver, which needs to be followed.

The H/W implementation of all the peripherals I have seen basically
suck, and the C driver implementer has to overcome all the deficiencies
forced upon him/her by the chip designers.

The proper approach is to start with the API and then
figure out how to implement this in a driver in the most efficient way.

spi_xfer(peripheral SPI, uint8_t src, size_t size, enum spi_flags flags)
{
    SPI->START = flags;        // Activate CS on request
    strncpy(SPI->FIFO, src, size);
    SPI->STOP  = flags;        // Deactivate CS on request
}

Once I have the driver figured out, I already have the headers,
so I do not want to create XML to regenerate what I already have.

AP

Had a brief look at your stuff at

* https://github.com/NJDFan/register-maps

This is mainly to do address decoding, right?
Do you have any support for the actual fields inside the registers?
That is a primary function I would be looking for.

I can actually see the use of such tool for me,
if my C struct parser generates the XML (or JSON)
for an intermediate representation.

BR
AP

Yep. Registers can have fields of types signed, unsigned, or bits.
That generates VHDL records with named fields of types SIGNED, UNSIGNED,
and STD_LOGIC_VECTOR (or STD_LOGIC for single bit fields) and functions
to translate the records to/from a STD_LOGIC_VECTOR the size of the
read/write bus, as well as procedures to modify a structured register
from a write data bus that has byte enables.

If you use the high-level API (suitable for "I want to implement these
registers on flops", not for "I want to implement a large BRAM for
this.") you wind up with the entire thing in a
t_<component_name>_regfile, which is a record type where each register
(or register array) is a field. So you wind up using things like
regfile.ctl.enable to interface with your logic.

When creating a data structure like this, is there any real reason to use std_logic_vector rather than unsigned? I tend to use either signed or unsigned for all multibit data types rather than std_logic_vector just because it is easier to type and I've never found an issue.


Just the sake of strong typing. To my mind, a STD_LOGIC_VECTOR is a
thing that does not have a numerical interpretation, and as such can't
have arithmetic applied to it. An UNSIGNED has one and only one
numerical interpretation, and as such can't consist of multiple
bitfields doing different things. It's easier to verify the code if you
do it that way, but nothing really essential.

There is no such restriction on signed or unsigned. How does verifying the code change?

Rick C.
 
Benjamin Couillard <benjamin.couillard@gmail.com> writes:

I did the same in VHDL about 10 years ago. It worked well for a
medium-sized system. It was based on a code snippet posted by Jonathan
Bromley on comp.lang.vhdl

Interesting. Do you still happen to have that VHDL snippet?

Personally, my projects have usually had so few registers I haven't
bothered with any generator. At least in my opinion if you have, say,
less than 20 registers, then who cares.

However, now I have a project which has quite a lot of registers. I
searched and found a Python script called hdlregs on Github. It's
actually by the guy (Guy Eschemann) who does AirHDL now which is a
payola web service to generate register files with an AXI4 slave
interface.

Hdlregs takes json as input and generates docs in HTML, VHDL code and C
headers. Bus interface is simple address/data/control, user interface to
regs is a single record in and another one out. The script seems to have
some limitations so hardly perfect but good enough for my needs. Then
again, it's in Python so easy to improve. Documentation is zero apart
from one example.
 
Le mercredi 27 mars 2019 04:03:00 UTC-4, Anssi Saari a Êcrit :
Benjamin Couillard <benjamin.couillard@gmail.com> writes:

I did the same in VHDL about 10 years ago. It worked well for a
medium-sized system. It was based on a code snippet posted by Jonathan
Bromley on comp.lang.vhdl

Interesting. Do you still happen to have that VHDL snippet?

https://groups.google.com/d/msg/comp.lang.vhdl/0JrSaPFUJ1k/JzDlR9MZVMUJ

Make sure to read the whole thread as there is a small typo in the posted code. The typo is corrected in a later post.
 
Feel free to use RegisterWizard from Bitvis. This is freeware - so no cost.. https://bitvis.no/dev-tools/register-wizard/

The input is in JSON, and is easy to use by anyone.
It is well documented - including examples.
The generated bus interface is what we call Simple Bus Interface (SBI), which is what people some year ago would have called a simple SRAM interface.
If you need a more advanced interface you can just make a general wrapper.

If you download the open source UVVM (Universal VHDL Verification Methodology) from Github (https://github.com/UVVM/UVVM) you will get a BFM (Bus functional model) and VVC (verification component) with procedures to access the SBI interface (or Avalon or AXI4-lite) in a testbench.

- Espen
 
Espen Tallaksen <espen.tallaksen@bitvis.no> writes:

Feel free to use RegisterWizard from Bitvis. This is freeware - so no
cost. https://bitvis.no/dev-tools/register-wizard/

We rejected that mostly due to the closed source nature of it but it did
seem good. The other option was free and so far has been good enough.
 
Benjamin Couillard <benjamin.couillard@gmail.com> writes:

Le mercredi 27 mars 2019 04:03:00 UTC-4, Anssi Saari a écrit :
Benjamin Couillard <benjamin.couillard@gmail.com> writes:

I did the same in VHDL about 10 years ago. It worked well for a
medium-sized system. It was based on a code snippet posted by Jonathan
Bromley on comp.lang.vhdl

Interesting. Do you still happen to have that VHDL snippet?


https://groups.google.com/d/msg/comp.lang.vhdl/0JrSaPFUJ1k/JzDlR9MZVMUJ

Make sure to read the whole thread as there is a small typo in the
posted code. The typo is corrected in a later post.

Thanks. Well, it looks like it will take some work to get from the
snippets to a working implementation but I'll see what I can do with it.
 

Welcome to EDABoard.com

Sponsor

Back
Top