MacPlus_MiSTer/sys/pll_hdmi_cfg/altera_pll_reconfig_core.v

2185 lines
83 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.
`timescale 1ps/1ps
module altera_pll_reconfig_core
#(
parameter reconf_width = 64,
parameter device_family = "Stratix V",
// MIF Streaming parameters
parameter RECONFIG_ADDR_WIDTH = 6,
parameter RECONFIG_DATA_WIDTH = 32,
parameter ROM_ADDR_WIDTH = 9,
parameter ROM_DATA_WIDTH = 32,
parameter ROM_NUM_WORDS = 512
) (
//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 [31:0] mgmt_readdata,
output wire mgmt_waitrequest,
input wire [5:0] mgmt_address,
input wire mgmt_read,
input wire mgmt_write,
input wire [31:0] mgmt_writedata,
//other
output wire mif_start_out,
output reg [ROM_ADDR_WIDTH-1:0] mif_base_addr
);
localparam mode_WR = 1'b0;
localparam mode_POLL = 1'b1;
localparam MODE_REG = 6'b000000;
localparam STATUS_REG = 6'b000001;
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;
localparam DSM_REG = 6'b000111;
localparam BWCTRL_REG = 6'b001000;
localparam CP_CURRENT_REG = 6'b001001;
localparam ANY_DPRIO = 6'b100000;
localparam CNT_BASE = 5'b001010;
localparam VCO_REG = 6'b011100;
localparam MIF_REG = 6'b011111;
//C Counters
localparam number_of_counters = 5'd18;
localparam CNT_0 = 1'd0, CNT_1 = 5'd1, CNT_2 = 5'd2,
CNT_3 = 5'd3, CNT_4 = 5'd4, CNT_5 = 5'd5,
CNT_6 = 5'd6, CNT_7 = 5'd7, CNT_8 = 5'd8,
CNT_9 = 5'd9, CNT_10 = 5'd10, CNT_11 = 5'd11,
CNT_12 = 5'd12, CNT_13 = 5'd13, CNT_14 = 5'd14,
CNT_15 = 5'd15, CNT_16 = 5'd16, CNT_17 = 5'd17;
//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_read;
wire slave_write;
wire [31: 0] slave_writedata;
reg [31: 0] slave_readdata_d;
reg [31: 0] slave_readdata_q;
wire slave_waitrequest;
reg slave_mode;
assign clk = mgmt_clk;
assign slave_address = mgmt_address;
assign slave_read = mgmt_read;
assign slave_write = mgmt_write;
assign slave_writedata = mgmt_writedata;
reg read_waitrequest;
// Outputs
assign mgmt_readdata = slave_readdata_q;
assign mgmt_waitrequest = slave_waitrequest | read_waitrequest; //Read waitrequest asserted in polling mode
//internal signals
wire locked_orig;
wire locked;
wire pll_start;
wire pll_start_valid;
reg status_read;
wire read_slave_mode_asserted;
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;
reg mif_start_assert;
reg dps_start_assert;
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 [7:0] temp_c_cnt_lo [0:17];
reg [7:0] temp_c_cnt_hi [0:17];
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;
// other
reg mif_reg_asserted;
// 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
if (status_read) // stay in LOCKED until user reads status
next_state = IDLE;
else
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);
assign mif_start_out = pll_start & mif_reg_asserted;
//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;
mif_start_assert <= 0;
dps_start_assert <= 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;
mif_reg_asserted <= 0;
mif_base_addr <= 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 (mif_start_out == 1'b1)
mif_start_assert <= 0; // Signaled MIF block to start, so deassert on next cycle
if (dps_done != 1'b1)
dps_start_assert <= 0; // DPS has started, so dessert its start signal on next cycle
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;
if (dps_changed | dps_changed_valid | !dps_done )
begin
usr_cnt_sel <= usr_cnt_sel;
end
else
begin
usr_cnt_sel <= 0;
end
mif_reg_asserted <= 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;
mif_reg_asserted <= mif_reg_asserted;
usr_cnt_sel <= usr_cnt_sel;
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_cnt_sel <= slave_writedata[20:16];
usr_up_dn <= slave_writedata[21];
dps_changed <= 1;
dps_start_assert <= 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];
usr_cnt_sel <= slave_writedata[22:18];
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
MIF_REG:
begin
mif_reg_asserted <= 1'b1;
mif_base_addr <= slave_writedata[ROM_ADDR_WIDTH-1:0];
mif_start_assert <= 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;
temp_c_cnt_lo[j][7:0] <= 0;
temp_c_cnt_hi[j][7:0] <= 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
case (cnt_sel)
CNT_0:
begin
temp_c_cnt_lo [0] <= usr_c_cnt_lo;
temp_c_cnt_hi [0] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [0] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [0] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [0] <= 1'b1;
end
CNT_1:
begin
temp_c_cnt_lo [1] <= usr_c_cnt_lo;
temp_c_cnt_hi [1] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [1] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [1] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [1] <= 1'b1;
end
CNT_2:
begin
temp_c_cnt_lo [2] <= usr_c_cnt_lo;
temp_c_cnt_hi [2] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [2] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [2] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [2] <= 1'b1;
end
CNT_3:
begin
temp_c_cnt_lo [3] <= usr_c_cnt_lo;
temp_c_cnt_hi [3] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [3] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [3] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [3] <= 1'b1;
end
CNT_4:
begin
temp_c_cnt_lo [4] <= usr_c_cnt_lo;
temp_c_cnt_hi [4] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [4] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [4] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [4] <= 1'b1;
end
CNT_5:
begin
temp_c_cnt_lo [5] <= usr_c_cnt_lo;
temp_c_cnt_hi [5] <= usr_c_cnt_hi;
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
CNT_6:
begin
temp_c_cnt_lo [6] <= usr_c_cnt_lo;
temp_c_cnt_hi [6] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [6] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [6] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [6] <= 1'b1;
end
CNT_7:
begin
temp_c_cnt_lo [7] <= usr_c_cnt_lo;
temp_c_cnt_hi [7] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [7] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [7] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [7] <= 1'b1;
end
CNT_8:
begin
temp_c_cnt_lo [8] <= usr_c_cnt_lo;
temp_c_cnt_hi [8] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [8] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [8] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [8] <= 1'b1;
end
CNT_9:
begin
temp_c_cnt_lo [9] <= usr_c_cnt_lo;
temp_c_cnt_hi [9] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [9] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [9] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [9] <= 1'b1;
end
CNT_10:
begin
temp_c_cnt_lo [10] <= usr_c_cnt_lo;
temp_c_cnt_hi [10] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [10] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [10] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [10] <= 1'b1;
end
CNT_11:
begin
temp_c_cnt_lo [11] <= usr_c_cnt_lo;
temp_c_cnt_hi [11] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [11] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [11] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [11] <= 1'b1;
end
CNT_12:
begin
temp_c_cnt_lo [12] <= usr_c_cnt_lo;
temp_c_cnt_hi [12] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [12] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [12] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [12] <= 1'b1;
end
CNT_13:
begin
temp_c_cnt_lo [13] <= usr_c_cnt_lo;
temp_c_cnt_hi [13] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [13] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [13] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [13] <= 1'b1;
end
CNT_14:
begin
temp_c_cnt_lo [14] <= usr_c_cnt_lo;
temp_c_cnt_hi [14] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [14] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [14] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [14] <= 1'b1;
end
CNT_15:
begin
temp_c_cnt_lo [15] <= usr_c_cnt_lo;
temp_c_cnt_hi [15] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [15] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [15] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [15] <= 1'b1;
end
CNT_16:
begin
temp_c_cnt_lo [16] <= usr_c_cnt_lo;
temp_c_cnt_hi [16] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [16] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [16] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [16] <= 1'b1;
end
CNT_17:
begin
temp_c_cnt_lo [17] <= usr_c_cnt_lo;
temp_c_cnt_hi [17] <= usr_c_cnt_hi;
temp_c_cnt_bypass_en [17] <= usr_c_cnt_bypass_en;
temp_c_cnt_odd_duty_div_en [17] <= usr_c_cnt_odd_duty_div_en;
c_cnt_changed [17] <= 1'b1;
end
endcase
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 | mif_start_assert)
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] = temp_c_cnt_lo[i];
avmm_dprio_writedata[15:8] = temp_c_cnt_hi[i];
//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 = 0; (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 = 0; (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 = 0; (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 = 0; (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;
// Read operations
always @(*)
begin
status = 0;
if (slave_mode == mode_POLL)
//asserting status to 1 if the slave is done.
status = (current_state == LOCKED);
end
//************************************************************//
//************************************************************//
//******************** READ STATE MACHINE ********************//
//************************************************************//
//************************************************************//
reg [1:0] current_read_state;
reg [1:0] next_read_state;
reg [5:0] slave_address_int_d;
reg [5:0] slave_address_int_q;
reg dprio_read_1;
reg [5:0] dprio_address_1;
reg [1:0] dprio_byteen_1;
reg [4:0] usr_cnt_sel_1;
localparam READ = 2'b00, READ_WAIT = 2'b01, READ_IDLE = 2'b10, READ_POST_WAIT = 2'b11;
always @(*)
begin
if(next_read_state == READ_IDLE)
begin
read_waitrequest <= 1'b0;
end
else
begin
read_waitrequest <= 1'b1;
end
end
always @(posedge clk)
begin
if (reset)
begin
current_read_state <= READ_IDLE;
slave_address_int_q <= 0;
slave_readdata_q <= 0;
end
else
begin
current_read_state <= next_read_state;
slave_address_int_q <= slave_address_int_d;
slave_readdata_q <= slave_readdata_d;
end
end
always @(*)
begin
dprio_read_1 = 0;
dprio_address_1 = 0;
dprio_byteen_1 = 0;
slave_address_int_d = 0;
slave_readdata_d = 0;
status_read = 0;
usr_cnt_sel_1 = 0;
case(current_read_state)
READ_IDLE:
begin
slave_address_int_d = 0;
next_read_state = READ_IDLE;
if ((current_state != WAIT_ON_LOCK) && slave_read)
begin
slave_address_int_d = slave_address;
if ((slave_address >= CNT_BASE) && (slave_address < CNT_BASE+18))
begin
next_read_state = READ_WAIT;
dprio_byteen_1 = 2'b11;
dprio_read_1 = 1'b1;
usr_cnt_sel_1 = (slave_address[4:0] - CNT_BASE);
if (fpll_1) dprio_address_1 = C_CNT_0_DIV_ADDR + C_CNT_0_DIV_ADDR_DPRIO_1 - cnt_sel;
else dprio_address_1 = C_CNT_0_DIV_ADDR + cnt_sel;
end
else
begin
case (slave_address)
MODE_REG:
begin
next_read_state = READ_WAIT;
slave_readdata_d = slave_mode;
end
STATUS_REG:
begin
next_read_state = READ_WAIT;
status_read = 1'b1;
slave_readdata_d = status;
end
N_REG:
begin
dprio_byteen_1 = 2'b11;
dprio_read_1 = 1'b1;
dprio_address_1 = N_CNT_DIV_ADDR;
next_read_state = READ_WAIT;
end
M_REG:
begin
dprio_byteen_1 = 2'b11;
dprio_read_1 = 1'b1;
dprio_address_1 = M_CNT_DIV_ADDR;
next_read_state = READ_WAIT;
end
BWCTRL_REG:
begin
dprio_byteen_1 = 2'b11;
dprio_read_1 = 1'b1;
dprio_address_1 = BWCTRL_ADDR;
next_read_state = READ_WAIT;
end
CP_CURRENT_REG:
begin
dprio_byteen_1 = 2'b11;
dprio_read_1 = 1'b1;
dprio_address_1 = CP_CURRENT_ADDR;
next_read_state = READ_WAIT;
end
VCO_REG:
begin
dprio_byteen_1 = 2'b11;
dprio_read_1 = 1'b1;
dprio_address_1 = VCO_ADDR;
next_read_state = READ_WAIT;
end
ANY_DPRIO:
begin
dprio_byteen_1 = 2'b11;
dprio_read_1 = ~slave_writedata[22];
dprio_address_1 = slave_writedata[5:0];
next_read_state = READ_WAIT;
end
default : next_read_state = READ_IDLE;
endcase
end
end
else
next_read_state = READ_IDLE;
end
READ_WAIT:
begin
next_read_state = READ;
slave_address_int_d = slave_address_int_q;
case (slave_address_int_q)
MODE_REG:
begin
slave_readdata_d = slave_readdata_q;
end
STATUS_REG:
begin
slave_readdata_d = slave_readdata_q;
end
endcase
end
READ:
begin
next_read_state = READ_POST_WAIT;
slave_address_int_d = slave_address_int_q;
slave_readdata_d = dprio_readdata;
case (slave_address_int_q)
MODE_REG:
begin
slave_readdata_d = slave_readdata_q;
end
STATUS_REG:
begin
slave_readdata_d = slave_readdata_q;
end
BWCTRL_REG:
begin
slave_readdata_d = dprio_readdata[3:0];
end
CP_CURRENT_REG:
begin
slave_readdata_d = dprio_readdata[2:0];
end
VCO_REG:
begin
slave_readdata_d = dprio_readdata[8];
end
ANY_DPRIO:
begin
slave_readdata_d = dprio_readdata;
end
endcase
end
READ_POST_WAIT:
begin
next_read_state = READ_IDLE;
end
default: next_read_state = 2'bxx;
endcase
end
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_cnt_sel_1),
.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 | dprio_address_1),
.avmm_dprio_read(avmm_dprio_read | dprio_read_1),
.avmm_dprio_byteen(avmm_dprio_byteen | dprio_byteen_1),
.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
module self_reset (input wire mgmt_reset, input wire clk, output wire reset, output wire init_reset);
localparam RESET_COUNTER_VALUE = 3'd2;
localparam INITIAL_WAIT_VALUE = 9'd340;
reg [9:0]counter;
reg local_reset;
reg usr_mode_init_wait;
initial
begin
local_reset = 1'b1;
counter = 0;
usr_mode_init_wait = 0;
end
always @(posedge clk)
begin
if (mgmt_reset)
begin
counter <= 0;
end
else
begin
if (!usr_mode_init_wait)
begin
if (counter == INITIAL_WAIT_VALUE)
begin
local_reset <= 0;
usr_mode_init_wait <= 1'b1;
counter <= 0;
end
else
begin
counter <= counter + 1'b1;
end
end
else
begin
if (counter == RESET_COUNTER_VALUE)
local_reset <= 0;
else
counter <= counter + 1'b1;
end
end
end
assign reset = mgmt_reset | local_reset;
assign init_reset = local_reset;
endmodule
module dprio_mux (
// Inputs from init block
input [ 5:0] init_dprio_address,
input init_dprio_read,
input [ 1:0] init_dprio_byteen,
input init_dprio_write,
input [15:0] init_dprio_writedata,
input init_atpgmode,
input init_mdio_dis,
input init_scanen,
input init_ser_shift_load,
input dprio_init_done,
// Inputs from avmm master
input [ 5:0] avmm_dprio_address,
input avmm_dprio_read,
input [ 1:0] avmm_dprio_byteen,
input avmm_dprio_write,
input [15:0] avmm_dprio_writedata,
input avmm_atpgmode,
input avmm_mdio_dis,
input avmm_scanen,
input avmm_ser_shift_load,
// Outputs to fpll
output [ 5:0] dprio_address,
output dprio_read,
output [ 1:0] dprio_byteen,
output dprio_write,
output [15:0] dprio_writedata,
output atpgmode,
output mdio_dis,
output scanen,
output ser_shift_load
);
assign dprio_address = dprio_init_done ? avmm_dprio_address : init_dprio_address;
assign dprio_read = dprio_init_done ? avmm_dprio_read : init_dprio_read;
assign dprio_byteen = dprio_init_done ? avmm_dprio_byteen : init_dprio_byteen;
assign dprio_write = dprio_init_done ? avmm_dprio_write : init_dprio_write;
assign dprio_writedata = dprio_init_done ? avmm_dprio_writedata : init_dprio_writedata;
assign atpgmode = init_atpgmode;
assign scanen = init_scanen;
assign mdio_dis = init_mdio_dis;
assign ser_shift_load = init_ser_shift_load ;
endmodule
module fpll_dprio_init (
input clk,
input reset_n,
input locked,
output [ 5:0] dprio_address,
output dprio_read,
output [ 1:0] dprio_byteen,
output dprio_write,
output [15:0] dprio_writedata,
output reg atpgmode,
output reg mdio_dis,
output reg scanen,
output reg ser_shift_load,
output reg dprio_init_done
);
reg [1:0] rst_n = 2'b00;
reg [6:0] count = 7'd0;
reg init_done_forever;
// Internal versions of control signals
wire int_mdio_dis;
wire int_ser_shift_load;
wire int_dprio_init_done;
wire int_atpgmode/*synthesis keep*/;
wire int_scanen/*synthesis keep*/;
assign dprio_address = count[6] ? 5'b0 : count[5:0] ;
assign dprio_byteen = 2'b11; // always enabled
assign dprio_write = ~count[6] & reset_n ; // write for first 64 cycles
assign dprio_read = 1'b0;
assign dprio_writedata = 16'd0;
assign int_ser_shift_load = count[6] ? |count[2:1] : 1'b1;
assign int_mdio_dis = count[6] ? ~count[2] : 1'b1;
assign int_dprio_init_done = ~init_done_forever ? (count[6] ? &count[2:0] : 1'b0)
: 1'b1;
assign int_atpgmode = 0;
assign int_scanen = 0;
initial begin
count = 7'd0;
init_done_forever = 0;
mdio_dis = 1'b1;
ser_shift_load = 1'b1;
dprio_init_done = 1'b0;
scanen = 1'b0;
atpgmode = 1'b0;
end
// reset synch.
always @(posedge clk or negedge reset_n)
if(!reset_n) rst_n <= 2'b00;
else rst_n <= {rst_n[0],1'b1};
// counter
always @(posedge clk)
begin
if (!rst_n[1])
init_done_forever <= 1'b0;
else
begin
if (count[6] && &count[1:0])
init_done_forever <= 1'b1;
end
end
always @(posedge clk or negedge rst_n[1])
begin
if(!rst_n[1])
begin
count <= 7'd0;
end
else if(~int_dprio_init_done)
begin
count <= count + 7'd1;
end
else
begin
count <= count;
end
end
// outputs
always @(posedge clk) begin
mdio_dis <= int_mdio_dis;
ser_shift_load <= int_ser_shift_load;
dprio_init_done <= int_dprio_init_done;
atpgmode <= int_atpgmode;
scanen <= int_scanen;
end
endmodule
module dyn_phase_shift
#(
parameter device_family = "Stratix V"
) (
input wire clk,
input wire reset,
input wire phase_done,
input wire pll_start_valid,
input wire dps_changed,
input wire dprio_write_done,
input wire [15:0] usr_num_shifts,
input wire [4:0] usr_cnt_sel,
input wire usr_up_dn,
input wire locked,
//output
output wire dps_done,
output reg phase_en,
output wire up_dn,
output wire dps_changed_valid,
output wire [4:0] cnt_sel);
reg first_phase_shift_d;
reg first_phase_shift_q;
reg [15:0] phase_en_counter;
reg [3:0] dps_current_state;
reg [3:0] dps_next_state;
localparam DPS_START = 4'd0, DPS_WAIT_PHASE_DONE = 4'd1, DPS_DONE = 4'd2, DPS_WAIT_PHASE_EN = 4'd3, DPS_WAIT_DPRIO_WRITING = 4'd4, DPS_CHANGED = 4'd5;
localparam PHASE_EN_WAIT_COUNTER = 5'd1;
reg [15:0] shifts_done_counter;
reg phase_done_final;
wire gnd /*synthesis keep*/;
//fsm
//always block controlling the state regs
always @(posedge clk)
begin
if (reset)
begin
dps_current_state <= DPS_DONE;
end
else
begin
dps_current_state <= dps_next_state;
end
end
//the combinational part. assigning the next state
//this turns on the phase_done_final signal when phase_done does this:
//_____ ______
// |______|
always @(*)
begin
phase_done_final = 0;
first_phase_shift_d = 0;
phase_en = 0;
dps_next_state = DPS_DONE;
case (dps_current_state)
DPS_START:
begin
phase_en = 1'b1;
dps_next_state = DPS_WAIT_PHASE_EN;
end
DPS_WAIT_PHASE_EN:
begin
phase_en = 1'b1;
if (first_phase_shift_q)
begin
first_phase_shift_d = 1'b1;
dps_next_state = DPS_WAIT_PHASE_EN;
end
else
begin
if (phase_en_counter == PHASE_EN_WAIT_COUNTER)
dps_next_state = DPS_WAIT_PHASE_DONE;
else dps_next_state = DPS_WAIT_PHASE_EN;
end
end
DPS_WAIT_PHASE_DONE:
begin
if (!phase_done | !locked)
begin
dps_next_state = DPS_WAIT_PHASE_DONE;
end
else
begin
if ((usr_num_shifts != shifts_done_counter) & (usr_num_shifts != 0))
begin
dps_next_state = DPS_START;
phase_done_final = 1'b1;
end
else
begin
dps_next_state = DPS_DONE;
end
end
end
DPS_DONE:
begin
phase_done_final = 0;
if (dps_changed)
dps_next_state = DPS_CHANGED;
else dps_next_state = DPS_DONE;
end
DPS_CHANGED:
begin
if (pll_start_valid)
dps_next_state = DPS_WAIT_DPRIO_WRITING;
else
dps_next_state = DPS_CHANGED;
end
DPS_WAIT_DPRIO_WRITING:
begin
if (dprio_write_done)
dps_next_state = DPS_START;
else
dps_next_state = DPS_WAIT_DPRIO_WRITING;
end
default: dps_next_state = 4'bxxxx;
endcase
end
always @(posedge clk)
begin
if (dps_current_state == DPS_WAIT_PHASE_DONE)
phase_en_counter <= 0;
else if (dps_current_state == DPS_WAIT_PHASE_EN)
phase_en_counter <= phase_en_counter + 1'b1;
if (reset)
begin
phase_en_counter <= 0;
shifts_done_counter <= 1'b1;
first_phase_shift_q <= 1;
end
else
begin
if (first_phase_shift_d)
first_phase_shift_q <= 0;
if (dps_done)
begin
shifts_done_counter <= 1'b1;
end
else
begin
if (phase_done_final & (dps_next_state!= DPS_DONE))
shifts_done_counter <= shifts_done_counter + 1'b1;
else
shifts_done_counter <= shifts_done_counter;
end
end
end
assign dps_changed_valid = (dps_current_state == DPS_CHANGED);
assign dps_done =(dps_current_state == DPS_DONE) | (dps_current_state == DPS_CHANGED);
assign up_dn = usr_up_dn;
assign gnd = 1'b0;
//cnt select luts (5)
generic_lcell_comb lcell_cnt_sel_0 (
.dataa(usr_cnt_sel[0]),
.datab(usr_cnt_sel[1]),
.datac(usr_cnt_sel[2]),
.datad(usr_cnt_sel[3]),
.datae(usr_cnt_sel[4]),
.dataf(gnd),
.combout (cnt_sel[0]));
defparam lcell_cnt_sel_0.lut_mask = 64'hAAAAAAAAAAAAAAAA;
defparam lcell_cnt_sel_0.dont_touch = "on";
defparam lcell_cnt_sel_0.family = device_family;
generic_lcell_comb lcell_cnt_sel_1 (
.dataa(usr_cnt_sel[0]),
.datab(usr_cnt_sel[1]),
.datac(usr_cnt_sel[2]),
.datad(usr_cnt_sel[3]),
.datae(usr_cnt_sel[4]),
.dataf(gnd),
.combout (cnt_sel[1]));
defparam lcell_cnt_sel_1.lut_mask = 64'hCCCCCCCCCCCCCCCC;
defparam lcell_cnt_sel_1.dont_touch = "on";
defparam lcell_cnt_sel_1.family = device_family;
generic_lcell_comb lcell_cnt_sel_2 (
.dataa(usr_cnt_sel[0]),
.datab(usr_cnt_sel[1]),
.datac(usr_cnt_sel[2]),
.datad(usr_cnt_sel[3]),
.datae(usr_cnt_sel[4]),
.dataf(gnd),
.combout (cnt_sel[2]));
defparam lcell_cnt_sel_2.lut_mask = 64'hF0F0F0F0F0F0F0F0;
defparam lcell_cnt_sel_2.dont_touch = "on";
defparam lcell_cnt_sel_2.family = device_family;
generic_lcell_comb lcell_cnt_sel_3 (
.dataa(usr_cnt_sel[0]),
.datab(usr_cnt_sel[1]),
.datac(usr_cnt_sel[2]),
.datad(usr_cnt_sel[3]),
.datae(usr_cnt_sel[4]),
.dataf(gnd),
.combout (cnt_sel[3]));
defparam lcell_cnt_sel_3.lut_mask = 64'hFF00FF00FF00FF00;
defparam lcell_cnt_sel_3.dont_touch = "on";
defparam lcell_cnt_sel_3.family = device_family;
generic_lcell_comb lcell_cnt_sel_4 (
.dataa(usr_cnt_sel[0]),
.datab(usr_cnt_sel[1]),
.datac(usr_cnt_sel[2]),
.datad(usr_cnt_sel[3]),
.datae(usr_cnt_sel[4]),
.dataf(gnd),
.combout (cnt_sel[4]));
defparam lcell_cnt_sel_4.lut_mask = 64'hFFFF0000FFFF0000;
defparam lcell_cnt_sel_4.dont_touch = "on";
defparam lcell_cnt_sel_4.family = device_family;
endmodule
module generic_lcell_comb
#(
//parameter
parameter family = "Stratix V",
parameter lut_mask = 64'hAAAAAAAAAAAAAAAA,
parameter dont_touch = "on"
) (
input dataa,
input datab,
input datac,
input datad,
input datae,
input dataf,
output combout
);
generate
if (family == "Stratix V")
begin
stratixv_lcell_comb lcell_inst (
.dataa(dataa),
.datab(datab),
.datac(datac),
.datad(datad),
.datae(datae),
.dataf(dataf),
.combout (combout));
defparam lcell_inst.lut_mask = lut_mask;
defparam lcell_inst.dont_touch = dont_touch;
end
else if (family == "Arria V")
begin
arriav_lcell_comb lcell_inst (
.dataa(dataa),
.datab(datab),
.datac(datac),
.datad(datad),
.datae(datae),
.dataf(dataf),
.combout (combout));
defparam lcell_inst.lut_mask = lut_mask;
defparam lcell_inst.dont_touch = dont_touch;
end
else if (family == "Arria V GZ")
begin
arriavgz_lcell_comb lcell_inst (
.dataa(dataa),
.datab(datab),
.datac(datac),
.datad(datad),
.datae(datae),
.dataf(dataf),
.combout (combout));
defparam lcell_inst.lut_mask = lut_mask;
defparam lcell_inst.dont_touch = dont_touch;
end
else if (family == "Cyclone V")
begin
cyclonev_lcell_comb lcell_inst (
.dataa(dataa),
.datab(datab),
.datac(datac),
.datad(datad),
.datae(datae),
.dataf(dataf),
.combout (combout));
defparam lcell_inst.lut_mask = lut_mask;
defparam lcell_inst.dont_touch = dont_touch;
end
endgenerate
endmodule