📄 cal_ctl.v
字号:
//*****************************************************************************************
//**
//** www.xilinx.com Copyright (c) 1984-2004 Xilinx, Inc. All rights reserved
//**
//** QDR(tm)-II SRAM Virtex(tm)-II Interface Verilog instanciation
//**
//*****************************************************************************************
//**
//** Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are
//** provided to you \"as is\". Xilinx and its licensors make and you
//** receive no warranties or conditions, express, implied, statutory
//** or otherwise, and Xilinx specifically disclaims any implied
//** warranties of merchantability, non-infringement, or fitness for a
//** particular purpose. Xilinx does not warrant that the functions
//** contained in these designs will meet your requirements, or that the
//** operation of these designs will be uninterrupted or error free, or
//** that defects in the Designs will be corrected. Furthermore, Xilinx
//** does not warrant or make any representations regarding use or the
//** results of the use of the designs in terms of correctness, accuracy,
//** reliability, or otherwise.
//**
//** LIMITATION OF LIABILITY. In no event will Xilinx or its licensors be
//** liable for any loss of data, lost profits, cost or procurement of
//** substitute goods or services, or for any special, incidental,
//** consequential, or indirect damages arising from the use or operation
//** of the designs or accompanying documentation, however caused and on
//** any theory of liability. This limitation will apply even if Xilinx
//** has been advised of the possibility of such damage. This limitation
//** shall apply not-withstanding the failure of the essential purpose of
//** any limited remedies herein.
//**
//*****************************************************************************************
// Implements the calibration technique. performs the following functions:
// 1. control circuit that determines each tap value
// 2. hold the total delay value of different taps.
// 3. determine the tap to use for a given frequency -> select the appropriate tap
`define idleSetup 4'b0000
`define idleD0 4'b0001
`define idleD1 4'b0010
`define idleD2 4'b0011
`define idleD3 4'b0100
`define idleD4 4'b0101
`define idleD5 4'b0110
`define waitSetup 4'b0111
`define waitDcmD0 4'b1000
`define waitDcmD1 4'b1001
`define waitDcmD2 4'b1010
`define waitDcmD3 4'b1011
`define waitDcmD4 4'b1100
`define waitDcmD5 4'b1101
`define idleDone 4'b1110
`define idleReset 1'b1
`define waitReset 1'b0
`define lBound 8'b0011_0010 // 1000ps, = 1000ps/20 taps.
`define uBound 8'b0101_0000 // 1600ps, = 1600ps/20 taps.
// `define lBound 8'b0001_0100 // for sims
// `define uBound 8'b0010_0000 // for sims
`define slipCnt 4'b1100
`define tap1 5'b00000
`define tap2 5'b10000
`define tap3 5'b11000
`define tap4 5'b11100
`define tap5 5'b11110
`define tap6 5'b11111
`define defaultTap `tap3
`timescale 1ns/100ps
module cal_ctl(
clk,
okToSelTap,
psDone,
reset,
hxSamp1,
phSamp1,
locReset,
selTap,
psEn,
psInc,
dcmlocked,
tapForDqs
);
input clk;
input dcmlocked;
input psDone;
input reset;
input hxSamp1;
input phSamp1;
input okToSelTap;
output locReset;
output psEn;
output psInc;
output [4:0] selTap;
output [4:0] tapForDqs;
reg psEn;
reg psInc;
reg [4:0] selTap;
reg [3:0] state;
reg [7:0] posPhShft;
reg [7:0] negPhShft;
reg prevSamp;
reg [7:0] d0Shft;
reg [7:0] d1Shft;
reg [7:0] d2Shft;
reg [7:0] d3Shft;
reg [7:0] d4Shft;
reg [7:0] d5Shft;
reg [7:0] suShft;
reg [4:0] tapForDqs;
reg waitOneCycle;
reg waitTwoCycle;
reg wait3Cycle;
reg wait4Cycle;
reg psDoneReg;
reg wait5Cycle;
reg [7:0] decPosSh;
reg [7:0] decNegSh;
reg rstate;
reg resetDcm;
reg [4:0] inTapForDqs;
reg [3:0] selCnt;
reg [4:0] newTap;
reg okSelCnt;
reg [3:0] midPt;
reg [2:0] uPtr;
reg [2:0] lPtr;
wire locReset;
reg [7:0] ozShft;
reg [7:0] zoShft;
assign locReset = (~reset && dcmlocked) ? 1'b0 : 1'b1;
always @(posedge clk) begin
if (reset) begin
ozShft[7:0] <= 8'h00;
zoShft[7:0] <= 8'h00;
end else begin
zoShft[7:0] <= suShft[7:0] - posPhShft[7:0];
ozShft[7:0] <= negPhShft[7:0]+ suShft[7:0];
end
end
// 1. divide clock by 2 since there is no way to get from clock net to D input.
// this is done outside in module cal_div2
// 2. register normal clock with phClkDiv2 twice to prvent metastability.
// done outside this block now.
// 3. at offset of 0 between clkDiv2 and phSamp1, set up time may not be met.
// increase the offset using phase shift to meet the set up time. the number of
// phase shifts required to meet set up is determined.
always @(posedge clk) begin
if (reset) begin
psEn <= 1'b0;
psInc <= 1'b0;
state <= `idleSetup;
prevSamp <= 1'b0;
posPhShft[7:0] <= 8'h00;
negPhShft[7:0] <= 8'h00;
d0Shft[7:0] <= 8'h00;
d1Shft[7:0] <= 8'h00;
d2Shft[7:0] <= 8'h00;
d3Shft[7:0] <= 8'h00;
d4Shft[7:0] <= 8'h00;
d5Shft[7:0] <= 8'h00;
suShft[7:0] <= 8'h00;
selTap[4:0] <= `tap1;
waitOneCycle <= 1'b1;
waitTwoCycle <= 1'b0;
wait3Cycle <= 1'b0;
wait4Cycle <= 1'b0;
wait5Cycle <= 1'b0;
psDoneReg <= 1'b0;
decPosSh[7:0] <= 8'h00;
decNegSh[7:0] <= 8'h00;
resetDcm <= 1'b0;
rstate <= `idleReset;
end else begin // if (reset)
psDoneReg <= psDone;
if (dcmlocked) begin
if (resetDcm) begin
if (rstate == `idleReset) begin
if (posPhShft[7:0] != decPosSh[7:0]) begin
psEn <= 1'b1;
psInc <= 1'b0;
decPosSh[7:0] <= decPosSh[7:0] + 1'b1;
rstate <= `waitReset;
end else if (negPhShft[7:0] != decNegSh[7:0]) begin
psEn <= 1'b1;
psInc <= 1'b1;
decNegSh[7:0] <= decNegSh[7:0] + 1'b1;
rstate <= `waitReset;
end else begin
resetDcm <= 1'b0;
posPhShft[7:0] <= 8'h00;
negPhShft[7:0] <= 8'h00;
decNegSh[7:0] <= 8'h00;
decPosSh[7:0] <= 8'h00;
end
end else if (rstate == `waitReset) begin
psEn <= 1'b0;
if (psDoneReg) rstate <= `idleReset;
else rstate <= `waitReset;
end
end else begin // if (resetDcm)
if (waitOneCycle) begin
waitOneCycle <= 1'b0;
waitTwoCycle <= 1'b1;
end else if (waitTwoCycle) begin
waitTwoCycle <= 1'b0;
wait3Cycle <= 1'b1;
end else if (wait3Cycle) begin
wait3Cycle <= 1'b0;
wait4Cycle <= 1'b1;
end else if (wait4Cycle) begin
wait4Cycle <= 1'b0;
wait5Cycle <= 1'b1;
end else if (wait5Cycle) begin
wait5Cycle <= 1'b0;
if (state == `idleSetup) prevSamp <= phSamp1;
else prevSamp <= hxSamp1;
end else begin
if (state == `idleSetup) begin
if ((phSamp1 == 1'b1) && (prevSamp == 1'b0))begin // 0 to 1 transition
suShft[7:0] <= posPhShft[7:0];
state <= `idleD0;
rstate <= `idleReset;
resetDcm <= 1'b1;
waitOneCycle <= 1'b1;
end else if ((phSamp1 == 1'b0) && (prevSamp == 1'b1)) begin // shd never happen
suShft[7:0] <= negPhShft[7:0];
state <= `idleD0;
rstate <= `idleReset;
resetDcm <= 1'b1;
waitOneCycle <= 1'b1;
end else if ((phSamp1 == 1'b0) && (prevSamp == 1'b0))begin
//increment shift
psEn <= 1'b1;
psInc <= 1'b1;
state <= `waitSetup;
prevSamp <= 1'b0;
end else if ((phSamp1 == 1'b1) && (prevSamp == 1'b1))begin
psEn <= 1'b1;
psInc <= 1'b0;
prevSamp <= 1'b1;
state <= `waitSetup;
end
end else if (state == `waitSetup)begin // if (state == `idleSetup)
psEn <= 1'b0;
if (psDoneReg) state <= `idleSetup;
end else if (state == `idleD0) begin
if ((hxSamp1 == 1'b1) && (prevSamp == 1'b0)) begin
d0Shft[7:0] <= zoShft;
selTap[4:0] <= `tap2;
waitOneCycle <= 1'b1;
state <= `idleD1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -