VPP library webpage

(still under construction)


What is VPP?
        VPP is a C++ class library. A C++ program linked to VPP has the ability to simulate and generate Verilog HDL code.

What is the main purpose of VPP?
        In some situations, it is very important to be able to model the behavior of the programmable logic using standard programming languages, such as C++. One example of such situation is the development of the hardware for CMS detector, which is being constructed at CERN.
        CERN requires all software models to be written in C++. A typical approach is to write a model in C++, and then make your programmable logic match that model. Unfortunately, the process of matching the model and the logic is very painful and time-consuming if the size of the project is significant.
        The main purpose of VPP is to make this process very straightforward and simple.

What are the main steps of development with VPP?

  1. You write the model of your logic device in C++ using syntax very similar to Verilog HDL.
  2. Model is debugged using any C++ compiler and debugger.
  3. Once you are satisfied with the model,  it is recompiled with VGEN parameter defined.
  4. The recompiled model, when run, generates human-readable Verilog HDL files containing the code equivalent to the model. You can easily trace line-by-line correspondence  between your model and generated Verilog HDL code.
  5. The generated files are synthesized into the hardware logic using any Verilog HDL compiler.

 

How do I write C++ code compatible with VPP?

        VPP has many classes and macros designed to represent all Verilog HDL constructs. Each Verilog module is represented as a C++ class. For each source file in Verilog (.v files) and for each function used in the code two C++ files have to be created: .h (header) and .cpp (source). Below is the table showing the correspondence between these three files for the module and function structure.

Description

a.v

a.h or func.h

a.cpp or func.cpp

Module declaration

module a(

i1,

i2,
o1,

o2);

input [1:0] i1;

input i2;

output o1;

output [1:0] o2;

reg   [1:0] o2;


/*module body here*/

endmodule

class a : public module
{
public:
   void operator()(

Signal i1,
Signal i2,
Signal o1,
Signal o2);

};

#include “a.h”
void a::operator()(

Signal i1,
Signal i2,
Signal o1,
Signal o2)

{
initio

Input_ (i1, 1, 0);

Input (i2);

Output (o1);

OutReg_ (o2, 1, 0);

beginmodule

/*module body here*/

endmodule
}

Function declaration

function [11:0] func;

input [11:0] a;
input [11:0] b;

begin

func = a+b;

end

endfunction

class func : public function
{

public:

Signal operator()(

Signal a, Signal b);

};

#include “func.h”
Signal func::operator()(

Signal a,
Signal b)

{
initio

Input_ (a, 11, 0);

Input_ (b, 11, 0);

beginfunction

result = a + b;

// “result” pre-declared
// variable is returned
// from function
endfunction
}

 

All shown below appears inside the module body

All shown below appears inside the class declaration’s public section.

All shown below appears between “beginmodule” and “endmodule” macros

reg declaration

reg [2:0] r1;
reg r2;

Signal r1, r2;

Reg_(r1, 2, 0);
Reg(r2);

wire declaration

wire [2:0] w1;
wire w2;

Signal w1, w2;

Wire_(w1, 2, 0);
Wire(w2);

Memory declaration

reg [2:0] mem [5:0];

memory mem;

Reg__(mem, 2, 0, 5, 0);

module instantiation

a a1 (i1, i2, o1);

a a1;

a1.init(“a”, “a1”);
a1(i1, i2, o1);

Function declaration

function [11:0] func;

input a, b;

begin

func = a+b;

end

endfunction

 

f.init(11, 0, "func");

Function call

a = func (b, c)

 

a = f(b, c);

for statement

for (i = 0;

i < 5;

i = i + 1)

begin
/*loop body*/
end

 

For (i = 0,

i < 5,
i = i + 1)

begin
/*loop body*/
end

if /else statement

if (a > b)
begin
end
else
begin
end

 

If (a > b)
begin
end
Else
begin
end

? : statement

a = (b == 0) ? c : d;

 

a = ifelse (b == 0, c, d);

case statement

case (r1)

1:
begin ... end

2,3:
begin ... end

default:
begin ... end

endcase

 

begincase (r1)

case1(1)
begin ... end

case2(2,3)
begin ... end

Default
begin ... end

endcase

always statement

always @(a or b or c)
begin

end

 

always @(posedge clk)

begin

end

 

always (a or b or c)
begin

end

 

always (posedge(clk))

begin

end

 

note: you must use “begin … end” pair with “always” blocks.

Concatenation

{a, b, c}

 

(a, b, c)

Bit selection

a[3]
a[5:3]

 

a(3)
a(5, 3)

Memory element selection

mem[4]

 

mem [4]

Unary operators

| a
& a
^ a

 

ror (a)
rand (a)
rxor (a)

Assignment

assign a = b;

 

assign a = b;