HITDAQ/FPGA_firmware/q_sys/synthesis/submodules/sequencer_m10.sv
2024-10-11 14:49:54 +02:00

1210 lines
55 KiB
Systemverilog

// (C) 2001-2019 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other
// software and tools, and its AMPP partner logic functions, and any output
// files from any of the foregoing (including device programming or simulation
// files), and any associated documentation or information are expressly subject
// to the terms and conditions of the Intel Program License Subscription
// Agreement, Intel FPGA IP License Agreement, or other applicable
// license agreement, including, without limitation, that your use is for the
// sole purpose of programming logic devices manufactured by Intel and sold by
// Intel or its authorized distributors. Please refer to the applicable
// agreement for further details.
// ******
// sequencer_m10
// ******
//
// Max10 RTL Sequencer
//
// General Description
// -------------------
//
// This component replaces the NIOS to calibrate Max10 EMIF
// Max10 EMIF uses PLL clock to capture DQ data
//
//
`timescale 1 ps / 1 ps
module sequencer_m10 #
( parameter
AVL_DATA_WIDTH = 32,
AVL_ADDR_WIDTH = 20,
READ_VALID_FIFO_SIZE = 16,
HPS_PROTOCOL = "DDR3",
PHY_MGR_BASE = 294912,
RW_MGR_BASE = 327680,
PLL_MGR_BASE = 360448,
MEM_DQ_WIDTH = 24
)
(
clk,
reset_n,
address,
write,
writedata,
read,
readdata,
waitrequest,
pd_reset_n,
pd_ack,
pd_up,
pd_down
);
localparam PRE_N_ACT_1 = (HPS_PROTOCOL == "DDR3") ? 'h14 : ((HPS_PROTOCOL == "DDR2") ? 'h16 : 'h14);
localparam PRE_N_ACT_2 = (HPS_PROTOCOL == "DDR3") ? 'hf : ((HPS_PROTOCOL == "DDR2") ? 'hf : 'hf );
localparam PRE_N_ACT_3 = (HPS_PROTOCOL == "DDR3") ? 'h10 : ((HPS_PROTOCOL == "DDR2") ? 'h12 : 'h10);
localparam PRE_N_ACT_4 = (HPS_PROTOCOL == "DDR3") ? 'hf : ((HPS_PROTOCOL == "DDR2") ? 'hf : 'hf );
localparam PRE_N_ACT_5 = (HPS_PROTOCOL == "DDR3") ? 'h12 : ((HPS_PROTOCOL == "DDR2") ? 'h14 : 'h12);
localparam PRE_N_ACT_6 = (HPS_PROTOCOL == "DDR3") ? 'hf : ((HPS_PROTOCOL == "DDR2") ? 'h11 : 'hf );
localparam GRNTEE_WR_1 = (HPS_PROTOCOL == "DDR3") ? 'h20 : ((HPS_PROTOCOL == "DDR2") ? 'h20 : 'h20);
localparam GRNTEE_WR_2 = (HPS_PROTOCOL == "DDR3") ? 'h1c : ((HPS_PROTOCOL == "DDR2") ? 'h1d : 'h19);
localparam GRNTEE_WR_3 = (HPS_PROTOCOL == "DDR3") ? 'h20 : ((HPS_PROTOCOL == "DDR2") ? 'h20 : 'h20);
localparam GRNTEE_WR_4 = (HPS_PROTOCOL == "DDR3") ? 'h20 : ((HPS_PROTOCOL == "DDR2") ? 'h21 : 'h1d);
localparam GRNTEE_WR_5 = (HPS_PROTOCOL == "DDR3") ? 'h2 : ((HPS_PROTOCOL == "DDR2") ? 'h2 : 'h2 );
localparam GRNTEE_WR_6 = (HPS_PROTOCOL == "DDR3") ? 'h1a : ((HPS_PROTOCOL == "DDR2") ? 'h1b : 'h17);
localparam GRNTEE_WR_7 = (HPS_PROTOCOL == "DDR3") ? 'h2 : ((HPS_PROTOCOL == "DDR2") ? 'h2 : 'h2 );
localparam GRNTEE_WR_8 = (HPS_PROTOCOL == "DDR3") ? 'h1e : ((HPS_PROTOCOL == "DDR2") ? 'h1f : 'h1b);
localparam GRNTEE_WR_9 = (HPS_PROTOCOL == "DDR3") ? 'h19 : ((HPS_PROTOCOL == "DDR2") ? 'h1a : 'h16);
localparam READ_CHK_1 = (HPS_PROTOCOL == "DDR3") ? 'h10 : ((HPS_PROTOCOL == "DDR2") ? 'h10 : 'h10);
localparam READ_CHK_2 = (HPS_PROTOCOL == "DDR3") ? 'h45 : ((HPS_PROTOCOL == "DDR2") ? 'h46 : 'h42);
localparam READ_CHK_3 = (HPS_PROTOCOL == "DDR3") ? 'h10 : ((HPS_PROTOCOL == "DDR2") ? 'h10 : 'h10);
localparam READ_CHK_4 = (HPS_PROTOCOL == "DDR3") ? 'h4b : ((HPS_PROTOCOL == "DDR2") ? 'h4c : 'h48);
localparam READ_CHK_5 = (HPS_PROTOCOL == "DDR3") ? 'h1 : ((HPS_PROTOCOL == "DDR2") ? 'h1 : 'h1 );
localparam READ_CHK_6 = (HPS_PROTOCOL == "DDR3") ? 'h41 : ((HPS_PROTOCOL == "DDR2") ? 'h42 : 'h3e);
localparam READ_CHK_7 = (HPS_PROTOCOL == "DDR3") ? 'h1 : ((HPS_PROTOCOL == "DDR2") ? 'h1 : 'h1 );
localparam READ_CHK_8 = (HPS_PROTOCOL == "DDR3") ? 'h41 : ((HPS_PROTOCOL == "DDR2") ? 'h42 : 'h3e);
localparam READ_CHK_9 = (HPS_PROTOCOL == "DDR3") ? 'h0 : ((HPS_PROTOCOL == "DDR2") ? 'h0 : 'h0 );
localparam READ_CHK_10 = (HPS_PROTOCOL == "DDR3") ? 'h41 : ((HPS_PROTOCOL == "DDR2") ? 'h42 : 'h3e);
localparam READ_CHK_11 = (HPS_PROTOCOL == "DDR3") ? 'h3e : ((HPS_PROTOCOL == "DDR2") ? 'h3f : 'h3b);
localparam READ_LATENCY = 5'h16;
localparam DISABLE_FILTER = 1'b0;
localparam DISABLE_PD = 1'b0;
input clk;
input reset_n;
output [AVL_ADDR_WIDTH - 1:0] address;
output write;
output [AVL_DATA_WIDTH - 1:0] writedata;
output read;
input [AVL_DATA_WIDTH - 1:0] readdata;
input waitrequest;
output pd_reset_n;
output pd_ack;
input pd_up;
input pd_down;
logic [AVL_ADDR_WIDTH - 1:0] address;
logic write;
logic [AVL_DATA_WIDTH - 1:0] writedata;
logic read;
logic pd_reset_n;
logic pd_ack;
logic [5:0] seq_state;
logic [AVL_ADDR_WIDTH - 1:0] main_address;
logic main_write;
logic [AVL_DATA_WIDTH - 1:0] main_writedata;
logic main_read;
logic [23:0] readdata_reg;
logic [23:0] best_comp_result;
logic data_mismatch;
logic [2:0] vfifo;
logic [7:0] count;
logic [7:0] valid_phase;
logic reverse;
logic finding_window;
logic window_found;
logic latency_calib;
logic [1:0] grp;
logic start_ddr3_init;
logic ddr3_init_done;
logic start_ddr2_init;
logic ddr2_init_done;
logic start_lpddr2_init;
logic lpddr2_init_done;
logic start_write;
logic write_done;
logic start_user_mr;
logic user_mr_done;
logic pd_start;
logic cal_init_req;
logic wr_and_not_waitrequest;
assign wr_and_not_waitrequest = main_write & ~waitrequest;
always_ff @(posedge clk, negedge reset_n)
begin
if (!reset_n)
begin
seq_state <= 0;
main_address <= '0;
main_write <= 0;
main_writedata <= '0;
main_read <= 0;
readdata_reg <= '0;
best_comp_result <= '0;
data_mismatch <= 0;
vfifo <= '0;
count <= 0;
valid_phase <= 0;
reverse <= 0;
finding_window <= 0;
window_found <= 0;
latency_calib <= 0;
start_ddr3_init <= 0;
start_ddr2_init <= 0;
start_lpddr2_init <= 0;
start_write <= 0;
start_user_mr <= 0;
pd_start <= 0;
grp <= '0;
end
else
case(seq_state)
0 :
begin
best_comp_result <= {24{1'b1}};
if (HPS_PROTOCOL == "DDR3")
seq_state <= 1;
else if (HPS_PROTOCOL == "DDR2")
seq_state <= 2;
else // LPDDR2
seq_state <= 3;
end
// start DDR3 initialization sequence
1 :
begin
start_ddr3_init <= 1;
if (ddr3_init_done)
begin
start_ddr3_init <= 0;
seq_state <= 4;
end
end
// end of DDR3 initialization sequence
// start DDR2 initialization sequence
2 :
begin
start_ddr2_init <= 1;
if (ddr2_init_done)
begin
start_ddr2_init <= 0;
seq_state <= 4;
end
end
// end of DDR2 initialization sequence
// start LPDDR2 initialization sequence
3 :
begin
start_lpddr2_init <= 1;
if (lpddr2_init_done)
begin
start_lpddr2_init <= 0;
seq_state <= 4;
end
end
// end of LPDDR2 initialization sequence
// precharge and activate then guarantee write
4 :
begin
start_write <= 1;
if (write_done)
begin
start_write <= 0;
seq_state <= 5;
end
end
// read data checking routine
5 : write_task_rw ('h201 ,READ_CHK_1 ,6 );
6 : write_task_rw ('h301 ,READ_CHK_2 ,7 );
7 : write_task_rw ('h202 ,READ_CHK_3 ,8 );
8 : write_task_rw ('h302 ,READ_CHK_4 ,9 );
9 : write_task_rw ('h200 ,READ_CHK_5 ,10 );
10 : write_task_rw ('h300 ,READ_CHK_6 ,11 );
11 : write_task_rw ('h203 ,READ_CHK_7 ,12 );
12 : write_task_rw ('h303 ,READ_CHK_8 ,13 );
13 : write_task_ph ('h2 ,'h0 ,14 ); // PHY manager, read fifo reset
14 : write_task_rw ('h400 ,READ_CHK_9 ,15 );
15 : write_task_rw (grp ,READ_CHK_10 ,16 );
16 :
begin
main_read <= 1;
main_address <= RW_MGR_BASE[AVL_ADDR_WIDTH - 1:0];//
if (main_read && !waitrequest)
begin
main_read <= 0;
main_address <= '0;
seq_state <= 38;
if (grp == 2)
readdata_reg[23:16] <= readdata[7:0];
else if (grp == 1)
readdata_reg[15:8] <= readdata[7:0];
else
readdata_reg[7:0] <= readdata[7:0];
end
end
38 :
begin
if (MEM_DQ_WIDTH == 24)
begin
if (grp == 2)
begin
grp <= 0;
seq_state <= 17;
end
else
begin
grp <= grp + 1'b1;
seq_state <= 5;
end
end
else if (MEM_DQ_WIDTH == 16)
begin
if (grp == 1)
begin
grp <= 0;
seq_state <= 17;
end
else
begin
grp <= grp + 1'b1;
seq_state <= 5;
end
end
else
seq_state <= 17;
end
17 : write_task_rw ('h0 ,READ_CHK_11 ,18 );
18 :
begin
if (readdata_reg != 0)
data_mismatch <= 1;
else
data_mismatch <= 0;
if (readdata_reg[23:16] < best_comp_result[23:16])
best_comp_result[23:16] <= readdata_reg[23:16];
if (readdata_reg[15:8] < best_comp_result[15:8])
best_comp_result[15:8] <= readdata_reg[15:8];
if (readdata_reg[7:0] < best_comp_result[7:0])
best_comp_result[7:0] <= readdata_reg[7:0];
if (latency_calib)
seq_state <= 29;
else if (finding_window)
seq_state <= 26;
else if (reverse)
seq_state <= 24;
else
seq_state <= 19;
end
// end read data checking routine
// find first working phase
19 :
begin
if (data_mismatch) // data mismatch
begin
if (count == 150) // 57x2 is the calculated steps for 167Mhz
seq_state <= 22; // give up, fail calibration
else if (vfifo == 7) // increment PLL phase
begin
write_task_capture_clock (1 ,20 );
if (wr_and_not_waitrequest)
count <= count + 1'b1;
end
else
seq_state <= 20;
end
else // data match! then reverse phase
begin
$display(" --- SEQUENCER FOUND FIRST WORKING PHASE --- ");
reverse <= 1;
seq_state <= 5 ;
end
end
20 :
begin
vfifo <= vfifo + 1'b1;
seq_state <= 21;
end
21 : write_task_ph ('h1 ,'hff ,5 ); // increment vfifo for all groups
// algorithm ends here
// PHY manager, cal fail
22 : write_task_ph ('h1003 ,'h2 ,36 );
// reverse phase until fail, useful if already in a working phase on start
24 :
begin
if (data_mismatch) //data mismatch, increment and move to finding window
begin
reverse <= 0;
write_task_capture_clock (1 ,25 );
end
else // data match, decrement until it fails
write_task_capture_clock (0 ,5 );
end
// finding window, sweep till fail
25 :
begin
$display(" --- START FINDING WINDOW --- ");
finding_window <= 1;
count <= 1;
seq_state <= 5 ;
end
26 :
begin
if (data_mismatch) // data mismatch
begin
if (!window_found)
write_task_capture_clock (1 ,5 );
else
begin
$display(" --- TOTAL VALID PHASE %d --- ",count - 1);
valid_phase <= count-1'b1;
finding_window <= 0;
count <= count/2'd2; // formula to move the correct number of phase
$display(" --- REVERSE TO CENTER %d PHASE(S)--- ",((count - 2)/2)+2);
seq_state <= 27;
end
end
else
begin
window_found <= 1;
write_task_capture_clock (1 ,5 ); // increment PLL phase
if (wr_and_not_waitrequest)
count <= count+1'b1;
end
end
// going to the center of window after sweep
27 :
begin
if (count != 0)
begin
write_task_capture_clock (0 ,27 ); // decrement PLL phase
if (wr_and_not_waitrequest)
count <= count-1'b1;
end
else
seq_state <= 31;
end
// calibration done
31 : write_task_rw ('h0 ,PRE_N_ACT_1 ,32 ); // precharge
32 : write_task_ph ('h2 ,'h0 ,33 ); // PHY manager, read fifo reset
33 :
begin
start_user_mr <= 1;
if (user_mr_done)
begin
start_user_mr <= 0;
seq_state <= 34;
end
end
// PHY manager, mux sel
34 : write_task_ph ('h1002 ,'h0 ,35 );
// PHY manager, cal success
35 : write_task_ph ('h1003 ,'h1 ,36 );
// PHY manager, debug info reports window size, best comparison data
36 : write_task_ph ('h1004 ,{best_comp_result,valid_phase} ,37 );
// calibration done
37 :
begin
if (pd_start && cal_init_req)
begin
pd_start <= 0;
seq_state <= 39;
readdata_reg <= '0;
best_comp_result <= '0;
data_mismatch <= 0;
vfifo <= '0;
count <= 0;
valid_phase <= 0;
reverse <= 0;
finding_window <= 0;
window_found <= 0;
latency_calib <= 0;
grp <= '0;
end
else
begin
pd_start <= 1;
end
end
39 : write_task_ph ('h1003 ,'h0 ,40 );
40 : write_task_ph ('h1002 ,'h1 ,0 );
endcase
end
task write_task_rw;
input [AVL_ADDR_WIDTH - 1:0] task_address;
input [AVL_DATA_WIDTH - 1:0] data;
input [5:0] next_state;
begin
main_write <= 1;
main_address <= RW_MGR_BASE[AVL_ADDR_WIDTH - 1:0] + {task_address[AVL_ADDR_WIDTH - 3:0],2'b0};
main_writedata <= data;
if (wr_and_not_waitrequest)
begin
main_write <= 0;
main_address <= '0;
main_writedata <= '0;
seq_state <= next_state;
end
end
endtask
task write_task_ph;
input [AVL_ADDR_WIDTH - 1:0] task_address;
input [AVL_DATA_WIDTH - 1:0] data;
input [5:0] next_state;
begin
main_write <= 1;
main_address <= PHY_MGR_BASE[AVL_ADDR_WIDTH - 1:0] + {task_address[AVL_ADDR_WIDTH - 3:0],2'b0};
main_writedata <= data;
if (wr_and_not_waitrequest)
begin
main_write <= 0;
main_address <= '0;
main_writedata <= '0;
seq_state <= next_state;
end
end
endtask
task write_task_capture_clock;
input data;
input [5:0] next_state;
begin
main_write <= 1;
main_address <= PLL_MGR_BASE[AVL_ADDR_WIDTH - 1:0];
main_writedata <= data;
if (wr_and_not_waitrequest)
begin
main_write <= 0;
main_address <= '0;
main_writedata <= '0;
seq_state <= next_state;
end
end
endtask
logic [4:0] ddr3_init_state;
logic [AVL_ADDR_WIDTH - 1:0] ddr3_init_address;
logic ddr3_init_write;
logic [AVL_DATA_WIDTH - 1:0] ddr3_init_writedata;
generate
if (HPS_PROTOCOL == "DDR3")
begin
task ddr3_init_write_task_rw;
input [AVL_ADDR_WIDTH - 1:0] task_address;
input [AVL_DATA_WIDTH - 1:0] data;
input [4:0] next_state;
begin
ddr3_init_write <= 1;
ddr3_init_address <= RW_MGR_BASE[AVL_ADDR_WIDTH - 1:0] + {task_address[AVL_ADDR_WIDTH - 3:0],2'b0};
ddr3_init_writedata <= data;
if (ddr3_init_write && !waitrequest)
begin
ddr3_init_write <= 0;
ddr3_init_address <= '0;
ddr3_init_writedata <= '0;
ddr3_init_state <= next_state;
end
end
endtask
always_ff @(posedge clk, negedge reset_n)
begin
if (!reset_n)
begin
ddr3_init_state <= 0;
ddr3_init_done <= 0;
ddr3_init_address <= '0;
ddr3_init_write <= 0;
ddr3_init_writedata <= '0;
end
else
case(ddr3_init_state)
0 : if (start_ddr3_init) ddr3_init_state <= 1;
// start DDR3 initialization sequence
// address data next_state
1 : ddr3_init_write_task_rw ('h800 ,'h0 ,2 );
2 : ddr3_init_write_task_rw ('h500 ,'hfe ,3 );
3 : ddr3_init_write_task_rw ('h500 ,'h0 ,4 );
4 : ddr3_init_write_task_rw ('h200 ,'hff ,5 );
5 : ddr3_init_write_task_rw ('h201 ,'hff ,6 );
6 : ddr3_init_write_task_rw ('h300 ,'h4f ,7 );
7 : ddr3_init_write_task_rw ('h301 ,'h50 ,8 );
8 : ddr3_init_write_task_rw ('h0 ,'h4f ,9 ); // delay?
9 : ddr3_init_write_task_rw ('h200 ,'hff ,10 );
10 : ddr3_init_write_task_rw ('h201 ,'hff ,11 );
11 : ddr3_init_write_task_rw ('h300 ,'h54 ,12 );
12 : ddr3_init_write_task_rw ('h301 ,'h55 ,13 );
13 : ddr3_init_write_task_rw ('h0 ,'h54 ,14 ); // reset goes high
14 : ddr3_init_write_task_rw ('h201 ,'h7c ,15 );
15 : ddr3_init_write_task_rw ('h301 ,'h5c ,16 );
16 : ddr3_init_write_task_rw ('h0 ,'h5c ,17 ); /// cke goes high
17 : ddr3_init_write_task_rw ('h0 ,'h7 ,18 ); // MR bank 2
18 : ddr3_init_write_task_rw ('h0 ,'h9 ,19 ); // MR bank 3
19 : ddr3_init_write_task_rw ('h0 ,'h5 ,20 ); // MR bank 1
20 : ddr3_init_write_task_rw ('h0 ,'h3 ,21 ); // DLL reset
21 : ddr3_init_write_task_rw ('h0 ,'hb ,22 ); // ZQ cal
// end of DDR3 initialization sequence
22 :
begin
if (cal_init_req)
begin
ddr3_init_done <= 0;
ddr3_init_state <= 0;
end
else
ddr3_init_done <= 1;
end
endcase
end
end
else
begin
assign ddr3_init_done = 0;
assign ddr3_init_address = '0;
assign ddr3_init_write = 0;
assign ddr3_init_writedata = '0;
end
endgenerate
logic [4:0] ddr2_init_state;
logic [AVL_ADDR_WIDTH - 1:0] ddr2_init_address;
logic ddr2_init_write;
logic [AVL_DATA_WIDTH - 1:0] ddr2_init_writedata;
logic [6:0] count2;
generate
if (HPS_PROTOCOL == "DDR2")
begin
task ddr2_init_write_task_rw;
input [AVL_ADDR_WIDTH - 1:0] task_address;
input [AVL_DATA_WIDTH - 1:0] data;
input [4:0] next_state;
begin
ddr2_init_write <= 1;
ddr2_init_address <= RW_MGR_BASE[AVL_ADDR_WIDTH - 1:0] + {task_address[AVL_ADDR_WIDTH - 3:0],2'b0};
ddr2_init_writedata <= data;
if (ddr2_init_write && !waitrequest)
begin
ddr2_init_write <= 0;
ddr2_init_address <= '0;
ddr2_init_writedata <= '0;
ddr2_init_state <= next_state;
end
end
endtask
always_ff @(posedge clk, negedge reset_n)
begin
if (!reset_n)
begin
ddr2_init_state <= 0;
ddr2_init_done <= 0;
ddr2_init_address <= '0;
ddr2_init_write <= 0;
ddr2_init_writedata <= '0;
count2 <= '0;
end
else
case(ddr2_init_state)
0 : if (start_ddr2_init) ddr2_init_state <= 1;
// start DDR2 initialization sequence
// address data next_state
1 : ddr2_init_write_task_rw ('h800 ,'h0 ,2 );
2 : ddr2_init_write_task_rw ('h500 ,'hfe ,3 );
3 : ddr2_init_write_task_rw ('h200 ,'hff ,4 );
4 : ddr2_init_write_task_rw ('h201 ,'hff ,5 );
5 : ddr2_init_write_task_rw ('h300 ,'h50 ,6 );
6 : ddr2_init_write_task_rw ('h301 ,'h51 ,7 );
7 : ddr2_init_write_task_rw ('h0 ,'h50 ,8 ); // delay?
8 : ddr2_init_write_task_rw ('h0 ,'h1 ,22 ); // CKE goes high
22 :
begin
if (count2 == 100)
begin
ddr2_init_state <= 9;
count2 <= 0;
end
else
count2 <= count2 + 1'b1;
end
9 : ddr2_init_write_task_rw ('h0 ,'h16 ,10 ); // precharge
10 : ddr2_init_write_task_rw ('h0 ,'hd ,11 ); // MR bank 2
11 : ddr2_init_write_task_rw ('h0 ,'hf ,12 ); // MR bank 3
12 : ddr2_init_write_task_rw ('h0 ,'h9 ,13 ); // MR bank 1
13 : ddr2_init_write_task_rw ('h0 ,'h7 ,14 ); // MR bank 0
14 : ddr2_init_write_task_rw ('h0 ,'h16 ,15 ); // precharge
15 : ddr2_init_write_task_rw ('h0 ,'h18 ,16 ); // refresh
16 :
begin
if (count2 == 100)
begin
ddr2_init_state <= 17;
count2 <= 0;
end
else
count2 <= count2 + 1'b1;
end
17 : ddr2_init_write_task_rw ('h0 ,'h18 ,23 ); // refresh
23 :
begin
if (count2 == 100)
begin
ddr2_init_state <= 18;
count2 <= 0;
end
else
count2 <= count2 + 1'b1;
end
18 : ddr2_init_write_task_rw ('h0 ,'h5 ,19 ); // MR bank 0
19 : ddr2_init_write_task_rw ('h0 ,'hb ,20 ); // MR bank 1
20 : ddr2_init_write_task_rw ('h0 ,'h9 ,21 ); // MR bank 1
// end of DDR2 initialization sequence
21 :
begin
if (cal_init_req)
begin
ddr2_init_done <= 0;
ddr2_init_state <= 0;
end
else
ddr2_init_done <= 1;
end
endcase
end
end
else
begin
assign ddr2_init_done = 0;
assign ddr2_init_address = '0;
assign ddr2_init_write = 0;
assign ddr2_init_writedata = '0;
end
endgenerate
logic [3:0] lpddr2_init_state;
logic [AVL_ADDR_WIDTH - 1:0] lpddr2_init_address;
logic lpddr2_init_write;
logic [AVL_DATA_WIDTH - 1:0] lpddr2_init_writedata;
logic [7:0] count4;
logic [7:0] count5;
generate
if (HPS_PROTOCOL == "LPDDR2")
begin
task lpddr2_init_write_task_rw;
input [AVL_ADDR_WIDTH - 1:0] task_address;
input [AVL_DATA_WIDTH - 1:0] data;
input [3:0] next_state;
begin
lpddr2_init_write <= 1;
lpddr2_init_address <= RW_MGR_BASE[AVL_ADDR_WIDTH - 1:0] + {task_address[AVL_ADDR_WIDTH - 3:0],2'b0};
lpddr2_init_writedata <= data;
if (lpddr2_init_write && !waitrequest)
begin
lpddr2_init_write <= 0;
lpddr2_init_address <= '0;
lpddr2_init_writedata <= '0;
lpddr2_init_state <= next_state;
end
end
endtask
always_ff @(posedge clk, negedge reset_n)
begin
if (!reset_n)
begin
lpddr2_init_state <= 0;
lpddr2_init_done <= 0;
lpddr2_init_address <= '0;
lpddr2_init_write <= 0;
lpddr2_init_writedata <= '0;
count4 <= '0;
count5 <= '0;
end
else
case(lpddr2_init_state)
0 : if (start_lpddr2_init) lpddr2_init_state <= 1;
// start LPDDR2 initialization sequence
// address data next_state
1 : lpddr2_init_write_task_rw ('h800 ,'h0 ,2 );
2 : lpddr2_init_write_task_rw ('h500 ,'hfe ,3 );
3 : lpddr2_init_write_task_rw ('h200 ,'h10 ,4 );
4 : lpddr2_init_write_task_rw ('h300 ,'h4c ,15 );
15 :
begin
if (&count4)
begin
count4 <= 0;
if (&count5)
begin
count5 <= 0;
lpddr2_init_state <= 5;
end
else
count5 <= count5 + 1'b1;
end
else
count4 <= count4 + 1'b1;
end
5 : lpddr2_init_write_task_rw ('h0 ,'h4c ,12 ); // CKE goes high
12 : //200us delay
begin
if (&count4)
begin
count4 <= 0;
if (&count5)
begin
lpddr2_init_state <= 6;
count5 <= 0;
end
else
count5 <= count5 + 1'b1;
end
else
count4 <= count4 + 1'b1;
end
6 : lpddr2_init_write_task_rw ('h0 ,'hd ,13 ); // MRW reset
13 : //10us delay
begin
if (count4 == 100)
begin
count4 <= 0;
if (count5 == 10)
begin
lpddr2_init_state <= 7;
count5 <= 0;
end
else
count5 <= count5 + 1'b1;
end
else
count4 <= count4 + 1'b1;
end
7 : lpddr2_init_write_task_rw ('h0 ,'hb ,14 ); // MRW MR10 ZQcal FF
14 : //1us delay
begin
if (count4 == 100)
begin
lpddr2_init_state <= 8;
count4 <= 0;
end
else
count4 <= count4 + 1'b1;
end
8 : lpddr2_init_write_task_rw ('h0 ,'h3 ,9 ); // MRW MR1
9 : lpddr2_init_write_task_rw ('h0 ,'h7 ,10 ); // MRW MR2
10 : lpddr2_init_write_task_rw ('h0 ,'h9 ,11 ); // MRW MR3
// end of LPDDR2 initialization sequence
11 :
begin
if (cal_init_req)
begin
lpddr2_init_done <= 0;
lpddr2_init_state <= 0;
end
else
lpddr2_init_done <= 1;
end
endcase
end
end
else
begin
assign lpddr2_init_done = 0;
assign lpddr2_init_address = '0;
assign lpddr2_init_write = 0;
assign lpddr2_init_writedata = '0;
end
endgenerate
logic [4:0] write_state;
logic [AVL_ADDR_WIDTH - 1:0] write_address;
logic write_write;
logic [AVL_DATA_WIDTH - 1:0] write_writedata;
logic [8:0] count3;
always_ff @(posedge clk, negedge reset_n)
begin
if (!reset_n)
begin
write_state <= 0;
write_done <= 0;
write_address <= '0;
write_write <= 0;
write_writedata <= '0;
count3 <= '0;
end
else
case(write_state)
0 : if (start_write) write_state <= 1;
// precharge and activate
1 :
begin
if (&count3)
begin
write_state <= 2;
count3 <= 0;
end
else
count3 <= count3 + 1'b1;
end
2 : write_write_task_rw ('h0 ,PRE_N_ACT_1 ,3 );
3 : write_write_task_rw ('h200 ,PRE_N_ACT_2 ,4 );
4 : write_write_task_rw ('h300 ,PRE_N_ACT_3 ,5 );
5 : write_write_task_rw ('h201 ,PRE_N_ACT_4 ,6 );
6 : write_write_task_rw ('h301 ,PRE_N_ACT_5 ,7 );
7 : write_write_task_rw ('h0 ,PRE_N_ACT_6 ,8 );
// guaranteed write
8 : write_write_task_rw ('h200 ,GRNTEE_WR_1 ,9 );
9 : write_write_task_rw ('h300 ,GRNTEE_WR_2 ,10 );
10 : write_write_task_rw ('h201 ,GRNTEE_WR_3 ,11 );
11 : write_write_task_rw ('h301 ,GRNTEE_WR_4 ,12 );
12 : write_write_task_rw ('h202 ,GRNTEE_WR_5 ,13 );
13 : write_write_task_rw ('h302 ,GRNTEE_WR_6 ,14 );
14 : write_write_task_rw ('h203 ,GRNTEE_WR_7 ,15 );
15 : write_write_task_rw ('h303 ,GRNTEE_WR_8 ,16 );
16 : write_write_task_rw ('h0 ,GRNTEE_WR_9 ,17 );
17 :
begin
if (cal_init_req)
begin
write_done <= 0;
write_state <= 0;
end
else
write_done <= 1;
end
endcase
end
task write_write_task_rw;
input [AVL_ADDR_WIDTH - 1:0] task_address;
input [AVL_DATA_WIDTH - 1:0] data;
input [4:0] next_state;
begin
write_write <= 1;
write_address <= RW_MGR_BASE[AVL_ADDR_WIDTH - 1:0] + {task_address[AVL_ADDR_WIDTH - 3:0],2'b0};
write_writedata <= data;
if (write_write && !waitrequest)
begin
write_write <= 0;
write_address <= '0;
write_writedata <= '0;
write_state <= next_state;
end
end
endtask
logic [3:0] user_mr_state;
logic [AVL_ADDR_WIDTH - 1:0] user_mr_address;
logic user_mr_write;
logic [AVL_DATA_WIDTH - 1:0] user_mr_writedata;
always_ff @(posedge clk, negedge reset_n)
begin
if (!reset_n)
begin
user_mr_state <= 0;
user_mr_done <= 0;
user_mr_address <= '0;
user_mr_write <= 0;
user_mr_writedata <= '0;
end
else
case(user_mr_state)
0 : if (start_user_mr) user_mr_state <= 1;
// precharge and activate
1 :
begin
if (HPS_PROTOCOL == "DDR3")
user_mr_state <= 2;
else if (HPS_PROTOCOL == "DDR2")
user_mr_state <= 7;
else // LPDDR2
user_mr_state <= 11;
end
// DDR3 user MR start
2 : user_mr_write_task_rw ('h0 ,'h14 ,3 );
3 : user_mr_write_task_rw ('h0 ,'h7 ,4 );
4 : user_mr_write_task_rw ('h0 ,'h9 ,5 );
5 : user_mr_write_task_rw ('h0 ,'h5 ,6 );
6 : user_mr_write_task_rw ('h0 ,'hd ,14 );
// DDR3 user MR ends
// DDR2 user MR start
7 : user_mr_write_task_rw ('h0 ,'hd ,8 );
8 : user_mr_write_task_rw ('h0 ,'hf ,9 );
9 : user_mr_write_task_rw ('h0 ,'h9 ,10 );
10 : user_mr_write_task_rw ('h0 ,'h3 ,14 );
// DDR2 user MR ends
// LPDDR2 user MR start
11 : user_mr_write_task_rw ('h0 ,'h5 ,12 );
12 : user_mr_write_task_rw ('h0 ,'h7 ,13 );
13 : user_mr_write_task_rw ('h0 ,'h9 ,14 );
// LPDDR2 user MR ends
14 :
begin
if (cal_init_req)
begin
user_mr_done <= 0;
user_mr_state <= 0;
end
else
user_mr_done <= 1;
end
endcase
end
task user_mr_write_task_rw;
input [AVL_ADDR_WIDTH - 1:0] task_address;
input [AVL_DATA_WIDTH - 1:0] data;
input [3:0] next_state;
begin
user_mr_write <= 1;
user_mr_address <= RW_MGR_BASE[AVL_ADDR_WIDTH - 1:0] + {task_address[AVL_ADDR_WIDTH - 3:0],2'b0};
user_mr_writedata <= data;
if (user_mr_write && !waitrequest)
begin
user_mr_write <= 0;
user_mr_address <= '0;
user_mr_writedata <= '0;
user_mr_state <= next_state;
end
end
endtask
logic [3:0] pd_state;
logic [AVL_ADDR_WIDTH - 1:0] pd_address;
logic pd_write;
logic pd_read;
logic [AVL_DATA_WIDTH - 1:0] pd_writedata;
logic [3:0] lock_count;
logic pd_down_r;
logic pd_up_r;
logic [3:0] cal_chk_count;
always_ff @(posedge clk, negedge reset_n)
begin
if (!reset_n)
begin
pd_down_r <= 0;
pd_up_r <= 0;
end
else
if (pd_state == 2 || pd_state == 6)
begin
pd_down_r <= pd_down;
pd_up_r <= pd_up;
end
end
always_ff @(posedge clk, negedge reset_n)
begin
if (!reset_n)
begin
pd_state <= 0;
pd_address <= '0;
pd_write <= 0;
pd_read <= 0;
pd_writedata <= '0;
pd_reset_n <= 0;
pd_ack <= 0;
lock_count <= '0;
cal_init_req <= 0;
cal_chk_count <= '0;
end
else
case(pd_state)
0 :
begin
if (pd_start && !cal_init_req)
begin
pd_reset_n <= 1;
pd_state <= 1;
end
if (cal_init_req)
cal_init_req <= 0;
end
1 :
begin
pd_ack <= 0;
if (pd_down)
pd_write_task_tracking_clock (0,2);
else if (pd_up)
pd_write_task_tracking_clock (1,2);
end
2 :
begin
if (pd_down_r && pd_up)
lock_count <= lock_count + 1'b1;
else if (pd_up_r && pd_down)
lock_count <= lock_count + 1'b1;
pd_ack <= 1;
pd_state <= 3;
end
3 :
begin
if (lock_count >= 8)
pd_state <= 4;
else
pd_state <= 1;
end
4 :
begin
pd_ack <= 0;
if (pd_down)
begin
if (pd_down_r || DISABLE_FILTER)
begin
if (DISABLE_PD)
pd_state <= 5;
else
pd_write_task_capture_clock (0,5);
end
else
pd_state <= 5;
end
else if (pd_up)
begin
if (pd_up_r || DISABLE_FILTER)
begin
if (DISABLE_PD)
pd_state <= 5;
else
pd_write_task_capture_clock (1,5);
end
else
pd_state <= 5;
end
end
5 :
begin
if (pd_down)
pd_write_task_tracking_clock (0,6);
else if (pd_up)
pd_write_task_tracking_clock (1,6);
end
6 :
begin
pd_ack <= 1;
if (cal_chk_count == 4'd10)
begin
cal_chk_count <= '0;
pd_state <= 7;
end
else
begin
cal_chk_count <= cal_chk_count + 1'b1;
pd_state <= 8;
end
end
7 :
begin
pd_read <= 1;
pd_address <= PLL_MGR_BASE[AVL_ADDR_WIDTH - 1:0]+{2'd2,2'b00};
if (pd_read && !waitrequest)
begin
pd_read <= 0;
pd_address <= '0;
if (readdata[0] == 1)
begin
pd_state <= 0;
cal_init_req <= 1;
lock_count <= 0;
end
else
pd_state <= 8;
end
end
8 :
pd_state <= 4;
endcase
end
task pd_write_task_tracking_clock;
input data;
input [2:0] next_state;
begin
pd_write <= 1;
pd_address <= PLL_MGR_BASE[AVL_ADDR_WIDTH - 1:0]+{1'b1,2'b00}; // tracking clock
pd_writedata <= data;
if (pd_write && !waitrequest)
begin
pd_write <= 0;
pd_address <= '0;
pd_writedata <= '0;
pd_state <= next_state;
end
end
endtask
task pd_write_task_capture_clock;
input data;
input [2:0] next_state;
begin
pd_write <= 1;
pd_address <= PLL_MGR_BASE[AVL_ADDR_WIDTH - 1:0];
pd_writedata <= data;
if (pd_write && !waitrequest)
begin
pd_write <= 0;
pd_address <= '0;
pd_writedata <= '0;
pd_state <= next_state;
end
end
endtask
assign address = main_address | ddr3_init_address | ddr2_init_address | lpddr2_init_address | write_address | user_mr_address | pd_address;
assign write = main_write | ddr3_init_write | ddr2_init_write | lpddr2_init_write | write_write | user_mr_write | pd_write;
assign writedata = main_writedata | ddr3_init_writedata | ddr2_init_writedata | lpddr2_init_writedata | write_writedata | user_mr_writedata | pd_writedata;
assign read = main_read | pd_read;
endmodule