// Integration layer for an APB to PLL interface module snps_PLL_integration_layer #( parameter DEFAULT_DIVVCOP=4'h0, parameter DEFAULT_DIVVCOR=4'h0, parameter DEFAULT_FBDIV=7'h10, parameter DEFAULT_P = 6'h03, parameter DEFAULT_R = 6'h01, parameter DEFAULT_PREDIV = 5'h00 )( `ifdef POWER_PINS inout wire agnd, inout wire avdd, inout wire avddhv, inout wire dgnd, inout wire dvdd, inout wire vp_vref, `endif input wire ref_clk, input wire resetn, output wire pll_lock, output wire out_clk1, output wire out_clk2, input wire PSELx, input wire [9:0] PADDR, input wire PENABLE, input wire [2:0] PPROT, input wire [3:0] PSTRB, input wire PWRITE, input wire [31:0] PWDATA, output wire [31:0] PRDATA, output wire PREADY, output wire PSLVERR ); // Control register // Bypass ---------------------------------------------------------------------------------| // Enable P -----------------------------------------------------------------------| | // Enable R ---------------------------------------------------------------------| | | // Gear Shift ---------------------------------------------------------------| | | | // bit 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // reg bypass_reg; reg enp_reg; reg enr_reg; reg gear_shift_reg; reg [15:0] gear_shift_counter; reg [15:0] enable_counter; reg [3:0] divvcop_reg; reg [3:0] divvcor_reg; reg [6:0] fbdiv_reg; reg [5:0] p_reg; reg [5:0] r_reg; reg [4:0] prediv_reg; reg pwron_reg; reg pll_rst; reg pll_lock_reg; reg [4:0] PLL_test_addr; reg PLL_test_wr_en; reg PLL_test_rd_en; reg [2:0] APB_PLL_counter; reg PLL_read_write_done; reg [7:0] PLL_data_i; wire [7:0] PLL_data_o; // APB interface localparam APB_IDLE = 3'd0, APB_WRITE = 3'd1, APB_READ = 3'd2, APB_WRITE_PLL = 3'd3, APB_READ_PLL = 3'd4; reg [2:0] apb_current_state; reg [2:0] apb_next_state; reg PSLVERR_reg; reg [31:0] PRDATA_reg; assign PRDATA = PRDATA_reg; assign PSLVERR = PSLVERR_reg; always @(posedge ref_clk or negedge resetn) begin if(~resetn) begin apb_current_state <= APB_IDLE; APB_PLL_counter <= 3'h0; end else begin apb_current_state <= apb_next_state; if(apb_current_state == APB_WRITE_PLL || apb_current_state == APB_READ_PLL) begin APB_PLL_counter <= APB_PLL_counter + 3'h1; end else begin APB_PLL_counter <= 3'h0; end end end always @(posedge ref_clk or negedge resetn) begin if(~resetn) begin gear_shift_counter = 16'h0000; enable_counter = 16'h0000; end else begin if((gear_shift_reg == 1'b1)&&(pll_rst==1'b1)) begin gear_shift_counter = gear_shift_counter+1; if (gear_shift_counter>16'h3E88) begin gear_shift_counter = 16'h0000; end end else begin if(((enp_reg==1'b0)||(enr_reg==1'b0))&&(pll_rst==1'b1)) begin enable_counter = enable_counter+1; if(enable_counter>16'h2718) begin enable_counter = 16'h0000; end end end end end always @(*) begin if(~resetn) begin bypass_reg = 1'b0; enp_reg = 1'b0; enr_reg = 1'b0; gear_shift_reg = 1'b0; pll_lock_reg = 1'b0; pwron_reg = 1'b0; pll_rst = 1'b0; // Default startup of PLL // F_vco = 100*20/1 = 1.6 GHz // F_vco = F_ref * fbdiv/prediv // F_clkoutp = 400 MHz // F_clkoutr = 800 MHz divvcop_reg = DEFAULT_DIVVCOP; // Divvco = 1 divvcor_reg = DEFAULT_DIVVCOR; // Divvco = 1 fbdiv_reg = DEFAULT_FBDIV; // Feeback = 16 p_reg = DEFAULT_P; // p = 4 r_reg = DEFAULT_R; // r=2 prediv_reg = DEFAULT_PREDIV; // prediv=1 PSLVERR_reg = 1'b0; PLL_read_write_done = 1'b0; PLL_test_wr_en = 1'b0; PLL_test_rd_en = 1'b0; end else begin if((gear_shift_reg == 1'b1)) begin if (gear_shift_counter>16'h3E80) begin gear_shift_reg = 1'b0; end end else begin if((enp_reg==1'b0)||(enr_reg==1'b0)) begin if(enable_counter>16'h2710) begin enp_reg = 1'b1; enr_reg = 1'b1; end end end if((enp_reg==1'b1)||(enr_reg==1'b1)) begin pll_lock_reg = pll_lock; end case(apb_current_state) APB_IDLE: begin PSLVERR_reg = 1'b0; PLL_read_write_done = 1'b0; PLL_test_wr_en = 1'b0; PLL_test_rd_en = 1'b0; if(PSELx) begin if(PWRITE) begin if(PADDR[9]) apb_next_state = APB_WRITE_PLL; else apb_next_state = APB_WRITE; end else begin if(PADDR[9]) apb_next_state = APB_READ_PLL; else apb_next_state = APB_READ; end end else begin apb_next_state = APB_IDLE; end end APB_WRITE: begin case(PADDR) 10'h000: begin if(PSTRB[0]==1'b1) begin bypass_reg = PWDATA[0]; enp_reg = PWDATA[4]; enr_reg = PWDATA[5]; gear_shift_reg = PWDATA[7]; end if(PSTRB[1]==1'b1) begin pwron_reg = PWDATA[8]; pll_rst = PWDATA[9]; end end 10'h001: begin if(PSTRB[0]==1'b1) begin gear_shift_counter[7:0] = PWDATA[7:0]; end if(PSTRB[1]==1'b1) begin gear_shift_counter[15:8] = PWDATA[15:8]; end end 10'h002: begin if(PSTRB[0]==1'b1) begin enable_counter[7:0] = PWDATA[7:0]; end if(PSTRB[1]==1'b1) begin enable_counter[15:8] = PWDATA[15:8]; end end 10'h003: begin if(PSTRB[0]==1'b1) r_reg = PWDATA[5:0]; if(PSTRB[1]==1'b1) divvcor_reg = PWDATA[11:8]; if(PSTRB[2]==1'b1) p_reg = PWDATA[21:16]; if(PSTRB[3]==1'b1) divvcop_reg = PWDATA[27:24]; end 10'h004: begin if(PSTRB[0]==1'b1) fbdiv_reg = PWDATA[6:0]; if(PSTRB[1]==1'b1) prediv_reg = PWDATA[12:8]; end endcase apb_next_state = APB_IDLE; end APB_READ: begin case(PADDR) 10'h000: PRDATA_reg = {{22{1'b0}}, pll_rst, pwron_reg, gear_shift_reg, 1'b0, enr_reg, enp_reg, {3{1'b0}}, bypass_reg}; 10'h001: PRDATA_reg = {{20{1'b0}}, gear_shift_counter}; 10'h002: PRDATA_reg = {{20{1'b0}}, enable_counter}; 10'h003: PRDATA_reg = {{4{1'b0}}, divvcop_reg, {2{1'b0}}, p_reg, {4{1'b0}}, divvcor_reg, {2{1'b0}}, r_reg}; 10'h004: PRDATA_reg = {{19{1'b0}}, prediv_reg, {1{1'b0}}, fbdiv_reg}; 10'h005: PRDATA_reg = 32'h534E504C; 10'h006: PRDATA_reg = {{31{1'b0}},pll_lock_reg}; endcase apb_next_state = APB_IDLE; end APB_WRITE_PLL: begin case(PADDR) 10'h200: PLL_test_addr = 5'h00; 10'h201: PLL_test_addr = 5'h01; 10'h202: PLL_test_addr = 5'h02; 10'h203: PLL_test_addr = 5'h03; 10'h204: PLL_test_addr = 5'h04; 10'h205: PLL_test_addr = 5'h10; 10'h206: PLL_test_addr = 5'h11; 10'h207: PLL_test_addr = 5'h12; 10'h208: PLL_test_addr = 5'h13; 10'h209: PLL_test_addr = 5'h14; 10'h20A: PLL_test_addr = 5'h15; 10'h20B: PLL_test_addr = 5'h16; 10'h20C: PLL_test_addr = 5'h17; endcase PLL_test_wr_en = 1'b1; PLL_data_i <= PWDATA[7:0]; if(APB_PLL_counter > 3'h2) begin PLL_read_write_done = 1'b1; end if(PLL_read_write_done) begin apb_next_state = APB_IDLE; end else begin apb_next_state = APB_WRITE_PLL; end end APB_READ_PLL: begin case(PADDR) 10'h200: PLL_test_addr = 5'h00; 10'h201: PLL_test_addr = 5'h01; 10'h202: PLL_test_addr = 5'h02; 10'h203: PLL_test_addr = 5'h03; 10'h204: PLL_test_addr = 5'h04; 10'h205: PLL_test_addr = 5'h10; 10'h206: PLL_test_addr = 5'h11; 10'h207: PLL_test_addr = 5'h12; 10'h208: PLL_test_addr = 5'h13; 10'h209: PLL_test_addr = 5'h14; 10'h20A: PLL_test_addr = 5'h15; 10'h20B: PLL_test_addr = 5'h16; 10'h20C: PLL_test_addr = 5'h17; endcase PLL_test_rd_en = 1'b1; if(APB_PLL_counter > 3'h2) begin PLL_read_write_done = 1'b1; PRDATA_reg = {{24{1'b0}}, PLL_data_o}; end if(PLL_read_write_done) begin apb_next_state = APB_IDLE; end else begin apb_next_state = APB_READ_PLL; end end default: apb_next_state = APB_IDLE; endcase end end assign PREADY = ((apb_current_state==APB_READ|apb_current_state==APB_WRITE|PLL_read_write_done==1'b1))? 1'b1:1'b0; dwc_z19606ts_ns u_snps_PLL( `ifdef BEHAVIOURAL_SIM // .agnd(64'd0), // Analog and digital clean ground // .avdd(64'h3FECCCCCCCCCCCCD), // Analog clean 0.9V supply // .avddhv(64'h3FFCCCCCCCCCCCCD), // Dedicated analog 1.8V supply // .dgnd(64'd0), // Digital ground // .dvdd(64'h3FECCCCCCCCCCCCD), // Digital 0.9V supply .vp_vref(64'h3FECCCCCCCCCCCCD), // Input reference voltage (similar to AVDD) `else // .agnd(agnd), // .avdd(avdd), // .avddhv(avddhv), // .dgnd(dgnd), // .dvdd(dvdd), .vp_vref(vp_vref), `endif // Clock Signals .ref_clk(ref_clk), // Input reference clock signal .clkoutp(out_clk1), .clkoutr(out_clk2), .bypass(bypass_reg), //PLL Bypass mode (0: clk_out = PLL output 1:clk_out = ref_clk/(p/r)) .divvcop(divvcop_reg), //Output divider for clock P (3:0) .divvcor(divvcor_reg), //Output divider for clock R (3:0) .enp(enp_reg), // Enable output clock P (1: clk_out = PLL output 0: clk_out = 0 or ref_clock/p) .enr(enr_reg), // Enable output clock R (1: clk_out = PLL output 0: clk_out = 0 or ref_clock/r) .fbdiv(fbdiv_reg), // Feedback multiplication facor (7 bits 8-131) .lock(pll_lock), // PLL Lock State .gear_shift(gear_shift_reg), // Locking control, set high for faster PLL locking at cost of phase margin and jitter .p(p_reg), // Post divider division factor P (1-64) .prediv(prediv_reg), // input frequency division factor (1-32) .pwron(pwron_reg), // Power on control .r(r_reg), // Post divider division factor R (1-64) .rst(~pll_rst), // Reset signal (set high for 4us whenever PWRON goes high) .vregp(), // Output voltage regulator for P clock .vregr(), // Output voltage regulator for R clock // Test Signals .test_data_i(PLL_data_i), //Data bus input control registers (7:0) .test_rd_en(PLL_test_rd_en), // Control register read enable .test_rst(~pll_rst), // Control register reset signal .test_sel(PLL_test_addr), // Select lines for control register (4:0) .test_wr_en(PLL_test_wr_en), // Control register write enable .test_data_o(PLL_data_o), //Data bus output control registers (7:0) .atb_f_m(), //Signal for sinking or sourcing currents to/from PLL (for internal debug) .atb_s_m(), // Signal for sensing voltages internal to PLL (for internal debug) .atb_s_p() // Signal for sensing voltages internal to PLL (for internal debug) ); endmodule