-
Notifications
You must be signed in to change notification settings - Fork 396
/
primitives.v
329 lines (287 loc) · 8.04 KB
/
primitives.v
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
`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 = 1,
//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 clk,
input D,
output reg Q
);
specify
(clk => Q) = "";
$setup(D, posedge clk, "");
$hold(posedge clk, D, "");
endspecify
initial begin
Q <= INITIAL_VALUE;
end
always@(posedge clk) 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
(* keep_hierarchy *)
module single_port_ram #(
parameter ADDR_WIDTH = 1,
parameter DATA_WIDTH = 1
) (
input clk,
input [ADDR_WIDTH-1:0] addr,
input [DATA_WIDTH-1:0] data,
input we,
output reg [DATA_WIDTH-1:0] out
);
localparam MEM_DEPTH = 2 ** ADDR_WIDTH;
reg [DATA_WIDTH-1:0] Mem[MEM_DEPTH-1:0];
specify
(clk*>out)="";
$setup(addr, posedge clk, "");
$setup(data, posedge clk, "");
$setup(we, posedge clk, "");
$hold(posedge clk, addr, "");
$hold(posedge clk, data, "");
$hold(posedge clk, we, "");
endspecify
always@(posedge clk) 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
(* keep_hierarchy *)
module dual_port_ram #(
parameter ADDR_WIDTH = 1,
parameter DATA_WIDTH = 1
) (
input clk,
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
(clk*>out1)="";
(clk*>out2)="";
$setup(addr1, posedge clk, "");
$setup(addr2, posedge clk, "");
$setup(data1, posedge clk, "");
$setup(data2, posedge clk, "");
$setup(we1, posedge clk, "");
$setup(we2, posedge clk, "");
$hold(posedge clk, addr1, "");
$hold(posedge clk, addr2, "");
$hold(posedge clk, data1, "");
$hold(posedge clk, data2, "");
$hold(posedge clk, we1, "");
$hold(posedge clk, we2, "");
endspecify
always@(posedge clk) begin //Port 1
if(we1) begin
Mem[addr1] = data1;
end
out1 = Mem[addr1]; //New data read-during write behaviour (blocking assignments)
end
always@(posedge clk) 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