blob: 2295ebaff396ca5004412c10fc04c998c0db9de1 [file] [log] [blame]
`timescale 1ps/1ps
//Overivew
//========
//This file contains the verilog primitives produced by VPR's
//post-synthesis netlist writer.
//
//If you wish to do back-annotated timing simulation you will need
//to link with this file during simulation.
//
//To ensure currect result when performing back-annoatation with
//Modelsim see the notes at the end of this comment.
//
//Specifying Timing Edges
//=======================
//To perform timing back-annotation the simulator must know the delay
//dependancies (timing edges) between the ports on each primitive.
//
//During back-annotation the simulator will attempt to annotate SDF delay
//values onto the timing edges. It should give a warning if was unable
//to find a matching edge.
//
//
//In Verilog timing edges are specified using a specify block (delimited by the
//'specify' and 'endspecify' keywords.
//
//Inside the specify block a set of specify statements are used to describe
//the timing edges. For example consider:
//
// input [1:0] in;
// output [1:0] out;
// specify
// (in[0] => out[0]) = "";
// (in[1] => out[1]) = "";
// endspecify
//
//This states that there are the following timing edges (dependancies):
// * from in[0] to out[0]
// * from in[1] to out[1]
//
//We could (according to the Verilog standard) equivalently have used:
//
// input [1:0] in;
// output [1:0] out;
// specify
// (in => out) = "";
// endspecify
//
//However NOT ALL SIMULATORS TREAT MULTIBIT SPECIFY STATEMENTS CORRECTLY,
//at least by default (in particular ModelSim, see notes below).
//
//The previous examples use the 'parrallel connection' operator '=>', which
//creates parallel edges between the two operands (i.e. bit 0 to bit 0, bit
//1 to bit 1 etc.). Note that both operands must have the same bit-width.
//
//Verilog also supports the 'full connection' operator '*>' which will create
//a fully connected set of edges (e.g. from all-to-all). It does not require
//both operands to have the same bit-width. For example:
//
// input [1:0] in;
// output [2:0] out;
// specify
// (in *> out) = "";
// endspecify
//
//states that there are the following timing edges (dependancies):
// * from in[0] to out[0]
// * from in[0] to out[1]
// * from in[0] to out[2]
// * from in[1] to out[0]
// * from in[1] to out[1]
// * from in[1] to out[2]
//
//For more details on specify blocks see Section 14 "Specify Blocks" of the
//Verilog standard (IEEE 1364-2005).
//
//Back-annotation with Modelsim
//=============================
//
//Ensuring Multi-bit Specifies are Handled Correctly: Bit-blasting
//----------------------------------------------------------------
//
//ModelSim (tested on Modelsim SE 10.4c) ignores multi-bit specify statements
//by default.
//
//This causes SDF annotation errors such as:
//
// vsim-SDF-3261: Failed to find matching specify module path
//
//To force Modelsim to correctly interpret multi-bit specify statements you
//should provide the '+bitblast' option to the vsim executable.
//This forces it to apply specify statements using multi-bit operands to
//each bit of the operand (i.e. according to the Verilog standard).
//
//Confirming back-annotation is occuring correctly
//------------------------------------------------
//
//Another useful option is '+sdf_verbose' which produces extra output about
//SDF annotation, which can be used to verify annotation occured correctly.
//
//For example:
//
// Summary of Verilog design objects annotated:
//
// Module path delays = 5
//
// ******************************************************************************
//
// Summary of constructs read:
//
// IOPATH = 5
//
//shows that all 5 IOPATH constructs in the SDF were annotated to the verilog
//design.
//
//Example vsim Command Line
//--------------------------
//The following is an example command-line to vsim (where 'tb' is the name of your
//testbench):
//
// vsim -t 1ps -L rtl_work -L work -voptargs="+acc" +sdf_verbose +bitblast tb
//K-input Look-Up Table
module LUT_K #(
//The Look-up Table size (number of inputs)
parameter K,
//The lut mask.
//Left-most (MSB) bit corresponds to all inputs logic one.
//Defaults to always false.
parameter LUT_MASK={2**K{1'b0}}
) (
input [K-1:0] in,
output out
);
specify
(in *> out) = "";
endspecify
assign out = LUT_MASK[in];
endmodule
//D-FlipFlop module
module DFF #(
parameter INITIAL_VALUE=1'b0
) (
input clock,
input D,
output reg Q
);
specify
(clock => Q) = "";
$setup(D, posedge clock, "");
$hold(posedge clock, D, "");
endspecify
initial begin
Q <= INITIAL_VALUE;
end
always@(posedge clock) begin
Q <= D;
end
endmodule
//Routing fpga_interconnect module
module fpga_interconnect(
input datain,
output dataout
);
specify
(datain=>dataout)="";
endspecify
assign dataout = datain;
endmodule
//2-to-1 mux module
module mux(
input select,
input x,
input y,
output z
);
assign z = (x & ~select) | (y & select);
endmodule
//n-bit adder
module adder #(
parameter WIDTH = 1
) (
input [WIDTH-1:0] a,
input [WIDTH-1:0] b,
input cin,
output cout,
output [WIDTH-1:0] sumout);
specify
(a*>sumout)="";
(b*>sumout)="";
(cin*>sumout)="";
(a*>cout)="";
(b*>cout)="";
(cin=>cout)="";
endspecify
assign {cout, sumout} = a + b + cin;
endmodule
//nxn multiplier module
module multiply #(
//The width of input signals
parameter WIDTH = 1
) (
input [WIDTH-1:0] a,
input [WIDTH-1:0] b,
output [2*WIDTH-1:0] out
);
specify
(a *> out) = "";
(b *> out) = "";
endspecify
assign out = a * b;
endmodule // mult
//single_port_ram module
module single_port_ram #(
parameter ADDR_WIDTH = 1,
parameter DATA_WIDTH = 1
) (
input [ADDR_WIDTH-1:0] addr,
input [DATA_WIDTH-1:0] data,
input we,
input clock,
output reg [DATA_WIDTH-1:0] out
);
localparam MEM_DEPTH = 2 ** ADDR_WIDTH;
reg [DATA_WIDTH-1:0] Mem[MEM_DEPTH-1:0];
specify
(clock*>out)="";
$setup(addr, posedge clock, "");
$setup(data, posedge clock, "");
$setup(we, posedge clock, "");
$hold(posedge clock, addr, "");
$hold(posedge clock, data, "");
$hold(posedge clock, we, "");
endspecify
always@(posedge clock) begin
if(we) begin
Mem[addr] = data;
end
out = Mem[addr]; //New data read-during write behaviour (blocking assignments)
end
endmodule // single_port_RAM
//dual_port_ram module
module dual_port_ram #(
parameter ADDR_WIDTH = 1,
parameter DATA_WIDTH = 1
) (
input clock,
input [ADDR_WIDTH-1:0] addr1,
input [ADDR_WIDTH-1:0] addr2,
input [DATA_WIDTH-1:0] data1,
input [DATA_WIDTH-1:0] data2,
input we1,
input we2,
output reg [DATA_WIDTH-1:0] out1,
output reg [DATA_WIDTH-1:0] out2
);
localparam MEM_DEPTH = 2 ** ADDR_WIDTH;
reg [DATA_WIDTH-1:0] Mem[MEM_DEPTH-1:0];
specify
(clock*>out1)="";
(clock*>out2)="";
$setup(addr1, posedge clock, "");
$setup(addr2, posedge clock, "");
$setup(data1, posedge clock, "");
$setup(data2, posedge clock, "");
$setup(we1, posedge clock, "");
$setup(we2, posedge clock, "");
$hold(posedge clock, addr1, "");
$hold(posedge clock, addr2, "");
$hold(posedge clock, data1, "");
$hold(posedge clock, data2, "");
$hold(posedge clock, we1, "");
$hold(posedge clock, we2, "");
endspecify
always@(posedge clock) begin //Port 1
if(we1) begin
Mem[addr1] = data1;
end
out1 = Mem[addr1]; //New data read-during write behaviour (blocking assignments)
end
always@(posedge clock) begin //Port 2
if(we2) begin
Mem[addr2] = data2;
end
out2 = Mem[addr2]; //New data read-during write behaviour (blocking assignments)
end
endmodule // dual_port_ram