📄 cal_ctl.v
字号:
/***************************************************************************
* 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; /* synthesis syn_keep = 1 */
output [4:0] tapForDqs; /* synthesis syn_keep = 1 */
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;
reg [7:0] ozShft;
reg [7:0] zoShft;
wire locReset;
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;
rstate <= `idleReset;
resetDcm <= 1'b1;
end else if ((hxSamp1 == 1'b0) && (prevSamp == 1'b1) ) begin
d0Shft[7:0] <= ozShft;
selTap[4:0] <= `tap2;
waitOneCycle <= 1'b1;
state <= `idleD1;
rstate <= `idleReset;
resetDcm <= 1'b1;
end else if ((hxSamp1 == 1'b0) && (prevSamp == 1'b0)) begin
// increment phase shift delay
psEn <= 1'b1;
psInc <= 1'b1;
state <= `waitDcmD0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -