x393  1.0
FPGAcodeforElphelNC393camera
clocks393m.v
Go to the documentation of this file.
1 
39 `timescale 1ns/1ps
40 
41 module clocks393m#(
42  parameter CLK_ADDR = 'h728, // ..'h729
43  parameter CLK_MASK = 'h7fe, //
44  parameter CLK_STATUS_REG_ADDR = 'h3a, //
45  parameter CLK_CNTRL = 0,
46  parameter CLK_STATUS = 1,
47 
48  parameter CLK_RESET = 'h0, // which clocks should stay reset after release of masrter reset {ff1,ff0,mem,sync,xclk,pclk,xclk}
49  parameter CLK_PWDWN = 'h0, // which clocks should stay powered down after release of masrter reset {sync,xclk,pclk,xclk}
50 
51 // CLocks derived from external clock source (for sesnors
52  parameter CLKIN_PERIOD_PCLK = 42, // 24MHz
53  parameter DIVCLK_DIVIDE_PCLK = 1,
54  parameter CLKFBOUT_MULT_PCLK = 40, // 960 MHz
55  parameter CLKOUT_DIV_PCLK = 10, // 96MHz
56  parameter BUF_CLK1X_PCLK = "BUFG",
57 `ifdef USE_PCLK2X
58  parameter CLKOUT_DIV_PCLK2X = 5, // 192 MHz
59  parameter PHASE_CLK2X_PCLK = 0.000,
60  parameter BUF_CLK1X_PCLK2X = "BUFG",
61 `endif
62 /*
63  Mutltiple clocks derived from PS source (excluding memory controller) using a single PLL
64  Fvco = 1200Mhz - maximal for spped grade -1
65 */
66  parameter MULTICLK_IN_PERIOD = 20, // 50MHz
67  parameter MULTICLK_DIVCLK = 1, //
68  parameter MULTICLK_MULT = 24, //1200MHz
69  parameter MULTICLK_DIV_DLYREF = 6, // 6 - 200MHz I/O delay reference clock (4 - 300MHz)
70  parameter MULTICLK_DIV_AXIHP = 8, // 150 MHz for AXI HP
71  parameter MULTICLK_DIV_XCLK = 5, // 240 MHz for compressor (12 for 100 MHz)
72 `ifdef USE_XCLK2X
73  parameter MULTICLK_DIV_XCLK2X = 6, // 200 MHz for compressor (when MULTICLK_DIV_XCLK uses 100 MHz)
74 `endif
75  parameter MULTICLK_DIV_SYNC = 12, // 100 MHz for inter-camera synchronization and time keeping
76 
77 // Additional parameters for multi-clock PLL (phases and buffer types)
78 
79  parameter MULTICLK_PHASE_FB = 0.0,
80  parameter MULTICLK_PHASE_DLYREF = 0.0,
81  parameter MULTICLK_BUF_DLYREF = "BUFG",
82  parameter MULTICLK_PHASE_AXIHP = 0.0,
83  parameter MULTICLK_BUF_AXIHP = "BUFG",
84  parameter MULTICLK_PHASE_XCLK = 0.0,
85  parameter MULTICLK_BUF_XCLK = "BUFG",
86 `ifdef USE_XCLK2X
87  parameter MULTICLK_PHASE_XCLK2X = 0.0,
88  parameter MULTICLK_BUF_XCLK2X = "BUFG",
89 `endif
90  parameter MULTICLK_PHASE_SYNC = 0.0,
91  parameter MULTICLK_BUF_SYNC = "BUFG",
92 
93  parameter MEMCLK_CAPACITANCE = "DONT_CARE",
94  parameter MEMCLK_IBUF_LOW_PWR = "TRUE",
95  parameter MEMCLK_IOSTANDARD = "DEFAULT",
96 
97  parameter FFCLK0_CAPACITANCE = "DONT_CARE",
98  parameter FFCLK0_DIFF_TERM = "FALSE",
99  parameter FFCLK0_IBUF_LOW_PWR = "TRUE",
100  parameter FFCLK0_IOSTANDARD = "DEFAULT",
101 
102  parameter FFCLK1_CAPACITANCE = "DONT_CARE",
103  parameter FFCLK1_DIFF_TERM = "FALSE",
104  parameter FFCLK1_IBUF_LOW_PWR = "TRUE",
105  parameter FFCLK1_IOSTANDARD = "DEFAULT"
106 
107 )(
108  input async_rst, // always reset MMCM/PLL
109  input mclk, // global clock, comes from the memory controller (uses aclk generated here)
110  input mrst,
111  // command/status interface
112  input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
113  input cmd_stb, // strobe (with first byte) for the command a/d
114  output [7:0] status_ad, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25]
115  output status_rq, // input request to send status downstream
116  input status_start, // Acknowledge of the first status packet byte (address)
117  input [3:0] fclk, // 4 clocks coming from the Zynq PS. Currently only [0] is used
118  input memclk_pad, // connected to external clock generator (VDD=1.5V)
119  input ffclk0p_pad, // differential clock (P) same power as sensors 0 and 1 (VCC_SENS01)
120  input ffclk0n_pad, // differential clock (N) same power as sensors 0 and 1 (VCC_SENS01)
121  input ffclk1p_pad, // differential clock (P) same power as sensors 0 and 1 (VCC_SENS01)
122  input ffclk1n_pad, // differential clock (N) same power as sensors 0 and 1 (VCC_SENS01)
123  output aclk, // global clock 50 MHz (used for maxi0)
124  output hclk, // global clock 150MHz (used for afi*, saxi*)
125  output pclk, // global clock for sensors (now 96MHz), based on external clock generator
126 `ifdef USE_PCLK2X
127  output pclk2x, // global clock for sensors, 2x frequency (now 192MHz)
128 `endif
129  output xclk, // global clock for compressor (now 100MHz)
130 `ifdef USE_XCLK2X
131  output xclk2x, // global clock for compressor, 2x frequency (now 200MHz)
132 `endif
133  output sync_clk, // global clock for camsync module (96 MHz for 353 compatibility - switch to 100MHz)?
134  output time_ref, // non-global, just RTC (currently just mclk/8 = 25 MHz)
135  output dly_ref_clk, // global clock for I/O delays calibration
136  input [1:0] extra_status, // just extra two status bits from the top module
138  output locked_xclk,
139  output locked_pclk,
140  output locked_hclk
141 );
142  wire memclk;
143  wire ffclk0;
144  wire ffclk1;
145  wire [8:0] status_data;
146  wire [10:0] cmd_data;
147  wire cmd_we;
148  wire [0:0] cmd_a;
149 
151  wire set_status_w = cmd_we & ((cmd_a && CLK_MASK) == CLK_STATUS);
152  wire [3:0] locked;
153  reg [6:0] reset_clk = CLK_RESET;
154  reg [3:0] pwrdwn_clk = CLK_PWDWN;
155  reg [2:0] test_clk; // FF to test input clocks are running
156  wire memclk_rst = reset_clk[4];
157  wire ffclk0_rst = reset_clk[5];
159 
160  assign locked[3:2] = 3; // for compatibility with previous clocks393.v module
161  assign locked_sync_clk = locked[3];
162  assign locked_xclk = locked[2];
163  assign locked_pclk = locked[1];
164  assign locked_hclk = locked[0];
165 
166  always @ (posedge mclk) begin
168  else if (set_ctrl_w) reset_clk <= {cmd_data[10:8], cmd_data[3:0]};
169 
171  else if (set_ctrl_w) pwrdwn_clk <= cmd_data[7:4];
172  end
174  always @ (posedge memclk or posedge memclk_rst) if (async_rst || memclk_rst) test_clk[0] <= 0; else test_clk[0] <= ~test_clk[0];
175  always @ (posedge ffclk0 or posedge ffclk0_rst) if (async_rst || ffclk0_rst) test_clk[1] <= 0; else test_clk[1] <= ~test_clk[1];
176  always @ (posedge ffclk1 or posedge ffclk1_rst) if (async_rst || ffclk1_rst) test_clk[2] <= 0; else test_clk[2] <= ~test_clk[2];
177 
178  cmd_deser #(
179  .ADDR (CLK_ADDR),
180  .ADDR_MASK (CLK_MASK),
181  .NUM_CYCLES (4),
182  .ADDR_WIDTH (1),
183  .DATA_WIDTH (11)
184  ) cmd_deser_32bit_i (
185  .rst (1'b0), // rst), // input
186  .clk (mclk), // input
187  .srst (mrst), // input
188  .ad (cmd_ad), // input[7:0]
189  .stb (cmd_stb), // input
190  .addr (cmd_a), // output[3:0]
191  .data (cmd_data), // output[31:0]
192  .we (cmd_we) // output
193  );
194 
195  status_generate #(
196  .STATUS_REG_ADDR (CLK_STATUS_REG_ADDR),
197  .PAYLOAD_BITS (9),
198  .REGISTER_STATUS (0)
199  ) status_generate_i (
200  .rst (1'b0), // rst), // input
201  .clk (mclk), // input
202  .srst (mrst), // input
203  .we (set_status_w), // input
204  .wd (cmd_data[7:0]), // input[7:0]
205  .status (status_data), // input[14:0]
206  .ad (status_ad), // output[7:0]
207  .rq (status_rq), // output
208  .start (status_start) // input
209  );
210 
211  BUFG bufg_axi_aclk_i (.O(aclk), .I(fclk[0])); // PS clock, 50MHz
212 
213 // from external clock sourec
215  .CLKIN_PERIOD (CLKIN_PERIOD_PCLK),
216  .DIVCLK_DIVIDE (DIVCLK_DIVIDE_PCLK),
217  .CLKFBOUT_MULT (CLKFBOUT_MULT_PCLK),
218  .CLKOUT_DIV_CLK1X (CLKOUT_DIV_PCLK),
219  .BUF_CLK1X (BUF_CLK1X_PCLK)
220 `ifdef USE_PCLK2X
221  ,.CLKOUT_DIV_CLK2X (CLKOUT_DIV_PCLK2X),
222  .PHASE_CLK2X (PHASE_CLK2X_PCLK),
223  .BUF_CLK2X (BUF_CLK1X_PCLK2X)
224 `else
225  ,.BUF_CLK2X ("NONE")
226 `endif
227  ) dual_clock_pclk_i (
228  .rst (async_rst || reset_clk[1]), // input
229  .clk_in (ffclk0), // input
230  .pwrdwn (pwrdwn_clk[1]), // input
231  .clk1x (pclk), // output
232 `ifdef USE_PCLK2X
233  .clk2x (pclk2x), // output
234 `else
235  .clk2x (), // output not connected
236 `endif
237  .locked (locked[1]) // output
238  );
239  wire multi_clkfb;
240  wire hclk_pre;
241  wire dly_ref_clk_pre;
242  wire xclk_pre;
243  wire sync_clk_pre;
244 `ifdef USE_PCLK2X
245  wire xclk2x_pre;
246 `endif
247 
248  pll_base #(
249  .CLKIN_PERIOD (MULTICLK_IN_PERIOD), // 20
250  .BANDWIDTH ("OPTIMIZED"),
251  .DIVCLK_DIVIDE (MULTICLK_DIVCLK),
252  .CLKFBOUT_MULT (MULTICLK_MULT), // 2..64, // Fvco=Fclkin*CLKFBOUT_MULT_F/DIVCLK_DIVIDE, Fout=Fvco/CLKOUT#_DIVIDE
253  .CLKFBOUT_PHASE (MULTICLK_PHASE_FB),
254  .CLKOUT0_DIVIDE (MULTICLK_DIV_AXIHP),
255  .CLKOUT0_PHASE (MULTICLK_PHASE_AXIHP),
256  .CLKOUT1_DIVIDE (MULTICLK_DIV_XCLK),
257  .CLKOUT1_PHASE (MULTICLK_PHASE_XCLK),
258 `ifdef USE_XCLK2X
259  .CLKOUT2_DIVIDE (MULTICLK_DIV_XCLK2X),
260  .CLKOUT2_PHASE (MULTICLK_PHASE_XCLK2X),
261 `endif
262  .CLKOUT3_DIVIDE (MULTICLK_DIV_SYNC),
263  .CLKOUT3_PHASE (MULTICLK_PHASE_SYNC),
264  .CLKOUT5_DIVIDE (MULTICLK_DIV_DLYREF),
265  .CLKOUT5_PHASE (MULTICLK_PHASE_DLYREF),
266  .REF_JITTER1 (0.010),
267  .STARTUP_WAIT ("FALSE")
268  ) pll_base_i (
269  .clkin(aclk), // input
270  .clkfbin (multi_clkfb), // input
271  .rst (async_rst || reset_clk[0]), // input TODO: check resets/
273  .pwrdwn (pwrdwn_clk[0]), // input
274  .clkout0 (hclk_pre), // output
275  .clkout1 (xclk_pre), // output
276 `ifdef USE_PCLK2X
277  .clkout2 (xclk2x_pre), // output
278 `else
279  .clkout2 (), // output
280 `endif
281  .clkout3 (sync_clk_pre), // output
282  .clkout4 (), // output
283  .clkout5 (dly_ref_clk_pre), // output
284  .clkfbout (multi_clkfb), // output
285  .locked (locked[0]) // output
286  );
287 
288 // Buffering clocks outputs
289  select_clk_buf #(.BUFFER_TYPE(MULTICLK_BUF_DLYREF)) dly_ref_clk_i (.o(dly_ref_clk), .i(dly_ref_clk_pre), .clr(async_rst));
290  select_clk_buf #(.BUFFER_TYPE(MULTICLK_BUF_AXIHP)) hclk_i (.o(hclk), .i(hclk_pre), .clr(async_rst));
291  select_clk_buf #(.BUFFER_TYPE(MULTICLK_BUF_XCLK)) xclk_i (.o(xclk), .i(xclk_pre), .clr(async_rst)); // locked[2],pwrdwn_clk[2],reset_clk[2]
292 `ifdef USE_XCLK2X
293  select_clk_buf #(.BUFFER_TYPE(MULTICLK_BUF_XCLK2X)) xclk2x_i (.o(xclk2x), .i(xclk2x_pre), .clr(async_rst));
294 `endif
295  select_clk_buf #(.BUFFER_TYPE(MULTICLK_BUF_SYNC)) sync_clk_i (.o(sync_clk), .i(sync_clk_pre), .clr(async_rst)); // locked[3],pwrdwn_clk[3],reset_clk[3]
296 
297  ibuf_ibufg #(
298  .CAPACITANCE (MEMCLK_CAPACITANCE),
299  .IBUF_LOW_PWR (MEMCLK_IBUF_LOW_PWR),
300  .IOSTANDARD (MEMCLK_IOSTANDARD)
301  ) ibuf_ibufg_i (
302  .O (memclk), // output
303  .I (memclk_pad) // input
304  );
305 
306  ibufds_ibufgds #(
307  .CAPACITANCE (FFCLK0_CAPACITANCE),
308  .DIFF_TERM (FFCLK0_DIFF_TERM),
309  .IBUF_LOW_PWR (FFCLK0_IBUF_LOW_PWR),
310  .IOSTANDARD (FFCLK0_IOSTANDARD)
311  ) ibufds_ibufgds0_i (
312  .O (ffclk0), // output
313  .I (ffclk0p_pad), // input
314  .IB (ffclk0n_pad) // input
315  );
316 
317  ibufds_ibufgds #(
318  .CAPACITANCE (FFCLK1_CAPACITANCE),
319  .DIFF_TERM (FFCLK1_DIFF_TERM),
320  .IBUF_LOW_PWR (FFCLK1_IBUF_LOW_PWR),
321  .IOSTANDARD (FFCLK1_IOSTANDARD)
322  ) ibufds_ibufgds10_i (
323  .O (ffclk1), // output
324  .I (ffclk1p_pad), // input
325  .IB (ffclk1n_pad) // input
326  );
327 
328  // RTC reference: integer number of microseconds, less than mclk/2. Not a global clock
329  // temporary:
330  reg [2:0] time_ref_r;
331  always @ (posedge mclk) if (mrst) time_ref_r <= 0; else time_ref_r <= time_ref_r + 1;
332  assign time_ref = time_ref_r[2];
333 
334 endmodule
335 
336 
9860MEMCLK_IBUF_LOW_PWR"TRUE"
Definition: clocks393m.v:88
9852MULTICLK_BUF_DLYREF"BUFG"
Definition: clocks393m.v:78
[7:0] 9875status_ad
Definition: clocks393m.v:108
9848MULTICLK_DIV_XCLK5
Definition: clocks393m.v:70
ibufds_ibufgds10_i ibufds_ibufgds
Definition: clocks393m.v:299
11577clkout1
Definition: pll_base.v:74
9831CLK_ADDR'h728
Definition: clocks393m.v:42
ibuf_ibufg_i ibuf_ibufg
Definition: clocks393m.v:279
9864FFCLK0_IBUF_LOW_PWR"TRUE"
Definition: clocks393m.v:93
9906reset_clkreg[6:0]
Definition: clocks393m.v:145
9840CLKFBOUT_MULT_PCLK40
Definition: clocks393m.v:54
11572clkin
Definition: pll_base.v:69
9836CLK_RESET'h0
Definition: clocks393m.v:48
9834CLK_CNTRL0
Definition: clocks393m.v:45
11575pwrdwn
Definition: pll_base.v:72
9843MULTICLK_IN_PERIOD20
Definition: clocks393m.v:65
9862FFCLK0_CAPACITANCE"DONT_CARE"
Definition: clocks393m.v:91
9904set_status_wwire
Definition: clocks393m.v:143
9849MULTICLK_DIV_SYNC12
Definition: clocks393m.v:72
9914dly_ref_clk_prewire
Definition: clocks393m.v:229
9838CLKIN_PERIOD_PCLK42
Definition: clocks393m.v:52
9839DIVCLK_DIVIDE_PCLK1
Definition: clocks393m.v:53
11579clkout3
Definition: pll_base.v:76
9897ffclk0wire
Definition: clocks393m.v:135
[1:0] 9891extra_status
Definition: clocks393m.v:128
9903set_ctrl_wwire
Definition: clocks393m.v:142
11573clkfbin
Definition: pll_base.v:70
pll_base_i pll_base
Definition: clocks393m.v:235
[3:0] 9878fclk
Definition: clocks393m.v:111
9845MULTICLK_MULT24
Definition: clocks393m.v:67
11580clkout4
Definition: pll_base.v:77
9902cmd_awire[0:0]
Definition: clocks393m.v:140
9857MULTICLK_PHASE_SYNC0.0
Definition: clocks393m.v:84
[ADDR_MASK2!=0?2:ADDR_MASK1!=0?1:0:0] 9935we
Definition: cmd_deser.v:60
9844MULTICLK_DIVCLK1
Definition: clocks393m.v:66
11576clkout0
Definition: pll_base.v:73
cmd_deser_32bit_i cmd_deser
Definition: clocks393m.v:170
11582clkfbout
Definition: pll_base.v:79
9858MULTICLK_BUF_SYNC"BUFG"
Definition: clocks393m.v:85
9847MULTICLK_DIV_AXIHP8
Definition: clocks393m.v:69
11581clkout5
Definition: pll_base.v:78
9865FFCLK0_IOSTANDARD"DEFAULT"
Definition: clocks393m.v:94
9907pwrdwn_clkreg[3:0]
Definition: clocks393m.v:146
9905lockedwire[3:0]
Definition: clocks393m.v:144
dual_clock_pclk_i dual_clock_source
Definition: clocks393m.v:206
9855MULTICLK_PHASE_XCLK0.0
Definition: clocks393m.v:81
9892locked_sync_clk
Definition: clocks393m.v:129
9866FFCLK1_CAPACITANCE"DONT_CARE"
Definition: clocks393m.v:96
9861MEMCLK_IOSTANDARD"DEFAULT"
Definition: clocks393m.v:89
9912multi_clkfbwire
Definition: clocks393m.v:227
11574rst
Definition: pll_base.v:71
9899status_datawire[8:0]
Definition: clocks393m.v:137
9832CLK_MASK'h7fe
Definition: clocks393m.v:43
9850MULTICLK_PHASE_FB0.0
Definition: clocks393m.v:76
[DATA_WIDTH-1:0] 9934data
Definition: cmd_deser.v:59
9851MULTICLK_PHASE_DLYREF0.0
Definition: clocks393m.v:77
9833CLK_STATUS_REG_ADDR'h3a
Definition: clocks393m.v:44
9867FFCLK1_DIFF_TERM"FALSE"
Definition: clocks393m.v:97
bufg_axi_aclk_i BUFG
Definition: clocks393m.v:203
9835CLK_STATUS1
Definition: clocks393m.v:46
11583locked
Definition: pll_base.v:80
9898ffclk1wire
Definition: clocks393m.v:136
9901cmd_wewire
Definition: clocks393m.v:139
9841CLKOUT_DIV_PCLK10
Definition: clocks393m.v:55
9900cmd_datawire[10:0]
Definition: clocks393m.v:138
9856MULTICLK_BUF_XCLK"BUFG"
Definition: clocks393m.v:82
9842BUF_CLK1X_PCLK"BUFG"
Definition: clocks393m.v:56
[7:0] 9931ad
Definition: cmd_deser.v:56
9913hclk_prewire
Definition: clocks393m.v:228
[ADDR_WIDTH-1:0] 9933addr
Definition: cmd_deser.v:58
9915xclk_prewire
Definition: clocks393m.v:230
9846MULTICLK_DIV_DLYREF6
Definition: clocks393m.v:68
status_generate_i status_generate
Definition: clocks393m.v:187
9853MULTICLK_PHASE_AXIHP0.0
Definition: clocks393m.v:79
9908test_clkreg[2:0]
Definition: clocks393m.v:147
9909memclk_rstwire
Definition: clocks393m.v:148
9916sync_clk_prewire
Definition: clocks393m.v:231
9854MULTICLK_BUF_AXIHP"BUFG"
Definition: clocks393m.v:80
9911ffclk1_rstwire
Definition: clocks393m.v:150
9910ffclk0_rstwire
Definition: clocks393m.v:149
9837CLK_PWDWN'h0
Definition: clocks393m.v:49
9868FFCLK1_IBUF_LOW_PWR"TRUE"
Definition: clocks393m.v:98
9917time_ref_rreg[2:0]
Definition: clocks393m.v:312
9863FFCLK0_DIFF_TERM"FALSE"
Definition: clocks393m.v:92
[ALL_BITS-1:0] 10777status
sync_clk_i select_clk_buf
Definition: clocks393m.v:277
11578clkout2
Definition: pll_base.v:75
9896memclkwire
Definition: clocks393m.v:134
[7:0] 9873cmd_ad
Definition: clocks393m.v:106
9869FFCLK1_IOSTANDARD"DEFAULT"
Definition: clocks393m.v:99
9859MEMCLK_CAPACITANCE"DONT_CARE"
Definition: clocks393m.v:87