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
|
// The four D flip-flops (DFFs) in a Cyclone V/10GX Adaptive Logic Module (ALM)
// act as one-bit memory cells that can be placed very flexibly (wherever there's
// an ALM); each flop is represented by a MISTRAL_FF cell.
//
// The flops in these chips are rather flexible in some ways, but in practice
// quite crippled by FPGA standards.
//
// What the flops can do
// ---------------------
// The core flop acts as a single-bit memory that initialises to zero at chip
// reset. It takes in data on the rising edge of CLK if ENA is high,
// and outputs it to Q. The ENA (clock enable) pin can therefore be used to
// capture the input only if a condition is true.
//
// The data itself is zero if SCLR (synchronous clear) is high, else it comes
// from SDATA (synchronous data) if SLOAD (synchronous load) is high, or DATAIN
// if SLOAD is low.
//
// If ACLR (asynchronous clear) is low then Q is forced to zero, regardless of
// the synchronous inputs or CLK edge. This is most often used for an FPGA-wide
// power-on reset.
//
// An asynchronous set that sets Q to one can be emulated by inverting the input
// and output of the flop, resulting in ACLR forcing Q to zero, which then gets
// inverted to produce one. Likewise, logic can operate on the falling edge of
// CLK if CLK is inverted before being passed as an input.
//
// What the flops *can't* do
// -------------------------
// The trickiest part of the above capabilities is the lack of configurable
// initialisation state. For example, it isn't possible to implement a flop with
// asynchronous clear that initialises to one, because the hardware initialises
// to zero. Likewise, you can't emulate a flop with asynchronous set that
// initialises to zero, because the inverters mean the flop initialises to one.
//
// If the input design requires one of these cells (which appears to be rare
// in practice) then synth_intel_alm will fail to synthesize the design where
// other Yosys synthesis scripts might succeed.
//
// This stands in notable contrast to e.g. Xilinx flip-flops, which have
// configurable initialisation state and native synchronous/asynchronous
// set/clear (although not at the same time), which means they can generally
// implement a much wider variety of logic.
// DATAIN: synchronous data input
// CLK: clock input (positive edge)
// ACLR: asynchronous clear (negative-true)
// ENA: clock-enable
// SCLR: synchronous clear
// SLOAD: synchronous load
// SDATA: synchronous load data
//
// Q: data output
//
// Note: the DFFEAS primitive is mostly emulated; it does not reflect what the hardware implements.
(* abc9_box, lib_whitebox *)
module MISTRAL_FF(
input DATAIN,
(* clkbuf_sink *) input CLK,
input ACLR, ENA, SCLR, SLOAD, SDATA,
output reg Q
);
`ifdef cyclonev
specify
if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 731;
if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 890;
if (ENA && !SCLR && SLOAD) (posedge CLK => (Q : SDATA)) = 618;
$setup(DATAIN, posedge CLK, /* -196 */ 0);
$setup(ENA, posedge CLK, /* -196 */ 0);
$setup(SCLR, posedge CLK, /* -196 */ 0);
$setup(SLOAD, posedge CLK, /* -196 */ 0);
$setup(SDATA, posedge CLK, /* -196 */ 0);
if (ACLR === 1'b0) (ACLR => Q) = 282;
endspecify
`endif
`ifdef arriav
specify
if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 470;
if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 633;
if (ENA && !SCLR && SLOAD) (posedge CLK => (Q : SDATA)) = 439;
$setup(DATAIN, posedge CLK, /* -170 */ 0);
$setup(ENA, posedge CLK, /* -170 */ 0);
$setup(SCLR, posedge CLK, /* -170 */ 0);
$setup(SLOAD, posedge CLK, /* -170 */ 0);
$setup(SDATA, posedge CLK, /* -170 */ 0);
if (ACLR === 1'b0) (ACLR => Q) = 215;
endspecify
`endif
`ifdef cyclone10gx
specify
// TODO (long-term): investigate these numbers.
// It seems relying on the Quartus Timing Analyzer was not the best idea; it's too fiddly.
if (ENA && ACLR !== 1'b0 && !SCLR && !SLOAD) (posedge CLK => (Q : DATAIN)) = 219;
if (ENA && SCLR) (posedge CLK => (Q : 1'b0)) = 219;
if (ENA && !SCLR && SLOAD) (posedge CLK => (Q : SDATA)) = 219;
$setup(DATAIN, posedge CLK, 268);
$setup(ENA, posedge CLK, 268);
$setup(SCLR, posedge CLK, 268);
$setup(SLOAD, posedge CLK, 268);
$setup(SDATA, posedge CLK, 268);
if (ACLR === 1'b0) (ACLR => Q) = 0;
endspecify
`endif
initial begin
// Altera flops initialise to zero.
Q = 0;
end
always @(posedge CLK, negedge ACLR) begin
// Asynchronous clear
if (!ACLR) Q <= 0;
// Clock-enable
else if (ENA) begin
// Synchronous clear
if (SCLR) Q <= 0;
// Synchronous load
else if (SLOAD) Q <= SDATA;
else Q <= DATAIN;
end
end
endmodule
|