📄 mem_interface_top_phy_calib_0.v
字号:
genvar dq_cnt_i3;
generate
for(dq_cnt_i3 = 0; dq_cnt_i3 < DQ_PER_DQS; dq_cnt_i3 = dq_cnt_i3 + 1)
begin: gen_dq_cnt3
always @(posedge clk90)begin
cal1_dlyinc_dq_cp3[dq_cnt_i3:dq_cnt_i3] <= 1'd0;
cal1_dlyinc_dq_cp3[dq_cnt_i3:dq_cnt_i3] <= 1'd0;
if (cal1_state_r1 == CAL1_DQ_DESKEW)begin
if(cal1_dq_count[(dq_cnt_i3 * 5)+4:dq_cnt_i3*5] > (MIN_WIN_SIZE))
begin
cal1_dlyce_dq_cp3[dq_cnt_i3:dq_cnt_i3] <= 1'd1;
cal1_dlyinc_dq_cp3[dq_cnt_i3:dq_cnt_i3] <= 1'd1;
cal1_dq_count_cp3[(dq_cnt_i3 * 5)+4:dq_cnt_i3*5] <=
cal1_dq_count[(dq_cnt_i3 * 5)+4:dq_cnt_i3*5] - 1'd1;
end
end
end
end // block: gen_dq_cnt3
endgenerate
//*****************************************************************
// keep track of the total taps used per byte. It accounts for DQS
// taps that are used in the first calibration and any dq tap that are
// used for deskew during first calibration ( dq taps are used here
// only if it is more than the dqs taps. The difference is added to
// the counter). Also add the increments done during the second
// calibration
//*****************************************************************
//synthesis attribute max_fanout of dqs_tap_count is 5
genvar dqs_cnt_i;
generate
for(dqs_cnt_i = 0; dqs_cnt_i < DQS_WIDTH; dqs_cnt_i = dqs_cnt_i + 1)
begin: gen_dqs_cnt
always @(posedge clk90)
if (cal1_dqs_count == dqs_cnt_i) begin
dqs_tap_count[(dqs_cnt_i*6)+5:dqs_cnt_i*6]
<= cal1_tp_count;
end
end
endgenerate
// assignment to the dqs_tap_count is pipelined for timing
always @(posedge clk90)
if((cal1_dq_deskew_count > cal1_dqs_inc_count)
&& (cal1_state_r1 == CAL1_DQ_RESET1))
cal1_tp_count <= cal1_dq_deskew_count;
else
cal1_tp_count <= cal1_dqs_inc_count;
// Extra register stages and pipeline for timing.
// Used in cal1 state machine
always @(posedge clk90) begin
dqs_tap_count_r1 <= dqs_tap_count;
cal1_dqs_count_r1 <= cal1_dqs_count;
cal1_dq_deskew_count_cp <= ((cal1_dqs_inc_count + cal1_dq_inc_count)
-MIN_WIN_SIZE);
cal1_dqs_count_check <= (cal1_dqs_count_r1 >= DQS_WIDTH-1);
cal1_detect_stable_r <= cal1_detect_stable;
end
//synthesis attribute max_fanout of cal1_detect_stable_r is 1
//synthesis attribute max_fanout of cal1_dqs_count is 3
//synthesis attribute max_fanout of cal1_dqs_count_r1 is 3
//synthesis attribute max_fanout of cal1_dqs_inc_count is 5
//synthesis attribute max_fanout of cal1_dq_inc_count is 5
//synthesis attribute max_fanout of cal1_dq_deskew_count is 2
//synthesis attribute max_fanout of cal1_dq_deskew_count_cp is 2
//synthesis attribute max_fanout of cal1_state is 5
//synthesis attribute max_fanout of cal1_state_r1 is 5
//synthesis attribute max_fanout of cal1_state_r2 is 5
// In simulation mode the first stage calibration is turned off.
always @(posedge clk90) begin
if (rst90) begin
//to avoid simulation issues when sim models have uncertainity
if(!SIM_ONLY)
calib_done[0] <= 1'b0;
else
calib_done[0] <= 1'b1;
cal1_data_chk_last <= {2*DQ_PER_DQS{1'bx}};
cal1_dlyce_dqs <= 1'bx;
cal1_dlyinc_dqs <= 1'bx;
cal1_dlyrst_dq <= 1'bx;
cal1_state <= CAL1_IDLE;
cal1_state_r1 <= CAL1_IDLE;
cal1_state_r2 <= CAL1_IDLE;
cal1_dqs_count <= {DQS_WIDTH{1'bx}};
cal1_dqs_inc_count <= {6{1'bx}};//cnt dqs inc
cal1_dq_inc_count <= {6{1'bx}};// total dq inc
cal1_dq_deskew_count <= {6{1'bx}};// dq deskew
end else begin
// default values for all "pulse" outputs
cal1_dlyce_dqs <= 1'd0;
cal1_dlyinc_dqs <= 1'd0;
cal1_dlyrst_dq <= 1'd0;
cal1_state_r1 <= cal1_state;
cal1_state_r2 <= cal1_state_r1;
case (cal1_state)
CAL1_IDLE: begin
cal1_dqs_count <= {DQS_WIDTH{1'b0}};
if (calib_start[0]) begin
if(!SIM_ONLY)// in sim mode avoid first stage calibration
cal1_state <= CAL1_INIT;
cal1_data_chk_last <= cal1_data_chk_r;
end
end
CAL1_INIT: begin
cal1_dq_inc_count <= 6'd0;
cal1_state <= CAL1_EDGE_DETECT;
end
// look for first edge
CAL1_EDGE_DETECT: begin
cal1_data_chk_last <= cal1_data_chk_r;
if((~|(cal1_detect_stable_r) && (cal1_window_cnt > 6'd0))) begin
cal1_state <= CAL1_DQ_RESET; // when no dq in valid window
end else if (|(cal1_detect_stable_r) || (cal1_stable_flag)) begin
cal1_dq_inc_count <= cal1_dq_inc_count + 1;
cal1_state <= CAL1_EDGE_DETECT_WAIT;
end
end
// wait for DQ IDELAY to settle
CAL1_EDGE_DETECT_WAIT: begin
if (!idel_set_wait) begin
cal1_state <= CAL1_EDGE_DETECT;
end
end
CAL1_DQS_INC:begin
if(cal1_dqs_inc_count> 6'd0)begin
cal1_dlyinc_dqs <= 1'd1;
cal1_dlyce_dqs <= 1'd1;
cal1_dqs_inc_count <= cal1_dqs_inc_count - 1;
end else
cal1_state <= CAL1_DQ_DESKEW;
end
CAL1_DQ_RESET: begin
cal1_dlyrst_dq <= 1'd1;
cal1_state <= CAL1_DQ_RESET1;
if(cal1_window_cnt < (MIN_WIN_SIZE-1))
cal1_dqs_inc_count <= (MIN_WIN_SIZE) - cal1_window_cnt;
else
cal1_dqs_inc_count <= 6'd0;
end
CAL1_DQ_RESET1: begin
cal1_dlyrst_dq <= 1'd1;
if(CLK_PERIOD < 3800)//deskew only for higer frequency
cal1_dq_deskew_count <= cal1_dq_deskew_count_cp;
else
cal1_dq_deskew_count <= 6'd0;
if(cal1_window_cnt_r1 >= (MIN_WIN_SIZE-1))
cal1_state <= CAL1_DQ_DESKEW;
else begin
cal1_state <= CAL1_DQS_INC;
end
end
CAL1_DQ_DESKEW: begin
if(cal1_dq_deskew_count > 0)
cal1_dq_deskew_count <= cal1_dq_deskew_count - 1'd1;
else
cal1_state <= CAL1_DONE;
end
CAL1_DONE:begin
if (!idel_set_wait) begin
if (cal1_dqs_count_check) begin
calib_done[0] <= 1'b1;
cal1_state <= CAL1_IDLE;
end else begin
cal1_state <= CAL1_INIT;
cal1_dqs_count <= cal1_dqs_count + 1;
end
end
end
endcase
end // else: !if(rst90)
end // always @ (posedge clk90)
//***************************************************************************
// Second stage calibration: DQS-FPGA Clock
// Algorithm Description:
// 1. Increment DQ and DQS IDEALY to find an edge
// 2. If edge found and and the window is >= MIN_WIN_SIZE, then
// position the DQS/DQ MIN_WIN_SIZE taps from the edge
// 3. If edge found and the window is < MIN_WIN_SIZE, then increment
// until the next edge is found.
// 3a. If next edge found, move (decrement) DQ/DQS by BIT_PERIOD_TAP
// + MIN_WIN_SIZE from the second edge. So that the DQ/DQS is
// positioned in the first half of the bit period
// 3b. If next edge not found and if the number of taps from the first
// edge is >= (BIT_PERIOD_TAP + MIN_WIN_SIZE), then move (decrement)
// DQ/DQS ((window_after_first_edge) - (BIT_PERIOD_TAP + MIN_WIN_SIZE))
// taps.
// 3c. If next edge not found and if the number of taps from the first edge
// edge is < (BIT_PERIOD_TAP + MIN_WIN_SIZE), then leave DQ/DQS at the
// current position.
// 4. Repeat for each DQS group.
//***************************************************************************
//*****************************************************************
// second stage calibration uses readback pattern of "1100" (i.e.
// 1st rising = 1, 1st falling = 1, 2nd rising = 0, 2nd falling = 0)
// only look at the first bit of each DQS group
//*****************************************************************
// register for timing purposes
always @(posedge clk90) begin
cal2_rd_data_fall_r <= rd_data_fall_r[cal2_dqs_count_r1*DQ_PER_DQS];
cal2_rd_data_rise_r <= rd_data_rise_r[cal2_dqs_count_r1*DQ_PER_DQS];
end
// deasserted when captured data has changed since IDELAY was
// incremented
assign cal2_detect_edge =
((cal2_rd_data_fall_r != cal2_rd_data_fall_last) ||
(cal2_rd_data_rise_r != cal2_rd_data_rise_last)) && cal2_rd_valid;
//*****************************************************************
//synthesis attribute max_fanout of cal2_dqs_count is 1
//synthesis attribute max_fanout of cal2_dqs_count_r1 is 3
//synthesis attribute max_fanout of cal2_tap_count is 5
//synthesis attribute max_fanout of cal2_tap_count_cp1 is 5
//synthesis attribute max_fanout of cal2_inc_count is 5
//synthesis attribute max_fanout of cal2_dec_count is 2
//synthesis attribute max_fanout of cal2_tap_count_index is 3
// cal2_tap_count_cp1 assignment is done here and it
// is assigned to the cal2_tap_count in the state
// machine. The index is calculation is pipelined
// for timing.
always @(posedge clk90) begin
cal2_tap_count_index <= cal2_dqs_count*6;
cal2_tap_count_cp1[0] <= dqs_tap_count_r1[cal2_tap_count_index];
cal2_tap_count_cp1[1] <= dqs_tap_count_r1[cal2_tap_count_index+1];
cal2_tap_count_cp1[2] <= dqs_tap_count_r1[cal2_tap_count_index+2];
cal2_tap_count_cp1[3] <= dqs_tap_count_r1[cal2_tap_count_index+3];
cal2_tap_count_cp1[4] <= dqs_tap_count_r1[cal2_tap_count_index+4];
cal2_tap_count_cp1[5] <= dqs_tap_count_r1[cal2_tap_count_index+5];
end
// Extra register stages and pipeline for timing.
// Used in cal2 state machine
always @(posedge clk90) begin
cal2_dec_count_c1 <= ((cal2_inc_count/2) - (MIN_WIN_SIZE-2));
if(cal2_inc_count > (BIT_PERIOD_TAPS + (MIN_WIN_SIZE-1)))
cal2_dec_count_c3 <= cal2_inc_count -
(BIT_PERIOD_TAPS + (MIN_WIN_SIZE-1));
else
cal2_dec_count_c3 <= cal2_inc_count/2;
cal2_detect_edge_r <= cal2_detect_edge;
cal2_dqs_count_r1 <= cal2_dqs_count;
cal2_dqs_count_check <= (cal2_dqs_count_r1 >= DQS_WIDTH-1);
end
//synthesis attribute max_fanout of cal2_state is 5
always @(posedge clk90) begin
if (rst90) begin
calib_done[1] <= 1'b0;
cal2_tap_count <= {6{1'bx}};// holds the total taps used
cal2_inc_count <= {6{1'bx}} ;// window cnt
cal2_dec_count <= {6{1'bx}};
cal2_inc_tap <= 1'd0;// flags for idelay
cal2_dec_tap <= 1'd0;// flags for idelay
cal2_first_edge_detect <= 1'd0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -