
Synchronizing Verilog, Python and C - ashitlerferad
http://blog.elphel.com/2016/03/synchronizing-verilog-python-and-c/
======
jhallenworld
This is one of those repeatedly solved problems in chip design... Here is my
solution:

[https://github.com/jhallen/joes-
sandbox/tree/master/verilog-...](https://github.com/jhallen/joes-
sandbox/tree/master/verilog-tools/vcsr)

My solution allows you to define registers as module instantiations throughout
the design hierarchy. Parameters give the address and bit positions of each
register. A tool extracts the registers and generates documentation and a C
header file for the chip. The tool has to elaborate the design to determine
the parameter values- so it also handles derived addresses by handling math
involving parameters. It generates C names for the registers which match the
register instantiation path in the design hierarchy (and tries to simplify it
by providing just enough of the path to make the names unique). Field names
are derived from the names of the wires connected to the register bits.

I've seen other tools which work the other way: the master is a C header file,
and the Verilog is derived. I'm not a fan of this, since it means you are have
to plumb signals to a central register file module, which creates a big mess.

I like to use an OR-tree for the on-chip register bus- I think it's the
optimal design for FPGAs. I have a library which includes simple registers and
modules which allow the internal bus to cross clock domains. Look at bus*.v
here:

[https://github.com/jhallen/joes-
sandbox/tree/master/fpga/hdl...](https://github.com/jhallen/joes-
sandbox/tree/master/fpga/hdl_lib)

You have to plumb just two identifiers throughout the design for the
registers: bus_in and bus_out.

~~~
Andrey_Filippov
Yes, you are absolutely right about "repeatedly solved problems", so it is
definitly one in the series of "yet another ...". I'll try your program on our
project files to see what registers it can extract from it. I'm assuming that
there is no perfect universal solution, and I agree that Verilog-to-C (just
having C in the back of your mind while working on the FPGA) is better here
than C-to-Verilog. So in our case there is no automatic generator, code just
helps you to avoid errors. Python program imports Verilog
parameters/localparams (just constants and the the ones derived from them
using expressions) and catches most of the typos when I write the generator
code (not dramatically shorter than what it generates). This allows me to be
flexible - the instantiated modules are not very uniform and not all have
exactly the same interface - many were developed a long time ago starting as
early as 2002. Not many are that old, but there are still many interface
variations, and I do not mind going once more through them before switching to
the C work from Verilog. I want just two things:

\- reduce the number of possible errors as a result of the manual translation
and

\- make this (somewhat hand-crafted) converter be able to synchronize future
changes in Verilog code to the C code that uses it, so five years from now it
will be easy to add functionality to the system.

And thanks again for the links - I'll look more into your code.

------
co_dh
First, I've never programmed Verilog before. But I see this breaks the DRY
principle. If I'm in your position, I may put the information into data, and
interpreter the data in Verilog, C, python.

Again, I don't have Verilog experience before and I might be totally wrong.

~~~
Andrey_Filippov
Yes, I'm guilty in DRY violation and I mentioned it in the post - I still
manually translate Verilog to Python when go from simulation/debugging to
hardware testing/debugging. And we are looking to use a more productive way to
do this - write the simulation code (that replaces the CPU activity of the
real hardware) in the programming language (Python) rather than switching to
System Verilog that is somewhat in between the hardware description language
and a software programming one. That is in our future plans, not there yet.

Other than that - DRY is always in our agenda, and there is only one place
that holds the parameters/ preprocessor macros that define the hardware and
its software interface. Python code reads Verilog files and extracts all the
parameter names and values (names/types are automatically added to the Python
source to allow checking). That Python code allows to run tests on the target
system, do some calibration and save results in the same Verilog parameters
format (same as here
[https://github.com/Elphel/x393/blob/master/includes/x393_cur...](https://github.com/Elphel/x393/blob/master/includes/x393_cur_params_target.vh)
, just no header). Same program uses Verilog data to export C files, it uses
hand-crafted code to allow flexibility - it is not always possible to fit
everything in the same format, but here the focus is again on the DRY - new
code to do what is different, and use common code that processes multiple data
items as much as possible. And when it is not - provide checks to catch
differences when you do have to repeat yourself.

Only part of the Python code is a "translation" of the Verilog tests (and this
we plan to eliminate in the future), the rest is just a continuation of the
project, and when writing (not just running) that code I'm re-using data
exported from the Verilog (and re-exported when there are changes that
influence data). Same with C - code continues the project, re-using
Verilog+Python data.

