Skip to content

A library to generate parameterized Verilog code from C++. Allows you to assemble Verilog modules in C++, use C++ syntax to dynamically generate complex connections, parameterize code, and ultimately get the Verilog code automatically generated.

License

Sooryakiran/dotV

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dotV

A library to generate parameterized Verilog code from C++.

What does it do?

Now you can construct Verilog modules in C++, use C++ syntax to dynamically generate complex connections, parameterize code, and finally get the Verilog code automatically generated.

What comes out of the box?

The library contains all the gates implemented. Furthermore, a Carry Ripple Adder, a Carry Lookahead Adder (Pipelined and flat), and a Wallace Tree Multiplier (Pipelined) also come as part of the core. All modules are parameterized. Both dataflow and behavior models are supported.

Compiling

To compile everything including, the example code src/main.cpp run, make all

Contributions

Contributions are welcome to improve the usability and flexibility of the library. This code was written as a part of my coursework, and as of now, is very basic. Further developments are not likely to occur unless I am really bored of watching Netflix.

Example code

Every Verilog module exists as a Chip Object in C++. All modules derive from the Chip Parent. There are also wire objects, which is basically a string. The Chips can have any number of wires or other Chips inside them. The Verilog file is automatically generated by recursing through all sub Chips and wires. I have already implemented some basic logic gates. The The chip also provides other useful functions like transistor count and painless insertion of other sub Chips.

The following example (./src/example.cpp) shows how to create a module for computing OUT=A&(B^C):

#include <iostream>
#include <verilog.h>
#include <vector>
using namespace std;

class MyChip : public Chip{
  public:
  MyChip(string name, vector<wire> input_wires, wire output_wires);
  };
  
MyChip::MyChip(string name, vector<wire>input_wires, wire output_wires){
  /*------------------------------------------------------------------------------------------
  We do the basic setups.
  This chip takes multiple inputs and has only one output. However, our chip objects require setup as various inputs and multiple outputs. So we push the outputs to the null vector.
  ------------------------------------------------------------------------------------------*/
  this->name = name;
  this->inputs = input_wires;
  this->outputs.push_back(output_wires);
  /*------------------------------------------------------------------------------------------
  We need to tell the Chip Object, which ones are our inputs and our outputs.
  ------------------------------------------------------------------------------------------*/
  this->declare("A", CHIP_INPUTS);
  this->declare("B", CHIP_INPUTS);
  this->declare("C", CHIP_INPUTS);
  this->declare("OUT", CHIP_OUTPUTS);
  /*------------------------------------------------------------------------------------------
  Now we do the wiring part. We need to create a wire to store temp outputs from XOR. Then we create instances of an XOR and an AND gate. Basic logic gates are already implemented.
  ------------------------------------------------------------------------------------------*/
  wire temp_wire = "temp_wire";
  XOR my_xor_gate("MyChipSubXOR1",  // Name
                  {"B", "C"},       // Inputs
                  temp_wire);       // Outputs
  
  AND my_and_gate("MyChipSubAND1",
                  {temp_wire, "A"},
                  "OUT");
  /*------------------------------------------------------------------------------------------
  Then we attach these individual instances to the parent chip.
  ------------------------------------------------------------------------------------------*/
  this->add_wire(temp_wire);
  this->add_submodule(my_xor_gate);
  this->add_submodule(my_and_gate);
  /*------------------------------------------------------------------------------------------
  Now we automatically generate the module definitions using the auto_gen() function.
  ------------------------------------------------------------------------------------------*/
  this->definition = this->auto_gen("module MyChip");
  /*------------------------------------------------------------------------------------------
  Now we need to specify the syntax to instantiate this chip. For example :
  MyChip my_instance_1("instance_name", "my_a", "my_b", "my_c", "my_out");
  }
  ------------------------------------------------------------------------------------------*/
  this->generate = "MyChip " + this->name + " (" + this->inputs.at(0) + ", " + this->inputs.at(1) + ", "
  + this->inputs.at(2) + ", " + this->outputs.at(0) + ");";
}

int main(){
  MyChip instance_1("my_instance_1",
                    {"input_1", "input_2", "input_3"},
                    "output");
  cout<<instance_1.generate_verilog();
  cout<<"\n--------------------------------------------------\n";
  cout<<instance_1.generate<<"\n";
}

About

A library to generate parameterized Verilog code from C++. Allows you to assemble Verilog modules in C++, use C++ syntax to dynamically generate complex connections, parameterize code, and ultimately get the Verilog code automatically generated.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages