profile
viewpoint
Rodrigo A. Melo rodrigomelo9 Instituto Nacional de Tecnología Industrial Bs As, Argentina www.linkedin.com/in/rodrigoalejandromelo Digital Electronic Engineer. Interested in projects that involve FPGA devices and/or GNU/Linux.

rodrigomelo9/verifying-foss-hdl-synthesizers 10

a project to check the FOSS synthesizers against vendors EDA tools

INTI-CMNB-FPGA/fpga_lib 6

Library of utilities such as cores, procedures and functions, commonly shared between FPGA projects.

INTI-CMNB-FPGA/fpga_helpers 5

A set of Tcl and Python scripts which helps to use FPGA development tools from command line in a vendor independent way

INTI-CMNB-FPGA/fpga_examples 4

This project is about FPGA hard blocks and board features. Examples ready to use and verified in hardware.

rodrigomelo9/vhdl2verilog 3

VHDL93 to Verilog2001 translator

INTI-CMNB-FPGA/CIAA_ACC_Support 2

Documentation, demos and basic support for this board, developed by INTI - CMNB as part of the CIAA project

INTI-CMNB-FPGA/FPGAsInArg 2

Relevamiento de grupos que trabajan con FPGAs en Argentina.

INTI-CMNB-FPGA/ICsPLDsOnArg 2

Relevamiento de grupos de desarrollo de Circuitos Integrados y Lógica Programable en Argentina

INTI-CMNB-FPGA/guidelines 1

GuideLines for HDL projects

fork whitequark/setuptools_scm

the blessed package to manage your versions by scm tags

fork in 2 hours

fork whitequark/ViewSB

open-source USB analyzer toolkit with support for a variety of capture hardware

fork in 2 hours

issue commentghdl/ghdl

Exception TYPES.INTERNAL_ERROR raised (VHDL 2008)

One way to find analysis bugs is to divide and conquer by manipulating the source file.

Here commenting out all the concurrent statements then re-exposing them in a sliding fashion from the top until all the bugs have shown up or all the concurrent statements analyze.

On line 668 of xpm_fifo_base.vhd:

    wea            => (others => ram_wr_en_i),

we'd find a dependence on an implicit signal for an actual expression that isn't currently supported by ghdl:

IEEE std 1076-2008 6.5.6.3 Port clauses:

If the actual part of a given association element for a formal port of a block is the reserved word inertial followed by an expression, or is an expression that is not globally static, then the given association element is equivalent to association of the port with an anonymous signal implicitly declared in the declarative region that immediately encloses the block. The signal has the same subtype as the formal port and is the target of an implicit concurrent signal assignment statement of the form

anonymous <= E;

where E is the expression in the actual part of the given association element. The concurrent signal assignment statement occurs in the same statement part as the block.

A work around would entail declaring a signal with a compatible subtype to the port actual in the immediately preceding block declarative region whose scope encloses the instantiation, assigning the expression to it in a concurrent assignment statement and using that signal as the actual. For troubleshooting purposes any valid and supported construct is fine. An actual of `(others => '0') will do for identifying more bugs without changing line numbering.

The next bug is another implicit signal on line 818:

port map(wrst_busy, wr_clk, (rd_pntr_ext-extra_words_fwft), rd_pntr_wr_dc);

(I stopped and searched the port maps and simply missed this one.)

These are the only two constructs causing INTERNAL_ERROR in xpm_fifo_base.vhd which analyzes successfully otherwise.

The immediate ghdl corrective action would be to add a message saying the creation of implicit signals for actual expressions isn't yet supported instead of reporting an INTERNAL_ERROR.

This is the first synthesis vendor's library code I recall seeing with this -2008 feature. It may alter the implementation priority from Tristan's perspective. It's been supported by at least two simulator vendors for several years and several third party library vendors have attempted to use it in the past.

fransschreuder

comment created time in 6 hours

issue commentghdl/ghdl

Exception TYPES.INTERNAL_ERROR raised (VHDL 2008)

@fransschreuder, there are some hints for debugging in https://ghdl.github.io/ghdl/development/Debugging.html

fransschreuder

comment created time in 10 hours

issue commentghdl/ghdl

Exception TYPES.INTERNAL_ERROR raised (VHDL 2008)

Thanks for looking into this. Is there any way I can help debugging this? I do write c/cpp and am usually good at firmware and software, but the hex numbers in the debug output don't mean anything to me yet.

fransschreuder

comment created time in 10 hours

issue commentghdl/ghdl

Exception TYPES.INTERNAL_ERROR raised (VHDL 2008)

I can reproduce the crash.

fransschreuder

comment created time in 11 hours

issue openedghdl/ghdl

Exception TYPES.INTERNAL_ERROR raised (VHDL 2008)

Description I have ported the Xilinx XPM libary to VHDL in order to use it with GHDL. It works in Questasim, at least up to the point where I have tested it. In GHDL TYPES.INTERNAL_ERROR is raised. I don't know how to pinpoint the GHDL issue in this particular code.

Expected behaviour The simulation should finish with the following output (questasim)

** Note: Test Completed Successfully

Time: 93860 ns Iteration: 4 Instance: /xpm_fifo_tb

How to reproduce?

git clone https://gitlab.nikhef.nl/franss/xpm_vhdl.git
cd xpm_vhdl/script
compile_ghdl.sh

Context

  • OS: Ubuntu 20.04
  • Origin:
    • [1.0-dev (v0.37.0-1070-ge18e9569)] Package manager: version
    • [ https://github.com/ghdl/ghdl.git] Released binaries: tarball_url
    • [ e18e9569] Built from sources: commit SHA

If a GHDL Bug occurred block is shown in the log, please paste it here:

******************** GHDL Bug occurred ***************************
Please report this bug on https://github.com/ghdl/ghdl/issues
GHDL release: 1.0-dev (v0.37.0-1070-ge18e9569) [Dunoon edition]
Compiled with GNAT Version: 10.2.0
Target: x86_64-linux-gnu
/home/frans/XPM_VHDL/script/
Command line:
ghdl -r --std=08 xpm_fifo_tb
Exception TYPES.INTERNAL_ERROR raised
Exception information:
raised TYPES.INTERNAL_ERROR : trans.adb:555
Call stack traceback locations:
0x555e32a1e1f1 0x555e32a1e5cf 0x555e32a1e84b 0x555e32baec36 0x555e32bbf802 0x555e32c1b8e0 0x555e32bf2fd8 0x555e32bf32b7 0x555e32bf30c4 0x555e32c3b320 0x555e32c3b447 0x555e32c3baa0 0x555e32c3c232 0x555e32c3de3e 0x555e32c3df93 0x555e32c413b7 0x555e32c45ca0 0x555e32c45ae3 0x555e32c45dda 0x555e32c09da2 0x555e32bfd754 0x555e32c0e634 0x555e32c08948 0x555e32c4e3fd 0x555e32b8db42 0x555e32ac7a4d 0x555e32c51d6f 0x555e32883af1 0x7f27944200b1 0x555e3288224c 0xfffffffffffffffe
******************************************************************

Additional context Add any other context about the problem here. If applicable, add screenshots to help explain your problem.

created time in 21 hours

issue commentghdl/ghdl

Generate a schematic starting from dump produced by GHDL (XML or others)

Ctags is a programming tool that generates an index (or tag) file of names found in source and header files of various programming languages to aid code comprehension. Depending on the language, functions, variables, class members, macros and so on may be indexed. These tags allow definitions to be quickly and easily located by a text editor, a code search engine, or other utility. Alternatively, there is also an output mode that generates a cross-reference file, listing information about various names found in a set of language files in human-readable form.

Thus, it mainly used to index a source code, but theoretically, it could perform a complete language parsing. At the current form, it is still very useful to index elements such as:

  • Entities
  • Ports
  • Generics
  • Constants
  • Types
  • Signals
  • Variables
  • Components
  • Labels
  • Packages
  • Processes
  • Architecture

almost every VHDL element.

It provides a list of tags where those keywords are defined, one for each row, with the corresponding line number of the source file where they are defined. But the most useful aspect is the scope. For example, given two identically named ports of two distinct entities, thanks to the scope I could differentiate those port when parsing the code, correctly associating them to the proper entity.

CTAGS is used in many editors: Eclipse, Visual Studio Code, Vim...

For more info:

http://docs.ctags.io/en/latest/

I was thinking about helping out CTAGS developers with adding some features so that processes and especially component instances could be parsed, useful for example to build a tool which could generate a tree of the component dependencies. Starting from that, a compile script could be generated, with the source files properly sorted. The resulting tree could be also used as a starting point to produce a diagram showing the relationship between those components.

pidgeon777

comment created time in a day

issue openedghdl/ghdl

synth: missing some VHDL-2008 SLV functions

Description The scalar-vector logical operators as well as the SLV shift operators added in VHDL-2008 are not supported in synthesis yet.

Expected behaviour The functions are synthesized correctly.

How to reproduce?

library ieee;
use ieee.std_logic_1164.all;

entity test is
	port (
		slv : in std_logic_vector(7 downto 0);
		sl  : in std_logic;
		int : in integer;

		vec_scal_and  : out std_logic_vector(7 downto 0);
		vec_scal_nand : out std_logic_vector(7 downto 0);
		vec_scal_or   : out std_logic_vector(7 downto 0);
		vec_scal_nor  : out std_logic_vector(7 downto 0);
		vec_scal_xor  : out std_logic_vector(7 downto 0);
		vec_scal_xnor : out std_logic_vector(7 downto 0);

		scal_vec_and  : out std_logic_vector(7 downto 0);
		scal_vec_nand : out std_logic_vector(7 downto 0);
		scal_vec_or   : out std_logic_vector(7 downto 0);
		scal_vec_nor  : out std_logic_vector(7 downto 0);
		scal_vec_xor  : out std_logic_vector(7 downto 0);
		scal_vec_xnor : out std_logic_vector(7 downto 0);

		slv_sll : out std_logic_vector(7 downto 0);
		slv_srl : out std_logic_vector(7 downto 0)
	);
end entity;

architecture arch of test is
begin
	vec_scal_and  <= slv and sl;
	vec_scal_nand <= slv nand sl;
	vec_scal_or   <= slv or sl;
	vec_scal_nor  <= slv nor sl;
	vec_scal_xor  <= slv xor sl;
	vec_scal_xnor <= slv xnor sl;

	scal_vec_and  <= sl and slv;
	scal_vec_nand <= sl nand slv;
	scal_vec_or   <= sl or slv;
	scal_vec_nor  <= sl nor slv;
	scal_vec_xor  <= sl xor slv;
	scal_vec_xnor <= sl xnor slv;

	slv_sll <= slv sll int;
	slv_srl <= slv srl int;
end architecture;
ghdl --synth --std=08 ops.vhd -e
ghdl:note: top entity is "test"
ent.vhd:31:29:error: unhandled predefined IEEE operator "and"
../../src/ieee2008/std_logic_1164.vhdl:125:12:error:  declared here

Context Please, provide the following information:

  • OS: Arch Linux
  • Origin:
    • Built from sources: 31ca0d8a

If a GHDL Bug occurred block is shown in the log, please paste it here:

******************** GHDL Bug occurred ***************************
Please report this bug on https://github.com/ghdl/ghdl/issues
GHDL release: 1.0-dev (v0.37.0-1074-g31ca0d8a) [Dunoon edition]
Compiled with GNAT Version: 10.2.0
Target: x86_64-pc-linux-gnu
/home/xiretza/temp/ghdl_synth_tests/
Command line:
ghdl --synth --std=08 ent.vhd -e
Exception CONSTRAINT_ERROR raised
Exception information:
raised CONSTRAINT_ERROR : synth-expr.adb:376 discriminant check failed
Call stack traceback locations:
0x558da6 0x546815 0x556188 0x548bb1 0x54a32c 0x54a145 0x54c6e5 0x54c9c8 0x546288 0x54889e 0x54d42f 0x54e0e8 0x5656e7 0x560cde 0x58ed32 0x4f58c6 0x407239 0x7fd1477df150 0x4072ac 0xfffffffffffffffe
******************************************************************

created time in a day

issue commentghdl/ghdl

Generate a schematic starting from dump produced by GHDL (XML or others)

Is ctags a real parser/parser generator or is it just source code indexer?

pidgeon777

comment created time in 2 days

issue commentghdl/ghdl

Learning VHDL with GHDL

@eine Thank you a lot. And I, as the author, have to say @targeted is right: The whole book content is under the CC-BY-ND license. The code examples I wrote (published at https://github.com/datacipy/VHDL) are under the MIT license. Some libraries or entities are from other authors - like T80 - and they're licensed under their own licenses (mostly MIT / BSD / GPL / LGPL).

Let me say it is my third book (an "electronics trilogy"). The first one was about the gates, transistors, volts, sensors, etc. The second one was about the "computer building" (illustrated on the 8bit single board computers, based on CPUs 8085, 6502, and 6809) and "programming in assembler". And the whole trilogy is under the CC-BY-ND, all constructions and software are under MIT or CERN OHL...

Thank you, guys, for awesome work with the GHDL! It is a great tool, which allows me not to focus only on the Quartus IDE and embedded Multisim, but on the VHDL code and its testing itself.

eine

comment created time in 2 days

issue commentghdl/ghdl

Generate a schematic starting from dump produced by GHDL (XML or others)

This is not strictly related to GHDL, but it could be of interest for many of you. I'm currently helping @masatake with completing the CTAGS-based VHDL parser. Something which could facilitate the schematic project I previously discussed with you:

https://github.com/universal-ctags/ctags/issues/2678

Anyway, those with a good knowledge of VHDL have now a great opportunity to participate in this discussion and help us with improving this CTAGS VHDL parser (I'm not a Universal Ctags developer, just someone using it extensively).

Some of the discussion points which are near to bo solved:

  • How to classify ports/generics.
  • How to identify instanced components inside an architecture.
  • How to define the scope of each instanced element? Ports, generics, components, packages, etc.

All of this could be very useful for quickly parsing multiple architectures, for example, for fast code navigation, or to build hierarchical component trees, and so on.

Those willing to share some opinions or do some tests are more than welcome.

pidgeon777

comment created time in 2 days

issue commentghdl/ghdl

Learning VHDL with GHDL

@targeted, thanks so much for explaining. I updated the added the links to PDF, EPUB and MOBI above. I'm glad I misunderstood the openness of the book 😅

@maly, congratulations on that very nice work!

eine

comment created time in 2 days

issue commentghdl/ghdl

Learning VHDL with GHDL

@eine

I don't know a word of czech, so I mostly guessed that the book itself is not open/public (but it is rather cheap, ~15€), however, there are dozens of references for learning VHDL and a bunch of open source IP cores. I'd be glad if anyone could confirm.

From the pure similarity between Czech and Russian, this here https://datacipy.cz/ "E-book je dostupný pod volnou licencí CC jako PDF • EPUB • MOBI" says that the e-book is available for download under free CC license.

Also in the book itself: "Toto autorské dílo podléhá licenci Creative Commons BY-ND 3.0 CZ"

And from https://github.com/datacipy/VHDL "Vše pod otevřenými licencemi MIT, pokud není uvedeno jinak (např. CC nebo GPL). " Says that all the utilities that accompany the book are available under open MIT licenses, unless otherwise noted.

eine

comment created time in 2 days

startedOpen-Smartwatch/open-smartwatch.github.io

started time in 2 days

starteddavidthings/hdelk

started time in 2 days

starteddavidthings/hdelk

started time in 2 days

startedhdl/containers

started time in 2 days

issue commentghdl/ghdl

Generate a schematic starting from dump produced by GHDL (XML or others)

when I expand those "processes", I can see their equivalent RTL representation?

yes, it should expand on-click . It creates a complex problem however. As parts of an expressions can be shared with multiple processes we need to take an extra care while moving gates in to "process box".

pidgeon777

comment created time in 2 days

issue commentghdl/ghdl

Generate a schematic starting from dump produced by GHDL (XML or others)

@Nic30

I am using grouping of the "gates by process" in hwtGraph and the examples in d3-hwschematic are generated from it. I do have positive feedback from colleagues and it seems to me as a must have. However nearly no other person is using that library. example

That seems to be a great project, congratulations. I wanted to do something very similar to your schematic, but for VHDL. I see that you're representing a language somehow different from VHDL.

Considering your example, when I expand those "processes", I can see their equivalent RTL representation? Correct? If yes, that is very cool.

Well, in the schematic that I had in mind I would be happy enough to expand the "process box" and simply see the code of the actual process, for example. Still, this "process box" should have as inputs all of the signals read by the process and the written signals as outputs. Exactly as you already did, except for that great RTL preview.

But, one day using the power of GHDL synthesis, maybe it could be possible to expand this box and actually show the GHDL synthesized RTL schematic, as you already did with your custom library.

It seems that your diagramming library could be a good candidate to display the resulting GHDL schematic, though. I like the fact that those rectangles can be expanded, maybe in a hierarchical way.

Anyway, I use Vivado and I love its RTL schematic viewer. Dynamically showing and hiding signal paths, and expanding subcomponents and so on. It would be good to obtain something similar for basic VHDL sources, without following all of the operations needed by Vivado, which is not a very light tool. Something fast to quickly display the HDL code would be nice to have, in my opinion.

pidgeon777

comment created time in 3 days

issue commentghdl/ghdl

Generate a schematic starting from dump produced by GHDL (XML or others)

@tgingold

Starting from the synthesized netlist would be much easier, but you won't be able to display process or concurrent assignments.

I didn't follow the latest GHDL developments, so now it is possible to obtain a complete synthesized netlist of the input source? If yes, then would it be currently possible to generate a schematic from that? With Yosis something like that was already possible.

It would be an interesting thing to do. But first, I would like to try a higher-level approach, for making the code easily readable during its development. Thus, visual high-level representation of instanced components, process, ports etc. to find the possible source of bugs I described above, or for quickly understand the involved subcomponents and their connections.

If you start from analyzed entity/architecture, you have to decide what to do with generate statements, and vector signals whose length is not known. So I suppose you'd like to start from an elaborated architecture. But then you have to decide how to give the value of the generics.

You're right. For the vector signals I could start with declaring them as buses of unknown size on that case. For the generate statements, it would obviously be harder.

The generate statements produce their effects on source compilation/elaboration (thinking for example about generics), so we could still instantiate all of the code included in the generate statement for example by putting them inside a rectangle with dashed edges as if to say, all of this could be instantiated or not after compilation. But at least someone would know those might actually be there.

Unfortunately, there is currently no easy way with GHDL to get a full access to an elaborated design. The API for that (VHPI) is not fully enough implemented.

Well, that would be useful. Let's hope, one day.

So maybe you should start from analyzed designs and deal with generate laters.

That was the idea, for now. Instantiate everything in the code eventually detecting those generates and placing the parsed elements accordingly (boxes with dashed edges etc.).

Using the xml file is not recommended. It's huge and not stable. I would start with libghdl (a thin python interface to the internal of ghdl).

Thanks for the tip, I'll look for the documentation of that interface.

I would like to report this HDL specific schematic diagram tool, which also seems to be very good for the kind of schematic I had in mind:

https://davidthings.github.io/hdelk/

https://github.com/davidthings/hdelk

Some examples:

https://davidthings.github.io/spokefpga/pipelines

https://davidthings.github.io/spokefpga/i2c

pidgeon777

comment created time in 3 days

issue commentghdl/ghdl

Generate a schematic starting from dump produced by GHDL (XML or others)

I am using grouping of the "gates by process" in hwtGraph and the examples in d3-hwschematic are generated from it. I do have positive feedback from colleagues and it seems to me as a must have. However nearly no other person is using that library.

example

I have never found a clear answer about what should be elaborated for a visualization and what should have a custom element. I remember a discussion with @drom and @xkotek07 . Drom suggested to start with the specification of shapes and behaviour of the gui.

pidgeon777

comment created time in 3 days

issue commentghdl/ghdl

Generate a schematic starting from dump produced by GHDL (XML or others)

That's indeed a very interesting and useful tool.

Starting from the synthesized netlist would be much easier, but you won't be able to display process or concurrent assignments.

If you start from analyzed entity/architecture, you have to decide what to do with generate statements, and vector signals whose length is not known.

So I suppose you'd like to start from an elaborated architecture. But then you have to decide how to give the value of the generics.

Unfortunately, there is currently no easy way with GHDL to get a full access to an elaborated design. The API for that (VHPI) is not fully enough implemented.

So maybe you should start from analyzed designs and deal with generate laters.

Using the xml file is not recommended. It's huge and not stable. I would start with libghdl (a thin python interface to the internal of ghdl).

pidgeon777

comment created time in 3 days

issue commentghdl/ghdl

Generate a schematic starting from dump produced by GHDL (XML or others)

The generated schematic could be something like this:

image

  • Main entity ports are placed externally as physical pins.
  • Sub-components are displayed as boxes with their input/output ports.
  • Processes are represented as boxes. Inside a process, a signal could be read or written. Thus, inputs of these processes will be associated with the signals read, outputs will be associated with the signals written inside the process.
  • Each concurrent assignment (assignments outside a process) will be represented as a box. Each of these will generally involve a signal written, and one or more signals read.

Thus, for example, if Process 1 write a signal that will be read by COMP2, a wire will connect one of the Process 1 outputs (the one associated to the signal) to COMP2 input (the port which has been mapped to that input signal).

As a result, the resulting schematic would greatly improve the readability of code in terms of:

  • Entity ports
  • Instantiated components
  • Declared processes
  • Concurrent statements

also helping to visually debug some problems, such as:

  • Inputs driven by more than one signal.
  • Outputs not connected.
  • Wrong signal connections (clocks, etc.).
  • Signals written by Process X at a certain clock frequency, read in Process Y working at a different clock frequency (possible metastability, draw a red line from Process X associated signal output to Process Y input).

and so on.

pidgeon777

comment created time in 3 days

issue commentghdl/ghdl

Use GHDL as a VHDL parser

Will the XML feature remain anyway? I have quite some dependencies on it.. See also https://hackfin.gitlab.io/xhdl/, this is one example on how to convert the GHDL XML output to SVG, etc.

@hackfin I tried your webpage but I don't know how to generate a schematic starting from the XML output file. Also something seems to be broken in your webpage because no schematic is shown.

I read that File API & FileReader available. Is there a way to obtain them?

Also, you might be interested in this discussion:

https://github.com/ghdl/ghdl/issues/1519

jagjordi

comment created time in 3 days

issue openedghdl/ghdl

Generate a schematic starting from dump produced by GHDL (XML or others)

Hi everyone, I would like to write a small tool which, given a VHDL file describing an entity plus its architecture, would allow me to draw its corresponding schematic. It should at least include:

  1. Entity input/output ports as pins.
  2. Boxes representing the instanced sub-components.
  3. Boxes representing the internal processes.
  4. Boxes representing the concurrent assignments (thus outside processes).
  5. Signal paths between 1, 2, 3 and 4.

Apparently, this would seem something not too much hard to do. It would involve:

  1. Identify which source should be used for the initial parsing. XML generated with --file-to-xml? The VHDL file itself? Some tags-based file? Etc.
  2. Identify the fastest, easiest and most optimized way to parse the obtained dump. Some specific language/library to parse the XML? Etc.
  3. Translate the parsed structures (entities, ports, signals etc.) into the final representation format. Dot? ELK? Etc.

So, I would like to know your opinion about this idea. For example:

  • Is someone already trying to do something similar to this?
  • Would the GHDL generated XML be the perfect starting point, or something better could be done?
  • What could be the best and fastest way to parse the XML file?

I thought about the XML dump, but maybe better solutions exist. Maybe the netlist obtained by GHDL synthesis? My dream one day would be to parse the VHDL file and obtain a schematic using some advanced routing algorithms which would automatically produce the layout.

This kind of algorithms already exist, here are some great examples using ELK, one of the best automatic layout and routing algorithm currently available:

created time in 3 days

issue commentghdl/ghdl

How to use GHDL .o from an external C program?

/cc @ktbarrett @whitequark @tomverbeure @mithro @PiotrZierhoffer @mgielda @kgugala /subject FYI: discussion about co-simulation of a Verilog machine around a VHDL CPU

Hi again @hrvach!

I use Verilator, the Verilog -> C++ translation

For clarification, regarding my previous explanation about HDL simulators needing "to be the root and absolute managers", note that Verilator is precisely a way to work around that: it provides everything except the root of the runtime, which you are in charge of. The concept of a 'ghdlator'|'vhdlator' has been discussed before, but it's not implemented.

All of this is to avoid having to do actual FPGA synthesis for every change because that takes forever.

Note that the advantage of (co)simulation depends on the complexity and the duration of the test. Typically, simulation is faster because we test very short periods. The are corner cases where simulation is slower than synthesis. Still, it might be desirable because, e.g. not all the modules/components might be finished yet.

I have the memory, bus, logic and peripherals in Verilog, testbench in C that actually has UI in SDL and soft CPU in C I am looking to replace with the compiled VHDL.

Thanks for providing this explanation. As you will see, this is of critical importance. Next time, do not hesitate to explain this (the context) from the beginning (this is just a fairly remainder :wink:).

The quick answer is, you cannot generate *.o objects from VHDL (components) and have them included in your C root, the same way you are including you Verilated (C++) modules. You need to forget about that code structure/architecture. I'm not saying it is not technically possible; it might be, but not with the currently available open source tools.

Let's leave the VHDL-Verilog co-simulation aside, for now. We'll get back to that later. Let's focus on testing an existing CPU in VHDL only. As a reference, the CPU will have a single (registered) input port and a single output port, apart from CLK and RST.

entity tb is
end entity;

architecture test of tb is

  signal clk, rst : std_logic := '0';
  signal iport, oport : std_logic_vector(31 downto 0);

begin

  clk <= not clk after 10 ns; -- 50 MHz

  process
  begin
    report "Start simulation";
    rst <= '0';
    wait for 100 ns;
    rst <= '1';
    wait for 1 ms;
    report "End simulation";
    std.env.stop(0);
    wait;
  end process;

  process(clk)
  begin
    if rising_edge(clk) then

      iport <= COSIM_FUNCTION(oport);

    end if;
  end process;

  UUT: entity work.CPU
  port map (
    CLK   => clk,
    RST   => rst,
    IPORT => iport,
    OPORT => oport
  );

end;

That's a very basic VHDL testbench, where RST is kept high for 100 ns and the simulation lasts 1 ms. In each rising edge of clk, a function receives oport (the output of the CPU) and generates iport (the input of the CPU).

You might implement that COSIM_FUNCTION as a plain VHDL function that reads a text file (maybe a CSV) or a binary file (see Files – theory & examples). It would be a two column table. In each execution after the first one, you compare the oport with the expected output from the previous cycle, and you load the new value for iport.

However, generating text files in a different language and reading them in VHDL is cumbersome. Binary files make it slightly easier, but it is not comfortable for handling tables/matrices. Instead, we can implement COSIM_FUNCTION in C. That's what the VHPIDIRECT examples in ghdl-cosim are about. These are the prototypes of the VHDL function and the corresponding C function:

function COSIM_FUNCTION ( oport : std_logic_vector(31 downto 0) ) return std_logic_vector(31 downto 0);
char* COSIM_FUNCTION (char* oport);

std_logic are 9-value enumerations (see Type declarations). That's why the vectors are char* in C. Typically, we will want to manipulate 32 bit vectors as signed/unsigned integers. Let's fix that:

  process(clk)
  begin
    if rising_edge(clk) then
      iport := std_logic_vector(to_signed(
                 COSIM_FUNCTION( integer(signed(oport)) )
               , 32));
    end if;
  end process;
function COSIM_FUNCTION ( oport : integer ) return integer;
int32_t COSIM_FUNCTION (int32_t oport);

Now, we can use C for evaluating each call to COSIM_FUNCTION by using an integer representing 32 bit input/output ports. For example, assuming that the CPU adds 10 to the input every clock cycle and provides it through the output:

int32_t TABLE[5][2] = {
  { 0, 10 },
  { 1, 11 },
  { 2, 12 },
  { 3, 13 },
  { 4, 14 },
}

uint8_t id = 0;

int32_t COSIM_FUNCTION (int32_t oport) {
  if ( id == 0 ) {
    return TABLE[0][0];
  }
  // Avoid crashing if the simulation is 'too long'
  if ( id > 4 ) {
    return 0;
  }
  assert( oport == TABLE[id++][0]);
  return TABLE[id][1];
}

In practice, all the C code is loaded in the same memory space as the simulation. Hence, the global variables in the C sources retain their values for all the duration. Nevertheless, we might keep track of id in VHDL instead, and pass it as an additional argument to COSIM_FUNCTION. That's how "frames" are marked in VGA (RGB image buffer) (see also VGA test pattern).

If you don't provide your own main function, GHDL will take care of that. Yet, you can provide it:

int32_t TABLE[5][2];

uint8_t id;

int32_t COSIM_FUNCTION (int32_t oport) {
  if ( id == 0 ) {
    return TABLE[0][0];
  }
  // Avoid crashing if the simulation is 'too long'
  if ( id > 4 ) {
    return 0;
  }
  assert( oport == TABLE[id++][0]);
  return TABLE[id][1];
}

int main(int argc, char* argv) {
  id = 0;
  TABLE = {
    { 0, 10 },
    { 1, 11 },
    { 2, 12 },
    { 3, 13 },
    { 4, 14 },
  };
  return ghdl_main(argc, argv);
}

Writing your custom main allows dynamically generating test data before starting the simulation, and/or manipulating GHDL's CLI arguments. This is explained in Wrapping a simulation (ghdl_main) (see examples in Wrapping ghdl_main).

Effectively, we now have a C interface. Instead of generating an executable binary, we can let GHDL generate a shared library. That allows loading it in e.g. Python, to have the TABLE generated with, say, some SciPy module. That's what Shared libs and dynamic loading is about. See also #1398. Note that you cannot generate a shared lib with a main function. That's why Python examples in ghdl-cosim use something else.

Summarising, we defined a callback using VHDL for describing precisely where in the hierarchy to call it and with which frequency it needs to be called. We also used VHDL for converting the data types to some which are friendly for binding to C. This meaningful because VHDL is much better designed for manipulating bits/slices that C.

At this point, from a higher level perspective, it is easy to understand VPI. With VPI, you don't need to write the VHDL testbench, and you don't need to define a COSIM_FUNCTION providing prototypes in VHDL and C. Instead, you can use the UUT as the top level of the HDL hierarchy, and there is an interface in C that allows you to "register a callback that is executed every X time". That callback receives the model/hierarchy of the simulation, which you can navigate through the API for reading/writing values. It might be misleading with VPI that, despite writting the entrypoint and registering everythin in C, the simulator is still the root of the execution.

In my opinion, the main limitation of not writing any VHDL testbench is that you are forced to doing all hierarchy navigation and the type manipulation in C. Moreover, accessing arrays/records through VPI is not supported in GHDL yet (see #1249). However, if you want to manipulate top-level ports only, it fits the purpose.

Instead of dealing with VPI in C, you can use cocotb, which is a Python wrapper around VPI. Although not exactly my cup of tea (I'm a VHDL person), cocotb is the fastest growing verification/testing approach: https://larsasplund.github.io/github-facts/verification-practices.html. You might want to have a look at this WIP discussion about combining cocotb and a top-level VHDL testbench: https://github.com/umarcor/vunit-cocotb/.

Therefore, and this is very important, GHDL's VHPIDIRECT and VPI are mostly equivalent. The main difference is the language you use for writting your test code. In both cases, GHDL is the root and it executes callbacks. Verbosity is different, each has some specific features which make things easier/harder, etc. so it's not exactly the same, but almost.

Now, back to your context. You don't want to generate iport values and/or to assert oport values in C/Python. You want to plug the rest of the machine (written in Verilog):

  • Option 1. Take COSIM_FUNCTION and put all your Verilated models inside. That is, let GHDL be the root, and evaluate the C++ models with a fixed frequency (in terms of simulation time). See #1335, where a user reported co-simulating microwatt (VHDL) and Litedram (Verilog) using this approach. I am not aware of a similar example using VPI, but it should be equivalent.
  • Option 2. Forget about this issue. Take VHDL + Verilog sources and synthesise them with ghdl-yosys-plugin + Yosys.
    • Option 2.a. Use Yosys' write_verilog command for generating post-synthesis Verilog sources. Process those with Verilator.
    • Option 2.b. Use CXXRTL, instead of write_verilog.
    • In any case, simulate as if VHDL or GHDL did never exist; i.e., be the manager of the simulation as you are used to doing with Verilator.

Naturally, options 2 have some caveats, such as not being able to simulate non-synthesisable VHDL models (Verilator is constrained to the synthesisable subset of Verilog anyway), or being lost in the conversion/mangling/flattening/casing. That's why I explained all the details about VHPIDIRECT, and that' why I think that VHPIDIRECT + Verilator is the way to go. Still, if you want to treat VHDL sources as a black box with "simple" port types, Yosys might be the best approach.

Closing remarks:

  • I wrote all the code examples above off the top of my head. There might be a lot of typos/bugs. Please, find working examples in ghdl-cosim (all of them are tested in CI).
  • I did never use CXXRTL, and I just run a couple of examples with cocotb.
  • GHDL's implementation of VHPIDIRECT is not compliant with the usage of the term/keyword VHPIDIRECT in the VHDL LRM, where it's part of VHPI. The concept of how VHPI/VHPIDIRECT work in the LRM is closer to VPI than to a Foreign Function Interface (FFI). However, what I explained above is essentially a FFI. That's why there is an on-going discussion in the VHDL Analysis and Standardisation Group (VASG) about including a FFI in the next revision of the standard: [LCS-202x] VHDL DPI/FFI based on GHDL’s implementation of VHPIDIRECT.

That was intense 😊 Cheers!

hrvach

comment created time in 3 days

startedsamlittlewood/caravel_carrier

started time in 3 days

startedwuxx/litexOnColorlightLab004

started time in 3 days

startedwuxx/Colorlight-FPGA-Projects

started time in 3 days

more