OpenCores
URL https://opencores.org/ocsvn/usb_fpga_2_14/usb_fpga_2_14/trunk

Subversion Repositories usb_fpga_2_14

[/] [usb_fpga_2_14/] [trunk/] [examples/] [memfifo/] [fpga-2.18/] [memfifo.srcs/] [sources_1/] [ip/] [mig_7series_0/] [mig_7series_0/] [user_design/] [rtl/] [phy/] [mig_7series_v2_3_poc_meta.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ZTEX
//*****************************************************************************
2
// (c) Copyright 2009 - 2012 Xilinx, Inc. All rights reserved.
3
//
4
// This file contains confidential and proprietary information
5
// of Xilinx, Inc. and is protected under U.S. and
6
// international copyright and other intellectual property
7
// laws.
8
//
9
// DISCLAIMER
10
// This disclaimer is not a license and does not grant any
11
// rights to the materials distributed herewith. Except as
12
// otherwise provided in a valid license issued to you by
13
// Xilinx, and to the maximum extent permitted by applicable
14
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
15
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
16
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
17
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
18
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
19
// (2) Xilinx shall not be liable (whether in contract or tort,
20
// including negligence, or under any other theory of
21
// liability) for any loss or damage of any kind or nature
22
// related to, arising under or in connection with these
23
// materials, including for any direct, or any indirect,
24
// special, incidental, or consequential loss or damage
25
// (including loss of data, profits, goodwill, or any type of
26
// loss or damage suffered as a result of any action brought
27
// by a third party) even if such damage or loss was
28
// reasonably foreseeable or Xilinx had been advised of the
29
// possibility of the same.
30
//
31
// CRITICAL APPLICATIONS
32
// Xilinx products are not designed or intended to be fail-
33
// safe, or for use in any application requiring fail-safe
34
// performance, such as life-support or safety devices or
35
// systems, Class III medical devices, nuclear facilities,
36
// applications related to the deployment of airbags, or any
37
// other applications that could lead to death, personal
38
// injury, or severe property or environmental damage
39
// (individually and collectively, "Critical
40
// Applications"). Customer assumes the sole risk and
41
// liability of any use of Xilinx products in Critical
42
// Applications, subject only to applicable laws and
43
// regulations governing limitations on product liability.
44
//
45
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
46
// PART OF THIS FILE AT ALL TIMES.
47
//
48
//*****************************************************************************
49
//   ____  ____
50
//  /   /\/   /
51
// /___/  \  /    Vendor: Xilinx
52
// \   \   \/     Version:%version
53
//  \   \         Application: MIG
54
//  /   /         Filename: mig_7series_v2_3_poc_meta.v
55
// /___/   /\     Date Last Modified: $$
56
// \   \  /  \    Date Created:Tue 15 Jan 2014
57
//  \___\/\___\
58
//
59
//Device: Virtex-7
60
//Design Name: DDR3 SDRAM
61
//Purpose: Phaser output calibration meta controller.
62
//
63
// Compute center of the window  set up with with the ktap_left, 
64
// ktap_right dance (hereafter "the window").  Also compute center of the 
65
// edge (hereafter "the edge") to be aligned in the center
66
// of this window.
67
//
68
// Following the ktap_left/right dance, the to be centered edge is 
69
// always left at the right edge of the window
70
// if SCANFROMRIGHT == 1, and the left edge otherwise.  
71
//
72
// An assumption is the rise(0) case has a window wider than the noise on the
73
// edge.  The noise case with the possibly narrow window
74
// will always be shifted by 90.  And the fall(180) case is shifted by
75
// 90 twice.  Hence when we start, we can assume the center of the
76
// edge is to the right/left of the the window center.
77
//
78
// The actual hardware does not necessarily monotonically appear to
79
// move the window centers.  Because of noise, it is possible for the
80
// centered edge to move opposite the expected direction with a tap increment.
81
//
82
// This problem is solved by computing the absolute difference between
83
// the centers and the circular distance between the centers.  These will
84
// be the same until the difference transits through zero.  Then the circular
85
// difference will jump to almost the value of TAPSPERKCLK.
86
//
87
// The window center computation is done at 1/2 tap increments to maintain
88
// resolution through the divide by 2 for centering.
89
//
90
// There is a corner case of when the shift is greater than 180 degress.  In
91
// this case the absolute difference and the circular difference will be
92
// unequal at the beginning of the alignment.  This is solved by latching
93
// if they are equal at the end of each cycle.  The completion must see
94
// that they were equal in the previous cycle, but are not equal in this cycle.
95
//
96
// Since the phaser out steps are of unknown size, it is possible to overshoot
97
// the center.  The previous difference is recorded and if its less than the current
98
// difference, poc_backup is driven high.
99
//
100
//Reference:
101
//Revision History:
102
//*****************************************************************************
103
 
104
`timescale 1 ps / 1 ps
105
 
106
module mig_7series_v2_3_poc_meta #
107
  (parameter SCANFROMRIGHT              = 0,
108
   parameter TCQ                        = 100,
109
   parameter TAPCNTRWIDTH               = 7,
110
   parameter TAPSPERKCLK                = 112)
111
  (/*AUTOARG*/
112
  // Outputs
113
  mmcm_edge_detect_done, poc_backup, mmcm_lbclk_edge_aligned,
114
  // Inputs
115
  rst, clk, mmcm_edge_detect_rdy, run, run_polarity, run_end,
116
  rise_lead_right, rise_trail_left, rise_lead_center,
117
  rise_trail_center, rise_trail_right, rise_lead_left, ninety_offsets,
118
  use_noise_window, ktap_at_right_edge, ktap_at_left_edge
119
  );
120
 
121
  localparam NINETY = TAPSPERKCLK/4;
122
 
123
  function [TAPCNTRWIDTH-1:0] offset (input [TAPCNTRWIDTH-1:0] a,
124
                                      input [1:0] b,
125
                                      input integer base);
126
    integer offset_ii;
127
    begin
128
      offset_ii = (a + b * NINETY) < base
129
                     ? (a + b * NINETY)
130
                     : (a + b * NINETY - base);
131
      offset = offset_ii[TAPCNTRWIDTH-1:0];
132
    end
133
  endfunction // offset
134
 
135
  function [TAPCNTRWIDTH-1:0] mod_sub (input [TAPCNTRWIDTH-1:0] a,
136
                                       input [TAPCNTRWIDTH-1:0] b,
137
                                       input integer base);
138
    begin
139
      mod_sub = (a>=b) ? a-b : a+base-b;
140
    end
141
  endfunction // mod_sub
142
 
143
  function [TAPCNTRWIDTH:0] center (input [TAPCNTRWIDTH-1:0] left,
144
                                    input [TAPCNTRWIDTH-1:0] diff,
145
                                    input integer base);
146
    integer center_ii;
147
    begin
148
      center_ii = ({left, 1'b0} + diff < base * 2)
149
                    ? {left, 1'b0} + diff + 32'h0
150
                    : {left, 1'b0} + diff - base * 2;
151
      center = center_ii[TAPCNTRWIDTH:0];
152
    end
153
  endfunction // center
154
 
155
  input rst;
156
  input clk;
157
 
158
 
159
  input mmcm_edge_detect_rdy;
160
 
161
  wire reset_run_ends = rst || ~mmcm_edge_detect_rdy;
162
 
163
  // This input used only for the SVA.
164
  input [TAPCNTRWIDTH-1:0] run;
165
 
166
  input run_end;
167
  reg run_end_r, run_end_r1, run_end_r2, run_end_r3;
168
  always @(posedge clk) run_end_r <= #TCQ run_end;
169
  always @(posedge clk) run_end_r1 <= #TCQ run_end_r;
170
  always @(posedge clk) run_end_r2 <= #TCQ run_end_r1;
171
  always @(posedge clk) run_end_r3 <= #TCQ run_end_r2;
172
 
173
  input run_polarity;
174
  reg run_polarity_held_ns, run_polarity_held_r;
175
  always @(posedge clk) run_polarity_held_r <= #TCQ run_polarity_held_ns;
176
  always @(*) run_polarity_held_ns = run_end ? run_polarity : run_polarity_held_r;
177
 
178
  reg [1:0] run_ends_r;
179
  reg [1:0] run_ends_ns;
180
  always @(posedge clk) run_ends_r <= #TCQ run_ends_ns;
181
  always @(*) begin
182
    run_ends_ns = run_ends_r;
183
    if (reset_run_ends) run_ends_ns = 2'b0;
184
    else case (run_ends_r)
185
           2'b00 : run_ends_ns = run_ends_r + {1'b0, run_end_r3 && run_polarity_held_r};
186
           2'b01, 2'b10 : run_ends_ns = run_ends_r + {1'b0, run_end_r3};
187
          endcase // case (run_ends_r)
188
  end
189
 
190
  reg done_r;
191
  wire done_ns = mmcm_edge_detect_rdy && &run_ends_r;
192
  always @(posedge clk) done_r <= #TCQ done_ns;
193
  output mmcm_edge_detect_done;
194
  assign mmcm_edge_detect_done = done_r;
195
 
196
  input [TAPCNTRWIDTH-1:0] rise_lead_right;
197
  input [TAPCNTRWIDTH-1:0] rise_trail_left;
198
  input [TAPCNTRWIDTH-1:0] rise_lead_center;
199
  input [TAPCNTRWIDTH-1:0] rise_trail_center;
200
  input [TAPCNTRWIDTH-1:0] rise_trail_right;
201
  input [TAPCNTRWIDTH-1:0] rise_lead_left;
202
 
203
  input [1:0] ninety_offsets;
204
  wire [1:0] offsets = SCANFROMRIGHT == 1 ? ninety_offsets : 2'b00 - ninety_offsets;
205
 
206
  wire [TAPCNTRWIDTH-1:0] rise_lead_center_offset_ns = offset(rise_lead_center, offsets, TAPSPERKCLK);
207
  wire [TAPCNTRWIDTH-1:0] rise_trail_center_offset_ns = offset(rise_trail_center, offsets, TAPSPERKCLK);
208
  reg [TAPCNTRWIDTH-1:0] rise_lead_center_offset_r, rise_trail_center_offset_r;
209
  always @(posedge clk) rise_lead_center_offset_r <= #TCQ rise_lead_center_offset_ns;
210
  always @(posedge clk) rise_trail_center_offset_r <= #TCQ rise_trail_center_offset_ns;
211
 
212
  wire [TAPCNTRWIDTH-1:0] edge_diff_ns = mod_sub(rise_trail_center_offset_r, rise_lead_center_offset_r, TAPSPERKCLK);
213
  reg [TAPCNTRWIDTH-1:0] edge_diff_r;
214
  always @(posedge clk) edge_diff_r <= #TCQ edge_diff_ns;
215
 
216
  wire [TAPCNTRWIDTH:0] edge_center_ns = center(rise_lead_center_offset_r, edge_diff_r, TAPSPERKCLK);
217
  reg [TAPCNTRWIDTH:0] edge_center_r;
218
  always @(posedge clk) edge_center_r <= #TCQ edge_center_ns;
219
 
220
  input use_noise_window;
221
  wire [TAPCNTRWIDTH-1:0] left = use_noise_window ? rise_lead_left : rise_trail_left;
222
  wire [TAPCNTRWIDTH-1:0] right = use_noise_window ? rise_trail_right : rise_lead_right;
223
 
224
  wire [TAPCNTRWIDTH-1:0] center_diff_ns = mod_sub(right, left, TAPSPERKCLK);
225
  reg [TAPCNTRWIDTH-1:0] center_diff_r;
226
  always @(posedge clk) center_diff_r <= #TCQ center_diff_ns;
227
 
228
  wire [TAPCNTRWIDTH:0] window_center_ns = center(left, center_diff_r, TAPSPERKCLK);
229
  reg [TAPCNTRWIDTH:0] window_center_r;
230
  always @(posedge clk) window_center_r <= #TCQ window_center_ns;
231
 
232
  localparam TAPSPERKCLKX2 = TAPSPERKCLK * 2;
233
 
234
  wire [TAPCNTRWIDTH+1:0] left_center = {1'b0, SCANFROMRIGHT == 1 ? window_center_r : edge_center_r};
235
  wire [TAPCNTRWIDTH+1:0] right_center = {1'b0, SCANFROMRIGHT == 1 ? edge_center_r : window_center_r};
236
 
237
  wire [TAPCNTRWIDTH+1:0] diff_ns = right_center >= left_center
238
                                     ? right_center - left_center
239
                                     : right_center + TAPSPERKCLKX2[TAPCNTRWIDTH+1:0] - left_center;
240
 
241
  reg [TAPCNTRWIDTH+1:0] diff_r;
242
  always @(posedge clk) diff_r <= #TCQ diff_ns;
243
 
244
  wire [TAPCNTRWIDTH+1:0] abs_diff = diff_r > TAPSPERKCLKX2[TAPCNTRWIDTH+1:0]/2
245
                                       ? TAPSPERKCLKX2[TAPCNTRWIDTH+1:0] - diff_r
246
                                       : diff_r;
247
 
248
  reg [TAPCNTRWIDTH+1:0] prev_ns, prev_r;
249
  always @(posedge clk) prev_r <= #TCQ prev_ns;
250
  always @(*) prev_ns = done_ns ? diff_r : prev_r;
251
 
252
  input ktap_at_right_edge;
253
  input ktap_at_left_edge;
254
 
255
  wire centering = !(ktap_at_right_edge || ktap_at_left_edge);
256
  wire diffs_eq = abs_diff == diff_r;
257
  reg diffs_eq_ns, diffs_eq_r;
258
  always @(*) diffs_eq_ns = centering && ((done_r && done_ns) ? diffs_eq : diffs_eq_r);
259
  always @(posedge clk) diffs_eq_r <= #TCQ diffs_eq_ns;
260
 
261
  reg edge_aligned_r;
262
  reg prev_valid_ns, prev_valid_r;
263
  always @(posedge clk) prev_valid_r <= #TCQ prev_valid_ns;
264
  always @(*) prev_valid_ns = (~rst && ~ktap_at_right_edge && ~ktap_at_left_edge && ~edge_aligned_r) && prev_valid_r | done_ns;
265
 
266
  wire indicate_alignment = ~rst && centering && done_ns;
267
  wire edge_aligned_ns = indicate_alignment && (~|diff_r || ~diffs_eq & diffs_eq_r);
268
  always @(posedge clk) edge_aligned_r <= #TCQ edge_aligned_ns;
269
 
270
  reg poc_backup_r;
271
  wire poc_backup_ns = edge_aligned_ns && abs_diff > prev_r;
272
  always @(posedge clk) poc_backup_r <= #TCQ poc_backup_ns;
273
  output poc_backup;
274
  assign poc_backup = poc_backup_r;
275
 
276
  output mmcm_lbclk_edge_aligned;
277
  assign mmcm_lbclk_edge_aligned = edge_aligned_r;
278
 
279
endmodule // mig_7series_v2_3_poc_meta
280
 
281
// Local Variables:
282
// verilog-library-directories:(".")
283
// verilog-library-extensions:(".v")
284
// End:

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.