MacPlus_MiSTer/sys/pll_cfg/pll_cfg_hdmi.v

1283 lines
50 KiB
Verilog

// (C) 2001-2017 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 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 MegaCore Function 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.
// original file was altera_pll_reconfig_core.v
// not needed functionality was cut out to reduce ressource consumption
module pll_cfg_hdmi
#(
parameter reconf_width = 64,
parameter device_family = "Cyclone V"
) (
//input
input wire mgmt_clk,
input wire mgmt_reset,
//conduits
output wire [reconf_width-1:0] reconfig_to_pll,
input wire [reconf_width-1:0] reconfig_from_pll,
// user data (avalon-MM slave interface)
output wire mgmt_waitrequest,
input wire [5:0] mgmt_address,
input wire mgmt_write,
input wire [31:0] mgmt_writedata
);
localparam mode_WR = 1'b0;
localparam MODE_REG = 6'b000000;
localparam START_REG = 6'b000010;
localparam N_REG = 6'b000011;
localparam M_REG = 6'b000100;
localparam C_COUNTERS_REG = 6'b000101;
//localparam DPS_REG = 6'b000110; // unused
localparam DSM_REG = 6'b000111;
localparam BWCTRL_REG = 6'b001000;
localparam CP_CURRENT_REG = 6'b001001;
//localparam ANY_DPRIO = 6'b100000; // unused
//localparam CNT_BASE = 5'b001010; // unused
//localparam VCO_REG = 6'b011100; // unused
//C Counters
localparam number_of_counters = 5'd6;
//C counter addresses
localparam C_CNT_0_DIV_ADDR = 5'h00;
localparam C_CNT_0_DIV_ADDR_DPRIO_1 = 5'h11;
localparam C_CNT_0_3_BYPASS_EN_ADDR = 5'h15;
localparam C_CNT_0_3_ODD_DIV_EN_ADDR = 5'h17;
localparam C_CNT_4_17_BYPASS_EN_ADDR = 5'h14;
localparam C_CNT_4_17_ODD_DIV_EN_ADDR = 5'h16;
//N counter addresses
localparam N_CNT_DIV_ADDR = 5'h13;
localparam N_CNT_BYPASS_EN_ADDR = 5'h15;
localparam N_CNT_ODD_DIV_EN_ADDR = 5'h17;
//M counter addresses
localparam M_CNT_DIV_ADDR = 5'h12;
localparam M_CNT_BYPASS_EN_ADDR = 5'h15;
localparam M_CNT_ODD_DIV_EN_ADDR = 5'h17;
//DSM address
localparam DSM_K_FRACTIONAL_DIVISION_ADDR_0 = 5'h18;
localparam DSM_K_FRACTIONAL_DIVISION_ADDR_1 = 5'h19;
localparam DSM_K_READY_ADDR = 5'h17;
localparam DSM_K_DITHER_ADDR = 5'h17;
localparam DSM_OUT_SEL_ADDR = 6'h30;
//Other DSM params
localparam DSM_K_READY_BIT_INDEX = 4'd11;
//BWCTRL address
//Bit 0-3 of addr
localparam BWCTRL_ADDR = 6'h30;
//CP_CURRENT address
//Bit 0-2 of addr
localparam CP_CURRENT_ADDR = 6'h31;
// VCODIV address
localparam VCO_ADDR = 5'h17;
localparam DPRIO_IDLE = 3'd0, ONE = 3'd1, TWO = 3'd2, THREE = 3'd3, FOUR = 3'd4,
FIVE = 3'd5, SIX = 3'd6, SEVEN = 3'd7, EIGHT = 4'd8, NINE = 4'd9, TEN = 4'd10,
ELEVEN = 4'd11, TWELVE = 4'd12, THIRTEEN = 4'd13, FOURTEEN = 4'd14, DPRIO_DONE = 4'd15;
localparam IDLE = 2'b00, WAIT_ON_LOCK = 2'b01, LOCKED = 2'b10;
wire clk;
wire reset;
wire gnd;
wire [5: 0] slave_address;
wire slave_write;
wire [31: 0] slave_writedata;
wire slave_waitrequest;
reg slave_mode;
assign clk = mgmt_clk;
assign slave_address = mgmt_address;
assign slave_write = mgmt_write;
assign slave_writedata = mgmt_writedata;
// Outputs
assign mgmt_waitrequest = slave_waitrequest; //Read waitrequest asserted in polling mode
//internal signals
wire locked_orig;
wire locked;
wire pll_start;
wire pll_start_valid;
wire pll_start_asserted;
reg [1:0] current_state;
reg [1:0] next_state;
reg status;//0=busy, 1=ready
//user_mode_init user_mode_init_inst (clk, reset, dprio_mdio_dis, ser_shift_load);
//declaring the init wires. These will have 0 on them for 64 clk cycles
wire [ 5:0] init_dprio_address;
wire init_dprio_read;
wire [ 1:0] init_dprio_byteen;
wire init_dprio_write;
wire [15:0] init_dprio_writedata;
wire init_atpgmode;
wire init_mdio_dis;
wire init_scanen;
wire init_ser_shift_load;
wire dprio_init_done;
//DPRIO output signals after initialization is done
wire dprio_clk;
reg avmm_dprio_write;
reg avmm_dprio_read;
reg [5:0] avmm_dprio_address;
reg [15:0] avmm_dprio_writedata;
reg [1:0] avmm_dprio_byteen;
wire avmm_atpgmode;
wire avmm_mdio_dis;
wire avmm_scanen;
//Final output wires that are muxed between the init and avmm wires.
wire dprio_init_reset;
wire [5:0] dprio_address /*synthesis keep*/;
wire dprio_read/*synthesis keep*/;
wire [1:0] dprio_byteen/*synthesis keep*/;
wire dprio_write/*synthesis keep*/;
wire [15:0] dprio_writedata/*synthesis keep*/;
wire dprio_mdio_dis/*synthesis keep*/;
wire dprio_ser_shift_load/*synthesis keep*/;
wire dprio_atpgmode/*synthesis keep*/;
wire dprio_scanen/*synthesis keep*/;
//other PLL signals for dyn ph shift
wire phase_done/*synthesis keep*/;
wire phase_en/*synthesis keep*/;
wire up_dn/*synthesis keep*/;
wire [4:0] cnt_sel;
//DPRIO input signals
wire [15:0] dprio_readdata;
//internal logic signals
//storage registers for user sent data
reg dprio_temp_read_1;
reg dprio_temp_read_2;
reg dprio_start;
wire usr_valid_changes;
reg [3:0] dprio_cur_state;
reg [3:0] dprio_next_state;
reg [15:0] dprio_temp_m_n_c_readdata_1_d;
reg [15:0] dprio_temp_m_n_c_readdata_2_d;
reg [15:0] dprio_temp_m_n_c_readdata_1_q;
reg [15:0] dprio_temp_m_n_c_readdata_2_q;
reg dprio_write_done;
//C counters signals
reg [7:0] usr_c_cnt_lo;
reg [7:0] usr_c_cnt_hi;
reg usr_c_cnt_bypass_en;
reg usr_c_cnt_odd_duty_div_en;
reg temp_c_cnt_bypass_en [0:17];
reg temp_c_cnt_odd_duty_div_en [0:17];
reg any_c_cnt_changed;
reg all_c_cnt_done_q;
reg all_c_cnt_done_d;
reg [17:0] c_cnt_changed;
reg [17:0] c_cnt_done_d;
reg [17:0] c_cnt_done_q;
//N counter signals
reg [7:0] usr_n_cnt_lo;
reg [7:0] usr_n_cnt_hi;
reg usr_n_cnt_bypass_en;
reg usr_n_cnt_odd_duty_div_en;
reg n_cnt_changed;
reg n_cnt_done_d;
reg n_cnt_done_q;
//M counter signals
reg [7:0] usr_m_cnt_lo;
reg [7:0] usr_m_cnt_hi;
reg usr_m_cnt_bypass_en;
reg usr_m_cnt_odd_duty_div_en;
reg m_cnt_changed;
reg m_cnt_done_d;
reg m_cnt_done_q;
//dyn phase regs
reg [15:0] usr_num_shifts;
reg [4:0] usr_cnt_sel /*synthesis preserve*/;
reg usr_up_dn;
reg dps_changed;
wire dps_changed_valid;
wire dps_done;
//DSM Signals
reg [31:0] usr_k_value;
reg dsm_k_changed;
reg dsm_k_done_d;
reg dsm_k_done_q;
reg dsm_k_ready_false_done_d;
//BW signals
reg [3:0] usr_bwctrl_value;
reg bwctrl_changed;
reg bwctrl_done_d;
reg bwctrl_done_q;
//CP signals
reg [2:0] usr_cp_current_value;
reg cp_current_changed;
reg cp_current_done_d;
reg cp_current_done_q;
//VCO signals
reg usr_vco_value;
reg vco_changed;
reg vco_done_d;
reg vco_done_q;
//Manual DPRIO signals
reg manual_dprio_done_q;
reg manual_dprio_done_d;
reg manual_dprio_changed;
reg [5:0] usr_dprio_address;
reg [15:0] usr_dprio_writedata_0;
reg usr_r_w;
//keeping track of which operation happened last
reg [5:0] operation_address;
// Address wires for all C_counter DPRIO registers
// These are outputs of LUTS, changing depending
// on whether PLL_0 or PLL_1 being used
//Fitter will tell if FPLL1 is being used
wire fpll_1;
// MAIN FSM
// Synchronize locked signal
altera_std_synchronizer #(
.depth(3)
) altera_std_synchronizer_inst (
.clk(mgmt_clk),
.reset_n(~mgmt_reset),
.din(locked_orig),
.dout(locked)
);
always @(posedge clk)
begin
if (reset)
begin
dprio_cur_state <= DPRIO_IDLE;
current_state <= IDLE;
end
else
begin
current_state <= next_state;
dprio_cur_state <= dprio_next_state;
end
end
always @(*)
begin
case(current_state)
IDLE:
begin
if (pll_start & !slave_waitrequest & usr_valid_changes)
next_state = WAIT_ON_LOCK;
else
next_state = IDLE;
end
WAIT_ON_LOCK:
begin
if (locked & dps_done & dprio_write_done) // received locked high from PLL
begin
if (slave_mode==mode_WR) //if the mode is waitrequest, then
// goto IDLE state directly
next_state = IDLE;
else
next_state = LOCKED; //otherwise go the locked state
end
else
next_state = WAIT_ON_LOCK;
end
LOCKED:
begin
next_state = LOCKED;
end
default: next_state = 2'bxx;
endcase
end
// ask the pll to start reconfig
assign pll_start = (pll_start_asserted & (current_state==IDLE)) ;
assign pll_start_valid = (pll_start & (next_state==WAIT_ON_LOCK)) ;
// WRITE OPERATIONS
assign pll_start_asserted = slave_write & (slave_address == START_REG);
//reading the mode register to determine what mode the slave will operate
//in.
always @(posedge clk)
begin
if (reset)
slave_mode <= mode_WR;
else if (slave_write & (slave_address == MODE_REG) & !slave_waitrequest)
slave_mode <= slave_writedata[0];
end
//record which values user wants to change.
//reading in the actual values that need to be reconfigged and sending
//them to the PLL
always @(posedge clk)
begin
if (reset)
begin
//reset all regs here
//BW signals reset
usr_bwctrl_value <= 0;
bwctrl_changed <= 0;
bwctrl_done_q <= 0;
//CP signals reset
usr_cp_current_value <= 0;
cp_current_changed <= 0;
cp_current_done_q <= 0;
//VCO signals reset
usr_vco_value <= 0;
vco_changed <= 0;
vco_done_q <= 0;
//DSM signals reset
usr_k_value <= 0;
dsm_k_changed <= 0;
dsm_k_done_q <= 0;
//N counter signals reset
usr_n_cnt_lo <= 0;
usr_n_cnt_hi <= 0;
usr_n_cnt_bypass_en <= 0;
usr_n_cnt_odd_duty_div_en <= 0;
n_cnt_changed <= 0;
n_cnt_done_q <= 0;
//M counter signals reset
usr_m_cnt_lo <= 0;
usr_m_cnt_hi <= 0;
usr_m_cnt_bypass_en <= 0;
usr_m_cnt_odd_duty_div_en <= 0;
m_cnt_changed <= 0;
m_cnt_done_q <= 0;
//C counter signals reset
usr_c_cnt_lo <= 0;
usr_c_cnt_hi <= 0;
usr_c_cnt_bypass_en <= 0;
usr_c_cnt_odd_duty_div_en <= 0;
any_c_cnt_changed <= 0;
all_c_cnt_done_q <= 0;
c_cnt_done_q <= 0;
//generic signals
dprio_start <= 0;
dprio_temp_m_n_c_readdata_1_q <= 0;
dprio_temp_m_n_c_readdata_2_q <= 0;
c_cnt_done_q <= 0;
//DPS signals
usr_up_dn <= 0;
usr_cnt_sel <= 0;
usr_num_shifts <= 0;
dps_changed <= 0;
//manual DPRIO signals
manual_dprio_changed <= 0;
usr_dprio_address <= 0;
usr_dprio_writedata_0 <= 0;
usr_r_w <= 0;
operation_address <= 0;
end
else
begin
if (dprio_temp_read_1)
begin
dprio_temp_m_n_c_readdata_1_q <= dprio_temp_m_n_c_readdata_1_d;
end
if (dprio_temp_read_2)
begin
dprio_temp_m_n_c_readdata_2_q <= dprio_temp_m_n_c_readdata_2_d;
end
if ((dps_done)) dps_changed <= 0;
if (dsm_k_done_d) dsm_k_done_q <= dsm_k_done_d;
if (n_cnt_done_d) n_cnt_done_q <= n_cnt_done_d;
if (m_cnt_done_d) m_cnt_done_q <= m_cnt_done_d;
if (all_c_cnt_done_d) all_c_cnt_done_q <= all_c_cnt_done_d;
if (c_cnt_done_d != 0) c_cnt_done_q <= c_cnt_done_q | c_cnt_done_d;
if (bwctrl_done_d) bwctrl_done_q <= bwctrl_done_d;
if (cp_current_done_d) cp_current_done_q <= cp_current_done_d;
if (vco_done_d) vco_done_q <= vco_done_d;
if (manual_dprio_done_d) manual_dprio_done_q <= manual_dprio_done_d;
if (dprio_next_state == ONE)
dprio_start <= 0;
if (dprio_write_done)
begin
bwctrl_done_q <= 0;
cp_current_done_q <= 0;
vco_done_q <= 0;
dsm_k_done_q <= 0;
dsm_k_done_q <= 0;
n_cnt_done_q <= 0;
m_cnt_done_q <= 0;
all_c_cnt_done_q <= 0;
c_cnt_done_q <= 0;
dsm_k_changed <= 0;
n_cnt_changed <= 0;
m_cnt_changed <= 0;
any_c_cnt_changed <= 0;
bwctrl_changed <= 0;
cp_current_changed <= 0;
vco_changed <= 0;
manual_dprio_changed <= 0;
manual_dprio_done_q <= 0;
end
else
begin
dsm_k_changed <= dsm_k_changed;
n_cnt_changed <= n_cnt_changed;
m_cnt_changed <= m_cnt_changed;
any_c_cnt_changed <= any_c_cnt_changed;
manual_dprio_changed <= manual_dprio_changed;
end
if(slave_write & !slave_waitrequest)
begin
case(slave_address)
//read in the values here from the user and act on them
DSM_REG:
begin
operation_address <= DSM_REG;
usr_k_value <= slave_writedata[31:0];
dsm_k_changed <= 1'b1;
dsm_k_done_q <= 0;
dprio_start <= 1'b1;
end
N_REG:
begin
operation_address <= N_REG;
usr_n_cnt_lo <= slave_writedata[7:0];
usr_n_cnt_hi <= slave_writedata[15:8];
usr_n_cnt_bypass_en <= slave_writedata[16];
usr_n_cnt_odd_duty_div_en <= slave_writedata[17];
n_cnt_changed <= 1'b1;
n_cnt_done_q <= 0;
dprio_start <= 1'b1;
end
M_REG:
begin
operation_address <= M_REG;
usr_m_cnt_lo <= slave_writedata[7:0];
usr_m_cnt_hi <= slave_writedata[15:8];
usr_m_cnt_bypass_en <= slave_writedata[16];
usr_m_cnt_odd_duty_div_en <= slave_writedata[17];
m_cnt_changed <= 1'b1;
m_cnt_done_q <= 0;
dprio_start <= 1'b1;
end
//DPS_REG:
//begin
// operation_address <= DPS_REG;
// usr_num_shifts <= slave_writedata[15:0];
// usr_up_dn <= slave_writedata[21];
// dps_changed <= 1;
//end
C_COUNTERS_REG:
begin
operation_address <= C_COUNTERS_REG;
usr_c_cnt_lo <= slave_writedata[7:0];
usr_c_cnt_hi <= slave_writedata[15:8];
usr_c_cnt_bypass_en <= slave_writedata[16];
usr_c_cnt_odd_duty_div_en <= slave_writedata[17];
any_c_cnt_changed <= 1'b1;
all_c_cnt_done_q <= 0;
dprio_start <= 1'b1;
end
BWCTRL_REG:
begin
usr_bwctrl_value <= slave_writedata[3:0];
bwctrl_changed <= 1'b1;
bwctrl_done_q <= 0;
dprio_start <= 1'b1;
operation_address <= BWCTRL_REG;
end
CP_CURRENT_REG:
begin
usr_cp_current_value <= slave_writedata[2:0];
cp_current_changed <= 1'b1;
cp_current_done_q <= 0;
dprio_start <= 1'b1;
operation_address <= CP_CURRENT_REG;
end
//VCO_REG:
//begin
// usr_vco_value <= slave_writedata[0];
// vco_changed <= 1'b1;
// vco_done_q <= 0;
// dprio_start <= 1'b1;
// operation_address <= VCO_REG;
//end
//ANY_DPRIO:
//begin
// operation_address <= ANY_DPRIO;
// manual_dprio_changed <= 1'b1;
// usr_dprio_address <= slave_writedata[5:0];
// usr_dprio_writedata_0 <= slave_writedata[21:6];
// usr_r_w <= slave_writedata[22];
// manual_dprio_done_q <= 0;
// dprio_start <= 1'b1;
//end
endcase
end
end
end
//C Counter assigning values to the 2-d array of values for each C counter
reg [4:0] j;
always @(posedge clk)
begin
if (reset)
begin
c_cnt_changed[17:0] <= 0;
for (j = 0; j < number_of_counters; j = j + 1'b1)
begin : c_cnt_reset
temp_c_cnt_bypass_en[j] <= 0;
temp_c_cnt_odd_duty_div_en[j] <= 0;
end
end
else
begin
if (dprio_write_done)
begin
c_cnt_changed <= 0;
end
if (any_c_cnt_changed && (operation_address == C_COUNTERS_REG))
begin
temp_c_cnt_bypass_en [5] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [5] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [5] <= 1'b1;
end
end
end
//logic to handle which writes the user indicated and wants to start.
assign usr_valid_changes =dsm_k_changed| any_c_cnt_changed |n_cnt_changed | m_cnt_changed | dps_changed_valid |manual_dprio_changed |cp_current_changed|bwctrl_changed|vco_changed;
//start the reconfig operations by writing to the DPRIO
reg break_loop;
reg [4:0] i;
always @(*)
begin
dprio_temp_read_1 = 0;
dprio_temp_read_2 = 0;
dprio_temp_m_n_c_readdata_1_d = 0;
dprio_temp_m_n_c_readdata_2_d = 0;
break_loop = 0;
dprio_next_state = DPRIO_IDLE;
avmm_dprio_write = 0;
avmm_dprio_read = 0;
avmm_dprio_address = 0;
avmm_dprio_writedata = 0;
avmm_dprio_byteen = 0;
dprio_write_done = 1;
manual_dprio_done_d = 0;
n_cnt_done_d = 0;
dsm_k_done_d = 0;
dsm_k_ready_false_done_d = 0;
m_cnt_done_d = 0;
c_cnt_done_d[17:0] = 0;
all_c_cnt_done_d = 0;
bwctrl_done_d = 0;
cp_current_done_d = 0;
vco_done_d = 0;
i = 0;
// Deassert dprio_write_done so it doesn't reset mif_reg_asserted (toggled writes)
if (dprio_start)
dprio_write_done = 0;
if (current_state == WAIT_ON_LOCK)
begin
case (dprio_cur_state)
ONE:
begin
if (n_cnt_changed & !n_cnt_done_q)
begin
dprio_write_done = 0;
avmm_dprio_write = 1'b1;
avmm_dprio_byteen = 2'b11;
dprio_next_state = TWO;
avmm_dprio_address = N_CNT_DIV_ADDR;
avmm_dprio_writedata[7:0] = usr_n_cnt_lo;
avmm_dprio_writedata[15:8] = usr_n_cnt_hi;
end
else if (m_cnt_changed & !m_cnt_done_q)
begin
dprio_write_done = 0;
avmm_dprio_write = 1'b1;
avmm_dprio_byteen = 2'b11;
dprio_next_state = TWO;
avmm_dprio_address = M_CNT_DIV_ADDR;
avmm_dprio_writedata[7:0] = usr_m_cnt_lo;
avmm_dprio_writedata[15:8] = usr_m_cnt_hi;
end
else if (any_c_cnt_changed & !all_c_cnt_done_q)
begin
for (i = 0; (i < number_of_counters) & !break_loop; i = i + 1'b1)
begin : c_cnt_write_hilo
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
dprio_write_done = 0;
avmm_dprio_write = 1'b1;
avmm_dprio_byteen = 2'b11;
dprio_next_state = TWO;
if (fpll_1) avmm_dprio_address = C_CNT_0_DIV_ADDR + C_CNT_0_DIV_ADDR_DPRIO_1 - i;
else avmm_dprio_address = C_CNT_0_DIV_ADDR + i;
avmm_dprio_writedata[7:0] = usr_c_cnt_lo;
avmm_dprio_writedata[15:8] = usr_c_cnt_hi;
//To break from the loop, since only one counter
//is addressed at a time
break_loop = 1'b1;
end
end
end
else if (dsm_k_changed & !dsm_k_done_q)
begin
dprio_write_done = 0;
avmm_dprio_write = 0;
dprio_next_state = TWO;
end
else if (bwctrl_changed & !bwctrl_done_q)
begin
dprio_write_done = 0;
avmm_dprio_write = 0;
dprio_next_state = TWO;
end
else if (cp_current_changed & !cp_current_done_q)
begin
dprio_write_done = 0;
avmm_dprio_write = 0;
dprio_next_state = TWO;
end
else if (vco_changed & !vco_done_q)
begin
dprio_write_done = 0;
avmm_dprio_write = 0;
dprio_next_state = TWO;
end
else if (manual_dprio_changed & !manual_dprio_done_q)
begin
dprio_write_done = 0;
avmm_dprio_byteen = 2'b11;
dprio_next_state = TWO;
avmm_dprio_write = usr_r_w;
avmm_dprio_address = usr_dprio_address;
avmm_dprio_writedata[15:0] = usr_dprio_writedata_0;
end
else dprio_next_state = DPRIO_IDLE;
end
TWO:
begin
//handle reading the two setting bits on n_cnt, then
//writing them back while preserving other bits.
//Issue two consecutive reads then wait; readLatency=3
dprio_write_done = 0;
dprio_next_state = THREE;
avmm_dprio_byteen = 2'b11;
avmm_dprio_read = 1'b1;
if (n_cnt_changed & !n_cnt_done_q)
begin
avmm_dprio_address = N_CNT_BYPASS_EN_ADDR;
end
else if (m_cnt_changed & !m_cnt_done_q)
begin
avmm_dprio_address = M_CNT_BYPASS_EN_ADDR;
end
else if (any_c_cnt_changed & !all_c_cnt_done_q)
begin
for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1)
begin : c_cnt_read_bypass
if (fpll_1)
begin
if (i > 13)
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR;
break_loop = 1'b1;
end
end
else
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR;
break_loop = 1'b1;
end
end
end
else
begin
if (i < 4)
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR;
break_loop = 1'b1;
end
end
else
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR;
break_loop = 1'b1;
end
end
end
end
end
//reading the K ready 16 bit word. Need to write 0 to it
//afterwards to indicate that K has not been done writing
else if (dsm_k_changed & !dsm_k_done_q)
begin
avmm_dprio_address = DSM_K_READY_ADDR;
dprio_next_state = FOUR;
end
else if (bwctrl_changed & !bwctrl_done_q)
begin
avmm_dprio_address = BWCTRL_ADDR;
dprio_next_state = FOUR;
end
else if (cp_current_changed & !cp_current_done_q)
begin
avmm_dprio_address = CP_CURRENT_ADDR;
dprio_next_state = FOUR;
end
else if (vco_changed & !vco_done_q)
begin
avmm_dprio_address = VCO_ADDR;
dprio_next_state = FOUR;
end
else if (manual_dprio_changed & !manual_dprio_done_q)
begin
avmm_dprio_read = ~usr_r_w;
avmm_dprio_address = usr_dprio_address;
dprio_next_state = DPRIO_DONE;
end
else dprio_next_state = DPRIO_IDLE;
end
THREE:
begin
dprio_write_done = 0;
avmm_dprio_byteen = 2'b11;
avmm_dprio_read = 1'b1;
dprio_next_state = FOUR;
if (n_cnt_changed & !n_cnt_done_q)
begin
avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR;
end
else if (m_cnt_changed & !m_cnt_done_q)
begin
avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR;
end
else if (any_c_cnt_changed & !all_c_cnt_done_q)
begin
for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1)
begin : c_cnt_read_odd_div
if (fpll_1)
begin
if (i > 13)
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR;
break_loop = 1'b1;
end
end
else
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR;
break_loop = 1'b1;
end
end
end
else
begin
if (i < 4)
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR;
break_loop = 1'b1;
end
end
else
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR;
break_loop = 1'b1;
end
end
end
end
end
else dprio_next_state = DPRIO_IDLE;
end
FOUR:
begin
dprio_temp_read_1 = 1'b1;
dprio_write_done = 0;
if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed)
begin
dprio_temp_m_n_c_readdata_1_d = dprio_readdata;
dprio_next_state = FIVE;
end
else dprio_next_state = DPRIO_IDLE;
end
FIVE:
begin
dprio_write_done = 0;
dprio_temp_read_2 = 1'b1;
if (vco_changed|cp_current_changed|bwctrl_changed|dsm_k_changed|n_cnt_changed|m_cnt_changed|any_c_cnt_changed)
begin
//this is where DSM ready value comes.
//Need to store in a register to be used later
dprio_temp_m_n_c_readdata_2_d = dprio_readdata;
dprio_next_state = SIX;
end
else dprio_next_state = DPRIO_IDLE;
end
SIX:
begin
dprio_write_done = 0;
avmm_dprio_write = 1'b1;
avmm_dprio_byteen = 2'b11;
dprio_next_state = SEVEN;
avmm_dprio_writedata = dprio_temp_m_n_c_readdata_1_q;
if (n_cnt_changed & !n_cnt_done_q)
begin
avmm_dprio_address = N_CNT_BYPASS_EN_ADDR;
avmm_dprio_writedata[5] = usr_n_cnt_bypass_en;
end
else if (m_cnt_changed & !m_cnt_done_q)
begin
avmm_dprio_address = M_CNT_BYPASS_EN_ADDR;
avmm_dprio_writedata[4] = usr_m_cnt_bypass_en;
end
else if (any_c_cnt_changed & !all_c_cnt_done_q)
begin
for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1)
begin : c_cnt_write_bypass
if (fpll_1)
begin
if (i > 13)
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR;
avmm_dprio_writedata[i-14] = temp_c_cnt_bypass_en[i];
break_loop = 1'b1;
end
end
else
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR;
avmm_dprio_writedata[i] = temp_c_cnt_bypass_en[i];
break_loop = 1'b1;
end
end
end
else
begin
if (i < 4)
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_0_3_BYPASS_EN_ADDR;
avmm_dprio_writedata[3-i] = temp_c_cnt_bypass_en[i];
break_loop = 1'b1;
end
end
else
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_4_17_BYPASS_EN_ADDR;
avmm_dprio_writedata[17-i] = temp_c_cnt_bypass_en[i];
break_loop = 1'b1;
end
end
end
end
end
else if (dsm_k_changed & !dsm_k_done_q)
begin
avmm_dprio_write = 0;
end
else if (bwctrl_changed & !bwctrl_done_q)
begin
avmm_dprio_write = 0;
end
else if (cp_current_changed & !cp_current_done_q)
begin
avmm_dprio_write = 0;
end
else if (vco_changed & !vco_done_q)
begin
avmm_dprio_write = 0;
end
else dprio_next_state = DPRIO_IDLE;
end
SEVEN:
begin
dprio_write_done = 0;
dprio_next_state = EIGHT;
avmm_dprio_write = 1'b1;
avmm_dprio_byteen = 2'b11;
avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q;
if (n_cnt_changed & !n_cnt_done_q)
begin
avmm_dprio_address = N_CNT_ODD_DIV_EN_ADDR;
avmm_dprio_writedata[5] = usr_n_cnt_odd_duty_div_en;
n_cnt_done_d = 1'b1;
end
else if (m_cnt_changed & !m_cnt_done_q)
begin
avmm_dprio_address = M_CNT_ODD_DIV_EN_ADDR;
avmm_dprio_writedata[4] = usr_m_cnt_odd_duty_div_en;
m_cnt_done_d = 1'b1;
end
else if (any_c_cnt_changed & !all_c_cnt_done_q)
begin
for (i = 5; (i < number_of_counters) & !break_loop; i = i + 1'b1)
begin : c_cnt_write_odd_div
if (fpll_1)
begin
if (i > 13)
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR;
avmm_dprio_writedata[i-14] = temp_c_cnt_odd_duty_div_en[i];
c_cnt_done_d[i] = 1'b1;
//have to OR the signals to prevent
//overwriting of previous dones
c_cnt_done_d = c_cnt_done_d | c_cnt_done_q;
break_loop = 1'b1;
end
end
else
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR;
avmm_dprio_writedata[i] = temp_c_cnt_odd_duty_div_en[i];
c_cnt_done_d[i] = 1'b1;
c_cnt_done_d = c_cnt_done_d | c_cnt_done_q;
break_loop = 1'b1;
end
end
end
else
begin
if (i < 4)
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_0_3_ODD_DIV_EN_ADDR;
avmm_dprio_writedata[3-i] = temp_c_cnt_odd_duty_div_en[i];
c_cnt_done_d[i] = 1'b1;
//have to OR the signals to prevent
//overwriting of previous dones
c_cnt_done_d = c_cnt_done_d | c_cnt_done_q;
break_loop = 1'b1;
end
end
else
begin
if (c_cnt_changed[i] & !c_cnt_done_q[i])
begin
avmm_dprio_address = C_CNT_4_17_ODD_DIV_EN_ADDR;
avmm_dprio_writedata[17-i] = temp_c_cnt_odd_duty_div_en[i];
c_cnt_done_d[i] = 1'b1;
c_cnt_done_d = c_cnt_done_d | c_cnt_done_q;
break_loop = 1'b1;
end
end
end
end
end
else if (dsm_k_changed & !dsm_k_done_q)
begin
avmm_dprio_address = DSM_K_READY_ADDR;
avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b0;
dsm_k_ready_false_done_d = 1'b1;
end
else if (bwctrl_changed & !bwctrl_done_q)
begin
avmm_dprio_address = BWCTRL_ADDR;
avmm_dprio_writedata[3:0] = usr_bwctrl_value;
bwctrl_done_d = 1'b1;
end
else if (cp_current_changed & !cp_current_done_q)
begin
avmm_dprio_address = CP_CURRENT_ADDR;
avmm_dprio_writedata[2:0] = usr_cp_current_value;
cp_current_done_d = 1'b1;
end
else if (vco_changed & !vco_done_q)
begin
avmm_dprio_address = VCO_ADDR;
avmm_dprio_writedata[8] = usr_vco_value;
vco_done_d = 1'b1;
end
//if all C_cnt that were changed are done, then assert all_c_cnt_done
if (c_cnt_done_d == c_cnt_changed)
all_c_cnt_done_d = 1'b1;
if (n_cnt_changed & n_cnt_done_d)
dprio_next_state = DPRIO_DONE;
if (any_c_cnt_changed & !all_c_cnt_done_d & !all_c_cnt_done_q)
dprio_next_state = ONE;
else if (m_cnt_changed & !m_cnt_done_d & !m_cnt_done_q)
dprio_next_state = ONE;
else if (dsm_k_changed & !dsm_k_ready_false_done_d)
dprio_next_state = TWO;
else if (dsm_k_changed & !dsm_k_done_q)
dprio_next_state = EIGHT;
else if (bwctrl_changed & !bwctrl_done_d)
dprio_next_state = TWO;
else if (cp_current_changed & !cp_current_done_d)
dprio_next_state = TWO;
else if (vco_changed & !vco_done_d)
dprio_next_state = TWO;
else
begin
dprio_next_state = DPRIO_DONE;
dprio_write_done = 1'b1;
end
end
//finish the rest of the DSM reads/writes
//writing k value, writing k_ready to 1.
EIGHT:
begin
dprio_write_done = 0;
dprio_next_state = NINE;
avmm_dprio_write = 1'b1;
avmm_dprio_byteen = 2'b11;
if (dsm_k_changed & !dsm_k_done_q)
begin
avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_0;
avmm_dprio_writedata[15:0] = usr_k_value[15:0];
end
end
NINE:
begin
dprio_write_done = 0;
dprio_next_state = TEN;
avmm_dprio_write = 1'b1;
avmm_dprio_byteen = 2'b11;
if (dsm_k_changed & !dsm_k_done_q)
begin
avmm_dprio_address = DSM_K_FRACTIONAL_DIVISION_ADDR_1;
avmm_dprio_writedata[15:0] = usr_k_value[31:16];
end
end
TEN:
begin
dprio_write_done = 0;
dprio_next_state = ONE;
avmm_dprio_write = 1'b1;
avmm_dprio_byteen = 2'b11;
if (dsm_k_changed & !dsm_k_done_q)
begin
avmm_dprio_address = DSM_K_READY_ADDR;
//already have the readdata for DSM_K_READY_ADDR since we read it
//earlier. Just reuse here
avmm_dprio_writedata = dprio_temp_m_n_c_readdata_2_q;
avmm_dprio_writedata[DSM_K_READY_BIT_INDEX] = 1'b1;
dsm_k_done_d = 1'b1;
end
end
DPRIO_DONE:
begin
dprio_write_done = 1'b1;
if (dprio_start) dprio_next_state = DPRIO_IDLE;
else dprio_next_state = DPRIO_DONE;
end
DPRIO_IDLE:
begin
if (dprio_start) dprio_next_state = ONE;
else dprio_next_state = DPRIO_IDLE;
end
default: dprio_next_state = 4'bxxxx;
endcase
end
end
//assert the waitreq signal according to the state of the slave
assign slave_waitrequest = (slave_mode==mode_WR) ? ((locked === 1'b1) ? (((current_state==WAIT_ON_LOCK) & !dprio_write_done) | !dps_done |reset|!dprio_init_done) : 1'b1) : 1'b0;
dyn_phase_shift dyn_phase_shift_inst (
.clk(clk),
.reset(reset),
.phase_done(phase_done),
.pll_start_valid(pll_start_valid),
.dps_changed(dps_changed),
.dps_changed_valid(dps_changed_valid),
.dprio_write_done(dprio_write_done),
.usr_num_shifts(usr_num_shifts),
.usr_cnt_sel(usr_cnt_sel),
.usr_up_dn(usr_up_dn),
.locked(locked),
.dps_done(dps_done),
.phase_en(phase_en),
.up_dn(up_dn),
.cnt_sel(cnt_sel));
defparam dyn_phase_shift_inst.device_family = device_family;
assign dprio_clk = clk;
self_reset self_reset_inst (mgmt_reset, clk, reset, dprio_init_reset);
dprio_mux dprio_mux_inst (
.init_dprio_address(init_dprio_address),
.init_dprio_read(init_dprio_read),
.init_dprio_byteen(init_dprio_byteen),
.init_dprio_write(init_dprio_write),
.init_dprio_writedata(init_dprio_writedata),
.init_atpgmode(init_atpgmode),
.init_mdio_dis(init_mdio_dis),
.init_scanen(init_scanen),
.init_ser_shift_load(init_ser_shift_load),
.dprio_init_done(dprio_init_done),
// Inputs from avmm master
.avmm_dprio_address(avmm_dprio_address),
.avmm_dprio_read(avmm_dprio_read),
.avmm_dprio_byteen(avmm_dprio_byteen),
.avmm_dprio_write(avmm_dprio_write),
.avmm_dprio_writedata(avmm_dprio_writedata),
.avmm_atpgmode(avmm_atpgmode),
.avmm_mdio_dis(avmm_mdio_dis),
.avmm_scanen(avmm_scanen),
// Outputs to fpll
.dprio_address(dprio_address),
.dprio_read(dprio_read),
.dprio_byteen(dprio_byteen),
.dprio_write(dprio_write),
.dprio_writedata(dprio_writedata),
.atpgmode(dprio_atpgmode),
.mdio_dis(dprio_mdio_dis),
.scanen(dprio_scanen),
.ser_shift_load(dprio_ser_shift_load)
);
fpll_dprio_init fpll_dprio_init_inst (
.clk(clk),
.reset_n(~reset),
.locked(locked),
//outputs
.dprio_address(init_dprio_address),
.dprio_read(init_dprio_read),
.dprio_byteen(init_dprio_byteen),
.dprio_write(init_dprio_write),
.dprio_writedata(init_dprio_writedata),
.atpgmode(init_atpgmode),
.mdio_dis(init_mdio_dis),
.scanen(init_scanen),
.ser_shift_load(init_ser_shift_load),
.dprio_init_done(dprio_init_done));
//address luts, to be reconfigged by the Fitter
//FPLL_1 or 0 address lut
generic_lcell_comb lcell_fpll_0_1 (
.dataa(1'b0),
.combout (fpll_1));
defparam lcell_fpll_0_1.lut_mask = 64'hAAAAAAAAAAAAAAAA;
defparam lcell_fpll_0_1.dont_touch = "on";
defparam lcell_fpll_0_1.family = device_family;
wire dprio_read_combout;
generic_lcell_comb lcell_dprio_read (
.dataa(fpll_1),
.datab(dprio_read),
.datac(1'b0),
.datad(1'b0),
.datae(1'b0),
.dataf(1'b0),
.combout (dprio_read_combout));
defparam lcell_dprio_read.lut_mask = 64'hCCCCCCCCCCCCCCCC;
defparam lcell_dprio_read.dont_touch = "on";
defparam lcell_dprio_read.family = device_family;
//assign reconfig_to_pll signals
assign reconfig_to_pll[0] = dprio_clk;
assign reconfig_to_pll[1] = ~dprio_init_reset;
assign reconfig_to_pll[2] = dprio_write;
assign reconfig_to_pll[3] = dprio_read_combout;
assign reconfig_to_pll[9:4] = dprio_address;
assign reconfig_to_pll[25:10] = dprio_writedata;
assign reconfig_to_pll[27:26] = dprio_byteen;
assign reconfig_to_pll[28] = dprio_ser_shift_load;
assign reconfig_to_pll[29] = dprio_mdio_dis;
assign reconfig_to_pll[30] = phase_en;
assign reconfig_to_pll[31] = up_dn;
assign reconfig_to_pll[36:32] = cnt_sel;
assign reconfig_to_pll[37] = dprio_scanen;
assign reconfig_to_pll[38] = dprio_atpgmode;
//assign reconfig_to_pll[40:37] = clken;
assign reconfig_to_pll[63:39] = 0;
//assign reconfig_from_pll signals
assign dprio_readdata = reconfig_from_pll [15:0];
assign locked_orig = reconfig_from_pll [16];
assign phase_done = reconfig_from_pll [17];
endmodule