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 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hdl/top.sv | 20 ++++++--- 2 files changed, 154 insertions(+), 6 deletions(-) create mode 100644 hdl/clock.sv (limited to 'hdl') 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 diff --git a/hdl/top.sv b/hdl/top.sv index 8d83f35..46620cb 100644 --- a/hdl/top.sv +++ b/hdl/top.sv @@ -4,14 +4,22 @@ module top #( ADDR_BITS = 14 , DATA_BITS = 12 ) - ( input bit clk // verilator public - , input bit reset_n // verilator public + ( input bit native_clk // verilator public + , input bit reset_n // verilator public ); -bit reset = 0; -bit have_reset = 0; -always_ff @(posedge clk) if (reset) have_reset <= 1; -assign reset = !reset_n || !have_reset; +bit clk; +bit reset; + +clock + #( .DIVIDE_BY(10) + , .MULTIPLY_BY(9) + ) pll + ( .native_clk(native_clk) + , .reset_n(reset_n) + , .target_clk(clk) + , .reset(reset) + ); bit mem_ready; bit mem_valid; -- cgit v1.2.3