Verilog to Routing XML file generation from Verilog (f4pga-v2x)

Documentation Status

v2x is a tool for converting specialized annotated Verilog models into XML needed for Verilog to Routing flow.

Documentation can be found at https://f4pga-v2x.readthedocs.io/en/latest/.

Installation

v2x can be installed from a local git repository using pip.

cd f4pga-v2x
pip install .

Alternatively, it can be installed from GitHub directly.

pip install git+https://github.com/chipsalliance/f4pga-v2x.git#egg=f4pga-v2x

Usage

After installing v2x, you can run v2x to use it.

v2x -h
usage: __main__.py [-h] [--top TOP] [--outfile OUTFILE] [--includes INCLUDES]
                   [--mode {pb_type,model}]
                   input.v [input.v ...]

Verilog to XML

positional arguments:
  input.v               One or more Verilog input files, that will be passed
                        to Yosys internally. They should be enough to generate
                        a flattened representation of the model, so that paths
                        through the model can be determined.

optional arguments:
  -h, --help            show this help message and exit
  --top TOP             Top level module, will usually be automatically
                        determined from the file name im.v
  --outfile OUTFILE, -o OUTFILE
                        Output filename, default 'output.xml'
  --includes INCLUDES   Comma separate list of include directories.
  --mode {pb_type,model}
                        Output file type, possible values are: pb_type and
                        model. Default value is pb_type

For example, to generate a pb_type xml file from adder.v, run

v2x -o adder.pb_type.xml adder.v

Or, to generate a model xml file, run

v2x --mode model -o adder.model.xml adder.v

v2x expects the module name to be the same as the file name. If it is different, make sure to specifiy it with the --top argument.

v2x --top BLOCK -o adder.pb_type.xml adder.v

Tests

The test cases are stored in tests/, and pytest can be used to run them.

rm -rf build  # run this step so that pytest uses the latest files for the tests
pytest -vv

If you are making changes to any python code, make sure that they follow the PEP8 style guide by running flake8.

flake8 tests
flake8 v2x

Documentation

We use sphinx for our documentation and the files are stored in docs/. To host it locally (if you are planning to update it), you can use the Makefile inside.

First, run make env to prepare a Conda environment that contains the necessary packages to build and host the documentation site. After that, simply run make livehtml which starts a local server running at port 8000 with the documentation site.

cd docs
make env
make livehtml

Talks

VPR device models generation from Verilog with V2X - Karol Gugala - ORConf 2019

v2x orconf talk

Examples

Here we have examples on how v2x converts a Verilog module to its corresponding model.xml and pb_type.xml files. These examples are taken from the v2x test cases.

Clock multiplexing primitive

This is an example of modeling a clock mux/buffer which utilizes both clock inputs and clock outputs.

By default, clocks are excluded from the combinational sink list. IE They do not have combinational_sink_ports property associated with them. However, clock multiplexers violate this rule as their input clocks do not drive any sequential logic. They are passed to output(s) instead. VPR requires Clock buffers & muxes to be defined in this way.

V2X provides the attribute (* COMB_INCLUDE_CLOCKS *) that when specified on an output port makes appear on the combinational_sink_ports list of its related input port(s) even if it is marked as a clock input.

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/clock_mux/gmux.sim.v
tests/clock_mux/gmux.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// A model of a clock multiplexer with two clock inputs, one clock output and
// a select input.

(* whitebox *)
module GMUX (IP, IC, IS0, IZ);

    // 1st clock input
    (* CLOCK *)
    input  wire IP;

    // 2nd clock input
    (* CLOCK *)
    input  wire IC;

    // Select input
    input  wire IS0;

    // Clock output (has to be defined as a regular output port)
    (* DELAY_CONST_IP="1e-10" *)
    (* DELAY_CONST_IC="2e-10" *)
    (* DELAY_CONST_IS0="3e-10" *)
    (* COMB_INCLUDE_CLOCKS *)
    output wire IZ;

    // Behavioral model:
    assign IZ = IS0 ? IC : IP;

endmodule

In this example the (* COMB_INCLUDE_CLOCKS *) attribute is set on the IZ output making it appear in combinational sinks lists of its associated clock input ports.

gmux.model.xml
<?xml version="1.0"?>
<models>
  <model name="GMUX">
    <input_ports>
      <port combinational_sink_ports="IZ" is_clock="1" name="IC"/>
      <port combinational_sink_ports="IZ" is_clock="1" name="IP"/>
      <port combinational_sink_ports="IZ" name="IS0"/>
    </input_ports>
    <output_ports>
      <port name="IZ"/>
    </output_ports>
  </model>
</models>
gmux.pb_type.xml
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" blif_model=".subckt GMUX" name="GMUX" num_pb="1">
  <clock name="IC" num_pins="1"/>
  <clock name="IP" num_pins="1"/>
  <input name="IS0" num_pins="1"/>
  <output name="IZ" num_pins="1"/>
  <delay_constant in_port="GMUX.IC" max="2e-10" out_port="GMUX.IZ"/>
  <delay_constant in_port="GMUX.IP" max="1e-10" out_port="GMUX.IZ"/>
  <delay_constant in_port="GMUX.IS0" max="3e-10" out_port="GMUX.IZ"/>
</pb_type>

Clock

There are various ways for an input or output port to be detected as a clock by v2x. Here are examples on ways to do so.

Autodetection of clock from flipflop
D-Flipflop with one clock

The following shows a simple D-flip flop driven by one clock. input wire a should be detected as a clock because it drives the flip flop.

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/clocks/dff_one_clock/dff_one_clock.sim.v

tests/clocks/dff_one_clock/dff_one_clock.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/*
 * `input wire a` should be detected as a clock because it drives the flip
 * flop.
 */
module BLOCK(a, b, c);
  input wire a;
  input wire b;
  output wire c;

  reg r;
  always @ ( posedge a ) begin
    r <= b;
  end
  assign c = r;
endmodule

As you can see in the generated model, the is_clock attribute of the a port is set to 1, while the b and c ports have their clock attribute set to a.

dff_one_clock.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port is_clock="1" name="a"/>
      <port clock="a" name="b"/>
    </input_ports>
    <output_ports>
      <port clock="a" name="c"/>
    </output_ports>
  </model>
</models>
D-Flipflop with combinational logic

The following shows a combinational logic design driven by a clock. input wire a should be detected as a clock because it drives the flip flop.

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/clocks/dff_comb_one_clock/dff_comb_one_clock.sim.v

tests/clocks/dff_comb_one_clock/dff_comb_one_clock.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * `input wire a` should be detected as a clock because it drives the flip
 * flop.
 */
module BLOCK(a, b, c, d);
  input wire a;
  input wire b;
  input wire c;
  output wire d;

  reg r;
        always @ ( posedge a ) begin
                r <= b | ~c;
        end
  assign d = r;
endmodule

The is_clock attribute of the a port is set to 1, and the ports b, c and d have their clock attribute set to a.

dff_comb_one_clock.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port is_clock="1" name="a"/>
      <port clock="a" combinational_sink_ports="d" name="b"/>
      <port clock="a" combinational_sink_ports="d" name="c"/>
    </input_ports>
    <output_ports>
      <port clock="a" name="d"/>
    </output_ports>
  </model>
</models>
D-Flipflop with two clocks

input wire c1 and input wire c2 should be detected as clocks because they drive the flip flop.

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/clocks/dff_two_clocks/dff_two_clocks.sim.v

tests/clocks/dff_two_clocks/dff_two_clocks.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
module BLOCK(c1, c2, a, b, c, o1, o2);
  input wire c1;
  input wire c2;
  input wire a;
  input wire b;
  input wire c;
  output wire o1;
  output wire o2;

  reg r1;
  reg r2;
        always @ ( posedge c1 ) begin
                r1 <= a | b;
        end
        always @ ( posedge c2 ) begin
                r2 <= b | c;
        end

  assign o1 = r1;
  assign o2 = r2;
endmodule

The is_clock attribute of the c1 and c2 ports are set to 1, and the ports a, b, c, o1 and o2 have their clock attribute set to the respective clocks they are driven by.

dff_two_clocks.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port clock="c1" combinational_sink_ports="o1" name="a"/>
      <port clock="c2 c1" combinational_sink_ports="o2 o1" name="b"/>
      <port clock="c2" combinational_sink_ports="o2" name="c"/>
      <port is_clock="1" name="c1"/>
      <port is_clock="1" name="c2"/>
    </input_ports>
    <output_ports>
      <port clock="c1" name="o1"/>
      <port clock="c2" name="o2"/>
    </output_ports>
  </model>
</models>
Manually set inputs as clock
Manually set input as clock by setting the CLOCK attribute

The following shows that input wire a is given the (* CLOCK *) attribute.


tests/clocks/input_attr_clock/input_attr_clock.sim.v
19
20
21
22
23
24
25
26
27
28
29
/*
 * `input wire a` should be detected as a clock because of the `(* CLOCK *)`
 * attribute.
 */
(* whitebox *)
module BLOCK(a, b, o);
  (* CLOCK *)
  input wire a;
  input wire b;
  output wire o;
endmodule

As such, the is_clock attribute of the a port is set to 1.

input_attr_clock.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port is_clock="1" name="a"/>
      <port name="b"/>
    </input_ports>
    <output_ports>
      <port name="o"/>
    </output_ports>
  </model>
</models>
Force input as regular input by setting the CLOCK attribute

input wire a should be detected as a clock because it drives the flip flop. However, it has the attribute CLOCK set to 0 which should force it to be a regular input.

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/clocks/input_attr_not_clock/block.sim.v

tests/clocks/input_attr_not_clock/block.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * `input wire a` should be detected as a clock because it drives the flip
 * flop. However, it has the attribute CLOCK set to 0 which should force it
 * to be a regular input.
 */
module BLOCK(a, b, c);
    (* CLOCK=0 *)
    input wire a;
    input wire b;
    output wire c;
    
    reg r;
    always @ ( posedge a ) begin
      r <= b;
    end
    assign c = r;
endmodule

As such, the is_clock attribute of the a port is not set.

block.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port clock="a" combinational_sink_ports="c" name="a"/>
      <port clock="a" name="b"/>
    </input_ports>
    <output_ports>
      <port clock="a" name="c"/>
    </output_ports>
  </model>
</models>
block.pb_type.xml
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" blif_model=".subckt BLOCK" name="BLOCK" num_pb="1">
  <input name="a" num_pins="1"/>
  <input name="b" num_pins="1"/>
  <output name="c" num_pins="1"/>
</pb_type>
Set input as clock by name (clk)

An input wire can be set as a clock by assigning clk as its name.


tests/clocks/input_named_clk/input_named_clk.sim.v
19
20
21
22
23
24
25
26
27
28
/*
 * `input wire clk` should be detected as a clock despite this being a black
 * box module.
 */
(* whitebox *)
module BLOCK(clk, a, o);
  input wire clk;
  input wire a;
  output wire o;
endmodule

As such, the is_clock attribute of the clk port is set to 1, without needing to set anything else in the verilog code.

input_named_clk.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port name="a"/>
      <port is_clock="1" name="clk"/>
    </input_ports>
    <output_ports>
      <port name="o"/>
    </output_ports>
  </model>
</models>
Set input as clock by name (regex)

An input wire can be set as a clock by having clk in its name (case insensitive).


tests/clocks/input_named_regex/block.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
(* whitebox *)
module BLOCK(
    input  wire clk,
    input  wire Clk,
    input  wire CLK,
    input  wire clkX,
    input  wire clkBus,
    input  wire sys_clk,
    input  wire sys_clk10,
    input  wire regular_input,
    output wire o
);

endmodule

As such, the is_clock attribute of wires with a variation of clk in their name is set to 1.

block.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port is_clock="1" name="Clk"/>
      <port is_clock="1" name="clk"/>
      <port is_clock="1" name="clkBus"/>
      <port is_clock="1" name="clkX"/>
      <port name="regular_input"/>
      <port is_clock="1" name="sys_clk"/>
      <port is_clock="1" name="sys_clk10"/>
    </input_ports>
    <output_ports>
      <port name="o"/>
    </output_ports>
  </model>
</models>
block.pb_type.xml
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" blif_model=".subckt BLOCK" name="BLOCK" num_pb="1">
  <clock name="CLK" num_pins="1"/>
  <clock name="Clk" num_pins="1"/>
  <clock name="clk" num_pins="1"/>
  <clock name="clkBus" num_pins="1"/>
  <clock name="clkX" num_pins="1"/>
  <clock name="sys_clk" num_pins="1"/>
  <clock name="sys_clk10" num_pins="1"/>
  <input name="regular_input" num_pins="1"/>
  <output name="o" num_pins="1"/>
</pb_type>
Manually set outputs as clock
Manually set output as clock by setting the CLOCK attribute

The following shows that output wire o is given the (* CLOCK *) attribute.


tests/clocks/output_attr_clock/output_attr_clock.sim.v
19
20
21
22
23
24
25
26
27
28
29
/*
 * `output wire o` should be detected as a clock because of the `(* CLOCK *)`
 * attribute.
 */
(* whitebox *)
module BLOCK(a, b, o);
  input wire a;
  input wire b;
  (* CLOCK *)
  output wire o;
endmodule

As such, the is_clock attribute of the o port is set to 1.

output_attr_clock.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port name="a"/>
      <port name="b"/>
    </input_ports>
    <output_ports>
      <port is_clock="1" name="o"/>
    </output_ports>
  </model>
</models>
Set output as clock by name (clk)

An output wire can be set as a clock by assigning clk as its name.


tests/clocks/output_named_clk/output_named_clk.sim.v
19
20
21
22
23
24
25
26
27
28
/*
 * `output wire clk` should be detected as a clock despite this being a black
 * box module.
 */
(* whitebox *)
module BLOCK(a, b, clk);
  input wire a;
  input wire b;
  output wire clk;
endmodule

As such, the is_clock attribute of the clk output port is set to 1.

output_named_clk.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port name="a"/>
      <port name="b"/>
    </input_ports>
    <output_ports>
      <port is_clock="1" name="clk"/>
    </output_ports>
  </model>
</models>
Multiple clocks
Set inputs as clock by name (multiple clock inputs)

input wire rdclk and input wire wrclk have clk in their names, hence are recognized as clock inputs by v2x.


tests/clocks/multiple_inputs_named_clk/multiple_inputs_named_clk.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
/*
 * `input wire rdclk` and `input wire wrclk` should be detected as a clock
 * despite this being a black box module.
 */
(* whitebox *)
module BLOCK(a, rdclk, b, wrclk, c, o);
  input wire a;
  input wire rdclk;
  input wire b;
  input wire wrclk;
  input wire c;
  output wire o;
endmodule

As such, the is_clock attribute of the rdclk and wrclk ports are set to 1.

multiple_inputs_named_clk.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port name="a"/>
      <port name="b"/>
      <port name="c"/>
      <port is_clock="1" name="rdclk"/>
      <port is_clock="1" name="wrclk"/>
    </input_ports>
    <output_ports>
      <port name="o"/>
    </output_ports>
  </model>
</models>
Set outputs as clock by name (multiple clock outputs)

output wire rdclk and output wire wrclk have clk in their names, hence are recognized as clock inputs by v2x.


tests/clocks/multiple_outputs_named_clk/multiple_outputs_named_clk.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
/*
 * `output wire rdclk` and `output wire wrclk` should be detected as a clock
 * despite this being a black box module.
 */
(* whitebox *)
module BLOCK(a, b, rdclk, o, wrclk);
  input wire a;
  input wire b;
  output wire rdclk;
  output wire o;
  output wire wrclk;
endmodule

As such, the is_clock attribute of the rdclk and wrclk ports are set to 1.

multiple_outputs_named_clk.model.xml
<?xml version="1.0"?>
<models>
  <model name="BLOCK">
    <input_ports>
      <port name="a"/>
      <port name="b"/>
    </input_ports>
    <output_ports>
      <port name="o"/>
      <port is_clock="1" name="rdclk"/>
      <port is_clock="1" name="wrclk"/>
    </output_ports>
  </model>
</models>

DSP examples

These are examples of modeling DSP-like complex primitives

Combinational DSP

A combinational DSP block capable of multiplication and division. Modeled as “combinational block” according to Figure 60 of Primitive Block Timing Modeling Tutorial.


/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/dsp/dsp_combinational/dsp_combinational.sim.v

tests/dsp/dsp_combinational/dsp_combinational.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
`ifndef DSP_COMB
`define DSP_COMB
(* whitebox *)
module DSP_COMBINATIONAL (
  a, b, m,
  out
);
  localparam DATA_WIDTH = 4;

  input wire [DATA_WIDTH/2-1:0] a;
  input wire [DATA_WIDTH/2-1:0] b;
  input wire m;

  (* DELAY_CONST_a="30e-12" *)
  (* DELAY_CONST_b="30e-12" *)
  (* DELAY_CONST_m="10e-12" *)
  output wire [DATA_WIDTH-1:0] out;

  // Full adder combinational logic
  assign out = m ? a * b : a / b;
endmodule
`endif
dsp_combinational.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?xml version="1.0"?>
<models>
  <model name="DSP_COMBINATIONAL">
    <input_ports>
      <port combinational_sink_ports="out" name="a"/>
      <port combinational_sink_ports="out" name="b"/>
      <port combinational_sink_ports="out" name="m"/>
    </input_ports>
    <output_ports>
      <port name="out"/>
    </output_ports>
  </model>
</models>
dsp_combinational.pb_type.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" blif_model=".subckt DSP_COMBINATIONAL" name="DSP_COMBINATIONAL" num_pb="1">
  <input name="a" num_pins="2"/>
  <input name="b" num_pins="2"/>
  <input name="m" num_pins="1"/>
  <output name="out" num_pins="4"/>
  <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
  <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
  <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
</pb_type>
Detection of combinational connections
  • Output has combinational connection with input

Blackbox detection
  • Model of the leaf pb_type is generated

  • Leaf pb_type XML is generated

DSP-style block with all inputs registered

A combinational DSP block with registered inputs. Modeled as a complex block.

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/dsp/dsp_in_registered/dsp_in_registered.sim.v

tests/dsp/dsp_in_registered/dsp_in_registered.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
`include "./dff/dff.sim.v"
`include "./dsp_combinational/dsp_combinational.sim.v"

/* DSP Block with register on all inputs */
module DSP_IN_REGISTERED (clk, a, b, m, out);
  localparam DATA_WIDTH = 4;

  input wire clk;
  input wire [DATA_WIDTH/2-1:0] a;
  input wire [DATA_WIDTH/2-1:0] b;
  input wire m;
  output wire [DATA_WIDTH-1:0] out;

  /* Input registers */
  (* pack="DFF2DSP" *)
  wire [DATA_WIDTH/2-1:0] q_a;
  (* pack="DFF2DSP" *)
  wire [DATA_WIDTH/2-1:0] q_b;
  (* pack="DFF2DSP" *)
  wire q_m;

  genvar i;
  for (i=0; i<DATA_WIDTH/2; i=i+1) begin
    DFF q_a_ff(.D(a[i]), .Q(q_a[i]), .CLK(clk));
    DFF q_b_ff(.D(b[i]), .Q(q_b[i]), .CLK(clk));
  end
  DFF m_ff(.D(m), .Q(q_m), .CLK(clk));

  /* Combinational Logic */
  DSP_COMBINATIONAL comb (.a(q_a), .b(q_b), .m(q_m), .out(out));
endmodule
dsp_in_registered.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>
<models>
  <model name="DFF">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port clock="CLK" name="D"/>
    </input_ports>
    <output_ports>
      <port clock="CLK" name="Q"/>
    </output_ports>
  </model>
  <model name="DSP_COMBINATIONAL">
    <input_ports>
      <port combinational_sink_ports="out" name="a"/>
      <port combinational_sink_ports="out" name="b"/>
      <port combinational_sink_ports="out" name="m"/>
    </input_ports>
    <output_ports>
      <port name="out"/>
    </output_ports>
  </model>
</models>
dsp_in_registered.pb_type.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="DSP_IN_REGISTERED" num_pb="1">
  <clock name="clk" num_pins="1"/>
  <input name="a" num_pins="2"/>
  <input name="b" num_pins="2"/>
  <input name="m" num_pins="1"/>
  <output name="out" num_pins="4"/>
  <pb_type blif_model=".subckt DSP_COMBINATIONAL" name="comb" num_pb="1">
    <input name="a" num_pins="2"/>
    <input name="b" num_pins="2"/>
    <input name="m" num_pins="1"/>
    <output name="out" num_pins="4"/>
    <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
    <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
    <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="m_ff" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="q_a_ff" num_pb="2">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="q_b_ff" num_pb="2">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <interconnect>
    <direct input="comb.out[0]" name="DSP_IN_REGISTERED-out[0]" output="DSP_IN_REGISTERED.out[0]"/>
    <direct input="comb.out[1]" name="DSP_IN_REGISTERED-out[1]" output="DSP_IN_REGISTERED.out[1]"/>
    <direct input="comb.out[2]" name="DSP_IN_REGISTERED-out[2]" output="DSP_IN_REGISTERED.out[2]"/>
    <direct input="comb.out[3]" name="DSP_IN_REGISTERED-out[3]" output="DSP_IN_REGISTERED.out[3]"/>
    <direct input="q_a_ff[0].Q" name="comb-a[0]" output="comb.a[0]">
      <pack_pattern in_port="q_a_ff[0].Q" name="pack-DFF2DSP" out_port="comb.a[0]"/>
    </direct>
    <direct input="q_a_ff[1].Q" name="comb-a[1]" output="comb.a[1]">
      <pack_pattern in_port="q_a_ff[1].Q" name="pack-DFF2DSP" out_port="comb.a[1]"/>
    </direct>
    <direct input="q_b_ff[0].Q" name="comb-b[0]" output="comb.b[0]">
      <pack_pattern in_port="q_b_ff[0].Q" name="pack-DFF2DSP" out_port="comb.b[0]"/>
    </direct>
    <direct input="q_b_ff[1].Q" name="comb-b[1]" output="comb.b[1]">
      <pack_pattern in_port="q_b_ff[1].Q" name="pack-DFF2DSP" out_port="comb.b[1]"/>
    </direct>
    <direct input="m_ff.Q" name="comb-m" output="comb.m">
      <pack_pattern in_port="m_ff.Q" name="pack-DFF2DSP" out_port="comb.m"/>
    </direct>
    <direct input="DSP_IN_REGISTERED.clk" name="m_ff-CLK" output="m_ff.CLK"/>
    <direct input="DSP_IN_REGISTERED.m" name="m_ff-D" output="m_ff.D"/>
    <direct input="DSP_IN_REGISTERED.clk" name="q_a_ff[0]-CLK" output="q_a_ff[0].CLK"/>
    <direct input="DSP_IN_REGISTERED.a[0]" name="q_a_ff[0]-D" output="q_a_ff[0].D"/>
    <direct input="DSP_IN_REGISTERED.clk" name="q_a_ff[1]-CLK" output="q_a_ff[1].CLK"/>
    <direct input="DSP_IN_REGISTERED.a[1]" name="q_a_ff[1]-D" output="q_a_ff[1].D"/>
    <direct input="DSP_IN_REGISTERED.clk" name="q_b_ff[0]-CLK" output="q_b_ff[0].CLK"/>
    <direct input="DSP_IN_REGISTERED.b[0]" name="q_b_ff[0]-D" output="q_b_ff[0].D"/>
    <direct input="DSP_IN_REGISTERED.clk" name="q_b_ff[1]-CLK" output="q_b_ff[1].CLK"/>
    <direct input="DSP_IN_REGISTERED.b[1]" name="q_b_ff[1]-D" output="q_b_ff[1].D"/>
  </interconnect>
</pb_type>
Detection of combinational connections
  • Output has combinational connection with input

  • pack_pattern defined on wire connections with pack attribute

Blackbox detection
  • Model of the leaf pb_type is generated

  • Leaf pb_type XML is generated

  • All dependency models and pb_types are included in the output files

DSP-style block with outputs registered

A combinational DSP block with registered outputs. Modeled as a complex block.

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/dsp/dsp_out_registered/dsp_out_registered.sim.v

tests/dsp/dsp_out_registered/dsp_out_registered.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
`include "./dff/dff.sim.v"
`include "./dsp_combinational/dsp_combinational.sim.v"

/* DSP Block with register on the output */
module DSP_OUT_REGISTERED (clk, a, b, m, out);
  localparam DATA_WIDTH = 4;

  input wire clk;
  input wire [DATA_WIDTH/2-1:0] a;
  input wire [DATA_WIDTH/2-1:0] b;
  input wire m;
  output wire [DATA_WIDTH-1:0] out;

  /* Combinational logic */
  (* pack="DSP-DFF" *)
  wire [DATA_WIDTH-1:0] c_out;
  DSP_COMBINATIONAL comb (.a(a), .b(b), .m(m), .out(c_out));

  /* Output register on clk */
  genvar j;
  for (j=0; j<DATA_WIDTH; j=j+1) begin: output_dffs_gen
    DFF q_out_ff(.D(c_out[j]), .Q(out[j]), .CLK(clk));
  end
endmodule
dsp_out_registered.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>
<models>
  <model name="DFF">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port clock="CLK" name="D"/>
    </input_ports>
    <output_ports>
      <port clock="CLK" name="Q"/>
    </output_ports>
  </model>
  <model name="DSP_COMBINATIONAL">
    <input_ports>
      <port combinational_sink_ports="out" name="a"/>
      <port combinational_sink_ports="out" name="b"/>
      <port combinational_sink_ports="out" name="m"/>
    </input_ports>
    <output_ports>
      <port name="out"/>
    </output_ports>
  </model>
</models>
dsp_out_registered.pb_type.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="DSP_OUT_REGISTERED" num_pb="1">
  <clock name="clk" num_pins="1"/>
  <input name="a" num_pins="2"/>
  <input name="b" num_pins="2"/>
  <input name="m" num_pins="1"/>
  <output name="out" num_pins="4"/>
  <pb_type blif_model=".subckt DSP_COMBINATIONAL" name="comb" num_pb="1">
    <input name="a" num_pins="2"/>
    <input name="b" num_pins="2"/>
    <input name="m" num_pins="1"/>
    <output name="out" num_pins="4"/>
    <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
    <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
    <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_0" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_1" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_2" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_3" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <interconnect>
    <direct input="output_dffs_gen_q_out_ff_0.Q" name="DSP_OUT_REGISTERED-out[0]" output="DSP_OUT_REGISTERED.out[0]"/>
    <direct input="output_dffs_gen_q_out_ff_1.Q" name="DSP_OUT_REGISTERED-out[1]" output="DSP_OUT_REGISTERED.out[1]"/>
    <direct input="output_dffs_gen_q_out_ff_2.Q" name="DSP_OUT_REGISTERED-out[2]" output="DSP_OUT_REGISTERED.out[2]"/>
    <direct input="output_dffs_gen_q_out_ff_3.Q" name="DSP_OUT_REGISTERED-out[3]" output="DSP_OUT_REGISTERED.out[3]"/>
    <direct input="DSP_OUT_REGISTERED.a[0]" name="comb-a[0]" output="comb.a[0]"/>
    <direct input="DSP_OUT_REGISTERED.a[1]" name="comb-a[1]" output="comb.a[1]"/>
    <direct input="DSP_OUT_REGISTERED.b[0]" name="comb-b[0]" output="comb.b[0]"/>
    <direct input="DSP_OUT_REGISTERED.b[1]" name="comb-b[1]" output="comb.b[1]"/>
    <direct input="DSP_OUT_REGISTERED.m" name="comb-m" output="comb.m"/>
    <direct input="DSP_OUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_0-CLK" output="output_dffs_gen_q_out_ff_0.CLK"/>
    <direct input="comb.out[0]" name="output_dffs_gen_q_out_ff_0-D" output="output_dffs_gen_q_out_ff_0.D">
      <pack_pattern in_port="comb.out[0]" name="pack-DSP-DFF" out_port="output_dffs_gen_q_out_ff_0.D"/>
    </direct>
    <direct input="DSP_OUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_1-CLK" output="output_dffs_gen_q_out_ff_1.CLK"/>
    <direct input="comb.out[1]" name="output_dffs_gen_q_out_ff_1-D" output="output_dffs_gen_q_out_ff_1.D">
      <pack_pattern in_port="comb.out[1]" name="pack-DSP-DFF" out_port="output_dffs_gen_q_out_ff_1.D"/>
    </direct>
    <direct input="DSP_OUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_2-CLK" output="output_dffs_gen_q_out_ff_2.CLK"/>
    <direct input="comb.out[2]" name="output_dffs_gen_q_out_ff_2-D" output="output_dffs_gen_q_out_ff_2.D">
      <pack_pattern in_port="comb.out[2]" name="pack-DSP-DFF" out_port="output_dffs_gen_q_out_ff_2.D"/>
    </direct>
    <direct input="DSP_OUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_3-CLK" output="output_dffs_gen_q_out_ff_3.CLK"/>
    <direct input="comb.out[3]" name="output_dffs_gen_q_out_ff_3-D" output="output_dffs_gen_q_out_ff_3.D">
      <pack_pattern in_port="comb.out[3]" name="pack-DSP-DFF" out_port="output_dffs_gen_q_out_ff_3.D"/>
    </direct>
  </interconnect>
</pb_type>
Detection of combinational connections
  • Output has combinational connection with input

  • pack_pattern defined on wire connections with pack attribute

Blackbox detection
  • Model of the leaf pb_type is generated

  • Leaf pb_type XML is generated

  • All dependency models and pb_types are included in the output files

DSP-style block with inputs and outputs registered (single clock)
/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/dsp/dsp_inout_registered/dsp_inout_registered.sim.v

tests/dsp/dsp_inout_registered/dsp_inout_registered.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
`include "./dff/dff.sim.v"
`include "./dsp_combinational/dsp_combinational.sim.v"

/* DSP Block with register on both the inputs and the output */
module DSP_INOUT_REGISTERED (clk, a, b, m, out);
  localparam DATA_WIDTH = 4;

  input wire clk;
  input wire [DATA_WIDTH/2-1:0] a;
  input wire [DATA_WIDTH/2-1:0] b;
  input wire m;
  output wire [DATA_WIDTH-1:0] out;

  /* Input registers */
  (* pack = "DFF-DSP" *)
  wire [DATA_WIDTH/2-1:0] q_a;
  (* pack = "DFF-DSP" *)
  wire [DATA_WIDTH/2-1:0] q_b;
  (* pack = "DFF-DSP" *)
  wire q_m;

  genvar i;
  for (i=0; i<DATA_WIDTH/2; i=i+1) begin: input_dffs_gen
    DFF q_a_ff(.D(a[i]), .Q(q_a[i]), .CLK(clk));
    DFF q_b_ff(.D(b[i]), .Q(q_b[i]), .CLK(clk));
  end
  DFF m_ff(.D(m), .Q(q_m), .CLK(clk));

  /* Combinational logic */
  (* pack = "DFF-DSP" *)
  wire [DATA_WIDTH-1:0] c_out;
  DSP_COMBINATIONAL comb (.a(q_a), .b(q_b), .m(q_m), .out(c_out));

  /* Output register */
  wire [DATA_WIDTH-1:0] q_out;
  genvar j;
  for (j=0; j<DATA_WIDTH; j=j+1) begin: output_dffs_gen
    DFF q_out_ff(.D(c_out[j]), .Q(out[j]), .CLK(clk));
  end

endmodule
dsp_inout_registered.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>
<models>
  <model name="DFF">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port clock="CLK" name="D"/>
    </input_ports>
    <output_ports>
      <port clock="CLK" name="Q"/>
    </output_ports>
  </model>
  <model name="DSP_COMBINATIONAL">
    <input_ports>
      <port combinational_sink_ports="out" name="a"/>
      <port combinational_sink_ports="out" name="b"/>
      <port combinational_sink_ports="out" name="m"/>
    </input_ports>
    <output_ports>
      <port name="out"/>
    </output_ports>
  </model>
</models>
dsp_inout_registered.pb_type.xml
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="DSP_INOUT_REGISTERED" num_pb="1">
  <clock name="clk" num_pins="1"/>
  <input name="a" num_pins="2"/>
  <input name="b" num_pins="2"/>
  <input name="m" num_pins="1"/>
  <output name="out" num_pins="4"/>
  <pb_type blif_model=".subckt DSP_COMBINATIONAL" name="comb" num_pb="1">
    <input name="a" num_pins="2"/>
    <input name="b" num_pins="2"/>
    <input name="m" num_pins="1"/>
    <output name="out" num_pins="4"/>
    <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
    <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
    <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_a_ff_0" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_a_ff_1" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_b_ff_0" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_b_ff_1" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="m_ff" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_0" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_1" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_2" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_3" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <interconnect>
    <direct input="output_dffs_gen_q_out_ff_0.Q" name="DSP_INOUT_REGISTERED-out[0]" output="DSP_INOUT_REGISTERED.out[0]"/>
    <direct input="output_dffs_gen_q_out_ff_1.Q" name="DSP_INOUT_REGISTERED-out[1]" output="DSP_INOUT_REGISTERED.out[1]"/>
    <direct input="output_dffs_gen_q_out_ff_2.Q" name="DSP_INOUT_REGISTERED-out[2]" output="DSP_INOUT_REGISTERED.out[2]"/>
    <direct input="output_dffs_gen_q_out_ff_3.Q" name="DSP_INOUT_REGISTERED-out[3]" output="DSP_INOUT_REGISTERED.out[3]"/>
    <direct input="input_dffs_gen_q_a_ff_0.Q" name="comb-a[0]" output="comb.a[0]">
      <pack_pattern in_port="input_dffs_gen_q_a_ff_0.Q" name="pack-DFF-DSP" out_port="comb.a[0]"/>
    </direct>
    <direct input="input_dffs_gen_q_a_ff_1.Q" name="comb-a[1]" output="comb.a[1]">
      <pack_pattern in_port="input_dffs_gen_q_a_ff_1.Q" name="pack-DFF-DSP" out_port="comb.a[1]"/>
    </direct>
    <direct input="input_dffs_gen_q_b_ff_0.Q" name="comb-b[0]" output="comb.b[0]">
      <pack_pattern in_port="input_dffs_gen_q_b_ff_0.Q" name="pack-DFF-DSP" out_port="comb.b[0]"/>
    </direct>
    <direct input="input_dffs_gen_q_b_ff_1.Q" name="comb-b[1]" output="comb.b[1]">
      <pack_pattern in_port="input_dffs_gen_q_b_ff_1.Q" name="pack-DFF-DSP" out_port="comb.b[1]"/>
    </direct>
    <direct input="m_ff.Q" name="comb-m" output="comb.m">
      <pack_pattern in_port="m_ff.Q" name="pack-DFF-DSP" out_port="comb.m"/>
    </direct>
    <direct input="DSP_INOUT_REGISTERED.clk" name="input_dffs_gen_q_a_ff_0-CLK" output="input_dffs_gen_q_a_ff_0.CLK"/>
    <direct input="DSP_INOUT_REGISTERED.a[0]" name="input_dffs_gen_q_a_ff_0-D" output="input_dffs_gen_q_a_ff_0.D"/>
    <direct input="DSP_INOUT_REGISTERED.clk" name="input_dffs_gen_q_a_ff_1-CLK" output="input_dffs_gen_q_a_ff_1.CLK"/>
    <direct input="DSP_INOUT_REGISTERED.a[1]" name="input_dffs_gen_q_a_ff_1-D" output="input_dffs_gen_q_a_ff_1.D"/>
    <direct input="DSP_INOUT_REGISTERED.clk" name="input_dffs_gen_q_b_ff_0-CLK" output="input_dffs_gen_q_b_ff_0.CLK"/>
    <direct input="DSP_INOUT_REGISTERED.b[0]" name="input_dffs_gen_q_b_ff_0-D" output="input_dffs_gen_q_b_ff_0.D"/>
    <direct input="DSP_INOUT_REGISTERED.clk" name="input_dffs_gen_q_b_ff_1-CLK" output="input_dffs_gen_q_b_ff_1.CLK"/>
    <direct input="DSP_INOUT_REGISTERED.b[1]" name="input_dffs_gen_q_b_ff_1-D" output="input_dffs_gen_q_b_ff_1.D"/>
    <direct input="DSP_INOUT_REGISTERED.clk" name="m_ff-CLK" output="m_ff.CLK"/>
    <direct input="DSP_INOUT_REGISTERED.m" name="m_ff-D" output="m_ff.D"/>
    <direct input="DSP_INOUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_0-CLK" output="output_dffs_gen_q_out_ff_0.CLK"/>
    <direct input="comb.out[0]" name="output_dffs_gen_q_out_ff_0-D" output="output_dffs_gen_q_out_ff_0.D">
      <pack_pattern in_port="comb.out[0]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_0.D"/>
    </direct>
    <direct input="DSP_INOUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_1-CLK" output="output_dffs_gen_q_out_ff_1.CLK"/>
    <direct input="comb.out[1]" name="output_dffs_gen_q_out_ff_1-D" output="output_dffs_gen_q_out_ff_1.D">
      <pack_pattern in_port="comb.out[1]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_1.D"/>
    </direct>
    <direct input="DSP_INOUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_2-CLK" output="output_dffs_gen_q_out_ff_2.CLK"/>
    <direct input="comb.out[2]" name="output_dffs_gen_q_out_ff_2-D" output="output_dffs_gen_q_out_ff_2.D">
      <pack_pattern in_port="comb.out[2]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_2.D"/>
    </direct>
    <direct input="DSP_INOUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_3-CLK" output="output_dffs_gen_q_out_ff_3.CLK"/>
    <direct input="comb.out[3]" name="output_dffs_gen_q_out_ff_3-D" output="output_dffs_gen_q_out_ff_3.D">
      <pack_pattern in_port="comb.out[3]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_3.D"/>
    </direct>
  </interconnect>
</pb_type>
Detection of combinational connections
  • Output has combinational connection with input

  • pack_pattern defined on wire connections with pack attribute

Blackbox detection
  • Model of the leaf pb_type is generated

  • Leaf pb_type XML is generated

  • All dependency models and pb_types are included in the output files

DSP-style block with inputs and outputs registered using separate clocks

A combinational DSP block with registered inputs and outputs. Separate clock is used for inputs and outputs. Modeled as a complex block.

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/dsp/dsp_inout_registered_dualclk/dsp_inout_registered_dualclk.sim.v

tests/dsp/dsp_inout_registered_dualclk/dsp_inout_registered_dualclk.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
`include "./dff/dff.sim.v"
`include "./dsp_combinational/dsp_combinational.sim.v"

/* DSP Block with register on both the inputs and the output, which use different clocks */
module DSP_INOUT_REGISTERED_DUALCLK (iclk, oclk, a, b, m, out);
  localparam DATA_WIDTH = 4;

  input wire iclk;
  input wire oclk;
  input wire [DATA_WIDTH/2-1:0] a;
  input wire [DATA_WIDTH/2-1:0] b;
  input wire m;
  output wire [DATA_WIDTH-1:0] out;

  /* Input registers on iclk */
  (* pack="DFF-DSP" *)
  wire [DATA_WIDTH/2-1:0] q_a;
  (* pack="DFF-DSP" *)
  wire [DATA_WIDTH/2-1:0] q_b;
  (* pack="DFF-DSP" *)
  wire q_m;

  genvar i;
  for (i=0; i<DATA_WIDTH/2; i=i+1) begin: input_dffs_gen
    DFF q_a_ff(.D(a[i]), .Q(q_a[i]), .CLK(iclk));
    DFF q_b_ff(.D(b[i]), .Q(q_b[i]), .CLK(iclk));
  end
  DFF m_ff(.D(m), .Q(q_m), .CLK(iclk));

  /* Combinational logic */
  (* pack="DFF-DSP" *)
  wire [DATA_WIDTH-1:0] c_out;
  DSP_COMBINATIONAL comb (.a(q_a), .b(q_b), .m(q_m), .out(c_out));

  /* Output register on oclk */
  wire [DATA_WIDTH-1:0] q_out;
  genvar j;
  for (j=0; j<DATA_WIDTH; j=j+1) begin: output_dffs_gen
    DFF q_out_ff(.D(c_out[j]), .Q(out[j]), .CLK(oclk));
  end

endmodule
dsp_inout_registered_dualclk.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>
<models>
  <model name="DFF">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port clock="CLK" name="D"/>
    </input_ports>
    <output_ports>
      <port clock="CLK" name="Q"/>
    </output_ports>
  </model>
  <model name="DSP_COMBINATIONAL">
    <input_ports>
      <port combinational_sink_ports="out" name="a"/>
      <port combinational_sink_ports="out" name="b"/>
      <port combinational_sink_ports="out" name="m"/>
    </input_ports>
    <output_ports>
      <port name="out"/>
    </output_ports>
  </model>
</models>
dsp_inout_registered_dualclk.pb_type.xml
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="DSP_INOUT_REGISTERED_DUALCLK" num_pb="1">
  <clock name="iclk" num_pins="1"/>
  <clock name="oclk" num_pins="1"/>
  <input name="a" num_pins="2"/>
  <input name="b" num_pins="2"/>
  <input name="m" num_pins="1"/>
  <output name="out" num_pins="4"/>
  <pb_type blif_model=".subckt DSP_COMBINATIONAL" name="comb" num_pb="1">
    <input name="a" num_pins="2"/>
    <input name="b" num_pins="2"/>
    <input name="m" num_pins="1"/>
    <output name="out" num_pins="4"/>
    <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
    <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
    <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_a_ff_0" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_a_ff_1" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_b_ff_0" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_b_ff_1" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="m_ff" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_0" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_1" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_2" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_3" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <interconnect>
    <direct input="output_dffs_gen_q_out_ff_0.Q" name="DSP_INOUT_REGISTERED_DUALCLK-out[0]" output="DSP_INOUT_REGISTERED_DUALCLK.out[0]"/>
    <direct input="output_dffs_gen_q_out_ff_1.Q" name="DSP_INOUT_REGISTERED_DUALCLK-out[1]" output="DSP_INOUT_REGISTERED_DUALCLK.out[1]"/>
    <direct input="output_dffs_gen_q_out_ff_2.Q" name="DSP_INOUT_REGISTERED_DUALCLK-out[2]" output="DSP_INOUT_REGISTERED_DUALCLK.out[2]"/>
    <direct input="output_dffs_gen_q_out_ff_3.Q" name="DSP_INOUT_REGISTERED_DUALCLK-out[3]" output="DSP_INOUT_REGISTERED_DUALCLK.out[3]"/>
    <direct input="input_dffs_gen_q_a_ff_0.Q" name="comb-a[0]" output="comb.a[0]">
      <pack_pattern in_port="input_dffs_gen_q_a_ff_0.Q" name="pack-DFF-DSP" out_port="comb.a[0]"/>
    </direct>
    <direct input="input_dffs_gen_q_a_ff_1.Q" name="comb-a[1]" output="comb.a[1]">
      <pack_pattern in_port="input_dffs_gen_q_a_ff_1.Q" name="pack-DFF-DSP" out_port="comb.a[1]"/>
    </direct>
    <direct input="input_dffs_gen_q_b_ff_0.Q" name="comb-b[0]" output="comb.b[0]">
      <pack_pattern in_port="input_dffs_gen_q_b_ff_0.Q" name="pack-DFF-DSP" out_port="comb.b[0]"/>
    </direct>
    <direct input="input_dffs_gen_q_b_ff_1.Q" name="comb-b[1]" output="comb.b[1]">
      <pack_pattern in_port="input_dffs_gen_q_b_ff_1.Q" name="pack-DFF-DSP" out_port="comb.b[1]"/>
    </direct>
    <direct input="m_ff.Q" name="comb-m" output="comb.m">
      <pack_pattern in_port="m_ff.Q" name="pack-DFF-DSP" out_port="comb.m"/>
    </direct>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.iclk" name="input_dffs_gen_q_a_ff_0-CLK" output="input_dffs_gen_q_a_ff_0.CLK"/>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.a[0]" name="input_dffs_gen_q_a_ff_0-D" output="input_dffs_gen_q_a_ff_0.D"/>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.iclk" name="input_dffs_gen_q_a_ff_1-CLK" output="input_dffs_gen_q_a_ff_1.CLK"/>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.a[1]" name="input_dffs_gen_q_a_ff_1-D" output="input_dffs_gen_q_a_ff_1.D"/>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.iclk" name="input_dffs_gen_q_b_ff_0-CLK" output="input_dffs_gen_q_b_ff_0.CLK"/>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.b[0]" name="input_dffs_gen_q_b_ff_0-D" output="input_dffs_gen_q_b_ff_0.D"/>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.iclk" name="input_dffs_gen_q_b_ff_1-CLK" output="input_dffs_gen_q_b_ff_1.CLK"/>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.b[1]" name="input_dffs_gen_q_b_ff_1-D" output="input_dffs_gen_q_b_ff_1.D"/>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.iclk" name="m_ff-CLK" output="m_ff.CLK"/>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.m" name="m_ff-D" output="m_ff.D"/>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.oclk" name="output_dffs_gen_q_out_ff_0-CLK" output="output_dffs_gen_q_out_ff_0.CLK"/>
    <direct input="comb.out[0]" name="output_dffs_gen_q_out_ff_0-D" output="output_dffs_gen_q_out_ff_0.D">
      <pack_pattern in_port="comb.out[0]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_0.D"/>
    </direct>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.oclk" name="output_dffs_gen_q_out_ff_1-CLK" output="output_dffs_gen_q_out_ff_1.CLK"/>
    <direct input="comb.out[1]" name="output_dffs_gen_q_out_ff_1-D" output="output_dffs_gen_q_out_ff_1.D">
      <pack_pattern in_port="comb.out[1]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_1.D"/>
    </direct>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.oclk" name="output_dffs_gen_q_out_ff_2-CLK" output="output_dffs_gen_q_out_ff_2.CLK"/>
    <direct input="comb.out[2]" name="output_dffs_gen_q_out_ff_2-D" output="output_dffs_gen_q_out_ff_2.D">
      <pack_pattern in_port="comb.out[2]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_2.D"/>
    </direct>
    <direct input="DSP_INOUT_REGISTERED_DUALCLK.oclk" name="output_dffs_gen_q_out_ff_3-CLK" output="output_dffs_gen_q_out_ff_3.CLK"/>
    <direct input="comb.out[3]" name="output_dffs_gen_q_out_ff_3-D" output="output_dffs_gen_q_out_ff_3.D">
      <pack_pattern in_port="comb.out[3]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_3.D"/>
    </direct>
  </interconnect>
</pb_type>
Detection of combinational connections
  • Output has combinational connection with input

  • pack_pattern defined on wire connections with pack attribute

Blackbox detection
  • Model of the leaf pb_type is generated

  • Leaf pb_type XML is generated

  • All dependency models and pb_types are included in the output files

DSP-style block with only one input registered

A combinational DSP block with all but one registered inputs. Modeled as a complex block.

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/dsp/dsp_partial_registered/dsp_partial_registered.sim.v

tests/dsp/dsp_partial_registered/dsp_partial_registered.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
`include "./dff/dff.sim.v"
`include "./dsp_combinational/dsp_combinational.sim.v"

/* DSP Block with register on only some inputs */
module DSP_PARTIAL_REGISTERED (clk, a, b, m, out);
  localparam DATA_WIDTH = 4;

  input wire clk;
  input wire [DATA_WIDTH/2-1:0] a;
  input wire [DATA_WIDTH/2-1:0] b;
  input wire m;
  output wire [DATA_WIDTH-1:0] out;

  /* Input registers */
  (* pack="DFF-DSP" *)
  wire [DATA_WIDTH/2-1:0] q_a;
  (* pack="DFF-DSP" *)
  wire [DATA_WIDTH/2-1:0] q_b;

  genvar i;
  for (i=0; i<DATA_WIDTH/2; i=i+1) begin: dffs_gen
    DFF q_a_ff(.D(a[i]), .Q(q_a[i]), .CLK(clk));
    DFF q_b_ff(.D(b[i]), .Q(q_b[i]), .CLK(clk));
  end

  /* Combinational Logic */
  DSP_COMBINATIONAL comb (.a(q_a), .b(q_b), .m(m), .out(out));
endmodule
dsp_partial_registered.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>
<models>
  <model name="DFF">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port clock="CLK" name="D"/>
    </input_ports>
    <output_ports>
      <port clock="CLK" name="Q"/>
    </output_ports>
  </model>
  <model name="DSP_COMBINATIONAL">
    <input_ports>
      <port combinational_sink_ports="out" name="a"/>
      <port combinational_sink_ports="out" name="b"/>
      <port combinational_sink_ports="out" name="m"/>
    </input_ports>
    <output_ports>
      <port name="out"/>
    </output_ports>
  </model>
</models>
dsp_partial_registered.pb_type.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="DSP_PARTIAL_REGISTERED" num_pb="1">
  <clock name="clk" num_pins="1"/>
  <input name="a" num_pins="2"/>
  <input name="b" num_pins="2"/>
  <input name="m" num_pins="1"/>
  <output name="out" num_pins="4"/>
  <pb_type blif_model=".subckt DSP_COMBINATIONAL" name="comb" num_pb="1">
    <input name="a" num_pins="2"/>
    <input name="b" num_pins="2"/>
    <input name="m" num_pins="1"/>
    <output name="out" num_pins="4"/>
    <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
    <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
    <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="dffs_gen_q_a_ff_0" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="dffs_gen_q_a_ff_1" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="dffs_gen_q_b_ff_0" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt DFF" name="dffs_gen_q_b_ff_1" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <interconnect>
    <direct input="comb.out[0]" name="DSP_PARTIAL_REGISTERED-out[0]" output="DSP_PARTIAL_REGISTERED.out[0]"/>
    <direct input="comb.out[1]" name="DSP_PARTIAL_REGISTERED-out[1]" output="DSP_PARTIAL_REGISTERED.out[1]"/>
    <direct input="comb.out[2]" name="DSP_PARTIAL_REGISTERED-out[2]" output="DSP_PARTIAL_REGISTERED.out[2]"/>
    <direct input="comb.out[3]" name="DSP_PARTIAL_REGISTERED-out[3]" output="DSP_PARTIAL_REGISTERED.out[3]"/>
    <direct input="dffs_gen_q_a_ff_0.Q" name="comb-a[0]" output="comb.a[0]">
      <pack_pattern in_port="dffs_gen_q_a_ff_0.Q" name="pack-DFF-DSP" out_port="comb.a[0]"/>
    </direct>
    <direct input="dffs_gen_q_a_ff_1.Q" name="comb-a[1]" output="comb.a[1]">
      <pack_pattern in_port="dffs_gen_q_a_ff_1.Q" name="pack-DFF-DSP" out_port="comb.a[1]"/>
    </direct>
    <direct input="dffs_gen_q_b_ff_0.Q" name="comb-b[0]" output="comb.b[0]">
      <pack_pattern in_port="dffs_gen_q_b_ff_0.Q" name="pack-DFF-DSP" out_port="comb.b[0]"/>
    </direct>
    <direct input="dffs_gen_q_b_ff_1.Q" name="comb-b[1]" output="comb.b[1]">
      <pack_pattern in_port="dffs_gen_q_b_ff_1.Q" name="pack-DFF-DSP" out_port="comb.b[1]"/>
    </direct>
    <direct input="DSP_PARTIAL_REGISTERED.m" name="comb-m" output="comb.m"/>
    <direct input="DSP_PARTIAL_REGISTERED.clk" name="dffs_gen_q_a_ff_0-CLK" output="dffs_gen_q_a_ff_0.CLK"/>
    <direct input="DSP_PARTIAL_REGISTERED.a[0]" name="dffs_gen_q_a_ff_0-D" output="dffs_gen_q_a_ff_0.D"/>
    <direct input="DSP_PARTIAL_REGISTERED.clk" name="dffs_gen_q_a_ff_1-CLK" output="dffs_gen_q_a_ff_1.CLK"/>
    <direct input="DSP_PARTIAL_REGISTERED.a[1]" name="dffs_gen_q_a_ff_1-D" output="dffs_gen_q_a_ff_1.D"/>
    <direct input="DSP_PARTIAL_REGISTERED.clk" name="dffs_gen_q_b_ff_0-CLK" output="dffs_gen_q_b_ff_0.CLK"/>
    <direct input="DSP_PARTIAL_REGISTERED.b[0]" name="dffs_gen_q_b_ff_0-D" output="dffs_gen_q_b_ff_0.D"/>
    <direct input="DSP_PARTIAL_REGISTERED.clk" name="dffs_gen_q_b_ff_1-CLK" output="dffs_gen_q_b_ff_1.CLK"/>
    <direct input="DSP_PARTIAL_REGISTERED.b[1]" name="dffs_gen_q_b_ff_1-D" output="dffs_gen_q_b_ff_1.D"/>
  </interconnect>
</pb_type>
Detection of combinational connections
  • Output has combinational connection with input

  • pack_pattern defined on wire connections with pack attribute

Blackbox detection
  • Model of the leaf pb_type is generated

  • Leaf pb_type XML is generated

  • All dependency models and pb_types are included in the output files

DSP-style block with different modes

The possible modes are

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/dsp/dsp_modes/dsp_modes.sim.v

tests/dsp/dsp_modes/dsp_modes.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
`include "./dsp_combinational/dsp_combinational.sim.v"
`include "./dsp_inout_registered/dsp_inout_registered.sim.v"
`include "./dsp_in_registered/dsp_in_registered.sim.v"
`include "./dsp_out_registered/dsp_out_registered.sim.v"
`include "./dsp_partial_registered/dsp_partial_registered.sim.v"

/* DSP Block with register on both the inputs and the output */
(* MODES="REGISTERED_NONE; REGISTERED_IN; REGISTERED_OUT; REGISTERED_INOUT; REGISTERED_PARTIAL" *)
module DSP_MODES (clk, a, b, m, out);
  localparam DATA_WIDTH = 4;

  parameter MODE = "REGISTERED_INOUT";

  input wire clk;
  input wire [DATA_WIDTH/2-1:0] a;
  input wire [DATA_WIDTH/2-1:0] b;
  input wire m;
  output wire [DATA_WIDTH-1:0] out;

  /* Register modes */
  generate
    if (MODE == "REGISTERED_NONE") begin
      DSP_COMBINATIONAL dsp_int_comb (.a(a), .b(b), .m(m), .out(out));
    end if (MODE == "REGISTERED_INOUT") begin
      DSP_INOUT_REGISTERED dsp_int_regio (.clk(clk), .a(a), .b(b), .m(m), .out(out));
    end if (MODE == "REGISTERED_IN") begin
      DSP_IN_REGISTERED dsp_int_regi (.clk(clk), .a(a), .b(b), .m(m), .out(out));
    end if (MODE == "REGISTERED_OUT") begin
      DSP_OUT_REGISTERED dsp_int_rego (.clk(clk), .a(a), .b(b), .m(m), .out(out));
    end if (MODE == "REGISTERED_PARTIAL") begin
      DSP_PARTIAL_REGISTERED dsp_int_part (.clk(clk), .a(a), .b(b), .m(m), .out(out));
    end
  endgenerate
endmodule
dsp_modes.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0"?>
<models>
  <model name="DSP_COMBINATIONAL">
    <input_ports>
      <port combinational_sink_ports="out" name="a"/>
      <port combinational_sink_ports="out" name="b"/>
      <port combinational_sink_ports="out" name="m"/>
    </input_ports>
    <output_ports>
      <port name="out"/>
    </output_ports>
  </model>
  <model name="DFF">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port clock="CLK" name="D"/>
    </input_ports>
    <output_ports>
      <port clock="CLK" name="Q"/>
    </output_ports>
  </model>
</models>
dsp_modes.pb_type.xml
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="DSP_MODES" num_pb="1">
  <clock name="clk" num_pins="1"/>
  <input name="a" num_pins="2"/>
  <input name="b" num_pins="2"/>
  <input name="m" num_pins="1"/>
  <output name="out" num_pins="4"/>
  <mode name="REGISTERED_NONE">
    <pb_type name="REGISTERED_NONE" num_pb="1">
      <clock name="clk" num_pins="1"/>
      <input name="a" num_pins="2"/>
      <input name="b" num_pins="2"/>
      <input name="m" num_pins="1"/>
      <output name="out" num_pins="4"/>
      <pb_type blif_model=".subckt DSP_COMBINATIONAL" name="dsp_int_comb" num_pb="1">
        <input name="a" num_pins="2"/>
        <input name="b" num_pins="2"/>
        <input name="m" num_pins="1"/>
        <output name="out" num_pins="4"/>
        <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
        <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
        <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
      </pb_type>
      <interconnect>
        <direct input="dsp_int_comb.out[0]" name="REGISTERED_NONE-out[0]" output="REGISTERED_NONE.out[0]"/>
        <direct input="dsp_int_comb.out[1]" name="REGISTERED_NONE-out[1]" output="REGISTERED_NONE.out[1]"/>
        <direct input="dsp_int_comb.out[2]" name="REGISTERED_NONE-out[2]" output="REGISTERED_NONE.out[2]"/>
        <direct input="dsp_int_comb.out[3]" name="REGISTERED_NONE-out[3]" output="REGISTERED_NONE.out[3]"/>
        <direct input="REGISTERED_NONE.a[0]" name="dsp_int_comb-a[0]" output="dsp_int_comb.a[0]"/>
        <direct input="REGISTERED_NONE.a[1]" name="dsp_int_comb-a[1]" output="dsp_int_comb.a[1]"/>
        <direct input="REGISTERED_NONE.b[0]" name="dsp_int_comb-b[0]" output="dsp_int_comb.b[0]"/>
        <direct input="REGISTERED_NONE.b[1]" name="dsp_int_comb-b[1]" output="dsp_int_comb.b[1]"/>
        <direct input="REGISTERED_NONE.m" name="dsp_int_comb-m" output="dsp_int_comb.m"/>
      </interconnect>
    </pb_type>
    <interconnect>
      <direct input="REGISTERED_NONE.out" name="DSP_MODES-out" output="DSP_MODES.out"/>
      <direct input="DSP_MODES.a" name="REGISTERED_NONE-a" output="REGISTERED_NONE.a"/>
      <direct input="DSP_MODES.b" name="REGISTERED_NONE-b" output="REGISTERED_NONE.b"/>
      <direct input="DSP_MODES.clk" name="REGISTERED_NONE-clk" output="REGISTERED_NONE.clk"/>
      <direct input="DSP_MODES.m" name="REGISTERED_NONE-m" output="REGISTERED_NONE.m"/>
    </interconnect>
  </mode>
  <mode name="REGISTERED_IN">
    <pb_type name="REGISTERED_IN" num_pb="1">
      <clock name="clk" num_pins="1"/>
      <input name="a" num_pins="2"/>
      <input name="b" num_pins="2"/>
      <input name="m" num_pins="1"/>
      <output name="out" num_pins="4"/>
      <pb_type name="dsp_int_regi" num_pb="1">
        <clock name="clk" num_pins="1"/>
        <input name="a" num_pins="2"/>
        <input name="b" num_pins="2"/>
        <input name="m" num_pins="1"/>
        <output name="out" num_pins="4"/>
        <pb_type blif_model=".subckt DSP_COMBINATIONAL" name="comb" num_pb="1">
          <input name="a" num_pins="2"/>
          <input name="b" num_pins="2"/>
          <input name="m" num_pins="1"/>
          <output name="out" num_pins="4"/>
          <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
          <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
          <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="m_ff" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="q_a_ff" num_pb="2">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="q_b_ff" num_pb="2">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <interconnect>
          <direct input="comb.out[0]" name="DSP_IN_REGISTERED-out[0]" output="DSP_IN_REGISTERED.out[0]"/>
          <direct input="comb.out[1]" name="DSP_IN_REGISTERED-out[1]" output="DSP_IN_REGISTERED.out[1]"/>
          <direct input="comb.out[2]" name="DSP_IN_REGISTERED-out[2]" output="DSP_IN_REGISTERED.out[2]"/>
          <direct input="comb.out[3]" name="DSP_IN_REGISTERED-out[3]" output="DSP_IN_REGISTERED.out[3]"/>
          <direct input="q_a_ff[0].Q" name="comb-a[0]" output="comb.a[0]">
            <pack_pattern in_port="q_a_ff[0].Q" name="pack-DFF2DSP" out_port="comb.a[0]"/>
          </direct>
          <direct input="q_a_ff[1].Q" name="comb-a[1]" output="comb.a[1]">
            <pack_pattern in_port="q_a_ff[1].Q" name="pack-DFF2DSP" out_port="comb.a[1]"/>
          </direct>
          <direct input="q_b_ff[0].Q" name="comb-b[0]" output="comb.b[0]">
            <pack_pattern in_port="q_b_ff[0].Q" name="pack-DFF2DSP" out_port="comb.b[0]"/>
          </direct>
          <direct input="q_b_ff[1].Q" name="comb-b[1]" output="comb.b[1]">
            <pack_pattern in_port="q_b_ff[1].Q" name="pack-DFF2DSP" out_port="comb.b[1]"/>
          </direct>
          <direct input="m_ff.Q" name="comb-m" output="comb.m">
            <pack_pattern in_port="m_ff.Q" name="pack-DFF2DSP" out_port="comb.m"/>
          </direct>
          <direct input="DSP_IN_REGISTERED.clk" name="m_ff-CLK" output="m_ff.CLK"/>
          <direct input="DSP_IN_REGISTERED.m" name="m_ff-D" output="m_ff.D"/>
          <direct input="DSP_IN_REGISTERED.clk" name="q_a_ff[0]-CLK" output="q_a_ff[0].CLK"/>
          <direct input="DSP_IN_REGISTERED.a[0]" name="q_a_ff[0]-D" output="q_a_ff[0].D"/>
          <direct input="DSP_IN_REGISTERED.clk" name="q_a_ff[1]-CLK" output="q_a_ff[1].CLK"/>
          <direct input="DSP_IN_REGISTERED.a[1]" name="q_a_ff[1]-D" output="q_a_ff[1].D"/>
          <direct input="DSP_IN_REGISTERED.clk" name="q_b_ff[0]-CLK" output="q_b_ff[0].CLK"/>
          <direct input="DSP_IN_REGISTERED.b[0]" name="q_b_ff[0]-D" output="q_b_ff[0].D"/>
          <direct input="DSP_IN_REGISTERED.clk" name="q_b_ff[1]-CLK" output="q_b_ff[1].CLK"/>
          <direct input="DSP_IN_REGISTERED.b[1]" name="q_b_ff[1]-D" output="q_b_ff[1].D"/>
        </interconnect>
      </pb_type>
      <interconnect>
        <direct input="dsp_int_regi.out[0]" name="REGISTERED_IN-out[0]" output="REGISTERED_IN.out[0]"/>
        <direct input="dsp_int_regi.out[1]" name="REGISTERED_IN-out[1]" output="REGISTERED_IN.out[1]"/>
        <direct input="dsp_int_regi.out[2]" name="REGISTERED_IN-out[2]" output="REGISTERED_IN.out[2]"/>
        <direct input="dsp_int_regi.out[3]" name="REGISTERED_IN-out[3]" output="REGISTERED_IN.out[3]"/>
        <direct input="REGISTERED_IN.a[0]" name="dsp_int_regi-a[0]" output="dsp_int_regi.a[0]"/>
        <direct input="REGISTERED_IN.a[1]" name="dsp_int_regi-a[1]" output="dsp_int_regi.a[1]"/>
        <direct input="REGISTERED_IN.b[0]" name="dsp_int_regi-b[0]" output="dsp_int_regi.b[0]"/>
        <direct input="REGISTERED_IN.b[1]" name="dsp_int_regi-b[1]" output="dsp_int_regi.b[1]"/>
        <direct input="REGISTERED_IN.clk" name="dsp_int_regi-clk" output="dsp_int_regi.clk"/>
        <direct input="REGISTERED_IN.m" name="dsp_int_regi-m" output="dsp_int_regi.m"/>
      </interconnect>
    </pb_type>
    <interconnect>
      <direct input="REGISTERED_IN.out" name="DSP_MODES-out" output="DSP_MODES.out"/>
      <direct input="DSP_MODES.a" name="REGISTERED_IN-a" output="REGISTERED_IN.a"/>
      <direct input="DSP_MODES.b" name="REGISTERED_IN-b" output="REGISTERED_IN.b"/>
      <direct input="DSP_MODES.clk" name="REGISTERED_IN-clk" output="REGISTERED_IN.clk"/>
      <direct input="DSP_MODES.m" name="REGISTERED_IN-m" output="REGISTERED_IN.m"/>
    </interconnect>
  </mode>
  <mode name="REGISTERED_OUT">
    <pb_type name="REGISTERED_OUT" num_pb="1">
      <clock name="clk" num_pins="1"/>
      <input name="a" num_pins="2"/>
      <input name="b" num_pins="2"/>
      <input name="m" num_pins="1"/>
      <output name="out" num_pins="4"/>
      <pb_type name="dsp_int_rego" num_pb="1">
        <clock name="clk" num_pins="1"/>
        <input name="a" num_pins="2"/>
        <input name="b" num_pins="2"/>
        <input name="m" num_pins="1"/>
        <output name="out" num_pins="4"/>
        <pb_type blif_model=".subckt DSP_COMBINATIONAL" name="comb" num_pb="1">
          <input name="a" num_pins="2"/>
          <input name="b" num_pins="2"/>
          <input name="m" num_pins="1"/>
          <output name="out" num_pins="4"/>
          <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
          <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
          <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_0" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_1" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_2" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_3" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <interconnect>
          <direct input="output_dffs_gen_q_out_ff_0.Q" name="DSP_OUT_REGISTERED-out[0]" output="DSP_OUT_REGISTERED.out[0]"/>
          <direct input="output_dffs_gen_q_out_ff_1.Q" name="DSP_OUT_REGISTERED-out[1]" output="DSP_OUT_REGISTERED.out[1]"/>
          <direct input="output_dffs_gen_q_out_ff_2.Q" name="DSP_OUT_REGISTERED-out[2]" output="DSP_OUT_REGISTERED.out[2]"/>
          <direct input="output_dffs_gen_q_out_ff_3.Q" name="DSP_OUT_REGISTERED-out[3]" output="DSP_OUT_REGISTERED.out[3]"/>
          <direct input="DSP_OUT_REGISTERED.a[0]" name="comb-a[0]" output="comb.a[0]"/>
          <direct input="DSP_OUT_REGISTERED.a[1]" name="comb-a[1]" output="comb.a[1]"/>
          <direct input="DSP_OUT_REGISTERED.b[0]" name="comb-b[0]" output="comb.b[0]"/>
          <direct input="DSP_OUT_REGISTERED.b[1]" name="comb-b[1]" output="comb.b[1]"/>
          <direct input="DSP_OUT_REGISTERED.m" name="comb-m" output="comb.m"/>
          <direct input="DSP_OUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_0-CLK" output="output_dffs_gen_q_out_ff_0.CLK"/>
          <direct input="comb.out[0]" name="output_dffs_gen_q_out_ff_0-D" output="output_dffs_gen_q_out_ff_0.D">
            <pack_pattern in_port="comb.out[0]" name="pack-DSP-DFF" out_port="output_dffs_gen_q_out_ff_0.D"/>
          </direct>
          <direct input="DSP_OUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_1-CLK" output="output_dffs_gen_q_out_ff_1.CLK"/>
          <direct input="comb.out[1]" name="output_dffs_gen_q_out_ff_1-D" output="output_dffs_gen_q_out_ff_1.D">
            <pack_pattern in_port="comb.out[1]" name="pack-DSP-DFF" out_port="output_dffs_gen_q_out_ff_1.D"/>
          </direct>
          <direct input="DSP_OUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_2-CLK" output="output_dffs_gen_q_out_ff_2.CLK"/>
          <direct input="comb.out[2]" name="output_dffs_gen_q_out_ff_2-D" output="output_dffs_gen_q_out_ff_2.D">
            <pack_pattern in_port="comb.out[2]" name="pack-DSP-DFF" out_port="output_dffs_gen_q_out_ff_2.D"/>
          </direct>
          <direct input="DSP_OUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_3-CLK" output="output_dffs_gen_q_out_ff_3.CLK"/>
          <direct input="comb.out[3]" name="output_dffs_gen_q_out_ff_3-D" output="output_dffs_gen_q_out_ff_3.D">
            <pack_pattern in_port="comb.out[3]" name="pack-DSP-DFF" out_port="output_dffs_gen_q_out_ff_3.D"/>
          </direct>
        </interconnect>
      </pb_type>
      <interconnect>
        <direct input="dsp_int_rego.out[0]" name="REGISTERED_OUT-out[0]" output="REGISTERED_OUT.out[0]"/>
        <direct input="dsp_int_rego.out[1]" name="REGISTERED_OUT-out[1]" output="REGISTERED_OUT.out[1]"/>
        <direct input="dsp_int_rego.out[2]" name="REGISTERED_OUT-out[2]" output="REGISTERED_OUT.out[2]"/>
        <direct input="dsp_int_rego.out[3]" name="REGISTERED_OUT-out[3]" output="REGISTERED_OUT.out[3]"/>
        <direct input="REGISTERED_OUT.a[0]" name="dsp_int_rego-a[0]" output="dsp_int_rego.a[0]"/>
        <direct input="REGISTERED_OUT.a[1]" name="dsp_int_rego-a[1]" output="dsp_int_rego.a[1]"/>
        <direct input="REGISTERED_OUT.b[0]" name="dsp_int_rego-b[0]" output="dsp_int_rego.b[0]"/>
        <direct input="REGISTERED_OUT.b[1]" name="dsp_int_rego-b[1]" output="dsp_int_rego.b[1]"/>
        <direct input="REGISTERED_OUT.clk" name="dsp_int_rego-clk" output="dsp_int_rego.clk"/>
        <direct input="REGISTERED_OUT.m" name="dsp_int_rego-m" output="dsp_int_rego.m"/>
      </interconnect>
    </pb_type>
    <interconnect>
      <direct input="REGISTERED_OUT.out" name="DSP_MODES-out" output="DSP_MODES.out"/>
      <direct input="DSP_MODES.a" name="REGISTERED_OUT-a" output="REGISTERED_OUT.a"/>
      <direct input="DSP_MODES.b" name="REGISTERED_OUT-b" output="REGISTERED_OUT.b"/>
      <direct input="DSP_MODES.clk" name="REGISTERED_OUT-clk" output="REGISTERED_OUT.clk"/>
      <direct input="DSP_MODES.m" name="REGISTERED_OUT-m" output="REGISTERED_OUT.m"/>
    </interconnect>
  </mode>
  <mode name="REGISTERED_INOUT">
    <pb_type name="REGISTERED_INOUT" num_pb="1">
      <clock name="clk" num_pins="1"/>
      <input name="a" num_pins="2"/>
      <input name="b" num_pins="2"/>
      <input name="m" num_pins="1"/>
      <output name="out" num_pins="4"/>
      <pb_type name="dsp_int_regio" num_pb="1">
        <clock name="clk" num_pins="1"/>
        <input name="a" num_pins="2"/>
        <input name="b" num_pins="2"/>
        <input name="m" num_pins="1"/>
        <output name="out" num_pins="4"/>
        <pb_type blif_model=".subckt DSP_COMBINATIONAL" name="comb" num_pb="1">
          <input name="a" num_pins="2"/>
          <input name="b" num_pins="2"/>
          <input name="m" num_pins="1"/>
          <output name="out" num_pins="4"/>
          <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
          <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
          <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_a_ff_0" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_a_ff_1" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_b_ff_0" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="input_dffs_gen_q_b_ff_1" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="m_ff" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_0" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_1" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_2" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="output_dffs_gen_q_out_ff_3" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <interconnect>
          <direct input="output_dffs_gen_q_out_ff_0.Q" name="DSP_INOUT_REGISTERED-out[0]" output="DSP_INOUT_REGISTERED.out[0]"/>
          <direct input="output_dffs_gen_q_out_ff_1.Q" name="DSP_INOUT_REGISTERED-out[1]" output="DSP_INOUT_REGISTERED.out[1]"/>
          <direct input="output_dffs_gen_q_out_ff_2.Q" name="DSP_INOUT_REGISTERED-out[2]" output="DSP_INOUT_REGISTERED.out[2]"/>
          <direct input="output_dffs_gen_q_out_ff_3.Q" name="DSP_INOUT_REGISTERED-out[3]" output="DSP_INOUT_REGISTERED.out[3]"/>
          <direct input="input_dffs_gen_q_a_ff_0.Q" name="comb-a[0]" output="comb.a[0]">
            <pack_pattern in_port="input_dffs_gen_q_a_ff_0.Q" name="pack-DFF-DSP" out_port="comb.a[0]"/>
          </direct>
          <direct input="input_dffs_gen_q_a_ff_1.Q" name="comb-a[1]" output="comb.a[1]">
            <pack_pattern in_port="input_dffs_gen_q_a_ff_1.Q" name="pack-DFF-DSP" out_port="comb.a[1]"/>
          </direct>
          <direct input="input_dffs_gen_q_b_ff_0.Q" name="comb-b[0]" output="comb.b[0]">
            <pack_pattern in_port="input_dffs_gen_q_b_ff_0.Q" name="pack-DFF-DSP" out_port="comb.b[0]"/>
          </direct>
          <direct input="input_dffs_gen_q_b_ff_1.Q" name="comb-b[1]" output="comb.b[1]">
            <pack_pattern in_port="input_dffs_gen_q_b_ff_1.Q" name="pack-DFF-DSP" out_port="comb.b[1]"/>
          </direct>
          <direct input="m_ff.Q" name="comb-m" output="comb.m">
            <pack_pattern in_port="m_ff.Q" name="pack-DFF-DSP" out_port="comb.m"/>
          </direct>
          <direct input="DSP_INOUT_REGISTERED.clk" name="input_dffs_gen_q_a_ff_0-CLK" output="input_dffs_gen_q_a_ff_0.CLK"/>
          <direct input="DSP_INOUT_REGISTERED.a[0]" name="input_dffs_gen_q_a_ff_0-D" output="input_dffs_gen_q_a_ff_0.D"/>
          <direct input="DSP_INOUT_REGISTERED.clk" name="input_dffs_gen_q_a_ff_1-CLK" output="input_dffs_gen_q_a_ff_1.CLK"/>
          <direct input="DSP_INOUT_REGISTERED.a[1]" name="input_dffs_gen_q_a_ff_1-D" output="input_dffs_gen_q_a_ff_1.D"/>
          <direct input="DSP_INOUT_REGISTERED.clk" name="input_dffs_gen_q_b_ff_0-CLK" output="input_dffs_gen_q_b_ff_0.CLK"/>
          <direct input="DSP_INOUT_REGISTERED.b[0]" name="input_dffs_gen_q_b_ff_0-D" output="input_dffs_gen_q_b_ff_0.D"/>
          <direct input="DSP_INOUT_REGISTERED.clk" name="input_dffs_gen_q_b_ff_1-CLK" output="input_dffs_gen_q_b_ff_1.CLK"/>
          <direct input="DSP_INOUT_REGISTERED.b[1]" name="input_dffs_gen_q_b_ff_1-D" output="input_dffs_gen_q_b_ff_1.D"/>
          <direct input="DSP_INOUT_REGISTERED.clk" name="m_ff-CLK" output="m_ff.CLK"/>
          <direct input="DSP_INOUT_REGISTERED.m" name="m_ff-D" output="m_ff.D"/>
          <direct input="DSP_INOUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_0-CLK" output="output_dffs_gen_q_out_ff_0.CLK"/>
          <direct input="comb.out[0]" name="output_dffs_gen_q_out_ff_0-D" output="output_dffs_gen_q_out_ff_0.D">
            <pack_pattern in_port="comb.out[0]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_0.D"/>
          </direct>
          <direct input="DSP_INOUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_1-CLK" output="output_dffs_gen_q_out_ff_1.CLK"/>
          <direct input="comb.out[1]" name="output_dffs_gen_q_out_ff_1-D" output="output_dffs_gen_q_out_ff_1.D">
            <pack_pattern in_port="comb.out[1]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_1.D"/>
          </direct>
          <direct input="DSP_INOUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_2-CLK" output="output_dffs_gen_q_out_ff_2.CLK"/>
          <direct input="comb.out[2]" name="output_dffs_gen_q_out_ff_2-D" output="output_dffs_gen_q_out_ff_2.D">
            <pack_pattern in_port="comb.out[2]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_2.D"/>
          </direct>
          <direct input="DSP_INOUT_REGISTERED.clk" name="output_dffs_gen_q_out_ff_3-CLK" output="output_dffs_gen_q_out_ff_3.CLK"/>
          <direct input="comb.out[3]" name="output_dffs_gen_q_out_ff_3-D" output="output_dffs_gen_q_out_ff_3.D">
            <pack_pattern in_port="comb.out[3]" name="pack-DFF-DSP" out_port="output_dffs_gen_q_out_ff_3.D"/>
          </direct>
        </interconnect>
      </pb_type>
      <interconnect>
        <direct input="dsp_int_regio.out[0]" name="REGISTERED_INOUT-out[0]" output="REGISTERED_INOUT.out[0]"/>
        <direct input="dsp_int_regio.out[1]" name="REGISTERED_INOUT-out[1]" output="REGISTERED_INOUT.out[1]"/>
        <direct input="dsp_int_regio.out[2]" name="REGISTERED_INOUT-out[2]" output="REGISTERED_INOUT.out[2]"/>
        <direct input="dsp_int_regio.out[3]" name="REGISTERED_INOUT-out[3]" output="REGISTERED_INOUT.out[3]"/>
        <direct input="REGISTERED_INOUT.a[0]" name="dsp_int_regio-a[0]" output="dsp_int_regio.a[0]"/>
        <direct input="REGISTERED_INOUT.a[1]" name="dsp_int_regio-a[1]" output="dsp_int_regio.a[1]"/>
        <direct input="REGISTERED_INOUT.b[0]" name="dsp_int_regio-b[0]" output="dsp_int_regio.b[0]"/>
        <direct input="REGISTERED_INOUT.b[1]" name="dsp_int_regio-b[1]" output="dsp_int_regio.b[1]"/>
        <direct input="REGISTERED_INOUT.clk" name="dsp_int_regio-clk" output="dsp_int_regio.clk"/>
        <direct input="REGISTERED_INOUT.m" name="dsp_int_regio-m" output="dsp_int_regio.m"/>
      </interconnect>
    </pb_type>
    <interconnect>
      <direct input="REGISTERED_INOUT.out" name="DSP_MODES-out" output="DSP_MODES.out"/>
      <direct input="DSP_MODES.a" name="REGISTERED_INOUT-a" output="REGISTERED_INOUT.a"/>
      <direct input="DSP_MODES.b" name="REGISTERED_INOUT-b" output="REGISTERED_INOUT.b"/>
      <direct input="DSP_MODES.clk" name="REGISTERED_INOUT-clk" output="REGISTERED_INOUT.clk"/>
      <direct input="DSP_MODES.m" name="REGISTERED_INOUT-m" output="REGISTERED_INOUT.m"/>
    </interconnect>
  </mode>
  <mode name="REGISTERED_PARTIAL">
    <pb_type name="REGISTERED_PARTIAL" num_pb="1">
      <clock name="clk" num_pins="1"/>
      <input name="a" num_pins="2"/>
      <input name="b" num_pins="2"/>
      <input name="m" num_pins="1"/>
      <output name="out" num_pins="4"/>
      <pb_type name="dsp_int_part" num_pb="1">
        <clock name="clk" num_pins="1"/>
        <input name="a" num_pins="2"/>
        <input name="b" num_pins="2"/>
        <input name="m" num_pins="1"/>
        <output name="out" num_pins="4"/>
        <pb_type blif_model=".subckt DSP_COMBINATIONAL" name="comb" num_pb="1">
          <input name="a" num_pins="2"/>
          <input name="b" num_pins="2"/>
          <input name="m" num_pins="1"/>
          <output name="out" num_pins="4"/>
          <delay_constant in_port="DSP_COMBINATIONAL.a" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
          <delay_constant in_port="DSP_COMBINATIONAL.b" max="30e-12" out_port="DSP_COMBINATIONAL.out"/>
          <delay_constant in_port="DSP_COMBINATIONAL.m" max="10e-12" out_port="DSP_COMBINATIONAL.out"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="dffs_gen_q_a_ff_0" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="dffs_gen_q_a_ff_1" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="dffs_gen_q_b_ff_0" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <pb_type blif_model=".subckt DFF" name="dffs_gen_q_b_ff_1" num_pb="1">
          <clock name="CLK" num_pins="1"/>
          <input name="D" num_pins="1"/>
          <output name="Q" num_pins="1"/>
          <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
          <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
          <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
        </pb_type>
        <interconnect>
          <direct input="comb.out[0]" name="DSP_PARTIAL_REGISTERED-out[0]" output="DSP_PARTIAL_REGISTERED.out[0]"/>
          <direct input="comb.out[1]" name="DSP_PARTIAL_REGISTERED-out[1]" output="DSP_PARTIAL_REGISTERED.out[1]"/>
          <direct input="comb.out[2]" name="DSP_PARTIAL_REGISTERED-out[2]" output="DSP_PARTIAL_REGISTERED.out[2]"/>
          <direct input="comb.out[3]" name="DSP_PARTIAL_REGISTERED-out[3]" output="DSP_PARTIAL_REGISTERED.out[3]"/>
          <direct input="dffs_gen_q_a_ff_0.Q" name="comb-a[0]" output="comb.a[0]">
            <pack_pattern in_port="dffs_gen_q_a_ff_0.Q" name="pack-DFF-DSP" out_port="comb.a[0]"/>
          </direct>
          <direct input="dffs_gen_q_a_ff_1.Q" name="comb-a[1]" output="comb.a[1]">
            <pack_pattern in_port="dffs_gen_q_a_ff_1.Q" name="pack-DFF-DSP" out_port="comb.a[1]"/>
          </direct>
          <direct input="dffs_gen_q_b_ff_0.Q" name="comb-b[0]" output="comb.b[0]">
            <pack_pattern in_port="dffs_gen_q_b_ff_0.Q" name="pack-DFF-DSP" out_port="comb.b[0]"/>
          </direct>
          <direct input="dffs_gen_q_b_ff_1.Q" name="comb-b[1]" output="comb.b[1]">
            <pack_pattern in_port="dffs_gen_q_b_ff_1.Q" name="pack-DFF-DSP" out_port="comb.b[1]"/>
          </direct>
          <direct input="DSP_PARTIAL_REGISTERED.m" name="comb-m" output="comb.m"/>
          <direct input="DSP_PARTIAL_REGISTERED.clk" name="dffs_gen_q_a_ff_0-CLK" output="dffs_gen_q_a_ff_0.CLK"/>
          <direct input="DSP_PARTIAL_REGISTERED.a[0]" name="dffs_gen_q_a_ff_0-D" output="dffs_gen_q_a_ff_0.D"/>
          <direct input="DSP_PARTIAL_REGISTERED.clk" name="dffs_gen_q_a_ff_1-CLK" output="dffs_gen_q_a_ff_1.CLK"/>
          <direct input="DSP_PARTIAL_REGISTERED.a[1]" name="dffs_gen_q_a_ff_1-D" output="dffs_gen_q_a_ff_1.D"/>
          <direct input="DSP_PARTIAL_REGISTERED.clk" name="dffs_gen_q_b_ff_0-CLK" output="dffs_gen_q_b_ff_0.CLK"/>
          <direct input="DSP_PARTIAL_REGISTERED.b[0]" name="dffs_gen_q_b_ff_0-D" output="dffs_gen_q_b_ff_0.D"/>
          <direct input="DSP_PARTIAL_REGISTERED.clk" name="dffs_gen_q_b_ff_1-CLK" output="dffs_gen_q_b_ff_1.CLK"/>
          <direct input="DSP_PARTIAL_REGISTERED.b[1]" name="dffs_gen_q_b_ff_1-D" output="dffs_gen_q_b_ff_1.D"/>
        </interconnect>
      </pb_type>
      <interconnect>
        <direct input="dsp_int_part.out[0]" name="REGISTERED_PARTIAL-out[0]" output="REGISTERED_PARTIAL.out[0]"/>
        <direct input="dsp_int_part.out[1]" name="REGISTERED_PARTIAL-out[1]" output="REGISTERED_PARTIAL.out[1]"/>
        <direct input="dsp_int_part.out[2]" name="REGISTERED_PARTIAL-out[2]" output="REGISTERED_PARTIAL.out[2]"/>
        <direct input="dsp_int_part.out[3]" name="REGISTERED_PARTIAL-out[3]" output="REGISTERED_PARTIAL.out[3]"/>
        <direct input="REGISTERED_PARTIAL.a[0]" name="dsp_int_part-a[0]" output="dsp_int_part.a[0]"/>
        <direct input="REGISTERED_PARTIAL.a[1]" name="dsp_int_part-a[1]" output="dsp_int_part.a[1]"/>
        <direct input="REGISTERED_PARTIAL.b[0]" name="dsp_int_part-b[0]" output="dsp_int_part.b[0]"/>
        <direct input="REGISTERED_PARTIAL.b[1]" name="dsp_int_part-b[1]" output="dsp_int_part.b[1]"/>
        <direct input="REGISTERED_PARTIAL.clk" name="dsp_int_part-clk" output="dsp_int_part.clk"/>
        <direct input="REGISTERED_PARTIAL.m" name="dsp_int_part-m" output="dsp_int_part.m"/>
      </interconnect>
    </pb_type>
    <interconnect>
      <direct input="REGISTERED_PARTIAL.out" name="DSP_MODES-out" output="DSP_MODES.out"/>
      <direct input="DSP_MODES.a" name="REGISTERED_PARTIAL-a" output="REGISTERED_PARTIAL.a"/>
      <direct input="DSP_MODES.b" name="REGISTERED_PARTIAL-b" output="REGISTERED_PARTIAL.b"/>
      <direct input="DSP_MODES.clk" name="REGISTERED_PARTIAL-clk" output="REGISTERED_PARTIAL.clk"/>
      <direct input="DSP_MODES.m" name="REGISTERED_PARTIAL-m" output="REGISTERED_PARTIAL.m"/>
    </interconnect>
  </mode>
</pb_type>
Blackbox detection
  • Model of the leaf pb_type is generated

  • Leaf pb_type XML is generated

  • All dependency models and pb_types are included in the output files

Modes generation
  • All the modes from list defined with MODES attribute

  • Mode setting is included in pb_type generation (correct part of logic is used)

  • Modes connections are generated correctly

Basic logic gates

These are some basic logic gates. NOT, AND and NOR are modeled as primitives while XOR is made up of 5 NOR gates.

NOT gate

This is an NOT gate

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/gates/not/not.sim.v

not.sim.v
19
20
21
22
23
24
25
26
module NOT (
    input  A,
    output Y
);

    assign Y = ~A;

endmodule

The gate model generated by V2X

not.model.xml
<?xml version="1.0"?>
<models>
  <model name="NOT">
    <input_ports>
      <port combinational_sink_ports="Y" name="A"/>
    </input_ports>
    <output_ports>
      <port name="Y"/>
    </output_ports>
  </model>
</models>

The gate pb_type generated by V2X

not.pb_type.xml
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" blif_model=".subckt NOT" name="NOT" num_pb="1">
  <input name="A" num_pins="1"/>
  <output name="Y" num_pins="1"/>
</pb_type>
AND gate

This is an AND gate

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/gates/and/and.sim.v

and.sim.v
19
20
21
22
23
24
25
26
27
module AND (
    input  A,
    input  B,
    output Y
);

    assign Y = A & B;

endmodule

The gate model generated by V2X

and.model.xml
<?xml version="1.0"?>
<models>
  <model name="AND">
    <input_ports>
      <port combinational_sink_ports="Y" name="A"/>
      <port combinational_sink_ports="Y" name="B"/>
    </input_ports>
    <output_ports>
      <port name="Y"/>
    </output_ports>
  </model>
</models>

The gate pb_type generated by V2X

and.pb_type.xml
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" blif_model=".subckt AND" name="AND" num_pb="1">
  <input name="A" num_pins="1"/>
  <input name="B" num_pins="1"/>
  <output name="Y" num_pins="1"/>
</pb_type>
NOR gate

This is an NOR gate

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/gates/nor/nor.sim.v

nor.sim.v
19
20
21
22
23
24
25
26
27
module NOR (
    input  A,
    input  B,
    output Y
);

    assign Y = ~(A | B);

endmodule

The gate model generated by V2X

nor.model.xml
<?xml version="1.0"?>
<models>
  <model name="NOR">
    <input_ports>
      <port combinational_sink_ports="Y" name="A"/>
      <port combinational_sink_ports="Y" name="B"/>
    </input_ports>
    <output_ports>
      <port name="Y"/>
    </output_ports>
  </model>
</models>

The gate pb_type generated by V2X

nor.pb_type.xml
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" blif_model=".subckt NOR" name="NOR" num_pb="1">
  <input name="A" num_pins="1"/>
  <input name="B" num_pins="1"/>
  <output name="Y" num_pins="1"/>
</pb_type>
XOR gate

This is a XOR gate made of NOR gates

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/gates/xor/xor.sim.v

xor.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
`include "./nor/nor.sim.v"

module XOR (
    input  A,
    input  B,
    output Y
);

    wire S00;
    NOR nor00 (.A(A), .B(B), .Y(S00));

    wire S10;
    wire S11;
    NOR nor10 (.A(A), .B(S00), .Y(S10));
    NOR nor11 (.A(B), .B(S00), .Y(S11));

    wire S20;
    NOR nor20 (.A(S10), .B(S11), .Y(S20));

    NOR nor30 (.A(S20), .B(S20), .Y(Y));

endmodule

The gate model generated by V2X

xor.model.xml
<?xml version="1.0"?>
<models>
  <model name="NOR">
    <input_ports>
      <port combinational_sink_ports="Y" name="A"/>
      <port combinational_sink_ports="Y" name="B"/>
    </input_ports>
    <output_ports>
      <port name="Y"/>
    </output_ports>
  </model>
</models>

The gate pb_type generated by V2X

xor.pb_type.xml
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="XOR" num_pb="1">
  <input name="A" num_pins="1"/>
  <input name="B" num_pins="1"/>
  <output name="Y" num_pins="1"/>
  <pb_type blif_model=".subckt NOR" name="nor00" num_pb="1">
    <input name="A" num_pins="1"/>
    <input name="B" num_pins="1"/>
    <output name="Y" num_pins="1"/>
  </pb_type>
  <pb_type blif_model=".subckt NOR" name="nor10" num_pb="1">
    <input name="A" num_pins="1"/>
    <input name="B" num_pins="1"/>
    <output name="Y" num_pins="1"/>
  </pb_type>
  <pb_type blif_model=".subckt NOR" name="nor11" num_pb="1">
    <input name="A" num_pins="1"/>
    <input name="B" num_pins="1"/>
    <output name="Y" num_pins="1"/>
  </pb_type>
  <pb_type blif_model=".subckt NOR" name="nor20" num_pb="1">
    <input name="A" num_pins="1"/>
    <input name="B" num_pins="1"/>
    <output name="Y" num_pins="1"/>
  </pb_type>
  <pb_type blif_model=".subckt NOR" name="nor30" num_pb="1">
    <input name="A" num_pins="1"/>
    <input name="B" num_pins="1"/>
    <output name="Y" num_pins="1"/>
  </pb_type>
  <interconnect>
    <direct input="nor30.Y" name="XOR-Y" output="XOR.Y"/>
    <direct input="XOR.A" name="nor00-A" output="nor00.A"/>
    <direct input="XOR.B" name="nor00-B" output="nor00.B"/>
    <direct input="XOR.A" name="nor10-A" output="nor10.A"/>
    <direct input="nor00.Y" name="nor10-B" output="nor10.B"/>
    <direct input="XOR.B" name="nor11-A" output="nor11.A"/>
    <direct input="nor00.Y" name="nor11-B" output="nor11.B"/>
    <direct input="nor10.Y" name="nor20-A" output="nor20.A"/>
    <direct input="nor11.Y" name="nor20-B" output="nor20.B"/>
    <direct input="nor20.Y" name="nor30-A" output="nor30.A"/>
    <direct input="nor20.Y" name="nor30-B" output="nor30.B"/>
  </interconnect>
</pb_type>

Forced non-sequential relations to an input

This is a case when a macro block consisting of a LUT and an FF is to be modeled in VPR as a single primitive. The block has two outputs: the first one sources at the LUT directly and the second one passes through an external register:

_images/lut_ff_macro.svg
tests/no_seq/lut_ff_macro.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
(* whitebox *)
module LUT_FF_MACRO (I0, I1, I2, I3, CLK, Z, QZ);

    // LUT inputs
    (* NO_SEQ *)
    input  wire  I0;
    (* NO_SEQ *)
    input  wire  I1;
    (* NO_SEQ *)
    input  wire  I2;
    (* NO_SEQ *)
    input  wire  I3;

    // Clock input
    input  wire  CLK;

    // Combinational LUT output
    (* DELAY_CONST_I0="1e-10" *)
    (* DELAY_CONST_I1="1e-10" *)
    (* DELAY_CONST_I2="1e-10" *)
    (* DELAY_CONST_I3="1e-10" *)
    output wire  Z;

    // Registered LUT output
    (* DELAY_CONST_I0="2e-10" *)
    (* DELAY_CONST_I1="2e-10" *)
    (* DELAY_CONST_I2="2e-10" *)
    (* DELAY_CONST_I3="2e-10" *)
    (* CLK_TO_Q="CLK 1e-10" *)
    (* SETUP="CLK 1e-10" *)
    (* HOLD="CLK 1e-10" *)
    output reg   QZ;

    // LUT behavioral model
    parameter [15:0] INIT = 16'd0;
    assign Z = INIT[{I3, I2, I1, I0}];

    // FF behavioral model    
    always @(posedge CLK)
        QZ <= Z;

endmodule

Since relation of LUT inputs is combinational for one output and sequential for another they have to be defined in a special way as required by VPR (see VTR documentation). Due to the presence of the output register all sequential annotations are moved to the output port. Hence LUT inputs must not mention any clock signal. This can be achieved in V2X by specifying the (* NO_SEQ *) attribute on them. The attribute prevents V2X from annotating input ports with any clock relations.

lut_ff_macro.model.xml
<?xml version="1.0"?>
<models>
  <model name="LUT_FF_MACRO">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port combinational_sink_ports="QZ Z" name="I0"/>
      <port combinational_sink_ports="QZ Z" name="I1"/>
      <port combinational_sink_ports="QZ Z" name="I2"/>
      <port combinational_sink_ports="QZ Z" name="I3"/>
    </input_ports>
    <output_ports>
      <port clock="CLK" name="QZ"/>
      <port name="Z"/>
    </output_ports>
  </model>
</models>
lut_ff_macro.pb_type.xml
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" blif_model=".subckt LUT_FF_MACRO" name="LUT_FF_MACRO" num_pb="1">
  <clock name="CLK" num_pins="1"/>
  <input name="I0" num_pins="1"/>
  <input name="I1" num_pins="1"/>
  <input name="I2" num_pins="1"/>
  <input name="I3" num_pins="1"/>
  <output name="QZ" num_pins="1"/>
  <output name="Z" num_pins="1"/>
  <delay_constant in_port="LUT_FF_MACRO.I0" max="2e-10" out_port="LUT_FF_MACRO.QZ"/>
  <delay_constant in_port="LUT_FF_MACRO.I1" max="2e-10" out_port="LUT_FF_MACRO.QZ"/>
  <delay_constant in_port="LUT_FF_MACRO.I2" max="2e-10" out_port="LUT_FF_MACRO.QZ"/>
  <delay_constant in_port="LUT_FF_MACRO.I3" max="2e-10" out_port="LUT_FF_MACRO.QZ"/>
  <delay_constant in_port="LUT_FF_MACRO.I0" max="1e-10" out_port="LUT_FF_MACRO.Z"/>
  <delay_constant in_port="LUT_FF_MACRO.I1" max="1e-10" out_port="LUT_FF_MACRO.Z"/>
  <delay_constant in_port="LUT_FF_MACRO.I2" max="1e-10" out_port="LUT_FF_MACRO.Z"/>
  <delay_constant in_port="LUT_FF_MACRO.I3" max="1e-10" out_port="LUT_FF_MACRO.Z"/>
  <T_setup clock="CLK" port="LUT_FF_MACRO.QZ" value="1e-10"/>
  <T_hold clock="CLK" port="LUT_FF_MACRO.QZ" value="1e-10"/>
  <T_clock_to_Q clock="CLK" max="1e-10" port="LUT_FF_MACRO.QZ"/>
</pb_type>

Pack pattern annotation

This example shows that v2x prevents annotating a top-level port of a pb_type when a net of that port is forking. This enables using pack patterns, e.g., for LUT to FF connections when the LUT output is also connected to a top-level output port.

/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/pack_pattern/pack_pattern.sim.v
pack_pattern.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
`include "./lut4/lut4.sim.v"
`include "./dff/dff.sim.v"

module PACK_PATTERN (
    CLK,
    LUT_IN,
    LUT_OUT,
    DFF_OUT
);
    input wire CLK;
    input wire [3:0] LUT_IN;

    output wire LUT_OUT;
    output wire DFF_OUT;

    (* pack *)
    wire w;

    LUT4 lut (.I(LUT_IN), .O(w));
    DFF dff (.CLK(CLK), .D(w), .Q(DFF_OUT));

    assign LUT_OUT = w;
endmodule
pack_pattern.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0"?>
<models>
  <model name="DFF">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port clock="CLK" name="D"/>
    </input_ports>
    <output_ports>
      <port clock="CLK" name="Q"/>
    </output_ports>
  </model>
  <model name="LUT4">
    <input_ports>
      <port combinational_sink_ports="O" name="I"/>
    </input_ports>
    <output_ports>
      <port name="O"/>
    </output_ports>
  </model>
</models>
pack_pattern.pb_type.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="PACK_PATTERN" num_pb="1">
  <clock name="CLK" num_pins="1"/>
  <input name="LUT_IN" num_pins="4"/>
  <output name="DFF_OUT" num_pins="1"/>
  <output name="LUT_OUT" num_pins="1"/>
  <pb_type blif_model=".subckt DFF" name="dff" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt LUT4" name="lut" num_pb="1">
    <input name="I" num_pins="4"/>
    <output name="O" num_pins="1"/>
    <delay_matrix in_port="LUT4.I" out_port="LUT4.O" type="max">
30e-12 20e-12 11e-12 3e-12
</delay_matrix>
  </pb_type>
  <interconnect>
    <direct input="dff.Q" name="PACK_PATTERN-DFF_OUT" output="PACK_PATTERN.DFF_OUT"/>
    <direct input="lut.O" name="PACK_PATTERN-LUT_OUT" output="PACK_PATTERN.LUT_OUT"/>
    <direct input="PACK_PATTERN.CLK" name="dff-CLK" output="dff.CLK"/>
    <direct input="lut.O" name="dff-D" output="dff.D">
      <pack_pattern in_port="lut.O" name="pack-00000000000000000000000000000001" out_port="dff.D"/>
    </direct>
    <direct input="PACK_PATTERN.LUT_IN[0]" name="lut-I[0]" output="lut.I[0]"/>
    <direct input="PACK_PATTERN.LUT_IN[1]" name="lut-I[1]" output="lut.I[1]"/>
    <direct input="PACK_PATTERN.LUT_IN[2]" name="lut-I[2]" output="lut.I[2]"/>
    <direct input="PACK_PATTERN.LUT_IN[3]" name="lut-I[3]" output="lut.I[3]"/>
  </interconnect>
</pb_type>

Verilog to Routing

The following shows some examples taken from the Verilog to Routing documentation.

Primitive Block Timing Modeling Tutorial

The following shows examples taken from the Primitive Block Timing Modeling Tutorial in the Verilog to Routing documentation.

Classical D-Flip-Flop test

An example of the classical D-Flip-Flop shown in Figure 60 - DFF.

Figure 60 from Verilog to Routing Documentation

Fig. 60 - DFF



dff.sim.v
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
`ifndef DFF
`define DFF

(* whitebox *)
module DFF (D, CLK, Q);

  input wire CLK;

  (* SETUP="CLK 10e-12" *)
  (* HOLD="CLK 10e-12" *)
  input wire D;

  (* CLK_TO_Q="CLK 10e-12" *)
  output reg Q;

  always @ ( posedge CLK ) begin
    Q <= D;
  end

`ifndef YOSYS
  specify
    specparam
      tplh$CLK$QP = 1.0,
      tphl$CLK$QP = 1.0,
      tplh$CLK$QN = 1.0,
      tphl$CLK$QN = 1.0,
      tsetup$D$CLK = 1.0,
      thold$D$CLK = 1.0,
      tminpwl$CLK = 1.0,
      tminpwh$CLK = 1.0;

    // PATH DELAYS
    if (flag)
      // Polarity of QP is positive referenced to D
      (posedge CLK *> (QP +: D)) = (tplh$CLK$QP, tphl$CLK$QP);
    if (flag)
      // Polarity of QN is negative referenced to D
      (posedge CLK *> (QN -: D)) = (tplh$CLK$QN, tphl$CLK$QN);

    // SETUP AND HOLD CHECKS
    $setuphold(posedge CLK &&& (flag == 1), posedge D, tsetup$D$CLK, thold$D$CLK, NOTIFIER);

    $setuphold(posedge CLK &&& (flag == 1), negedge D, tsetup$D$CLK, thold$D$CLK, NOTIFIER);

    // MINIMUM WIDTH CHECKING
    $width(negedge CLK, tminpwl$CLK, 0, NOTIFIER);
    $width(posedge CLK, tminpwh$CLK, 0, NOTIFIER);

  endspecify
`endif

endmodule

`endif
dff.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<?xml version="1.0"?>
<models>
  <model name="DFF">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port clock="CLK" name="D"/>
    </input_ports>
    <output_ports>
      <port clock="CLK" name="Q"/>
    </output_ports>
  </model>
</models>
dff.pb_type.xml
1
2
3
4
5
6
7
8
9
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" blif_model=".subckt DFF" name="DFF" num_pb="1">
  <clock name="CLK" num_pins="1"/>
  <input name="D" num_pins="1"/>
  <output name="Q" num_pins="1"/>
  <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
  <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
  <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
</pb_type>
Clock associations inference
  • Automatic inference is signal is associated with any clock and include the info in the model

  • Automatic clock detection (signals named clk are considered as clocks)

Blackbox detection
  • Model of the leaf pb_type is generated

  • Leaf pb_type XML is generated

Timings
  • All the timings defined for wires with attributes should be included in pb_type XML

Full Adder Example

An example of the classical combinational “full adder” circuit shown in Figure 60 - Full Adder of the “Combinational block” section in the Primitive Block Timing Modeling Tutorial of the Verilog to Routing documentation and reproduced below.

Figure 59 from Verilog to Routing Documentation

Fig. 59 - Full Adder


/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/vtr/full-adder/adder.sim.v

adder.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(* whitebox *)
module ADDER (
  a, b, cin,
  sum, cout
);
  input wire a;
  input wire b;
  (* carry = "ADDER" *)
  input wire cin;

  (* DELAY_CONST_a   = "300e-12" *)
  (* DELAY_CONST_b   = "300e-12" *)
  (* DELAY_CONST_cin = "300e-12" *)
  output wire sum;

  (* carry = "ADDER" *)
  (* DELAY_CONST_a   = "300e-12" *)
  (* DELAY_CONST_b   = "300e-12" *)
  (* DELAY_CONST_cin =  "10e-12" *)
  output wire cout;

  // Full adder combinational logic
  assign sum = a ^ b ^ cin;
  assign cout = ((a ^ b) & cin) | (a & b);

  // Timing parameters, not supported by Yosys at the moment.
`ifndef YOSYS
  `timescale 1ps/1ps
  specify
    specparam T1 300;
    specparam T2 10;
    // (input->output) min:typ:max

    (a => sum)  = T1;
    (b => sum)  = T1;
    (cin => sum)  = T1;

    (a => cout) = T1;
    (b => cout) = T1;
    (cin => cout) = T2;

  endspecify
`endif
endmodule
adder.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?xml version="1.0"?>
<models>
  <model name="ADDER">
    <input_ports>
      <port combinational_sink_ports="cout sum" name="a"/>
      <port combinational_sink_ports="cout sum" name="b"/>
      <port combinational_sink_ports="cout sum" name="cin"/>
    </input_ports>
    <output_ports>
      <port name="cout"/>
      <port name="sum"/>
    </output_ports>
  </model>
</models>
adder.pb_type.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" blif_model=".subckt ADDER" name="ADDER" num_pb="1">
  <input name="a" num_pins="1"/>
  <input name="b" num_pins="1"/>
  <input name="cin" num_pins="1"/>
  <output name="cout" num_pins="1"/>
  <output name="sum" num_pins="1"/>
  <delay_constant in_port="ADDER.a" max="300e-12" out_port="ADDER.cout"/>
  <delay_constant in_port="ADDER.b" max="300e-12" out_port="ADDER.cout"/>
  <delay_constant in_port="ADDER.cin" max="10e-12" out_port="ADDER.cout"/>
  <delay_constant in_port="ADDER.a" max="300e-12" out_port="ADDER.sum"/>
  <delay_constant in_port="ADDER.b" max="300e-12" out_port="ADDER.sum"/>
  <delay_constant in_port="ADDER.cin" max="300e-12" out_port="ADDER.sum"/>
</pb_type>
Detection of combinational connections
  • Output has combinational connection with input

Blackbox detection
  • Model of the leaf pb_type is generated

  • Leaf pb_type XML is generated

Timings
  • All the timings defined for wires with attributes should be included in pb_type XML

LUT with FlipFlop Example

An example of the classical LUT with FlipFlop pair shown in Figure 31 - Pack Pattern Example of the “Architecture Reference” section of the Verilog to Routing Documentation demonstrating the <pack_pattern> tag.

Figure 31 from Verilog to Routing Documentation

Fig. 31 - Pack Pattern Example


/home/docs/checkouts/readthedocs.org/user_builds/f4pga-v2x/checkouts/latest/docs/examples/vtr/lutff-pair/pair.sim.v

pair.sim.v
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
`include "./lut4/lut4.sim.v"
`include "./dff/dff.sim.v"
`include "./omux/omux.sim.v"

module PAIR (
  I,
  CLK,
  O
);
  input wire [3:0] I;
  input wire CLK;

  output wire O;

  (* pack="LUT2FF" *)
  wire lut_out;

  LUT4 lut (.I(I), .O(lut_out));

  wire ff_out;
  DFF dff (.CLK(CLK), .D(lut_out), .Q(ff_out));

  parameter FF_BYPASS = "F";
  OMUX #(.MODE(FF_BYPASS)) mux(.L(lut_out), .F(ff_out), .O(O));

endmodule
pair.model.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0"?>
<models>
  <model name="DFF">
    <input_ports>
      <port is_clock="1" name="CLK"/>
      <port clock="CLK" name="D"/>
    </input_ports>
    <output_ports>
      <port clock="CLK" name="Q"/>
    </output_ports>
  </model>
  <model name="LUT4">
    <input_ports>
      <port combinational_sink_ports="O" name="I"/>
    </input_ports>
    <output_ports>
      <port name="O"/>
    </output_ports>
  </model>
</models>
pair.pb_type.xml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0"?>
<pb_type xmlns:xi="http://www.w3.org/2001/XInclude" name="PAIR" num_pb="1">
  <clock name="CLK" num_pins="1"/>
  <input name="I" num_pins="4"/>
  <output name="O" num_pins="1"/>
  <pb_type blif_model=".subckt DFF" name="dff" num_pb="1">
    <clock name="CLK" num_pins="1"/>
    <input name="D" num_pins="1"/>
    <output name="Q" num_pins="1"/>
    <T_setup clock="CLK" port="DFF.D" value="10e-12"/>
    <T_hold clock="CLK" port="DFF.D" value="10e-12"/>
    <T_clock_to_Q clock="CLK" max="10e-12" port="DFF.Q"/>
  </pb_type>
  <pb_type blif_model=".subckt LUT4" name="lut" num_pb="1">
    <input name="I" num_pins="4"/>
    <output name="O" num_pins="1"/>
    <delay_matrix in_port="LUT4.I" out_port="LUT4.O" type="max">
30e-12 20e-12 11e-12 3e-12
</delay_matrix>
  </pb_type>
  <interconnect>
    <mux input="dff.Q lut.O" name="mux" output="PAIR.O">
      <metadata>
        <meta name="fasm_mux">
dff.Q : mux.F
lut.O : mux.L
</meta>
        <meta name="type">bel</meta>
        <meta name="subtype">routing</meta>
      </metadata>
    </mux>
    <direct input="PAIR.CLK" name="dff-CLK" output="dff.CLK"/>
    <direct input="lut.O" name="dff-D" output="dff.D">
      <pack_pattern in_port="lut.O" name="pack-LUT2FF" out_port="dff.D"/>
    </direct>
    <direct input="PAIR.I[0]" name="lut-I[0]" output="lut.I[0]"/>
    <direct input="PAIR.I[1]" name="lut-I[1]" output="lut.I[1]"/>
    <direct input="PAIR.I[2]" name="lut-I[2]" output="lut.I[2]"/>
    <direct input="PAIR.I[3]" name="lut-I[3]" output="lut.I[3]"/>
  </interconnect>
</pb_type>
Blackbox detection
  • Model of the leaf pb_type is generated

  • Leaf pb_type XML is generated

  • All dependency models and pb_types are included in the output files

Carry chain inference
  • pack_pattern inference - pack_patterns defined on wires with pack attributes should be propagated to pb_type XMLs