General Queries on PLL usage with ECP5

Kia ora,

I was wondering if anyone has used PLLs with yosys? I am in the middle of working on a SDRAM controller for the ULX3S, but the memory requires a 165Mhz clock and the onboard clock is 25Mhz.

I understand the ECP5 has onboard PLLs but I do not know how to interact with them. Any advice would be much appreciated, also if you could keep in mind that I am new to PLLs as well with any explanations that would be really appreciated :slight_smile:

I did see the following article but the disclaimer scared me off a little Configuring the Lattice ECP5 PLL ยท blog.dave.tf

Best,
Finlay

Iโ€™m unsure how I am meant to use the lock value produced by the ecppll file. Is there any working examples?

I assume I must get the value from a posedge/negedge on locked.

Solved. Need to create a lock_sync like so:

// diamond 3.7 accepts this PLL
// diamond 3.8-3.9 is untested
// diamond 3.10 or higher is likely to abort with error about unable to use feedback signal
// cause of this could be from wrong CPHASE/FPHASE parameters
module pll_165
(
    input reset, // 0:inactive, 1:reset
    input clkin, // 25 MHz, 0 deg
    output clkout0, // 50 MHz, 0 deg
    output reg clklocked
);

wire locked;
(* FREQUENCY_PIN_CLKI="25" *)
(* FREQUENCY_PIN_CLKOP="165" *)
(* ICP_CURRENT="12" *) (* LPF_RESISTOR="8" *) (* MFG_ENABLE_FILTEROPAMP="1" *) (* MFG_GMCREF_SEL="2" *)
EHXPLLL #(
        .PLLRST_ENA("ENABLED"),
        .INTFB_WAKE("DISABLED"),
        .STDBY_ENABLE("DISABLED"),
        .DPHASE_SOURCE("DISABLED"),
        .OUTDIVIDER_MUXA("DIVA"),
        .OUTDIVIDER_MUXB("DIVB"),
        .OUTDIVIDER_MUXC("DIVC"),
        .OUTDIVIDER_MUXD("DIVD"),
        .CLKI_DIV(5),
        .CLKOP_ENABLE("ENABLED"),
        .CLKOP_DIV(4),
        .CLKOP_CPHASE(2),
        .CLKOP_FPHASE(0),
        .FEEDBK_PATH("CLKOP"),
        .CLKFB_DIV(33)
    ) pll_i (
        .RST(reset),
        .STDBY(1'b0),
        .CLKI(clkin),
        .CLKOP(clkout0),
        .CLKFB(clkout0),
        .CLKINTFB(),
        .PHASESEL0(1'b0),
        .PHASESEL1(1'b0),
        .PHASEDIR(1'b1),
        .PHASESTEP(1'b1),
        .PHASELOADREG(1'b1),
        .PLLWAKESYNC(1'b0),
        .ENCLKOP(1'b0),
        .LOCK(locked)
	);

    reg locked_sync;
    always @(posedge clkout0) begin
        locked_sync <= locked; 
        clklocked <= locked_sync;
    end
endmodule

Project F guide helped a lot for working with the PLLs: ECP5 FPGA Clock Generation - Project F

1 Like