From 3975a7e26d0ad8c7f33e28e1222d1e09f7bcdb82 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Wed, 14 Apr 2021 08:44:31 -0700 Subject: Use internal PLL for clock and reset generation. --- hdl/clock.sv | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 hdl/clock.sv (limited to 'hdl/clock.sv') diff --git a/hdl/clock.sv b/hdl/clock.sv new file mode 100644 index 0000000..b33645b --- /dev/null +++ b/hdl/clock.sv @@ -0,0 +1,140 @@ +`include "util.svh" + +module clock + #( DIVIDE_BY = 1 + , MULTIPLY_BY = 1 + , NATIVE_PERIOD_PICOSECONDS = 20_000 + ) + ( input bit native_clk + , input bit reset_n + + , output bit target_clk + , output bit reset + ); + +enum + { AWAIT_LOCKED + , AWAIT_LOW + , AWAIT_HIGH + , AWAIT_LOW_2 + , READY + } state = state.first; + +bit locked; + +`ifdef SYNTHESIS + +altpll + #( .bandwidth_type("AUTO") + , .clk0_divide_by(DIVIDE_BY) + , .clk0_duty_cycle(50) + , .clk0_multiply_by(MULTIPLY_BY) + , .clk0_phase_shift(0) + , .compensate_clock("CLK0") + , .inclk0_input_frequency(NATIVE_PERIOD_PICOSECONDS) + , .intended_device_family("Cyclone 10 LP") + , .lpm_hint("CBX_MODULE_PREFIX=clock") + , .lpm_type("altpll") + , .operation_mode("NORMAL") + , .pll_type("AUTO") + , .port_activeclock("PORT_UNUSED") + , .port_areset("PORT_USED") + , .port_clkbad0("PORT_UNUSED") + , .port_clkbad1("PORT_UNUSED") + , .port_clkloss("PORT_UNUSED") + , .port_clkswitch("PORT_UNUSED") + , .port_configupdate("PORT_UNUSED") + , .port_fbin("PORT_UNUSED") + , .port_inclk0("PORT_USED") + , .port_inclk1("PORT_UNUSED") + , .port_locked("PORT_USED") + , .port_pfdena("PORT_UNUSED") + , .port_phasecounterselect("PORT_UNUSED") + , .port_phasedone("PORT_UNUSED") + , .port_phasestep("PORT_UNUSED") + , .port_phaseupdown("PORT_UNUSED") + , .port_pllena("PORT_UNUSED") + , .port_scanaclr("PORT_UNUSED") + , .port_scanclk("PORT_UNUSED") + , .port_scanclkena("PORT_UNUSED") + , .port_scandata("PORT_UNUSED") + , .port_scandataout("PORT_UNUSED") + , .port_scandone("PORT_UNUSED") + , .port_scanread("PORT_UNUSED") + , .port_scanwrite("PORT_UNUSED") + , .port_clk0("PORT_USED") + , .port_clk1("PORT_UNUSED") + , .port_clk2("PORT_UNUSED") + , .port_clk3("PORT_UNUSED") + , .port_clk4("PORT_UNUSED") + , .port_clk5("PORT_UNUSED") + , .port_clkena0("PORT_UNUSED") + , .port_clkena1("PORT_UNUSED") + , .port_clkena2("PORT_UNUSED") + , .port_clkena3("PORT_UNUSED") + , .port_clkena4("PORT_UNUSED") + , .port_clkena5("PORT_UNUSED") + , .port_extclk0("PORT_UNUSED") + , .port_extclk1("PORT_UNUSED") + , .port_extclk2("PORT_UNUSED") + , .port_extclk3("PORT_UNUSED") + , .self_reset_on_loss_lock("ON") + , .width_clock(5) + ) pll + ( .areset(!reset_n) + , .inclk(native_clk) + , .clk(target_clk) + , .locked(locked) + , .activeclock() + , .clkbad() + , .clkena({6{1'b1}}) + , .clkloss() + , .clkswitch(1'b0) + , .configupdate(1'b0) + , .extclkena({4{1'b1}}) + , .fbin(1'b1) + , .fbmimicbidir() + , .fbout() + , .fref() + , .icdrclk() + , .pfdena(1'b1) + , .phasecounterselect({4{1'b1}}) + , .phasedone() + , .phasestep(1'b1) + , .phaseupdown(1'b1) + , .pllena(1'b1) + , .scanaclr(1'b0) + , .scanclk(1'b0) + , .scanclkena(1'b1) + , .scandata(1'b0) + , .scandataout() + , .scandone() + , .scanread(1'b0) + , .scanwrite(1'b0) + , .sclkout0() + , .sclkout1() + , .vcooverrange() + , .vcounderrange() + ); + +`endif + +always_latch begin + `ifndef SYNTHESIS + target_clk = native_clk; + locked = 1; + `endif + + if (!reset_n || !locked) state = AWAIT_LOCKED; + + case (state) + AWAIT_LOCKED: if (locked) state = AWAIT_LOW; + AWAIT_LOW: if (!target_clk) state = AWAIT_HIGH; + AWAIT_HIGH: if (target_clk) state = AWAIT_LOW_2; + AWAIT_LOW_2: if (!target_clk) state = READY; + endcase + + reset = !(state == READY); +end + +endmodule -- cgit v1.2.3